【发布时间】:2019-01-29 05:43:00
【问题描述】:
我有一个位矩阵(大小为 6x6、7x7 或 8x8)存储在一个 64 位整数中。
我正在寻找将这些矩阵旋转 90、180、270 度的 c++ 代码,以及用于移动(水平和垂直)和镜像这些矩阵的 c++ 代码。输出必须再次为 64 位整数。
使用一些高级 CPU 指令集以及使用哈希表或类似技术可能没问题 - 速度是最重要的,并且 RAM 可用。我将在 AMD Ryzen 7 1700 八核 PC 上运行它。我不熟悉这些指令集(例如 SSE2),但我在 C++ 中使用过 __popcnt64() 和 _rotl64()。
谁能指出我正确的方向?我已经为 7x7 矩阵编写了自己的代码,但我现在需要 6x6 和 8x8 的代码,并且想知道是否有人发表过关于这个主题的任何文章,也许以比我的 7x7 方法更聪明的方式。
顺便说一下,6x6 和 7x7 矩阵分别存储在最低有效位 36 和 49 位中,其余位设置为零。
【问题讨论】:
-
这有被关闭作为图书馆或类似请求的危险。见How to Ask。只是问最好的方法是什么。 google 是您询问是否只想找到已经存在的实现的地方。 Stack Overflow 是您询问实际最佳/最有效的实现方式的地方。
-
在 6x6 矩阵或其次要对角线周围将行向左旋转 90°,使用
mat*0x810204081 & 0x820820820像 what I used for 8x8 -
您是否考虑将 7x7 位存储为
0, 0, ..., 0, 0, b48, ...b42,...,0, b20, ...,b14, 0, b13, ..., b7, 0, b6, ... , b0,即在其间填充 7 次 1 个零位和最后 8 个额外的零位。然后,您也可以将互联网上所有现有的 8x8 代码用于 7x7 案例。最后只需要一个额外的位移,就可以将位放在正确的位置。 -
@wim:我也在想同样的事情。 6x6 和 7x7 的最佳选择是解包到 8 位的行步长,以设置 SIMD 字节操作。例如
_mm_shuffle_epi8用于 180 度旋转或镜像,用于每个字节内的位反转(使用 4 位查找表)+ 右移 1 或 2。标量bswap+ shift 可以字节反转,所以你可能想将这些转变结合在一起。在没有 pext/pdep 的情况下解压成那种格式很糟糕。 godbolt.org/z/6cUhIL 标量和/andn(BMI1) + ADD 或 LEA 的设计说明。 (使用x+x = x<<1屏蔽移动一些位,但x+ (x&mask)。
标签: c++ bit-manipulation x86-64 avx micro-optimization