指令集优化心得一
SSE指令集优化心得(一)
背景
SIMD(singleinstruction,multipledata)是一种使用单道指令处理多道数据流的CPU执行模式,即在一个CPU指令执行周期内用一道指令完成处理多个数据的操作。
常见的指令集
MMX(MultiMediaExtensions,多媒体扩展),主要问题是只对整数起作用,不支持浮点计算;
SSE(StreamingSIMDExtensions,单指令多数据流扩展),兼容MMX指令,可以提高浮点运算速度。
SSE2、SSE3、SSE4(是SSE的扩展技术)
3DNow!
X86
AVX(AdvancedVectorExtensions)沿用了的MMXSSE指令集,指令格式上有一些变化,增强了SIMD计算性能。
问题
最初,我们只能使用汇编语言来编写SIMD代码。不仅写起来很麻烦,而且易读性、可维护性、移植性都较差。不久,VC、GCC等编译器相继支持了Intrinsic函数,使我们可以摆脱汇编,利用C语言来调用SIMD指令集,大大提高了易读性和可维护。而且移植性也有提高,能在同一编译器上实现32位与64位的平滑过渡。但当代码在另一种编译器编译时,会遇到一些问题而无法编译。甚至在使用同一种编译器的不同版本时,也会遇到无法编译问题。
首先是整数类型问题
传统C语言的short、int、long等整数类型是与平台相关的,不同平台上的位长是不同的(例如Windows是LLP64模型,Linux、Mac等Unix系统多采用LP64模型)。而使用SSE等SIMD指令集时需要精确计算数据的位数,不同位长的数据必须使用不同的指令来处理。有一个解决办法,就是使用C99标准中stdint。h所提供的指定位长的整数类型。GCC对C99标准支持性较好,而VC的步骤很慢,貌似直到VC2010才支持stdint。h。而很多时候我们为了兼容旧代码,不得不使用VC6等老版本的VC编译器。
19
其次是Intrinsic函数的头文件问题
不同编译器所使用的头文件不同对于早期版本VC,需要根据具体的指令集需求,手动引入mmintrin。h、xmmintrin。h等头文件。对于VC2005或更高版本,引入intrin。h就行了,它会自动引入当前编译器所支持的所有Intrinsic头文件。对于早期版本GCC,也是手动引入mmintrin。h、xmmintrin。h等头文件。而对于高版本的GCC,引入x86intrin。h就行了,它会自动引入当前编译环境所允许的Intrinsic头文件。
再次是当前编译环境下的Intrinsic函数集支持性问题
对于VC来说,VC6支持MMX、3DNow!、SSE、SSE2,然后更高版本的VC支持更多的指令集。但是,VC没有提供检测Intrinsic函数集支持性的办法。例如你在VC2010上编写了一段使用了AVXIntrinsic函数的代码,但拿到VC2005上就不能通过编译了。其次,VC不支持64位下的MMX,这让一些老程序迁徙到64位版时遭来了一些麻烦。
而对于GCC来说,它使用mmmx、msse等编译器开关来启用各种指令集,同时定义了对应的MMX、SSE等宏,然后x86intrin。h会根据这些宏来声明相应的Intrinsic函数集。MMX、SSE等宏可以帮助我们判断Intrinsic函数集是否支持,但这只是GCC的专用功能。
此外还有一些细节问题,例如某些Intrinsic函数仅在64下才能使用、有些老版本编译器的头文件缺少某个Intrinsic函数。所以我们希望有一种统一的方式来判断Intrinsic函数集的支持性。
除了编译期间的问题外,还有运行期间的问题
在运行时,怎么检测当前处理器支持哪些指令集?
虽然X86体系提供了用来检测处理器的CPUID指令,但它没有规范的Intrinsic函数,在不同的编译器上的用法不同。
而且X86体系有很多种指令集,每种指令集具体的检测方法是略有区别的。尤其是SSE、AVX这样的SIMD指令集是需要操作系统配合才能正常使用的,所以在CPUID检查通过后,还需要进一步验证。
SSE介绍
SSE(为StreamingSIMDExtensions的缩写)是由Intel公司,在1999年推出PentiumIII处理器时,同时推出的新指令集,它是SIMD指令集扩展。SIMD(singleinstruction,multipledata)是一种使用单道指令处理多道数据流的CPU执行模式,即在一个CPU指令执行周期内用一道指令完成处理多个数据的操作。当对多个数据对象执行完全相同的操作时,SIMD指令可以大大提高性能。典型的应用是数字信号处理和图形处理。
29
SSE指令包括了四个主要的部份:单精度浮点数运算指令、整数运算指令(此为MMX之延伸,并和MMX使用同样的缓存器)、Cache控制指令、和状态控制指令。这里主要是介绍浮点数运算指令和Cache控制指令。
intrinsic内联函数
在CC程序中使用SSE指令有两种方式:
直接嵌入汇编指令(内嵌式汇编语言);
使用编译器提供的支持SSE的intrinsics内联函数(从代码可读和维护角度讲,通过intrinsics内联函数的形式来使用SSE更好)。
内嵌式汇编语言使用SSE指令集
asmaddpsxmm0,xmm1
asmmovaps〔ebx〕,xmm0
。。。
m128data;
。。。
asm
{
leaebx,data
addpsxmm0,xmm1
movaps〔ebx〕,xmm0
}
通过intrinsics内联函数使用SSE指令集
m128data1,data2;
。。。
m128outmmaddps(data1,data2);
。。。
intrinsics函数是对MMX、SSE等指令集的一种封装,以函数的形式提供,在编译的时候,这些函数会被内联为汇编,不会产生函数调用的开销。
头文件
VisualStudio使用SSE指令集需要添加对应的头文件:
intrin。hamp;gt;AllArchitectures
mmintrin。hamp;gt;MMX
xmmintrin。hamp;gt;SSE
emmintrin。hamp;gt;SSE2
pmmintrin。hamp;gt;SSE3
smmintrin。hamp;gt;SSE4
immintrin。hamp;gt;AVX
39
SSE新增的寄存器(用于浮点运算指令)
SSE指令集支持的处理器有8个128位的寄存器(xmm0xmm7),每一个寄存器可以存放4个(32位)单精度的浮点数。SSE的浮点数运算指令就是使用这些寄存器。下图是SSE新增的寄存器的示意图:
m128数据类型
SSE使用4个浮点数(432bit)组合成一个新的数据类型m128,对应128位的寄存器。SSE指令的参数和返回结果的数据类型都是m128。
比如:m128mmaddps(m128a,m128b);两个四维向量相加
SSE浮点运算指令分类
packed指令是一次对XMM寄存器中的四个浮点数(即DATA0DATA3)均进行计算;
scalar只对XMM暂存器中的DATA0进行计算。
SSE指令格式mmlt;opcodegt;lt;suffixgt;(参数表)lt;suffixgt;lt;opcodegt;
前缀mm,表示是SSE指令集对应的Intrinsic函数;
49
lt;opcodegt;表示指令的作用,比如加法add;lt;opcodegt;
lt;suffixgt;是ps或者ss,分别表示为packed或者scalar;lt;suffixgt;
如m128mmaddps(m128a,m128b);两个四维向量相加
内存对齐
SSE指令要求处理的数据16字节(128位二进制)对齐,也就是每16个字节分为一组。
静态数组(staticarray)可由declspec(align(16))关键字声明:
declspec(align(16))floatmfArray〔ARRAYSIZE〕;
在xxmintrin。h中定义了一个宏MMALIGN16,所以上面的程序也可以写成:
MMALIGN16floatmfArray〔ARRAYSIZE〕;
动态数组(dynamicarray)可由alignedmalloc函数为其分配空间:
mfArray(float)alignedmalloc(ARRAYSIZEsizeof(float),16);
由alignedmalloc函数分配空间的动态数组可以由alignedfree函数释放其占用的空间:
alignedfree(mfArray);
以mmloadps函数为例,其使用示例如下:
这里加载正确的前提是:input这个浮点数阵列都是对齐在16bytes的边上。如果没有对齐,就需要使用mmloadups函数,这个函数用于处理没有对齐在16bytes上的数据,但是其速度会比较慢。
【注意】GCC编译器和VC编译器下字节对齐是不同的:
GCC:attribute((aligned(16)))
VC:declspec(align(16))
IntrinsicSSE相关指令
Load系列(用于加载数据,从内存到寄存器)
m128mmloadss(floatp)
m128mmloadps(floatp)
m128mmload1ps(floatp)
m128mmloadhpi(m128a,m64p)
m128mmloadlpi(m128a,m64p)
m128mmloadrps(floatp)
m128mmloadups(floatp)不要求16字节对齐
Set系列(用于加载数据,从内存到寄存器,大部分需要多条指令完成,但是可能不需要16字节对
59
绝对不可以心慈手软吴桥是一个日语翻译,接触很多的日本人,觉得日本人都是彬彬有礼,和那些电视上面所演的日本人完全不同;而且,他也很喜欢中国古代文化,所以知道日本的礼节是从中国演变而来的。这让他对继……
给女朋友甜言蜜语的情话我不是有耐心的人却对你用尽一、我要闪现到你的怀里用治疗术治愈你用我的可爱眩晕你狂暴的强吻你干扰你的呼吸和心跳然后悄悄疾跑掉。二、我忘了自己曾经多洒脱,不受他人感情左右。我忘了自己曾经多美好,不会脏……
房子距离我们的婚礼还有十七天。我灰头灰脑地走在大街上,去买自考的书。混乱的日子,折磨的心情,失去活力的身体。眼泪含在眼里,料峭的春风,冰冷,冰冷。开始封闭自己,不想跟人……
菲姬魅惑蓬松时尚发型写真黑眼豆豆主唱菲姬新年魅惑蓬松时尚发型写真黑眼豆豆被广大乐迷们所喜欢,女主唱Fergie如今已经从当家女主唱,蜕变成时尚界性感宝贝与电影明星。黑眼豆豆主唱菲姬新年魅惑……
双丸子头的扎法动图教程时尚又兼备减龄效果年轻人都喜欢扎丸子头,头发长的妹子扎丸子头也能让长发变得更好打理一点,那丸子头怎么弄好看呢?头发比较短的也没关系,扎的小小的更显得古灵精怪。头发比较长的可以编发。就……
女生绑头发的叫什么女生绑头发注意什么女生绑头发的叫什么头绳。头绳通常是用带松紧性的橡胶材质制作,外敷各种花色布料,用来捆扎头发用。这个前期事为了方便女性整理发型而产生的一种工具,后来指女性用来装饰头发的一种……
寒山寺的钟声寒山寺的钟声特别响亮,据说在苏州城敲一下,东海邻国日本就能应一声。这两地钟声呼应,那是在传达寒山与拾得的别后离情。相传唐代在苏州寒山寺里,当家的是寒山、拾得两个和尚。这两……
小白兔吹笛子在一个月朗星稀的夜晚,一只活泼可爱的小白兔在一棵又结实又粗壮的老槐树下拿出自己心爱的小笛子吹起了悠扬的曲子,这婉转的笛声传到了小动物的耳朵里。森林里的花草树木都沙沙地响了……
红楼梦中贾琏性格特点是什么样的其实贾琏也不是太坏红楼人物红楼梦的读者大多很讨厌贾琏。第一,他总是偷鸡摸狗。即如好色是男人的天性,薛蟠似乎也比贾琏可爱点。因为薛蟠的肉欲游戏显得很光明正大,我行我素……
自信自信,是走向成功的伴侣,是战胜困难的利剑,是驶向理想彼岸的舟楫。Psy525。cn自信,是一种美妙的生活态度,是一种面对生活的乐观情绪,是一种完善自我的心理素质。没……
父母要警惕幼儿也会自慰不要以为自慰这种事情只会发生在性成熟的人身上,其实很多幼儿都会下意识的自慰。Psy525。cn午睡时,看到奇奇的被套和里面的棉絮分开了,老师就上前拉开拉链,想帮她调整一下……
孟子主要内容简介及赏析《孟子》是中国儒家学派经典之一。战国时孟轲及其高足弟子万章等著,或说是孟轲弟子、再传弟子的记述。《史记孟荀列传》记为7篇,《汉书艺文志》著录11篇,然现存7篇,另据东汉赵歧《孟……
一个人如何练空翻练空翻首先要准备一个柔软的垫子,练习翻滚,然后练习倒立,之后在上手支撑翻越,最后脱手空翻即可,这个需要一个过程,不断练习,此外要注意安全。空翻是一种比较危险的运动,在训练……
笔记本自动关机怎么办aclasstaghrefwiki10449IHtPgab16。html电脑a用久了难免出现一些故障。下面,我们来看看笔记本自动关机怎么办吧。操作方法01:hr感染……
如何设置华为手机锁定时显示通知内容如何aclasstaghrefwiki10950Iakl1fi24。html设置a华为手机锁定时显示通知内容呢?下面小编来教大家。操作方法01:hr首先,我们打开我……
没身份证怎么坐火车没有aclasstaghrefwiki10569dTJCsDVg56B3。html身份证a,可以制作临时身份证,还可以携带户口本,如果是军人,那么没身份证带军人证也可以。……
鲜花如何保鲜更长时间01hr浸在清水里;放在冰库花朵从枝条上面剪下来之后,如果想要让它们保持更强的观赏期,那你就是要将它浸在清水里,或者是放在冰库里面。鲜花的保存也要从源头上开始注意,……
施工建筑单位自查自纠报告范文施工单位自查自纠报告xxx水厂扩建工程位于xx内,本工程由xxx有限公司投资建设,xx工程设计研究院设计,xx建设工程管理有限公司监理,xx集团有限公司具体负责施工,由x……
这一天让我铭记时间总是如此短暂,一个美好的一天终消散了,每个人都属于自己的完美的一天,让自己刻骨铭心,永生难忘。我有属于我的一天,跟随着我未探寻、感受这一天!曾经得在一个下雪的天……
我的好朋友我有一个好朋友,它时时刻刻都在陪伴我,它乐于助人、知晓天下事,无所不能。她就是我的好朋友书。我的这位朋友,它知识渊博,乐于助人。当我有问题时,它总能帮我解答。在家里,我写……
给远方小朋友的一封信远方的朋友:你好!你肯定会因为我给你的来信而感到不解吧?因为我们并不认识。可尽管如此,我还是很想和你交个朋友,我相信我们会相处愉快的。我叫李念,是一名五年级的……
雨轰隆隆轰隆隆雷公公击着鼓宣布着雨娃娃的突袭。你看,雨娃娃聚集在一起,叫嚷着开始突袭。雨娃娃们奔向了各地,有的落到了原野,给草弟弟洗澡,给花儿们解渴。有的落在了城市,迫使人……
功夫乌龟啊!我那龟缩了一个冬天的小乌龟终于苏醒了!昨天,我去阳台看书的时候,看见它俩脚(两个后爪)蹬在龟盆里的大石头上,两前脚抓着盆的边缘,头伸得老长,老长好,好,我大发慈悲,给……
画猪鼻子游戏今天,我们幸运星基础班的小朋友一起做了一个画猪鼻子游戏。游戏规则是这样的:老师用布蒙住同学们的眼睛,同学们要给猪画一个鼻子。第一个上去的是小怡,老师用红布蒙住小怡的……