《深入浅出DPDK》—第3章3.2节指令并发与数据并行

3.2 指令并发与数据并行
前面我们花了较大篇幅讲解多核并发对于整体性能提升的帮助,从本节开始,我们将从另外一个维度——指令并发,站在一个更小粒度的视角,去理解指令级并发对于性能提升的帮助。
3.2.1 指令并发
现代多核处理器几乎都采用了超标量的体系结构来提高指令的并发度,并进一步地允许对无依赖关系的指令乱序执行。这种用空间换时间的方法,极大提高了IPC,使得一个时钟周期完成多条指令成为可能。
图3-6中Haswell微架构流水线是Haswell微架构的流水线参考,从中可以看到Scheduler下挂了8个Port,这表示每个core每个时钟周期最多可以派发8条微指令操作。具体到指令的类型,比如Fast LEA,它可以同时在Port 1和Port 5上派发。换句话说,该指令具有被多发的能力。可以简单地理解为,该指令先后操作两个没有依赖关系的数据时,两条指令有可能被处理器同时派发到执行单元执行,由此该指令实际执行的吞吐率就提升了一倍。

虽然处理器内部发生的指令并发过程,对于开发者是透明的。但不同的代码逻辑、数据依赖、存储布局等,会影响CPU运行时指令的派发,最终影响程序运行的IPC。由于涉及的内容非常广泛,本书限于篇幅有限不能一一展开。理解处理器的体系结构以及微架构的设计,对于调优或者高效的代码设计都会很有帮助。这里推荐读者阅读64-ia-32架构优化手册,手册中会从前端优化、执行core优化、访存优化、预取等多个方面讲解各类技巧。
3.2.2 单指令多数据
在进入到什么是“单指令多数据”之前,先简单认识一下它的意义。“单指令多数据”给了我们这样一种可能,即使某条指令本身不再能被并(多)发,我们依旧可以从数据位宽的维度上提升并行度,从而得到整体性能提升。
3.2.2.1 SIMD简介
SIMD是Single-Instruction Multiple-Data(单指令多数据)的缩写,从字面的意思就能理解大致的含义。多数据指以特定宽度为一个数据单元,多单元数据独立操作。而单指令指对于这样的多单元数据集,一个指令操作作用到每个数据单元。可以把SIMD理解为向量化的操作方式。典型SIMD操作如图3-7所示,两组各4个数据单元(X1,X2,X3,X4和Y1,Y2,Y3,Y4)并行操作,相同操作作用在相应的数据单元对上(X1和Y1,X2和Y2,X3和Y3,X4和Y4),4对计算结果组成最后的4数据单元数。

SIMD指令操作的寄存器相对于通用寄存器(general-purpose register,RPRS)更宽,128bit的XMM寄存器或者256bit的YMM寄存器,有2倍甚至4倍于通用寄存器的宽度(在64bit架构上)。所以,用SIMD指令的一个直接好处是最大化地利用一级缓存访存的带宽,以表3-3所示Haswell微架构中第一级Cache参数为例,每时钟周期峰值带宽为64B(load)(注:每周期支持两个load微指令,每个微指令获取最多32B数据)+32B(store)。可见,该微架构单时钟周期可以访存的最大数据宽度为32B即256bit,只有YMM寄存器宽度的单指令load或者store,可以用尽最大带宽。

对于I/O密集的负载,如DPDK,最大化地利用访存带宽,减少处理器流水线后端因I/O访问造成的CPU失速,会对性能提升有显著的效果。所以,DPDK在多个基础库中都有利用SIMD做向量化的优化操作。然而,也并不是所有场景都适合使用SIMD,由于数据位较宽,对繁复的窄位宽数据操作副作用比较明显,有时数据格式调整的开销可能更大,所以选择使用SIMD时要仔细评估好负载的特征。
图3-8所示的128位宽的XMM和256位宽的YMM寄存器分别对应Intel? SSE(Streaming SIMD Extensions)和Intel? AVX(Advanced Vector Extensions)指令集。

3.2.2.2 实战DPDK
DPDK中的memcpy就利用到了SSE/AVX的特点。比较典型的就是rte_memcpy内存拷贝函数。内存拷贝是一个非常简单的操作,算法上并无难度,关键在于很好地利用处理器的各种并行特性。当前Intel的处理器(例如Haswell、Sandy Bridge等)一个指令周期内可以执行两条Load指令和一条Store指令,并且支持SIMD指令(SSE/AVX)来在一条指令中处理多个数据,其Cache的带宽也对SIMD指令进行了很好的支持。因此,在rte_memcpy中,我们使用了平台所支持的最大宽度的Load和Store指令(Sandy Bridge为128bit,Haswell为256bit)。此外,由于非对齐的存取操作往往需要花费更多的时钟周期,rte_memcpy优先保证Store指令存储的地址对齐,利用处理器每个时钟周期可以执行两条Load这个超标量特性来弥补一部分非对齐Load所带来的性能损失。更多信息可以参考[Ref3-3]。
例如,在Haswell上,对于大于512字节的拷贝,需要按照Store地址进行对齐。

