Ask Your Question
4

Reentrancy problems

asked 2016-03-15 12:59:21 -0600

pistachio gravatar image

updated 2016-03-15 16:56:50 -0600

Dear OpenCV,

I have version 3.0 on windows 8 embedded (cognex VC5 machine) and I have written 3 threads to process 3 different camera video sequences.

I only call a few openCV functions, the first being cvtColor using BGR2HSV conversion.  I have created a test case with just the three threads and it 'appears' as there is some form of reentrancy issue.  each thread is completely separate, no shared data, and for the test I just create an test matrix (filled with zeros or whatever)

By executing the code on only one thread and not running the other two it runs fine, and when I run all three threads it 'sometimes' works too, but more often causes an assertion.

 It is not specific to the cvtcolor function, however it happens there a lot, I use a few others and they are causing an assertion as well.

As I had to build the openCV for my platform, is there any particular build options I need to set to have the code compile to properly support 'thread safe' results?

Thanks.

Upon examining this it appears that openCV is not re-entrant on initialization. Taking the cvtcolor function for example here is a snippet of code from BGR2HSV case:

    if (is_hsv && depth == CV_8U)
    {
        static UMat sdiv_data;
        static UMat hdiv_data180;
        static UMat hdiv_data256;
        static int sdiv_table[256];
        static int hdiv_table180[256];
        static int hdiv_table256[256];
        static volatile bool initialized180 = false, initialized256 = false;
        volatile bool & initialized = hrange == 180 ? initialized180 : initialized256;

        if (!initialized)
       {

Here they attempt to do a one time initialization of the static tables, but what if thread 2 gets scheduled while thread 1 is processing this one time initialization?

By building protection around my threads I am unable to observe the problem any further...

So if I put a protection around the openCV code in my thread

define oneTimeThreadInit as global initialized to false

if ( myThread == THREAD1 ) || ( oneTimeThreadIniti == true ) ) {

do my openCV code

set oneTimeThreadInit = true }

This is not exact code, as I'd use semaphores.... but the idea is if thread 1 is allowed to run to completion, to execute all my chosen openCV functions, this allows all my openCV functions to execute any one time initialization internally where they are using static vars... after this one time execution of all my chosen openCV functions, then I allow all threads to execute... since I've assured that the initialization is complete inside the openCV functions, I no longer am seeing the assertion error... So without exactly knowing where its conflicting... I believe this is the source of the problem.

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
0

answered 2016-03-17 11:14:42 -0600

chrisg gravatar image

This is not an answer. Adding a program that crashes on Windows 10 with opencv-3.0.0-rc1 and VS 2013.

#define CONCURRENT_CVT_COLOR

std::condition_variable c0;
std::mutex m0;

void testthread(void)
{
#ifdef CONCURRENT_CVT_COLOR
    // Make the lock local, so that it doesn't wait to get the lock from multiple threads.
    std::mutex m0;
#endif
    std::unique_lock<std::mutex> l(m0);
    c0.wait(l);
    cv::Mat m_in(cv::Size(2048, 1536), CV_8U);
    cv::Mat m_out(cv::Size(2048, 1536), CV_8UC3);
    cv::cvtColor(m_in, m_out, CV_GRAY2RGB);
}

int main(void)
{
    unsigned int nthreads = 2;

    std::vector<std::thread> threads(nthreads);

    for (unsigned int i = 0; i < nthreads; i++)
        threads[i] = std::thread(testthread);

    Sleep(100);
    c0.notify_all();

    for (unsigned int i = 0; i < nthreads; i++)
        threads[i].join();

    return(1);
}

If CONCURRENT_CVT_COLOR is not defined, then the program does not crash. Thanks pistachio for your solution.

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2016-03-15 12:59:21 -0600

Seen: 672 times

Last updated: Mar 15 '16