【高性能计算背景】《并行计算教程简介》翻译 - 中文 - 4 / 4


一、写在前面

并行计算的入门文章非劳伦斯利弗莫尔国家实验室(LLNL)《Introduction to Parallel Computing Tutorial》[1]所属,于是本着学习的态度,笔者对其进行了翻译,以下是《Introduction to Parallel Computing Tutorial》的中文版,篇幅限制,本篇博客仅包含F. 并行示例G. 参考资料和更多信息部分,为《Introduction to Parallel Computing Tutorial》的第四部分,共四部分。

【高性能计算背景】《并行计算教程简介》翻译 - 中文 - 1 / 4
【高性能计算背景】《并行计算教程简介》翻译 - 中文 - 2 / 4
【高性能计算背景】《并行计算教程简介》翻译 - 中文 - 3 / 4
【高性能计算背景】《并行计算教程简介》翻译 - 中文 - 4 / 4


二、摘要

这是“利弗莫尔计算入门”研讨会的第一篇教程。本文旨在简要概述并行计算这一广泛而宽泛的主题,作为后续教程的导读。因此,它只涵盖并行计算的基本知识,面向刚刚熟悉该主题并计划参加本研讨会的一个或多个其他教程的人。它并不打算深入讨论并行编程,因为这将需要更多的时间。本教程首先讨论并行计算 - 它是什么以及如何使用,然后讨论与并行计算相关的概念和术语。然后探讨了并行内存体系结构和编程模型的主题。这些主题之后是一系列关于设计和运行并行程序的复杂问题的实际讨论。本教程最后给出了几个如何并行处理几个简单问题的示例。包括参考文献,以供进一步自学。

A. 并行计算概述

1. 什么是并行计算?

2. 为什么使用并行计算?

3. 谁在使用并行计算?


B. 概念和术语

1. 冯诺依曼计算机体系结构

2. 弗林分类法

3. 通用并行计算术语

4. 并行编程的潜在好处、限制和成本


C. 并行计算机内存架构

1. 共享内存

2. 分布式内存

3. 混合分布式共享内存


D. 并行编程模型

1. 共享内存模型

2. 线程模型

3. 分布式内存/消息传递模型

4. 数据并行模型

5. 混合模型

6. SPMD 和 MPMP


E. 设计并行程序

1. 自动并行 vs. 手动并行

2. 理解问题和程序

3. 分解

4. 通讯

5. 同步

6. 数据依赖

7. 负载均衡

8. 粒度

9. I/O

10. 调试

11. 性能分析和调优


F. 并行示例

1. 数组处理

  • 这个例子演示了二维数组元素的计算;函数在每个数组元素上求值。
  • 每个数组元素上的计算独立于其他数组元素。
  • 这个问题需要大量计算。
  • 串行程序按顺序一次计算一个元素。
  • 串行代码的形式可以是:
    do j = 1,n
      do i = 1,n
        a(i,j) = fcn(i,j)
      end do
    end do

在这里插入图片描述

二维数组

  • 要问的问题:
    • 这个问题可以并行化吗?
    • 如何划分问题?
    • 是否需要通信?
    • 是否存在任何数据依赖关系?
    • 是否需要同步?
    • 负载平衡会成为一个问题吗?

并行解决方案1

  • 元素的计算相互独立,带来理想的并行解决方案。

  • 数组元素均匀分布,以便每个进程拥有数组(子数组)的一部分。

    • 分配方案被选择以实现高效的内存访问;例如,以单位步长遍历子数组(步长为1)。单位步长可最大限度地提高缓存/内存使用率。
    • 由于希望能以单元步长遍历子数组,因此分配方案的选择一定程度上取决于编程语言。请参见块-周期分配图
  • 数组元素的独立计算确保任务之间不需要通信或同步。

  • 由于工作量均匀分布在各个进程之间,因此不应该存在负载平衡问题。

  • 数组分发后,每个任务执行对应于它拥有的数据的循环部分。

  • 例如,显示了 Fortran(列优先)和 C(行优先)块分布:

列优先:

do j = mystart, myend 
  do i = 1, n 
    a(i,j) = fcn(i,j) 
  end do 
end do

行优先:

for i (i = mystart; i < myend; i++) { 
  for j (j = 0; j < n; j++) { 
    a(i,j) = fcn(i,j); 
  }
}

一种可能的解决方案:

  • 作为单程序多数据(SPMD)模型实现——每个任务执行相同的程序。
  • 主进程初始化数组,将信息发送给工作进程并接收结果。
  • 工作进程接收信息,执行其共享的计算,并将结果发送给主进程。
  • 使用Fortran存储方案,使用数组的块分布。
  • 解决方案的伪代码:红色强调了并行化更改。

在这里插入图片描述

示例程序

并行解决方案2:任务池

  • 之前的数组解决方案展示了静态负载均衡:

    • 每个任务拥有固定数量的工作去做
    • 对于速度更快或负载更轻的处理器来说,空闲时间可能很长——最慢的任务决定了总体性能。
  • 如果所有任务在相同的机器上执行相同的工作量,静态负载平衡通常不是主要考虑。

  • 如果您有负载平衡问题(某些任务的工作速度比其他任务快),您可以使用任务池方案。

任务池方案

  • 使用两个进程

主进程

  • 保存工作进程要执行的任务池
  • 当收到请求时向工作进程发送任务
  • 收集工作进程的结果

工作进程

  • 从主进程获取任务
  • 执行计算
  • 将结果发送给主进程

  • 工作进程在运行前不知道将处理数组的哪一部分,也不知道将执行多少任务。
  • 动态负载平衡发生在运行时:越快执行的任务获得更多工作去做。
  • 解决方案的伪代码:红色强调了并行化更改。
    在这里插入图片描述

讨论

  • 在上面的任务池示例中,每个任务计算一个单独的数组元素作为作业。计算与通信的比率非常精细。
  • 细粒度解决方案会产生更多的通信开销,以减少任务空闲时间。
  • 一个更好的解决方案可能是为每个作业分配更多的工作。正确的工作量取决于问题本身。

2. 计算PI

  • PI 的值可以通过多种方式计算。考虑近似 PI 的蒙特卡洛方法:
  • 在边长为 2 r 2r 2r的正方形上内接一个半径为 r r r的圆
  • 圆的面积是 π r 2 π r^2 πr2,正方形的面积是 4 r 2 4r^2 4r2
  • 圆的面积与正方形的面积之比为:
    π r 2 / 4 r 2 π r^2 / 4r^2 πr2/4r2 = π / 4 π / 4 π/4
  • 如果您在正方形内随机生成N个点,则大约 ( N ∗ π ) / 4 (N*π)/ 4 (Nπ)/4个点 ( M ) 应该落在圆内。
    然后 π π π 的值近似为:
    ( N ∗ π ) / 4 = M (N*π) / 4 = M (Nπ)/4=M
    π / 4 = M / N π / 4 = M / N π/4=M/N
    π = 4 ∗ M / N π = 4 * M / N π=4M/N
    请注意,增加生成的点数会提高近似值。

在这里插入图片描述

串行计算PI 👆

  • 此过程的串行伪代码:
    npoints = 10000
    circle_count = 0

    do j = 1,npoints
      generate 2 random numbers between 0 and 1
      xcoordinate = random1
      ycoordinate = random2
      if (xcoordinate, ycoordinate) inside circle
      then circle_count = circle_count + 1
    end do

    PI = 4.0*circle_count/npoints
  • 问题是计算密集型的,大部分时间都花在执行循环上
  • 要问的问题:
    • 这个问题可以并行化吗?
    • 如何划分问题?
    • 是否需要通信?
    • 是否存在任何数据依赖关系?
    • 是否需要同步?
    • 负载平衡会成为一个问题吗?

并行解决方案

  • 又一个易于并行化的问题:

    • 所有点计算都是独立的;无数据依赖关系
    • 工作可以平均分配;无负载平衡问题
    • 任务之间无需通信或同步
  • 并行策略:

    • 将循环划分为可由任务池执行的相等部分
    • 每个任务独立执行其工作
    • 使用SPMD模型
    • 一个任务充当主任务来收集结果并计算PI的值

在这里插入图片描述

并行计算PI 👆

  • 解决方案的伪代码:红色强调了并行化更改。
    在这里插入图片描述

示例程序

3. 简单热方程

在这里插入图片描述

有限差分格式 👆

在这里插入图片描述

二维热问题 👆

  • 并行计算中的大多数问题都需要任务之间的通信。许多常见问题需要与邻居任务进行通信。

  • 给定初始温度分布和边界条件,二维热方程描述了温度随时间的变化。

  • 采用有限差分格式在正方形区域上数值求解热方程。

    • 二维数组的元素表示正方形上各点的温度。
    • 边界处的初始温度为零,中间的初始温度为高。
    • 边界温度保持在零度。
    • 采用时间步进算法。
  • 元素的计算依赖于相邻元素的值:

在这里插入图片描述

上述各项的计算 👆

  • 串行程序将包含如下代码:
   do iy = 2, ny - 1
      do ix = 2, nx - 1
        u2(ix, iy) =  u1(ix, iy)  +
            cx * (u1(ix+1,iy) + u1(ix-1,iy) - 2.*u1(ix,iy)) +
            cy * (u1(ix,iy+1) + u1(ix,iy-1) - 2.*u1(ix,iy))
      end do
    end do
  • 要问的问题:
    • 这个问题可以并行化吗?
    • 如何划分问题?
    • 是否需要通信?
    • 是否存在任何数据依赖关系?
    • 是否需要同步?
    • 负载平衡会成为一个问题吗?

并行解决方案

  • 这个问题更具挑战性,因为存在需要通信和同步的数据依赖关系。

  • 整个数组被划分并作为子数组分发给所有任务。每个任务在整个数组中拥有相等的份额。

  • 因为工作量是相等的,所以不应该考虑负载平衡。

  • 确定数据相关性:

    • 属于任务的内部元素独立于其他任务
    • 边界元素依赖于相邻任务的数据,因此需要进行通信。
  • 作为SPMD模型实施:

    • 主进程将初始信息发送给工作进程,然后等待从所有工作进程收集结果。
    • 工作进程在指定的时间步数内计算解决方案,必要时与相邻进程通信。
  • 解决方案的伪代码:红色强调了并行化更改。

在这里插入图片描述

样例程序

4. 一维波动方程

  • 在此示例中,在经过指定的时间后,计算沿均匀振动管柱的振幅。
  • 计算包括:
    • y y y轴上的振幅
    • x x x轴上的位置索引 i i i
    • 沿着波动曲线的节点
    • 以离散时间步更新振幅。

在这里插入图片描述

一维波动问题

  • 要求解的方程是一维波动方程:
    A(i,t+1) = (2.0 * A(i,t)) - A(i,t-1) + (c * (A(i-1,t) - (2.0 * A(i,t)) + A(i+1,t)))

其中c是常数

  • 请注意,振幅将取决于之前的时间步(t,t-1)和相邻点(i-1,i+1)。

  • 要问的问题:

    • 这个问题可以并行化吗?
    • 如何划分问题?
    • 是否需要通信?
    • 是否存在任何数据依赖关系?
    • 是否需要同步?
    • 负载平衡会成为一个问题吗?

一维波动方程并行解决方案

  • 这是涉及数据依赖性的问题的另一个例子。并行解决方案将涉及通信和同步。
  • 整个振幅阵列被划分并作为子数组分布到所有任务。每个任务在整个数组中拥有相等的份额。
  • 负载平衡:所有的点都需要相等的工作,所以这些点应该平均分配。
  • 块分解将把工作划分为多个任务作为块,允许每个任务拥有大部分连续的数据点。
  • 通信只需要在数据边界上进行。块大小越大,通信越少。

在这里插入图片描述

一维波动问题的并行解法

  • 作为SPMD模型实施:

    • 主流程将初始信息发送给工作线程,然后等待从所有工作线程收集结果
    • 工作进程在指定的时间步数内计算解决方案,必要时与相邻进程通信
  • 解决方案的伪代码:红色强调了并行化更改。
    在这里插入图片描述

