は、次の関数を考えてみましょう:Pythonマルチプロセッシング - functools.partialをデフォルト引数よりも遅く使用するのはなぜですか?
def f(x, dummy=list(range(10000000))):
return x
私はmultiprocessing.Pool.imap
を使用している場合は、私は次のタイミングを得る:
import time
import os
from multiprocessing import Pool
def f(x, dummy=list(range(10000000))):
return x
start = time.time()
pool = Pool(2)
for x in pool.imap(f, range(10)):
print("parent process, x=%s, elapsed=%s" % (x, int(time.time() - start)))
parent process, x=0, elapsed=0
parent process, x=1, elapsed=0
parent process, x=2, elapsed=0
parent process, x=3, elapsed=0
parent process, x=4, elapsed=0
parent process, x=5, elapsed=0
parent process, x=6, elapsed=0
parent process, x=7, elapsed=0
parent process, x=8, elapsed=0
parent process, x=9, elapsed=0
今、私が代わりにデフォルト値を使用してのfunctools.partial
を使用する場合:
import time
import os
from multiprocessing import Pool
from functools import partial
def f(x, dummy):
return x
start = time.time()
g = partial(f, dummy=list(range(10000000)))
pool = Pool(2)
for x in pool.imap(g, range(10)):
print("parent process, x=%s, elapsed=%s" % (x, int(time.time() - start)))
parent process, x=0, elapsed=1
parent process, x=1, elapsed=2
parent process, x=2, elapsed=5
parent process, x=3, elapsed=7
parent process, x=4, elapsed=8
parent process, x=5, elapsed=9
parent process, x=6, elapsed=10
parent process, x=7, elapsed=10
parent process, x=8, elapsed=11
parent process, x=9, elapsed=11
functools.partial
を使用しているバージョンの方がずっと遅いのはなぜですか?
なぜ 'list(range(...)) 'を使用していますか? AFAIKあなたのコードは、ShadowRangerによって説明された問題が起こらず、酸洗いのオーバーヘッドがずっと小さくなることを除いて、 'list'を呼び出すことなく全く同じことをするでしょう。 – Bakuriu
サイドノート:デフォルトの(または部分的にバインドされた)引数として 'list's(または他の変更可能な型)を使用することは危険です。なぜなら_same_' list'は新しいコピーではなく、関数のすべてのデフォルト呼び出し間で共有されるからです各呼び出しごとに。通常、新鮮なコピーが必要です。 – ShadowRanger
注意しておきますが、通常、変更可能なオブジェクトをデフォルト値として使用することは好ましくありません。なぜなら、関数の中でそれを変更すると、関数への呼び出しごとに変更が表示されるからです。 – Copperfield