【问题标题】:Scatter a grid into equally-sized blocks将网格分散成大小相等的块
【发布时间】:2017-01-22 15:48:19
【问题描述】:

给定一个 10x10 大小的网格,如下所示:

        0,1,2,3,4,          5,6,7,8,9,
        10,11,12,13,14,     15,16,17,18,19,
        20,21,22,23,24,     25,26,27,28,29,
        30,31,32,33,34,     35,36,37,38,39,
        40,41,42,43,44,     45,46,47,48,49,

        50,51,52,53,54,     55,56,57,58,59,
        60,61,62,63,64,     65,66,67,68,69,
        70,71,72,73,74,     75,76,77,78,79,
        80,81,82,83,84,     85,86,87,88,89,
        90,91,92,93,94,     95,96,97,98,99

如何将视觉上分离的分散到四个进程?
我已经尝试过使用 Scatterv 描述的here(甚至here)的方式,并且它有效,但是我记得有一个项目有完全相同的问题并且使用调整大小或 Scatterv 来解决它。

这是我所拥有的最小代码示例:

#include <stdio.h>
#include <mpi.h>
#include <stdlib.h>
#include <assert.h>
#include <memory.h>
#include <unistd.h>

void print_array(int* arr, int width, int height)
{
    int i;
    for (i = 0; i< width * height;i++)
    {
        if((i != 0) && (i % width == 0))
            printf("\n");
        printf("%4d ", arr[i]);
    }
    putchar('\n');
}

int main() {
    int board[100] = {
            0,1,2,3,4,          5,6,7,8,9,
            10,11,12,13,14,     15,16,17,18,19,
            20,21,22,23,24,     25,26,27,28,29,
            30,31,32,33,34,     35,36,37,38,39,
            40,41,42,43,44,     45,46,47,48,49,

            50,51,52,53,54,     55,56,57,58,59,
            60,61,62,63,64,     65,66,67,68,69,
            70,71,72,73,74,     75,76,77,78,79,
            80,81,82,83,84,     85,86,87,88,89,
            90,91,92,93,94,     95,96,97,98,99
    };

    int numprocs, rank;
    MPI_Init(NULL, NULL);
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    int* block = calloc(25, sizeof(int));
    assert(block != NULL);


    MPI_Datatype sent_block_t, resized_sent_block_t;
    MPI_Type_vector(5, 5, 10, MPI_INT, &sent_block_t);
    MPI_Type_create_resized(sent_block_t, 0, 5*sizeof(int), &resized_sent_block_t);
    MPI_Type_commit(&sent_block_t);
    MPI_Type_commit(&resized_sent_block_t);

    if (rank == 0) {
        print_array(board, 10, 10);
        MPI_Scatter(&(board[0]), 1, resized_sent_block_t,
                    &(block[0]), 25, MPI_INT,
                    0, MPI_COMM_WORLD);
    }
    else {
        MPI_Scatter(NULL, 0, resized_sent_block_t,
                    &(block[0]), 25, MPI_INT,
                    0, MPI_COMM_WORLD);
    }

    for (int i = 0; i < numprocs; i++) {
        MPI_Barrier(MPI_COMM_WORLD);
        sleep(1);
        if (i == rank) {
            printf("\nRank: %d\n", rank);
            print_array(block, 5, 5);
        }
    }

    MPI_Finalize();
    free(block);
}

用 4 个进程运行它,我得到了这个:

  0    1    2    3    4    5    6    7    8    9 
  10   11   12   13   14   15   16   17   18   19 
  20   21   22   23   24   25   26   27   28   29 
  30   31   32   33   34   35   36   37   38   39 
  40   41   42   43   44   45   46   47   48   49 
  50   51   52   53   54   55   56   57   58   59 
  60   61   62   63   64   65   66   67   68   69 
  70   71   72   73   74   75   76   77   78   79 
  80   81   82   83   84   85   86   87   88   89 
  90   91   92   93   94   95   96   97   98   99 

Rank: 0
   0    1    2    3    4 
  10   11   12   13   14 
  20   21   22   23   24 
  30   31   32   33   34 
  40   41   42   43   44 

Rank: 1
   5    6    7    8    9 
  15   16   17   18   19 
  25   26   27   28   29 
  35   36   37   38   39 
  45   46   47   48   49 

Rank: 2
  10   11   12   13   14 
  20   21   22   23   24 
  30   31   32   33   34 
  40   41   42   43   44 
  50   51   52   53   54 

Rank: 3
  15   16   17   18   19 
  25   26   27   28   29 
  35   36   37   38   39 
  45   46   47   48   49 
  55   56   57   58   59 

这个散射是错误的,注意rank 2和3的内容
正确的是:

Rank 0:             Rank 1:
0,1,2,3,4,          5,6,7,8,9,
10,11,12,13,14,     15,16,17,18,19,
20,21,22,23,24,     25,26,27,28,29,
30,31,32,33,34,     35,36,37,38,39,
40,41,42,43,44,     45,46,47,48,49,

Rank 2:             Rank 3:
50,51,52,53,54,     55,56,57,58,59,
60,61,62,63,64,     65,66,67,68,69,
70,71,72,73,74,     75,76,77,78,79,
80,81,82,83,84,     85,86,87,88,89,
90,91,92,93,94,     95,96,97,98,99

问题
有没有什么方法可以在不使用 Scatterv 的情况下分散相同大小的网格块?

【问题讨论】:

  • 所以你说你的代码有效并且你理解它很好。您的实际问题是什么?
  • @Zulan 不,我发布的结果不是正确的输出。请参阅帖子开头的给定板,它在视觉上分为四个块。我想要左上角,去进程 0,右上角到进程 1,左下角到进程 2,左下角到进程 3。(我已经添加了预期的输出。)
  • 抱歉,我只是简要浏览了输出。有一个very good extensive explanation,关于如何正确地做你想做的事,使用MPI_Scatterv。我无法想象只使用MPI_Scatter 的正确实现,这不是不必要的hacky。

标签: c mpi


【解决方案1】:

我认为使用 MPI_Scatter 不可能做到这一点,因为数据类型的位移不是恒定的 - 在一行内,位移是 5 个整数(或调整大小的类型的计数为 1),但跳到下一行是 50 个整数的位移(或 count=10)。

在 4 个进程上,使用:

  int counts[4] = {1, 1, 1, 1};
  int disps[4] = {0, 1, 10, 11};
  ...
  if (rank == 0) print_array(board, 10, 10);

  MPI_Scatterv(&(board[0]), counts, disps, resized_sent_block_t,
              &(block[0]), 25, MPI_INT,
              0, MPI_COMM_WORLD);

似乎工作正常。请注意,您不需要单独调用 scatter - MPI 保证仅在根处有效的参数只会在根处被引用。

【讨论】:

    猜你喜欢
    • 2022-10-29
    • 1970-01-01
    • 2011-07-28
    • 2012-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-31
    相关资源
    最近更新 更多