23.07.2013 Views

Solutions Brief Title – 18pt - HP

Solutions Brief Title – 18pt - HP

Solutions Brief Title – 18pt - HP

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>HP</strong>-UX 11i 知識隨選:<br />

本實驗室為您提供的效能優化最佳作法<br />

開發人員系列<br />

用編譯器獲取最佳效能 --<br />

線上講座主題錄音稿<br />

您好,我是 Teresa Johnson,今天所要講的主題是有關於如何利用編譯器獲取 <strong>HP</strong>-UX 的最佳效能。<br />

[下一張投影片]<br />

談到這次演講的講程,首先我會先提出 Intel Itanium 架構中,提供絕佳應用程式效能的一些功能,接著再說明編譯器的<br />

設計如何能夠讓這種架構中的應用程式效能更加快速。 之後,我會概略講述 <strong>HP</strong> 編譯器中有的各種編譯器最佳化層級<br />

,順道討論如何用 <strong>HP</strong> 編譯器讓 <strong>HP</strong> Integrity 伺服器發揮最佳的效能。 這些講完之後,再簡要地提出與浮點數應用程<br />

式有關的一些特殊效能調整問題,接著會談幾個編譯選項,在您進行最佳化的過程中遇到應用程式問題而加以疑難排<br />

解時,這些會有所幫助。 最後,我會說明為 Itanium 調整效能時,可以用的一些資源。<br />

[下一張投影片]<br />

Intel Itanium 架構有一些非常精密的功能,很適合用於指令層級的平行處理,協助提高應用程式效能,而且不必變更應<br />

用程式就能夠善加運用這些功能;一部份須歸功於 <strong>HP</strong> 編譯器是設計成能自動利用這些進階功能,為應用程式提高效<br />

能。 不過,使用編譯器之前必須先經過思考,以便善加運用這些功能,為 Itanium 上的應用程式帶來最大的幫助。在<br />

演講中,我也會描述如何用 <strong>HP</strong> 編譯器讓 Itanium 發揮最佳的應用程式效能。<br />

[下一張投影片]<br />

目前,Itanium 的實作都是以靜態的方式排程,也就是說,編譯器對於獲取 Itanium 上最佳應用程式效能來說至關重要<br />

。 <strong>HP</strong> 所推出適用於 <strong>HP</strong>-UX 的 C、C++ 與 Fortran 90 編譯器在分析與最佳化 Itanium 方面非常主動且具有擴充力。<br />

特別這三種編譯器共用同一個後端,這個後端則是為了 Itanium 從頭撰寫而成。 C 語言編譯器的高階最佳化部分能進<br />

行精湛的分析,此外純量和巢狀迴圈最佳化與特定機器最佳化工具兩者,在建置和設計上都是特別以善加利用 Itanium<br />

上這些進階的結構功能為目的,例如它有預測支援、控制項與資料推測、與軟體管線操作等等。


<strong>HP</strong> 為了輔助這些編譯器提供了高效能的數學函式庫,其實它是以 C 語言和內嵌組譯碼合併撰寫而成,這樣的好<br />

處在於,隨著我們不斷地繼續實作 Itanium,只要用 <strong>HP</strong> 編譯器把數學函式庫重新編譯,就可以享受這些新微型<br />

結構功能帶來的優點了。 此外,<strong>HP</strong>-UX 還有效能調整與效能分析工具,例如 <strong>HP</strong> Caliper;有了這些元件,將<br />

Itanium 上應用程式效能最佳化所需的工具便一應俱全了。<br />

[下一張投影片]<br />

從高層級的角度看來,<strong>HP</strong> 編譯器中有四個不同的最佳化層級。 預設的編譯層級是 +O1 或 +O1 -g,以 +O1 而<br />

言,編譯器應用程式有充分偵錯能力,但只運用非常有限的本機最佳化功能。 這一點在應用程式開發以及應用<br />

程式偵錯的過程中非常有幫助。<br />

不過,如果希望所部署的應用程式能夠達到高效能,這還算不上適當的最佳化層級了。 下一個最佳化層級是<br />

+O2,它的另一個別名是 -O;+O2 層級的編譯器會套用檔案層級的全域最佳化。 例如,會套用同一個檔案內<br />

的程序內嵌,而且排程工具也會善用 Itanium 的進階功能,例如對控制項推測與資料推測的支援。 也能執行軟<br />

體的管線操作與預測等其他的進階最佳化功能。 此外,O2 層級有一些有限的迴圈層級最佳化,例如資料預讀<br />

、迴圈展開等等。 這其實只是應為任何發行的應用程式考量的基本最佳化層級。 下一個最佳化層級是 +O3;<br />

+O3 有更高層級的迴圈最佳化。<br />

例如:迴圈下一轉換、迴圈封鎖、迴圈互換,這其實只是浮點數應用程式應考量的基本最佳化層級,因為這些類<br />

