parallel-processing - 写入单个向量时 OpenMP 中的错误共享
问题描述
我是通过Tim Matterson 的讲义学习 OpenMP 的,他举了一个虚假共享的例子,如下所示。代码很简单,用于从 4.0/(1+x*x) 的数值积分计算 pi,x 范围为 0 到 1。代码使用向量来包含 4.0/(1+x*x) 的值对于从 0 到 1 的每个 x,然后对最后的向量求和:
#include <omp.h>
static long num_steps = 100000;
double step;
#define NUM_THREADS 2
void main()
{
int i, nthreads; double pi, sum[NUM_THREADS];
step = 1.0/(double)num_steps;
omp_set_num_threads(NUM_THREADS);
#pragma omp parallel
{
int i, id, nthrds;
double x;
id = omp_get_thread_num();
nthrds = omp_get_num_threads();
if (id == 0) nthreads = nthrds;
for (i=id, sum[id]=0.0; i<num_steps; i=i+nthrds){
x = (i+0.5)*step;
sum[id] += 4.0/(1.0+x*x);
}
}
for (i=0; pi=0.0; i<nthreads;i++) pi += sum[i]*step;
}
我对这个示例中的虚假共享有一些疑问:
- 是不是因为写入数组的工作在两个线程(即[thread0, thread1, thread0, thread1, ...])之间间歇性地划分而导致的错误共享?如果我们使用
#pragma omp parallel for
,那么数组将被划分为 [thread0, thread0, thread0, ...., thread1, thread1, thread1, ...],那么我们是否仍然存在错误共享,现在每个地址都被访问线程彼此相距很远? - 如果我有一份工作用于
#pragma omp parallel for
写入与我的输入向量具有 1 对 1 对应关系的输出向量(例如,输入是预测变量矩阵,输出是预测向量),那么我什么时候需要担心虚假分享?
解决方案
本教程不断向 Stack Overflow 发送困惑的人 - 有时自下而上学习并不是一个好主意。
该数组
sum
只有2 === NUM_THREADS
条目,即[sum of thread 0, sum of thread 1
]。这些值可能在同一缓存行上,因此会导致错误共享。如果输入和输出向量足够多(即每个线程有数百个元素),那就没问题了。您应该始终使用惯用的 OpenMP,即使用
parallel for
而不是本教程有问题的示例中展示的手动工作共享。那么默认情况下就可以了,因为 OpenMP 会将相邻的索引分配给同一个线程。
如果您还没有达到教程中的重点,请确保使用内置的归约关键字,而不是像示例中公开的那样手动组合归约。
推荐阅读
- html - 纯 CSS 中非全宽 div 的视差滚动
- php - 过滤具有相同值的数组键
- java - Java combining two hashmaps of the same type into a new hashmap keeping duplicates
- python - 用于固定字符长度的 Python 正则表达式
- cordova - 尝试运行离子项目时出错
- rust - 在命令缓冲区执行之间清除非瞬态图像
- java - Spark 独立模式:有没有办法以编程方式从 Spark 的 localhost:8080 获取每个工作人员的核心/内存信息
- powershell - 记录 Powershell 模块:您应该对输出类型有多具体?
- c# - 如何强制实体框架允许数据库创建 GUID PK?
- python - 使用 Python 抓取返回变量值