簡體   English   中英

將 C++ 代碼轉換為 x87 內聯匯編代碼

[英]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 風格的內聯匯編中編程

MSVC 風格的內聯匯編可能很容易編程,但它也強制所有變量存在於 memory 中。 每次讀取或分配一個變量時,都會執行一次慢速 memory 訪問。 這對性能有很大的影響。

相反,將整個 function 寫在單獨的匯編文件中。 如果這是不可能的,至少開始你的匯編代碼,將所有變量加載到寄存器中,然后完全在這些寄存器上進行計算,並通過將寄存器寫回變量來結束匯編部分。 這樣,無用數據移動的數量就被最小化了。

當你這樣做時,在匯編中實現for循環本身,這樣你就不必在每次迭代中寫出然后讀回所有變量,而只需為整個循環寫一次。

在寄存器中保留盡可能多的值

如前所述,所有這些fldfstp指令都需要時間。 將數字保存在寄存器中,這樣您就不必不斷地重新加載它們。 此外,如果這不可能,至少將加載和存儲合並到以下說明中。 例如,而不是

__asm fld x 
__asm faddp st(1), st(0) 

你可以做

__asm fadd x

但最好將所有內容都保存在寄存器中。 例如,您可以輕松地擺脫c變量,只需將其保留在堆棧中即可。

不要執行兩次工作

您的代碼計算a*ab*b兩次:一次在上一次迭代中計算norm2一次在下一次迭代中計算c 計算一次這些乘積並保留它們以節省兩次乘法。

使用更便宜的指令而不是更昂貴的指令。

回想一下 2x = x + x 並用加法代替昂貴的常數負載和乘法。

還記得 a² - b² = (a + b)(a - b) 用加法代替乘法。 請注意,這可能會更改舍入,並且與“不要執行兩次工作”的建議不兼容。 但也許它可以用於初始迭代。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM