PC平台的SIMD支持检测
如果我们希望在用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的一些基本功能
Initial EAX Value |
Information Provided about the Processor | ||||||||||||||||||
Basic CPUID Information | |||||||||||||||||||
00H |
|
||||||||||||||||||
01H |
|
||||||||||||||||||
02H |
|
||||||||||||||||||
03H |
|
||||||||||||||||||
... |
检查CPU对SIMD扩展的支持
通过指令CPUID可以检测CPU对SIMD扩展的支持。在输入为EAX=01H的情况下执行CPUID,可以使得ECX以及EDX返回如下信息:
其中与SIMD扩展硬件支持的相关bit如下,当相应的bit为1时表示支持该扩展:
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的支持状况。
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。
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有如下指示:
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支持检测的更多相关文章
- PC平台主要SIMD扩展发展简史
Single Instruction Multiple Data,简称SIMD.SIMD描述的是微处理器中单条指令能完成对数据的并行处理.SIMD所使用的是特殊的寄存器,一个寄存器上存储有多个数据,在 ...
- PC平台在Unity3D中播放硬盘ogg,mp3,wav文件
Unity3D PC平台本身是支持直接用www读取本地ogg,wav的,但是并不能读取byte[],字节数组格式,这对用习惯了bass,fmod的人来说有点不方便. 搜了一圈发现了一个C#的音频库叫N ...
- 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 ...
- 20165309 《网络对抗技术》实验一:PC平台逆向破解
20165309 <网络对抗技术>实验一:PC平台逆向破解 目录 实践目标 基础知识 实验原理.内容及步骤 问题与解决 实验收获 一.实践目标 本次实践的对象是一个名为pwn1的linux ...
- 1个多商户、多平台版 微信小程序(多商户、多平台版),影城行业、影业连锁 多商户、多平台版微信小程序。(基于多平台版,支持在业务上 可给 每个单独影城 分发定制单独的小程序版本)
1个 影城行业 微信小程序(多商户.多平台版), 影业连锁 多商户.多平台版微信小程序.(基于多平台版,支持在业务上 可给 每个单独影城 分发定制单独的小程序版本) 资讯QQ: 876635409 ...
- 20145325张梓靖 《网络对抗技术》 PC平台逆向破解
20145325张梓靖 <网络对抗技术> PC平台逆向破解 学习任务 shellcode注入:shellcode实际是一段代码,但却作为数据发送给受攻击服务器,将代码存储到对方的堆栈中,并 ...
- 2017-2018 Exp1 PC平台逆向破解 20155214
目录 Exp1 PC平台逆向破解 实验内容 知识点 官方源 中科大源 上海交大的源 新加坡源 debain源 debian安全更新源 163源的地址 阿里云kali源 启发 评论 Exp1 PC平台逆 ...
- 20155233 Exp1 PC平台逆向破解(5)M
Exp1 PC平台逆向破解(5)M 实践一 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数. 步骤 1.cp pwn1 pwn20155233拷贝pwn1文件,命名为pwn201 ...
- 20145331魏澍琛 《网络对抗技术》 PC平台逆向破解
20145331魏澍琛 <网络对抗技术> PC平台逆向破解 学习任务 1.shellcode注入:shellcode实际是一段代码,但却作为数据发送给受攻击服务器,将代码存储到对方的堆栈中 ...
随机推荐
- ASP.NET Core中代码使用X509证书,部署到IIS上后报错:System cannot find the specified file 的解决办法(转载)
问: I am trying to embrace the mysteries of SSL communication and have found a great tutorial on this ...
- [Spark][Python][DataFrame][RDD]从DataFrame得到RDD的例子
[Spark][Python][DataFrame][RDD]从DataFrame得到RDD的例子 $ hdfs dfs -cat people.json {"name":&quo ...
- Python股票分析系列——基础股票数据操作(二).p4
该系列视频已经搬运至bilibili: 点击查看 欢迎来到Python for Finance教程系列的第4部分.在本教程中,我们将基于Adj Close列创建烛台/ OHLC图,这将允许我介绍重新采 ...
- 卷积神经网络CNN的意义
一.选用卷积的原因 局部感知 简单来说,卷积核的大小一般小于输入图像的大小(如果等于则是全连接),因此卷积提取出的特征会更多地关注局部 —— 这很符合日常我们接触到的图像处理.而每个神经元其实没有必要 ...
- 循环 while
day 2 ---------------------------------------------------把一件简单的事情做到极致,你就成功了. Day2作业及默写 1.判断下列逻辑语句的Tr ...
- eclipes个人配置
设置字体:https://jingyan.baidu.com/article/f96699bb9442f3894e3c1b15.html general->appearance->colo ...
- IBM的淘汰之路
BM曾经在计算领域独领风骚,但是90年被PC产业链上的微软.英特尔等厂商围殴,遭遇最严重的危机; 今天在云计算市场,IBM曾在遭遇同样的危机,这一次不知道它能否安然度过; IBM收购红帽转向混合云,是 ...
- cent6.x配置主机名及静态网络
# 修改网卡名为NAME="eth0" [root@jenkins ~]# -persistent-net.rules # This file was automatically ...
- opencv2\core\cuda.hpp(106): error C2059: 语法错误:“常量”
在 cuda.hpp 中, virtual void free(GpuMat* mat) = 0; -> virtual void _free(GpuMat* mat) = 0;
- Azure系列2.1.5 —— BlobOutputStream
(小弟自学Azure,文中有不正确之处,请路过各位大神指正.) 网上azure的资料较少,尤其是API,全是英文的,中文资料更是少之又少.这次由于公司项目需要使用Azure,所以对Azure的一些学习 ...