Share via


C++ AMP gebruiken in UWP-apps

U kunt C++ AMP (C++ Accelerated Massive Parallelism) in uw UWP-app (Universal Windows Platform) gebruiken om berekeningen uit te voeren op de GPU (Graphics Processing Unit) of andere rekenkundige accelerators. C++ AMP biedt echter geen API's voor het rechtstreeks werken met Windows Runtime-typen en de Windows Runtime biedt geen wrapper voor C++ AMP. Wanneer u Windows Runtime-typen gebruikt in uw code, inclusief de typen die u zelf hebt gemaakt, moet u deze converteren naar typen die compatibel zijn met C++ AMP.

Opmerking

C++ AMP-headers worden afgeschaft vanaf Visual Studio 2022 versie 17.0. Als u AMP-headers opneemt, zullen er buildfouten optreden. Definieer _SILENCE_AMP_DEPRECATION_WARNINGS voordat u AMP-headers opneemt om de waarschuwingen te onderdrukken.

Prestatie-overwegingen

Als u Visual C++-onderdeelextensies C++/CX gebruikt om uw UWP-app (Universal Windows Platform) te maken, raden we u aan om POD-typen (plain-old-data) te gebruiken samen met aaneengesloten opslag, zoals bijvoorbeeld C-stijl arrays, voor gegevens die worden gebruikt met C++ AMP. Dit kan u helpen hogere prestaties te bereiken dan door niet-POD-typen of Windows Runtime-containers te gebruiken, omdat er geen marshaling hoeft te gebeuren.

In een C++ AMP-kernel kunt u toegang krijgen tot gegevens die op deze manier zijn opgeslagen, verpakt u de std::vector of matrixopslag in een concurrency::array_view en gebruikt u vervolgens de matrixweergave in een concurrency::parallel_for_each lus:

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

Het marshallen van Windows Runtime-typen

Wanneer u met Windows Runtime-API's werkt, wilt u mogelijk C++ AMP gebruiken voor gegevens die zijn opgeslagen in een Windows Runtime-container, zoals een Platform::Array<T>^ of in complexe gegevenstypen, zoals klassen of structs die worden gedeclareerd met behulp van het trefwoord verw of het waardewoord . In deze situaties moet u wat extra werk doen om de gegevens beschikbaar te maken voor C++ AMP.

Platform::Array<T>^, waarbij T een POD-type is

Wanneer u een Platform::Array<T>^ tegenkomt en T een POD-type is, hebt u toegang tot de onderliggende opslag alleen met de get lidfunctie:

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

Als T geen POD-type is, gebruikt u de techniek die wordt beschreven in de volgende sectie om de gegevens te gebruiken met C++ AMP.

Typen Windows Runtime: referentieklassen en waardeklassen

C++ AMP biedt geen ondersteuning voor complexe gegevenstypen. Dit omvat niet-POD-typen en alle typen die worden gedeclareerd met behulp van het trefwoord ref of het trefwoord waarde. Als een niet-ondersteund type wordt gebruikt in een restrict(amp) context, wordt er een compilatiefout gegenereerd.

Wanneer u een niet-ondersteund type tegenkomt, kunt u interessante delen van de gegevens naar een concurrency::array object kopiƫren. Naast het beschikbaar maken van de gegevens die C++ AMP kan gebruiken, kan deze methode voor handmatig kopiƫren ook de prestaties verbeteren door de locatie van gegevens te maximaliseren en ervoor te zorgen dat gegevens die niet worden gebruikt, niet naar de accelerator worden gekopieerd. U kunt de prestaties verder verbeteren door gebruik te maken van een tussenstappenarray, wat een speciale vorm is die aan de AMP-runtime aangeeft dat de array geoptimaliseerd moet worden voor regelmatige overdracht tussen deze en andere arrays op de opgegeven accelerator.

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

Zie ook

Uw eerste UWP-app maken met C++
Windows Runtime-onderdelen maken in C++