
Tornadovm ist ein Plug-In zu OpenJDK und GraalVM, mit dem Programmierer Java-Programme automatisch auf heterogenen Hardware ausführen können. Tornadovm Ziele OpenCL, PTX und SPIR-V-kompatible Geräte, die Multi-Core-CPUs, dedizierte GPUs (Intel, Nvidia, AMD), integriertes GPUs (Intel HD Graphics und Arm Mali) und FPGAS (Intel und Xilinx) enthalten.
Tornadovm hat drei Backends, die OpenCL C, Nvidia Cuda PTX-Assemblierung und Binäranlagen erzeugen. Entwickler können auswählen, welche Backends installiert und ausgeführt werden sollen.
Website : Tornadovm.org
Dokumentation : https://tornadovm.readthedocs.io/en/latest/
Für eine kurze Einführung lesen Sie bitte die folgenden FAQs.
Letzte Veröffentlichung: Tornadovm 1.0.8 - 30/09/2024: Siehe ChangeLog.
In Linux und MacOS kann Tornadovm automatisch mit dem Installationsskript installiert werden. Zum Beispiel:
$ ./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 directoryHinweis Wählen Sie das gewünschte Backend aus:
opencl : Ermöglicht das OpenCL -Backend (erfordert OpenCL -Treiber).ptx : Ermöglicht das PTX -Backend (erfordert Nvidia CUDA -Treiber)spirv : Ermöglicht das Spirv -Backend (erfordert Intel Level Null -Treiber)Beispiel der 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,ptxAlternativ kann Tornadovm entweder manuell aus der Quelle oder mithilfe von Docker installiert werden.
Wenn Sie vorhaben, Docker mit Tornadovm bei GPUs zu verwenden, können Sie diese Richtlinien auch befolgen.
Sie können auch Tornadovm auf Amazon AWS CPUs, GPUs und FPGAs ausführen, die den Anweisungen hier folgen.
Tornadovm wird derzeit verwendet, um maschinelles Lernen und Deep -Learning -Anwendungen, Computer Vision, Physiksimulationen, Finanzanwendungen, Computerfotografie und Signalverarbeitung zu beschleunigen.
Ausgewählte Anwendungsfälle:
Wir haben auch eine Reihe von Beispielen, die NBODY, DFT, KMEANS -Rechen- und Matrixberechnungen umfassen.
Weitere Informationen
Tornadovm setzt über eine Parallelität auf Task-Level-, Datenebene und Pipeline-Ebene über eine Light Application Programming Interface (API) aus. Darüber hinaus verwendet Tornadovm eine Single-Source-Eigenschaft, in der der zu beschleunigte Code und der Hostcode im selben Java-Programm live live.
Rechenkern in Tornadovm können mit zwei verschiedenen Ansätzen (APIs) programmiert werden:
Berechnenkerne sind in sequentieller Form geschrieben (Aufgaben, die für eine einzelne Threadausführung programmiert sind). Um Parallelität auszudrücken, enthält Tornadovm zwei Anmerkungen, die in Schleifen und Parametern verwendet werden können: a) @Parallel zum Annotieren paralleler Schleifen; und b) @Reduce für Annotierungsparameter, die bei Reduktionen verwendet werden.
Das folgende Code-Snippet zeigt ein vollständiges Beispiel zur Beschleunigung der Matrix-Multiplikation mit Tornadovm und der Loop-Parallel-API:
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
// ...
}
}
} Eine andere Möglichkeit, Berechnungskerns in Tornadovm auszudrücken, ist die Kernel-API . Dazu enthält Tornadovm die KernelContext -Datenstruktur, in der die Anwendung direkt auf den Thread-ID zugreifen kann, Speicher im lokalen Speicher (gemeinsamer Speicher auf NVIDIA-Geräten) zuordnen und Barrieren einfügen. Dieses Modell ähnelt der Programmierberechnung in Sycl, Oneapi, OpenCL und CUDA. Daher eignet sich diese API besser für GPU/FPGA -Expertenprogrammierer, die mehr Kontrolle haben oder vorhandene CUDA/OpenCL -Rechenkerne in Tornadovm berechnen möchten.
Das folgende Code-Snippet zeigt das Beispiel für die Matrix-Multiplikation unter Verwendung der Kernel-Parallel-API:
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
// ...
}
}
}Zusätzlich können die beiden Modi des Ausdrucks der Parallelität (Kernel- und Schleifenparallelisierung) in demselben Task -Graph -Objekt kombiniert werden.
Die dynamische Neukonfiguration ist die Fähigkeit von Tornadovm, eine Live -Aufgabenmigration zwischen Geräten durchzuführen, was bedeutet, dass Tornadovm entscheidet, wo der Code ausgeführt wird, um die Leistung zu erhöhen (wenn möglich). Mit anderen Worten, Tornadovm schaltet Geräte, wenn er feststellen kann, dass ein bestimmtes Gerät eine bessere Leistung liefern kann (im Vergleich zu einem anderen).
Mit der Aufgabenmigration besteht der Ansatz von Tornadovm darin, das Gerät nur zu wechseln, wenn er erkennt, dass eine Anwendung schneller ausgeführt werden kann als die CPU-Ausführung unter Verwendung des von C2 oder Graal-Jit zusammengestellten Codes, andernfalls bleibt er auf der CPU. So kann Tornadovm als Ergänzung zu C2- und Graal -JIT -Compilern angesehen werden. Dies liegt daran, dass es keine einzige Hardware gibt, um alle Workloads effizient am besten auszuführen. GPUs sind sehr gut darin, SIMD -Anwendungen zu nutzen, und FPGAs sind sehr gut darin, Pipeline -Anwendungen zu nutzen. Wenn Ihre Anwendungen diesen Modellen folgen, wählt Tornadovm wahrscheinlich heterogene Hardware aus. Andernfalls bleibt es mit den Standard Compilern (C2 oder Graal) auf der CPU.
Um die dynamische Neukonfiguration zu verwenden, können Sie mithilfe von Tornadovm -Richtlinien ausführen. Zum Beispiel:
// TornadoVM will execute the code in the best accelerator.
executionPlan . withDynamicReconfiguration ( Policy . PERFORMANCE , DRMode . PARALLEL )
. execute ();Weitere Details und Anweisungen zum Aktivieren dieser Funktion finden Sie hier.
Um Tornadovm zu verwenden, benötigen Sie zwei Komponenten:
A) Die Tornadovm jar -Datei mit der API. Die API ist mit Ausnahme von Klassenpfad als GPLV2 lizenziert. b) Die Kernbibliotheken von Tornadovm zusammen mit der dynamischen Bibliothek für den Treibercode ( .so -Dateien für OpenCL, PTX und/oder Spirv/Level Null).
Sie können die Tornadovm -API importieren, indem Sie diese die folgende Abhängigkeit in der Datei maven pom.xml festlegen:
< 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 >Um Tornadovm auszuführen, müssen Sie entweder die Tornadovm -Erweiterung für Graalvm/OpenJDK installieren oder mit unseren Docker -Bildern ausgeführt werden.
Hier finden Sie Videos, Präsentationen, Tech-Artikeln und Artefakte, die Tornadovm beschreiben und wie man sie benutzt.
Wenn Sie Tornadovm> = 0,2 verwenden (einschließlich der dynamischen Rekonfiguration, die anfängliche FPGA -Unterstützung und die CPU/GPU -Reduzierungen), verwenden Sie bitte das folgende Zitat:
@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 }
}Wenn Sie Tornado 0.1 (erste Version) verwenden, verwenden Sie bitte das folgende Zitat in Ihrer Arbeit.
@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 } ,
}Ausgewählte Veröffentlichungen finden Sie hier.
Diese Arbeit wird teilweise von der Intel Corporation finanziert. Darüber hinaus wurde es von den folgenden EU & UKRI -Zuschüssen (zuletzt zuerst) unterstützt:
Darüber hinaus wurde Tornadovm durch die folgenden EPSRC -Zuschüsse unterstützt:
Wir begrüßen Kooperationen! Bitte beachten Sie, wie Sie zum Projekt auf der beitragenden Seite beitragen.
Zusätzlich können Sie neue Vorschläge auf der Seite GitHub -Diskussionen eröffnen.
Alternativ können Sie ein Google -Dokument mit uns teilen.
Für akademische und branchenübergreifende Kooperationen wenden Sie sich bitte hier an.
Besuchen Sie unsere Website, um das Team zu treffen.
Um Tornadovm zu verwenden, können Sie die Tornadovm -API mit Ihrer Anwendung unter Apache 2 verknüpfen.
Jedes Java -Tornadovm -Modul ist wie folgt lizenziert:
| Modul | Lizenz |
|---|---|
| Tornado-api | |
| Tornado-Runtime | |
| Tornado-Assembly | |
| Tornado-Fahrer | |
| Tornado-Schuld-OpenCl-Header | |
| Tornado-Skripte | |
| Tornado-Annotation | |
| Tornado-Unittest | |
| Tornado-Benchmarks | |
| Tornado-Beispiele | |
| Tornado-Matrizen | |