如何在 C++ 中使用 MPI 对简单循环进行负载平衡
How to load balance a simple loop using MPI in C++
我正在编写一些计算成本很高但高度可并行的代码。一旦并行化,我打算在 HPC 上运行它,但是为了将运行时间缩短到一周内,问题需要随着处理器数量的增加而很好地扩展。
下面是一个简单而荒谬的例子,说明我试图实现的目标,它足够简洁,可以编译和演示我的问题;
#include <iostream>
#include <ctime>
#include "mpi.h"
using namespace std;
double int_theta(double E){
double result = 0;
for (int k = 0; k < 20000; k++)
result += E*k;
return result;
}
int main()
{
int n = 3500000;
int counter = 0;
time_t timer;
int start_time = time(&timer);
int myid, numprocs;
int k;
double integrate, result;
double end = 0.5;
double start = -2.;
double E;
double factor = (end - start)/(n*1.);
integrate = 0;
MPI_Init(NULL,NULL);
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
for (k = myid; k<n+1; k+=numprocs){
E = start + k*(end-start)/n;
if (( k == 0 ) || (k == n))
integrate += 0.5*factor*int_theta(E);
else
integrate += factor*int_theta(E);
counter++;
}
cout<<"process "<<myid<<" took "<<time(&timer)-start_time<<"s"<<endl;
cout<<"process "<<myid<<" performed "<<counter<<" computations"<<endl;
MPI_Reduce(&integrate, &result, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
if (myid == 0)
cout<<result<<endl;
MPI_Finalize();
return 0;
}
我已经在我的四核笔记本电脑上编译了这个问题
mpiicc test.cpp -std=c++14 -O3 -DMKL_LP64 -lmkl_intel_lp64 - lmkl_sequential -lmkl_core -lpthread -lm -ldl
我得到以下输出;
$ mpirun -np 4 ./a.out
process 3 took 14s
process 3 performed 875000 computations
process 1 took 15s
process 1 performed 875000 computations
process 2 took 16s
process 2 performed 875000 computations
process 0 took 16s
process 0 performed 875001 computations
-3.74981e+08
$ mpirun -np 3 ./a.out
process 2 took 11s
process 2 performed 1166667 computations
process 1 took 20s
process 1 performed 1166667 computations
process 0 took 20s
process 0 performed 1166667 computations
-3.74981e+08
$ mpirun -np 2 ./a.out
process 0 took 16s
process 0 performed 1750001 computations
process 1 took 16s
process 1 performed 1750000 computations
-3.74981e+08
在我看来,似乎一定在某个地方存在我不知道的障碍。我使用 2 个处理器比 3 个处理器获得更好的性能。请问有人可以提供任何建议吗?谢谢
如果我正确阅读了您给出的lscpu
的输出(例如,在 https://unix.stackexchange.com/a/218081 的帮助下(,您有 4 个逻辑 CPU,但只有 2 个硬件内核(每个插槽 1 个插槽 x 2 个内核(。使用cat /proc/cpuinfo
您可以找到CPU的品牌和型号,以了解更多信息。
四个逻辑 CPU 可能是超线程的结果,这意味着一些硬件资源(例如 FPU 单元,但我不是这方面的专家(在两个内核之间共享。因此,我不希望在两个进程之外有任何好的并行扩展。
对于可伸缩性测试,您应该尝试使用具有 6 个或更多硬件内核的计算机,以获得更好的估计。
通过查看您的代码,我希望可以完美地扩展到任意数量的内核 - 至少只要您不包括进程启动和最终MPI_Reduce所需的时间。随着涉及更多过程,这些肯定会变慢。
相关文章:
- 在c++中用vector填充一个简单的动态数组
- (C++)分析树以计算返回错误值的简单算术表达式
- 我的简单if-else语句是如何无法访问的代码
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 一种在C++中读取TXT配置文件的简单方法
- 关于简单C++函数(is_palindrome)的逻辑的问题
- 显示错误输出的简单数组排序程序
- 当无法使用模板和宏时,生成类型变体C++代码的最简单方法是什么?
- 退出简单while循环时出现问题
- 为什么简单的算术减法在"if"条件下不起作用?
- C++-字符串是否包含一个带有简单循环的单词
- 关于 c++ 函数中指针赋值的简单问题
- 从函数返回任意简单类型的数据
- 如何在没有函数的情况下编写此代码并使C++更简单?
- 有没有办法简单地从 GPU 调用多个 cpp 输出文件?
- 在简单示例中,Python3 + ctypes 回调会导致内存泄漏
- 当简单捕获中的标识符显示为参数的声明符 ID 时,没有编译器诊断
- 如何使用 samtools C API 构建一个简单的主.cpp文件
- CPU 瓶颈;处理具有许多非静态对象的 3D 场景渲染的简单方法