Cache ping-pong

 

Cache

CPU为了更快速度读取数据,都会用到Cache,因为直接访问RAM速度会比较慢。现代的CPU架构都会支持多级Cache,有单核独享的cache,也有多核共享的cache。

 

 

这样做读取速度是快了,但是在并发编程时就会遇到问题,如果任何一个核对数据有写操作,如何保证所有core都能及时看到新的数据?考虑如下程序:

1 std::atomic<int> counter{0};
2 
3 void thread_func(void)
4 {
5      counter++;  
6 }

如果两个线程在两个核上并发执行这个函数,会怎么样?如果每个core都使用自己cache中的counter值(初始值为0,所以两个core的私有cache中可能都是0)进行++操作,那么最终的结构有可能counter==1.因为如果两核不同步cache中对counter的缓存,就会出现这种问题。这就是cache的一致性问题。为了保证cache的一致性,那么有私有cache的CPU体系架构必须保证同一个cache line(cache里缓存的最小单位,可能是32、64或128字节)同一时刻只能由一个core缓存。通常的write-through cache(写操作一直穿透到RAM写完毕)为了实现这种一致性,会在某个core发现自己缓存的cache line被其他core命中(进入其他core的cache中)时,主动使自己缓存的cache line失效。也就是说如果这个core下面计算需要这份数据,需要重新从RAM中一级一级载入cache,而不再使用之前cache中的缓存。这就好像是对这个数据的读写失去了cache,每次都需要穿透到RAM的操作。

 

Cache ping-pong

当多个core要并行操作内存中的同一份数据,就会出现Cache ping-pong的问题,举个例子:

1. core1 从内存中加载Cache line做操作

2. core2 也要对这个数据操作,于是它也加载了这个Cache line。core1发现core2加载了这个cache line,于是让自己的加载的cache line失效

3. core1 又需要处理这个数据,core1需要重新从内存中加载这个cache line,同时导致core2的cache line失效

4. core2 又要处理这个数据,又要加载cache line,导致core1的cache line失效

5. 如此反复。

 

例如如下示例程序的处理过程。考虑core1,core2同时执行这个thread_func的情况。

std::atomic<int> counter{0};

void thread_func(void)
{
    while (counter < 100)
    {
          counter++;  
          // do other thing.
    }
}

cache ping-pong等效于cache失效,每次CPU都要从RAM中加载数据,这会导致很大的性能问题,这也是编写多线程程序需要考虑的设计问题。应该尽量避免代码中多个线程对同一数据资源的竞争。

 

False sharing

即使两个线程不操作同一个数据,也可能会导致cache ping-pong的问题,因为cache line的存在。考虑以下结构体:

struct flags {
      bool pushed;
      bool popped;
};

由于pushed和popped内存分布极为接近,它们几乎总会在一个cache line中被加载(cache line可能为32-128字节),如果两个core并行操作,一个修改pushed,一个修改popped,虽然修改的变量不同,一样会导致cache line ping-pong,因为cache line是一个整体(当然支持cache line能修改单字节而不是整体加载的CPU体系结构可能没有这个问题). 这就是False sharing的问题:虽然并行访问不同对象,但却像是访问同一个对象一样引起cache line ping-pong。

简单的解决方法通常也很粗暴——通过添加padding,强制pushed和popped分布在不同的cache line上,例如下面这样定义flags:

struct flags {
      bool pushed[N];
      char pad[LINE_SIZE];
      bool popped[N];
   } states;

 

关于cache的问题,先说这么多,祝大家好运。

posted on 2014-01-18 01:42  facile  阅读(3690)  评论(0)    收藏  举报

导航