nはどのくらいの大きさですか?
OpenMP parallel for
ディレクティブのデフォルトスケジューリングは、実装固有のものです。 GOMP(gccで使用されるOpenMP実装)のように見えますが、デフォルトはで、documentation hereに従っています。これは、各スレッドが隣のスレッドによってロードされるメモリ位置に(i-1
とi+1
で)アクセスしていることを意味します。これは、キャッシュ使用率の低下につながります。現代のCPUアーキテクチャでは、このようなステンシル操作は頻繁にメモリに依存し、キャッシュに敏感です。あなたが例えば、大きな塊で、スケジュールを指定してみてください:私はちょうどここでは例として1024を使用してい
#pragma omp parallel for schedule(dynamic,1024)
。実際には、最適なチャンクファクタを見つけるために実験を行う必要があります(または、パラメータスイープを使用して系統的に検索する、「自動チューニング」と呼ばれるプロセス)。あるいは、CPUのL1またはL2キャッシュサイズから派生させるなど、理論に基づいた値を選択することもできます。
また、forループ内の計算量がスレッド間で均一で、動的スケジューラのオーバーヘッドがボトルネックの原因になる場合があるため、静的スケジューリングを試すこともできます。
#pragma omp parallel for schedule(static)
をチャンクサイズなしで指定すると、各スレッドにほぼ同じサイズの1つのチャンクが割り当てられます。
最後に、OpenMPスレッドを独自のCPUコアに固定することもできます。これは、環境変数GOMP_CPU_AFFINITYを使用して行うことができます。
編集:
私は、GCC 4.2.1でコンパイルされた次のテストプログラムで遊んでた、と私は、私は上記にリンクされているドキュメントが間違っていると思います。 GOMPのデフォルトはschedule(static)
です。
#include <stdio.h>
#include <omp.h>
int main(int argc, char** argv)
{
int i;
#pragma omp parallel for
for (i=0; i<15; i++) {
int id = omp_get_thread_num();
printf("%d assigned to thread %d\n", i, id);
}
}
そして、二つのスレッドでの出力は次のとおりです。
$ ./test_sched | sort -n
0 assigned to thread 0
1 assigned to thread 0
2 assigned to thread 0
3 assigned to thread 0
4 assigned to thread 0
5 assigned to thread 0
6 assigned to thread 0
7 assigned to thread 0
8 assigned to thread 1
9 assigned to thread 1
10 assigned to thread 1
11 assigned to thread 1
12 assigned to thread 1
13 assigned to thread 1
14 assigned to thread 1
コンパイルし、GCC 4.6.1で正常に実行します。どのコンパイラを使用しますか? –
コンパイラとオペレーティングシステムに関する詳細を追加できますか? – talonmies
MacOS Snow Leopardのgcc 4.2.1、正確には:686-apple-darwin10-g ++ - 4.2.1(GCC)4.2.1(Apple Inc. build 5666)(ドット3) – Chris