在 Windows 市集應用程式中使用 C++ AMP
必須在 Windows 市集 應用程式中使用 C++ AMP (C++ Accelerated Massive Parallelism) 執行 GPU (圖形處理單元 (GPU)) 或其他計算快速鍵的計算。 然而, C++ AMP 為工作不提供 API 直接以 Windows 執行階段 (WinRT) 型別,因此, WinRT 為 C++ AMP 不提供包裝函式。 當您使用時 WinRT 輸入程式碼包括您自行建立您必須轉換成與 C++ AMP 相容的型別。
效能考量
如果您使用 Visual C++ 元件擴充功能 (C++/CX) 以建立 Windows 市集 應用程式,建議您使用連續使用簡單舊資料 (POD) 型別儲存為,例如 std::vector 或 C-Style 陣列會使用與 C++ AMP 的資料。 因為封送處理不需要發生,這可協助您完成更高的效能比使用非 POD 型別或 Windows RT 容器。
以這種方式儲存的 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 執行階段型別
當您使用 WinRT API 時,您可以使用 ref 關鍵字或 value 關鍵字,來取得儲存 WinRT 容器 (例如 Platform::Array<T>^ ) 或在複雜資料型別 (例如類別或結構宣告中您可能要使用資料的 C++ AMP。 在這些情況下,您必須進行一些額外的工作可讓資料至 C++ AMP。
Platform::Array<T>^,其中 T 是 POD 型別
當您遇到 Platform::Array<T>^ 時,和 T 是 POD 型別,或使用 get 成員函式,您可以存取基礎儲存:
Platform::Array<float>^ arr; // Assume that this was returned by a WinRT API
concurrency::array_view<float, 1> av(arr->Length, &arr->get(0));
如果 T 非 POD 型別,請使用下列章節中描述搭配 C++ AMP 資料的技術。
Windows 執行階段型別:ref 類別和實值類別
C++ AMP 不支援複雜資料型別。 這包括使用 ref 關鍵字或 value 關鍵字,宣告的非 POD 型別和任何型別。 如果有不支援的型別是 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;
});