如果我有两个 32 位值 X 和 Y,如何有效地将它们的位按照 xyxyxyxy 的顺序交错为一个 64 位值 Z...(Z 是 Z 顺序曲线上的一个位置。)
我可以迭代 X 和 Y 中的每个位,同时设置 Z 中的位。这看起来效率很低。
是否有一种捷径可以将两个值中的位交错为一个大值,而这需要不到一百条 CPU 指令?
如果我有两个 32 位值 X 和 Y,如何有效地将它们的位按照 xyxyxyxy 的顺序交错为一个 64 位值 Z...(Z 是 Z 顺序曲线上的一个位置。)
我可以迭代 X 和 Y 中的每个位,同时设置 Z 中的位。这看起来效率很低。
是否有一种捷径可以将两个值中的位交错为一个大值,而这需要不到一百条 CPU 指令?
此 C++ 答案也适用于 C:https ://stackoverflow.com/a/39490836/11993121
答案概括了原理,但没有写出完整的解决方案。一个工作实现如下:
测试示例:
无论如何,这是一个手动矢量化版本,它使用 SSE 内在函数同时对 x 和 y 进行位运算。然而,gcc 编译器对我来说太聪明了,它以某种方式更有效地优化了尼尔森的标量函数。
不管怎样,这可行,但可能只对那些可能想要调整它以使用更宽的向量宽度来同时交错一对以上 uint32_ts 的人有用。
你是否必须经常这样做,比如你有很多 X 与很多 Y 交错吗?如果没有,下面的内容仅供参考。
如果是,则存在“正交”方法。假设您有 128 个 X 与 128 个 Y 交错。从 32 128 位向量开始,将 X[0] 的位放在 32 个向量的第 0 位中。将 X[1] 的位放入向量的第 1 位,依此类推。对另一组 32 128 位向量中的 Y 值执行相同的操作。这有效地将值中的位转置为一组向量中的位列。然后,交错它们只是在从两组向量重新构建 64 位值时交替索引 X 向量和 Y 向量的情况。
诚然,仅对于交织而言,将整数转置为向量数组中的位列可能效率低下。但是,如果稍后要完成更多位操作,则可以减少大量工作来重新索引数组中的向量。一些 SIMD 单元(如 Altivec)具有可以帮助进行转置的向量指令。
按位逻辑运算(例如 AND)仍然可以完成(一次 1 位,但一次 128 个不同的值),但没有速度优势。然而,在已经转置的表示中也没有缺点。如果处理是一系列位操作和按位操作,则位操作实际上是“自由的”,这就是可以节省时间的地方。