应该一个一个特殊情况吗?

时间:2017-01-11 17:28:22

标签: c++ optimization cpu

如果我们在内循环中有一个除法,那么添加特殊案例处理以消除划分是明智的:

之前:

    int collapseFactorDepth...
    for (int i = 0; i < numPixels; i++)
    {
      pDataTarget[i] += pPixelData[i] / collapseFactorDepth;
    }

在:

  if (collapseFactorDepth != 1)
  {
    for (int i = 0; i < numPixels; i++)
    {
      pDataTarget[i] += pPixelData[i] / collapseFactorDepth;
    }
  }
  else
  {
    for (int i = 0; i < numPixels; i++)
    {
      pDataTarget[i] += pPixelData[i];
    }
  }

编译器可以自己解释这个吗?现代CPU是否包含任何优化此功能的方法?

如果您认为附加代码与性能增益相比有什么好处(有没有?),我特别感兴趣。

背景:

  • Numpixels很大
  • collapseFactorDepth是90%的时间1
  • 现代CPU:Intel x86 / amd64架构
  • 请不要考虑更广泛的事情。加载的内存开销得到优化。
  • 让我们不要大汗淋漓,不管怎么说,我们应该把它做成双重乘法。

2 个答案:

答案 0 :(得分:2)

作为一般规则,答案是。首先编写清晰的代码,然后在探查器告诉您出现问题时对其进行优化。

回答此特定优化是否有助于此特定热点的唯一方法是:“测量并查看”。

除非collapseFactorDepth几乎始终 1,或numPixels非常大(至少数千且可能更多),否则我不希望优化有所帮助(分支是昂贵的)。

您更有可能从使用SSE或类似的SIMD指令中受益。

答案 1 :(得分:0)

  1. 关注@Martin Bonner的建议。在需要时进行优化。
  2. 当您需要:
  3. int identity(int pixel)
    {
        return pixel;
    }
    
    template<int collapseFactorDepth>
    int div(int pixel)
    {
        return pixel / collapseFactorDepth;
    }
    
    struct Div
    {
        int collapseFactorDepth_;
        Div(collapseFactorDepth)
            : collapseFactorDepth(collapseFactorDepth_) {}
        int operator()(int pixel)
        {
            return pixel / collapseFactorDepth_;
        }
    };
    
    template<typename T>
    void fn(int* pDataTarget, T fn)
    {    
        for (int i = 0; i < numPixels; i++)
        {
            pDataTarget[i] += fn(pPixelData[i]);
        }
    }
    
    void fn(int* pDataTarget)
    {
        fn(pDataTarget, identity);
    }
    
    template<int collapseFactorDepth>
    void fnComp()
    {
        fn(pDataTarget, div<collapseFactorDepth>);
    }
    
    void fn(int* pDataTarget, int collapseFactorDepth)
    {
        fn(pDataTarget, Div(collapseFactorDepth));
    }
    

    这为您提供了一个方便的默认行为,一个编译时除法(可能比div-by-int更快)和一种方式(传递Div)到指定运行时行为。