我一直在寻找一种方法来分配硬件可以写入的DMA缓冲区,但是可以从CPU读取缓存。 我开始使用Linux命令行选项mem = 896为DMA缓冲区保留最后128 MB的RAM(是的,这是过多的)。 然后在我写的驱动程序中,我执行以下操作:
void *srcBuf = NULL;
void *dstBuf = NULL;
dma_declare_coherent_memory(&gDev, BUFFER_ADDR, BUFFER_ADDR, 128*1024*1024, DMA_MEMORY_MAP);
srcBuf = dma_alloc_coherent(&gDev, 10*1024*1024, &dmaSrcAddr, GFP_DMA);
dstBuf = dma_alloc_coherent(&gDev, 10*1024*1024, &dmaDstAddr, GFP_DMA);
这在BUFFER_ADDR(物理RAM的末尾)正确分配128 MB,然后从该区域获得两个10 MB缓冲区。 然后我做一些简单的memset,memcpy代码来测试带宽:
start = ktime_get();
memset(srcBuf, 0x55, BUFFER_SIZE);
stop = ktime_get();
printPerformance(start.tv64, stop.tv64, "Write performance to memory");
start = ktime_get();
memcpy(dstBuf, srcBuf, BUFFER_SIZE);
stop = ktime_get();
printPerformance(start.tv64, stop.tv64, "Copy performance from src to dst");
这对于memset产生了可怕的919 MB /秒,对于memcpy产生了125 MB /秒。 这种设计对于Zedboard很简单,我有两个16位533 MHz DDR3L部件。 我应该有(533 * 2 * 4)4264 MB /秒的带宽。
然后我从用户空间做同样的事情,但使用posix_memalign。 这为memset提供了2461 MB /秒,对memcpy提供了298 MB /秒。 更好,但仍然很糟糕。
最后我写了一个裸机应用来做同样的事情。 虽然我没有分配内存,但我没有运行MMU,所以我只选了两个地址并执行了memset / memcpy测试。 我还启用了裸机测试,启用了L1和L2缓存,启用了L1缓存,但L @禁用,并且两个缓存都被禁用。 这导致以下结果:两个启用memset - 5296 MB /秒memcpy - 637 MB /秒L2禁用memset - 1426 MB /秒memcpy - 834 MB /秒两个禁用memset - 426 MB /秒memcpy - 276 MB /秒
用户空间代码的性能与禁用的两个缓存相同。 内核代码的性能只有一半。 有人有想法么?
那些喜欢图片的图表: