C++ AMP in UWP-Apps

Sie können C++ AMP (C++ Accelerated Massive Parallelism) in Ihrer Universelle Windows-Plattform (UWP)-App verwenden, um Berechnungen auf der GPU (Graphics Processing Unit) oder anderen Rechenbeschleunigern 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 sind ab Visual Studio 2022, Version 17.0, veraltet. Wenn Alle AMP-Header eingeschlossen werden, werden Buildfehler generiert. Definieren Sie _SILENCE_AMP_DEPRECATION_WARNINGS , bevor Sie AMP-Header einschließen, um die Warnungen zu stillen.

Überlegungen zur Leistung

Wenn Sie C++/CX-Komponentenerweiterungen von Visual C++/CX zum Erstellen Ihrer Universelle Windows-Plattform (UWP)-App verwenden, empfiehlt es sich, Nur-Old-Data-Typen (POD) zusammen mit zusammenhängenden Speichertypen ( z. B. C-Format- oder C-Stil-Arrays ) für Daten zu verwenden, std::vector die mit C++ AMP verwendet werden. Dies kann Ihnen helfen, eine höhere Leistung zu erzielen als bei Verwendung von Nicht-POD-Typen oder Windows-Runtime Containern, da keine 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];
    });

Marshallen von Windows-Runtime-Typen

Wenn Sie mit Windows-Runtime-APIs arbeiten, sollten Sie 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 Verweis-Schlüsselwort (keyword) oder des Werts Schlüsselwort (keyword) 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üsselwort (keyword) oder des Werts Schlüsselwort (keyword) 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 Stagingarray verwenden, bei dem es sich um eine spezielle Form handelt concurrency::array , die einen Hinweis auf die AMP-Laufzeit bietet, dass das Array für die häufige Übertragung zwischen dem Array und anderen Arrays auf der angegebenen Zugriffstaste 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++