Freigeben über


C++ AMP in UWP-Apps

Sie können C++ AMP (C++ Accelerated Massive Parallelism) in Ihrer Universal Windows Platform (UWP)-App verwenden, um Berechnungen auf der GPU (Graphics Processing Unit) oder anderen Berechnungsbeschleunigern durchzuführen. bietet jedoch keine APIs, um mit Windows-Runtime-Typen direkt zu arbeiten, und die Windows-Runtime stellt keinen Wrapper für bereit. Wenn Sie Windows-Runtime-Typen im Code verwenden (einschließlich selbst erstellter), müssen sie in Typen konvertiert werden, die mit kompatibel sind.

Hinweis

C++ AMP-Header werden ab Visual Studio 2022 Version 17.0 veraltet sein. Das Einfügen von AMP-Headern führt zu Erstellungsfehlern. Definiert _SILENCE_AMP_DEPRECATION_WARNINGS, bevor Sie AMP-Header einfügen, um die Warnungen zu unterdrücken.

Überlegungen zur Leistung

Wenn Sie Visual C++-Komponentenerweiterungen C++/CX verwenden, um Ihre Universal Windows Platform (UWP)-App zu erstellen, empfehlen wir Ihnen, für Daten, die mit C++ AMP verwendet werden, POD-Typen (Plain Old Data) zusammen mit zusammenhängendem Speicherplatz zu verwenden, z. B. std::vector oder Arrays im C-Stil. Dadurch können Sie eine höhere Leistung erzielen als durch die Verwendung von Nicht-POD-Typen oder Windows Runtime-Containern, da kein Marshaling stattfinden muss.

Um in einem C++ AMP-Kernel auf Daten zuzugreifen, die auf diese Weise gespeichert wurden, müssen Sie nur den std::vector- oder Arrayspeicher in einer concurrency::array_view und verwenden die Arrayansicht dann in einer concurrency::parallel_for_each-Schleife:

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

Marshallen von Windows-Runtime-Typen

Wenn Sie mit Windows-Runtime-APIs arbeiten, möchten Sie möglicherweise C++ AMP für Daten verwenden, die in einem Windows-Runtime-Container gespeichert sind, z. B. in komplexen Platform::Array<T>^ Datentypen wie Klassen oder Strukturen, die mithilfe des Ref-Schlüsselworts oder des Wertschlüsselworts deklariert werden. In diesen Fällen ist zusätzliche Arbeit erforderlich, um die Daten für C++ AMP verfügbar zu machen.

Platform::Array<T>^, wobei T ein POD-Typ ist

Wenn ein Platform::Array<T>^ auftritt und T ein POD-Typ ist, können Sie auf den zugrunde liegenden Speicher zugreifen, indem Sie die get-Memberfunktion verwenden:

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

Wenn T kein POD-Typ ist, verwenden Sie die im folgenden Abschnitt beschriebene Technik, um die Daten mit C++ AMP zu verwenden.

Windows-Runtime-Typen: Verweisklassen und Wertklassen

C++ AMP unterstützt keine komplexen Datentypen. Dazu gehören nicht-POD-Typen und alle Typen, die mithilfe des Ref-Schlüsselworts oder des Wertschlüsselworts deklariert werden. Wenn ein nicht unterstützter Typ in einem restrict(amp)-Kontext verwendet wird, wird ein Kompilierzeitfehler generiert.

Wenn ein nicht unterstützter Typ auftritt, können Sie die interessanten Teile seiner Daten in ein concurrency::array-Objekt kopieren. Mit diesem Ansatz des manuellen Kopierens werden nicht nur die Daten für C++ AMP verfügbar gemacht. Er kann zusätzlich die Leistung verbessern, indem der Datenort maximiert und sichergestellt wird, dass Daten, die nicht verwendet werden, nicht in den Beschleuniger kopiert werden. Sie können die Leistung weiter verbessern, indem Sie ein Staging-Array verwenden. Dabei handelt es sich um eine spezielle Form von concurrency::array, die der AMP Runtime einen Hinweis gibt, dass das Array für häufige Übertragungen zwischen ihm und anderen Arrays auf dem angegebenen Beschleuniger optimiert werden sollte.

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

Weitere Informationen

Erstellen Ihrer ersten UWP-App mit C++
Erstellen von Komponenten für Windows-Runtime in C++