1

スタックオーバーフローのユーザーの皆様、こんにちは。

私はこれを調べようとしましたが、答えを見つけることができませんでした: 私は基本的に関数を並列処理するのが好きで (独立したプロセス!)、関数には 1 つの反復可能な ( x)いくつかの定数引数 ( k, d) があります。以下は、非常に単純化された例です。

from multiprocessing import *

def test_function(args):
    k = args[0]
    d = args[1]
    x = args[2]
    del args

    return k*x + d

if __name__ == '__main__':
    pool = Pool(processes=2)

    k = 3.
    d = 5.

    constants = [k,d]
    xvalues = range(0,10)
    result = [pool.apply_async(test_function, constants.append(i)) for i in xvalues]

    output = [r.get() for r in result]

    print output
    #I expect [5.0, 8.0, 11.0, 14.0, 17.0, 20.0, 23.0, 26.0, 29.0, 32.0]

これにより、次のエラーメッセージが表示されます。

Traceback (most recent call last):
  File "test_function.py", line 23, in <module>
    output = [r.get() for r in result]
  File "C:\Program Files\Python2.7\lib\multiprocessing\pool.py", line 528, in get
    raise self._value
TypeError: test_function() argument after * must be a sequence, not NoneType

だから私の質問は:

このエラー メッセージの実際の意味は何ですか?

期待どおりの結果が得られるように修正するにはどうすればよいですか (コード例の最後の行を参照)。

apply_sync を呼び出す行のより良い/機能する/エレガントな方法はありますか?

参考までに: 私はここで Python を初めて使用します。ご容赦ください。投稿に詳細が必要な場合はお知らせください。

ご提案いただきありがとうございます。

4

2 に答える 2

1

このエラー メッセージの実際の意味は何ですか?

メソッドによって返される値appendは常にNoneであるため、次の場合:

pool.apply_async(test_function, constants.append(i))

引数として呼び出しpool.apply_asynchていますが、引数としてイテラブルが必要です。していることは-unpackingと呼ばれます。Noneargsapply_asynchapply_asynchtuple

期待される結果を得るにはどうすれば修正できますか?

i期待される出力を得るには、 を定数に単純に連結します。

pool.apply_asynch(test_function, (constants + [i],))

apply_sync を呼び出す行のより良い/機能する/エレガントな方法はありますか?

test_function単一の引数を受け入れるため、すべての引数を 1 つの要素のタプルにラップする必要があることに注意してください。次のように変更できます。

def test_function(k, d, x):
    # etc

そして、単に使用します:

pool.apply_asynch(test_function, constants + [i])

は、 -unpackingを使用して を関数の 3 つの引数にapply_asynch自動的にアンパックします。(と フレンズのドキュメントを注意深く読んでください)。argstuplePool.apply


apply_sync を呼び出す行のより良い/機能する/エレガントな方法はありますか?

サイラスが指摘したようにPool.apply_asynch、値のリストを使用する代わりに、Pool.mapまたはPool.map_asynchメソッドを使用する必要があります。

例えば:

results = pool.map(test_function, [(constants + [i],) for i in xvalues])

ただし、この場合test_functionは単一の引数を受け入れる必要があるためx、質問で行っていたように、定数と を手動でアンパックする必要があることに注意してください。


また、一般的な提案として:

  • あなたtest_functionの中でする必要はまったくありませんdel args関数の実行が遅くなるだけです(ごくわずかです)。del必要なときだけ、控えめに使用してください。
  • タプルから要素を手動で割り当てる代わりに、次の構文を使用できます。

    k, d, x = args
    

    これは(おそらく少し遅い)と同等です:

    k = args[0]
    d = args[1]
    x = args[2]
    
  • このような単純な関数を呼び出すために使用すると、大幅な速度低下が予想されます。multiprocessingプロセスの通信と同期のコストは非常に大きいため、単純な関数の呼び出しを避ける必要があり、可能な場合は常に「チャンク」で作業するようにしてください (たとえば、各リクエストを個別に送信する代わりに、100 のリクエストのリストを一度にワーカーに送信します)。口論)。
于 2013-09-16T18:01:42.913 に答える