Skip to content

Commit ebdd741

Browse files
committed
core(test): add regression test for RNG in parallel_for_()
1 parent b28fd79 commit ebdd741

File tree

1 file changed

+36
-0
lines changed

1 file changed

+36
-0
lines changed

modules/core/test/test_rand.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,3 +382,39 @@ TEST(Core_Rand, Regression_Stack_Corruption)
382382
ASSERT_EQ(param1, -9);
383383
ASSERT_EQ(param2, 2);
384384
}
385+
386+
namespace {
387+
388+
class RandRowFillParallelLoopBody : public cv::ParallelLoopBody
389+
{
390+
public:
391+
RandRowFillParallelLoopBody(Mat& dst) : dst_(dst) {}
392+
~RandRowFillParallelLoopBody() {}
393+
void operator()(const cv::Range& r) const
394+
{
395+
cv::RNG rng = cv::theRNG(); // copy state
396+
for (int y = r.start; y < r.end; y++)
397+
{
398+
cv::theRNG() = cv::RNG(rng.state + y); // seed is based on processed row
399+
cv::randu(dst_.row(y), Scalar(-100), Scalar(100));
400+
}
401+
// theRNG() state is changed here (but state collision has low probability, so we don't check this)
402+
}
403+
protected:
404+
Mat& dst_;
405+
};
406+
407+
TEST(Core_Rand, parallel_for_stable_results)
408+
{
409+
cv::RNG rng = cv::theRNG(); // save rng state
410+
Mat dst1(1000, 100, CV_8SC1);
411+
parallel_for_(cv::Range(0, dst1.rows), RandRowFillParallelLoopBody(dst1));
412+
413+
cv::theRNG() = rng; // restore rng state
414+
Mat dst2(1000, 100, CV_8SC1);
415+
parallel_for_(cv::Range(0, dst2.rows), RandRowFillParallelLoopBody(dst2));
416+
417+
ASSERT_EQ(0, countNonZero(dst1 != dst2));
418+
}
419+
420+
} // namespace

0 commit comments

Comments
 (0)