void matrix_map_row(matrix_t* mat, const matrix_row_t* row, const offset_t i) { if( matrix_row( mat, i ) != NULL ) { //printf(" problem, sir" ); return; } // allocate space to copy the row size_t copy_size = (mat->num_mapped_rows+1)*sizeof(mapped_row_t); mat->mapped_rows = (mapped_row_t*)realloc( mat->mapped_rows, copy_size ); CHECK_ALLOC( mat->mapped_rows ); // setup the mapped row copy_size = sizeof(matrix_row_t); mapped_row_t* mapped_row = &(mat->mapped_rows[mat->num_mapped_rows]); mapped_row->i = i; memcpy( &(mapped_row->row), row, copy_size ); assert( row->num_cells >= 0 ); assert( row->num_cells <= mat->n ); // allocate space for the copied cells and copy them copy_size = row->num_cells * sizeof(cell_t); mapped_row->row.cells = (cell_t*)malloc( copy_size ); CHECK_ALLOC( mapped_row->row.cells ); memcpy( mapped_row->row.cells, row->cells, copy_size ); mat->num_mapped_rows++; assert( mat->num_mapped_rows <= mat->m - matrix_num_rows( mat ) ); }
double matrix_get(matrix* m, int row, int col) { ASSERT(0 <= row); ASSERT(row < matrix_num_rows(m)); ASSERT(0 <= col); ASSERT(col < matrix_num_cols(m)); return m->rows[row][col]; }
void matrix_smul(matrix* m, double x) { int i, j; for (i = 0; i < matrix_num_rows(m); i++) { for (j = 0; j < matrix_num_cols(m); j++) { m->rows[i][j] *= x; } } }
void matrix_set(matrix* m, int row, int col, double val) { ASSERT(0 <= row); ASSERT(row < matrix_num_rows(m)); ASSERT(0 <= col); ASSERT(col < matrix_num_cols(m)); m->rows[row][col] = val; }
matrix *matrix_mmul(matrix* m1, matrix* m2) { ASSERT(matrix_num_cols(m1) == matrix_num_rows(m2)); matrix* m = matrix_new(matrix_num_rows(m1), matrix_num_cols(m2)); int row, col, i; for (row = 0; row < matrix_num_rows(m); row++) { for (col = 0; col < matrix_num_cols(m); col++) { double sum = 0; for (i = 0; i < matrix_num_cols(m1); i++) { sum += matrix_get(m1, row, i) * matrix_get(m2, i, col); } matrix_set(m, row, col, sum); } } return m; }
void matrix_serialize( const matrix_t* mat, char** buf, offset_t* bufsize ) { *bufsize = sizeof(matrix_t) + matrix_num_rows(mat) * sizeof(matrix_row_t); // calculate buffer size offset_t i; for( i = mat->from_i; i <= mat->to_i; i++ ) { *bufsize += matrix_row(mat, i)->num_cells * sizeof(cell_t); } LOG(LOG_DEBUG, "serialize buffer size: %lu\n", *bufsize); *buf = (char*)malloc( *bufsize ); CHECK_ALLOC( *buf ); size_t offset = 0; size_t copy_size = 0; // copy matrix copy_size = sizeof(matrix_t); memcpy( *buf, mat, copy_size ); offset += copy_size; // copy rows copy_size = matrix_num_rows(mat) * sizeof(matrix_row_t); memcpy( *buf + offset, matrix_row(mat, mat->from_i), copy_size ); offset += copy_size; // copy cells of each row for( i = mat->from_i; i <= mat->to_i; i++ ) { matrix_row_t* row = matrix_row(mat, i); if(row->num_cells > 0) { LOG(LOG_DEBUG, "-->(%lu) has %lu\n", i, row->num_cells); copy_size = row->num_cells * sizeof(cell_t); memcpy( *buf + offset, row->cells, copy_size ); offset += copy_size; } } assert( offset == *bufsize ); }
void matrix_deserialize( matrix_t* mat, const char* buf ) { size_t offset = 0; size_t copy_size = 0; // copy matrix copy_size = sizeof(matrix_t); memcpy( mat, buf, copy_size ); offset += copy_size; // explicitly set this null to avoid problems. mat->num_mapped_rows = 0; mat->mapped_rows = NULL; LOG(LOG_DEBUG, "deserializing matrix... from_i=%lu, to_i=%lu. #=%lu\n", mat->from_i, mat->to_i, matrix_num_rows(mat) ); // copy rows copy_size = matrix_num_rows(mat) * sizeof(matrix_row_t); mat->rows = (matrix_row_t*)malloc( copy_size ); CHECK_ALLOC( mat->rows ); memset( mat->rows, 0, copy_size ); memcpy( matrix_row(mat, mat->from_i), buf + offset, copy_size ); offset += copy_size; LOG(LOG_DEBUG, "deserializing matrix... from_i=%lu, to_i=%lu\n", mat->from_i, mat->to_i ); // copy cells of each row offset_t i; for( i = mat->from_i; i <= mat->to_i; i++ ) { matrix_row_t* row = matrix_row(mat, i); assert( row != NULL ); assert( row->num_cells <= mat->n ); LOG(LOG_DEBUG, "(%lu) has %lu\n", i, row->num_cells); if( row->num_cells > 0 ) { copy_size = row->num_cells * sizeof(cell_t); row->cells = (cell_t*)malloc( copy_size ); CHECK_ALLOC( row->cells ); memcpy( row->cells, buf + offset, row->num_cells * sizeof(cell_t) ); offset += copy_size; } } }
// read sparse matrix // LIL representation: // http://en.wikipedia.org/wiki/Sparse_matrix#List_of_lists_.28LIL.29 void matrix_init( matrix_t* mat, const offset_t m, const offset_t n, const offset_t from_i, const offset_t to_i ) { mat->m = m; mat->n = n; mat->from_i = from_i; mat->to_i = (to_i >= m) ? m-1 : to_i; mat->num_mapped_rows = 0; mat->mapped_rows = NULL; assert( mat->from_i >= 0 ); assert( mat->to_i >= mat->from_i ); assert( mat->to_i < mat->m ); offset_t rows_size = matrix_num_rows(mat) * sizeof(matrix_row_t); mat->rows = (matrix_row_t*)malloc( rows_size ); LOG(LOG_DEBUG, "alloc %lu x %lu matrix. rows_size=%lu. from_i=%lu, to_i=%lu, # rows=%lu\n", m, n, rows_size, mat->from_i, mat->to_i, matrix_num_rows(mat)); CHECK_ALLOC( mat->rows ); memset( mat->rows, 0, rows_size ); }
void matrix_read(matrix_t* mat, const char* file, const offset_t m, const offset_t n, MPI_Comm comm, const boolean_t is_vec) { rank_t p, r; MPI_CALL( MPI_Comm_size(comm, &p) ); MPI_CALL( MPI_Comm_rank(comm, &r) ); if( r == 0 ) { matrix_t root_mat; const offset_t partition_size = floor( (double)m / (double)p ); LOG(LOG_IO, "matrix_read: m=%lu, p=%u, partition_size (m/p)=%lu\n", m, p, partition_size); FILE* input = fopen(file, "r"); size_t mem_size = 2*p*sizeof(MPI_Request); MPI_Request* request = (MPI_Request*)malloc( mem_size ); memset( request, 0, mem_size ); char** buf = (char**)malloc( p*sizeof(char*) ); rank_t to_r; for(to_r = 0; to_r < p; to_r++) { { // limit scope of from/to_i because matrix_init may change them. offset_t from_i = to_r * partition_size; offset_t to_i = (to_r+1) * partition_size - 1; // since we floor divisions, give the last processor the slack... if(to_r == p - 1) { //printf("last fix\n"); to_i = m - 1; } matrix_init( mat, m, n, from_i, to_i ); LOG(LOG_IO, "give partition of range [%lu, %lu] to r=%u, \n", mat->from_i, mat->to_i, to_r); matrix_read_rows( mat, input, is_vec ); // >= because the last row can be bigger. assert(matrix_num_rows( mat ) >= partition_size ); assert(matrix_num_rows( mat ) < 2*partition_size ); } if( to_r != 0 ) { offset_t bufsize; matrix_serialize( mat, &(buf[to_r]), &bufsize ); assert( buf[to_r] != NULL ); assert( bufsize > 0 ); MPI_CALL( MPI_Send(&bufsize, 1, MPI_OFFSET_T, to_r, 0, comm ) ); // , &request[to_r - 1] MPI_CALL( MPI_Isend(buf[to_r], bufsize, MPI_BYTE, to_r, 1, comm, &request[p + to_r - 2] ) ); // , matrix_free( mat ); } else { memcpy( &root_mat, mat, sizeof(matrix_t) ); } } LOG(LOG_IO, "waiting for distribution to complete...\n", 0); fclose( input ); //MPI_Waitall( 2*p - 2, request, MPI_STATUSES_IGNORE ); for(to_r = 1; to_r < p; to_r++) { //free(buf[to_r]); } //free(buf); //free(request); memcpy( mat, &root_mat, sizeof(matrix_t) ); LOG(LOG_IO, "matrix dist done.\n"); } else { char* buf; offset_t bufsize; MPI_Status stat; LOG(LOG_IO, "%u: waiting for parition size...\n", r ); MPI_CALL( MPI_Recv(&bufsize, 1, MPI_OFFSET_T, 0, 0, comm, &stat ) ); assert( bufsize >= 0 ); buf = (char*)malloc( bufsize ); CHECK_ALLOC( buf ); LOG(LOG_IO, "%u: waiting for parition buffer of size %lu...\n", r, bufsize ); MPI_CALL( MPI_Recv(buf, bufsize, MPI_BYTE, 0, 1, comm, &stat ) ); LOG(LOG_IO, "%u: got partiton buffer. about to deserialize.\n", r ); matrix_deserialize( mat, buf ); LOG(LOG_IO, "%u: got partiton buffer. partition is size=%lu...\n", r, matrix_num_rows( mat ) ); free( buf ); } //MPI_Barrier( comm ); }
void matrix_read_rows(matrix_t* mat, FILE* input, const boolean_t is_vec) { const char* sep = "(), \n"; offset_t line_num = 0; while( !feof( input ) ) { offset_t i, j, cell_val; fpos_t start_pos; char line[ 50 ]; fgetpos( input, &start_pos ); fgets( line, 50, input ); // HACK if(is_vec) { i = mat->from_i + line_num; j = 0; cell_val = atoi( line ); } else { char* tok = NULL; char* brk = NULL; offset_t num_toks = 0; for(tok = strtok_r(line, sep, &brk); tok; tok = strtok_r(NULL, sep, &brk), num_toks++ ) { value_t val = atoi( tok ); switch(num_toks) { case 0: i = val; break; case 1: j = val; break; case 2: cell_val = val; break; }; } if(num_toks < 2) { break; } if( j >= mat->n || j < 0 || i >= mat-> m || i < 0 ) { LOG(LOG_ERROR, "Out of bounds cell: (%lu, %lu).\n", i, j); CLEAN_EXIT(-1); } assert( i < mat->m ); assert( j < mat->n ); } if( i > mat->to_i ) { fsetpos( input, &start_pos ); break; } assert( i >= mat->from_i ); assert( i <= mat->to_i ); matrix_row_t* row = matrix_row(mat, i); assert( row != NULL ); size_t cells_size = sizeof(cell_t)*(row->num_cells + 1); row->cells = (cell_t*)realloc( row->cells, cells_size ); CHECK_ALLOC( row->cells ); cell_t* cell = &(row->cells[ row->num_cells ]); CHECK_ALLOC( cell ); cell->j = j; cell->val = cell_val; LOG(LOG_DEBUG, "read-->(%lu, %lu, %lu)\n", i, j, cell_val); row->num_cells++; line_num++; // this could go father and assert sparse-ness assert( row->num_cells <= mat->n ); // FIXME why is this failing? assert( line_num <= mat->from_i + mat->n * matrix_num_rows( mat ) ); } }