https://software.intel.com/zh-cn/articles/accelerating-your-nvme-drives-with-spdk

简介

存储性能开发套件 (SPDK) 是 GitHub 托管的一套开源工具和库,可帮助开发人员创建高性能和可扩展存储应用。 本教程将重点介绍 SPDK 提供的用户空间 NVMe 驱动程序,并展示如何在英特尔® 架构平台上运行 Hello World 示例

软硬件配置

CPU 和芯片组

英特尔® 至强® 处理器 E5-2697 v2 @ 2.7 GHz

  • 每路的物理内核数量: 12(24 个逻辑内核)
  • 插座数量: 2
  • 芯片组: 英特尔® C610(C1 步进)
  • 系统总线: 9.6 GT/秒 QPI

内存

内存大小: 8 GB (8X8 GB) DDR3 1866

品牌/型号: Samsung – M393B1G73BH0*

存储

英特尔® 固态盘 DC P3700 系列

操作系统

CentOS* 7.2.1511,包含内核 3.10.0

为何需要使用用户空间 NVMe 驱动程序?

一直以来,存储设备的速度都远低于计算机系统的其他组件,比如 RAM 和 CPU。 这意味着操作系统和 CPU 需借助中断才能与磁盘进行交互:

  1. 向操作系统提出从磁盘读取数据的请求。
  2. 驱动程序处理请求,并与硬件通信。
  3. 磁盘片开始运转。
  4. 针在磁盘片内移动,开始读取数据。
  5. 数据被读取并拷贝至缓冲区。
  6. 生成中断,通知 CPU 数据已就绪。
  7. 最后从缓冲区读取数据。

这种中断模式会产生开销;但它的延迟一直远低于基于磁盘的存储设备,因此不失为一种有效方式。 随着固态盘 (SSD) 等全新存储设备以及 3D XPoint™ 存储等下一代存储技术的推出,使存储速度远高于磁盘,并将瓶颈从硬件(比如磁盘)移回至了软件(比如中断 + 内核),如图 1 所示:

图 1.固态盘 (SSD) 和 3D XPoint™ 存储的速度远高于磁盘。 硬件不再存在瓶颈。

读写数据时,用户空间 NVMe 驱动程序轮询存储设备,因此不再需要使用中断。 此外更重要的是,NVMe 驱动程序在用户空间中运行,这意味着应用能够直接与 NVMe 设备交互,无需通过内核。 它会产生开销,因为在与内核交互的过程中需要保存和恢复状态。  NVMe 采用无锁设计,不必使用 CPU 周期同步线程之间的数据,而且这种无锁方法还支持并行 IO 命令执行。

相比于使用 Linux 内核的方法,SPDK 用户空间 NVMe 驱动程序可将总体延迟降低 10 倍:

SPDK 能够使 8 块 NVMe 固态盘达到饱和,从而通过单个 CPU 内核提供超过 350 万次 IOPs:

前提条件和构建 SPDK

SPDK 支持 Fedora*、CentOS*、Ubuntu*、Debian* 和 FreeBSD*。 如欲获取完整的先决软件包列表,请访问此处。

构建 SPDK 之前,必须首先安装数据平面开发套件 (DPDK),因为 SPDK 依赖 DPDK 中的内存管理和队列功能。 DPDK 是比较成熟的库,常用于网络数据包处理,而且经过高度优化,能够以较低的延迟管理内存和队列数据。

使用以下命令从 GitHub 中克隆 SPDK 源代码:

git clone https://github.com/spdk/spdk.git

构建 DPDK(面向 Linux*):

1 cd /path/to/build/spdk
2  
3 wget http://fast.dpdk.org/rel/dpdk-16.07.tar.xz
4  
5 tar xf dpdk-16.07.tar.xz
6  
7 cd dpdk-16.07 && make install T=x86_64-native-linuxapp-gcc DESTDIR=.

构建 SPDK(面向 Linux*):

在 SPDK 文件夹中构建 DPDK 后,需要将目录恢复成 SPDK,并将 DPDK 位置传输至 make,以构建 SPDK:

1 cd /path/to/build/spdk
2  
3 make DPDK_DIR=./dpdk-16.07/x86_64-native-linuxapp-gcc

运行 SPDK 应用之前设置系统

以下命令可设置 hugepage 并解除内核驱动程序对 NVMe 和 I/OAT 设备的绑定:

sudo scripts/setup.sh

使用 hugepage 对性能至关重要,因为相比于默认的 4KiB 页面大小,它们的大小只有 2MiB,并能降低转换后备缓冲区 (TLB) 缺失的几率。 TLB 是 CPU 的一个组件,负责将虚拟地址转换成物理内存地址,因此使用较大的页面 (hugepage) 有助于高效使用 TLB。

借助‘Hello World’开始使用 SPDK

SPDK 包含许多示例和实用文档。可帮助您快速入门。 接下来我们通过示例介绍如何将‘Hello World’保存至 NVMe 设备,然后将其读取至缓冲区。

跳至代码之前还有一点值得注意,即如何组织 NVMe 设备结构,并提供高级示例解释如何利用 NVMe 驱动程序检测 NVMe 设备并读写数据。

组织 NVMe 设备(亦称作 NVMe 控制器)结构时需要考虑以下几点:

  • 系统可以有一台或多台 NVMe 设备。
  • 每台 NVMe 设备包含多个命名空间(可以仅为一个)。
  • 每个命名空间包含多个逻辑块地址 (LBA)。

本示例将经历以下几个步骤:

设置

  1. 初始化 DPDK 环境抽象层 (EAL)。 -c 为支持内核运行的位掩码,-n 为面向 master 的内核 ID,--proc-type 为安装 hugetlbfs 的目录。

    1 static char *ealargs[] = {
    2          "hello_world",
    3          "-c 0x1",
    4          "-n 4",
    5          "--proc-type=auto",
    6 };
    7 rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), ealargs);
  2. 创建请求缓冲池,用于 SPDK 内部保存各 I/O 请求数据:
    1 request_mempool = rte_mempool_create("nvme_request", 8192,
    2           spdk_nvme_request_size(), 128, 0,
    3           NULL, NULL, NULL, NULL,
    4           SOCKET_ID_ANY, 0);
  3. 寻找适用于 NVMe 设备的系统:
    rc = spdk_nvme_probe(NULL, probe_cb, attach_cb, NULL);
  4. 枚举 NVMe 设备,向 SPDK 返回布尔值,表示是否连接设备:
    01 static bool
    02 probe_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr_opts *opts)
    03 {
    04      printf("Attaching to %04x:%02x:%02x.%02x\n",
    05              spdk_pci_device_get_domain(dev),
    06              spdk_pci_device_get_bus(dev),
    07              spdk_pci_device_get_dev(dev),
    08              spdk_pci_device_get_func(dev));
    09  
    10      return true;
    11 }
  5. 设备已连接;现在可以请求命名空间数量信息:
    01 static void
    02 attach_cb(void *cb_ctx, struct spdk_pci_device *dev, struct spdk_nvme_ctrlr *ctrlr,
    03       const struct spdk_nvme_ctrlr_opts *opts)
    04 {
    05     int nsid, num_ns;
    06     const struct spdk_nvme_ctrlr_data *cdata = spdk_nvme_ctrlr_get_data(ctrlr);
    07  
    08     printf("Attached to %04x:%02x:%02x.%02x\n",
    09            spdk_pci_device_get_domain(dev),
    10            spdk_pci_device_get_bus(dev),
    11            spdk_pci_device_get_dev(dev),
    12            spdk_pci_device_get_func(dev));
    13  
    14     snprintf(entry->name, sizeof(entry->name), "%-20.20s (%-20.20s)", cdata->mn, cdata->sn);
    15  
    16     num_ns = spdk_nvme_ctrlr_get_num_ns(ctrlr);
    17     printf("Using controller %s with %d namespaces.\n", entry->name, num_ns);
    18     for (nsid = 1; nsid <= num_ns; nsid++) {
    19         register_ns(ctrlr, spdk_nvme_ctrlr_get_ns(ctrlr, nsid));
    20     }
    21 }
  6. 枚举用户空间,以检索相关信息(比如大小):
    1 static void
    2 register_ns(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns)
    3 {
    4      printf("  Namespace ID: %d size: %juGB\n", spdk_nvme_ns_get_id(ns),
    5             spdk_nvme_ns_get_size(ns) / 1000000000);
    6 }
  7. 创建 I/O 队列对,向命名空间提交读/写请求:
    ns_entry->qpair = spdk_nvme_ctrlr_alloc_io_qpair(ns_entry->ctrlr, 0);

    读/写数据

  8. 为即将读/写的数据分配缓冲区:
    sequence.buf = rte_zmalloc(NULL, 0x1000, 0x1000);
  9. 将‘Hello World’拷贝至缓冲区:
    sprintf(sequence.buf, "Hello world!\n");
  10. 将写入请求提交至特定命名空间,从而提供队列对、缓冲区指示器、LBA 索引、数据写入时的回调,以及应传递至回调的数据的指示器:
    1 rc = spdk_nvme_ns_cmd_write(ns_entry->ns, ns_entry->qpair, sequence.buf,
    2                             0, /* LBA start */
    3                             1, /* number of LBAs */
    4                             write_complete, &sequence, 0);
  11. 同时调用写入完成回调。
  12. 将读取请求提交至特定命名空间,从而提供队列对、缓冲区指示器、LBA 索引、已读取的数据回调,以及应传递至回调的数据的指示器:
    1 rc = spdk_nvme_ns_cmd_read(ns_entry->ns, ns_entry->qpair, sequence->buf,
    2                            0, /* LBA start */
    3                            1, /* number of LBAs */
    4                            read_complete, (void *)sequence, 0);
  13. 同时调用读取完成回调。
  14. 轮询表明数据读写均已完成的标记。 如果请求仍处于传输过程中,我们可以轮询特定队列对的完成情况。 尽管实际数据读写过程处于同步但 spdk_nvme_qpair_process_completions 函数会查看并返回已完成 I/O 请求的数量,并调用上述读/写完成回调:
    1 while (!sequence.is_completed) {
    2        spdk_nvme_qpair_process_completions(ns_entry->qpair, 0);
    3 }
  15. 退出之前需要释放队列对并进行清空:
    spdk_nvme_ctrlr_free_io_qpair(ns_entry->qpair);

