Semenalidery.com

IT Новости из мира ПК
1 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Std chrono time point

Работа с датой и временем на С++

Моя программа должна обрабатывать дату и время, мне нужно:

  1. получать текущую дату/время от операционной системы;
  2. вычислять разницу в днях/часах/секундах между двумя моментами времени;
  3. создавать объект для произвольного момента времени (например в файле или базе данных находится дата регистрации пользователя, которую должна обработать моя программа).

Как решить эти задачи на С++?

В стандарте С++11 появился набор классов для работы со временем, он позволяет больше чем старый модуль time.h и расположен в пространстве имен std::chrono . В нем определены классы для задания моментов времени ( std::chrono::timepoint ), интервалов времени ( std::chrono::duration ) и несколько видов часов:

  1. std::chrono::system_clock предназначен для получения данных от системных часов реального времени, моменты времени system_clock::time_point могут быть преобразованы в тип time_t с округлением до секунд при помощи метода system_clock::to_time_t() . Получить текущее время можно с помощью метода system_clock::now() . Недостатком системных часов является их нестабильность — системные часы могут быть подведены пользователем или процессом автоматической синхронизации с внешним сервером;
  2. std::chrono::steady_clock предоставляет возможность работы со стабильными системными часами. Эти часы возвращают не системное время (на них не влияет напрямую изменение системного времени). Эти часы оптимально подходят для замера времени выполнения фрагмента кода. Текущее время можно получить при помощи steady_clock::now() ;
  3. Класс std::chrono::high_resolution_clock позволяет работать с системными часами максимально высокого разрешения (как и для обычные системные часы, он не является стабильным, т.е. допускает подведение времени). При помощи метода high_resolution_clock::now() можно получить самое высокое разрешение из всех видов часов, входящих в библиотеку.

Чтобы получить текущее время от операционной системы нужно использовать один из трех видов часов — вызвать у них метод now() , в результате будет получен объект типа timepoint . Чтобы вывести время на экран вы можете преобразовать его функцией to_time_t в тип time_t , а затем в строку при помощи функции ctime :

Обычно этого достаточно, при преобразовании в тип time_t момент времени округляется до секунд. Если же такое преобразование не выполняется, а лишь вычисляется разница двух моментов времени — можно работать даже с наносекундами — см. Пример с замером времени работы функции.

Вы можете создавать моменты времени ( chrono::timepoint ), преобразованием из time_t , который в свою очередь проще создавать преобразованием из типа std::tm :

Обратите внимание, что несмотря на то, что в структуре tm :

  • нумерация месяцев начинается с нуля (мы пишем седьмой месяц, хотя создаем август);
  • год задается как целое число лет, прошедших с 1900 года (пишем 116 вместо 2016 );
  • поле tm_isdst отвечает за перевод времени на летнее и зимнее (пишем -1 если ничего про это не известно).

Таким образом, вы можете использовать std::chrono для хранения интервалов времени в своей программе, определения наиболее точного времени и замера времени со стабильными часами (без возможности их подведения пользователем), однако при вводе произвольного момента времени в программу или выводе времени на экран/файл наиболее удобным способом является использование структур time_t и std::tm .

Хроно в C ++

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

chrono — это имя заголовка, а также подпространства имен: все элементы в этом заголовке (кроме специализаций common_type) определяются не непосредственно в пространстве имен std (как большая часть стандартной библиотеки), а в std :: хроно пространство имен .
Элементы в этом заголовке имеют дело со временем. Это делается в основном с помощью трех концепций:

продолжительность

Объект длительности выражает промежуток времени с помощью отсчета, например, минуты, два часа или десять миллисекунд. Например, «42 секунды» могут быть представлены продолжительностью, состоящей из 42 тиков в 1-секундную единицу времени.

// C ++ программа для иллюстрации утилиты
// длительность функции :: count
#include
#include

Читать еще:  Как можно поменять пароль wifi

using namespace std::chrono;

