Clock определить процессорное время


Содержание

Clock определить процессорное время

Заметим, что время может превысить свое максимальное значение. В 32-битных системах, где CLOCKS_PER_SEC равно 1000000, функция clock() возвращает одно и то же значение примерно каждые 72 минуты.

В некоторых других реализациях значение, возвращаемое clock(), также включает в себя время всех дочерних процессов, чьи состояния были собраны через wait(2) (или другие системные вызовы типа wait). Linux не включает время ожидающих потомков в значение, возвращаемое clock(). Возможно, предпочтительнее использовать функцию times(2), явно возвращающую (отдельно) информацию о вызвавшем функцию и его дочерних процессах.

В glibc 2.17 и старее, функция clock() работает на основе times(2). Для повышения точности, начиная с glibc 2.18, она реализуется через clock_gettime(2) (используются часы CLOCK_PROCESS_CPUTIME_ID).

C99 определение «процессорного времени»

Раздел 7.23.1, пункт 1 стандарта C99 определяет несколько терминов «время»:

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

Однако определение «процессорного времени» отсутствует.

Пункт 7.23.2.1 параграфа 2 С99 гласит:

Функция clock определяет время процессора.

Что такое «процессорное время»? «Время процессора» определено в стандарте C99; если да, то где это определено?

Стандарт не определяет фразу «процессорное время». Он использует его в своем обычном техническом английском смысле.

Стандарт включает список нормативных ссылок в разделе 2, один из которых:

  • ISO/IEC 2382-1:1993, Информационные технологии. Словарь. Часть 1. Основные термины.

Если в этом документе определено «время процессора», тогда это определение используется стандартом. Я не знаю, делает он это или нет, так как у меня нет доступа к этому документу.

Но идея состоит в том, что «процессорное время» — это количество типа, используемого процессором, что исключает время, затрачиваемое на спящий режим или ожидающее какого-либо события, такого как завершение запроса ввода-вывода. Например, программа, которая считывает строку ввода с клавиатуры, может потреблять, скажем, 60 секунд «времени настенных часов» (если пользователь так долго реагирует), но всего лишь часть секунды процессорного времени. Обычно прошедшее время процессора будет меньше, чем прошедшее время «настенных часов», но может быть больше, если программа работает на нескольких процессорах.

Кстати, эта формулировка существенно не изменилась на C90, C99 и C11.

Заголовок определяет два макроса. NULL (описано в 7.17); а также

CLOCKS_PER_SEC

который расширяется до постоянного выражения с типом clock_t (описано ниже), которое представляет собой число в секунду значения, возвращаемого функцией часов.

Поэтому время процессора должен означать clock_t величину, измеренную в CLOCKS_PER_SEC , учитывая, что спецификация определяет, что в результате вызова clock и в другом месте использует термин «процессорное время» в качестве имени для этого результата.

производительность — вычисление процессорного времени в C ++ в Windows

Есть ли способ в C ++, чтобы рассчитать, сколько времени требуется для запуска данной программы или процедуры во время процессора?

Я работаю с Visual Studio 2008 под управлением Windows 7.

Решение

Если вы хотите узнать общее количество процессорного времени, используемого процессом, ни clock ни rdtsc (напрямую или через встроенный компилятор) — действительно лучший выбор, по крайней мере, IMO. Если вам нужен переносимый код, лучшее, что вы можете сделать, это использовать clock протестируйте систему как можно тише и надейтесь на лучшее (но если это так, знайте, что разрешение clock является CLOCKS_PER_SEC , которое может быть или не быть 1000, и даже если это так, ваше фактическое временное разрешение часто не будет таким хорошим — оно может дать вам время в миллисекундах, но, по крайней мере, обычно увеличивается на десятки миллисекунд за раз).

Однако, поскольку вы, похоже, не возражаете против кода, специфичного для Windows, вы можете сделать это немного лучше. По крайней мере, если мое понимание того, что вы ищете, верно, то, что вы действительно хотите, это, вероятно, GetProcessTimes , который (отдельно) сообщит вам об использовании процессора процессом как в режиме ядра, так и в режиме пользователя (а также время начала и время выхода, из которого вы можете вычислить время, которое вы использовали на стене, если вам это нужно). Есть также QueryProcessCycleTime , которая сообщит вам общее количество тактов ЦП, использованных процессом (общее количество как в режиме пользователя, так и в режиме ядра во всех потоках). Лично мне трудно представить себе, что последнее очень полезно — подсчет отдельных тактов может быть полезен для маленький фрагменты кода подвергаются интенсивной оптимизации, но я менее уверен в том, как вы примените его к завершенному процессу. GetProcessTimes использует структуры FILETIME, которые поддерживают разрешение 100 наносекунд, но в действительности вы увидите, что в большинстве случаев это будет кратный временной интервал планировщика (который варьируется в зависимости от версии окон, но составляет порядка от миллисекунд до десятков миллисекунд).

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

Другие решения

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

clock_t begin=clock(); начинается до выполнения маршрута и clock_t end=clock(); начинается сразу после выхода из рутины.

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

__rdtscp intrinsic даст вам время в циклах процессора с некоторыми оговорками.
Вот статья MSDN

Это действительно зависит от того, что вы хотите измерить. Для лучших результатов возьмите в среднем несколько миллионов (если не миллиард) итераций.

Функция clock () [как предусмотрено в Visual C ++ 2008] не возвращает процессорное время, используемое программой, пока должен (в соответствии со стандартом C и / или стандартом C ++). Тем не менее, для измерения процессорного времени в Windows у меня есть вспомогательный класс (который неизбежно является непереносимым):


Например, можно измерить, сколько времени занимает выполнение блока, определив ScopedProcessorTimer в начале этого блока <>.

Этот код является процесс использования процессора

Измерение времени выполнения блока кода на C/С++

Распространенный совет, который дают новичкам: подключить библиотеку time.h и, с помощью функции получения времени clock() , определить время перед выполнением блока кода и после него. Время выполнения блока будет разницей полученных времен. То есть, что-то вроде

Здесь clock_t — арифметический тип для представления времени; clock() возвращает время, фиксируемое процессором от начала выполнения программы, или -1 , если оно не известно. Для выражения этого времени в секундах применяется формула clock()/CLOCKS_PER_SEC .

Однако такой способ плохо подходит для измерения коротких интервалов времени. Рассмотрим следующий код

Он (взят отсюда) составлен по приведенной выше схеме и подсчитывает количество простых чисел на интервале от 0 до maxnum . Сущность вычислений сейчас не важна — они просто занимают некоторое время, которое мы пытаемся подсчитать. Выполнив, получим

Теперь уменьшим maxnum в 10 раз

Количество простых чисел сократилось даже менее, чем в 10 раз. Казалось бы, мы вправе ожидать ненулевого результата, но. Недаром пишут в руководстве по clock():

Видимо, все дело в этом «approximation».

Обращает на себя внимание то, что следующая за выводом программы строка

показывала ненулевое время. То есть системные средства считают все, что нужно, и пора ими воспользоваться.

Сначала приведем решения для Linux, хотя они работают и в Windows при использовании компилятора MinGW. Итак, альтернативами clock() являются gettimeofday() и clock_gettime() .

позволяет получить время в виде структуры timeval (вторая структура — timezone считается устаревшей и при вызове заменяется NULL’ом):

которая содержит число секунд и микросекунд, прошедших с 1-го января 1970 г. 00:00:00 Всемирного времени. Имеется в виду, что с начального момента прошло tv_sec секунд и еще tv_usec микросекунд.

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

Тестовую программу переделаем следующим образом:

В результате получим

Calculating. The number of primes lower than 100000 is: 9592 It took me 144 milliseconds.

Calculating. The number of primes lower than 10000 is: 1229 It took me 7 milliseconds.

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

Функция clock_gettime() из time.h обеспечивает доступ к нескольким видам системных таймеров и имеет наносекундное разрешение. Прототип функции имеет вид:

clk_id позволяет выбрать вид таймера, например (приведу фрагмент из руководства, там есть и другие таймеры):

  • CLOCK_REALTIME , a system-wide realtime clock.
  • CLOCK_PROCESS_CPUTIME_ID , high-resolution timer provided by the CPU for each process.
  • CLOCK_THREAD_CPUTIME_ID , high-resolution timer provided by the CPU for each of the threads.

Время сохраняется в структуре timespec

по тому же принципу, что и в timeval : с начального момента прошло tv_sec секунд и еще tv_nsec наносекунд.

Запишем функцию, возвращающую время в миллисекундах, основываясь на clock_gettime()

Теперь — Windows-решение, работающее в Visual Studio. Это функция GetTickCount() , возвращающая время в миллисекундах с момента старта операционной системы и в течение 49.7 дней:

DWORD WINAPI GetTickCount(void);

Поскольку GetTickCount() возвращает DWORD , счетчик времени сбрасывается в ноль через 49.7 дней. Эта проблема решается использованием GetTickCount64()

ULONGLONG WINAPI GetTickCount64(void);

переполнение в которой вряд ли возможно.

Тестовая программа с использованием GetTickCount() :

Читайте также


Комментарии

Дмитрий Храмов
Компьютерное моделирование и все, что с ним связано: сбор данных, их анализ, разработка математических моделей, софт для моделирования, визуализации и оформления публикаций. Ну и за жизнь немного.

Функции работы с датой и временем

Для работы с системной датой и временем используется библиотека time.h .

Типы, определенные в библиотеке time.h

Тип Описание
size_t Целочисленный тип, возвращаемый операцией sizeof .
clock_t Арифметический тип, подходящий для представления времени.
time_t Арифметический тип, подходящий для представления времени.
struct tm Структурный тип, содержащий компоненты календарного времени.

Для определения текущего календарного времени используется функция

Данная функция возвращает время в секундах начиная с 1 января 1970 г.

Структура tm имеет вид

преобразует календарное время, указанное ptm , сохраняет его в структуре tm и возвращает указатель на нее.

осуществляет обратное преобразование.

Если время не доступно или не может быть представлено, возвращает (clock_t) (-1) .

копирует строку fmt в строку s , заменяя спецификаторы формата в fmt соответствующими данными, взятыми из содержимого структуры времени, на которое указывает tmpt ; в строку s помещается не более max символов.

Функция возвращает количество символов (исключая нулевой) в результирующей строке. Если результирующая строка (включая нулевой символ) содержит больше, чем max символов, функция возвращает 0, а содержимое s не определено.

Спец. Назначение
%a Локальное сокращенное название дня недели
%A Локальное полное название дня недели
%b Локальное сокращенное название месяца
%B Локальное полное название месяца
%c Локальный разделитель даты и времени
%d День месяца в виде десятичного числа (01-31)
%D Эквивалент %m%d%y
%e День месяца (десятичное число): однозначные числа дополнены пробелом
%F Эквивалент %Y-%m-%d
%g Последние два разряда года (00-99)
%G Год в виде десятичного числа
%H Часы (по 24-часовой шкале) в виде десятичного числа (00-23)
%I Часы (по 12-часовой шкале) в виде десятичного числа (01-12)
%j День года в виде десятичного числа (001-366)
%m Месяц в виде десятичного числа (01-12)
%n Символ новой строки
%M Минуты в виде десятичного числа (00-59)
%p Локальный эквивалент a.m./p.m. для 12-часовой временной шкалы
%r Локальное 12-часовое время
%R Эквивалент %H:%M
%S Секунды в виде десятичного числа (00-61)
%t Символ горизонтальной табуляции
%T Эквивалент %H:%M:%S
%u Номер дня недели (1-7), где 1 соответствует понедельнику
%U Номер недели в году, считая воскресенье первым днем недели (00-53)
%w Номер дня недели в виде десятичного числа, начиная с воскресенья (0-6)
%W Номер недели в году, считая понедельник первым днем недели (00-53)
%y Год без века в виде десятичного числа (00-99)
%Y Год с веком в виде десятичного числа
%z Смещение от UTC («-800» означает на 8 ч по Гринвичу западнее).
%Z Наименование часового пояса (если доступно)
%% % (то есть знак процента).

Функция, позволяющая вывести день недели на русском языке

Добавление нескольких дней к текущему времени

Рассмотрим еще один пример. Допустим, требуется добавить несколько дней к текущей дате.
Реализация на Си

Средства для измерения времени выполнения кода

Добрый день! Подскажите, пожалуйста, какие-нибудь библиотеки для измерения времени выполнения участка кода на С++.

7 ответов 7

Под Windows можно использовать QueryPerformanceCounter и QueryFrequencyCounter. Если необязательно нужен самый точный таймер, то можно использовать GetTickCount.

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

Я меряю в миллисекундах. IMHO в реальности более мелким единицам доверять (при замерах производительности) нельзя.

Очень просто, работает и в Windows (использую MinGW) и в Linux.

time.h — подключив библиотеку можно воспользоваться функцией получения времени time() — получить время перед выполнением блока кода, и после. Время выполнения блока, будет разницей полученных времен.

  • timer: Измерение затраченного времени.
  • progress_timer: Измерение затраченного времени (с использованием таймера), воспроизведение при уничтожении.
  • progress_display: Отображение информации о прогрессе в направлении заданной цели.

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

заголовок *profiler.h*

реализация *profiler.cpp*

самое простое использование — вставить SHOT_PROFILER_CPU в начало блока, скорость выполнения которого нужно замерить. < SHOT_PROFILER_CPU; // Какой то код >

Ещё очень часто удобно просто компилировать с опцией -fopenmp (g++ -fopenmp . ) , подключать omp.h и использовать double omp_get_wtime() , которая возвращает время в секундах, но имеет тип double , т.е. покажет затраченное время, как, например, 12.3452 ( 12,3452 секунды):

Удобно в связи с форматом (double) и тем, что почти все имеют поддержку openmp (gcc, компилятор в Microsoft Visual Studio, насколько я знаю, тоже, и др).

С появлением C++11, появились дополнительные кроссплатформенные решения по измерению скорости выполнения кода стандартными средствами. В С++11 имеется библиотека времени chrono.

В мире компьютера существует два типа часов:


  • REALTIME(измеряет реальное время в системе)
  • MONOTONIC(измеряет время начиная с некоторого времени в прошлом и всегда увеличивается)

Вкратце, чтобы показать разницу между типами: если взять и перевести в системе часы назад, то значение MONOTONIC часов по-прежнему будет увеличиваться, а значение REALTIME часов станут меньше, так как системные часы переведены назад.
Чем отличаются эти два типа часов более подробно рассказано в английском SO.
Для измерения времени выполнения кода предпочтительнее использовать MONOTONIC часы.

