벡터 프로세서

벡터 프로세서(Vector processor) 또는 어레이 프로세서(Array processor)는 벡터라고 불리는 다수의 데이터를 처리하는 명령어를 가진 CPU를 말한다. 컴퓨터에서 벡터란 1차원 배열의 데이터를 뜻한다. 벡터 프로세서와 반대되는 말로는 스칼라 프로세서가 있는데 한 개의 데이터를 처리하는 명령어를 가진 프로세서를 말한다. 대부분의 CPU는 스칼라 프로세서이다.
벡터 프로세서는 1970년대 처음 나타났으며 1980년에서 1990년대 동안 슈퍼 컴퓨터의 기본적인 형태였다. 스칼라 프로세서, 특히 마이크로프로세서에서 성능을 높이기 위해 벡터 프로세서 기술을 도입한 CPU가 1990년대 초 나타났다. 오늘날 대부분의 CPU는 MMX, SSE, 알티벡(AltiVec) 같이 다수의 데이터를 처리하는 벡터 프로세싱을 위한 SIMD(Single Instruction Multiple Data) 명령어를 갖추고 있다. 벡터 프로세서 기술은 그래픽 가속기나 게임 콘솔에서도 찾아 볼 수 있다. 2000년 IBM, 도시바, 소니가 개발한 셀(Cell) 프로세서는 1개의 스칼라 프로세서와 8개의 벡터 프로세서로 구성되어 있으며 플레이스테이션 3에 사용되었다.
벡터 프로세싱을 위한 또 다른 CPU 디자인으로 다수의 명령어로 다수의 데이터를 처리하는 MIMD (Multiple Instruction Multiple Data) 가 있지만 전문적인 용도로만 사용될 뿐 일반적인 용도로 쓰이지는 않았다.

역사

