본문 바로가기

전기

SVC에 대한 답변 ? 32비트변수 읽기는 32비트CPU에서 atomic(무결성)이다 하지만 쓰기는 아니다!

Data race 는 반드시 잡아야 하나요? 올려짐: 2006-07-20 16:05

--------------------------------------------------------------------------------

멀티쓰레드 프로그래밍에서
bool 등의 단순한 변수를
하나의 쓰레드는 읽기만 하고
다른 쓰레드가 그 값에 쓰기를 하는데,
Intel Thread Checker 에서
Data race 가 발생한다고 진단하였습니다.

별로 중요한 로직에 관여하는 변수도 아니고
단순한 플래그 체크를 하는 것인데 read 하고 싶을때마다
CRITICAL_SECTION 등으로 Lock 을 걸고 읽고, 풀고..
이 작업을 꼭 해줘야 하는 것인가요?

위로


imays

가입: 2003년 2월 18일
올린 글: 1043

그렇습니다. 올려짐: 2006-07-20 16:22

--------------------------------------------------------------------------------

한쪽 스레드에서 읽는 동안 다른 스레드에서 값을 바꿔버리면 간발의 차이로 원치 않는 결과를 얻을 수 있습니다.
따라서 critical section은 쓸 필요가 있습니다.
물론 critical section의 코스트가 크기 때문에 가급적 넓은 메모리 범위에 대해 적용하는 것이 권장됩니다.

만약 정확성이 좀 떨어져도 문제없다면 안 걸어도 되고요.

critical section을 쓰지 않더라도 thread safe하게 접근하는 방법이 몇 가지 있습니다. 비록 플래그에는 적용하기가 어렵겠지만 GPG6 1장 근처에 있는 thread safe data 구조체 글을 참고하셔도 될 것 같습니다.
_________________
온라인 게임 서버 엔진 ProudNet
http://www.nettention.co.kr

위로


비회원
손님

Re: Data race 는 반드시 잡아야 하나요? 올려짐: 2006-07-20 16:28

--------------------------------------------------------------------------------

비회원 씀:
멀티쓰레드 프로그래밍에서
bool 등의 단순한 변수를
하나의 쓰레드는 읽기만 하고
다른 쓰레드가 그 값에 쓰기를 하는데,
Intel Thread Checker 에서
Data race 가 발생한다고 진단하였습니다.

별로 중요한 로직에 관여하는 변수도 아니고
단순한 플래그 체크를 하는 것인데 read 하고 싶을때마다
CRITICAL_SECTION 등으로 Lock 을 걸고 읽고, 풀고..
이 작업을 꼭 해줘야 하는 것인가요?


boolean 값에 대한 설정과 읽기는 atomic 한 operation 이라 lock을 걸지 않아도
상관 없지 않나요? 32bit 머신에서는 32bit 값 (int 겠군요)까지는 atomic 한 operation일
거라고 생각이 되는데요.

Race condition 이라는게 동일한 리소스를 놓고 쓰레드가 경쟁할때 발생하는 것일진데
이것은 단순히 lock을 걸고 풀고 하는 것으로 해결될 거 같지는 않습니다.

데이터의 무결성을 보장해야 하는 부분 그러니깐 반드시 하나의 atomic 한 처리가 보장되어야
하는 부분에 대해서 locking을 해야 하는 것이고, race condition이 발생한다면 그것이 발생되지
않도록 로직을 수정하는 편이 좋을것 같네요.

위로


조성경

가입: 2005년 12월 13일
올린 글: 307

Re: Data race 는 반드시 잡아야 하나요? 올려짐: 2006-07-20 17:38

--------------------------------------------------------------------------------

비회원 씀:
boolean 값에 대한 설정과 읽기는 atomic 한 operation 이라 lock을 걸지 않아도
상관 없지 않나요? 32bit 머신에서는 32bit 값 (int 겠군요)까지는 atomic 한 operation일
거라고 생각이 되는데요.


