Hello there,
I am writing a small application that solves matrices on parallel machines with MPI.
I am using string a of characters to store the information about the filenames(matrix to read etc.). I am using malloc to allocate memory for the string of character. Whenever I try to
"free" the strong of characters I get bus errors. And depending on wich string of characters it is, I get either the bus error immediatelly after I call the free function, or after the program exists.. I tried to do a free immediatelly after I allocated memory and it worked fine.. But it does not work where I want it to be. Why is that? Should I put the string of characters as static global, outside of int main? Can anybody explain to me why the OS doesnt catch the segmentation fault but the hardware does?
here is the code, I have bolded the part that creates the bus error. Sorry if it isnt very readable! The formatting is a little weird.
I am writing a small application that solves matrices on parallel machines with MPI.
I am using string a of characters to store the information about the filenames(matrix to read etc.). I am using malloc to allocate memory for the string of character. Whenever I try to
"free" the strong of characters I get bus errors. And depending on wich string of characters it is, I get either the bus error immediatelly after I call the free function, or after the program exists.. I tried to do a free immediatelly after I allocated memory and it worked fine.. But it does not work where I want it to be. Why is that? Should I put the string of characters as static global, outside of int main? Can anybody explain to me why the OS doesnt catch the segmentation fault but the hardware does?
here is the code, I have bolded the part that creates the bus error. Sorry if it isnt very readable! The formatting is a little weird.
Code:
/******************************************************************************************
1) type "Makefile hypreSolver" to compile program
2) type "mprun -np 2 hypreSolver -a nonsingular_3d2.csr -b b_3d2.csr -x x.csr"
to run with 2 CPUs, default solver PCG and its default preconditioner.
type "mprun -np 2 hypreSolver -a nonsingular_3d2.csr -b b_3d2.csr -x x.csr -p euclid"
to run with 2 CPUs, default solver PCG and the ILU preconditioner euclid.
type "mprun -np 1 hypreSolver -a nonsingular_3d2.csr -b b_3d2.csr -x x.csr -s boomeramg"
to run with 1 CPU and BoomerAMG solver.
3)
a = coefficient matrix
b = right hand side vector
x = solution vector(where solution should be written to)
s = type of solver(default is PCG)
p = preconditioner(default is some kind of diagonal scaling for PCG I think)
(They call it Krylov in the source code)
solvers supported are: -s boomeramg
-s pcg
preconditioners for pcg supported are: -p default
-p diagonal
-p boomeramg
-p euclid
*****************************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "utilities.h"
#include "HYPRE.h"
#include "HYPRE_parcsr_mv.h"
#include "HYPRE_parcsr_ls.h"
#include "HYPRE_IJ_mv.h"
#include "krylov.h"
int main(int argc, char *argv[])
{
const int _DEFAULT = 0;
const int _DIAGONAL = 1;
const int _BOOMERAMG = 2;
const int _EUCLID= 3;
HYPRE_Solver preconditioner=NULL;
HYPRE_Solver solver=NULL;
HYPRE_Vector b_vector;
HYPRE_Vector x_vector;
HYPRE_ParCSRMatrix par_a;
HYPRE_ParVector par_vector_b;
HYPRE_ParVector par_vector_x;
HYPRE_CSRMatrix csr_a = NULL;
int size;
int my_id;
int time_index1;
int time_index2;
int first_local_row;
int last_local_row;
int local_num_rows;
int first_local_col;
int last_local_col;
int local_num_cols;
int num_of_rows;
int num_of_columns;
int num_iterations;
int a_used=0;
int x_used=0;
int b_used=0;
int i;
int ich;
int ierr;
int precond_value=_DEFAULT;
int solver_value=_DEFAULT;
double final_res_norm;
char *a_file=(char *)malloc(sizeof(char)*100);
char *x_file=(char *)malloc(sizeof(char)*100);
char *b_file=(char *)malloc(sizeof(char)*100);
char *temp_string=(char *)malloc(sizeof(char)*100);
MPI_Status Stat;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &my_id );
/* If I am processor 0, then read the files and settings from input */
if (my_id == 0)
{
while ((ich = getopt (argc, argv, "a:x:b:p:s:")) != -1) {
switch(ich) {
case 'a':
a_file=argv[optind-1];
a_used=1;
break;
case 'x':
x_file=argv[optind-1];
x_used=1;
break;
case 'b':
b_file=argv[optind-1];
b_used=1;
break;
case 'p':
temp_string=argv[optind-1];
if (strcmp("diagonal",temp_string) == 0)
precond_value=_DIAGONAL;
else if (strcmp("boomeramg",temp_string) == 0)
precond_value=_BOOMERAMG;
else if (strcmp("euclid",temp_string) == 0)
precond_value=_EUCLID;
else precond_value=_DEFAULT;
break;
case 's':
temp_string=argv[optind-1];
if (strcmp("boomeramg",temp_string) == 0)
solver_value=_BOOMERAMG;
else solver_value=_DEFAULT;
break;
default:
break;
}
}
if (a_used != 1 || x_used != 1 || b_used != 1)
{
printf("Input Error!\n");
MPI_Abort(MPI_COMM_WORLD, 1);
}
printf("ID-%d:\tReading coefficient matrix %s\n", my_id,a_file);
csr_a = HYPRE_CSRMatrixRead(a_file);
printf("ID-%d:\tReading right hand side vector %s\n", my_id,b_file);
b_vector = HYPRE_VectorRead(b_file);
/* Send the name of the result/solution file to the rest of the CPU's */
for (i=1; i<size;i++)
MPI_Send(x_file,100,MPI_CHAR,i,1,MPI_COMM_WORLD);
}
/* Receive the name of the result/solution file from CPU 0 */
if (my_id != 0)
MPI_Recv(x_file,100,MPI_CHAR,0,1,MPI_COMM_WORLD,&Stat);
/* Distribute the vector B */
HYPRE_VectorToParVector(MPI_COMM_WORLD,b_vector, NULL, &par_vector_b);
printf("ID-%d:\tDistributed right-hand-side vector b created\n",my_id);
/* Distribute the sparse matrix A */
HYPRE_CSRMatrixToParCSRMatrix(MPI_COMM_WORLD, csr_a, NULL, NULL, &par_a);
printf("ID-%d:\tDistributed coefficient matrix A created\n",my_id);
/* If I am processor 0, delete csr_a, b_vector */
/* Then create and initialize our solution vector X */
if (my_id == 0)
{
HYPRE_CSRMatrixDestroy(csr_a);
HYPRE_VectorDestroy(b_vector);
/* get the dimensions of the matrix A */
HYPRE_ParCSRMatrixGetDims(par_a,&num_of_rows,&num_of_columns);
printf("ID-%d:\tThe dimensions of matrix A is %d X %d\n",
my_id,num_of_rows,num_of_columns);
x_vector = HYPRE_VectorCreate(num_of_rows);
HYPRE_VectorInitialize(x_vector); // default sets values to zero
}
HYPRE_ParCSRMatrixGetLocalRange(par_a,
&first_local_row,
&last_local_row ,
&first_local_col,
&last_local_col);
printf("ID-%d:\tFirst row %d last row %d\n\tFirst col %d last col %d\n",
my_id,first_local_row,last_local_row,first_local_col,last_local_col);
/* Distribute the vector X */
HYPRE_VectorToParVector(MPI_COMM_WORLD,x_vector, NULL, &par_vector_x);
printf("ID-%d:\tDistributed solution vector x created\n",my_id);
/* If I am CPU 0, delete/remove x_vector */
if (my_id == 0)
HYPRE_VectorDestroy(x_vector);
time_index2 = hypre_InitializeTiming("Time for preconditioner/solver construction");
hypre_BeginTiming(time_index2);
printf("ID-%d:\tCreating preconditioner and solver\n",my_id);
/**************************** BoomerAMG Solver ***************************/
if (solver_value == _BOOMERAMG)
{
HYPRE_BoomerAMGCreate(&solver);
HYPRE_BoomerAMGSetMaxIter(solver, 5000);
HYPRE_BoomerAMGSetTol(solver, 1.0e-06);
//////////////////////////////////////////////////////////////////
//CPU 0 never returns from the call if more than one CPU is used//
//////////////////////////////////////////////////////////////////
HYPRE_BoomerAMGSetup(solver, par_a, par_vector_b, par_vector_x);
}
/******************************* PCG Solver ******************************/
else if (solver_value == _DEFAULT)
{
HYPRE_ParCSRPCGCreate(MPI_COMM_WORLD, &solver);
HYPRE_ParCSRPCGSetMaxIter(solver, 5000);
HYPRE_ParCSRPCGSetTol(solver, 1.0e-06);
HYPRE_ParCSRPCGSetTwoNorm(solver, 1);
// HYPRE_ParCSRPCGSetRelChange(solver, 0);
// HYPRE_ParCSRPCGSetStopCrit(solver, 1.0e-01);
HYPRE_ParCSRPCGSetLogging(solver, 1);
/******************** Diagonal scaling Preconditioner ********************/
if (precond_value == _DIAGONAL)
{
preconditioner = NULL;
HYPRE_ParCSRPCGSetPrecond(solver,
(HYPRE_PtrToParSolverFcn)
HYPRE_ParCSRDiagScale,
(HYPRE_PtrToParSolverFcn)
HYPRE_ParCSRDiagScaleSetup,
preconditioner);
}
/*********************** BoomerAMG Preconditioner ************************/
else if (precond_value == _BOOMERAMG)
{
HYPRE_BoomerAMGCreate(&preconditioner);
HYPRE_BoomerAMGSetTol(preconditioner, 0.);
HYPRE_BoomerAMGSetMaxIter(preconditioner, 1);
HYPRE_ParCSRPCGSetPrecond(solver,
(HYPRE_PtrToParSolverFcn)
HYPRE_BoomerAMGSolve,
(HYPRE_PtrToParSolverFcn)
HYPRE_BoomerAMGSetup,
preconditioner);
}
/************************* Euclid Preconditioner *************************/
else if (precond_value == _EUCLID)
{
HYPRE_EuclidCreate(MPI_COMM_WORLD,&preconditioner);
//HYPRE_EuclidSetParams(preconditioner,"-level","3");
HYPRE_ParCSRPCGSetPrecond(solver,
(HYPRE_PtrToParSolverFcn)
HYPRE_EuclidSolve,
(HYPRE_PtrToParSolverFcn)
HYPRE_EuclidSetup,
preconditioner);
}
//////////////////////////////////////////////////////////////////
/////////////If preconditioner = euclid or boomeramg//////////////
//CPU 0 never returns from the call if more than one CPU is used//
//////////////////////////////////////////////////////////////////
HYPRE_ParCSRPCGSetup(solver, par_a, par_vector_b, par_vector_x);
}
hypre_EndTiming(time_index2);
printf("ID-%d:\tSolving matrix\n",my_id);
time_index1 = hypre_InitializeTiming("Time for solving matrix");
hypre_BeginTiming(time_index1);
if (solver_value == _BOOMERAMG)
{
HYPRE_BoomerAMGSolve(solver, par_a, par_vector_b, par_vector_x);
hypre_EndTiming(time_index1);
HYPRE_BoomerAMGGetNumIterations(solver, &num_iterations);
HYPRE_BoomerAMGGetFinalRelativeResidualNorm(solver, &final_res_norm);
HYPRE_BoomerAMGDestroy(solver);
}
else if (solver_value == _DEFAULT)
{
HYPRE_ParCSRPCGSolve(solver,par_a,par_vector_b,par_vector_x);
hypre_EndTiming(time_index1);
HYPRE_ParCSRPCGGetNumIterations(solver, &num_iterations);
HYPRE_ParCSRPCGGetFinalRelativeResidualNorm(solver, &final_res_norm);
HYPRE_ParCSRPCGDestroy(solver);
}
printf("ID-%d:\tWriting result/solution vector to disk\n", my_id);
/* write the solution vector x to file */
HYPRE_ParVectorPrint(par_vector_x,x_file);
/* delete/remove the distributed matrix A, vectors b and x */
HYPRE_ParCSRMatrixDestroy(par_a);
HYPRE_ParVectorDestroy(par_vector_b);
HYPRE_ParVectorDestroy(par_vector_x);
[b]
free(a_file);
free(x_file);
free(b_file);
free(temp_string);
[/b]
/* Print out the time results */
hypre_PrintTiming("Solve phase times", MPI_COMM_WORLD);
hypre_FinalizeTiming(time_index1);
hypre_FinalizeTiming(time_index2);
hypre_ClearTiming();
if (my_id == 0)
printf("Number of iterations: %d and final residual norm: %E\n",
num_iterations,final_res_norm);
MPI_Finalize();
return 0;
}