IPU Programming Model

Sungho Kim·2023년 11월 2일

IPU Programming

목록 보기
1/7

이 섹션에서는 IPU 추상 프로그래밍 모델과 IPU 프로그램 컴파일 및 실행 기술에 대해 설명합니다.

3.1. 포플러 그래프 라이브러리

이 섹션에서 설명하는 프로그래밍 모델은 포플러 그래프 라이브러리( libpoplar)에서 구현됩니다. 이 라이브러리는 IPU 프로그램을 구성하고 실행하기 위한 API를 제공하고 IPU 장치에서 프로그램을 실행하는 데 필요한 컴파일을 수행합니다. 자세한 내용은 Poplar 및 PopLibs 사용 설명서를 참조하세요 .

3.2. 프로그램들

프로그램은 일련의 IPU를 통해 실행됩니다. 이 세트는 사용자가 구성할 수 있으며 프로그램이 컴파일되기 전에 선택됩니다. 프로그램을 실행하는 IPU 세트는 프로그램 실행 과정에서 변경되지 않습니다.

단일 프로그램은 선택된 모든 IPU에서 실행됩니다. 이 프로그램은 지정된 제어 흐름의 경로를 따르고 CPU의 표준 프로그램과 마찬가지로 변수를 조작합니다. 조작되는 변수는 IPU 및 스트리밍 메모리의 다양한 메모리 요소에 존재하는 대규모 데이터 배열(종종 다차원 텐서로 해석됨)입니다. 프로그램은 타일 프로세서의 스레드에서 실행되는 일련의 고도로 병렬적인 작업( 정점 이라고 함)을 통해 이러한 변수를 조작합니다. 이러한 작업 세트를 컴퓨팅 세트 라고 합니다 . 그림 3.1은 IPU에 있는 프로그램의 전체 구조를 보여줍니다.


그림 3.1 IPU 세트에서 실행되는 프로그램

프로그램이 모든 IPU에서 실행되더라도 IPU는 SIMD 장치가 아닙니다. IPU에 배포되는 단일 기계 수준 명령 스트림은 없습니다. 대신 IPU는 알려진 지점에서 동기화하여 프로그램을 실행합니다. 이를 통해 동기화 지점 사이의 모든 병렬 스레드에서 완전히 다른 코드를 유연하게 실행할 수 있습니다.

3.2.1. 데이터 변수

변수는 프로그램이 실행되는 동안 데이터를 보유합니다. 각 타일 세트에서 프로그램은 유형이 지정된 배열(고정 크기)을 조작합니다. float예를 들어, 변수는 1024개 유형의 요소 (32비트 부동 소수점 숫자) 를 포함하는 배열일 수 있습니다 .

단일 변수는 여러 타일의 메모리 단위에 걸쳐 저장될 수 있습니다. 변수의 각 요소는 특정 타일에 배치되거나 "매핑"됩니다. 이를 변수의 타일 매핑 이라고 합니다.

그림 3.2 변수와 타일에 대한 매핑

변수는 항상 전역 범위를 갖습니다. 프로그램의 어느 부분에서나 읽거나 쓸 수 있지만 변수에 할당된 물리적 메모리는 동시에 필요하지 않은 다른 변수와 공유될 수 있습니다( 섹션 3.5.1, 변수 활성 ).

ML 프로그램이 변수를 조작할 때 변수를 다차원 텐서로 보는 것이 유용한 경우가 많습니다. 이 경우, 프로그램의 다른 부분에서는 기본 변수를 다른 종류의 텐서로 보기를 원할 수 있습니다(예: 행렬을 행 주요 또는 열 주요로 보기). 따라서 IPU의 프로그램에서 텐서는 기본 변수에 대한 뷰입니다.

그림 3.3 동일한 변수에 대한 다중 보기

변수를 다차원 텐서로 보는 것은 IPU에서 프로그램을 실행하는 데 필요한 액세스 패턴을 구축하는 데 매우 유용합니다. 그러나 데이터 조작은 여전히 ​​메모리의 기본 변수에서 발생합니다.

