我在Matlab的Profiler中运行了以下代码,对我来说这是非常必要的,因为我认为这是一个不必要的for循环。
我有2个矩阵G和source_data。 G中的每一列都将确定我需要从source_data中获取的行,并将它们放在一起。
我正在使用以下代码
创建G和source_datafor i=1:10
source_data(i,:)=rand(1,20)<.8;
end
for i=1:15
G(:,i)=rand(10,1)<.9;
end
我正在使用下面的for循环执行xor操作:
z=1;
while(i<=15)
for j=1:10
if(G(j,i)==1)
intersum(z+1,:)=xor(intersum(z,:), source_data(j,:));
z=z+1;
end
end
C(i,:)=intersum(z,:);
i=i+1;
end
有没有办法对这段代码进行矢量化?时间滞后对于小矩阵是可接受的,但对于大矩阵,这个代码非常有效。
谢谢,
Bhavya
答案 0 :(得分:1)
假设:
这是您的代码的矢量化形式,它产生与原始代码完全相同的结果:
function C = version_a()
source_data = rand(10,20)<.8;
G = rand(10,15)<.9;
intersum = zeros(1, size(source_data,2));
z = 1;
i = 1;
while i <= 15
for j=1:10
if(G(j,i)==1)
intersum(z+1,:)=xor(intersum(z,:), source_data(j,:));
z=z+1;
end
end
C(i,:)=intersum(z,:);
i=i+1;
end
ret = C;
end
function C = version_b()
source_data = rand(10,20)<.8; % Can initialize in a single call
G = rand(10,15)<.9; % Same here
C = zeros(size(G,2),size(source_data,2));
C(1,:) = mod(sum(source_data(G(:,1),:)),2);
for i = 2:15
C(i,:) = mod(C(i-1,:) + sum(source_data(G(:,i),:)),2);
end
end
为了检查两个版本的时间,我使用了这个测试功能:
function ret = xor_test()
ret = 0;
seed = 123456789;
laps = 10000;
tic
for i = 1:laps
RandStream.getDefaultStream.reset(seed);
a = version_a();
end
toc
tic
for i = 1:laps
RandStream.getDefaultStream.reset(seed);
b = version_b();
end
toc
ret = ret + sum(sum(b ~= a));
end
我的机器上有以下时间:
Elapsed time is 13.537738 seconds.
Elapsed time is 2.302747 seconds.
ans =
0
现在为什么我这样改变了......
xor
数组上的logical
操作几乎检查总和的奇偶校验(将true
值视为1)。此外,intersum
被用作累加器,所以有人的值最终会在C
中结束,所以我们完全跳过它。取G(j,i)
为1的行可以通过logical indexing完成。
最后,即使您不喜欢此建议版本,我也建议您预先分配您的C
和intersum
向量(如果您还没有这样做)。这对我来说有很大的不同。