主要内容

本页采用了机器翻译。点击此处可查看最新英文版本。

MATLAB 中快速启动并行计算

您可以使用并行计算同时执行多项计算。将大问题拆分成多个小问题,以便可以同时处理。

通过并行计算,您可以:

  • 通过分配任务并同时执行来节省时间

  • 通过数据分区解决大数据问题

  • 充分利用您的台式计算机资源并扩展到集群和云计算

Diagram that shows four MATLAB workers in a loop.

该表列出了一些重要的并行计算术语及其定义。

术语定义
线程

CPU 可以独立调度和执行的最小指令集。GPU、多处理器或多核计算机可以执行多线程,即同时执行多个线程。

进程

由一个或多个线程执行计算机程序的一个实例。每个进程都有自己的内存块。

节点

包含一个或多个 CPU 或 GPU 的独立计算机。节点可以联网形成集群或超级计算机。

集群

一组相互连接的计算机,它们作为统一的系统协同工作,提供高性能的计算能力来处理复杂且数据密集型的任务。

可扩展性

通过添加更多资源来提高并行加速。

前提条件

要运行此页面上的示例,您必须拥有 Parallel Computing Toolbox™ 许可证。要确定您是否安装了 Parallel Computing Toolbox,以及您的计算机是否可以创建默认并行池,请在 MATLAB® 命令行窗口中输入此代码。

if canUseParallelPool
    disp("Parallel Computing Toolbox is installed")
else
    disp("Parallel Computing Toolbox is not installed")
end

或者,要查看已安装哪些 MathWorks® 产品,请在命令行窗口中输入 ver

加速 MATLAB 代码执行

在并行化代码之前,您可以使用向量化和预分配等技术来提高 MATLAB 代码的顺序性能。顺序加速和并行化通常可以协同工作以提供累积的性能改进。

向量化

MATLAB 针对涉及矩阵和向量的运算进行了优化。修正基于循环且面向标量的代码以使用 MATLAB 矩阵和向量运算的过程称为向量化。使用向量化代码而不是基于循环的操作通常可以提高代码性能。

这些代码片段比较了软件使用基于循环的代码与向量化代码计算 1,000,000 个值的平方根所需的时间。

不进行向量化

进行向量化

tic
for k = 1:1000000
   x(k) = sqrt(k);
end
toc
Elapsed time is 0.112298 seconds.
tic
k = 1:1000000;
x = sqrt(k);
toc
Elapsed time is 0.006783 seconds.

预分配

在某些情况下,每次循环时逐渐增加数组大小的 whilefor 循环可能会对性能和内存使用产生不利影响。您可以预先分配数组所需的最大空间量,而不是在运行基于循环的代码时不断调整数组大小。

这些代码片段比较了当您在 for 循环中逐渐增加 x 的大小时软件创建标量变量 x 所需的时间与为 x 预分配 1×1,000,000 的内存块所需的时间。

不带预分配

带预分配

tic
x = 0;
for k = 2:1000000
   x(k) = x(k-1) + 5;
end
toc
Elapsed time is 0.103415 seconds.
tic
x = zeros(1,1000000);
for k = 2:1000000
   x(k) = x(k-1) + 5;
end
toc
Elapsed time is 0.018758 seconds.

该表显示了您想要初始化的数组类型的适当的预分配函数。

要初始化的数组类型预分配函数
数值zeros
字符串strings
元胞cell
table

在多核和多处理器节点上运行 MATLAB

MATLAB 支持两种方式在多核和多处理器节点上并行化代码。

内置多线程的隐式并行化

一些 MATLAB 函数隐式使用多线程来并行执行。这些函数在单个 MATLAB 会话中自动在多个计算线程上执行,这意味着它们在支持多核的计算机上运行速度更快。一些示例是线性代数和数值函数,例如 fftmldivideeigsvdsort。因此,如果您在具有多核的计算机上使用这些函数,您会发现性能有所提升。

Diagram comparing the time it takes a MATLAB client using multithreading to accelerate task execution to a MATLAB client that does not use panellization.

使用 MATLAB 工作单元进行显式并行化

MATLAB 和 Parallel Computing Toolbox 软件使用 MATLAB 工作单元来明确地并行化您的代码。MATLAB 工作单元是在后台运行的、无需图形桌面的 MATLAB 计算引擎。与您交互的 MATLAB 会话(也称为 MATLAB 客户端)使用并行语言函数指导工作单元。您使用 Parallel Computing Toolbox 函数自动划分任务并将其分配给这些工作单元以并行执行计算。

Diagram comparing the time it takes parallel computing workers to accelerate task execution to a MATLAB client with no parallelization.

设置显式并行化环境

如果您的计算机上安装了 Parallel Computing Toolbox,您可以启动一个交互式并行工作单元池,以充分利用多核计算机中的核心。

并行池(parpool)是一组 MATLAB 工作单元,您可以在其上以交互方式运行代码。

