하이브리드 연산 : 공유메모리와 분산 메모리의 결합에 대한 장점

0 Comments/in /by

이전 블로그에서 우리는 COMSOL Multiphysics에서 사용하는 공유메모리와 분산메모리에 대하여 살펴보았습니다. 오늘은 두 가지 방법이 혼합된 하이브리드(Hybrid) 연산에 대하여 알아보도록 하겠습니다. 여기서는 다양한 관점으로 하이브리드 연산과 모델링에 대하여 살펴보고, COMSOL Multiphysics상에서 최적화된 병렬연산을 제공하기 위해서 어떻게 하이브리드 형태를 사용하는지 설명 드리겠습니다.

 

하이브리드 연산 소개

최근에 클러스터 시스템은 다중코어기술의 발달에 의해 더욱더 강력해 졌습니다. 병렬화는 몇 단계에 걸쳐 이루어져 있고, 거대 시스템은 노드와 소켓, 코어 등을 아우르는 병렬화를 이용합니다.

게다가, 메모리 시스템 또한 몇 단계로 구성되어 있습니다. 이러한 계층구조는 더욱 깊어지고 복잡해 지며, 이러한 구성 형태를 반영하여 프로그램을 만들고 모델을 실행하여야 합니다. 한가지 방식만을 이용한 프로그래밍과 모델실행은 비효율적이므로, 연산방식은 점차 하이브리드화 되어 가고 있습니다.

 

코어의 법칙과 클러스터

다수의 코어에 의한 연산은 어디에서나 사용하고 있고, 병렬로 사용되고 있습니다. 동작 주파수는 2-5GHz정도의 높은 대역에서 고착되어 있어서, 연산능력 증가를 위해 코어를 점점 추가하고 있습니다. 그래서 잘 알려진 무어의 법칙은 면적 당 코어의 수가 지수적으로 증가하는 코어의 법칙이 되었습니다.

이러한 발전으로 코어당 연산자원(예:캐쉬메모리, 메모리 채널 수 등)은 더 작아질 것입니다. 일반적인 CPU의 최신 멀티코어 기술은 16개의 코어를 가지고 있으나 4개의 메모리 채널만 가집니다.
일반적으로 여러 개의 다중코어 CPU는 GigaFLOP/s(초당 10억번의 부동 소수점 연산을 수행함)단위의 뛰어난 연산능력을 제공하는 공유메모리 노드를 제공합니다. 이러한 공유메모리 노드의 일부는 고속연결을 통한 클러스터로 통합되어 있습니다. 이러한 클러스터는 예산의 허용범위 내에서 거의 무한한 메모리 자원과 (Giga/Tera/Peta)FLOP/s의 연산속도를 제공합니다.

그러므로 전세계의 연산속도가 가장 빠른 상위권 슈퍼 컴퓨터들은 10만개이상의 코어를 사용하고 있습니다.

 

한계의 도달

클러스터란 메시지가 노드 사이에서 메시지 전달에 의해 전송되는 분산메모리 시스템을 나타냅니다. 여기에서 여러 오픈 소스 들이 있고, 상업적으로 사용되는 메시지 전송 인터페이스(MPI)가 주로 사용됩니다. 노드 내부에서 OpenMP는 공유메모리 프로그래밍에 사용됩니다.

그러나 수치 실험을 통하여 다중코어 플랫폼의 한계를 발견할 수 있습니다. 기계에서 꾸준히 제품을 만들기 위해서는 그 재료가 계속 공급되어야 하는 것과 같이, 빠르게 동작하는 코어를 유지하도록 충분히 많은 데이터를 얻는 것은 어렵기 때문입니다. 기본적으로 FLOP/s는 자유롭게 활용 가능하지만, 데이터 당 FLOP의 수와 같은 계산량에 관심을 가져야 합니다. 계산량은 계산할 수 있는 FLOP/s비율에 대한 한계를 결정하게 됩니다.

