分享
 
 
 

MMX开发文档

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

MMX开发文档

I MMX简介

Intel的MMX™技术是对Intel体系结构(IA)指令集的扩展。该技术使用了单指令多数据技术(SIMD)技术,以并行方式处理多个数据元素,从而提高了多媒体和通讯软件的运行速度。MMX™指令集增加了57条新的操作码和一个新的64位四字数据类型。

MMX™技术提高了很多应用程序的执行性能,例如活动图像、视频会议、二维图形和三维图形。几乎每一个具有重复性和顺序性整数计算的应用程序都可以从MMX™技术中受益。对于8位、16位和32位数据元素的处理,改善了程序的性能。一个MMX™指令可一次操作8个字节,且在一个时钟周期内完成两条指令,也就是说,可在一个时钟周期内处理16个数据元素。另外,为增强性能,MMX™技术为其它功能释放了额外的处理器周期。以前需要其它硬件支持的应用程序,现在仅需软件就能运行。更小的处理器占用率给更高程度的并发技术提供了条件,在当今众多的操作系统中这些并发技术得到了利用。在基于Intel的分析系统中,某些功能的性能提高了50%到400%。这种数量级的性能扩展可以在新一代处理器中得到体现。在软件内核中,其速度得到更大的提高,其幅度为原有速度的三至五倍。

MMX的缺点:由于MMX的运算指令必须在数据配对整齐的时候才能使用,所以使用MMX指令要比普通的汇编指令多余许多分组配对的指令,如果运算不是特别的整齐的话,就要浪费大量的时间在数据的配对上,所以说MMX指令也不是万能的,也有其很大的缺陷。同时MMX指令在处理16位数据的时候才能发挥最大的作用,处理8位数据要有一点技巧。而处理32位数据,MMX指令几乎没有什么加速能力。(考虑分组耗时的话)

II MMX基本指令集

具体细节请参阅《INTEL 体系结构MMX技术程序员参考手册》第五章

2.1 拷贝指令

movq:64位数据拷贝,如果内存8位对齐的话,是一个64位写,否则2个32位写。

movd:32位数据拷贝,注意:如果从内存向MMX寄存器拷贝,MMX高32位清零!

2.2 分组指令

分组指令是MMX特有的,所以对于它我们要特别的关注。分组指令基本上可以分为2类,一类是不带符号紧缩的,一类是带符号紧缩的。现在我们分别予以介绍:

①punpcklbw / punpcklwd / punpckldq (l表示低位分组,bw8位,wd16位,dq32位):它是简单的将两个MMX寄存器的低32位交错组合为一个64位数据。所以它是不能将长数据转换为短数据的。

②packuswb 将16位数据转换为无符号的8位数据。所以可以将两个MMX寄存器不交错的合为一个64位数据。

③packsswb/packssdw 将32位-》16位,16位-》8位,都是有符号的数据。

2.3 运算指令

加法运算指令:paddb(w)(d):没有越界保护的加法,当越界的时候仅仅丢弃超出范围的高位比特,(b)(w)(d)分别为8,16,32位加法;paddsb(w):具有越界保护的有符号加法,当上溢的时候为0x7fff,下溢的时候为0x8000;paddusb(w):具有越界保护的无符号加法,当上溢的时候为0x7fff,下溢的时候为0x0。

减法运算指令同上;add改为sub。

乘法指令:pmullw / pmulhw 是4个16位数据的乘法,pmullw中是结果的低16位,pmulhw是结果的高16位。pmaddwd 乘加指令。

2.4 逻辑指令,移位指令和EMMS指令

细节参见《INTEL 体系结构MMX技术程序员参考手册》。

III MMX经典处理策略

①数据输入输出:

在输入数据的时候,经典的处理方法是将一个数组整个“Load”到MMX寄存器中。这样简单同时利用了MMX64位读写数据的能力,提高了性能。同样在输出的时候,也是将一个64位MMX寄存器中的数据内容整个“Store”到内存中。

如果实在是不能这样处理的话,就要利用移位指令了。比如说将一个MMX内的4个16位数据分别拷贝到不同的内存变量(或者16位通用寄存器中)x1,x2,x3,x4,那么可以这样处理:

movd eax,mm1

psrlq mm1,32

movd ebx,mm1

mov x1,ax

mov x2,bx

shr eax,16

shr ebx,16

mov x3,ax

mov x4,bx

可见如果不采用数组形式的话,输入输出将十分的麻烦。

②数据分组以及求绝对值的方法等:

细节请参阅《INTEL 体系结构MMX™ 技术开发者手册》第五章

IV 自定义组合指令

①八位无符号数的移位:

在MMX指令集中是没有8位数据的移位指令的,但是有的时候我们确实需要,所以可以用以下两个指令来实现:

psrlq mm0,1

pand mm0,0x7f7f7f7f7f7f7f7f

②如何防止计算过程中越界:

比如在计算的时候,我们有(x1+x2+1)>>1,这个时候x1+x2就会越界(8位数据),那么我们就不得不使用替代了办法,比如(x1>>1+x2>>1)这个处理是不精确的,在不需要很精确的场合,是可以使用的,但是如果结果差错1都不可容忍的话,就要进行一点处理:

pand mm0,0x01010101010101 //保留数据的最后一位数

pand mm1,0x01010101010101 //保留数据的最后一位数

por mm0,mm1

paddusb mmx,mm0 //修正数据

(x1>>2+x2>>2):这个处理是通用的

pand mm0,0x03030303030303 //保留数据的最后两位数

pand mm1, 0x03030303030303 //保留数据的最后两位数

paddusb mm0,mm1

psrlq mm0,2

pand mm0,0x3f3f3f3f3f3f3f3f

paddusb mmx,mm0

③符号扩展指令:

mm0:*,*,A,B => 现在要符号扩展为 mm0:(A符号)A, (A符号)B

movq mm1,mm0

pcgtm mm1,0 //比较mm0,生成mm1:(A符号) (B符号)()()

punpcklwd mm0,mm1

④分组指令

除了基本的分组指令以外,我们还可以利用移位指令和pand por指令来实现分组的功能,移位主要是要产生0,这样por mm0,mm1就可以将mm0和mm1合并了。

比如:mm0(*,*,A,B) mm1(0,0,C,D) 则

psllq mm0,32

por mm0,mm1 => (A,B,C,D) 当然这个例子我们可以用普通的分组指令实现,但是在某些复杂的处理中,这样的处理是必须的。

总之,要灵活运用MMX的现有指令来实现自己需要的功能。

V MMX编程心得

使用MMX技术进行编程,目的就是要提高运算速度,所以,对于如何尽可能的提高代码的效率,我们是要特别关注的。这里,我介绍一些需要注意的事项。

① 尽可能的提高内存访问的容量,我们可以看看下面的代码:

for (j=0; j<h; j++)

{

d[0] = s[0];

d[1] = s[1];

d[2] = s[2];

d[3] = s[3];

d[4] = s[4];

d[5] = s[5];

d[6] = s[6];

d[7] = s[7];

d[8] = s[8];

d[9] = s[9];

d[10] = s[10];

d[11] = s[11];

d[12] = s[12];

d[13] = s[13];

d[14] = s[14];

d[15] = s[15];

s+= lx2;

d+= lx;

}

__asm{

pushf

mov edx,dword ptr h

xor ecx,ecx

mov esi,dword ptr s

mov edi,dword ptr d

mov eax,lx2

mov ebx,lx

AGAIN:

movq mm0,byte ptr [esi]

movq mm1,byte ptr [esi+8]

movq byte ptr [edi],mm0

movq byte ptr [edi+8],mm1

add esi,eax

add edi,ebx

add ecx,1

cmp ecx,edx

jl AGAIN

emms

popf

}

仅仅将几个8位的写,改为64位的写,测试得到速度提升了25%,同样的道理,我们要尽可能的将几个movq写在一起,这样可以提高5%左右的速度。原C代码的效率也是很高的,它不用数组的【】【】来寻址,而是将s+= lx2; 从而将二维数组的寻址改为一维数组的寻址。尽可能的减少寻址的复杂度,这也是一种高效的办法。 还有一点就是如果将原来的简单赋值改为memcpy()的话,可以提高大约10%的速度。这也是提高了数据流通容量的关系。

② 一些要注意的地方:

1. 尽可能的使用static变量, 访问这样的变量是很快的=访问立即数的速度

2. 由于只有一个mmx移位寄存器, (移位分组指令) 是不能配对的

3. 不要在eax使用完, 使用ax, 不要使用完一个mm1,就立即使用它

4. 可以这样立即使用mm1, movq mm2,mm1 movq mm1,mm3 (Z顺序是可以的)

5. (4个以上)movq尽可能的在一起, 前提是在一起的mov不要使用一样的mmx寄存器

6. mov eax, [esi] ([esi+2*eax]) 访问寻址的内存是特别的慢的

7. 同上 stow 也是很慢的 (mov cx,n; loop是很慢的,如果可能,要展开循环)

8. 尽可能的在寄存器中完成操作,不要去访问内存

9. 用变量名访问变量,尤其是static的,是很快.

10. 访问寻址的内存的速度下降 》 数据不对齐8位的速度下降 》 指令不配对的速度下降

11. 所以在传统的代码优化的方法中,构造数组,然后将运算变为查表的方法,有的时候在MMX技术内反而会降低速度。(这个时候,如果真的用查表有提升速度的话,建议采用段地址+偏移量的办法)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有