如何在给定的 MPI 进程中 运行 多个线程?

How can I run multiple threads inside of a given MPI process?

假设您使用 OpenMP 运行 多线程 您将像使用 MPI 一样编写 OpenMP 代码。 (这个说法过于简化了)

当 MPI 出现时,您需要考虑您的进程将如何通信。 MPI 不是向单个线程发送消息,而是向单个进程发送消息。出于这个原因,MPI 提供了四种与线程交互的模式。

  1. MPI_THREAD_SINGLE: 只提供一个线程
  2. MPI_THREAD_FUNNELED:可以提供很多线程,但是只有主线程可以进行MPI调用。主线程是调用 MPI_Init...
  3. 的线程
  4. MPI_THREAD_SERIALIZED: 可以提供多个线程,但一次只能调用一个线程。
  5. MPI_THREAD_MULTIPE: 可以提供很多线程,所有线程都可以随时进行MPI调用。

您需要在 MPI_Init 指定您想要的模式,它变成: MPI_Init_thread(&argc, &argv, HERE_PUT_THE_MODE_YOU_NEED, PROVIDED_MODE) 前任: MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPE, &provided)

在提供的字段中 MPI_Init_thread returns 提供的模式。确保你有一个模式,你的代码可以处理它。

另外,避免使用MPI_Probe和MPI_IProbe,因为它们不是线程保存的。您应该使用 MPI_Mprobe 和 MPI_Improbe。

这是一个简单的 'hello world' 示例,@ab2050 问:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <omp.h>
#include "mpi.h"

int main(int argc, char *argv[]) {
    int provided;
    int rank;

    MPI_Init_thread(&argc, &argv, MPI_THREAD_FUNNELED, &provided);
    if (provided != MPI_THREAD_FUNNELED) {
        fprintf(stderr, "Warning MPI did not provide MPI_THREAD_FUNNELED\n");
    }

    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    #pragma omp parallel default(none), \
                        shared(rank), \
                        shared(ompi_mpi_comm_world), \
                        shared(ompi_mpi_int), \
                        shared(ompi_mpi_char)
    {
        printf("Hello from thread %d at rank %d parallel region\n", 
                omp_get_thread_num(), rank);
        #pragma omp master
        {
            char helloWorld[12];
            if (rank == 0) {
                strcpy(helloWorld, "Hello World");
                MPI_Send(helloWorld, 12, MPI_CHAR, 1, 0, MPI_COMM_WORLD);
                printf("Rank %d send: %s\n", rank, helloWorld);
            }
            else {
                MPI_Recv(helloWorld, 12, MPI_CHAR, 0, 0, MPI_COMM_WORLD,
                         MPI_STATUS_IGNORE);
                printf("Rank %d received: %s\n", rank, helloWorld);
            }
        }

    }

    MPI_Finalize();
    return 0;
}

您必须 运行 在两个进程上执行此代码。因为选择了 'MPI_THREAD_FUNNELED' 只有主线程进行 MPI 调用。

以下变量在 OpenMP 数据作用域位置指定 因为 gcc 版本 6.1.1 需要它。像 4.8 这样的旧版本不需要声明它们。

ompi_mpi_comm_world
ompi_mpi_char