- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个代码,我试图在其中并行执行。
#include<iostream>
#include<omp.h>
#include<math.h>
#include<cstdlib>
#include<iterator>
#include<string.h>
#include<vector>
#include<map>
#include<time.h>
#include<gsl/gsl_rng.h>
#include<gsl/gsl_randist.h>
gsl_rng ** threadvec = new gsl_rng*[omp_get_num_threads()];
using namespace std;
int main(){
clock_t begin = omp_get_wtime();
vector<double> PopVals;
map<int, vector<double> > BigMap;
int Num1 = 100;
double randval;
int Num2 = 10;
#pragma omp parallel
{
gsl_rng_env_setup();
for (int b = 0; b < omp_get_num_threads(); b++)
threadvec[b] = gsl_rng_alloc(gsl_rng_taus);
}
for( int i = 0; i < Num1; i++){
PopVals.resize(Num2);
#pragma omp parallel for
for( int j = 0; j < Num2; j++){
randval = gsl_rng_uniform(threadvec[omp_get_thread_num()]);
PopVals[j] = randval;
}
BigMap.insert(make_pair(i,PopVals));
PopVals.clear();
}
map<int,vector<double> >::iterator it = BigMap.find(Num1-1);
vector<double> OutVals = it->second;
for (int i = 0; i < Num2; i++)
cout << endl << OutVals[i] << endl;
for (int b = 0; b < omp_get_num_threads(); b++)
gsl_rng_free(threadvec[b]);
clock_t end = omp_get_wtime();
double elapsed_time = double(end - begin);
cout << endl << "Time taken to run: " << elapsed_time << " secs" << endl;
}
当我运行它时,有 8 个线程并行执行嵌套循环,但我一直看到每个线程的随机数相同。我将这种行为归因于每次迭代都没有设置种子。如果有人能指出,我如何以线程安全的方式在循环的每次迭代中生成唯一的随机数,那就太好了。
以上代码输出0.793816,10次。然而,我希望内部循环中的每个值都有唯一的数字。
谢谢。
最佳答案
这里有多个问题。
omp_get_num_threads
在并行区域之外,omp_get_num_threads()
始终返回 1
。请改用 omp_get_max_threads()
,它将返回任何即将到来的 parallel
区域的线程数,除非手动覆盖。特别是 threadvec
只有一个条目。
在并行区域调用 gsl_rng_env_setup
将无法正常工作。您还试图通过所有线程分配整个 rngs vector ...只需删除并行区域并正确使用 omp_get_max_threads()
。或者你也可以这样做:
gsl_rng_env_setup(); // serial
#pragma omp parallel
threadvec[omp_get_thread_num()] = gsl_rng_alloc(gsl_rng_taus);
尽管从文档中还不能 100% 清楚这是否是线程安全的,所以只需使用串行循环版本即可。
默认情况下,所有 rng 都使用相同的数字作为种子,因此很明显它们将返回完全相同的序列。用线程号正确地播种它们,例如gsl_rng_set(threadvec[b], b * 101);
。请注意,Tausworthe 生成器很奇怪。当使用 0
或 1
播种时,这些特定的数字会生成相同的数字序列。
您的变量 randval
是在并行区域之外定义的,因此它是隐式共享的。您可以强制它是私有(private)的,但最好尽可能在本地声明变量。这使得对 OpenMP 代码的推理变得更加容易。
最后,它看起来像这样:
#include <cstdlib>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_rng.h>
#include <iostream>
#include <iterator>
#include <map>
#include <math.h>
#include <omp.h>
#include <string.h>
#include <time.h>
#include <vector>
// DO NOT using namespace std;
int main() {
clock_t begin = omp_get_wtime();
std::vector<double> PopVals;
std::map<int, std::vector<double>> BigMap;
constexpr int Num1 = 100;
constexpr int Num2 = 10;
gsl_rng_env_setup();
gsl_rng **threadvec = new gsl_rng *[omp_get_max_threads()];
for (int b = 0; b < omp_get_max_threads(); b++) {
threadvec[b] = gsl_rng_alloc(gsl_rng_taus);
gsl_rng_set(threadvec[b], b * 101);
}
for (int i = 0; i < Num1; i++) {
PopVals.resize(Num2);
#pragma omp parallel for
for (int j = 0; j < Num2; j++) {
double randval = gsl_rng_uniform(threadvec[omp_get_thread_num()]);
PopVals[j] = randval;
}
BigMap.insert(std::make_pair(i, PopVals));
PopVals.clear();
}
std::map<int, std::vector<double>>::iterator it = BigMap.find(Num1 - 1);
std::vector<double> OutVals = it->second;
for (int i = 0; i < Num2; i++)
std::cout << std::endl << OutVals[i] << std::endl;
for (int b = 0; b < omp_get_max_threads(); b++)
gsl_rng_free(threadvec[b]);
clock_t end = omp_get_wtime();
double elapsed_time = double(end - begin);
std::cout << std::endl << "Time taken to run: " << elapsed_time << " secs" << std::endl;
delete[] threadvec;
}
关于c++ - GSL+OMP : Thread safe random number generators in C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45171623/
好的,我希望以前没有问过这个问题,因为在搜索中很难找到。 我查看了 F95 手册,但仍然觉得这很模糊: For the simple case of: DO i=0,99 END DO 我正
这两者有什么区别? [一] #pragma omp parallel { #pragma omp for for(int i = 1; i < 100; ++i) {
这两者有什么区别? [一] #pragma omp parallel { #pragma omp for for(int i = 1; i < 100; ++i) {
我有这段代码: #include #include int main(){ int i,j = 0 ; int tid; # pragma omp parallel pri
刚开始接触OPENMP,想用它来求解波动方程,串口代码在这里: #include #include #include #include #define GRID_SZ 3000 #define
我对 omp single 感到困惑和 omp task指令。我已经阅读了几个使用它们的例子。以下示例显示如何使用任务构造来处理链表的元素。 1 #pragma omp parallel 2 {
我试图了解 omp ordered 和 omp critical 之间的区别。他们都没有相同的语义吗?每个线程中编写的代码都被串行执行,当一个线程处于有序/关键 block 中时,其他线程等待。我看不
是否可以在 omp 并行 block 之外使用 omp pragma,如 critical、single、master 或 barrier?我有一个函数可以从 OMP 并行 block 调用,也可以不
我想测试 #pragma omp parallel for 和 #pragma omp simd 一个简单的矩阵加法程序。当我分别使用它们时,我没有收到任何错误,而且看起来还不错。但是,我想测试使用它
考虑: void saxpy_worksharing(float* x, float* y, float a, int N) { #pragma omp parallel for
我试图了解 #pragma omp critical 之间的确切区别和 #pragma omp single在 OpenMP 中: Microsoft 对这些的定义是: Single:让您指定应在其上
在带有 openMP 的 C++ 中,两者之间有什么区别吗 #pragma omp parallel for for(int i=0; i
我正在处理一些事情,试图让孤立工作发挥作用,并通过减少 #pragma omp parallel 的调用来减少开销。我正在尝试的是这样的: #pragma omp parallel default(n
在我学习 OpenMP 的过程中,我遇到了一个示例,其中的主要内容如下所示: int main(){ #pragma omp parallel #pragma omp sing
我是 OpenMP 的新手,我一直在尝试运行一个使用 OpenMP 添加两个数组的程序。在 OpenMP 教程中,我了解到,在 for 循环上使用 OpenMP 时,我们需要使用 #pragma om
我正在阅读 Peter S. Pacheco 的《并行编程简介》一书。在第 5.6.2 节中,它对减少 fork/join 开销进行了有趣的讨论。 考虑奇偶转置排序算法: for(phase=0; p
之间有什么区别: #pragma omp for {for_loop} 和 #pragma omp parallel for {for_loop} 最佳答案 #pragma omp par
在 OpenMP 中 #pragma omp master 中的任何代码指令由单个线程(主线程)执行,在区域末尾没有隐含的屏障。 (见 section on MASTER directive in t
如果我明白 aligned omp simd的条款构造,它指的是整个数组的对齐方式。 它如何用于多维数组?认为 ni = 131; nj = 137; nk = 127 !allocates arr
我有一个问题:我必须使用 OMP 并行化这段代码。 存在数据依赖问题,不知道如何解决。有什么建议么? for (n = 2; n < N+1; n++) { dz = *(dynamic_d +
我是一名优秀的程序员,十分优秀!