- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
考虑下面的程序,它应该对 double
进行一些愚蠢的添加:
#include <iostream>
#include <vector>
#include <mpi.h>
void add(void* invec, void* inoutvec, int* len, MPI_Datatype*)
{
double* a = reinterpret_cast <double*> (inoutvec);
double* b = reinterpret_cast <double*> (invec);
for (int i = 0; i != *len; ++i)
{
a[i] += b[i];
}
}
int main(int argc, char* argv[])
{
MPI_Init(&argc, &argv);
std::vector<double> buffer = { 2.0, 3.0 };
MPI_Op operation;
MPI_Op_create(add, 1, &operation);
MPI_Datatype types[1];
MPI_Aint addresses[1];
int lengths[1];
int count = 1;
MPI_Get_address(buffer.data(), &addresses[0]);
lengths[0] = buffer.size();
types[0] = MPI_DOUBLE;
MPI_Datatype type;
MPI_Type_create_struct(count, lengths, addresses, types, &type);
MPI_Type_commit(&type);
MPI_Allreduce(MPI_IN_PLACE, MPI_BOTTOM, 1, type, operation, MPI_COMM_WORLD);
MPI_Type_free(&type);
MPI_Op_free(&operation);
MPI_Finalize();
std::cout << buffer[0] << " " << buffer[1] << "\n";
}
因为这是更大程序的一部分,我想发送的数据 1) 在堆上,2) 由不同的类型组成,所以我认为我必须使用用户定义的类型。
现在这里一定有问题,因为程序在使用 mpirun -n 2 ./a.out
运行时崩溃了。来自 gdb 的回溯是:
#0 __memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:158
#1 0x00007ffff65de460 in non_overlap_copy_content_same_ddt () from /usr/local/lib/libopen-pal.so.6
#2 0x00007ffff180a69b in ompi_coll_tuned_allreduce_intra_recursivedoubling () from /usr/local/lib/openmpi/mca_coll_tuned.so
#3 0x00007ffff793bb8b in PMPI_Allreduce () from /usr/local/lib/libmpi.so.1
#4 0x00000000004088b6 in main (argc=1, argv=0x7fffffffd708) at mpi_test.cpp:39
第 39 行是 MPI_Allreduce
调用。这可能是一个愚蠢的错误,但在盯着它看了几个小时之后,我仍然没有看到它。有人发现错误吗?谢谢!
最佳答案
编辑:Open MPI 在执行就地缩减为时如何处理具有非零下限的类型(例如您在使用绝对地址时创建的类型)存在一个错误全部。它似乎存在于所有版本中,包括开发分支。可以通过关注 issue on GitHub 来跟踪状态.
您的 add
运算符是错误的,因为您没有考虑数据类型的下限。一个合适的解决方案是这样的:
void add(void* invec, void* inoutvec, int* len, MPI_Datatype* datatype)
{
MPI_Aint lb, extent;
MPI_Type_get_true_extent(*datatype, &lb, &extent);
double* a = reinterpret_cast <double*> (reinterpret_cast <char*>(inoutvec) + lb);
double* b = reinterpret_cast <double*> (reinterpret_cast <char*>(invec) + lb);
for (int i = 0; i != *len; ++i)
{
a[i] += b[i];
}
}
这将正确访问数据,但仍然是错误的。 *len
将是 1,因为这是您传递给 MPI_Allreduce
的值,但每个元素后面有两个 double 。正确编写的运算符将使用类型自省(introspection)机制来获取 double block 的长度并将 *len
乘以它,或者简单地将 vector 长度硬编码为二:
for (int i = 0; i < 2*(*len); i++)
{
a[i] += b[i];
}
关于c++ - 具有用户定义函数和 MPI_BOTTOM 的 Allreduce,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37664742/
考虑下面的程序,它应该对 double 进行一些愚蠢的添加: #include #include #include void add(void* invec, void* inoutvec, i
我是一名优秀的程序员,十分优秀!