В библиотеке chrono классом, реализующего MONOTONIC часы, является класс steady_clock. Он гарантирует реальное измерение времени с максимально высокой точностью. С помощью него измерить разницу можно очень просто

C-C++: как измерять процессорное время

От переводчика:
Большинство моих знакомых для измерения времени в разного вида бенчмарках в С++ используют chrono или, в особо запущенных случаях, ctime . Но для бенчмаркинга гораздо полезнее замерять процессорное время. Недавно я наткнулся на статью о кроссплатформенном замере процессорного времени и решил поделиться ею тут, возможно несколько увеличив качество местных бенчмарков.

P.S. Когда в статье написано «сегодня» или «сейчас», имеется ввиду «на момент выхода статьи», то есть, если я не ошибаюсь, март 2012. Ни я, ни автор не гарантируем, что это до сих пор так.
P.P.S. На момент публикации оригинал недоступен, но хранится в кэше Яндекса

Функции API, позволяющие получить процессорное время, использованное процессом, отличаются в разных операционных системах: Windows, Linux, OSX, BSD, Solaris, а также прочих UNIX-подобных ОС. Эта статья предоставляет кросс-платформенную функцию, получающую процессорное время процесса и объясняет, какие функции поддерживает каждая ОС.

Как получить процессорное время

Процессорное время увеличивается, когда процесс работает и потребляет циклы CPU. Во время операций ввода-вывода, блокировок потоков и других операций, которые приостанавливают работу процессора, процессорное время не увеличивается пока процесс снова не начнет использовать CPU.

Разные инструменты, такие как ps в POSIX, Activity Monitor в OSX и Task Manager в Windows показывают процессорное время, используемое процессами, но часто бывает полезным отслеживать его прямо из самого процесса. Это особенно полезно во время бенчмаркинга алгоритмов или маленькой части сложной программы. Несмотря на то, что все ОС предоставляют API для получения процессорного времени, в каждой из них есть свои тонкости.

Функция getCPUTime( ) , представленная ниже, работает на большинстве ОС (просто скопируйте код или скачайте файл getCPUTime.c). Там, где это нужно, слинкуйтесь с librt, чтобы получить POSIX-таймеры (например, AIX, BSD, Cygwin, HP-UX, Linux и Solaris, но не OSX). В противном случае, достаточно стандартных библиотек.

Далее мы подробно обсудим все функции, тонкости и причины, по которым в коде столько #ifdef ‘ов.

Использование

Чтобы замерить процессорное время алгоритма, вызовите getCPUTime( ) до и после запуска алгоритма, и выведите разницу. Не стоит предполагать, что значение, возвращенное при единичном вызове функции, несет какой-то смысл.

Обсуждение

Каждая ОС предоставляет один или несколько способов получить процессорное время. Однако некоторые способы точнее остальных.

OS clock clock_gettime GetProcessTimes getrusage times
AIX yes yes yes yes
BSD yes yes yes yes
HP-UX yes yes yes yes
Linux yes yes yes yes
OSX yes yes yes
Solaris yes yes yes yes
Windows yes

Каждый из этих способов подробно освещен ниже.

GetProcessTimes( )

На Windows и Cygwin (UNIX-подобная среда и интерфейс командной строки для Windows), функция GetProcessTimes( ) заполняет структуру FILETIME процессорным временем, использованным процессом, а функция FileTimeToSystemTime( ) конвертирует структуру FILETIME в структуру SYSTEMTIME, содержащую пригодное для использования значение времени.

Доступность GetProcessTimes( ): Cygwin, Windows XP и более поздние версии.

Получение процессорного времени:

clock_gettme( )

На большинстве POSIX-совместимых ОС, clock_gettime( ) (смотри мануалы к AIX, BSD, HP-UX, Linux и Solaris) предоставляет самое точное значение процессорного времени. Первый аргумент функции выбирает «clock id», а второй это структура timespec , заполняемая использованным процессорным временем в секундах и наносекундах. Для большинства ОС, программа должна быть слинкована с librt.

Однако, есть несколько тонкостей, затрудняющих использование этой функции в кросс-платформенном коде:

  • Функция является опциональной частью стандарта POSIX и доступна только если _POSIX_TIMERS определен в значением больше 0. На сегодняшний день, AIX, BSD, HP-UX, Linux и Solaris поддерживают эту функцию, но OSX не поддерживает.
  • Структура timespec , заполняемая функцией clock_gettime( ) может хранить время в наносекундах, но точность часов отличается в разных ОС и на разных системах. Функция clock_getres( ) возвращает точность часов, если она вам нужна. Эта функция, опять-таки, является опциональной частью стандарта POSIX, доступной только если _POSIX_TIMERS больше нуля. На данный момент, AIX, BSD, HP-UX, Linux и Solaris предоставляют эту функцию, но в Solaris она не работает.
  • стандарт POSIX определяет имена нескольких стандартных значений «clock id», включая CLOCK_PROCESS_CPUTIME_ID , чтобы получить процессорное время процесса. Тем не менее, сегодня BSD и HP-UX не имеют этого id, и взамен определяют собственный id CLOCK_VIRTUAL для процессорного времени. Чтобы запутать все ещё больше, Solaris определяет оба этих, но использует CLOCK_VIRTUAL для процессорного времени потока, а не процесса.
ОС Какой id использовать
AIX CLOCK_PROCESS_CPUTIME_ID
BSD CLOCK_VIRTUAL
HP-UX CLOCK_VIRTUAL
Linux CLOCK_PROCESS_CPUTIME_ID
Solaris CLOCK_PROCESS_CPUTIME_ID
  • Вместо того, чтобы использовать одну из констант, объявленных выше, функция clock_getcpuclockid( ) возвращает таймер для выбранного процесса. Использование процесса 0 позволяет получить процессорное время текущего процесса. Однако, это ещё одна опциональная часть стандарта POSIX и доступна только если _POSIX_CPUTIME больше 0. На сегодняшний день, только AIX и Linux предоставляют эту функцию, но линуксовские include-файлы не определяют _POSIX_CPUTIME и функция возвращает ненадёжные и несовместимые с POSIX результаты.
  • Функция clock_gettime( ) может быть реализована с помощью регистра времени процессора. На многопроцессорных системах, у отдельных процессоров может быть несколько разное восприятие времени, из-за чего функция может возвращать неверные значения, если процесс передавался от процессора процессору. На Linux, и только на Linux, это может быть обнаружено, если clock_getcpuclockid( ) возвращает не-POSIX ошибку и устанавливает errno в ENOENT . Однако, как замечено выше, на Linux clock_getcpuclockid( ) ненадежен.

На практике из-за всех этих тонкостей, использование clock_gettime( ) требует много проверок с помощью #ifdef и возможность переключиться на другую функцию, если она не срабатывает.

Доступность clock_gettime( ): AIX, BSD, Cygwin, HP-UX, Linux и Solaris. Но clock id на BSD и HP-UX нестандартные.

Доступность clock_getres( ): AIX, BSD, Cygwin, HP-UX и Linux, но не работает Solaris.

Доступность clock_getcpuclockid( ): AIX и Cygwin, не недостоверна на Linux.


Получение процессорного времени:

getrusage( )

На всех UNIX-подобных ОС, функция getrusage( ) это самый надежный способ получить процессорное время, использованное текущим процессом. Функция заполняет структуру rusage временем в секундах и микросекундах. Поле ru_utime содержит время проведенное в user mode, а поле ru_stime — в system mode от имени процесса.

