我在 C API 中有 double A[B_ROWS][B_COLUMNS];
我使用了 stufflike:
MPI_Isend(&A[low_bound][0], (upper_bound - low_bound) * A_COLUMNS, MPI_DOUBLE, i, MASTER_TO_SLAVE_TAG + 2, MPI_COMM_WORLD, &request);
和
MPI_Recv(&A[low_bound][0], (upper_bound - low_bound) * A_COLUMNS, MPI_DOUBLE, 0, MASTER_TO_SLAVE_TAG + 2, MPI_COMM_WORLD, &status);
现在with boost::mpi我尝试:
world.isend(i, TO_SLAVE_TAG + 2, &A[low_bound][0], (upper_bound - low_bound) * A_COLUMNS);
和
world.recv(0, TO_SLAVE_TAG + 2, &A[low_bound][0], (upper_bound - low_bound) * A_COLUMNS);
但我的应用经常失败,例如:
rank 1 in job 10 master_39934 caused collective abort of all ranks
exit status of rank 1: killed by signal 11
这意味着 seg fault
,请注意原始 C 应用程序按需要工作,我当前更改的所有内容都是使用 api - 没有任何逻辑。
那么通过 boost::mpi 发送 2d C 样式数组的正确方法是什么?
最佳答案
假设我的盲目猜测是正确的,并且您在上面键入的内容是准确的,A
的大小与 A_COLUMNS
无关(相反,A
有 B_COLUMNS
)。如果是这样,下面的代码将修复这种“不同步”错误:
template<typename World, typename T>
void isend( World& w, int dest, int tag, T const* t, size_t n = 1) {
world.isend(dest, tag, &t, n);
}
template<typename World, typename T, size_t aSize>
void isend( World& w, int dest, int tag, T const (*arr1)[aSize], size_t n = 1) {
world.isend(dest, tag, &(*arr)[0], n*aSize);
}
template<typename World, typename T, size_t aSize, size_t bSize>
void isend( World& w, int dest, int tag, T const (*arr2)[aSize][bSize], size_t n = 1) {
world.isend(dest, tag, &(*arr)[0][0], n*aSize*bSize);
}
template<typename World, typename T>
void recv( World& w, int dest, int tag, T* t, size_t n = 1) {
world.recv(dest, tag, &t, n);
}
template<typename World, typename T, size_t aSize>
void recv( World& w, int dest, int tag, T (*arr1)[aSize], size_t n = 1) {
world.recv(dest, tag, &(*arr)[0], n*aSize);
}
template<typename World, typename T, size_t aSize, size_t bSize>
void recv( World& w, int dest, int tag, T (*arr2)[aSize][bSize], size_t n = 1) {
world.recv(dest, tag, &(*arr)[0][0], n*aSize*bSize);
}
对于一维和二维数组,上面的代码会计算出您真正想要发送多少份 T,而无需您手动维护它。
它甚至适用于切片,例如 &A[low_bound]、upper_bound-lower_bound
。
您可能需要注意的一件事是吹过数组的末尾。您的 C 代码很可能会超出数组的末尾,但那里没有任何重要的东西,所以它幸免于难。在 C++ 代码中,你可以在那里有一个对象,你死了而不是生存。
另一种方法可能是编写一个同时接受切片的上限和下限的函数,如下所示:
template<typename World, typename T, size_t N>
void isend_slice( World& w, int dest, int tag, T const (&t)[N], size_t start=0, size_t end=N ) {
Assert( end <= N && start < end );
isend(world, dest, tag, &(t[start]), end-start);
}
template<typename World, typename T, size_t N>
void recv_slice( World& w, int dest, int tag, T (&t)[N], size_t start=0, size_t end=N ) {
Assert( end <= N && start < end );
recv(world, dest, tag, &(t[start]), end-start);
}
在这种情况下,你直接传递一个数组,然后说你想从哪里开始和结束阅读。优点是我检查数组是否确实有要发送的数据,或数据到达的空间。
(这两个函数依赖上面的函数)
在分布式情况下,您希望为您的断言生成一种描述性的日志记录机制。
下面是上面代码的使用示例:
int array[10];
int array2[10][10];
isend(world, dest, tag+0, &int(7)); // tag is an int
isend(world, dest, tag+1, &array); // tag+1 is a 10 int array
isend(world, dest, tag+2, &array2); // tag+2 is a 100 int array
isend(world, dest, tag+1, &(array2[5])); // tag+1 is a 10 int array
isend_slice(world, tag+3, 0, array2, 7, 11); // asserts, but its a 40 int array
recv 也是如此。
关于c++ - 如何通过 Boost::MPI 发送 2d C 样式数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13773390/