.NET 求和的效率

昨日,写了篇文章《.NET 4:并行求和不爽》,得到大家的热心回复,受大家启发,逐步发现了并行求和效率不要的两个原因:

  1. 我用的是伪四核 CPU;
  2. .NET 求和(非并行)效率问题。

今天,就看下 .NET 求和的效率问题。这里不是要和 c、c++等其它语言进行对比,而是对 .NET 中各种求和方式的相对比较。

.NET 中求和有多种方式,可以用 Linq 中的 Sum 扩展方法,也可使用 foreach、for 等。

准备测试数据

先准备用来测试求和的数组:

1
2
3
4
var random = new Random();
var data = Enumerable.Range(1, 67108864)
    .Select(i => (long)random.Next(int.MaxValue))
    .ToArray();

一个很大的长整型数组,装满了随机数,生成大约用 5 秒。

数组求和

我想到的求和方法有下面 5 种,使用 Stopwatch 计时:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Stopwatch watch = new Stopwatch();
//Enumerable.Sum
watch.Start();
var sum1 = data.Sum();
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
//foreach
watch.Restart();
var sum2 = 0L;
foreach (var d in data)
    sum2 += d;
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
//for Enumerable.Count
watch.Restart();
var sum3 = 0L;
for (int i = 0; i < data.Count(); i++) 
    sum3 += data[i];
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
//for Length
watch.Restart();
var sum4 = 0L;
for (int i = 0; i < data.Length; i++)
    sum4 += data[i];
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
//for 常数 
watch.Restart();
var sum5 = 0L;
for (int i = 0; i < 67108864; i++)
    sum5 += data[i];
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);

分别是使用 Enumerable.Sum、foreach、for,for 循环又根据结束条件分成了三个。

以下是测试结果:

 12345678910
Enumerable.Sum651706640652640644645669649652
foreach406431400412403410406409418405
for Enumerable.Count16532168831710016668168101763617413170121756717655
for Length341338356349341338304338339337
for 常数299293306315298295301296296297

(单位:毫秒)

从上面表格中可以看出:

  • Enumerable.Count 方式效率最差
  • 另外两种 for 循环效率要高于 foreach, 远高于 Enumerable.Sum

列表求和

将前面的代码简单修改,即可用来测试列表 (List<T>)求和

得到的测试结果如下:

 12345678910
Enumerable.Sum766693703974704971699966978751
foreach698707693682741706686697700709
for Enumerable.Count1565157015551562155917001565168415481752
for Length759772761750749788786774747762
for 常数609595590588594625592616590598

(单位:毫秒)

同样 Enumerable.Count 方式效率最差。

其他几中方式效率相差不太(相对于数组求和)。

总结

同是求和,不同和方式、不同的数据源有不同的效率。

这种效率差异在大规模计算时比较明显,少量计算则可忽略(毫秒级或微秒级的)。

 

说明:for + Enumerable.Count 的方式之以最慢,是因为每次循环都要调用 Enumerable.Count 方法(可从反编译的 IL 得知)。Enumerable.Count 方法本身效率不错,但经过近七千万次调用,落后 17 秒也是正常的,平均到每次也就 0.25 微秒(毫秒的千分之一)。常规使用,完全可以忽略,希望大家不要对 Enumerable.Count 产生误解。

有了这些测试数据,《.NET 4:并行求和不爽》一文中最后提出的问题也就很容易解答了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值