共用方式為


使用accelerator與accelerator_view物件

你可以用加速器和accelerator_view類別指定要執行 C++ AMP 程式碼的裝置或模擬器。 系統可能有多個裝置或模擬器,分別在記憶體容量、共享記憶體支援、除錯支援或雙精度支援上有所不同。 C++ 加速大規模平行運算(C++ AMP)提供的 API 可讓您檢視可用的加速器、將其中一個設為預設加速器、為多次呼叫 parallel_for_each 指定多個 accelerator_views,以及進行特殊的偵錯任務。

備註

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

使用預設加速器

C++ AMP 執行時會選擇預設的加速器,除非你寫程式碼選擇特定加速器。 執行時選擇預設加速器如下:

  1. 如果應用程式以除錯模式運行,則會有一個支援除錯的加速器。

  2. 否則,如果設定了環境變數,則使用由該環境變數指定的CPPAMP_DEFAULT_ACCELERATOR加速器。

  3. 否則,就用非模擬裝置。

  4. 否則,是擁有最多可用記憶體的裝置。

  5. 否則,就是未連接至顯示器的設備。

此外,執行時間會將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 與加速器無法同時存取,這會導致未定義的行為。 如果加速器支援共享記憶體,屬性 supports_cpu_shared_memory 會回傳true,且屬性 default_cpu_access_type 獲得配置在 的預設存取類型,例如與 相關的 accelerator,或在 array_view 上存取的 accelerator 物件。

C++ AMP 執行時會自動為每個 access_type選擇最佳預設accelerator值,但共享記憶體的效能特性(頻寬與延遲)在從 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 總是反映與其關聯的 default_cpu_access_typeaccelerator,且不提供介面來覆蓋或更改其 access_type

更改預設加速器

你可以透過呼叫 accelerator::set_default 方法來更改預設加速器。 你每次執行應用程式只能更改一次預設加速器,且必須在執行任何程式碼前先更改。 任何用於改變加速器的後續函式呼叫回傳 false。 如果你想在呼叫 parallel_for_each中使用不同的加速器,請閱讀本文中的「使用多個加速器」章節。 以下程式碼範例將預設加速器設定為未模擬、未連接顯示器且支援雙精度的加速器。

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_viewparallel_for_each 方法的呼叫。

  • 你可以使用特定物件來建立陣列物件。 C++ AMP 執行階段會從 lambda 運算式中取出 accelerator_view 物件,這個物件是從已捕獲的 陣列 物件中來的。

特殊加速器

三種特殊加速器的裝置路徑可作為類別 accelerator 的特性提供:

Interoperability

C++ AMP 執行環境支援類別與 Direct3D accelerator_view之間的互通性。 create_accelerator_view 方法會接收介面IUnknown並回傳一個accelerator_view物件。 get_device 方法會接收一個accelerator_view物件並回傳一個IUnknown介面。

另請參閱

C++ AMP (C++加速大規模平行處理原則)
偵錯 GPU 程式碼
accelerator_view 類別