다음을 통해 공유


C++ AMP 개요

C + + 가속 대규모 병렬 (c + + AMP)의 그래픽 처리 장치 (GPU)와 같은 데이터 병렬 하드웨어 별도 그래픽 카드를 이용 하 여 c + + 코드의 실행 속도 높입니다.C + + AMP를 사용 하 여 유형이 다른 하드웨어에서 병렬 처리를 사용 하 여 실행을 가속 수 있도록 다차원 데이터 알고리즘을 코딩할 수 있습니다.다차원 배열, 인덱싱, 메모리 전송, 바둑판식으로 배열 및 수학 함수 라이브러리를 c + + AMP 프로그래밍 모델을 포함합니다.성능을 향상 시킬 수 있도록 데이터에서 CPU는 GPU와, 뒷면에 이동 방법 제어 하려면 c + + AMP 언어 확장을 사용할 수 있습니다.

시스템 요구 사항

  • Windows 7, Windows 8, Windows Server 2008 R2 또는 Windows Server 2012

  • DirectX 11 기능 수준 11.0 또는 나중에 하드웨어

  • 소프트웨어 에뮬레이터에서 디버깅을 위한 Windows 8 또는 Windows Server 2012 필요 합니다.하드웨어를 디버깅 하는 데 사용 중인 그래픽 카드의 드라이버를 설치 해야 합니다.자세한 내용은 GPU 코드 디버깅을 참조하십시오.

소개

다음 두 예제는 c + + AMP의 주요 구성 요소를 보여 줍니다.해당 요소의 1 차원 배열 두 개를 추가 한다고 가정 합니다.예를 들어, 추가 하려는 {1, 2, 3, 4, 5} 및 {6, 7, 8, 9, 10} 를 구하려면 {7, 9, 11, 13, 15}.C + + AMP를 사용 하지 않고 숫자를 추가 하 고 결과 표시 하는 다음 코드를 작성할 수 있습니다.

#include <iostream>

void StandardMethod() {

    int aCPP[] = {1, 2, 3, 4, 5};
    int bCPP[] = {6, 7, 8, 9, 10};
    int sumCPP[5];

    for (int idx = 0; idx < 5; idx++)
    {
        sumCPP[idx] = aCPP[idx] + bCPP[idx];
    }

    for (int idx = 0; idx < 5; idx++)
    {
        std::cout << sumCPP[idx] << "\n";
    }
}

코드의 중요 한 부분으로 다음과 같습니다.

  • 데이터: 데이터의 세 개의 배열을 구성 됩니다.모두 동일한 차수 (1) 및 (5) 길이 있습니다.

  • 반복: 첫 번째 for 루프 배열의 요소를 반복 하는 메커니즘을 제공 합니다.합계를 계산 하려면 다음을 실행 하려는 코드에 첫 번째 포함 된 for 블록.

  • 인덱스:에서 idx 변수 배열의 개별 요소에 액세스 합니다.

C + + AMP를 사용 하 여 다음 코드를 대신 작성할 수 있습니다.

#include <amp.h>
#include <iostream>
using namespace concurrency;

const int size = 5;

void CppAmpMethod() {
    int aCPP[] = {1, 2, 3, 4, 5};
    int bCPP[] = {6, 7, 8, 9, 10};
    int sumCPP[size];
    
    // Create C++ AMP objects.
    array_view<const int, 1> a(size, aCPP);
    array_view<const int, 1> b(size, bCPP);
    array_view<int, 1> sum(size, sumCPP);
    sum.discard_data();

    parallel_for_each( 
        // Define the compute domain, which is the set of threads that are created.
        sum.extent, 
        // Define the code to run on each thread on the accelerator.
        [=](index<1> idx) restrict(amp)
    {
        sum[idx] = a[idx] + b[idx];
    }
    );

    // Print the results. The expected output is "7, 9, 11, 13, 15".
    for (int i = 0; i < size; i++) {
        std::cout << sum[i] << "\n";
    }
}

