Почему std :: future :: wait_for не ожидает правильной продолжительности? - PullRequest
4 голосов
/ 18 апреля 2019

Я не понимаю, почему расхождение между измеренной и указанной длительностью при вызове std::future::wait_for увеличивается при увеличении указанной продолжительности.

Когда я говорю std::future ждать 10 нс и измерятьПрошедшее время я получаю ~ 2000нс.Теперь 10 нс - очень короткая продолжительность, поэтому, возможно, слишком много накладных расходов связано с вызовами связанных функций, чтобы ждать такого короткого промежутка времени.Но когда я говорю std::future ждать 100000 нс и измерять прошедшее время, я получаю ~ 150000 нс.Аналогичный эффект можно наблюдать при ожидании 10 и 100 микросекунд соответственно.

#include <chrono>
#include <future>
#include <iostream>
#include <thread>

using namespace std::chrono;
using namespace std::chrono_literals;

void f() { std::this_thread::sleep_for(1s); }

int main() {
  steady_clock::time_point start, end;

  std::future<void> future = std::async(std::launch::async, f);

  start = steady_clock::now();
  future.wait_for(10ns);
  end = steady_clock::now();
  std::cout << "10 -> " << (end - start).count() << '\n';

  start = steady_clock::now();
  future.wait_for(100000ns);
  end = steady_clock::now();
  std::cout << "100000 -> " << (end - start).count() << '\n';

  return 0;
}

Я скомпилировал приведенный выше код с g++ future_test.cpp -lpthread, с g ++ 7.3.0 на Ubuntu 18.04.

Я мог бы объяснить что-то вроде

10 -> 2000
100000 -> 102000

Но это не то, что я получаю.Вот репрезентативный результат нескольких выполнений:

10 -> 2193
100000 -> 154723

Почему измеренная продолжительность для 100 000 нс превышает ~ 2 000 нс от указанной продолжительности?

Ответы [ 4 ]

10 голосов
/ 18 апреля 2019

Цитирование документации :

std::future_status wait_for( const std::chrono::duration& timeout_duration );

Эта функция может блокироваться на дольше , чем timeout_duration из-за задержки при планировании или конфликте ресурсов.

7 голосов
/ 18 апреля 2019

Спит и ждет только обещание подождать как минимум столько, сколько вы попросите.Поскольку ограничения оборудования и планирования вводят непредсказуемую задержку, не существует фиксированного максимума продолжительности ожидания или ожидания.

Для циклических приложений (таких как таймер) вы можете получить устойчивый сон (в среднем)если вы подождете до момента времени, а затем увеличите его на фиксированную величину.Если вы продолжите делать это, при условии, что поток просыпается достаточно часто, вы получите целевую задержку в среднем за период времени.

2 голосов
/ 18 апреля 2019

Частота 4 ГГц - 0,25 секунды на такт. 10 нс - это 40 тиков или 40 инструкций, которые дают или берут.

Запрашивать задержку в 10 нс для обозначения чего-либо довольно нелепо; время, необходимое для вычисления текущего времени, может легко превысить 10 нс.

Итак, что вы измеряете здесь:

start = steady_clock::now();
future.wait_for(10ns);
end = steady_clock::now();
std::cout << "10 -> " << (end - start).count() << '\n';

время, необходимое для расчета текущего времени, ожидания служебных данных (проверьте, готово ли оно и т. Д.).

Во втором случае:

start = steady_clock::now();
future.wait_for(100000ns);
end = steady_clock::now();
std::cout << "100000 -> " << (end - start).count() << '\n';

разница составляет около 50000 нс. Это 1/20000 секунды.

Здесь мы могли бы сделать что-то вроде перевода процессора в режим пониженного энергопотребления или даже настройки спин-блокировки.

Возможно, вы переключаете контекст, но я бы не подумал; переключение на другой контекст и затем обратно, вероятно, стоило бы слишком дорого, чтобы беспокоиться здесь.

Время на интерактивной ОС обычно составляет порядка 1/50 секунды или порядка 20000000 нс при наличии конфликтов в ЦП.

0 голосов
/ 18 апреля 2019

Вы запрашиваете материал в реальном времени, и это чрезвычайно зависит от системы.Это работа ОС.Но даже если вы используете RTOS, preempt-RT или что-то подобное, я не уверен, что C ++ stdlib может получить такую ​​точность.

Когда вам это нужно, при условии, что система может предоставить егоВам, вероятно, лучше прибегнуть к вызовам, зависящим от ОС.

В любом случае, в области точности 1 мс я обычно вращаюсь.Но учтите: у вас будут выбросы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...