Verwenden von accelerator-Objekten und accelerator_view-Objekten

Sie können die Zugriffstaste und accelerator_view Klassen verwenden, um das Gerät oder den Emulator anzugeben, auf dem Ihr C++-AMP-Code ausgeführt werden soll. Ein System kann über mehrere Geräte oder Emulatoren verfügen, die sich im Hinblick auf die Größe des Arbeitsspeichers, Unterstützung von freigegebenem Arbeitsspeicher, Debugunterstützung oder Unterstützung doppelter Genauigkeit unterscheiden. C++ Accelerated Massive Parallelism (C++ AMP) stellt APIs bereit, die Sie verwenden können, um die verfügbaren Zugriffstasten zu prüfen, eine als Standardvorlage festzulegen, mehrere accelerator_view-Objekte für mehrere Aufrufe von parallel_for_each festzulegen und spezielle Debugaufgaben auszuführen.

Hinweis

C++AMP-Header sind ab Visual Studio 2022, Version 17.0, veraltet. Wenn Alle AMP-Header eingeschlossen werden, werden Buildfehler generiert. Definieren Sie _SILENCE_AMP_DEPRECATION_WARNINGS , bevor Sie AMP-Header einschließen, um die Warnungen zu stillen.

Verwenden der Standardzugriffstaste

Die C++ AMP-Laufzeit wählt eine Standardzugriffstaste aus, sofern Sie keinen Code schreiben, um eine bestimmte Taste auszuwählen. Die Laufzeit wählt die Standardzugriffstaste wie folgt aus:

  1. Eine Zugriffstaste, die das Debuggen unterstützt, wenn die Anwendung im Debugmodus ausgeführt wird.

  2. Andernfalls wird die durch die CPPAMP_DEFAULT_ACCELERATOR Umgebungsvariable angegebene Zugriffstaste verwendet, wenn sie festgelegt ist.

  3. Andernfalls ein nicht emuliertes Gerät.

  4. Andernfalls das Gerät, das über den größte verfügbaren Speicherplatz verfügt.

  5. Andernfalls ein Gerät, das nicht mit der Anzeige verbunden ist.

Außerdem gibt die Laufzeit den access_typeaccess_type_auto für die Standardzugriffstaste an. Dies bedeutet, dass der Standardbeschleuniger freigegebenen Speicher verwendet, wenn er unterstützt wird und die Leistungsmerkmale (Bandbreite und Latenz) als der dedizierte (nicht gemeinsam genutzte) Speicher bekannt sind.

Sie können die Eigenschaften der Standardzugriffstaste bestimmen, indem Sie die Standardzugriffstaste erstellen und ihre Eigenschaften überprüfen. Das folgende Codebeispiel legt den Pfad, die Größe des Zugriffstastenspeichers, die Unterstützung des freigegebenen Arbeitsspeichers, die Unterstützung doppelter Genauigkeit und die eingeschränkte Unterstützung doppelter Genauigkeit für die Standardzugriffstaste fest.

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-Umgebungsvariable

Sie können die CPPAMP_DEFAULT_ACCELERATOR-Umgebungsvariable festlegen, um den Pfad accelerator::device_path der Standardzugriffstaste anzugeben. Der Pfad ist von der Hardware abhängig. Der folgende Code verwendet die accelerator::get_all-Funktion, um eine Liste der verfügbaren Zugriffstasten abzurufen und anschließend den Pfad und die Eigenschaften jeder Zugriffstaste anzuzeigen.

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

Auswählen einer Zugriffstaste

Um eine Zugriffstaste auszuwählen, rufen Sie mit der accelerator::get_all-Methode eine Liste der verfügbaren Zugriffstasten ab und wählen Sie eine Taste auf Grundlage ihrer Eigenschaften aus. Dieses Beispiel zeigt, wie Sie die Zugriffstaste mit dem größten Arbeitsspeicher auswählen:

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

Hinweis

Eine der Zugriffstasten, die von accelerator::get_all zurückgegeben werden, ist die CPU-Zugriffstaste. Sie können auf der CPU-Zugriffstaste keinen Code ausführen. Um den CPU-Beschleuniger herauszufiltern, vergleichen Sie den Wert der device_path Eigenschaft der Zugriffstaste, die mit accelerator::get_all dem Wert der Accelerator::cpu_accelerator zurückgegeben wird. Weitere Informationen finden Sie im Abschnitt "Spezielle Zugriffstasten" in diesem Artikel.

Gemeinsam genutzter Speicherbereich

Freigegebener Arbeitsspeicher ist der Arbeitsspeicher, auf den sowohl die CPU als auch die Zugriffstaste zugreifen kann. Durch die Verwendung von freigegebenem Arbeitsspeicher entfällt bzw. reduziert sich der Mehraufwand zum Kopieren von Daten zwischen CPU und der Zugriffstaste erheblich. Obwohl der Arbeitsspeicher freigegeben wird, kann darauf nicht von CPU und der Zugriffstaste gleichzeitig zugegriffen werden. In diesem Fall kommt es zu einem nicht definierten Verhalten. Die Zugriffstasteneigenschaft supports_cpu_shared_memory gibt zurücktrue, wenn die Zugriffstaste gemeinsam genutzten Speicher unterstützt, und die default_cpu_access_type -Eigenschaft ruft die Standard-access_typefür den acceleratorarbeitsspeicher zugewiesenen Arbeitsspeicher ab , z. B. Arrays, die dem zugeordneten Array zugeordnet sind, oder array_view Objekte, auf die acceleratorauf der acceleratorZeichenfolge zugegriffen wird.

