CompiledFunctionCall WVM操作码是否有效?


15

有例如Mathematica的文档中大约Compile

cf = Compile[{{x}}, Sin[x]]; 
cf5 = Compile[ {{x}}, cf[x^2], 
    CompilationOptions -> {"InlineExternalDefinitions" -> True, 
    "InlineCompiledFunctions" -> False}]; 

上面的代码使得"InlineCompiledFunctions"False,从而防止内联。如果我们着眼于CompilePrint输出,

<<CompiledFunctionTools' 
CompilePrint[cf5] 

 1 argument 
     3 Real registers 
     Underflow checking off 
     Overflow checking off 
     Integer overflow checking on 
     RuntimeAttributes -> {} 

     R0 = A1 
     Result = R2 

1 R1 = Square[ R0] 
2 R2 = CompiledFunctionCall[ Hold[CompiledFunction[{x}, Sin[x], -CompiledCode-]][ R1]] 
3 Return 

有一个CompiledFunctionCall操作码。 我不知道这个调用是否和“inline”版本一样高效。文件没有说。

我在这里引用了一段,我不太明白。

这里使用外部定义,但编译的函数不是内嵌的 。相反,它使用有效的指令来允许一个编译的函数调用另一个函数。这种类型的调用很重要,因为它可以允许编译函数自行调用,并且在编译器中执行并行执行时,可以在没有任何同步锁定的情况下调用 。

这是什么意思?它说“它可以允许编译的函数自己调用”。但是在编译函数是递归调用的相同文档中有一个例子。例如,

cFact = Compile[{{x, _Integer}}, If[x == 1, 1, x*cFact[x - 1]], 
    {{_cFact, _Integer}}, 
    CompilationOptions -> {"InlineExternalDefinitions" -> True}]; 
CompilePrint[cFact] 

,什么是“同步锁定”

20

Wolfram虚拟机的CompiledFunctionCall操作码是让一个编译函数调用另一个的快速方法。速度优势很大程度上是因为可以在不离开虚拟机的情况下进行呼叫。

有时内联可以很快,特别是对于函数体非常小的函数,但是您只需要测试两种方法来知道哪个更好。

这就是为什么文档没有说哪一个更快 - 这取决于你运行的代码。

至于同步锁定:

当虚拟机是在并行线程中运行并且需要调用该数学评估器时,它首先必须执行“同步锁定”。想象一下,平行线程是可以完成工作的房间,它们通向走廊,大厅尽头是评估室。规则是一次只有一个人可以进入评估室,为了执行此操作,评估室的门锁定。如果某人在并行线程间并需要使用评估者房间,则他们离开他们的房间,并且如果评估者房间是空的,他们进入并锁定门(这种行为称为“同步锁定”),执行他们的工作,打开门并离开。您可以看到,如果其他人需要使用评估室,但他们无法进入,需要等待。这种等待会减慢速度。该段落解释说,如果您需要评估程序的唯一原因是调用另一个编译函数,则CompiledFunctionCall操作码的这一新功能意味着您可以在不离开并行线程的情况下执行此操作,并避免由于同步锁定而等待的可能性。

  0

此答案明确说明了文档中写的内容 - 感谢和+1。但是,理想情况下,我希望看到文档本身在未来得到澄清,因为缺少您的答案,线程在这里应该同步的内容并不明显。实际上,我不确定这个互斥体是否被实现,但至少对于使用操作码46或47的调用,因为这些产生了带有“并行化 - >真”的“CompiledFunction :: pext”。只有操作码43似乎是允许的,这似乎使关于同步的讨论无关紧要,因为没有任何显然发生。 05 1月. 142014-01-05 06:05:26

+1

我无法得到一个递归编译函数来工作(也就是说,创建一个函数,更不用说它并行化 - 它会产生大量嵌套的操作码46调用,并且根本不使用43 )。所以,除非我错过了重要的东西,就文档而言,关于同步和递归点的注释似乎都不是什么限制因素,因为这些功能实际上并未在当前版本中实现? 05 1月. 142014-01-05 07:07:23