SIMD基本入门
官网,需要查询什么的有用:
https://software.intel.com/sites/landingpage/IntrinsicsGuide
https://www.sunxidong.com/357.html
SIMD全称Single Instruction Multiple Data,即单指令多数据流,一次运算指令可以执行多个数据流,可以提升程序的运行速度。由于工作中,clickhouse中使用到了SSE2(Streaming SIMD Extensions 2),这里主要记录SSE2相关的指令集和函数。
一、SSE指令简介
1、SSE寄存器
SSE(为Streaming SIMD Extensions的缩写)是由 Intel公司推出的指令集,是一种SIMD指令集,而SSE2针对SSE做了扩展,不过,基本原理是一样的。
SSE有8个128位寄存器,XMM0 ~XMM7。这些128位的寄存器,可以用来存放四个32位的单精确度浮点数。SSE的浮点数运算指令就是使用这些寄存器。
2、SSE浮点运算指令分类
SSE的浮点运算指令分为两大类:Packed 和Scalar。
Packed指令是一次对XMM寄存器中的四个浮点数(即DATA0 ~ DATA3)均进行计算,而Scalar则只对XMM暂存器中的DATA0进行计算。
SSE指令的一般格式,由三部分组成,第一部分是表示指令的作用,比如加法add等,第二部分是s或者p分别表示scalar或packed,第三部分为s,表示单精度浮点数(single precision floating point data)。
常用到的sse2指令集见:
http://www.cppblog.com/tgh621/archive/2010/08/20/124113.aspx
二、SSE2函数
查询sse2的函数
https://software.intel.com/sites/landingpage/IntrinsicsGuide
https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/x7s4chk3(v=vs.100)
https://blog.csdn.net/bwl111/article/details/8979638?spm=1001.2014.3001.5501
https://blog.csdn.net/bwl111/article/details/8968956?spm=1001.2014.3001.5501
https://blog.csdn.net/bwl111/article/details/8969125?spm=1001.2014.3001.5501
https://blog.csdn.net/bwl111/article/details/8970577?spm=1001.2014.3001.5501
https://blog.csdn.net/bwl111/article/details/8979770?spm=1001.2014.3001.5501
https://blog.csdn.net/bwl111/article/details/8980449?spm=1001.2014.3001.5501
https://blog.csdn.net/bwl111/article/details/8980902?spm=1001.2014.3001.5501
三、简单例子
使用sse2指令,写个简单例子,算是简单入门吧:寻找字符串中的某个符号,并返回字符串中的第一个位置。
#include <iostream>
#include <string>
#include <emmintrin.h>
using namespace std;
int FindLocByChar(string str, char ch)
{
__m128i ch_s = _mm_set1_epi8(ch); // 16个8bit,都赋值为ch
const char * next_pos = str.c_str();
size_t len = str.length();
int i = 0;
for (; i + 15 < len; i += 16)
{
__m128i next_ch = _mm_load_si128(reinterpret_cast<const __m128i *>(next_pos + i)); // 加载128 bit的值。
__m128i eq_pos = _mm_cmpeq_epi8(ch_s, next_ch); // 比较这128bit中,哪个字节的值是相等的。如果相等的话,则赋值0xFF
uint16_t bit_mask = _mm_movemask_epi8(eq_pos); // 取16位中,每位的最高位的值,组成一个新的128bit的值,但是只有前16bit有效,直接截取
if (bit_mask)
return __builtin_ctz(bit_mask) + i * 16; // 因为加载的时候,数据是这样排列的 dst[127:0] := MEM[mem_addr+127:mem_addr]
}
while (i < len && *(next_pos + i) != ch)
i++;
return i == len ? -1 : i;
}
int main()
{
string str = "123qwe1\r23fsffhgsd45\r\n1234";
char ch = '\r';
cout << str.find_first_of(ch) << endl;
cout << FindLocByChar(str, ch) << endl;
return 0;
}
- 点赞
- 收藏
- 关注作者
评论(0)