
關於作者
張銀於 2018 年獲得中山大學計算機科學與技術學士學位。他現在是中國科學院軟體研究所智慧軟體研究中心的碩士研究生。他的主要研究方向是編譯技術,特別是 RISC-V ISA 的支援和應用。
這篇文章是谷歌暑期程式設計訓練營 2020 專案的一部分。
OpenCV 在許多硬體平臺上執行,並利用支援 SIMD(單指令多資料)加速的平臺。今天我們將介紹如何將 OpenCV 移植到 RISC-V 並加速其效能。
什麼是 RISC-V 以及為什麼選擇 RISC-V
來自 維基百科
RISC-V 是一種開放標準指令集架構 (ISA),基於已建立的精簡指令集計算機 (RISC) 原則。與大多數其他 ISA 設計不同,RISC-V 在開源許可下提供,無需使用費。許多公司正在提供或已經宣佈推出 RISC-V 硬體,支援 RISC-V 的開源作業系統也已可用,並且多個流行的軟體工具鏈也支援該指令集。
換句話說,與其他一些流行的架構相比,RISC-V 具有免費/開源許可證,並且設計更加簡潔。這些關鍵特性使其有可能在未來得到廣泛應用。由於 OpenCV 的根源在於開放式軟體和硬體,我們非常高興將對 RISC-V 的支援引入該平臺,並將繼續改進它。
最佳化方法
OpenCV 提供了一種便捷的方法,可以將許多最佳化的核心一次性移植到新的 CPU 上,只要該 CPU 支援 SIMD/向量指令即可。我們為此使用了所謂的寬通用行內函數。到目前為止,寬通用行內函數支援多種 SIMD 指令集,例如 x86 和 x64 架構上的 SSE、AVX、AVX2、AVX512,ARM 架構上的 NEON,IBM Power 架構上的 VSX,以及 MIPS 架構上的 MSA。
作者完成的谷歌暑期程式設計訓練營 2020 專案的目標是新增基於 RISC-V 向量擴充套件的寬通用行內函數實現,以便在 RISC-V 架構上實現向量加速。

RISC-V 的“V”(向量)擴充套件 (RVV) 是 RISC-V ISA 的標準擴充套件之一(實際上,RVV 擴充套件仍處於草案階段)。它在基本 RISC-V ISA 中引入了向量暫存器和相應的向量指令,以便程式程式碼可以使用向量架構進行最佳化和加速。
在我們的程式碼中,我們使用 RISC-V 向量擴充套件的本機行內函數來訪問其向量資料型別和向量操作。我們將它們封裝到 OpenCV 的寬通用行內函數中。當 OpenCV 在 RISC-V 平臺上編譯並執行時,OpenCV 演算法使用的寬通用行內函數將被轉換為 RISC-V 向量指令。
OpenCV 中 RISC-V 加速的現狀
目前,我們已經完成了 寬通用行內函數 RISC-V 版本的首次實現。第一個版本已成功由 RISC-V gnu 工具鏈 和 PLCT 提供的 rvv-llvm 版本編譯。當使用 QEMU 在我們的模擬器上進行測試時,此版本已透過所有 HAL(硬體加速層)準確性測試和 11000 多個核心測試(約 99.8% 的核心測試)。
如何在 RISC-V 上編譯和執行 OpenCV
要使用啟用的 RISC-V RVV 最佳化構建 OpenCV,可以使用以下命令在執行在 X64 平臺上的 Ubuntu(在 Ubuntu 18.04 上測試)上交叉編譯 OpenCV。
1. 收集先決條件
apt-get update apt-get install gcc g++ git make cmake python python3 gcc-multilib vim autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev pkg-config libglib2.0-dev
2. 構建 RISC-V GNU 編譯器工具鏈和 QEMU 模擬器
git clone [email protected]:riscv/riscv-gnu-toolchain.git -b rvv-intrinsic cd riscv-gnu-toolchain git submodule update --init --recursive ./configure --prefix=/opt/RISCV --with-arch=rv64gcv_zfh --with-abi=lp64d make linux -j$(nproc) make build-qemu -j$(nproc)
3. 為 RISC-V 構建 OpenCV
git clone [email protected]:opencv/opencv.git cd opencv mkdir build && cd build cmake -DCMAKE_TOOLCHAIN_FILE=../platforms/linux/riscv64-gcc.toolchain.cmake ../ make -j$(nproc)
完成上述命令後,您已成功為 RISC-V 編譯了 OpenCV 庫,並使用了 RVV。現在可以在 RISC-V 平臺上執行程式碼。由於在撰寫本文時沒有合適的硬體,因此可以在剛剛構建的 QEMU 模擬器上執行它。使用以下命令在 QEMU 模擬器上執行準確性測試。
4. 在 QEMU 模擬器上執行準確性測試
/opt/RISCV/bin/qemu-riscv64 -cpu rv64,x-v=true opencv/build/bin/opencv_test_core
未來的工作
記憶體中的向量型別
寬通用行內函數框架最初是基於固定的向量長度設計的。我們今天基於 RISC-V 向量擴充套件的實現是使用 128 位固定向量長度建立的,但 RISC-V 向量擴充套件本身是可擴充套件的。因此,當前版本支援的通用行內函數的向量型別儲存在記憶體中。這對效能有負面影響。
我們看到兩種解決這個問題的方法:
- 設計一個新的寬通用行內函數框架,以適應與向量長度無關的架構。
- 在編譯器端新增對 RVV 的不可擴充套件支援。
效能測試和最佳化
今天展示的實現已經通過了我們的準確性測試。但是,如上所述,此實現以及我們的通用行內函數可能不是最高效的。隨著時間的推移,我們一定會進行更多效能測試,並引入進一步的最佳化。
當然,如果沒有相容的硬體來執行,即使是高度最佳化的程式碼也是無用的。RISC-V 社群正在積極努力完成 RISC-V RVV 規範,我們希望很快看到一些硬體支援。
參考資料和相關連結
- RISC-V 維基百科: https://en.wikipedia.org/wiki/RISC-V
- 實現的拉取請求: https://github.com/opencv/opencv/pull/18228
- 寬通用行內函數: https://docs.opencv.tw/master/df/d91/group__core__hal__intrin.html
- OpenCV 官方倉庫: https://github.com/opencv/opencv
- RISC-V ISA 規範: https://github.com/riscv/riscv-isa-manual
- RISC-V “V” 擴充套件規範: https://github.com/riscv/riscv-v-spec
- RVV 行內函數規範: https://github.com/riscv/rvv-intrinsic-doc
- RISC-V GNU 工具鏈: https://github.com/riscv/riscv-gnu-toolchain
- PLCT 集團的 Rvv-llvm: https://github.com/isrc-cas/rvv-llvm
- 記憶體中問題詳細資訊: https://github.com/riscv/riscv-gnu-toolchain/issues/701






