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

ocl::OpenCLExecutionContext::create(Context&, Device&) fails when device is created independently #20537

Closed
4 tasks done
hedgepigdaniel opened this issue Aug 11, 2021 · 2 comments

Comments

@hedgepigdaniel
Copy link
Contributor

System information (version)
Detailed description

https://docs.opencv.org/4.5.2/d7/d83/classcv_1_1ocl_1_1OpenCLExecutionContext.html#a2890cfb4b198f7621590a2c0de4465fc

Due to the check in _init_device here, ocl::OpenCLExecutionContext::create(Context&, Device&) requires that the device wrapper passed in (i.e. the Device, not just the cl_device_id) is one of the Devices in the Context.

This is not the case if the user does the following:

cl_context context = get_opencl_context_from_outside_opencv();
cl_device_id device = get_opencl_device_from_outside_opencv(context);

ocl::OpenCLExecutionContext opencv_context = ocl::OpenCLExecutionContext::create(
    ocl::Context::fromHandle(context),
    ocl::Device::fromHandle(device));

Despite the underlying OpenCL device ids being the same:

(gdb) n
866	        int ndevices = (int)context_.ndevices();
(gdb) n
867	        CV_Assert(ndevices > 0);
(gdb) print ndevices
$1 = 1
(gdb) n
868	        bool found = false;
(gdb) n
869	        for (int i = 0; i < ndevices; i++)
(gdb) n
871	            ocl::Device d = context_.device(i);
(gdb) n
872	            if (d.getImpl() == device.getImpl())
(gdb) print d
$2 = {p = 0x7fff80003d70}
(gdb) print device
$3 = (const cv::ocl::Device &) @0x7fff9affcce8: {p = 0x7fff80000b60}
(gdb) d.ptr()
Undefined command: "d.ptr".  Try "help".
(gdb) print d.ptr()
$4 = (void *) 0x555555727780
(gdb) print device.ptr()
$5 = (void *) 0x555555727780
(gdb) print device.getImpl()
$6 = (cv::ocl::Device::Impl *) 0x7fff80000b60
(gdb) print d.getImpl()
$7 = (cv::ocl::Device::Impl *) 0x7fff80003d70

The result is an exception:

#0  0x00007ffff698bd22 in raise () from /usr/lib/libc.so.6
#1  0x00007ffff6975862 in abort () from /usr/lib/libc.so.6
#2  0x00007ffff6bcf802 in __gnu_cxx::__verbose_terminate_handler () at /build/gcc/src/gcc/libstdc++-v3/libsupc++/vterminate.cc:95
#3  0x00007ffff6bdbc8a in __cxxabiv1::__terminate (handler=<optimized out>) at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:48
#4  0x00007ffff6bdbcf7 in std::terminate () at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:58
#5  0x00007ffff6bdbf8e in __cxxabiv1::__cxa_throw (obj=<optimized out>, tinfo=0x7ffff7f42878 <typeinfo for cv::Exception>, dest=0x7ffff714a724 <cv::Exception::~Exception()>) at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_throw.cc:95
#6  0x00007ffff714cc17 in cv::error (exc=...) at /home/daniel/code/oss/opencv/modules/core/src/system.cpp:1166
#7  0x00007ffff714cce4 in cv::error (_code=-215, _err="found && \"OpenCL device can't work with passed OpenCL context\"", _func=0x7ffff7b78c41 "_init_device", 
    _file=0x7ffff7b78440 "/home/daniel/code/oss/opencv/modules/core/src/ocl.cpp", _line=879) at /home/daniel/code/oss/opencv/modules/core/src/system.cpp:1178
#8  0x00007ffff70825e9 in cv::ocl::OpenCLExecutionContext::Impl::_init_device (this=0x7fff80002220, device=...) at /home/daniel/code/oss/opencv/modules/core/src/ocl.cpp:879
#9  0x00007ffff7082c2e in cv::ocl::OpenCLExecutionContext::Impl::Impl (this=0x7fff80002220, context=..., device=...) at /home/daniel/code/oss/opencv/modules/core/src/ocl.cpp:913
#10 0x00007ffff70c170d in __gnu_cxx::new_allocator<cv::ocl::OpenCLExecutionContext::Impl>::construct<cv::ocl::OpenCLExecutionContext::Impl, cv::ocl::Context const&, cv::ocl::Device const&> (this=0x7fff96ffcadf, __p=0x7fff80002220)
    at /usr/include/c++/11.1.0/ext/new_allocator.h:156
