Linux と対称型マルチプロセッシング

SMP システムで Linux の能力を解き放つ

代表的な中央演算処理装置 (CPU) ベンダーの数々を見ても明らかなように、マルチコア・プロセッサーがデスクトップ市場と組み込み市場を独占しようとしています。マルチプロセッシングによって確かにパフォーマンスは向上しますが、新たな問題も伴います。この記事ではマルチプロセッシングの背後にある概念、そしてSMP を活用する Linux® 対応アプリケーションを開発する方法を検討します。

M. Tim Jones (mtj@mtjones.com), Consultant Engineer, Emulex

M. Tim JonesM. Tim Jones は組み込みソフトウェアのエンジニアであり、『GNU/Linux Application Programming』や『AI Application Programming』(現在、第 2 版)、それに『BSD Sockets Programming from a Multilanguage Perspective』などの著者でもあります。技術的な経歴は静止軌道衛星用のカーネル開発から、組み込みシステム・アーキテクチャーやネットワーク・プロトコル開発まで、広範にわたっています。また、コロラド州ロングモン所在のEmulex Corp. の顧問エンジニアでもあります。


developerWorks 貢献著者レベル

2007年 3月 14日

Linux システムのパフォーマンスを向上させるさまざまな取り組みのなかで最もよく用いられているのは、プロセッサーのパフォーマンスを向上させるという方法です。明らかなソリューションはクロック速度を上げてプロセッサーを使用することですが、どんな技術にしても、クロックをそれ以上高速化できないという物理的上限があります。この上限に達した場合、次に採用できる手段は、多ければ多いほどいいという考えで複数のプロセッサーを適用することです。ただし、個々のプロセッサーのパフォーマンスを集約したからといって、それに比例してシステムのパフォーマンスが向上するというわけにはいきません。

Linux でのマルチプロセッシング・アプリケーションについて説明する前に、マルチプロセッシングの歴史を簡単に振り返ってみましょう。

マルチプロセッシングの歴史

Flynn によるマルチ CPU アーキテクチャーの分類

SISD (Single Instruction, Single Data) は、典型的なユニプロセッサー・アーキテクチャーです。MIMD (MultipleInstruction, Multiple Data) マルチプロセッシング・アーキテクチャーでは、各プロセッサーがそれぞれ独立したデータを処理します(制御の並列処理)。一方、SIMD (Single Instruction, Multiple Data) では複数のプロセッサーが単一の命令で同時に複数のデータを処理します(データの並列処理)。

Flynn の論文についての詳細は、 「参考文献」 セクションを参照してください。

マルチプロセッシングの起源は 1950年代半ばに遡ります。みなさんもご存知の会社やもう記憶に残っていない会社を含め、多くの会社 (IBM、DigitalEquipment Corporation、Control Data Corporation) がマルチプロセッシングを開始しました。1960年代の初頭には、BurroughsCorporation が 4 個の CPU と最大 16 個のモジュールをクロスバー・スイッチで接続した対称型 MIMD マルチプロセッサーを発表しました(初の SMP アーキテクチャー)。高い人気で成功を収めた CDC 6600 は 1964年に発表されたもので、CPU に 10 個のサブプロセッサー(周辺処理装置) が搭載されました。1960年代後半になると、Honeywell が初の Multics システムを実現しました。このシステムも同じく対称型マルチプロセッシング・システムで、8個の CPU を搭載しています。

マルチプロセッシング・システムの開発が進むなか、プロセッサーを小型化し、一層高いクロック速度で動作させるための技術も進歩しました。1980年代、CrayResearch などの会社はマルチプロセッサー・システムとそれを利用する UNIX® ライクなオペレーティング・システム (CX-OS)を発表しています。

1980年代後半になると、IBM PC をはじめとするユニプロセッサー・パーソナル・コンピューター・システムの人気が高まったことから、マルチプロセッシング・システムの人気はいったん衰えます。ですがそれから20 年を経た現在、マルチプロセッシングは対称型マルチプロセッシングという形で再びパーソナル・コンピューター・システムで採用されるようになりました。

アムダールの法則

