• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • VC++.NET 2003代碼優化方法

    發表于:2007-05-25來源:作者:點擊數: 標簽:代碼方法優化VC++.NET2003
    概要: 這篇文章介紹了Visual C++.NET 2003中的代碼優化。另外,有些讀者可能對VC.NET 2002的優化不太了解,所以我們會簡短介紹一下全程優化(Whole Program Optimization)。最后我們用一些例子充分表現一下VC.NET的優化 性能 ,并對其討論。 前言 人們在使用


      概要:這篇文章介紹了Visual C++.NET 2003中的代碼優化。另外,有些讀者可能對VC.NET 2002的優化不太了解,所以我們會簡短介紹一下全程優化(Whole Program Optimization)。最后我們用一些例子充分表現一下VC.NET的優化性能,并對其討論。

      前言

      人們在使用一個新的編程工具時總會感到缺乏自信,本文試圖讓你對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的優化選項來提高你程序的質量。

    原文轉自:http://www.kjueaiud.com

    評論列表(網友評論僅供網友表達個人看法,并不表明本站同意其觀點或證實其描述)
    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>