热门标签 | 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 中保持,所以它的寄存器重命名机制是不同的.)


推荐阅读
  • 本文概述了JNI的原理以及常用方法。JNI提供了一种Java字节码调用C/C++的解决方案,但引用类型不能直接在Native层使用,需要进行类型转化。多维数组(包括二维数组)都是引用类型,需要使用jobjectArray类型来存取其值。此外,由于Java支持函数重载,根据函数名无法找到对应的JNI函数,因此介绍了JNI函数签名信息的解决方案。 ... [详细]
  • 三、查看Linux版本查看系统版本信息的命令:lsb_release-a[root@localhost~]#lsb_release-aLSBVersion::co ... [详细]
  • Spark面试题汇总大全
    1RDD简介RDD是Spark最基本也是最根本的数据抽象,它具备像MapReduce等数据流模型的容错性,并且允许开发人员在大型集群上执行基于内存的计 ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 服务器上的操作系统有哪些,如何选择适合的操作系统?
    本文介绍了服务器上常见的操作系统,包括系统盘镜像、数据盘镜像和整机镜像的数量。同时,还介绍了共享镜像的限制和使用方法。此外,还提供了关于华为云服务的帮助中心,其中包括产品简介、价格说明、购买指南、用户指南、API参考、最佳实践、常见问题和视频帮助等技术文档。对于裸金属服务器的远程登录,本文介绍了使用密钥对登录的方法,并提供了部分操作系统配置示例。最后,还提到了SUSE云耀云服务器的特点和快速搭建方法。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 通过Anaconda安装tensorflow,并安装运行spyder编译器的完整教程
    本文提供了一个完整的教程,介绍了如何通过Anaconda安装tensorflow,并安装运行spyder编译器。文章详细介绍了安装Anaconda、创建tensorflow环境、安装GPU版本tensorflow、安装和运行Spyder编译器以及安装OpenCV等步骤。该教程适用于Windows 8操作系统,并提供了相关的网址供参考。通过本教程,读者可以轻松地安装和配置tensorflow环境,以及运行spyder编译器进行开发。 ... [详细]
  • 目录1、将mysql数据导出到SQL文件中(数据库存在的情况)2、将现有的sql文件数据导入到数据库中(前提数据库存在) 3、利用Navicat导出SQL文件和导入SQL文件1)从 ... [详细]
  • 【技术分享】一个 ELF 蠕虫分析
    【技术分享】一个 ELF 蠕虫分析 ... [详细]
  • 基于STM32的智能循迹小车设计(基础版)
    基于STM32的智能循迹小车设计(基础版)硬件准备1、小车底盘+四直流电机(带轮)2、STM32F103C8T6核心板3、12V8700mAh锂电池(可以用几节18650锂电池)4 ... [详细]
  • 最简便的 JavaScript 代码检查工具安装方式
    前两天发了一篇用mingw编译javascriptv8,讲述我为了在Windows下给javascript做lint检查,费劲去编译google的jav ... [详细]
  • 如何进行Intel CSME 漏洞预警的分析
    本篇文章为大家展示了如何进行IntelCSME漏洞预警的分析,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获 ... [详细]
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社区 版权所有