【问题标题】:c# IF performance optimizationc# IF性能优化
【发布时间】:2018-07-03 10:18:21
【问题描述】:

对于数百万个循环,哪种方法更快?

双a、b、c、d、e、f;

1.

for (int i=0; i<1000000; i++)
{
  // simulation which changes the a,b,c,d,e,f values
  ...
  if (a>b)
  {
     if (c<d)
     {
       if (e==f)
         // do something
     }
  }
}

2.

for (int i=0; i<1000000; i++)
{
   // simulation which changes the a,b,c,d,e,f values
   ...
   if ((a>b) && (c<d) && (e==f))
     // do something
}

我在想方法 1 会更快,因为它会跳过很多 if 比较,而不是每次都比较所有 3 个变量。

【问题讨论】:

  • 嗯,数百万个循环的想法似乎不是最好的方法
  • 这是一个技巧问题吗?他们都将永远使用while (1) 或直到外部终止。
  • while (1): 这个应该怎么编译,1不是bool
  • 你应该阅读&amp;&amp;-operator,尤其是关于“短路”评估的部分

标签: c# .net performance if-statement optimization


【解决方案1】:

这(可能)是一个完全不切实际的测试,但你去吧

基准测试

Mode             : Release (64Bit)
Test Framework   : .NET Framework 4.7.1

Operating System : Microsoft Windows 10 Pro
Version          : 10.0.17134

CPU Name         : Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz
Description      : Intel64 Family 6 Model 42 Stepping 7

Cores (Threads)  : 4 (8)      : Architecture  : x64
Clock Speed      : 3401 MHz   : Bus Speed     : 100 MHz
L2Cache          : 1 MB       : L3Cache       : 8 MB

Benchmarks Runs : Inputs (1) * Scales (1) * Benchmarks (3) * Runs (1000) = 3,000

结果

--- Standard input --------------------------------------------------------
| Value  |   Average |   Fastest |     Cycles |  Garbage | Test |    Gain |
--- Scale 1,000,000 --------------------------------------- Time 28.630 ---
| Bit    |  9.120 ms |  8.332 ms | 31,041,747 | 7.477 KB | N/A  | 37.59 % |
| Single | 14.549 ms | 13.815 ms | 49,549,071 | 7.541 KB | N/A  |  0.45 % |
| Multi  | 14.615 ms | 13.806 ms | 49,730,909 | 7.545 KB | Base |  0.00 % |
---------------------------------------------------------------------------

测试数据

private List<Tuple<double, double, double, double, double, double>> GenerateInput(int scale)
{
   var list = Enumerable.Range(0, scale)
                        .Select(x => new Tuple<double, double, double, double, double, double>(Rand.Next(), Rand.Next(), Rand.Next(), Rand.Next(), Rand.Next(), Rand.Next()))
                        .ToList();
   return list;
}

多重

public class Multi : Benchmark<List<Tuple<double, double, double, double, double, double>>, int>
{
   protected override int InternalRun()
   {
      int i = 0;
      foreach (var item in Input)
         if (item.Item1 > item.Item2)
            if (item.Item3 < item.Item4)
               if (item.Item5 == item.Item6)
                  i++;

      return i;
   }    
}

单身

public class Single : Benchmark<List<Tuple<double, double, double, double, double, double>>, int>
{
   protected override int InternalRun()
   {
      int i = 0;
      foreach (var item in Input)
         if ((item.Item1 > item.Item2) && (item.Item3 < item.Item4) && (item.Item5 == item.Item6))
            i++;

      return i;
   }
}

比特

public class Bit : Benchmark<List<Tuple<double, double, double, double, double, double>>, int>
{
   protected override int InternalRun()
   {
      int i = 0;
      foreach (var item in Input)
         if ((item.Item1 > item.Item2) & (item.Item3 < item.Item4) & (item.Item5 == item.Item6))
            i++;

      return i;
   } 
}

【讨论】:

  • 谢谢!所以看起来 Bit 更快,也跳过了更多比较
  • @MarioM 是的,我只是进行了更多比较,结果中单和多可以互换,我的 cpu 上的位总是快 35% 左右
  • 35% 对我的项目来说已经很多了!完成模拟需要几个小时,并且 IF 占用了大部分 CPU,其中也有 6 个,但我用 3 个使问题更简单
【解决方案2】:

你错了。 C# 的 &amp;&amp; operator 使用名为 short-circuit evaluation 的东西。

很明显,在评估a &amp;&amp; b 时,如果afalse,则计算机不会费心评估b

两个 sn-ps 的性能应该相同。

【讨论】:

  • 不完全清楚为什么这会被否决。所以也许有人可以解释一下
  • "Both snippets should perform identically." 是的......他们都会给你一个编译错误。顺便说一句,我不同意你为这样一个糟糕的问题提供答案
  • 短路不依赖于语言,它依赖于运营商。在这里使用 & 就可以了。并且可能会产生更快的代码,因为在现代内核上这些比较同时运行。例如,Haswell 可以同时运行 4 个整数比较和(我认为)2 个浮点比较。试图绕过占用 CPU 周期一小部分的比较毫无意义,分支只会增加成本。然而,在双打上使用 == 总是错误的。很难对糟糕的代码给出好的答案。
  • @HansPassant:但无论如何,这个答案并没有错或不好,因为它只是说这两种方法基本上都是一样的,这要归功于&amp;&amp; 运算符
  • @TimSchmelter 有些人倾向于否决任何简短的答案,无论其内容如何!我也看不出答案有什么问题。
猜你喜欢
  • 2013-06-10
  • 2018-05-07
  • 2017-10-31
  • 2013-06-28
  • 1970-01-01
  • 1970-01-01
  • 2015-08-24
  • 1970-01-01
  • 2011-12-06
相关资源
最近更新 更多