2018年10月12日

CPUクロックを測る方法がちょっと間違ってたなぁ

昔、いじくるつくーるを作成していた際、利用者からの問合せの時にPC環境情報を効率よく収集してもらうための「環境情報の表示」(CCPU)という機能を付けていました。

このこともあり、「いじくるつくーる」は、「環境情報も表示できるカスタマイズツール」なんて言われたこともありました。
表示できる環境情報の中には、CPUのクロック周波数を表示する機能もありまして、先日、ちょっと懐かしくなって、改めてどんなことをやっていたのか振り返ってみようと思ったのですが、衝撃の事実が分かりました。

ちょっとやり方、間違ってたかも。

まぁ、CPUのクロック周波数が判明している色々な環境で試し、問題が露呈していなかったわけなので、現実的な問題とはならなかったみたいですけどね。今も当時みたいに頻繁にメンテナンスをしていたなら、慌てて直していたろうなぁ。


CPUのクロック周波数の調査は、Intelのx86系のCPUが持つ「RDTSC」(Read TimeStamp Counter)という命令を使っています。「環境情報の表示」(CCPU)で間違っていた箇所は、次の箇所でした。

  1. CPUには、動作効率化のため、命令の順序を入れ替えて実行する「アウト オブ オーダー実行」という機構がある。これにより、RDTSC周辺の実行順序が入れ替わると問題が生じることになる。そのため、意図通りの命令実行順とするため、直前にCPUID命令を入れなければならない。
  2. RDTSC命令の結果は、EAXレジスタとEDXレジスタに結果値を格納する。これは、C言語で64bit変数を戻り値とする場合のレジスタと一致する。よって、RDTSC命令の結果をがんばって組み立てて64bit変数にしてreturnに渡す必要はない。
もしかしたら、上記2の間違えを犯していたおかげで命令順が複雑になり、上記1の問題が生じなかった可能性もあるのかもしれないと思うし、上記2の間違えを犯していたとしてもVisual C++の高度な最適化機構により64bit変数の組み立てとreturnへの引き渡しは削除されていたのかもしれない。

だから、表面上問題は発生していないように見えていたのかもしれない。
将来的にコンパイラが変わったら、問題が発生していたのかもしれない。

いやぁ、怖いですね。
「アウト オブ オーダー実行」については、知識としては知っていましたが、情報処理試験で頻出するパイプライン実行と比べると「まだまだ他人事」くらいのことと考えていたので、全然身に染みて分かっていませんでした。

こういうコンピュータの世界って、情報処理試験のために習う知識が、実際に自分が使っているコンピュータの挙動が結び付かずに覚えていることが、結構ありますよね。

例えば、「Direct Memory Access」。
CPUを介さずに、メモリ-メモリ間や、ディスク-メモリ間で、直接データをやりとりする方式のことを指すんですが、これが、自作PC作成の時に散々出てきた「UltraDMA」という用語と、頭の中で結びついてなかった。

それから「シリアル信号」。
シリアル通信では1ビットずつデータを流し、パラレル通信では複数ビットずつデータを流す。
パラレル通信の方が複数ビットまとめて転送できる分、有利のはずだが、超高速通信時代ではノイズやケーブル内の不純物、ケーブル長の変化のせいで、当時到着を期待できなくなったため、シリアル通信が主流になってきている。
で、最近、スマホの充電等で大活躍の「USB」。PC等母艦機との通信の際は、シリアル通信するのか? パラレル通信するのか?

「USB」は「Universal Serial Bus」の略であり、2文字目のSは「シリアル」の略なわけだから、これはシリアル通信。
でも、頭の中でサッと結びついていなかったりする。

ちなみに、USBがシリアルかパラレルかを問う質問は、基本情報処理試験か第二種情報処理試験の試験でも出ていたような気がする。だいぶ前だけど。


posted by ayacy at 00:00 | Comment(0) | TrackBack(0) | プログラミング