MPI学习——jacabi迭代(非阻塞通信与重复阻塞通信)

史上最完整的MPI实现Jacobi(雅可比)迭代算法[C++] 史上最详细的MPI 雅可比迭代算法实现(c++) 阅读详情
      为了实现计算与通信的最大重叠 一个通用的原则就是 尽早开始通信 尽晚完成通信
在开始通信和完成通信之间进行计算 这样通信启动得越早 完成得越晚 就有可能有更多
的计算任务可以和通信重叠 也使通信可以在计算任务执行期间完成 而不需要专门的等待
时间
      为此 修改Jacobi迭代过程如下
        1 计算迭代任务中下次需要通信的数据
        2 启动非阻塞通信 传递这些数据 转下一次迭代
        3 计算剩余的迭代部分

        4 完成非阻塞通信

#include<mpi.h>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 8;
const int SIZE = N / 4;
const int T = 2;


int main()
{
    double matrix1[SIZE+2][N], matrix[SIZE+2][N];
    int myid;
    MPI_Status status[4];
    MPI_Request request[4];


    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &myid);


    memset(matrix1, 0, sizeof matrix1);
    memset(matrix2, 0, sizeof matrix2);


    //赋值边界数据
    if(0 == myid)
        for(int j = 0; j < N; j++)
            matrix1[1][j] = matrix[2][j] = N;
    if(3 == myid)
        for(int j = 0; j < N; j++)
            matrix1[SIZE][j] = matrix2[SIZE][j] = N;
    for(int i = 1; i < SIZE+1; i++)
        matrix1[i][0] = matrix1[i][N-1] = matrix2[0] = matrix2[N-1] = N;

      
    //引入虚拟进程简化代码
    int up_proc_id = myid==0 ? MPI_PROC_NULL : myid - 1;
    int down_proc_id = myid==3 ? MPI_PROC_NULL : myid + 1;
    //jacobi迭代
    int t, row, col;
    for(t = 0; t < T; t++)
    {
        if(0 == myid)
            for(col = 1; col < N-1; col++)
                matrix2[SIZE][col] = 0.25 * (matrix1[SIZE][col-1] + matrix1[SIZE][col+1] + matrix1[SIZE-1][col] + matrix[SIZE+1][col]);
        else if(3 == myid)
            for(col = 1; col < N-1; col++)
                matrix2[1][col] = 0.25 * (matrix1[1][col-1] + matrix1[1][col+1] + matrix1[0][col] + matrix1[2][col]);;
        else
            for(col = 1; col < N-1; col++) // 中间的矩阵块
                matrix2[SIZE][col] = 0.25 * (matrix1[SIZE][col-1] + matrix1[SIZE][col+1] + matrix1[SIZE+1][col] + matrix1[SIZE-1][col]);
                matrix2[1][col] = 0.25 * (matrix1[1][col-1] + matrix1[1][col+1] + matrix1[2][col] + matrix1[0][col]);
        //利用非阻塞通信传递边界数据
        int tag1 = 1, tag2 = 2;
        MPI_Isend(&matrix2[1][0], N, MPI_DOUBLE, up_proc_id, tag1, MPI_COMM_WORLD, request[0]);
        MPI_Isend(&matrix2[SIZE][0], N, MPI_DOUBLE, down_proc_id, tag2, MPI_COMM_WORLD, request[1]);
        MPI_Irecv(&matrix1[SIZE+1][0], N, MPI_DOUBLE, down_proc_id, tag1, MPI_COMM_WORLD, request[2]);
        MPI_Irecv(&matrix1[0][0], N, MPI_DOUBLE, up_proc_id, tag1, MPI_COMM_WORLD, request[3]);


        //利用通信的时间计算矩阵中间值
        int begin_row = 0==myid ? 2 : 1;
        int end_row = 3==myid ? (SIZE-1) : (SIZE);
        for (row = begin_row; row < end_row; row++)
            for (col = 1; col < N-1; col++)
                matrix2[row][col] = 0.25 * (matrix1[row][col-1] + matrix1[row][col+1] + matrix1[row+1][col] + matrix1[row-1][col]);


        //利用通信的时间更新矩阵
        for(row = begin_row; row <= end_row; row++)
            for(col = 1; col < N-1; col++)
                matrix1[row][col] = matrix2[row][col];
        MPI_Waitall(4, &request[0], &status[0]);
    }
    MPI_Barrier(MPI_COMM_WORLD);
    MPI_Finalize();
    return 0;
}

       如果一个通信会被重复执行 比如循环结构内的通信调用 MPI提供了特殊的实现方式 对这样的通信进行优化 以降低不必要的通信开销 它将通信参数和MPI的内部对象建立固 定的联系 然后通过该对象完成重复通信的任务 。大致步骤如下
      1 通信的初始化 比如MPI_SEND_INIT       
      2 启动通信 MPI_START       
      3 完成通信 MPI_WAIT       
      4 释放查询对象 MPI_REQUEST_FREE

