如何在MPI中传递2D数组并使用C语言创建动态标签值?

2024-05-08

我是 MPI 编程新手。我有一个 8 x 10 数组,需要用它来并行查找每行的总和。在等级 0(进程 0)中,它将使用 2 维数组生成 8 x 10 矩阵。然后我会用tagnumber 作为数组的第一个索引值(行号)。这样,我可以使用唯一的缓冲区通过 Isend 发送。但是,我的 Isend 标签号生成方法似乎不起作用。您能否查看以下代码并告诉我是否正确传递了二维数组和标签号。当我运行此代码时,它在执行 rannk 1 后立即停止并等待。我在这个例子中使用了 3 个进程并使用命令mpirun -np 3 test如果可能的话,请让我知道如何通过示例来解决这个问题。

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

int main (int argc, char *argv[])
{
        MPI_Init(&argc, &argv);
        int world_rank;
        MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
        int world_size;
        MPI_Comm_size(MPI_COMM_WORLD, &world_size);        
        int tag = 1;        
        int arr[8][10]; 
        MPI_Request request;
        MPI_Status status;
        int source = 0;
        int dest;

        printf ("\n--Current Rank: %d\n", world_rank);

        if (world_rank == 0)
        {
            int i = 0;
            int a, b, x, y;

            printf("* Rank 0 excecuting\n");

            for(a=0; a<8/(world_size-1); a++)//if -np is 3, this will loop 4 times
            {           
                for(b=0; b<(world_size-1); b++)//if -np is 3, this loops will loop 2 times
                {//So, if -np is 3, due to both of these loops, Isend will be called 8 times
                    dest = b+1;     
                    tag = a+b;//create a uniqe tag value each time, which can be use as first index value of array
                    //Error: This tag value passing to Isend doesn't seems to be workiing
                    MPI_Isend(&arr[tag][0], 10, MPI_INT, dest, tag, MPI_COMM_WORLD, &request);  
                }
            }

            for(x=0; x<8; x++)//Generating the whole 8 by 10 2D array
            {   
                i++;
                for ( y = 0; y < 10; y++ )
                {
                    arr[x][y] = i; 
                }   
            }               
        }
        else 
        {
            int a, b;                   
            for(b=1; b<=8/(world_size-1); b++)
            {
                int sum = 0;
                int i;
                MPI_Irecv(&arr[tag][0], 10, MPI_INT, source, tag, MPI_COMM_WORLD, &request);
                MPI_Wait (&request, &status);               
                        //Error: not getting the correct tag value
                for(i = 0; i<10; i++)
                {   
                    sum = arr[tag][i]+sum;
                }
                printf("\nSum is: %d at rank: %d and tag is:%d\n", sum, world_rank, tag);
            }           
        }
        MPI_Finalize();
}

标签问题是由于如何在不同进程上计算(或不计算)标签而导致的。您正在将所有进程的标签值初始化为

int tag = 1; 

之后,对于进程等级 0,您将标记设置为

tag = a+b;

这是第一次设置,将设置tag为 0 因为两者a and b从零开始。但是,对于等级高于 0 的进程,标记永远不会更改。他们将继续将标签设置为 1。

该标签唯一标识正在发送的消息MPI_Isend and MPI_Irecv,这意味着发送及其相应的接收必须具有相同的标记才能使数据传输成功。由于大多数接收进程之间的标签不匹配,因此传输大多不成功。这会导致排名高于 0 的进程最终在调用时永远阻塞(等待)MPI_Wait.

为了解决这个问题,您必须确保更改排名高于零的进程的标签。然而,在我们做到这一点之前,还有一些其他问题值得讨论。

按照您现在为排名 0 进程设置标签的方式,tag只能有 0 到 4 的值(假设有 3 个进程)。这是因为a限制在 0 到 3 的范围内,并且b只能有值 0 或 1。这些值的最大可能总和是 4。这意味着当您使用arr[tag][0],您将错过很多数据,并且您将多次重新发送相同的行。我建议更改发送每个子数组的方式(您当前正在使用tag),这样您就只有一个 for 循环来确定要发送哪个子数组,而不是两个嵌入式循环。然后,您可以计算将数组发送到的过程:

