Как узнать время выполнения программы c visual studio
Распространенный совет, который дают новичкам: подключить библиотеку 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() :
Комментарии
Дмитрий Храмов
Компьютерное моделирование и все, что с ним связано: сбор данных, их анализ, разработка математических моделей, софт для моделирования, визуализации и оформления публикаций. Ну и за жизнь немного.
System. Diagnostics
Простой пример использования Stopwatch
Для начала, рассмотрим простой пример использования класса Stopwatch для измерения затраченного времени на выполнение операции.
- Создать объект класса Stopwatch ;
- Выполнить метод Start() для того, чтобы засечь время начала операции;
- Выполнить метод Stop() для того, чтобы засечь время окончания операции;
- Воспользоваться одним из свойств объекта для получения данных о затраченном на выполнение операции времени.
В примере использовано свойство ElapsedMilliseconds , которое позволяет получить количество миллисекунд, затраченных на выполнение операции. Рассмотрим какие ещё есть свойства и методы у класса Stopwatch .
Stopwatch
Свойства Stopwatch
Elapsed
Свойство Elapsed позволяет получить общее затраченное время, измеренное текущим экземпляром класса Stopwatch . Описание свойства выглядит следующим образом:
ElapsedMilliseconds
Свойство ElapsedMilliseconds позволяет получить общее затраченное время, измеренное текущим экземпляром класса Stopwatch в миллисекундах. В примере использования класса Stopwatch выше продемонстрировано использование этого свойства.
Elapsed Ticks
Свойство Elapsed Ticks позволяет получить общее время выполнение операции в тактах таймера, измеренное текущим экземпляром Stopwatch . Такт — это наименьшая единица времени, которую Stopwatch может измерять таймер. В следующем примере показано использование свойства Elapsed Ticks для измерения времени, затраченного на преобразование строки в целое число типа int .
Результатом выполнения этого кода может быть вот такой вывод консоли:
Is Running
Свойство IsRunning позволяет получить значение типа bool , указывающее на то запущен ли в данный момент таймер Stopwatch .
Поля Stopwatch
Класс Stopwatch содержит два статических поля, позволяющих получить сведения о настройках таймера.
Frequency
Поле Frequency содержит частоту таймера в виде количества тактов в секунду.
Это поле удобно использовать вместе со свойством Elapsed Ticks для преобразования количества тактов в секунды. Например,
Is High Resolution
Свойство Is High Resolution указывает, зависит ли таймер Stopwatch от счетчика производительности высокого разрешения ( true ) или же использует класс DateTime ( false ).
Пример использования поля
Вывод консоли будет иметь следующий вид:
Операции рассчитываются с использованием системного счетчика производительности с высоким разрешением.Частота таймера = 10000000
Таймер работает с точностью до 100 наносекунд
Методы Stopwatch
Start и Stop
Start New
Reset
Restart
Метод Restart() останавливает измерение интервала времени, обнуляет затраченное время и повторно запускает таймер. Таким образом, предыдущий пример можно переписать следующим образом:
Итого
у меня есть программа на C, которая стремится работать параллельно на нескольких процессорах. Мне нужно иметь возможность записывать время выполнения (которое может быть от 1 секунды до нескольких минут). Я искал ответы, но все они, похоже, предлагают использовать clock() функция, которая затем включает в себя вычисление количества часов, взятых программой, разделенной на Clocks_per_second значение.
Я не уверен, как Clocks_per_second стоимость рассчитывается?
в Java, я просто взял текущее время в миллисекундах до и после выполнения.
есть ли подобная вещь в C? Я посмотрел, но, похоже, не могу найти способ получить что-то лучше, чем второе разрешение.
Я также знаю, что профилировщик будет вариантом, но я хочу реализовать таймер сам.
CLOCKS_PER_SEC - константа, которая объявляется в <time.h> . Чтобы получить время процессора, используемое задачей в приложении C, используйте:
обратите внимание, что это возвращает время в виде с плавающей точкой. Это может быть более точным, чем второй (например, вы измеряете 4.52 секунды). Точность зависит от архитектуры; на современных системах вы легко получаете 10 мс или ниже, но на старых машинах Windows (с эпохи Win98) это было ближе к 60 мс.
clock() стандартный C; он работает "везде." Существуют системные функции, такие как getrusage() в Unix-подобных системах.
в Java System.currentTimeMillis() не измеряет то же самое. Это "настенные часы": он может помочь вам измерить, сколько времени потребовалось для выполнения программы, но он не говорит вам, сколько времени процессора было использовано. В многозадачных системах (т. е. во всех) они могут быть совершенно разными.
Если вы используете оболочку Unix для запуска, вы можете использовать команду time.
предполагая a.out как исполняемый файл даст u время, необходимое для запуска этого
вы функционально хотите этого:
обратите внимание, что измеряется в микросекундах, а не только секунд.
в простой ванили C:
большинство простых программ имеют время вычисления в миллисекундах. Так что, я полагаю, вы найдете это полезным.
Если вы хотите вычислить время выполнения всей программы, и вы находитесь в системе Unix, запустите программу с помощью времени такой time ./a.out
многие ответы предлагали clock() а то CLOCKS_PER_SEC С time.h . Это, вероятно, плохая идея, потому что это то, что моя говорит:
так CLOCKS_PER_SEC может быть определено как 1000000, в зависимости от того, какие параметры вы используете для компиляции, и поэтому это не кажется хорошим решением.
вы должны учитывать, что измерения времени это заняло программу для выполнения, во многом зависит от нагрузки, которую машина имеет в этот конкретный момент.
зная, что способ получения текущего времени в C может быть достигнут разными способами, Проще:
надеюсь, что это помогает.
ANSI C указывает только функции времени второй точности. Однако, если вы работаете в среде POSIX вы можете использовать gettimeofday() функция, которая обеспечивает разрешение микросекунд времени, прошедшего с эпохи UNIX.
в качестве примечания я бы не рекомендовал использовать clock (), так как он плохо реализован на многих(если не на всех?) системы и не точны, кроме того, что это относится только к тому, как долго ваша программа потратила на процессор, а не всего срок службы программы, который, согласно вашему вопросу, я предполагаю, что вы хотели бы измерить.
КДПВ
От переводчика:
Большинство моих знакомых для измерения времени в разного вида бенчмарках в С++ используют 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). В противном случае, достаточно стандартных библиотек.
Использование
Чтобы замерить процессорное время алгоритма, вызовите 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 определен в <unistd.h> значением больше 0. На сегодняшний день, AIX, BSD, HP-UX, Linux и Solaris поддерживают эту функцию, но OSX не поддерживает.
- Структура timespec , заполняемая функцией clock_gettime( ) может хранить время в наносекундах, но точность часов отличается в разных ОС и на разных системах. Функция clock_getres( ) возвращает точность часов, если она вам нужна. Эта функция, опять-таки, является опциональной частью стандарта POSIX, доступной только если _POSIX_TIMERS больше нуля. На данный момент, AIX, BSD, HP-UX, Linux и Solaris предоставляют эту функцию, но в Solaris она не работает. определяет имена нескольких стандартных значений "clock id", включая CLOCK_PROCESS_CPUTIME_ID , чтобы получить процессорное время процесса. Тем не менее, сегодня BSD и HP-UX не имеют этого id, и взамен определяют собственный id CLOCK_VIRTUAL для процессорного времени. Чтобы запутать все ещё больше, Solaris определяет оба этих, но использует CLOCK_VIRTUAL для процессорного времени потока, а не процесса.
- Вместо того, чтобы использовать одну из констант, объявленных выше, функция 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( ): 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, а также много других вещей.
Читайте также: