前往
大廳
主題

使用 Gem5 X86 架構中的 se.py 模擬,並新增 L3 cache

灰塵 | 2024-01-31 16:49:49 | 巴幣 0 | 人氣 86

如標題所述,這是我修的計算機組織這門課的期末加分題。我就期末為了分數稍微碰一下而已,沒有在這塊鑽研太多,單純紀錄,如有錯誤還請留言糾正。

要改 L3 cache 的直接跳到 5.

我是參考助教的方法安裝並使用 Gem 5,他似乎需要在 Linux 的環境下跑:

1.安裝 VirtualBox 虛擬機 (以下兩個都要下載並安裝)
VirtualBox 7.0.14 platform packages
VirtualBox 7.0.14 Oracle VM VirtualBox Extension Pack

2.下載 Ubuntu 映像檔 (應該只要是Linux就可以,助教用 Ubuntu 我就照做)
- 用映像檔開一個 Ubuntu 虛擬機,記憶體給愈多愈好,Gem5 build 很吃記憶體,CPU核心數能給多的話也能加快速度。硬碟(助教給50GB)也可以給多一點,之後能作為虛擬記憶體(swap)用,我記憶體少所以給個200GB壓壓驚。之後就建立虛擬機然後裝好系統。
- 建議設定讓 Ubuntu 別因閒置自動鎖定,免得 build 到一半自動鎖定?
- 最後參考這篇配多點 swap storage 怕記憶體不夠

3.安裝 Gem5,有任何問題請先參考官方文件
- 開終端機輸入以下指令安裝 Gem5 需要的項目
sudo apt install build-essential git m4 scons zlib1g zlib1g-dev libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev python3-dev python3
- 打以下指令從這裡複製 Gem5 到目錄下
git clone https://github.com/gem5/gem5.git
- 裝 Gem5 需要的 requirements
sudo pip install install -r requirements.txt
- 如果像我一樣記憶體很少,建議打以下指令,讓 Ubuntu 不會因 build 時耗太多記憶體把終端機砍掉
sudo systemctl disable --now systemd-oomd
- 執行以下指令開始 build,j 參數跟CPU核心數有關,詳情請見官方文件
scons build/X86/gem5.opt -j 4
然後我只給得出3GB多的記憶體,swap給50GB,build 得有夠久,應該有5、6小時,記憶體夠應該頂多1、2小時

4.開始模擬
- 以下一行很長的指令是我們加分題要測的,使用 se.py 用參數給的 cache 架構執行 Mibench JPEG Encoder ,用其中的 cjpeg 把 input_small.ppm 轉成 output_small_encode.jpeg,系統模擬的紀錄會在 m5out 中,其中 stats.txt 是模擬後的資訊、config.ini應該是一些配置資訊。
build/X86/gem5.opt configs/deprecated/example/se.py --cmd=../mibench/consumer/jpeg/jpeg-6a/cjpeg --options="-dct int -progressive -opt -outfile output_small_encode.jpeg" --input=../mibench/consumer/jpeg/input_small.ppm --l1i_size=16kB --l1d_size=64kB --cacheline_size=64 --l1d_assoc=2 --caches --l2_size=256kB --l2cache --cpu-type=TimingSimpleCPU
以上可見 --l2cache 是啟用 L2 cache 的意思、--l2_size=256kB 就是 L2 cache 的大小,更多資訊請見
build/X86/gem5.opt configs/deprecated/example/se.py --help
或查官方文件。(Mibench JPEG Encoder 是我修的課指定要測的程式,需額外下載)
- 如果有要求要記錄 stats.txt 裡某些特定資訊,可以在 Gem5 目錄下用 grep 這個指令取得,因為 stats.txt 裡還蠻多資訊的,每次都進去找有點累。以下為 grep 的使用範例:
grep -E '^system.cpu.icache.overallMisses::total ' m5out/stats.txt
grep -E '^system.cpu.icache.overallHits::total ' m5out/stats.txt
grep -E '^system.cpu.dcache.overallMisses::total ' m5out/stats.txt
grep -E '^system.cpu.dcache.overallHits::total ' m5out/stats.txt
grep -E '^system.l2.overallMisses::total ' m5out/stats.txt
grep -E '^system.l2.overallHits::total ' m5out/stats.txt
grep -E '^system.cpu.numCycles ' m5out/stats.txt

5.L3 cache 修改
- 如果你此時嘗試用 --l3cache、--l3_size 等參數會發現他找不到,需要修改一些程式碼才行。
- 我參考了以下兩篇文章才改出來,不過以下兩篇跟實際程式碼有些出入,可能是因為程式更新的關係,或許現在我這篇也跟實際程式碼有些出入。
- 私心推薦裝個vscode,在眾多文件中修改比較方便,改錯也能反悔,也可能是我跟vim和nano不熟。

./config/common/Caches.py 新增
class L3Cache(Cache):
    assoc = 64
    tag_latency = 32
    data_latency = 32
    response_latency =32
    mshrs = 32
    tgts_per_mshr = 24
    write_buffers = 16
以上數值如 latency 可以自行修改,我的加分題是只要能用 L3 就好,就不調整了

./config/common/CacheConfig.py 修改
dcache_class, icache_class, l2_cache_class, walk_cache_class = (
    core.O3_ARM_v7a_DCache,
    core.O3_ARM_v7a_ICache,
    core.O3_ARM_v7aL2,
    None,
)
改成
dcache_class, icache_class, l2_cache_class, walk_cache_class,l3_cache_class = (
    core.O3_ARM_v7a_DCache,
    core.O3_ARM_v7a_ICache,
    core.O3_ARM_v7aL2,
    None,
    core.O3_ARM_v7aL3,
)

./config/common/CacheConfig.py 修改
else:
        dcache_class, icache_class, l2_cache_class, walk_cache_class = (
            L1_DCache,
            L1_ICache,
            L2Cache,
            None,
        )
改成
else:
        dcache_class, icache_class, l2_cache_class, walk_cache_class,l3_cache_class = (
            L1_DCache,
            L1_ICache,
            L2Cache,
            None,
            L3Cache,
        )

./config/common/CacheConfig.py 修改
if options.l2cache:
        # Provide a clock for the L2 and the L1-to-L2 bus here as they
        # are not connected using addTwoLevelCacheHierarchy. Use the
        # same clock as the CPUs.
        system.l2 = l2_cache_class(
            clk_domain=system.cpu_clk_domain, **_get_cache_opts("l2", options)
        )

        system.tol2bus = L2XBar(clk_domain=system.cpu_clk_domain)
        system.l2.cpu_side = system.tol2bus.mem_side_ports
        system.l2.mem_side = system.membus.cpu_side_ports
改成
if options.l2cache and  options.l3cache:
        system.l2 = l2_cache_class(clk_domain=system.cpu_clk_domain,
                                   size=options.l2_size,
                                   assoc=options.l2_assoc)
        system.l3 = l3_cache_class(clk_domain=system.cpu_clk_domain,
                                   size=options.l3_size,
                                   assoc=options.l3_assoc)

        system.tol2bus = L2XBar(clk_domain = system.cpu_clk_domain)
        system.tol3bus = L3XBar(clk_domain = system.cpu_clk_domain)

        system.l2.cpu_side = system.tol2bus.master
        system.l2.mem_side = system.tol3bus.slave

        system.l3.cpu_side = system.tol3bus.master
        system.l3.mem_side = system.membus.slave
elif options.l2cache:
        # Provide a clock for the L2 and the L1-to-L2 bus here as they
        # are not connected using addTwoLevelCacheHierarchy. Use the
        # same clock as the CPUs.
        system.l2 = l2_cache_class(
            clk_domain=system.cpu_clk_domain, **_get_cache_opts("l2", options)
        )

        system.tol2bus = L2XBar(clk_domain=system.cpu_clk_domain)
        system.l2.cpu_side = system.tol2bus.mem_side_ports
        system.l2.mem_side = system.membus.cpu_side_ports

./src/mem/XBar.py 增加
class L3XBar(CoherentXBar):
    # 256-bit crossbar by default
    width = 32

    # Assume that most of this is covered by the cache latencies, with
    # no more than a single pipeline stage for any packet.
    frontend_latency = 1
    forward_latency = 0
    response_latency = 1
    snoop_response_latency = 1

./src/cpu/BaseCPU.py 修改
from m5.objects.XBar import L2XBar
改成
from m5.objects.XBar import L2XBar, L3XBar

./src/cpu/BaseCPU.py 在 class BaseCPU 裡增加
def addThreeLevelCacheHierarchy(self, ic, dc, l3c, iwc = None, dwc = None):
        self.addPrivateSplitL1Caches(ic, dc, iwc, dwc)
        self.toL3Bus = L3XBar()
        self.connectCachedPorts(self.toL3Bus)
        self.l3cache = l3c
        self.toL2Bus.master = self.l3cache.cpu_side
        self._cached_ports = ['l3cache.mem_side']

./configs/common/Options.py 修改
parser.add_argument("--caches", action="store_true")
parser.add_argument("--l2cache", action="store_true")
parser.add_argument("--num-dirs", type=int, default=1)
改成多增加 l3cache
parser.add_argument("--caches", action="store_true")
parser.add_argument("--l2cache", action="store_true")
parser.add_argument("--l3cache", action="store_true")
parser.add_argument("--num-dirs", type=int, default=1)

最後再編譯一次即可(他會編譯修改過的地方,不會像第一次如此久)
scons build/X86/gem5.opt -j 4

之後就能在 se.py 使用 --l3cache、--l3_size 等參數

結果最後我總成績 110+,溢出超多其實根本不需要做加分題,最後也只給99 :(

送禮物贊助創作者 !
0
留言

創作回應

更多創作