Microsoft MVP성태의 닷넷 이야기
Parallel.For 에서 동기화문제에 관한 질문입니다. [링크 복사], [링크+제목 복사]
조회: 13748
글쓴 사람
초록물꼬기
홈페이지
첨부 파일
[sync.png]    

안녕하세요, C#을 열심히 공부하고 있는 초록물꼬기라고 합니다.

멀티쓰레딩을 공부하다가 예전에 얼핏 보았던 Parallel Class 를 한번 심도있게 공부해보고자 하는데 도저히 이해를 못하는 부분이 있어서 도움을 청하고자 질문을 드립니다.

일단 질문드릴 간단한 소스코드를 써보겠습니다.

            int n = 0;

            Parallel.For(0, 100, (i) =>
            {
                n++;
                Console.WriteLine(n);
            });

Parallel.For 가 멀티쓰레드로 이 코드를 돌린다고 처음 알았을 때 당연히 n 에 대한 동기화 문제가 발생할거라고 생각했습니다.
하지만 몇번을 돌려도, 중간 인자를 10000으로 늘려도 동기화 문제는 발생하지 않았습니다.

이부분에 대해서 좀 찾아본 결과 Data Parallelism 에 의해 대량의 데이터에 대해 CPU에게 적당히 일감을 나눠준다고 하는데..(http://www.csharpstudy.com/Threads/parallel.aspx)
일단 MSDN 에서도 스레드로부터의 안정성을 All public and protected members of Parallel are thread-safe and may be used concurrently from multiple threads. 라고 명시한 걸로 봐서
(https://msdn.microsoft.com/ko-kr/library/system.threading.tasks.parallel(v=vs.110).aspx)
따로 동기화를 해줄 필요는 없구나! 싶었습니다.
사실 개개의 Thread 에 lock 을 걸어야 한다면 멀티코어의 이점이 엄청 사라질 수 있으니 당연히 장치는 해 두었을거라고 생각합니다.

하지만 중간에 Sleep 를 넣으면.. 즉

            int n = 0;

            Parallel.For(0, 100, (i) =>
            {
                Thread.Sleep(500);
                n++;
                Console.WriteLine(n);
            });

이 코드에서는 n 을 출력한 가장 큰 값이 98 ~ 101 까지 다양했습니다. (제 CPU가 4코어 하이퍼쓰레드라 그런지 값은 8개씩 나옵니다)
즉 동기화 문제가 발생했다는건데(첨부파일 참조)

악보 재생을 Parallel.Invoke() 를 이용해서 하려고 했는데 음악의 속도(BPM)에 따라서 Sleep 는 필연적으로 사용해야 하기 때문에 굉장히 망설여지고 있습니다..

혹여나 제가 MSDN 문서에 대해 좀 잘못 이해하고 있는것 같기도 한데.. 위의 동기화 문제는 왜 발생하게 되는걸까요?








[최초 등록일: ]
[최종 수정일: 1/6/2016]


비밀번호

댓글 작성자
 



2016-01-06 08시52분
[초록물꼬기] 질문 드리고나서 나름 연구해 보았습니다.

1. lock 을 걸어서 동기화를 해보면 어떻게 되는지 돌려보았습니다
 => 동기화가 잘 되는 것을.. 게다가 순서까지 정확히 잘 나오는 것을 볼 수 있었습니다.

2. 쓰레드들끼리 돌아가는 사이에 발생할 수도 있을거라 생각하고 (조금 의미없을지도 모르는)구분선을 생성해주는 메인스레드와 같이 돌렸는데 의외로 처음부터 동기화 문제가 발생하기도 하였습니다.
 => http://mitssi.ncity.net/sync2.png

3. Parallel 이 동기화해주는 원리는 lock 을 거는게 아닐 수도 있을거라 생각하고 혹시나 중복으로 실행하는 쓰레드가 있는지 확인해보기 위해 아래 코드를 실행해 봤는데 마지막 부분에 와서 중복으로 실행하는 부분을 어떤 원리인지는 몰라도 실행은 하되 결과는 적용시키지 않는 것을 볼 수 있었습니다.
 => http://mitssi.ncity.net/sync3.png

4. 조금 흥미로운 점은 3번에서 1000번까지 돌려도 Warning 은 마지막에 가서야 조금씩 발생했지만 3번에서 Sleep 주석을 풀고 1500정도로 맞추면 처음부터 Warning 이 많이 발생한다는 점이였습니다.
게다가 소스코드가 조금 늘어나서 그런지 가끔가다가 알 수 없는 deadlock 도 발생하여 cntl + c 를 한번 누르니 풀려나서 프로그램이 또 실행됩니다.
 => http://mitssi.ncity.net/sync4.png

이상 제가 나름 이해해보려고 노력한 부분입니다 ㅠㅠ (확실한 정답은 아직도 잘 모르겠네요)
[guest]
2016-01-07 12시27분
[ryujh] 안녕하세요. 본문 중에

'악보 재생을 Parallel.Invoke() ...' 로 하는 이유를 모르겠습니다. 악보 재생이 병렬과 관계가 있나요?
[guest]
2016-01-07 12시40분
MSDN의 스레드 안정성은 해당 메서드와 그 내부에서 관리되는 데이터들에 대한 것입니다. 외부의 데이터는 대상이 아닙니다. 가령 Thread.Start도 thread-safe이지만 그 내부에 있는 전역 변수의 값을 thread-safe하게 다루지는 않는 것과 같습니다. Console.WriteLine(n);이 추가되었을 때 동기화 문제가 발생하지 않았던 것은 살펴봐야겠지만, 그건 운좋게 얻은 부수효과일뿐 어쨌든 안전하게 동기화는 해야 합니다.
정성태
2016-01-07 01시31분
[초록물꼬기] @ryujh 아니요! 꼭 병렬로 해야하는 것은 아닙니다. 현재에는 병렬로 안하고 있는데 약간의 랙(?) 같은게 느껴져서 병렬로 해보면 어떨까 싶어서 그렇습니다 ^^
https://youtu.be/RbvFC4d9G7U 여기서 보시면 여러개의 악기가 같이 연주되기 때문에 이 부분을 병렬로 하면 좀 더 자연스럽게 흘러가지 않을까 했습니다.
[guest]
2016-01-07 01시33분
[초록물꼬기] @정성태 아..!! 외부 데이터는 대상이 아니였군요. Thread.Start도 thread-safe 라는 말씀에 확 와닿았습니다. 감사합니다 ^^
[guest]
2016-01-07 01시35분
[초록물꼬기] int n = 0;

            Parallel.For(0, 10000, i =>
            {
                n++;
            });

            Console.WriteLine(n);

으로 했을 때 동기화 문제가 발생하게 되네요. 답변 감사드립니다~~
[guest]
2016-01-07 01시44분
마지막 덧글의 코드가 좀 이상하군요. ^^ 다음과 같은 식으로 확인해야 맞습니다.

        var result = Parallel.For(0, 10000, i =>
        {
            n++;
        });


        while (result.IsCompleted == false) // 병렬 작업이 끝날 때까지 대기
        {
            Thread.Sleep(1);
        }

        Console.WriteLine(n);
정성태
2016-01-07 01시51분
Simple Midi Player using WPF("https://youtu.be/RbvFC4d9G7U") 프로그램 직접 만드신 건가요? 와~~~ 대단하시네요. ^^ 멋진 프로그램입니다.
정성태
2016-01-07 02시08분
[ryujh] 프로그램 잘 봤습니다. 고생 많으셨습니다.

악보 재생이라면 오선마다 악기 하나씩이니 애드립카드의 컴포저처럼 악기별 동시 연주하는 것으로 보면 될까요?

그렇다면 하나의 오선의 연주는 스레드 하나로 순차적으로 실행 (음표 그리는 스레드와 오선그리는 스레드는 별도)

오선마다 스레드는 parallel 반복하는 것이 아니고 시작을 동시에 하고 연주 끝날 때 까지 그 스레드에서 연주나 음표 그리는 스레드를 별도로 두는 것입니다.

컴퓨터 타이머와 스레드 내에서 동기화가 필요할 것 같습니다.

참고하십시오.
[guest]
2016-01-07 02시19분
[초록물꼬기] @정성태 아이고 감사합니다 과찬의 말씀이십니다 ㅠㅠ.. 문제가 많은 프로그램입니다.
수정해주신 코드 보고 또 배웠습니다. 포어그라운드에서 그냥 출력하고 끝날수가 있겠네요.

나름 인터페이스나 클레스 설계라던지.. 굉장히 힘들게 고심하여 MVVM 으로 만들었지만 결과적으로는 이번에도 실패했습니다..
C#의 가비지 컬렉터를 너무 믿지 말라는 말이 너무 와닿네요. 음표를 삭제하고 추가하는 작업을 계속 할 때 삭제한 음표 GUI 덩어리가 일부 남아있는게 계속 쌓여 메모리 릭을 발생시키는데 ㅠㅠ
GUI 덩어리 설계에서 실패한 듯 합니다.. 한번 갈아 엎어서 아예 음표, 코드, 커맨드 들을 IEnumerable 을 상속하여 정말 관리하기 쉽게 만들어보려고 합니다.

집필하신 책 항상 잘 읽고 있습니다. 훌륭한 책 써주셔서 감사합니다 ^^
[guest]
2016-01-07 02시28분
[초록물꼬기] @ryujh 조언 감사합니다 ^^
악기별 동시 연주가 맞습니다.
컴퓨터 타이머와 스래드 내의 동기화 부분에서 많은 고생을 했습니다.
앞으로 더 잘 설계해야 좀 더 부드러운 재생이 가능하겠죠!
연주하는 함수는 이번에 갈아엎을 때 말씀하신 부분 참고하여 설계해보도록 하겠습니다
[guest]

... 31  32  33  34  35  36  37  38  39  40  41  42  43  44  [45]  ...
NoWriterDateCnt.TitleFile(s)
4719이민구4/29/201611971[시작하세요! C# 프로그래밍] 4.5.1.6 열거형 마지막 예제 질문입니다. [4]파일 다운로드1
4718ds4/27/201610331오라클 DB 칼럼에 있는 특정 데이터를 가져올수가 있나여? [1]
4717최령진4/26/20169385모바일 웹 앱 관련문의 드립니다 [1]
4715과객4/7/201611354TFS 와 Stylecop Integration 시 체크인 정책 적용 방법이 궁금합니다. [1]
4714임형복4/7/201611302DLL 을 프로세스처럼 사용하기 [3]파일 다운로드1
4713김태훈4/5/201611492하위 폴더 권한 상속 문제 [1]
4712차가워4/5/201613188멀티코어 스레드 문의 [1]
4711이대희4/1/201610703Xamarin 라이센스 변경 (Visual Sutuio 무료 사용) [2]
4709가가멜3/25/201635073국내 WPF 책은 왜 2010 년 이후로 전멸인지요? [1]
4704최훈3/15/201615004C# 6.0 예제 7.1 관련 질문입니다. [2]
4702popo3/14/201614519C# WeakReference이 CPU 플랫폼 설정 마다 결과가 틀리게 나옵니다. [9]
4701쌉쓰릅3/13/201612227uwp에서 그림판의 지우개 기능을 구현하려고하는데요 참고할 만한 정보가 있을가요? [2]
4700정우진3/12/201610633안녕하세요. 10049소켓에러의 해결법을 알고싶습니다. - 수정본 [1]파일 다운로드1
4699정우진3/11/201613420안녕하세요. 10049소켓에러의 해결법을 알고싶습니다. [1]
4698지나가는3/10/201612012안녕하세요. 주기적으로 일어나는 .net 관련 질문이 있습니다 [1]
4697정우진3/9/20169642안녕하세요. AWS EC2를 이용한 서버 개발에 대해 질문드립니다. [1]
4696삽질맨3/9/201614203Winform Cold Start 로딩 속도 개선 방법이 없을까요? [1]
4695popo3/9/201611982wpf의 ICommand 질문 입니다. [5]파일 다운로드1
4694아무개2/28/201611541책 잘보고있습니다~ [1]
4693초보2/25/20169717카카오톡 오류 질문 [1]
3701강준2/19/2016192242개의 DataTable Join 결과 전체 컬럼을 DataTable 로 리턴하기 [5]
3700박성훈2/18/201610794시작하세요! C# 6.0 프로그래밍 105쪽 예제 질문 [1]
3699박성훈2/18/201610422공부 방향성 질문 [2]
3698강준2/16/201611023Entity Framework 에서 Select for Update 가 가능한가요??? [1]
3697ds2/16/201610573어느 정도 문법을 알고 나면 [6]
3695Bere...2/15/201612844호출당한 메서드가 호출한 메서드를 알 수 있는 방법이 일반적인 방법 말고도 있을까요? [2]
... 31  32  33  34  35  36  37  38  39  40  41  42  43  44  [45]  ...