31个版本
0.0.38 | 2023年10月10日 |
---|---|
0.0.35 | 2023年9月8日 |
0.0.32 | 2023年7月29日 |
0.0.19 | 2023年3月22日 |
0.0.6 | 2022年11月28日 |
#378 在 性能分析
用于 nvbit-rs
1.5MB
3K SLoC
包含 (静态库,1.5MB) nvbit_release/core/libnvbit.a,(ELF可执行文件/库,64KB) mem_trace.o,(ELF可执行文件/库,24KB) inject_funcs.o
nvbit-rs
试用
make -j -B -C test-apps/
# build the mem trace example tracer
cargo build --release -p mem_trace
# trace a sample application
LD_PRELOAD=./target/release/libmem_trace.so ./test-apps/vectoradd/vectoradd 100
完成
- 实现messagepack和json跟踪转储
- 不工作:清理nvbit api,以便在nvbit-rs中管理上下文,而钩子只是函数
Accelsim参考
make -B -j -C ./tracer_nvbit
LD_PRELOAD=./tracer_nvbit/tracer_tool/tracer_tool.so ./nvbit-sys/nvbit_release/test-apps/vectoradd/vectoradd
这将生成以下文件: ./tracer_nvbit/tracer_tool/traces/kernelslist
和 ./tracer_nvbit/tracer_tool/traces/stats.csv
。
我们的实现
cargo build --release
make -B -j -C ./examples/accelsim
LD_PRELOAD=./target/release/libaccelsim.so ./test-apps/vectoradd/vectoradd 100
LD_PRELOAD=./target/release/libmem_trace.so ./test-apps/vectoradd/vectoradd 100
docker build --platform linux/amd64 -t builder .
docker run --rm -i -v "$PWD":/src -v "$PWD"/buildcache:/cache builder cargo build
nvcc -D_FORCE_INLINES -dc -c -std=c++11 -I../nvbit_release/core -Xptxas -cloning=no -Xcompiler -w -O3 -Xcompiler -fPIC tracer_tool.cu -o tracer_tool.o
nvcc -D_FORCE_INLINES -I../nvbit_release/core -maxrregcount=24 -Xptxas -astoolspatch --keep-device-functions -c inject_funcs.cu -o inject_funcs.o
nvcc -D_FORCE_INLINES -O3 tracer_tool.o inject_funcs.o -L../nvbit_release/core -lnvbit -lcuda -shared -o tracer_tool.so
现在是介绍工作区的好时机,使示例成为带有cargo.toml的独立crate,并使用build.rs为每个示例编写自定义跟踪内核,这样我们最终可以包括符号
TODO - 我们发现Rust和C++互操作性很困难 - 例如 nvbit_get_related_functions
返回 std::vector<CUfunction>
,没有简单的绑定,即使使用 &cxx::CxxVector<CUfunction>
也不行,因为 CUfunction
是一个FFI结构体(按值)。
-
一个可能的方法是提供一个包装器,将其复制到
cxx::Vec<CUfuncton>
,我想(参见 这个示例) -
由于我们正在跟踪,并且需要对每个未见过的函数执行此操作,因此这种复制开销是不可接受的
- TODO:找出它被调用的频率,也许仍然可以这样做并测量
- 更新:get_related_functions 只调用一次,在 rust 中尝试一下
- TODO:找出它被调用的频率,也许仍然可以这样做并测量
-
其他方法:只从通道接收数据,一个简单的结构体...
- 如果那样行得通:我们如何决定使用哪个跟踪函数
- (因为我们不能在 rust 中编写新的函数)
- 如果那样行得通:我们如何决定使用哪个跟踪函数
-
找出是否可以通过使用命名空间来以某种方式重用相同的 nvbit 名称?
-
或者用 rust 包装调用,这些调用调用
ffi::rust_*
函数。 -
重要观察
- 我几乎要放弃
cxx
,因为它只给我Unsupported type
错误 - 我没有在
ffi
模块中导入cxx::UniquePtr
或cxx::CxxVector
,所以我假设我需要使用cxx::
来引用类型。 - 它们在文档中不做这样的事情,但在顶级模块中使用它们...
- 结果是,你 必须 省略
cxx::
前缀,因为这全是宏魔法...
- 我几乎要放弃
完成
- 我们必须以某种方式将 CUDA 注入函数和
nvbit_tool.h
包含到二进制文件中。- 也许可以在构建脚本中静态编译它们
- 然后与
nvbit-sys
crate 链接 - 然后,
nvbit_at_init
应该 被调用 - 希望如此
示例
当前目标是获取一个用 rust 编写的跟踪器的有效示例。使用应该是
# install lld
sudo apt-get install -y lld
# create a shared dynamic library that implements the nvbit hooks
cargo build -p accelsim
# run the nvbit example CUDA application with the tracer
LD_PRELOAD=./target/debug/libaccelsim.so nvbit-sys/nvbit_release/test-apps/vectoradd/vectoradd
备注
检查安装的 clang 版本
apt list --installed | grep clang
当运行 clang nvbit.h
时,它也抱怨缺少 cassert。使用 -std=c++11 -I$(NVBIT_PATH)
是 C++ STL,因此我们需要: clang++ -std=c++11 nvbit.h
。
bindgen
与 C++ 代码配合得不是很好,请查看 这里。
我们还需要一些 clang 东西,这样 bindgen 才能找到 #include <cassert>
。
我们还需要包含 nvbit.h
、nvbit_tool.h
和跟踪注入的函数,这需要将 .cu
文件编译并链接到二进制文件中。
此示例 展示了如何编译和链接 .cu
以与 cc
crate 链接。
确保 nvbit 的 C 函数钩子在共享库中未混淆
nm -D ./target/debug/examples/libtracer.so
nm -D ./target/debug/build/nvbit-sys-08fdef510bde07a0/out/libinstrumentation.a
问题:我们需要在二进制文件中存在 instrument_inst
函数,就像示例一样
nm -D /home/roman/dev/nvbit-sys/tracer_nvbit/tracer_tool/tracer_tool.so | grep instrument
# for a static library:
nm --debug-syms target/debug/build/accelsim-a67c1762e4619dad/out/libinstrumentation.a | grep instrument
目前,它没有 :(
确保我们链接的是静态的
ldd ./target/debug/examples/libtracer.so
检查 cxx 生成了什么包含
tre target/debug/build/nvbit-sys-*/out/cxxbridge/
依赖关系
~0.7–5MB
~91K SLoC