dest = subarray_index%(world_size - 1) + 1;

这将在等级大于零的进程之间交替目的地。您可以将标签保留为subarray_index。在接收端,您需要计算每个进程、每个接收的标签。

最后,我看到您在发送数据后正在初始化数组。你想提前这样做。

结合所有这些方面,我们得到

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

int main (int argc, char *argv[])
{
        MPI_Init(&argc, &argv);
        int world_rank;
        MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
        int world_size;
        MPI_Comm_size(MPI_COMM_WORLD, &world_size);        
        int tag = 1;        
        int arr[8][10]; 
        MPI_Request request;
        MPI_Status status;
        int source = 0;
        int dest;

        printf ("\n--Current Rank: %d\n", world_rank);

        if (world_rank == 0)
        {
            int i = 0;
            int a, b, x, y;

            printf("* Rank 0 excecuting\n");
            //I've moved the array generation to before the sends.
            for(x=0; x<8; x++)//Generating the whole 8 by 10 2D array
            {   
                i++;
                for ( y = 0; y < 10; y++ )
                {
                    arr[x][y] = i; 
                }   
            }

            //I added a subarray_index as mentioned above.
            int subarray_index;
            for(subarray_index=0; subarray_index < 8; subarray_index++)
            {
                dest = subarray_index%(world_size - 1) + 1;     
                tag = subarray_index;
                MPI_Isend(&arr[subarray_index][0], 10, MPI_INT, dest, tag, MPI_COMM_WORLD, &request);
            }

        }
        else 
        {
            int a, b;                   
            for(b=0; b<8/(world_size-1); b++)
            {
                int sum = 0;
                int i;
                //We have to do extra calculations here. These match tag, dest, and subarray.
                int my_offset = world_rank-1;
                tag = b*(world_size-1) + my_offset;
                int subarray = b;
                MPI_Irecv(&arr[subarray][0], 10, MPI_INT, source, tag, MPI_COMM_WORLD, &request);
                MPI_Wait (&request, &status);               
                for(i = 0; i<10; i++)
                {   
                    sum = arr[subarray][i]+sum;
                }
                printf("\nSum is: %d at rank: %d and tag is:%d\n", sum, world_rank, tag);
            }           
        }
        MPI_Finalize();
}

在这个版本中,有一件事似乎还没有完成,需要你考虑:如果你的进程数量发生变化,会发生什么?例如,如果您有 4 个进程而不是 3 个,那么循环可能会遇到一些问题

for(b=0; b<8/(world_size-1); b++)

因为每个进程都会执行相同的次数,但发送的数据量并不能完全分配给 3 个工作进程(非零级进程)。

但是,如果您不关心这一点,那么您就不需要处理此类情况。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在MPI中传递2D数组并使用C语言创建动态标签值? 的相关文章

