Есть ли способ указать, какой аргумент в QuTiP Parallel_map должен повторяться? - PullRequest
0 голосов
/ 21 марта 2020

Функция QuTiP parallel_map предоставляет возможность вычислить значение данной функции для нескольких значений ее аргумента параллельно. Все примеры показывают случаи, когда первый позиционный аргумент изменяется, например:

def testFunc1(a, b):
    return a, b

from qutip import parallel_map
parallel_map(testFunc1, (1, 2, 3), task_args=(4,))

Возвращает [(1, 4), (2, 4), (3, 4)]. Теперь мне интересно, возможно ли также иметь фиксированное значение для a и кортеж для b. Согласно документации task_args также может быть словарем, поэтому я попытался

parallel_map(testFunc1, (1, 2, 3), task_args={'a': 4})
parallel_map(testFunc1, (1, 2, 3), task_args={'a': 4, 'b': (1, 2, 3)})

, но это привело к TypeError: can only concatenate tuple (not "dict") to tuple.
Когда я пытаюсь

parallel_map(testFunc1, b=(1, 2, 3), task_args={'a': 4})

, я получаю TypeError: parallel_map() missing 1 required positional argument: 'values'.

Кто-нибудь знает, как использовать parallel_map для n -го позиционного аргумента ( без написания функции-оболочки для каждого n )?

Ответы [ 2 ]

0 голосов
/ 22 марта 2020

Просмотр исходного кода для parallel_map показывает, почему он работает только для первого аргумента функции:

async_res = [pool.apply_async(task, (value,) + task_args, task_kwargs, _update_progress_bar)
             for value in values]

В этой строке создаются параллельные процессы. Функция task получает кортеж, представляющий все позиционные аргументы, который создается из 1 элемента values и всех других task_args. Поскольку элемент values находится в первой позиции объединенного кортежа ((value,) + task_args), всегда является первым аргументом функции, которая изменяется между его параллельными экземплярами. TypeError: can only concatenate tuple (not "dict") to tuple, если словарь используется для task_args, происходит из-за того, что + -оператор перегружен только для (tuple, tuple), а не для (tuple, dict).

Таким образом, в конце концов, есть нет способа построить обертку. Либо один для каждого конкретного n , либо универсальный c, например:

def wrapper(varyingArgument, moreArgs):
    n = moreArgs[0]
    orderedArgs = moreArgs[1:n] + (varyingArgument,) + moreArgs[n:]
    return testFunc1(*orderedArgs)

. Вызов с помощью

parallel_map(wrapper, (1,2,3), task_args=((2, 4),))

возвращает

[(4, 1), (4, 2), (4, 3)]
0 голосов
/ 21 марта 2020

Q : "как использовать parallel_map для n -го позиционного аргумента (без написания функции-оболочки для каждого n) ? "

Избегайте создания проблем там, где их нет, и размещайте все, что у вас есть n -ое внешнее заполнение, повторяемое в вашем def вызов функции-подписи прямо в parallel_map()-ожидаемую (как документально подтвержденную) и совместимую с итерационной обработкой tuple:

#          (           )-------------------------- parallel_map() expected TUPLE
#your Fun( (  a    vv--)-------------------)----------------your FED-IN ITERABLE
testFunc1( ( 'a', 'b1' ), 'of-no-interest' ) --> (('a', 'b1'), 'of-no-interest')
testFunc1( ( 'a', 'b2' ), 'of-no-interest' ) --> (('a', 'b2'), 'of-no-interest')
testFunc1( ( 'a', 'b3' ), 'of-no-interest' ) --> (('a', 'b2'), 'of-no-interest')

"Вы имеете в виду что-то вроде parallel_map(testFunc1, [(4, 1), (4, 2), (4, 3)], task_args=('of-no-interest',))? Здесь b всегда имеет значение 'of-no-interest'. - AP 2 часа a go"

Нет,
Примером является четкий путь к разгрузке a и всем без исключения n -ому пользовательский код FED-IN повторяемый ( с) , как и требовалось выше.

def testFun2( a, b ):
    return [ item for item in tuple( a ) ], b

показать способ вызова:

testFun2( ( 'a', 'b', "c", None, 42, -3.14159, "The-N-th-ITERABLE" ),
          'not-important-one-(of-no-interest-HERE-in-solving-N-th-iterable-for-parallel_star()-calls)...'
           )

доставляет ->

(['a', 'b', 'c', None, 42, -3.14159, "The-N-th-ITERABLE"], 'not-important-one-(of-no-interest-HERE-in-solving-N-th-iterable-for-parallel_star()-calls)...')

Точно соответствует обоим a) ваш w sh иметь свободные руки для любой N-й итерируемой, а не только первой позиционной и также b) той самой сигнатуры вызова parallel_map() ожидает и была задокументирована для этого:

parallel_map( testFun2,                                        # TASK         Callable
              ( <_USER-SIDE_GENERATOR_FEED-IN_TUPLEsOfPARs_> ),# TASK VALUE(s)Array / List
              any_other_wished2have_call-signature_parameters, # TASK_ARGS    Dict
              ...,                                             # TASK_KWARGS  Dict
              ...                                              # call  KWARGS Dict
              )
...