2009-08-31 62 views
5

我在C#中有一個uint類型的數組,在檢查程序是否在小端機上工作後,我想將數據轉換爲大端類型。由於數據量可能會變得非常大,但總是偶數,所以我在考慮將兩種uint類型視爲ulong類型,以獲得更好的性能並在ASM中對其進行編程,所以我正在尋找一種非常快速(儘可能最快)彙編器算法來轉換big-endian中的little-endian。ASM中的快速小端到大端轉換

+0

爲我定義'非常大'? – 2009-08-31 18:33:36

+0

至少1'000'000點(可能少一點,但可以變大) – 2009-08-31 18:43:22

回答

6

對於大量的數據,bswap指令(在Visual C++中提供的_byteswap_ushort, _byteswap_ulong, and _byteswap_uint64內在函數)是要走的路。這甚至會超越手寫大會。這些都不是純C#不提供的P/Invoke,所以:

  1. 只有當你有數據的大量以字節交換使用。
  2. 您應該認真考慮在託管C++中編寫最低級別的應用程序I/O,以便在將數據引入托管數組之前進行交換。您必須編寫一個C++庫,因此沒有太多可能丟失,並且避免了在大型數據集上運行的低複雜度算法的所有與P/Invoke相關的性能問題。

PS:很多人都不知道字節交換內在函數。它們的性能令人驚訝,對於浮點數據來說更是如此,因爲它將它們作爲整數處理。如果沒有人爲每個單字節交換用例編寫寄存器加載代碼,就沒有辦法打敗它,如果你嘗試這樣做,你可能會在優化器中產生比以往任何時候都大的衝擊。

1

我想考慮兩個UINT 類型爲ULONG型

好,這也將交換兩個UINT值,這可能是不希望...

你可以嘗試一些不安全模式下的C#代碼,這可能實際上表現不錯。像:

public static unsafe void SwapInts(uint[] data) { 
    int cnt = data.Length; 
    fixed (uint* d = data) { 
     byte* p = (byte*)d; 
     while (cnt-- > 0) { 
     byte a = *p; 
     p++; 
     byte b = *p; 
     *p = *(p + 1); 
     p++; 
     *p = b; 
     p++; 
     *(p - 3) = *p; 
     *p = a; 
     p++; 
     } 
    } 
} 

在我的計算機上,吞吐量大約是每秒2 GB。

2

你可能只想重新思考問題,這不應該是一個瓶頸。採用天真的算法(用CLI組件編寫,只是爲了好玩)。讓我們假設我們所要的號碼是本地號碼0

LDLOC 0 
SHL 24 
LDLOC 0 
LDC.i4 0x0000ff00 
SHL 8 
OR 
LDLOC 0 
LDC.i4 0x00ff0000 
SHL.UN 8 
OR 
LDLOC 0 
SHL.UN 24 
OR 

在大多數的13%數量(x86)的彙編指令(最有可能的解釋會更聰明,通過巧妙的寄存器)。它並沒有比這更天真。

現在,比較,爲的

  • 的成本(包括任何外設您正在使用入門加載的數據!)
  • Maniuplation數據(做比較,例如)
  • 輸出結果(不管它是什麼)

如果每個數字13只說明是你的執行時間的顯著大塊,那麼你正在做一個非常高性能的任務,應該有正確的格式您的輸入!您也可能不會使用託管語言,因爲您需要對數據緩衝區的更多控制,而不是什麼,也不需要額外的數組邊界檢查。

如果該數據陣列遇到網絡,我認爲從套接字管理的成本要比從單純的字節順序翻轉出來的成本要高得多,如果它從磁盤上來看,請考慮在執行該程序之前預翻轉。