Usar objetos accelerator y accelerator_view
Se pueden utilizar las clases accelerator y accelerator_view para especificar el dispositivo o emulador para ejecutar el código en C++ AMP.Un sistema podría tener varios dispositivos o emuladores que difieren según la cantidad de memoria, la compatibilidad de depuración o la compatibilidad de doble precisión.El Paralelismo masivo acelerado C++ (C++ AMP) ofrece varias especificaciones de API que se pueden utilizar para examinar los aceleradores disponibles, establecer uno como valor predeterminado, especificar varios aceleradores para múltiples llamadas a parallel for each y realizar tareas especiales de depuración.
Usar el acelerador predeterminado
El runtime de C++ AMP selecciona un acelerador predeterminado, a menos que se escriba el código para especificar alguno.El runtime elige el acelerador predeterminado como se muestra a continuación:
Si la aplicación se ejecuta en modo depuración, un acelerador admite la depuración.
De lo contrario, el acelerador especificado por la variable del entorno es CPPAMP_DEFAULT_ACCELERATOR, si se establece.
O un dispositivo no emulado.
O el dispositivo que contiene la cantidad máxima de memoria disponible.
Si no , un dispositivo que no está asociado a la pantalla.
Se pueden determinar las propiedades del acelerador predeterminado mediante la construcción del acelerador predeterminado y el examen de sus propiedades.El siguiente ejemplo de código imprime la ruta de acceso, la memoria y la compatibilidad de doble precisión del acelerador predeterminado.
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";
}
Variable del entorno CPPAMP_DEFAULT_ACCELERATOR
Se puede establecer la variable del entorno CPPAMP_DEFAULT_ACCELERATOR para especificar el accelerator::device_path del acelerador predeterminado.La ruta de acceso es dependiente del hardware.El siguiente código utiliza la función accelerator::get_all para recuperar una lista de los aceleradores disponibles y después mostrar la ruta de acceso 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";
}
}
Selección de un acelerador
Para seleccionar un acelerador, utilice el método accelerator::get_all para recuperar una lista de los aceleradores disponibles y luego seleccione uno teniendo en cuenta sus propiedades.El siguiente ejemplo muestra cómo elegir el acelerador que tenga la máxima memoria:
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";
}
[!NOTA]
Uno de los aceleradores devueltos por accelerator::get_all es el acelerador de CPU.No se puede ejecutar el código en el acelerador CPU.Para filtrar el acelerador de CPU, compare el valor de la propiedad device_path del acelerador devuelto por accelerator::get_all con el valor de accelerator::cpu_accelerator.Para obtener más información, consulte la sección «Aceleradores especiales» en este mismo artículo.
Cambio del acelerador predeterminado
Se puede cambiar el acelerador predeterminado llamando al método accelerator::set_default.Sólo se puede cambiar el acelerador predeterminado una vez por ejecución de la aplicación y además se debe cambiar antes de que el código sea ejecutado en el GPU.Cualquier llamada de función posterior para cambiar el acelerador devuelve false.Si se desea utilizar otro acelerador en una llamada a parallel_for_each, lea la sección “Utilización de varios aceleradores” en este artículo.El siguiente ejemplo de código establece el acelerador predeterminado en uno que no se emula, no está conectado a una pantalla y admite doble precisión.
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;
}
Utilización de varios aceleradores
Hay dos maneras de utilizar varios aceleradores en la aplicación:
Se pueden pasar los objetos accelerator_view a las llamadas a los métodos parallel_for_each.
Se puede construir un objeto array mediante un objeto específico accelerator.El tiempo de ejecución de C+AMP elegirá el objeto accelerator_view desde el objeto capturado array en la expresión lambda.
Aceleradores especiales
Las rutas de acceso de tres aceleradores especiales están disponibles como propiedades de la clase accelerator:
accelerator::direct3d_ref (Miembro de datos): Este acelerador de un único subproceso utiliza el software de la CPU para emular una tarjeta de gráficos genérica.Se utiliza de forma predeterminada para la depuración, pero no es útil en la producción porque es más lento que los aceleradores de hardware.Además solo está disponible en DirectX SDK y Windows SDK y es poco probable que esté instalado en los equipos de los clientes.Para obtener más información, vea Depurar código de GPU.
accelerator::direct3d_warp (Miembro de datos): Este acelerador ofrece una solución de reserva para ejecutar el código C++ AMP en los CPU de varios núcleos que utilizan las extensiones Streaming SIMD (SSE).
accelerator::cpu_accelerator (Miembro de datos): Puede utilizar este acelerador para establecer las matrices provisionales.No se puede ejecutar el código de C++ AMP.Para obtener más información, consulte Matrices provisionales en C++ AMP publicado en Programación paralela en el blog de código nativo.
Interoperabilidad
El tiempo de ejecución de C++ AMPadmite la interoperabilidad entre la clase accelerator_view y el Direct3D interfaz de ID3D11Device.El método create_accelerator_view toma una interfaz IUnknown y devuelve un objeto accelerator_view.El método get_device toma un objeto accelerator_view y devuelve una interfaz IUknown.