#11 0x00007ffff70c06e5 in std::allocator_traits<std::allocator<cv::ocl::OpenCLExecutionContext::Impl> >::construct<cv::ocl::OpenCLExecutionContext::Impl, cv::ocl::Context const&, cv::ocl::Device const&> (__a=..., __p=0x7fff80002220)
    at /usr/include/c++/11.1.0/bits/alloc_traits.h:512
#12 0x00007ffff70be81e in std::_Sp_counted_ptr_inplace<cv::ocl::OpenCLExecutionContext::Impl, std::allocator<cv::ocl::OpenCLExecutionContext::Impl>, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<cv::ocl::Context const&, cv::ocl::Device const&> (this=0x7fff80002210, __a=...) at /usr/include/c++/11.1.0/bits/shared_ptr_base.h:519
#13 0x00007ffff70bc63d in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<cv::ocl::OpenCLExecutionContext::Impl, std::allocator<cv::ocl::OpenCLExecutionContext::Impl>, cv::ocl::Context const&, cv::ocl::Device const&> (
    this=0x7fff96ffcc78, __p=@0x7fff96ffcc70: 0x0, __a=...) at /usr/include/c++/11.1.0/bits/shared_ptr_base.h:650
#14 0x00007ffff70b980d in std::__shared_ptr<cv::ocl::OpenCLExecutionContext::Impl, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<cv::ocl::OpenCLExecutionContext::Impl>, cv::ocl::Context const&, cv::ocl::Device const&> (
    this=0x7fff96ffcc70, __tag=...) at /usr/include/c++/11.1.0/bits/shared_ptr_base.h:1337
#15 0x00007ffff70b4d1c in std::shared_ptr<cv::ocl::OpenCLExecutionContext::Impl>::shared_ptr<std::allocator<cv::ocl::OpenCLExecutionContext::Impl>, cv::ocl::Context const&, cv::ocl::Device const&> (this=0x7fff96ffcc70, __tag=...)
    at /usr/include/c++/11.1.0/bits/shared_ptr.h:409
#16 0x00007ffff70af2d5 in std::allocate_shared<cv::ocl::OpenCLExecutionContext::Impl, std::allocator<cv::ocl::OpenCLExecutionContext::Impl>, cv::ocl::Context const&, cv::ocl::Device const&> (__a=...)
    at /usr/include/c++/11.1.0/bits/shared_ptr.h:861
#17 0x00007ffff70a7a4b in std::make_shared<cv::ocl::OpenCLExecutionContext::Impl, cv::ocl::Context const&, cv::ocl::Device const&> () at /usr/include/c++/11.1.0/bits/shared_ptr.h:877
#18 0x00007ffff7084dbe in cv::ocl::OpenCLExecutionContext::create (context=..., device=...) at /home/daniel/code/oss/opencv/modules/core/src/ocl.cpp:1136
Steps to reproduce

You can reproduce with a small modification to the reproduction here: #20518

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 solution
  • I updated to latest OpenCV version and the issue is still there
  • There is reproducer code and related data files: videos, images, onnx, etc
@hedgepigdaniel
Copy link
Contributor Author

replacing

if (d.getImpl() == device.getImpl())

with

if (d.ptr() == device.ptr())

fixes the problem, but results in a net decrease in the reference count of the passed device - because a reference is not kept to it.

@alalek
Copy link
Member

alalek commented Aug 17, 2021

There is a prerequisite that ocl::Context should be created using the passed ocl::Device.

ocl::Device may have the same cl_device handler, but extra OpenCV-specific configuration may be different - e.g. used max work group size (for cases like #13108).

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

No branches or pull requests

2 participants