parallel_for を使用するアプリケーションの作成

このセクションでは、部分文字列一致プログラムで parallel_for テンプレートを使用する基本的な例を説明します。文字列の各位置で、プログラムは文字列のほかの部分と一致する最も大きな部分文字列の長さと位置を表示します。

例として、文字列 babba を考えてみます。位置 0 で開始すると、文字列で一致する最大の部分文字列は位置 3 の ba です。

インテル® TBB の examples/GettingStarted フォルダーに含まれているこのプログラムの完全バージョンを参照するか、あるいは、次の説明に従ってアプリケーションを作成してみてください。このセクションでは、各ステップに追加するコードを bold font で表示しています。行番号は、最終的なサンプルの行番号を示しています。

サンプルコードの作成手順:

  1. 新しい空のアプリケーションを作成します。
  2. using 文は、ライブラリーのすべてのクラスと関数が含まれる namespace tbb をインポートします (行 07)。
    07:    using namespace tbb;
    
    36:    int main() {
    50:      return 0;
    51:    }
  3. プログラムによって変換されるサンプル文字列を作成します (行 38 - 40)。次に、一致する最大の部分文字列の長さと場所を格納する配列を作成します (行 42 - 43)。サンプルは、a および b 文字のフィボナッチ文字列を生成します。
  4. 各位置の一致する最大の部分文字列の長さと場所を出力する文を追加します (行 46 - 47)。
    01:    #include <iostream>
    02:    #include <string>    
    
    07:    using namespace tbb;
    08:    using namespace std;
    09:    static const size_t N = 23;
    
    36:    int main() {
    
    38:      string str[N] = { string("a"), string("b") };
    39:      for (size_t i = 2; i < N; ++i) str[i] = str[i-1]+str[i-2];
    40:      string &to_scan = str[N-1]; 
    41:      size_t num_elem = to_scan.size();
    
    42:      size_t *max = new size_t[num_elem];
    43:      size_t *pos = new size_t[num_elem];
    
    44—45:      // add code to populate max and pos here
    
    46:      for (size_t i = 0; i < num_elem; ++i)
    47:        cout << " " << max[i] << "(" << pos[i] << ")" << endl;
    48:      delete[] pos;
    49:      delete[] max;
    50:      return 0;
    51:    }
  5. parallel_for テンプレート関数の呼び出しを追加します (行 44 - 45)。

    呼び出しの第 1 引数は、反復空間を示す blocked_range オブジェクトです。

    blocked_range は、インテル® TBB ライブラリーによって提供されるテンプレート・クラスです。コンストラクターの引数は、次のようになります。

    • 範囲の下限。
    • 範囲の上限。

    parallel_for 関数の第 2 引数は、各サブ範囲に適用する関数オブジェクトです。

    01:    #include <iostream>
    02:    #include <string>                        
    05:    #include "tbb/parallel_for.h"
    06:    #include "tbb/blocked_range.h"
    
    07:    using namespace tbb;
    08:    using namespace std;
    09:    static const size_t N = 23;
    
    36:    int main() {
    
    38:      string str[N] = { string("a"), string("b") };
    39:      for (size_t i = 2; i < N; ++i) str[i] = str[i-1]+str[i-2];
    40:      string &to_scan = str[N-1]; 
    
    41:      size_t num_elem = to_scan.size();
    
    42:      size_t *max = new size_t[num_elem];
    43:      size_t *pos = new size_t[num_elem];
    
    44:      parallel_for(blocked_range<size_t>(0, num_elem ),
    45:                   SubStringFinder( to_scan, max, pos ) );         
    
    46:      for (size_t i = 0; i < num_elem; ++i)
    47:        cout << " " << max[i] << "(" << pos[i] << ")" << endl;
    48:      delete[] pos;
    49:      delete[] max;
    50:      return 0;
    51:    }
  6. parallel_for ループのボディーを実装します (行 10 - 35)。

    ランタイムに、parallel_for テンプレートは範囲を複数のサブ範囲に分割して、各サブ範囲で SubStringFinder 関数オブジェクトを呼び出します。

  7. 指定されたサブ範囲内で見つかった max および pos 配列要素を格納する SubStringFinder クラスを定義します (行 10)。

    行 16 の r.begin() はサブ範囲の開始位置を、r.end() はサブ範囲の終了位置を返します。

    01:    #include <iostream>
    02:    #include <string>                        
    03:    #include <algorithm>
    04:    #include "tbb/parallel_for.h"
    05:    #include "tbb/blocked_range.h"
    
    07:    using namespace tbb;
    08:    using namespace std;
    09:    static const size_t N = 23;
    
    10:    class SubStringFinder {    
    11:      const string str;    
    12:      size_t *max_array;
    13:      size_t *pos_array;
    14:    public: 
    15:      void operator() ( const blocked_range<size_t>& r ) const { 
    16:        for ( size_t i = r.begin(); i != r.end(); ++i ) {
    17:          size_t max_size = 0, max_pos = 0;
    18:          for (size_t j = 0; j < str.size(); ++j)
    19:          if (j != i) {    
    20:            size_t limit = str.size()-max(i,j);
    21:            for (size_t k = 0; k < limit; ++k) {
    22:              if (str[i + k] != str[j + k]) break;
    23:              if (k > max_size) {
    24:                max_size = k;
    25:                max_pos = j;
    26:              }
    27:            }
    28:         }
    29:          max_array[i] = max_size;
    30:          pos_array[i] = max_pos;
    31:        }
    32:      }
    33:      SubStringFinder(string &s, size_t *m, size_t *p) :
    34:        str(s), max_array(m), pos_array(p) { }
    35:    };
    
    36—51:    // The function main starting at line 36 goes here