型的應用程式容易把大多數的時間花在巢狀迴圈上,所以善加利用 +O3 提供的高層級群組最佳化是很要緊的。<br />

接下來是 +O4,它除了 +O2 和 +O3 含有的所有最佳化功能之外,還能進行程序之間的跨檔案最佳化與內嵌,<br />

例如會套用全程式分析。 <strong>HP</strong> 所實作的程序間最佳化功能,這部分在後段還會再談到,它既透明化又具有擴充能<br />

力,所以對您的建置程序的影響應當甚小,而且儘管在 +O4 所執行的是全程式的最佳化,還是能擴充為極大的<br />

應用程式。<br />

我在這張投影片中還列出了另一項最佳化功能,雖然這不算是最佳化層級,卻對於 Itanium 的效能而言非常關鍵<br />

,那就是 +Oprofile。 這個選項可搭配 +O2 以上使用,以達到側寫的最佳化,我會在稍後講一下側寫最佳化,<br />

這裡之所以先提到,是因為說到讓不同的最佳化層級執行最好的主動分析與最佳化功能,它正是箇中的關鍵。<br />

[下一張投影片]<br />

這是 -O 效能的摘要。 <strong>HP</strong> 編譯器能夠在 -O 層級提供非常合理的效能,因此這是我們對應用程式供應商所推薦<br />

的基本最佳化層級。 尤其請不要為已發行的應用程式使用 +O1 或 +O0。 直接用 -O 便能夠達到高出許多的效<br />

能層級。 對於浮點數應用程式,-O 是不夠的。 請從 +O3 開始,它能夠達到高層級的迴圈最佳化。<br />

[下一張投影片]<br />

透過這張投影片,我想要稍微提一些如何讓 <strong>HP</strong> Integrity 伺服器發揮最大效能的關鍵建議。 首先,是儘可能使用<br />

最新版的編譯器。 例如 2007 年 9 月發行的 6.15 版編譯器,與我們在 2006 年 9 月發行的 6.12 版編譯器相<br />

比,提高了 5% 到 10% 的效能。 如果回顧這幾年來編譯器的效能,可以看出逐年持續地大幅改進,例如 6.12<br />

版之前,效能與兩三年前的 5.50 版編譯器相比提高了 10 至 20%,所以儘可能改用最新版本的編譯器是非常重<br />

要的。


另一點我曾經提到過的,就是運用適當的最佳化層級。 再度強調,您在開發的時候可能先使用的是 +O1,但較<br />

之下 -O 或 +O2 可能提供雙倍的效能。 還有一點必須考量的是,在 -O 之外也使用一些最佳化標幟,以便獲取<br />

最佳效能。<br />

[下一張投影片]<br />

剛才提到過,-O 之外也請使用一些最佳化標幟,以便從 Itanium 處理器獲取最佳效能,此外也請專注在對大多數<br />

應用程式而言影響最大且比較安全的一些選項。 這些標幟往往並未併入預設的 -O,因為可能會影響應用程式的<br />

建置模型或使用模型,所以使用的時候必須思考一下。 此外也可能需要更多的編譯時間,例如 +O3 有時候需<br />

要比 +O2 長約 25% 的編譯時間,到了 +O4、也就是程序間的最佳化,有時需要多 100% 的編譯時間。 所以<br />

會增加成本,不過我會再提出說明,這裡頭的好處會很大。<br />

[下一張投影片]<br />

在還沒有詳細說明這些進階的最佳化標幟之前,我先摘要敘述一下,採取較高層級的最佳化,並且用一點額外的<br />

最佳化標幟,在效能上所能達到的效果。 首先,先來談一下 64 位元編譯器的 SPEC2006 整數效能。 然後再<br />

與只使用 Vanilla +O2 編譯來作比較。 可以看到,以這些整數基準測試來講,使用 +O3 其實並沒有好處,這<br />

並不教人意外,因為 +O3 具有巢狀迴圈最佳化,但整數基準測試通常不會有太多巢狀迴圈。<br />

我所要提出的下一個最佳化標幟是 +Ofast,稍後會再更深入地談這一個最佳化標幟,基本上這是綜合各種最佳<br />

化標幟,對大多數的應用程式而言應該是有效且安全的。 您可以看出,這能提高兩、三個百分比的效能。 但只<br />

要開始加入側寫的最佳化,就會發現效能提高了,而且攀升將近 10%,至於 +O4 與 +O2 比較之下,可以提高<br />

將近 15%。<br />

最後,使用 +O4 與側寫最佳化的組合,可提高超過 30% 的效能。所以這裡值得注意的一個關鍵就是,+O4 與<br />

側寫最佳化的組合所能增加的效能,實際上比單獨使用側寫最佳化或只單獨使用 +O4 的總和還要高,這是因為<br />

我剛才提過,側寫的最佳化其實能使 +O4 啟用許多主動最佳化與分析功能,並且善加利用。<br />

[下一張投影片]<br />

接下來看到的是浮點數,也就是 SPEC2006 基準測試的浮點數部分。 這張投影片當中,我會和 +O3 比較效能<br />

,剛才提過,對於浮點數應用程式,其實應該從 +O3 開始。 我要提出的第一個選項是 +Ofltacc=relaxed 選項<br />

,也是稍後會再更深入地談;這裡先說明的是,如果可以接受對於浮點數的準確性稍微不那麼敏感的話,它可以<br />

允許執行一些較為主動的浮點數最佳化,這樣可以提高兩、三個百分比的效能。 若加入 +FPD 也就是清除為零<br />

的捨入模式,可獲得超過 40% 的大幅提升。 最後,如果升級為 +O4 並且加入大型頁面,可獲得將近 70% 或<br />

70% 上下的提升,所以相當可觀。<br />

[下一張投影片]<br />

這裡舉出我們從採取較高層級的最佳化所達到的成果。 重提一遍,+O3 非常適合浮點數應用程式,對於大量使<br />

用記憶體的應用程式,衷心建議您考慮使用大型頁面。 如果有大量使用記憶體的應用程式,啟用的手續不麻煩<br />

,而且對您減少可能發生的 TLB 遺漏非常重要。 剛才提過 +Ofast 綜合一些最佳化標幟,可能導致對於浮點數的<br />

準確性非常敏感的部分應用程式失敗;所以舉例而言,對這類應用程式恐怕不宜使用 +Ofltacc=relaxed 和清除為


零的捨入模式;不過對於絕大多數的應用程式來說還是蠻安全的,明顯具有效能優點。<br />

關於側寫最佳化,我在談整數基準測試的投影片中講過,在 O2 達到將近 10% 的提升。 我們也實際看過對大<br />

型商用應用程式帶來更大的幫助,約莫 10 至 15% 之譜;剛才在那張投影片的時候也說過,側寫最佳化與 +O4<br />

的組合可發揮的好處,甚至比這兩種最佳化本身單獨使用更大。 把這些好處全部加起來的話,會非常驚人。<br />

[下一張投影片]<br />

暫且先撇開編譯選項不談,我想更深入一點地討論側寫最佳化、如何使用,以及對您有哪些好處。 Itanium 結構<br />

有一些機制能夠用來增加平行處理,尤其您若瞭解應用程式的行為的話。 例如,若您知道應用程式的哪部分用<br />

得特別多,應用程式執行所走的哪些路徑格外頻繁,在控制項推測與預測的運用上就能有效率許多。 若是這樣<br />

,側寫最佳化的好處就會比傳統式的 RISC 系統多更多,僅僅單獨使用側寫最佳化就能提高多達 30%。<br />

側寫有什麼回饋呢? 側寫的應用程式會收集幾種類型的資訊。 最重要的是執行頻率資訊,它可以告訴編譯器,<br />

程式碼中哪些路徑的最常執行。 在編譯器的整個最佳化過程中,許多地方都可以派上用場,也有助於選擇對程<br />

式中的哪些區域套用主動最佳化。<br />

可產生更精準的程序內嵌,和間接呼叫升級。 剛才提過,它能更有效地提供推測與預測的選擇對象,也容許編<br />

譯器以更加準確的方式,在程序內執行程式碼配置,這在效能上可帶來明顯的好處。 除了這個執行頻率的資訊<br />

之外,編譯器還能夠排列應用程式中程序的順序;若知道頻率時,更能分割程序中熱門與冷門的部分。 最後一<br />

點是,有些資料配置轉換是根據執行頻率資訊所套用的。<br />

這份清單不太長。 這只是稍微取樣,看看編譯器能拿執行頻率資訊作些什麼用途。 此外,若有經常引起快取<br />

不中的走訪聯結串列,側寫回饋可以說明資料存取的進展。 如果可以看出進展一致,就能套用更有效率的預讀<br />

,以減少這些迴圈中發生快取不中。<br />

還有,可以收集迴圈反覆計數成為小型的長條圖,讓編譯器能夠剝除極短行程計數的迴圈,或者若有數個極為熱<br />

門的反覆計數時,也可以執行多重版本化,使得不同版本能以不同的方式最佳化;如果頻繁出現不同的反覆計數<br />

時,效率就會很高。<br />

[下一張投影片]<br />

側寫最佳化該如何使用,或是側寫最佳化該怎麼執行呢? 這道最佳化程序分為三個步驟。 首先,您需要插入二<br />

進位程式碼以收集側寫資料;之後就可以執行一般的編譯,作法是新增 profile=collect 的最佳化選項,抱歉,應<br />

該是 profile=collect 標幟到編譯行中。<br />

這樣就可以讓編譯器為程式加入測量方法,在執行期間收集側寫資料。 用 profile=collect 編譯完成之後,下一<br />

步就是執行資料收集。 這時,請用代表性的輸入或一組代表性的輸入來執行程式,以便收集統計資料和當作基<br />

