結構昔にRISC-V Vector Extensionの仕様を日本語化したものを公開していたのだが、公開して移行全くアップデートしていなかったので最新仕様に対応すべく修正を行った。
前回の公開時の記事はこちら。v.0.7.1をベースに執筆している。
今回は最新仕様のv0.8に基づいて修正を行っている。 RISC-V Vector Extensionの仕様書のタグv0.8を参照しながら執筆を行ったので、中途半端な修正ではなくちゃんと正式リリースに対応しているはずだ。
そしてこちらが修正を実施した日本語版。
- RISC-V “V” Extension 日本語版
RISC-V “V” Extension — riscv-v-spec-japanese ドキュメント
あらかじめ断っておきますが、あくまで趣味で翻訳しているものなので間違いや誤訳はかなり含まれていると思います。 これに関してはDog Foodingというか、自分が使うことになったら修正をかけていくと思う。Pull Requestも大歓迎だけれども。
v0.8での変更点
せっかくなので修正点を要約する。v.0.7.1からv0.8において、主に以下の点において修正が加わっている。
vlenb
レジスタの導入- VL以降のベクトル要素についてはゼロ書き込みの仕様であったものが、「値の変更なし」に変えられている。
- 全体ベクトルレジスタ・ベクトルロードストア命令が新規追加となる。
- 4倍ビット幅整数乗算加算命令が新規追加となっている。
- ビット幅拡張飽和付き累積乗算加算命令が全面削除
vfredosum
命令の導入。
テール要素の扱いについて
特に大きめの修正点としては「VL以降のベクトル要素についてはゼロ書き込みの仕様であったものが、「値の変更なし」に変えられている。」つまりテール要素に対する書き込みのポリシーに変更が加わっている。
これに関してはかなり議論が行われていたようで、以下の示すような議論の履歴を残すメモも公開されていた。
Selecting "undisturbed" versus "zeroing" behavior for vector inactive and tail elements riscv-v-spec/v-undisturbed-versus-zeroing.adoc at master · riscv/riscv-v-spec · GitHub
日本語版 「インアクティブおよびテール要素の「変更なし」と「ゼロ設定」に関する議論」 インアクティブおよびテール要素の「変更なし」と「ゼロ設定」に関する議論 — riscv-v-spec-japanese ドキュメント
ただし図が全くないので理解が難しいのだが、自分でいろいろ図を書いて調べてみた。主にレジスタリネーミングのポリシをどのように考えるかというところで実装のしやすさが変わる、というところらしい。
- ベクトルのテール要素(つまり演算対象ではないベクトルの後ろの方)のアップデートを行わない場合(v0.8の仕様)
この場合、まず空間的にベクトルレジスタが配置されている場合(つまりSIMDみたいな感じかしら)、テール要素をどのように扱おうがオーバヘッドは発生しない。同時に演算が実行されるだけである。
ただしこれが時間的なベクトルレジスタ配置(つまり、先頭のベクトルから順番に実行していく場合)の場合、テール要素は無視するだけでなく、リネーム元のレジスタの内容をちゃんとコピーしないと「値の保持」にならない。このためのオーバヘッドが発生する。これがベクトルの長さが大きくなるとバカにできなくなる。
ただしやり方としてはいろいろあって、例えば長いベクトルレジスタをいくつかに分割して細かくリネーミングすることで、例えばテール要素はリネームせずに前のレジスタIDを保持することで「値の保持」が実現できるようになる。ただしこの方式の弱点は、リネームテーブルを余計に消費してしまうことである。
- ベクトルのテール要素(つまり演算対象ではないベクトルの後ろの方)をすべてゼロで埋める場合(v0.7.1の仕様)
ベクトルのテールをすべて0で埋める場合には、「ゼロを書き込む」という操作が必要になり結局オーバヘッドが発生する。
ただしこれにも解決方法があって、ある程度のグループで「すべての要素がゼロである(というか、テール要素である)」ビットを付加しておき、そのビットが立っている場合には演算を省略するという方式がある。
さらに、リネームをするタイプの演算であれば、やはりベクトルレジスタグループを細かく分割して、テール要素が含まれているベクトルレジスタグループは常に定数ゼロレジスタにリネームするようにしておけば、コストを省略できる。