コンピューター・アーキテクトで IBM フェローでもある Gene Amdahl は、IBM と彼の名前にちなんだベンチャー企業、AmdahlCorporation などの会社でコンピューター・アーキテクチャーを開発しましたが、彼の名前を有名にしたのは、システムの一部が改良された場合に最大限期待できるパフォーマンス向上の度合いを予測する法則です。この法則は、複数のプロセッサーを使用した場合に理論上考えられる最大のパフォーマンス向上率を計算する方法として広く普及しています(図 1 を参照)。

図 1. プロセッサーを並列化する場合のアムダールの法則
図 1. プロセッサーを並列化する場合のアムダールの法則

システムの最大パフォーマンス向上率は、図 1 に示す等式で計算できます。N はプロセッサーの数で、F は並列化できないシステムの部分 (システムの性質上シーケンシャルに処理される部分)を指定する係数です。この等式の結果を図 2 に示します。

図 2. 10 個までの CPU に対するアムダールの法則
図 2. 10 個までの CPU に対するアムダールの法則

図 2 では、一番上の線がプロセッサーの数を示します。プロセッサーを追加してこの線のとおりに問題を解決できれば理想的ですが、そう簡単には行きません。問題をまるごと並列化できるわけではなく、プロセッサーを管理する上でオーバーヘッドが生じるため、速度の上昇率はこれより大幅に少なくなります。一番下(紫色の線) は、問題の 90% の部分がシーケンシャルに処理されるため場合の線です。このグラフで最も成績が良いのは茶色の線で、シーケンシャルに処理される部分が10% の場合を示しています。つまり、90% を並列化できるということですが、この場合でも 10 個のプロセッサーでのパフォーマンス向上率は5 個のプロセッサーに比べてほんのわずかです。


マルチプロセッシングと PC

SMP アーキテクチャーは、2 個以上の同一プロセッサーが共有メモリーを介して互いに接続している単純なアーキテクチャーです。それぞれのプロセッサーは共有メモリーに等しくアクセスします(メモリー空間に対するアクセス遅延が同じです)。NUMA (Non-Uniform Memory Access) アーキテクチャーはこれとは対照的で、例えば各プロセッサーは独自のメモリーを持つだけでなく、共有メモリーにも異なるアクセス遅延でアクセスします。

疎結合マルチプロセッシング

初期の Linux SMP システムは疎結合マルチプロセッサー・システムで、高速相互接続 (10G Ethernet、ファイバー・チャネル、Infinibandなど) によって結合された複数のスタンドアロン・システムで構成されていました。このタイプのアーキテクチャーはクラスター (図 3 を参照) とも呼ばれ、今でもLinux Beowulf プロジェクトがクラスター・ソリューションとしてよく使用されています。Linux Beowulf クラスターは、汎用ハードウェアとEthernet などの一般的なネットワーキング相互接続で構築できます。

図 3. 疎結合マルチプロセッシングのアーキテクチャー
図 3. 疎結合マルチプロセッシングのアーキテクチャー

疎結合マルチプロセッサーのアーキテクチャーを構築するのは (Beowulf のようなプロジェクトのお陰で) 簡単ですが、それなりの制約事項があります。まず、大規模なマルチプロセッサー・ネットワークを構築すると、かなりのスペースと電力を使うことになります。このアーキテクチャーは一般的に汎用ハードウェアで構築されるため、関連性がないにもかかわらず電力とスペースを消費するハードウェアが含まれるためです。最大の障害は通信ファブリックで、10GEthernet のような高速ネットワークの場合でもシステムのスケーラビリティーには限界があります。

密結合マルチプロセッシング

密結合マルチプロセッシングとは、チップ・レベルのマルチプロセッシング (CMP) を意味します。疎結合アーキテクチャーをチップ・レベルまで縮小してみてください。それがまさに、密結合マルチプロセッシング(マルチコア・コンピューティングとも呼ばれます) の背後にある概念です。1 つの集積回路上に、複数のチップ、共有メモリー、そして相互接続がマルチプロセッシング用の1 つの密に統合されたコアを形成します (図 4 を参照)。

プロセッサーの相互接続

相互接続のオプション (システム・ファブリック用バス) としては、AMD の HyperTransport もあります。また、Intel®が現在計画中の新しい相互接続、Common System Interface は 2008年に完成する予定です。

図 4. 密結合マルチプロセッシングのアーキテクチャー
図 4. 密結合マルチプロセッシングのアーキテクチャー

