gem5-NVDLA 是 gem5-RTL 的专门版本,旨在与 NVDLA verilog 模型一起使用。对于该项目基于的gem5+RTL框架,请参阅其原始repo gem5-RTL。这里我们展示了gem5+RTL的引用,但是我们重写了安装过程以使其对新手更加友好。
除了针对 NVDLA 专门采用 gem5 内存系统之外,该项目还支持从任何 NVDLA 支持的 caffe NN 模型到 NVDLA 寄存器事务跟踪(即此处的 input.txn 之类的内容)的转换。该转换实用程序的代码和详细用法可以在bsc-util/nvdla_utilities
中找到。
NVDLA(NVIDIA 深度学习加速器)是一个全栈实用程序,展示了行业级加速器的工作原理。随着 2018 年停止维护,公众必须自行使其从编译到运行时都能正常工作。以前,运行 NVDLA 的唯一方法是在 FPGA 上实例化,并使用 NVDLA 提供的编译器和运行时在板上物理运行 NN。然而,这使得内存架构师无法探索人工智能加速器系统中的内存子系统,因为他们需要模拟器来获取不同内存配置的统计数据。因此,本回购协议的目的就是弥合这一差距。一方面,它集成了运行 NVDLA 编译器、运行时和虚拟平台所需的所有未记录错误和用法的解决方案。另一方面,它提供了在模拟器中运行NVDLA的新功能,即应用调度算法、SPM分配和预取机制,这使得能够进一步探索NVDLA。
这里我们列出了除了 gem5 骨架之外的代码结构:
ext/rtl/model_nvdla/
包含NVDLA和嵌入式SPM的包装类( wrapper_nvdla.cc
)以及gem5数据包和NVDLA AXI请求之间转换的逻辑( axiResponder.cc
);src/rtl/rtlNVDLA.cc
将 NVDLA 的行为作为 gem5 对象,例如发送和接收内存请求;src/dev/dma_nvdla.cc
描述 DMA 引擎的行为;bsc-util/
将所有调用 NVDLA 的调度程序放入模拟中;bsc-util/nvdla_utilities/
放置了 NVDLA 的所有编译相关内容,包括单 NVDLA 和多 NVDLA 编译脚本。bsc-util/nvdla_utilities/sweep/
包含用于参数扫描和数据收集的脚本。bsc-util/nvdla_utilities/example_usage/
包括 caffe 模型、编译的寄存器跟踪和多个测试用例的其他日志文件,以及示例扫描参数配置 json 文件。强烈建议在 docker 环境中运行模拟,因为它可以节省安装依赖项的时间和精力。然而,由于以下环境要求,我们面临着将整个流程(即将 Caffe NN 编译为 NVDLA 寄存器跟踪、模拟点创建和模拟)集成到一个 docker 镜像中的困难,因此必须从以下位置运行命令: 2个不同的docker环境以及具有sudo权限的主机:
edwinlai99/advp
容器;edwinlai99/gem5_nvdla_env
容器中)。幸运的是,我们提供了安装了所有依赖项的 docker 映像以及每个阶段的一步脚本(以及在bsc-util/nvdla_utilities/BUILD.md
中构建这些 docker 映像的步骤),以便可以最大程度地减少手动工作。在整个存储库中,每个示例命令都会以(docker_image_name)#
或$
为前缀,以区分运行环境。仅带有#
符号的行是注释。
需要在宿主机上使用 Gurobi,然后修改bsc-util/nvdla_utilities/match_reg_trace_addr/CVSRAMAlloc/Makefile
中的路径。如果未安装,激活固定和混合固定策略将无法正常运行。
我们强烈建议将gem5-nvdla/
和gem5_linux_images/
放在~/
目录下,这样下面命令中的路径和我们预构建的 docker 镜像中的路径变量就不需要额外的修改。如果没有,请检查gem5_nvdla_env
容器中的root/.bashrc
文件。
$ cd ~/
$ git clone https://github.com/suchandler96/gem5-NVDLA.git
$ mv gem5-NVDLA/ gem5-nvdla # simply a rename
$ mkdir nvdla # to put testcases in the steps afterwards
$ cd gem5-nvdla/
$ mkdir ext/rtl/model_nvdla/verilator_nvdla
$ mkdir mnt
$ git apply ban_git_hook_install_Ofast.patch # to prevent a git_hook bug in case of dubious ownership of the repo
$ docker pull edwinlai99/advp:v1
$ docker pull edwinlai99/gem5_nvdla_env:v3
由于该框架运行在gem5的完整系统模式下,因此需要准备linux内核和磁盘映像。一种选择是使用 gem5 doc ARM fs 二进制文件中提供的那些。按以下层次结构组织下载的文件:
~/
|-- gem5_linux_images/
|-- ubuntu-18.04-arm64-docker.img
|-- aarch-system-20220707/
|-- binaries/
|-- disks/
......
如果gem5_linux_images
没有放在~/
目录下:
configs/example/arm/fs_bigLITTLE_RTL.py
中的全局变量default_kernel
和default_disk
也必须相应更改。gem5_nvdla_env
docker 镜像中/root/.bashrc
中的M5_PATH
变量。每次实例化新容器时,都应该修改该变量,或者继续使用相同的容器。nvdla_utilities/sweep/main.py
中 Argparse 参数“disk_image”的默认值。 NVDLA 工作负载是在 gem5 的全系统模式下模拟的,因此应该有一个调用加速器的 CPU 二进制文件。仿真使用的架构是基于ARM的,因此需要交叉编译。二进制文件的源代码位于bsc-util/*.c
,应与aarch64-linux-gnu-g++-9
交叉编译。此外,还应该交叉编译定义特定于 gem5 的操作的汇编文件 ( util/m5/src/abi/arm64/m5op.S
)。因此可以将它们分别编译成 *.o 并将它们链接在一起。一个示例编译过程是:
# The version of cross-compiling toolchain does not matter very much.
It depends on the user's OS version. Since we are tested on Ubuntu 18.04, gcc-7 is used. But gcc-9 may be more convenient on systems >= 20.04
$ sudo apt install gcc-9-aarch64-linux-gnu g++-9-aarch64-linux-gnu
$ cd gem5-nvdla/bsc-util/
$ aarch64-linux-gnu-g++-9 my_validation_nvdla_single_thread.cpp -c -o my_validation_nvdla_single_thread.o -I../include -fPIC -O3 --static -std=c++11
$ aarch64-linux-gnu-g++-9 ../util/m5/src/abi/arm64/m5op.S -c -o m5op.o -I../include -fPIC -O3 --static -std=c++11
$ aarch64-linux-gnu-g++-9 my_validation_nvdla_single_thread.o m5op.o -o my_validation_nvdla_single_thread -fPIC -O3 --static -std=c++11
$ python3 ../util/gem5img.py mount ~/gem5_linux_images/ubuntu-18.04-arm64-docker.img ../mnt
$ sudo mv my_validation_nvdla_single_thread ../mnt/home/
# ... (do the same thing to pipeline_execute scheduler)
# must move to ../mnt/home/ because bsc-util/nvdla_utilities/sweep/main.py will look for the binaries there
gem5_nvdla_env
Docker 容器中构建 gem5 $ docker run --net=host -v ~/:/home -it --rm edwinlai99/gem5_nvdla_env:v3
(gem5_nvdla_env)# cp /usr/local/nvdla/hw/outdir/nv_full/verilator/VNV_nvdla__ALL.a /home/gem5-nvdla/ext/rtl/model_nvdla/verilator_nvdla/
(gem5_nvdla_env)# cp /usr/local/nvdla/hw/outdir/nv_full/verilator/VNV_nvdla.h /home/gem5-nvdla/ext/rtl/model_nvdla/verilator_nvdla/
(gem5_nvdla_env)# cd /home/gem5-nvdla/ext/rtl/model_nvdla/verilator_nvdla/
(gem5_nvdla_env)# mv VNV_nvdla__ALL.a libVNV_nvdla__ALL.a # rename
(gem5_nvdla_env)# cd /home/gem5-nvdla/
# check Makefile to see the number of threads options before compilation
(gem5_nvdla_env)# make nvdla
(gem5_nvdla_env)# exit
请注意,以下命令会将文件写入gem5_linux_images/
中的磁盘映像。
$ mkdir -p ~/nvdla/traces # make a directory to store the simulation files
$ cd ~/gem5-nvdla/bsc-util/nvdla_utilities/sweep/
$ cp -r ../example_usage/traces/lenet ~/nvdla/traces/
$ cp -r ../example_usage/experiments/jsons_tiny/ ~/nvdla/traces/lenet/
$ python3 main.py --jsons-dir ~/nvdla/traces/lenet/jsons_tiny/ --out-dir ~/nvdla/traces/lenet/logs/ --vp-out-dir ~/nvdla/traces/lenet/ --sim-dir /home/lenet/ --model-name lenet --gen-points --num-threads 24 --scheduler my_validation_nvdla_single_thread --home /home
gem5_nvdla_env
Docker 容器中运行模拟并收集结果 $ docker run --net=host -v ~/:/home -it --rm edwinlai99/gem5_nvdla_env:v3
(gem5_nvdla_env)# cd /home/gem5-nvdla/bsc-util/nvdla_utilities/sweep/
(gem5_nvdla_env)# python3 main.py --jsons-dir /home/nvdla/traces/lenet/jsons_tiny/ --out-dir /home/nvdla/traces/lenet/logs/ --vp-out-dir /home/nvdla/traces/lenet/ --sim-dir /home/lenet/ --model-name lenet --run-points --num-threads 24 --scheduler my_validation_nvdla_single_thread
# wait until the simulation ends... It may take roughly 30-60 seconds depending on the computer's performance
(gem5_nvdla_env)# exit
$ cd ~/gem5-nvdla/bsc-util/nvdla_utilities/sweep/
$ python3 get_sweep_stats.py -d ~/nvdla/traces/lenet/logs/ -j ~/nvdla/traces/lenet/jsons_tiny/ -p lenet_test --out-dir ~/
# Then a file named "lenet_test_summary.csv" would appear in ~/
需要一些接近下表的结果:
扫描ID | DMA 启用 | 添加加速私有缓存 | 使用假内存 | pft 启用 | nvdla_cycles[0] | 内存周期[0] |
---|---|---|---|---|---|---|
0 | 错误的 | 错误的 | 错误的 | 真的 | 113221 | 76946 |
1 | 错误的 | 错误的 | 真的 | 真的 | 71137 | 0 |
2 | 错误的 | 真的 | 错误的 | 真的 | 89407 | 48231 |
3 | 真的 | 错误的 | 错误的 | 真的 | 73459 | 31553 |
对于我们示例中提供的其他工作负载,应针对该工作负载再次执行步骤 5-6。如果要编译新的神经网络,另请参阅“编译单个神经网络”和“编译流水线多批次神经网络”部分。对于想要定制我们工具链的用户,请参考bsc-util/nvdla_utilities/BUILD.md
。
我们的框架提供了比 gem5-rtl 和原始 NVDLA verilator 验证流程更好的模拟性能(18x-22x 模拟速度),接近其 C 模型的性能。在理想的内存设置下,Resnet-50可以在2小时内模拟出来。我们的优化包括:
ext/rtl/model_nvdla/verilator_nvdla/axiResponder.hh
);-O3
应用于.v
-> .cpp
编译;-O3 -Ofast
应用于.cpp
-> .a
编译;.cpp
-> .a
编译(额外提高 40%);-Ofast
应用于gem5.fast
的编译;本节提供在bsc-util/nvdla_utilities/example_usage/lenet/
中生成文件的过程。
$ docker run -it --rm -v ~/:/home edwinlai99/advp:v1
(advp)# cd /home/gem5-nvdla/bsc-util/nvdla_utilities/
(advp)# python3.6 caffe2trace.py --model-name lenet --caffemodel example_usage/caffe_models/lenet/lenet_iter_10000.caffemodel --prototxt example_usage/caffe_models/lenet/Lenet.prototxt --out-dir /home/nvdla/traces/lenet/
然后日志文件和*.txn
寄存器跟踪将出现在/home/nvdla/traces/lenet/
中。
我们的存储库提供了一个调度程序,可以将单个模型的多批 NN 推理任务映射到多个模拟 NVDLA 上。因此,该脚本pipeline_compile.py
有助于同时编译多个 prototxt 文件。该脚本期望用户手动将一个 Caffe NN 拆分为多个*.prototxt
文件( *.caffemodel
不需要修改),每个文件对应一个 pipeline stage。这些.prototxt
文件应按管道阶段的顺序提供给脚本。在对管道工作负载进行参数扫描时,用户应在match_reg_trace_addr/remap.py
中使用PipelineRemapper
的子类。使用方法见下图:
$ docker run -it --rm -v ~/:/home edwinlai99/advp:v1
(advp)# cd /home/gem5-nvdla/bsc-util/nvdla_utilities/
(advp)# python3.6 pipeline_compile.py --model-name lenet --caffemodel example_usage/caffe_models/lenet/lenet_iter_10000.caffemodel --prototxts /home/gem5-nvdla/bsc-util/nvdla_utilities/example_usage/traces/lenet_pipeline/stage_1/lenet_stage1.prototxt /home/gem5-nvdla/bsc-util/nvdla_utilities/example_usage/traces/lenet_pipeline/stage_2/lenet_stage2.prototxt --out-dir /home/nvdla/traces/lenet_pipeline/
如果您使用 CLion 作为 IDE,您可以:
configs/
-> 将目录标记为 -> Python 命名空间包。~/gem5-nvdla/configs/
和~/gem5-nvdla/src/python/
到 PYTHONPATH。麻省理工学院