【问题标题】:C++ clock stays zeroC++ 时钟保持为零
【发布时间】:2013-09-12 20:09:43
【问题描述】:

我正在尝试获取我的程序的经过时间。实际上我认为我应该使用来自time.hyclock()。但它在程序的所有阶段都保持为零,尽管我添加了 10^5 个数字(必须消耗一些 CPU 时间)。我已经搜索过这个问题,似乎运行 Linux 的人只有这个问题。我正在运行 Ubuntu 12.04LTS。

我将比较 AVX 和 SSE 指令,因此使用 time_t 并不是一个真正的选择。有什么提示吗?

代码如下:

 //Dimension of Arrays
unsigned int N = 100000;
//Fill two arrays with random numbers
unsigned  int a[N];
clock_t start_of_programm = clock();
for(int i=0;i<N;i++){
    a[i] = i;
}
clock_t after_init_of_a = clock();
unsigned  int b[N];
for(int i=0;i<N;i++){
    b[i] = i;
}
clock_t after_init_of_b = clock();

//Add the two arrays with Standard
unsigned int out[N];
for(int i = 0; i < N; ++i)
    out[i] = a[i] + b[i];
clock_t after_add = clock();

cout  << "start_of_programm " << start_of_programm  << endl; // prints
cout  << "after_init_of_a " << after_init_of_a  << endl; // prints
cout  << "after_init_of_b " << after_init_of_b  << endl; // prints
cout  << "after_add " << after_add  << endl; // prints
cout  << endl << "CLOCKS_PER_SEC " << CLOCKS_PER_SEC << endl;

还有控制台的输出。我也用printf()%d,没有区别。

start_of_programm 0
after_init_of_a 0
after_init_of_b 0
after_add 0

CLOCKS_PER_SEC 1000000

【问题讨论】:

  • “我正在尝试计算我的进程运行的时间”...您的意思是经过的时间? clock() 返回进程使用的 CPU 时间量。
  • 真的。我不是天生的演讲者。无论如何,对解决我的问题有什么建议吗?
  • 如果在N 上再添加两个0s 会怎样?
  • 如果您可以访问 C++11(任何最近的编译器),请尝试使用 std::chrono 而不是 C 时间函数。
  • @toebs,如果您要比较 AVX 和 SSE 代码,那么您可能希望使用 32 字节对齐的内存以及更大的数组大小。在那种情况下,在堆栈上分配你的数组是行不通的。我会使用_mm_malloc(sizeof(int)*N, 32)

标签: c++ time.h


【解决方案1】:

clock 确实返回了使用的 CPU 时间,但粒度在 10Hz 的量级。因此,如果您的代码不超过 100 毫秒,您将得到零。除非它明显长于 100 毫秒,否则您将无法获得非常准确的值,因为您的误差范围将在 100 毫秒左右。

因此,增加 N 或使用不同的方法来测量时间将是您的选择。 std::chrono 很可能会产生更准确的时间(但它会测量“墙上时间”,而不是 CPU 时间)。

timespec t1, t2; 
clock_gettime(CLOCK_REALTIME, &t1); 
... do stuff ... 
clock_gettime(CLOCK_REALTIME, &t2); 
double t = timespec_diff(t2, t1);

double timespec_diff(timespec t2, timespec t1)
{
    double d1 = t1.tv_sec + t1.tv_nsec / 1000000000.0;
    double d2 = t2.tv_sec + t2.tv_nsec / 1000000000.0;

    return d2 - d1;
}

【讨论】:

  • 这个库已经是 gcc4.6 的特性了吗?我的编译器抛出错误,chrono 仍处于测试阶段
  • 这是C++11的特性,所以老版本的gcc可能没有。
  • 是否有可能增加粒度?
  • @toebs:现在发布了适用于 Linux 的解决方案,使用高分辨率 clock_gettime
  • 谢谢,这工作正常,并提供与 openmp 解决方案相同的结果!
【解决方案2】:

获得时间的最简单方法是仅使用 OpenMP 中的存根函数。这将适用于 MSVC、GCC 和 ICC。使用 MSVC,您甚至不需要启用 OpenMP。如果您喜欢-openmp-stubs,您可以使用 ICC 仅链接存根。使用 GCC 你 have to use -fopenmp.

#include <omp.h>

double dtime;
dtime = omp_get_wtime();
foo();
dtime = omp_get_wtime() - dtime;
printf("time %f\n", dtime);

【讨论】:

  • 似乎至少可以工作。当我使用 ICC 时,你能解释一下在 Eclipse 中在哪里添加 -openmp-stubs 吗?我将它添加为链接器和编译器选项,但它会引发错误,即函数未知。对于 gcc 它可以工作
  • 您可以将-fopenmp-openmp 与 ICC 一起使用,就像 GCC 一样。我没有使用过 Eclipse(我使用 QtCreator 或者只是一个文本编辑器和 shell)。你用什么来制作 Makefile?
  • 这里是显示 ICC 的 -openmp-stubs 选项的链接。
【解决方案3】:

首先,编译器很可能会优化您的代码。检查编译器的优化选项。

由于包含out[], a[], b[]的数组没有被后续代码使用,并且不会输出来自out[], a[], b[]的值,因此编译器将代码块优化如下,就像根本不执行一样:

for(int i=0;i<=N;i++){
    a[i] = i;
}

for(int i=0;i<=N;i++){
    b[i] = i;
}

for(int i = 0; i < N; ++i)
    out[i] = a[i] + b[i];

由于clock()函数返回CPU时间,上述代码优化后几乎不消耗时间。

还有一件事,将 N 设置为更大的值。 100000 对于性能测试来说太小了,现在计算机在 100000 规模上运行 o(n) 代码非常快。

unsigned int N = 10000000;

【讨论】:

  • 很遗憾,这不是解决方案。无论如何,我编译时没有优化,但即使我例如。 print "out[]" 经过的时间还是0。
【解决方案4】:

将此添加到代码的末尾

int sum = 0;
for(int i = 0; i<N; i++)
    sum += out[i];
cout << sum;

那你就会看到时代了。

由于您不使用a[], b[], out[],它会忽略相应的 for 循环。这是因为编译器的优化。

此外,要查看它所花费的确切时间,请使用 debug mode 而不是 release,然后您将能够看到它所花费的时间。

【讨论】:

  • 很遗憾,这不是解决方案。无论如何,我编译时没有优化,但即使我例如。 print "out[]" 经过的时间仍然是 0。我仍然很好奇为什么粒度是 10Hz,无论你在哪里看,都建议使用时钟来测量经过的时间:\
  • 你增加了N,因为它太小了。N=10^8可以测试。你也可以在代码中做一些更复杂的事情,例如int tot = 0; for(i=1:N) tot++; tot /=2;。我不知道粒度:(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-26
相关资源
最近更新 更多