예전에 `Multicore의 concurrency를 위해선 멀티스레딩 뿐인가?” 라는 글을 썼다.
OpenMP나 tbb, 혹은 MS의 Parallel Patterns Library 모두 일을 더 쉽게 만들어주는게 아니다. 그네들은 병렬 프로그래밍을 쉽게해주는 기능을 제공해 주긴 한다. 하지만 당연히 싱글스레드 프로그래밍보다 어렵다.
즉, 원래 목표여야 하는 “병렬 하드웨어 활용을 쉽게해주는 것”이 아니다. 이 툴들의 목적은 현재 단일 스레드로 작성한 프로그램을 , 어떻게 멀티스레드 프로그램으로 수정하면 병렬 하드웨어를 좀 더 잘 쓸 수 있을까 하는 경우를 해결하는 것이다.
이거랑 멀티코어 CPU를 잘 쓰는 일은 동일한게 아니다.
쉬운 길은 이미 “많은 프로그램들이 잘 하고 있는 일”이다.간단하게, 하드웨어가 병렬화가 되면 `할 일을 더 주면 된다’. (Gustafson’s Law)
웹 서버나, hadoop처럼 부하가 늘어나면 작업 단위를 처리하는 `프로세스를 더 많이 띄우면 된다’.복수의 프로세스(스레드)가 특정 상태를 공유하면서 / 업데이트하지 않는 이상, 이 방법은
- 작성하기 익숙하고 (익숙한 싱글스레드 프로그램이다!)
- 디버깅 하기 쉽고 (멀티스레드 프로그램은 비결정론적이다)
- 기존 코드를 거의 변경하지 않아도 된다
라는 엄청난 장점이 있다.
서버 프로그래밍의 — 특히 게임 서버 프로그래밍 — 목적은, 지연 시간을 일정 이하로 유지하는 수준에서 최대 처리량(throughput)을 얻는 것에 있다고 생각한다. 즉, 개별 서버 프로세스가 비슷한 일 — 프로세스마다 1개 채널의 로비를 처리한다거나 — 을 처리해서 부하를 적당히 쪼개고, 싱글스레드에서 처리가능한 수준 ((그러니까 엄한 지연 시간이 나오지 않는)) 의 부하를 담당한다면, 굳이 이걸 omp/tbb/ppl 같은 걸 써서 복잡하게 짤 이유는 없지 않은가?
물론 공유 상태가 많으면 MT로 짤 수는 있겠지만, 그 경우에도 비슷한 원칙을 유지한다.
- 싱글스레드화 되는 부분 — 동기화 처리부분 — 은 메시지 교환 등으로 우회하거나, 최소화하고
- 같은 일을 하는 프로세스…대신 스레드를 여럿 둔다
- 그리고 이 스레드의 수만 늘린다
즉, 본질적으로는 일부분을 제외하고는 싱글스레드 프로그래밍을 하고, 이 부분을 늘려서 주어진 병렬 하드웨어를 잘 쓰자라는 것.
그러니까, 싱글 스레드 성능 향상이 목적이 아니라면, omp/ppl/tbb 다 그렇게 영양가 높은 얘기는 아니다라는게 내 생각이다. ((물론 일부분, 예를 들어 tbb scalable allocator라거나 concurrent container류는 그 자체만으로 쓸모있는 라이브러리이기 때문에 여기저기 쓸 곳이 많다. 그렇지만 parallel_for, parallel_reduce 같은게 정말 필요한가?)) 오히려, 전체 구조를 잘 생각하고 똑같은게 여러 개 돌 부분을 찾고, 이 부분을 여럿 띄울 생각을 하는게 — 예를 들자면 마비노기 영웅전의 micro-kernel 틱한 구조에서 개별 서비스를 여러 개 띄우는 것 처럼 — 생산적인게 아닐까?
그 이전에(…) 서버 자체는 많은 경우 애초부터 멀티스레드로 짜고, 독립적으로 할 수 있는 부분도 많기 때문에 tbb같은게 적합할 태스크 패러럴, 혹은 데이터 패러럴한 워크로드가 아닌 것도 좀… 코어를 다 차지할 만큼의 스레드들이 있는데, 굳이 단일 스레드 프로그래밍에서 CPU 코어 여러개 쓰기 위한 방법을 가져다 쓸 이유가 있을까?
—
내가 리뷰 안 쓰는 무언가 때문에 이런 글을 썼다고 느끼면 “그게 다 기분 탓” 입니다.
개인적으로도 병렬 프로그래밍 연구자들이 지나치게(?) computational, algorithmic하게 토픽에 접근하는게 좀 불만이었습니다. 사실 병렬 프로그래밍이라는건 스케일 큰 일부 scientific computing 이슈들 빼면 어떻게 하면 알아서 잘 수행하도록 구조를 잘 만들고 로직을 구성하느냐가 가장 큰 문제라고 생각하거든요.
저 같은 경우는 병렬 프로그래밍 문제의 본질은 거의 대부분 상태에 대한 순서 의존성 – 객체의 처리 순서, 함수 호출 순서, 락이 걸리는 순서 등등 – 에 기인한다고 보기 때문에 이걸 exploit하려는 알고리즘적인 접근은 실효성이 거의 없다고 봅니다. 실제 로직에는 이걸 최대한 감추는 방향으로 가야 된다고 생각… 물론 저게 논문 쓰는데는 좋겠지만 (…)
연구자들이야 기존에 만들어진 프로그램 거의 대부분이 스레드를 염두에 두지 않고 만들었으니, 그 자체를 잘 조작(?)해서 병렬화 하는데 관심이 가는건 어떤 의미로는 당연한듯합니다.
하지만 직업 프로그래머가,
에 머무르고,
라고 말할 수 없는 건, 혹은 말하지 않는 건 좀 문제라고 봅니다. 요 며칠 간 그런 말 하는 걸 몇 개 봤더니 좀 그렇더라고요(…).
TPL 의 경우에는 비동기 방식도 손쉽게 지원합니다. 이 부분이 병렬 프로그래밍 부분과 같은 비중으로 중요하다고 생각됩니다.
공부하면서도 병렬 프로그래밍만 본다면, 거시적으로 프로세스를 여러개 사용하는 것이 더 효과적일 수 있다고 생각했지만, 비동기 방식 지원에 대해 공부까지 해보니, TPL의 경우는 병렬도 손쉽게 사용할 수 있어 좋지만 (초중급에게 교육 시키고, 보급 시키기도 좋습니다) 그보다 더 좋은 점이 비동기 방식의 프로그래밍을 아주 쉽게 적용가능하다는 거라고 생각됩니다. C# 5.0에는 Async 가 기본으로 제공된다고 하니 기대해볼만 합니다.
이 글의 논지는 그런 쪽이 아닙니다. 제가 얘기하고자하는 바는,
1. 정말로 멀티코어 하드웨어 쓰겠다고 비동기/병렬 프로그래밍을 해야하는가?
2. 상호동립적인 비슷한 일(구스타프슨 법칙을 생각하면…)이 많다면 그냥 복수의 동일한 프로세스를 실행하는 식으로 피해갈 수 있겠다
라는 내용입니다.
즉, 정말로 병렬 처리가 필요한 상황이 아니면 — 보통은 병렬 처리가 아니라 병행 프로그래밍 (concurrent programming) 이겠지만 — 굳이 안해도 되며, 위에서 언급한 제약 사항대로 설계 수준에서 피해가자라는게 주입니다.
멀티코어-병렬 프로그래밍 은 매칭이 되지만, 비동기 프로그래밍은 꼭 멀티코어와는 상관없습니다. 당연 Computed Bound 비동기 프로그래밍은 멀티스레딩이고, 멀티코어에서 더 좋은 환경이 되겠지요.
제 말도 비슷한데…
1. 굳이 쓸데 없이 병렬프로그래밍을 적용하려고 애쓸 필요는 없다.
2. 단 비동기 방식은 되도록 사용하자. 그게 IO-Bounded라면 무조건!!! Computed-Bounded라면 절제해서…
사실 모든 코딩 상황이 병렬 처리가 필요한 상황인지 예측하기도 힘듬니다. 그렇다고 현실적으로 개발자들이 병렬 프로그램에 대해 거부감만 가지고, 학습조차 하지 않으려는 그런 상황에서 저는 병렬 프로그래밍으로 적용해보기를 추천합니다. 그런 후 장단점 분석을 해보니 아니다라면 그 때 기존 방식을 사용해도 늦지 않다는 얘기입니다.
2. 상호독립적인 일에 대해서는 뭘로 하던 상관없지만… 같은 프로세스에서 움직여야 하는 제약사항이 있는 Client Application인 경우에는 비동기/병렬 프로그래밍이 필수입니다.
전 굳이 피해갈 필요 없다고 생각합니다^^ (아직 배우지도 못한 사람들이 핑계를 너무 대거든요)
제 얘기는 병렬 프로그래밍은 어차피 쉽지 않으니 피해갈 수 있는 만큼 피해가잔는 얘기입니다.
회사에서 하는 일도 explicit threading으로 서버 프로그램을 작성하는 일이지만, 비동기 메시징을 이용해서 멀티 코어를 모두 활용은 하고 — 물론 충분한 수의 스레드가 돌고 있는 환경 — 전체 프로그램 구조 자체는 아주 일부분을 제외하면 싱글 스레드처럼 만듭니다. (오히려 코어 수가 늘어날 수록 이쪽 처럼 최대한 동기화 연산을 피해가게 만든 성능이 더 잘나오는 편이기도 하고요).
클라이언트 어플리케이션도 멀티 코어 활용한다고 만드는 경우에는 대부분 잘 정의된 병렬 프로그래밍 구조 (producer/consumer, reader/writer, …)만 씁니다. 굳이 전체 패러다임을 옮길 이유는 없는거죠; 현재도 GUI 프로그램에서 반응성 문제 때문에 많은 경우 비동기 메시지로 처리합니다. 다만 메시지 전달을 동기화해서 싱글 스레드처럼 짜도 쉽게 해주는 것 뿐이지요.
시스템 프로그래머적인 관점에서 본다면, 해야 할 일은 “대부분의 응용 프로그램 작성자가 쉽게 코어 활용을 하게 해주는 일”이지 “멀티스레드 프로그래밍을 가르친다”가 아니거든요…
병렬 프로그래밍을 가지고 삽질하고 있지만 병렬 프로그래밍 혹은 멀티스레드, 또는 병행 프로그래밍의 첫번째 원칙은 “필요 없으면 하지 말자”라고 생각해요 ㅎㅎㅎ 주장하시는 바를 요약하면 멀티스레드+단일프로세스보다 단일스레드+멀티프로세스로 하자는데 그게 가능하다면 당연히 그렇게 해야죠. 멀티프로세스 구조는 안정성에도 도움이 되고요. 물론 좀 오버헤드가 따르겠지만 그게 상쇄 가능할 정도라면 그게 편하다고 봅니다.
그리고 보통 OpenMP나 TBB는 (TPL은 안 써봐서 모르겠는데 비슷할 듯) 대부분이 embarrassingly parallel한 작업에 약간의 동기화(barrier/mutex정도)에 적합합니다. 저걸로 복잡한 스레드 제어는 좀 어렵죠. 아예 제대로 디자인 된 패러럴 프로그래밍 언어인 X10/Habanero Java는 잘 추상화된 동기화 연산이 있지만…
강연 듣다가 누가 “멀티스레드로 가야한다!” 라고 주장한 걸 들었나요? 뭐든 필요할 때 쓰는 것이 중요. 마치 안티 패턴을 보는 것 같군요.
한 머신에서 버티컬 스케일링을 극대화하겠다, 그것도 커플링이 심한 경우에… 를 빼고는 사실 멀티스레딩 하면 안된다고 생각하빈다.
근데 최근에 들은 강연 몇 개에서 그런 얘기를 듣고나니 좀 입맛이 쓰더라고요.
현실에서 웹 프로그래밍 개발자만 가득한 상황에서, Client Application이나 백그라운드 서비스 모듈을 만드는 고급 개발 과정으로 진입하기 위해서는 멀티스레딩 프로그래밍은 필수입니다. 거기에 비동기 프로그래밍도 필수이구요 (네트웍, 큐 방식). 거기에 병렬프로그래밍까지 할 수 있다면 더 좋겠죠.
현실적으로 후배 개발자들에게 기술 전수를 하려고 할 때, 제가 애로점을 느끼는 것은
첫째. 웹 프로그래밍 경험만으로 다른 기술에 대한 필요성을 느끼지 못한다는 점
둘째. 스레드에 대한 개념이 없다. (물론 OS, DB, WAS 의 기초적인 구조도 모르는 경우도 허다합니다)
세째. 문제 해결을 위한 적용 방안에 대한 장/단점 분석이 객관적이지 않고, 자신이 알고 있는 수준에서 결정한다는 것입니다. (예를 들어, 비동기 방식 프로그래밍을 모른다면, 절대로 비동기 방식 프로그래밍을 채택하지 않습니다)
뭐 현실적으로 이런 문제 때문에 아침에 비몽사몽 얘기했습니다.
CGI 는 멀티프로세스이고, IIS 는 멀티스레드 방식이죠. 제대로 사용한다면 저는 IIS가 더 좋은 방식이라 생각됩니다.
IIS를 제대로 활용 못하고, 잘못 사용하는 개발자가 문제지요.
제가 비동기 프로그래밍을 비판하는 입장은 아닙니다. 멀티스레드 프로그래밍이 만능의 칼은 아니라는 거죠. 말씀하신 바처럼 싱글 스레드 프로그래밍에만 익숙한 ‘많은 수의 개발자’에게 적합한 구조’를 만들어야 한다는 얘깁니다.
너무 개발자들을 몇 가지 스테레오 타입으로 나누려고 하시는 듯 한데,
1. 웹 프로그래밍이라고 해도 크게 프런트엔드와 백엔드 프로그래머로 나눈다면, 백엔드 프로그래머들은 (어차피 이전에도) 멀티스레드 / 멀티 프로세스 프로그래밍을 해왔습니다. (간단한 예로는 제가 참가하고 있는 프리웨어 멀티스레드 웹 서버인 Berryz WebShare부터, 훨씬 복잡한 메시지 큐 구현체나 웹 서버, 혹은 웹 서비스 컨테이너 작성자들이 있겠습니다)
2. 스레드에 대한 개념은 학부 OS 수준만 알아도, 실제로 많이 경험하게 될 일은 (적어도 제가 생각하기엔) 태스크 병렬 작업들이거나, 전체 병렬화 작업이 잘 정의된 과학연산들일꺼라 큰 문제 없어 보입니다.
3. 이런 문제 분석은 좀 더 높은 추상화 수준에서 일어나야 하고, 경험 적은 개발자가 그걸 다 하진 않을 거 같은데요.
부언하자면, CGI는 ‘프로토콜’이고 IIS는 MS의 웹 서버입니다. 약간 비교가 이상하네요. 예를 들어 CGI 인터페이스의 프로그램이 Apache MPM 의 개별 워커 프로세스 (설정에 따라선 스레드) 위에서 돈다면 이건 다른 의미로 멀티스레딩이죠. 그리고 단일 CGI 프로그램이라 할지라도 그 내부 구현을 단일 스레드로 제한하지는 않습니다.
CGI와 ASP.NET이 되겠죠..
저랑은 현실적으로 많이 다른 곳에 있는 듯합니다. 아마 Business Web Application 프로젝트에서 90% 이상이 스레드에 대해 모릅니다.
학부요? 요즘 웹 개발 환경에서 말이죠 전산이외의 과가 더 많고, 전산과 출신이라 하더라도 스레드에 대해 전혀 사용해보지 못한 그런 사람들이 더 많더군요… 이런 사람들이 언젠가는 중급, 고급 개발자로 커야 하는데, 그렇게 되기 위해서는 꼭 멀티스레드에 대해 공부해야 한다는 점입니다.
말씀드렸듯이, CGI 인터페이스를 써도 얼마든지 그 위에서도는 프로그램은 MT일 수 있습니다. CGI래봐야 환경변수, stdin/stdout에 대한 조건 밖에 없으니까요.
그리고 웹 개발로 더 한정해서 얘기하자면, 대체 웹 서버나 캐싱 레이어, 웹 응용 프로그램 컨테이너 말고 MT에 대해 생각할 이유가 있나요? 웹 자체의 스케일링은 주로 버티컬한 MT 기반의 스케일링이 아니라, 단일 서버내의 복수 프로세스 (혹은 복수 웹 응용 프로그램 스레드), 혹은 복수 서버 군에서의 다중 프로세스 + 캐싱 + 리버스 프록싱 + 로드 밸런싱 … 등으로 이뤄질 거라 생각합니다.
대다수의 개발자가 이를 위한 인프라 (웹 서버자체, 캐싱 서버 자체, 데이터 베이스 엔진 자체, … )를 작성하는게 아니라면 굳이 비동기/병렬 프로그래밍을 해야할까요? 현재 유효한 하드웨어 자원들은 인프라 자체에서 활용하는 형태로 가는건데 말이죠…
그런 의미에서 중급/고급 개발자로 크려면 이런 큰 그림을 이해하고, 어디가 정말 성능 문제를 일으키는지 파악하고, 해당 부분을 극복할 수 있는 구조를 설계할 수 있어야 할 것 같습니다.
오프토픽이지만 현대적인 웹 프로그래밍 모델이 아니신 것 같습니다. 단일 프로세스의 멀티 스레드로 얼마나 많은 요청을 커버할 수 있을까요? 하나의 프로세스가 생성할 수 있는 쓰레드의 양은 제한적입니다. 웹서버가 reverse proxy가 되는 현대적인 웹 프로그래밍에서는 다중 프로세스를 선택하는 것이 일반적입니다. 그리고 요청의 상당수를 백엔드의 메시지 큐와 같은 외부 세계에 의존하고요. 지금의 웹 프로그래밍은 예전의 더 많은 요구사항을 더 강력하게 수행하면서도 더 이해하기 쉬운 모델을 가지고 있습니다.
왜 단일 프로세스라 한정하지요? 왜 모아니면 도입니까? 두 분 말씀 자체가 우선 순위의 애기라면, 당연히 비용이 저렴한 단일 프로세스의 멀티스레드 방식부터 시작해서, 더 많은 확장성을 위해서 멀티 프로세스의 멀티 스레드로 가야지요. 왜 제 말이 단일 프로세스에 한정한다고들 생각하는지 이해가 안되네요. HA 구성도 효율 및 효과를 생각한다면 당연히 멀티스레드 특히 ThreadPool을 잘 사용해야 한다고 봅니다.
지금 모델과 구 모델을 뭘 말씀하시는지?
.NET Framework의 경우, CPU당 WorkerThread 수를 25 -> 100 으로 늘렸습니다. 그래도 프론트쪽에서 잘못구현하면 요청큐가 꽉 찰 수 있습니다.
H/W로 뭔가 하는 것은 프로그래머가 잘 이용하는 것 밖에는 안되는 것이고, 그 것으로도 부족할 때에는 결국 S/W 적으로 해결해야만 합니다.
전 S/W 방식으로 해결방법이 있는데도, H/W에 미루는 게 더 이상하다고 생각합니다.
일단 원본 블로그 글을 다 읽고 글을 써주시면 좋겠네요.
우선 순위문제라면 당연히 가장 쉬운 단일 스레드의 복수 프로세스 그리고 복수 머신으로 가야지요. 이게 불가능해서 다중스레드 프로그래밍으로 버티컬 스케일링을 하려는게 아니면요. 게다가 HA를 단일 머신에서 한다는건 잘 이해가 안가는군요. 겨우 스레드 풀로 HA를 한다는건 SW버그나 하드웨어 오동작은 신경도 안쓰겠다는 건가요?
지금 디밥님이 얘기하는 모든 문맥이 전부 구모델입니다. 단일 머신의 성능을 올려서 부하를 견디는게 예전 방식인 거죠.
왜 프런트 웹서버와 응용 프로그램 컨테이너가 하나인 IIS + .net 으로 얘기를 한정하는건지 설명 좀 해주시면 좋겠군요.
여기서 하고자하는 얘기는 실제로 부하가 걸리는 웹 응용프로그램과 프런트엔드를 분리하고 해당 부분을 복수로 여러코어 여러 머신에 뜨워서 부하를 견디고 다중 코어도 잘 쓰잖거죠. 왜 겨우 단일 머신 단일 웹서버 얘기인지 모르겠네요.
그게 아닙니다. 순서가 바뀌지 않았느냐는 것입니다. HA를 누가 단일 머신으로 구성합니까? 당연히 여러 머신으로 묶는 것이지요. 제 얘기는 HA 구성 전이라 하더라도 Local Optimization이 선행되어야 한다는 요지이고, HA 를 구성한다 하더라도 결국 확장성면에서 좀 더 좋아졌을 뿐 단일 요청에 대한 처리는 결국 한 머신에서 이루어집니다. 그러니 ‘비동기’ 가 됐던, Thread Pool 이 되었건 좀 더 나은 throughput을 내기 위한 방안을 찾아야 한다는 것이지요.
제가 글을 잘 못쓰나요? HA 하면 당연히 멀티 머신이라 얘기한 건데, 문맥상 뛰어넘은 부분이 있나보군요.
왜 local-optimum을 찾아가는 ‘헛수고’를 해야하는 거죠? 대부분의 경우 “전체 시스템”에서 최적점을 찾으면 local-optimum을 찾는데 들어간 수고 중 상당 부분은 ‘헛수고’로 끝납니다.
복수의 머신, 복수의 코어, 이 모든걸 활용하기 위한 구조를 짜내면 버그내기도 쉽고, 대부분의 프로그래머에게 그다지 일상적이지 않을 다중 스레드 프로그래밍을 강요할 이유가 없습니다.
달리나음 님이 말씀하신 것처럼 왜 IIS + .net thread pool이라는 기괴한 구조에 집착하시는건지요?
현존하는 대부분의 horizotal-scaling하는 아키텍쳐는,
* 직접 연결을 받는 가벼운 웹 서버 (프런트엔드웹서버)
* 어떤 의미있는 연산을 하는 웹 응용 프로그램과, 그 응용 프로그램을 실행하는 웹 응용 프로그램 컨테이너 (IIS는 그 무게 때문에 역할은 이 기능 이상을 할 수가 없습니다)
* 이 사이의 연결을 처리하는 로드 밸런서와 리버스 프락시들
* 전체 시스템에서 메시지 교환을 위한 메시지 큐(MQ) 혹은 인 메모리 자료 구조(Redis?)
* 이 시스템에서 사용하는 데이터가 유지되는 데이터베이스와 이 데이터베이스들의 샤드, 밸런서, 슬레이브 머신들…
이렇게 계층적이고 / 잘 분리된 인터페이스를 사용합니다. 그런데 왜 겨우 응용 프로그램 컨테이너 하나에 집착해서 스레드 풀, 비동기 처리, 다중 스레드 프로그래밍을 해야할까요?
멀티 프로세스로 horizontal scaling할 수 있는 구조라면 멀티 쓰레드를 이용한 최적화를 해준다고 한들 그로 인한 성능 이득은 상수 수준에 그친다고 봐야 할 겁니다. 특히나 지금 같이 개별 머신에 올라가는 코어 숫자가 한 자리인 상태에서는요. 이 정도는 머신을 더 들이면 되는 일인거고, 개인적으로 병렬 프로그래밍에 통달한 개발자를 구인하는데 드는 비용보단 이 비용이 더 저렴할 것은 확실하다고 보고 있습니다.
윈도우즈를 제외한 운영체제라면 프로세스 생성 비용과 쓰레드 생성 비용이 극단적인 차이를 보이지 않습니다. (이미 아시겠지만) 윈도우즈는 프로세스 생성이 느린 운영체제 중 하나지요. 그리고 쓰레드당 사용할 수 있는 메모리 양의 제약 때문에 하나의 쓰레드가 할 수 있는 일은 단순한 모양을 가지게 되고요. 쓰레드를 이용한 프로그래밍은 일반적으로 훨씬 어렵습니다. 또 다중 머신으로 확장할 때 개념적으로 일관성을 가지기 어렵고요. 멀티 프로세스만 생각하는게 비용의 차이가 크지않고, 더 유연하고, 더 쉽다면 왜 멀티쓰레드를 고집해야 할까요? ASP.NET 밖의 세상에서는 멀티쓰레드를 쓰지 않으면서 몇년 전보다 더 높은 응답을 보여주고 있습니다. 멀티프로세스로 구축을 하고 멀티하드웨어로 나가는게 답이라고 봅니다.
네 난이도에 대한 의견과 비용에 대한 의견에는 동의합니다. 전체적인 방향도 동의하지 않는 바가 아닙니다. ASP.NET을 예를 들었다고 그것밖에 세상이 없는건 아니죠. ASP.NET 조차도 한 머신에서 멀티프로세스로 움직일 수 있습니다. 더 좋은 성능을 보여줍니다. 다만 Cache와 같은 부분은 따로 빼야 합니다. 근데, 그런 부분에 대한 이해나 비용 발생 없이 단순히 H/W 투입만으로 해결되지는 않는다는 뜻입니다.
계속 멀티프로세스에 대해 읽다보니 차라리 GRID가 가장 좋은 해법이라고 생각되네요…
local-optimazation 말을 했을 때 예상했습니다. 총비용이요? 누가 지불합니까? 지불할 사람이 지불할 용의가 있는지요? 실현가능한지요?
1. 최적의 해가 바로 앞에 있지만, 절대 손에 쥐지 못하는 경우도 있습니다.
2. 그 경우에만 최적의 해라고 한다면요?
3. 그 경우의 최적의 해를 다른 사람들이 오용해서 다른 경우에 적용하려고 할 때에는요?
그래서 멀티프로세스도 중요하지만, local-optimization이 라기보다 기본기 차원에서 멀티스레드나 비동기 프로그래밍은 해줘야 한다는 것입니다.
그래야 여러 해법 중에 선택을 할 수 있죠.
이 글의 논지는 “멀티 스레드 프로그래밍을 하지 말아라”가 아니라 다중 코어 활용을 위한 방법은 여러가지가 있고, 현재 많이 사용되고, 그 안정성 / 활용도가 높이 평가되는 방법에 대해 “알리는 것”입니다.
대체 왜 계속 다중스레드 프로그래밍에 관한 얘기를 하시는지요? 그리고 다중 프로세스 프로그램은 해당 프로세스 간 통신을 처리하기 위해서 “당연히 비동기 프로그래밍”입니다.
그리고 뭔가 “다중 스레드 프로그래밍의 비용”에 대해 매우 간과하고 있는 거 같은데, 다중 스레드 프로그래밍의 유지/관리 비용은 매우 높습니다.
그나마 쉽게 쓰라고 만들어놓은 intel tbb나 Microsoft ppl 혹은 tpl, 아니면 omp 같은데서 왜 “디버깅이 힘드니 싱글스레드에서 도나부터 확인해라” 같은 얘길할까요?
업계에서 수위에 드는 엔지니어들이 만든 프로젝트도, 라이브 서비스 몇 년씩 지나도 가끔 레이스 컨디션 등으로 인해 해묵은 버그가 드러나곤 합니다. 심지어 일부 경우를 제외하고는 regression test를 만들 수도 없는 버그들이죠. 이런 문제들은 다 생각하고 그 “총비용”을 계산하면 다중스레드 프로그래밍이 더 나은 해법인 경우는 꽤나 한정적일 겁니다.
저도 달리나음 님이 말씀하시는 것처럼, ‘더 이해하기 쉬우면서도 (외부 요소로) 하드웨어를 활용하는 방법을 찾는 것’에 방점을 찍고 싶은데, MT만 강조하시는 분들이 있더라고요 -_-;
좀 더 직설적으로 얘기한다면 업계에서 말하는 “무식하면서도 간단한” 방법을 말하는 건가요?
그렇다면 더 이상 논의할 게 없네요^^
업계에서 말하는 건, 그리고 소프트웨어 공학에서 말하는건 적재적소겠죠.
모든 곳에서, 그리고 대부분의 프로그래머가 병렬 프로그래밍을 배울 필요는 없겠죠. 오히려 현재의 복수 머신을 쓰는 환경을 생각하면 분산 프로그래밍을 알면 좋기야 하겠군요.
겨우 단일 머신 스케일링만 논하시려는 거 같으니 확실히 더 얘기할 게 없긴 하겠군요.
네 모든 개발자가 멀티 코어 자체도 이해할 필요는 없겠죠. 다만 좀 더 나은 개발자가 되고자 한다면, 적재적소 – 최적의 해법 또는 공학적 타협 – 라 하더라도, 큰 개념에서이고,
제가 이 글을 반대하거나 따지하는 게 아니라, 어떤 사람 (저가 개발자를 색안경 끼고 보는 것처럼 느끼셨죠?) 같은 경우, “최적해법”을 핑계삼아, 모자라는 부분을 채우지 않는 부분을 경계하고자 하는 뜻이 있었습니다.
그리고 H/W로 해결하는 방안이야 말로 Architecture가 정하고, 많은 비용이 수반되는 결정 사항이므로, 개발자로서는 제어할 수 없는 부분이니, 개발자들은 자신들이 제어할 수 있는 부분에서 더 많은 효과와 효율을 찾을 수 있는 방안을 찾자. 그게 현재는 비동기/병렬 프로그래밍이 아닌가? 하는 얘기입니다.
지금 디밥님이 지속적으로 주장하는 내용은,
“많은 개발자들이 최적해법이 아니란 이유로 다중 스레드 프로그래밍 등 모자라는 부분을 채우지 않는다”
라는 것 같습니다.
그렇지만 제가 보기에는 디밥님이
“큰 그림을 보고, 그에 따라 프로그래머들이 쉽고 생산성 높게 일할 수 있게 하라”
라는 소프트웨어 공학의 관점을 무시하는 걸로 밖에 안보입니다.
개발자 != 아키텍쳐란 의견도 이해가 안가고, 자신들이 제어고 선택 할 수 있는 부분인 다중 프로세스 프로그래밍을 이용해서 하드웨어도 잘 활용하고 분산 시스템에도 대비하자는게 이 글의 논지입니다. 굳이 투입 비용 대비 효과가 적을 비동기/병렬 프로그래밍에만 의존할 이유가 없다는 거지요.
제 본 뜻은 “모든 문제가 하나의 해법으로 해결되지 않는다”, 그리고 여러가지 변수에 의해 옳다고 생각했던 해법 또한 변할 수 있다라고 생각합니다.
rein님이 총비용으로 전체적인 최적화를 멀티프로세스로 해결볼 수 있다고 했지만, 그것도 제한된 경우가 아니냐는 겁니다.
일례로 Shopfloor Controller의 경우 많은 처리량을 수용하기 위해 필수적으로 멀티스레드와 비동기 기법이 필요합니다.
특정 case에 대해 이런 해법이 있다. 좋습니다. 그런데, 그 case 에 맞지도 않는데, 그 해법을 드리미는 사람들이 있다는 얘기입니다.
즉 제 논지의 핵심은 “해법의 오용” 에 있다는 것입니다.
모든 개발자가 Architecture는 아니죠. 이건 인건비(MM)를 제외한 비용(고객이 피같이 아끼는)에 대한 결정권한이 개발자에게 없다는 뜻입니다.
위에도 써 뒀듯이. 이 글을 다시 읽어주시기 바랍니다.
다중 코어 활용을 위해 다중 스레드만 주장하면 안된다라는 요지를 읽어주시기 바랍니다.
그리고 당연히 일부 개발자는 아키텍쳐입니다.
그리고 계속 논지를 “다중 스레드 프로그래밍을 배워야 한다”라고만 가지고 가시는데, 이 글의 논지와 ‘무관’합니다. 그 논지로 더 이상 여기에 댓글 안 다셨으면 합니다.
글쓴이께서 방점을 찍기를 원하시는 글에 댓글을 남겨서 죄송하게 생각하지만, 두분의 의견이 모두 유용한 의견임에도 불구하고 사소한 토론상의 오류로 인해 오해만 남기고 끝나는 것 같아 실례를 무릅쓰고 한마디 적겠습니다.
글쓴이께서 댓글에 이 글의 논지로 정리해 주신 다음 사항 중
1. 멀티코어 하드웨어를 활용하기 위해 반드시 비동기/병렬 프로그래밍을 해야하는가?
2. 상호독립적인 비슷한 일이 많다면 복수의 독립적인 프로세스를 실행하는 것이 더 좋다.
2번은 제가 생각할 때 오해의 소지가 전혀 없는 옳은 말씀으로 쓰레드에서도 아무 이견이 없는 것 같습니다.
문제는 1번인 것 같은데, “반드시”라는 데 초점을 맞춰 한마디로 대답을 한다면 No입니다. 2번이 맞는 얘기이니까요.
하지만 법률 문서를 다루듯 토씨 하나하나에 맞춰서 비평을 비판할 필요 또한 없을 것 같습니다. 디밥님께서 말씀하고 싶으셨던 것은 멀티쓰레딩이 ‘반드시’ 필요한 것은 아니지만, “필요한 경우가 분명 존재한다”는 것입니다. 그런 경우가 많으냐 적으냐라는 부분에 있어서는 개인적인 경험과 의견에 의해 입장이 크게 달라지겠습니다만.
글쓴이께서 이 “필요한 경우가 분명 존재한다”라는 것을 충분히 인지하고 계시다는 것은, 글을 유심히 읽어보면 충분히 알 수 있습니다. 그렇기 때문에 어쩌면 디밥님께서 그런 댓글을 다시는 것이 글쓴이의 의도를 충분히 파악하지 못한 일이라고 할 수도 있을 것입니다. 특히, ‘멀티쓰레딩이 익숙하지 않기 때문에 멀티쓰레딩을 사용하지 않는 것은 문제’라는 부분은, 실제로 이 글의 논지와 동떨어진 감이 있고, 특히 이런 맥락의 글을 쓰신 글쓴이를 정당한 근거 없이 직접적으로 비판하는 것으로 비춰질 수도 있다고 봅니다.
하지만, 글쓴이께서도 디밥님의 댓글의 의도를 좀더 넓은 시야에서 파악할 수도 있는 것 같습니다. 올려주신 글을 “엄밀히” 따져보면 글쓴이께서 특정한 경우에 멀티쓰레딩이 필요하다는 것에 동의하는 것을 알 수 있지만, 솔직히 말씀드려 제가 글을 다 읽고 난 뒤에 남는 ‘뉘앙스’는 멀티쓰레딩은 쓸모없다라는 극단적인 쪽에 가까운 것 같았습니다. 물론 글을 자세히 읽어보면 그런 뜻이 아니시라는 것을 알 수 있지만, 디밥님께서 글쓴이께 드리는 말씀이 아니라 이 글을 읽는 다른 독자들을 위해서라도 멀티쓰레딩이 필요한 경우가 있다는 말을 남겨두고 싶으셨던 것도 이해가 갑니다. 댓글이 설령 글쓴이에게 전달되기엔 적절치 않더라고, 글을 읽는 다른 독자들에게 어떤 도움이 된다면 인터넷 상에서 글 자체의 가치를 높이는 데에도 더 도움이 되지 않을까 생각해 봅니다.
실로 주제넘은 댓글을 남기는 것에 대하여 두분께 모두 사과드리고, 제가 오해하거나 잘못 생각한 부분이 있다면 꼭 알려주시면 겸허히 받아들이겠습니다.
좋은 마무리라고 생각합니다.
감사합니다.
서버 프로그램 입장에서는 필장의 의견에 적극 동의합니다.
하지만 클라이언트 프로그램은 사정이 다릅니다.
가령 넥서스 S로 네이버에 들어가면 데스크탑보다 3배이상 오래걸립니다.
네트워크속도는 여전히 기하급수적으로 빨라지지만 싱글코어의 스피드는 따라주지 않으면서 점차 클라이언트 프로그램은 CPU 바운드에 병목이 걸리는 방향으로 가고있습니다.
하지만 브라우저나 게임엔진 등의 클라이언트 프로그램은 정형화된 테스크가 없어 멀티코어를 최대한 활용하게 프로그래밍을 하는것이 너무나 어렵습니다.
OMP, TBB, PPP, OpenCL등의 최근 뜨고 있는 싱글스래드 프로그램을 병렬화 시키는 방법들은 클라이언트 프로그램 때문일 것입니다.
네 클라이언트 프로그램은 사정이 많이 다르죠. 서버는 많은 경우 “잘 정의된 반복단위”가 있어서 상대적으로 최근 뜨고 있는 트렌드가 빗겨갑니다(슬프게도).
OMP/TBB/PPL/OpenCL/Cilk/… 등 최근 나온 혹은 각광받는 방법들이 클라이언트 프로그램에 요긴하게 사용될 곳이 많다는 점에는 저도 적극 동의합니다. 더 쉽고 활용하기 편한 방법도 많이 기대하고 있고요.
저도 TBB를 Core 활용을 높이는데 보다는 Thread Programming을 쉽고 코드를 단순하게 하는데 쓰고 있습니다.
솔직히 잘못짜여진 쓰레드 프로그램은 싱글보다 훨씬 느리고 디버깅도 힘듭니다.
lock/unlock이 심해지고 컨텐션이 발생하는 부분이라면 single thread로 바꾸고 프로세스 여러개 띄우는게 더 좋을 수 있습니다.
넵 저도 그렇습니다. TBB의 워커 모델을 살리기엔 이미 병렬 프로그램인 녀석들은 좀 무리지요. 물론 할당자나 컨테이너들은 즐겁게 쓰오 있습니다 :)
싱글 스레드에서 디버깅 불가능한 녀석들은 멀티스레드에선 (…) 인걸 생각하면… (…)