【问题标题】:Scattering blocks of a contiguous 2D Array using MPI使用 MPI 散射连续 2D 阵列的块
【发布时间】:2020-03-30 18:08:51
【问题描述】:

我目前正在学习使用 MPI 并尝试将我的数组块分散到我的其余处理器。

我的根处理器是最后一个 (nproc-1),我正在该处理器中生成数组。在我的代码的下一次迭代中,它将是一个随机数组。

对于我的所有处理器,我都使用 calloc 为“array”和“grain”分配连续内存。 Grain 存储要处理的数据,由于我需要原始数组中的上下行,因此我将其设置为 grain_length+2。

我的问题是我从原始数组 except 中获得了最后两个值的正确数据(请参见下面的输出示例)。

int main(int argc, char** argv) 
{
    int         i, j, m;
    int         array_size, grain_length;
    int         rc, rank, nproc;
    MPI_Status  status;

    rc = MPI_Init(&argc, &argv);
    if (rc != MPI_SUCCESS)
    {
        printf("Error starting MPI Program.\n");
        MPI_Abort(MPI_COMM_WORLD, rc);
    }

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

    array_size = 8;

    grain_length = array_size / nproc;

    double **array= (double **) calloc(array_size, sizeof (double *));
    for (i = 0; i < array_size; i++)
        array[i] = (double *) calloc(array_size, sizeof (double));

    double **grain = (double **) calloc(grain_length+2, sizeof (double *));
    for (i = 0; i < grain_length + 2; i++)
        grain[i] = (double *) calloc(array_size, sizeof (double));

    if (array == NULL || grain == NULL)
    {
        printf("Memory could not be allocated for the arrays.");
        exit(EXIT_FAILURE);
    }

    if (rank == nproc-1)
    {
        for (i = 0; i < array_size; i++) 
        {
            for (j = 0; j < array_size; j++) 
            {
                //array[i][j] = rand() % 10;
                array[i][j] = i+j;
            }
        }
    }

    MPI_Scatter(
            &array[0][0], grain_length*array_size, MPI_DOUBLE,
            &grain[1][0], grain_length*array_size, MPI_DOUBLE, 
            nproc-1, MPI_COMM_WORLD);

    for (m = 0; m < nproc; m++)
    {
        if (rank == m) 
        {
            printf("Grain from processor %d:\n", rank);
            for (i = 0; i < grain_length+2; i++)
            {
                for (j = 0; j < array_size; j++)
                {
                    printf("%f\t", grain[i][j]);
                }
                printf("\n");
            }
            printf("\n");
        }   
        MPI_Barrier(MPI_COMM_WORLD);
    }

    if (rank == nproc-1)
    {
        printf("Array from processor %d:\n", rank);
        for (i = 0; i < array_size; i++)
        {
            for (j = 0; j < array_size; j++)
            {
                printf("%f\t", array[i][j]);
            }
            printf("\n");
        }
        printf("\n");
    }

    MPI_Finalize();
    return 0;
}

这是输出。在 Grain 0 中,第一行和最后一行是预期的 0,因为上面和下面的行将被发送并放置在那里。然后第二行是正确的,但第三行缺少 7 和 8 值,它们是 Grain 1 中的第一个值。

Grain 0 中的两个 0 是数组的两个指针地址吗?我不明白为什么当内存中的数组连续存储时,我得到的数据不完整。

我尝试将 scatterv 与位移一起使用,但我不确定我是否理解它是如何工作的。 我也尝试创建一个 MPI 类型,但也没有成功。

我设法将数组的每一行广播到所有其他处理器。但我认为这是非常低效的。我就是这样做的。

for (i=0; i < array_size; i++) 
     MPI_Bcast(&array[i][0], array_size, MPI_DOUBLE, nproc-1, MPI_COMM_WORLD);

非常感谢您的帮助!!

Grain from processor 0:
0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    
0.000000    1.000000    2.000000    3.000000    4.000000    5.000000    6.000000    7.000000    
1.000000    2.000000    3.000000    4.000000    5.000000    6.000000    0.000000    0.000000    
0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    

Grain from processor 1:
0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    
7.000000    8.000000    0.000000    0.000000    2.000000    3.000000    4.000000    5.000000    
8.000000    9.000000    0.000000    0.000000    3.000000    4.000000    0.000000    0.000000    
0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    

