10

所以准确的时序对我来说很重要,我正在研究 C++ 11 中指定的 3 种时钟类型,即system_clocksteady_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;
}

我用它编译

$ 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]

我用 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 内核可能只有一个用户可访问的时钟?

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

如果你可以在其他平台/编译器上运行这个简单的程序,我很想知道结果。如果有人想知道,我的 Core i7 上大约是 25 ns/迭代,而 Tegra 2 上大约是 1000 ns/迭代。

4

3 回答 3

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是正确的,但前提是您使用--enable-libstdcxx-time=rt

有关该配置选项的详细信息,请参阅https://stackoverflow.com/a/12961816/981959

对于 GCC 4.9,如果您的操作系统和 C 库支持 POSIX 单调时钟,它将自动启用clock_gettime(对于带有 glibc 2.17 或更高版本的 GNU/Linux 以及 Solaris 10、IIRC 都是如此)

--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.

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

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.
于 2013-02-22T21:58:57.223 回答
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.

steady_clock并且system_clock必须是不同的类型。 steady_clock::is_steady必须是truehigh_resolution_clock可能是 or 的不同类型或steady_clock别名system_clocksystem_clock::rep必须是有符号类型。

于 2013-02-22T20:23:36.360 回答
4

根据GNU 的网站,GNU libstdc++ 还不支持steady_clock。这就是为什么steady_clock::is_steady是假的。

以下是支持清单的相关部分:

20.11.7.1   Class system_clock           Y   
20.11.7.2   Class steady_clock           N   Support old monotonic_clock spec instead
20.11.7.3   Class high_resolution_clock  Y   
于 2013-02-22T20:34:13.323 回答