2009-04-28 24 views
6

Tôi đang cố gắng tìm cách kiểm tra khoảng thời gian cần một khối mã C++ để chạy. Tôi đang sử dụng nó để so sánh mã với các thuật toán khác nhau và theo các ngôn ngữ khác nhau, vì vậy lý tưởng tôi muốn một thời gian tính bằng giây/mili giây. Trong Java Tôi đang sử dụng một cái gì đó như thế này:Kiểm tra hiệu suất của ứng dụng C++

long startTime = System.currentTimeMillis(); 

function(); 

long stopTime = System.currentTimeMillis(); 
long elapsedTime = stopTime - startTime; 

Có cách nào tốt để có được một thời gian chính xác như vậy trong C++ (Hoặc tôi nên sử dụng một số phương tiện khác của điểm chuẩn)?

+4

RELA ted question: http://stackoverflow.com/questions/275004/c-timer-function-to-provide-time-in-nano-seconds –

+1

Thời gian phụ thuộc vào nền tảng. Bạn nên liệt kê (các) nền tảng nào bạn đang sử dụng. –

+0

Thật đáng thất vọng vì không có câu trả lời nào ở đây có thành phần thống kê. – uckelman

Trả lời

8

Sử dụng bộ đếm tốt nhất có sẵn trên nền tảng của bạn, rơi trở lại thời gian() cho tính di động. Tôi đang sử dụng QueryPerformanceCounter, nhưng xem các bình luận trong trả lời khác.

lời khuyên chung:

Các bên trong vòng lặp nên chạy ít nhất khoảng 20 lần so với độ phân giải của đồng hồ của bạn, để làm cho các lỗi độ phân giải < 5%. (vì vậy, khi sử dụng time() vòng lặp bên trong của bạn sẽ chạy ít nhất 20 giây)

Lặp lại các phép đo này, để xem chúng có nhất quán hay không.

Tôi sử dụng thêm vòng ngoài, chạy mười lần và bỏ qua phép đo nhanh nhất và chậm nhất để tính trung bình và độ lệch. Độ lệch có ích khi so sánh hai lần triển khai: nếu bạn có một thuật toán lấy 2.0ms +/-. 5 và khác 2.2 +/- .5, sự khác biệt không đáng kể khi gọi một trong số đó là "nhanh hơn". (tối đa và tối thiểu sẽ vẫn được hiển thị). Vì vậy, IMHO một đo lường hiệu suất hợp lệ nên tìm một cái gì đó như thế này:

10000 x 2.0 +/- 0.2 ms (min = 1.2, , max=12.6), 10 repetitions 

Nếu bạn biết những gì bạn đang làm, thanh lọc bộ nhớ cache và thiết lập chủ đề mối quan hệ có thể làm cho số đo của bạn nhiều mạnh mẽ hơn.

Tuy nhiên, đây không phải là không có pifalls. Độ đo càng "ổn định" càng ít thì nó càng ít thực tế. Mọi triển khai sẽ thay đổi mạnh theo thời gian, tùy thuộc vào trạng thái dữ liệu và bộ nhớ cache lệnh. Tôi lười biếng ở đây, sử dụng giá trị max = để phán đoán hình phạt đầu tiên, điều này có thể không đủ cho một số trường hợp.

7

Thực hiện chức năng vài nghìn lần để có được phép đo chính xác.

Một phép đo đơn lẻ có thể bị chi phối bởi sự kiện hệ điều hành hoặc tiếng ồn ngẫu nhiên khác.

2

Bạn có thể sử dụng chức năng time() để nhận hẹn giờ với độ phân giải một giây. Nếu bạn cần thêm độ phân giải, bạn có thể sử dụng gettimeofday(). Độ phân giải tùy thuộc vào hệ điều hành và thư viện thời gian chạy của bạn.

5

Trong Windows, bạn có thể sử dụng bộ đếm hiệu suất cao để có được kết quả chính xác hơn:

Bạn có thể sử dụng QueryPerformanceFrequency() chức năng để có được số lượng tần số cao bọ ve mỗi seconde và người sử dụng các QueryPerformanceCounter() trước và sau khi các chức năng bạn muốn thời gian.

Tất nhiên, phương pháp này không phải là di động ...

+0

Hãy cẩn thận với các bộ đếm HF. Hệ thống đa bộ xử lý đôi khi làm cho việc sử dụng chúng trở nên thú vị. Họ làm việc với các bộ xử lý cụ thể quầy, vì vậy nếu bạn kết thúc với mã của bạn trên một CPU khác nhau, các quầy có thể được tắt (tùy thuộc vào phần cứng chính xác của bạn, tất nhiên). –

+1

Đặt mối quan hệ chuỗi thành một CPU trong khoảng thời gian của điểm chuẩn sẽ loại bỏ thời gian liên quan đến SMP. Cũng có thể có sự tăng tốc đồng hồ do quản lý nguồn điện, điều này sẽ trở thành vấn đề nếu CPU không hoạt động vì mã được đánh giá chuẩn sẽ ngủ hoặc chặn trên I/O. Đối với các hệ thống AMD, việc cài đặt Trình xử lý AMD sẽ cải thiện đáng kể việc đồng bộ hóa QPC(). Windows Vista và Windows 7 sử dụng bộ đếm thời gian HPET (nếu có) thay cho TSC, do đó, các vấn đề TSC cuối cùng có thể biến mất (khi/nếu Windows XP biến mất). – bk1e

