멀티프로그래밍 위키로 바로가기 → http://www.devnote.net/wiki
언젠가 어느 게임 커뮤티에서 하나의 프로그램이 만들 수 있는 최대 스레드 개수에 관해 논의 한 적이 있다. 잊어 버리기 전에 이에 관해 간단히 정리해 보겠다.

우선, 윈도우즈는 최대 스레드 개수에 대해 제한 사항을 두지 않는다는 것이다.  단지, 스레드 개수를 제한하는 가장 큰 요인은 다름 아닌 메모리이다. 각 스레드는 기본으로 1MB의 스택 메모리를 예약해 놓는다. 따라서 2000개의 스레드가 생성되면, 벌써 2GB의 메모리 주소 공간이 사용된다.  32비트 윈도우즈에서는 하나의 프로세스는 기본적으로 2GB의 사용자 메모리 주소를  가지므로 최대 2000개 스레드가 결국 한계이다.

여기서 한가지 주의하여야할 것은 가상 메모리와 실제 물리메모리를 구분해야 한다는 것이다.  위에서 2GB메모리 주소라고 한 것은 가상메모리 주소 공간이다. 스레드가 생성될 때 1MB중의 일부(약 4KB)만을 실제 물리메모리에서 가져와 사용(commit)하고, 나머지는 메모리 주소를 예약(reserve)해놓는 것이다. 그러니까, 가상메모리 공간 부족은 어쩔 수 없는 한계이다. 하지만, 물리메모리가 1GB라고 해도 가상메모리 공간이 줄어드는 것은 아니고 여전히 2GB이다. 즉, 1GB메모리를 가진 시스템에서도 최대 스레드 개수는 2000가 된다. 마찬가지로 물리 메모리가 4GB 있어도 하나의 어플리케이션은 가상 메모리 2GB의 제한이 걸린다. (Windows XP, Vista와 Windows Server 2003 Standard의 경우 4GB, Enterprise의 경우 32GB 의 최대 물리메모리를 가짐. 자세한 내용은 마이크로소프트사의 이 웹페이지를 참고 바람.)

* 실제 물리 메모리보다 큰 가상메모리를 사용하게 되면 OS는 당장 사용하지 않는 메모리 데이터의 일부분을 하드디스크의 페이지 파일로 옮겨(swap) 메모리를 사용 가능하게 만들어 줍니다. 이러한 경우 하드디스크 액세스로 인해 전체시스템 성능저하가 나타납니다.

하나의 어플리케이션이 최대 2000개의 스레드를 가지므로, 같은 어플리케이션 여러 개를 실행하면 2000개 이상의 스레드를 만드는 효과를 낼 수도 있다.

각, 스레드의 스택의 맨 위 페이지 (스택은 큰 메모리 주소에서 작은 주소로 자라난다)는 memory guard page로 설정되어, 만약 스택사용이 많아지게 되면 예외(exception)가 발생한다. 이 때 예약해 놓은 메모리 공간에 새 물리 메모리를 할당(commit)하여 스택의 크기는 최대 처음 확보해 놓은 가상 메모리(이것은 CreateThread API에서 파라미터로 변경할 수 있다)만큼 커질 수 있다. 이 이상 스택메모리를 사용하려고 하면 스택 오버플로우 예외가 발생한다.

여기서 중요한 점은 이처럼 한 번 할당된 스택메모리는 다시 줄어들지 않는다는 것이다. 스택을 많이 사용하는 것은 주로 재귀적(recursive) 함수 호출이나, 큰 지역변수(local variable)의 사용이다. _alloca를 쓰는 것도 마찬가지로 스택을 사용한다. 단 하나의 함수만이라도 큰 지역변수를 가지고 있다면, 그 함수가 호출된 이후 스택에 할당된 물리메모리는 계속 유지되게 된다.

할당할 수 있는 물리 메모리가 더 이상 없다면 Out Of Memory 에러가 발생하므로 예외처리를 제대로 하지 않으면 프로그램이 크래시될 수 있다. 물리적 메모리가 2GB이하인 경우, 스레드를 많이 만들면 이러한 Out Of Memory상황이 생길 가능성이 커진다.

스레드를 많이 만드는 것은 그리 권장할 만한 사항은 아니지만, 할 수 없이 많이 만들어야 한다면, 이러한 스택메모리에 의한 한계를 염두해 두어야할 것이다. 4GT라는 것을 사용하면 하나의 프로세스의 가상 메모리 주소를 3GB까지 늘릴 수 있다. 그렇다면 3000개의 스레드 생성도 가능해진다. 또, 모든 함수들이 스택을 많이 사용하지 않는다면 CreateThread API의 파라미터에 1MB보다 작은 스택메모리를 예약하도록 하면 10000개 이상의 스레드도 만들 수 있다. 만약 64비트 OS를 사용하면 더 이상 이러한 제약은 물론 없어질 것이다.

다음에 시간이 되면 스택오버플로우(stack overflow)가 발생하는 경우 어떻게 예외처리를 하는 지에 관해 써보도록 하겠다. 이것은 간단해 보이지만 스택오버플로우 상황에서는 더 이상의 스택을 사용하는 것이 허용되지 않고, 스택 보호페이지(guard page)가 사라져 프로그램이 아무런 에러 로그나 리포트를 하지 못하고 종료될 수 있다. 다시 말하면, 재귀적 함수호출이 무한히 반복되는 버그가 있는 경우 예외처리에 걸리지 않고 예기치 않게 프로세스가 종료되어 버리는 문제가 나타난다.
크리에이티브 커먼즈 라이센스
Creative Commons License

Trackback Address :: http://devnote.net/trackback/42

  1. Tracked from ayukawa's me2DAY 2008/10/24 02:55 삭제

    Subject: 마사키군의 생각

    아까 그 글보다는 이 글이 더 설명이 잘 되어 있는듯
  1. ohyecloudy 2009/07/08 18:42 댓글주소 | 수정 | 삭제 | 댓글

    좋은 글 잘 봤습니다.

    스레드를 한계치까지 만들어 보지 않아서 생성 가능한 개수를 계산해보지 않았는데, 글을 보고 단번에 알게됐습니다. ;-)


◀ PREV : [1] : ... [55] : [56] : [57] : [58] : [59] : [60] : [61] : [62] : [63] : ... [93] : NEXT ▶