免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: zylthinking
打印 上一主题 下一主题

为什么用户空间程序不用考虑内存屏障? [复制链接]

论坛徽章:
7
丑牛
日期:2013-10-18 14:43:21技术图书徽章
日期:2013-11-03 09:58:03辰龙
日期:2014-01-15 22:57:50午马
日期:2014-09-15 07:04:39丑牛
日期:2014-10-16 14:25:222015年亚洲杯之伊朗
日期:2015-03-16 10:24:352015亚冠之城南
日期:2015-05-31 09:52:32
51 [报告]
发表于 2011-10-16 17:39 |只看该作者
回复 44# asuka2001


    我也是这个意思。我只认为加上判断是解决A的数据依存问题,并没说能在B就获得标志和buf同步,确切的说在B接受的信息和A不是同一参考系。一个buf一个标志都从A传到B,谁先传到B本来就是不确切的,只有锁才会在各种条件下都保证一致。

论坛徽章:
0
52 [报告]
发表于 2011-10-17 09:52 |只看该作者
看完这个回复, 终于对内存屏障有了一个初步了解了;
现在的一个问题是, 为什么用户空间的程序不需要考虑 ...
zylthinking 发表于 2011-10-14 10:12



    编译器再怎么优化也不能打乱,有数据相关性的指令执行顺序的。线程A的那两条语句是不会 反序的。
  另外,内存屏障主要是用于 访问内存或IO寄存器的顺序的问题上。

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
53 [报告]
发表于 2011-10-17 09:59 |只看该作者
编译器再怎么优化也不能打乱,有数据相关性的指令执行顺序的。线程A的那两条语句是不会 反序的。 ...
zhoulongunix 发表于 2011-10-17 09:52


这个。。。感觉你需要再研究研究乱序了

论坛徽章:
0
54 [报告]
发表于 2011-10-17 10:45 |只看该作者
楼主的疑问清楚了,个人解决不了。
说一下个人观点:
应用程序考虑的应该是程序逻辑正确性。CPU乱序不应由应用程序员来考虑。
顺序执行,程序没有问题,优化后乱序提高效率就会导致问题,那也应该是编译器考虑不周。

楼主代码个人认为没有问题,像41楼仁兄自以为严谨,殊不知楼主只是贴出考虑问题的重点,还真是幽默!

论坛徽章:
17
水瓶座
日期:2013-08-29 12:09:27白羊座
日期:2014-08-07 12:36:42丑牛
日期:2014-07-24 12:44:41寅虎
日期:2014-04-16 16:15:33寅虎
日期:2014-03-12 09:28:43摩羯座
日期:2014-03-06 13:22:04技术图书徽章
日期:2014-03-06 11:34:50天蝎座
日期:2014-01-09 11:31:44寅虎
日期:2013-12-27 17:01:44双子座
日期:2013-12-27 12:32:29双子座
日期:2013-12-25 09:03:33丑牛
日期:2013-12-24 16:18:44
55 [报告]
发表于 2011-10-17 10:46 |只看该作者
本帖最后由 asuka2001 于 2011-10-17 10:52 编辑

回复 52# zhoulongunix

??? ptr->buffer的赋值和 ptr->enable的赋值,没有什么相关性啊?编译器和CPU怎么知道你程序逻辑里ptr->enable和ptr->buffer的关联呢?

除非你加上
if (ptr->buffer)
{
        ptr->enable = 1;
}
这样才算有吧?这里编译器和CPU才知道这2个之间有依赖!就没有判断而言,编译器是可以打乱指令的。
不过这个都不是重点,关键是我们要意识到:

在任何平台之下,如果能够保证比如边界对齐,与CPU字长相等的如int型(或者long型)的原子读,原子写。这种情况下,用它做同步会出现问题吗?

结论是这样的整形还是和锁,原子类型有差异,是不能够保证一定同步的,大家还是老实的使用锁和原子类型吧!

论坛徽章:
17
水瓶座
日期:2013-08-29 12:09:27白羊座
日期:2014-08-07 12:36:42丑牛
日期:2014-07-24 12:44:41寅虎
日期:2014-04-16 16:15:33寅虎
日期:2014-03-12 09:28:43摩羯座
日期:2014-03-06 13:22:04技术图书徽章
日期:2014-03-06 11:34:50天蝎座
日期:2014-01-09 11:31:44寅虎
日期:2013-12-27 17:01:44双子座
日期:2013-12-27 12:32:29双子座
日期:2013-12-25 09:03:33丑牛
日期:2013-12-24 16:18:44
56 [报告]
发表于 2011-10-17 10:55 |只看该作者
象编译器的乱序和CPU的乱序,都不是用户空间的程序员该关心的,锁和原子类型应该为大家考虑了。所以如果不用锁或者原子类型,那么估计就得自己去考虑了,这个难免考虑不周到而出现很诡异的BUG。。。而且很难查找!

论坛徽章:
0
57 [报告]
发表于 2011-10-17 17:09 |只看该作者
回复 1# zylthinking
至少指令进入CPU是顺序进入的, 只是在内部乱而已
zylthinking 发表于 2011-10-14 12:27

这么说来是不是意味着,机器指令乱序也只是发生在 当前被cpu流水执行的几条指令中?如果是的话,我就有疑问了
那么如果线程A乱序执行, 先 enable =true 后又发生线程切换到B, 岂不是挂了???
zylthinking 发表于 2011-10-14 10:12

这个malloc到机器指令上就是许多条,指令进cpu的顺序是:malloc的指令们->ptr赋值指令->enable赋值指令->线程切换指令们,而乱序的规模也仅在几条以内的话,即使enable赋值能先于ptr赋值完成,这个先也仅是几条指令的距离,而接下来就是线程切换的指令们,只要线程切换的指令数量比乱序的规模大的多,就可以保证malloc驻留在cpu中的指令们和ptr赋值指令在完成线程切换前完成,即最后执行线程B时就不会有问题。
这是以我菜鸟的见识推出来的,请诸位高手指正

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
58 [报告]
发表于 2011-10-17 17:28 |只看该作者
回复  zylthinking

这个malloc到机器指令上就是许多条,指令进cpu的顺序是:malloc的指令们->ptr赋值指令->enable赋值指令->线程切换指令们,而乱序的规模也仅在几条以内的话,即使enable赋值能先于ptr赋值完成,这个先也仅是几条指令的距离,而接下来就是线程切换的指令们,只要线程切换的指令数量比乱序的规模大的多,就可以保证malloc驻留在cpu中的指令们和ptr赋值指令在完成线程切换前完成,即最后执行线程B时就不会有问题。
这是以我菜鸟的见识推出来的,请诸位高手指正
jeung 发表于 2011-10-17 17:09


这个估计问塑料袋才能彻底清楚, 我自己理解如下:
1. 单CPU下, 确实可能存在你所说的就算乱序, 也来不及作怪的情景---但其实这不是一个问题, 就算线程切换短到只有一个指令就能完成, 照样不出错, 究其原因, 至少是因为虽然是2个线程, 但是是一个CPU, 它自己做出的改变他自己知道。 换句话说, 还是之前塑料袋在一个帖子里提到的, 指令进CPU是顺序的, 即便执行结果反映在寄存器是乱序的(x86反映在寄存器也不是乱序的), 但CPU是知道它已经缓存了一个 ptr->buffer = xxx 的赋值指令, 那么if(ptr->enable) 通过后, 下一步的 memcpy() 就要用这个 ptr->buffer了, 它肯定是先执行赋值, 然后再 memcpy

2. 但多 CPU 就没这么幸运了, 因为是一个不同的CPU, 它的缓存是不知道 ptr->buffer = xxx 这回事的, 如果没有相应手段, 问题就会出来

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
59 [报告]
发表于 2011-10-19 15:14 |只看该作者
看完这个回复, 终于对内存屏障有了一个初步了解了;
现在的一个问题是, 为什么用户空间的程序不需要考虑 ...
zylthinking 发表于 2011-10-14 10:12



    函数调用,应该不会做此种倒序.指令乱序是基于对内存先后写入顺序无所谓这样的认识基础之上的.

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
60 [报告]
发表于 2011-10-19 15:26 |只看该作者
多CPU如果不考虑这个原则, 那就真的对应用程序来说是灾难了, 问题是几乎没有内存屏障概念的用户空间代 ...
zylthinking 发表于 2011-10-14 13:58



    O3写出问题,那都是因为该加volatile的地方不加,O3本身应该是符合单线程的语意而没有问题的.很多人写多线程应用程序的时候需要加volatile的地方不加volatile,我一直很奇怪
   另外,由这个问题居然扯到CPU的乱序,就是概念不清
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP