diss
тривиально вычислить в неоне, возможно, он может быть реализован следующим образом (непроверенный код):
uint32x4_t diss_x4(uint32x4_t x4, uint32x4_t y4)
{
uint8x16_t diff = vabdq_u8(vreinterpretq_u8_u32(x4), vreinterpretq_u8_u32(x4));
uint16x8_t m0 = vmull_u8(vget_low_u8(diff), vget_low_u8(diff));
uint16x8_t m1 = vmull_u8(vget_high_u8(diff), vget_high_u8(diff));
uint16x4_t s0 = vpadd_u16(vget_low_u8(m0), vget_high_u8(m0));
uint16x4_t s1 = vpadd_u16(vget_low_u8(m1), vget_high_u8(m1));
uint16x4_t sx = vpadd_u16(s0, s1);
return vmovl_u16(sx);
}
но не так тривиально для findDissimilar
. Я думаю, что лучший подход заключается в следующем:
- загрузить все 16 дюймов в 4 q-регистра {q0, q1, q2, q3}
.
- первый регистр q0 содержит { buf[0], buf[1], buf[2], buf[3] }
- затем я могу выполнить цикл 15 раз и извлечь из 4 входных регистров q значения qext, такие как vextq_u32 (q0, q1, 1) для первой итерации и так далее.
- вычислить минимумы между q0 и qext.
тогда тот же процесс должен быть выполнен для q1, q2, q3.
Возможно, если я отменю перемежение {q0, q1, q2, q3}
байт, его можно оптимизировать еще лучше.