/**
 * Make store aligned when copy size exceeds 512 bytes
 */
dstofss = 32 - ((uintptr_t)dst & 0x1F);
n -= dstofss;
rte_mov32((uint8_t *)dst, (const uint8_t *)src);
src = (const uint8_t *)src + dstofss;
dst = (uint8_t *)dst + dstofss;
在Sandy Bridge上,由于非对齐的Load/Store所带来的的额外性能开销非常大,因此,除了使得Store对齐之外,Load也需要进行对齐。在操作中,对于非对齐的Load,将其首尾未对齐部分多余的位也加载进来,因此,会产生比Store指令多一条的Load。
xmm0 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 0 * 16));
len -= 128;
xmm1 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 1 * 16));
xmm2 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 2 * 16));
xmm3 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 3 * 16));
xmm4 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 4 * 16));
xmm5 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 5 * 16));
xmm6 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 6 * 16));
xmm7 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 7 * 16));
xmm8 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 8 * 16));
src = (const uint8_t *)src + 128;
_mm_storeu_si128((__m128i *)((uint8_t *)dst + 0 * 16), _mm_alignr_epi8(xmm1, xmm0, offset));
_mm_storeu_si128((__m128i *)((uint8_t *)dst + 1 * 16), _mm_alignr_epi8(xmm2, xmm1, offset));
_mm_storeu_si128((__m128i *)((uint8_t *)dst + 2 * 16), _mm_alignr_epi8(xmm3, xmm2, offset));
_mm_storeu_si128((__m128i *)((uint8_t *)dst + 3 * 16), _mm_alignr_epi8(xmm4, xmm3, offset));
_mm_storeu_si128((__m128i *)((uint8_t *)dst + 4 * 16), _mm_alignr_epi8(xmm5, xmm4, offset));
_mm_storeu_si128((__m128i *)((uint8_t *)dst + 5 * 16), _mm_alignr_epi8(xmm6, xmm5, offset));
_mm_storeu_si128((__m128i *)((uint8_t *)dst + 6 * 16), _mm_alignr_epi8(xmm7, xmm6, offset));
_mm_storeu_si128((__m128i *)((uint8_t *)dst + 7 * 16), _mm_alignr_epi8(xmm8, xmm7, offset));
dst = (uint8_t *)dst + 128;
时间: 2024-08-28 08:07:39

《深入浅出DPDK》—第3章3.2节指令并发与数据并行的相关文章

《精通Wireshark》—第1章1.4节通过Wireshark进行数据包分析

1.4 通过Wireshark进行数据包分析 数据包分析(也称为数据包嗅探或协议分析)的作用是抓取在网络(以太网或WiFi)传输中的数据包,并且对其中的信息进行解答的过程,其目的在于了解网络中正在发生的情况.数据包分析需要借助像Wireshark这样的协议分析软件来实现,这些软件可以在互联网上进行下载.其中有些软件是免费的,也有一些软件需要付费才能用于商业目的.在本书中,我们会使用Wireshark来进行网络分析.Wireshark是一款开源软件,同时也是互联网上最优秀的免费网络分析软件. 在当

《深入浅出DPDK》目录—导读

引 言 动机 2015年4月,第一届DPDK中国峰会在北京成功召开.来自中国移动.中国电信.阿里巴巴.IBM.Intel.华为以及中兴的专家朋友登台演讲,一起分享了以DPDK为中心的技术主题.表1列出了2015 DPDK中国峰会的主题及演讲者. 这次会议吸引了来自各行业.科研单位与高校的200多名开发人员.专家和企业代表参会.会上问答交流非常热烈,会后我们就想,也许是时间写一本介绍DPDK.探讨NFV数据面的技术书籍.现在,很多公司在招聘网络和系统软件人才时,甚至会将DPDK作为一项技能罗列在招

《深入浅出DPDK》—第3章3.1节并行计算

