测试在二进制表示中设置了哪些 trit

Testing which trits are set in a binary representation

提问人:Octavianus 提问时间:11/19/2020 最后编辑:Octavianus 更新时间:11/21/2020 访问量:233

问:

我有一个问题,我有八个元素可以包含 0、1 或 2。我可以轻松地用 16 位表示这一点,但出于 SIMD 效率的原因,我需要它占用 13 位(它不是通道中唯一存在的东西)。

幸运的是,,和 ,所以我想要的状态可以适应。然而,这就是事情变得有趣的地方。天真地,我只是通过计算三元数字状态来表示这些状态。例如,为了表示 tritmask(我将以此为例),我可以只写 .2^13==81923^8==65610t122110120t12211012 = 2*3^0+1*3^1+0*3^2+1*3^3+1*3^4+2*3^5+2*3^6+1*3^7 = 4244 = 0b1000010010100

我有一组需要支持的操作:

  • 修改 trits。这在默认表示中很容易。例如,如果我有 tritmask,并且我希望将 a 放在保持零的位置,我可以简单地添加 .(请注意,转换为 tritspace 很容易,因为我只有 8 个 trit,所以我可以将基本功率存储在寄存器中并使用 pshufw 对其进行索引)。0t1221101220t200=18
  • 查找设置为特定值的所有元素。例如,给定 tritmask ,我希望能够提取 的位掩码 ,即 、 、 和 ,即 。我还没有弄清楚该怎么做,这就是我想要的帮助。如何在适合 x86 SIMD 的少量操作中执行此操作?0t1221101200b0000010010b1001101020b01100001

谢谢!

编辑 11/18/20:举一个我认为太慢的方法的例子:我们可以迭代地找到值 mod 3 并除以 3 以从表示的最不重要的一端拉出 trits,然后以这种方式组装蒙版。C++ 代码段:

uint32_t trits = <something>;
uint8_t mask0 = 0, mask1 = 0, mask2 = 0;
for (uint8_t shift = 0; shift < 8; ++shift) {
  const uint32_t remainder = trits % 3;
  mask0 |= (!remainder) << shift;
  mask1 |= (remainder == 1) << shift;
  mask2 |= (remainder == 2) << shift;
  trits /= 3;
}

当实际用 SIMD 语言编写它时,我们将使用标准的乘移技巧来除以常数。但是你可以看到它在trit的数量上是线性的,并且每次迭代都有很多操作。我们可以对此进行一些编码,但我认为这从根本上是错误的方法。理想情况下,应该可以为每个 trit 并行执行某些操作......但我没有看到。

编辑 11 年 20 月 20 日:我半心半意地将 Aha 应用于这个问题,但没有成功。也许要解决的一个有趣的子问题是 - 在与上述相同的约束下,是否有一小段按位运算充当“三元按位 AND”?也就是说,在 tritspace 中比较两个编码数字并返回一个位掩码,当相应的 trit 相等且不然为零时,该位掩码为 1?这将是一个原始的,我们可以从中构建所需的操作。我们在三分空间中有左移和右移(只需乘以或除以 3);我们有一个 +/- 一个值。因此,我们缺少的是测试 trits 是否为特定值的能力......

C++ 数学 位操作 SSE 三元

评论

1赞 Peter Cordes 11/19/2020
如果你的数字是二进制的,但需要以 3 为基数的数字,AFAIK 没有比重复除法和模数更有效的方法了(当然,使用乘法逆)。与需要二进制整数的十进制数字时相同。你可能最好使用 BCD,呃 BCT 我猜你会这样称呼它,每个 trit 有 2 位字段,即使这意味着较低的数据密度(比如 2 个向量来保存你的所有数据,或者将 3 位元数据(?)保存在一个单独的uint8_t数组中,就像结构体样式的数组一样。您可以从该 8 位数组加载并使用 trit 元素排列元数据)pmovzxbw
1赞 Stef 11/19/2020
听起来你必须做出选择:在 16 位上方便地表示,还是在 13 位上压缩表示。现在您要求 13 位表示,但没有不便!
2赞 phuclv 11/19/2020
您可以将 5 个 trit 打包成 8 位 (3^5 = 243 < 256)。但是您仍然需要使用除法来提取 trits。您可以使用比uint16_t three2four[6561]
3赞 Mark Dickinson 11/19/2020
这篇论文可能很有趣,尽管他们关注的是值集为 {-1, 0, 1} 而不是 {0, 1, 2} 的 trit。
1赞 chtz 11/19/2020
如果你想对你的算法进行 SIMDize,你可以将输入广播到 8 个通道,然后将元素除以并计算其中的余数 mod 3(当然,所有这些都使用逆乘法)——不过,可能还有更优雅的解决方案。k3^k

答: 暂无答案