首页 > 解决方案 > 跨线程共享读取资源

问题描述

这是一个关于多线程代码中读取性能的问题。

这就是这种情况。我有数千个实体需要知道才能做出反应的大量数据。这个数据改变每一帧,所以让我们调用它frame data

这些实体中的每一个都有一个需要在每一帧运行的函数,让我们调用它run()。函数 run() 需要经常读取(但从不写入)到frame data. 我们还假设它frame data在堆中,因此在创建新线程时不会克隆。

这些实体可能都run()在单个线程上按顺序排列,或者如果运行此代码的平台对实体有利,则这些实体可能会被批处理到多个 pthread 中,或者每个都run()在它们自己的 pthread 上。

所以基本上每个帧frame data都会更新,然后每个实体run()在任意线程上以任意顺序获取。

我意识到读取将花费相同的时间,但我担心的是线程在等待另一个线程完成读取simulation data. 这是一个有效的担忧吗?

不考虑复制的成本,为simulation data我创建的每个线程制作一份副本对我来说是个好主意,或者 CPU 是否可以让多个线程读取此资源?simulation data如果在堆栈上,这将如何变化。

标签: c++linuxmultithreadingoperating-systemcpu

解决方案


您似乎有一个经典的单作者/多读者队列。同步的一些策略包括RW-lockCircular Ring Buffers

由于缓存,拥有一个副本绝对是最好的策略。在现代架构中,队列条目将被第一个线程读入缓存,例如L3 。同一 CPU 上的后续线程将避免从 RAM 重新读取内存。队列条目的多个副本可能存在于多个 CPU 的高速缓存中。

线程将在 CPU 上进行时间切片,以便一次只运行一个。线程在读取相同数据时不会像互斥锁一样在串行锁的意义上相互阻塞。

为每个线程制作多个副本将是一个坏主意。即使数据完全相同,副本也会使缓存失效。

堆栈不跨线程共享。如果队列元素位于线程的本地堆栈上,则它是私有副本。如果通过指向主线程堆栈的指针访问队列元素,则将仅存在一个副本。让一个线程访问另一个线程的堆栈通常是一个糟糕的主意,但是因为可能出现竞争条件


推荐阅读