这里的所有技巧都是关于 MATLAB 中使用的线性索引。我们创建偏移线性索引时牢记最终输出的大小。首先,将创建偏移索引以索引到A 的一个 3D 切片,然后索引到整个 3D 数组。它们在代码中分别命名为offset2D 和offset3D。最后,我们添加从m 和n 获得的线性索引。
假设您将m 和n 索引保存到两个单独的一维数组中,例如m_arr 和n_arr,您将获得带有bsxfun 的最终矢量化实现,就像这样 -
%// Say you have the m,n arrays are created like this -
m_arr = round(rand(30,1)*32)+1;
n_arr = round(rand(30,1)*32)+1;
%// Get linear indices with m,n
mn_arr = (n_arr-1)*size(A,1) + m_arr;
%// Calculate offset indices for 2D and then 3D versions
offset2D = bsxfun(@plus,[0:27]',[0:27]*size(A,1)); %//'
offset3D = bsxfun(@plus,offset2D(:),[0:30-1]*numel(A(:,:,1)));
%// Incorporate m,n indices into offset to get final linear indices to index into A
lidx = bsxfun(@plus,mn_arr(:).',offset3D); %//'
%// Initialize output array and then index into A to values from a
A = zeros(60,60,30);
A(lidx) = a;
对于未来的读者,这里是 for 循环和矢量化代码的参数化版本 -
%// Parameters
M = 4;
D = 3;
mx = 3;
%// For-loop code
A = zeros(M+mx,M+mx,D);
a = rand(M,M,D);
m_arr = round(rand(D,1)*mx)+1;
n_arr = round(rand(D,1)*mx)+1;
for i=1:D
m = m_arr(i);
n = n_arr(i);
A(m:m+M-1,n:n+M-1,i) = a(:,:,i);
end
%// Vectorized code
mn_arr = (n_arr-1)*size(A,1) + m_arr;
offset2D = bsxfun(@plus,[0:M-1]',[0:M-1]*size(A,1)); %//'
offset3D = bsxfun(@plus,offset2D(:),[0:D-1]*numel(A(:,:,1)));
lidx = bsxfun(@plus,mn_arr(:).',offset3D); %//'
A_vectorized = zeros(M+mx,M+mx,D);
A_vectorized(lidx) = a;
最后,让我们比较一下循环代码和矢量化代码的输出 -
>> max(abs(A(:)-A_vectorized(:)))
ans =
0