
CPU 進化の方向性がクロック数の向上からコア数の増大へと大きく変化した現在、ソフトウェアの性能を向上する技術として、並列処理を実現する、いわゆる並列化プログラミングの重要性が高まっています。 この並列化プログラミングとはどういうもので、どのように実現するものなのか。インテルとマイクロソフトでそれぞれ関連する技術を担当する、菅原氏と川西氏に聞きました。
―― インテルの CPU ではマルチコア化が進んでいますね。その理由はなぜでしょう? そしてマルチコア化はソフトウェアにどのような影響を与えるのですか?
菅原
約 2 年ごとに CPU のトランジスタが倍になるという「ムーアの法則」はよく知られていると思います。これまでは増えたトランジスタを、シングル スレッドのソフトウェアを速くするために使われてきました。例えば、CPU にキャッシュや浮動小数点のユニットを内蔵する、パイプラインの段数を深くするなどです。
いまでもこのムーアの法則は健在ですが、実は CPU によるシングル スレッドの性能向上は 2000 年あたりから鈍化しています。
理由は電力の問題です。以下のグラフは電力と CPU 性能の関係を表しています。20 年前に登場した 80486 の性能と消費電力をそれぞれ 1 とすると、初代の Pentium 4 は性能が 6 倍で消費電力がなんと 23 倍です。このトレンドで性能をあげていこうとすると、消費電力が圧倒的に増えてしまうという問題があるのです。
図: 電力と CPU 性能の関係
その中で、2003 年に登場した Pentium M は、消費電力は抑えつつ、Pentium 4 に匹敵する性能の CPU でした。その後に登場した Core 2 Duo や Core 2 Quad は、この Pentium M をベースにマルチコア化しています。ここから、CPU の性能向上はマルチコアによる方法を取り入れるようになりました。
いままでマルチ CPU、マルチコアを意識したプログラミングというのは、環境がなかったせいもあって PC の世界ではあまり求められませんでしたが、2005 年に Pentium D でインテルがマルチコア CPU をリリースしてからは、モバイルでもデスクトップでもマルチコア環境が揃うようになってきました。
つまり、いままではソフトウェアは特に工夫をしなくても CPU がどんどん速くなったおかげでソフトウェアも速くなった。しかしいまは CPU が新しくなっても、以前ほどの速度向上は得られなくなったということです。
今後ソフトウェアの性能をあげるには、プログラム自身がマルチコアに適応した形態、すなわち同時実行を考慮したものにならなければなりません。インテルとしては、そういう分散処理に対応したソフトウェア開発という方向にデベロッパーのみなさんを導いていきたいと考えています。
川西
マルチコア化の将来のロードマップはどうなっているのですか?
菅原
当面は 4 コア、その先を考えると 6から8 コア程度がモバイルやデスクトップ PCに対応した CPU には載ってくると思います。ハイパースレッドを ON にすると、最大 16 コアまでは増えるかもしれませんね。
ワークステーション環境やサーバー環境では、1 つのサーバーが物理的に複数の CPU を搭載することになるでしょうから、さらにコア数は増えていくと考えられます。

―― CPU がマルチコアになっても、OS などがソフトウェアの処理を自動的に複数のコアに分散してくれるわけではないんですね?
川西
マルチコアの CPU が出始めたころから、例えば PC でウイルス チェックとアプリケーションを同時に走らせても、2 つのコアがそれぞれの処理を分担してくれるので遅くならない、といった説明がされていました。サーバーのように複数のアプリケーションや複数のジョブが同時実行する場合にはこの説明のとおり、OS がコアに処理を分散して割り当ててくれるので、マルチコアの恩恵を受けることができます。
しかし、クライアントのように 1 つのソフトウェアをマルチコアの CPU で速く動したい場合には、そのソフトウェアの中でコアをうまく使うような同時実行に対応した書き方をするしかありません。そのような書き方をしていないソフトウェアは、たとえ 8 コアの CPU の上で動かしても性能は変わらないのです。
マルチコアに対応するソフトウェア開発では、いわゆる「並列プログラミング」と呼ばれるテクニックを用います。
かつて並列プログラミングとして、プログラマーがスレッドを管理するマルチスレッドやマルチプロセスといった手法が使われていました。しかしスレッドは、並列プログラミングにおいてはアセンブリ言語のように低レベルな操作であり、現在ではそれをプログラマーが制御することは望ましくありません。では、どうするかといえば、「タスク」という概念で考えるのが現在の並列プログラミングの手法です。
菅原
現在では、スレッドの管理は並列処理用のライブラリや、.NET のランタイムにまかせられるようになっています。例えば、スレッドをいちいち生成するのではなく、ライブラリがスレッド プールを用意しておいてくれるので、プログラマーは必要なタスクをそこに投げる。するとライブラリ側で効率のよい並列処理を実行してくれる、といったことが可能になっています。
しかも、スレッドの処理性能をあげるには、あるコアで動いた処理は連続してそのコアで動き続けた方が効率的です。コアが持つキャッシュを有効に使えるからです。プログラマーが意識しなくても、これらはライブラリが実行します。これにより、プログラマーが自分でスレッド管理をするよりも、ずっと効率的な実行が可能です。
つまりプログラマーにとって重要なのは、いまやマルチスレッドのプログラミングのテクニックではありません。いかに並列に処理できる「タスク」をソフトウェアの中に実装するかが重要です。マルチコアの時代では、この設計やアルゴリズムこそがソフトウェアの性能にとって高い重要度を持つ要素になってきています。
川西
コンパイラがソース コードを解析して自動的に並列化してくれるような技術はないのでしょうか?
菅原
インテルのコンパイラには、自動的にソース コードを解析して自動的に並列化する機能は用意されていますが、オプションになっていて明示的にオンにする必要があります。また、必ずしも開発者が並列化したい部分を並列化してくれるとは限らないなど、どうしても不十分なところが多く残っています。
ですから、再コンパイルすれば並列処理に対応したバイナリが自動的にできあがる、ということにはならないというのが、いまのところの前提です。

