現在のシステム時刻をマイクロ秒の分解能で知りたい。 date +%s
は、エポック(1-1-1970)以降の時間を秒単位で返します。マイクロ秒単位で時間を取得するにはどうすればよいですか。この値のクエリにはどのくらいの遅延がありますか?遅延とは、時間t
秒でクエリを実行すると、値t + t'
とは t'
?
私の使用例:複数のRaspberry Piを使用してビデオをシミュレーションで録画しています。次に、ビデオの各フレームにタイムスタンプを付けて、それらを整列できるようにします。現在、タイムスタンプには、ブート時間(ブートからの時間)を使用しています。起動時間は正確ですが、Raspberry Piごとに異なります。すべてのPiをNTPサーバーに構成したので、すべて同じシステム時間になります。基本的に、ブート時間ではなくシステム時間のタイムスタンプが必要です。どうすればよいですか?
date +%s%N
エポック以降のナノ秒を示します。マイクロ秒を取得するには、評価を実行します
expr `date +%s%N` / 1000
コマンド(date
コマンドを含む)の実行に少なくとも数百マイクロ秒かかることを考えると、シェルスクリプトでこの種の精度を要求することはあまり意味がありません。
特に、実際にdate
コマンドを使用して、この種の精度でコマンドの実行を計時することはできません。
そのためには、time
コマンドまたはキーワードを使用するのが最適です。
いくつかの実装では、フォーマットを変更してelapsed時間を1秒未満の精度でのみ提供できます。
$ bash -c 'TIMEFORMAT=%3R; time date +%s'
1432210052
0.001
$ ksh -c 'TIMEFORMAT=%3R; time date +%s'
1432210094
0.001
$ zsh -c 'TIMEFMT=%*E; time date +%s'
1432210123
0.001
さまざまなシェルには、時間を確保するためのさまざまな組み込みの(遅延が最小限の)方法があります。
ksh93
とzsh
には、型をfloatに変更した場合にサブセカンド精度を提供する$SECONDS
変数があります。
$ zsh -c 'typeset -F SECONDS=0; date; echo "$SECONDS"'
Thu 21 May 13:09:37 BST 2015
0.0012110000
$ ksh -c 'typeset -F SECONDS=0; date; echo "$SECONDS"'
Thu 21 May 13:09:42 BST 2015
0.0010249615
zsh
には、$EPOCHREALTIME
特殊変数があります(zsh/datetime
モジュールで使用可能):
$ zsh -c 'zmodload zsh/datetime; echo $EPOCHREALTIME; date; echo $EPOCHREALTIME'
1432210318.7319943905
Thu 21 May 13:11:58 BST 2015
1432210318.7333047390
ksh93
およびbash
の新しいバージョンは、printf
組み込みの%(format)T
形式をサポートしていますが、bash
は%N
をサポートしていません(GNU拡張子)、そしてnowの表現方法について意見が異なります。
$ ksh -c 'printf "%(%s.%N)T\n" now;printf "%(%s.%N)T\n" now'
1432210726.203840000
1432210726.204068000
(ご覧のとおり、組み込みコマンドの2つの呼び出しの間に、228マイクロ秒がまだ経過しています)。
あなたが言ったように_date +%s
_はエポックからの秒数を返します。そう、
_date +%s%N
_は、秒と現在のナノ秒を返します。
_date +%s%N
_の値を1000で割ると、マイクロ秒単位になります。
echo $(($(date +%s%N)/1000))
すべてのRaspberry PiをlocalNTPサーバーに設定している場合、つまり、 NTP LAN上のサーバー。これらの同期は、ビデオフレームのタイムスタンプタスクに適しています。
BashとPythonは、システム時間を取得するためにシステム関数呼び出しを行う必要があります。Bashを使用してその呼び出しを行うことには利点がありません。両方Python&Bashスクリプトはインタプリタ言語であり、スクリプトの実行に伴う時間オーバーヘッドは、通常、コンパイルされた言語OTOHよりも大きくなりますPythonスクリプトはPython実行形式は、通常、コンパイルの形式がないBashスクリプトよりも効率的です。ビデオフレームのタイムスタンプのこの特定のケースでは、Pythonバッシュで書かれたものよりも正確です。
ただし、マルチタスクOSでこのようなことを行うと、CPUがジョブの実行と処理を切り替えているため、予測できないさまざまな遅延が発生します他のタスクの束。したがって、他のタスクを最小限に抑え、タイムスタンプスクリプトを高い優先度で実行して、他のタスクの影響を減らすように最善を尽くしてください。カーネルがHDの読み取りまたは書き込みの最中にシステムコールを実行して時間を取得することは、おそらくお勧めできません。 :)
タイトなループでタイムスタンプを行う場合、各タイムスタンプ間の時間差を追跡できます。そして、その差が大きくなりすぎたり、変化が大きすぎたりする場合、スクリプトは現在のタイムスタンプが不適切であると判断できます。 OTOH、フレームレートが50フレーム/秒、つまり20ミリ秒/フレームであると仮定すると、ミリ秒の精度はこのタスクにはおそらく十分すぎるほどです。
FWIW、ここに少しPython 2GHzマシンで実行しており、通常の優先度で通常のタスク負荷(VLCでの音楽のダウンロードと再生を含む))を実行しています。
>>> from time import time as tf
>>> t=[tf()for _ in range(9)];['%0.3f'%(1E6*(u-v))for u,v in Zip(t[1:],t)]
['2.146', '0.954', '1.907', '1.192', '1.907', '1.907', '1.192', '0.954']
ご覧のとおり、マイクロ秒レベルの変動はそれほど悪くありません。
マイクロ秒の解像度は必要ありません。ミリ秒は1秒あたり約20〜60フレームで実行されます。
すべてのPiのシステム時間をNTPサーバーから1回取得すると、内部クロックごとに約100 ppm(part per 100万)。200秒後、最大20ミリ秒の差が出る可能性があります。
NTPサーバーから時間を取得した直後に、すべてのPiがサブミリ秒の精度で整列することはないと思います。
もちろん、各Piのフレームレートにも約100 ppmの個別の誤差があります。
私はすべてのPiの中央クロックソースを考えます。
頑張ってください、あなたはそれを必要とするでしょう。