【问题标题】:"Magical" intel c++ compiler : what happened?“神奇”的英特尔 c++ 编译器:发生了什么?
【发布时间】:2015-09-12 22:07:17
【问题描述】:

我在 *nix 上。在looptest.cpp中有这个简单的c++代码

#include <iostream>
#include <time.h>

int main()
{
      double sum = 0.0;
      int n ;
      std::cout << "n ?" << std::endl;
      std::cin >> n ;
      clock_t t_start = clock();
      for (int i = 0 ; i < n ; ++i)
      {
            sum+= static_cast<double>(i);
      }
      clock_t t_end = clock();
      clock_t diff = t_end - t_start;
      double diffd = static_cast<double>(diff)/CLOCKS_PER_SEC;
      std::cout << diffd << " seconds." << std::endl;
      sum*=1.0;
      return 0;
}

使用 intel c++ 编译器 (icpc (ICC) 14.0.4 20140805, 2013) 编译如下:

/opt/intel/bin/icpc looptest.cpp -o looptest

当我测试它时,我有以下奇怪的结果:

My-MacBook-Air:tmp11 XXXX$ ./looptest 
n ?
10000
4e-06 seconds.
My-MacBook-Air:tmp11 XXXX$ ./looptest 
n ?
100000
3e-06 seconds.
My-MacBook-Air:tmp11 XXXX$ ./looptest 
n ?
1000000
3e-06 seconds.
My-MacBook-Air:tmp11 XXXX$ ./looptest 
n ?
1000000000
2e-06 seconds.
My-MacBook-Air:tmp11 XXXX$ ./looptest 
n ?
4294967295
3e-06 seconds.

很奇怪,不是吗?这里发生了什么 ?当然,使用 gnu-5.2 的 g++ 而不是 icpc 编译会得到预期的结果(当 n 增加时,时间会增加。)

【问题讨论】:

  • C++ 编程中从来没有任何神奇。跳过这个概念,变得认真!
  • 他把“神奇的”放在引号中表示它不是真正的神奇。
  • 用 -ffast-math 也试试 g++
  • 优化器能够确定你没有对计算结果做任何事情,因此它可能只是删除了你的循环。
  • @πάνταῥεῖ,不过,未定义的行为可能会导致一些非常神奇的优化后行为。

标签: c++ intel icc


【解决方案1】:

sum 无处读取,因此删除了对变量的所有赋值。这使得 for 循环为空,所以它也被删除了。因此剩下的就是:

#include <iostream>
#include <time.h>

int main()
{
      int n ;
      std::cout << "n ?" << std::endl;
      std::cin >> n ;
      clock_t t_start = clock();
      clock_t t_end = clock();
      clock_t diff = t_end - t_start;
      double diffd = static_cast<double>(diff)/CLOCKS_PER_SEC;
      std::cout << diffd << " seconds." << std::endl;
      return 0;
}

有效地衡量对clock() 的单次调用有多快。

查看编译后的代码,找出编译器所做的优化。 GCC“应该”能够进行相同的优化,但只有在调用中添加参数-O-O2-O3-Os)时才会这样做。

【讨论】:

  • 确实,在之后添加涉及sum 的内容(例如求一个因子并将总和乘以它之后)会产生 O(n) 时间。而-O 的,在初始代码的情况下,产生相同的结果。不过有一个问题:sum 确实无处可读,但出现在用于产生时间间隔的两个时间之间,然后打印。为什么编译器没有检测到这个?重新表述:编译器有多聪明? ;-)
  • @user10000100_u:现代优化编译器非常聪明。例如见Data-flow analysis
  • @user10000100_u 编译器很聪明地尽可能快地生成正确的函数结果(或您告诉它执行的任何其他优化),而不是检测您想要测量的某些副作用。不管怎样,您有兴趣测量clock 调用的开销。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-07
  • 2013-11-11
  • 2010-11-21
  • 2021-08-08
相关资源
最近更新 更多