Внимание: Некоторые ОС, до широкого распространения поддержки 64-бит, определяли функцию getrusage( ) , возвращающую 32-битное значение, и функцию getrusage64( ) , возвращающую 64-битное значение. Сегодня, getrusage( ) возвращает 64-битное значение, а getrusage64( ) устарело.

Доступность getrusage( ): AIX, BSD, Cygwin, HP-UX, Linux, OSX, and Solaris.

Получение процессорного времени:

times( )

На всех UNIX-подобных ОС, устаревшая функция times( ) заполняет структуру tms с процессорным временем в тиках, а функция sysconf( ) возвращает количество тиков в секунду. Поле tms_utime содержит время, проведенное в user mode, а поле tms_stime — в system mode от имени процесса.

Внимание: Более старый аргумент функции sysconf( ) CLK_TCK устарел и может не поддерживаться в некоторых ОС. Если он доступен, функция sysconf( ) обычно не работает при его использовании. Используйте _SC_CLK_TCK вместо него.

Доступность times( ): AIX, BSD, Cygwin, HP-UX, Linux, OSX и Solaris.

Получение процессорного времени:

clock( )

На всех UNIX-подобных ОС, очень старая функция clock( ) возвращает процессорное время процесса в тиках, а макрос CLOCKS_PER_SEC количество тиков в секунду.

Заметка: Возвращенное процессорное время включает в себя время проведенное в user mode И в system mode от имени процесса.

Внимание: Хотя изначально CLOCKS_PER_SEC должен был возвращать значение, зависящее от процессора, стандарты C ISO C89 и C99, Single UNIX Specification и стандарт POSIX требуют, чтобы CLOCKS_PER_SEC имел фиксированное значение 1,000,000, что ограничивает точность функции микросекундами. Большинство ОС соответствует этим стандартам, но FreeBSD, Cygwin и старые версии OSX используют нестандартные значения.

Внимание: На AIX и Solaris, функция clock( ) включает процессорное время текущего процесса И и любого завершенного дочернего процесса для которого родитель выполнил одну из функций wait( ) , system( ) или pclose( ) .

Внимание: В Windows, функция clock( ) поддерживается, но возвращает не процессорное, а реальное время.

Доступность clock( ): AIX, BSD, Cygwin, HP-UX, Linux, OSX и Solaris.

Получение процессорного времени:

Другие подходы

Существуют и другие ОС-специфичные способы получить процессорное время. На Linux, Solarisи некоторых BSD, можно парсить /proc/[pid]/stat, чтобы получить статистику процесса. На OSX, приватная функция API proc_pidtaskinfo( ) в libproc возвращает информацию о процессе. Также существуют открытые библиотеки, такие как libproc, procps и Sigar.

На UNIX существует несколько утилит позволяющих отобразить процессорное время процесса, включая ps, top, mpstat и другие. Можно также использовать утилиту time, чтобы отобразить время, потраченное на команду.

На Windows, можно использовать диспетчер задач, чтобы мониторить использование CPU.

На OSX, можно использовать Activity Monitor, чтобы мониторить использование CPU. Утилита для профайлинга Instruments поставляемая в комплекте с Xcode может мониторить использование CPU, а также много других вещей.

Downloads

  • getCPUTime.c реализует выше описанную функцию на C. Скомпилируйте её любым компилятором C и слинкуйте с librt, на системах где она доступна. Код лицензирован под Creative Commons Attribution 3.0 Unported License.

Смотри также

Связанные статьи на NadeauSoftware.com

  • C/C++ tip: How to measure elapsed real time for benchmarking объясняет как получить реальное время, чтобы измерить прошедшее время для куска кода, включая время, потраченное на I/O или пользовательский ввод.
  • C/C++ tip: How to use compiler predefined macros to detect the operating system объясняет как использовать макросы #ifdef для ОС-специфичного кода. Часть из этих методов использовано в этой статье, чтобы определить Windows, OSX и варианты UNIX.

Linux.yaroslavl.ru

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

Функции времени относятся к трем категориям:

  • Функции для измерения прошедшего времени CPU обсуждены в Разделе 17.1 [Время Процессора].
  • Функции календарного времени обсуждены в Разделе 17.2 [Календарное Время].
  • Функции для установки будильников и таймеров обсуждены в Разделе 17.3 [Установка Сигнализации].

Если вы пробуете оптимизировать вашу программу или измерять эффективность, очень полезно знать, сколько времени процессора или CPU времени она использовала в любой заданной точке. Процессорное время является отличным от фактических часов, потому что оно не включает все потраченное время на ожидание ввода-вывода или когда выполняется некоторый другой процесс. Процессорное время представляется типом данных clock_t, и дано как ряд импульсов времени относительно произвольного базового времени, отмечающего начало одиночного вызова программы.


Запрос Основного Времени CPU

Чтобы получить прошедшее CPU время, используемое процессом, Вы можете использовать функцию clock. Это средство объявлено в заглавном файле » time.h «.

Обычно, Вы вызываете функцию clock в начале и конца интервала, который Вы хотите измерить, вычитаете значения, и тогда делите на CLOCKS_PER_SEC (число импульсов времени clock в секунду), примерно так:

В системе GNU, clock _t эквивалентен long int, а CLOCKS_PER_SEC — целочисленное значение. Но в других системах, и clock _t и тип макрокоманды CLOCKS_PER_SEC может быть или целое число, или с плавающей точкой. Приведением значения времени процессора к double, см. пример выше, удостоверяется, что нужные операции работают правильно и последовательно независимо от того, каково основное представление.

Детализированный Запрос Времени CPU

Функция times возвращает более детализированную информацию относительно прошедшего процессорного времени в struct tmsobject. Вы должны включить заглавный файл » sys/times.h » чтобы использовать это средство.

Все времена даны в импульсах сигналов времени. Они — абсолютные значения; в новом процессе, они — все нуль. См. Раздел 23.4 [Создание Процесса].

Возвращаемое значение — также как значение clock (): прошедшее реальное время относительно произвольной основы. Основа — константа внутри специфического процесса, и обычно представляет время начиная с запуска системы. Значение (clock_t) (-1) возвращается, чтобы указать отказ.

Примечание Переносимости: функция clock, описанная в Разделе 17.1.1 [Базисное процессорное Время], определена в соответствии c стандартом ANSI C. Функция times — возможность POSIX.1. В системе GNU, значение, возвращенное функцией clock эквивалентно сумме tms_utime и tms_stime полей, возвращенных times.

Этот раздел описывает средства для слежения за датами и временем согласно Грегорианскому календарю.

Имеются три представления информации даты и времени:

  • Календарное время (time_t тип данных) — компактное представление, обычно дает число секунд, истекающих начиная с некоторого основного времени.
  • Имеется также представление времени с высоким разрешением (struct timeval тип данных) которое включает доли секунды. Используйте это представление времени вместо обычного календарного времени, когда нужна большая точность.
  • Местное время (struct tm тип данных) представляет дату и время как набор компонентов, определяющих год, месяц, и так далее, для специфического часового пояса. Это представление обычно используется вместе с форматированием значений даты и времени.

Простое Календарное Время

Этот раздел описывает time_t тип данных для представления календарного времени, и функции, которые используют объекты календарного времени. Эти средства объявлены в заглавном файле » time.h «.

