c++ - uint8 使用 SIMD Neon 内在函数 float

标签 c++ c simd intrinsics neon

我正在尝试优化将灰度图像转换为在 Neon A64/v8 上运行的 float 图像的代码。
当前的实现使用 OpenCV 的 convertTo() 相当快(为 android 编译的),但这仍然是我们的瓶颈。
所以我想出了以下代码,并想听听可能的改进。
如果有帮助,图像高度和宽度是 16 的系数。
我在运行 for在此循环:

static void u8_2_f(unsigned char* in, float* out)
{
    //1 u8x8->u16x8
    uint8x8_t u8x8src = vld1_u8(in);
    uint16x8_t u16x8src = vmovl_u8(u8x8src);

    //2 u16x8 -> u32x4high, u32x4low
    uint32x4_t u32x4srch = vmovl_u16(vget_high_u16(u16x8src));
    uint32x4_t u32x4srcl = vmovl_u16(vget_low_u16(u16x8src));

    //3 u32x4high, u32x4low -> f32x4high, f32x4low
    vst1q_f32(out, vcvtq_f32_u32(u32x4srch));
    vst1q_f32(out+4, vcvtq_f32_u32(u32x4srcl));
}

最佳答案

为了可能的改进,尝试更换 vcvtq_f32_u32有了这个功能。它是 2 条指令而不是 1 条指令,但它们在某些 CPU 上可能更快。

// Convert bytes to float, assuming the input is within [ 0 .. 0xFF ] interval
inline float32x4_t byteToFloat( uint32x4_t u32 )
{
    // Floats have 23 bits of mantissa.
    // We want least significant 8 bits to be shifted to [ 0 .. 255 ], therefore need to add 2^23
    // See this page for details: https://www.h-schmidt.net/FloatConverter/IEEE754.html
    // If you want output floats in [ 0 .. 255.0 / 256.0 ] interval, change into 2^15 = 0x47000000
    constexpr uint32_t offsetValue = 0x4b000000;
    // Check disassembly & verify your compiler has moved this initialization outside the loop
    const uint32x4_t offsetInt = vdupq_n_u32( offsetValue );
    // Bitwise is probably slightly faster than addition, delivers same results for our input
    u32 = vorrq_u32( u32, offsetInt );
    // The only FP operation required is subtraction, hopefully faster than UCVTF
    return vsubq_f32( vreinterpretq_f32_u32( u32 ), vreinterpretq_f32_u32( offsetInt ) );
}

关于c++ - uint8 使用 SIMD Neon 内在函数 float ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63547634/

相关文章:

c++ - 如何使用 C++ 在不同的线程上调用函数?

c++ - 通过将两个短裤组合成一个整数来同时对两个短裤进行操作

c - linux中c程序中调用 "lp filename"命令是什么?

c - 多次互斥锁定

c 从文件初始化数组使第一个元素为-1

linux-kernel - 为什么内核中不使用 SIMD 指令?

c++ - 将数组的所有元素相加的 SSE 指令

C++ 编译时表达式作为数组大小

assembly - 快速的寄存器内字节排序?

c++ - OpenCV 高斯模糊破坏了 Tesseract?