C++ 11时钟:g ++ steady_clock :: is_steady == false?

Nic*_*rca 9 c++ gcc c++11 gcc4.7

因此,准确的时间是对我很重要,我正在调查这3种类型的C++ 11,即指定的时钟system_clock,steady_clockhigh_resolution_clock.我最初关注的是测试不同类型时钟的呼叫开销是否存在差异,以及检查每种类型时钟的分辨率.这是我的示例程序:

#include <chrono>
#include <cstdio>
using namespace std;
using namespace std::chrono;

int main(int argc, char **argv)
{
  size_t N = 1e6;
  if(2 == argc) {
    sscanf(argv[1], "%zu", &N);
  }

#if defined(hrc)
  typedef high_resolution_clock clock;
#warning "High resolution clock"
#elif defined(sc)
  typedef steady_clock clock;
#warning "Steady clock"
#elif defined(sys)
  typedef system_clock clock;
#warning "System clock"
#endif

  const double resolution = double(clock::period::num) / double(clock::period::den);

  printf("clock::period: %lf us.\n", resolution*1e6);
  printf("clock::is_steady: %s\n", clock::is_steady ? "yes" : "no");
  printf("Calling clock::now() %zu times...\n", N);

  // first, warm up
  for(size_t i=0; i<100; ++i) {
    time_point<clock> t = clock::now();
  }

  // loop N times
  time_point<clock> start = clock::now();
  for(size_t i=0; i<N; ++i) {
    time_point<clock> t = clock::now();
  }
  time_point<clock> end = clock::now();

  // display duration
  duration<double> time_span = duration_cast<duration<double>>(end-start);
  const double sec = time_span.count();
  const double ns_it = sec*1e9/N;
  printf("That took %lf seconds. That's %lf ns/iteration.\n", sec, ns_it);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我用它编译它

$ g++-4.7 -std=c++11 -Dhrc chrono.cpp -o hrc_chrono
chrono.cpp:15:2: warning: #warning "High resolution clock" [-Wcpp]
$ g++-4.7 -std=c++11 -Dsys chrono.cpp -o sys_chrono
chrono.cpp:15:2: warning: #warning "System clock" [-Wcpp]
$ g++-4.7 -std=c++11 -Dsc  chrono.cpp -o sc_chrono
chrono.cpp:15:2: warning: #warning "Steady clock" [-Wcpp]
Run Code Online (Sandbox Code Playgroud)

我用G ++ 4.7.2编译,然后运行它

  • SUSE Linux,内核v3.1.10,CPU i7
  • Angstrom Linux嵌入式系统,内核v3.1.10,MCU Tegra 2(ARM Cortex A9).

第一个令人惊讶的事情是3种类型的时钟显然是同义词.它们都具有相同的周期(1微秒),并且时间/呼叫几乎相同.如果它们全部相同,那么指定3种类型的时钟有什么意义呢?这只是因为G ++的实现chrono还不成熟吗?或者3.1.10内核可能只有一个用户可访问的时钟?

第二个惊喜,这是巨大的,是steady_clock :: is_steady == false.我相当肯定,根据定义,该属性应该是真的.是什么赋予了??我该如何解决它(即实现稳定的时钟)?

如果你可以在其他平台/编译器上运行简单的程序,我会非常有兴趣知道结果.如果有人想知道,我的Core i7上大约25 ns /迭代,Tegra 2上大约1000 ns /迭代.

Jon*_*ely 9

steady_clock 支持GCC 4.7(作为4.7释放所示的文档:http://gcc.gnu.org/onlinedocs/gcc-4.7.2/libstdc++/manual/manual/status.html#status.iso.2011)并且steady_clock::is_steady是真的,但只有你用它构建GCC--enable-libstdcxx-time=rt

有关该配置选项的详细信息,请参阅/sf/answers/907327151/.

对于GCC 4.9,如果您的OS和C库支持POSIX单调时钟,它将自动启用clock_gettime(对于带有glibc 2.17或更高版本的GNU/Linux和适用于Solaris 10,IIRC的GNU/Linux)

以下是配置--enable-libstdcxx-time=rt在AMD Phenom II X4 905e,2.5GHz上的GCC 4.8的结果,但我认为它现在被限制为800MHz,运行Linux 3.6.11,glibc 2.15

$ ./hrc
clock::period: 0.001000 us.
clock::is_steady: no
Calling clock::now() 1000000 times...
That took 0.069646 seconds. That's 69.645928 ns/iteration.
$ ./sys
clock::period: 0.001000 us.
clock::is_steady: no
Calling clock::now() 1000000 times...
That took 0.062535 seconds. That's 62.534986 ns/iteration.
$ ./sc
clock::period: 0.001000 us.
clock::is_steady: yes
Calling clock::now() 1000000 times...
That took 0.065684 seconds. That's 65.683730 ns/iteration.
Run Code Online (Sandbox Code Playgroud)

在运行Linux 3.4.0的ARMv7 Exynos5上没有 GCC 4.7 --enable-libstdcxx-time(所有三种时钟类型的结果都相同),glibc 2.16

clock::period: 1.000000 us.
clock::is_steady: no
Calling clock::now() 1000000 times...
That took 1.089904 seconds. That's 1089.904000 ns/iteration.
Run Code Online (Sandbox Code Playgroud)

  • 我在您的存档电子邮件(http://gcc.gnu.org/ml/libstdc++/2012-05/msg00085.html)中看到:“要在GNU / Linux上获得最大的时钟分辨率,仍然需要使用--enable -libstdcxx-time = rt,_在使用libstdc ++的单线程代码中导致性能下降。_“您能否指定您的意思(即,哪些操作将导致性能下降?)以及得出结论的方式(即,你有个人资料吗?)? (2认同)
  • 请参阅该邮件的第一段:_原因是这些调用中的部分或全部是在librt中定义的,但是在GNU/Linux上如果是libstdc ++.所以链接到librt.so然后它也链接到libpthread.so,所以__gthread_active_p()将始终返回true,导致单线程apps中的额外锁定._ libstdc ++中的引用计数将在使用多个线程的程序中使用原子操作或互斥,这取决于程序是否链接到libpthread. (2认同)

How*_*ant 7

如果你可以在其他平台/编译器上运行简单的程序,我会非常有兴趣知道结果.

Mac OS X 10.8,clang ++/libc ++, - O3,2.8 GHz Core i5:

High resolution clock

clock::period: 0.001000 us.
clock::is_steady: yes
Calling clock::now() 1000000 times...
That took 0.021833 seconds. That's 21.832827 ns/iteration.

System clock

clock::period: 1.000000 us.
clock::is_steady: no
Calling clock::now() 1000000 times...
That took 0.041930 seconds. That's 41.930000 ns/iteration.

Steady clock

clock::period: 0.001000 us.
clock::is_steady: yes
Calling clock::now() 1000000 times...
That took 0.021478 seconds. That's 21.477953 ns/iteration.
Run Code Online (Sandbox Code Playgroud)

steady_clock并且system_clock必须是不同的类型. steady_clock::is_steady必须是true. high_resolution_clock可以是或的别名steady_clock或别名system_clock. system_clock::rep必须是签名类型.