基于C语言实现并行程序设计

article/2025/4/30 15:54:11

资源下载地址:https://download.csdn.net/download/sheziqiong/86771681
资源下载地址:https://download.csdn.net/download/sheziqiong/86771681

lab1

  1. 分别用omp和mpi实现树型求和和蝶式求和
    树型omp实现思路:对每一层的计算并行化,对叶节点编号,序号值为线程号。
    考虑兄弟结点相加时把结果存在序号较小的结点中。
    将二叉树每一次计算步骤编号为1-n步,因为任务数为2的幂次方,因 此n= log_2⁡N
    要并行化的计算是每一步的节点与兄弟节点的加法。每一步的节点序 号与兄弟节点序号的差值为2^(n−i),i为步数。将加法交予不同的线程并行实现。
    分发结果就是求和的逆向实现,区别在于是自上而下的。

    实验结果:

    树型mpi实现思路:在计算全和时,在第i步,进程id整除2^(n−i +1) 的负责接收数据并求和,其余进程负责发送数据。
    在分发全和时,在第i步,进程id整除2^(n−i+1) 的负责发送数据,其余进程负责接收数据。
    发送与接收数据的进程编号在第i步相差2^(n−i) 。

    //主要代码:  
    for (int i = 1; i <= logN; i++)
    {int tag = i;int step = (int)pow(2, i);if (pid % step == 0){MPI_Recv(&recvdata, 1, MPI_INT, pid+step/2,     tag, MPI_COMM_WORLD, &status);data += recvdata;}elseif(pid % step == step/2){MPI_Send(&data, 1, MPI_INT, pid-step/2, tag,    MPI_COMM_WORLD);}
    }
    //spread
    for (int i = logN; i >0; i--)
    {int tag = i;int step = (int)pow(2, i);if (pid % step == 0){MPI_Send(&data, 1, MPI_INT, pid+step/2, tag,    MPI_COMM_WORLD);}elseif(pid % step == step/2){MPI_Recv(&recvdata, 1, MPI_INT, pid-step/2,     tag, MPI_COMM_WORLD, &status);data = recvdata;}}    
    

    实验结果:

    蝶式求和omp实现思路:仍然是对每一步的计算并行化,对叶节点编 号,序号值为线程号。考虑兄弟结点相加时把结果存在序号较小的结点中。
    依然将计算步骤编号从开始到结束编为1-n步,因为任务数为2的幂次方,因此n= log_2⁡N
    要并行化的计算是每一步的节点与兄弟节点的加法。关键在于如何确定相加节点的序号差值。
    将编号写为n位的二进制格式,可以发现,在第i步,相加的节点序号恰好在第i位不同,而其余位都相同。

    //主要代码:
    for (int i = 0; i < logN; i++)
    {step = (int)pow(2, i);
    #pragma omp parallel private(pid, tmp, dest){pid = omp_get_thread_num();tmp = num[pid];dest = pid^step;tmp = num[pid] + num[dest];
    #pragma omp barriernum[pid] = tmp;
    #pragma omp barrier}
    }
    

    实验结果:

    蝶式求和mpi实现思路:思路与omp实现相同,区别在于不用关心哪两个节点相加,
    此时发送目的进程和接受来源进程的id的二进制格式在第i步时的第i位不同。

    //主要代码:  
    int logN = (int)log2(num_procs);
    for(int i = 0; i < logN; i++) {int tag = i+1;int step = (int)pow(2,i);int dest = id_procs ^ step;MPI_Send(&data, 1, MPI_INT, dest, tag,  MPI_COMM_WORLD);MPI_Recv(&recvdata, 1, MPI_INT, dest, tag,  MPI_COMM_WORLD, &status);data += recvdata;
    }
    

    实验结果:

  2. 实现MyBcast()
    思路:
    (1)将MPI进程按所在节点划分子通讯域N;
    (2)可以将各子通讯域的首进程(编号为0)再组成一个子通讯域H;
    (3)由广播的root进程将消息发给原来最大通讯域中的0号进程h,再由h在H通讯域中广播(MPI_Bcast),各首进程然后在各自子通讯域N中再行广播(MPI_Bcast);
    (4)子通讯域H:将N的首进程通过MPI_Group_incl()函数建立一个组,再用MPI_Comm_create()建立子通讯域H。

    //伪代码
    MPI_Comm_split(MPI_COMM_WORLD, color, key, &split_comm_world);
    建立MPI_COMM_WORLD的进程组World_Group;
    通过World_Group建立h_Group;
    PI_Comm_create(MPI_COMM_WORLD, h_Group, &h_comm_world);
    oot进程发送消息:MPI_Send(data, count, MPI_TYPE, 0, 1, MPI_COMM_WORLD);
    原通讯域的0号进程接收:MPI_Recv(data, count, MPI_TYPE, root, 1, MPI_COMM_WORLD,&status);
    号进程在H中广播:MPI_Bcast(data, count, MPI_TYPE, 0, h_comm_world);
    在N中广播MPI_Bcast(data, count, MPI_TYPE, 0, split_comm_world);
    ```http://www.biyezuopin.vip
    ```c
    //主要代码:
    MPI_Comm h_comm_world;
    MPI_Comm_group(MPI_COMM_WORLD, &world_group);
    int grpsize = num_procs / 2;
    int zerolist[] = {0, 1, 2, 3};
    int zerocnt = 0;MPI_Group_incl(world_group, grpsize, zerolist, &    new_group);
    MPI_Comm_create(MPI_COMM_WORLD, new_group, &    h_comm_world);
    // message from root to 0 proc of MPI_COMM_WORLD
    if (id_procs == root)
    {MPI_Send(&seq, 16, MPI_CHAR, 0, 1, MPI_COMM_WORLD);
    }
    else if (id_procs == 0)
    {MPI_Recv(&seq, 16, MPI_CHAR, root, 1,   MPI_COMM_WORLD, &status);
    }
    MPI_Barrier(MPI_COMM_WORLD);
    // Broadcast within the group H
    if(h_comm_world != MPI_COMM_NULL)MPI_Bcast(&seq, 16, MPI_CHAR, 0, h_comm_world);
    MPI_Barrier(MPI_COMM_WORLD);
    //Broadcasr within the group NMPI_Bcast(&seq, 16, MPI_CHAR, 0, split_comm_world);
    MPI_Barrier(MPI_COMM_WORLD);
    

    实验结果:

  3. 用MPI_Send和MPI_Recv来模拟实现诸如MPI_Alltoall, MPI_Allgather功能并与标准MPI实现做简要性能对比.

    //MPI_Alltoall实现
    void MPI_Alltoall_my(int* senddata, int sendcount, MPI_Datatype senddatatype, int* recvdata, int recvcount,
    MPI_Datatype recvdatatype, MPI_Comm comm)
    {int rank, size;MPI_Status status;MPI_Comm_rank(comm, &rank);MPI_Comm_size(comm, &size);for (int i = 0; i < size; i++){if (i != rank){MPI_Send(senddata + i * sendcount, sendcount,       senddatatype, i, rank , comm);MPI_Recv(recvdata + i * recvcount, recvcount,       recvdatatype, i, i, comm, &status);}else{//memcpy(recvdata + i * recvcount, senddata,        sizeof(senddatatype)*sendcount);recvdata[i] = senddata[i];}}
    }
    
    //MPI_Allgather实现  
    void MPI_Allgather_my(int* senddata, int sendcount, MPI_Datatype senddatatype, int* recvdata, int recvcount,
    MPI_Datatype recvdatatype, MPI_Comm comm)
    {int rank, size, i;MPI_Status status;MPI_Comm_rank(comm, &rank);MPI_Comm_size(comm, &size);for (i = 0; i < size; i++){if (i != rank){MPI_Send(senddata, sendcount, senddatatype, i,      rank , comm);MPI_Recv(recvdata + i * recvcount, recvcount,       recvdatatype, i, i, comm, &status);}else{//memcpy(recvdata + i * recvcount, senddata,        sizeof(senddatatype)*sendcount);recvdata[i] = *senddata;}}
    }
    

    性能对比:

lab2

  1. 用mpi和omp实现LU分解

    • 原理
      利用主行i对j >i的其他行做初等行变换,由于各行计算时没有数据相关,因此可以对矩阵按行划分做并行计算。课本的并行算法考虑到各处理器之间的负载均衡,使用的是交叉行划分。划分后各处理器轮流选出主行并广播给其他处理器,其他处理器利用接收的主行对部分行向量进行计算。
    • 思路
      在课本第18章附录2的LU分解的MPI实现上,对处理器用主行做行变换的循环部分用openmp实现for编译制导,将计算平均分给各线程处理,其他不动。

    实验结果(只跑了6维矩阵和5维矩阵作为演示):


    性能对比:

    线程数100 * 1001000 * 100010000 * 10000
    20.1143s0.55024s237.638s
    40.0968s0.508s229.686s
    80.1019s0.349117s201.801s
  2. 用纯omp实现QR分解
    QR分解的串行算法有三层循环,直接对最内层循环做并行化处理。

    //主要代码  
    for(int j = 0; j < N; j++){for (int i = j+1; i < N; i++){sq = sqrt(A(j, j) * A(j, j) + A(i, j) * A(i, j));c = A(j, j)/sq;s = A(i, j)/sq;int k ;#pragma omp parallel for private(k)for (k = 0; k < N; k++){Aj[k] = c * A(j, k) + s * A(i, k);Qj[k] = c * Q(j, k) + s * Q(i, k); Ai[k] = - s * A(j, k) + c * A(i, k);Qi[k] = - s * Q(j, k) + c * Q(i, k);}#pragma omp parallel for private(k)for (k = 0; k < N; k++){A(j, k) = Aj[k];A(i, k) = Ai[k];Q(i, k) = Qi[k];Q(j, k) = Qj[k];}         }
    }
    

    性能对比:

    线程数矩阵维数n=8矩阵维数n=16矩阵维数n=32
    10.0000730.0002930.001481
    20.0001822.1367280.002181
    40.4348244.5819920.004917
    81.97092110.21833045.5784
    分析:
    我们惊讶的发现,即使不考虑节点自身的问题————如运算资源在被其他程序所消耗等,线程数增加后,运行时间反而增大了。特别是在线程数增加到8后,对32维矩阵的QR分解时间增大到一种吓人的地步。我从知乎上得到了一个很有说服力的解释:
    嵌套循环,内层循环并行。并行线程的创建与销毁会有开销,在嵌套循环的时候如果对内层for并行的话,这个开销会很大。解决方法是把并行放在外层的for。
  3. 用mpi实现summa算法
    原理:

    性能对比:

    length/process number1248
    160.0000230.0000510.0001481.002412
    2560.1297140.0439310.0231010.011794
    10249.2663331.9760201.2651440.594526

资源下载地址:https://download.csdn.net/download/sheziqiong/86771681
资源下载地址:https://download.csdn.net/download/sheziqiong/86771681


http://chatgpt.dhexx.cn/article/NsO0SJhp.shtml

相关文章

0成本睡后收入!从0教你搭建外卖红包CPS小程序

外卖返利小程序源码; 轻松部署搭建&#xff0c;小程序服务号数据互通&#xff1b; 对接美团官方; 佣金比例自定义分配; 三级分佣&#xff0c;所有资金数据一目了然&#xff1b; 拉新立减最低4.9元购月卡&#xff1b; 签到20天免费领取会员卡&#xff1b; 提现秒到账&#xff01…

SLAM前端之ndt_omp使用

ndt_omp(部分参考https://zhuanlan.zhihu.com/p/48853182) 简介&#xff1a; koide3/ndt_omp。继承自pcl ndt&#xff0c;并做了多线程等优化。参考&#xff1a;koide3/ndt_omp 环境需求&#xff1a; 1) 需要编译安装pcl-1.8.1或以上版本。因为ndt_omp是继承自pcl ndt的。 …

正交匹配追踪算法OMP

浅谈压缩感知&#xff08;九&#xff09;&#xff1a;正交匹配追踪算法OMP </h1><div class"clear"></div><div class"postBody">主要内容&#xff1a; OMP算法介绍 OMP的MATLAB实现 OMP中的数学知识 一、OMP算法介绍 来源&#…

OMP算法代码学习

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请注明出处&#xff0c;谢谢&#xff01; https://blog.csdn.net/jbb0523/article/details/45130793 </div><link rel"stylesheet" href"https://csdnimg.cn/release/phoenix/…

美团饿了么返利公众号小程序搭建(付源码)

外卖返利小程序源码; 轻松部署搭建&#xff0c;小程序服务号数据互通&#xff1b; 对接美团官方; 佣金比例自定义分配; 三级分佣&#xff0c;所有资金数据一目了然&#xff1b; 拉新立减最低4.9元购月卡&#xff1b; 签到20天免费领取会员卡&#xff1b; 提现秒到账&#xff01…

OMP算法笔记

OMP算法笔记 OMP算法整理&#xff08;以备自己后期查阅&#xff0c;集合了几篇博主的文章&#xff09; &#xff08;1&#xff09;数理知识基础–投影矩阵 详见&#xff1a; 作者&#xff1a;nineheaded_bird 来源&#xff1a;CSDN 原文&#xff1a;https://blog.csdn.net/teng…

使用python实现微信小程序自动签到2.0

微信小程序自动签到 功能描述目标输出包管理 程序的结构设计步骤1步骤2步骤3步骤4 代码实现使用findler抓包工具查看请求类型再次使用findler抓包&#xff0c;查看请求内容使用多线程完成多用户提交的功能使用itchat第三方库实现微信自动回复 将程序部署到服务器中使用scp命令将…

并行程序设计——OMP编程

并行程序设计——OMP编程 实验一 实验内容 分别实现课件中的梯形积分法的Pthread、OpenMP版本&#xff0c;熟悉并掌握OpenMP编程方法&#xff0c;探讨两种编程方式的异同。 实验代码 OpenMP编程 #include <stdio.h> #include <stdlib.h> #include <omp.h&g…

利用中国知网快速自动生成参考文献

1.打开知网 2.输入引用的文献名称 3.点击文章 4.点击“导出/参考文献” 5.自动生成参考文献

知网导出外文参考文献格式和下载文章(2019.5)

如果不弹出页面&#xff0c;是网络的原因&#xff0c;等一等

谷歌学术、中国知网生成参考文献

谷歌学术 step1.登陆谷歌学术 step2.查找需要的文献 step3.点击引用标志 step4.生成相关引用 step5.选择不同的标准复制粘贴 中国知网 step1.在知网搜索需要的论文 step2.点击导出参考文献 step3.生成参考文献引用

中国知网文献引用导入EndNote9.X,Web of science导入endnote以及谷歌学术导入endnote图文详解,全网最细版本适用EndNote9.x,Endnote20版本

文章目录 一、EndNote导入文献的以下几种格式1.1 中国知网1.2web of science1.3 谷歌学术 一、EndNote导入文献的以下几种格式 all as we konow&#xff0c;引用参考文献也就是如下三个&#xff0c;那么分别导入endnote改怎么使用呢&#xff1f; 1.1 中国知网 在你想要的文献里…

在CNKI上导出TXT文件

在使用CiteSpace之前要先下载数据源&#xff0c;今天就来讲一讲从CNKI上导出txt文件。 1、从学校官网进入中国知网CNKI&#xff0c;单击高级检索 2、输入关键字&#xff0c;可以选择组合输入&#xff0c;单击搜索 3、在每页显示处选择50 4、勾选所有所有记录&#xff08;每次导…

EndNote20导入知网文献和导出BibTeX于TexStudio

第一步&#xff1a;在知网官网中找到一篇论文并点击引号键 第二步&#xff1a;点击EndNote下载该txt文件 第三步&#xff1a;在EndNote20中点击File->Import->File&#xff0c;引入刚刚下载的txt文件 注意Import Option选择的是EndNote Import&#xff0c;点击import导入…

知网导出之Excel

背景&#xff1a;需要整理知网XX方向的论文&#xff0c;包括题目&#xff0c;内容&#xff0c;发表时间等等信息。但是一个个写也太麻烦了&#xff0c;所以&#xff0c;一些不需要人总结的东西&#xff0c;就直接导出好了。 流程&#xff1a; 选择好文献之后&#xff0c;选择自…

知网如何快速引用参考文献

1.在知网搜索界面&#xff0c;搜索自己想搜的内容&#xff0c;然后点击下图引号位置 2.在弹框中选择你要引用的格式 复制粘贴到自己论文中即可

知网 BibTeX自动生成(使用BibTeX引用中文参考文献)

前言 谷歌学术具备生成英文文献的bibtex文献引用代码的功能&#xff0c;而知网里不具备生成中文文献的bibtex引用代码的功能。因此&#xff0c;本文将生成中文文献bibtex引用代码的操作过程简单记录便于自己再次翻阅&#xff0c;操作方法源自知乎作者 上官无忌 &#xff0c;具…

知网导出引用文件,插入到Endnote管理文献

直接选endnote是txt格式 改格式也没用&#xff0c;endnote改也不行 这里选择refworks 导出txt之后 选择refworks import即可

Web of Science如何导出参考文献

Web of Science&#xff08;WOS&#xff09;是大型综合性、多学科、核心期刊引文索引数据库。 Endnote是一款可以有效管理参考文献的软件&#xff0c;并且在论文写作时&#xff0c;利用endnote可以很方便的修改引用格式。 1.进入论文界面 2.点击查看PDF,然后点击红圈 3. 可以…

Endnote导出目标期刊的参考文献的格式

Endnote导出目标期刊的参考文献的格式 1、知网文献与endnote的操作流程2、其他的参考文件来源&#xff08;如bib、ris等&#xff09;及导出格式选择 1、知网文献与endnote的操作流程 导出的格式为txt格式&#xff0c;这时候打开endnote&#xff0c;导入choose你的txt文件就可以…