主要内容

基准\ b

这个例子展示了如何在集群中对线性系统进行基准测试。MATLAB®的代码来解决XA * x =是非常简单的。最常见的是,使用矩阵左除法(也称为mldivide)或反斜杠操作符(\)来计算X(那是,x = a \ b)。然而,在集群上对矩阵左除法的性能进行基准测试并不是那么简单。

基准测试的最具挑战性方面之一是避免落入寻找一个代表系统整体性能的单个数字的陷阱。我们将查看可能帮助您识别群集上的性能瓶颈的性能曲线,甚至可以帮助您了解如何基准代码,并能够从结果中得出有意义的结论。

相关例子:

这个例子中的代码可以在这个函数中找到:

函数结果= paralleldemo_backslash_bench(MemoryPerWorker)

选择合适的矩阵大小是非常重要的。我们可以通过指定每个worker可用的系统内存(以GB为单位)作为示例函数的输入来实现这一点。默认值非常保守;您应该指定一个适合您的系统的值。

如果nargin == 0 memoryPerWorker = 8.00;%在GB%的警告(“pctexample: backslashbench: BackslashBenchUsingDefaultMemory”,…%['每个worker可用的系统内存数量是',…%的未指定。使用保守的默认值',…%'%'%.2f千兆字节,每个工人。'],Modenperworker);结束

避免开销

为了精确测量我们解线性系统的能力,我们需要排除任何可能的开销来源。这包括获取当前并行池和暂时禁用死锁检测功能。

p = gcp;如果isempty (p)错误(“pctexample: backslashbench: poolClosed”......[这个例子需要一个并行池。......'使用parpool命令或设置手动启动池'......你的平行偏好自动启动一个池]);结束poolSize = p.NumWorkers;PCTRunonall.“mpiSettings(“DeadlockDetection”、“关闭”);“
使用“BigMJS”配置文件启动并行池(Parpool)...连接到12名工人。

基准测试函数

我们要基准矩阵左除法(\),而不是成本进入SPMD.块,创建矩阵所需的时间,或其他参数。因此,我们将数据生成与线性系统的求解分离开来,只测量完成后者所需的时间。我们使用二维块循环协分配器生成输入数据,因为这是求解线性系统最有效的分布方案。我们的基准测试包括测量所有工作人员完成求解线性系统所需的时间A * x =。同样,我们试图消除任何可能的开销来源。

函数[A, b] = getData(n) fprintf(n)'创建一个大小为%d-by-%d.\n'n, n);SPMD.%使用通常能提供最佳性能的协分发器%用于求解线性方程组。codistr = codistributor2dbc (codistributor2dbc.defaultLabGrid,......codistributor2dbc.defaultBlockSize,......“上校”);一个= codistributed。兰特(n, n, codistr);b = codistributed。兰特(n, 1, codistr);结束结束函数Time = Timesolve(A,B)SPMD.抽搐;x = \ b;我们不需要x的值。time = gop(@max,toc);所有完成的时间。结束时间= {1};结束

选择问题的大小

就像具有大量的其他并行算法一样,求解线性系统并联的性能大大取决于矩阵尺寸。我们的先天的因此,预期是计算:

  • 对于小矩阵有点低效

  • 对于大型矩阵非常有效

  • 如果矩阵太大,无法装入系统内存,并且操作系统开始将内存交换到磁盘,则效率低下

因此,为许多不同矩阵大小的计算计时是很重要的,以便理解在这种情况下“小”、“大”和“太大”的含义。根据之前的实验,我们期望:

  • “太小”的矩阵大小不是1000乘1000

  • “大”矩阵占用每个工作者可用内存的比例略低于45%

  • “太大”矩阵占据了每个工人可用的50%或更多的系统内存

这些是试探法,精确的值可能会在不同版本之间改变。因此,使用跨越整个范围的矩阵大小并验证预期性能是很重要的。

注意,通过根据工人的数量来改变问题的规模,我们使用了弱尺度。其他基准测试示例,如使用二十一点的Parcom的简单基准在集群上对独立作业进行基准测试,也采用弱尺度。这些例子是对任务并行计算进行基准测试的例子,它们的弱伸缩性包括使迭代的数量与工作人员的数量成比例。然而,这个例子是对数据并行计算的基准测试,因此我们将矩阵的上限与工人的数量联系起来。

%声明矩阵大小从1000 × 1000到系统的45%每个工人可用的%内存。maxMemUsagePerWorker = 0.45 * memoryPerWorker * 1024 ^ 3;%的字节。maxMatSize =圆(√maxMemUsagePerWorker * poolSize / 8));linspace(1000, maxMatSize, 5) = round(linspace(1000, maxMatSize, 5));

比较性能:吉拍

我们使用每秒浮点操作的数量作为我们的性能衡量标准,因为这允许我们比较算法的不同矩阵大小和不同数量的工人的性能。如果我们成功地测试矩阵左部的性能,以获得足够广泛的矩阵大小,我们希望性能图看起来类似于以下内容:

通过生成图形,例如,我们可以回答以下问题:

  • 最小的矩阵会不会太小以至于我们的性能很差?

  • 当矩阵如此之大以至于它占用了总系统内存的45%时,我们是否看到性能下降?

  • 对于一定数量的员工,我们能达到的最佳绩效是什么?

  • 在哪种矩阵规模下,16个工人比8个工人表现更好?

  • 系统内存是否限制了峰值性能?

给定一个矩阵大小,标杆函数创建矩阵一种右边B.一次,然后解一个\ b多次才能得到准确的测量时间。我们使用HPC Challenge的浮点运算计数,因此对于一个n × n矩阵,我们将浮点运算计数为2/3 * n ^ 3 + 3/2 * n ^ 2

函数gflops = benchFcn(n) numReps = 3;[A, b] = getData(n);时间=正;%我们解决线性系统几次,并计算Gigaflops%基于最佳时间。itr = 1:numReps tcurr = timeSolve(A, b);如果fprintf() == 1执行时间:% f ', tcurr);其他的fprintf(”,% f ', tcurr);结束时间= min(tcurr,时间);结束fprintf(' \ n ');翻转= 2/3*n^3 + 3/2*n^2;gflops =失败/时间/ 1 e9;结束

执行标准

完成所有设置后,就可以直接执行基准测试了。然而,计算可能需要很长时间才能完成,所以我们在完成每个矩阵大小的基准测试时打印一些中间状态信息。

流(['以%d个不同的矩阵大小开始基准测试,范围为\n'......'从%d-by-%d到%d.\n'),....../ * * * * * * * * * * * * * * * * * * * * * *......matSize(结束));gflops = 0(大小(matSize));i = 1:长度(matsize)gflops(i)= benchfcn(matsize(i));fprintf('Gigaflops:%f \ n \ n'gflops(我));结束结果。matSize = matSize;结果。gflops = gflops;
使用从1000 × 1000到76146 × 76146的5种不同的矩阵大小开始基准测试。创建一个大小为1000 × 1000的矩阵。分析并传送文件给工人…完成。执行时间:1.038931,0.592114,0.5575135 Gigaflops: 1.161756创建一个大小为19787-by 19787的矩阵。执行时间:119.402579,118.087116,119.323904 Gigaflops: 43.741681创建一个大小为38573 × 38573的矩阵。执行时间:552.256063,549.088060,555.753578 Gigaflops: 69.685485创建一个大小为57360 × 57360的矩阵。执行时间:3580.232186,3726.588242,3113.261810 Gigaflops: 40.414533创建一个大小76146 × 76146的矩阵。执行时间:9261.720799,9099.777287,7968.750495 Gigaflops: 36.937936

绘制的性能

我们现在可以绘制结果,并与上面所示的预期图进行比较。

