使用MPI_Datatype进行C转换

时间:2016-06-24 07:35:24

标签: c casting mpi

我有一个存储在不透明结构中的数组列表,它们的类型都不同。我有一个函数可以将它们还给我,并将它们存储为void *数组。我有一个其他功能,他给我的类型为MPI_Datatype

当我操纵这些数组时,我将它们转换为byte *。但是byte是一个8位长的数据类型,而我的数组类型可以是16位,32位或64位长。

那么,这些是否会在访问好的单元格时出现问题,并“使用”大量的位?

如果是,有没有办法使用存储为MPI_Datatype的类型来投射我的数组?

这是一个例子

void * intab;
void * out1tab;
void * out2tab;
int tag;
int j;
MPI_Datatype type;
Iterator vaiter;

IteratInit (inStruct, &vaiter);

while (IteratHasMore(&vaiter)) {

  tag = IteratCurTagNum (&vaiter);
  type = IteratCurTypeVal (&vaiter);

  ValueLink (out1Struct, (void**) &out1tab, type, tag));
  ValueLink (out2Struct, (void**) &out2tab, type, tag));

  intab = IteratCurValue (&vaiter);

  for (j = baseval ; j < nbr + baseval ; ++j) {
    if (flagtab[j] == 1) {
      ((byte*)out1tab)[j] = ((byte*)intab)[j];
    }
    else {
      ((byte*)out2tab)[j] = ((byte*)intab)[j];
    }
  }

  IteratNext(&vaiter);
}

2 个答案:

答案 0 :(得分:3)

MPI数据类型是告诉MPI在构造和解构消息时如何访问和解释内存内容的蓝图。 MPI只关心二进制内容的布局,并且对与其对应的语言类型一无所知,比如它是一个数组还是一个相同类型元素的结构,如果它是一个结构,它的字段是如何命名的。 MPI数据类型只是MPI库管理的不透明结构的句柄。

虽然几乎不可能用MPI数据类型构造语言类型,至少不能用C等静态类型语言构建语言类型,但仍然可以查询MPI数据类型的内部结构并对元素中的元素执行操作。记忆。程序大致如下(被警告 - 这远非微不足道):

  • 您应首先使用MPI_Type_get_envelope获取数据类型信封,它为您提供有关用于创建数据类型的MPI数据类型构造函数调用(组合器)的一些基本信息。对于使用MPI_Type_struct(不建议使用)和MPI_Type_create_struct创建的结构数据类型,组合器将为MPI_COMBINER_STRUCT。对于使用MPI_Type_contiguous创建的连续(数组)数据类型,组合器将为MPI_COMBINER_CONTIGUOUS,对于使用MPI_Type_vector创建的向量数据类型(跨步块),组合器将为MPI_COMBINER_VECTOR。完整列表可以在MPI标准或上面链接的Open MPI手册页中找到。

  • 鉴于MPI_Type_get_envelope的结果,您应该分配足够大的整数,偏移量和MPI数据类型的数组,然后调用MPI_Type_get_contents来获取数据类型构造函数的实际参数。

  • 由于MPI允许实际上无限制地嵌套数据类型,因此您应该进一步递归到每种数据类型,直到到达MPI_COMBINER_NAMED的组合器,该组合器对应于预定义的MPI数据类型。从那以后,基本语言类型可以简单地进行。

上面的过程将为您提供基本语言类型列表及其相对于数据缓冲区开头的偏移量,即所谓的 typemap 。您可以使用每个元素的偏移量和大switch语句来相应地处理它。您仍然无法在源代码中执行强制转换。后者在一些动态脚本语言中是可能的,它允许通过使用一些内省机制来构造语言类型。

最好的情况是,如果程序中使用的MPI数据类型有限,则应使用带有MPI数据类型句柄的switch运算符,并单独转换为相应的语言类型,最好不要使用某些奇怪的预处理器宏观解决方案。

答案 1 :(得分:-1)

这样的东西?

#define COPY_ELEMENT(type)                     \
do {                                           \
    if (flagtab[j] == 1) {                     \
      ((type*)out1tab)[j] = ((type*)intab)[j]; \
    }                                          \
    else {                                     \
      ((type*)out2tab)[j] = ((type*)intab)[j]; \
    }                                          \
    j += sizeof(type);                         \                                                                     
} while(0)

for (j = baseval ; j < nbr + baseval ; ) { // no j++, j is advanced by COPY_ELEMENT
    switch (type) {
    case MPI_BYTE:
        COPY_ELEMENT(byte);
        break;
    case MPI_SHORT:
        COPY_ELEMENT(short);
        break;
    case MPI_INT:
        COPY_ELEMENT(int);
        break;
    // all cases?
    }
}

(警告:未对此进行测试)