【问题标题】:Scope for improvement in this code此代码的改进范围
【发布时间】:2011-05-18 23:54:04
【问题描述】:

我在 MATLAB 中编写了以下代码来处理大约 3000x2500 像素的大图像。目前该操作需要半个多小时才能完成。是否有任何改进代码以减少时间的余地?我听说并行处理可以使事情变得更快,但我不知道如何实现它。给定以下代码,我该怎么做?

function dirvar(subfn)
[fn,pn] = uigetfile({'*.TIF; *.tiff; *.tif; *.TIFF; *.jpg; *.bmp; *.JPG; *.png'}, ...
            'Select an image', '~/');
I = double(imread(fullfile(pn,fn)));
ld = input('Enter the lag distance = '); % prompt for lag distance
fh = eval(['@' subfn]); % Function handles
I2 = uint8(nlfilter(I, [7 7], fh));
imshow(I2); % Texture Layer Image
imwrite(I2,'result_mat.tif');

% Zero Degree Variogram
function [gamma] = ewvar(I)
    c = (size(I)+1)/2; % Finds the central pixel of moving window
    EW = I(c(1),c(2):end); % Determines the values from central pixel to margin of window
    h = length(EW) - ld; % Number of lags
    gamma = 1/(2 * h) * sum((EW(1:ld:end-1) - EW(2:ld:end)).^2);
end

输入滞后距离通常为1。

【问题讨论】:

  • 你的电脑有多少内存?并行处理和其他方法都以执行速度换取内存使用。另外,您是否在图像上运行除变异函数以外的函数?
  • 我的电脑有 2.5 GB 的 RAM 和运行 Ubuntu 11.04、64 位的 Intel 双核处理器。我运行其他类似的函数来计算方向变异函数,但一次只运行一个函数。
  • 图片是什么数字格式? double?
  • 它们是 tiff 格式的 8 位图像(我研究区域的 LANDSAT 卫星图像子集)。
  • 不同的操作系统处理 Matlab 的方式不同。对于数字运算,Windows 和 Linux 差不多。对于图像处理,Linux 破坏了竞争。 Mac总体上是坏的。在同一台计算机上,当我运行 Matlab 基准(bench)时,Windows 7 得分为 65,我的 linux 得分为 110

标签: matlab performance parallel-processing


【解决方案1】:

您确实需要使用分析器来对其进行一些改进。我的第一个猜测(因为我还没有运行探查器,你应该按照建议),将尽可能少地使用 length 操作。由于您正在使用[7 7] 窗口处理每个图像,因此您可以预先计算一些部分, 这样你就不会重复这些动作了

function dirvar(subfn)
[fn,pn] = uigetfile({'*.TIF; *.tiff; *.tif; *.TIFF; *.jpg; *.bmp; *.JPG; *.png'}, ...
            'Select an image', '~/');
I = double(imread(fullfile(pn,fn)));
ld = input('Enter the lag distance = '); % prompt for lag distance
fh = eval(['@' subfn]); % Function handles

%% precalculations
wind = [7 7];
center = (wind+1)/2; % Finds the central pixel of moving window
EWlength = (wind(2)+1)/2;
h = EWlength - ld; % Number of lags

%% calculations
I2 = nlfilter(I, wind, fh);
imshow(I2); % Texture Layer Image
imwrite(I2,'result_mat.tif');

% Zero Degree Variogram
function [gamma] = ewvar(I)
    EW = I(center(1),center(2):end); % Determines the values from central pixel to margin of window
    gamma = 1/(2 * h) * sum((EW(1:ld:end-1) - EW(2:ld:end)).^2);
end
end

请注意,这样做会以性能换取代码的清晰性和耦合(在函数dirvar 和嵌套函数ewvar 之间)。但是,由于我没有分析您的代码(您应该自己使用自己的输入进行分析),您可以找到代码的哪一行消耗的时间最多。

