我在 GPU (OpenCL) 的帮助下使用 arrayfire 来加速一些 C++ 代码。我有 600MB 和更多的 af::array,我需要沿列维度翻转然后转置它。
到目前为止,我几乎使用 C++ 例程完成了这些操作。然而,我现在想用 AF 来做,但注意到 AF 库的内存使用过多。我有两个问题:
1) 我完全不明白为什么 300MB 阵列上的任何操作(例如翻转或 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 框架内执行此操作。
(所有内存使用统计数据都是使用 gpustat 从 debian 上的 NVIDIA 内核驱动程序包中读取的。)
CPU后端的内存使用量也过多。
感谢 umar-arshad 的回复:当我上次在 CPU 上运行代码时,我分析了内存使用情况——假设它的行为相同。我在 GPU 上仔细检查了测量结果,并同时使用了 gpustat 和 nvidia-smi。事实上,测量的代码是不同的,正如你所解释的那样。现在一切都说得通了——至少是 GPU 部分。
也许在 CPU 上 foo 最初只有 f64,因为只使用了实部,并且通过使用翻转或转置它变成了 c64。
“分配在某些平台上的所有队列上触发隐式设备同步”的事实与此网站一起:http ://forums.accelereyes.com/forums/viewtopic.php?f=17&t=43097&p=61730&hilit=copy+host+ memory+into+an+array#p61727 和 af::printMemInfo(); 帮助我最终弄清楚了 AF 的大部分内存处理。大大加快了我的程序。
然而,就地(或尽可能少的开销)执行这两个操作的唯一选择仍然是使用:
// 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 格式和索引魔法而烦恼。所以我仍然在这里寻找建议。