Today, I'm trying to launch my CUDA C/C++ program from a C# application.
So, I did some research on the web, but I didn't found that much information. I only saw the "GitHub" but, no...
So I've got a Kernel defined like follow : (that's an example)
__global__ void kernel(Cartesian a, Cartesian b, Cartesian *c)
With "Cartesian" :
class Cartesian
{
public:
double x;
double y;
double z;
};
With what I understand from managedCUDA. It's like replacing the main function of a CUDA C/C++ program. Using a lib that "do the work for us"
So i followed an example from this page :
And write my C# program like this :
The part that create the context : (dont really get this "notion")
static void InitKernels()
{
CudaContext cntxt = new CudaContext();
CUmodule cumodule = cntxt.LoadModule(@"C:\Users\stage\Documents\Visual Studio 2013\Projects\Cs_link_test\Cs_link_test\x64\Release\kernel.ptx");
addWithCuda = new CudaKernel("kernel", cumodule, cntxt);
}
The part that launch (I guess) the function and get back the modification made by the kernel :
static Func<Cartesian, Cartesian, Cartesian> cudaAdd = (a, b) =>
{
CudaDeviceVariable<Cartesian> result_dev;
Cartesian result_host;
addWithCuda.Run(a, b, result_dev.DevicePointer);
result_dev.CopyToHost(ref result_host);
return result_host;
};
And from this part I don't understand anything from the line :
static Func<Cartesian, Cartesian, Cartesian> cudaAdd = (a, b) =>
I'm not familiar with C# (just saying)
So my problem come from the error caused by result_dev and result_host;
The error says :
Use of unassigned local variable 'result_*'
So, is it because they arren't initialized ?
If so, why result_host cause an error ? It must get the data from result_dev which must be modified by the kernel..
If not, how to fix this ?
And I also wanted to know, is it possible to passe Class parameter through a kernel function ? If so, how to set a CudaDeviceVariable, cause it says that the type must be non-nullable. It's why I change class with struct.
Ok so.. I just figured out how to solve my problem. Read the "discussion" section on https://managedcuda.codeplex.com/discussions/659183 help me to do it. So how to proceed to pass struct parameter to a kernel using managedCUDA ?
First thing I did wrong (I guess) is to use the Func<T, T, T>
part.
You must declare your class in your .cu file like follow :
class Cartesian
{
public:
double x;
double y;
double z;
}
And the same in your .cs file like follow :
[StructLayout(LayoutKind.Sequential)]
struct Cartesian
{
public double x;
public double y;
public double z;
public Cartesian(double x, double y, double z) { this.x = x; this.y = y; this.z = z; }
};
Then you can initialize your kernel as you want, I do it like this :
static void InitKernels()
{
CudaContext ctx = new CudaContext();
CUmodule cumodule = ctx.LoadModule(@"C:\Users\stage\Documents\Visual Studio 2013\Projects\Cs_link_test\Cs_link_test\x64\Release\kernel.ptx");
kernel = new CudaKernel("kernelPosGeo", cumodule, ctx);
kernel.BlockDimensions = 1024;
kernel.GridDimensions = 614;
}
And what you need to do is simply call your kernel with the parameters you want.
Cartesian a = new Cartesian(1, 2, 3);
kernel.Run(a);
I guess I had a problem because I used Func<T, T,T>
but till I don't use it anymore, it seems easier. And the declaration of Func
had at maximum 2 parameter in and 1 out. So I've got a Kernel that have 4 or 5 parameters and I was limited here... But right now, do not have any problem.