C mmap&x27;内存访问非常慢

C mmap&x27;内存访问非常慢,c,mmap,v4l2,C,Mmap,V4l2,我使用v4l2通过流式io从摄像机获取视频帧,需要对帧进行一些计算 但是,访问帧内存的速度比分配内存慢10倍 记忆混乱 我猜mmap帧内存不可由cpu缓存。 这是测试代码 //mmap video buffers struct v4l2_buffer buf; CLEAR(buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; if (-1 == xioctl(_fdC

我使用v4l2通过流式io从摄像机获取视频帧,需要对帧进行一些计算

但是,访问帧内存的速度比分配内存慢10倍 记忆混乱

我猜mmap帧内存不可由cpu缓存。

这是测试代码

//mmap video buffers
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (-1 == xioctl(_fdCamera, VIDIOC_QUERYBUF, &buf)) {
    ERROR("VIDIOC_QUERYBUF");
    goto error_querybuf;
}
_buffers[i].start = mmap(NULL, buf.length,
PROT_READ | PROT_WRITE,
MAP_SHARED, _fdCamera, buf.m.offset);


//use mmap'ed buffer to do some calculation
u16* frame=_buffers[0].start;

u64 sum=0;
u16* p=frame;
time[0]=GetMicrosecond64();
while(p!=frame+PIXELS){
    sum+=*p;
    p++;
}
time[1]=GetMicrosecond64();
printf("mmap:sum %lld,time %lld\n",sum, time[1] - time[0]);

//use a copy of data to do some calculation
u16* frame_copy=(u16*)malloc(PIXELS*2);
memcpy(frame_copy,frame,PIXELS*2);
sum=0;
p=frame_copy;
time[0]=GetMicrosecond64();
while(p!=frame_copy+PIXELS){
    sum+=*p;
    p++;
}
time[1]=GetMicrosecond64();
printf("malloc:sum %lld,time %lld\n",sum, time[1] - time[0]);
更新

我在linux-2.6.35中使用s5pv210。fimc_dev.c表示mmaped未缓存

如何使帧缓冲存储器同时支持DMA和缓存?

static inline int fimc_mmap_cap(struct file *filp, struct vm_area_struct *vma)
{
    struct fimc_prv_data *prv_data =
                (struct fimc_prv_data *)filp->private_data;
    struct fimc_control *ctrl = prv_data->ctrl;
    u32 size = vma->vm_end - vma->vm_start;
    u32 pfn, idx = vma->vm_pgoff;

    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
    vma->vm_flags |= VM_RESERVED;

    /*
     * page frame number of the address for a source frame
     * to be stored at.
     */
    pfn = __phys_to_pfn(ctrl->cap->bufs[idx].base[0]);

    if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) {
        fimc_err("%s: writable mapping must be shared\n", __func__);
        return -EINVAL;
    }

    if (remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot)) {
        fimc_err("%s: mmap fail\n", __func__);
        return -EINVAL;
    }

    return 0;
}

缓存摄影机帧缓冲区没有任何意义。想象一下如果你这样做会发生什么。摄影机在看到的场景发生变化时会继续更新帧缓冲区,但缓存永远不会更新。您必须每X毫秒使缓存失效一次,以保持帧更新。那太糟糕了。Imstead、memcpy或DMA删除帧缓冲区的副本,并对副本执行所有计算。