Bagikan melalui


Gambaran Umum AMP C++

Catatan

Header AMP C++ tidak digunakan lagi dimulai dengan Visual Studio 2022 versi 17.0. Menyertakan header AMP apa pun akan menghasilkan kesalahan build. Tentukan _SILENCE_AMP_DEPRECATION_WARNINGS sebelum menyertakan header AMP apa pun untuk membungkam peringatan.

C++ Accelerated Massive Parallelism (C++ AMP) mempercepat eksekusi kode C++ dengan memanfaatkan perangkat keras paralel data seperti unit pemrosesan grafis (GPU) pada kartu grafis diskrit. Dengan menggunakan C++ AMP, Anda dapat mengodekan algoritma data multi-dimensi sehingga eksekusi dapat dipercepat dengan menggunakan paralelisme pada perangkat keras heterogen. Model pemrograman C++ AMP mencakup array multidimensi, pengindeksan, transfer memori, ubin, dan pustaka fungsi matematika. Anda dapat menggunakan ekstensi bahasa C++ AMP untuk mengontrol bagaimana data dipindahkan dari CPU ke GPU dan kembali, sehingga Anda dapat meningkatkan performa.

Persyaratan Sistem

  • Windows 7 atau yang lebih baru

  • Windows Server 2008 R2 hingga Visual Studio 2019.

  • Perangkat keras DirectX 11 Feature Level 11.0 atau yang lebih baru

  • Untuk penelusuran kesalahan pada emulator perangkat lunak, Windows 8 atau Windows Server 2012 diperlukan. Untuk penelusuran kesalahan pada perangkat keras, Anda harus menginstal driver untuk kartu grafis Anda. Untuk informasi selengkapnya, lihat Men-debug Kode GPU.

  • Catatan: AMP saat ini tidak didukung di ARM64.

Pendahuluan

Dua contoh berikut mengilustrasikan komponen utama C++ AMP. Asumsikan bahwa Anda ingin menambahkan elemen yang sesuai dari dua array satu dimensi. Misalnya, Anda mungkin ingin menambahkan {1, 2, 3, 4, 5} dan {6, 7, 8, 9, 10} untuk mendapatkan {7, 9, 11, 13, 15}. Tanpa menggunakan C++ AMP, Anda mungkin menulis kode berikut untuk menambahkan angka dan menampilkan hasilnya.

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

Bagian penting dari kode adalah sebagai berikut:

  • Data: Data terdiri dari tiga array. Semua memiliki peringkat yang sama (satu) dan panjang (lima).

  • Iterasi: Perulangan pertama for menyediakan mekanisme untuk iterasi melalui elemen dalam array. Kode yang ingin Anda jalankan untuk menghitung jumlah terkandung dalam blok pertama for .

  • Indeks: idx Variabel mengakses elemen individual dari array.

Dengan menggunakan C++ AMP, Anda dapat menulis kode berikut sebagai gantinya.

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

Elemen dasar yang sama ada, tetapi konstruksi C++ AMP digunakan:

  • Data: Anda menggunakan array C++ untuk membuat tiga objek array_view C++ AMP. Anda menyediakan empat nilai untuk membuat array_view objek: nilai data, peringkat, jenis elemen, dan panjang array_view objek di setiap dimensi. Peringkat dan jenis diteruskan sebagai parameter jenis. Data dan panjang diteruskan sebagai parameter konstruktor. Dalam contoh ini, array C++ yang diteruskan ke konstruktor adalah satu dimensi. Peringkat dan panjang digunakan untuk membangun bentuk persegi panjang data dalam array_view objek, dan nilai data digunakan untuk mengisi array. Pustaka runtime juga menyertakan Kelas array, yang memiliki antarmuka yang mirip array_view dengan kelas dan dibahas nanti dalam artikel ini.

  • Iterasi: Fungsi parallel_for_each (C++ AMP) menyediakan mekanisme untuk iterasi melalui elemen data, atau domain komputasi. Dalam contoh ini, domain komputasi ditentukan oleh sum.extent. Kode yang ingin Anda jalankan terkandung dalam ekspresi lambda, atau fungsi kernel. menunjukkan restrict(amp) bahwa hanya subset bahasa C++ yang dapat dipercepat C++ AMP yang dapat dipercepat yang digunakan.

  • Indeks: Variabel Kelas indeks, idx, dinyatakan dengan peringkat satu agar sesuai dengan peringkat array_view objek. Dengan menggunakan indeks, Anda dapat mengakses masing-masing elemen array_view objek.

Membentuk dan Mengindeks Data: indeks dan luas

Anda harus menentukan nilai data dan mendeklarasikan bentuk data sebelum Anda dapat menjalankan kode kernel. Semua data didefinisikan sebagai array (persegi panjang), dan Anda dapat menentukan array untuk memiliki peringkat apa pun (jumlah dimensi). Data dapat berukuran apa pun dalam salah satu dimensi.

Kelas indeks

Kelas indeks menentukan lokasi di array objek atau array_view dengan merangkum offset dari asal di setiap dimensi menjadi satu objek. Saat Anda mengakses lokasi dalam array, Anda meneruskan index objek ke operator pengindeksan, [], alih-alih daftar indeks bilangan bulat. Anda dapat mengakses elemen di setiap dimensi dengan menggunakan Operator array::operator() atau Operator array_view::operator().

Contoh berikut membuat indeks satu dimensi yang menentukan elemen ketiga dalam objek satu dimensi array_view . Indeks digunakan untuk mencetak elemen ketiga dalam array_view objek. Outputnya adalah 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

Contoh berikut membuat indeks dua dimensi yang menentukan elemen di mana baris = 1 dan kolom = 2 dalam objek dua dimensi array_view . Parameter pertama dalam index konstruktor adalah komponen baris, dan parameter kedua adalah komponen kolom. Outputnya adalah 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

Contoh berikut membuat indeks tiga dimensi yang menentukan elemen di mana kedalaman = 0, baris = 1, dan kolom = 3 dalam objek tiga dimensi array_view . Perhatikan bahwa parameter pertama adalah komponen kedalaman, parameter kedua adalah komponen baris, dan parameter ketiga adalah komponen kolom. Outputnya adalah 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

Kelas tingkat

Kelas sejauh ini menentukan panjang data di setiap dimensi array objek atau array_view . Anda dapat membuat jangkauan dan menggunakannya untuk membuat array objek atau array_view . Anda juga dapat mengambil sejauh mana objek atau array_view yang adaarray. Contoh berikut mencetak panjang sejauh mana di setiap dimensi array_view objek.

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

Contoh berikut membuat array_view objek yang memiliki dimensi yang sama dengan objek dalam contoh sebelumnya, tetapi contoh ini menggunakan extent objek alih-alih menggunakan parameter eksplisit di array_view konstruktor.

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

Memindahkan Data ke Akselerator: array dan array_view

Dua kontainer data yang digunakan untuk memindahkan data ke akselerator ditentukan dalam pustaka runtime. Mereka adalah Kelas array dan Kelas array_view. Kelas array adalah kelas kontainer yang membuat salinan dalam data saat objek dibuat. Kelas array_view adalah kelas pembungkus yang menyalin data saat fungsi kernel mengakses data. Ketika data diperlukan pada perangkat sumber, data disalin kembali.

Kelas array

array Saat objek dibuat, salinan mendalam data dibuat pada akselerator jika Anda menggunakan konstruktor yang menyertakan penunjuk ke himpunan data. Fungsi kernel memodifikasi salinan pada akselerator. Ketika eksekusi fungsi kernel selesai, Anda harus menyalin data kembali ke struktur data sumber. Contoh berikut mengalikan setiap elemen dalam vektor dengan 10. Setelah fungsi kernel selesai, vector conversion operator digunakan untuk menyalin data kembali ke objek vektor.

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

Kelas array_view

array_view memiliki anggota array yang hampir sama dengan kelas, tetapi perilaku yang mendasar tidak sama. Data yang diteruskan ke array_view konstruktor tidak direplikasi pada GPU seperti halnya dengan array konstruktor. Sebagai gantinya, data disalin ke akselerator ketika fungsi kernel dijalankan. Oleh karena itu, jika Anda membuat dua array_view objek yang menggunakan data yang sama, kedua array_view objek merujuk ke ruang memori yang sama. Ketika Anda melakukan ini, Anda harus menyinkronkan akses multithreaded apa pun. Keuntungan utama menggunakan array_view kelas adalah bahwa data dipindahkan hanya jika diperlukan.

Perbandingan array dan array_view

Tabel berikut ini meringkas kesamaan dan perbedaan antara array kelas dan array_view .

Deskripsi kelas array kelas array_view
Ketika peringkat ditentukan Pada waktu kompilasi. Pada waktu kompilasi.
Ketika jangkauan ditentukan Pada waktu proses. Pada waktu proses.
Bentuk Persegi panjang. Persegi panjang.
Penyimpanan data Adalah kontainer data. Adalah pembungkus data.
Menyalin Salinan eksplisit dan mendalam pada definisi. Salinan implisit saat diakses oleh fungsi kernel.
Pengambilan data Dengan menyalin data array kembali ke objek pada utas CPU. Dengan akses array_view langsung objek atau dengan memanggil metode array_view::synchronize untuk terus mengakses data pada kontainer asli.

Memori bersama dengan array dan array_view

