【96】write combine机制介绍


前言

这篇文章主要介绍了write combine的机制


一、write combine的试验

1.系统配置

(1)、CPU:11th Gen Intel(R) Core(TM) i7-11700 @ 2.50GHz

(2)、GPU:XX

(3)、link status:X16 GEN4(受限于CPU能力)

(4)、主板: TUF GAMING B560M-PLUS

(5)、linux  5.15.0-107-generic,ldd (Ubuntu GLIBC 2.31-0ubuntu9.16) 2.31

注意:CPU write combine受到CPU write combine buffer大小、write combine buffer entry数量、CPU的运行频率以及CPU evict write combine buffer的策略影响非常大,因此,绝对速率和CPU有关,这里只需要关注两种情况下,速率提高比例就可以了。

2、数据对比

    可见使用memcpy 把32M数据从system main memory拷贝的到GDDR,开启write combine后,CPU写的性能提供了13.3倍。这是怎么做到的呢?在讲write combine前需要先讲一下处理器的memory system,以及memory system中的cache。

二、背景知识:X86下的memory system

1、X86下的memory system简介

    上图中的白色框就是memory system的组件。其中main memory在处理器芯片外,是离processor execution units最远的。

    Cache是离processor execution units(处理器中负责执行指令和计算操作的部分)最近的。图中只是画了三种cache(L1 instruction cache、L1 data cache、L2 cache),实际上,对于多CPU core还有L3 cache。不同的微架构,L1/L2/L3的功能可能不太相同,但是基本原理差不多。

    L1 cache和L2 cache一般是每个core都有自己独立的,只是L1 cache通常会被分成L1 data cache和L1 instruction cache ,而L2 cache的data 和instruction是合一的。

2、skylake CPU的cache hierarchy

    下图是intel skylake CPU的 cache hierarchy(缓存层次结构),可看到每个CPU core有自己独立的L1和L2 cache,但是L3 cache(LLC)是share给所有的processors的。

    在L2 cache和L3 cahce之间是L2 Snoop Filter, 是skylake架构中的一个缓存一致性机制。L2 Snoop Filter通过减少不必要的snoop请求(记录缓存数据的位置),来减少的缓存之间的通信开销,提高缓存一致性协议的效率。

    所谓缓存一致性就是在多核处理器系统中,各个核的缓存需要保持一致性,以确保不同核访问同一内存地址时,数据是一致的。当一个核需要访问另一个核的缓存数据时,会发出 snoop 请求。这种请求会在总线上广播,以检查其他缓存中是否有该数据。

    关于snoop,Intel64 andlA-32 Architectures Software Developer's Manual的11.2 CACHING TERMINOLOGY讲得比较清楚了。

    在MP(多处理器)系统中,像Intel486和Intel 64这样的处理器具有snoop(侦听、监视)其他处理器访问system memory和访问处理器internal cache的能力,也就是所谓的“snoop”。 Snoop的功能让处理器的internal cache与system memory和总线上其他处理器中的cache保持一致。

     例如,在Pentium和P6系列处理器中,通过侦听功能,如果处理器A检测到另一个处理器打算写一块memory location,而这块memory location已经自己被cache了,侦听处理器A就会invalidate自己的cache line,强制让自己在下一次访问相同的memory location时执行cache line fill的操作(从system memory来获取最新的数据)。

    从P6系列处理器开始,如果一个处理器A检测到另一个处理器正在尝试访问一块memory location,而这块memory location已经在自己的cache中修改,但尚未写回到system memory,那么侦听处理器A将向其他处理器发出HITM#信号(Hold In Transaction Mode),这个信号告诉另一个处理器该cache line处于modify状态。

    在这种情况下,具有有效修改数据的处理器可能会直接将此数据传递给其他处理器,而不立即将其写回system memory中。负责管理系统内存的memroy controller监视此操作,以确保系统内存最终得到最新的数据。因此,即使数据可能在处理器之间共享而不立即写回内存,内存控制器也确保系统内存最终反映出最新的数据。。

    也就说,任何一个处理器别想偷偷干坏事(让自己的internal cache和其他处理的internal cache不一致),其他处理器一直在偷偷看着呢。