В других системах, time_t может быть или целым числом или с плавающей запятой.

В системе GNU, Вы можете просто вычитать значения time_t. Но в других системах, time_t тип данных может использовать некоторое другое кодирование, где вычитание не работает непосредственно.

Календарь с высоким разрешением

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

Некоторые приложения нуждаются в большей точности.

Так, библиотека GNU C также содержит функции, которые способны представить календарь с более высокой разрешающей способностью чем одна секунда. Функции и связанные типы данных, описанные в этом разделе объявлены в » sys/time.h «.

Некоторые значения struct timeval — используются для временных интервалов. Тогда tv_sec элемент — число секунд в интервале, а tv_usec — число микросекунд.

Часто необходимо вычесть два значения типа struct timeval. Вот самый лучший способ делать это. Он работает даже на некоторых специфических операционных системах, где tv_sec элемент имеет тип unsigned.

Возвращаемое значение — 0 при успехе и -1 при отказе. Следующее errno условие ошибки определено для этой функции: ENOSYS

операционная система не поддерживает получение информации часового пояса, и tzp — не пустой указатель. Операционная система GNU не поддерживает использование struct timezoneto для представления информации часового пояса; это — устаревшая возможность 4.3 BSD. Вместо этого, используйте средства, описанные в Разделе 17.2.6 [Функции Часового пояса].

Вы должны быть привилегированным пользователем, чтобы использовать settimeofday.

Возвращаемое значение — 0 при успехе и -1 при отказе. Следующие errno условия ошибки определены для этой функции: EPERM

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

операционная система не поддерживает установку информации часового пояса, и tzp — не пустой указатель.

Аргумент delta определяет относительную корректировку, которая будет сделана относительно текущего времени. Если он отрицателен, часы системы замедляются. Если положителен, часы системы ускоряются.

Если аргумент olddelta — не пустой указатель, функция adjtime, возвращает информацию относительно любой предыдущей корректировки, которая еще не завершилась.

Эта функция обычно используется, чтобы синхронизировать часы компьютеров в местной сети.

Вы должны быть привилегированным пользователем, чтобы использовать ее. Возвращаемое значение — 0 при успехе и -1 при отказе. Следующее errno условие ошибки определено для этой функции: EPERM

Вы не имеют привилегий, чтобы установить время. Примечание Переносимости: функции gettimeofday, settimeofday, и adjtime — из BSD.

Разделенное Время

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


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

Символы в этом разделе объявлены в заглавном файле » time.h «.

Tm_gmtoff поле ­ расширение библиотеки GNU.

Возвращаемое значение — указатель на статическую структуру разделенного времени, которая могла бы быть записана поверх последующими обращениями к любой из функций date и time. (Но никакая другая библиотечная функция не записывает поверх содержимого этого объекта.)

Вызов localtime имеет и другой эффект: она устанавливает переменную tzname с информацией относительно текущего часового пояса. См. Раздел 17.2.6 [Функции Часового пояса].

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

Mktime функция игнорирует заданное содержимое tm_wday и tm_yday элементов структуры разделенного времени. Она использует значения других компонентов, чтобы вычислить календарное время; для этих компонентов допустимо иметь ненормализованные значения вне их нормальных диапазонов. Еще mktime корректирует компоненты структуры brokentime (включая tm_wday и tm_yday).

Если заданное разделенное время не может представляться как календарное время, mktime, возвращает значение (time_t) (-1) и не изменяет содержимое brokentime.

Вызов mktime также устанавливает переменную tzname с информацией относительно текущего часового пояса. См. Раздел 17.2.6 [Функции Часового пояса].

Форматирование Даты и времени

Функции, описанные в этом разделе форматирнуют значения времени как строки. Эти функции объявлены в заглавном файле » time.h «.

Сокращения для месяцев: `Jan’, `Feb’, `Mar’, `Apr’, `May’, `Jun’, `Jul’, `Aug’, `Sep’, `Oct’, `Nov’, and `Dec’.

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

Обычные символы, появляющиеся в шаблоне копируются в строку вывода s; она может включать многобайтовые символы. Спецификаторы Преобразования представляются символом ` % ‘, и заменяются в строке вывода следующим образом:

  • %a сокращенный день недели согласно текущему стандарту.
  • %A полный день недели согласно текущему стандарту.
  • %b сокращенный месяц согласно текущему стандарту.
  • %B полное название месяца согласно текущему стандарту.
  • %c привилегированное представление даты и времени для текущего стандарта.
  • %d день месяца как десятичное число (от 01 до 31).
  • %H час как десятичное число, используя 24-часовые часы (от 00 до 23).
  • %I час как десятичное число, используя 12-часовые часы (от 01 до 12).
  • %j день года как десятичное число (от 001 до 366).
  • %m месяц как десятичное число (от 01 до 12).
  • %M минуты как десятичное число.
  • %p Или «am» или «pm», согласно данному значению времени; или соответствующие строки для текущего стандарта.
  • %S секунды как десятичное число.
  • %U число недель текущего года как десятичное число, начинающееся с первого воскресенья как первый день первой недели.
  • %W число недель текущего года как десятичное число, начинающееся с первого понедельника как первый день первой недели.
  • %w день недели как десятичное число, воскресенье — 0.
  • %x привилегированное представление даты для текущего стандарта, но без времени.
  • %X привилегированное представление времени для текущего стандарта, но без даты.
  • %y год как десятичное число, но без столетия (от 00 до 99).
  • %Y год как десятичное число, включая столетие.
  • %Z часовой пояс или имя или сокращение (пусто, если часовой пояс не может быть определен).
  • %% литеральный символ ` % ‘.

Параметр size может использоваться, чтобы определить максимальное число символов, которое будет сохранено в массиве s, включая пустой символ завершения. Если форматируемое время требует больше чем size символов, лишние символы отбрасываются. Возвращаемое значение из strftime — число символов, помещенное в массив s, не включая пустой символ завершения. Если значение равняется размеру, это означает что массив s был слишком мал; Вы должны повторить обращение, обеспечивая больший массив.

Если s — пустой указатель, strftime не делает фактической записи чего-нибудь, но взамен возвращает число символов, которое она написала бы.

Для примера strftime, см. Раздел 17.2.7 [Пример Функции Времени].

Определение Часового пояса с TZ

В системе GNU, пользователь может определять часовой пояс посредством TZ переменной среды.

Для уточнения инфрмации относительно того, как устанавливать переменные среды, см. Раздел 22.2 [Переменные среды]. Функции для доступа к часовому поясу объявлены в » time.h «.

Значение TZ переменной может иметь один из трех форматов. Первый формат используется, когда не имеется никакого Смещения светового дня (или в летнее время) в зоне местного времени:

Смещение определяет значение которое нужно добавить к местному времени, чтобы получить значение Координированного Универсального времени. Она имеет синтаксис подобно [+ | -] hh [: mm [: ss]]. Она положительно, если зона местного времени — к западу от Главного меридиана и отрицательно, если она восточнее. Час должен быть от 0 до 24, а минуты и секунды от 0 до 59.

Например, вот, как мы определили бы Восточное Стандартное Время, но без любых Смещений Светового дня:

Остаточный член от спецификации описывает, когда смещение светового дня действует. Поле start — то, когда смещение светового дня входит в силу, а поле end — то, когда изменение будет сделано обратно к стандартному времени. Следующие форматы распознаваемы для этих полей: Jn определяет Юлианский день, с n между 1 и 365. 29 февраля никогда не рассчитывается, даже в високосные годы. N определяет Юлианский день, с n между 0 и 365. 29 февраля рассчитан в високосные годы. Mm.w.d определяет день d недели w месяца m. день d должен быть между 0 (воскресеньем) и 6. Неделя w должна быть между 1 и 5; неделя 1 — первая неделя, в которой есть день d , а неделя 5 определяет последний d день в месяце. Месяц m должен быть между 1 и 12.

Поля time определяют, когда, по местному времени происходит изменение к другому времени. Значение по умолчанию — 02:00:00.

Например, вот, как можно определить Восточный часовой пояс в Соединенных Штатах, включая соответствующее смещение светового дня и даты применимости. Нормальное смещение ПО ГРИНВИЧУ — 5 часов; так как это — к западу от главного меридиана, знак положителен. Летний период начинается в первое воскресенье апреля в 2:00am, и кончается в последнее воскресенье октября в 2:00am.

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

Третий формат походит на:

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

Функции и Переменные для Часовых поясов

Следующие переменные определены для совместимости с System V Unix. Эти переменные устанавливаются вызоввом localtime.

Пример Функции Времени

Вот пример программы, показывающий использование некоторых функций местного и календарного времени.

Функции alarm и setitimer обеспечивают механизм прерывания процесса, в некоторое время. Они делают это, устанавливая таймер; когда время таймер истекает, процесс получает сигнал.

Каждый процесс имеет три доступных независимых таймера интервала:

  • Таймер в реальном времени, который считает время как часы. Этот таймер посылает сигнал SIGALRM процессу, когда время истекает.
  • Виртуальный таймер, который считает процессорное время, используемое процессом. Этот таймер посылает сигнал SIGVTALRM процессу, когда время истекает.
  • Таймер профилирования, который считает оба: процессорное время, используемое процессом, и процессорное время, потраченное в системных вызовах от имени процесса. Этот таймер посылает сигнал SIGPROF процессу, когда время истекает.


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

Вы должны установить обработчик для соответствующего сигнала alarm, используюя signal или sigaction перед обращением к setitimer или alarm. Иначе, необычная цепочка событий может заставлить таймер исчерпать время прежде, чем ваша программа установит обработчик, и в этом случае она будет завершена, так как это — заданное по умолчанию действие для сигналов alarm. См. Главу 21 [Обработка Сигнала].

Функция setitimer — первичный способ для установки будильника. Это средство объявлено в заглавном файле » sys/time.h «. Функция alarm, объявленная в » unistd.h «, обеспечивает несколько более простой интерфейс для установки таймера в реальном времени.

Тип данных Struct timeval описан в Разделе 17.2.2 [Календарь с высоким разрешением].

Если old — не пустой указатель, setitimer возвращает информацию относительно любого предыдущего неистекшего таймера того же самого вида в структуре, на которую он указывает.

Возвращаемое значение — 0 при успехе и -1 при отказе. Следующие errno условия ошибки определены для этой функции: EINVAL

интервал таймера был слишком большой.

Возвращаемое значение и условия ошибки — такие же как для setitimer.

Возвращаемое значение указывает, сколько секунд оставалось прежде, чем предыдущий сигнал был бы послан. Если не было никакого предыдущего сигнала, alarm возвращает нуль.

Функция alarm могла бы быть определена в терминах setitimer примерно так:

Если Вы просто хотите, чтобы ваш процесс ждал данное число секунд, Вы должен использовать функцию sleep. См. Раздел 17.4 [Sleep].

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

Примечание Переносимости: setitimer и getitimer — функции UNIX BSD, в то время как функция alarm определена POSIX.1 стандартом. Setitimer более мощная чем alarm, но alarm более широко используется.

Sleep дает простой способ заставить программу ждать некоторый период времени. Если ваша программа не использует сигналы (за исключением завершения), то Вы можете расчитывать, что sleep будет ждать заданное количество времени. Иначе, sleep может возвращаться, если прибывает сигнал; если Вы хотите ждать данный период независимо от сигналов, используйте select (см. Раздел 8.6 [Ждущий ввод — вывод] ) и не определяйте ни каких описателей ожидания.

Если функция sleep возвращает значение по истечении времени, то это значение нуль. Если она возвращается после сигнала, возвращаемое значение — остающееся время ожидания sleep.

Функция sleep объявлена в » unistd.h «.

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

Функция getrusage и тип данных struct rusage используется для исследования типа использования процесса. Они объявлены в » sys/resource.h «.

В большинстве систем, processes имеет только два допустимых значения:

В системе GNU, Вы можете также запрашивать относительно специфического дочернего процесса, определяя ID процесса.

Возвращаемое значение getrusage — нуль при успехе, и -1 при отказе.

Аргумент EINVAL processes не допустим.

Еще один способ получения типа использования для специфического дочернего процесса — функцией wait4, которая возвращает общие количества для дочернего процесса при его завершении. См. Раздел 23.8 [BSD Функции Ожидания].

Дополнительная историческая функция для исследования типов использования, vtimes, обеспечивается но здесь не описана. Она объявлена в » sys/vtimes.h «.

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

Символы в этом разделе определены в » sys/resource.h «.

Возвращаемое значение — 0 при успехе и -1 при отказе. Единственое возможное errno условие ошибки — EFAULT.

Возвращаемое значение — 0 при успехе и -1 при отказе. Следующее errno условие ошибки возможно: EPERM

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

Rlim_cur Текущее значение рассматриваемого ограничения.

Rlim_max Максимально допустимое значение рассматриваемого ограничения. Вы не можете устанавливать текущее значение ограничения больше чем этот максимум. Только root может изменять максимально допустимое значение.

В getrlimit, эта структура — вывод; она получает текущие значения. В setrlimit она определяет новые значения.

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

Две исторических функции для установки ограничений ресурса, ulimit и vlimit, не зарегистрированы здесь. Они объявлены в » sys/vlimit.h » и исходят ИЗ BSD.

Когда отдельные процессы выполняются, их приоритеты определяют то, какую часть ресурсов CPU каждый процесс получает. Этот раздел описывает, как Вы можете читать и устанавливать приоритет процесса. Все эти функции и макрокоманды объявлены в » sys/resource.h «.

Промежуток допустимых значений зависит от операционной системы, но обычно он выполняется от -20 до 20. Меньшее значение приоритета означает что процесс выполняет чаще. Эти константы описывают некоторые значения: PRIO_MIN самое маленькое допустимое значение приоритета. PRIO_MAX самое большое допустимое значение приоритета.


Возвращаемое значение — значение приоритета при успехе, и -1 при отказе. Следующее errno условие ошибки возможно для этой функции: ESRCH

комбинация class и id не соответствует никакому существующему процессу. EINVAL

значение class не допустимо. Когда возвращаемое значение -1, это может указывать отказ, или значение приоритета.

Единственый способ различить состоит в том, чтобы установить errno = 0 перед вызовом getpriority, и тогда использовать errno!= 0 позже как критерий для отказа.

Возвращаемое значение — 0 при успехе и -1 при отказе. Следующее errno условие ошибки определено для этой функции: ESRCH

комбинация class и id не соответствует никакому существующему процессу. EINVAL

значение класса не допустимо. EPERM

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

Вы пробовали понизить приоритет процесса, и Вы не имеете привилегий для этого. Аргументы class и id вместе определяет набор процессов, которыми Вы заинтересованы. Вот возможные значения для class:

Если id аргумент — 0, то обрабатывается текущий процесс, текущая группа процесса, или текущий пользователь, согласно классу.

процессорное время — CPU time

Процессорного времени (или время процесса ) представляет собой количество времени , в течение которого центральный процессор был использован (ЦП) для обработки инструкций одного компьютерной программы или системы операционной , в отличие от истекшего времени, которая включает в себя, например, в ожидании ввода / вывода (I / O) операции или режим ввода с низким энергопотреблением ( в режиме ожидания). Процессорное время измеряются в тиках или секундах. Часто бывает полезно для измерения времени центрального процессора в процентах от мощности процессора, который называется использованием процессора .

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

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

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

содержание

подразделение

Процессорное время или использование процессора может быть представлено либо для каждой нити , для каждого процесса или для всей системы. Кроме того, в зависимости от того, что именно процессор делает, сообщенные значения могут быть подразделены на:

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

Команды Unix, для процессорного времени

Команда Unix топ

Unix командной топ предоставляет процессорное время, приоритет, прошедшее в режиме реального времени , а также другую информацию для всех процессов и обновлений в режиме реального времени.

Команда Unix времени

Unix команды время времени печатает CPU и прошедшее в режиме реального времени для процесса Unix.

Этот процесс занял в общей сложности 0,337 секунды процессорного времени, из которых 0,327 секунд было израсходовано в пользовательском пространстве, а конечные 0,010 секунды в режиме ядра от имени процесса. Прошедшее в реальное время составило 1,15 секунды.

Ниже приведен исходный код приложения nextPrimeNumber, который был использован в приведенном выше примере.

Функции POSIX clock() и getrusage()

Функции POSIX clock() и getrusage() могут быть использованы для получения процессорного времени потребляемого любого процесса в среде POSIX. Если процесс является многопоточным, время процессора является суммой для всех потоков . С Linux начиная с ядра 2.6.26 есть параметр RUSAGE_THREAD , который приводит к ресурсу статистики использования для только вызывающего потока.

Общее время CPU

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

процессорное время и прошедшее в режиме реального времени

Прошедшее в режиме реального времени всегда больше или равно времени ЦП для компьютерных программ, которые используют только один процессор для обработки. Если не ждать не участвует для ввода / вывода или других ресурсов, прошло в режиме реального времени и время процессора очень похожи.

процессорное время и прошедшее в реальном масштабе времени для параллельной технологии обработки

Если программа использует параллельную обработку , общее время CPU для этой программы будет больше , чем его истекшее реальное время. (Общее время ЦП) / (число процессоров) будет таким же , как истекшее реальное время , если рабочая нагрузка распределяется равномерно на каждый процессор и не ждать не участвуют в I / O или других ресурсы.


Пример: Программное приложение выполняется на гекса-ядерный процессор создает три Unix процессы для выполнения требования пользователя. Каждый из этих трех процессов создает два потока, перечислив в общей сложности 6 рабочих потоков. Вычисление распределяется равномерно на 6 независимых потоков. Если не ждать ресурсов не участвует, общее процессорное время , как ожидается , будет в шесть раз прошли в режиме реального времени.

Точное измерение времени в программах

Эта статья завершает цикл материалов, начатый в № 7/01 и адресованный студентам и школьникам, интересующимся программированием. Были рассмотрены практически все аспекты интерфейса пользователя для спрайтовой игры (за исключением звука): перемещение по экрану одного или нескольких спрайтов, работа с мышью и клавиатурой, вывод текста и чтение файла формата BMP, отсчет времени и некоторые вопросы оптимизации.

Редакции хотелось бы знать мнение читателей, стоит ли в дальнейшем продолжать циклы статей, адресованные начинающему программисту: использование OpenGL для отображения динамичных 3D-сцен; внутренняя логика игр; элементы искусственного интеллекта, применяемые в компьютерных играх, и т. п.

Название статьи не следует понимать как «определение истинного времени», поскольку речь здесь пойдет о таком измерении малых интервалов времени, которое невозможно выполнить стандартными средствами ОС.

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

Один из методов измерения времени уже был описан в журнале 1 , но он возможен только в одной ОС (DOS и совместимые с ней). Другие операционные системы обладают собственными инструментами измерения времени, например Windows включает сообщение таймера или функцию GetTickCount. К сожалению, хотя такие средства и предоставляются разными ОС, они имеют общие недостатки, в первую очередь низкую точность и большую погрешность измерения. Так, в DOS время отсчитывается квантами по 55 мс, в Windows 95 — по 13,7 мс (видимо, эта величина зависит от конфигурации ПК), а в Windows 98/NT — по 5 мс. Таким образом, получается интервал, который существенно больше принятого для отсчета измеряемой величины: для DOS — 0,01 с, для Windows — 1 мс. С периодичностью вызова сообщения таймера дело обстоит еще хуже. Их частота не превышает 18,2 в секунду, а минимальный интервал составляет все те же 55 мс. Кроме того, опыты показывают, что приращение времени — величина непостоянная. Попробуйте запустить следующий фрагмент программы:

t0 := GetTickCount;
for i := 0 to 10 do begin
t1 := t0;
repeat
t0 := GetTickCount;
until t0 <> t1;
c[i] := t0-t1;
end;
for i := 1 to 10 do
writeln(i:3,c[i]:3);

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

Наряду с использованием GetTime и GetTickCount можно применить и более радикальные меры: в DOS — переопределение прерывания таймера, в Windows — употребление QueryPerformanceCounter. Однако и здесь есть свои недостатки.

Тем не менее уже начиная с Pentium средства, пригодные для измерения времени, находятся в центральном процессоре. К ним можно отнести 64-разрядный счетчик циклов тактовой частоты, показания которого считываются программно. Очевидно, значение тактовой частоты достаточно велико, чтобы обеспечить любую разумную точность. Беда только в том, что частота работы у всех процессоров разная и колеблется от 60 МГц до 3 ГГц. Поэтому счетчик следует отградуировать с помощью стандартных функций измерения времени ОС. Конечно, по абсолютной точности он будет уступать стандартным средствам для измерения больших интервалов времени (например, погрешность может составить несколько секунд за час — из-за неточности градуировки), но при определении малых интервалов, а также при вычислении отношения длительности двух измерений его точности вполне достаточно.

Измерение времени на основе внутреннего счетчика процессора реализовано в модуле, приведенном в листинге 1. Он содержит три функции для получения отсчетов времени, функцию для получения полного 64-разрядного значения счетчика (вдруг она кому-нибудь понадобится), а также (в качестве побочного продукта) функции, возвращающие измеренную частоту процессора и предполагаемую погрешность ее измерения.

Наличие трех функций измерения объясняется тем, что использовать 64-разрядные числа в большинстве случаев неудобно (пока еще не нашли широкого применения 64-разрядные процессоры), а 32-разрядный счетчик, работающий на высокой частоте, довольно часто обнуляется. Поэтому для измерения коротких интервалов времени следует предпочесть счетчик с максимальным разрешением, равным 1 мкс, а в остальных случаях — с более грубым.

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

