【问题标题】:Performance comparison MPI vs OpenMP性能比较 MPI 与 OpenMP
【发布时间】:2017-08-09 14:43:46
【问题描述】:

我有一个很奇怪的问题。 我什至不知道我是否可以为您提供回答我的问题所需的所有信息;如果有什么遗漏,请告诉我。

我使用 MPI 运行这样的代码:

#include <mpi.h>
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <iostream>
#include <stdexcept>
#include <algorithm>
#include "mkl.h"
double *gradient_D = new double[K*M];
double *DX = new double[M*N];
double gradientD_time = MPI_Wtime();
for (int j = 0; j < K; j++){
    for (int i = 0; i < M; i++){
        gradient_D[j*M+i] = 0;
        for (int k = 0; k < n; k++)
            gradient_D[i+M*j] += DX[i+k*M];
        }   
    }  
double gradientD_total_time = (MPI_Wtime() - gradientD_time);
printf("Gradient D total = %f \n", gradientD_total_time);

代码的含义并不重要:我只是运行三个 for 循环并评估 CPU 时间。 在cmake中我写了以下命令:

project(mpi_algo)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_COMPILER "mpicxx")
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS)
set(CMAKE_CXX_FLAGS "-cxx=icpc -mkl=sequential")
add_executable(mpi_algo main.cpp)

然后我运行代码:

mpirun -np 1 ./mpi_algo

之后,我运行了一个类似的代码,在其中执行相同的操作,但使用的是 OpenMP 而不是 MPI:

#include <omp.h>
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <iostream>
#include <stdexcept>
#include <algorithm>
#include "mkl.h"
double *gradient_D = new double[K*M];
double *DX = new double[M*N];
double gradientD_time = omp_get_wtime();
for (int j = 0; j < K; j++){
    for (int i = 0; i < M; i++){
        gradient_D[j*M+i] = 0;
        for (int k = 0; k < n; k++)
            gradient_D[i+M*j] += DX[i+k*M];
        }   
    }  
double gradientD_total_time = (omp_get_wtime() - gradientD_time);
printf("Gradient D total = %f \n", gradientD_total_time);

您可以看到代码中存在细微差别。 这是cmake:

project(openmp_algo)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_COMPILER "icc")
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS)
set(CMAKE_CXX_FLAGS "-qopenmp -mkl=sequential")
add_executable(openmp_algo main.cpp)

然后我运行代码:

./openmp_algo

现在,我无法解释的是,使用 MPI 的代码需要大约 1 秒才能运行。另一个应该是一样的,大约需要 20 秒。

请有人解释一下为什么?

编辑:常量 M、N、n、k 对理解问题无关紧要。他们只是定义了数组的维度。

【问题讨论】:

  • 您编译时是否启用了优化?没有它们,这是毫无意义的比较;一个编译器可能会默认进行某种程度的优化并优化大部分循环(由于未使用结果,因此实际上可以使用更高的优化级别完全删除循环),另一个编译器可能正在完成所有工作然后将其丢弃。这不是minimal reproducible example 也无济于事;我们不知道gradient_D_loc 是在哪里定义的,是什么常量等等。
  • 我不知道你指的是什么。实际上在整个代码中都使用了该循环的结果。
  • 我编辑了:gradient_D_loc 应该只是 gradient_D
  • 编译器采用标志来启用优化(大多数默认生成未优化的代码,但不是全部)。将时序结果与关闭或不同级别的优化进行比较不会给您有用的结果。例如,icc-O## 为 0-3)用于越来越高的优化级别,加上 -fast 用于“极端优化”。由于mpicxx 似乎在这里包装了icpc,它会传递类似的选项。看起来像-O2 -xHostis recommended with icc/icpc
  • 为什么在 OpenMP 示例中使用 icc 作为 C++ 编译器?

标签: c++ performance time mpi openmp


【解决方案1】:

由于您没有提供太多有关环境的详细信息,因此我将胡乱猜测以尝试给出解释。首先,让我们做几点说明:

  • 您看似完全相同,但什么都不做,因此聪明的编译器完全有权优化您的计算循环并只进行打印;
  • 您的 OpenMP 代码是用 vanilla icc 编译的(顺便说一句,C++ 代码的奇怪选择)因此优化级别将是默认的 -O2(减去默认情况下被视为不是线程安全的额外优化,使用 @ 987654323@ 将禁用;
  • 您的 MPI 代码是使用纯 mpicxx 编译的,它将在内部调用 icpc 作为编译器。

这是mpicxx,我怀疑是这里的关键:确实,mpicxx 只是实际编译器的包装器,它还将设置一些包含路径、一些库路径和列表,但也可能设置一些额外的优化选项。例如,在某些情况下,安装 MPI 库时使用的优​​化选项将保存在 mpicxx 包装器中,并在编译代码时默认使用...

所以这是我的猜测,您的 mpicxx 设置在其他 -O3 优化选项中,因此,编译器将优化 MPI 循环,而您为 OpenMP 代码获得的默认 -O2 没有不要这样做。因此,在 MPI 代码的情况下,您几乎没有计时,而您正在使用 OpenMP 代码计时实际循环执行。

只是一个猜测,但这似乎很公平。一个很好的测试是检查 mpicxx -cxx=icpc -show 会给你什么...

【讨论】:

  • 好的,我会检查的。但是您是否知道如何更改两个编译器以使两个代码之间的比较变得合理。我应该降低(我不知道如何)到-O2mpicxx 还是应该增加到-O3(我不知道)icpc 编译器?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-04
  • 2011-06-10
  • 1970-01-01
  • 1970-01-01
  • 2021-12-14
  • 2010-11-14
相关资源
最近更新 更多