Mathematica -- How to compile BitShiftRight (or Left)?
Asked Answered
P

1

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 ?

Pronty answered 22/6, 2012 at 0:11 Comment(0)
G
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.

Grangerize answered 22/6, 2012 at 2:24 Comment(2)
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...).Robbirobbia
@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).Pronty

© 2022 - 2024 — McMap. All rights reserved.