각각의 pack 안에 있는 값을 shift 연산한다. SHift 연산을 실행하면 2배수 곱 또는 나눈 효과를 얻을 수 있다.

 

#include <iostream>
#include <afx.h>
using namespace std;
#include <emmintrin.h>

int main(int argc, char* argv[])
{
	__declspec(align(16)) short A[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
	__declspec(align(16)) short B[8] = { -1, -2, -3, -4, -5, -6 , -7, -8 };
	__declspec(align(16)) short R[8] = { 0 };

	__m128i xmmA = _mm_load_si128((__m128i*)A);				//양수값 입력
	__m128i xmmB = _mm_load_si128((__m128i*)B);				//음수값 입력

	__m128i xmmR = _mm_slli_epi16(xmmA, 1);					//양수 왼쪽 shift 연산
	_mm_store_si128((__m128i*)R, xmmR);						//결과 출력	
	cout << "Left Shift : " << R[7] << ", " << R[6] << ", " << R[5] << ", " << R[4] << ", " << R[3] << ", " << R[2] << ", " << R[1] << ", " << R[0] << endl;


	xmmR = _mm_slli_epi16(xmmB, 1);							//음수 왼쪽 shift 연산
	_mm_store_si128((__m128i*)R, xmmR);						//결과 출력
	cout << "Left Shift : " << R[7] << ", " << R[6] << ", " << R[5] << ", " << R[4] << ", " << R[3] << ", " << R[2] << ", " << R[1] << ", " << R[0] << endl;


	xmmR = _mm_srai_epi16(xmmA, 1);							//양수 산술적 오른쪽 shift 연산
	_mm_store_si128((__m128i*)R, xmmR);						//결과 출력
	cout << "Arithmetic Right Shift : " << R[7] << ", " << R[6] << ", " << R[5] << ", " << R[4] << ", " << R[3] << ", " << R[2] << ", " << R[1] << ", " << R[0] << endl;


	xmmR = _mm_srli_epi16(xmmA, 1);							//양수 논리적 오른쪽 shift 연산
	_mm_store_si128((__m128i*)R, xmmR);						//결과 출력
	cout << "Logical Right Shift : " << R[7] << ", " << R[6] << ", " << R[5] << ", " << R[4] << ", " << R[3] << ", " << R[2] << ", " << R[1] << ", " << R[0] << endl;


	xmmR = _mm_srai_epi16(xmmB, 1);							//음수 산술적 오른쪽 shift 연산
	_mm_store_si128((__m128i*)R, xmmR);						//결과 출력
	cout << "Arithmetic Right Shift : " << R[7] << ", " << R[6] << ", " << R[5] << ", " << R[4] << ", " << R[3] << ", " << R[2] << ", " << R[1] << ", " << R[0] << endl;


	xmmR = _mm_srli_epi16(xmmB, 1);							//음수 논리적 왼쪽 shift 연산
	_mm_store_si128((__m128i*)R, xmmR);						//결과 출력
	cout << "Logical Right Shift : " << R[7] << ", " << R[6] << ", " << R[5] << ", " << R[4] << ", " << R[3] << ", " << R[2] << ", " << R[1] << ", " << R[0] << endl;

	return 0;
}

실행결과

왼쪽 shift 연산에 대해서는 양수와 음수 모두 결과에 이상이 없음을 볼 수 있다. 오른쪽 shift연산의 경우 양수일 떄는 산술적 shift 와 논리적 shift 모두 이상이 없다. 하지만, 음수일 떄는 논리적 오른쪽 shift의 경우 모두 큰 양수 값으로 결과가 바뀌는 오류가 발생하였다. 오른쪽 shift의 경우 음수 연산에 대하여 나눗셈 연산이 목적이라면 산술적 shift를 사용해야 한다.

 

- 나눗셈 구현

 

정수형 intrinsic 함수에서 나눗셈을 지원하지 않기 때문에 shift 연산으로 대체해야 한다.

 

#include <iostream>
#include <afx.h>
using namespace std;
#include <emmintrin.h>

int main(int argc, char* argv[])
{
	short nA = 149;
	short nB = 9;
	short nR = nA / nB;

	cout << "C Div : " << nA << " / " << nB << " = " << nR << endl;

	__declspec(align(16)) short A[8] = { 149,149,149,149,149,149,149,149 };

	__declspec(align(16)) short R[8] = { 0 };

	__m128i xmmA = _mm_load_si128((__m128i*)A);
	__m128i xmmB = _mm_set1_epi16(256/9);

	xmmA = _mm_mullo_epi16(xmmA, xmmB);

	__m128i xmmR = _mm_srai_epi16(xmmA, 8);

	_mm_store_si128((__m128i*)R, xmmR);
	cout << "intrinsic Div : " << R[7] << ", " << R[6] << ", " << R[5] << ", " << R[4] << ", " << R[3] << ", " << R[2] << ", " << R[1] << ", " << R[0] << endl;

	return 0;
}

실행결과

__m128i xmmB = _mm_set1_epi16(256/9); 에서 나눗셈이 되는데 왜 안된다는지 잘 모르겠다...

'자기개발 > SIMD' 카테고리의 다른 글

SIMD - Unpack, Pack 함수  (0) 2021.10.12
SIMD - 비교 연산  (0) 2021.10.12
SIMD - Intrinsics 세트 함수(값 입력 함수)  (0) 2021.10.08
SIMD - Intrinsics 정수의 산술 연산  (0) 2021.10.08
SIMD - Intrinsics 개요  (0) 2021.10.08
Posted by pi92

블로그 이미지
pi92

공지사항

Yesterday
Today
Total

달력

 « |  » 2025.5
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

최근에 올라온 글

최근에 달린 댓글

글 보관함