準測試,或者在用測量方法執行應用程式的時候,會在一旁收集和產生側寫資料庫 (叫做 flow.data 檔案)。<br />

接著第三個步驟是用側寫資料庫執行最佳化,所以應該在編譯行使用 profile=use 標幟,這樣編譯器就會讀取第<br />

二個步驟中所收集的 flow.data 資料庫,再將側寫統計資料送入編譯器中,那麼就會像我在上一張投影片所說的<br />

,在整個編譯器中用來執行各種最佳化,或指引進行各種最佳化。


[下一張投影片]<br />

若您想要對所收集的側寫資料進行微調,或者您的應用程式因為某種原因而無法收集側寫值,<strong>HP</strong> 編譯器有幾個<br />

pragma 選項,可以向編譯器指出,替程式碼假定是哪種類型的執行側寫。 第一個是估算頻率的 pragma,可讓<br />

您指出區塊的估算相對頻率,也可用來指出迴圈的平均反覆計數,我在這裡舉出了幾個範例。 第一個範例是一<br />

個 IF 條件,可以把 pragma 估算頻率放到那個 IF 條件的本文中,例如 99% 的時間會執行那個程式碼,因此<br />

99% 的時間當中 IF 條件為真,您執行了 IF THEN ELSE 區塊的本文。<br />

看到這個範例的第二部分,在 FOR 迴圈當中,我把估算頻率 pragma 設為 10,也就是告訴編譯器,這個迴圈平<br />

均重覆執行 10 次。 對呼叫套用的,另外還有兩個 pragma。 第一個是常被叫用的 pragma,第二個是很少被<br />

叫用的 pragma,它們也有相對應的編譯行選項可替代 pragma 使用,例如對引導內嵌會有所幫助。 如果編譯<br />

器知道某個特定程序經常被叫用,對於內嵌就能夠更加主動,反之若被指為很少被叫用,也是相同的道理。<br />

[下一張投影片]<br />

再下來我想要多談一點程序間的最佳化。 這是用 +O4 最佳化層級來啟用的,此外在 +O2 或 +O3 層級也可以<br />

用 -ipo 選項來啟用。 我剛才提過,可讓編譯器執行完整程式分析和程序間的分析。 若進行程序間的最佳化,<br />

會使您的物件檔案含有中間程式碼,而非物件程式碼中一般會看到的組譯碼,實際上會延到您將所有的物件檔案<br />

都聯結在一起之後才最佳化。<br />

這個選項可以用在您要套用程序間最佳化的所有檔案,或是部分檔案。 顯然對所有檔案使用 +O4 或 -ipo 可以<br />

收到最好的效果,因為這樣可以啟用整個程式的分析和最佳化,而最佳化工具若能看到完整的程式,功能會強大<br />

許多。 程序間的最佳化是設計成不需變更使用者的建置程序,所以即使物件檔案含的是中間程式碼,在您編譯<br />

程式碼時,還是照常經過一般的編譯聯結程序。 只是最佳化會延到聯結期間罷了。<br />

我們把程序間最佳化工具設計成對 Itanium 處理器來說非常具有擴充性、也非常耐用,不過相對地建置時間與磁<br />

碟空間的用量也會增加,例如因為物件檔案含有中間程式碼的關係。 另外一點注意事項是,若您要發行程式庫<br />

檔,便無法運用程序間的最佳化,這也同樣是因為物件檔案中含有中間程式碼,由於不知道使用者會怎樣用應用<br />

程式聯結進去,所以不能發行這些檔案。<br />

[下一張投影片]<br />

這張圖片是表示我們的可擴充 IPO 實作中,整體的建置模型。 在 IPO 之下,我提到的編譯器產生中間 ELF 檔 (<br />

稱為 IELF 檔),之後會傳遞到聯結器;在聯結期間,程序間最佳化工具就會取得所有這些 IELF 檔,讀入,再執行<br />

程序間的分析和內嵌。 那個最佳化階段完成後,編譯器會善用建置機器上可用的平行處理,並且以平行方式呼<br />

叫多個後端的實例,以實際執行編譯器的程序間部分,於是產生最終的二進位程式碼。<br />

[下一張投影片]<br />

那麼,程序間的分析和最佳化究竟有什麼用處呢? 以下我來就執行程序間最佳化時可用的幾種最佳化,一一地<br />

詳細說明。 首先是別名分析。 最佳化期間,編譯器能確實同時得知可執行檔所有部分的話,便能執行更多的主<br />

動別名分析,於是例如若在 +O2 或 +O3 層級使用 -ipo 標幟執行程序間最佳化,編譯器就會執行全域位址暴露<br />

分析,基本上也就能推論出是否能套用沒有指標指向全域的宣告。 而存在有 +Ono 指標指向全域選項;這只是


宣告,您必須瞭解這對您的應用程式來說是否安全。 好,如果使用 -ipo 的話,編譯器會自行推論出來,所以您<br />

不必親自判斷是否能套用那個最佳化標幟。 若採用 +O4 層級並且加入 +Onolimit 選項,這個選項會命令編譯<br />

器在編譯期間必須非常主動,而且不必擔心編譯時間;編譯器就會執行整個程式指向分析,這項非常強大的功能<br />

可以產生別名分析,以便送入編譯的其餘部分中,可容許編譯器進行更多的主動程式碼轉換。 此外,我們也用<br />

IPO 執行跨檔案內嵌。<br />

失效的變數與函數會被移除。 我們執行變數私有化,並且也將簡短資料最佳化。 這兩項、也就是最後兩項的變<br />

數私有化與簡短資料最佳化可以改善資料存取序列。 此外,我們也會執行間接呼叫升級。 對應用程式來說的好<br />

處在於,因為您有了增強的別名分析,編譯器只要知道哪些記憶體存取彼此有別名關係、哪些資料彼此有別名關<br />

係,就能執行更多主動程式碼轉換與程式碼排程。<br />

應用程式若含有許多檔案間的呼叫,最好加以最佳化,因為您可以執行這種跨檔案的內嵌;應用程式若執行許多<br />

間接呼叫、或有許多虛擬函數,也最好加以最佳化。 此外,使用 IPO 而套用的一些最佳化項目,能夠改進資料<br />

存取的行為,所以若能運用程序間的最佳化,資料快取的行為和資料 TLB 的行為就可以大幅改進。<br />

[下一張投影片]<br />

我想談的下一個最佳化標幟是 +Ofast 選項。 剛才提過,這個選項是綜合各種選項,對多數應用程式而言一般會<br />

非常有效。<br />

這個選項是一些其他選項的別名,為了舉例,我在這裡列出所含的選項。 +Onolimit 選項讓編譯器能運用更長的<br />

編譯時間,以讓較大的程式能夠充分最佳化。 根據預設,編譯器會儘量在特定預算編譯時間內進行最佳化,但<br />

是如果超過這個時間,編譯器可能會捨棄那個最佳化層級,以免在編譯上頭花費過長的時間。 如果使用<br />

+Onolimit,它會要編譯器較為主動,不必擔心編譯時間,若應用程式含有一些大型的程序,就非常有利於獲得<br />

最佳效能。 +Ofltacc = relaxed 選項可啟用其他的浮點數最佳化功能,某些情形下會影響精確度。 有幾張投影<br />

片會再說明得更詳細一點。<br />

另外,也包括啟用清除為零的捨入模式的 +FPD 選項。 還有 +DSnative 選項,能告訴編譯器要為執行編譯器的<br />

硬體主動進行程式碼排程。 這一點很重要,因為根據預設,編譯器會運用混合排程模式。 有一些 Itanium 的實<br />

作略有差異,編譯器預設會以一般最佳的方式為程式碼排程,導致進行的處理對於 Itanium 的特定實作來說或許<br />

並非最好,但就整體實作而言確實良好;要是使用 +DSnative,它會要編譯器針對特定實作替程式碼排程,也就<br />

是您目前所編譯的實作,這對於從那項 Itanium 實作之中獲取最佳效能而言非常的好用。<br />

另外,也包含能夠控制指令和資料頁面大小的選項。 預設的頁面大小相當小,用這個選項可以取得 1M 這樣大<br />

得許多的頁面,對於減少資料 TLB 遺漏與指令 TLB 遺漏很有幫助。 此外還包括能告訴編譯器把共用程式庫的資<br />

料區段合併起來的選項。<br />

[下一張投影片]<br />

再多講一點能夠增加頁面大小的選項,這些是聯結選項,對使用大量記憶體的應用程式來說非常好用,尤其若使<br />

用應用程式時,會發生大量資料 TLB 或指令 TLB 遺漏的情形,這些就是您真的應該考慮使用的選項。 控制資料<br />

虛擬頁面大小與指令虛擬頁面大小兩者的,是兩個不同的選項;另外還有一個聯結選項,它能讓動態載入器把共<br />

用程式庫的所有資料區段合併起來。 如果應用程式聯結了大量的共用程式庫,大可以用它來降低整體的記憶體


用量與分散程度。 因為這些都是聯結選項,而不是編譯選項,實際上可以用 chatr 直接來變更。<br />

[下一張投影片]<br />

我要講的下一個選項是 +Oshortdata 選項。 剛才談到程序間的最佳化時曾經提過這個選項,因為這項最佳化可<br />

在程序間最佳化的時候自動地完成。 但如果無法或者決定對應用程式不使用程序間最佳化的話,可以考慮改用<br />

+Oshortdata。 它能控制全域指標所能存取的資料大小,也能提供比預設更短的存取序列。 編譯器一般會為它<br />

選用 n = 8 的值。 這樣一來,全域指標可以存取 8 位元組以內的資料。<br />

您可以利用這個選項來增加這個的大小,以針對較大區塊的資料使用更快的存取序列,如果指定 +Oshortdata 的<br />