안타깝게도 boolean값을 변경하는것도 atomic하지 않습니다.

불린값이라는것 자체가 값의 토글을 위해서 존재합니다. 아래와 같은 경우를 가정해보죠.

코드:
view source

print?
한쪽에서

...

isProcess = false;


코드:
view source

print?
다른 한쪽에서

if (isProcess)

{

...

}


위와 같은 상황이라고 하죠. isProcess를 false로 바꾸고 더 이상 처리하지 못하게 하려고 합니다. 그에 따른 데이터들도 false인 상황에 맞게 바꿨겠지요.

근데 이게 false로 바꾸는 와중에 context switching이 일어나 버립니다. 그럼 다른쪽에서는 isProcess가 true기 때문에 걍 고해버립니다. 물론 로직을 적절히 배치하면 이런 문제를 최소화 할수 있습니다만, 모든 팀원이 다 이상황을 확실히 알고 있고, 조심할거라는 생각은 하지 마시기 바랍니다.

ps. 윈도우 플랫폼이라면 Interlocked.. 시리즈를 사용하세요. 그리고 CRITICAL_SECTION의 부하가 성능에 영향을 줄정도로 큰건 아닙니다. 조금이라도 의심이 간다면 그냥 쓰세요. 아주 황당한 연산이 아니라면 CPU가 100%되기 전에 다른 리소스가 딴지를 걸테니 걱정안하셔도 됩니다.
_________________
더 이상 이 곳에 오지 않습니다.

위로


전외솔

가입: 2002년 7월 3일
올린 글: 517


--------------------------------------------------------------------------------
타 사이트 ID(?):
102053962 올려짐: 2006-07-20 23:37

--------------------------------------------------------------------------------

neuk님께서 적으신 글은 boolean 값에 대한 변경이 atomic한지 아닌지에 대한 답변은 아닌 것 같습니다.
이것이 atomic하다면 보여주신 예제에서
인용:

근데 이게 false로 바꾸는 와중에 context switching이 일어나 버립니다.

이러한 경우 자체가 일어나지 않을겁니다.

쓰레드라는 것이, 멀티 프로세싱이 아니라 단일 프로세싱에서 시분할 개념으로 쓰레드들이
CPU를 나누어 갖는 것이기 때문에, atomic한 연산에 대해서는 연산 도중에 context switching이
일어나지 않습니다.

저도 모르는 내용이라서 질문을 이어가려고 합니다만, 혹시 누구 아시는 분 안계신가요 ?
IsProcess=false; 와 같은 코드가 atomic한지 아닌지에 대해서요.

위로


sphawk

가입: 2004년 5월 28일
올린 글: 149
소속: N모사
올려짐: 2006-07-20 23:46

--------------------------------------------------------------------------------

결론부터 말하자면, atomic하지 않습니다. 어지간한 멀티스레드를 다루는 책이면 다 나오는 이야기입니다.

bool isProcess = false;
C++ 로는 한줄이지만, 컴파일되면 몇개의 어셈블리 명령으로 바뀔지 며느리도 모릅니다.
(추측은 가능하겠지요. 레지스터로 적재-<;레지스터값 메모리에 기록.. 이런 식으로 될 듯 합니다.
증가연산이면 레지스터 적재 -<; 레지스터값 증가 -<; 메모리에 기록.. )
그리고 어셈블리 명령 하나로 컴파일되면 해결되느냐..
그것도 아닙니다. 버스에 락 걸지 않으면 다중프로세스 환경에서는 장담 못합니다. 괜히 InterlockedXXX 계열 명령어들이 있는 것이 아닙니다.

위로


비회원
손님

올려짐: 2006-07-21 09:59

--------------------------------------------------------------------------------

producer-consumer 모델에서의 아래와 같은 플래그 사용도 안전하지 않는 걸까요?

코드:
view source

print?
bool flag = true;

class Producer : public Thread

{

public :

Producer() {}

int svc()

{

while ( true )

{

if ( flag )

{

produce();

flag = false;

}

}

}

void produce()

{

}

};

