国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

C++代碼優化方法(1)

2019-11-17 05:15:57
字體:
來源:轉載
供稿:網友
在C++層次進行優化,比在匯編層次優化具有更好的移植性,應該是優化中的首選做法。

確定浮點型變量和表達式是 float 型

為了讓編譯器產生更好的代碼(比如說產生3DNow! 或SSE指令的代碼),必須確定浮點型變量和表達式是 float 型的。要非凡注重的是,以 ";F"; 或 ";f"; 為后綴(比如:3.14f)的浮點常量才是 float 型,否則默認是 double 型。為了避免 float 型參數自動轉化為 double,請在函數聲明時使用 float。

使用32位的數據類型

編譯器有很多種,但它們都包含的典型的32位類型是:int,signed,signed int,unsigned,unsigned int,long,signed long,long int,signed long int,unsigned long,unsigned long int。盡量使用32位的數據類型,因為它們比16位的數據甚至8位的數據更有效率。

明智使用有符號整型變量

在很多情況下,你需要考慮整型變量是有符號還是無符號類型的。比如,保存一個人的體重數據時不可能出現負數,所以不需要使用有符號類型。但是,假如是要保存溫度數據,就必須使用到有符號的變量。

在許多地方,考慮是否使用有符號的變量是必要的。在一些情況下,有符號的運算比較快;但在一些情況下卻相反。比如:整型到浮點轉化時,使用大于16位的有符號整型比較快。因為x86構架中提供了從有符號整型轉化到浮點型的指令,但沒有提供從無符號整型轉化到浮點的指令。看看編譯器產生的匯編代碼,不好的代碼:

編譯前 編譯后

double x; mov [foo + 4], 0

unsigned int i; mov eax, i

x = i; mov [foo], eax

flid qWord ptr [foo]

fstp qword ptr [x]

上面的代碼比較慢。不僅因為指令數目比較多,而且由于指令不能配對造成的FLID指令被延遲執行。最好用以下代碼代替,推薦的代碼:

編譯前 編譯后

double x; fild dword ptr [i]

int i; fstp qword ptr [x]

x = i;

在整數運算中計算商和余數時,使用無符號類型比較快。以下這段典型的代碼是編譯器產生的32位整型數除以4的代碼,不好的代碼 推薦的代碼

編譯前 編譯后

int i; mov eax, i

i = i / 4; cdq

and edx, 3

add eax, edx

sar eax, 2

mov i, eax

編譯前 編譯后

unsigned int i; shr i, 2

i = i / 4;

總結:

無符號類型用于:

除法和余數

循環計數

數組下標

有符號類型用于:

整型到浮點的轉化

while VS. for

在編程中,我們經常需要用到無限循環,常用的兩種方法是while (1) 和 for (;;)。這兩種方法效果完全一樣,但那一種更好呢?然我們看看它們編譯后的代碼:

編譯前 編譯后

while (1); mov eax,1

test eax,eax

je foo+23h

jmp foo+18h

編譯前 編譯后

for (;;); jmp foo+23h

for (;;)指令少,不占用寄存器,而且沒有判定跳轉,比while (1)好。使用數組型代替指針型 使用指針會使編譯器很難優化它。因為缺乏有效的指針代碼優化的方法,編譯器總是假設指針可以訪問內存的任意地方,包括分配給其他變量的儲存空間。所以為了編譯器產生優化得更好的代碼,要避免在不必要的地方使用指針。一個典型的例子是訪問存放在數組中的數據。C++ 答應使用操作符 [] 或指針來訪問數組,使用數組型代碼會讓優化器減少產生不安全代碼的可能性。比如,x[0] 和x[2] 不可能是同一個內存地址,但 *p 和 *q 可能。強烈建議使用數組型,因為這樣可能會有意料之外的性能提升。

不好的代碼 推薦的代碼 typedef strUCt

{

float x,y,z,w;

} VERTEX;

typedef struct

{

float m[4][4];

} MATRIX;

void XForm(float* res, const float* v, const float* m, int nNumVerts)

