멀티스레드가 정말 제한된 영역에서만 쓰여야 하는가? Parallel & Cloud

글쎄... 누군가 "멀티스레드는 필수입니다" 라는 주장에 입맛이 쓰다... 멀티스레드 만이 멀티코어를 잘 사용하는 것은 아니다 라고 주장하네요.

제가 병렬 프로그래밍을 공부할 때 항상 의문점이 바로 이점입니다.

어차피 실제 운용 환경에서는 멀티코어가 많은 작업을 처리하느라 바쁜데, 굳이 하나로 처리할 작업을 세분하여, 더 많은 작업으로 나누고, 그걸 Worker Thread에 의해서 작업하는게 얼마나 더 효율적일까? (분명 효율적입니다만 효과적일지 그건 비교해봐야 압니다.)
차라리 기존과 같이 그대로 냅두는 것이 낫지 않을까? "과유불급" 

흠... 아직도 명확한 구분은 없습니다만... 

단 한가지 어느정도 작업량이 되는 것이고, 세부 작업들이 병렬로 처리가 가능하다면, 병렬로 처리하는 것이 더 좋다. 어차피 OS나 Fraemwork에서 작업 스케쥴링에 대해 최적화를 수행하지만, 병렬로 처리가 가능한 것으로 제한적으로 사용하면 좋다고 생각합니다.

누군가는 웹 응용프로그램의 웹 프론트 부분에서 굳이 멀티스레드를 사용할 필요가 있을까요? 라는 의문을 제기하더군요.

일례로 포탈 페이지에 자그만하게 요약용 테이블에 나의 메일/나의 할일/나의 메모/기타 등등의 COUNT를 제공하는 기능이 있다고 하지요.
물론 서비스이니 옵션에 따라 특정 항목의 갯수를 보여줄 것인가 말 것인가 달라질 수 도 있습니다.
이때, 각 항목의 갯수를 구하는 작업은 서로간에 관련이 없으므로 병렬로 처리하면 좋습니다.

즉 갯수를 얻어야 할 항목의 수 만큼 스레드를 만들어서 항목 수를 얻어 온다면, 이상적으로는 1/N 이고, 단일 작업 중 최대 시간만큼 걸리겠죠. 
당연히 순차실행보다 병렬실행이 좋습니다. 더욱이 DB 와의 통신을 IO-Bounded 비동기 작업을 수행한다면, 스레드가 살아있지 않아 Thread Context Changing 부하도 생기지 않습니다.

즉 병렬 작업이 쓰이는 데에는 단순 병렬만으로도 효과가 있지만, IO-Bounded 비동기 방식의 작업으로 수행한다면, 환상적인 결과를 얻을 수 있습니다.

대게 ASP.NET 웹 응용프로그램을 제작하고 서비스하는데, 보통 동시 사용자 50명만 되도 버벅됩니다. 왜일까요? 

  1. 대부분 IO-Bounded 비동기 DB 작업을 하지 않습니다.
  2. 성능에 Critical 한 Page의 경우, 비동기 방식 프로그래밍을 하지 않아, 작업 요청이 계속 쌓이게 됩니다.
  3. 병렬로 수행할 수 있는 작업 부분을 순차방식으로 수행합니다.

웹 응용프로그램 뿐 아니라 일반 Application의 경우에는 더 합니다. Background 처리, UI Update 등 최소 3~4개의 스레드가 돌고 있을 수 밖에 없지요 (메인 스레드 포함해서)

근데 보통 Application 중에 단독으로 실행되어야 할 경우가 많은데, 이럴 경우 멀티코어는 사치일 뿐일까요?
제 생각에는 잘 나눠주면 멀티코어에서 더 잘 사용할 겁니다.

어차피 윈도우즈, 맥 OS, UNIX 등이 여러 프로세스가 돌고 있죠. 그건 OS가 알아서 해주는 것이고, 
자신이 개발하는 프로그램이 전체 구조상, 그리고 성능상 핵심 부분에 대해서는 위의 관점에서 좀 더 좋은 방안을 찾도록 노력하고, 검증하여, 더 좋은 프로그램이 되도록 하시는게 어떨까요?


핑백

