例コード:はのparforループ内でクラスメソッドを参照:クラスの大幅なメモリ使用量
classdef testcls
methods
function sayhello(~)
disp('Hello! ')
end
end
end
と私は
A = testcls;
parfor ii = 1:4
A.sayhello()
end
以下のよう
parfor
でメソッドを呼び出す場合、今Mlintは私のパフォーマンスを告げますループ内の
A
の使用に関する問題:
The entire array or structure 'obj' is a broadcast variable. This might result in unnecessary communication overhead.
そして私はsuppr匿名関数を使用してこのメッセージを送信してください:
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
EDIT:
私はメモリのコピー操作に関連する重要なリソース消費を観察しました。基本的に、ジョブ・ディスパッチャーは、すべての変更されたプロパティーを含む各ワーカー用に同一のオブジェクトを作成します。
f = @A.sayhello;
このメソッドを使用すると、メソッド自体がクラスプロパティを呼び出したり保存したりしなくても、Matlabはオブジェクト全体を個々のワーカーにmemcpyする必要がなくなります。
私はこれが透明性を確保する方法だと思います。しかし、データ量が膨大な場合、これは頭の中で大きな痛みになるでしょう。
目的の機能をスタンドアロンのファイルベースの機能に分離する代わりに、オブジェクト全体にmemcopyを呼び出さないオブジェクトにsayhello
をパッケージ化する方法がありますか?
編集:示唆的な回答のために@gnoviceに感謝します。私は、parfor
を静的メソッドと比較するためのテストケースを作成しました。parfor
は非静的メソッドであり、シリアル実行はarrayfun
を使用しています。
テストケース1:非静的メソッド(コントロール)
とparfor
メモリ使用状況レコードに見られるように、単一のオブジェクトtestcls
の作成はで示される、〜700メガバイトのRAMを使用ラベル1
の後にclear
というラベルのコマンドが続き、ラベル3
の上にparfor
のループが続きます。 parfor
によるピーク使用量は単一のオブジェクトの約4倍ですが、プールには4人の作業者がいます。
テストケース2:静的メソッドとparfor
試験手順は同様に行われ、標識されています。この証拠から、結論は、メソッドを静的にするだけでは、すべての作業者に対して同じオブジェクトが生成されるのを防ぐことができないことになります。
テストケース3:arrayfun
を使用してシリアル評価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
を置き換えることができます。
あなたの最後のサンプルコードは、エラーを与える:「スライスされた変数fが関数ハンドルを参照してはなりません」 - 代わりに 'feval(f、ii)'を使用しなければなりません([こちらを参照](https://www.mathworks.com/help/distcomp/objects-and-handles-in-parfor-loops.html) – whrrgarbl
@ whrrgarbl whoaあなたが正しいです。自分のコードには何の議論もありませんでしたが、私はそれが1つのコードで動作すると思っていました。最も簡単な方法でコードを編集します。 – Yvon