리눅스에서 멀티쓰레드 프로그램이 여러 CPU를 동시에 사용하나요?
글쓴이: superkkt / 작성시간: 목, 2007/03/22 - 9:38오전
리눅스에서 멀티쓰레드 프로그램을 개발하고 있습니다. CPU가 여러개 있는 시스템에서 멀티쓰레드 프로그램을 돌리면 각 쓰레드가 서로 다른 CPU에서 동시에 실행될 수 있다고 들었습니다. 그래서 프로그램을 실행시키고 top 명령어에서 마지막으로 사용된 CPU를 보여주는 옵션을 켜서 확인하고 있는데, 계속 같은 CPU에서만 돌아가는걸로 나오네요.
혹시 top 말고 쓰레드의 현재 상태(어떤 CPU를 사용하는지 등)를 자세하게 볼 수 있는 명령어가 있나요? 듀얼코어, 쿼드코어 등 여러 시스템에서도 돌려봐도 계속 하나만 사용하는걸로 나오는군요..
Forums:
쓰레드에도 종류가 있습니다.
쓰레드는 대표적으로 커널레벨 쓰레드와 유저레벨 쓰레드가 있습니다.
솔라리스의 경우에는 커널레벨 쓰레드는 lwp 라고 부르는데요. Light Weight Process 의 약자입니다.
커널레벨 쓰레드는 스케줄링을 커널에서 하는 것으로서 이 경우는
여러 프로세서에서 병렬로 동시에 작동합니다.
유저레벨 쓰레드는 유저레벨에서 스케줄링을 하므로 동시에 여러 프로세서를 사용하지 않습니다.
대신 커널레벨과 다른 장점을 갖고 있습니다.
superkkt님께서는 아마 유저레벨 쓰레드를 생성했을 것으로 짐작이 됩니다.
커널레벨인지
커널레벨인지 유저레벨인지 프로그램이 선택 할 수 있는건가요?
개발 & 운영 환경은 아래와 같습니다.
CentOS 4.4
gcc 3.4.6
======================
BLOG : http://superkkt.com
======================
BLOG : http://superkkt.com
일반적으로는,
일반적으로는, 사용하는 thread 라이브러리에 따라 의존적인데요.
pthread는 커널 thread 로 알고 있는데 정확히 잘 모르겠네요.
유저레벨은 http://www.gnu.org/software/pth 과 같은 라이브러리가 있습니다.
장단점이 있으니 프로젝트의 성격에 맞는걸 고르면 좋을 듯 합니다.
ACE library의 thread 라이브러리는 옵션에 lwp (커널 thread) 여부를 설정하도록 되어 있습니다.
예전 버젼인
예전 버젼인 LinuxThreads와 새로운 버젼인 NPTL 모두 커널에서 관리하므로 커널 레벨이라고 할 수 있겠네요.
POSIX 메뉴얼과
POSIX 메뉴얼과 인터넷에 찾은 레퍼런스를 보면 pthread_attr_setscope() / pthread_attr_getscope() 함수를 사용해서 쓰레드의 경쟁범위를 설정할 수 있다고 되었있습니다.
그리고 PTHREAD_SCOPE_SYSTEM 설정을 가지는 쓰레드는 시스템 경쟁범위를 가져서 각각의 쓰레드가 1:1로 kernel entity와 연결된다고 되어 있고요. 반대로 PTHREAD_SCOPE_PROCESS 설정을 가지는 쓰레드는 프로세스 경쟁범위를 가져서 여러개의 쓰레드가 하나의 kernel entity를 공유 한다고 되어있습니다.
그럼 이 옵션을 사용해서 커널레벨인지 유저레벨인지 설정 할 수 있는건가요? 그리고 리눅스 맨페이지에는 LinuxThread 라이브러리를 사용하는 시스템은 PTHREAD_SCOPE_PROCESS를 지원하지 않는다고 되어있네요.
그런데 이 옵션을 사용해서 커널레벨/유저레벨을 선택하는게 맞다면 솔라리스는 이 옵션의 기본값이 PTHREAD_SCOPE_PROCESS라고 되어있는데, 그렇다면 솔라리스는 기본적으로 유저레벨 쓰레드를 사용하는 것인가요? 이 부분이 좀 이해가 안되네요.
======================
BLOG : http://superkkt.com
======================
BLOG : http://superkkt.com
네 맞습니다.
네 맞습니다. PTHREAD_SCOPE_PROCESS 는 (커널이 아닌) 프로세스가 스케줄링을 하는 것으로 유저레벨을 의미합니다.
커널레벨 쓰레드와 유저레벨 쓰레드를 모두 지원하는 경우는 M:N 으로 조합해서 사용할 수 있습니다.
유저레벨의 경우는 자발적인 cpu 반환이 없습니다. 다시 말해 non-preemptive 인데요. I/O 등으로 인해 block 될 때 cpu 실행 흐름을 놓게 되기 때문에 context 스위칭이 발생이 최소화 되므로 preemptive 방식에 비해 효율적입니다. (througput 입장에서 효율적인다는 의미입니다.)
그래서 이론적으로 가장 이상적인 조합은 커널레벨 쓰레드는 cpu 코어와 같은 수만큼만 생성하고 나머지는 유저레벨 쓰레드로 생성하는 거지요.
유저레벨
유저레벨 스케쥴링에서 높은 순위의 쓰레드가 오면 preemption 되는 것이 아닙니까??
그리고 유저레벨의 경우 컨텍스트 스위칭 비용이 적기 때문에 많은 쓰세드 생성에 유리하고 IO/CPU 위주의 프로세스일
경우 커널레벨이 유리하다고 보통 말하는 걸로 알고 있는데요??
커널쓰레드와
커널쓰레드와 유저쓰레드는 같은 위상에 있는 것이 아닙니다.
커널은 커널 쓰레드만을 관리하고 커널 쓰레드가 유저쓰레드를 관리하고 유저쓰레드가 실제 프로그램을 실행한다고 보시면 됩니다.
그래서 프로세스가 구동되면 일단 무조건 메인 쓰레드 하나가 생성되는되는데요. 그것은 커널 쓰레드입니다.
그러므로 유저쓰레드만을 여러개 생성했다면, 커널쓰레드 하나에 복수개의 유저쓰레드가 생기게 되는 걸로 보시면 됩니다.
커널은 커널쓰레드만을 스케줄링하므로 유저쓰레드가 아무리 많아도 이 유저쓰레드 모두는 cpu 한개에서만 작동하게 됩니다.
유저쓰레드가 non-preemption 이기 때문에 비자발적으로 cpu는 놓는 경우가 없지만, 그 유저쓰레드를 구동하고 있는
커널쓰레드가 preemption이기 때문에 커널쓰레드가 sleep 되면 그 하부의 유저쓰레드도 같이 sleep가 됩니다.
즉, 유저쓰레드 그 자체는 non-preemption 이지만 (같은 유저레벨 쓰레드끼리라고 보시면 좋겠네요) 큰 관점에서는 preemption이
된다고 보시면 됩니다.
커널은 커널레벨 쓰래드만을 제공해주고, 그 하부단에서(유저레벨에서) 내가 직접
(물리적으로는 병렬이 아니지만 논리적으로 병렬인) 쓰래드를 구현했다고 보시면 됩니다.
위와 같은 위상으로 보시면 됩니다.
인용: 커널쓰레드와
위상이란 단어가 생소하지만, 같은 위상이 아닌 것만을 틀림없지요.
지금 얘기하시는 것은 현재 리눅스에서 쓰는 1:1 모델을 말하는 것은 아닌 것 같네요.
그렇게 구현할 수 있겠지만 그래서는 안 되겠죠.
스케쥴링을 어디서 관리하는냐가 애초에 문제였습니다. 유저 레벨의 라이브러리에서 하느냐 아니면 커널 레벨에서 하는냐에
따라 장단점이 나눠지고 리눅스의 경우 커널 레벨에서 하는 것이 구현에 잘 맞는 것 같아서 그렇게 한 것입니다.
preemption은 사실 이 질문의 문맥과 좀 떨어진 얘기입니다. 그렇지만 preemption이 유저/커널 쓰레드 여부에 따라 구분
된다는 말은 처음 듣네요.
M:N 을 얘기하려고 하신 것 같네요. 그렇지만 직접할 필요는 없고요, 더구나 잘못된 모델을 구현해서는 안됩니다.
POSIX에는 모두
POSIX에는 모두 설정하는 것을 허용하고 있지만 LinuxThread나 NPTL에서는 PTHREAD_SCOPE_SYSTEM만
사용할 수 있습니다. 반환값이 0인지 검사해서 확인할 수 있고요, 유저/커널 레벨 스케쥴링인지 확인하는 용도를 써도 될 것 같네요(적어도 제가 이해한 바로는).
유저레벨에서도...
nptl 같은 경우 다음과 같은 함수가 있습니다.
pthread_attr_setaffinity_np
pthread_attr_getaffinity_np
그건
아마 일정 리소스 이상 차지해야 다른 CPU도 사용할 것입니다(irqbalance라는 userspace 프로그램에 의해).
/proc/interrupts 에서 사용하는 것을 확인할 수 있습니다.
그런데 top에서는 각
그런데 top에서는 각 쓰레드별로 출력을 하는 기능은 없나요? 쓰레드가 6개 이상 생겼는데 top에서는 프로세스 하나만 보이네요. 그리고 그 프로세스는 계속 같은 CPU만 사용하는걸로 출력되고요. 각 쓰레드가 어떤 CPU 상에서 실행중인지를 보고 싶은데 아무리 뒤져봐도 방법을 모르겠네요. :-(
======================
BLOG : http://superkkt.com
======================
BLOG : http://superkkt.com
저도 몰라서
저도 몰라서 찾아봤더니 스레드별 상태보기는 'H'(shift-h)키로 토글이네요.
----
jai guru deva om...
----
jai guru deva om...
혹시 top 버전이
혹시 top 버전이 어떻게 되시나요? 저는 CentOS에 기본으로 깔린 top을 사용하는데 H(shift-h)를 아무리 눌러봐도 안되는군요.
======================
BLOG : http://superkkt.com
======================
BLOG : http://superkkt.com
ubuntu edgy에, top 3.2.7
ubuntu edgy에, top 3.2.7 입니다.
----
jai guru deva om...
----
jai guru deva om...
음.. 저도 방금 3.2.7
음.. 저도 방금 3.2.7 깔아서 해봤는데.. 역시나.. top 기본화면에서 shift + h 키 누르면 unknown command라고만 나오는데 혹시 제가 사용법을 잘모르고 있는건가요?
======================
BLOG : http://superkkt.com
======================
BLOG : http://superkkt.com
혹시나 해서 레뎃9,
혹시나 해서 레뎃9, top(procps)버전 2.0.11 에서 해봤습니다만...
잘되는데요.. -_ ㅡ;
----
jai guru deva om...
----
jai guru deva om...
GNU 사이트 말고
GNU 사이트 말고 소스포지에 있는 procps 소스코드를 다운 받아서 설치하는 잘 되는군요. 얼핏보기는 두개가 똑같은 코드 같은데 뭐가 문제였는지는 잘 모르겠네요. 아무튼 shift + h와 f 누르고 j 눌러서 마지막 사용한 CPU 내역을 보여주도록 하니까 각 쓰레드가 서로 다른 CPU에서 잘 돌고있는게 확인 되었습니다.
======================
BLOG : http://superkkt.com
======================
BLOG : http://superkkt.com
저도
저도 질문입니다만,
/proc/interrupts 에서 아래처럼 CPU0에 인터럽트가 몰리는 현상은
어떻게 이해해야 하는건가요?
----
jai guru deva om...
----
jai guru deva om...
좀 더 일을 많이
좀 더 일을 많이 시키면 다른 시피유도 쓸꺼예요.
리눅스 커널의
리눅스 커널의 버그로 알고 있습니다. 아직까지 안고쳐졌죠.
그래서 현재는 irqbalance라는 외부 대몬으로 해결을 하고 있고요.
Written By the Black Knight of Destruction
Written By the Black Knight of Destruction
그렇지 않습니다.
성능과 전원 절약을 고려해서 그렇게 디자인 된 것입니다.
다음 주소를 참고하세요.
http://www.irqbalance.org/documentation.php
댓글 달기