问题标签 [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 回答
13489 浏览

c - 避免在 OpenMP 中使用数组进行错误共享

我已经开始学习如何在大学课程中使用 OpenMP。作为实验室练习,我们得到了一个需要并行化的串行程序。

我们首先意识到False Sharing的危险,尤其是当涉及到并行更新数组时 for 循环。

但是,我发现很难将以下代码片段转换为可并行化的任务而不会导致错误共享:

我的第一反应是尝试分享ukp1

但这清楚地表明与串行版本相比显着放缓。显而易见的原因是在对ukp1的某些写入操作期间发生了错误共享。

我的印象是也许我可以使用归约子句,但是我很快发现这不能用于数组。

有什么我可以用来并行化此代码以改善运行时的吗?有没有我没听说过的可以使用的子句?或者这是我需要重组代码以允许适当并行化的任务?

所有形式的输入将不胜感激!

编辑:有人指出我的代码有错误。我本地的代码是正确的,我只是错误地编辑了它(改变了代码的结构),很抱歉造成混乱!

编辑2

@Sergey 向我指出的一些我觉得有用的信息:

  • 将 uk 或 ukp1 设置为 private 本质上与将它们设置为 shared 具有相同的效果,因为它们都是指向同一内存位置的指针

  • 理论上使用静态调度应该会有所帮助,但我仍然遇到同样的减速。另外,我觉得静态调度不是解决这个问题的最便携的方法。

0 投票
1 回答
190 浏览

c - 在这种情况下,您将如何避免虚假共享?

在下面的代码中,我使用 OpenMP 的标准parallel for子句进行了并行化。

这让我的运行时间有了显着改善(~140s 到 ~40s),但我注意到仍然有一个领域确实落后了——我在上面标记的最里面的循环。

我肯定知道上面的数组会导致错误共享,因为如果我在下面进行更改,我会看到性能的另一个巨大飞跃(约 40 秒到约 13 秒)。

换句话说,只要我将内存位置更改为写入私有变量,就会有巨大的加速提升。

在我刚刚解释的场景中,有什么方法可以通过避免错误共享来改善我的运行时间?即使问题本身被提及很多,我似乎也无法在网上找到许多似乎有助于解决此问题的资源。

我有一个想法来创建一个过大的数组(需要的 10 倍),以便在每个元素之间保持足够的边距空间,以确保当它进入缓存行时,没有其他线程会拾取它。然而,这未能产生预期的效果。

是否有任何简单的(或者如果需要的话甚至很难)方法来减少或删除该循环中发现的错误共享?

任何形式的见解或帮助将不胜感激!

编辑:假设 some_calculation() 执行以下操作:

我无法将此计算移出我的 for 循环,因为我依赖于为每次迭代计算的 d_equ。

0 投票
0 回答
114 浏览

caching - 虚假共享和缓存对齐

我在 C++ 中有以下代码(稍后解释):

在 64 位 linux 机器上的输出是:

每个电阻器都有一组属性,这些属性将由线程修改(读取和写入)。理想情况下,它们可以被视为线程私有变量。但是,由于旧代码库施加的一些限制,我只能采用以下三种方法之一:

  • 方法 0:在每个电阻器结构中,声明“线程私有”变量数组。线程 0 将使用 mean_tau[0]、offset[0]..,线程 1 将使用 mean_tau[1]、offset[1]...等等。据我了解,这不是一个好方法,会导致很多虚假分享。
  • 方法 1:电阻器的每个实例中的 struct th_private 的一维数组,其中 state[0] 仅由 thread[0] 使用,state[0] 仅由 thread[1] 使用,依此类推。可能会消除错误共享,但如何确保它在缓存中对齐?
  • 方法 2:声明一个全局 2D 矩阵,其中每一行属于一个线程,每一列属于一个电阻器(代码中的更多详细信息)。

现在,i) 避免错误共享和 ii) 缓存对齐,哪种方法最好?

0 投票
1 回答
782 浏览

c - Cuda GPU 中的虚假共享:它是否存在/类似于 CPU?

我了解在对称多处理器 (SMP) 系统中,由于每个内核中的单独缓存,可能会发生错误共享,如下代码: http: //software.intel.com/en-us/articles/avoiding-and-identifying -假线程间共享

所以我的问题是:

  1. 错误共享主要来自这样一个事实:内存是通过由固定数量的字节组成的块来访问的,并且每个进程都有自己的缓存。这块内存是一起写入和读取的。我的理解接近事实吗?
  2. GPU中的内存访问模式怎么样?所有的流处理器是共享一组缓存还是有单独的缓存?虚假共享是否也是 GPU 计算中的一个问题?
0 投票
0 回答
554 浏览

