0

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 をいじってみましたが、状況は変わらないようです。

4

0 に答える 0