스레드에 관해서 궁금해서요 글 올립니다.

jw8704의 이미지

안녕하세요

멀티 스레드 프로그래밍 에 관해서 궁금한게 있어서 여쭤봅니다.

스레드를 사용하면 병렬처리? 개념이 되는건가요? 안되는건가요?

마땅히 예를들을 만한것이 없어 부족하지만 예를 하나 들어보겠습니다.

어떤 프로그램에서 직사각형으로 이루어진 블록을 길에 수평으로 ㅁㅁㅁㅁㅁ 형식으로 서울서부터 부산까지 이어붙여 나가는데요

그때 스레드를 사용해서 A 스레드는 서울서부터 경기도, B 스레드는 경기도서부터 경상남도 또 C는 어디서부터 부산 이런식으로 나뉘어서

초기에 스레드를 다 생성시켜서 하는거랑.

그냥 프로그램이 스레드 생성안하고 서울서부터 부산까지 하는거랑 어떤게 더 속도가 빨리 될까요?

궁금해서요.. 알려주시면 감사하겠습니다.

저건 단지 예를 들은거고 제가 궁금한건 스레드가 어떤 문제를 병렬적으로 속도를 빠르게 처리하는데 이용될수있나요?

또 이용한다면 저렇게 하는것도 하나의 방법이될수있나요?

안녕히계세요.

사랑천사의 이미지

우선 thread 하나당 한 processor에 할당되고 동시에 그에 걸맞는 통신 대역이 주어지고 한다면 충분히 그런 식으로 병렬 처리 될 거 같습니다. 다만 thread간 충돌이 일어나지 않게 조율을 잘 해야 할 거고 특히나 공유된 메모리에 접근할 때는 서로 기다려주고 기다리는게 필요하겠조. 만약 공유 메모리에 이런 식으로 접근하는 경우라면 경우에 따라서는 병렬 처리는 어려울 겁니다. 결국 한 thread가 메모리에 쓰기나 읽기 하는 동안에 다른 thread가 기다려야 할 테니까요. 물론 항상 그럴 필요는 없겠조. 모든 스레드가 읽기만 한다거나 쓰기 작업이라도 그냥 정말 쓰기만 하는 경우라면.

그런데 thread를 이용해서 병렬 처리를 하는 경우라면... 특별히 이 분야를 먼저 생각해 보실 것이 아니라 병렬 처리 자체의 유용성이나 사용 환경, 필요 환경 등을 먼저 생각해 보시면 답이 쉽게 나오지 않을까요?

병렬 처리라는게 흔히 말하는 클러스터나 이런 식만 있는게 아니고 말씀하신 것 처럼 multi-processor에 multi-threads를 얹어서 어떻게 처리해 보는 것도 들어가는 걸고 알고 있습니다. 근데 이거 꼭 multi-threads가 아니어도 되긴 할겁니다. 어덯게 라이브러리 잘 사용하거나 만들면. 근데 전... 이 족은 잘 몰라서 하하.

사람천사

ifree의 이미지

멀티 코어 머신이라면 멀티스레딩 작업이 더 빠르죠.
코어가 충분하다면 위의 A, B, C 세 쓰레드가 동시간에 병렬로 진행될 수 있습니다.

싱글 코어의 경우에는 속도의 향상은 없고 병렬 진행의 오버헤드로 오히려 더 느려지게 됩니다.
즉, 하나의 코어가 시간을 쪼개어 세 개의 스레드를 왔다 갔다 하면서 수행하게 되는데 스레드 간 전환으로 인해 오버헤드가 발생하죠. 이 경우, 순간적으로는 하나의 스레드만 수행되므로 병렬 진행이라고 할 수 없지만, 어느 정도의 시간 간격을 두고 관찰하면 여러 개의 스레드가 수행되었으므로 병렬 수행이라고 볼 수도 있죠.

멀티 스레드가 최대의 효과를 발휘하는 예는 3D 그래픽 렌더링과 같이, 공유된 데이터를 읽기만 하면서 각 스레드가 완전히 독립적으로 수행되는 경우입니다.

