Wolfram mathematica 如何并行设置变量/函数定义(例如,使用ParallelMap)?

Wolfram mathematica 如何并行设置变量/函数定义(例如,使用ParallelMap)?,wolfram-mathematica,Wolfram Mathematica,我有一个函数,用于根据索引查找值。该值需要一些时间来计算,因此我想使用ParallelMap,并引用另一个类似的函数,该函数返回表达式列表,也基于索引 然而,当我以一种似乎合理的方式设置它时,我看到一些非常奇怪的行为。首先,我看到这个函数似乎在工作,尽管速度很慢。但是,对于大型索引,Taskmangler中的处理器活动在很长一段时间(即2-4分钟)内完全保持为零,而Mathematica的所有实例似乎都是惰性的。然后,在没有任何CPU使用的情况下,就会出现一个结果。这是Mathematica的另

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

然而,当我以一种似乎合理的方式设置它时,我看到一些非常奇怪的行为。首先,我看到这个函数似乎在工作,尽管速度很慢。但是,对于大型索引,Taskmangler中的处理器活动在很长一段时间(即2-4分钟)内完全保持为零,而Mathematica的所有实例似乎都是惰性的。然后,在没有任何CPU使用的情况下,就会出现一个结果。这是Mathematica的另一个例子吗

也就是说,我想创建一个存储表达式的变量/函数,这里是一个整数列表(
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的相似之处,所以我对这个结论不能太有信心。尽管它的速度慢得令人沮丧,但它在不需要CPU的情况下执行计算的能力令人印象深刻

我认为这可能是因为主进程和从进程之间使用了任何通信协议,可能是因为它太慢了,以至于处理器似乎什么也没做,而实际上它们只是在等待发送某个定义或其他定义的下一位。在这种情况下,我认为
ParallelMap[…,Method->“粗粒度”]
会有一些用处。但是不,那也不行


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

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

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

Clear[IndexedFunk]
Scan[(IndexedFunk[#[[1]]] = #[[2]]) &, 
   ParallelMap[{#, Min[ListOfInts[#] /. rulez]} &, Range[maxIndex]]
]
ParallelMap
负责自动分发定义,因此调用
DistributeDefinitions
是多余的。(作为一个次要的注意事项,它并不像写的那样正确,省略了
maxIndex
变量,但是在这种特殊情况下,
ParallelMap
会自动处理这个省略。)


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

在DistributedDefinitions[…]中,您是打算
列出要点
还是应该是
列出要点
?作为一个评论/问题,我认为您关于
DistributedDefinitions
的评论是多余的,仅适用于V8+对吗,我相信V8会自动分发定义。@kkm,是的,您的解决方案也是我得出的。我只是希望使用SharedFunction(而不是如您所注意到的SetSharedDefinition)会自动为我处理函数定义。但我不明白你怎么知道共享定义会引起争论。您是否认为每次向IndexedFunk添加新的downvalue时,都必须将其重新传输到所有内核?虽然这是有道理的,但为什么TaskManager中根本没有出现这种情况?@kkm:那么,你会说这种奇怪的行为(在没有CPU活动的情况下徘徊数分钟)之所以发生,是因为我从文档(ParallelTools/tutorial/VirtualSharedMemory)中为IndexedFunk指定了一百万个不同的下行值:共享变量的缺点是每次读写访问都需要通过网络进行通信,因此它比访问本地非共享变量慢。共享函数大致相同:定义保存在主内核中,并通过网络发送到正在计算的内核。跨进程通信确实很昂贵,所以我认为会出现像你所描述的那种奇怪的情况。(很抱歉进行了多次编辑,尚未用于该界面。)