programing

블록 순환 분포를 얻는 방법은?

megabox 2023. 9. 16. 08:55
반응형

블록 순환 분포를 얻는 방법은?

나는 나의 매트릭스를 블록 순환 방식으로 배포하려고 합니다.저는 이 질문(MPI IO 읽기 및 쓰기 블록 순환 행렬)을 통해 많은 것을 배웠지만, 그것은 제가 정말로 필요로 하는 것이 아닙니다.

제 문제를 설명해 드리겠습니다.

첫 번째 프로세서가 굵게 표시된 요소를 얻을 수 있도록 차원 2 x 3의 프로세서 그리드에 배포하고자 하는 차원 12 x 12 행렬이 있다고 가정합니다.

A =
1 2     3     4     5     6     7 8     9    10    11    1213 14    15    16    17    18    19 20    21    22    23    2425    26    27    28    29    30    31    32    33    34    35    3637    38    39    40    41    42    43    44    45    46    47    4849 50    51    52    53    54    55 56    57    58    59    6061 62    63    64    65    66    67 68    69    70    71    7273    74    75    76    77    78    79    80    81    82    83    8485    86    87    88    89    90    91    92    93    94    95    9697 98    99   100   101   102   103 104   105   106   107   108109 110   111   112   113   114   115 116   117   118   119   120121   122   123   124   125   126   127   128   129   130   131   132133   134   135   136   137   138   139   140   141   142   143   144

그래서 기본적으로 행렬을 2 x 2 차원의 블록으로 분할한 다음 이 블록을 1부터 6까지 숫자로 표시한 프로세서에 다음과 같은 방식으로 배포하고자 합니다.

1 2 3 1 2 34 5 6 4 5 61 2 3 1 2 34 5 6 4 5 6

위 링크된 질문과 같이 이를 달성하려고 했지만 문제는 첫 번째 프로세서를 위한 로컬 어레이가 열 단위로 형성된다는 것입니다. 즉, 이렇게 보입니다.

1, 13, 49, 61, 97, 109, 2, 14, 50, 62, 98, 110, 7, 19, 55, 67, 103, 115, 8, 20, 56, 68, 104, 116

이것이 내 C 코드입니다.

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

#define     N           12
#define     P           2
#define     Q           3

int main(int argc, char **argv) {
    int rank;
    int size;

    double *A;
    int A_size;
    
    MPI_Datatype filetype;
    MPI_File fin;

    MPI_Status status;

    MPI_Init(&argc, &argv);

    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    /**
     * Reading from file.
     */
    int gsizes[2], distribs[2], dargs[2], psizes[2];

    gsizes[0] = N; /* no. of rows in global array */
    gsizes[1] = N; /* no. of columns in global array*/

    distribs[0] = MPI_DISTRIBUTE_CYCLIC;
    distribs[1] = MPI_DISTRIBUTE_CYCLIC;

    dargs[0] = 2; // no of rows in block
    dargs[1] = 2; // no of cols in block

    psizes[0] = P; /* no. of processes in vertical dimension
     of process grid */
    psizes[1] = Q; /* no. of processes in horizontal dimension
     of process grid */

    MPI_Type_create_darray(P * Q, rank, 2, gsizes, distribs, dargs, psizes,
            MPI_ORDER_FORTRAN, MPI_DOUBLE, &filetype);
    MPI_Type_commit(&filetype);

    MPI_File_open(MPI_COMM_WORLD, "A.txt",
            MPI_MODE_RDONLY,
            MPI_INFO_NULL, &fin);

    MPI_File_set_view(fin, 0, MPI_DOUBLE, filetype, "native",
            MPI_INFO_NULL);

    A_size = (N * N) / (P * Q);
    A = (double*) malloc(A_size * sizeof(double));
    MPI_File_read_all(fin, A, A_size,
            MPI_DOUBLE, &status);

    MPI_File_close(&fin);

    printf("\n======\ni = %d\n", rank);
    printf("A : ");
    for (int i = 0; i &lt A_size; i++) {
        printf("%lg ", A[i]);
    }

    MPI_Finalize();
    return 0;
}

제가 정말로 원하는 것은 이 2 x 2 블록이 연속적으로 쓰여지는 것입니다. 즉, 첫 번째 프로세서의 로컬 어레이는 다음과 같습니다.

1, 13, 2, 14, 49, 61, 50, 62, 97, 109, 98, 110, ...

벡터나 서브어레이와 같은 다른 MPI_Data 유형을 정의해야 한다고 가정하지만, 어떻게 하면 이를 달성할 수 있을지 모르겠습니다.

편집

저는 제 문제를 부분적으로 해결했다고 생각합니다.기본적으로 각 프로세서는 FORTRAN 순서로 4 x 6 행렬로 끝나고 MPI_Create_subarray(...)를 사용하면 쉽게 2 x 2 블록을 추출할 수 있습니다.

그러나 각 프로세서가 블록 행을 각 프로세서에 동일한 열로 전송하고 그 반대의 경우도 마찬가지입니다.프로세서에 그리드 번호가 부여됨

1 2 34 5 6

예를 들어, 첫 번째 단계에서 프로세서 1은 블록 행을 전송해야 합니다.

1  2  7  813 14 19 20

프로세서 4; 및 해당 블록 열에 연결합니다.

1   213  1449  5061  6297  98109 110

프로세서 2와 3에 연결합니다.

데카르트 통신기를 만들고 MPI_Cart_sub()을 사용하여 행 및 열 단위 통신기도 만들었습니다.

MPI_Bcast()를 사용해야 할 것 같은데 MPI_Bcast()와 MPI_Type_create_subarray()를 결합하는 방법을 모르겠습니다.먼저 추출된 서브어레이를 local_array에 복사한 다음 Bcast(local_array)를 복사해야 합니다.그러나 MPI_Type_create_subarray()는 서브어레이에서 "뷰"만 제공하고 실제로는 제공하지 않습니다. 따라서 제가 생각해낸 가장 좋은 해결책은 Irecv root->root입니다.

좀 더 우아한 해결책이 있을까요?

아직까지는 당신의 실행이 정확한 것 같습니다.첫 번째 프로세서의 로컬 배열을 인쇄하는 방법이 문제입니다.로컬 배열은 파일을 읽는 방식과 프로세스 간에 데이터가 분산되기 때문에 열 단위로 형성됩니다.

첫 번째 프로세서의 로컬 배열을 행 단위로 인쇄하려면 다음과 같이 코드를 수정할 수 있습니다.

if (rank == 0) {
    printf("\nLocal Array for Processor 0\n");
    for (i = 0; i < P * Q; i++) {
        for (j = 0; j < dargs[0] * dargs[1]; j++) {
            printf("%.0f ", A[i * dargs[0] * dargs[1] + j]);
            if ((j + 1) % dargs[1] == 0)
                printf("\n");
        }
        printf("\n");
    }
}

이렇게 하면 다음과 같이 첫 번째 프로세서의 로컬 배열이 행 단위로 인쇄됩니다.

Local Array for Processor 0
1  2  3  4 
13 14 15 16

49 50 51 52
61 62 63 64

97 98 99 100
109 110 111 112

2  3  4  5 
14 15 16 17

50 51 52 53
62 63 64 65

103 104 105 106
115 116 117 118

출력에는 첫 번째 프로세서의 로컬 배열만 표시됩니다.각 프로세서의 로컬 배열을 비슷한 방식으로 인쇄하려면 루프를 수정해야 합니다.

언급URL : https://stackoverflow.com/questions/28128605/how-to-get-block-cyclic-distribution

반응형