使用 accelerator 和 accelerator_view 物件
您可以使用 accelerator 和 accelerator_view 類別,指定裝置或模擬器來執行您的 C++ AMP 程式碼。 系統可能包含數個因記憶體數量、共用記憶體支援、偵錯支援或雙精確度支援而有所差異的裝置或模擬器。 C++ Accelerated Massive Parallelism (C++ AMP) 提供應用程式開發介面,您可用來檢查可用的加速器、將其設定為預設、指定多個對 parallel_for_each 多重呼叫的 accelerator_views,以及執行特別的偵錯工作。
使用預設加速器
C++ AMP 執行階段會選擇預設的加速器,除非您撰寫程式碼來選擇特定加速器。 執行階段會選擇預設加速器,如下所示:
如果應用程式在偵錯模式下執行,則挑選支援偵錯的加速器。
否則,如果 CPPAMP_DEFAULT_ACCELERATOR 環境變數有被設置的話,則挑選其指定的加速器 。
否則,選擇非模擬的裝置。
否則,選擇具有最多可用記憶體的裝置。
否則,選擇沒有被附加至顯示的裝置。
此外,執行階段會指定預設加速器之 access_type_auto 的 access_type 。 這表示,如果支援,而且如果其效能特性 (頻寬和延遲) 已知與專用 (非共用) 記憶體相同,預設加速器會使用共用記憶體。
您可以透過建立預設加速器並檢查其屬性來判斷預設加速器的屬性。 下列程式碼範例會列印路徑、加速器記憶體數量、共用記憶體支援、雙精確度支援以及預設加速器的有限雙精確度支援。
void default_properties() {
accelerator default_acc;
std::wcout << default_acc.device_path << "\n";
std::wcout << default_acc.dedicated_memory << "\n";
std::wcout << (accs[i].supports_cpu_shared_memory ?
"CPU shared memory: true" : "CPU shared memory: false") << "\n";
std::wcout << (accs[i].supports_double_precision ?
"double precision: true" : "double precision: false") << "\n";
std::wcout << (accs[i].supports_limited_double_precision ?
"limited double precision: true" : "limited double precision: false") << "\n";
}
CPPAMP_DEFAULT_ACCELERATOR 環境變數
您可以設定 CPPAMP_DEFAULT_ACCELERATOR 環境變數,以指定預設加速器的accelerator::device_path。 路徑與硬體相依。 下列程式碼會使用 accelerator::get_all 函式擷取可用的加速器清單,然後顯示每個加速器的路徑和特性。
void list_all_accelerators()
{
std::vector<accelerator> accs = accelerator::get_all();
for (int i = 0; i < accs.size(); i++) {
std::wcout << accs[i].device_path << "\n";
std::wcout << accs[i].dedicated_memory << "\n";
std::wcout << (accs[i].supports_cpu_shared_memory ?
"CPU shared memory: true" : "CPU shared memory: false") << "\n";
std::wcout << (accs[i].supports_double_precision ?
"double precision: true" : "double precision: false") << "\n";
std::wcout << (accs[i].supports_limited_double_precision ?
"limited double precision: true" : "limited double precision: false") << "\n";
}
}
選取加速器
若要選取加速器,請使用 accelerator::get_all 方法擷取可用加速器清單,然後根據其屬性選取加速器。 這個範例顯示如何挑選擁有最多記憶體的加速器:
void pick_with_most_memory()
{
std::vector<accelerator> accs = accelerator::get_all();
accelerator acc_chosen = accs[0];
for (int i = 0; i < accs.size(); i++) {
if (accs[i].dedicated_memory > acc_chosen.dedicated_memory) {
acc_chosen = accs[i];
}
}
std::wcout << "The accelerator with the most memory is "
<< acc_chosen.device_path << "\n"
<< acc_chosen.dedicated_memory << ".\n";
}
注意事項 |
---|
其中一個由 accelerator::get_all 所傳回的加速器是 CPU 加速器。您無法在 CPU 加速器上執行程式碼。若要篩選掉 CPU 加速器,請將 accelerator::get_all 所回傳之加速器的 device_path 屬性值與 accelerator::cpu_accelerator 的值做比較。如需詳細資訊,請參閱本文<特殊的加速器>一節。 |
共用記憶體
共用記憶體是可由 CPU 和加速器存取的記憶體。 使用共用記憶體排除或大幅減少在 CPU 和加速器之間複製資料的額外負荷。 雖然共用記憶體,但目前 CPU 和加速器都無法存取,而且會產生未定義的行為。 如果加速器支援共用記憶體,且 default_cpu_access_type 屬性取得 accelerator 配置之記憶體的預設 access_type (例如,與 accelerator 相關聯的 array,或是在 accelerator 上存取的 array_view 物件),則加速器屬性 supports_cpu_shared_memory 會傳回 true。
C++ AMP 執行階段自動為每個 accelerator 選擇最佳的預設 access_type,但是當讀取 CPU、從 CPU 寫入或兩者都執行時,共用記憶體的效能特性 (頻寬和延遲) 會比專用 (非共用) 加速器記憶體的效能特性還要差。 如果共用記憶體就像專屬記憶體一般執行從 CPU 讀取和寫入的工作,則執行階段會預設為 access_type_read_write;否則,如果其計算核心的記憶體存取模式受益於不同的 access_type,執行階段會選擇較保守的預設 access_type,並且允許應用程式覆寫它。
下列程式碼範例示範如何判斷預設加速器是否支援共用記憶體,然後覆寫其預設存取類型並從其中建立 accelerator_view。
#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.set_default_cpu_access_type(access_type_read_write);
// Create an accelerator_view from the default accelerator. The
// accelerator_view reflects the default_cpu_access_type of the
// accelerator it’s associated with.
accelerator_view acc_v = acc.default_view;
}
accelerator_view 永遠反映與它關聯之 accelerator 的 default_cpu_access_type ,而且不提供覆寫或變更它的 access_type 的介面。
變更預設加速器
您可以藉由呼叫 accelerator::set_default 方法來改變預設加速器。 在應用程式每次執行時,您只能變更預設加速器一次,而且必須在 GPU 執行任何程式碼之前執加以變更。 任何要變更加速器的後續函式呼叫都會回傳 false。 如果您想要藉由呼叫 parallel_for_each 來使用不同的 accelerator ,請參閱本文「使用多個 Accelerator 」一節。 下列程式碼範例會將預設加速器設定為未模擬、未連接到顯示器且支援雙精確度的加速器。
bool pick_accelerator()
{
std::vector<accelerator> accs = accelerator::get_all();
accelerator chosen_one;
auto result =
std::find_if(accs.begin(), accs.end(), [] (const accelerator& acc)
{
return !acc.is_emulated &&
acc.supports_double_precision &&
!acc.has_display;
});
if (result != accs.end())
chosen_one = *(result);
std::wcout << chosen_one.description << std::endl;
bool success = accelerator::set_default(chosen_one.device_path);
return success;
}
使用多個加速器
有兩種方式可在您的應用程式中使用多個加速器:
您可以將 accelerator_view 物件傳遞給對 parallel_for_each 方法的呼叫。
您可以使用特定 accelerator_view 物件來建構 array 物件。 C++ AMP 執行階段會從 Lambda 運算式中擷取的 array 物件選擇 accelerator_view 物件。
特殊快速鍵
三個特殊加速器的裝置路徑可做為 accelerator 類別的屬性提供:
accelerator::direct3d_ref 資料成員:此單一執行緒加速器會使用 CPU 上的軟體來模擬一般圖形卡。 它預設用來偵錯,但因為比硬體加速器慢所以在生產環境中並不實用。 此外,這只能在 DirectX SDK 和 Windows SDK 中使用,客戶的電腦很可能沒有安裝它們。 如需詳細資訊,請參閱偵錯 GPU 程式碼。
accelerator::direct3d_warp 資料成員:此加速器提供後援解決方案,以便在使用 Streaming SIMD Extensions (SSE) 的多核心 CPU 上執行 C++ AMP 程式碼。
accelerator::cpu_accelerator 資料成員:您可以使用此加速器來設定預備環境陣列。 它無法執行 C++ AMP 程式碼。 如需詳細資訊,請參閱機器碼平行程式設計部落格上的 C++ AMP 中的預備環境陣列文章 (英文)。
互通性
C++ AMP 執行階段支援 accelerator_view 類別與 Direct3D ID3D11Device 介面之間的互通性。 create_accelerator_view 方法接受 IUnknown 介面並傳回 accelerator_view 物件。 get_device 方法接受 accelerator_view 物件並傳回 IUknown 介面。