- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
代码:
double x(){return (double)rand()/(double)RAND_MAX;}
double y(){return (double)rand()/(double)RAND_MAX;}
double z(){return (double)rand()/(double)RAND_MAX;}
int d(double x, double y, double z){
if ( ( (pow(x,2)+pow(y,2)) <1 ) && ( z<=1 && z>=0 )) return 1;
return 0;
}
double f(double x, double y, double z){
return 1;
}
#pragma omp parallel default(none) private(id,numt,j,local_sum,local_good_dots,local_coi,x_,y_,z_) shared(total_sum,good_dots,count_of_iterations)
{
local_coi = count_of_iterations;
id = omp_get_thread_num() + 1;
numt = omp_get_num_threads();
#pragma omp for
for (j = 1; j <= local_coi; j++){
x_=x();
y_=y();
z_=z();
if (d(x_,y_,z_) == 1){
local_sum += f(x_,y_,z_);
local_good_dots += 1;
}
}
#pragma omp critical
{
total_sum = total_sum + local_sum;
good_dots = good_dots + local_good_dots;
}
}
注释:该代码是蒙特卡罗方法的实现,用于计算函数f()
在区域d()
中的三维积分。
我希望这段代码在多线程模式(openmp)下运行得更快。
但是出了点问题。
经过几个小时的修改(openmp pragma 中的减少
、if 条件的简化(例如 f(x_,y_,z_) * d(x_,y_,z_)
code>)) 我不明白,为什么这个简单的循环在更多线程上变得更慢。
但是当我在循环之前为每个坐标生成一个 3 维数组并将其放入 shared
后,我的程序变得更快。
那么,问题:
如何修改此代码以及并行 block 中允许哪些功能(操作)?
P.S:据我所知,不允许使用 rand
函数(或者我错了?)
感谢您的帮助!
修改(在 @HristoIliev 的帮助下)
double x(){return (double)rand()/(double)RAND_MAX;}
double y(){return (double)rand()/(double)RAND_MAX;}
double z(){return (double)rand()/(double)RAND_MAX;}
int d(double x, double y, double z){
if ( ( (pow(x,2)+pow(y,2)) <1 ) && ( z<=1 && z>=0 )) return 1;
return 0;
}
double f(double x, double y, double z){
return 1;
}
#pragma omp parallel default(none) private(j,local_coi,x_,y_,z_) shared(count_of_iterations) reduction(+:total_sum,good_dots)
{
local_coi = count_of_iterations;
#pragma omp for(prng)
for (j = 1; j <= local_coi; j++){
#pragma omp critical(prng)
{
x_=x();
y_=y();
z_=z();
}
if (d(x_,y_,z_) == 1){
total_sum += f(x_,y_,z_);
good_dots += 1;
}
}
}
最佳答案
随机数生成器rand()
使用全局静态分配状态,由所有线程共享,因此不是线程安全的。从多个线程使用它,您会遇到对共享变量进行不 protected 访问的非常糟糕的情况,这会破坏缓存并减慢程序速度。您应该使用 rand_r()
或 erand48()
- 它们使用您必须提供的单独状态存储。您必须为每个线程声明一个状态(例如将其设为私有(private)),基本上为每个线程创建不同的 PRNG。然后你必须相应地播种它们,否则你会得到统计上不好的结果。原则上,您可以使用一个 rand48()
生成器的输出来为其他生成器提供种子 - 它应该足以获得中等长度的不相关序列。
这里是使用 rand_r()
的示例实现(并不是说这是一个用于蒙特卡洛模拟的非常糟糕生成器,erand48
更好最好是使用 GNU Scientific Library 中的“Mersenne Twister”类型生成器(如果可用):
unsigned int prng_state;
#pragma omp threadprivate(prng_state)
double x(){return (double)rand_r(&prng_state)/(double)RAND_MAX;}
double y(){return (double)rand_r(&prng_state)/(double)RAND_MAX;}
double z(){return (double)rand_r(&prng_state)/(double)RAND_MAX;}
int d(double x, double y, double z){
if ( ( (pow(x,2)+pow(y,2)) <1 ) && ( z<=1 && z>=0 )) return 1;
return 0;
}
double f(double x, double y, double z){
return 1;
}
...
#pragma omp parallel default(none) \
private(id,numt,x_,y_,z_) \
shared(count_of_iterations) \
reduction(+:total_sum,good_dots)
{
id = omp_get_thread_num() + 1;
numt = omp_get_num_threads();
// Sample PRNG seeding code - DO NOT USE IN PRODUCTION CODE!
prng_state = 67894 + 1337*id;
#pragma omp for
for (j = 1; j <= count_of_iterations; j++){
x_=x();
y_=y();
z_=z();
if (d(x_,y_,z_) == 1){
total_sum += f(x_,y_,z_);
good_dots += 1;
}
}
}
这只是一个非常糟糕的(从质量角度来看)实现,但它应该让您了解事情是如何工作的。这也是您如何通过对原始代码进行最少的更改来实现线程安全。基本要点是:
threadprivate
指令将 PRNG 状态 prng_state
设置为每个线程私有(private);x()
、
y 中,使用具有线程特定状态变量的
rand_r()
代替 rand()
()
和 z()
;prng_state = 67894 + 1337*id;
,以便不同的线程(希望)获得不相关的伪随机数流。请注意,rand()
和 rand_r()
的质量很差,这只是一个学术示例。使用较长的 PRNG 序列,您将在不同线程中获得相关流,这会破坏统计数据。我让您使用 erand48()
重写代码。
回答您最初的问题 - 所有线程安全函数调用都允许在并行 block 内。您还可以调用非线程安全函数,但必须保护(命名)关键
构造内的调用,例如:
#pragma omp for
for (j = 1; j <= local_coi; j++) {
#pragma omp critical(prng)
{
x_=x();
y_=y();
z_=z();
}
if (d(x_,y_,z_) == 1) {
local_sum += f(x_,y_,z_);
local_good_dots += 1;
}
}
这将确保不会并行调用rand()
。但您仍然可以对共享状态进行读-修改-写访问,因此会出现与缓存相关的速度减慢。
此外,请勿尝试重新实现 OpenMP reduction
或类似构造。编译器供应商已经投入巨大的努力来确保它们以尽可能最好(读取最快)的方式实现。
关于c - 并行 block 中允许哪些功能和操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13458471/
我的 blockly.js 文件中有以下代码 Blockly.Blocks['account_number'] = { // Other type. init: function() {
首先抱歉我的英语不好,我正在开发 Image Splitter 应用程序并且已经完成,但是现在的要求是当图像被分割(分成几 block /chunks)那么图像 block 的每一 block (ch
#value: 消息的返回值,当发送到一个 block 时,是该 block 中最后一句话的值。所以 [ 1 + 2. 3 + 4. ] value 计算结果为 7。我发现有时很难使用。有没有办法显式
我想构建一个包含 3 div 的响应式导航栏相同的 width和 height . 我申请了 inline-block到每个 block ,我得到一个我不理解的行为。 问题是,第三 block 由 2
我希望使用 Blockly 来允许非技术人员用户指定测试脚本。 它的一部分需要一个文件选择器,但是,我看不到 Blockly 有一个。是吗? 实际上,我找不到完整的标准 block 列表。谁有网址?
仅当您位于父 block 内部时,父 block 的 props.isSelected 才为 true,但当您在该 block 的 innerBlocks 内进行编辑时则不然。 如何从父 block
仅当您位于父 block 内部时,父 block 的 props.isSelected 才为 true,但当您在该 block 的 innerBlocks 内进行编辑时则不然。 如何从父 block
我想创建一个具有不同背景颜色 block 和不同悬停颜色 block 的导航栏 block 。我可以分别创建不同的悬停颜色 block 或不同的背景颜色 block ,但不能一起创建。所以请告诉我如何
我正在使用看到的代码 here定期执行代码: #define DELAY_IN_MS 1000 __block dispatch_time_t next = dispatch_time(DISPATC
为什么 block 必须被复制而不是保留?两者在引擎盖下有什么区别?在什么情况下不需要复制 block (如果有)? 最佳答案 通常,当您分配一个类的实例时,它会进入堆并一直存在,直到它被释放。但是,
我想弄清楚我这样做是否正确: 如果我有一个 block ,我会这样做: __weak MyClass *weakSelf = self; [self performBlock:^{
我想制作一个 4 block 导航菜单,虽然我已经显示了一个 block ,然后单击打开第二个 block ,从第二个开始选择并再次单击出现第三个 block ,第四个 block 相同...这是我的
例如,这样更好吗? try { synchronized (bean) { // Write something } } catch (Int
我想让一只乌龟检查前方小块的颜色并决定移动到哪里。如果前面的补丁不是白色的,那么乌龟向左或向右旋转并移动。我的 If 决策结构中出现错误,显示“此处应为 TRUE?FALSE,而不是 block 列表
我想创建一个 block 对角矩阵,其中对角 block 重复一定次数,非对角 block 都是零矩阵。例如,假设我们从一个矩阵开始: > diag.matrix [,1] [,2] [
我是区 block 链新手。突然我有一个问题,我们是否可以通过区 block 号来访问以太坊区 block 链上之前的区 block 数据。 例如我创建了一个block1、block2。 block
我是区 block 链新手。突然我有一个问题,我们是否可以通过区 block 号来访问以太坊区 block 链上之前的区 block 数据。 例如我创建了一个block1、block2。 block
我创建了一个等距环境,全部使用 Javascript 和 HTML5 (2D Canvas),大部分情况下工作正常。我面临的问题是使用不同高度的图 block ,然后对图 block 上的对象索引进行
这是令我困惑的代码: public Integer getInteger(BlockingQueue queue) { boolean interrupted = false; try
我有一个基于 TPL 数据流的应用程序,它仅使用批处理 block 和操作 block 就可以正常工作。 我已经添加了一个 TransformBlock 以尝试在发布到批处理 block 之前从源中转
我是一名优秀的程序员,十分优秀!