热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

分段寄存器的mov是否比通用寄存器的mov慢?

如何解决《分段寄存器的mov是否比通用寄存器的mov慢?》经验,为你挑选了1个好方法。

具体是:

mov %eax, %ds

慢于

mov %eax, %ebx

或者他们是相同的速度.我在网上研究过,但一直无法找到明确的答案.

我不确定这是否是一个愚蠢的问题,但我认为修改分段寄存器可以使处理器做额外的工作.

NB我关注旧的x86 linux cpus,而不是现代的x86_64 cpus,其中分段的工作方式不同.



1> Peter Cordes..:

mov %eax, %ebx通用寄存器之间是常用的指令之一.现代硬件非常有效地支持它,通常具有不适用于任何其他指令的特殊情况.在较旧的硬件上,它始终是最便宜的指令之一.

在Ivybridge及更高版本中,它甚至不需要执行单元并且具有零延迟.它在寄存器重命名阶段处理. x86的MOV真的可以"免费"吗?为什么我不能重现这个呢? 即使在早期的CPU上,任何ALU端口都是1 uop(因此通常每个时钟吞吐量为3或4).

在AMD Piledriver/Steamroller mov r32,r32和r64上,r64可以在AGU端口和ALU端口上运行,每个时钟吞吐量为4,而每个时钟有2个用于添加,或者用于mov8或16位寄存器(必须合并到目的地).


mov在典型的32位和64位代码中,段reg是一种相当罕见的指令.它是内核为每个系统调用(可能是中断)所做的事情的一部分,因此使其高效将加速系统调用和I/O密集型工作负载的快速路径.因此即使它只出现在少数地方,它也可以运行相当数量.但与之相比,它仍然不太重要mov r,r!

mov 段REG慢:它触发从GDT或LDT更新描述符缓冲的负载,所以它的微码.

即使在x86-64长模式下也是如此 ; 在段基/极限字段的GDT项被忽略,但它仍然有更新与其他领域的描述符缓冲段描述符,其中包括不适用于数据段的DPL(描述符特权级).


Agner Fog的指令表列出mov sr, r了Nehalem和早期CPU的uop计数和吞吐量(Intel synax,mov to segment reg).他不再为以后的CPU测试seg regs,因为它很模糊而且没有被编译器使用(或者人工优化),但SnB系列的数量可能有些相似.( InstLatx64也不测试seg regs,例如不在此 Sandybridge指令定时测试中)

MOV sr,r在Nehalem上(可能在保护模式或长模式下测试):

前端有6个融合域uops

ALU端口3个uop(p015)

装载端口为3 uops(p2)

吞吐量:每13个周期1个(在巨型循环中重复该指令数千次).IDK,如果CPU重命名段regs.如果没有,它可能会延迟以后的加载(或所有后来的指令?),直到更新描述符缓存并且mov to sr指令退出.即我不确定这会对周围代码的无序执行产生多大影响.

其他CPU类似:

PPro/PII/PIII(原始P6):p0为8 uops,未列出吞吐量.5周期延迟.(请记住,这个uarch是在1995年发布之前设计的,当时16位代码仍然很常见.这就是P6系列为整数寄存器(AL,AH与AX分开)进行部分寄存器重命名的原因)

奔腾4:4 uops + 4微码,14c吞吐量.

延迟= 12c 16位实数或vm86模式,32位保护模式下24c.12c是他在主表中列出的,所以可能他的其他CPU的延迟数也是实模式延迟,其中写一个段reg只是设置base = sreg<<4.)

与其他CPU不同,在P4上读取段reg很慢:4 uops + 4个微码,6c吞吐量

P4 Prescott:1 uop + 8微码.27c吞吐量. 读取段reg = 8c吞吐量.

Pentium M:p0为8 uops,与PIII相同.

Conroe/Merom和Wolfdale/Penryn(第一代和第二代Core2):8个融合域uop,4个ALU(p015),4个负载/ AGU(p2).每16个周期吞吐量一个,是Agner测试它的任何CPU中最慢的.

Skylake(我的测试用我在循环外读取的值重新加载它们):在一个只有dec/jnz的循环中:10个融合域uops(前端),6个unfused-domain(执行单元).每18c吞吐量一个.

在写入4个不同 seg regs(ds/es/fs/gs)的循环中,都使用相同的选择器:mov每25c吞吐量4 个,6个融合/未融合域uop.(也许有些人被取消了?)

在写入ds4次循环中:每72c一次(mov ds,eax每18c一次).相同的uop计数:~6个融合和未融合mov.

这似乎表明Skylake 没有重命名段regs:写入一个必须在下一次写入开始之前完成.

K7/K8/K10:6"操作",8c吞吐量.

原子:7 uops,21c吞吐量

通过Nano 2000/3000:未列出的uops,20个周期的吞吐量和延迟.Nano 3000具有0.5个循环吞吐量,用于读取 seg reg(mov r, sr).没有列出延迟,这很奇怪.也许他正在测量seg-write延迟,以便何时可以将它用于负载?喜欢mov eax, [ebx]/ mov ds, eax在循环中?

奇怪的Al是对的,它是关于Pentiums的全部

按顺序Pentium(P5/PMMX)有更便宜的mov-to-sr:Agner将其列为"> = 2个循环",并且不可配对.(P5是有序的2-wide superscalar,有一些配对规则,指令可以一起执行).这似乎对保护模式来说很便宜,所以2可能处于实模式,而保护模式可能大于?我们从他的P4表中了解到他当时以16位模式测试过.


Agner Fog的微型指南说Core2/Nehalem可以重命名段寄存器(第8.7节注册重命名):

可以重命名所有整数,浮点,MMX,XMM,标志和段寄存器.浮点控制字也可以重命名.

(Pentium M 无法重命名FP控制字,因此更改舍入模式会阻止FP指令的OoO执行.例如,所有早期的FP指令必须先完成才能修改控制字,后来才能在之后启动.I猜段段regs是相同的,但对于加载和存储uops.)

他说Sandybridge可能"可能"重命名段regs,Haswell/Broadwell/Skylake可以"或许"重命名它们.我对SKL的快速测试表明,重复编写相同的段reg比写入不同的段reg更慢,这表明它们没有完全重命名.删除支持似乎是一件显而易见的事情,因为它们在普通的32/64位代码中很少被修改.

