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:
Eine Zugriffstaste, die das Debuggen unterstützt, wenn die Anwendung im Debugmodus ausgeführt wird.
Andernfalls wird die durch die
CPPAMP_DEFAULT_ACCELERATOR
Umgebungsvariable angegebene Zugriffstaste verwendet, wenn sie festgelegt ist.Andernfalls ein nicht emuliertes Gerät.
Andernfalls das Gerät, das über den größte verfügbaren Speicherplatz verfügt.
Andernfalls ein Gerät, das nicht mit der Anzeige verbunden ist.
Außerdem gibt die Laufzeit den access_type
access_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_type für den accelerator
arbeitsspeicher zugewiesenen Arbeitsspeicher ab , z. B. Arrays, die dem zugeordneten Array zugeordnet sind, oder array_view
Objekte, auf die accelerator
auf der accelerator
Zeichenfolge 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_type
Schnittstelle 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 übergeben
accelerator_view
.Sie können ein Arrayobjekt mithilfe eines bestimmten
accelerator_view
Objekts erstellen. Die C+AMP-Laufzeit übernimmt dasaccelerator_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 Grafikkarte 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