加载 netcdf 数据时 matlab 代码变慢

问题描述 投票:0回答:1

代码

我必须绘制一些大小为

1080*171*52*120
(经度、纬度、深度、时间)的大型 netcdf 文件中包含的数据。我的策略是在第一个维度中按 12 个块加载数据,在第四个维度中按 36 个块加载数据(请参阅末尾的script)。

所以,我在 12 个空间块上有一个

for
循环,它包含一个在 36 个时间块上的
for
循环。在时间块的每次迭代中,我将所需的信息存储在矩阵
V
中,然后进行绘图。

问题:

几次迭代后,代码的速度似乎变慢了。它发生在哪次迭代不是恒定的......通常是 5 或 8。减速似乎不是由于内存问题,因为在第一次迭代后分配的内存是恒定的。问题似乎是由于数据加载(via

ncread
)。但是,我上传的数据大小对于所有迭代都是恒定的......

这里是

memory
在减速之前的输出 以及加载文件所用的时间:

最大可能的数组:23186 MB(2.431e+10 字节)* 内存 适用于所有阵列:23186 MB(2.431e+10 字节)* 内存 MATLAB 使用:1226 MB(1.286e+09 字节)物理内存 (RAM): 16296 MB (1.709e+10 bytes)

  • 受可用系统内存(物理+交换文件)限制。经过的时间是0.384304秒。

这里是相同的输出减速后

最大可能的数组:23186 MB(2.431e+10 字节) * 所有阵列可用的内存:23186 MB(2.431e+10 字节) * MATLAB 使用的内存:1226 MB(1.286e+09 字节)物理内存(RAM):16296 MB(1.709e+10 字节)

  • 受可用系统内存(物理+交换文件)限制。经过的时间是26.155781秒。

进一步混淆...

每个时间块由5个时间点组成。这些时间点的索引以 5 x 5 的比例存储在具有 120/5 元素的元胞数组 (

new_inds
) 的每个元胞中。 但是,如果我将此元胞数组的长度限制为 8(或 8*5 个时间点),代码不会变慢。

事实上,最后一个案例中的加载时间在整个执行过程中实际上是恒定的:

最大可能的数组:23068 MB(2.419e+10 字节)* 内存 适用于所有阵列:23068 MB(2.419e+10 字节)* 内存 MATLAB 使用:1231 MB(1.291e+09 字节)物理内存 (RAM): 16296 MB (1.709e+10 bytes)

  • 受可用系统内存(物理+交换文件)限制。经过的时间是0.390843秒。

请注意,在最后一种情况下,要上传的块的大小与以前相同。所以,即使我显然希望代码整体运行得更快(因为总共有更少的时间点),我也不明白为什么在最后一种情况下加载效果很好。

问题:

两种情况之间唯一不同的是包含时间索引的元胞数组的长度。但我真的怀疑这可能是速度变慢的原因......也是因为在第一种情况下,matlab 在迭代次数不固定后变得懒惰。

有人能明白其中的原因吗?

脚本:

TT=length(new_inds);%how many time steps to average at each iteration

%%%plotting by chunk
figure;hold on

for kkk=1:numel(chunks)-1   %iteration on space
V=0;   %matrix to update after each iteration on time    

for ttt=1:TT   %iteration on time

fprintf(['LOADING -',num2str(ttt),'/',num2str(TT),'- STARTED!\r'])

s=chunks(kkk+1)-chunks(kkk) %size in space of the current chunk
t=new_inds{ttt}(end)-new_inds{ttt}(1)+1  %size in time of the current chunk
memory 
tic 
%load the velocitites on the current chunk
Uvel=ncread(uvelnc,'Uvel',[chunks(kkk) 1 1 new_inds{ttt}(1)],...
    [chunks(kkk+1)-chunks(kkk)+2 y2 Inf new_inds{ttt}(end)-new_inds{ttt}(1)+1]);

Vvel=ncread(vvelnc,'Vvel',[chunks(kkk) 1 1 new_inds{ttt}(1)],...
    [chunks(kkk+1)-chunks(kkk)+2 y2 Inf new_inds{ttt}(end)-new_inds{ttt}(1)+1]);

Uvel(Uvel==-9999)=NaN;
Vvel(Vvel==-9999)=NaN;
toc

fprintf(['LOADING -',num2str(ttt),'/',num2str(TT),'- DONE!\r'])


%%%velocity module
Uvel= nansum(Uvel,4);
Vvel= nansum(Vvel,4);

[Xv,Yv,Zv]=ndgrid(lonMv(chunks(kkk):chunks(kkk+1)-1+2),latMv(1,:),uv_levs);
[Xu,Yu,Zu]=ndgrid(lonMu(chunks(kkk):chunks(kkk+1)-1+2),latMu(1,:),uv_levs);
Vvel=interpn(Xv,Yv,Zv,Vvel,Xu,Yu,Zu,'linear',NaN);

V = V + sqrt(Uvel.^2+Vvel.^2); %update the matrix V
end %of the iteration on time


V_t=V/sum(cellfun('length',new_inds)); %average V on time

%%%plotting
V_t=V_t(:,:,1); %surface values

lonP=lonMu(chunks(kkk):chunks(kkk+1)-1+2,:);
lonP(V_t==0)=NaN;
latP=latMu(chunks(kkk):chunks(kkk+1)-1+2,:);
m_pcolor(lonP,latP,V_t); 

end %iteration on space
matlab netcdf
1个回答
1
投票

使用低级函数

netcdf.getVar
可能有帮助

© www.soinside.com 2019 - 2024. All rights reserved.