1 /*
  2  * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 package hat.test;
 26 
 27 import hat.Accelerator;
 28 import hat.ComputeContext;
 29 import hat.KernelContext;
 30 import hat.NDRange;
 31 import hat.backend.Backend;
 32 import hat.buffer.F32Array;
 33 import hat.buffer.S32Array;
 34 import hat.test.annotation.HatTest;
 35 import hat.test.exceptions.HATAsserts;
 36 import jdk.incubator.code.Reflect;
 37 import optkl.ifacemapper.MappableIface.RO;
 38 import optkl.ifacemapper.MappableIface.RW;
 39 import optkl.ifacemapper.MappableIface.WO;
 40 
 41 import java.lang.invoke.MethodHandles;
 42 import java.util.Random;
 43 
 44 public class TestArrays {
 45 
 46     @Reflect
 47     public static int squareit(int v) {
 48         return v * v;
 49 
 50     }
 51 
 52     @Reflect
 53     public static void squareKernel(KernelContext kc, S32Array array) {
 54         if (kc.gix < kc.gsx) {
 55             int value = array.array(kc.gix);
 56             array.array(kc.gix, squareit(value));
 57         }
 58     }
 59 
 60     @Reflect
 61     public static void square(@RO ComputeContext cc, @RW S32Array array) {
 62         cc.dispatchKernel(NDRange.of1D(array.length()),
 63                 kc -> squareKernel(kc, array)
 64         );
 65     }
 66 
 67     @Reflect
 68     public static void vectorAddition(KernelContext kc, S32Array arrayA, S32Array arrayB, S32Array arrayC) {
 69         if (kc.gix < kc.gsx) {
 70             int valueA = arrayA.array(kc.gix);
 71             int valueB = arrayB.array(kc.gix);
 72             arrayC.array(kc.gix, (valueA + valueB));
 73         }
 74     }
 75 
 76     @Reflect
 77     public static void vectorAdd(@RO ComputeContext cc, @RO S32Array arrayA, @RO S32Array arrayB, @WO S32Array arrayC) {
 78         cc.dispatchKernel(NDRange.of1D(arrayA.length()),
 79                 kc -> vectorAddition(kc, arrayA, arrayB, arrayC)
 80         );
 81     }
 82 
 83     @Reflect
 84     public static void saxpy(KernelContext kc, F32Array arrayA, F32Array arrayB, F32Array arrayC, float alpha) {
 85         if (kc.gix < kc.gsx) {
 86             float valueA = arrayA.array(kc.gix);
 87             float valueB = arrayB.array(kc.gix);
 88             float result = alpha * valueA + valueB;
 89             arrayC.array(kc.gix, result);
 90         }
 91     }
 92 
 93     @Reflect
 94     public static void computeSaxpy(@RO ComputeContext cc, @RO F32Array arrayA, @RO F32Array arrayB, @RW F32Array arrayC, float alpha) {
 95         cc.dispatchKernel(NDRange.of1D(arrayA.length()),
 96                 kc -> saxpy(kc, arrayA, arrayB, arrayC, alpha)
 97         );
 98     }
 99 
100     @HatTest
101     @Reflect
102     public static void testHelloHat() {
103         final int size = 64;
104         var accelerator = new Accelerator(MethodHandles.lookup(), Backend.FIRST);
105         var array = S32Array.create(accelerator, size);
106 
107         // Initialize array
108         for (int i = 0; i < array.length(); i++) {
109             array.array(i, i);
110         }
111 
112         // Blocking call
113         accelerator.compute(cc -> TestArrays.square(cc, array));
114 
115         S32Array test = S32Array.create(accelerator, size);
116 
117         for (int i = 0; i < test.length(); i++) {
118             test.array(i, squareit(i));
119         }
120 
121         for (int i = 0; i < test.length(); i++) {
122             HATAsserts.assertEquals(test.array(i), array.array(i));
123         }
124     }
125 
126     @HatTest
127     @Reflect
128     public static void testVectorAddition() {
129         final int size = 8192;
130         var accelerator = new Accelerator(MethodHandles.lookup(), Backend.FIRST);
131         var arrayA = S32Array.create(accelerator, size);
132         var arrayB = S32Array.create(accelerator, size);
133         var arrayC = S32Array.create(accelerator, size);
134 
135         // Initialize array
136         arrayA.fill(i -> i);
137         arrayB.fill(i -> 100 + i);
138 
139         accelerator.compute(cc ->
140                 TestArrays.vectorAdd(cc, arrayA, arrayB, arrayC));
141 
142         S32Array test = S32Array.create(accelerator, size);
143 
144         for (int i = 0; i < test.length(); i++) {
145             test.array(i, arrayA.array(i) + arrayB.array(i));
146         }
147 
148         for (int i = 0; i < test.length(); i++) {
149             HATAsserts.assertEquals(test.array(i), arrayC.array(i));
150         }
151     }
152 
153     @HatTest
154     @Reflect
155     public static void testVectorSaxpy() {
156         final int size = 8192;
157         var accelerator = new Accelerator(MethodHandles.lookup(), Backend.FIRST);
158         var arrayA = F32Array.create(accelerator, size);
159         var arrayB = F32Array.create(accelerator, size);
160         var arrayC = F32Array.create(accelerator, size);
161 
162         // Initialize array
163         Random r = new Random(71);
164         for (int i = 0; i < arrayA.length(); i++) {
165             arrayA.array(i, r.nextFloat());
166             arrayB.array(i, r.nextFloat());
167         }
168 
169         var alpha = 0.2f;
170         accelerator.compute(cc ->
171                 TestArrays.computeSaxpy(cc, arrayA, arrayB, arrayC, alpha));
172 
173         F32Array test = F32Array.create(accelerator, size);
174 
175         for (int i = 0; i < test.length(); i++) {
176             test.array(i, alpha * arrayA.array(i) + arrayB.array(i));
177         }
178 
179         for (int i = 0; i < test.length(); i++) {
180             HATAsserts.assertEquals(test.array(i), arrayC.array(i), 0.01f);
181         }
182     }
183 
184     @HatTest
185     @Reflect
186     public static void testSmallGrid() {
187 
188         final int size = 50;
189         var accelerator = new Accelerator(MethodHandles.lookup(), Backend.FIRST);
190         var arrayA = F32Array.create(accelerator, size);
191         var arrayB = F32Array.create(accelerator, size);
192         var arrayC = F32Array.create(accelerator, size);
193 
194         // Initialize array
195         Random r = new Random(71);
196         for (int i = 0; i < arrayA.length(); i++) {
197             arrayA.array(i, r.nextFloat());
198             arrayB.array(i, r.nextFloat());
199         }
200 
201         var alpha = 0.2f;
202         accelerator.compute(cc ->
203                 TestArrays.computeSaxpy(cc, arrayA, arrayB, arrayC, alpha));
204 
205         F32Array test = F32Array.create(accelerator, size);
206 
207         for (int i = 0; i < test.length(); i++) {
208             test.array(i, alpha * arrayA.array(i) + arrayB.array(i));
209         }
210 
211         for (int i = 0; i < test.length(); i++) {
212             HATAsserts.assertEquals(test.array(i), arrayC.array(i), 0.01f);
213         }
214     }
215 
216 }