MN-Core Challenge 振り返り・解説

MN-Core Challenge 振り返り・解説

2024/08/28- 2024/09/23 に開催した MN-Core Challenge の統計や解説の資料です。

Avatar for Preferred Networks

Preferred Networks PRO

September 26, 2024
Tweet

More Decks by Preferred Networks

Other Decks in Programming

Transcript

  1. 8/28 - 9/23 (約1ヶ月) MN-Core Challenge 概要 期間 500名以上 登録者数

    全20問 問題数 MN-Core2 競技性 コードの短さ∝実行速度 * を比較 * MV命令を除く 問題例
  2. 原案、および社内最短との比較 問題名 原案 社内最短 参加者最短 Mul 7 drafear 6行 (nu)

    6行 (sosuupoyo) Abs drafear 14行 (drafear) 13行 (sosuupoyo) FAM 8 drafear 15行 (nu) 15行 (sakeikuratarako) FMul 2 drafear 10行 (nu) 9行 (sosuupoyo) Lesseq drafear 4行 (TumoiYorozu) 4行 (syttrea) Transpose imachi 11行 (TumoiYorozu) 10行 (sosuupoyo) Gather shinh 6行 (gw) 6行 (tails) Square Sum drafear 11行 (nu) 11行 (syttrea) Convert Endian κeen 3行 (nu) 3行 (kik) Mod 3 drafear 10行 (nu) 9行 (logicmachine)
  3. 原案、および社内最短との比較 問題名 原案 社内最短 参加者最短 Matrix Square TumoiYorozu 10行 10行

    (v) Contains drafear 20行 (nu) 20行 (sosuupoyo) Count Up nu 23行 (nu) 26行 (sosuupoyo) Transpose MAB drafear 20行 (drafear) 15行 (sosuupoyo) Inversion Small drafear 11行 (TumoiYorozu) 10行 (tails) Inversion drafear 33行 (nu) 31行 (sosuupoyo) FizzBuzz shinh 53行 (nu) 98行 (tails)
  4. 参加後アンケート 特別賞用アピール 賞金確定者 (2024/9/26時点) 順位賞 最多最短賞 最短賞 100位賞 Par賞 特別賞

    1位 sosuupoyo 2位 logicmachine 3位 tails 4位 sakeikuratarako 5位 angel_p_57 6位 risujiroh 7位 yupiteru 8位 mujc14 9位 v 10位 dnek sosuupoyo (6+2問) Transpose MAB sosuupoyo Inversion Small tails Inversion sosuupoyo FizzBuzz tails ryota2357 アピール受付中 特別賞決定後に決定
  5. • 解説 ◦ Abs ◦ Lesseq ◦ Convert Endian ◦

    Mul 7 ◦ FizzBuzz (参加者より解説) ◦ Transpose MAB • 簡易解説 ◦ Gather ◦ Contains ◦ Inversion Small ◦ Inversion 解説リスト
  6. Abs 22行解 問題 Y = |X| (44長語ぶん) • Y =

    max(0 - X, X) • 0は適当に0初期化された $lr0v などを利用する • スループットは 4長語/2行 isub $lr0v $lm0v $nowrite imax $lm0v $aluf $ln0v ...(計11回)
  7. Abs 問題 Y = |X| (44長語ぶん) • ALU と MAU

    を重ねたい • 入力を眺めてみる 17行解 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 10 -5
  8. Abs 問題 Y = |X| (44長語ぶん) • Float として解釈すると... 17行解

    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1
  9. Abs 問題 Y = |X| (44長語ぶん) • ALU と MAU

    を重ねて計算 • 入力の最大値が小さいので、入力を Float と解釈すると、 X < 0 のとき -inf X ≧ 0 のとき 0 • これを利用して MAU を使って並列にマスク生成 • スループットは 8長語/3行 17行解 isub $lr0v $llm0v $ln0v4; hvpassar $llm0vr $omr1 isub $lr0v $lm2v4 $ln2v4; ipassa $llm0v $lln0v/$llimr1 ...
  10. Abs 問題 Y = |X| (44長語ぶん) 15行解 • ipassa の代わりに

    l1bmd で転送する • 毎回 $ln には書けないので、$lr にも書いて後で2長語転送をする isub $t $lm8v $lr8v; fvpassa $lm8v $omr1; l1bmd $lm8v $lbi; l1bmd $lbi $ln16v/$imr1 isub $t $lm24v $ln24v; fvpassa $lm24v $omr1; l1bmd $lm24v $lbi; l1bmd $lbi $lr8v/$imr1 ... 14行解 • 上のように交互に LM1完成、GRF完成、...、LM1完成、GRF完成 となる • 初手で敢えてLM1に書かずに GRF完成 から始めると最後にうまく重なる
  11. Abs - 14行解 isub $t $lm0v $lr0v; fvpassa $lm0v $omr1;

    l1bmd $lm0v $lbi isub $t $lm16v $ln16v; fvpassa $lm16v $omr1; l1bmd $lm16v $lbi; l1bmd $lbi $lr0v/$imr1 isub $t $lm8v $lr8v; fvpassa $lm8v $omr1; l1bmd $lm8v $lbi; l1bmd $lbi $ln16v/$imr1 isub $t $lm24v $ln24v; fvpassa $lm24v $omr1; l1bmd $lm24v $lbi; l1bmd $lbi $lr8v/$imr1 isub $t $lm32v $lr32v; fvpassa $lm32v $omr1; l1bmd $lm32v $lbi; l1bmd $lbi $ln24v/$imr1 isub $t $lm48v $ln48v; fvpassa $lm48v $omr1; l1bmd $lm48v $lbi; l1bmd $lbi $lr32v/$imr1 isub $t $lm40v $lr40v; fvpassa $lm40v $omr1; l1bmd $lm40v $lbi; l1bmd $lbi $ln48v/$imr1 isub $t $lm56v $ln56v; fvpassa $lm56v $omr1; l1bmd $lm56v $lbi; l1bmd $lbi $lr40v/$imr1 isub $t $lm64v $lr64v; fvpassa $lm64v $omr1; l1bmd $lm64v $lbi; l1bmd $lbi $ln56v/$imr1 isub $t $lm80v $ln80v; fvpassa $lm80v $omr1; l1bmd $lm80v $lbi; l1bmd $lbi $lr64v/$imr1 isub $t $lm72v $lr72v; fvpassa $lm72v $omr1; l1bmd $lm72v $lbi; l1bmd $lbi $ln80v/$imr1 ipassa $llr0v $lln0v; l1bmd $lbi $lr72v/$imr1 ipassa $llr32v $lln32v ipassa $llr64v $lln64v
  12. Lesseq - 問題文中のコード Y = X≧1.0 ? inf : 0

    問題 ERROR imm f"1.0" $lr0/1000 fvadd $lm0v -$aluf $omr1 imm f"inf" $ln0v/$imr1; fvadd $lm8v -$lr0 $omr1 imm f"inf" $ln8v/$imr1; fvadd $lm16v -$lr0 $omr1 imm f"inf" $ln16v/$imr1; fvadd $lm24v -$lr0 $omr1 imm f"inf" $ln24v/$imr1; fvadd $lm32v -$lr0 $omr1 imm f"inf" $ln32v/$imr1 同時にできないのでエラー
  13. Lesseq - 8行解 Y = X≧1.0 ? inf : 0

    問題 8行解 imm f"inf" $ls0/1000 imm f"1.0" $lr0/1000 fvadd $lm0v -$aluf $omr1 ipassa $ls0 $ln0v/$imr1; fvadd $lm8v -$lr0 $omr1 ipassa $ls0 $ln8v/$imr1; fvadd $lm16v -$lr0 $omr1 ipassa $ls0 $ln16v/$imr1; fvadd $lm24v -$lr0 $omr1 ipassa $ls0 $ln24v/$imr1; fvadd $lm32v -$lr0 $omr1 ipassa $ls0 $ln32v/$imr1 即値を予め書いておく
  14. Lesseq - 8行より短くならないか...? • 順位表を見ると4行解がある • どうやっても5行はかかる • 2長語書き込み •

    そういえば FMul 2 で hvadd・hvmul の2長語仕様に悩まされた • hvadd の基本動作: half 4長語 + float 8長語 → float 8長語 8行解 imm f"inf" $ls0/1000 imm f"1.0" $lr0/1000 fvadd $lm0v -$aluf $omr1 ipassa $ls0 $ln0v/$imr1; fvadd $lm8v -$lr0 $omr1 ipassa $ls0 $ln8v/$imr1; fvadd $lm16v -$lr0 $omr1 ipassa $ls0 $ln16v/$imr1; fvadd $lm24v -$lr0 $omr1 ipassa $ls0 $ln24v/$imr1; fvadd $lm32v -$lr0 $omr1 ipassa $ls0 $ln32v/$imr1
  15. Lesseq - 6行解 6行解 imm f"inf" $lls0/ll1000 imm f"1.0" $llr0/ll1000

    fvadd -$aluf $lm0v $omr1 ipassa $ls0 $ln0v/$imr1; hvadd -$llr0r $llm8v $omr1 ipassa $lls0 $lln8v/$llimr1; hvadd -$llr0r $llm24v $omr1 ipassa $lls0 $lln24v/$llimr1
  16. Lesseq - 6行解のその後 6行解 imm f"inf" $lls0/ll1000 imm f"1.0" $llr0/ll1000

    fvadd -$aluf $lm0v $omr1 ipassa $ls0 $ln0v/$imr1; hvadd -$llr0r $llm8v $omr1 ipassa $lls0 $lln8v/$llimr1; hvadd -$llr0r $llm24v $omr1 ipassa $lls0 $lln24v/$llimr1 0 1 1 1 1 1 1 1 1 * * * * * * * * * * * * * * * * * * * * * * * 即値とfvadd重ならないかな +inf 符号=0 指数部=ALL 1 であればよい not($msb1) または decr($msb1)
  17. Lesseq - 5行解 5行解 imm f"1.0" $llr0/ll1000 idec $msb1 $ls0v;

    fvadd -$aluf $lm0v $omr1 ipassa $aluf $ln0v/$imr1; hvadd -$llr0r $llm8v $omr1 ipassa $lls0 $lln8v/$llimr1; hvadd -$llr0r $llm24v $omr1 ipassa $lls0 $lln24v/$llimr1
  18. Lesseq - 4行解に向けて 5行解 imm f"1.0" $llr0/ll1000 idec $msb1 $ls0v;

    fvadd -$aluf $lm0v $omr1 ipassa $aluf $ln0v/$imr1; hvadd -$llr0r $llm8v $omr1 ipassa $lls0 $lln8v/$llimr1; hvadd -$llr0r $llm24v $omr1 ipassa $lls0 $lln24v/$llimr1 消せないか • 即値 1.0 なしで x ≧ 1.0 を判定したい • 2長語を計算したいので MAU を使って判定したい • MAU は A × B + C ≧ 0 を判定してくれる • x2 ± x ≧ 0 くらいしか判定できなそう
  19. Lesseq - 4行解 4行解 idec $msb1 $ls0v; fvfma $lm0v $lm0v

    -$lm0v $omr1 ipassa $aluf $ln0v/$imr1; hvfma $llm8vr $llm8vr -$llm8v $omr1 ipassa $lls0 $lln8v/$llimr1; hvfma $llm24vr $llm24vr -$llm24v $omr1 ipassa $lls0 $lln24v/$llimr1 |x| < 1.0 ⇔ x2 < x ※ただし、x = 0 のときだけ壊れるので、追加制約で除外  また、half への丸めが悪さをするので、追加制約でキリの良い数に
  20. Convert Endian - 考察 問題 64ビット整数のリトルエンディアン表現をビッグエンディアン表現に変換せよ。 8 bits 8 bits

    8 bits 8 bits 8 bits 8 bits 8 bits 8 bits A B C D E F G H H G F E D C B A 8 ビット単位に切って reverse すればよい 8 ビット単位でのデータ移動になる
  21. Convert Endian - 2つだけの場合 8 bits 8 bits A B

    B A 16ビット内で8ビット右にrotate (sbsr命令) すれば完成
  22. Convert Endian - SIMD動作 実はSIMD動作で他も入れ替わっている 8 bits 8 bits 8

    bits 8 bits 8 bits 8 bits 8 bits 8 bits A B C D E F G H B A D C F E H G H G F E D C B A ???
  23. Convert Endian - 考察 8 bits 8 bits 8 bits

    8 bits 8 bits 8 bits 8 bits 8 bits A B C D E F G H B A D C F E H G H G F E D C B A 16 ビット単位で reverse する問題になっていた!
  24. Convert Endian - 6行解 A B C D E F

    G H B A D C F E H G D C B A H G F E H G F E D C B A sbsr ibsr lbsr imm s"8" $lr0/1000 imm i"16" $lr2/1000 imm i"32" $r5/1000 sbsr $lm0v $lr0 $nowrite ibsr $aluf $lr2 $nowrite lbsr $aluf $lr4 $ln0v 6行解
  25. Convert Endian - 4行解 D C B A H G

    F E H G F E D C B A 単語書込 imm s"8" $lr0/1000 imm i"16" $lr2/1000 sbsr $m0v $lr0 $nowrite ibsr $aluf $lr2 $n[1,0,100,100] 4行解
  26. Convert Endian - 3行解に向けて imm i"16" $lr0/1000 imm s"8" $lr2/1000

    ibsr $m0v $lr0 $nowrite sbsr $aluf $lr2 $n[1,0,100,100] imm s"8" $lr0/1000 imm i"16" $lr2/1000 sbsr $m0v $lr0 $nowrite ibsr $aluf $lr2 $n[1,0,100,100] rotate順は任意
  27. Convert Endian - 3行解に向けて imm i"16" $lr0/1000 imm s"8" $lr2/1000

    ibsr $m0v $lr0 $nowrite sbsr $aluf $lr2 $n[1,0,100,100] ここでMAUを使って即値を作るしかない • "16" を使って "8" を作りたい • 下位 4 (5) ビットぶんが "8" ("16") ならOK • 様々な方法が考えられるが、丸めを使う方法を紹介する 0 0 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 Half 仮数部 9bits Float 仮数部 23bits 丸めたら仮数部がここまでになる* (*) 最近接偶数丸めに注意
  28. Convert Endian - 3行解 imm i"0x3f820010" $nowrite ibsr $m0v $aluf

    $nowrite; fvpassar $aluf $nowrite sbsr $aluf $mauf $n[1,0,100,100] 3行解 0 0 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 Half 仮数部 9bits Float 仮数部 23bits 丸めたら仮数部がここまでになる* (*) 最近接偶数丸めに注意
  29. Mul 7 - Par 24行解, 16行解 Y = X ×

    7 (16長語ぶん) 問題 24行解 Y = X + X + ... + X (7要素和) iadd $lm0v $lm0v $nowrite iadd $aluf $lm0v $nowrite iadd $aluf $lm0v $nowrite iadd $aluf $lm0v $nowrite iadd $aluf $lm0v $nowrite iadd $aluf $lm0v $ln0v ... 16行解 Y = X + 2×X + 4×X iadd $lm0v $lm0v $lr0v # 2x iadd $aluf $aluf $nowrite # 4x iadd $aluf $lr0v $nowrite # 6x iadd $aluf $lm0v $ln0v # 7x ...
  30. Mul 7 - 9行解 Y = X × 7 (16長語ぶん)

    問題 9行解 Y = 8×X - X imm i"3" $lr0v ilsl $lm0v $aluf $nowrite # 8x isub $aluf $lm0v $ln0v ...
  31. Mul 7 - 7行解への道のり • これ以上 ALU だけで短くすることは難しそう • ALU

    の横で MAU を使って並列に計算するしかない • itof がSDM の最後に載っているが、 ftoi( itof(X) × 7 ) だと遅い • 仮数部で X×7 を計算して、上位16ビットを捨てる作戦を考える 考察 Float: (-1)符号 × 2指数部-127 × 0b1.仮数部 23bit ※指数部 ALL 0 なら 0 ※指数部 ALL 1 なら -inf or inf
  32. Mul 7 - 7行解への道のり 作戦 仮数部で X×7 を計算して、上位16ビットを捨てる Float: (-1)符号

    × 2指数部-127 × 0b1.仮数部 23bit 適当な符号と指数部 仮数部=X 適当な符号と指数部 仮数部=7X ②どうにかして仮数部を 7倍する ①適当な定数とORをとる ③マスク付きで下位 16ビットだけ書き込む 入力 出力
  33. Mul 7 - 7行解への道のり 223 × 仮数部=X 仮数部=7X ②どうにかして仮数部を 7倍する

    223 × 最下位ビットの重みが 20 になるよう 223 を指数部に選ぶ 7.0 を掛けてみる 7X' - 6×223 = 223 + 7X X' X' = 223 + X 7X' = 7×223 + 7X 指数部を 223 に保ってみる
  34. Mul 7 - 7行解 imm f"7" $ls40v imm f"8388608" $lr40v;

    hvpassar -$aluf $omr1 # 2**23, 下位32bitだけ書き込み有効になるマスク ior $lm0v $aluf $nowrite; fvfma $ls40 $aluf -$aluf $lt # 7*(2**23)-(2**23) = 6*(2**23) ior $lm8v $lr40 $nowrite; fvfma/$imr1 $aluf $ls40 -$mauf $ln0v # 7X'-6*(2**23) ior $lm16v $lr40 $nowrite; fvfma/$imr1 $aluf $ls40 -$lt $ln8v ior $lm24v $lr40 $nowrite; fvfma/$imr1 $aluf $ls40 -$lt $ln16v fvfma/$imr1 $aluf $ls40 -$lt $ln24v 7行解
  35. Mul 7 - 6行解 imm f"7" $ls40v imm f"8388608" $lr40v;

    hvpassar -$aluf $omr1 # 2**23, 下位32bitだけ書き込み有効になるマスク ior $lm0v $aluf $nowrite; fvfma $ls40 $aluf -$aluf $lt # 7*(2**23)-(2**23) = 6*(2**23) ... 仮数部の下の方に影響が出なければ良いので、7 で良い imm f"-7" $ls40v $lr40v sadd $lm0v $aluf $omr1; fvfma $aluf $aluf $aluf $lt # 7*7-7 = 42 ior $lm8v $lr40 $nowrite; fvfma/$imr1 $aluf $ls40 -$mauf $ln0v # 7X'-42 ior $lm16v $lr40 $nowrite; fvfma/$imr1 $aluf $ls40 -$lt $ln8v ior $lm24v $lr40 $nowrite; fvfma/$imr1 $aluf $ls40 -$lt $ln16v fvfma/$imr1 $aluf $ls40 -$lt $ln24v マスク生成を工夫する
  36. Contains 簡易解説 C[i] = A[i] in B ? 1 :

    0 問題 • 入力値の範囲が狭いので、 LM0の空きスペースを使って、 間接参照で D[n] := n in B ? 1 : 0 が作れる • 間接参照で D[A[i]] が取れる • D[A[i]] の結果が MAB,PE 間に散らばっているので、最後に MAB,PE 間縮約を行う • PE間縮約は行列積を使うと速い ◦ halfで行うと BF 化が一部サボれる • MAB間縮約は 0 or 1 で出力できるので、MAB内では 0 or 非ゼロ で良い
  37. 転倒数とは… 「自分より左にいるのに自分より大きい数」なペアの個数。 バブルソートするときの交換回数。 ナイーブに計算すると O(n2)、アルゴリズムを工夫すると O(n log n) だが、 今回の並列計算では

    O(n2) をベースに並列化した方が良い Inversion Small 長さ 16 のULong 配列 A の、転倒数を求めてください。 問題 レイアウト 例 ((8_L2B:1, 8_L1B:1), (16:1); B@[PE,MAB]) [4, 2, 6, 4, 8, 6, 1, 3, 8, 1, 9, 8, 9, 4, 1, 3] → 52
  38. Inversion Small   4 2 6 4 8 6 1

    3 8 1 9 8 9 4 1 3 4   !         ! !   !         ! ! 2 -1           !     !         !   6 -1 -1   !     ! !   !       ! ! ! 4 -1 -1 -1       ! !   !         ! ! 8 -1 -1 -1 -1   ! ! !   !       ! ! ! 6 -1 -1 -1 -1 -1   ! !   !       ! ! ! 1 -1 -1 -1 -1 -1 -1                     3 -1 -1 -1 -1 -1 -1 -1     !         !   8 -1 -1 -1 -1 -1 -1 -1 -1   !       ! ! ! 1 -1 -1 -1 -1 -1 -1 -1 -1 -1               9 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1   !   ! ! ! 8 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1     ! ! ! 9 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1   ! ! ! 4 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1   ! ! 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1     3 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1   !の個数が、転倒数 → 52 個
  39. lpackbit $subpeid $t $omr3; lpackbit $mabid $t $t $ls8v; dmwrite

    $aluf $lx0; l1bmr4liadd $aluf $lbi; imm h"1.5" $ls100v $lr100v; dmread $lx0 $nowrite; l1bmm4 $lbi $nowrite; l1bmd $lmt0 $lb0; ladd $mreadf $lbf $lt; fvpassa -$alufe $s120v; l1bmd $lbi $nowrite; lmax $aluf $ls8v $omr2; lsub/$imr2 $lmt0 $lbf $nowrite; hvpassa $s[100,100,120,120] $lr0v $omr3/$imr2 iand $aluf $lr100v $s[4,5,4,5]/$imr3; hvpassa $s120 $omr4; hmwrite $lr100v $llx0 imm f"524288.0" $lr400v # 2^19 hmfma $lx $ls[0,0,0,4] $aluf $nowrite l1bmrffadd $mauf $lbi l1bmm $lbi $n1/$imr4 # ftoi Inversion Small 社員解(11 lines)
  40. Inversion Small   4 2 6 4 8 6 1

    3 8 1 9 8 9 4 1 3 4   !         ! !   !         ! ! 2 -1           !     !         !   6 -1 -1   !     ! !   !       ! ! ! 4 -1 -1 -1       ! !   !         ! ! 8 -1 -1 -1 -1   ! ! !   !       ! ! ! 6 -1 -1 -1 -1 -1   ! !   !       ! ! ! 1 -1 -1 -1 -1 -1 -1                     3 -1 -1 -1 -1 -1 -1 -1     !         !   8 -1 -1 -1 -1 -1 -1 -1 -1   !       ! ! ! 1 -1 -1 -1 -1 -1 -1 -1 -1 -1               9 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1   !   ! ! ! 8 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1     ! ! ! 9 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1   ! ! ! 4 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1   ! ! 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1     3 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1   レイアウト ((8_L2B:1, 8_L1B:1), (16:1); B@[PE,MAB]) PE0 Cycle 0 PE0 Cycle 1 PE0 Cycle 2 PE0 Cycle 3 PE1 Cycle 0 PE1 Cycle 1 PE1 Cycle 2 PE1 Cycle 3 PE2 Cycle 0 PE2 Cycle 1 PE2 Cycle 2 PE2 Cycle 3 PE3 Cycle 0 PE3 Cycle 1 PE3 Cycle 2 PE3 Cycle 3 MAB 0 MAB 1 MAB 2 MAB 3 MAB 4 MAB 5 MAB 6 MAB 7 MAB 8 MAB 9 MAB10 MAB11 MAB12 MAB13 MAB14 MAB15 16x16 の二次元で考えて、 ・4 PE × 4 Cycle ・16 MAB で並列化して、 ・4 PE × 4 Cycle の縮約 ・16 MAB 間の縮約 をする half の行列積
  41. Inversion Small PE0 Cycle 0 PE0 Cycle 1 PE0 Cycle

    2 PE0 Cycle 3 PE1 Cycle 0 PE1 Cycle 1 PE1 Cycle 2 PE1 Cycle 3 PE2 Cycle 0 PE2 Cycle 1 PE2 Cycle 2 PE2 Cycle 3 PE3 Cycle 0 PE3 Cycle 1 PE3 Cycle 2 PE3 Cycle 3 packbit で $subpeid を 2 倍にしたあと… ・dmwrite → dmread で、PE方向 [0, 2, 4, 6] × 4 Cycle を、Cycle 方向 [0, 1, 2, 3] × 4 PE に ・l1bmr4liadd → l1bmm4 で、peid を更に 4 倍に add すると、T レジスタに [ subpeid * 4 + cycle ] *2 が格納されて、アドレスが完成 4 PE × 4 Cycle のアドレスをつくる lpackbit $subpeid $t $omr3; dmwrite $aluf $lx0; l1bmr4liadd $aluf $lbi; dmread $lx0 $nowrite; l1bmm4 $lbi $nowrite; ladd $mreadf $lbf $lt;
  42. Inversion Small index が j < k なものだけフラグ 転倒していたら、上単語が 0xffff’ffff、違えば

    0 0,1 サイクル目は全書き込み、 2,3 サイクル目は最 初の半語以外を書き込むマスクをつくる $lr100v は half 1.5 = BFed 1.0 h $r100 → $s4 $r102 → $s5 $r104 → $s4 の下半語 $r106 → $s5 の下半語 上三角部で転倒していた場所を 1.0 にして、 「4 PE × 4 Cycle」を「4 PE × 4 half」に押し込む 5 lmax $aluf $ls8v $omr2 6 lsub/$imr2 $lmt0 $lbf $s0v; hvpassa $s[100,100,120,120] $lr0v $omr3/$imr2 7 iand $aluf $lr100v $s[4,5,4,5]/$imr3
  43. Inversion Small $ls4 の「4 PE × 1 LongWord」に収まったので、半精度行列積で 16 値を縮約

    $ls4 には、「1.5 half = 1.0 BFed half」と「0.0 half」が混ざっていることになる。 指数部が違うのでエミュレータがエラーになると思いきや、半精度の場合は「拡張表現」があり、指数 0 も有効値になる。 SDM「3.6.12.12 bfe, bfn - ブロックフロート化命令」「4.4 ブロックフロート化」 半精度ブロックフロート形式には、通常の浮動小数点数の非正規化数のような拡張表現がある。 拡張表現では、指数部が共通指数ではなく全ビット 0 である値を許す。 行列積和 hmfma で 2^19 を足しておくと、最終的に最下位ビットの重みが 1.0 になり 下位半語だけ書き込むマスク /$imr4 をすると ftoi の代わりになる imm f"524288.0" $lr400v # 2^19 hmfma $lx $ls[0,0,0,4] $aluf $nowrite l1bmrffadd $mauf $lbi l1bmm $lbi $n1/$imr4 # ftoi
  44. lpackbit $mabid $t $lmb lpackbit $subpeid $t $t imm ui"0x40000000"

    $lls0 # 2.0f iinc $m1 $nowrite isub $mt4065v8 $aluf $omr1 imm ui"0x3a400000" $r12v/$imr1 hmwrite $alufr $llx0 hmfma $lx $llr0vr $lls0 $nowrite l1bmriiadd $mauf $lbi l1bmm $lbi $n1 Inversion Small tails さんの解答 (10 lines) $lmb (LM0 のベースアドレスレジスタ) を使用し mabid と subpeid を add するのを回避 $mt4065v8:LM はアドレスが mod 4096 で ラップアラウンドされることを利用(次ページ) 0x3a400000 = 0.00048828125 bf (=1/211) 二乗して 2.0f (=0x4000’0000) を加算すると、 2.000000238418334961f = 0x4000'0001 16 PE で iadd(整数和)で縮約すると、 下位の重みだけが残る
  45. Inversion Small MAB 0 MAB 1 MAB 2 MAB 3

    MAB 4 MAB 5 MAB 6 MAB 7 MAB 8 MAB 9 MAB 10 MAB 11 MAB 12 MAB 13 MAB 14 MAB 15 cy0 pe0 4065 4067 4069 4071 4073 4075 4077 4079 4081 4083 4085 4087 4089 4091 4093 4095 cy0 pe1 4067 4069 4071 4073 4075 4077 4079 4081 4083 4085 4087 4089 4091 4093 4095 1 cy0 pe2 4069 4071 4073 4075 4077 4079 4081 4083 4085 4087 4089 4091 4093 4095 1 3 cy0 pe3 4071 4073 4075 4077 4079 4081 4083 4085 4087 4089 4091 4093 4095 1 3 5 cy1 pe0 4073 4075 4077 4079 4081 4083 4085 4087 4089 4091 4093 4095 1 3 5 7 cy1 pe1 4075 4077 4079 4081 4083 4085 4087 4089 4091 4093 4095 1 3 5 7 9 cy1 pe2 4077 4079 4081 4083 4085 4087 4089 4091 4093 4095 1 3 5 7 9 11 cy1 pe3 4079 4081 4083 4085 4087 4089 4091 4093 4095 1 3 5 7 9 11 13 cy2 pe0 4081 4083 4085 4087 4089 4091 4093 4095 1 3 5 7 9 11 13 15 cy2 pe1 4083 4085 4087 4089 4091 4093 4095 1 3 5 7 9 11 13 15 17 cy2 pe2 4085 4087 4089 4091 4093 4095 1 3 5 7 9 11 13 15 17 19 cy2 pe3 4087 4089 4091 4093 4095 1 3 5 7 9 11 13 15 17 19 21 cy3 pe0 4089 4091 4093 4095 1 3 5 7 9 11 13 15 17 19 21 23 cy3 pe1 4091 4093 4095 1 3 5 7 9 11 13 15 17 19 21 23 25 cy3 pe2 4093 4095 1 3 5 7 9 11 13 15 17 19 21 23 25 27 cy3 pe3 4095 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 vs 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 lpackbit $mabid $t $lmb;→ lpackbit $subpeid $t $t;→ $mt4065v8 lpackbit $mabid $t $lmb;→ $m1
  46. Inversion Smallと同じく転倒数を求める問題だが、以下のような違いがある - SmallではPE, MAB間で放送されていたが、こちらはL1B, L2B間で放送されている - 4_PE, 2_W方向に違うテストケースが並んでいるので行列乗算による縮約は不要 -

    配列が大きく1命令の比較では終わらない Inversion 長さ 64 のUInt 配列 A の、転倒数を求めてください。 問題 レイアウト ((16_MAB:1, 4_PE:1, 2_W:1), (64:1); B@[L1B,L2B])
  47. Smallと同じ考え方でL1B, L2Bで分担 L2B内L1B数もチップ内L2B数も両方8 →64x64の三角領域を縦横8ずつ分割 Inversion - 短い命令数で解く方針 (1,0) (2,0) (4,0)

    (2,1) (4,1) (4,2) (4,3) (5,0) (6,0) (5,1) (6,1) (5,2) (6,2) (5,3) (6,3) (3,0) (3,1) (3,2) (7,0) (7,1) (7,2) (7,3) (5,4) (6,4) (6,5) (7,4) (7,5) (7,6) (1,0) (2,0) (4,0) (2,1) (4,1) (4,2) (4,3) (5,0) (6,0) (5,1) (6,1) (5,2) (6,2) (5,3) (6,3) (3,0) (3,1) (3,2) (7,0) (7,1) (7,2) (7,3) (5,4) (6,4) (6,5) (7,4) (7,5) (7,6) 8x8三角領域を 2L1B, 2L2Bで分割する例 一部のL1Bだけ担当領域数が 少し多いがおおむね均等
  48. ipackbit $l2bid $lm0 $lr8 $t imm i"0x4a000000" $ln0 iinc $lmt0v16

    $ls0v; fvmul $aluf $aluf $lr0v l1bmd $lmt64v16 $lbi; ipackbit $l1bid $t $t l1bmd $lbi $ls8v; imin $aluf $lr8 $omr2 imax $lmt0v16 $ls0v $omr1/$imr2 fvadd $lr0v $ln0 $lr0v/$imr1; iinc $ls8v $ls8v imax $lmt64v16 $aluf $omr1/$imr2; l1bmd $aluf $lbi fvpassa/$imr1 $ln0 $ls16v; imax $lmt0 $ls8v $omr1; l1bmd $lbi $lr8v fvadd $lr0v $ln0 $lr0v/$imr1; imax $lmt[0,0,0,96] $ls[2,4,6,14] $omr1 fvadd $ls16v $ln0 $ls16v/$imr1; imax $lmt16 $lr8v $omr1 fvadd $lr0v $ln0 $lr0v/$imr1; imax $lmt[16,16,80,80] $ls[4,6,12,14] $omr1 fvadd $ls16v $ln0 $ls16v/$imr1; imax $lmt32 $lr8v $omr1 fvadd $lr0v $ln0 $lr0v/$imr1; imax $lmt[32,64,64,64] $ls[6,10,12,14] $omr1 fvadd $ls16v $ln0 $ls16v/$imr1; imax $lmt48 $lr8v $omr1 fvadd $lr0v $ln0 $lr0v/$imr1 Inversion - vsm 社員解(33 lines)前半 余分に計算する必要があるかどうかのマスク GRF両面に交互にaccumulation
  49. fvadd $lr0 $ls16 $ls8/0001 fvadd $lr2v $ls18v $lr0v $ls0v fvadd

    $mauf $ls8 $ls8/0010 fvadd $lr0v $ls0 $nowrite fvadd $mauf $ls6v $nowrite l1bmd $mauf $lb0 nop/2 l2bmriiadd $lb64 $lc0 nop mvriiadd/n64 $lc0 $p0@0 mvb/n64 $p0@0 $lc0 nop/2 l2bmb $lc0 $lb192 hvpassa -$ln0 $omr1 l1bmd/$imr1 $lb0 $ln0 Inversion - vsm 社員解(33 lines)後半 サイクル方向の縮約 読めるギリギリのサイクルで足していくことで nop数を減らすことができる L1B, L2B間の縮約
  50. MAB → LM Addr ↓ LM Addr ↓ MAB →

    MAB3, LM Addr1 MAB1, LM Addr3 (16_MAB, 16) → (16, 16_MAB)
  51. Transpose MAB - 考察 • L1BM を介する必要がある • L1BM <=>

    LM 間転送で一番スループットが高いのは l1bmd (gather/distribute) • l1bmd+1 ~ l1bmd+15 を使うと mab をそのぶんだけ等しくずらせる • これを使ってできないか考えてみる
  52. mabdiff でできること MAB0 MAB1 MAB2 MAB3 MAB4 … l1bmd+2 $lm0

    $lbi l1bmd+2 $lbi $ln0 • MABのrotate • 等しく 0~15 ずらせる
  53. 非対角要素 : mabdiffで移動 LM[$mabid + 1 & 15] を l1bmd+1

    で LM[$mabid - 1 & 15] に MAB → LM Addr ↓
  54. 27行解 lpassa $llm0v $llr0v lpassa $llm16v $llr16v lpassa $llr0v $llm32v

    lpassa $llr16v $llm48v lpackbit $mabid $lr100 $lt $lnb nop l1bmd+15 $lmt30 $lbi l1bmd+14 $lmt28 $lbi; l1bmd+15 $lbi $ln2 $lr2 l1bmd+13 $lmt26 $lbi; l1bmd+14 $lbi $ln4 $lr4 l1bmd+12 $lmt24 $lbi; l1bmd+13 $lbi $ln6 $lr6 l1bmd+11 $lmt22 $lbi; l1bmd+12 $lbi $ln8 $lr8 l1bmd+10 $lmt20 $lbi; l1bmd+11 $lbi $ln10 $lr10 l1bmd+9 $lmt18 $lbi; l1bmd+10 $lbi $ln12 $lr12 l1bmd+8 $lmt16 $lbi; l1bmd+9 $lbi $ln14 $lr14 l1bmd+7 $lmt14 $lbi; l1bmd+8 $lbi $ln16 $lr16 l1bmd+6 $lmt12 $lbi; l1bmd+7 $lbi $ln18 $lr18 l1bmd+5 $lmt10 $lbi; l1bmd+6 $lbi $ln20 $lr20 l1bmd+4 $lmt8 $lbi; l1bmd+5 $lbi $ln22 $lr22 l1bmd+3 $lmt6 $lbi; l1bmd+4 $lbi $ln24 $lr24 l1bmd+2 $lmt4 $lbi; l1bmd+3 $lbi $ln26 $lr26 l1bmd+1 $lmt2 $lbi; l1bmd+2 $lbi $ln28 $lr28 l1bmd+1 $lbi $ln30 $lr30/1000 lpassa $lmt0 $ln0 lpassa $lr0v $ln4064v lpassa $lr8v $ln4072v lpassa $lr16v $ln4080v lpassa $lr24v $ln4088v 入力を2倍に広げる 出力を前後から書き 込んで完成させる 出力のイメージ
  55. より短くするには • l1bmd の 4 サイクルぶんを活かせていないので、活かすことによってさらに短く ◦ l1bmd+7 = l1bmd+1

    + l1bmd+2 + l1bmd+4 作戦 ◦ 4_MAB:1 <=> 4:1 と 4_MAB:4 <=> 4:4 の2段階に分ける作戦 ▪ それぞれ 4:4, 4:1 がバッチになるので活かせる ▪ ただし、4_MAB:1 のときは rotate にならなくて、 例えば MAB=0 に来てほしいものが MAB=4 に来て 4 ずれるが、 後の 4_MAB:4 <=> 4:4 によって MAB 4ズレ が LMアドレス 1ズレ になる ◦ 2倍に伸ばすのをやめて、断片を何種類か転送する作戦
  56. sosuupoyo さんの解答 (15行) ipackbit $mabid $ls0 $t $nb; nop l1bmd+1

    $lmt[2,4066,0,0] $lbi; dvpassa $lmt[2,4066,0,0] $ln0/0010 l1bmd+2 $lmt[4,4068,20,4084] $lb128; l1bmd+1 $lbi $ln[4094,30,0,0]/1100 l1bmd+3 $lmt[6,4070,22,4086] $lb0; l1bmd+2 $lbi $ln[4092,28,0,0]/1100 l1bmd+4 $lmt[8,4072,24,4088] $lb512; l1bmd+3 $lbi $ln[4090,26,0,0]/1100 l1bmd+5 $lmt[10,4074,26,4090] $lb384; l1bmd+4 $lbi $ln[4088,24,0,0]/1100 l1bmd+6 $lmt[12,4076,28,4092] $lb896; l1bmd+5 $lbi $ln[4086,22,0,0]/1100 l1bmd+7 $lmt[14,4078,30,4094] $lb768; l1bmd+6 $lbi $ln[4084,20,0,0]/1100 l1bmd+8 $lmt[16,4080,0,0] $lbi; l1bmd+7 $lbi $ln[4082,18,0,0]/1100 l1bmd+9 $lmt[18,4082,0,0] $lbi; l1bmd+8 $lbi $ln[4080,16,0,0]/1100 l1bmd+9/1100 $lbi $ln[4078,14,4078,4078]/1100 l1bmd+8 $lb128 $ln[4074,10,4076,12] l1bmd+8 $lb512 $ln[4070,6,4072,8] l1bmd+8 $lb896 $ln[4066,2,4068,4]