有没有一种方法可以指定QuTiP的parallel_map迭代哪个参数?

时间:2020-03-21 13:57:32

标签: python parallel-processing parameter-passing qutip

QuTiP的函数parallel_map为并行计算其参数的多个值提供了计算给定函数的值的可能性。所有examples都显示了第一个位置参数变化的情况,如下所示:

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设置一个元组。根据{{​​3}} 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 :(得分:0)

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'。– A. P. 2 hours ago” < / em>

否,
该示例是卸载a 以及所有 n -th 的清晰路径用户端代码FED​​-IN 可迭代 s),如上所述。

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) ,您希望在第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
              )

答案 1 :(得分:0)

查看source code of parallel_map揭示了为什么它仅适用于函数的第一个参数:

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

在这一行中,创建了并行进程。函数task获取一个表示所有位置参数的元组,该元组由values的1个元素和所有其他task_args的元素创建。由于values的元素位于组合元组((value,) + task_args)的第一个位置,因此始终是该函数的第一个参数,该参数在其并行实例之间有所不同。 TypeError: can only concatenate tuple (not "dict") to tuple(如果用于task_args的词典是由于+运算符仅对(tuple, tuple)而不是(tuple, dict)重载的事实而来。

因此,最终没有办法构建包装器。对于每个特定的 n 之一,或者诸如此类的通用名称:

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)]