Top: 9 lines / sosuupoyo
Par: 14 lines
LM0上の Half
配列 \(X\) の各要素 \(X[i]\) に対して \(Y[i] = X[i] \times 2\) を計算し、LM1上に出力してください。
MAU 命令も覚えたので、この問題も imm h"2.0"
で即値を用意したあと、半精度の乗算命令 hvmul
を使用して 2.0
を掛ければ良いと思うところでしょう。しかし、MAU を使用した MN-Core 2 の半精度系演算は注意が必要です。
半精度の積和演算は、half × half + float = float の精度で行われるため、この精度に合わせて入出力を行わないといけないからです。
半精度乗算命令 hvmul
はサイクルあたり \(1\) 長語ぶんの「\(4\) 要素の half」をふたつ受け取り、\(2\) 長語で「\(4\) 要素の float」の出力をします。つまり、half で結果を得たい場合は、出力を float から half に変換する必要があります。
MN-Core 2 では hvmulr
のように、MAU 命令式オペコードの末尾に r
を付加することで、double 出力を float に、float 出力を half に変換する事ができます。 (SDM 3.6.9.25「出力の精度縮減」)
つまり、hvmulr $lr0v $ls0v $lm0v
とすれば、half の長語入力を \(2\) つ受け取り、half の長語出力を得ることができます。
同様に、fvmulr $lr0v $ls0v $m0v
とすれば float の長語入力を \(2\) つ受け取り half の単語出力が、dvaddr $lr0v $ls0v $m0v
とすれば double の長語入力を \(2\) つ受け取り、float の単語出力が得られます。
半精度の積和演算 hvfma
を使用して、半精度の値 \(r, s, m\) に対して \(n = r \times s + m\) を計算する場合を考えます。
このとき、hvfma
の \(3\) 番目の引数は float である必要があるので、\(m\) を half から float に変換する必要があります。
MN-Core 2 では hvfma $lr0v $ls0v $lm0ve $lln0v
のように、入力オペランドの末尾に e
を付加すると、half の入力を float に、float の入力を double に変換して入力することができます。(SDM 3.6.9.23「入力の精度拡張」)
この例を見ると、hvfma はサイクルあたり \(1\) 長語ぶんの「\(4\) 要素の half」を \(2\) つと、\(2\) 長語ぶんの「\(4\) 要素の float」を受け取り、\(2\) 長語ぶんの「\(4\) 要素の float」を出力します。
そのため、$lm0
の \(1\) 長語領域にある「\(4\) 要素の half」を精度拡張し、\(2\) 長語ぶんの「\(4\) 要素の float」に変換しています。
結果も half で良ければ、出力の丸めと組み合わせて hvfmar $lr0v $ls0v $lm0ve $ln0v
にします。
半精度を入力に演算をする命令に関しては、hvmul $lr0 $lls0r $lln0
のように入力オペランドの末尾に r
を付加すると、float を half に変換して入力できます。(SDM 3.6.9.24「入力の精度縮減」)
この例では、\(1\) 長語ぶんの「\(4\) 要素の half」と、\(2\) 長語ぶんの「\(4\) 要素の float」を half に変換して受け取り、それらの積を \(2\) 長語ぶんの「\(4\) 要素の float」を出力します。
なお、double を float に入力で丸める事はできません。また、同様の入力丸め機能は ALU の半精度演算命令にも存在します。(SDM 3.6.12.19「ALU への入力の単精度から半精度への精度縮減」)
出力を float から double のように精度拡張する事はできません。
半精度の積和演算は、half × half + float = float の精度で行われると説明しましたが、vadd
や vpassa
もこの積和演算器を流用しているため、同様に精度の丸めや拡張を行う必要があります。
hvadd は half + float = float で行われるので、入力を half で行いたい場合は、\(2\) 番目の引数を e
で精度拡張する必要があります。
hvpassa も half → float で行われるので、出力を half で行いたい場合は出力を half に丸める必要があります。
なお、 hvfma $lr0v $ls0v $ls0ve $lln0v
のように、同じ読み出し元 PE オペランドに対して精度変換の指定を混在させることも可能です。
$lm[0:96]
/ ((16_MAB:1, 4_PE:1, 48:1, 4_W:1); B@[L1B,L2B])
$ln[0:96]
/ ((16_MAB:1, 4_PE:1, 48:1, 4_W:1))
/ \(10^{-9}\) 以下の絶対誤差が許容されます