并且每个seg reg通常一次只修改一次,因此对于相同的段寄存器而言,多个dep链在飞行中并不是非常有用.(即,你不会在Linux中看到针对段注册的WAW危险,而WAR几乎不相关,因为内核不会在内核入口点使用用户空间的DS进行任何内存引用.(我认为中断是序列化的,但是通过进入内核syscall可能仍然有用户空间加载或存储在飞行中但尚未执行.)

在第2章中,它解释了无序执行程序(除了P1/PMMX之外的所有CPU),2.2寄存器重命名表示"可能会重命名段寄存器",但IDK如果他意味着某些CPU可以执行,而某些CPU则需要重命名t,或者如果他不确定一些旧的CPU.他没有提到PII/PII或Pentium-M部分中的seg reg重命名,所以我不能告诉你关于你显然要问的旧32位CPU.(而且他在K8之前没有针对AMD的微型指南部分.)

如果您对性能计数器感到好奇,您可以自己进行基准测试.(请参阅是否加载并存储重新排序的唯一指令?有关如何测试阻止无序执行的示例,并且x86的MOV真的可以"免费"吗?为什么我不能重现这个?)了解perf在Linux 上使用微小循环上的微基准测试的基础知识.


阅读段注册

mov 来自段寄存器相对便宜:它只修改了一个GP寄存器,并且CPU擅长写入GP寄存器,使用寄存器重命名等.Agner Fog发现它在Nehalem上只是一个uop.有趣的是,在Core2/Nehalem上它运行在加载端口上,所以我猜这就是段regs存储在该微体系结构上的地方.

(除了P4:显然在那里阅读seg regs是昂贵的.)

对我的Skylake进行快速测试(在长模式下)显示mov eax, fs(或者cs或者ds其他)是2 uops,其中一个只在端口1上运行,另一个可以在p0156上运行.(即它在ALU端口上运行).它的吞吐量为每时钟1个,在端口1上有瓶颈.


您通常只使用FS或GS进行线程本地存储,而不是使用movFS,您进行系统调用以使用OS wrfsbase来修改缓存段描述中的段基.


NB我关注旧的x86 linux cpus,而不是现代的x86_64 cpus,其中分段的工作方式不同.

你说"Linux",所以我假设你的意思是保护模式,而不是真实模式(分割的工作方式完全不同).mov sr, r在实模式下可能以不同的方式进行解码,但我没有测试设置,我可以使用性能计数器进行配置文件,以实现本机运行的真实或VM86模式.

长模式下的FS和GS基本上与保护模式下的相同,它是在长模式下"绝育"的其他seg reg.我认为Agner Fog的Core2/Nehalem数字可能类似于您在保护模式下的PIII中看到的数字.他们是同一个微体系结构家族的一部分.我认为在保护模式下P5奔腾段寄存器写入没有一个有用的数字.

(Sandybridge是源自P6系列的新系列中的第一个,具有显着的内部变化,而P4的一些想法实现了不同的(更好的)方式,例如SnB的解码uop缓存不是跟踪缓存.但更重要的是,SnB使用一个物理寄存器文件,而不是在ROB 中保持,所以它的寄存器重命名机制是不同的.)


推荐阅读
  • 线程能否先以安全方式获取对象,再进行非安全发布? ... [详细]
  • ButterKnife 是一款用于 Android 开发的注解库,主要用于简化视图和事件绑定。本文详细介绍了 ButterKnife 的基础用法,包括如何通过注解实现字段和方法的绑定,以及在实际项目中的应用示例。此外,文章还提到了截至 2016 年 4 月 29 日,ButterKnife 的最新版本为 8.0.1,为开发者提供了最新的功能和性能优化。 ... [详细]
  • TypeScript 实战分享:Google 工程师深度解析 TypeScript 开发经验与心得
    TypeScript 实战分享:Google 工程师深度解析 TypeScript 开发经验与心得 ... [详细]
  • 深入解析Go语言的编译与执行流程
    上一篇我们探讨了Golang在多种操作系统中的安装方法,并通过一个经典的HelloWorld示例进行了实践。在此过程中,我们使用了`gorun`命令,该命令能够一次性完成从源代码编译到程序执行的全过程。本文将深入剖析这一流程,揭示其背后的机制。实际上,`gorun`的功能可以视为`go build`与直接运行可执行文件的结合。在Golang的构建过程中,`go build`工具负责将源代码编译成二进制文件,这是生成可执行程序的关键步骤。 ... [详细]
  • 2017-09-07前端日报精选JavaScriptEventLoop机制详解与Vue.js中实践应用Redux基础与实践如何用js获取虚拟键盘高度?( ... [详细]
  • mybatis相关面试题 ... [详细]
  • 本文通过对OkHttp源码的详细解读,旨在帮助读者理解其核心执行流程,特别是同步与异步请求的处理方式。文中不仅涵盖了基本的使用示例,还深入探讨了OkHttp的核心功能——拦截器链的工作原理。 ... [详细]
  • 为了和DSP兼容,TSint64和TUint64设置成TSint40和TUint40一样的数结果VC中还是认为是32位的,显然不合适typedefsig ... [详细]
  • 【java】关键字、代码块、接口、枚举学习笔记
    主要内容1关键字2代码块3接口4枚举1Java中的关键字1.1static关键字用一句话说就是:可以直接通过对象.的形式使用,不用new实 ... [详细]
  • 本文通过分析一个具体的案例,探讨了64位Linux系统对32位应用程序的兼容性问题。案例涉及OpenVPN客户端在64位系统上的异常行为,通过逐步排查和代码测试,最终定位到了与TUN/TAP设备相关的系统调用兼容性问题。 ... [详细]
  • 解决Only fullscreen opaque activities can request orientation错误的方法
    本文介绍了在使用PictureSelectorLight第三方框架时遇到的Only fullscreen opaque activities can request orientation错误,并提供了一种有效的解决方案。 ... [详细]
  • 浏览器作为我们日常不可或缺的软件工具,其背后的运作机制却鲜为人知。本文将深入探讨浏览器内核及其版本的演变历程,帮助读者更好地理解这一关键技术组件,揭示其内部运作的奥秘。 ... [详细]
  • 本文介绍了如何利用Struts1框架构建一个简易的四则运算计算器。通过采用DispatchAction来处理不同类型的计算请求,并使用动态Form来优化开发流程,确保代码的简洁性和可维护性。同时,系统提供了用户友好的错误提示,以增强用户体验。 ... [详细]
  • V8不仅是一款著名的八缸发动机,广泛应用于道奇Charger、宾利Continental GT和BossHoss摩托车中。自2008年以来,作为Chromium项目的一部分,V8 JavaScript引擎在性能优化和技术创新方面取得了显著进展。该引擎通过先进的编译技术和高效的垃圾回收机制,显著提升了JavaScript的执行效率,为现代Web应用提供了强大的支持。持续的优化和创新使得V8在处理复杂计算和大规模数据时表现更加出色,成为众多开发者和企业的首选。 ... [详细]
  • 如何解决《intelcorei5是否属于i686或x86_64系列》经验,为你挑选了1个好方法。 ... [详细]
author-avatar
APP精品限免大全_312
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有