Sparse matrix multiplication
up vote
2
down vote
favorite
I am working on a sparse matrix application in C and I choose compressed sparse row (CSC) and compressed sparse column (CSC) as my data structure for it. But the difficult part is I cannot improve my matrix multiplication function.
/**
* The element and matrix are the naive format I have for sparse matrix,
* They are just for storing information got from after reading the file(s).
*/
typedef struct{
int row;
int column;
int id;
int value;
} element;
typedef struct{
int row;
int column;
int numberofElements;
element* elements;
} matrix;
/**
* CSR and CSC are compressed sparse row/column format to store sparse matrix
* The detailed definition is here:http://en.wikipedia.org/wiki/Sparse_matrix
*/
typedef struct{
int row;
int column;
int length;//The number of non-zero element in a matrix.
int* val;
int* col_ind;
int* row_ptr;
} CSR;
typedef struct{
int row;
int column;
int length;
int* val;
int* row_ind;
int* col_ptr;
} CSC;
typedef struct{
int val;
int index;
} tuple;
int compute(tuple* row, tuple* column, int row_length, int col_length){
int result = 0;
for(int i = 0; i < row_length; i++){
for(int j = 0; j < col_length; j++){
if(row[i].index == column[j].index){
result += row[i].val * column[j].val;
}
}
}
return result;
}
void multiply(matrix X, matrix Y, matrix* result){
CSR cX;
CSC cY;
int product = 0;
tuple **row = NULL, **column = NULL;
int *row_length,*col_length;
matrixtoCSR(&cX, X);
matrixtoCSC(&cY, Y);
row = (tuple **) malloc(X.row * sizeof(tuple *));
row_length = (int *) malloc (X.row * sizeof(int));
column = (tuple **) malloc(Y.column *sizeof(tuple *));
col_length = (int *) malloc (Y.column * sizeof (int ));
for(int r = 0; r < X.row; r++){
row_length[r] = (r == cX.row-1) ? cX.length - cX.row_ptr[r]:cX.row_ptr[r+1] - cX.row_ptr[r];
row[r] = !row_length[r] ? NULL : (tuple* ) malloc (row_length[r] * sizeof(tuple));
if(row[r] != NULL){
for(int i = 0; i < row_length[r]; i++){
row[r][i].val = cX.val[cX.row_ptr[r]+i];
row[r][i].index = cX.col_ind[cX.row_ptr[r]+i];
}
}
}
for(int c = 0; c < Y.column; c++){
col_length[c] = (c == cY.column-1) ? cY.length- cY.col_ptr[c]:cY.col_ptr[c+1] - cY.col_ptr[c];
column[c] = !col_length[c] ? NULL : (tuple *) malloc (col_length[c] * sizeof(tuple));
if(column != NULL){
for(int i = 0; i < col_length[c]; i++){
column[c][i].val = cY.val[cY.col_ptr[c]+i];
column[c][i].index = cY.row_ind[cY.col_ptr[c]+i];
}
}
}
for(int r = 0; r < X.row; r++){
for(int c = 0; c < Y.column; c++){
product = 0;
if(row[r] != NULL && column[c] != NULL)
product=compute(row[r], column[c], row_length[r], col_length[c]);
if(product){
result->elements[result->numberofElements].row = r;
result->elements[result->numberofElements].column = c;
result->elements[result->numberofElements].id = r * result->column + c;
result->elements[result->numberofElements].value = product;
result->numberofElements++;
}
}
}
result->elements = (element *)realloc( result->elements , result->numberofElements * sizeof(element));
for(int i = 0 ; i < X.row; i++){
if(row[i] != NULL)
free(row[i]);
}
free(row);
for(int i = 0 ; i < Y.column; i++){
if(column[i] != NULL)
free(column[i]);
}
free(column);
free(row_length);
free(col_length);
cleanCSR(&cX);
cleanCSC(&cY);
}
I used gprof to prof it and it shows that if I multiply 4 1000*1000 matrix the program will take about 7s to compute the output and 98.7% of time it is running this function.
How can I improve it? I have tried a lot of things like trade-off some space but the time just doesn't go down. I think I am kind of stuck.
optimization performance c matrix
add a comment |
up vote
2
down vote
favorite
I am working on a sparse matrix application in C and I choose compressed sparse row (CSC) and compressed sparse column (CSC) as my data structure for it. But the difficult part is I cannot improve my matrix multiplication function.
/**
* The element and matrix are the naive format I have for sparse matrix,
* They are just for storing information got from after reading the file(s).
*/
typedef struct{
int row;
int column;
int id;
int value;
} element;
typedef struct{
int row;
int column;
int numberofElements;
element* elements;
} matrix;
/**
* CSR and CSC are compressed sparse row/column format to store sparse matrix
* The detailed definition is here:http://en.wikipedia.org/wiki/Sparse_matrix
*/
typedef struct{
int row;
int column;
int length;//The number of non-zero element in a matrix.
int* val;
int* col_ind;
int* row_ptr;
} CSR;
typedef struct{
int row;
int column;
int length;
int* val;
int* row_ind;
int* col_ptr;
} CSC;
typedef struct{
int val;
int index;
} tuple;
int compute(tuple* row, tuple* column, int row_length, int col_length){
int result = 0;
for(int i = 0; i < row_length; i++){
for(int j = 0; j < col_length; j++){
if(row[i].index == column[j].index){
result += row[i].val * column[j].val;
}
}
}
return result;
}
void multiply(matrix X, matrix Y, matrix* result){
CSR cX;
CSC cY;
int product = 0;
tuple **row = NULL, **column = NULL;
int *row_length,*col_length;
matrixtoCSR(&cX, X);
matrixtoCSC(&cY, Y);
row = (tuple **) malloc(X.row * sizeof(tuple *));
row_length = (int *) malloc (X.row * sizeof(int));
column = (tuple **) malloc(Y.column *sizeof(tuple *));
col_length = (int *) malloc (Y.column * sizeof (int ));
for(int r = 0; r < X.row; r++){
row_length[r] = (r == cX.row-1) ? cX.length - cX.row_ptr[r]:cX.row_ptr[r+1] - cX.row_ptr[r];
row[r] = !row_length[r] ? NULL : (tuple* ) malloc (row_length[r] * sizeof(tuple));
if(row[r] != NULL){
for(int i = 0; i < row_length[r]; i++){
row[r][i].val = cX.val[cX.row_ptr[r]+i];
row[r][i].index = cX.col_ind[cX.row_ptr[r]+i];
}
}
}
for(int c = 0; c < Y.column; c++){
col_length[c] = (c == cY.column-1) ? cY.length- cY.col_ptr[c]:cY.col_ptr[c+1] - cY.col_ptr[c];
column[c] = !col_length[c] ? NULL : (tuple *) malloc (col_length[c] * sizeof(tuple));
if(column != NULL){
for(int i = 0; i < col_length[c]; i++){
column[c][i].val = cY.val[cY.col_ptr[c]+i];
column[c][i].index = cY.row_ind[cY.col_ptr[c]+i];
}
}
}
for(int r = 0; r < X.row; r++){
for(int c = 0; c < Y.column; c++){
product = 0;
if(row[r] != NULL && column[c] != NULL)
product=compute(row[r], column[c], row_length[r], col_length[c]);
if(product){
result->elements[result->numberofElements].row = r;
result->elements[result->numberofElements].column = c;
result->elements[result->numberofElements].id = r * result->column + c;
result->elements[result->numberofElements].value = product;
result->numberofElements++;
}
}
}
result->elements = (element *)realloc( result->elements , result->numberofElements * sizeof(element));
for(int i = 0 ; i < X.row; i++){
if(row[i] != NULL)
free(row[i]);
}
free(row);
for(int i = 0 ; i < Y.column; i++){
if(column[i] != NULL)
free(column[i]);
}
free(column);
free(row_length);
free(col_length);
cleanCSR(&cX);
cleanCSC(&cY);
}
I used gprof to prof it and it shows that if I multiply 4 1000*1000 matrix the program will take about 7s to compute the output and 98.7% of time it is running this function.
How can I improve it? I have tried a lot of things like trade-off some space but the time just doesn't go down. I think I am kind of stuck.
optimization performance c matrix
Well you could make sure the indentation is consistent so people can read it.
– Martin York
Jan 3 '13 at 19:16
2
please post the struct and type definitions too - I wont review it unless I can compile it.
– William Morris
Jan 3 '13 at 21:58
Hi, I have updated it. would u please have a look at it now? Thanks.
– dorafmon
Jan 4 '13 at 10:54
Yourtupletype andmatrixtoCSRandmatrixtoCSCare still missing. Also please post amain()with a simple test case. BTW why do you use a CSC and a CSR?
– William Morris
Jan 6 '13 at 18:16
@WilliamMorris Hi I have updated it with the def of tuple but sorry I cannot provide a test case because the main method reads some files of certain form and then call the multiply function. It will be too many lines to paste here. If you want I can send a email to you withe all the source files and test files. The reason why I use CSC and CSR is that I read the sparse matrix entry in wikipedia and I think it is a good idea to store the matrix in this form since it is fast for row/column slicing.
– dorafmon
Jan 6 '13 at 18:22
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I am working on a sparse matrix application in C and I choose compressed sparse row (CSC) and compressed sparse column (CSC) as my data structure for it. But the difficult part is I cannot improve my matrix multiplication function.
/**
* The element and matrix are the naive format I have for sparse matrix,
* They are just for storing information got from after reading the file(s).
*/
typedef struct{
int row;
int column;
int id;
int value;
} element;
typedef struct{
int row;
int column;
int numberofElements;
element* elements;
} matrix;
/**
* CSR and CSC are compressed sparse row/column format to store sparse matrix
* The detailed definition is here:http://en.wikipedia.org/wiki/Sparse_matrix
*/
typedef struct{
int row;
int column;
int length;//The number of non-zero element in a matrix.
int* val;
int* col_ind;
int* row_ptr;
} CSR;
typedef struct{
int row;
int column;
int length;
int* val;
int* row_ind;
int* col_ptr;
} CSC;
typedef struct{
int val;
int index;
} tuple;
int compute(tuple* row, tuple* column, int row_length, int col_length){
int result = 0;
for(int i = 0; i < row_length; i++){
for(int j = 0; j < col_length; j++){
if(row[i].index == column[j].index){
result += row[i].val * column[j].val;
}
}
}
return result;
}
void multiply(matrix X, matrix Y, matrix* result){
CSR cX;
CSC cY;
int product = 0;
tuple **row = NULL, **column = NULL;
int *row_length,*col_length;
matrixtoCSR(&cX, X);
matrixtoCSC(&cY, Y);
row = (tuple **) malloc(X.row * sizeof(tuple *));
row_length = (int *) malloc (X.row * sizeof(int));
column = (tuple **) malloc(Y.column *sizeof(tuple *));
col_length = (int *) malloc (Y.column * sizeof (int ));
for(int r = 0; r < X.row; r++){
row_length[r] = (r == cX.row-1) ? cX.length - cX.row_ptr[r]:cX.row_ptr[r+1] - cX.row_ptr[r];
row[r] = !row_length[r] ? NULL : (tuple* ) malloc (row_length[r] * sizeof(tuple));
if(row[r] != NULL){
for(int i = 0; i < row_length[r]; i++){
row[r][i].val = cX.val[cX.row_ptr[r]+i];
row[r][i].index = cX.col_ind[cX.row_ptr[r]+i];
}
}
}
for(int c = 0; c < Y.column; c++){
col_length[c] = (c == cY.column-1) ? cY.length- cY.col_ptr[c]:cY.col_ptr[c+1] - cY.col_ptr[c];
column[c] = !col_length[c] ? NULL : (tuple *) malloc (col_length[c] * sizeof(tuple));
if(column != NULL){
for(int i = 0; i < col_length[c]; i++){
column[c][i].val = cY.val[cY.col_ptr[c]+i];
column[c][i].index = cY.row_ind[cY.col_ptr[c]+i];
}
}
}
for(int r = 0; r < X.row; r++){
for(int c = 0; c < Y.column; c++){
product = 0;
if(row[r] != NULL && column[c] != NULL)
product=compute(row[r], column[c], row_length[r], col_length[c]);
if(product){
result->elements[result->numberofElements].row = r;
result->elements[result->numberofElements].column = c;
result->elements[result->numberofElements].id = r * result->column + c;
result->elements[result->numberofElements].value = product;
result->numberofElements++;
}
}
}
result->elements = (element *)realloc( result->elements , result->numberofElements * sizeof(element));
for(int i = 0 ; i < X.row; i++){
if(row[i] != NULL)
free(row[i]);
}
free(row);
for(int i = 0 ; i < Y.column; i++){
if(column[i] != NULL)
free(column[i]);
}
free(column);
free(row_length);
free(col_length);
cleanCSR(&cX);
cleanCSC(&cY);
}
I used gprof to prof it and it shows that if I multiply 4 1000*1000 matrix the program will take about 7s to compute the output and 98.7% of time it is running this function.
How can I improve it? I have tried a lot of things like trade-off some space but the time just doesn't go down. I think I am kind of stuck.
optimization performance c matrix
I am working on a sparse matrix application in C and I choose compressed sparse row (CSC) and compressed sparse column (CSC) as my data structure for it. But the difficult part is I cannot improve my matrix multiplication function.
/**
* The element and matrix are the naive format I have for sparse matrix,
* They are just for storing information got from after reading the file(s).
*/
typedef struct{
int row;
int column;
int id;
int value;
} element;
typedef struct{
int row;
int column;
int numberofElements;
element* elements;
} matrix;
/**
* CSR and CSC are compressed sparse row/column format to store sparse matrix
* The detailed definition is here:http://en.wikipedia.org/wiki/Sparse_matrix
*/
typedef struct{
int row;
int column;
int length;//The number of non-zero element in a matrix.
int* val;
int* col_ind;
int* row_ptr;
} CSR;
typedef struct{
int row;
int column;
int length;
int* val;
int* row_ind;
int* col_ptr;
} CSC;
typedef struct{
int val;
int index;
} tuple;
int compute(tuple* row, tuple* column, int row_length, int col_length){
int result = 0;
for(int i = 0; i < row_length; i++){
for(int j = 0; j < col_length; j++){
if(row[i].index == column[j].index){
result += row[i].val * column[j].val;
}
}
}
return result;
}
void multiply(matrix X, matrix Y, matrix* result){
CSR cX;
CSC cY;
int product = 0;
tuple **row = NULL, **column = NULL;
int *row_length,*col_length;
matrixtoCSR(&cX, X);
matrixtoCSC(&cY, Y);
row = (tuple **) malloc(X.row * sizeof(tuple *));
row_length = (int *) malloc (X.row * sizeof(int));
column = (tuple **) malloc(Y.column *sizeof(tuple *));
col_length = (int *) malloc (Y.column * sizeof (int ));
for(int r = 0; r < X.row; r++){
row_length[r] = (r == cX.row-1) ? cX.length - cX.row_ptr[r]:cX.row_ptr[r+1] - cX.row_ptr[r];
row[r] = !row_length[r] ? NULL : (tuple* ) malloc (row_length[r] * sizeof(tuple));
if(row[r] != NULL){
for(int i = 0; i < row_length[r]; i++){
row[r][i].val = cX.val[cX.row_ptr[r]+i];
row[r][i].index = cX.col_ind[cX.row_ptr[r]+i];
}
}
}
for(int c = 0; c < Y.column; c++){
col_length[c] = (c == cY.column-1) ? cY.length- cY.col_ptr[c]:cY.col_ptr[c+1] - cY.col_ptr[c];
column[c] = !col_length[c] ? NULL : (tuple *) malloc (col_length[c] * sizeof(tuple));
if(column != NULL){
for(int i = 0; i < col_length[c]; i++){
column[c][i].val = cY.val[cY.col_ptr[c]+i];
column[c][i].index = cY.row_ind[cY.col_ptr[c]+i];
}
}
}
for(int r = 0; r < X.row; r++){
for(int c = 0; c < Y.column; c++){
product = 0;
if(row[r] != NULL && column[c] != NULL)
product=compute(row[r], column[c], row_length[r], col_length[c]);
if(product){
result->elements[result->numberofElements].row = r;
result->elements[result->numberofElements].column = c;
result->elements[result->numberofElements].id = r * result->column + c;
result->elements[result->numberofElements].value = product;
result->numberofElements++;
}
}
}
result->elements = (element *)realloc( result->elements , result->numberofElements * sizeof(element));
for(int i = 0 ; i < X.row; i++){
if(row[i] != NULL)
free(row[i]);
}
free(row);
for(int i = 0 ; i < Y.column; i++){
if(column[i] != NULL)
free(column[i]);
}
free(column);
free(row_length);
free(col_length);
cleanCSR(&cX);
cleanCSC(&cY);
}
I used gprof to prof it and it shows that if I multiply 4 1000*1000 matrix the program will take about 7s to compute the output and 98.7% of time it is running this function.
How can I improve it? I have tried a lot of things like trade-off some space but the time just doesn't go down. I think I am kind of stuck.
optimization performance c matrix
optimization performance c matrix
edited Jan 26 '15 at 4:50
200_success
127k15148412
127k15148412
asked Jan 3 '13 at 14:22
dorafmon
1588
1588
Well you could make sure the indentation is consistent so people can read it.
– Martin York
Jan 3 '13 at 19:16
2
please post the struct and type definitions too - I wont review it unless I can compile it.
– William Morris
Jan 3 '13 at 21:58
Hi, I have updated it. would u please have a look at it now? Thanks.
– dorafmon
Jan 4 '13 at 10:54
Yourtupletype andmatrixtoCSRandmatrixtoCSCare still missing. Also please post amain()with a simple test case. BTW why do you use a CSC and a CSR?
– William Morris
Jan 6 '13 at 18:16
@WilliamMorris Hi I have updated it with the def of tuple but sorry I cannot provide a test case because the main method reads some files of certain form and then call the multiply function. It will be too many lines to paste here. If you want I can send a email to you withe all the source files and test files. The reason why I use CSC and CSR is that I read the sparse matrix entry in wikipedia and I think it is a good idea to store the matrix in this form since it is fast for row/column slicing.
– dorafmon
Jan 6 '13 at 18:22
add a comment |
Well you could make sure the indentation is consistent so people can read it.
– Martin York
Jan 3 '13 at 19:16
2
please post the struct and type definitions too - I wont review it unless I can compile it.
– William Morris
Jan 3 '13 at 21:58
Hi, I have updated it. would u please have a look at it now? Thanks.
– dorafmon
Jan 4 '13 at 10:54
Yourtupletype andmatrixtoCSRandmatrixtoCSCare still missing. Also please post amain()with a simple test case. BTW why do you use a CSC and a CSR?
– William Morris
Jan 6 '13 at 18:16
@WilliamMorris Hi I have updated it with the def of tuple but sorry I cannot provide a test case because the main method reads some files of certain form and then call the multiply function. It will be too many lines to paste here. If you want I can send a email to you withe all the source files and test files. The reason why I use CSC and CSR is that I read the sparse matrix entry in wikipedia and I think it is a good idea to store the matrix in this form since it is fast for row/column slicing.
– dorafmon
Jan 6 '13 at 18:22
Well you could make sure the indentation is consistent so people can read it.
– Martin York
Jan 3 '13 at 19:16
Well you could make sure the indentation is consistent so people can read it.
– Martin York
Jan 3 '13 at 19:16
2
2
please post the struct and type definitions too - I wont review it unless I can compile it.
– William Morris
Jan 3 '13 at 21:58
please post the struct and type definitions too - I wont review it unless I can compile it.
– William Morris
Jan 3 '13 at 21:58
Hi, I have updated it. would u please have a look at it now? Thanks.
– dorafmon
Jan 4 '13 at 10:54
Hi, I have updated it. would u please have a look at it now? Thanks.
– dorafmon
Jan 4 '13 at 10:54
Your
tuple type and matrixtoCSR and matrixtoCSC are still missing. Also please post a main() with a simple test case. BTW why do you use a CSC and a CSR?– William Morris
Jan 6 '13 at 18:16
Your
tuple type and matrixtoCSR and matrixtoCSC are still missing. Also please post a main() with a simple test case. BTW why do you use a CSC and a CSR?– William Morris
Jan 6 '13 at 18:16
@WilliamMorris Hi I have updated it with the def of tuple but sorry I cannot provide a test case because the main method reads some files of certain form and then call the multiply function. It will be too many lines to paste here. If you want I can send a email to you withe all the source files and test files. The reason why I use CSC and CSR is that I read the sparse matrix entry in wikipedia and I think it is a good idea to store the matrix in this form since it is fast for row/column slicing.
– dorafmon
Jan 6 '13 at 18:22
@WilliamMorris Hi I have updated it with the def of tuple but sorry I cannot provide a test case because the main method reads some files of certain form and then call the multiply function. It will be too many lines to paste here. If you want I can send a email to you withe all the source files and test files. The reason why I use CSC and CSR is that I read the sparse matrix entry in wikipedia and I think it is a good idea to store the matrix in this form since it is fast for row/column slicing.
– dorafmon
Jan 6 '13 at 18:22
add a comment |
1 Answer
1
active
oldest
votes
up vote
3
down vote
Here is my understanding of what you are doing:
- you have some matrices stored in files using your own 'naive' format.
- you read these into your
matrixstructures - two of these matrices are then passed to
multiply()
- you convert one of the matrices into a Compressed Row Storage
- and the other into a Compressed Column Storage
- you then extract the matrices from these compressed forms into arrays of
values, one for rows and one for columns - and finally you multiply them.
I find that complicated!
- Why not store the matrices directly in compressed format?
- Or convert your naive format into the extracted form without the CSC/CSR stage?
- Why use both CSR and CSC? They are both methods of compressing a matrix but
they do the same job. I can see no point in using both.
With these defects, there is not much point in reviewing the code in detail,
but here are some general points:
- include the right headers and don't cast the return from
malloc
know that
callocgives you a zeroed arrayuse
constwhere possible on function parameters (eg row/column in
compute, X/Y inmultiply)use
staticwhere possible for functionscomputeandmultiplyare badly namedimprove your naming in general. You have four structures all containing
fields namedrowandcolumn. I'm sure at least two of these contain the
number of rows/columns (eg.n_rows). And yourtuplelists are
calledrowandcolumn. It all becomes very confusing.pass by reference is better for structures.
your
multiplydoes a lot more than just multiply the matrices. It first
compresses the input matrices and then expands the compressed matrices.
These steps belong elsewhere (if they belong anywhere). Your first two big
for-loops shoud be separate functions. The nested-for in each might well
belong in a separate function too (difficult to tell, but nested loops are
often better split). And the free-loops should also be separate functions. By splitting a big function into several smaller ones (with appropriate names), you make the code easier to read and test.
Sorry to be negative.
1
Thanks. I will try to follow your advice and modify my code. Thanks indeed.
– dorafmon
Jan 6 '13 at 20:29
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
Here is my understanding of what you are doing:
- you have some matrices stored in files using your own 'naive' format.
- you read these into your
matrixstructures - two of these matrices are then passed to
multiply()
- you convert one of the matrices into a Compressed Row Storage
- and the other into a Compressed Column Storage
- you then extract the matrices from these compressed forms into arrays of
values, one for rows and one for columns - and finally you multiply them.
I find that complicated!
- Why not store the matrices directly in compressed format?
- Or convert your naive format into the extracted form without the CSC/CSR stage?
- Why use both CSR and CSC? They are both methods of compressing a matrix but
they do the same job. I can see no point in using both.
With these defects, there is not much point in reviewing the code in detail,
but here are some general points:
- include the right headers and don't cast the return from
malloc
know that
callocgives you a zeroed arrayuse
constwhere possible on function parameters (eg row/column in
compute, X/Y inmultiply)use
staticwhere possible for functionscomputeandmultiplyare badly namedimprove your naming in general. You have four structures all containing
fields namedrowandcolumn. I'm sure at least two of these contain the
number of rows/columns (eg.n_rows). And yourtuplelists are
calledrowandcolumn. It all becomes very confusing.pass by reference is better for structures.
your
multiplydoes a lot more than just multiply the matrices. It first
compresses the input matrices and then expands the compressed matrices.
These steps belong elsewhere (if they belong anywhere). Your first two big
for-loops shoud be separate functions. The nested-for in each might well
belong in a separate function too (difficult to tell, but nested loops are
often better split). And the free-loops should also be separate functions. By splitting a big function into several smaller ones (with appropriate names), you make the code easier to read and test.
Sorry to be negative.
1
Thanks. I will try to follow your advice and modify my code. Thanks indeed.
– dorafmon
Jan 6 '13 at 20:29
add a comment |
up vote
3
down vote
Here is my understanding of what you are doing:
- you have some matrices stored in files using your own 'naive' format.
- you read these into your
matrixstructures - two of these matrices are then passed to
multiply()
- you convert one of the matrices into a Compressed Row Storage
- and the other into a Compressed Column Storage
- you then extract the matrices from these compressed forms into arrays of
values, one for rows and one for columns - and finally you multiply them.
I find that complicated!
- Why not store the matrices directly in compressed format?
- Or convert your naive format into the extracted form without the CSC/CSR stage?
- Why use both CSR and CSC? They are both methods of compressing a matrix but
they do the same job. I can see no point in using both.
With these defects, there is not much point in reviewing the code in detail,
but here are some general points:
- include the right headers and don't cast the return from
malloc
know that
callocgives you a zeroed arrayuse
constwhere possible on function parameters (eg row/column in
compute, X/Y inmultiply)use
staticwhere possible for functionscomputeandmultiplyare badly namedimprove your naming in general. You have four structures all containing
fields namedrowandcolumn. I'm sure at least two of these contain the
number of rows/columns (eg.n_rows). And yourtuplelists are
calledrowandcolumn. It all becomes very confusing.pass by reference is better for structures.
your
multiplydoes a lot more than just multiply the matrices. It first
compresses the input matrices and then expands the compressed matrices.
These steps belong elsewhere (if they belong anywhere). Your first two big
for-loops shoud be separate functions. The nested-for in each might well
belong in a separate function too (difficult to tell, but nested loops are
often better split). And the free-loops should also be separate functions. By splitting a big function into several smaller ones (with appropriate names), you make the code easier to read and test.
Sorry to be negative.
1
Thanks. I will try to follow your advice and modify my code. Thanks indeed.
– dorafmon
Jan 6 '13 at 20:29
add a comment |
up vote
3
down vote
up vote
3
down vote
Here is my understanding of what you are doing:
- you have some matrices stored in files using your own 'naive' format.
- you read these into your
matrixstructures - two of these matrices are then passed to
multiply()
- you convert one of the matrices into a Compressed Row Storage
- and the other into a Compressed Column Storage
- you then extract the matrices from these compressed forms into arrays of
values, one for rows and one for columns - and finally you multiply them.
I find that complicated!
- Why not store the matrices directly in compressed format?
- Or convert your naive format into the extracted form without the CSC/CSR stage?
- Why use both CSR and CSC? They are both methods of compressing a matrix but
they do the same job. I can see no point in using both.
With these defects, there is not much point in reviewing the code in detail,
but here are some general points:
- include the right headers and don't cast the return from
malloc
know that
callocgives you a zeroed arrayuse
constwhere possible on function parameters (eg row/column in
compute, X/Y inmultiply)use
staticwhere possible for functionscomputeandmultiplyare badly namedimprove your naming in general. You have four structures all containing
fields namedrowandcolumn. I'm sure at least two of these contain the
number of rows/columns (eg.n_rows). And yourtuplelists are
calledrowandcolumn. It all becomes very confusing.pass by reference is better for structures.
your
multiplydoes a lot more than just multiply the matrices. It first
compresses the input matrices and then expands the compressed matrices.
These steps belong elsewhere (if they belong anywhere). Your first two big
for-loops shoud be separate functions. The nested-for in each might well
belong in a separate function too (difficult to tell, but nested loops are
often better split). And the free-loops should also be separate functions. By splitting a big function into several smaller ones (with appropriate names), you make the code easier to read and test.
Sorry to be negative.
Here is my understanding of what you are doing:
- you have some matrices stored in files using your own 'naive' format.
- you read these into your
matrixstructures - two of these matrices are then passed to
multiply()
- you convert one of the matrices into a Compressed Row Storage
- and the other into a Compressed Column Storage
- you then extract the matrices from these compressed forms into arrays of
values, one for rows and one for columns - and finally you multiply them.
I find that complicated!
- Why not store the matrices directly in compressed format?
- Or convert your naive format into the extracted form without the CSC/CSR stage?
- Why use both CSR and CSC? They are both methods of compressing a matrix but
they do the same job. I can see no point in using both.
With these defects, there is not much point in reviewing the code in detail,
but here are some general points:
- include the right headers and don't cast the return from
malloc
know that
callocgives you a zeroed arrayuse
constwhere possible on function parameters (eg row/column in
compute, X/Y inmultiply)use
staticwhere possible for functionscomputeandmultiplyare badly namedimprove your naming in general. You have four structures all containing
fields namedrowandcolumn. I'm sure at least two of these contain the
number of rows/columns (eg.n_rows). And yourtuplelists are
calledrowandcolumn. It all becomes very confusing.pass by reference is better for structures.
your
multiplydoes a lot more than just multiply the matrices. It first
compresses the input matrices and then expands the compressed matrices.
These steps belong elsewhere (if they belong anywhere). Your first two big
for-loops shoud be separate functions. The nested-for in each might well
belong in a separate function too (difficult to tell, but nested loops are
often better split). And the free-loops should also be separate functions. By splitting a big function into several smaller ones (with appropriate names), you make the code easier to read and test.
Sorry to be negative.
answered Jan 6 '13 at 20:02
William Morris
8,7671241
8,7671241
1
Thanks. I will try to follow your advice and modify my code. Thanks indeed.
– dorafmon
Jan 6 '13 at 20:29
add a comment |
1
Thanks. I will try to follow your advice and modify my code. Thanks indeed.
– dorafmon
Jan 6 '13 at 20:29
1
1
Thanks. I will try to follow your advice and modify my code. Thanks indeed.
– dorafmon
Jan 6 '13 at 20:29
Thanks. I will try to follow your advice and modify my code. Thanks indeed.
– dorafmon
Jan 6 '13 at 20:29
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f20124%2fsparse-matrix-multiplication%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Well you could make sure the indentation is consistent so people can read it.
– Martin York
Jan 3 '13 at 19:16
2
please post the struct and type definitions too - I wont review it unless I can compile it.
– William Morris
Jan 3 '13 at 21:58
Hi, I have updated it. would u please have a look at it now? Thanks.
– dorafmon
Jan 4 '13 at 10:54
Your
tupletype andmatrixtoCSRandmatrixtoCSCare still missing. Also please post amain()with a simple test case. BTW why do you use a CSC and a CSR?– William Morris
Jan 6 '13 at 18:16
@WilliamMorris Hi I have updated it with the def of tuple but sorry I cannot provide a test case because the main method reads some files of certain form and then call the multiply function. It will be too many lines to paste here. If you want I can send a email to you withe all the source files and test files. The reason why I use CSC and CSR is that I read the sparse matrix entry in wikipedia and I think it is a good idea to store the matrix in this form since it is fast for row/column slicing.
– dorafmon
Jan 6 '13 at 18:22