―― そのような新しいタスク ベースの並列プログラミングをサポートするツールとして、インテルやマイクロソフトはどのような開発ツールを提供しているのでしょうか。
菅原
インテルが提供する並列プログラミングのためのツールは、コンパイラ、ライブラリ、チューニング ツール、デバッガなどで、開発ライフサイクル全体をカバーするツールが揃っています。シングルコアはもちろん、マルチコアだけでなくマルチノード環境もサポートしており、さまざまな環境での並列プログラミングをサポートします。
これらのツールは基本的にネイティブ コード (バイナリ) を生成する目的で使用するツールです。まずはコンパイラから紹介しましょう。インテルのコンパイラはインテル自身が開発しているため、最新のCPUが登場するとその命令セットにいちはやく対応することが特徴の 1 つといえます。
並列プログラミングに関しては、コンパイラがソース コードを解析して並列化に関するレポートを表示してくれる機能があります。「ループの依存性」や「並列化する際のグローバル変数」といったことを指摘してくれます。それ以外にもさまざまな最適化機能によって高速化を支援しますし、またインテルのCPUが持つストリーミング SIMD (Single Instruction Multi Data) 拡張命令に対応したベクタライザによる命令レベルの並列化も備えています。
もちろん、日常的にこうした高度な機能を使うプログラミングばかりではないと思いますが、インテルのコンパイラは、日常的な開発環境のコンパイラとしての能力も十分に備えています。しかしコンパイラを急に切り替えることに抵抗を感じる企業や開発者も多いでしょう。そこで、ソフトウェア全体は Visual Studio などの通常のコンパイラを用い、処理の中で時間がかかっている部分については、インテルのコンパイラでコンパイルし直して性能を向上する、という方法をとっているケースも多くあるようです。
菅原
チューニングやデバッグについても紹介しましょう。パフォーマンス解析ツール「インテル VTune パフォーマンス アナライザー」では、ターゲットとなるソフトウェアが CPU をどのように使っているのかを調査でき、キャッシュ ヒットや分岐ミスなどの特性を見ることができますので、それを基にソフトウェアの性能向上を図ることが可能です。
菅原
分散プログラミングによってマルチスレッドで動作するようになったソフトウェアのデバッグは、実は難しいものです。しかもバグを見つけようとしてデバッガを使ったり、プリント文を入れたりすると、スレッド処理のタイミングや順番が変わって、バグが再現しないといったこともあります。
その際に「インテル スレッドチェッカー」は非常に強力なデバッグ ツールとなります。これは実行中のソフトウェアを動的に解析して、データ競合やデッドロックなど、バグの原因となりそうな個所を自動的に発見してくれるツールです。
図: スレッド処理の正当性をチェックする「インテル スレッド チェッカー」
つまり、実行時に特定の現象が発生しないとしても、そのソフトウェアのスレッド処理に内在する問題、デッドロックやリソースの競合の可能性といったものをレポートしてくれるのです。問題を発見するとソース コードのレベルで該当する行を示してくれます。
菅原
図 : マイクロソフトの Visual Studio に統合可能なインテル Parallel Studio
また、「インテル スレッド プロファイラー 」もあります。これでスレッドがいつ生成され、スレッド間でどういう同期が行われていたかなどの情報を確認できます。スレッドの負荷のバランス、処理が長くかかっているスレッドなどを見付け、性能の改善に役立てることが可能です。
ここで紹介したツールはそれぞれ単独で動作するツールですが、Visual Studio に統合して利用可能なサブセット「インテル Parallel Studio」もあります。

