Search
Duplicate

20201222(화)

내용
42) memmove함수와 memcpy함수의 차이 & restrict
공부장소
2021/03/20 18:22
학습 날짜
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함수의 차이