
Tornadovm es un complemento para OpenJDK y Graalvm que permite a los programadores ejecutar automáticamente programas Java en hardware heterogéneo. TornadovM se dirige a los dispositivos compatibles con OpenCL, PTX y SIG-V que incluyen CPU de múltiples núcleos, GPU dedicadas (Intel, NVIDIA, AMD), GPU integradas (Intel HD Graphics y Arm Mali) y FPGA (Intel y Xilinx).
Tornadovm tiene tres backends que generan OpenCl C, ensamblaje NVIDIA CUDA PTX y binario SIGR-V. Los desarrolladores pueden elegir qué backends instalar y ejecutar.
Sitio web : Tornadovm.org
Documentación : https://toNnadovm.readthedocs.io/en/latest/
Para una introducción rápida, lea las siguientes preguntas frecuentes.
Último lanzamiento: Tornadovm 1.0.8 - 30/09/2024: ver ChangeLog.
En Linux y MacOS, Tornadovm se puede instalar automáticamente con el script de instalación. Por ejemplo:
$ ./bin/tornadovm-installer
usage: tornadovm-installer [-h] [--version] [--jdk JDK] [--backend BACKEND] [--listJDKs] [--javaHome JAVAHOME]
TornadoVM Installer Tool. It will install all software dependencies except the GPU/FPGA drivers
optional arguments:
-h, --help show this help message and exit
--version Print version of TornadoVM
--jdk JDK Select one of the supported JDKs. Use --listJDKs option to see all supported ones.
--backend BACKEND Select the backend to install: { opencl, ptx, spirv }
--listJDKs List all JDK supported versions
--javaHome JAVAHOME Use a JDK from a user directoryNota Seleccione el backend deseado:
opencl : habilita el backend de OpenCl (requiere controladores de opencl)ptx : habilita el backend PTX (requiere controladores Nvidia Cuda)spirv : habilita el backend de Spirv (requiere controladores cero de nivel Intel)Ejemplo de instalación:
# Install the OpenCL backend with OpenJDK 21
$ ./bin/tornadovm-installer --jdk jdk21 --backend opencl
# It is also possible to combine different backends:
$ ./bin/tornadovm-installer --jdk jdk21 --backend opencl,spirv,ptxAlternativamente, TornadovM se puede instalar manualmente desde la fuente o utilizando Docker.
Si planea usar Docker con Tornadovm en GPU, también puede seguir estas pautas.
También puede ejecutar Tornadovm en Amazon AWS CPUS, GPU y FPGA siguiendo las instrucciones aquí.
Tornadovm se está utilizando actualmente para acelerar las aplicaciones de aprendizaje automático y aprendizaje profundo, visión por computadora, simulaciones físicas, aplicaciones financieras, fotografía computacional y procesamiento de señales.
Casos de uso destacados:
También tenemos un conjunto de ejemplos que incluyen Nbody, DFT, Computación de Kmeans y cálculos de matriz.
información adicional
Tornadovm expone al paralelismo a nivel de tarea del programador, a nivel de datos y paralelismo a nivel de tubería a través de una interfaz de programación de aplicaciones de luz (API). Además, Tornadovm utiliza una propiedad de fuente única, en la que el código se acelerará y el código de host vivo en el mismo programa Java.
Los kernos de cómputo en Tornadovm se pueden programar utilizando dos enfoques diferentes (API):
Los núcleos de cómputo se escriben en forma secuencial (tareas programadas para una ejecución de un solo hilo). Para expresar el paralelismo, Tornadovm expone dos anotaciones que pueden usarse en bucles y parámetros: a) @Parallel para anotar bucles paralelos; y b) @Reduce para anotar los parámetros utilizados en reducciones.
El siguiente fragmento de código muestra un ejemplo completo para acelerar la matriz-multiplicación usando tornadovm y la API de bucle-paralelo:
public class Compute {
private static void mxmLoop ( Matrix2DFloat A , Matrix2DFloat B , Matrix2DFloat C , final int size ) {
for ( @ Parallel int i = 0 ; i < size ; i ++) {
for ( @ Parallel int j = 0 ; j < size ; j ++) {
float sum = 0.0f ;
for ( int k = 0 ; k < size ; k ++) {
sum += A . get ( i , k ) * B . get ( k , j );
}
C . set ( i , j , sum );
}
}
}
public void run ( Matrix2DFloat A , Matrix2DFloat B , Matrix2DFloat C , final int size ) {
// Create a task-graph with multiple tasks. Each task points to an exising Java method
// that can be accelerated on a GPU/FPGA
TaskGraph taskGraph = new TaskGraph ( "myCompute" )
. transferToDevice ( DataTransferMode . FIRST_EXECUTION , A , B ) // Transfer data from host to device only in the first execution
. task ( "mxm" , Compute :: mxmLoop , A , B , C , size ) // Each task points to an existing Java method
. transferToHost ( DataTransferMode . EVERY_EXECUTION , C ); // Transfer data from device to host
// Create an immutable task-graph
ImmutableTaskGraph immutableTaskGraph = taskGraph . snaphot ();
// Create an execution plan from an immutable task-graph
try ( TornadoExecutionPlan executionPlan = new TornadoExecutionPlan ( immutableTaskGraph )) {
// Run the execution plan on the default device
TorandoExecutionResult executionResult = executionPlan . execute ();
} catch ( TornadoExecutionPlanException e ) {
// handle exception
// ...
}
}
} Otra forma de expresar los kernos de cómputo en Tornadovm es a través de la API del núcleo . Para hacerlo, Tornadovm expone la estructura de datos KernelContext , en la que la aplicación puede acceder directamente al ID de subproceso, asignar memoria en la memoria local (memoria compartida en dispositivos NVIDIA) e insertar barreras. Este modelo es similar a la programación de los kernos en Sycl, Onapi, OpenCl y CUDA. Por lo tanto, esta API es más adecuada para programadores expertos de GPU/FPGA que desean más control o desean transferir los núcleos CUDA/OpenCL de OpenCl en Tornadovm.
El siguiente código-snippet muestra el ejemplo de multiplicación de matriz usando la API de kernel-paralelo:
public class Compute {
private static void mxmKernel ( KernelContext context , Matrix2DFloat A , Matrix2DFloat B , Matrix2DFloat C , final int size ) {
int idx = context . globalIdx
int jdx = context . globalIdy ;
float sum = 0 ;
for ( int k = 0 ; k < size ; k ++) {
sum += A . get ( idx , k ) * B . get ( k , jdx );
}
C . set ( idx , jdx , sum );
}
public void run ( Matrix2DFloat A , Matrix2DFloat B , Matrix2DFloat C , final int size ) {
// When using the kernel-parallel API, we need to create a Grid and a Worker
WorkerGrid workerGrid = new WorkerGrid2D ( size , size ); // Create a 2D Worker
GridScheduler gridScheduler = new GridScheduler ( "myCompute.mxm" , workerGrid ); // Attach the worker to the Grid
KernelContext context = new KernelContext (); // Create a context
workerGrid . setLocalWork ( 16 , 16 , 1 ); // Set the local-group size
TaskGraph taskGraph = new TaskGraph ( "myCompute" )
. transferToDevice ( DataTransferMode . FIRST_EXECUTION , A , B ) // Transfer data from host to device only in the first execution
. task ( "mxm" , Compute :: mxmKernel , context , A , B , C , size ) // Each task points to an existing Java method
. transferToHost ( DataTransferMode . EVERY_EXECUTION , C ); // Transfer data from device to host
// Create an immutable task-graph
ImmutableTaskGraph immutableTaskGraph = taskGraph . snapshot ();
// Create an execution plan from an immutable task-graph
try ( TornadoExecutionPlan executionPlan = new TornadoExecutionPlan ( immutableTaskGraph )) {
// Run the execution plan on the default device
// Execute the execution plan
TorandoExecutionResult executionResult = executionPlan
. withGridScheduler ( gridScheduler )
. execute ();
} catch ( TornadoExecutionPlanException e ) {
// handle exception
// ...
}
}
}Además, los dos modos de expresión del paralelismo (paralelización de núcleo y bucle) se pueden combinar en el mismo objeto de gráfico de tareas.
La reconfiguración dinámica es la capacidad de Tornadovm para realizar la migración de tareas en vivo entre dispositivos, lo que significa que Tornadovm decide dónde ejecutar el código para aumentar el rendimiento (si es posible). En otras palabras, TornadovM cambia los dispositivos si puede detectar que un dispositivo específico puede producir un mejor rendimiento (en comparación con otro).
Con la migración de tareas, el enfoque de TornadovM es solo cambiar el dispositivo si detecta una aplicación se puede ejecutar más rápido que la ejecución de la CPU utilizando el código compilado por C2 o Graal-Jit, de lo contrario permanecerá en la CPU. Por lo tanto, Tornadovm puede verse como un complemento para los compiladores C2 y Graal JIT. Esto se debe a que no hay hardware único para ejecutar mejor todas las cargas de trabajo de manera eficiente. Las GPU son muy buenas para explotar las aplicaciones SIMD, y las FPGA son muy buenas para explotar las aplicaciones de la tubería. Si sus aplicaciones siguen esos modelos, Tornadovm probablemente seleccionará hardware heterogéneo. De lo contrario, permanecerá en la CPU utilizando los compiladores predeterminados (C2 o Graal).
Para usar la reconfiguración dinámica, puede ejecutar utilizando políticas Tornadovm. Por ejemplo:
// TornadoVM will execute the code in the best accelerator.
executionPlan . withDynamicReconfiguration ( Policy . PERFORMANCE , DRMode . PARALLEL )
. execute ();Se pueden encontrar más detalles e instrucciones sobre cómo habilitar esta función aquí.
Para usar Tornadovm, necesita dos componentes:
a) El archivo jar tornadovm con la API. La API tiene licencia como GPLV2 con excepción de classpath. b) Las bibliotecas centrales de Tornadovm junto con la biblioteca dinámica para el código del controlador (archivos .so para OpenCL, PTX y/o Spirv/Level Zero).
Puede importar la API TornadovM estableciendo esto la siguiente dependencia en el archivo maven pom.xml :
< repositories >
< repository >
< id >universityOfManchester-graal</ id >
< url >https://raw.githubusercontent.com/beehive-lab/tornado/maven-tornadovm</ url >
</ repository >
</ repositories >
< dependencies >
< dependency >
< groupId >tornado</ groupId >
< artifactId >tornado-api</ artifactId >
< version >1.0.8</ version >
</ dependency >
< dependency >
< groupId >tornado</ groupId >
< artifactId >tornado-matrices</ artifactId >
< version >1.0.8</ version >
</ dependency >
</ dependencies >Para ejecutar Tornadovm, debe instalar la extensión Tornadovm para GRAALVM/OpenJDK, o ejecutar con nuestras imágenes Docker.
Aquí puede encontrar videos, presentaciones, artelos tecnológicos y artefactos que describen Tornadovm, y cómo usarlo.
Si está utilizando tornadovm> = 0.2 (que incluye la reconfiguración dinámica, el soporte FPGA inicial y las reducciones de CPU/GPU), utilice la siguiente cita:
@inproceedings { Fumero:DARHH:VEE:2019 ,
author = { Fumero, Juan and Papadimitriou, Michail and Zakkak, Foivos S. and Xekalaki, Maria and Clarkson, James and Kotselidis, Christos } ,
title = { {Dynamic Application Reconfiguration on Heterogeneous Hardware.} } ,
booktitle = { Proceedings of the 15th ACM SIGPLAN/SIGOPS International Conference on Virtual Execution Environments } ,
series = { VEE '19 } ,
year = { 2019 } ,
doi = { 10.1145/3313808.3313819 } ,
publisher = { Association for Computing Machinery }
}Si está utilizando Tornado 0.1 (lanzamiento inicial), utilice la siguiente cita en su trabajo.
@inproceedings { Clarkson:2018:EHH:3237009.3237016 ,
author = { Clarkson, James and Fumero, Juan and Papadimitriou, Michail and Zakkak, Foivos S. and Xekalaki, Maria and Kotselidis, Christos and Luj'{a}n, Mikel } ,
title = { {Exploiting High-performance Heterogeneous Hardware for Java Programs Using Graal} } ,
booktitle = { Proceedings of the 15th International Conference on Managed Languages & Runtimes } ,
series = { ManLang '18 } ,
year = { 2018 } ,
isbn = { 978-1-4503-6424-9 } ,
location = { Linz, Austria } ,
pages = { 4:1--4:13 } ,
articleno = { 4 } ,
numpages = { 13 } ,
url = { http://doi.acm.org/10.1145/3237009.3237016 } ,
doi = { 10.1145/3237009.3237016 } ,
acmid = { 3237016 } ,
publisher = { ACM } ,
address = { New York, NY, USA } ,
keywords = { Java, graal, heterogeneous hardware, openCL, virtual machine } ,
}Las publicaciones seleccionadas se pueden encontrar aquí.
Este trabajo está parcialmente financiado por Intel Corporation. Además, ha sido respaldado por las siguientes subvenciones de la UE y Ucri (más reciente):
Además, Tornadovm ha sido apoyado por las siguientes subvenciones de EPSRC:
¡Damos la bienvenida a las colaboraciones! Consulte cómo contribuir al proyecto en la página contribuyente.
Además, puede abrir nuevas propuestas en la página de discusiones de GitHub.
Alternativamente, puede compartir un documento de Google con nosotros.
Para colaboraciones académicas e industriales, comuníquese aquí.
Visite nuestro sitio web para conocer al equipo.
Para usar Tornadovm, puede vincular la API Tornadovm a su aplicación que está en Apache 2.
Cada módulo Java Tornadovm tiene licencia de la siguiente manera:
| Módulo | Licencia |
|---|---|
| Tornado-api | |
| Tornado-runmime | |
| Ensamblaje de tornados | |
| Conductores de tornados | |
| Tornado-Drivers-Opencl-Headers | |
| Scripts de tornados | |
| Anotación de tornado | |
| Tornado-sintests | |
| Tornado-benchmarks | |
| Prueba de tornado | |
| Matrices de tornados | |