并发内存访问减慢系统速度



我有一个需要可视化的粒子系统。但可视化实际上应该对模拟本身没有影响。目前发生这种情况的方式是让第二个线程读取粒子系统的状态,而无需任何同步。这当然会导致模拟显示一些故障,但这不是问题。

然而,似乎发生的事情是渲染渲染得越快,粒子系统变得越慢。模拟的测量时间步长出现峰值,平均几乎翻倍。我相当确定这是由于渲染器从不同的线程访问粒子系统使用的内存。

现在的问题是:是否有可能以某种方式在较小的范围内干扰粒子系统?可视化的准确性根本不是问题。从理论上讲,我可以想象某种方法来指示编译器渲染器是纯只读的和/或它不需要数据的"最新"版本。但我不知道如何处理这个问题。

语言:C++,IDE:Visual Studio

PSS。当然,由于内存访问较少,保持渲染器的低 FPS 已经有所帮助,但模拟的测量定时步长仍然会飙升并减慢速度。

您的系统速度变慢,因为当您只进行模拟时,您的数据很可能处于缓存级别 1-2 中。缓存行处于"已修改"状态,对这些缓存行的每次读取和写入都是没有总线事务(即快速)的缓存命中。

一旦运行另一个线程访问相同的数据,模拟所做的更改需要传播到一致性点,以便可视化过程(在另一个 CPU 内核上运行)可以读取它们。因此,缓存行的状态从"已修改"状态转换为"共享"状态。

然后,一旦模拟线程想要再次修改该共享数据,缓存行就会从"共享"转换回"已修改"状态并生成总线事务,因此其他缓存中的缓存行将失效。

因此,即使从另一个线程读取也会减慢模拟速度,因为缓存行在状态之间跳跃,并且许多总线事务都在下面进行。在英特尔上,高速缓存一致性协议称为MESI(F),您可以在维基百科上找到更多信息:

https://en.wikipedia.org/wiki/MESI_protocol

关于如何处理这个问题。基本上,您应该避免同时读取和写入相同的数据。这很难,但您可能需要考虑以下几点:

  1. 您可以尝试修改模拟,使其对两个数据库进行操作。一个库将用于模拟,而另一个库将用于可视化先前计算的数据。

  2. 您可以尝试在模拟循环完成后立即一次性复制可视化线程中的数据。它将修复故障,并可能提高整体性能。

要在模拟线程和可视化线程之间同步,您应该使用繁忙等待(如旋转锁),而不是内核对象,如互斥锁。

综上所述,无法保证这些技术中的任何一种都会对您有所帮助。这完全取决于您的数据,CPU,缓存大小等。

相关内容

  • 没有找到相关文章

最新更新