sse4.2 指令集

sse4.2 指令集

简介

全称是 Sreaming SIMD Extensions, 它是一组Intel CPU指令,用于像信号处理、科学计算或者3D图形计算一样的应用。其优势包括:更高分辨率的图像浏览和处理、高质量音频、MPEG2视频、同时MPEG2加解密;语音识别占用更少CPU资源;更高精度和更快响应速度。使用SSE指令集,主要是通过8个128-bit的寄存器:xmm0到xmm7 来完成的。在Linux下可以使用cat /proc/cpuinfo来查看CPU支持哪些指令集。 SSE的指令集是X86架构CPU特有的,对于ARM架构、MIPS架构等CPU是不支持的,所以使用了SSE指令集的程序,是不具备可移植标准的。

sse4.2 指令集为什么比普通指令集快

SSE(Stream SIMD Extentions,数据流单指令多数据扩展)是英特尔继MMX(Multi Media eXtension,多媒体扩展指令集)之后推出的新一代CPU指令集。MMX提供了8个64bit的寄存器进行SIMD操作,SSE系列提供了8个128bit的寄存器进行SIMD操作。而最新的AVX指令则支持256bit的SIMD操作。

如下图所示,SSE新增的8个128位寄存器(xmm0 ~ xmm7),每个寄存器可以用来存放4个32位单精度浮点数,8个16位整型数。也就是说,SSE中的所有计算都是一次性针对4个浮点数来完成的,这种批处理会带来显著的效率提升。使用SSE优化之后,我们的代码不一定会得到4倍速的提升,因为编译器可能已经自动对某些代码进行SSE优化了。

avatar

如何使用sse指令

使用SSE指令有两种方式:一是直接在C/C++中嵌入(汇编)指令;二是使用Intel C++ Compiler或是Microsoft Visual C++中提供的支持SSE指令集的intrinsics内联函数。从代码可读和维护角度讲,推荐使用intrinsics内联函数的形式。intrinsics是对MMX、SSE等指令集的一种封装,以函数的形式提供,使得程序员更容易编写和使用这些高级指令,在编译的时候,这些函数会被内联为汇编,不会产生函数调用的开销。想要使用SSE指令,则需要包含对应的头文件:

#include <mmintrin.h>   //mmx
#include <xmmintrin.h>  //sse
#include <emmintrin.h>  //sse2
#include <pmmintrin.h>  //sse3

1:#pragma simd //使用编译器指示符
2:使用内置函数(intrinsics)的方式,如SSE _mm_add_ps

使用sse4.2优化 crc32c

通用写法,支持4字节、2字节、1字节对齐的crc 运算

#include "nmmintrin.h"

uint32_t extend(uint32_t init_crc, const char *data, size_t n)
{
	uint32_t res = init_crc ^ 0xffffffff;
	size_t i;
#ifdef __x86_64__
	uint64_t *ptr_u64;
	uint64_t tmp;
#endif
	uint32_t *ptr_u32;
	uint16_t *ptr_u16;
	uint8_t *ptr_u8;
	// aligned to machine word's boundary
	for (i = 0; (i < n) && ((intptr_t)(data + i) & ALIGN_MASK); ++i) {
		res = _mm_crc32_u8(res, data[i]);
	}

#ifdef __x86_64__
	tmp = res;
	while (n - i >= sizeof(uint64_t)) {
		ptr_u64 = (uint64_t *)&data[i];
		tmp = _mm_crc32_u64(tmp, *ptr_u64);
		i += sizeof(uint64_t);
	}
	res = (uint32_t)tmp;
#endif

	while (n - i >= sizeof(uint32_t)) {
		ptr_u32 = (uint32_t *)&data[i];
		res = _mm_crc32_u32(res, *ptr_u32);
		i += sizeof(uint32_t);
	}
	while (n - i >= sizeof(uint16_t)) {
		ptr_u16 = (uint16_t *)&data[i];
		res = _mm_crc32_u16(res, *ptr_u16);
		i += sizeof(uint16_t);
	}
	while (n - i >= sizeof(uint8_t)) {
		ptr_u8 = (uint8_t *)&data[i];
		res = _mm_crc32_u8(res, *ptr_u8);
		i += sizeof(uint8_t);
	}

	return res ^ 0xffffffff;
};
posted @ 2021-01-22 15:47  boht  阅读(1606)  评论(0编辑  收藏  举报