第3章 并 行 计 算 处理器性能提升主要有两个途径,一个是提高IPC(每个时钟周期内可以执行的指令条数),另一个是提高处理器主频率.每一代微架构的调整可以伴随着对IPC的提高,从而提高处理器性能,只是幅度有限.而提高处理器主频率对于性能的提升作用是明显而直接的.但一味地提高频率很快会触及频率墙,因为处理器的功耗正比于主频的三次方. 所以,最终要取得性能提升的进一步突破,还是要回到提高IPC这个因素.经过处理器厂商的不懈努力,我们发现可以通过提高指令执行的并行度来提高IPC.而提高并行度主要有两

《深入浅出DPDK》—第2章2.5节Cache预取

2.5 Cache预取以上章节讲到了多种和Cache相关的技术,但是事实上,Cache对于绝大多数程序员来说都是透明不可见的.程序员在编写程序时不需要关心是否有Cache的存在,有几级Cache,每级Cache的大小是多少:不需要关心Cache采取何种策略将指令和数据从内存中加载到Cache中:也不需要关心Cache何时将处理完毕的数据写回到内存中.这一切,都是硬件自动完成的.但是,硬件也不是完全智能的,能够完美无缺地处理各种各样的情况,保证程序能够以最优的效率执行.因此,一些体系架构引入了能够

《Google软件测试之道》—第2章2.2节测试认证

本节书摘来自异步社区<Google软件测试之道>一书中的第2章2.2节测试认证,作者[美]James Whittaker , Jason Arbon , Jeff Carollo,更多章节 2.2 测试认证 Patrick Copeland在本书的序中强调了让开发人员参与测试的难度.招聘到技术能力强的测试人员只是刚刚开始的第一步,我们依然需要开发人员参与进来一起做测试.其中我们使用的一个 关键方法就是被称为"测试认证"(译注:Test Certified)的计划.现在回过头

《C++ 黑客编程揭秘与防范(第2版)》—第6章6.3节PE结构的3种地址

6.3 PE结构的3种地址 C++ 黑客编程揭秘与防范(第2版) 在上一章中用OD调试器调试程序时看到的地址与本章使用C32Asm以十六进制形式查看程序时的地址形式有所差异.程序在内存中与在文件中有着不同的地址形式,而且PE相关的地址不只有这两种形式.与PE结构相关的地址形式有3种,且这3种地址形式可以进行转换. 6.3.1 与PE结构相关的3种地址 与PE结构相关的3种地址是VA(虚拟地址).RVA(相对虚拟地址)和FileOffset(文件偏移地址). VA(虚拟地址):PE文件映射到内存后

《Wireshark网络分析实战》—第1章1.1节 Wireshark简介

第1章 Wireshark简介 Wireshark网络分析实战 本章涵盖以下内容: 安置Wireshark(主机/程序): 开始抓包: 配置启动窗口: 配置时间参数: 调整配色规则: 保存.打印及导出数据: 配置用户界面(点击EDIT菜单的Preferences菜单项,会弹出Preferences窗口.所谓配置用户界面,就是配置该窗口中User Interface配置选项里的内容): 配置协议参数(即配置Preferences窗口中Protocol配置选项里的内容). 1.1 Wireshark

《C++ 黑客编程揭秘与防范(第2版)》—第6章6.4节PE相关编程实例

6.4 PE相关编程实例 C++ 黑客编程揭秘与防范(第2版) 前面讲的都是概念性的知识,本节主要编写一些关于PE文件结构的程序代码,以帮助读者加强对PE结构的了解. 6.4.1 PE查看器 写PE查看器并不是件复杂的事情,只要按照PE结构一步一步地解析就可以了.下面简单地解析其中几个字段内容,显示一下节表的信息,其余的内容只要稍作修改即可.PE查看器的界面如图6-26所示. PE查看器的界面按照图6-26所示的设置,不过这个可以按照个人的偏好进行布局设置.编写该PE查看器的步骤为打开文件并创建

《Wireshark数据包分析实战(第2版)》—第6章6.1节地址解析协议

第6章 通用底层网络协议 Wireshark数据包分析实战(第2版) 无论是处理延迟问题,还是甄别存在错误的应用,抑或对安全威胁进行聚焦检查,都是为了发现异常的流量,而你必须首先了解正常的流量.在下面的几章中,你将会学到正常的网络流量在数据包级别是如何工作的. 我们将介绍最常见的几种协议,包括最基础的TCP.UDP和IP,以及如HTTP.DHCP.DNS等最常用的应用层协议.在每个协议的相关部分,都会至少有一个捕获文件供你下载,并可以让你直接上手分析.在这一章中,我们将着重关注在OSI分层模型中