2012-03-26 4 views
8

У меня есть что-то вроде этого:почему C часов() возвращает 0

clock_t start, end; 
start=clock(); 

something_else(); 

end=clock(); 
printf("\nClock cycles are: %d - %d\n",start,end); 

и я всегда получаю в качестве выхода «такты: 0 - 0»

Любая идея, почему это происходит ?

(Просто для того, чтобы дать небольшую деталь, функция something_else() выполняет экспоненциацию слева направо с использованием представления montgomery, более того, я точно не знаю, что функция something_else() действительно занимает некоторое неменьшее время.)

Это на Linux. Результат uname -a является:

Linux snowy.*****.ac.uk 2.6.32-71.el6.x86_64 #1 SMP Fri May 20 03:51:51 BST 2011 x86_64 x86_64 x86_64 GNU/Linux

+2

Какую операционную систему вы используете? – trojanfoe

+0

Я только что отредактировал вопрос, чтобы добавить эту деталь! –

+1

'clock_t', вероятно, не является' int', поэтому '% d' не подходит. См. Этот вопрос: http://stackoverflow.com/questions/1083142/whats-the-correct-way-to-use-printf-to-print-a-clock-t. –

ответ

6

clock Функция не измеряет тактовые частоты процессора.

C говорит clock«возвращает наилучшее приближение в реализации в ко времени процессора , используемого программа с начала эпохи реализации определенной связанной только к программе вызову.»

Если между двумя последовательными clock звонков вы программа занимает меньше времени, чем одно единство функции clock, вы могли бы получить 0.

POSIX clock определяет единство с CLOCKS_PER_SEC как 1000000 (единство составляет 1 микросекунду).

http://pubs.opengroup.org/onlinepubs/009604499/functions/clock.html

Для измерения тактовых циклов в x86/x64 вы можете использовать встроенный ассемблер, чтобы извлечь счетчик часов счетчика времени CPU Stamp регистр rdtsc.

+1

То, что вы говорите о счетчике отметки времени, действительно интересно. Можете ли вы указать хороший источник, о котором можно прочитать? Большое спасибо –

+0

Также полезно отметить, что в то время как clock() является функцией в стандарте C90, существуют платформы, где clock() технически неподдерживается и реализуется, чтобы всегда возвращать -1. – rrrzx

4

Ну, вы хотите, чтобы время something_else() принимает? Попробуйте это:

#include <sys/time.h> 
#include <stdio.h> 
#include <unistd.h> 
int main(void) { 
struct timeval start, end; 
long mtime, secs, usecs;  

gettimeofday(&start, NULL); 
something_else(); 
gettimeofday(&end, NULL); 
secs = end.tv_sec - start.tv_sec; 
usecs = end.tv_usec - start.tv_usec; 
mtime = ((secs) * 1000 + usecs/1000.0) + 0.5; 
printf("Elapsed time: %ld millisecs\n", mtime); 
return 0; 

}

+0

К несчастью мне нужны тактовые циклы, а не время. –

+1

Я не думаю, что вы сможете измерить тактовые частоты. Я не думаю, что есть что-то об этом в стандарте C или POSIX. – Guido

+0

@eddy ed, если вы хотите измерить такты синхронизации, вам нужно использовать логический анализатор, частотомер или другой инструмент аппаратного измерения, прикрепленный к вашему оборудованию. – mah

2

Проверьте значение CLOCKS_PER_SEC в time.h/clock.h. Например, в моей системе (Dev Cpp на Windows 7) это всего лишь 1000. Что касается моей программы, то 1000 тиков в секунду. Ваш something_else будет выполнен в микросекундах. И поэтому clock() возвращает нуль как до, так и после вызова функции.

В моей системе, когда я заменить вашу something_else с трудоемкой рутиной, как этого

for (unsigned i=0xFFFFFFFF;i--;); 

start=clock(); 

for (unsigned i=0xFFFFFFFF;i--;); 

end=clock(); 

я

тактов: 10236 - 20593

На одном из ящиков linux, я нашел следующее в bits/time.h

/* ISO/IEC 9899:1990 7.12.1: <time.h> 
    The macro `CLOCKS_PER_SEC' is the number per second of the value 
    returned by the `clock' function. */ 
/* CAE XSH, Issue 4, Version 2: <time.h> 
    The value of CLOCKS_PER_SEC is required to be 1 million on all 
    XSI-conformant systems. */ 
# define CLOCKS_PER_SEC 1000000l 

Так что считаю, что это, прежде чем анализировать возвращаемое значение clock()

2

правильный способ использования часов() для измерения времени будет:

printf("\nTime elapsed: %.2f\n",1.0*(end-start)/CLOCKS_PER_SEC); 

