리눅스에서 프로그램 성능을 측정하는 고해상도 타이머를 만드는 방법은 무엇입니까?
GPU와 CPU 성능을 비교하려고 합니다.NVIDIA GPU를 위해 사용해 왔습니다.cudaEvent_t
매우 정확한 타이밍을 얻기 위해 입력합니다.
CPU에 대해 다음 코드를 사용했습니다.
// Timers
clock_t start, stop;
float elapsedTime = 0;
// Capture the start time
start = clock();
// Do something here
.......
// Capture the stop time
stop = clock();
// Retrieve time elapsed in milliseconds
elapsedTime = (float)(stop - start) / (float)CLOCKS_PER_SEC * 1000.0f;
분명히, 그 코드는 당신이 몇 초 안에 셀 때만 유효합니다.또한, 결과는 때때로 꽤 이상하게 나옵니다.
리눅스에서 고해상도 타이머를 만드는 방법을 아는 사람이 있습니까?
체크아웃, 이것은 고해상도 타이머에 대한 POSIX 인터페이스입니다.
만약, 맨 페이지를 읽고 나서, 당신이 다른 것에 대해 궁금해 한다면,CLOCK_REALTIME
그리고.CLOCK_MONOTONIC
CLOCK_REALTIME과 CLOCK_MONOTONIC의 차이점을 확인하십시오.
전체 예는 다음 페이지를 참조하십시오. http://www.guyrutenberg.com/2007/09/22/profiling-code-using-clock_gettime/
#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;
}
지금까지 제시된 정보를 요약하면, 일반적인 애플리케이션에 필요한 두 가지 기능이 있습니다.
#include <time.h>
// call this function to start a nanosecond-resolution timer
struct timespec timer_start(){
struct timespec start_time;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_time);
return start_time;
}
// call this function to end a timer, returning nanoseconds elapsed as a long
long timer_end(struct timespec start_time){
struct timespec end_time;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_time);
long diffInNanos = (end_time.tv_sec - start_time.tv_sec) * (long)1e9 + (end_time.tv_nsec - start_time.tv_nsec);
return diffInNanos;
}
다음은 입력 목록의 분산을 계산하는 데 걸리는 시간을 측정하는 데 사용하는 방법의 예입니다.
struct timespec vartime = timer_start(); // begin a timer called 'vartime'
double variance = var(input, MAXLEN); // perform the task we want to time
long time_elapsed_nanos = timer_end(vartime);
printf("Variance = %f, Time taken (nanoseconds): %ld\n", variance, time_elapsed_nanos);
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
CLOCK_REALTIME_HR도 있습니다만, 차이가 있는지 모르겠습니다.
벽 시간(실제 경과 시간) 또는 사이클 카운트(사이클 수)에 관심이 있습니까?첫 번째 경우에는 다음과 같은 것을 사용해야 합니다.gettimeofday
.
최고 해상도 타이머는RDTSC
x86 어셈블리 명령.그러나 이렇게 하면 시계 눈금이 측정되므로 절전 모드가 비활성화되어 있는지 확인해야 합니다.
TSC의 Wiki 페이지에는 몇 가지 예가 나와 있습니다. http://en.wikipedia.org/wiki/Time_Stamp_Counter
이 스레드를 읽은 후 c++11의 크로노에 대해 clock_gettime 코드를 테스트하기 시작했는데 일치하지 않는 것 같습니다.
그들 사이에는 큰 격차가 있습니다!
std::chrono::seconds(1)는 clock_gettime의 ~70,000과 동일한 것 같습니다.
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <thread>
#include <chrono>
#include <iomanip>
#include <vector>
#include <mutex>
timespec diff(timespec start, timespec end);
timespec get_cpu_now_time();
std::vector<timespec> get_start_end_pairs();
std::vector<timespec> get_start_end_pairs2();
void output_deltas(const std::vector<timespec> &start_end_pairs);
//=============================================================
int main()
{
std::cout << "Hello waiter" << std::endl; // flush is intentional
std::vector<timespec> start_end_pairs = get_start_end_pairs2();
output_deltas(start_end_pairs);
return EXIT_SUCCESS;
}
//=============================================================
std::vector<timespec> get_start_end_pairs()
{
std::vector<timespec> start_end_pairs;
for (int i = 0; i < 20; ++i)
{
start_end_pairs.push_back(get_cpu_now_time());
std::this_thread::sleep_for(std::chrono::seconds(1));
start_end_pairs.push_back(get_cpu_now_time());
}
return start_end_pairs;
}
//=============================================================
std::vector<timespec> get_start_end_pairs2()
{
std::mutex mu;
std::vector<std::thread> workers;
std::vector<timespec> start_end_pairs;
for (int i = 0; i < 20; ++i) {
workers.emplace_back([&]()->void {
auto start_time = get_cpu_now_time();
std::this_thread::sleep_for(std::chrono::seconds(1));
auto end_time = get_cpu_now_time();
std::lock_guard<std::mutex> locker(mu);
start_end_pairs.emplace_back(start_time);
start_end_pairs.emplace_back(end_time);
});
}
for (auto &worker: workers) {
if (worker.joinable()) {
worker.join();
}
}
return start_end_pairs;
}
//=============================================================
void output_deltas(const std::vector<timespec> &start_end_pairs)
{
std::cout << "size: " << start_end_pairs.size() << std::endl;
for (auto it_start = start_end_pairs.begin(); it_start < start_end_pairs.end(); it_start += 2)
{
auto it_end = it_start + 1;
auto delta = diff(*it_start, *it_end);
std::cout
<< std::setw(2)
<< std::setfill(' ')
<< std::distance(start_end_pairs.begin(), it_start) / 2
<< " Waited ("
<< delta.tv_sec
<< "\ts\t"
<< std::setw(9)
<< std::setfill('0')
<< delta.tv_nsec
<< "\tns)"
<< std::endl;
}
}
//=============================================================
timespec diff(timespec start, timespec end)
{
timespec temp;
temp.tv_sec = end.tv_sec-start.tv_sec;
temp.tv_nsec = end.tv_nsec-start.tv_nsec;
if (temp.tv_nsec < 0) {
--temp.tv_sec;
temp.tv_nsec += 1000000000;
}
return temp;
}
//=============================================================
timespec get_cpu_now_time()
{
timespec now_time;
memset(&now_time, 0, sizeof(timespec));
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &now_time);
return now_time;
}
출력:
Hello waiter
0 Waited (0 s 000843254 ns)
1 Waited (0 s 000681141 ns)
2 Waited (0 s 000685119 ns)
3 Waited (0 s 000674252 ns)
4 Waited (0 s 000714877 ns)
5 Waited (0 s 000624202 ns)
6 Waited (0 s 000746091 ns)
7 Waited (0 s 000575267 ns)
8 Waited (0 s 000860157 ns)
9 Waited (0 s 000827479 ns)
10 Waited (0 s 000612959 ns)
11 Waited (0 s 000534818 ns)
12 Waited (0 s 000553728 ns)
13 Waited (0 s 000586501 ns)
14 Waited (0 s 000627116 ns)
15 Waited (0 s 000616725 ns)
16 Waited (0 s 000616507 ns)
17 Waited (0 s 000641251 ns)
18 Waited (0 s 000683380 ns)
19 Waited (0 s 000850205 ns)
epoll 구현: https://github.com/ielife/simple-timer-for-c-language
다음과 같이 사용:
timer_server_handle_t *timer_handle = timer_server_init(1024);
if (NULL == timer_handle) {
fprintf(stderr, "timer_server_init failed\n");
return -1;
}
ctimer timer1;
timer1.count_ = 3;
timer1.timer_internal_ = 0.5;
timer1.timer_cb_ = timer_cb1;
int *user_data1 = (int *)malloc(sizeof(int));
*user_data1 = 100;
timer1.user_data_ = user_data1;
timer_server_addtimer(timer_handle, &timer1);
ctimer timer2;
timer2.count_ = -1;
timer2.timer_internal_ = 0.5;
timer2.timer_cb_ = timer_cb2;
int *user_data2 = (int *)malloc(sizeof(int));
*user_data2 = 10;
timer2.user_data_ = user_data2;
timer_server_addtimer(timer_handle, &timer2);
sleep(10);
timer_server_deltimer(timer_handle, timer1.fd);
timer_server_deltimer(timer_handle, timer2.fd);
timer_server_uninit(timer_handle);
언급URL : https://stackoverflow.com/questions/6749621/how-to-create-a-high-resolution-timer-in-linux-to-measure-program-performance
'programing' 카테고리의 다른 글
UI 테이블 보기:일부 행만 선택하고 다른 행은 선택하지 않는 방법 (0) | 2023.06.15 |
---|---|
C 프로그램에는 main()이 필요합니까? (0) | 2023.06.15 |
재할당이 이전 내용을 덮어쓰나요? (0) | 2023.06.15 |
화이트리스트에 있는 링크에 대해 Firebase에서 "도메인이 화이트리스트에 없음"으로 표시됨 (0) | 2023.06.10 |
Scikit 학습의 랜덤 상태(의사 난수) (0) | 2023.06.10 |