【发布时间】:2021-07-06 21:07:03
【问题描述】:
我正在尝试并行化 Gauss-Seidel 算法中使用的一些代码,以逼近线性方程组的解。
简而言之,对于NxN 矩阵,在一次迭代期间,我正在逐一进行sqrt(N) 并行计算会话。在一个并行计算会话中,我将计算sqrt(N) 值的任务分配给可用的worker。
并行计算会话中涉及的代码是这样的:
future_results(1:num_workers) = parallel.FevalFuture;
for i = 1:num_workers
start_itv = buck_bound+1 + (i - 1) * worker_length;
end_itv = min(buck_bound+1 + i * worker_length - 1, ends_of_buckets(current_bucket));
future_results(i) = parfeval(p, @hybrid_parallel_function, 3, A, b, x, x_last, buck_bound, n, start_itv, end_itv);
end
for i = 1:num_workers
[~, arr, start_itv, end_itv] = fetchNext(future_results(i));
x(start_itv:end_itv) = arr;
end
parfeval调用的函数是这样的:
function [x_par, start_itv, end_itv] = hybrid_parallel_function (A, b, x, x_last, buck_bound, n, start_itv, end_itv)
x_par = zeros(end_itv - start_itv + 1, 1);
for i = start_itv:end_itv
x_par(i-start_itv+1) = b(i);
x_par(i-start_itv+1) = x_par(i-start_itv+1) - A(i, 1:buck_bound) * x(1:buck_bound);
x_par(i-start_itv+1) = x_par(i-start_itv+1) - A(i, buck_bound+1:i-1) * x_last(buck_bound+1:i-1);
x_par(i-start_itv+1) = x_par(i-start_itv+1) - A(i, i+1:n) * x_last(i+1:n);
x_par(i-start_itv+1) = x_par(i-start_itv+1) / A(i, i);
end
end
完整的代码可以在这里找到:https://pastebin.com/hRQ5Ugqz
1000x1000 矩阵的 matlab 分析器。并行代码比串行代码慢 20 到 135 倍,具体取决于所选的系数矩阵(但仍比 spmd 快得多)。
parfeval 计算可能会在第 50 行和第 57 行之间延迟拆分?尽管如此,我还是无法向自己解释为什么会有这么大的开销。这似乎与调用 parfeval 的次数有关:我确实通过降低 parfeval 调用来降低执行时间。
有什么可以进一步优化的吗?我必须求助于用 C++ 编写代码吗?
请帮忙。非常感谢!
【问题讨论】:
-
您是如何配置并行池的?默认情况下,MATLAB 使用多个 MATLAB 会话,并在它们之间传递数据。这是为在计算集群上运行而设计的,集群中的每个节点都运行一个会话。不过,您可以将其配置为使用基于线程的并行性。无论如何,较少的大型作业比许多小型作业更好地并行化。
-
你可能是对的,我会在更新到 R2020 后立即尝试 parpool('threads'),谢谢。
标签: matlab parallel-processing parfor spmd