MPI的数据类型适用于花车,而不是双打。它是一个对齐问题? [英] MPI derived datatype works for floats, but not for doubles. Is it an alignment issue?

查看:212
本文介绍了MPI的数据类型适用于花车,而不是双打。它是一个对齐问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须与正在沟通与MPI的数据类型的帮助下,C-结构,一个奇怪的问题。以下作品中的例子。它简单的发送由一个整数加4 浮动值的消息。

I have a weird issue related to a C-structure that is communicated with the help of an MPI derived datatype. The example below works; it simply sends a message consisting of one integer plus 4 float values.

Minmum的例子:

#include <mpi.h>
#include <stdio.h>

int main(int argc, char *argv[]) {
    MPI_Init(&argc, &argv);

    int i, rank, tag = 1;
    MPI_Status status;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    // Array of doubles plus element count
    typedef struct {
        int row;
        float elements[4];
    } My_array;

    // Derived datatype for an array of doubles plus element count
    MPI_Datatype MY_ARRAY_TYPE;
    const int nr_blocks = 2;
    int blocklengths[2] = {1, 4};
    MPI_Datatype oldtypes[2] = {MPI_INT, MPI_FLOAT};
    MPI_Aint extent, lb;
    MPI_Type_get_extent(MPI_INT, &lb, &extent);
    MPI_Aint displacements[2] = {0, extent};
    MPI_Type_create_struct(nr_blocks, blocklengths, displacements,
                       oldtypes, &MY_ARRAY_TYPE);
    MPI_Type_commit(&MY_ARRAY_TYPE);

   if(rank == 0) {
        My_array array1  = {3, 3.1, 3.2, 3.3, 3.4};
        MPI_Send(&array1, 1, MY_ARRAY_TYPE, 1, tag, MPI_COMM_WORLD);
   }
   if(rank == 1) {
        My_array array2;
        MPI_Recv(&array2, 1, MY_ARRAY_TYPE, 0, tag, MPI_COMM_WORLD, &status);
        printf("Rank %d received elements of row %d:\n", rank, array2.row);
        for(i = 0; i < 4; i++)
            printf("\t%.1f\n", array2.elements[i]);
    }
    MPI_Type_free(&MY_ARRAY_TYPE);
    MPI_Finalize();
}

如果你有机会到MPI安装,例如可以通过 mpicc -o例如example.c 编译和的mpirun -np运行例如2
输出应该是

If you have access to an MPI installation, the example can be compiled by mpicc -o example example.c and run by mpirun -np 2 example. The output should be

Rank 1 received elements of row 3:
    3.1
    3.2
    3.3
    3.4

问题:
现在,当浮动的阵s被改为数组双击 S,并据此 MPI_FLOAT MPI_DOUBLE ,我得到一个错误的结果。

The problem: Now when the array of floats is changed to an array of doubles, and accordingly MPI_FLOATto MPI_DOUBLE, I get a wrong result.

这code:

#include <mpi.h>
#include <stdio.h>

int main(int argc, char *argv[]) {
    MPI_Init(&argc, &argv);

    int i, rank, tag = 1;
    MPI_Status status;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    // Array of doubles plus element count
    typedef struct {
        int row;
        double elements[4];
    } My_array;

    // Derived datatype for an array of doubles plus element count
    MPI_Datatype MY_ARRAY_TYPE;
    const int nr_blocks = 2;
    int blocklengths[2] = {1, 4};
    MPI_Datatype oldtypes[2] = {MPI_INT, MPI_DOUBLE};
    MPI_Aint extent, lb;
    MPI_Type_get_extent(MPI_INT, &lb, &extent);
    MPI_Aint displacements[2] = {0, extent};
    MPI_Type_create_struct(nr_blocks, blocklengths, displacements,
                       oldtypes, &MY_ARRAY_TYPE);
    MPI_Type_commit(&MY_ARRAY_TYPE);

   if(rank == 0) {
        My_array array1  = {3, 3.1, 3.2, 3.3, 3.4};
        MPI_Send(&array1, 1, MY_ARRAY_TYPE, 1, tag, MPI_COMM_WORLD);
   }
   if(rank == 1) {
        My_array array2;
        MPI_Recv(&array2, 1, MY_ARRAY_TYPE, 0, tag, MPI_COMM_WORLD, &status);
        printf("Rank %d received elements of row %d:\n", rank, array2.row);
        for(i = 0; i < 4; i++)
            printf("\t%.1f\n", array2.elements[i]);
    }
    MPI_Type_free(&MY_ARRAY_TYPE);
    MPI_Finalize();
}

