昔書いた記事の供養です。2006/04/15加筆修正したもので、現在もこの情報が正しいかどうかは不明です。
Windows APIに、マルチメディアタイマーの最小分解能を指定するtimeBeginPeriod() という関数があります。使ってみたところ、こやつはかなり挙動不審です。本ページに気づいた点をまとめました。またタイマーと分解能について、解説を加筆いたしました。ご参考になれば幸いです。
※当方の環境はWindows 2000 SP4 with VC++ 6.0 SP5です。Windows 9x系はカーネル等が根本的に異なるため、この限りではありません。
Windowsには2種類のタイマーがあります。
です。同様に、システム時刻の取得にもいくつかの手法があります。
などがあります。カウンタの値が現在時刻など特定の意味を持つとは限らず、差分として用いることにだけ意味があるカウンタ(高分解能カウンタがそう)もあります。自分のシステムで、現在時刻と一致したからといって他のシステムでも同じとは限りません。ここではそれぞれのAPIの詳細を述べることはしません。
先ほど述べたtimeGetTime() APIで得られる値はms単位ですが、分解能を変更することができます。分解能というのはなんでしょうか?もう少し説明しましょう。アナログ(デジタルでも構いませんが)時計を思い浮かべてください。
このとき分解能は時計の針が一度にどれだけ進むかに相当します。分解能を細かくすると、1秒に一度1/60度だけ進む律儀な時計になり、分解能を荒くすると、5秒に一度1/12(= 5/60) 度だけ進むルーズな時計になります。
分解能の適正な値は用途によって異なります。普段の生活では腕時計(1秒の分解能)で十分ですが、短距離走のタイムを計るときに腕時計は使いません。短距離走は1秒以下のタイムで勝負が決しますが、1秒以下の値を指せない腕時計では秒以下のタイムが計れないからです。用途に合った分解能を持つ時計、例えばストップウォッチ(分解能10ms程度)を用います。
同様にコンピュータのタイマーも用途に合った分解能を用います。常に最も分解能の細かいカウンタを用いても良いですが、ストップウォッチが高価なように高分解能のカウンタには制約がある場合があります。例えばWindowsの高分解能カウンターは非常に大きな値を返すため、少し処理が複雑です。適材適所が良いでしょう。
分解能が荒いとゲーム製作で非常に難儀します。60fpsにおいて、1フレームが消費する時間は16.67msです。Windows 2000では初期値の分解能が10msのため、16ms待ちたくてSleep(16) としても20ms待ってしまいます。Sleep(n) がきちんとn[ms] で返ってこなければ60fpsより低い、あるいは高いフレーム数になってしまいます。
高分解能カウンタをスピンウェイト(全力でポーリングして監視する方法)は最も正確ですが、ゲームの処理を終えて時間が余ったとしても、時間の経過を待つ作業でCPU資源を浪費するため、省電力などの観点から見てもあまりよろしくありません。時間が過ぎるのを待つだけの処理なのですから、Sleep() 関数を呼び他のプロセスに実行権を譲りCPU負荷を減らすのが道理です。
冒頭で述べたとおりtimeGetTime() の分解能は最大で1msですが、Windows 2000では分解能の初期値は10msです。変更するにはtimeBeginPeriod() APIを用います。timeBeginPeriod() を呼び出せば、当然分解能が変更されます。
実験していると不思議なことが2つあって、1つ目はtimeBeginPeriod() を呼び出す前から、分解能の初期値が1msになっていることで、2つ目は副スレッドからtimeBeginPeriod() を呼び出してもtimeBeginPeriod() が機能していないようにみえることです。
調べるとMSN Messenger 6.1が起動していると最小分解能が変化することがわかりました。あるプロセスでtimeBeginPeriod() を呼ぶと他のプロセスに影響するのではないでしょうか?
自作のtimeBeginPeriod() を呼ぶプログラムで実験すると、timeBeginPeriod() は最も細かい分解能を「システム全体に」適用することがわかります。
あるプロセスがtimeBeginPeriod() を呼び出し最小分解能を指定した後、他のプロセスがtimeBeginPeriod() を使用すると最小分解能はその値に上書きされます。後に起動したプロセスが終了しても最小分解能は元に戻りません。最小分解能を1msに設定して、その後5msに設定しても分解能が変化しません。
例外として10ms以上の値を指定すると、他のプロセスに最小分解能を上書きされなくなります。しかし最小分解能は10ms固定になります。
もしtimeEndPeriod() を呼ばずに終了する「行儀の悪い」プログラムがあったときは、プロセスが終了すればtimeEndPeriod() を呼んだときと同様に分解能の変更が無効化されます。
全くtimeBeginPeriod() を呼び出さないプロセスの場合は、他プロセスがtimeBeginPeriod() の呼び出しの影響を受け分解能が変化しますが、timeBeginPeriod() 呼んでいた他のプロセスが全て終了すると初期値の10msに戻ります。
プロセスに複数のスレッドがある場合、メインスレッドからtimeBeginPeriod() を呼ばないと効果がないようです。関数の帰り値は分解能の変更に成功したと報告しますが、最小分解能は変化しません。
ちなみにこの現象は、後述するプログラムでは確認できません。ごめんなさい。
同一プロセス、同一スレッド内でtimeEndPeriod() を呼び出した場合「だけ」最小分解能の指定が解除されます。この条件下ではネストした指定も可能です。例えばbegin(3) begin(2) begin(1) end(2) end(1) とすると、内側にある1msの設定と2msの設定が解除されて、3msの設定に戻ります。
しかし他にtimeBeginPeriod() を利用するプロセスが1つでも存在すると、timeEndPeriod() は機能しません。
最小分解能が変化すると困る場合は、指定できる最も細かい分解能(timeGetDevCaps() APIで取得できます)以外の値は指定しないほうが良いでしょう。途中で他のプロセスに影響されて変わってしまうかもしれません。
脱線話ですが、Windows上で得られる最高の分解能が気になる方もいるかと思います。
おそらくWindows 2000において最も細かい分解能を持つのは高分解能カウンタです。周波数は約3.5MHzで、分解能に直せば300ns程度です。ただしここまで細かい間隔だと、CPUが十分に速くないと取りこぼしてしまいそうです。
近年のOSはカーネルが任意の地点で実行権を取り上げて他のプロセスに渡せる(プリエンプティブ)ため、Windowsは正確なリアルタイム処理には向きません。UNIXなども同様の理由でリアルタイム処理には用いません。しかし最近は組み込み機器向けにリアルタイム処理に対応したLinuxが登場しています。
それとですね……書いた後で気づきましたが、PSX Alternative! にも当ページと同様の実験が紹介されていました。実験方法は違います(向こうはSleep(1) にかかる時間を見ている)が、やはり同様にtimeBeginPeriod() はおかしいと指摘していました。
検証方法と用いたプログラムは以下の通りです。
ビジーループしてtimeGetTime() で取得できるカウンターの差分が最小分解能と一致しているか確かめます。最小分解能は高々1msであること、ループに1ms以上かからないことを仮定しています。
// mmtimer.c
#include <stdio.h>
#include <windows.h>
int main()
{
unsigned long mmt, mmt_b;
timeBeginPeriod(1);
mmt = mmt_b = 0;
while (true) {
mmt = timeGetTime();
if (mmt != mmt_b)
printf("%d ms\n", mmt - mmt_b);
mmt_b = mmt;
}
timeEndPeriod(1);
return 0;
}
結果は以下のとおりです。
%./mmtimer↓ ・ ・ 1 ms↓ 1 ms↓ 1 ms↓ 1 ms↓ 1 ms↓ ・ ・
値の変化が1msであることがわかると思います。
昔書いたメモを発掘したので、これも供養しておきます。
LARGE_INTEGER freq;
LARGE_INTEGER st, ed;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&st);
Sleep(100);
QueryPerformanceCounter(&ed);
簡単なAPIではありますが、動作チェックはしていませんのでご注意ください。
立命(高校)のみんなと食事&カラオケ。少なくとも半年空いてるので、毎回すごーく久しぶりに会った気がします。高校卒業からだいぶ経つけど、みんな良い意味で変わってないよ。ずっとこうやって集まりたいね。
昨日の日記で泣くとか泣かないとか書いて思い出した。私はけっこう涙もろくて、特に一人で感動モノ見ると泣けて仕方ないです。仕方なさ過ぎて、頬を涙が伝います。
映画なんかでもOKですが、短い文章の方が良いかも。これって普段のイメージ(って自分じゃわからんけど)からすると当然?意外?
母方の祖母のお見舞いに行きました。ペースメーカーを埋めると聞いていて不安でしたが、結局埋めないそうです。微妙な状態なんでしょうけど、医者が要らんって言うなら要らんのでしょう。
テレビでSWING GIRLSをやっていたので、鑑賞。おかっぱの人(パーカッション)がすげー。ジャズってサックスがカッコいいねえ。
実家でボーっとしててと、ふと思った。働き始めるとまとまった休みはないから、今年の冬って北海道に長期間帰省できる最後の機会じゃね?今年の冬は感慨深いものになるはず……ってのはちと大げさか?
別れは悲しいものですが、私は死別でもなければあまり気にならないかも。卒業式とかお別れ会で全く泣かないタイプです。
母と妹が出かけたので、父方のばーさまと一緒に留守番でした。昼頃、ばーさまが財布がないとか言って、家捜しを始め、しまいには父(つまりばーさまの息子)に盗られたとか言い始める。なんだかな…。
ついに半年分のジャンプを全部読み終えたぞお。長かった。
母はコンピュータ関連の話に理解があるので、ルータや無線LAN環境の購入許可がさらっと得られました。おかげで実家のネットワーク環境がかなり充実しております。
今日も、妹の転入届を出しに札幌市北区役所へ行くついでに、ベスト電器で無線LANルータを買ってきました。これできしめんみたいなLANケーブルとおさらばです。
さらに聞いたらADSLを1.5Mbpsタイプから8Mbpsタイプに(4〜5Mbpsしか出ないかも?)する許可も得られたのですが、契約書が見つからなくて契約変更できず。それほど必要性も感じないからまあいいか。
ゲド戦記を見に行きました。小難しいし、急展開すぎてよくわかんないなあ…。見に行く前に期待しすぎたのかなあ…。
ボクシングWBAライトフライ級、あの判定は素人目にも贔屓しすぎに映りました。でも負けちゃうとTBSが既に組んである大晦日の防衛戦とか、地元でやる優勝パレードがパアになりますから、大人の事情で勝たせないといかんのよね。
マスコミのいい食い物ってやつでしょうか。願わくば次の防衛戦でボッコボコにされて使い捨て、なんてことにならないことを。
北海道に帰省しました。ちょっとミスって6,000円ほど損しました。
昨日、チケットを二回予約してしまったことに気づきました。それも単なる予約じゃなくて、予約時にメールアドレスを間違って入力したせいで、予約確認メールが来ておらず、カードで支払い処理を済ませてしまった状態です。ひじょーに面倒な状態です。
全部お伝えするとクドいので、以下、今日に至るまでの流れ。
解約したい
→ 解約には予約番号が必要
→ 予約番号は予約確認メールに書いてある
→ そもそもメールが来てねー!
→ そんなときはサポートデスク
→ 全然繋がりません、本当にありがとうございました
→ 諦めて寝る
→ 本日、空港に行って聞く
→ 「その便は、もう飛びましたね」
→ 糸冬 了
「もう飛んじゃった」と言われたときは、さ、3万円がー!!とブルー入ったんですが、飛行機って乗り過ごしてもキャンセルできるそうな。手数料は6,000円(行き先により異なる)と高いけど、3万よりはマシ。まったくつまらんミスで痛い目に遭ったよ。
ドコモミーティング。10月の目標に向け作業はいよいよ佳境に入るっぽい。頑張る。
TX秋葉原駅で1周年のイベントをやっていました。バックアップは国土地理院や産総研で、キログラム原器のレプリカとか、立体地図とか、アザラシロボット「パロ」が居ました。
テーブルに鎮座していたパロその1の写真です。クリックで拡大します。目が据わってて奇声を発しながらうねうね動く。カワイイやらカワイクないやら、びみょー…。
ちなみに電池切れで、コンセント咥えてるパロその2も居ました。これもクリックで拡大します。充電中はピクリともせず、どうみても人工呼吸器付きの瀕死アザラシです。
全然脈絡無いですが、明日から7日まで北海道に里帰りします。帰省すると食事の誘いが多いように感じるのは、きっと気のせいだ。
最近お出かけが多くて研究のテンションは低め。夜中、明日に向けて資料を作りながら、うとうとー……ああ、もう朝だ。
このサイトにコメント機能をつけられないか、って言われてから考えてたんだけど、やっぱり今のままじゃ無理。何らかのシステムに移行するとしても、今まで書いた文をどうするやら。先の長そう(今後もしばらくメンテされる)で有名な日記システムっていうと何じゃろなー??
ちなみに自分で書くのも一つの勉強だけど、ネットで公開するだけにバグとかセキュリティホールで他人に迷惑かけるリスクを考えると、勇気が要るね。
園芸の皆さんとひたちなか市の国営ひたち海浜公園へ遊びに行きました。ここは県内でも数カ所しかない、パターゴルフやディスクゴルフを体験できる場所だそうです。
パターゴルフは名前そのままで、パターを使ってミニコースを回っていくものです。初めての割に結構上手くいったように思います。
ディスクゴルフはフリスビーをゴールに投げ入れるゲームです。森と草原のコースがありましたが、Rock in Japan Festivalの施設工事のため、草原コースが使えませんでした。残念。
願わくばもう少し涼しい時期に行きたいですね。季節としては秋か晩夏あたりで。
運動の後は風呂!っつーことで常陸太田市の梅里ガーデンアクアビラに行きました。湯船に浸かっていたらやたら汗が口に入ってくるから、熱くもないのにおかしいなー?とか思ってたら、単に温泉がナトリウム泉なだけだった。そらしょっぱいよな。
そのあとカラオケに行って6人(山下さん歌わないから実質5人)で5時間も歌った…。非常に疲れました。
エンジンオイル交換に行ってきました。オイル交換って簡単そうですが「オイルの缶&4Lの廃油処理が面倒だ。」とか「下手に持ち上げて作業中に車が落ちたら死んじゃう。」など、やりたくない要素満載です。
それに加えて新筑波モータースは、工賃サービスなので、自分でやるメリットはゼロ。
オイルといえば、昔はリッター2000円とか3000円のエンジンオイルに目を引かれたもんです。でも私はちょっとしたオイルの質の違いがわかるほど通でもないですし、街乗りしかしないので、単なる贅沢になってしまいます。お財布にも車にも安いオイルが一番です。
ドラミの声優が千秋に変わるらしい。こうしてどんどんドラえもんが暴走していく、ショックだなあ。
日光旅行3日目。
ポンテ(ガラス工房)で、ガラス吹きを体験しました。ガラスと聞くと難しそうですが、ほとんど職人さんが作ってくれますのでまず失敗しません。頑張って吹いたら「そんなに強く吹かなくて良いですよ」って言われた。ガラスって意外に軽く膨らむんですね。
作品は後ほど宅配便で届くそうです。
霧降高原有料道路(930円、意外と高い)で、霧降高原を駆け上ります。途中のキスゲ平でリフトに乗り、ハイキングして駐車場まで戻りました。雲が厚くてあまり景色が良くなかったのが残念です。
有料道路の終点にある大笹牧場で一休みして、復路は東側の一般道路(けっこう細いので注意)で下って、一気に帰宅しました。
大笹牧場の伊藤園の自販機がお茶を強調しすぎ…つーか全部お茶かよ!!(写真、クリックで拡大)中谷美紀の「これがお茶」というポスターもこの自販機なら説得力がある。
いろは坂を二往復(実は1日目も登った)したわりに、燃費は11km/Lと意外に好調でした。最近遠出続きで、結構走ったし、土曜に備えて明日はオイル交換かな。
日光旅行2日目。
ペンションで朝食、いろは坂を登って中禅寺湖で遊覧船に乗りました。景色が最高に良くて、この季節なのに涼しいのが最高!
昼を定食屋で済ませて、華厳の滝に向かいました。エレベータ(有料、530円)に乗って滝の近くまで。連日の雨の影響で増水しているらしく、観瀑台まで激しい水しぶきが襲ってきます。おかげで服も頭もびしょ濡れです…夏だからこれもまたいいかな。写真は華厳の滝です。クリックで拡大します。
その後、湖畔の土産を見て回り、風呂は日光アストリアホテルの温泉(湯本温泉かけ流し、硫黄泉質)に日帰り入浴しました。温泉もさることながら、ホテルの周りに広がる静寂が実に良い雰囲気でした。今度はこのホテルに泊まってみたい…。
ペンションに戻って夕ご飯をいただいて、明日のロングドライブに備えて就寝しました。
ああ、そうそう、このペンションは以前園芸で来たヴィラ・リバージュのすぐそばです。このあたりが、山の上へも下へも一番アクセスが良いですよね。
日光旅行1日目。
まずは車で日光まで。宇都宮がやや混んでいましたが、日光宇都宮道路(宇都宮IC〜日光IC 450円)に乗ってしまえばあとはスイスイ日光へ。
とりあえずこの旅行の目的(大下さんの)である、日光山輪王寺、日光東照宮、二荒山神社、輪王寺大猷院の順に、全部制覇しました。
料金が1,000円(二社一寺拝観券)です。東照宮の眠り猫(520円)と宝物館(500円)は別料金です。他も何かあったような気がするけど…まあいいや。写真はクリックで拡大します。
日光植物園に行きました。植物名を記したプレートが地面のあちこちに刺してあって、名前を調べながら散策できるようになっています。ぐるーっと回って一時間くらいの散歩道です。
公式ページにあるとおり東京大学の付属施設ですが、ろくに調べずに行ったために、料金払ってパンフレット貰ってから「へー?東大だったの!?」なんてさわいでいました。
夕方、サンシャイン・ブルーバード・インにチェックインしました。お得な2泊3食プランなので、今晩の夕ご飯はありません(3食 =1日目なし、2日目の朝食、夕食、3日目の朝食)。飯屋を探しに出ても、みんな18時には閉店、どこも開いていない。
なんとか遅くまで開いてるお好み焼き屋さんを見つけて入りました。店内で近所のおばさんと思しき人と、店主のばーちゃんとの会話が、これぞ田舎の近所づきあいって感じで和みまくった。
夜はペンションの露天風呂に浸かりました。温泉ではないけれどこれは良いわー。
盛りだくさんの一日でした。
< | 2006 | > | ||||
<< | < | 08 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
- | - | 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | - | - |
合計:
本日: