如果我有一个 64 位整数,我将其解释为一个包含 8 个元素的压缩 8 位整数数组。我需要1在处理溢出时从每个压缩整数中减去常量,而一个元素的结果不会影响另一个元素的结果。
我现在有这个代码并且它可以工作,但我需要一个解决方案来并行地减去每个打包的 8 位整数并且不进行内存访问。在 x86 上,我可以使用类似的 SIMD 指令psubb并行减去打包的 8 位整数,但我正在编码的平台不支持 SIMD 指令。(在这种情况下为 RISC-V)。
因此,我正在尝试执行SWAR(寄存器内的 SIMD)以手动取消 a 的字节之间的进位传播uint64_t,执行与此等效的操作:
uint64_t sub(uint64_t arg) {
uint8_t* packed = (uint8_t*) &arg;
for (size_t i = 0; i < sizeof(uint64_t); ++i) {
packed[i] -= 1;
}
return arg;
}
Run Code Online (Sandbox Code Playgroud)
我认为你可以用按位运算符来做到这一点,但我不确定。我正在寻找一种不使用 SIMD 指令的解决方案。我正在寻找一个非常便携的 C 或 C++ 解决方案,或者只是它背后的理论,这样我就可以实现我自己的解决方案。
假设我有两个uint16_t[4]数组,a并且b. 这些数组中的每个整数都在 [0, 16383] 范围内,因此未设置第 14 和 15 位。a[i]然后我有一些代码来查找每个b[i]之间的最小值和最大值i:
uint16_t min[4], max[4];
for (int i = 0; i < 4; i++) {
if (a[i] < b[i]) {
min[i] = a[i];
max[i] = b[i];
} else {
min[i] = b[i];
max[i] = a[i];
}
}
Run Code Online (Sandbox Code Playgroud)
假设由于某种原因我不能/不会使用 SIMD,但我仍然想在 64 位平台上尽可能快地计算它。因此,一个自然的解决方案是在 64 位寄存器上使用 SIMD 寄存器内 (SWAR) 范例,在单次迭代中计算这 4 个值,而不是使用 16 位算术进行超过 4 次迭代。
可以使用哪些位操作技巧来使用 SWAR 范例来实现(最小或最大)或理想情况下这两种操作,以便生成的代码比上面的循环更快?我的目标架构是 ARMv8,因此请随意使用任何有助于减少指令数量的 ARMv8 指令。
C、汇编或 C+ …
我有两个 64 位整数x和y. 每个代表5个无符号短整数:前10位代表第一个整数,接下来的13位代表第二个整数,接下来的16位代表第三个整数,接下来的14位代表第四个整数,其余位代表第 5 个整数。
设x0,x1,x2,x3,x4是构成5个短整型x。设y0,y1,y2,y3,y4是构成5个短整型y。我需要知道是否x0 < y0AND x1 < y1AND x2 < y2AND x3 < y3AND x4 < y4。
我认为最简单的解决方案是转移:
bool allLess(std::size_t x, std::size_t y)
{
if(x >= y) return 0;
int shift[] = {10, 13, 16, 14};
for(int i = 0; i < …Run Code Online (Sandbox Code Playgroud) 我试图使用s 的uint64_t8 个车道uint8_t;我的目标是实现逐车道小于。如果相应车道 in的值小于该车道 in 的值,则此操作,给定x和y,应0xFF在车道内产生结果,否则。逐车道小于或等于也可以。xy0x00
根据我所看到的,我猜我需要一个车道差异或零操作(定义为doz(x, y) = if (x < y) then 0 else (x - y)),然后使用它来构建一个选择掩码。但是,我见过的所有车道减法方法都是有符号的,我不确定如何使用它们来完成此类任务。
有没有办法做到这一点,使用差异或零或其他方式?
Stockfish 国际象棋引擎需要存储残局得分和中局得分以进行评估。
它将它们打包成一个 ,而不是单独存储它们int。中局得分存储在低 16 位中。如果中局得分为正,则残局得分存储在高 16 位中;如果中局得分为负,则减一。
这样做的优点是可以并行地对两个数字进行运算(加法、减法、求反和乘法)。
/// Score enum stores a middlegame and an endgame value in a single integer (enum).
/// The least significant 16 bits are used to store the middlegame value and the
/// upper 16 bits are used to store the endgame value. We have to take care to
/// avoid left-shifting a signed int to avoid undefined behavior.
enum Score : int { SCORE_ZERO };
constexpr Score make_score(int mg, …Run Code Online (Sandbox Code Playgroud) 对于 64 位 x86 寄存器,如果一个值的大小足够小以至于多个指令可以放入一个寄存器中,是否可以在同一寄存器中一次保存多个值?例如,将两个 32 位整数装入一个寄存器。如果可能的话,这会是一件坏事吗?我一直在阅读寄存器,并且对这个概念很陌生。
我最近面临一个给定的问题:
\n\n\n向量中有8个元素,每个元素都用int8_t表示。
\n在 x86_64 中实现一个算法,将两个向量(uint64_t 类型)相加。
\n添加元素时应考虑饱和算术。
\n例如:
\n80 + 60 = 127
\n(\xe2\x88\x9240) + (\xe2\x88\x92100) = \xe2\x88\x92128
\n
最大的挑战是施加的限制:
\n我想不出任何符合这些限制的解决方案。\n有人能给我一些提示吗?欢迎使用 C 语言的示例。
\n我只能使用“标准”、传输、算术、逻辑指令和标准寄存器:
\n