当前位置: 首页 > news >正文

x86_64 Linux使用avx指令(补充)

x86_64 Linux使用avx指令(补充)

一些必要的函数的补充,主要包含fma相关指令,cmp比较指令以及shuffle相关的指令,这些函数在实现一些比较简单数学函数、FFT蝶形变换的用处会比较大,所以专门作为指令的进行补充。

立即数指令为何不能使用内联函数

在cmp和shuffle函数中需要使用到立即数,但是C语言是没有一种函数参数的类型是可以表示立即数据,也就是说cmp和shuffle函数如果需要使用内联汇编函数实现的格式大致是根据某一个int类型的变量,使用switch-case的形式将变量转换为函数需要的立即数格式,大致形式如下:

__m256 _mm256_cmp_ps(__m256 a,__m256 b,int imm8) 
{switch(imm8){case 0:AVX256_INLINE_x_n_xx(vcmpps,0x00,a,b);case 1:AVX256_INLINE_x_n_xx(vcmpps,0x01,a,b);case 2:AVX256_INLINE_x_n_xx(vcmpps,0x02,a,b);case 3:AVX256_INLINE_x_n_xx(vcmpps,0x03,a,b);case 4:AVX256_INLINE_x_n_xx(vcmpps,0x04,a,b);}AVX256_INLINE_x_n_xx(vcmpps,0x01,a,b);
}

通过O3优化反编译可以发现,只要_mm256_cmp_ps中给定的参数是imm8是一个立即数,_mm256_cmp_ps就会被优化成一条vcmpps指令,也不存在说什么降低指令集性能的情况,按理说这种带立即数的这样写就完事了。但是_mm256_shuffle_ps这种函数该怎么办,这种是拿立即数当掩码用的,如果是拿switch-case需要展开256次,如果真这么写,以后一个带掩码的内联函数都得写几百行,内联函数又要求函数完整的出现在头文件中,多加几个带掩码的avx指令,这头文件都没法看了。
因此,这里就只能使用宏定义函数实现对应的功能,问题也是有的,就是不能看出变量的类型到底是什么样的,所以就在变量名上下功夫,如__m256类型的就以__m256_a、__m256_b表示其输入是一个256位的向量类型的变量;interl的官方文档中avx汇编指令部分均是以imm8表示立即数,这里也沿用这种写法,以imm8表示立即数。当然因为宏定义函数没有对变量的类型的强制限制,可能会存在一些使用上的BUG。
当然我还是希望C语言能够出一种函数的参数类型,能用于表示立即数,或者在内联汇编函数中对"i"(num)中的num只能是立即数而不能是变量的问题进行修复。

avx指令补充

