インテル コンパイラーの実力を測る――インテル コンパイラー版MySQLは本当に速いのか?

 インテルが開発している「インテル コンパイラー」は、インテルCPUに最適化された高速なバイナリを生成するということで知られており、Oracleなどパフォーマンスを求めるベンダーで採用されているほか、科学計算用アプリケーション、3Dグラフィックソフトなど、さまざまなソフトウェアのコンパイルに利用されている。

 しかし、「インテル コンパイラーはパフォーマンスが高い」とだけ言われても、なかなかピンと来ない人も多いのではないだろうか。そこで、インテル コンパイラーでコンパイルされたバイナリをベンチマークテストし、実際どの程度の性能向上が見込まれるのかを調べてみよう。

各所で高評価を受けるインテル コンパイラー

 インテル コンパイラーはCPUメーカーであるインテルが開発しているということで、Core i7などの最新CPUに搭載されているSSE 4.2といった命令セットへの対応が図られているほか、インテルおよびインテル互換CPUに向けた最適化機能や自動並列化機能、プロシージャ間の最適化(Interprocedural optimization、IPO)と呼ばれる全体最適化機能など、よりパフォーマンスの高いバイナリを生成するための機能を備えている。そのため、特に浮動小数点演算を多用する科学技術系シミュレーションや画像処理、動画/音声処理、CGといったアプリケーションとの相性が良いと言われており、実際の採用例も多い。

 たとえば、日本国内でインテル コンパイラーの販売・サポートを行っているエクセルソフトのWebサイトに掲載されている「インテル製品の導入事例」では、工学系や金融系のシミュレーションアプリケーションでインテル コンパイラーを使用したところ、1.5倍~2倍以上の速度向上が見られる、という例が複数報告されている。

 また、シミュレーションだけでなく音声処理でもパフォーマンス向上が報告されており、ソニーデジタルネットワークアプリケーションズ株式会社の採用例では、インテル コンパイラーの採用や並列化、パフォーマンス解析などによって最終的に3倍程度の高速化に成功している。

 さらに、大手データベースベンダーであるOracleは同社製品のコンパイルにインテル コンパイラーを採用している。インテル コンパイラーの採用により、特にXeonやItanium 2などの64ビット環境で大きなパフォーマンス向上が達成できたそうだ。

 このように、特に科学技術系やシミュレーションの分野で評価の高いインテル コンパイラーであるが、いっぽうで身近なオープンソースソフトウェアでも、インテル コンパイラーを利用することでパフォーマンスが向上する、というレポートが挙げられている。そのなかでも興味深いのが、MySQLの事例だ。Linux World 2005で発表された「Improving MySQL Server Performance with Intel C++ Compiler」というレポートでは、「Set Query Benchmark」というベンチマークにおいて、インテル コンパイラーを利用することでMySQLのパフォーマンスをPentium 4マシンで最大1.35倍、Itanium 2マシンで最大1.24倍、Xeon(64ビット環境)では最大2.55倍向上できた、と報告されている。

 MySQLはオープンソースのリレーショナルデータベースシステムで、もともとはスウェーデンのMySQL社によって開発されていたが、現在ではサン・マイクロシステムズがその権利を所有している。MySQLにはオープンソース版の「MySQL Community Server」と、商用製品である「MySQL Enterprise」の2製品があるが、MySQL Community ServerのLinux版についてはGCCでコンパイルされたバイナリに加え、インテル コンパイラーでコンパイルされたバイナリも配布されている(ダウンロードページ)。そこでこれらのバイナリを使い、本当にこのようなパフォーマンス向上が見られるのか、比較してみよう。

インテル コンパイラー版MySQLのパフォーマンスを見る

 データベースのベンチマーク手法には大規模なものから簡易的なものまで様々なものがあるが、今回はMySQLに付属している「sql-bench」というベンチマークツールを利用した。sql-benchはPerlで記述されたベンチマークツールで、9つのベンチマーク項目が用意されており(表1)、データベースに対してさまざまなSQLコマンドを発行してその実行時間を測定するものだ。SQLコマンドの発行はシングルスレッドで行われるので、データベースがどの程度の負荷に耐えられるかを測定する、というよりも、データベース自体の処理速度を計測する目的で利用されることが多いベンチマークである。また、SQLコマンドの種類ごとに処理にかかった時間を測定できるため、どのような処理が得意でどのような処理が苦手なのか、という傾向をつかむこともできる。

表1 sql-benchに用意されているベンチマーク項目
ベンチマーク項目 説明
alter-table テーブルに対して多数のフィールド追加/削除を行うテスト
ATIS 複数のテーブルに対して多数のselect文を発行するテスト
big-tables 巨大なテーブルに対してアクセスを行うテスト
connect サーバーへの接続速度を評価するテスト
create テーブル作成の速度を評価するテスト
insert テーブルへのデータのinsert速度を評価するテスト
select select文のパフォーマンスを評価するテスト
transactions トランザクションの速度を計測するテスト
wisconsin Wisconsinベンチマークを行うテスト。SQL文の実行速度を計測できる

 今回のベンチマークには、CPUとしてCore 2 Duo(2.33GHz)を搭載したLinuxマシンを使用した。OSにはDebian GNU/Linux 5.0を使用している(表2)。また、MySQLの設定は基本的にはデフォルトのままだが、バッファ/キャッシュサイズについては表3のように変更している。ベンチマークはそれぞれ3回ずつ実行し、その平均をベンチマーク結果とした。なお、今回のベンチマークではデータベースとしてMySQLデフォルトのMyISAMを使用しているため、トランザクションに関するベンチマークは行っていない。そのほかベンチマークの詳細な手順については、コラムを参照してほしい。

表2 ベンチマークに使用したPC環境
構成要素 スペック
CPU Core 2 Duo E6550(2.33GHz)
OS Debian GNU/Linux 5.0
メモリ 2GB
HDD(OS) Seagate Barracuda 7200.10(250GB)
HDD(DB) Maxtor DiamondMax Plus 9(80GB)


表3 MySQLの設定(抜粋)
設定項目
key_buffer_size 860MB
table_cache 512
sort_buffer_size 128MB
read_buffer_size 100M
read_rnd_buffer_size 96MB
myisam_sort_buffer_size 128MB
thread_cache_size 64
query_cache_size 256MB


コラム MySQLのインストールおよびセットアップ、ベンチマーク手順

 今回のベンチマークは、次のような手順で行った。なお、今回のベンチマークは比較的スタンダードな設定で行っているが、ベンチマーク結果はMySQLの設定や使用するマシンのCPU、OS、搭載メモリ、ストレージなどによって大きく変動する場合がある。ベンチマークに必要なファイル等はすべてWeb上からダウンロードできるので、実際に手元で確認していただきたい。

1.MySQLのインストールおよび初期設定

 MySQL 5.1のダウンロードページから、Linux(non RPM package)およびLinux(non RPM, Intel C/C++ compiled, glibc-2.3)版のバイナリをダウンロードし、アーカイブに含まれている「INSTALL-BINARY」ファイルの指示通りにインストールしてMySQLサーバーを起動する。なお、MySQLサーバーはオプションで使用するバッファやキャッシュのサイズを指定できるが、今回は「mysqld_safe」コマンドに次のようなオプションを付けて起動した。

$ ./mysqld_safe --user=mysql --key_buffer_size=860MB --table_cache=512 \
--sort_buffer_size=128MB --read_buffer_size=100M --read_rnd_buffer_size=96MB \
--myisam_sort_buffer_size=128MB --thread_cache_size=64 --query_cache_size=256MB
2.ベンチマークの準備

 sql-benchは実行にPerlおよびDBIモジュールが必要である。今回テストに使用したDebian GNU/Linuxの場合、次のようにして必要なモジュールのインストールが行える。

# apt-get install libdbd-mysql-perl

 また、実行結果はベンチマークを実行したディレクトリ以下の「output」ディレクトリ内に保存されるので、あらかじめこのディレクトリを作成し、ベンチマークを実行するユーザーが書き込めるようにパーミッションを設定しておく。

3.ベンチマーク実行

 sql-benchディレクトリ中の「run-all-tests」を実行することでベンチマークが開始される。

$ cd sql-bench
$ ./run-all-tests

ベンチマーク結果

 それではベンチマーク結果を見てみよう。sql-benchには9つのベンチマークが含まれているが、それらを起動してから実行完了するまでにかかった時間を比較したものが表4だ。

表4 インテル コンパイラー(ICC)版バイナリとGCC版バイナリのベンチマーク結果
ベンチマーク項目 ICC版 GCC版
alter-table 18.3秒 31.7秒
ATIS 3.7秒 3.3秒
big-tables 3.0秒 4.0秒
connect 50.0秒 50.7秒
create 248秒 249秒
insert 648秒 663秒
select 44.7秒 59.0秒
wisconsin 4.0秒 3.7秒

 また、GCC版の結果を1とした場合の相対的な実行結果を示したものが図1である。

