Точные часы C / C ++ на многоядерном процессоре с автоматическим разгоном?

Я рассмотрел несколько тем, чтобы попытаться получить некоторые идеи о том, как сделать надежные часы с помощью C или C ++. Тем не менее, я также видел, как некоторые функции использовали тики и тики процессора в секунду для расчета конечного результата, что, как я думаю, может быть проблемой для процессора с автоматическим разгоном, как тот, который у меня есть. Я также видел, как через некоторое время один из них сбрасывается, поэтому он не очень надежен.

Идея состоит в том, чтобы сделать (желательно кроссплатформенные) часы, подобные игровым, с точностью лучше секунды, чтобы иметь возможность добавлять прошедшее время в «текущем сеансе» с сохраненным временем в конце. программы. Это означало бы подсчитать время, потраченное на консольную игру, в которой нет игровых часов, и в конечном итоге, возможно, интегрировать ее в реальные игры для ПК.

Он должен иметь возможность работать, не занимая слишком много или всего времени ЦП (или времени одного ядра для многоядерных ЦП), поскольку было бы довольно плохо использовать все эти ресурсы только для часов, а также в системах с автоматическим -Overclock (что в противном случае могло бы привести к неточным результатам).

Программа, в которую я хотел бы реализовать эту функцию, в настоящее время выглядит так, но я мог бы перекодировать ее на C (поскольку мне нужно вернуться к изучению того, как кодировать на C ++):

#include <iostream>
#include <cstdlib>

using namespace std;

int main()
{
    cout << "In game" << endl;
    system("PAUSE");
    return 0;
}

Кстати, мне все еще нужно избавиться от функции PAUSE, специфичной для Windows, но я думаю, что об этом можно позаботиться с помощью простого цикла while (char! = '\ N').

Что я уже бегло просмотрел:

(Изменить: дополнительные исследования, в частности, для реализации C:

Проблема в том, что неясно, правильно ли работают некоторые из упомянутых методов, такие как Boost или SDL2, в частности, с автоматическим разгоном.

TL; DR: какую кросс-платформенную функцию мне следует использовать для создания точного счетчика с точностью до секунды на C / C ++, который мог бы работать на многоядерных процессорах и / или процессорах с автоматическим разгоном, пожалуйста?

Заранее спасибо.


person Coroice    schedule 26.12.2017    source источник
comment
Мне кажется, вам нужен std :: chrono :: stable_clock.   -  person Jesper Juhl    schedule 26.12.2017
comment
проголосовать за все исследования   -  person Jean-François Fabre    schedule 26.12.2017
comment
Похоже, это может быть то, что я действительно ищу ... Если я правильно понял документацию, вы можете установить определенный период, который не зависит от тиков процессора, это правильно? Если это так, то это может быть просто идеально.   -  person Coroice    schedule 26.12.2017
comment
std::chrono::steady_clock ни на что не устанавливается. В любой момент он сообщает вам значение часов. Вам решать, измерить часы в начале и в конце интервала и соответственно вычислить прошедшее время.   -  person Sam Varshavchik    schedule 26.12.2017
comment
Ох, тогда ладно. Спасибо за разъяснения! Но рискует ли повлиять частота процессора или нет? Это то, о чем я беспокоюсь, так как я думаю, что это может привести к довольно большим различиям между временем настенных часов и временем, отсчитываемым часами за более или менее длительные периоды (например, час).   -  person Coroice    schedule 26.12.2017
comment
@Coroice std::chrono::steady_clock - это монотонно увеличивающиеся часы, на которые не влияют внешние факторы, такие как скорость процессора или пользовательские настройки даты / времени или аналогичные - да.   -  person Jesper Juhl    schedule 26.12.2017
comment
Это все еще вопрос C ++ с принятым ответом. Я не имею ни малейшего представления о том, как применить эти знания в моих программах на C.   -  person Antti Haapala    schedule 26.12.2017
comment
Еще раз спасибо за разъяснения! И я согласен, что было бы также интересно иметь эквивалент для программы на C, хотя у меня уже есть ответ для программы на C ++. clock_gettime() достаточно ли надежен (и портативен)?   -  person Coroice    schedule 27.12.2017
comment
omp_get_wtime() - это то, что я обычно использую.   -  person Z boson    schedule 27.12.2017
comment
omp_get_wtime() похоже, зависит от настенных часов и имеет разрешение секунды; в некоторых случаях этого достаточно, но не совсем то, что я искал. Кроме того, похоже, что он может измерять эффективное время выполнения, а не иметь продолжительность между двумя точками времени (в начале и в конце программы соответственно). omp_get_wtick() может быть лучше для субсекундной точности, но опять же, совместим ли он с автоматическим разгоном?   -  person Coroice    schedule 27.12.2017
comment
Невозможно отредактировать предыдущий пост, поэтому я должен написать новый комментарий: omp_get_wtick(), похоже, также имеет разрешение секунды, так что это подходит не для всех случаев ...   -  person Coroice    schedule 27.12.2017
comment
omp_get_wtime() имеет разрешение лучше микросекунды. Не знаю, откуда вы взяли, что у него разрешение секунды. На самом деле он просто вызывает другие функции. В GCC он вызывает clock_gettime. Его реализация определена, но для меня она была точной. Это наиболее удобный кроссплатформенный и кросс-компиляторный (GCC, Claing, ICC, MSVC) метод, который я знаю, чтобы получить время стены. Я бы не стал использовать его для большого проекта, но для мелочей (особенно на SO) он отлично работает. Однажды у меня была одна проблема, хотя stackoverflow.com/a/43277581/2542702   -  person Z boson    schedule 28.12.2017
comment
Извините за поздний ответ ... Это плохо, я неправильно понял документацию, поскольку в ней говорится, что возвращает значение в секундах времени, прошедшего с некоторой точки, но на самом деле это число с плавающей запятой с большей точностью. И clock_gettime, похоже, тоже работает монотонно, поэтому auto-OC не должен вызывать проблем ... Большое спасибо за разъяснения, я буду помнить об этой функции для проектов C!   -  person Coroice    schedule 05.01.2018


Ответы (1)


std::chrono::high_resolution_clock кажется тем, что вы ищете. На большинстве современных процессоров это будет стабильно монотонно увеличивающаяся частота, на которую не повлияет разгон процессора.

Только имейте в виду, что по нему нельзя определять время. Это полезно только для обозначения временных интервалов, а это большая разница. Например:

using clock = std::chrono::high_resolution_clock;
auto start = clock::now();
perform_operation();
auto end = clock::now();
auto us = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
std::cout << "Operation took " << us << " microseconds.\n";

Если проверка часов сама по себе является операцией, зависящей от производительности, вам придется прибегнуть к уловкам, зависящим от платформы, из которых наиболее популярным является прямое считывание счетчика тиков ЦП (RDTSC в семействе Intel). Это очень быстрый и очень точный способ измерения временных интервалов на современных процессорах.

person SergeyA    schedule 26.12.2017
comment
Похоже, что и часы с высоким разрешением, и устойчивые часы из библиотеки chrono могут быть тем, что мне нужно; единственной проблемой после этого может быть преобразование секунд в минуты и часы. Большое спасибо! - person Coroice; 26.12.2017
comment
Проблема с std::chrono::high_resolution_clock vs std::chrono::steady_clock заключается в том, что первое не гарантирует, что никогда не вернется назад во времени. То, как я читаю вопрос OP, они хотят стабильно увеличивающихся часов, на которые не влияет изменение пользователем текущей даты / времени, изменение частоты ЦП и т. Д. быть). - person Jesper Juhl; 26.12.2017
comment
@Coroice преобразование единиц времени выполняется просто. См. en.cppreference.com/w/cpp/chrono/duration/duration_cast - person Richard Hodges; 26.12.2017
comment
@JesperJuhl, как я уже сказал, на большинстве современных платформ часы с высоким разрешением монотонно увеличиваются (и фактически являются синонимом stable_clock). - person SergeyA; 26.12.2017
comment
@Sergey: Конечно, но это не гарантируется. Если вам нужны гарантированные монотонно возрастающие часы, тогда std::steady_clock - это то, что вам нужно. - person Jesper Juhl; 26.12.2017
comment
gcc использует псевдонимы с high_resolution_clock по system_clock. Все остальные (libc ++ / VS) используют псевдоним steady_clock. Я рекомендую выбрать system_clock или steady_clock, чтобы сделать код более переносимым. system_clock хорошо, если вам нужно связать время с человеческим календарем (то есть настенными часами). steady_clock хорош, если вам нужны только промежутки времени между двумя временными точками и / или гарантия того, что время идет монотонно (например, секундомер). - person Howard Hinnant; 26.12.2017
comment
Похоже, мне может не понадобиться дополнительная точность std::chrono::high_resolution_clock, плюс она может иметь побочные эффекты (хотя они, вероятно, незначительны, но все же), поэтому я думаю, что буду придерживаться steady_clock. Тем не менее, вспомогательное преобразование - это хорошо. Спасибо за дополнительную информацию! - person Coroice; 27.12.2017