MINC/工具/emma/emma-matlab 記憶體
外觀
MATLAB 是一個非常有用的工具,用於分析醫學影像資料。不幸的是,它有一個明顯的缺點:MATLAB 記憶體管理很糟糕。記憶體很容易變得碎片化,沒有嘗試進行壓縮(除了幾乎無用的 MATLABpack函式)。對於大型醫學影像體積,結果可能是災難性的,導致巨大的記憶體使用,效能低下,在極端情況下,作業系統會終止你的 MATLAB 程序。
控制 MATLAB 記憶體使用有點像變戲法。有一些通用的指導方針可以遵循,但沒有適用於所有情況的硬性規定。以下是一些軟性規則
- 儘可能重複使用記憶體。例如,EMMAgetimages函式允許你指定要使用的記憶體塊。通常,這是包含影像的變數,並且應該與要載入的影像的大小相同
PET = getimages(h,8,1:21,PET);
將重複使用分配給矩陣 PET 的記憶體,並且不會為返回的影像分配新的記憶體。這消除了與重新載入一組影像相關的碎片化問題。
- 使用 EMMArescale函式將矩陣乘以標量。此函式不分配新的記憶體,而是使用已經分配給矩陣的記憶體。例如,MATLAB 指令
PET = PET .* 5;
將導致碎片化,因為矩陣 PET 將被複制。但是,指令
rescale (PET,5);
具有相同的效果,但不會導致碎片化。
- 初始化大型矩陣。當你想透過一系列操作來緩慢地填充矩陣時,這很有用。例如,如果你想在變數中建立一個 128x128 的影像,一行一行地建立Fake_PET,你應該指定
Fake_PET = zeros(128,128);
這將初始化矩陣為正確的大小,並用零填充。然後,當你用你的值填充矩陣時,它不會被複制,並且不會發生記憶體碎片化。
- 一次使用少量記憶體。這可能是 *最重要的規則*,並且可以潛在地解決所有記憶體使用問題。例如,當分析動態研究時,請考慮分解你的分析,以便它可以一次在一行(或幾行)上執行,而不是在整個影像上執行。
例如,考慮 [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);