Matlab 从一系列产品创建矩阵的快速高效方法
Ax,Ay,Az:[N-by-N] B=AA(并矢乘积) 这意味着:Matlab 从一系列产品创建矩阵的快速高效方法,matlab,performance,matrix,large-data,Matlab,Performance,Matrix,Large Data,Ax,Ay,Az:[N-by-N] B=AA(并矢乘积) 这意味着: B(i,j)= [Ax(i,j);Ay(i,j);Az(i,j)]*[Ax(i,j) Ay(i,j) Az(i,j)] B(i,j):一个3x3矩阵。 构造B的一种方法是: N=2; Ax=rand(N); Ay=rand(N); Az=rand(N); %# [N-by-N] t=1; F=zeros(3,3,N^2); for i=1:N for j=1:N F(:,:,t)= [Ax(
B(i,j)= [Ax(i,j);Ay(i,j);Az(i,j)]*[Ax(i,j) Ay(i,j) Az(i,j)]
B(i,j):一个3x3矩阵。
构造B的一种方法是:
N=2;
Ax=rand(N); Ay=rand(N); Az=rand(N); %# [N-by-N]
t=1;
F=zeros(3,3,N^2);
for i=1:N
for j=1:N
F(:,:,t)= [Ax(i,j);Ay(i,j);Az(i,j)]*[Ax(i,j) Ay(i,j) Az(i,j)];
t=t+1; %# t is just a counter
end
end
%# then we can write
B = mat2cell(F,3,3,ones(N^2,1));
B = reshape(B,N,N)';
B = cell2mat(B);
当N很大时,有没有更快的方法
编辑:
谢谢你的回答。(更快)
让我们把:
N=2;
Ax=[12;34];Ay=[56;78];Az=[9 10;11 12]
B =
1 5 9 4 12 20
5 25 45 12 36 60
9 45 81 20 60 100
9 21 33 16 32 48
21 49 77 32 64 96
33 77 121 48 96 144
运行:??? 使用==>mtimes时出错 内部矩阵尺寸必须一致 如果我写:
p=Ai*Aj代码>然后
B =
7 19 31 15 43 71
23 67 111 31 91 151
39 115 191 47 139 231
10 22 34 22 50 78
34 78 122 46 106 166
58 134 210 70 162 254
那与上面不同
从[Ax(1,1)Ay(1,1)Az(1,1)]
编辑:
编辑:
在对我的应用程序进行一些修改后:
按gnovice代码
1st code : 19.303310 seconds
2nd code: 23.128920 seconds
3rd code: 13.363585 seconds
似乎任何函数调用,如ceil、ind2sub。。。尽可能使环变慢并避免
syindex
很有趣!谢谢。这里有一个相当简单和通用的实现,它使用单个for循环执行,避免处理三维变量或重塑:
A = cat(3, Ax, Ay, Az); % [N-by-N-by-3]
F = zeros(3, 3, N^2);
for i = 1:3,
for j = 1:3,
Ai = A(:,:,i);
Aj = A(:,:,j);
P = Ai(:) .* Aj(:);
F(i,j,:) = reshape(P, [1, 1, N^2]);
end
end
%# then we can write
B = mat2cell(F,3,3,ones(N^2,1));
B = reshape(B,N,N)';
B = cell2mat(B);
%# General solution:
%# ----------------
B = cell(N);
for index = 1:N^2
A = [Ax(index) Ay(index) Az(index)];
B{index} = A(:)*A;
end
B = cell2mat(B);
编辑#1:
为了回答如何减少对称矩阵B
计算次数的附加问题,您可以使用上述代码的以下修改版本:
%# Symmetric solution #1:
%# ---------------------
B = cell(N);
for index = find(tril(ones(N))).' %'# Loop over the lower triangular part of B
A = [Ax(index) Ay(index) Az(index)];
B{index} = A(:)*A;
symIndex = N*rem(index-1,N)+ceil(index/N); %# Find the linear index for the
%# symmetric element
if symIndex ~= index %# If we're not on the main diagonal
B{symIndex} = B{index}; %# then copy the symmetric element
end
end
B = cell2mat(B);
但是,在这种情况下,通过前面的线性索引和使用两个带有下标索引的for循环,您可能会获得更好的性能(或者至少是看起来更简单的代码),如下所示:
%# Symmetric solution #2:
%# ---------------------
B = cell(N);
for c = 1:N %# Loop over the columns
for r = c:N %# Loop over a subset of the rows
A = [Ax(r,c) Ay(r,c) Az(r,c)];
B{r,c} = A(:)*A;
if r ~= c %# If we're not on the main diagonal
B{c,r} = B{r,c}; %# then copy the symmetric element
end
end
end
B = cell2mat(B);
编辑#2:
第二个对称解决方案可以通过将对角线计算移到内部循环之外(不需要条件语句)并用结果覆盖a(:)*a
来进一步加快速度,这样我们就可以使用a
而不是B{r,c}来更新对称单元格条目B{c,r}
(即用一个单元格的内容更新另一个单元格似乎会带来一些额外的开销):
下面是使用以下样本对称矩阵的3个对称解的计时结果Ax
,Ay
和Az
:
N = 400;
Ax = tril(rand(N)); %# Lower triangular matrix
Ax = Ax+triu(Ax.',1); %'# Add transpose to fill upper triangle
Ay = tril(rand(N)); %# Lower triangular matrix
Ay = Ay+triu(Ay.',1); %'# Add transpose to fill upper triangle
Az = tril(rand(N)); %# Lower triangular matrix
Az = Az+triu(Az.',1); %'# Add transpose to fill upper triangle
%# Timing results:
%# --------------
%# Solution #1 = 0.779415 seconds
%# Solution #2 = 0.704830 seconds
%# Solution #3 = 0.325920 seconds
解决方案3的大速度主要是由于使用局部变量A
更新B
的单元格内容,而不是使用另一个单元格的内容更新一个单元格。换句话说,用B{c,r}=B{r,c}代码>带来的开销比我预期的要多。p=Ai(:)*Aj(:)代码>-->P=Ai*Aj代码>?@user784433:已修复。它应该是元素相乘,产生一个[N^2,1,1]
向量。谢谢。非常感谢你。这太棒了!在线性索引中,我们是否可以对算法说,当B对称时,只计算矩阵的一半?
%# Symmetric solution #3:
%# ---------------------
B = cell(N);
for c = 1:N %# Loop over the columns
A = [Ax(c,c) Ay(c,c) Az(c,c)];
B{c,c} = A(:)*A;
for r = c+1:N %# Loop over a subset of the rows
A = [Ax(r,c) Ay(r,c) Az(r,c)];
A = A(:)*A;
B{r,c} = A;
B{c,r} = A;
end
end
B = cell2mat(B);
N = 400;
Ax = tril(rand(N)); %# Lower triangular matrix
Ax = Ax+triu(Ax.',1); %'# Add transpose to fill upper triangle
Ay = tril(rand(N)); %# Lower triangular matrix
Ay = Ay+triu(Ay.',1); %'# Add transpose to fill upper triangle
Az = tril(rand(N)); %# Lower triangular matrix
Az = Az+triu(Az.',1); %'# Add transpose to fill upper triangle
%# Timing results:
%# --------------
%# Solution #1 = 0.779415 seconds
%# Solution #2 = 0.704830 seconds
%# Solution #3 = 0.325920 seconds