【发布时间】:2021-01-01 18:04:49
【问题描述】:
这是一个直截了当的问题:在 MATLAB 中是否有比 all(a(:,i)==a,1) 更快的替代方法?
我正在考虑一种在整个过程中受益于短路评估的实现。我的意思是,all() 肯定会从短路评估中受益,但 a(:,i)==a 不会。
我尝试了以下代码,
% example for the input matrix
m = 3; % m and n aren't necessarily equal to those values.
n = 5000; % It's only possible to know in advance that 'm' << 'n'.
a = randi([0,5],m,n); % the maximum value of 'a' isn't necessarily equal to
% 5 but it's possible to state that every element in
% 'a' is a positive integer.
% all, equal solution
tic
for i = 1:n % stepping up the elapsed time in orders of magnitude
%%%%%%%%%% all and equal solution %%%%%%%%%
ax_boo = all(a(:,i)==a,1);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end
toc
% alternative solution
tic
for i = 1:n % stepping up the elapsed time in orders of magnitude
%%%%%%%%%%% alternative solution %%%%%%%%%%%
ax_boo = a(1,i) == a(1,:);
for k = 2:m
ax_boo(ax_boo) = a(k,i) == a(k,ax_boo);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end
toc
但很明显,MATLAB 环境中的任何“for-loop-solution”都会自然而然地变慢。我想知道是否有用更快的语言编写的 MATLAB 内置函数。
编辑:
在运行更多测试后,我发现隐式扩展在评估a(:,i)==a 时确实会对性能产生影响。如果矩阵a 有多于一行,则all(repmat(a(:,i),[1,n])==a,1) 可能比all(a(:,i)==a,1) 快,具体取决于列数 (n)。对于n=5000,repmat 显式扩展已被证明更快。
但我认为,如果a 的所有元素都是正整数,那么 Kenneth Boyd 的答案的概括就是“终极解决方案”。我不会以原始形式处理a(m x n矩阵),而是存储和处理adec(1 x n矩阵):
exps = ((0):(m-1)).';
base = max(a,[],[1,2]) + 1;
adec = sum( a .* base.^exps , 1 );
换句话说,每一列将被编码为一个整数。当然adec(i)==adec 比all(a(:,i)==a,1) 快。
编辑 2:
我忘了提到adec 方法有一个功能限制。充其量,将adec 存储为uint64,以下不等式必须满足base^m < 2^64 + 1。
【问题讨论】:
-
这应该评估什么?您是否正在寻找与列
i相同的列? -
如果是这样的话,就相当于只评估它们是否都与第 1 列相同。无需循环它们。
-
在这种情况下,每列中的元素数量非常少,这意味着只有 8 个可能的唯一列。我会找出哪些列等于 8 种可能性中的每一种,而不是使用
b=([4 2 1]*a==[0:7].').'之类的东西来匹配 5 列中的每一种,这在 Octave 中似乎要快 3 或 4 个数量级。但是,当然,更改输入大小可能会对速度差异产生巨大影响。 -
这正是我选择留下评论而不是答案的原因。很明显,您没有向我们提供提供相关答案所需的详细信息。您评论中的所有信息都应包含在问题本身中。
-
嗯@Zalnd,那个“终极解决方案”看起来很眼熟……但我以为你不想要不同的方法?
标签: performance matlab boolean comparison-operators