2012-03-05 54 views
1

我想對在極大位向量(即100,000位)中設置的位進行計數。在C計數位中旋轉的位

我現在正在做的是使用指向char(即char * cPtr)的指針指向位數組的開始位置。然後我:

1. look at each element of the array (i.e. cPtr[x]), 
2. convert it to an integer (i.e. (int) cPtr[x]) 
3. use a 256 element look-up table to see how many bits are set in the given byte (i.e. cPtr[x]). 

它發生,我認爲如果我使用short int類型的指針來代替(即短整型*特徵碼),那麼我只需要一半的樣子起坐,但有65534元look-這個表格在內存使用上會有自己的成本。

我在想什麼是每次檢查的最佳位數。另外,如果這個數字不是某種預設類型的大小,我該如何走下我的位向量,並將指針設置爲位數組起始位置之後的任意位數的ANY

我知道還有其他的方法來計數位,但現在我想確定我可以優化這種方法之前進行比較其他方法。

+0

這可能是值得看看這個網站:http://graphics.stanford.edu/~seander/bithacks.html – caspase 2012-03-05 21:41:10

+0

測試是唯一的方法來找出什麼給你的特定機器的性能。由於位移的開銷,幾乎可以肯定地發現8的倍數對你來說效率最高,並且由於緩存局部性,可能正好是8位。 – 2012-03-05 22:11:02

回答

1

我想知道什麼是位的最佳數量每次

找出的唯一方法是進行測試檢查。每次請參閱this question for a discussion of the fastest way to count 32 bits

此外,如果該號碼是不是有些預設類型的大小,我怎樣才能 走我的位矢量並設置一個指針是比特的任意數目0​​過去的比特數組的起始位置。

您不能將指針設置爲任意位。大多數機器都有字節尋址,有些只能尋址字。

可以構建起一個任意有點像這麼一句話:

long wordAtBit(int32_t* array, size_t bit) 
{ 
    size_t idx = bit>>5; 
    long word = array[idx] >> (bit&31); 
    return word | (array[idx+1] << (32 - (bit&31)); 
} 
+0

謝謝 - 我忘記了字節尋址。但它非常有意義。現在我只需要比較我現有的兩種方法,然後嘗試瞭解您提供鏈接的海明重量方法。 – user1245262 2012-03-05 22:32:10

2

可以使用位運算算吧:

char c = cPtr[x]; 
int num = ((c & 0x01) >> 0) + 
      ((c & 0x02) >> 1) + 
      ((c & 0x04) >> 2) + 
      ((c & 0x08) >> 3) + 
      ((c & 0x10) >> 4) + 
      ((c & 0x20) >> 5) + 
      ((c & 0x40) >> 6) + 
      ((c & 0x80) >> 7); 

這似乎有點長,但它並不需要訪問很多的時間來記憶,所以畢竟這似乎是相當便宜我。

你甚至可以通過每次讀取一個int來降低成本,但是你可能需要解決對齊問題。

+0

我不確定。好像要計算一個字節中的設置位數,我已經交換了8位移位和7位移位的1個存儲器訪問(即查表)。我錯過了什麼嗎? – user1245262 2012-03-05 21:52:18

+0

我認爲在大多數架構中位操作會更快,但我沒有測量它。 – MByD 2012-03-05 21:55:55

1

這應該是相當快(從Wikipedia拍攝):

static unsigned char wordbits[65536] = { bitcounts of ints between 0 and 65535 }; 
static int popcount(uint32 i) 
{ 
    return (wordbits[i&0xFFFF] + wordbits[i>>16]); 
} 

通過這種方式,你可以檢查每次迭代32位。

0

我有點遲到了,但也有迄今已提出更快的方法比那些。原因在於許多現代體系結構提供硬件指令來以各種方式(前導零,前導,尾隨零或1,計數設置爲1的位數等)計數位數。計數設置爲1的位數稱爲漢明權重,通常也稱爲總體計數,或者只是popcount。

事實上,x86 CPUs有一個POPCNT指令作爲SSE4.2指令集的一部分。英特爾最新的最新CPU架構(綽號Haswell)爲BMI1和BMI2擴展提供了更多的位操作硬件支持 - 也許還有別的用處!