図1 ベンチマークの実行結果(相対時間比較)
図1 ベンチマークの実行結果(相対時間比較)

 ベンチマーク結果でまず目を引くのが、alter-tableテストおよびselectテスト実行の結果である。インテル コンパイラー版バイナリはGCC版バイナリと比べ、alter-tableテストでは約6割、selectテストでは約8割ほどの時間でテストを完走できている。ATISおよびwisconsinテストではGCC版のほうがインテル コンパイラー版よりも若干速かったが、これらについてはそれぞれ0.4秒、0.3秒という僅差である。

 また、wisconsinベンチマークによって測定されたSQLコマンドごとのパフォーマンスをまとめたものが表5である。この表は、それぞれのSQLコマンドを一定回数実行するのにどれだけ時間がかかったか、というのを示しており、数値が小さいほどパフォーマンスが高い。この結果を見ると、インテル コンパイラー版バイナリはテーブルへの項目追加/削除といった操作が大幅に高速化されていることが分かるほか、データの並び替えやキャッシュされたテーブルのselect、キーの更新などもインテル コンパイラー版バイナリの方が高速、という結果となっている。

表5 SQLコマンドごとのパフォーマンス比較(抜粋)
操作 所要時間(秒)
ICC版 GCC版
alter_table_add 7.3 13.7
alter_table_drop 7.7 13.3
count 3.0 8.7
insert_key 137.3 140.3
order_by_big 9.0 10.7
order_by_big_key 8.7 10.0
order_by_big_key_desc 9.0 10.7
order_by_big_key_diff 9.0 10.7
order_by_big_key_prefix 8.3 9.3
prepared_select 16.3 18.0
select_big 8.7 9.7
select_cache2 26 39.7
select_key 30.3 27.0
select_key2 32.7 28.7
select_key2_return_key 30.3 27.3
select_key2_return_prim 31.7 28.0
select_key_prefix 32.3 28.0
select_key_return_key 29.0 26.3
update_of_key 6.7 21.0
update_of_primary_key_many_keys 42.0 37.0

より高いパフォーマンスを求めてコンパイル

 このように、MySQLのWebサイトで配布されているインテル コンパイラー版バイナリはGCC版バイナリよりも高速ということが分かったが、さらにこれを高速化することはできないだろうか。MySQLのWebサイトによると、このインテル コンパイラー版バイナリは、下記のような設定でコンパイルされている。

CC=icc CXX=icpc CFLAGS="-O3 -unroll2 -ip -mp -no-gcc -restrict" CXXFLAGS="-O3 -unroll2 -ip -mp -no-gcc \
-restrict" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data \
--libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client \
--enable-local-infile --enable-assembler --disable-shared --with-client-ldflags=-all-static \
--with-mysqld-ldflags=-all-static --with-embedded-server --with-innodb

 この設定では、複数のファイル間での最適化を行うIPOが行われていない。また、インテル コンパイラーは特定のCPU向けに最適化したバイナリを生成する機能があるが、こちらについても利用されていない。そこで、続いてはこれらの機能を有効にしてMySQLをコンパイルし、MySQLのWebサイトで提供されているインテル コンパイラー版バイナリと比較してみよう。

 コンパイルには、インテル コンパイラー 11.0の体験版を使用した。この体験版は国内でインテル コンパイラーの代理店となっているエクセルソフトのWebサイトからダウンロード可能だ。30日の使用制限があるものの、機能的には正式版とまったく同等である。

 今回使用したコンパイル設定は下記のようにした。なお、IPOを利用する場合、アーカイバとしてLinux標準のarではなく、インテル コンパイラーに付属するxiarを利用することに注意して欲しい。

AR=xiar CC=icc CXX=icpc CFLAGS="-O3 -unroll4 -ipo -fp-model precise -no-gcc -restrict -xSSSE3" \
CXXFLAGS="-O3 -unroll4 -ipo -fp-model precise -no-gcc -restrict -xSSSE3" ./configure \
--prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin \
 --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler \
 --disable-shared --with-client-ldflags=-all-static --with-mysqld-ldflags=-all-static \
 --with-embedded-server --with-innodb

 また、原稿執筆時に公開されているMySQL 5.1.31は、そのままではインテル コンパイラーでコンパイルできないという問題がある。この件はすでにMySQLのバグリポートで指摘されており、MySQLのソースコードを展開したディレクトリ以下の「mysys/stacktrace.c」を次のように修正することで対応できる。

ソースコード69行目の下記の部分

#if BACKTRACE_DEMANGLE

char __attribute__ ((weak)) *my_demangle(const char *mangled_name, int *status)
{
  return NULL;
}

を、次のように修正する。

#if BACKTRACE_DEMANGLE

