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
.
我的代码涉及一些繁重的计算,所以我在 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
.