seb*_*007 3 multithreading atomic openmp shared-memory
我在 C++ 中有一个 openmp 并行循环,其中所有线程都访问一个共享的 double 数组。
我是否需要原子写入来确保读取的数据有效(旧的或更新的),或者仅当多个线程尝试在同一位置写入时才需要原子写入?
它似乎可以在有或没有原子写入的情况下工作,但如果没有原子写入,当然速度更快。
对于正确的可移植程序,您应该使用原子写入和读取。根据标准规定:
\n\n\n\n\n2.13.6 原子构造
\n\n[...] 为了避免竞争条件,对 x 指定的可能并行发生的位置的所有访问都必须使用原子构造进行保护。
\n
更详细地说:
\n\n\n\n\n1.4.1 OpenMP 内存模型的结构
\n\n[...]
\n\n对变量的单次访问可以使用多个加载或存储指令来实现,因此不能保证相对于对同一变量的其他访问是原子的。
\n\n[...]
\n\n如果至少一个线程从存储器单元读取并且至少一个线程在不同步到该同一存储器单元的情况下写入,包括由于如上所述的原子性考虑的情况,则发生数据争用。如果发生数据竞争,则程序的结果是不确定的。
\n
除了原子性之外,还应该考虑可见性:
\n\n\n\n\n1.4.3 冲洗操作
\n\n内存模型具有宽松一致性,因为线程\xe2\x80\x99的内存临时视图不需要始终与内存保持一致。写入变量的值可以保留在 thread\xe2\x80\x99s 临时视图中,直到稍后强制存储到内存中。同样,从变量读取可以从 thread\xe2\x80\x99s 临时视图中检索值,除非强制从内存中读取。OpenMP 刷新操作强制临时视图和内存之间的一致性。
\n
这意味着,除非您有任何显式或隐式内存刷新,否则无法保证您会看到更新的值。
\n\n然而,原子版本并不一定较慢。实现原子操作的编译器知道该体系结构的特定内存模型并可以自由地利用它。事实上,gcc 和 clang 都不会为在 x86 上原子写入或读取 a生成昂贵的锁double,而对于原子增量或long double操作则这样做。不幸的是,原子可能仍然阻碍某些优化 - 但如果您省略了 .txt 文件,这些很可能会导致未指定的结果atomic。不要低估编译器优化:对于严格来说不符合标准的明显合理的程序,很容易出现未定义的行为。
至于内存刷新对性能的影响,取决于您的实际算法需要刷新内存的频率。
\n| 归档时间: |
|
| 查看次数: |
1278 次 |
| 最近记录: |