簡體   English   中英

如何將32個字符(0/1)的序列轉換為32位(uint32_t)?

[英]How to convert a sequence of 32 char (0/1) to 32 bits (uint32_t)?

我有一個從文件讀取的char數組(通常長數千個字節),它們都由0和1(不是'0'和'1'組成,在這種情況下,我可以使用strtoul )。 我想將它們打包為單個位,從而將每個32個字符轉換為單個uint32_t。 我應該用32個部分編寫一個移位操作,還是有一個更明智的方法?

out[i/32] = 
    data[i] << 31 |
    data[i+1] << 30 |
    data[i+2] << 29 |
    data[i+3] << 28 |
    data[i+4] << 27 |
    data[i+5] << 26 |
    data[i+6] << 25 |
    data[i+7] << 24 |
    data[i+8] << 23 |
    data[i+9] << 22 |
    data[i+10] << 21 |
    data[i+11] << 20 |
    data[i+12] << 19 |
    data[i+13] << 18 |
    data[i+14] << 17 |
    data[i+15] << 16 |
    data[i+16] << 15 |
    data[i+17] << 14 |
    data[i+18] << 13 |
    data[i+19] << 12 |
    data[i+20] << 11 |
    data[i+21] << 10 |
    data[i+22] << 9 |
    data[i+23] << 8 |
    data[i+24] << 7 |
    data[i+25] << 6 |
    data[i+26] << 5 |
    data[i+27] << 4 |
    data[i+28] << 3 |
    data[i+29] << 2 |
    data[i+30] << 1 |
    data[i+31];

如果這種怪異的移位是運行時最快的,那么我就必須堅持下去。

限於x86平台,可以使用PEXT指令。 它是新處理器上BMI2指令集擴展的一部分。

連續使用32位指令,然后通過移位將結果合並為一個值。

這可能是在Intel處理器上的最佳方法,但是缺點是該指令在AMD Ryzen上速度較慢。

如果您不需要輸出位以與輸入字節完全相同的順序出現,但是如果可以以特定的方式對它們進行“交織”,那么一種快速且可移植的方法是占用8個塊8個字節(總共64個字節),並將所有LSB合並為一個8字節的值。

就像是:

uint32_t extract_lsbs2(uint8_t (&input)[32]) {
  uint32_t t0, t1, t2, t3, t4, t5, t6, t7;
  memcpy(&t0, input + 0 * 4, 4);
  memcpy(&t1, input + 1 * 4, 4);
  memcpy(&t2, input + 2 * 4, 4);
  memcpy(&t3, input + 3 * 4, 4);
  memcpy(&t4, input + 4 * 4, 4);
  memcpy(&t5, input + 5 * 4, 4);
  memcpy(&t6, input + 6 * 4, 4);
  memcpy(&t7, input + 7 * 4, 4);

  return 
    (t0 << 0) |
    (t1 << 1) |
    (t2 << 2) |
    (t3 << 3) |
    (t4 << 4) |
    (t5 << 5) |
    (t6 << 6) |
    (t7 << 7);
}

這會在大多數編譯器上生成“不可怕,不完美”的代碼。

如果使用uint64_t而不是uint32_t則在64位平台上,速度通常會快兩倍(假設要轉換的總字節數超過32個)。

使用SIMD,您可以像兩個指令(對於AVX2,但可以使用任何x86 SIMD ISA一樣)輕松地將整個操作向量化:compare和pmovmskb

移位是解決此問題的最簡單方法。 最好編寫反映您實際操作的代碼,而不是嘗試進行微優化。

所以你想要這樣的東西:

char bits[32];
// populate bits
uint32_t value = 0;
for (int i=0; i<32; i++) {
    value |= (uint32_t)(bits[i] & 1) << i;
}

暫無
暫無

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

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