Есть ли способ измерить время с высокой точностью в Python - точнее, чем на одну секунду? Я сомневаюсь, что это кросс-платформенный способ сделать это; Мне интересно в режиме высокой точности в Unix, в частности Solaris, работающем на машине Sun SPARC.
timeit , по-видимому, способен к высокоточному измерению времени, но вместо измерения сколько времени занимает фрагмент кода, я хотел бы получить прямой доступ к значениям времени.
Стандартная функция 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
Комментарий , оставленный tiho 27-27 марта в 17:21 , заслуживает собственного ответа:
Чтобы избежать кода, специфичного для платформы, use timeit.default_timer ()
blockquote>
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, но возвращает число наносекунд как int Python.
blockquote>
Сообщение Дэвида пыталось показать, какое разрешение часов в 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
Который ~ 0.4e-06
Интересно, что в 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
будет исправлять его каждый час)
time.clock
измеряет прошедшее время до высокой точности. В OS X и Linux он измеряет время процессора. Начиная с Python 3.3, устарел в пользу perf_counter
для измерения прошедшего времени и process_time
для измерения CPU.
– George
9 June 2016 в 03:51
Я заметил, что разрешение time.time () отличается от версий Windows 10 Professional и Education.
На машине с Windows 10 Professional разрешение составляет 1 мс. На компьютере с системой Windows 10 разрешение составляет 16 мс.
Я нахожу, что это искусственное ограничение довольно красноречиво (и даже неэтично), особенно если оно не включено в сравнительную документацию Windows, опубликованную Microsoft.
Если 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
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)
Вы также можете использовать time.clock () Он подсчитывает время, используемое процессом в Unix, и время со времени первого вызова на него в Windows.
Это обычно используемая функция для измерения производительности.
Просто позвоните
import time
t_ = time.clock()
#Your code here
print 'Time in function', time.clock() - t_
EDITED: Ups, I пропустите вопрос, как вы хотите точно знать время, а не время, потраченное ...
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)
time.time()
или что ваши вызовы Linux занимают некоторое время (ящик очень медленный, поймал таймер при переходе и т. Д.). Я отправлю код, который показывает способ решения вопроса, который вы здесь задали.
– cod3monk3y
23 January 2014 в 07:50