자기개발/SIMD
SIMD - 최대값 구하기( C랑 비교)
pi92
2021. 10. 8. 10:33
int main(int argc, char* argv[])
{
clock_t start_c, end_c; // C언어 속도 측정을 위한 변수들
clock_t start_simd, end_simd; // SIMD 속도 측정을 위한 변수들
const int MAX_SIZE = 100000000; // 1억개 비교
short* pShortArray = new short[MAX_SIZE]; //MAX_SIZE 만큼 배열 생성
memset(pShortArray, 0x00, MAX_SIZE * sizeof(short)); //모든 배열에 0x00(0) 값을 대입
pShortArray[9000003] = 100; // 9000003번째 값에만 100 대입
int nResult = 0; //최대값 넣기 위한 변수
// c로 만든 GetMaxValueC
start_c = clock();
nResult = GetMaxValueC(pShortArray, MAX_SIZE);
end_c = clock();
cout << " C Get Value : " << nResult << ", Time : " << (end_c - start_c)/1000 << endl;
//SIMD로 만든 GetMaxValueSIMD
start_simd = clock();
nResult = GetMaxValueSIMD(pShortArray, MAX_SIZE);
end_simd = clock();
cout << "SIMD Get Value : " << nResult << ", Time : " << (end_simd - start_simd)/1000 << endl;
delete[] pShortArray;
return 0;
}
C로 만든 함수
//c로 만든 함수
short GetMaxValueC(const short *pShortArray, const int nSize)
{
short MaxValue = 0; //return 값
for (int i = 0; i < nSize; i++) //배열 크기만큼 반복
{
if (pShortArray[i] > MaxValue) //현재 값과 이전 MaxValue 값 비교
MaxValue = pShortArray[i]; //현재 값이 크면 값 대입
}
return MaxValue; //결과 리턴
}
SIMD 사용
//SIMD 사용
short GetMaxValueSIMD(const short *pShortArray, const int nSize)
{
const short* pShort = pShortArray; //스택 포인터 변수로 받아온다.
int nLoopCount = (nSize / 8) * 16; //8배수 개수를 한 번에 계산(한개당 16bit)
int nRemain = nSize % 8; //8배수 나머지 영역은 C로 구현
short nMaxValue = 0; //결과값을 가지고 있을 메모리 변수
short MaxValueArray[8] = { 0 }; //중간 결과값을 담을 배열
__asm //어셈블리
{
pushad
mov eax, pShort // eax = pShort;
// 자료구조 포인터를 레지스터에 옮긴다.
mov esi, 0 // esi = 0;
//자료구조를 indexing할 레지스터 초기화
mov ecx, nLoopCount // ecx = nLoopCount;
//순환 연산 Limit 값을 담을 변수
pxor xmm1, xmm1 // xmm1 = 0; //결괏값을 담을 레지스터 변수 초기화
FINDLP:
movdqu xmm0, [eax+esi] //xmm0 에 현재 값을 가져온다.
//xmm0 = *(eax+esi);
pmaxsw xmm1, xmm0 //8배수 만큼 각각 비교하여 xmm1에 최대값을 넣는다.
//xmm1 = __max( xmm0, xmm1)
add esi, 16 //다음 주소만큼 추가
//esi = esi + 16;
cmp esi, ecx //jne 일 경우 if( esi != ecx)
jne FINDLP //goto FINDLP
movdqu MaxValueArray, xmm1 //MaxValueArray = xmm1;
popad
}
for (unsigned char Count = 0; Count < 8; Count++)
{
//xmm1 에서 구한 값 8개를 비교하여 최종 결괏값을 구한다.
if (MaxValueArray[Count] > nMaxValue)
nMaxValue = MaxValueArray[Count];
}
if (nRemain != 0) //8의 배수가 아닌 나머지 값이 있으면 max 값 비교를 수행
{
for (int i = nSize - nRemain; i < nSize; i++)
{
if(pShortArray[i] > nMaxValue)
nMaxValue = pShortArray[i];
}
}
return nMaxValue;
}
메인함수
int main(int argc, char* argv[])
{
clock_t start_c, end_c; // C언어 속도 측정을 위한 변수들
clock_t start_simd, end_simd; // SIMD 속도 측정을 위한 변수들
const int MAX_SIZE = 100000000; // 1억개 비교
short* pShortArray = new short[MAX_SIZE]; //MAX_SIZE 만큼 배열 생성
memset(pShortArray, 0x00, MAX_SIZE * sizeof(short)); //모든 배열에 0x00(0) 값을 대입
pShortArray[9000003] = 100; // 9000003번째 값에만 100 대입
int nResult = 0; //최대값 넣기 위한 변수
// c로 만든 GetMaxValueC
start_c = clock();
nResult = GetMaxValueC(pShortArray, MAX_SIZE);
end_c = clock();
cout << " C Get Value : " << nResult << ", Time : " << (float)(end_c - start_c) / 1000 << "(s)" << endl;
//SIMD로 만든 GetMaxValueSIMD
start_simd = clock();
nResult = GetMaxValueSIMD(pShortArray, MAX_SIZE);
end_simd = clock();
cout << "SIMD Get Value : " << nResult << ", Time : " << (float)(end_simd - start_simd) / 1000 << "(s)" << endl;
delete[] pShortArray;
return 0;
}
결과
책에선 2배정도 차이난것같은데 10배차이나네..??