Sdílet prostřednictvím


Používání akcelerátoru a objektů accelerator_view

Akcelerátor a třídy accelerator_view můžete použít k určení zařízení nebo emulátoru pro spuštění kódu C++ AMP. Systém může mít několik zařízení nebo emulátorů, které se liší množstvím paměti, podporou sdílené paměti, podporou ladění nebo podporou dvojité přesnosti. C++ Akcelerovaný massive parallelism (C++ AMP) poskytuje rozhraní API, která můžete použít k prozkoumání dostupných akcelerátorů, nastavení jednoho jako výchozího, určení více accelerator_views pro více volání do parallel_for_each a provádění speciálních úloh ladění.

Poznámka

Hlavičky C++ AMP jsou zastaralé od sady Visual Studio 2022 verze 17.0. Zahrnutím všech hlaviček AMP se vygenerují chyby sestavení. Před zahrnutím záhlaví AMP definujte _SILENCE_AMP_DEPRECATION_WARNINGS upozornění.

Použití výchozího akcelerátoru

Modul runtime C++ AMP vybere výchozí akcelerátor, pokud nezapíšete kód, který vybere konkrétní akcelerátor. Modul runtime zvolí výchozí akcelerátor následujícím způsobem:

  1. Pokud je aplikace spuštěná v režimu ladění, akcelerátor, který podporuje ladění.

  2. Jinak akcelerátor určený proměnnou CPPAMP_DEFAULT_ACCELERATOR prostředí, pokud je nastavený.

  3. V opačném případě neemulované zařízení.

  4. V opačném případě zařízení, které má největší množství dostupné paměti.

  5. V opačném případě zařízení, které není připojené k displeji.

Modul runtime navíc určuje access_type výchozí access_type_auto akcelerátor. To znamená, že výchozí akcelerátor používá sdílenou paměť, pokud je podporovaná a jestli jsou její charakteristiky výkonu (šířka pásma a latence) známé jako vyhrazená (nesdílená) paměť.

Vlastnosti výchozího akcelerátoru můžete určit tak, že vytvoříte výchozí akcelerátor a prozkoumáte jeho vlastnosti. Následující příklad kódu vytiskne cestu, velikost paměti akcelerátoru, podporu sdílené paměti, podporu dvojité přesnosti a omezenou podporu dvojité přesnosti výchozího akcelerátoru.

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";
}

proměnná prostředí CPPAMP_DEFAULT_ACCELERATOR

Proměnnou prostředí CPPAMP_DEFAULT_ACCELERATOR můžete nastavit tak, aby určila accelerator::device_path výchozí akcelerátor. Cesta je závislá na hardwaru. Následující kód pomocí accelerator::get_all funkce načte seznam dostupných akcelerátorů a pak zobrazí cestu a vlastnosti každého akcelerátoru.

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";
    }
}

Výběr akcelerátoru

Chcete-li vybrat akcelerátor, použijte metodu accelerator::get_all k načtení seznamu dostupných akcelerátorů a pak vyberte jeden na základě jeho vlastností. Tento příklad ukazuje, jak vybrat akcelerátor, který má nejvíce paměti:

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";
}

Poznámka

Jedním z akcelerátorů vrácených accelerator::get_all je akcelerátor procesoru. V akcelerátoru procesoru nelze spustit kód. Chcete-li vyfiltrovat akcelerátor procesoru, porovnejte hodnotu vlastnosti device_path akcelerátoru vrácenou accelerator::get_all hodnotou akcelerátoru::cpu_accelerator. Další informace najdete v části Speciální akcelerátory v tomto článku.

Sdílená paměť

Sdílená paměť je paměť, ke které má přístup procesor i akcelerátor. Použití sdílené paměti eliminuje nebo výrazně snižuje režii při kopírování dat mezi procesorem a akcelerátorem. I když je paměť sdílená, nelze k ní přistupovat současně procesorem i akcelerátorem a tím způsobit nedefinované chování. Vlastnost akcelerátoru supports_cpu_shared_memory vrátí true , pokud akcelerátor podporuje sdílenou paměť, a vlastnost default_cpu_access_type získá výchozí access_type pro paměť přidělenou acceleratorpaměti – například polepřidružená k objektu acceleratornebo array_view objekty, ke kterým se acceleratorpřistupuje .

