我在不支持未对齐内存访问的嵌入式设备上工作。
对于视频解码器,我必须处理8x8像素块中的像素(每个像素一个字节)。该设备具有一些SIMD处理功能,使我可以并行处理4个字节。
问题是,不能保证8x8像素块从对齐的地址开始,并且功能需要最多读取/写入这些8x8块中的三个。
如果您想要非常好的性能,您将如何处理?经过一番思考,我提出了以下三个想法:
以字节为单位进行所有内存访问。这是最简单的方法,但是很慢,并且不能与SIMD功能兼容(这是我目前在参考C代码中所做的事情)。
编写四个复制功能(每个对齐方式一个),通过两个32位读取加载像素数据,将这些位移到正确的位置,然后将数据写入到暂存存储器的某些对齐块中。然后,视频处理功能可以使用32位访问和SIMD。缺点:CPU将没有机会将内存延迟隐藏在处理之后。
与上面相同的想法,但是不是将像素写到暂存器中,而是进行视频处理。这可能是最快的方法,但是我必须为此方法编写的函数数量很高(我猜大概有60个)。
顺便说一句:我将不得不在汇编器中编写所有函数,因为当涉及到SIMD扩展时,编译器会生成可怕的代码。
您会走哪条路,或者您对如何解决这个问题有其他想法?
最佳答案
您应该首先将代码分成访存/处理部分。
提取代码应复制到工作缓冲区中,并具有对齐内存(您应该能够使用SIMD寄存器进行复制的内存)和需要逐字节复制的非对齐内存(如果平台可以)的情况。进行未对齐的访问,并且您的源/目的地具有不同的对齐方式,那么这是您可以做的最好的事情。
然后,可以保证您的处理代码为SIMD,并且可以处理对齐的数据。对于任何实际程度的处理,执行复制+处理绝对比对未对齐数据进行非SIMD操作要快。
假设源和目标相同,则进一步的优化将是仅在源未对齐的情况下使用工作缓冲区,而在内存已对齐的情况下就地进行处理。这样做的好处将取决于数据的特征。
根据您的体系结构,在处理之前预取数据可能会获得更多好处。在这里,您可以发出指令以在需要它们之前将内存区域提取到缓存中,因此您可以在处理当前块之前发出对下一个块的提取。