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)
|