【计算机系统结构实验】实验4 向量扩展指令和编程

4.1 实验目的

  1. 理解向量的处理方法;掌握X86体系中MMX/SSE/AVX指令集进行编程的基本方法。
  2. 理解SIMD指令含义及原理,了解Kunpeng数学库的安装与使用

4.2 实验平台

  1. 需要x86计算机和微软编程工具Visual Studio 2012。
  2. Taishan服务器,安装openEuler系统,已安装gcc编译器和鲲鹏数学库KML

4.3 实验说明

  1. SSE、AVX 都是 x86 平台的 SIMD 指令,SIMD 是单指令多数据流的简称,可用来加快计算速度。鲲鹏平台也有自己的 SIMD 指令,名为 Neon。
  2. 鲲鹏数学库(Kunpeng Math Library,以下简称KML)提供了基于鲲鹏平台优化的高性能数学函数,所有接口由C/C++、汇编语言实现,部分接口提供Java语言封装的接口。向量数学库(Vector Mathematical Library),通过Neon指令优化、内联汇编等方法,对输入数据进行向量化处理,充分利用了鲲鹏架构下的寄存器特点,实现了在鲲鹏服务器上的性能提升。

(Kunpeng BoostKit 22.0.0 鲲鹏数学库 开发指南 01 - 华为)

4.4 实验内容

1. X86平台的向量扩展指令

x86处理器支持的向量扩展指令有:MMX/SSE/AVX指令集。在Visual Studio中可使用内联函数访问,使用时需要添加对应的头文件:

mmintrin.h------>MMX

xmmintrin.h------>SSE

emmintrin.h------>SSE2

pmmintrin.h------>SSE3

immintrin.h------>AVX

可使用CPU-Z的小工具查询自己的机器支持的MMX/SSE/AVX指令集情况。

下面以SSE指令集为例,做一个小实验。

SSE指令在运算时使用128位的SSE暂存器 (可看作是向量寄存器)

使用SSE指令写代码的步骤为:使用load/set函数将数据从内存加载到SSE暂存器;使用相关SSE运算指令完成计算;使用store函数将结果从暂存器保存回内存。

1)Load系列函数:用于加载数据,将数据从内存加载到暂存器。

比如,使用_mm_load_ps(float const * _A)函数来实现加载4float型的元素,组合成1__m128类型的向量数据,放入暂存器。(注:__m128 SSE指令采用的向量数据类型,是128位(16字节)的)。

在使用该函数时,输入数据需要先被指定为16字节对齐,用_declspec函数来实现对齐: __declspec(align(16))  float  Input[4]={1.0,2.0,3.0,4.0}

2)Store系列函数:用于将SSE暂存器的数据保存回内存中。

SSE指令运算后的数据一般以__m128的数据类型保存在暂存器里,可以使用以下store函数将其变回float类型再保存到内存中:

void _mm_store_ps(float* p, __m128 a);

3)运算指令

SSE提供了大量的向量浮点运算指令,包括加法、减法、乘法、除法、开方、最大值、最小值、近似求倒数、求开方的倒数等等。下面是一条向量加法指令。

__m128 _mm_add_ps (__m128 a, __m128 b)

新建一个空项目,添加项目中的cpp源文件,代码如下:

#include "xmmintrin.h"  
#include <iostream>  
using namespace std;  
void main()  
{   __declspec(align(16)) float Input1[4] = {1.0,2.0,3.0,4.0};  __declspec(align(16)) float Input2[4] = {5.0,6.0,7.0,8.0};__declspec(align(16)) float Result[4];__m128 a = _mm_load_ps(Input1);  __m128 b = _mm_load_ps(Input2);  __m128 c = _mm_add_ps(a,b);  _mm_store_ps(Result,c); cout<<a.m128_f32[0]<<" "<<a.m128_f32[1]<<" " <<a.m128_f32[2]<<" "<<a.m128_f32[3]<<endl;cout<<b.m128_f32[0]<<" "<<b.m128_f32[1]<<" " <<b.m128_f32[2]<<" "<<b.m128_f32[3]<<endl;cout<<c.m128_f32[0]<<" "<<c.m128_f32[1]<<" " <<c.m128_f32[2]<<" "<<c.m128_f32[3]<<endl;  for(int i=0;i<4;i++) {  cout<<Result[i]<<" ";  }  cout<<endl; getchar();    
}

 

运行结果:

这段代码主要使用了SSE指令集,其实现的功能如下:

    1. 定义了两个16字节对齐(_declspec函数)的浮点数数组Input1、Input2和结果数组Result。

    2. 使用_mm_load_ps函数从Input1和Input2数组(内存)中加载4个float型的元素,组合成1个__m128类型的向量数据,放入__m128类型(SSE指令采用的向量数据类型,是128位(16字节)的)的变量a和b(暂存器)中。

    3.使用_mm_add_ps函数对a和b(暂存器)进行向量浮点加法操作,结果(数据类型为__m128)存储在c(暂存器)中。

    4. 使用_mm_store_ps函数将c中的结果的数据类型由__m128变回float类型,并将其存储到Result数组(内存)中。

   5. 代码打印了a, b, 和 c中的各个元素。

   6. 代码打印了Result数组中的各个元素。

这段代码使用了SSE指令集进行运算操作,以及使用load/set与store函数进行内存与暂存器的数据传输,展示了向量扩展指令的运用。

2. OpenEuler平台的KML库

1)在实验机器上,使用学生账号通过SSH方式远程连接Taishan服务器 (用户名:stud001——stud140,密码:1)

2) 使用VIM编辑器,创建程序simd.c,使用sin函数作为耗时功能函数,并使gcc编译该程序, -lm参数进行解释说明。

-l[library name],用来指定编译时候使用的库,-lm 为指定数学库。

3) 运行simd程序,查看并记录结果。

多次运行结果显示

Time: 0.002871

Time: 0.002772

Time: 0.002759

Time: 0.002765

这段代码主要操作如下:

  1. 用一个for循环将src数组中的每个元素赋值为它的索引值。
  2. 用另一个for循环将src数组中的每个元素的sin值计算出来,并存储到withoutv数组中。
  3. 打印出计算sin值所花费的时间。(double)(t2-t1)是计算两个时间点之间的时间差,CLOCKS_PER_SEC是每秒的时钟周期数,所以整个表达式的值就是时间差除以每秒的时钟周期数,即计算出的秒数。

4)使用KML库中的函数改写程序,新建程序simdv.c ,使用向量vdsin函数,其余保持不变,使用GCC编译程序,对“- L“- I” 参数进行相应的解释说明

编译指令为:

-L [dir],制定编译的时候,指定库的搜索路径,告诉编译器在 dir 目录中查找库文件,例如可以指定搜索自定义库。

-I [dir],表示将 dir 目录添加到头文件搜索路径中,这样就可以直接使用 #include<header.h> 的形式进行包含。

5) 运行simdv程序,查看并记录结果。

多次运行结果显示

Time: 0.000778

Time: 0.000772

Time: 0.000799

Time: 0.000772

6) 修改上述simdsimdv代码中L参数,并使用tan功能,记录结果对比长度对时间的影响:

L

Time: Simd.c

Time: Simdv.c

1

0.000004

0.000006

10

0.000010

0.000004

100

0.000019

0.000004

1000

0.000078

0.000013

10000

0.000637

0.000102

100000

0.006211

0.000969

可以看到,当数组大小变大时,vdtan函数可以显著缩短程序的运行时间。

4.5 实验总结

       通过本次实验,我了解了SIMD指令含义及原理与MMX/SSE/AVX指令集的功能与使用,并在电脑上使用SSE指令集进行了基本的运算操作,学习运用了向量扩展指令。同时也了解了鲲鹏数学库的功能与使用,并编译运行了包含sin函数、vdsin函数、tan函数、vdtan函数的程序,对比了数组长度与不同函数对程序运行时间的影响。

-------------------------------------------------------------------------------------------------------

最后一点碎碎念:如果各位有发现本文有哪处有误或理解不当的地方,敬请指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/293613.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决找不到vcruntime140.dll无法继续执行的多种方法分享

最近&#xff0c;我在使用电脑时遇到了一个问题&#xff0c;即“由于找不到vcruntime140.dll无法继续执行”。vcruntime140.dll是Visual C Redistributable Packages中的一个组件&#xff0c;它是Visual Studio 2015中运行C程序所必需的。如果找不到vcruntime140.dll文件&#…

PostgreSQL从入门到精通教程 - 第39讲:数据库完全恢复