无花果=图;ax =轴(“父”图);情节(ax, matSize / 1000 gflops);行= ax.Children;行。标志=“+”;ylabel (ax,“吉拍”)包含(ax,“矩阵大小以千计”) titleStr = sprintf([]'解决A\\b的不同矩阵大小'......' % d工人), poolSize);标题(ax, titleStr,“翻译”“没有”);

如果基准结果不如您可能期望的那么好,这里有一些需要考虑的事情:

  • 底层实现使用的是ScaLAPACK,它的高性能已经得到了证实。因此,不太可能是算法或库导致了效率低下,而是它的使用方式导致了效率低下,如下文所述。

  • 如果对于您的集群来说,这些矩阵太小或太大,那么最终的性能将会很差。

  • 如果网络通信速度慢,将严重影响性能。

  • 如果cpu和网络通信都非常快,但是内存数量有限,那么您可能无法使用足够大的矩阵进行基准测试,以充分利用可用的cpu和网络带宽。

  • 为了获得最终的性能,重要的是要使用一个为您的网络设置量身定制的MPI版本,并让工人以尽可能多的通信通过共享内存进行的方式运行。但是,解释如何识别和解决这些类型的问题超出了本示例的范围。

比较不同数量的工人

我们现在通过观看通过使用不同数量的工人来查看通过运行此示例而获得的数据来比较不同数量的工人。在从上面的群集中获得此数据。

其他的例子如在集群上对独立作业进行基准测试解释了在对不同数量的工人进行并行算法的基准测试时,通常采用弱缩放。也就是说,随着工人数量的增加,问题的规模也相应地增加。在矩阵左除法的情况下,我们必须特别注意,因为除法的性能很大程度上取决于矩阵的大小。下面的代码创建了一个用于我们测试的所有矩阵大小和所有不同数量的工人的Gigaflops性能的图表,这给了我们关于矩阵左除法性能特征的最详细的图片在这个特定的群集上

s =负载(“pctdemo_data_backslash.mat”“workers4”'工人8'......“workers16”“workers32”'工人64');无花果=图;ax =轴(“父”图);情节(ax, s.workers4.matSize。s.workers4.gflops / 1000,......s.workers8.matSize。s.workers8.gflops / 1000,......s.workers16.matSize。s.workers16.gflops / 1000,......s.workers32.matSize。s.workers32.gflops / 1000,......S.Workers64.Matsize./1000,S.Workers64.gflops);行= ax.Children;套(行,{“标记”}, {“+”;“o”;“v”;'。';‘*’});ylabel (ax,“吉拍”)包含(ax,“矩阵大小以千计”)标题(斧头,......'在不同数量的工人上解决\\ b的比较数据);传奇(“4个工人“8工人的16个工人'32工人'......64年的工人“位置”'西北');

看上图时,我们首先注意到的是,64个工人比4个工人能解决的线性方程组要大得多。此外,我们可以看到,即使一个矩阵的大小是60000 × 60000在4个工人,我们将得到大约10 Gigaflops的性能。因此,即使这4个工人有足够的内存来解决如此大的问题,64个工人仍然会大大超过他们。

观察4个工人的曲线斜率,我们可以看到,在三个最大的矩阵尺寸之间,只有适度的性能增长。与之前的期望性能曲线图进行比较一个\ b对于不同的矩阵尺寸,我们得出结论,对于矩阵尺寸为7772 × 7772的4个工人,我们已经非常接近达到最佳性能了。

查看8和16名工人的曲线,我们可以看到性能下降到最大的矩阵大小,表明我们近乎或已经有耗尽的可用系统内存。但是,我们看到,第二和第三大矩阵大小之间的性能增加非常适度,表明某种类型的稳定性。因此,我们猜测在使用8或16名工人时,如果我们增加系统内存并以较大的矩阵尺寸进行测试,我们很可能不会看到Gigaflops的显着增加。

观察32名和64名员工的曲线,我们可以看到,在第二和第三大矩阵规模之间有显著的业绩增长。对于64名工人,在两个最大的矩阵尺寸之间也有显著的绩效提高。因此,我们推测,在达到最佳性能之前,32个和64个工人的系统内存已经耗尽。如果这是正确的,那么为计算机添加更多内存既可以让我们解决更大的问题,也可以在更大的矩阵规模下表现得更好。

加速

使用诸如反斜杠等线性代数算法获得的传统测量加速的方式是比较峰值性能。因此,我们计算为每位工人实现的最大Gigaflops数量。

Peakperf = [max(s.workers4.gflops),max(s.workers8.gflops),......马克斯(s.workers16.gflops)、马克斯(s.workers32.gflops),......马克斯(s.workers64.gflops)];disp ('4-64名工人Gigaflops的高峰表现:') disp peakPerf disp (从4名工人增加到8、16、32和64名工人时的速度加快) disp (peakPerf(2:结束)/ peakPerf (1))
4-64工人Gigaflops的峰值性能:10.9319 23.2508 40.7157 73.5109 147.0693从4名工人到8,16,32和64名工人时,加速:2.1269 3.7245 6.7244 13.4532

因此,我们得出结论,当增加工人数量16折的数量,从4名工人增加到64时,我们得出结论约为13.5。正如我们上面所述的那样,性能图表明我们可能能够提高64名工人的性能(和因此,通过增加集群计算机上的系统存储器,从而提高加速即将进一步提高。

使用的集群

这些数据是由16台双处理器、八核计算机生成的,每台计算机都有64gb内存,并与千兆以太网连接。当使用4个工人时,他们都在一台计算机上。我们用2台电脑给8个工人,4台电脑给16个工人,等等。

重新启用死锁检测

现在我们已经完成了基准测试,我们可以安全地在当前并行池中重新启用死锁检测。

PCTRunonall.'Mpisettings('''''''''''');'
结束
ANS =带有字段的结构:MATSIZE:[1000 19787 38573 57360 76146] GFLOPS:[1.1618 43.7417 69.6855 40.4145 36.9379]