在基于线程和基于进程的环境之间进行选择
使用 Parallel Computing Toolbox™,您可以在不同的并行环境中运行并行代码,例如基于线程或基于进程的环境。这些环境提供了不同的优势。
请注意,基于线程的环境仅支持进程工作单元可用的 MATLAB® 函数的子集。如果您对不受支持的函数感兴趣,请告知 MathWorks 技术支持团队。有关支持的更多信息,请参阅 检查对基于线程的环境的支持。
选择并行环境
根据您选择的并行环境的类型,功能可以在进程工作单元或线程工作单元上运行。要确定哪种环境适合您,请查阅下图和表。
要使用并行池功能(例如
parfor
或parfeval
),请使用parpool
函数在所选环境中创建并行池。环境 推荐 示例 本地计算机上的基于线程的环境 使用此设置可以减少内存使用量、加快调度速度并降低数据传输成本。
parpool('Threads')
注意
如果您选择
'Threads'
,请检查您的代码是否受支持。有关详细信息,请参阅检查对基于线程的环境的支持。要了解是否可以从基于线程的池中获得足够的好处,请使用
ticBytes
和tocBytes
测量基于进程的池中的数据传输。如果数据传输量很大,例如超过 100 MB,则使用'Threads'
。本地计算机上的基于进程的环境 在扩展到集群或云之前,请将此设置用于大多数用例和原型设计。
parpool('Processes')
远程集群上基于进程的环境 使用此设置来扩大您的计算规模。
其中parpool('MyCluster')
MyCluster
是集群配置文件的名称。要使用集群功能(例如
batch
),请使用parcluster
函数在所选环境中创建集群对象。请注意,集群功能仅在基于进程的环境中受支持。环境 推荐 示例 本地计算机上的基于进程的环境 如果您有足够的本地资源,或者在扩展到集群或云之前进行原型设计,请使用此设置。
parcluster('Processes')
远程集群上基于进程的环境 使用此设置来扩大您的计算规模。
parcluster('MyCluster')
其中
MyCluster
是集群配置文件的名称。
推荐
建议默认使用基于流程的环境。
它们支持完整的并行语言。
它们与之前的版本向后兼容。
在发生碰撞时它们更加坚固。
外部库不需要是线程安全的。
在以下情况下选择基于线程的环境:
您的并行代码由基于线程的环境支持。
您希望减少内存使用量、加快调度速度并降低数据传输成本。
比较进程工作单元和线程工作单元
下面以利用线程工作单元效率的示例为例,展示了进程工作单元和线程工作单元之间的性能比较。
创建一些数据。
X = rand(10000, 10000);
创建一个进程工作单元的并行池。
pool = parpool('Processes');
Starting parallel pool (parpool) using the 'Processes' profile ... Connected to the parallel pool (number of workers: 6).
对某些并行代码的执行进行计时并测量数据传输。对于此示例,使用 parfeval
执行。
ticBytes(pool);
tProcesses = timeit(@() fetchOutputs(parfeval(@sum,1,X,'all')))
tocBytes(pool)
tProcesses = 3.9060 BytesSentToWorkers BytesReceivedFromWorkers __________________ ________________________ 1 0 0 2 0 0 3 0 0 4 0 0 5 5.6e+09 16254 6 0 0 Total 5.6e+09 16254
请注意,数据传输非常重要。为了避免产生数据传输成本,您可以使用线程式工作单元。删除当前并行池并创建基于线程的并行池。
delete(pool);
pool = parpool('Threads');
计时相同代码运行的时间。
tThreads = timeit(@() fetchOutputs(parfeval(@sum,1,X,'all')))
tThreads = 0.0232
比较时间。
fprintf('Without data transfer, this example is %.2fx faster.\n', tProcesses/tThreads)
Without data transfer, this example is 168.27x faster.
线程工作单元的性能优于进程工作单元,因为线程工作单元可以使用数据 X
而无需复制它,并且它们的调度开销更少。
在基于进程和基于线程的池上并行解决优化问题
此示例说明如何使用基于进程和基于线程的池并行解决优化问题。
基于线程的池针对更少的数据传输、更快的调度和减少的内存使用进行了优化,因此可以提高应用程序的性能。
问题描述
问题是改变大炮的位置和角度,以便将抛射体发射到尽可能远的墙壁之外。该炮的炮口初速为 300 米/秒。墙高 20 米。如果大炮离墙壁太近,发射的角度就会太陡,抛射体的飞行距离就不够远。如果大炮离墙壁太远,抛射体就飞得不够远。有关完整问题的详细信息,请参阅并行优化 ODE (Global Optimization Toolbox)或视频代理优化的后半部分。
MATLAB 问题表述
为了解决这个问题,从 Global Optimization Toolbox 调用 patternsearch
求解器。目标函数位于 cannonobjective
辅助函数中,它计算抛射体在给定位置和角度下落在墙壁以外的距离。约束在 cannonconstraint
辅助函数中,它计算抛射体是否击中墙壁,或者是否在击中地面之前到达墙壁。辅助函数位于单独的文件中,您可以在运行此示例时查看它们。
为 patternsearch
求解器设置以下输入。请注意,要使用 Parallel Computing Toolbox,您必须在优化选项中将 'UseParallel'
设置为 true
。
lb = [-200;0.05]; ub = [-1;pi/2-.05]; x0 = [-30,pi/3]; opts = optimoptions('patternsearch',... 'UseCompletePoll', true, ... 'Display','off',... 'UseParallel',true); % No linear constraints, so set these inputs to empty: A = []; b = []; Aeq = []; beq = [];
基于流程的池化求解
为了进行比较,首先在基于进程的并行池上解决问题。
启动一个进程工作单元的并行池。
p = parpool('Processes');
Starting parallel pool (parpool) using the 'Processes' profile ... Connected to the parallel pool (number of workers: 6).
为了稍后重现相同的计算,请使用默认值为随机生成器提供种子。
rng default;
使用循环多次解决问题并取结果的平均值。
tProcesses = zeros(5,1); for repetition = 1:numel(tProcesses) tic [xsolution,distance,eflag,outpt] = patternsearch(@cannonobjective,x0, ... A,b,Aeq,beq,lb,ub,@cannonconstraint,opts); tProcesses(repetition) = toc; end tProcesses = mean(tProcesses)
tProcesses = 2.7677
为了准备与基于线程的池进行比较,请删除当前并行池。
delete(p);
基于线程池的解决方案
启动线程工作单元的并行池。
p = parpool('Threads');
Starting parallel pool (parpool) using the 'Threads' profile ... Connected to the parallel pool (number of workers: 6).
将随机数生成器恢复为默认设置并运行与之前相同的代码。
rng default tThreads = zeros(5,1); for repetition = 1:numel(tThreads) tic [xsolution,distance,eflag,outpt] = patternsearch(@cannonobjective,x0, ... A,b,Aeq,beq,lb,ub,@cannonconstraint,opts); tThreads(repetition) = toc; end tThreads = mean(tThreads)
tThreads = 1.5790
比较线程工作单元和进程工作单元的性能。
fprintf('In this example, thread workers are %.2fx faster than process workers.\n', tProcesses/tThreads)
In this example, thread workers are 1.75x faster than process workers.
请注意由于基于线程的池的优化而带来的性能提升。
完成计算后,删除并行池。
delete(p);
什么是基于线程的环境?
在基于线程的环境中,并行语言功能在由计算线程支持的工作单元上运行,这些工作单元在计算机的核心上运行代码。它们与计算进程的不同之处在于它们在同一个进程内共存并可以共享内存。
基于线程的环境与基于进程的环境相比具有以下优势。
由于线程式工作单元可以共享内存,因此它们无需复制即可访问数值数据,因此它们的内存效率更高。
线程之间的通信耗费的时间较少。因此,调度任务或者工作单元间通信的开销较小。
使用基于线程的环境时,请记住以下注意事项。
检查您的代码是否支持基于线程的环境。有关详细信息,请参阅检查对基于线程的环境的支持。
如果您正在使用来自工作单元 的外部库,那么您必须确保库函数是线程安全的。
什么是基于流程的环境?
在基于进程的环境中,并行语言特性在由计算进程支持的工作单元上运行,这些工作单元在计算机的核心上运行代码。它们与计算线程的不同之处在于它们彼此独立。
基于进程的环境与基于线程的环境相比具有以下优势。
它们支持所有语言功能,并与之前的版本向后兼容。
在发生碰撞时它们更加坚固。如果进程工作单元崩溃,那么 MATLAB 客户端不会崩溃。如果某个进程工作单元崩溃,并且您的代码不使用
spmd
或分布式数组,那么其余工作单元可以继续运行。如果您使用来自工作单元 的外部库,则无需注意线程安全。
您可以使用集群特征,例如
batch
。
当您使用基于流程的环境时,请牢记以下注意事项。
如果您的代码从工作单元访问文件,那么您必须使用附加选项(例如
'AttachedFiles'
或'AdditionalPaths'
)才能使数据可访问。
检查对基于线程的环境的支持
线程工作单元仅支持进程工作单元可用的 MATLAB 函数的子集。如果您对不受支持的函数感兴趣,请告知 MathWorks 技术支持团队。
使用 MATLAB Compiler™ 创建的独立应用程序和托管在 MATLAB Web App Server™ 上的 Web App 支持线程式工作单元。
有关线程式工作单元支持的函数的详细信息,请参阅 在基于线程的环境中运行 MATLAB 函数。