2021. 10. 12. 09:29 자기개발/SIMD
SIMD - Shift 연산, intrinsic 나눗셈 구현
각각의 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 |