Hyun의 이미지

그런데, 멀티코어의 경우 캐쉬 동기화 등의 이유로 한 프로세스 안의 다중 스래드를 여러 CPU에서 동시에 실행하는게 힘들지 않나요?

지리즈의 이미지

코어별로 별도의 캐쉬도 가지지만, 코어가 공유하는 캐쉬도 있지요.

그리고, 캐쉬 동기화가 필요한 쓰레드라면
쓰레드 별로 데이터를 동기화할 필요성이 있다는 의미인데,
slee0303님이 언급하신, "3D 그래픽 렌더링과 같이, 공유된 데이터를 읽기만 하면서 각 스레드가 완전히 독립적으로 수행되는 경우"와 같은
멀티 스레드가 최대의 효과를 발휘하는 예에는 속하지 않습니다.

There is no spoon. Neo from the Matrix 1999.

preisner의 이미지

Hyun님이 언급하신 내용은 SMP 머신에서 나타나는 CPU cache 동기화 문제인 것 같습니다.
멀티 프로세서 시스템에서 CPU를 늘리는 만큼 성능 향상이 일어나지 않는 주된 이유 이기도 하죠.
OS 레벨에서 처리하는 쓰레드와는 별로 상관없는 주제 입니다.

싱글 CPU 장비에서 멀티 쓰레드 라고 해도 결국 하나의 CPU에서 실행 되긴 합니다만,
일반적으로 많이 쓰는 커널 쓰레드 모델에서는 100개 쓰레드를 가지는 프로세스는
단일 쓰레드보다 100배 많은 CPU 시간을 확보 할 수 있게 되므로 일반적으로 응답성은 좋아지게 됩니다.
(단순하게 이렇다, 라고 말할 순 없습니다만, 일반적으로 말이죠.)

slee0303님 이 언급한 3D 렌더링이 멀티쓰레드를 이용한 좋은 예 입니다.
네트워크 데몬 어플리케이션들도 멀티 쓰레드 모델을 많이 사용 합니다.

지리즈의 이미지

처리속도의 향상(물론 다중 프로세서에서는 의미가 있지만)보다는
응답성 때문이죠.

설사 쓰레드를 사용하는 것이 안그런 경우보다 더 느려질 수 있더라도,
선택의 여지가 없기 때문에 사용합니다.

질문자의 글이 참 오묘한데,
이 부분에 대한 이해가 있는지 없는지를 파악하기가 참 어렵다는 점입니다.

저도 저 답글을 달 때 고민을 많이 했습니다. ^^

There is no spoon. Neo from the Matrix 1999.

지리즈의 이미지

캐쉬 동기화 등의 문제가 거의 없습니다.

병렬로 처리해서 연산속도를 늘리기 위해서는
가급적 쓰레드간의 통신의 양을 줄여야 합니다.
쓰레드간 통신이 많아지면 아무래도 효율이 줄게 되지요.

그래서, 병렬 프로그램은 상당히 어렵습니다.

There is no spoon. Neo from the Matrix 1999.

preisner의 이미지

제가 혹시 잘못 이해하고 있는게 있는지 궁금해서 글을 남깁니다.

말씀하신 캐쉬 동기화라는게 멀티 쓰레드와 무슨 관계가 있는지 모르겠네요.
Lock 이나 공유 메모리 를 통한 쓰레드간 통신/데이터 동기화 문제에 대해서는 이미 잘 알려진 문제라 저도 잘 알고 있습니다만,
Cache 동기화 문제가 멀티쓰레드와 관련 있다는 건 처음 들어보는 내용 이어서 말이죠.
말씀 하신 Cache 동기화가 CPU 간 L1/2/3 Cache 동기화를 말씀 하시는 게 아닌가요?
CPU Cache 동기화 문제는 멀티 쓰레딩 이 아니라 멀티 프로세서 환경에서 나타나는 문제라고 생각 합니다만.

지리즈의 이미지