生产:

Rank 1 received elements of row 3:
    3.1
    3.2
    3.3
    0.0

我尝试了一下周围,在结构和派生数据类型使用其它数据(例如,整数而不是一个数组, INT / MPI_INT 而不是浮动 / MPI_FLOAT 等),并看到问题使用时,双打只出现。这让我怀疑这可能是各种各样的对齐问题 - 但我卡在那里。 MPI应自动照顾比对。

I tried around a bit, using other data in the struct and the derived datatype (e.g., an array of integers instead of just one, int/MPI_INT instead of float/MPI_FLOAT, etc.) and saw that the problem arises only when doubles are used. Which makes me suspect that this might be an alignment issue of sorts - but I am stuck there. MPI should take care of alignments automatically.

问:为什么用浮动 / MPI_FLOAT 上面的例子中的工作,但与双击 / MPI_DOUBLE ,我该如何解决这个问题?

Question: Why does the above example work with float/MPI_FLOAT, but not with double/MPI_DOUBLE and how can I fix it?

有些机细节,可能是相关的:

Some machine specifics that might be relevant:


  • CPU:AMD皓龙6134

  • 地址尺寸:48位

  • 对齐:64

  • 编译器:GCC 4.4.7

  • MPI库:(可惜)厂商特定

编辑:在弗拉基米尔·F中的意见建议,我增加了code不起作用

as suggested in the comments by Vladimir F, I added the code that does not work.

推荐答案

我只是发现了问题所在:它确实是对齐。第二code上市产生正确的第3双打也不过是一个奇怪的巧合...通过使用 MPI_INT 为以下值的偏移量的扩大,我认为不会有什么填充。这是更好地计算这样的偏移量:

I just found out what the problem is: it is indeed alignment. That the second code listing produces the first 3 doubles correctly is nothing but a weird coincidence...By using the extend of MPI_INT as the offset of the following value, I assumed that there would be no padding. It is better to compute the offsets like this:

#include <stddef.c> 
...
MPI_Datatype MY_ARRAY_TYPE;
const int nr_blocks = 2;
int blocklengths[2] = {1, 4};
MPI_Datatype oldtypes[2] = {MPI_INT, MPI_DOUBLE};
MPI_Aint displacements[2];
displacements[0] = offsetof(My_array, row);
displacements[1] = offsetof(My_array, elements);
MPI_Type_create_struct(nr_blocks, blocklengths, displacements,
                   oldtypes, &MY_ARRAY_TYPE);
MPI_Type_commit(&MY_ARRAY_TYPE);
...

我真的有兴趣看看它是如何制定出这样......为什么我们拿到3正确的价值观和一个0.0?由于取向是关闭的4个字节和双打重新由8个字节我的平台,为什么我没有得到一些随机数上psented $ P $?如何前3已经去codeD正确,如果他们每人拿了一张双人床再加上接下来的双重的上4下4个字节?

I'd really be interested to see how it can work out this way...why do we get 3 correct values and one 0.0? Since the alignment was off by 4 bytes and doubles are represented by 8 bytes on my platform, why didn't I get some random numbers? How can the first 3 have been decoded correctly if they each took the lower 4 bytes of one double plus the upper 4 of the next double?

这篇关于MPI的数据类型适用于花车,而不是双打。它是一个对齐问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