dsh*_*let 2 c# linq jit codedom roslyn
我正在开发一个应用程序,我想动态生成用于数值计算的代码(用于性能).将此计算作为数据驱动操作太慢.要描述我的要求,请考虑以下类:
class Simulation
{
Dictionary<string, double> nodes;
double t, dt;
private void ProcessOneSample()
{
t += dt;
// Expensive operation that computes the state of nodes at the current t.
}
public void Process(int N, IDictionary<string, double[]> Input, IDictionary<string, double[]> Output)
{
for (int i = 0; i < N; ++i)
{
foreach (KeyValuePair<string, double[]> j in Input)
nodes[j.Key] = j.Value[i];
ProcessOneSample();
foreach (KeyValuePair<string, double[]> j in Output)
j.Value[i] = nodes[j.Key];
}
}
}
Run Code Online (Sandbox Code Playgroud)
我想要做的是JIT编译一个在Process中实现外部循环的函数.定义此函数的代码将由当前用于实现ProcessOneSample的数据生成.为了澄清我的期望,我希望所有的字典查找都在编译过程中执行一次(即JIT编译将直接绑定到字典中的相关对象),这样当编译的代码实际上是执行后,好像所有查找都已经过硬编码.
我想弄清楚的是解决这个问题的最佳工具.我问这个问题的原因是因为有很多选择:
有没有人有这样的经验可以分享?
我不确定我理解你的例子,也不知道代码生成是提高它性能的最好方法.
但是,如果您想了解代码生成选项,请首先考虑您的要求.性能是您想要的,但代码生成的性能和生成的代码的性能.这些定义不一样.然后是代码的可写性和可读性.不同的选项在这个上有很不同的分数.
你的第一个选择是Reflection.Emit,尤其是DynamicMethod.Reflection.Emit是一个非常低级的API,非常高效(即代码生成具有良好的性能).此外,因为您可以完全控制生成的代码,所以您有可能生成最有效的代码(或者显然生成非常糟糕的代码).此外,您不仅限于C#等语言允许的操作,CLR的全部功能都在您的指尖.Reflection.Emit的最大问题是需要编写大量代码,并且需要深入了解IL.编写代码并不容易,之后也不会阅读或维护代码.
Linq.Expressions,更具体地说是Compile方法提供了一个不错的选择.您可以将此视为基本上是使用Reflection.Emit围绕DynamicMethod生成的类型安全包装器.生成代码有一些开销,这可能不是一个大问题.至于表达自由,你几乎可以用普通的C#方法做所有事情.您无法完全控制生成的代码,但质量通常非常好.这种方法的最大优点是使用这种技术编写和读取程序要容易得多.
对于Roslyn,您可以选择生成语法树,或生成C#(或VB)并将其解析为要编译的语法树.由于我们没有可用的生产代码(在撰写本文时),因此可以尽早猜测性能可能是什么.显然,解析语法树会产生一些开销,如果你生成一个单一的方法,Roslyn在paralle中生成多个方法的能力将无济于事.使用Roslyn有可能允许非常易读的程序.
对于CodeDom,我建议反对它.这是一个非常古老的API,(在当前实现中)启动CSC.exe进程来编译代码.我也相信它不支持完整的C#语言.
归档时间: |
|
查看次数: |
1044 次 |
最近记录: |