MPI_DOUBLE_INT and C++ struct
MPI_DOUBLE_INT and C++ struct
MPI标准定义了一系列MPI_X_INT
X = FLOAT, DOUBLE, ...
的数据类型。让我们坚持MPI_DOUBLE_INT
确定性。其正式定义是:
"(第180页(数据类型MPI_DOUBLE_INT好像由以下指令序列定义:
block[0] = 1; block[1] = 1; disp[0] = 0; disp[1] = sizeof(double); type[0] = MPI_DOUBLE; type[1] = MPI_INT; MPI_TYPE_CREATE_STRUCT(2, block, disp, type, MPI_DOUBLE_INT);
该定义意味着double
和int
之间没有填充。该标准还断言这种类型的总大小应为 16,示例如下(对于char
而不是int
(:
(第85页( 例4.1假设
Type = {(double, 0), (char, 8)}
(位移为零时double
,位移 8 时char
(。此外,假设double
必须在 8 的倍数地址处严格对齐。然后,此数据类型的范围为 16(9 舍入到 8 的下一个倍数(。
相应的C++结构struct DI { double d; int i; };
。这个答案断言,struct
应该打包以避免在double
和int
之间填充。但是一个填充结构的大小是 12(假设sizeof(int) = 4
(,并且不可能使用它们的数组:
constexpr auto count = 2; // >1
DI_packed di[count] = {...};
MPI_Send(di, count, MPI_DOUBLE_INT, ...); // wrong!
是否有与 MPI 定义完全对应并且可以在 MPI 代码中安全、可移植地使用的C++struct
?似乎唯一有保证的使用struct
方法是定义一个带有手动添加尾部填充char
s的填充结构。这是对的吗?
作为旁注,在我的机器上,MSVC 和 GCC 都为解压缩的struct DI
生成"MPI 兼容"布局,因此从实际的角度来看,这个问题可能无关紧要,但我不确定。
也许你可以使用联合来做到这一点?
如果使用 g++ 编译以下内容并运行
#include <iostream>
using namespace std;
int main()
{
typedef struct {double x; int i;} Tmp;
typedef union {char pad[16]; Tmp dint;} Doubleint;
Doubleint value;
value.dint.x = 3.14;
value.dint.i = 6;
cout << "sizeof(Tmp) = " << sizeof(Tmp) << endl;
cout << "sizeof(Doubleint) = " << sizeof(Doubleint) << endl;
typedef struct {double x; int i;} __attribute__((packed)) Packtmp;
typedef union {char pad[16]; Packtmp dint;} Packdoubleint;
Packdoubleint packvalue;
packvalue.dint.x = 6.12;
packvalue.dint.i = 9;
cout << "sizeof(Packtmp) = " << sizeof(Packtmp) << endl;
cout << "sizeof(Packdoubleint) = " << sizeof(Packdoubleint) << endl;
return 0;
}
你得到
sizeof(Tmp) = 16
sizeof(Doubleint) = 16
sizeof(Packtmp) = 12
sizeof(Packdoubleint) = 16
即联合变量(Doubleint 和 Packdoubleint(始终为 16 字节长,即使结构具有不同的大小 - 我强制使用 g++ 特定的属性取消填充 Packtmp。
您可以使用C++11的alignas关键字来修复对齐方式(gcc 9.2,clang 9.0.0,icc 19.0.1(:
int main() {
#pragma pack(push, 1)
struct alignas(alignof(double)) pair {
double d;
int i;
};
#pragma pack(pop)
static_assert(sizeof(double) == 8, "");
static_assert(sizeof(int) == 4, "");
static_assert(sizeof(double)+sizeof(int) == 12, "");
static_assert(sizeof(pair) == 16, "");
static_assert(alignof(double) == 8, "");
static_assert(alignof(pair) == 8, "");
return 0;
}
如果没有alignas
打包结构在 x86-64 Linux 上与 gcc 9.2、clang 9.0.0 和 icc 19.0.1 上存在对齐问题:
int main() {
#pragma pack(push, 1)
struct pair {
double d;
int i;
};
#pragma pack(pop)
static_assert(sizeof(double) == 8, "");
static_assert(sizeof(int) == 4, "");
static_assert(sizeof(double)+sizeof(int) == 12, "");
static_assert(sizeof(pair) == 12, "");
static_assert(alignof(double) == 8, "");
static_assert(alignof(pair) == 1, ""); // !!!
return 0;
}
顺便说一句:不确定,但OpenMPI可能能够在ompi/datatype/ompi_datatype_module.c中的数据类型定义期间处理非打包结构:
#define DECLARE_MPI2_COMPOSED_STRUCT_DDT( PDATA, MPIDDT, MPIDDTNAME, type1, type2, MPIType1, MPIType2, FLAGS)
do {
struct { type1 v1; type2 v2; } s[2];
ompi_datatype_t *types[2], *ptype;
int bLength[2] = {1, 1};
ptrdiff_t base, displ[2];
types[0] = (ompi_datatype_t*)ompi_datatype_basicDatatypes[MPIType1];
types[1] = (ompi_datatype_t*)ompi_datatype_basicDatatypes[MPIType2];
base = (ptrdiff_t)(&(s[0]));
displ[0] = (ptrdiff_t)(&(s[0].v1));
displ[0] -= base;
displ[1] = (ptrdiff_t)(&(s[0].v2));
displ[1] -= base;
ompi_datatype_create_struct( 2, bLength, displ, types, &ptype );
displ[0] = (ptrdiff_t)(&(s[1]));
displ[0] -= base;
if( displ[0] != (displ[1] + (ptrdiff_t)sizeof(type2)) )
ptype->super.ub = displ[0];
...
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- C++Union/Struct位域的实现和可移植性
- 如何在c++中定义以struct为数据成员的类中的构造函数
- 结构体 S { int align; } 之间的区别;(struct 关键字后的名称)和 struct { int al
- struct.error:解压缩 C++ 结构时,解包需要 288 字节的缓冲区
- 错误:"Left of getValue must have class/struct/union"
- 在 SVM-Struct 中未定义对 sqrt 的引用(已使用 -lm)
- 数据类型"struct seq<0, 1, 2>{}"含义是什么?
- 附加使用 Struct 作为"multikey"并将 std::vector 用作映射值的映射
- QML/C++/QObject Struct Copy
- 如何在 cpp 中解压缩数字,如果它们是使用 struct.pack(fmt, v1, v2, ..) 打包在 pyth
- Msgpack能否提供更好的性能和与Python的struct.pack()相同的功能?
- 将向量传递给<struct> Lua 表
- MPI_DOUBLE_INT and C++ struct
- C++ 中的"template <typename From, typename Tag> struct Alias;"是什么?
- 如何使用Struct打印交换函数
- 返回类型为struct的函数每次调用时都不返回任何内容
- 对struct::struct的未定义引用是什么意思
- 在c++Primer中使用Struct和Vector时出现错误C2661