IBM®
메인 컨텐츠로 가기
    Korea [국가변경]    이용약관
 
 
   
        제품    서비스 & 솔루션    고객지원 & 다운로드    회원 서비스    
메인 컨텐츠로 가기

한국 developerWorks  >  리눅스  >

리눅스와 시메트릭 멀티프로세싱(symmetric multiprocessing) (한글)

SMP 시스템과 리눅스 활용하기

developerWorks
문서 옵션

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.

영어원문

영어원문


제안 및 의견
피드백

난이도 : 중급

M. Tim Jones, Consultant Engineer, Emulex

2007 년 5 월 29 일

주요 CPU 벤더들에 의해 입증되었듯이, 멀티 코어 프로세서들이 데스크탑과 임베디드 분야를 주도하고 있습니다. 멀티프로세싱(multiprocessing)은 월등한 성능을 보이지만, 새로운 문제점도 갖고 있습니다. 이 글에서 멀티프로세싱의 개념과, SMP를 활용하는 리눅스®용 애플리케이션 개발에 대해 설명합니다.

리눅스 시스템의 성능을 높일 수 있는 방법은 여러 가지가 있는데, 가장 대중적인 방법은 프로세서의 성능을 높이는 것이다. 확실한 솔루션은 더욱 빠른 클럭 비율의 프로세서를 사용하는 것이지만, 클럭 속도라는 한계에 부딪히게 된다. 이러한 한계에 다다르면, 멀티 프로세서를 적용하게 된다. 안타깝게도, 개별 프로세서들의 성능을 모은다고 해서 성능이 이와 비례해서 늘어나는 것은 아니다.

리눅스에 멀티프로세싱을 적용하는 것을 논하기 전에, 멀티프로세싱의 역사에 대해 살펴보도록 하자.

멀티프로세싱의 역사

Flynn의 멀티 CPU 아키텍처 분류법

Single Instruction, Single Data (SISD)는 전형적인 유니프로세서(uniprocessor) 아키텍처이다. Multiple Instruction, Multiple Data (MIMD) 멀티프로세싱 아키텍처는 독립 데이터에서 개별 프로세서들이 작동한다(컨트롤 병행성). 마지막으로, Single Instruction, Multiple Data (SIMD)는 다른 데이터에 여러 프로세서들이 작동한다(데이터 병행성).

Flynn의 원문 페이퍼는 참고자료 섹션을 참조하라.

멀티프로세싱은 1950년대 중반에 생겨났다. (IBM, Digital Equipment Corporation, Control Data Corporation). 1960년대 초반, Burroughs Corporation은 네 개의 CPU와 최대 16 개의 메모리 모듈이 크로스바 스위치를 통해 연결되어 있는 시메트릭 MIMD 멀티프로세서를 도입했다. (최초의 SMP 아키텍처) 대중적이고 성공적인 CDC 6600은 1964년에 도입되었으며, 한 개의 CPU에 10개의 하위 프로세서(peripheral processing units)가 있었다. 1960년대 후반에, Honeywell은 8개의 CPU를 가진 또 다른 시메트릭 멀티프로세싱 시스템인 Multics 시스템을 선보였다.

멀티프로세싱 시스템들이 개발되는 동안, 프로세서를 줄이고 훨씬 더 높은 클럭 비율로 실행되는 기술로 진보했다. 1980년대에, Cray Research같은 기업들은 멀티프로세서 시스템들과 이것을 활용하는 UNIX® 계열 OS를 도입했다.

1980년대 후반에, IBM PC 같은 유니프로세서 개인용 컴퓨터 시스템이 대중화 되면서, 멀티프로세싱 시스템들은 후퇴를 했다. 하지만, 20년이 지난 지금 멀티프로세싱은 시메트릭 멀티프로시싱을 통해서 개인용 컴퓨터 시스템에 다시 진입했다.

Amdahl의 법칙

컴퓨터 아키텍트이자 IBM 직원이었던 Gene Amdahl은 IBM과 그의 이름을 딴 벤처 기업인 Amdahl Corporation에서 컴퓨터 아키텍처를 개발했다. 그는, 시스템의 한 부분이 향상될 때 전체적인 시스템 향상도를 예상하는 법칙으로 유명해졌다. 이 공식은 멀티 프로세서를 사용할 때 이론상의 최대 성능 향상을 계산하는데 사용되고 있다. (그림 1)


그림 1. Amdahl의 프로세서 병렬성 법칙
Amdahl의 프로세서 병렬성 법칙

그림 1과 같은 방정식을 사용하여 N 개의 프로세서와 병렬화 될 수 없는 시스템의 부분을 지정한 F 요소(본질이 순차적인 시스템의 부분)를 사용하여 시스템의 최대 성능 향상을 계산할 수 있다. 결과는 그림 2에 나타나있다.


그림 2. 최대 10개의 CPU에 대한 Amdahl의 법칙
최대 10개의 CPU에 대한 Amdahl의 법칙

그림 2에서, 맨 위에 있는 라인은 프로세서의 수를 나타낸다. 이상적으로는, 프로세서들을 추가함으로써 얻고 싶은 결과이다. 안타깝게도, 모든 것들이 병렬화 될 수 있는 것은 아니고 프로세서를 관리하는데 오버헤드도 있기 때문에 속도 향상은 크게 없다. 밑에 있는 라인(보라색 라인)은 90%가 순차적인 문제의 경우이다. 최상의 퍼포먼스를 보이는 갈색 라인은 10퍼센트가 순차적이고, 따라서 90퍼센트가 병렬화 가능하다. 이 경우에서도 10개의 프로세서들은 5개 보다 약간 더 나은 성능을 보일 뿐이다.




위로


멀티프로세싱과 PC

SMP 아키텍처에서는 두 개 이상의 동일 프로세서들이 공유 메모리를 통해 서로 연결되어 있다. 각 프로세서는 공유 메모리로 동등한 액세스를 한다. (메모리 공간에 같은 레이턴시를 갖고 있다.) 이는 Non-Uniform Memory Access (NUMA) 아키텍처와 대조된다. 이 아키텍처에서는, 각 프로세서가 고유의 메모리를 갖고 있지만, 다른 액세스 레이턴시로 공유 메모리에 액세스 한다.

약결합 멀티프로세싱

최초의 리눅스 SMP 시스템들은 약결합 멀티프로세서 시스템이었다. 이들은 고속 인터커넥트(10G Ethernet, Fibre Channel, 또는 Infiniband)에 의해 연결된 여러 개의 독립 시스템들에서 구현된다. 이러한 유형의 아키텍처는 클러스터라고도 불린다. (그림 3) Linux Beowulf 프로젝트가 대표적인 솔루션이다. Linux Beowulf 클러스터는 일반 하드웨어와 Ethernet 같은 전형적인 네트워킹 인터커넥트에서 구현될 수 있다.


그림 3. 약결합 멀티프로세싱 아키텍처
약결합 멀티프로세싱 아키텍처

(Beowulf 같은 프로젝트 덕택에) 약결합 멀티프로세서 아키텍처를 구현하는 일은 쉽지만, 여기에도 한계는 있다. 대형 멀티프로세서 네트워크를 구현하는 데에는 상당한 공간과 파워가 필요하다. 이들은 일반 하드웨어에서 구현되기 때문에 의미는 없지만 파워와 공간을 소비하는 하드웨어를 포함하고 있다. 더 큰 문제는 통신망이다. 10G Ethernet 같은 고속 네트워크를 사용하더라도 시스템의 확장성에는 제한이 있다.

강결합 멀티프로세싱

강결합 멀티프로세싱을 chip-level multiprocessing (CMP)이라고 한다. 칩 레벨로 내려가는 약결합 아키텍처에 대해 생각해 보라. 바로 이것이 강결합 멀티프로세싱(멀티-코어 컴퓨팅)의 기본 개념이다. 싱글 통합 회로, 멀티 칩, 공유 메모리, 인터커넥트가 멀티프로세싱을 위한 강결합 코어를 형성한다. (그림 4)

프로세서 인터커넥트
또 다른 인터커넥트 옵션(시스템 패브릭 용 버스)으로는 AMD의 HyperTransport가 있다. Intel®은 Common System Interface라고 하는 새로운 인터커넥트를 구상 중이고, 2008년에 출시될 예정이다.

그림 4. 강결합 멀티프로세싱 아키텍처
강결합 멀티프로세싱 아키텍처

CMP에서, 다중 CPU들은 공유 버스를 통해서 공유 메모리로 연결된다. (level 2 cache) 각 프로세서는 고유의 패스트(fast) 메모리를 갖고 있다. (level 1 cache) CMP의 강결합 본성으로 인해 프로세서와 메모리간 매우 짧은 물리적 거리가 생기기 때문에 메모리 액세스 레이턴시는 최소화 되고 성능은 더 높아진다. 이러한 유형의 아키텍처는 멀티-쓰레디드 애플리케이션에서 잘 작동한다. 이곳에서는 쓰레드들이 프로세서들간 분산되어 병렬로 실행된다. 이를 Thread-Level Parallelism (TLP)이라고 한다.

이러한 멀티프로세서 아키텍처가 대중화 되면서, 많은 벤더들이 CMP 장치들을 선보이고 있다. 표 1은 리눅스 지원이 되는 제품들이다.


표 1. CMP 장치
벤더장치설명
IBMPOWER4SMP, dual CPU
IBMPOWER5SMP, dual CPU, 네 개의 동시 쓰레드
AMDAMD X2SMP, dual CPU
Intel® XeonSMP, dual 또는 quad CPU
IntelCore2 DuoSMP, dual CPU
ARMMPCoreSMP, 최대 4개의 CPU
IBMXenonSMP, 3개의 Power PC CPU
IBMCell ProcessorAsymmetric multiprocessing (ASMP), 9개의 CPU




위로


커널 설정

SMP 실행 하드웨어 기반 리눅스에서 SMP를 활용하려면, 커널도 올바르게 구성되어야 한다. CONFIG_SMP 옵션이 커널 설정 동안 실행되어 커널이 SMP를 인식할 수 있도록 해야 한다. 멀티-CPU 호스트에서 SMP 인식 커널을 실행시키면, proc 파일시스템을 사용하여 프로세서의 수와 유형을 파악할 수 있다.

먼저, grep을 사용하여 /proc의 cpuinfo에서 프로세서의 수를 검색한다. Listing 1에서 보듯, processor라는 단어로 시작하는 라인에 대해 카운트 옵션(-c)을 사용한다. cpuinfo 파일의 콘텐트가 나타난다. 다음은 2-칩 Xeon 마더보드에서 온 예제이다.


Listing 1. proc 파일시스템을 사용하여 CPU 정보 검색하기
                
mtj@camus:~$ grep -c ^processor /proc/cpuinfo
8
mtj@camus:~$ cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 15
model           : 6
model name      : Intel(R) Xeon(TM) CPU 3.73GHz
stepping        : 4
cpu MHz         : 3724.219
cache size      : 2048 KB
physical id     : 0
siblings        : 4
core id         : 0
cpu cores       : 2
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 6
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr 
pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm 
pbe nx lm pni monitor ds_cpl est cid xtpr

bogomips        : 7389.18

...

processor       : 7
vendor_id       : GenuineIntel
cpu family      : 15
model           : 6
model name      : Intel(R) Xeon(TM) CPU 3.73GHz
stepping        : 4
cpu MHz         : 3724.219
cache size      : 2048 KB
physical id     : 1
siblings        : 4
core id         : 3
cpu cores       : 2
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 6
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr 
pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm 
pbe nx lm pni monitor ds_cpl est cid xtpr

bogomips        : 7438.33 

mtj@camus:~$




위로


SMP와 리눅스 커널

초기 Linux 2.0 시절에, SMP 지원은 시스템에 대한 액세스를 직렬화 했던 "big lock"으로 구성되었다. SMP 지원도 서서히 도입되었지만 SMP의 힘이 완전히 드러났던 2.6 커널이 탄생하기 전까지는 그렇지 못했다.

2.6 커널은 SMP 시스템을 위한 더 나은 지원이 포함된 새로운 O(1) 스케줄러를 도입했다. 포인트는 캐시 효율성을 위해 어느 정도의 유사성을 관리하면서 가용 CPU들간 작업의 로드 밸런스를 맞추는 기능이다. 캐시 효율성의 경우, 그림 4를 다시 기억해 보면, 태스크가 하나의 CPU와 연결될 때, 이것을 다른 CPU로 옮길 경우 그 태스크를 위해 캐시가 플러시(flush) 되어야 한다. 이는 데이터가 새로운 CPU의 캐시에 있기 전까지는 태스크의 메모리 액세스의 레이턴시는 증가한다.

