Delen via


Accelerator en accelerator_view-objecten gebruiken

U kunt de accelerator en accelerator_view klassen gebruiken om het apparaat of de emulator op te geven waarop uw C++ AMP-code moet worden uitgevoerd. Een systeem kan verschillende apparaten of emulators hebben die verschillen per hoeveelheid geheugen, ondersteuning voor gedeeld geheugen, ondersteuning voor foutopsporing of ondersteuning voor dubbele precisie. C++ Accelerated Massive Parallelism (C++ AMP) biedt API's die u kunt gebruiken om de beschikbare accelerators te onderzoeken, er een in te stellen als de standaardinstelling, meerdere accelerator_views op te geven voor meerdere aanroepen naar parallel_for_each en speciale foutopsporingstaken uit te voeren.

Opmerking

C++ AMP-headers worden afgeschaft vanaf Visual Studio 2022 versie 17.0. Als u AMP-headers opneemt, zullen er buildfouten optreden. Definieer _SILENCE_AMP_DEPRECATION_WARNINGS voordat u AMP-headers opneemt om de waarschuwingen te onderdrukken.

De standaardversneller gebruiken

De C++ AMP-runtime kiest een standaardversneller, tenzij u code schrijft om een specifieke te kiezen. De runtime kiest de standaardversneller als volgt:

  1. Als de app wordt uitgevoerd in de foutopsporingsmodus, een accelerator die ondersteuning biedt voor foutopsporing.

  2. Anders is de accelerator die is opgegeven door de CPPAMP_DEFAULT_ACCELERATOR omgevingsvariabele, als deze is ingesteld.

  3. Anders is het een niet-geëmuleerd apparaat.

  4. Anders is het apparaat met de meeste hoeveelheid beschikbaar geheugen.

  5. Een apparaat dat niet aan het beeldscherm is gekoppeld.

Daarnaast geeft de runtime een access_type van access_type_auto voor de standaardversneller. Dit betekent dat de standaardversneller gebruikmaakt van gedeeld geheugen als dit wordt ondersteund en als de prestatiekenmerken (bandbreedte en latentie) bekend zijn als hetzelfde als toegewezen (niet-gedeeld) geheugen.

U kunt de eigenschappen van de standaardversneller bepalen door de standaardversneller samen te stellen en de eigenschappen ervan te controleren. In het volgende codevoorbeeld worden het pad, de hoeveelheid geheugen van de accelerator, ondersteuning voor gedeeld geheugen, ondersteuning voor dubbele precisie en beperkte ondersteuning voor dubbele precisie van de standaardversneller afgedrukt.

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

Omgevingsvariabele CPPAMP_DEFAULT_ACCELERATOR

U kunt de CPPAMP_DEFAULT_ACCELERATOR omgevingsvariabele instellen om de accelerator::device_path standaardversneller op te geven. Het pad is hardwareafhankelijk. De volgende code gebruikt de accelerator::get_all functie om een lijst met beschikbare accelerators op te halen en geeft vervolgens het pad en de kenmerken van elke accelerator weer.

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

Een accelerator selecteren

Als u een accelerator wilt selecteren, gebruikt u de accelerator::get_all methode om een lijst met de beschikbare accelerators op te halen en selecteert u er vervolgens een op basis van de eigenschappen. In dit voorbeeld ziet u hoe u de accelerator kiest die het meeste geheugen heeft:

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

Opmerking

Een van de accelerators die worden geretourneerd door accelerator::get_all is de CPU-accelerator. U kunt geen code uitvoeren op de CPU-accelerator. Als u de CPU-accelerator wilt filteren, vergelijkt u de waarde van de eigenschap device_path van de accelerator die wordt geretourneerd door accelerator::get_all met de waarde van de accelerator::cpu_accelerator. Zie de sectie Speciale accelerators in dit artikel voor meer informatie.

Gedeeld geheugen

Gedeeld geheugen is geheugen dat toegankelijk is voor zowel de CPU als de accelerator. Het gebruik van gedeeld geheugen elimineert of vermindert de overhead van het kopiëren van gegevens tussen de CPU en de accelerator aanzienlijk. Hoewel het geheugen wordt gedeeld, kan het niet gelijktijdig worden geopend door zowel de CPU als de accelerator, en zorgt dit voor niet-gedefinieerd gedrag. De eigenschap supports_cpu_shared_memory retourneert true als de accelerator gedeeld geheugen ondersteunt, en de eigenschap default_cpu_access_type haalt het standaard access_type op voor het geheugen dat is toegewezen op de accelerator, zoals matrices die zijn gekoppeld aan de accelerator of array_view-objecten die op de accelerator-accelerator worden benaderd.

