最大消息长度 MPI_Type_vector 和 MPI_Gather
Maximum message length MPI_Type_vector and MPI_Gather
当我尝试将具有 超过 750 个元素的双精度类型数组收集到表示矩阵的数组中时,我收到错误消息 "An error occurred in MPI_Gather"。正在收集的数组应该代表矩阵的列,并且由于矩阵的构造使得行在内存中是连续的,所以我将派生数据类型定义为列向量并调用 MPI_Gather 如下:
for (i = 0; i < k; i++) {
MPI_Gather(&Q_vector[i*m], m, MPI_DOUBLE, &Q[i*size], 1, vector_m, 0, MPI_COMM_WORLD);
}
其中k是向量的个数,m是每个向量的长度(矩阵的行数), size 是进程数,vector_m 是这样构造的派生数据类型:
MPI_Type_vector(m, 1, n, MPI_DOUBLE, &vector_m_type);
MPI_Type_create_resized(vector_m_type, 0, sizeof(double), &vector_m);
MPI_Type_commit(&vector_m);
其中 n 是矩阵中的列数。
这在 m > 750 之前工作正常。例如,如果 m = 751 发生错误(751 个双精度类型的元素).它不依赖于 n 的值。我完全更改了算法,以便矩阵的列连续存储在内存中,而不是通过完全避免派生数据类型来解决问题,但我仍然很好奇为什么会发生这种情况。
计算机规格:
CPU:英特尔(R) 酷睿(TM) i7-4790K CPU @ 4.00GHz
内存:8GB
OS: Windows 10 家 64 位
编译器:gcc 6.4.0
我用的是 Cygwin。
有时会打印此错误消息:
”
通信器 MPI_COMM_WORLD
上的进程 [52635822596882433,77309411328] 报告的 MPI_Gather 发生错误
MPI_ERR_IN_STATUS: 状态错误代码
MPI_ERRORS_ARE_FATAL(此通信器中的进程现在将中止,并且可能会中止您的 MPI 作业)
“
重现错误的最小工作示例代码:
#include <stdio.h>
#include <mpi.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int n, m, size, rank, i, j, k;
double *Q, *Q_vector;
MPI_Datatype vector_m_type, vector_m;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
m = atoi(argv[1]);
n = atoi(argv[2]);
if (rank == 0) {
Q = (double *)malloc(m*n*sizeof(double));
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
Q[i*n+j] = drand48()*10;
}
}
}
// k = number of (column) vectors per process
k = n/size;
Q_vector = (double *)malloc(k*m*sizeof(double));
MPI_Type_vector(m, 1, n, MPI_DOUBLE, &vector_m_type);
MPI_Type_create_resized(vector_m_type, 0, sizeof(double), &vector_m);
MPI_Type_commit(&vector_m);
for (i = 0; i < k; i++) {
MPI_Scatter(&Q[i*size], 1, vector_m, &Q_vector[i*m], m, MPI_DOUBLE, 0, MPI_COMM_WORLD);
}
for (i = 0; i < k; i++) {
MPI_Gather(&Q_vector[i*m], m, MPI_DOUBLE, &Q[i*size], 1, vector_m, 0, MPI_COMM_WORLD);
}
if (rank == 0) {
printf("Success!\n");
free(Q);
}
free(Q_vector);
MPI_Finalize();
}
编译并运行像这样:
mpicc -o test MPI_Type_vector_test.c -lmpi -lm
mpirun -np 8 ./test 751 750
这是 Open MPI 中的一个 known issue,当集体操作使用匹配的签名但数据类型不同时会发生
(例如,一方面是一个向量,另一方面是几个元素)。
解决此问题的最简单方法是禁用 coll/tuned
模块
mpirun --mca coll ^tuned -np 8 ./test 751 750
另一种选择是重写您的代码并使用描述行的其他派生数据类型(而不是使用 m
元素)
当我尝试将具有 超过 750 个元素的双精度类型数组收集到表示矩阵的数组中时,我收到错误消息 "An error occurred in MPI_Gather"。正在收集的数组应该代表矩阵的列,并且由于矩阵的构造使得行在内存中是连续的,所以我将派生数据类型定义为列向量并调用 MPI_Gather 如下:
for (i = 0; i < k; i++) {
MPI_Gather(&Q_vector[i*m], m, MPI_DOUBLE, &Q[i*size], 1, vector_m, 0, MPI_COMM_WORLD);
}
其中k是向量的个数,m是每个向量的长度(矩阵的行数), size 是进程数,vector_m 是这样构造的派生数据类型:
MPI_Type_vector(m, 1, n, MPI_DOUBLE, &vector_m_type);
MPI_Type_create_resized(vector_m_type, 0, sizeof(double), &vector_m);
MPI_Type_commit(&vector_m);
其中 n 是矩阵中的列数。
这在 m > 750 之前工作正常。例如,如果 m = 751 发生错误(751 个双精度类型的元素).它不依赖于 n 的值。我完全更改了算法,以便矩阵的列连续存储在内存中,而不是通过完全避免派生数据类型来解决问题,但我仍然很好奇为什么会发生这种情况。
计算机规格:
CPU:英特尔(R) 酷睿(TM) i7-4790K CPU @ 4.00GHz
内存:8GB
OS: Windows 10 家 64 位
编译器:gcc 6.4.0
我用的是 Cygwin。
有时会打印此错误消息:
” 通信器 MPI_COMM_WORLD
上的进程 [52635822596882433,77309411328] 报告的 MPI_Gather 发生错误MPI_ERR_IN_STATUS: 状态错误代码 MPI_ERRORS_ARE_FATAL(此通信器中的进程现在将中止,并且可能会中止您的 MPI 作业) “
重现错误的最小工作示例代码:
#include <stdio.h>
#include <mpi.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int n, m, size, rank, i, j, k;
double *Q, *Q_vector;
MPI_Datatype vector_m_type, vector_m;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
m = atoi(argv[1]);
n = atoi(argv[2]);
if (rank == 0) {
Q = (double *)malloc(m*n*sizeof(double));
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
Q[i*n+j] = drand48()*10;
}
}
}
// k = number of (column) vectors per process
k = n/size;
Q_vector = (double *)malloc(k*m*sizeof(double));
MPI_Type_vector(m, 1, n, MPI_DOUBLE, &vector_m_type);
MPI_Type_create_resized(vector_m_type, 0, sizeof(double), &vector_m);
MPI_Type_commit(&vector_m);
for (i = 0; i < k; i++) {
MPI_Scatter(&Q[i*size], 1, vector_m, &Q_vector[i*m], m, MPI_DOUBLE, 0, MPI_COMM_WORLD);
}
for (i = 0; i < k; i++) {
MPI_Gather(&Q_vector[i*m], m, MPI_DOUBLE, &Q[i*size], 1, vector_m, 0, MPI_COMM_WORLD);
}
if (rank == 0) {
printf("Success!\n");
free(Q);
}
free(Q_vector);
MPI_Finalize();
}
编译并运行像这样:
mpicc -o test MPI_Type_vector_test.c -lmpi -lm
mpirun -np 8 ./test 751 750
这是 Open MPI 中的一个 known issue,当集体操作使用匹配的签名但数据类型不同时会发生 (例如,一方面是一个向量,另一方面是几个元素)。
解决此问题的最简单方法是禁用 coll/tuned
模块
mpirun --mca coll ^tuned -np 8 ./test 751 750
另一种选择是重写您的代码并使用描述行的其他派生数据类型(而不是使用 m
元素)