―― マイクロソフトのツールはどうですか?
川西
マイクロソフトの開発ツールはネイティブ コードへの対応もありますが、Visual Studio 2010 と .NET Framework 4 で新たにマネージ コードでの並列化プログラミングを支援します。
.NET Framework 4 からは、パラレル タスク ライブラリがサポートされます。複数のタスクを同時に処理するような「タスク並列」のためのライブラリと、ループを動的に分割して並列に処理するような「データ並列」のためのライブラリです。LINQ にも「.AsParallel()」というオプションを付けることで処理が並列化される PLINQ 機能があります。.NET Framework 4 の並列プログラミングのライブラリは、.NET らしい非常にシンプル、かつ柔軟なコーディングが可能で、開発生産性を保ったまま並列処理の利点を受けることができます。
Visual Studio でもタスクベースで並列プログラミングを行えば、プログラマーは実行環境が 2 コアなのか、4 コアなのか、8 コアなのかはまったく気にせずに開発していくことが可能です。.NET のランタイムが実行環境に合わせて実行時に最適化を行い、スレッドへのタスクのスケジューリングを行います。プログラミングはもちろん C# や Visual Basic などでできます。
川西
デバッガなどについても紹介しましょう。デバッガでは、スレッドの動きや親子関係の状態などを見ることができます。これはタスク単位でも表示可能です。
図: Visual Studio 2010 における並列プログラムのデバッグ
たくさんのスレッドがある場合には、特定のスレッドをフォーカスして表示することもできますし、スレッド名にはソース コード内のクラス名が使われているので、ソース コードとの対比も容易です。例えばデッドロックがおきている場合には、その状態を表示することもできる。
プロファイラーでは、スレッドがどのように動いているのか分かります。スレッド同士の同期をどこでとっているのか、どのスレッドがどのスレッドを待っているのか、I/O の状況なども見えます。これによって、無駄に待ちの状態が長かったり、時間がかかったりしているスレッドなどをチェックすれば、最適化のためのヒントになります。
―― デバッガとプロファイラーはインテルからもマイクロソフトからも提供されていますね。それぞれの違いは?
川西
マネージ コードとして開発するには、Visual Studio のデバッガとプロファイラーを使うことになります。ネイティブ コードとして開発するのならば、Visual Studio でも実施できますがより高度な機能を持つインテル社も合わせて活用いただくのが良いかもしれません。いずれにしろ開発環境は Visual Studio に統合されていますので、開発者はツールの使い分けに大きく混乱することなく開発に専念できるのではないでしょうか。
どちらのツールを使うにせよ、ソフトウェアに並列プログラミングを取り入れていくことで、いまの性能を下げずにソフトウェアが提供する機能やサービスを同時に提供できるようになります。これからのソフトウェアを進化させていくために、並列処理を考慮したタスクベースのプログラミングを行い、その際にはツールを活用するということを、ぜひ多くの開発者の方々に実践してほしいと思っています。

菅原清文
インテル株式会社
インテル技術本部 ソフトウェア & サービス統括部
シニア・ソフトウェア・エンジニア
インテル株式会社ソフトウェア & サービス統括部 シニア・アプリケーション・エンジニアであり、プロセッサーアーキテクチャー、各種オペレーティングシステム、アプリケーション開発で長年の経験と実績をもち、2008 年より現職に従事。開発者支援業務に従事しながら並列プログラミングのエバンジェリストを兼務し、次世代ソフトウェア技術の布教活動を行っている
川西裕幸
日本マイクロソフト株式会社
デベロッパー & プラットフォーム統括本部
プラットフォームエバンジェリスト
北海道大学理学部物理学科卒。リアルタイム 3D グラフィックスを専門とし、グラフィックスやシェーダに関する技術文章を執筆・講演。 DirectX SDK 日本語ドキュメントの開発に携わるとともに、Windows Presentation Foundation プログラミング (オーム社)、Game Programming Gems シリーズ、リアルタイム レンダリング第 2 版 (ボーンデジタル)、Texturing & Modeling、A Procedural Approach などを翻訳・監修、XAML プログラミング (ソフトバンク クリエイティブ) を執筆。趣味は薪割り
▲ Top of Page
|