CでOpenMPを使用する方法を学習中です。HelloWorldの練習として、私は素数を数えるプログラムを作成しています。次のように私は、これを並列化:OpenMPパラレルforループでパフォーマンスが少し向上する
int numprimes = 0;
#pragma omp parallel for reduction (+:numprimes)
for (i = 1; i <= n; i++)
{
if (is_prime(i) == true)
numprimes ++;
}
私は(私が使用していmath.h
機能のための-lm
)gcc -g -Wall -fopenmp -o primes primes.c -lm
を使用してこのコードをコンパイル。次に、私はIntel® Core™2 Duo CPU E8400 @ 3.00GHz × 2
でこのコードを実行し、予想どおり、パフォーマンスはシリアルプログラムよりも優れています。
しかし、これをもっと強力なマシンで実行しようとすると、問題が発生します。 (私もnum_threads
で使用する手動でスレッド数を設定しようとしたが、これは何も変更しませんでした。)10 000 000
までのすべての素数を数える私は(time
を使用して)、次の回与えます:
8コアマシンを:
real 0m8.230s
user 0m50.425s
sys 0m0.004s
デュアルコアマシン:
real 0m10.846s
user 0m17.233s
sys 0m0.004s
そして、このパターンはより多くの素数を数えるために続けて、より多くのコアを搭載したマシンは、わずかな性能向上を示しているが、いない限り、私はサイコーのための期待通り非常に多くのコアが利用可能です。 (私は4倍以上のコアは、ほぼ4分の走行時間を意味することを期待する?)
カウントが50 000 000
までの素数:
8コアマシン:
real 1m29.056s
user 8m11.695s
sys 0m0.017s
デュアルコアマシン:
real 1m51.119s
user 2m50.519s
sys 0m0.060s
誰でも私のためにこれを明確にすることができれば、非常に感謝しています。
EDIT
これは私のプライム・チェック機能です。
static int is_prime(int n)
{
/* handle special cases */
if (n == 0) return 0;
else if (n == 1) return 0;
else if (n == 2) return 1;
int i;
for(i=2;i<=(int)(sqrt((double) n));i++)
if (n%i==0) return 0;
return 1;
}
あなたの 'is_prime'の見た目はどうですか?スレッド間で共有されるデータにアクセスすると、同期オーバーヘッドが発生します。 –
'static int is_prime(int n)'は呼び出された関数のヘッダです。問題を明らかにするには、関数全体を追加することができます。私は各スレッドが自動的に独自の関数を呼び出すと思いますか? – casper
この関数は、静的または(半)グローバルデータを使用していますか?あるいは、引数と定数のみを使用していますか? –