smalloc 发表于 2011-10-15 11:36

本帖最后由 smalloc 于 2011-10-15 12:35 编辑

LZ不懂多线程编程,建议好好看看 POSIX多线程程序设计 这书。
另你这段程序有问题,没有判断malloc是否成功就设置了变量。从而造成了标志和分配内存的2个事务的不相关性。不相关或独立性才是乱序之根源。
你做一个判断再设置标志看看CPU还能乱序不?
可以这样理解。C语言在语句上单参考系的顺序模型。但处理器因为乱序却有可能改变这种序。但在数据相关性和逻辑相关性下还是保证序的。

tempname2 发表于 2011-10-15 14:44

回复 41# smalloc


NB,应该就是这个了。

chishanmingshen 发表于 2011-10-15 17:03

invalidate request代表的是CPUA向内存系统提交了自己的store请求,代表的其他CPU如CPUB“可以”感知到stor ...
asuka2001 发表于 2011-10-15 09:28 http://bbs.chinaunix.net/images/common/back.gif


    我也是这么理解的.

    如果x86真是写有序,那就万事大吉了.

asuka2001 发表于 2011-10-15 17:24

回复 41# smalloc

请教一下,如果判断buf,CPUA这边有数据依赖,可以保证写有序;但是CPUB这边可能没法保证能够有序的感知到buf和enable的数据更新了吧?

我们不能仅仅依赖边界对齐的int的原子性读写?我觉得它和原子类型可能还是有区别的,所以是不是用户空间保护共享数据的时候,还是应该依赖原子类型和锁机制,不知道这个看法对不对。。。

塑料袋 发表于 2011-10-15 18:49

LZ不懂多线程编程,建议好好看看 POSIX多线程程序设计 这书。
另你这段程序有问题,没有判断malloc是否成功 ...
smalloc 发表于 2011-10-15 11:36 http://bbs.chinaunix.net/images/common/back.gif


不相关或独立性,并不是乱序的根源。

而且以CPU的视角来说,根本不存在不相关的指令,即使他们看起来毫无关联。



即使两个指令不相关,但是他们有可能对同地址进行读写,如果有对同地址的W-->W,W-->R.... 这也称之为dependency,前者叫output dependency,后者为anti dependency。此时load/store unit必须知道指令的顺序,才能产生正确结果。

而且我们认为计算目标地址的过程是,基地址+偏移 ---> 虚拟地址,虚拟地址+TLB ---> 物理地址。所以不到计算出来物理地址的最后一刻,CPU根本不知道那些指令间存在output dependency,anti dependency......

比如说有一条store指令的物理地址还没出来之前,则store后边的load/store指令,从本质上说是不能发射的。



但是站在cache的视角来观察load / store,则即使存在control dependency,true data dependency(后边指令的操作地址或者操作数依赖于前边),则这些指令也是可以乱序的。



粗略的原理概述就是:

load / store unit总是顺序的收到各load / store指令,或者是知道各load / store指令的顺序信息。

load / store unit乱序的计算各指令的目标物理地址

当目标物理地址确定后,load / store unit又知道指令间的顺序信息,所以可以判断那些指令间存在output dependency或者anti dependency。

load / store unit既然顺序的判断了指令间的dependency,现在可以顺序的将load / store的操作提交给下一级。下一级是个缓冲区,原始的就一个store buffer,复杂的称为LSQ,这个缓冲区直接和cache打交道。

LSQ还是顺序的看到load / store,但是LSQ却乱序的将load /store提交给cache,或者根本不提交。

对于LSQ来说,不仅对不同地址的操作可以随便乱序;即使对相同地址的操作,同样可以乱序。比如说将两个同地址的W合为一个,可以将W的数据直接返回给后边对同地址的R........


LSQ之所以敢于这样乱序的原因是,LSQ中的R/W都是必须要完成的,即使CPU由于中断等,发生了roll-back,这些R/W也不会被撤消;而且,load / store unit在看cache时,只要考虑到LSQ,将LSQ与cache的数据联合在一起看,则load / store unit看到的结果是顺序的。

任何时候,只要将LSQ中的数据写回了cache,则cache就得到了一种顺序RW的结果。

zylthinking 发表于 2011-10-15 19:46

本帖最后由 zylthinking 于 2011-10-15 21:28 编辑

LZ不懂多线程编程,建议好好看看 POSIX多线程程序设计 这书。
另你这段程序有问题,没有判断malloc是否成功 ...
smalloc 发表于 2011-10-15 11:36 http://bbs.chinaunix.net/images/common/back.gif

1. pthread_mutex_t, flock, semphore, rwlock, fcntl, __sync_add_and_fetch, CreateEvent, InterlockedIncrement, 。。。。。。。。。。。。。。 就那么显得高深, 非要拿出来显摆显摆才过瘾?
2. 斤斤计较的在鸡毛蒜皮的无关主题的枝节上纠缠很有意思么, 还要我判断 malloc 返回值, 加 if 以顺序写, 你干嘛不要我假设在 x86 上?

仔细将帖子整个再看一遍, 先弄明白我到底在问什么问题, 在反过头看看你这个帖子, 大义凛然的跑题就不是跑题了吗

amarant 发表于 2011-10-15 20:38

malloc函数不是几个cpu指令就可以搞定的,所以LZ这个问题应该跟cpu乱序没关系吧!

zylthinking 发表于 2011-10-15 22:50

总结一下吧:

首先提出的这个问题是错的, 用户空间不考虑内存屏障是错的;
单CPU可以不考虑, 线程切换导致的乱序不确定状态CPU乱序执行机制本身就可以解决; 多CPU必须考虑内存屏障。
之前一直疑惑为什么一直没有看到过相关问题的讨论, 只不过是就是没看到而已, 仔细在网上找了找, 确实发现了多核心下对于这个问题的讨论;
操作系统对线程切换时会不会做一个内存屏障的问题, 现在感觉没必要做了, 至少没必要针对这个问题专门做了---单CPU不需要, 多核心做了也没有太大意义

塑料袋 发表于 2011-10-16 00:28

总结一下吧:
操作系统对线程切换时会不会做一个内存屏障的问题, 现在感觉没必要做了, 至少没必要针对这个问题专门做了---单CPU不需要, 多核心做了也没有太大意义
zylthinking 发表于 2011-10-15 22:50 http://bbs.chinaunix.net/images/common/back.gif


不是这样的。

对于这个问题的准确描述,见《Memory Consistency Models for Shared-Memory Multiprocessors》---by Kourosh Gharachorloo的212页,

5.7 Interaction with Thread Placement and Migration


里边解释的很详细,而且这个论文算是多核标杆了。

zylthinking 发表于 2011-10-16 01:00

本帖最后由 zylthinking 于 2011-10-16 01:03 编辑

不是这样的。

对于这个问题的准确描述,见《Memory Consistency Models for Shared-Memory Multip ...
塑料袋 发表于 2011-10-16 00:28 http://bbs.chinaunix.net/images/common/back.gif

是哪一句不对, 我看了部分你所说的章节, 但它在讲线程迁移中发生的故事; 而我的假设是已经在两个 CPU 上正常跑的两个线程。
线程切换这个假设在多CPU下我觉得已经没什么意义了----在单CPU上, 我只是用它产生并发效果而已。
页: 1 2 3 4 [5] 6 7 8 9 10 11
查看完整版本: 为什么用户空间程序不用考虑内存屏障?