2017-07-11 64 views
1

示例代碼:參照在PARFOR環類方法:顯著存儲器使用的一類

classdef testcls 
    methods 
     function sayhello(~) 
      disp('Hello! ') 
     end 
    end 
end 

和,如果我現在調用該方法在parfor如下

A = testcls; 
parfor ii = 1:4 
    A.sayhello() 
end 

Mlint告訴我一個性能問題在迴路中使用A

The entire array or structure 'obj' is a broadcast variable. This might result in unnecessary communication overhead.

而且我可以suppr ESS此消息通過使用匿名函數:

A = testcls; 
f = @A.sayhello; 
parfor ii = 1:4 
    f() 
end 

但我的問題是,這樣做幫助,反正速度?有沒有更好的方法來調用parfor中的方法?

那麼,如果我想設置函數的輸入/輸出參數,那麼情況會變得更復雜嗎?

classdef testcls 
    methods 
     function [out1,out2] = sayhello(~,n) 
      out1 = (['Hello! ', num2str(n)]); 
      out2 = n; 
     end 
    end 
end 

A = testcls; 
f = @A.sayhello; 
[a,b] = deal(cell(4,1)); 
parfor ii = 1:4 
    [a{ii},b{ii}] = feval(f,ii); 
end 

編輯:

我觀察相關的內存複製操作顯著資源消耗。基本上,作業調度員將爲每個工人創建一個相同的對象,包括所有修改後的屬性。

f = @A.sayhello;使用不會將Matlab從memcpy整個對象存儲到每個工作人員,即使該方法本身不調用或存儲任何類屬性。

我認爲這是確保透明度的方法。然而,當數據量巨大時,這將成爲頭痛的一大難題。

有沒有一種方法,而不是孤立所需的功能到一個獨立的基於文件的功能,包裝sayhello在對象中,將不會調用整個對象的複製?


編輯:感謝@gnovice提示性答案。我曾經爲了與靜態方法,parfor非靜態方法比較parfor做了一個試驗案例,並使用arrayfun串行執行。

測試用例1:parfor與非靜態方法(對照)

parfor non-static

如可在存儲器使用記錄可以看出,單個對象testcls的創建使用〜700MB RAM,由指示標籤1,隨後是一個clear命令標記爲2parfor環以上標籤3運行。 parfor的峯值使用量約爲單個對象的4倍,而游泳池有4名工人。

測試用例2:parfor與靜態方法

parfor static

試驗程序完成並以同樣的方式進行標記。從這些證據可以得出結論,只有將方法設爲靜態並不能防止parpool爲所有工作人員產生相同的對象。

測試用例3:使用arrayfun

serial

由於arrayfun串行評價進行非順序串行批次評價,這裏沒有理由arrayfun使用比需要由單個線程更多的存儲器。因此證據。

示例代碼:

classdef testcls 
    properties 
     D 
    end 
    methods (Static = false) 
     function [out1,out2] = sayhello(~,n) 
      out1 = (['Hello! ', num2str(n)]); 
      out2 = n; 
     end 
    end 
    methods 
     function obj = testcls(~) 
      obj.D = rand(1e8,1); 
     end 
    end 
end 

要運行測試,使用這個腳本:

clear;clc;close all 

A = testcls; 
f = @A.sayhello; 
parfor ii = 1:4 
    feval(f,ii) 
end 

您可以用arrayfun代替parfor串行驗證。

+1

你最後的示例代碼給出了錯誤:「切片變量f不能引用函數處理」 - 你必須使用'feval(F,II)'代替([見這裏](https://www.mathworks.com/help/distcomp/objects-and-handles-in-parfor-loops.html)) – whrrgarbl

+0

@ whrrgarbl哇你是對的。我自己的代碼沒有任何爭論,但我認爲它可以與一個工作。我編輯我的代碼到最簡單的情況。 – Yvon

回答

1

對於沒有引用類的所有屬性的方法,它可能是最好的,使他們static methods。從文檔:

Static methods are associated with a class, but not with specific instances of that class. These methods do not require an object of the class as an input argument, unlike ordinary methods which operate on specific objects of the class. You can call static methods without creating an object of the class

,因爲他們可以不必創建一個類的對象調用,這會幫助你避免在每個工人的整個對象的不必要的重複。

實例方法:

classdef testcls 
    ... 
    methods(Static) 
    function sayhello 
     disp('Hello!'); 
    end 
    end 
    ... 
end 

並把它從每個工人撥打:

testcls.sayhello(); 
+0

謝謝你的想法!我已經進行了比較測試並將結果發佈在問題中。不幸的是,靜態方法不能消除相同的對象產卵。請看看快照。 – Yvon

+1

@Yvon:調用與靜態方法'F = @ A.sayhello;'可能無法工作,因爲它仍然依賴於對象'A'。我會重新測試靜態方法,方法是在沒有對象的情況下調用它,只需要類名稱:'f = @ testcls.sayhello;'。我期望得到不同的結果。 – gnovice

+0

你說得對。通過類名稱調用靜態方法可避免相同對象的不必要的產生。它以這種方式工作,儘管我失去了訪問全班範圍運行時參數的機會,因爲我無法從「參數」(只有幾個數字來控制程序運行)中區分「數據」(大量出現)。 – Yvon

相關問題