Přehled produktu C++ AMP
Knihovna C++ Accelerated Massive Parallelism (C++ AMP) urychluje provádění kódu jazyka C++ využitím hardwaru, umožňujícím paralelní zpracování dat, jako například grafického procesoru (GPU) na samostatné grafické kartě.Pomocí knihovny C++ AMP lze vytvořit kód algoritmů pracujících s vícerozměrnými daty tak, že jejich provádění bude urychleno pomocí paralelismu na heterogenním hardwaru.Model programování knihovny C++ AMP zahrnuje vícerozměrná pole, indexování, přenos paměti, rozložení a knihovnu matematických funkcí.Jazyková rozšíření, obsažená v knihovně C++ AMP, lze použít pro ovládání toho, jak jsou data přenášena z procesoru do GPU a zpět, a tak zvýšit výkon.
Požadavky na systém
Windows 7, Windows 8, Windows Server 2008 R2, nebo Windows Server 2012
Rozhraní DirectX 11 úroveň funkce 11.0 nebo novější hardware
Pro ladění v softwarovém emulátoru je vyžadován systém Windows 8 nebo systém Windows Server 2012.Pro ladění na hardwaru je nutné nainstalovat ovladače pro grafickou kartu.Další informace naleznete v tématu Ladění kódu GPU.
Úvod
Následující dva příklady ilustrují primární součásti knihovny C++ AMP.Předpokládejme, že je třeba přidat odpovídající prvky dvou jednorozměrných polí.Například může být třeba přidat pole {1, 2, 3, 4, 5} a pole {6, 7, 8, 9, 10} pro získání pole {7, 9, 11, 13, 15}.Bez použití knihovny C++ AMP lze kód pro přidání čísel a zobrazení výsledků zapsat následně.
#include <iostream>
void StandardMethod() {
int aCPP[] = {1, 2, 3, 4, 5};
int bCPP[] = {6, 7, 8, 9, 10};
int sumCPP[5];
for (int idx = 0; idx < 5; idx++)
{
sumCPP[idx] = aCPP[idx] + bCPP[idx];
}
for (int idx = 0; idx < 5; idx++)
{
std::cout << sumCPP[idx] << "\n";
}
}
Důležité části kódu jsou:
Data: Data obsahují tři pole.Všechny mají stejný počet rozměrů (jeden) a délku (pět).
Iterace: První smyčka for poskytuje mechanismus pro procházení prvků v polích.Kód, který bude třeba spustit pro výpočet součtu, je obsažen v prvním bloku smyčky for.
Index: Proměnná idx umožňuje přístup k jednotlivým prvkům polí.
Použitím knihovny C++ AMP lze kód přepsat následujícím způsobem.
#include <amp.h>
#include <iostream>
using namespace concurrency;
const int size = 5;
void CppAmpMethod() {
int aCPP[] = {1, 2, 3, 4, 5};
int bCPP[] = {6, 7, 8, 9, 10};
int sumCPP[size];
// Create C++ AMP objects.
array_view<const int, 1> a(size, aCPP);
array_view<const int, 1> b(size, bCPP);
array_view<int, 1> sum(size, sumCPP);
sum.discard_data();
parallel_for_each(
// Define the compute domain, which is the set of threads that are created.
sum.extent,
// Define the code to run on each thread on the accelerator.
[=](index<1> idx) restrict(amp)
{
sum[idx] = a[idx] + b[idx];
}
);
// Print the results. The expected output is "7, 9, 11, 13, 15".
for (int i = 0; i < size; i++) {
std::cout << sum[i] << "\n";
}
}
Jsou k dispozici stejné základní prvky, ale jsou použity konstrukce knihovny C++ AMP:
Data: Pro tvorbu tří objektů typu array_view knihovny C++ AMP jsou použita pole jazyka C++.Pro tvorbu objektu typu array_view je třeba zadat čtyři hodnoty: datové hodnoty, počet rozměrů, typ elementu a délku objektu typu array_view v každém rozměru.Počet rozměrů a typ jsou předány jako parametry typu.Data a délka jsou předány jako parametry konstruktoru.V tomto příkladu je pole jazyka C++, které je předáno konstruktoru, jednorozměrné.Počet rozměrů a délka jsou v objektu typu array_view použity k tvorbě obdélníkového tvaru dat a datové hodnoty jsou použity k vyplnění pole.Běhová knihovna také zahrnuje třídu array – třída, která má podobné rozhraní jako třída array_view, která je popsána dále v tomto článku.
Iterace: Funkce parallel_for_each – funkce (C++ AMP) poskytuje mechanismus pro procházení datových prvků, neboli výpočetní domény.V tomto příkladu je výpočetní doména zadána pomocí sum.extent.Kód, který je třeba spustit, je obsažen ve výrazu lambda, nebo ve funkci jádra.Modifikátor restrict(amp) určuje, že je použita pouze podmnožina jazyka C++, kterou může knihovna C++ AMP urychlit.
Index: Proměnná struktury index – třída, idx, je deklarována s rozměrem jedna, aby odpovídala rozměru objektu typu array_view.Pomocí indexu lze přistupovat k jednotlivým prvkům objektu typu array_view.
Tvarování a indexování dat: index a rozsah
Před spuštěním kódu jádra je třeba definovat hodnoty dat a deklarovat tvar dat.Všechna data jsou definována v poli (obdélníkovém) a pole lze definovat tak, že může mít jakékoliv řazení (počet rozměrů).Data mohou mít libovolnou velikost a mít libovolný počet rozměrů.
Třída index
Struktura index – třída určuje umístění v objektu typu array či v objektu typu array_view zapouzdřením posunu od začátku v každém rozměru do jediného objektu.Při přístupu k umístění v poli je třeba namísto seznamu celočíselných indexů indexujícímu operátoru [] předat objekt typu index.K elementům lze v každém rozměru přistupovat pomocí operátoru array::operator() – operátor či pomocí operátoru array_view::operator() – operátor.
Následující příklad vytvoří jednorozměrný index, který určuje třetí prvek v jednorozměrném objektu typu array_view.Index je použit ke zobrazení třetího prvku objektu array_view.Výstup je 3.
int aCPP[] = {1, 2, 3, 4, 5};
array_view<int, 1> a(5, aCPP);
index<1> idx(2);
std::cout << a[idx] << "\n";
// Output: 3
Následující příklad vytváří dvojrozměrný index, který určuje prvek, který je v dvourozměrném objektu typu array_view na řádku 1 a ve sloupci 2.První parametr v konstruktoru typu index reprezentuje řádek a druhý parametr zase sloupec.Výstup je 6.
int aCPP[] = {1, 2, 3,
4, 5, 6};
array_view<int, 2> a(2, 3, aCPP);
index<2> idx(1, 2);
std::cout << a[idx] << "\n";
// Output: 6
Následující příklad vytvoří trojrozměrný index, který určuje prvek, který je v trojrozměrném objektu typu array_view umístěn v hloubce 0, na řádku 1 a ve sloupci 3.Všimněte si, že první parametr je hloubka, druhý parametr řádek a třetí parametr je sloupec.Výstup je 8.
int aCPP[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
array_view<int, 3> a(2, 3, 4, aCPP);
// Specifies the element at 3, 1, 0.
index<3> idx(0, 1, 3);
std::cout << a[idx] << "\n";
// Output: 8
Třída extent
Struktura extent – třída (C++ AMP) určuje délku dat v každém rozměru objektu typu array nebo objektu typu array_view.Lze vytvořit rozsah a použít jej pro vytvoření objektu array či objektu array_view.Je také možné získat rozsah existujícího objektu typu array či objektu typu array_view.Následující příklad vytiskne délku rozsahu v každém rozměru objektu array_view.
int aCPP[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
// There are 3 rows and 4 columns, and the depth is two.
array_view<int, 3> a(2, 3, 4, aCPP);
std::cout << "The number of columns is " << a.extent[2] << "\n";
std::cout << "The number of rows is " << a.extent[1] << "\n";
std::cout << "The depth is " << a.extent[0]<< "\n";
std::cout << "Length in most significant dimension is " << a.extent[0] << "\n";
V následujícím příkladu je vytvořen objekt typu array_view, který má stejné rozměry jako objekt v předchozím příkladu, ale v tomto příkladu je namísto použití explicitních parametrů v konstruktoru typu array_view použit objekt typu extent.
int aCPP[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
extent<3> e(2, 3, 4);
array_view<int, 3> a(e, aCPP);
std::cout << "The number of columns is " << a.extent[2] << "\n";
std::cout << "The number of rows is " << a.extent[1] << "\n";
std::cout << "The depth is " << a.extent[0] << "\n";
Přesun dat na akcelerátor: array a array_view
Pro použití pro přesun dat do akcelerátoru jsou v běhové knihovně definovány dva datové kontejnery.Jedná se o třídu array – třída a třídu array_view – třída.Třída array je třídou kontejneru, která při vytvoření objektu vytvoří hlubokou kopii dat.Třída array_view je třídou obálky, která zkopíruje data při přístupu funkce jádra k nim.Při potřebě dat na zdrojovém zařízení jsou data zkopírována zpět.
Třída array
Pokud je použit konstruktor, který obsahuje ukazatel na sadu dat, je při vytvoření objektu typu array v akcelerátoru vytvořena hluboká kopie dat.Funkce jádra modifikuje kopii v akcelerátoru.Po dokončení spuštění funkce jádra je třeba zkopírovat data zpět do struktury zdrojových dat.Následující příklad vynásobí desíti každý prvek vektoru.Po dokončení funkce jádra je pro zkopírování dat zpět do objektu vektoru použit operátor převodu vektoru.
std::vector<int> data(5);
for (int count = 0; count < 5; count++)
{
data[count] = count;
}
array<int, 1> a(5, data.begin(), data.end());
parallel_for_each(
a.extent,
[=, &a](index<1> idx) restrict(amp)
{
a[idx] = a[idx] * 10;
}
);
data = a;
for (int i = 0; i < 5; i++)
{
std::cout << data[i] << "\n";
}
Třída array_view
Třída array_view má téměř stejné členy jako třída array, ale základní chování stejné není.Data předaná do konstruktoru třídy array_view nejsou v GPU replikována tak jako v konstruktoru třídy array.Místo toho jsou data při provádění funkce jádra zkopírována na akcelerátor.Proto pokud jsou vytvořeny dva objekty typu array_view, které používají stejná data, oba objekty typu array_view budou odkazovat do stejného paměťového prostoru.Při tomto provedení je třeba synchronizovat vícevláknový přístup.Hlavní výhodou používání třídy array_view je to, že jsou data přesunuta pouze v případě, kdy je to nezbytné.
Porovnání třídy array a třídy array_view
Následující tabulka shrnuje podobnosti a rozdíly mezi třídou array a třídou array_view.
Description |
třída array |
třída array_view |
---|---|---|
Kdy je určen počet rozměrů |
V době kompilace. |
V době kompilace. |
Kdy je stanoven rozsah |
V době běhu. |
V době běhu. |
Tvar |
Obdélníkový. |
Obdélníkový. |
Úložiště dat |
Je kontejner dat. |
Je obálka dat. |
Kopírovat |
Explicitní a hluboká kopie při definici. |
Implicitní kopie při přístupu z funkce jádra. |
Načítání dat |
Kopírování dat pole zpět do objektu ve vlákně procesoru. |
Pomocí přímého přístupu objektu typu array_view, nebo pomocí volání metody array_view::synchronize – metoda pro pokračování přístupu k datům v původním kontejneru. |
Sdílená paměť s objekty array a array_view
Sdílená paměť je paměť, ke které lze přistupovat pomocí procesoru a akcelerátoru.Použití sdílené paměti eliminuje nebo významně snižuje režijní náklady na kopírování dat mezi procesorem a akcelerátorem.I když je paměť sdílená, nelze k ní přistupovat zároveň z procesoru a akcelerátoru. Došlo by k nedefinovanému chování.
Objekty array lze použít k určení jemně odstupňovaného ovládání využití sdílené paměti, pokud to umožňuje přidružený akcelerátor.Zda akcelerátor podporuje sdílenou paměť, určuje vlastnost supports_cpu_shared_memory akcelerátoru, která vrací true, pokud je podporována sdílená paměť.Pokud je podporována sdílená paměť, výchozí access_type – výčet pro přidělení paměti v akcelerátoru je určen vlastností default_cpu_access_type.Ve výchozím nastavení objekty array a array_view trvají na stejném access_type jako primárně spojený accelerator.
Nastavením vlastnosti array::cpu_access_type Data – datový člen explicitně pro array si můžete procvičit jemné doladění řízení nad použitou sdílenou pamětí, abyste mohli optimalizovat aplikace pro výkonnostní charakteristiky hardwaru na základě vzorců přístupu k paměti pro její výpočetní jádra.array_view odráží stejné cpu_access_type jako array, se kterým je přidruženo; nebo, není-li objekt array_view konstruován beze zdroje dat, jeho access_type odráží prostředí, které nejprve vyvolá přidělení úložiště.To znamená, pokud je nejprve otevřen hostitelem (CPU), pak se chová jako by byl vytvořen ze zdrojů dat procesoru a sdílí access_type z accelerator_view spojeného při vzniku. Pokud je však nejprve otevřen accelerator_view, pak se chová, jako by byl vytvořen z array vytvořeném u tohoto accelerator_view a sdílí access_type objektu array.
Následující příklad kódu ukazuje, jak určit, zda výchozí akcelerátor podporuje sdílenou paměť a potom vytvoří několik polí, která mají různou konfiguraci cpu_access_type.
#include <amp.h>
#include <iostream>
using namespace Concurrency;
int main()
{
accelerator acc = accelerator(accelerator::default_accelerator);
// Early out if the default accelerator doesn’t support shared memory.
if (!acc.supports_cpu_shared_memory)
{
std::cout << "The default accelerator does not support shared memory" << std::endl;
return 1;
}
// Override the default CPU access type.
acc.default_cpu_access_type = access_type_read_write
// Create an accelerator_view from the default accelerator. The
// accelerator_view inherits its default_cpu_access_type from acc.
accelerator_view acc_v = acc.default_view;
// Create an extent object to size the arrays.
extent<1> ex(10);
// Input array that can be written on the CPU.
array<int, 1> arr_w(ex, acc_v, access_type_write);
// Output array that can be read on the CPU.
array<int, 1> arr_r(ex, acc_v, access_type_read);
// Read-write array that can be both written to and read from on the CPU.
array<int, 1> arr_rw(ex, acc_v, access_type_read_write);
}
Provádění kódu nad daty: parallel_for_each
Funkce Parallel_for_each definuje kód, který je třeba provést v akcelerátoru nad daty v objektu typu array či objektu typu array_view.Vezměme v potaz následující kód z úvodu tohoto tématu.
#include <amp.h>
#include <iostream>
using namespace concurrency;
void AddArrays() {
int aCPP[] = {1, 2, 3, 4, 5};
int bCPP[] = {6, 7, 8, 9, 10};
int sumCPP[5] = {0, 0, 0, 0, 0};
array_view<int, 1> a(5, aCPP);
array_view<int, 1> b(5, bCPP);
array_view<int, 1> sum(5, sumCPP);
parallel_for_each(
sum.extent,
[=](index<1> idx) restrict(amp)
{
sum[idx] = a[idx] + b[idx];
}
);
for (int i = 0; i < 5; i++) {
std::cout << sum[i] << "\n";
}
}
Metoda parallel_for_each přebírá dva argumenty, výpočetní doménu a výraz lambda.
Výpočetní doména je objektem typu extent nebo objektem typu tiled_extent, který definuje sadu vláken pro vytvoření pro paralelní provedení.Pro každý prvek ve výpočetní doméně je generováno jedno vlákno.V tomto případě je objekt typu extent jednorozměrný a má pět prvků.Proto je spuštěno pět vláken.
Výraz lambda definuje kód, který má být v každém vlákně spuštěn.Klauzule sběru [=] určuje to, že tělo výrazu lambda přistupuje ke všem zachyceným proměnným pomocí hodnoty, které jsou v tomto případě a, b a sum.V tomto příkladu vytváří seznam parametrů jednorozměrnou proměnnou typu index nazvanou idx.Hodnota idx[0] je v prvním vlákně nula a v každém následném vlákně se o jednu zvyšuje.Modifikátor restrict(amp) určuje, že je použita pouze podmnožina jazyka C++, kterou může knihovna C++ AMP urychlit. Omezení ve funkcích, které obsahují modifikátor restrict, jsou popsány v Klauzule omezení (C++ AMP).Další informace naleznete v tématu Syntaxe výrazu lambda.
Výraz lambda může obsahovat kód pro spuštění, nebo může volat samostatnou funkci jádra.Funkce jádra musí zahrnovat modifikátor restrict(amp).Následující příklad je ekvivalentní k předchozímu, ale volá samostatnou funkci jádra.
#include <amp.h>
#include <iostream>
using namespace concurrency;
void AddElements(index<1> idx, array_view<int, 1> sum, array_view<int, 1> a, array_view<int, 1> b) restrict(amp)
{
sum[idx] = a[idx] + b[idx];
}
void AddArraysWithFunction() {
int aCPP[] = {1, 2, 3, 4, 5};
int bCPP[] = {6, 7, 8, 9, 10};
int sumCPP[5] = {0, 0, 0, 0, 0};
array_view<int, 1> a(5, aCPP);
array_view<int, 1> b(5, bCPP);
array_view<int, 1> sum(5, sumCPP);
parallel_for_each(
sum.extent,
[=](index<1> idx) restrict(amp)
{
AddElements(idx, sum, a, b);
}
);
for (int i = 0; i < 5; i++) {
std::cout << sum[i] << "\n";
}
}
Urychlování kódu: Dlaždice a překážky
Další zrychlení lze získat pomocí rozložení.Rozložení rozděluje vlákna v rovnocenné obdélníkové podmnožiny neboli dlaždice.Velikost odpovídající dlaždice určuje programátor na základě sady dat a algoritmu, který je jím vytvářen.Pro každé vlákno je umožněn přístup ke globálnímu umístění datového prvku, relativnímu k celému objektu typu array, či objektu typu array_view, a přístup k místnímu umístění, relativnímu k dlaždici.Používání hodnoty místního indexu zjednodušuje kód, protože není třeba psát kód pro převod hodnot indexu z globálních na místní.Pro použití rozložení je třeba ve výpočetní doméně v metodě parallel_for_each zavolat metodu extent::tile – metoda a ve výrazu lambda použít objekt typu tiled_index.
V typických aplikacích prvky v dlaždici nějakým způsobem navzájem souvisejí, kód má přístup k hodnotám a může sledovat hodnoty napříč dlaždicí.K dosažení tohoto cíle je třeba použít klíčové slovo tile_static klíčové slovo a metodu tile_barrier::wait – metoda.Proměnná, u které je použito klíčové slovo tile_static má rozsah přes celou dlaždici a instance proměnné je vytvořena pro každou dlaždici.Je třeba ošetřit synchronizaci přístupu vláken dlaždic k proměnné.Metoda tile_barrier::wait – metoda zastaví provádění aktuálního vlákna, dokud všechna vlákna v dlaždici nedosáhnou volání metody tile_barrier::wait.Takto lze nashromáždit hodnoty napříč dlaždicí pomocí proměnné tile_static.Poté mohou být dokončeny všechny výpočty, které vyžadují přístup ke všem hodnotám.
Následující diagram představuje dvojrozměrné pole dat vzorkování, která jsou uspořádána v dlaždicích.
Následující příklad kódu používá data vzorkování z předchozího diagramu.Kód nahradí každou hodnotu v dlaždici průměrem hodnot v dlaždici.
// Sample data:
int sampledata[] = {
2, 2, 9, 7, 1, 4,
4, 4, 8, 8, 3, 4,
1, 5, 1, 2, 5, 2,
6, 8, 3, 2, 7, 2};
// The tiles:
// 2 2 9 7 1 4
// 4 4 8 8 3 4
//
// 1 5 1 2 5 2
// 6 8 3 2 7 2
// Averages:
int averagedata[] = {
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
};
array_view<int, 2> sample(4, 6, sampledata);
array_view<int, 2> average(4, 6, averagedata);
parallel_for_each(
// Create threads for sample.extent and divide the extent into 2 x 2 tiles.
sample.extent.tile<2,2>(),
[=](tiled_index<2,2> idx) restrict(amp)
{
// Create a 2 x 2 array to hold the values in this tile.
tile_static int nums[2][2];
// Copy the values for the tile into the 2 x 2 array.
nums[idx.local[1]][idx.local[0]] = sample[idx.global];
// When all the threads have executed and the 2 x 2 array is complete, find the average.
idx.barrier.wait();
int sum = nums[0][0] + nums[0][1] + nums[1][0] + nums[1][1];
// Copy the average into the array_view.
average[idx.global] = sum / 4;
}
);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 6; j++) {
std::cout << average(i,j) << " ";
}
std::cout << "\n";
}
// Output:
// 3 3 8 8 3 3
// 3 3 8 8 3 3
// 5 5 2 2 4 4
// 5 5 2 2 4 4
Matematické knihovny
Knihovna C++ AMP obsahuje dvě matematické knihovny.Knihovna s dvojitou přesností v oboru názvů Concurrency::precise_math – obor názvů poskytuje podporu pro funkce s dvojitou přesností.Také poskytuje podporu pro funkce s jednoduchou přesností, přestože je na hardwaru stále vyžadována dvojitá přesnost.Odpovídá specifikaci C99 (ISO/IEC 9899).Akcelerátor musí podporovat plnou dvojitou přesnost.Lze určit, zda ji provede pomocí kontroly hodnoty datového členu accelerator::supports_double_precision – datový člen.Rychlá matematická knihovna v oboru názvů Concurrency::fast_math – obor názvů obsahuje jinou sadu matematických funkcí.Tyto funkce, které podporují pouze operandy typu float, jsou prováděny rychleji, ale nejsou tak přesné jako ty v matematické knihovně s dvojitou přesností.Funkce jsou obsaženy v hlavičkovém souboru <amp_math.h> a všechny jsou deklarovány s použitím klíčového slova restrict(amp).Funkce v hlavičkovém souboru <cmath> jsou importovány do obou oborů názvů, fast_math a precise_math.Klíčové slovo restrict, které se používá pro rozlišení verze <cmath> a verze C++ AMP.Následující kód vypočítá dekadický logaritmus s pomocí rychlé metody pro každou hodnotu, která je ve výpočetní oblasti.
#include <amp.h>
#include <amp_math.h>
#include <iostream>
using namespace concurrency;
void MathExample() {
double numbers[] = { 1.0, 10.0, 60.0, 100.0, 600.0, 1000.0 };
array_view<double, 1> logs(6, numbers);
parallel_for_each(
logs.extent,
[=] (index<1> idx) restrict(amp) {
logs[idx] = concurrency::fast_math::log10(logs[idx]);
}
);
for (int i = 0; i < 6; i++) {
std::cout << logs[i] << "\n";
}
}
Grafická knihovna
Knihovna C++ AMP obsahuje grafickou knihovnu, která je navržena pro urychlené programování grafiky.Tato knihovna se používá pouze u zařízení, která podporují nativní grafické funkce.Metody jsou umístěny v oboru názvů Concurrency::graphics – obor názvů a jsou obsaženy v hlavičkovém souboru <amp_graphics.h>.Klíčové součásti grafické knihovny jsou:
texture – třída: Tuto třídu textur lze použít pro tvorbu textur z paměti nebo ze souboru.Textury se podobají polím, protože obsahují data a připomínají kontejnery knihovny Standard Template Library (STL) s ohledem na přiřazení a konstrukci kopie.Další informace naleznete v tématu STL – kontejnery.Parametry šablony pro třídu texture jsou typ prvku a počet rozměrů.Počet rozměrů může být 1, 2 nebo 3.Typ prvku může být jeden z typů krátkých vektorů, popsaných dále v tomto článku.
Třída writeonly_texture_view – třída: Poskytuje přístup jen pro zápis pro všechny textury.
Knihovna Krátké vektorové knihovny: Definuje sadu typů krátkých vektorů o délce 2, 3 a 4, které jsou založeny na typech int, uint, float, double, norm, a nebo unorm.
Aplikace pro Windows Store
Stejně jako ostatní knihovny jazyka C++, knihovnu C++ AMP lze použít také v aplikacích pro systém Windows Store.Tyto články popisují, jak zahrnout kód využívající knihovnu C++ AMP, v aplikacích, které jsou vytvořeny pomocí jazyků C++, C#, Visual Basic či JavaScript:
Knihovna C++ AMP a Vizualizér souběžnosti
Vizualizátor souběžnosti zahrnuje podporu pro analýzu výkonu kódu, využívajícího knihovnu C++ AMP.Tyto články popisují tyto funkce:
Doporučení pro výkon
Operace modulo a dělení celých čísel bez znaménka mají výrazně lepší výkon než operace modulo a dělení celých čísel se znaménkem.Je doporučováno použití celých čísel bez znaménka, pokud je to možné.
Viz také
Referenční dokumentace
Další zdroje
C++ AMP (C++ Accelerated Massive Parallelism)