Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

mxCreateNumericArray segmentation violation

60 views
Skip to first unread message

Nathaniel

unread,
Apr 30, 2011, 7:54:05 PM4/30/11
to
Hello,

I am attempting to use mxCreateNumericArray. When I use mxCreateNumericMatrix there are no issues. When I use mxCreateNumericArray for the same purpose a segmentation violation occurs. Any help would be greatly appreciated.

Thanks,
Nate

Here is a simple example that reproduces the error:

************MODULE FILE************

module mexf90
interface

function mxClassIDFromClassName(classname)
character :: classname
integer*8 :: mxClassIDFromClassName
end function mxClassIDFromClassName

function mxGetPr(pm)
integer*8,pointer :: mxGetPr
integer*8 :: pm
end function mxGetPr

function mxCreateNumericArray(ndim,dims,classid,type)
integer*8 , dimension(2) :: dims
integer*8 :: ndim,classid,type, mxCreateNumericArray
end function mxCreateNumericArray

function mxCreateNumericMatrix(m,n,classid,type)
integer*8 :: m, n
integer*8 :: classid,type,mxCreateNumericArray
end function mxCreateNumericMatrix

end interface
end module mexf90

************MEX FUNCTION************

subroutine mexFunction(nlhs, plhs, nrhs, prhs)
use mexf90

implicit none

integer*8, intent(in) :: nlhs, nrhs
integer*8, intent(in), dimension(*) :: prhs
integer*8, intent(out), dimension(*) :: plhs

integer*8 :: classid
integer*8, pointer :: A
integer*8, dimension(2) :: dims

dims(1) = 10
dims(2) = 10
classid = mxClassIDFromClassName('double')

plhs(1) = mxCreateNumericArray(2,dims,classid,0)
!plhs(1) = mxCreateNumericMatrix(10,10,classid,0)
A => mxGetPr(plhs(1))

call myroutine(A)

end subroutine mexFunction

subroutine myroutine(A)

implicit none
integer*8 :: i1, i2
double precision, dimension(10,10) :: A

do i1 = 1, 10
do i2 = 1, 10
A(i1,i2) = 1;
end do
end do

end subroutine myroutine

************MATLAB script************

mex mexf90.f90 -c
mex numeric.f90 mexf90.f90
A = numeric;

James Tursa

unread,
Apr 30, 2011, 9:42:04 PM4/30/11
to
"Nathaniel" wrote in message <ipi7et$mik$1...@fred.mathworks.com>...

> Hello,
>
> I am attempting to use mxCreateNumericArray. When I use mxCreateNumericMatrix there are no issues. When I use mxCreateNumericArray for the same purpose a segmentation violation occurs. Any help would be greatly appreciated.
>
> Thanks,
> Nate
>
> Here is a simple example that reproduces the error:
>
> ************MODULE FILE************
>
> module mexf90
> interface
>
> function mxClassIDFromClassName(classname)
> character :: classname
> integer*8 :: mxClassIDFromClassName
> end function mxClassIDFromClassName

This interface does not look correct. Here is the interface from the doc:

integer*4 mxClassIDFromClassName(classname)
character*(*) classname

So unless your particular installation is different you should change your integer*8 to integer*4.

> function mxGetPr(pm)
> integer*8,pointer :: mxGetPr
> integer*8 :: pm
> end function mxGetPr

I don't see how this can work in general unless you are very lucky. A pointer in Fortran is a descriptor that has more information than just the address. It has the dimensions and strides of each dimension as well. You are telling the compiler that the mxGetPr function is returning *all* of that information in a descriptor that is specific to the Fortran compiler you are using, when in fact the only thing that is actually returned from the mxGetPr function is an address contained in an integer (either *4 or *8 depending on platform). What is really returned is a C_PTR, so you would need to use C interoperability.

> function mxCreateNumericArray(ndim,dims,classid,type)
> integer*8 , dimension(2) :: dims
> integer*8 :: ndim,classid,type, mxCreateNumericArray
> end function mxCreateNumericArray

Again, this does not look correct. Here is the interface from the doc:

