首页 > 解决方案 > MPI_DOUBLE_INT 和 C++ 结构

问题描述

MPI标准使用MPI_X_INT. _ X = FLOAT, DOUBLE, ...让我们坚持下去MPI_DOUBLE_INT。它的正式定义是:

(p. 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,示例为(forchar而不是int):

(p.85) 例 4.1假设Type = {(double, 0), (char, 8)}(adouble在位移 0,然后是 achar在位移 8)。此外,假设doubles 必须在 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!

是否有struct与 MPI 定义完全对应并且可以在 MPI 代码中安全且可移植地使用的 C++?似乎唯一有保证的使用方法struct是使用手动添加的尾部填充来定义打包结构char。这个对吗?

附带说明一下,在我的机器上,MSVC 和 GCC 都为 unpacked 生成“MPI 兼容”布局struct DI,因此从实际角度来看,这个问题可能无关紧要,但我不确定。

标签: c++structmpipacking

解决方案


也许您可以使用union来做到这一点?

如果您使用 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。


推荐阅读