5
$\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$
6
  • 1
    $\begingroup$ Have you seen this? Of course there are other methods of interpolation that InterpolatingFunction supports. $\endgroup$
    – Michael E2
    Commented Mar 20, 2017 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
    Commented Mar 20, 2017 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$
    – NicolasW
    Commented Mar 20, 2017 at 12:26
  • $\begingroup$ @user21 I don't quite understand what you mean. $\endgroup$
    – NicolasW
    Commented Mar 20, 2017 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$
    – NicolasW
    Commented Mar 20, 2017 at 14:43

1 Answer 1

3
$\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$
2
  • $\begingroup$ Unfortunately, at least for me in 11.2, CompilePrint shows this too is bailing out to MainEvaluate $\endgroup$
    – b3m2a1
    Commented Jan 8, 2018 at 20:17
  • 1
    $\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
    Commented Jan 24, 2018 at 21:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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