MPI - 使用MPI_Probe()时发送我自己的结构

时间:2014-12-24 14:40:31

标签: c struct parallel-processing mpi

我需要使用MPI_Send()发送自己的结构。问题是,我不确定如何正确使用MPI中的结构。我当然试图自己找到它,但我没有找到任何适合我需要的例子。

现在,当我运行Makefile时,我收到了这个错误:

probe_and_struct.c: In function ‘main’:
probe_and_struct.c:72:13: error: expected ‘;’ before ‘buf’
    myStruct buf;
             ^
probe_and_struct.c:73:4: error: ‘buf’ undeclared (first use in this function)
    buf = (myStruct *) malloc( sizeof(myStruct) * status_size );
    ^
probe_and_struct.c:73:4: note: each undeclared identifier is reported only once for each function it appears in
probe_and_struct.c:73:21: error: expected expression before ‘)’ token
    buf = (myStruct *) malloc( sizeof(myStruct) * status_size );
                     ^
make: *** [probe_and_struct] Error 1

那么,请你告诉我,我做错了什么,我应该如何正确使用这个结构?

修改 我已经重写了代码,但现在程序在MPI_Send()上出现分段错误崩溃。


这是我的代码:

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

#define ARR_LEN 2 // length of test array and the size sent

int main() {
    //---------------------------------------------------------------------------------------------------------------------------------------
    // Create own structure
    //----------------------

    // Structure of structure :-)
    struct {
        int id;
        char c;
    } value;

    // Declare parts of structure
    MPI_Datatype myStruct;
    int blockLengths[2];
    MPI_Aint indices[2];
    MPI_Datatype types[2];

    // Initialize parts of structure
    blockLengths[0] = 1; // stucture's attributes' sizes
    blockLengths[1] = 1;
    types[0] = MPI_INT; // structure's attributes' data types
    types[1] = MPI_CHAR;
    MPI_Address( &value.id, &indices[0] );
    MPI_Address( &value.c, &indices[1] );

    // Create and commit new structure
    MPI_Type_struct( 2, blockLengths, indices, types, &myStruct );
    MPI_Type_commit( &myStruct );

    //---------------------------------------------------------------------------------------------------------------------------------------
    // Message passing
    //-----------------

    MPI_Init(NULL, NULL);

    value.id = 0;
    value.c = 'a';

    // Number of processes, ID of current process
    int world_size;
    MPI_Comm_size( MPI_COMM_WORLD, &world_size );

    int world_rank;
    MPI_Comm_rank( MPI_COMM_WORLD, &world_rank );

    // Test array to send
    int arr[ 2 ] = {10,20};

    MPI_Status status;

    switch( world_rank ) {
        case 0:
            printf("This is the process number %d.\n\t", world_rank);
            MPI_Send( &value, 2, myStruct, 1, 0, MPI_COMM_WORLD);
            printf("The array of INT was sent.\n");
            break;
        case 1:
            // Recognize the size of the message
            MPI_Probe( 0, 0, MPI_COMM_WORLD, &status );

            // Number of blocks sent
            int status_size;
            MPI_Get_count( &status, myStruct, &status_size );

            // Allocate buffer with the size needed
            myStruct buf;
            buf = (myStruct *) malloc( sizeof(myStruct) * status_size );

            // Receive and print message
            MPI_Recv( buf, status_size, myStruct, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE );
            printf("This is the process number %d.\n\t[ ", world_rank);
            for( int i = 0; i < status_size; i++ ) {
                printf( "%d ", buf[i] );
            }
            printf("]\n");
            break;
        default:
            printf("This is the process number %d.\n", world_rank);
            break;
    }

    MPI_Type_free( &myStruct );
    MPI_Finalize();
    return 0;
}

生成文件:

CC=mpicc

STD=-std=c11

all: probe_and_struct

probe_and_struct: probe_and_struct.c
    $(CC) -o probe_and_struct probe_and_struct.c $(STD)

clean:
    rm -f probe_and_struct

我的代码 - 第二版:

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

#define ARR_LEN 2 // length of test array and the size sent

