针对* ​​uncached *内存优化的ARM / neon memcpy?

时间:2016-01-19 23:09:36

标签: arm memcpy neon soc

我正在使用Xilinx Zynq 7000基于ARM的SoC。我正在努力使用DMA缓冲区(Need help mapping pre-reserved **cacheable** DMA buffer on Xilinx/ARM SoC (Zynq 7000)),所以我追求的是更快的memcpy。

我一直在寻找使用Neon指令和内联asm为ARM编写更快的memcpy。无论glibc有什么,它都很糟糕,特别是如果我们从ucached DMA缓冲区复制的话。

我已经从各种来源整理了我自己的复制功能,包括:

我的主要区别在于我尝试从未缓存的缓冲区进行复制,因为它是一个DMA缓冲区,并且ARM对缓存的DMA缓冲区的支持是不存在的。

所以我写的是:

void my_copy(volatile unsigned char *dst, volatile unsigned char *src, int sz)
{
    if (sz & 63) {
        sz = (sz & -64) + 64;
    }
    asm volatile (
        "NEONCopyPLD:                          \n"
        "    VLDM %[src]!,{d0-d7}                 \n"
        "    VSTM %[dst]!,{d0-d7}                 \n"
        "    SUBS %[sz],%[sz],#0x40                 \n"
        "    BGT NEONCopyPLD                  \n"
        : [dst]"+r"(dst), [src]"+r"(src), [sz]"+r"(sz) : : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "cc", "memory");
}

我做的主要是省略了预取指令,因为我认为它在未缓存的内存上毫无价值。

这样做比glibc memcpy的速度提高了4.7倍。速度从大约70MB /秒提高到大约330MB /秒。

不幸的是,这并不像缓存内存中的memcpy那么快,系统内存的运行速度大约为720MB /秒,Neon版本的运行速度大约为620MB /秒(可能因为我的memcpy不能运行速度慢)预取,也许)。

任何人都可以帮我弄清楚我能做些什么来弥补这个性能差距吗?

我尝试了很多东西,比如一次复制更多,两次加载,然后是两个商店。我可以尝试预取只是为了证明它没用。还有其他想法吗?

2 个答案:

答案 0 :(得分:0)

您可以尝试使用缓冲内存而不是非缓存内存。

答案 1 :(得分:0)

如果您尝试进行大而快速的传输,缓存内存通常会优于未缓存内存,但正如您所指出的,必须在某处管理对缓存 DMA 缓冲内存的支持,并且在 <=ARMv7 上,该位置是内核/内核驱动程序。

我对您的设计有两个假设:

  • 用户空间正在读取内存映射的硬件缓冲区
  • 从 FGPA 到 CortexA9 VIC/GIC 的某种信号/事件/中断会告诉 CortexA9 何时有新的缓冲区可供读取。

在缓存行边界上对齐 DMA 缓冲区,并且不要在 DMA 缓冲区的末尾和下一个缓存行之间放置任何东西。每当 FPGA 向 CPU 发出缓冲区准备就绪的信号时,使缓存无效。

我认为 A9 没有一种机制可以将所有内核和层上的缓存行控制在一起,因此您可能希望将执行此操作的程序固定到一个内核,以便您可以跳过维护另一个内核上的缓存。

>