如何在Parallel中设置变量/函数定义(例如使用ParallelMap)?

时间:2012-01-15 02:43:32

标签: wolfram-mathematica

我有一个用于根据索引查找值的函数。该值需要一些时间来计算,所以我想用ParallelMap来做,并引用另一个类似的这样的函数,它返回一个表达式列表,也基于一个索引。

然而,当我以一种看似合理的方式设置它时,我看到了一些非常奇怪的行为。首先,我看到该功能似乎有效,尽管速度很慢。然而,对于大型索引,Taskmangler中的处理器活动在延长的时间段(即2-4分钟)内完全保持为零,其中Mathematica的所有实例看起来都是惰性的。然后,如果没有最轻微的CPU使用,就会出现结果。这是Mathematica的另一个案例spukhafte Fernwirkung吗?

也就是说,我想创建一个存储表达式的变量/函数,这里是一个整数列表(ListOfInts),然后在并行工作者上我想对该表达式执行一些函数(这里我应用一组替换规则并取Min)。我希望该函数的结果也被另一个变量/函数(IndexedFunk)下的相同索引索引,其结果随后可在Mathematica的主实例上获得:

(*some arbitrary rules that will convert some of the integers to negative values:*)
rulez=Dispatch[Thread[Rule[Range[222],-Range[222]]]];

maxIndex = 333;
Clear[ListOfInts]
Scan[(ListOfInts[#]=RandomInteger[{1,999},55])&,Range[maxIndex ]]
(*just for safety's sake:*)
DistributeDefinitions[rulez, ListOfInts]

Clear[IndexedFunk]
(*I believe I have to have at least one value of IndexedFunk defined before I Share the definition to the workers:*)
IndexedFunk[1]=Min[ListOfInts[1]]/.rulez
(*... and this should let me retrieve the values back on the primary instance of MMA:*)
SetSharedFunction[IndexedFunk]

(*Now, here is the mysterious part: this just sits there on my multiprocessor machine for many minutes until suddenly a result appears.  If I up maxIndex to say 99999 (and of course re-execute the above code again) then the effect can more clearly be seen.*)
AbsoluteTiming[Short[ParallelMap[(IndexedFunk[#]=Min[ListOfInts[#]/.rulez])&, Range[maxIndex]]]]

我相信这是一些错误,但后来我仍在试图找出Mathematica Parallel,所以我不能对这个结论过于自信。尽管速度慢得令人沮丧,但它在执行计算的能力方面仍然令人印象深刻,而实际上并不需要CPU这样做。

我想也许是因为在主进程和从进程之间使用了任何通信协议,可能它是如此之慢,以至于只是看起来处理器什么都不做,而事实上他们只是在等待发送下一位一些定义或其他。在这种情况下,我认为ParallelMap[..., Method->"CoarsestGrained"]会有所帮助。但不,那也不起作用。

一个问题:“我做的事情显然是错的,还是这个错误?”

1 个答案:

答案 0 :(得分:3)

恐怕你是。问题在于变量的共享定义。 Mathematica在内核的所有变量副本中保持单个连贯值,因此该变量成为一个巨大争用的单点。 CPU处于空闲状态,因为内核排队等待变量IndexedFunk的队列,并且大部分时间花在进程间或机器间通信上。去图。

顺便说一句,在我所知道的任何Mathematica版本中都没有函数SetSharedDefinition。您可能打算写SetSharedVariable。但无论如何要删除那个邪恶的召唤!为了避免争用,将并行计算的结果作为对列表返回,然后在主内核中将它们组合成变量的下行值:

Clear[IndexedFunk]
Scan[(IndexedFunk[#[[1]]] = #[[2]]) &, 
   ParallelMap[{#, Min[ListOfInts[#] /. rulez]} &, Range[maxIndex]]
]

ParallelMap负责自动分发定义,因此调用DistributeDefinitions是多余的。 (作为一个小注,它写得不正确,省略了maxIndex变量,但在这种特殊情况下ParallelMap会自动处理遗漏。)

编辑,NB!:自动分发仅适用于Mathematica的版本8。感谢@MikeHoneychurch进行更正。