今さら聞けないマルチプロセッサの基礎教えます ――キャッシュの共有,割り込みの共有,OSによる制御
● クリティカル・セクションは短く設定する
また,前述したOSの待ち行列の問題のように,データを複数のタスクで共有する場合には注意が必要です.このような共有データを扱う部分をクリティカル・セクション,排他的に共有データにアクセスすることを排他制御と呼びます.具体的には,クリティカル・セクションの先頭で,フラグ変数を使って共有データが使用中であることを示し,データをロックします(ほかのタスクからの変更を禁止する).
このときクリティカル・セクションが長いと,複数のCPUがクリティカル・セクションの実行順番待ちをすることになり,処理効率が悪くなります.共有データやそれを操作するクリティカル・セクションについては,設計段階からその処理が必要以上に長くなっていないかなどを考察する必要があります.
また,クリティカル・セクションはバグの温床になりやすい部分です.例えば,共有資源を扱うライブラリ関数(malloc関数など)はクリティカル・セクションになりますが注5,並列処理を想定していなかったmalloc()が複数のCPUから同時に呼び出されると,それぞれのCPUに同じ領域を返してしまうかもしれません.このような状況では,バグの原因が特定しづらくなります.
また,クリティカル・セクションではプロセッサのデータ・アクセス順のちょっとした違いによってバグを再現しにくくなってしまうので,非常にやっかいなことになります.逆に,プログラム内部の状態を逐一観察できるようなしくみを用意できれば,プログラムの調整やテストの苦労を大きく軽減できます.
注5;malloc()関数は,メモリのヒープ領域からユーザが指定した容量だけメモリ領域を割り当てる.このときmalloc()関数の内部では,ヒープ領域内部の確保した領域と使用領域を,スタティック変数やグローバル変数で管理している.複数のタスクが同時に実行されるシステムの場合,これらの管理情報も共有資源となるので,malloc()関数はクリティカル・セクションとなる.並列処理を想定したmalloc()関数はロック処理を用いて,複数のプロセッサが同時にmalloc()を呼び出しても,同時には処理しないようにしている.