3、memory type(cache type)

    前面说了那么多,就是为了引出cache type(memory type),Intel 64和IA-32架构定义下面的memory type。

    对WC类型的memory的写操作可能会delay并被combine在write combing buffer中,因此来减少memory access。如果WC buffer只是部分填充,write会被delay直到下一个串行事件发生,比如SFENCE或者MFENCE指令,CPUID或者其他串行指令,read或者write uncached memory,中断产生,或者执行LOCK指令。

    WC 类型的cache-control非常适合video frame buffer,因为写order不重要。只要写入操作更新了内存,显示内容能够正确地显示在屏幕上即可。换句话说,即使写入操作的顺序不同,只要最终的内存状态能够正确反映出视频内容,就可以保证画面的正常显示。

4、Write combining buffer

    往WC memory的写的数据会被保存在internal write combining buffer,这个buffer和L1/L2/L3 cache是不同的(见前面的Figure 7-1. Processor and Memory System)。WC buffer没有snoop功能,因此,不能提供数据一致性。

    WC缓冲区的大小和结构在本架构文档上没有定义(也就说是vendor specific的)。对于Intel Core 2 Duo、Intel Atom、Intel Core Duo、Pentium M、Pentium 4和Intel Xeon处理器,WC缓冲区由若干个64字节的WC缓冲区组成。对于P6系列处理器,WC缓冲区由若干个32字节的WC缓冲区组成

    当软件开始向WC内存写入数据时,处理器就开始逐个填充WC缓冲区当一个或多个WC缓冲区被填满后,处理器可以选择将数据从write combining buffer evict到system memory。WC缓冲区evict协议取决于厂商具体的实现,软件不能依赖此协议来确保系统内存的一致性。使用WC内存类型时,软件必须要注意:数据延迟写入系统内存,并在需要系统内存一致性时,需要软件主动清空WC缓冲区

    一旦处理器开始从WC缓冲区将数据evict到系统内存,它将基于缓冲区中包含的有效数据量做bus-transaction style的决策。如果缓冲区已满(例如,所有字节都是有效的),处理器将在总线上执行一个burst-write transaction。一个burst-write transaction会有32字节(P6系列处理器)64字节(奔腾4及更高版本处理器)的数据会传输到data bus上。如果WC缓冲区的数据有一个或多个字节是无效的(例如,尚未被软件写入),处理器将使用“partial”transaction将数据传输到内存(一次一个chunk,其中一个“chunk”是8字节)。

    “partial”transaction将导致将WC缓冲区中的数据发送到内存时最多进行4个(32/8)“partial”transaction(对于P6系列处理器)或8个(64/8)“partial”transaction(对于奔腾4及更高版本处理器)。

    WC内存类型在定义上是weakly order的。一旦开始evict WC缓冲区中的数据,数据就受到weakly order的影响。在连续分配/释放WC缓冲区时不会保持顺序(例如,对WC缓冲区1的写入后,然后对WC缓冲区2的写入,可能在系统总线上看起来是缓冲区2先于缓冲区1)。使用partial write把数据从WC缓冲区中evict到system memory时,连续部分写之间也没有保证的顺序(例如,chunk 2的partial write可能在总线上先于chunk 1的partial write,反之亦然)。

三、Linux中Write combine相关函数

1、使能PAT的debug打印

    关于pat的介绍可以参考

13. PAT (Page Attribute Table) — The Linux Kernel documentation

    在cmdline增加debugpat就可以让dprintk打印

    下面的打印就是我们cmdline增加debugpat,然后调用对应的API接口时,OS的打印:

[28168.324996] x86/PAT: memtype_reserve added [mem 0x6000000000-0x67ffffffff], track write-combining, req write-combining, ret write-combining

[28168.325001] mtgpu 0000:01:00.0: Enable mtrr success,base:0x6000000000,size:0x800000000, mtrr 0.

[28168.325006] x86/PAT: Overlap at 0xa4a00000-0xa4a48000

[28168.325009] x86/PAT: memtype_reserve added [mem 0xa4000000-0xa5ffffff], track uncached-minus, req uncached-minus, ret uncached-minus

[28168.325021] mtgpu 0000:01:00.0: PCIe BAR0 map start:0xa4000000 size:0x2000000, virtal addr:00000000d90d9aa4 (attribution: UC)

