c - 将 1D 二进制数组分解为多个较小的 MPI 数组,没有填充适当的数据,缺少什么?

标签 c arrays mpi

我正在处理一个导入 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

这被读入一维数组并按顺序处理。我试图以 4x4 模式将一维数组分成多个数组。一旦分成“ block ”,临时的较小阵列将被分配到多个处理元件。在处理完每个较小的 block 后,“ block ”将被发送回主节点以重新组装。

这是按顺序工作的完整代码:

/*  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“ block ”:

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];

数组 p 是创建为 masterP 的 4x4“ block ”的数组。

示例输出:

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

感谢您的帮助!

最佳答案

您可以使用 MPI 派生数据类型以更优雅的方式做到这一点。看看 MPI_Type_vector。它创建了一个派生数据类型,指示 MPI 获取 count block blocklength 旧数据类型的元素,每个 block 由 stride 元素分隔:

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

现在,如果您将 count 设置为 4,将 blocklength 设置为 4,将 stride 设置为一行的长度,这正是一种数据类型将从大阵列中取出一个 4x4 block 。您可以在发送和接收操作中使用此数据类型,并使用一些 MPI 类型按摩魔法(特别是使用 MPI_Type_create_resized 调整类型大小)您甚至可以在分散/收集操作中使用它。

例如,要在第二个 4 行上发送第二个 block ,假设每一行都有 row4cols 4 列:

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);

这将发送一条包含 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);

这也适用于另一个方向 - worker 发送 MPI_UNSIGNED_CHAR 的 16 个元素,而 master 使用 block4type 在适当的位置接收数据作为 4x4 block masterP.

关于c - 将 1D 二进制数组分解为多个较小的 MPI 数组,没有填充适当的数据,缺少什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14805073/

相关文章:

c - C 中的逗号、圆括号和大括号之间的关系是什么?

arrays - Excel VBA 连接函数

javascript - 合并数组中的对象

c - 通过 system() C/C+ 将 mpi 等级传递给 bash 脚本;奇怪的错误

linux - 如何在 Linux 中使用多 CPU 来加快计算速度

c++ - 毫秒 mpi 错误 : unable to allocate launching block

c - C 中删除 else 语句是否更有效?

c - 已分配但未释放的内存

c# - 在 `byte[]` 被 `MemoryStream` 包装后,通过对流执行操作来修改 0x104567910 吗?

C - 外部 ELF 加载