死了死了(。)
1 . 题目:回顾 MPI 的通信机制,写出如下 Collective Communications 操作的伪代码: ① One-to-all Broadcast ;② All-to-all Reduction ;③ Scatter
① One-to-all Broadcast (& all-to-one Reduction)
先回顾一下概念:
这里One to all broadcast是指将一个线程里知道的消息广播到所有消息里去;而all to one reduction则是将将所有线程里的凑到一个里来
One-To-All Broadcast如图(来自ppt233)
②然后是All-to-All Reduction( & Broadcast)
这第二张ppt感觉时是错的…既然这样那直接每个线程删除除了i以外的所有消息不就行了?
然后我又翻到了这张PPT,发现All-to-allreduction的原型是MPI_Reduce_Scatter,然后我去查了这个函数:
http://mpi.deino.net/mpi_functions/MPI_Reduce_scatter.html
和同学讨论后觉得all-to-all reduction是一次交换信息和一次规约reduction:比如若reduction是sum,在有四个顶点的(超)立方体上来举例,那就是和all-to-all bc正好相反的过程。现在假设有00,01,10,11四个点,且各自有a[1],a[2],a[3],a[4]四个数,那么这个过程就是:11和01交换信息各自求和a[2]+a[4],00和10交换后各自求一遍a[1]+a[3],然后00和01交换,11和10交换,每个线程自己求出a[1]+a[2]+a[3]+a[4]。
注意,每次交换完后立刻求和的过程相当于定义里面的“On receiving a message, a node must combine it with the local copy",这里的sum就是交换过来的信息(数字)和本地信息(数字)combine(求和)的过程了。
这样做的好处是,可以减少加法次数。设想另一个all-to-one bc后再求和的过程,求和需要n次,是一个线程在做,但是其他线程需要等着它做完,做完后还需要把这个sum广播回去。如果是all-to-all reduction的过程就是所有线程都做一遍求和,但是这个求和只需要logn步骤,可能会有优势(至少不会是劣势)
那么过程如下:
③然后是scatter
这里我的理解是每次都对半,留一半发一半给临近的该发的地方。处理措施是每次i循环的广播源用一个j循环删除前一半消息(前2^i个消息)保留后一半消息广播出去,而到了自己要保留的消息呢,则自己保留前一半消息,正好要删除的是刚刚广播出去的消息(delete(send_message,message))
话不多说上代码
2.对于Floyd算法,存在一种MPI的实现使得每个处理器需要花费Θ(n2logp)进行通信,且问题规模n时所需的内存容量为n2,也即M(n) = n2。求该系统的等效率关系与可扩展性函数。
解:这个附上我前两天(突击复习)总结的:https://blog.csdn.net/Unauthorized_/article/details/105407878
关键是等效指标的那一套运算:
总结:等效关系【n>=f§】-》求出可扩展函数【M(f(p ))/p】,确定问题规模n作为处理器个数p的函数应该如何增长,才能维持原来效率不变。经同学指正,忘了乘以p了,更正了更正了233
3.完成求素数(#4),给出不同问题规模及处理器数量下的性能比较与分析。
求素数题:
这个书上有一整章来描述…第五章,摘抄内容:
有的地方需要改改,但是大体上这样就ok
改动方式我参照的:https://www.cnblogs.com/LCcnblogs/p/6015096.html
至于具体运行的话:我用的VS2017,先去百度一下怎么样运行mpi(悲哀发现dev不能继续苟了呜呜)
https://www.cnblogs.com/CheeseIce/p/10626345.html
然后用的cmd运行,这里.exe之后的那个数字10000就是你想让他算的n,然后之前那个-n 10那个10是你设定的p(感觉字母好像冲突了 呜呜)
这里结果就是1229个素数,1个线程,运行时间0.003759.
没有想好怎么样做临湖草堂那个从小到大顺序输出。我的想法是先设定一个筛完后的barrier,然后按照id号进行输出…或者是bc到一个线程中然后排序…据说草堂上的最大范围是2^24,不是很有想法呜呜(。
【更新】感谢lyk和my同学,居然还有gatherv这么方便的东东可以把所有线程的素数按照线程顺序集中到一起了。这里需要的每个线程的mark个数(也即每个线程size组成一个globalsize[])作为一个数组,和每个线程的mark相对于总线程上的偏移量还需要算一算。
嘤,本来想粘贴代码但是这个markdown抽风了每次粘贴都卡机…就先这样吧,反正改动不大。
第四题仍然是未做状态orz
【更新】
我来了 感觉第四题的奇妙之处就在于你需要读懂草堂的输入输出233
草堂上的要求第一个,这个struct的意思是输入的“视图”,控制input函数从offset开始,每次间隔stride子节读入width个字节。
而input如下:
所以输入格式如下:(大哥们记得自己改一下代码,忘了查重还是不差了反正小心点23333)
解释一下:就像下图,一行视为一个size的数据的话,每个线程需要处理两行内容(2size):第i行和倒数第i行,比如第一个线程处理黄色的两行,第二个线程处理蓝色的两行,那么两次的起始点中间隔着的就是pstride那么多的“格子”,第一个线程黄色的两个起始点隔着的是n-20size-size=n-size,第二个线程隔着n-3size。蓝色+白色是第一个第一个ianxchegnxu需要跨过去的pstride,白色是第二个线程需要跨过去的pstride,当然8是因为数据类型xu需要。之后每个线程得到的就是一个in[]数组了,就可以按照题目要求的那样挨个取大取小了就不放函数了。每个线程处理的的都是size*2那么大小的 ,用一个循环来做,每次都是min/max(in[i] , in[2 * size - i - 1]))就可以了。
最后output的时候也要
顺便,在草堂上发现需要设置M=2N,否则会出现segmentation fault,个人猜测是因为那个input_data是需要读入整M个的,多了少了都会错,而草堂上的那个N是输入规模,输入个数为2N,
所以需要M=2N。我设置的N=10,M=1024,p=4,输出对了但是还有什么abort6错误…don’t know了
【肝完了 爷溜了 还有博社作业呢 55】
P.S.:Markdown太难受了