c - DMA缓冲区怎么这么慢?
问题描述
我从一些书籍或链接中学习,
- DMA 缓冲区位于系统内存中,让设备无需 CPU 即可访问它。
所以我有一个问题,
- 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;
}
解决方案
推荐阅读
- android - 将位图转换为 Firebase ML 套件的 N*N*N*N 字节数组
- python - 如何将我的自定义菜单添加到门户用户菜单列表?
- javascript - 如何从 javascript 传递数组输入框值?我只填充第一个值
- javascript - 如何在不使用 window.location.reload() 的情况下刷新/重新加载 Angular 2 应用程序?
- java - 每次在目录java中搜索时如何创建新线程
- android - 自动化应用程序操作
- java - 反序列化资源中的 POST 参数
- java - 输入验证和再次播放循环 JAVA 作业出现问题
- python - 如何在python中使用for循环从字符串中打印每个唯一单词的频率
- python - 从网页中快速定位元素