Hi,
I am having some issues with some multithreading code. I have written this code a while ago on windows (windows 10, visual studio 2019, openCV 4.3.0 with openMP and TBB off), now I want to run it on ubuntu (ubuntu 20.04, visual studio code, gcc 9.4.0, openCV 4.3.0), but it only works when I turn OpenMP on while building OpenCV.
Minimal example of the code:
.cpp file
namespace Foo {
class ExampleClass : public cv::ParallelLoopBody {
public:
ExampleClass(const cv::Mat& _srcmat, cv::Mat& _dstmat)
: ParallelLoopBody(), srcmat_(_srcmat), rgb_dst_mat_(_dstmat) {
}
void operator()(const cv::Range& range) const CV_OVERRIDE {
int col = 1;
int row = range.start;
auto src_image = srcmat_;
auto dst_image = rgb_dst_mat_;
for (; col < src_image.cols; col++) {
float R = src_image.at<float>(row, col) * 10;
float G = src_image.at<float>(row, col) * 1;
float B = src_image.at<float>(row, col) * 2;
dst_image.ptr<float>(row, col)[0] = R;
dst_image.ptr<float>(row, col)[1] = G;
dst_image.ptr<float>(row, col)[2] = B;
}
}
private:
cv::Mat srcmat_;
cv::Mat rgb_dst_mat_;
};
void Example::function(const cv::Mat& src_image, cv::Mat& dst_image) {
if (src_image.empty()) {
throw std::invalid_argument("Provided src_image image is empty");
}
if (src_image.type() != CV_32FC1 || dst_image.type() != CV_32FC3) {
throw std::invalid_argument("Invalid image type");
}
if (src_image.size() != dst_image.size()) {
throw std::invalid_argument("Image size is not the same");
}
int width = src_image.cols;
int height = src_image.rows;
cv::parallel_for_(cv::Range(1, height - 1), ExampleClass(src_image, dst_image));
}
} // namespace Foo
.hpp file
namespace Foo {
class Example {
public:
virtual ~Example();
static void function(const cv::Mat& bayer, cv::Mat& rgb);
};
} // namespace Foo
This will result in a correct image in Windows, but in Ubuntu only when openMP is set to ON when compiling OpenCV.
Results:
Ubuntu - OpenMP: OFF, TBB: OFF
Ubuntu - OpenMP: OFF, TBB: ON
Ubuntu - OpenMP: ON, TBB: OFF
I do have a few questions after getting those results:
- What is the difference between OpenMP and TBB? What I understand is that both are multithreading libraries, but are working differently. How do they each work?
- Why can I run my program on Windows without building any of those two libraries, but do I have to compile OpenMP on Ubuntu?
- We suspect there is an interference with different multithreading platforms (parallel_for_ and main thread). Is that possible here? And is there a way to detect automatically which one should be used?
Thanks in advance!