명령어수준 병렬성(ILP, Instruction-level Parallelism)

ILP 는 비순차 실행에서 사용되는 기술입니다.
말그대로 명령어 수준에서 프로그램에 기록된 순서대로 순차적으로 처리하는게 아니라, 명령어간의 상관관계를 잘 따져서 병렬처리가 가능하도록 하는 기술입니다.
예를 들어, 다음과 같은 코드가 있다고 가정하면…

int main()
{
    int  x, y, a, b, c, d;
    int  myarray[4];
    ...
    x = myarray[4];   -- (가)
    y = x + 10;       -- (나)
    a = b - 4;        -- (다)
    c = d * 7;        -- (라)
    ...
}

위 코드의 의존성을 따져보면, (가)와 (나)의 경우 의존성이 있는 반면, (다) 및 (라)는 어느 코드와도 의존성을 갖지 않습니다.
이 경우는 간단히 cycle 별로 처리가능한 명령어들을 따져보면 다음과 같이 가능할겁니다.

1 cycle 에서 실행하는 명령 : (가) (다) (라)
2 cycle 에서 실행하는 명령 : (나)

이는 다시 말해 4 개의 명령어를 2 cycle 에 처리가 가능하다는 것인데, 이것이 곧 병렬처리되는 것이므로 ILP 라고 부를 수 있습니다.
이를 수치화할 수 있는데 만약 4 개의 명령어가 모두 의존성으로 묶여있다면, 4 개 명령어를 4 cycle 에 처리할 수 있다고 하여 ILP = 4 / 4 = 1 이라고 말합니다. 반면 위와 같은 경우, 4 개의 명령을 2 cycle 에 처리할 수 있으므로 ILP = 4 / 2 =2 라고 수치화할 수 있습니다. 의존성이 서로 아무 것도 없는 명령들이라면 ILP 값은 4 가 되겠네요.
물론 이러한 계산들은 이상적으로 생각해서 하나의 명령은 무조건 1 cycle 에 끝나고, 또 명령어 개수만큼 코어 수도 받쳐준다는 가정을 할 경우일 것입니다.

이러한 명령어 수준에서의 병렬성, 즉 ILP 와 대응되는 개념으로 “TLP(Thread-level Parallelism)”, 즉 “스레드 수준 병렬성”이라는 것도 존재합니다. 이는 한마디로 스레드를 여러개 띄워서 프로그램을 명시적으로 병렬적으로 처리하게 하는 것을 말합니다.
그런데, 프로그래머는 스레드를 여러개 만들어서 실행했지만, 하드웨어는 싱글코어일 수도 있고 멀티코어 환경일 수도 있겠죠. 싱글코어일 때는 OS 단에서 스케줄링에 의해 사용자에게 멀티스레드가 병렬로 동작하는 것처럼 보일 것입니다. 어쨌건 그렇더라도 이것 또한 스레드 수준 병렬성이라고 부릅니다.

결국은 ILP 와 TLP 의 구분 기준은 멀티스레드를 통한 명시적인 병렬성이냐(TLP), 아니면 싱글스레드에서도 명령어 의존성을 분석하여 병렬성을 구현했느냐(ILP)의 차이인 것입니다.
잘 생각해보면 그렇다면 ILP 의 경우는 명령어 사이의 의존성을 분석해서 병렬가능한 것을 찾는 것이니, CPU 뿐 아니라 컴파일러도 그 역할을 할 수 있겠네요. 그리고, 분명 그러한 의존성을 분석할 수 있는 범위도 컴파일러가 넓을 것입니다. CPU 코어의 경우 기껏해야 명령어 스트림을 저장해둘 수 있는 Window 크기(보통 100 개 명령어 범위 정도)에 한정될 것인데, 컴파일러는 그러한 가두리가 없으니 훨씬 자유롭게 넓은 범위의 의존성을 검사할 수 있을 것입니다.

You may also like...