Jaa


aobench の並列化

CEDEC 2009 での講演の準備中に、レイトレースの C のベンチマーク aobench を教えてもらったので、このベンチマークを Visual Studio 2010 の PPL(並列パターン ライブラリー)を使い、並列化してみました。

レンダリング ループを parallel_for を使って以下のように並列化しました。

void render(unsigned char *img, int w, int h, int nsubsamples)
{
int x, y;
int u, v;

//for (y = 0; y < h; y++) {
parallel_for( 0, h, [&](int y) {
//for (x = 0; x < w; x++) {
parallel_for( 0, w, [&](int x) {
for (v = 0; v < nsubsamples; v++) {
for (u = 0; u < nsubsamples; u++) {

        …

      }
}
//}
});
//}
});

この並列化によって、ベンチマークの結果は Core2 Quad で2.13秒(直列)から0.64秒(並列)へとそこそこの結果でしたが、結果の画像が次のようにおかしくなってしまいました。

clip_image001

2日ほど悩みましたが、理由がわからず US の Parallel Team に問い合わせると、10分で回答が返ってきました! 変数 u, v がループの外側で宣言され、並列な全タスクで共有されていたのが原因です。最終的に以下のようにループ内での宣言に直すと、正しい画像が得られるようになりました。並列化のワナですね...

void render(unsigned char *img, int w, int h, int nsubsamples)
{

parallel_for( 0, h, [&](int y) {
parallel_for( 0, w, [&](int x) {
for (int v = 0; v < nsubsamples; v++) {
for (int u = 0; u < nsubsamples; u++) {

        …

      }
}
});
});

PPLやTPLによる並列化は、スレッドを生成・管理するスレッド ベースの並列化手法に比べ、はるかに簡単に並列化でき、スケーラブルな性能が期待できるのが魅力的です。コードを添付しますので試してみてください。

ao.cpp