1.
https://ww2.mathworks.cn/matlabcentral/answers/46102-when-to-use-spmd-and-parfor-function
這是一個非常簡短的摘要:
PARFOR比SPMD使用起來簡單得多,通常在嘗試并行化獨立計算的集合時,它通常是您的首選。您需要確定您的計算不依賴于順序(即,它們一定不能依賴于先前計算的結果)。
SPMD較難使用,但允許使用labSend和labReceive的從業人員之間進行通信。如果您希望為分布式陣列實作新功能,這也是合适的選擇。
2.
https://ww2.mathworks.cn/matlabcentral/answers/48871-best-approach-to-this-problem-spmd-or-parfor
我想說這聽起來像是您的PARFOR解決方案可能接近您可以做的最好的事情。聽起來您的問題很适合PARFOR-很多獨立的工作要做。使用SPMD可以實作相同的目的,但是您将無法獲得PARFOR所提供的自動負載平衡功能,是以最終運作效率可能會降低。
您可能考慮的一件事是将PARFOR循環移動到外部循環,因為這将減少與并行運作相關的一些開銷。
3.
https://stackoverflow.com/questions/12385534/spmd-vs-parfor
spmd是并行區域,而parfor是并行for循環。差別在于,在spmd區域中,您可以并行執行的任務具有更大的靈活性。您可以編寫一個for循環,可以對分布式數組和向量進行操作。您可以對整個工作流程進行程式設計,該工作流程通常包含多個循環。這是有代價的:您需要更多地了解如何線上程之間配置設定工作和資料。例如,并行化循環需要在工作線程之間顯式地劃分循環索引範圍(通過使用labindex在代碼中進行此操作),并可能建立分布式數組。
另一方面,parfor僅這樣做-并行化的for循環。您可以添加自動并行化的工作,是以工作可以通過MATLAB在從業人員之間進行劃分。
如果隻想并行運作一個循環,然後再在本地用戶端上處理結果,則應使用parfor。如果要并行化整個MATLAB程式,則必須處理spmd和工作配置設定的複雜性。
4.
spmd如果您在計算期間需要worker之間的通信,請使用此選項。
parfeval在以下情況下使用:
● 您想在背景運作計算。
● 每個任務都依賴于其他任務。
5.
https://ww2.mathworks.cn/help/parallel-computing/choose-spmd-parfor-parfeval.html
通信并行代碼
要運作在并行計算,可以使用parfor, parfeval,parfevalOnAll,或 spmd。每個構造都依賴于不同的并行程式設計概念。如果你要求勞工在整個計算,用于通信 parfeval,parfevalOnAll或 spmd。
● 如果您的代碼可以分為一組任務,請使用parfeval或parfevalOnAll,其中每個任務可以取決于其他任務的輸出。
● spmd如果您在計算期間需要從業人員之間的通信,請使用此選項。
與parfeval的計算最好用圖形表示,類似于帶阻塞的看闆。通常,計算完成後會從從業人員那裡收集結果。您可以parfeval使用afterEach 或從執行操作中收集結果 afterAll。通常将結果用于進一步的計算。
spmd類似于瀑布式工作流程,用最好用流程圖表示。執行spmd 語句的池工作程式稱為實驗室。可以在計算過程中從實驗室收集結果。有時,實驗室必須與其他實驗室進行通信才能完成計算。
如果不确定,請問自己以下問題:在我正在交流的并行代碼中,無需勞工之間的任何交流就可以完成每個計算嗎?如果是,請使用 parfeval。否則,請使用spmd。
同步和異步工作
當之間進行選擇parfor, parfeval和spmd,考慮你的計算是否需要與用戶端同步。
parfor并spmd要求同步,是以從MATLAB上運作的任何新的計算結果阻止你®用戶端。parfeval不需要同步,是以用戶端可以自由地從事其他工作。
比較多線程性能和 ProcessPool
檢視MATLAB指令
在此示例中,您将比較快速功能在用戶端和上運作的速度ProcessPool。一些MATLAB函數使用多線程。使用這些功能的任務在多個線程上的性能要優于單個線程。是以,如果在具有多個核心的計算機上使用這些功能,則本地群集的性能可能比用戶端上的多線程性能差。
如果在用戶端上執行多個執行的速度比-loop更快clientFasterThanPool,則傳回本示例末尾列出的支援功能。文法與以下内容相同:将函數句柄用作第一個參數,将輸出數量用作第二個參數,然後為該函數提供所有必需的參數。trueparforparfeval
首先,建立一個local ProcessPool。
p = parpool('local');
使用``本地''配置檔案啟動并行池(parpool)...
連接配接到并行池(勞工人數:6)。
eig使用clientFasterThanPool支援功能檢查功能運作的速度。建立一個匿名函數eig以代表您的函數調用。
[〜,t_client,t_pool] = clientFasterThanPool(@(N)eig(randn(N)),0,500)
t_client = 22.6243
t_pool = 4.9334
并行池比用戶端更快地計算答案。除以t_client通過maxNumCompThreads查找用戶端上的每個線程所花費的時間。
t_client / maxNumCompThreads
年= 3.7707
預設情況下,工作程序是單線程的。結果表明,用戶端和池上每個線程花費的時間相似,因為的值t_pool大約是的1.5倍t_client/maxNumCompThreads。該eig功能無法從多線程中受益。
接下來,lu使用clientFasterThanPool支援功能檢查該功能運作的速度。
[〜,t_client,t_pool] = clientFasterThanPool(@(N)lu(randn(N)),0,500)
t_用戶端= 1.0225
t_pool = 0.4693
如果本地計算機具有四個或更多核心,那麼并行池通常比用戶端更快地計算答案。除以t_client通過maxNumCompThreads找到每個線程所花費的時間。
t_client / maxNumCompThreads
年= 0.1704
此結果表明,用戶端上每個線程花費的時間比池中少得多,因為的值t_pool大約是的3倍t_client/maxNumCompThreads。每個線程使用較少的計算時間,表明lu使用多線程。
定義輔助函數
支援功能clientFasterThanPool檢查用戶端上的計算是否比并行池上的計算更快。它以函數句柄fcn和可變數量的輸入參數(in1, in2, ...)作為輸入。clientFasterThanPool執行fcn(in1, in2, ...)用戶端和活動并行池兩者上。例如,如果要測試rand(500),則函數句柄必須采用以下形式:
fcn = @(N)rand(N);
然後,使用clientFasterThanPool(fcn,500)。
函數[結果,t_multi,t_single] = clientFasterThanPool(fcn,numout,varargin)
%為輸出預配置設定單元格數組
輸出= cell(numout);
客戶百分比
抽動
對于i = 1:200
如果numout == 0
fcn(varargin {:});
其他
[outputs {1:numout}] = fcn(varargin {:});
年底
結束
t_multi = toc;
%平行泳池
vararginC = parallel.pool.Constant(varargin);
抽動
parfor i = 1:200
%為輸出預配置設定單元格數組
輸出= cell(numout);
如果numout == 0
fcn(vararginC.Value {:});
其他
[outputs {1:numout}] = fcn(vararginC.Value {:});
年底
結束
t_single = toc;
%如果多線程化更快,則傳回true
結果= t_single> t_multi;
結束
比較性能parfor,parfeval和spmd
檢視MATLAB指令
取決于計算類型,使用spmd可能比使用parfor-loops或慢或快parfeval。開銷會影響parfor-loopparfeval和的相對性能spmd。
對于一組任務,parfor并且parfeval通常執行優于spmd在這些條件下。
● 每個任務花費的計算時間不确定。
● 每個任務花費的計算時間不一緻。
● 從每個任務傳回的資料很小。
parfeval在以下情況下使用:
● 您想在背景運作計算。
● 每個任務都依賴于其他任務。
在此示例中,您檢查了使用parfor-loop parfeval,和時執行矩陣運算的速度spmd。
首先,建立一個本地并行池p。
p = parpool('local');
使用``本地''配置檔案啟動并行池(parpool)...
連接配接到并行池(勞工人數:6)。
計算随機矩陣
通過使用parfor-loop parfeval,和來檢查生成随機矩陣的速度spmd。設定試驗次數(n)和矩陣大小(對于m-bym矩陣)。增加試驗次數可以改善以後分析中使用的統計資訊,但不會影響計算本身。
m =
1000;
n =
20;
然後,使用parfor-looprand(m)對每個工作程式執行一次。為每個m試驗安排時間。
parforTime = zeros(n,1);
因為我= 1:n
抽動
墊= cell(1,p.NumWorkers);
PARFOR N = 1:p.NumWorkers
mats {N} = rand(m);
結束
parforTime(i)= toc;
結束
接下來,用于為每個工作程式parfeval執行rand(m)一次。為每個m試驗計時。
parfevalTime =零(n,1);
因為我= 1:n
抽動
f(1:p.NumWorkers)= parallel.FevalFuture;
對于N = 1:p.NumWorkers
f(N)= parfeval(@ rand,1,m);
端
墊= fetchOutputs(f,“ UniformOutput”,false)';
parfevalTime(i)= toc;
明确˚F
結束
最後,用于為每個實驗spmd執行rand(m)一次。有關實驗室及其執行指令的詳細資訊spmd,請參閱在多個資料集上運作單個程式。為每個m試驗計時。
spmdTime = zeros(n,1);
因為我= 1:n
抽動
spmd
e =蘭特(m);
結束
eigenvals = {e {:}};
spmdTime(i)= toc;
結束
用于rmoutliers從每個試驗中删除異常值。然後,用于boxplot比較時間。
%隐藏異常值
boxData = rmoutliers([parforTime parfevalTime spmdTime]);
%劇情資料
箱線圖(boxData,'标簽',{ 'PARFOR' ,'parfeval' ,'SPMD' },'符号','' )
ylabel('時間(秒)')
title('制作n個随機矩陣(m×m)')
通常,spmd每次評估比parfor或需要更多的開銷parfeval。是以,在這種情況下,使用parfor-loop或parfeval更有效。
計算随機矩陣之和
接下來,計算随機矩陣的總和。您可以通過減少變量和做到這一點parfor-loop,一筆帶計算後parfeval,或gplus用spmd。再次,設定試驗次數(n)和矩陣大小(對于m-副m矩陣)。
m =
1000;
n =
20;
然後,使用parfor-looprand(m)對每個工作程式執行一次。用歸約變量計算總和。為每個m試驗計時。
parforTime = zeros(n,1);
因為我= 1:n
抽動
結果= 0;
PARFOR N = 1:p.NumWorkers
結果=結果+ rand(m);
結束
parforTime(i)= toc;
結束
接下來,用于為每個工作程式parfeval執行rand(m)一次。使用fetchOutputs上的所有矩陣,然後使用sum。為每個m試驗計時。
parfevalTime =零(n,1);
因為我= 1:n
抽動
f(1:p.NumWorkers)= parallel.FevalFuture;
對于N = 1:p.NumWorkers
f(N)= parfeval(@ rand,1,m);
結束
結果= sum(fetchOutputs(f));
parfevalTime(i)= toc;
明确˚F
結束
最後,用于為每個實驗spmd執行rand(m)一次。用于gplus對所有矩陣求和。要将結果僅發送到第一個實驗室,請将可選targetlab參數設定為1。為每個m試驗計時。
spmdTime = zeros(n,1);
因為我= 1:n
抽動
spmd
r = gplus(rand(m),1);
結束
結果= r {1};
spmdTime(i)= toc;
結束
用于rmoutliers從每個試驗中删除異常值。然後,用于boxplot比較時間。
%隐藏異常值
boxData = rmoutliers([parforTime parfevalTime spmdTime]);
%劇情資料
箱線圖(boxData,'标簽',{ 'PARFOR' ,'parfeval' ,'SPMD' },'符号','' )
ylabel('時間(秒)')
title('n個随機矩陣之和(m×m)')
對于此計算,spmd其速度明顯快于parfor-loop或parfeval。在parfor-loop中使用歸約變量時,會将-loop每次疊代的結果廣播parfor給所有工作程式。相比之下,僅spmd調用gplus一次即可執行全局歸約操作,所需的開銷更少。這樣,計算的減少部分的開銷為O (ñ2)對于spmd和Ô (米ñ2)為parfor。