linux - Linux 中的 DMA memcpy 操作

标签 linux dma

我想使用 dmaengine.c 文件 (linux/drivers/dma) 中的 dma_async_memcpy_buf_to_buf 函数进行 dma。为此,我在 dmatest.c 文件 (linux/drivers/dma) 中添加了一个函数,如下所示:

void foo ()
{
    int index = 0;
    dma_cookie_t cookie;
    size_t len = 0x20000;

    ktime_t start, end, end1, end2, end3;
    s64 actual_time;    

    u16* dest;
    u16* src;

    dest = kmalloc(len, GFP_KERNEL);
    src = kmalloc(len, GFP_KERNEL);

    for (index = 0; index < len/2; index++)
    {
        dest[index] = 0xAA55;
        src[index] = 0xDEAD;
    }

    start = ktime_get();
    cookie = dma_async_memcpy_buf_to_buf(chan, dest, src, len);

    while (dma_async_is_tx_complete(chan, cookie, NULL, NULL) == DMA_IN_PROGRESS)
    {
       dma_sync_wait(chan, cookie);
    }
    end = ktime_get();
    actual_time = ktime_to_ns(ktime_sub(end, start));
    printk("Time taken for function() execution     dma: %lld\n",(long long)actual_time);   

    memset(dest, 0 , len);

    start = ktime_get();
    memcpy(dest, src, len);

    end = ktime_get();
    actual_time = ktime_to_ns(ktime_sub(end, start));
    printk("Time taken for function() execution non-dma: %lld\n",(long long)actual_time);
}

DMA 存在一些问题:

  1. 有趣的是,memcpy 函数的执行时间少于 dma_async_memcpy_buf_to_buf 函数。可能与ktime_get()函数问题有关。

  2. 我使用 foo 函数的方法执行 DMA 操作是正确的还是不正确的?我不确定这一点。

  3. 如何根据 cpu 使用率测量 memcpy 和 dma_async_memcpy_buf_to_buf 函数的滴答计数

  4. 最后,DMA 操作是否可以在应用程序级别进行?到目前为止,我在内核级别使用,如上所示(dmatest.c 已插入内核模块)

最佳答案

您的问题中存在多个问题,因此很难准确回答您的问题:

  1. 是的,您的通用 DMA 操作调用算法是正确的。

  2. 使用普通 memcpy 和 DMA 操作复制内存的根本区别不是获得直接的性能提升,而是 (a) 由于在使用 DMA 时维持 CPU 缓存/预取器状态而带来的性能提升操作(当使用在 CPU 本身上执行的普通旧式 memcpy 时可能会出现乱码),以及 (b) 真正的后台操作,让 CPU 可以用来做其他事情。

  3. 给定 (a),对小于 CPU 缓存大小(即几十兆字节)的任何内容使用 DMA 操作是毫无意义的。通常,它是为了快速 off-CPU 流处理的目的而完成的,即移动无论如何都会由外部设备产生/使用的数据,例如快速网卡、视频流/捕获/编码硬件等。

  4. 根据挂钟运行时间来比较异步和同步操作是错误的。可能有数百个线程/进程在运行,没有人可以保证您会在下一个时钟节拍而不是数千个时钟节拍之后得到安排。

  5. ktime_get 用于基准测试目的是错误的 - 它相当不精确,尤其是对于给定的如此短的工作。分析内核代码实际上是一项非常艰巨和复杂的任务,远远超出了这个问题的范围。此处的一个快速建议是完全避免此类微基准测试,并描述一个更大、更完整的工作 - 类似于您最终要实现的目标。

  6. 尽管您可以使用 CPU 供应商特定的工具,例如 Intel's VTune,但测量现代 CPU 的“滴答声”也是毫无意义的。 .

  7. 在应用程序级别使用 DMA 复制操作是毫无意义的 - 至少在值得麻烦的时候,我无法从头脑中得出一个可行的方案。它并不是天生就更快,而且,更重要的是,我严重怀疑您的应用程序性能的瓶颈是内存复制。对于这种情况,您通常应该比常规内存复制更快做所有其他事情,而且我真的想不出应用程序级别的任何东西会比 memcpy。如果我们谈论的是与其他一些非 CPU 处理设备的通信,那么它自动不是应用程序级别。

  8. 一般来说,内存复制性能通常受限于内存速度,即时钟频率和时序。在直接性能方面,您不会比常规 memcpy 获得任何奇迹般的提升,只是因为在 CPU 上执行的 memcpy 足够快,因为 CPU 通常以 3x-5x-时钟频率比内存快 10 倍。

关于linux - Linux 中的 DMA memcpy 操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25521422/

相关文章:

c - 如何使用动态分配的数组实现队列?

c++ - 在 linux 上部署 Qt5.10 App 时出错

linux - 进程虚拟内存

linux - 如何通过 Linux 命令提示符导航到目录中的文件

c - STM32:以DMA模式实现UART

c - Linux get_user_pages 是否保证页面不会被交换?

rust - 如何在Rust结构实现中编写SPI DMA代码?

Linux : power fault input?

linux - 每个进程的页表是否包含映射到内核地址空间的条目?

interrupt - STM32f0 是否可以在 DMA 完成一半时获得中断