싱글코어에서도 데이터레이스는 발생한다.

Yoon Sunkue·2022년 9월 6일
1

노트

목록 보기
9/9

멀티쓰레딩이란, 하나의 프로세스에서 코드,데이터,힙 영역을 공유한채로 스택영역을 하나 더 생성시켜 대칭적 스케쥴링으로 여러개의 스택을 실행시키는 것을 말한다.

데이터 레이스의 발생 조건은
1. 각 쓰레드가 하나의 메모리영역에 동시에 접근하면서
2. 적어도 한개의 쓰레드가 쓰기 명령을 실행할 때

멀티코어 에서는 읽기 명령어, 쓰기 명령어가 동시에 발생 할 수 있다. 그럴 경우 데이터 레이스가 발생하는 것이다.

현대의 운영체제는 asm명령어를 수행하고, 인터럽트를 확인하는 것을 반복하며 스케쥴링이 일어난다. 시스템콜은 소프트웨어적으로 인터럽트를 실행한다.

인터럽트 서비스 루틴이 실행되면, 먼저 스케쥴링되어 실행중이던 프로그램의 레지스터값들은 스택으로 대피된다.

싱글코어에서도 스케쥴링은 일어난다. 인터럽트는 발생한다. 싱글코어에서는 아래와 같이 동작한다.

스케쥴 인터럽트가 쓰레드1의 함수가 채 끝나기 전에 발생하여 데이터 레이스가 마찬가지로 발생한다.

데이터 레이스의 발생이유는 쓰레드1의 읽기, 변경, 쓰기의 삼박자가 끝나기 전에 쓰레드2의 읽기, 변경, 쓰기가 발생하기 때문이다. 정확히는 읽기, 쓰기 라는 메모리 접근 루틴 사이에 다른쓰레드의 읽기, 쓰기 루틴이 끼어들기 때문이다. "복수의 쓰레드가 동시에 메모리에 접근하며, 적어도 하나는 쓰기를 한다" 는 조건. 이 조건이 싱글 코어에서도 인터럽트 스케쥴링에 의해 발생하기 때문에, 데이터 레이스가 생기는 것이다.

MOV ADD MOV 세개의 asm명령어는 SUM+=2 라는 하나의 코드다. 이 코드가 _asm add sum, 2 라는 하나의 명령어로 수행된다면, 명령어 수행이 끝나기 전에는 스케쥴링 인터럽트가 발생하지 않으므로 싱글코어에서는 메모리에 동시에 접근하지 않으므로 데이터 레이스가 생기지 않는다.

하지만 멀티코어에서는 여전히 데이터 레이스가 발생한다. 하나의 명령어는 한 쿨럭에 실행되는 것이 아니다. _asm add sum, 2 라는 명령어는 sum의 값을 레지스터에 올리는데에 한쿨럭, 이걸 ALU에서 2와 더하는데에 한쿨럭, 이걸 메모리에 다시 원위치 시키는데에 한쿨럭이 걸린다. 또 각 코어마다 캐시를 가지고 있으며, 쓰기 명령어가 실행되더라도 같은 asm 명령어를 수행하더라도 cpu의 구현의 따라 캐시의 값을 메모리에 바로 올리지 않는 둥. 캐시 동기화가 이루어지지 않으면 결국 각 쓰레드가 다른 메모리에 접근하여 값을 읽고 쓰게 된다. 이 복잡한 일련의 작업 와중에 다른 쓰레드도 같은 작업을 수행중이며, 코어1이 1쿨럭에 읽기를 수행하고, 2쿨럭에 변경를 수행 할 때, 동시에 코어2 에서 쓰기를 수행해 버린다.

이러한 경합을 없애는 _asm lock add sum, 2 명령어가 있다. lock asm명령어가 수행 중일 때에는, 다른 코어에서 그 메모리에 읽기, 쓰기를 수행 할 수 없도록 스케쥴링된다. 이는 메모리 접근 순서를 고정 시키는 효과이다. 이게 C++ std::atomic 의 구현이다. 하드웨어단의 구현이다.

0개의 댓글