Насколько эффективен код операции 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 опкод. Я не знаю, эффективен ли этот вызов так же, как и встроенная версия. В документации не говорилось.

Я цитирую параграф, который я не совсем понимаю.

Здесь используется внешнее определение, но скомпилированная функция не является inlined. Вместо этого он использует эффективную инструкцию, чтобы одна компиляционная функция вызывала другую. Этот тип вызова важен , поскольку он может позволить скомпилированной функции вызывать себя, а при выполнении в компиляторе параллельного выполнения выполняется без блокировки синхронизации.

Что это значит? В нем говорится, что «это может позволить скомпилированной функции вызывать себя». Но есть пример в той же документации, где скомпилированная функция является рекурсивным вызовом. Например,

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

И что "Синхронизация блокировки"?

20

Операционный код CompiledFunctionCall виртуальной машины Wolfram - это быстрый способ позволить одной скомпилированной функции вызвать другую. Преимущество скорости в значительной степени связано с тем, что вызов может быть выполнен без выхода из виртуальной машины.

Иногда встраивание может быть быстрым, особенно для функций с очень маленькими функциональными органами, но вам просто нужно проверить оба способа узнать, что лучше.

Именно поэтому в документации не указано, какой из них быстрее - это зависит от кода, который вы используете.

Как блокировки синхронизации:

Когда виртуальная машина работает в параллельном потоке и нужно вызвать оценщика Mathematica, он сначала должен выполнить «синхронизации» блокировку. Представьте себе, что параллельные потоки - это комнаты, где можно сделать работу, они открываются в коридор, а в конце зала находится комната оценщика. Правило состоит в том, что за один раз может быть только один человек в комнате оценщика, и для обеспечения этого есть замок на двери в комнату оценщика. Если кто-то находится в комнате с параллельным потоком и должен использовать комнату оценщика, они покидают свою комнату, и если комната оценщика пуста, они входят, блокируют дверь (этот акт называется «синхронизация блокировки»), выполняют свою работу, откройте дверь и уходите. Вы можете видеть, что если кто-то еще должен использовать комнату оценщика, когда он уже используется, они не могут войти, и им нужно подождать. Это ожидание замедляет работу.В параграфе объясняется, что если единственной причиной, по которой вам нужен оценщик, является вызов другой скомпилированной функции, эта новая функция кода операции CompiledFunctionCall означает, что вы можете сделать это, не выходя из параллельного потока, и избегать возможности ожидания из-за блокировки синхронизации.

  0

Этот ответ определенно разъясняет, что написано в документации - спасибо и +1. Но, в идеале, я бы хотел, чтобы сама документация была прояснена в будущем, так как вы отсутствуете в своем ответе, совсем не очевидно, что здесь должны синхронизировать потоки. На самом деле, я не уверен, что этот мьютекс был даже реализован [хотя], по крайней мере для вызовов с использованием кода операции 46 или 47, поскольку они создают 'CompiledFunction :: pext' с' Parallelization -> True'. По-видимому, допустим только код операции 43, который, по-видимому, делает это обсуждение о синхронизации неактуальным, поскольку, по-видимому, это не происходит. 05 янв. 142014-01-05 06:05:26

+1

Мне не удалось получить рекурсивную скомпилированную функцию для работы (то есть, чтобы создать ее, а тем более ее распараллелить), она генерирует большой беспорядок вложенных вызовов кода opcode 46 и, похоже, не использует 43). Итак, если мне не хватает чего-то важного, что касается документации, и комментарий о синхронизации и рекурсии кажется нелогичным, поскольку эти функции фактически не реализованы в текущей версии? 05 янв. 142014-01-05 07:07:23