SIMD

섬네일|220px|SIMD의 동작 구조. 하나의 명령어와 여러 개의 값을 다룰 수 있다.

**단일 명령어 다중 데이터**(Single instruction, multiple data, **SIMD**)는 플린 분류에서 병렬 컴퓨팅 (처리)의 한 유형이다. SIMD는 동일한 연산을 여러 데이터 지점에 동시에 수행하는 다중 처리 요소를 가진 컴퓨터를 설명한다. SIMD는 내부적(하드웨어 설계의 일부)일 수 있으며, 명령어 집합 (ISA)을 통해 직접 접근할 수 있지만, ISA와 혼동해서는 안 된다.

이러한 기계는 데이터 병렬성을 활용하지만, 동시성은 활용하지 않는다. 즉, 동시(병렬) 계산이 있지만, 각 단위는 주어진 순간에 정확히 동일한 명령어를 수행한다(단지 다른 데이터로). 간단한 예는 많은 숫자 쌍을 함께 더하는 것이다. 모든 SIMD 단위는 덧셈을 수행하지만, 각 단위는 더해야 할 다른 값 쌍을 가지고 있다. SIMD는 디지털 이미지의 대비 조정이나 디지털 오디오의 볼륨 조정과 같은 일반적인 작업에 특히 적용 가능하다. 대부분의 최신 중앙 처리 장치 (CPU) 설계에는 멀티미디어 사용 성능을 향상시키기 위한 SIMD 명령어가 포함되어 있다. 최신 CPU에서 SIMD 장치는 캐시 계층 및 프리페치 메커니즘과 밀접하게 연결되어 대규모 블록 작업 시 대기 시간을 최소화한다. 예를 들어, AVX-512를 지원하는 프로세서는 전체 캐시 라인을 미리 가져와 단일 SIMD 사이클에서 퓨즈 곱셈-덧셈 연산(FMA)을 적용할 수 있다.

SIMD는 플린의 1972년 분류법에서 세 가지 하위 범주를 가지며, 그 중 하나는 단일 명령어 다중 스레드 (SIMT)이다. SIMT는 소프트웨어 스레드 또는 하드웨어 스레드와 혼동해서는 안 된다. 둘 다 작업 시간 공유(타임 슬라이싱) 방식이다. SIMT는 진정한 동시 병렬 하드웨어 수준 실행이다. SIMT의 주요 특징은 워프(엔비디아 용어) 또는 웨이브프론트(AMD 용어)와 같은 제어 흐름 메커니즘의 존재이다. 이를 통해 공유 명령어 스트림 하에서도 스레드의 분기와 합류가 가능하여, 고전적인 SIMD보다 약간 더 많은 유연성을 제공한다.

개별 데이터 항목에서 작동하는 각 하드웨어 요소(PU)는 때때로 SIMD 레인 또는 채널이라고도 불린다. 최신 그래픽 처리 장치 (GPU)는 종종 광범위한 SIMD(일반적으로 16개 이상의 데이터 레인 또는 채널) 구현이다. 일부 최신 GPU는 단순 SIMD를 넘어 혼합 정밀도 SIMD 파이프라인을 통합하여, 8비트, 16비트, 32비트 연산을 다른 레인에서 동시에 실행할 수 있도록 한다. 이는 혼합 정밀도가 처리량을 높이는 AI 추론과 같은 애플리케이션에 매우 중요하다.

또한 SIMD는 고정 및 확장 가능한 벡터 형식으로 모두 존재할 수 있다. 고정 폭 SIMD 장치는 명령어당 일정한 수의 데이터 지점에서 작동하는 반면, RISC-V 벡터 또는 ARM의 SVE와 같은 확장 가능한 설계는 하드웨어 구현에 따라 데이터 요소의 수를 다양하게 허용한다. 이는 프로세서 세대 간의 하위 호환성을 향상시킨다.

## 역사
SIMD 명령어를 처음 사용한 것은 1972년에 완성된 ILLIAC IV였다. 여기에는 동일한 명령어를 수행하면서 다른 값을 저장할 수 있는 로컬 메모리를 가진 64개의 프로세서(원래 설계는 256개)가 포함되었다. 별도의 하드웨어는 처리할 값을 빠르게 보내고 결과를 수집했다.

