如何在ARM NEON中将uint8x8_t加载到float32x4中?

时间:2013-06-19 16:58:15

标签: android c optimization arm neon

我正在研究图像处理算法,我正在研究使用NEON进行优化。 该算法包括将每个(RGBA,8位)像素乘以某个权重,进行一些加法并最终转换回uint8_t值。 我遇到的第一个问题是如何有效地加载单个uint8_t像素并将其转换为NEON的float32x4_t。我搜索了一个合适的转换参考,但是找不到合适的转换,所以我使用了这个丑陋的代码:

const uint8_t* psrc = ...; // pointer to image data
float rgba[4];
for (int c = 0; c < 4; ++c) {
  rgba[c] = *psrc++;
}
float32x4_t srcpix = vld1q_f32(rgba);

任何人都可以为此建议一种“更清洁”的方式吗?

编辑: 所以我想出了这个,仍然觉得很麻烦:

uint8x8_t srcu8 = vld1_u8(psrc);
uint16x8_t srcu16x8 = vmovl_u8(srcu8);
uint16x4_t srcu16x4 = vget_low_u16(srcu16x8);
uint32x4_t srcu32x4 = vmovl_u16(srcu16x4);
srcpix = vcvtq_f32_u32(srcu32x4);

3 个答案:

答案 0 :(得分:1)

所以你想将它们转换为float以进行某些算术并将结果转换回int?这与人们称之为优化的方式正好相反。

坚持NEON真正发光的定点运算。

我很难想象任何转换为​​float的情况都会对ARGB格式有意义,其中每个通道的大小只有8位(精确度)。

显然你试图让NEON在ARM完成浮点运算时来回转换,但这正是使用NEON的错误方法。

适当的NEON优化功能应让NEON自行处理数据加载,算术和数据存储。正确完成后,我确信NEON版本的运行速度将比当前版本快20倍,接近memcpy速度。 - 使用定点算法,NEON功能强大。

请详细说明您要做的事情。也许我可以帮忙。

答案 1 :(得分:1)

VTBX表查找指令可以在单个操作中执行无符号8位-32位扩展,但遗憾的是输出是单个氖寄存器(将是uint32x2_t),因此要“填充”{ {1}}你需要调用它两次。对于uint32x4_t源的所有八个字节,您必须执行以下操作:

uint8x8_t

我认为这不比你找到的方法更少。查找表也来自内存,所以它可能会更慢。然后还需要uint8x8_t bvec = vld1_u8(psrc); uint8x8x4_t tbl = { { 0, -1, -1, -1, 1, -1, -1, -1 }, { 2, -1, -1, -1, 3, -1, -1, -1 } { 4, -1, -1, -1, 5, -1, -1, -1 } { 6, -1, -1, -1, 7, -1, -1, -1 } }; uint32x4_t ivec[2] = { { vreinterpret_u32_u8(vtbx1_u8(tbl[0], bvec, 0)), vreinterpret_u32_u8(vtbx1_u8(tbl[1], bvec, 0)) }, { vreinterpret_u32_u8(vtbx1_u8(tbl[2], bvec, 0)), vreinterpret_u32_u8(vtbx1_u8(tbl[3], bvec, 0)) } }; float32x4_t vec[2] = { vcvtq_f32_u32(ivec[0]), vcvtq_f32_u32(ivec[1]) }; ...这是一个免费的操作,但看起来很邋。。

答案 2 :(得分:0)

据我所知,NEON仅支持32位转换(使用vcvt_...(),您可以在float32x4_tint32x4_t之间进行转换(例如)。因此,您需要将uint8x8_t转换为uint32x4x2_t,然后将vcvt用于uint32x4x2_t的两半。

修改 不幸的是,我无法为你提供代码,因为我没有花很多时间处理它,也无法记住命令。