[28168.325028] x86/PAT: Overlap at 0x6000000000-0x6800000000

[28168.325030] x86/PAT: memtype_reserve added [mem 0x6000000000-0x67ffffffff], track write-combining, req write-combining, ret write-combining

[28168.325038] mtgpu 0000:01:00.0: PCIe BAR2 map start:0x6000000000 size:0x800000000, virtal addr:00000000542d4401 (attribution: WC)

2、debugFS中PAT

    cat /sys/kernel/debug/x86/pat_memtype_list,在我们drv中调用对应API后,debugFS会显示对应的page attribute。

    Linux 代码中的实现如下:

 3、API接口

3.1 arch_io_reserve_memtype_wc

4.9.0增加了arch_io_reserve_memtype_wc

[PATCH 1/2] x86/io: add interface to reserve io memtype for a resource range. - Dave Airlie

memtype.c - arch/x86/mm/pat/memtype.c - Linux source code (v5.15) - Bootlin

3.2 memtype_reserve_io

arch_io_reserve_memtype_wc->memtype_reserve_io

memtype.c - arch/x86/mm/pat/memtype.c - Linux source code (v5.15) - Bootlin

3.3 memtype_reserve

arch_io_reserve_memtype_wc->memtype_reserve_io->memtype_reserve

memtype.c - arch/x86/mm/pat/memtype.c - Linux source code (v5.15) - Bootlin

    memtype_reserve是API调用栈的核心代码,主要实现下面功能

(1)memtype_reserve->pat_x_mttr_type来获取actual_type,

(2)然后memtype_reserve->pat_pagerange_is_ram来检查start和end是否不是RAM

./kprobe 'r:myopen pat_pagerange_is_ram $retval'

    使用kprobe查看pat_pagerange_is_ram的返回值,当传入的start和end是MMIO地址的话,pat_pagerange_is_ram返回是的0。

(3)申请一个entry_new,memtype_reserve->memtype_check_insert,把新的entry插入到memtype_rbroot

./kprobe 'r:myopen pat_pagerange_is_ram $retval'

3.4 memtype_check_insert

arch_io_reserve_memtype_wc->memtype_reserve_io->memtype_reserve->memtype_check_insert

memtype_interval.c - arch/x86/mm/pat/memtype_interval.c - Linux source code (v5.15) - Bootlin

3.5、哪些接口会调用memtype_check_insert

./kprobe -s 'p:myprobe memtype_check_insert'

可以看到涉及到使用MMIO的下面接口都会调用memtype_check_insert

3.6、ioremap和ioremap_wc区别

ioremap.c - arch/x86/mm/ioremap.c - Linux source code (v5.15) - Bootlin

    ioremap和ioremap_wc区别就是传入的page attribute不一样。最终还是会调用memtype_check_insert把对应的entry放到memtype_rbroot。

3.7 arch_phys_wc_add

linux kernel 3.11.0增加了arch_phys_wc_add

如果pat_enable已经enable或者mtrr_enable没有enable,arch_phys_wc_add直接返回了。

四、开启write combine后访问MMIO提升的原因

    回到我们最初的问题,使用memcpy 把32M数据从system main memory拷贝的到GDDR,开启write combine后,CPU写的性能提供了13.3倍。这是怎么做到的呢?在回答这个问题前,我们先看看两种场景下PCIe trace的差异。

1、disable write combine时PCIe trace

    我们从PCIe trace上看到第一笔写到最后一笔写,耗时是90753us,和测试代码抓到的耗时(90707us)一致。

    分析trace可以发现,disable write combine时,所有写请求都是32byte的,32M的数据需要32M/32= 1,048,576笔操作。

    这里为啥每一笔写请求都是32byte,而不是4byte的,和glibc对于memcpy的实现有关系,这里不展开说明,有兴趣的看glibc的memcpy作者马凌的回答。

https://www.zhihu.com/question/35172305

    随机找了两笔相邻的请求,时间间隔93ns,看了一下统计基本上在80-100ns之间,个别可能超过100ns。1,048,576笔传输,耗时90753us,每传输32Byte耗时90753us/1,048,576=86.5ns,每传输64Byte需要耗时173ns。

