免费注册 查看新帖 |

Chinaunix

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

[C] 烦请哪位老大可以介绍一下C语言中的内存对齐的原理和实现? [复制链接]

论坛徽章:
11
摩羯座
日期:2013-09-29 17:39:09白羊座
日期:2014-11-13 09:38:14技术图书徽章
日期:2014-01-17 15:07:36狮子座
日期:2013-12-25 14:01:52技术图书徽章
日期:2013-12-17 11:33:22技术图书徽章
日期:2013-12-03 10:27:57天秤座
日期:2013-11-08 15:47:19申猴
日期:2013-10-29 13:16:32未羊
日期:2013-10-12 22:28:56辰龙
日期:2013-10-09 14:39:5515-16赛季CBA联赛之山东
日期:2016-07-25 10:23:00
11 [报告]
发表于 2012-08-28 14:04 |只看该作者
回复 10# liuiang

楼上威武!


   

论坛徽章:
0
12 [报告]
发表于 2012-08-28 16:23 |只看该作者
讨论的很好

论坛徽章:
1
白羊座
日期:2013-09-18 22:02:26
13 [报告]
发表于 2012-08-28 17:29 |只看该作者
回复 8# superwujc
  1. #define DOUNDARY8(ptr) (((char*)prt) + (0x8 - ((char *)ptr)&0x8))
复制代码

论坛徽章:
11
摩羯座
日期:2013-09-16 11:10:272015亚冠之阿尔萨德
日期:2015-06-12 22:53:29午马
日期:2014-04-15 11:08:53亥猪
日期:2014-03-02 23:46:35申猴
日期:2013-12-06 22:07:00亥猪
日期:2013-11-28 12:03:13双鱼座
日期:2013-11-21 14:43:56亥猪
日期:2013-10-23 10:55:49处女座
日期:2013-10-17 18:15:43午马
日期:2013-09-27 17:40:4215-16赛季CBA联赛之青岛
日期:2016-06-22 00:45:55
14 [报告]
发表于 2012-08-28 19:08 |只看该作者
Ager 发表于 2012-08-28 12:54
lenky0401         + 4         虽然有点混乱,但回答得很认真。


郁闷了……不过还是谢谢版主大虾:)



论坛徽章:
11
摩羯座
日期:2013-09-29 17:39:09白羊座
日期:2014-11-13 09:38:14技术图书徽章
日期:2014-01-17 15:07:36狮子座
日期:2013-12-25 14:01:52技术图书徽章
日期:2013-12-17 11:33:22技术图书徽章
日期:2013-12-03 10:27:57天秤座
日期:2013-11-08 15:47:19申猴
日期:2013-10-29 13:16:32未羊
日期:2013-10-12 22:28:56辰龙
日期:2013-10-09 14:39:5515-16赛季CBA联赛之山东
日期:2016-07-25 10:23:00
15 [报告]
发表于 2012-08-28 22:29 |只看该作者
回复 9# Ager


再请教一下,怎样在系统中查看CPU的内存访问粒度?

论坛徽章:
11
摩羯座
日期:2013-09-16 11:10:272015亚冠之阿尔萨德
日期:2015-06-12 22:53:29午马
日期:2014-04-15 11:08:53亥猪
日期:2014-03-02 23:46:35申猴
日期:2013-12-06 22:07:00亥猪
日期:2013-11-28 12:03:13双鱼座
日期:2013-11-21 14:43:56亥猪
日期:2013-10-23 10:55:49处女座
日期:2013-10-17 18:15:43午马
日期:2013-09-27 17:40:4215-16赛季CBA联赛之青岛
日期:2016-06-22 00:45:55
16 [报告]
发表于 2012-08-29 01:12 |只看该作者
本帖最后由 Ager 于 2012-08-29 04:54 编辑
superwujc 发表于 2012-08-28 22:29
回复 9# Ager

再请教一下,怎样在系统中查看CPU的内存访问粒度?


呵呵,不敢当啦,我也就是稀里糊涂“扯”一通而已。

关于你的这个问题,其实对于x86家族有些扯不太清楚。以前的x86即从80386直到x86_64之前的CPU,乃地道的32bits的处理器,即从内部寄存器(或字长)角度看,它一次性access数据的宽度是32bits的,但是,又因为架构从80586开始支持的external databus的宽度是64bits,所以,它一次性access内存的宽度就翻番到了64bits —— 这种机制乃是依赖于80586处理器拥有两条内部流水线同时工作,即Superscalar机制(该机制的主要前提是RISC范式)。既然Intel公司都已经把CPU发展到了这一步,那么咱们用计算机的人,也不能当这档子事不存在,所以,统统认为是64bits的就没错。

