TL;DR: Can I somehow create an algorithm that can use different functionality in the inner loop, and still get that "functionality" inlined, without resorting to copy/paste or if/else statements?
I am trying to create an algorithm that basically looks like this:
for(var i=0; i<big; i++) {
for(var j=0; j<big2; j++) {
// ... processing
var x = SomeFunc(a, b, c);
// ... more processing
}
}
I want the algorithm to be run for a number of possible functions (SomeFunc
above), each called a large number of times per run. Each SomeFunc
function is very simple (usually an arithmetic expression).
Now, to get acceptable performance out of this algorithm, it is imperative that SomeFunc
is inlined. However I fail to get the function inlined while still allowing for multiple functions.
I realize this means that the algorithm function has to be JITted multiple times, but I was hoping that a construct like this would work:
interface ISomeFunc {
int SomeFunc(int a, int b, int c);
}
private sealed class SomeFunc1 : ISomeFunc {
public int SomeFunc(int a, int b, int c) {
return ....;
}
}
private static void RunMyGenericAlgo<T>(T func) where T : ISomeFunc
{
for ... for ..
x = func.SomeFunc(a, b, c);
}
But it appears that the function call is not inlined since func
above is called via the interface and not via the sealed class.
I also tried the obvious approach:
abstract class MyAlgo {
protected abstract int SomeFunc(int a, int b, int c);
public void Run() {
// as RunMyGenericAlgo above
}
}
sealed class MyAlgoSomeFunc1 : MyAlgo {
protected override int SomeFunc(int a, int b, int c) {...}
}
and it did not inline either.
This program will however inline as desired (and runs about 50% faster):
class MyAlgo {
int SomeFunc(int a, int b, int c) {...}
public void Run() {
// as above
}
}
EDIT: To clarify, I also investigated using the MethodImpl
attribute with AggressiveInlining
, and it did not seem to help.
Is what I'm trying even possible in C# or do I have to copy/paste my algorithm for each implementation of my inner function?