Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support risc-v platform #910

Merged
merged 28 commits into from
Aug 26, 2022
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions cmake/toolchains/riscv64-linux-gnu.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR riscv)

if(DEFINED ENV{RISCV_ROOT_PATH})
file(TO_CMAKE_PATH $ENV{RISCV_ROOT_PATH} RISCV_ROOT_PATH)
else()
message(FATAL_ERROR "RISCV_ROOT_PATH env must be defined")
endif()

set(CMAKE_C_COMPILER ${RISCV_ROOT_PATH}/bin/riscv64-unknown-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER ${RISCV_ROOT_PATH}/bin/riscv64-unknown-linux-gnu-g++)

set(CMAKE_SYSROOT "${RISCV_ROOT_PATH}/sysroot" CACHE PATH "riscv sysroot")
set(CMAKE_FIND_ROOT_PATH ${RISCV_ROOT_PATH}/riscv64-unknown-linux-gnu)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

set(CMAKE_C_FLAGS "-march=rv64gc")
set(CMAKE_CXX_FLAGS "-march=rv64gc")

# cache flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags")
2 changes: 1 addition & 1 deletion csrc/mmdeploy/backend_ops/ncnn/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ else ()
endif ()


if (NOT ANDROID AND NOT IOS)
if (NOT ANDROID AND NOT IOS AND NOT CMAKE_CROSSCOMPILING)
add_subdirectory(ops)
add_subdirectory(onnx2ncnn)
add_subdirectory(pyncnn_ext)
Expand Down
3 changes: 3 additions & 0 deletions csrc/mmdeploy/net/ppl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@ if (PPLNN_USE_CUDA AND ("cuda" IN_LIST MMDEPLOY_TARGET_DEVICES))
endif ()
target_link_libraries(${PROJECT_NAME}
PRIVATE ${PPLNN_LIBRARIES})
if (PPLNN_USE_RISCV AND ("cpu" IN_LIST MMDEPLOY_TARGET_DEVICES))
target_compile_definitions(${PROJECT_NAME} PRIVATE -DPPL_NN_HAS_RISCV=1)
endif ()
add_library(mmdeploy::pplnn_net ALIAS ${PROJECT_NAME})
17 changes: 17 additions & 0 deletions csrc/mmdeploy/net/ppl/ppl_net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
#include "ppl/nn/engines/cuda/ops.h"
#define PPL_CUDA_IMPORT_FROM_BUFFER 1
#endif
#if PPL_NN_HAS_RISCV
#include "ppl/nn/engines/riscv/engine_factory.h"
#include "ppl/nn/engines/riscv/engine_options.h"
#include "ppl/nn/engines/riscv/ops.h"
#endif

