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

Is it possible to use a value in d[x] register as address in vld?

本文关键字:地址 vld 寄存器 可以使 是否      更新时间:2023-10-16

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

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

然而,我想使用ARM Neon内部函数来优化此操作。由于有32个(如果我错了,请更正)neon(dx)寄存器寄存器,我不能对大于的查找表使用VTBL指令

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

ARM NEON:如何实现256字节查找表

我如何才能优化如此简单的操作?我认为使用图像的像素作为VLD函数的地址参数,如下所示:

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

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

另一个例子中的优化是通过在寄存器中保存整个查找表来实现的。你根本无法做到这一点:你的表是16384字节(2^14->2^8),这远远超过了你在寄存器空间中的容量。

因此,您的表将位于一级缓存中。显而易见的C++代码:

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

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

如果速度是个问题,我会通过积极地将表修剪到128个条目,并在接下来的几位上使用线性插值来解决这个问题。

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

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

例如,你可以在输入的前三或四位使用VTBL,在其余位使用线性插值。但只有当曲线足够平滑,线性插值是一个足够的近似值时,这才有效。

匹配所述参数的常见操作是线性到sRGB转换;在这种情况下,您将考虑将每个输入提高到5/12的幂。这有点棘手,但如果你不需要太准确,你仍然可以获得一些性能提升。