C++ AMP este o bibliotecă și o mică extensie de limbaj care permite procesarea eterogenă într-o singură aplicație C++. Visual Studio are noi unelte și capabilități pentru a suporta debugging și profiling pentru aplicațiile C++ AMP, inclusiv debugging pentru GPU și vizualizarea concurenței acestuia. Prin C++ AMP, dezvoltatorii C++ pot utiliza unelte familiare pentru a crea aplicații portabile și de viitor care pot obține accelerarea dramatică a aplicațiilor paralele.

C++ AMP (C++ Accelerated Massive Parallelism) accelerează execuția codului C++ prin utilizarea hardware-ului de procesare paralelă în mod uzual cunoscut ca și Unitatea de Procesare Grafica (GPU) aparținând unei plăci grafice.

Utilizând C++ AMP se pot programa algoritmi pentru date multi-dimensionale astfel încat execuția să fie accelerată utilizând paralelism pe hardware eterogen. Modelul de programare C++ AMP include vectori multidimensionali, indexare, transfer de memorie și o bibliotecă pentru funcții matematice. Pot fi utilizate extensiile de limbaj C++ AMP pentru a controla felul în care datele sunt mutate între CPU și GPU astfel încat să se îmbunătățească performanța.

Cerinte de sistem modificare

  • Windows 7, Windows 8, Windows Server 2008 R2, Windows Server 2012
  • DirectX 11 Feature Level 11.0 sau versiuni mai noi
  • Pentru debug pe emulatorul software, este necesar Windows 8 sau Windows Server 2012. Pentru debug pe hardware, trebuie instalate driver-e pentru placa grafică.

Exemplu de utilizare modificare

În următoarele două exemple sunt ilustate principalele componente ale C++ AMP. Se presupune că se dorește adunarea a două elemente corespunzătoare făcând parte din doi vectori unidimensionali. Spre exemplu, se adună {1, 2, 3, 4, 5} și {6, 7, 8, 9, 10} pentru a rezulta {7, 9, 11, 13, 15}. Fără a utiliza C++ AMP, codul pentru a realiza aceasta operație s-ar scrie astfel:

#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";
    }
}

Părțile importante din cod sunt următoarele:

  • Datele: sunt reprezentate prin trei vectori. Toți au același nivel (unu) și aceeași lungime (5).
  • Iterațiile: prima buclă for oferă un mecanism pentru a itera prin elementele vectorilor. Codul scris pentru a executa calculul sumei este conținut de prima buclă for.
  • Index: variabilele de acces idx accesează elementele individuale ale vectorilor.

Utilizând C++ AMP codul scris pentru realizarea operațiilor descrise mai sus ar fi următorul:

#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];
    
    // Crearea obiectelor C++ AMP.
    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( 
        // Se definește domeniul de calcul, care este setul de fire de execuție create.
        sum.extent, 
        // Se definește codul care se rulează pentru fiecare fir de execuție al acceleratorului.
        [=](index<1> idx) restrict(amp)
    {
        sum[idx] = a[idx] + b[idx];
    }
    );

    // Se afișează rezultatele.
    for (int i = 0; i < size; i++) {
        std::cout << sum[i] << "\n";
    }
}

Aceleași elemente de bază sunt prezente, dar construcția C++ AMP utilizează:

  • Datele: se utilizează vectori C++ pentru a construi trei obiecte C++ AMP array_view. Pentru a crea un asemenea obiect trebuie oferite patru date: valorile elementelor, nivelul/dimensiunea, tipul de date, și lungimea obiectului pentru fiecare dimensiune. Nivelul și tipul de date sunt transmise ca parametrii de tip. Datele și lungimea sunt transmise ca parametrii de constructor. În exemplu, vectorul C++ transmis constructorului este unidimensional. Nivelul și lungimea sunt utilizate pentru a construi forma dreptunghiulară a datelor în obiectul array_view, și valorile sunt utilizate pentru a umple acest vector. Biblioteca de runtime include și clasa array, care este o interfață asemănătoare clasei array_view.
  • Iteratii: funcția parallel_for_each, aparținând bibliotecii C++ AMP oferă un mecanism de iterare prin elemente. În acest exemplu, domeniul de calcul este specificat prin sum.extent. Codul care se va executa este cuprins într-o funcție lambda, sau funcție de nucleu(kernel function). Funcția restrict(amp) indică faptul că subsetul de limbaj C++ care poate fi accelerat de C++ AMP este utilizat.
  • Index: variabila de tip index este declarată cu dimensiunea unu pentru a corespunde dimensiunii obiectului array_view. Utilizând acest index se pot accesa elemente individuale ale obiectului de tip array_view.

Fundamente C++ AMP modificare

Câteva dintre structurile și funcțiile puse la dispoziție de biblioteca C++ AMP sunt urmatoarele:

  • array<T,N> - cel mai important tip de date utilizat în programarea ce folosește C++ AMP. A fost expus pe larg în capitolul anterior.
  • array_view – este un obiect cu aproximativ aceleași componente ca și array, dar comportamentul este diferit. Prin acesta, datele sunt copiate în accelerator atunci când funcția nucleu este executată, spre deosebire de array, unde datele sunt replicate în GPU.
  • accelerator și accelerator_view – reprezintă nu numai GPU-ul ci și un posibil accelerator virtual precum emulatorul instalat cu Visual Studio sau WARP (accelerator pentru CPU implementat utilizând arhitectura multicore și instrucțiuni SSE). Are o memorie care poate stoca mai mulți vectori, poate realiza calcule asupra acestora și este optimizată pentru procesarea paralelă a datelor.
  • index<N> - fiecare element al unui array sau array_view există la o poziție reprezentată printr-un index.
  • extend<N> - clasa template utilizată pentru identificarea „adresei” unui element dintr-un array sau array_view.
  • parallel_for_each – funcție care paralelizează operația. Se creează un array și se populează, se realizează un array_view în jurul unor valori conținute într-o structură legată de CPU precum std::vector, apoi se utilizează bucla parallel_for_each pentru a executa operații pe fiecare element al structurii.

Vezi și modificare

Bibliografie modificare

Gregory, Kate; Miller, Ade (). C++ AMP Accelerated Massive Parallelism with Microsoft Visual C++. OReilly. p. 15. ISBN 978-0-7356-6473-9. 

Gregory, Kate; Miller, Ade (). C++ AMP Accelerated Massive Parallelism with Microsoft Visual C++. OReilly. pp. 45 – 62. ISBN 978-0-7356-6473-9. 

„Microsoft Visual Studio - documentation”. Accesat în .