FreeBSD で Python の time.clock() 関数をテストしているときに、常に同じ値 (約 0.156) を返すことに気付きました。
time.time() 関数は正常に動作しますが、解像度が少し高いものが必要です。
それがバインドされているC関数はありますか?代替の高解像度タイマーがある場合は?
私はプロファイリングを行っていないので、TimeIt モジュールはここでは適切ではありません。
FreeBSD で Python の time.clock() 関数をテストしているときに、常に同じ値 (約 0.156) を返すことに気付きました。
time.time() 関数は正常に動作しますが、解像度が少し高いものが必要です。
それがバインドされているC関数はありますか?代替の高解像度タイマーがある場合は?
私はプロファイリングを行っていないので、TimeIt モジュールはここでは適切ではありません。
Pythonのtime.clockはC関数clock(3)を呼び出します-BSDで動作man clock
するはずであることが確認されるはずなので、なぜ動作しないのかわかりません。たぶん、システムCライブラリから時計関数を直接呼び出すことでPythonポートのこの明らかなバグを回避することができますctypes
(ライブラリを.so / .dynlib / .dllとして、またはダイナミック共有ライブラリが呼び出されている場合) FreeBSD)?
time.timeは非常に高解像度であると想定されていますが、内部的にはgettimeofdayを呼び出します(とにかく、適切に構築されたPythonでは)-システムでどの解像度を観察しますか?
編集:wat.c
これは、この明らかなFreeBSDポートの問題を回避するためのBSD固有の拡張機能です(私のMacでのみテストされています-申し訳ありませんが、他のBSDフレーバーは手元にありません)。
#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'])],
)
URLが正しいので、ここでこれら2つのファイルを圧縮することもできます。
この拡張機能をビルドしてインストールするにはpython setup.py install
(Pythonのインストールに書き込む権限がある場合)、またはpython setup.py build_ext -i
ソースを配置したディレクトリにwat.soを書き込みます(その後、必要な場所に手動で移動しますが、最初にたとえば、python -c'import wat; print repr(wat.time())'
ビルドしたのと同じディレクトリで試してみてください)。
gettimeofday
FreeBSD(または!-を含む他のUnixフレーバー)でどのように機能するかを教えてください-Cコンパイラが文句を言うgettimeofday
場合は、2番目の引数を見たくないシステムを使用している可能性があります。それなしで試してください!- )。
time.clock()
UNIXシステムではCPU時間を返し、Windowsではプログラムが起動してからの実時間を返します。私の意見では、これは非常に残念な非対称性です。
の定義time.time()
は、Pythonソースのここ(Googleコード検索へのリンク)にあります。利用可能な最高解像度のタイマーを使用しているようです。これは、クイックグーグルによるとgettimeofday()
FreeBSDにもあり、マイクロ秒の精度クラスである必要があります。
ただし、本当に精度が必要な場合は、非常に高解像度のタイミング(おそらく、現在のマイクロ秒数を返す可能性があるもの)のために独自のCモジュールを作成することを検討できます。Pyrexを使用すると、Python拡張機能の記述が非常に簡単になり、SWIGがもう1つの一般的な選択肢になります。(実際には、タイマーの精度をマイクロ秒単位で削減したい場合は、純粋なC Python拡張機能として自分で記述してください。)Ctypesもオプションですが、おそらくかなり低速です。
頑張ってください!
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
これで問題が解決することを願っています。
time.clock()は、次の結果のdouble値を返すように実装されています。
((double)clock()) / CLOCKS_PER_SEC
なぜtime.time()の解像度が悪いと思いますか?gettimeofdayを使用します。これにより、非常に優れた解像度のハードウェアクロックが読み取られます。