跳转到内容

MINC/工具/emma/emma-matlab 内存

来自维基教科书,开放的书籍,面向开放的世界

控制 MATLAB 内存使用

[编辑 | 编辑源代码]

MATLAB 是一个非常有用的工具,用于分析医学图像数据。不幸的是,它有一个明显的缺点:MATLAB 内存管理很糟糕。内存很容易变得碎片化,没有尝试进行压缩(除了几乎无用的 MATLABpack函数)。对于大型医学图像体积,结果可能是灾难性的,导致巨大的内存使用,性能低下,在极端情况下,操作系统会终止你的 MATLAB 进程。

控制 MATLAB 内存使用有点像变戏法。有一些通用的指导方针可以遵循,但没有适用于所有情况的硬性规定。以下是一些软性规则

  1. 尽可能重复使用内存。例如,EMMAgetimages函数允许你指定要使用的内存块。通常,这是包含图像的变量,并且应该与要加载的图像的大小相同
PET = getimages(h,8,1:21,PET);

将重复使用分配给矩阵 PET 的内存,并且不会为返回的图像分配新的内存。这消除了与重新加载一组图像相关的碎片化问题。

  1. 使用 EMMArescale函数将矩阵乘以标量。此函数不分配新的内存,而是使用已经分配给矩阵的内存。例如,MATLAB 指令
PET = PET .* 5;

将导致碎片化,因为矩阵 PET 将被复制。但是,指令

rescale (PET,5);

具有相同的效果,但不会导致碎片化。

  1. 初始化大型矩阵。当你想通过一系列操作来缓慢地填充矩阵时,这很有用。例如,如果你想在变量中创建一个 128x128 的图像,一行一行地创建Fake_PET,你应该指定
Fake_PET = zeros(128,128);

这将初始化矩阵为正确的大小,并用零填充。然后,当你用你的值填充矩阵时,它不会被复制,并且不会发生内存碎片化。

  1. 一次使用少量内存。这可能是 *最重要的规则*,并且可以潜在地解决所有内存使用问题。例如,当分析动态研究时,请考虑分解你的分析,以便它可以一次在一行(或几行)上执行,而不是在整个图像上执行。

例如,考虑 [emma1.html 基本 EMMA 图像操作] 教程中介绍的情况:我们想要生成一个集成图像体积。以下代码片段演示了错误的执行方式

h=openimage('/local/matlab/toolbox/emma/examples/yates_19445.mnc');
h2 = newimage('new.mnc',[0 15], ...
     '/local/matlab/toolbox/emma/examples/yates_19445.mnc');

ftimes = getimageinfo (h,'MidFrameTimes');

img = zeros (16384,1);

for j=1:15
   PET = getimages(h,j,1:21);
   img = ntrapz(ftimes,PET')';
   putimages(h2,img,j);
end;

closeimage(h);
closeimage(h2);

这种蛮力技术违反了上述几个准则。它在从 MINC 文件加载图像时没有重复使用内存。它转置PET,这会导致PET被复制。然后它转置来自ntrapz的结果,这会导致此结果被复制。

更好的方法是加载一个切片中的图像,逐行获取数据,然后重新组装成最终图像。以下 MATLAB 代码片段具有与上述代码相同的最终结果,但使用更少的内存(大约 4 兆字节)。

h=openimage('/local/matlab/toolbox/emma/examples/yates_19445.mnc');
h2 = newimage('new.mnc',[0 15], ...
     '/local/matlab/toolbox/emma/examples/yates_19445.mnc');

ftimes = getimageinfo (h,'MidFrameTimes');

img = zeros (16384,1);

for j=1:15
   PET = getimages(h,j,1:21,PET);
   for i=1:128:16257;
      line = PET(i:i 127,:);
      img (i:i 127) = ntrapz(ftimes, line')';
   end;

   putimages(h2,img,j);
end;

closeimage(h);
closeimage(h2);
华夏公益教科书