前回、RISC-V Rocket-Chip を使って、コアの基本体力である命令のレイテンシ・スループットを測定する環境作成に取り掛かった。
整数命令についてはおおよそ測定できるようになった。次は浮動小数点命令だ。四則演算など、基本的なところから手を付けて行きたい。
測定用のベンチマークは、少し改造して以下のようになっている。あまり命令間に余計なものが入ってほしくないので、
同じ命令を連続して同じasm volatile
内に並べることにしている。オペランドの数にどうやら制限がある?(asm volatile
では30個以上のオペランドを取ることはできないようだ)ので、そこは分割している。
int benchmark () { float register out0; float register out1; float register out2; float register out3; float register out4; float register out5; float register out6; float register out7; float register out8; float register out9; float register out10; float register out11; float register out12; float register out13; float register out14; float register out15; float register in0_0 = 13334.21358; float register in1_0 = 15871.94397; float register in2_0 = 12938.99489; float register in3_0 = 22206.69387; float register in0_1 = 2078.584430; float register in1_1 = 8601.0001; float register in2_1 = 4256.832673; float register in3_1 = 6706.55472; int i; for (i = 0; i < 32; i++) { asm volatile ( "fadd.s %[w00],%[a00],%[b00]; \n" "fadd.s %[w01],%[a01],%[b01]; \n" "fadd.s %[w02],%[a02],%[b02]; \n" "fadd.s %[w03],%[a03],%[b03]; \n" "fadd.s %[w04],%[a00],%[b00]; \n" "fadd.s %[w05],%[a01],%[b01]; \n" "fadd.s %[w06],%[a02],%[b02]; \n" "fadd.s %[w07],%[a03],%[b03]; \n" "fadd.s %[w08],%[a00],%[b00]; \n" "fadd.s %[w09],%[a01],%[b01]; \n" "fadd.s %[w10],%[a02],%[b02]; \n" "fadd.s %[w11],%[a03],%[b03]; \n" "fadd.s %[w12],%[a00],%[b00]; \n" "fadd.s %[w13],%[a01],%[b01]; \n" "fadd.s %[w14],%[a02],%[b02]; \n" "fadd.s %[w15],%[a03],%[b03]; \n" : [w00] "=f"(out0), [w01] "=f"(out1), [w02] "=f"(out2), [w03] "=f"(out3), [w04] "=f"(out4), [w05] "=f"(out5), [w06] "=f"(out6), [w07] "=f"(out7), [w08] "=f"(out8), [w09] "=f"(out9), [w10] "=f"(out10), [w11] "=f"(out11), [w12] "=f"(out12), [w13] "=f"(out13), [w14] "=f"(out14), [w15] "=f"(out15) : [a00] "f" (in0_0 ), [b00] "f" (in0_1 ), [a01] "f" (in1_0 ), [b01] "f" (in1_1 ), [a02] "f" (in2_0 ), [b02] "f" (in2_1 ), [a03] "f" (in3_0 ), [b03] "f" (in3_1 ) );
さらにベンチマークを取得しようとしてハマってしまったのだが、 RISC-VのFPUは実行前にCSRを操作してEnableにしなければならないらしい。 まあ、その辺はどのCPUアーキテクチャでも一緒なので別に驚くにはあたらないのだが、RISC-Vの場合はそういう情報を探そうとしてどこにも載っていないところだなあ... 結局riscv-testsのベンチマークテストのアセンブリを見ながら見様見真似した。
#define MSTATUS_FS 0x00006000 void start () { asm volatile ("csrs mstatus, %0": :"r"(MSTATUS_FS & (MSTATUS_FS >> 1))); asm volatile ("csrwi fcsr, 0"); asm volatile ("csrw mepc, %0" : :"r"(benchmark)); asm volatile ("mret"); }
ベンチマークを実行するのにmret
をしなければならないかどうかは正直よくわからない。とりあえずこれで動いたから良しとするけど、本当はFCSR
レジスタを設定するだけでアッサリ動いたりするのかなあ。
というわけでベンチマークプログラムを走らせた。まずはスループットだ。ログを確認してみよう。
C0: 730 [1] pc=[00800000ee] W[r 5=000000000000000e][1] R[r15=000000000000000f] R[r31=750f36e9750f36eb] inst=[fff7829b] addiw t0, a5, -1 C0: 731 [1] pc=[00800000f2] W[r 0=000000000000000e][0] R[r 1=000000000000000f] R[r 0=0000000000000000] inst=[0000f153] fadd.s ft2, ft1, ft0 C0: 732 [1] pc=[00800000f6] W[r 0=0000000000000005][0] R[r10=000000000000000f] R[r11=750f36e9750f36eb] inst=[00b571d3] fadd.s ft3, fa0, fa1 C0: 733 [1] pc=[00800000fa] W[r 0=0000000000000003][0] R[r12=000000000000000f] R[r13=750f36e9750f36eb] inst=[00d67253] fadd.s ft4, fa2, fa3 C0: 734 [1] pc=[00800000fe] W[r 0=0000000000000001][0] R[r14=000000000000000f] R[r15=750f36e9750f36eb] inst=[00f772d3] fadd.s ft5, fa4, fa5 C0: 735 [1] pc=[0080000102] W[r 0=000000000000000e][0] R[r 1=000000000000000f] R[r 0=0000000000000000] inst=[0000f353] fadd.s ft6, ft1, ft0 C0: 736 [1] pc=[0080000106] W[r 0=0000000000000005][0] R[r10=000000000000000f] R[r11=750f36e9750f36eb] inst=[00b573d3] fadd.s ft7, fa0, fa1 C0: 737 [1] pc=[008000010a] W[r 0=0000000000000003][0] R[r12=000000000000000f] R[r13=750f36e9750f36eb] inst=[00d67853] fadd.s fa6, fa2, fa3 C0: 738 [1] pc=[008000010e] W[r 0=0000000000000001][0] R[r14=000000000000000f] R[r15=750f36e9750f36eb] inst=[00f778d3] fadd.s fa7, fa4, fa5 C0: 739 [1] pc=[0080000112] W[r 0=000000000000000e][0] R[r 1=000000000000000f] R[r 0=0000000000000000] inst=[0000fe53] fadd.s ft8, ft1, ft0 C0: 740 [1] pc=[0080000116] W[r 0=0000000000000005][0] R[r10=000000000000000f] R[r11=750f36e9750f36eb] inst=[00b57ed3] fadd.s ft9, fa0, fa1 C0: 741 [1] pc=[008000011a] W[r 0=0000000000000003][0] R[r12=000000000000000f] R[r13=750f36e9750f36eb] inst=[00d67f53] fadd.s ft10, fa2, fa3 C0: 742 [1] pc=[008000011e] W[r 0=0000000000000001][0] R[r14=000000000000000f] R[r15=750f36e9750f36eb] inst=[00f77fd3] fadd.s ft11, fa4, fa5 C0: 743 [1] pc=[0080000122] W[r 0=000000000000000e][0] R[r 1=000000000000000f] R[r 0=0000000000000000] inst=[0000f453] fadd.s fs0, ft1, ft0 C0: 744 [1] pc=[0080000126] W[r 0=0000000000000005][0] R[r10=000000000000000f] R[r11=750f36e9750f36eb] inst=[00b574d3] fadd.s fs1, fa0, fa1 C0: 745 [1] pc=[008000012a] W[r 0=0000000000000003][0] R[r12=000000000000000f] R[r13=750f36e9750f36eb] inst=[00d67953] fadd.s fs2, fa2, fa3 C0: 746 [1] pc=[008000012e] W[r 0=0000000000000001][0] R[r14=000000000000000f] R[r15=750f36e9750f36eb] inst=[00f779d3] fadd.s fs3, fa4, fa5 C0: 747 [1] pc=[0080000132] W[r 6=000000000000000d][1] R[r 5=000000000000000e] R[r31=750f36e9750f36eb] inst=[fff2831b] addiw t1, t0, -1 C0: 748 [1] pc=[0080000136] W[r 0=000000000000000e][0] R[r 1=000000000000000f] R[r 0=0000000000000000] inst=[0000f153] fadd.s ft2, ft1, ft0 C0: 749 [1] pc=[008000013a] W[r 0=0000000000000005][0] R[r10=000000000000000f] R[r11=750f36e9750f36eb] inst=[00b571d3] fadd.s ft3, fa0, fa1 C0: 750 [1] pc=[008000013e] W[r 0=0000000000000003][0] R[r12=000000000000000f] R[r13=750f36e9750f36eb] inst=[00d67253] fadd.s ft4, fa2, fa3 C0: 751 [1] pc=[0080000142] W[r 0=0000000000000001][0] R[r14=000000000000000f] R[r15=750f36e9750f36eb] inst=[00f772d3] fadd.s ft5, fa4, fa5 C0: 752 [1] pc=[0080000146] W[r 0=000000000000000e][0] R[r 1=000000000000000f] R[r 0=0000000000000000] inst=[0000f353] fadd.s ft6, ft1, ft0 C0: 753 [1] pc=[008000014a] W[r 0=0000000000000005][0] R[r10=000000000000000f] R[r11=750f36e9750f36eb] inst=[00b573d3] fadd.s ft7, fa0, fa1 C0: 754 [1] pc=[008000014e] W[r 0=0000000000000003][0] R[r12=000000000000000f] R[r13=750f36e9750f36eb] inst=[00d67853] fadd.s fa6, fa2, fa3 C0: 755 [1] pc=[0080000152] W[r 0=0000000000000001][0] R[r14=000000000000000f] R[r15=750f36e9750f36eb] inst=[00f778d3] fadd.s fa7, fa4, fa5
1サイクル毎にfadd.s
命令が発行できていることが分かる。素晴らしい。整数乗算命令は結構遅いのに...
続いて、fadd.s
のレイテンシを図ってみよう。レジスタ依存関係を作ることでレイテンシを測定する。
C0: 2165 [1] pc=[00800001d4] W[r 0=000000000000000a][0] R[r13=0000000000000007] R[r29=750f36e9750f36eb] inst=[01d6ff53] fadd.s ft10, fa3, ft9 C0: 2169 [1] pc=[00800001d8] W[r 0=0000000000000009][0] R[r14=0000000000000007] R[r30=750f36e9750f36eb] inst=[01e77fd3] fadd.s ft11, fa4, ft10 C0: 2173 [1] pc=[00800001dc] W[r 0=0000000000000008][0] R[r15=0000000000000007] R[r31=750f36e9750f36eb] inst=[01f7f453] fadd.s fs0, fa5, ft11 C0: 2174 [1] pc=[00800001e0] W[r11=0000000000000002][1] R[r10=0000000000000003] R[r31=750f36e9750f36eb] inst=[fff5059b] addiw a1, a0, -1 C0: 2175 [1] pc=[00800001e4] W[r 0=0000000000000009][0] R[r11=0000000000000002] R[r12=750f36e9750f36eb] inst=[00c5f553] fadd.s fa0, fa1, fa2 C0: 2179 [1] pc=[00800001e8] W[r 0=000000000000000e][0] R[r13=0000000000000003] R[r10=750f36e9750f36eb] inst=[00a6f053] fadd.s ft0, fa3, fa0 C0: 2183 [1] pc=[00800001ec] W[r 0=000000000000000d][0] R[r14=0000000000000003] R[r 0=0000000000000000] inst=[000770d3] fadd.s ft1, fa4, ft0 C0: 2187 [1] pc=[00800001f0] W[r 0=000000000000000c][0] R[r15=0000000000000003] R[r 1=750f36e9750f36eb] inst=[0017f153] fadd.s ft2, fa5, ft1 C0: 2191 [1] pc=[00800001f4] W[r 0=0000000000000008][0] R[r11=0000000000000003] R[r 2=750f36e9750f36eb] inst=[0025f1d3] fadd.s ft3, fa1, ft2 C0: 2195 [1] pc=[00800001f8] W[r 0=000000000000000e][0] R[r13=0000000000000003] R[r 3=750f36e9750f36eb] inst=[0036f253] fadd.s ft4, fa3, ft3 C0: 2199 [1] pc=[00800001fc] W[r 0=000000000000000d][0] R[r14=0000000000000003] R[r 4=750f36e9750f36eb] inst=[004772d3] fadd.s ft5, fa4, ft4 C0: 2203 [1] pc=[0080000200] W[r 0=000000000000000c][0] R[r15=0000000000000003] R[r 5=750f36e9750f36eb] inst=[0057f353] fadd.s ft6, fa5, ft5 C0: 2207 [1] pc=[0080000204] W[r 0=0000000000000008][0] R[r11=0000000000000003] R[r 6=750f36e9750f36eb] inst=[0065f3d3] fadd.s ft7, fa1, ft6 C0: 2211 [1] pc=[0080000208] W[r 0=000000000000000e][0] R[r13=0000000000000003] R[r 7=750f36e9750f36eb] inst=[0076f853] fadd.s fa6, fa3, ft7 C0: 2215 [1] pc=[008000020c] W[r 0=000000000000000d][0] R[r14=0000000000000003] R[r16=750f36e9750f36eb] inst=[010778d3] fadd.s fa7, fa4, fa6 C0: 2219 [1] pc=[0080000210] W[r 0=000000000000000c][0] R[r15=0000000000000003] R[r17=750f36e9750f36eb] inst=[0117fe53] fadd.s ft8, fa5, fa7 C0: 2223 [1] pc=[0080000214] W[r 0=0000000000000008][0] R[r11=0000000000000003] R[r28=750f36e9750f36eb] inst=[01c5fed3] fadd.s ft9, fa1, ft8 C0: 2227 [1] pc=[0080000218] W[r 0=000000000000000e][0] R[r13=0000000000000003] R[r29=750f36e9750f36eb] inst=[01d6ff53] fadd.s ft10, fa3, ft9 C0: 2231 [1] pc=[008000021c] W[r 0=000000000000000d][0] R[r14=0000000000000003] R[r30=750f36e9750f36eb] inst=[01e77fd3] fadd.s ft11, fa4, ft10 C0: 2235 [1] pc=[0080000220] W[r 0=000000000000000c][0] R[r15=0000000000000003] R[r31=750f36e9750f36eb] inst=[01f7f453] fadd.s fs0, fa5, ft11 C0: 2236 [1] pc=[0080000224] W[r12=0000000000000001][1] R[r11=0000000000000002] R[r31=750f36e9750f36eb] inst=[fff5861b] addiw a2, a1, -1 C0: 2237 [1] pc=[0080000228] W[r 0=0000000000000008][0] R[r11=0000000000000003] R[r12=0000000000000001] inst=[00c5f353] fadd.s ft6, fa1, fa2 C0: 2241 [1] pc=[008000022c] W[r 0=000000000000000e][0] R[r13=0000000000000003] R[r 6=750f36e9750f36eb] inst=[0066f2d3] fadd.s ft5, fa3, ft6 C0: 2245 [1] pc=[0080000230] W[r 0=000000000000000d][0] R[r14=0000000000000003] R[r 5=750f36e9750f36eb] inst=[00577253] fadd.s ft4, fa4, ft5 C0: 2249 [1] pc=[0080000234] W[r 0=000000000000000c][0] R[r15=0000000000000003] R[r 4=750f36e9750f36eb] inst=[0047f1d3] fadd.s ft3, fa5, ft4 C0: 2253 [1] pc=[0080000238] W[r 0=0000000000000008][0] R[r11=0000000000000003] R[r 3=750f36e9750f36eb] inst=[0035f153] fadd.s ft2, fa1, ft3 C0: 2257 [1] pc=[008000023c] W[r 0=000000000000000e][0] R[r13=0000000000000003] R[r 2=750f36e9750f36eb] inst=[0026f0d3] fadd.s ft1, fa3, ft2
1命令実行におおよそ4サイクルかかっている。つまりレイテンシ=4だ。整数乗算より速いじゃないか... ? とりあえず測定できる環境は構築できたので、次はいろんな命令で体力測定をしてみる。