如何解决在对大型矩阵执行操作时避免在内存中存储额外数组的方法?
我正在编写一个 Matlab 脚本,该脚本对 3D 矩阵进行计算(实际代码是迭代一个字段以在 3D 空间中随时间求解微分方程)。有很多函数,但我在下面包含了一个简单的例子来说明问题。
代码在内存中存储变量 A
、K
和 B
。存储这些是不可避免的,所以没关系。函数 calculate_E_values()
然后根据这三个矩阵计算一些值:
A = complex( rand(64,64,'double') );
K = rand(64,'double');
B = rand(64,'double');
[E1,E,E32] = calculate_E_values(A,K,B);
function [E1,E2,E3] = calculate_E_values(A,B)
A_sq = abs(A).^2;
A_hat = fftn( ifftshift(A) );
L_hat = -K.*A_hat;
L = fftshift( ifftn(L_hat) );
% Calculate E1
E1I = -1/2 * real( conj(A).*L );
E1 = sum(sum(sum( E1I )));
% Calculate E2
E2I = B.*A_sq;
E2 = sum(sum(sum( E2I )));
% Calculate E3
E3I = -1/2 * real( conj(A).*L ) + ( B + A_sq ).*A_sq;
E3 = sum(sum(sum( E3I )));
end
现在,当输入函数 calculate_E_values()
时问题就来了。由于我已经分配了临时变量,因此在退出此函数并返回主脚本之前的工作区如下所示:
可以看出已经创建了许多额外的数组。在我的实际代码中,我想要使用更大的数组(例如 512 x 512 x 512),然后这些额外的副本会导致“内存不足”错误。
我的问题是:是否有更好的结构/风格可以避免这种情况?
我的想法:
E1 = sum(sum(sum( -1/2 * real( conj(A).*fftshift( ifftn(-K.*fftn( ifftshift(A) )) ) ) )));
(另外,例如 A_sq 被使用了两次,所以把它放在一行会增加执行时间)。
- 我可以分配一个临时变量
TMP
,并继续覆盖它 - 但同样,这会严重影响可读性。我还需要存储TMP
本身。例如,
TMP = fftn( ifftshift(A) );
TMP = -K.*TMP;
TMP = fftshift( ifftn(TMP) );
TMP = -1/2 * real( conj(A).*TMP );
E1 = sum(sum(sum( TMP )));
- 我想如果我可以将变量名用作某种引用而不实际存储变量会更好吗?
谢谢!
解决方法
人们可能对如何实现这一点有不同的看法,但他们都会同意覆盖中间变量。我会这样做:
function [E1,E2,E3] = calculate_E_values(A,K,B)
A_sq = abs(A).^2;
L = fftn(ifftshift(A)); % = A_hat
L = -K.*L; % = L_hat
L = fftshift(ifftn(L));
E1 = -1/2 * real( conj(A).*L );
E1 = sum(sum(sum( E1 )));
E2 = B.*A_sq;
E2 = sum(sum(sum( E2 )));
E3 = -1/2 * real( conj(A).*L ) + ( B + A_sq ).*A_sq;
E3 = sum(sum(sum( E3 )));
end
你也可以这样做,虽然它不那么可读:
L = fftshift(ifftn(...
-K.*...
fftn(ifftshift(A))));
您也可以在不再需要时使用 clear L_hat
,但是在函数中使用 clear
会显着减慢它的速度,不推荐这样做。
与您的问题无关:您应该使用 sum(E1(:))
而不是 sum(sum(sum(E3)))
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。