样例程序

本教程到此结束。


G. 参考资料和更多信息

四、总结

以上就是今天要分享的内容,笔者没想到翻译工作居然要花费那么长的时间,原计划分为三部分后来发现篇幅有限制,只能改成四部分,本章节由浅入深的从理论和伪代码层面分析了四个并行计算的例子,同时也教会了读者书写并行程序时要学会这样思考:

- 这个问题可以并行化吗?
- 如何划分问题?
- 是否需要通信?
- 是否存在任何数据依赖关系?
- 是否需要同步?
- 负载平衡会成为一个问题吗?

本文翻译了《并行计算教程简介》的F章节,笔者一人翻译难免有翻译的不足之处,望海涵 😭 。
如果本文能给你带来帮助的话,点个赞鼓励一下作者吧! 😭


五、参考

[1] Lawrence Livermore National Laboratory:https://hpc.llnl.gov/documentation/tutorials/introduction-parallel-computing-tutorial

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 设计目的、意义(功能描述) 蒙特·卡罗方法(Monte Carlo method),也称统计模拟方法,是二十世纪四十年代中期由于科学技术的发展和电子计算机的发明,而被提出的一种以概率统计理论为指导的一类非常重要的数值计算方法。本次大作业主要是对蒙特·卡罗方法进行并行处理,通过OpenMP、MPI、.NET、Java、Win32API等一系列并行技术和并行机制对该算法进行并行处理,从而也进一步熟悉了蒙特·卡罗方法的串行算法和并行算法,实现了用蒙特·卡罗方法计算出半径为1单位的球体的体积,体会到了并行技术在实际生活中的应用。 2. 方案分析(解决方案) 蒙特·卡罗方法(Monte Carlo method)是指使用随机数(或更常见的伪随机数)来解决很多计算问题的方法。球的体积可以估算为:位于点模型内随机点个数与全体随机点个数的比值乘以包围盒的体积算的。 3. 设计分析 3.1 串行算法设计 假定球体用B表示,半径r=1单位,B1是包含B的参考立方体(在本例中是边长为2的正方体),在B1中产生N个均匀分布的伪随机点。对每个随机点检测其是否在B内,假设位于B内的随机点个数为N(in)(<=N),应用蒙特卡洛算法,则B的体积为 V=V1(N(in)/N) 其中V1是B1的体积。如果产生足够多的随机点,理论上可以获得任意逼近精度。 算法描述如下: BEGIN N=_MAX; FOR I=0;I<_MAX;I++ X=RANDOM(); Y=RANDOM(); Z=RANDOM(); IF (X*X+Y*Y+Z*Z)<=1 COUNT++; END IF; END FOR; BULK=V1*(COUNT/_MAX); END; 本算法主要是在参考立方体的选取上和定义的_MAX的值对结果影响较大,所以应该选择合适的数。 3.2 并行算法设计 对FOR循环进行划分使用两个处理器完成计算。例如对一个长为n的序列,首先划分得到两个长为n/2的序列,将其交给两个处理器分别处理;而后进一步划分得到四个长为n/4的序列,再分别交给四个处理器处理;如此递归下去最终得到结果。当然这是理想的划分情况,如果划分步骤不能达到平均分配的目的,那么结果的效率会相对较差。 伪代码如下: BEGIN N=_MAX; FOR1 I=0;I<_MAX/2;I++ X1=RANDOM(); Y1=RANDOM(); Z1=RANDOM(); IF (X1*X1+Y1*Y1+Z1*Z1)<=1 COUNT1++; END IF; END FOR1; FOR2 I=_MAX/2+1;I<_MAX;I++ X2=RANDOM(); Y2=RANDOM(); Z2=RANDOM(); IF (X2*X2+Y2*Y2+Z2*Z2)<=1 COUNT2++; END IF; END FOR2; BULK=V1*((COUNT1+ COUNT2)/_MAX); END; 3.3 理论加速比分析 实验中大量数据所产生的加速比比小量数据所产生的加速比要体现得更明显,并且数据生成的并行加速比随着处理器核的增加而增加。设处理器个数为p,数据量为n,由于正常情况下该快速排序算法的复杂度为O(nlogn),并行处理的时间复杂度为O(klogk),其中k=n/p,所以并行算法的时间复杂度为O((n/p)log(n/p)),理论加速比为nlogn/((n/p)log(n/p))=p+logp. 4. 功能模块实现与最终结果分析 4.1 基于OpenMP的并行算法实现 4.1.1 主要功能模块与实现方法 利用了OpenMP里面的#omp parallel sections将对两个for循环用两个线程并行化执行,以多线程方式并行运行程序,并行的算法步骤如下: (1)初始化_max = 10000000; (2)创建两个线程; (3)由OpenMP编译指导语句控制产生并行执行代码区段; (4)将数据存放到tianqing_count; (5)各线程调用算法得出结果; 并行算法的部分代码如下: #pragma omp parallel for private(tianqing_x,tianqing_y,tianqing_z) reduction(+:tianqing_count2) for (tianqing_i = 0; tianqing_i<tianqing_max; tianqing_i++) { tianqing_x = rand(); tianqing_x = tianqing_x / 32767; tianqing_y = rand(); tianqing_y = tianqing_y / 32767; tianqing_z = rand(); tianqing_z = tianqing_z / 32767; if ((tianqing_x*tianqing_x + tianqing_y*tianqing_y + tianqing_z*tianqing_z) work1.pSumto(b, 0, MAXN - 1)); Thread newthread1 = new Thread(thread1); 创建Work类的对象work2; ThreadStart thread2 = new ThreadStart(() => work2.pSumto(c, 0, MAXN - 1)); Thread newthread2 = new Thread(thread2); stopwatch.Start(); 启动线程1和线程2; 等待进程结束; stopwatch.Stop(); 得到结果; 4.5.2 实验加速比分析 实验中创建了两个线程,通过多次测试,得出实验结果:由上面的理论加速比分析可知,当线程数为2时,理论加速比为2+log2=3.但由于实际操作中硬件设备以及内存分配的影响,实验加速比达不到理论值3.实验加速比在2.6~2.7左右。 4.6 并行计算技术在实际系统中的应用 4.6.1 主要功能模块与实现方法 该飞机订票系统主要实现了对机票的一些基本信息进行存储和管理的功能。在系统中实现了对机票信息的增删改查,考虑到查询的方便性,对机票按照航班号进行排序,而此排序方法用并行快速排序运用进来。利用OpenMP的并行技术,对机票信息按顺序排列好,并分析了实验过程中的加速比。 4.6.2 实验加速比分析 实验中创建了两个线程,通过多次测试,得出实验结果:当数据量比较大时,加速比理论在1.9左右。数据量较大时体现出来的加速比更准确。由上面的理论加速比分析可知,当线程数为2时,理论加速比为2+log2=3.但由于实际操作中硬件设备以及内存分配的影响,实验加速比达不到理论值3.实验加速比在2.2~2.4左右。 5. 设计体会 虽然没有按时完成作业,但这份报告花了我好几天的时间,从开始的搭建并行计算平台到最后的程序运行成功可以说是对我的一个锻炼。每一次的遇到问题与每一次的解决问题都是一个成长。每一次遇到问题和解决问题都是一种锻炼,一种尝试,从我们上并行计算课我懂得了很多电脑硬件和软件的知识,这些可能对于我们这个专业以后都是没有机会接触的,所以我觉得选择了并行计算与多核多线程技术这门课是非常正确的。对OpenMP、MPI、WIN32API、Java、.NET的并行技术有了一定的了解。在搭建MPI并行程序这块,学习的知识尤为增加,这些都是在不断的摸索、学习中学会的。 这次的大作业虽然是对以前实验的整合,但它加深了我对并行计算的印象,也使我对并行计算知识的理解更加深刻,也使我认识到了自己很多不足之处。学习并行计算的历程不会因为完成本次大作业而停止,我们是为了用知识武装大脑而学习,通过学习充实自己的生活,要努力学习,争取以后能够完成规模更大的程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值