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;
};


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM