2

对于 32 位整数,将其分成 32 个连续整数箱,这样每个连续箱中的整数数量是两倍。第一个 bin 包含 0,第二个 bin 包含 0..1,依此类推,直到 0..2^31-1。

给定一个 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) 存储在 bin 0 中,将 0 存储在 bin 31 中,但这没关系):

// 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,但这并不重要。

整数和 bins/items 之间的映射可以是完全任意的,只要在每个连续的 bin 中结束两倍的连续整数并且 bin 中的整数总数为 2^32-1。你能想出一种更有效的算法来在 i7 上对 32 个整数进行分箱吗?请记住,i7 是超标量,因此任何不相互依赖的操作都可以并行执行,直至每种指令类型的吞吐量。

4

1 回答 1

1

您可以通过尝试在计数零之前先对数据进行排序来改进您的算法。

例如,首先将其与 2^31 进行比较,如果更大,则将其放入该 bin 中,否则继续计算尾随零。有了这个,你现在有一半的数据集在 2 条指令中放入它的 bin 中……可能是两个周期。另一半需要更长的时间,但最终结果会有所改善。如果考虑到这一点,您可能会进一步优化。

我想这也取决于分支预测的效率。

于 2013-05-14T03:58:14.850 回答