我试图将注意力集中在用户创建的MPI数据类型上,所以我创建了一个小型演示程序,该程序在集群的两个节点上运行。
该程序旨在让第一个进程创建一个矩阵,该矩阵按列顺序存储在线性存储区域内,然后通过首先创建适当的“矩阵行”数据类型,将该矩阵的多行发送给第二个进程。我知道这在某种程度上是人为的,我只是打算将其作为MPI_Type_vector
的简单用例,不必担心这通常是否应该以不同的方式进行。
现在在这种特殊情况下,我试图将最后一个发送到在第一个过程中构造的矩阵的行中,并在第二个过程中分配的矩阵的前两行中接收/存储它们。但是,这会导致接收操作失败,并显示以下信息:
... free(): invalid pointer
======= Backtrace: =========
/usr/lib64/libc.so.6(+0x7c619)[0x2b60c02e0619]
/sw/global/compilers/intel/2018/impi/2018.1.163/lib6/libmpi.so.12(+0x15ad6d)[0x2b60bee0fd6d]
/sw/global/compilers/intel/2018/impi/2018.1.163/lib64/libmpi.so.12(MPI_Recv+0x6b0)[0x2b60bf0e4020]
...
这是源代码,我正在使用icc 18.0.1
进行编译,并在(物理)Linux集群上运行它。我的代码中有明显的错误吗?
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
/* initialize MPI */
MPI_Init(NULL, NULL);
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
/* create datatype */
MPI_Datatype row_type;
if (MPI_Type_vector(3, 1, 3, MPI_INT, &row_type) != MPI_SUCCESS)
return 1;
if (MPI_Type_commit(&row_type) != MPI_SUCCESS)
return 2;
/* allocate dummy data */
int *matrix = calloc(3 * 3, sizeof(int));
if (world_rank == 0) {
int data = 1;
for (int c = 0; c < 3; ++c) {
for (int r = 0; r < 3; ++r)
matrix[c * 3 + r] = data++;
}
/* print ingoing data */
for (int i = 0; i < 3 * 3; ++i)
printf("0: %d => %d\n", i, matrix[i]);
if (MPI_Send(&matrix[1], 2, row_type, 1, 0, MPI_COMM_WORLD) != MPI_SUCCESS)
return 3;
} else {
if (MPI_Recv(matrix, 2, row_type, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE) != MPI_SUCCESS)
return 4;
/* print received data */
for (int i = 0; i < 3 * 3; ++i)
printf("1: %d => %d\n", i, matrix[i]);
}
/* clean up */
free(matrix);
MPI_Type_free(&row_type);
MPI_Finalize();
return 0;
}
编辑:这个问题似乎与例如Sending columns of a matrix using MPI_Scatter。接受的答案很好地说明了问题,很容易理解为什么这会导致我的程序崩溃。