【问题标题】:Is a switch statement faster than a for loop?switch 语句比 for 循环快吗?
【发布时间】:2015-10-30 22:50:41
【问题描述】:

我正在查看 Lourakis & Argyros 的稀疏束调整库 (sba) 的源代码。更准确地说,我正在查看以下函数nrmL2xmy,它计算两个向量的平方 L2 差。以下代码是从文件sba_levmar.c 中复制的,从146 行开始:

/* Compute e=x-y for two n-vectors x and y and return the squared L2 norm of e.
 * e can coincide with either x or y. 
 * Uses loop unrolling and blocking to reduce bookkeeping overhead & pipeline
 * stalls and increase instruction-level parallelism; see http://www.abarnett.demon.co.uk/tutorial.html
 */
static double nrmL2xmy(double *const e, const double *const x, const double *const y, const int n)
{
const int blocksize=8, bpwr=3; /* 8=2^3 */
register int i;
int j1, j2, j3, j4, j5, j6, j7;
int blockn;
register double sum0=0.0, sum1=0.0, sum2=0.0, sum3=0.0;

  /* n may not be divisible by blocksize, 
   * go as near as we can first, then tidy up.
   */
  blockn = (n>>bpwr)<<bpwr; /* (n / blocksize) * blocksize; */

  /* unroll the loop in blocks of `blocksize'; looping downwards gains some more speed */
  for(i=blockn-1; i>0; i-=blocksize){
            e[i ]=x[i ]-y[i ]; sum0+=e[i ]*e[i ];
    j1=i-1; e[j1]=x[j1]-y[j1]; sum1+=e[j1]*e[j1];
    j2=i-2; e[j2]=x[j2]-y[j2]; sum2+=e[j2]*e[j2];
    j3=i-3; e[j3]=x[j3]-y[j3]; sum3+=e[j3]*e[j3];
    j4=i-4; e[j4]=x[j4]-y[j4]; sum0+=e[j4]*e[j4];
    j5=i-5; e[j5]=x[j5]-y[j5]; sum1+=e[j5]*e[j5];
    j6=i-6; e[j6]=x[j6]-y[j6]; sum2+=e[j6]*e[j6];
    j7=i-7; e[j7]=x[j7]-y[j7]; sum3+=e[j7]*e[j7];
  }

  /*
   * There may be some left to do.
   * This could be done as a simple for() loop, 
   * but a switch is faster (and more interesting) 
   */

  i=blockn;
  if(i<n){ 
  /* Jump into the case at the place that will allow
   * us to finish off the appropriate number of items. 
   */
    switch(n - i){ 
      case 7 : e[i]=x[i]-y[i]; sum0+=e[i]*e[i]; ++i;
      case 6 : e[i]=x[i]-y[i]; sum0+=e[i]*e[i]; ++i;
      case 5 : e[i]=x[i]-y[i]; sum0+=e[i]*e[i]; ++i;
      case 4 : e[i]=x[i]-y[i]; sum0+=e[i]*e[i]; ++i;
      case 3 : e[i]=x[i]-y[i]; sum0+=e[i]*e[i]; ++i;
      case 2 : e[i]=x[i]-y[i]; sum0+=e[i]*e[i]; ++i;
      case 1 : e[i]=x[i]-y[i]; sum0+=e[i]*e[i]; ++i;
    }
  }

  return sum0+sum1+sum2+sum3;
}

在代码中间(大致),作者声明如下:

 /*
   * There may be some left to do.
   * This could be done as a simple for() loop, 
   * but a switch is faster (and more interesting) 
   */

我不明白为什么 switch 比简单的 for 循环更快。

所以我的问题是:这句话是真的吗?如果是,为什么

【问题讨论】:

  • 我没有明白你的意思。 for 是一个循环,switch 充其量只是一个决定。如何比较它们?
  • 你在比较苹果和橘子。
  • 查看这些案例,您会发现它们并非以break 结尾,因此会失败。简直就是loop unrolling的一种。
  • 这句话是真的吗?只有一种方法可以找出...
  • 顺便说一下,IMO 虽然这可能更优化(特别是如果经常调用该函数),但它可能是过早优化的情况(编译器可能能够展开),也是一种方法程序员为了炫耀一些聪明才智,并且作为编程中的大多数优化和聪明,它混淆了代码,使其更难理解和维护。

标签: c performance for-loop optimization switch-statement


【解决方案1】:

在这种情况下,switch 会更快,因为循环会多次检查结束条件,而 switch 只会检查一次。这称为loop unrolling,优化编译器在很大程度上是自己完成的。

【讨论】:

    【解决方案2】:

    有问题的 switch 案例在所有案例中都使用了贯穿,所以它基本上是一个展开的for 循环。这很可能会(稍微)快一些,因为没有执行比较操作。

    鉴于少数情况,任何性能差异都可以忽略不计,因此从代码可读性的角度来看,for 循环会更好。

    【讨论】:

      【解决方案3】:

      示例:只有值匹配时才能生成输出。 18岁或60岁时。没有基于大于或小于的数据的commarison。根据相等性比较数据。

      For 循环:检查数据的值是否小于或大于。 (范围内)。 例如:可以告诉天气输入年龄大于 18 岁小于 60 岁。

      Switch Case:检查预先指定的数据值。只等于。

      根据你所说,我会使用 for 循环。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-19
        相关资源
        最近更新 更多