mwPointer mxCreateNumericArray(ndim, dims, classid,
ComplexFlag)
mwSize ndim, dims
integer*4 classid, ComplexFlag

The doc is wrong as it should list dims(*).

You have dims hard-coded to 2D which is incorrect. It should be (*) instead of (2). Also, again unless your installation is different, you have the wrong types for classid and type. In addition, type is a very poor choice for a variable name since it is a Fortran key word.

> function mxCreateNumericMatrix(m,n,classid,type)
> integer*8 :: m, n
> integer*8 :: classid,type,mxCreateNumericArray
> end function mxCreateNumericMatrix

Similar comments as above. Here is the interface from the doc:

mwPointer mxCreateNumericMatrix(m, n, classid,
ComplexFlag)
mwSize m, n
integer*4 classid, ComplexFlag

I would add general advice to use the types specified in the MATLAB doc of mwPointer and mwSize etc instead of hard-coding your integer*8. Your code will be more portable that way.

> end interface
> end module mexf90
>
> ************MEX FUNCTION************
>
> subroutine mexFunction(nlhs, plhs, nrhs, prhs)
> use mexf90
>
> implicit none
>
> integer*8, intent(in) :: nlhs, nrhs
> integer*8, intent(in), dimension(*) :: prhs
> integer*8, intent(out), dimension(*) :: plhs

Again a mismatch from the doc:

subroutine mexFunction(nlhs, plhs, nrhs, prhs)

integer*4 nlhs, nrhs
mwPointer plhs(*), prhs(*)

>
> integer*8 :: classid

Be careful with the use of a variable named classid. Some versions of the Intel Fortran compiler will incorrectly interpret it as the keyword class followed by the identifier id. This is a compiler bug but I would advise changing your variable name to something else even if you don't have the Intel compiler, like myclassid or something.

> integer*8, pointer :: A
> integer*8, dimension(2) :: dims
>
> dims(1) = 10
> dims(2) = 10
> classid = mxClassIDFromClassName('double')
>
> plhs(1) = mxCreateNumericArray(2,dims,classid,0)
> !plhs(1) = mxCreateNumericMatrix(10,10,classid,0)

Th above function will work only if you are lucky per my comments above about your function signature mismatches.

> A => mxGetPr(plhs(1))

Per my comments above I would expect you to get a seg fault with the above line using mxGetPr since you are definitely *not* getting a Fortran pointer descriptor returned from the MATLAB API function mxGetPr.

>
> call myroutine(A)
>
> end subroutine mexFunction
>
> subroutine myroutine(A)
>
> implicit none
> integer*8 :: i1, i2
> double precision, dimension(10,10) :: A
>
> do i1 = 1, 10
> do i2 = 1, 10
> A(i1,i2) = 1;
> end do
> end do

The above double nested do loops can be replaced by a single line:

A = 1

> end subroutine myroutine
>
> ************MATLAB script************
>
> mex mexf90.f90 -c
> mex numeric.f90 mexf90.f90

The above is not really the best sequence of commands to use. The first one creates the module object file. The second one first compiles numeric.f90. This will only work if there is a compiled module file available first, which you did in the first line. All good there. But the mexf90.f90 in the second line doesn't really make much sense since you already compiled it. I would have done this:

mex mexf90.f90 -c
mex numeric.f90 mexf90.obj

or this:

mex mexf90.f90 numeric.f90


My final advice is that you may want to look into my MATLAB - Fortran 95 interface code that I have posted on the FEX. You can find it here:

http://www.mathworks.com/matlabcentral/fileexchange/25934-fortran-95-interface-to-matlab-api-with-extras

It has some issues with 64-bit platforms that I am working on and I hope to post an update soon.


James Tursa

Nathaniel

unread,
Apr 30, 2011, 10:20:19 PM4/30/11
to
Thank you for the quick response.

