Ada 202x (18日目) - pragma Conflict_Check_Policy ================================================ .. post:: Dec 18, 2019 :tags: ada, ada_2022 引き続きスレッド検証。 これまでのあらすじ ------------------ ``parallel`` により簡単に並列化できるようになったため、並列化まわりの検証が重要になっています。 (繰り返し。) アクセスの競合もよく起きるバグです。 ``parallel`` によってものすごく簡単に問題のあるコードが書けてしまいます。 .. code-block:: ada declare X : Integer := 100; begin parallel do X := X + 1000_000; and X := X - 10; end do; 競合の有名な例え話で銀行口座に百万円振り込んだと同時に10円引き落とされたらというのがあります。 「上側/下側での読み取り」「上側の書き込み」「下側の書き込み」の順番で実行されてしまいますと口座には90円しか残らなくなります。 最近のCPUでは投機実行でもっと謎な挙動になることも考えられます。 Ada 202xでの改善 ---------------- Ada 202xではアクセスの競合に対してかなり気合の入った検証が行われます。 pragma Conflict_Check_Policy ++++++++++++++++++++++++++++ 大枠としては pragma ``Conflict_Check_Policy`` を用いてチェックを有効にしますと ``parallel`` の各分岐や ``task`` 間で変数へのアクセスが競合しているかどうかがコンパイル時に検証されるというものです。 .. code-block:: ada 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`` やランデブーの中で行うようにします。 .. code-block:: ada 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; これで上側と下側のどちらが先に実行されても口座の残高は同じになります。 どの変数にアクセスしているかという情報はサブプログラムの外に伝播します。 ``Add`` が ``protected`` ではない単なるサブプログラムですとソースコード上では一箇所からしかアクセスしていないように見えてもやはりエラーになります。 .. code-block:: ada 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** .. _`AI12-0267-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0267-1.txt .. _`AI12-0298-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0298-1.txt