HSAのメモリモデル

次の図のように2つのスレッドが"1"をaというアドレスと、bと言うアドレスに書き込んで、それぞれbとaのアドレスを読んだら、どのような値が得られるであろうか? なお、当初はa、bの内容は"0"であったとする。

2つのスレッドが関係のあるアドレスを相互にアクセスするとどうなるか?

ワークアイテム0の青のスレッドの命令とワークアイテム1の赤のスレッドの命令の実行はどのようなタイミングで起こるかわからないとすると、次の図の下側に書いたように、両方の命令が入り乱れる。しかし、赤の命令同士、青の命令同士の順序は変わっていない。(この図は誤りがあり、4行目のldは青、5行目のstは赤が正しい)

このように1つのスレッドの命令が実行される順序が変わらない場合、シーケンシャルコンシステンシがあるという。

下の順序で青と赤のスレッドの命令が実行されると、$s2は0、$s4は1となる

しかし、次の図のように、青と赤のスレッドのldとstの実行順序が逆転すると、$s2と$s4は両方とも"0"になってしまう。

下の順序で青と赤のスレッドが実行されると、$s2と$s4は両方0となる

シーケンシャルコンシステンシは理解しやすいが、実行性能の観点では、それぞれのスレッドのld命令をst命令よりも先に実行するほうが効率が良く、Out-of-Order実行を行うCPUでは、このような逆転が起こり得る。このような逆転を許すメモリアクセスをリラックスドコンシステンシと呼ぶ。

また、命令の実行順序が変わらなくても、aがCPU側のメモリで、bがGPU側のメモリなどという場合は、ハードウェアの造りによっては、CPU側から見るのと、GPU側から見るのでは、ldとstの順序が逆転して見えるということも起こり得る。

しかし、リラックスドコンシステンシのシステムだからと言って、逆転が起こるかどうかはプロセサの状態によるので、常に逆転が起こるとは限らない。つまり、同じ命令列を実行したのに、結果が異なるという困ったことになってしまう。

シーケンシャルコンシステンシを保てば問題はないが、システムのどこから見てもメモリアクセスの順序が同じように見えるハードウェアは、並列性を利用して性能を出すのが難しい。一方、メモリアクセスの順序が全く保証されないリラックスドコンシステンシでは、プログラムを書くことが難しい。

この問題をどのように回避するかがメモリモデルの重要なポイントであり、HSAのメモリモデルでは、リリースコンシステンシを採用している。

HSAではリリースコンシステンシを採用している

リリースコンシステンシのシステムでは、通常のld、st命令に加えて、ld_acq命令とst_rel命令が追加されている。通常のld、st命令は実行順序が規定されないが、1つのスレッド内のld_acq命令とst_rel命令の実行の順序は他のスレッドから見ても、プログラムに書かれた順に実行されたように見えるようになっている。このメモリモデルはARMの64ビットアーキテクチャであるARMv8のモデルとほぼ同じである。

このst_rel命令とld_acq命令を使うと、実行の順序は逆転せず、シーケンシャルコンシステンシの場合と同じ結果になる。

st_rel命令ld_acq命令を使えば、順序を保証でき、$s2=0、$s4=1となる

また、実行順序を保証する必要がないメモリアクセスは、通常のld、st命令を使えば、ハードウェアとして効率の良い順序で、命令を実行し、他のメモリアクセスとの関係のチェックも省くことができるので、プログラムの実行性能を改善することができる。