namespace mmdeploy {

Expand Down Expand Up @@ -92,6 +97,18 @@ Result<void> PPLNet::Init(const Value& args) {
engines_.emplace_back(ppl::nn::x86::EngineFactory::Create({}));
}
#endif
#if PPL_NN_HAS_RISCV
if (device_.is_host()) {
ppl::nn::riscv::RegisterBuiltinOpImpls();
ppl::nn::riscv::EngineOptions options{};
// TODO:
// FP16 -> postprocess
options.forward_precision = ppl::common::DATATYPE_FLOAT32;
options.dynamic_tuning_level = 0;
options.winograd_level = 1;
engines_.emplace_back(ppl::nn::riscv::EngineFactory::Create(options));
}
#endif

std::vector<ppl::nn::Engine*> engines;
for (const auto& engine : engines_) {
Expand Down
94 changes: 94 additions & 0 deletions docs/en/01-how-to-build/riscv.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Build for RISC-V

## 1. Install MMDeploy

We need `mmdeploy_onnx2ncnn` program to convert a ncnn model,so we have to install ncnn engine. You can refer to this [doc](./linux-x86_64.md) for installation.

## 2. Test the model

Take Resnet-18 as an example. First refer to [documentation to install mmcls](https://github.com/open-mmlab/mmclassification) to install mmcls. Then use `tools/deploy.py` to convert a model.

```bash
$ export MODEL_CONFIG=/path/to/mmclassification/configs/resnet/resnet18_8xb16_cifar10.py
$ export MODEL_PATH=https://download.openmmlab.com/mmclassification/v0/resnet/resnet18_b16x8_cifar10_20210528-bd6371c8.pth

export PYTHONPATH=${PWD}/service/riscv/client:${NCNN_ROOT}/build/python/ncnn:${PYTHONPATH}
export PATH=${pwd}/build/bin:${PATH}

# Convert the model
$ cd /path/to/mmdeploy
$ python3 tools/deploy.py configs/mmcls/classification_ncnn_static.py $MODEL_CONFIG $MODEL_PATH /path/to/test.png --work-dir resnet18 --device cpu --dump-info

# accuracy test
$ python3 tools/test.py configs/mmcls/classification_ncnn_static.py $MODEL_CONFIG --model reset18/end2end.param resnet18/end2end.bin --metrics accuracy precision f1_score recall
```

## 3. Build SDK

### 1) Download the compiler toolchain and set environment

```bash
# download Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.2.6-20220516.tar.gz
# https://occ.t-head.cn/community/download?id=4046947553902661632
$ tar xf Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.2.6-20220516.tar.gz
$ export RISCV_ROOT_PATH=`realpath Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.2.6`
```

### 2) Compile ncnn & opencv

```bash
# ncnn
# refer to https://github.com/Tencent/ncnn/wiki/how-to-build#build-for-allwinner-d1

# opencv
$ git clone https://github.com/opencv/opencv.git
$ mkdir build && cd build
$ cmake .. \
-DCMAKE_TOOLCHAIN_FILE=/path/to/mmdeploy/cmake/toolchains/riscv64-linux-gnu.cmake \
-DCMAKE_INSTALL_PREFIX=install \
-DBUILD_PERF_TESTS=OFF \
-DBUILD_SHARED_LIBS=OFF \
-DBUILD_TESTS=OFF \
-DCMAKE_BUILD_TYPE=Release
$ make -j$(nproc) && make install
```

### 3) Compile mmdeploy SDK & demo

```bash
$ cd /path/to/mmdeploy
$ mkdir build && cd build
$ cmake .. \
-DMMDEPLOY_BUILD_RISCV_SERVER=ON \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DCMAKE_TOOLCHAIN_FILE=../cmake/toolchains/riscv64-linux-gnu.cmake \
-DMMDEPLOY_BUILD_SDK=ON \
-DMMDEPLOY_SHARED_LIBS=OFF \
-DMMDEPLOY_BUILD_EXAMPLES=ON \
-DMMDEPLOY_TARGET_DEVICES="cpu" \
-DMMDEPLOY_TARGET_BACKENDS="ncnn" \
-Dncnn_DIR=/home/cx/ws/ncnn/build-c906/install/lib/cmake/ncnn/ \
-DMMDEPLOY_CODEBASES=all \
-DOpenCV_DIR=${OpenCV_DIR}/build/install/lib/cmake/opencv4

$ make -j$(nproc) && make install
$ tree -L 1 bin/
.
├── image_classification
├── image_restorer
├── image_segmentation
├── object_detection
├── ocr
├── pose_detection
└── rotated_object_detection
```

### 4) Run the demo

First make sure that`--dump-info`is used during convert model, so that the `resnet18` directory has the files required by the SDK such as `pipeline.json`.

Copy the model folder and executable file to the device.

```bash
./image_classification cpu ./resnet18 tiger.jpeg
```
99 changes: 99 additions & 0 deletions docs/zh_cn/01-how-to-build/riscv.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# 支持 RISC-V

MMDeploy 选择 ncnn 作为 RISC-V 平台下的推理后端,为了使模型运行在 RISC-V 平台,我们需要进行模型转换以及模型部署两个步骤,其中模型转换在 Host 端完成,需要在 Host 端编译 ncnn 以及 MMDeploy,模型部署在 device 端完成,需要对各模块进行交叉编译。
irexyc marked this conversation as resolved.
Show resolved Hide resolved

## 1. 模型转换

a) 安装 MMDeploy

可参考 [BUILD 文档](./linux-x86_64.md),安装 ncnn 推理引擎以及 MMDeploy。

b) 模型转换

以 Resnet-18 为例。先参照[文档](https://github.com/open-mmlab/mmclassification)安装 mmcls,然后使用 `tools/deploy.py` 转换模型。

```bash
$ export MODEL_CONFIG=/path/to/mmclassification/configs/resnet/resnet18_8xb16_cifar10.py
irexyc marked this conversation as resolved.
Show resolved Hide resolved
$ export MODEL_PATH=https://download.openmmlab.com/mmclassification/v0/resnet/resnet18_b16x8_cifar10_20210528-bd6371c8.pth

# 模型转换
$ cd /path/to/mmdeploy
$ python tools/deploy.py \
configs/mmcls/classification_ncnn_static.py \
$MODEL_CONFIG \
$MODEL_PATH \
/path/to/test.png \
irexyc marked this conversation as resolved.
Show resolved Hide resolved
--work-dir resnet18 \
--device cpu \
--dump-info
```

## 2. 模型部署

a) 下载交叉编译工具链,设置环境变量

```bash
# 下载 Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.2.6-20220516.tar.gz
# https://occ.t-head.cn/community/download?id=4046947553902661632
$ tar xf Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.2.6-20220516.tar.gz
$ export RISCV_ROOT_PATH=`realpath Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.2.6`
```

b) 编译 ncnn & opencv