時候旁邊沒有附上數值,編譯器就會把應用程式本身的資料全都放在簡短資料區內。 這裡有一個問題,就是簡<br />

短資料的大小以 4 MB 為限,所以如果應用程式本身的資料超過 4 MB,那麼單獨使用 +Oshortdata 就會發生聯<br />

結器錯誤。 如果有這種情形,請找一個最大值的 n,把儘可能多的資料塞到 4 MB 的區域中,以便加快存取序<br />

列。同樣道理,應該儘量運用程序間的最佳化,如此一來因為預設原本就會執行,就完全不必手動處理了。<br />

[下一張投影片]<br />

有些情況下,可以利用符號繫結選項來縮短資料符號的預設指令存取序列,以及副程式呼叫的指令序列。 根據<br />

預設,編譯器必須透過聯結表間接地參照外部資料符號,同時也必須儲存與復原對外部函數所有呼叫的 GP。 -<br />

Bprotected_def 最佳化標幟會把所有本區定義的符號都標示為受保護。 換句話說,這些無法被搶先取得,如此<br />

一來的好處在於編譯器能夠略過這些聯結表的存取,和本區呼叫的 GP 儲存與復原。<br />

下一個符號繫結選項是 -exec 標幟,也是剛才所講上一個選項的超集合,它能夠告訴編譯器這所有的程式碼是要<br />

編譯成為一個可執行檔,這樣可以辦到對可執行檔內所定義的符號全部都是絕對定址,此外若是您所建置的可執<br />

行檔對共用程式庫的運用非常有限,則可以使用 -minshared 選項。 除了我談到在 -Bprotected_def 和 -exec 之下<br />

的其他最佳化項目以外,對於非共用程式庫的程式碼與資料,它也能盡量產生最快的存取序列。 除非另有指示<br />

,否則它會假定所參照的符號全部都是在同一個載入模組之內所定義。<br />

所以,您發出的系統呼叫、或對共用程式庫的呼叫,都應該有相對應的系統標頭在檔案中。 舉例而言,如果呼<br />

叫 printf,請包括適當的系統標頭,這樣可以避免聯結期間發生錯誤;因為在這些標頭檔中,這些符號會標示有<br />

#pragma extern,它可以指示編譯器這些符號為外部參照性質,不要產生最快的存取序列,因為對這類呼叫是非<br />

法的。 否則就會得到聯結錯誤,若使用不當時會通知您。<br />

[下一張投影片]<br />

我要談的下一個最佳化標幟是 +Oautopar 選項,這是在即將發行的 6.15 版編譯器中的新標幟。 這是針對 C 和<br />

Fortran 語言所支援,但目前不適用於 C++ 的 +O3 及以上的最佳化層級。 若使用這個選項,編譯器會自動平<br />

行處理認為安全並且值得這麼做的所有迴圈,這樣可讓應用程式享受所執行系統擁有多核心的優勢,若您的程式<br />

碼在迴圈上花費許多時間,這一點非常有利。 不過,有個問題是這樣會增加資源的使用量,所以如果有其他程<br />

式正在執行當中,可能會有不利的影響;因為 +Oautopar 而由應用程式使用的核心數目就是一個例子,所以這<br />

一點必須牢記在心。 如同我在投影片上所表示出來的,對於迴圈執行極為密集的程式碼,運用這個選項可以收<br />

到很大的益處。 所以,舉例而言,使用 autopar 可讓 SPEC2006 FP 的 cactusADM 基準測試結果改善 60%,<br />

lbm 可改善 23%。 對於在迴圈中花費大量時間的程式碼,如果能使用這個選項,又是在多核心系統中執行的話


,得到的幫助會很大。<br />

[下一張投影片]<br />

我想討論的下一個主題是,針對浮點數應用程式進行調整時的一些特殊問題。 之前所討論過的效能調整選項,<br />

對浮點數應用程式都能適用。 不過,在對浮點數應用程式進行最佳化處理時,還是必須考慮一些權衡條件。 尤<br />

其是必須為了速度而權衡應用程式的行為或準確度時;有一個很好的例子就是採用縮約,例如浮點數相乘與相加<br />

的指令。 這個指令會執行相乘與相加,在您進行浮點數應用程式中極為常見的乘加序列時,可以省下一個指令<br />

。 只使用這個融合指令,因為可以減少中間的捨入,其實可以提高準確度。<br />

不過,如果是要將加和乘分開而達到特定捨入的極少數應用程式,可能會造成中斷。 所以某些情形下必須收斂<br />

最佳化,使應用程式達到理想的準確度。 編譯器會提供各種好用的選項和 pragma,可向編譯器描述那個應用<br />

程式的相關浮點數屬性,例如對精確計算的靈敏度,以及對浮點數環境的靈敏度 (例如是否對浮點數的運算使用<br />

狀態暫存器),編譯器就會查看這些選項和 pragma,然後按照這些限制,只套用安全的最佳化。<br />

[下一張投影片]<br />

舉例來講,我來談一下之前有幾張投影片裡頭曾經提到的 +Ofltacc 選項。 根據預設,編譯器會執行縮約的產生<br />

,例如浮點數的相乘與相加,因為這些對絕大多數的浮點數應用程式來說既安全又非常的有效。 不過,如果您<br />

的應用程式對於因最佳化所變更的值非常敏感,那就可以使用 +Ofltacc=strict 選項,它可禁止所有會將數值改變<br />

的最佳化。<br />

除了使用這個選項全面對檔案套用禁止行為之外,還有一個替代選擇是用我在這裡列出的一個 pragma:<br />

FP_CONTRACT,可將限制範圍侷限在對於會將數值變更的最佳化非常敏感的程式碼上。 反過來說,也可以使<br />

用 +Ofltacc 選項讓編譯器執行更主動的浮點數最佳化,例如若使用 +Ofltacc = limited,就能允許更多幾項最佳<br />

化,不保留 NaN、無限或帶正負號的零的行為。 同樣地,這對大多數的應用程式來說可以放心使用。接著講到<br />

+Ofltacc = relaxed,它能讓編譯器執行效率更高的除及乘序列,並可執行轉型,重新建立浮點數運算的關聯,並<br />

經由部分加總來執行總和簡化的最佳化。<br />

[下一張投影片]<br />

其他還有一些選項對於浮點數的效能有所幫助。 若您不能使用 +Ofltacc= relaxed,但程式碼中含有許多執行總<br />

和簡化的迴圈,可以用 +Osumreduction 選項讓編譯器利用展開迴圈和運算部分加總的方式,來最佳化這些序列<br />

。 所以,如果應用程式一般來講對於浮點數的行為雖然敏感,又不致於非常敏感,因此您不能將這些部分加總<br />

調整順序,那麼從這些迴圈當中獲取更好的效能會非常有幫助。 另外一個選項,我剛才也已經談過的,就是能<br />

夠對反向溢位啟用清除為零模式的 +FPD 選項,在說明 SPEC FP 效能的投影片中可以看出,它可說是非常重要的<br />

效能,因為當反向溢位將會產生異常時,它能夠避開極為緩慢的軟體輔助陷阱。<br />

不過,和在 PA RISC 上不同的是,它無法避免異常輸入的軟體輔助,卻可以避免產生許多異常的程式碼,所以才<br />

能夠避開這種軟體輔助陷阱。 此外,也有助於避免錯誤的 SIR 停頓。 SIR 是指安全指令辨識,FP 管線的第一階<br />

段會嘗試猜測目前的指令是否可能造成例外,若無法偵測得出,就會停頓。 再強調一次,使用 +FPD 有助於減<br />

少出現這種錯誤 SIR 停頓的案例數目。


[下一張投影片]<br />

我想要簡短講一下的下個主題,是在您執行最佳化當中排解疑難問題時,可以使用的幾個選項。 主動最佳化其<br />

實可能暴露出應用程式的瑕疵,我們也從一些案例看到過;因為以主動方式將程式碼最佳化的時候,等於是把運<br />

算重新排序以及執行其他轉換,這時沒有最佳化之前不曾有過的瑕疵就會忽然出現。 例如,對於主動最佳化,<br />

未初始化的變數造成問題的可能性會高出很多。<br />

所以,若發現應用程式開始作出不正確的行為,或者發出訊號,表示出現 NaT 耗用的錯誤,這時可以嘗試用<br />

+Oinitcheck 選項看看,這個選項會教編譯器偵測並且初始化所有可能未初始化的變數,於是會把編譯器無法證<br />

實已經初始化的變數全部初始化為零,在您最佳化的過程中,忽然發覺應用程式開始出現錯誤的時候,這麼做往<br />

往可以讓錯誤消失。<br />

我還想要談的另外一個領域就是溢位;依照預設,標準的帶正負號整數運算溢位,它的行為模式未定。 不過,<br />

有些應用程式其實必須倚賴預設會發生的行為。 所以根據預設,編譯器會認定帶正負號的整數運算不會溢位,<br />

如果真的發生溢位,就會執行可能使結果改變的轉換。 如果您的應用程式真的發生帶正負號整數運算的溢位,<br />

必須倚賴沒有最佳化時因這種溢位而有某種特定行為的話,可以使用 Ointeger_overflow=conservative 選項,它<br />

會告訴編譯器,如果溢位是發生在帶正負號的整數運算指令,就不要執行可能會使行為改變的轉換。 另一方面<br />

,如果有一些變數的數值龐大,可能會造成溢位,可以使用 +Ointeger_overflow 的 aggressive 選項,允許編譯<br />

器在迴圈最佳化的過程中執行變數的一些縮放,但如果知道應用程式運算使用的數值並非極為龐大,就可以用<br />

aggressive 選項來製造進一步的迴圈最佳化機會。<br />

