5

このバグは、Matlab が賢すぎてそれ自体が役に立たないことが原因です。

私は次のようなものを持っています

for k=1:N
    stats = subfun(E,k,stats);
end

wherestats1xN配列で、N=5000たとえば、 からsubfun計算stats(k)E、それを統計に入力します

function stats = subfun(E,k,stats)
    s = mean(E);
    stats(k) = s;
end

もちろん、大きな配列を前後に渡すと、その要素の 1 つを埋めるためだけにオーバーヘッドが発生します。ただし、私の場合、オーバーヘッドはごくわずかであり、代わりにこのコードを好みます

for k=1:N
    s = subfun(E,k);
    stats(k) = s;
end

私の好みは、実際にはstats. また、いくつかの割り当ては、実際にはかなり複雑です。

前述のとおり、オーバーヘッドは無視できます。しかし、私が些細なことをすると、この取るに足らないif文のように

for k=1:N
    i = k;
    if i>=1
        stats = subfun(E,i,stats);
    end
end

subfun 内で行われる割り当ては、突然「永久に」かかります (N で直線的に増加するよりもはるかに速く増加します)。そして、永遠にかかるのは計算ではなく、割り当てです。実際、それは次のナンセンスよりもさらに悪いですsubfun

function stats = subfun(E,k,stats)
    s = calculation_on_E(E);
    clear stats
    stats(k) = s;
end

毎回統計を再割り当てする必要があります。

なぜこれが起こるのか、誰かが最もかすかな考えを持っていますか?

4

2 に答える 2

5

これは、Matlab のJITのあいまいな詳細が原因である可能性があります。最近のバージョンの Matlab の JIT は、新しい配列を作成するのではなく、限られたケースでその場で変更を行うことを認識しています。要件の 1 つは、関数が次のように定義されていることです。

function x = modify_big_matrix(x, i, j)
x(i, j) = 123;

としてではなく

function x_out = modify_big_matrix(x_in, i, j)
x_out = x_in;
x_out(i, j) = 123;

あなたの例はこのルールに従っているように見えるので、プレトリアンが述べたように、あなたのifステートメントは、JITがインプレース操作であることを認識できない可能性があります。

アルゴリズムを本当に高速化する必要がある場合は、独自の mex-functions を使用して配列をインプレースで変更できます。このトリックを使用して、いくつかの中規模のアレイ (100x100x100 IIRC のオーダー) で 4 倍のスピードアップを達成しました。ただし、これはお勧めできません。注意しないと、Matlab でセグメンテーション違反が発生する可能性があり、将来のバージョンで動作しなくなる可能性があります。

于 2013-09-26T18:17:35.773 に答える
0

他の人が議論したように、問題はほぼ間違いなく JIT と、その場で変更する比較的脆弱な能力にあります。

前述のように、他の実行可能な解決策が提案されていますが、私は関数呼び出しと代入の最初の形式を本当に好みます。JIT に依存しない場合、これが効率的である唯一の方法は (私が見る限り)、何らかの形式の参照渡しです。

Statsしたがって、ハンドルから継承し、のデータ配列を含むクラスを作成しましたk=1:N。その後、参照によって渡されます。

将来の参考のために、これは非常にうまく機能し、優れたパフォーマンスを発揮するようです。現在、私はそれを私の実用的なソリューションとして使用しています.

于 2013-09-27T07:09:58.230 に答える