ただし、スレッド化ライブラリは、コアへのスレッドの割り当てについて心配する必要さえあります。これはオペレーティング システムの仕事ではないでしょうか。それでは、Boost よりも TBB を使用することの本当の利点は何でしょうか?
その通りです。通常、スレッド ライブラリは、スレッドをコアにマッピングすることを気にするべきではありません。そしてTBBはそうではありません。TBB は、スレッドではなくタスクで動作します。TBB のスケジューラは、スレッドのプールを割り当て、実行するタスクを動的に選択できるようにすることで、すべてのコアを利用します。これは、使用可能な作業を手動でスレッドにマップする必要がある Boost よりも優れている点です。そして、TBB は、最も一般的な並列パターンを表現し、タスクによるすべての操作を隠すために使用できる、parallel_for、parallel_pipeline などの高レベルの構造を提供します。
たとえば、マンデルブロ フラクタルのポイントを計算するコードを見てみましょう ( http://warp.povusers.org/Mandelbrot/から取得、変数の初期化は省略):
for(unsigned y=0; y<ImageHeight; ++y)
{
double c_im = MaxIm - y*Im_factor;
for(unsigned x=0; x<ImageWidth; ++x)
{
double c_re = MinRe + x*Re_factor;
double Z_re = c_re, Z_im = c_im;
bool isInside = true;
for(unsigned n=0; n<MaxIterations; ++n)
{
double Z_re2 = Z_re*Z_re, Z_im2 = Z_im*Z_im;
if(Z_re2 + Z_im2 > 4)
{
isInside = false;
break;
}
Z_im = 2*Z_re*Z_im + c_im;
Z_re = Z_re2 - Z_im2 + c_re;
}
if(isInside) { putpixel(x, y); }
}
}
これを TBB と並列にするには、最も外側のループを tbb::parallel_for に変換するだけです (簡潔にするために C++11 ラムダを使用します)。
tbb::parallel_for(0, ImageHeight, [=](unsigned y)
{
// the rest of code is exactly the same
double c_im = MaxIm - y*Im_factor;
for(unsigned x=0; x<ImageWidth; ++x)
{
...
// if putpixel() is not thread safe, a lock might be needed
if(isInside) { putpixel(x, y); }
}
});
TBB はすべてのループ反復を使用可能なコアに自動的に分散し (いくつでも構いません)、動的に負荷を分散します。これにより、スレッドにさらに作業が必要な場合、他のスレッドがそれを待つだけでなく、CPU を最大化するのに役立ちます。利用。生のスレッドで実装してみてください。違いを感じるでしょう :)