DSP程式優化方法

2022-12-15 20:54:03 字數 2743 閱讀 2369

6、提高cpu的並行性

(1)使用並行**

盡可能把長的有依賴的**鏈分解成幾個可以在流水線執行單元中並行執行的沒有依賴的**鏈。很多高階語言,包括c++,並不對產生的浮點表示式重新排序,因為那是乙個相當複雜的過程。需要注意的是,重排序的**和原來的**在**上一致並不等價於計算結果一致,因為浮點操作缺乏精確度。

在一些情況下,這些優化可能導致意料之外的結果。幸運的是,在大部分情況下,最後結果可能只有最不重要的位(即最低位)是錯誤的。不好的**:

double a[100],sum;int i;sum = 0.0f;

for (i=0;i<100;i++)

sum += a[i];推薦的**:

double a[100],sum1,sum2,sum3,sum4,sum;int i;

sum1 = sum2 = sum3 = sum4 = 0.0;for (i = 0;i < 100;i += 4)

sum = (sum4+sum3)+(sum1+sum2);

要注意的是:使用4路分解是因為這樣使用了4段流水線浮點加法,浮點加法的每乙個段占用乙個時鐘週期,保證了最大的資源利用率。

(2)避免沒有必要的讀寫依賴

當資料儲存到記憶體時存在讀寫依賴,即資料必須在正確寫入後才能再次讀取。雖然amd athlon等cpu有加速讀寫依賴延遲的硬體,允許

在要儲存的資料被寫入記憶體前讀取出來,但是,如果避免了讀寫依賴並把資料儲存在內部暫存器中,速度會更快。在一段很長的又互相依賴的**鏈中,避免讀寫依賴顯得尤其重要。如果讀寫依賴發生在運算元組時,許多編譯器不能自動優化**以避免讀寫依賴。

所以推薦程式設計師手動去消除讀寫依賴,舉例來說,引進乙個可以儲存在暫存器中的臨時變數。這樣可以有很大的效能提公升。下面一段**是乙個例子:

不好的**:

float x[veclen],y[veclen],z[veclen];。。。。。。

for (unsignedint k = 1;k < veclen;k ++)

for (k = 1;k x[k] = z[k] * (y[k] - x[k-1]);}

推薦的**:

float x[veclen],y[veclen],z[veclen];。。。。。。float t(x[0]);

for (unsignedint k = 1;k < veclen;k ++)

t = x[0];

for (k = 1;k <;veclen;k ++)

7、迴圈不變計算

對於一些不需要迴圈變數參加運算的計算任務可以把它們放到迴圈外面,現在許多編譯器還是能自己幹這件事,不過對於中間使用了變數的算式它們就不敢動了,所以很多情況下你還得自己幹。對於那些在迴圈中呼叫的函式,凡是沒必要執行多次的操作通通提出來,放到乙個init函式裡,迴圈前呼叫。另外儘量減少餵食次數,沒必要的話盡量不給它傳參,需要迴圈變數的話讓它自己建立乙個靜態迴圈變數自己累加,速度

會快一點。

還有就是結構體訪問,東樓的經驗,凡是在迴圈裡對乙個結構體的兩個以上的元素執行了訪問,就有必要建立中間變數了(結構這樣,那c++的物件呢?想想看),看下面的例子:舊**:total =

a->b->c[4]->aardvark +a->b->c[4]->baboon +a->b->c[4]->cheetah +a->b->c[4]->dog;新**:

struct animals * temp = a->b->c[4];total =

temp->aardvark +temp->baboon +temp->cheetah +temp->dog;

一些老的c語言編譯器不做聚合優化,而符合ansi規範的新的編譯器可以自動完成這個優化,看例子:float a,b,c,d,f,g;。。。

a = b / c * d;f = b * g / c;

這種寫法當然要得,但是沒有優化float a,b,c,d,f,g;。。。

a = b / c * d;f = b / c * g;

如果這麼寫的話,乙個符合ansi規範的新的編譯器可以只計算b/c一次,然後將結果代入第二個式子,節約了一次除法運算。

8、函式優化

(1)inline函式

在c++中,關鍵字inline可以被加入到任何函式的宣告中。這個關鍵字請求編譯器用函式內部的**替換所有對於指出的函式的呼叫。這樣做在兩個方面快於函式呼叫:

第一,省去了呼叫指令需要的執行時間;第二,省去了傳遞變元和傳遞過程需要的時間。但是使用這種方法在優化程式速度的同時,程式長度變大了,因此需要更多的rom。使用這種優化在inline函式頻繁呼叫並且只包含幾行**的時候是最有效的。

(2)不定義不使用的返回值

函式定義並不知道函式返回值是否被使用,假如返回值從來不會被用到,應該使用void來明確宣告函式不返回任何值。

(3)減少函式呼叫引數

使用全域性變數比函式傳遞引數更加有效率。這樣做去除了函式呼叫引數入棧和函式完成後引數出棧所需要的時間。然而決定使用全域性變數會影響程式的模組化和重入,故要慎重使用。

(4)所有函式都應該有原型定義

一般來說,所有函式都應該有原型定義。原型定義可以傳達給編譯器更多的可能用於優化的資訊。

(5)盡可能使用常量(const)

盡可能使用常量(const)。c++標準規定,如果乙個const宣告的物件的位址不被獲取,允許編譯器不對它分配儲存空間。這樣可以使**更有效率,而且可以生成更好的**。

(6)把本地函式宣告為靜態的(static)

如果乙個函式只在實現它的檔案中被使用,把它宣告為靜態的(static)以強制使用內部連線。否則,預設的情況下會把函式定義為外部連線。這樣可能會影響某些編譯器的優化——比如,自動內聯。

最優化方法之存貯論的例項和源程式

天津工業大學理學院 最優化課程設計 最優化方法課程設計 關於存貯論的操作實踐 存貯論 inventory theory 又稱庫存理論,是運籌學中發展較早的分支。現代化的生產和經營活動都離不開存貯,為了使生產和經營活動有條不紊地進行,一般的工商企業總需要一定數量的貯備物資來支援。在企業的生產經營或人們...

微控制器C程式優化

對程式進行優化,通常是指優化程式 或程式執行速度。優化 和優化速度實際上是乙個予盾的統一。一般是優化了 的尺寸,就會帶來執行時間的增加 如果優化了程式的執行速度,通常會帶來 增加的 很難魚與熊掌兼得,只能在設計時掌握乙個平衡點。一 程式結構的優化 1 程式的書寫結構 雖然書寫格式並不會影響生成的 質...

最優化方法綜述

1.引論 1.1應用介紹 最優化理論與演算法是乙個重要的數學分支,它所研究的問題是討論在眾多的方案中什麼樣的方案最優以及怎樣找出最優方案。這類問題普遍存在。例如,工程設計中怎樣選擇設計引數,使得設計方案滿足設計要求,又能降低成本 資源分配中,怎樣分配有限資源,使得分配方案既能滿足各方面的基本要求,又...