Bagikan melalui


Menggunakan C++ AMP di Aplikasi UWP

Anda dapat menggunakan C++ AMP (C++ Accelerated Massive Parallelism) di aplikasi Platform Windows Universal (UWP) Anda untuk melakukan perhitungan pada GPU (Graphics Processing Unit) atau akselerator komputasi lainnya. Namun, C++ AMP tidak menyediakan API untuk bekerja langsung dengan jenis Windows Runtime, dan Windows Runtime tidak menyediakan pembungkus untuk C++ AMP. Saat Anda menggunakan jenis Windows Runtime dalam kode Anda—termasuk jenis yang telah Anda buat sendiri—Anda harus mengonversinya ke jenis yang kompatibel dengan C++ AMP.

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.

Pertimbangan performa

Jika Anda menggunakan ekstensi komponen Visual C++ C++/CX untuk membuat aplikasi Platform Windows Universal (UWP), kami sarankan Anda menggunakan jenis data lama biasa (POD) bersama dengan penyimpanan yang berdekatan—misalnya, std::vector atau array gaya C—untuk data yang akan digunakan dengan C++ AMP. Ini dapat membantu Anda mencapai performa yang lebih tinggi daripada dengan menggunakan jenis non-POD atau kontainer Windows Runtime karena tidak ada marshaling yang harus terjadi.

Dalam kernel C++ AMP, untuk mengakses data yang disimpan dengan cara ini, cukup bungkus std::vector penyimpanan array atau dalam lalu concurrency::array_view gunakan tampilan array dalam perulangan 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];
    });

Jenis Marshaling Windows Runtime

Saat bekerja dengan WINDOWS Runtime API, Anda mungkin ingin menggunakan C++ AMP pada data yang disimpan dalam kontainer Windows Runtime seperti Platform::Array<T>^ atau dalam jenis data kompleks seperti kelas atau struktur yang dideklarasikan dengan menggunakan kata kunci ref atau kata kunci nilai . Dalam situasi ini, Anda harus melakukan beberapa pekerjaan tambahan untuk membuat data tersedia untuk C++ AMP.

Platform::Array<T>^, di mana T adalah jenis POD

Ketika Anda menemukan Platform::Array<T>^ dan T adalah jenis POD, Anda dapat mengakses penyimpanan yang mendasar hanya dengan menggunakan get fungsi anggota:

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

Jika T bukan jenis POD, gunakan teknik yang dijelaskan di bagian berikut untuk menggunakan data dengan C++ AMP.

Jenis Windows Runtime: kelas ref dan kelas nilai

C++ AMP tidak mendukung jenis data yang kompleks. Ini termasuk jenis non-POD dan jenis apa pun yang dideklarasikan dengan menggunakan kata kunci ref atau kata kunci nilai . Jika jenis yang tidak didukung digunakan dalam restrict(amp) konteks, kesalahan waktu kompilasi dihasilkan.

Ketika Anda menemukan jenis yang tidak didukung, Anda dapat menyalin bagian-bagian menarik dari datanya ke dalam concurrency::array objek. Selain membuat data tersedia untuk dikonsumsi C++ AMP, pendekatan penyalinan manual ini juga dapat meningkatkan performa dengan memaksimalkan lokalitas data, dan dengan memastikan bahwa data yang tidak akan digunakan tidak disalin ke akselerator. Anda dapat meningkatkan performa lebih lanjut dengan menggunakan array penahapan, yang merupakan bentuk concurrency::array khusus yang memberikan petunjuk untuk runtime AMP bahwa array harus dioptimalkan untuk transfer yang sering antara itu dan array lain pada akselerator yang ditentukan.

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

Lihat juga

Buat aplikasi UWP pertama Anda menggunakan C++
Membuat Komponen Runtime Windows di C++