随机推荐

  • UIModalPresentationFormSheet 的圆角

    如果这是一个明显的问题 请原谅我 我是个相对较新的人 我有一个模态视图 我设置了自定义尺寸和圆角 void viewWillLayoutSubviews super viewWillLayoutSubviews self view supe
  • 如何使用一个凉亭同时创建两个地图?

    如下图所示 现在我的gazebo正在运行2个slam gmapping包 首先是 turtlebot slam gmapping 发布到 map 主题 第二个是 slam gmapping 发布到与第一个相同的 map 主题 我想创建一个新
  • 在操作栏中编辑文本

    我正在使用 Action Bar Sherlock 为我的应用程序创建 UI 在将依赖项添加到我的项目等后 我创建了一个活动来测试它 public class PPS extends SherlockActivity Override pu
  • 在用例建模中分解 CRUD

    我有一个后续问题用例图中的 CRUD https stackoverflow com questions 7772399 crud in a use case diagram 如果我需要分解复杂的用例 例如 管理用户 假设这很复杂 可以将它
  • 管道序列中的异常处理

    我正在开发一个基本的 2D CAD 引擎 管道操作符显着改进了我的代码 基本上 有几个函数从空间中的点 x y 开始 并在多次移动操作后计算最终位置 let finalPosition startingPosition gt moveByL
  • SeekBar setProgress 丢弃次要进度

    我的小学和中学的进步是同时增长的 中学的进步比小学的进步快 每次我更新主要进度时 次要进度都会丢失 就像它为零或小于主要进度一样 这会产生令人讨厌的闪烁 我发现的唯一解决方法是在设置主数据库后将辅助数据库设置为自身 我添加了 1 因为 Se
  • 如何使用延迟位置 iOS 6?

    我正在尝试使用新的 iOS 6 延迟位置更新功能 但不断收到此错误 didFinishDeferredUpdatesWithError Error Domain kCLErrorDomain Code 11 操作无法完成 kCLErrorD
  • 检查数独字段的很酷的算法?

    有谁知道一个简单的算法来检查数独配置是否有效 我想出的最简单的算法是 对于大小为 n 的板 伪代码 for each row for each number k in 1 n if k is not in the row using ano
  • 奇异矩阵 - python

    下面的代码显示了矩阵的奇异性问题 因为在 Pycharm 中工作我得到 raise LinAlgError Singular matrix numpy linalg linalg LinAlgError Singular matrix 我猜
  • 修改 Settings.apk 以与 Project Glass 配合使用

    我正在尝试构建要在 Google I O 的 Hacking Glass 会议上在 Glass 上使用的 Settings apk 他提到 为了让设置 apk 正常工作 需要修改清单中的一行 这是 AOSP 清单 http pastebin
  • 在 Metal 中,将顶点和片段缓冲区设置为相同的 MTLBuffer 是否仅将其复制到 GPU 一次?

    我将统一缓冲区传递给顶点着色器和片段着色器 let uniformBuffer device makeBuffer length 4096 options renderEncoder setVertexBuffer uniformBuffe
  • 通过串行端口通过诺基亚手机发送短信

    我正在尝试通过诺基亚手机通过串口发送短信 这通过腻子很容易 命令来自诺基亚文档 http wiki forum nokia com index php Using AT commands to send and read SMS工作正常 然
  • vim 映射键不起作用

    我一直在尝试映射 ctrl 来在 vim 的插入模式下保存 它似乎永远不起作用 http vim wikia com wiki Map Ctrl S to save current or new files http vim wikia c
  • 如何在淘汰赛模板中控制日志

    我认为这是正确的 div div
  • 文件夹包含在 tar.gz 中,而不是在wheel、setuptools build 中

    自动发现setuptools build meta将不应包含的顶级文件夹包含到 tarball 中 我们试图建立一个蟒蛇包 https gitlab com octopus code postopus with python3 m buil
  • Windows 中“nice”的等效词

    Windows 中是否有相当于 Unix 命令的命令 nice 我正在专门寻找可以在命令行中使用的东西 并且not任务管理器中的 设置优先级 菜单 我在谷歌上寻找这个的尝试被那些想不出更好形容词的人挫败了 如果您想在启动进程时设置优先级 您
  • Yii2迁移问题

    我是第一次使用 yii2 我想尝试 yii 迁移 问题 我创建了迁移文件 php yii migrate create new table 文件已创建 然后我将新表详细信息输入到迁移文件中 当我跑步时php yii migrate我收到错误
  • readFile() 和 readFileSync() 之间的区别

    以下代码将index html 的内容 仅包含文本hello world 输出到浏览器 然而 当我更换readFile with readFileSync 请求超时 我缺少什么 是否需要不同类型的缓冲区 我使用的是node 0 61 和ex
  • 在 Ruby on Rails 中渲染部分集合正在乘以项目

    我想在 Ruby on Rails 的页面中显示项目列表 我使用部分 in my index html erb我有的文件 in list news html erb I have div class news div
  • 如何在MPI中传递2D数组并使用C语言创建动态标签值?

    我是 MPI 编程新手 我有一个 8 x 10 数组 需要用它来并行查找每行的总和 在等级 0 进程 0 中 它将使用 2 维数组生成 8 x 10 矩阵 然后我会用tagnumber 作为数组的第一个索引值 行号 这样 我可以使用唯一的缓