Search code examples
c++multithreadingc++11stdvectorstdthread

passing by reference in C++ 11 threads; changes are localized


I am trying to fasten some processing of my opencv code using C++ 11 threads.

In a meanwhile I am using vector for sharing data

Please consider a following piece of code:

start_t = cv::getTickCount();
std::vector <std::thread>   tMSE_Calc(nComparisons);
std::vector<float> sum;
sum.resize(nComparisons);

for(int i = 0 ; i < nComparisons ; ++i)
{
    tMSE_Calc[i] = std::thread(FindMSE_Fast, vector1, vector2, sum, i);
}

for(int i = 0 ; i < nComparisons ; ++i)
{
    tMSE_Calc[i].join();
}
end_t = cv::getTickCount();
logfile << "Actual Comparison Took " << (end_t - start_t) * freq * 1000 << " milliseconds"<< std::endl;

for(int i = 0 ; i < nComparisons ; ++i)
{
    std::cout << "Sum[" << i << "] = " << sum[i] << std::endl;
}

And I have a thread function:

void FindMSE_Fast(cv::Mat& m1, cv::Mat& m2, std::vector<float>& sumVec, int idx)
{
    cv::Mat s;
    cv::absdiff(m1, m2, s);
    s = s.mul(s);
    cv::Scalar sum = cv::sum(s);
    sumVec[idx] = cv::sqrt(sum[0]);
    std::cout << "Difference is: " << cv::sqrt(sum[0]) << "index is: " << sumVec[idx] << std::endl;

    //std::cout << "Difference is: " << cv::sqrt(sum[0]) << std::endl;
}

It seems so obvious to me that vector sum should be modified at the end of thread calls, but when I print it in main thread later, all of its contents are zero.

Is there something different that we need to do with function parameters in order to pass by reference?


Solution

  • The bound function arguments are copied and are not passed by reference. This behavior is the same, e.g., with std::bind(). The arguments are passed as deduced T&& to the constructor but that's only used to initialize some held values.

    If you don't want the arguments to be copied, you'd pass a std::reference_wrapper<T> instead, e.g., using

    std::thread(FindMSE_Fast, vector1, vector2, std::ref(sum), i)
    

    while pass sum by reference. Since std::reference_wrapper<T> has a conversion operator to T& your function will be called appropriately.