Pin-Jiun / Programming-Language-CPP

It's the note/experience about C++, and I have the basic ability of C.
0 stars 0 forks source link

21-Running Time Calculation #28

Open Pin-Jiun opened 1 year ago

Pin-Jiun commented 1 year ago
  1. 使用 clock() 精確度只到 ms
  2. 使用 clock_gettime(),精確度可達 ns 3.使用windows.h中的QueryPerformanceCount / QueryPerformanceFrequency, 精度達微秒,但在 MSDN 上亦註明,此函式若硬體不支援,將只傳回 1000

clock

clock()會回傳「程式開始執行」到「clock本行程式碼被執行」時的時間差,回傳型別為clock_t clock()會在程式開始執行時計時,直接呼叫就能知道已經執行多久

cout << (double)clock() / CLOCKS_PER_SEC << " S";

由於 clock 回傳的數值是以毫秒為單位,所以會在除上一個 CLOCKS_PER_SEC,這個 CLOCKS_PER_SEC 通常都是 1000

可以差值測試某一段程式所需的時間

```c++
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h> // clock 函數所需之標頭檔
double pi(int n) {
  srand(5);
  int count = 0;
  double x, y;
  for (int i = 0; i < n; ++i) {
    x = (double) rand() / RAND_MAX;
    y = (double) rand() / RAND_MAX;
    if (x * x + y * y <= 1) ++count;
  }
  return (double) count / n * 4;
}
int main() {
  // 儲存時間用的變數
  clock_t start, end;
  double cpu_time_used;

  // 計算開始時間
  start = clock();

  // 主要計算
  double result = pi(1e8);

  // 計算結束時間
  end = clock();

  // 計算實際花費時間
  cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;

  printf("PI = %f\n", result);
  printf("Time = %f\n", cpu_time_used);
}

clock_gettime

clock_gettime 的 prototype 如下

int clock_gettime(clockid_t clk_id, struct timespect *tp);

選擇要拿哪個 clock 的時間,放入 clk_id 這欄位,以下是較常用的 clock CLOCK_REALTIME, a system-wide realtime clock. CLOCK_PROCESS_CPUTIME_ID, high-resolution timer provided by the CPU for each process. CLOCK_THREAD_CPUTIME_ID, high-resolution timer provided by the CPU for each of the threads.

timespect 這個 struct 有兩個 member,tv_sec 與 tv_nsec

struct timespec {
    time_t tv_sec; /* seconds */
    long tv_nsec; /* nanoseconds */
};

用一個簡單的for loop來計算執行時間

#include <iostream>
#include <time.h>
using namespace std;

timespec diff(timespec start, timespec end);

int main()
{
    timespec time1, time2;
    int temp;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);
    for (int i = 0; i< 242000000; i++)
        temp+=temp;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);
    cout<<diff(time1,time2).tv_sec<<":"<<diff(time1,time2).tv_nsec<<endl;
    return 0;
}

timespec diff(timespec start, timespec end)
{
    timespec temp;
    if ((end.tv_nsec-start.tv_nsec)<0) {
        temp.tv_sec = end.tv_sec-start.tv_sec-1;
        temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
    } else {
        temp.tv_sec = end.tv_sec-start.tv_sec;
        temp.tv_nsec = end.tv_nsec-start.tv_nsec;
    }
    return temp;
}

QueryPerformanceCount / QueryPerformanceFrequency: 這應是目前精度最高之函式,精度達微秒,但在 MSDN 上亦註明,此函式若硬體不支援,將只傳回 1000,再用 GetTickCount 代替它 (如果我沒意會錯的話應為如此)。使用此函式時將較耗資源。

#include<windows.h>  
#include<iostream>  
using namespace std;
int main()
{
    double time = 0;
    double counts = 0;
    LARGE_INTEGER nFreq;
    LARGE_INTEGER nBeginTime;
    LARGE_INTEGER nEndTime;
    QueryPerformanceFrequency(&nFreq);
    QueryPerformanceCounter(&nBeginTime);//開始計時  
    for (int i = 0; i<99999; i++)
    {
        counts++;
    }
    QueryPerformanceCounter(&nEndTime);//停止計時  
    time = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) / (double)nFreq.QuadPart;//計算程式執行時間單位為s  
    cout << "程式執行時間:" << time * 1000 << "ms" << endl;
    system("pause");
    return 0;
}

參考資料 https://jerrynest.io/calculate-running-time/ https://blog.gtwang.org/programming/measure-the-execution-time-in-c-language/ https://www.guyrutenberg.com/2007/09/22/profiling-code-using-clock_gettime/