Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 动态编译以提高性能_C#_Performance_Code Generation_Dynamic Compilation - Fatal编程技术网

C# 动态编译以提高性能

C# 动态编译以提高性能,c#,performance,code-generation,dynamic-compilation,C#,Performance,Code Generation,Dynamic Compilation,我知道如何通过动态代码生成来提高性能,但我不确定哪种方法是解决此问题的最佳方法 假设我有一节课 class Calculator { int Value1; int Value2; //.......... int ValueN; void DoCalc() { if (Value1 > 0) { DoValue1RelatedStuff(); } if (Value2 > 0) { DoVal

我知道如何通过动态代码生成来提高性能,但我不确定哪种方法是解决此问题的最佳方法

假设我有一节课


class Calculator
{
  int Value1;
  int Value2;
  //.......... 
  int ValueN;

  void DoCalc()
  {
    if (Value1 > 0)
    {
      DoValue1RelatedStuff();    
    }
    if (Value2 > 0)
    {
      DoValue2RelatedStuff();    
    }
    //....
    //....
    //....
    if (ValueN > 0)
    {
      DoValueNRelatedStuff();    
    }
  }
}
DoCalc方法处于最低级别,在计算过程中多次调用。另一个重要方面是,ValueN仅在开始时设置,在计算过程中不会更改。因此,DoCalc方法中的许多ifs都是不必要的,因为ValueN的许多ifs都是0。所以我希望动态代码生成能够帮助提高性能

例如,如果我创建一个方法


  void DoCalc_Specific()
  {
    const Value1 = 0;
    const Value2 = 0;
    const ValueN = 1;

    if (Value1 > 0)
    {
      DoValue1RelatedStuff();    
    }
    if (Value2 > 0)
    {
      DoValue2RelatedStuff();    
    }
    ....
    ....
    ....
    if (ValueN > 0)
    {
      DoValueNRelatedStuff();    
    }
  }
并在打开优化的情况下编译,C#编译器足够聪明,只保留必要的东西。因此,我希望在运行时基于ValueN的值创建这样的方法,并在计算过程中使用生成的方法

我想我可以使用表达式树,但是表达式树只适用于简单的lambda函数,所以我不能在函数体中使用if、while等。因此,在这种情况下,我需要以适当的方式更改此方法

另一种可能是将必要的代码创建为字符串并动态编译。但是如果我能采用现有的方法并相应地修改它,对我来说会更好

还有反射。发射,但我不想坚持使用它,因为它很难维护

顺便说一句,我并不局限于C。所以我愿意接受最适合这种问题的编程语言的建议。除了LISP之外,还有几个原因

一个重要的澄清。DoValue1RelatedStuff()不是我的算法中的方法调用。这只是一些基于公式的计算,速度非常快。我应该这样写的


if (Value1 > 0)
{
  // Do Value1 Related Stuff
}
我已经运行了一些性能测试,我可以看到在禁用一个ifs时,使用两个ifs时,优化方法的速度大约是使用冗余if时的2倍

以下是我用于测试的代码:


    public class Program
    {
        static void Main(string[] args)
        {
            int x = 0, y = 2;

            var if_st = DateTime.Now.Ticks;
            for (var i = 0; i  < 10000000; i++)
            {
                WithIf(x, y);
            }
            var if_et = DateTime.Now.Ticks - if_st;
            Console.WriteLine(if_et.ToString());

            var noif_st = DateTime.Now.Ticks;
            for (var i = 0; i  < 10000000; i++)
            {
                Without(x, y);
            }
            var noif_et = DateTime.Now.Ticks - noif_st;
            Console.WriteLine(noif_et.ToString());

            Console.ReadLine();

        }

        static double WithIf(int x, int y)
        {
            var result = 0.0;
            for (var i = 0; i  < 100; i++)
            {
                if (x > 0)
                {
                    result += x * 0.01;
                }
                if (y > 0)
                {
                    result += y * 0.01;
                }
            }
            return result;
        }

        static double Without(int x, int y)
        {
            var result = 0.0;
            for (var i = 0; i < 100; i++)
            {
                result += y * 0.01;
            }
            return result;
        }
    }

公共课程
{
静态void Main(字符串[]参数)
{
int x=0,y=2;
var if_st=DateTime.Now.Ticks;
对于(变量i=0;i<10000000;i++)
{
带if(x,y);
}
var if_et=DateTime.Now.Ticks-if_st;
Console.WriteLine(if_et.ToString());
var noif_st=DateTime.Now.Ticks;
对于(变量i=0;i<10000000;i++)
{
没有(x,y);
}
var noif_et=DateTime.Now.Ticks-noif_st;
Console.WriteLine(noif_et.ToString());
Console.ReadLine();
}
带IF的静态双精度(整数x,整数y)
{
var结果=0.0;
对于(变量i=0;i<100;i++)
{
如果(x>0)
{
结果+=x*0.01;
}
如果(y>0)
{
结果+=y*0.01;
}
}
返回结果;
}
不带(整数x,整数y)的静态双精度
{
var结果=0.0;
对于(变量i=0;i<100;i++)
{
结果+=y*0.01;
}
返回结果;
}
}

我会惊讶地发现,在这种情况下,评估if语句的开销值得动态发出代码

现代CPU对和的支持,使得代码小段中的分支开销接近于零


您是否尝试过对代码的两个手工编码版本进行基准测试,一个包含所有if语句,但大多数都提供零值,另一个删除所有相同的if分支?

我通常不会考虑这样的优化。
DoValueXRelatedStuff()
要做多少工作?超过10到50个处理器周期?对这意味着您将要构建一个相当复杂的系统,以节省不到10%的执行时间(这在我看来是非常乐观的)。这很容易降到1%以下

没有其他优化的空间吗?更好的算法?如果分支预测是正确的,您真的需要消除只占用单个处理器周期的单个分支吗?对您不应该考虑用汇编程序或其他更特定于机器的东西来编写代码,而不是使用.NET吗


您能给出
N
的顺序、典型方法的复杂性以及通常计算为true的表达式的比率吗?

如果您真的对代码优化感兴趣,请先运行探查器!它将告诉您瓶颈在哪里,哪些方面值得优化

另外-如果语言选择不受限制(LISP除外),那么就性能而言,没有什么能打败汇编程序;)

我记得通过使用汇编程序重写一些内部函数(如您拥有的函数)实现了一些性能魔法。

在您做任何事情之前,您是否真的有问题

i、 它跑的时间够长吗

如果是这样的话,找出真正需要时间的是什么,而不是你的猜测。是我用来判断时间流逝的快速、肮脏和高效的方法

现在,你谈论的是口译还是编译。解释代码通常比编译代码慢1-2个数量级。原因是解释器不断地计算下一步要做什么,然后忘记,而编译的代码只是知道而已


如果您处于这种情况,那么为获得编译代码的速度而付出翻译的代价可能是有意义的。

我同意,N必须是数百,如果不是数千,并且大多数情况在实践中需要省略,我已经有好几年没有在ASM/IL级别做太多工作了,但我相信当前的英特尔处理器将预先决定