SIMD는 1970년대 초 CDC 스타-100 및 텍사스 인스트루먼츠 ASC와 같은 벡터 슈퍼컴퓨터의 기반이 되었으며, 이들은 단일 명령어로 데이터 "벡터"를 처리할 수 있었다. 벡터 처리는 1970년대와 1980년대에 크레이에 의해 특히 대중화되었다. 벡터 처리 아키텍처는 이제 SIMD 컴퓨터와는 별개로 간주된다. 던컨의 분류법에는 포함되지만, 플린의 작업(1966, 1972)이 Cray-1 (1977)보다 앞섰기 때문에 플린 분류에는 포함되지 않는다.

현대 SIMD 컴퓨터의 첫 시대는 매시블리 병렬 처리 방식의 슈퍼컴퓨터인 씽킹 머신즈의 커넥션 머신 CM-1 및 CM-2로 특징지어졌다. 이 컴퓨터들은 병렬로 작동하는 많은 제한된 기능의 프로세서를 가지고 있었다. 예를 들어, 씽킹 머신즈 CM-2에 있는 65,536개의 단일 비트 프로세서 각각은 동시에 동일한 명령어를 실행하여, 예를 들어 하이퍼큐브 연결 네트워크 또는 프로세서 전용 RAM을 사용하여 피연산자를 찾아 한 번에 65,536쌍의 비트를 논리적으로 결합할 수 있었다. 슈퍼컴퓨팅은 인텔 i860 XP와 같은 상용 프로세서를 기반으로 한 저렴한 스칼라 다중 명령어 다중 데이터 (MIMD) 접근 방식이 더 강력해지면서 SIMD 접근 방식에서 멀어졌고, SIMD에 대한 관심은 시들해졌다.

현재 SIMD 프로세서 시대는 슈퍼컴퓨터 시장이 아닌 데스크톱 컴퓨터 시장에서 발전했다. 1990년대에 데스크톱 프로세서가 실시간 게임 및 오디오/비디오 처리를 지원할 만큼 강력해지면서 이러한 유형의 컴퓨팅 능력에 대한 수요가 증가했고, 마이크로프로세서 공급업체는 이러한 수요를 충족시키기 위해 SIMD에 의존했다. 이러한 부활은 DirectX 및 OpenGL 셰이더 모델의 부상과도 일치했으며, 이는 내부적으로 SIMD를 많이 활용했다. 그래픽 API는 프로그래머들이 데이터 병렬 프로그래밍 스타일을 채택하도록 장려하여, 데스크톱 소프트웨어에서 SIMD 채택을 간접적으로 가속화했다. 휴렛 팩커드는 1994년에 MPEG 디코딩을 가속화하기 위해 PA-RISC 1.1 데스크톱에 멀티미디어 가속 확장 (MAX) 명령어를 도입했다. 썬 마이크로시스템즈는 1995년에 울트라SPARC I 마이크로프로세서에 "VIS" 명령어 집합 확장에서 SIMD 정수 명령어를 도입했다. MIPS도 유사한 MDMX 시스템으로 뒤를 이었다.

가장 널리 배포된 데스크톱 SIMD는 1996년 인텔의 X86 아키텍처에 대한 MMX 확장과 함께였다. 이는 모토로라 파워PC 및 IBM의 POWER 시스템에 훨씬 더 강력한 AltiVec 시스템을 도입하는 계기가 되었다. 인텔은 1999년에 완전히 새로운 SSE 시스템을 도입하여 이에 대응했다. 그 이후로 두 아키텍처 모두 SIMD 명령어 집합에 여러 확장이 있었다. 고급 벡터 확장인 AVX, AVX2 및 AVX-512는 인텔에서 개발했다. AMD는 현재 제품에서 AVX, AVX2 및 AVX-512를 지원한다.

이 모든 개발은 실시간 그래픽 지원을 지향하며, 따라서 데이터 유형 및 아키텍처에 따라 보통 2~16 워드 길이의 벡터를 사용하여 2, 3 또는 4차원 처리를 지향한다. 새로운 SIMD 아키텍처를 이전 아키텍처와 구별해야 할 때, 새로운 아키텍처는 "단축 벡터" 아키텍처로 간주되는데, 이는 이전 SIMD 및 벡터 슈퍼컴퓨터의 벡터 길이가 64에서 64,000에 달했기 때문이다. 현대의 슈퍼컴퓨터는 거의 항상 MIMD 컴퓨터의 클러스터이며, 각 MIMD 컴퓨터는 (단축 벡터) SIMD 명령어를 구현한다.

## 장점
SIMD를 활용할 수 있는 애플리케이션은 동일한 값이 많은 데이터 포인트에 추가되거나(또는 빼지는) 경우인데, 이는 많은 멀티미디어 애플리케이션에서 흔히 볼 수 있는 작업이다. 한 가지 예는 이미지의 밝기를 변경하는 것이다. 이미지의 각 화소는 색상의 빨간색(R), 녹색(G), 파란색(B) 부분의 밝기에 대한 세 가지 값으로 구성된다. 밝기를 변경하려면 R, G, B 값을 메모리에서 읽어와서 값을 더하거나(또는 빼고) 결과 값을 다시 메모리에 쓴다. 오디오 DSP도 마찬가지로 볼륨 제어를 위해 왼쪽 및 오른쪽 채널을 동시에 곱할 것이다.

SIMD 프로세서를 사용하면 이 과정에 두 가지 개선 사항이 있다. 첫째, 데이터는 블록 단위로 이해되며, 여러 값을 한 번에 로드할 수 있다. "이 픽셀을 검색하고, 다음 픽셀을 검색하라"는 일련의 명령어 대신, SIMD 프로세서는 효과적으로 "n 픽셀을 검색하라"(여기서 n은 설계마다 다른 숫자)고 말하는 단일 명령어를 가질 것이다. 여러 가지 이유로, 이는 기존 CPU 설계에서 각 픽셀을 개별적으로 검색하는 것보다 훨씬 적은 시간이 걸릴 수 있다. 또한 SIMD 명령어는 브로드캐스팅 기능을 통해 동일한 피연산자가 여러 계산에 사용되는 데이터 재사용을 활용할 수 있다. 예를 들어, 여러 픽셀에 상수 스칼라 값을 곱하는 것은 스칼라를 한 번 로드하고 SIMD 레지스터에 브로드캐스팅함으로써 더 효율적으로 수행할 수 있다.

또 다른 장점은 명령어가 단일 작업으로 로드된 모든 데이터를 처리한다는 것이다. 즉, SIMD 시스템이 한 번에 8개의 데이터 포인트를 로드하여 작동한다면, 데이터에 적용되는 `add` 작업은 8개의 모든 값에 동시에 발생할 것이다. 이러한 병렬성은 슈퍼스칼라 프로세서가 제공하는 병렬성과는 별개이다. 8개의 값은 비슈퍼스칼라 프로세서에서도 병렬로 처리되며, 슈퍼스칼라 프로세서는 여러 SIMD 작업을 병렬로 수행할 수 있다.