A few months ago I had a problem that you helped me with (http://www.mathworks.com/matlabcentral/newsreader/view_thread/295751). In that thread you concluded that the c-sytle pointers would work. They have never been problematic for me. I made the other changes and I still get a segmentation violation. The strange thing is that I haven't been having problems but now that I'm using arrays I'm getting a segmentation error.

"James Tursa" wrote in message <ipidpc$pk2$1...@fred.mathworks.com>...

James Tursa

unread,
May 1, 2011, 12:48:03 AM5/1/11
to
"Nathaniel" wrote in message <ipig13$sap$1...@fred.mathworks.com>...

> Thank you for the quick response.
>
> A few months ago I had a problem that you helped me with (http://www.mathworks.com/matlabcentral/newsreader/view_thread/295751). In that thread you concluded that the c-sytle pointers would work. They have never been problematic for me. I made the other changes and I still get a segmentation violation. The strange thing is that I haven't been having problems but now that I'm using arrays I'm getting a segmentation error.

In that thread I was specifically referring to a pointer to scalar, not a pointer to an array. Since a scalar doesn't have to have dimensions or strides represented, the compiler could easily represent a Fortran pointer to scalar as just a simple C-style pointer (i.e., address only and nothing else). This is not true for arrays, and thus I would expect any code that depends on this behavior to break down for arrays.

James Tursa

Nathaniel

unread,
May 1, 2011, 12:42:04 PM5/1/11
to
James,
I've tried to make all the corrections you have suggested. Furthermore, I found another example using mxCreateNumericArray, and now I call mxCopyPtrToReal8 and mxCopyReal8ToPtr. I was so hopeful this morning that this would fix things, but I am still getting a segmentation violation. Do you have any more suggestions (other than using your API, which is not thread safe as I do use the PCToolbox)?
Much Thanks,
Nate

***********MODULE FILE***********
#include "fintrf.h"


module mexf90
interface

function mxClassIDFromClassName(classname)

character, dimension(*) :: classname
integer*4 :: mxClassIDFromClassName


end function mxClassIDFromClassName

function mxGetPr(pm)

mwPointer mxGetPr
mwPointer pm
end function mxGetPr

function mxCreateNumericArray(ndim,dims,myclassid,ComplexFlag)
mwPointer mxCreateNumericArray
mwSize ndim
mwSize dims(*)
integer*4 :: myclassid, ComplexFlag
end function mxCreateNumericArray

subroutine mxCopyPtrToReal8(px,y,n)
mwPointer px
mwSize n
real*8, dimension(n) :: y
end subroutine mxCopyPtrToReal8

subroutine mxCopyReal8ToPtr(y,px,n)
mwPointer px
mwSize n
real*8, dimension(n) :: y
end subroutine mxCopyReal8ToPtr



end interface
end module mexf90

***********MEX FUNCTION***********
#include "fintrf.h"


subroutine mexFunction(nlhs, plhs, nrhs, prhs)
use mexf90

! Declarations
implicit none
! mexFunction arguments
mwPointer plhs(*), prhs(*)
integer*4 nlhs, nrhs
! Pointers to input/output mxArrays
mwPointer A_pr, B_pr
! Array information
mwSize dims(2)
mwSize size
integer*4 myclassid
real*8 A, B
dimension A(10,10), B(10,10)

! Arguments for mxCreateNumericArray


dims(1) = 10
dims(2) = 10

size = dims(1)*dims(2)
myclassid = mxClassIDFromClassName('double')

!Create a Fortran array A from the input
A_pr = mxGetPr(prhs(1))
call mxCopyPtrToReal8(A_pr,A,size)

!Create array for return argument
plhs(1) = mxCreateNumericArray(2,dims,myclassid,0)
B_pr = mxGetPr(plhs(1))

call myroutine(A,B,dims)

!Load fortran array B into B_pr, which is the output to MATLAB
call mxCopyReal8ToPtr(B,B_pr,size)

end subroutine mexFunction

subroutine myroutine(A,B,dims)

implicit none
mwSize dims(2)
mwSize i1, i2
real*8 A, B
dimension A(10,10), B(10,10)



do i1 = 1, 10
do i2 = 1, 10

B(i1,i2) = A(i1,i2)**2;


end do
end do

end subroutine myroutine

***********MATLAB SCRIPT***********
mex mexf90.f90 numeric.f90
A = rand(10,10)
numeric(A)

James Tursa

unread,
May 1, 2011, 2:27:04 PM5/1/11
to
"Nathaniel" wrote in message <ipk2gs$4pa$1...@fred.mathworks.com>...

> James,
> I've tried to make all the corrections you have suggested. Furthermore, I found another example using mxCreateNumericArray, and now I call mxCopyPtrToReal8 and mxCopyReal8ToPtr. I was so hopeful this morning that this would fix things, but I am still getting a segmentation violation. Do you have any more suggestions (other than using your API, which is not thread safe as I do use the PCToolbox)?
> Much Thanks,
> Nate

I have read on the newsgroup from others that using any of the MATLAB API memory allocation functions such as mxCreate___, mxMalloc, etc is not thread-safe. If that is true then you will never be able to do what you are attempting in a thread-safe manner. But that is just what I have read ... I don't have the PC Toolbox and have no personal experience trying to multi-thread mex routines that allocate with MATLAB API functions. Do you need to allocate inside your threads, or just access MATLAB pre-existing variables?

James Tursa

Nathaniel

unread,
May 1, 2011, 4:22:04 PM5/1/11
to
I only need to access MATLAB pre-existing variables. The trouble I'm having is not accessing pre-existing MATLAB variables, but creating an array as output. Note that mxCreateDoubleMatrix and mxCreateNumericMatrix have both worked for me even within the PCT and when using the c-style pointers (must be that I'm lucky). It's only moving to use mxCreateNumericArray that has been a problem.

I think the speed-up from using FORTRAN is still greater than parallelization across 8 workers as I am integrating over 3 dimensions, which I would need to use a few loops in MATLAB that are incredibly slow (e.g. 1000 or more points to interpolate/extrapolate per each of the 3000 or more nodes in the state space is very expensive). I could just code it all in FORTRAN, but another factor of 8 is a gain I'd rather not give up (not to mention the debugging headache and the loss of convenience of matrix/array operations for computation of the integrals in MATLAB).

Thank you again for the helpful feedback. Your posts in this community are a tremendous value to me.

"James Tursa" wrote in message <ipk8lo$3o7$1...@fred.mathworks.com>...

James Tursa

unread,
May 2, 2011, 12:41:05 PM5/2/11
to
"Nathaniel" wrote in message <ipkfdc$cr3$1...@fred.mathworks.com>...

> I only need to access MATLAB pre-existing variables. The trouble I'm having is not accessing pre-existing MATLAB variables, but creating an array as output. Note that mxCreateDoubleMatrix and mxCreateNumericMatrix have both worked for me even within the PCT and when using the c-style pointers (must be that I'm lucky). It's only moving to use mxCreateNumericArray that has been a problem.
>
> I think the speed-up from using FORTRAN is still greater than parallelization across 8 workers as I am integrating over 3 dimensions, which I would need to use a few loops in MATLAB that are incredibly slow (e.g. 1000 or more points to interpolate/extrapolate per each of the 3000 or more nodes in the state space is very expensive). I could just code it all in FORTRAN, but another factor of 8 is a gain I'd rather not give up (not to mention the debugging headache and the loss of convenience of matrix/array operations for computation of the integrals in MATLAB).
>
> Thank you again for the helpful feedback. Your posts in this community are a tremendous value to me.

