- 主题:经常看到内存屏障,查了很多资料,感觉自己不会编程了
这个问题可以简化版理解一下:比如x86平台下的2核处理器。对于head++,假如cpu核a执行了head++,那cpu核b此时的head怎么才能看到这个正确值?x86平台使用的是mesi做cpu间数据同步,但是mesi做cpu间同步是有缺陷的。cpu的核a需要等待cpu核b的明确返回消息才能执行下一步,如果这个时候核b执行死循环,此时的cpu核a也在忙等同步消息返回。为了解决这种缺陷,引入了invalid queue和store buffer。cpu核a通知核b的信息,自己更改的head++放入store buffer,核心b的head失效信息放在invalid queue中。此时核a缓存中的head和核b中的值都不是正确的值,写屏障的意思是:核a把store buffer的值刷新到缓存中,这个时候取值才是正确的;读屏障的意思是:核b取head的值,会检查invalid queue,如果发现缓存失效,去内存中取正确的值。他们的表现都是cpu指令乱序执行,本质是硬件层面引入mesi导致硬件层面不能保证指令信息同步,需要软件层面的内存屏障来保证。
【 在 freyoneby 的大作中提到: 】
: 比如一段代码
: head++;
: rear++;
: ....................
- 来自「最水木 for iPhone X」
--
FROM 183.192.23.*
我是觉得像cpu之间的cache同步,不应该做业务的去关心,架构设计上应该保证,cpu切换读取相同内存的时候,能够自动让这部分cache先回写,大部分都是各自领域专业的软件开发,还要关心这种东西,说明目前架构设计,编译器设计都不完美
【 在 leving 的大作中提到: 】
: 这个问题可以简化版理解一下:比如x86平台下的2核处理器。对于head++,假如cpu核a执行了head++,那cpu核b此时的head怎么才能看到这个正确值?x86平台使用的是mesi做cpu间数据同步,但是mesi做cpu间同步是有缺陷的。cpu的核a需要等待cpu核b的明确返回消息才能执行下一步,如果这个时候核b执行死循环,此时的cpu核a也在忙等同步消息返回。为了解决这种缺陷,引入了invalid queue和store buffer。cpu核a通知核b的信息,自己更改的head++放入store buffer,核心b的head失效信息放在invalid queue中。此时核a缓存中的head和核b中的值都不是正确的值,写屏障的意思是:核a把store buffer的值刷新到缓存中,这个时候取值才是正确的;读屏障的意思是:核b取head的值,会检查invalid queue,如果发现缓存失效,去内存中取正确的值。他们的表现都是cpu指令乱序执行,本质是硬件层面引入mesi导致硬件层面不能保证指令信息同步,需要软件层面的内存屏障来保证。
: - 来自「最水木 for iPhone X」
--
FROM 112.64.184.*
volatile的作用之一就是解决编译器乱序的,但是CPU乱序这个不好弄
【 在 freyoneby 的大作中提到: 】
: 这也是我疑惑的地方,已经不能相信编译器
--
FROM 124.202.185.*
业务层也好理解,没有一种语言保证在多线程对一个变量a执行a++ 100次,最后结果一定是100。如果你理解内存屏障,适当位置插入读写屏障能保证最后结果是对的。而不是无脑的使用mutex或者atomic。
【 在 freyoneby 的大作中提到: 】
: 我是觉得像cpu之间的cache同步,不应该做业务的去关心,架构设计上应该保证,cpu切换读取相同内存的时候,能够自动让这部分cache先回写,大部分都是各自领域专业的软件开发,还要关心这种东西,说明目前架构设计,编译器设计都不完美
: 【 在 leving 的大作中提到: 】
: : 这个问题可以简化版理解一下:比如x86平台下的2核处理器。对于head++,假如cpu核a执行了head++,那cpu核b此时的head怎么才能看到这个正确值?x86平台使用的是mesi做cpu间数据同步,但是mesi做cpu间同步是有缺陷的。cpu的核a需要等待cpu核b的明确返回消息才能执行下一步,如果这个时候核b执行死循环,此时的cpu核a也在忙等同步消息返回。为了解决这种缺陷,引入了invalid queue和store buffer。cpu核a通知核b的信息,自己更改的head++放入store buffer,核心b的head失效信息放在invalid queue中。此时核a缓存中的head和核b中的值都不是正确的值,写屏障的意思是:核a把store buffer的值刷新到缓存中,这个时候取值才是正确的;读屏障的意思是:核b取head的值,会检查invalid queue,如果发现缓存失效,去内存中取正确的值。他们的表现都是cpu指令乱序执行,本质是硬件层面引入mesi导致硬件层面不能保证指令信息同步,需要软件层面的内存屏障来保证。
- 来自「最水木 for iPhone X」
--
FROM 183.192.23.*
Consistency model确实不是做业务需要考虑的。有那么多debug好的thread-safe库,就不要重复造轮子了。更何况risc-v上的thread-safe concurrent data structure不是造轮子,而是造火箭 :)
不过我觉得现在armv8/risc-v的release consistency model已经是多核CPU最完美的consistency model了。x86 TSO约束的太死了,只允许read超前write,这导致coherence protocol设计和验证都太复杂,而且很多情况下软件也不需要那么严格的约束。release consistency刚刚好,软件只需要考虑acquire-release语义,按需要来决定程序要同步的地方,同时硬件上对于普通的read write可以任意乱序,提供了足够多的Memeory-level parallelism掩藏acquire/release coherence latency;同时release consistency又不像POWER那样有那么多乱序的可能性,搞出那么多种fence,学习成本太高
【 在 freyoneby 的大作中提到: 】
: 我是觉得像cpu之间的cache同步,不应该做业务的去关心,架构设计上应该保证,cpu切换读取相同内存的时候,能够自动让这部分cache先回写,大部分都是各自领域专业的软件开发,还要关心这种东西,说明目前架构设计,编译器设计都不完美
--
修改:MegaStone FROM 45.32.65.*
FROM 45.32.65.*
能提示一下哪些thread-safe好的库,请教请教
【 在 MegaStone 的大作中提到: 】
: Consistency model确实不是做业务需要考虑的。有那么多debug好的thread-safe库,就不要重复造轮子了。更何况risc-v上的thread-safe concurrent data structure不是造轮子,而是造火箭 :)
: 不过我觉得现在armv8/risc-v的release consistency model已经是多核CPU最完美的consistency model了。x86 TSO约束的太死了,只允许read超前write,这导致coherence protocol设计和验证都太复杂,而且很多情况下软件也不需要那么严格的约束。release consistency刚刚好,软件只需要考虑acquire-release语义,按需要来决定程序要同步的地方,同时硬件上对于普通的read write可以任意乱序,提供了足够多的Memeory-level parallelism掩藏acquire/release coherence latency;同时release consistency又不像POWER那样有那么多乱序的可能性,搞出那么多种fence,学习成本太高
:
--
FROM 112.64.184.*
就是线程交互,否则没有必要
【 在 chenpp 的大作中提到: 】
: 内存屏障多数情况下是针对多线程的情况吧
:
--
FROM 36.154.100.*
自修改程序呢?不过这种情况需要DSB/ISB
【 在 MaLing 的大作中提到: 】
: 就是线程交互,否则没有必要
: 【 在 chenpp 的大作中提到: 】
: : 内存屏障多数情况下是针对多线程的情况吧
: ....................
- 来自「最水木 for iPhone Xs Max」
--
FROM 98.165.80.171
x86上intel tbb和boost中的线程安全数据结构都可用。
risc-v上我没试过。boost应该可以。另外就是github上能搜到很多
【 在 freyoneby 的大作中提到: 】
: 能提示一下哪些thread-safe好的库,请教请教
--
FROM 120.244.190.*
居然到现在还没人提到
《What Every Programmer Should Know About Memory》
这本书。
【 在 freyoneby (freyoneby) 的大作中提到: 】
: 比如一段代码
: head++;
: rear++;
: ...................
--
FROM 140.224.34.*