Passing pointer between different mex functions

  • Follow


Hello,
I'm trying to pass a pointer between two different mex functions.
To give you a big picture, here is what I'm trying to achieve in general:

handle = mex_func_init()
mex_func_calc1(handle);
.....
mex_func_calcN(handle);
mex_func_destroy(handle);

So far I have  the following code
============ MEX FUNCTION 1 ============
double* h_in = NULL;
int* ptr;
int obj[3]={7,8,9};

void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray*prhs[] )
{
	// check: only one input and one output argument
	if (nrhs !=1) mexErrMsgTxt("Must have one input argument");
	// create a pointer to the real data in the input matrix
	h_in = mxGetPr(prhs[0]);
	// Create numericArray as handle 
	plhs[0]  = mxCreateNumericMatrix(1, 1, mxUINT32_CLASS, mxREAL);
	// Create a pointer to the output data 
	ptr = (int*)mxGetPr(plhs[0]);
	*ptr = (int)obj;
}
============ MEX FUNCTION 2 ============
double* g_var = NULL;
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray*prhs[] )
{
	// check: only one input and one output argument
	if (nrhs !=1) mexErrMsgTxt("Must have one input argument");
	g_var =mxGetPr(prhs[0]);
        //I expected to see '8' as a result of this output, but instead i gives 8-digits number 
	mexPrintf("%d\n", g_var[1]);
}
=====================================

I'm definitely missing something. Could anybody point out what exactly is wrong and a possible solution on how to fix it? Thank you!
0
Reply Max 6/21/2010 10:12:05 AM

"Max " <gm.pantagruel@gmail.com> wrote in message <hvndtl$nvf$1@fred.mathworks.com>...
> Hello,
> I'm trying to pass a pointer between two different mex functions.
> To give you a big picture, here is what I'm trying to achieve in general:
> 
> handle = mex_func_init()
> mex_func_calc1(handle);
> ....
> mex_func_calcN(handle);
> mex_func_destroy(handle);
> 
> So far I have  the following code
> ============ MEX FUNCTION 1 ============
> double* h_in = NULL;
> int* ptr;
> int obj[3]={7,8,9};
> 
> void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray*prhs[] )
> {
> 	// check: only one input and one output argument
> 	if (nrhs !=1) mexErrMsgTxt("Must have one input argument");
> 	// create a pointer to the real data in the input matrix
> 	h_in = mxGetPr(prhs[0]);
> 	// Create numericArray as handle 
> 	plhs[0]  = mxCreateNumericMatrix(1, 1, mxUINT32_CLASS, mxREAL);
> 	// Create a pointer to the output data 
> 	ptr = (int*)mxGetPr(plhs[0]);
> 	*ptr = (int)obj;
> }

That won't work because as soon as this mex function returns to MATLAB the memory pointed to by your "handle" will be invalid ... MATLAB will free it. You need to look into mexMakeMemoryPersistent etc.

> ============ MEX FUNCTION 2 ============
> double* g_var = NULL;
> void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray*prhs[] )
> {
> 	// check: only one input and one output argument
> 	if (nrhs !=1) mexErrMsgTxt("Must have one input argument");
> 	g_var =mxGetPr(prhs[0]);
>         //I expected to see '8' as a result of this output, but instead i gives 8-digits number 
> 	mexPrintf("%d\n", g_var[1]);
> }
> =====================================
> 
> I'm definitely missing something. Could anybody point out what exactly is wrong and a possible solution on how to fix it? Thank you!

Before offering a solution, may I ask why you are trying to do this? There is sometimes a cleaner solution we can offer if we know the reason. Often you can put all of your functions inside one mex routine, for instance.

James Tursa
0
Reply James 6/21/2010 3:09:21 PM


> Before offering a solution, may I ask why you are trying to do this? There is sometimes a >cleaner solution we can offer if we know the reason. Often you can put all of your >functions inside one mex routine, for instance.

Thank you for you reply. I'm trying to build a bridge between Matlab and CUDA. As far as I understand 'the rule number one' when working with CUDA is to avoid frequent memory operations that involve coping data from GPU to the host and back to GPU. So I'd like to reduce the number of those memory transfers by initializing variable in one mex function and pass only the pointer to the allocated memory on GPU to the other mex function.

I could definitely combine everything in one huge mex function - but it makes it difficult to reuse  this code it in the future. I'd rather have a small building blocks as a separate mex functions.
PS. 
Btw, I'm aware of existing solutions like Jacket and GPUmat. But I have to repeat this functionality for my project.
0
Reply Max 6/21/2010 5:01:21 PM

"Max " <gm.pantagruel@gmail.com> wrote in message <hvo5t0$rft$1@fred.mathworks.com>...
> > Before offering a solution, may I ask why you are trying to do this? There is sometimes a >cleaner solution we can offer if we know the reason. Often you can put all of your >functions inside one mex routine, for instance.
> 
> Thank you for you reply. I'm trying to build a bridge between Matlab and CUDA. As far as I understand 'the rule number one' when working with CUDA is to avoid frequent memory operations that involve coping data from GPU to the host and back to GPU. So I'd like to reduce the number of those memory transfers by initializing variable in one mex function and pass only the pointer to the allocated memory on GPU to the other mex function.
> 
> I could definitely combine everything in one huge mex function - but it makes it difficult to reuse  this code it in the future. I'd rather have a small building blocks as a separate mex functions.
> PS. 
> Btw, I'm aware of existing solutions like Jacket and GPUmat. But I have to repeat this functionality for my project.

So you want to allocate memory in one mex routine and use it in other mex routine(s) (i.e., pass it to the GPU). Then at some point later on free the memory. Is that correct?  Do you need the memory to be part of an mxArray for use in MATLAB or can it just be a block of memory that is not part of an mxArray?

James Tursa
0
Reply James 6/21/2010 5:29:22 PM

>So you want to allocate memory in one mex routine and use it in other mex routine(s) >(i.e., pass it to the GPU). Then at some point later on free the memory. Is that correct?

Yes. That is exactly what i'm trying to do. Allocate memory on GPU in the first mex function and then somehow get access to this part of GPU memory from another mex function. Perform calculations on GPU. Copy result from GPU memory to host memory. Convert result from host memory to mxArray for output in matlab.

>Do you need the memory to be part of an mxArray for use in MATLAB or can it just be a >block of memory that is not part of an mxArray?
>

After all the calculations performed on GPU I guess I have to copy it back to host memory and then convert it to mxArray to output result in matlab.

 
0
Reply Max 6/21/2010 6:24:08 PM

"Max " <gm.pantagruel@gmail.com> wrote in message <hvoao8$9b2$1@fred.mathworks.com>...
> >So you want to allocate memory in one mex routine and use it in other mex routine(s) >(i.e., pass it to the GPU). Then at some point later on free the memory. Is that correct?
> 
> Yes. That is exactly what i'm trying to do. Allocate memory on GPU in the first mex function and then somehow get access to this part of GPU memory from another mex function. Perform calculations on GPU. Copy result from GPU memory to host memory. Convert result from host memory to mxArray for output in matlab.
> 
> >Do you need the memory to be part of an mxArray for use in MATLAB or can it just be a >block of memory that is not part of an mxArray?
> >
> 
> After all the calculations performed on GPU I guess I have to copy it back to host memory and then convert it to mxArray to output result in matlab.

I will caution you up front that what you are attempting to do *may* not work. I am not familiar with CUDA programming, but from what others have posted in the past there may be a memory access problem. The GPU may see the different mex routines as different processes, and as such will not allow them to share memory as you are attempting. That being said, here is how you can do it *if* the GPU allows it.  I have used malloc instead of an actual GPU call for illustrative purposes only, and am working with only the first value for simplicity. Also, this is bare bones with very little argument checking.

---------------------------------------------------------------------------------------------------------

// gpu_memory.c
// gpu_memory(n) allocates memory for n doubles
// gpu_memory(0) deallocates memory
// gpu_memory    returns pointer value to memory

#include <stdlib.h>
#include "mex.h"

double *gpu_dp = NULL;

double *gpu_allocate(mwSize n);
void gpu_deallocate(double *dp);

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    double **dpp;
    mwSize n;
    if( nrhs == 0 ) {
        plhs[0] = mxCreateNumericMatrix(1, 1, mxUINT64_CLASS, mxREAL);
        dpp = (double **) mxGetData(plhs[0]);
        *dpp = gpu_dp;
    } else {
        n = mxGetScalar(prhs[0]);
        if( n ) {
            if( gpu_dp ) {
                mexErrMsgTxt("gpu memory already allocated.");
            } else {
                gpu_dp = gpu_allocate(n);
                mexLock();
            }
        } else {
            if( gpu_dp ) {
                gpu_deallocate(gpu_dp);
                gpu_dp = NULL;
                mexUnlock();
            }
        }
    }
}

double *gpu_allocate(mwSize n)
{
    return malloc(n * sizeof(double));
}

void gpu_deallocate(double *dp)
{
    if( dp ) free(dp);
}

---------------------------------------------------------------------------------------------------------

// gpu_set.c
// gpu_set(x) sets first value of gpu_memory block to x
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    double **dpp;
    mxArray *mx;
    mexCallMATLAB(1,&mx,0,NULL,"gpu_memory");
    dpp = mxGetData(mx);
    if( *dpp ) {
        **dpp = mxGetScalar(prhs[0]);
    } else {
        mexErrMsgTxt("gpu_memory not allocated.");
    }
}

---------------------------------------------------------------------------------------------------------

// gpu_get.c
// gpu_get gets first double value of gpu_memory and returns it as MATLAB variable
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    double *dp;
    double **dpp;
    mxArray *mx;
    mexCallMATLAB(1,&mx,0,NULL,"gpu_memory");
    dpp = mxGetData(mx);
    if( *dpp ) {
        plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
        dp = mxGetData(plhs[0]);
        *dp = **dpp;
    } else {
        plhs[0] = mxCreateDoubleMatrix(0, 0, mxREAL);
    }
}

---------------------------------------------------------------------------------------------------------

And here is a sample run:

>> mex gpu_memory.c
>> mex gpu_get.c
>> mex gpu_set.c
>> gpu_memory
ans =
                    0
>> gpu_set(3.4)
??? Error using ==> gpu_set
gpu_memory not allocated.
 
>> gpu_get
ans =
     []
>> gpu_memory(3)
>> gpu_memory
ans =
             15783464
>> gpu_get
ans =
  3.6496e-304
>> gpu_set(1.23)
>> gpu_get
ans =
    1.2300
>> clear all
>> gpu_get
ans =
    1.2300
>> gpu_set(3.45)
>> gpu_get
ans =
    3.4500
>> gpu_memory(0)
>> gpu_get
ans =
     []
>> gpu_set(5.67)
??? Error using ==> gpu_set
gpu_memory not allocated.
 

James Tursa
0
Reply James 6/21/2010 8:04:23 PM

Thanks you so much James! That is exactly I was looking for.
Max
0
Reply Max 6/22/2010 11:39:09 AM

6 Replies
251 Views

(page loaded in 0.047 seconds)

Similiar Articles:











7/25/2012 6:01:52 AM


Reply: