-
Notifications
You must be signed in to change notification settings - Fork 5.9k
Description
cv::cuda::HoughSegmentDetector crashes when used in multiple threads because it uses texture reference.
A texture reference is similar to global memory which is not thread-safe.
The current implementation of HoughSegmentDetector uses texture reference. See here :
| texture<uchar, cudaTextureType2D, cudaReadModeElementType> tex_mask(false, cudaFilterModePoint, cudaAddressModeClamp); |
For CV_CUDEV_ARCH > =300, CUDA implementation should instead use texture objects. This already has been implemented in opencv_contrib but for a different algorithm. Specifically, cv::cuda::createCannyEdgeDetector in this commit : 6ca24c8
I already have an implementation which solves this problem for cv::cuda::HoughSegmentDetector() based on cv::cuda::createCannyEdgeDetector() implementation.
I will submit a PR with this solution shortly.
System information (version)
- OpenCV => 4.5.5-dev
- Operating System / Platform => Ubuntu 18.04
- Compiler => gcc
Detailed description
See above.
Code to reproduce
This code launches 5 threads and each executes probabilistic hough segment detector on a sample image 1000 times.
When two threads are trying to access the texture reference (which behaves similar to global memory), the code crashes.
#include <iostream>
#include <opencv2/opencv.hpp>
#include "opencv2/cudaimgproc.hpp"
#include <pthread.h>
#define NUM_THREADS 5
#define NUM_IMG_PER_THREAD 1000
cv::Mat testImg;
void *findHough(void *threadid) {
uint64_t threadNo = (uint64_t)threadid;
cv::Ptr<cv::cuda::HoughSegmentDetector> hough = cv::cuda::createHoughSegmentDetector(1.0f, (float) (CV_PI / 180.0f), 50, 5);
for(int i=0; i<NUM_IMG_PER_THREAD; i++) {
cv::cuda::Stream stream;
cv::cuda::GpuMat d_lines;
cv::cuda::GpuMat srcImgGpu;
cv::Mat houghLines;
srcImgGpu.upload(testImg, stream);
hough->detect(srcImgGpu, d_lines, stream);
d_lines.download(houghLines, stream);
stream.waitForCompletion();
std::cout << "Thread, " << threadNo << ", index, " << i << ",Found #lines, " << houghLines.cols << std::endl;
}
return NULL;
}
int main()
{
std::cout << "Test case for hough segmentation cuda crash..." << std::endl;
std::cout << "Reading test image..." << std::endl;
testImg = cv::imread("./sample_img/test_img_4k.jpg", cv::IMREAD_GRAYSCALE);
if (testImg.empty()) {
std::cout << "Test image empty." << std::endl;
return -1;
} else {
std::cout << "Test image reading successful." << std::endl;
}
pthread_t threads[NUM_THREADS];
int rc;
uint64_t i;
for( i = 0; i < NUM_THREADS; i++ ) {
rc = pthread_create(&threads[i], NULL, findHough, (void *) i);
if (rc) {
std::cout << "Error:unable to create thread," << rc << std::endl;
exit(-1);
}
}
for (int i = 0; i < NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
Here's the crash log.
root@df29f8235b3a:/src/testdata# ./hough_crash_reproduce
Test case for hough segmentation cuda crash...
Reading test image...
Test image reading successful.
Thread, 4, index, 0,Found #lines, 4096
Thread, 3, index, 0,Found #lines, 4096
Thread, 1, index, 0,Found #lines, 4096
Thread, 0, index, 0,Found #lines, 4096
...
Thread, 4, index, 21,Found #lines, 4096
terminate called after throwing an instance of 'cv::Exception'
what(): OpenCV(4.5.3) /opencv_contrib-4.5.3/modules/cudaimgproc/src/cuda/hough_segments.cu:234: error: (-217:Gpu API call) an illegal memory access was encountered in function 'houghLinesProbabilistic_gpu'
terminate called recursively
terminate called recursively
Aborted (core dumped)
I'm attaching the test image that was used to reproduce the crash. However, any image can be used to reproduce this bug.

Issue submission checklist
- I report the issue, it's not a question
- I checked the problem with documentation, FAQ, open issues,
forum.opencv.org, Stack Overflow, etc and have not found any solution - I updated to the latest OpenCV version and the issue is still there
- There is reproducer code and related data files: videos, images, onnx, etc