FreeBSD上的Python时钟函数
在FreeBSD上测试Python的time.clock()函数时,我发现它总是返回一个差不多的值,大约是0.156。
而time.time()函数运行正常,但我需要一个精度稍微高一点的计时器。
有没有人知道它对应的C语言函数是什么?或者有没有其他高精度的计时器可以用?
我不是在做性能分析,所以TimeIt模块在这里不太合适。
4 个回答
time.clock()
在 UNIX 系统上返回的是 CPU 时间,而在 Windows 系统上返回的是程序开始以来的实际时间。我觉得这真是个不太好的设计。
你可以在 Python 的源代码中找到 time.time()
的定义,点击 这里(这是一个 Google 代码搜索的链接)。看起来它使用的是可用的最高精度计时器,根据我快速查找的结果,在 FreeBSD 上也是 gettimeofday()
,这个计时器的精度应该在微秒级别。
不过,如果你真的需要更高的精度,可以考虑自己写一个 C 模块来实现非常高精度的计时(比如说,直接返回当前的微秒数!)。Pyrex 让编写 Python 扩展变得非常简单,而 SWIG 也是一个常用的选择。(不过,如果你想尽量减少计时器的误差,最好还是自己写一个纯 C 的 Python 扩展。)Ctypes 也是一个选择,但可能会比较慢。
祝你好运!
Python里的time.clock函数调用了C语言的clock(3)函数——你可以通过输入man clock
来确认它应该在BSD系统上正常工作,所以我不明白为什么你会遇到问题。也许你可以尝试用ctypes
直接调用系统C库里的clock函数,来绕过你Python版本中的这个明显的bug(前提是你有这个库的.so/.dynlib/.dll文件,或者在FreeBSD上称之为其他动态共享库的文件)?
顺便说一下,time.time应该是非常高精度的,因为它内部调用了gettimeofday(当然,前提是你的Python是正确构建的)——你在你的系统上观察到的精度是多少呢?
编辑:这里有一个wat.c
文件,这是一个特定于BSD的扩展(我只在我的Mac上测试过——抱歉,我手头没有其他BSD版本)来解决这个明显的FreeBSD端口问题:
#include "Python.h"
#include <sys/time.h>
static PyObject *
wat_time(PyObject *self, PyObject *args)
{
struct timeval t;
if (gettimeofday(&t, (struct timezone *)NULL) == 0) {
double result = (double)t.tv_sec + t.tv_usec*0.000001;
return PyFloat_FromDouble(result);
}
return PyErr_SetFromErrno(PyExc_OSError);
}
static PyMethodDef wat_methods[] = {
{"time", wat_time, METH_VARARGS,
PyDoc_STR("time() -> microseconds since epoch")},
{NULL, NULL} /* sentinel */
};
PyDoc_STRVAR(wat_module_doc,
"Workaround for time.time issues on FreeBsd.");
PyMODINIT_FUNC
initwat(void)
{
Py_InitModule3("wat", wat_methods, wat_module_doc);
}
还有这个setup.py
文件,放在同一个目录下:
from distutils.core import setup, Extension
setup (name = "wat",
version = "0.1",
maintainer = "Alex Martelli",
maintainer_email = "aleaxit@gmail.com",
url = "http://www.aleax.it/wat.zip",
description = "WorkAround for Time in FreeBSD",
ext_modules = [Extension('wat', sources=['wat.c'])],
)
这个网址是正确的,所以你也可以在这里下载这两个文件的压缩包。
要构建和安装这个扩展,运行python setup.py install
(如果你有权限在Python的安装目录写入)或者运行python setup.py build_ext -i
,这样会把wat.so文件写入你放置源代码的目录(然后你可以手动把它移动到你想要的地方,但首先可以在构建它的同一目录下尝试,比如用python -c'import wat; print repr(wat.time())'
来测试)。
请告诉我它在FreeBSD(或任何其他带有gettimeofday
的Unix系统)上运行的情况!如果C编译器对gettimeofday
发出警告,可能是你的系统不需要它的第二个参数,试试去掉它!-)
time.clock() 返回的是处理器的时间。也就是说,它显示的是当前程序在处理器上使用了多少时间。所以,如果你有一个叫做 "clock.py" 的 Python 脚本,里面写了 import time;print time.clock()
,每次运行它时,输出的结果几乎是一样的,因为每次运行时都会启动一个新的进程。
这里有一个 Python 控制台的日志,可能能帮助你理解:
>>> import time
>>> time.clock()
0.11
>>> time.clock()
0.11
>>> time.clock()
0.11
>>> for x in xrange(100000000): pass
...
>>> time.clock()
7.7800000000000002
>>> time.clock()
7.7800000000000002
>>> time.clock()
7.7800000000000002
希望这能让你更明白。