是否可以将d [x]寄存器中的值用作vld中的地址?

时间:2015-04-03 15:11:20

标签: c++ arm simd neon

我有一个大小为M x N的图像,每个像素为14位(所有像素都以16位整数存储,但不使用2个最低有效位)。我想将每个像素映射到8位值,因为映射函数只是16384个值的数组。我使用纯C ++执行此图像色调映射,如下所示:

for(int i=0;i<imageSize;i++)
{
    resultImage[i] = mappingArray[image[Index]];
}

但是,我想使用ARM Neon内在函数优化此操作。由于氖(dx)寄存器寄存器有32个(如果我错了),我不能将VTBL指令用于大于

的查找表

8x32 = 256 元素。此外,还有另一个关于使用大于32字节的查找表的stacoverflow的讨论:

ARM NEON: How to implement a 256bytes Look Up table

如何设法优化这种简单的外观操作?我想使用图像的像素作为VLD函数的地址参数,如下所示:

VLD1.8 {d1},[d0] ??

有可能吗?或者我该如何处理?

2 个答案:

答案 0 :(得分:1)

另一个示例中的优化通过在寄存器中保存整个查找表来工作。你根本不能这样做:你的表是16384字节(2 ^ 14 - > 2 ^ 8),这是比你在寄存器空间中的方式更多的方式。

因此,您的表将驻留在L1缓存中。显而易见的C ++代码:

unsigned char mappingArray[16384];
fill(mappingArray);
for(int i=0;i<imageSize;i++)
{
    resultImage[i] = mappingArray[image[i]>>2];
}

可能会直接编译为最有效的代码。问题不在于你如何在寄存器中获取东西。问题是您需要对输入图像,映射表和输出图像进行内存访问。

如果速度有问题,我可以通过积极地将表格修改为128个条目,并在接下来的几个位上使用线性插值来解决这个问题。

答案 1 :(得分:1)

给定一个大的查找表,正常的过程是仔细查看它以找出(或在互联网上找到)计算每个条目的算法。如果该算法足够简单,那么您可能会发现并行执行计算的速度更快,而不是执行标量表查找。

或者,根据数据的形状,您可以尝试查找符合要求但更容易计算的近似值。

例如,您可以在输入的前三或四位使用VTBL,在其余部分使用线性插值。但这仅在曲线足够平滑以使线性插值足够近似时才有效。

与所述参数匹配的常见操作与sRGB转换呈线性关系;在这种情况下,您正在考虑将每个输入提高到5/12的功率。这有点毛茸茸,但如果你不太准确,你仍然可以获得一些性能提升。