首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用usleep控制循环时间

使用usleep控制循环时间
EN

Stack Overflow用户
提问于 2018-06-29 01:48:29
回答 3查看 651关注 0票数 0

我尝试使用usleep确保每个循环的执行时间为10ms,但有时会超过10ms。

我不知道如何解决这个问题,在这种情况下,使用usleepgettimeofday合适吗?

请帮我找出我错过了什么。

成绩: 0.0127289 0.0136499 0.0151598 0.0114031 0.014801

代码语言:javascript
复制
double tvsecf(){
     struct timeval tv;
     double asec;

     gettimeofday(&tv,NULL);
     asec = tv.tv_usec;
     asec /= 1e6;
     asec += tv.tv_sec;

     return asec;
}
int main(){
    double t1 ,t2;
    t1 = tvsecf();
    for(;;){
        t2= tvsecf();
        if(t2-t1 >= 0.01){
            if(t2-t1 >= 0.011)
                cout << t2-t1 <<endl;
            t1 = tvsecf();
        }
        usleep(100);
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-06-29 02:48:57

为了防止循环开销(通常是未知的)不断累积错误,您可以休眠到time ,而不是time duration。使用C++的<chrono><thread>库,这非常简单:

代码语言:javascript
复制
#include <chrono>
#include <iostream>
#include <thread>

int
main()
{
    using namespace std;
    using namespace std::chrono;
    auto t0 = steady_clock::now() + 10ms;
    for (;;)
    {
        this_thread::sleep_until(t0);
        t0 += 10ms;
    }
}

可以通过调用更多的steady_clock::now()来确定迭代之间的时间,也许更重要的是,平均迭代时间:

代码语言:javascript
复制
#include <chrono>
#include <iostream>
#include <thread>

int
main()
{
    using namespace std;
    using namespace std::chrono;
    using dsec = duration<double>;
    auto t0 = steady_clock::now() + 10ms;
    auto t1 = steady_clock::now();
    auto t2 = t1;
    constexpr auto N = 1000;
    dsec avg{0};
    for (auto i = 0; i < N; ++i)
    {
        this_thread::sleep_until(t0);
        t0 += 10ms;
        t2 = steady_clock::now();
        dsec delta = t2-t1;
        std::cout << delta.count() << "s\n";
        avg += delta;
        t1 = t2;
    }
    avg /= N;
    cout << "avg = " << avg.count() << "s\n";
}

在上面,我通过在循环中做更多的事情来增加循环开销。然而,循环仍然会大约每10ms唤醒一次。有时操作系统会延迟唤醒线程,但下一次循环会自动调整自身以缩短休眠时间。因此,平均迭代速率自校正为10ms。

在我的机器上,这只是输出:

代码语言:javascript
复制
...
0.0102046s
0.0128338s
0.00700504s
0.0116826s
0.00785826s
0.0107023s
0.00912614s
0.0104725s
0.010489s
0.0112545s
0.00906409s
avg = 0.0100014s
票数 3
EN

Stack Overflow用户

发布于 2018-06-29 01:58:33

usleep man page

休眠可能会因任何系统活动或处理呼叫所花费的时间或系统计时器的粒度而稍微延长。

如果您需要高分辨率:在Unix (或Linux)上使用C,请查看this answer,其中解释了如何使用clock_gettime使用高分辨率计时器。

编辑:正如Tobias提到的,nanosleep可能是一个更好的选择:

代码语言:javascript
复制
Compared to sleep(3) and usleep(3), nanosleep() has the following
advantages: it provides a higher resolution for specifying the sleep
interval; POSIX.1 explicitly specifies that it does not interact with
signals; and it makes the task of resuming a sleep that has been
interrupted by a signal handler easier.
票数 0
EN

Stack Overflow用户

发布于 2018-06-29 02:28:16

没有办法保证10ms的循环时间。所有休眠功能至少会休眠所需的时间。对于可移植的解决方案,请使用std::this_thread::sleep_for

代码语言:javascript
复制
#include <iostream>
#include <chrono>
#include <thread>

int main()
{
    for (;;) {
        auto start = std::chrono::high_resolution_clock::now();
        std::this_thread::sleep_for(std::chrono::milliseconds{10});
        auto end = std::chrono::high_resolution_clock::now();
        std::chrono::duration<double, std::milli> elapsed = end-start;
        std::cout << "Waited " << elapsed.count() << " ms\n";
    }
}

根据您正在尝试做的事情,请查看Howard Hinnants date库。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51088819

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档