For the MEX experts out there: I would like to factor a huge
matrix (passed in as a one-dimensional array) in-place in a
mex file. Unfortunately, the documentation says there may
be side effects (and there are: the Matlab executive is
apparently getting all mixed up).
Is there no way I could modify an argument in-place? If that
is not possible, the penalty would be huge. We are talking
about a matrix of several gigabytes size...
Thanks for your help.
Petr
|
|
0
|
|
|
|
Reply
|
pkryslNOSP (71)
|
2/14/2008 4:25:03 AM |
|
In article <fp0fqv$3gd$1@fred.mathworks.com>,
Petr Krysl <pkryslNOSP@Mucsd.edu> wrote:
>For the MEX experts out there: I would like to factor a huge
>matrix (passed in as a one-dimensional array) in-place in a
>mex file. Unfortunately, the documentation says there may
>be side effects (and there are: the Matlab executive is
>apparently getting all mixed up).
>Is there no way I could modify an argument in-place?
I know little about MEX, but generally speaking, the memory
that you are handed for any Matlab variable might be shared
with other Matlab variables due to the "lazy copy" behaviour.
The columns you see might be linked to columns of other variables.
When you change the memory in-place, you would have changed those
other variables too.
--
"Let me live in my house by the side of the road --
It's here the race of men go by.
They are good, they are bad, they are weak, they are strong
Wise, foolish -- so am I;" -- Sam Walter Foss
|
|
0
|
|
|
|
Reply
|
roberson2 (8067)
|
2/14/2008 4:38:38 AM
|
|
roberson@ibd.nrc-cnrc.gc.ca (Walter Roberson) wrote in
message <fp0gke$gqq$1@canopus.cc.umanitoba.ca>...
> I know little about MEX, but generally speaking, the memory
> that you are handed for any Matlab variable might be shared
> with other Matlab variables due to the "lazy copy" behaviour.
> The columns you see might be linked to columns of other
variables.
> When you change the memory in-place, you would have
changed those
> other variables too.
I am not sure I follow: I can certainly access the
individual elements of the array that I want to modify by
read-access (and I see the right data). Why can't I write
into the same memory locations? I understand that I might be
modifying a copy of the input argument, but that does not
seem to be the case. Actually, when I look at the matrix
after I've modified the input argument and returned from the
mex file, the matrix contains correctly modified data.
Unfortunately something else seems to have been affected,
and the Matlab interpreter stops working correctly.
|
|
0
|
|
|
|
Reply
|
pkryslNOSP (71)
|
2/14/2008 5:45:03 AM
|
|
roberson@ibd.nrc-cnrc.gc.ca (Walter Roberson) wrote in
message <fp0gke$gqq$1@canopus.cc.umanitoba.ca>...
>
> I know little about MEX, but generally speaking, the memory
> that you are handed for any Matlab variable might be shared
> with other Matlab variables due to the "lazy copy" behaviour.
> When you change the memory in-place, you would have
changed those
> other variables too.
That is the danger, of course.
> The columns you see might be linked to columns of other
variables.
I suppose that is possible, but I seriously doubt it. When
you create a variable, MATLAB grabs memory from the heap to
do it. It has to grab the data memory as one contiguous
chunk in order for all of the other things you do with
variables to work properly, like reshape & calls to the BLAS
etc. Real data & imag data are two separate memory chunks,
but each one is contiguous. When freeing this data memory
back to the heap, it would have to be done all at once, not
piecemeal. That would be impossible if other variables were
allowed to share only portions of the data block like
columns. You wouldn't be able to free it until all of the
variables that had pieces were cleared. This would be a
tremendous waste of resources and a nightmare to manage. For
example, do the following:
format debug
a = rand(3,3)
b = a(:,1)
c = a(:,:)
d = a
You can see that the real data pointer pr for b and c are
different from a, indicating that a copy of the data was
made, whereas d and a share the same data pointer. In this
case a copy of the data was made to create c even though it
was the same size and could have used the same data pointer
as a. Now do this:
e = b(:)
Suddenly MATLAB realizes that all of the data is being
copied so an actual copy isn't made ... e simply uses the
same data pointer as b. I don't know what the rules for
data sharing are, but you can see that it can be tricky to
try and guess what MATLAB will do in every case.
But getting back to OP's original question. Can you modify
input variable data in place and get away with it? The
answer is yes, but only if you are very careful. And even
then you will have to accept some risk. If you create a huge
2GB variable in MATLAB and don't do anything that would
cause data sharing (like the d = a statement above), then
you can get away with modifying the data in place inside a
mex routineand not screw up other variables. The problem, of
course, is that there is no official list (that I am aware
of) of things you should avoid in order to prevent data
sharing. You should avoid assignments like the d = a above,
of course, but what else?
My advice to OP is to go ahead and do it (at risk) if the
memory/speed penalty is too great otherwise, but never do
MATLAB assignments and function calls that might result in
data sharing with this variable before your mex call.
None of this would be recommended by the Mathworks, of course.
James Tursa
|
|
0
|
|
|
|
Reply
|
aclassyguywithaknotac (1113)
|
2/14/2008 7:01:06 AM
|
|
"Petr Krysl" <pkryslNOSP@Mucsd.edu> schrieb im Newsbeitrag
news:fp0fqv$3gd$1@fred.mathworks.com...
> For the MEX experts out there: I would like to factor a huge
> matrix (passed in as a one-dimensional array) in-place in a
> mex file. Unfortunately, the documentation says there may
> be side effects (and there are: the Matlab executive is
> apparently getting all mixed up).
>
> Is there no way I could modify an argument in-place? If that
> is not possible, the penalty would be huge. We are talking
> about a matrix of several gigabytes size...
>
> Thanks for your help.
>
> Petr
Hi,
besides the warnings given by others, I have another question:
do you really need to do this in a mex file? And why?
MATLAB provides some sort of in-place operation for
variables, e.g.,
function X = somefunction(X)
% modify X
and you call this function by
foo = somefunction(foo);
then MATLAB will actually not copy your matrix foo...
Titus
|
|
0
|
|
|
|
Reply
|
titus.edelhofer (1621)
|
2/14/2008 8:42:34 AM
|
|
"Titus" <titus.edelhofer@mathworks.de> wrote in message
<fp0utr$4gr$1@fred.mathworks.com>...
>
> "Petr Krysl" <pkryslNOSP@Mucsd.edu> schrieb im Newsbeitrag
> news:fp0fqv$3gd$1@fred.mathworks.com...
> > For the MEX experts out there: I would like to factor a huge
> > matrix (passed in as a one-dimensional array) in-place in a
> > mex file. Unfortunately, the documentation says there may
> > be side effects (and there are: the Matlab executive is
> > apparently getting all mixed up).
> >
> > Is there no way I could modify an argument in-place? If that
> > is not possible, the penalty would be huge. We are talking
> > about a matrix of several gigabytes size...
> >
> > Thanks for your help.
> >
> > Petr
>
> Hi,
>
> besides the warnings given by others, I have another question:
> do you really need to do this in a mex file? And why?
> MATLAB provides some sort of in-place operation for
> variables, e.g.,
>
> function X = somefunction(X)
> % modify X
>
> and you call this function by
>
> foo = somefunction(foo);
>
> then MATLAB will actually not copy your matrix foo...
>
> Titus
>
>
James' advice is perfect.
Titus: there are lots of things you can do in mexFunctions
that are too slow in M, or take too much memory. So
sometimes you just can avoid going to C.
The new feature where MATLAB can avoid a memory copy in
functions like x=f(x) is really handy, but unfortunately
it's not made available to us mex authors. At least not
yet. It would be great if there could be query like:
if (mxIsThisVariableAShallowCopy (prhs [0]))
{
oops, make a copy of prhs[0], and modify the copy
}
else
{
modify prhs[0] in place
}
plhs [0] = prhs [0] ;
There would be lots of cool things a mexFunction could do if
it could modify its inputs (like a sparse cholupdate with an
O(1) best-case run time, for xample), but it's very dangerous.
The safest thing to do for a mexFunction that modifies its
inputs is to wrap it in an M-file that guarantees the
parameters to the hazardous mexFunction aren't a shallow
copy of another variable.
|
|
0
|
|
|
|
Reply
|
davis6756 (475)
|
2/14/2008 1:37:05 PM
|
|
"Tim Davis" <davis@cise.ufl.edu> wrote in message
<fp1g61$elr$1@fred.mathworks.com>...
> The new feature where MATLAB can avoid a memory copy in
> functions like x=f(x) is really handy, but unfortunately
> it's not made available to us mex authors.
Not to mention that, as you recalled, it is a relatively
new functionality that is not available in older ML
versions and in compiled code.
MEX in place modifications are very usefull for memory
savings. I have done it a lot without regrets.
J. Luis
|
|
0
|
|
|
|
Reply
|
Joaquim
|
2/14/2008 1:55:18 PM
|
|
"Tim Davis" <davis@cise.ufl.edu> writes:
> The new feature where MATLAB can avoid a memory copy in
> functions like x=f(x) is really handy, but unfortunately
> it's not made available to us mex authors. At least not
> yet. It would be great if there could be query like:
>
> if (mxIsThisVariableAShallowCopy (prhs [0]))
> {
> oops, make a copy of prhs[0], and modify the copy
This stuff is getting to be a bigger and bigger problem. More and more
features are being added to MATLAB without access methods for users, or
without proper documentation. In many cases, it is almost as if MATLAB
is aiming to be an analysis package rather than a programming
environment. Whenever a MATLAB employee can produce a chunk of code
that users cannot, the value of the software as a programming
environment has gone way down.
There's a bunch of new graphics stuff (like lineseries objects) that are
poorly (if at all) documented. There are opaque objects that users
cannot create on their own. There are features like you mention above
which are just "magic".
It's either intentional, or evidence of poor design, or ...
-Peter
|
|
0
|
|
|
|
Reply
|
boettcher (2302)
|
2/14/2008 2:15:37 PM
|
|
"Petr Krysl" <pkryslNOSP@Mucsd.edu> writes:
> roberson@ibd.nrc-cnrc.gc.ca (Walter Roberson) wrote in
> message <fp0gke$gqq$1@canopus.cc.umanitoba.ca>...
>> I know little about MEX, but generally speaking, the memory
>> that you are handed for any Matlab variable might be shared
>> with other Matlab variables due to the "lazy copy" behaviour.
>> The columns you see might be linked to columns of other
> variables.
>> When you change the memory in-place, you would have
> changed those
>> other variables too.
>
> I am not sure I follow: I can certainly access the
> individual elements of the array that I want to modify by
> read-access (and I see the right data). Why can't I write
> into the same memory locations? I understand that I might be
> modifying a copy of the input argument, but that does not
> seem to be the case. Actually, when I look at the matrix
> after I've modified the input argument and returned from the
> mex file, the matrix contains correctly modified data.
> Unfortunately something else seems to have been affected,
> and the Matlab interpreter stops working correctly.
First generate a dataset. Then do b=a; (Copy the dataset). Then run
your in-place code on "a". Then look at b. That's the problem.
This can happen in strange places if you're not careful.
The answer is to use the undocumented mxUnshareArray() before modifying
the input. We think the prototype is:
int mxUnshareArray(mxArray *, int);
We don't know what the second argument does. Zero seems to do the trick.
-Peter
|
|
0
|
|
|
|
Reply
|
boettcher (2302)
|
2/14/2008 2:17:54 PM
|
|
Peter Boettcher <boettcher@ll.mit.edu> wrote in message
<muyir0r1v1p.fsf@G99-Boettcher.llan.ll.mit.edu>...
> "Petr Krysl" <pkryslNOSP@Mucsd.edu> writes:
>
> First generate a dataset. Then do b=a; (Copy the
dataset). Then run
> your in-place code on "a". Then look at b. That's the
problem.
>
Actually, I'm trying carefully to avoid having two copies of
the data (because of the tremendous size). The variable I
want to modify is an attribute of a class (variable A): see the
solve method.
% Constructor of a sparse system matrix. This class provides
methods for
% constructing a skyline-storage system matrix, In-place
factorization into
% L*D*L^T, and solution via forward and backward substitution.
%
% The factorization and forward/backward substitution code
is adapted from
% a Fortran 77 kernel by Bathe/1976 (see Bittnar, Rericha 1983).
%
% function retobj = sparse_colsol_sysmat ()
%
% See discussion of constructors in <a href="matlab:helpwin
'sofea/classes/Contents'">classes/Contents</a>.
%
function self = sparse_colsol_sysmat (varargin)
class_name='sparse_colsol_sysmat';
parent=sysmat;
Factorized =false;
Single = false;
invalid_eqnum = 0;
A = [];
MAXA= [];
Column_height = [];
NEQ= 0;
MEPSIL = 1.0e-307;
Factorization_progress = [];
function assemble_method(ems)
ne =length(ems);
% Compute the height of the columns
Column_height =zeros(1,NEQ);
for m = 1:ne
eqnums=get(ems(m), 'eqnums');
minen=min(eqnums(eqnums~= 0));
for I=1:length (eqnums);
II=eqnums(I);
if (II~=invalid_eqnum)
ME=II-minen;
if (ME >Column_height(II))
Column_height(II) = ME;
end
end
end
end
% Compute the addresses of the Diagonal elements
MAXA=zeros(1,NEQ+1);
MAXA(1:2) =(1:2);
for I = 2:NEQ
MAXA(I+1)=MAXA(I)+Column_height(I)+1;
end
% Allocate the Matrix
if (Single)
disp ([' Allocating ' num2str(MAXA(end)) '
single-precision matrix elements'])
A =zeros(1,MAXA(end),'single');
else
disp ([' Allocating ' num2str(MAXA(end)) '
double-precision matrix elements'])
A =zeros(1,MAXA(end),'double');
end
% Assemble the element Matrices
for m = 1:ne
eqnums = get(ems(m), 'eqnums');
mat = get(ems(m), 'mat');
ND =length(eqnums);
for I = 1:ND %DO 200 I = 1,ND
II = eqnums(I);
if (II ~=invalid_eqnum)
MI = MAXA(II);
for J = 1:ND %DO 220 J = 1,ND
JJ = eqnums(J);
if (JJ ~=invalid_eqnum)
if (II >= JJ)
KK = MI+II-JJ;
A( KK ) = A( KK ) + mat( I,J );
end
end
end%220 CONTINUE
end
end%200 CONTINUE
end
end
self.assemble_method=@assemble_method;
function x=solve_method (V)
% This is a MEX code
if (~Factorized)
MAXA =uint32(MAXA);
colsoldecomp(A, MAXA);
Factorized = true;
end
if (Single)
V =single(V);
end
x=REDBAK_precision_sensitive(V);
if (Single)
x =double(x);
end
% This is pure-Matlab code
% if (~Factorized)
% DECOMP_precision_sensitive;
% Factorized = true;
% end
% if (Single)
% V =single(V);
% end
% x=REDBAK_precision_sensitive(V);
% if (Single)
% x =double(x);
% end
end
self.solve_method=@solve_method;
function retobj=start_method (dim)
NEQ =dim;
Factorized = ~true;
retobj =self;
end
self.start_method=@start_method;
function val = get_method(varargin)
if (nargin == 0)
val = {{{'dim'}, {'dimension, array '}};
{{'mat'}, {'sparse data matrix, array
[dim,dim]'}};
{{'MAXA'}, {'diagonal element address array'}}};
return;
else
prop_name=varargin{1};
switch prop_name
case 'mat'
val = sparse(NEQ,NEQ);
for m = 1:NEQ
k = MAXA(m);
r=m;
while (k <MAXA(m+1))
val(m,r)=A(k);
val(r,m)=A(k);
r=r+1; k=k+1;
end
end
case 'dim'
val = NEQ;
case 'MAXA'
val=MAXA;
case 'Column_height'
val=Column_height;
otherwise
error(['Unknown property name '''
prop_name '''!']);
end
end
return;
end
self.get_method=@get_method;
function retval=set_method(varargin)
if (nargin == 1)
retval = {{{'Factorization_progress'},
{'progress report function Handle'}};
{{'Single'}, {'use storage in single
precision, true or false'}};};
return;
end
prop_name=varargin{1};
val=varargin{2};
switch prop_name
case 'Factorization_progress'
Factorization_progress = val;
case 'Single'
Single = (val==true);
otherwise
error(['Unknown property ''' prop_name '''!'])
end
retval=self; % return self
end
self.set_method=@set_method;
self = class(self, class_name);
end
|
|
0
|
|
|
|
Reply
|
pkryslNOSP (71)
|
2/14/2008 2:48:02 PM
|
|
"Tim Davis" <davis@cise.ufl.edu> schrieb im Newsbeitrag
news:fp1g61$elr$1@fred.mathworks.com...
> "Titus" <titus.edelhofer@mathworks.de> wrote in message
> <fp0utr$4gr$1@fred.mathworks.com>...
>>
>> "Petr Krysl" <pkryslNOSP@Mucsd.edu> schrieb im Newsbeitrag
>> news:fp0fqv$3gd$1@fred.mathworks.com...
>> > For the MEX experts out there: I would like to factor a huge
>> > matrix (passed in as a one-dimensional array) in-place in a
>> > mex file. Unfortunately, the documentation says there may
>> > be side effects (and there are: the Matlab executive is
>> > apparently getting all mixed up).
>> >
>> > Is there no way I could modify an argument in-place? If that
>> > is not possible, the penalty would be huge. We are talking
>> > about a matrix of several gigabytes size...
>> >
>> > Thanks for your help.
>> >
>> > Petr
>>
>> Hi,
>>
>> besides the warnings given by others, I have another question:
>> do you really need to do this in a mex file? And why?
>> MATLAB provides some sort of in-place operation for
>> variables, e.g.,
>>
>> function X = somefunction(X)
>> % modify X
>>
>> and you call this function by
>>
>> foo = somefunction(foo);
>>
>> then MATLAB will actually not copy your matrix foo...
>>
>> Titus
>>
>>
>
> James' advice is perfect.
>
> Titus: there are lots of things you can do in mexFunctions
> that are too slow in M, or take too much memory. So
> sometimes you just can avoid going to C.
>
> The new feature where MATLAB can avoid a memory copy in
> functions like x=f(x) is really handy, but unfortunately
> it's not made available to us mex authors. At least not
> yet. It would be great if there could be query like:
>
> if (mxIsThisVariableAShallowCopy (prhs [0]))
> {
> oops, make a copy of prhs[0], and modify the copy
> }
> else
> {
> modify prhs[0] in place
> }
> plhs [0] = prhs [0] ;
>
> There would be lots of cool things a mexFunction could do if
> it could modify its inputs (like a sparse cholupdate with an
> O(1) best-case run time, for xample), but it's very dangerous.
>
> The safest thing to do for a mexFunction that modifies its
> inputs is to wrap it in an M-file that guarantees the
> parameters to the hazardous mexFunction aren't a shallow
> copy of another variable.
Hi Tim,
no doubt, MEX files are often quite handy, it's not that I want
to put this in question. The only thing I try to keep pointing at,
is, that I've seen quite a few MEX files of people who could
have avoided the effort when using (o.k., in newer versions)
the capabilities e.g. JIT has added to the MATLAB programming
language.
Titus
|
|
0
|
|
|
|
Reply
|
titus.edelhofer (1621)
|
2/14/2008 2:50:14 PM
|
|
"Titus" <titus.edelhofer@mathworks.de> wrote in message
<fp1kf6$pgq$1@fred.mathworks.com>...
>
> "Tim Davis" <davis@cise.ufl.edu> schrieb im Newsbeitrag
> news:fp1g61$elr$1@fred.mathworks.com...
> > "Titus" <titus.edelhofer@mathworks.de> wrote in message
> no doubt, MEX files are often quite handy, it's not that I
want
> to put this in question. The only thing I try to keep
pointing at,
> is, that I've seen quite a few MEX files of people who could
> have avoided the effort when using (o.k., in newer versions)
> the capabilities e.g. JIT has added to the MATLAB programming
> language.
>
> Titus
Titus,
Actually, my solver already modifies the matrix in place
when I use pure Matlab code. The factorization is about an
order of magnitude slower than the Matlab Choleski sparse
solver (which is a compiled mex code). Therefore, I see a
potential to speed up while at the same time preserving the
in-place aspect...
Petr
|
|
0
|
|
|
|
Reply
|
pkryslNOSP (71)
|
2/14/2008 3:05:18 PM
|
|
"Petr Krysl" <pkryslNOSP@Mucsd.edu> writes:
> Peter Boettcher <boettcher@ll.mit.edu> wrote in message
> <muyir0r1v1p.fsf@G99-Boettcher.llan.ll.mit.edu>...
>> "Petr Krysl" <pkryslNOSP@Mucsd.edu> writes:
>>
>> First generate a dataset. Then do b=a; (Copy the dataset). Then run
>> your in-place code on "a". Then look at b. That's the problem.
>
> Actually, I'm trying carefully to avoid having two copies of
> the data (because of the tremendous size). The variable I
> want to modify is an attribute of a class (variable A): see the
> solve method.
I'm trying to explain to you the problem with in-place modification.
The deal is that b=a does NOT copy the data, but instead shares it,
which leads to strange behavior. Then I give the solution to it.
If you can avoid it altogether, because you are sure it is never
assigned (this includes passing into functions, for example), then
ignore the whole thing! Modify your data at will!
-Peter
|
|
0
|
|
|
|
Reply
|
boettcher (2302)
|
2/14/2008 5:54:08 PM
|
|
Peter Boettcher <boettcher@ll.mit.edu> wrote in message
<muyir0r1v1p.fsf@G99-Boettcher.llan.ll.mit.edu>...
>
> The answer is to use the undocumented mxUnshareArray()
before modifying
> the input. We think the prototype is:
>
> int mxUnshareArray(mxArray *, int);
>
> We don't know what the second argument does. Zero seems
to do the trick.
>
>
> -Peter
If mxUnshareArray does what I think it does, which is make
a copy of the data (if needed) and reset the data pointers
to the new copy, then I disagree that this is *the* answer
to OP's problem. OP is trying to avoid multiple copies of
his data, not make new ones just so his mex routine can
modify the data in place. For example, suppose A was a 2GB
array and then you did B = A, and then you called the mex
routine mymexroutine(B). What is the difference, memory
usage wise, between calling mxUnshareArray(prhs[0]) and
then modifying prhs[0] in place vs just calling plhs[0]
=mxDuplicateArray(prhs[0]) and then modifying plhs[0]?
Nothing. You still get two copies of the 2GB data either
way. I still think the best thing to do is be very careful
on the MATLAB side to never do assignments or function
calls that might result in data sharing *before* you call
the mex routine. Then you can call mxUnshareArray inside
the mex routine just to be safe. In those cases where you
screwed up on the MATLAB side and the data was in fact
shared, you would wind up paying the memory/speed penalty
or maybe even exhaust the heap. But at least you would
return with an error instead of screwing up other
variables had you not called mxUnshareArray.
Do you know if mxUnshareArray behaves like other mx
functions that allocate memory? i.e., if it fails in a mex
routine does it free all memory allocated inside the mex
routine and return control to MATLAB? And in an engine
application if it fails does it return 1?
James Tursa
|
|
0
|
|
|
|
Reply
|
aclassyguywithaknotac (1113)
|
2/14/2008 10:13:02 PM
|
|
Just did a quick check. mxUnshareArray does indeed return
control to MATLAB (with an out-of-memory error message) if
there is an out of memory error inside the call. I don't
know about engine applications yet.
James Tursa
|
|
0
|
|
|
|
Reply
|
aclassyguywithaknotac (1113)
|
2/15/2008 1:31:02 AM
|
|
"Petr Krysl" <pkryslNOSP@Mucsd.edu> wrote in message
<fp1lbe$8v7$1@fred.mathworks.com>...
> "Titus" <titus.edelhofer@mathworks.de> wrote in message
> <fp1kf6$pgq$1@fred.mathworks.com>...
> >
> > "Tim Davis" <davis@cise.ufl.edu> schrieb im Newsbeitrag
> > news:fp1g61$elr$1@fred.mathworks.com...
> > > "Titus" <titus.edelhofer@mathworks.de> wrote in message
> > no doubt, MEX files are often quite handy, it's not that I
> want
> > to put this in question. The only thing I try to keep
> pointing at,
> > is, that I've seen quite a few MEX files of people who could
> > have avoided the effort when using (o.k., in newer versions)
> > the capabilities e.g. JIT has added to the MATLAB
programming
> > language.
> >
> > Titus
>
> Titus,
>
> Actually, my solver already modifies the matrix in place
> when I use pure Matlab code. The factorization is about an
> order of magnitude slower than the Matlab Choleski sparse
> solver (which is a compiled mex code). Therefore, I see a
> potential to speed up while at the same time preserving the
> in-place aspect...
>
> Petr
>
<Advance notice of particular bias>
I'm the author of sparse Cholesky in MATLAB
</end notice>
I wouldn't recommend using a skyline code. Even written in
C, theres no way any skyline code can beat a true sparse
Cholesky code. For more details, see:
http://doi.acm.org/10.1145/1236463.1236465
The question about how to modify a mxArray in place is still
a good one, but you shouldn't try to do it for this case.
|
|
0
|
|
|
|
Reply
|
davis6756 (475)
|
2/15/2008 1:50:17 AM
|
|
"Tim Davis" <davis@cise.ufl.edu> wrote in message
<fp2r4p$s2u$1@fred.mathworks.com>...
>
> <Advance notice of particular bias>
> I'm the author of sparse Cholesky in MATLAB
> </end notice>
>
> I wouldn't recommend using a skyline code. Even written in
> C, theres no way any skyline code can beat a true sparse
> Cholesky code. For more details, see:
>
> http://doi.acm.org/10.1145/1236463.1236465
>
> The question about how to modify a mxArray in place is still
> a good one, but you shouldn't try to do it for this case.
>
Tim,
I hear you, and I know that the Cholesky solver in Matlab is
lightning fast. However, I'm up against its memory usage
here: the largest matrix I want to deal with has on the
order of 20 GB of nonzeros, and that is just the upper
triangle.
The skyline is slower, but its memory usage is way down
because I can do the factorization in place.
Petr
|
|
0
|
|
|
|
Reply
|
pkryslNOSP (71)
|
2/15/2008 2:15:02 AM
|
|
>
> Tim,
>
> I hear you, and I know that the Cholesky solver in Matlab is
> lightning fast. However, I'm up against its memory usage
> here: the largest matrix I want to deal with has on the
> order of 20 GB of nonzeros, and that is just the upper
> triangle.
>
> The skyline is slower, but its memory usage is way down
> because I can do the factorization in place.
>
> Petr
What about an iterative solver then, like something from the
preconditioned conjugate gradient family. You only need to
store the matrix plus some additional vectors, so it should
be much lighter in terms of memory use than trying to form L*L'.
You could probably get away with only storing the upper
triangle as well, as you only need to implement a
matrix-vector multiply.
Skyline solvers are generally really, really slow, and they
should also probably use more memory to store the matrix in
skyline format as opposed to a true sparse format.
Darren
|
|
0
|
|
|
|
Reply
|
d_engwirda.nospam (14)
|
2/15/2008 10:23:02 AM
|
|
"Titus" <titus.edelhofer@mathworks.de> wrote in message ...
> Hi Tim,
> no doubt, MEX files are often quite handy, it's not that I
want
> to put this in question. The only thing I try to keep
pointing at,
> is, that I've seen quite a few MEX files of people who could
> have avoided the effort when using (o.k., in newer versions)
> the capabilities e.g. JIT has added to the MATLAB programming
> language.
>
> Titus
>
>
Yes, I agree with you. Sometimes using mex is not needed,
when the latest JIT can do just as well. mex should be the
last resort.
|
|
0
|
|
|
|
Reply
|
davis6756 (475)
|
2/15/2008 11:50:04 AM
|
|
"Darren Engwirda" <d_engwirda.nospam@hotmail.com> wrote in
message <fp3p66$4vu$1@fred.mathworks.com>...
>
> >
> > Tim,
> >
> > I hear you, and I know that the Cholesky solver in Matlab is
> > lightning fast. However, I'm up against its memory usage
> > here: the largest matrix I want to deal with has on the
> > order of 20 GB of nonzeros, and that is just the upper
> > triangle.
> >
> > The skyline is slower, but its memory usage is way down
> > because I can do the factorization in place.
> >
> > Petr
>
> What about an iterative solver then, like something from the
> preconditioned conjugate gradient family. You only need to
> store the matrix plus some additional vectors, so it should
> be much lighter in terms of memory use than trying to form
L*L'.
>
> You could probably get away with only storing the upper
> triangle as well, as you only need to implement a
> matrix-vector multiply.
>
> Skyline solvers are generally really, really slow, and they
> should also probably use more memory to store the matrix in
> skyline format as opposed to a true sparse format.
>
>
> Darren
>
If chol is running out of memory, then iterative methods are
definitely worth trying.
Regarding the use of chol: internally, chol uses a
different data structure for L than the standard MATLAB
sparse matrix. So x=A\b when A is symmetric positive
definite takes less memory than what is required to hold a
MATLAB L. However, L=chol(A,'lower') is worse; it must
create a MATLAB sparse matrix L from its (more compact)
supernodal L. This is not quite as bad as you may imagine,
because some of the memory converting the supernodal L into
the MATLAB L is done in-place.
What is still worse, R=chol(A) must make another copy,
because the matrix computed by CHOLMOD is lower triangular,
not upper.
So R=chol(A) first creates a supernodal L, and then modifies
it partly in place into the MATLAB sparse L. Then R=L' is
performed. that last step is a pure copy, and thus the
total memory usage of R=chol(A) is about twice that of
L=chol(A,'lower').
So ... the moral is ... if you're running out of memory in
R=chol(A), use L=chol(A,'lower') instead.
Of course, in both cases, you should actually use
[R,q,q] = chol(A) or [L,p,q] = chol(A,'lower'), since
otherwise you don't get the fill-reducing ordering, q.
You can read the code for "chol" itself in
SuiteSparse/CHOLMOD/MATLAB/chol2.c (for the R=chol(A) usage)
or SuiteSparse/CHOLMOD/MATLAB/lchol.c for the
L=chol(A,'lower') usage. The "chol" code itself is not
there; but it's pretty much an amalgam of chol2.c and
lchol.c. Note the extra transpose in chol2.c. SuiteSparse
is on the File Exchange.
|
|
0
|
|
|
|
Reply
|
davis6756 (475)
|
2/15/2008 12:02:02 PM
|
|
"James Tursa" <aclassyguywithaknotac@hotmail.com> writes:
> Peter Boettcher <boettcher@ll.mit.edu> wrote in message
> <muyir0r1v1p.fsf@G99-Boettcher.llan.ll.mit.edu>...
>>
>> The answer is to use the undocumented mxUnshareArray() before
>> modifying the input. We think the prototype is:
>>
>> int mxUnshareArray(mxArray *, int);
>>
>> We don't know what the second argument does. Zero seems to do the
>> trick.
>
> If mxUnshareArray does what I think it does, which is make
> a copy of the data (if needed) and reset the data pointers
> to the new copy, then I disagree that this is *the* answer
> to OP's problem. OP is trying to avoid multiple copies of
> his data, not make new ones just so his mex routine can
> modify the data in place. For example, suppose A was a 2GB
> array and then you did B = A, and then you called the mex
> routine mymexroutine(B). What is the difference, memory
> usage wise, between calling mxUnshareArray(prhs[0]) and
> then modifying prhs[0] in place vs just calling plhs[0]
> =mxDuplicateArray(prhs[0]) and then modifying plhs[0]?
> Nothing. You still get two copies of the 2GB data either
> way.
Well... yes, in that case. The difference is that mxUnshareArray()
copies the data only when necessary, while mxDuplicateArray will do it
every time, all the time.
> I still think the best thing to do is be very careful
> on the MATLAB side to never do assignments or function
> calls that might result in data sharing *before* you call
> the mex routine. Then you can call mxUnshareArray inside
> the mex routine just to be safe. In those cases where you
> screwed up on the MATLAB side and the data was in fact
> shared, you would wind up paying the memory/speed penalty
> or maybe even exhaust the heap. But at least you would
> return with an error instead of screwing up other
> variables had you not called mxUnshareArray.
Right.
> Do you know if mxUnshareArray behaves like other mx
> functions that allocate memory? i.e., if it fails in a mex
> routine does it free all memory allocated inside the mex
> routine and return control to MATLAB? And in an engine
> application if it fails does it return 1?
I assume this to be the case...
-Peter
|
|
0
|
|
|
|
Reply
|
boettcher (2302)
|
2/15/2008 1:43:20 PM
|
|
"Tim Davis" <davis@cise.ufl.edu> wrote in message
<fp3uvq$75i$1@fred.mathworks.com>...
> "Darren Engwirda" <d_engwirda.nospam@hotmail.com> wrote in
> message <fp3p66$4vu$1@fred.mathworks.com>...
> >
> > >
Thank you very much, Tim. The information below is worth
its weight in gold (figuratively ;))...
Petr
> Regarding the use of chol: internally, chol uses a
> different data structure for L than the standard MATLAB
> sparse matrix. So x=A\b when A is symmetric positive
> definite takes less memory than what is required to hold a
> MATLAB L. However, L=chol(A,'lower') is worse; it must
> create a MATLAB sparse matrix L from its (more compact)
> supernodal L. This is not quite as bad as you may imagine,
> because some of the memory converting the supernodal L into
> the MATLAB L is done in-place.
>
> What is still worse, R=chol(A) must make another copy,
> because the matrix computed by CHOLMOD is lower triangular,
> not upper.
>
> So R=chol(A) first creates a supernodal L, and then modifies
> it partly in place into the MATLAB sparse L. Then R=L' is
> performed. that last step is a pure copy, and thus the
> total memory usage of R=chol(A) is about twice that of
> L=chol(A,'lower').
>
> So ... the moral is ... if you're running out of memory in
> R=chol(A), use L=chol(A,'lower') instead.
>
> Of course, in both cases, you should actually use
> [R,q,q] = chol(A) or [L,p,q] = chol(A,'lower'), since
> otherwise you don't get the fill-reducing ordering, q.
>
> You can read the code for "chol" itself in
> SuiteSparse/CHOLMOD/MATLAB/chol2.c (for the R=chol(A) usage)
> or SuiteSparse/CHOLMOD/MATLAB/lchol.c for the
> L=chol(A,'lower') usage. The "chol" code itself is not
> there; but it's pretty much an amalgam of chol2.c and
> lchol.c. Note the extra transpose in chol2.c. SuiteSparse
> is on the File Exchange.
|
|
0
|
|
|
|
Reply
|
pkryslNOSP (71)
|
2/15/2008 6:01:03 PM
|
|
"Darren Engwirda" <d_engwirda.nospam@hotmail.com> wrote in
message <fp3p66$4vu$1@fred.mathworks.com>...
> What about an iterative solver then, like something from the
> preconditioned conjugate gradient family. You only need to
> store the matrix plus some additional vectors, so it should
> be much lighter in terms of memory use than trying to form
L*L'.
>
> You could probably get away with only storing the upper
> triangle as well, as you only need to implement a
> matrix-vector multiply.
I agree with you there Darren, for a one-shot solution that
will be a good alternative. However, I need to perform on
the order of a few dozen or a hundred solves (the linear
equation solver is called from within an eigenvalue solver
repeatedly). Then a single factorization may be amortized
quite quickly.
>
> Skyline solvers are generally really, really slow, and they
> should also probably use more memory to store the matrix in
> skyline format as opposed to a true sparse format.
For finite element applications, with fairly limited number
of non-zeros and reasonable fill in, the skyline solver is
not too bad. Furthermore, I'm hoping to amortize the cost
of the factorization as indicated above.
Petr
|
|
0
|
|
|
|
Reply
|
pkryslNOSP (71)
|
2/15/2008 6:07:03 PM
|
|
"Petr Krysl" <pkryslNOSP@Mucsd.edu> wrote in message
> Thank you very much, Tim. The information below is worth
> its weight in gold (figuratively ;))...
>
> Petr
>
Considering that bits don't weigh very much at all, maybe
it's worth its weight in gold after all :-)
|
|
0
|
|
|
|
Reply
|
davis6756 (475)
|
2/15/2008 6:46:03 PM
|
|
"Joaquim Luis" <jluis@--ualg--.pt> wrote in message
<fp1h86$f8o$1@fred.mathworks.com>...
> "Tim Davis" <davis@cise.ufl.edu> wrote in message
> <fp1g61$elr$1@fred.mathworks.com>...
>
> > The new feature where MATLAB can avoid a memory copy in
> > functions like x=f(x) is really handy, but unfortunately
> > it's not made available to us mex authors.
>
> Not to mention that, as you recalled, it is a relatively
> new functionality that is not available in older ML
> versions and in compiled code.
From which version of MATLAB this kind of memory saving is
implemented?
Do you know why it is not implemented in compiled code?
Thanks,
Bruno
|
|
0
|
|
|
|
Reply
|
b.luong (628)
|
2/16/2008 9:22:02 AM
|
|
"Bruno Luong" <b.luong@fogale.fr> wrote in message
<fp69vp$4vh$1@fred.mathworks.com>...
> "Joaquim Luis" <jluis@--ualg--.pt> wrote in message
> <fp1h86$f8o$1@fred.mathworks.com>...
>
> > Not to mention that, as you recalled, it is a
relatively
> > new functionality that is not available in older ML
> > versions and in compiled code.
>
> From which version of MATLAB this kind of memory saving
is
> implemented?
I don't know. Maybe at 2006b. I learnt about it in this
Loren's blog
http://blogs.mathworks.com/loren/2007/03/22/in-place-
operations-on-data/
> Do you know why it is not implemented in compiled code?
I was refering to *real* compiler which ended its existance
at R13.
L. Luis
|
|
0
|
|
|
|
Reply
|
Joaquim
|
2/16/2008 2:28:01 PM
|
|
"Tim Davis" <davis@cise.ufl.edu> wrote in message
<fp4mlb$fb4$1@fred.mathworks.com>...
> "Petr Krysl" <pkryslNOSP@Mucsd.edu> wrote in message
>
> > Thank you very much, Tim. The information below is worth
> > its weight in gold (figuratively ;))...
Tim,
I would like to avoid the transpose of L =chol(A,'lower')
when solving by forward/backward substitution (this is where
I run out of memory). Is there support in the cholmod
package for this operation?
Thanks very much,
Petr
|
|
0
|
|
|
|
Reply
|
pkryslNOSP (71)
|
2/17/2008 1:02:02 AM
|
|
"Petr Krysl" <pkryslNOSP@Mucsd.edu> wrote in message
> I would like to avoid the transpose of L =chol(A,'lower')
> when solving by forward/backward substitution (this is where
> I run out of memory). Is there support in the cholmod
> package for this operation?
Actually, I have just had some sort of inspiration ;). I
would do
c=A\V; x = (c'/A)';
instead of
x = A'\(A\V);
That seems to do the trick.
Petr
|
|
0
|
|
|
|
Reply
|
pkryslNOSP (71)
|
2/17/2008 1:52:02 AM
|
|
"Petr Krysl" <pkryslNOSP@Mucsd.edu> wrote in message
<fp8402$n2u$1@fred.mathworks.com>...
> "Petr Krysl" <pkryslNOSP@Mucsd.edu> wrote in message
>
> > I would like to avoid the transpose of L =chol(A,'lower')
> > when solving by forward/backward substitution (this is where
> > I run out of memory). Is there support in the cholmod
> > package for this operation?
>
> Actually, I have just had some sort of inspiration ;). I
> would do
>
> c=A\V; x = (c'/A)';
>
> instead of
>
> x = A'\(A\V);
>
> That seems to do the trick.
It seemed a good idea, but the implementation got in the
way. Apparently, the / is implemented with A'\c, which
means that the matrix is first transposed. Exactly what I
wanted to avoid. So I'm still looking for a solution. Ideas
and suggestions are welcome.
Petr
PS: Here is the test that shows that the memory is increased
during the backward substitution phase (at least with 2007b).
clear all
n = 6500;
disp(' Starting in Five seconds')
pause(5);
% A = spalloc(n,n,nzmax);
% for i=1:n
% v = randn(i-prof(i)+1,1);
% A(prof(i):i,i) = v;
% A(i,prof(i):i) = v';
% A(i,i) = abs(A(i,i));
% i
% end
disp(' Starting assembly')
A= sprandsym(n,0.1);
A = A + diag(sum(abs(A)));
V =rand(n,1);
disp(' Finished assembling the matrix')
% p=symamd(A);
% A = A(p,p);
% spy(A)
pause(5);
disp(' Starting factorization')
A = chol(A,'lower');
disp(' Finished factorization of the matrix')
pause(5);
disp(' Starting Forward substitution')
c=A\V;
disp(' Finished forward Substitution')
pause(5);
disp(' Starting backward substitution')
x=(c'/A)';
disp(' Finished backward Substitution')
|
|
0
|
|
|
|
Reply
|
pkryslNOSP (71)
|
2/18/2008 10:55:03 PM
|
|
"Petr Krysl" <pkryslNOSP@Mucsd.edu> wrote in message
<fp812a$qe2$1@fred.mathworks.com>...
> "Tim Davis" <davis@cise.ufl.edu> wrote in message
> <fp4mlb$fb4$1@fred.mathworks.com>...
> > "Petr Krysl" <pkryslNOSP@Mucsd.edu> wrote in message
> >
> > > Thank you very much, Tim. The information below is worth
> > > its weight in gold (figuratively ;))...
>
> Tim,
>
> I would like to avoid the transpose of L =chol(A,'lower')
> when solving by forward/backward substitution (this is where
> I run out of memory). Is there support in the cholmod
> package for this operation?
>
> Thanks very much,
>
> Petr
You want to do the forward/backsolve after getting L, right?
Try cs_lsolve and cs_ltsolve, in CSparse/CXSparse. I can't
recall off the top of my head if I have that same code in
CHOLMOD ... I'd have to look it up. But I know it's in C*Sparse
|
|
0
|
|
|
|
Reply
|
davis6756 (475)
|
2/19/2008 1:11:01 AM
|
|
"Petr Krysl" <pkryslNOSP@Mucsd.edu> wrote in message
<fpd2c7$eqt$1@fred.mathworks.com>...
> "Petr Krysl" <pkryslNOSP@Mucsd.edu> wrote in message
> <fp8402$n2u$1@fred.mathworks.com>...
> > "Petr Krysl" <pkryslNOSP@Mucsd.edu> wrote in message
> >
> > > I would like to avoid the transpose of L =chol(A,'lower')
> > > when solving by forward/backward substitution (this is
where
> > > I run out of memory). Is there support in the cholmod
> > > package for this operation?
> >
> > Actually, I have just had some sort of inspiration ;). I
> > would do
> >
> > c=A\V; x = (c'/A)';
> >
> > instead of
> >
> > x = A'\(A\V);
> >
> > That seems to do the trick.
>
> It seemed a good idea, but the implementation got in the
> way. Apparently, the / is implemented with A'\c, which
> means that the matrix is first transposed. Exactly what I
> wanted to avoid. So I'm still looking for a solution. Ideas
> and suggestions are welcome.
>
> Petr
>
> PS: Here is the test that shows that the memory is increased
> during the backward substitution phase (at least with 2007b).
>
>
> clear all
> n = 6500;
> disp(' Starting in Five seconds')
> pause(5);
> % A = spalloc(n,n,nzmax);
> % for i=1:n
> % v = randn(i-prof(i)+1,1);
> % A(prof(i):i,i) = v;
> % A(i,prof(i):i) = v';
> % A(i,i) = abs(A(i,i));
> % i
> % end
> disp(' Starting assembly')
> A= sprandsym(n,0.1);
> A = A + diag(sum(abs(A)));
> V =rand(n,1);
> disp(' Finished assembling the matrix')
> % p=symamd(A);
> % A = A(p,p);
> % spy(A)
>
> pause(5);
> disp(' Starting factorization')
> A = chol(A,'lower');
> disp(' Finished factorization of the matrix')
> pause(5);
> disp(' Starting Forward substitution')
> c=A\V;
> disp(' Finished forward Substitution')
> pause(5);
> disp(' Starting backward substitution')
> x=(c'/A)';
> disp(' Finished backward Substitution')
I see ... I was confused by your use of "A" for "L". A is
the original matrix, so c=A\v looked like a full chol to me,
not a forward solve.
Don't use symamd ... let chol do the work (using amd
internally):
[L,ignore,p] = chol(A, 'lower') ;
x = cs_ltsolve (L, cs_lsolve (L, b(p))) ;
x (p) = x ;
I might be off on permutations ... I always have to rethink
them from scratch - I'm a bit dyslexic and get rows and
columns mixed up sometimes :-)
Also - you've picked an exceedingly slow and memory
intensive method for creating A. See Loren's March 1st,
2007, blog for more details on how to do it better.
|
|
0
|
|
|
|
Reply
|
davis6756 (475)
|
2/19/2008 1:17:02 AM
|
|
"Tim Davis" <davis@cise.ufl.edu> wrote in message
> [L,ignore,p] = chol(A, 'lower') ;
> x = cs_ltsolve (L, cs_lsolve (L, b(p))) ;
> x (p) = x ;
>
Thank you Tim, this works like a charm. I do have one more
wish though: is this possible to do this with cholmod?
Otherwise I'd have to distribute csparse with my toolbox and
also I'd have to make sure that csparse is installed... Not
that it is a big deal, the install script works very well
indeed. (By the way, I just ordered the companion SIAM
book, looks like a good read.)
Thanks again for your help,
Petr
|
|
0
|
|
|
|
Reply
|
pkryslNOSP (71)
|
2/19/2008 2:47:01 AM
|
|
cs_lsolve and cs_ltsolve are included in Csparse,
but not in CHOLMOD or LDL, as long as I can find.
cs_lsolve and cs_ltsolve in Csparse are pretty slow,
compared to the triangular solvers in
CHOLMOD/LDL/mldivide. (For the triangular solve,
mldivide was 3 times faster than cs_lsolve and cs_ltsolve
in Csparse, for my problem.)
|
|
0
|
|
|
|
Reply
|
jmathgeek (18)
|
2/19/2008 1:29:02 PM
|
|
"J Mathgeek" <jmathgeek@gmail.com> wrote in message
<fpeliu$2h$1@fred.mathworks.com>...
> cs_lsolve and cs_ltsolve are included in Csparse,
> but not in CHOLMOD or LDL, as long as I can find.
> cs_lsolve and cs_ltsolve in Csparse are pretty slow,
> compared to the triangular solvers in
> CHOLMOD/LDL/mldivide. (For the triangular solve,
> mldivide was 3 times faster than cs_lsolve and cs_ltsolve
> in Csparse, for my problem.)
>
If b is sparse, as I think you're trying to do, CSparse will
be slow. Its triangular solvers are designed for dense
right-hand-sides. CSparse has a solver, cs_spsolve, for
sparse right-hand-side, but it doesn't have a MATLAB interface.
|
|
0
|
|
|
|
Reply
|
davis6756 (475)
|
2/20/2008 1:16:11 AM
|
|
What if there are multiple sparse right-hand sides, will
cs_spsolve still be faster than mldivide?
(Are you planning on giving cs_spsolve a MATLAB interface?)
|
|
0
|
|
|
|
Reply
|
jmathgeek (18)
|
2/22/2008 12:01:02 PM
|
|
"J Mathgeek" <jmathgeek@gmail.com> wrote in message
<fpmdhu$kng$1@fred.mathworks.com>...
> What if there are multiple sparse right-hand sides, will
> cs_spsolve still be faster than mldivide?
>
> (Are you planning on giving cs_spsolve a MATLAB interface?)
>
In my book, I think that's an exercise left to the reader
.... :-)
It's trickier than it looks at first glance. In part, it
requires an O(k*log(k)) time sort, where k = nnz(x) and
x=L\b is the result. That sort is "useless",
algorithmically speaking. It's there only because MATLAB
requires sparse matrices with sorted columns. However, that
sort can dominate the total run time. The cs_spsolve time
can be as low as Omega(k).
The mexFunction must not do any O(n) work, either, so it
can't do any "calloc" of workspaces ("malloc" instead).
|
|
0
|
|
|
|
Reply
|
davis6756 (475)
|
2/22/2008 9:14:03 PM
|
|
"Petr Krysl" <pkryslNOSP@Mucsd.edu> wrote in message
<fp0fqv$3gd$1@fred.mathworks.com>...
> For the MEX experts out there: I would like to factor a
huge
> matrix (passed in as a one-dimensional array) in-place in
a
> mex file. Unfortunately, the documentation says there may
> be side effects (and there are: the Matlab executive is
> apparently getting all mixed up).
>
> Is there no way I could modify an argument in-place? If
that
> is not possible, the penalty would be huge. We are
talking
> about a matrix of several gigabytes size...
>
> Thanks for your help.
>
> Petr
Back on this original point, I've haven't had any problems
abusing the const nature of the data of a mex input. You
can unintentionally change other matlab variables, but this
hasn't caused Matlab internal errors. For example the mex
file MyFun.c:
#include "mex.h"
#include "matrix.h"
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
double *pData;
int i;
pData = mxGetPr(prhs[0]); //Grab the data pointer
for (i = 0; i < mxGetNumberOfElements(prhs[0]); i++)
pData[i]++;
}
And then:
a = [1,2]; b = a;
MyFun(a);
a =
2 3
b =
2 3
b = b + 1;
a =
2 3
b =
3 4
No Matlab internal errors... If you try to change the data
pointer of the input it spits the dummy though.
Cheers,
Andrew
|
|
0
|
|
|
|
Reply
|
awbsmith (68)
|
2/27/2008 7:49:01 AM
|
|
"Andrew " <awbsmith@itee.uq.edu.au> wrote in message
....
> Back on this original point, I've haven't had any problems
> abusing the const nature of the data of a mex input. You
> can unintentionally change other matlab variables, but this
> hasn't caused Matlab internal errors. For example the mex
> file MyFun.c:
>
Danger Will Robinson, Danger!
:-)
Modifying the inputs in a mexFunction is a Really Bad Idea -
unless and until it's supported by The MathWorks. You may
not think you're breaking something when you really are, if
you were to test the use of your mexFunction carefully.
Give me any mexFunction that can modify its inputs, and I
can merrily destroy MATLAB for you. Or at least I can
destroy things you don't expect to be destroyed.
|
|
0
|
|
|
|
Reply
|
davis6756 (475)
|
3/1/2008 10:57:01 PM
|
|
If I changed my example function to check the input is a
non-sparse double precision matrix what could possibli go
wrong? I'm not seeing how modifying a data value could be
anything but opaque to Matlab.
Andrew
"Tim Davis" <davis@cise.ufl.edu> wrote in message
<fqcmvt$ss7$1@fred.mathworks.com>...
> "Andrew " <awbsmith@itee.uq.edu.au> wrote in message
> ...
> > Back on this original point, I've haven't had any
problems
> > abusing the const nature of the data of a mex input.
You
> > can unintentionally change other matlab variables, but
this
> > hasn't caused Matlab internal errors. For example the
mex
> > file MyFun.c:
> >
>
> Danger Will Robinson, Danger!
>
> :-)
>
> Modifying the inputs in a mexFunction is a Really Bad
Idea -
> unless and until it's supported by The MathWorks. You may
> not think you're breaking something when you really are,
if
> you were to test the use of your mexFunction carefully.
>
> Give me any mexFunction that can modify its inputs, and I
> can merrily destroy MATLAB for you. Or at least I can
> destroy things you don't expect to be destroyed.
|
|
0
|
|
|
|
Reply
|
awbsmith (68)
|
3/3/2008 1:27:01 AM
|
|
"Andrew " <awbsmith@itee.uq.edu.au> wrote in message
<fqfk55$t1a$1@fred.mathworks.com>...
> If I changed my example function to check the input is a
> non-sparse double precision matrix what could possibli go
> wrong? I'm not seeing how modifying a data value could be
> anything but opaque to Matlab.
>
> Andrew
>
It can fail. It has nothing to do with sparsity. What if
you do something like
x = fun(a+b)
where "fun" is your mangling mexFunction? What if you do
a = b ;
x = fun (a) ;
then look at b? You mexFunction has modified *both* a and b.
Modifying the inputs to a mexFunction is far from opaque to
MATLAB.
|
|
0
|
|
|
|
Reply
|
davis6756 (475)
|
3/7/2008 12:21:02 PM
|
|
"Tim Davis" <davis@cise.ufl.edu> wrote in message
> >
>
> It can fail. It has nothing to do with sparsity. What if
> you do something like
There are actually even worse failings. Here is an example
that completely destroys Matlab's representation of the
matrix that is being modified in place. And still, all I'm
doing is over writing the elements of the array in which
Matlab holds the input matrix. So not only the variable
referencing is in danger here.
For details refer to
http://www.mathworks.com/matlabcentral/newsreader/view_thread/163748#415068
Petr
|
|
0
|
|
|
|
Reply
|
pkryslNOSP (71)
|
3/8/2008 2:54:02 AM
|
|
We're trying to make an inplace function, so we don't need
to assign outputs. Think of it as a C function with the
form:
void myFun(double * pIn, int* pSize);
Making the inplace function return its input is really
bad. So put in an "if (nlhs > 0) then error" line if you
like.
fun(a+b) works fine, but since a+b makes a temporary
mxArray you can't access the result.
As I mentioned before:
a = b ;
fun(a);
will modify a and b, so the programmers discretion is
required. But I think this thread started with someone
wanting an inplace funtion because they couldn't hold two
copies of the input in memory anyway, i.e.
a = not_inplace_fun(b) generates an out of memory error
anyway...
"Tim Davis" <davis@cise.ufl.edu> wrote in message
<fqrbve$jol$1@fred.mathworks.com>...
> "Andrew " <awbsmith@itee.uq.edu.au> wrote in message
> <fqfk55$t1a$1@fred.mathworks.com>...
> > If I changed my example function to check the input is
a
> > non-sparse double precision matrix what could possibli
go
> > wrong? I'm not seeing how modifying a data value could
be
> > anything but opaque to Matlab.
> >
> > Andrew
> >
>
> It can fail. It has nothing to do with sparsity. What if
> you do something like
>
> x = fun(a+b)
>
> where "fun" is your mangling mexFunction? What if you do
>
> a = b ;
> x = fun (a) ;
>
> then look at b? You mexFunction has modified *both* a
and b.
>
> Modifying the inputs to a mexFunction is far from opaque
to
> MATLAB.
|
|
0
|
|
|
|
Reply
|
awbsmith (68)
|
3/10/2008 2:24:02 AM
|
|
I took a quick look at this Petr and couldn't see where its
doing anything in place. You can typecast the pointers to
the inputs to const and it still compiles...
const COLSOL_Index *MAXA = (const COLSOL_Index *)mxGetData
(pargin[1]);
const double *Ain= (const double*)mxGetPr(pargin[0]) ;
"Petr Krysl" <pkryslNOSP@Mucsd.edu> wrote in message
<fqsv4a$npj$1@fred.mathworks.com>...
> "Tim Davis" <davis@cise.ufl.edu> wrote in message
> > >
> >
> > It can fail. It has nothing to do with sparsity. What
if
> > you do something like
>
> There are actually even worse failings. Here is an example
> that completely destroys Matlab's representation of the
> matrix that is being modified in place. And still, all
I'm
> doing is over writing the elements of the array in which
> Matlab holds the input matrix. So not only the variable
> referencing is in danger here.
>
> For details refer to
>
http://www.mathworks.com/matlabcentral/newsreader/view_threa
d/163748#415068
>
> Petr
|
|
0
|
|
|
|
Reply
|
awbsmith (68)
|
3/10/2008 2:37:04 AM
|
|
"Andrew " <awbsmith@itee.uq.edu.au> wrote in message
<fr26sg$sr9$1@fred.mathworks.com>...
> I took a quick look at this Petr and couldn't see where its
> doing anything in place. You can typecast the pointers to
> the inputs to const and it still compiles...
>
Apologies. I posted code which was tweaked in my attempts
to understand what was going on. The correct code is
....
if (mxIsClass(pargin [0], "double")) {
double *A= mxGetPr (pargin[0]) ;
int n;
// for (n = 0; n < MAXA [neq]; ++n) { printf ("A
[%d] =%g\n",n,A[n]); }
if (! (decomp_double(A, MAXA, neq)==0)) {
mexErrMsgTxt ("colsoldecomp: A factorization
failed") ;
}
// for (n = 0; n < MAXA [neq]; ++n) { printf ("A
[%d] =%g\n",n,A[n]); }
} else if (mxIsClass(pargin [0], "single")) {
...
}
....
This is a call to an in-place factorization routine. The
doubles in A are modified in place. The correct mex routine
and the test data are posted in the archive
http://hogwarts.ucsd.edu/~pkrysl/public/colsol.zip
When compiled using colsol_make.m, the test reports
decomposed matrix of the form
A =
0.0e+000 *
1.#INF
1.#INF
-1.#INF
...
-1.#INF
0
1.#INF
I have even difficulty understanding what this printout means!
Petr
|
|
0
|
|
|
|
Reply
|
pkryslNOSP (71)
|
3/10/2008 3:19:02 PM
|
|
"Andrew " <awbsmith@itee.uq.edu.au> wrote in message
<fr2642$ltq$1@fred.mathworks.com>...
> We're trying to make an inplace function, so we don't need
> to assign outputs. Think of it as a C function with the
> form:
>
> void myFun(double * pIn, int* pSize);
>
> Making the inplace function return its input is really
> bad. So put in an "if (nlhs > 0) then error" line if you
> like.
>
> fun(a+b) works fine, but since a+b makes a temporary
> mxArray you can't access the result.
>
> As I mentioned before:
> a = b ;
> fun(a);
>
> will modify a and b, so the programmers discretion is
> required. But I think this thread started with someone
> wanting an inplace funtion because they couldn't hold two
> copies of the input in memory anyway, i.e.
>
> a = not_inplace_fun(b) generates an out of memory error
> anyway...
>
>
>
That's not my point. A mexFunction that modifies its input
is free to return (another) output, or not. The problem has
nothing to do with the outputs. so
a = b ;
x = fun (b) ;
is just as bad (or good) as
a = b ;
fun (b) ;
Your test for "if (nargin > 0) mexErrMsgTxt ( )." won't
really help (nor will it make anything worse), unless you
are also trying to do
b = fun(b)
for example (or if inside the mexFunction you try to return
your input, as in plhs[0] = prhs[0]).
My point is that modifying your inputs is dangerous. It's
not supported by The MathWorks. Future versions of MATLAB
would be free to crash in a most merrily manner if told to
modify the inputs of a mexFunctions; your code would break
and you can't complain to The MathWorks for breaking your code.
Having said all that ... if you get it to work - that's
fine. Just be aware that you are living outside the letter
of the law, so to speak, and have to be willing to see codes
die on you, if not now then maybe later on...
|
|
0
|
|
|
|
Reply
|
davis6756 (475)
|
3/10/2008 10:04:50 PM
|
|
"Andrew " <awbsmith@itee.uq.edu.au> wrote in message
<fr2642$ltq$1@fred.mathworks.com>...
> We're trying to make an inplace function, so we don't need
> to assign outputs. Think of it as a C function with the
> form:
>
> void myFun(double * pIn, int* pSize);
>
> Making the inplace function return its input is really
> bad. So put in an "if (nlhs > 0) then error" line if you
> like.
>
> fun(a+b) works fine, but since a+b makes a temporary
> mxArray you can't access the result.
>
> As I mentioned before:
> a = b ;
> fun(a);
>
> will modify a and b, so the programmers discretion is
> required. But I think this thread started with someone
> wanting an inplace funtion because they couldn't hold two
> copies of the input in memory anyway, i.e.
>
> a = not_inplace_fun(b) generates an out of memory error
> anyway...
>
>
>
That's not my point. A mexFunction that modifies its input
is free to return (another) output, or not. The problem has
nothing to do with the outputs. so
a = b ;
x = fun (b) ;
is just as bad (or good) as
a = b ;
fun (b) ;
Your test for "if (nargin > 0) mexErrMsgTxt ( )." won't
really help (nor will it make anything worse), unless you
are also trying to do
b = fun(b)
for example (or if inside the mexFunction you try to return
your input, as in plhs[0] = prhs[0]).
My point is that modifying your inputs is dangerous. It's
not supported by The MathWorks. Future versions of MATLAB
would be free to crash in a most merrily manner if told to
modify the inputs of a mexFunctions; your code would break
and you can't complain to The MathWorks for breaking your code.
Having said all that ... if you get it to work - that's
fine. Just be aware that you are living outside the letter
of the law, so to speak, and have to be willing to see codes
die on you, if not now then maybe later on...
|
|
0
|
|
|
|
Reply
|
davis6756 (475)
|
3/10/2008 10:04:50 PM
|
|
"Andrew " <awbsmith@itee.uq.edu.au> wrote in message
<fr2642$ltq$1@fred.mathworks.com>...
> We're trying to make an inplace function, so we don't need
> to assign outputs. Think of it as a C function with the
> form:
>
> void myFun(double * pIn, int* pSize);
>
> Making the inplace function return its input is really
> bad. So put in an "if (nlhs > 0) then error" line if you
> like.
>
> fun(a+b) works fine, but since a+b makes a temporary
> mxArray you can't access the result.
>
> As I mentioned before:
> a = b ;
> fun(a);
>
> will modify a and b, so the programmers discretion is
> required. But I think this thread started with someone
> wanting an inplace funtion because they couldn't hold two
> copies of the input in memory anyway, i.e.
>
> a = not_inplace_fun(b) generates an out of memory error
> anyway...
>
>
>
That's not my point. A mexFunction that modifies its input
is free to return (another) output, or not. The problem has
nothing to do with the outputs. so
a = b ;
x = fun (b) ;
is just as bad (or good) as
a = b ;
fun (b) ;
Your test for "if (nargin > 0) mexErrMsgTxt ( )." won't
really help (nor will it make anything worse), unless you
are also trying to do
b = fun(b)
for example (or if inside the mexFunction you try to return
your input, as in plhs[0] = prhs[0]).
My point is that modifying your inputs is dangerous. It's
not supported by The MathWorks. Future versions of MATLAB
would be free to crash in a most merrily manner if told to
modify the inputs of a mexFunctions; your code would break
and you can't complain to The MathWorks for breaking your code.
Having said all that ... if you get it to work - that's
fine. Just be aware that you are living outside the letter
of the law, so to speak, and have to be willing to see codes
die on you, if not now then maybe later on...
|
|
0
|
|
|
|
Reply
|
davis6756 (475)
|
3/10/2008 10:04:50 PM
|
|
"Andrew " <awbsmith@itee.uq.edu.au> wrote in message
<fr2642$ltq$1@fred.mathworks.com>...
> We're trying to make an inplace function, so we don't need
> to assign outputs. Think of it as a C function with the
> form:
>
> void myFun(double * pIn, int* pSize);
>
> Making the inplace function return its input is really
> bad. So put in an "if (nlhs > 0) then error" line if you
> like.
>
> fun(a+b) works fine, but since a+b makes a temporary
> mxArray you can't access the result.
>
> As I mentioned before:
> a = b ;
> fun(a);
>
> will modify a and b, so the programmers discretion is
> required. But I think this thread started with someone
> wanting an inplace funtion because they couldn't hold two
> copies of the input in memory anyway, i.e.
>
> a = not_inplace_fun(b) generates an out of memory error
> anyway...
>
>
>
That's not my point. A mexFunction that modifies its input
is free to return (another) output, or not. The problem has
nothing to do with the outputs. so
a = b ;
x = fun (b) ;
is just as bad (or good) as
a = b ;
fun (b) ;
Your test for "if (nargin > 0) mexErrMsgTxt ( )." won't
really help (nor will it make anything worse), unless you
are also trying to do
b = fun(b)
for example (or if inside the mexFunction you try to return
your input, as in plhs[0] = prhs[0]).
My point is that modifying your inputs is dangerous. It's
not supported by The MathWorks. Future versions of MATLAB
would be free to crash in a most merrily manner if told to
modify the inputs of a mexFunctions; your code would break
and you can't complain to The MathWorks for breaking your code.
Having said all that ... if you get it to work - that's
fine. Just be aware that you are living outside the letter
of the law, so to speak, and have to be willing to see codes
die on you, if not now then maybe later on...
|
|
0
|
|
|
|
Reply
|
davis6756 (475)
|
3/10/2008 10:04:50 PM
|
|
I learned about mex functions recently. It seems that mex
function input arguments can indeed be modified in place.
This is s simple mex function:
// begin of source code
#include "Mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const
mxArray *prhs[])
{
double *pElement = mxGetPr(prhs[0]);
for(unsigned int n = 0; n < mxGetNumberOfElements(prhs
[0]); n++)
{
pElement[n] = pElement[n] + 2;
};
plhs[0] = (mxArray*) prhs[0];
return;
}
// end of source code
In Matlab you can do things like these:
>> a = [1 2]
>> a =
[1 2]
>> a = MexInline(a)
>> a =
[3 4]
>> a = magic(3)
a =
8 1 6
3 5 7
4 9 2
>> a = 'Everything is fine.'
a =
Everything is fine.
Indeed everything has been fine until now. However, things
can get messy if you type something like this:
>> a = MexInplace(a + 1)
a =
4.0000 5.0000
Of course you are not going to use an inplace mex function
this way. For the statement a + 1 at least one temporary
variable must be created and you loose the advantages of
your in place function. Moreover, the memory for a + 1 is
released when the function returns and so is the memory of
a. Matlab can crash if you access a in any way.
But what if you have forgotten how MexInplace works or
someone else who isn't aware of the implementation of
MexInplace is trying to use this function? You can't catch
an expression like a + 1 inside the mex function. So you
should document your mex function very well and give it a
name that reminds the users of its effects.
|
|
0
|
|
|
|
Reply
|
OkinawaDolphin (61)
|
3/17/2008 12:24:07 PM
|
|
I learned about mex functions recently. It seems that mex
function input arguments can indeed be modified in place.
This is s simple mex function:
// begin of source code
#include "Mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const
mxArray *prhs[])
{
double *pElement = mxGetPr(prhs[0]);
for(unsigned int n = 0; n < mxGetNumberOfElements(prhs
[0]); n++)
{
pElement[n] = pElement[n] + 2;
};
plhs[0] = (mxArray*) prhs[0];
return;
}
// end of source code
In Matlab you can do things like these:
>> a = [1 2]
>> a =
[1 2]
>> a = MexInline(a)
>> a =
[3 4]
>> a = magic(3)
a =
8 1 6
3 5 7
4 9 2
>> a = 'Everything is fine.'
a =
Everything is fine.
Indeed everything has been fine until now. However, things
can get messy if you type something like this:
>> a = MexInplace(a + 1)
a =
4.0000 5.0000
Of course you are not going to use an inplace mex function
this way. For the statement a + 1 at least one temporary
variable must be created and you loose the advantages of
your in place function. Moreover, the memory for a + 1 is
released when the function returns and so is the memory of
a. Matlab can crash if you access a in any way.
But what if you have forgotten how MexInplace works or
someone else who isn't aware of the implementation of
MexInplace is trying to use this function? You can't catch
an expression like a + 1 inside the mex function. So you
should document your mex function very well and give it a
name that reminds the users of its effects.
|
|
0
|
|
|
|
Reply
|
OkinawaDolphin (61)
|
3/17/2008 12:26:04 PM
|
|
> Is there no way I could modify an argument in-place? If
that
> is not possible, the penalty would be huge. We are
talking
> about a matrix of several gigabytes size...
What if you make your variable global, and ask for it's
pointer from your mex file using mexGetArrayPtr ? (pass
only the name of the var in the mex)
That looks more safe, although still not supported.
Gergely Katona
|
|
0
|
|
|
|
Reply
|
asdasd15 (3)
|
4/3/2008 12:50:04 PM
|
|
"Gergely Katona" <asdasd15@freemail.hu> wrote in message
<ft2jps$8oq$1@fred.mathworks.com>...
>
> > Is there no way I could modify an argument in-place? If
> that
> > is not possible, the penalty would be huge. We are
> talking
> > about a matrix of several gigabytes size...
>
>
> What if you make your variable global, and ask for it's
> pointer from your mex file using mexGetArrayPtr ? (pass
> only the name of the var in the mex)
> That looks more safe, although still not supported.
> Gergely Katona
That doesn't make any difference.
This thread is dragging on far past its useful life.
The final word is, yes, you "can" modify your inputs, but
doing so can have indeterminate side effects. It is
unsupported. Do so only at your own peril. Modifying the
inputs to your mexFunction is very dangerous, but sometimes
useful. It is never safe. It should never be done in a
mexFunction that you intend for others to use.
|
|
0
|
|
|
|
Reply
|
davis6756 (475)
|
4/3/2008 6:18:02 PM
|
|
> What if you make your variable global, and ask for it's
> pointer from your mex file using mexGetArrayPtr ? (pass
> only the name of the var in the mex)
> That looks more safe, although still not supported.
> Gergely Katona
That doesn't work. Global Variables can't be accessed by
mex files, because they are unknown there.
|
|
0
|
|
|
|
Reply
|
OkinawaDolphin (61)
|
4/4/2008 11:25:04 AM
|
|
|
52 Replies
218 Views
(page loaded in 0.509 seconds)
Similiar Articles: Modifying MEX arguments in place? - comp.soft-sys.matlab ...For the MEX experts out there: I would like to factor a huge matrix (passed in as a one-dimensional array) in-place in a mex file. Unfortunately, the... MEX file cannot find entry point in 64-bit linux - comp.soft-sys ...I have written a mex file that compiles ... spelled correctly with the correct arguments. I'm at a loss to why this is happening. gfortran 4.4 and mex files on Linux - comp.soft-sys.matlab ...I have some fortran mex files that work beautifully ... I modified timestwo and renamed it timestwo.F90 ... glnxa64 -lmx -lmex -lmat -lm -lstdc++ > arguments ... Re: Compile #7 - comp.soft-sys.math.mathematica... to > the > local variable x; no immediate substitution in the first argument takes > place. ... Cross-compiler mex files on Windows 7 64 bit - comp.soft-sys ... MEX file ... Creating static libs to use in mex - comp.soft-sys.matlab ...... some library or it wasn't in its right place ... messages, logs or dumps ..... used modified gnumex to create .def and .lib files ... write,compile,link and run mex files ... matlab crashes (win 7 64 bit) without messages, logs or dumps ...... bit) without messages, logs or dumps while using mex ... a+2;// Check the number of inputs and output arguments if(n ... to create .def and .lib files > > mexopt.bat modified to ... comp.std.c++ - page 2Given the below, to sum all arguments passed, 1. What should be coded in place of the "/*What goes here*/" part? 2. How can I modify this to use std::plus [... Define a variable at a fixed address? - comp.compilers.lcc ...... moving this variable to its own separate file and then modifying the linker script to place it ... int ... list into a struct of which I pass the address ... as argument ... mexCallMATLAB : mxArray input and output problem - comp.soft-sys ...It is the first time that I use mex, but I have done some cpp and some matlab... ... int nrhs, mxArray ... calling the mexCallMATLAB function, the number of output arguments ... Compiling MCR C++ dll with VS2010 - comp.soft-sys.matlab ...Where do i have to place: namespace mat{ #include ... It does not seem to work when modifying only my main{}. ... CHAR16T #define CHAR16_T #endif #include "mex.h ... Help needed: read 3-dimensional array from a MAT-file in Fortran ...... named readinput.f90 like this: #include "mex.h ... explicit interfaces and can use ! assumed shape arguments. ... I modified them a bit. Can you take a look at them? Explanation needed for const int "error: variably modified ... at ...... but it is "const", i.e., read-only, in the sense that you're not allowed to modify ... http://www.cpax.org.uk> Email: -http://www. +rjh@ "Usenet is a strange place ... Use of MATLAB fftshift - comp.dspOne or more of the arguments to the function are array ... so that the unbiasing that needs to take place is ... of origin different than 1, you would have to modify the .mex ... read() error - Bad Address - comp.unix.programmer... and it's sockaddr_in structure are > passed > as arguments ... You're asking read to place data in the area pointed to ... What() is:bad allocation Error in mex file ... Undefined Function or Method - comp.soft-sys.matlabUndefined function or method 'times' for input arguments of type 'function_handle'. ... I just wanted to thank you both for the help; I was modifying an existing file and ... Modifying MEX arguments in place? - comp.soft-sys.matlab ...For the MEX experts out there: I would like to factor a huge matrix (passed in as a one-dimensional array) in-place in a mex file. Unfortunately, the... Modifying MEX arguments in place? - Newsreader - MATLAB CentralFor the MEX experts out there: I would like to factor a huge matrix (passed in as a one-dimensional array) in-place in a mex file. Unfortunately, the documentation ... 7/27/2012 8:00:27 PM
|