까슈1
12
2019-02-07 13:54:49
8
433

C#(.net 4.0 / 4.5) 멀티스레드(약 2천개 이상) 사용 시, 발생하는 여러가지 문제점..


안녕하세요? 회사에서 어떠한 프로젝트를 하는데, 선임이 없어 물어볼데가 여기뿐이라 여쭤봅니다ㅠㅠ

보안상 완전 자세하게는 설명을 못드려서 죄송합니다..


개발PC 사양은

Windows 10 Pro

CPU : intel Xeon W-2145 3.70Ghz (8코어 16스레드)

RAM : 64GB

입니다.


현재 프로그램 실행 시, CPU 가동률은 거의 90~100%에 육박합니다. 

램 사용률은 약 1Gb정도 됩니다.


스레드를 약 2천개정도 띄워서 실시간 작업을 해야 하는데요,

1천개는 mqtt 통신용이고 나머지 1천개는 계산 용입니다.

통신과 계산이 한 묶음이라, 만약 2천개가 너무 버겁다면 둘을 총 1천개정도로 줄일 수도 있습니다.

스레드는 종료되면 안되고, 항상 살아있어야합니다.(스레드 풀/태스크 사용 불가할 것으로 예상)


보기 쉽게 질문을 리스트로 정리하면

0. 스레드 풀/태스크 를 사용하지 않고 하나씩 전부 생성해서 사용하는 프로그램이 현실적으로 가능 한 것인가요?

1. 스레드 풀을 사용해서 최대 스레드수를 2천개로 잡아도 프로그램 실행 시, 한번에 다 생기지 않는 것 같습니다.

1-1. 태스크도 사용해 보았는데, 최대 개수 지정을 못하는 것으로 알고 있어서, 성능이 더 안좋게 나왔습니다.

2. 각 스레드가 비동기로 동작하다가 어느순간이 지나면, 스레드 1부터 1000까지 순서대로 동작하는데 왜 그런가요?

2-1. 2번 질문과 같은 이유로 스레드 풀이나 태스크를 사용하지 못하고 그냥 무식하게 하나씩 다 생성해서 사용해야 할 것 같습니다..

3. 스레드 1개당 스택?힙? 크기가 기본으로 정해져 있다고 들었는데(1mb?), 그 때문에 스레드 생성 개수가 제한이 된다면, 그것을 임의로 줄일 수 있는 방법이 있을까요?(os 상에서 혹은 visualstudio에서)

3-1. 3번 질문에서 크키를 줄인다면, 프로그램에 걸리는 부하가 줄어들까요?

4. 너무 많은 수의 스레드가 돌다 보니, ui 스레드가 자꾸 죽습니다. 현재 winform으로 개발되어 있는데, ui스레드를 항상 안 죽게 할 수 있나요?

4-1. winform을 wpf로 바꾼다면 달라질까요?


질문이 좀 많습니다ㅠㅠ 첫 직장 신입 개발자에게 선임도 없이 개발하라니 너무 막막하네요

많은 도움이 필요합니다! 감사합니다!!