Grain from processor 2:
0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    
5.000000    6.000000    7.000000    8.000000    9.000000    10.000000   0.000000    0.000000    
6.000000    7.000000    8.000000    9.000000    10.000000   11.000000   0.000000    0.000000    
0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    

Grain from processor 3:
0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    
0.000000    0.000000    5.000000    6.000000    7.000000    8.000000    9.000000    10.000000   
0.000000    0.000000    6.000000    7.000000    8.000000    9.000000    0.000000    0.000000    
0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    

Array from processor 3:
0.000000    1.000000    2.000000    3.000000    4.000000    5.000000    6.000000    7.000000    
1.000000    2.000000    3.000000    4.000000    5.000000    6.000000    7.000000    8.000000    
2.000000    3.000000    4.000000    5.000000    6.000000    7.000000    8.000000    9.000000    
3.000000    4.000000    5.000000    6.000000    7.000000    8.000000    9.000000    10.000000   
4.000000    5.000000    6.000000    7.000000    8.000000    9.000000    10.000000   11.000000   
5.000000    6.000000    7.000000    8.000000    9.000000    10.000000   11.000000   12.000000   
6.000000    7.000000    8.000000    9.000000    10.000000   11.000000   12.000000   13.000000   
7.000000    8.000000    9.000000    10.000000   11.000000   12.000000   13.000000   14.000000   

【问题讨论】:

  • 您的二维数组必须在连续内存中。现代 C 最简单的选择是声明double array[array_size][array_size]。如果这不是一个选项,快速搜索 SO 将为您指明如何在连续内存中动态分配 2D 数组的正确方向。

标签: multidimensional-array mpi scatter calloc contiguous


【解决方案1】:

我能够通过将发送信息的长度更改为每个单独的进程来实现您想要的结果:

MPI_Scatter(
        &array[0][0], grain_length*array_size, MPI_DOUBLE,
        &grain[1][0], grain_length*array_size, MPI_DOUBLE, 
        nproc-1, MPI_COMM_WORLD);

收件人:

MPI_Scatter(
        &array[0][0], 4+grain_length*array_size, MPI_DOUBLE,
        &grain[1][0], 4+grain_length*array_size, MPI_DOUBLE, 
        nproc-1, MPI_COMM_WORLD);

结果:

    Grain from processor 0:
0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    
0.000000    1.000000    2.000000    3.000000    4.000000    5.000000    6.000000    7.000000    
1.000000    2.000000    3.000000    4.000000    5.000000    6.000000    7.000000    8.000000    
0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    

Grain from processor 1:
0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    
2.000000    3.000000    4.000000    5.000000    6.000000    7.000000    8.000000    9.000000    
3.000000    4.000000    5.000000    6.000000    7.000000    8.000000    9.000000    10.000000   
0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    

Grain from processor 2:
0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    
4.000000    5.000000    6.000000    7.000000    8.000000    9.000000    10.000000   11.000000   
5.000000    6.000000    7.000000    8.000000    9.000000    10.000000   11.000000   12.000000   
0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    

Grain from processor 3:
0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    
6.000000    7.000000    8.000000    9.000000    10.000000   11.000000   12.000000   13.000000   
7.000000    8.000000    9.000000    10.000000   11.000000   12.000000   13.000000   14.000000   
0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    0.000000    

Array from processor 3:
0.000000    1.000000    2.000000    3.000000    4.000000    5.000000    6.000000    7.000000    
1.000000    2.000000    3.000000    4.000000    5.000000    6.000000    7.000000    8.000000    
2.000000    3.000000    4.000000    5.000000    6.000000    7.000000    8.000000    9.000000    
3.000000    4.000000    5.000000    6.000000    7.000000    8.000000    9.000000    10.000000   
4.000000    5.000000    6.000000    7.000000    8.000000    9.000000    10.000000   11.000000   
5.000000    6.000000    7.000000    8.000000    9.000000    10.000000   11.000000   12.000000   
6.000000    7.000000    8.000000    9.000000    10.000000   11.000000   12.000000   13.000000   
7.000000    8.000000    9.000000    10.000000   11.000000   12.000000   13.000000   14.000000   

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 2016-08-25
    • 2017-12-23
    • 2021-12-20
    • 2015-06-02
    • 2018-05-22
    • 2011-06-09
    • 2023-03-17
    • 2016-02-04
    相关资源
    最近更新 更多