2013-05-14 99 views
2

對於32位整數,將其分成32個連續整數的整數,這樣每個整數的整數連續的箱子。第一個bin包含0,第二個0..1等等直到0..2^31-1。將32位整數映射爲32個bin,每個bin具有1,2,4..2^31個連續整數

最快的算法我能想出,給定一個32位的整數i,是對一個I7 5個週期(位掃描3個循環):

// bin is the number of leading zeroes, and then we clear the msb to get item 
bin_index = bsr(i) 
item = i^(1 << bin_index) 

或等同(以及它存儲項0 ..2 ^(32-1)在0倉和倉31 0,但是這並不重要):

// bin is the number of trailing zeroes, and then we shift down by that many bits + 1 
bin_index = bsf(i) 
item = i >> (bin_index + 1) 

在每種情況下的bin索引被編碼爲主導數量/尾隨零個比特,用1將它們與項目編號分開。您可以對前導或尾隨進行相同的處理,並使用零來分隔它們。兩者都不適用於i = 0,但這並不重要。

只要連續兩個整數在每個連續的bin中結束並且整個bin中的整數總和爲2^32-1,整數和bin/items之間的映射就可以是完全任意的。你能想到一個更有效的算法來在i7上分割32個整數嗎?請記住,i7是超標量的,因此任何不依賴於彼此的操作都可以並行執行,直到每種指令類型的吞吐量。

+0

既然你提到i7,你可以嘗試將整數轉換爲浮點數並提取指數以得到一個有偏見的bin_index。零需要特別關注。 – 2013-05-14 04:14:43

+0

看起來它不是一個勝利,http://www.agner.org/optimize/instruction_tables.pdf把操作放在一個i7上3 + 2個週期(不確定這裏的+2是什麼意思,但它與3是無關的足以殺死任何可能的收益 – Eloff 2013-05-14 11:33:06

+0

我更喜歡思考SSE單元並且至少並行執行4個操作 – 2013-05-14 13:40:08

回答

1

通過在計數零之前嘗試對數據進行排序,可以改進算法。

例如,首先將其與2^31進行比較,如果其較大者將其放入該垃圾箱,則繼續計算尾部零。有了這個,你現在有一半的數據集放入它的bin在2條指令中......可能是兩個週期。另一半需要更長的時間,但最終的結果將是一個改進。如果想到的話,你可能會進一步優化這條線。

我想這也將取決於分支預測的效率。

+0

對於一個有序數組(可能是2),期望的速度是每個數字4個週期,但是我懷疑排序可以在每個元素的1-3個週期內完成,以達到平衡點 – 2013-05-14 06:24:57

+0

這是一個有趣的想法,但我無法對數據集進行排序,但我知道大部分時間值都小於2^31。但是在2條指令中的一半數據集和一半分支未命中的數據集絕對不是勝利((7 + 2 + brnach miss)/ 2> 4.5但是有一個變體解決方案將倉位0和1結合在一起(其他倉庫保持不變)。然後我會在2條指令中使用3/4的數據集 - 一個可預測的分支t變成(7 + 2 +分支未命中)/ 4> 2.25。如果我們在一個隨機pdf上在線找到的i7上的分支丟失取15個週期的值,它將是(7 + 2 + 15)/ 4 = 6。仍然是一個損失:( – Eloff 2013-05-14 11:19:31