5.5 Reducing Procedure Calls(프로시저 호출 줄이기)
- 함수 호출은 최적화를 방해하고 오버헤드를 증가시킨다.
- 아래 예시에서 combine2는 get_vec_element 함수를 경계 검사(bound check)를 위해 반복 수행한다.
- 그러나 length라는 범위 내에서는 명백한 인덱스이기 때문에 경계 검사(bound check)는 불필요하다.
- 임의의 접근을 할 때는 경계 검사(bound check)가 필요하지만 명백한 인덱스를 알고 있을 때는 경계 검사(bound check)가 불필요하다.
/* Move call to vec_length out of loop */
void combine2(vec_ptr v, data_t *dest)
{
long i;
long length = vec_length(v);
*dest = IDENT;
for (i = 0; i < length; i++) {
data_t val;
get_vec_element(v, i, &val);
*dest = *dest OP val;
}
/*
* Retrieve vector element and store at dest.
* Return 0 (out of bounds) or 1 (successful)
*/
int get_vec_element(vec_ptr v, long index, data_t *dest)
{
if (index < 0 || index >= v->len)
return 0;
*dest = v->data[index];
return 1;
}
아래 코드는 불필요한 함수 호출을 제거한 결과이다.
data_t *get_vec_start(vec_ptr v)
{
return v->data;
}
/* Direct access to vector data */
void combine3(vec_ptr v, data_t *dest)
{
long i;
long length = vec_length(v);
data_t *data = get_vec_start(v);
*dest = IDENT;
for (i = 0; i < length; i++) {
*dest = *dest OP data[i];
}
}
- get_vec_start 함수는 data(array)를 반환한다.
- combine3는 반환한 array에 대해 index로 직접 접근하고 있다.
- 경계성 검사(bound check)를 루프문 내에서 제거하여 반복 수행하지 않고 있다.
- 누군가는 modularity(모듈성)이 사라지는 코드 변환이라 하겠지만, 고성능 주의자들은 꼭 필요한 과정이라 주장한다.

- lol? 그렇지만, 결과는 차이가 거의 없고 integer의 경우 오히려 더 안좋은 결과가 나왔다.
- 왜 combine3가 combine2 보다 안좋은 결과는 내었는지에 대해서는 향후 5.11.2 절에서 다룰 예정이다.
- 함수 호출을 줄이는 과정은 불필요한 것이 아니었다. performance를 향상시키는 중요한 step 중 하나라고 생각하고 넘어가자. 향후 이유를 알게 될 것이다.
'Computer Science > 컴퓨터 구조' 카테고리의 다른 글
[CSAPP] 5.7 Understanding Modern Processors(현대 프로세서 이해) (0) | 2023.01.30 |
---|---|
[CSAPP] 5.6 Eliminating Unneeded Memory References(불필요한 메모리 참조 제거) (0) | 2023.01.30 |
[CSAPP] 5.4 Eliminating Loop Inefficiencies(루프 비효율성 제거하기) (0) | 2023.01.30 |
[CSAPP] 5.3 Program Example(프로그램 예제) (0) | 2023.01.30 |
[CSAPP] 5.2 Expressing Program Performance(프로그램 성능의 표현) (0) | 2023.01.29 |