arrayfire を使用して、GPU (OpenCL) の助けを借りて一部の C++ コードを高速化します。私は 600MB 以上の af::array を持っており、列の次元に沿って反転させて転置する必要があります。
これまでのところ、C++ ルーチンを使用してこれらの操作をほぼ適切に実行しました。しかし、AFでそれをやりたいのですが、AFライブラリの過度のメモリ使用に気付きました. これには2つの問題があります:
1) 300MB 配列に対する操作 (flip や T など) が 900MB をはるかに超えるメモリを使用する理由がまったくわかりません。2) 配列 foo のコピーを作成しないようにする方法を知りたいです。操作を別の関数内にカプセル化することで、コピーを取り除くことができると考えました。
次のようなコードがあります。
void prepare_array(af::array &a) {
af::array b = af::flip(a, 1); // ~1400MB
a = b.T(); // ~3000MB
}
af::array foo = af::randn(768,16384,3,1,c64); // ~300MB
prepare_array(foo);
af::deviceGC(); // ~600MB
この操作は一度だけ実行する必要があるため、速度はメモリ使用量ほど重要ではありませんが、AF フレームワーク内でこの操作を実行することをお勧めします。
(すべてのメモリ使用統計は、debian の NVIDIA カーネル ドライバー パッケージから gpustat で読み取られます。)
CPU バックエンドのメモリ使用量も過剰です。
返信 umar-arshad のおかげです: 前回 mem-usage のプロファイリングを行ったとき、CPU でコードを実行しました - それが同じように動作すると仮定して。GPU で測定値を再確認し、gpustat と nvidia-smi の両方を使用しました。実際、コードは測定値が異なり、説明したとおりです。少なくとも GPU の部分については、今では完全に理にかなっています。
おそらく CPU 上の foo は最初は f64 だけです。これは、実部のみが使用され、フリップまたは転置のいずれかを使用して c64 になるためです。
「割り当てにより、特定のプラットフォームのすべてのキューで暗黙的なデバイス同期がトリガーされる」という事実と、この Web サイト: http://forums.accelereyes.com/forums/viewtopic.php?f=17&t=43097&p=61730&hilit=copy+host+ memory+into+an+array#p61727 および af::printMemInfo(); AFのメモリ処理のほとんどを最終的に理解するのに役立ちました。プログラムを大幅に高速化します。
ただし、現時点では、これら 2 つの操作をインプレースで (または可能な限り少ないオーバーヘッドで) 実行する唯一の代替手段は、次を使用することです。
// Generate/store data in std::array<af::cdouble> foo_unwrap = new af::cdouble[768*16384*3*1];
// Flip/Transpose foo_unwrap in plain C/C++, like in:
// for(column = 0; column < max_num_column/2; column++)
// swap column with max_num_column-1-column
//
// http://www.geeksforgeeks.org/inplace-m-x-n-size-matrix-transpose/
// but for Column-Major Order matrices
//
// and afterwards whenever needed do ad-hoc:
af::cdouble* first_elem = (af::cdouble*) &(foo_unwrap[0]); // to ensure correct type detection via AF
af::array foo = af::array(768,16384,3,1, first_elem, afDevice);
ただし、Row-/Column-Major 形式とインデックス マジックを気にしたくなかったので、これは非常に面倒です。だから私はまだここで提案を探しています。