您可以使用 parpool 或支持自动并行的函数创建并行工作单元池。默认情况下,并行语言函数(例如 parforparfevalspmd)会在您需要时自动创建并行池。当工作单元启动时,您的 MATLAB 会话将连接到它们。例如,此代码自动启动一个并行池,并在六个工作单元上并行运行 parfor 循环中的语句。

parfor i = 1:100
    c(i) = max(eig(rand(1000)));
end
Starting parallel pool (parpool) using the 'Processes' profile ...
Connected to parallel pool with 6 workers.

您还可以使用 MATLAB 桌面左下角的并行状态指示器手动启动并行池。点击指示器图标,然后选择启动并行池

The parallel status indicator, including a menu showing options for starting a parallel pool and inspecting your parallel settings.

要在启动时停止并行池,请按 Ctrl+CCtrl+Break。在 Apple macOS 操作系统上,您还可以使用 command+command 键和加号键)。

启动并行池通常需要很长时间,这会影响只需几秒钟即可执行的代码的性能。对于运行时间较长的代码,开销就变得不那么重要了。

您的默认并行环境决定了并行池集群。本地计算机的默认并行环境称为 Processes。该环境启动了一个进程工作单元的并行池。您可以在 MATLAB 主页选项卡上的并行菜单中查看可用的并行环境。

Selection of the Processes local cluster profile from the MATLAB menu.

注意

对于默认的 Processes 配置文件,默认的进程工作单元数量是每个物理 CPU 核心一个,使用单个计算线程。这种限制确保每个工作单元都可以独占访问浮点单元,并且通常可以优化计算代码的性能。如果您的代码不是计算密集型的,例如输入/输出 (I/O) 密集型的代码,那么请考虑每个物理核心最多使用两个工作单元。在太少的资源上运行太多的工作单元会影响计算机的性能和稳定性。

下表总结了创建交互式并行池的不同方法。

并行环境工作单元类型位置可用核心或线程数
Processes进程本地计算机

最多 512 个核心

Threads线程本地计算机

最多 512 个线程

backgroundPool线程本地计算机

没有 Parallel Computing Toolbox 许可证:1 个线程

使用 Parallel Computing Toolbox 许可证:最多为 maxNumCompThreads 函数返回的线程数

Cluster进程现场或云集群

集群最多可以启动最多数量的工作单元

Parallel Computing Toolbox 还支持运行由计算线程,而不是进程工作单元支持的并行工作单元池。这个并行环境被称为 Threads。线程式工作单元减少了内存使用量,加快了调度速度,并降低了数据传输成本。但是线程工作单元仅支持进程工作单元可用的 MATLAB 函数的子集。

MATLAB 还支持一个名为 backgroundPool 的附加本地并行环境。backgroundPool 环境由线程式工作单元支持,并支持在您同时在会话中运行其他代码时在后台运行代码。当您没有 Parallel Computing Toolbox 许可证时,您可以在 backgroundPool 环境中使用一个线程式工作单元。如果您拥有 Parallel Computing Toolbox 许可证,则 backgroundPool 中线程式工作单元的最大数量就是 maxNumCompThreads 函数返回的值。

如果您有权访问现场或云集群,您可以通过点击并行 > 发现集群并按照提示来发现在您的网络或 Cloud Center 运行的其他集群。集群上的并行池由进程工作单元支持并支持完整的并行语言。

当您拥有一个交互式并行工作单元池时,您可以使用并行语言函数将大问题拆分为工作单元可以并行执行的较小任务。为了加速您的 MATLAB 代码,请使用交互式并行功能,例如 parfor

使用 parfor 循环运行显式并行化

此示例显示如何将 for 循环转换为 parfor 循环,并计算 parfor 循环随工作单元数量变化的可扩展性。

您可以使用 for 循环将 parfor 循环转换为并行运行。通常,您可以简单地将 for 替换为 parfor。然而,您经常需要进一步调整代码以实现并行运行。

parfor 循环的机制

当您运行 parfor 循环时,MATLAB 会并行执行循环体中的语句。parfor 循环体的每次执行都是一次迭代。MATLAB 客户端发出 parfor 命令并与工作单元协调在并行池中的工作单元上并行执行循环迭代。parfor 循环可以提供比其类似的 for 循环更好的性能,因为多个工作单元可以同时计算迭代。

当您运行 parfor 循环时,MATLAB 客户端会将循环迭代划分为子范围并将它们分配给工作单元。如果工作单元数量等于循环迭代次数,则每个工作单元执行一次循环迭代。如果迭代次数大于工作单元数量,则一些工作单元将执行一次以上的循环迭代。在这种情况下,工作单元一次接收多个迭代以减少通信时间。客户端还对 parfor 循环代码进行静态分析,以确定要将哪些数据传输给每个工作单元以及将哪些数据传输回客户端。客户端将必要的数据发送给执行大部分计算的工作单元。然后,工作单元将结果发送回客户端,客户端将这些结果汇总起来。MATLAB 工作单元以无特定顺序且彼此独立的方式评估迭代。因为每次迭代都是独立的,所以迭代不需要同步,而且通常也不需要同步。

