Facetsというのは、Googleがリリースしたデータ解析ツールだ。機械学習に使えるとしており、データを可視化するのが得意で、ダイナミックな動きが特徴のデータ可視化ツールセットとなっている。
これを使って何かできないかと考えたのだが、例えばCPUベンチマークプログラムの結果を投入してプログラムの解析に使えないだろうか?
Facetsを使って解析する内容
RISC-VのRocket Chipを使うと、ベンチマークプログラムのログを取得することが出来る。これをFacetsに投入して、グラフ化してもらうというわけだ。
Rocket-Chipを使うと、以下のようなトレースファイルを取得することが出来る。
C0: 386 [0] pc=[000000081c] W[r 0=0000000000000400][0] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[40044403] lbu s0, 1024(s0) C0: 387 [1] pc=[0000000820] W[r 8=0000000000000000][1] R[r 8=0000000000000000] R[r 1=0000000000000003] inst=[00147413] andi s0, s0, 1 C0: 388 [1] pc=[0000000824] W[r 0=0000000000000000][0] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[02041063] bnez s0, pc + 32 C0: 389 [0] pc=[0000000824] W[r 0=0000000000000000][0] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[02041063] bnez s0, pc + 32 C0: 390 [0] pc=[0000000824] W[r 0=0000000000000000][0] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[02041063] bnez s0, pc + 32 C0: 391 [0] pc=[0000000824] W[r 0=0000000000000000][0] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[02041063] bnez s0, pc + 32 C0: 392 [1] pc=[0000000828] W[r 8=0000000000000000][1] R[r 0=0000000000000000] R[r20=0000000000000003] inst=[f1402473] csrr s0, mhartid C0: 393 [0] pc=[0000000828] W[r 0=0000000000000000][0] R[r 0=0000000000000000] R[r20=0000000000000003] inst=[f1402473] csrr s0, mhartid C0: 394 [0] pc=[0000000828] W[r 0=0000000000000000][0] R[r 0=0000000000000000] R[r20=0000000000000003] inst=[f1402473] csrr s0, mhartid C0: 395 [1] pc=[000000082c] W[r 0=0000000000000400][1] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[40044403] lbu s0, 1024(s0) C0: 396 [0] pc=[000000082c] W[r 0=0000000000000400][0] R[r 8=0000000000000000] R[r 0=0000000000000000] inst=[40044403] lbu s0, 1024(s0)
左から順に、
これを加工して、CSVファイルにしていこう。以下sedコマンドを組んで、|
で区切るcsvファイルを作成した (,を使うとニーモニック中の,と混ざるので避けた)。
sed 's/C0://g' output/dhrystone.riscv.out | grep "\[1\] pc" | sed "s/inst=\(.*\)\] \(.*\)$/\inst=\1| \2/g" | sed 's/\]/|/g' | sed 's/pc=\[//g' | sed 's/W\[//g' | sed 's/R\[//g' | sed 's/inst=\[//g' | sed 's/|\[/| /'g | sed 's/\[/| /g' | sed 's/r *\([0-9]*\)=/\1|/g' > output/dhrystone.riscv.en.csv
これで以下のようなデータセットが出来上がる。
21 | 1| 0000010040| 10|0000000000000000| 1| 0|0000000000000000| 20|b28a1708b379bc0f| f1402573| csrr a0, mhartid 22 | 1| 0000010044| 11|0000000000010044| 1| 0|0000000000000000| 0|0000000000000000| 00000597| auipc a1, 0x0 23 | 1| 0000010048| 11|0000000000010080| 1| 11|0000000000010044| 28|b28a1708b379bc0f| 03c58593| addi a1, a1, 60 24 | 1| 000001004c| 0|fffffff0c1981058| 0| 0|0000000000000000| 5|b28a1708b379bc0f| 10500073| wfi (args unknown) 29 | 1| 0000010050| 0|0000000000010052| 1| 31|000ce533b5bf589f| 29|b28a1708b379bc0f| 0000bff5| j pc - 4 31 | 1| 000001004c| 0|fffffff0c1981058| 0| 0|0000000000000000| 5|b28a1708b379bc0f| 10500073| wfi (args unknown) 36 | 1| 0000010050| 0|0000000000010052| 1| 31|000ce533b5bf589f| 29|b28a1708b379bc0f| 0000bff5| j pc - 4 38 | 1| 000001004c| 0|fffffff0c1981058| 0| 0|0000000000000000| 5|b28a1708b379bc0f| 10500073| wfi (args unknown) 43 | 1| 0000010050| 0|0000000000010052| 1| 31|000ce533b5bf589f| 29|b28a1708b379bc0f| 0000bff5| j pc - 4 45 | 1| 000001004c| 0|fffffff0c1981058| 0| 0|0000000000000000| 5|b28a1708b379bc0f| 10500073| wfi (args unknown) 50 | 1| 0000010050| 0|0000000000010052| 1| 31|000ce533b5bf589f| 29|b28a1708b379bc0f| 0000bff5| j pc - 4 52 | 1| 000001004c| 0|fffffff0c1981058| 0| 0|0000000000000000| 5|b28a1708b379bc0f| 10500073| wfi (args unknown) 57 | 1| 0000010050| 0|0000000000010052| 1| 31|000ce533b5bf589f| 29|b28a1708b379bc0f| 0000bff5| j pc - 4 59 | 1| 000001004c| 0|fffffff0c1981058| 0| 0|0000000000000000| 5|b28a1708b379bc0f| 10500073| wfi (args unknown) 64 | 1| 0000010050| 0|0000000000010052| 1| 31|000ce533b5bf589f| 29|b28a1708b379bc0f| 0000bff5| j pc - 4 66 | 1| 000001004c| 0|fffffff0c1981058| 0| 0|0000000000000000| 5|b28a1708b379bc0f| 10500073| wfi (args unknown) 71 | 1| 0000010050| 0|0000000000010052| 1| 31|000ce533b5bf589f| 29|b28a1708b379bc0f| 0000bff5| j pc - 4 73 | 1| 000001004c| 0|fffffff0c1981058| 0| 0|0000000000000000| 5|b28a1708b379bc0f| 10500073| wfi (args unknown) 99 | 1| 0000000800| 0|0000000000000804| 1| 0|0000000000000000| 12|b28a1708b379bc0f| 00c0006f| j pc + 0xc 101 | 1| 000000080c| 0|0000000000000000| 0| 0|0000000000000000| 31|b28a1708b379bc0f| 0ff0000f| fence 102 | 1| 0000000810| 0|a4f64d88d88675f3| 1| 8|43b5da18a0deb0df| 18|b28a1708b379bc0f| 7b241073| csrw dscratch, s0 107 | 1| 0000000814| 8|0000000000000000| 1| 0|0000000000000000| 20|b28a1708b379bc0f| f1402473| csrr s0, mhartid 110 | 1| 0000000818| 0|0000000000000100| 0| 0|0000000000000000| 8|0000000000000000| 10802023| sw s0, 256(zero) 121 | 1| 000000081c| 0|0000000000000400| 1| 8|0000000000000000| 0|0000000000000000| 40044403| lbu s0, 1024(s0) ...
これをJupyter Notebookに取り込んで、解析してみる。以下のようにフィールドを作成して取り込んだ。
import pandas as pd features = ["Cycle", "Enable", "PC", "Write Addr", "Write Data", "Write Enable", "Read Addr0", "Read Data0", "Read Addr1", "Read Data1", "Instruction", "Mnemonic"] # フィールドを定義する。 jsonstr = pd.read_csv( "dhrystone.riscv.en.csv", names=features, sep=r'\s*\|\s*', # <-- 区切り記号を|に変更する。 engine='python', skiprows=[0], na_values="?").to_json(orient='records')
HTMLにして表示してみよう。
# Display the Dive visualization for this data from IPython.core.display import display, HTML HTML_TEMPLATE = """<link rel="import" href="/nbextensions/facets-dist/facets-jupyter.html"> <facets-dive id="elem" height="600"></facets-dive> <script> var data = {jsonstr}; document.querySelector("#elem").data = data; </script>""" html = HTML_TEMPLATE.format(jsonstr=jsonstr) display(HTML(html))
できた!X軸とY軸をそれぞれ命令のオペランド0のRead Address、Y軸を命令の書き込みアドレスとしてみた。これにどんな意味があるのか分からないけど。
ちなみに、Read AddressもWrite Addressも「実際にそのレジスタにアクセスしているか」とは無関係に作っているのでちょっと解析結果としては微妙だ。もうすこしデータをフィルタリングしないといけないかもしれない。
本当にこの結果が正しいかどうかは置いておいて、
- 読み込みレジスタとしては、reg0 - reg3, reg10 - reg15 が一番よくアクセスが発生する。
- 書き込みデータとしては、reg10-reg13 が一番よくアクセスする。
ってことが分かるかなあ。もうちょっときちんと解析しないと無駄な解析だな。