본문 바로가기

CS/컴퓨터구조

[컴퓨터구조] Parallel Processing(2)

현재 글은 이 글에서 이어지며, 컴퓨터 구조와 아키텍처 서적 및 대학에서 들은 강의를 기반으로 한다.


T = Ic * CPI * 1/f

MIPS  rate
= Ic / T = f/CPI(instruction당 사이클 수)
= f * IPC(사이클 당 instruction 수)

f : 프로세서 클럭 속도
IPC: 클럭 당 평균 intruction 개수

 컴퓨터의 성능을 비교할 때는 벤치마킹을 이용하는 것이 일반적이지만, MIPS 역시 성능을 나타내는 척도로 사용될 수 있다. MIPS는 초당 실행되는 instruction의 개수를 의미하며, 해당 수치가 높을 수록 컴퓨터의 성능이 높다는 의미가 된다.

  위 수식에 따르면 MIPS 성능을 높이기 위해서는 프로세서의 클럭 속도 또는 클럭당 실행하는 instruction의 개수를 늘려야 한다. 그러나 프로세서의 클럭 속도의 경우 전력 소모 증가 등 존재하는 문제점에 의해 2007년 이후부터 성장이 어렵다. 따라서 현대 컴퓨터가 성능을 높이기 위해서는 IPC, 즉 한 사이클 당 실행되는 instruction의 개수를 늘려야 한다. 이런 부분에서 멀티 스레딩 및 멀티 코어 시스템이 필요하게 된다. 

 멀티 스레딩은 프로그램의 instruction stream을 더 작은 stream으로 나누어 스레드라는 실행 단위로 할당, 이를 병렬적으로 처리하는 방식을 의미한다. 각 스레드가 서로 다른 실행 범위를 가지거나 독립적으로 실행될 수 있는 작업에 할당되면 낮은 dependency를 기반으로 효율적인 병렬 처리가 가능할 수 있다.


process & thread

 컴퓨터 내에는 프로세스와 스레드라는 실행 단위가 존재한다. 이 둘에 대해 잠시 알아보자.

프로세스

 프로그램이 메모리 상에 적재되어 실행되고 있는 인스턴스로, 각 프로세스는 스택, 힙, 코드 등 프로그램이 실제로 동작하기 위해 필요한 데이터들을 개별적으로 유지한다. 스케줄링과 실행 및 자원 소유권 등을 고려하게 된다.

 프로세서 내에서 프로세스를 스위칭할 때는 현재 프로세스가 관리하는 정보들에 대해 저장하는 과정이 필요하다. 또한 프로세스를 스위칭하는 것은 완전히 다른 실행 단위로 바꾸는 것이므로 캐시에 없는 데이터를 요청할 확률이 높아지므로 전반적으로 오버헤드가 크다.

스레드

 프로세스 내에서의 기본적인 실행 단위로, 동일 프로세스에 대한 스레드들은 자신이 속한 프로세스가 유지하는 데이터를 공유하여 사용하되, 개별 스레드가 동작하는데 필요한 레지스터 정보(PC, 스택 포인터 등) 같은 데이터만을 개별적으로 유지한다. 프로세스의 하위 단위이므로 스케줄링 및 실행 정도만 고려하면 된다.

 스레드는 프로세스의 스택, 힙, 코드 등의 데이터를 동일 프로세스의 다른 스레드들과 공유하므로 스위칭이 일어나더라도 큰 부담이 없다. 대부분의 데이터가 공유되는 덕분에 레지스터 등 일부 정보만을 교체하여 실행할 수 있어 프로세스의 스위칭보다 오버헤드가 적고 속도가 빠른 장점이 있다.


Implicit & Explicit Multithreading

 멀티 스레딩은 두가지 방식으로 수행될 수 있다.

Explicit Multithreading

 프로그래머가 코드를 구현하는 시점에 병렬 처리가 필요한 부분에 명시적인 명령을 사용하는 방식이다. 현재 사용하는 대다수의 상용 프로세서나 실험적 머신들은 여기에 속한다. 대다수의 프로그래밍 언어는 언어 차원에서 스레딩을 생성하고 관리하는 라이브러리를 가지는 경우가 많은데, 이를 이용하여 명시적으로 스레드를 만들거나 동작할 수 있다.

  • Interleaved
    • 매 클럭 사이클마다 실행되고 있는 스레드를 스위칭하여 실행하는 방식.
    • 스레드가 캐시 이슈, I/O 등에 의해 blocked 상태에 있다면 스킵한다.
    • parallel 보다는 concurrent에 가까운 병렬 처리 방식으로 보임.
  • Blocked
    • 현재 실행되고 있는 스레드가 I/O 등에 의해 멈춘 경우에만 스레드를 스위칭하여 실행하는 방식.
    • pipeline stall을 줄이는데 도움이 되며, in-order 방식으로 동작하는 프로세서에게 효과적이다.
  • Simultaneous(SMT)
    • 프로세서 내에 충분한 하드웨어 장치가 존재하여 여러 스레드를 동시에 실행하는 방식.
    • 슈퍼스칼라 구조를 전제로 한다.
  • Chip Multiprocessing( Multi-core )
    • 하나의 칩 내에 여러개의 프로세서(코어)가 여러개 존재하여 각 프로세서가 병렬적으로 동작하는 방식.
    • 현대 사용되는 컴퓨터의 프로세서 구조가 기본적으로 여기에 속한다.

여러가지 Explicit multiprocessing 방법들이 동작을 나타낸 그림들

Implicit Multithreading

 프로그래머가 스레드를 고려하지 않고 일반적인 순차 실행 프로그램을 구현하면, 컴파일러의 정적 분석 단계 또는 하드웨어의 동적 실행 단계에서 자동으로 스레드를 생성하여 프로세스를 실행하는 방식이다.

 사용자 입장에서는 편리할 수 있으나, 컴파일러 또는 하드웨어가 시스템을 적절히 분석하여 병렬적으로 처리할 구역을 판단하는 것 자체가 어렵기 때문에 완전히 암시적으로 멀티스레딩을 수행하는 경우는 거의 없다. 대신 openMP와 같은 라이브러리처럼 스레드의 개수, 병렬 처리할 영역 등 최소한의 정보를 제공하여 컴파일러가 암시적으로 스레드를 할당하도록 구현하는 하이브리드 방식으로 사용되고 있는 편이다.


Memory Consistent Model

  기본적으로 프로그래머가 작성한 프로그램은 컴파일러에 의해 ILP 효율을 높이기 위해 instruction 수준에서 순서가 변동될 수 있다. 따라서 해당 프로세서가 채택하고 있는 방식에 따라 프로그램이 작성된 순서와 실제로 실행되는 순서는 크게 달라질 수 있다. 메모리 일관성 모델에서는 병렬 스레드가 공유 메모리를 관찰하는 방법을 정의한다. 시스템이 어떤 일관성 모델을 따르는가에 따라 실행 순서 및 결과가 달라질 수 있다.

Sequential Consistent

 메모리 일관성 모델 중 하나로, 실행 결과가 모든 프로세서의 작업이 순차적으로 실행된 경우와 같으며 각 개별 프로세서의 작업이 프로그램에 의해 지정된 순서대로 수행되는 경우를 뜻한다고 한다. 즉, 각 프로세서는 자신이 할당 받은 작업에 대해 instruction 순서를 뒤바꾸지 않고 그대로 실행한다. 이에 대한 예시는 위 링크 중 두번째를 보면 이해가 된다.

스레드 예시

 멀티 프로세서 환경에서 두개의 프로세서에 각각 스레드 1과 스레드 2가 할당되었다고 생각해보자. 해당 시스템이 Sequential Consistent을 메모리 일관성 모델로 채택하는 경우, (1) 과 (2), (3) 과 (4)는 반드시 순차적으로 실행된다. 전체적으로 (1) -> (3) -> (2) -> (4)는 가능하지만, (2) -> (3) -> (4) -> (1) 처럼 스레드 내의 instruction 실행 순서는 바뀔 수 없다. 따라서 A ==0 & B == 0 조건에 의해 "AB" 또는 "BA"는 절대 출력될 수 없다.

 이 모델은 순서를 교체할 수 없는 strong model에 속한다. strong model의 경우 연산의 실행 순서가 보장되므로 소프트웨어에 대한 제약이 적고 예상하지 못한 결과가 발생하는 것을 막을 수 있으나, write buffer, out-of-order memory access, pipeline 등 성능 향상을 위한 최적화 기법을 적용하지 못하는 경우가 발생할 수 있다.

 반면 weak model의 경우 다양한 최적화 기법을 적용할 수 있으므로 효과적인 구현이 가능하나, 순서가 보장되야 하는 instruction 들에 대해 프로그래머가 명시적으로 설정해야 하는 어려움이 있다.


Cluster

 자체적으로 PC의 역할을 수행할 수 있는 다수의 컴퓨터들을 연결하여 마치 하나의 시스템인 것처럼 운용하는 방식.

SSI(Single System Image)에 기반하여 동작하며, 전체 노드는 clustering middleware이라는 특별한 노드에서 집중적으로(centralized) 관리(orchestrate)하므로 사용자는 클러스터 내부의 노드들을 일일이 알 필요 없이 하나의 시스템 관점에서 접근할 수 있다. 

 클러스터의 각 노드는 병렬 처리를 위한 특별한 장치를 새로 생산하여 사용하는 것이 아니라 시장에서 생산되는 제품을 이용하므로 구축 비용이 저렴하다. 사용되는 네트워크 역시 기존에 사용되는 이더넷을 기반으로 동작한다. 대신 네트워크의 경우 각 노드 사이에서 교환되는 메시지를 충분히 빠른 속도로 전달할 수 있어야 하는데, 대략 Msec 수준의 전달 속도를 요구한다. 고성능 분산 컴퓨팅을 위한 소프트웨어 정도만 클러스터에 요구되는 새로운 요소로 볼 수 있다.

 현재 대부분의 슈퍼 컴퓨터는 클러스터에 기반한다. 클러스터의 장점은 다음과 같다.

  • Absolute Scalability: 확장성이 매우 좋다. 몇 천개의 노드도 연결할 수 있다.
  • Incremental Scalability: 순차적으로 확장할 수 있다. 노드를 추가하더라도 문제 없이 동작한다.
  • High Availability: 노드가 몇 개 고장나더라도 전체 시스템이 멈추지 않고 정상적으로 동작한다.
  • superior price/performance
    : 각 노드는 대량 생산되는 제품을 이용한 일반적인 PC를 기반으로 하고, 네트워크 역시 기존 이더넷 기반이므로 병렬 처리를 위한 새로운 하드웨어 또는 네트워크를 요구하지 않아 가격이 저렴한 편이다.

 클러스터는 일반적인 상업 목적(general purpose business) 또는 연산 집약적 계산을 진행할 때 사용되는데, 두가지 경우 모두 높은 가용성을 만족해야 하며, 이를 위해 다음과 같은 속성을 가진다. 

  • Load balancing: 클러스터의 각 노드에 대해 작업을 적절하게 분산할 수 있어야 한다. 클러스터는 loosely coupled 시스템이므로 다른 시스템들보다 로드 밸런싱이 더 어렵다.
  • Highly-availability Cluster: redundant node를 둬서 single points of failure - 시스템의 한 부분이 망가질 때 전체 시스템이 고장나는 상황을 방지해야 한다.

연관된 개념들

  • peer to peer: 각 노드가 클라이언트 또는 서버의 역할을 수행할 수 있는 네트워킹 모델로, 관리의 책임이 분산된다.
  • grid computing: 다수의 컴퓨터가 하나의 목적을 달성하기 위해 동작하는 방식. 해당 프로젝트에 참여하고 싶은 유저가 해당 단체에 요청하면(자발적인 지원이 필요) 오픈소스 프로그램 등을 제공하여 메인 서버와 통신함으로써 유저의 컴퓨터를 연산에 참여시킨다. 전 세계에서 낭비되는 컴퓨팅 자원을 과학적 프로젝트 등 비 상업적 측면에 활용하겠다는 목적을 가지나, 최근에는 비트코인 채굴 등에 악용되기도 한다.

Data Sharing

 초기 슈퍼 컴퓨터는 공유 메모리를 기반으로 했으나, 클러스터의 경우 각 노드가 하나의 컴퓨터 역할을 수행하기 때문에 물리적으로 메모리를 구현하지는 않는다. 대신 파일 시스템의 경우는 clustered file system을 이용한다고 한다.

https://en.wikipedia.org/wiki/Clustered_file_system


Message Passing & Communication

 클러스터는 크게 2가지 방식으로 노드 간 통신을 수행한다고 한다.


Task Scheduling

 멀티 유저 클러스터의 경우 매우 많은 데이터 및 작업을 가지게 되며, 이를 분산하는 작업은 매우 어렵다. 이쪽 분야는 현재 상당히 연구가 진행되고 있다고 하며, 현재 시점에서는 Hadoop의 MapReduce을 이용한다고 한다.

Hadoop

 아파치 재단에 의해 관리되는 오픈소스 기반 분산 컴퓨팅 지원 프로그램으로, MapReduce 기법을 이용한다고 한다. MapReduce 기법은 말 그대로 Map 과 Reduce을 수행하는 것으로, 주어진 데이터를 가공(Map)하여 처리한 후 집계(Reduce)하는 절차를 가지고 있다. Hadoop은 이러한 프로세스를 통해 HDFS의 데이터를 분산한다.