对于批处理,我还建议省略任何 inputimshowimwriteuigetfile。这些是您通常从更高级的函数/脚本调用的命令,即使您希望它们保持不变,它们也会强制您输入这些输入。因此,不要使用该代码,而是将它们生成(/处理)的每个变量作为您的函数的参数(/返回值)。这样,您可以让 MATLAB 在周末运行以处理所有内容(无需手动输入所有这些值),即使您无法加快代码速度。

【讨论】:

    【解决方案2】:

    一些通用技巧:

    1 - 使用MATLAB profiler 确定所有计算瓶颈

    2 - 并行处理可以使事情变得更快,并且您可以使用很多工具,但这取决于您的整个代码的设置方式以及代码是否针对它进行了优化。到目前为止,最容易学习的技巧是parfor,您可以在其中将顶级for 循环替换为parfor。这确实意味着您必须使用 matlabpool open 打开 MATLAB 池。

    3 - 如果您有一个相当新的Nvidia GPU 以及 MATLAB 2011,您还可以编写一些 CUDA 代码。

    总而言之,30 分钟对我来说是花生,所以不要太担心。

    【讨论】:

    • 我不介意花 30 分钟进行一次操作,但就我而言,我必须在 50 个这样的图像上使用此代码!
    • 我不是图像处理人员,但查看目前的一些信息,我认为您需要让自己访问分布式网络。在这种情况下,学习如何设置批处理作业,它会减少你的时间,也许是一夜之间运行。 (mathworks.com/help/toolbox/distcomp/batch.html)
    • 对给出的提示的一点补充:如果你有 MATLAB 2011,你可能想看看 MATLAB Coder,它可能允许你将代码从 MATLAB 转换为 C,它还可以运行快很多。
    • @Egon,我即将参加一个讨论这个概念的会议,所以我会回复你
    • 嗯,据我所知,这是一种非常有前途的技术。但是,使用 OP 中的代码,我无法用它生成任何 C 代码。所以它还不是完全安全的。
    【解决方案3】:

    首先,我强烈建议你遵循@Egon 的建议:编写一个单独的函数来收集文件列表(来自FEX 的优秀UIPICKFILES 是你的朋友),然后运行你的过滤代码每个图像的循环。请注意,您绝对应该在过滤代码中保留对 imwrite 的调用:如果分析在图像 48 处崩溃(例如由于电源故障),您不想丢失之前的所有工作。

    因此以批处理模式运行有两大优势:(1) 您可以开始运行您的代码并在周末回家,以及 (2) 您可以使用 PARFOR 轻松并行化这个外部循环。但是,只有双核机器,您不太可能从并行化中获得任何显着改进 - 您的操作系统有时也希望运行一些东西,并行化的开销可能超过运行两个工作人员的收益。此外,2.5GB 的 RAM 严重受限。

    至于您的具体代码:根据我使用IM2COL 的经验,通常比NLFILTER 快​​。 im2col 从您的图像中创建一个 nElementsInMask-by-nMasks 数组,以便您可以在一次操作中应用过滤。对于 7x7 的窗口,im2col 的输出将是 3000*2500*49 字节,接近 400MB。因此,它应该可以正常工作。您需要做的就是重写ewvar,使其适用于构成掩码像素的49x1 像素数组,如果我正确理解您的代码,这将需要一些索引处理。

    【讨论】:

    • 我认为你最好在外部循环中使用imwrite 而不是处理函数:你可能希望有一天重用过滤代码而不写入磁盘(同样,在原始代码,所有内容都写入同一个文件,对于批处理来说并不是很好的行为)。 parfor 是一个非常棒的建议,我已经获得了很大的性能提升(尽管在具有 8GB RAM 的四核上,但我想即使在双核上你也会获得足够的收益)。
    猜你喜欢
    • 2011-04-13
    • 2016-12-20
    • 1970-01-01
    • 2012-02-16
    • 1970-01-01
    • 2016-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多