天天看點

Matlab 并行運算的嘗試

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。

繼續閱讀