自从我使用 MPI 已经有一段时间了,所以我并没有真正回答“如何编写代码”的问题。我更多地关注基准方法方面的事情,所以你希望可以设计它来实际衡量一些有用的东西。基准测试很难;得到一个数字很容易,很难得到一个有意义的数字来衡量你想要衡量的东西。
而不是指定你得到哪些节点,你可以只查询你得到了哪些节点。(即检测 MPI 作业的多个进程最终在同一物理主机上竞争内存带宽的情况。)
您还可以随机化您在每个节点上运行的线程数或其他东西,以查看带宽如何随着执行 memcpy、memset 或诸如缩减或 memcmp 之类的只读操作的线程数而扩展。
在最近的 Intel Xeon 上,每台机器一个线程不会接近饱和内存带宽,除了可能类似于桌面 CPU 的低核数 CPU。(然后仅当您的代码编译为有效的矢量化 asm 时)。L3 / 内存延迟太高,单核有限的内存并行性无法饱和吞吐量。(请参阅为什么 Skylake 在单线程内存吞吐量方面比 Broadwell-E 好得多? ,以及用于 memcpy 的增强型 REP MOVSB 中的“延迟绑定平台” 。)
运行带宽瓶颈代码(如 STREAMS 基准测试)可能需要 4 到 8 个线程才能使多核 Xeon 的内存带宽饱和。比这更多的线程将具有大致相同的总数,除非您使用非常小的数组进行测试,以便私有的每核 L2 缓存发挥作用。(在现代 Intel CPU 上为 256kB,而每个内核 L3 共享约 2MB)。更新:Skylake-AVX512 上每个核心私有 L2 1 MiB。
对于双插槽节点,NUMA 是一个因素。如果您的线程最终使用的内存都映射到一个插槽上的物理内存控制器,而让另一个插槽的内存控制器空闲,您将只能看到机器带宽的一半。这可能是测试内核的 NUMA 感知物理内存分配是否适合您的实际工作负载的好方法。(如果您的带宽微基准与您的实际工作负载相似)
请记住,内存带宽是节点上所有内核的共享资源,因此为了获得可重复的结果,您需要避免与其他负载竞争。即使内存占用很小的东西也可以使用大量带宽,如果它的工作集不适合每个核心的私有 L2 缓存,所以不要假设另一个作业不会仅仅因为它只使用内存带宽而竞争内存带宽几百MB。