Skip to content

Commit a8b209a

Browse files
committed
cpu and gpu tests
1 parent 1f06b00 commit a8b209a

File tree

10 files changed

+299
-9
lines changed

10 files changed

+299
-9
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.github.TannerLow.JavaMatrixMath.Exceptions;
2+
3+
public class DimensionsMismatchException extends IllegalArgumentException {
4+
5+
private int[] dimensionsA;
6+
private int[] dimensionsB;
7+
8+
public DimensionsMismatchException(int[] dimensionsA, int[] dimensionsB) {
9+
super();
10+
this.dimensionsA = dimensionsA;
11+
this.dimensionsB = dimensionsB;
12+
}
13+
14+
@Override
15+
public String getMessage() {
16+
String dimensionsAString = dimensionsToString(this.dimensionsA);
17+
String dimensionsBString = dimensionsToString(this.dimensionsB);
18+
return "Dimensions mismatch: " + dimensionsAString + " " + dimensionsBString;
19+
}
20+
21+
private static String dimensionsToString(final int[] dimensions) {
22+
if(dimensions == null || dimensions.length == 0) {
23+
return "(0)";
24+
}
25+
26+
StringBuilder sb = new StringBuilder();
27+
sb.append("(");
28+
sb.append(dimensions[0]);
29+
for(int i = 1; i < dimensions.length; i++) {
30+
sb.append("x");
31+
sb.append(dimensions[i]);
32+
}
33+
sb.append(")");
34+
35+
return sb.toString();
36+
}
37+
}

src/main/java/com/github/TannerLow/GPU.java renamed to src/main/java/com/github/TannerLow/JavaMatrixMath/GPU.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
package com.github.TannerLow;
1+
package com.github.TannerLow.JavaMatrixMath;
22

33
import org.jocl.CL;
44
import org.jocl.Pointer;
5-
import org.jocl.Sizeof;
65
import org.jocl.cl_command_queue;
76
import org.jocl.cl_context;
87
import org.jocl.cl_context_properties;
@@ -37,7 +36,6 @@
3736
import static org.jocl.CL.clReleaseContext;
3837
import static org.jocl.CL.clReleaseKernel;
3938
import static org.jocl.CL.clReleaseProgram;
40-
import static org.jocl.CL.clSetKernelArg;
4139

