我有一个需要可视化的粒子系统。但是可视化应该对模拟本身没有任何影响。目前发生这种情况的方法是让第二个线程在没有任何同步的情况下读取粒子系统的状态。这当然会导致模拟显示一些故障,但这不是问题。
然而,似乎发生的事情是渲染呈现的速度越快,粒子系统变得越慢。模拟的测量时间步长达到峰值,平均几乎翻倍。我相当肯定这是因为渲染器从不同的线程访问粒子系统使用的内存。
现在的问题是;是否有可能在较小的范围内扰乱粒子系统?可视化的准确性根本不是问题。理论上我可以想象某种方法来指示编译器渲染器纯粹是只读的和/或它不需要"最近"版本的数据。但我不知道如何处理这个问题。
PS。语言:C ++,IDE:Visual Studio
PSS。当然,由于较少的内存访问,保持渲染器的FPS已经有所帮助,但是模拟的测量时间步长仍然会出现峰值并减慢。
答案 0 :(得分:1)
您的系统速度变慢,因为当您进行模拟时,您的数据很可能是在缓存级别1-2中。缓存行位于"修改"状态和对这些高速缓存行的每次读写都是没有总线事务的高速缓存命中(即快速)。
一旦你运行另一个线程访问相同的数据,模拟所做的更改需要传播到一致性点,因此可视化过程(在另一个CPU核心上运行)可以读取它们。所以缓存行的状态从" Modified"到共享"共享"状态。
然后,一旦模拟线程想要再次修改该共享数据,缓存行就会从"共享"回到"修改"生成状态和总线事务,因此其他高速缓存中的高速缓存行无效。
因此,即使从另一个线程读取也会减慢模拟速度,因为缓存行在状态之间跳转,并且很多总线事务正在下面进行。在英特尔上,缓存一致性协议称为MESI(F),你可以在维基百科上找到更多内容:
https://en.wikipedia.org/wiki/MESI_protocol
关于如何处理这个问题。基本上,您应该避免同时读取和写入相同的数据。这很难,但您可能需要考虑以下事项:
您可能会尝试修改模拟,因此它可以在两组数据上运行。一个银行将用于模拟,而另一个银行用于可视化以前计算的数据。
在模拟循环结束后,您可能会尝试简单地在可视化线程中复制数据。它将修复故障,并可能改善整体性能。
要在模拟和可视化线程之间进行同步,您应该使用忙等待(如自旋锁),而不是内核对象,如互斥锁。
所有这一切都说明,没有任何保证会对你的案件有所帮助。这一切都取决于您的数据,CPU,缓存大小等。