ページ

2009年6月9日火曜日

[.NET] Parallel ループ本体が小さいときの速度アップ法

Achieving Speedups with Small Parallel Loop Bodies より。
イテレーションが小さいときにうかつに Parallel にするとかえってパフォーマンスが悪くなる可能性があります。
例としてこんなコードが載っています。

int[] array = new int[100000000];
Parallel.For(0, array.Length, i =>
{
array[i] = i * i * i;
});

これだと 「array[i] = i*i*i;」 というだけのコードをパラレルにものすごい回数実行するため、パラレルのオーバーヘッドがしゃれにならないくらい大きくなってしまうわけですね。
普通の for ループにしてしまえばパラレルにするオーバーヘッドは無くなりますが、それではスレッド一つしか使わないためもったいないです。

上記の記事では、こういった場合に使える ForRange というちょっとしたメソッドが紹介されています。
ForRange はこんな風に使います。

int[] array = new int[100000000];
ForRange(0, array.Length, (from, to) =>
{
for (int i = from; i < to; ++i)
{
array[i] = i * i * i;
}
});

上記記事に載っているソースコードを見れば明らかですが、ForRange は Environment.ProcessorCount (搭載されているプロセッサ・コア数) 分に分割して Parallel.For を呼ぶようになっています。
仮にプロセッサ・コア数が 4 つの場合は、上記のコードは 0~25000000、25000000~50000000、50000000~75000000、75000000~100000000 の 4 の for ループが Parallel.For されることになります。

なるほどなぁ。


0 件のコメント:

コメントを投稿