並列処理の不具合と対策について、ブログをはじめます。
並列処理プログラミング経験の浅い私が、pthreadライブラリを使用して並列化を行い、その過程で発生するトラブルの情報を掲載します。
題材プログラムは、簡単な演算処理プログラム
昨年につづいて今年も小さなプログラムで試します。
・10進整数を引数で受け、0から引数値までの整数を4バイトで加算します。
・4バイトのint型、2バイトのshort型、この2つのサイズで計算し、計算結果が同じであることを確認します。
・short型の加算処理では4バイト数値として加算するために、上位と下位の2度加算し桁上り処理をします。
・さらに、short型の加算処理は、2つの関数を動作させて並列処理します。
まず、ベースとなる逐次処理のプログラムを作りました。 C言語です。
2つの型による加算関数は以下の通りです(プログラム全体は末尾からダウンロード可能です)。
2つの関数の加算結果が同じ時は以下のような動作結果になります(引数の値には100000を指定しています)。 プログラム名は、sample1_0.exe です。
並列処理
2バイト関数の並列化処理では、0から加算してゆく関数と、指定値から0に向かって加算してゆく関数の2関数を並列に動かします。ぶつかったところで加算処理を停止します。
2つの加算関数は以下の通りです。
この2関数を並列動作させましたが、正しい加算結果を得られません。
誤動作の原因は変数の競合
並列処理では2つの関数が同時に動作するので、自分の処理を別の処理が邪魔します。
両関数が同じ変数をアクセスするために、個々の関数の想定外の値を使ってしまうのです。
何が起きているのか
2つの関数が同時に動作する際のいくつかの状況を考えてみます。
0x111111111 に A関数が 0x22222222 を加算し、 B関数が 0x33333333 を加算する2つの処理例を以下に示します。
この場合、どちらも問題ありません。
さらに処理順序を細分化してみます。
この例でも問題ありませんが、もし矢印の部分の順序が逆転すると正しい結果が得られません。
競合を回避するための排他処理
他の処理に邪魔されないようにするには、邪魔されたくない区間を単独で動作するようにします。
・指定区間では他関数の動作を排除する
・動作するには優先権が必要(優先権が得られない時は待つ)
競合を回避するための排他処理
他の処理に邪魔されないようにするには、邪魔されたくない区間を単独で動作するようにします。
・指定区間では他関数の動作を排除する
・動作するには優先権が必要(優先権が得られない時は待つ)
排他処理対策の結果は
排他処理を施して動作させたプログラムは、何時間待っても終わらなくなってしまいました。
次回は、この問題の調査と対策を行います。
コメントをお書きください