optimization - 康威的人生游戏:openMP 优化

我正在尝试为康威的生命游戏优化我的 openMP 代码。我的主要问题可能与虚假共享有关。这是我的代码:这是我的类“mondo”中的一个方法。m 是我的方案,r 是行数,c 是列数,我使用的是环形方案。

0 投票
1 回答
6703 浏览

caching - 什么是“虚假分享”?如何重现/避免它?

今天我和我的教授在并行编程课上对什么是“虚假共享”有了不同的理解。我的教授说的没有道理,所以我立即指出。她认为“虚假分享”会导致节目结果出现错误。

我说过,当不同的内存地址分配给同一个缓存行时,会发生“错误共享”,将数据写入其中一个会导致另一个被踢出缓存。如果处理器在两个虚假共享地址之间来回写入,它们都不能留在缓存中,因此所有操作都会导致对DRAM的访问。

到目前为止,这是我的看法。事实上,我也不确定我所说的......如果我有误解,请指出。

所以有一些问题。缓存假定为 64 字节对齐,4 路组关联。

  1. 两个超过 64 字节的地址是否有可能是“虚假共享”?
  2. 单线程程序是否可能遇到“错误共享”问题?
  3. 重现“虚假共享”的最佳代码示例是什么?
  4. 一般来说,避免程序员“虚假分享”应该注意什么?
0 投票
1 回答
382 浏览

c++ - 发出信号并保持pthread打开的有效方法?

我有一些代码试图运行一些密集的矩阵处理,所以我认为如果我多线程它会更快。但是,我的目的是让线程保持活动状态,以便将来可以使用它进行更多处理。这是问题所在,代码的多线程版本比单线程运行得慢,我相信问题在于我发出信号/保持线程存活的方式。

我在 Windows 和 C++ 上使用 pthreads。这是我的线程代码,其中runtest()是发生矩阵计算的函数:

playQueue()函数是传递给 pthread的函数,到目前为止,我所拥有的是一个队列(testQueue),可以说是 1000 个项目,并且有 100 个线程。每个线程将继续运行,直到队列为空(因此互斥锁内的东西)。

我相信多线程运行如此缓慢的原因是因为所谓的虚假共享(我认为?)以及我向线程发出信号以调用runtest()并保持线程存活的方法很差。

什么是这样做的有效方法,以便多线程版本将运行得更快(或至少与迭代版本一样快)?

这是我的代码的完整版本(减去矩阵的东西)

所以在这里,“matrix_exponential_tests”是从这个网站上获得许可的,是所有矩阵数学发生的地方。该计数器仅用于调试并确保所有实例都在运行。

0 投票
1 回答
650 浏览

c++ - 错误共享的openMP性能不佳

我知道它存在这个线程 openMP 性能

但这里我的例子很简单

C代码:

当我在没有 openMP 的情况下使用 openMP 0.015s 对使用 openMP 的 0.045 秒(szGlobalworkSize = 131072)时,此示例的时间会增加

我使用这行 gcc:gcc -march=native -fopenmp -O3 MyCode.c -lm

gcc (GCC) 4.8.2 20140120 (红帽 4.8.2-15)

编辑1:

同时与块与 memalign

用线程计时编辑 2

每个线程需要 0.015,总共需要 0.045,因此 openmp 中有一个 0.03 的修复部分。奇怪的是,即使尺寸很大,我们也看到 openmp 的这个修复部分和工作较少的线程需要与整个大小相同的时间(48 个线程这里)

谢谢

0 投票
1 回答
374 浏览

multithreading - 当线程只写入同一个缓存块时,是否也会发生错误共享?

如果我们有两个核心在同一个缓存块中读取和写入不同的内存位置,则两个核心都被迫一次又一次地重新加载该缓存块,尽管这在逻辑上是不必要的。这就是我们所说的虚假分享。

但是,如果内核从不从该缓存块中读取,而只是写入呢?想象一下,两个内核只是在同一个缓存块中设置了一些位,但它们不必从该块中读取,因为它们设置的位信息仅在程序的后期阶段需要。

只有当内核在同一个块上读取和写入时才会发生错误共享,还是如果两者都只写入它也会发生?

0 投票
1 回答
240 浏览

openmp - OpenMp 代码的性能

我已经为矩阵向量乘法编写了代码。矩阵根据线程数被划分为行块,每个块乘以向量,向量存储在线程私有的数组中。但是我的加速很差。对于大小为 16 X 16 的矩阵,它小于 1。

这可能是因为我将我的矩阵和向量在外部声明为共享变量,并且当每个线程尝试从矩阵和向量中读取值时可能会导致竞争条件/错误共享?

我对虚假共享和竞争条件有点困惑。