CMP では、複数の CPU が共通バスを介して共有メモリー (レベル 2 キャッシュ) に接続されます。各プロセッサーには、それぞれに固有の高速メモリー(レベル 1 キャッシュ) もあります。CMP の密結合という性質により、プロセッサーとメモリー間の物理的な距離を極めて短くできるため、アクセス遅延が最小限になりパフォーマンスが向上します。このようなアーキテクチャーが効果を発揮するのは、スレッドをプロセッサーに分散させて並列処理することが可能なマルチスレッド化されたアプリケーションです。これは、スレッド・レベルの並列処理(TLP) としても知られています。

このマルチプロセッサー・アーキテクチャーに人気が集まっていることから、多くのベンダーでは CMP デバイスを生産しています。表 1 に、よく使用されているCMP デバイスで Linux をサポートするものをいくつかリストします。

表 1. CMP デバイスの抜粋
ベンダーデバイス説明
IBMPOWER4SMP、デュアル CPU
IBMPOWER5SMP、デュアル CPU、4 つの同時スレッド
AMDAMD X2SMP、デュアル CPU
Intel®XeonSMP、デュアルまたはクワッド CPU
IntelCore2 DuoSSMP、デュアル CPU
ARMMPCoreSMP、最大 4 個の CPU
IBMXenonSMP、3 個の Power PC CPU
IBMCell Processor非対称型マルチプロセッシング (ASMP)、9 個の CPU

カーネルの構成

SMP 対応ハードウェア上の Linux で SMP を活用するには、カーネルが正しく構成されていなければなりません。それには、カーネルの構成中にCONFIG_SMP オプションを有効にして、カーネルが SMP を認識するようにします。SMP 認識カーネルを複数の CPU を搭載したホストで実行すると、procファイルシステムによってプロセッサーの数とそれぞれのタイプを識別できます。

まず grep を使用して、/proc 内にある cpuinfo ファイルでプロセッサーの数を検索してください。リスト 1 に示すように、processor というワードで始まる行に対してカウント・オプション (-c) を使用します。この検索によって、cpuinfo ファイルの内容が表示されます。以下は、2 個の Xeon チップを搭載したマザーボードでの例です。

リスト 1. proc ファイルシステムによる CPU 情報の検索
mtj@camus:~$ grep -c ^processor /proc/cpuinfo
8
mtj@camus:~$ cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 15
model           : 6
model name      : Intel(R) Xeon(TM) CPU 3.73GHz
stepping        : 4
cpu MHz         : 3724.219
cache size      : 2048 KB
physical id     : 0
siblings        : 4
core id         : 0
cpu cores       : 2
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 6
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr 
pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm 
pbe nx lm pni monitor ds_cpl est cid xtpr

bogomips        : 7389.18

...

processor       : 7
vendor_id       : GenuineIntel
cpu family      : 15
model           : 6
model name      : Intel(R) Xeon(TM) CPU 3.73GHz
stepping        : 4
cpu MHz         : 3724.219
cache size      : 2048 KB
physical id     : 1
siblings        : 4
core id         : 3
cpu cores       : 2
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 6
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr 
pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm 
pbe nx lm pni monitor ds_cpl est cid xtpr

bogomips        : 7438.33 

mtj@camus:~$

SMP と Linux カーネル

初期の頃の Linux 2.0 では、SMP サポートはシステム全体でアクセスを逐次化する「大掛かりなロック」で構成されていました。SMP のサポートはゆっくりと進歩していきましたが、それでも2.6 カーネルまでは SMP の実力は埋もれていました。

2.6 カーネルが導入した新しい O(1) スケジューラーでは、SMP システムのサポートが改善されています。その鍵は、使用可能な CPU で作業負荷を均等にすると同時に、アフィニティーを維持してキャッシュの効率化を図ることができるという点です。キャッシュの効率性について、図4 をもう一度見てください。単一の CPU に関連付けられたタスクを別の CPU に移すには、そのタスクのためにキャッシュをフラッシュしなければなりません。そのため、タスクのデータが新しいCPU のキャッシュに入るまでのメモリー・アクセス遅延が長くなります。

カーネルでの SMP

