我有一个大型的浮动三维数据集,大约有5亿个元素(3000 x 300 x 600)。
我想使低于或高于特定阈值的元素为零。逻辑索引可以做到这一点,例如
__INT64_TYPE__
问题是这对我来说非常缓慢,数据量大。上面的代码需要240秒才能在我的计算机上运行。有没有更快的方法可以做到这一点?
非常感谢
答案 0 :(得分:0)
正如@rayryeng和@AndrasDeak在对你的问题的评论中指出的那样,逻辑索引通常是最快的,尽管你的运行时表明你可能受到内存的限制(并且被迫交换到磁盘上)而不是实际的速度。索引。
在这种情况下可以胜出的一个令人惊讶的替代方案是循环。这是因为逻辑索引需要三次遍历数组(每次不等式测试一次,一次更改数据),而for循环只需要一次遍历数组。
所以我在具有8 GB内存的机器上运行这些测试(并且意外地将数组大小加倍):
>> A = randn(6000,300,600);
>> cut_in = -1;
>> cut_out = 1;
使用for循环:
>> tic; for i=1:numel(A), if A(i)<cut_in || A(i)>cut_out, A(i)=0; end; end; toc
Elapsed time is 597.384884 seconds.
使用逻辑索引:
>> tic; A(A<cut_in | A>cut_out) = 0; toc
Elapsed time is 1619.105332 seconds.
只是为了笑(有一些时间在我的手上等待基准运行),这里是一个编译for循环:
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *A = mxGetPr(prhs[0]);
size_t N = mxGetNumberOfElements(prhs[0]);
double cut_in = *mxGetPr(prhs[1]);
double cut_out = *mxGetPr(prhs[2]);
// You're not supposed to do in-place operations! Don't do this!
for (ptrdiff_t ii=0; ii<N; ii++) {
if ((A[ii]<cut_in) || (A[ii]>cut_out))
A[ii] = 0;
}
}
基准测试:
>> mex -v CXXOPTIMFLAGS="-O3 -DNDEBUG" -largeArrayDims apply_threshold.cpp
>> tic; apply_threshold(A,cut_in,cut_out); toc
Elapsed time is 529.994643 seconds
要记住的一点是,我们在一个访问交换空间是性能主要瓶颈的制度下运行,因此即使在同一台机器内,基准测试结果也会有所不同,具体取决于当前主存储器中的内容(与需要交换的内容相比,以及正在运行的后台进程。