我已经写了一个小的控制台测试类来衡量这个效果.我初始化一个static double []数组项,两个方法对它执行循环操作,将结果写入静态double []数组缓冲区.最初,我的方法是我注意到差异的方法,即复数的幅度计算.对于长度为1000000的项目数组运行这些数组100次,对于循环中变量(6个双变量)的运行时间一直较低,例如:32,83±0,64 ms v 43,44使用Intel Core 2 Duo @ 2.66 GHz的老年人配置为±0,45 ms.我尝试以不同的顺序执行它们,但并不影响结果.
然后我意识到,计算一个复数的大小远远不是一个最小的工作实例,并且测试了两个更简单的方法:
static void Square1() { double x; for (int i = 0; i < buffer.Length; i++) { x = items[i]; buffer[i] = x * x; } } static void Square2() { for (int i = 0; i < buffer.Length; i++) { double x; x = items[i]; buffer[i] = x * x; } }
有了这些,结果出来了另一种方式:声明环外的变量似乎更有利:对于Square2(),Square1()v为7.07±0.43 ms为12.07±0.51 ms.
我不熟悉ILDASM,但是我已经拆卸了两种方法,唯一的区别似乎是局部变量的初始化:
.locals init ([0] float64 x,[1] int32 i,[2] bool CS$4$0000)
在Square1()v
.locals init ([0] int32 i,[1] float64 x,[2] bool CS$4$0000)
在Square2()中.根据它,stloc.1在一个是stloc.0在另一个,反之亦然.在较长的复数量级计算中,MSIL代码甚至代码大小不同,我在内部声明代码中存在stloc.0的外部声明代码中看到了stloc.s i.
那怎么可能呢?我是忽略某些东西还是真正的效果?如果是这样,它可以在长循环的性能上有显着差异,所以我认为它值得一些讨论.
你的想法非常感激.
编辑:我忽略的一件事是在发布之前在几台电脑上进行测试.我现在在i5上运行它,两种方法的结果几乎相同.对于发表了这样的误导性观察,我深表歉意.
解决方法
所以保持double x;内部循环,如果可能的话.
不过,如果项目[i]是普通数据数组访问,那么我会写缓冲区[i] =项目[i] *项目[i]. C和C会优化,但我不认为C#是(还);你的拆卸意味着它没有.