跳轉到內容

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);
華夏公益教科書