1
$\begingroup$

I have rather large equations that profit a lot from compiling, unfortunately they require input from external numerics and need to be interpolated.

In the end this costs a lot of performance as InterpolatingFunction triggers a MainEvaluate.

A minimal example:

testInt = Interpolation[{{0., 0.}, {2.5, 2.5}, {5., 5.}, {10., 10.}, {15., 
 15.}}];

testCompile = With[{testInt = testInt},
Compile[{{x, _Real}, {a, _Real}},
testInt[a*x], CompilationTarget -> "C", 
"RuntimeOptions" -> "Speed", 
CompilationOptions -> {"InlineExternalDefinitions" -> True, 
  "InlineCompiledFunctions" -> True}, 
RuntimeAttributes -> {Listable}, Parallelization -> False
]];

CompilePrint[testCompile]

Out[3]= "
    2 arguments
    4 Real registers
    Underflow checking off
    Overflow checking off
    Integer overflow checking off
    RuntimeAttributes -> {Listable}

    R0 = A1
    R1 = A2
    Result = R3

1   R2 = R1 * R0
2   R3 = MainEvaluate[ Hold[InterpolatingFunction[{{0., 15.}}, <>]][ R2]]
3   Return
"

The options are set as in the case of my application.

Is there any way to access circumvent this the non compilabilty of InterpolatingFunction by accessing for example the resulting piece wise polynomial?

$\endgroup$
  • 1
    $\begingroup$ Have you seen this? Of course there are other methods of interpolation that InterpolatingFunction supports. $\endgroup$ – Michael E2 Mar 20 '17 at 1:48
  • 2
    $\begingroup$ Possibly you could rearrange your code such that all interpolation is done before passing that result as a packed array to the compiled function? $\endgroup$ – user21 Mar 20 '17 at 10:33
  • $\begingroup$ @MichaelE2 sort of, it would boil down to writing my own compiled interpolation, which i will probably end up with. $\endgroup$ – Gebbo Mar 20 '17 at 12:26
  • $\begingroup$ @user21 I don't quite understand what you mean. $\endgroup$ – Gebbo Mar 20 '17 at 12:26
  • 1
    $\begingroup$ Yes, to be more specific the data/interpolation serves as an input for solving a differential equation and is only loaded once in the beginning. $\endgroup$ – Gebbo Mar 20 '17 at 14:43
1
$\begingroup$

Using existing code from here to extract the piece-wise polynomial from the interpolation and compile it.

data = MapIndexed[
  Flatten[{#2, #1}] &, {2, 5, 9, 15, 22, 33, 50, 70, 100, 145, 200, 280, 375, 495, 635, 800, 1000, 1300, 1600, 2000, 2450, 3050, 3750, 4600, 5650, 6950}];

intF = Interpolation@data;
pwF[x_] = Piecewise[MapIndexed[{InterpolatingPolynomial[#1, x], x < 1 First[#2] + 2} &, Most[#]], InterpolatingPolynomial[Last@#1, x]] &@Partition[data, 4, 1];
compF = With[{}, Compile[{{x, _Real}}, Evaluate[N[pwf[x]]], CompilationTarget -> "C", "RuntimeOptions" -> "Speed", RuntimeAttributes -> {Listable}, CompilationOptions -> {"InlineExternalDefinitions" -> True}]];

compF[1.]//AbsoluteTiming
pwF[1.]//AbsoluteTiming
intF[1.]//AbsoluteTiming
 {7.38984*10^-6,2.}
 {0.0000640453,2.}
 {0.0000225801,2.}

This solves the problem at hand and even speeds up the evaluation.

$\endgroup$
  • $\begingroup$ Unfortunately, at least for me in 11.2, CompilePrint shows this too is bailing out to MainEvaluate $\endgroup$ – b3m2a1 Jan 8 '18 at 20:17
  • $\begingroup$ @b3m2a1 wF = Which @@ Flatten[List[ MapIndexed[{x < 1 First[#2] + 2, InterpolatingPolynomial[#1, x]} &, Most[#]], {True, InterpolatingPolynomial[Last@#1, x]}] &@ Partition[data, 4, 1]]; then compF = With[{wF = wF}, Compile[{{x, _Real}}, wF, CompilationTarget -> "WVM", "RuntimeOptions" -> "Speed", RuntimeAttributes -> {Listable}, CompilationOptions -> {"InlineExternalDefinitions" -> True}]] $\endgroup$ – QuantumDot Jan 24 '18 at 21:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.