{

float dp;

int i;

 const VERTEX* vv = (VERTEX *)v;

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

{

dp = vv->;x * *m ++;

dp += vv->;y * *m ++;

dp += vv->;z * *m ++;

dp += vv->;w * *m ++;

*res ++ = dp;// 寫入轉換了的 x

dp = vv->;x * *m ++;

dp += vv->;y * *m ++;

dp += vv->;z * *m ++;

dp += vv->;w * *m ++;

*res ++ = dp; // 寫入轉換了的 y

dp = vv->;x * *m ++;

dp += vv->;y * *m ++;

dp += vv->;z * *m ++;

dp += vv->;w * *m ++;

*res ++ = dp;// 寫入轉換了的 z

dp = vv->;x * *m ++;

dp += vv->;y * *m ++;

dp += vv->;z * *m ++;

dp += vv->;w * *m ++;

*res ++ = dp;// 寫入轉換了的 w

vv ++;  // 下一個矢量

m -= 16;

}

}

typedef struct

{

float x,y,z,w;

} VERTEX;

typedef struct

{

float m[4][4];

} MATRIX;

void XForm (float* res, const float* v, const float* m, int nNumVerts)

{

int i;

const VERTEX* vv = (VERTEX*)v;

const MATRIX* mm = (MATRIX*)m;

VERTEX* rr = (VERTEX*)res;

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

{

rr->;x = vv->;x * mm->;m[0][0] + vv->;y * mm->;m[0][1]

+ vv->;z * mm->;m[0][2] + vv->;w * mm->;m[0][3];

rr->;y = vv->;x * mm->;m[1][0] + vv->;y * mm->;m[1][1]

+ vv->;z * mm->;m[1][2] + vv->;w * mm->;m[1][3];

rr->;z = vv->;x * mm->;m[2][0] + vv->;y * mm->;m[2][1]

+ vv->;z * mm->;m[2][2] + vv->;w * mm->;m[2][3];

rr->;w = vv->;x * mm->;m[3][0] + vv->;y * mm->;m[3][1]

+ vv->;z * mm->;m[3][2] + vv->;w * mm->;m[3][3];

}

}


注重: 源代碼的轉化是與編譯器的代碼發生器相結合的。從源代碼層次很難控制產生的機器碼。依靠編譯器和非凡的源代碼,有可能指針型代碼編譯成的機器碼比同等條件下的數組型代碼運行速度更快。明智的做法是在源代碼轉化后檢查性能是否真正提高了,再選擇使用指針型還是數組型。 在C++層次進行優化,比在匯編層次優化具有更好的移植性,應該是優化中的首選做法。

確定浮點型變量和表達式是 float 型

為了讓編譯器產生更好的代碼(比如說產生3DNow! 或SSE指令的代碼),必須確定浮點型變量和表達式是 float 型的。要非凡注重的是,以 ";F"; 或 ";f"; 為后綴(比如:3.14f)的浮點常量才是 float 型,否則默認是 double 型。為了避免 float 型參數自動轉化為 double,請在函數聲明時使用 float。

使用32位的數據類型

編譯器有很多種,但它們都包含的典型的32位類型是:int,signed,signed int,unsigned,unsigned int,long,signed long,long int,signed long int,unsigned long,unsigned long int。盡量使用32位的數據類型,因為它們比16位的數據甚至8位的數據更有效率。

明智使用有符號整型變量

在很多情況下,你需要考慮整型變量是有符號還是無符號類型的。比如,保存一個人的體重數據時不可能出現負數,所以不需要使用有符號類型。但是,假如是要保存溫度數據,就必須使用到有符號的變量。

在許多地方,考慮是否使用有符號的變量是必要的。在一些情況下,有符號的運算比較快;但在一些情況下卻相反。比如:整型到浮點轉化時,使用大于16位的有符號整型比較快。因為x86構架中提供了從有符號整型轉化到浮點型的指令,但沒有提供從無符號整型轉化到浮點的指令。看看編譯器產生的匯編代碼,不好的代碼:

編譯前 編譯后

double x; mov [foo + 4], 0

unsigned int i; mov eax, i

x = i; mov [foo], eax

flid qword ptr [foo]

fstp qword ptr [x]

上面的代碼比較慢。不僅因為指令數目比較多,而且由于指令不能配對造成的FLID指令被延遲執行。最好用以下代碼代替,推薦的代碼:

編譯前 編譯后

double x; fild dword ptr [i]

int i; fstp qword ptr [x]

x = i;

在整數運算中計算商和余數時,使用無符號類型比較快。以下這段典型的代碼是編譯器產生的32位整型數除以4的代碼,不好的代碼 推薦的代碼

編譯前 編譯后

int i; mov eax, i

i = i / 4; cdq

and edx, 3

add eax, edx

sar eax, 2

mov i, eax

編譯前 編譯后

unsigned int i; shr i, 2

i = i / 4;

總結:

無符號類型用于:

除法和余數

循環計數

數組下標

有符號類型用于:

整型到浮點的轉化

while VS. for

在編程中,我們經常需要用到無限循環,常用的兩種方法是while (1) 和 for (;;)。這兩種方法效果完全一樣,但那一種更好呢?然我們看看它們編譯后的代碼:

編譯前 編譯后

while (1); mov eax,1

test eax,eax

je foo+23h

jmp foo+18h

編譯前 編譯后

for (;;); jmp foo+23h

for (;;)指令少,不占用寄存器,而且沒有判定跳轉,比while (1)好。使用數組型代替指針型 使用指針會使編譯器很難優化它。因為缺乏有效的指針代碼優化的方法,編譯器總是假設指針可以訪問內存的任意地方,包括分配給其他變量的儲存空間。所以為了編譯器產生優化得更好的代碼,要避免在不必要的地方使用指針。一個典型的例子是訪問存放在數組中的數據。C++ 答應使用操作符 [] 或指針來訪問數組,使用數組型代碼會讓優化器減少產生不安全代碼的可能性。比如,x[0] 和x[2] 不可能是同一個內存地址,但 *p 和 *q 可能。強烈建議使用數組型,因為這樣可能會有意料之外的性能提升。

不好的代碼 推薦的代碼 typedef struct

{

float x,y,z,w;

} VERTEX;

typedef struct

{

float m[4][4];

} MATRIX;

void XForm(float* res, const float* v, const float* m, int nNumVerts)

{

float dp;

int i;

 const VERTEX* vv = (VERTEX *)v;

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

{

dp = vv->;x * *m ++;

dp += vv->;y * *m ++;

dp += vv->;z * *m ++;

dp += vv->;w * *m ++;

*res ++ = dp;// 寫入轉換了的 x

dp = vv->;x * *m ++;

dp += vv->;y * *m ++;

dp += vv->;z * *m ++;

dp += vv->;w * *m ++;

*res ++ = dp; // 寫入轉換了的 y

dp = vv->;x * *m ++;

dp += vv->;y * *m ++;

dp += vv->;z * *m ++;

dp += vv->;w * *m ++;

*res ++ = dp;// 寫入轉換了的 z

dp = vv->;x * *m ++;

dp += vv->;y * *m ++;

dp += vv->;z * *m ++;

dp += vv->;w * *m ++;

*res ++ = dp;// 寫入轉換了的 w

vv ++;  // 下一個矢量

m -= 16;

}

}

typedef struct

{

float x,y,z,w;

} VERTEX;

typedef struct

{

float m[4][4];

} MATRIX;

void XForm (float* res, const float* v, const float* m, int nNumVerts)

