是否有用于圆形功能的 ARM Neon 指令?

Are there are ARM Neon instructions for round function?

我正在尝试使用 ARM Neon 内部函数实现轮函数。

这个函数看起来像这样:

float roundf(float x) {
    return signbit(x) ? ceil(x - 0.5) : floor(x + 0.5);
}

有没有办法使用 Neon 内在函数来做到这一点?如果没有,如何使用Neon intrinsics来实现这个功能?

已编辑

计算两个浮点数的乘积后,调用roundf(在armv7和armv8上)。

我的编译器是 clang。

这可以通过 vrndaq_f32 完成:https://developer.arm.com/architectures/instruction-sets/intrinsics/#f:@navigationhierarchiessimdisa=[Neon]&q=vrndaq_f32 for armv8.

如何在 armv7 上执行此操作?

已编辑

我的实现

// input: float32x4_t arg
float32x4_t vector_zero = vdupq_n_f32(0.f);
float32x4_t neg_half = vdupq_n_f32(-0.5f);
float32x4_t pos_half = vdupq_n_f32(0.5f);

uint32x4_t mask = vcgeq_f32(arg, vector_zero);
uint32x4_t mask_neg = vandq_u32(mask, neg_half);
uint32x4_t mask_pos = vandq_u32(mask, pos_half);
arg = vaddq_f32(arg, (float32x4_t)mask_pos);
arg = vaddq_f32(arg, (float32x4_t)mask_neg);
int32x4_t arg_int32 = vcvtq_s32_f32(arg);
arg = vcvtq_f32_s32(arg_int32);

有没有更好的实现方式?

确定您真正想要的 哪种 舍入形式很重要。请参阅 Wikipedia 了解有多少舍入选项。

从您的代码片段中,您要求 commercialsymmetric 舍入,这是从零舍入的关系。对于 ARMv8 / ARM64,vrndaq_f32 应该这样做。

The SSE4 _mm_round_ps and ARMv8 ARM-NEON vrndnq_f32 do bankers rounding i.e. round-to-nearest (even).

您的解决方案在周期计数和寄存器利用率方面都非常昂贵。

如果-(2^30) <= arg < (2^30),您可以执行以下操作:

int32x4_t argi = vcvtq_n_s32_f32(arg, 1);
argi = vsraq_n_s32(argi, argi, 31);
argi = vrshrq_n_s32(argi, 1);
arg = vcvtq_f32_s32(argi);

除了 arg 本身不需要任何其他寄存器,只需 4 条廉价指令即可完成。它适用于 aarch32aarch64

godblot link