1. 程式人生 > >提高程式執行速度的方法

提高程式執行速度的方法

1、選擇一組合適的演算法和資料結構;
2、編寫出編譯器能夠有效優化的原始碼;(編寫程式方式中一點小小的變動,都會引起編譯器優化方式的很大變化,必須瞭解編譯器的能力和侷限性,有些程式語言比其他語言容易優化得多,C語言的有些特性,如:執行指標運算和強制型別轉換,使得編譯器很難對它進行優化。在程式的開發和優化的過程中,我們必須考濾程式碼的使用方法,程式設計師必須在實現和維護程式的簡單性與它的執行速度之間做出權衡,在程式碼級上,許多低階的優化往往會降低程式的可讀性和模組性,使得程式容易出錯,並且更難以修改和擴充套件。
優化程式效能的基本策略:
1、高階設計。為遇到的問題選擇適當的演算法和資料結構。要特別警覺,避免使用那些會漸進地產生糟糕效能的演算法或編碼技術
2、基本編碼原則。避免限制優化的因素,這樣編譯器就能產生高效的程式碼。消除連續的函式呼叫。在可能時,將計算移到迴圈外。考慮有選擇地妥協程式的模組性以獲得更大的效率。消除不必要的儲存器引用。引入臨時變數來儲存中間結果。只有在最後的值計算出來時,才將結果存放到陣列或全域性變數中。
3、低階優化。展開迴圈,降低開銷,並且使得進一步優化成為可能。通過使用例如多個累積變數和重新結合等技術,找到方法提高指令級並行。用功能的風格重寫條件操作,使得編譯採用條件資料傳送。)
3、將一個任務分成多個部分,使這些部分可以在多核和多處理器以及網路中能夠並行、併發的執行。

Amdahl定律:

如果邏輯控制流在時間上重疊,就是併發的。並行與併發的區別是,並行流是並行執行的,併發流是交替執行的,在巨集觀上產生幾個程式同時執行的現象,併發並沒有在根本上提高程式的執行效率。並行需要硬體的支援,併發可以在邏輯控制流上實現。併發可以解決訪問慢速I/O裝置、與人互動、推遲工作到優先順序較低的併發流中以降低延遲、服務多個網路客戶端,併發可以利用多核CPU實現平行計算。

使用應用級併發的應用程式稱為併發程式,現代作業系統提供三種基本的構造併發程式的方法:1、程序:用這種方法,每個邏輯控制流都是一個程序,由核心來排程和維護。因為程序有獨立的虛擬地址空間,想要和其他流通訊,控制流必須使用某種顯式的程序間通訊(interprocess communication, IPC)機制。2、I/O多路複用:在這種形式的併發程式設計中,應用程式在一個程序的上下文中顯式地排程它們自己的邏輯流。邏輯流被模型化為狀態機,資料到達檔案描述符後,主程式顯式地從一個狀態轉換到另一個狀態。因為程式是一個單獨的程序,所以所有的流都共享同一個地址空間。3、執行緒:執行緒是執行在一個單一程序上下文中的邏輯流,由核心進行排程。你可以把執行緒看成是其他兩種方式的混合體,像程序流一樣由核心進行排程,而像I/O多路複用流一樣共享同一個虛擬地址空間。

基於程序的併發程式設計:關於程序的優劣:
    對於在父、子程序間共享狀態資訊,程序有一個非常清晰的模型:共享檔案表,但是不共享使用者地址空間。程序有獨立的地址空間即是優點也是缺點。這樣一來,一個程序不可能不小心覆蓋另一個程序的虛擬儲存器,這就消除了許多令人迷惑的錯誤——這是一個明顯的優點。
    另一方面,獨立的地址空間使得程序共享狀態資訊變得更加困難。為了共享資訊,它們必須使用顯式的IPC(程序間通訊)機制。基於程序的設計的另一個缺點是,它們往往比較慢,因為程序和IPC的開銷很高。

基於I/O多路複用的併發程式設計:I/O多路複用技術的優劣:
    I/O多路複用可以用做併發事件驅動程式的基礎,在事件驅動程式中,流是因為某種事件而前進的。一般概念是將邏輯流模型化為狀態機。不嚴格地說,一個狀態機就是一組狀態(state)、輸入事件(input event)和轉移(transition),其中轉移就是將狀態和輸入事件對映到狀態。每個轉移都將一個(輸入狀態,輸入事件)對對映到一個輸出狀態。自迴圈(self-loop)是同一輸入和輸出狀態之間的轉移。通常把狀態機畫成有向圖,其中節點表示狀態,有向弧表示轉移,而弧上的標號表示輸入事件。一個狀態機從某種初始狀態開始執行。每個輸入事件都會引發一個從當前狀態到下一狀態的轉移。
    基於I/O多路複用的事件驅動設計的一個優點是,它比基於程序的設計給了程式設計師更多的對程式行為的控制。另一個優點是,一個基於I/O多路複用的事件驅動伺服器是執行在單一程序上下文中的,因此每個邏輯流都能訪問該程序的全部地址空間。這使得在流之間共享資料變得容易。最後,事件驅動設計常常比基於程序的設計要高效得多,因為它們不需要程序上下文切換來排程新的流。
    事件驅動設計的一個明顯示的缺點就是編碼複雜。隨著併發粒度的減小,複雜性上升。基於事件的設計的另一個重大缺點是它們不能充分利用多核處理器。

基於執行緒的併發程式設計:
    基於執行緒的併發程式設計可以看作上面兩種方式的混合,相較於基於程序的併發程式設計,基於執行緒的併發程式設計具有一至的使用者虛擬地址空間,使得資訊共享較容易實現,相較於基於I/O多路複用的併發程式設計,基於執行緒的併發程式設計的每個邏輯流會被核心自動排程,有利於充分利用多核處理器。
    執行緒(thread)就是執行在程序上下文中的邏輯流。執行緒由核心自動排程。每個執行緒都有自己的執行緒上下文(thread context),包括一個唯一的整數執行緒ID(Thread ID)、棧、棧指標、程式計數器、通用目的暫存器和條件碼。所有的執行在一個程序裡的執行緒共享該程序的整個虛擬地址空間。
    多執行緒的執行模型在某些方面和多程序的執行模型是相似的。在一些重要的方面,執行緒執行是不同於程序的。因為一個執行緒的上下文要比一個程序的上下文小得多。另一個不同就是執行緒不像程序那樣,不是按照嚴格的父子層次來組織的。和一個程序相關的執行緒組成一個對等(執行緒)池(pool),獨立於其他執行緒建立的執行緒。主執行緒和其他執行緒的區別僅在於它總是程序中第一個執行的執行緒。對等(執行緒)池概念的主要影響是,一個執行緒可以殺死它的任何對等執行緒,或者等待它的任意對等執行緒終止。另外,每個對等執行緒都能讀寫相同的共享資料。
    Posix執行緒(Pthreads)是在C程式中處理執行緒的一個標準介面。
    基於執行緒的事件驅動程式:使用執行緒提高並行性:一旦要求同步對資料的訪問,事情就變得複雜得多了。
    執行緒安全。可重入性。競爭。