マルチコア競合の影響は甚大になりうる
このようなマルチコア競合への懸念は、共有リソースへのアクセスは1回で1マイクロ秒にも満たないことが多いので、考えすぎではないかとも思えます。
しかしこの小さな変化はすぐに積み上がっていきます。また、競合が繰り返されると一時的なサービス拒否にもなってしまいます。
リソースアクセスを公平にしたいちばん簡単な形で考えると、2個のコアが同じリソースに、同時かつ同じ方法でアクセスしようとした場合、各コアはリソースの帯域幅を半分ずつ取ります。同様に、コアが4個だった場合はそれぞれ4分の1ずつ取ります。設計保証レベルがもっとも高い(DAL A)アプリケーションに4倍長く割り当てるだけでは妥当とはまったく言えません。さらに、アクセスは必ずしも同じタイプではなく、その割り当てアルゴリズムも誰もが望むような公平なものとは限らないことも、事態を複雑にします。
複数のコアがDRAMにアクセスすることを考えます。DDRコントローラの共有リソースアービトレーションとスケジューリング優先度では、公平性は担保されず、競合の影響は一次関数的な増え方ではないことがあります。
動作の種類とその組み合わせ(リード、ライト、コヒーレンシートラフィック、ブロードキャストなど)や、どのコアで実行されているかなどによって、競合の影響は大きく変わります。例えば、メモリへの書き込み動作は、アーキテクチャによっては読み込みに対して不釣り合いに大きな競合をすることがあります。
マルチコア競合によって長くなる最悪実行時間(WCET)はせいぜい2~3倍程度だという主張もありますが、Power Architectureのコアでのテストでは、競合するコアが1個だけでも、競合を受けるコアのWCETが8倍にもなってしまう場合があることが判明しました。競合源が複数のコアからDDRメモリにオンチップのインターコネクト経由でアクセスするだけの場合でも、クアッドコアのシステムでWCETが12倍以上になる現象が見られました。このような増え方は、同時に実行されるI/OアクセスやDMAエンジンの影響では説明がつきません。
コア当たりのメモリ帯域幅
図2は、別々のプロセッサ上にあるDAL AとDAL CのアプリケーションがDRAMに同時にアクセスしようとした場合の、メモリ帯域幅の例です。
理想としては、DAL Aのアプリケーションが帯域幅の大半を取るべきです。競合緩和を何もしなければ、帯域幅は均等に分割されると予測されます。しかし、Power Architectureで観察された実際の結果では、DAL Cのプロセスがある特定の動作を実行する場合、競合するコアが1個だけでも、帯域幅の大半、DAL Aプロセスの8倍近くまで占有してしまうことが分かります。
マルチコア競合を緩和する方法
マルチコア競合を軽減・緩和する方法には色々あります。理論的には、できる限り競合を減らして競合緩和の作業を簡単にするのが理想です。実際のところ、競合軽減手法のほとんどでは、必然的にアプリケーションが厳しく制限されたり、システム全体の効率やスループットが大きく削られたりします。
例えば、各コアで実行されるアプリケーションをDAL B以上に制限した場合、よくテストされた、信頼できるアプリケーションだけが存在し、暴走や未知の競合などは起こりにくくなると考えられます。I/Oをすべてタイムパーティショニングされたコア1個に移動させるという方法もありますが、この場合既存のアプリケーションを書き直したり他のコアの稼働率を下げたりする必要が出てきます。この方法でI/Oアクセスの問題は解決できても、DDRメモリの競合というさらに大きな問題には対応できません。よほど小さくてコア内部のキャッシュメモリも使い切らないのでもない限り、どんなアプリケーションでもDDRメモリにアクセスしなければなりません。
DMAエンジンは注意深い管理で対応可能なリソースです。I/Oのタイミングを管理して、DMA転送を実行することで、DMAエンジンが原因となる競合は減らせます。
マルチコア競合の大部分は、緩和することができます。しかし減らすことはできません。緩和のやり方は、「対症療法」から共有リソースの利用を監視して厳しく制御する細かい粒度の共有リソースアクセス自動制御まで幅があります。単純ですが非効率的なやり方としては、最大の競合を想定してWCETを新たに見積もって、そのWCETに対してパーティション時間窓を与え、アプリケーションがその時間窓内で完了するかどうか徹底的にテストします。この方法の最大の欠点は、もっと有効な方法ならWCETが競合のない場合の1.5倍程度で済むところ、10倍近くにもなってしまい、マルチコアのスループットがほとんど活かせないことです。また、この方法ではアプリケーションを更新または追加した場合WCETも変化するのでリグレッションテストが必要となり、メンテナンスコストも高くなることがあります。
もっと賢いやり方は、共有リソースへのアクセスを監視し、コアに割り当てられた閾値を超えた時にアクセスを制限する方法です。この方法は、マルチコアプロセッサのほとんどに用意されているハードウェアカウンタで実現できる上、マクロレベルでは比較的シンプルなやり方です。アプリケーションごとに、そのパーティション時間窓に対して閾値が設定され、その閾値を超えたら、そのアプリケーションは一時停止されます。この方法は粒度が大きく、不正な動作をするアプリケーションを捕まえるのには適していますが、もっとよくある事象である、重要度の低いアプリケーションが重要度の高いアプリケーションから帯域幅を奪ってしまうという状態には効きません。それには、パーティション時間窓よりもずっと短いタイムスライスに閾値を設定する、細かい粒度での制御が必要です。
細かい粒度の制御でなら、重要度の低いアプリケーションは共有リソースへの帯域幅を理想的な閾値まで抑えられ、重要度の高いアプリケーションはそのパーティション時間窓の最初から最大の帯域幅が割り当てられます。