OK, try this out (CAUTION: Posted code is UNTESTED). I have taken your idea of telling the compiler that mxGetPr returns a real*8 Fortran pointer to scalar. This will only work if the compiler actually represents such a pointer internally as a simple C-style pointer (address only with no other descriptor info), since that is actually what mxGetPr returns as a result. Then I insert an interface for a routine fp0tofp2 where I tell the compiler that the first argument is a real*8 scalar, but in actual fact the fp0tofp2 routine has the first argument as a 2D array. The interface is necessary to get the function to return a Fortran pointer. Inside the fp0tofp2 routine is a simple statement to create the 2D pointer return value. Let me know how this works. I like this approach because it avoids the use of %VAL(), LOC, and COMMON blocks to form the Fortran pointer from the MATLAB function
mxGetPr, so maybe it will be thread-safe. The drawback is that it relies on the compiler storing a Fortran pointer to scalar as a simple C-style pointer which may be non-portable. But as stated in the other thread you mentioned it *does* work for Compaq and Intel compilers on a PC. I may post a query out on the Fortran newsgroup to see if others can verify the behavior of other compilers.


James Tursa

!---------------------------------------------------------------------------------------------

#include "fintrf.h"
module mexf90
interface

function mxClassIDFromClassName(classname)
character, dimension(*) :: classname
integer*4 :: mxClassIDFromClassName
end function mxClassIDFromClassName

