3

我正在开发不支持未对齐内存访问的嵌入式设备。

对于视频解码器,我必须处理 8x8 像素块中的像素(每个像素一个字节)。该设备具有一些 SIMD 处理功能,允许我并行处理 4 个字节。

问题是,8x8 像素块不能保证从对齐的地址开始,并且函数需要读取/写入最多三个这些 8x8 块。

如果您想要非常好的性能,您将如何处理?经过一番思考,我想出了以下三个想法:

  1. 将所有内存访问作为字节进行。这是最简单的方法,但速度很慢,而且它不适用于 SIMD 功能(这是我目前在参考 C 代码中所做的)。

  2. 编写四个复制函数(每个对齐情况一个),通过两个 32 位读取加载像素数据,将位移动到正确的位置,并将数据写入一些对齐的暂存内存块。然后视频处理功能可以使用 32 位访问和 SIMD。缺点:CPU 将没有机会隐藏处理背后的内存延迟。

  3. 与上述相同的想法,但不是将像素写入暂存内存,而是进行视频处理。这可能是最快的方法,但是我必须为这种方法编写的函数数量很多(我猜大约 60 个)。

顺便说一句:我将不得不在汇编程序中编写所有函数,因为编译器在涉及 SIMD 扩展时会生成可怕的代码。

你会走哪条路,或者你有其他想法如何解决这个问题?

4

5 回答 5

4

您可以使用memcpy(如果我记得可以对其进行优化以在可能的情况下执行字复制)复制到对齐的数据结构(例如,分配在堆栈上或 from 的东西malloc)。然后对该对齐的数据结构执行处理。

不过,最有可能的是,您希望在处理器的寄存器中而不是在内存中处理事情。您将如何处理您的任务取决于硬件的功能(例如,一个 32 位寄存器可以拆分为四个 8 位寄存器吗?SIMD 操作对哪些寄存器进行操作?)如果您要走简单的路线,您可以调用一个小的加载器函数,它会为您执行未对齐的读取。

于 2008-12-17T19:16:39.073 回答
3

首先对齐数据,然后采用对齐 SIMD 方法。

这比选项 3 的工作量少,幸运的是,您的代码将在 25% 的时间内达到最高速度(即已经对齐的情况)。在您知道输入将正确对齐的情况下,您将来可以愉快地重用代码。

只有当这不能让您满意时,您才应考虑将所有四种对齐可能性硬编码到您的函数中。

于 2008-12-30T05:55:51.140 回答
3

您应该首先将代码分解为获取/处理部分。

提取代码应该复制到工作缓冲区中,并且有对齐内存的情况(您应该能够使用 SIMD 寄存器进行复制)和需要逐字节复制的非对齐内存(如果您的平台可以) t 进行未对齐的访问,并且您的源/目标具有不同的对齐方式,那么这是您能做的最好的)。

然后,您的处理代码可以是 SIMD,并保证处理对齐的数据。对于任何真正程度的处理,复制+处理肯定会比对未对齐数据的非 SIMD 操作更快。

假设您的源和目标相同,进一步的优化将是仅在源未对齐时使用工作缓冲区,如果内存对齐,则在原地进行处理。这样做的好处将取决于您的数据的特征。

根据您的架构,您可以通过在处理之前预取数据获得更多好处。在这里,您可以发出指令以在需要之前将内存区域提取到缓存中,因此您可以在处理当前块之前发出对下一个块的提取。

于 2008-12-30T06:21:07.347 回答
2

我会选择选项 1)直到你知道它太慢了(慢是可以的,太慢是不好的)

于 2008-12-17T19:07:08.263 回答
2

一般建议:您为什么不使用听起来合理的东西(例如#2)然后衡量性能?如果不可接受,您可以返回绘图板。

当然,在测量之前在汇编程序中手工制作 60 个函数会算作“过早的优化”。:)

于 2008-12-30T06:28:15.770 回答