이 새로운 답변은 C ++ 11의 <chrono>
기능을 사용합니다. 사용하는 방법을 보여 다른 답변이 있지만 <chrono>
, 그들 중 누구도 사용하는 방법을 보여줍니다 <chrono>
와 RDTSC
여기에 다른 답변의 여러에서 언급 한 시설. 그래서 제가 사용하는 방법을 보여 것이라고 생각 RDTSC
으로 <chrono>
. 또한 , 및 / 또는을 RDTSC
기반으로하는 시스템의 내장 클록 기능 사이를 빠르게 전환 할 수 있도록 클록에서 테스트 코드를 템플릿 화하는 방법을 보여줄 것 입니다.clock()
clock_gettime()
QueryPerformanceCounter
참고 것을 RDTSC
명령은 86 별이다. QueryPerformanceCounter
Windows 전용입니다. 그리고 clock_gettime()
POSIX 전용입니다. 아래에서 두 가지 새로운 시계를 소개합니다. std::chrono::high_resolution_clock
및 std::chrono::system_clock
, C ++ 11을 가정 할 수 있다면 이제 크로스 플랫폼입니다.
먼저, Intel rdtsc
어셈블리 명령어 에서 C ++ 11 호환 시계를 만드는 방법이 있습니다 . 나는 그것을 부를 것이다 x::clock
:
#include <chrono>
namespace x
{
struct clock
{
typedef unsigned long long rep;
typedef std::ratio<1, 2'800'000'000> period; // My machine is 2.8 GHz
typedef std::chrono::duration<rep, period> duration;
typedef std::chrono::time_point<clock> time_point;
static const bool is_steady = true;
static time_point now() noexcept
{
unsigned lo, hi;
asm volatile("rdtsc" : "=a" (lo), "=d" (hi));
return time_point(duration(static_cast<rep>(hi) << 32 | lo));
}
};
} // x
이 클럭이하는 일은 CPU주기를 계산하고 부호없는 64 비트 정수에 저장하는 것입니다. 컴파일러의 어셈블리 언어 구문을 조정해야 할 수도 있습니다. 또는 컴파일러가 대신 사용할 수있는 내장 함수를 제공 할 수 있습니다 (예 :) now() {return __rdtsc();}
.
시계를 만들려면 표시 (저장 유형)를 제공해야합니다. 또한 시스템이 다른 전원 모드에서 클럭 속도를 변경할 수 있더라도 컴파일 시간 상수 여야하는 클럭 기간을 제공해야합니다. 또한 이러한 기본 사항에 따라 시계의 "기본"시간 기간과 시점을 쉽게 정의 할 수 있습니다.
당신이 원하는 것이 클럭 틱의 수를 출력하는 것이라면, 클럭 기간 동안 어떤 숫자를 제공하든 상관 없습니다. 이 상수는 클럭 틱 수를 나노초와 같은 실시간 단위로 변환하려는 경우에만 작동합니다. 이 경우 클록 속도를 더 정확하게 제공할수록 나노초 (밀리 초 등) 로의 변환이 더 정확 해집니다.
다음은 사용 방법을 보여주는 예제 코드입니다 x::clock
. 실제로 동일한 구문으로 여러 다른 시계를 사용할 수있는 방법을 보여주고 싶기 때문에 시계에 코드를 템플릿으로 작성했습니다. 이 특정 테스트는 루프에서 원하는 시간을 실행할 때 루프 오버 헤드가 무엇인지 보여줍니다.
#include <iostream>
template <class clock>
void
test_empty_loop()
{
// Define real time units
typedef std::chrono::duration<unsigned long long, std::pico> picoseconds;
// or:
// typedef std::chrono::nanoseconds nanoseconds;
// Define double-based unit of clock tick
typedef std::chrono::duration<double, typename clock::period> Cycle;
using std::chrono::duration_cast;
const int N = 100000000;
// Do it
auto t0 = clock::now();
for (int j = 0; j < N; ++j)
asm volatile("");
auto t1 = clock::now();
// Get the clock ticks per iteration
auto ticks_per_iter = Cycle(t1-t0)/N;
std::cout << ticks_per_iter.count() << " clock ticks per iteration\n";
// Convert to real time units
std::cout << duration_cast<picoseconds>(ticks_per_iter).count()
<< "ps per iteration\n";
}
이 코드가 수행하는 첫 번째 작업은 결과를 표시 할 "실시간"단위를 만드는 것입니다. 피코 초를 선택했지만 정수 또는 부동 소수점 기반 중에서 원하는 단위를 선택할 수 있습니다. 예를 들어 std::chrono::nanoseconds
내가 사용할 수 있는 미리 만들어진 장치가 있습니다.
또 다른 예로, 반복 당 평균 클럭 사이클 수를 부동 소수점으로 인쇄하고 싶으므로, 클럭의 틱 ( Cycle
코드에서 호출 됨)과 동일한 단위를 갖는 double을 기준으로 다른 기간을 만듭니다 .
루프는 clock::now()
양쪽 에 대한 호출로 시간이 설정됩니다. 이 함수에서 반환 된 유형의 이름을 지정하려면 다음과 같습니다.
typename clock::time_point t0 = clock::now();
( x::clock
예제에 명확하게 표시되어 있으며 시스템 제공 시계에도 해당됨).
부동 소수점 클록 틱의 관점에서 기간을 얻으려면 1은 단순히 두 시점을 빼고 반복 당 값을 얻으려면 해당 기간을 반복 횟수로 나눕니다.
count()
멤버 함수 를 사용하여 기간에 관계없이 개수를 가져올 수 있습니다 . 이것은 내부 표현을 반환합니다. 마지막으로 std::chrono::duration_cast
기간 Cycle
을 기간으로 변환하여 picoseconds
인쇄합니다.
이 코드를 사용하는 방법은 간단합니다.
int main()
{
std::cout << "\nUsing rdtsc:\n";
test_empty_loop<x::clock>();
std::cout << "\nUsing std::chrono::high_resolution_clock:\n";
test_empty_loop<std::chrono::high_resolution_clock>();
std::cout << "\nUsing std::chrono::system_clock:\n";
test_empty_loop<std::chrono::system_clock>();
}
나는 우리 집에서 만든을 사용하여 시험을 행사보다도 x::clock
, 시스템이 제공하는 시계 두 개를 사용하여 그 결과를 비교 : std::chrono::high_resolution_clock
와 std::chrono::system_clock
. 나를 위해 이것은 다음과 같이 인쇄됩니다.
Using rdtsc:
1.72632 clock ticks per iteration
616ps per iteration
Using std::chrono::high_resolution_clock:
0.620105 clock ticks per iteration
620ps per iteration
Using std::chrono::system_clock:
0.00062457 clock ticks per iteration
624ps per iteration
이것은 반복 당 틱이 각 클록마다 크게 다르기 때문에 이러한 클록 각각이 다른 틱주기를 가지고 있음을 보여줍니다. 그러나 알려진 시간 단위 (예 : 피코 초)로 변환하면 각 시계에 대해 거의 동일한 결과를 얻습니다 (마일리지는 다를 수 있음).
내 코드에 "매직 변환 상수"가 완전히 없는지 확인하십시오. 실제로 전체 예제에는 두 개의 매직 넘버 만 있습니다.
- 정의하기 위해 내 컴퓨터의 클럭 속도
x::clock
.
- 테스트 할 반복 횟수입니다. 이 숫자를 변경하면 결과가 크게 달라지는 경우 반복 횟수를 늘리거나 테스트하는 동안 컴퓨터에서 경쟁 프로세스를 비워야합니다.