问题标签 [false-sharing]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 在openmp中读取数据时会发生错误共享吗?
如果我有一个具有 OpenMP 并行化的 C++ 程序,其中不同的线程不断使用一些小的共享数组仅用于从中读取数据,在这种情况下是否会发生错误共享?换句话说,错误共享仅与内存写入操作有关,或者它也可能发生在内存读取操作中。
c++ - OpenMP 循环阵列访问中的虚假共享
我想利用 OpenMP 使我的任务并行。
我需要对数组的所有元素减去相同的数量并将结果写入另一个向量。两个数组都是动态分配的malloc
,第一个数组是用文件中的值填充的。每个元素都是 type uint64_t
。
我shift
想从vec
. size
是 和 的长度,vec
大约new_vec
为 200k。
g++ -fopenmp
我在 Arch Linux 上编译代码。我在 Intel Core i7-6700HQ 上,我使用 8 个线程。当我使用 OpenMP 版本时,运行时间要高 5 到 6 倍。当我运行 OpenMP 版本时,我可以看到所有内核都在工作。
我认为这可能是由虚假共享问题引起的,但我找不到。
c++ - 使用实体组件系统避免工作线程之间的错误共享
在 ECS 中存储组件的一种缓存有效的方法是将组件类型划分为大型数组,然后让每个系统对组件进行迭代。但是,假设我还想避免渲染和物理线程之间的错误共享,试图同时访问实体的坐标。
让我们假设一个高速缓存行是 64 字节大。假设我有一个 1 GiB 的“位置”数组。我可以将它分成 64 字节的页面,我只需要一个布尔值来存储页面是否繁忙(正在写入)。使用std::vector<bool>
, 每个布尔值仅使用 1 位,这将占用 2 Mib 的内存。
到目前为止,这听起来是可行的。但是,我仍然没有办法有效地处理工作线程发现页面繁忙的情况。
我应该忙着等吗?有没有解决这个问题的通用模式?
或者更重要的是,这是无痛的过度工程吗?我只是想让我的“家庭作业”框架扩展证明,以供学习。从来没有做过大型引擎,我不知道在这种情况下,虚假共享是否真的是一个值得注意的性能上限。
c++ - 为什么从多个线程使用相同的缓存行不会导致严重的减速?
看看这个片段:
这个小程序从四个不同的线程中多次递增四个相邻字节。之前,我使用的规则是:不要使用来自不同线程的相同缓存行,因为缓存行共享是不好的。所以我预计四线程版本 ( N=4
) 比单线程版本 ( ) 慢得多N=1
。
但是,这些是我的测量结果(在 Haswell CPU 上):
- N=1:1 秒
- N=4:1.2 秒
所以N=4
也不会慢很多。如果我使用不同的缓存行(替换*1
为*64
),那么N=4
会变得更快一点:1.1 秒。
原子访问的相同度量(交换注释typedef
),相同的缓存行:
- N=1:3.1 秒
- N=4:48 秒
所以这个N=4
案子要慢得多(正如我所料)。如果使用不同的高速缓存行,则N=4
具有类似的性能N=1
:3.3 秒。
我不明白这些结果背后的原因。为什么我不会严重减慢非原子N=4
案例?四个核心在它们的缓存中具有相同的内存,所以它们必须以某种方式同步它们,不是吗?它们如何能几乎完美地并行运行?为什么只有原子案例会严重放缓?
我想我需要了解在这种情况下内存是如何更新的。一开始,缓存中没有内核buffer
。在一次for
迭代后(in fn
),所有 4 个内核都buffer
在其缓存行中,但每个内核写入不同的字节。这些缓存行如何同步(在非原子情况下)?缓存如何知道哪个字节是脏的?还是有其他机制来处理这种情况?为什么这种机制比原子机制便宜很多(实际上,它几乎是免费的)?
c++ - OpenMP 并行区域中的这个 std::vector push_back 会导致错误共享吗?
下面的示例代码是我的工作代码的简化版本。在此代码中,写入共享变量仅在std::vector::push_back
调用的最后一行完成。
我想知道这个push_back
操作是否会导致错误共享,让我有机会通过摆脱它来进一步优化。在深入研究这个问题之前,我决定先做一些基准测试。
使用chrono
,我分别测量了挂钟some_heavy_work()
和临界区的执行时间。后者的执行时间大约是前者的10^(-4)倍,所以我得出的结论是,无论是否涉及虚假共享,优化这部分几乎没有任何好处。
无论如何,我仍然很好奇虚假共享是否是这里的一个问题。我是否必须查看 的内部实现std::vector
?任何启示将不胜感激。(我在VS2015上)
c - OpenMP - 没有错误共享的数组插入
我正在使用 C 语言中的 OpenMP 来并行化我的程序。我的程序中有一个部分将计算值插入到数组中。代码将是这样的:
从我了解到的情况来看,我认为这段代码会在数组中出现 False Sharing 问题arr
。为了避免这个问题,我找到了几种方法,例如:
- 数组填充
- 用块调度
这两种方法要求我知道我的处理器缓存大小有多大。假设我想在一个未知系统上运行我的程序(我不知道缓存大小有多大)。此代码是否有不需要我知道缓存大小的解决方法?或者可能是一个可以读取程序正在运行的系统的缓存大小的 C 代码?
java - 与非易失状态的虚假共享
在以下状态下是否会发生错误共享:
两个线程同时修改 x 和 y?还是无法判断编译器可能会将 x 和 y 优化为寄存器?
c - 虚假共享诊断/预防
在我的代码中,我有以下部分(简化)
并行化时,速度会急剧下降。我怀疑存在错误共享的问题,并且使用 valgrind 我发现在给定的执行中存在很多缓存未命中。
我没有提供关于 get_new_x 中发生的事情的详细信息,因为我想一次只专注于一件事;猜测在运行到函数调用的部分中发生了一些错误的共享是否合理?每个线程都有自己的 x,y,z,w 局部变量,但它们都将从同一个数组中读取。这是否足以导致缓存未命中?同样,我怀疑从 get_new_x 写入 out[] 时可能存在缓存冲突问题。
我想所有这些都是错误共享的可能原因,但是有什么方法可以解决它?是否有任何操作(读取与写入)或多或少会导致错误共享问题?
c++ - 避免虚假共享以提高性能
我使用上面的代码来演示虚假共享对性能的影响。但令我惊讶的是,填充似乎根本没有加速程序。有趣的是,如果两者a
都是b
原子变量,则有明显的改进。有什么不同?