"그런데, 멀티코어의 경우 캐쉬 동기화 등의 이유로 한 프로세스 안의 다중 스래드를 여러 CPU에서 동시에 실행하는게 힘들지 않나요?"
라는 글에 대한 내용이었습니다.
(멀티 코어 대신 preisner님 말씀대로 일반적인 SMP로 생각하고)

멀티 프로세서 환경에서 멀티 쓰레딩의 효율을 고려하는 내용이겠죠. ^^

단일 CPU에서 멀티 쓰레딩은 이러한 문제가 없을 겁니다.

제가 잘못 생각하고 있을지도... ^^

There is no spoon. Neo from the Matrix 1999.

ddoman의 이미지

약간 다른 예를 들어보겠습니다.

어느 오피스가 있는데, 다음과 같은 일꾼들이 필요로 합니다:

====================================
경리1, 인사관리1, 청소1, 매장관리1
=====================================

만약 일꾼( CPU )이 1명이라면
저 4개의 포지션을 다 감당 할 수 없습니다.일꾼은 한명이거든요

그렇다면, 마치 4명의 일꾼(4개의 CPU)이 있는거 마냥 한 사람(1개의 CPU)이

경리의 일을 10초간 하다가,
인사관리 일을 10초간 하다가,
매장관리를 10초간 하다가...
그런식으로...

한 사람이서 여러일을 동시에 하는것 마냥..여러 일을 동시에( 사실상 정말로 동시(병렬)에 진행하는건 아닙니다. 몸=CPU 는 1개니까요 )
작업 하는것을, ""멀티 쓰레딩""이 라고 생각하시면 됩니다.

사실, 기술적으로 정확한 표현은 아닙니다. 하지만, 일단은 비유상 그렇게 이해하시면 됩니다.
======================================================

이 비유에서 든 예와 같이...마치 한 사람이서 여러 일을 해 봤자, 정말 돌아가는 일꾼의 수( CPU 갯수 )는 1이므로
즉, 병렬처럼 가상으로 이일했다가 저일했다가 해봤자, 그냥 경리일 전념해서 모두 끝내고, 인사관리 일 모두 끝내고...이런식으로
순차적으로 하는것보다 빠를수 없습니다.

오히려, 10초마다 이일 저일 바꿔가며 동시에 진행하는것처럼 하려고 해봤자, 저일 했다가 일을 계속 바꿔서 해야하기 때문에
일 전환 비용이 발생합니다. 우리의 손은 2개고 우리의 머리도 기억용량 한계가 있기 때문에
경리일 하다가 화장실 청소 좀 하고, 다시 경리 위치로 돌아왔을 때, 마치 그전에도 경리일을 계속 그 일하고 있었던 것 처럼 마냥
바로 일을 시작 할 수 없습니다. 기존에 어디까지 하고 있었는지 기억을 다시 해봐야겠죠..

따라서, 각 일 전환( 경리 -> 인사관리 -> 청소 ) 할 때마다
그때까지 하던 상태를 종이(메모리)에 전부 기록을 해놓고, 다음에 다시 그 일을 맡을 때
종이(메모리)에 적어 놨던 메모 등을 보고 기존의 작업 상태로 기억을 되 살린 후
다시 그 일을 시작합니다.

이 일 전환 비용은 컴퓨터에서 context switching이라고 불리는데,
이 비용이 매우매우매우 비싸서, 병렬로 처리를 해봤자 이 context switching 비용 때문에 오히려 그냥 순차적으로 직렬로 처리한것 보다
총 소요시간이 더 길어지는..즉 배보다 배꼽이 더 큰 경우가 많아 집니다.

===============================================

그래서 병렬 처리는 느린것이냐? 꼭 그렇지는 않습니다. 문제는 job의존성과 완료시간입니다.
가령, 청소잡을 할 때 빨래 해야한다고 가정합시다.
세탁기에 빨래를 넣고 빨래가 완료되기까지 30분이 걸린다고 했을 때,

만약 순차적으로 일을 경리 -> 인사관리 -> 청소 -> 매장 관리
를 하고 있었다면, 청소시간중 빨래 관 완료되기 까지 기다리는 시간은..그냥 낭비일 수 있습니다.

