X86 SSE/AVX指令集加速学习

news/2025/1/15 19:51:36/

在看了刘文志的《并行编程方法与优化实践》后决定写一写书中的例子或者实际工程中用到加速的一些sample,这本书的pdf我也有,可以在下面留言,我发给你。

1. 使用SSE指令实现了一些简单函数,可以自定义事件函数测试加速比

#include "xmmintrin.h"
#include "windows.h"
#include "math.h"
#include "iostream"
using namespace std;
typedef unsigned long uL;void MultiplyWithSSE(float * a, DWORD len, float scale){ //DWORD means unsigned longDWORD nowlen = len / 4;__m128 new_scale = _mm_set_ps1(nowlen);for(DWORD i = 0; i < nowlen; i++){*(__m128*)(a + i*4) = _mm_mul_ps(*(__m128*)(a + i*4), new_scale);}
}void MultiplyWithoutSSE(float *a, DWORD len, float scale){for(DWORD i = 0; i < len; i++){a[i] *= scale;}
}void AddWithSSE(float *a, DWORD len, float add){DWORD nowlen = len / 4;__m128 new_add = _mm_set_ps1(nowlen);for(DWORD i = 0; i < nowlen; i++){*(__m128*)(a + i*4) = _mm_add_pd(*(__m128*)(a + i*4), new_add);}
}void AddWithoutSSE(float *a, DWORD len, float add){for(DWORD i = 0; i < len; i++){a[i] += add;}
}void SqrtWithSSE(float *a, DWORD len, float scale){DWORD nowlen = len / 4;__m128 new_add = _mm_set_ps1(nowlen);for(DWORD i = 0; i < nowlen; i++){*(__m128*)(a + i*4) = _mm_sqrt_pd(scale);}
}void SqrtWithoutSSE(float *a, DWORD len, float scale){for(DWORD i = 0; i < len; i++){a[i] = sqrt(scale);}
}void MinWithSSE(float *a, DWORD len, float scale){DWORD nowlen = len / 4;__m128 new_min = _mm_set_ps1(nowlen);for(DWORD i = 0; i < nowlen; i++){*(__m128*)(a + i*4) = _mm_min_pd(*(__m128*)(a + i*4), scale);}
}void MinWithoutSSE(float *a, DWORD len, float scale){for(DWORD i = 0; i < len; i++){a[i] = min(a[i], scale);}
}void MaxWithSSE(float *a, DWORD len, float scale){DWORD nowlen = len / 4;__m128 new_max = _mm_set_ps1(nowlen);for(DWORD i = 0; i < nowlen; i++){*(__m128*)(a + i*4) = _mm_max_pd(*(__m128*)(a + i*4), scale);}
}void MaxWithoutSSE(float *a, DWORD len, float scale){for(DWORD i = 0; i < len; i++){a[i] = max(a[i], scale);}
}void Add2WithSSE(float *a, DWORD len, float scale){DWORD nowlen = len / 4;__m128 new_and = _mm_set_ps1(nowlen);for(DWORD i = 0; i < nowlen; i++){*(__m128*)(a + i*4) = _mm_add_ps(*(__m128*)(a + i*4), scale);}
}void Add2WithoutSSE(float *a, DWORD len, float scale){for(DWORD i = 0; i < len; i++){a[i]  = (int) a[i] & (int) scale;}
}int main(){
}

2. 积分计算圆周率PI

#include "avxintrin.h"
#include "windows.h"
#include "math.h"
#include "time.h"
#include "iostream"
using namespace std;
typedef unsigned long uL;//cal PI
double calPI(size_t dt){double pi = 0;double delta = 1.0 / delta;for(size_t i = 0; i < dt; i++){double x = (double) i / dt;pi += delta / (1.0 + x * x);}return pi * 4.0;
}//cal PI with AVX
double calPIWithAVX(size_t dt){double pi = 0;double delta = 1.0 / dt;__m256d ymm0, ymm1, ymm2, ymm3, ymm4;ymm0 = _mm256_set1_pd(1.0); //赋值ymm1 = _mm256_set1_pd(delta);ymm2 = _mm256_set_pd(delta*3, delta*2, delta, 0.0);ymm4 = _mm256_setzero_pd();for(int i = 0; i <= dt-4; i+=4){ymm3 = _mm256_set1_pd(i * delta);ymm3 = _mm256_add_pd(ymm3, ymm2);ymm3 = _mm256_mul_pd(ymm3, ymm3);ymm3 = _mm256_add_pd(ymm0, ymm3);ymm3 = _mm256_div_pd(ymm1, ymm3);ymm4 = _mm256_add_pd(ymm4, ymm3);}double tmp[4] __attribute__((aligned(32))); //_attribute__((aligned(n)))// 此属性指定了指定类型的变量的最小对齐(以字节为单位)。// 如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。_mm256_store_pd(tmp, ymm4); //对齐存储pi += tmp[0] + tmp[1] + tmp[2] + tmp[3];return pi * 4.0;
}//cal PI with AVX and LOOP EXPANSION
double calPIWITHAVX2(size_t dt){double pi = 0;double delta = 1.0 / dt;__m256d ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, temp;ymm0 = _mm256_set1_pd(1.0);ymm1 = _mm256_set1_pd(delta);ymm2 = _mm256_set_pd(delta*3, delta*2, delta, 0.0);temp = _mm256_set_pd(delta*7, delta*6, delta*5, delta*4);ymm4 = _mm256_setzero_pd();ymm5 = _mm256_setzero_pd();for(int i = 0; i <= dt - 8; i += 8){ymm3 = _mm256_set1_pd(i * delta);ymm3 = _mm256_add_pd(ymm3, ymm2);ymm3 = _mm256_mul_pd(ymm3, ymm3);ymm3 = _mm256_add_pd(ymm0, ymm3);ymm3 = _mm256_div_pd(ymm1, ymm3);ymm4 = _mm256_add_pd(ymm4, ymm3);ymm6 = _mm256_set1_pd((i+4) * delta);ymm6 = _mm256_mul_pd(ymm6, temp);ymm6 = _mm256_add_pd(ymm0, ymm6);ymm6 = _mm256_div_pd(ymm1, ymm6);ymm5 = _mm256_add_pd(ymm5, ymm6);}ymm4 = _mm256_add_pd(ymm4, ymm5);double tmp[4] __attribute__((aligned(32))); //_attribute__((aligned(n)))// 此属性指定了指定类型的变量的最小对齐(以字节为单位)。// 如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。_mm256_store_pd(tmp, ymm4); //对齐存储pi += tmp[0] + tmp[1] + tmp[2] + tmp[3];return pi * 4.0;
}int main(){clock_t st = clock();calPI(1000000000);clock_t en = clock();double t = (double)(en - st) / CLOCKS_PER_SEC;printf("%.5f\n", t);st = clock();calPIWithAVX(10000000000);en = clock();t = (double)(en - st) / CLOCKS_PER_SEC;printf("%.5f\n", t);st = clock();calPIWITHAVX2(10000000000);en = clock();t = (double)(en - st) / CLOCKS_PER_SEC;printf("%.5f\n", t);return 0;
}

http://www.ppmy.cn/news/415998.html

相关文章

AVX指令集函数列表

基于Intel Intrinsics Guide 3.62&#xff0c;不包括AVX、AVX2中的以__mm开头的函数。 Arithmetic __m256i _mm256_add_epi16 (__m256i a, __m256i b) 16位整形向量a加b Add packed 16-bit integers in a and b, and store the results in dst. __m256i _mm256_add_epi32 (__…

不支持AVX指令集的电脑安装tensorflow

Tensorflow从1.6开始从AVX编译二进制文件&#xff0c;所以如果你的CPU不支持AVX 你需要 从源码编译下载旧版 安装旧版&#xff08;1.5或之前版本&#xff09;&#xff1a; pip3 install tensorflow<version> #version指定版本 但是现在很多基于tensorflow的项目都是…

AVX 指令集架构简介

AVX 指令集架构的改进和增强的功能&#xff1a; 128 位 SIMD 寄存器 xmm0 - xmm15 扩展为 256 位的 ymm0 - ymm15 寄存器支持 256 位的矢量运算&#xff0c;由原来 128 位扩展为 256 位指令可支持最多 4 个操作数&#xff0c;实现目标操作数无需损毁原来的内容引进新的 AVX 指…

avx2指令集对php有用吗,AVX2指令集:AVX指令集的加强版

◆AVX2指令集:AVX指令集的加强版 对于指令集和AVX指令集不了解的朋友可以先看看《AVX是什么?AVX指令集技术与应用解析》。当年AVX在SSE4指令集的基础上加入了256位矢量宽度、增强的数据排序、3/4个操作数、不对齐内存存取以及VEX编码方式,最直接的收益就是浮点性能最大提升了…

AVX指令集加速矩阵乘法

AVX简介 SIMD SIMD&#xff08;Single Instruction Multiple Data&#xff0c;单指令多数据流&#xff09;&#xff0c;是一种实现空间上的并行性的技术。这种技术使用一个控制器控制多个处理单元&#xff0c;同时对一组数据中的每一个数据执行相同的操作。在 SIMD 指令执行期…

SIMD、SSE、AVX指令集

指令集 指令集是指CPU能执行的所有指令的集合&#xff0c;每一指令对应一种操作&#xff0c;任何程序最终要编译成一条条指令才能让CPU识别并执行。CPU依靠指令来计算和控制系统&#xff0c;所以指令强弱是衡量CPU性能的重要指标&#xff0c;指令集也成为提高CPU效率的有效工具…

AVX application for Linux | Linux中使用AVX指令集编程踩坑

背景&#xff1a;学习使用SIMD AVX指令集&#xff0c;已经完成了一份代码&#xff0c;在Windows中能正常运行&#xff0c;想迁移到Linux中&#xff0c;结果却出现两个问题&#xff0c;最终逐渐排坑至可以正常运行。 环境&#xff1a;windows 10, ubuntu 20.04 目录 一、Window…

AVX指令集实现矩阵乘

本节矩阵乘选择方阵 思想&#xff1a;c语言默认按行优先存储&#xff0c;矩阵a * b&#xff0c;a的行连续&#xff0c;可以连续访存&#xff0c;大大提高效率&#xff1b;但是b要按列取数&#xff0c;所以去b的列向量浪费时间&#xff0c;解决办法是&#xff1a;将b转置存储&am…