커널의 SMP
아키텍처에서 SMP가 초기화되는 방법을 이해하려면, ./linux/arch/<arch>/kernel/에 있는 커널 내에서 smp.c 또는 smpboot.c 파일을 확인하라.

2.6 커널은 각 프로세서를 위해 한 쌍의 runqueue를 관리한다. (종료된 runqueue와 활성 runqueue) 각 runqueue는 140개의 우선 순위(priority)를 지원하고, 이 중 상위 100개는 실시간 태스크에, 하위 40개는 사용자 태스크용이다. 태스크에는 실행을 위한 타임 슬라이스가 주어지며, 이들이 할당된 타임 슬라이스를 사용하면, 활성 runqueue에서 종료 runqueue로 이동된다. 이로써, CPU에 모든 태스크들이 공평하게 액세스 하게 된다. (CPU 기반에만 잠금)

CPU 당 태스크 큐의 경우, 작업은 시스템의 모든 CPU의 로드에 맞춰 균형이 맞춰진다. 200밀리초 마다, 스케줄러는 로드 밸런싱을 수행하여 프로세서간 밸런스를 관리한다. 리눅스 2.6 스케줄러에 대한 자세한 내용은 참고자료를 참조하라.




위로


사용자 공간 쓰레드: SMP 활용하기

SMP를 활용하기 위해 많은 작업들이 리눅스 커널에 이루어졌지만, OS 자체로는 충분하지 않다. SMP의 힘은 TLP에 있다. 단일의 통합(non-threaded) 프로그램들은 SMP를 활용할 수 없고, SMP는 코어들 간 분산될 수 있는 많은 쓰레드들로 구성된 프로그램에서 활용될 수 있다. 하나의 쓰레드가 I/O의 완료를 기다리느라 지연되는 동안, 다른 쓰레드는 유용한 작업을 수행할 수 있다. 이러한 방식으로, 쓰레드는 서로 작동하여 서로의 레이턴시를 숨겨준다.

쓰레디드(threaded) 애플리케이션들을 구현하는 좋은 방법이다. POSIX 쓰레드는 쓰레딩 메커니즘과 공유 메모리를 제공한다. 일정량의 쓰레드를 만드는 프로그램이 호출될 때, 각 쓰레드에는 고유의 스택(로컬 변수와 상태)이 주어지지만, 부모의 데이터 공간을 공유한다. 생성된 모든 쓰레드들은 이와 같은 데이터 공간을 공유하지만, 여기에 문제가 있다.

공유 메모리에 멀티-쓰레디드 액세스를 지원하려면, 조정 장치가 필요하다. POSIX는 mutex 함수를 제공하여 단일 쓰레드에 의한 객체(메모리 조각)으로의 배타적인 액세스를 실행하는 중요한 섹션(critical sections)을 만든다. 이렇게 하지 않으면 다중 쓰레드에 의해 동기화 되지 않은 조작으로 인해 메모리가 오염된다. Listing 2는 POSIX mutex로 중요한 섹션을 만드는 방법이다.


Listing 2. pthread_mutex_lock과 unlock을 사용하여 중요한 섹션 만들기
                
pthread_mutex_t crit_section_mutex = PTHREAD_MUTEX_INITIALIZER;

...

pthread_mutex_lock( &crit_section_mutex );

/* Inside the critical section. Memory access is safe here
 * for the memory protected by the crit_section_mutex.
 */

pthread_mutex_unlock( &crit_section_mutex );

다중 쓰레드가 초기 호출 후에 세마포어 잠금을 시도한다면, pthread_mutex_unlock 호출이 수행될 때까지 차단되고 요청들은 대기열에 놓이게 된다.




위로


SMP용 커널 변수 보호

한 프로세서의 멀티 코어들이 커널을 위해 동시에 실행될 때, 특정 코어에 해당하는 데이터를 공유하지 않는 것이 좋다. 이러한 이유로, 2.6 커널은 하나의 CPU와 연결된 per-CPU 변수 개념을 도입했다. 가장 일반적으로 액세스 되는 CPU에 대한 변수 선언을 허용하여, 잠금 요구 사항을 최소화 하고 성능을 높인다.

