Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Megjegyzés:
A C++ AMP fejlécek elavultak a Visual Studio 2022 17.0-s verziójától kezdve.
Az AMP-fejlécek beépítése építési hibákat fog okozni. A figyelmeztetések elnémításához a _SILENCE_AMP_DEPRECATION_WARNINGS definiálása előtt az AMP-fejléceket be kell vonni.
A C++ gyorsított masszív párhuzamosság (C++ AMP) felgyorsítja a C++ kód végrehajtását azáltal, hogy kihasználja az adat-párhuzamos hardvereket, például a grafikus feldolgozó egységet (GPU) egy különálló grafikus kártyán. A C++ AMP használatával többdimenziós adat-algoritmusokat kódolhat, így a végrehajtás felgyorsítható a heterogén hardvereken alkalmazott párhuzamossággal. A C++ AMP programozási modell többdimenziós tömböket, indexelést, memóriaátvitelt, burkolást és matematikai függvénytárat tartalmaz. A C++ AMP nyelvi bővítményekkel szabályozhatja, hogy az adatok hogyan kerülnek át a processzorról a GPU-ra és vissza, így javíthatja a teljesítményt.
Rendszerkövetelmények
Windows 7 vagy újabb
Windows Server 2008 R2–Visual Studio 2019.
DirectX 11 Feature Level 11.0 vagy újabb hardver
A szoftveremulátoron végzett hibakereséshez Windows 8 vagy Windows Server 2012 szükséges. A hardveren végzett hibakereséshez telepítenie kell a grafikus kártya illesztőprogramjait. További információ: GPU-kód hibakeresése.
Megjegyzés: Az AMP jelenleg nem támogatott az ARM64-ben.
Bevezetés
Az alábbi két példa a C++ AMP elsődleges összetevőit mutatja be. Tegyük fel, hogy két egydimenziós tömb megfelelő elemeit szeretné hozzáadni. Előfordulhat például, hogy hozzá szeretne adni {1, 2, 3, 4, 5} és {6, 7, 8, 9, 10}, hogy megkapja {7, 9, 11, 13, 15}. A C++ AMP használata nélkül a következő kódot írhatja a számok hozzáadásához és az eredmények megjelenítéséhez.
#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";
}
}
A kód fontos részei a következők:
Adatok: Az adatok három tömbből állnak. Mindegyiknek ugyanaz a rangja (egy) és hossza (öt).
Iteráció: Az első
forhurok mechanizmust biztosít a tömbök elemein keresztüli iteráláshoz. Az összeg kiszámításához végrehajtandó kód az elsőforblokkban található.Index: A
idxváltozó hozzáfér a tömbök egyes elemeihez.
A C++ AMP használatával ehelyett a következő kódot írhatja.
#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";
}
}
Ugyanazok az alapvető elemek vannak jelen, de C++ AMP-szerkezeteket használnak.
Adatok: C++ tömbök használatával három C++ AMP array_view objektumot hozhat létre. Egy objektum létrehozásához
array_viewnégy értéket kell megadnia: az adatértékeket, a rangot, az elemtípust és az objektum hosszát azarray_viewegyes dimenziókban. A rangsor és a típus típusparaméterként lesz átadva. A rendszer konstruktorparaméterként adja át az adatokat és a hosszt. Ebben a példában a konstruktornak átadott C++ tömb egydimenziós. A rang és a hossz az objektumban lévőarray_viewadatok négyszögletes alakjának kialakítására szolgál, az adatértékek pedig a tömb kitöltésére szolgálnak. A futtatókörnyezeti kódtár tartalmazza a tömbosztályt is, amely egy, azarray_viewosztályhoz hasonló felülettel rendelkezik, amelyet a cikk későbbi részében ismertetünk.Iteráció: A parallel_for_each függvény (C++ AMP) az adatelemeken vagy számítási tartományon keresztüli iterálás mechanizmusát biztosítja. Ebben a példában a számítási tartományt a
sum.extenthatározza meg. A végrehajtani kívánt kód egy lambdakifejezésben vagy kernelfüggvényben található. Ezrestrict(amp)azt jelzi, hogy csak a C++ nyelv azon részhalmazát használja, amelyet a C++ AMP fel tud gyorsítani.Index: Az indexosztály változója
idxegy ranggal van deklarálva, amely megfelel azarray_viewobjektum rangjának. Az index használatával elérheti az objektumok egyes elemeitarray_view.
Adatok formázása és indexelése: indexelés és kiterjedés
A kernelkód futtatása előtt meg kell határoznia az adatértékeket, és deklarálnia kell az adatok alakját. Minden adat tömbként van definiálva (négyszögletes), és bármilyen rangot (dimenziók számát) megadhatja a tömböt. Az adatok bármilyen méretűek lehetnek bármelyik dimenzióban.
indexosztály
Az indexosztály egy helyet határoz meg az array adott array_view objektumban úgy, hogy az eltolást az egyes dimenziók forrásából egy objektumba foglalja. Amikor a tömb egy helyéhez fér hozzá, egy index objektumot ad át az indexelő operátornak az []egész indexek listája helyett. Az egyes dimenziók elemeit a tömb::operátor() operátorral vagy a array_view::operátor() operátorral érheti el.
Az alábbi példa létrehoz egy egydimenziós indexet, amely egy egydimenziós array_view objektum harmadik elemét határozza meg. Az index az objektum harmadik elemének nyomtatására array_view szolgál. A kimenet 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
Az alábbi példa egy kétdimenziós indexet hoz létre, amely meghatározza azt az elemet, amelyben a sor = 1 és az oszlop = 2 egy kétdimenziós array_view objektumban. A konstruktor első paramétere index a sorösszetevő, a második pedig az oszlopösszetevő. A kimenet: 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
Az alábbi példa egy háromdimenziós indexet hoz létre, amely meghatározza azt az elemet, amelyben a mélység = 0, a sor = 1 és az oszlop = 3 egy háromdimenziós array_view objektumban. Figyelje meg, hogy az első paraméter a mélységi összetevő, a második pedig a sorösszetevő, a harmadik pedig az oszlopösszetevő. A kimenet értéke 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
kiterjesztés osztály
A extent osztály az adatok hosszát határozza meg az array vagy array_view objektum minden dimenziójában. Létrehozhat egy kiterjedést, és használhatja egy array vagy array_view objektum létrehozására. Egy meglévő array vagy array_view objektum kiterjedése is lekérhető. Az alábbi példa kiírja az array_view objektum minden dimenziójának kiterjedés hosszát.
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";
Az alábbi példa egy array_view olyan objektumot hoz létre, amelynek mérete megegyezik az előző példában szereplő objektummal, de ez a példa egy extent objektumot használ a array_view konstruktor explicit paraméterei helyett.
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";
Adatok áthelyezése a gyorsítóba: tömb és array_view
Az adatok gyorsítóba való áthelyezéséhez használt két adattároló a futtatókörnyezeti kódtárban van definiálva. Ezek a tömbosztály és a array_view osztály. Az array osztály egy tárolóosztály, amely az objektum létrehozásakor létrehozza az adatok mély másolatát. Az array_view osztály egy burkolóosztály, amely akkor másolja az adatokat, amikor a kernelfüggvény hozzáfér az adatokhoz. Ha az adatokra a forráseszközön van szükség, az adatok vissza lesznek másolva.
tömbosztály
array Objektum létrehozásakor az adatok mély másolata jön létre a gyorsítón, ha olyan konstruktort használ, amely az adathalmazra mutató mutatót tartalmaz. A kernel függvény módosítja a gyorsítón lévő példányt. Ha a kernelfüggvény végrehajtása befejeződött, vissza kell másolnia az adatokat a forrásadat-struktúrába. Az alábbi példa egy vektor minden elemét megszorozza 10-sel. A kernelfüggvény befejezése után a vector conversion operator rendszer az adatokat visszamásolja a vektorobjektumba.
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";
}
array_view osztály
A array_view tagok majdnem ugyanazok, mint az array osztály, de a mögöttes viselkedés nem ugyanaz. A konstruktornak array_view átadott adatok nem replikálódnak a GPU-n, mint egy array konstruktor esetén. Ehelyett a rendszer a kernelfüggvény végrehajtásakor másolja az adatokat a gázpedálba. Ezért ha két array_view olyan objektumot hoz létre, amelyek ugyanazt az adatot használják, mindkét array_view objektum ugyanarra a memóriaterületre hivatkozik. Ha ezt teszi, szinkronizálnia kell minden többszálú hozzáférést. Az osztály használatának fő előnye, hogy az array_view adatok csak akkor kerülnek áthelyezésre, ha szükséges.
Tömb és array_view összehasonlítása
Az alábbi táblázat a hasonlóságokat és az arrayarray_view osztályok közötti különbségeket foglalja össze.
| Leírás | tömbosztály | array_view osztály |
|---|---|---|
| Rangsor meghatározásakor | Fordítás idején. | Fordítás idején. |
| A mérték meghatározásakor | Futásidőben. | Futásidőben. |
| Forma | Derékszögű. | Derékszögű. |
| Adattárolás | Adattároló. | Adatburkoló. |
| Másolás | Kifejezett és mély másolás a definíció létrehozásakor. | Implicit másolás, amikor a kernelfüggvény hozzáfér hozzá. |
| Adatok beolvasása | Az adatok visszamásolása a tömbből egy objektumba a CPU szálán. | Az objektum közvetlen elérésével array_view vagy a array_view::szinkronizálási metódus meghívásával továbbra is hozzáférhet az eredeti tároló adataihoz. |
Megosztott memória tömb és array_view használatával
A megosztott memória a processzor és a gyorsító által egyaránt elérhető memória. A megosztott memória használata kiküszöböli vagy jelentősen csökkenti az adatok másolásának többletterhelését a processzor és a gyorsító között. Bár a memória meg van osztva, a processzor és a gyorsító nem tudja egyidejűleg elérni, és ez nem definiált viselkedést okoz.
array objektumok segítségével részletes vezérlést adhat meg a megosztott memória használata felett, ha a társított gyorsító támogatja azt. Azt, hogy a gyorsító támogatja-e a megosztott memóriát, a gyorsító supports_cpu_shared_memory tulajdonsága határozza meg, amely akkor tér vissza true , ha a megosztott memória támogatott. Ha a megosztott memória támogatott, akkor a gyorsító memóriafoglalásainak alapértelmezett access_type számbavétele a default_cpu_access_type tulajdonság által van meghatározva. Alapértelmezés szerint az arrayarray_view objektumok az elsődleges társított access_typeobjektummal azonosakaccelerator.
A tömb::cpu_access_type Data Member tulajdonság array explicit módon történő beállításával részletesen szabályozhatja a megosztott memória használatát, így optimalizálhatja az alkalmazást a hardver teljesítményjellemzőihez a számítási kernelek memóriahozzáférési mintái alapján. A array_view ugyanazt a cpu_access_type tükrözi, mint az a array, amelyhez kapcsolódik; vagy ha az array_view adatforrás nélkül jön létre, akkor az a környezetet tükrözi, amely először a tárterület lefoglalását okozza. Ez azt jelzi, hogy ha először a gazdagép (CPU) fér hozzá, akkor úgy viselkedik, mintha egy CPU-adatforráson keresztül lett volna létrehozva, és megosztja a rögzítéssel összekapcsolt access_typeaccelerator_view-t. Ha azonban először egy accelerator_view fér hozzá, akkor úgy viselkedik, mintha egy adatforráson létrehozott array ezen accelerator_view-en lett volna létrehozva, és megosztja azokat arrayaccess_type.
Az alábbi példakód bemutatja, hogyan állapítható meg, hogy az alapértelmezett gyorsító támogatja-e a megosztott memóriát, majd több különböző cpu_access_type konfigurációval rendelkező tömböt hoz létre.
#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);
}
Kód végrehajtása adatokon keresztül: parallel_for_each
A parallel_for_each függvény az a kódrészletet határozza meg, amelyet a gyorsítón futtatandó az array vagy array_view objektumban lévő adatokon. A témakör bevezető részében tekintse meg az alábbi kódot.
#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";
}
}
A parallel_for_each metódus két argumentumot, egy számítási tartományt és egy lambda kifejezést használ.
A számítási tartomány egy extent objektum vagy objektum tiled_extent , amely meghatározza a párhuzamos végrehajtáshoz létrehozandó szálak készletét. A számítási tartomány minden eleméhez egy szál jön létre. Ebben az esetben az extent objektum egydimenziós, és öt elemből áll. Ezért öt szál indul el.
A lambda kifejezés határozza meg az egyes szálakon futtatandó kódot. A rögzítési záradék azt határozza meg, [=]hogy a lambda kifejezés törzse az összes rögzített változóhoz érték szerint fér hozzá, ami ebben az esetben a következőa: és bsum. Ebben a példában a paraméterlista létrehoz egy egydimenziós index változót.idx Az érték idx[0] 0 az első szálban, és minden további szálban egy-egyvel növekszik. Ez restrict(amp) azt jelzi, hogy csak a C++ nyelv azon részhalmazát használja, amelyet a C++ AMP fel tud gyorsítani. A korlátozásmódosítóval rendelkező függvényekre vonatkozó korlátozásokat a korlátozás (C++ AMP) ismerteti. További információ: Lambda Kifejezés szintaxisa.
A lambda kifejezés tartalmazhatja a végrehajtandó kódot, vagy meghívhat egy külön kernelfüggvényt. A kernelfüggvénynek tartalmaznia kell a restrict(amp) módosítót. Az alábbi példa egyenértékű az előző példával, de külön kernelfüggvényt hív meg.
#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";
}
}
Kódgyorsítás: Csempék és korlátok
A burkolással további gyorsulást érhet el. A burkolás a szálakat egyenlő téglalap alakú részhalmazokra vagy csempékre osztja. Az adatkészlet és a kódoláshoz használt algoritmus alapján határozza meg a megfelelő csempeméretet. Minden szál esetében hozzáférhet egy adatelem globális helyéhez, amely az egész array és array_view kontextusához viszonyított, valamint hozzáférhet a csempe viszonylatában lévő helyi helyhez. A helyi indexérték használata leegyszerűsíti a kódot, mert nem kell írnia a kódot az indexértékek globálisról helyire történő fordításához. Burkolás alkalmazásához hívja meg a extent::tile metódust a parallel_for_each metódus számítási tartományán, és lambda kifejezésben tiled_index objektumot használjon.
A tipikus alkalmazásokban a csempék elemei valamilyen módon kapcsolódnak, és a kódnak hozzá kell férnie és nyomon kell követnie az értékeket a csempén. Ehhez használja a tile_static kulcsszót és a tile_barrier::wait metódust . A tile_static kulcsszóval rendelkező változó hatóköre egy teljes csempén belül található, és a változó egy példánya jön létre minden csempéhez. Kezelnie kell a csempeszál változóhoz való hozzáférésének szinkronizálását. A tile_barrier::wait metódus leállítja az aktuális szál végrehajtását, amíg az összes szál a tile-ban el nem érte a hívást.tile_barrier::wait. Így tile_static változók használatával összegyűjtheti az értékeket a csempén. Ezután befejezhet minden olyan számítást, amely az összes értékhez hozzáférést igényel.
Az alábbi diagram egy kétdimenziós mintavételi adatokat ábrázol, amelyek csempékbe vannak rendezve.
Az alábbi példakód az előző diagram mintavételezési adatait használja. A kód a csempe minden értékét lecseréli a csempe értékeinek átlagára.
// 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
Matematikai kódtárak
A C++ AMP két matematikai kódtárat tartalmaz. Az Concurrency::precise_math névtér dupla pontosságú könyvtára támogatja a dupla pontosságú függvényeket. Támogatja az egypontos pontosságú függvényeket is, bár a hardveren továbbra is szükség van a dupla pontosságú támogatásra. Megfelel a C99 specifikációnak (ISO/IEC 9899). A gyorsítónak támogatnia kell a teljes dupla pontosságot. Ezt a gyorsító értékének ellenőrzésével állapíthatja meg ::supports_double_precision Adattag. A gyors matematikai kódtár az Egyidejűség::fast_math névtérben egy másik matematikai függvénykészletet tartalmaz. Ezek a függvények, amelyek csak float operandusokat támogatnak, gyorsabban hajthatók végre, de nem olyan pontosak, mint a dupla pontosságú matematikai kódtárban. A függvények a <amp_math.h> fejlécfájlban találhatók, és mindegyik a következővel restrict(amp)van deklarálva: . A <cmath> fejlécfájlban lévő függvények importálódnak mind a fast_math, mind a precise_math névtérbe. A restrict kulcsszó a cmath< és a >C++ AMP verzió megkülönböztetésére szolgál. Az alábbi kód kiszámítja a számítási tartományban lévő összes érték 10-es alapú logaritmusát a gyors metódus használatával.
#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(numbers[idx]);
}
);
for (int i = 0; i < 6; i++) {
std::cout << logs[i] << "\n";
}
}
Grafikai könyvtár
A C++ AMP egy gyorsított grafikus programozáshoz tervezett grafikus kódtárat tartalmaz. Ez a kódtár csak natív grafikus funkciókat támogató eszközökön használható. A metódusok az Egyidejűség::grafikus névtérben találhatók, és a <amp_graphics.h> fejlécfájlban találhatók. A grafikus kódtár fő összetevői a következők:
textúraosztály: A textúraosztály használatával memóriából vagy fájlból hozhat létre textúrákat. A textúrák azért hasonlítanak a tömbökre, mert adatokat tartalmaznak, és a C++ standard kódtár tárolóira hasonlítanak hozzárendelés és másolás építés szempontjából. További információ: C++ Standard kódtártárolók. Az osztály sablonparaméterei az
textureelemtípus és a rang. A rangsor 1, 2 vagy 3 lehet. Az elemtípus lehet az egyik rövid vektortípus, amelyet a cikk későbbi részében ismertetünk.writeonly_texture_view osztály: Írás-only hozzáférést biztosít bármely textúrához.
Rövid vektortár: 2, 3 és 4 hosszúságú rövid vektortípusokat határoz meg, amelyek
int,uint,float,double, norma vagy unorm alapján vannak.
Univerzális Windows-platform (UWP) alkalmazások
A többi C++ kódtárhoz hasonlóan a C++ AMP-t is használhatja a UWP-alkalmazásokban. Ezek a cikkek azt ismertetik, hogyan lehet C++ AMP-kódot belefoglalni a C++, C#, Visual Basic vagy JavaScript használatával létrehozott alkalmazásokba:
Bing Maps Trip Optimizer, Windows Áruházbeli alkalmazás JavaScriptben és C++ nyelven
A C++ AMP használata C#-ból a Windows Futtatókörnyezet használatával
C++ AMP és egyidejűségi vizualizáció
Az egyidejűségi vizualizáció támogatja a C++ AMP-kód teljesítményének elemzését. Ezek a cikkek a következő funkciókat ismertetik:
Teljesítménnyel kapcsolatos javaslatok
A modulusok és az aláíratlan egész számok osztása jelentősen jobb teljesítményt nyújt, mint a modulusok és az aláírt egész számok osztása. Javasoljuk, hogy ha lehetséges, használjon aláíratlan egész számokat.
Lásd még
C++ AMP (C++ gyorsított masszív párhuzamosság)
Lambda kifejezés szintaxisa
Referencia (C++ AMP)
Párhuzamos programozás a natív kód blogjában