FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

Facetsでプロセッサベンチマークソフトウェアの解析を試行した話

Facetsというのは、Googleがリリースしたデータ解析ツールだ。機械学習に使えるとしており、データを可視化するのが得意で、ダイナミックな動きが特徴のデータ可視化ツールセットとなっている。

これを使って何かできないかと考えたのだが、例えばCPUベンチマークプログラムの結果を投入してプログラムの解析に使えないだろうか?

f:id:msyksphinz:20171009194155g:plain

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))

f:id:msyksphinz:20171009195324p:plain

できた!X軸とY軸をそれぞれ命令のオペランド0のRead Address、Y軸を命令の書き込みアドレスとしてみた。これにどんな意味があるのか分からないけど。

ちなみに、Read AddressもWrite Addressも「実際にそのレジスタにアクセスしているか」とは無関係に作っているのでちょっと解析結果としては微妙だ。もうすこしデータをフィルタリングしないといけないかもしれない。

本当にこの結果が正しいかどうかは置いておいて、

  • 読み込みレジスタとしては、reg0 - reg3, reg10 - reg15 が一番よくアクセスが発生する。
  • 書き込みデータとしては、reg10-reg13 が一番よくアクセスする。

ってことが分かるかなあ。もうちょっときちんと解析しないと無駄な解析だな。