```bash
# ncnn
# 可参考 https://github.com/Tencent/ncnn/wiki/how-to-build#build-for-allwinner-d1

# opencv
$ git clone https://github.com/opencv/opencv.git
$ mkdir build && cd build
$ cmake .. \
-DCMAKE_TOOLCHAIN_FILE=/path/to/mmdeploy/cmake/toolchains/riscv64-linux-gnu.cmake \
-DCMAKE_INSTALL_PREFIX=install \
irexyc marked this conversation as resolved.
Show resolved Hide resolved
-DBUILD_PERF_TESTS=OFF \
-DBUILD_SHARED_LIBS=OFF \
-DBUILD_TESTS=OFF \
-DCMAKE_BUILD_TYPE=Release
$ make -j$(nproc) && make install
```

c) 编译 mmdeploy SDK & demo

```bash
$ cd /path/to/mmdeploy
$ mkdir build && cd build
$ cmake .. \
-DMMDEPLOY_BUILD_RISCV_SERVER=ON \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DCMAKE_TOOLCHAIN_FILE=../cmake/toolchains/riscv64-linux-gnu.cmake \
-DMMDEPLOY_BUILD_SDK=ON \
-DMMDEPLOY_SHARED_LIBS=OFF \
-DMMDEPLOY_BUILD_EXAMPLES=ON \
-DMMDEPLOY_TARGET_DEVICES="cpu" \
-DMMDEPLOY_TARGET_BACKENDS="ncnn" \
-Dncnn_DIR={ncnn_DIR}/build/install/lib/cmake/ncnn/ \
-DMMDEPLOY_CODEBASES=all \
-DOpenCV_DIR=${OpenCV_DIR}/build/install/lib/cmake/opencv4

$ make -j$(nproc) && make install
$ tree -L 1 bin/
irexyc marked this conversation as resolved.
Show resolved Hide resolved
.
├── image_classification
├── image_restorer
├── image_segmentation
├── object_detection
├── ocr
├── pose_detection
└── rotated_object_detection
```

d) 运行 demo

先确认测试模型用了 `--dump-info`,这样 `resnet18` 目录才有 `pipeline.json` 等 SDK 所需文件。

把 dump 好的模型目录、可执行文件拷贝到设备中
irexyc marked this conversation as resolved.
Show resolved Hide resolved

```bash
./image_classification cpu ./resnet18 tiger.jpeg
irexyc marked this conversation as resolved.
Show resolved Hide resolved
```
2 changes: 0 additions & 2 deletions tools/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,6 @@ def parse_args():
'in data config.')
parser.add_argument(
'--uri',
action='store_true',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove these two lines?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think uri is str, and there shoudn't have action='store_true'

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will it affect snpe test?

default='192.168.1.1:60000',
help='Remote ipv4:port or ipv6:port for inference on edge device.')

args = parser.parse_args()
Expand Down