! CAUTION: mxGetPr only works if Fortran pointer to scalar is just an address (C-style pointer)
function mxGetPr(pm)
real*8, pointer :: mxGetPr


mwPointer pm
end function mxGetPr

function mxCreateNumericArray(ndim,dims,myclassid,ComplexFlag)
mwPointer mxCreateNumericArray
mwSize ndim
mwSize dims(*)
integer*4 :: myclassid, ComplexFlag
end function mxCreateNumericArray

mwSize function mxGetM(pm)
mwPointer pm
end function mxGetM

mwSize function mxGetN(pm)
mwPointer pm
end function mxGetN

! Lie to compiler. Tell it that first argument is a scalar.
function fp0tofp2( fp0, N, N ) result(fp2)
real*8, pointer :: fp2(:,:)
mwSize, intent(in) :: M, N
real*8, target, intent(in) :: fp0
end function fp0tofp2

end interface

contains

! Extracts a real*8 2D pointer to data area of mxArray
function fpGetPr(pm)
implicit none
!-ARG
real*8, pointer :: fpGetPr(:,:)
mwPointer, intent(in) :: pm
!-LOC
real*8, pointer :: fp
mwSize M, N
!----
M = mxGetM(pm)
N = mxGetN(pm)
fp => mxGetPr(pm)
fpGetPr => gp0togp2(fp,M,N)
end function fpGetPr

end module mexf90

!-- IMPLICIT INTERFACE

! Lie to compiler. Now tell it that first argument is a 2D array.
! This must be an implicit interface for the lie to work.
function fp0tofp2( fp0, M, N ) result(fp2)
real*8, pointer :: fp2(:,:)
mwSize, intent(in) :: M, N
real*8, target, intent(in) :: fp0(M,N)
if( M > 0 .and. N > 0 ) then
fp2 => fp0
else
nullify(fp2)
endif
end function fp0tofp2

!***********MEX FUNCTION***********

subroutine mexFunction(nlhs, plhs, nrhs, prhs)
use mexf90
! Declarations
implicit none
! mexFunction arguments
mwPointer plhs(*), prhs(*)
integer*4 nlhs, nrhs
! Pointers to input/output mxArrays

real*8, pointer :: A_pr(:,:), B_pr(:,:)
! Array information
mwSize ndim
mwSize dims(2)
integer*4 :: myclassid, ComplexFlag

!Create a Fortran pointer to the input (assumed to be 2D)
A_pr => fpGetPr(prhs(1))
dims(1) = size(A_pr,1)
dims(2) = size(A_pr,2)
ndim = 2



!Create array for return argument

! Arguments for mxCreateNumericArray


myclassid = mxClassIDFromClassName('double')

ComplexFlag = 0
plhs(1) = mxCreateNumericArray(ndim,dims,myclassid,ComplexFlag)
B_pr => fpGetPr(plhs(1))

call myroutine(A_pr,B_pr)

contains

subroutine myroutine(A, B)

implicit none
real*8 :: A(:,:), B(:,:)

B = A**2;

end subroutine myroutine

end subroutine mexFunction

James Tursa

unread,
May 2, 2011, 2:46:08 PM5/2/11
to
"James Tursa" wrote in message <ipmmr1$6fc$1...@fred.mathworks.com>...
>
> fpGetPr => gp0togp2(fp,M,N)

Typo. Should be:

fpGetPr => fp0tofp2(fp,M,N)


James Tursa

0 new messages