如何使用霓虹内在函数准确地将 uchar 转换为 float32 ,反之亦然

Posted

技术标签:

【中文标题】如何使用霓虹内在函数准确地将 uchar 转换为 float32 ,反之亦然【英文标题】:How do I accurately convert a uchar into a float32 and vice versa using neon intrinsics 【发布时间】:2016-02-02 00:56:03 【问题描述】:

我正在努力优化一些用于视频过滤的 c++ 代码并使用内部函数来做到这一点。但是,我无法弄清楚如何在加载和存储到不同类型的向量时仍然保持准确性的同时键入我的值。

我需要将 uchar 向量 img 的 4 个值存储到 float32x4_t 向量中。

我使用的第一种方法是:

  float32x4_t first_val = (float32_t)img.data[STEP0*i + STEP1*j],
                                (float32_t)img.data[STEP0*i + STEP1*(j + 1)],
                                (float32_t)img.data[STEP0*i + STEP1*(j + 2)],
                                (float32_t)img.data[STEP0*i + STEP1*(j + 3)]
                                ; 

这可行,但现在阻碍了我的速度。所以我尝试了:

float32x4_t first_val = vld1q_f32((float32_t*)&img.data[STEP0*i + STEP1*j]);

这不起作用。我怀疑这是因为它将我的 8 位像素中的 4 个转换为一个浮点数,并且本质上将其解释为垃圾。

我正在考虑使用 vreinterpretq_dsttype_srctype 来避免这个问题,但示例代码似乎只能将 x 大小的 var 类型重新解释为另一个相同大小的 vartype。我在存储和加载时遇到了同样的问题。

如果有人知道从 uchar -> float32 和 float32->uchar 准确获取的正确方法,请提供帮助。

【问题讨论】:

【参考方案1】:

图像数据的索引计算相当昂贵,您要执行 4 次。我假设 data[] 正在按顺序传输,但由于缺少代码我无法判断。这个假设是基于您在第二个示例中尝试使用 vld1q_f32() 的事实,并且这期望数据是按顺序排列的。

不管怎样,试试这个:

uchar* p = &img.data[STEP0*i + STEP1*j];

float32x4_t first_val = (float32_t)*p++,
                            (float32_t)*p++,
                            (float32_t)*p++,
                            (float32_t)*p++
                            ; 

如果您可以在循环外初始化第一行,那么您应该会看到显着增加。

如果您希望它更快,请记住调查 UNION 关键字,这可能会带来更多麻烦而不值得。个人不推荐。

vld1q_f32() 似乎适用于相同的格式,而不是混合 2 种数据类型。你对它为什么不起作用的原因是我怀疑发生了什么。

【讨论】:

我已经尝试过了,虽然它的速度有所提高,但它也扭曲了我的视频。是否可以向您发送消息以详细说明并提供我的代码? 如果它不起作用,则字节不按顺序排列。您需要提供更多源代码。我怀疑解决方案是设置 4 个 uchar* 变量。只要它们可以在内循环之外进行初始化,那么这种速度改进就可以发生。欢迎留言。

以上是关于如何使用霓虹内在函数准确地将 uchar 转换为 float32 ,反之亦然的主要内容,如果未能解决你的问题,请参考以下文章

如何在具有霓虹内在函数的多核处理器中有效地使用所有霓虹灯单元

霓虹灯:isnan(val) 内在函数

与霓虹内在函数中的浮点数比较

为啥乘法、加法的霓虹内在函数比运算符慢?

使用联合(封装在结构中)绕过霓虹灯数据类型的转换

在单臂霓虹灯寄存器中有效地将 8 位数字扩展到 12 位