我正在撰寫一個 cuda 庫,我需要檢查選項 CPU 和 GPU 之間的性能差異。因此,我創建了一個名為 Timer 的簡單類來測量首先執行 GPU 功能和 CPU 版本所需的時間。
class Timer
{
public:
Timer()
{
_StartTimepoint = std::chrono::steady_clock::now();
}
~Timer() {}
void Stop()
{
_stopped = true;
using namespace std::chrono;
auto endTimepoint = steady_clock::now();
auto start = time_point_cast<milliseconds>(_StartTimepoint).time_since_epoch().count();
auto end = time_point_cast<milliseconds>(endTimepoint).time_since_epoch().count();
auto _ms = end - start;
_secs = _ms / 1000;
_ms -= _secs * 1000;
_mins = _secs / 60;
_secs -= _mins * 60;
_hour = _mins / 60;
_mins -= _hour * 60;
}
double GetTime(){
if(_stopped == true)
return _ms;
else{
Stop();
return _ms;
}
}
private:
std::chrono::time_point< std::chrono::steady_clock> _StartTimepoint;
double _secs,_ms,_mins,_hour;
bool _stopped = false;
};
因為我需要檢查引數 m 的不同值的性能,所以我只需在 for 回圈中運行這兩個函式,如您所見:
for (size_t m = MIN_M; m < MAX_M; m =M_STEP){
m_array[m_cont] = m;
//simulate
double time_gpu,time_cpu;
Timer timer_gpu;
run_device(prcr_args,seeds,&m_array[m_cont]);
timer_gpu.Stop();
time_gpu = timer_gpu.GetTime();
Timer timer_cpu;
simulate_host(prcr_args,seeds,&m_array[m_cont]);
timer_cpu.Stop();
time_cpu = timer_cpu.GetTime();
double g = time_cpu/time_gpu;
ofs << m //stream to print the results
<< "," << time_cpu
<< "," << time_gpu
<< "," << g << "\n";
m_cont ;
}
問題是我獲得的結果非常小而且明顯是錯誤的,因為它們都是相等的(執行時間應該隨著 m 增加)并且我的代碼需要幾分鐘才能運行。
m,cpu_time,gpu_time,g
10,9.88131e-324,6.90979e-310,1.43004e-14
15,9.88131e-324,6.90979e-310,1.43004e-14
....
90,9.88131e-324,6.90979e-310,1.43004e-14
95,9.88131e-324,6.90979e-310,1.43004e-14
100,9.88131e-324,6.90979e-310,1.43004e-14
我的猜測是 CPU 不會按順序執行回圈,因此會立即啟動和停止時鐘。
uj5u.com熱心網友回復:
您宣告一個與成員變數同名的區域變數 _ms。在停止函式期間,區域變數優先于成員變數,因此您永遠不會在成員中實際存盤值。您可以通過將成員初始化為類定義中的某個值來顯示這一點,您將看到最后彈出相同的值。'auto' 與它無關 - 將其嚴格定義為 double 將具有與創建優先于成員的本地相同的結果。
因為您未初始化該成員,所以它會填充在創建它的堆疊上發生的任何內容。這就是為什么定時器的每個實體在回圈中都具有相同的值。
一個非常小的修復:
auto _msB = end - start;
_secs = _msB / 1000;
_ms = _msB - _secs * 1000;
您還應該初始化您的成員變數,以便除錯更容易,即使它們在使用程序中會被覆寫。
我也鼓勵讓 chrono 庫為你做更多的作業。一個非常簡短的片段是:
auto duration = endTimepoint - _StartTimepoint;
auto ms = duration_cast<milliseconds>(duration);
_ms = ms.count();
您可以為每個單位型別的名稱進行持續時間轉換,而不會在轉換時出現拼寫錯誤或不必要地丟失精度。
我不確定為什么要將差分時間數字作為計時器的一部分,但是如果您必須執行該算術運算,則可以通過對持續時間轉換產生的計數值使用 std::ratio 來實作。
uj5u.com熱心網友回復:
問題按以下順序排列:
auto _ms = end - start;
_secs = _ms / 1000;
_ms -= _secs * 1000;
_mins = _secs / 60;
_secs -= _mins * 60;
_hour = _mins / 60;
_mins -= _hour * 60;
如評論中所示,
auto正在創建一個新的區域變數。可能不是你想要的。似乎算術的目的是只留下毫秒部分
_ms。由于這是您要回傳的數量,如果這是真的,您的GetTime()方法只會回傳 0 到 999 之間的值。由于您的成員變數是 type
double,而不是整數型別:double _secs,_ms,_mins,_hour;這個算術沒有做你想要的:
_secs = _ms / 1000; _ms -= _secs * 1000;那不是整數除法。
考慮到這些想法,修復Timer課程的路線圖可能如下所示:
class Timer
{
public:
Timer()
{
_StartTimepoint = std::chrono::steady_clock::now();
}
~Timer() {}
void Stop()
{
_stopped = true;
using namespace std::chrono;
auto endTimepoint = steady_clock::now();
auto start = time_point_cast<milliseconds>(_StartTimepoint).time_since_epoch().count();
auto end = time_point_cast<milliseconds>(endTimepoint).time_since_epoch().count();
_ms = end - start;
_secs = _ms / 1000;
_ms -= _secs * 1000;
_mins = _secs / 60;
_secs -= _mins * 60;
_hour = _mins / 60;
_mins -= _hour * 60;
}
double GetTime(){
if(!_stopped) Stop();
return _ms (((_hour * 60) _mins)*60 _secs) * 1000;
}
private:
std::chrono::time_point< std::chrono::steady_clock> _StartTimepoint;
size_t _secs,_ms,_mins,_hour;
bool _stopped = false;
};
我還沒有徹底測驗過。當然,這一切都與此無關cuda。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/524126.html
標籤:C c 11库达
上一篇:如何呼叫回傳函式指標的函式?
下一篇:定時器結束時做點什么[JS]
