48 コア システム (4xAMD Opteron 6348、2.8 Ghz、CPU あたり 12 コア) での並列化の制限を理解しようとしています。私はこの小さな OpenMP コードを書いて、可能な限り最良の状況であると考えられる状況でスピードアップをテストしました (タスクは恥ずかしいほど並列です)。
// Compile with: gcc scaling.c -std=c99 -fopenmp -O3
#include <stdio.h>
#include <stdint.h>
int main(){
const uint64_t umin=1;
const uint64_t umax=10000000000LL;
double sum=0.;
#pragma omp parallel for reduction(+:sum)
for(uint64_t u=umin; u<umax; u++)
sum+=1./u/u;
printf("%e\n", sum);
}
スケーリングが非常に非線形であることに驚きました。48 スレッドでコードを実行するには約 2.9 秒、36 スレッドで 3.1 秒、24 スレッドで 3.7 秒、12 スレッドで 4.9 秒、1 スレッドでコードを実行するには 57 秒かかります。
残念ながら、1 つのコアを 100% 使用してコンピューター上で実行されているプロセスが 1 つあると言わざるを得ないため、それが影響している可能性があります。これは私のプロセスではないので、違いをテストするために終了することはできませんが、どういうわけか、それが 19 ~ 20 倍の高速化と理想的な 48 倍の高速化の違いを生んでいるとは思えません。
OpenMP の問題ではないことを確認するために、プログラムの 2 つのコピーをそれぞれ 24 スレッドで同時に実行しました (1 つは umin=1、umax=5000000000 で、もう 1 つは umin=5000000000、umax=10000000000 です)。その場合、プログラムの両方のコピーが 2.9 秒後に終了するため、プログラムの 1 つのインスタンスで 48 スレッドを実行するのとまったく同じです。
この単純なプログラムで線形スケーリングを妨げているのは何ですか?