简体   繁体   中英

How to use _beginthreadex in a loop and keep parallelism

  HANDLE h[4]; 
  for(int i=0;i<test_img_num;i++)
     h[i] = (HANDLE)_beginthreadex(0, 0, (unsigned int (__stdcall *)(void *))ThreadFunc, &test_images[i], 0, 0);  
  WaitForMultipleObjects(4,h,true,INFINITE);

test_images is vector<Mat_<uchar> > test_images;

and my ThreadFunc is,

Mat_<double> _stdcall ThreadFunc( void * param)
{
    Mat_<uchar> *img=(Mat_<uchar> *)param;
     BoundingBox temp;
    temp.start_x=temp.start_y=0;
    temp.width=img->cols;
    temp.height=img->rows;
    temp.centroid_x = temp.start_x + temp.width/2.0;
    temp.centroid_y = temp.start_y + temp.height/2.0; 
    Mat_<double> current_shape = regressor.Predict(*img,temp,INITIAL_NUMBER);
    return current_shape;
} 

The weirld thing is it runs ok sometimes but somestimes it crashes(in thread img can not be read,"Memory access violation"). By google I find that test_images[i] changes when the sub threads run and when i=5test_images[i] can not be read. I guess this may be the problem. And I learned that I can use lock to prevent test_images[i] from unexpected change.

However,the problem is what I want is to keep parallelism of Predict function in ThreadFunc between the four threads,but if I lock i ,the second thread must wait until Predict operation of the first thread finishes and there will be no parallelism.

How can I solve this problem? Thanks a lot !

update: I directly use

    h[0] = (HANDLE)_beginthreadex(0, 0, (unsigned int (__stdcall *)(void *))ThreadFunc, &test_images[0], 0, 0); 
  h[1] = (HANDLE)_beginthreadex(0, 0, (unsigned int (__stdcall *)(void *))ThreadFunc, &test_images[1], 0, 0); 
  h[2] = (HANDLE)_beginthreadex(0, 0, (unsigned int (__stdcall *)(void *))ThreadFunc, &test_images[2], 0, 0); 
  h[3] = (HANDLE)_beginthreadex(0, 0, (unsigned int (__stdcall *)(void *))ThreadFunc, &test_images[3], 0, 0);

it still alerts "Memory access violation" when execute temp.width=img->cols; Perhaps the change of i is not the problem??

Never cast function pointers.

More precisely, you can cast them temporarily, but you must never call (or allow to be called) a function pointer that doesn't point to a function with a matching type.

Violating this rule is undefined behavior. The below is a description of what goes wrong internally, but that's just technical background information.

In your case, ThreadFunc returns a Mat_<double> , but _beginthreadex expects a function that returns an unsigned int , so you cast the function pointer instead of changing the function to match what is expected.

Why is this relevant? Because return types aren't simply ignored. The function has to store the return value somewhere, and the calling function will probably want to use it. _beginthreadex passes the result of the thread function to ExitThread as the exit code, which you could then retrieve with GetExitCodeThread . By returning something that isn't an unsigned int , you will probably get garbage there.

But that's the small problem. The big problem is what happens when you return a class type. In the Windows calling convention (and most others), complex structure return values are written into stack space allocated by the caller, through a pointer passed as a hidden additional argument to the callee. But if the caller thinks the function returns an unsigned int , it won't allocate the stack space or pass the hidden pointer. When the callee wants to write the return value, it will read what it expects to be the hidden argument, but which is just some random value, and then try to write to the address it read. This will cause it to overwrite random memory or, if you're lucky, produce an access violation, crashing the program immediately.

You should consider using a std::vector<std::thread> instead of creating the threads with _beginthreadex , by the way. The thread class is far more flexible in what it allows to be called, makes it easier to pass context to the thread function, and automatically handles cleanup of thread handles.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM