diff --git a/INSTALL_GUIDE_CN.md b/INSTALL_GUIDE_CN.md index 7114913c..2aa7fb80 100644 --- a/INSTALL_GUIDE_CN.md +++ b/INSTALL_GUIDE_CN.md @@ -36,7 +36,16 @@ > > [CUDA Toolkit 安装](https://developer.nvidia.com/cuda-toolkit), > > [Cudnn 安装](https://developer.nvidia.com/rdp/cudnn-download), > > [Cublas 安装](https://developer.nvidia.com/cublas), - > > 安装完成后请进行相应的环境变量配置,将可执行文件目录与库目录添加到操作系统识别的路径中, + > > 安装完成后请进行相应的环境变量配置,将可执行文件目录与库目录添加到操作系统识别的路径中,例如 + > > ```bash + > > # 将如下内容写入到你的 bashrc 文件并 source 该文件 + > > export CUDA_HOME="/PATH/TO/YOUR/CUDA_HOME" + > > export CUDNN_HOME="/PATH/TO/YOUR/CUDNN_HOME" + > > export PATH="${CUDA_HOME}/bin:${PATH}" + > > export LD_LIBRARY_PATH="${CUDA_HOME}/lib64:${LD_LIBRARY_PATH}" + > > # 如您不方便将上述环境变量配置到 bashrc 文件中进行长期使用,你也可以在我们提供的 env.sh 文件中进行正确配置并激活,作为临时使用 + > > source env.sh + > > ``` 我们强烈建议您规范安装,统一到一个目录下,以免不必要的麻烦。 > 如您的第三方加速卡为寒武纪 MLU,请参考寒武纪官方文档进行: @@ -49,6 +58,8 @@ > > export NEUWARE_HOME="/usr/local/neuware" > > export PATH="${NEUWARE_HOME}/bin:${PATH}" > > export LD_LIBRARY_PATH="${NEUWARE_HOME}/lib64:${LD_LIBRARY_PATH}" + > > # 如您不方便将上述环境变量配置到 bashrc 文件中进行长期使用,你也可以在我们提供的 env.sh 文件中进行正确配置并激活,作为临时使用 + > > source env.sh > > ``` > > 我们强烈建议您规范安装,统一到一个目录下,以免不必要的麻烦。另外请注意,由于 MLU 上层软件建设适配程度有限,如您在其覆盖的机器,操作系统之外运行,需要在安装驱动之后使用上层软件的 Docker。 diff --git a/Makefile b/Makefile index 0edf6c20..c258ac2d 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ install-python: build cp build/$(TYPE)/backend*.so pyinfinitensor/src/pyinfinitensor pip install pyinfinitensor/ -test-cpp: build +test-cpp: @echo cd build/$(TYPE) && make test diff --git a/README_CN.md b/README_CN.md deleted file mode 100644 index 9ff63a02..00000000 --- a/README_CN.md +++ /dev/null @@ -1,259 +0,0 @@ -# 使用指南 - -## 目录 - -- [环境准备](#环境准备) -- [编译本项目](#编译本项目) -- [使用方法](#使用方法) -- [python-前端应用指南](#python-前端应用指南) - - [导入-onnx-模型](#导入-onnx-模型) - - [导出-onnx-模型](#导出-onnx-模型) - - [执行推理](#执行推理) - - [样例代码](#样例代码) -- [技术支持](#技术支持) -- [测试](#测试) - -## 环境准备 - -推荐使用 X86-64 机器以及 Ubuntu-22.04,本文以此环境为例。 - -1. 确认 GCC 版本为 11.3 及以上的稳定版本,如若您的机器 GCC 版本不满足此条件,请自行编译安装,下述方式二选一: - > [GCC 官方文档](https://gcc.gnu.org/onlinedocs/gcc-11.3.0/gcc/) - > [网友安装分享](https://zhuanlan.zhihu.com/p/509695395) -2. 确认 CMake 版本为 3.17 及以上的稳定版本, 如若您的机器 CMake 版本不满足此条件,请自行编译安装,下述方式二选一: - > [CMake 官方文档](https://cmake.org/install/) - > [网友安装分享](https://zhuanlan.zhihu.com/p/110793004) -3. 第三方加速卡软件资源安装,目前本项目已经适配了如下的第三方加速卡: - > 如您的第三方加速卡为英伟达 GPU,请参考英伟达官方文档进行[驱动安装](https://www.nvidia.cn/geforce/drivers/),[CUDA Toolkit 安装](https://developer.nvidia.com/cuda-toolkit),[Cudnn 安装](https://developer.nvidia.com/rdp/cudnn-download),[Cublas 安装](https://developer.nvidia.com/cublas),我们强烈建议您规范安装,统一到一个目录下,以免不必要的麻烦。 - > 如您的第三方加速卡为寒武纪 MLU,请参考寒武纪官方文档进行[驱动安装](https://www.cambricon.com/docs/sdk_1.11.0/driver_5.10.6/user_guide_5.10.6/index.html),[CNToolkit 安装](https://www.cambricon.com/docs/sdk_1.11.0/cntoolkit_3.4.1/cntoolkit_install_3.4.1/index.html),[CNNL 安装](https://www.cambricon.com/docs/sdk_1.11.0/cambricon_cnnl_1.16.1/user_guide/index.html),我们强烈建议您规范安装,统一到一个目录下,以免不必要的麻烦。另外请注意,由于 MLU 上层软件建设适配程度有限,如您在其覆盖的机器,操作系统之外运行,需要在安装驱动之后使用上层软件的 Docker。 -4. 确认您安装了 make,build-essential, python-is-python3, python-dev-is-python3, python3-pip, libdw-dev,如您的机器没有上述基础依赖,请自行按需安装。 - > 在使用 apt-get 工具情况下,您可以这样子执行。 - - ```bash - sudo apt-get install make cmake build-essential python-is-python3 python-dev-is-python3 python3-pip libdw-dev - ``` - - > 其他工具请自行上网搜寻 - -5. 更新pip并切换到清华源 - - ```bash - python -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --upgrade pip - pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple - ``` - -## 编译本项目 - -推荐使用 X86-64 机器以及 Ubuntu-22.04,本文以此环境为例。 - -1. 编译并安装 python 库 - - > 第一次执行会同时安装 python 依赖库,耗时略长,请耐心等待 - - 仅编译 CPU 部分,不编译第三方计算卡: - - ```bash - make install-python - ``` - - 编译 CPU 部分,同时编译英伟达 GPU 部分: - - ```bash - make install-python CUDA=ON - ``` - - 编译 CPU 部分,同时编译寒武纪 MLU 部分: - - ```bash - make install-python BANG=ON - ``` - -## 使用方法 - -项目管理功能已写到 [Makefile](Makefile),支持下列功能: - -- 编译项目:`make`/`make build` -- 清理生成文件:`make clean` -- 安装 python 库:`make install-python` -- 测试 c++ 后端:`make test-cpp` -- 测试 python 前端:`make test-onnx` - -并使用下列环境变量传递选项参数: - -- `TYPE`:编译模式(`debug`/`release`),默认值为 `release` -- `CUDA`:是否编译 CUDA 后端,默认为 `OFF`,`ON` 打开 -- `BANG`:是否编译寒武纪后端,默认为 `OFF`,`ON` 打开 -- `BACKTRACE`:是否启用栈回溯,默认为 `ON`,`OFF` 关闭,建议调试时打开 -- `TEST`:是否编译 `googletest`,默认为 `ON`,`OFF` 关闭,只有 `test-cpp` 时必要 - -## python 前端应用指南 - -`make install-python` 会将项目的 python 前端以 `pyinfinitensor` 为名字安装到系统目录,可以直接 `import pyinfinitensor` 来使用。现阶段,项目的主要用法是从 onnx 导入模型进行优化,然后可以再导出优化后的模型到 onnx,也可以直接运行推理。 - -### 导入 onnx 模型 - -支持的模型: - -- [x] [ResNet18-v2](https://github.com/onnx/models/blob/main/vision/classification/resnet/model/resnet18-v2-7.onnx) -- [x] [DenseNet-121-12](https://github.com/onnx/models/blob/main/vision/classification/densenet-121/model/densenet-12.onnx) -- [x] [Inception-2](https://github.com/onnx/models/blob/main/vision/classification/inception_and_googlenet/inception_v2/model/inception-v2-9.onnx) -- [x] [EfficientNet-Lite4](https://github.com/onnx/models/blob/main/vision/classification/efficientnet-lite4/model/efficientnet-lite4-11.onnx) - -```python -import onnx -from pyinfinitensor.onnx import OnnxStub -from pyinfinitensor import backend - -stub = OnnxStub(onnx.load("model_file"), backend.cpu_runtime()) -``` - -[`onnx.load`](https://onnx.ai/onnx/api/serialization.html#load-a-model) 是 onnx 提供的加载函数,将 onnx 文件读取为保存在内存中的 onnx 模型。 - -`OnnxStub` 是 onnx 模型在项目中的表示,通过构造这个对象,将 onnx 模型导入到项目中。其构造器的第一个参数是 onnx 模型文件;第二个参数是模型运行的后端运行时,可以是 `backend.cpu_runtime()`、`backend.cuda_runtime()` 或 `backend.bang_runtime()`。 - -构造出的 stub 对象可以用于操作项目中的模型和运行时。 - -### 优化 - -TODO - -### 导出 onnx 模型 - -优化后的模型可以导出成 onnx 文件提供给其他运行时。 - -```python -with open("optimized.onnx", "wb") as f: - f.write(stub.to_onnx("optimized").SerializeToString()) -``` - -`stub.to_onnx()` 将模型转换为 onnx 模型对象,`` 将填写到 onnx 模型的 `name` 字段。序列化到文件的代码见[官方示例](https://onnx.ai/onnx/intro/python.html#model-serialization)。 - -要可视化检查导出的模型文件,可以利用 [onnx 提供的功能](https://onnx.ai/onnx/api/shape_inference.html#infer-shapes)将所有的张量的形状推理出来再导出: - -```python -from onnx.shape_inference import infer_shapes - -with open("optimized.onnx", "wb") as f: - f.write(infer_shapes(stub.to_onnx("optimized")).SerializeToString()) -``` - -然后用 [Netron](https://netron.app/) 绘制计算图。 - -### 执行推理 - -也可以使用项目的运行时执行推理。 - -第一步是将数据传入计算图。`OnnxStub.inputs` 是一个 `Dict[str, Tensor]`,保存着模型的所有输入的名字和对象。可以用 [`items()`](https://docs.python.org/zh-cn/3/library/stdtypes.html#dict.items) 来遍历。 - -这个代码片段显示了如何打印出模型所有输入张量的名字、形状和对象指针: - -```python -for name, tensor in stub.inputs.items(): - print(name, tensor.shape(), tensor) -``` - -对于 [resnet18-v2-7.onnx](https://github.com/onnx/models/blob/main/vision/classification/resnet/model/resnet18-v2-7.onnx),会打印出: - -```plaintext -data [1, 3, 224, 224] -``` - -当然,地址是随机的。这个输出表明需要输入一个名为 “data”,形为 1×3×224×224 的数据。通常来说,这表示一张 224×224 的 rgb 图片。而这个模型是一个 1000 分类的图像分类模型。 - -为了方便,这里我们向模型传入一个随机的数据。 - -```python -import numpy - -stub.init() -for name, tensor in stub.inputs.items(): - print(name, tensor.shape(), tensor) - input = numpy.random.random(tensor.shape()).astype(numpy.float32) - tensor.copyin_float(input.flatten().tolist()) -``` - -`stub.init()` 为所有张量分配空间。空间是预分配的,所以不支持动态 size 的模型。 - -`tensor.copyin_float()` 向张量传入数据。其参数必须是一个 `List[float]`,即压平的数据。类似的函数还有 `copyin_int32()` 和 `copyin_int64()` - -然后,调用 `stub.run()` 执行推理: - -```python -stub.run() -``` - -最后,将结果拷贝出来,传入类似: - -```python -stub.init() -for name, tensor in stub.outputs.items(): - print(name, tensor.shape(), tensor) - print(tensor.copyout_float()) -``` - -### 样例代码 - -您可以参照[./example/Resnet/resnet.py](./example/ResNet/resnet.py)的样例代码进行了解,并尝试运行。在这个文件中,我们使用了 Pytorch 构建了 resnet 网络。您可以查阅该脚本使用方式: - -```python -python resnet.py -h -``` - -在样例代码中,我们对定义的网络进行了序列化操作,并存储为模型文件。之后加载该模型文件,并转换为本项目的模型进行优化操作,再进行推理。您可以关注一下代码中 242 行之后的代码。请注意,您可以按照您的需求来进行操作,通常来说,您所需要撰写的代码就是加载模型,转换为本项目的模型进行优化,推理运行。 - -## 技术支持 - -如若您遇到了本项目的问题,请联系我们的技术支持团队 - - -## 测试 - -除了单元测试 `make test-cpp` 和 `make test-onnx` 之外,还可以用其他方式来测试单个模型导入导出和优化的正确性。 - -这个脚本利用 onnxruntime 来测试导出的模型是否与导入的模型等价: - -```python -import onnx -import numpy -import sys -from onnx import ModelProto, ValueInfoProto -from pyinfinitensor.onnx import OnnxStub -from pyinfinitensor import backend -from onnxruntime import InferenceSession - - -def infer(model: ModelProto, input) -> dict: - collection = set() - for node in model.graph.node: - for output in node.output: - collection.add(output) - model.graph.output.extend([ValueInfoProto(name=x) for x in collection]) - session = InferenceSession(model.SerializeToString()) - i = session.get_inputs()[0].name - return dict( - zip( - [x.name for x in session.get_outputs()], - [x.flatten() for x in session.run(None, {i: input})], - ) - ) - - -model0 = onnx.load(sys.argv[1]) -model1 = OnnxStub(model0, backend.cpu_runtime()).to_onnx("new") - -input_shape = [x.dim_value for x in model1.graph.input[0].type.tensor_type.shape.dim] -input = numpy.random.random(input_shape).astype(numpy.float32) - -output0 = infer(model0, input)[model0.graph.output[0].name] -output1 = infer(model1, input)[model1.graph.output[0].name] - -print("error =", sum((output1 - output0) ** 2) / len(output0)) -``` - -要运行脚本,先安装 onnxruntime: - -```bash -pip install onnxruntime -``` - -打印出的 `error = ...` 是两个模型输出张量的均方误差。对于不同的模型,这个误差最小为 0,最大不超过 1e-9。 diff --git a/env.sh b/env.sh index db8a08bf..58e74a86 100644 --- a/env.sh +++ b/env.sh @@ -1,6 +1,8 @@ # 配置英伟达 CUDA 的 HOME 路径,请注意安装 CUDA Toolkit, CUDNN 并将路径配置到下述环境变量。 export CUDA_HOME=/PATH/TO/YOUR/CUDA/HOME export CUDNN_HOME=/PATH/TO/YOUR/CUDNN/HOME +export PATH="${CUDA_HOME}/bin:${PATH}" +export LD_LIBRARY_PATH="${CUDA_HOME}/lib64:${LD_LIBRARY_PATH}" # 配置寒武纪 BANG 的 HOME 路径,请注意 /usr/local/neuware 是寒武纪软件栈建议的,同时也是默认的安装路径。 # 如若用户有其他的路径安装方式,请自行配置正确的路径。 @@ -20,6 +22,8 @@ export CUDNN_HOME=/PATH/TO/YOUR/CUDNN/HOME # ├── share # └── version.txt export NEUWARE_HOME=/usr/local/neuware +export PATH="${NEUWARE_HOME}/bin:${PATH}" +export LD_LIBRARY_PATH="${NEUWARE_HOME}/lib64:${LD_LIBRARY_PATH}" # 配置昆仑芯 XPU 的 HOME 路径,请注意 /usr/local/xpu 是昆仑芯软件栈提供的软件包路径。 # 如若用户有其他的路径安装方式,请自行配置正确的路径。