マルチコアで処理時間短縮の前にやるべきこと組み込みマルチコア進化論(1)(3/4 ページ)

» 2008年11月05日 00時00分 公開
[塚田 雄一 キャッツ,@IT MONOist]

マルチコア分割における問題点

オーバーヘッド

 マルチコアにより処理分割を行う際には、必ずオーバーヘッドが存在します。逐次実行の場合には命令を順番に実行しますが、マルチコア環境においては「処理の起動」「処理が実行するために必要な情報の引き渡し」「処理の終了」「処理の終了結果の情報」などさまざまな情報のやりとりをコア間で行う必要があるため、オーバーヘッドが発生します。

 当然ながらオーバーヘッドは少なければ少ないほど良い性能が期待されます。オーバーヘッド時間が同じであると考えると、処理時間が長い部分を分割した方がオーバーヘッドは少なくて済むので、良い性能が期待されます。例えばmain()から、sub1()がコールされ、さらにsub1()からsub2()が10回コールされていたとします。するとmain()からsub1()がコールされる部分で分割を行った場合(1)ではオーバーヘッドが1回で済みますが、sub1()とsub2()で分割が行われた場合(2)ではオーバーヘッドが10回発生します。

分割部分によるオーバーヘッドの違い 図7 分割部分によるオーバーヘッドの違い

 ここでは「起動オーバーヘッド時間」を100μSEC、「終了オーバーヘッド時間」を100μSECとしてオーバーヘッド時間を計算します。main()からsub1()がコールされる部分で分割した場合(1)は1回のみコールされるため、オーバーヘッドは合計200μSECになります。また、sub1()からsub2()がコールされる部分で分割した場合(2)では10回コールされるため、オーバーヘッドは10倍の2m(2000μ)SECとなります。従って分割ポイントとしては、なるべく親関数に近い部分おいて分割を検討するべきであるといえます。

オーバーヘッド時間の計算 図8 オーバーヘッド時間の計算

依存関係

 ソフトウェアにおいて処理結果が同一関数の場合とそうでない場合、その依存関係について考慮する必要があります。処理結果が同一関数の場合は関数分割が行われても内部変数に格納されますが、処理結果が同一関数内でない場合は外部変数もしくは関数のリターン値などに格納されます。

 また一般的にシーケンス処理と呼ばれるものは、並列化を行った際に処理性能の向上が期待できません。各処理についてその前処理結果が出るまで待ち続ける必要があるためです。例えば「処理1」と「処理2」という2つの処理が存在する場合、「処理2」は「処理1」の結果を演算に使用する場合など、「処理1」と「処理2」をコア分割して並列化した際に「処理2」は「処理1」の結果を待ち続けてしまいます。

依存関係について 図9 依存関係について

デッドロック

 デットロックは、マルチコア(並列化)における問題として最も一般的なものです。複数のプロセスそれぞれが必要とするリソースをお互いにロックし、必要なリソースが開放されるまでお互いにロック(待ち)状態になることを示します。つまり、お互いにロックされていて動作ができない状態です。以下にデッドロックの簡単な例を記します。

  • (1)処理1がロックAの資源を保持していて、ロックBの資源を要求し待ち状態
  • (2)処理2がロックBの資源を保持していて、ロックAの資源を要求し待ち状態

 処理1がロックBの資源を要求しても、すでに処理2が保持しているため、ロック状態となります。また、処理2がロックAの資源を要求しても、すでに処理1が保持しているため、ロックされた状態となります。よってお互いが待ち状態となり、動作ができない状態となります。

デッドロック 図10 デッドロック

Copyright © ITmedia, Inc. All Rights Reserved.