[转]数据对齐对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 ...
随机推荐
- 自学Linux Shell6.1-环境变量概念
点击返回 自学Linux命令行与Shell脚本之路 6.1-环境变量概念 环境变量 在Linux中,很多程序和脚本都通过环境变量来获取系统信息.存储临时数据和配置信息: bash shell使用环境变 ...
- 自学Linux Shell7.1-linux用户账户和组
点击返回 自学Linux命令行与Shell脚本之路 7.1-linux用户账户和组 linux安全系统的核心是用户账户.每个能进入linux系统的用户都会被分配唯一的用户账户,用户对系统中各对象的访问 ...
- CF 468B Two Sets
题意: 给定n个正整数与a,b两个集合,求一种方案使得这n个数恰好被分在这两个集合中且集合中无多余的数且若x在a中则A-x在a中,若x在b中则B-x在b中. 题意理解了我好半天... 解法1:并查集. ...
- 【POJ1961】最短周期串/最大周期 kmp
引理:\(s[1,i]\) 具有长度为 \(len\) 的循环节的充要条件是:\(len\ |\ i,s[1,i-len]=s[len+1,i]\). 代码如下 #include <cstdio ...
- 树链剖分&dfs序
树上问题 很多处理区间的问题(像是RMQ,区间修改).可以用线段树,树状数组,ST表这些数据结构来维护.但是如果将这些问题挪到了树上,就不能直接用这些数据结构来处理了.这时就用到了dfs序和树链剖分. ...
- apache 基本vhost配置 【目的及过程】
转: apache 基本vhost配置 2012年04月18日 09:39:28 chamtianjiao 阅读数:74075 经常使用Apache虚拟主机进行开发和测试,但每次需要配置虚拟主 ...
- JasperReport 中踩过的坑
Mac Book Pro 10.13.6Jaspersoft Studio community version 6.6.9JDK 8 安装 Jaspersoft Studio Jasper Rep ...
- calloc()的使用
百度百科 calloc是一个ISO C函数 函数名: calloc 函数原型:void *calloc(size_t n, size_t size): 功 能: 在内存的动态存储区中分配n个长度为si ...
- HTTP Status 405 - HTTP method POST is not supported by this URL
出现这个问题, 1.在servlet中没有调用post()方法引起的 2.在serlvet中跳转没有用外跳(response.sendRedirect()) 我的是因为第一种,是没有写dopost() ...
- 【Maven】eclipse中使用Maven、生命周期
1.在eclipse中创建maven工程 >>在eclipse中配置maven: 配置maven版本:Eclips自带了一个maven,一般不用自带的这个,而选择我们安装的那个maven ...