0

32x32 または 64x64 の PBM イメージ ファイルをインポートするプロジェクトに取り組んでいます。以下にサンプルを示します。

P1
# CREATOR: GIMP PNM Filter Version 1.1
32 32
01111110000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000001000000000000
00000000000001100000000000000000
00001100000000100011100000000000
00001100000000000000000000000000
00000011000000000000000000000000
00000011000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000011100000
01000101001000000000000000000000
01000101010000011100000000000000
01000101100000111000000000000000
01000101010000000000000000000000
01000101001000000000000000000000
00111001001000000000000001000000
00000000000000000000000001000000
00000000000000000000000001000000
00000000000000000000000000000000
00000000010000000000000000000000
00000000001000000000000000000000
00000000111000000000000000000000
00000000000000000000000110000000
00000000000000000000001001000000
00110000000000000000000110000000
01100000000000000110000000001000
00100000000000000110000000001100
00000000000000011000000000001100
00000000000000011000000000000100
00000000000000000000000000000000

これは 1D 配列に読み込まれ、順次処理されます。1D 配列を 4x4 パターンの複数の配列に分割しようとしています。「チャンク」に分割されると、一時的な小さな配列が複数の処理要素に分散されます。小さなチャンクが処理されるたびに、「チャンク」はプライマリ ノードに送り返され、再構築されます。

これは、シーケンシャルに動作する完全なコードです。

/*  life.c

    Play Conway's Game of Life

    Reads a P1 file in, outputs a P1 file.

    Does as many timesteps as stated on the command line.

    Uses a classic 1-element fake zone internally.

    Jan. 30, 2013 by H. Dietz
*/

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


unsigned char *
read_P1(int *xdim, int *ydim)
{
    register int c, x, y;
    register unsigned char *p;

    if ((c = getchar()) != 'P') {
pbm_bad:
        fprintf(stderr, "Bad PBM input\n");
        exit(1);
    }
    if ((c = getchar()) != '1') goto pbm_bad;
    c = getchar();

#define Eat_Space \
    while ((c == ' ') || \
           (c == '\t') || \
           (c == '\n') || \
           (c == '\r') || \
           (c == '#')) { \
        if (c == '#') while ((c = getchar()) != '\n') ; \
        c = getchar(); \
    }

    Eat_Space;      /* Eat white space and comments */

#define Get_Number(n) \
    { \
        if ((c < '0') || (c > '9')) goto pbm_bad; \
 \
        n = (c - '0'); \
        c = getchar(); \
        while ((c >= '0') && (c <= '9')) { \
            n *= 10; \
            n += (c - '0'); \
            c = getchar(); \
        } \
    }

    Get_Number(*xdim);  /* Get image width */

    Eat_Space;      /* Eat white space and comments */
    Get_Number(*ydim);  /* Get image height */

    p = ((unsigned char *)
         calloc(((*xdim + 2) * (*ydim + 2)),
            sizeof(unsigned char)));
    if (p == 0) goto pbm_bad;

    Eat_Space;

    for (y=0; y<*ydim; ++y) {
        for (x=0; x<*xdim; ++x) {
            Eat_Space;
            switch (c) {
            case '1':   p[x+1+((y+1)*(*xdim+2))] = 1; break;
            case '0':   /* 0 from calloc() */ break;
            default:    goto pbm_bad;
            }
            c = getchar();
        }
    }

    return(p);
}

#undef  Eat_Space
#undef  Get_Number


write_P1(register int xdim,
register int ydim,
register unsigned char *p)
{
    register int x, y, pos = 0;

    printf("P1\n"
           "# CREATOR: P1IO\n"
           "%d %d\n",
           xdim,
           ydim);

    for (y=0; y<ydim; ++y) {
        for (x=0; x<xdim; ++x) {
            int c = "01"[ p[x+1+((y+1)*(xdim+2))] != 0 ];
            putchar(c);

            /* Keep lines even matrices */
            if ( (++pos)%xdim == 0) {
                putchar('\n');
            }
        }
    }
    putchar('\n');
}