// std :: chrono :: milliseconds является

// создание экземпляра std :: chrono :: duration: — 1 секунда

std::cout «duration (in periods): » ;

std::cout «duration (in seconds): » ;

Часы

Часы состоят из начальной точки (или эпохи) и частоты тиков. Например, часы могут иметь эпоху 22 февраля 1996 года и тикать каждую секунду. C ++ определяет три типа часов:

  • system_clock — это текущее время по системе (обычные часы, которые мы видим на панели инструментов компьютера). Написано как -std :: chrono :: system_clock
  • устойчивые часы — это монотонные часы, которые никогда не будут регулироваться. Они идут с одинаковой скоростью. Это написано как-STD :: Chrono :: устойчивый_clock
  • high_resolution_clock — обеспечивает минимально возможный период тика. Написано как -std :: chrono :: high_resolution_clock

Момент времени

Объект time_point выражает момент времени относительно эпохи часов. Внутри объект хранит объект типа длительности и использует тип Clock в качестве ссылки для своей эпохи.

// C ++ программа для иллюстрации момента времени
// и функции системных часов
#include
#include
#include

// Функция для расчета
// ряд Фибоначчи

long fibonacci(unsigned n)

return fibonacci(n-1) + fibonacci(n-2);

// Используем момент времени и системный час

std::chrono::time_point start, end;

std::cout «f(42) = » ‘n’ ;

std::chrono::duration double > elapsed_seconds = end — start;

std:: time_t end_time = std::chrono::system_clock::to_time_t(end);

std::cout «finished computation at » ctime (&end_time)

«elapsed time: » «sn» ;

Эта статья предоставлена Шамбхави Сингхом . Если вы как GeeksforGeeks и хотели бы внести свой вклад, вы также можете написать статью с помощью contribute.geeksforgeeks.org или по почте статьи contribute@geeksforgeeks.org. Смотрите свою статью, появляющуюся на главной странице GeeksforGeeks, и помогите другим вундеркиндам.

Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.

Измерение времени выполнения

Измерение времени выполнения функции
Почему-то в конце постоянно получается elapsed_seconds = 0. #include "stdafx.h" #include.

Измерение времени выполнения потока
#include "stdafx.h" #include <clocale> #include <math.h> #include <windows.h> int l, m, n.

Измерение времени
DWORD dwStart, dwFinish, dwDif; dwStart=GetTickCount();.

Так я его вроде на микросекунду усыпляю — std::chrono::microseconds(1)
Но результат остаётся тот же и при:
std::chrono::microseconds(10)
std::chrono::microseconds(100)
std::chrono::microseconds(1000)

И чё делать? Я использую Visual Studio 2013 Update 5.

mns_14, усыпите на std::chrono::nanoseconds(10)

Я не в курсе какие версии у студии поддерживают std::chrono::high_resolution_clock

Добавлено через 2 минуты
А также попробуйте усыпить на std::chrono::seconds(1)

mns_14, посмотрите в сорсах как у вас реализован std::chrono::high_resolution_clock (go to definition на нём), предполагаю что typedef к чему-то с меньшей точностью.

В общем у вас на платформе 1мс — минимальная точность.

typedef system_clock high_resolution_clock;

не только. это зависит от платформы, а не от с++.

в многозадачных системах опираться можно лишь на статистику.
и то — с учетом общей загрузки системы активными процессами.

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

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

Операционки типа Windows вообще не могут гарантировать замер временных интервалов с какой-либо точностью (пусть это миллисекунды, пусть микро, пусть нано).

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

Все дело во многозадачности — как только у вашего потока исчерпался квант времени и операционка переключилась на выполнение другого потока — нет никаких гарантий того, что следующий квант времени поток получит в какие-то определенные временные рамки, если это не realtime system.

На практике, на windows нам еще более менее удавалось привязываться к временным отсчетам с периодом около 20-30 мсек, где результаты измерений более менее не «гуляли» по времени.
Если система требует более короткого периода, то сиглалы, идущие с такой частотой, анализировали уже с помощью «железок» собственной разработки, с которой считывали уже подготовленные и буферизованные данные для представления пользователю.
Также, в одном из проектов применяли QNX вместо windows для обесечения точности отсчетов временных интервалов.

Читать еще:  Не раздает wifi

Библиотека времени Chrono

О библиотеке

Для работы со временем в STD, начиная со стандарта C++11, появилась библиотека времени – Chrono. До выхода C++11 в STD была только одна библиотека работающая со временем – это Си-библиотека ctime . Она доступна и сейчас. Но время не стоит на месте. Новые скорости – новое время. Разработчики chrono хотели создать библиотеку решающую ряд недостатков сишной библиотеки, прежде всего – точность интервалов времени, часы, которые бы использовали такты времени, не связанные с системным временем. Библиотеку chrono составляют три основных типа:

  • Интервалы ( duration )
  • Моменты ( time_point )
  • Часы ( clock )

Определение интервалов. Часы

В задачах мы ограничимся использованием часов system_clock – системные часы реального времени (всего же используются три типа часов; в C++20 будет добавлено ещё 6). Поскольку эти часы связаны с системными часами, то они могут быть не монотонными, так как системное время может быть в любой момент синхронизировано. Методов всего три:

  • now() – текущий момент времени
  • to_time_t() – преобразует момент времени в тип time_t
  • from_time_t() – преобразует тип time_t в момент времени системных часов

Возможный вывод программы:

Чтобы получить текущий момент времени необходимо создать объект начального момента времени (start), инициализировав его значением, которое возвращает метод now() . Для system_clock – это текущий момент системного времени. В программе 1, для лаконичности определений, мы используем пространство имен chrono :

Чтобы сделать выражение ещё более компактным, можно воспользоваться спецификатором auto :

Далее, определяем интервал, как разность двух моментов. В шаблонном параметре типа объекта duration указывается тип значения интервала. В данном случае – это действительное число.
Чтобы вывести итоговое значение нам нужно знать количество тактов. За такое вычисление берется метод count() , который и позволяет вывести окончательный результат. Но не всегда такой вывод может нас устроить. Что, если нам нужно определить интервалы с очень большой точностью, скажем в наносекундах? Такая необходимость возникает при тестировании быстрых алгоритмов. Chrono позволяет использовать на выводе различные единицы – от часов до наносекунд (в зависимости от величины интервала). Для изменения единиц времени используется формат преобразования в стиле C++ duration_cast<> , которому, в качестве шаблонного параметра, необходимо передать один из возможных типов перечисленных ниже:

  • std::chrono::nanoseconds
  • std::chrono::microseconds
  • std::chrono::milliseconds
  • std::chrono::seconds
  • std::chrono::minutes
  • std::chrono::hours

Изменим немножко код в самом конце:

Возможный вывод этого варианта программы:

Как вы уже поняли, к интервалам применяются арифметические операции: operator+ , operator- , operator* , operator/ , operator% . Используя операцию «%» вы можете разделить интервал на разные единицы (как это сделать см. [1, 179]). Также для интервалов доступны все известные операции сравнения.

Chrono и генератор случайных чисел

Переходим к следующему вопросу. Как передать в качестве начального значения генератору случайных чисел момент времени полученный в chrono , который будет создавать всегда новый набор случайных чисел с каждым запуском программы? На самом деле, тип time_point – это абстрактный тип основанный на std::ratio , таким образом, к фундаментальному типу его преобразовать не получится. Вот почему в программе 1 велись такие многоступенчатые преобразования. Следовательно, нам нужно сразу получить готовое число, представляющее некоторый интервал. Такая возможность имеется, если мы возьмем за начальный момент – начало Эпохи UNIX, а конечный, собственно, текущий момент системного времени. Чтобы не заниматься этими вычислениями самостоятельно, проще взять метод класса time_point – time_since_epoch() , который возвращает количество тактов от начала эпохи до определенного момента (в данном случае момент системного времени). А затем использовать метод count() для получения нужного нам числа. В программе ниже используется генератор случайных чисел С++ (библиотека random):
Программа 2

