[[PageNavi(NavigationList)]]
==== SSE対応のC標準関数を使う ====
インテル コンパイラーではabsやsin、cos、tan、logといった各種数値演算関数や、strcpy、strlen、memcpy、memsetといった文字列/メモリアクセス関数といった、C標準ライブラリ関数の一部についても組み込み関数として用意されている。これらの組み込み関数については、「/Oi」(Windows版)もしくは「-fbuiltin」(Linux、Mac OS X版)オプション付きでコンパイルを行うことで利用できる。
たとえばC標準ライブラリ関数には切り上げ/切り捨て処理を行う関数としてceilおよびfloorという関数が用意されているのだが、インテル コンパイラーで組み込み関数を有効にし、かつSSE4向けの最適化を行うように設定すると、これらの関数がSSE4で追加された浮動小数点の丸め演算命令(ROUND*命令)を利用するものに置き換わり、高速に実行できるようになる。
次の'''リスト5'''のようなコードをコンパイルオプションを変えてコンパイルし、その実行速度の違いを検証したところ、'''表7'''のような結果となった(テスト環境は先ほどと同様、'''表4'''のとおり)。組み込み関数を使用してSSE4.1および4.2向けの最適化を行った場合、floorおよびceilの実行時間がそれぞれ半分程度にまで短縮されていることが分かる。
{{{ html
<h6>表7 floorおよびceil関数の実行時間比較</h6>
<table class="wikitable" border="1">
<tr><th rowspan="2">SSEの指定</th><th colspan="2">実行時間(秒)</th></tr>
<tr><td>floor</td><td>ceil</td></tr>
<tr><td>指定なし</td><td>0.262</td><td>0.172</td></tr>
<tr><td>SSE2</td><td>0.260</td><td>0.173</td></tr>
<tr><td>SSE3</td><td>0.258</td><td>0.171</td></tr>
<tr><td>SSSE3</td><td>0.258</td><td>0.174</td></tr>
<tr><td>SSE4.1</td><td>0.156</td><td>0.072</td></tr>
<tr><td>SSE4.2</td><td>0.156</td><td>0.072</td></tr>
</table>
}}}
'''リスト5 ceil関数の処理速度測定コード'''
{{{
float* A;
float* B;
int n;
int dim = 1024*1024*100;
LARGE_INTEGER freq, begin, end;
srand(1111);
for( n = 0; n dim; n++ ) {
A[n] = (float)rand() / (float)(RAND_MAX);
}
QueryPerformanceFrequency(freq );
QueryPerformanceCounter(begin );
for( i = 0; i dim; i++ ) {
B[i] = ceil(A[i]);
}
QueryPerformanceCounter(end );
printf( "ceil: %f sec.\n", ( (double)(end.QuadPart - begin.QuadPart) / (double)freq.QuadPart ));
QueryPerformanceFrequency(freq );
QueryPerformanceCounter(begin );
for( i = 0; i dim; i++ ) {
B[i] = floor(A[i]);
}
QueryPerformanceCounter(end );
printf( "floor: %f sec.\n", ( (double)(end.QuadPart - begin.QuadPart) / (double)freq.QuadPart ));
}}}
==== SSEに対応するインテル インテグレーテッド・パフォーマンス・プリミティブ(IPP) ====
そのほか、インテル コンパイラー 11.1に付属するライブラリ「インテル インテグレーテッド・パフォーマンス・プリミティブ(IPP)」についても、AtomおよびCore i7対応が行われている。といっても、プログラムのコンパイル時やリンク時に特に意識する必要はなく、リンクしたプログラムの実行時にCPUが判別され、対応する関数やコードが自動的に実行される。また、IPPのランタイムライブラリDLLについても、x86汎用のものに加えて特定のCPU向けに最適化されたものが用意されている。
たとえば、IPPのサンプルとしてインテルが提供している、H.264エンコーダ(「umc_h264_dec_con.exe」)で比較してみると、SSEを利用しないx86汎用のライブラリを使用した場合と、SSE4向けのライブラリを使用した場合とで10倍以上パフォーマンスが異なるという結果となった('''表8''')。テストに使用した環境は先ほどと同様、'''表4'''のとおりである。
{{{ html
<h6>表8 SSEを利用することによるH.264エンコーダの処理時間の違い</h6>
<table class="wikitable" border="1">
<tr><th>使用するライブラリ</th><th>エンコード時間(秒)</th></tr>
<tr><td>汎用版</td><td>73</td></tr>
<tr><td>SSE4向け最適化版</td><td>6.73</td></tr>
</table>
}}}
このサンプルプログラムは米インテルのWebサイトからダウンロードできるもので、詳細については 『[http://sourceforge.jp/magazine/08/12/24/1210211 マルチメディア処理から信号処理まで幅広く活用できる高速ライブラリ「IPP」]』でも解説しているのでそちらを確認してほしい。なお、比較に使用した動画ファイルはWindows Vistaに含まれるサンプルビデオ「湖.wmv」(縦横サイズは720×480、長さは約16秒間)をYUV形式に変換したものを用いている。
=== SSEを利用することで大幅なパフォーマンスの向上が可能 ===
SSEが初めて搭載されたPentium IIIが登場した1999年から約10年が経過した現在では、ほぼすべてのPCでSSEの利用が可能と言っても過言ではない。SSEを利用することで、多くの状況でパフォーマンスの向上が期待できるため、パフォーマンスが必要とされるアプリケーションではSSEの積極利用を検討するべきであろう。
ただし、自動ベクトル化は万能ではなく、コードによってはうまく最適化が行われない場合もある。その場合、インテル コンパイラーの「/Qvec-report」(Windows版)もしくは「-vec-report」(LinuxおよびMac OS X版)オプションを利用することで、ベクトル化できない個所やその依存性などに関するレポートを確認できる。これらによって問題点を特定し、ソースを変更して原因を排除できれば自動ベクトル化が可能になる場合もある。自動ベクトル化と組み込み関数の使用を組み合わせ、より細かい最適化を行っていくと良いだろう。
[[PageNavi(NavigationList)]]