Freigeben über


Verwenden von C++ AMP in UWP-Apps

Sie können C++ AMP (C++ Accelerated Massive Parallelism) in Ihrer UWP-App (Universelle Windows-Plattform) verwenden, um Berechnungen für die GPU (Grafikverarbeitungseinheit) oder andere Rechenbeschleuniger durchzuführen. C++ AMP stellt jedoch keine APIs für die direkte Arbeit mit Windows-Runtime-Typen bereit, und die Windows-Runtime stellt keinen Wrapper für C++ AMP bereit. Wenn Sie Windows-Runtime-Typen in Ihrem Code verwenden, einschließlich derjenigen, die Sie selbst erstellt haben, müssen Sie sie in Typen konvertieren, die mit C++ AMP kompatibel sind.

Hinweis

C++AMP-Header sind ab Visual Studio 2022, Version 17.0, veraltet. Wenn alle AMP-Header einbezogen werden, führt dies zu Buildfehlern. Definieren Sie _SILENCE_AMP_DEPRECATION_WARNINGS , bevor Sie AMP-Header einschließen, um die Warnungen zu stillen.

Leistungsüberlegungen

Wenn Sie C++/CX-Komponentenerweiterungen von Visual C++ zum Erstellen Ihrer UWP-App (Universelle Windows-Plattform) verwenden, empfehlen wir, Plain-Old-Data-Typen (POD) in Verbindung mit zusammenhängendem Speicher zu verwenden – zum Beispiel std::vector oder C-Stil-Arrays – für Daten, die mit C++ AMP genutzt werden sollen. Dies kann Ihnen helfen, eine höhere Leistung zu erzielen als bei der Verwendung von Nicht-POD-Typen oder Windows-Runtime-Containern, da kein Marshalling erforderlich ist.

Wenn Sie in einem C++-AMP-Kernel auf Daten zugreifen möchten, die auf diese Weise gespeichert sind, schließen Sie einfach den std::vector Speicher oder den Arrayspeicher in einer concurrency::array_view Schleife um, und verwenden Sie dann die Arrayansicht 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];
    });

Marshaling 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 Situationen müssen Sie zusätzliche Arbeit unternehmen, um die Daten für C++ AMP verfügbar zu machen.

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

Wenn T ein POD-Typ ist, können Sie mithilfe der get-Memberfunktion auf den zugrunde liegenden Speicher zugreifen:

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: Referenzklassen 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 Kompilierungszeitfehler generiert.

Wenn Sie auf einen nicht unterstützten Typ stoßen, können Sie interessante Teile seiner Daten in ein concurrency::array Objekt kopieren. Zusätzlich zu der Bereitstellung der Daten für die Verwendung durch C++ AMP kann dieser manuelle Kopieransatz auch die Leistung verbessern, indem er die Datenlokalität maximiert und sicherstellt, dass Daten, die nicht verwendet werden, nicht an den Beschleuniger kopiert werden. Sie können die Leistung weiter verbessern, indem Sie ein Stagingarray verwenden, welches die spezielle Form von concurrency::array ist, die einen Hinweis an die AMP Runtime bietet, dass das Array für die häufige Übertragung zwischen ihm und anderen Arrays auf dem spezifizierten Beschleuniger optimiert werden soll.

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

Siehe auch

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