10

遅延した 2 番目の 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

まず、ワーカー プロセスで何が起こっているかを把握することから始めます。multiprocessing モジュールには、必要に応じてサブプロセスのログが付属しています。コードを単純化して問題を絞り込んだので、次のようにいくつかの print ステートメントでデバッグします (またはpf配列を PrettyPrint できます)。


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 のマルチプロセッシングで、プールからサブプロセスを生成する際に問題が発生するのを見てきました。(具体的には、マルチプロセッシングを使用してサブプロセスを生成するスクリプトを作成しました。これらのサブプロセスは、マルチプロセッシングを正しく使用できませんでした (プールがロックされました))。mulitprocessing バックポートを使用して python2.5 を試してください。

3) picloudの cloud.mp モジュール (マルチプロセッシングをラップしますが、プールの処理が少し異なります) を試して、それが機能するかどうかを確認します。

あなたはするだろう

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

(免責事項: 私は PiCloud の開発者の 1 人です)

于 2009-12-02T05:13:11.773 に答える