[下一張投影片]<br />

我想要談的最後一個主題,是可以用來進行效能分析與調整的幾種工具。 2007 年 9 月發行的編譯器中,有個<br />

新的 +wperfadvice 選項,有了這個選項,編譯器就可以送出效能改善的意見。 可能也會有程式碼轉換方面的建<br />

議。 可能還會建議一些在指令行套用的選項,如果要為應用程式尋找最佳化的機會,不妨一試。 此外,<br />

Caliper 工具非常適合用來提供在 <strong>HP</strong>-UX 上編譯的應用程式的詳細效能側寫。<br />

Caliper 中也有效能顧問模式,提供的建議例如對原始碼進行變更,或根據它所收集的詳細側寫、與從側寫資料<br />

中所分析出來的作用點,建議在編譯期間提出的選項。 我想提到的另外一點是,協力廠商的程式庫效能對於應<br />

用程式效能來說可能非常重要,因此請確定所要連入的程式庫也經過良好的最佳化,尤其如果會經常使用到的話<br />

。<br />

最後,您可以使用 +Oinfo 選項,讓編譯器送出所執行最佳化屬於哪種類型的資訊,或許它能透露出編譯器所套<br />

用的最佳化類型,此外也可能指出一些實用的最佳化標幟,有助於更加主動地最佳化您的程式碼。 例如,若看<br />

到編譯器送出程式碼中的許多預讀,可能表示這個程式碼具有大量執行巢狀迴圈的傾向,這時如果您還在 +O2<br />

層級,就可以考慮把最佳化層級提高到 +O3。<br />

[下一張投影片]<br />

總之,請儘可能保持使用最新版本的編譯器。 剛才提過,編譯器所產生的效能會持續不斷地改良,所以只要改<br />

用最新版的編譯器,您的應用程式就能夠繼續提高效能。 另外,我也提過,當您建置應用程式的時候,從 +O2<br />

開始可以輕輕鬆鬆獲得非常不錯的效能,至於浮點數的應用程式,則請從 +O3 開始。 大力推薦您使用側寫最


佳化,它能夠大幅提高效能。再重複一遍,這是分為三個步驟的程序,請使用 +Oprofile 選項來利用您所收集的<br />

側寫資料庫。 如果不是要用存檔的程式庫出貨,一定要考慮加入 +O4 選項或 -ipo,以進行完整程式分析、程序<br />

間最佳化以及內嵌。 如果您的應用程式需要很多的記憶體,請用 +pd 和 +pi 聯結選項、或 chatr 指令來啟用大<br />

型頁面,尤其若是發現應用程式有許多 TLB 遺漏的話,那就更應該這麼做。<br />

[下一張投影片]<br />

若您無法使用 +O4,可以考慮使用一些選項來獲取好處,例如 -minshared 選項、-Bprotected_def 和<br />

+Oshortdata 選項都可以。 如果您能夠使用 +O4 和 -ipo,那太好了,您甚至不必考慮使用最佳化標幟,因為預<br />

設就有這種行為;但若無法使用 +O4,請考慮使用這些各種不同的標幟,如果編譯器不會執行完整程式分析,<br />

至少也能夠補充一些編譯器無法取得的資訊。<br />

對於浮點數特別多的程式碼,我再說一次,請從 +O3 開始,並且考慮使用 +Ofltacc = relaxed 和 +FPD。 它們<br />

適用於絕大多數的浮點數應用程式,可為 Itanium 提升很多的效能。<br />

[下一張投影片]<br />

為了對這個主題感興趣的人,我特地列出了一些討論 <strong>HP</strong>-UX 上應用程式效能與調整的其他文獻指引,也列出了<br />

<strong>HP</strong> Caliper 網站指引,裡頭有 Caliper 的下載項目;另外還有說明文件的指引,對於我提到的效能調整非常實用<br />

。<br />

[下一張投影片]<br />

在這張投影片,我提供了一些網頁的指引,您可以下載各種編譯器的開發人員套件,這些網頁中還有編譯器的說<br />

明文件指引、和其他技術資源,例如我在上一張投影片所提及文獻指引等等。 在右邊這裡,是告訴您如何取得<br />

C 與 C++ 語言的線上程式設計師指南。 這些指南中有我所說明的一些選項、以及其他可用選項的詳細描述,只<br />

要在編譯指令的後面使用 +help 選項,就能夠叫出。 今天就講到這裡。 感謝您的參與。<br />

如需更多資訊,請到:<br />

www.hp.com/go/kod<br />

© 2008 Hewlett-Packard Development Company, L.P. 本文包含的資訊如有變更,恕不另行通知。 產品與服務所附<br />

的保固聲明是 <strong>HP</strong> 對其產品與服務的唯一保固內容。 本文所述一切不應被視為提供額外保固。 <strong>HP</strong> 對於本文中的技<br />

術錯誤、編輯錯誤或遺漏概不負責。

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!