Sdílet prostřednictvím


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

Můžete použít třídy accelerator a accelerator_view, které umožňují určit, na kterém zařízení nebo emulátoru spustit kód AMP.Systém může mít několik zařízení nebo emulátorů, které se liší podle množství paměti, podpory sdílené paměti, podpory ladění nebo podpory dvojité přesnosti.C++ AMP poskytuje rozhraní API, která umožňují zkoumat všechny dostupné akcelerátory, nastavení jednoho z nich jako výchozí, použití více zobrazení akcelerátorů pro více volání na parallel_for_each a provádění zvláštních ladících úloh.

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

Pokud nenapíšete kód pro výběr zvoleného akcelerátoru, zvolí modul runtime C++ AMP výchozí akcelerátor.Modul runtime zvolí výchozí akcelerátor takto:

  1. Pokud je aplikace spuštěna v režimu ladění, akcelerátor podporující ladění.

  2. V opačném případě akcelerátor zadaný proměnnou prostředí CPPAMP_DEFAULT_ACCELERATOR, pokud je nastavena.

  3. Jinak – neemulované zařízení.

  4. Jinak zařízení, které má největší velikost dostupné paměti.

  5. Jinak – zařízení, které není připojeno k zobrazení.

Kromě toho modul runtime určuje access_type z access_type_auto pro výchozí akcelerátor.To znamená, že výchozí akcelerátor používá sdílenou paměť v případě, že je podporován a o jeho vlastnostech výkonu (šířka pásma a čekací doba) se ví, že budou stejné jako vyhrazená (nesdílená) paměť.

Můžete určit vlastnosti výchozího akcelerátoru sestavením a přezkoumáním vlastnosti výchozího akcelerátoru.Následující příklad kódu zobrazí cestu, množství paměti akcelerátoru, podporu sdílené paměti, podporu dvojité přesnosti a omezenou podporu dvojité přesnosti pro výchozí akcelerátor.

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

Můžete nastavit proměnnou prostředí CPPAMP_DEFAULT_ACCELERATOR zadáním accelerator::device_path výchozí akcelerátoru.Cesta je závislá na hardwaru.Následující kód používá funkci accelerator::get_all pro načtení seznamu dostupných akcelerátorů a poté zobrazí cestu a charakteristiku 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 pro načtení seznamu dostupných akcelerátorů a následně vyberte jeden z nich na základě vlastností akcelerátoru.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]

Jeden z akcelerátorů vrácený accelerator::get_all je akcelerátor procesoru.Kód nelze spustit na akcelerátoru procesoru.Chcete-li filtrovat akcelerátor procesoru, porovnejte hodnotu vlastnosti akcelerátoru device_path vrácenou accelerator::get_all s hodnotou accelerator::cpu_accelerator.Další informace naleznete v části Speciální akcelerátory v rámci tohoto tématu.

Sdílená paměť

Sdílená paměť je paměť, ke které lze přistupovat pomocí procesoru a akcelerátoru.Použití sdílené paměti eliminuje nebo významně snižuje režijní náklady na kopírování dat mezi procesorem a akcelerátorem.I když je paměť sdílená, nelze k ní přistupovat zároveň z procesoru a akcelerátoru. Došlo by k nedefinovanému chování.Vlastnost akcelerátoru supports_cpu_shared_memory vrátí hodnotu true, pokud akcelerátor podporuje sdílenou paměť a vlastnost default_cpu_access_type získá výchozí hodnotu access_type pro paměť přidělenou na accelerator– například arrays přidružené s objekty accelerator nebo array_view využívané v rámci accelerator.

Runtime C++ AMP automaticky zvolí nejvhodnější výchozí access_type pro každou accelerator, ale charakteristiky výkonu (šířka pásma a čekací doba) sdílené paměti mohou být horší, než u vyhrazené (nesdílené) paměti akcelerátoru při čtení z procesoru, zápisu z procesoru, nebo obojí.Pokud sdílená paměť funguje stejně dobře jako vyhrazená paměť pro čtení a zápis z procesoru, modul runtime nastaví výchozí hodnotu na access_type_read_write; v opačném případě modul runtime zvolí konzervativnější výchozí access_type a umožňuje aplikacím ho přepsat, pokud vzorce přístupů k paměti jádra jeho výpočtu těží 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 potom přepíše jeho výchozí typ přístupu a vytvoří z ní 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 vždy odráží default_cpu_access_type ze accelerator, ke kterému je přidružen, a poskytuje rozhraní pro přepsání nebo změnu jeho access_type.

Změna výchozího akcelerátoru

Můžete změnit výchozí akcelerátor voláním metody accelerator::set_default.Výchozí akcelerátor lze změnit pouze jednou za spuštění aplikace a je nutné jej změnit před spuštěním libovolného kódu v GPU.Jakákoli následná volání funkce změny akcelerátoru vrátí false.Pokud chcete použít jiný akcelerátor ve volání parallel_for_each, přečtěte si v této sekci článek "Použití více akcelerátorů".Následující ukázka kódu nastaví výchozí akcelerátor na akcelerátor, který není emulován, není připojen k zobrazení 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ů

Existují dvě možnosti použití více akcelerátorů v aplikaci:

  • Můžete předat objekt accelerator_view k volání metody parallel_for_each.

  • Můžete vytvořit objekt array pomocí zvláštního objektu accelerator_view.Modul runtime jazyka C+ AMP vybere objekt accelerator_view ze zachyceného objektu array v rámci výrazu lambda.

Speciální akcelerátory

Umístění zařízení tří speciálních akcelerátorů jsou dostupná jako vlastnosti třídy accelerator:

  • accelerator::direct3d_ref – datový člen: Tento jednovláknový akcelerátor používá software na procesoru pro emulaci obecné grafické kartyPoužívá se ve výchozím nastavení pro ladění, ale není užitečné ve výrobě, protože je pomalejší než hardwarové akcelerátory.Navíc je k dispozici pouze jako součást rozhraní DirectX SDK a Windows SDK a pravděpodobné nebude nainstalován na počítači zákazníka.Další informace naleznete v tématu Ladění kódu GPU.

  • accelerator::direct3d_warp – datový člen: Tento akcelerátor poskytuje záložní řešení pro provádění kódu jazyka C++ AMP na vícejádrových procesorech pomocí Streaming SIMD Extensions (SSE).

  • accelerator::cpu_accelerator – datový člen: Pomocí tohoto akcelerátoru nastavíte pracovní pole.Nedokáže spustit kód jazyka C++ AMP.Další informace naleznete v příspěvku Fázování polí v C++AMP na blogu Paralelní programování v nativním kódu.

Vzájemná spolupráce

Runtime C++ AMP podporuje interoperabilitu mezi třídou accelerator_view a rozhraním Direct3D ID3D11Device.Metoda Create_accelerator_view přebírá rozhraní IUnknown a vrací objekt accelerator_view.Metoda Get_device přebírá objekt accelerator_view a vrací rozhraní IUknown.

Viz také

Referenční dokumentace

accelerator – třída

accelerator_view – třída

Další zdroje

C++ AMP (C++ Accelerated Massive Parallelism)

Ladění kódu GPU