변수는 타일 전체와 스트리밍 메모리에 저장할 수 있습니다( 섹션 2.1, 메모리 아키텍처 ).

포플러 그래프 라이브러리는 슬라이싱, 전치 및 연결을 포함하여 변수의 텐서 뷰를 생성하기 위한 풍부한 연산자 세트를 제공하여 텐서를 구축합니다. 자세한 내용은 Poplar Tensor API를 참조하세요 .

3.2.2. 데이터 복사 및 컴퓨팅 세트 실행

프로그램이 타일 세트에서 실행되면 프로그램의 변수를 조작하게 됩니다. 이를 수행하는 두 가지 주요 방법은 데이터 복사와 컴퓨팅 세트 실행입니다.

가장 기본적인 복사에는 하나의 변수를 다른 변수로 복사하는 작업이 포함됩니다. 예를 들면 다음과 같습니다.

Copy(v1, v2);

그러나 복사에는 고정된 패턴의 재배열도 포함될 수 있습니다. 이는 섹션 3.2.1, 데이터 변수 에 설명된 텐서 뷰를 통해 수행할 수 있습니다 . 예를 들어, 전치된 보기에서 복사하면 전치 복사가 수행됩니다.

Copy(t1.tranpose(), t2);

여기서는 t1.transpose()재배열된 데이터 요소의 보기만 제공하지만 이를 새 변수에 대한 복사 작업의 소스로 사용하여 실제로 재배열을 수행하고 메모리에서 데이터를 이동합니다.

컴퓨팅 세트는 코드를 실행하여 데이터를 조작합니다. 각 컴퓨팅 세트에는 이름이 있습니다.

Execute(cs1)

컴퓨팅 세트가 실행되면 프로그램 변수에서 변수 요소 세트를 읽고, 계산하고, 씁니다.


그림 3.4 컴퓨팅 세트

메모: 특정 컴퓨팅 세트에서 액세스하는 가변 요소는 고정되어 있으므로 각 실행 시 달라질 수 없습니다.

컴퓨팅 세트는 예를 들어 변수의 모든 요소를 ​​증가시키는 등 다양한 계산을 수행할 수 있습니다. 프로그램이 컴퓨팅 세트가 실행하는 기능을 지정하는 방법은 섹션 3.2.4, 컴퓨팅 세트 에 설명되어 있습니다 .

3.2.3. 제어 흐름: 시퀀스, 조건부 및 루프

데이터 복사 및 컴퓨팅 세트 실행과 같은 기본 작업 외에도 IPU에서 실행되는 프로그램은 루프, 조건부 등과 같은 표준 제어 흐름을 실행할 수 있습니다. 예:

목록 3.1 제어 흐름의 예

while(v1 < v2):
  copy(t1, t2);
  execute(cs1);
  if (v3 < v4):
    copy(t2, t3);
  else:
    copy(t3, t2);
  execute(cs2);

여기서 제어 흐름에 사용되는 변수는 컴퓨팅 세트로 조작할 수 있는 표준 변수(예: 목록 3.1v1 ) 에 매핑된 크기 1의 텐서(즉, 스칼라)입니다 .

프로그램에 의해 정의된 전체 제어 흐름은 모든 IPU의 모든 타일에 대해 동일합니다. 개념적으로 시스템의 모든 IPU에 적용되는 전역 제어 흐름을 정의하는 단일 프로그램이 있습니다. 그러나 이 전역 프로그램은 그래프의 각 꼭지점에서 수행되는 계산과 분리되어 있습니다(이 장의 시작 부분에서 설명했듯이 기계는 SIMD가 아니며 모든 꼭지점은 독립적인 프로그램을 실행할 수 있습니다). 각 타일은 프로그램을 통해 서로 다른 경로를 사용할 수 있습니다. 로컬 데이터에 따라 실행할 조건부 분기 또는 실행할 루프 반복 횟수를 결정합니다.