Node failure management

 클러스터는 높은 성능 및 가용성을 만족해야 한다. 클러스터의 구성 요소인 일부 노드가 고장났음에도 불구하고 계속 해당 노드에게 작업을 분배한다면 특정 작업이 제대로 진행되지 않는 등의 문제가 발생할 수 있다. 따라서 노드가 고장났는지 검사하거나, 고장이 의심되는 노드들을 기존 시스템과 격리(fencing)하는 기법이 요구된다.

 하드웨어 또는 소프트웨어적 접근 방식이 있을 수 있다.

  • 하드웨어적 방식: 각 노드에 고장을 감지하기 위한 장치를 설치한다. 추가 비용이 발생하므로 효율이 낮다.
  • 소프트웨어적 방식: 해당 노드가 정상적으로 동작하기 위해 주기적으로 하트비트를 보내 검사한다.

노드의 격리 방식도 다양할 수 있다.

  • power fencing: 해당 노드의 전원을 내리는 등 방법을 통해 노드를 비활성화한다.
  • resource fencing: 해당 노드로 전달되는 자원(업무 등)을 차단한다.

클러스터링 방식

 클러스터의 동작 방식에 따라 2가지로 나눌 수 있다.

  • passive standby
    • 현재 동작하는 서버의 고장을 대비하여 secondary 서버를 두는 방식으로, 중복 서버는 작업을 수행하지 않는다.
    • 장점: 시스템의 구현이나 고장 발생 시 대응이 쉽다.
    • 단점: 중복 서버는 성능에 기여하지 않으므로 컴퓨팅 자원의 낭비로 볼 수 있다.
  • active standby
    • 여러 서버가 동시에 동작하되 특정 서버가 고장나면 secondary 서버가 이를 대체한다.
    • 장점: 모든 서버가 동작하므로 비용이 덜 든다.
    • 단점: 시스템을 구현하기 복잡하다.

 노드의 구성에 따라 3가지로 나눌 수 있다.

  • Seperate server
    • 노드가 디스크를 개별적으로 가지며, 기존 서버에서 중복 서버로 지속적으로 데이터가 복사된다.
    • 장점: 가용성이 높다.
    • 단점: 데이터가 지속적으로 복사되므로 서버 및 네트워크 오버헤드가 상당한 편이다.
  • Servers Connected to Disks
    • 노드가 자신의 디스크를 가지되, 공유 디스크도 가진다.
      한 서버가 고장나면 작업 중이던 디스크 내용이 다른 서버로 전송된다.
    • 장점: 지속적인 복사 작업이 제거되었으므로 서버 및 네트워크의 오버헤드가 적다.
    • 단점: disk failure이 큰 문제를 일으킬 수 있으므로 RAID 시스템 등에 의한 보완이 필요하다.
  • Servers Share Disks
    • 다수의 서버가 동시에 디스크를 공유한다.
    • 장점: 서버 및 네트워크의 오버헤드가 작고, disk failure에 의한 고장 시간이 짧다.
    • 단점: 공유 디스크의 고장을 방지하기 위해 mirroring 또는 RAID 기법을 도입해야 하며, 다수의 서버가 동시에 파일 시스템에 접근할 때 발생할 수 있는 동기화 문제 등을 처리하기 위해 관리 목적 소프트웨어가 필요하다. 

클러스터링 구성 방식들

Operating System design issues

 고장이 어떻게 관리되는지는 어떤 클러스터링 메서드를 사용하는가에 달렸다. 클러스터 내 failure을 해결하기 위해서는 다음과 같은 부분들을 고려해야 할 필요가 있다.

  • Fault tolerant: 클러스터가 높은 가용성을 가지기 위해서 redundant shared disk를 사용할 수 있어야 하며, 커밋 기반으로 완전히 수행되어 제출되지 않은 작업을 back up 할 수 있어야 한다.
  • Failover: 특정 노드가 고장나면 해당 노드가 작업 중이던 데이터 자원을 클러스터 내 다른 노드에게 넘겨 계속 수행할 수 있어야 한다.
  • Failback: 고장난 노드가 고쳐지면 해당 노드가 수행하던 작업 및 데이터를 복원할 수 있어야 한다.
  • Load balancing: 확장성 등을 고려. 새로운 노드가 추가되면 자동적으로 스케줄링에 포함되어야 하며, 클러스터링 미들웨어는 언급한 사항들을 인지할 수 있어야 한다.

parallel computing

  • Parallelizing compiler
    • 컴파일러가 컴파일 타임에 어플리케이션의 어떤 위치가 병렬적으로 처리될 수 있는지 파악하고 결정하여 클러스터내 서로 다른 노드들에게 작업을 배분한다.
  • Parallelized application
    • 개발자가 프로그램 자체를 병렬적으로 동작할 수 있도록 작성한다.
  • Parametic computing
    • 동일한 작업에 대해 데이터 등 조건만 다르게 하여 반복 실행해야 하는 경우, 고성능의 단일 CPU 대신 성능이 낮은 저렴한 대량 CPU에 작업을 할당하여 실행한다.