代码之家  ›  专栏  ›  技术社区  ›  Evg

MPI2DouLyIt和C++结构

  •  0
  • Evg  · 技术社区  · 6 年前

    这个 MPI standard MPI_X_INT 具有 X = FLOAT, DOUBLE, ... . 让我们坚持下去 MPI_DOUBLE_INT 为了明确。其形式定义是:

    数据类型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 而不是 内景 ):

    例4.1 假设 Type = {(double, 0), (char, 8)} (一) 双重的 烧焦 双重的 必须在8的倍数的地址上严格对齐。然后,该数据类型的范围是16(9四舍五入为8的下一个倍数)。

    相应的C++结构是 struct DI { double d; int i; }; This answer 声称 struct 应包装以避免在 内景 . 但填充结构的大小是12(假设 sizeof(int) = 4 ),不可能使用它们的数组:

    constexpr auto count = 2;  // >1
    DI_packed di[count] = {...};
    MPI_Send(di, count, MPI_DOUBLE_INT, ...);  // wrong!
    

    有C++吗? 结构 放心 结构 定义一个包含手动添加尾部填充的压缩结构 烧焦 s、 这是对的吗?

    struct DI ,所以这个问题从实际的角度来说可能无关紧要,但我不确定。

    1 回复  |  直到 6 年前
        1
  •  2
  •   David Henty    6 年前

    也许你可以用 联盟

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

    i、 联合变量(Doubleint和Packdoubleint)总是16字节长,即使结构有不同的大小——我已经强制Packtmp使用特定于g++的属性取消添加。

        2
  •  0
  •   Jakob    4 年前

    你可以用 C++11's alignas keyword 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;
     }
    

    BTW:不确定,但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];                                              \
             ...
    
    推荐文章