그림 3.5 IPU의 전체 시스템은 단일 프로그램을 실행합니다.

3.2.4. 컴퓨팅 세트(Compute set)

컴퓨팅 세트는 고도로 병렬화된 컴퓨팅 부분입니다. 각 컴퓨팅 세트는 컴퓨팅 작업인 여러 정점 으로 구성됩니다. 컴퓨팅 세트 내의 각 정점은 다른 정점과 병렬로 코드 조각을 실행합니다. 따라서 그림 3.4 에서 계산을 수행하고 변수를 읽고 쓰는 계산 집합은 실제로 병렬로 실행되는 정점 집합이며, 각 정점은 변수를 읽고 쓰고 계산을 수행합니다.


그림 3.6 컴퓨팅 세트 내의 정점

꼭짓점은 컴퓨팅 세트가 해당 작업을 세분화된 병렬 컴퓨팅 조각으로 분할하여 IPU의 많은 타일과 작업자 스레드를 사용하는 방법을 결정합니다. 각 정점은 IPU의 특정 타일에 연결됩니다.

각 정점은 자체 입력 및 출력을 처리하는 작은 코드 조각(기본 프로그램과 별도로)을 실행합니다. 정점이 실행하는 코드 조각을 코드 렛 이라고 합니다 . 이 코드를 병렬로 실행하는 각 정점의 조합은 컴퓨팅 세트의 기능을 정의합니다. 정점 프로그래밍에 대한 자세한 내용은 Poplar 및 PopLibs 사용자 가이드 에서 확인할 수 있습니다 .

3.2.5. 계산 그래프(Compute Graph)

프로그램의 여러 계산 집합의 정점은 그림 3.7 과 같이 프로그램의 계산 그래프를 형성합니다 .


그림 3.7 변수의 그래프 표현과 처리

이 그래프는 프로그램으로 명시적이고 생성된 컴퓨팅과 데이터 간의 관계를 유지합니다. 그래프는 데이터 관계를 보여주지만 프로그램의 제어 흐름은 보여주지 않습니다.

3.2.6. 데이터 스트림(Data Stream)

IPU에서 실행되는 프로그램은 외부 데이터에 대한 연결에 액세스할 수 있습니다. 이러한 데이터 스트림을 통해 프로그램은 외부 소스(일반적으로 호스트 컴퓨터의 메모리)의 데이터를 프로그램 변수로 복사할 수 있습니다.

목록 3.2 프로그램의 데이터 스트림 복사 예

..
stream-copy(s1, v1)
execute(cs)
copy(v1, v2)

데이터 스트림에서 데이터가 제공되거나 소비되는 방식에 대한 구성은 프로그램이 실행될 때 호스트에 의해 구성됩니다( 섹션 3.3, 프로그램 로드 및 실행 참조 ).

데이터 스트림 복사는 일반적으로 IPU에 도달하기 전에 여러 메모리(호스트 메모리 및 스트리밍 메모리)를 거치기 때문에 전송을 최적화하기 위한 여러 구현별 플래그가 있습니다(예: 데이터를 프리페치하여 메모리 전송의 중복을 활성화함). 이러한 옵션에 대한 자세한 내용은 Poplar 및 PopLibs 사용자 가이드 에서 확인할 수 있으며, 이러한 최적화를 애플리케이션에 적용하는 방법에 대한 실제 논의는 메모리 및 성능 최적화 가이드 에서 찾을 수 있습니다 .

3.2.7. IPU 수준 작업 병렬성

각 컴퓨팅 세트의 세분화된 병렬 처리뿐만 아니라 IPU 세트에서 실행되는 프로그램은 포크 조인 스타일 병렬 처리를 통해 병렬 하위 프로그램으로 분할될 수도 있습니다.