Memori bersama adalah memori yang dapat diakses oleh CPU dan akselerator. Penggunaan memori bersama menghilangkan atau secara signifikan mengurangi overhead penyalinan data antara CPU dan akselerator. Meskipun memori dibagikan, memori tidak dapat diakses secara bersamaan oleh CPU dan akselerator, dan melakukannya menyebabkan perilaku yang tidak ditentukan.

array objek dapat digunakan untuk menentukan kontrol terperinci atas penggunaan memori bersama jika akselerator terkait mendukungnya. Apakah akselerator mendukung memori bersama ditentukan oleh properti supports_cpu_shared_memory akselerator, yang kembali true ketika memori bersama didukung. Jika memori bersama didukung, Enumerasi access_type default untuk alokasi memori pada akselerator ditentukan oleh default_cpu_access_type properti . Secara default, array dan array_view objek mengambil yang sama access_type dengan primer terkait accelerator.

Dengan mengatur properti array Array::cpu_access_type Data Member secara eksplisit, Anda dapat melakukan kontrol terperinci atas cara memori bersama digunakan, sehingga Anda dapat mengoptimalkan aplikasi untuk karakteristik performa perangkat keras, berdasarkan pola akses memori kernel komputasinya. Mencerminkan array_view hal yang sama array cpu_access_type dengan yang dikaitkan dengan; atau, jika array_view dibangun tanpa sumber data, itu access_type mencerminkan lingkungan yang pertama kali menyebabkannya mengalokasikan penyimpanan. Artinya, jika pertama kali diakses oleh host (CPU), maka itu berpura-pura seolah-olah dibuat melalui sumber data CPU dan berbagi access_type dari yang terkait dengan tangkapan; namun, jika pertama kali diakses oleh accelerator_view, maka itu bersifat seolah-olah dibuat atas array yang dibuat pada itu accelerator_view dan berbagi array.access_typeaccelerator_view

Contoh kode berikut menunjukkan cara menentukan apakah akselerator default mendukung memori bersama, lalu membuat beberapa array yang memiliki konfigurasi cpu_access_type yang berbeda.

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

Menjalankan Kode melalui Data: parallel_for_each

Fungsi parallel_for_each menentukan kode yang ingin Anda jalankan pada akselerator terhadap data di array objek atau array_view . Pertimbangkan kode berikut dari pengenalan topik ini.

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

Metode ini parallel_for_each mengambil dua argumen, domain komputasi dan ekspresi lambda.

Domain komputasi adalah extent objek atau tiled_extent objek yang menentukan kumpulan utas yang akan dibuat untuk eksekusi paralel. Satu utas dihasilkan untuk setiap elemen di domain komputasi. Dalam hal ini, extent objek bersifat satu dimensi dan memiliki lima elemen. Oleh karena itu, lima utas dimulai.

Ekspresi lambda mendefinisikan kode untuk dijalankan pada setiap utas. Klausa pengambilan, [=], menentukan bahwa isi ekspresi lambda mengakses semua variabel yang diambil berdasarkan nilai, yang dalam hal ini adalah a, b, dan sum. Dalam contoh ini, daftar parameter membuat variabel satu dimensi index bernama idx. Nilainya idx[0] adalah 0 di utas pertama dan meningkat satu di setiap utas berikutnya. menunjukkan restrict(amp) bahwa hanya subset bahasa C++ yang dapat dipercepat C++ AMP yang dapat dipercepat yang digunakan. Batasan pada fungsi yang memiliki pengubah pembatasan dijelaskan dalam batasan (C++ AMP). Untuk informasi selengkapnya, lihat Sintaks Ekspresi Lambda.

Ekspresi lambda dapat menyertakan kode yang akan dijalankan atau dapat memanggil fungsi kernel terpisah. Fungsi kernel harus menyertakan pengubah restrict(amp) . Contoh berikut setara dengan contoh sebelumnya, tetapi memanggil fungsi kernel terpisah.

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

Mempercepat Kode: Petak peta dan Hambatan

Anda dapat memperoleh akselerasi tambahan dengan menggunakan ubin. Ubin membagi utas menjadi subset atau petak peta persegi panjang yang sama. Anda menentukan ukuran petak peta yang sesuai berdasarkan himpunan data dan algoritma yang Anda kodekan. Untuk setiap utas, Anda memiliki akses ke lokasi global elemen data yang relatif terhadap seluruh array atau array_view dan akses ke lokasi lokal relatif terhadap petak peta. Menggunakan nilai indeks lokal menyederhanakan kode Anda karena Anda tidak perlu menulis kode untuk menerjemahkan nilai indeks dari global ke lokal. Untuk menggunakan petak peta, panggil metode extent::tile pada domain komputasi dalam parallel_for_each metode , dan gunakan objek tiled_index dalam ekspresi lambda.

