【问题标题】:C++ Setting Speed of While Loop per SecondC++设置While循环每秒的速度
【发布时间】:2012-05-26 02:03:44
【问题描述】:

我对 C++ 比较陌生,所以我没有大量的经验。我已经学习了 Python,并且正在尝试制作我用 C++ 编写的 Python 代码的改进版本。但是,我希望它实时工作,所以我需要设置 While 循环的速度。我确定有答案,但我找不到。我想要一个与此类似的代码:

rate(timeModifier * (1/dt))

这是我在 Python 中使用的代码。我可以设置一个变量 dt 来使计算更精确,而 timeModifier 可以将速度提高一倍或三倍(1 将其设置为实时)。这意味着程序将每秒循环 1/dt 次。我知道我可以在标题中包含 time.h,但我想我对 C++ 太陌生了,无法理解如何将其转移到我的需求中。

【问题讨论】:

标签: c++ loops time while-loop modifier


【解决方案1】:

您可以编写自己的计时器类:

#include <ctime>

class Timer {
    private:
        unsigned long startTime;
    public:
        void start() {
            startTime = clock();
        }

        unsigned long elapsedTime() {
            return ((unsigned long) clock() - startTime) / CLOCKS_PER_SEC;
        }

        bool isTimeout(unsigned long seconds) {
            return seconds >= elapsedTime();
        }
};


int main() 
{
    unsigned long dt = 10; //in seconds
    Timer t;
    t.start();

    while(true) 
    {
        if(t.elapsedTime() < dt) 
        {
            //do something to pass time as a busy-wait or sleep
        }
        else 
        {
            //do something else
                    t = Timer(); //reset the timer
        }
    }
}

请注意,不鼓励忙等待,因为它们会占用 CPU。如果您不需要执行任何操作,请使用sleep 命令(Windows)或usleep(Linux)。有关在 C++ 中制作计时器的更多信息,请参阅this link

【讨论】:

    【解决方案2】:

    您不能在 C++ 中以同样的方式进行操作。您需要在计算循环中手动调用某种睡眠函数,Windows 上的 Sleep 或 *NIX 上的 usleep

    【讨论】:

    • 是的,这就是我所需要的。 Sleep() 的工作方式与 Python 版本相反,但它可以满足我的需要。
    • 我不推荐使用Sleep()函数,因为它会阻止整个应用程序运行并且给出不准确的时间,但是,它绝对不适合实时的东西。
    【解决方案3】:

    我已经有一段时间没有做这样的事情了,但是这样的事情会起作用:

    #include <time.h>
    
    time_t t2, t1 = time(NULL);
    
    while(CONDITIONS)
    {
        time_t t2 = time(NULL);
        if(difftime(t2, t1) > timeModifier)
        {
            //DO the stuff!
            t1 = time(NULL);
        }
    }
    

    但是,我应该注意,我不熟悉这种方法的精度,我认为它以秒为单位测量差异。

    如果您需要更精确的信息,请使用 clock() 函数,该函数具有从 1980 年 1 月 1 日凌晨 12:00 开始的毫秒数,精确到 10 毫秒。 也许是这样的:

    #include <time.h>
    
    clock_t t2, t1 = clock();
    
    while(CONDITIONS)
    {
        t2 = clock();
        if((t2-t1) > someTimeElapsed*timeModifier)
        {
            //DO the stuff!
            t1 = clock());
        }
    }
    

    更新: 您甚至可以通过在 if 语句的末尾添加以下内容,将 CPU 让给其他线程和进程:

    else
    {
        usleep(10000); //sleep for ten milliseconds (chosen because of precision on clock())
    }
    

    【讨论】:

    • 您似乎在分配之前从 t1 读取,并且在您获得 +1 之前应该有一个包含 sleep 的 else
    • @MooingDuck 我添加了一条注释,但对我来说,这取决于程序在做什么,我是否希望它休眠。
    【解决方案4】:

    根据您需要的精度和您的平台,您可以使用usleep 这允许您将暂停时间设置为微秒:

     #include <unistd.h>
    
     int usleep(useconds_t useconds);
    

    请记住,由于循环其余部分的固有处理时间,您的循环将始终花费比这更长的时间,但这是一个开始。要获得更准确的信息,您可能需要查看基于计时器的回调。

    【讨论】:

    • 你应该提到windows对此有不同的命令。
    • @MooingDuck:我确实提到它依赖于平台。我不确定 Windows 提供了什么,因为我不使用它。 :)
    • 其他答案提到了 Windows 等效项:sleep:D
    【解决方案5】:

    您真的应该创建一个新线程并让它进行计时,以便它不受循环中完成的处理工作的影响。

    警告:伪代码...只是为了让您了解如何开始。

    Thread* tThread = CreateTimerThread(1000);
    tThread->run();
    while( conditionNotMet() )
    {
        tThread->waitForTimer();
        doWork();
    }
    

    CreateTimerThread() 应该返回你想要的线程对象,并且运行会是这样的:

    run()
    {
        while( false == shutdownLatch() )
        {
            Sleep( timeout );
            pulseTimerEvent();
        }
    }
    
    waitForTimer()
    {
        WaitForSingleObject( m_handle );
        return;
    }
    

    【讨论】:

    • 也许可以,但它会消除保持固定时间和计算睡眠循环的“担忧”。很适合多线程。如今,使用 apache decaf、boost 和 Intel TBB 库并不难。除了看看代码变得多么干净...... :)
    【解决方案6】:

    在 Windows 下可以使用QueryPerformanceCounter,在轮询时间的同时(例如在另一个while循环中)调用Sleep(0)以允许其他线程继续操作。

    记住Sleep 是非常不准确的。为了完全控制,只需运行一个没有操作的循环,但是您将使用 100% 的 CPU。要减轻 CPU 的压力,您可以致电 Sleep(10) 等。

    【讨论】:

      猜你喜欢
      • 2015-11-24
      • 1970-01-01
      • 2020-01-16
      • 2016-07-15
      • 1970-01-01
      • 1970-01-01
      • 2013-12-24
      • 1970-01-01
      • 2018-03-15
      相关资源
      最近更新 更多