#include<mpi.h>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 8;
const int SIZE = N / 4;
const int T = 2;

int main()
{
    double matrix1[SIZE+2][N], matrix[SIZE+2][N];
    int myid;
    MPI_Status status[4];
    MPI_Request request[4];

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &myid);

    memset(matrix1, 0, sizeof matrix1);
    memset(matrix2, 0, sizeof matrix2);

    //赋值边界数据
    if(0 == myid)
        for(int j = 0; j < N; j++)
            matrix1[1][j] = matrix[2][j] = N;
    if(3 == myid)
        for(int j = 0; j < N; j++)
            matrix1[SIZE][j] = matrix2[SIZE][j] = N;
    for(int i = 1; i < SIZE+1; i++)
        matrix1[i][0] = matrix1[i][N-1] = matrix2[0] = matrix2[N-1] = N;
    //引入虚拟进程简化代码
    int up_proc_id = myid==0 ? MPI_PROC_NULL : myid - 1;
    int down_proc_id = myid==3 ? MPI_PROC_NULL : myid + 1;
    //初始化重复非阻塞通信
    int tag1 = 1, tag2 = 2;
    MPI_Send_init(&matrix2[1][0], N, MPI_DOUBLE, up_proc_id, tag1, MPI_COMM_WORLD, request[0]);
    MPI_Send_init(&matrix2[SIZE][0], N, MPI_DOUBLE, down_proc_id, tag2, MPI_COMM_WORLD, request[1]);
    MPI_Recv_init(&matrix1[SIZE+1][0], N, MPI_DOUBLE, down_proc_id, tag1, MPI_COMM_WORLD, request[2]);
    MPI_Recv_init(&matrix1[0][0], N, MPI_DOUBLE, up_proc_id, tag1, MPI_COMM_WORLD, request[3]);
    //jacobi迭代
    int t, row, col;
    for(t = 0; t < T; t++)
    {
        if(0 == myid)
            for(col = 1; col < N-1; col++)
                matrix2[SIZE][col] = 0.25 * (matrix1[SIZE][col-1] + matrix1[SIZE][col+1] + matrix1[SIZE-1][col] + matrix[SIZE+1][col]);
        else if(3 == myid)
            for(col = 1; col < N-1; col++)
                matrix2[1][col] = 0.25 * (matrix1[1][col-1] + matrix1[1][col+1] + matrix1[0][col] + matrix1[2][col]);;
        else
            for(col = 1; col < N-1; col++) // 中间的矩阵块
                matrix2[SIZE][col] = 0.25 * (matrix1[SIZE][col-1] + matrix1[SIZE][col+1] + matrix1[SIZE+1][col] + matrix1[SIZE-1][col]);
                matrix2[1][col] = 0.25 * (matrix1[1][col-1] + matrix1[1][col+1] + matrix1[2][col] + matrix1[0][col]);
        //启动非阻塞通信传递边界数据
        MPI_Startall(4, &request[0]);

        //利用通信的时间计算矩阵中间值
        int begin_row = 0==myid ? 2 : 1;
        int end_row = 3==myid ? (SIZE-1) : (SIZE);
        for (row = begin_row; row < end_row; row++)
            for (col = 1; col < N-1; col++)
                matrix2[row][col] = 0.25 * (matrix1[row][col-1] + matrix1[row][col+1] + matrix1[row+1][col] + matrix1[row-1][col]);

        //利用通信的时间更新矩阵
        for(row = begin_row; row <= end_row; row++)
            for(col = 1; col < N-1; col++)
                matrix1[row][col] = matrix2[row][col];
        MPI_Waitall(4, &request[0], &status[0]);
    }
    //释放非阻塞通信对象
    for(int i = 0; i < 4; i++) MPI_Request_free(&request[i]);
    MPI_Barrier(MPI_COMM_WORLD);
    MPI_Finalize();
    return 0;
}




