다음을 통해 공유


UWP 앱에서 C++ AMP 사용

UWP(유니버설 Windows 플랫폼) 앱에서 C++ AMP(C++ 가속 대규모 병렬 처리)를 사용하여 GPU(그래픽 처리 장치) 또는 기타 계산 가속기에서 계산을 수행할 수 있습니다. 그러나, C++ AMP는 Windows Runtime 형식으로 직접 작업하기 위한 API를 제공하지 않으며, Windows 런타임은 C++ AMP에 대한 래퍼를 제공하지 않습니다. 코드(본인이 직접 만든 형식 포함)에 Windows 런타임 형식을 사용할 경우 C++ AMP와 호환되는 형식으로 변환해야 합니다.

참고 항목

C++ AMP 헤더는 Visual Studio 2022 버전 17.0부터 더 이상 사용되지 않습니다. AMP 헤더를 포함하면 빌드 오류가 생성됩니다. 경고를 무음으로 표시하기 위해 AMP 헤더를 포함하기 전에 정의 _SILENCE_AMP_DEPRECATION_WARNINGS 합니다.

성능 고려 사항

Visual C++ 구성 요소 확장 C++/CX를 사용하여 UWP(유니버설 Windows 플랫폼) 앱을 만드는 경우 C++ AMP와 함께 사용할 데이터에 대해 연속 스토리지(예std::vector: C 스타일 배열)와 함께 POD(일반 데이터) 형식을 사용하는 것이 좋습니다. 이렇게 하면 마샬링이 발생하지 않으므로 비 POD 형식 또는 Windows 런타임 컨테이너를 사용하는 것보다 더 높은 성능을 얻을 수 있습니다.

C++ AMP 커널에서 이러한 방식으로 저장된 데이터에 액세스하려면 배열 스토리지를 래 concurrency::array_viewstd::vector 한 다음 루프에서 배열 뷰를 concurrency::parallel_for_each 사용합니다.

// simple vector addition example
std::vector<int> data0(1024, 1);
std::vector<int> data1(1024, 2);
std::vector<int> data_out(data0.size(), 0);

concurrency::array_view<int, 1> av0(data0.size(), data0);
concurrency::array_view<int, 1> av1(data1.size(), data1);
concurrency::array_view<int, 1> av2(data_out.size(), data2);

av2.discard_data();

concurrency::parallel_for_each(av0.extent, [=](concurrency::index<1> idx) restrict(amp)
    {
        av2[idx] = av0[idx] + av1[idx];
    });

Windows 런타임 형식 마샬링

Windows 런타임 API를 사용하는 경우 ref 키워드 또는 값 키워드를 사용하여 선언된 클래스 또는 구조체와 같은 복잡한 데이터 형식과 같은 Platform::Array<T>^ Windows 런타임 컨테이너에 저장된 데이터에 C++ AMP를 사용할 수 있습니다. 이러한 상황에서는 C++ AMP에서 데이터를 사용할 수 있도록 몇 가지 추가 작업을 수행해야 합니다.

Platform::Array<T>^, 여기서 T는 POD 형식입니다.

T가 Platform::Array<T>^ POD 형식인 경우 멤버 함수를 사용하여 기본 스토리지에 get 액세스할 수 있습니다.

Platform::Array<float>^ arr; // Assume that this was returned by a Windows Runtime API
concurrency::array_view<float, 1> av(arr->Length, &arr->get(0));

T가 POD 형식이 아닌 경우 다음 섹션에 설명된 기술을 사용하여 C++ AMP에서 데이터를 사용합니다.

Windows 런타임 형식: ref 클래스 및 값 클래스

C++ AMP는 복잡한 데이터 형식을 지원하지 않습니다. 여기에는 POD가 아닌 형식과 ref 키워드 또는 값 키워드를 사용하여 선언된 모든 형식이 포함됩니다. 지원되지 않는 형식이 컨텍스트에서 restrict(amp) 사용되는 경우 컴파일 시간 오류가 생성됩니다.

지원되지 않는 형식이 발견되면 데이터의 흥미로운 부분을 개체에 복사할 concurrency::array 수 있습니다. 이 수동 복사 방법은 C++ AMP에서 데이터를 사용할 수 있도록 하는 것 외에도 데이터 지역성을 최대화하고 사용되지 않는 데이터가 가속기로 복사되지 않도록 하여 성능을 향상시킬 수 있습니다. 지정된 액셀러레이터에서 배열과 다른 배열 간의 빈번한 전송을 위해 배열을 최적화해야 한다는 힌트를 AMP 런타임에 제공하는 특별한 형식인 concurrency::array 스테이징 배열을 사용하여 성능을 더욱 향상시킬 수 있습니다.

// pixel_color.h
ref class pixel_color sealed
{
public:
    pixel_color(Platform::String^ color_name, int red, int green, int blue)
    {
        name = color_name;
        r = red;
        g = green;
        b = blue;
    }

    property Platform::String^ name;
    property int r;
    property int g;
    property int b;
};

// Some other file

std::vector<pixel_color^> pixels (256);

for (pixel_color ^pixel : pixels)
{
    pixels.push_back(ref new pixel_color("blue", 0, 0, 255));
}

// Create the accelerators
auto cpuAccelerator = concurrency::accelerator(concurrency::accelerator::cpu_accelerator);
auto devAccelerator = concurrency::accelerator(concurrency::accelerator::default_accelerator);

// Create the staging arrays
concurrency::array<float, 1> red_vec(256, cpuAccelerator.default_view, devAccelerator.default_view);
concurrency::array<float, 1>  blue_vec(256, cpuAccelerator.default_view, devAccelerator.default_view);

// Extract data from the complex array of structs into staging arrays.
concurrency::parallel_for(0, 256, [&](int i)
    {
        red_vec[i] = pixels[i]->r;
        blue_vec[i] = pixels[i]->b;
    });

// Array views are still used to copy data to the accelerator
concurrency::array_view<float, 1> av_red(red_vec);
concurrency::array_view<float, 1> av_blue(blue_vec);

// Change all pixels from blue to red.
concurrency::parallel_for_each(av_red.extent, [=](index<1> idx) restrict(amp)
    {
        av_red[idx] = 255;
        av_blue[idx] = 0;
    });

참고 항목

C++를 사용하여 첫 번째 UWP 앱 만들기
C++에서 Windows 런타임 구성 요소 만들기