Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Você pode usar as classes accelerator e accelerator_view para especificar o dispositivo ou emulador no qual executar seu código AMP C++. Um sistema pode ter vários dispositivos ou emuladores que diferem por quantidade de memória, suporte de memória compartilhada, suporte de depuração ou suporte de precisão dupla. O C++ Accelerated Massive Parallelism (C++ AMP) fornece APIs que você pode usar para examinar os aceleradores disponíveis, definir um como padrão, especificar vários accelerator_views para várias chamadas a parallel_for_each e executar tarefas especiais de depuração.
Observação
Os cabeçalhos AMP C++ foram preteridos a partir do Visual Studio 2022 versão 17.0.
A inclusão de cabeçalhos AMP gerará erros de compilação. Defina _SILENCE_AMP_DEPRECATION_WARNINGS antes de incluir quaisquer cabeçalhos AMP para silenciar os avisos.
Usando o acelerador padrão
O tempo de execução do C++ AMP escolhe um acelerador padrão, a menos que você escreva código para escolher um específico. O tempo de execução escolhe o acelerador padrão da seguinte maneira:
Se o aplicativo estiver sendo executado no modo de depuração, um acelerador que ofereça suporte à depuração.
Caso contrário, o acelerador especificado pela
CPPAMP_DEFAULT_ACCELERATORvariável de ambiente, se estiver definido.Caso contrário, um dispositivo não emulado.
Caso contrário, o dispositivo que tem a maior quantidade de memória disponível.
Caso contrário, um dispositivo que não esteja conectado à tela.
Além disso, o tempo de execução especifica um access_type de access_type_auto para o acelerador padrão. Isso significa que o acelerador padrão usa memória compartilhada se for suportado e se suas características de desempenho (largura de banda e latência) forem conhecidas por serem as mesmas da memória dedicada (não compartilhada).
Você pode determinar as propriedades do acelerador padrão construindo o acelerador padrão e examinando suas propriedades. O exemplo de código a seguir imprime o caminho, a quantidade de memória do acelerador, o suporte à memória compartilhada, o suporte de precisão dupla e o suporte limitado de precisão dupla do acelerador padrão.
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 variável de ambiente
Você pode definir a CPPAMP_DEFAULT_ACCELERATOR variável de ambiente para especificar o accelerator::device_path do acelerador padrão. O caminho depende do hardware. O código a seguir usa a accelerator::get_all função para recuperar uma lista dos aceleradores disponíveis e, em seguida, exibe o caminho e as características de cada acelerador.
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";
}
}
Selecionando um acelerador
Para selecionar um acelerador, use o accelerator::get_all método para recuperar uma lista dos aceleradores disponíveis e, em seguida, selecione um com base em suas propriedades. Este exemplo mostra como escolher o acelerador que tem mais memória:
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";
}
Observação
Um dos aceleradores que são retornados por accelerator::get_all é o acelerador de CPU. Não é possível executar código no acelerador de CPU. Para filtrar o acelerador da CPU, compare o valor da propriedade device_path do acelerador retornado por accelerator::get_all com o valor de acelerador::cpu_accelerator. Para obter mais informações, consulte a seção "Aceleradores especiais" neste artigo.
Memória compartilhada
A memória compartilhada é a memória que pode ser acessada pela CPU e pelo acelerador. O uso de memória compartilhada elimina ou reduz significativamente a sobrecarga de copiar dados entre a CPU e o acelerador. Embora a memória seja compartilhada, ela não pode ser acessada simultaneamente pela CPU e pelo acelerador, e isso causa um comportamento indefinido. A propriedade accelerator supports_cpu_shared_memory retornará true se o acelerador oferecer suporte à memória compartilhada e a propriedade default_cpu_access_type obtiver o access_type padrão para memória alocada no accelerator—por exemplo, matrizesassociadas ao accelerator, ou array_view objetos acessados no accelerator.
O tempo de execução do C++ AMP escolhe automaticamente o melhor padrão access_type para cada accelerator, mas as características de desempenho (largura de banda e latência) da memória compartilhada podem ser piores do que as da memória aceleradora dedicada (não compartilhada) ao ler da CPU, gravar a partir da CPU ou ambos. Se a memória compartilhada funcionar tão bem quanto a memória dedicada para leitura e gravação da CPU, o tempo de execução assume o padrão access_type_read_write; caso contrário, o tempo de execução escolhe um padrão mais conservador access_type e permite que o aplicativo o substitua se os padrões de acesso à memória dos seus kernels de computação se beneficiarem de um diferente access_type.
O exemplo de código a seguir mostra como determinar se o acelerador padrão oferece suporte à memória compartilhada e, em seguida, substitui seu tipo de acesso padrão e cria um accelerator_view a partir dele.
#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;
}
Um accelerator_view sempre reflete o default_cpu_access_type do accelerator a que está associado e não fornece qualquer interface para substituir ou alterar o seu access_type.
Alterando o acelerador padrão
Você pode alterar o acelerador padrão chamando o accelerator::set_default método. Você pode alterar o acelerador padrão apenas uma vez por execução de aplicativo e deve alterá-lo antes que qualquer código seja executado na GPU. Qualquer função subsequente chama para alterar o retorno falsedo acelerador. Se você quiser usar um acelerador diferente em uma chamada para parallel_for_each, leia a seção "Usando vários aceleradores" neste artigo. O exemplo de código a seguir define o acelerador padrão como um que não é emulado, não está conectado a um monitor e oferece suporte a precisão dupla.
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;
}
Usando vários aceleradores
Há duas maneiras de usar vários aceleradores em seu aplicativo:
Você pode passar
accelerator_viewobjetos para as chamadas do método parallel_for_each.Você pode construir um objeto array usando um objeto específico
accelerator_view. O tempo de execução do C++ AMP vai captar o objetoaccelerator_viewdo array capturado na expressão lambda.
Aceleradores Especiais
Os caminhos de dispositivo de três aceleradores especiais estão disponíveis como propriedades da accelerator classe:
accelerator::direct3d_ref Data Member: Este acelerador único de thread usa software na CPU para emular uma placa gráfica comum. Ele é usado por padrão para depuração, mas não é útil na produção porque é mais lento do que os aceleradores de hardware. Além disso, está disponível apenas no SDK do DirectX e no SDK do Windows, e é improvável que seja instalado nos computadores dos seus clientes. Para obter mais informações, consulte Depuração de código GPU.
accelerator::direct3d_warp Data Member: Este acelerador fornece uma solução alternativa para executar código AMP C++ em CPUs multi-core que usam Extensões SIMD de Streaming (SSE).
accelerator::cpu_accelerator Data Member: Você pode usar este acelerador para configurar arrays de estágio. Ele não pode executar código AMP C++. Para obter mais informações, consulte a postagem Matrizes de preparo em C++ AMP no blog Programação paralela em código nativo.
Interoperabilidade
O runtime C++ AMP suporta a interoperabilidade entre a classe accelerator_view e a interface ID3D11Device do Direct3D. O método create_accelerator_view usa uma IUnknown interface e retorna um accelerator_view objeto. O método get_device pega um accelerator_view objeto e retorna uma IUnknown interface.
Ver também
C++ AMP (paralelismo maciço acelerado em C++)
Depurando código da GPU
accelerator_view Classe