并行程序设计基础——并行模式之对等模式 通过雅克比迭代的多种MPI并行实现介绍了MPI并行程序设计模式中的对等模式 阅读详情

相关推荐

MPI非阻塞通信使用、性能分析与实现原理

非阻塞通信: 异步通信通常是使MPI应用程序实现高性能计算的关键,使用异步通信具有如下优势: 1)函数是非阻塞的,这使得进程在与另一个进程通信的同时继续参与计算; 2)如果应用适当,可以绕过MPI的内部buffers,极大地提高程序的通信带宽; 最常见的基本的非阻塞调用就是MPI_Isend和MPI_Irecv MPI_Isend的使用 与同步版本的MPI_Send不同,MPI

qq100440110的专栏 8450

MPI jacobi iterator (c++ version)

因为原文只有fortran,而且评论链接里的代码没有考虑c++是row major的储存格式,在这里提供对应的C++代码。

Amadeus_Physics的博客 202

学习笔记:MPI非阻塞通信

学习笔记-MPI非阻塞通信 非阻塞通信主要用于计算和通信的重叠。 在非阻塞通信中,同样有之前提到的四种通信模式,其效果是将非阻塞通信的基本特征和具体的通信模式相结合后的综合体现。 非阻塞通信模式 发送 接收 标准 MPI_Isend MPI_Irecv 缓存 MPI_Ibsend MPI_Irecv 同步 MPI_Issend MPI_Irecv 就绪 MPI_Irse...

2450

MPI C++ jacobi迭代

MPI C++ 实现jacobi迭代,

zx1772874955的博客 1139

Jacobi迭代的MPI进阶——计算通信重叠和虚拟进程的使用

这里先放Makefile和run.slurm Makefile run.slurm 使用阻塞通信实现不同进程之间的消息传递, rank=0: send,recv rank=1: recv,send, send,recv …:recv,send,send,recv rank = size - 1:recv,send上面涉及到相邻进程的消息互换,所以为了方便起见,我们也可以使用send_recv函数来完成相邻进程之间的消息传递,但是另一方面我们发现上面这种写法其实需要对rank进行分类,中间的rank需要两次

forrestguang的博客 1027

使用boost::mpi::wait_all的示例程序(C/C++)

然后,我们创建了一个std::vector来存储所有的MPI通信请求(mpi::request)。首先,我们创建了一个mpi::environment对象来初始化MPI环境,并创建了一个mpi::communicator对象来表示所有通信进程。接下来,我们将展示一个简单的示例,其中包含了使用boost::mpi::wait_all函数的代码。以下是一个使用boost::mpi::wait_all函数的示例程序,该函数用于等待所有MPI通信操作的完成。本文将介绍该函数的用法,并提供相应的源代码。

HackDyno的博客 134

21.11.7学习记录

1.在子网格生成刚度矩阵后,如何分发对应行到对应进程时遇到的问题: 想达成的目标:每个代码根据已经生成好的send_info和recv_info发送对应信息至对应进程,同时接收来自其他进程的对应信息 尝试1:MPI_Send & Recv 尝试1错误:阻塞通信,每个进程不完成发送操作不会进行下一步接收操作,死锁 尝试2:MPI_Isend & Irecv 尝试2错误:通讯正常,但是由于没有等待所有通讯完成就进行接下来的操作,导致实际上不会完成通讯 最终解决方法:使用MPI_Wa

yiaoxing0794的博客 430

基于MPI的并行计算实现Jacobi迭代

基于MPI的并行计算实现Jacobi迭代

Jacobi迭代法

我们在求解矩阵时,有很多种方法,其中当矩阵是大型稀疏矩阵(矩阵中有大部分元素都为0)时,我们可以用迭代法求解。 其中Jacobi迭代法就是很简单易懂的一种。 我编写的C++代码如下,其中文件matrix.txt内容如下, 第一行的第一个数字表示矩阵的行数或者列数,因为rows==cols 下面的三行表示矩阵本体 最后的一行表示该矩阵和向量(x1,x2,x3) 相乘后的结果 ...

阿桑的专栏 3万+

MPI并行程序雅克比迭代

这是大学课程 mpi并行程序设计实例教程上课中 讲解的雅克比迭代 的代码。

从零开始:使用COLMAP与OpenMVS构建高精度三维Mesh模型

