parallel_for 和随机数的可重现结果?

Reproducible results with parallel_for and random numbers possible?

我的代码涉及一些繁重的计算,所以我在 Visual Studio C++ 中使用 parallel_for 循环。这工作正常,代码 运行s 比普通的 for 循环快得多。

我的问题是我想要可重现的结果,但计算涉及随机数。我可以使用固定种子,但这似乎在使用 parallel_for 循环时有效。

示例代码:

#include <iostream>
#include <random>
#include <ppl.h>

#define USE_PAR 1

std::mutex m;
double x_min = 1.0e300;

double draw()
{
    int seed = 1;
    std::uniform_real_distribution<double> d(-1.0, 1.0);
    static std::mt19937 mt(seed);
    return d(mt);
}

void expensive_function()
{
    double x;
    for (volatile int i = 0; i < 1000; ++i)
        x = draw();
    std::lock_guard<std::mutex> lock(m);
    if (x < x_min)
        x_min = x;
}

void test()
{
#if USE_PAR
    concurrency::parallel_for(size_t(0), size_t(10), [&](size_t i) { expensive_function(); });
#else
    for (size_t i = 0; i < 10; ++i) { expensive_function(); }
#endif
    std::cout << x_min << "\n";
}

int main()
{
    for (int i = 0; i < 10; ++i) test();
}

当我使用普通的 for 循环而不是 parallel_for (USE_PAR = 0) 时,我每次 运行 程序时都会重复得到相同的输出:

-0.935609
-0.952062
-0.952062
-0.952062
-0.952062
-0.952062
-0.988225
-0.988225
-0.988225
-0.99249

但是使用 parallel_for 循环 (USE_PAR = 1),我每次都会得到不同的结果。比如第一次:

-0.733511
-0.733511
-0.855412
-0.855412
-0.93122
-0.93122
-0.93122
-0.987444
-0.987444
-0.987444

然后第二次:

-0.90946
-0.997749
-0.997749
-0.997749
-0.997749
-0.997749
-0.997749
-0.997749
-0.997749
-0.997749

可以两者兼得吗? parallel_for 性能良好,即使使用随机数也可重现结果?

原因是你有未定义的行为。您同时从多个线程调用 static 随机数生成器。

使其成为 thread_local(当你这样做时它也会变成 static):

thread_local std::mt19937 mt(seed);

注意:我不知道 <ppl.h> 库,但是只要变量在程序的控制下(即不连接到某些外部可能会改变它的硬件)。删除 volatile int i 并使其成为 int i.