#if defined(__INTEL_COMPILER)
#pragma weak my_demangle=my_demangle_null
char *my_demangle_null(const char *mangled_name, int *status)
#else /* __INTEL_COMPILER */
char __attribute__ ((weak)) *my_demangle(const char *mangled_name, int *status)
#endf /* !__INTEL_COMPILER */
{
  return NULL;
}

コラム:浮動小数点の精度指定

 インテル コンパイラーでは、浮動小数点の精度を「-fp-model」コンパイルオプションで指定できる。今回は「precise」を指定したが、もし高い精度が不要な場合はこれを「fast=1」(高速)に変更することでより高速化できる可能性がある。もし興味のある方は試してみてほしい。

ベンチマーク結果

 このようにしてコンパイルしたMySQLを先の公式版バイナリとまったく同様の設定でセットアップ・起動し、sql-benchを実行した結果が次の表6図2である。alter-tableテストについては公式のインテル コンパイラー版よりもパフォーマンスが低下したものの、insertテストやconnectテストについてはパフォーマンスの向上が見られた。また、wisconsinテストによるSQLコマンドごとのパフォーマンス結果については、全体的にはパフォーマンスの向上が見られたものの、項目によっては公式版のほうがパフォーマンスが良い、という結果になったものもあった。

表6 インテル コンパイラーで自作ビルドしたバイナリと公式版バイナリのベンチマーク結果比較
ベンチマーク項目 インテル コンパイラー版 公式GCC版
自作版 公式版
alter-table 29.3秒 18.3秒 31.7秒
ATIS 3.3秒 3.7秒 3.3秒
big-tables 3.3秒 3.0秒 4.0秒
connect 48.3秒 50.0秒 50.7秒
create 252.0秒 248.0秒 249.0秒
insert 618.3秒 648.3秒 662.7秒
select 44.0秒 44.7秒 59.0秒
wisconsin 3.3秒 4.0秒 3.7秒


図2 ベンチマークの実行結果(公式のGCC版を1とした相対時間比較)
図2 ベンチマークの実行結果(公式のGCC版を1とした相対時間比較)


表7 SQLコマンドごとのパフォーマンス比較(抜粋)
操作 所要時間(秒)
インテル コンパイラー版 GCC版
自作版 公式版
alter_table_add 13.0 7.3 13.7
alter_table_drop 12.3 7.7 13.3
count_distinct_big 2.3 3.7 3.7
count_on_key 9.3 9.3 11.3
delete_all_many_keys 65.7 78.0 77.7
delete_big_many_keys 65.7 78.0 77.7
insert_key 125.7 137.3 140.3
once_prepared_select 11.0 12.7 12.7
prepared_select 16.7 16.3 18.0
select_cache2 25.7 26.0 39.7
select_key 26.0 30.3 27.0
select_key2 27.3 32.7 28.7
select_key2_return_key 26.7 30.3 27.3
select_key2_return_prim 27.0 31.7 28.0
select_key_prefix 27.0 32.3 28.0
update_of_key 28.7 6.7 21.0
update_of_primary_key_many_keys 42.3 42.0 37.0


インテル コンパイラーでコンパイルすることでMySQLの高速化が期待できる

 以上のように、インテル コンパイラーでコンパイルしたMySQLバイナリは、sql-benchにおいてGCCでコンパイルしたものと比べ高いパフォーマンスを発揮していることが分かった。特にinsertやselectといった操作はより高速に実行できる可能性がある。

 ただし、実運用環境においては必ずしも大きな差が出るとは限らない点には気を付けてほしい。たとえば、MySQL向けの簡易ベンチマークとして、mysqlbenchというものがあるが、こちらのベンチマーク結果では、インテル コンパイラー版とGCC版とではほとんどパフォーマンスに差が見られなかった。このmysqlbenchはTPC-Bと呼ばれる、バッチ処理をイメージした単純なトランザクションのパフォーマンスを測定するもので、どちらかというとI/Oパフォーマンスが重視されるベンチマークだからだと思われる。

 この点を考慮しても、インテル コンパイラー版のMySQLバイナリはGCC版バイナリ以上のパフォーマンスが期待できると考えて良いだろう。また、MySQLに限らず、ほかのデータベースシステムでもインテル コンパイラーを利用することで高速化が期待できる。もちろん、世の中のすべてのプログラムがインテル コンパイラーで高速化できるわけではないが、もし高いパフォーマンスが要求されるアプリケーションが必要な場合、一度インテル コンパイラーでのコンパイルを試してみてはいかがだろうか。

 なお、インテル コンパイラーの最新情報や採用事例などはインテルのWebサイトでも公開されている。インテル コンパイラーに興味を持たれた方は、ぜひこちらも参照してほしい。