6

ループ内で、aparforにアクセスする関数を呼び出そうとしていますglobal

関数

function a = getA()
   global OPTIONS;
   a=OPTIONS.PROBLEM.A;
end

ループ:

parfor i=1:3
    b=getA();
end

エラー:

Error using parallel_function (line 589)

Attempt to reference field of non-structure array.

私は何が間違っているのですか?

4

2 に答える 2

8

上のドキュメントからparfor

parfor-loopの本体には、グローバル変数宣言または永続変数宣言を含めることはできません。

問題のコンテキストで、つまり、内で関数を呼び出してaparforを参照するglobal場合、これは次のように変換されます。「parfor期待される結果または意味のある結果が得られない可能性があります」。

これは完全に理にかなっています。次のことを考慮してください

Lab 1:         Lab 2: 

GetB();        GetB();

の内容GetB()がこれである場合:

function GetB()
    global B;

    %# do something useful

    B = rand;

 end

B参照されたときの値はどうなりLab 1ますか?とLab 2randコミュニケーションのさまざまな結果はどのようになっていますか?めちゃくちゃになりそうです!

ループに適したコードを書くことは、そのコードが通常のループしか念頭に置いparforていないものからのものである場合、非常に苦痛になる可能性があります。for一般に、計算量の多いMatlabコードを作成することが事前にわかっている場合は、すべての関数とループをparfor最初からループとして作成します。これが、このようなバグが関数のトランスコードに1日もかからない唯一の方法です。

forからへの変換は、まったく簡単でparforはありません。

于 2012-08-30T11:58:23.057 に答える
6

GLOBALPARFOR各ワーカーは個別のMATLABプロセスであり、グローバル変数はクライアント(または他のプロセス)からワーカーに同期されないため、データを内部で使用するのは困難です。ワーカーの別の関数からグローバルデータを初期化すると機能します。(Rodyが指摘しているように、PARFORループの本体でglobalキーワードを直接使用することは許可されていません。ただし、個別の関数でこれを行うことができます)。したがって、これを行うことは合法です。

parfor ii=1:matlabpool('size')
  myFcnWhichSetsUpGlobalData(); %# defines global OPTIONS
end
parfor ii=1:N
  result(ii) = myFcnWhichUsesGlobalData(); %# reads global OPTIONS
end

私は個人的にGLOBALあなたのアプリケーションからデータを削除しようとします-それはそれがでより良く機能するようになりPARFOR、そしてそれは依存関係をより明確にするでしょう。

探索するもう1つのオプションは、ワーカーにデータを複数回転送する必要がないように設計されたワーカーオブジェクトラッパーです。あなたはそれをこのように使うかもしれません:

options = buildOptions();
w_options = WorkerObjWrapper(options);
parfor ii=1:N
  result(ii) = myFcnNeedingOptions(ii, w_options.Value);
end
于 2012-08-30T12:42:24.077 に答える