1 /*
  2  * Copyright (c) 2020, 2024, 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.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 package org.openjdk.bench.valhalla.matrix;
 24 
 25 import org.openjdk.bench.valhalla.types.Complex;
 26 import org.openjdk.bench.valhalla.types.QComplex;
 27 import org.openjdk.jmh.annotations.Benchmark;
 28 import org.openjdk.jmh.annotations.CompilerControl;
 29 import org.openjdk.jmh.annotations.Setup;
 30 
 31 import java.util.concurrent.ThreadLocalRandom;
 32 
 33 public abstract class Inline extends Base {
 34 
 35     public static final Complex IZERO = new QComplex(0,0);
 36     public static final QComplex VZERO = new QComplex(0,0);
 37     public static final QComplex RZERO = new QComplex(0,0);
 38 
 39     private static void populate(Complex[][] m) {
 40         int size = m.length;
 41         for (int i = 0; i < size; i++) {
 42             for (int j = 0; j < size; j++) {
 43                 m[i][j] = new QComplex(ThreadLocalRandom.current().nextDouble(), ThreadLocalRandom.current().nextDouble());
 44             }
 45         }
 46     }
 47 
 48 //    public static class Ref extends Inline {
 49 //
 50 //    }
 51 
 52     public static class Ref extends Inline {
 53         QComplex[][] A;
 54         QComplex[][] B;
 55 
 56         @Setup
 57         public void setup() {
 58             A = new QComplex[size][size];
 59             populate(A);
 60             B = new QComplex[size][size];
 61             populate(B);
 62         }
 63 
 64         @Benchmark
 65         @CompilerControl(CompilerControl.Mode.DONT_INLINE)
 66         public QComplex[][] multiply() {
 67             int size = A.length;
 68             QComplex[][] R = new QComplex[size][size];
 69             for (int i = 0; i < size; i++) {
 70                 for (int j = 0; j < size; j++) {
 71                     QComplex s = RZERO;
 72                     for (int k = 0; k < size; k++) {
 73                         s = s.add(A[i][k].mul(B[k][j]));
 74                     }
 75                     R[i][j] = s;
 76                 }
 77             }
 78             return R;
 79         }
 80 
 81 //        @Benchmark
 82 //        public QComplex[][] multiplyCacheFriendly() {
 83 //            int size = A.length;
 84 //            QComplex[][] R = new QComplex[size][size];
 85 //            for (int i = 0; i < size; i++) {
 86 //                for (int k = 0; k < size; k++) {
 87 //                    QComplex aik = A[i][k];
 88 //                    for (int j = 0; j < size; j++) {
 89 //                        R[i][j] = R[i][j].add(aik.mul(B[k][j]));
 90 //                    }
 91 //                }
 92 //            }
 93 //            return R;
 94 //        }
 95 
 96     }
 97 
 98     public static class Val extends Inline {
 99         QComplex[][] A;
100         QComplex[][] B;
101 
102         @Setup
103         public void setup() {
104             A = new QComplex[size][size];
105             populate(A);
106             B = new QComplex[size][size];
107             populate(B);
108         }
109 
110         @Benchmark
111         @CompilerControl(CompilerControl.Mode.DONT_INLINE)
112         public QComplex[][] multiply() {
113             int size = A.length;
114             QComplex[][] R = new QComplex[size][size];
115             for (int i = 0; i < size; i++) {
116                 for (int j = 0; j < size; j++) {
117                     QComplex s = VZERO;
118                     for (int k = 0; k < size; k++) {
119                         s = s.add(A[i][k].mul(B[k][j]));
120                     }
121                     R[i][j] = s;
122                 }
123             }
124             return R;
125         }
126 
127 //        @Benchmark
128 //        public QComplex[][] multiplyCacheFriendly() {
129 //            int size = A.length;
130 //            QComplex[][] R = new QComplex[size][size];
131 //            for (int i = 0; i < size; i++) {
132 //                for (int k = 0; k < size; k++) {
133 //                    QComplex aik = A[i][k];
134 //                    for (int j = 0; j < size; j++) {
135 //                        R[i][j] = R[i][j].add(aik.mul(B[k][j]));
136 //                    }
137 //                }
138 //            }
139 //            return R;
140 //        }
141 
142     }
143 
144     public static class Int extends Inline {
145         Complex[][] A;
146         Complex[][] B;
147 
148         @Setup
149         public void setup() {
150             A = new Complex[size][size];
151             populate(A);
152             B = new Complex[size][size];
153             populate(B);
154         }
155 
156         @Benchmark
157         @CompilerControl(CompilerControl.Mode.DONT_INLINE)
158         public Complex[][] multiply() {
159             int size = A.length;
160             Complex[][] R = new Complex[size][size];
161             for (int i = 0; i < size; i++) {
162                 for (int j = 0; j < size; j++) {
163                     Complex s = IZERO;
164                     for (int k = 0; k < size; k++) {
165                         s = s.add(A[i][k].mul(B[k][j]));
166                     }
167                     R[i][j] = s;
168                 }
169             }
170             return R;
171         }
172     }
173 
174     public static class ICov extends Inline {
175         Complex[][] A;
176         Complex[][] B;
177 
178         @Setup
179         public void setup() {
180             A = new QComplex[size][size];
181             populate(A);
182             B = new QComplex[size][size];
183             populate(B);
184         }
185 
186         @Benchmark
187         @CompilerControl(CompilerControl.Mode.DONT_INLINE)
188         public Complex[][] multiply() {
189             int size = A.length;
190             Complex[][] R = new QComplex[size][size];
191             for (int i = 0; i < size; i++) {
192                 for (int j = 0; j < size; j++) {
193                     Complex s = IZERO;
194                     for (int k = 0; k < size; k++) {
195                         s = s.add(A[i][k].mul(B[k][j]));
196                     }
197                     R[i][j] = s;
198                 }
199             }
200             return R;
201         }
202 
203 //        @Benchmark
204 //        public Complex[][] multiplyCacheFriendly() {
205 //            int size = A.length;
206 //            Complex[][] R = new QComplex[size][size];
207 //            for (int i = 0; i < size; i++) {
208 //                for (int k = 0; k < size; k++) {
209 //                    Complex aik = A[i][k];
210 //                    for (int j = 0; j < size; j++) {
211 //                        R[i][j] = R[i][j].add(aik.mul(B[k][j]));
212 //                    }
213 //                }
214 //            }
215 //            return R;
216 //        }
217 
218     }
219 
220     public static class RCov extends Inline {
221         QComplex[][] A;
222         QComplex[][] B;
223 
224         @Setup
225         public void setup() {
226             A = new QComplex[size][size];
227             populate(A);
228             B = new QComplex[size][size];
229             populate(B);
230         }
231 
232         @Benchmark
233         @CompilerControl(CompilerControl.Mode.DONT_INLINE)
234         public QComplex[][] multiply() {
235             int size = A.length;
236             QComplex[][] R = new QComplex[size][size];
237             for (int i = 0; i < size; i++) {
238                 for (int j = 0; j < size; j++) {
239                     QComplex s = RZERO;
240                     for (int k = 0; k < size; k++) {
241                         s = s.add(A[i][k].mul(B[k][j]));
242                     }
243                     R[i][j] = s;
244                 }
245             }
246             return R;
247         }
248 
249 //        @Benchmark
250 //        public Complex[][] multiplyCacheFriendly() {
251 //            int size = A.length;
252 //            Complex[][] R = new QComplex[size][size];
253 //            for (int i = 0; i < size; i++) {
254 //                for (int k = 0; k < size; k++) {
255 //                    Complex aik = A[i][k];
256 //                    for (int j = 0; j < size; j++) {
257 //                        R[i][j] = R[i][j].add(aik.mul(B[k][j]));
258 //                    }
259 //                }
260 //            }
261 //            return R;
262 //        }
263 
264     }
265 
266 }