github 提供有关上述 Hello World 应用的完整代码示例,有关 SPDK NVME 驱动程序的 API 文档请访问www.spdk.io

运行 Hello World 示例时将显示以下输出:

SPDK 中的其他示例

SPDK 包含许多示例,可帮助您快速入门并了解 SPDK 的工作原理。 perf 示例对 NVMe 硬盘进行了性能评测,以下为该示例的输出:

开发人员如需获取 NVMe 硬盘信息,比如特性、管理命令集属性、NVMe 命令集属性、能源管理和健康信息,可使用识别示例:

其他实用链接

  • SPDK 邮件列表
  • SPDK 网站
  • SPDK 文档
  • SPDK 支持存储变革视频 – 需注册才能观看
  • 智能存储加速库 (ISA-L) 助力加速存储算法视频
  • ISA-L 助力加速重复数据删除博客

作者

Steven Briscoe 是英特尔(英国)公司的一名应用工程师,在软件服务事业部负责云计算工作。

Thai Le 是英特尔公司的一名软件工程师,负责云计算和性能计算分析工作。

【转】SPDK 助力加速 NVMe 硬盘相关推荐

  1. MacBook Air 2014 安装NVME硬盘并纯UEFI安装和引导Win7

    前言: 本文是关于在苹果笔记本上安装NVME固态硬盘.纯UEFI安装及引导win7的实践,供电脑爱好者参考. 手里有一台MacBook Air(MBA) 2014,256G,跟现在的笔记本比较,性能肯 ...

  2. 新硬盘显示有储存空间但无法分区_容量更足高速无忧,奥睿科迅龙V500 NVME硬盘体验...

    经济宽松的时候总会想要折腾折腾各种电子设备啥的,特别是对笔记本,电脑啥的总想着升级升级,拥有更宽松的储存容量,用来安装更多的游戏,下载更精彩的视频,或者是从网上搜集搜集更多电纸书籍用于自己充电或者教育 ...

  3. 什么是NVMe硬盘?

    本文摘自:https://zhidao.baidu.com/question/590890784.html NVMe硬盘指的是非易失性内存主机控制器接口规范(Non-Volatile Memory e ...

  4. linux控制NVme硬盘点灯,一种实现多NVMe硬盘背板点灯的设计方法与流程

    本发明涉及服务器硬盘背板领域,具体来说涉及一种实现多NVMe硬盘背板点灯的设计方法. 背景技术: 随着CPU.显卡性能的不断提升,服务器的计算瓶颈逐渐向存储设备转移,存储技术也随之升级,硬盘传输速率从 ...

  5. 服务器nvme硬盘识别不了,NVMe硬盘无法安装win7怎么办|安装win7找不到nvme硬盘解决方法...

    现在很多固态硬盘采用的是NVMe新协议,如果安装win7系统,往往会找不到硬盘,在选择硬盘界面是空白,找不到这个nvme硬盘,因为win7系统没有集成nvme驱动,所以这种情况下nvme硬盘无法安装w ...

  6. VMware ESXi添加NVMe硬盘扩容

    18年春节,也就是2月份,我买了第一块NVMe固态硬盘,容量是250G,价格是499块,券后481块.当时对于这种读取2100 MBps,写入1300 MBps的高性能产品,我直呼太值了!毕竟当时SA ...

  7. 联想H61主板升级BIOS,支持nvme硬盘

    本教程升级有一定风险:请阅读文章最后的"遗憾"部分接受再升级 最近因为手上有一台联想的i7 2600主机,他的主板是H61的,正好看见pcie接口空着,在网上看见有人用它升级了拜滕 ...

  8. linux控制NVme硬盘点灯,硬盘点灯模式的设置方法及装置与流程

    本发明涉及自动化控制技术领域,更具体的,涉及一种硬盘点灯模式的设置方法及装置. 背景技术: 随着信息化的发展,客户对服务器的需求日益增多.不同客户在同款服务器机型中对硬盘配置参数可能要求各异,例如,一 ...

  9. (原创)修改BIOS让华硕Z87-A老主板支持NVMe硬盘启动(采坑实录)

    当年经典的华硕Z87-A主板至今仍然老当益壮,美中不足就是不支持NVMe SSD作为启动盘.由于工作生活繁忙,2年多来陆陆续续查了好多资料,再加上有CH341A编程器加持,自认已经准备得够充分.最近乘 ...