特定のアーキテクチャーで SMP がどのように初期化されるのかを理解するには、smp.c または smpboot.c ファイルを参照してください。大抵のアーキテクチャーおよびプラットフォームでは、この2 つのファイルは ./linux/arch/<arch>/kernel/ のカーネル内にあります。

2.6 カーネルは、プロセッサーごとに 1 対のランキューを維持します (期限切れおよびアクティブ・ランキュー)。各ランキューがサポートする優先順位の数は140 で、上位の 100 はリアルタイムのタスク用、下位の 40 はユーザー・タスク用です。タスクには特定のタイム・スライスが与えられ、割り当てられたタイム・スライスを使ったタスクは、アクティブ・ランキューから期限切れランキューに移されます。このようにして、すべてのタスクが平等にCPU にアクセスできるようになっています (ロックは CPU 単位でのみ行われます)。

CPU ごとのタスク・キューにより、システムで測定された全 CPU の負荷を基に作業負荷を分散することができます。スケジューラーは200 ミリ秒ごとにロード・バランシングを行ってタスクの負荷を分散しなおし、プロセッサー複合システム全体の負荷バランスを保ちます。Linux2.6 スケジューラーについての詳細は、「参考文献」セクションを参照してください。


ユーザー空間のスレッド: SMP の能力の活用

Linx カーネルには SMP を活用するための多大な労力が注がれましたが、オペレーティング・システムだけでは不十分です。SMP の能力は TLPで発揮されることを思い出してください。つまり、単一のモノリシックな (スレッド化されていない) プログラムでは SMP を活用できませんが、プログラムを多数のスレッドで構成し、これらのスレッドをコアに分散させればSMP を活用できるということです。このようなプログラムでは、1 つのスレッドが入出力の完了を待っている間、別のスレッドが有益な作業を実行できます。このように、スレッドが連動して互いの処理遅延を隠蔽します。

POSIX (Portable Operating System Interface) スレッドは、SMP を利用するスレッド化アプリケーションを構築するのに最適な手段です。POSIXスレッドは、スレッド化機構とともに共有メモリーも提供します。プログラムが呼び出されて複数のスレッドを作成すると、各スレッドにはそれぞれ固有のスタック(ローカル変数と状態) が与えられます。ただし、これらのスレッドは親のデータ空間を共有します。作成されたすべてのスレッドが同じデータ空間を共有することになるわけですが、ここに問題があります。

共有メモリーへのマルチスレッドによるアクセスをサポートするには、調整機構が必要となります。そこで、POSIX で用意されているのが mutex関数です。mutex 関数は、単一のスレッドだけが排他的にオブジェクト (メモリーの一部) にアクセスするクリティカル・セクションを作成します。このようにしないと、複数のスレッドによる操作が同期されないことからメモリーが壊れる可能性があるからです。リスト2 に、POSIX mutex によるクリティカル・セクションの作成方法を示します。

リスト 2. pthread_mutex_lock と pthread_mutex_unlock によるクリティカル・セクションの作成
pthread_mutex_t crit_section_mutex = PTHREAD_MUTEX_INITIALIZER;

...

pthread_mutex_lock( &crit_section_mutex );

/* Inside the critical section. Memory access is safe here
 * for the memory protected by the crit_section_mutex.
 */

pthread_mutex_unlock( &crit_section_mutex );

上記の呼び出しを最初に行った後に複数のスレッドがセマフォーをロックしようとすると、これらのスレッドがブロックし、pthread_mutex_unlock が呼び出されるまでスレッドの要求がキューに入れられます。


SMP に対するカーネル変数の保護

プロセッサー内の複数のコアがカーネルに対して同時に動作する場合に望ましいのは、特定コアの固有データが共有されないようにすることです。このため2.6 カーネルでは、単一の CPU に関連付けた CPU ごとの変数というコンセプトが導入されています。このコンセプトでは CPU がもっともよくアクセスする変数を宣言できるため、ロックの要件が最小限になり、パフォーマンスが向上します。

CPU ごとの変数を定義するには、DEFINE_PER_CPU マクロに型と変数名を指定します。このマクロは l 値のように振る舞うため、このマクロで変数を初期化することも可能です。以下の例 (./arch/i386/kernel/smpboot.cから引用) では、システム内の各 CPU 対して状態を表す変数を定義しています。

/* State of each CPU. */
DEFINE_PER_CPU(int, cpu_state) = { 0 };

