[英]Convert C++ code to x87 inline assembly code
我正在嘗試將 C++ 代碼轉換為 x87 樣式的內聯匯編代碼。
C++ 代碼:
double a = 0.0, b = 0.0, norm2 = 0.0;
int n;
for (n = 0; norm2 < 4.0 && n < N; ++n) {
double c = a*a - b*b + x;
b = 2.0*a*b + y;
a = c;
norm2 = a*a + b*b;
}
內聯匯編代碼:
double a = 0.0, b = 0.0, norm2 = 0.0;
int n;
for (n = 0; norm2 < 4.0 && n < N; ++n) {
// double c = a * a - b * b + x;
__asm fld a
__asm fmul st(0), st(0)
__asm fld b
__asm fmul st(0), st(0)
__asm fsubp st(1), st(0)
__asm fld x
__asm faddp st(1), st(0)
__asm fstp c
// b = 2.0 * a * b + y;
__asm fld two
__asm fld b
__asm fld a
__asm fmulp st(2), st(0)
__asm fmulp st(1), st(0)
__asm fld y
__asm faddp st(1), st(0)
__asm fstp b
// a = c
__asm fld c
__asm fstp a
//norm2 = a * a + b * b;
__asm fld a
__asm fmul st(0), st(0)
__asm fld b
__asm fmul st(0), st(0)
__asm faddp st(1), st(0)
__asm fstp norm2
}
雖然我的匯編代碼有效,但速度很慢。 我怎樣才能加快速度?
這個有很多需要改進的地方。 以下是一些要點:
MSVC 風格的內聯匯編可能很容易編程,但它也強制所有變量存在於 memory 中。 每次讀取或分配一個變量時,都會執行一次慢速 memory 訪問。 這對性能有很大的影響。
相反,將整個 function 寫在單獨的匯編文件中。 如果這是不可能的,至少開始你的匯編代碼,將所有變量加載到寄存器中,然后完全在這些寄存器上進行計算,並通過將寄存器寫回變量來結束匯編部分。 這樣,無用數據移動的數量就被最小化了。
當你這樣做時,在匯編中實現for
循環本身,這樣你就不必在每次迭代中寫出然后讀回所有變量,而只需為整個循環寫一次。
如前所述,所有這些fld
和fstp
指令都需要時間。 將數字保存在寄存器中,這樣您就不必不斷地重新加載它們。 此外,如果這不可能,至少將加載和存儲合並到以下說明中。 例如,而不是
__asm fld x
__asm faddp st(1), st(0)
你可以做
__asm fadd x
但最好將所有內容都保存在寄存器中。 例如,您可以輕松地擺脫c
變量,只需將其保留在堆棧中即可。
您的代碼計算a*a
和b*b
兩次:一次在上一次迭代中計算norm2
一次在下一次迭代中計算c
。 計算一次這些乘積並保留它們以節省兩次乘法。
回想一下 2x = x + x 並用加法代替昂貴的常數負載和乘法。
還記得 a² - b² = (a + b)(a - b) 用加法代替乘法。 請注意,這可能會更改舍入,並且與“不要執行兩次工作”的建議不兼容。 但也許它可以用於初始迭代。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.