SSE体系结构与编程.ppt
本课程得到Intel大学合作计划支持课程网站:http:/ SSE编程华南理工大学 陈虎 博士什么是SIMDSIMD(Single Instruction Multiple Data):单指令流多数据流)用一个控制器对一组数据(又称“数据向量”)中的每一个分别执行相同的操作来实现空间上的并行性典型实例:Intel的MMX或SSEAMD的3D Now!Intel的SSE技术SSE指令集出现在Pentium III处理器中包括了70条指令,其中50条SIMD浮点运算指令、12条MMX 整数运算增强指令、8条内存连续数据块传输指令。SSE2指令集:使用了144个新增指令从64位扩展到了128 位提供双精度操作支持Intel的SSE技术SSE3指令集增加13条指令超线程性能增强指令可以提升处理器的超线程处理能力SSE4指令集共包括16条指令AVX(Advanced Vector Extensions),预计2010年发布数据宽度从128位扩展为256位操作数从两个增加到三个SSE2的寄存器结构IA32 Basic Architecture:图10-1SSE1、2的数据类型数据总宽度为128位,可以表示成:四个单精度浮点数两个双精度浮点数16个字节整数8个16位整数4个32位整数2个64位整数SSE指令SSE指令按功能可以分成四组:封装和标量单精度浮点指令 64位的SIMD整数指令状态管理指令缓存控制,预取和内存命令指令浮点指令数据移动指令(标量、成组)寄存器到存储器存储器到寄存器寄存器之间算术运算指令(标量、成组)加、减、乘、除、平方根、最大、最小比较指令(标量、成组)混洗指令 转换指令逻辑操作指令整数指令算术指令最大、最小、平均值数据移动指令混洗指令MXCSR管理指令Cache和存储器控制指令使用SSE指令的四种方法编译器的自动矢量化使用C+类库使用编译器的内嵌原语(Intrinsics)嵌入汇编语言四种方式的比较自动矢量化自动矢量化C+类库类库内嵌原语内嵌原语汇编语言汇编语言代码可读性好好中等查效率编译器不一定能识别无法使用所有指令可以使用所有指令,不能直接访问数据寄存器直接控制所有指令和寄存器兼容性好好差差VC8.0的内嵌原语(intrinsics)什么内嵌原语:一条或一组汇编指令内嵌原语格式 _mm_:指令类别(add、sub):指令操作数的类型内嵌原语的数据类型p:紧密,指令对寄存器中的每个元素进行运算ep:扩充紧密s:标量,只将寄存器中的第一个元素参与运算 其他说明数据类型的关键字有:s 单精度浮点数d 双精度浮点数i128 带符号128位整型i64 带符号64位整型u64 无符号64位整型i32 带符号32位整型u32 无符号32位整型i8 带符号8位整型u8 无符号8位整型内嵌原语的类别矩阵变换读写控制寄存器混洗Cache控制数据整型操作存储操作 置位运算读取运算转换运算比较操作逻辑运算算术运算矩阵变换矩阵变换例:_MM_TRANSPOSE4_PS(row0,row1,row2,row3)作用:转置一个44的单精度或双精度元素矩阵混洗操作混洗操作例:_MM_SHUFFLE(z,y,x,w)(z6)|(y4)|(x2)|w说明:从第一个操作数中选取两个数,从第二个操作数中选取两个数,形成一个结果字 支持支持Cache控制控制_mm_prefetch:预取稍后运行需要的数据_mm_stream_pi:把指定位置的数据存储到指定的地址,而不替换cache整型原语整型原语_mm_extract_pi16:从4个字中提取一个字_mm_insert_pi16:插入一个字_mm_max_pi16:计算出最大值_mm_min_pi16:计算最小值读写控制寄存器读写控制寄存器 _MM_SET_EXCEPTION_STATE:设置异常状态寄存器 _MM_GET_EXCEPTION_STATE:读取异常状态寄存器可以操作寄存器还包括:EXCEPTION_MASK(异常屏蔽寄存器)、ROUNDING_MODE(舍入模式寄存器)、FLUSH_ZERO_MODE(清0模式寄存器)存储操作存储操作_mm_store_ss:存储低位值_mm_store_ps:存储4个值,位址对齐_mm_storer_ps:存储4个值,顺序相反读取运算读取运算_mm_load_ss:读取低值,同时清空其他3个高值_mm_loadr_ps:以相反的顺序读入4个值设置运算设置运算_mm_set_ss:设置低位为1,同时清空其余三个高位值_mm_set1_ps:设置所有4个值为同一值_mm_setzero_ps:把所有4个值清零转换运算转换运算_mm_cvtss_si32:转换单精度浮点数为32位整数_mm_cvttss_si32:转换单精度浮点数为32位整数(带截断操作)_mm_cvtpi16_ps:转换16位有符号整数为单精度浮点数比较原语比较原语_mm_cmpeq_ss:是否相等_mm_cmplt_ps:是否小于_mm_cmpgt_ps:是否大于逻辑运算逻辑运算_mm_and_ps:与运算_mm_or_ps:或运算算术运算算术运算_mm_add_ss:加法_mm_sub_ps:减法_mm_mul_ps:乘法SSE程序实例双精度三维变换原理SSE程序实例两种不同的数据结构数组-结构(the array-of-structures format(AoS)结构-数组(the structures-of-arrays data format(SoA)数组-结构(AoS)结构-数组(SoA)SSE程序实例for(int i=0;i dm00);/取出y(i)和y(i+1)ty=_mm_load_pd(vertex.y+i);mx1=_mm_mul_pd(ty,WM-dm01);/取出z(i)和z(i+1)tz=_mm_load_pd(vertex.z+i);mx2=_mm_mul_pd(tz,WM-dm02);/x(i)=x(i)*m00+y(i)*m01+z(i)*m02+m03 /x(i+1)=x(i+1)*m00+y(i+1)*m01+z(i+1)*m02+m03 mx0=_mm_add_pd(mx0,_mm_add_pd(mx1,_mm_add_pd(mx2,WM-dm03);/写入结果x(i),x(i+1)_mm_store_pd(vertex.x+i,mx0);/计算y(i)和y(i+1)mx0=_mm_mul_pd(tx,WM-dm10);/tx,ty,tz已经事先读入 mx1=_mm_mul_pd(ty,WM-dm11);mx2=_mm_mul_pd(tz,WM-dm12);mx0=_mm_add_pd(mx0,_mm_add_pd(mx1,_mm_add_pd(mx2,WM-dm13);_mm_store_pd(vertex.y+i,mx0);/计算z(i)和z(i+1)mx0=_mm_mul_pd(tx,WM-dm20);mx1=_mm_mul_pd(ty,WM-dm21);mx2=_mm_mul_pd(tz,WM-dm22);mx0=_mm_add_pd(mx0,_mm_add_pd(mx1,_mm_add_pd(mx2,WM-dm23);_mm_store_pd(vertex.z+i,mx0);/计算z(i)和z(i+1)mx0=_mm_mul_pd(tx,WM-dm30);mx1=_mm_mul_pd(ty,WM-dm31);mx2=_mm_mul_pd(tz,WM-dm32);mx0=_mm_add_pd(mx0,_mm_add_pd(mx1,_mm_add_pd(mx2,WM-dm33);_mm_store_pd(vertex.w+i,mx0);SSE程序实例技巧:一次完成两个矩阵变换SoA的数据结构有利于减少数据读出次数AoS数据结构需要读入两次结果(P4 1.2GHZ平台上)C语言AoS结构 29.9秒C语言SoA结构 32.4秒内嵌原语+AoS结构 19.4秒内嵌原语+SoA结构 16.1秒结论:性能几乎提高两倍