학습 날짜
•
2020/12/22(화)
학습 시간
•
09:00 ~ 22:00 (자가)
학습 범위 및 주제
•
Libft
•
window vm setting & vscode setting
동료 학습 방법
•
온라인(Discord를 활용) 스터디 진행
•
본인 포함 4명 (@jseo @chan @hyson @klim)
학습 목표
•
restrict 포인터에 대한 이해
•
memmove함수와 memcpy함수의 차이
상세 학습 내용
restrict 포인터에 대한 이해
restrict 포인터는 메모리 접근에 관련된 최적화 기능이다.
예를 들어 아래와 같은 포이너를 역참조하여 값을 증가시키는 코드가 있다.
void increase(int *a, int *b, int *x)
{
*a += *x;
*b += *x;
}
Plain Text
복사
이 코드를 gcc에서 컴파일한 뒤 어셈블리 코드로 살펴보면
mov (%rdx),%eax
add %eax,(%rdi)
mov (%rdx),%eax
add %eax,(%rsi)
Plain Text
복사
다음과 같이 되는 것을 볼 수 있다.
아래의 코드와 같이 매개변수에 들어있는 메모리 주소가 같은 공간일 수 있기때문에 컴파일러는 매번 메모리에 접근하여 값을 가져온다.
int a = 1;
increase(&a, &a, &a);
Plain Text
복사
같은 메모리 공간일 경우 이전 명령어의 결과에 따라 값이 변할 수 있기 때문에 다음 명령을 수행하기 전에 이전 결과가 적용된 값을 가져와야 한다.
하지만 매개변수가 가리키는 주소가 겹치는 메모리 공간을 가리키지 않는다면 위와같은 연산이 상당히 비용이 복잡해질 수 있다.
그렇다면 같은 공간을 가리키지 않는 매개변수가 들오온다는게 보장 되어있다고 했을 때,
여기서 restrict포인터를 사용해 보자.
void increase(int *restrict a, int *restrict b, int *restrict x)
{
*a += *x;
*b += *x;
}
Plain Text
복사
그러면 위의 어셈블리 코드에서 아래와 같이 변한 것을 볼 수 있다.
mov (%rdx),%eax
add %eax,(%rdi)
add %eax,(%rsi)
Plain Text
복사
컴파일러가 속도 향상을 위해서 최적화를 한 것이다.
그래서 memmove 와 memcpy는 외형적으로는 비슷한 역할을 하지만 내부적으로 살펴 봤을 때, 큰 차이가 있음을 알 수 있다.
•
memcpy의 함수 원형은
void* memcpy(void* restrict dest, const void* restrict src, size_t size);
Plain Text
복사
•
memmove의 함수 원형은
void* memmove(void* dest, const void* src, size_t size);
Plain Text
복사
memmove는 restrict키워드가 없고 memcpy는 restrict키워드가 존재한다. 따라서 겹치는 공간이 없을 때에는 memcpy가 조금 더 빠른 성능을 보이지만, 만약 겹치는 공간이 있다면 memcpy는 오류가 날 수도 있는 문법인 것이다.
과제에서는 현재 C99컴파일러가 아닌 이후버전을 사용하기 때문에 restrict를 고려하지 않고 코드를 구현하면 된다.(컴파일러 내부에서 알아서 다 처리해주기 때문...!) 하지만 내부적으로 이런 문제들을 고려하여 필요에 따라 높은 효율성을 가지는 함수를 골라서 사용할 수 있다.
학습 내용에 대한 개인적인 총평
라이브러리 내부적인 것을 공부하면서 컴파일러부분에서 고려되는 것 까지 신경써야 한다는 것을 알게되었다. 단지 로직만을 생각해서 알고리즘 문제를 풀듯이 코드를 구현하는 것이 아니라 실제 컴퓨터 내부에서 어떤 원리로 작동하는지, 메모리작동 등 많은 것을 신경써야 더 좋은 코드와 함수들을 만들 수 있다는 것을 알 수 있었다. 이때까지 알고리즘 위주의 공부와 보여지는 것들 위주(html, css 등을 활용한 다소 시각적인 프로그래밍 기법)로 공부했었는데 조금은 컴퓨터 내부적인 공부를 더 진행하고 싶은 욕망이 생겼다. 이번 내용에 대해 함께 스터디를 진행하면서 어셈블리코드도 다시한번 보게 되었는데, 재학 중일 때 시험공부를 목적으로 했을 때와는 다르게 느껴졌다. 당시에는 어셈블리어를 하는 이유도 잘 알지 못했지만 함께 스터디를 진행하면서 어셈블리코드를 어떤 식으로 활용할 수 있는지 알게 되면서 조금은 더 깊은 공부를 할 수 있어서 좋았다.
다음 학습 계획
과제 제출에 앞서 다양한 vim과 git세팅을 진행하고 남은 libft함수들을 구현해 볼 예정이다.
•
memmove함수와 memcpy함수의 차이
•
memmove함수와 memcpy함수의 차이