+0

Xem http://support.microsoft.com/kb/895980 để biết các giải pháp. – peterchen

5

Bạn đã thực sự xem xét việc sử dụng một hồ sơ chưa? Visual Studio Team System có tích hợp sẵn, nhưng có sẵn những ứng dụng khác như VTune và GlowCode.

cũng What's the best free C++ profiler for Windows?

+0

Gah! Họ có những cái không tốn kém nhiều không? –

+1

Vâng, hãy xem ở trên. – rlbond

+4

Profilers rất tốt cho việc trả lời câu hỏi "phần chậm nhất của chương trình của tôi là gì?" nhưng thường không giỏi trả lời câu hỏi "chương trình của tôi chậm đến mức nào?" chính xác. – bk1e

0

Xem Bạn chỉ có thể sử dụng time() trong mã của bạn để đo lường trong phạm vi chính xác của giây. Tiêu chuẩn kỹ lưỡng nên chạy nhiều lần lặp lại cho độ chính xác, vì vậy giây phải là một lề đủ lớn. Nếu bạn đang sử dụng Linux, bạn có thể sử dụng tiện ích thời gian theo quy định của các dòng lệnh như sau:

[[email protected]]$time ./loops.sh 

real 0m3.026s 
user 0m4.000s 
sys  0m0.020s 
0

Trên các hệ thống unix (Linux, Mac, vv), bạn có thể sử dụng time tiện ích như vậy:

$ time ./my_app 
0

Nếu chức năng của bạn là rất nhanh, một thực hành tốt là để thời gian chức năng trong một vòng lặp và sau đó trừ chi phí vòng lặp.

Something như thế này:

int i; 
int limit=1000000; 
int t0=getTime(); 
for(i=0; i < limit; ++i) 
    ; 
int t1=getTime(); 
int loopoverhead = t1-t0; 
t0=getTime(); 
for(i=0; i < limit; ++i) 
    function(); 
t1=getTime(); 
double tfunction = (1.0/limit)*((t1-t0)-loopoverhead); 
2

tôi luôn luôn sử dụng boost::timer hoặc boost::progress_timer.

psudo mã:

#include <boost/timer.hpp> 

boost::timer t; 

func1(); 
cout << "fun1: " << t.elapsed(); 

t.restart(); 
func2(); 
cout << "func2(): " << t.elapsed(); 
2

Nếu bạn muốn kiểm tra xem bạn thực hiện, bạn nên xem xét đo sử dụng bộ vi xử lý thời gian, không phải là thực khi bạn đang cố gắng để đo bây giờ. Nếu không, bạn có thể nhận được khá thời gian không chính xác nếu một số ứng dụng khác chạy trong nền quyết định làm một số tính toán nặng cùng một lúc. Các chức năng bạn muốn là GetProcessTimes trên Windows và getrusage trên Linux.

Ngoài ra, bạn nên cân nhắc việc sử dụng các hồ sơ, như những người khác đã đề xuất.

0

Chạy 1000 lần dưới 100 lần lặp * 10 lần lặp, nơi bạn bỏ vòng lặp bên trong để giảm thiểu chi phí. Sau đó, giây chuyển thành mili giây.

Như những người khác đã chỉ ra, đây là một cách hay để đo lường phải mất bao lâu.

Tuy nhiên, nếu bạn cũng muốn giảm thời gian, đó là mục tiêu khác và cần kỹ thuật khác. My favorite is this.

3

Có gì sai với clock()CLOCKS_PER_SEC? Đó là tiêu chuẩn C89.

Giống như (nicked từ MSDN):

long i = 6000000L; 
    clock_t start, finish; 
    double duration; 

    // Measure the duration of an event. 
    printf("Time to do %ld empty loops is ", i); 
    start = clock(); 
    while(i--) 
     ; 
    finish = clock(); 
    duration = (double)(finish - start)/CLOCKS_PER_SEC; 
    printf("%2.1f seconds\n", duration); 
0

nền tảng của bạn để triển khai có thể có tác động nghiêm trọng đến độ chính xác đồng hồ của bạn. Nếu bạn đang lấy mẫu bên trong một Máy ảo, tất cả các phiên cược sẽ bị tắt. Đồng hồ hệ thống trong một máy ảo nổi liên quan đến đồng hồ vật lý và đôi khi phải được thay đổi lại.Nó gần như là một điều chắc chắn rằng điều này sẽ xảy ra sẽ xảy ra, do tính chất tinh nghịch của ông Murphy trong vũ trụ phần mềm

2

TỔNG QUAN

Tôi đã viết một đơn giản ngữ nghĩa Hack cho việc này.

  • Dễ sử dụng
  • Mã trông gọn gàng.

MACRO

#include <time.h> 

#ifndef SYSOUT_F 
#define SYSOUT_F(f, ...)  _RPT1(0, f, __VA_ARGS__) // For Visual studio 
#endif 

#ifndef speedtest__    
#define speedtest__(data) for (long blockTime = NULL; (blockTime == NULL ? (blockTime = clock()) != NULL : false); SYSOUT_F(data "%.9fs", (double) (clock() - blockTime)/CLOCKS_PER_SEC)) 
#endif 

SỬ DỤNG

speedtest__("Block Speed: ") 
{ 
    // The code goes here 
} 

OUTPUT

Block Speed: 0.127000000s 
Các vấn đề liên quan