4240
public class GPU implements Closeable {
4341
private static final long deviceType = CL_DEVICE_TYPE_GPU;
@@ -159,12 +157,12 @@ public int loadProgram(String programCode) {
159157
return programs.size()-1;
160158
}
161159

162-
public boolean loadKernel(int programId, String programName, String kernelName) {
160+
public boolean loadKernel(int programId, String scopeName, String kernelName) {
163161
if(programId >= programs.size() && programId < 0) {
164162
return false;
165163
}
166164

167-
String scopedKernelName = programName + "::" + kernelName;
165+
String scopedKernelName = scopeName + "::" + kernelName;
168166

169167
if(kernels.containsKey(scopedKernelName)) {
170168
throw new InvalidParameterException("Kernel of that name and scope already exists on GPU.");

src/main/java/com/github/TannerLow/InternalFile.java renamed to src/main/java/com/github/TannerLow/JavaMatrixMath/InternalFile.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.github.TannerLow;
1+
package com.github.TannerLow.JavaMatrixMath;
22

33
import java.io.InputStream;
44

src/main/java/com/github/TannerLow/Matrix.java renamed to src/main/java/com/github/TannerLow/JavaMatrixMath/Matrix.java

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
package com.github.TannerLow;
1+
package com.github.TannerLow.JavaMatrixMath;
22

3+
import com.github.TannerLow.JavaMatrixMath.Exceptions.DimensionsMismatchException;
34
import org.jocl.Pointer;
45
import org.jocl.Sizeof;
56
import org.jocl.cl_command_queue;
@@ -39,9 +40,11 @@ public Matrix(int rows, int cols, float[] data) {
3940
}
4041
}
4142

42-
public Matrix multiply(Matrix other) {
43+
public Matrix multiply(Matrix other) throws DimensionsMismatchException {
4344
if(cols != other.rows) {
44-
return null;
45+
final int[] dimensionsA = {rows, cols};
46+
final int[] dimensionsB = {other.rows, other.cols};
47+
throw new DimensionsMismatchException(dimensionsA, dimensionsB);
4548
}
4649

4750
Matrix result = new Matrix(rows, other.cols);
@@ -59,6 +62,35 @@ public Matrix multiply(Matrix other) {
5962
return result;
6063
}
6164

65+
public Matrix addRowToRows(Matrix row) throws DimensionsMismatchException {
66+
if(cols != row.cols) {
67+
final int[] dimensionsA = {rows, cols};
68+
final int[] dimensionsB = {row.rows, row.cols};
69+
throw new DimensionsMismatchException(dimensionsA, dimensionsB);
70+
}
71+
72+
Matrix result = new Matrix(rows, cols);
73+
74+
for(int currentRow = 0; currentRow < rows; currentRow++) {
75+
for(int col = 0; col < cols; col++) {
76+
int index = currentRow * cols + col;
77+
result.data[index] = data[index] + row.data[col];
78+
}
79+
}
80+
81+
return result;
82+
}
83+
84+
public Matrix relu() {
85+
Matrix result = new Matrix(rows, cols);
86+
87+
for(int i = 0; i < data.length; i++) {
88+
result.data[i] = Math.max(data[i], 0);
89+
}
90+
91+
return result;
92+
}
93+
6294
public static boolean isCompatibleWithGPU(GPU gpu) {
6395
return gpu.isInitialized() &&
6496
gpu.getKernel("Matrices::matrixMultiply") != null &&
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package com.github.TannerLow.JavaMatrixMath;
2+
3+
import com.github.TannerLow.TestUtils.TestFailedException;
4+
import com.github.TannerLow.TestUtils.TestMath;
5+
6+
public class CpuTest {
7+
public static void testAll() {
8+
testMultiply();
9+
testAddRowToRows();
10+
testRelu();
11+
}
12+
13+
private static void testMultiply() {
14+
float[] aData = {1,2,3,0,1,0};
15+
float[] bData = {1,0,1,3,2,1};
16+
float[] expected = {9,9,1,3};
17+
18+
Matrix a = new Matrix(2,3, aData);
19+
Matrix b = new Matrix(3,2, bData);
20+
21+
Matrix result = a.multiply(b);
22+
23+
if(result.rows != a.rows || result.cols != b.cols) {
24+
throw new TestFailedException();
25+
}
26+
27+
for(int i = 0; i < result.data.length; i++) {
28+
if(!TestMath.withinMariginOfError(expected[i], result.data[i], 0.0005f)) {
29+
throw new TestFailedException();
30+
}
31+
}
32+
}
33+
34+
private static void testAddRowToRows() {
35+
float[] aData = {1,2,3,0,0,0};
36+
float[] bData = {3,2,1};
37+
float[] expected = {4,4,4,3,2,1};
38+
39+
Matrix a = new Matrix(2,3, aData);
40+
Matrix b = new Matrix(1,3, bData);
41+
42+
Matrix result = a.addRowToRows(b);
43+
44+
if(result.rows != a.rows || result.cols != a.cols) {
45+
throw new TestFailedException();
46+
}
47+
48+
for(int i = 0; i < result.data.length; i++) {
49+
if(!TestMath.withinMariginOfError(expected[i], result.data[i], 0.0005f)) {
50+
throw new TestFailedException();
51+
}
52+
}
53+
}
54+
55+
private static void testRelu() {
56+
float[] data = {-1,2,-3,0};
57+
float[] expected = {0,2,0,0};
58+
59+
Matrix m = new Matrix(2, 2, data);
60+
61+
Matrix result = m.relu();
62+
63+
if(result.rows != m.rows || result.cols != m.cols) {
64+
throw new TestFailedException();
65+
}
66+
67+
for(int i = 0; i < result.data.length; i++) {
68+
if(!TestMath.withinMariginOfError(expected[i], result.data[i], 0.0005f)) {
69+
throw new TestFailedException();
70+
}
71+
}
72+
}
73+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package com.github.TannerLow.JavaMatrixMath;
2+
3+
import com.github.TannerLow.TestUtils.TestFailedException;
4+
import com.github.TannerLow.TestUtils.TestMath;
5+
6+
import java.io.IOException;
7+
import java.io.InputStream;
8+
import java.nio.charset.StandardCharsets;
9+
10+
public class GpuTest {
11+
12+
private static final GPU gpu = new GPU();
13+
14+
public static void testAll() throws IOException {
15+
try(gpu) {
16+
setup();
17+
18+
testMultiply();
19+
testAddRowToRows();
20+
testRelu();
21+
}
22+
}
23+
24+
private static void setup() throws IOException {
25+
// Load GPU program code into memory
26+
String matricesKernelFilePath = "kernels/Matrices.cl";
27+
String matricesKernelCode = readFromInternalFile(matricesKernelFilePath);
28+
if(matricesKernelCode == null) {
29+
throw new IOException("Failed to read file: " + matricesKernelFilePath);
30+
}
31+
32+
gpu.initialize(true);
33+
int programId = gpu.loadProgram(matricesKernelCode);
34+
gpu.loadKernel(programId, "Matrices", "matrixMultiply");
35+
gpu.loadKernel(programId, "Matrices", "addRowToRows");
36+
gpu.loadKernel(programId, "Matrices", "relu");
37+
38+
if(!gpu.isInitialized()) {
39+
throw new IllegalStateException("GPU in unexpected state.");
40+
}
41+
}
42+
43+
private static void testMultiply() {
44+
float[] aData = {1,2,3,0,1,0};
45+
float[] bData = {1,0,1,3,2,1};
46+
float[] expected = {9,9,1,3};
47+
48+
Matrix a = new Matrix(2,3, aData);
49+
Matrix b = new Matrix(3,2, bData);
50+
51+
Matrix result = a.multiply(gpu, b);
52+
53+
if(result.rows != a.rows || result.cols != b.cols) {
54+
throw new TestFailedException();
55+
}
56+
57+
for(int i = 0; i < result.data.length; i++) {
58+
if(!TestMath.withinMariginOfError(expected[i], result.data[i], 0.0005f)) {
59+
throw new TestFailedException();
60+
}
61+
}
62+
}
63+
64+
private static void testAddRowToRows() {
65+
float[] aData = {1,2,3,0,0,0};
66+
float[] bData = {3,2,1};
67+
float[] expected = {4,4,4,3,2,1};
68+
69+
Matrix a = new Matrix(2,3, aData);
70+
Matrix b = new Matrix(1,3, bData);
71+
72+
Matrix result = a.addRowToRows(gpu, b);
73+
74+
if(result.rows != a.rows || result.cols != a.cols) {
75+
throw new TestFailedException();
76+
}
77+
78+
for(int i = 0; i < result.data.length; i++) {
79+
if(!TestMath.withinMariginOfError(expected[i], result.data[i], 0.0005f)) {
80+
throw new TestFailedException();
81+
}
82+
}
83+
}
84+
85+
private static void testRelu() {
86+
float[] data = {-1,2,-3,0};
87+
float[] expected = {0,2,0,0};
88+
89+
Matrix m = new Matrix(2, 2, data);
90+
91+
Matrix result = m.relu(gpu);
92+
93+
if(result.rows != m.rows || result.cols != m.cols) {
94+
throw new TestFailedException();
95+
}
96+
97+
for(int i = 0; i < result.data.length; i++) {
98+
if(!TestMath.withinMariginOfError(expected[i], result.data[i], 0.0005f)) {
99+
throw new TestFailedException();
100+
}
101+
}
102+
}
103+
104+
private static String readFromInternalFile(String filepath) {
105+
try(InputStream fileInputStream = InternalFile.getInstance().getFileInputStream(filepath)) {
106+
byte[] bytes = fileInputStream.readAllBytes();
107+
String fileContent = new String(bytes, StandardCharsets.UTF_8);
108+
return fileContent;
109+
} catch (Exception e) {
110+
e.printStackTrace();
111+
}
112+
113+
return null;
114+
}
115+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.github.TannerLow.JavaMatrixMath;
2+
3+
import com.github.TannerLow.TestUtils.TestSuiteFailedException;
4+
5+
public class Tester {
6+
public static void main(String[] args) throws TestSuiteFailedException {
7+
try {
8+
CpuTest.testAll();
9+
GpuTest.testAll();
10+
}
11+
catch(Exception e) {
12+
e.printStackTrace();
13+
throw new TestSuiteFailedException();
14+
}
15+
16+
System.out.println("All tests succeeded");
17+
}
18+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package com.github.TannerLow.TestUtils;
2+
3+
public class TestFailedException extends RuntimeException {
4+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.github.TannerLow.TestUtils;
2+
3+
public class TestMath {
4+
public static boolean withinMariginOfError(float a, float b, float marginOfError) {
5+
float error = Math.abs(a - b);
6+
return error <= marginOfError;
7+
}
8+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.github.TannerLow.TestUtils;
2+
3+
public class TestSuiteFailedException extends RuntimeException {
4+
5+
}

0 commit comments

Comments
 (0)