int main(int argc, char **argv)
{
    if(MPI_Init(&argc, &argv) != MPI_SUCCESS){
        exit(1);
    }

    int xdim, ydim;
    int iproc, nproc;
    register unsigned char *p, *q, *masterP;
    register int x, y, i, j, t, divisions, timesteps;

    divisions = 4;

    MPI_Comm_size(MPI_COMM_WORLD, &nproc); //nproc = number of PE
    MPI_Comm_rank(MPI_COMM_WORLD, &iproc); //iproc = position out of nproc

    if (argc != 2) {
        fprintf(stderr, "Usage: %s timesteps\n", argv[0]);
        exit(2);
    }
    timesteps = atoi(argv[1]);


    /* Carve p into 4x4 and send to 15 processing elements. PE0 will
    handle one chunk on its own */
    //if(iproc == 0){
        int masterx, mastery;
        /* Read the initial state image */
        masterP = read_P1(&masterx, &mastery);
        xdim = (masterx/divisions);
        ydim = (mastery/divisions);


        /* Make a temporary array to send each chunk of the image */
        p = ((unsigned char *)calloc((((xdim)+2) * ((ydim)+2)), 
            sizeof(unsigned char)));
        if (p == 0) {
        fprintf(stderr, "Calloc failed\n");
        exit(3);
        }

        printf("Check master P\n");
        write_P1(masterx, mastery, masterP);


        int loopx , loopy;
        int cnt = 0;
        for(loopy = 0; loopy < divisions; ++loopy){
            for(loopx = 0; loopx < divisions; ++loopx){
                x=1;
                //Fill p
                for (j=(loopy*ydim)+1; j<((loopy+1)*ydim+2); ++j){
                    for( i=(loopx*xdim)+1; i<((loopx+1)*xdim+2); ++i){
                        //printf("j: %d i: %d\n",j,i);
                        p[x]=masterP[i+(loopy*j)+1];
                        printf("%d",p[x]);
                        x++;
                    }
                }
                //Print P contents
                printf("\nIteration Y:%d X:%d\n",loopy, loopx);
                write_P1(xdim, ydim, p);

            }
        }


        //MPI_Send(p, sizeof(temp), MPI_UNSIGNED_CHAR, pe_num, 0, MPI_COMM_WORLD);
        //++pe_num;

    //}/* End IProc 0's business */


    /* Make a target image (with blank fake zone) */
    q = ((unsigned char *)
         calloc(((xdim + 2) * (ydim + 2)),
            sizeof(unsigned char)));
    if (q == 0) {
        fprintf(stderr, "Calloc failed\n");
        exit(3);
    }

    /* Iterate over the timesteps */
    for (t=0; t<timesteps; ++t) {
#ifdef  VERBOSE
        fprintf(stderr, "Timestep %d...\n", t);
#endif

        for (y=0; y<ydim; ++y) {
            for (x=0; x<xdim; ++x) {

#define FAKE(P, X, Y) P[((X)+1)+(((Y)+1)*(xdim+2))]

                register int live = FAKE(p, x-1, y-1) +
                            FAKE(p, x, y-1) +
                            FAKE(p, x+1, y-1) +
                            FAKE(p, x-1, y) +
                            FAKE(p, x+1, y) +
                            FAKE(p, x-1, y+1) +
                            FAKE(p, x, y+1) +
                            FAKE(p, x+1, y+1);

                /* Apply Conway's rules...
                   (yes, I know this is clever code!)
                */
                FAKE(q, x, y) = ((live == 3) ||
                         ((live == 2) &&
                          FAKE(p, x, y)));
            }
        }

        /* Swap our notion of p and q...
           this saves us copying every timestep
        */
        {
            register unsigned char *pt = p;
            p = q;
            q = pt;
        }
    } /* End iterate timestep for block */

    /* Done; write-out results */
    write_P1(masterx, mastery, q);
    exit(0);
}

次の例では、大きな配列masterPを 4x4 の「チャンク」に分割する必要があります。

int loopx , loopy;
int cnt = 0;
for(loopy = 0; loopy < divisions; ++loopy){
    for(loopx = 0; loopx < divisions; ++loopx){
        x=1;
        //Fill p
        for (j=(loopy*ydim)+1; j<((loopy+1)*ydim+2); ++j){
            for( i=(loopx*xdim)+1; i<((loopx+1)*xdim+2); ++i){
                //printf("j: %d i: %d\n",j,i);
                p[x]=masterP[i+(loopy*j)+1];
                printf("%d",p[x]);
                x++;
            }
        }
        //Print P contents
        printf("\nIteration Y:%d X:%d\n",loopy, loopx);
        write_P1(xdim, ydim, p);

    }
}

しかし、私の結果の配列はすべて0です。言うのは不適切ですか

  p[x]=masterP[i+(loopy*j)+1];

Arraypは、 の 4x4 の「チャンク」になるように作成された配列ですmasterP

出力例:

P1  
# CREATOR: GIMP PNM Filter Version 1.1
32 32
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000001000000000000
00000000000001100000000000000000
00001100000000100011100000000000
00001100000000000000000000000000
00000011000000000000000000000000
00000011000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000011100000
01000101001000000000000000000000
01000101010000011100000000000000
01000101100000111000000000000000
01000101010000000000000000000000
01000101001000000000000000000000
00111001001000000000000001000000
00000000000000000000000001000000
00000000000000000000000001000000
00000000000000000000000000000000
00000000010000000000000000000000
00000000001000000000000000000000
00000000111000000000000000000000
00000000000000000000000110000000
00000000000000000000001001000000
00110000000000000000000110000000
01100000000000000110000000001000
001000000000000001100000000000001100
00000000000000011000000000000100
00000000000000000000000000000000
Check master P
P1
# CREATOR: P1IO
32 32
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000001000000000000
00000000000001100000000000000000
00001100000000100011100000000000
00001100000000000000000000000000
00000011000000000000000000000000
00000011000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000011100000
01000101001000000000000000000000
01000101010000011100000000000000
01000101100000111000000000000000
01000101010000000000000000000000
01000101001000000000000000000000
00111001001000000000000001000000
00000000000000000000000001000000
00000000000000000000000001000000
00000000000000000000000000000000
00000000010000000000000000000000
00000000001000000000000000000000
00000000111000000000000000000000
00000000000000000000000110000000
00000000000000000000001001000000
00110000000000000000000110000000
01100000000000000110000000001000
00100000000000000110000000001100
00000000000000011000000000001100
00000000000000011000000000000100
00000000000000000000000000000000

000000000000000000000000000000000000000000000000000000000000000000000000000000000
Iteration Y:0 X:0
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000

000000000000000000000000000000000000000000000000000000000000000000000000000000000
Iteration Y:0 X:1
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000

000000000000000000000000000000000000000000000000000000000000000000000000000000000
Iteration Y:0 X:2
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000

000000000000000000000000000000000000000000000000000000000000000000000000000000000
Iteration Y:0 X:3
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000

000000000000000000000000000000000000000000000000000000000000000000000000000000000
Iteration Y:1 X:0
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000

000000000000000000000000000000000000000000000000000000000000000000000000000000000
Iteration Y:1 X:1
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000

000000000000000000000000000000000000000000000000000000000000000000000000000000000
Iteration Y:1 X:2
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000

000000000000000000000000000000000000000000000000000000000000000000000000000000000
Iteration Y:1 X:3
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000

000000000000000000000000000000000000000000000000000000000000000000000000000000000
Iteration Y:2 X:0
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000

000000000000000000000000000000000000000000000000000000000000000000000000000000000
Iteration Y:2 X:1
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000

000000000000000000000000000000000000000000000000000000000000000000000000000000000
Iteration Y:2 X:2
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000

000000000000000000000000000000000000000000000000000000000000000000000000000000000
Iteration Y:2 X:3
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000

000000000000000000000000000000000000000000000000000000000000000000000000000000000
Iteration Y:3 X:0
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000

000000000000000000000000000000000000000000000000000000000000000000000000000000000
Iteration Y:3 X:1
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000

000000000000000000000000000000000000000000000000000000000000000000000000000000000
Iteration Y:3 X:2
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000

000000000000000000000000000000000000000000000000000000000000000000000000000000000
Iteration Y:3 X:3
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000

P1
# CREATOR: P1IO
32 32
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000100000
11011100011111100111110000000000
11110001111110011111000111111000
00000000000101111100000000000111
00000000000000000010000000110111
01111110010000000100000001111110
00000100000000100000001101110000
00000000000000000000000000000000
00000000000000000001111100011111
01111100011111000111110001111100
11110000111100011111000111110001
11000111111001111100011111100111
00011111100111110001111110011111
01111110011111000111111001111100
11111001111100011111100111110001
11100111110001111110011111000111
10011111000111111001111100011111
01111100000000000111110001111110
11110001111110000000000000000100
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000

