SIMD๋ž€? (Single Instruction Multiple Data)

2024. 3. 26. 13:48

 

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/

 

BELATED ARTICLES

more