Up

スレッドの配列と並行実行

 

Visual C++2008/CLRにおいてマルチ・コアPCの能力を活用するためにはスレッドによる処理の並行実行が考えられる。ホームページ

http://homepage2.nifty.com/okamotoy/cppsamples/multithreads/

には、スレッドによる処理効率の向上を示すプログラム例を用意した。

上記ホームページでは、スレッドは個別の変数によって表わされている。

多くのスレッドを使用するときは、スレッドの配列を用意するとプログラミング作業が簡単になる。

以下に、プログラム例を示す。ソースコードを含むファイルはこのページの最後に用意した。

まず、並行処理を行うアルゴリズムとその対象および環境を1つのref classとしてまとめる。

本ページのサンプルプログラムは、上記のスレッドによる処理効率の向上を示すサンプル・プログラムを基に用意したので、以下のようになっている。

typedef double * aryDouble;

 

      public ref class myThreads{

              public:

                      aryDouble z;

                      int N;

                      myrn * rn;  //   myrnは乱数生成用クラス型。rnkissM.hに用意されている。

 

                      myThreads(){}

                      virtual ~myThreads(){}

 

                      void set( aryDouble pz, int vN, myrn * prn ){

                              z = pz;

                              N = vN;

                              rn = prn;

                      }

 

                      void Calc(){

                              for (int i = 0; i < N; i++)

                                      z[i] = rn->normal();

                      }

 

      };

 

上記myThreads型のインスタンスを配列として複数個(ここでは10個)用意する

 

                              array<myThreads ^> ^ MyThread;

                              MyThread = gcnew array<myThreads ^>(10);

                              for (int i = 0; i < 10; i++){

                                      MyThread[i] = gcnew myThreads();

                                      MyThread[i]->set( x2[i], N, &(rn21[i]) );

                              }

 

myThreads型のインスタンスに対してそのメソッドCalc()をスレッドとして実行するためのデリゲートを用意する。

 

                          array<ThreadStart ^> ^ myDelegate;

                          myDelegate = gcnew array<ThreadStart ^>(10);

                          for (int i = 0; i < 10; i++)

                                  myDelegate[i] = gcnew ThreadStart( MyThread[i], &myThreads::Calc );

 

次に、デリゲートに対するスレッドを用意する。

 

                         array<Thread ^ > ^ runThread;

                         runThread = gcnew array<Thread ^>(10);

                         for (int i = 0; i < 10; i++)

                                 runThread[i] = gcnew Thread( myDelegate[i] );

 

用意した10個のスレッドの実行

 

                               for (int i = 0; i < 10; i++)

                               runThread[i]->Start();

 

サンプルプログラムは上記のような感じでスレッドによる処理の並行実行が行われている。

乱数はマルチ・スレッド対応で

                                myrn * rn21;

                                rn21 = new myrn[10];

                                for (int i = 0; i < 10; i++)

                                        rn21[i].Init( 10, i );

と乱数生成用クラス型myrnのインスタンスを生成した後、初期化メソッドをInit( ic, ib )と呼び出すと、

乱数は基礎となる乱数生成において初期の一様乱数の出発点をibとし、以後周期icごとの一様乱数が呼び出される。

したがって、上記の10本のスレッドを走らせている例においては、i=0から9までの異なる出発点に対して

一様乱数は10個目ごとに呼び出されるので、各スレッドの乱数は独立となる。

詳しくはサンプルプログラムを参照されたい。

サンプルプログラムのソースファイルなどをまとめたZIPファイルは、ここを右ボタンでクリックするとダウンロードできる。

ダウンロードしたファイルは、解凍するとVisual C++2008で開くことができる。

 

Up