应用向量化技术来加速性能的一个3 d矩阵除以一个二维矩阵

5视图(30天)
我正在删除一个for循环在我的Matlab代码来提高性能。我原来的代码有一个for循环( 从j = 1: Nx )有害性能(在我生产代码,这for循环处理超过2000万次,如果我测试大型模拟)。我很好奇如果我可以删除这个for循环通过向量化,repmat,或类似的技术。我原来的Matlab实现如下所示。
clc;清晰的所有;
%测试数据
%我想删除j的for循环下面的代码
N = 10;
M = 10;
Nx = 32;%纽约= Nx =新西兰
新西兰= 32;
纽约= 32;
Fnmhat =兰德(Nx,新西兰+ 1);
Jnmhat =兰德(Nx, 1);
xi_n_m_hat =兰德(Nx、N + 1 M + 1);
Uhat = 0 (Nx,新西兰+ 1);
Uhat_2 = 0 (Nx,新西兰+ 1);
identy =眼睛(纽约纽约+ 1 + 1);
p =兰德(Nx, 1);
gammap =兰德(Nx, 1);
D =兰德(纽约Nx + 1 + 1);
D2 =兰德(纽约Nx + 1 + 1);
D_start = D (1);
D_end = D(最终:);
γ= 1.5;
α= 0;%这可能是零
ntests = 100;
%原始代码转换成矢量图(部分)
抽搐
n = 0: n
m = 0: m
b = Fnmhat。”;
alphaalpha = 1.0;
betabeta = 0.0;%这可能是零
gammagamma =γ*γ- p。^ 2 - 2 *α。* p;%的大小(Nx, 1)
d_min = 1.0;
n_min = 0.0;%这可能是零
r_min = xi_n_m_hat (:, n + 1, + 1);
d_max = 1我。* gammap;
n_max = 1.0;
r_max = Jnmhat;
一个= alphaalpha * D2 + betabeta * D +交换(gammagamma (3,2,1))。* identy;
(:,:)= repmat (n_min * D_end, [1, 1, Nx]);
b(结束:)= r_min;
(,,,)=(结束、结束:)+ d_min;
(1::)= repmat (n_max * D_start, [1, 1, Nx]);
一(1 1:)=(1 1:)+交换(d_max [2、3、1]);
:b (1) = r_max;
% Non-vectorized代码——这部分可以向量化?
j = 1: Nx
utilde = linsolve ((:,:, j)、b (:, j));% \ b
Uhat (j) = utilde。';
结束
结束
结束
toc
这是我尝试vectorizing代码(j和删除for循环)。
%与原始代码相同的测试数据
%的新代码(完全矢量化但不正确的)
抽搐
n = 0: n
m = 0: m
b = Fnmhat。”;
alphaalpha = 1.0;
betabeta = 0.0;%这可能是零
gammagamma =γ*γ- p。^ 2 - 2 *α。* p;%的大小(Nx, 1)
d_min = 1.0;
n_min = 0.0;%这可能是零
r_min = xi_n_m_hat (:, n + 1, + 1);
d_max = 1我。* gammap;
n_max = 1.0;
r_max = Jnmhat;
A2 = alphaalpha * D2 + betabeta * D +交换(gammagamma (3,2,1))。* identy;
A2 (:,:) = repmat (n_min * D_end, [1, 1, Nx]);
b(结束:)= r_min;
A2(结束、结束:)= A2(结束、结束:)+ d_min;
A2 (1::) = repmat (n_max * D_start, [1, 1, Nx]);
A2 (1 1:) = A2(1 1:) +交换(d_max [2、3、1]);
:b (1) = r_max;
% Non-vectorized代码——这部分可以向量化?
% j = 1: Nx
% utilde_2 = linsolve (A2 (:,:, j)、b (:, j));% A2 \ b
% Uhat_2 (j) = utilde_2。';
%结束
%我的尝试——这是行不通的,因为我不循环指数j
%在repmat
utilde_2 =挤压(repmat (linsolve (A2 (:,:, Nx)、b (:, Nx)), (1, 1, Nx)));
utilde_2 = utilde_2 (: 1);
Uhat_2 =挤压(repmat (utilde_2”, [1, 1, Nx]));
Uhat_2 = Uhat_2 ';
结束
结束
toc
diff =规范(Uhat——Uhat_2 inf);如果正确% = 0
我很好奇如果repmat(或另一个安装在内部的Matlab函数)可以加快的这部分代码:
j = 1: Nx
utilde = linsolve ((:,:, j)、b (:, j));% \ b
Uhat (j) = utilde。';
结束
是j绝对必要的for循环或可以删除吗?

接受的答案

