10

我编写了以下代码以使我的第二个懒惰的 CPU 内核正常工作。代码所做的基本上是首先在目录层次结构中找到所需的“sea”文件,然后执行一组外部脚本来处理这些二进制“sea”文件,以生成 50 到 100 个文本和二进制文件。正如问题的标题所暗示的那样,以并行方式提高处理速度。

这个问题源于我们在标题为“无法启动 ipcluster ”的 IPython 用户列表上进行的长时间讨论。从我对 IPython 的并行处理功能的实验开始。

问题是我无法让这段代码正确运行。如果包含“sea”文件的文件夹仅包含“sea”文件,则脚本完成其执行而不完全执行外部脚本运行。(假设我有 30-50 个外部脚本要运行,但我的多处理启用脚本仅在执行这些外部脚本链中的第一个脚本后才会耗尽。)有趣的是,如果我在已处理的文件夹(即“sea”文件)上运行此脚本预先处理并且输出文件已经在该文件夹中)然后它运行,但是这次我在线性处理时间方面得到了大约 2.4 到 2.7 倍的加速。因为我的笔记本电脑中只有一个 Core 2 Duo 2.5 Ghz CPU,所以这不是很值得期待。虽然我有一个支持 CUDA 的 GPU,但它与我目前的并行计算斗争无关 :)

您认为这个问题的根源可能是什么?

感谢您的所有意见和建议。

#!/usr/bin/env python

from multiprocessing import Pool
from subprocess import call
import os


def find_sea_files():

   file_list, path_list = [], []
   init = os.getcwd()

   for root, dirs, files in os.walk('.'):
      dirs.sort()
      for file in files:
          if file.endswith('.sea'):
              file_list.append(file)
              os.chdir(root)
              path_list.append(os.getcwd())
              os.chdir(init)

   return file_list, path_list


def process_all(pf):
   os.chdir(pf[0])
   call(['postprocessing_saudi', pf[1]])


if __name__ == '__main__':
   pool = Pool(processes=2)              # start 2 worker processes
   files, paths = find_sea_files()
   pathfile = [[paths[i],files[i]] for i in range(len(files))]
   pool.map(process_all, pathfile)
4

2 回答 2

6

我会首先对工作进程的情况有更好的感觉。如果需要,多处理模块会为其子进程提供日志记录。由于您已简化代码以缩小问题范围,因此我只需使用一些打印语句进行调试,如下所示(或者您可以 PrettyPrint pf数组):


def process_all(pf):
   print "PID: ", os.getpid()
   print "Script Dir: ", pf[0]
   print "Script: ", pf[1]
   os.chdir(pf[0])
   call(['postprocessing_saudi', pf[1]])


if __name__ == '__main__':
   pool = Pool(processes=2)
   files, paths = find_sea_files()
   pathfile = [[paths[i],files[i]] for i in range(len(files))]
   pool.map(process_all, pathfile, 1) # Ensure the chunk size is 1
   pool.close()
   pool.join()

我用 2.6.4 完成的 Python 版本。

于 2009-12-21T18:21:30.937 回答
3

我能想到几件事:

1)你打印出路径文件了吗?你确定它们都是正确生成的吗?

a)我问你的 os.walk 有点有趣;dirs.sort() 应该没问题,但似乎非常不必要。os.chdir() 通常不应使用;恢复应该没问题,但通常你应该只是将root附加到init。

2) 我已经看到 python2.6 上的多处理在从池中生成子进程时遇到问题。(我专门有一个脚本使用多处理来生成子进程。这些子进程然后无法正确使用多处理(池被锁定))。尝试带有多处理反向端口的 python2.5。

3)尝试picloud的 cloud.mp 模块(它包装了多处理,但处理池的方式略有不同),看看它是否有效。

你会做

cloud.mp.join(cloud.mp.map(process_all, pathfile))

(免责声明:我是 PiCloud 的开发者之一)

于 2009-12-02T05:13:11.773 回答