Использование C++ AMP в приложениях UWP

Вы можете использовать C++ AMP (C++ Accelerated Massive Parallelism) в приложении универсальной платформы Windows (UWP) для выполнения вычислений на GPU (единице обработки графики) или других вычислительных акселераторов. Однако C++ AMP не предоставляет API для работы непосредственно с типами среды выполнения Windows, а среда выполнения Windows не предоставляет оболочку для C++ AMP. При использовании типов среды выполнения Windows в коде, включая созданные самостоятельно, необходимо преобразовать их в типы, совместимые с C++ AMP.

Замечание

Заголовки C++ AMP устарели начиная с Visual Studio 2022 версии 17.0. Включение любых заголовков AMP приведет к возникновению ошибок сборки. Определите _SILENCE_AMP_DEPRECATION_WARNINGS перед включением всех заголовков AMP, чтобы подавить предупреждения.

Вопросы производительности

Если вы используете расширения компонентов Visual C++/CX для создания приложения универсальной платформы Windows (UWP), рекомендуется использовать типы обычных данных (POD) вместе с непрерывным хранилищем ( например, std::vector массивами стилей C++) для данных, которые будут использоваться с C++ AMP. Это может помочь добиться более высокой производительности, чем при использовании типов, отличных от POD, или контейнеров в среде выполнения Windows Runtime, потому что маршалирование не требуется.

В ядре AMP C++ для доступа к данным, хранящимся таким образом, просто оберните std::vector хранилище или хранилище массивов в concurrency::array_view и затем используйте представление массива в цикле 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

При работе с API среды выполнения Windows может потребоваться использовать C++ AMP для данных, хранящихся в контейнере среды выполнения Windows, например в Platform::Array<T>^ или в сложных типах данных, таких как классы или структуры, объявленные с помощью ключевого слова ref или ключевого слова value. В таких ситуациях необходимо выполнить дополнительную работу, чтобы сделать данные доступными для C++ AMP.

Platform::Array<T>^, где T является типом POD

При обнаружении Platform::Array<T>^, и если 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: ссылочные классы и классы значений

C++ AMP не поддерживает сложные типы данных. Это включает типы, отличные от типов POD, и любые типы, объявленные с помощью ключевого слова ref или value. Если неподдерживаемый тип используется в restrict(amp) контексте, создается ошибка во время компиляции.

Когда вы сталкиваетесь с неподдерживаемым типом, можно скопировать интересные части его данных в concurrency::array объект. Помимо обеспечения доступности данных для использования C++ AMP, этот подход к копированию вручную также может повысить производительность, максимизуя локальность данных, и гарантируя, что данные, которые не будут использоваться, не копируются в акселератор. Кроме того, можно повысить производительность с помощью промежуточногоconcurrency::array массива, который представляет собой специальную форму, которая указывает среде выполнения AMP, что массив должен быть оптимизирован для частой передачи между ним и другими массивами на указанном акселераторе.

// 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;
    });

См. также

Создание первого приложения UWP с помощью C++
Создание компонентов среды выполнения Windows на C++