最新文章

  1. lua5.2调用c函数成功的例子
  2. 电脑下载python多少位的在哪看-python64位
  3. windows 取色器_这款 Windows 10 官方「外挂」让你取色更便捷
  4. 如何使用 Serverless Devs 部署静态网站到函数计算(上)
  5. 外网质量监控系统实践之路
  6. linux安装consul集群
  7. e-HR推动知识型企业人力资源管理提升
  8. 《21天学通C语言(第6版•修订版)》一1.7 问与答
  9. smplayer变成电视操作步骤
  10. 有关不平衡学习与SMOTE算法
  11. arm嵌入式led灯闪烁实验报告_ARM嵌入式系统与应用实验报告
  12. 物联网设备接入流程与平台架构
  13. 怎样把计算机添加到网络打印机,怎么将电脑打印机设置成连接网络打印机
  14. Python:存取npy格式数据
  15. c语言与程序设计曹计昌 答案,c语言与程序设计答案曹计昌
  16. NMAKE参考之二——运行NMAKE
  17. 计算机最快接口速度,实测:USB3.1究竟比USB3.0接口快多少?
  18. 完美实现PC端软件控制手机(无需安装任何APK)(一)
  19. 物联网的物流企业信息集成综合管理平台,主要有哪些特征?
  20. 波卡动态 | Moonbeam 上第一个3D NFT项目宣布合作

热门文章

  1. Hadoop分布式(最小集群)搭建(三台虚拟机)
  2. 前端 - HTML基础
  3. 离职员工讲述易到混乱:CEO在办公室煮面条、逼员工下跪
  4. 功率预测发展趋势之概率预测
  5. openCV数字图像处理
  6. 每个月总有几天愚人,愚自己
  7. tinyxml2解析rss文件
  8. 【DL】第 2 章 :变分自动编码器(VAE)
  9. 设置浏览器横屏可行性测试,附带浏览器全屏功能
  10. win mysql 错误日志_关于事件管理器中“应用程序”中显示windows error reporting的输入法报错日志...