【问题标题】:OpenMPI + Infiniband performanceOpenMPI + Infiniband 性能
【发布时间】:2017-02-24 04:04:51
【问题描述】:

我是 HPC 新手,我对 MPI 在 Infiniband 上的性能感到好奇。作为参考,我在通过 IB 连接的两台不同机器上使用 OpenMPI。

我编写了一个非常简单的基准测试,以了解我可以使用 MPI 调用在 IB 上传输数据的速度。下面你可以看到代码。

问题是,当我运行它时,我的吞吐量约为 1.4 GB/秒。然而,当我使用像 ib_write_bw 这样的标准 ib 基准测试时,我得到了将近 6 GB/s。是什么导致了这种巨大的差异?我是否对 Gather 很天真,或者这只是我无法克服的 OpenMPI 开销的结果?

除了代码之外,我还提供了一个图表来显示我的简单基准测试的结果。

提前致谢!

结果:

代码:

#include<iostream>
#include<mpi.h>
#include <stdint.h>
#include <ctime>
using namespace std;


void server(unsigned int size, unsigned int n) {
 uint8_t* recv = new uint8_t[size * n];
 uint8_t* send = new uint8_t[size];
 std::clock_t s = std::clock();
 MPI_Gather(send, size, MPI_CHAR, recv, size, MPI_CHAR, 0, MPI_COMM_WORLD);
 std::clock_t e = std::clock();
 cout<<size<<" "<<(e - s)/double(CLOCKS_PER_SEC)<<endl;
 delete [] recv;
 delete [] send;
}

void client(unsigned int size, unsigned int n) {
 uint8_t* send = new uint8_t[size];
 MPI_Gather(send, size, MPI_CHAR, NULL, 0, MPI_CHAR, 0, MPI_COMM_WORLD);
 delete [] send;
}

int main(int argc, char **argv) {
 int ierr, size, rank;
 MPI_Init(&argc, &argv);
 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
 MPI_Comm_size(MPI_COMM_WORLD, &size);
 cout<<"Rank "<<rank<<" of "<<size<<endl;
 unsigned int min = 1, max = (1 << 31), n = 1000;
 for (unsigned int i = 1; i < n; i++) {
  unsigned int s = i * ((max - min) / n);
  if(rank == 0) server(s, size); else client(s, size);
 }

 MPI_Finalize();
}

【问题讨论】:

  • 您是否尝试过使用另一个已建立的基准来验证这些性能问题与代码无关?如果您可以访问英特尔编译器和 MPI,英特尔 MPI 基准测试是验证性能问题的绝佳工具software.intel.com/en-us/articles/intel-mpi-benchmarks。您是否在基准测试中改变了负载大小或使用单一大小,热身怎么样,您运行了多少次? IMB-PingPong 将在多次迭代中运行各种负载大小,以在预热后测试带宽和吞吐量。

标签: mpi openmpi infiniband


【解决方案1】:

在您的代码中,您针对每个消息大小执行一个集体操作。 与为性能测量而编写的测试(例如 ib_write_bw)相比,这涉及 巨大 开销。 一般来说,将 MPI 集合与 ib_write_bw 进行比较不是苹果对苹果的比较:

  • RDMA 操作码

    • ib_write_bw 使用 RDMA_WRITE 操作,它根本不使用 CPU - 一旦完成初始握手,它就是纯 RDMA,仅受网络和 PCIe 功能的限制。
    • MPI 将为不同的集合和不同的消息大小使用不同的 RDMA 操作码,如果您像在代码中那样做,MPI 会为每条消息做很多事情(因此开销很大)
  • 数据开销

    • ib_write_bw 传输几乎纯数据(有本地路由标头和有效负载)
    • MPI 向每个数据包添加了更多数据(标头),以允许接收器识别消息
  • 零拷贝

    • ib_write_bw 正在执行所谓的“零复制” - 数据直接从用户缓冲区发送,并直接在接收端写入用户缓冲区,无需从缓冲区复制/复制到缓冲区
    • MPI 会将消息从客户端缓冲区复制到发送方的内部缓冲区,然后再将其从接收方的内部缓冲区复制到服务器缓冲区。同样,此行为取决于消息大小和 MPI 配置以及 MPI 实现,但您大致了解。
  • 内存注册

    • ib_write_bw 注册所需的内存区域并在开始测量性能之前在客户端和服务器之间交换此信息
    • 如果 MPI 需要在集体执行期间注册一些内存区域,它会在您测量时间时完成
  • 还有更多

    • 即使是“小”的事情,比如预热 HCA 上的缓存行...

所以,既然我们已经介绍了为什么您不应该比较这些东西,下面是您应该做的事情:

有两个库被视为 MPI 性能测量的事实标准:

  1. IMB (Intel MPI Benchmark) - 上面写着 Intel,但它是作为标准 MPI 应用程序编写的,适用于任何 MPI 实现。
  2. OSU benchmarks - 再次显示 MVAPICH,但它适用于任何 MPI。

下载这些,使用您的 MPI 进行编译,运行您的基准测试,看看您会得到什么。 这是您使用 MPI 可以获得的最高值。 如果你得到的结果比你的小程序好得多(你肯定会的)——这是开源的,看看专业人士是怎么做的:)

玩得开心!

【讨论】:

    【解决方案2】:

    您必须考虑在等级 0 上收到的集体呼叫的完整有效负载大小取决于等级数。因此,比如说,4 个进程发送 1000 个字节,您实际上会在根级别上收到 4000 个字节。这包括从 rank 0 的输入缓冲区到输出缓冲区的内存副本(可能会绕过网络堆栈)。那是您添加 MPI 和较低网络协议的开销之前。

    【讨论】:

    • 我发布的情节是针对双节点系统的,所以你的论点,一般来说是正确的,不应该影响本案。
    猜你喜欢
    • 1970-01-01
    • 2016-11-04
    • 2016-01-10
    • 2018-05-28
    • 1970-01-01
    • 2018-04-06
    • 2017-04-28
    • 2016-01-28
    • 2018-10-22
    相关资源
    最近更新 更多