至于如何在计算机上查看CPU的内存access粒度,有好几种方法 —— 不过,不是国内中文网站上普遍宣称的那一系列“getconf xxxBIT”、“uname -xxx”之类的方法,那些方法都是错的,有的是针对OS的,不是针对CPU的。

以下方法,仅供参考:

(1)从版主提到的Cache Line角度,可以用形如以下的命令
  1. cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size
复制代码
查看到Cache Line的长度,单位是Bytes。

如果我们知道Cache Line前缀Tag的宽度(哪位大虾请给个解法?),那么可以用公式:粒度宽度 = Tag的宽度+ lg(Cache Block的长度) + lg(Cache总数据量长度/Cache Block的长度) (注:式中“宽度者”单位均为bits;“长度者”单位均为Bytes;lg的底为2;且本公式也属于我的扯,希望有大虾验证或判否,呵呵……)

(2)直接查看CPU的状况,可以用
  1. grep flags /proc/cpuinfo
复制代码
在flags里,有许多项目可以作为最实在的参考标准,比如有“lm”(Long Mode)就说明必定是64bits的CPU。

如果你想进一步了解x86家族CPU的内存access的粒度(或原子性),那么,你得找一位老乞丐……

老乞丐一看到你为这事儿而来,说:“看你年纪轻轻,就对CPU和内存的事情这麽感兴趣,真是前途无量呀!……”

于是,他从破布口袋里掏出一本白皮书,书名曰《Intel® 64 and IA-32 Architectures  Software Developer’s Manual  Volume 3 (3A, 3B & 3C): System Programming Guide》…… 哇,好长!书也狂厚,大约有2000页……

“看你这麽迫不及待的样子,那就直接看书中的8.1.1吧,在第325页……”

如果老乞丐问你要钱,那你别睬他,因为这本白皮书,在网上可以免费下载阅览:
  1. wget http://download.intel.com/products/processor/manual/325384.pdf
复制代码
以上,经供参考,呵呵 —— :)


论坛徽章:
11
摩羯座
日期:2013-09-29 17:39:09白羊座
日期:2014-11-13 09:38:14技术图书徽章
日期:2014-01-17 15:07:36狮子座
日期:2013-12-25 14:01:52技术图书徽章
日期:2013-12-17 11:33:22技术图书徽章
日期:2013-12-03 10:27:57天秤座
日期:2013-11-08 15:47:19申猴
日期:2013-10-29 13:16:32未羊
日期:2013-10-12 22:28:56辰龙
日期:2013-10-09 14:39:5515-16赛季CBA联赛之山东
日期:2016-07-25 10:23:00
17 [报告]
发表于 2012-08-29 01:54 |只看该作者
回复 16# Ager

敢问阁下是否就是传说中的老乞丐式的世外高人啊,我等菜鸟级简直要膜拜了。。。受教!!!


   

论坛徽章:
11
摩羯座
日期:2013-09-16 11:10:272015亚冠之阿尔萨德
日期:2015-06-12 22:53:29午马
日期:2014-04-15 11:08:53亥猪
日期:2014-03-02 23:46:35申猴
日期:2013-12-06 22:07:00亥猪
日期:2013-11-28 12:03:13双鱼座
日期:2013-11-21 14:43:56亥猪
日期:2013-10-23 10:55:49处女座
日期:2013-10-17 18:15:43午马
日期:2013-09-27 17:40:4215-16赛季CBA联赛之青岛
日期:2016-06-22 00:45:55
18 [报告]
发表于 2012-08-29 02:18 |只看该作者
本帖最后由 Ager 于 2012-08-29 04:47 编辑
superwujc 发表于 2012-08-29 01:54
回复 16# Ager

敢问阁下是否就是传说中的老乞丐式的世外高人啊,我等菜鸟级简直要膜拜了。。。受教!! ...


{:3_185:} {:3_194:} {:3_185:} 不是不是……请千万别……

我就一“扯”者,不是什么高人……

“老乞丐”一说,完全是为了插科打诨,搞笑用的。

真正的高人,在楼下登场{:3_189:}






论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
19 [报告]
发表于 2012-08-29 02:50 |只看该作者
Ager 发表于 2012-08-28 12:54
斑竹大虾,您也忒严厉了吧,就算是我灌水也不至于倒扣2分吧……我在CU上本来就是一个千年穷光蛋,再这麽 ...