하지만, 병렬로 일을 조금씩 시간별로 분할 하고 있었다면
빨래가 완료 될 때까지, "청소"에는 전혀 시간을 할당 안하고
다른 경리나, 인사관리 등의 일에 시간을 더 할당 했다면( CPU자원을 더 할당했다면 )

총 소요시간은...앞서 말한 context switching 비용을 감안하더라도 훨신 단축될 것입니다.

그래서, 병렬이 빠른 경우가 대부분이냐라고 묻는다면 꼭 그렇지도 않습니다.
앞서 다른분들이 말한...synchronization 문제...

만약 경리와 인사관리가 같은 자료를 사용하며 일을 하고 있었기에, 서로 일을 진행함에따라 서로에게 보고를 하고
그 결과를 계속 기다린다던지..그런식의 자료 공유와 관련한 문제가 발생하면 또 다른 비용이 발생합니다.

=====================================================================

즉, 멀티쓰레딩이 속도개선에 도움을 주냐는 질문에 대한 답변은...그럴수도 있고 아닐수도 있다..라는 것 입니다.
지리즈님이 말씀하신것처럼 총 소요시간을 줄이는 목적보다는 응답성을 빠르게 하는 목적으로 사용하는 경우도 많고,

병렬 프로그래밍의 목적은

어떻게 하면 CPU의 연산을 더 빠르게 만들어서 속도를 늘리거나
CPU가 처리해야하는 양을 줄여서 더 빠르게 만드느냐...그런것들은 아니고

어떻게 하면 CPU가 노는 시간( 대개의 경우 H/W I/O가 끝나길 기다리는 시간 )이나
BUSY WAITING같은걸 최소화 시키느냐는 것입니다.

좀 더 깊이 파고들자면
대학교 2,3,4학년때 배우는 운영체제 과목들 교재의 CPU scheduling 이랑 synchronization의 주제들에 대해서 공부하시면 좀 더 정확한 답변을 얻으실 것입니다.

emptynote의 이미지

저기.. 운영자님께 이글 옮겨 달라고 하시면 안될까요?

여기는 자유 게시판입니다.

jachin의 이미지

말씀하신 예처럼 서울부터 부산까지 블럭을 이어간다고 생각해봅시다.

서울-대전-대구-부산구간을 통해 블럭을 이어갈 예정이 정해져 있다면,
이 경우 스레드는 성립합니다.
'서울-대전', '대전-대구', '대구-부산'은
각각 독립된 조건으로 과정을 진행할 수 있으니까요.

하지만 서울-부산 간 어떤 구간을 통해 이어갈지 모른다면,
이 경우 스레드는 쓸 수 없습니다.

임의의 점 '서울', '광주', '대구', '부산' 에서 시작했을 때,
'서울'에서 출발해서 도착점이 '인천'이 되고,
'광주'에서 출발해서 도착점이 '구미'가 되고,
'대구'에서 출발해서 도착점이 '부산'이 된다면,
'서울'에서부터 '부산'까지 블럭을 이어갈 수 없기 때문이지요.

앞의 경우를 '예측 가능한 분산 처리 결과'라고 볼 수 있습니다.
이 때 스레드 함수의 내용은 '블럭을 이어가는 과정'으로 가정합니다.

또 다른 경우도 있습니다.
서로 다른 결과값을 갖더라도 결과값끼리 독립적인 경우입니다.

그래픽 프로세싱에서 Rasterize 된 최종 표시 이미지를 산출할 경우,
3D 가속 하드웨어에 의한 결과값들은 각 스크린 픽셀의 값이 됩니다.
이웃하는 픽셀과 연관성은 있겠지만, 실제로 계산중에는 옆의 픽셀값이
영향을 미치는 값이 아니기 때문에, 3D 렌더링에서 스레드를 쓰는 경우가
많습니다. 이 때 스레드 함수 내용은 '모델에 입사하는 빛의 각도와 카메라
뮤의 법선 벡터를 이용하여 실제 스크린에 투영될 픽셀의 색상값을
구하는 과정'이라고 가정합니다.