我正在为来自 PDE 的特定离散化(具有已知的稀疏结构)的非常大的稀疏矩阵进行自适应矩阵向量乘法的 MATLAB 实现。
经过大量预处理后,我最终得到了许多不同的块(例如,大于 200),我想为其计算选定的条目。
预处理步骤之一是确定我要计算的每个块的(数量)条目,这使我几乎完美地衡量了每个块将花费的时间量(对于所有意图和目的,正交努力是每个条目都相同)。
感谢https://stackoverflow.com/a/9938666/2965879,我能够通过以相反的顺序对块进行排序来利用它,从而促使 MATLAB 首先从最大的块开始。
但是,每个块的条目数量差异很大,以至于直接运行 parfor 会受到条目数量最多的块的严重限制,即使它们被反向输入循环。
我的解决方案是串行执行最大的块(但在条目级别上并行化!),只要每个迭代的开销无关紧要,这很好。块不会变得太小。然后我用 parfor 完成其余的块。理想情况下,我会让 MATLAB 决定如何处理这个问题,但是由于嵌套的 parfor 循环失去了并行性,所以这不起作用。此外,将两个循环打包成一个(几乎)是不可能的。
我现在的问题是关于如何最好地确定串行和并行机制之间的截止值,同时考虑到我所拥有的关于条目数量的信息(对于不同的问题,有序条目的曲线形状可能会有所不同),如以及我可用的工人数量。
到目前为止,我一直在与标准 PCT 许可下可用的 12 名工作人员一起工作,但是自从我现在开始在集群上工作,确定这个截止值变得越来越重要(因为对于许多内核来说与并行循环相比,串行循环变得越来越昂贵,但类似地,拥有支撑其余部分的块甚至更昂贵)。
对于 12 个核心(分别是我正在使用的计算服务器的配置),我已经找到了一个合理的参数,即每个工作人员 100 个条目作为截止值,但是当核心数量不是时,这不起作用相对于块的数量(例如 64 对 200)来说已经很小了。
我试图缩小具有不同功率(例如 1/2、3/4)的核心数量,但这也不能始终如一地工作。接下来,我尝试将块分组并确定当条目大于每批平均值时的截止值,resp。他们离终点的批次数:
logical_sml = true(1,num_core); i = 0;
while all(logical_sml)
i = i+1;
m = mean(num_entr_asc(1:min(i*num_core,end))); % "asc" ~ ascending order
logical_sml = num_entr_asc(i*num_core+(1:num_core)) < i^(3/4)*m;
% if the small blocks were parallelised perfectly, i.e. all
% cores take the same time, the time would be proportional to
% i*m. To try to discount the different sizes (and imperfect
% parallelisation), we only scale with a power of i less than
% one to not end up with a few blocks which hold up the rest
end
num_block_big = num_block - (i+1)*num_core + sum(~logical_sml);
(注意:此代码不适用于num_entr_asc
长度不是 的倍数的向量,但为了便于阅读num_core
,我决定省略这些结构。)min(...,end)
我还省略了< max(...,...)
for 组合这两个条件(即加上每个工人的最少条目),这是必要的,这样就不会太早发现截止。我也考虑过以某种方式使用方差,但到目前为止,所有尝试都不能令人满意。
如果有人对如何解决这个问题有一个好主意,我将不胜感激。
感谢您阅读这个很长的问题,
最好的问候,
阿克塞尔
附言。由于我的“亲爱的 stackoverflow”似乎被过滤了,让我感谢我已经在这里找到了我的问题的解决方案。