Ada 2020 (18日目) - pragma Conflict_Check_Policy

引き続きスレッド検証。

これまでのあらすじ

parallel により簡単に並列化できるようになったため、並列化まわりの検証が重要になっています。 (繰り返し。)

アクセスの競合もよく起きるバグです。 parallel によってものすごく簡単に問題のあるコードが書けてしまいます。

declare
   X : Integer := 100;
begin
   parallel do
      X := X + 1000_000;
   and
      X := X - 10;
   end do;

競合の有名な例え話で銀行口座に百万円振り込んだと同時に10円引き落とされたらというのがあります。 「上側/下側での読み取り」「上側の書き込み」「下側の書き込み」の順番で実行されてしまいますと口座には90円しか残らなくなります。

最近のCPUでは投機実行でもっと謎な挙動になることも考えられます。

Ada 2020での改善

Ada 2020ではアクセスの競合に対してかなり気合の入った検証が行われます。

pragma Conflict_Check_Policy

大枠としては pragma Conflict_Check_Policy を用いてチェックを有効にしますと parallel の各分岐や task 間で変数へのアクセスが競合しているかどうかがコンパイル時に検証されるというものです。

declare
   pragma Conflict_Check_Policy (All_Conflict_Checks);
   A, B : Integer := 0;
begin
   parallel do
      A := B + 2;
   and
      B := A + 3; -- error
   end do;

検証の仕組みとしては各分岐ごと各変数ごとに読み取り(in)と書き込み(out)のアクセスがされているかどうかが調べられ、それが衝突しているかどうかがチェックされます。

この例では parallel の上側では A がout、B がinです。 下側では A がin、B がoutです。 out同士またはinとoutは衝突します。

最初の例でも両方の側で X に対してin out両方のアクセスがされていますので衝突します。

これを修正するには変数へのアクセスを protected やランデブーの中で行うようにします。

declare
   pragma Conflict_Check_Policy (All_Conflict_Checks);
   protected Prot is
      procedure Add (Offset : in Integer);
   private
      X : Integer := 100;
   end Prot;
   protected body Prot is
      procedure Add (Offset : in Integer) is
      begin
         X := X + Offset;
      end Add;
   end Prot;
begin
   parallel do
      Prot.Add (1000_000);
   and
      Prot.Add (-10);
   end do;

これで上側と下側のどちらが先に実行されても口座の残高は同じになります。

どの変数にアクセスしているかという情報はサブプログラムの外に伝播します。 Addprotected ではない単なるサブプログラムですとソースコード上では一箇所からしかアクセスしていないように見えてもやはりエラーになります。

declare
   pragma Conflict_Check_Policy (All_Conflict_Checks);
   X : Integer := 100;
   procedure Add (Offset : in Integer) is -- Xにin outアクセス
   begin
      X := X + Offset;
   end Add;
begin
   parallel do
      Add (1000_000);
   and
      Add (-10); -- error
   end do;

他の要素で排他制御が行える場合やロックフリーなアルゴリズムを使いたいときは邪魔になりますので No_Conflict_Checks 等を指定してチェックを行わないようにできます。

翻訳単位を跨ぐと見えない変数が出てくるのではないか、抽象型はどうなっているのか、変数以外も競合するのでは等の疑問があるとは思います。 そちらはまた後日。 (小出し。)

関連AI

  • AI12-0267-1 Data race and non-blocking checks for parallel constructs

  • AI12-0298-1 Revise the conflict check policies to ensure compatibility