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`