このマクロは、CPU インスタンスごとに 1 つの変数配列を作成します。CPU ごとの変数にアクセスするには、per_cpu マクロを smp_processor_id と一緒に使用します。smp_processor_id は、実行中のコードが対象としている現行 CPU の ID を返す関数です。

per_cpu( cpu_state, smp_processor_id() ) = CPU_ONLINE;

2.6 カーネルには、CPU ごとのロックや変数の動的割り当てを行うための関数も用意されています。これらの関数は ./include/linux/percpu.hにあります。


まとめ

プロセッサーの周波数が限界に達したときにパフォーマンスを向上させる手段としてよく使われるのは、プロセッサーを追加するという単純な方法です。初期の頃、これはマザーボードにプロセッサーを追加したり、あるいは複数の独立したコンピューターをまとめてクラスター化することを意味していました。今日ではチップ・レベルのマルチプロセッシングにより、単一のチップにCPU を追加してメモリー・アクセス遅延を短縮し、パフォーマンスをさらに向上させることが可能になっています。SMP システムはサーバーだけでなく、デスクトップでも使用されており、とくに仮想化の導入とあわせて使用されています。

Linux でもほとんどの最先端の技術と同じく、SMP のサポートを提供しています。また、(スレッドから仮想化オペレーティング・システムに至るまで)カーネルが、使用可能な CPU 全体での負荷を最適化するというその役割を果します。後はアプリケーションを十分にマルチスレッド化して、SMP の能力が発揮されるようにするだけです。

参考文献

学ぶために

  • 「Linux スケジューラーの内側」(developerWork、2006年6月) では、2.6 カーネルで導入された新しい Linux スケジューラーについて詳しく説明しています。
  • 「Basic use of Pthreads」(developerWorks、2004年1月) では、Linux での Pthread プログラミングを紹介しています。
  • 「/procファイルシステムを使用したLinuxカーネルへのアクセス」(developerWorks、2006年3月) では、/proc ファイルシステムにファイルを提供する独自のカーネル・モジュールのビルド方法をはじめ、/procファイルシステムの概要を説明しています。
  • 「The History of Parallel Processing」(1998年) では、Mark Pacifico と Mike Merrill がマルチプロセッシングの 50 年にわたる歴史を簡潔かつ興味深く説明しています。
  • IBM POWER4 および POWER5 は対称型マルチプロセッシング用アーキテクチャーです。POWER5 では対称型マルチスレッド化 (SMT) も行うため、パフォーマンスがさらに向上します。
  • Cell プロセッサー は非対称型マルチプロセッシングに対応した注目のアーキテクチャーです。Cell を使用する Sony Playstation 3 を見ても、このプロセッサーの実力は明らかです。
  • Power Architecture technology ゾーン では、IBM の半導体技術に重点を置いた技術資料を紹介しています。
  • IBM では、HACMP(High-Availability Cluster Multiprocessing) におけるクラスター化技術を提供しています。クラスター化によるマルチプロセッシングの他、HACMP は完全なオンライン・システム監視によって信頼性の向上も実現します。
  • Flynn 本人による分類法では、考えられるマルチプロセッシングのアーキテクチャーを定義しています。この彼の論文「Some ComputerOrganizations and Their Effectiveness」は 1972年、IEEE Transactions on Computing,Vol. C-21 で発表されました。 ウィキペディアに、Flynn による 4 つの分類が分かりやすく要約されています。
  • ARM11 MPCoreは合成可能なプロセッサーで、最大 4 個の ARM11 CPU を実装して総計 2600 Dhrystone MIPS (100 万命令/秒)のパフォーマンスを達成できます。
  • Beowulf クラスター は、汎用 Linux サーバーを集約してハイパフォーマンス・システムをビルドするのに最適な手段です。
  • HyperTransportRapidIO、そしてこれから登場する Common System Interconnectなどの標準は、次世代システムのための効率的なチップ間相互接続を実現します。
  • developerWorks Linux ゾーンには、Linux 開発者用の資料が豊富に揃っています。
  • developerWorks technical events and Webcastsで最新情報を入手してください。

製品や技術を入手するために

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux
ArticleID=245806
ArticleTitle=Linux と対称型マルチプロセッシング
publish-date=03142007