0

I'm rewriting algorithm to GPU with Cudafy. I need to call Execute() from a static method. It's necessary to calculate on GPU. How could I do this? What fields or anything should I copy into static?

Object of the class is called from non-static method and it couldn't be changed. It creates an objects, makes Execute (ideally), and gets triangles as result.

The class code is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.Media3D;

using DICOMViewer.Helper;
using DICOMViewer.Volume;
using DICOMViewer.ImageFlow;

using Cudafy;
using Cudafy.Host;
using Cudafy.Translator;

namespace DICOMViewer.GPU
{
    class MarchingCubesOnGPU
    {
        private static List<Triangle> theTriangles;
        // CPU fields
        private Point3D[] points = new Point3D[8];
        private int[] values = new int[8];
        private double theIsoValue;
        private List<Triangle> triangles;

        // GPU fields
        private static PointGPU[] pointsGpu = new PointGPU[8];
        static int[] valsGpu = new int[8];
        private static double[] isolevelGpu = new double[1];
        private static TriangleGPU[] trianglesGpu;

        public static int[] EdgeTableStatic = new int[256]
        {
           // here are the values for edgeTable from the algorithm link
        };

        public static int[,] TriTableStatic = new int[256, 16]
        {
            // here are the values for triTable from the algorithm link
        };

        public MarchingCubesOnGPU(GridCell grid, double isolevel, List<Triangle> theTriangleList)
        {
            points = grid.p;
            values = grid.val;
            this.theIsoValue = isolevel;
            triangles = theTriangleList;
            theTriangles = new List<Triangle>();

            ConvertToStandardTypes();
            Execute(); // ???
        }

        public List<Triangle> getTriangles()
        {
            return theTriangles;
        }

        // Convert fields for GPU
        public void ConvertToStandardTypes()
        {
            for (int i = 0; i < points.Length; i++)
            {
                pointsGpu[i].x = points[i].X;
                pointsGpu[i].y = points[i].Y;
                pointsGpu[i].z = points[i].Z;
            }

            valsGpu = values;
            isolevelGpu[0] = theIsoValue;

            for (int i = 0; i < triangles.Count; i++)
            {
                trianglesGpu[i].p[i].x = triangles[i].p[i].X;
                trianglesGpu[i].p[i].y = triangles[i].p[i].Y;
                trianglesGpu[i].p[i].z = triangles[i].p[i].Z;

            }
        }

        public static void Execute()
        {
            CudafyModule km = CudafyTranslator.Cudafy();
            GPGPU gpu = CudafyHost.GetDevice(CudafyModes.Target, CudafyModes.DeviceId);
            gpu.LoadModule(km);

            TriangleGPU[] tris;

            PointGPU[] dev_points = gpu.Allocate(pointsGpu);
            int[] dev_values = gpu.Allocate(valsGpu);
            double[] dev_iso = gpu.Allocate<double>();
            TriangleGPU[] dev_triangles = gpu.Allocate(trianglesGpu);
            int[] dev_edgeTable = gpu.Allocate<int>();
            int[,] dev_triangleTable = gpu.Allocate(TriTableStatic);

            gpu.CopyToDevice(pointsGpu, dev_points);
            gpu.CopyToDevice(valsGpu, dev_values);
            gpu.CopyToDevice(isolevelGpu, dev_iso);
            gpu.CopyToDevice(trianglesGpu, dev_triangles);
            gpu.CopyToDevice(EdgeTableStatic, dev_edgeTable);
            gpu.CopyToDevice(TriTableStatic, dev_triangleTable);

            gpu.Launch().PolygoniseOnGpu(dev_iso, dev_edgeTable, dev_triangleTable, dev_points, dev_values, dev_triangles);

            for (int k = 0; k < dev_triangles.Length; k++)
            {
                gpu.CopyFromDevice(dev_triangles, out trianglesGpu[k]);
            }

            for (int i = 0; i < trianglesGpu.Length; i++)
            {
                theTriangles[i].p[i].X = trianglesGpu[i].p[i].x;
                theTriangles[i].p[i].Y = trianglesGpu[i].p[i].y;
                theTriangles[i].p[i].Z = trianglesGpu[i].p[i].z;
            }

            gpu.FreeAll();
        }

        [Cudafy]
        public void PolygoniseOnGpu(double[] iso, int[] edgeT, int[,] triT, PointGPU[] p, int[] v, TriangleGPU[] tri)
        {
            int cubeindex = 0;
            for (int i = 0; i < 8; ++i)
            {
                if (valsGpu[i] < iso[0])
                    cubeindex |= 1 << i;
            }

            if (EdgeTableStatic[cubeindex] == 0)
                return;

            PointGPU[] vertList = new PointGPU[12];

            // Find the vertices where the surface intersects the cube 
            for (int id = 1, count = 0; id < 2048; id *= 2, count++)
            {
                if ((edgeT[cubeindex] & id) > 0)
                    vertList[count] = VertexInterpolation(iso[0], p[count], p[count + 1], v[count], v[count + 1]);
            }

            // Create the triangle 
            for (int i = 0; triT[cubeindex, i] != -1; i += 3)
            {
                TriangleGPU triangle = new TriangleGPU(3);

                triangle.p[0] = vertList[triT[cubeindex, i]];
                triangle.p[1] = vertList[triT[cubeindex, i + 1]];
                triangle.p[2] = vertList[triT[cubeindex, i + 2]];

                tri[i] = triangle;
            }
        }
    }

    [Cudafy]
    public struct TriangleGPU
    {
        public PointGPU[] p;

        public TriangleGPU(int t)
        {
            p = new PointGPU[t];
        }
    }

    [Cudafy]
    public struct PointGPU
    {
        public double x;
        public double y;
        public double z;

        public PointGPU(double x, double y, double z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }
    }   
}

ADDED: Execute is a static method as it should be but it could be called only from static. In other case the line:

CudafyModule km = CudafyTranslator.Cudafy();

doesn't work because it is not supported from non-static calles Execute.

In other words, what fields or anything else should I create and fill in new static method to have an independent static entity to call execute?

Community
  • 1
  • 1
  • 1
    Very unclear. Where is the problem? Is Cudafy even relevant to the problem, or is it just a code review? What doesn't work? Is that really the most minimal code example you can provide? – Kilazur Feb 24 '17 at 08:45
  • Looks like `Execute` itself is already static, so you can just call it like `MarchingCubesOnGPU.Execute()`. (Or just `Execute()`, if you're calling it from within the `MarchingCubesOnGPU` class.) – Abion47 Feb 24 '17 at 08:45
  • @Abion47 Execute is static but it could be called only from static (other isn't supported by Cudafy) – Julia Grabovska Feb 24 '17 at 08:50
  • @Kilazur Execute is a static method as it should be but it could be called only from static that I don't know how to perform. – Julia Grabovska Feb 24 '17 at 08:51
  • By that, do you mean that `Execute` can only be called by a static method? That seems rather arbitrary, but I don't see you couldn't just have a static `CallExecute` method that does the `Execute` calling. – Abion47 Feb 24 '17 at 09:03
  • @Abion47 this way (have a static CallExecute method that does the Execute calling) works the same as calling by non-static (without any copied fields I suppose). It's not supported. – Julia Grabovska Feb 24 '17 at 09:07
  • 2
    So it sounds like your problem is not with `Execute` being static, but that you want to access non-static elements of the class from within `Execute`. To access non-static elements, you need an instance of the class. So you need to either **A]** make `Execute` not static, **B]** pass an instance of the `MarchingCubesOnGPU` class to the `Execute` method as a parameter, or **C]** create a static field in `MarchingCubesOnGPU` that holds an instance of the class that `Execute` can then use. (I wouldn't recommend the third option unless you can't use the other two.) – Abion47 Feb 24 '17 at 09:26

1 Answers1

0

Sorry for disinformation. The problem was in just public void PolygoniseOnGpu(...). It wasn't noted as static.