I have a problem in using time. I want to use and get microseconds on windows using C++.
我无法找到办法。
I have a problem in using time. I want to use and get microseconds on windows using C++.
我无法找到办法。
The “canonical” questionnaire was given by unwind/strong>:
一种受欢迎的方式是使用QueryPerformanceCounter()电话。
然而,这种方法存在的问题很少:
QueryPerformanceCounter
is not implemented in user space; this means context switch is needed to call kernel side of implementation, and that is relatively expensive (around 0.7 microsecond). This seems to be required to support legacy hardware.但并非全部损失。 第1点和第2点是你可以做的编码范围,3点可以直接打电话给RDTSC(可通过<代码>__rdtsc(<> 固有”),只要你知道CPU24的准确频率的话。 虽然在旧的CPU上,这种呼吁可能会受到内部锁定速度的改变,但在所有新的英特尔公司和AMD CPU中,这种呼吁得到保证,能够取得相当准确的结果,并受到CPU锁(例如电力储蓄特征)的改变的影响。
让我们从1开始。 这里的数据结构是掌握校准数据:
struct init
{
long long stamp; // last adjustment time
long long epoch; // last sync time as FILETIME
long long start; // counter ticks to match epoch
long long freq; // counter frequency (ticks per 10ms)
void sync(int sleep);
};
init data_[2] = {};
const init* volatile init_ = &data_[0];
这里是初步校准守则;必须给它时间(流利器)以等待24小时搬迁;我发现,500毫秒(时间越短,精确的校准)。 为了便于使用,我们将使用<代码>。 证书/编码等。 仅需要将其称作<条码>数据_[0]条码>,因为<条码>数据_[...]/条码>将通过定期24小时调整加以更新(见下文)。
void init::sync(int sleep)
{
LARGE_INTEGER t1, t2, p1, p2, r1, r2, f;
int cpu[4] = {};
// prepare for rdtsc calibration - affinity and priority
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
SetThreadAffinityMask(GetCurrentThread(), 2);
Sleep(10);
// frequency for time measurement during calibration
QueryPerformanceFrequency(&f);
// for explanation why RDTSC is safe on modern CPUs, look for "Constant TSC" and "Invariant TSC" in
// Intel(R) 64 and IA-32 Architectures Software Developer’s Manual (document 253668.pdf)
__cpuid(cpu, 0); // flush CPU pipeline
r1.QuadPart = __rdtsc();
__cpuid(cpu, 0);
QueryPerformanceCounter(&p1);
// sleep some time, doesn t matter it s not accurate.
Sleep(sleep);
// wait for the system clock to move, so we have exact epoch
GetSystemTimeAsFileTime((FILETIME*) (&t1.u));
do
{
Sleep(0);
GetSystemTimeAsFileTime((FILETIME*) (&t2.u));
__cpuid(cpu, 0); // flush CPU pipeline
r2.QuadPart = __rdtsc();
} while(t2.QuadPart == t1.QuadPart);
// measure how much time has passed exactly, using more expensive QPC
__cpuid(cpu, 0);
QueryPerformanceCounter(&p2);
stamp = t2.QuadPart;
epoch = t2.QuadPart;
start = r2.QuadPart;
// calculate counter ticks per 10ms
freq = f.QuadPart * (r2.QuadPart-r1.QuadPart) / 100 / (p2.QuadPart-p1.QuadPart);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
SetThreadAffinityMask(GetCurrentThread(), 0xFF);
}
有了良好的校准数据,你可以计算低廉的低温和反应能力的确切时间(我对电传和计算进行了测量,在我的机器上为大约25纳米秒)。 值得注意的是:
返回类型是符合国际自由职业和专业技能评估体系结构的双轨,与<代码”不同,准确到100人。 GetSystemtimeAsFiletime(在1030天或10 000天以上或1毫秒之间加薪)。
为了避免将昂贵的重新分类为两倍于累犯,整个计算是在64个轨道分类账中进行的。 尽管这些数字可能很多,但确实存在着造成分类过度流动的风险,因此,必须定期提交<条码>><>启动/代码>,以避免出现这种情况。 这样做是为了进行24小时调整。
我们正在提供校准数据的副本,因为在我们的呼吁中,可以通过在另一条路面进行锁定调整来加以更新。
在这里,该守则将非常精确地阅读目前的时间。 回归价值是与国际自由职业观察所兼容的双倍,即自1 1601年1月以来100-nanosecond的间隔。
long long now()
{
// must make a copy
const init* it = init_;
// __cpuid(cpu, 0) - no need to flush CPU pipeline here
const long long p = __rdtsc();
// time passed from epoch in counter ticks
long long d = (p - it->start);
if (d > 0x80000000000ll)
{
// closing to integer overflow, must adjust now
adjust();
}
// convert 10ms to 100ns periods
d *= 100000ll;
d /= it->freq;
// and add to epoch, so we have proper FILETIME
d += it->epoch;
return d;
}
为了进行24小时调整,我们需要抓住确切的时间(按系统锁定)并将时间与我们24小时进行比较;这将给我们带来流动价值。 其次,我们采用简单的公式计算“调整后的”通用报告格式频率,以便在下一次调整时锁定我们的锁定会。 因此,必须定期进行调整;我发现,每次15分钟,调整工作都很好。 我使用<代码>Createtimer Queuetimer,在计划启动时,一度要求安排调整电话(此处没有说明)。
掌握准确的系统时间(用于计算漂流)的轻微问题是,我们需要等到这个系统24小时才能移动,这可能需要30毫米秒左右(long)。 如不进行调整,则有可能在职能<代码>now(<>>>/代码>内进行批发,更不用提从系统锁上未经校正的流出。 在<代码>now()中,防止超支,但我们确实不想在错误时刻用“now(<<><><>>>>/code”号”的透镜中 trigger。
这里是定期24小时调整的代码,24小时流放载于r->epoch - r->stamp
:
void adjust()
{
// must make a copy
const init* it = init_;
init* r = (init_ == &data_[0] ? &data_[1] : &data_[0]);
LARGE_INTEGER t1, t2;
// wait for the system clock to move, so we have exact time to compare against
GetSystemTimeAsFileTime((FILETIME*) (&t1.u));
long long p = 0;
int cpu[4] = {};
do
{
Sleep(0);
GetSystemTimeAsFileTime((FILETIME*) (&t2.u));
__cpuid(cpu, 0); // flush CPU pipeline
p = __rdtsc();
} while (t2.QuadPart == t1.QuadPart);
long long d = (p - it->start);
// convert 10ms to 100ns periods
d *= 100000ll;
d /= it->freq;
r->start = p;
r->epoch = d + it->epoch;
r->stamp = t2.QuadPart;
const long long dt1 = t2.QuadPart - it->epoch;
const long long dt2 = t2.QuadPart - it->stamp;
const double s1 = (double) d / dt1;
const double s2 = (double) d / dt2;
r->freq = (long long) (it->freq * (s1 + s2 - 1) + 0.5);
InterlockedExchangePointer((volatile PVOID*) &init_, r);
// if you have log output, here is good point to log calibration results
}
最后,两个公用事业职能。 一种做法是将国际电算和测算系统(包括从<代码>now(<>>>>>>>/代码>)转换成SYSTEMT,同时将微型秒转换成单独的<代码>int。 另一些则将返回频率,因此贵方案可直接使用<代码>_rdtsc(>,以便准确测量时间间隔(精确度为纳米秒)。
void convert(SYSTEMTIME& s, int &us, long long f)
{
LARGE_INTEGER i;
i.QuadPart = f;
FileTimeToSystemTime((FILETIME*) (&i.u), &s);
s.wMilliseconds = 0;
LARGE_INTEGER t;
SystemTimeToFileTime(&s, (FILETIME*) (&t.u));
us = (int) (i.QuadPart - t.QuadPart)/10;
}
long long frequency()
{
// must make a copy
const init* it = init_;
return it->freq * 100;
}
当然,上述内容中没有一个比你的系统锁更准确,这不可能比几百毫秒。 上文实施的
我认为,它做得很好。 例使用是标志,其中人们不仅可以使用时间序列来确定事件的时间,而且还可以说明内部方案的时间、相对性(微观轨道)等原因。
我将管道(用于初步校准、时间安排调整)作为硬体读物者的一种做法。
你们可以使用提高日期的图书馆。
You can use boost::posix_time::hours, boost::posix_time::minutes, boost::posix_time::seconds, boost::posix_time::millisec, boost::posix_time::nanosec
一种受欢迎的方式是使用<代码>。 QueryPerformanceCounter(> calls。 如果你需要高精度的时间,例如只按摩擦顺序衡量期限,那是有用的。 我认为,通过<条码>RDTSC的机器指示实施。
可能会出现一些问题,例如,相对频率与节能不同,以及多个核心之间的同步。 关于这些问题的详情,见上文Wikipedia链接。
查阅:。
可帮助:
NTSTATUS WINAPI NtQuerySystemTime(__out PLARGE_INTEGER SystemTime);
系统时间——接收系统时间的LARGE-INTEERT结构的协调人。 这是自1月1日1 1601(UTC)以来100-nanosecond的64倍值。