在Matlab中高效矢量化元素操作

时间:2018-10-29 09:44:45

标签: arrays matlab vectorization

我有一个代表n个球体的nx4矩阵A和一个代表m个点的mx3矩阵B。我需要测试这些m点是否在任何球体内。我可以使用for循环执行此操作,但是对于较大的nm而言,此方法效率很低。如何将这个操作向量化?我目前的方法是

A = [0.8622    1.1594    0.7457    0.6925;
     1.4325    0.2559    0.0520    0.4687;
     1.8465    0.3979    0.2850    0.4259;
     1.4387    0.8713    1.6585    0.4616;
     0.2383    1.5208    0.5415    0.9417;
     1.6812    0.2045    0.1290    0.1972];

B = [0.5689    0.9696    0.8196;
     0.5211    0.4462    0.6254;
     0.9000    0.4894    0.2202;
     0.4192    0.9229    0.4639];

for i=1:size(B,1)

    mask = vecnorm(A(:, 1:3) - B(i,:), 2, 2) < A(:, 4);

    if sum(mask) > 0
        C(i) = true;
    else
        C(i) = false;
    end %if

end %for

我测试了@LuisMendo建议的方法,似乎它只加快了相当小的mn的计算速度,却加快了mn的计算速度,例如,我的问题大约在10000左右,改进非常有限。但是@NickyMattsson给了我一些提示。由于matlab中的逻辑运算比vecnorm更快,因此我首先使用粗略的检查来找到该点附近的球体,然后进行精细的检查:

A = [0.8622    1.1594    0.7457    0.6925;
     1.4325    0.2559    0.0520    0.4687;
     1.8465    0.3979    0.2850    0.4259;
     1.4387    0.8713    1.6585    0.4616;
     0.2383    1.5208    0.5415    0.9417;
     1.6812    0.2045    0.1290    0.1972];

B = [0.5689    0.9696    0.8196;
     0.5211    0.4462    0.6254;
     0.9000    0.4894    0.2202;
     0.4192    0.9229    0.4639];

ids = 1:size(A, 1);

for i=1:size(B,1)

    % first a rough check
    xbound = abs(A(:, 1) - B(i, 1)) < A(:, 4);
    ybound = abs(A(:, 2) - B(i, 2)) < A(:, 4);
    zbound = abs(A(:, 3) - B(i, 3)) < A(:, 4);
    nears = ids(xbound & ybound & zbound);
    if isempty(nears)
        C(i) = false;
    else 
        % then a fine check
        mask = vecnorm(A(nears, 1:3) - B(i,:), 2, 2) < A(nears, 4);

        if sum(mask) > 0
            C(i) = true;
        else
            C(i) = false;
        end 
    end

end 

这可以将时间减少到1/2或1/3,这是可以接受的,并且如果我将mn分成批处理,则可能会更快,而不会增加内存负担。 @CrisLuengo提到了R * -tree方法,但是似乎XD的实现非常复杂

1 个答案:

答案 0 :(得分:3)

这使用implicit expansion计算点与球心之间的所有距离,然后将其与球半径进行比较:

select (multiple: true)

这可能比循环方法要快,但也要占用更多的内存,因为要计算一个中间UserTaxonomy×nested_form×C = any(vecnorm(permute(B, [1 3 2]) - permute(A(:,1:3), [3 1 2]), 2, 3) < A(:,4).', 2); 数组。