是否有时间函数,其结果保证每次调用都会改变?

时间:2014-06-07 17:47:12

标签: c++ windows synchronization

我试过GetTickCount64(),直到我尝试了这个:

#include <fstream>
#include <windows.h>
#include <iostream>

void doSomething();

int main() {
srand(GetTickCount64());
std::fstream file;
file.open("test.dat", std::ios_base::out | std::ios_base::trunc);

    for (;;)
        file <<std::boolalpha<<(GetTickCount64()==GetTickCount64()) << std::endl;
}

而且:

#include <fstream>
#include <windows.h>
#include <iostream>

void doSomething();

int main() {
srand(GetTickCount64());
std::fstream file;
file.open("test.dat", std::ios_base::out | std::ios_base::trunc);

__int64 a, b;
for (;;) {
    a = GetTickCount64();
    doSomething();
    b = GetTickCount64();
    file <<std::boolalpha<<(a==b) << std::endl;
    }
}

void doSomething() {
int T=(see below);
    for (int i = 0; i < (rand() % T); i++)
        __noop;
}

对于第一个变体,我每200.000真(806642次迭代)收到1假。

使用第二个变量并且T = 5我每90000真(627018次迭代)收到1假,T = 1000我每4444真(693361次迭代)收到1假。

因此,每次调用时绝对不会给出不同的值。我需要在共享内存区域创建一个时间戳,我尝试猜测程序无法正常工作时有很多乐趣!

我可以用什么功能代替?  谢谢!

编辑以澄清:我知道计时器根本无法获得无限的准确性,但我想知道是否存在一个准确到足以比cpu更快的计时器(是的,可能这是一个荒谬的问题,但我对计时器如何运作只有一个模糊的想法。

顺便说一下,我会使用一些随机函数生成一个唯一的数字,我会将时间存储在另一个地方。

5 个答案:

答案 0 :(得分:6)

由于你只关心单调增加的价值,并且(显然)不关心一个和另一个之间存在多大的差异,所以InterlockedIncrement64似乎对你有用。

从那里可以确保所有需要序列号的代码都可以访问同一位置。 Windows有几种方法可以做到这一点,但你还没有真正告诉我们你正在做什么/如何使用它来提供有关哪种最适合你的需求的有意义的建议。

答案 1 :(得分:5)

您可能想查看QueryPerformanceCounter:

http://msdn.microsoft.com/en-us/library/windows/desktop/dn553408%28v=vs.85%29.aspx

例如:

LARGE_INTEGER li;
QueryPerformanceCounter(&li);
然而,

并非每次被称为&#34; ...

答案 2 :(得分:4)

简短的回答是否定的,因为定时器永远不会有无限的准确性。即你将始终受到基础计时器准确性的限制。

特别是

GetTickCount,有limited accuracy来解释您的观察结果:

  

GetTickCount函数的分辨率仅限于   系统计时器的分辨率,通常在10的范围内   毫秒到16毫秒。 GetTickCount的分辨率   功能不受调整的影响   GetSystemTimeAdjustment函数。

Microsoft recommends如果您的系统支持高分辨率计时器,则使用性能计数器:

在这个有用的教程中,Microsoft承认计时器的准确性有限:

  

Windows已经并将继续投资提供可靠的和   高效的绩效柜台。当你需要带时间戳的时候   分辨率为1微秒或更好,你不需要时间   要同步到外部时间参考的标记,请选择   QueryPerformanceCounter或KeQueryPerformanceCounter。当你需要的时候   UTC同步时间戳,分辨率为1微秒或   更好的是,选择GetSystemTimePreciseAsFileTime或   KeQuerySystemTimePrecise。

如果您只关心单调函数,您可以获得自己的计数器(可能的不同输出的数量受限于用于计数的数据类型的范围,例如,这里是一个ulong long)

e.g:

static unsigned long GetNext()
{
    static unsigned long long counter;
    return counter++;
}

当然,您需要在多线程程序上同步对此计数器的调用,通常使用InterlockedIncrement

答案 3 :(得分:4)

您可以使用__rdtsc()(MSVC)

读取时间戳计数器

由于它是一个处理器注册表,用于计算自复位后的时钟周期数,因此两个近距离调用不可能返回相同的值。

然而,它不是在几秒钟内,而是在时钟周期中,因此将其转换为实时并不简单,特别是在时钟速度变化的情况下(现代处理器保证频率更新不变)对于RDTSC,可以使用CPUID检查

此外,在早期的多核处理器上,此值不会在核心之间同步(可以使用CPUID检查)。也适用于多处理器系统。因此,跨多个线程的行为可能取决于硬件。

答案 4 :(得分:0)

假设Windows CoCreateGuid怎么样?我确信在其他平台上有类似的方法。更新:不确定......也许你正在寻找时间而不是唯一性。