{

int i;

const VERTEX* vv = (VERTEX*)v;

const MATRIX* mm = (MATRIX*)m;

VERTEX* rr = (VERTEX*)res;

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

{

rr->;x = vv->;x * mm->;m[0][0] + vv->;y * mm->;m[0][1]

+ vv->;z * mm->;m[0][2] + vv->;w * mm->;m[0][3];

rr->;y = vv->;x * mm->;m[1][0] + vv->;y * mm->;m[1][1]

+ vv->;z * mm->;m[1][2] + vv->;w * mm->;m[1][3];

rr->;z = vv->;x * mm->;m[2][0] + vv->;y * mm->;m[2][1]

+ vv->;z * mm->;m[2][2] + vv->;w * mm->;m[2][3];

rr->;w = vv->;x * mm->;m[3][0] + vv->;y * mm->;m[3][1]

+ vv->;z * mm->;m[3][2] + vv->;w * mm->;m[3][3];

}

}


注重: 源代碼的轉化是與編譯器的代碼發生器相結合的。從源代碼層次很難控制產生的機器碼。依靠編譯器和非凡的源代碼,有可能指針型代碼編譯成的機器碼比同等條件下的數組型代碼運行速度更快。明智的做法是在源代碼轉化后檢查性能是否真正提高了,再選擇使用指針型還是數組型。 在C++層次進行優化,比在匯編層次優化具有更好的移植性,應該是優化中的首選做法。

確定浮點型變量和表達式是 float 型

為了讓編譯器產生更好的代碼(比如說產生3DNow! 或SSE指令的代碼),必須確定浮點型變量和表達式是 float 型的。要非凡注重的是,以 ";F"; 或 ";f"; 為后綴(比如:3.14f)的浮點常量才是 float 型,否則默認是 double 型。為了避免 float 型參數自動轉化為 double,請在函數聲明時使用 float。

使用32位的數據類型

編譯器有很多種,但它們都包含的典型的32位類型是:int,signed,signed int,unsigned,unsigned int,long,signed long,long int,signed long int,unsigned long,unsigned long int。盡量使用32位的數據類型,因為它們比16位的數據甚至8位的數據更有效率。

明智使用有符號整型變量

在很多情況下,你需要考慮整型變量是有符號還是無符號類型的。比如,保存一個人的體重數據時不可能出現負數,所以不需要使用有符號類型。但是,假如是要保存溫度數據,就必須使用到有符號的變量。

在許多地方,考慮是否使用有符號的變量是必要的。在一些情況下,有符號的運算比較快;但在一些情況下卻相反。比如:整型到浮點轉化時,使用大于16位的有符號整型比較快。因為x86構架中提供了從有符號整型轉化到浮點型的指令,但沒有提供從無符號整型轉化到浮點的指令。看看編譯器產生的匯編代碼,不好的代碼:

編譯前 編譯后

double x; mov [foo + 4], 0

unsigned int i; mov eax, i

x = i; mov [foo], eax

flid qword ptr [foo]

fstp qword ptr [x]

上面的代碼比較慢。不僅因為指令數目比較多,而且由于指令不能配對造成的FLID指令被延遲執行。最好用以下代碼代替,推薦的代碼:

編譯前 編譯后

double x; fild dword ptr [i]

int i; fstp qword ptr [x]

x = i;

在整數運算中計算商和余數時,使用無符號類型比較快。以下這段典型的代碼是編譯器產生的32位整型數除以4的代碼,不好的代碼 推薦的代碼

編譯前 編譯后

int i; mov eax, i

i = i / 4; cdq

and edx, 3

add eax, edx

sar eax, 2

mov i, eax

編譯前 編譯后

unsigned int i; shr i, 2

i = i / 4;

總結:

無符號類型用于:

除法和余數

循環計數

數組下標

有符號類型用于:

整型到浮點的轉化

while VS. for

在編程中,我們經常需要用到無限循環,常用的兩種方法是while (1) 和 for (;;)。這兩種方法效果完全一樣,但那一種更好呢?然我們看看它們編譯后的代碼:

編譯前 編譯后

while (1); mov eax,1

test eax,eax

je foo+23h

jmp foo+18h

編譯前 編譯后

for (;;); jmp foo+23h

