在 UWP 應用程式中使用 C++ AMP

您可以在 通用 Windows 平臺 (UWP) 應用程式中使用 C++ AMP (C++ 加速大規模平行處理原則),在 GPU (圖形處理單位) 或其他計算加速器上執行計算。 然而,C++ AMP 並未提供可直接搭配 Windows 執行階段類型使用的 API,而 Windows 執行階段也未提供 C++ AMP 的包裝函式。 當您在程式碼中使用 Windows 執行階段類型 (包括您自行建立的類型) 時,必須將這些類型轉換成與 C++ AMP 相容的類型。

注意

從 Visual Studio 2022 17.0 版開始,C++ AMP 標頭已被取代。 包含任何 AMP 標頭將會產生建置錯誤。 先定義 _SILENCE_AMP_DEPRECATION_WARNINGS ,再包含任何 AMP 標頭以讓警告無聲。

效能考量

如果您使用 Visual C++ 元件延伸模組 C++/CX 來建立您的通用 Windows 平臺 (UWP) 應用程式,建議您搭配連續儲存體使用純舊資料 (POD) 類型,例如 std::vector C++ 陣列或 C 樣式陣列,以用於 C++ AMP 的資料。 這可協助您達到比使用非 POD 類型或Windows 執行階段容器更高的效能,因為不需要進行封送處理。

在 C++ AMP 核心中,若要存取以這種方式儲存的資料,只要將 或 陣列儲存體包裝 std::vector 在 中 concurrency::array_view ,然後在迴圈中使用 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];
    });

封送處理 Windows 執行階段型別

當您使用Windows 執行階段 API 時,可能會想要在儲存在Windows 執行階段容器中的資料上使用 C++ AMP,例如 Platform::Array<T>^ 或 ,例如使用 ref 關鍵字或 value 關鍵字宣告 的複雜資料類型中。 在這些情況下,您必須執行一些額外的工作,讓 C++ AMP 可以使用資料。

Platform::Array < T^,其中 T > 是 POD 類型

當您遇到 Platform::Array<T>^ 和 T 是 POD 類型時,只要使用 get 成員函式即可存取其基礎儲存體:

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

如果 T 不是 POD 類型,請使用下一節中所述的技術搭配 C++ AMP 使用資料。

Windows 執行階段型別: ref 類別和實值類別

C++ AMP 不支援複雜的資料類型。 這包括非 POD 型別,以及使用 ref 關鍵字或 value 關鍵字宣告的任何型別。 如果在內容中使用 restrict(amp) 不支援的類型,就會產生編譯時期錯誤。

當您遇到不支援的類型時,可以將其資料 concurrency::array 有趣的部分複製到 物件中。 除了讓 C++ AMP 能夠取用的資料之外,這個手動複製方法也可以藉由最大化資料位置來改善效能,並確保不會使用的資料不會複製到加速器。 您可以使用暫存陣列來進一步 改善效能,此陣列 是一種特殊的形式 concurrency::array ,可向 AMP 執行時間提供提示,指出陣列應該針對指定的加速器與其他陣列之間的頻繁傳輸進行優化。

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

另請參閱

使用 C++ 建立您的第一個 UWP 應用程式
在 C++ 中建立 Windows 執行階段元件