Контролируйте время цикла с помощью usleep - PullRequest
0 голосов
/ 28 июня 2018

Я пытаюсь сделать так, чтобы время выполнения каждого цикла составляло 10 мс с usleep, но иногда оно превышает 10 мс.

Я понятия не имею, как решить эту проблему, правильно ли использовать usleep и gettimeofday в этом случае?

Пожалуйста, помогите мне выяснить, что я пропустил.

Результат: 0,0127289 0.0136499 0.0151598 0.0114031 0.014801

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);
    }
}

Ответы [ 3 ]

0 голосов
/ 28 июня 2018

Нет способа гарантировать время цикла 10 мс. Все функции сна спят в течение, по крайней мере, желаемого времени. Для переносимого решения используйте std :: this_thread :: sleep_for

#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";
    }
}

В зависимости от того, что вы пытаетесь сделать, взгляните на Говард Хиннантс библиотека дат.

0 голосов
/ 28 июня 2018

Чтобы не допустить постоянных ошибок в цикле (которые обычно неизвестны), вы можете спать до времени точка вместо для времени продолжительность . Используя библиотеки C ++ <chrono> и <thread>, это невероятно просто:

#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(), чтобы определить время между итерациями, и, возможно, что еще более важно, среднее время итерации:

#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";
}

Выше я добавил к издержкам цикла, делая больше вещей в цикле. Однако цикл все еще будет просыпаться около каждые 10 мс. Иногда ОС просыпает поток поздно, но в следующий раз цикл автоматически настраивается на более короткий период сна. Таким образом, средняя скорость итерации автоматически корректируется до 10 мс.

На моей машине это просто вывод:

...
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
0 голосов
/ 28 июня 2018

Со страницы usleep man :

Сон может быть немного увеличен из-за любой системной активности или из-за времени, потраченного на обработку вызова, или из-за гранулярности системных таймеров.

Если вам нужно высокое разрешение: с C в Unix (или Linux), проверьте этот ответ , который объясняет, как использовать таймеры высокого разрешения с помощью clock_gettime.

Редактировать: Как уже упоминал Тобиас nanosleep может быть лучшим вариантом:

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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...