使用parfor进行适当的并行化

时间:2013-05-10 16:09:01

标签: matlab parallel-processing

我在Matlab中编写了一些图像处理代码我想加速使用并行处理。我选择了花费时间最长的任务:对图像应用高斯模糊。在文件交换的帮助下,我已经获得了比imfilter()更快的高斯模糊。但是,它仍然不会扩大规模。这是我的测试代码:

clear all
clc
image_paths = dir('C:\pics\Baustahl\3Bleche(3)\*.png');       
image_paths = sort({image_paths.name});

count = 600;

Img = cell(1, count);
Mean = cell(1, count);

for i = 1:count
    Img{i} = imread(['C:\pics\Baustahl\3Bleche(3)\ ' image_paths{i}]);
    Img{i} = Img{i}(:,:,1);
    Img{i} = single(Img{i})./255;
end
clear vars bilder

fprintf(1, 'Starting processing....\n');

starttime = tic;
parfor (i = 1:count, 4)
    Mean{i} = imgaussian(Img{i}, 25, 81);
end
elapsedtime = toc(starttime);
fprintf(1, 'Finished processing. (%d Files in %.1fs, %.1f files/second)\n', count, elapsedtime, count/elapsedtime);
fprintf(1, '\n');

clear vars Img Mean

我的系统有一个Q6600和4GB的RAM(这已经足够了)如果我将MATLAB限制为一个核心,我得到:

  

完成处理。 (600个文件,12.0s,49.8个文件/秒)

两个核心:

  

完成处理。 (600个文件,7.5秒,80.3个文件/秒)

使用所有四个核心,我得到以下内容:

  

完成处理。 (560s中的600个文件,104.7个文件/秒)

这是两倍的加速,虽然性能应该翻两番。每次迭代都独立于其他迭代,因此非常适合并行处理。 为什么规模如此糟糕?

我尝试过的事情:

  1. 我为C#安装了OpenCV和EmguCV包装器。使用标准for循环我得到~52个文件/秒,使用Parallel.ForEach()我得到~200个文件/秒。 (正如我所料)
  2. 使用不同数量的文件。如果我选择了足够的文件,则不会更改文件/秒:

      

    以0.3秒为单位的20个文件,每秒72.7个文件   60个文件,0.6s,94.3文件/秒
      200个文件,1.9s,105.3文件/秒

  3. 在Matlab中使用正常的for循环不会改变任何东西。显然,它与parfor-loop进行相同数量的并行化(自动魔术)。

  4. 明确指定它应该使用4个工作线程(见上文) - 什么都不做。 (设置为1时甚至不会降低性能)
  5. 文件大概是640x480灰度,内容相似。

    有什么想法吗?

2 个答案:

答案 0 :(得分:0)

您是否在致电parfor之前打开了matlabpool(否则它的行为会像平常一样)?

matlabpool 4
parfor 
    ...
end
matlabpool close

请注意,打开和关闭池将有10-20的开销。

答案 1 :(得分:0)

通过简单添加代码,这是一个非常好的加速。如上所述,如果没有足够的迭代或计算,使用parfor实际上可能会产生不利的性能。将文件发送到正确的内存空间并将其恢复的开销可能会导致此问题。

我猜你可以尝试spmd并平均分配每个工作人员的图像数量(有点像parfor那样做)。如果spmdparfor使用parfor但是值得一试,真的不确定{{1}}或{{1}}是否更快。