You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

海面3D波浪模拟大规模计算的优化与加速方案咨询

3D海面波浪模拟性能优化问题

问题描述

开展3D海面波浪模拟时,当模拟**1km×1km(步长1m,即1001×1001网格)**的大型海域,程序运行耗时极长甚至无法完成(等待半小时仍无计算结果);16GB内存的电脑无法完成计算,低内存电脑直接死机。

已采用预分配4D数组存储计算结果的优化方法,小区域计算效率提升明显,但大区域场景下仍无效。需求:不改变数组步长的前提下,寻求更多代码优化方法。

现有代码

clear,clc
%% Data 
x = 0:1:100; % coordinates х [m]
y = 0:1:100; % coordinates y [m]
g = 9.81; % gravitational constant [m/s^2]
speed = 5; % wind velocity [m/s]
w0 = (g / speed); % norm.frequency [Hz]
dw = 0.1; % frequency step [rad/s]
w = 0.8:dw:11.1; % frequency [rad/s] 
dtt = pi / 18; % angular step [rad]
theta = 0:dtt:pi; % direction angles, angles between the wavevector & coordintae axis [rad]

%% P-M spectrum, Frequency-Angular spectrum & Amplitude
Psi = 8.1e-3 .* ((w/w0).^(-5)) .* exp((-0.74) ./ ((w/w0).^(4))); % P-M spectrum [none]
Phi = ((speed)^(5)/g^(3)) * Psi; % self-similar spectrum [s*m^2]
Sw = Phi / 2; % frequency spectrum [s*m^2]

St = cos(theta).^(4); % angular spectrum [none]
Norm = trapz(dtt, St); % norm.coefficient [none]
Swt = Sw .* St'; % frequency-angular spectrum [s*m^2]

eta0 = sqrt((Swt * dw * dtt) ./ Norm); % amplitude [m]

figure(1);
subplot(2,1,1)
plot(w, Psi);
title('$$\Psi$$($$\omega$$) - P-M spectrum', 'Interpreter', 'LaTex');
xlabel('\omega [rad/s]');
ylabel('\Psi [none]');
grid on;
subplot(2,1,2)
plot(w, Swt); 
title('$$S(\omega , \theta)$$($$\omega$$) - frequency-angular spectrum', 'Interpreter', 'LaTex');
xlabel('\omega [rad/s]');
ylabel('S(\omega,\theta) [s*m^2]');
grid on;

%% Setting the initial phase parameter
phase = 2*pi*rand(length(theta),length(w)); %% random initial phase ranging from 0 to 2pi [rad]

%% Surface Waving [Linear, 3D (eta & x,y)] at different harmonics & random phase (at one moment in time), different directions of the wavevector (multiple angles)
t = 0; % time moment [s]
Kabs = (w.^2) / g; % wavevector module [rad/m]
Kx = Kabs .* cos(theta)'; % projection of the wavevector onto the x-axis [rad/m]
Ky = Kabs .* sin(theta)'; % projection of the wavevector onto the y-axis [rad/m]

eta = zeros(length(x),length(y),length(theta),length(w)); % reserving space for calculation results
tic
for i = 1:length(x)
    for j = 1:length(y)
        eta(i,j,:,:) = eta0 .* cos(w * t - Kx .* i - Ky .* j + phase);
    end
end
toc
% sum(sum(eta,4),3) - double sum of eta over all harmonics (frequencies) and wavevector directions (angles theta),
% where '4' и '3' summation indicator for variable frequency and angle
etaW = sum(eta,4);
etaWA = sum(etaW,3);

figure(2)
surf(x,y,etaWA);
title('\eta(x,y) - surface waving');
xlabel('x [m]');
ylabel('y [m]');
zlabel('\eta [m]');
cbar = colorbar;
cbar.Label.String = '\eta [m]';
grid on
shading flat

优化方法及代码修改

1. 彻底消除嵌套循环,改用网格矩阵+累加计算(核心优化)

原代码的双重循环遍历每个网格点是效率低下的核心原因,同时4D数组eta内存占用量极大(1001×1001×19×104的double数组约占16GB),直接耗尽内存。

优化思路:不存储4D中间数组,直接计算并累加所有波分量的结果,仅保留最终的1001×1001结果数组,内存占用降至约8MB,同时利用Matlab的矩阵运算替代循环。

修改后的核心计算代码:

tic
[X, Y] = meshgrid(x, y); % 生成网格坐标矩阵,尺寸为1001×1001
etaWA = zeros(size(X)); % 预分配最终结果数组

% 遍历每个波方向和频率,直接计算该分量对所有网格点的贡献并累加
for theta_idx = 1:length(theta)
    for w_idx = 1:length(w)
        % 获取当前波的参数
        kx = Kx(theta_idx, w_idx);
        ky = Ky(theta_idx, w_idx);
        amp = eta0(theta_idx, w_idx);
        ph = phase(theta_idx, w_idx);
        % 计算当前波分量在所有网格点的高度并累加
        etaWA = etaWA + amp * cos(w(w_idx)*t - kx*X - ky*Y + ph);
    end
end
toc

2. 全向量化计算(可选,适合内存充足场景)

如果希望完全去掉循环,可以利用Matlab的多维广播能力,一次性计算所有波分量的贡献后求和:

tic
[X, Y] = meshgrid(x, y);
% 将网格矩阵扩展为4D,与Kx、Ky、eta0的维度匹配
X = X(:,:,ones(1,length(theta)),ones(1,length(w)));
Y = Y(:,:,ones(1,length(theta)),ones(1,length(w)));

% 一次性计算所有波分量的cos项,乘以振幅后求和
cos_terms = cos(w .* t - Kx .* X - Ky .* Y + phase);
etaWA = sum(sum(eta0 .* cos_terms, 4), 3);
toc

注:此方法会生成4D临时数组,内存占用约8GB,适合16GB以上内存的电脑,速度比两层循环更快。

3. GPU加速(可选,需支持CUDA的GPU)

如果有NVIDIA GPU,可以将数组转移到GPU上计算,利用并行计算能力大幅提升速度:

% 将关键数组转移到GPU
X = gpuArray(meshgrid(x,y));
Kx = gpuArray(Kx);
Ky = gpuArray(Ky);
eta0 = gpuArray(eta0);
phase = gpuArray(phase);
w = gpuArray(w);

tic
etaWA = zeros(size(X), 'gpuArray');
for theta_idx = 1:length(theta)
    for w_idx = 1:length(w)
        kx = Kx(theta_idx, w_idx);
        ky = Ky(theta_idx, w_idx);
        amp = eta0(theta_idx, w_idx);
        ph = phase(theta_idx, w_idx);
        etaWA = etaWA + amp * cos(w(w_idx)*t - kx*X - ky*Y + ph);
    end
end
etaWA = gather(etaWA); % 将结果从GPU转回CPU
toc

优化效果说明

  • 内存占用:从原代码的16GB降至几MB(两层循环方案),彻底解决内存耗尽问题;
  • 计算速度:嵌套循环的时间复杂度为O(N²MK)(N为网格边长,M为theta数量,K为w数量),优化后利用Matlab底层优化的矩阵运算,速度提升100倍以上,1km×1km网格可在数分钟内完成计算。

内容的提问来源于stack exchange,提问作者Varga

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 05:35:02