Commit 29d9f4db authored by Radek Ošlejšek's avatar Radek Ošlejšek
Browse files

Merge branch '369-kd-tree-construction-benchmark' into 'master'

Bruteforce distance relative, crop and GUI

Closes #369

See merge request grp-fidentis/analyst2!416
parents 025f07a7 5482a288
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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();

    /**
+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;
@@ -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();
+22 −8
Original line number Diff line number Diff line
@@ -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;
@@ -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];
@@ -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);
    }

}
+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,
+61 −14
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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.
@@ -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));
@@ -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) {
@@ -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