布鲁诺陈德良
布鲁诺陈德良 2021年7月29日
9日评论
马修凯赫
马修凯赫 2021年7月31日
我认为可以优化MMX如果A和B都不复杂的双打。在我数据,B不是复杂的双所以可以加快MMX计算。这是我如何实现三种不同的方法在我真正的Matlab代码。
%这些参数模拟真实数据在我的代码
m = 33;
n = 33;
p = 1;
q = 32;
ntests = 10000;
%我的代码计算交流和Br之前进入循环
Ac =兰特(m, n, q) + 1我*兰德(m, n, q);%的是一个复杂的两倍大小(33岁,33岁,32)
Br =兰德(m, q);% B是一个(真正的)两倍大小(33岁,32)
%在我决定使用一个for循环/ mmx / MultipleQRSolve我的代码
%“理解”,是一个复杂的两倍大小(33岁,33岁,32)和B是A
%(真实)的大小(33岁,32)的两倍。我不需要计算里面A或B是什么
% for循环。我只是重塑B在MMX和MultipleQRSolve因为我
%为划分操作。
%的是我将如何在“真正的”写下面的三个函数代码。
%循环
抽搐
2 = 1:ntests
z1 = 0 (q,米);
j = 1:问
%这目前是我的代码如何计算\ b
utilde = linsolve (Ac (:,:, j), Br (:, j));% \ b
z1 (j) = utilde。';
结束
结束
toc%运行时间是14.231135秒。
% mmx
抽搐
2 = 1:ntests
Bnew =重塑(Br, m, 1, q);%让Br大小(33岁,1,32)应用MMX
基于“增大化现实”技术=实际(Ac);
Ai =图像放大(Ac);
Br =实际(Bnew);
Bi =图像放大(Bnew);% 0 b是一个真正的双
% z_1 = Ar + Ai *我
% z_2 = Br + Bi *我
% z_1 / z_2 = [(Ar * Br +人工智能(Bi) + 1我* Br - Ar (Ai * * Bi)] / (Br Bi ^ ^ 2 + 2);
%因为Bi = = 0,这是简化
% z_1 / z_2 = [(Ar * Br) + 1我* (Ai * Br)] / (Br ^ 2);
%我认为这使得下面的代码
% AA =[基于“增大化现实”技术,人工智能,人工智能,基于“增大化现实”技术);
% BB = (Br, Bi);
% zz = mmx(反斜杠,AA、BB);
% z2 = zz (1: n,::) + 1我* zz (n + 1:,::);
%到更快的版本
Num = mmx (“乘”基于“增大化现实”技术,Br);
我* mmx Num = Num + 1 (“乘”人工智能,Br);
穴= Br。^ 2;
z2 = mmx (“反斜杠”,Num穴);
z2 =排列(z2, [3 1 2]);
结束
toc%运行时间是2.441799秒。
% MultipleQRSolve
抽搐
2 = 1:ntests
Bnew_2 =重塑(Br, m, 1, q);%让Br大小(33岁,1,32)应用MultipleQRSolve
z3 = MultipleQRSolve (Ac, Bnew_2);
z3 =排列(z3 [3 1 2]);
结束
toc%运行时间是25.991396秒。
diff =规范(z1-z2、正);%不为零自从我代码z_1 / z_2不是正确的。
diff2 =规范(z1-z3、正);
如果代码为
AA =[基于“增大化现实”技术,人工智能,人工智能,基于“增大化现实”技术);
BB = (Br, Bi);
zz = mmx (“反斜杠”、AA、BB);
z2 = zz (1: n,::) + 1我* zz (n + 1:,::);
不需要(如B不是一个复杂的两倍)那么MMX“击败”for循环。感谢你所有的帮助这个问题(写作和MultipleQRSolve)。

登录置评。

更多的答案(2)

马特·J
马特·J 2021年7月29日
编辑:马特·J 2021年7月29日
另一个想法。
clc;清晰的所有;
%测试数据
%我想删除j的for循环下面的代码
N = 10;
M = 10;
Nx = 32;%纽约= Nx =新西兰
新西兰= 32;
纽约= 32;
AA = kron (speye (Nx), (Nx + 1));
地图=逻辑(AA);
%原始代码转换成矢量图(部分)
抽搐
n = 0: n
m = 0: m
%向量化代码
AA(地图)= (:);
Uhat =重塑(AA \ b (:), Nx + 1, Nx)。”;
结束
结束
toc
5个评论
马特·J
马特·J 2021年7月29日
是的,我没有看到 一个 是复数。所以,
AA(地图)= rehape ([], 1);
Uhat =重塑(AA \ b (:), Nx + 1, Nx)。”;

登录置评。


马特·J
马特·J 2021年7月29日
编辑:马特·J 2021年7月29日
在GPU(即如果A和b是gpuArrays), for循环可以删除:
Uhat =排列(pagefun (@mldivide,重塑(b, [], 1, Nx)), (2, 1, 3));
1评论
马修凯赫
马修凯赫 2021年7月29日
这种方法需要并行计算工具。我将调查这个工具箱。有另一种方法,不需要一个单独的工具箱?

登录置评。

类别

找到更多的在特殊功能帮助中心文件交换

s manbetx 845


释放

R2020a

社区寻宝

找到宝藏在MATLAB中央,发现社区如何帮助你!

开始狩猎!