使用 MPI Barrier 导致致命错误
Using of MPI Barrier lead to fatal error
我的简单 MPI 程序出现奇怪的行为。我花了时间自己寻找答案,但我做不到。我在这里提出了一些问题,例如 OpenMPI MPI_Barrier problems, MPI_SEND stops working after MPI_BARRIER, Using MPI_Bcast for MPI communication. I red MPI tutorial on mpitutorial。
我的程序只是修改从根进程广播的数组,然后将修改后的数组收集到一个数组中并打印出来。
所以,问题是,当我使用下面列出的未注释 MPI_Barrier(MPI_COMM_WORLD) 的代码时,我得到一个错误。
#include "mpi/mpi.h"
#define N 4
void transform_row(int* row, const int k) {
for (int i = 0; i < N; ++i) {
row[i] *= k;
}
}
const int root = 0;
int main(int argc, char** argv) {
MPI_Init(&argc, &argv);
int rank, ranksize;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &ranksize);
if (rank == root) {
int* arr = new int[N];
for (int i = 0; i < N; ++i) {
arr[i] = i * i + 1;
}
MPI_Bcast(arr, N, MPI_INT, root, MPI_COMM_WORLD);
}
int* arr = new int[N];
MPI_Bcast(arr, N, MPI_INT, root, MPI_COMM_WORLD);
//MPI_Barrier(MPI_COMM_WORLD);
transform_row(arr, rank * 100);
int* transformed = new int[N * ranksize];
MPI_Gather(arr, N, MPI_INT, transformed, N, MPI_INT, root, MPI_COMM_WORLD);
if (rank == root) {
for (int i = 0; i < ranksize; ++i) {
for (int j = 0; j < N ; j++) {
printf("%i ", transformed[i * N + j]);
}
printf("\n");
}
}
MPI_Finalize();
return 0;
}
线程数 > 1 时出现错误。错误:
PMPI_Barrier 中的致命错误:消息被截断,错误堆栈:
PMPI_Barrier(425) .....................: MPI_Barrier(MPI_COMM_WORLD) 失败
MPIR_Barrier_impl(332)................: 集体失败
MPIR_Barrier_impl(327) ...............:
MPIR_Barrier(292)......................:
MPIR_Barrier_intra(150)................:
barrier_smp_intra(111)................:
MPIR_Bcast_impl(1452)......:
MPIR_Bcast(1476)......................:
MPIR_Bcast_intra(1287) ...............:
MPIR_Bcast_二项式(239)......................:
MPIC_Recv(353)......................:
MPIDI_CH3U_Request_unpack_uebuf(568):消息被截断;收到 16 个字节,但缓冲区大小为 1
我知道缓冲区存在一些问题,但是当我使用 MPI_buffer_attach 将大缓冲区附加到 MPI 时它没有帮助。
看来我需要增加这个缓冲区,但我现在不知道该怎么做。
XXXXXX@XXXXXXXXX:~/test_mpi$ mpirun --version
HYDRA 构建细节:
Version: 3.2
Release Date: Wed Nov 11 22:06:48 CST 2015
所以请帮助我。
一个问题是 MPI_Bcast()
被 root
等级调用两次,而其他等级只调用一次。然后 root
等级使用未初始化的 arr
.
MPI_Barrier()
可能只会隐藏问题,但不能解决问题。
此外,请注意,如果 N
是 "large enough",则 root
等级调用的第二个 MPI_Bcast()
可能会挂起。
您可以通过以下方式修改 init/broadcast 阶段来解决这些问题。
int* arr = new int[N];
if (rank == root) {
for (int i = 0; i < N; ++i) {
arr[i] = i * i + 1;
}
MPI_Bcast(arr, N, MPI_INT, root, MPI_COMM_WORLD);
请注意,在这种情况下,您可以简单地在所有行列上初始化 arr
,这样您甚至不需要广播数组。
附带说明一下,MPI 程序通常
#include <mpi.h>
然后使用 mpicc
作为 compilation/linking
(这是一个包装器,在设置 include/library 路径并使用 MPI 库后调用真正的编译器)
我的简单 MPI 程序出现奇怪的行为。我花了时间自己寻找答案,但我做不到。我在这里提出了一些问题,例如 OpenMPI MPI_Barrier problems, MPI_SEND stops working after MPI_BARRIER, Using MPI_Bcast for MPI communication. I red MPI tutorial on mpitutorial。 我的程序只是修改从根进程广播的数组,然后将修改后的数组收集到一个数组中并打印出来。 所以,问题是,当我使用下面列出的未注释 MPI_Barrier(MPI_COMM_WORLD) 的代码时,我得到一个错误。
#include "mpi/mpi.h"
#define N 4
void transform_row(int* row, const int k) {
for (int i = 0; i < N; ++i) {
row[i] *= k;
}
}
const int root = 0;
int main(int argc, char** argv) {
MPI_Init(&argc, &argv);
int rank, ranksize;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &ranksize);
if (rank == root) {
int* arr = new int[N];
for (int i = 0; i < N; ++i) {
arr[i] = i * i + 1;
}
MPI_Bcast(arr, N, MPI_INT, root, MPI_COMM_WORLD);
}
int* arr = new int[N];
MPI_Bcast(arr, N, MPI_INT, root, MPI_COMM_WORLD);
//MPI_Barrier(MPI_COMM_WORLD);
transform_row(arr, rank * 100);
int* transformed = new int[N * ranksize];
MPI_Gather(arr, N, MPI_INT, transformed, N, MPI_INT, root, MPI_COMM_WORLD);
if (rank == root) {
for (int i = 0; i < ranksize; ++i) {
for (int j = 0; j < N ; j++) {
printf("%i ", transformed[i * N + j]);
}
printf("\n");
}
}
MPI_Finalize();
return 0;
}
线程数 > 1 时出现错误。错误:
PMPI_Barrier 中的致命错误:消息被截断,错误堆栈: PMPI_Barrier(425) .....................: MPI_Barrier(MPI_COMM_WORLD) 失败
MPIR_Barrier_impl(332)................: 集体失败
MPIR_Barrier_impl(327) ...............:
MPIR_Barrier(292)......................:
MPIR_Barrier_intra(150)................:
barrier_smp_intra(111)................:
MPIR_Bcast_impl(1452)......:
MPIR_Bcast(1476)......................:
MPIR_Bcast_intra(1287) ...............:
MPIR_Bcast_二项式(239)......................:
MPIC_Recv(353)......................:
MPIDI_CH3U_Request_unpack_uebuf(568):消息被截断;收到 16 个字节,但缓冲区大小为 1
我知道缓冲区存在一些问题,但是当我使用 MPI_buffer_attach 将大缓冲区附加到 MPI 时它没有帮助。
看来我需要增加这个缓冲区,但我现在不知道该怎么做。
XXXXXX@XXXXXXXXX:~/test_mpi$ mpirun --version
HYDRA 构建细节:
Version: 3.2
Release Date: Wed Nov 11 22:06:48 CST 2015
所以请帮助我。
一个问题是 MPI_Bcast()
被 root
等级调用两次,而其他等级只调用一次。然后 root
等级使用未初始化的 arr
.
MPI_Barrier()
可能只会隐藏问题,但不能解决问题。
此外,请注意,如果 N
是 "large enough",则 root
等级调用的第二个 MPI_Bcast()
可能会挂起。
您可以通过以下方式修改 init/broadcast 阶段来解决这些问题。
int* arr = new int[N];
if (rank == root) {
for (int i = 0; i < N; ++i) {
arr[i] = i * i + 1;
}
MPI_Bcast(arr, N, MPI_INT, root, MPI_COMM_WORLD);
请注意,在这种情况下,您可以简单地在所有行列上初始化 arr
,这样您甚至不需要广播数组。
附带说明一下,MPI 程序通常
#include <mpi.h>
然后使用 mpicc
作为 compilation/linking
(这是一个包装器,在设置 include/library 路径并使用 MPI 库后调用真正的编译器)