首页 > 解决方案 > DMA缓冲区怎么这么慢?

问题描述

我从一些书籍或链接中学习,

所以我有一个问题,

  1. RAM 速度通常在 12 GB/s 左右,但我在用户空间测试了 DMA 缓冲区,使用 mmap/memcpy 的传输速度只有 0.03 GB/s 左右,为什么?下面是我的代码。

我得到了结果:

内存速度:12.953367 GB/s
DMA 速度:0.029834 GB/s

#include <string.h>
#include <iostream>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <cstring>
#include <fcntl.h>
#include <unistd.h>
struct drm_mode_create_dumb
{
    __u32 height;
    __u32 width;
    __u32 bpp;
    __u32 flags;
    /* handle, pitch, size will be returned */
    __u32 handle;
    __u32 pitch;
    __u64 size;
};
struct drm_prime_handle
{
    __u32 handle;

    /** Flags.. only applicable for handle->fd */
    __u32 flags;

    /** Returned dmabuf file descriptor */
    __s32 fd;
};

struct drm_mode_destroy_dumb
{
    __u32 handle;
};

double TimeStamp()
{
    struct timespec now;
    timespec_get(&now, TIME_UTC);
    return (((int64_t)now.tv_sec) * 1000 + ((int64_t)now.tv_nsec) / 1000000) / 1000.0;
}

void test_ram_speed()
{
    int i = 0;
    char *pbuf1 = new char[1024 * 1024];
    char *pbuf2 = new char[1024 * 1024];
    memset(pbuf1, 0, 1024 * 1024);
    memset(pbuf2, 1, 1024 * 1024);

    double ibegin = TimeStamp();
    double iend = 0;
    int MB = 1024 * 10;

    while (i < MB) /* Here you can adjust the byte size */
    {
        i++;
        memcpy(pbuf1, pbuf2, 1024 * 1024);
    }

    iend = TimeStamp();

    printf("Ram Speed : %f GB/s \n", MB * 1 / (iend - ibegin) / 1024.0);
}

void test_dma_speed()
{
    struct drm_mode_create_dumb mRequest;

    int DRM_FD = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
    if (DRM_FD < 0)
    {
        return;
    }

    mRequest.height = 1024;
    mRequest.width = 1024;
    mRequest.bpp = 1;

    int nRet = ioctl(DRM_FD, _IOWR('d', 0xB2, struct drm_mode_create_dumb), &mRequest);

    if (nRet)
    {
        return;
    }

    struct drm_prime_handle prime_request = {
        .handle = mRequest.handle,
        .flags = O_CLOEXEC | O_RDWR,
        .fd = -1};

    nRet = ioctl(DRM_FD, _IOWR('d', 0x2d, struct drm_prime_handle), &prime_request);

    int mDmaBufFd = prime_request.fd;

    if (nRet || mDmaBufFd < 0)
    {
        return;
    }

    uint8_t *PrimedFramebuffer = (uint8_t *)mmap(0, mRequest.size,
                                                 PROT_READ | PROT_WRITE, MAP_SHARED,
                                                 mDmaBufFd, 0);
    if (PrimedFramebuffer == MAP_FAILED)
    {
        return;
    }

    char *pbuf1 = new char[1024 * 1024];

    double ibegin = TimeStamp();
    double iend = 0;
    int MB = 1024 * 0.03;
    int i = 0;
    while (i < MB) /* Here you can adjust the byte size */
    {
        i++;
        memcpy(pbuf1, PrimedFramebuffer, 1024 * 1024);
    }

    iend = TimeStamp();

    printf("DMA Speed : %f GB/s \n", MB * 1 / (iend - ibegin) / 1024.0);

    munmap(PrimedFramebuffer, mRequest.size);

    struct drm_mode_destroy_dumb destroy_request = {
        .handle = mRequest.handle};

    ioctl(DRM_FD, _IOWR('d', 0xB4, struct drm_mode_destroy_dumb), &destroy_request);

    close(DRM_FD);
}

int main()
{
    test_ram_speed();

    test_dma_speed();
    return 0;
}

标签: clinuxdma

解决方案


推荐阅读