C++ 时间测量看起来太慢了

Posted

技术标签:

【中文标题】C++ 时间测量看起来太慢了【英文标题】:C++ time measurement looks too slow 【发布时间】:2017-05-02 19:01:55 【问题描述】:

我正在使用 OpenGL GLUT 代码编写游戏,并且我正在应用一种游戏开发技术,该技术包括测量游戏主循环的每次迭代所消耗的时间,因此您可以使用它来按比例更新游戏场景上次更新了。为了实现这一点,我在循环开始时有这个:

void logicLoop () 

    float finalTime = (float) clock() / CLOCKS_PER_SEC;
    float deltaTime = finalTime - initialTime;
    initialTime = finalTime;

    ...
    // Here I move things using deltaTime value
    ...

当我在游戏中添加子弹时,问题就来了。如果子弹在两秒钟内没有击中任何目标,则必须将其摧毁。然后,我所做的就是保持对创建子弹的那一刻的引用,如下所示:

class Bullet: public GameObject 

    float birthday;

public:
    Bullet () 
        ...
        // Some initialization staff
        ...

        birthday = (float) clock() / CLOCKS_PER_SEC;
    

    float getBirthday ()  return birthday; 


然后我在 finalTime 和 deltaTime 测量之外添加了这个逻辑:

if (bullet != NULL) 
    if (finalTime - bullet->getBirthday() > 2) 
        world.remove(bullet);
        bullet = NULL;
    

看起来不错,但是当我运行代码时,子弹的存活时间太长了。寻找问题所在,我打印了 (finalTime - bullet->getBirthday()) 的值,我发现它的增长非常缓慢,就像它不是以秒为单位的时间一样。

问题出在哪里?我以为结果会在几秒钟内,所以子弹会在两秒钟内被移除。

【问题讨论】:

不确定这里发生了什么,但如果你有 C++11,你可以尝试使用 <chrono> 并在项目符号中存储 std::chrono::time_point 为什么不使用glutGet(GLUT_ELAPSED_TIME) @genpfault:虽然看起来很可能而且很明显,但请确保文档没有说明;那是挂墙时间,是吗? 【参考方案1】:

这是一个常见的错误。 clock() 不测量实际时间的流逝;它测量 CPU 运行这个特定进程时已经过去了多少时间。

其他进程也占用CPU时间,所以两个时钟不一样。每当您的操作系统正在执行某个其他进程的代码时,包括当这个“睡眠”时,都不算在clock() 中。如果您的程序在具有多个 CPU 的系统上是多线程的,clock() 可能会“重复计算”时间!

人类对操作系统时间片一无所知或感知:我们只是感知实际时间的实际流逝(称为“墙上时间”)。最终,您将看到 clock() 的时基与挂钟时间不同。

Do not use clock() to measure wall time!

你想要gettimeofday()clock_gettime() 之类的东西。为了减轻人们更改系统时间的影响,在 Linux 上,我个人推荐 clock_gettime() 使用系统的“单调时钟”,该时钟与墙上时间同步,但具有不受人们玩耍影响的任意纪元电脑时间设置。 (如果需要,显然切换到便携式替代品。)

这个其实在the cppreference.com page for clock()讨论过:

std::clock 时间可能会比挂钟快或慢,这取决于操作系统给予程序的执行资源。例如,如果 CPU 由其他进程共享,std::clock 时间可能会比挂钟慢。另一方面,如果当前进程是多线程的并且有多个执行内核可用,std::clock 时间可能会比挂钟快。

当您不确定发生了什么时,请养成阅读您使用的所有功能的文档的习惯。

编辑:原来 GLUT 本身有一个你可以使用的功能,这可能很方便。 glutGet(GLUT_ELAPSED_TIME) 为您提供自您致电 glutInit() 以来经过的墙毫秒数。所以我想这就是你需要的。它的性能可能稍高一些,特别是如果 GLUT(或 OpenGL 的其他部分)已经定期请求挂起时间,并且如果此函数仅查询已经获得的时间……从而使您免于不必要的第二次系统调用(成本) .

【讨论】:

这是正确答案。在低延迟系统中,我们还使用clock_gettime 为我们的应用程序计时。【参考方案2】:

如果您在 Windows 上,您可以使用 QueryPerformanceFrequency / QueryPerformanceCounter,它可以提供非常准确的时间测量。

这是一个例子。

#include <Windows.h>
using namespace std;

int main()
    
    LARGE_INTEGER freq = 0, 0;
    QueryPerformanceFrequency(&freq);

    LARGE_INTEGER startTime = 0, 0;
    QueryPerformanceCounter(&startTime);

    // STUFF.
    for(size_t i = 0; i < 100; ++i) 
        cout << i << endl;
        

    LARGE_INTEGER stopTime = 0, 0;
    QueryPerformanceCounter(&stopTime);

    const double ellapsed = ((double)stopTime.QuadPart - (double)startTime.QuadPart) / freq.QuadPart;
    cout << "Ellapsed: " << ellapsed << endl;

    return 0;
    

【讨论】:

很难确定,因为 MSDN 太差了,但这个 似乎 是独立于进程且稳定的,因此在 Windows 上是一个不错的选择。

以上是关于C++ 时间测量看起来太慢了的主要内容,如果未能解决你的问题,请参考以下文章

C ++二项式系数太慢了

调试,测量django中的时间图像上传

InAppReview : SKStoreReviewController 太慢了

MySQL查询太慢了

sqlmap太慢了

iPad 中的洪水填充太慢了