确实有点混乱。
有几个问题探讨吧:
>> 不过,在后来的运用中,高级语言编程下的数据结构对齐策略之矢,确是以Cache为的而放的。
内存对齐是内存对齐,cache对齐(姑且叫对齐)是cache对齐,虽然都是对齐某些地址。我不觉得内存对齐到了高级语言就是为了给cache对齐,也就是那什么之矢什么之的的说法。不管是高级语言还是低级语言,内存对齐都是体系结构的要求。换个角度来说,内存对不齐可能会crash,而cache没对齐最多就是性能稍微受影响。而且一般cache可以被控制比如设置write-though或者write-back,可以刷新cache,还可以选择替换策略等操作,而内存对齐目前没看过那个体系可以选择可对奇可不对齐或者选择按1字节还是2字节对齐的。
特定到楼主posix_memalign函数就是上面版主说的大多使用这个是为了性能的cache对齐来手工控制。
高级程序员也没见谁把内存对齐说为“数据结构对齐”。内存对齐就是内存对齐,内存是物理概念,实际看得见摸得着,数据结构是抽象概念,图上看得见,实际摸不着。牵强一些未经大众认可的说法,个人认为欠妥。

>>还有一个原因,就是这种策略,也是满足“程序在不同架构之间的‘可移植性’的要求”(某些硬件设施只能在存储器的特定位置处access特定类型的数据或结构)的必要条件之一。
内存对齐我认为也不是为了所谓的“可移植性”要求,内存对齐就是它的体系要求的,而这个体系直观而简单的例子就是x86代表的CISC和mips代表的RISC。这个在每个处理器的ABI手册上可以查,这一层都不会考虑其它体系的东西,当然专门为了其它体系而做的兼容又当另讲。ABI层没有任何不同体系间的可移植性,所谓的可移植性是上层软件赋予的比如C编译器或者Java平台。如果体系设计的时候可以稍微考虑下移植其它体系的话,那么big 和 little ending早就该消失一种了。所以个人认为这个说法也有点牵强。

>> “Cache Line”, “Cache Block”
cache line我认为也和内存对齐没什么关系,cache line确实如上面版主说的常见是64字节,根据设计可以做到128字节甚至更大,总之一般以字节为单位,而不是word或者其它什么东西。cache block不明白你指的什么,字面上看cache block算是组或路的概念吧,一般会有几条cache line,免得被太快替换。

>> 这样一来,数据X肯定是抓不完整了,寄存器里原来有2个有效数据,现在只剩了1个有效数据(即数据Y),还有2个无效的数据(X的XL部分和Z的ZH部分)
在不对齐的地址上取大于1byte的数据,处理器要么支持不对齐的访问,要么访问错误。也就是说单纯的处理器访问,要么按照你需要的byte,word,dword给你正确的东西,要么exception,不会一半对一半错。不支持非对齐访问的机器也不会自己主动发两次甚至多次访问操作来帮你取数据,如果它自己知道取两次就不会发生访问错误了。现代的话更多的是编译器越来越能搞,这样x86这样的东西编译器可以直接生成访问代码,而比如RISC这样的精简指令集,编译器需要比前者更强大的生成能力来避免非对齐的访问错误:处理器要么对齐访问要么单字节访问,再由编译器调度移位等操作生成完整的2bytes或4bytes。当然这个过程总线不上锁的话可以被打断,也就没有原子性保证了。编译器不帮你搞,还是访问错误。VLIW更依赖编译能力。

所以我个人猜测问题1,2,3某些地方你想说的是register,问题4你想说是编译器吧。

写这么多,也忒认真回复了吧,怎么的也得加8分吧,哈哈。

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
20 [报告]
发表于 2012-08-29 03:15 |只看该作者
本帖最后由 gvim 于 2012-08-29 03:30 编辑

回复 16# Ager

>> 又因为架构从80586开始支持的external databus的宽度是64bits,所以,它一次性access内存的宽度就翻番到了64bits
不是很明白你说的依据,我概念里预取和访问是两个东西。如果按照几条流水来扩展访存能力的话,我现在用的64位 4核处理,8条超线程,16条流水线,岂不是一次性访存就可以搞64*16=1024bits=128个字节回来?如果真这样的话,单独拿一个核出来看,一条流水线搞个for循环的话,岂不是就可以把另外三条的取数据搞停下来?
我不能说你说的不对,这块我印象里也不是很深刻,或许对取指令来说是对的,但如果没有权威的出处的话,我比较怀疑这个说法。


ps:
>> 至于如何在计算机上查看CPU的内存access粒度........(1)从版主提到的Cache Line角度,可以用
我上面以为你应该是没表达清楚,这样看来你不会真认为cache line是64位(bits)的吧?

这话扯的
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP