分享
 
 
 

Viusal C++.NET 2003 的优化代码

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

Viusal C++的优化代码

Mark Lacey

Microsoft Corporation

April 2003

翻译:cnss

概要:这篇文章介绍了Visual C++.NET 2003中的代码优化。另外,有些读者可能对VC.NET 2002的优化不太了解,所以我们会简短介绍一下全程优化(Whole Program Optimization)。最后我们用一些例子充分表现一下VC.NET的优化性能,并对其讨论。

本文适用于:Visual C++ .NET 2003

-------------------------------------------------------------------

前言

人们在使用一个新的编程工具时总会感到缺乏自信,本文试图让你对VC的代码优化有更直观的感觉,希望你能通过阅读本文从VC中"得到"更多的东西。

Visual C++ .NET 2003

VC.NET 2003不仅带来了两个新的优化选项,它还改进了VC.NET 2002中一些优化的性能。

第一个新增选项是"/G7",它告诉编译器对Intel Pentium 4和AMD Athlon处理器进行优化。

使用"/G7"选项编译的程序,当我们和VC.NET 2002生成的代码比较时发现,它通常能使典型的程序的运行速度提高5到10个百分点,如果使用了大量浮点代码甚至能提高10到15个百分点。而提高的优化程度可能很高也可能较低,在一些使用最新CPU和"/G7"选项的测试中,甚至提高了20%的性能。

使用"/G7"选项不代表生成的代码只能运行在Intel Pentium 4和AMD Athlon处理器上。这些代码仍可以运行在老的CPU上,只是在性能表现上可能有"小小的惩罚"。另外,我们观察到一些程序使用"/G7"后在AMD Athlon上运行的比用Intel Pentium 4更慢。

当没使用"/Gx"选项时,编译器会默认使用"/GB"选项,此时为"blended"优化模式。在VC.NET 2002和VC.NET 2003中,"/GB"代表"/G6",即为Intel Pentium Pro, Pentium II, Pentium III处理器优化。

这儿有一个例子,它展示了做与常整数乘法时使用Pentium 4和"/G7"的优化效果,下面是源代码:

int i;

// Do something that assigns a value to i.

return i*15;

当使用"/G6"时,生成了目标代码:

mov eax, DWORD PTR _i$[esp-4]

imul eax, 15

当使用"/G7"时,生成了更快(可惜更长)的代码,它没用imul(乘)指令,在Pentium 4上执行只需要14个周期。目标代码如下:

mov ecx, DWORD PTR _i$[esp-4]

mov eax, ecx

shl eax, 4

sub eax, ecx

第二个优化选项是"/arch:[argument]",用它可对SSE或SSE2优化,生成使用Streaming SIMD Extensions (SSE) 和 Streaming SIMD Extensions 2 (SSE2) 指令集的程序。当使用"/arch:SSE"选项时,目标代码只能运行在支持SSE指令(如:CMOV, FCOMI, FCOMIP, FUCOMI, FUCOMIP)的CPU上。当使用"/arch:SSE2"选项时,目标代码只能运行在支持SSE2指令集的CPU上。

相比于"/G7",使用了SSE或SSE2优化的程序,一般能减少2-3%的运行时间,个别测试中甚至能减少5%的运行时间。

使用"/arch:SSE"可得到以下效果:

1。在使用单精度浮点数时,使用SSE指令对其处理。

2。使用CMOV指令,它最早被Pentium Pro支持。

3。使用FCOMI, FCOMIP, FUCOMI, FUCOMIP指令,它们也是最早被Pentium Pro支持的。

使用"/arch:SSE2"的话,可以得到所有"/arch:SSE"选项的效果,另外还有以下几个效果:

1。在使用双精度浮点数时,使用SSE2指令对其处理。

2。使SSE2指令集做64位切换。(原文:Making use of SSE2 instructions for 64-bit shifts)

还有其它的好处,在同时使用"/arch:SSE"或"/arch:SSE2” 和 "/GL"(全程优化)选项选项时,编译器会对浮点参数和浮点返回值做函数调用规则优化。

上面说的几点优化特性已经包括于VC.NET 2003里了。另外还有一点就是能消除"死参数"--从没被用过的参数。比如:

int

f1(int i, int j, int k)

{

return i + k;

}

int

main()

{

int n = a+b+c+d;

m = f1(3, n, 4);

return 0;

}

在函数f1()中,第二个参数从没被使用过。当我们用"/GL"(全程优化)选项时,编译器将产生如下目标代码来调用f1():

mov eax, 4

mov ecx, 3

call ?f1@@YAHHHH@Z

mov DWORD PTR ?m@@3HA, eax

在这个例子里,变量"n"从没被运算,只有两个参数被f1()使用,所以只传递那两个参数(并且它们是从寄存器传过去的,这比使用栈传更快)。另外,编译这个例子时要禁止内联(inlining),否则函数f1()就不存在了,而直接给m赋予值7。

Visual C++ .NET 2002

VC.NET 2002引入了全程优化(Whole Program Optimization,缩写为WPO)的概念,"/GL"选项代表使用全程优化。全程优化意味着:编译器在.obj文件中存放的是代码的中间表达而不是目标代码,在连接时连接器对其优化处理并生成真正的目标代码。

全程优化的一个主要好处在于我们可以跨越源文件进行函数内联,这将大大提高程序的性能。还有一个好处在于编译器可以跟踪内存和寄存器的使用,以便优化使函数调用的开销更小。