1
0
  • 답변 8

  • 나도아빠다
    2k
    2019-02-07 14:19:00

    잘은 모르겠지만..어마어마하네요..

    저정도 쓰레드갯수면 얼랭의 영역아닌가요...?!

    0
  • 파란미르
    8
    2019-02-07 14:29:55 작성 2019-02-07 14:32:33 수정됨

    대부분 뇌피셜이긴 합니다만, 도움이 될까 해서...
    0. 불가능하다고 보시는 게 나을 겁니다. 물론 이론상으로는 가능합니다만... 그러지 말라고 나온 게 풀이니까요.

    1. 처음에 미리 만들어두지는 않을 수 있습니다만, 옵션이나 그런 걸 찾아봐야 할 듯 합니다.

    2. 최대치가 찬 것 같습니다. 그렇다면 스레드가 종료되지 않거나 뭔가 다른 문제가 생긴듯 하네요.

    3. 안 되는 걸로 알고 있습니다.

    3-1. 다른 언어에는 경량 쓰레드라든가 하는 개념이 있는 경우가 있습니다. 줄어듭니다.

    4. 항상 안 죽는 건 불가능입니다.

    4-1. 그것보다는 다른 방법을 찾는 게 맞을 듯 합니다.


    지금 상황을 보니까 클라이언트가 2천개 정도 붙어서 서버에서 계산을 처리하는 것 같은데 맞나요?

    그러면 요청마다 쓰레드, 태스크를 생성하지 마시고


    클라이언트 송수신용 워커 => 요청 큐 => 계산처리용 워커 => 결과 큐 => 클라이언트 송수신용 워커


    이런 식으로 처리하는 게 효율이 나을 듯 합니다. 물론 워커는 task나 쓰레드풀을 쓰시구요.

    1
  • 까슈1
    12
    2019-02-07 15:19:32

    @나도아빠다

    답변 감사합니다.. 제가 초보 개발자라 그런데 얼랭이 뭔가요?


    @파란미르

    자세한 답변 감사합니다. 추가로 질문이 더 생겼는데용..

    현재 구조가 [다른 프로그램A - MQTT브로커 - 질문한 프로그램B] 처럼 되어 있습니다.

    A에서 어떠한 명령 브로커로 쏘면 B가 그걸 받아서 처리하고 처리할때마다 상황을 다시 브로커로 쏩니다

    스레드 하나가 많을 때는 초당 3개 이상의 메세지를 브로커로 쏘는 구조입니다.

    대략적으로 택시와 비교하시면 좋을 듯 합니다. 위에서 각 택시마다 목적지를 쏴주면, 그에 따라 이동하는 택시들이 자신의 상황을 계속해서 보내주는 식이죠.(폴링은 아니고 이벤트식)

    그래서 요청마다 스레드를 생성한다기보단, 언제 위에서 목적지를 보낼 지 모르니 항상 스레드가 살아 있어야합니다.

    말씀해주신 "클라이언트 송수신용 워커 => 요청 큐 => 계산처리용 워커 => 결과 큐 => 클라이언트 송수신용 워커" 이 구조에서 계산용 워커는 별개의 프로그램을 말씀하시는건가요? 현재도 모든 메시지들은 큐를 사용해서 처리하고 있습니다.

    0
  • ceastgun
    1k
    2019-02-07 17:55:57 작성 2019-02-07 18:48:28 수정됨

    64bit로 컴파일한거 맞나요?

    https://stackoverflow.com/questions/145312/maximum-number-of-threads-in-a-net-app


    0
  • 나도아빠다
    2k
    2019-02-07 17:59:23

    분산시스템 전용으로 나온 언어라고는 하는데 저도 해본적은 없어서 자세한 설명은 못드릴거같습니다 ㅠㅠ 

    저정도 숫자의 쓰레드를 경험해본적이 없네요....

    0
  • 파란미르
    8
    2019-02-08 03:22:18

    @까슈 계산용 워커는 여기서는 질문한 프로그램 B의 계산 처리 로직이 되겠네요. 요청수만큼 스레드를 만들지 않기 위해서 말씀드린 구조인데, 이미 브로커가 있고 큐를 쓰신다고 하면 신경쓰실 필요는 없겠습니다. 음... 꼭 스레드가 살아있어야 한다고 하면 A의 명령에 대한 결과로 B가 데이터를 전송하는 것 뿐만이 아니라 B에서도 전송하거나 지속적으로 독립된 계산이 이루어져야 한다는 거죠?  말씀하시는 프로그램이 어떻게 쓰이는 건지 잘 모르겠지만, 쓰레드가 각 클라이언트마다 살아있어야 하는 경우는 상상이 잘 안 되네요. 택시의 목적지는 메모리에 있는 건데 쓰레드가 각 목적지마다 살아 있어야 할 필요성은 없어보이구요. 택시의 움직임을 계속 시뮬레이션 하는 거라면, 시뮬레이트 하는 로직을 두고, 거기서 현재 위치를 계속 받아오는 게 맞다고 보이네요.

    계속 계산이 이루어지는 게 아니라 단순히 메세지 대기를 위해서 스레드를 살려두는 경우라면 구조를 바꾸시는 게 좋을 듯 합니다.

    하지만 계속해서 돌아가는 구조라면 무조건 CPU를 써야 할테니까, B 기기를 증설하시는 게 맞겠네요.

    1
  • 까슈1
    12
    2019-02-08 15:02:12 작성 2019-02-08 15:10:33 수정됨

    @ceastgun

    네 맞습니다. 처음에는 저도 이 문제로 고생 했었습니다.


    @파란미르

    답변 감사합니다. 스레드가 살아있어야 하는 이유는, 그 전 정보를 요청받을 경우가 생기기 때문입니다.. 스레드를 죽였다가 다시 생성하게되면 이전의 정보를 메모리에 저장하면 되겠네요.. !! 음.. 일단 시도해보겠습니다.

    0
  • 파란미르
    8
    2019-02-08 20:08:38

    @까슈 화이팅입니다!

    0
  • 로그인을 하시면 답변을 등록할 수 있습니다.