5

我们有一个应用程序需要大约 1MB 的缓冲区来填充硬件设备,因此我们编写了一个内核模块,使用 kmalloc() 分配缓冲区。我们没有使用 dma_alloc_coherent() 因为我们需要操纵缓冲区,因此希望它们被缓存(我们在需要时刷新缓存)。完成的操作之一是内核模块将一个缓冲区复制到另一个缓冲区。在计时这些副本时,我们看到复制缓冲区大约需要 2 毫秒。该时间不包括任何缓存刷新。

由于这看起来很慢,我们编写了一个标准的用户空间测试应用程序,它使用 malloc() 创建 1MB 缓冲区并复制它们。用户空间副本大约需要 0.5 毫秒,这大约是在我们正在使用的处理器/内存配置上移动这么多内存的正确时间。

我们尝试过的想法:为了确保它在内核空间和用户空间中不是不同的 memcpy(),我们编写了自己的 NEON 优化副本,但没有任何区别。将缓冲区大小从 100KB 更改为 10MB,没有任何区别。所有时间都超过 10 份,但总是非常非常一致。时间例程在用户空间中使用 gettimeofday()。

我们唯一能想到的是,kmalloc()'ed 内存和 malloc()'ed 内存的数据缓存设置不同???

我们正在研究 iMX6 ARM、Linaro 内核。

4

1 回答 1

2

kmalloc()内存在物理空间中是连续的。用户空间肯定不会(mlock()可能导致更接近连续)。如果您有多个 SDRAM 芯片,则您的内存控制器可能允许 同时对不同芯片进行流水线操作多个问题读/写。使用多家银行甚至可能更快。 vmalloc()不会使用连续页面。参考 您应该能够编写一个测试来交换kmalloc(). vmalloc()如果较新的 ARM 发生了某些变化并且缓存不是VIVT,则物理地址的差异可能会导致缓存(混叠?)对某些处理器产生影响。

我不认为内核内存和用户内存的缓存设置不同。至少有 2.6.34 个变体;但它们可能来自不同的池。此外,memcpy()不需要大缓存;你只需要足够的东西来确保 SDRAM 会爆裂。

另一个问题是外围设备。例如,一个芯片上的大型图形缓冲区可能会通过 DMA 窃取周期。如果您可以更改您的机器文件设备表以禁用尽可能多的驱动程序,则可以消除这种情况。这与流水线相结合可以解释观察到的减速类型。

我相信这是一个平台问题。如果是严格意义上的 Linux,我认为数百万用户中的一个可能已经遇到过它。但是,您还没有给出特定版本的 Linux。这可能是基于 ARM 的问题;所以我把它标记为这样。我认为这是您的平台/ARM 组合;仅仅因为其他人会观察到这一点。您是否还可以提供您的设计所基于的特定机器文件设备表以及 Linux 版本。

于 2013-03-20T04:06:36.720 回答