比較快的方式有一定是一個更快,更好的方式來交換的16位字字節那麼這:交換字節序在C#與16個字
public static void Swap(byte[] data)
{
for (int i = 0; i < data.Length; i += 2)
{
byte b = data[i];
data[i] = data[i + 1];
data[i + 1] = b;
}
}
有沒有人有一個想法?
比較快的方式有一定是一個更快,更好的方式來交換的16位字字節那麼這:交換字節序在C#與16個字
public static void Swap(byte[] data)
{
for (int i = 0; i < data.Length; i += 2)
{
byte b = data[i];
data[i] = data[i + 1];
data[i + 1] = b;
}
}
有沒有人有一個想法?
在試圖申請Uberhacker獎時,我提交了以下內容。對於我的測試中,我使用的8,192字節的源陣列,並呼籲SwapX2
10萬次:
public static unsafe void SwapX2(Byte[] source)
{
fixed (Byte* pSource = &source[0])
{
Byte* bp = pSource;
Byte* bp_stop = bp + source.Length;
while (bp < bp_stop)
{
*(UInt16*)bp = (UInt16)(*bp << 8 | *(bp + 1));
bp += 2;
}
}
}
我的基準測試表明,該版本比原來的問題提交的代碼快了1.8倍。
那麼,你可以使用XOR swapping trick來避免中間字節。然而,它不會更快,如果IL完全一樣,我也不會感到驚訝。
for (int i = 0; i < data.Length; i += 2)
{
data[i] ^= data[i + 1];
data[i + 1] ^= data[i];
data[i] ^= data[i + 1];
}
好的。但是這樣看起來有點令人困惑。而維基百科聲稱「在現代(桌面)CPU上,XOR技術比使用臨時變量進行交換要慢得多。」好吧。感謝性感的解決方案。 – initialZero 2009-10-23 01:23:10
是的,我認爲我們可以說的就是它很整潔。我只是對它進行了基準測試,得到的結果與您的解決方案相同。所以,其中一種形式可能會優化到另一種形式。 – 2009-10-23 01:25:04
這種方式似乎是在原來的問題略高於方法快:
private static byte[] _temp = new byte[0];
public static void Swap(byte[] data)
{
if (data.Length > _temp.Length)
{
_temp = new byte[data.Length];
}
Buffer.BlockCopy(data, 1, _temp, 0, data.Length - 1);
for (int i = 0; i < data.Length; i += 2)
{
_temp[i + 1] = data[i];
}
Buffer.BlockCopy(_temp, 0, data, 0, data.Length);
}
我的基準假設方法反覆調用,從而使_temp
數組的大小調整爲不一個因素。此方法依賴於一半的字節交換可以通過初始的Buffer.BlockCopy(...)
調用(源位置偏移1)完成。
請自行評估一下,以防萬一我完全失去理智。在我的測試中,這種方法大約需要原始方法的70%(我修改後聲明byte b
以外的循環)。
Uberhacker獎!我希望有一個大的溫度調整比一個就地交換更昂貴。這只是一個內存泄漏,只是臨時坐着。 – initialZero 2009-10-23 02:07:59
@initialZero:在我的基準測試中,我最初將其尺寸與我的測試陣列大小相同,因此在那裏沒有任何成本。像這樣的溫度變量一般以犧牲內存爲代價來購買速度,這可能或可能不是一個好的決定。 – MusiGenesis 2009-10-23 02:12:09
@MusiGenesis你可以隨時在交換結束時設置temp = null來修復泄漏。這絕對是一個很酷的解決方案。謝謝。 – initialZero 2009-10-23 02:17:17
我一直很喜歡這樣的:
public static Int64 SwapByteOrder(Int64 value)
{
var uvalue = (UInt64)value;
UInt64 swapped =
((0x00000000000000FF) & (uvalue >> 56)
| (0x000000000000FF00) & (uvalue >> 40)
| (0x0000000000FF0000) & (uvalue >> 24)
| (0x00000000FF000000) & (uvalue >> 8)
| (0x000000FF00000000) & (uvalue << 8)
| (0x0000FF0000000000) & (uvalue << 24)
| (0x00FF000000000000) & (uvalue << 40)
| (0xFF00000000000000) & (uvalue << 56));
return (Int64)swapped;
}
我相信你會發現這是最快的方法還有一個是相當可讀的,安全的。顯然,這適用於64位值,但相同的技術可用於32位或16位。
你的解決方案似乎是一個很好的解決方案,只是如果你的數據是奇數長度的,你的代碼將拋出數組超出限制的異常。 – NawaMan 2009-10-23 00:53:15
如果他交換16位字,那麼他的數據永遠不會有奇數長度。 – 2009-10-23 00:59:32
是的,這將是一個私人的方法,它將保證有16位字。 – initialZero 2009-10-23 01:02:34