[완료] 멀티스레드 프로그램 관련해서 질문드립니다
안녕하세요, 실력이 안되서 꾸준히 눈팅만 하다가
학교 과제를 하던 중에 제 짧은 지식으로는 해결 안되는 의문점이 하나 생겨서
급히 가입을 하고 질문을 드립니다.
과제 관련해서 kldp에 물어보는게 예의가 아닌 줄 알지만
동기들이나 주위에 물어봐도 잘 모르고, 교수님께 질문을 드렸는데
조금 바빠 보이셨던데다가 제 질문을 조금 오해하신것 같아 더 여쭤 보지는 못했는데
의문점이 이내 풀리지 않아 질문을 드리게 됐습니다.
과제내용은
간단한 멀티 스레드 프로그램이 주어지고
상호배제가 필요한 공유변수를 이용하나
실제로 상호배제관련 코드는 없고,
일단 그 주어진 코드를 몇 회 실행해보고
그 결과를 루프의 실행 횟수를 몇번 바꿔가면서 보이고, 그 결과가 왜 그렇게 나왔는지를 논하고
공유변수가 적절하게 액세스 되게끔 구현한 후에 결과를 보이는 그런 과제입니다.
http://pds24.egloos.com/pds/201203/27/75/Thread.c
http://pds24.egloos.com/pds/201203/27/75/result.JPG
위의 Thread.c는 소스코드이고
위의 이미지 파일은 위의 소스코드를 컴파일한 결과를
인텔 셀러론 M 530 (http://ark.intel.com/products/29733/Intel-Celeron-M-Processor-530-(1M-Cache-1_73-GHz-533-MHz-FSB)-Socket-M)
CPU가 탑재된 노트북으로 실행한 결과입니다.
소스코드가 첨부되어있지만 간단하게 슈도코드를 적어보면
공유변수=0;
특정한횟수 = 임의의숫자;
메인 스레드()
{
스레드1 생성
for(특정한횟수 만큼순회)
{
공유변수++;
}
스레드1종료기다림;
공유변수 출력;
}
스레드1()
{
for(특정한횟수 만큼순회 )
{
공유변수++;
}
}
대충 이런 코드인데 공유변수에 대해 상호 배제가 되는 상황에서는 공유변수의 최종값이
공유변수 = 2 * 특정한횟수
가 되겠지만
상호배제가 되지 않는 상황에서는
1*특정한횟수 와 2* 특정한횟수 내의 임의의 값이 나오게 된다는 것으로 이해를 하고 있습니다
처음에 위의 이미지에 나와있는 2개의 결과들이 다 납득이 가지 않았는데
2000만의 결과가 나온 경우는
실행했던 노트북의 CPU가 싱글코어, 단일스레드 CPU임을 감안할때
스레드1을 생성했으나 생성만 해놓고 컨텍스트 스위칭이 전혀 일어나지 않은 상황에서 메인스레드가 스레드1의 종료를 기다리는
코드에 도달한다면 충분히 그럴 수도 있겠구나 라는 생각을
제 메인 PC(듀얼코어)에서 실행해본 결과가 "1000만과 2000만 사이의 적당한 수" 로 나온 것을 보고 비로소 하게 되었습니다.
실제로 노트북에서도 컨텍스트 스위칭이 일어날만큼 큰 루프(양쪽 다 1억번 순회)를 돌게 하니까 적당한 중간값이 나오더라구요.
그러나 결과값이 1000만으로 나오는 경우는 어떻게 해서라도 제게 이해가 잘 되지 않아서
생각을 조금 해봤는데 결과값이 1000만이 나오는 경우는..
양쪽 루프에서
1. 공유변수 메모리에서 레지스터에 로드
2. 레지스터 1 증가
3. 레지스터에서 공유변수 메모리로 저장
루프 1000만회를 돈다면 2번 위치에서 컨텍스트 스위칭이
1000만회 일어나야한다는것 같은데
한루프당 한 스위칭이 일어날만큼, 스위칭이 자주 일어난다는게 말이 안되는것 같은데
이런 결과가 무엇에서 기인하였는지 이해가 되지 않습니다.
제가 아예 처음 했던 생각의 시작이나 지식이 잘못됬던 것인지 의문이 듭니다.
위의 상황이 듀얼코어 PC에서 돌렸을때는 안 나타나며,
위의 실행 결과들은 VS 2008 컴파일러로 컴파일을 하였는데,
컴파일 후 그냥 실행파일 자체를 실행하면 또 그런 문제가 안 보이는데
Ctrl+F5 단축키로 컴파일후 실행을 이용하면 꼭 그런 상황이 몇번 실행 중 한번 정도로 발생을 하더라구요.
혹시 이 문제에 대해 왜 그럴 것이다 라고 설명을 해주시면 감사드리겠습니다.
디버거 개입 + 컴파일러 최적화가 가장 큰 요인으로
디버거 개입 + 컴파일러 최적화가 가장 큰 요인으로 생각됩니다.
특히 실행 파일를 직접 실행하는 것과 F5키를 눌러서 실행하는 것의 차이는 디버거의 개입으로 인해 만들어진 것 같네요
하지만 저렇게 동기화에 대한 아무런 조치가 없는 멀티스레딩 프로그램이
머리속에 구상한 가상의 모델에 따라서 동작할 것이라는 기대는 하지 않는게 좋습니다.
정확한 예측은 *완전* 불가능하고 대략의 추측은 할 수는 있어도 별다른 의미가 없습니다.
오히려 잘못된 인식이나 가정만 만들어질 수 있습니다.
:)
음 그렇군요..
앞으로 멀티스레드 프로그래밍 할때 가정이나 기대는 배제해놓고
구현을 해야겠습니다.
답변 감사합니다!
좋은 밤 되세요!
확실하지는 않지만
윈도우에서 C코드를 작성해본적이 없으나 일단
첫번째로, 값을 증가시킬때 해당변수를 증가시키는 동안 다른 쓰레드가 끼어들수 있다고 알고 있습니다. 그래서, increse 같은 함수를 제공하는 언어도 있죠.
가정하신대로 그럴수 있다고 알고 있습니다.
두번째는 제가 궁금한건, 생성하는 쓰레드의 지역변수가 초기화 되나요? C에서는 안되는걸로 알고 있는데 윈도우 컴파일러는 지역변수를 초기화 해주나요? 스택내용을 자동으로 초기화 해준다면, 제 짧은 생각으로는 첫번째 경우만있을것 같구요. 쓰레드가 끝나길 기다릴때 sleep을 넣어주지 않으면 싱글코어에서는 행업 비슷한 상태가 되어야 한다고 알고 있습니다.
C 안한지 몇년되어서 도움이 될런지 모르겠습니다.
언제나 시작
댓글 달기