关于cpu体系架构的一些有趣的故事分享
从排查一次匪夷所思的coredump,引出各种体系架构的差异。
本文中的所有内容来自学习DCC888的学习笔记或者自己理解的整理,如需转载请注明出处。周荣华@燧原科技
1 背景
从全世界有记载的第一台计算机Z1 (computer) - Wikipedia在1936年发明,到1946年冯诺依曼体系架构的清晰提出,计算机体系架构的演进虽然没有什么革命性的变化,但各种体系架构的微调还是很明显的。
发展到现在虽然存在X86/ARM/MIPS/ALPHA/PPC/RISC-V等多种门派,但实际的设计思想上,主要有两种,一种是基于X86的系统架构,另外一种就是其他系统架构。
为什么这么分?
因为X86的很多特性,基本上只有X86有,而其他体系架构基本上都是共享的另外一种。
例如CISC和RISC,字节对齐,变长指令和固定长度指令,指令寻址模式,等等。
现在用的各种体系架构,只有x86是复杂指令集,变长,内存访问可以不是字节对齐的(当然,对齐之后性能更好),没有固定的加载和保存指令,而是采用很多计算指令直接访问内存。
相对于x86,其他体系架构,包括ARM/MIPS/ALPHA/PPC/RISC-V,都是精简指令集,指令长度也是固定的,内存访问必须对齐,否则coredump,内存的访问只能通过有限的几个加载和保存指令进行,其他计算指令仅限于在寄存器上操作。
2 体系架构
计算机的体系架构,英文称为Computer architecture - Wikipedia,涉及的工作主要分三部分:
指令集、微架构和系统设计。
其中指令集相当于用户界面,是软件和硬件的接口。
微架构是指令集的具体实现。
系统设计主要是支撑微架构的内存、总线、功耗等设计。
下面的问题单就X86来阐述。
32位的处理器太古老,我们单说64位之后的故事。
x86-64 - Wikipedia讲述了x86-64的体系架构的微架构演进过程:

最早出来的是x86-64,相当于64位x86的基线版本,基本上所有64位x86处理器都支持,包括常见的MMX、SSE、FPU,都不是问题。基于这个基线版本往上发展出了v2/v3和v4版本。
现在虚拟机(QEMU)基本上支持到v2就终结了,所以后面v3/v4变成了少数用户的选择。随着这些微架构的演进,不仅指令集,寄存器也会有较大变化。那怎么保证编译出来的程序在各种x86的硬件上都能正常运行是个大问题。解决这个问题的主角就是编译器。
考虑到泛化和性能的不同要求,即使在同样的体系架构下,也可以指定具体的硬件版本,这就是gcc/clang等编译器的arch参数的由来。
x86 Options (Using the GNU Compiler Collection (GCC))中提到的arch的取值从各种具体的处理器型号,到泛化的v2/v3/v4,都是为了方便程序员可以尽可能保证兼容性的前提下,也能提升性能。
如果不考虑泛化,用户还可以简单用一个-march-native在x86平台上实现基于当前硬件的极致优化。
3 问题
这里碰到的一个问题就是极致优化带来的兼容性问题。
某服务器上编译出来的版本,在部分x86的机器上能正常运行,但部分x86机器上不能正常运行。通过gdb断点排查,报非法指令,而且代码段指向vxorps这条指令,后面紧跟着的3个寄存器非常扎眼zmm。

zmm寄存器是v4版本引入的功能。
能运行含zmm寄存器指令的cpu是“Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz”,网上查了一下,是intel 2017年的产品。
到目前位置,MMX指令使用的寄存器经过了三代演进,xmm/ymm/zmm:
xmm0 ~ xmm15, are 128 bits, almost every modern machine has it, they are released in 1999.
ymm0 ~ ymm15, are 256 bits, new machine usually have it, they are released in 2011.
zmm0 ~ zmm31, are 512 bits, normal pc probably don't have it (as the year 2016),
由于后一代的寄存器长度是上一代的两倍,决定了前一代处理器是无法使用后一代处理器的寄存器的,相反,本地如果是更高一级的寄存器,可以运行低级的寄存器相关指令。
同样的代码,都指定-march=native的情况下,在“AMD Ryzen Threadripper 3960X 24-Core Processor”上编译的结果是这样的,指令本身没有变,寄存器从zmm变成了xmm。

4 问题的解决
既然知道是gcc的arch指定有问题导致的,就要从修改arch入手。
做了一些实验,例如下面左边是-march=native编译,右边是-march=x86-64的结果。可以看出native编译出来使用incl,相对于addl,使指令更短,性能更好。

