tgool
Tgool
tgool
전체 방문자
오늘
어제
  • 분류 전체보기
    • Data Science
      • AI
      • Data Mining
      • ML(Machine Learning)
    • Computer Science
      • 자료구조
      • 알고리즘
      • 시스템 프로그래밍
      • 운영체제
      • 컴퓨터 구조
      • 컴퓨터 네트워크
      • 데이터 베이스
      • 파이썬
      • 자바
      • 아두이노
    • Math
      • 통계학
      • 확률론
      • 선형대수학
      • 수리통계학
      • 회귀분석
    • TOFEL
    • Git
    • Plan
    • Book
    • Working out
      • 영양과 생활
      • 운동 정보
      • 운동 기록

인기 글

최근 글

최근 댓글

hELLO · Designed By 정상우.
tgool
Computer Science/컴퓨터 구조

[CSAPP] 5.8 Loop Unrolling(루프 풀기)

[CSAPP] 5.8 Loop Unrolling(루프 풀기)
Computer Science/컴퓨터 구조

[CSAPP] 5.8 Loop Unrolling(루프 풀기)

2023. 1. 30. 12:05

5.8 Loop Unrolling(루프 언롤링)

  • Loop Unrolling(루프 언롤링)이란 각 반복에서 계산되는 요소의 수를 늘려 루프틔 반복 횟수를 줄이는 프로그램 변환법이다. 
  • 5.2에서 나온 psum2가 대표적인 예시이다. 아래 코드가 루프 언롤링을 적용한 것.  psum1 -> psum2
/* Compute prefix sum of vector a */
2 void psum1(float a[], float p[], long n)
{
	long i;
	p[0] = a[0];
	for (i = 1; i < n; i++)
		p[i] = p[i-1] + a[i];
}

void psum2(float a[], float p[], long n)
{
	long i;
	p[0] = a[0];
	for (i = 1; i < n-1; i+=2) {
		float mid_val = p[i-1] + a[i];
		p[i] = mid_val;
		p[i+1] = mid_val + a[i+1];
}
/* For even n, finish remaining element */
	if (i < n)
		p[i] = p[i-1] + a[i];
}

 

  • Loop Unrolling(루프 언롤링)은 두 가지 방법으로 성능을 향상시킬 수 있다.
    • 1. 루프 indexing 및 조건 분기(conditional branch)와 같이 프로그램 결과에 '직접적'으로 관여하지 않는 작업의 수를 줄이는 방법.
    • 2. 전체 계산의 criticial path에서 작업 수를 줄이기 위해 코드를 추가로 변환할 수 있는 방법.
  • 아래는 2 * 1 루프 언롤링이라고 불리는 것을 사용하는 결합 코드를 보여준다.
/* 2 x 1 loop unrolling */
void combine5(vec_ptr v, data_t *dest)
{
	long i;
	long length = vec_length(v);
	long limit = length-1;
	data_t *data = get_vec_start(v);
	data_t acc = IDENT;

/* Combine 2 elements at a time */
	for (i = 0; i < limit; i+=2) {
		acc = (acc OP data[i]) OP data[i+1];
	}

/* Finish any remaining elements */
	for (; i < length; i++) {
		acc = acc OP data[i];
	}
	*dest = acc;
}
  • 우리는 우리의 코드가 임의의 벡터 길이에 대해 올바르게 작동하는 것을 원한다.
  • 이를 위한 두 가지 방법이 존재.
    • 1. 첫번째 루프가 array 경계를 초과하지 않는 확인하는 것. ex) 길이가 n인 벡터의 경우 루프 한계를 n-1로 설정. 그런 다음에 루프의 인덱스 i가 i < n-1를 만족할 때만 루프가 실행될 것. 따라서 최대 array 인덱스는 i + 1 < (n - 1) + 1 = n 즉 i + 1 < n 을 만족할 것을 보장. 
    • 이를 일반화하여 k * 1 루프 언롤링을 초래하는 요인 k에 의해 루프를 언롤링할 수 있다.
    • 우리의 상한을 n - k + 1로 설정하고 루프 내에서 combining operation를 i ~ i + k -1에 적용한다. 루프 인덱스 i는 각 반복에서 k씩 증가하면 최대 array 인덱스 i + k - 1이 n 보다 작아진다. 
    • 2. 우리는 벡터의 마지막 몇 가지 요소를 한 번에 하나씩 통과하는 두 번째 루프를 포함시킨다. 이 루프는 0 ~ k-1회 사이에 실행된다. k =2일 때, psum2 같이 간단한 조건문만을 이용 가능하다.  k > 2인 경우 루프로 더 표현하기 쉽다.
    • 우리는 k배만큼 풀지만 단일 변수 acc에 값을 축적하기 때문에 이 변환을 k  * 1 언롤링이라 부른다.
  • 언롤링 요소 k = 2, k = 3일 때 측정된 평가 값은 다음과 같다.

  • integer 덧셈에 대한 CPE가 개선 되어 Latency bound가 약 1.00을 달성했다.
  • 이 결과는 루프의 오버헤드 작업을 줄이는 이점 때문일 수 도 있다.
  • 벡터 합을 계산하는데 필요한 추가 수에 비해 오버헤드 작업 수를 줄임으로써 정수 추가의 1 cycle latency이 성능 제한 요소가 되는 지점에 도달할 수 있다.
  • 반면, 다른 사례들은 개선되지 않았다. 이미 latency bounds에 도달했기 때문이다.

 

  • 아래 그림은 루프를 최대 10배(k = 10)까지 풀 때의 CPE 측정값을 보여준다.

  • 2와 3의 언롤링에 대해 관찰한 추세가 동일하고 latency bound를 밑도는 것은 없다.
  • k * 1 언롤링이 latency bound 이상의 성능을 향상시킬 수 없는 이유를 이해하기 위해, k = 2인 combine5의 내부 루프에 대한 기계어 코드를 보자.
  • data_t 타입이 double이고 연산이 곱셉이면 다음 코드가 된다.
