久しぶりのDelphiネタ。そしてBilinear補間処理の続き。
何年ぶりだろ?ようやくDelphi復帰宣言です。

今回はかなり時代遅れな感じが否めないMMXによる最適化です。
本当はSSEとかマルチスレッドとか使うべきなんだろうけど・・・

MMXって何だっけ?

もう世間では当たり前になっているので手短に済まします。

複数のデータを一挙に処理する事ができるCPUの拡張命令セットです。

整数演算を同時処理する為のもので、古くからあるので機能的には結構物足りないところも多いです。

まあ何だか分からなければ下記のWiki記事読んだりYahoo!でググってくださいw
もうそこらのPentium互換CPUは必ず搭載してて当たり前になっているので、特別説明することも無いでしょう。

MMX – Wikipedia

で、MMXを利用するにはIntelのお高いコンパイラとかを駆使すれば高級言語からでもいい感じになるのでしょうが、金かけたくないですし、手動チューニングの面白さを尊重したいと思います。
そこでアセンブラでのコード記述が必要となってきます。流石にプログラム全体をアセンブラで書くのは無謀過ぎるので、インラインアセンブラを利用します。

コードサンプル

インラインアセンブラはDelphiでも当然サポートされているので使ってみました。VisualStudioでC++などで同様にインラインアセンブラを使うときもほとんど同じコードを流用できるので、他の言語使いの方でも多少は参考になるかと思います。
ただ、x86アセンブラ初挑戦な上に、4年も前に組んだシロモノ・・・大分至らぬところはあると思います。
今回も前回の固定小数点数化を踏襲して整数演算を主体に処理しています。

多分これチラっと見ただけじゃあなんだかさっぱりだと思います。
アセンブラはデータの流れを追うのは結構大変です。デバッガでステップ実行しながらCPUのレジスタを見ると何をやっているのかわかると思われます。
しかしながらパック、アンパックという作業は複数のビットが一気に交換されるので混乱してしまうかもしれません。

結果的には普通にDelphiのコードを記述したときより圧倒的に早くなりました(10倍位)。PC環境が大幅に変わってしまって、以前の結果と比較が出来なくなってしまったので、具体的な数値は出せません。

なお、MMXはFPU(浮動小数点演算ユニット)とレジスタを共有するので、後片付け処理(emms命令)をしなければなりませんし(初期化は自動的に行われる)、MMX使用中は浮動小数点演算ができません。
なのでMMXの利用は今日においては非推奨なんですよね…

で、そもそもアセンブラ分からない人は参考書読め!とかしか言い様が無いです。CPUアーキテクチャを理解しなければならないので、一言で片付くレベルではありません。

MMXを初めとしたSIMDで最適化したロジックは実に奥深いです。やっぱプロのアセンブラ使いはこんな付け焼刃レベルじゃないんでしょうね。

次回はBicubicという補間アルゴリズムのサンプルを作ってみます!