2021. 10. 7. 17:18 자기개발/SIMD
SIMD - 정수 연산 SIMD 프로그래밍(XMM 값 대입, 논리 연산)
SIMD에는 정수형과 실수형 두 가지 병렬 연산 방식이 있다. 내포하고 있는 Pack의 형태에 따라 연산하는 방식이 달라지기 때문이다. 초기 MMX에는 64bit 병렬 연산만 가능하였으나 SSE2fh sjadjdhaustj 128bit 병렬 연산이 가능해졌다.
명명법
P<SIMD_op><suffix>
접두사 P는 'packed'를 의미하며 정수형 SIMD 명령어이다. 실수형 SIMD 명령어는 P 접사가 뒤에 붙어 실수형과 정수형을 구분하게 된다(4장 참조).
<SIMD_op> : 실제 연산을 수행할 내용(명령어)이 오게 된다. 예를 들면 덧셈일 경우 ADD, 뺄셈일 경우 SUB와 같이 연산을 의마하게 되는 단어가 오게 된다.
<suffix> : 연산을 수행할 pack의 사이즈를 의미하는 접미사가 오게 된다.
MOVDQU : Move Unaligned Double Quad word
- 128bit 레지스터 혹은 128bit 메모리에 정렬되어 있지 않은 값을 읽어올 때 사용한다.
-------------------------------------------
MOVDQU xmm1. xmm2/m128
MOVDQU xmm2/m128, xmm1
-------------------------------------------
int main(int argc, char* argv[])
{
short ShortArrayA[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
short ShortArrayB[8]{ 0 };
__asm
{
pushad
movdqu xmm0, ShortArrayA //xmm0 = ShortArrayA
//ShortArrayA 메모리 변수를 xmm0 레지스터에 대입
movdqu ShortArrayB, xmm0 //ShortArrayB = xmm0
//xmm0 레지스터의 값을 ShortArrayB 메모리에 대입
popad
}
cout << "ShortArrayB : " << ShortArrayB[7]<<", " << ShortArrayB[6] << ", " << ShortArrayB[5] << ", " << ShortArrayB[4] << ", "
<< ShortArrayB[3] << ", " << ShortArrayB[2] << ", " << ShortArrayB[1] << ", " << ShortArrayB[0] << endl;
return 0;
}
MOVDQU : Move Aligned Double Quad word
- 128bit 레지스터 혹은 128bit 메모리에 정렬되어 있는 값을 읽어올 때 사용한다. 메모리가 정렬되어 있으므로 movdqu보다 빠른 속도로 값을 읽어올 수 있다.
-------------------------------------------
MOVDQA xmm1. xmm2/m128
MOVDQA xmm2/m128, xmm1
-------------------------------------------
int main(int argc, char* argv[])
{
__declspec(align(16)) short ShortArrayA[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
__declspec(align(16)) short ShortArrayB[8]{ 0 };
__asm
{
pushad
movdqu xmm0, ShortArrayA //xmm0 = ShortArrayA
//ShortArrayA 메모리 변수를 xmm0 레지스터에 대입
movdqu ShortArrayB, xmm0 //ShortArrayB = xmm0
//xmm0 레지스터의 값을 ShortArrayB 메모리에 대입
popad
}
cout << "ShortArrayB : " << ShortArrayB[7]<<", " << ShortArrayB[6] << ", " << ShortArrayB[5] << ", " << ShortArrayB[4] << ", "
<< ShortArrayB[3] << ", " << ShortArrayB[2] << ", " << ShortArrayB[1] << ", " << ShortArrayB[0] << endl;
return 0;
}
논리 연산
128bit XMM 레지스터의 모든 값에 대해 bit 연산을 수행한다. 논리 연산으로 동작하는 규칙은 같으며 128bit 모두에 대해 이루어지는 것이 다르다.
-PAND (Bitwise Logical And)
2개의 128bit XMM 레지스터를 받아서 bit 단위 AND 연산을 수행한다. 비교 연산 후 충족하는 값만 뽑아낼 때 많이 사용한다.
-------------------------------------------
PAND xmm1, xmm2/m128
-------------------------------------------
-POR (Bitwise Logical OR)
2개의 128bit XMM 레지스터를 받아서 bit 단위 OR 연산을 수행한다.
-------------------------------------------
POR xmm1, xmm2/m128
-------------------------------------------
-PXOR (Bitwise Logical Exclusive OR)
2개의 128bit XMM 레지스터를 받아서 bit 단위 XOR 연산을 수행한다. 만일 같은 레지스터에 대하여 XOR 연산을 수행하면 해당 레지스터는 0으로 초기화된다. 따라서 레지스터를 초기화할 때 많이 사용된다.
-------------------------------------------
PXOR xmm1, xmm2/m128
-------------------------------------------
-PANDN (Bitwise Logical And Not)
2개의 128bit XMM 레지스터를 받아서 bit 단위 ANDNOT연산을 수행한다.
-------------------------------------------
PANDN xmm1, xmm2/m128
-------------------------------------------
int main(int argc, char* argv[])
{
__declspec(align(16)) int IntArrayA[4] = { 1, 1, 0, 0 };
__declspec(align(16)) int IntArrayB[4] = { 1, 0, 1, 0 };
__declspec(align(16)) int ANDResult[4] = { 0 }; //0으로 초기화
__declspec(align(16)) int ORResult[4] = { 0 }; //0으로 초기화
__declspec(align(16)) int XORResult[4] = { 0 }; //0으로 초기화
__declspec(align(16)) int ANDNOTResult[4] = { 0 }; //0으로 초기화
__asm
{
pushad
movdqa xmm0, IntArrayA //xmm0 = IntArrayA;
movdqa xmm1, xmm0 //xmm1 = xmm0;
movdqa xmm2, xmm0 //xmm2 = xmm0;
movdqa xmm3, xmm0 //xmm3 = xmm0;
movdqa xmm4, IntArrayB //xmm4 = IntArrayB;
pand xmm0, xmm4 //AND 연산
por xmm1, xmm4 //OR 연산
pxor xmm2, xmm4 //XOR 연산
pandn xmm3, xmm4 //ANDNOT 연산
movdqa ANDResult, xmm0 //ANDResult = xmm0;
movdqa ORResult, xmm1 //ORResult = xmm1;
movdqa XORResult, xmm2 //XORResult = xmm2;
movdqa ANDNOTResult, xmm3 //ANDNOTResult = xmm3;
popad
}
cout << "ANDResult : " << ANDResult[0] << ", " << ANDResult[1] << ", " << ANDResult[2] << ", " << ANDResult[3] << endl;
cout << "ORResult : " << ORResult[0] << ", " << ORResult[1] << ", " << ORResult[2] << ", " << ORResult[3] << endl;
cout << "XORResult : " << XORResult[0] << ", " << XORResult[1] << ", " << XORResult[2] << ", " << XORResult[3] << endl;
cout << "ANDNOTResult : " << ANDNOTResult[0] << ", " << ANDNOTResult[1] << ", " << ANDNOTResult[2] << ", " << ANDNOTResult[3] << endl;
return 0;
}
'자기개발 > SIMD' 카테고리의 다른 글
SIMD - Intrinsics 개요 (0) | 2021.10.08 |
---|---|
SIMD - memcpy구현 (0) | 2021.10.08 |
SIMD - 최대값 구하기( C랑 비교) (0) | 2021.10.08 |
SIMD - (feat C++, Assembly 조건 제어문) (0) | 2021.10.07 |
SIMD 알아보기 (feat C++, Assembly 연산) (0) | 2021.10.07 |