ご協力ありがとうございました!

4

3 に答える 3

3

MPI 派生データ型を使用すると、より洗練された方法でこれを行うことができます。をご覧くださいMPI_Type_vector。これは、要素で区切られたブロックごとに古いデータ型countの要素のブロックを取得するよう MPI に指示する派生データ型を作成します。blocklengthstride

block 1      block 2      block 3 ..... block count
   |            |            |             |
   V            V            V             V
+-----+------+-----+------+-----+-------+-----+------
|XXXXX|      |XXXXX|      |XXXXX|       |XXXXX|
+-----+------+-----+------+-----+-------+-----+------
|<- stride ->|            |     |
                        ->|-----|<-
                        blocklength

ここで、4、4、および1 行の長さに設定countすると、それはまさに、大きな配列から 4x4 ブロックを取り出すデータ型になります。このデータ型は送受信操作で使用でき、MPI タイプのメッセージ マジック (具体的には を使用したタイプのサイズ変更) を使用すると、スキャッター/ギャザー操作でも使用できます。blocklengthstrideMPI_Type_create_resized

たとえば、2 番目の 4 行で 2 番目のブロックを送信するには、各行にrow4cols4 列があると仮定します。

MPI_Datatype block4type;

MPI_Type_vector(4, 4, 4*rows4cols, MPI_UNSIGNED_CHAR, &block4type);
MPI_Type_commit(&block4type);

MPI_Send(&masterP[(2-1)*(4*4*rows4cols) + (2-1)*4], 1, block4type,
         dest_rank, 0, MPI_COMM_WORLD);

これは、 type の 16 個の要素を持つメッセージを送信しますMPI_UNSIGNED_CHAR。レシーバーはこれを単純に 4x4 配列で受信できます。

unsigned char block[4][4];
MPI_Status status;

MPI_Recv(block, 4*4, MPI_UNSIGNED_CHAR,
         master_rank, 0, MPI_COMM_WORLD, &status);

これは逆方向にも機能します。ワーカーは の 16 要素を送信MPI_UNSIGNED_CHARし、マスターはblock4typeの適切な位置で 4x4 ブロックとしてデータを受信するために使用しますmasterP

于 2013-02-11T13:14:41.630 に答える
2

インクリメントすることはありませんx。意図していたようです。したがって、常にデータを に割り当てていますp[1]。に割り当てる代わりにp[x]、実際に に割り当てる必要があるようp[cnt]です。

于 2013-02-11T02:41:55.110 に答える
1

皆様のご支援ありがとうございました!確かに私を正しい方向に押し進めるのに役立ちました。私はついに私のインデックスから派生したいくつかの問題を整理しました。

1d配列には32x32画像の1024要素が必要ですが、処理関数は32x32画像の4x4チャンクの周りに「偽のゾーン」またはバッファーを設定します。偽のゾーンの場合、次元は(x + 2)x(y + 2)であるため、32x32の画像の場合、1d配列に1156個の要素が含まれると予想されます。以前は、偽のゾーンが追加したラップアラウンドと余分なバッファスペースを適切に処理していませんでした。

4つのforループを使用して、より大きな32x32イメージを反復処理し、16個の8x8チャンクのイメージを生成しました。これは2次元行列を使用するとはるかに簡単だったと思いますが、処理関数は1次元配列を受け入れるように設定されています。1D操作の正しいインデックスパターンを導出する場合と比較して、2D配列を受け入れるように処理関数を変換する場合のオーバーヘッドが大きくなります。以下に、使用される4つのforループを示します。

    int loopx , loopy, pe_num;
int cnt = 0;

for(loopy = 0; loopy < divisions; loopy++){
    for(loopx = 0; loopx < divisions; loopx++){
        //Fill p
        cnt=(xdim+3); //Reinitialize the first index for every new p to xdim+2
        for (j=0; j<(ydim); j++){
            for( i=0; (i<xdim); i++){
                p[cnt]=masterP[((masterx+2)+(j*(masterx+2))+(loopy*(masterx+2)*ydim)+(loopx*xdim)+i+1)];
                //printf("%d",masterP[((masterx+2)+(j*(masterx+2))+(loopy*(masterx+2)*ydim)+(loopx*xdim)+i)]);  
                if( ((cnt+1)%(xdim+2))==0) //skip over fake zone
                    cnt = cnt+3;
                else
                    cnt++;
            }
        }
        pe_num = ((loopy*divisions)+loopx);
        //Print "chunk" p contents
        printf("\nPE #%d\n",pe_num);
        write_P1(xdim, ydim, p);
        //MPI_Send(p, sizeof(p), MPI_UNSIGNED_CHAR, pe_num, 0, MPI_COMM_WORLD);
    }
} 

入力の場合:

P1
# CREATOR: GIMP PNM Filter Version 1.1
32 32
01111111111110000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000001000000000000
00000000000001100000000000000000
00001100000000100011100000000000
00001100000000000000000000000000
00000011000000000000000000000000
00000011000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000011100000
01000101001000000000000000000000
01000101010000011100000000000000
01000101100000111000000000000000
01000101010000000000000000000000
01000101001000000000000000000000
00111001001000000000000001000000
00000000000000000000000001000000
00000000000000000000000001000000
00000000000000000000000000000000
00000000010000000000000000000000
00000000001000000000000000000000
00000000111000000000000000000000
00000000000000000000000110000000
00000000000000000000001001000000
00110000000000000000000110000000
01100000000000000110000000001000
00100000000000000110000000001100
00000000000000011000000000001100
00000000000000011000000000000100
00000000000000000000000000000000

元の画像の4x4グリッドを形成する16のチャンクに正常に分割しました。

Check master P
P1
# CREATOR: P1IO
32 32
01111111111110000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000001000000000000
00000000000001100000000000000000
00001100000000100011100000000000
00001100000000000000000000000000
00000011000000000000000000000000
00000011000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000011100000
01000101001000000000000000000000
01000101010000011100000000000000
01000101100000111000000000000000
01000101010000000000000000000000
01000101001000000000000000000000
00111001001000000000000001000000
00000000000000000000000001000000
00000000000000000000000001000000
00000000000000000000000000000000
00000000010000000000000000000000
00000000001000000000000000000000
00000000111000000000000000000000
00000000000000000000000110000000
00000000000000000000001001000000
00110000000000000000000110000000
01100000000000000110000000001000
00100000000000000110000000001100
00000000000000011000000000001100
00000000000000011000000000000100
00000000000000000000000000000000


PE #0
P1
# CREATOR: P1IO
8 8
01111111
00000000
00000000
00000000
00000000
00001100
00001100
00000011


PE #1
P1
# CREATOR: P1IO
8 8
11111000
00000000
00000000
00000000
00000110
00000010
00000000
00000000


PE #2
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00010000
00000000
00111000
00000000
00000000


PE #3
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000


PE #4
P1
# CREATOR: P1IO
8 8
00000011
00000000
00000000
00000000
01000101
01000101
01000101
01000101


PE #5
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00100000
01000001
00000011
01000000


PE #6
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
01000000
00000000
00000000


PE #7
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
01100000
00000000
00000000
00000000
00000000


PE #8
P1
# CREATOR: P1IO
8 8
01000101
00111001
00000000
00000000
00000000
00000000
00000000
00000000


PE #9
P1
# CREATOR: P1IO
8 8
00100000
00100000
00000000
00000000
00000000
01000000
00100000
01100000


PE #10
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000


PE #11
P1
# CREATOR: P1IO
8 8
00000000
01000000
01000000
01000000
00000000
00000000
00000000
00000000


PE #12
P1
# CREATOR: P1IO
8 8
00000000
00000000
00110000
01100000
00100000
00000000
00000000
00000000


PE #13
P1
# CREATOR: P1IO
8 8
00000000
00000000
00000000
00000000
00000000
00000001
00000001
00000000


PE #14
P1
# CREATOR: P1IO
8 8
00000001
00000010
00000001
01100000
01100000
00000000
00000000
00000000


PE #15
P1
# CREATOR: P1IO
8 8
10000000
01000000
00000000
00001000
00001100
00001100
00000100
00000000

貢献してくださった方々、ありがとうございました。Hristo、私はあなたがした推薦を試すことに非常に興味があります、私はそれがより効率的な方法であると信じています!

于 2013-02-12T02:13:02.693 に答える