4

我有一组图像(~10^7),它们包含在一个巨大的二进制文件中。我想使用我已经拥有的功能有效地阅读和分析它们。代码中该用户函数foo的每次迭代大约需要 0.1 秒,因此代码需要数天时间才能使用读取数据库的简单 for 循环来处理整个数据库:

... 
for image_number=1:N
     offset_in_bytes = npoints_per_image*element_size*(image_number-1);
     fseek(fid, offset_in_bytes, 'bof'); 
     s=fread(fid, npoints_to_load,'ushort');
     image=reshape(s,nrows,[]);
     [outputs]=foo(image)
end

我已经尽可能地优化了函数foo(尽可能对代码进行矢量化,使用正确的数据类等)。我唯一还没有做的是创建一个 mex 版本。我想用parfor这个,但我无法让它工作。艰难的每个图像都是独立的,上面的代码串行读取数据,所以我不能真正并行化它。如何使该parfor选项可以访问此代码和数据库?谢谢

4

2 回答 2

0

我在这里假设您的图像大小都相同,或者您事先知道的大小。也就是说:您不必扫描所有以前的图像来知道当前图像的大小。如果不是这种情况,以下将无济于事。

提供的代码不适用于 parfor,因为您有多个工作人员试图共享一个文件句柄。Matlab 的并行工具设计用于多个计算机集群,因此文件句柄之类的东西不能很好地复制。

要使您的代码与 parfor 一起工作,您需要在循环中打开和关闭文件,如下所示:

parfor image_number=1:N
  fid = fopen(filename, 'r');
  offset_in_bytes = npoints_per_image*element_size*(image_number-1);
  fseek(fid, offset_in_bytes, 'bof'); 
  s=fread(fid, npoints_to_load,'ushort');
  image=reshape(s,nrows,[]);
  [outputs]=foo(image);
  fclose(fid);
end

如果您发现这会增加流程的开销,您可能需要使用嵌套循环并可能需要一些缓冲:

chunk_size = ceil(N/10);
parfor i = 0:9
  fid = fopen(filename, 'r');

  %some buffering code here

  %start this iteration of the parfor loop at this image_number
  start_num = 1+(i * chunk_size); 
  end_num = min(N, (i+1) * chunk_size); %and end it at this one

  for image_number=start_num:end_num
    %your code here
  end

  fclose(fid);
end

正如 Edric 所提到的,如果您在 foo 函数中充分利用矢量处理,那么这可能不会加快速度,因为 parfor 确实使 matlab 在单线程模式下运行。

于 2013-03-27T18:19:03.423 回答
0

要有效地并行运行此循环,您需要能够并行运行FREAD部分和foo部分。您可以通过将 替换为对 MATLAB 之类的虚拟调用来检查该foo部分是否并行运行。FREADRAND

请注意,matlabpoolworker 以单线程模式运行。如果您在一台机器上运行所有工作人员,这一点尤其重要。如果foo能够很好地利用 MATLAB 的内在多线程,那么使用PARFOR循环可能会使事情变慢。

我怀疑如果您只有一个大图像文件,那么您的文件系统可能会或可能不会让您完全并行访问它。我不确定如何最好地解决这个问题 - 它几乎可以肯定取决于您的特定文件系统。

于 2013-02-26T10:46:35.950 回答