最先進的非加密雜湊函式在過去幾年中得到了快速推廣。當我這週搜尋的時候,我很高興的看到新的尖端雜湊函式已經發布即使上次我進行這個方面的搜尋是6個月到1年前的事情了。
非加密雜湊函式將字串作為輸入,通過計算輸出乙個整數。理想的雜湊函式的乙個特性是輸出非常均勻分布在可能的輸出域,特別是當輸入非常相似的時候。不同於加密雜湊函式,這些函式不是為防止攻擊者找出碰撞而設計的。加密雜湊函式有這個特性但是要慢的多: sha-1大約為0.09 bytes/cycle,而最新的非加密雜湊函式的速度大約為3 bytes/cycle。所以在不考慮抵禦攻擊的成本下,非加密雜湊大約要快33倍。非加密雜湊函式用的最多的地方是hash table。
乙個有趣的題外話,現在lua社群上有個關於針對lua的雜湊函式理論上可以被攻擊使得hash table最壞情況下的查詢複雜度降低到o(n) 的事實我們應該做些什麼(如果可以的話)的爭論,如果攻擊者引導你輸入你放入lua hash table的東西,那麼他可以通過dos攻擊你。lua的作者懷疑這種攻擊實施的可行性(以及它的代價是否比其他dos攻擊更小),但是他還是打算在將要使用的雜湊函式的開始時候生成隨機種子。這是乙個有趣的加密替代函式,能夠給你與加密雜湊函式相同的耐碰撞能力(假設你有能夠給你真正隨機位的資訊源),但這將以非重複性輸出為代價。
由於非加密雜湊函式有很多種選擇,並且可供選擇的數目不斷擴大,我想我應該總結以下我對這個領域的了解。
bob jenkins已經在雜湊函式領域工作了將近15年。在2023年他在《 dr. dobbs journal》雜誌上發表了一片關於雜湊函式的文章《a hash function for hash table lookup》,這篇文章自從發表以後現在網上有更多的擴充套件內容。這篇文章中,bob廣泛收錄了很多已有的雜湊函式,這其中也包括了他自己所謂的「lookup2」。隨後在2023年,bob發布了lookup3,由於它即快速(bob自稱,0.5 bytes/cycle)又無嚴重缺陷,在這篇文章中我把它認為是第乙個「現代」雜湊函式。
更多有關bob's雜湊函式的內容請參閱維基百科:jenkins hash function.
2023年,發布了兩個雜湊函式,相對於murmurhash ,它們都進行了改善,這主要應歸功於更高的指令級並行機制。google發布了cityhash(由geoff pike 和jyrki alakuijala編寫),bob jenkins發布了他自己的乙個新雜湊函式spookyhash(這樣命名是因為它是在萬聖節發布的)。它們都擁有2倍於murmurhash的速度,但他們都只使用了64位數學函式而沒有32位版本,並且cityhash的速度取決於crc32 指令,目前為sse 4.2(intel nehalem及以後版本)。spookyhash給出128位輸出,而cityhash有64位,128位以及256位的幾個變種。
從我所了解的情況來看,這篇文章中所提到的所有雜湊函式從統計學角度來看已經足夠好。需要考慮的乙個因素是cityhash/spookyhash的輸出超過了64位,但是對於乙個32位的hash table來說這輸出太多了。其他應用可能會用到128或256位輸出。
如果你用的是32位機器,murmurhash看起來是最明顯的贏家,因為它是唯一乙個快於lookup3的32位原生版本。32位機器很可能可以編譯並執行city和spooky,但我預計它們的執行速度和在64位機器上執行的速度比起來要慢的多,畢竟32位機器需要模擬64位的數**算。
在64位機器上,由於沒有更深層次的基準,也很難說哪種演算法是最好的。比起city我更傾向於spooky,因為city的執行速度需要依賴於crc32指令,畢竟這種環境並不是任何機器上都有的。
另乙個需要考慮的是對齊和非對齊的訪問。murmur雜湊(不像city或者spooky)是乙個僅能進行對齊讀取的變種,因為在很多架構上非對齊的讀取會崩潰或者返回錯誤的資料(非對齊的讀取操作在c中是未定義的行為)。city和spooky都強調使用memcpy()把輸入資料複製到對齊的儲存結構中;spooky使用一次memcpy()操作乙個塊(如果allow_unaligned_reads未定義),city使用一次memcpy()操作乙個整型!在可以處理非對稱讀取的機器上(像x86和x86-64),memcpy將被優化,但我在我的小arm上做了乙個測試,發現如下:
#include #include int32_t read32_unaligned(const void *buf)
編譯這段低效的**(在x86上是乙個單獨的操作):
0: b500 push
2: 2204 movs r2, #4
4: b083 sub sp, #12
6: 4601 mov r1, r0
8: eb0d 0002 add.w r0, sp, r2
c: f7ff fffe bl 0
10: 9801 ldr r0, [sp, #4]
12: b003 add sp, #12
14: bd00 pop
結論是,如果你需要32位或者僅僅是對齊讀取的話,murmur雜湊看起來依舊是最好的選擇。city雜湊和spooky雜湊在x86-64上看起來更快,但我更傾向於認為它們是特定用於那個架構的,因為我不知道是否有其他既是64位又允許非對其讀取的架構。 函式之概覽
函式是程式設計師編寫的,用於實現功能的 塊.資料型別 函式名稱 形式引數說明 資料型別 為返回值即 表示式 的型別 函式名稱是乙個識別符號 形式引數說明是對變數的定義.可以為void,表示無參 函式引數說明 後面必須有一對 中的內容被稱為函式體.函式體中可以有語句序列,可以沒有.return語句必須...
Hash函式和Hash衝突
2.rehash 3.鍊錶法 4.建立公共溢位區 一 簡介 將任意長度的數值以某個對映規則對映為固定長度的數值,這個過程稱為hash,而這個對映規則被稱為hash函式,而對這個key value進行儲存的資料結構被稱為hash表。由於通過key的hash對映直接得到了記憶體位址,所以hash查詢的時...
Python函式簡單概覽
遞迴函式 把生活中的咖啡機看成乙個函式。它們都滿足這三個要點 組織好的 做咖啡的過程已經設定在了機器裡 可重複使用的 做完一次咖啡,下次還能用 用來實現特定功能 用咖啡豆和水做咖啡 寫函式的通用思路 告訴計算機,要定義乙個函式 函式的名字是什麼 這個函式需要輸入什麼引數 引數的處理過程是什麼樣的 把...