SSE4とSuper Shuffle Engine
Radix-16とあわせて今回搭載された大きなものがSSE4とSuper Shuffle Engineである。実はこの両者は密接に関係しており、「SSE4は内部でSuper Shuffle Engineを利用しており、両者は密な関係にある。Radix-16はSSE4とは独立しているが」(Stephen L. Smith氏(Photo06))という返事が返ってきた。そのSuper Shuffle Engineは要するに1サイクルでデータの並べ替えを行うもので、直接x86命令とかSSE命令で利用するものではないが、逆にデータの並べ替えが内部で行われる命令に関しては、スループットを大幅に向上できるとしている。
さて、問題はSSE4だ。既にレポートで報じられた通り、PenrynはConroeに比べて全般的に性能が向上することが示されている。このあたりの解説は後で行うとして、取り上げておくべきはSSE4の効用である。DivX 6.6 Alphaは新たにSSE4を使ったAMS(Advanced Motion Search:Photo08)が追加されており、これを使うと大幅にMPEGのエンコードが高速化されることが示されている。実はこのベンチマークの際に、何故高速化されるかといったプレゼンテーションも見せられたのだが、これが非公開だとかで内容を紹介することが出来ない。ただ幸いな事に、Intel自身がSSE4を使ったMotion Estimationの高速化技法とか、テクニカルセッションにも"Tuning for Intel SSE4 for the 45nm Next Generation Intel Core Microarchitecture"なんてものがあり、ここでもほぼ同じ内容に触れているので、これらの資料を基にちょっと解説してみたい。
Photo08:DivX PROの設定画面。"Enhanced multithreading"のチェックはDivX Pro 6.5.1にもあるが、"SSE4.1 Advanced Motion Search(AMS)"は今回初登場。 |
まず前提知識をかいつまんで説明する。MPEGという動画形式が「動きベクトル」というものをベースに構成されているという話はご存知の方も多いだろう。端的に言えばMPEGは「前画像から現画像で、どう動いたかのベクトル」+「差分」から構成される。例えば図1の様に、青地に赤い丸が移動する図を考える。MPEGではまずこの画像を小さなブロックに分割した上で、各ブロックがどう移動したか、のベクトル(これを動きベクトルと呼ぶ)を算出して現画像を構成するという仕組みだ。ただ、常に動きベクトルを計算できるとは限らない。図2の様に赤い丸が高速で移動していると、もともとの位置の周囲をいくら探しても新しい赤丸の位置が見つからない。その場合、動きベクトルだけでは画像が再現できないので、「差分」の形で情報を追加してやる必要がある。
ここから、動きベクトルをいかに正確に求めるかがキーであることがわかる。差分が多くなるということは、MPEGのビットレートが増えてしまうことになるからだ。逆にビットレートが一定(例えばDVD片面単層ならトータルで4.7GBという容量が決まり、ここに2時間のMPEG映像+特典映像etc...を入れるとなると、最大でもビットレートは9Mbpsとかそれ以下に抑えないといけない。フレームレートが29.97fpsだとすると、720×480ピクセルの画面一枚に費やせるのは300Kbit=37.5KBでしかない)だとすると、差分データに高圧縮を掛けないといけなくなり、これは当然画質の劣化に繋がる。そこで動きベクトルを正確に求める事で差分データの絶対値を減らし、相対的に圧縮率を下げる工夫が必要になる。
ところがこの動きベクトルを求めるのが大変なのである。例えば図3のケースで、B2の位置にある前画像がどこに動くか、を算出する事を考えよう。基本的な考え方は「ブロック単位で前画像と現画像の引き算を行い、その差が一番小さい位置に移動したと考える」方法だ。図3の例で言えば、現画像では右に1ブロック分、赤い丸が移動しているので、位置としては(+7,0)というあたりが一番近い事になる。
ただ人間は目で見て「(+7,0)が一番差が少ない」と判断できるが、プログラムでこれはできないので、もう少し愚直な方法を取る。要するに、2つの画像の値をピクセル単位で引き算し、その差の総合計が一番少ない場所を求めるという方式だ。図4に、これを判りやすく示してみた。8×8ピクセルで構成されるあるブロック同士を比較する場合、要するにピクセル単位で引き算を64回行い、各々の絶対値を取った上で、最後にそれらを全部足しこむという作業である。これをSADs(Sum of Absolute Differences)と呼ぶが、このSADsの値を比較することで最終的にベクトルが算出できる。図3のケースで周囲のブロックのSADsを求めた結果が図5の様になった場合、SADs=30の(+7,0)の位置にベクトルが向いていると考えるのが妥当というわけだ。
さて、では何が問題かというと、ベクトルを正しく求めるためには、なるべく幅広い範囲を検索してSADsを求め、比較する必要があるというわけだ。ここまでで見たとおりSADsの計算そのものは非常に簡単(単なる減算と加算だ)だが、8×8ピクセルのSADsを1個求めるのに128回(絶対値にする作業まで数えると192回)もの演算が必要になる。この回数を減らす訳にはいかないので、次はいかに検索範囲を絞りつつ、効果的にベクトルを求めるかという事になる。例えば図6の総当り法(検索範囲を総なめして比較)なんていうのは愚直の極みであり、もっと効果的に判断する必要がある。
そこで、適当な足切り(例えばSADsが20未満になったら、そこがベクトルの位置と判断してそれ以上検索しない、とか)を利用すると共に、効果的な検索方法が色々編み出された。ステップサーチ(複数個おきに検索し、その中で一番小さなSADsの周辺を更に細かく検索する)とかスパイラルサーチ(近傍から徐々に検索することで、早いタイミングで足切りすることを狙う)、ダイアモンドサーチ(自分の上下左右1つだけを見て、その範囲で自分の位置が最小のSADsなら検索終了。さもなくば一番小さいSADsの周囲で更に検索を繰り返す)という3つの例を図6には示したが、他にも例えば斜め方向の検索を捨てて水平、垂直方向のみを検索するとか、更には1つ前のフレームの動きベクトルを元に予測するなんて方式もある。
実のところ、このあたりは各社のノウハウの塊であって、うかつな実装をすると直ぐにソフトウェア特許に引っかかりかねない部分でもある。また当然各方式とも得手・不得手があるわけで、「これで完璧」という検索方法は無い(というか、少なくとも筆者は知らない)。