Высокоточные часы в Python - PullRequest
       86

Высокоточные часы в Python

41 голосов
/ 21 декабря 2009

Есть ли способ измерения времени с высокой точностью в Python - точнее, чем за одну секунду? Я сомневаюсь, что есть кросс-платформенный способ сделать это; Мне интересно время с высокой точностью в Unix, особенно в Solaris, работающем на машине Sun SPARC.

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

Ответы [ 12 ]

47 голосов
/ 21 декабря 2009

Стандартная функция time.time() обеспечивает точность до секунды, хотя эта точность зависит от платформы. Для Linux и Mac точность составляет +- 1 мкс или 0,001 миллисекунды. Python в Windows использует точность +- 16 миллисекунд из-за проблем с реализацией часов из-за прерываний процесса. Модуль timeit может обеспечить более высокое разрешение, если вы измеряете время выполнения.

>>> import time
>>> time.time()        #return seconds from epoch
1261367718.971009      

Python 3.7 представляет новые функции для модуля time, которые обеспечивают более высокое разрешение:

>>> import time
>>> time.time_ns()
1530228533161016309
>>> time.time_ns() / (10 ** 9) # convert to floating-point seconds
1530228544.0792289
22 голосов
/ 10 августа 2010

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

/* Implement floattime() for various platforms */

static double
floattime(void)
{
    /* There are three ways to get the time:
      (1) gettimeofday() -- resolution in microseconds
      (2) ftime() -- resolution in milliseconds
      (3) time() -- resolution in seconds
      In all cases the return value is a float in seconds.
      Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
      fail, so we fall back on ftime() or time().
      Note: clock resolution does not imply clock accuracy! */
#ifdef HAVE_GETTIMEOFDAY
    {
        struct timeval t;
#ifdef GETTIMEOFDAY_NO_TZ
        if (gettimeofday(&t) == 0)
            return (double)t.tv_sec + t.tv_usec*0.000001;
#else /* !GETTIMEOFDAY_NO_TZ */
        if (gettimeofday(&t, (struct timezone *)NULL) == 0)
            return (double)t.tv_sec + t.tv_usec*0.000001;
#endif /* !GETTIMEOFDAY_NO_TZ */
    }

#endif /* !HAVE_GETTIMEOFDAY */
    {
#if defined(HAVE_FTIME)
        struct timeb t;
        ftime(&t);
        return (double)t.time + (double)t.millitm * (double)0.001;
#else /* !HAVE_FTIME */
        time_t secs;
        time(&secs);
        return (double)secs;
#endif /* !HAVE_FTIME */
    }
}

(из http://svn.python.org/view/python/trunk/Modules/timemodule.c?revision=81756&view=markup)

19 голосов
/ 23 января 2014

В сообщении Дэвида была попытка показать разрешение часов в Windows. Я был озадачен его выводом, поэтому я написал код, который показывает, что time.time() на моем ноутбуке с Windows 8 x64 имеет разрешение 1 мсек:

# measure the smallest time delta by spinning until the time changes
def measure():
    t0 = time.time()
    t1 = t0
    while t1 == t0:
        t1 = time.time()
    return (t0, t1, t1-t0)

samples = [measure() for i in range(10)]

for s in samples:
    print s

Какие выходы:

(1390455900.085, 1390455900.086, 0.0009999275207519531)
(1390455900.086, 1390455900.087, 0.0009999275207519531)
(1390455900.087, 1390455900.088, 0.0010001659393310547)
(1390455900.088, 1390455900.089, 0.0009999275207519531)
(1390455900.089, 1390455900.09, 0.0009999275207519531)
(1390455900.09, 1390455900.091, 0.0010001659393310547)
(1390455900.091, 1390455900.092, 0.0009999275207519531)
(1390455900.092, 1390455900.093, 0.0009999275207519531)
(1390455900.093, 1390455900.094, 0.0010001659393310547)
(1390455900.094, 1390455900.095, 0.0009999275207519531)

И способ сделать среднее значение для дельты по 1000 выборок:

reduce( lambda a,b:a+b, [measure()[2] for i in range(1000)], 0.0) / 1000.0

Какой вывод на двух последовательных прогонах:

0.001
0.0010009999275207519

Итак, time.time() на моей Windows 8 x64 имеет разрешение 1 мсек.

Аналогичный запуск на time.clock() возвращает разрешение 0,4 микросекунды:

def measure_clock():
    t0 = time.clock()
    t1 = time.clock()
    while t1 == t0:
        t1 = time.clock()
    return (t0, t1, t1-t0)

reduce( lambda a,b:a+b, [measure_clock()[2] for i in range(1000000)] )/1000000.0

Возвращает:

4.3571334791658954e-07

Что ~ 1024 *

Интересная вещь в time.clock() заключается в том, что он возвращает время с момента первого вызова метода, поэтому, если вам нужно время микросекундного разрешения, вы можете сделать что-то вроде этого:

class HighPrecisionWallTime():
    def __init__(self,):
        self._wall_time_0 = time.time()
        self._clock_0 = time.clock()

    def sample(self,):
        dc = time.clock()-self._clock_0
        return self._wall_time_0 + dc

(который, вероятно, через некоторое время будет дрейфовать, но вы можете иногда исправлять это, например, dc > 3600 будет исправлять это каждый час)

14 голосов
/ 21 декабря 2009

Вы также можете использовать time.clock (). Он подсчитывает время, использованное процессом в Unix, и время с момента первого обращения к нему в Windows. Это точнее, чем time.time ().

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

Просто позвоните

import time
t_ = time.clock()
#Your code here
print 'Time in function', time.clock() - t_

Отредактировано: Ups, я скучаю по вопросу, потому что вы хотите точно знать время, а не время, потраченное ...

7 голосов
/ 08 июля 2016

Если Python 3 является опцией, у вас есть два варианта:

  • time.perf_counter, которые всегда используют самые точные часы на вашей платформе. Это включает время, проведенное вне процесса.
  • time.process_time, который возвращает время процессора. НЕ включает время, проведенное вне процесса.

Разница между ними может быть показана с помощью:

from time import (
    process_time,
    perf_counter,
    sleep,
)

print(process_time())
sleep(1)
print(process_time())

print(perf_counter())
sleep(1)
print(perf_counter())

Какие выходы:

0.03125
0.03125
2.560001310720671e-07
1.0005455362793145
4 голосов
/ 05 апреля 2018

Python 3.7 представляет 6 новых функций времени с разрешением наносекунд , например, вместо time.time() вы можете использовать time.time_ns():

import time
print(time.time())
# 1522915698.3436284
print(time.time_ns())
# 1522915698343660458

Эти 6 функций описаны в PEP 564 :

time.clock_gettime_ns(clock_id)

time.clock_settime_ns(clock_id, time:int)

time.monotonic_ns()

time.perf_counter_ns()

time.process_time_ns()

time.time_ns()

Эти функции аналогичны версии без суффикса _ns, но вернуть число наносекунд в виде Python int.

4 голосов
/ 10 августа 2010

time.clock() имеет 13 десятичных знаков в Windows, но только два в Linux. time.time() имеет 17 десятичных знаков в Linux и 16 в Windows, но фактическая точность отличается.

Я не согласен с документацией, что time.clock() следует использовать для тестирования производительности в Unix / Linux. Это не достаточно точно, поэтому, какой таймер использовать, зависит от операционной системы.

В Linux разрешение по времени высокое в time.time():

>>> time.time(), time.time()
(1281384913.4374139, 1281384913.4374161)

В Windows, однако, функция времени, похоже, использует последний вызванный номер:

>>> time.time()-int(time.time()), time.time()-int(time.time()), time.time()-time.time()
(0.9570000171661377, 0.9570000171661377, 0.0)

Даже если я пишу вызовы в разных строках в Windows, он все равно возвращает одно и то же значение, поэтому реальная точность ниже.

Таким образом, при серьезных измерениях необходимо проверить платформу (import platform, platform.system()), чтобы определить, использовать ли time.clock() или time.time().

(протестировано в Windows 7 и Ubuntu 9.10 с python 2.6 и 3.1)

2 голосов
/ 29 ноября 2016

Комментарий , оставленный Тихо 27 марта '14 в 17:21 , заслуживает отдельного ответа:

Чтобы избежать специфичного для платформы кода, используйте timeit.default_timer ()

1 голос
/ 05 февраля 2019

Для тех, кто застрял на Windows (версия> = сервер 2012 или Win 8) и Python 2.7,

import ctypes

class FILETIME(ctypes.Structure):
    _fields_ = [("dwLowDateTime", ctypes.c_uint),
                ("dwHighDateTime", ctypes.c_uint)]

def time():
    """Accurate version of time.time() for windows, return UTC time in term of seconds since 01/01/1601
"""
    file_time = FILETIME()
    ctypes.windll.kernel32.GetSystemTimePreciseAsFileTime(ctypes.byref(file_time))
    return (file_time.dwLowDateTime + (file_time.dwHighDateTime << 32)) / 1.0e7

Функция GetSystemTimePreciseAsFileTime

1 голос
/ 02 июля 2018

Я заметил, что разрешение time.time () отличается в версиях Windows 10 Professional и Education.

На компьютере с Windows 10 Professional разрешение составляет 1 мс. На компьютере с Windows 10 Education разрешение составляет 16 мс.

К счастью, есть инструмент, который увеличивает временное разрешение Python в Windows: https://vvvv.org/contribution/windows-system-timer-tool

С помощью этого инструмента мне удалось достичь разрешения 1 мс независимо от версии Windows. Вы должны поддерживать его работу во время выполнения ваших кодов Python.

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