Clear Filters
Clear Filters

Multiply large matrix by scalar - speed issue

5 views (last 30 days)
Ok this probably doesn't have an answer, but I have a large-ish matrix (1024x1024) which I want to scale by a constant. I need to do this for two equal sized matrices. Unfortunately, when I do this using Matrix = Matrix*c and Matrix2 = Matrix2*c2, it takes 90% of the time of the entire rest of the code, (thereby slowing things to a crawl) which does several numeric integrations and calculations on vectors of size 1024 and the like. I was wondering if there's some other way to get this to go faster, though it seems doutful since the entirety of the code in question is Matrix=Matrix*c. Well any help is appreciated.

Accepted Answer

James Tursa
James Tursa on 19 Apr 2011
OK, here is a mex routine that does the exact calculation you have shown IN-PLACE, and it is bare bones without any argument checking. Translation: it is dangerous to use and will crash MATLAB if you do not pass it exactly what it wants. The idea is to try this out just to see how much difference it makes in your timing. If it is significant then we can fiddle with the safety issues. To compile it do the following:
Call the file multiply1024.c
Type the following at the MATLAB prompt:
mex -setup
(wait for the prompt, then press Enter)
(enter the number of a C compiler such as lcc)
(press Enter again)
mex multiply1024.c
Then replace this line:
W_array(1:1024,1:1024)=W_array(1:1024,1:1024)*(1/tau)
with this:
multiply1024(W_array,W_array,1/tau)
and replace this line:
gNMDA_W_array(1:1024,1:1024)=W_array(1:1024,1:1024)*pyr
with this:
multiply1024(gNMDA_W_array,W_array,pyr)
Report back on timing differences and we will go from there.
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
mwSize i, j, Cm, Am;
double *Cpr, *Apr, *Cpr0, *Apr0;
double b;
Cm = mxGetM(prhs[0]);
Am = mxGetM(prhs[1]);
b = mxGetScalar(prhs[2]);
Cpr = Cpr0 = mxGetPr(prhs[0]);
Apr = Apr0 = mxGetPr(prhs[1]);
for( j=0; j<1024; j++ ) {
Cpr = Cpr0 + j * Cm;
Apr = Apr0 + j * Am;
for( i=0; i<1024; i++ ) {
*Cpr++ = *Apr++ * b;
}
}
}
  10 Comments
James Tursa
James Tursa on 20 Apr 2011
Thanks, but I will again caution you that the above code has no argument checking and it requires that the 1st input is not shared with another non-temporary variable. I know that statement probably doesn't make much sense to you at this time, but it is an important restriction. If you plan on using it just let me know exactly the interface you need and I will post a mex function with some argument checks.
CP
CP on 20 Apr 2011
Well, as you guessed, I'm not sure what the restriction means to me so I will describe the use instead. W_array and gNMDA_W_array have the same use, in that they represent weights in a network with recursive connections. MxN matrix is the weight of node M on N (So W_array(1,2) is weight of 1 on 2, while W_array(2,1) is weight of 2 on 1).
Both arrays are initialized as MxN matrices of constants to start, with gNMDA_W_array being initialized as a scaled version of W_array.
The only lines of code that change the contents of the arrays are the two lines I posted above (which are now changed to use the mex function) as well as the following for W_array:
W_array:
Ne=1024;
for ii = TMP
W_array(ii,1:Ne)=W_array(ii,1:Ne).*(1-rate_dw)+(((n_bind-n_ubind)./(1+(abs(fired_vector-fired_vector(ii)))))+n_ubind).*(rate_dw);
end
I'm not sure if this answers your question about the 'interface' that I need, but basically the goal is just to simply scale a chunk of the array (e.g. one class of nodes scales connections to eachother over time but not to the other class of nodes, where their incoming and outgoing connections stay constant).

Sign in to comment.

More Answers (2)

Matt Fig
Matt Fig on 18 Apr 2011

James Tursa
James Tursa on 19 Apr 2011
MATLABs matrix * scalar is pretty fast and multi-threaded to boot. Unless you have complex numbers involved I don't think you will be able to speed this up, even with a mex routine. It is possible that Matrix and Matrix2 are shared and that is why the scalar multiplications are taking so long because it involves a data-copy and can't be done in-place. Can't tell without seeing more of your code.
  4 Comments
CP
CP on 19 Apr 2011
Both W_array and gNMDA_W_array are 1280x1280. If that's the case, it might be trivial to split off the arrays e.g. W_array1 having the 1024x1024 values multiplied and W_array2 having the remaining 256x256. Would that be about the same as using mex?
CP
CP on 19 Apr 2011
Though that might be tricky since I'd need to break W_array into 4 arrays and gNMDA_W_array into another 4. Then doing the math with them might be annoying or slow. I'll look into it.

Sign in to comment.

Categories

Find more on Write C Functions Callable from MATLAB (MEX Files) in Help Center and File Exchange

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!