首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为包含动态数组的结构创建MPI类型

为包含动态数组的结构创建MPI类型
EN

Stack Overflow用户
提问于 2015-10-03 23:28:58
回答 1查看 2.1K关注 0票数 2

我试图发送一个结构,其中一个成员作为动态数组,但这个数组似乎没有正确发送。对怎么做有什么建议吗?

这就是我所拥有的:

代码语言:javascript
运行
复制
struct bar
{
    int a;
    int b;
    int* c;
};

void defineMPIType(MPI_Datatype* newType, int cLen, struct bar* msg)
{
    int blockLengths[3] = {1, 1, cLen};
    MPI_Datatype types[3] = {MPI_INT, MPI_INT, MPI_INT};
    MPI_Aint offsets[3];

    MPI_Aint addrB, addrC;
    MPI_Address(&(msg->b), &addrB);
    MPI_Address(msg->c, &addrC);

    offsets[0] = offsetof(struct bar, a);
    offsets[1] = offsetof(struct bar, b);
    offsets[2] = addrC - addrB; 

    MPI_Type_create_struct(3, blockLengths, offsets, types, newType);
    MPI_Type_commit(newType);
}

void main(int argc, char* argv[])
{   
    MPI_Init(&argc, &argv);
    int rank, p;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &p);

    int cLen = argv[0];    
    MPI_Datatype MPI_BAR_TYPE;

    struct bar* msg = malloc(sizeof(*msg)); 
    msg->c =  malloc(sizeof(int) * cLen);
    defineMPIType(&MPI_BAR_TYPE, cLen, msg);

    if (rank == 0)
    {
        msg->a = 1;
        msg->b = 2;
        for (int i = 0; i < cLen; ++i)
            msg->c[i] = i;
        MPI_Send(msg, 1, MPI_BAR_TYPE, 1, 111, MPI_COMM_WORLD); 
    }
    else
    {
        MPI_Status stat;        
        MPI_Recv(msg, 1, MPI_BAR_TYPE, 0, 111, MPI_COMM_WORLD, &stat);      
    }

    printf("Rank %d has c = [", rank);
    for (int i = 0; i < cLen; ++i)
        printf("%d, ", msg->c[i]);
    printf("]\n");

    free(msg);
    MPI_Type_free(&MPI_BAR_TYPE);
    MPI_Finalize();
}

ab成员被正确发送,但c没有。

EN

Stack Overflow用户

发布于 2015-10-04 13:50:48

您的代码中存在一些问题,甚至忽略了类型本身的问题:

  • 首先,您只在进程#0上为您的c数组分配内存,然后您(尝试)将这些数据发送到进程#1,但是进程#1没有为存储消息分配任何内存。因此,即使发送的方式是正确的,代码也会失败。
  • MPI_开头的名称是为MPI库保留的,因此您不能随意使用它们。您必须为您的MPI_BAR_TYPE找到另一个名称。
  • 这一行让我有些困惑:int cLen = argv[0];,我想您想要从命令行读取要分配的数组的大小,在这种情况下,可能应该读取类似于int clen = atoi(argv[1]);的内容(忘记了需要正确处理的有效性测试.)
  • 您只测试该进程是否为0级,这意味着如果由于某种原因启动了3个进程,那么第2级进程将永远等待来自级别#0的进程的消息,而该消息永远不会到达。
  • 最后,数组本身:在您的代码中,指针cc指向的数据之间存在很大的混淆。结构嵌入指针,但不嵌入指向的内存。所以您不能映射到MPI结构中相应的数据..。最明显的原因是,从一个调用到下一个调用(或从一个进程到下一个进程),无法保证c所指向的结构地址和数据地址的偏移将是相同的(实际上,几乎可以保证它将有所不同)。所以你不能可靠地映射它们。

因此,为了解决问题,您需要做的是一次只传输两个整数ab (如果需要的话可能创建一个MPI结构来传输它们的数组)。然后,您将传输c所指向的内存,您将事先分配这些内存。

例如,您的代码可以变成:

代码语言:javascript
运行
复制
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>

struct bar
{
    int a;
    int b;
    int* c;
};

void defineMPIType( MPI_Datatype* newType ) {
    struct bar tmp[2];
    MPI_Aint extent = &tmp[1] - &tmp[0];

    MPI_Type_create_resized( MPI_2INT, 0, extent, newType );
    MPI_Type_commit( newType );
}

int main( int argc, char* argv[] ) {   
    MPI_Init(&argc, &argv);
    int rank, p;
    MPI_Comm_rank( MPI_COMM_WORLD, &rank );
    MPI_Comm_size( MPI_COMM_WORLD, &p );

    int cLen = atoi( argv[1] );    
    MPI_Datatype Bar_type;
    defineMPIType( &Bar_type );

    struct bar msg; 
    msg.c = ( int* ) malloc( sizeof( int ) * cLen );
    if ( rank == 0 ) {
        msg.a = 1;
        msg.b = 2;
        for ( int i = 0; i < cLen; ++i ) {
            msg.c[i] = i;
        }
        MPI_Send( &msg, 1, Bar_type, 1, 111, MPI_COMM_WORLD );
        MPI_Send( msg.c, cLen, MPI_INT, 1, 222, MPI_COMM_WORLD );
    }
    else if ( rank == 1 ) {
        MPI_Recv( &msg, 1, Bar_type, 0, 111, MPI_COMM_WORLD, MPI_STATUS_IGNORE );
        MPI_Recv( msg.c, cLen, MPI_INT, 0, 222, MPI_COMM_WORLD, MPI_STATUS_IGNORE );
    }

    printf("Rank %d has a = %d, b = %d, c = [", rank, msg.a, msg.b );
    for ( int i = 0; i < cLen - 1; ++i ) {
         printf( "%d, ", msg.c[i] );
    }
    printf( "%d]\n", msg.c[cLen - 1] );

    free( msg.c );
    MPI_Type_free( &Bar_type );
    MPI_Finalize();

    return 0;
}

这意味着:

代码语言:javascript
运行
复制
$ mpirun -n 2 ./a.out 3
Rank 0 has a = 1, b = 2, c = [0, 1, 2]
Rank 1 has a = 1, b = 2, c = [0, 1, 2]

MPI编码愉快。

票数 3
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32928523

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档