## 단점
* 모든 알고리즘을 쉽게 벡터화할 수 있는 것은 아니다. 예를 들어, 코드 구문 분석과 같이 흐름 제어가 많은 작업은 SIMD의 이점을 쉽게 얻지 못할 수 있다. 그러나 이론적으로는 비교를 벡터화하고 "배치 흐름"을 사용하여 최대 캐시 최적화를 목표로 할 수 있지만, 이 기술은 더 많은 중간 상태를 필요로 한다. 참고: 배치 파이프라인 시스템(예: GPU 또는 소프트웨어 래스터화 파이프라인)은 SIMD 내장 함수로 구현될 때 캐시 제어에 가장 유리하지만, SIMD 기능에만 국한되지는 않는다. 코드 문자열과 같은 일련의 종속성을 피하기 위해 추가적인 복잡성이 나타날 수 있다. 반면 벡터화에는 독립성이 필요하다. 또한, 다른 데이터 레인이 다른 실행 경로를 따르는 발산 제어 흐름은 SIMD 하드웨어의 활용률을 저하시킬 수 있다. 이러한 발산을 처리하기 위해 마스킹 및 예측과 같은 기술이 종종 사용되지만, 성능 오버헤드와 복잡성을 초래한다.
* 대용량 레지스터 파일은 전력 소비와 필요한 칩 면적을 증가시킨다.
* 현재 SIMD 명령어를 사용하여 알고리즘을 구현하는 것은 일반적으로 사람의 노동을 필요로 한다. 예를 들어, 대부분의 컴파일러는 일반적인 C 프로그램에서 SIMD 명령어를 생성하지 않는다. 컴파일러의 자동 벡터화는 컴퓨터 과학 연구의 활발한 분야이다. (벡터 프로세서와 비교.)
* 주어진 SIMD 명령어 집합으로 프로그래밍하는 것은 많은 낮은 수준의 문제를 수반할 수 있다.
** SIMD는 데이터 정렬에 제한이 있을 수 있다. 특정 아키텍처에 익숙한 프로그래머는 이를 예상하지 못할 수 있다. 더 나쁜 것은, 정렬이 한 버전에서 다른 버전 또는 "호환" 프로세서로 변경될 수 있다는 것이다.
** 데이터를 SIMD 레지스터로 수집하고 올바른 대상 위치로 분산하는 것은 까다롭다(때로는 순열 명령어 (연산)를 필요로 하며 비효율적일 수 있다.
** 일부 SIMD 명령어 집합에서는 회전 또는 3-피연산자 덧셈과 같은 특정 명령어를 사용할 수 없다.
** 명령어 집합은 아키텍처에 따라 다르다. 일부 프로세서에는 SIMD 명령어가 전혀 없으므로 프로그래머는 비벡터화된 구현(또는 다른 벡터화된 구현)을 제공해야 한다.
** 다른 아키텍처는 다른 레지스터 크기(예: 64, 128, 256 및 512비트)와 명령어 집합을 제공하므로, 프로그래머는 모든 CPU에서 최적으로 작동하도록 벡터화된 코드의 여러 구현을 제공해야 한다. 또한, SIMD 명령어의 가능한 집합은 새로운 레지스터 크기마다 증가한다. 불행히도, 레거시 지원상의 이유로 이전 버전을 폐기할 수 없다.
** 초기 MMX 명령어 집합은 부동소수점 스택과 레지스터 파일을 공유하여 부동소수점 및 MMX 코드를 혼합할 때 비효율성을 야기했다. 그러나 SSE2는 이를 해결한다.

문제 1과 5를 해결하기 위해 RISC-V의 벡터 확장은 대안적인 접근 방식을 사용한다. 즉, 프로그래머에게 하위 레지스터 수준의 세부 정보를 노출하는 대신, 이 명령어 집합을 가진 모든 CPU에서 동일한 인터페이스를 사용하는 몇 가지 "벡터 레지스터"로 추상화한다. 하드웨어는 모든 정렬 문제와 루프의 "스트립 마이닝"을 처리한다. 다른 벡터 크기를 가진 기계는 동일한 코드를 실행할 수 있다. LLVM은 이 벡터 유형을 ""이라고 부른다.

동등한 스칼라 또는 동등한 벡터 코드와 비교할 때 코드 크기가 한 자릿수 증가하는 것은 드문 일이 아니며, 벡터 ISA를 사용하면 한 자릿수 또는 그 이상의 효율성(명령어당 수행되는 작업)을 달성할 수 있다.

ARM의 Scalable Vector Extension은 플린 분류에서 "연관 처리(Associative Processing)"로 알려진 다른 접근 방식을 취하며, 오늘날에는 일반적으로 "조건부" (마스크된) SIMD로 알려져 있다. 이 접근 방식은 벡터 프로세싱만큼 압축적이지는 않지만, 비조건부 SIMD보다 훨씬 낫다. 자세한 비교 예시는 에서 제공된다. 또한 ARM 아키텍처의 모든 버전은 메모리의 연속적인 블록에서 데이터를 레지스터 범위 또는 비연속적인 레지스터 집합으로 로드하거나 저장하는 다중 명령어 로드 및 저장을 제공한다.

## 연표

## 하드웨어
작은 규모(64비트 또는 128비트) SIMD는 1990년대 초 범용 CPU에서 인기를 얻었으며, 1997년과 그 이후까지 알파용 모션 비디오 명령어(MVI)와 함께 계속되었다. SIMD 명령어는 IBM의 AltiVec 및 파워PC용 신호 처리 엔진(SPE), 휴렛 팩커드 (HP)의 PA-RISC 멀티미디어 가속 확장 (MAX), 인텔의 MMX 및 iwMMXt, 스트리밍 SIMD 확장 (SSE), SSE2, SSE3 SSSE3 및 SSE4, AMD의 3DNow!, ARC의 ARC 비디오 서브시스템, SPARC의 VIS 및 VIS2, 썬의 MAJC, ARM의 네온 기술, MIPS의 MDMX (MaDMaX) 및 MIPS-3D를 포함하여 대부분의 CPU에서 어느 정도 찾아볼 수 있다. IBM, 소니, 도시바가 공동 개발한 셀 프로세서의 시너지 프로세싱 엘리먼트 (SPE) 명령어 집합은 SIMD 기반이 대부분이다. 필립스, 현재 NXP는 Xetal이라는 여러 SIMD 프로세서를 개발했다. Xetal은 비전 작업을 위해 특별히 설계된 320개의 16비트 프로세서 요소를 가지고 있다. 애플의 M1 및 M2 칩에는 GPU 및 Neural Engine과 깊이 통합된 SIMD 장치도 포함되어 있으며, 이미지 필터링, 컨볼루션 및 행렬 곱셈에 최적화된 애플이 설계한 SIMD 파이프라인을 사용한다. 이 통합 메모리 아키텍처는 SIMD 명령어가 공유 메모리 풀에서 더 효율적으로 작동하도록 돕는다.

인텔의 AVX-512 SIMD 명령어는 한 번에 512비트의 데이터를 처리한다.

## 소프트웨어
섬네일|280px| 일반적인 8비트 숫자 4개를 세 배로 늘리는 과정. CPU는 8비트 숫자 하나를 R1에 로드하고, R2와 곱한 다음, R3의 결과 값을 다시 RAM에 저장한다. 이 과정은 각 숫자에 대해 반복된다.
right|섬네일|280px| SIMD로 8비트 숫자 4개를 세 배로 늘리는 과정. CPU는 4개의 숫자를 한 번에 로드하고, 하나의 SIMD 곱셈으로 모두 곱한 다음, 한 번에 모두 RAM에 다시 저장한다. 이론적으로 속도는 4배가 될 수 있다.

SIMD 명령어는 3D 그래픽 처리에 널리 사용되지만, 현대의 그래픽 카드는 내장 SIMD를 통해 CPU에서 이 작업을 대부분 인계받았다. 일부 시스템은 벡터 내부의 요소를 재포장하는 순열 함수도 포함하고 있어 데이터 처리 및 압축에 특히 유용하다. 또한 암호화에도 사용된다. GPU를 이용한 범용 컴퓨팅의 추세는 미래에 SIMD의 더 넓은 사용을 가져올 수 있다. LLVM, GCC, 인텔의 ICC와 같은 최신 컴파일러는 적극적인 자동 벡터화 옵션을 제공한다. 개발자는 종종 `-O3` 또는 `-ftree-vectorize`와 같은 플래그를 사용하여 이를 활성화할 수 있으며, 이는 컴파일러가 SIMD 호환성을 위해 루프를 재구성하도록 안내한다.

개인용 컴퓨터 소프트웨어에서 SIMD 시스템의 채택은 여러 가지 문제로 인해 처음에는 느렸다. 한 가지 문제는 초기 SIMD 명령어 집합의 상당수가 기존 부동소수점 레지스터의 재사용으로 인해 시스템의 전반적인 성능을 저하시키는 경향이 있었다는 점이다. MMX 및 3DNow!와 같은 다른 시스템은 광범위한 사용자에게는 흥미롭지 않은 데이터 유형을 지원했으며, FPU와 MMX 레지스터를 사용하는 전환을 위한 값비싼 컨텍스트 스위칭 명령어를 가지고 있었다. 컴파일러도 종종 지원이 부족하여 프로그래머들이 어셈블리어 코딩에 의존해야 했다.

X86에서의 SIMD는 시작이 느렸다. AMD의 3DNow!와 인텔의 SSE의 도입은 다소 혼란을 주었지만, 오늘날에는 시스템이 정착되었고(AMD가 SSE를 채택한 후) 새로운 컴파일러는 더 많은 SIMD 지원 소프트웨어를 만들어낼 것이다. 인텔과 AMD는 이제 SIMD 명령어를 사용하는 최적화된 수학 라이브러리를 제공하며, libSIMD, SIMDx86, SLEEF와 같은 오픈 소스 대안도 나타나기 시작했다(또한 libm 참조).

애플은 SIMD 시장에 다른 회사들보다 늦게 진입했지만, 어느 정도 성공을 거두었다. AltiVec은 풍부한 시스템을 제공했으며, 모토로라, IBM, GNU의 점점 더 정교한 컴파일러를 사용하여 프로그래밍할 수 있었으므로 어셈블리어 프로그래밍은 거의 필요하지 않았다. 또한 SIMD의 이점을 누릴 수 있는 많은 시스템은 애플 자체에서 제공되었는데, 예를 들어 아이튠즈와 퀵타임이 있다. 그러나 2006년 애플 컴퓨터는 인텔 x86 프로세서로 전환했다. 애플의 API와 개발 도구 (XCode)는 SSE2 및 SSE3뿐만 아니라 AltiVec을 지원하도록 수정되었다. 애플은 IBM과 프리스케일 세미컨덕터로부터 파워PC 칩의 주요 구매자였다. 애플이 제품에서 파워PC 프로세서 사용을 중단했지만, AltiVec의 추가 개발은 프리스케일과 IBM의 여러 파워PC 및 Power ISA 설계에서 계속되고 있다.

레지스터 내 SIMD(SIMD within a register) 또는 SWAR은 SIMD 명령어를 직접 지원하지 않는 하드웨어에서 일반 목적 레지스터에서 SIMD를 수행하는 데 사용되는 다양한 기술과 요령이다. 이는 SIMD를 직접 지원하지 않는 하드웨어에서도 특정 알고리즘에서 병렬성을 활용하는 데 사용할 수 있다.

### 프로그래머 인터페이스
SIMD 명령어 집합의 개발사는 자체적인 C 및 C++ 언어 확장과 내장 함수 또는 특별한 데이터 형식(과 연산자 오버로딩)을 제공하여 벡터 코드 생성을 보장하는 것이 일반적이다. 인텔, AltiVec, ARM NEON은 CPU를 대상으로 하는 컴파일러에 널리 채택된 확장을 제공한다. (더 복잡한 연산은 벡터 수학 라이브러리의 역할이다.)

GNU C 컴파일러는 SIMD 데이터 형식을 정의하는 방법을 제공함으로써 확장 기능을 한 단계 더 발전시켜 어떤 플랫폼에서도 사용할 수 있는 범용 인터페이스로 추상화한다. LLVM Clang 컴파일러도 이 기능을 구현하며, IR에 정의된 유사한 인터페이스를 가지고 있다. Rust의  크레이트(및 실험적인 )는 이 인터페이스를 사용하며, 스위프트 2.0+도 마찬가지이다.

C++에는 GCC 확장과 유사하게 작동하는 실험적인 인터페이스 가 있다. LLVM의 libcxx는 이를 구현하는 것으로 보인다. GCC 및 libstdc++의 경우 GCC 확장을 기반으로 하는 래퍼 라이브러리를 사용할 수 있다.

마이크로소프트는 RyuJIT에서 .NET에 SIMD를 추가했다. NuGet에서 사용할 수 있는  패키지는 SIMD 데이터 형식을 구현한다. 자바도 OpenJDK 17의 인큐베이터 모듈에서 SIMD 명령어를 위한 새로운 API를 제안했다. 또한 지원되지 않는 CPU에서는 간단한 루프로 안전하게 대체되는 메커니즘도 제공한다.

SIMD 데이터 타입을 제공하는 대신, 컴파일러는 일부 루프를 자동으로 벡터화하도록 힌트를 받을 수도 있으며, 이는 데이터 종속성 부족에 대한 일부 가정을 취할 수 있다. 이는 SIMD 변수를 직접 조작하는 것만큼 유연하지는 않지만 사용하기 더 쉽다. OpenMP 4.0+에는  힌트가 있다. 이 OpenMP 인터페이스는 Cilk의 , GCC의  등을 포함한 광범위한 비표준 확장 기능을 대체했다.

### SIMD 다중 버전화
일반적으로 소비자 소프트웨어는 여러 세대의 CPU에서 작동하도록 예상되므로, 프로그래머가 프로그램의 계산 성능을 향상시키기 위해 새로운 SIMD 명령어를 사용하는 능력이 제한될 수 있다. 해결책은 오래된 SIMD 기술 또는 최신 SIMD 기술을 사용하는 동일한 코드의 여러 버전을 포함하고, 런타임에 사용자 CPU에 가장 적합한 버전을 선택하는 것이다(동적 디스패치). 주요 두 가지 해결책은 다음과 같다.
* 함수 다중 버전화 (FMV): 프로그램 또는 라이브러리의 서브루틴이 여러 명령어 집합 확장에 대해 복제 및 컴파일되며, 프로그램은 런타임에 사용할 버전을 결정한다.
* 라이브러리 다중 버전화 (LMV): 전체 프로그래밍 라이브러리가 여러 명령어 집합 확장에 대해 복제되며, 운영 체제 또는 프로그램은 런타임에 로드할 버전을 결정한다.

어셈블리어로 수동으로 코딩된 FMV는 glibc 및 libjpeg-turbo와 같은 여러 성능에 민감한 라이브러리에서 매우 일반적으로 사용된다. 인텔 C++ 컴파일러, GCC 6부터의 GNU 컴파일러 모음 및 clang 7부터의 Clang은 간소화된 접근 방식을 허용하며, 컴파일러가 함수 복제 및 선택을 처리한다. GCC 및 clang은 함수를 "클론"하기 위해 코드에 명시적인  레이블을 필요로 하는 반면, ICC는 자동으로 수행한다(명령줄 옵션  사용). 러스트 프로그래밍 언어도 FMV를 지원한다. 설정은 GCC 및 Clang과 유사하게 코드가 컴파일할 명령어 집합을 정의하지만, 복제는 인라인을 통해 수동으로 수행된다.

GCC와 Clang에서 FMV를 사용하려면 코드 수정이 필요하므로, 공급업체는 라이브러리 다중 버전화를 더 일반적으로 사용한다. 이는 컴파일러 스위치만 변경하면 되므로 달성하기 쉽다. Glibc는 LMV를 지원하며, 이 기능은 인텔이 지원하는 클리어 리눅스 프로젝트에서 채택되었다.

## 웹의 SIMD
2013년 존 맥커천은 다트 프로그래밍 언어를 위한 고성능 SIMD 명령어 집합 인터페이스를 만들었다고 발표하며, SIMD의 이점을 웹 프로그램에 처음으로 가져왔다. 이 인터페이스는 두 가지 유형으로 구성된다.
* Float32x4, 4개의 단일 정밀도 부동 소수점 값.
* Int32x4, 4개의 32비트 정수 값.

이러한 유형의 인스턴스는 불변하며 최적화된 코드에서는 SIMD 레지스터에 직접 매핑된다. 다트로 표현된 연산은 일반적으로 오버헤드 없이 단일 명령어로 컴파일된다. 이는 C 및 C++ 내장 함수와 유사하다. 4×4 행렬 곱셈, 3D 정점 변환, 망델브로 집합 시각화 벤치마크는 다트로 작성된 스칼라 코드에 비해 거의 400%의 속도 향상을 보여준다.

인텔은 IDF 2013에서 V8과 스파이더몽키 모두에 맥커천의 사양을 구현하고 있다고 발표했다. 그러나 2017년까지 SIMD.js는 웹어셈블리에서 유사한 인터페이스를 추구하기 위해 ECMA스크립트 표준 대기열에서 제외되었다. SIMD 지원은 2022년에 완성되어 2024년 12월에 공식화된 WebAssembly 2.0 사양에 추가되었다. C 또는 C++를 WebAssembly로 컴파일할 때 LLVM의 자동 벡터화는 WebAssembly SIMD를 대상으로 SIMD를 자동으로 활용할 수 있으며, SIMD 내장 함수도 사용할 수 있다.

## 상업적 응용
SIMD 전용 프로세서에 대한 지속적인 상업적 응용 분야를 찾는 것은 일반적으로 어려운 일로 입증되었다.

어느 정도 성공을 거둔 한 가지는 GAPP이다. 이는 록히드 마틴에 의해 개발되었고, 그들의 스핀오프인 Teranex에 의해 상업 부문으로 진출했다. GAPP의 최근 구현은 다양한 비디오 표준 및 프레임 속도(NTSC와/에서 PAL, NTSC와/에서 HDTV 형식 등) 간의 변환, 디인터레이스, 이미지 노이즈 감소, 적응형 영상 압축, 이미지 향상과 같은 실시간 비디오 처리 응용 분야에서 강력한 도구가 되었다.

SIMD의 더 보편적인 응용 분야는 비디오 게임에서 찾을 수 있다. 1998년 이후 거의 모든 현대 비디오 게임 콘솔은 아키텍처 어딘가에 SIMD 프로세서를 통합했다. 플레이스테이션 2는 자율적인 DSP로 자체 명령어 스트림을 실행하거나 일반 CPU 명령어에 의해 구동되는 코프로세서로 기능할 수 있는 벡터-부동 소수점 장치 중 하나를 가지고 있다는 점에서 특이했다. 3D 그래픽 응용 프로그램은 4차원 벡터를 사용하는 연산에 크게 의존하므로 SIMD 처리에 잘 적합한 경향이 있다. 마이크로소프트의 Direct3D 9.0은 이제 SIMD 지원 명령어를 포함하여 자체 수학 연산의 프로세서별 구현을 런타임에 선택한다.

벡터 처리를 사용한 후기 프로세서는 플레이스테이션 3에 사용된 셀 프로세서로, IBM이 도시바 및 소니그룹과 협력하여 개발했다. 이 프로세서는 여러 SIMD 프로세서(NUMA 아키텍처, 각각 독립적인 로컬 스토어를 가지며 범용 CPU에 의해 제어됨)를 사용하며, 3D 및 비디오 처리 응용 프로그램에 필요한 방대한 데이터 세트에 적합하다. 스칼라 레지스터가 별도로 없는 처음부터 SIMD 기반이라는 점에서 전통적인 ISA와 다르다.

Ziilabs는 미디어 플레이어 및 휴대폰과 같은 모바일 장치에 사용되는 SIMD 유형 프로세서를 생산했다.

더 큰 규모의 상업용 SIMD 프로세서는 ClearSpeed Technology, Ltd. 및 Stream Processors, Inc.에서 구할 수 있다. ClearSpeed의 CSX600(2004)은 각각 두 개의 배정밀도 부동 소수점 단위를 가진 96개의 코어를 가지고 있으며, CSX700(2008)은 192개를 가지고 있다. Stream Processors는 컴퓨터 아키텍트 빌 댈리가 이끌고 있다. 그들의 Storm-1 프로세서(2007)는 MIPS CPU에 의해 제어되는 80개의 SIMD 코어를 포함한다.

## 같이 보기
* 스트리밍 SIMD 확장
* 명령어 집합
* 플린 분류
* OpenCL

## 각주

## 외부 링크
* 텀즈 - SIMD
* SIMD architectures (2000)


분류:병렬 컴퓨팅
분류:디지털 신호 처리
분류:플린 분류