Borrar filtros
Borrar filtros

Multiply large matrix by scalar - speed issue

5 visualizaciones (últimos 30 días)
CP
CP el 18 de Abr. de 2011
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.

Respuesta aceptada

James Tursa
James Tursa el 19 de Abr. de 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 comentarios
James Tursa
James Tursa el 20 de Abr. de 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 el 20 de Abr. de 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).

Iniciar sesión para comentar.

Más respuestas (2)

Matt Fig
Matt Fig el 18 de Abr. de 2011

James Tursa
James Tursa el 19 de Abr. de 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 comentarios
CP
CP el 19 de Abr. de 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 el 19 de Abr. de 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.

Iniciar sesión para comentar.

Categorías

Más información sobre Write C Functions Callable from MATLAB (MEX Files) en Help Center y File Exchange.

Etiquetas

Community Treasure Hunt

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

Start Hunting!

Translated by