本文为零基础新手提供了使用COLMAP与OpenMVS构建高精度三维Mesh模型的完整实战指南。详细介绍了从环境配置、数据采集黄金法则,到COLMAP稀疏与稠密重建、OpenMVS网格生成与纹理映射的每一步操作,并分享了关键的避坑技巧与参数调优建议,帮助读者从二维照片中成功重建出属于自己的三维模型。

metal的博客 505

入门并行编程MPI(五)

检查一个交易所的执行情况 当几个进程同时交换消息时,可以使用同时适用于几个交换的检查。 这种检查有三种类型。 检查所有交换的完成情况。 检查多个交易所之间任何交易所的终止情况。 在几个交换中检查一个特定交换的完成情况。 每种支票都有两个品种。 "待定"。 "检查"。 阻止验证操作 MPI_Wait子程序阻止进程的运行,直到消息完成。 int MPI_Wait(MPI_Request *request, MPI_Status *status) MPI_Wait(reques

JiangTao2333的博客 2271

ROS2与Gazebo协同实现多机器人避障仿真

本文详细介绍了如何利用ROS2与Gazebo协同搭建多机器人避障仿真环境。通过创建SDF机器人模型、编写多机器人启动文件以及集成基础避障算法,构建了一个低成本、高效率的虚拟测试平台,为AGV编队、机器人集群等项目的算法验证与迭代提供了完整解决方案。

weixin_29065659的博客 294

MPI 点对点通信

定义 点对点通信是两个进程之间的通信,从源进程发送消息到目标进程。通信是发生在同一个通信器内,并且进程可以通过其在通信器内的标号标识。 MPI 系统的通信方式都是建立在点对点通信之上。 阻塞式点对点通信 阻塞式点对点通信主要涉及四个函数: MPI_SEND MPI_Recv MPI_Get_count(查询接收到的消息长度) MPI_Sendrecv(捆绑发送和接受) 消息 MPI 消息包括信封和数据两个部分。信封指出了发送或接收消息的对象及相关信息,而数据是本消息将要传递的内容。信封和数据又分别包括三个部

帅比王的博客 4337

SFF-8654接口引脚定义全解析:从SAS到U.2的高速硬件连接核心

在高速数据存储与传输领域,接口标准是连接主机与存储设备、确保信号完整性与协议互通性的物理基础。其核心原理在于通过精确定义的物理引脚和电气特性,承载不同的高速串行通信协议,如SAS和PCIe。这类高密度连接器的技术价值在于以紧凑的形态支持多协议兼容与高速率传输,满足了企业级存储、高性能计算对带宽和可靠性的苛刻要求。典型的应用场景包括服务器硬盘背板连接、NVMe U.2固态硬盘直连以及外部存储扩展。本文聚焦于SFF-8654(亦称Mini SAS HD)这一关键接口,深入剖析其引脚定义、信号分区(如高速数据通道

weixin_29188043的博客 707

基于Codex平台与AI Agent技能开发,实现抖音爆款视频分析与脚本自动生成

大家好,我是专注于AI应用开发的技术博主。最近在探索如何利用AI工具自动化内容创作时,我发现了一个非常有趣的组合:通过Codex平台创建自定义的Skill(技能),来批量分析抖音平台的爆款视频,并基于分析结果自动生成新的带货视频脚本。这听起来像是内容团队的“黑科技”,但实现起来其实有清晰的路径可循。本文将为你完整拆解这个实战项目,从环境搭建、Skill编写、数据抓取到视频脚本生成,手把手教你打造自己的“AI内容助理”。无论你是想了解AI Agent的开发,还是对短视频自动化创作感兴趣,都能从本文中获得可直接

weixin_34110749的博客 644

【MPI】非阻塞通信(点对点)

MPI点对点通信中非阻塞通信的学习,实现计算和通信重叠,并对jacobi进行优化.

weixin_43730667的博客 528

【实战解析】Ubuntu双网卡冲突:如何解决同一网段下网关无法访问及上网问题

本文深入解析Ubuntu服务器双网卡配置在同一网段时引发的路由冲突问题,导致网关无法ping通及无法上网。通过分析路由表与Metric值原理,提供使用route命令调整优先级及修改Netplan配置文件的实战解决方案,确保主次路由明确,一劳永逸解决网络冲突。

f9g0h的博客 280

(三)MPI中的阻塞式和非阻塞式

1.MPI阻塞式通信的一个例子 先看下面这段程序,可以看到每个进程都调用了两次MPI_Bcast(),其中第一次广播的数据为字符串HelloStr的长度,第二次广播的数据为HelloStr字符串本身。所以可以很容易地理解到,0号进程要向其他进程广播一个任意长度地字符串时,需要分为两步,第一次先向组中的其他进程广播字符串的长度,第二次广播字符串本身;其他进程在接收时,要先接收到从0号进程发送来的字符...

xinwuya_的博客 7865

从零到一:树莓派OpenWrt squashfs固件扩容背后的文件系统魔法

本文深入解析树莓派OpenWrt系统中squashfs固件的扩容原理与操作。通过理解squashfs与overlayfs的协同机制,掌握分区调整和文件系统扩容技巧,解决存储空间限制问题,提升设备可用性。

hadoop5ranger的博客 1037

GQA数据集介绍

GQA,这是一个用于真实世界视觉推理和组合问答的新数据集。2200万个不同的推理问题,所有这些问题都带有表示其语义的功能程序。答案分布受到严格控制。11.3万张图像、2200万个问题,推理能力有对象和属性识别、传递关系跟踪、空间推理、逻辑推理和比较。

qq_56551150的博客 2954

MPI非阻塞式点对点通信

非阻塞通信是一种通信方式,允许程序在消息发送或接收的过程中,不必等待操作完成而继续执行其他任务。这种方式能够提高并行程序的效率,因为程序不再因为等待通信完成而停滞。与之相对的是阻塞通信,它要求程序必须等待消息传递完成后才能继续执行。

weixin_74939789的博客 1320

JumpServer未授权访问漏洞 CVE-2023-42442

JumpServer 是全球首款完全开源的堡垒机, 使用GNU GPL v2.0 开源协议, 是符合4A 的专业运维审计系统。 JumpServer 使用Python / Django 进行开发。2021年1月15日,阿里云应急响应中心监控到开源堡垒机JumpServer发布更新,修复了一处远程命令执行漏洞。由于 JumpServer 某些接口未做授权限制,攻击者可构造恶意请求获取到日志文件获取敏感信息,或者执行相关API操作控制其中所有机器。

holyxp的博客 1423

MPI中的非阻塞通信

MPI中的非阻塞通信   前面已经介绍了阻塞通信和非阻塞通信的区别。下面我们介绍MPI中对非阻塞通信的支持,和通常的调用模式。   上面的四种通信模式都有对应的非阻塞通信模式。他们对应的函数如下:   标准通信模式: MPI_ISEND MPI_IRECV   缓冲通信模式: MPI_IBSEND   同步通信模式: MPI_ISSEND   就绪通信模式:

chrysanthemumcao的专栏 1万+

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

并行计算之MPI简介以及基本通信案例(阻塞,非阻塞)

MPI_Test 函数的作用与 MPI_Wait 函数类似,都是等待一个请求对象进入完成状态,但 MPI_Test 函数是非阻塞的,即当请求对象尚未完成时,MPI_Test 函数会立即返回一个标志值,而不会阻塞当前进程的执行。通信域中的每个进程都有一个唯一的标识符(通信域内部的秩/等级(rank)),并可以通过指定目标进程的标识符来对目标进程进行通信。,在每个阶段中,数据沿着流水线被处理,不同的进程专门处理不同的阶段。拥有一个主进程,主进程作为任务的分配方,从进程执行任务,主进程负责管理数据的分发和接受;

KingOfMyHeart的博客 5096

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

MPI之非阻塞通信中通信完成检测接口简介

个 MPI 请求组成的数组中的任一组请求是否已经完成,如果有已完成请求,则返回已完成操作的数量,并将这些完成操作的索引值存储在。个 MPI 请求组成的数组中的任一请求是否已经完成,如果有已完成请求,则返回其在数组中的索引值,并将该值存储在。个 MPI 请求组成的数组中的任一请求完成,返回值为完成操作的请求在数组中的索引值,将该值存储在。个 MPI 请求组成的数组中的所有请求是否都已经完成,如果所有请求都已经完成,则返回值。个 MPI 请求组成的数组中所有请求完成,返回值为。如果没有请求已经完成,则返回值。

KingOfMyHeart的博客 419

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

上一篇: MPI相关函数
下一篇: MPI学习——进程组与通信域相关函数
Interstellar_
博客等级 码龄10年 8粉丝 121原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值