我需要找到满足条件A(i)< = b的向量A的第一个元素的索引。我事先知道A的至少一个元素符合条件。我尝试过这个,但效率非常低:
i = find(A <= b, 1)
似乎Matlab正在做与此相同的事情:
X = A <= b
find(X, 1)
计算X的所有元素都有浪费:一旦遇到i,你就应该停止A(i)&lt; = b。所以我尝试了这个:
for i = 1 : length(A)
if A(i) <= b
break
end
end
但迭代代码甚至比矢量化代码慢。
有没有办法更有效地执行此查找?
答案 0 :(得分:1)
我不确定你是如何得出循环代码比矢量化代码慢的结论,但这里是结果的基准和一些上下文!
我正在使用2015b,所以这可能会利用Matlab的new(ish) JIT compiler。
function benchie()
A = rand(1e9, 1);
b = 0.01;
f = @() original(A,b);
g = @() usingloop(A,b);
disp(['Original with logical A <= b: ', num2str(timeit(f)), ' sec']);
disp(['Looping until found, then break: ', num2str(timeit(g)), ' sec']);
end
% Both of these functions return the same value for idx
function idx = original(A,b)
idx = find(A <= b, 1);
end
function idx = usingloop(A,b)
for idx = 1:length(A)
if A(idx) <= b
break
end
end
end
<强>输出强>:
Original with logical A <= b: 0.83666 sec
Warning: The measured time for F [function g] may be inaccurate because it is running
too fast. Try measuring something that takes longer.
> In timeit (line 158)
In benchie (line 7)
Looping until found, then break: 1.8043e-06 sec
<强>摘要强>:
使A
与我的RAM一样大(8GB),usingloop
方法仍然太快,timeit
认为自己准确无误!这两个函数都给出了相同的答案,我认为usingloop
的速度要快几个数量级。
我希望包含一个显示不同大小数组时间比较的图表,但不能usingloop
太快...
注意:我使用idx
作为我的变量而不是i
。这是因为默认情况下i
是复数常量sqrt(-1)
,并且在写过时您将立即产生(小)性能影响!
修改强>
我运行了另一个测试,其中A = 1e8:-1:1;
和b
的值为A
的每十分之一,以确定向量化的开销是否超过了进一步循环所需的时间进入阵列。以下是输出:
您可以看到逻辑比较的开销几乎都是所需的时间,并且无论位置如何,该向量的实际索引都非常小。相反,一旦所需元素进入数组的短路,循环方法就很糟糕。
鉴于MATLAB使用矢量化和逻辑索引进行快速计算的声誉,我将回应@beaker的评论,说自定义(编译)C函数可能是看到对原始方法有任何改进的唯一方法。