メモめもメモ

環境構築やプログラミングに関するメモ

Python3でコードを並列実行して高速化する

コードを並列実行する方法はマルチスレッドを使う方法とマルチプロセスを使う方法がありますが、Pythonはグローバルインタプリタロック(GIL)と呼ばれる仕組みにより同一プロセス内では常に1スレッドしか進行できません。そのため、マルチスレッドを使う方法は高速化につながりません(ブロッキングI/Oを使う場合を除く)。 高速化を目的として並列実行している場合はマルチプロセスを使いましょう。

コード

適当な重い処理を「並列実行なし」、「マルチスレッド」、「マルチプロセス」で実行して所要時間を表示します。 マルチスレッドとマルチプロセスの実現にはpython3.2で追加されたconcurrent.futuresモジュールを使用しました。

import concurrent.futures
import time


# 適当な重い処理
def allsum(num):
    a = 0
    for i in range(num):
        a += i
    return a


def main():
    nums = [4927814, 4142984, 6154248, 4149289, 4421984, 4812798, 4724198, 4421949]

    # 並列実行なし
    start = time.time()
    ans1 = list(map(allsum, nums))
    end = time.time()
    print("normal = %.3f sec" % (end-start))

    # マルチスレッドによる並列実行
    start = time.time()
    with concurrent.futures.ThreadPoolExecutor(max_workers=8) as pool:
        ans2 = list(pool.map(allsum, nums)) # <= ThreadPoolExecutorのmapを呼ぶ
    end = time.time()
    print("thread pool = %.3f sec" % (end-start))

    # マルチプロセスによる並列実行
    start = time.time()
    with concurrent.futures.ProcessPoolExecutor(max_workers=8) as pool:
        ans3 = list(pool.map(allsum, nums))# <= ProcessPoolExecutorのmapを呼ぶ
    end = time.time()
    print("process pool = %.3f sec" % (end-start))


if __name__ == '__main__':
    main()

実行結果

論理コア数8のCPUを搭載したマシンでプログラムを実行した結果です。 並列実行なしとマルチスレッドの所要時間はほぼ同じで、マルチプロセスのみ高速化に成功していることが読み取れます。

normal = 1.838 sec
thread pool = 1.859 sec
process pool = 0.752 sec