[英]Matlab: filtering large array elements, quicker alternative to logical indexing?
我有一个大型的三维浮点数据集,大约有5亿个元素(3000 x 300 x 600)。
我想将低于或高于某些阈值的元素设为零。 逻辑索引可以做到这一点,例如
cut_in = 0.5
cut_out = 6
Hs(Hs<cut_in) = 0 ;
Hs(Hs>cut_out) = 0 ;
问题在于,对于大数据量来说,这对于我来说是缓慢的。 上面的代码需要240秒才能在我的计算机上运行。 有没有更快的方法可以做到这一点?
非常感谢
正如@rayryeng和@AndrasDeak在对问题的注释中指出的那样,逻辑索引通常是最快的,尽管您的运行时建议您可能受内存(并被强制交换到磁盘)的限制,而不是受索引实际速度的限制。
在这种情况下可以胜出的一种令人惊讶的替代方法是for循环。 这是因为逻辑索引需要遍历该数组三遍(每个不等式测试一次,一次更改数据),而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
要记住的一件事是,我们在一种操作环境中进行操作,其中访问交换空间是性能的主要瓶颈,因此,即使在同一台机器上,基准测试结果也可能有所不同,具体取决于主内存中的当前内容(与之相对)。需要交换)以及正在运行哪种后台进程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.