В блоке инициализации модуля происходят подсчет частоты процессора, оценка погрешности вычисления, а также определение коэффициентов деления для всех точек входа и масок для них. Последние необходимы для того, чтобы предотвратить переполнение при целочисленном делении 64-разрядного числа на 32-разрядное. Маска представляет собой максимальное число, не превосходящее делитель, все биты которого установлены в «1». Если маски не вычислять, а задавать константами, то на медленных процессорах будет слишком маленький период обнуления, а на тех, что ожидаются в будущем, вероятно, произойдет аварийное завершение программы из-за ошибки деления.

Чтобы поточнее определить частоту ЦП, измерения нужно проводить несколько раз, далее их массив сортируется и при вычислении берется только его центральная часть (наибольшие и наименьшие результаты отбрасываются). Таким способом удается отсечь отдельные измерения с большой погрешностью, характерные для многозадачных ОС и вызванные разделением времени.

Модуль написан для TMT Pascal 4.0 и совместим с любой из целевых платформ: DOS, Windows или OS/2, причем в двух последних, как консольное приложение 2 . Правда, при работе в стандартной оконной среде Windows в приложениях, использующих кодовую страницу 866, возникают проблемы с кириллицей. Поэтому здесь я изменил своему правилу применять в программах сообщения на русском языке. Другой способ решения проблемы описан во врезке.

Если необходимо переделать модуль для одноплатформного компилятора, не поддерживающего совместимую с DOS процедуру GetTime, то последнюю следует заменить стандартной операцией для выбранной ОС. Например, для Windows целесообразно выбрать GetTickCount, и тогда из цикла измерения можно будет убрать дополнительную проверку на обнуление сотых долей секунды. Константы модуля подобраны для оптимальной работы при интервале приращения показаний системных часов, равном 55 мс, но модуль сохраняет работоспособность и при любых других, что, правда, порой сказывается на точности вычисления тактовой частоты процессора и, следовательно, на точности коэффициентов деления. Здесь необходимо пойти на определенный компромисс: при росте числа измерений (константа n) повышается точность последних, но в этом случае увеличивается время, приходящееся на них и, естественно, тот период, в течение которого пользователю придется простаивать в ожидании загрузки программы. При уменьшении числа измерений наблюдается обратная зависимость. Думаю, что время измерения не более 0,5 с можно считать вполне приемлемым. А если опираться на приращение времени, равное 5 мс, то лучше задать следующие значения констант:

const
n = 100;
Const1 : extended = 0.2;

Можно изменять n таким образом, чтобы время измерения не превышало фиксированной величины, например 500 мс. Однако для этого следует описать размеры массивов не менее чем 501 — на случай, если вдруг приращение времени составит 1 мс.

В таблице приведены процедуры измерения времени. Вот несколько рекомендаций по их применению.

GetTime — предназначена для получения показаний астрономического времени в часах, минутах и секундах. С некоторой натяжкой может быть использована для измерения временн?ых интервалов от нескольких секунд (при условии, что требуется точность не ниже 1%). Данная процедура неудобна из-за того, что нужно отслеживать переходы на следующие секунду, минуту, час, а также сутки. Она работает медленно из-за многочисленных промежуточных вызовов и преобразований. В 24 ч 00 мин 00 с показания сбрасываются.

GetTickCount — подходит для измерения интервалов времени от 0,5 с в случае, если допустима погрешность в пределах 1%. При этом она предпочтительнее всех остальных для измерения больших интервалов времени (в пределах нескольких суток), так как в отличие от GetTime не требует преобразований. Эта процедура позволяет определить время в удобных единицах и не несет в себе погрешности измерения частоты процессора. Данная процедура — самая быстрая, она выполняет наиболее простую работу, а именно читает значения переменной из оперативной памяти или даже из кэш-памяти процессора.

QueryPerformanceCounter — опрашивает при работе порты таймера, подключенного по шине ISA, или ее аналога в современных наборах микросхем. Работает очень долго — несколько миллисекунд, что существенно искажает результаты измерения. Поэтому диапазон ее применения начинается с интервалов в сотни микросекунд. Кроме того, сама единица измерения довольно неудобна. Тем не менее процедура не требует градуировки, возвращаемое ею значение никогда не переполняется и имеет достаточно высокое разрешение, так что она может быть полезна тогда, когда нужно использовать лишь одну операцию в очень широком диапазоне: от долей миллисекунд до нескольких месяцев и даже лет.

GetTimer_1 — применяется от десятков микросекунд до десятков секунд, если, конечно, не хочется «натыкаться» на переход через 0 чаще одного раза на 100 измерений. Впрочем, хороший стиль программирования требует, чтобы подобные ситуации специально отслеживались. И тогда процедуру можно будет безболезненно использовать для измерения времени в интервале до получаса.

GetTimer_50 — наверное, наилучший выбор для программ, написанных для использования на компьютере дома или в офисе. Счетчик переполнится лишь спустя сутки с небольшим после последней перезагрузки ПК, поэтому если компьютер ежедневно выключается или хотя бы перезапускается, то переполнение счетчика не грозит. В то же время процедура обеспечивает достаточную точность, например, при определении того, как распределяется вычислительная нагрузка между разными блоками при формировании одного кадра для игр в режиме реального времени.

GetTimer_1000 — несколько точнее, чем GetTickCount на небольших интервалах (до нескольких секунд), и менее точна на больших вследствие погрешности определения частоты. А если требуется знать не действительное значение времени, а отношение длительности двух измеренных интервалов, то всегда обеспечивает более высокую точность, чем GetTickCount. Кроме того, может использоваться в среде любой ОС.

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

InitTimer — применяется для реинициализации таймера, т. е. для вычисления частоты процессора и всех необходимых констант заново. Пример использования дается в листинге 2.

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

1 См. «Мир ПК», № 1/02, с.117.
2 Точнее, сам модуль сохраняет работоспособность и в GUI, но пример программы осуществляет вывод в консольное окно или файл.

Как работать с текстом в кодировке 866 из оконной среды Windows

При разработке консольных приложений и DOS-программ с помощью оконной среды (IDE) Windows возникает одна проблема, характерная только для нашей страны, а именно, несоответствие кодировок кириллицы: в DOS и консольном режиме используется кодовая страница 866, а в оконной среде — 1251. Проблема не является типично паскалевской, с ней сталкиваются все программисты, которые, используя оконную среду, пишут русскоязычные программы для DOS или консоли. Фактически задача разделяется на две части: достигнуть правильного отображения на экране текста в кодировке 866 и добиться соответствия странице 866 кодов, выдаваемых клавиатурой.

Первая часть решается просто: в качестве шрифта для отображения текста программы следует указать Terminal. Именно его используют консольные приложения, и после его применения текст программы будет отображаться на экране в соответствии с кодовой страницей 866. В среде ТМТ Паскаль для этого нужно внести изменения, выбрав Options•Environment•Display•Font name.

С клавиатурой несколько сложнее. Необходимо установить кодовую таблицу 866 подобно тому, как устанавливаются любые языки, например немецкий или итальянский. Для этого проще всего воспользоваться программой RusLat227, которую можно переписать по адресу http://www.netcity.ru/

sergb. Значительно удобнее поместить ссылку на эту утилиту в папку «Автозагрузка», и тогда в Панели задач постоянно будет присутствовать индикатор раскладки. Стандартный же индикатор лучше убрать. Для этого необходимо выбрать опции «Пуск•Настройка•Панель управления•Клавиатура•Язык» и выключить функцию «Отображать индикатор языка на панели задач».

Илон Маск рекомендует:  Как добавить два фоновых изображения к одному элементу
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL