Loading FaceData/src/main/java/cz/fidentis/analyst/data/face/HumanFace.java +5 −0 Original line number Diff line number Diff line Loading @@ -128,6 +128,11 @@ public interface HumanFace extends Serializable { */ void setLeftBalancedKdTree(LeftBalancedKdTree kdTree); /** * Checks if HumanFace has LeftBalancedKdTree calculated * * @return true if yes and false if not */ boolean hasLeftBalancedKdTree(); /** Loading FaceEngines/src/main/java/cz/fidentis/analyst/engines/face/impl/FaceDistanceServicesImpl.java +11 −11 Original line number Diff line number Diff line package cz.fidentis.analyst.engines.face.impl; import cz.fidentis.analyst.data.face.HumanFace; import cz.fidentis.analyst.data.kdtree.KdTree; import cz.fidentis.analyst.data.landmarks.Landmark; import cz.fidentis.analyst.data.mesh.measurement.*; import cz.fidentis.analyst.engines.distance.MeshDistanceConfig; Loading Loading @@ -47,31 +48,30 @@ public class FaceDistanceServicesImpl { FaceStateServices.updateKdTree(primaryFace, FaceStateServices.Mode.COMPUTE_IF_ABSENT); case RAY_CASTING -> FaceStateServices.updateOctree(primaryFace, FaceStateServices.Mode.COMPUTE_IF_ABSENT); case RAY_CASTING_GPU, POINT_TO_TRIANGLE_BRUTEFORCE_GPU -> {} case RAY_CASTING_GPU, POINT_TO_TRIANGLE_BRUTEFORCE_GPU, POINT_TO_POINT_BRUTEFORCE_GPU -> {} case POINT_TO_POINT_NEAREST_NEIGHBORS_GPU, POINT_TO_TRIANGLE_NEAREST_NEIGHBORS_GPU -> FaceStateServices.updateLeftBalancedKdTree(primaryFace, FaceStateServices.Mode.COMPUTE_IF_ABSENT); default -> throw new IllegalStateException("Unexpected value: " + Objects.requireNonNull(strategy)); } MeshDistanceVisitor distVisitor; KdTree kdTree; if (strategy == MeshDistanceConfig.Method.POINT_TO_POINT_NEAREST_NEIGHBORS_GPU || strategy == MeshDistanceConfig.Method.POINT_TO_TRIANGLE_NEAREST_NEIGHBORS_GPU) { distVisitor = new MeshDistanceConfig( strategy, primaryFace.getLeftBalancedKdTree(), primaryFace.getOctree(), gpuData, relativeDist, crop).getVisitor(); kdTree = primaryFace.getLeftBalancedKdTree(); } else { kdTree = primaryFace.getKdTree(); } distVisitor = new MeshDistanceConfig( strategy, primaryFace.getKdTree(), kdTree, primaryFace.getOctree(), gpuData, relativeDist, crop).getVisitor(); } secondaryFace.getMeshModel().compute(distVisitor); distVisitor.dispose(); Loading GPU/src/main/resources/opencl/MeshDistanceCalculations.c +22 −8 Original line number Diff line number Diff line Loading @@ -91,9 +91,9 @@ kernel void closestOnTriangles(global const MeshTriangle* triangles, global cons } kernel void bruteforceTriangles(global const MeshTriangle* triangles, global const Point3D* fromPoints, kernel void bruteforceTriangles(global const MeshTriangle* triangles, global const Point3D* fromPoints, global const Point3D* fromNormals, global double* resultDist, global Point3D* resultPoints, const int numTriangles, const int numPoints) { const int numTriangles, const int numPoints, const int calcRelativeDist) { const int Gid = get_global_id(0); if (Gid >= numPoints) { return; Loading @@ -113,18 +113,25 @@ kernel void bruteforceTriangles(global const MeshTriangle* triangles, global con } resultPoints[Gid] = closestPoint; if (calcRelativeDist) { resultDist[Gid] = relativeDistance(fromPoint, closestPoint, fromNormals[Gid]); } else { resultDist[Gid] = sqrt(closestDist); } } kernel void bruteforceVertexes(global const Point3D* toPoints, global const Point3D* fromPoints, global double* resultDist, global Point3D* resultPoints, const int numToPoints, const int numFromPoints) { kernel void bruteforceVertices(global const Point3D* toPoints, global const Point3D* fromPoints, global const Point3D* fromNormals, global double* resultDist, global int* resultPointIndices, const int numToPoints, const int numFromPoints, const int calcRelativeDist) { const int Gid = get_global_id(0); if (Gid >= numFromPoints) { return; } int closestPointIndex; Point3D closestPoint; double closestDist = INFINITY; Point3D fromPoint = fromPoints[Gid]; Loading @@ -135,9 +142,16 @@ kernel void bruteforceVertexes(global const Point3D* toPoints, global const Poin if (currDist < closestDist) { closestDist = currDist; closestPoint = currPoint; closestPointIndex = i; } } resultPoints[Gid] = closestPoint; resultPointIndices[Gid] = closestPointIndex; if (calcRelativeDist) { resultDist[Gid] = relativeDistance(fromPoint, closestPoint, fromNormals[Gid]); } else { resultDist[Gid] = sqrt(closestDist); } } GPU/src/main/resources/opencl/NNKdTree.c +3 −0 Original line number Diff line number Diff line /* Kernel uses stack-free traversal of a left-balanced kd-tree to find closest vertex. Adapted from I. Wald - A Stack-Free Traversal Algorithm for Left-Balanced k-d Trees [https://www.sci.utah.edu/~wald/Publications/2022/kdtree/stack-free-v2.pdf] @author Lubomir Jurcisin */ kernel void NNKdTree(global const Point3D* from, global const Point3D* fromNormals, global const Point3D* kdTree, Loading GUI/src/main/java/cz/fidentis/analyst/gui/app/tools/opencl/VertexDistanceBenchmark.java→GUI/src/main/java/cz/fidentis/analyst/gui/app/tools/opencl/MeshDistanceBenchmark.java +61 −14 Original line number Diff line number Diff line Loading @@ -5,7 +5,6 @@ import cz.fidentis.analyst.data.mesh.MeshFactory; import cz.fidentis.analyst.data.mesh.MeshModel; import cz.fidentis.analyst.engines.distance.MeshDistanceConfig; import cz.fidentis.analyst.engines.distance.MeshDistanceVisitor; //import cz.fidentis.analyst.engines.distance.impl.MeshDistanceBruteforceGPU; import cz.fidentis.analyst.gui.task.batch.Stopwatch; import java.io.IOException; Loading @@ -18,11 +17,12 @@ import static cz.fidentis.analyst.gui.app.tools.opencl.BenchmarkUtils.saveAsCsv; * * @author Ľubomír Jurčišin */ public class VertexDistanceBenchmark { public class MeshDistanceBenchmark { private static final String MODEL_FROM_PATH = "/home/lubomir/Documents/MUNI/5_semester/BP/analyst-data/multi-scan/02/00002_01_ECA.obj"; private static final String MODEL_TO_PATH = "/home/lubomir/Documents/MUNI/5_semester/BP/analyst-data/multi-scan/04/00004_01_ECA.obj"; private static final String RESULT_CSV_PATH = "/home/lubomir/Desktop/result.csv"; private static final boolean BENCHMARK_KD_TREE_CONSTRUCTION = false; private static final int ITERATIONS = 10; private static final boolean REBUILD_TREE = false; private static final boolean SYNTHETIC = false; Loading @@ -37,6 +37,10 @@ public class VertexDistanceBenchmark { private static final Stopwatch CPU_TRIANGLE_STOPWATCH = new Stopwatch("TRIANGLE_CPU"); private static final Stopwatch GPU_TRIANGLE_PRECISE_STOPWATCH = new Stopwatch("TRIANGLE_PRECISE_GPU"); private static final Stopwatch LEFTBALANCED_KDTREE_STOPWATCH = new Stopwatch("LEFTBALANCED_KDTREE"); private static final Stopwatch TRIANGLE_KDTREE_STOPWATCH = new Stopwatch("TRIANGLE_KDTREE"); private static final Stopwatch NORMAL_KDTREE_STOPWATCH = new Stopwatch("NORMAL_KDTREE"); /** * Start benchmark. Loading @@ -57,13 +61,24 @@ public class VertexDistanceBenchmark { modelTo = BenchmarkUtils.getModel(MODEL_TO_PATH); } ArrayList<ArrayList<Long>> csvData = new ArrayList<>(); String[] headers; if (BENCHMARK_KD_TREE_CONSTRUCTION) { headers = new String[]{"LEFT_BALANCED_KD_TREE", "TRIANGLE_KD_TREE", "NORMAL_KD_TREE"}; csvData.add(leftBalancedKdTreeBuild(modelTo)); csvData.add(triangleKdTreeBuild(modelTo)); csvData.add(normalKdTreeBuild(modelTo)); } else { BenchmarkUtils.printGPU(); String[] headers = {"NN_GPU", "NN_BRUTEFORCE_GPU", "NN_CPU", headers = new String[]{"NN_GPU", "NN_BRUTEFORCE_GPU", "NN_CPU", "TRIANGLE_APPROXIMATE_GPU", "TRIANGLE_PRECISE_BRUTEFORCE_GPU", "TRIANGLE_CPU"}; //String[] headers = {"TRIANGLE_BRUTEFORCE_GPU", "TRIANGLE_PRECISE_GPU"}; ArrayList<ArrayList<Long>> csvData = new ArrayList<>(); //headers = new String[]{"TRIANGLE_BRUTEFORCE_GPU", "TRIANGLE_PRECISE_GPU"}; csvData.add(distanceNNGPU(modelFrom, modelTo)); csvData.add(distanceNNBruteforceGPU(modelFrom, modelTo)); csvData.add(distanceNNCPU(modelFrom, modelTo)); Loading @@ -72,8 +87,10 @@ public class VertexDistanceBenchmark { csvData.add(distanceTriangleBruteforceGPU(modelFrom, modelTo)); //csvData.add(distanceTrianglePreciseGPU(modelFrom, modelTo)); csvData.add(distanceTriangleCPU(modelFrom, modelTo)); } saveAsCsv(csvData, headers, RESULT_CSV_PATH); } private static ArrayList<Long> distanceNNGPU(MeshModel from, MeshModel to) { Loading Loading @@ -221,4 +238,34 @@ public class VertexDistanceBenchmark { return cpuTimes; } private static ArrayList<Long> leftBalancedKdTreeBuild(MeshModel model) { ArrayList<Long> times = new ArrayList<>(); for (int i = 0; i < ITERATIONS; i++) { LEFTBALANCED_KDTREE_STOPWATCH.start(); MeshDistanceVisitor visitorGPU = new MeshDistanceConfig(MeshDistanceConfig.Method.POINT_TO_POINT_NEAREST_NEIGHBORS_GPU, model, null, false, false).getVisitor(); times.add(LEFTBALANCED_KDTREE_STOPWATCH.stop()); } return times; } private static ArrayList<Long> triangleKdTreeBuild(MeshModel model) { ArrayList<Long> times = new ArrayList<>(); for (int i = 0; i < ITERATIONS; i++) { TRIANGLE_KDTREE_STOPWATCH.start(); MeshDistanceVisitor visitorGPU = new MeshDistanceConfig(MeshDistanceConfig.Method.POINT_TO_TRIANGLE_PRECISE_GPU, model, null, false, false).getVisitor(); times.add(TRIANGLE_KDTREE_STOPWATCH.stop()); } return times; } private static ArrayList<Long> normalKdTreeBuild(MeshModel model) { ArrayList<Long> times = new ArrayList<>(); for (int i = 0; i < ITERATIONS; i++) { NORMAL_KDTREE_STOPWATCH.start(); MeshDistanceVisitor visitorGPU = new MeshDistanceConfig(MeshDistanceConfig.Method.POINT_TO_POINT_NEAREST_NEIGHBORS, model, null, false, false).getVisitor(); times.add(NORMAL_KDTREE_STOPWATCH.stop()); } return times; } } Loading
FaceData/src/main/java/cz/fidentis/analyst/data/face/HumanFace.java +5 −0 Original line number Diff line number Diff line Loading @@ -128,6 +128,11 @@ public interface HumanFace extends Serializable { */ void setLeftBalancedKdTree(LeftBalancedKdTree kdTree); /** * Checks if HumanFace has LeftBalancedKdTree calculated * * @return true if yes and false if not */ boolean hasLeftBalancedKdTree(); /** Loading
FaceEngines/src/main/java/cz/fidentis/analyst/engines/face/impl/FaceDistanceServicesImpl.java +11 −11 Original line number Diff line number Diff line package cz.fidentis.analyst.engines.face.impl; import cz.fidentis.analyst.data.face.HumanFace; import cz.fidentis.analyst.data.kdtree.KdTree; import cz.fidentis.analyst.data.landmarks.Landmark; import cz.fidentis.analyst.data.mesh.measurement.*; import cz.fidentis.analyst.engines.distance.MeshDistanceConfig; Loading Loading @@ -47,31 +48,30 @@ public class FaceDistanceServicesImpl { FaceStateServices.updateKdTree(primaryFace, FaceStateServices.Mode.COMPUTE_IF_ABSENT); case RAY_CASTING -> FaceStateServices.updateOctree(primaryFace, FaceStateServices.Mode.COMPUTE_IF_ABSENT); case RAY_CASTING_GPU, POINT_TO_TRIANGLE_BRUTEFORCE_GPU -> {} case RAY_CASTING_GPU, POINT_TO_TRIANGLE_BRUTEFORCE_GPU, POINT_TO_POINT_BRUTEFORCE_GPU -> {} case POINT_TO_POINT_NEAREST_NEIGHBORS_GPU, POINT_TO_TRIANGLE_NEAREST_NEIGHBORS_GPU -> FaceStateServices.updateLeftBalancedKdTree(primaryFace, FaceStateServices.Mode.COMPUTE_IF_ABSENT); default -> throw new IllegalStateException("Unexpected value: " + Objects.requireNonNull(strategy)); } MeshDistanceVisitor distVisitor; KdTree kdTree; if (strategy == MeshDistanceConfig.Method.POINT_TO_POINT_NEAREST_NEIGHBORS_GPU || strategy == MeshDistanceConfig.Method.POINT_TO_TRIANGLE_NEAREST_NEIGHBORS_GPU) { distVisitor = new MeshDistanceConfig( strategy, primaryFace.getLeftBalancedKdTree(), primaryFace.getOctree(), gpuData, relativeDist, crop).getVisitor(); kdTree = primaryFace.getLeftBalancedKdTree(); } else { kdTree = primaryFace.getKdTree(); } distVisitor = new MeshDistanceConfig( strategy, primaryFace.getKdTree(), kdTree, primaryFace.getOctree(), gpuData, relativeDist, crop).getVisitor(); } secondaryFace.getMeshModel().compute(distVisitor); distVisitor.dispose(); Loading
GPU/src/main/resources/opencl/MeshDistanceCalculations.c +22 −8 Original line number Diff line number Diff line Loading @@ -91,9 +91,9 @@ kernel void closestOnTriangles(global const MeshTriangle* triangles, global cons } kernel void bruteforceTriangles(global const MeshTriangle* triangles, global const Point3D* fromPoints, kernel void bruteforceTriangles(global const MeshTriangle* triangles, global const Point3D* fromPoints, global const Point3D* fromNormals, global double* resultDist, global Point3D* resultPoints, const int numTriangles, const int numPoints) { const int numTriangles, const int numPoints, const int calcRelativeDist) { const int Gid = get_global_id(0); if (Gid >= numPoints) { return; Loading @@ -113,18 +113,25 @@ kernel void bruteforceTriangles(global const MeshTriangle* triangles, global con } resultPoints[Gid] = closestPoint; if (calcRelativeDist) { resultDist[Gid] = relativeDistance(fromPoint, closestPoint, fromNormals[Gid]); } else { resultDist[Gid] = sqrt(closestDist); } } kernel void bruteforceVertexes(global const Point3D* toPoints, global const Point3D* fromPoints, global double* resultDist, global Point3D* resultPoints, const int numToPoints, const int numFromPoints) { kernel void bruteforceVertices(global const Point3D* toPoints, global const Point3D* fromPoints, global const Point3D* fromNormals, global double* resultDist, global int* resultPointIndices, const int numToPoints, const int numFromPoints, const int calcRelativeDist) { const int Gid = get_global_id(0); if (Gid >= numFromPoints) { return; } int closestPointIndex; Point3D closestPoint; double closestDist = INFINITY; Point3D fromPoint = fromPoints[Gid]; Loading @@ -135,9 +142,16 @@ kernel void bruteforceVertexes(global const Point3D* toPoints, global const Poin if (currDist < closestDist) { closestDist = currDist; closestPoint = currPoint; closestPointIndex = i; } } resultPoints[Gid] = closestPoint; resultPointIndices[Gid] = closestPointIndex; if (calcRelativeDist) { resultDist[Gid] = relativeDistance(fromPoint, closestPoint, fromNormals[Gid]); } else { resultDist[Gid] = sqrt(closestDist); } }
GPU/src/main/resources/opencl/NNKdTree.c +3 −0 Original line number Diff line number Diff line /* Kernel uses stack-free traversal of a left-balanced kd-tree to find closest vertex. Adapted from I. Wald - A Stack-Free Traversal Algorithm for Left-Balanced k-d Trees [https://www.sci.utah.edu/~wald/Publications/2022/kdtree/stack-free-v2.pdf] @author Lubomir Jurcisin */ kernel void NNKdTree(global const Point3D* from, global const Point3D* fromNormals, global const Point3D* kdTree, Loading
GUI/src/main/java/cz/fidentis/analyst/gui/app/tools/opencl/VertexDistanceBenchmark.java→GUI/src/main/java/cz/fidentis/analyst/gui/app/tools/opencl/MeshDistanceBenchmark.java +61 −14 Original line number Diff line number Diff line Loading @@ -5,7 +5,6 @@ import cz.fidentis.analyst.data.mesh.MeshFactory; import cz.fidentis.analyst.data.mesh.MeshModel; import cz.fidentis.analyst.engines.distance.MeshDistanceConfig; import cz.fidentis.analyst.engines.distance.MeshDistanceVisitor; //import cz.fidentis.analyst.engines.distance.impl.MeshDistanceBruteforceGPU; import cz.fidentis.analyst.gui.task.batch.Stopwatch; import java.io.IOException; Loading @@ -18,11 +17,12 @@ import static cz.fidentis.analyst.gui.app.tools.opencl.BenchmarkUtils.saveAsCsv; * * @author Ľubomír Jurčišin */ public class VertexDistanceBenchmark { public class MeshDistanceBenchmark { private static final String MODEL_FROM_PATH = "/home/lubomir/Documents/MUNI/5_semester/BP/analyst-data/multi-scan/02/00002_01_ECA.obj"; private static final String MODEL_TO_PATH = "/home/lubomir/Documents/MUNI/5_semester/BP/analyst-data/multi-scan/04/00004_01_ECA.obj"; private static final String RESULT_CSV_PATH = "/home/lubomir/Desktop/result.csv"; private static final boolean BENCHMARK_KD_TREE_CONSTRUCTION = false; private static final int ITERATIONS = 10; private static final boolean REBUILD_TREE = false; private static final boolean SYNTHETIC = false; Loading @@ -37,6 +37,10 @@ public class VertexDistanceBenchmark { private static final Stopwatch CPU_TRIANGLE_STOPWATCH = new Stopwatch("TRIANGLE_CPU"); private static final Stopwatch GPU_TRIANGLE_PRECISE_STOPWATCH = new Stopwatch("TRIANGLE_PRECISE_GPU"); private static final Stopwatch LEFTBALANCED_KDTREE_STOPWATCH = new Stopwatch("LEFTBALANCED_KDTREE"); private static final Stopwatch TRIANGLE_KDTREE_STOPWATCH = new Stopwatch("TRIANGLE_KDTREE"); private static final Stopwatch NORMAL_KDTREE_STOPWATCH = new Stopwatch("NORMAL_KDTREE"); /** * Start benchmark. Loading @@ -57,13 +61,24 @@ public class VertexDistanceBenchmark { modelTo = BenchmarkUtils.getModel(MODEL_TO_PATH); } ArrayList<ArrayList<Long>> csvData = new ArrayList<>(); String[] headers; if (BENCHMARK_KD_TREE_CONSTRUCTION) { headers = new String[]{"LEFT_BALANCED_KD_TREE", "TRIANGLE_KD_TREE", "NORMAL_KD_TREE"}; csvData.add(leftBalancedKdTreeBuild(modelTo)); csvData.add(triangleKdTreeBuild(modelTo)); csvData.add(normalKdTreeBuild(modelTo)); } else { BenchmarkUtils.printGPU(); String[] headers = {"NN_GPU", "NN_BRUTEFORCE_GPU", "NN_CPU", headers = new String[]{"NN_GPU", "NN_BRUTEFORCE_GPU", "NN_CPU", "TRIANGLE_APPROXIMATE_GPU", "TRIANGLE_PRECISE_BRUTEFORCE_GPU", "TRIANGLE_CPU"}; //String[] headers = {"TRIANGLE_BRUTEFORCE_GPU", "TRIANGLE_PRECISE_GPU"}; ArrayList<ArrayList<Long>> csvData = new ArrayList<>(); //headers = new String[]{"TRIANGLE_BRUTEFORCE_GPU", "TRIANGLE_PRECISE_GPU"}; csvData.add(distanceNNGPU(modelFrom, modelTo)); csvData.add(distanceNNBruteforceGPU(modelFrom, modelTo)); csvData.add(distanceNNCPU(modelFrom, modelTo)); Loading @@ -72,8 +87,10 @@ public class VertexDistanceBenchmark { csvData.add(distanceTriangleBruteforceGPU(modelFrom, modelTo)); //csvData.add(distanceTrianglePreciseGPU(modelFrom, modelTo)); csvData.add(distanceTriangleCPU(modelFrom, modelTo)); } saveAsCsv(csvData, headers, RESULT_CSV_PATH); } private static ArrayList<Long> distanceNNGPU(MeshModel from, MeshModel to) { Loading Loading @@ -221,4 +238,34 @@ public class VertexDistanceBenchmark { return cpuTimes; } private static ArrayList<Long> leftBalancedKdTreeBuild(MeshModel model) { ArrayList<Long> times = new ArrayList<>(); for (int i = 0; i < ITERATIONS; i++) { LEFTBALANCED_KDTREE_STOPWATCH.start(); MeshDistanceVisitor visitorGPU = new MeshDistanceConfig(MeshDistanceConfig.Method.POINT_TO_POINT_NEAREST_NEIGHBORS_GPU, model, null, false, false).getVisitor(); times.add(LEFTBALANCED_KDTREE_STOPWATCH.stop()); } return times; } private static ArrayList<Long> triangleKdTreeBuild(MeshModel model) { ArrayList<Long> times = new ArrayList<>(); for (int i = 0; i < ITERATIONS; i++) { TRIANGLE_KDTREE_STOPWATCH.start(); MeshDistanceVisitor visitorGPU = new MeshDistanceConfig(MeshDistanceConfig.Method.POINT_TO_TRIANGLE_PRECISE_GPU, model, null, false, false).getVisitor(); times.add(TRIANGLE_KDTREE_STOPWATCH.stop()); } return times; } private static ArrayList<Long> normalKdTreeBuild(MeshModel model) { ArrayList<Long> times = new ArrayList<>(); for (int i = 0; i < ITERATIONS; i++) { NORMAL_KDTREE_STOPWATCH.start(); MeshDistanceVisitor visitorGPU = new MeshDistanceConfig(MeshDistanceConfig.Method.POINT_TO_POINT_NEAREST_NEIGHBORS, model, null, false, false).getVisitor(); times.add(NORMAL_KDTREE_STOPWATCH.stop()); } return times; } }