首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TRNG随机生成

TRNG随机生成
EN

Stack Overflow用户
提问于 2021-03-22 22:48:44
回答 1查看 142关注 0票数 1

对于下面的代码,它为蒙特卡罗模拟生成随机数,我需要收到每次运行的精确和,但这不会发生,尽管我已经修复了种子。如果有人能指出这段代码的问题,我将不胜感激。

代码语言:javascript
复制
#include <cmath>
#include <random>
#include <iostream>
#include <chrono>
#include <cfloat>
#include <iomanip>
#include <cstdlib>
#include <omp.h>
#include <trng/yarn2.hpp>
#include <trng/mt19937_64.hpp>
#include <trng/uniform01_dist.hpp>

using namespace std;
using namespace chrono;
const double landa = 1; 
const double exact_solution = landa / (pow(landa, 2) + 1); 
double function(double x) {
    return cos(x) / landa;
}

int main() {
    int rank; 
    const int N = 1000000;
    double sum = 0.0;
    trng::yarn2 r[6];
    for (int i = 0; i <6; i++)
    { 
        r[i].seed(0); 
    }
    
    for (int i = 0; i < 6; i++)
    {
          r[i].split(6,i);
    }
    
     trng::uniform01_dist<double> u;
     auto start = high_resolution_clock::now();
     #pragma omp parallel  num_threads(6)  
     {
         rank=omp_get_thread_num();
         #pragma omp for reduction (+: sum)
         for (int i = 0; i<N; ++i) {
            //double x = distribution(g);
      
            double x= u(r[rank]); 
            x = (-1.0 / landa) * log(1.0 - x); 
            sum = sum+function(x);
         }
    }
     double app   = sum / static_cast<double> (N);
     auto end = high_resolution_clock::now();
        
    auto diff=duration_cast<milliseconds>(end-start);
    
    cout << "Approximation is: " <<setprecision(17) << app << "\t"<<"Time: "<< setprecision(17) << diff.count()<<" Error: "<<(app-exact_solution)<< endl; 

    return 0;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-03-23 07:43:08

TL;博士这个问题有两个方面:

  1. 浮点加法不相联;
  2. 您正在为每个线程生成不同的随机数。

我需要收到每一次运行的确切金额,但这种情况不会发生,虽然我已经固定了种子。如果有人能指出这段代码的问题,我将不胜感激。

首先,在rank=omp_get_thread_num();上有一个争用条件,变量rank在所有线程之间共享,以修复可以在并行区域内声明变量rank的问题,因此,使其成为每个线程的私有变量。

代码语言:javascript
复制
 #pragma omp parallel  num_threads(6)  
 {
     int rank=omp_get_thread_num();
     ...
  }

在您的代码中,您不应该期望sum的值对于不同数目的线程是相同的。为什么?

  1. 因为您正在并行地添加doubles。 (int i= 0;i从每一个计算机科学家应该知道的浮点算法可以读到: 另一个灰色地带涉及括号的解释。由于舍入误差,代数的联想定律不一定适用于浮点数,例如,当x= 1e30,y= -1e30和z=1时,(x+y)+z的表达式(x+y)+z与x+(y+z)的答案完全不同(前者为1,后者为0)。

因此,您可以得出浮点加法不是关联的,以及对于不同数量的线程,您可能有不同的sum值的原因。

  1. 您正在每个线程生成不同的随机值: 对于(int i= 0;i< 6;i++) { ri.split(6,i);} 因此,对于不同数量的线程,变量sum也会得到不同的结果。

正如杰罗姆-理查德在评论中指出的那样:

请注意,像Kahan求和这样更精确的算法可以显着地减少舍入问题,同时仍然是相对快速的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66754871

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档