• コンパイルされたマシン語とCPUの挙動(実行サイクル数)まで意識した高速化プログラミング

コンパイルされたマシン語とCPUの挙動(実行サイクル数)まで意識した高速化プログラミング

2016年6月21日 13:00
  • 神楽坂ショールーム
  • 資料請求・お問い合わせ
  • 概算見積もり

ネオレックスの技術者には、アセンブラやマシン語にも精通し、CPUの実際の挙動まで意識をしながらプログラムを書いている人たちがいます。

例えば、コンピューターに計算などのある処理をさせようとするとき、それを実現するためのプログラムの書き方(コーディング)は何通りもあります。

それらは同じ結果が得られるわけですが、CPUが実際に処理する分量=動作速度がかなり違ってくる場合があります。

以下のお題について考えてみたいと思います。

お題「変数aの値を15倍して変数bに格納する」

実は「15倍する」という計算は、コンピュータは元々それほど得意ではありません。
でも「16倍する」という計算は得意なんです。

私たちは普段、数を10進数で扱いますが、コンピュータは数を2進数で持ちます。
10進数では、1を、

  • 10倍すると「10」に、
  • 100倍すると「100」に、
  • 1000倍すると「1000」に、

となります。
計算するというより、桁をずらして後ろに0を補うだけですね。

同じように、2進数では、1を、

  • 2倍すると「10」に、
  • 4倍すると「100」に、
  • 8倍すると「1000」に、
  • 16倍すると「10000」に、

という風に、2の累乗の計算は桁をずらして後ろに0を補うだけということになりますので、コンピュータはこういう計算が得意なのです。

例えば「a = 5」とすると、2進数では「101」ですので、16倍は後ろに0を4つ補って「1010000」となります。 お題は15倍ですので、この結果からaを1つ分引いて15倍にします。

私たちが暗算する時に「8 × 999」を「8 × 1000から8を引く」とすると簡単になるのと同じ考え方です。

動作速度を比較

このコーディングの違いが具体的にどの程度の差になるかを見るために、C言語で書いたコードがどのようにコンパイル(変換)されるかを表にしてみました。C言語、アセンブリ言語になじみのない方は「実行サイクル」だけを見ていただければと思います。実行サイクルは各行の命令を実行するため掛かる時間を表しています。

共通条件

プログラムの開始番地 変数aのメモリ番地 変数bのメモリ番地
0x00000100 0x10203040 0x10203044

お題をそのままコーディングした場合
「お題をそのままコーディングした場合」の比較表

16倍してからaを引く場合
「16倍してからaを引く場合」の比較表

マシン語のダンプリスト比較
マシン語のダンプリスト比較表 マシン語のダンプリスト比較表

プログラムのサイズは偶然どちらも17byteと同じですが、実行速度は平均で2.4倍も速くなることが期待できます。

このように、同じ処理であってもプログラムの書き方次第で動作速度が大幅に違ってくることがあるため、コンパイルされたプログラムがどのようなマシン語となり、その処理が何サイクル程度になるのかというCPUの実際の挙動への意識が時に大変重要になります。

最近は、強力な最適化機能を持ち、こうした配慮があまり必要ないコンパイラも出てきています。また、一部の処理の実行サイクルを大幅に短縮したCPUも出てきています。

しかし、プログラムが最終的にマシン語となり、そのマシン語がCPUによって処理されるという原理には変化はありません。

マシン語やCPUへの配慮により、より良いシステムを開発することができる。あるいは、こうした配慮がなければ、思わぬパフォーマンスダウンや不具合に見舞われることがある。

私たちネオレックスは、このような思想を持って毎日のバイバイ タイムカードの開発に取り組んでいます。

今回の記事は、分かりやすさを優先し、インテルi386プロセッサとその当時のコンパイラという少し古いものの挙動をベースにまとめています。
本文中にあるように、最近のコンパイラやCPUは以前に比べて高性能になっています。例えば「b = a * 15;」とコーディングしても自動的に「b = (a << 4) - a;」と読み替えるコンパイラや、本記事で実行サイクルが9~38となっている「mul ebx」を2~3サイクルで実行できるCPUが登場しています。
このため、CPUやコンパイラの特性や挙動を理解していないと、動作速度を上げるつもりの工夫が逆に動作速度を遅くしてしまう結果となることもあり、注意が必要です。

(畠山 裕)

  • バイバイ タイムカード日記

このページの先頭へ