我有很多进程,大约16个(但设计限制是几百个)通过共享内存进行通信。每个进程在共享内存中都有一个保留区域,用于放置请求。当请求为其他人准备好时,它会设置每个进程位" RequestReady"。其他进程正在读取短期自旋循环内的RequestReady位,并在设置位时执行操作。这特定于我们的需求,并且内核信号量也经常使用,但旋转循环对于我们的高度特定需求(测试)更快
我对x86平台上的跨套接字缓存一致性的效果特别感兴趣,而不是共享的L2 / L3缓存设计。这不是关于亲和力的问题,我知道使用它。
目前,我有" RequestReady"位间隔开,以便每个进程的位都在单独的高速缓存行上。逻辑上像
struct {
unsigned long RequestReady;
char DataArea[5000];
} ProcessSlots[MAX_SLOTS];
这意味着我基本上有MAX_SLOTS的缓存行,无效。优点是只有一个核心将写入缓存行,而其他套接字只需要重新验证。这意味着作者不会(不应该?)写档,但读者会在他们扫描工作的某个阶段。缺点是我使用了许多可能对其他东西更好的缓存行。
另一种布局是
unsigned long RequestReady[MAX_SLOTS];
char DataArea[5000*MAX_SLOTS];
这意味着所有RequestReady标志都在一个缓存行中,因此我只有一个缓存无效消息,但我担心创建这样的热点,一个基本上在每个套接字/核心共享的热点。这会降级,以便每个对此高速缓存行的读/写都将转到主内存吗?
RequestReady位经常切换(大约10,000 /秒)并经常扫描(大约100K到10M /秒)。我知道我会经常使用主内存访问速度,但是想要一个可以在这么热的区域内最小化这种内容的布局。
布局这些RequestReady位的好方法是什么?是否有其他布局我还没有考虑过?在第二种方法中,我的第一种方法是否对作者有任何好处?