[转]数据对齐对CPU的影响
[转]http://www.cnblogs.com/wuzhenbo/archive/2012/06/05/2537465.html
1.前言
在IBM开发社区上发现一篇叫'Data alignment: Straighten up and fly right'的文章,下面的很多内容都是来自那篇文章的。
内存可以看成一个byte数组,我们通过编程语言提供的工具对这个'大数组'中的每个元素进行读写,比如在C中我们可以用指针一次读写一个或者更多 个字节,这是我们一般程序员眼中的内存样子。但是从机器角度更具体的说从CPU角度看呢,CPU发出的指令是一个字节一个字节读写内存吗?答案是'否'。 CPU是按照'块(chunk)'来读写内存的,块的大小可以是2bytes, 4bytes, 8bytes, 16bytes甚至是32bytes. 这个CPU访问内存采用的块的大小,我们可以称为'内存访问粒度'。
2.程序员与CPU眼中的内存
程序员眼中的内存样子:
---------------------------------
| | | | | | | | | | | | | | | | |
---------------------------------
0 1 2 3 4 5 6 7 8 9 A B C D E F (地址)
CPU眼中的内存样子:(以粒度=4为例)
---------------------------------------------
| | | | | | | | | | | | | | | | | | | |
---------------------------------------------
0 1 2 3 4 5 6 7 8 9 A B C D E F (地址)
注:实际上CPU是先访问cache的,当cache中的数据不存在时会以cache line大小为单位每次从memeory中读取数据到cache中,因此此处的粒度指的就是cache line的大小,cache line一般等于机器字长。
3. 访存粒度对CPU访问内存的影响
假设这里我们需要的数据分别存储于地址0和地址1起始的连续4个字节的存储器中,我们目的是分别读取这些数据到一个4字节的寄存器中,
- 如果'内存访问粒度'为1
CPU从地址0开始读取,需要4次访问才能将4个字节读到寄存器中;
同样如果'内存访问粒度'为1,CPU从地址1开始读取,也需要4次访问才能将4个字节读到寄存器中;而且对于这种理想中的''内存访问粒度'为1的CPU,所有地址都是'aligned address'。
- 如果'内存访问粒度'为2
CPU从地址0开始读取,需要2次访问才能将4个字节读到寄存器中;每次访存都能从'aligned address'起始。
如果'内存访问粒度'为2,CPU从地址1开始读取,相当于内存中数据分布在1,2,3,4三个地址上,由于1不是'aligned address',所以这时CPU要做些其他工作,由于这四个字节分步在三个chunk上,所以CPU需要进行三次访存操作,第一次读取chunk1(即 地址0,1上两个字节,而且仅仅地址1上的数据有用),第二次读取chunk2(即地址2,3上两个字节,这两个地址上的数据都有用),最后一次读取 chunk3(即地址4,5上两个字节,而且仅仅地址4上的数据有用),最后CPU会将读取的有用的数据做merge操作,然后放到寄存器中。
- 如果'内存访问粒度'为4
那么从地址1开始读取,需要2次访问,访问后得到的结果merge后放到寄存器中。
注:有些厂商的CPU发现你访问unaligned address,就会报错,或者打开调试器或者dump core,比如sun sparc solaris绝对不会容忍你访问unaligned address,都会以一个core结束你的程序的执行。所以一般编译器都会在编译时做相应的优化以保证程序运行时所有数据都是存储在'aligned address'上的,这就是内存对齐的由来。
4. 指定访问内存的粒度
我们可以指定按照何种粒度访问特定内存块儿:其中void *T为指向特定内存块的地址指针
char *p = (char*)T;每次操作一个字节
short *p = (short*)T;每次操作两个字节
int *p = (int*)T;每次操作四个字节
以此类推。
注:在'Data alignment: Straighten up and fly right'这篇文章中作者还得出一个结论那就是:"如果访问的地址是unaligned的,那么采用大粒度访问内存有可能比小粒度访问内存还要慢"。
5. 小结
要想提高对结构体成员的访存速度,需要做到结构体你对齐,如果要做到更高效的访存,最好是将结构体按自然对齐(自然对齐指的是地址是字长的整数倍),但是自然对齐会带来空间的损失,因此结构体对齐是空间和访问时间的折中方案。
- 结构体一般对齐
原则A:struct或者union的成员,第一个成员在偏移0的位置,之后的每个成员的起始位置必须是当前成员大小的整数倍;
原则B:如果结构体A含有结构体成员B,那么B的起始位置必须是B中最大元素大小整数倍地址;
原则C:结构体的总大小,必须是内部最大成员的整数倍;
- 结构体自然对齐
struct或者union的成员,第一个成员在偏移0的位置,之后的每个成员的起始地址都做到自然对齐
[转]数据对齐对CPU的影响的更多相关文章
- CSAPP阅读笔记-struct, union, 数据对齐-来自第三章3.9的笔记-P183-P191
1.数据对齐 为什么要对齐:通俗点解释就是CPU对数据访问时,每次都是取固定数量的字节数,假如一次取4个字节,若有个int存在0x01-0x04,则一次就能取出,若存在0x03-0x06,则需要分两次 ...
- C/C++数据对齐汇总
C/C++数据对齐汇总 这里用两句话总结数据对齐的原则: (1)对于n字节的元素(n=2,4,8,...),它的首地址能被n整除,才干获得最好的性能: (2)如果len为结构体中长度最长的变量,s ...
- data structure alignment(数据对齐)
概述: 数据对齐指数据在计算机内存中排放和获取的方式.包含三个方面:数据对齐(data alignment).数据结构填充(data alignment).打包(packing) 如果数据是自然对齐的 ...
- 【C/C++开发】内存对齐(内存中的数据对齐)、大端模式及小端模式
数据对齐,是指数据所在的内存地址必须是该数据长度的整数倍.DWORD数据的内存起始地址能被4除尽,WORD数据的内存起始地址能被2除尽.X86 CPU能直接访问对齐的数据,当它试图访问一个未对齐的数据 ...
- gcc数据对齐之: howto 2.
原文链接:http://www.catb.org/esr/structure-packing/ 谁应阅读本文 本文探讨如何通过手工重新打包C结构体声明,来减小内存空间占用.你需要掌握基本的C语言知识, ...
- 谈谈C++中的数据对齐
对于C/C++程序员来说,掌握数据对齐是很有必要的,因为只有了解了这个概念,才能知道编译器在什么时候会偷偷的塞入一些字节(padding)到我们的结构体(struct/class),也唯有这样我们才能 ...
- C++中数据对齐
大体看了看数据对齐,不知道是否正确,总结如下: struct A { char name; double dHeight; int age; }; sizeof(A) = (1+7+8+4+4) = ...
- STM32使用串口1配合DMA接收不定长数据,减轻CPU载荷
STM32使用串口1配合DMA接收不定长数据,减轻CPU载荷 http://www.openedv.com/thread-63849-1-1.html 实现思路:采 用STM32F103的串口1,并配 ...
- gpu显存(全局内存)在使用时数据对齐的问题
全局存储器,即普通的显存,整个网格中的随意线程都能读写全局存储器的任何位置. 存取延时为400-600 clock cycles 很easy成为性能瓶颈. 訪问显存时,读取和存储必须对齐,宽度为4B ...
随机推荐
- 自学Aruba1.3-WLAN厂家魔力象限
点击返回:自学Aruba之路 自学Aruba1.3-WLAN厂家魔力象限 以下为2017<有线和无线局域网接入基础设施的魔力象限>报告: Aruba.cisco为无线领域领导者. ...
- JOISC 2017 自然公园
吐槽 YMD的课件是真的毒,YYB的也很毒. 题目链接 LOJ sol 我是一个一个Subtask做的... Subtask 1 \(O(n^2)\)枚举每两个点有没有边即可. Subtask 2 链 ...
- bzoj1492/luogu4027 货币兑换 (斜率优化+cdq分治)
设f[i]是第i天能获得的最大钱数,那么 f[i]=max{在第j天用f[j]的钱买,然后在第i天卖得到的钱,f[i-1]} 然后解一解方程什么的,设$x[j]=\frac{F[j]}{A[j]*Ra ...
- 前端学习 -- Html&Css -- ie6 png 背景问题
在IE6中对图片格式png24支持度不高,如果使用的图片格式是png24,则会导致透明效果无法正常显示 解决方法: 1.可以使用png8来代替png24,即可解决问题,但是使用png8代替png24以 ...
- 拆分string 用空格 逗号
string that have both comma and space struct tokens: std::ctype<char>{ tokens(): std::ctype< ...
- HDU 1074 Doing Homework (动态规划,位运算)
HDU 1074 Doing Homework (动态规划,位运算) Description Ignatius has just come back school from the 30th ACM/ ...
- C# 面向对象的封装、继承、多态
一.封装: 封装:把客观的事物封装成类,使用和修改方便: 作用和结构体使用方法相似,程序执行流程不同: 要点:成员变量,属性,成员方法,构造函数,成员方法的静态和非静态,命名空间,常用的访问修饰符pu ...
- 【洛谷P2607】骑士 没有上司的舞会+
题目大意:给定一个 N 个点的外向树森林,点有点权.从该树中选出若干顶点组成一个集合,满足任意相邻的两个顶点不同时出现在该集合中,求这样集合中点权和的最大值为多少. 题解:与树相比,该题多了环这个结构 ...
- Sublime Text3—系统设置
摘要 软件的设置分为系统设置和快捷键设置两项,这次分享系统设置,Sublime Text3-自带快捷键介绍前面已分享过. 正文 菜单依次选择Preferences | Settings,我们修改设置不 ...
- 动态分配内存 new
a=]; ;i<=n;i++) a[i]=]; 感觉比malloc好用. 动态初始化后,值并非全为0,注意!