FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

RISC-Vベクトル拡張仕様書 v1.0 を読み直す (20. リダクション命令)

RISC-Vベクトル拡張仕様書の読み直し。次はリダクション命令。

整数と浮動小数点、さらにWideningまであるのでとっても厄介。

github.com

github.com


14. ベクトルリダクション操作

ベクトルリダクションは、ベクトルレジスタ群の要素と、ベクトルレジスタの要素0に保持されているスカラを受け取り、 何らかの二項演算子を用いてリダクションを行い、ベクトルレジスタの要素0にスカラの結果を出力するものです。 スカラの入出力オペランドは、ベクトルレジスタ群ではなく、単一のベクトルレジスタの要素0に保持されるため、LMULの設定に関わらず、 どのベクトルレジスタもベクトルリダクションのスカラのソースまたは書き込みレジスタとなります。

書き込みのベクターレジスタは、マスクレジスタを含むソースオペランドとオーバーラップすることができます。

Note: リダクションは、スカラプロセッサとのデカップリングの損失を回避し、 スカラユニットでサポートされていない将来の型で将来のポリモーフィックな使用をサポートするために、 スカラオペランドと結果をベクトルレジスタの要素0に読み書きします。 ソースベクトルレジスタグループの非アクティブな要素はリダクションから除外されますが、 スカラオペランドはマスク値にかかわらず常に含まれます。

書き込みベクトルレジスタ内の他の要素(0 < index < VLEN/SEW)は末尾とみなされ、 現在のtail agnostic/undisturbedポリシで管理されます。

vl=0の場合は、操作は行われず、書き込みレジスタは更新されません。

ベクトルリダクション命令のトラップは、常に vstart が0で報告されます。 ベクトルリダクション操作は、vstart が 0 でない場合、不正な命令の例外を発生させます。

縮小演算のアセンブラ構文は、vredop.vs です。.vs は、第1オペランドがベクトルレジスタグループで、 第 2 オペランドがベクトルレジスタの要素 0 に格納されたスカラであることを表します。

14.1. ベクトル単一幅整数リダクション命令

単一幅のリダクション命令のオペランドと結果は、すべて同じSEW幅になります。 算術加算ではオーバーフローは丸められます。

 # 単純なリダクション命令. [*]は全てのアクティブな要素を意味する:
    vredsum.vs  vd, vs2, vs1, vm   # vd[0] =  sum( vs1[0] , vs2[*] )
    vredmaxu.vs vd, vs2, vs1, vm   # vd[0] = maxu( vs1[0] , vs2[*] )
    vredmax.vs  vd, vs2, vs1, vm   # vd[0] =  max( vs1[0] , vs2[*] )
    vredminu.vs vd, vs2, vs1, vm   # vd[0] = minu( vs1[0] , vs2[*] )
    vredmin.vs  vd, vs2, vs1, vm   # vd[0] =  min( vs1[0] , vs2[*] )
    vredand.vs  vd, vs2, vs1, vm   # vd[0] =  and( vs1[0] , vs2[*] )
    vredor.vs   vd, vs2, vs1, vm   # vd[0] =   or( vs1[0] , vs2[*] )
    vredxor.vs  vd, vs2, vs1, vm   # vd[0] =  xor( vs1[0] , vs2[*] )

14.2. ベクトル幅拡張整数リダクション命令

符号なしの vwredsumu.vs 命令は、SEW幅のベクトル要素をゼロ拡張してから合計し、 次に2SEW幅のスカラー要素を加え、その結果を2SEW幅のスカラー要素に格納します。

vwredsum.vs 命令は、SEW幅のベクトル要素を符号拡張してから加算します。

 # 2倍幅での符号なしリダクション加算を倍幅でアキュムレートする
    vwredsumu.vs vd, vs2, vs1, vm   # 2*SEW = 2*SEW + sum(zero-extend(SEW))

    # 符号付きリダクション加算を倍幅でアキュムレートする
    vwredsum.vs  vd, vs2, vs1, vm   # 2*SEW = 2*SEW + sum(sign-extend(SEW))

14.3. ベクトル単一幅浮動小数点リダクション命令

    # 単純なリダクション
    vfredosum.vs vd, vs2, vs1, vm # 順序付き加算
    vfredusum.vs vd, vs2, vs1, vm # 順序無し加算
    vfredmax.vs  vd, vs2, vs1, vm # 最大値
    vfredmin.vs  vd, vs2, vs1, vm # 最小値

Note: 過去のアセンブラニーモニックである vfredsum は vfredsum へのエイリアスとして残されています。

14.3.1. ベクトル順序付き単一幅浮動小数点リダクション加算命令

vfredosum命令は、vs1[0]スカラーから順に、 浮動小数点値を要素順に合計しなければなりません—​つまり、以下のように計算を行います。

 vd[0] = `(((vs1[0] + vs2[0]) + vs2[1]) + ...) + vs2[vl-1]`

ここで各加算は、例外フラグの発生や特別な値の生成・伝搬という点で、スカラ浮動小数点演算命令と同じ動作をします。

Note: 順序付きリダクションはコンパイラの自動ベクトル化に対応していますが、順序のないFP加算はより高速な実装を可能にします。

演算がマスクされている場合(vm=0)、マスクされていない要素は結果や例外フラグに影響を与えません。

Note: アクティブな要素がない場合、加算は行われず、vs1[0] のスカラは、NaN値の正規化や例外フラグの設定を行うことなく、単に書き込みレジスタにコピーされます。 この動作は、スカラの加算ループを自動ベクトル化する際のNaN、例外、丸めの処理と同一です。

14.3.2. ベクトル順序無し単一幅浮動小数点リダクション加算命令

順序無しリダクション命令である vfredusum は、リダクションを実行する際の実装の自由度を高めます。

実装では、ソースのベクトルレジスタ群(vs2)とソースのスカラー値(vs1[0])の要素を入力とし バイナリ演算子ノードで構成されるリダクションツリーと同等の結果を生成する必要があります。 ツリー内の各演算子は、2つの入力を受け入れ、1つの結果を生成します。 各演算子は、まず、RISC-Vのスカラ浮動小数点加算として、指数の範囲と精度が無限大の正確な和を計算し、 次に、この正確な和を、SEWで示される要素浮動小数点フォーマットと少なくとも同じ範囲と精度を持つ浮動小数点フォーマットに変換し、 現在アクティブな浮動小数点ダイナミック丸めモードを用いて丸めます。 各演算子の結果には、異なる浮動小数点の範囲と精度を選択することができます。 一方の入力が、マスクされた要素やアクティブなベクトル長を超えた要素からのみ得られるノードは、 その入力を適切なEEWの加法単位元として扱うか、あるいは単に他方の入力をその出力にコピーすることができます。 ツリーのルートノードからの丸められた結果は、SEW で示される標準的な浮動小数点フォーマットに変換されます(動的丸めモードを使用して再度丸められます)。 実装では、最終結果に加法単位元を加えることができます。

加算単位元は,切り捨て(-∞方向)の場合は+0.0、その他の丸め方の場合は-0.0である。

リダクションツリーの構造は、vtype と vl に与えられた値に対して決定的でなければなりません。

Note: この定義の結果として、要素がアクティブでない場合、実装はNaNペイロードをリダクションツリーに伝搬させる必要はありません。 特に、アクティブな要素がなく、スカラー入力がNaNの場合、実装はNaNを正規化し、NaNがシグナリングの場合は、無効な例外フラグを設定することが許可されています。 また、vfredosum のように、元のNaNを通過させ、例外フラグを設定しないことも可能です。

Note: vfredosum 命令は、 vfredusum としても有効です。