簡體   English   中英

將16位整數哈希有效地哈希到256位空間

[英]Hash 16-bit integer to a 256-bit space efficiently

聽起來越來越很奇怪,但這就是我想要做的。 我想采用16位整數的整個序列,並對每個哈希進行哈希處理,以使其均勻地映射到256位空間。

原因是我試圖將16位數字空間的一部分放入256位Bloom過濾器中,以進行快速成員資格測試。

我可以在每個整數上使用一些眾所周知的哈希函數,但是我正在尋找一種非常高效的實現(只需幾條指令),以便在GPU着色器程序中很好地運行。 我感覺這樣的事實:已知哈希輸入只有16位,可以以某種方式通知哈希函數,但是我看不到解決方案。

有任何想法嗎?


EDITS

根據答復,我的原始問題令人困惑。 對於那個很抱歉。 我將嘗試使用更具體的示例來重述它:

我有一個來自集合S的n個數字的子集S1,其范圍為(0,2 ^ 16-1)。 我需要用一個由單個哈希函數構造的256位Bloom過濾器來表示此子集S1。 使用布隆過濾器的原因是出於空間考慮。 我選擇了一個256位的布隆過濾器,因為它符合我的空間要求,並且誤報的可能性很低。 我正在尋找一個非常簡單的哈希函數,該函數可以從集合S中獲取一個數字,並以256位表示該數字,從而使每個位具有大約為1或0的概率。

哈希函數要求簡單的原因是,此哈希函數將不得不在每個像素上運行數千次,因此在任何我可以修整指令的地方都是一個勝利。

我相信所提出的問題有些混亂。 我將首先嘗試清除我在上面注意到的所有不一致之處。

OP最初表示,他正在嘗試將較小的空間映射到較大的空間。 如果確實如此,則不需要使用布隆過濾器算法。 相反,如上面的注釋中所建議的,標識功能是設置和測試每個位所必需的唯一“哈希”功能。 但是,我斷言這不是OP真正想要的。 如果是這樣,那么OP必須在內存中存儲2^256位(基於問題的表達方式),以使16位整數(即2^16 )的空間小於其設置的大小; 這將占用不合理的內存量,並且不太可能是這種情況。

因此,我假設問題約束如下:我們有一個256位的位向量 ,我們要在其中映射16位整數的空間。 也就是說,我們有256位可用於映射2^16可能的不同整數。 因此,我們實際上並沒有映射到更大的空間,而是映射到了更小的空間。 類似地,確實出現了(再次如前面的注釋中先前指出的那樣)OP正在請求單個哈希函數。 在這種情況下,對於布隆過濾器的工作原理存在明顯的誤解。

布隆過濾器通常使用一組獨立於哈希的哈希函數來減少誤報。 無需贅述,布隆過濾器的每個輸入都通過所有n哈希函數運行,然后針對每個函數測試位向量中的所得索引。 如果將所有測試的索引都設置為1 ,則該值可能在集合中(如果所有n散列函數存在適當的沖突或重疊,則會出現誤報)。 此外,如果將任何索引設置為0 ,則該值絕對不在集合中。 考慮到這一點,重要的是要注意完全飽和的布隆過濾器沒有任何好處。 也就是說,對布隆過濾器的每個查詢都將返回該項目在集合中。

哈希函數問題

現在,回到OP的原始問題。 最好使用已知的哈希算法(因為這些算法在數學上很難編寫,並且“滾動自己的算法”通常效果不佳)。 如果您擔心效率低至時鍾周期,請使用適合您的體系結構的匯編語言自己實現算法,以減少每個哈希函數的運行時間。 請記住,從算法上講,哈希函數應在O(1)時間內運行,因此,如果正確實現,則它們不應造成太多開銷。 首先,我建議您考慮修改后的伯恩斯坦哈希。 我在下面針對您的特定情況編寫了一個版本(主要出於示例目的):

unsigned char modified_bernstein(short key)
{
  unsigned ret = key & 0xff;
  ret = 33 *  ret ^ (key >> 8);
  return ret % 256; // Try to do some modulo math to keep it in range
}

我改編的伯恩斯坦方法通常根據輸入的字節數運行。 由於short類型是2個字節或16-bits ,因此我從算法中刪除了所有變量和循環,並簡單地執行了一些小操作以獲取每個字節。 最后, unsigned char可以返回[0,256)范圍內的值,這迫使哈希函數返回位向量中的有效索引。

如果你乘(使用uint32_t )由總理(或與此有關的任何奇數)一個16位的值, p 2 ^ 31和2 ^ 32之間,那么“可能”抹黑結果整個32位空間相當均勻。 然后,您可能想要添加另一個素數,以防止0映射到0 (您希望每一位具有相等的概率為01 ,因此2 ^ 256中只有一個輸入值應該輸出全零,並且由於存在僅2 ^ 16個輸入,這意味着您不希望它們輸出全零)。

因此,這就是通過一次操作將16位擴展為32位的方法(以及加載常量所需的任何指令)。 使用四個不同的值p1 ... p4獲得256位,並使用不同的p值運行一些測試以找到好的值(即,在給定的p大小的情況下,產生的誤報不會比您對Bloom過濾器的期望多得多)設置您要進行編碼並假設使用理想的哈希函數)。 例如,我很確定-1是一個錯誤的p值。

但是,無論這些值多么好,您都會看到一些相關性:例如,正如我在上面所描述的那樣,所有4個單獨值的最低位都相等,這是一個非常嚴重的依賴性。 因此,您可能希望進行更多“混合”操作。 例如,您可能會說最終輸出的每個字節應該是我所描述的兩個字節的XOR(而不是兩個最小公稱字節!),只是為了擺脫簡單的算術關系。

但是,除非我誤解了這個問題,否則布魯姆過濾器通常不會工作 通常,您希望您的哈希為每個輸入生成確切固定數量的設置位,並且所有計算誤報率的算法都依賴於此。 這就是為什么對於256位大小的Bloom過濾器,您通常會有k 8位哈希,而不是一個256位哈希。 k通常小於以位為單位的過濾器大小的一半(最佳值是過濾器中每個值的位數,乘以ln(2) ,約為0.7)。 因此,通常您希望每個位為1的概率高達0.5。

原因是,一旦您對至少4個此類256位值進行“或”運算,就幾乎設置了過濾器中的所有位(其中16位中的15位)。 因此,您已經發現了很多誤報。

但是,如果您已經完成數學運算,並且對單個散列函數感到滿意,那么該哈希函數會產生可變數量的平均置位位數,那么就足夠了。 還是數字256的重復出現只是一個巧合,因為對於您選擇的設置大小, k恰好是32,並且您實際上將256位哈希用作32個8位哈希?

[編輯:您的評論澄清了這一點,但是無論如何k都不會太高,以至於您總共需要256位哈希。 顯然,在這種情況下,使用具有每個值超過16位(即少於16個值)的Bloom過濾器是沒有意義的,因為使用相同數量的空間,您可以只列出這些值,並且誤報率為0。每個值具有16位的filter的假陽性率大約為2200中的1。即使在那里,最優k也只有23,也就是說,您應該為集合中的每個值在filter中設置23位。 如果您希望這些集合大於16個值,那么您希望為每個元素設置更少的位,您將獲得更高的誤報率。]

暫無
暫無

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

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