c++ - MPI - 随着进程数量的增加没有加速

标签 c++ performance mpi

我正在编写程序来测试数字是否为素数。一开始我计算分配给每个进程的数字,然后将这个数量发送给进程。接下来,执行计算并将数据发送回保存结果的进程 0。下面的代码有效,但是当我增加进程数时,我的程序不会加速。在我看来,我的程序不能并行运行。怎么了?这是我在 MPI 的第一个项目,因此欢迎任何建议。

我使用 mpich2,并在 Intel Core i7-950 上测试我的程序。

主要.cpp:

if (rank == 0) {
    int workers = (size-1);
    readFromFile(path);
    int elements_per_proc = (N + (workers-1)) / workers;
    int rest = N % elements_per_proc;

    for (int i=1; i <= workers; i++) {
        if((i == workers) && (rest != 0))
            MPI_Send(&rest, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
        else
            MPI_Send(&elements_per_proc, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
    }

    int it = 1;
    for (int i=0; i < N; i++) {
        if((i != 0) && ((i % elements_per_proc) == 0))
        it++;
        MPI_Isend(&input[i], 1, MPI_INT, it, 0, MPI_COMM_WORLD, &send_request);
    }
}

if (rank != 0) {
    int count;
    MPI_Recv(&count, 1, MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    for (int j=0; j < count; j++) {
        MPI_Recv(&number, 1, MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        result = test(number, k);
        send_array[0] = number;
        send_array[1] = result;
        MPI_Send(send_array, 2, MPI_INT, 0, 0, MPI_COMM_WORLD);
    }
}   

if (rank == 0) {
    for (int i=0; i < N; i++) {
        MPI_Recv(rec_array, 2, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        //  save results
    }
}

最佳答案

您的实现可能无法很好地扩展到许多流程,因为您在每一步都进行沟通。您目前为每个输入传达数字和结果,这会产生很大的延迟开销。相反,您应该考虑批量 传达输入(即,使用单个消息)。

此外,使用 MPI 集合操作 (MPI_Scatter/MPI_Gather) 代替 MPI_Send/MPI_Recv 循环可能进一步提高您的表现。

此外,您还可以利用 master 进程来处理输入 block 。

更具可扩展性的实现可能如下所示:

// tell everybody how many elements there are in total
MPI_Bcast(&N, 1, MPI_INT, 0, MPI_COMM_WORLD);

// everybody determines how many elements it will work on
// (include the master process)
int num_local_elements = N / size + (N % size < rank ? 1 : 0);
// allocate local size
int* local_input = (int*) malloc(sizeof(int)*num_local_elements);

// distribute the input from master to everybody using MPI_Scatterv
int* counts; int* displs;
if (rank == 0) {
    counts = (int*)malloc(sizeof(int) * size);
    displs = (int*)malloc(sizeof(int) * size);
    for (int i = 0; i < size; i++) {
        counts[i] = N / size + (N % size < i ? 1 : 0);
        if (i > 0)
            displs[i] = displs[i-1] + counts[i-1];
    }
    // scatter from master
    MPI_Scatterv(input, counts, displs, MPI_INT, local_input, num_local_elements, MPI_INT, 0, MPI_COMM_WORLD);
} else {
    // receive scattered numbers
    MPI_Scatterv(NULL, NULL, NULL, MPI_DATATYPE_NULL, local_input, num_local_elements, MPI_INT, 0, MPI_COMM_WORLD);
}

// perform prime testing
int* local_results = (int*) malloc(sizeof(int)*num_local_elements);
for (int i = 0; i < num_local_elements; ++i) {
    local_results[i] = test(local_input[i], k);
}

// gather results back to master process
int* results;
if (rank == 0) {
    results = (int*)malloc(sizeof(int)*N);
    MPI_Gatherv(local_results, num_local_elements, MPI_INT, results, counts, displs, MPI_INT, 0, MPI_COMM_WORLD);
    // TODO: save results on master process
} else {
    MPI_Gatherv(local_results, num_local_elements, MPI_INT, NULL, NULL, NULL, MPI_INT, 0, MPI_COMM_WORLD);
}

关于c++ - MPI - 随着进程数量的增加没有加速,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30512770/

相关文章:

c++ - C++11 中常量表达式的模板 int 参数

c++ - 为什么这段代码使用不同的参数传递策略没有显着的性能差异?

c++ - 是否可以忽略/丢弃 MPI_Allgather 中接收到的数据?

c - 使用MPI的不同大小的散布矩阵 block

c++ - Qt QQuickFramebufferObject OpenGL渲染侵入其他物体场景为红色

c# - c# 中的链表和红/黑树 - 引用问题?

C++ 链表仅在 GNU/Linux 而不是 Windows 中导致段错误

performance - 快速解压算法

performance - 我的C++应用程序在Docker容器中运行速度较慢

mpi - 当我尝试发送 2D int 数组时,为什么 MPI_Send 会阻塞?