2010-02-19 30 views

Trả lời

4

Tôi đã triển khai bộ đếm thời gian cho các tình huống như thế này trước đây: Tôi thực sự đã kết thúc với một lớp với hai cài đặt khác nhau, một cho Windows và một cho POSIX.

Lý do là Windows có chức năng QueryPerformanceCounter() cho phép bạn truy cập vào một chiếc đồng hồ rất chính xác lý tưởng cho các thời gian như vậy.

Trên POSIX tuy nhiên điều này không có sẵn vì vậy tôi chỉ sử dụng các lớp học của boost.datetime để lưu trữ thời gian bắt đầu và kết thúc sau đó tính thời lượng từ những người đó. Nó cung cấp một bộ đếm thời gian "độ phân giải cao" nhưng độ phân giải là không xác định và thay đổi từ nền tảng đến nền tảng.

1

giờ cao độ chính xác là nền tảng cụ thể và do đó không được chỉ định bởi các tiêu chuẩn C++, nhưng có những thư viện có sẵn. Xem this question để thảo luận.

0

Đây có thể là sự cố phụ thuộc vào hệ điều hành hơn là vấn đề ngôn ngữ.

Nếu bạn đang sử dụng Windows thì bạn có thể truy cập mili giây bộ đếm thời gian từ 10 đến 16 giây thông qua GetTickCount() hoặc GetTickCount64(). Chỉ cần gọi nó một lần khi bắt đầu và một lần ở cuối, và trừ đi.

Đó là những gì tôi đã sử dụng trước đây nếu tôi nhớ chính xác. Trang được liên kết cũng có các tùy chọn khác.

+0

Liệu GetTickCount() sử dụng QueryPerformanceCounter() bên dưới nắp ca-pô hay? – Mithrax

+0

Điều đó tôi không biết. Tôi đã thêm một liên kết đến trang GetTickCount() và có vẻ như bạn có các tùy chọn khác, có lẽ tốt hơn dựa trên những gì có ở đó. – John

+0

No. GetTickCount() không chính xác. Nếu bạn muốn đếm chính xác, bạn phải sử dụng QueryPerformanceCounter() (EDIT: bởi không chính xác tôi có nghĩa là +/- 10ms) –

0
#include <time.h> 

clock_t start, end; 
start = clock(); 
//Do stuff 
end = clock(); 

printf("Took: %f\n", (float)((end - start)/(float)CLOCKS_PER_SEC)); 
+0

Điều này sẽ hiệu quả nhưng độ phân giải sẽ kém. –

+0

Điều này thực sự không hoạt động để đo thời gian tuyệt đối, vì 'clock()' chỉ trả về thời gian CPU mà ** mã ** của bạn đã thực hiện. Do đó, nếu bạn thay thế '\\ Thực hiện công việc' bằng' usleep (1000000) 'printf sẽ trả về 0,0000 giây thay vì 1 giây. – CodingAway

3

Tôi sử dụng phiên bản Python của riêng mình time_it chức năng. Ưu điểm của hàm này là nó lặp lại một phép tính nhiều lần khi cần thiết để thu được các kết quả có ý nghĩa. Nếu tính toán rất nhanh, nó sẽ được lặp lại nhiều lần. Cuối cùng, bạn có được thời gian trung bình của tất cả các lần lặp lại. Nó không sử dụng bất kỳ chức năng phi tiêu chuẩn:

#include <ctime> 

double clock_diff_to_sec(long clock_diff) 
{ 
    return double(clock_diff)/CLOCKS_PER_SEC; 
} 

template<class Proc> 
double time_it(Proc proc, int N=1) // returns time in microseconds 
{ 
    std::clock_t const start = std::clock(); 
    for(int i = 0; i < N; ++i) 
     proc(); 
    std::clock_t const end = std::clock(); 
    if(clock_diff_to_sec(end - start) < .2) 
     return time_it(proc, N * 5); 
    return clock_diff_to_sec(end - start) * (1e6/N); 
} 

Ví dụ sau đây sử dụng time_it chức năng để đo hiệu suất của STL container khác nhau:

void dummy_op(int i) 
{ 
    if(i == -1) 
     std::cout << i << "\n"; 
} 

template<class Container> 
void test(Container const & c) 
{ 
    std::for_each(c.begin(), c.end(), &dummy_op); 
} 

template<class OutIt> 
void init(OutIt it) 
{ 
    for(int i = 0; i < 1000; ++i) 
     *it = i; 
} 

