1 # Heterogeneous Accelerator Toolkit (HAT)
  2 
  3 [![repo](https://img.shields.io/badge/github-repo-blue?logo=github)](https://github.com/openjdk/babylon/tree/code-reflection/hat)
  4 
  5 HAT is a toolkit that allows developers to express data-parallel applications in Java, optimize, offload and execute them on hardware accelerators.
  6 - **Heterogeneous**: a variety of devices and their corresponding programming languages.
  7 - **Accelerator**: GPUs, FPGA, CPUs, etc.
  8 - **Toolkit**: a set of libraries for Java developers.
  9 
 10 HAT uses the code reflection API from the [Project Babylon](https://github.com/openjdk/babylon).
 11 
 12 The toolkit offers:
 13 - An API for SIMT (Single Instruction Multiple Thread) Kernel Programming on Accelerators from Java.
 14 - An API for Tile Kernel Programming on Accelerators from Java. Currently only available to target NVIDIA GPUs (Ampere or later).
 15 - An API for Combining multiple kernels into a compute-graph.
 16 - An API for Java object mapping to hardware accelerators using Panama FFM.
 17 - An extensible backend system for multiple accelerators:
 18   - OpenCL C
 19   - CUDA C/C++
 20   - Java
 21 
 22 ## Prerequisites
 23 
 24 - HAT currently requires Babylon JDK, which contains the code reflection APIs.
 25 - A base JDK >= 26. We currently use OpenJDK 26 for development.
 26 - A GPU SDK (one or more of the SDKs below) to be able to run on GPUs:
 27   - An OpenCL implementation (e.g., Intel, Apple Silicon, CUDA SDK)
 28     - OpenCL >= 1.2
 29   - CUDA SDK >= 13.0
 30 - `cmake` >= `3.22.1`
 31 - `gcc` >= 12.0, or `clang` >= 17.0
 32 
 33 ## Compatible systems
 34 
 35 We actively develop and run benchmarks on the following systems:
 36 
 37 - Apple Silicon M1-M5
 38 - Linux Fedora >= 43
 39 - Oracle Linux >= 10.0
 40 - Ubuntu >= 22.04
 41 
 42 ## Quick Start
 43 
 44 ### 1. Build Babylon JDK
 45 
 46 ```bash
 47 git clone https://github.com/openjdk/babylon
 48 cd babylon
 49 bash configure --with-boot-jdk=${JAVA_HOME}
 50 make clean
 51 make images
 52 ```
 53 
 54 ### 2. Update JAVA_HOME and PATH
 55 
 56 ```bash
 57 cd hat/
 58 source env.bash
 59 ```
 60 
 61 The env.bash script will setup the `JAVA_HOME` and the `PATH` to use the Babylon JDK.
 62 
 63 Alternatively, you can run it manually:
 64 
 65 ```bash
 66 export JAVA_HOME=<BABYLON-DIR>/build/macosx-aarch64-server-release/images/jdk
 67 export PATH=$JAVA_HOME/bin:$PATH
 68 ```
 69 
 70 ### 3. Install HAT specific tools (cmake and maven)
 71 
 72 Either:
 73 
 74 ```bash
 75 brew install maven
 76 brew install cmake
 77 ```
 78 
 79 Or
 80 
 81 ```bash
 82 ## Debian-based distros
 83 sudo apt-get install maven cmake
 84 
 85 ## For RHEL-based distros
 86 sudo dnf install maven cmake
 87 ```
 88 
 89 ### 4. Build HAT
 90 
 91 ```bash
 92 cd <path-to>/babylon/hat
 93 mvn clean package
 94 ```
 95 
 96 Done!
 97 
 98 ## Run Examples
 99 
100 For instance, matrix-multiply:
101 
102 ```bash
103 java @.ffi-opencl-example matmul.Main --size=1024
104 ```
105 
106 Some examples have a GUI implementation:
107 
108 ```java
109 java @.ffi-opencl-example mandel.Main
110 ```
111 
112 Full list of examples:
113 - [link](https://github.com/openjdk/babylon/tree/code-reflection/hat/examples)
114 
115 
116 ## Run Unit-Tests
117 
118 OpenCL backend:
119 
120 ```bash
121 java @.ffi-opencl-test-suite
122 ```
123 
124 CUDA backed:
125 
126 ```bash
127 java @.ffi-cuda-test-suite
128 ```
129 
130 ## Full Example Explained (SMIT Model)
131 
132 The following example compute the square value of an input vector.
133 The example is self-contained and it can be directly run with the `java` command.
134 
135 Place the following code in the `hat` directory.
136 
137 ```java
138 import hat.*;
139 import hat.Accelerator.Compute;
140 import hat.backend.*;
141 import hat.buffer.*;
142 import optkl.ifacemapper.MappableIface.*;
143 import jdk.incubator.code.Reflect;
144 import java.lang.invoke.MethodHandles;
145 
146 import static hat.KernelContext.*;
147 
148 public class ExampleHAT {
149 
150     // Kernel Code: This is the function to be offloaded to the accelerator (e.g.,
151     // a GPU). The kernel will be executed by many GPU threads, in this case,
152     // as many threads as elements in `array`.
153     // HAT kernels follow the SIMT programming model (Single Instruction Multiple Thread)
154     // mode.
155     // Kernel code is reflectable. Thus, the HAT runtime and HAT compiler can build
156     // and optimize the code model. Once the code model is optimized, HAT generates
157     // OpenCL/CUDA C99 code.
158     @Reflect
159     public static void squareKernel(S32Array array) {
160         // HAT kernels support a reduced set of Java.
161         // Kernels express the work to be done per thread (GPU/accelerator thread).
162         // Use GIX() to obtain the thread global id for the first dimension
163         if (GIX() < array.length()) {
164             int value = array.array(GIX());
165             array.array(GIX(), (value * value));
166         }
167     }
168 
169     // The following method represents the compute layer, in which we specify
170     // the number of threads to be deployed on the accelerator. The number of threads
171     // is specified in an ND-Range. An ND-Range could be 1D, 2D and 3D.
172     // In this example, we launch 1D-range with the number of threads equal to
173     // the input array size.
174     @Reflect
175     public static void square(ComputeContext cc, S32Array array) {
176         var ndRange = NDRange.of1D(array.length());
177 
178         // Dispatch the kernel. The HAT runtime will offload the kernels
179         // reached from this point and run the generated GPU kernels on the
180         // target accelerator.
181         // Furthermore, HAT automatically transfers data to the accelerator.
182         // This is a blocking call, and when it returns control to the main
183         // Java thread, results (outputs) are available to be consumed.
184         cc.dispatchKernel(ndRange, () -> squareKernel(array));
185     }
186 
187     static void main() {
188         final int size = 4096;
189         // Create a new accelerator object
190         var accelerator = new Accelerator(MethodHandles.lookup(), Backend.FIRST);
191 
192         // Instantiate an array on the target accelerator.
193         // Data is stored off-heap using the Panama FFM API.
194         var array = S32Array.create(accelerator, size);
195 
196         // Data initialization
197         for (int i = 0; i < array.length(); i++) {
198             array.array(i, i);
199         }
200 
201         // Dispatch the set of kernels defined in the compute-layer on the target accelerator.
202         // This is a blocking call. Once this call finalizes, the results (outputs)
203         // will be available to consume by the current Java thread.
204         accelerator.compute((@Reflect Compute) cc -> ExampleHAT.square(cc, array));
205 
206         // Test result
207         boolean isCorrect = true;
208         for (int i = 0; i < size; i++) {
209             if (array.array(i) != i * i) {
210                 isCorrect = false;
211             }
212         }
213         if (isCorrect) {
214             IO.println("Result is correct");
215         } else {
216             IO.println("Result is NOT correct");
217         }
218     }
219 }
220 ```
221 
222 Run this example in the `babylon/hat` directory.
223 If you run from another directory, update the `--class-path` parameter accordingly.
224 Use the `java` version built with the Babylon JDK.
225 
226 ```bash
227 java --enable-preview \
228    --add-modules=jdk.incubator.code \
229    --enable-native-access=ALL-UNNAMED \
230    --class-path build/hat-optkl-1.0.jar:build/hat-core-1.0.jar:build/hat-backend-ffi-shared-1.0.jar:build/hat-backend-ffi-opencl-1.0.jar \
231    -Djava.library.path=build \
232    ExampleHAT.java
233 ```
234 
235 If you run with `HAT=INFO` you can see which accelerator was used:
236 
237 ```bash
238 $ HAT=INFO java --enable-preview \
239    --add-modules=jdk.incubator.code \
240    --enable-native-access=ALL-UNNAMED \
241    --class-path build/hat-optkl-1.0.jar:build/hat-core-1.0.jar:build/hat-backend-ffi-shared-1.0.jar:build/hat-backend-ffi-opencl-1.0.jar \
242    -Djava.library.path=build \
243   ExampleHAT.java
244 
245 [INFO] Config Bits = 8000
246 [INFO] Platform :"Apple"
247 [INFO]   Version      :"OpenCL 1.2 (Jan 16 2026 07:22:26)"
248 [INFO]   Name         :"Apple"
249 [INFO]   Device Type  : GPU  4
250 [INFO] OpenCLBackend::OpenCLQueue::dispatch
251 [INFO] numDimensions: 1
252 [INFO] GLOBAL [4096,1,1]
253 [INFO] LOCAL  [ nullptr ] // The driver will setup a default value
254 ```
255 
256 ## Documentation
257 
258 Visit the [docs](docs/) folder.
259 
260 ## Contributing
261 
262 Contributions are welcome. Please see the [OpenJDK Developers' Guide](https://openjdk.org/guide/).
263 
264 ## Development Workflow
265 
266 1. Fork the repository
267 2. Create a feature branch: `git checkout -b <branch>`
268 3. Commit with clear messages
269 4. Run formatting and tests:
270    1. For OpenCL: `java @.ffi-opencl-test-suite`
271    1. For CUDA: `java @.ffi-cuda-test-suite`
272 5. Submit a pull request
273 
274 
275 ## Contacts/Questions
276 
277 You can interact, provide feedback and ask questions using the [babylon-dev](https://mail.openjdk.org/archives/list/babylon-dev@openjdk.org/) mailing list.
278