programing

C에서의 구조 직렬화 및 MPI를 통한 전송

oldcodes 2023. 7. 8. 11:10
반응형

C에서의 구조 직렬화 및 MPI를 통한 전송

사용자 지정을 정의했습니다.struct다른 MPI 프로세스로 전송해야 합니다.MPI_Bsend(또는)MPI_Send).

구조는 다음과 같습니다.

struct car{
  int shifts;
  int topSpeed;
}myCar;

문제는 원시 유형을 제외하고 MPI가 위에 표시된 구조와 같은 복잡한 데이터 유형의 직접 "전송"을 지원하지 않는 것 같습니다.저는 "직렬화"를 사용해야 할 수도 있다고 들었습니다.

어떻게 접근하여 성공적으로 전송해야 합니까?myCar5번 프로세스로?

예레미야 말이 맞아요 - MPI_Type_create_struct가 여기로 가는 길입니다.

MPI는 언어에 내장된 라이브러리가 아니라 라이브러리라는 점을 기억하는 것이 중요합니다. 따라서 MPI는 구조가 어떻게 생겼는지 직접 직렬화할 수 없습니다.따라서 복잡한 데이터 유형을 전송하려면 레이아웃을 명시적으로 정의해야 합니다.직렬화를 기본적으로 지원하는 언어에서는 MPI 래퍼 세트가 이를 사용할 수 있습니다. 예를 들어 mpi4py는 파이썬의 피클을 사용하여 복잡한 데이터 유형을 투명하게 전송하지만 C에서는 소매를 걷어붙이고 직접 해야 합니다.

구조의 경우 다음과 같습니다.

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

typedef struct car_s {
        int shifts;
        int topSpeed;
} car;

int main(int argc, char **argv) {

    const int tag = 13;
    int size, rank;

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    if (size < 2) {
        fprintf(stderr,"Requires at least two processes.\n");
        exit(-1);
    }

    /* create a type for struct car */
    const int nitems=2;
    int          blocklengths[2] = {1,1};
    MPI_Datatype types[2] = {MPI_INT, MPI_INT};
    MPI_Datatype mpi_car_type;
    MPI_Aint     offsets[2];

    offsets[0] = offsetof(car, shifts);
    offsets[1] = offsetof(car, topSpeed);

    MPI_Type_create_struct(nitems, blocklengths, offsets, types, &mpi_car_type);
    MPI_Type_commit(&mpi_car_type);

    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    if (rank == 0) {
        car send;
        send.shifts = 4;
        send.topSpeed = 100;

        const int dest = 1;
        MPI_Send(&send,   1, mpi_car_type, dest, tag, MPI_COMM_WORLD);

        printf("Rank %d: sent structure car\n", rank);
    }
    if (rank == 1) {
        MPI_Status status;
        const int src=0;

        car recv;

        MPI_Recv(&recv,   1, mpi_car_type, src, tag, MPI_COMM_WORLD, &status);
        printf("Rank %d: Received: shifts = %d topSpeed = %d\n", rank,
                 recv.shifts, recv.topSpeed);
    }

    MPI_Type_free(&mpi_car_type);
    MPI_Finalize();

    return 0;
}

Jonathan Dursi의 대답이 맞긴 하지만, 너무 복잡합니다. MPI는 당신의 문제에 더 적합한 단순하고 덜 일반적인 유형의 생성자를 제공합니다. MPI_Type_create_struct기본 유형(예: int 및 float)이 다른 경우에만 필요합니다.

예를 들어, 몇 가지 더 나은 솔루션이 있습니다.

  • 두 정수가 연속적인 메모리 영역(예: 정수 배열)에 정렬되어 있다고 가정하면 파생 데이터 유형이 전혀 필요하지 않습니다.두 가지 유형의 요소만 전송/수신MPI_INT유형의 변수의 주소가 있는.car송신/수신 버퍼로 사용:

    MPI_Send(&send, 2, MPI_INT, dest, tag, MPI_COMM_WORLD);
    MPI_Recv(&recv, 2, MPI_INT, src, tag, MPI_COMM_WORLD, &status);
    
  • 파생 데이터 유형(예: 가독성 또는 재미를 위해)을 사용하려면 다음을 사용할 수 있습니다.MPI_Type_contiguous이는 배열에 해당합니다.

    MPI_Type_contiguous(2, MPI_INT, &mpi_car_type);
    
  • 두 정수가 서로 다르게 정렬되어 있는 경우(대부분은 그렇지 않지만 기계에 의존하고 있으며 MPI 구현은 다양한 플랫폼에 대해 존재합니다),MPI_Type_indexed_block그것은 일련의 변위를 필요로 합니다 (예:MPI_Type_create_struct)이지만 이전 형식의 인수는 하나뿐이며 각 블록의 블록 길이는 정의에 따라 1입니다.

    MPI_Aint offsets[2];
    offsets[0] = offsetof(car, shifts) ; //most likely going to be 0 
    offsets[1] = offsetof(car, topSpeed);
    MPI_Type_indexed_block(2, offsets, MPI_INT);
    

다른 솔루션은 의미론적으로 올바르지만 읽기가 훨씬 어렵고 성능 저하가 클 수 있습니다.

를 .MPI_Type_create_struct개체에 대한 사용자 지정 MPI 데이터 유형을 만듭니다.를 들어 http://beige.ucs.indiana.edu/I590/node100.html 을 참조하십시오.

int MPI_Send(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)

는 OpenMPI를 합니다.count * sizeof(datatype)음으로 시연바이트로 bufint 배열과 같은 것을 보낼 수 있습니다.들어 array 를들배 10 int 을선는하경우언을 int arr[10]와 함께 보낼 수 있습니다.

MPI_Send(arr, 10, MPI_INT, 1, 0, MPI_COMM_WORLD);

그리고 비슷하게 받습니다. 때부터buf입니다. 이를 하여 보드포입다를 전송하여 할 수 있습니다. 우리는 이것을 사용하여 구조물을 보낼 수 있습니다.sizeof(my_struct)바이트 및 수신측 구조체로 캐스팅합니다.다음은 예입니다.

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

typedef struct 
{
    char a;
    int b;
    short c;
} my_struct;


int main (int argc, char *argv[])
{
    int  numtasks, taskid;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &taskid);
    MPI_Comm_size(MPI_COMM_WORLD, &numtasks);


    if (taskid == 0) 
    {
        my_struct m;
        m.a = '!';
        m.b = 1234;
        m.c = 5678;

        MPI_Send(&m, sizeof(my_struct), MPI_CHAR, 1, 0, MPI_COMM_WORLD);
    }
    else 
    {
        my_struct m;
        MPI_Recv(&m, sizeof(my_struct), MPI_CHAR, 0, 0, MPI_COMM_WORLD, 
                 MPI_STATUS_IGNORE);
        printf("%c %d %d\n", m.a, m.b, m.c); 
    }

    MPI_Finalize();
}

C 배열은 데이터를 연속적으로 저장하기 때문에 구조 배열을 mallocation하는 방법과 유사한 구조 배열을 보낼 도 있습니다.그래서 만약에 당신이my_struct m_array[10]당신은 (그리고 비슷하게) 보낼 것입니다.

MPI_Send(m_array, sizeof(my_struct) * 10, MPI_CHAR, 1, 0, MPI_COMM_WORLD);

언급URL : https://stackoverflow.com/questions/9864510/struct-serialization-in-c-and-transfer-over-mpi

반응형