De C++ AMP-runtime kiest automatisch de beste standaardinstelling access_type voor elk accelerator, maar de prestatiekenmerken (bandbreedte en latentie) van gedeeld geheugen kunnen slechter zijn dan die van toegewezen (niet-gedeeld) acceleratorgeheugen bij het lezen van de CPU, schrijven vanuit de CPU of beide. Als gedeeld geheugen net zo goed presteert als toegewezen geheugen voor lezen en schrijven vanaf de CPU, stelt de runtime standaard access_type_read_write in; anders kiest de runtime een conservatievere standaardwaarde access_type, en kan de app deze overschrijven als de toegangspatronen van zijn rekenkernels voor het geheugen baat hebben bij een andere access_type.

In het volgende codevoorbeeld ziet u hoe u kunt bepalen of de standaardversneller gedeeld geheugen ondersteunt en vervolgens het standaardtoegangstype overschrijft en er een accelerator_view van maakt.

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

Een accelerator_view weerspiegelt altijd de default_cpu_access_type van de accelerator waarmee het is geassocieerd en biedt geen interface om zijn access_type te overschrijven of te wijzigen.

De standaardversneller wijzigen

U kunt de standaardversneller wijzigen door de accelerator::set_default methode aan te roepen. U kunt de standaardversneller slechts eenmaal per app-uitvoering wijzigen en u moet deze wijzigen voordat code wordt uitgevoerd op de GPU. Eventuele volgende functie-aanroepen om de accelerator te wijzigen resulteren in false. Als u een andere accelerator in een aanroep parallel_for_eachwilt gebruiken, leest u de sectie 'Meerdere accelerators gebruiken' in dit artikel. In het volgende codevoorbeeld wordt de standaardversneller ingesteld op een accelerator die niet is geëmuleerd, niet is verbonden met een beeldscherm en ondersteuning biedt voor dubbele precisie.

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

Meerdere accelerators gebruiken

Er zijn twee manieren om meerdere accelerators in uw app te gebruiken:

  • U kunt objecten aan de aanroepen naar de methode accelerator_view doorgeven .

  • U kunt een matrixobject maken met behulp van een specifiek accelerator_view object. De C++ AMP-runtime haalt het accelerator_view object op uit het vastgelegde matrixobject in de lambda-expressie.

Speciale versnellers

De apparaatpaden van drie speciale accelerators zijn beschikbaar als eigenschappen van de accelerator klasse:

  • accelerator::direct3d_ref Data Member: Deze single-threaded accelerator maakt gebruik van software op de CPU om de werking van een standaard grafische kaart te simuleren. Deze wordt standaard gebruikt voor foutopsporing, maar is niet nuttig in productie omdat deze langzamer is dan de hardwareversnellers. Bovendien is deze alleen beschikbaar in de DirectX SDK en de Windows SDK, en is het onwaarschijnlijk dat deze op de computers van uw klanten wordt geïnstalleerd. Zie Debugging GPU-code voor meer informatie.

  • accelerator::direct3d_warp Data Member: Deze accelerator biedt een terugvaloplossing voor het uitvoeren van C++ AMP-code op multicore-CPU's die gebruikmaken van Streaming SIMD Extensions (SSE).

  • accelerator::cpu_accelerator Gegevenslid: u kunt deze accelerator gebruiken voor het instellen van faseringsmatrices. C++ AMP-code kan niet worden uitgevoerd. Zie de faseringsmatrices in C++ AMP-post op de blog Parallel Programming in Native Code voor meer informatie.

Interoperabiliteit

De C++ AMP-runtime ondersteunt interoperabiliteit tussen de accelerator_view klasse en de Direct3D ID3D11Device-interface. De methode create_accelerator_view gebruikt een IUnknown interface en retourneert een accelerator_view object. De methode get_device gebruikt een accelerator_view object en retourneert een IUnknown interface.

Zie ook

C++ AMP (C++ Versneld massaal parallellisme)
Debuggen van GPU-Code
accelerator_view-klasse