for (;;)指令少,不占用寄存器,而且沒有判定跳轉,比while (1)好。使用數組型代替指針型 使用指針會使編譯器很難優化它。因為缺乏有效的指針代碼優化的方法,編譯器總是假設指針可以訪問內存的任意地方,包括分配給其他變量的儲存空間。所以為了編譯器產生優化得更好的代碼,要避免在不必要的地方使用指針。一個典型的例子是訪問存放在數組中的數據。C++ 答應使用操作符 [] 或指針來訪問數組,使用數組型代碼會讓優化器減少產生不安全代碼的可能性。比如,x[0] 和x[2] 不可能是同一個內存地址,但 *p 和 *q 可能。強烈建議使用數組型,因為這樣可能會有意料之外的性能提升。

不好的代碼 推薦的代碼 typedef struct

{

float x,y,z,w;

} VERTEX;

typedef struct

{

float m[4][4];

} MATRIX;

void XForm(float* res, const float* v, const float* m, int nNumVerts)

{

float dp;

int i;

 const VERTEX* vv = (VERTEX *)v;

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

{

dp = vv->;x * *m ++;

dp += vv->;y * *m ++;

dp += vv->;z * *m ++;

dp += vv->;w * *m ++;

*res ++ = dp;// 寫入轉換了的 x

dp = vv->;x * *m ++;

dp += vv->;y * *m ++;

dp += vv->;z * *m ++;

dp += vv->;w * *m ++;

*res ++ = dp; // 寫入轉換了的 y

dp = vv->;x * *m ++;

dp += vv->;y * *m ++;

dp += vv->;z * *m ++;

dp += vv->;w * *m ++;

*res ++ = dp;// 寫入轉換了的 z

dp = vv->;x * *m ++;

dp += vv->;y * *m ++;

dp += vv->;z * *m ++;

dp += vv->;w * *m ++;

*res ++ = dp;// 寫入轉換了的 w

vv ++;  // 下一個矢量

m -= 16;

}

}

typedef struct

{

float x,y,z,w;

} VERTEX;

typedef struct

{

float m[4][4];

} MATRIX;

void XForm (float* res, const float* v, const float* m, int nNumVerts)

{

int i;

const VERTEX* vv = (VERTEX*)v;

const MATRIX* mm = (MATRIX*)m;

VERTEX* rr = (VERTEX*)res;

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

{

rr->;x = vv->;x * mm->;m[0][0] + vv->;y * mm->;m[0][1]

+ vv->;z * mm->;m[0][2] + vv->;w * mm->;m[0][3];

rr->;y = vv->;x * mm->;m[1][0] + vv->;y * mm->;m[1][1]

+ vv->;z * mm->;m[1][2] + vv->;w * mm->;m[1][3];

rr->;z = vv->;x * mm->;m[2][0] + vv->;y * mm->;m[2][1]

+ vv->;z * mm->;m[2][2] + vv->;w * mm->;m[2][3];

rr->;w = vv->;x * mm->;m[3][0] + vv->;y * mm->;m[3][1]

+ vv->;z * mm->;m[3][2] + vv->;w * mm->;m[3][3];

}

}


注重: 源代碼的轉化是與編譯器的代碼發生器相結合的。從源代碼層次很難控制產生的機器碼。依靠編譯器和非凡的源代碼,有可能指針型代碼編譯成的機器碼比同等條件下的數組型代碼運行速度更快。明智的做法是在源代碼轉化后檢查性能是否真正提高了,再選擇使用指針型還是數組型。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 黎川县| 新丰县| 九江县| 易门县| 兰坪| 崇文区| 仁寿县| 屯留县| 张掖市| 黑山县| 永平县| 白银市| 陈巴尔虎旗| 苍梧县| 古浪县| 电白县| 富裕县| 安西县| 涟源市| 巩留县| 莱芜市| 麻栗坡县| 灵丘县| 平舆县| 黔东| 高雄县| 耿马| 景东| 永福县| 台安县| 昌黎县| 新绛县| 万盛区| 海阳市| 繁昌县| 报价| 平泉县| 泰安市| 乌海市| 海门市| 邹城市|