opencv / opencv

Open Source Computer Vision Library
https://opencv.org
Apache License 2.0
79.3k stars 55.85k forks source link

OCL sepFilter2D and Scharr freeze for several minutes #26365

Open savuor opened 1 month ago

savuor commented 1 month ago

System Information

OpenCV version: 4.10.0 (appeared earlier?) Device: Nothing Phone 2 OS: Android 14 CPU: Qualcomm Snapdragon 8+ Gen1 iGPU: QUALCOMM Adreno(TM) (OpenCL 3.0 Adreno(TM) 730)

Detailed description

There are two test cases at which cv::sepFilter2D and cv::Scharr() misbehave, i.e. freeze for about 240 secs (Scharr) or 60 secs (sepFilter2D) and quit with wrong results.

In both cases they invoke OpenCL version and freeze at the same place after running col_filter kernel.

The test cases are:

The root cause is still unclear to me:

Steps to reproduce

Build OpenCV for ARM Android, upload binaries to device and run the tests.

CMake flags for build:

WITH_OPENCL : true
ANDROID_ABI : "arm64-v8a"
ANDROID_SDK : "~/Android/Sdk"
ANDROID_NDK : "~/Android/Sdk/ndk/26.1.10909125"
CMAKE_TOOLCHAIN_FILE : "~/Android/Sdk/ndk/26.1.10909125/build/cmake/android.toolchain.cmake"
BUILD_ANDROID_PROJECTS : false

Upload binary:

adb push ${OpenCV_build_directory}/bin/opencv_test_imgproc /data/local/tmp

Run:

adb shell '/data/local/tmp/opencv_test_imgproc --gtest_filter=*OCL_ImageProc/SepFilter2D.Mat/10'
adb shell '/data/local/tmp/opencv_test_imgproc --gtest_filter=*OCL_Filter/Scharr3x3_cols16_rows2.Mat/26'

Issue submission checklist

savuor commented 3 weeks ago

Since the problem seems to be strictly related to a specific OpenCL implementation, I tried to write a better reproducer that contains as less extra code as possible. However, it behaves as a sort of Heisenbug, i.e. changing the source even a little sometimes makes the bug disappear. This means that stripping the reproducer code to its minimum may lead to reproducing some other bug.

So here's a one more reproducer for the separable filter case. It should replace the corresponding test in modules/imgproc/test/ocl/test_sepfilter2d.cpp file.

OCL_TEST_P(SepFilter2D, Mat)
{
    kernelX = cv::Mat{0.054970797, 0.23388229, -0.10257328, 0.13320626, -0.064946003, 0.26863641, 0.085793667, -0.0085192155, -0.047472052};
    kernelY = cv::Mat{0.0089966953, -0.012068954, 0.36833209, -0.14149781, -0.17481904, -0.11397947, -0.18030594};

    Size roiSize(60, 51);

    anchor.x = anchor.y = -1;
    delta = 66.015212;

    src = cv::Mat(roiSize, CV_8UC1, cv::Scalar(0));
    src.copyTo(usrc);

    usrc = cv::UMat(roiSize, CV_8UC1, cv::Scalar(0));
    udst = cv::UMat(roiSize, CV_8UC1, cv::Scalar(0));

    std::cout << "on:" << std::endl;
    cv::ocl::setUseOpenCL(true);
    cv::sepFilter2D(usrc, udst, -1, kernelX, kernelY, anchor, delta, borderType);

    std::cout << "finished" << std::endl;

    std::cout << "before copy..." << std::endl;
    src.copyTo(usrc);
    // this place is reached after some long time
    std::cout << "after copy..." << std::endl;
}