만약 계산량이 문제의 크기에 비례하여 선형적으로 증가하면, 대역폭은 성능을 제한하지는 않습니다. 하지만 유한요소법을 이용한 수치 해석은 대역폭이 제한된 희소행렬형태(Sparse matrix vector)로 동작하고, 대역폭은 다중코어 시스템의 메모리 채널 수에 비례합니다. 사용 가능한 메모리의 대역폭이 포화되면, 더 많은 코어를 사용하더라도 연산속도는 빨라지지 않습니다. 이것이 다중코어 CPU를 사용하는 공유메모리 플랫폼상에서 모든 코어를 사용하지 않더라고 메모리 트래픽이 최고단계에 도달하여 일정 이상 연산속도가 증가하지 않는 이유입니다. 하지만 클러스터시스템은 누적되는 대역폭이 증가된 장점이 있으므로 더 나은 성능을 제공합니다.

하드웨어 측면에서 계층적인 캐시 메모리를 도입하여 대역폭 제한을 경감시켰습니다. 이것을 이용하면 메모리크기가 수백KB인 단일코어로 제한된 1레벨 캐쉬에서 메모리가 수십MB로 증가된 여러 코어들 사이를 공유하는 3레벨 캐쉬로 확장할 수 있습니다. 이러한 캐쉬를 사용하면 재사용될 데이터를 다시 메인 메모리로부터 가져오지 않고, 코어 근처에 저장해 두어 메모리 채널의 부하를 줄일 수 있습니다.

단일 다중코어 프로세서에서도 중첩메모리 구조를 가질 수 있습니다. 그러나 일반적으로 다수 소켓에 다수의 다중코어 프로세서를 결합한 불균일 기억 장치 접근(NUMA)방식의 공유 메모리 노드 형태로 만듭니다. 즉 응용프로그램 데이터의 일부는 코어와 관련된 메모리에 저장되고, 그 외 데이터는 원거리의 메모리에 저장됩니다. 그러므로 어떤 부분은 접근하기 위해 긴 대기시간이 필요하지만, 일부분은 매우 빠르게 접근할 수 있습니다. 이를 통하여 데이터의 정확한 위치와 이와 관련된 연산작업의 분포가 성능에 직접적인 영향을 준다는 것을 알 수 있습니다.

 

계층구조의 성능에 대한 이해

우리는 공유 메모리 시스템이 코어와 메모리의 계층적 구조로 만들어 져있고, 프로그래밍 모델과 알고리즘, 실행에는 이러한 계층구조에 대한 이해가 필요하다는 것을 알고 있습니다. 공유 메모리 노드의 연산자원은 한정적이므로, 추가적인 연산능력은 분산 연산에서 빠른 네트워크로 연결된 몇몇의 공유 메모리 노드들을 연결하여 얻을 수 있습니다.
이전의 공유메모리와 분산 메모리 연산에 대한 블로그 글과 같이 클러스터를 다수의 회의장소로, 공유메모리 노드들을 큰 책상이 있는 회의실로 가정하겠습니다.

만약 전반적인 작업의 량이 계속 증가한다면, 회의 관리자는 도움을 위해 회사의 다른 지사들을 호출 할 수 있습니다. 회의실이 보스턴과 샌프란시스코, 런던, 파리, 뮌헨에 있다면, 이러한 원거리의 회의실을 연결하는 것을 분산 메모리 프로세스(MPI 프로세스)로 표현할 수 있습니다. 관리자는 필요하다면 스톡홀름과 같은 새로운 장소에 회의실을 추가할 수 있으며, 하이브리드 연산 관점에서 관리자는 공유메모리 노드 당(회의실 하나당) 추가적인 프로세스(회의 책상)을 설치할 수 있습니다.

각 지사들의 회의실의(프로세스) 책상 위에는 데이터나 정보를 다른 회의실들과 교환하기 위해(메시지 전달) 전화기가 설치되어 있습니다. 각 지사의 직원들은 각 회의실의 책상 주위에 대기하고 있으며, 회의실 책상주변의 모든 직원들은 회의실 책상에 있는 일들을 해결하기 위한 스래드라고 생각할 수 있습니다.

책상에서 작업을 하는데 필요한 데이터들은 보고서(1레벨 케쉬)나 폴더(2레벨 케쉬), 캐비닛 내부의 폴더(3레벨 케쉬), 같은 층의 서재(메인 메모리), 지하 기록보관소의 서류(하드디스크)들에서 확인 할 수 있습니다. 서재나 기록보관소에서 필요한 정보를 가진 폴더들을 가져오기 위해 몇몇의 조수들(메모리채널)이 주변에서 일하고 있으며, 조수들의 수와 그들이 동시에 가져올 수 있는 폴더의 수(대역폭)은 한정되어 있습니다.

