2011-09-08 46 views
8

我需要在複製到另一個陣列期間有效地交換數組的字節順序。複製期間的字節交換

源數組是特定類型的; char,short或int,因此所需的字節交換是明確的,並且將根據該類型進行。

我的計劃是使用多遍逐字節拷貝(簡稱爲2,簡寫爲int,...)來完成此操作。但是,是否有任何預先存在的「memcpy_swap_16/32/64」函數或庫?也許在用於BGR/RGB圖像處理的圖像處理中。

編輯

我知道如何交換個體值的字節,這是沒有問題的。我想在的副本中執行此過程,我將執行

例如,如果我有一個數組或小端的4字節整數,我可以通過執行4個按字節複製,初始偏移量爲0,1,2和3,步長爲4來進行交換。一種更好的方法,甚至可以單獨讀取每個4字節的整數,並使用字節交換內部函數_byteswap_ushort,_byteswap_ulong和_byteswap_uint64將會更快。但我懷疑必須有現有的功能來完成這種類型的處理。

EDIT 2

剛剛發現這一點,這可能是上證所的有用基礎,但其真正的內存帶寬,可能使得它在浪費時間。

Fast vectorized conversion from RGB to BGRA

回答

1

是的,現有的功能就像問題中鏈接的功能一樣,但不值得費力,因爲數據的大小(在這種情況下)意味着設置開銷太高。相反,最好一次只讀出2,4和8個字節,並使用內部函數和回寫進行交換。

6

Unix系統有一個swab函數,你想要做什麼16位陣列。這可能是優化的,但我不確定。需要注意的是現代的GCC將產生非常高效的代碼,如果你只寫天真字節交換代碼:

uint32_t x, y; 
y = (x<<24) | (x<<8 & 0xff0000) | (x>>8 & 0xff00) | (x>>24); 

即它將使用bswap指令上的i486 +。據推測,這將在一個循環中會給出一個有效的循環太...

編輯:爲了您的複印任務,我會做你的循環如下:

  1. 閱讀從32位值const uint32_t *src
  2. 使用上面的代碼來交換它。
  3. 將32位值寫入uint32_t *dest

嚴格來說,這可能不是便攜式(別名衝突),但只要複製功能是在其自己的翻譯單元,並沒有得到內聯,有很少操心。 忘記我寫的關於別名的東西;如果您將數據交換爲32位值,那麼它幾乎肯定是以32位值開頭的,而不是其他類型的指針,因此沒有問題。

+1

編譯器字節交換內在函數是保證使用正確指令的更好方法。但這不是問題。 – hplbsh

+0

我不確定你爲什麼稱他們爲「更好」。它們特定於特定的編譯器。我給出的代碼將在任何真正困擾優化的編譯器上生成「正確」指令。 –

+0

因爲即使在未優化的調試版本中它也會很快。 – hplbsh

3

在linux中,你應該檢查標題bits/byteswap.h。有一組bswap _ ##形式的宏,其中一些在適當的地方使用匯編指令。

+2

這個頭文件的寫法是一種令人憎惡的東西,他們使用內聯彙編使其「快速」,然後gcc擴展來支持C上的彙編,因爲參數是常量,所以gcc可以摺疊常量。但是 - 如果它不那麼令人傷心,這就是讓它變得有趣的地方 - 如果你只是像我在我的回答中寫的那樣寫出天真的C,gcc就會自己生成相同或更好的asm –

+0

@R。它包含16,32 ,64位實現並正確處理32/64位系統,並使它像'bswap_16(...)'一樣簡單 –

+0

我同意這些函數是有用的我只是聲稱頭是可怕的寫入如果所有的內聯asm並且gcc擴展被剝離出來,生成的代碼將會一樣好或者更好,並且錯誤和不兼容性的可能性幾乎將被消除。此外,清理它將有助於教新手不要練習過早優化... –