如果我们希望在用SIMD来提升程序处理的性能,首先需要做的就是检测程序所运行的平台是否支持相应的SIMD扩展。平台对SIMD扩展分为两部分的支持:

  • CPU对SIMD扩展的支持。SIMD扩展是随着CPU的发展不断改进的,CPU为SIMD扩展提供了硬件上的最基本支持。
  • 操作系统对SIMD扩展的支持。目前PC上运行的基本都是多任务操作系统,也就是会“同时”运行着多个程序,这些程序依靠操作系统进行任务调度以使得多个程序看起来是在同时运行,在进行任务调度时需要进行程序上下文的切换,其中就包括寄存器内容的保存与恢复。操作系统对SIMD扩展的支持总的来说主要是在任务上下文切换时,对该SIMD扩展所使用的寄存器的保存与恢复。

CPU Identification

检查平台对SIMD扩展的支持,必不可少的就是指令CPUID。CPUID即CPU Identification,通过该指令能获取到CPU相关的各种信息,其中包括CPU制造商、CPU版本、CPU串号、对各种扩展的支持、Cache相关信息等等。

如果EFLAGS寄存器的ID flag(bit 21)能被置1或者置零的话,则表明能使用CPUID指令。CPUID没有任何操作数,不过CPUID却是一个功能性的指令,有输入以及输出。

  • 输入用的寄存器为EAX(有时也会用到ECX作为扩展输入),用于指定CPUID的功能。在执行CPUID指令前需要往EAX寄存器写入相应的值。
  • 输出用的寄存器为EAX、EBX、ECX、EDX共四个。在CPUID指令执行后可以从这四个寄存器中获取到所需要的信息。

如下所示为CPUID的一些基本功能

Information Returned by CPUID Instruction
Initial EAX
Value
Information Provided about the Processor
Basic CPUID Information
00H
EAX Maximum Input Value for Basic CPUID information.
EBX "Genu"
ECX "ntel"
EDX "inel"
01H
EAX Version Information: Type,Family,Model, and Stepping ID.
EBX Bits 07-00: Brand Index.
Bits 15-08: CLFLUSH line size(Value*8 = cache line size in bytes; used also by CLFLUSHOPT).
Bits 23-16: Maximum number of addressable IDs for logical processors in this physical package.
Bits 31-24: Initial APIC ID.
ECX Feature Information.
EDX Feature Information.
02H
EAX Cache and TLB Information.
EBX Cache and TLB Information.
ECX Cache and TLB Information.
EDX Cache and TLB Information.
03H
EAX Reserved.
EBX Reserved.
ECX Bit 00-31 of 96 bit processor serial number.(Available in P3 only, otherwise reserved.)
EDX Bit 32-64 of 96 bit processor serial number.(Available in P3 only, otherwise reserved.)
...

检查CPU对SIMD扩展的支持

通过指令CPUID可以检测CPU对SIMD扩展的支持。在输入为EAX=01H的情况下执行CPUID,可以使得ECX以及EDX返回如下信息:

其中与SIMD扩展硬件支持的相关bit如下,当相应的bit为1时表示支持该扩展:

SIMD Feature Returned by CPUID Instruction
Register Bit Feature
ECX 0 SSE3
9 SSSE3
12 FMA
19 SSE4.1
20 SSE4.2
25 AES
28 AVX
EDX 23 MMX
25 SSE
26 SSE2

在输入为EAX=07H的情况下执行CPUID,可以通过返回的寄存器EBX上的bit5以及bit16分别检测CPU对AVX2以及AVX512的支持状况。

SIMD Feature Returned by CPUID Instruction
Register Bit Feature
EBX 5 AVX2
16 AVX512

检查操作系统对SIMD扩展的支持

程序通过访问寄存器XCR0(eXterned Control Register)可以得到操作系统对SIMD扩展的支持信息。该寄存器通过XSETBV进行设置,通过XGETBV进行读取。

回顾上一小节,可以看到EAX=01H CPUID.ECX的26、27bit分别为XSAVE以及OSXSAVE。其中XSAVE为1则表示存在XCR0寄存器,并且可以通过XSETBV以及XGETBV访问该寄存器。对操作系统来说,会先查看处理器是否支持XSAVE,如果支持,则会根据操作系统自身的实现情况去设置XCR0寄存器。不过,操作系统与一般的程序有不同的权限,操作系统可以通过设置CR4寄存器的bit8(CR4.OSXSAVE)来控制一般程序对XCR0的访问权限,CPUID得到的OSXSAVE(bit27)表示的就是操作系统是否设置了允许一般程序去访问XCR0寄存器,我们一般的程序只需要去判断这一个bit就知道是否能访问XCR0。

XSAVE Feature Returned by CPUID Instruction
Register Bit Feature Description
ECX 26 XSAVE 为1则表明该处理器支持XSAVE/XRSTOR,支持扩展state,支持XSETBV/XGETBV之类,支持XCR0寄存器
27 OSXSAVE 为1则表明操作系统允许一般程序通过XSETBV/SGETBV访问XCR0寄存器,允许一般程序通过XSAVE/XRSTOR访问扩展state

如果OSXSAVE=1,则可以通过XGETBV指令访问XCR0寄存器,得到系统对SIMD扩展的支持信息。指令XGETBV同样也没有任何的操作数,不过也存在输入与输出。其中输入为ECX,用于指定XCR寄存器,一般只有XCR0,即ECX=0。输出有64bit,保存于EDX:EAX。

XGETBV的输出,即返回值的各个bit有如下指示:

XCR0 SIMD Feature
Register Bit Feature Description
EAX 0 MMX/FPU 这个bit必为1,表明操作系统支持MMX以及ST寄存器
1 SSE 为1则表明操作系统支持XMM寄存器,32位时为XMM0~XMM7,64位时为XMM0~XMM15
2 AVX 为1则表明操作系统支持YMM寄存器,32位时为YMM0~YMM7,64位时为YMM0~YMM15
6 ZMM_Hi265 为1则表明操作系统支持ZMM寄存器,32位时为ZMM0~ZMM7,64位时为ZMM0~ZMM15
7 Hi16_ZMM 为1则表明如果CPU工作在64位模式,则操作系统支持ZMM16~ZMM31

总结

查看平台对SIMD扩展的支持需要分别检查处理器以及操作系统对SIMD扩展的支持。

  • 处理器:调用EAX=1 CPUID,然后查看所返回的ECX或EDX寄存器相应的bit。
  • 操作系统:调用EAX=1 CPUID,然后查看ECX.OSXSAVE(bit27),如果为1则调用XGETBV去获取XCR0,最后查看返回值EAX上相应的bit。

GCC:

#include <stdio.h>

inline static void cpuid (unsigned int output[4], unsigned int EAX, unsigned int ECX) {
unsigned int a, b, c, d;
__asm("cpuid" : "=a"(a),"=b"(b),"=c"(c),"=d"(d) : "a"(EAX),"c"(ECX) : );
output[0] = a;
output[1] = b;
output[2] = c;
output[3] = d;
} inline static unsigned int xgetbv (unsigned int ECX) {
unsigned int ret = 0;
__asm("xgetbv" : "=a"(ret) : "c"(ECX) : );
return ret;
} int main(){
unsigned int CPUInfo[4] = {0}, ECX = 0, EDX = 0, XCR0_EAX = 0;
cpuid(CPUInfo, 1, 0);
ECX = CPUInfo[2];
EDX = CPUInfo[3]; if(EDX & 0x00800000)
printf("CPU Support MMX\n");
if(EDX & 0x02000000)
printf("CPU Support SSE\n");
if(EDX & 0x04000000)
printf("CPU Support SSE2\n");
if(ECX & 1)
printf("CPU Support SSE3\n");
if(ECX & 0x00000200)
printf("CPU Support SSSE3\n");
if(ECX & 0x00080000)
printf("CPU Support SSE4.1\n");
if(ECX & 0x00100000)
printf("CPU Support SSE4.2\n");
if(ECX & 0x02000000)
printf("CPU Support AES\n");
if(ECX & 0x10000000)
printf("CPU Support AVX\n");
if(ECX & 0x08000000)
printf("OS Support XSAVE\n");
else{
printf("OS not Support XSAVE, OS not Support SIMD\n");
return -1;
} XCR0_EAX = xgetbv(0);
if(XCR0_EAX & 0x00000002)
printf("OS Support SSE/SSE2/SSE3/SSE4\n");
if(XCR0_EAX & 0x00000004)
printf("OS Support AVX\n");
if(XCR0_EAX & 0x00000040)
printf("OS Support AVX-512\n"); printf("ECX=%x, EDX=%x, XCR0_EAX=%x\n", ECX, EDX, XCR0_EAX);
return 0;
}

YASM:

global SIMD_Support

;this code just check SSE3 support
;bit0:SSE3, bit27:OSXSAVE
%define CPU_SUPPORT_CONST_ECX 0x08000001
;bit23:MMX, bit25:SSE, bit26:SSE2
%define CPU_SUPPORT_CONST_EDX 0x06800000 ;bit2:XMM
%define OS_SUPPORT_CONST 2 SIMD_Support:
;processor supports
mov eax, 1
cpuid
and ecx, CPU_SUPPORT_CONST_ECX
cmp ecx, CPU_SUPPORT_CONST_ECX
jne not_supported
and edx, CPU_SUPPORT_CONST_EDX
cmp edx, CPU_SUPPORT_CONST_EDX
jne not_supported ;OS supports
mov ecx, 0
XGETBV; result in EDX:EAX
and eax, OS_SUPPORT_CONST
cmp eax, OS_SUPPORT_CONST
jne not_supported mov eax, 0 ; return 0
ret not_supported:
mov eax, -1 ; return -1
ret

Reference:

Intel 64 and IA-32 Architectures Software Developer's Manual

PC平台的SIMD支持检测的更多相关文章

  1. PC平台主要SIMD扩展发展简史

    Single Instruction Multiple Data,简称SIMD.SIMD描述的是微处理器中单条指令能完成对数据的并行处理.SIMD所使用的是特殊的寄存器,一个寄存器上存储有多个数据,在 ...

  2. PC平台在Unity3D中播放硬盘ogg,mp3,wav文件

    Unity3D PC平台本身是支持直接用www读取本地ogg,wav的,但是并不能读取byte[],字节数组格式,这对用习惯了bass,fmod的人来说有点不方便. 搜了一圈发现了一个C#的音频库叫N ...

  3. 1、大部分社交平台接口不支持https协议。

    参考文献来自:http://wiki.mob.com/ios9-%E5%AF%B9sharesdk%E7%9A%84%E5%BD%B1%E5%93%8D%EF%BC%88%E9%80%82%E9%85 ...

  4. 20165309 《网络对抗技术》实验一:PC平台逆向破解

    20165309 <网络对抗技术>实验一:PC平台逆向破解 目录 实践目标 基础知识 实验原理.内容及步骤 问题与解决 实验收获 一.实践目标 本次实践的对象是一个名为pwn1的linux ...

  5. 1个多商户、多平台版 微信小程序(多商户、多平台版),影城行业、影业连锁 多商户、多平台版微信小程序。(基于多平台版,支持在业务上 可给 每个单独影城 分发定制单独的小程序版本)

    1个 影城行业 微信小程序(多商户.多平台版), 影业连锁 多商户.多平台版微信小程序.(基于多平台版,支持在业务上 可给 每个单独影城 分发定制单独的小程序版本) 资讯QQ: 876635409  ...

  6. 20145325张梓靖 《网络对抗技术》 PC平台逆向破解

    20145325张梓靖 <网络对抗技术> PC平台逆向破解 学习任务 shellcode注入:shellcode实际是一段代码,但却作为数据发送给受攻击服务器,将代码存储到对方的堆栈中,并 ...

  7. 2017-2018 Exp1 PC平台逆向破解 20155214

    目录 Exp1 PC平台逆向破解 实验内容 知识点 官方源 中科大源 上海交大的源 新加坡源 debain源 debian安全更新源 163源的地址 阿里云kali源 启发 评论 Exp1 PC平台逆 ...

  8. 20155233 Exp1 PC平台逆向破解(5)M

    Exp1 PC平台逆向破解(5)M 实践一 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数. 步骤 1.cp pwn1 pwn20155233拷贝pwn1文件,命名为pwn201 ...

  9. 20145331魏澍琛 《网络对抗技术》 PC平台逆向破解

    20145331魏澍琛 <网络对抗技术> PC平台逆向破解 学习任务 1.shellcode注入:shellcode实际是一段代码,但却作为数据发送给受攻击服务器,将代码存储到对方的堆栈中 ...

随机推荐

  1. 基于webpack+react+antd 项目构建

    工欲善其事必先利其器,学习React也是如此. 下面分享一篇基于webpack+react+antd 项目构建的好文章, https://blog.hduzplus.xyz/articles/2017 ...

  2. OdnShop 发布 V1.0 正式版,完整可用的开源微商城系统

    OdnShop是基于ASP.NET 4.0+Mysql开发的开源微商城系统,我们的目标是构建一个核心完善而又轻量级的微商城平台. 本版本更新功能: 1,修正数据库操作的部分表名称的表前缀错误: 2,修 ...

  3. 天坑之路:用js给选中文字添加样式

    前言 本例基于react,但是实际上就是用原生js做的.兼容性做到了IE9,但是按照这个思路做是可以做到IE8甚至更低的. 需求与最初的思路 当我拿到这个需求的时候以为很简单,就是可以给页面上的文章做 ...

  4. ASP.NET MVC5+EF6+EasyUI 后台管理系统(91)-EF 连接 MySql

    前言 虽然系统目前只支持MSSQL版本,但是很多朋友公司技术规定必须使用MySql,下面我们就来使用EF连接MySQL吧! (1)安装MYSQL环境 1.下载安装MYSQL数据,这里我们安装phpSt ...

  5. mysql 库 行 列的 操作使用

    -----------------------------------------------------------------------------时间不等你,下一刻,全是新的.每一刻都让它变得 ...

  6. vscode 缩进改为2空格

    因为vscode默认启用了"editor.detectIndentation": true”根据文件类型自动设置tabsize的选项. 在配置中加上 "editor.de ...

  7. H5 27-优先级之important

    27-优先级之important 我是段落 <!DOCTYPE html> <html lang="en"> <head> <meta c ...

  8. AtCoder Beginner Contest 122 D - We Like AGC (DP)

    D - We Like AGC Time Limit: 2 sec / Memory Limit: 1024 MB Score : 400400 points Problem Statement Yo ...

  9. 将工程改造为SOA架构

    商城是基于soa的架构,表现层和服务层是不同的工程.所以要实现商品列表查询需要两个系统之间进行通信. 流动计算架构 当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基 ...

  10. Dubbo负载均衡与集群容错机制

    1  Dubbo简介 Dubbo是一款高性能.轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现. 作为一个轻量级RPC框架,D ...