繁体   English   中英

Matlab:过滤大型数组元素,更快地替代逻辑索引吗?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM