多核并行编程中的内存栅栏

来源:互联网 发布:sql server中通配符 编辑:程序博客网 时间:2024/05/22 15:17

随着多核,众核已经进入了产品应用的时代,并行编程是不可避免遇到的问题,在工作中,也遇到了这方面的一些问题。

不管是多进程或是多线程数据,总会存在通信问题,在并行编程中最常用的方式就有共享内存,在原有的概念中,共享内存无非是lock锁的问题,但是随着核数越来越多,如果继续使用锁的工作机制,锁的碰撞几率就会变得非常高,这个时候对于critical reource的竞争将会非常激烈, 在我们不考虑“异步消息传递并行模型”的情况下,极大能力减小锁的粒度甚至与避免锁是常规的思考方法。

如想通过队列无锁的方式:

typedef struct{  entry_s       **EntryPtrArray;  uint32_t      cnt;      // 目前长度  uint32_t      size;     // 队列总长度  uint64_t      push_nr;  // 放入总计数  uint64_t      pop_nr;   // 取出总计数  uint32_t      head;     // 头  uint32_t      tail;     // 尾
}shared_queue_s;

在上面的结构中,工作在无锁模式下,push_nr-pop_nr 和size之间比较是是否可放入队列的判断条件,每次放入,都会执行push_nr+1和(head+1)%size的操作,而取出执行pop_nr+1 和 (tail+1)%size的操作, 似乎可以正常work起来,其实不然,因为在多核编程下,因为内存模型(一致性)和加速并行处理而存在的乱序执行的问题,将实际上你认为正确的代码变得"不正确了"。

针对该问题的解决方案是内存栅栏(memory fence)

针对这有不同的实现方式:

1. 前往不要抱有volatile解决问题的想法,虽然某些硬件平台(具体不知道)和vs等编译器支持acquire 和 release语义。

2. 使用memory barrier,__asm__ __volatile__("":::"memory"),但是这会将缓存中的数据都刷到内存,会严重影响效率

3. 同样的影响效率的方式,对数据实现强不可被cache,这样在系统总线上的读写会以程序次序,而不被无序执行


注意:  有些弱一致性体系下还需要将信息反映到其他核上,tilera还需要使用指令__insn_mf()来实现


原创粉丝点击