[英]uint8 to float using SIMD Neon intrinsics
我正在嘗試優化將灰度圖像轉換為在 Neon A64/v8 上運行的浮動圖像的代碼。
當前的實現使用 OpenCV 的convertTo()
(為 android 編譯convertTo()
相當快,但這仍然是我們的瓶頸。
所以我想出了以下代碼,並想聽聽可能的改進。
如果有幫助,圖像高度和寬度是 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 ) );
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.