class Consumer : public Thread

{

public :

Consumer() {}

int svc()

{

while ( true )

{

if ( !flag )

{

consume();

flag = true;

}

}

}

void consume()

{

}

};



위로


hey

가입: 2006년 5월 12일
올린 글: 22

올려짐: 2006-07-21 10:07

--------------------------------------------------------------------------------

음. 몇가지 atomic한 연산이 있습니다. int 값을 대입한다든지, 하나의 변수 값을 비교한다든지, swap의 경우 몇 번의 연산이 필요하지만 - atomic한 swap을 제공하는 기능도 있고요.
그런데 문제는 어떤 변수를 건드리는 행위가 atomic하느냐가 그리 중요한 게 아니라는 겁니다. 예를 들어,
코드:
view source

print?
if( !isProcess )

{

isProcess = TRUE;

}

if( !isProcess )와 isProcess = TRUE; 가 각각 atomic한 연산이라고 할지라도, 위의 "구문"이 atomic한 구문인 것은 아니라는 거죠.

위로


비회원
손님

올려짐: 2006-07-21 10:16




위로


조성경

가입: 2005년 12월 13일
올린 글: 307

올려짐: 2006-07-21 11:09

--------------------------------------------------------------------------------

pinewood 씀:
neuk님께서 적으신 글은 boolean 값에 대한 변경이 atomic한지 아닌지에 대한 답변은 아닌 것 같습니다.
이것이 atomic하다면 보여주신 예제에서
인용:

근데 이게 false로 바꾸는 와중에 context switching이 일어나 버립니다.

이러한 경우 자체가 일어나지 않을겁니다.

쓰레드라는 것이, 멀티 프로세싱이 아니라 단일 프로세싱에서 시분할 개념으로 쓰레드들이
CPU를 나누어 갖는 것이기 때문에, atomic한 연산에 대해서는 연산 도중에 context switching이
일어나지 않습니다.

저도 모르는 내용이라서 질문을 이어가려고 합니다만, 혹시 누구 아시는 분 안계신가요 ?
IsProcess=false; 와 같은 코드가 atomic한지 아닌지에 대해서요.


atomic하지 않다고 글의 서두에서 분명히 밝혔는데, 의심을 받다니. 쩝...

C++같은 High-level 언어중에 atomic한건 없다고 생각하시면 됩니다.

동기화 객체도 atomic하지는 않습니다. 결과적으로 그와 비슷한 행동을 하는것뿐이죠.

다른 쓰레드에서 진입하지 못하도록 하는거니까요.


출처: http://www.gpgstudy.com/forum/viewtopic.php?t=11619&highlight=

////////////////////////////////////////////////

이해가간다.cpu의 각 코어의 캐쉬(레지스터)에서 사용할때는 메인메모리하나가 아닌 듀얼코어이상cpu면 여러개라서 연산해다가 쓸때 문제가된다.

즉, 대입할때는 32비트변수라도 무결성(atomic)하지않다. 하지만 읽기는 펌글에도있듯이 인텔32비트cpu특성상 비트단위로 처리하는게아니라서

다른쓰레드에서 쓰더라도 bit로 끊어서 쓰는게아니라서 안전하다!!

단 64비트 변수라면 32비트씩 두번끊어서쓰기땜에 읽기도 락을 걸어야한다.

메모리블록이라는게 있는데 cpu코어의 캐쉬를 안쓰고 메인메모리하나만 쓰도록하는게있는데 그게 그역할임!! 크리티컬섹션락은 쓰레드별로 동기화라서 그 기능까지 포함된거라보면됨.

즉 int형변수는 읽을땐 그냥 읽어오면되고 쓸때는 락을걸어주고. strcpy등으로 데이터를 32비트초과해서 얻어올땐 읽는것도 락을 걸어줘야함!

또 로직상 읽기 쓰기가 락이필요하다면 데이터무결을위해 걸어줘야함!






www.shop-dwg.co.kr 구인, 구직 소개