IPU 내의 모든 타일은 동기화를 위해 함께 그룹화되므로 프로그램의 병렬화는 개별 하위 프로그램이 서로 다른 IPU에서 실행되는 세분성으로 작동합니다. 그림 3.8은 이를 보여준다.


그림 3.8 병렬 하위 프로그램으로 분할되는 프로그램

이 기능은 파이프라인 모델 병렬 처리와 같은 여러 프로그래밍 기술에 사용되며 섹션 5, IPU의 일반적인 알고리즘 기술 에 설명되어 있습니다 .

3.2.7.1. IPU 내 I/O 중첩

서로 다른 IPU에서 프로그램을 병렬로 실행하는 일반적인 방법 외에도 제한된 형태의 작업 병렬 처리가 IPU 내에서 실행될 수 있습니다. IPU는 두 세트의 타일 그룹으로 분할될 수 있습니다. 한 타일 그룹은 칩 외부에서 데이터를 가져오고 수신하는 I/O만 수행하고 다른 타일 그룹은 일반 컴퓨팅을 수행할 수 있습니다. 그런 다음 프로그램은 두 개의 하위 프로그램으로 분할되어 하위 프로그램 중 하나와 병렬로 실행되며 스트리밍 메모리에 있는 변수와 I/O 전용 타일 그룹에 대한 데이터 스트림 또는 복사본의 시퀀스를 실행합니다.


그림 3.9 I/O의 병렬 실행

3.3. 프로그램 로드 및 실행

다중 IPU 장치는 항상 프로그램의 컴파일 및 실행을 제어하는 ​​호스트에 연결됩니다.

먼저, 호스트는 IPU 세트에서 실행할 프로그램 세트를 구성합니다. 그런 다음 이러한 프로그램은 바이너리로 함께 컴파일되어 IPU에 로드됩니다.


그림 3.10 IPU에 프로그램 로드

프로그램을 로드하는 것 외에도 호스트는 프로그램이 데이터 스트림 중 하나를 읽거나 쓸 때 어떤 일이 발생하는지 구성해야 합니다. 이는 데이터 스트림을 데이터 소스(예: 호스트 메모리 영역)에 연결하거나 IPU의 데이터 스트림 요청을 처리하는 호스트의 핸들러에 연결하는 호스트 애플리케이션에 의해 사전에 수행됩니다.

프로그램이 로드되고 구성되면 호스트는 IPU에 프로그램 중 하나를 실행하도록 지시할 수 있습니다.


그림 3.11 실행할 제어 프로그램 선택

이 시점에서 IPU는 선택된 전체 프로그램을 실행합니다. 이 프로그램이 실행되는 동안 IPU는 데이터 스트림에서 데이터를 읽고 쓸 수 있습니다. 예를 들어, 프로그램은 신경망 모델(모델 자체가 이미 프로세서에 상주함)을 훈련할 때 훈련 데이터 항목을 IPU로 가져오라는 명령을 내릴 수 있습니다.

3.4. IPU 프로그램을 사용한 ML 프레임워크 구현

PyTorch 및 TensorFlow 와 같은 더 높은 수준의 기계 학습 프레임워크를 사용 하면 외부 현상의 모델을 제공하는 계산 그래프를 지정할 수 있습니다. 이러한 그래프에는 훈련 데이터를 사용하는 프레임워크에 지정된 최적화 알고리즘을 사용하여 프레임워크가 훈련할 수 있는 학습 가능한 매개변수가 있습니다.

일반적인 상위 수준 프레임워크에서 IPU 프로그램으로의 구현 흐름이 그림 3.12 에 나와 있습니다 .


그림 3.12 IPU에서 실행하기 위해 낮추는 일반적인 프레임워크

프레임워크는 계산 그래프에서 변환을 수행하고 해당 그래프에 역방향 전달 및 최적화 루프를 추가한 다음 마지막으로 각 노드가 특정 순서로 계산되도록 그래프를 예약합니다. 예약된 그래프가 준비되면 각 노드가 컴퓨팅 세트 실행으로 대체되는 IPU 프로그램으로 변환될 수 있습니다.

3.5. IPU 프로그램의 컴파일 및 실행

IPU에서 실행되는 프로그램은 개념적으로 모든 IPU에서 함께 실행됩니다. 그러나 IPU는 완전히 분리된 메모리( 그림 2.3 )를 가지므로 공유 상태에 직접 액세스할 수 없습니다.

이는 프로그램이 기존 컴파일러를 통해 전달되어 타일 세트에서 실행될 수 없음을 의미합니다. 대신 프로그램은 먼저 IPU 칩 실행과 일치하는 형식으로 낮아집니다( 섹션 2.2 실행 에 설명된 대로 동기화, 교환 및 계산으로 구성됨 ).


그림 3.13 명시적인 동기화, 교환 및 계산 단계로 프로그램 낮추기

그런 다음 글로벌 프로그램은 각 타일에 대한 명시적인 동기화 및 통신 단계를 사용하여 각 타일에 대한 프로그램으로 낮아집니다.


그림 3.14 프로그램을 여러 타일로 낮추기

이렇게 낮추면 각 타일에는 자체 버전의 프로그램이 있습니다. 이 버전:

자체 타일 메모리에서만 데이터를 읽고 씁니다.
다른 타일에 대한 명시적인 동기화 지침이 포함되어 있습니다.
다른 타일과 교환할 수 있는 데이터 통신 루틴이 포함되어 있습니다.
컴퓨팅 세트를 실행할 때 해당 타일의 정점을 실행하기만 하면 됩니다.~~

이러한 낮추기는 포플러 그래프 라이브러리에 의해 수행됩니다. 결과는 타일에서 실행하기 위해 기존 컴파일러로 컴파일할 수 있는 타일별 프로그램입니다.

이러한 감소가 발생하더라도 타일 간의 동기화로 인해 실행을 모든 타일에 걸쳐 전역 실행으로 보는 것이 여전히 가능합니다. 예를 들어 이것은 PopVision 그래프 분석기 도구가 보여주는 보기입니다 .

3.5.1. 가변 활성

프로그램 내에서 모든 변수는 전역 변수입니다. 변수는 스트리밍 메모리 또는 타일 배열 전체에 저장됩니다(다른 타일에 저장된 변수의 각 영역에 대해 타일 메모리에 여러 주소가 있음).

변수의 전역 범위에도 불구하고 변수는 모두 타일 또는 스트리밍 메모리의 해당 영역에 대해 고유한 주소를 갖지 않습니다. 변수는 겹칠 수 있으며 일부 변수는 동일한 메모리 영역을 공유합니다. 이는 프로그램의 각 단계의 입력과 출력이 알려져 있고 컴파일 중에 각 변수의 활성(즉, 프로그램 실행 중 변수가 필요한 지점)이 알려져 있기 때문에 가능합니다. 이를 통해 컴파일러는 동시에 활성화되지 않은 변수를 동일한 메모리 주소에 할당할 수 있습니다.

프로그램 실행 중 각 지점에서 여러 변수가 활성화됩니다. 이는 동적으로 할당된 시스템의 메모리 힙 크기와 동일합니다. 라이브 변수 메모리 크기는 해당 시점에 사용되는 임시 메모리의 양입니다. 일부 변수는 항상 활성 상태 입니다 . 항상 나중에 사용할 수 있는 데이터를 포함하며 메모리에 고유한 주소를 갖습니다.

PopVision 그래프 분석기는 프로그램이 실행될 때 라이브 메모리와 항상 라이브 메모리를 보여줍니다. 다음 스냅샷은 프로그램 실행 중에 메모리 사용량이 어떻게 변하는지에 대한 아이디어를 제공하기 위해 이를 보여줍니다.

시간이 지남에 따라 실시간 가변 메모리

profile
오복, 무심

0개의 댓글