Používání modelu C++ AMP v aplikacích pro UPW
Pomocí C++ AMP (C++ Accelerated Massive Parallelism) v aplikaci Univerzální platforma 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. Při použití prostředí Windows Runtime typů v kódu ( včetně těch, které jste sami vytvořili), je nutné je převést na typy, které jsou 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 záhlaví AMP definujte _SILENCE_AMP_DEPRECATION_WARNINGS
upozornění.
Důležité informace o výkonu
Pokud k vytvoření aplikace Univerzální platforma Windows (UPW) používáte rozšíření komponent jazyka Visual C++/CX, doporučujeme pro data, std::vector
která se budou používat s C++ AMP, používat typy prostých starých dat (POD). To vám může pomoct dosáhnout vyššího výkonu, než když použijete jiné typy než pod nebo prostředí Windows Runtime kontejnery, protože k zařazování nedojde.
Pokud chcete získat přístup k datům uloženým tímto způsobem, stačí v jádru C++ AMP zabalit std::vector
úložiště pole do concurrency::array_view
pole a pak 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ů modulu Windows Runtime
Při práci s rozhraními API prostředí Windows Runtime můžete chtít použít C++ AMP u dat uložených v kontejneru prostředí Windows Runtime, jako Platform::Array<T>^
jsou třídy nebo struktury deklarované pomocí klíčového slova ref nebo klíčového slova hodnoty. 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 modulu Windows Runtime: třídy deklarované s použitím klíčových slov ref a value
C++ AMP nepodporuje složité datové typy. To zahrnuje typy bez podu a všechny typy, které jsou deklarovány pomocí klíčového slova odkaz nebo klíčového slova hodnoty . 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 přístup ručního kopírování zvýšit výkon také maximalizací umístění dat a zajištěním toho, aby se data, která se do akcelerátoru nezkopírují, se nezkopírují. Výkon můžete dále zlepšit pomocí přípravného pole, což je speciální forma concurrency::array
, která poskytuje nápovědu pro modul runtime AMP, který má být pole optimalizováno pro častý přenos mezi ním a dalšími poli v zadané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++