SIMD๋? (Single Instruction Multiple Data)
SIMD
SIMD๋ Single Instruction, Multiple Data์ ์ฝ์๋ก, ํ๋์ ๋ช ๋ น์ด๋ก ์ฌ๋ฌ ๋ฐ์ดํฐ์ ๋ํ ์ฐ์ฐ์ ๋์์ ์ํํ ์ ์๋ ๋ณ๋ ฌ ์ฒ๋ฆฌ ๊ธฐ์ ์ด๋ค.
์ด ๊ธฐ์ ์ ๋ฐ์ดํฐ๋ฅผ ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํจ์ผ๋ก์จ ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์๋ค.
์๋ฅผ ๋ค์ด, ๋ฒกํฐ๋ ํ๋ ฌ ๊ฐ์ ๋๋์ ๋ฐ์ดํฐ์ ๊ฐ์ ์ฐ์ฐ(๋ํ๊ธฐ, ๊ณฑํ๊ธฐ ๋ฑ)์ ๋ฐ๋ณต์ ์ผ๋ก ์ ์ฉํด์ผํ ๋, SIMD๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ฌํ ์ฐ์ฐ์ ํ ๋ฒ์ ์ฌ๋ฌ ๋ฐ์ดํฐ ๋จ์๋ก ์ฒ๋ฆฌํ ์ ์์ด์ ์ฒ๋ฆฌ ์๋๊ฐ ๋งค์ฐ ๋นจ๋ผ์ง๋ค.
์ปดํจํฐ์ CPU๋ GPU์์ ๋๋ฆฌ ์ฌ์ฉ๋๊ณ ์๊ณ , ํนํ ๊ทธ๋ํฝ ์ฒ๋ฆฌ, ๊ณผํ ๊ธฐ์ ๊ณ์ฐ, ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ฒ์, ๋๊ท๋ชจ ์ซ์ ์ฐ์ฐ ์ฒ๋ฆฌ ๋ฑ ๋ค์ํ ๋ถ์ผ์์ ํจ์จ์ฑ์ ๋ฐํํ๋ค.
C๋ C++์์๋ SIMD๋ฅผ ๊ตฌํํ๊ธฐ ์ํด ํน์ ํ ์ปดํ์ผ๋ฌ ํ์ฅ(ex. SSE, AVX ์ง์์ด)๋ฅผ ์ฌ์ฉํ๊ฑฐ๋, ์ธ๋ผ์ธ ์ด์ ๋ธ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๋ฑ์ด ์๋ค.
์ปดํ์ผ๋ฌ ํ์ฅ (SSE ์ฌ์ฉ)
SSE (Single Instruction, Multiple Data Extensions)
SSE๋ ๋จ์ผ ๋ช ๋ น์ด๋ก ์ฌ๋ฌ ๊ฐ์ ์ฑ๊ธ ํ๋ฆฌ์์ (32๋นํธ) ๋ถ๋ ์์์ ์๋ฅผ ๋์์ ์ฒ๋ฆฌํ ์ ์๋๋ก ํ๋ค.
#include <xmmintrin.h> // SSE ํ์ฅ์ ์ํ ํค๋
void add_floats_sse(float* a, float* b, float* result, int n)
{
// n์ 4์ ๋ฐฐ์๋ผ๊ณ ๊ฐ์
for (int i = 0; i < n; i += 4)
{
__m128 a_pack = _mm_loadu_ps(a + i); // a ๋ฐฐ์ด์์ 4๊ฐ์ ๋ถ๋ ์์์ ์๋ฅผ ๋ก๋
__m128 b_pack = _mm_loadu_ps(b + i); // b ๋ฐฐ์ด์์ 4๊ฐ์ ๋ถ๋ ์์์ ์๋ฅผ ๋ก๋
__m128 result_pack = _mm_add_ps(a_pack, b_pack); // a_pack๊ณผ b_pack์ ๋ํจ
_mm_storeu_ps(result + i, result_pack); // ๊ฒฐ๊ณผ๋ฅผ result ๋ฐฐ์ด์ ์ ์ฅ
}
}
a์ b ๋ฐฐ์ด์ ๋ถ๋ ์์์ ์๋ฅผ SSE๋ฅผ ์ด์ฉํด ํ ๋ฒ์ 4๊ฐ์ฉ ๋ํด result ๋ฐฐ์ด์ ์ ์ฅํ๋ ํจ์
์ธ๋ผ์ธ ์ด์ ๋ธ๋ฆฌ
์ธ๋ผ์ธ ์ด์ ๋ธ๋ฆฌ๋ ํน์ ์์ ์ ์ํด ์ง์ CPU ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ํด์ค๋ค.
int add_ints(int a, int b)
{
int result;
__asm__("addl %%ebx, %%eax"
: "=a" (result)
: "a" (a), "b" (b));
return result;
}
__asm__ ๊ตฌ๋ฌธ์ ์ฌ์ฉํด์ a์ b์ ๊ฐ์ ๋ํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ result์ ์ ์ฅ
์ฌ๋ฌ ์ฐ์ฐ์ ํ ๋ฒ์ ์ํํ ์ ์๋ ์ด์
SIMD ๋ช ๋ น์ด๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ ํ๋์จ์ด์ ์ง์์ด ์๊ธฐ ๋๋ฌธ์ด๋ค.
CPU ๋ด์๋ SIMD ๋ช ๋ น์ด๋ฅผ ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํ ์ ์๋ ํน์ํ ํ๋ก๊ฐ ์๋๋ฐ ์ด ํ๋ก๋ฅผ ํตํด ์ฌ๋ฌ ๋ฐ์ดํฐ๋ฅผ ๋์์ ์ฒ๋ฆฌํ ์ ์๋ค.
์๋ฅผ ๋ค์ด์ ๋ฒกํฐ ๋ง์ ์ฐ์ฐ์ ํ๋ ค๊ณ ํ ๋ ์ผ๋ฐ์ ์ธ CPU ์ฐ์ฐ์์๋ ํ ๋ฒ์ ํ๋์ ๋ฐ์ดํฐ ์์ ๋ํด์๋ง ๋ง์ ์ ์ํํ ์ ์๋ค.
๊ทธ๋์ ๋ค ์์ ๋ฐ์ดํฐ๊ฐ ์๋ค๋ฉด, ๋ค ๋ฒ์ ์ฐ์ฐ์ด ํ์ํ๋ค.
ํ์ง๋ง SIMD๋ฅผ ์ง์ํ๋ CPU ์์๋ ์ด ๋ค ์์ ๋ฐ์ดํฐ์ ๋ํ ๋ง์ ์ ํ๋์ ์ฐ์ฐ์ผ๋ก ์ฒ๋ฆฌํ ์ ์๋ค.
์ด๋ ๊ฐ๊ฐ์ ๋ฐ์ดํฐ ์์ด ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌ๋๊ธฐ ๋๋ฌธ์ด๋ค.
SIMD๋ฅผ ์ง์ํ๋ CPU์ ์ง์ํ์ง ์๋ CPU
๋๋ถ๋ถ์ ํ๋์ ์ธ CPU๋ ์ด๋ ์ ๋์ SIMD ๋ช ๋ น์ด ์ง์์ ์ ๊ณตํ๋ค.
์ธํ ๊ณผ AMD์ ์ต์ CPU๋ SSE(์คํธ๋ฆฌ๋ฐ SIMD ํ์ฅ), AVX(๊ณ ๊ธ ๋ฒกํฐ ํ์ฅ)๊ณผ ๊ฐ์ ์ฌ๋ฌ ์ธ๋์ SIMD ๋ช ๋ น์ด ์ธํธ๋ฅผ ์ง์ํ๋ค.
ํ์ง๋ง ์ค๋๋ CPU๋ ์ ์ ๋ ฅ์ ๋ชฉํ๋กํ๋ ์ผ๋ถ ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ์ CPU๋ SIMD ๋ช ๋ น์ด ์ธํธ๋ฅผ ์ง์ํ์ง ์์ ์๋ ์๋ค.
๊ทธ๋์ ๋ง์ฝ SIMD ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ ์ฝ๋๊ฐ SIMD๋ฅผ ์ง์ํ์ง ์๋ CPU์์ ์คํ๋ ๊ฒฝ์ฐ์๋ ์์ธ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ๊ณ ์ถ๋ค๋ฉด ์คํ ์์ ํ๋ก๊ทธ๋จ์ด ๋์ํ๋ CPU๊ฐ ํ์ํ SIMD ๋ช ๋ น์ด๋ฅผ ์ง์ํ๋์ง ํ์ธํด์ผ ํ๋ค. ์ด๋ CPUID๊ฐ์ ๋ช ๋ น์ด๋ฅผ ํตํด์ ํ์ธ์ด ๊ฐ๋ฅํ๋ค.
CPUID๋ฅผ ์ด์ฉํด์ SSE, SSE2, AVX ์ง์ ์ฌ๋ถ๋ฅผ ํ์ธํ๊ธฐ
__get_cpuid ํจ์๋ฅผ ์ฌ์ฉํด์ cpu์ ๊ธฐ๋ฅ์ ํ์ธํ๋ค.
eax, ebx, ecx, edx ๋ ์ง์คํฐ์์ ๋ฐํ๋ ๊ฐ์ ํน์ ๋นํธ๋ฅผ ๊ฒ์ํจ์ผ๋ก์จ SSE, SSE2, AVX ๋ช ๋ น์ด ์ธํธ์ ์ง์ ์ฌ๋ถ๋ฅผ ์ ์ ์๋ค.
ํ์ง๋ง ๋ชจ๋ ์์คํ ์ด <cpuid.h> ํค๋ ํ์ผ์ ์ง์ํ๋ ๊ฒ์ ์๋๋ค.
ํนํ Windows ์์คํ ์์๋ ์ด ํค๋ ํ์ผ์ด ์์ ์ ์์ผ๋ ๊ทธ ๊ฒฝ์ฐ์ ์ธ๋ผ์ธ ์ด์ ๋ธ๋ฆฌ ์ฌ์ฉ ๋ฑ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ๊ณ ๋ คํด์ผ ํ๋ค.
๋ํ AVX ์ง์ ํ์ธ ์์ osxsaveSupported๊ฐ ํ์ํ ์ด์ ๋ OS๊ฐ AVX ์ํ๋ฅผ ์ ์ฅํ๊ณ ๋ณต์ํ ์ ์๋ ๊ธฐ๋ฅ(OSXSAVE)๋ฅผ ์ง์ํด์ผ๋ง AVX ๋ช ๋ น์ด ์ฌ์ฉ์ด ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ด๋ค.
#include <iostream>
#include <cpuid.h>
void checkSIMDSupport()
{
unsigned int eax, ebx, ecx, edx;
// SSE์ SSE2 ์ง์ ํ์ธ
__get_cpuid(1, &eax, &ebx, &ecx, &edx);
bool sseSupport = edx & (1 << 25);
bool sse2Support = edx & (1 << 26);
// AVX ์ง์ ํ์ธ
__get_cpuid(1, &eax, &ebx, &ecx, &edx);
bool osxsaveSupported = ecx & (1 << 27);
bool avxSupport = ecx & (1 << 28) && osxsaveSupported;
// ๊ฒฐ๊ณผ ์ถ๋ ฅ
std::cout << "SSE ์ง์: " << (sseSupport ? "์" : "์๋์ค") << std::endl;
std::cout << "SSE2 ์ง์: " << (sse2Support ? "์" : "์๋์ค") << std::endl;
std::cout << "AVX ์ง์: " << (avxSupport ? "์" : "์๋์ค") << std::endl;
}
int main() {
checkSIMDSupport();
return 0;
}โ
๋ง์ฝ ์ง์ํ์ง ์๋๋ค๋ฉด SIMD๋ฅผ ์ฌ์ฉํ์ง ์๋ ๋์ฒด ์ฝ๋ ๊ฒฝ๋ก๋ฅผ ์คํํด์ผ ํ๋ค.
ํ์ง๋ง ์ต์ ์๊ตฌ ์ฌํญ์ ์ค์ ํด ํด๋น ์ํํธ์จ์ด๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด ํน์ SIMD๋ช ๋ น์ด ์ธํธ๋ฅผ ์ง์ํ๋ CPU์์๋ง ๋์ํ๋ค๋ ๊ฒ์ ๋ช ์์ ์ผ๋ก ์ต์ ์๊ตฌ ์ฌํญ์ผ๋ก ์ค์ ํ๋ฉด ํด๋น ๋ช ๋ น์ด๋ฅผ ์ง์ํ๋ CPU์์๋ ์ํํธ์จ์ด๋ฅผ ์คํํ์ง ๋ชปํ๊ฒ ํ ์๋ ์๋ค.
๋ํ ์ผ๋ถ ๊ณ ์์ค์ ํ๋ก๊ทธ๋๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํ๋ ์์ํฌ๋ ๋ค์ํ CPU ์ต์ ํ๋ฅผ ์๋์ผ๋ก ์ฒ๋ฆฌํด์ค ์ ์๋ค.
์๋ฅผ ๋ค์ด์ ์ฌ์ฉํ๋ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ SIMD ์ต์ ํ๋ฅผ ๋ด๋ถ์ ์ผ๋ก ์ง์ํ๋ค๋ฉด ๊ฐ๋ฐ์๊ฐ ์ง์ ์์ธ ์ฒ๋ฆฌ๋ฅผ ํ ํ์๊ฐ ์๋ค. ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ์คํ ์ค์ธ CPU์ ํน์ฑ์ ์๋์ผ๋ก ๊ฐ์งํ๊ณ ์ต์ ์ ์ฝ๋ ๊ฒฝ๋ก๋ฅผ ์ ํํ๋ค.
(Ex. Intel MKL, OpenBLAS, Eigen, ARM NEON)
;์ฐธ๊ณ ์ถ์ฒ
- https://en.wikipedia.org/wiki/Single_instruction,_multiple_data
- Text generated by ChatGPT, March 26, 2024, OpenAI, https://chat.openai.com/
'๐โ๏ธ(ใปโใป) > computer' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์ค๋ ๋ ๋ฐ์ฐ (thread divergence) (1) | 2024.04.12 |
---|---|
Mac VSCode-๋ท๋ท sdk ์ค๋ฅ๊ฐ ๋ฐ์ํ ๋ (The .NET Core SDK cannot be located) (0) | 2023.06.17 |
Mac ์ ๋ํฐ-VSCode ์ฐ๋ ์ค์ (M2 pro) (0) | 2023.06.17 |