简单聊一聊零拷贝

前言

零拷贝我们经常听说,相比于传统的io在性能上有了很大提升,那么在os里面他是怎么设计的呢,与传统io又有什么区别呢

Direct Memory Access(DMA)

在聊零拷贝之前,先看一看DMA在百度百科中的解释如下

DMA(Direct Memory Access,直接存储器访问) 是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依赖于 CPU 的大量中断负载。否则,CPU 需要从来源把每一片段的资料复制到暂存器,然后把它们再次写回到新的地方。在这个时间中,CPU 对于其他的工作来说就无法使用。

通俗来讲一些硬件子系统在读取内存的时候需要通过cpu调度内存,然后再获取到内存当中的数据,这样的一个过程大大依赖cpu性能,当cpu负载过高时硬件获取内存内容的速度就会大大减小

在这里插入图片描述

而DMA技术则不再依赖cpu,而是硬件系统直接去内存读取

在这里插入图片描述

传统数据io

传统io模式就是我们在以前学习编程基础时的io和网络这块,在传统模式下,我们从磁盘读取一个文件然后发送至网络中,通常流程就是读取文件,然后将文件转为字节流写入Socket中,进行传输,这样一个过程在OS中中的流程如下

在这里插入图片描述

在传统io模型中,读取一个文件的流程如下:

  • 从硬盘通过DMA拷贝将文件读取到内核缓冲区(第一次拷贝)
  • 从内存缓冲区复制到用户缓冲区中(第二次复制,且从内核态转换到用户态)
  • 从用户缓冲区复制到Socket缓冲区(第三次复制,且从用户态切换到内核态)
  • 从Socket缓冲区通过DMA拷贝到网络中(第四次复制)

从这个流程中可以看出在一次文件读取到网络的过程中,一共发生了四次复制过程,其中DMA拷贝两次CPU拷贝两次,这样的拷贝方式非常占用资源,而且存在一些不必要的复制过程

mmap映射

mmap通过与用户缓冲区共享内核缓冲区从而减少复制次数

在这里插入图片描述

mmap读取一个文件流程如下:

  • 首先从硬盘文件复制到内核缓冲区(第一次复制)
  • 由于用户缓冲区与共内核缓冲区共享,所以不需要再将内核缓冲区复制到用户缓冲区,用户缓冲区直接操作共享的内核缓冲区即可
  • 内核缓冲区将数据拷贝到Socket缓冲区(第二次复制)
  • Socket缓冲区再使用DMA拷贝到网络中(第三次复制)

可以看到相比于传统拷贝,mmap拷贝的复制次数减少了一次。由于用户态中的用户缓冲区直接操作内核缓冲区,因此用户态对文件的操作有容易丢失的缺点。

sendFile

在mmap中依然发生了三次复制,能不能再进行优化呢?Linux2.1提供了sendFile函数来进行文件拷贝传输,其基本流程如下
在这里插入图片描述

  • 首先从硬盘文件复制到内核缓冲区(第一次复制)
  • 从内核态再将文件拷贝到Socket缓冲区(第二次复制)
  • 从Socket缓冲区使用DMA拷贝到网络(第三次复制)

从这个流程可以看出sendFile的拷贝过程依然是三次复制,但是用户缓冲区没有参与到拷贝当中,因此在这个过程中虽然复制次数没变,但是减少了用户态和内核态的切换次数,效率有了一定提升

Linux2.4之后在这个基础上又进行了修改,修改后的拷贝流程如下

在这里插入图片描述

  • 首先从硬盘文件复制到内核缓冲区(第一次复制)
  • 从内核缓冲区直接拷贝到网络当中(第二次复制)
  • 内核缓冲区拷贝一些offset和length信息到Socket缓冲区

从上面的流程可以看到整个过程发生了三次拷贝,但是由于从内核缓冲区复制到Socket缓冲区拷贝内容较少,其消耗可忽略不计,因此修改后的SendFile可以看成之发生了两次拷贝,与传统拷贝相比拷贝次数减少一半,并且用户态和内核态的切换更少,性能更高

mmap和sendFile比较

虽然叫零拷贝,但并不意味着没有发生复制过程,而是相比于传统拷贝复制过程更少,用户态和内核态切换次数更少

mmap和sendFile比较如下

mmapsendFile
mmap适合小文件的拷贝sendFile适合大文件的传输
mmap发生4次用户态和内核态切换sendFile发生3次用户态和内核态切换
mmap发生3次数据拷贝sendFile发生2次数据拷贝
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenCL(Open Computing Language)是一种开放的跨平台并行计算框架,它允许开发者在不同的硬件平台上进行并行计算。零拷贝(Zero-Copy)是OpenCL中的一种技术,用于在主机(CPU)和设备(GPU)之间实现数据的高效传输。 在传统的计算模型中,主机和设备之间的数据传输通常需要通过主机内存进行拷贝,这会导致额外的内存开销和数据传输延迟。而零拷贝技术通过共享主机内存和设备内存的方式,避免了数据的多次拷贝,提高了数据传输的效率。 在OpenCL中,可以使用零拷贝技术通过以下步骤实现数据的高效传输: 1. 创建共享内存缓冲区:在主机端创建一个共享内存缓冲区,并将其映射到设备端。 2. 分配设备端内存:在设备端分配一块内存,用于与共享内存缓冲区进行数据交换。 3. 将数据写入共享内存缓冲区:将需要传输的数据写入共享内存缓冲区。 4. 在设备端进行计算:使用OpenCL在设备端进行并行计算,可以直接访问共享内存缓冲区中的数据。 5. 将计算结果读取到共享内存缓冲区:将设备端计算得到的结果写入共享内存缓冲区。 6. 从共享内存缓冲区读取数据:将最终的计算结果从共享内存缓冲区读取到主机端。 通过使用零拷贝技术,可以减少数据传输的开销,提高计算效率。然而,零拷贝也有一些限制和注意事项,例如需要确保主机和设备端的内存访问一致性,并且在数据传输过程中需要进行同步操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值