RuNaPi 2022. 10. 26. 12:29

SIMD는 병렬처리의 한 종류로, 하나의 명령어로 여러 개의 값을 동시에 계산하는 방법이다.

SIMD의 동작 구조. 하나의 명령어와 여러 개의 값을 다룰 수 있다.

벡터나 행렬과 같은 다량의 데이터를 계산하는데 유리하기에 그래픽스를 처리하기에 유리하다.

struct Vector4
{
	union { float x, r; };
	union { float y, g; };
	union { float z, b; };
	union { float w, a; };

	Vector4() = default;
	Vector4(const Vector4&) = default;
};

inline Vector4 __vectorcall operator+ (Vector4 V1, Vector4 V2)
{
	Vector4 result;

	result.x = V1.x + V2.x;
	result.y = V1.y + V2.y;
	result.z = V1.z + V2.z;
	result.w = V1.w + V2.w;

	return result;
}

int main()
{
	Vector4 vector1{ 1, 2, 3, 4 };
	Vector4 vector2{ 5, 6, 7, 8 };

	Vector4 vector3 = vector1 + vector2;
}

SISD 로 처리 할 경우

#include <xmmintrin.h>
#include <emmintrin.h>

using Vector = __m128;

inline Vector __vectorcall operator+(Vector V1, Vector V2)
{
	return _mm_add_ps(V1, V2);
}


int main()
{
	Vector vector1 = _mm_set_ps(1, 2, 3, 4);
	Vector vector2 = _mm_set_ps(5, 6, 7, 8);

	Vector vector3 = vector1 + vector2;
}

SIMD(SSE)로 처리 할 경우

SISD로 처리 할때보다 SIMD로 처리 할 경우 명령어가 많이 줄어든 것을 확인 할 수 있다.

#include <time.h>
#include <iostream>
#include <xmmintrin.h>
#include <emmintrin.h>


__declspec(align(16)) struct Vector4
{
	union { float x, r; };
	union { float y, g; };
	union { float z, b; };
	union { float w, a; };

	Vector4() = default;
	Vector4(const Vector4&) = default;
};

inline Vector4 __vectorcall operator+= (Vector4& V1, Vector4 V2)
{
	V1.x += V2.x;
	V1.y += V2.y;
	V1.z += V2.z;
	V1.w += V2.w;

	return V1;
}

using Vector = __m128;

inline Vector& __vectorcall operator+=(Vector& V1, Vector V2)
{
	V1 = _mm_add_ps(V1, V2);
	return V1;
}

int main()
{
	{
		clock_t start = clock();
		Vector4 vector1{ 0,  };
		Vector4 vector2{ 1, 2, 3, 4 };

		for (int i = 0; i < Test_Time; i++)
		{
			vector1 += vector2;
		}

		clock_t end = clock();
		std::cout << "SISD :" << (float)(end - start) / CLOCKS_PER_SEC << '\n';
	}


	{
		clock_t start = clock();
		Vector vector1{ 0, };
		Vector vector2{ 1, 2, 3, 4 };

		for (int i = 0; i < Test_Time; i++)
		{
			vector1 += vector2;
		}

		clock_t end = clock();
		std::cout << "SIMD :" << (float)(end - start) / CLOCKS_PER_SEC << '\n';
	}
}