【问题标题】:Why is VC++ unable to optimize an integer wrapper?为什么 VC++ 无法优化整数包装器?
【发布时间】:2015-04-04 00:23:36
【问题描述】:

在 C++ 中,我正在尝试编写一个 64 位整数的包装器。我的期望是,如果编写正确并且所有方法都被内联,这样的包装器应该与真实类型一样高效。在 SO 上回答这个 question 似乎符合我的期望。

我写了这段代码来测试我的期望:

class B
{
private:
   uint64_t _v;

public:
   inline B() {};
   inline B(uint64_t v) : _v(v) {};

   inline B& operator=(B rhs) { _v = rhs._v; return *this; };
   inline B& operator+=(B rhs) { _v += rhs._v; return *this; };
   inline operator uint64_t() const { return _v; };
};

int main(int argc, char* argv[])
{
   typedef uint64_t;
   //typedef B T;
   const unsigned int x = 100000000;

   Utils::CTimer timer;
   timer.start();

   T sum = 0;
   for (unsigned int i = 0; i < 100; ++i)
   {
      for (uint64_t f = 0; f < x; ++f)
      {
         sum += f;
      }
   }

   float time = timer.GetSeconds();

   cout << sum << endl
        << time << " seconds" << endl;

   return 0;
}

当我使用typedef B T 运行它时;而不是typedef uint64_t T,使用 VC++ 编译时,报告的时间始终慢 10%。使用 g++,无论我是否使用包装器,性能都是相同的。

既然 g++ 做到了,我想 VC++ 不能正确优化这一点没有技术原因。我可以做些什么来优化它吗?

我已经尝试过使用优化标志但没有成功

【问题讨论】:

  • 您是从 Visual Studio 还是从 Windows 控制台运行代码?
  • 如果 g++ 折叠了整个循环,我不会感到惊讶。
  • 深入生成程序集!
  • 我想我都测试了,但我需要再次测试以确保。它会有所作为吗?
  • 你是怎么编译的?我假设发布,但您使用了哪些优化标志?还是 g++ 代码更快还是 VC++ 已经优化了代码?

标签: c++ visual-c++ optimization wrapper


【解决方案1】:

为了记录,这是 g++ 和 clang++ 在-O2 生成的程序集转换为(在包装和非包装情况下),以计时部分为模:

sum = 499999995000000000;
cout << sum << endl;

换句话说,它完全优化了循环。无论您如何努力矢量化循环,都很难击败根本不循环:)

【讨论】:

    【解决方案2】:

    使用 /O2(最大化速度),这两种替代方案使用 Visual Studio 2012 生成完全相同的程序集。这是您的代码,减去时间和输出:

    00FB1000  push        ebp  
    00FB1001  mov         ebp,esp  
    00FB1003  and         esp,0FFFFFFF8h  
    00FB1006  sub         esp,8  
    00FB1009  mov         edx,64h  
    00FB100E  mov         edi,edi  
    00FB1010  xorps       xmm0,xmm0  
    00FB1013  movlpd      qword ptr [esp],xmm0  
    00FB1018  mov         ecx,dword ptr [esp+4]  
    00FB101C  mov         eax,dword ptr [esp]  
    00FB101F  nop  
    00FB1020  add         eax,1  
    00FB1023  adc         ecx,0  
    00FB1026  jne         main+2Fh (0FB102Fh)  
    00FB1028  cmp         eax,5F5E100h  
    00FB102D  jb          main+20h (0FB1020h)  
    00FB102F  dec         edx  
    00FB1030  jne         main+10h (0FB1010h)  
    00FB1032  xor         eax,eax
    

    我认为测量的时间会波动或并不总是正确的。

    【讨论】:

    • xmm0 ! MMX 注册!它确实对操作进行了矢量化!
    • @PanagiotisKanavos 确实,我会说这是一种罕见的景象。
    • 其实并不罕见,VC在并行化代码方面只被英特尔自己的编译器超越。
    • 我花了很多时间手动优化一个紧密循环,其中 Visual Studio 会使用大量 mulss,但从不使用 mulps,尽管这是完全可能的。让我失去了一点信心;)
    • 什么版本?每个后续版本都有很多改进,并且在过去几年中有两个主要的新版本。此外,与英特尔签订的新协议意味着最新版本包含更大部分英特尔矢量化技术、并行库等
    猜你喜欢
    • 2019-07-02
    • 1970-01-01
    • 1970-01-01
    • 2017-09-17
    • 2017-07-02
    • 1970-01-01
    • 1970-01-01
    • 2020-10-10
    • 2014-05-26
    相关资源
    最近更新 更多