Это потому, что clock_t не гарантируется быть int или любым другим типом в этом отношении.

+0

OP заинтересован в том, чтобы знать, почему 'start' и' end' оказываются 0? В этом случае с плавающей запятой не помогает –

+0

Я имею в виду, что они могут быть не типа int, поэтому их печать не имеет смысла. Правильный способ их использования заключается в выделении двух из сумм и делении на CLOCKS_PER_SEC. Практически все остальное не определено. Код, который я дал, работает правильно, показывая количество прошедших секунд. – Guido

5

Я думаю, причина в том, что ваш something_else() потребляет так мало времени, что превышает точность clock(). Я попытался позвонить clock() дважды, и оба start и end - ноль, но результат разумный, когда я занимаюсь отнимающим много времени материалом.

Вот мой тестовый фрагмент кода:

int main(void) { 
    clock_t start, end; 
    start = clock(); 
    int c; 
    for (int i = 0; i < 100; i++) { 
     for (int j = 0; j < (1<<30); j++) { 
      c++; 
     } 
    } 
    printf("start = %d, end = %d\n", start, end); 
    return 0; 
} 

И результат на моем компьютере:

start = 0, end = 27700000 

Кроме того, две подсказки:

  1. При тестировании, не используйте любую оптимизацию компилятора. Вы можете подумать, что ваш something_else() занимает много времени, но компилятор может просто игнорировать эти операции (особенно петли), поскольку они считают их бессмысленными.
  2. Используйте sizeof(clock_t) на вашей платформе, чтобы увидеть размер clock_t.
+0

Я пробовал свой код в своей системе. Для выполнения требуется несколько секунд, но все же я получаю два нуля. Я также попытался напечатать его как printf ("\ nTime истек:% .2f \ n", 1.0 * (end-start)/CLOCKS_PER_SEC); , но я все равно получаю ноль. Там определенно что-то не так с функцией часов. Есть ли какой-либо флаг, который мне нужно установить, или что-нибудь, о чем вам известно? –

+0

@eddyed: 'start' должен быть нулевым, так как он записывает истекшее время с момента запуска программы, но' end' не должно быть равно нулю. Насколько мне известно, для использования 'clock()' не нужны специальные флаги или любые другие трюки. BTW, каков результат 'sizeof (clock_t)' на вашей платформе? –

+0

+1 для * не оптимизируйте * –

0

Я использовал небольшую программу ниже, чтобы исследовать настенные часы и время процессора.

На моей тестовой системном печатается

CLOCKS_PER_SEC 1000000

CPU time usage resolutio п выглядит 0.010000 seconds

gettimeofday изменен 9634 uS когда процессорное время изменен 0.010000

разрешением gettimeofday выглядит 1 мкс

#include <stdio.h> 
#include <unistd.h> 
#include <sys/time.h> 
#include <ctime> 


int main(int argc, char** argv) { 

    struct timeval now; // wall clock times 
    struct timeval later; 

    clock_t tNow = clock(); // clock measures CPU time of this Linux thread 
    gettimeofday(&now, NULL); // wall clock time when CPU time first read 

    clock_t tLater = tNow; 
    while (tNow == tLater) 
      tLater = clock(); // consume CPU time 

    gettimeofday(&later, NULL); // wall clock time when CPU time has ticked 

    printf("CLOCKS_PER_SEC %ld\n",CLOCKS_PER_SEC); 

    double cpuRes = (double)(tLater - tNow)/CLOCKS_PER_SEC; 

    printf("CPU time usage resolution looks to be %f seconds\n", cpuRes); 

    unsigned long long nowUs = ((unsigned long long)now.tv_sec) * 1000000ULL; 
    nowUs += (unsigned long long)now.tv_usec; 

    unsigned long long laterUs = ((unsigned long long)later.tv_sec) * 1000000ULL; 
    laterUs += (unsigned long long)later.tv_usec; 

    printf("gettimeofday changed by %d uS when CPU time changed by %f seconds\n", (int)(laterUs - nowUs), cpuRes); 

    // now measure resolution of gettimeofday 

    gettimeofday(&now, NULL); 
    later = now; 

    while ((now.tv_sec == later.tv_sec) && (now.tv_usec == later.tv_usec)) 
      gettimeofday(&later, NULL); 

    nowUs = ((unsigned long long)now.tv_sec) * 1000000ULL; 
    nowUs += (unsigned long long)now.tv_usec; 

    laterUs = ((unsigned long long)later.tv_sec) * 1000000ULL; 
    laterUs += (unsigned long long)later.tv_usec; 

    printf("gettimeofday resolution looks to be %d us\n", (int)(laterUs - nowUs)); 

} 
Смежные вопросы