#define AVX256_INLINE_x_xxx(op,a,b,c) {__m256 result;__asm__ volatile (#op " %2, %1, %0": "=x" (result.__float32__): "x" (a.__float32__), "x" (b.__float32__), "0" (c.__float32__));return result;}#define AVX256_INLINE_x_n_xx(op,num,a,b) ({__m256 result;__asm__ volatile (#op " $"#num ", %1, %2, %0": "=x" (result.__float32__): "x" (a.__float32__), "x" (b.__float32__)); result;})static inline __m256 _mm256_floor_pd(__m256 a) AVX256_INLINE_x_n_x(vroundpd,0x01,a);
static inline __m256 _mm256_ceil_ps(__m256 a) AVX256_INLINE_x_n_x(vroundps,0x02,a);
static inline __m256 _mm256_ceil_pd(__m256 a) AVX256_INLINE_x_n_x(vroundpd,0x02,a);static inline __m256 _mm256_fmadd_ps(__m256 a, __m256 b, __m256 c) AVX256_INLINE_x_xxx(vfmadd231ps,a,b,c);
static inline __m256 _mm256_fmadd_pd(__m256 a, __m256 b, __m256 c) AVX256_INLINE_x_xxx(vfmadd231pd,a,b,c);static inline __m256 _mm256_fmsub_ps(__m256 a, __m256 b, __m256 c) AVX256_INLINE_x_xxx(vfmsub231ps,a,b,c);
static inline __m256 _mm256_fmsub_pd(__m256 a, __m256 b, __m256 c) AVX256_INLINE_x_xxx(vfmsub231pd,a,b,c);static inline __m256 _mm256_fnmadd_ps(__m256 a, __m256 b, __m256 c) AVX256_INLINE_x_xxx(vfnmsadd231ps,a,b,c);
static inline __m256 _mm256_fnmadd_pd(__m256 a, __m256 b, __m256 c) AVX256_INLINE_x_xxx(vfnmsadd231pd,a,b,c);static inline __m256 _mm256_fnmsub_ps(__m256 a, __m256 b, __m256 c) AVX256_INLINE_x_xxx(vfnmsub231ps,a,b,c);
static inline __m256 _mm256_fnmsub_pd(__m256 a, __m256 b, __m256 c) AVX256_INLINE_x_xxx(vfnmsub231pd,a,b,c);static inline __m256 _mm256_fmsubadd_ps(__m256 a, __m256 b, __m256 c) AVX256_INLINE_x_xxx(vfmsubadd231ps,a,b,c);
static inline __m256 _mm256_fmsubadd_pd(__m256 a, __m256 b, __m256 c) AVX256_INLINE_x_xxx(vfmsubadd231pd,a,b,c);static inline __m256 _mm256_fmaddsub_ps(__m256 a, __m256 b, __m256 c) AVX256_INLINE_x_xxx(vfmaddsub231ps,a,b,c);
static inline __m256 _mm256_fmaddsub_pd(__m256 a, __m256 b, __m256 c) AVX256_INLINE_x_xxx(vfmaddsub231pd,a,b,c);// __m256_a:__m256,__m256_b:__m256,imm8:立即数 return:__m256     
#define _mm256_cmp_ps(__m256_a,__m256_b,imm8) AVX256_INLINE_x_n_xx(vcmpps,imm8,__m256_a,__m256_b);
// __m256_a:__m256,__m256_b:__m256,imm8:立即数 return:__m256
#define _mm256_cmp_pd(__m256_a,__m256_b,imm8) AVX256_INLINE_x_n_xx(vcmppd,imm8,__m256_a,__m256_b);
// __m256_a:__m256,__m256_b:__m256,imm8:立即数 return:__m256
#define _mm256_shuffle_ps(__m256_a,__m256_b,imm8) AVX256_INLINE_x_n_xx(vshufps,imm8,__m256_a,__m256_b);
// __m256_a:__m256,__m256_b:__m256,imm8:立即数 return:__m256
#define _mm256_shuffle_pd(__m256_a,__m256_b,imm8) AVX256_INLINE_x_n_xx(vshufpd,imm8,__m256_a,__m256_b);static inline __m256 _mm256_odd_epi64(__m256 a)
{return _mm256_and_epi64(a,_mm256_set1_epi64(1));
}static inline __m256 _mm256_odd_epi32(__m256 a)
{return _mm256_and_epi32(a,_mm256_set1_epi32(1));
}static inline __m256 _mm256_odd_epi16(__m256 a)
{return _mm256_and_epi16(a,_mm256_set1_epi16(1));
}static inline __m256 _mm256_odd_epi8(__m256 a)
{return _mm256_and_epi8(a,_mm256_set1_epi8(1));
}static inline __m256 _mm256_even_epi64(__m256 a)
{return _mm256_sub_epi64(_mm256_set1_epi64(1),_mm256_and_epi64(a,_mm256_set1_epi64(1)));
}static inline __m256 _mm256_even_epi32(__m256 a)
{return _mm256_sub_epi32(_mm256_set1_epi32(1),_mm256_and_epi32(a,_mm256_set1_epi32(1)));
}static inline __m256 _mm256_even_epi16(__m256 a)
{return _mm256_sub_epi16(_mm256_set1_epi16(1),_mm256_and_epi16(a,_mm256_set1_epi16(1)));
}static inline __m256 _mm256_even_epi8(__m256 a)
{return _mm256_sub_epi8(_mm256_set1_epi8(1),_mm256_and_epi8(a,_mm256_set1_epi8(1)));
}

说明

__m256定义以及一些基本的avx函数在之前的一篇博客中展示过。使用这里面的函数时不能#include <immintrin.h> ,因函数和变量名存在冲突。

仓库

x86_64 Linux使用avx指令

http://www.xdnf.cn/news/243253.html

相关文章:

  • RISC-V AIA SPEC学习(四)
  • python如何把pdf转word
  • (33)VTK C++开发示例 ---图片转3D
  • Lucene多种数据类型使用说明
  • 文献阅读篇#5:5月一区好文阅读,BFA-YOLO,用于建筑信息建模!(上)
  • 段永平浙大访谈精华:长期主义的知行合一
  • 类成员函数编译链接的过程
  • Spark-小练试刀
  • centos7 离线安装python3 保留python2
  • 华为eNSP:多区域集成IS-IS
  • 数据升降级:医疗数据的“时空穿梭“系统工程(分析与架构篇)
  • Linux btop 使用教程
  • 三元运算符与扩展运算符
  • Java 中的 CopyOnWriteArrayList
  • 11.多边形的三角剖分 (Triangulation) : 画廊问题
  • Postgresql源码(145)优化器nestloop参数化路径评估不准问题分析
  • WSGI(Web Server Gateway Interface)服务器
  • Seata服务端同步提交事务核心源码解析
  • MySQL零基础入门:Ubuntu环境安装与操作精解
  • 深度探索DeepSeek:从架构设计到性能优化的实战指南
  • WPF嵌入webapi服务器,充当微服务角色
  • ActiveMQ 性能优化与网络配置实战(二)
  • 使用Python和Pandas实现的Snowflake权限检查与SQL生成用于IT审计
  • 利用无事务方式插入数据库解决并发插入问题
  • windows系统搭建自己的ftp服务器,保姆级教程(用户验证+无验证)
  • OkHttp3.X 工具类封装:链式调用,支持HTTPS、重试、文件上传【内含常用设计模式设计示例】
  • 深度学习基础--目标检测入门简介
  • PHP之CURL通过header传参数及接收
  • day12:遗传算法及常见优化算法分享
  • 指针与算法的双人舞:蓝桥杯两道趣味题的降维打击