向量化矩阵的列式逻辑索引

时间:2018-11-01 03:16:42

标签: arrays matlab matrix indexing

我正在MATLAB中对矩阵进行列式逻辑索引。一个例子是:

tic

N = 5*10^6;
input = randi(100,N,12);
output = zeros(N,1);

d_sn2 = randi(25,N,12);
d_sd2 = randi(25,N,12);

LL1 = randi(8,N,12);
UL1 = randi([12,20],N,12);

LL2 = randi(8,N,12);
UL2 = randi([12,20],N,12);

for p = 1:N
    temp = zeros(12,12);
    for i = 1:12
        I2 = (d_sn2(:,i)>LL1(p,i) & d_sn2(:,i)<UL1(p,i)) & (d_sd2(:,i)>LL2(p,i) & d_sd2(:,i)<UL2(p,i));
        temp(i,:) = mean(input(I2,:));
    end
    output(p) = max(temp(:));
end

toc               

我想知道是否可以向量化此操作或使速度更快?

1 个答案:

答案 0 :(得分:1)

内部循环中I2的计算可以很容易地向量化。这个:

temp = zeros(12,12);
for i = 1:12
   I2 = (d_sn2(:,i)>LL1(p,i) & d_sn2(:,i)<UL1(p,i)) & (d_sd2(:,i)>LL2(p,i) & d_sd2(:,i)<UL2(p,i));
   temp(i,:) = mean(input(I2,:));
end

与此相同:

I2 = d_sn2>LL1(p,:) & d_sn2<UL1(p,:) & d_sd2>LL2(p,:) & d_sd2<UL2(p,:);
temp = zeros(12,12);
for i = 1:12
   temp(i,:) = mean(input(I2(:,i),:));
end

此代码使用隐式单例扩展,如果您具有R2016b之前的MATLAB版本,则需要分别编写>gt)和<({{1} })使用ltbsxfun等进行呼叫

不幸的是,对bsxfun(@gt,d_sn2,LL1(p,:))的索引很难向量化。因为input的每次迭代都会访问i的不同数量的元素,所以没有简单的方法来创建没有循环的矩阵input。我尝试过的几种方法都比循环代码慢得多。

如果您使用的是最新版本的MATLAB,您的代码将非常高效。 MATLAB的解释器使用JIT(即时编译器)使循环的速度不再像以前那样慢。例如,与使用函数temp相比,添加矩阵的所有元素的琐碎循环的差异仅慢2-3倍。在过去,这可能慢了100倍。因此,矢量化的好处与以往不同。再加上您正在使用的非常大的数组,这意味着矢量化将是一种悲观化,因为矢量化通常意味着需要创建更大的中间矩阵。