我怎样才能内心化我的内心功能?

时间:2014-08-12 10:35:53

标签: c# inline

TL; DR :我可以以某种方式创建一个可以在内循环中使用不同功能的算法,并且仍然可以获得"功能"内联,无需借助复制/粘贴或if / else语句?

我正在尝试创建一个基本上如下的算法:

for(var i=0; i<big; i++) {
  for(var j=0; j<big2; j++) {
     // ... processing
     var x = SomeFunc(a, b, c);
     // ... more processing
  }
}

我希望算法能够运行许多可能的函数(上面SomeFunc),每次运行都会调用很多次函数。每个SomeFunc函数都非常简单(通常是算术表达式)。

现在,为了从该算法中获得可接受的性能,必须内联SomeFunc。但是我仍然没有内联函数,同时仍然允许多个函数。

我意识到这意味着算法函数必须被多次JIT,但我希望像这样的构造能够工作:

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);
}

但似乎函数调用没有内联,因为上面的func是通过接口而不是通过密封类调用的。

我也尝试过这种明显的方法:

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) {...}
}

它也没有内联。

然而,该程序将根据需要内联(并且运行速度提高约50%):

class MyAlgo {
   int SomeFunc(int a, int b, int c) {...}
   public void Run() {
     // as above
   }
}

编辑:要澄清,我还调查了使用MethodImpl AggressiveInlining属性进行调查,但似乎没有帮助。

我在C#中尝试甚至是可能的,还是我必须为我的内部函数的每个实现复制/粘贴算法?

1 个答案:

答案 0 :(得分:2)

要允许内联方法,实现必须是常量(例如,不依赖于变量)。因此,任何形式的虚拟/抽象/接口/委托调用都是一个永远不能内联的调用。 因此,唯一的方法是进行非虚方法调用,或者只是将代码粘贴到那里。

此规则有一些例外情况。例如,JVM设计人员存在默认情况下所有Java方法都是虚拟的问题,它们具有虚拟调用内联。这将做类似的事情:

//calling obj.MyVirtCall();
if (obj.Type == MyCommonType) {
    //inlined code for MyCommonType.MyVirtCall();
} else {
    obj.MyVirtCall();
}

修改 您可以使用T4 templates为算法示例中的每个Run覆盖生成C#代码,不需要重复代码,但是它可能会使维护稍微复杂一些,还必须维护T4模板而不是只是C#代码。