并行化IO-heavy for循环:愚蠢的想法?

时间:2014-05-31 13:34:45

标签: python parallel-processing

对于某个目录中的每个文件,我需要阅读其内容,并根据其内容对该文件执行某些操作。

我以为我会将其并行化,以便可以同时处理多个文件。 (我使用了python joblib。)

但它比顺序实施慢。

是否因为文件上的每个操作都涉及IO,并且IO无法并行化?因此,并行化没有加速,并且由于在所有分叉进程之间切换而导致速度减慢?


更多详情:

227,732个文件(所有文件.dat和< 100 kB) 1个四核CPU Ubuntu 13.04。

顺序所需的时间:9秒 平行时间:64秒。

from joblib import Parallel, delayed

def parallel(data_dir,dirlist):
  Parallel(n_jobs=-1)(delayed(good_or_bad_train_case)(filename, data_dir) 
                      for filename in dirlist if filename.endswith('.dat'))

def sequential(data_dir,dirlist):
  t = time.clock()
  [good_or_bad_train_case(filename,data_dir) for filename in 
   dirlist if filename.endswith('.dat')]

def good_or_bad_file(filename,data_dir):
  fullname = os.path.join(data_dir, filename)
  rootname = os.path.splitext(filename)[0]
  f = open(fullname)
  content = f.readlines()
  if 'NoPhotoOfJoint\r\n' in content or 'PoorPhoto\r\n' in content:
    os.symlink(fullname,data_dir+'/bad_data/'+rootname+'.jpg')
    os.symlink(fullname,data_dir+'/bad_data/'+rootname+'.dat')
  else: 
    os.symlink(fullname,data_dir+'/good_data/'+rootname+'.jpg')
    os.symlink(fullname,data_dir+'/good_data/'+rootname+'.dat')

注意:我知道并行化这种轻型操作没有多大意义;这是练习。

1 个答案:

答案 0 :(得分:2)

这里有几点需要注意:

  • joblib带来了很多开销,因为它必须使用Python的multiprocessing模块生成单独的进程,然后与这些进程通信以交换数据。它真正意味着科学计算工作负载,其中这种开销被子进程中的大量计算所抵消。
  • 所有工作进程都在访问同一磁盘。其中只有一个可以随时从磁盘中提取数据,因此,如果其余部分没有足够的计算量,他们就会等待。 (与CPU带宽相比,磁盘带宽微不足道。)
  • 由于磁盘速度很慢,在这种情况下通常需要两个工作人员,而不是“只有CPU /核心数量多”,因为超过秒的每个工作者只会增加开销。两个工作人员可以同时保持CPU和一个核心忙碌(尽管他们甚至不会给你两倍的加速)。
  • joblib 0.8有一个可以尝试的线程后端。