Browse Source

Implement transition matrix pruning, Fix sparse matrices sizes, Fix output

master
Apostolos Fanakis 6 years ago
parent
commit
694f53cc0f
No known key found for this signature in database GPG Key ID: 56CE2DEDE9F1FB78
  1. 4
      serial/coo_sparse_matrix.c
  2. 14
      serial/csr_sparse_matrix.c
  3. 4
      serial/csr_sparse_matrix.h
  4. 43
      serial/serial_gs_pagerank.c
  5. 78
      serial/serial_gs_pagerank_functions.c
  6. 4
      serial/serial_gs_pagerank_functions.h

4
serial/coo_sparse_matrix.c

@ -49,7 +49,7 @@ void transposeSparseMatrix(CooSparseMatrix *sparseMatrix) {
void transformToCSR(CooSparseMatrix initialSparseMatrix, void transformToCSR(CooSparseMatrix initialSparseMatrix,
CsrSparseMatrix *transformedSparseMatrix) { CsrSparseMatrix *transformedSparseMatrix) {
// Checks if the sizes of the two matrices fit // Checks if the sizes of the two matrices fit
if (initialSparseMatrix.numberOfNonZeroElements > transformedSparseMatrix->size) { if (initialSparseMatrix.numberOfNonZeroElements > transformedSparseMatrix->numberOfElements) {
printf("Transformed CSR matrix does not have enough space!\n"); printf("Transformed CSR matrix does not have enough space!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -85,8 +85,6 @@ void transformToCSR(CooSparseMatrix initialSparseMatrix,
transformedSparseMatrix->rowCumulativeIndexes[i] = last; transformedSparseMatrix->rowCumulativeIndexes[i] = last;
last = temp; last = temp;
} }
transformedSparseMatrix->numberOfNonZeroElements = initialSparseMatrix.numberOfNonZeroElements;
} }
void cooSparseMatrixVectorMultiplication(CooSparseMatrix sparseMatrix, void cooSparseMatrixVectorMultiplication(CooSparseMatrix sparseMatrix,

14
serial/csr_sparse_matrix.c

@ -3,7 +3,7 @@
CsrSparseMatrix initCsrSparseMatrix() { CsrSparseMatrix initCsrSparseMatrix() {
CsrSparseMatrix sparseMatrix; CsrSparseMatrix sparseMatrix;
sparseMatrix.size = 0; sparseMatrix.size = 0;
sparseMatrix.numberOfNonZeroElements = 0; sparseMatrix.numberOfElements = 0;
sparseMatrix.values = NULL; sparseMatrix.values = NULL;
sparseMatrix.columnIndexes = NULL; sparseMatrix.columnIndexes = NULL;
@ -11,17 +11,19 @@ CsrSparseMatrix initCsrSparseMatrix() {
return sparseMatrix; return sparseMatrix;
} }
void allocMemoryForCsr(CsrSparseMatrix *sparseMatrix, int numberOfElements) { void allocMemoryForCsr(CsrSparseMatrix *sparseMatrix, int size, int numberOfElements) {
sparseMatrix->values = (double *) malloc(numberOfElements * sizeof(double)); sparseMatrix->values = (double *) malloc(numberOfElements * sizeof(double));
sparseMatrix->columnIndexes = (int *) malloc( sparseMatrix->columnIndexes = (int *) malloc(
numberOfElements * sizeof(int)); numberOfElements * sizeof(int));
sparseMatrix->rowCumulativeIndexes = (int *) malloc( sparseMatrix->rowCumulativeIndexes = (int *) malloc(
(numberOfElements + 1) * sizeof(int)); (size + 1) * sizeof(int));
for (int i=0; i<numberOfElements+1; ++i) { for (int i=0; i<size+1; ++i) {
sparseMatrix->rowCumulativeIndexes[i] = 0; sparseMatrix->rowCumulativeIndexes[i] = 0;
} }
sparseMatrix->size = numberOfElements;
sparseMatrix->size = size;
sparseMatrix->numberOfElements = numberOfElements;
} }
void zeroOutRow(CsrSparseMatrix *sparseMatrix, int row) { void zeroOutRow(CsrSparseMatrix *sparseMatrix, int row) {
@ -34,7 +36,7 @@ void zeroOutRow(CsrSparseMatrix *sparseMatrix, int row) {
} }
void zeroOutColumn(CsrSparseMatrix *sparseMatrix, int column) { void zeroOutColumn(CsrSparseMatrix *sparseMatrix, int column) {
for (int i=0; i<sparseMatrix->numberOfNonZeroElements; ++i){ for (int i=0; i<sparseMatrix->numberOfElements; ++i){
if(sparseMatrix->columnIndexes[i] == column){ if(sparseMatrix->columnIndexes[i] == column){
sparseMatrix->values[i] = 0; sparseMatrix->values[i] = 0;
} }

4
serial/csr_sparse_matrix.h

@ -12,7 +12,7 @@
// A sparse matrix in compressed SparseRow format. // A sparse matrix in compressed SparseRow format.
typedef struct csrSparseMatrix { typedef struct csrSparseMatrix {
int size, numberOfNonZeroElements; int size, numberOfElements;
int *rowCumulativeIndexes, *columnIndexes; int *rowCumulativeIndexes, *columnIndexes;
double *values; double *values;
} CsrSparseMatrix; } CsrSparseMatrix;
@ -24,7 +24,7 @@ typedef struct csrSparseMatrix {
CsrSparseMatrix initCsrSparseMatrix(); CsrSparseMatrix initCsrSparseMatrix();
// allocMemoryForCsr allocates memory for the elements of the matrix. // allocMemoryForCsr allocates memory for the elements of the matrix.
void allocMemoryForCsr(CsrSparseMatrix *sparseMatrix, int numberOfElements); void allocMemoryForCsr(CsrSparseMatrix *sparseMatrix, int size, int numberOfElements);
// zeroOutRow assigns a zero value to all the elements of a row in the matrix. // zeroOutRow assigns a zero value to all the elements of a row in the matrix.
void zeroOutRow(CsrSparseMatrix *sparseMatrix, int row); void zeroOutRow(CsrSparseMatrix *sparseMatrix, int row);

43
serial/serial_gs_pagerank.c

@ -15,13 +15,38 @@ int main(int argc, char **argv) {
initialize(&transitionMatrix, &pagerankVector, &parameters); initialize(&transitionMatrix, &pagerankVector, &parameters);
// Saves information about the dataset to the output file
{
FILE *outputFile;
outputFile = fopen(parameters.outputFilename, "w");
if (outputFile == NULL) {
printf("Error while opening the output file.\n");
exit(EXIT_FAILURE);
}
fprintf(outputFile, "Pagerank will run for the dataset %s\n"\
"Dataset contains %d pages with %d outlinks.\n",
parameters.graphFilename, parameters.numberOfPages, transitionMatrix.size);
fclose(outputFile);
}
// Starts wall-clock timer // Starts wall-clock timer
gettimeofday (&startwtime, NULL); gettimeofday (&startwtime, NULL);
int* iterations = (int *)malloc(parameters.numberOfPages*sizeof(int)); int* iterations = (int *)malloc(parameters.numberOfPages*sizeof(int));
// Calculates pagerank
iterations = pagerank(&transitionMatrix, &pagerankVector, iterations = pagerank(&transitionMatrix, &pagerankVector,
&convergenceStatus, parameters, &maxIterationsForConvergence); &convergenceStatus, parameters, &maxIterationsForConvergence);
if (parameters.verbose) {
// Stops wall-clock timer
gettimeofday (&endwtime, NULL);
double seq_time = (double)((endwtime.tv_usec - startwtime.tv_usec)/1.0e6 +
endwtime.tv_sec - startwtime.tv_sec);
printf("%s wall clock time = %f\n","Pagerank (Gauss-Seidel method), serial implementation",
seq_time);
printf(ANSI_COLOR_YELLOW "\n----- RESULTS -----\n" ANSI_COLOR_RESET); printf(ANSI_COLOR_YELLOW "\n----- RESULTS -----\n" ANSI_COLOR_RESET);
if (convergenceStatus) { if (convergenceStatus) {
printf(ANSI_COLOR_GREEN "Pagerank converged after %d iterations!\n" \ printf(ANSI_COLOR_GREEN "Pagerank converged after %d iterations!\n" \
@ -30,20 +55,10 @@ int main(int argc, char **argv) {
printf(ANSI_COLOR_RED "Pagerank did not converge after max number of" \ printf(ANSI_COLOR_RED "Pagerank did not converge after max number of" \
" iterations (%d) was reached!\n" ANSI_COLOR_RESET, maxIterationsForConvergence); " iterations (%d) was reached!\n" ANSI_COLOR_RESET, maxIterationsForConvergence);
} }
}
// Stops wall-clock timer // Saves results to the output file
gettimeofday (&endwtime, NULL); savePagerankToFile(parameters.outputFilename, iterations, pagerankVector,
double seq_time = (double)((endwtime.tv_usec - startwtime.tv_usec)/1.0e6 + parameters.numberOfPages, maxIterationsForConvergence);
endwtime.tv_sec - startwtime.tv_sec);
printf("%s wall clock time = %f\n","Pagerank (Gauss-Seidel method), serial implementation",
seq_time);
if (!parameters.history) {
// Always outputs numberOfPages, max_iterations, last pagerank and iterations
// for all pages
savePagerankToFile(parameters.outputFilename, false, pagerankVector,
parameters.numberOfPages, iterations, maxIterationsForConvergence);
}
free(pagerankVector); free(pagerankVector);
destroyCsrSparseMatrix(&transitionMatrix); destroyCsrSparseMatrix(&transitionMatrix);

78
serial/serial_gs_pagerank_functions.c

@ -24,15 +24,18 @@ int* pagerank(CsrSparseMatrix *transitionMatrix, double **pagerankVector,
bool *convergenceStatus, Parameters parameters, int* maxIterationsForConvergence) { bool *convergenceStatus, Parameters parameters, int* maxIterationsForConvergence) {
// Variables declaration // Variables declaration
int numberOfPages = parameters.numberOfPages; int numberOfPages = parameters.numberOfPages;
int *iterations;
double delta, *pagerankDifference, *previousPagerankVector, double delta, *pagerankDifference, *previousPagerankVector,
*convergedPagerankVector, *linksFromConvergedPagesPagerankVector; *convergedPagerankVector, *linksFromConvergedPagesPagerankVector;
CsrSparseMatrix originalTransitionMatrix = initCsrSparseMatrix();
CooSparseMatrix linksFromConvergedPages = initCooSparseMatrix(); CooSparseMatrix linksFromConvergedPages = initCooSparseMatrix();
bool *convergenceMatrix; bool *convergenceMatrix;
int* iterations = (int *)malloc(numberOfPages*sizeof(int));
// Space allocation // Space allocation
{ {
size_t sizeofDouble = sizeof(double); size_t sizeofDouble = sizeof(double);
// iterations until each page converged
iterations = (int *) malloc(numberOfPages * sizeof(int));
// pagerankDifference used to calculate delta // pagerankDifference used to calculate delta
pagerankDifference = (double *) malloc(numberOfPages * sizeofDouble); pagerankDifference = (double *) malloc(numberOfPages * sizeofDouble);
// previousPagerankVector holds last iteration's pagerank vector // previousPagerankVector holds last iteration's pagerank vector
@ -48,7 +51,16 @@ int* pagerank(CsrSparseMatrix *transitionMatrix, double **pagerankVector,
*convergenceStatus = false; *convergenceStatus = false;
// Initialization // Initialization
allocMemoryForCoo(&linksFromConvergedPages, transitionMatrix->numberOfNonZeroElements); // originalTransitionMatrix used to run pagerank in phases
allocMemoryForCsr(&originalTransitionMatrix, transitionMatrix->size, transitionMatrix->numberOfElements);
memcpy(originalTransitionMatrix.rowCumulativeIndexes, transitionMatrix->rowCumulativeIndexes,
(transitionMatrix->size+1) * sizeof(int));
memcpy(originalTransitionMatrix.columnIndexes, transitionMatrix->columnIndexes,
transitionMatrix->numberOfElements * sizeof(int));
memcpy(originalTransitionMatrix.values, transitionMatrix->values,
transitionMatrix->numberOfElements * sizeof(double));
allocMemoryForCoo(&linksFromConvergedPages, transitionMatrix->numberOfElements);
for (int i=0; i<numberOfPages; ++i) { for (int i=0; i<numberOfPages; ++i) {
convergedPagerankVector[i] = 0; convergedPagerankVector[i] = 0;
convergenceMatrix[i] = false; convergenceMatrix[i] = false;
@ -73,8 +85,8 @@ int* pagerank(CsrSparseMatrix *transitionMatrix, double **pagerankVector,
if (parameters.history) { if (parameters.history) {
// Outputs pagerank vector to file // Outputs pagerank vector to file
savePagerankToFile(parameters.outputFilename, true, savePagerankToFile(parameters.outputFilename, NULL, *pagerankVector,
*pagerankVector, numberOfPages, iterations, *maxIterationsForConvergence); numberOfPages, *maxIterationsForConvergence);
} }
// Periodically checks for convergence // Periodically checks for convergence
@ -92,6 +104,8 @@ int* pagerank(CsrSparseMatrix *transitionMatrix, double **pagerankVector,
} }
} }
++(*maxIterationsForConvergence);
// Periodically increases sparsity // Periodically increases sparsity
if ((*maxIterationsForConvergence) && !(*maxIterationsForConvergence % SPARSITY_INCREASE_ITERATION_PERIOD)) { if ((*maxIterationsForConvergence) && !(*maxIterationsForConvergence % SPARSITY_INCREASE_ITERATION_PERIOD)) {
bool *newlyConvergedPages = (bool *) malloc(numberOfPages * sizeof(bool)); bool *newlyConvergedPages = (bool *) malloc(numberOfPages * sizeof(bool));
@ -106,6 +120,7 @@ int* pagerank(CsrSparseMatrix *transitionMatrix, double **pagerankVector,
newlyConvergedPages[i] = true; newlyConvergedPages[i] = true;
convergenceMatrix[i] = true; convergenceMatrix[i] = true;
convergedPagerankVector[i] = (*pagerankVector)[i]; convergedPagerankVector[i] = (*pagerankVector)[i];
iterations[i] = *maxIterationsForConvergence;
} }
} }
@ -131,7 +146,7 @@ int* pagerank(CsrSparseMatrix *transitionMatrix, double **pagerankVector,
// Increases sparsity of the transition matrix by zeroing // Increases sparsity of the transition matrix by zeroing
// out elements that correspond to converged pages // out elements that correspond to converged pages
zeroOutRow(transitionMatrix, i); zeroOutRow(transitionMatrix, i);
zeroOutColumn(transitionMatrix, i); //zeroOutColumn(transitionMatrix, i);
// Builds the new linksFromConvergedPagesPagerankVector // Builds the new linksFromConvergedPagesPagerankVector
cooSparseMatrixVectorMultiplication(linksFromConvergedPages, cooSparseMatrixVectorMultiplication(linksFromConvergedPages,
@ -142,23 +157,29 @@ int* pagerank(CsrSparseMatrix *transitionMatrix, double **pagerankVector,
free(newlyConvergedPages); free(newlyConvergedPages);
} }
// Prunes the transition matrix every 8 iterations
if (*maxIterationsForConvergence != 0 && (*maxIterationsForConvergence%8 == 0)) {
memcpy(transitionMatrix->values, originalTransitionMatrix.values,
transitionMatrix->numberOfElements * sizeof(double));
for (int i=0; i<numberOfPages; ++i) { for (int i=0; i<numberOfPages; ++i) {
if(!convergenceMatrix[i]){ convergedPagerankVector[i] = 0;
++iterations[i]; convergenceMatrix[i] = false;
linksFromConvergedPagesPagerankVector[i] = 0;
} }
linksFromConvergedPages.numberOfNonZeroElements = 0;
} }
++(*maxIterationsForConvergence);
// Outputs information about this iteration // Outputs information about this iteration
if (parameters.verbose){
if ((*maxIterationsForConvergence)%2) { if ((*maxIterationsForConvergence)%2) {
printf(ANSI_COLOR_BLUE "Iteration %d: delta = %f\n" ANSI_COLOR_RESET, *maxIterationsForConvergence, delta); printf(ANSI_COLOR_BLUE "Iteration %d: delta = %f\n" ANSI_COLOR_RESET, *maxIterationsForConvergence, delta);
} else { } else {
printf(ANSI_COLOR_CYAN "Iteration %d: delta = %f\n" ANSI_COLOR_RESET, *maxIterationsForConvergence, delta); printf(ANSI_COLOR_CYAN "Iteration %d: delta = %f\n" ANSI_COLOR_RESET, *maxIterationsForConvergence, delta);
} }
}
} while (!*convergenceStatus && (parameters.maxIterations == 0 || } while (!*convergenceStatus && (parameters.maxIterations == 0 ||
*maxIterationsForConvergence < parameters.maxIterations)); *maxIterationsForConvergence < parameters.maxIterations));
// Frees memory // Frees memory
free(pagerankDifference); free(pagerankDifference);
free(previousPagerankVector); free(previousPagerankVector);
@ -231,7 +252,7 @@ void calculateNextPagerank(CsrSparseMatrix *transitionMatrix,
vectorNorm(*pagerankVector, vectorSize); vectorNorm(*pagerankVector, vectorSize);
for (int i=0; i<vectorSize; ++i) { for (int i=0; i<vectorSize; ++i) {
(*pagerankVector)[i] += dampingFactor* normDifference * webUniformProbability + (*pagerankVector)[i] += normDifference * webUniformProbability +
linksFromConvergedPagesPagerankVector[i] + convergedPagerankVector[i]; linksFromConvergedPagesPagerankVector[i] + convergedPagerankVector[i];
} }
} }
@ -255,13 +276,13 @@ double vectorNorm(double *vector, int vectorSize) {
* parseArguments parses the command line arguments given by the user. * parseArguments parses the command line arguments given by the user.
*/ */
void parseArguments(int argumentCount, char **argumentVector, Parameters *parameters) { void parseArguments(int argumentCount, char **argumentVector, Parameters *parameters) {
if (argumentCount < 2 || argumentCount > 10) { if (argumentCount < 2 || argumentCount > 12) {
validUsage(argumentVector[0]); validUsage(argumentVector[0]);
} }
(*parameters).numberOfPages = 0; (*parameters).numberOfPages = 0;
(*parameters).maxIterations = 0; (*parameters).maxIterations = 0;
(*parameters).convergenceCriterion = 1; (*parameters).convergenceCriterion = 0.001;
(*parameters).dampingFactor = 0.85; (*parameters).dampingFactor = 0.85;
(*parameters).verbose = false; (*parameters).verbose = false;
(*parameters).history = false; (*parameters).history = false;
@ -435,7 +456,7 @@ void generateNormalizedTransitionMatrixFromFile(CsrSparseMatrix *transitionMatri
// Transposes the temporary transition matrix (P^T). // Transposes the temporary transition matrix (P^T).
transposeSparseMatrix(&tempMatrix); transposeSparseMatrix(&tempMatrix);
allocMemoryForCsr(transitionMatrix, numberOfEdges); allocMemoryForCsr(transitionMatrix, (*parameters).numberOfPages, numberOfEdges);
// Transforms the temporary COO matrix to the desired CSR format // Transforms the temporary COO matrix to the desired CSR format
transformToCSR(tempMatrix, transitionMatrix); transformToCSR(tempMatrix, transitionMatrix);
destroyCooSparseMatrix(&tempMatrix); destroyCooSparseMatrix(&tempMatrix);
@ -474,47 +495,34 @@ int checkIncrement(int previousIndex, int maxIndex, char *programName) {
return ++previousIndex; return ++previousIndex;
} }
void savePagerankToFile(char *filename, bool append, double *pagerankVector, void savePagerankToFile(char *filename, int *iterationsUntilConvergence,
int vectorSize, int* iterations, int maxIterationsForConvergence) { double *pagerankVector, int vectorSize, int iteration) {
FILE *outputFile; FILE *outputFile;
if (append) {
outputFile = fopen(filename, "a"); outputFile = fopen(filename, "a");
} else {
outputFile = fopen(filename, "w");
}
if (outputFile == NULL) { if (outputFile == NULL) {
printf("Error while opening the output file.\n"); printf("Error while opening the output file.\n");
return; return;
} }
fprintf(outputFile, "\n----- Iteration %d -----\n", iteration);
if(append){ // Saves the pagerank vector
double sum = 0; double sum = 0;
for (int i=0; i<vectorSize; ++i) { for (int i=0; i<vectorSize; ++i) {
sum += pagerankVector[i]; sum += pagerankVector[i];
} }
if (iterationsUntilConvergence == NULL){
for (int i=0; i<vectorSize; ++i) { for (int i=0; i<vectorSize; ++i) {
fprintf(outputFile, "%d = %.10g\n", i, pagerankVector[i]/sum); fprintf(outputFile, "%d = %.10g\n", i, pagerankVector[i]/sum);
} }
} } else {
else{
fprintf(outputFile, "numberOfPages = %d \t max_iterations_needed = %d \n", vectorSize, maxIterationsForConvergence);
double sum = 0;
for (int i=0; i<vectorSize; ++i) {
sum += pagerankVector[i];
}
for (int i=0; i<vectorSize; ++i) { for (int i=0; i<vectorSize; ++i) {
fprintf(outputFile, "%d \t %d \t %.10g\n", i, iterations[i], pagerankVector[i]/sum); fprintf(outputFile, "%d\t%d\t%.10g\n", i, iterationsUntilConvergence[i],
pagerankVector[i]/sum);
} }
} }
// Saves the pagerank vector
fclose(outputFile); fclose(outputFile);
} }

4
serial/serial_gs_pagerank_functions.h

@ -71,8 +71,8 @@ void generateNormalizedTransitionMatrixFromFile(CsrSparseMatrix *transitionMatri
// Function savePagerankToFile appends or overwrites the pagerank vector // Function savePagerankToFile appends or overwrites the pagerank vector
// "pagerankVector" to the file with the filename supplied in the arguments. // "pagerankVector" to the file with the filename supplied in the arguments.
void savePagerankToFile(char *filename, bool append, double *pagerankVector, void savePagerankToFile(char *filename, int *iterationsUntilConvergence,
int vectorSize, int* iterations, int maxIterationsForConvergence); double *pagerankVector, int vectorSize, int iteration);
// Function initialize allocates memory for the pagerank vector, reads the // Function initialize allocates memory for the pagerank vector, reads the
// dataset from the file and creates the transition probability distribution // dataset from the file and creates the transition probability distribution

Loading…
Cancel
Save