회의실의 책상에 더욱더 많은 직원이 존재하더라도 일하는데 필요한 정보를 충분히 가져다 줄 조수가 더 많이 없다면, 일 처리 속도는 증가하지 않습니다. 회의 관리자는 책상에 일 처리에 필요한 데이터가 있으며, 회의실의 모든 직원들이 주어진 문제를 해결하는데 효율적으로 기여하고 있는지 확인 할 필요가 있습니다. 그리고 관리자는 책상에서 전화기를 통해 다른 지사의 회의실을 호출하는 경우가 최소로 유지되는지도 확인하여야 합니다. 수치해석적 관점에서 표현하면 실행 시 계층구조를 인식해야 하고, 데이터는 근처에 존재 해야 하며, 통신의 량은 최소로 유지 되어야 합니다.

각 회의실간의 전화 통화는 프로세스들 사이의 MPI 호출을 의미합니다. 회의실 책상에서는 공유메모리 방식이 사용됩니다. 전체적으로 분산 메모리(MPI)와 공유 메모리(OpenMP)의 완벽한 상호작용이 필요해 집니다.

 

하이브리드 클러스터 형태의 예

지금부터 몇 가지 가능한 클러스터와 코어의 구성에 대하여 살펴보도록 하겠습니다. 아래의 벤치마크모델에서 우리는 3개의 공유 메모리 노드들로 구성되어 있는 작은 클러스터를 사용하였습니다. 모든 노드들은 쿼드코어 프로세서가 있는 두 개의 소켓들이 있고, 총 24개의 코어를 사용할 수 있습니다. 각각의 프로세서들에는 로컬 메모리 뱅크가 있는 NUMA형태의 메인 메모리를 나타내고 있습니다.

여기에서 우리는 3개, 6개, 12개, 24개의 MPI를 실행하여 볼 것 입니다. 3개의 MPI를 실행할 경우, 노드당 1개의 MPI가 실행될 것이고, MPI프로세스당 8개의 스레드들이 노드 내부의 두개의 소켓사이를 공유메모리방식/OpenMP를 이용하여 통신할 것입니다. 6개의 MPI를 실행할 경우, 소켓당 1개의 MPI가 실행될 것이고, 각각의 MPI프로세스는 4개의 스레드들이 필요합니다. 12개의 MPI를 실행할 경우, 프로세서당 2개의 MPI가 실행되며, 각각 2개의 스레드들이 실행됩니다. 마지막으로 코어당 1개의 MPI가 실행되는 24개의 MPI를 시스템에 실행할 경우, 이것은 공유메모리 연산은 사용하지 않고, 분산 메모리 연산만 사용하므로, 하이브리드 연산형태가 아니게 됩니다.

어떤 형태가 가장 좋을까요?

17_blog_01

 

쿼드코어 프로세서와 메모리 뱅크가 있는 두 개의 소켓으로 구성된 세 개의 공유메모리 노드들을 가진 클러스터의 다양한 MPI 형태

 

하이브리드를 사용해야 하는 이유?

왜 코어 구성 및 메모리 형태를 고려해야 하며, 하나의 방법만 사용하여 프로그램을 실행하지 않을까요? 그 이유는 공유메모리 방식(OpenMP)을 모든 시스템에서 사용할 수는 없기 때문입니다.

그럼 왜 메시지 전달(Message-passing)이 위의 예제와 같이 24 MPI 프로세스를 가진 모든 코어들에서 사용되지 않겠습니까? 물론 사용하는 것이 가능은 합니다. 사용자는 같은 공유메모리를 사용하는 코어들 사이에서는 메시지 전달을 사용할 수 있습니다. 그러나 이것은 모든 직원들이 자신의 전화기를 가지고, 다른 직원들을 동시에 호출하는 것과 유사합니다. 이 경우, 모든 신호들은 통화 중이므로, 사람들은 전화기를 계속 붙잡고 있게 되고, 결과적으로 일이 처리되지 않습니다.

