
O Tornadovm é um plug-in para o OpenJDK e o GRAALVM que permite que os programadores executem automaticamente os programas Java em hardware heterogêneo. Dispositivos compatíveis com Tornadovm OpenCL, PTX e SPIR-V, que incluem CPUs multi-core, GPUs dedicadas (Intel, NVIDIA, AMD), GPUs integradas (gráficos Intel HD e Mali ARM) e FPGAs (Intel e Xilinx).
O Tornadovm tem três back-end que geram o conjunto de OpenCl C, Nvidia Cuda Ptx e SPIR-V binário. Os desenvolvedores podem escolher quais traseiros instalam e executam.
Site : Tornadovm.org
Documentação : https://tornadovm.readthedocs.io/en/latest/
Para uma introdução rápida, leia as seguintes perguntas frequentes.
Liberação mais recente: Tornadovm 1.0.8 - 30/09/2024: ver Changelog.
No Linux e MacOS, o Tornadovm pode ser instalado automaticamente com o script de instalação. Por exemplo:
$ ./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 Selecione o back -end desejado:
opencl : Ativa o back -end do OpenCL (requer drivers de OpenCL)ptx : Ativa o back -end do PTX (requer motoristas NVIDIA CUDA)spirv : Ativa o back -end da SPIRV (requer motoristas de nível de zero de nível Intel)Exemplo de instalação:
# 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,ptxComo alternativa, o Tornadovm pode ser instalado manualmente a partir da fonte ou usando o Docker.
Se você planeja usar o Docker com o Tornadovm nas GPUs, também pode seguir essas diretrizes.
Você também pode executar o Tornadovm nas CPUs da Amazon AWS, GPUs e FPGAs seguindo as instruções aqui.
Atualmente, o Tornadovm está sendo usado para acelerar aplicativos de aprendizado de máquina e aprendizado profundo, visão computacional, simulações de física, aplicações financeiras, fotografia computacional e processamento de sinais.
Casos de uso em destaque:
Também temos um conjunto de exemplos que incluem cálculos de nBody, DFT, Kmeans e matriz.
Informações adicionais
O Tornadovm expõe ao paralelismo no nível da tarefa, no nível de dados e no nível de dados e no nível de dados por meio de uma interface de programação de aplicativos leves (API). Além disso, o Tornadovm usa propriedade de fonte única, na qual o código a ser acelerado e o código do host ao vivo no mesmo programa Java.
Os kernels de computação em Tornadovm podem ser programados usando duas abordagens diferentes (APIs):
Os kernels de computação são gravados em um formulário seqüencial (tarefas programadas para uma única execução de encadeamento). Para expressar o paralelismo, o Tornadovm expõe duas anotações que podem ser usadas em loops e parâmetros: a) @Parallel para anotar loops paralelos; e b) @Reduce para anotar parâmetros usados em reduções.
O snippet de código a seguir mostra um exemplo completo para acelerar a multiplicação da matriz usando o Tornadovm e a API paralela ao loop:
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
// ...
}
}
} Outra maneira de expressar os kernels de computação em Tornadovm é através da API do kernel . Para isso, o Tornadovm expõe a estrutura de dados KernelContext , na qual o aplicativo pode acessar diretamente a ID do thread-ID, alocar memória na memória local (memória compartilhada em dispositivos NVIDIA) e inserir barreiras. Este modelo é semelhante à programação de computação-Kernels em SYCL, ONEAPI, OPENCL e CUDA. Portanto, esta API é mais adequada para programadores especialistas em GPU/FPGA que desejam mais controle ou portar os kernels de computação CUDA/OpenCL existentes para o Tornadovm.
O seguinte snippet de código mostra o exemplo de multiplicação da matriz usando a API paralela do kernel:
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
// ...
}
}
}Além disso, os dois modos de expressar paralelismo (paralelização do kernel e loop) podem ser combinados no mesmo objeto gráfico de tarefas.
A reconfiguração dinâmica é a capacidade do Tornadovm de realizar a migração de tarefas ao vivo entre os dispositivos, o que significa que o Tornadovm decide onde executar o código para aumentar o desempenho (se possível). Em outras palavras, o Tornadovm troca de dispositivos se puder detectar que um dispositivo específico pode produzir um melhor desempenho (em comparação com outro).
Com a migração de tarefas, a abordagem do Tornadovm é alternar apenas o dispositivo se detectar um aplicativo pode ser executado mais rapidamente que a execução da CPU usando o código compilado por C2 ou Graal-Jit, caso contrário, ele permanecerá na CPU. Portanto, o Tornadovm pode ser visto como um complemento aos compiladores C2 e Graal JIT. Isso ocorre porque não existe um hardware único para executar melhor todas as cargas de trabalho com eficiência. As GPUs são muito boas em explorar aplicativos SIMD, e os FPGAs são muito bons em explorar aplicativos de pipeline. Se seus aplicativos seguirem esses modelos, o Tornadovm provavelmente selecionará hardware heterogêneo. Caso contrário, ele permanecerá na CPU usando os compiladores padrão (C2 ou Graal).
Para usar a reconfiguração dinâmica, você pode executar usando políticas de Tornadovm. Por exemplo:
// TornadoVM will execute the code in the best accelerator.
executionPlan . withDynamicReconfiguration ( Policy . PERFORMANCE , DRMode . PARALLEL )
. execute ();Mais detalhes e instruções sobre como ativar esse recurso podem ser encontrados aqui.
Para usar o Tornadovm, você precisa de dois componentes:
a) O arquivo jar Tornadovm com a API. A API é licenciada como GPLV2 com a exceção do ClassPath. b) As principais bibliotecas do Tornadovm, juntamente com a biblioteca dinâmica do código do driver (arquivos .so para OpenCL, PTX e/ou SPIRV/Nível Zero).
Você pode importar a API do Tornadovm definindo isso a seguinte dependência no arquivo 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 executar o Tornadovm, você precisa instalar a extensão do Tornadovm para Graalvm/OpenJDK ou executar com nossas imagens do Docker.
Aqui você pode encontrar vídeos, apresentações, artigos de tecnologia e artefatos que descrevem o Tornadovm e como usá-lo.
Se você estiver usando Tornadovm> = 0,2 (que inclui a reconfiguração dinâmica, o suporte inicial do FPGA e as reduções de CPU/GPU), use a seguinte citação:
@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 }
}Se você estiver usando o Tornado 0.1 (liberação inicial), use a seguinte citação em seu trabalho.
@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 } ,
}Publicações selecionadas podem ser encontradas aqui.
Este trabalho é parcialmente financiado pela Intel Corporation. Além disso, foi apoiado pelas seguintes doações da UE e Ukri (mais recente primeiro):
Além disso, o Tornadovm foi apoiado pelas seguintes doações do EPSRC:
Congratulamo -nos com colaborações! Consulte como contribuir para o projeto na página contribuinte.
Além disso, você pode abrir novas propostas na página de discussões do Github.
Como alternativa, você pode compartilhar um documento do Google conosco.
Para colaborações acadêmicas e da indústria, entre em contato aqui.
Visite nosso site para conhecer a equipe.
Para usar o Tornadovm, você pode vincular a API do Tornadovm ao seu aplicativo, que está no Apache 2.
Cada módulo Java Tornadovm é licenciado da seguinte forma:
| Módulo | Licença |
|---|---|
| Tornado-api | |
| Runtime de tornado | |
| Montagem do tornado | |
| Tornado-drivers | |
| Tornado-Drivers-OpenCl-headers | |
| Tornado-scripts | |
| Anitação de tornados | |
| Tornado-Unittests | |
| Tornado-benchmarks | |
| Exemplos de tornados | |
| Tornado-matrizes | |