使用“行”更快地替换INTERSECT - MATLAB

时间:2015-02-13 06:32:52

标签: performance matlab matrix intersect

我有一个用Matlab编写的代码,它使用' intersect'找到在两个大矩阵中相交的向量(及其索引)。我发现'相交'是我的代码中最慢的行(通过很大的差异)。不幸的是,到目前为止,我找不到更快的替代方案。

作为一个示例,运行下面的代码需要大约5秒钟在我的电脑上:

profile on
for i = 1 : 500
    a = rand(10000,5);
    b = rand(10000,5);
    [intersectVectors, ind_a, ind_b] = intersect(a,b,'rows');
end
profile viewer

我想知道是否有更快的方法。注意,矩阵(a)和(b)有5列。对于两个矩阵,不必要的行数必须相同。

任何帮助都会很棒。 感谢

1 个答案:

答案 0 :(得分:3)

讨论和解决方案代码

您可以使用利用fast matrix multiplication in MATLAB的方法将输入数组的5列转换为一列,方法是将每列视为重要的数字"一个数字。因此,您最终会得到一个只包含列的数组,然后,您可以使用intersectismember而不使用'rows',这必须大大加快代码的速度!

以下是作为功能代码的承诺实现,以便于使用 -

<强> intersectrows_fast_v1.m:

function [intersectVectors, ind_a, ind_b] = intersectrows_fast_v1(a,b)

%// Calculate equivalent one-column versions of input arrays
mult = [10^ceil(log10( 1+max( [a(:);b(:)] ))).^(size(a,2)-1:-1:0)]'; %//'
acol1 = a*mult;
bcol1 = b*mult;

%// Use intersect without 'rows' option for a good speedup
[~, ind_a, ind_b] = intersect(acol1,bcol1);
intersectVectors = a(ind_a,:);

return;

<强> intersectrows_fast_v2.m:

function [intersectVectors, ind_a, ind_b] = intersectrows_fast_v2(a,b)

%// Calculate equivalent one-column versions of input arrays
mult = [10^ceil(log10( 1+max( [a(:);b(:)] ))).^(size(a,2)-1:-1:0)]'; %//'
acol1 = a*mult;
bcol1 = b*mult;

%// Use ismember to get indices of the common elements
[match_a,idx_b] = ismember(acol1,bcol1);

%// Now, with ismember, duplicate items are not taken care of automatically as
%// are done with intersect. So, we need to find the duplicate items and
%// remove those from the outputs of ismember
[~,a_sorted_ind] = sort(acol1);
a_rm_ind =a_sorted_ind([false;diff(sort(acol1))==0]); %//indices to be removed
match_a(a_rm_ind)=0;

intersectVectors = a(match_a,:);
ind_a = find(match_a);
ind_b = idx_b(match_a);

return;

快速测试和结论

使用问题中列出的数据,运行时间为 -

-------------------------- With original approach
Elapsed time is 3.885792 seconds.
-------------------------- With Proposed approach - Version - I
Elapsed time is 0.581123 seconds.
-------------------------- With Proposed approach - Version - II
Elapsed time is 0.963409 seconds.

结果似乎表明支持两种提议方法的version - I的一个很大的优势,在原始方法上的强度加速 6.7x !! < / p>

此外,请注意,如果您不需要原始intersect的三个输出中的任何一个或两个输出&#39;行&#39;基于方法,然后可以进一步缩短所提出的方法以获得更好的运行时性能!