Возможный вывод программы:

Форматированный вывод даты/времени

А вот с форматированным выводом у chrono проблемы. Разработчики не посчитали нужным добавить человеко понятный вывод. Ничего не остается, как воспользоваться возможностями старой ctime . Но и это еще не все. Чтобы вывод соответствовал региональным традициям необходимо использовать библиотеку local . Собственно, форматирование вывода производит библиотека ios, которая перехватывает передающиеся ей от ctime данные для форматирования, а дальше, как говорится, дело техники. Нам нужно от chrono две вещи: текущий момент системного времени и, упомянутый выше, метод преобразования to_time_t() , который преобразовывает момент времени в тип time_t (с ним может работать ctime ). В итоге, программный код форматирования даты/времени может быть представлен в следующем виде:
Программа 3

Читать еще:  Reference by pointer

Возможный вывод программы:

В грядущем стандарте С++20 функции форматирования даты/времени в chrono всё же были заявлены [5].

Урок №129. Измерение времени выполнения (тайминг) кода

Обновл. 2 Янв 2020 |

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

Один из самых простых способов — засечь время выполнения каждого из фрагментов кода. В C++11 это делается через библиотеку chrono. Мы можем легко инкапсулировать весь необходимый нам функционал в класс, который затем будем использовать в наших собственных программах.

Для его использования нужно определить объект класса Timer в верхней части функции main() (или откуда вы хотите начинать отсчёт), а затем просто вызвать метод elapsed() после части кода, которую вы проверяете:

Теперь проделаем то же самое, но с std::sort из стандартной библиотеки C++:

Таким образом, std::sort в 75 раз быстрее, чем сортировка, которую мы написали сами!

Что влияет на тайминг кода?

Тайминг кода является достаточно простым и прозрачным, но ваши результаты могут существенно отличаться из-за ряда вещей:

Во-первых, убедитесь, что вы используете режим конфигурации Release, а не Debug. Во время режима Debug оптимизация обычно отключена, а она может оказывать значительное влияние на результаты. Например, в конфигурации Debug, выполнение сортировки элементов массива через std::sort на компьютере автора заняло 0.0237 секунды — в 34 раза больше, нежели в конфигурации Release!

Во-вторых, на результаты тайминга влияют процессы, которые ваша система может выполнять в фоновом режиме. Для достижения наилучших результатов убедитесь, что ваша ОС не делает ничего, что интенсивно нагружает процессор, жёсткий диск (например, запущен поиск файла или сканирование антивирусом) или расходует много памяти (например, вы играете в игры или работаете в фото или видео редакторе).

Выполняйте тайминг как минимум 3 раза. Если результаты одинаковые — выбираем среднее. Если один или два результата значительно отличаются друг от друга, то запустите тайминг ещё несколько раз, пока не получите лучшее представление о том, какие из результатов оказались «левыми». Обратите внимание, некоторые, казалось бы, невинные вещи, такие как веб-браузеры, могут временно увеличить нагрузку на ваш процессор до 100%, когда сайт, на котором вы находитесь в фоновом режиме, выполняет сразу целую кучу скриптов JavaScript (рекламные баннеры, запуск видео, сложная анимация и т.д.). Запуск тайминга несколько раз позволит определить, повлияло ли подобное событие на ваши результаты.

В-третьих, при сравнении двух фрагментов кода старайтесь не запускать ничего лишнего в фоновом режиме при пригонах, так как это также может повлиять на результаты тайминга. Возможно, ваш антивирус начал сканирование в фоновом режиме, или, может быть, вы решили послушать музыку в стриминговом сервисе (и это всё в перерывах между прогонами).

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

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

Ссылка на основную публикацию
Adblock
detector