Usando objetos accelerator e accelerator_view
Você pode usar as classes accelerator e accelerator_view para especificar o dispositivo ou o emulador para executar sobre seu código AMP C++.Um sistema pode ter vários dispositivos ou emuladores que diferem pela quantidade de memória, suporte de depuração ou o suporte de precisão dupla.O Paralelismo Massivo Acelerado C++ (AMP C++) fornece APIs que você pode usar para examinar os aceleradores disponíveis, para definir um como padrão, para especificar vários aceleradores para chamadas múltiplos ao parallel_for_each, e para executar tarefas de depuração especial.
Usando o acelerador padrão
O tempo de execução de AMP C++ escolhe um acelerador padrão, a menos que você escrever código para escolher um específico.O tempo de execução escolhe o acelerador padrão da seguinte maneira:
Se o aplicativo é executado no modo de depuração, um acelerador que ofereça suporte a depuração.
Caso contrário, o acelerador que é especificado pela variável de ambiente de CPPAMP_DEFAULT_ACCELERATOR, 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 é anexado a exibir.
Você pode determinar as propriedades de aceleradores padrão construindo o acelerador padrão e examinando suas propriedades.O exemplo de código a seguir mostra o caminho, a memória e o suporte de precisão dupla de aceleradores padrão.
void default_properties() {
accelerator default_acc;
std::wcout << default_acc.device_path << "\n";
std::wcout << default_acc.dedicated_memory << "\n";
std::wcout << (default_acc.supports_double_precision ?
"double precision: true" : "double precision: false") << "\n";
}
Variável de ambiente CPPAMP_DEFAULT_ACCELERATOR
Você pode definir a variável de ambiente CPPAMP_DEFAULT_ACCELERATOR para especificar accelerator::device_path de aceleradores padrão.O caminho é dependente de hardware.O código a seguir usa a função accelerator::get_all para recuperar uma lista de aceleradores disponíveis e exibir o caminho 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_double_precision ?
"double precision: true" : "double precision: false") << "\n";
}
}
Selecionando um acelerador
Para selecionar um acelerador, use o método accelerator::get_all para recuperar uma lista de aceleradores disponíveis e então selecione um com base em suas propriedades.Este exemplo mostra como escolher o acelerador que tem a maior 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 CPU.Você não pode executar código no acelerador CPU.Para filtrar o acelerador de CPU, compare o valor da propriedade device_path de aceleradores que é retornado por accelerator::get_all com o valor de accelerator::cpu_accelerator.Para obter mais informações, consulte a seção “Aceleradores Especiais” neste artigo. |
Alterando o acelerador padrão
Você pode alterar o acelerador padrão chamando o método accelerator::set_default .Você pode alterar o acelerador padrão apenas uma vez por execução de aplicativo e você deve alterá-la antes que qualquer código seja executado no GPU.Quaisquer chamadas de função subsequentes para alterar o acelerador retorna false.Se você deseja usar um acelerador diferente em uma chamada para parallel_for_each leia a seção “Usando múltiplos aceleradores” neste artigo.O exemplo de código a seguir define o acelerador padrão para um que não é emulado, não é conectado a uma exibição e oferece suporte de 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 múltiplos aceleradores
Há duas maneiras de usar múltiplos aceleradores em seu aplicativo:
Você pode passar objetos accelerator_view para chamadas ao método parallel_for_each .
Você pode criar um objeto array usando um objeto específico accelerator.O tempo de execução AMP C++ pegará o objeto accelerator_view do objeto capturado array na expressão lambda.
Aceleradores especiais
Os caminhos de dispositivo de três aceleradores especiais estão disponíveis como propriedades da classe accelerator :
Membro de dados de Accelerator::direct3d_ref: Este acelerador de thread única usa software no CPU para emular uma placa gráfica genérica.Usado por padrão de depuração, mas não é útil para a produção porque é mais lento do que os aceleradores de hardware.Além de isso, está disponível somente em DirectX SDK e o Windows SDK, e é improvável que esteja instalado nos computadores dos seus clientes.Para obter mais informações, consulte Depuração de código GPU.
Membro de dados de Accelerator::direct3d_warp: Este acelerador fornece uma solução de retorno para executar o código de AMP C++ em CPUs multi-core que usam extensões Streaming SIMD (SSE, em inglês).
Membro de dados de Accelerator::cpu_accelerator: Você pode usar esse acelerador para configurar matrizes de teste.Não pode executar o código de AMP C++.Para obter mais informações, consulte Matrizes de teste em AMP C++ postagem em programação paralela no blog de código nativo.
Interoperabilidade
Interoperabilidade de suporte em tempo de execução do AMP C++ entre a classe accelerator_view e o Direct3D interface de ID3D11Device.O método create_accelerator_view usa uma interface IUnknown e retorna um objeto accelerator_view .O método get_device utiliza um objeto accelerator_view e retorna uma interface IUknown .