Používání C++ AMP v aplikacích pro UPW

Pomocí C++ AMP (C++ Accelerated Massive Parallelism) v aplikaci pro Univerzální platformu Windows (UPW) můžete provádět výpočty s GPU (grafickým procesorem) nebo jinými výpočetními akcelerátory. C++ AMP ale neposkytuje rozhraní API pro práci přímo s typy prostředí Windows Runtime a prostředí Windows Runtime neposkytuje obálku pro C++ AMP. Pokud ve svém kódu používáte typy prostředí Windows Runtime včetně těch, které jste sami vytvořili, musíte je převést na typy kompatibilní s C++ AMP.

Poznámka:

Hlavičky C++ AMP jsou zastaralé od sady Visual Studio 2022 verze 17.0. Zahrnutím všech hlaviček AMP se vygenerují chyby sestavení. Před zahrnutím jakýchkoli hlaviček AMP definujte _SILENCE_AMP_DEPRECATION_WARNINGS, abyste ztlumili varování.

Důležité informace o výkonu

Pokud k vytvoření aplikace pro Univerzální platformu Windows (UWP) používáte rozšíření součástí Visual C++/CX, doporučujeme používat typy prostých starých dat (POD) společně se spojitým uložením dat, například std::vector nebo polem ve stylu C, pro data, která budou používána s C++ AMP. To vám může pomoci dosáhnout vyššího výkonu než při použití typů, které nejsou typu POD, nebo kontejnerů Windows Runtime, protože není nutné žádné marshaling.

Pokud chcete v kernelu C++ AMP přistupovat k datům uloženým tímto způsobem, stačí zabalit úložiště std::vector nebo pole do concurrency::array_view a poté použít zobrazení pole ve smyčce concurrency::parallel_for_each.

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

Zařazování typů prostředí Windows Runtime

Při práci s rozhraními API Windows Runtime můžete chtít použít C++ AMP u dat uložených v kontejneru Windows Runtime, takové jako Platform::Array<T>^ nebo v komplexních datových typech, jako jsou třídy nebo struktury deklarované pomocí klíčového slova ref nebo klíčového slova value. V těchto situacích musíte udělat další práci, aby byla data dostupná pro C++ AMP.

Platform::Array<T>^, kde T je typ POD

Když narazíte na typ podu Platform::Array<T>^ a T, můžete k příslušnému úložišti přistupovat pouze pomocí get členské funkce:

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

Pokud T není typ POD, použijte metodu popsanou v následující části k použití dat s C++ AMP.

Typy prostředí Windows Runtime: třídy ref a třídy hodnot

C++ AMP nepodporuje složité datové typy. To zahrnuje typy, které nejsou typy POD, a všechny typy, které jsou deklarovány pomocí klíčového slova ref nebo klíčového slova hodnota. Pokud se v restrict(amp) kontextu používá nepodporovaný typ, vygeneruje se chyba v době kompilace.

Když narazíte na nepodporovaný typ, můžete do objektu concurrency::array zkopírovat zajímavé části dat. Kromě zpřístupnění dat pro využití C++ AMP může tento postup manuálního kopírování zlepšit výkon maximalizací lokality dat a zajištěním, že data, která nebudou použita, nejsou kopírována do akcelerátoru. Výkon můžete dále zvýšit pomocí staging array, což je speciální forma concurrency::array, která poskytuje nápovědu runtime AMP, aby bylo pole optimalizováno pro častý přenos mezi ním a dalšími poli na určeném akcelerátoru.

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

Viz také

Vytvoření první aplikace pro UPW pomocí jazyka C++
Vytváření komponent prostředí Windows Runtime v jazyce C++