[英]How can I benchmark C code easily?
是否有一個簡單的庫來對執行一部分 C 代碼所需的時間進行基准測試? 我想要的是這樣的:
int main(){
benchmarkBegin(0);
//Do work
double elapsedMS = benchmarkEnd(0);
benchmarkBegin(1)
//Do some more work
double elapsedMS2 = benchmarkEnd(1);
double speedup = benchmarkSpeedup(elapsedMS, elapsedMS2); //Calculates relative speedup
}
如果該庫讓您進行多次運行,對它們進行平均並計算時間差異,那也會很棒!
使用time.h
定義的函數clock()
:
startTime = (float)clock()/CLOCKS_PER_SEC;
/* Do work */
endTime = (float)clock()/CLOCKS_PER_SEC;
timeElapsed = endTime - startTime;
基本上,您只需要一個高分辨率計時器。 經過的時間當然只是時間的差異,加速比是通過除以每個任務的時間來計算的。 我已經包含了一個高分辨率計時器的代碼,它至少應該在 windows 和 unix 上工作。
#ifdef WIN32
#include <windows.h>
double get_time()
{
LARGE_INTEGER t, f;
QueryPerformanceCounter(&t);
QueryPerformanceFrequency(&f);
return (double)t.QuadPart/(double)f.QuadPart;
}
#else
#include <sys/time.h>
#include <sys/resource.h>
double get_time()
{
struct timeval t;
struct timezone tzp;
gettimeofday(&t, &tzp);
return t.tv_sec + t.tv_usec*1e-6;
}
#endif
#include <time.h>
int main(void) {
clock_t start_time = clock();
// code or function to benchmark
double elapsed_time = (double)(clock() - start_time) / CLOCKS_PER_SEC;
printf("Done in %f seconds\n", elapsed_time);
}
如果要對多線程程序進行基准測試,首先需要仔細查看時鍾:
clock() 函數返回程序使用的處理器時間的近似值。
返回的值是目前使用的 CPU 時間作為clock_t; 要獲得使用的秒數,除以 CLOCKS_PER_SEC。 如果使用的處理器時間不可用或其值無法表示,則函數返回值 (clock_t)(-1)
因此,將 elapsed_time 除以線程數以獲得函數的執行時間非常重要:
#include <time.h>
#include <omp.h>
#define THREADS_NB omp_get_max_threads()
#pragma omp parallel for private(i) num_threads(THREADS_NB)
clock_t start_time = clock();
// code or function to benchmark
double elapsed_time = (double)(clock() - start_time) / CLOCKS_PER_SEC;
printf("Done in %f seconds\n", elapsed_time / THREADS_NB); // divide by THREADS_NB!
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <omp.h>
#define N 20000
#define THREADS_NB omp_get_max_threads()
void init_arrays(double *a, double *b) {
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
for (int i = 0; i < N; i++) {
a[i] += 1.0;
b[i] += 1.0;
}
}
double func2(double i, double j) {
double res = 0.0;
while (i / j > 0.0) {
res += i / j;
i -= 0.1;
j -= 0.000003;
}
return res;
}
double single_thread(double *a, double *b) {
double res = 0;
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
if (i == j) continue;
res += func2(a[i], b[j]);
}
}
return res;
}
double multi_threads(double *a, double *b) {
double res = 0;
int i, j;
#pragma omp parallel for private(j) num_threads(THREADS_NB) reduction(+:res)
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
if (i == j) continue;
res += func2(a[i], b[j]);
}
}
return res;
}
int main(void) {
double *a, *b;
a = (double *)calloc(N, sizeof(double));
b = (double *)calloc(N, sizeof(double));
init_arrays(a, b);
clock_t start_time = clock();
double res = single_thread(a, b);
double elapsed_time = (double)(clock() - start_time) / CLOCKS_PER_SEC;
printf("Default: Done with %f in %f sd\n", res, elapsed_time);
start_time = clock();
res = multi_threads(a, b);
elapsed_time = (double)(clock() - start_time) / CLOCKS_PER_SEC;
printf("With OMP: Done with %f in %f sd\n", res, elapsed_time / THREADS_NB);
}
編譯:
gcc -O3 multithread_benchmark.c -fopenmp && time ./a.out
輸出:
Default: Done with 2199909813.614555 in 4.909633 sd
With OMP: Done with 2199909799.377532 in 1.708831 sd
real 0m6.703s (from time function)
在 POSIX 中,嘗試getrusage 。 相關參數為 RUSAGE_SELF,相關字段為 ru_utime.tv_sec 和 ru_utime.tv_usec。
可能有現有的實用程序可以幫助解決這個問題,但我懷疑大多數會使用某種采樣或可能的注入。 但是要對代碼的特定部分進行計時,您可能必須像示例中所示那樣添加對計時器的調用。 如果您使用的是 Windows,則高性能計時器可以工作。 我回答了一個類似的問題,並展示了可以做到這一點的示例代碼。 Linux 也有類似的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.