for循环的优化

S_B*_*Man 4 .net c# optimization c#-4.0

大家好,我正在编写一些目前应该尽可能快地运行的c#代码,通常占用100%的单个核心大约25分钟.我需要代码保持单核心,因为跨多个核心运行此代码的好处不会像同时多次运行此项目一样好

有问题的代码如下

public Double UpdateStuff(){

    ClassA[] CAArray = ClassA[*a very large number indeed*];
    Double Value = 0;
    int length = CAArray.Length;

    for (int i= 0; i< length ; i++)
        {
         Value += CAArray[i].ClassB.Value * CAArray[i].Multiplier;
        }  
    return Value;
}
Run Code Online (Sandbox Code Playgroud)

根据分析器,代码的这个区域负责应用程序的78%负载,因此似乎是优化的良好候选者.

!!!注意:该函数已从返回类型void更改为返回类型Double,这是伪代码而不是实际代码,以便于阅读

澄清:.net,c#4.0,visual studio 2010,目标机器:windows server 2008 x64

编辑:进一步澄清:此上下文中的所有变量都是公共的而不是属性.CAArray [i] .ClassB.Value中的值将永远改变不能匹配的双精度数.

MgS*_*Sam 10

你应该删除这个:

int length = CAArray.Length;
Run Code Online (Sandbox Code Playgroud)

并用这个替换循环:

for (int i= 0; i < CAArray.Length; i++)
{
    Value += CAArray[i].ClassB.Value * CAArray[i].Multiplier;
} 
Run Code Online (Sandbox Code Playgroud)

像原始代码一样存储长度确实会降低 C#代码的速度(反直觉,我知道).这是因为如果您在for循环中直接使用Array.Length,则抖动将跳过对循环的每次迭代执行数组边界检查.

另外,我强烈建议将此过程并行化.最简单的方法是

CAArray.AsParallel().Sum(i => i.ClassB.Value * i.Multiplier);
Run Code Online (Sandbox Code Playgroud)

虽然没有LINQ 你可能获得更快的速度(尽管你需要担心管理多个线程的低级细节).


Red*_*ter 6

尝试:

for (int i = 0; i < length; i++)
{
    var a = CAArray[i];
    Value += a.ClassB.Value * a.Multiplier;
}  
Run Code Online (Sandbox Code Playgroud)

  • 迭代循环中只有*one*index访问权限. (2认同)
  • @jonnyGold只有当你真正需要变量时才能声明变量是一个好习惯 - 提高可读性并且显然不会达到性能(几乎从不). (2认同)

Sim*_*Var 6

一个区别是在for循环中使用临时变量来保存当前值.

第二个区别,可能更重要的是,将CAArray.Length放入for循环边界而不是count.编译器优化这样的循环以消除边界检查.

for (int i = 0; i < CAArray.Length; i++)
{
    var curr = CAArray[i];
    Value += curr.ClassB.Value * curr.Multiplier;
}
Run Code Online (Sandbox Code Playgroud)

您可以做的另一件事是将ClassB,ClassB.Value和Multiplier属性作为字段,如果可以的话.

最后 - 记得检查解决方案属性中的"优化代码",让编译器优化代码.