1 # Building HAT
2
3 [Back to Index ../](../index.md)
4
5 We use `maven` and `cmake` to build HAT.
6
7 Maven controls the build but delegates to cmake for native artifacts (such as
8 `ffi-backends`), we also use `cmake` to provide `jextract`
9 with location information needed to reference various include and lib paths.
10 (See the [extractions/pom.xml](../../extractions/pom.xml) file).
11
12
13 ## Prerequisites
14
15 On Debian-based:
16
17 ```bash
18 sudo apt install cmake maven
19 ```
20
21 On RHEL-based:
22
23 ```bash
24 sudo dnf install cmake maven
25 ```
26
27 Or using `brew`:
28
29 ```bash
30 brew install cmake
31 brew install maven
32 ```
33
34 ## Setting environment variables JAVA_HOME and PATH
35
36 To build HAT we need to ensure that `JAVA_HOME` points to our Babylon JDK (the
37 one we built [here](babylon.md))
38
39 We also need to ensure that `${JAVA_HOME}/bin` is in our PATH (before any other
40 JAVA location).
41
42 We also need `jextract` for some maven targets.
43
44 We can download and install `jextract` from [here](https://jdk.java.net/jextract/)
45
46 The `env.bash` shell script can be sourced (dot included) in your shell to set
47 `JAVA_HOME` and `PATH`.
48
49 ```bash
50 cd hat
51 . ./env.bash
52 ```
53
54 This should detect the arch type (`AARCH64` or `X86_64`) and select the correct
55 relative parent directory and inject that directory in your `PATH` if you are
56 working with HAT in the original subdir of the babylon project.
57
58 ```bash
59 cd hat
60 source env.bash
61 ```
62
63 ## Building
64
65 Now we should be able to use maven to build, if successful maven will place all
66 jars and libs in a newly created `build` dir in your top level hat dir.
67
68 ```bash
69 cd hat
70 source env.bash
71 mvn clean package
72 ```
73
74 ## Running examples
75
76 To run we use some common java `opt` files.
77
78 When executing with `java` we can place common java parameters in files (say opts),
79 and then use `java @opts` to avoid typing all the opts each time.
80
81 To declutter the hat directory, we prefix some useful `opt` files with `.`
82
83 For example in the `.ffi-opencl-example` opt file we have:
84
85 ```bash
86 cat .ffi-opencl-example
87 --enable-preview --add-modules=jdk.incubator.code --enable-native-access=ALL-UNNAMED -Djava.library.path=build --class-path build/hat-ffi-opencl-examples-1.0.jar
88 ```
89
90 ### NBody
91
92 So you can run an example (say `nbody`) using the `opencl` backend using
93
94 ```bash
95 java @.ffi-opencl-example nbody.Main
96 ```
97
98 ### Matmul
99
100 ```bash
101 java @.ffi-opencl-example matmul.Main
102 ```
103
104 ### Flash Attention
105 ```bash
106 java @.ffi-opencl-example flashattention.Main
107 ```
108
109 ### ViolaJones
110
111 ```bash
112 HAT=MC java @.ffi-opencl-example violajones.Main
113 ```
114
115 ### Life
116
117 ```bash
118 HAT=MC java @.ffi-opencl-example life.Main
119 ```
120
121 ### Mandelbrot
122
123 ```bash
124 HAT=MC java @.ffi-opencl-example mandel.Main
125 ```
126
127 ## Running HAT Test Suite
128
129 #### OpenCL Test Suite
130
131 ```bash
132 java @.test-suite ffi-opencl
133 ```
134
135 #### CUDA Test Suite
136
137 ```bash
138 java @.test-suite ffi-cuda
139 ```
140
141 ----
142
143 ## HAT runtime environment variables
144
145 During ffi-backend development we added some useful flags to pass to native code
146 to allow us to trace calls, inject logging, control options.
147
148 These should be considered just development flags.
149
150 At runtime the ffi-backends all communicate from the java side to the native
151 side via a 32 bit 'config' int.
152
153 The Java side
154 class [hat.backend.ffi.Config](https://github.com/openjdk/babylon/blob/code-reflection/hat/backends/ffi/shared/src/main/java/hat/backend/ffi/Config.java)
155
156 Is initialized from an environment variable `HAT` at runtime
157
158 So for example when we launch
159
160 ```bash
161 java @hat/run ffi-opencl heal
162 ```
163
164 We can pass config info to `HAT` via either `-DHAT=xxx` or via the `HAT` ENV
165 variable.
166
167 So for example to get HAT to dump the text form of the kernel code models.
168
169 ```bash
170 HAT=INFO,SHOW_KERNEL_MODEL java @hat/run ffi-opencl heal
171 ```
172
173 Or to show generated opencl or cuda code
174
175 ```
176 HAT=INFO,SHOW_CODE java @hat/run ffi-opencl heal
177 ```
178
179 This is particularly useful for selecting `PLATFORM` + `DEVICE` if you have multiple
180 GPU devices.
181
182 Here we select DEVICE 0 on PLATFORM 0 (actually the default)
183
184 ```bash
185 HAT=INFO,PLATFORM:0,DEVICE:0,SHOW_CODE ...
186 ```
187
188 or for DEVICE 1 on PLATFORM 1
189
190 ```bash
191 HAT=INFO,PLATFORM:1,DEVICE:1,SHOW_CODE ...
192 ```
193
194 Note the platform and device id's are 3 bits. This probably works for
195 development, but we will need a more expressive way of capturing this via the
196 accelerator selection.
197
198 This just allows us to test without code changes.
199
200 To keep he java code and the native code in sync. The `main` method at the end
201 of
202 [hat.backend.ffi.Config](https://github.com/openjdk/babylon/blob/code-reflection/hat/backends/ffi/shared/src/main/java/hat/backend/ffi/Config.java)
203 is actually used to create the C99 header for CUDA and OpenCL ffi-backends.
204
205 So whenever we change the Java config class we should run the main method to
206 generate the header. This is not really robust, (but proved way better than
207 trying to remember for all backends) but you need to know, if you add move
208 config bits to the Java side.
209
210 The Main method uses a variant of the code builders used for C99 style code
211 (CUDA/OpenCL) to generate the config.h header.
212
213 This is how we keep the ffi based backends in sync
214
215 Some more useful `config bits`:
216
217 ```bash
218 HAT=PTX java @hat/run ffi-cuda ....
219 ```
220
221 Sends PTX generated by our prototype PTX generator to the backend (for CUDA)
222 rather than C99 code.
223
224 ```bash
225 HAT=INFO java @hat/run ....
226 ```
227
228 Will dump all of the `config bits` from the native side.
229
230 At present this yields
231
232 ```
233 native minimizeCopies 0
234 native trace 0
235 native profile 0
236 native showCode 0
237 native showKernelModel 0
238 native showComputeModel 0
239 native info 1
240 native traceCopies 0
241 native traceSkippedCopies 0
242 native traceEnqueues 0
243 native traceCalls 0
244 native showWhy 0
245 native showState 0
246 native ptx 0
247 native interpret 0
248 ```
249
250 Generally the flags all represent single bits (except PLATFORM:n and DEVICE:n)
251 and are set using comma separated uppercase+underscore string forms.
252
253 So to experiment with `minimizeCopies` and to `showCode` we set
254 `HAT=MINIMIZE_COPIES,SHOW_CODE`