동일한 기본 요소에는 있지만 구문은 c + + AMP를 사용 하는:

  • 데이터: c + + 배열을 세 개의 c + + AMP를 만드는 데 사용할 array_view 개체입니다.생성 하는 네 가지 값을 제공는 array_view 개체: 데이터 값, 순위, 요소 형식 및 길이 array_view 각 차원 개체입니다.차수 및 형식을 형식 매개 변수로 전달 됩니다.데이터와 길이 생성자 매개 변수로 전달 됩니다.이 예제에서는 생성자에 전달 되는 c + + 배열이 1 차원입니다.차수 및 길이 직사각형 모양에 있는 데이터의 생성에 사용 되는 array_view 개체 및 데이터 값 배열을 채우는 데 사용 됩니다.런타임 라이브러리도 포함 되어 있습니다는 array 클래스, 있는 유사한 인터페이스는 array_view 클래스 및이 문서에서 나중에 설명 합니다.

  • 반복:에서 parallel_for_each 함수(C++ AMP) 데이터 요소를 통해 반복 하는 메커니즘을 제공 하거나 도메인 계산.이 예에서 계산 도메인 지정 된 sum.extent.실행 코드는 람다 식에 포함 된 또는 커널 함수.restrict(amp) C + + AMP를 가속화할 수 있는 c + + 언어의 하위 집합만 사용 됨을 나타냅니다.

  • 인덱스:는 index 클래스 변수를 idx, 일치의 순위를 순위에 선언 되는 array_view 개체.인덱스를 사용 하 여 개별 요소에 액세스할 수 있는 array_view 개체입니다.

모양 처리 및 인덱싱 데이터: 인덱스 및 범위

데이터 값을 정의 하 고 커널 코드를 실행 하기 전에 데이터의 모양에 선언 해야 합니다.모든 데이터를 정의 하는 배열 (사각형)로 하 고 배열의 임의의 차수 (차원의 수)를 정의할 수 있습니다.데이터 크기에 모든 크기입니다.

Hh265136.collapse_all(ko-kr,VS.110).gif클래스 색인

index 클래스 의 위치를 지정은 array 또는 array_view 각 차원에서 원점을 오프셋 한 개체로 캡슐화 하는 개체입니다.위치 배열에 액세스 하는 경우 전달에 index 개체 인덱싱 연산자를 [], 정수 인덱스 목록을 대신 합니다.사용 하 여 각 차원에 있는 요소를 액세스할 수 있는 array::operator() 연산자 또는 array_view::operator() 연산자.

다음 예제에서는 세 번째 요소는 1 차원으로 지정 된 1 차원 인덱스를 만듭니다. array_view 개체입니다.인덱스의 세 번째 요소가 인쇄 되는 array_view 개체입니다.결과 3입니다.

    
int aCPP[] = {1, 2, 3, 4, 5};
array_view<int, 1> a(5, aCPP);
index<1> idx(2);
std::cout << a[idx] << "\n";  
// Output: 3

다음 예제에서는 요소를 지정 하는 2 차원 인덱스 위치 행 1, 열 = = 2 차원에서 array_view 개체입니다.첫 번째 매개 변수는 index 생성자 행 구성 요소 이며 두 번째 매개 변수는 열 구성 요소입니다.출력은 6입니다.

int aCPP[] = {1, 2, 3,
              4, 5, 6};
array_view<int, 2> a(2, 3, aCPP);
index<2> idx(1, 2);
std::cout << a[idx] << "\n";
// Output: 6

다음 예제에서는 요소를 지정 하는 3 차원 인덱스 위치 깊이 = 0, 행 1, 열 = = 3 차원에서 3 array_view 개체.첫 번째 매개 변수는 깊이 구성 요소입니다, 행 구성 요소를 두 번째 매개 변수는 및 세 번째 매개 변수는 열 구성 요소입니다 확인할 수 있습니다.출력은 8입니다.

