2011-12-21 29 views
7

Tôi cố gắng để tính toán số lượng bọ ve một hàm sử dụng để chạy và để làm như vậy một cách sử dụng các chức năng clock() như vậy:đồng hồ() chính xác trong time.h

unsigned long time = clock(); 
myfunction(); 
unsigned long time2 = clock() - time; 
printf("time elapsed : %lu",time2); 

Nhưng vấn đề là các giá trị nó trả về là bội số của 10000, mà tôi nghĩ là CLOCK_PER_SECOND. Có cách nào hay giá trị hàm tương đương chính xác hơn?

Tôi đang sử dụng Ubuntu 64 bit, nhưng sẽ thích nếu giải pháp có thể hoạt động trên các hệ thống khác như Windows & Mac OS.

+2

xem http://stackoverflow.com/questions/538609/high-resolution-timer-with-c-and-linux – NPE

+0

Không nên đặt tên biến 'time', đặc biệt nếu bạn đang sử dụng' ', vì có một hàm chuẩn theo tên đó. –

+0

tôi đã sử dụng thời gian như tên biến chỉ cho mục đích của câu hỏi. – mteffaha

Trả lời

7

Có một số bộ tính giờ chính xác hơn trong POSIX.

  • gettimeofday() - chính thức lỗi thời, nhưng rất phổ biến; độ phân giải micro giây.
  • clock_gettime() - thay thế cho gettimeofday() (nhưng không nhất thiết phải có sẵn rộng rãi; trên phiên bản cũ của Solaris, yêu cầu -lposix4 để liên kết), với độ phân giải nano giây.

Có tính giờ phụ thứ hai khác xưa nhiều hay ít, tính di động, và độ phân giải, bao gồm:

  • ftime() - Độ phân giải millisecond (đánh dấu 'di sản' trong POSIX 2004; không trong POSIX 2008) .
  • clock() - mà bạn đã biết. Lưu ý rằng nó đo thời gian CPU, không trôi qua (đồng hồ treo tường) thời gian.
  • times() - CLK_TCK hoặc HZ. Lưu ý rằng điều này đo thời gian CPU cho quá trình cha mẹ và con.

Không sử dụng ftime() hoặc times() trừ khi không có gì tốt hơn. Dự phòng cuối cùng, nhưng không đáp ứng các yêu cầu trước mắt của bạn, là

  • time() - một độ phân giải thứ hai.

Các clock() báo cáo chức năng trong các đơn vị của CLOCKS_PER_SEC, mà bắt buộc phải 1,000,000 bởi POSIX, nhưng thặng dư có thể xảy ra ít thường xuyên (100 lần mỗi giây là một tần số chung). Giá trị trả lại phải được xác định bởi CLOCKS_PER_SEC để nhận thời gian tính bằng giây.

+2

Vâng thực tế là nó có sẵn trên Solaris là một điều tốt. Một hệ điều hành khác đang nỗ lực tuân thủ POSIX. Tuy nhiên, POSIX không cho rằng biểu tượng có sẵn với ít nhất '-lrt'? –

+0

Tôi đã viết những ghi chú đó một thời gian trước đây - có lẽ là thời đại Solaris 2.6 (hmmm ... 1998 ... vâng, khá lâu rồi!). Vì vậy, thư viện yêu cầu có thể đã thay đổi. –

+0

@ jørgensen: Liên kết đến POSIX 2008 và nó vẫn được liệt kê như một phần của POSIX, mặc dù bị đánh dấu là lỗi thời kể từ Số phát hành 7 (là [POSIX 2008] (http://pubs.opengroup.org/onlinepubs/9699919799/toc .htm), xem tiêu đề của các trang được liên kết đến). Vì vậy, tôi tin rằng bạn đang quá sớm trong tuyên bố 'gettimeofday()' lỗi thời; nó vẫn chỉ là lỗi thời. –

1

Mỗi manpage đồng hồ, trên nền tảng POSIX giá trị của macro CLOCKS_PER_SEC phải là 1000000. Khi bạn nói rằng giá trị trả về bạn nhận được từ clock() là bội số của 10000, điều đó có nghĩa là độ phân giải là 10 ms.

Cũng lưu ý rằng đồng hồ() trên Linux trả về xấp xỉ thời gian xử lý được chương trình sử dụng. Trên Linux, một lần nữa, thống kê lịch biểu được cập nhật khi bộ lập lịch chạy, với tần số CONFIG_HZ. Vì vậy, nếu đánh dấu thời gian định kỳ là 100 Hz, bạn sẽ nhận được số liệu thống kê tiêu thụ thời gian CPU với độ phân giải 10 ms.

Đo thời gian sử dụng đất không bị ràng buộc bởi điều này và có thể chính xác hơn nhiều. clock_gettime (CLOCK_MONOTONIC, ...) trên một hệ thống Linux hiện đại cung cấp độ phân giải nano giây.

+0

cảm ơn mọi cơ thể cho câu trả lời của bạn, tôi đã có thể làm với clock_gettime. – mteffaha

1

Cách chính xác nhất (nhưng cao không phải là di động) để đo thời gian là đếm số lần tích tắc CPU.

Ví dụ trên x86

unsigned long long int asmx86Time() 
{ 
    unsigned long long int realTimeClock = 0; 
    asm volatile ("rdtsc\n\t"   
        "salq $32, %%rdx\n\t"  
        "orq %%rdx, %%rax\n\t" 
        "movq %%rax, %0"   
        : "=r" (realTimeClock) 
        : /* no inputs */ 
        : "%rax", "%rdx"); 
    return realTimeClock; 
} 

double cpuFreq() 
{ 
    ifstream file ("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq"); 
    string sFreq; if (file) file >> sFreq; 
    stringstream ssFreq (sFreq); double freq = 0.; 
    if (ssFreq) { ssFreq >> freq; freq *= 1000; } // kHz to Hz 
    return freq; 
} 

// Timing 

unsigned long long int asmStart = asmx86Time(); 
doStuff(); 
unsigned long long int asmStop = asmx86Time(); 
float asmDuration = (asmStop - asmStart)/cpuFreq(); 

Nếu bạn không có một x86, bạn sẽ phải viết lại mã lắp ráp phù hợp để CPU của bạn. Nếu bạn cần độ chính xác tối đa, đó là điều không may là cách duy nhất để đi ... nếu không sử dụng clock_gettime().

-1

Tôi đồng ý với giải pháp của Jonathan. Đây là việc thực hiện clock_gettime() với độ chính xác nano giây.

//Import 
#define _XOPEN_SOURCE 500 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <time.h> 
#include <sys/time.h> 


int main(int argc, char *argv[]) 
{ 
    struct timespec ts; 
    int ret; 
    while(1) 
    { 
     ret = clock_gettime (CLOCK_MONOTONIC, &ts); 
     if (ret) 
     { 
      perror ("clock_gettime"); 
      return; 
     } 
     ts.tv_nsec += 20000; //goto sleep for 20000 n 
     printf("Print before sleep tid%ld %ld\n",ts.tv_sec,ts.tv_nsec); 
     // printf("going to sleep tid%d\n",turn); 
     ret = clock_nanosleep (CLOCK_MONOTONIC, TIMER_ABSTIME,&ts, NULL); 

    } 
} 

Mặc dù khó đạt được độ chính xác ns nhưng có thể sử dụng để có độ chính xác dưới một micro giây (700-900 ns). printf ở trên được sử dụng để chỉ in các thread # (nó chắc chắn sẽ mất 2-3 micro giây để chỉ in một tuyên bố).

Các vấn đề liên quan