最终各种实验对比结果看结论如下:
-m64 -march=x86-64 -mtune=generic 编译出来的结果使用xmm寄存器
-march=native 编译出来的结果,在amd服务器上是xmm寄存器,在intel服务器上是zmm寄存器
为了保证兼容性,先统一用-m64 -march=x86-64 -mtune=generic 进行编译。
5 怎么做的更好
由于大多数编译器还不支持-march=x86-64-v2等直接选择x86-64具体版本的选项,有一种折中方案是native-avx512的做法,一般参数是这样的:
add_compile_options (-march=native)
add_compile_options (-mno-avx512f)
这样写的意思是其他方面可以尽量用本地能支持的最新的,但不要使用avx512f的功能,约等于x86-64-v3这个arch参数的功能。
关于cpu体系架构的一些有趣的故事分享的更多相关文章
- 【转】XenServer体系架构解析
XenServer是一套已在云计算环境中经过验证的企业级开放式服务器虚拟化解决方案,可以将静态.复杂的IT环境转变为更加动态.易于管理的虚拟数据中心,从而大大降低数据中心成本.同时,它可以提供先进的管 ...
- 面向服务体系架构(SOA)和数据仓库(DW)的思考基于 IBM 产品体系搭建基于 SOA 和 DW 的企业基础架构平台
面向服务体系架构(SOA)和数据仓库(DW)的思考 基于 IBM 产品体系搭建基于 SOA 和 DW 的企业基础架构平台 当前业界对面向服务体系架构(SOA)和数据仓库(Data Warehouse, ...
- 基于物联网操作系统HelloX的智慧家庭体系架构
基于物联网操作系统HelloX的智慧家庭体系架构 智慧家庭是物联网的一个分支应用,是一个被广泛认同的巨大IT市场空间.目前市场上已经有很多针对智慧家庭的产品或解决方案,但与移动互联网不同,智慧家庭至今 ...
- [转]OpenContrail 体系架构文档
OpenContrail 体系架构文档 英文原文:http://opencontrail.org/opencontrail-architecture-documentation/ 翻译者:@KkBLu ...
- InnoDB引擎体系架构
InnoDB引擎架构介绍 innodb存储引擎的体系架构,可简单划分成三层: 数据文件 :磁盘上的数据文件 内存池:缓存磁盘上的数据,方便读取,同时在对磁盘文件数据修改之前在这里缓存,然后按一定规刷新 ...
- InnoDB体系架构(二)内存
InnoDB体系架构(二)内存 上篇文章 InnoDB体系架构(一)后台线程 介绍了MySQL InnoDB存储引擎后台线程:Master Thread.IO Thread.Purge Thread. ...
- InnoDB体系架构
MySQL支持插件式存储引擎,常用的存储引擎则是MyISAM和InnoDB,通常在OLTP(Online Transaction Processing 在线事务处理)中,我们选择使用InnoDB,所以 ...
- NUMA 体系架构
NUMA 体系架构 SMP 体系架构 NUMA 体系架构 NUMA 结构基本概念 Openstack flavor NUMA 策略 Nova 实现 NUMA 流程 1. SMP 体系架构 CPU 计算 ...
- 面向服务体系架构(SOA)和数据仓库(DW)的思考
摘要: 当前业界对面向服务体系架构(SOA)和数据仓库(Data Warehouse,DW)都介绍的很多,提出了很多优秀的解决方案,但是一般是把 SOA 和 DW 单独考虑,SOA 和 DW 有着共同 ...
随机推荐
- .NET宝藏API之:IHostedService,后台任务执行
我们在项目开发的过程中可能会遇到类似后台定时任务的需求,比如消息队列的消费者. 按照.NetF时的开发习惯首先想到的肯定是Windows Service,拜托,都什么年代了还用Windows服务(小声 ...
- XCTF练习题---MISC---simple_transfer
XCTF练习题---MISC---simple_transfer flag:HITB{b3d0e380e9c39352c667307d010775ca} 解题步骤: 1.观察题目,下载附件 2.经过观 ...
- Maven install没有将jar包加载到本地仓库
错误描述 使用mvn install:install-file -Dfile=ojdbc8-19.3.0.0.jar -DgroupId=com.oracle -DartifactId=ojdbc8 ...
- [笔记] K-D Tree
一种可以 高效处理 \(k\) 维空间信息 的数据结构. 在正确使用的情况下,复杂度为 \(O(n^{1-\frac{1}{k}})\). K-D Tree 的实现 建树 随机一维选择最中间的点为当前 ...
- python+pytest接口自动化(15)-日志管理模块loguru简介
python自带日志管理模块logging,使用时可进行模块化配置,详细可参考博文Python日志采集(详细). 但logging配置起来比较繁琐,且在多进行多线程等场景下使用时,如果不经过特殊处理, ...
- 手脱UPX(3.91)
1.使用Detect It Easy进行查壳: 2.使用x32dbg打开该带壳程序,在选项->选项->异常中添加区间设置0~FFFFFFFF全忽略: 3.我们F9运行到程序入口处,看到了p ...
- 2.0 vue2+tinymce实现图片上传与回显
1.效果 2.配置 2.1 在init中添加图片上传函数 // 图片上传 images_upload_handler: (blobInfo, success, failure) => { // ...
- OAuth2.0笔记
OAuth2.0笔记 角色 一般资源服务器和授权服务器是一个 资源拥有者 客户端应用 资源服务器 授权服务器 客户端类型 OAuth 2.0规范定义了两种客户端类型: 保密的:web应用 公有的:用户 ...
- SpringBoot进阶教程(七十四)整合ELK
在上一篇文章<SpringBoot进阶教程(七十三)整合elasticsearch >,已经详细介绍了关于elasticsearch的安装与使用,现在主要来看看关于ELK的定义.安装及使用 ...
- babel使用
Babel转码器 Babel定义 Babel 是一个广泛使用的 ES6 转码器,可以将 ES6 代码转为 ES5 代码,从而在老版本的浏览器执行 Babel安装 仅需要在项目文件下安装 npm ins ...