さて、並列処理を実装する方法として、TBBのほかにも前述のようにマルチスレッドやOpenMPといった方法がある。これらと比較してTBBのメリットはどこにあるのだろうか。
まずマルチスレッドによる実装との比較であるが、TBBでは「複数のスレッドを作成し、適切なデータに対して適切な処理を割り当てる」という処理が、テンプレート関数という形であらかじめ用意されている。そのため、データとロジックのみを用意するだけで、面倒なスレッドの生成やデータの分割といった部分を気にせずに並列処理を実装できる。
一方OpenMPでは、for/whileループの並列処理やブロックごとの並列処理といった、スレッドの生成に関わる部分については面倒を見なくてもよいものの、データの分割については基本的には自前で処理しなければならない。また、OpenMPは並列処理すべき個所にプラグマを記述していく実装スタイルであるため、ソースコードの視認性や保守性が悪くなりやすいという問題もある。TBBはテンプレートクラスライブラリという形で実装されているため、並列処理をカプセル化しやすく、保守性/再利用性の高いコードを記述できる。
先に述べたように、TBBでは実行する処理と処理すべきデータを用意し、使用するアルゴリズムに対応するテンプレート関数にそれらを渡すというスタイルで並列処理を実装していく。以下では、典型的な並列処理を例に、TBBでの実装方法を紹介していこう。
なお、本記事ではテスト環境として、CPUにCore i7 920(2.66GHz)、3GBのメモリを搭載したPCを使用した。OSはWindows Vista Home Premiumで、開発環境にはVisual Studio 2009 SP2およびParallel Studioを使用している。また、コンパイルオプションについてはデフォルトの設定(最適化オプションは「/O2」のみ)を使用している。
TBBを利用する際には、使用するコンポーネントに応じたヘッダーファイルをincludeしておく必要がある。また、アルゴリズムテンプレート関数や後述するタスクスケジューラを使用する前には、「task_scheduler_init.h」内で定義されている「tbb::task_scheduler_init」クラスのオブジェクトを生成・初期化しておく必要がある。通常はリスト1のようにプログラムのスタートアップ時にこのオブジェクトを生成し、終了時にオブジェクトが破棄されるようにすれば良いだろう。
#include "tbb/task_scheduler_init.h"
int main() {
tbb::task_scheduler_init init;
// 以下、アプリケーションの初期化とメイン処理を記述
:
:
:
return 0; // main()関数から抜けるとともに、initオブジェクトは破棄される
}
また、TBBのヘッダーファイルおよびライブラリが適切に読み込まれるよう、ヘッダーファイルおよびライブラリの検索ディレクトリを適切に設定しておく必要がある。インテル Parallel Studioに付属するTBBを利用する場合、Parallel Composerの「Select Build Components」画面の「Use TBB」にチェックを入れておくだけでこれらの設定が完了する(図3、4)。
Plugin Error: Unsupported filetype
オープンソース化された並列化テンプレートクラスライブラリ「Intel Threading Building Blocks」入門Page 1: Intel Threading Building Blocksが持つ機能Page 2: TBBのメリット、TBBを用いた並列アプリケーションの設計と実装Page 3: 要素数が分かっているデータ群に対する反復処理の並列実装(forループの並列化)Page 4: 要素数が分からないデータ群に対する反復処理の並列実装(whileループの並列化)Page 5: パイプライン処理の並列化Page 6: パイプライン処理の並列化・ソースコード詳細解説[http://sourceforge.jp/magazine/09/08/21/1128207/7 Page 7: 高い抽象度でアルゴリズムを実装できるTBB
]