
Tornadovm est un plug-in pour OpenJDK et GraalVM qui permet aux programmeurs d'exécuter automatiquement des programmes Java sur du matériel hétérogène. La tornadovm cible les dispositifs compatibles OpenCL, PTX et SPRI-V qui incluent des CPU multi-core, des GPU dédiés (Intel, NVIDIA, AMD), des GPU intégrés (Intel HD Graphics and Arm Mali) et FPGA (Intel et Xilinx).
La tornadovm a trois backends qui génèrent un assemblage OpenCl C, Nvidia Cuda PTX et Spir-V binaire. Les développeurs peuvent choisir les backends pour installer et exécuter.
Site Web : Tornadovm.org
Documentation : https://tornadovm.readthedocs.io/en/latest/
Pour une introduction rapide, veuillez lire la FAQ suivante.
Dernière version: Tornadovm 1.0.8 - 30/09/2024: Voir Changelog.
Dans Linux et MacOS, Tornadovm peut être installé automatiquement avec le script d'installation. Par exemple:
$ ./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 directoryRemarque Sélectionnez le backend souhaité:
opencl : Active le backend OpenCL (nécessite des pilotes OpenCL)ptx : Active le backend PTX (nécessite des pilotes Nvidia Cuda)spirv : Active le backend SPIRV (nécessite des pilotes Intel Level Zero)Exemple d'installation:
# 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,ptxAlternativement, la tornadovm peut être installée soit manuellement à partir de source, soit en utilisant Docker.
Si vous prévoyez d'utiliser Docker avec Tornadovm sur les GPU, vous pouvez également suivre ces directives.
Vous pouvez également exécuter Tornadovm sur les processeurs AWS AWS, les GPU et les FPGA Amazon après les instructions ici.
La tornadovm est actuellement utilisée pour accélérer l'apprentissage automatique et les applications d'apprentissage en profondeur, la vision par ordinateur, les simulations de physique, les applications financières, la photographie de calcul et le traitement du signal.
Cases d'utilisation en vedette:
Nous avons également un ensemble d'exemples qui incluent les calculs NBODY, DFT, KMEANS et Matrix.
Informations Complémentaires
Tornadovm expose au programme du programmeur au niveau de la tâche, au niveau des données et au niveau du pipeline via une interface de programmation d'application légère (API). De plus, Tornadovm utilise une propriété à source unique, dans laquelle le code à accélérer et le code hôte vivent dans le même programme Java.
Les cas de calcul dans la tornadovm peuvent être programmés en utilisant deux approches différentes (API):
Les noyaux de calcul sont écrits sous une forme séquentielle (tâches programmées pour une seule exécution de thread). Pour exprimer le parallélisme, la tornadovm expose deux annotations qui peuvent être utilisées dans les boucles et les paramètres: a) @Parallel pour annotation des boucles parallèles; et b) @Reduce pour les paramètres annotés utilisés dans les réductions.
L'extrait de code suivant montre un exemple complet pour accélérer la multiplication matricielle à l'aide de la tornadovm et de l'API Loop-Parallel:
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
// ...
}
}
} Une autre façon d'exprimer des bernées de calcul dans la tornaDovm est via l' API du noyau . Pour ce faire, Tornadovm expose la structure de données KernelContext , dans laquelle l'application peut accéder directement au thread-id, allouer la mémoire dans la mémoire locale (mémoire partagée sur les périphériques NVIDIA) et insérer des barrières. Ce modèle est similaire à la programmation des cas-cassaux dans SYCL, ONEAPI, OPENCL et CUDA. Par conséquent, cette API est plus adaptée aux programmeurs d'experts GPU / FPGA qui veulent plus de contrôle ou souhaitent porter des grains de calcul CUDA / OpenCL existants dans la tornadovm.
Le code-snippet suivant montre l'exemple de multiplication de la matrice à l'aide de l'API de noyau-parallèle:
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
// ...
}
}
}De plus, les deux modes d'expression parallélisme (noyau et parallélisation de boucle) peuvent être combinés dans le même objet de graphique de tâche.
La reconfiguration dynamique est la capacité de la tornadovm à effectuer une migration des tâches en direct entre les appareils, ce qui signifie que la tornadovm décide où exécuter le code pour augmenter les performances (si possible). En d'autres termes, la tornadovm change de dispositif s'il peut détecter qu'un dispositif spécifique peut produire de meilleures performances (par rapport à un autre).
Avec la tâche-migration, l'approche de la tornaDovm est de changer le périphérique si elle détecte qu'une application peut être exécutée plus rapidement que l'exécution du CPU à l'aide du code compilé par C2 ou Graal-Jit, sinon il restera sur le CPU. La tornadovm peut donc être considérée comme un complément aux compilateurs C2 et Graal Jit. En effet, il n'y a pas de matériel unique pour exécuter au mieux toutes les charges de travail efficacement. Les GPU sont très bons pour exploiter les applications SIMD, et les FPGA sont très bons pour exploiter les applications de pipeline. Si vos applications suivent ces modèles, Tornadovm sélectionnera probablement le matériel hétérogène. Sinon, il restera sur le CPU en utilisant les compilateurs par défaut (C2 ou GRAAL).
Pour utiliser la reconfiguration dynamique, vous pouvez exécuter à l'aide de politiques Tornadovm. Par exemple:
// TornadoVM will execute the code in the best accelerator.
executionPlan . withDynamicReconfiguration ( Policy . PERFORMANCE , DRMode . PARALLEL )
. execute ();De plus amples détails et des instructions sur la façon d'activer cette fonctionnalité peuvent être trouvés ici.
Pour utiliser Tornadovm, vous avez besoin de deux composants:
a) Le fichier jar Tornadovm auprès de l'API. L'API est sous licence GPLV2 à l'exception de ClassPath. b) Les bibliothèques principales de Tornadovm ainsi que la bibliothèque dynamique pour le code du pilote (fichiers .so pour OpenCL, PTX et / ou SPIRV / NIVEAU ZERO).
Vous pouvez importer l'API Tornadovm en définissant ceci la dépendance suivante dans le fichier 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 >Pour exécuter Tornadovm, vous devez soit installer l'extension Tornadovm pour GraalVM / OpenJDK, soit exécuter avec nos images Docker.
Ici, vous pouvez trouver des vidéos, des présentations, des articles technologiques et des artefacts décrivant la tornadovm et comment l'utiliser.
Si vous utilisez Tornadovm> = 0,2 (qui inclut la reconfiguration dynamique, la prise en charge FPGA initiale et les réductions CPU / GPU), veuillez utiliser la citation suivante:
@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 vous utilisez Tornado 0.1 (version initiale), veuillez utiliser la citation suivante dans votre travail.
@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 } ,
}Des publications sélectionnées peuvent être trouvées ici.
Ce travail est partiellement financé par Intel Corporation. De plus, il a été soutenu par les subventions de l'UE et de l'UKRI suivantes (le plus récent en premier):
De plus, la tornadovm a été soutenue par les subventions EPSRC suivantes:
Nous accueillons les collaborations! Veuillez voir comment contribuer au projet dans la page contributive.
De plus, vous pouvez ouvrir de nouvelles propositions sur la page des discussions GitHub.
Alternativement, vous pouvez partager un document Google avec nous.
Pour les collaborations académiques et de l'industrie, veuillez contacter ici.
Visitez notre site Web pour rencontrer l'équipe.
Pour utiliser Tornadovm, vous pouvez relier l'API Tornadovm à votre application qui est sous Apache 2.
Chaque module Java Tornadovm est sous licence comme suit:
| Module | Licence |
|---|---|
| Tornade | |
| Tornade | |
| Tornade | |
| Tornade | |
| Tornado-Drivers-OpenCl-Headers | |
| Tornade | |
| Tornade | |
| Tornades | |
| Tornado-benchmarks | |
| Tornado-Exemples | |
| Tornado-matrices | |