Dalam aplikasi umum, elemen dalam petak peta terkait dalam beberapa cara, dan kode harus mengakses dan melacak nilai di seluruh petak peta. Gunakan kata kunci kata kunci tile_static dan metode tile_barrier::wait untuk menyelesaikan ini. Variabel yang memiliki kata kunci tile_static memiliki cakupan di seluruh petak peta, dan instans variabel dibuat untuk setiap petak peta. Anda harus menangani sinkronisasi akses utas petak ke variabel. Metode tile_barrier::wait menghentikan eksekusi utas saat ini sampai semua utas dalam ubin telah mencapai panggilan ke tile_barrier::wait. Jadi Anda dapat mengakumulasi nilai di seluruh petak peta dengan menggunakan variabel tile_static . Kemudian Anda dapat menyelesaikan komputasi apa pun yang memerlukan akses ke semua nilai.

Diagram berikut mewakili array data pengambilan sampel dua dimensi yang disusun dalam petak peta.

Nilai indeks dalam jangkauan berjenjang.

Contoh kode berikut menggunakan data pengambilan sampel dari diagram sebelumnya. Kode menggantikan setiap nilai dalam petak peta berdasarkan rata-rata nilai dalam petak peta.

// 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

Pustaka Matematika

C++ AMP menyertakan dua pustaka matematika. Pustaka presisi ganda dalam Namespace Layanan Concurrency::p recise_math menyediakan dukungan untuk fungsi presisi ganda. Ini juga memberikan dukungan untuk fungsi presisi tunggal, meskipun dukungan presisi ganda pada perangkat keras masih diperlukan. Ini sesuai dengan Spesifikasi C99 (ISO/IEC 9899). Akselerator harus mendukung presisi ganda penuh. Anda dapat menentukan apakah itu dilakukan dengan memeriksa nilai Akselerator::supports_double_precision Anggota Data. Pustaka matematika cepat, dalam Namespace Layanan Konkurensi::fast_math, berisi serangkaian fungsi matematika lainnya. Fungsi-fungsi ini, yang hanya float mendukung operan, dijalankan dengan lebih cepat tetapi tidak sama tepatnya dengan yang ada di pustaka matematika presisi ganda. Fungsi terkandung dalam <file header amp_math.h> dan semuanya dideklarasikan dengan restrict(amp). Fungsi dalam <file header cmath> diimpor ke dalam fast_math namespace layanan dan precise_math . Kata restrict kunci digunakan untuk membedakan <versi cmath> dan versi AMP C++. Kode berikut menghitung logaritma base-10, menggunakan metode cepat, dari setiap nilai yang ada di domain komputasi.

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

Pustaka Grafik

C++ AMP menyertakan pustaka grafis yang dirancang untuk pemrograman grafis yang dipercepat. Pustaka ini hanya digunakan pada perangkat yang mendukung fungsionalitas grafis asli. Metode berada di Namespace Layanan Konkurensi::grafis dan terkandung dalam <file header amp_graphics.h> . Komponen utama pustaka grafis adalah:

  • Kelas tekstur: Anda dapat menggunakan kelas tekstur untuk membuat tekstur dari memori atau dari file. Tekstur menyerupai array karena berisi data, dan menyerupai kontainer di Pustaka Standar C++ sehubungan dengan penugasan dan konstruksi salin. Untuk informasi selengkapnya, lihat Kontainer Pustaka Standar C++. Parameter templat untuk texture kelas adalah jenis elemen dan peringkat. Peringkatnya bisa 1, 2, atau 3. Jenis elemen dapat menjadi salah satu jenis vektor pendek yang dijelaskan nanti dalam artikel ini.

  • kelas writeonly_texture_view: Menyediakan akses tulis-saja ke tekstur apa pun.

  • Pustaka Vektor Pendek: Mendefinisikan satu set jenis vektor pendek panjang 2, 3, dan 4 yang didasarkan pada int, , uintfloat, double, norma, atau unorm.

Aplikasi Platform Windows Universal (UWP)

Seperti pustaka C++ lainnya, Anda dapat menggunakan C++ AMP di aplikasi UWP Anda. Artikel ini menjelaskan cara menyertakan kode AMP C++ dalam aplikasi yang dibuat dengan menggunakan C++, C#, Visual Basic, atau JavaScript:

C++ AMP dan Visualizer Konkurensi

Visualizer Konkurensi mencakup dukungan untuk menganalisis performa kode AMP C++. Artikel ini menjelaskan fitur-fitur ini:

Rekomendasi Kinerja

Modulus dan pembagian bilangan bulat yang tidak ditandatangani memiliki performa yang jauh lebih baik daripada modulus dan pembagian bilangan bulat yang ditandatangani. Kami menyarankan agar Anda menggunakan bilangan bulat yang tidak ditandatangani jika memungkinkan.

Lihat juga

C++ AMP (C++ Accelerated Massive Parallelism)
Sintaks Ekspresi Lambda
Referensi (C++ AMP)
Pemrograman Paralel di Blog Kode Asli