하다 못해 모바일도 GPU 가속을 받는 세상이니까.
걍 썰이 풀고파서 끄적임.
1. Single Core Parallelism
이건 superpipeline 과 superscalar 를 이용한 기술을 말한다.
그러기 위해서 data hazard, branch hazard, structural hazard 를 제거 해야한다.
structural hazard 는 사실 개인이 손댈 여지가 그닥 없다고 본다. 컴파일러가 알아서 해 줘야 할 문제.
data hazard 의 경우, 종속성을 없애거나 줄이면된다. branch hazard 의 경우, 분기를 없애거나 줄이면 된다.
가령, 1 ~ 100 까지의 누적합을 (누가 가우스의 등차수열의 합산공식을 안쓰겠냐만은) 구하는데 있어
int sum = 0;
for(int i = 1; i <= 100; ++i) sum += i;
하는것 보다,
int sum = 0;
for(int i = 1; i <= 100;)
{
sum += i++;
sum += i++;
sum += i++;
....
sum += i++;
}
하는게 cmp(비교)와 jmp(분기) 가 줄겠지?
하지만 저 코드는 루프의 확장이라 불리는 전통적인 기법으로 아주 미미한 최적화 효과만 있다.
왜냐하면 sum 과 i 값의 write back 에 data dependency 가 걸려 있기 때문이다.
그렇다면,
int sum = 0;
for(int i = 1; i <= 100; i+=10)
{
sum += i;
sum += i + 1;
sum += i + 2;
....
}
이건 어떤가? i, i + 1, i + 2 가 write back 없이 병렬화 될 수 있다. 하지만 sum 에 대한 dependency는 해결되지 못했다.
int sum[10] = {0, };
for(int i = 1; i <= 100; i += 10)
{
sum[0] += i;
sum[1] += i + 1;
....
}
이건 어떤가? sum 자체에 대한 dependency는 줄었다. 그렇지만 배열 태그 연산비용이 생겼다.
그럼,
int sum0, sum1, sum2.... sum9;
sum0 sum1 = ... sum9 = 0;
for(int i = 1; i <= 100; i += 10)
{
sum0 += i;
sum1 += i + 1;
....
}
int sum = sum0 + sum1 + ... sum9;
이건 어떤가? 스택에 생성된 변수들을 기억해야할 갯수가 늘긴 했다. 이 말은 레지스터 활용도가 조금 떨어진단 이야기다.
하지만 그 위의 코드와 이 코드는 코어별로 확실히 성능차이를 보인다. (어눌한 코어일수록 아랫것이 유리)
이것이 data hazard 를 다루는 기본 기법중 하나다. 지금 당장 필요하지 않은 코드를 컴파일러가 알아서 삽입해주기도 하지만,
연속한 데이타를 다루는데 있어서는 스크램블링을 해주지 않는다. 코드가 늘어난다는건, 또 다른 비용발생이 있긴하다. (캐시)
이러한 병렬화의 의존제거를 위한 작업분리와, 연산후의 mux 개념은 싱글 코어의 범주를 넘어서,
쓰레드 베이스 멀티프로세싱, 분산 처리에 그대로 적용된다.
하지만 누가 손으로 짜 걍 OpenMP 나 C++AMP, OpenCL 등등 여러 도구들 많은데 =_=
더 떠들면 글 짤리겠지? 요까이.
담엔 브랜치 없애는 기법들을 예시로 보여주고 싶은데 비추천이 기분나쁘다.
그래서 본문 삭제.
째째한거보소 ㅋㅋ
긁으면 나와.
비추천을 누르든 말든 긁을 정도 정성이면 읽어보든가 ㅋㄷ
http://dblack.tk
커뮤니티 사이트 입니다 많은 이용 부탁 드립니다.