parfor 循环必须满足这些基本要求。

  • 循环迭代是独立的。当将 for 循环转换为 parfor 循环时,必须确保循环迭代是独立的。如果您的 parfor 代码在循环迭代之间存在依赖关系,则 MATLAB 编辑器中的代码分析器会检测到该依赖关系。执行 parfor 循环会产生错误。

  • 循环执行不按顺序。因为 parfor 循环迭代没有保证的顺序,所以您必须确保使用 parfor 循环的代码不依赖于 parfor 循环的输出是否按顺序排列。

for 循环转换为 parfor 循环

将代码中的 for 循环转换为 parfor 循环,通过将 for 替换为 parfor 来计算 5000 个 200×200 随机矩阵的奇异值分解的最大值。对六个工作单元执行 parfor 循环。比较它们的执行时间。

当您使用 parfor 并且安装了 Parallel Computing Toolbox 软件时,MATLAB 会自动启动并行工作单元池。并行池可能需要很长时间才能启动。此示例显示池已启动的第二次运行。您可以观察到在六个工作单元上执行的 parfor 代码比 for 循环代码 . 运行速度快得多

tic
y = zeros(5000,1);
for n = 1:5000
    y(n) = max(svd(randn(200)));
end
toc
Elapsed time is 21.837346 seconds.
tic
y = zeros(5000,1);
parfor n = 1:5000
    y(n) = max(svd(randn(200)));
end
toc
Elapsed time is 3.908282 seconds.

如果加速程度低于您的预期,您可以计算 parfor 循环代码的可扩展性。

计算可扩展性

您可以计算将此 for 循环转换为 parfor 循环的可扩展性。使用可扩展性来确定您的 parfor 循环代码是否可以随着工作单元数量很好地扩展,以及是否存在限制。

使用 for 循环遍历不同数量的工作单元来运行 parfor 循环。要指定工作单元的数量,请使用第二个输入参量 parfor。您可以修改 NumWorkers 数组中的值以匹配您的可用资源。

numIterations = 5000;
numWorkers = [1 2 3 4 5 6];
t = zeros(size(numWorkers));
for w = 1:numel(numWorkers)
    tic;
    y = zeros(numIterations,1);
    parfor (n = 1:numIterations,numWorkers(w))
        y(n) = max(svd(randn(200)));
    end
    t(w) = toc;
end

通过计算单个工作单元的计算时间与每个最大工作单元数的计算时间之间的比率来计算加速比。要计算并行任务的效率,请将理想加速比除以计算出的加速比。

speedup = t(1)./t;
efficiency = (speedup./numWorkers).*100;

为了直观地了解计算量如何随着工作单元数量的增加而增加,请使用示例末尾定义的 comparePlot 函数绘制加速和效率与工作单元数量的关系图。

随着工作单元数量的增加,加速也会增加。添加更多的工作单元可以减少计算时间,但这种扩展并不完美,因为效率会随着工作单元数量的增加而降低。这是由于并行化相关的开销。并行开销包括软件从客户端端到工作单元进行通信、协调和数据传输所需的时间。

没有很多迭代或计算要求高的任务的 parfor 循环通常不能随着工作单元数量的增加而很好地扩展,因为与软件进行计算所需的时间相比,软件进行数据传输所需的时间非常重要。

comparePlot(numWorkers,speedup,efficiency);

完成计算后,您可以删除当前并行池。使用gcp函数获取当前并行池。

delete(gcp)
Parallel pool using the 'Processes' profile is shutting down.

辅助函数

此函数绘制了 parfor 循环的加速和效率与工作单元数量的关系图。

function comparePlot(numWorkers,speedup,efficiency)
yyaxis left
plot(numWorkers,speedup,'-*')
grid on
title('Speedup and Efficiency with Number of Workers');
xlabel('Number of Workers');
xticks(numWorkers);
ylabel('Speedup');
yyaxis right
plot(numWorkers,efficiency,'--o');
ylabel('Efficiency')
xticks(numWorkers);
ylabel('Efficiency (%)');
legend('Speedup','Efficiency')
end

发现其他并行语言函数

您可以将 Parallel Computing Toolbox 与其他并行语言函数结合使用来执行这些任务。

  • 使用 parfeval 执行异步处理。

  • 使用 gpuArray 来加快您计算机支持的 GPU 上的计算速度。

  • 使用并行池的大数据处理工具(例如 distributedtall)来扩大您的计算规模。

  • 使用 batch 将您的计算卸载到计算机集群或云计算设施。

  • parsim (Simulink)batchsim (Simulink) 并行运行 Simulink® 模型。

  • 使用 MATLAB Parallel Server™ 软件将您的计算卸载到现场集群或云中。有关详细信息,请参阅集群和云

一些 MathWorks 产品现在提供对并行计算产品的内置支持,无需额外编码。有关这些产品及其并行功能的当前列表,请参阅 MATLAB 和 Simulink 产品中的并行计算支持

有关并行语言函数及其应用的更多信息,请参阅 选择并行计算解决方案并行语言决策表

另请参阅

| | | | | | | | | (Simulink) | (Simulink)

主题