per-CPU 변수 정의는 DEFINE_PER_CPU 매크로를 사용하는데, 여기에 유형과 변수 이름을 제공해야 한다. 매크로는 l-value처럼 작동하기 때문에 이것 역시 초기화 해야 한다. 다음 예제(./arch/i386/kernel/smpboot.c 에서 발췌)는 변수를 정의하여 시스템의 각 CPU에 대한 상태를 나타낸다.

/* State of each CPU. */
DEFINE_PER_CPU(int, cpu_state) = { 0 };

이 매크로는 CPU 인스턴스 당 하나씩 변수 어레이를 만든다. per-CPU 변수에 액세스 하려면 per_cpu 매크로가 smp_processor_id와 함께 사용된다. 이 함수는 실행 대상 코드에 대한 현재 CPU 식별자를 리턴한다.

per_cpu( cpu_state, smp_processor_id() ) = CPU_ONLINE;

이 커널은 per-CPU 잠금에 대한 다른 함수들과 변수에 대한 동적 할당을 제공한다. ./include/linux/percpu.h에서 이러한 함수들을 찾을 수 있다.




위로


요약

소셜 북마크

mar.gar.in mar.gar.in
digg Digg
del.icio.us del.icio.us
Slashdot Slashdot

프로세서 주파수가 한계에 다다를 때, 성능을 높일 수 있는 가장 일반적인 방법은 더 많은 프로세서를 추가하는 것이다. 초기에는 더 많은 프로세서들을 마더보드에 추가하거나 여러 개의 독립 컴퓨터들을 클러스터링 하는 것을 의미했다. 오늘날, 칩 레벨(chip-level) 멀티프로세싱은 하나의 칩에 더 많은 CPU들을 제공하여 더 나은 성능을 보장하고 메모리 레이턴시는 줄여준다.

가상화의 도입으로 인해, SMP 시스템들은 서버뿐만 아니라, 데스크탑에서도 찾을 수 있다. 대부분의 첨단 기술과 마찬가지로, 리눅스도 SMP를 지원한다. 커널은 (쓰레드에서 가상 OS까지) 가용 CPU들 간 로드를 최적화하는 역할을 수행한다. 이제 남은 일은 애플리케이션이 충분히 멀티쓰레디드 되어 SMP의 힘을 활용하는 것이다.



참고자료

교육

제품 및 기술 얻기
  • 리눅스 SEK 주문하기: 리눅스용 DB2®, Lotus®, Rational®, Tivoli®, WebSphere® 최신 IBM 시험판 SW가 두장의 DVD에 담겨있다.

  • IBM 시험판 SW를 한국 developerWorks에서 다운로드하여 다음 리눅스 개발 프로젝트를 개선해보라.


토론


필자소개

M. Tim Jones

M. Tim Jones는 임베디드 소프트웨어 아키텍트이자 GNU/Linux Application Programming, AI Application Programming, BSD Sockets Programming from a Multilanguage Perspective 등을 저술한 작가이다. 정지 우주선용 커널 개발부터 임베디드 시스템 아키텍처와 네트워킹 프로토콜 개발에 이르기까지 다양한 엔지니어링 경력이 있다. Longmont, 콜로라도주에 위치한 Emulex Corp.의 컨설턴트 엔지니어이다.




기사에 대한 평가


보다 나은 서비스를 제공하기 위함이오니 잠시 짬을 내어 이 양식을 제출하여 주십시오.



아니오잘 모르겠음
 


 


12345
 



위로


DB2, Lotus, Rational, Tivoli, and WebSphere are trademarks of IBM Corporation in the United States, other countries, or both. Intel is a registered trademarks of Intel Corporation or its subsidiaries in the United States and other countries. Linux is a trademark of Linus Torvalds in the United States, other countries, or both. UNIX is a registered trademark of The Open Group in the United States and other countries. 기타 회사, 제품, 및 서비스명은 다른 상표나 서비스 마크일 수 있습니다.

developerWorks 콘텐트를 다른 사이트에 전재하기:
developerWorks 콘텐트에 대한 저작권은 IBM에 있습니다. IBM의 서면 허가나 원본 저자의 허락이 없이는 전재를 금합니다. 저희 콘텐트를 전재하시려면 IBM developerWorks 담당자 에게 문의하십시오.
    IBM 소개 개인정보 보호정책 문의