chrono는 C++11에서 새로 추가된 시간 라이브러리입니다. 기존의 C 런타임에서 제공하는 time 함수에 비해서 다양한 기능이 있고, 사용이 쉽고 정밀도는 훨씬 높습니다. time 함수는 초 단위의 값만 측정할 수 있는 것에 비해 chrono는 나노 밀리 초 단위도 측정할 수 있습니다.
현재의 C++(C++03)에서는 초 단위보다 더 정밀한 단위로 시간을 측정할 때는 OS에서 제공하는 API를 사용해야 했는데 chrono를 사용하면 OS 독립적으로 높은 단위의 시간을 측정할 수 있습니다.
VC10에서는 chrono가 들어가지 않았지만 이번 VC11에서 chrono는 STL에 들어갔습니다. 만약 VC11을 사용하지 못하는 경우라면 Boost 라이브러리를 사용하면 사용할 수 있습니다.
chrono를 사용하면 특정 시간 구간에 걸린 시간을 초, 밀리 초, 나노 초 단위로 얻을 수 있으며 또 시간끼리 연산을 할 수 있습니다
chrono 사용 방법
chrono를 사용하기 위해서는 아래의 헤더 파일을 추가합니다.
#include <chrono>
chrono에 대한 자세한 설명에 앞서 어떤 기능인지 좀 더 쉽게 알 수 있도록 예제를 하나 보여드리겠습니다. 아래의 예제는 어떤 함수의 성능을 측정하기 위해서 chrono를 사용했습니다.
< 예제. 1 >
#include <chrono>
#include <iostream>
#include <cmath>
void Test()
{
for ( long i = 0; i < 10000000; ++i )
{
std::sqrt( 123.456L );
}
}
int main()
{
std::chrono::system_clock::time_point start = std::chrono::system_clock::now();
Test();
std::chrono::duration<double> sec = std::chrono::system_clock::now() - start;
std::cout << "Test() 함수를 수행하는 걸린 시간(초) : " << sec.count() << " seconds" << std::endl;
return 0;
}
< 실행 결과 >
<예제.1>에서는 std::chrono::system_clock::now()을 사용하여 현재 시간을 얻습니다.
std::chrono::system_clock::time_point start = std::chrono::system_clock::now();
여기서 time_point 타입은 시간 상의 한 축을 뜻합니다.
이후 Test() 함수를 실행한 후 다시 현재 시간을 얻은 후 Test()를 시작하기 전에 저장한 현지 시간을 빼면 Test()를 수행하는 걸린 시간을 얻을 수 있습니다.
std::chrono::duration<double> sec = std::chrono::system_clock::now() - start;
* std::chrono::system_clock::now()에 의해서 얻는 시간의 초기 시간은 1970년 입니다.
시간 단위
chrono는 경과 시간을 계산할 때 다양한 시간 타입으로 계산할 수 있습니다.
<예제.1>에서는 초 단위의 정밀도로 소수점까지 표시할 수 있었습니다.
std::chrono::duration<double> sec = std::chrono::system_clock::now() - start;
그런데 보통은 소수점이 나오는 결과 값보다는 정수로 나오는 값을 사용하는 경우가 많을 것입니다.
chrono에서는 경과 시간을 나타내는 클래스는 duration입니다.
duration은 6개의 시간 단위를 지원합니다.
std::chrono::nanoseconds // 나노 세컨드. 10억분의 1초
std::chrono::microseconds // 마이크로 세컨드. 100만분의 1초
std::chrono::milliseconds // 밀리 세컨드. 1000분의 1초
std::chrono::seconds // 초
std::chrono::minutes // 분
std::chrono::hours // 시
<예제.1>을 수정하여 위에 열거한 chrono의 다양한 단위를 사용하여 시간 측정을 해 보겠습니다.
< 예제. 2 >
#include <chrono>
#include <iostream>
#include <cmath>
void Test()
{
for ( long i = 0; i < 10000000; ++i )
{
std::sqrt( 123.456L );
}
}
int main()
{
std::chrono::system_clock::time_point StartTime = std::chrono::system_clock::now();
Test();
std::chrono::system_clock::time_point EndTime = std::chrono::system_clock::now();
std::chrono::duration<double> DefaultSec = EndTime - StartTime;
std::chrono::nanoseconds nano = EndTime - StartTime;
std::chrono::microseconds micro = std::chrono::duration_cast<std::chrono::microseconds>(EndTime - StartTime);
std::chrono::milliseconds mill = std::chrono::duration_cast<std::chrono::milliseconds>(EndTime - StartTime);
std::chrono::seconds sec = std::chrono::duration_cast<std::chrono::seconds>(EndTime - StartTime);
std::chrono::minutes min = std::chrono::duration_cast<std::chrono::minutes>(EndTime - StartTime);
std::chrono::hours hour = std::chrono::duration_cast<std::chrono::hours>(EndTime - StartTime);
std::cout << "Test() 함수를 수행하는 걸린 시간 : " << DefaultSec.count() << " default" << std::endl;
std::cout << "Test() 함수를 수행하는 걸린 시간 : " << nano.count() << " nanoseconds" << std::endl;
std::cout << "Test() 함수를 수행하는 걸린 시간 : " << micro.count() << " microseconds" << std::endl;
std::cout << "Test() 함수를 수행하는 걸린 시간 : " << mill.count() << " milliseconds" << std::endl;
std::cout << "Test() 함수를 수행하는 걸린 시간 : " << sec.count() << " seconds" << std::endl;
std::cout << "Test() 함수를 수행하는 걸린 시간 : " << min.count() << " minutes" << std::endl;
std::cout << "Test() 함수를 수행하는 걸린 시간 : " << hour.count() << " hour" << std::endl;
return 0;
}
< 실행 결과 >
http://sweeper.egloos.com/2996847
- GetTickCount
- timeGetTime : 멀티미디어 라이브러리를 이용 (Windows.h와 winmm.lib 필요)
- #include <Windows.h>
- #pragma comment(lib, "winmm.lib")
- timeBeginPeriod(1);
- // ...timeGetTime 사용
- // timeEndPeriod의 인자값은 timeBeginPeriod에서 설정한 인자값과 동일해야 한다
- timeEndPeriod(1);
- #include <chrono>
- /-
- namespace std
- {
- namespace chrono
- {
- }
- }
- *-
- // 즉, 주로 사용시엔 아래와 같이 using namespace를 쓰는 게 편하다.
- using namespace std;
- using namespace chrono;
- #include <chrono>
- using namespace std;
- using namespace chrono;
- // Debug 모드로 재 보니, i5-750에서 9.87초나 걸린다
- void BigLoop()
- {
- for (int i = 1; i <= 50000; i++)
- {
- for (int j = 1; j <= 50000; j++)
- {
- int x = (i + j) * 2 + (i / j);
- }
- }
- }
- int main()
- {
- // now() 함수를 통해 현재 시간값을 구한다.
- system_clock::time_point start = system_clock::now();
- BigLoop();
- system_clock::time_point end = system_clock::now();
- // 초 단위 (소수점으로 표현)
- duration<double> sec = end - start;
- }
- static time_point now() _NOEXCEPT
- {
- // get current time
- return (time_point(duration(_Xtime_get_ticks())));
- }
- template<class _Clock, class _Duration = typename _Clock::duration>
- class time_point
- { // represents a point in time
- public:
- typedef _Clock clock;
- typedef _Duration duration;
- typedef typename _Duration::rep rep;
- typedef typename _Duration::period period;
- time_point() : _MyDur(_Duration::zero())
- { // check asserts
- static_assert(_Is_duration<_Duration>::value,
- "duration must be an instance of std::duration");
- }
- explicit time_point(const _Duration& _Other) : _MyDur(_Other)
- { // construct from a duration
- }
- template<class _Duration2>
- time_point(const time_point<_Clock, _Duration2>& _Tp,
- typename enable_if<is_convertible<_Duration2, _Duration>::value, void>::type ** = 0)
- : _MyDur(_Tp.time_since_epoch())
- { // construct from another duration
- }
- _Duration time_since_epoch() const
- { // get duration from epoch
- return (_MyDur);
- }
- time_point& operator+=(const _Duration& _Dur)
- { // increment by duration
- _MyDur += _Dur;
- return (*this);
- }
- time_point& operator-=(const _Duration& _Dur)
- { // decrement by duration
- _MyDur -= _Dur;
- return (*this);
- }
- static time_point (min)()
- { // get minimum time point
- return (time_point((_Duration::min)()));
- }
- static time_point (max)()
- { // get maximum time point
- return (time_point((_Duration::max)()));
- }
- private:
- _Duration _MyDur; // duration since the epoch
- };
- typedef duration<int, ratio<3600> > hours;
- typedef duration<int, ratio<60> > minutes;
- typedef duration<long long> seconds;
- typedef duration<long long, milli> milliseconds;
- typedef duration<long long, micro> microseconds;
- typedef duration<long long, nano> nanoseconds;
- system_clock::time_point start = system_clock::now();
- BigLoop();
- system_clock::time_point end = system_clock::now();
- // 시간 단위
- hours hour = duration_cast<hours>(end - start);
- // 분 단위
- minutes min = duration_cast<minutes>(end - start);
- // 초 단위
- duration<double> sec = end - start;
- // 밀리 초 단위 (1/1000)
- milliseconds milliSec = duration_cast<milliseconds>(end - start);
- // 마이크로 초 단위 (1/1000000)
- microseconds microSec = duration_cast<microseconds>(end - start);
- // 나노 초 단위 (1/1000000000)
- nanoseconds nanoSec = end - start;
- // 밀리 초 단위를 double로 표현하고 싶다.
- typedef duration<double, milli> doublemillisec;
- doublemillisec doubleMilliSec = duration_cast<doublemillisec>(end - start);
- // _Rep : 표현하고자 하는 단위의 타입 (즉, long, double)
- // _Period : 시간 단위를 얼마의 비율로 보여 줄것인가? (1/1000인가? milli, 1/1000000인가? micro)
- template<class _Rep, class _Period>
- class duration
- { // represents a time duration
- // ...
- // 기본 사칙 연산과 % 연산자를 지원한다.
- };
- typedef ratio<1, (_LONGLONG)1000000000 * 1000000000> atto;
- typedef ratio<1, (_LONGLONG)1000000 * 1000000000> femto;
- typedef ratio<1, (_LONGLONG)1000 * 1000000000> pico;
- typedef ratio<1, 1000000000> nano;
- typedef ratio<1, 1000000> micro;
- typedef ratio<1, 1000> milli;
- typedef ratio<1, 100> centi;
- typedef ratio<1, 10> deci;
- typedef ratio<10, 1> deca;
- typedef ratio<100, 1> hecto;
- typedef ratio<1000, 1> kilo;
- typedef ratio<1000000, 1> mega;
- typedef ratio<1000000000, 1> giga;
- typedef ratio<(_LONGLONG)1000 * 1000000000, 1> tera;
- typedef ratio<(_LONGLONG)1000000 * 1000000000, 1> peta;
- typedef ratio<(_LONGLONG)1000000000 * 1000000000, 1> exa;
- system_clock
- steady_clock
- high_resolution_clock
- process_real_cpu_clock
- process_user_cpu_clock
- process_system_cpu_clock
- process_cpu_clock
- thread_clock
- system_clock
- steady_clock
- high_resolution_clock
- // time_point -> time_t
- system_clock::time_point currTimePoint = system_clock::now();
- time_t currTime = system_clock::to_time_t(currTimePoint);
- // time_t -> time_point
- time_t currTime = time(nullptr);
- system_clock::time_point currTimePoint = system_clock::from_time_t(currTime);
- class steady_clock : public system_clock
- { // wraps monotonic clock
- public:
- static const bool is_monotonic = true; // retained
- static const bool is_steady = true;
- };
- typedef steady_clock monotonic_clock; // retained
- CPU : i5-750 no overclock
- RAM : 4GB
- #include <Windows.h>
- #include <iostream>
- #include <chrono>
- using namespace std;
- using namespace chrono;
- void ChronoLoop()
- {
- system_clock::time_point start;
- for (int i = 1; i <= 10000; i++)
- {
- for (int j = 1; j <= 10000; j++)
- {
- start = system_clock::now();
- }
- }
- }
- void QueryLoop()
- {
- LARGE_INTEGER li;
- for (int i = 1; i <= 10000; i++)
- {
- for (int j = 1; j <= 10000; j++)
- {
- QueryPerformanceCounter(&li);
- }
- }
- }
- typedef duration<double, milli> doublemillisec;
- int main()
- {
- system_clock::time_point start = system_clock::now();
- ChronoLoop();
- system_clock::time_point end = system_clock::now();
- doublemillisec doubleMilliSec = duration_cast<doublemillisec>(end - start);
- cout << "ChronoLoop: " << doubleMilliSec.count() << endl;
- start = system_clock::now();
- QueryLoop();
- end = system_clock::now();
- doubleMilliSec = duration_cast<doublemillisec>(end - start);
- cout << "QueryLoop: " << doubleMilliSec.count() << endl;
- return 0;
- }
'메타프로그래밍 > Boost::' 카테고리의 다른 글
boost::unordered_map (0) | 2012.11.13 |
---|---|
boost::filesystem (파일, 디렉터리 다루기) (0) | 2012.11.04 |
Chapter 6. Boost.Container - 번역중 (0) | 2012.10.27 |
Chapter 2. Boost.Any (0) | 2012.10.27 |
Chapter 1. Boost.Accumulators (0) | 2012.10.27 |