Partager via


Utilisation de C++ AMP dans les applications UWP

Vous pouvez utiliser C++ AMP (C++ Accelerated Massive Parallelism) dans votre application plateforme Windows universelle (UWP) pour effectuer des calculs sur le GPU (Unité de traitement graphique) ou d’autres accélérateurs de calcul. Toutefois, C++ AMP ne fournit pas d’API pour travailler directement avec les types Windows Runtime, et Windows Runtime ne fournit pas de wrapper pour C++ AMP. Lorsque vous utilisez des types Windows Runtime dans votre code, y compris ceux que vous avez créés vous-même, vous devez les convertir en types compatibles avec C++ AMP.

Remarque

Les en-têtes AMP C++ sont déconseillés à partir de Visual Studio 2022 version 17.0. L’inclusion d’en-têtes AMP génère des erreurs de génération. Définissez _SILENCE_AMP_DEPRECATION_WARNINGS avant d’inclure tous les en-têtes AMP pour silence les avertissements.

Considérations relatives aux performances

Si vous utilisez des extensions de composant Visual C++ C++C+/CX pour créer votre application plateforme Windows universelle (UWP), nous vous recommandons d’utiliser des types pod (plain-old-data) avec un stockage contigu( par exemple, std::vector ou des tableaux de style C) pour les données qui seront utilisées avec C++ AMP. Cela peut vous aider à obtenir des performances plus élevées qu’à l’aide de types non POD ou de conteneurs Windows Runtime, car aucun marshaling n’a lieu.

Dans un noyau AMP C++, pour accéder aux données stockées de cette façon, il vous suffit d’encapsuler le std::vector stockage ou le stockage de tableau dans une concurrency::array_view boucle, puis d’utiliser l’affichage tableau dans une concurrency::parallel_for_each boucle :

// 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 des types Windows Runtime

Lorsque vous utilisez des API Windows Runtime, vous pouvez utiliser C++ AMP sur les données stockées dans un conteneur Windows Runtime tel qu’un Platform::Array<T>^ ou dans des types de données complexes tels que des classes ou des structs déclarés à l’aide de la référence mot clé ou de la valeur mot clé. Dans ces situations, vous devez effectuer un travail supplémentaire pour rendre les données disponibles pour C++ AMP.

Platform ::Array<T>^, où T est un type POD

Lorsque vous rencontrez un Platform::Array<T>^ type POD et T, vous pouvez accéder à son stockage sous-jacent à l’aide de la get fonction membre :

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

Si T n’est pas un type POD, utilisez la technique décrite dans la section suivante pour utiliser les données avec C++ AMP.

Types Windows Runtime : classes de référence et classes de valeur

L’AMP C++ ne prend pas en charge les types de données complexes. Cela inclut les types non POD et tous les types déclarés à l’aide de la référence mot clé ou de la valeur mot clé. Si un type non pris en charge est utilisé dans un restrict(amp) contexte, une erreur au moment de la compilation est générée.

Lorsque vous rencontrez un type non pris en charge, vous pouvez copier des parties intéressantes de ses données dans un concurrency::array objet. En plus de rendre les données disponibles pour C++ AMP, cette approche de copie manuelle peut également améliorer les performances en optimisant la localité des données et en garantissant que les données qui ne seront pas utilisées ne seront pas copiées dans l’accélérateur. Vous pouvez améliorer les performances en utilisant un tableau intermédiaire, qui est une forme spéciale de concurrency::array ce qui fournit un indicateur au runtime AMP que le tableau doit être optimisé pour un transfert fréquent entre celui-ci et d’autres tableaux sur l’accélérateur spécifié.

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

Voir aussi

Créer votre première application UWP à l’aide de C++
Création de composants Windows Runtime en C++