使计算节点中的所有处理器在 OpenMPI 中读取相同的内存块

Making all processors in a computing node read the same memory block in OpenMPI

我想 运行 使用 OpenMPI 和 C 在计算集群中进行数值模拟。但是,有一个大矩阵 A 在每个处理器中都是恒定且相等的。为了避免分配太多不必要的内存,我想将具有共享内存(即它们在同一计算节点中)的处理器分组,并且每个节点 malloc 中只有一个处理器并设置那个大矩阵 A.然后节点中的所有其他处理器应该能够读取该矩阵。

This other question 正是我所需要的,但它是在 Fortran 中。我接受了它的回答并用 C 做了一个原型,但它没有按预期工作。由于我无法理解的原因,MPI_Win_allocate_shared 返回的内存地址偏移了 1 个位移单位。请参阅下面的代码:

#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>

int
main ()
{
    MPI_Init(NULL, NULL);
    int num_processors;
    MPI_Comm_size(MPI_COMM_WORLD, &num_processors);
    int proc_global_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &proc_global_rank);

    // Split de global communicator, grouping by shared memory
    MPI_Comm compute_comm;
    MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, 0, MPI_INFO_NULL, &compute_comm);
    int proc_compute_rank;
    MPI_Comm_rank(compute_comm, &proc_compute_rank);

    // Create the window
    const int ARRAY_SIZE = 1;
    int* shared_data;
    MPI_Aint shared_data_size;
    if (proc_compute_rank == 0) {
        shared_data_size = ARRAY_SIZE * sizeof(int);
    } else {
        shared_data_size = 0;
    }
    int disp_unit = sizeof(int);
    MPI_Win window;
    MPI_Win_allocate_shared(shared_data_size, disp_unit, MPI_INFO_NULL, compute_comm, &shared_data, &window);
    if (proc_compute_rank == 0) {
        shared_data[0] = -10;
    }
    // get the location of the shared memory segment
    if (proc_compute_rank != 0) {
        MPI_Win_shared_query(window, 0, &shared_data_size, &disp_unit, shared_data);
    }
    MPI_Win_fence(0, window);  // wait for shared variables to be ready to be used
    MPI_Barrier(compute_comm);
    printf("rank %d, value[0] = %d\n", proc_compute_rank, shared_data[0]);  // prints a wrong value
    printf("rank %d, value[-1] = %d\n", proc_compute_rank, shared_data[-1]);  // prints correct value
    // do calculations...
    MPI_Win_fence(0, window);  // wait for shared variables to be no longer needed
    MPI_Barrier(compute_comm);
    MPI_Win_free(&window);
    MPI_Finalize();
    return EXIT_SUCCESS;
}

你的代码中真正的问题是你传递了一个 int*MPI_Win_query,但是那个调用需要设置指针,所以你需要传递一个 int**,这意味着在你的情况下 &shared_data.

可能存在第二个问题:通过显式设置 window 缓冲区的内容,您假设是“统一内存模型”,这很可能就是这种情况。如有疑问,请测试

MPI_Win_get_attr(the_window,MPI_WIN_MODEL,&modelstar,&flag); 

并确保该参数不是 MPI_WIN_SEPARATE,在这种情况下,您必须 MPI_Put 将数据放入 window。

顺便说一句,您对获取不同地址的进程进行了观察。即使在你修复了你的&符号错误之后,这仍然是正确的!程序员认为的地址只是一个 逻辑地址 ,它被“页面 table” 翻译成 物理地址 .但是每个进程都有自己的页面table,所以相同的物理地址会在进程中转换为不同的逻辑地址,所以,是的,即使你有正确的指针,你也会得到不同的十六进制地址。