我试图了解 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.9s,36个线程需要3.1s,24个线程需要3.7s,12个线程需要4.9s,1个线程运行代码需要57s。
不幸的是,我不得不说有一个进程在使用 100% 的一个内核运行在计算机上,所以这可能会影响它。这不是我的过程,所以我无法结束它来测试差异,但不知何故,我怀疑这会导致 19~20 倍加速和理想的 48 倍加速之间的差异。
为了确保这不是 OpenMP 问题,我同时运行了程序的两个副本,每个副本有 24 个线程(一个具有 umin=1,umax=5000000000,另一个具有 umin=5000000000,umax=10000000000)。在这种情况下,程序的两个副本都在 2.9 秒后完成,因此它与使用单个程序实例运行 48 个线程完全相同。
是什么阻止了这个简单程序的线性缩放?