PostgreSQL从小白到专家&#xff0c;是从入门逐渐能力提升的一个系列教程&#xff0c;内容包括对PG基础的认知、包括安装使用、包括角色权限、包括维护管理、、等内容&#xff0c;希望对热爱PG、学习PG的同学们有帮助&#xff0c;欢迎持续关注CUUG PG技术大讲堂。 第39讲&#…

JavaScript高级 构造函数与原型篇

构造函数与原型 1、构造函数 构造函数是一种特殊的函数&#xff0c;主要用来初始化对象&#xff0c;即为对象成员变量赋初始值&#xff0c;它总与new一起使用。我们可以把对象中一些公共的属性和方法抽取出来&#xff0c;然后封装到这个函数里面。 // 定义学生构造函数func…

微信小程序开发系列-02注册小程序

上一篇文章&#xff0c;创建了一个最小的小程序&#xff0c;但是&#xff0c;还有3个疑问没有弄清楚&#xff0c;还是基于demo1工程&#xff0c;这篇文章继续探索。 当前的目录结构是否是完备的呢&#xff1f;&#xff08;虽然小程序可以运行起来&#xff09;app.js文件内容还…

Springboot是什么?Springboot详解!入门介绍

&#x1f4eb;作者简介&#xff1a;小明java问道之路&#xff0c;2022年度博客之星全国TOP3&#xff0c;专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化&#xff0c;文章内容兼具广度、深度、大厂技术方案&#xff0c;对待技术喜欢推理加验证&#xff0c;就职于…

使用通道和模式

通过通道、选择语句和最佳实践掌握 Go 中的并发编程 并发编程是构建高效和响应迅速的软件的强大范例。Go&#xff0c;也被称为 Golang&#xff0c;通过通道提供了一种健壮且优雅的解决方案来进行并发通信。在这篇文章中&#xff0c;我们将探讨通道的概念、它们在并发编程中的作…

海量搜索需求助推,跟着官方和优秀创作者一起来“百度夜校”开课!

文章目录 &#x1f354;概述&#x1f6f8;新中产消费人群占比高&#xff0c;教育博主快速崭露头角&#x1f6f8;亿级消费入口&#xff0c;泛知识创作者的新蓝海 &#x1f354;概述 近日&#xff0c;百度百家号官方开启“教育变现专场”和“泛知识专场”两场爆款公开课的讲座&a…

vscode中vue项目报错

当在vscode中写代码时&#xff0c;报错报错报错......... 已经头大&#xff0c;还没写就报错&#xff0c; 这是因为eslint对语法的要求太过严格导致的编译时&#xff0c;出现各种语法格式错误 我们打开vue.config.js&#xff0c;加上这句代码&#xff0c;就OK啦 lintOnSave:…

DDPM推导笔记

各位佬看文章之前&#xff0c;可以先去看看这个视频&#xff0c;并给这位up主点赞投币&#xff0c;这位佬讲解的太好了&#xff1a;大白话AI 1.前置知识的学习 1.1 正态分布特性 ​ &#xff08;1&#xff09;正态分布的概率密度函数 f ( x ) 1 2 π σ e − ( x − μ ) …

【深入解析spring cloud gateway】12 gateway参数调优与分析

本节主要对网关主要的一些参数做一些解释说明&#xff0c;并用压测工具测试一下网关的接口&#xff0c;通过压测来验证参数配置是否合理 一、连接池参数 参数示例 spring:application:name: gatewaycloud:gateway:# http连接设置httpclient:# 全局的响应超时时间&#xff0c…

aws-waf-cdn 基于规则组的永黑解决方案

1. 新建waf 规则组 2. 为规则组添加规则 根据需求创建不同的规则 3. waf中附加规则组 &#xff08;此时规则组所有规则都会附加到waf中&#xff0c;但是不会永黑&#xff09; 此刻&#xff0c;可以选择测试下规则是否生效&#xff0c;测试前确认保护资源绑定无误 4. 创建堆…

加密算法学习

最近在写一些加密的东西。所以就整理一下常见的加密算法。 欢迎帮助纠错&#xff0c;谢谢。 废话不多直接上图&#xff1a; 加密学习一级介绍描述常见算法常见算法细分非对称加密解释 非对称加密需要两个密钥&#xff1a;公钥 (publickey) 和私钥 (privatekey)。公钥和私钥是…