// Inner loop of combine5. data_t = double, OP = *
//in %rdx, data %rax, limit in %rbx, acc in %xmm0
.L35: //loop:
vmulsd (%rax,%rdx,8), %xmm0, %xmm0 //Multiply acc by data[i]
vmulsd 8(%rax,%rdx,8), %xmm0, %xmm0 //Multiply acc by data[i+1]
addq $2, %rdx //Increment i by 2
cmpq %rdx, %rbp //Compare to limit:i
jg .L35 //If >, goto loop
  • 루프 인덱스 i는 레지스터 %rdx에 저장되고 데이터의 주소는 레지스터 %rax에 저장된다.
  • 누적 값 acc는 벡터 레지스터 %xmm0에 저장된다.
  • 루프 언롤링은 두 가지 vmulsd 명령으로 수행된다. 
    • 하나는 acc에 데이터 [i]를 추가하고
    • 다른 하나는 acc에 데이터 [i + 1]를 추가한다. 
  • 아래 그림은 이 코드를 그래픽으로 표현한 것이다.

  • vmulsd 명령은 각각 메모리에서 array 요소를 load하는 작업과 이 값에 누적 값을 곱하는 작업의 두 가지 작업으로 변환된다. 
  • 여기서는 각 루프 실행에서 레지스터 %xmm0이 두 번 읽고 쓰는 것을 볼 수 있다.
  • 아래 그림 (a)에 표시된 프로세스에 따라 이 그래프를 재정렬, 단순화, 추상화해서 (b)로 표시된 템플릿을 얻을 수 있다.

  • 그런 다음 이 템플릿을 n/2회 복제하여 길이 n의 벡터에 대한 계산을 보여주며, 아래 그림에 표시된 data flow 표현을 얻을 수 있다.

  • 위 그림에서 우리는 이 그래프에서 n개의 mul operation의 critical path가 여전히 존재한다는 것을 알 수 있다.
  • 반복 횟수는 절반이지만 각 반복에는 두 개의 multiplication operation이 순차적으로 있다. 
  • critical path는 루프 언롤링이 없는 코드 성능에 대한 제한 요소였기 때문에, k * 1에서도 마찬가지로 적용되는 제한 요소이다.

'Computer Science > 컴퓨터 구조' 카테고리의 다른 글

[CSAPP] 5.10 Summary of Results for Optimizing Combining Code (최적화 코드의 결과 요약)  (0) 2023.02.08
[CSAPP] 5.9 Enhancing Parallelism(병렬성 향상시키기)  (0) 2023.01.30
[CSAPP] 5.7 Understanding Modern Processors(현대 프로세서 이해)  (0) 2023.01.30
[CSAPP] 5.6 Eliminating Unneeded Memory References(불필요한 메모리 참조 제거)  (0) 2023.01.30
[CSAPP] 5.5 Reducing Procedure Calls(프로시저 호출 줄이기)  (0) 2023.01.30
    'Computer Science/컴퓨터 구조' 카테고리의 다른 글
    • [CSAPP] 5.10 Summary of Results for Optimizing Combining Code (최적화 코드의 결과 요약)
    • [CSAPP] 5.9 Enhancing Parallelism(병렬성 향상시키기)
    • [CSAPP] 5.7 Understanding Modern Processors(현대 프로세서 이해)
    • [CSAPP] 5.6 Eliminating Unneeded Memory References(불필요한 메모리 참조 제거)
    tgool
    tgool

    티스토리툴바

    단축키

    내 블로그

    내 블로그 - 관리자 홈 전환
    Q
    Q
    새 글 쓰기
    W
    W

    블로그 게시글

    글 수정 (권한 있는 경우)
    E
    E
    댓글 영역으로 이동
    C
    C

    모든 영역

    이 페이지의 URL 복사
    S
    S
    맨 위로 이동
    T
    T
    티스토리 홈 이동
    H
    H
    단축키 안내
    Shift + /
    ⇧ + /

    * 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.