前回、SIMDレジスタの全要素に、別なSIMDレジスタの1要素を乗じる形の命令を練習しました。この「全要素に他方の一要素を共通で掛け算」する系統の命令は実に33種あり(前回の3種含む)、忘却力の老人が覚えきれるものではありませぬ。そこで今回は一覧表を作って「整理」してみたのだけれど、ダメだ、こんがらがる。。。
※「ぐだぐだ低レベルプログラミング」投稿順indexはこちら
※実機動作確認には以下を使用しております。
-
- Raspberry Pi 4 model B、Cortex-A72コア(ARMv8-A)
- Raspberry Pi OS (64bit) bullseye
- gcc (Debian 10.2.1-6) 10.2.1 20210110
ARMv8もいろいろレベルがあり、Arm Cortex-A72はARMv8の中でもベーシックな(命令数の少ない)ARMv8p0です。
※A64の最新のマニュアルは以下でダウンロード可能です。
Arm Architecture Reference Manual for A-profile architecture
SIMD by element arithmetic
前回も書きましたが、SIMD演算の場合、各要素毎並列に計算するという通常のスタイルだけでなく、一方のSIMDレジスタの全要素に他方の1要素を作用させるスタイルの計算(多くは積和算)も多用されるじゃないかと思います。前回、MUL、MLA、MLSを練習してますが、一覧表として全て列挙するとこんな形になりました。
multiply | multiply-add | multiply-subtract | |
---|---|---|---|
Int, Unsigned | MUL | MLA | MLS |
Int, Signed long | SMULL, SMULL2 | SMLAL, SMLAL2 | SMLSL, SMLSL2 |
Int, Unsigned long | UMULL, UMULL2 | UMLAL, UMLAL2 | UMLSL, UMLSL2 |
Int, Signed saturating doubling long | SQDMULL, SQDMULL2 | SQDMLAL, SQDMLAL2 | SQDMLSL, SQDMLSL2 |
Int, Signed saturating doubling long HF | SQDMULH | ||
Int, Signed saturating rounding doubling HF | SQRDMULH | SQRDMLAH | SQRDMLSH |
FP, fused | FMLA | FMLS | |
FP, fused long | FMLAL, FMLAL2 | FMLSL, FMLSL2 | |
FP | FMUL | ||
FP, extended | FMULX |
いつもの繰り返しですが書いておきます。「命令多過ぎA64」と。
上記で、注釈を書いておかねばならない部分を列挙すると以下のようです。
-
- long、結果のビット幅が倍幅になるもの
- saturating、オーバーフロー時に表現可能な上限、下限へのサチュレーションが起こるもの
- doubling、結果の値を2倍にするもの
- fused、積和、積差などの演算時に、掛け算と足し算/引き算のそれぞれで丸めをするのではなく、両方を1度に計算した後、まとめて丸めを行うもの
- HF(high halfを勝手に略称)、掛け算の場合、結果は倍のビット幅になるが、その上位半分の幅を結果として返すもの
- rounding、上記のHF処理をするときに下の値を丸めた値を返すもの
- extended、無限大とゼロの計算が「拡張」されているもの。わしゃ知らんよ。どんなときに使うの?
今回は一覧表を作っただけで疲れました。実習は無ね。