최초로 동작되는 벡터 프로세서는 1960년대 초, 웨스팅하우스(Westinghouse)의 솔로몬 프로젝트였다. 솔로몬의 목표는 많은 수의 단순한 수치 연산 코프로세서(ALU)를 1개의 마스터 CPU로 제어하는 방법을 사용해 수치 연산 성능을 극적으로 끌어 올리는 것 이었다. CPU는 사이클 당 하나의 공통 명령어를 모든 ALU로 보냈지만 데이터는 ALU 마다 각각 다르게 보내주었다. 이 방법은 솔로몬 머신에서 하나의 알고리즘을 배열 형태의 많은 데이터에 이용할 수 있도록 해 준다. 1962년 웨스팅하우스는 솔로몬 프로젝트를 중단하였지만 벡터 프로세서의 개발에 대한 노력은 일리노이즈 대학 (University of Illinois) 의 일리악 IV (ILLIAC IV)에서 다시 시작되었다. 일리악은 256개의 ALU를 사용해 1 GFLOPS(기가플롭스)의 머신을 만들고자 하였으나 1972년 완성되었을 때는 64개의 ALU로 100 ~ 150 MFLOPS(메가플롭스)의 성능밖에 내지 못했다. 그렇지만 기본 개념은 충실해서 유체 역학과 같은 데이터 중심의 애플리케이션에서는 세계에서 가장 빠른 머신이었다. 일라악의 각 데이터 요소마다 별도의 ALU를 사용한 방법은 이후 벡터 브로세서 설계에서도 일반적인 것은 아니었으며 대규모 병렬 컴퓨팅 범주로 구분되기도 한다.
초창기 벡터 프로세서 시스템 중 유명한 것은 CDC(Control Data Corporation)의 STAR-100과 텍사스 인스트루먼츠(Texas Instruments)의 ASC(Advanced Scientific Computer) 였다. ASC의 ALU는 1개의 파이프를 가진 파이프라인 아키텍처를 사용해 스칼라와 벡터 연산을 모두 처리할 수 있었으며 최대 성능은 길이가 긴 벡터를 처리할 경우 약 20 MFLOPS에 달했다. 확장 ALU 구성에서는 2개나 4개로 파이프를 확장해 2배나 4배의 성능을 얻을 수 있었다. 메모리 대역폭은 확장 모드를 사용하는데 충분했다. STAR는 CDC 7600같은 CDC의 슈퍼 컴퓨터보다는 느릴지는 몰라도 데이터 관련 작업에서는 크기도 작고 가격도 낮았다. 하지만 STAR는 벡터 명령어를 디코딩하고 프로세스의 실행을 준비하는데 시간이 많이 걸렸다. 그래서 실제 성능을 발휘하려면 매우 일정한 데이터 집합이 필요했다.
벡터 기술은 크레이-1[(Cray-1)에서 처음으로 완성되었다. 크레이는 STAR나 ASC 같이 데이터를 메모리에 남겨두지 않고 8개의 벡터 레지스터를 사용했다. 벡터 레지스터는 64비트 워드 64개로 이루어져 있다. 벡터 명령어는 레지스터 사이에서 실행되었는데 메인 메모리에서 가져오는 방법보다 훨씬 빨랐다. 크레이는 벡터 명령어를 실행하는데 다수의 ALU를 사용하는 대신 파이프라인 병렬화를 사용했다. 이 방법은 명령어에 따라 파이프라인을 나누어 놓은 것으로 예를 들어 뎃셈/뺄셈은 곱셈과는 다른 파이프라인에서 실행된다. 이런 기술을 벡터 체인닝이라 부른다. 크레이-1의 일반적인 성능은 80 MFLOPS 정도였으나 3개의 체인으로 실행할 경우 최대 성능은 240 MFLOPS를 기록했다.
다른 예는 CDC가 슈퍼 컴퓨터 시장에 재진입하기 위해 제작한 ETA-10 머신이지만 거의 판매되지 않았기 때문에 CDC가 슈퍼 컴퓨터 시장에서 철수하는 계기가 되었다. 1980년대 중반 후지쯔, 히타치, NEC 같은 일본 기업들이 크레이-1과 비슷한 레지스터 기반의 벡터 머신을 제작, 판매하였는데 좀 더 빠르고 크기도 작았다. 오리건(Oregon)의 FPS(Floating Point Systems)은 미니컴퓨터를 위한 애드인 방식의 어레이 프로세서를 제작하였으며 나중에는 미니슈퍼 컴퓨터를 제작하기도 했다. 하지만 크레이가 여전히 성능상 우위를 점하고 있었으며 크레이-2(Cray-2), 크레이 X-MP(Cray X-MP), 크레이 Y-MP(Cray Y-MP)를 발표해 명성을 이어나갔다. 그 후 슈퍼 컴퓨터 시장은 벡터 브로세서의 개선보다는 대규모 병렬 프로세싱에 초점을 맞추게 된다. 하지만 벡터 프로세서의 장점은 널리 알려져 있었으며 IBM은 여러 개의 스칼라 프로세서를 짝지어 벡터 프로세서처럼 동작하게 하는 가상 벡터 아키텍처(Virtual Vector Architecture)를 개발하기도 했다.
벡터 프로세싱 기술은 최근의 거의 모든 CPU에서 SIMD라는 명칭으로 추가되었다. 벡터 유닛은 프로그램으로부터 처리할 데이터를 받아 메인 스칼라 CPU와 동시에 작동한다.

특징

일반적인 조건에서 CPU는 한번에 1개나 2개의 데이터를 처리 할 수 있다. 예를 들어 CPU에 “A와 B를 더한 후 결과를 C에 저장하라” 라는 명령을 내리면 A, B, C의 데이터는 바로 명령어에서 사용할 수 있도록 변환(encode)되어야 한다. 즉, 데이터가 저장되어 있는 메모리 위치의 주소를 지정하는(point to) 작업이 필요하다. 이처럼 주소를 디코딩하고 메모리에서 데이터를 가져오는데는 일정한 시간이 걸린다. CPU 속도가 증가함에 따라 메모리 지연 시간(latency)이 성능에 큰 영향을 미치게 되었다.
이렇게 낭비되는 시간을 줄이기 위해 최근 CPU에서는 파이프라인 기술을 사용한다. 명령어는 몇 개의 서브 유닛을 차례로 통과하는데 첫 번째 서브 유닛에서는 어드레스를 읽어 해독하고 다음 서브 유닛은 주소 값을 불러오며(fetch) 그 다음 서브 유닛은 그것들을 연산한다. 파이프라인은 마치 조립 라인과 같이 CPU에서 하나의 명령이 끝나기 전에 다른 명령을 해독하기 시작하는 것으로 주소 디코더는 끊임없이 계속 사용된다. 어떤 특정 명령어는 실행 완료되는데 일정한 시간이 걸린다. 이 시간을 레이턴시라고 하는데 CPU는 파이프라인을 이용해 레이턴시 동안 기다리지 않고 한번에 하나씩 실행할 수 있다.
벡터 프로세서는 이런 개념을 한층 발전시켜 명령어를 파이프라인하는 것만 아니라 데이터 그 자체도 파이프라인으로 처리되도록 하였다. A와 B를 더하라는 명령뿐만 아니라 지정한 범위 안의 모든 숫자를 더할 수 있도록 한 것이다. 즉, 여기서 여기까지의 모든 숫자를 저기서 저기까지의 모든 숫자에 모두 더할 수 있다. 끊임없이 명령어를 해독하고 거기에 필요한 데이터를 가져오는 대신 메모리는 한번에 하나의 명령어로만 읽을 수 있는데 마지막 사용한 주소에서 하나 더 큰 주소가 다음에 필요한 주소다. 이 방법은 디코딩 시간을 줄이는데 도움이 된다.
아래는 벡터 프로세서와 스칼라 프로세서의 차이점을 설명하기 위한 예제이다. 10개의 숫자로 된 2그룹을 모두 더하는 간단한 작업이다. 일반적인 프로그래밍 언어에서는 루프(loop)를 사용해 각 숫자를 하나씩 가져와 더한다. 이 작업을 CPU에서는 다음과 같이 한다.
execute this loop 10 times (아래 작업을 10번 반복 실행한다)
  read the next instruction and decode it (다음 명령을 읽어들여 해독한다)
  fetch this number (이쪽의 숫자를 가져온다)
  fetch that number (저쪽의 숫자를 가져온다)
  add them (두 숫자를 더한다)
  put the result here (결과를 여기에 넣는다)
end loop (루프 마지막)
벡터 프로세서에서는 이 작업은 매우 다른 것이 된다.
read instruction and decode it (명령을 읽어들여 해독한다)
fetch these 10 numbers (이쪽의 숫자 10개를 모두 가져온다)
fetch those 10 numbers (저쪽의 숫자 10개를 모두 가져온다)
add them (모두 더한다)
put the results here (결과를 여기에 넣는다)
이 방법은 몇가지 장점이 있는데 한 가지는 프로그램을 실행하는데 2개의 주소 변환만이 필요하다는 점으로 아키텍처에 따라 많은 시간을 단축할 수 있다. 또 다른 장점은 명령어를 불러와(fetch) 해독(decode)하는 작업을 10번 해야하는 것에서 1번만으로 끝낼 수 있기 때문에 작업 시간을 줄일 수 있다. 또한 코드 자체도 작아져서 메모리를 보다 효율적으로 사용할 수 있다.
벡터 프로세서가 가진 여러 기능의 유닛에 병렬로 숫자들을 추가할 수 있다. 벡터 명령은 여러 독립된 작업을 지정하며 그 숫자들 사이의 의존성 검사는 할 필요가 없다. 이 방법은 제어 로직을 간단하게 만들어주며 지연없이 성능을 증가시킬 수 있다.
앞서 말한 크레이는 한 걸음 앞선 방식으로 서로 다른 형태의 작업을 한번에 실행할 수 있다. 두 숫자를 더한후 세 번째 숫자와 곱하는 작업을 예로 들면 크레이에서는 이들 숫자를 한번에 모두 불러와 덧셈과 곱셈을 동시에 처리한다. 크레이에서는 아래와 같은 코드로 실행된다.
read instruction and decode it (명령을 읽어들여 해독한다)
fetch these 10 numbers (이쪽의 숫자 10개를 모두 가져온다)
fetch those 10 numbers (저쪽의 숫자 10개를 모두 가져온다)
fetch another 10 numbers (또 다른 쪽 숫자 10개를 모두 가져온다)
add and multiply them (한 번에 더하고 곱한다)
put the results here (결과를 여기에 넣는다)
연산 작업은 전체적으로 훨씬 빠르게 완료되며 제한 요소는 메모리에서 데이터를 가져오는데 걸리는 시간이다.
모든 문제에 이 같은 해법이 적용되지는 않는다. 이러한 종류의 명령어는 CPU 코어의 복잡함을 유발하며 일반적으로 벡터 작업이 아닌 다른 명령어조차 느리게 만든다. 또한 더 복잡해진 명령어를 실행하는 데에는 좀 더 복잡한 디코더가 필요하다. 이것은 디코딩 속도를 느리게 만들며 일반 덧셈과 같은 명령어의 실행 속도도 늦어지는 것을 뜻한다.
사실 벡터 프로세서는 대규모의 데이터를 처리해야 하는 상황에서 최상으로 작동한다. 이러한 이유로 벡터 프로세서는 주로 슈퍼 컴퓨터에 사용되었으며 기상 예측 센터나 물리학 연구소 같은 엄청난 데이터를 처리해야 하는 곳에서 찾아 볼 수 있다.