Die C++ AMP-Laufzeit wählt automatisch den besten standardmäßigen access_type für jedes accelerator-Objekt aus. Die Leistungsmerkmale (Bandbreite und Wartezeit) von freigegebenem Arbeitsspeicher können beim Lesen und/oder Schreiben über die CPU jedoch schlechter sein als die des dedizierten (nicht freigegebenen) Zugriffstastenspeichers. Wenn freigegebener Arbeitsspeicher beim Lesen und Schreiben über die CPU die gleiche Leistung zeigt wie dedizierter Arbeitsspeicher verwendet die Laufzeit standardmäßig access_type_read_write; andernfalls wählt die Laufzeit einen konservativeren standardmäßigen access_type aus und ermöglicht es der Anwendung, ihn zu überschreiben, wenn die Speicherzugriffmuster seiner Berechnungskernel von einem anderen access_type profitieren.

Das folgende Codebeispiel zeigt, wie bestimmt wird, ob die Standardzugriffstaste freigegebenen Arbeitsspeicher unterstützt, und der Standardzugriffstyp überschrieben und ein accelerator_view-Objekt daraus erstellt wird.

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

Eine accelerator_view zeigt immer den default_cpu_access_type der accelerator zugeordneten Elemente an und stellt keine Schnittstelle zum Überschreiben oder Ändern seiner access_typeSchnittstelle bereit.

Ändern der Standardzugriffstaste

Sie können die Standardzugriffstaste ändern, indem Sie die accelerator::set_default-Methode aufrufen. Sie können die Standardzugriffstaste nur einmal pro App-Ausführung ändern. Die Änderung muss erfolgen, bevor Code auf dem GPU-Computer ausgeführt wird. Alle nachfolgenden Funktionsaufrufe zum Ändern der Zugriffstastenrückgabe false. Wenn Sie eine andere Tastenkombination in einem Aufruf von parallel_for_each verwenden möchten, lesen Sie den Abschnitt "Verwenden mehrerer Zugriffstasten" in diesem Artikel. Im folgenden Codebeispiel wird die Standardzugriffstaste auf eine Taste festgelegt, die nicht emuliert, nicht mit einer Anzeige verbunden ist und doppelte Genauigkeit unterstützt.

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

Verwenden mehrerer Zugriffstasten

Es gibt zwei Möglichkeiten, mehrere Zugriffstasten in Ihrer App zu verwenden:

  • Sie können Objekte an die Aufrufe der parallel_for_each-Methode übergebenaccelerator_view.

  • Sie können ein Arrayobjekt mithilfe eines bestimmten accelerator_view Objekts erstellen. Die C+AMP-Laufzeit übernimmt das accelerator_view Objekt aus dem erfassten Arrayobjekt im Lambda-Ausdruck.

Spezielle Zugriffstasten

Die Gerätepfade von drei speziellen Zugriffstasten sind als Eigenschaften der accelerator-Klasse verfügbar:

  • accelerator::d irect3d_ref Data Member: Dieser Singlethreaded Accelerator verwendet Software auf der CPU, um eine generische Grafik Karte zu emulieren. Sie wird standardmäßig für das Debuggen verwendet, ist jedoch in der Produktion nicht vorteilhaft, da sie langsamer ist als die Hardwarezugriffstasten. Außerdem ist sie nur im DirectX SDK und im Windows SDK verfügbar und wird mit großer Wahrscheinlichkeit nicht auf den Computern der Kunden installiert. Weitere Informationen finden Sie unter Debuggen von GPU-Code.

  • accelerator::d irect3d_warp Data Member: Diese Zugriffstaste bietet eine Fallbacklösung zum Ausführen von C++-AMP-Code auf Multi-Core-CPUs, die Streaming SIMD-Erweiterungen (SSE) verwenden.

  • accelerator::cpu_accelerator Data Member: Sie können diese Zugriffstaste zum Einrichten von Stagingarrays verwenden. Sie kann keinen C++ AMP-Code ausführen. Weitere Informationen finden Sie im Beitrag "Stagingarrays in C++AMP " im Blog "Parallel Programming in Native Code".

Interoperabilität

Die C++AMP-Laufzeit unterstützt die Interoperabilität zwischen der accelerator_view Klasse und der Direct3D ID3D11Device-Schnittstelle. Die create_accelerator_view-Methode verwendet eine IUnknown Schnittstelle und gibt ein accelerator_view Objekt zurück. Die get_device-Methode verwendet ein accelerator_view Objekt und gibt eine IUnknown Schnittstelle zurück.

Siehe auch

C++ AMP (C++ Accelerated Massive Parallelism)
Debuggen von GPU-Code
accelerator_view-Klasse