我有以下程序C ++程序,它不使用任何通信,并且在所有内核上完成相同的相同工作,我知道这根本不使用并行处理:
unsigned n = 130000000;
std::vector<double>vec1(n,1.0);
std::vector<double>vec2(n,1.0);
double precision :: t1,t2,dt;
t1 = MPI_Wtime();
for (unsigned i = 0; i < n; i++)
{
// Do something so it's not a trivial loop
vec1[i] = vec2[i]+i;
}
t2 = MPI_Wtime();
dt = t2-t1;
我在一个有两个节点的节点上运行这个程序 英特尔®至强®处理器E5-2690 v3,因此我共有24个内核。这是一个专用节点,没有其他人在使用它。 由于没有通信,并且每个处理器正在执行相同数量的(相同)工作,因此在多个处理器上运行它应该给出相同的时间。但是,我得到以下时间(所有核心的平均时间):
1核心:0.237
2个核心:0.240
4核:0.241
8个核心:0.261
16核:0.454
什么可能导致时间的增加?特别适用于16个核心。 我已经运行了callgrind,并且在所有内核上获得了大致相同数量的数据/指令未命中(未命中的百分比相同)。
我在一个带有两个Intel®Xeon®处理器E5-2628L v2的节点上重复了相同的测试(16个核心全部在一起),我观察到执行时间的增加。这与MPI实现有关吗?
答案 0 :(得分:4)
考虑到每个等级使用~2 GiB内存,您的代码受内存限制。除了prefetchers之外,您不是在缓存中操作,而是在主内存中操作。您只需在一定数量的活动核心上达到内存带宽。
另一方面可以是turbo模式,如果启用的话。如果使用更少的内核,Turbo模式可以将核心频率提高到更高的水平。只要内存带宽不饱和,来自turbo核心的更高频率将增加每个内核获得的带宽。 This paper讨论Haswell处理器上可用的总内存带宽,具体取决于活动核心数和频率(图7./8。)
请注意,这与MPI / OpenMPI无关。您也可以通过任何其他方式启动相同的程序X次。
答案 1 :(得分:2)
我怀疑您的程序应该使用公共资源,所以当它们的数量增加时,会有延迟,因此资源是免费的#39; ed以便其他进程可以使用它。
您可以看到,您可能拥有24个核心,但这并不意味着您的所有系统都允许每个核心同时执行所有操作。正如评论中所提到的,内存访问是可能导致延迟(由于流量)的一件事,对于磁盘也是如此。
还要考虑互连网络,它也可能遭受许多访问。总之,请注意这些硬件延迟足以淹没处理时间。
一般说明:记住如何定义程序的效率:
E = S / p,其中S是加速,p是节点/进程/线程的数量
现在考虑 Scalability 。通常程序的可扩展性很弱,即您必须以与问题大小相同的速率增加 p 。通过仅增加 p 的数量,同时保持问题的大小(在您的情况下为n
)不变,同时保持效率不变,产生一个强可伸缩的程序。
答案 2 :(得分:1)
您的程序根本没有使用并行处理。仅仅因为你用OpenMP编译它并没有使它成为 parallel 。
例如,要并行化for循环,您需要使用不同的#pragma的OpenMP商品。
unsigned n = 130000000;
std::vector<double>vec1(n,1.0);
std::vector<double>vec2(n,1.0);
double precision :: t1,t2,dt;
t1 = MPI_Wtime();
#pragma omp parallel for
for (unsigned i = 0; i < n; i++)
{
// Do something so it's not a trivial loop
vec1[i] = vec2[i]+i;
}
t2 = MPI_Wtime();
dt = t2-t1;
但是,考虑到对于较大的n值,缓存未命中的影响可能会隐藏多核心所获得的性能。