7

I want to compile a Mathematica module because I am after speed.

    testC = Compile[{{inputInt, _Integer}},
      Module[{outputInt, bitShift = 5},
      outputInt = BitShiftRight[inputInt, bitShift]
      ]
      , CompilationTarget -> "C", RuntimeOptions -> "Speed"
      , CompilationOptions -> {"ExpressionOptimization" -> True, 
       "InlineCompiledFunctions" -> True, 
       "InlineExternalDefinitions" -> True}
    ];

My real function is longer but has a very simple structure, uses lists, and only contains the following function: Total, Table, BitAnd, If. All the Compilation and Runtime options are useful (maybe) in my real function, not this one line extract.

I have set

SetSystemOptions["CompileOptions" -> "CompileReportExternal" -> True];

to make sure I can see what happens, and

CompilePrint[testC]

gives the following result

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

    I0 = A1
    I1 = 5
    Result = I2

    1   I2 = MainEvaluate[ Hold[BitShiftRight][ I0, I1]]
    2   Return

As expected/feared from this thread https://mathematica.stackexchange.com/a/1101/1403 BitShiftRight is not compilable, and this call to MainEvaluate is a serious drag on my function. I am extremely surprised that this sort of very low level, common function is not compilable while BitAnd, BitNot, BitOr, BitXor are ! Does anybody know of a (fast) workaround ? I can use a MathLink call to a C language function, but my objective is to use this function in a Manipulate[ ] and deploy it as a stand alone cdf file. And I understand that in this context I cannot use MathLink, correct ? By the way, is there some tractable workaround there ?

Community
  • 1
  • 1
Oscar6E
  • 106
  • 4

1 Answers1

3

If you divide by 32, the compiler will likely rewrite this as a shift. You should also try dividing by 32 in Mathematica directly, making sure your data is and stays packed (Developer`ToPackedArray[]). The overhead of sending the data back and forth probably won't be worth the benefit of computing in C.

Joshua Martell
  • 7,074
  • 2
  • 30
  • 37
  • Just to confirm (and slightly modify), if you use Quotient it will compile sans external evaluator calls. In the simple example, the appropriate line would be outputInt = Quotient[inputInt, 2^bitShift]]. If your shift length is a fixed constant, the powering should be done at compile time (probably you both knew that...). – Daniel Lichtblau Jun 22 '12 at 17:13
  • @Daniel: Your solution solves my pb. Thx! Then the compiled code is `I3 = Quotient[ I0, I2]`. If I just divide by 2^5, I need to Round[] the result to cast it into an Integer. Then the compile code is `R1 = Reciprocal[ R0] ` `R0 = I0` `R0 = R0 * R1` `I3 = Round[ R0]` (longer, less efficient). – Oscar6E Jun 25 '12 at 23:28