我有以下代码
if(value == 0)
{
value = 1;
}
使用NEON向量化指令我需要执行上述操作。如何将NEON寄存器值与0进行比较,一次为4个元素,如果元素为零,则将值更改为1。
假设整数数据,那么由于NEON具有特定的“与零比较”指令,并且按位方式比较结果起作用,使用一个备用寄存器实现这一点的方法非常厚颜无耻。在广义伪装配中:
VCEQ.type mask, data, #0 @ Generate bitmask vector with all bits set in elements
@ corresponding to zero elements in the data
VSUB.type data, data, mask @ Interpret "mask" as a vector of 0s and -1s, with the
@ result of incrementing just the zero elements of "data"
@ (thanks to twos complement underflow)
这个技巧对浮点数据不起作用,因为非零值的位模式更复杂,如果替换值不是1(或-1),它也不起作用,所以在那些情况下你需要构造一个包含适当替换元素的单独向量,并根据@Ermlg's answer使用比较掩码进行条件选择。
也许它看起来像这样:
uint32x4_t value = {7, 0, 0, 3};
uint32x4_t zero = {0, 0, 0, 0};
uint32x4_t one = {1, 1, 1, 1};
uint32x4_t mask = vceqq_u32(value, zero);
value = vbslq_u32(mask, one, value);
要获得更多信息,请参阅here。
如果要检查向量的任何元素是否为非零并在其上分支:
您可以在矢量通道中使用get min / max。
if(vmaxvq_u32(value) == 0) { // Max value across quad vector, equals zero?
value = vmovq_n_u32(1); // Set all lanes to 1
}
对于双向量
if(vmaxv_u32(value) == 0) { // Max value across double vector, equals zero?
value = vmov_n_u32(1); // Set all lanes to 1
}
注意唯一的区别是'q'用于表示四进制128位向量或64位双向量,如果不是。编译器将使用mov指令从单个指令传输到arm通用寄存器以进行比较。