2016-03-17 13 views
14

置換処理ではの異なる行列が出力に出力される必要があります。not like reshapeの場合、データは変更されません。permuteはデータを変更します。なぜMATLABは余分なメモリを必要としませんか?

ただし、多次元パーミュテーションのメモリ使用量をテストする場合は、使用する変数と同じです。ですから、私の質問は、どのように余分なメモリを使用しないようにMATLABはこの順列を実行するのですか?

その他の質問:MATLABが実際に余分なメモリを使用するシナリオはありますか?


テストコード:

function out=mtest() 
    out = ones(1e3,1e3,1e3); % Caution, 8Gb 
    out=permute(out,[3 1 2]); 
end 

コールこれに:

profile -memory on 
a=mtest; 
profreport 

注意、データのその8GBの。

答えて

10

あなたの議論は、MATLABメモリプロファイラがあなたに真実を伝えていないので、欠陥があります!

実際permute方法は

は、私はちょうどこれを自分自身を試してみました...データが並べ替えられ、それを返して、マトリックスの2番目のコピーを作成しない:

のWindows 10では
  • 、 「パフォーマンス」タブに「メモリ」グラフが表示された「タスクマネージャ」を開いた。私はまた、 "更新速度"を "高"に設定して、より細かい時間分解能を得ました。

  • 私はので、私のようにあなたの関数を変更しスラッシングを避けるために、私のラップトップ上のRAMの8本のライブを持っている:私は、関数を実行した

    function out = mtest() 
        out = rand([1e3,5e2,5e2]); % about 1.8 GB = 1e3*5e2*5e2*8/2^30 
        out = permute(out, [3 2 1]); 
    end 
    
  • 単に:

    %clear a 
    a = mtest(); 
    

    とメモリ使用量を監視しました。それは使用中の1.8ギグから、5.2に急上昇し、3.6ギグまで急速に下がった。これにより、コピーが作成されたことが確認されます。

    perfmon

    は、あなたがそのピーク時に関数が戻ったときの2倍のメモリ使用量に達したかを確認することができます

は私も同じパターンを示した0​​の下でテストを繰り返しました。これは、(より良い適切なメモリプロファイラ、インテル®Inspector XEのようなものを使用)、メモリ使用量をプロファイリングするための最良の方法は正確ではありませんが

、それはpermuteが実際インプレース働いていないことをある程度示しています。

+0

ブリリアント!私はMATLABが私を欺いていたのか疑問に思っていました。このコピーが実際に発生することを知ることは良いことです。 –

+1

すばらしい答え!私は、プログラマがメモリ効率よりも優先される速度 –

3

私は実際にpermuteがフードの下で何をしているのかわからないので、これは単なる推測です。

  1. 次元の置換は、常に要素の置換操作のシーケンスとして実行できます。「基本」とは、2つの次元のみを交換することを意味します。例えば、permute(x, [4 1 2 3])は基本並び替える操作のこの配列に相当する(配列が一意ではない):

    permute(..., [4 2 3 1]) %// interchange dims 1 and 4: we have dims [4 2 3 1] 
    permute(..., [1 4 3 2]) %// interchange dims 2 and 4: we have dims [4 1 3 2] 
    permute(..., [1 2 4 3]) %// interchange dims 3 and 4: we have dims [4 1 2 3] 
    
  2. これらの基本操作(二次元を入れ替える)の各々は、本質的に多次元の所定の平面に沿って転置であります他のすべての次元に沿って繰り返し実行されます。

  3. 転位can be done inline固定量の余分なメモリしか必要とせず、アレイサイズに依存せず、またはアレイサイズによって非常にゆっくりと成長する。一緒にこれら三つの事実を置く

はそれが余分な大量のメモリなしでそれを行うには可能であることを示しています。しかし、Matlabが実際に使用しているアプローチではないかもしれません。

+0

転置は転置より速いです。私はそれが配列データに全く触れていないと賭けているだけで、インデックスが評価される順番を変えるだけです。もし2D実行列を転置したいなら、 'numrows * colindex + rowindex'を実行する代わりにインデックスを1Dのバッキング配列に追加するには、単にnumcols * rowIndex + colindexを使用するように切り替えることができます。それは、データを変更することなく行列を転置するような外観になります。暗黙の[1 2 3 4 ... N]設計に頼るのではなく、次元をトラバースする順序を指定する配列を各配列に簡単に関連付けることができます。 – KitsuneYMG

+1

@KitsuneYMG私はあなたが何を意味しているのか知っていますが、このロジックには欠陥があります。その "インデックススイッチ"でアレイをインデックスすることは、メモリリードキャッシュに対して非常にコストがかかります。あなたが言うことが正確に(インデックス化された変更と同じように)起こるならば、後で他の操作で行列を使用すると、転置されたという理由だけでパフォーマンスが大幅に低下します。この効果はMATLABでは見られません。私の推測では、他のアルゴリズムを使用しているため、転置は高速です。 –

+0

@Amrosを見ると、メモリを意識したpermuteを作るために 'mempermute'関数を作成することができますか? –

関連する問題