실제현상은 더욱 복잡합니다. 왜냐하면 MPI 실행은 계층적으로 잘 알려져 있는 방법으로 실행되며, 지역적인 통신을 위해 공유 메모리방식을 사용하도록 잘 다듬어져 있습니다. MPI의 단점 중 하나는 메모리 자원이 사용되는 프로세스 수 대비 2차 함수적으로 낭비된다는 점으로, 프로세스들 사이에 실제 메시지를 보내기 전에 데이터를 저장하는 내부적인 버퍼가 존재하기 때문입니다. 만약 MPI 실행이 계층적인 방법을 사용하지 않는다면, 하나의 광역 통신의 106코어는 1012의 메모리 버퍼가 필요합니다. 하이브리드 계산에서 MPI프로세스의 수는 일반적으로 코어의 수보다 적은 수가 사용되어 메모리와 데이터 전달 시 사용되는 자원을 절약할 수 있습니다.

하이브리드 모델 사용의 또 다른 장점은 데이터 배치나 스레드 고정, 부하 균형과 같은 많은 방식들이 프로그래머의 정형화된 설정이 필요하며, 하이브리드 모델은 이러한 것들을 상세히 표현하기 위해 훨씬 다양한 기능들을 제공합니다. 그러므로 메모리와 코어 배열이 혼합된 구조가 적합하며, 자연스럽게 하이브리드OpenMP+MPI 모델을 고려하게 됩니다.

중요한 것은, 하이브리드 모델은 유연하고 쉽게 적용할 수 있으며, 자원에 대한 요구와 경비를 줄일 수 있습니다. 그리고 유한요소법 관점에서, 데이터와 작업의 상하관계는 종종 물리적 모델과 형상, 알고리즘, 사용된 솔버로 부터 얻을 수 있으며, 이러한 상하관계는 공유메모리 방식과 분산메모리 방식으로 나뉘어 지게 됩니다.

물론, 하이브리드 모델은 공유메모리와 분산연산의 단점을 모두 가지고 있고, 훨씬 더 복잡합니다. 하지만 노력대비 훨씬 가치 있는 결과를 제공합니다. 그러므로 이러한 기능을 이용하여 COMSOL Multiphysics는 결과값을 출력하고 다층 병렬화를 위한 세련된 데이터 구조들과 알고리즘들을 제공합니다. 이들은 동시에 공유메모리와 분산메모리를 사용할 수 있게 하며, 사용자는 최적의 성능을 위해 상호관계를 조절할 수 있습니다.

 

모델과 시스템에 대한 시험

앞의 이론적인 설명을 보고 나면, COMSOL Multiphyscis에서 실제모델을 이용하여 병렬해석 시 확장성, 속도 향상, 생산성 향상을 확인하고 싶어질 것입니다.

이 경우, 의미 있는 결과를 얻기 위해서는 해석하고자 하는 모델의 해석 크기가 중요합니다. 모든 병렬화 문제에 대한 효율성을 고려하기 위해서는 프로세스들 사이의 데이터 교환량이 상당히 많도록 프로세스당 계산량이 많아야 합니다. 이를 위해서는 모든 스레드 들에 대한 공유메모리 노드 상에 해석되는 문제들의 사이즈 또한 충분이 커야 합니다. 예를 들어 각 해석시간당 문제 사이즈는 작지만, 해석될 시간이 긴 시간해석문제의 경우, 코어 및 노드 수 증가에 따른 효율성을 확인하기가 어렵습니다.

 

하이브리드 확장성 연구

이번에는 타이어 압력에 의해 열 개의 스포크(spoke)가 존재하는 휠의 하중 분포를 해석 한 결과를 나타내는 구조모델을 살펴보도록 하겠습니다.

17_blog_02

휠 전체 모델과 부분적인 작은 모델

이 모델은 세 개의 해석 노드를 이용하여 해석하였습니다. 해석에 사용된 각 노드들은 각각 64GB RAM을 가지고 있으며, 쿼드코어 Intel Xeon® E5-2609프로세서들이 있는 두 개의 소켓을 가지고 있습니다. 노드들은 Gigabit 이더넷을 이용하여 연결되어 있으며, 총 24개의 코어를 사용할 수 있습니다.

하단의 그림에서 하이브리드 모델 형태를 이용하여 하루에 이 모델을 해석할 수 있는 횟수를 비교하였습니다. 우리는 1, 2, 3, 6, 12, 24개의 MPI를 실행하였고, 경우에 따라 1, 2, 3, 4, 6, 8, 12, 16, 24개의 코어를 사용하였습니다. 그래프에서 각각의 막대들은 (nn x np)형태로 표현 되었고, 이 때, nn는 프로세서의 수, np는 프로세서당 스레드의 개수를 나타냅니다. 그리고 nn x np는 활성화된 코어의 수를 나타냅니다. 막대들은 활성화된 코어의 수가 같은 것들끼리 묶여 있고, 각각의 형태들은 막대 상단부분에 정리되어 있습니다.

그래프는 평균적으로 코어 수 증가에 따라 성능이 향상되는 것을 보여 주고 있습니다. 우리는 구성형태 변화에 따라 약간씩 성능의 변화가 발생하는 것을 볼 수 있으며, 24개의 core를 사용하였을 때, 소캣 당 하나의 MPI프로세스를 사용하는 것이 가장 좋은 형태라는 것을 확인할 수 있습니다. 6×4조합을 사용하는 세 개의 노드 시스템은 1×8조합의 단일 공유메모리 노드 보다 두 배 이상 성능이 좋습니다. 이 경우 같은 코어 수를 사용하는 24×1의 완전 분산모델보다 거의 30%이상 성능이 좋은 것을 확인 할 수 있습니다.

24×1의 경우, 12×1의 경우와 비교했을 때, 코어를 두 배 더 사용하지만, 성능향상이 거의 없는 것을 볼 수 있습니다. 이것은 노드들을 연결하는데 사용된 Gigabit 이더넷 네트워크가 12 MPI 프로세스 사용시 성능의 한계에 도달했기 때문입니다. 그러므로 MPI를 더 사용하더라도 성능의 증가가 없을 것으로 예상됩니다. 코어 수에 따라 프로세스당 스레드의 수를 두 배 사용하는12×1경우와 12×2경우를 비교 했을 때, 이더넷을 통한 통신량이 증가하지 않았다는 것을 알 수 있습니다.

17_blog_03

다른형태의 하이브리드 구성을 사용하여 휠에 대한 구조해석을 수행하였습니다. y축은 하루당 이 모델을 해석할 수 있는 횟수를 통한 성능향상을 나타내고 있습니다. 막대들은 서로 다른 nn x np형태 구성을 나타내고, 여기에서 nn은 MPI프로세스의 수, np는 프로세스당 스레드의 수를 의미합니다.

 

COMSOL Multiphysics에서 하이브리드 실행 설정

병렬 하이브리드 모드에서 COMSOL Multiphysics를 실행할 때, 사용되는 프로세서와 스레드의 수에 대한 많은 경우의 수가 존재 합니다. 이 부분에 대해서는 Preference설정의 Multicore and Cluster Computing항목이나 Model Builder의 Study설정 하단에 있는 Cluster Computing에서 설정할 수 있습니다. 그리고 클러스터 해석 시 사용되는 노드의 수와 같은 상세 설정은 Job Configuration노드 하단의 Cluster Computing부분에서 설정 가능합니다. 설정 창에서 드롭 다운메뉴를 사용하면 노드당 사용 프로세서 수와 같은 추가적인 설정도 가능합니다.

프로세스당 사용되는 스레드들의 수는 자동으로 설정됩니다. COMSOL Multiphysics는 기본설정으로 항상 모든 코어를 사용하도록 설정되어 있습니다. 그리고 Preference설정의 Mulicore항목의 Number of processors설정을 이용하여 사용할 코어 수를 지정할 수도 있습니다.

리눅스 시스템에서는 MPI프로세서 수에 대한 –nn 명령어와 MPI프로세스당 스레드수를 자동으로 결정하는 -np명령어를 제공하고 있습니다. 그리고 -nnhost옵션을 이용하면, 호스트당 프로세서의 수를 설정할 수 있습니다. nnhost의 경우, 1또는 노드당 소켓의 수로 설정합니다.

0 replies

댓글 남기기