gpt4 book ai didi

c - 如何并行生成随机数?

转载 作者:太空狗 更新时间:2023-10-29 16:35:08 25 4
gpt4 key购买 nike

我想使用 openMP 并行生成伪随机数,如下所示:

int i;
#pragma omp parallel for
for (i=0;i<100;i++)
{
printf("%d %d %d\n",i,omp_get_thread_num(),rand());
}
return 0;

我已经在 Windows 上对其进行了测试,并获得了巨大的加速,但每个线程生成的数字完全相同。我也在 Linux 上对其进行了测试,我发现速度非常慢,8 核处理器上的并行版本比顺序版本慢大约 10 倍,但每个线程生成不同的数字。

有没有办法既有加速又有不同的数字?

编辑 27.11.2010
我想我已经使用 Jonathan Dursi 帖子中的想法解决了它。似乎以下代码在 linux 和 windows 上都运行得很快。数字也是伪随机的。你怎么看?

int seed[10];

int main(int argc, char **argv)
{
int i,s;
for (i=0;i<10;i++)
seed[i] = rand();

#pragma omp parallel private(s)
{
s = seed[omp_get_thread_num()];
#pragma omp for
for (i=0;i<1000;i++)
{
printf("%d %d %d\n",i,omp_get_thread_num(),s);
s=(s*17931+7391); // those numbers should be choosen more carefully
}
seed[omp_get_thread_num()] = s;
}
return 0;
}

PS.: 我还没有接受任何答案,因为我需要确定这个想法是好的。

最佳答案

我会在这里发布我发布到 Concurrent random number generation 的内容:

我认为您正在寻找 rand_r(),它明确地将当前 RNG 状态作为参数。然后每个线程都应该有自己的种子数据副本(无论你想让每个线程以相同的种子还是不同的种子开始取决于你在做什么,在这里你希望它们不同或者你会得到同一行一次又一次)。这里有一些关于 rand_r() 和线程安全的讨论:whether rand_r is real thread safe? .

假设您希望每个线程的种子都以其线程号开始(这可能不是您想要的,因为每次运行相同数量的线程时它都会给出相同的结果,但就像示例):

#pragma omp parallel default(none)
{
int i;
unsigned int myseed = omp_get_thread_num();
#pragma omp for
for(i=0; i<100; i++)
printf("%d %d %d\n",i,omp_get_thread_num(),rand_r(&myseed));
}

编辑:开玩笑,检查上面是否会得到任何加速。完整代码是

#define NRANDS 1000000
int main(int argc, char **argv) {

struct timeval t;
int a[NRANDS];

tick(&t);
#pragma omp parallel default(none) shared(a)
{
int i;
unsigned int myseed = omp_get_thread_num();
#pragma omp for
for(i=0; i<NRANDS; i++)
a[i] = rand_r(&myseed);
}
double sum = 0.;
double time=tock(&t);
for (long int i=0; i<NRANDS; i++) {
sum += a[i];
}
printf("Time = %lf, sum = %lf\n", time, sum);

return 0;
}

其中 tick 和 tock 只是 gettimeofday() 的包装器,而 tock() 返回以秒为单位的差异。打印 Sum 只是为了确保没有优化掉任何东西,并展示一个小点;你会得到不同数量的线程,因为每个线程都有自己的线程数作为种子;如果您使用相同数量的线程一次又一次地运行相同的代码,您将出于相同的原因得到相同的总和。无论如何,计时(在没有其他用户的 8 核 nehalem 盒子上运行):

$ export OMP_NUM_THREADS=1
$ ./rand
Time = 0.008639, sum = 1074808568711883.000000

$ export OMP_NUM_THREADS=2
$ ./rand
Time = 0.006274, sum = 1074093295878604.000000

$ export OMP_NUM_THREADS=4
$ ./rand
Time = 0.005335, sum = 1073422298606608.000000

$ export OMP_NUM_THREADS=8
$ ./rand
Time = 0.004163, sum = 1073971133482410.000000

如此加速,如果不是很好的话;正如@ruslik 指出的那样,这并不是一个真正的计算密集型过程,内存带宽等其他问题开始发挥作用。因此,在 8 核上只有超过 2 倍的加速。

关于c - 如何并行生成随机数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4287531/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com