Modul runtime C++ AMP automaticky zvolí nejlepší výchozí hodnotu access_type pro každou z nich accelerator, ale charakteristiky výkonu (šířka pásma a latence) sdílené paměti můžou být horší než ty, které mají vyhrazenou (nesdílenou) paměť při čtení z procesoru, zápisu z procesoru nebo obojího. Pokud sdílená paměť provádí stejně jako vyhrazenou paměť pro čtení a zápis z procesoru, modul runtime výchozí access_type_read_writehodnotu ; jinak modul runtime zvolí konzervativnější výchozí hodnotu access_typea umožní aplikaci přepsat, pokud vzory přístupu k paměti jeho výpočetních jader mají prospěch z jiného access_type.

Následující příklad kódu ukazuje, jak určit, zda výchozí akcelerátor podporuje sdílenou paměť, a pak přepíše jeho výchozí typ přístupu a vytvoří z něj.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;
}

Vždy accelerator_view odráží, k default_cpu_access_typeaccelerator čemu je přidružena, a neposkytuje žádné rozhraní k přepsání nebo změně jeho access_type.

Změna výchozího akcelerátoru

Výchozí akcelerátor můžete změnit voláním accelerator::set_default metody. Výchozí akcelerátor můžete změnit jenom jednou na spuštění aplikace a před spuštěním jakéhokoli kódu na GPU ho musíte změnit. Všechna následná volání funkce ke změně návratu falseakcelerátoru . Pokud chcete ve volání parallel_for_eachpoužít jiný akcelerátor, přečtěte si část Používání více akcelerátorů v tomto článku. Následující příklad kódu nastaví výchozí akcelerátor na ten, který není emulován, není připojen k displeji a podporuje dvojitou přesnost.

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

Použití více akcelerátorů

V aplikaci můžete použít několik akcelerátorů dvěma způsoby:

  • Do volání metody parallel_for_each můžete předat accelerator_view objekty.

  • Objekt pole můžete vytvořit pomocí konkrétního accelerator_view objektu. Modul runtime C+AMP vyzvedne accelerator_view objekt z zachyceného objektu pole ve výrazu lambda.

Speciální akcelerátory

Cesty zařízení tří speciálních akcelerátorů jsou k dispozici jako vlastnosti accelerator třídy:

  • accelerator::d irect3d_ref Data Member: Tento akcelerátor s jedním vláknem používá software na procesoru k emulaci obecné grafické karty. Ve výchozím nastavení se používá k ladění, ale není užitečná v produkčním prostředí, protože je pomalejší než hardwarové akcelerátory. Kromě toho je k dispozici pouze v sadě DirectX SDK a sadě Windows SDK a je nepravděpodobné, že by se nainstalovala na počítače vašich zákazníků. Další informace najdete v tématu Ladění kódu GPU.

  • accelerator::d irect3d_warp – Datový člen: Tento akcelerátor poskytuje náhradní řešení pro spouštění kódu C++ AMP na vícejádrových procesorech, které používají rozšíření SSE (Streaming SIMD Extensions).

  • accelerator::cpu_accelerator Datový člen: Tento akcelerátor můžete použít k nastavení pracovních polí. Nelze spustit kód C++ AMP. Další informace najdete v příspěvku O přípravných polích v C++ AMP v blogovém příspěvku Paralelní programování v nativním kódu.

Vzájemná funkční spolupráce

Modul runtime C++ AMP podporuje interoperabilitu accelerator_view mezi třídou a rozhraním Direct3D ID3D11Device. Create_accelerator_view metoda přebírá IUnknown rozhraní a vrací accelerator_view objekt. Metoda get_device přebírá accelerator_view objekt a vrací IUnknown rozhraní.

Viz také

C++ AMP (C++ Accelerated Massive Parallelism)
Ladění kódu GPU
accelerator_view – třída