int main() 
{
    MPI_Init(NULL, NULL);

    //---------------------------------------------------------------------------------------------------------------------------------------
    // Create own structure
    //----------------------

    // Structure of structure :-)
    typedef struct Values
    {
        int id;
        char c;
    } Values;

    Values value;

    // Declare parts of structure
    MPI_Datatype myStruct;
    int blockLengths[2];
    MPI_Aint indices[2];
    MPI_Datatype types[2];

    // Initialize parts of structure
    blockLengths[0] = 1; // stucture's attributes' sizes
    blockLengths[1] = 1;
    types[0] = MPI_INT; // structure's attributes' data types
    types[1] = MPI_CHAR;
    MPI_Address( &value.id, &indices[0] );
    MPI_Address( &value.c, &indices[1] );

    // Create and commit new structure
    MPI_Type_struct( 2, blockLengths, indices, types, &myStruct );
    MPI_Type_commit( &myStruct );

    //---------------------------------------------------------------------------------------------------------------------------------------
    // Message passing
    //-----------------

    value.id = 0;
    value.c = 'a';

    // Number of processes, ID of current process
    int world_size;
    MPI_Comm_size( MPI_COMM_WORLD, &world_size );

    int world_rank;
    MPI_Comm_rank( MPI_COMM_WORLD, &world_rank );

    // Test array to send
    //int arr[ 2 ] = {10,20};

    MPI_Status status;

    switch( world_rank ) {
        case 0:
            printf("Toto je proces cislo %d.\n\t", world_rank);
            MPI_Send( &value, sizeof(struct Values), myStruct, 1, 0, MPI_COMM_WORLD);
            printf("Odeslano pole INTu.\n");
            break;
        case 1:
            // Recognize the size of the message
            MPI_Probe( 0, 0, MPI_COMM_WORLD, &status );

            // Number of blocks sent
            int status_size;
            MPI_Get_count( &status, myStruct, &status_size );
puts("b");
            // Allocate buffer with the size needed
            Values * buf;
            buf = (Values *) malloc( sizeof(Values) * status_size );
puts("b");
            // Receive and print message
            //MPI_Recv( buf, status_size, myStruct, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE );
            printf("Toto je proces cislo %d.\n\t[ ", world_rank);
            for( int i = 0; i < status_size; i++ ) {
                printf( "%d %c", buf[i].id, buf[i].c );
            }
            printf("]\n");
            break;
        default:
            printf("Toto je proces cislo %d.\n", world_rank);
            break;
    }

    MPI_Type_free( &myStruct );
    MPI_Finalize();
    return 0;
}

3 个答案:

答案 0 :(得分:3)

您使用myStruct类似于某种类型并尝试实例化buf,但myStructMPI_Datatype的实例(而不是类型)。< / p>

这部分代码(其中myStruct被声明为MPI_Datatype):

// Declare parts of structure
MPI_Datatype myStruct;

与此部分冲突(您尝试将myStruct用作类型):

        // Allocate buffer with the size needed
        myStruct buf;
        buf = (myStruct *) malloc( sizeof(myStruct) * status_size );

答案 1 :(得分:2)

您没有正确构建MPI数据类型。或者更确切地说,您没有正确使用发送结构的构造数据类型。您应该执行以下任一操作:

1。修复数据类型

内的偏移量

此代码:

// Initialize parts of structure
blockLengths[0] = 1; // stucture's attributes' sizes
blockLengths[1] = 1;
types[0] = MPI_INT; // structure's attributes' data types
types[1] = MPI_CHAR;
MPI_Address( &value.id, &indices[0] );
MPI_Address( &value.c, &indices[1] );

// Create and commit new structure
MPI_Type_struct( 2, blockLengths, indices, types, &myStruct );
MPI_Type_commit( &myStruct );

...

MPI_Send( &value, sizeof(struct Values), myStruct, 1, 0, MPI_COMM_WORLD);

应该成为:

// Initialize parts of structure
blockLengths[0] = 1; // stucture's attributes' sizes
blockLengths[1] = 1;
types[0] = MPI_INT; // structure's attributes' data types
types[1] = MPI_CHAR;
MPI_Address( &value.id, &indices[0] );
MPI_Address( &value.c, &indices[1] );

// Convert the absolute addresses into offsets
indices[1] -= indices[0];
indices[0] = 0;

// Create and commit new structure
MPI_Type_struct( 2, blockLengths, indices, types, &myStruct );
MPI_Type_commit( &myStruct );

...

MPI_Send( &value, 1, myStruct, 1, 0, MPI_COMM_WORLD);

此外,如果您愿意发送此类数据类型的数组,则应采取一些特殊措施来考虑编译器完成的类型填充。请参阅this question如何。

2。发送数据时使用MPI_BOTTOM

您可以保留绝对地址,而不是修复类型描述中的偏移量。缺点是,对于绝对地址,您只能发送构造数据类型时使用的特定变量的内容(因为其他变量通常会在内存中的其他位置结束)。使用此类数据类型时,不会指定缓冲区的地址,而是MPI_BOTTOM,即此代码:

MPI_Send( &value, sizeof(struct Values), myStruct, 1, 0, MPI_COMM_WORLD);

变为:

MPI_Send( MPI_BOTTOM, 1, myStruct, 1, 0, MPI_COMM_WORLD);

请注意,在这种情况下,要发送的元素数必须等于1,即无法发送数组(除非数据类型本身描述了所有元素)数组)。


另请注意,在这两种情况下sizeof(struct Values)都是错误的,必须更正为1,因为MPI_Send的第二个参数给出了要发送的元素数量和实际数据大小每个元素的数据已经以MPI数据类型编码。

我强烈建议你选择#1。

答案 2 :(得分:1)

您将MPI_type与变量的类型混淆。例如,让我们使用一个简单的intMPI_type的{​​{1}}是int,对吗?但这不是正确的代码:

MPI_INT

相反,你会使用:

MPI_INT a = 5; //wrong, MPI_INT is an MPI_Type
               //not the type we want to declare a variable
MPI_Send(&a, 1, MPI_INT, 1, 0, MPI_COMM_WORLD);

同样,如果你有一个结构:

int a = 5; //int is used to declare a variable
MPI_Send(&a, 1, MPI_INT, 1, 0, MPI_COMM_WORLD); //MPI_INT is the type to 
                                                //send the variable

然后,在使用struct value { int id; char c; }; 声明新的MPI类型后,您将使用:

MPI_Type_commit