int aCPP[] = {
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

array_view<int, 3> a(2, 3, 4, aCPP); 
// Specifies the element at 3, 1, 0.
index<3> idx(0, 1, 3);               
std::cout << a[idx] << "\n";

// Output: 8

Hh265136.collapse_all(ko-kr,VS.110).gif클래스 범위

extent 클래스(C++ AMP) 각 차원에서 데이터의 길이 지정 된 array 또는 array_view 개체.익스텐트를 만들고 사용 하 여 만들 수 있는 array 또는 array_view 개체입니다.기존 범위를 검색할 수도 있습니다 array 또는 array_view 개체입니다.범위에서 각 차원의 길이 인쇄 하는 다음 예제는 array_view 개체입니다.

int aCPP[] = {
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
// There are 3 rows and 4 columns, and the depth is two.
array_view<int, 3> a(2, 3, 4, aCPP); 
std::cout << "The number of columns is " << a.extent[2] << "\n";
std::cout << "The number of rows is " << a.extent[1] << "\n";
std::cout << "The depth is " << a.extent[0]<< "\n";
std::cout << "Length in most significant dimension is " << a.extent[0] << "\n";

다음 예제에서는 array_view 가 동일한 개체는 사용 하 여 치수 앞의 예에서 되지만이 예제에서 개체는 extent 명시적 매개 변수를 사용 하는 대신 개체의 array_view 생성자.

int aCPP[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
extent<3> e(2, 3, 4);
array_view<int, 3> a(e, aCPP);
std::cout << "The number of columns is " << a.extent[2] << "\n";
std::cout << "The number of rows is " << a.extent[1] << "\n";
std::cout << "The depth is " << a.extent[0] << "\n";

액셀러레이터 키에 데이터를 이동 합니다: 배열 및 array_view

가속기에 데이터를 이동 하는 데 사용 하는 두 개의 데이터 컨테이너 런타임 라이브러리에서 정의 됩니다.들의 array 클래스 , array_view 클래스.array 개체가 생성 될 때 데이터의 전체 복사본을 컨테이너 클래스입니다.array_view 커널 함수는 데이터에 액세스할 때 데이터를 복사 하는 래퍼 클래스입니다.데이터 소스 장치에서 필요한 경우 데이터를 다시 복사 됩니다.

Hh265136.collapse_all(ko-kr,VS.110).gif배열 클래스

경우는 array 개체가 생성, 데이터 집합에 대 한 포인터를 포함 하는 생성자를 사용 하는 경우 데이터의 전체 복사본은 가속기에서 만들어집니다.커널 함수 가속기에 복사본을 수정합니다.커널 함수 실행이 완료 되 면 원본 데이터 구조에 데이터를 복사 해야 합니다.다음 예제에서는 각 요소에 벡터 10을 곱한.커널 함수를 후에 벡터 변환 연산자 벡터 개체로 데이터를 복사 하는 데 사용 됩니다.

std::vector<int> data(5);
for (int count = 0; count < 5; count++) 
{
     data[count] = count;
}

array<int, 1> a(5, data.begin(), data.end());

parallel_for_each(
    a.extent, 
    [=, &a](index<1> idx) restrict(amp)
    {
        a[idx] = a[idx] * 10;
    }
);

data = a;
for (int i = 0; i < 5; i++) 
{
    std::cout << data[i] << "\n";
}

Hh265136.collapse_all(ko-kr,VS.110).gifarray_view 클래스

array_view 가 거의 동일한 구성원으로는 array 내부 동작 하지만 클래스와 다릅니다.데이터를 전달 하는 array_view 생성자와 마찬가지로 GPU에서 복제 하지 않습니다는 array 생성자입니다.대신, 커널 함수를 실행할 때 데이터는 가속기에 복사 됩니다.따라서 두 개를 만드는 경우 array_view 개체는 동일한 데이터를 사용 하 여 둘 다 array_view 개체 참조는 같은 메모리 공간에.이렇게 하면 다중 스레드 액세스를 동기화 해야 합니다.주요 장점은 array_view 클래스는 필요한 경우에 데이터를 이동 합니다.

Hh265136.collapse_all(ko-kr,VS.110).gif배열 및 array_view의 비교

다음 표에서 유사성을 요약 하 고 차이점은 arrayarray_view 클래스입니다.

설명

배열 클래스입니다.

array_view 클래스

순위 결정 되는 경우

컴파일 타임에 있습니다.

컴파일 타임에 있습니다.

범위 결정 되는 경우

런타임에.

런타임에.

모양

사각형입니다.

사각형입니다.

데이터 저장소

데이터 컨테이너가입니다.

데이터 래퍼입니다.

복사

정의에 명시적이 고 전체 복사본입니다.

커널 함수를 통해 액세스할 때 암시적 복사본입니다.

데이터 검색

배열 데이터를 복사 하 여 개체에 CPU 스레드를 백업 합니다.

직접 액세스 하는 array_view 개체 또는 호출의 array_view::synchronize 메서드 계속 원래 컨테이너에 있는 데이터에 액세스 하려면.

데이터에 대해 코드를 실행 합니다.: parallel_for_each

Parallel_for_each 함수 정의에서 가속기의 데이터에 대해 실행 하려는 코드를 array 또는 array_view 개체입니다.이 항목의 소개 부분에서 다음 코드를 고려 하십시오.

#include <amp.h>
#include <iostream>
using namespace concurrency;

void AddArrays() {
    int aCPP[] = {1, 2, 3, 4, 5};
    int bCPP[] = {6, 7, 8, 9, 10};
    int sumCPP[5] = {0, 0, 0, 0, 0};

    array_view<int, 1> a(5, aCPP);
    array_view<int, 1> b(5, bCPP);
    array_view<int, 1> sum(5, sumCPP);

    parallel_for_each(
        sum.extent, 
        [=](index<1> idx) restrict(amp)
        {
            sum[idx] = a[idx] + b[idx];
        }
    );

    for (int i = 0; i < 5; i++) {
        std::cout << sum[i] << "\n";
    }
}

parallel_for_each 메서드는 두 인수, 계산 도메인 및 람다 식을 사용 합니다.

도메인 계산 되는 extent 개체 또는 tiled_extent 의 병렬 실행을 위해 만드는 스레드 집합을 정의 하는 개체입니다.한 스레드가 컴퓨트 도메인의 각 요소에 대해 생성 됩니다.이 경우에 extent 개체가 1 차원 이며 다섯 가지 요소가 있습니다.따라서 5 개의 스레드를 시작 됩니다.

람다 식 각 스레드에서 실행 하는 코드를 정의 합니다.캡처 절 [=], 이런 값으로 람다 식의 본문이 액세스할 모든 캡처된 변수 지정 는, b, 및 sum.이 예제에서는 매개 변수 목록을 1 차원 만듭니다 index 라는 변수 idx.값은 idx[0] 0에 첫 번째 스레드가 있고 각 후속 스레드를 1 씩 증가 합니다.restrict(amp) C + + AMP를 가속화할 수 있는 c + + 언어의 하위 집합만 사용 됨을 나타냅니다.제한 한정자가 있는 함수에는 제한 사항이 설명 되어 제약 조건 절 (AMP C++).자세한 내용은 람다 식 구문를 참조하십시오.

람다 식을 실행 하는 코드를 포함할 수 있습니다 또는 별도 커널 함수를 호출할 수 있습니다.커널 함수를 포함 해야의 restrict(amp) 한정자입니다.다음 예제는 이전 예제와 동일 하지만 별도 커널 함수를 호출 합니다.

#include <amp.h>
#include <iostream>
using namespace concurrency;

void AddElements(index<1> idx, array_view<int, 1> sum, array_view<int, 1> a, array_view<int, 1> b) restrict(amp)
{
    sum[idx] = a[idx] + b[idx];
}


void AddArraysWithFunction() {

    int aCPP[] = {1, 2, 3, 4, 5};
    int bCPP[] = {6, 7, 8, 9, 10};
    int sumCPP[5] = {0, 0, 0, 0, 0};

    array_view<int, 1> a(5, aCPP);
    array_view<int, 1> b(5, bCPP);
    array_view<int, 1> sum(5, sumCPP);

    parallel_for_each(
        sum.extent, 
        [=](index<1> idx) restrict(amp)
        {
            AddElements(idx, sum, a, b);
        }
    );

    for (int i = 0; i < 5; i++) {
        std::cout << sum[i] << "\n";
    }
}

기미가 코드: 타일 및 장애물

바둑판식 배열 사용 하 여 추가 가속을 얻을 수 있습니다.바둑판식 배열 같은 사각형 하위 집합으로 스레드를 분할 또는 타일.데이터 세트 및 코딩 하는 알고리즘을 기반으로 적절 한 타일 크기를 결정 합니다.액세스할 수 있는 각 스레드에 대 한의 글로벌 전체를 기준으로 데이터 요소의 위치 array 또는 array_view 및 액세스를 로컬 타일의 상대적인 위치.로컬에서 전역 인덱스 값을 변환 하는 코드를 작성 하지 않아도 되기 때문에 로컬 인덱스 값을 사용 하 여 코드를 단순화 합니다.바둑판식 배열 사용 하려면 호출의 extent::tile 메서드 계산 도메인에서 parallel_for_each 메서드를 사용 하 고는 tiled_index 람다 식에 대 한 개체.

일반적인 응용 프로그램 타일의 요소는 어떤 식으로든 관련 된 및 코드를 액세스 하 고 값에 걸쳐 분할을 추적할 수 있습니다.사용은 tile_static 키워드 키워드 및 tile_barrier::wait 메서드 이 작업을 수행 합니다.이 변수는 tile_static 키워드 범위는 전체 바둑판 전체와 각 타일에 대 한 인스턴스 변수를 만들.타일 스레드 변수에 대 한 액세스는 동기화를 처리 해야 합니다.tile_barrier::wait 메서드 타일 내의 모든 스레드가 호출에 도달할 때까지 현재 스레드 실행을 중지 tile_barrier::wait.값을 사용 하 여 타일에 누적 될 수 있으므로 tile_static 변수입니다.그런 다음 모든 값에 대 한 액세스가 필요한 모든 계산을 완료할 수 있습니다.

다음 다이어그램은 타일에 정렬 된 데이터를 샘플링 하는 2 차원 배열을 나타냅니다.

바둑판식 범위의 인덱스 값

다음 코드 예제에서는 이전 다이어그램에서 샘플링 데이터를 사용합니다.코드에서 타일 값의 평균으로 바둑판의 각 값을 대체합니다.

// Sample data:
int sampledata[] = {
    2, 2, 9, 7, 1, 4,
    4, 4, 8, 8, 3, 4,
    1, 5, 1, 2, 5, 2,
    6, 8, 3, 2, 7, 2};

// The tiles:
// 2 2    9 7    1 4
// 4 4    8 8    3 4
//
// 1 5    1 2    5 2
// 6 8    3 2    7 2

// Averages:
int averagedata[] = { 
    0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 
};

array_view<int, 2> sample(4, 6, sampledata);
array_view<int, 2> average(4, 6, averagedata);

parallel_for_each(
    // Create threads for sample.extent and divide the extent into 2 x 2 tiles.
    sample.extent.tile<2,2>(),
    [=](tiled_index<2,2> idx) restrict(amp)
    {
        // Create a 2 x 2 array to hold the values in this tile.
        tile_static int nums[2][2];
        // Copy the values for the tile into the 2 x 2 array.
        nums[idx.local[1]][idx.local[0]] = sample[idx.global];
        // When all the threads have executed and the 2 x 2 array is complete, find the average.
        idx.barrier.wait();
        int sum = nums[0][0] + nums[0][1] + nums[1][0] + nums[1][1];
        // Copy the average into the array_view.
        average[idx.global] = sum / 4;
      }
);

for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 6; j++) {
        std::cout << average(i,j) << " ";
    }
    std::cout << "\n";
}

// Output:
// 3 3 8 8 3 3
// 3 3 8 8 3 3
// 5 5 2 2 4 4
// 5 5 2 2 4 4

수학 라이브러리

C + + AMP 두 수학 라이브러리를 포함합니다.배정밀도 라이브러리에 있는 Concurrency::precise_math 네임스페이스 배정밀도 함수에 대 한 지원을 제공 합니다.배정밀도 지원 하드웨어도 필요 하지만 또한 단일 정밀도 함수에 대 한 지원을 제공 합니다.이 준수의 C99 사양 (ISO/IEC 9899).액셀러레이터 키 전체 배정밀도 지원 해야 합니다.값을 검사 하 여 작동 하는지 확인할 수 있는 accelerator::supports_double_precision 데이터 멤버.빠른 수학 라이브러리에는 Concurrency::fast_math 네임스페이스, 다른 수학 함수 집합을 포함 합니다.만 지 원하는 이러한 함수를 float 피연산자 보다 빠르게 실행 되지만 배정밀도 연산 라이브러리에는 정밀 하지 않은.<amp_math.h>에 들어 있는 함수는 헤더 파일 및 모든 선언 된 restrict(amp).<cmath>의 함수 헤더 파일을 모두 가져오는 있는 fast_mathprecise_math 네임 스페이스입니다.restrict 키워드를 사용 하 여 <cmath>를 구별 합니다. 버전 및 c + + AMP 버전입니다.연산 도메인에 있는 각 값의 빠른 메서드를 사용 하는 상용, 다음 코드를 계산 합니다.

#include <amp.h>
#include <amp_math.h>
#include <iostream>
using namespace concurrency;


void MathExample() {

    double numbers[] = { 1.0, 10.0, 60.0, 100.0, 600.0, 1000.0 };
    array_view<double, 1> logs(6, numbers);

    parallel_for_each(
        logs.extent,
         [=] (index<1> idx) restrict(amp) {
            logs[idx] = concurrency::fast_math::log10(logs[idx]);
        }
    );

    for (int i = 0; i < 6; i++) {
        std::cout << logs[i] << "\n";
    }
}

그래픽 라이브러리

C + + AMP 가속된 그래픽 프로그래밍에 대 한 설계 된 그래픽 라이브러리를 포함 합니다.이 라이브러리는 네이티브 그래픽 기능을 지 원하는 장치에만 사용 됩니다.메서드는 Concurrency::graphics 네임스페이스 <amp_graphics.h>에 포함 된 헤더 파일입니다.그래픽 라이브러리의 주요 구성 요소는 다음과 같습니다.

  • texture 클래스: 텍스처 클래스 메모리 나 파일에서 텍스처를 만들 수 있습니다.텍스처 배열에는 데이터를 포함 하 고 이러한 컨테이너에는 STL (표준 템플릿 라이브러리) 배정 및 복사 생성 유사 하기 때문에 유사 합니다.자세한 내용은 STL 컨테이너을 참조하십시오.에 대 한 템플릿 매개 변수는 texture 클래스에는 요소 형식 및 차수가.순위는 1, 2 또는 3 될 수 있습니다.요소 형식은이 문서 뒷부분에서 설명 하는 짧은 벡터 형식 중 하나를 수 있습니다.

  • writeonly_texture_view 클래스: 모든 질감을 쓰기 전용 액세스를 제공합니다.

  • 짧은 벡터 라이브러리: 2, 3 및 4에 따라 길이의 짧은 벡터 형식 집합을 정의 합니다. int, uint, float, double, 일반화, 또는 unorm.

Windows 스토어응용 프로그램

다른 c + + 라이브러리와 같은 c + + AMP를 사용 하 여 Windows 스토어 응용 프로그램.이러한 문서는 c + +, C#, Visual Basic 또는 Javascript를 사용 하 여 만든 c + + AMP 코드 응용 프로그램을 포함 하는 방법을 설명 합니다.

C + + AMP 및 동시성 시각화 도우미

동시성 시각화 도우미에는 AMP c + + 코드의 성능을 분석 하는 것에 대 한 지원이 포함 됩니다.이러한 기능은이 문서를 설명합니다.

성능 권장 사항

모듈러스와 부호 없는 정수 나누기 모듈러스와 부호 있는 정수 나누기 보다 월등히 뛰어난 성능을 했습니다.가능 하면 부호 없는 정수를 사용 하는 것이 좋습니다.

참고 항목

참조

람다 식 구문

기타 리소스

C++ AMP(C++ Accelerated Massive Parallelism)

참조(C++ AMP)

병렬 프로그래밍에서 네이티브 코드 블로그