int main(int argc, char ** argv) 
{ 
    { 
     std::vector<int> c; 
     init(std::back_inserter(c)); 
     std::cout << "vector: " 
        << time_it(boost::bind(&test<std::vector<int> >, c)) << "\n"; 
    }  
    { 
     std::list<int> c; 
     init(std::back_inserter(c)); 
     std::cout << "list: " 
        << time_it(boost::bind(&test<std::list<int> >, c)) << "\n"; 
    } 
    { 
     std::deque<int> c; 
     init(std::back_inserter(c)); 
     std::cout << "deque: " 
        << time_it(boost::bind(&test<std::deque<int> >, c)) << "\n"; 
    } 
    { 
     std::set<int> c; 
     init(std::inserter(c, c.begin())); 
     std::cout << "set: " 
        << time_it(boost::bind(&test<std::set<int> >, c)) << "\n"; 
    } 
    { 
     std::tr1::unordered_set<int> c; 
     init(std::inserter(c, c.begin())); 
     std::cout << "unordered_set: " 
      << time_it(boost::bind(&test<std::tr1::unordered_set<int> >, c)) << "\n"; 
    }  
} 

Trong trường hợp bất cứ ai là tò mò đây là sản phẩm tôi được (biên soạn với VS2008 trong chế độ phát hành):

vector: 8,7168

danh sách: 27,776

deque: 91,52

bộ: 103,04

unordered_set: 29.76

+0

Rất thú vị. Cả hai cho chức năng thời gian và cái nhìn sâu sắc về các containter khác nhau! Cám ơn. – Morlock

+0

@Morlock - Cảm ơn! Tôi sẽ mất thời gian với một nhúm muối, 'std :: deque' cư xử khủng khiếp trong thử nghiệm này nhưng tôi chắc chắn trong một thiết lập chung nó không phải là quá xấu. – Manuel

3

Tôi đã sử dụng boost::timer để đo thời lượng hoạt động. Nó cung cấp một cách rất dễ dàng để thực hiện phép đo, và đồng thời là nền tảng độc lập. Dưới đây là ví dụ:

boost::timer myTimer; 
doOperation(); 
std::cout << myTimer.elapsed(); 

P.S. Để khắc phục các lỗi chính xác, sẽ rất tuyệt vời để đo lường các hoạt động mất vài giây. Đặc biệt là khi bạn đang cố gắng để so sánh một số lựa chọn thay thế. Nếu bạn muốn đo lường điều gì đó tốn ít thời gian, hãy thử đưa nó vào vòng lặp. Ví dụ: chạy hoạt động 1000 lần và sau đó chia tổng thời gian cho 1000.

0

Bạn có thể tìm thấy lớp hữu ích this.

Sử dụng thành ngữ RAII, nó in văn bản được đưa ra trong khi xây dựng khi hàm hủy được gọi, điền vào phần giữ chỗ thời gian đã trôi qua với giá trị phù hợp.

Ví dụ về sử dụng:

int main() 
{ 
    trace_elapsed_time t("Elapsed time: %ts.\n"); 
    usleep(1.005 * 1e6); 
} 

Output:

Elapsed time: 1.00509s. 
1

Tôi khiêm nhường nộp riêng micro-benchmarking mini-library (on Github) tôi. Đó là siêu đơn giản - lợi thế duy nhất nó có hơn cán của riêng bạn là nó đã có mã bộ đếm thời gian hiệu suất cao được thực hiện cho Windows và Linux, và tóm tắt đi các boilerplate gây phiền nhiễu.

Chỉ cần chuyển một hàm (hoặc lambda), số lần nó được gọi cho mỗi lần chạy thử (mặc định: 1) và số lần chạy thử (mặc định: 100). Chạy thử nghiệm nhanh nhất (đo bằng mili giây phân đoạn) được trả về:

// Example that times the compare-and-swap atomic operation from C++11 
// Sample GCC command: g++ -std=c++11 -DNDEBUG -O3 -lrt main.cpp microbench/systemtime.cpp -o bench 
#include "microbench/microbench.h" 

#include <cstdio> 
#include <atomic> 

int main() 
{ 
    std::atomic<int> x(0); 
    int y = 0; 

    printf("CAS takes %.4fms to execute 100000 iterations\n", 
     moodycamel::microbench(
      [&]() { x.compare_exchange_strong(y, 0); }, /* function to benchmark */ 
      100000, /* iterations per test run */ 
      100 /* test runs */ 
     ) 
    ); 

    // Result: Clocks in at 1.2ms (12ns per CAS operation) in my environment 

    return 0; 
} 
Các vấn đề liên quan