82

concurrent.futures.Executor.map、指定された関数が呼び出される反復可能オブジェクトの可変数を取ります。通常はその場でアンパックされるタプルを生成するジェネレーターがある場合、どのように呼び出す必要がありますか?

生成されたタプルのそれぞれが map への異なる引数として与えられるため、以下は機能しません:

args = ((a, b) for (a, b) in c)
for result in executor.map(f, *args):
    pass

ジェネレーターがない場合、マップする必要のある引数は次のようになります。

executor.map(
    f,
    (i[0] for i in args),
    (i[1] for i in args),
    ...,
    (i[N] for i in args),
)
4

9 に答える 9

75

繰り返される 1 つの引数、1 つの引数c

from itertools import repeat
for result in executor.map(f, repeat(a), c):
    pass

のアイテムを開梱する必要がありc、開梱できますc

from itertools import izip
for result in executor.map(f, *izip(*c)):
    pass

のアイテムを開梱する必要がありますがc、開梱できませんc

  1. f単一の引数を取り、関数で引数をアンパックするように変更します。
  2. の各アイテムcのメンバー数が可変の場合、または数回しか呼び出しfていない場合:

    executor.map(lambda args, f=f: f(*args), c)
    

    から各アイテムをアンパックしcて呼び出す新しい関数を定義しますf。でデフォルトの引数を使用するとf、内でローカルになるため、ルックアップ時間が短縮されます。lambdaflambda

  3. 固定数の引数があり、何度も呼び出す必要がある場合f:

    from collections import deque
    def itemtee(iterable, n=2):
        def gen(it = iter(iterable), items = deque(), next = next):
            popleft = items.popleft
            extend = items.extend
            while True:
                if not items:
                    extend(next(it))
                yield popleft()
        return [gen()] * n
    
    executor.map(f, *itemtee(c, n))
    

nへの引数の数はどこにありますかf。これは から改作されていitertools.teeます。

于 2011-08-08T00:25:10.483 に答える
68

通話中*にを削除する必要があります。map

args = ((a, b) for b in c)
for result in executor.map(f, args):
    pass

fこれは, len(args)timesを呼び出します。 wherefは 1 つのパラメーターを受け入れる必要があります。

2 つのパラメーターを受け入れたい場合はf、次のようなラムダ呼び出しを使用できます。

args = ((a, b) for b in c)
for result in executor.map(lambda p: f(*p), args):   # (*p) does the unpacking part
    pass
于 2011-08-08T01:08:52.123 に答える
12

したがって、 3 つの引数を取る関数があり、3 つの引数はすべて動的で、呼び出しごとに変化し続けるとします。例えば:

def multiply(a,b,c):
    print(a * b * c)

スレッド化を使用してこれを複数回呼び出すには、まず、各タプルが a、b、c のバージョンであるタプルのリストを作成します。

arguments = [(1,2,3), (4,5,6), (7,8,9), ....]

concurrent.futuresの関数は、実行される関数の各バージョンの引数のリストとして、ターゲット関数mapとして最初の引数を受け入れ、2 番目の引数を受け入れることがわかっています。したがって、次のような呼び出しを行うことができます。

for _ in executor.map(multiply, arguments) # Error

ただし、これにより、関数が予期したエラー3 arguments but got only 1が発生します。この問題を解決するために、ヘルパー関数を作成します。

def helper(numbers):
    multiply(numbers[0], numbers[1], numbers[2])

これで、次のようにエグゼキューターを使用してこの関数を呼び出すことができます。

with ThreadPoolExecutor() as executor:
     for _ in executor.map(helper, arguments):
         pass

これにより、望ましい結果が得られるはずです。

于 2019-12-05T10:58:48.670 に答える
1

以下に示すデータフレームにこのようなデータがあり、最初の2列を関数に渡し、画像を読み取って特徴を予測し、差を計算して差の値を返すとします。

注:要件に応じて任意のシナリオを作成でき、それぞれ関数を定義できます。

以下のコード スニペットは、これら 2 つの列を引数として取り、スレッドプール メカニズムに渡します (プログレス バーも表示します)。

ここに画像の説明を入力

''' function that will give the difference of two numpy feature matrix'''
def getDifference(image_1_loc, image_2_loc, esp=1e-7):
       arr1 = ''' read 1st image and extract feature '''
       arr2 = ''' read 2nd image and extract feature '''
       diff = arr1.ravel() - arr2.ravel() + esp    
       return diff

'''Using ThreadPoolExecutor from concurrent.futures with multiple argument'''

with ThreadPoolExecutor() as executor:
        result = np.array(
                         list(tqdm(
                                   executor.map(lambda x : function(*x), [(i,j) for i,j in df[['image_1','image_2']].values]),
                               total=len(df)
                                  ) 
                             )
                          )

ここに画像の説明を入力

于 2021-06-29T09:53:26.470 に答える