multiprocessing の pool.map( ... ) を使用して多数の計算を並行して実行する python スクリプトがあります。これらの各計算は、subprocess.popen( ... , stdin=PIPE, stdout=PIPE, stderr=PIPE ) を使用してプログラムを実行し、入力をダンプして読み取り、fortran プログラムの入力を設定する Python スクリプトで構成されます。出力。次に、スクリプトは出力を解析し、必要な数値を取得してから、次の実行のためにもう一度実行します。
def main():
#Read a configuration file
#do initial setup
pool = multiprocessing.Pool(processes=maxProc)
runner = CalcRunner( things that are the same for each run )
runNumsAndChis = pool.map( runner, xrange(startRunNum, endRunNum))
#dump the data that makes it past a cut to disk
class CalcRunner(object):
def __init__(self, stuff):
#setup member variables
def __call__(self, runNumber):
#get parameters for this run
params = self.getParams(runNum)
inFileLines = []
#write the lines of the new input file to a list
makeInputFile(inFileLines, ... )
process = subprocess.Popen(cmdString, bufsize=0, stdin=subprocess.PIPE, ... )
output = proc.communicate( "".join(inFileLines) )
#get the needed numbers from stdout
chi2 = getChiSq(output[0])
return [runNumber, chi2]
...
とにかく、質問の理由に進みます。このスクリプトをグリッド エンジン システムに送信して、この膨大なパラメータ スペース スイープを 1000、12 コア (ほとんどのグリッドが 12 コアであるため、12 を選択) のタスクに分割します。1 つの 12 コア マシンで 1 つのタスクを実行すると、マシンの時間の約 1/3 がシステム処理に費やされ、残りの 2/3 がユーザー計算に費やされ、おそらく ECIS (前述の FORTRANコード)、ECIS の実行、および ECIS の出力の解析。ただし、5 つのタスクが 64 コアのマシンに送信され、その 60 のコアが使用されることがあります。そのマシンでは、時間の 40% がシステム処理に費やされ、1 ~ 2% がユーザー処理に費やされます。
まず第一に、すべてのシステム コールはどこから来ているのでしょうか。私は、ECIS を個別のスレッドごとに 1 回実行し、新しい入力をそれにパイプし続け、システム内ではるかに多くの時間を費やす (そして全体的に遅くなる) プログラムのバージョンを作成しようとしました。プロセスの作成と削除。次に、システム コールにかかる時間を減らすにはどうすればよいでしょうか。
推測では、プロセスから何かを取得するためにgfortranの出力バッファリングをオフにする必要があったため、プロセスを1回開いて入力を送信し続けるのが遅くなりました。ハプニング)。
これを開発した自宅のテスト マシンの OS は Fedora 14 です。グリッド マシンの OS は Red Hat の最新バージョンです。
-1 (システムのデフォルト)、0 (バッファなし)、1 (行ごと)、および 64Kb に設定して、bufsize をいじってみましたが、状況は変わらないようです。