덧글

  • 몽몽이 2011/06/12 13:52 #

    비동기 I/O가 Thread Context Switching 부하가 생기지 않는다는 말씀은 어폐가 있는 듯 합니다.
    결국 User Context이든 System Context이든 누군가는 모니터링을 해야 하니까요.
    비동기 I/O는 성능 향상 목적이 아니라 완전한 멀티쓰레딩 지원이 되지 않던 시절의 유물로 알고 있습니다.
  • debop 2011/06/12 14:17 #

    허걱... 잘못 알고 계십니다. Sleep과 Awake... 자고 있는 놈은 일 시킬려고 할 필요가 없으니 CPU가 스케쥴링에서 빼도 되므로, 다른 스레드들이 더 많은 작업을 할 수 있습니다. 즉 시켜도 일 하지도 않을 확률이 높은 놈에게 일할 기회를 줄 필요는 없다는 것입니다. 그래서 Switching 부하가 안생깁니다.
    OS에서 담당하는 일은 기본적으로 어차피 하는 일이므로, 기본적인 부하로 깔고 가야 하는 것이구요.
    CPU, 메모리를 제외한 Disk, Network 작업은 분명히 I/O 를 비동기 방식으로 처리하는 것이 좋습니다.
    유물이 아닙니다. C# 5.0의 가장 핵심 부분이 "비동기" 입니다.
  • debop 2011/06/12 14:25 #

    CLR via C# 2nd Ed. 책을 참고하세요.
  • 몽몽이 2011/06/12 15:34 #

    윈도우는 3.1 시절 비동기 Network I/O API를 만들었고 그러고나서 한참 후에야 지금과 같이 됐죠.
    그리고 동기식 I/O로 멀티쓰레드를 돌리는 것이 비동기 I/O를 사용하는 것보다 throughput이 좋습니다.
    동기식 멀티쓰레드 방식에서도 윈도우의 경우 남은 스케줄을 반납할 수 있으므로 스위칭이 일어나더라도 부하는 상대적으로 최소화할 수 있습니다.
    Disk의 I/O와는 별개의 이야기입니다.
  • debop 2011/06/12 15:59 #

    Windows 3.1 이전에도 비동기 프로그램은 있었습니다.
    누가 동기식 I/O 멀티 스레드가 비동기 I/O 보다 throughput이 좋다고 하던가요?
    그럼 멀티스레드와 ThreadPool 사용하는 것과 어떤 것이 throughput 이 좋은가요?

    멜티스레드의 최대 단점이 개발의 어려움과 CPU에서의 Thread Context Switching 부하인데...
    이 부하를 줄여주는 IO-Bounded 비동기프로그래밍이 처리량이 더 않좋다구요?
    글쎄요...
    제가 분석한 내용과는 전혀 다른 주장을 하시는군요.

    어째됐건 CLR via C# 2nd Ed. 책을 참고해보세요. 저와 비슷한 논지를 가지는 사람이 쓴 글입니다.
  • 몽몽이 2011/06/12 19:57 #

    I/O 비동기 프로그래밍이 개발의 어려움을 줄여주지는 않습니다. 그건 해 보셨을테니 아실텐데요.
    비동기 프로그래밍에서의 에러 처리가 더 어렵지 않습니까.
    throughput 이야기는 예전에 네트워크 전공하던 제 후배에게서 들은 이야기입니다.
    unix 환경에서의 이야기라고 해도 윈도우에서 다를 것으로 생각되지는 않네요.
    그리고 멀티스레드가 Context Switch 부하가 문제인걸 부정하는게 아니라 네트워크 프로그래밍에서 비동기 방식으로 그 문제가 해결되지는 않는다는 말씀입니다.
    system context에서 app. context로 데이터가 복제되어야 하지 않겠습니까.
    그 복제의 부하가 핵심이지 나머지는 상대적으로 부수적이겠지요.
    권해주신 책은 참고하도록 하겠습니다.
  • debop 2011/06/12 20:11 #

    네 이번에 나온 TPL을 해보세요. 그럼 아주 쉬워졌습니다. 예외처리도 구조적이구요.

    네트웍 프로그래밍에 대해 가장 개발이 쉽지만 비효울적인 방식부터 나열해보겠습니다.

    1. 순차 방식으로 Blocking 방식
    2. Unblocking 방식이지만 Thread를 만들어서 사용
    3. Unblocking 방식이면서 IO-Bounded 비동기 방식

    이 부분에 대해서는 추천 서적을 참고해주세요.
※ 로그인 사용자만 덧글을 남길 수 있습니다.