Pla*_*god 2 indexing optimization matlab for-loop vectorization
我有两个数组:
timesteps = [1,3;5,7;9,10];
data = [1,2,3,4,5,6,7,8,9,10];
Run Code Online (Sandbox Code Playgroud)
timesteps数组中的值描述了data我想要的值。第一列开始,第二列结束。
例如我在这里想得到[1,2,3,5,6,7,9,10]。
所以这段代码对我来说很好用,但是由于for循环的缘故,它非常慢... Matlab中是否有一个内衬,所以我可以摆脱for循环?
newData=[];
for ind=1:size(timesteps,1)
newData=cat(2,newData,data(timesteps(ind,1):timesteps(ind,2)));
end
Run Code Online (Sandbox Code Playgroud)
编辑:通过Wolfie的解决方案,我得到了以下(非常好的)结果。(我只使用了一个小数据集,通常是大数据集的50倍。)
(Mine) Elapsed time is 48.579997 seconds.
(Wolfies) Elapsed time is 0.058733 seconds.
Run Code Online (Sandbox Code Playgroud)
Irreducible的答案使用str2num并sprintf在数字和char数据之间切换以创建索引...(在我的测试中)这对循环性能不佳(在我的测试中),就像您对小型数组所做的那样,但是对于大型数组,由于处理了内存分配,因此执行起来更快更好。
您可以通过预分配输出并对其进行索引来避免循环中的连接,从而提高性能。对于大型阵列,这可以大大提高速度。
N = [0; cumsum( diff( timesteps, [], 2 ) + 1 )];
newData = NaN( 1, max(N) );
for ind = 1:size(timesteps,1)
newData(N(ind)+1:N(ind+1)) = data(timesteps(ind,1):timesteps(ind,2));
end
Run Code Online (Sandbox Code Playgroud)
下面的基准测试显示了如何始终保持更快的速度。
dataindex的行数比少4倍data。标杆图
注意,这是可变的,取决于所使用的索引。在下面的代码中,我每次运行都会随机生成索引,因此您可能会看到绘图略有跳跃。
但是,具有预分配的循环始终较快,而没有预分配的循环始终呈指数级增长。
基准测试代码
T = [];
p = 4:12;
for ii = p
n = 2^ii;
k = 2^(ii-2);
timesteps = reshape( sort( randperm( n, k*2 ) ).', 2, [] ).';
data = 1:n;
f_Playergod = @() f1(timesteps, data);
f_Irreducible = @() f2(timesteps, data);
f_Wolfie = @() f3(timesteps, data);
T = [T; [timeit( f_Playergod ), timeit( f_Irreducible ), timeit( f_Wolfie )]];
end
figure(1); clf;
plot( T, 'LineWidth', 1.5 );
legend( {'Loop, no preallocation', 'str2num indexing', 'loop, with preallocation'}, 'location', 'best' );
xticklabels( 2.^p ); grid on;
function newData = f1( timesteps, data )
newData=[];
for ind=1:size(timesteps,1)
newData=cat(2,newData,data(timesteps(ind,1):timesteps(ind,2)));
end
end
function newData = f2( timesteps, data )
newData = data( str2num(sprintf('%d:%d ',timesteps')) );
end
function newData = f3( timesteps, data )
N = [0; cumsum( diff( timesteps, [], 2 ) + 1 )];
newData = NaN( 1, max(N) );
for ind = 1:size(timesteps,1)
newData(N(ind)+1:N(ind+1)) = data(timesteps(ind,1):timesteps(ind,2));
end
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
71 次 |
| 最近记录: |