2、enable write combine时PCIe trace

    我们从PCIe trace上看到第一笔写到最后一笔写,耗时是6836us,和测试代码抓到的耗时(6837us)一致。

    分析trace可以发现,disable write combine时,所有写请求都是64byte的(和前面intel architecture介绍的WC buffer是64Byte是吻合的),32M的数据需要32M/64= 524,288笔操作。

    随机找了两笔相邻的请求,时间间隔8ns,看了一下统计差异比较大,大部分都在10~20ns之间。524,288笔传输,耗时6837us,每传输64Byte耗时6837us/524,288= 13ns,数据是吻合的。

    猜测每次时间间隔比较大的时候,都是处理器在fill WC buffer的时候(只是猜测,没有datasheet没法证明),只是这种猜测符合WC memory delay and combine的设计。


总结

    使用memcpy 把32M数据从system的main memory拷贝的到GDDR,开启write combine后,CPU写的性能提供了13.3倍,主要原因不是写的transaction的combine(transaction数量只少了一半),而在于数据先处理器被从main memory预取到write combine buffer,然后从write combine buffer使用burst 传输方式推送system bus提供传输效率,这个时间(10多ns)比从main memory的时间短的多(100多ns)。

     上图中architecture中的这两段话值得多读几遍,这是为什么write combine可以提高CPU写的原因所在。

    手上没有11th Gen Intel(R) Core(TM) i7-11700 @ 2.50GHz的资料,只有一个skylake的资料,看到从main memory读大概需要167*0.5(2GHz)需要83ns,考虑到server级别的CPU,而11th Gen Intel(R) Core(TM) i7-11700 @ 2.50GHz是消费级别的CPU,会被skylake弱一些,我们抓的数据是符合预期的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/24174.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL(四) - SQL优化

一、SQL执行流程 MySQL是客户端-服务器的模式。一条SQL的执行流程如下: 在执行过程中,主要有三类角色:客户端、服务器、存储引擎。 大致可以分为三层: 第一层:客户端连接到服务器,构造SQL并发送给服务器…

惠海 H5528 升降压芯片 12V24V36V48V60V75V LED恒流驱动IC 调光细腻顺滑无阶梯感

惠海H5528是一款升压、降压、升压降压的LED恒流驱动IC,其具备宽范围调光比且无频闪调光的特性,使得它在智能照明、Dali调光、0~10V调光、摄影灯照明以及补光灯照明等多种应用中具有广泛的应用前景。 这款芯片支持降压、升压和升降压拓扑的应用&#xff0…

C++面向对象程序设计 - 文件操作与文件流

在实际应用中,常以磁盘文件作为对象,即能从磁盘文件读取数据,也能将数据输出到磁盘文件,磁盘是计算机的外部存储器,能够长期保留信息,能读能写,可以刷新重写等等。 在C中,文件操作通…

106.网络游戏逆向分析与漏洞攻防-装备系统数据分析-在UI中显示装备与技能信息

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 如果看不懂、不知道现在做的什么,那就跟着做完看效果,代码看不懂是正常的,只要会抄就行,抄着抄着就能懂了 内容…

新媒体暴力起号必备因素!沈阳新媒体运营培训学校

1周涨粉10w?这对普通人来说可以说是天文数字,但只要掌握方式方法,普通人也能做到! 面试经验丰富的人都深知,给面试官留下的第一印象相当重要,几乎决定了80%的面试机会。标题也是如此,在完成一篇…

[经验] 蝉联一词的含义是什么 #知识分享#职场发展

蝉联一词的含义是什么 蝉联这个词起源于古代中国,最初是指天子连续两年以上的年号相同。后来,这个词被用于形容某个人或某个团体连续多次获得某种荣誉或奖项的情况。在现代生活中,我们常常听到某个体育运动员蝉联冠军、某个企业蝉联业绩排行榜…

基于拓扑漏洞分析的网络安全态势感知模型

漏洞态势分析是指通过获取网络系统中的漏洞信息、拓扑信息、攻击信息等,分析网络资产可能遭受的安全威胁以及预测攻击者利用漏洞可能发动的攻击,构建拓扑漏洞图,展示网络中可能存在的薄弱环节,以此来评估网络安全状态。 在网络安…

科普|大数据风险检测对申贷人有哪些好处?

大数据风险检测可以极大地提高金融机构在用户肖像、反欺诈和信用评级等方面的效率和风险控制能力,这是金融企业发展过程中必须结合的一种科技技术。大数据风险检测覆盖信贷领域的所有流程,从客户获取到身份验证,再到信贷中和信贷后。因此&…

电赛报告书写

一、总体要求 (1)摘要:一页,小于300字 (2)正文:不超过8页 (3)附录:可以没有,但是不能超过2页 二、摘要书写 摘要要小于等于300字&#xff0c…

实现飞书机器人推送消息到指定群组或者用户

实现飞书机器人推送消息到指定群组或者用户 1 简介2 创建飞书应用2.1 注册登录2.2 创建应用2.3 添加应用能力2.4 权限管理3 发布应用4 代码示例4.1 获取应用ID与token4.2 使用Python SDK4.3 简单示例4.4 获取用户或机器人所在的群列表4.5 通过手机号或邮箱获取用户 ID4.6 给群组…

生活使用英语口语柯桥外语学校成人英语学习

● “自来水”英语怎么说? ● “自来水”的英语表达是:Running water或者Tap water. 例句: There are hot and cold running water in all the bedrooms. 所有的卧室里都有冷热自来水。 ● “热水”英文怎么水? ● 我们不管…

C++设计模式——Adapter适配器模式

一,适配器模式简介 适配器模式是一种结构型设计模式,用于将已有接口转换为调用者所期望的另一种接口。 适配器模式让特定的API接口可以适配多种场景。例如,现有一个名为"Reader()"的API接口只能解析txt格式的文件,给这…

【css3】png图片实现动态动画

.border_style {width: 400px;height: 400px;background-color: black;margin: auto;}keyframes sprite-animation {0% {background-position: 0 0;}100% {background-position: 0 -2064px;/* 假设每个图像的宽度为100px */}}.wrj_box {width: 86px;height: 86px;background-im…

STL中stack和queue模拟实现+容器适配器

目录 容器适配器 STL标准库中stack和queue的底层结构 deque的简单介绍 deque的缺陷 为什么选择deque作为stack和queue的底层默认容器 stack的模拟实现 queue的模拟实现 容器适配器 适配器是一种设计模式(设计模式是一套被反复使用的,多数人知晓…

OpenAI模型规范概览

这是OpenAI对外分享的模型规范文档(Model Spec),它定义了OpenAI希望在API接口和ChatGPT(含GPT系列产品)中模型的行为方式,这也是OpenAI超级对齐团队奉行的行为准则,希望能对国内做RLHF的同学有帮…

阿里云对象存储OSS简单使用

文章目录 概念基本概念Bucket 准备工作控制台操作对象存储OSSJava客户端操作对象存储OSS参考来源 概念 基本概念 阿里云对象存储 OSS是一款海量、安全、低成本、高可靠的云存储服务,提供最高可达 99.995 % 的服务可用性。而且提供了多种存储类型,降低我…

SemiDrive X9H 平台 QT 静态编译

一、 前言 芯驰 X9H 芯片,搭载多个操作系统协同运行,系统实现了仪表、空调、中控、副驾多媒体的四屏驱动控制,在人车智能交互上可以通过显示屏、屏幕触摸控制、语音控制、物理按键控制、车身协议的完美融合,使汽车更智能。让车主…

算法:94. 二叉树的中序遍历

给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。 示例 1: 输入:root [1,null,2,3] 输出:[1,3,2]示例 2: 输入:root [] 输出:[]示例 3: 输入:root [1] 输出&am…

静态IP代理服务对比:哪些提供商值得信赖?静态ip代理哪家好用?

当涉及选择静态IP代理时,许多人可能会感到困惑,因为市场上存在着各种各样的选项。本文旨在为您提供一些关键指导,帮助您确定哪种静态IP代理是最适合您需求的。在这个过程中,我们将介绍一个备受推崇的解决方案——太阳HTTP。 1.高速…

拥抱生态农业,享受绿色生活

随着人们对健康生活的追求日益增强,生态农业逐渐成为人们关注的焦点。我们深知生态农业对于保护生态环境、提高农产品品质的重要性,因此,我们积极推广生态农业理念,让更多的人了解并参与到生态农业的实践中来。 生态农业的蓝总说&…