下面的代表展示了全程优化的表现:

// File 1

extern void func (int *, int *);

int g, h;

int

main()

{

int i = 0;

int j = 1;

g = 5;

h = 6;

func(&I, &j);

g = g + i;

h = h + i;

return 0;

}

// File 2

extern int g;

extern int h;

void

func(int *pi, int *pj)

{

*pj = g;

h = *pi;

}

当不使用"/GL"选项时,生成了如下代码:

sub esp, 8

lea eax, DWORD PTR _j$[esp+8]

push eax

lea ecx, DWORD PTR _i$[esp+12]

push ecx

mov DWORD PTR _i$[esp+16], 0

mov DWORD PTR _j$[esp+16], 1

mov DWORD PTR ?g@@3HA, 5

mov DWORD PTR ?h@@3HA, 6

call ?func@@YAXPAH0@Z

mov eax, DWORD PTR _i$[esp+16]

mov edx, DWORD PTR ?g@@3HA

mov ecx, DWORD PTR ?h@@3HA

add edx, eax

add ecx, eax

mov DWORD PTR ?g@@3HA, edx

mov DWORD PTR ?h@@3HA, ecx

xor eax, eax

add esp, 16

ret 0

当使用了"/GL"时,你会看到下面的代码,现在的代码短多了。注意编译这个例子时同样要注意关掉内联优化。

sub esp, 8

lea ecx, DWORD PTR _j$[esp+8]

lea edx, DWORD PTR _i$[esp+8]

mov DWORD PTR _i$[esp+8], 0

mov DWORD PTR ?g@@3HA, 5

mov DWORD PTR ?h@@3HA, 6

call ?func@@YAXPAH0@Z

mov DWORD PTR ?g@@3HA, 5

xor eax, eax

add esp, 8

ret 0

表现优化的最好例子

VC编译器包括两个主要的优化参数,"/O1"和"/O2"。"/O1"代表最小尺寸,选了它编译器认为用了以下选项。

1./Og 全局优化,比如经常用到的变量使用寄存器保存,或者循环内的计算优化

2./Os 程序(exe或dll)尺寸优化优先于代码速度优化

3./Oy 使用帧指针,以提高函数调用速度

4./Ob2 编译器“觉得”应该使用内联的函数,都使用内联

5./GF 使用只读字符串池

6./Gy 告诉编译器将各个函数按打包格式编译

"/O2"选项代表最快速度,它基本上与"/O1"相同,只是用"/Ot"(更快的代码)代替了"/Os"。另外还有"/Oi"代表了展开内联函数。

一般来说,对小程序使用最快优化,对大程序使用最小尺寸优化,这是因为尺寸大的程序通常能导致加载缓慢,CACHE命中率低,系统频繁切换分布内存等问题。使用最小尺寸优化,编译不再展开循环,也不会采用更长的代码。

在选择了主要优化选项后,用profile去寻找"热区"是一个好办法,这样你可以对程序不同部分做最适当的优化。比如如果你用最小尺寸优化后,用profile发现有几个函数执行的很频繁,那你就可以把那几个函数按最快速度优化。

VC编译器可以对特定函数进行优化选项!

比如,如果你发现fiddle()函数被调用的频率很高,那你就可以让编译器只对这个函数进行最快速度优化,这样:

#pragma optimize("t", on)

int fiddle(S *p)

{

…;

}

#pragma optimize("", on)

除了"/O1"和"/O2"以外,还有"/Ox"选项,它很与"/O2"效果相同,而"/Ox"与"/Os"组合则与"/O1"效果相同。我们推荐使用"/O1"和"/O2",而不是用"/Ox"。

至此,我们讨论了"/G7","/arch"和"/GL"优化选项。

除了上面介绍的,VC还提供了两个:

1./GA 优化静态线程局部存储。(不要用于DLL project,用了也没效果)

2./Gr 使用__fastcall作默认调用规则,这代表头两个参数会用寄存器传送(如果参数能装进寄存器)。

另外的一个选项是"/opt:ref",用它可以通知连接器,在连接时去掉没被调用的函数和没被使用的数据。用"/opt:icf"选项能合并相同函数(比如你的程序可能通过模板展开了好几遍),这时优化也能减小程序的尺寸。

Visual C++ .NET中的优化改进

这儿有3个重要的优化选项,你可以把它们用在VC.NET 2003的项目中。虽然VC.NET 2002也提供了这些选项,但VC.NET 2003对它们做了性能上的改进。

下表简要的描述了它们,如果你想了解更详细的内容,请查阅VC所带的文档。

选项

效果

/RTC1

使用无优化的Debug模式,编译器插入动态检测代码以帮助你发现程序中的错误。比如你没有初始化的内存,或者你把__stdcall和__cdecl弄混了。

/GS

加入检测静态缓冲区(栈)溢出的代码,黑客就不能覆盖函数返回的地址以执行恶意代码。

注意:这不意味着你可以高枕无忧,你仍要留心编写安全的代码!

/Wp64

检测生成64位代码的问题,通过它你可以发现移植到64位环境下你的代码可能出现的问题。

结论

VC.NET 2003引入了两个新的优化选项,同时也改进了VC.NET 2002中的几个优化的性能,希望你能通过VC.NET 2003的优化选项来提高你程序的质量,ok, enjoy it!

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝網路 版權所有