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

RISC-V: support RVV 0.7 in mainline RVV intrinsics #23246

Merged
merged 1 commit into from Feb 20, 2023

Conversation

mshabunin
Copy link
Contributor

@mshabunin mshabunin commented Feb 13, 2023

Recent T-Head GCC have ability to produce RVV 0.7.1 compatible machine code using mainline intrinsics syntax. It makes possible to have single intrinsics implementation for both 0.7 and 1.0 versions (intrin_rvv.hpp, maybe scalable too).

Build and test with RVV 1.0 (non-scalable)

Using one of the following toolchains:

Using one of the following qemu:

cmake \
    -DCMAKE_TOOLCHAIN_FILE=/work/opencv/platforms/linux/riscv64-gcc.toolchain.cmake \
    -DCPU_RVV_FLAGS_ON="-march=rv64gcv" \
    -DRISCV_RVV_SCALABLE=OFF \
    ../opencv
# T-Head qemu
/opt/xuantie-qemu-20221104/bin/qemu-riscv64 \
	-L ${sysroot} \
	-cpu c908v \
	./bin/opencv_test_core
# Collab qemu
/opt/bin/qemu-riscv64 \
    -L ${sysroot} \
    -cpu rv64,v=true,vext_spec=v1.0 \
    ./bin/opencv_test_core

Build and test with RVV 0.7.1 (non-scalable)

Using one of the following toolchains:

Using qemu:

cmake \
    -DCMAKE_TOOLCHAIN_FILE=/work/opencv/platforms/linux/riscv64-gcc.toolchain.cmake \
    -DCPU_RVV_FLAGS_ON="-march=rv64gcv0p7" \
    -DRISCV_RVV_SCALABLE=OFF \
    ../opencv
# T-Head qemu
/opt/xuantie-qemu-20221104/bin/qemu-riscv64 \
	-L ${sysroot} \
        -cpu c906fdv \
	./bin/opencv_test_core

Notes:

  • v_trunc implementation have modified because there is no corresponding _rtz_ intrinsics in 0.7
  • v_absdiff have been reimplemented to avoid using 64-bit types for 32-bit input
  • v_check_ also updated to use 32-bit internally
  • CV_SIMD128_64F guard was missing in some places
  • additional modification in intrin_rvv07.hpp is made to improve support on real HW (C906 / D1 SoC).
force_builders=Custom
build_image:Custom=riscv-gcc-rvv07
test_modules:Custom=core,imgproc,dnn
buildworker:Custom=linux-4
test_timeout:Custom=1200
build_contrib:Custom=OFF

@alalek
Copy link
Member

alalek commented Feb 14, 2023

@mshabunin I added riscv-gcc-rvv07 build image. Please verify build/test logs with your results.

@mshabunin
Copy link
Contributor Author

Which qemu do you use? Why is it -cpu rv64,v=true,vext_spec=v1.0 when the build is for v0p7?

I only tested core and imgproc in Xuantie qemu. I will run the whole testsuite and compare results with yours.

@alalek
Copy link
Member

alalek commented Feb 15, 2023

Please merge build + test steps instructions for different scenarios.
Currently it is unclear from PR's description: there are 2 alternative builds and 2 alternative tests.

@mshabunin
Copy link
Contributor Author

mshabunin commented Feb 16, 2023

Updated the description, also filed an issue to the T-Head toolchain: T-head-Semi/xuantie-gnu-toolchain#5 - apparently toolchain built from sources can not compile OpenCV with RVV 0.7 support, but prebuilt one can.

Also added my Docker-based testing environment: https://github.com/mshabunin/riscv-check

#ifdef __THEAD_VERSION__
# if __riscv_v == 7000 // -march=rv64gcv0p7
# include <fenv.h>
# define CV_RISCV_OLD
Copy link
Member

Choose a reason for hiding this comment

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

CV_RISCV_OLD

This name is unclear.
Please be more specific when and why we use it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Renamed to CV_RVV_THEAD_0_7 and added a comment

@opencv-pushbot opencv-pushbot merged commit 4262127 into opencv:4.x Feb 20, 2023
@mshabunin mshabunin deleted the rvv07-support branch February 20, 2023 18:37
@asmorkalov asmorkalov mentioned this pull request May 31, 2023
@Lzingnow
Copy link

Hello, I want to know if this RVV1.0-compatible opencv can be compiled using the riscv64-unknown-elf toolchain. This is because I downloaded the riscv-gnu-toolchain branch of rvv-next, but after make linux only generated the gcc compiler and no g++.It is not known what caused the problem.

image

@mshabunin
Copy link
Contributor Author

@Lzingnow , I didn't try to build with elf toolchain. Your issue is that you should build linux target. (maybe also add --enable-linux when configuring). Also rvv_next branch is considered obsolete, instead one should use master branch of riscv-gnu-toolchain repository and update gcc submodule to 13.x manually. See the following snippet for example: https://github.com/mshabunin/riscv-check/blob/6d07d13f98cba29bf59a39b7b9de9b1ac39bd4d5/Dockerfile-collab#L34-L48

@Lzingnow
Copy link

Lzingnow commented Aug 13, 2023

Hello, I have successfully installed the rvv-next branch of riscv-gnu-toolchain by following the above procedure. Then, I downloaded the source code for opencv4.8. Build with the following commands:

mkdir build 

cmake .. -DCMAKE_TOOLCHAIN_FILE=../platforms/linux/riscv64-gcc.toolchain.cmake -DCPU_RVV_FLAGS_ON="-march=rv64gcv" -DRISCV_RVV_SCALABLE=OFF  ../

make -j$(nproc)

make install -j$(nproc)

At this point, it indicates that the installation was successful.

Next, I want to write c++ code that calls the opencv library to generate an executable file that can run on a CPU that supports rvv1.0. Specifically, the PULP project's ara project. Here I test the resize function, c++ code is as follows:

#include <opencv2/opencv.hpp>
#include <iostream>

int main() {

    cv::Mat originalImage = cv::Mat(100, 100, CV_8UC3);
    cv::randu(originalImage, cv::Scalar(0, 0, 0), cv::Scalar(255, 255, 255));

    cv::Mat resizedImage;
    cv::resize(originalImage, resizedImage, cv::Size(50, 50), 0, 0, cv::INTER_LINEAR);

    std::cout << "Resized Image:" << std::endl;
    for (int row = 0; row < resizedImage.rows; ++row) {
        for (int col = 0; col < resizedImage.cols; ++col) {
            cv::Vec3b pixel = resizedImage.at<cv::Vec3b>(row, col);
            std::cout << "(" << int(pixel[0]) << "," << int(pixel[1]) << "," << int(pixel[2]) << ") ";
        }
        std::cout << std::endl;
    }

    return 0;
}

The specific compilation options are as follows:

riscv64-unknown-linux-gnu-g++ -march=rv64gcv resize.cpp -o resize.o -I/home/opencv/build/install/include/opencv4 -L/home/ara/opencv/build/install/lib -lopencv_core -lopencv_imgcodecs -lopencv_imgproc

But I did not find the vector instruction after decompilation. May I ask why? The files resize.o and resize.dump are attached.

riscv64-unknown-linux-gnu-objdump -d  resize.o>resize.dump

resize.zip

@mshabunin
Copy link
Contributor Author

Your resize.o does not use vector instructions, try to objdump libopencv_core.a (or .so).

@Lzingnow
Copy link

@mshabunin Thank you very much. I got the executable file containing the vector instructions by setting up static compilation.

But I also have a question about whether the opencv library for rvv1.0 is dependent on the linux operating system and cannot run in bare-mental environment.

This is because I once tried to compile opencv libraries using the elf toolchain, but it failed. But linx-gnu works. On the other hand, I ran the resize executable using linux-gnu statically compiled in a bare-mental environment, and it did not work as expected and reported errors.

@mshabunin
Copy link
Contributor Author

We do not build OpenCV for bare metal environments, it is not supported officially. In general OpenCV uses C/C++ libraries, some POSIX functions and a threading library (pthreads). If your toolchain can provide these interfaces, then perhaps it might work.

@Lzingnow
Copy link

Thank you for your reply.

@Lzingnow
Copy link

Lzingnow commented Sep 5, 2023

@mshabunin

Hello, I would like to know if you have encountered such problems when testing with the rvv-next branch. After compiling the opencv library using the rvv-next branch, I want to test it using qemu. The steps are as follows:

1.Compile qemu: make build-qemu -j8
2.Test opencv:

/opt/bin/qemu-riscv64 \
    -L ${sysroot} \
    -cpu rv64,v=true,vext_spec=v1.0 \
    ./bin/opencv_test_core

But there was an error:

qemu-riscv64: can't apply global rv64-riscv-cpu.v=true: Property 'rv64-riscv-cpu.v' not found
make: *** [Makefile:2: all] Error 1

Then I found another qemu setup for rvv1.0 here: https://lists.riscv.org/g/tech-vector-ext/topic/85564316?p=,,,20,0,0,0::recentpostdate/sticky,,,20,2,0,85564316

  1. Change the cpu option to -cpu rv64,x-v=true,vlen=128,elen=64,vext_spec=v1.0

But there is still one mistake: qemu-riscv64: Unsupported vector spec version 'v1.0'

In addition, I also tried qemu under the master branch, but still got an error: qemu-riscv64: can't apply global rv64-riscv-cpu.x-v=true: Property 'rv64-riscv-cpu.x-v' not found

I don't know how to solve this problem.

@Lzingnow
Copy link

Lzingnow commented Sep 6, 2023

I think I solved the problem, but instead of using qemu under the rvv-next branch, I downloaded it separately.Using qemu-7.1.0:

wget https://download.qemu.org/qemu-7.1.0-rc1.tar.xz
tar xvJf qemu-7.1.0-rc1.tar.xz
cd qemu-7.1.0-rc1
./configure --target-list=riscv64-softmmu,riscv64-linux-user --prefix=/home/dingli/qemu-7.1.0-rc1-riscv64
make -j8
make install -j8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants