当前位置: 首页 > 知识库问答 >
问题:

用非线程安全随机数生成器修正C语言中pi monte carlo的OpenMP语用

鱼浩荡
2023-03-14

我需要一些帮助,用一个给定的随机数生成器用openmp并行化与蒙特卡洛方法的pi计算,这不是线程安全的。

第一:这条线对我没有帮助。

我自己的尝试是下面的#pragma omp语句。我认为I、x和y变量应该是每个线程的init,并且应该是private的。z是圆圈中所有命中数的总和,因此它应该在for循环后隐含的barriere之后求和。

认为主要的问题是随机数发生器的静态无功。我在调用函数的地方做了一个关键部分,这样每次只有一个线程可以执行它。但Pi解并不具有更高的值。

int main (int argc, char *argv[]) {

    int i, z = 0, threads = 8, iters = 100000;
    double x,y, pi;

    #pragma omp parallel firstprivate(i,x,y) reduction(+:z) num_threads(threads)
        for (i=0; i<iters; ++i) {
            #pragma omp critical
            {
                x = rng_doub(1.0);
                y = rng_doub(1.0);
            }
            if ((x*x+y*y) <= 1.0)
                z++;
        }

    pi = ((double) z / (double) (iters*threads))*4.0;
    printf("Pi: %lf\n", pi);;
    return 0;
}
#define RNG_MOD 741025

int rng_int(void) {
    static int state = 0;

    return (state = (1366 * state + 150889) % RNG_MOD);
}

double rng_doub(double range) {
    return ((double) rng_int()) / (double) ((RNG_MOD - 1)/range);
}

我也尝试过使静态int状态全局化,但它并没有改变我的结果,也许我做错了。所以你能帮我做正确的修改吗?非常感谢!

共有1个答案

黄聪
2023-03-14

请尝试下面的代码。它为每个线程创建一个私有状态。我对atrand_r函数做了类似的操作,为什么使用OpenMP进行计算要比使用单个线程多花100倍的时间呢?

编辑:我使用Hristo的一些建议更新了我的代码。我(第一次)使用了threadprivate。我还使用了一个更好的兰德函数,它给出了pi的更好估计,但它仍然不够好。

一个奇怪的事情是我必须在threadprivate之后定义函数rng_int否则我会得到一个错误“error:'state'声明'threadprivate'after first use”。我也许该问个问题。

//gcc -O3 -Wall -pedantic -fopenmp main.c
#include <omp.h>
#include <stdio.h>

#define RNG_MOD 0x80000000
int state;

int rng_int(void);
double rng_doub(double range);

int main() {
    int i, numIn, n;
    double x, y, pi;

    n = 1<<30;
    numIn = 0;

    #pragma omp threadprivate(state)
    #pragma omp parallel private(x, y) reduction(+:numIn) 
    {

        state = 25234 + 17 * omp_get_thread_num();
        #pragma omp for
        for (i = 0; i <= n; i++) {
            x = (double)rng_doub(1.0);
            y = (double)rng_doub(1.0);
            if (x*x + y*y <= 1) numIn++;
        }
    }
    pi = 4.*numIn / n;
    printf("asdf pi %f\n", pi);
    return 0;
}

int rng_int(void) {
   // & 0x7fffffff is equivalent to modulo with RNG_MOD = 2^31
   return (state = (state * 1103515245 + 12345) & 0x7fffffff);
}

double rng_doub(double range) {
    return ((double)rng_int()) / (((double)RNG_MOD)/range);
}

您可以在http://coliru.stacked-crooked.com/a/23c1753a1b7d1b0d上看到结果(以及编辑和运行代码

 类似资料:
  • 下面简单脚本并行产生随机数 在使用单个线程时,上述脚本是确定性 然而,当使用多个线程时,它是部分随机,且包含线程之间的相关性(这可能是一个相当大的问题 我明白为什么我的代码不是线程安全的,但我不明白如何使它是线程安全的。是否可以不考虑线程的数量而具有确定性的输出? 目标是使产生与相同的输出(即线程数不会影响对象)。如果这不可能,则目标是产生与相同的输出。

  • 本文向大家介绍C语言/C++如何生成随机数,包括了C语言/C++如何生成随机数的使用技巧和注意事项,需要的朋友参考一下 本文分享了C语言/C++如何生成随机数的具体实现方法,供大家参考,具体内容如下 C语言/C++怎样产生随机数:这里要用到的是rand()函数, srand()函数,C语言/C++里没有自带的random(int number)函数。 (1) 如果你只要产生随机数而不需要设定范围的

  • 本文向大家介绍C语言随机数生成教程(rand和srand用法),包括了C语言随机数生成教程(rand和srand用法)的使用技巧和注意事项,需要的朋友参考一下 在实际编程中,我们经常需要生成随机数,例如,贪吃蛇游戏中在随机的位置出现食物,扑克牌游戏中随机发牌。 在C语言中,我们一般使用 <stdlib.h> 头文件中的 rand() 函数来生成随机数,它的用法为: void 表示不需要传递参数。

  • 本文向大家介绍C语言编程中生成随机数的入门教程,包括了C语言编程中生成随机数的入门教程的使用技巧和注意事项,需要的朋友参考一下 语言产生随机数是一个常见的编程功能任务,当然这个也不难,调用两三个函数就出来了,但是你知道这些函数具体是起到怎样的作用,并且是它们是如何产生随机数的吗? 几个概念 随机数:数学上产生的都是伪随机数,真正的随机数使用物理方法产生的。 随机数种子:随机数的产生是由算术规则产生

  • 根据文档,java.util.random不是真正的随机生成器。 我必须实现真正的随机数生成器。请建议任何编程语言或java语言的替代方案

  • 主要内容:随机数的本质,重新播种,生成一定范围内的随机数,连续生成随机数在实际编程中,我们经常需要生成随机数,例如,贪吃蛇游戏中在随机的位置出现食物,扑克牌游戏中随机发牌。 在C语言中,我们一般使用 <stdlib.h> 头文件中的 rand() 函数来生成随机数,它的用法为: int rand (void); void 表示不需要传递参数。 C语言中还有一个 random() 函数可以获取随机数,但是 random() 不是标准函数,不能在 VC/VS 等编译器通过