问题标签 [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.

0 投票
2 回答
1163 浏览

c++ - 在openmp中读取数据时会发生错误共享吗?

如果我有一个具有 OpenMP 并行化的 C++ 程序,其中不同的线程不断使用一些小的共享数组仅用于从中读取数据,在这种情况下是否会发生错误共享?换句话说,错误共享仅与内存写入操作有关,或者它也可能发生在内存读取操作中。

0 投票
1 回答
1742 浏览

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 版本时,我可以看到所有内核都在工作。

我认为这可能是由虚假共享问题引起的,但我找不到。

0 投票
0 回答
258 浏览

false-sharing - 了解虚假分享示例

我正在研究错误共享,我有一个关于如何通过填充数组来避免它的示例:

代码示例

只要确保我理解正确,这只有在我们使用 8 字节整数时才有效,对吧?如果我们使用 4 字节整数,整个数组将是 64 字节,它不会避免错误共享。

0 投票
0 回答
212 浏览

c++ - 使用实体组件系统避免工作线程之间的错误共享

在 ECS 中存储组件的一种缓存有效的方法是将组件类型划分为大型数组,然后让每个系统对组件进行迭代。但是,假设我还想避免渲染和物理线程之间的错误共享,试图同时访问实体的坐标。

让我们假设一个高速缓存行是 64 字节大。假设我有一个 1 GiB 的“位置”数组。我可以将它分成 64 字节的页面,我只需要一个布尔值来存储页面是否繁忙(正在写入)。使用std::vector<bool>, 每个布尔值仅使用 1 位,这将占用 2 Mib 的内存。

到目前为止,这听起来是可行的。但是,我仍然没有办法有效地处理工作线程发现页面繁忙的情况。

我应该忙着等吗?有没有解决这个问题的通用模式?

或者更重要的是,这是无痛的过度工程吗?我只是想让我的“家庭作业”框架扩展证明,以供学习。从来没有做过大型引擎,我不知道在这种情况下,虚假共享是否真的是一个值得注意的性能上限。

0 投票
2 回答
2847 浏览

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在其缓存行中,但每个内核写入不同的字节。这些缓存行如何同步(在非原子情况下)?缓存如何知道哪个字节是脏的?还是有其他机制来处理这种情况?为什么这种机制比原子机制便宜很多(实际上,它几乎是免费的)?

0 投票
2 回答
1897 浏览

c++ - OpenMP 并行区域中的这个 std::vector push_back 会导致错误共享吗?

下面的示例代码是我的工作代码的简化版本。在此代码中,写入共享变量仅在std::vector::push_back调用的最后一行完成。

我想知道这个push_back操作是否会导致错误共享,让我有机会通过摆脱它来进一步优化。在深入研究这个问题之前,我决定先做一些基准测试。

使用chrono,我分别测量了挂钟some_heavy_work()和临界区的执行时间。后者的执行时间大约是前者的10^(-4)倍,所以我得出的结论是,无论是否涉及虚假共享,优化这部分几乎没有任何好处。

无论如何,我仍然很好奇虚假共享是否是这里的一个问题。我是否必须查看 的内部实现std::vector?任何启示将不胜感激。(我在VS2015上)

0 投票
1 回答
506 浏览

c - OpenMP - 没有错误共享的数组插入

我正在使用 C 语言中的 OpenMP 来并行化我的程序。我的程序中有一个部分将计算值插入到数组中。代码将是这样的:

从我了解到的情况来看,我认为这段代码会在数组中出现 False Sharing 问题arr。为了避免这个问题,我找到了几种方法,例如:

  1. 数组填充
  2. 用块调度

这两种方法要求我知道我的处理器缓存大小有多大。假设我想在一个未知系统上运行我的程序(我不知道缓存大小有多大)。此代码是否有不需要我知道缓存大小的解决方法?或者可能是一个可以读取程序正在运行的系统的缓存大小的 C 代码?

0 投票
3 回答
259 浏览

java - 与非易失状态的虚假共享

在以下状态下是否会发生错误共享:

两个线程同时修改 x 和 y?还是无法判断编译器可能会将 x 和 y 优化为寄存器?

0 投票
0 回答
66 浏览

c - 虚假共享诊断/预防

在我的代码中,我有以下部分(简化)

并行化时,速度会急剧下降。我怀疑存在错误共享的问题,并且使用 valgrind 我发现在给定的执行中存在很多缓存未命中。

我没有提供关于 get_new_x 中发生的事情的详细信息,因为我想一次只专注于一件事;猜测在运行到函数调用的部分中发生了一些错误的共享是否合理?每个线程都有自己的 x,y,z,w 局部变量,但它们都将从同一个数组中读取。这是否足以导致缓存未命中?同样,我怀疑从 get_new_x 写入 out[] 时可能存在缓存冲突问题。

我想所有这些都是错误共享的可能原因,但是有什么方法可以解决它?是否有任何操作(读取与写入)或多或少会导致错误共享问题?

0 投票
1 回答
765 浏览

c++ - 避免虚假共享以提高性能

我使用上面的代码来演示虚假共享对性能的影响。但令我惊讶的是,填充似乎根本没有加速程序。有趣的是,如果两者a都是b原子变量,则有明显的改进。有什么不同?