diff --git a/Base/CMakeLists.txt b/Base/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..2acb5e21be9845f6427db8933eb2a281c50370cf --- /dev/null +++ b/Base/CMakeLists.txt @@ -0,0 +1,18 @@ +# Source files +SET( HEADERS + Configure.h.in + TimeMeasurementBase.h + RunTimeTimer.h + CPUTimeTimer.h +) + +SET( SOURCES + RunTimeTimer.cpp + CPUTimeTimer.cpp +) + +# Create the library +ADD_LIBRARY( Base STATIC ${HEADERS} ${SOURCES} ) + +SET_TARGET_PROPERTIES(Base PROPERTIES LINKER_LANGUAGE CXX) + diff --git a/Base/CPUTimeTimer.cpp b/Base/CPUTimeTimer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad8377cd9348611c414574d9cf914b08ece7a7ff --- /dev/null +++ b/Base/CPUTimeTimer.cpp @@ -0,0 +1,17 @@ +#include "CPUTimeTimer.h" + +void CPUTimeTimer::start() +{ + _start = clock(); +} + +void CPUTimeTimer::stop() +{ + _stop = clock(); +} + +double CPUTimeTimer::elapsed() +{ + return (_stop-_start)/(double)(CLOCKS_PER_SEC); +} + diff --git a/Base/CPUTimeTimer.h b/Base/CPUTimeTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..8b5eb18b6022e395f7b5beda3dadd7472218f734 --- /dev/null +++ b/Base/CPUTimeTimer.h @@ -0,0 +1,21 @@ +#ifndef CPUTIMETIMER_H +#define CPUTIMETIMER_H + +#include <ctime> + +#include "TimeMeasurementBase.h" + +class CPUTimeTimer +{ +public: + virtual void start(); + virtual void stop(); + virtual double elapsed(); + ~CPUTimeTimer() {}; +private: + clock_t _start; + clock_t _stop; +}; + +#endif + diff --git a/Base/Configure.h.in b/Base/Configure.h.in new file mode 100644 index 0000000000000000000000000000000000000000..aead27c31e567cdc1e141fa27ebce45f7e77f5a5 --- /dev/null +++ b/Base/Configure.h.in @@ -0,0 +1,15 @@ +/** + * \file Configure.h.in + * + * #defines which gets set through CMake + */ +#ifndef CONFIGURE_H +#define CONFIGURE_H + +#define SOURCEPATH "${CMAKE_SOURCE_DIR}" + +#cmakedefine HAVE_PTHREADS +#cmakedefine PROCESSOR_COUNT "${PROCESSOR_COUNT}" + +#endif // CONFIGURE_H + diff --git a/Base/RunTimeTimer.cpp b/Base/RunTimeTimer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b89563245665c5178af08395f02c339cf2890ed4 --- /dev/null +++ b/Base/RunTimeTimer.cpp @@ -0,0 +1,17 @@ +#include "RunTimeTimer.h" + +void RunTimeTimer::start() +{ + gettimeofday(&_start, 0); +} + +void RunTimeTimer::stop() +{ + gettimeofday(&_stop, 0); +} + +double RunTimeTimer::elapsed() +{ + return (_stop.tv_sec + _stop.tv_usec/1000000.0 - (_start.tv_sec + _start.tv_usec/1000000.0)); +} + diff --git a/Base/RunTimeTimer.h b/Base/RunTimeTimer.h new file mode 100644 index 0000000000000000000000000000000000000000..871cfb5a601a0212ab67e77dc7846dd03c4672a1 --- /dev/null +++ b/Base/RunTimeTimer.h @@ -0,0 +1,21 @@ +#ifndef RUNTIMETIMER_H +#define RUNTIMETIMER_H + +#include <sys/time.h> + +#include "TimeMeasurementBase.h" + +class RunTimeTimer +{ +public: + virtual void start(); + virtual void stop(); + virtual double elapsed(); + ~RunTimeTimer() {}; +private: + timeval _start; + timeval _stop; +}; + +#endif + diff --git a/Base/TimeMeasurementBase.h b/Base/TimeMeasurementBase.h new file mode 100644 index 0000000000000000000000000000000000000000..36c081fe3db1afe184da77f95482b40ba6210d73 --- /dev/null +++ b/Base/TimeMeasurementBase.h @@ -0,0 +1,14 @@ +#ifndef TIMEMEASUREMENT_H +#define TIMEMEASUREMENT_H + +class TimeMeasurementBase +{ +public: + virtual void start () = 0; + virtual void stop () = 0; + virtual double elapsed () = 0; + virtual ~TimeMeasurementBase () {}; +}; + +#endif + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..56d6bf2f70ae4cc4994bf0e6d9276105abfbfdd4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,33 @@ +# Specify minimum CMake version +cmake_minimum_required(VERSION 2.6) + +# Project name +project( OGS-6 ) + +# Set cmake module path +#SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMakeConfiguration") + +### For GNU C/CXX +IF(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC) + IF( NOT CMAKE_BUILD_TYPE STREQUAL "Debug" ) + MESSAGE(STATUS "Set GCC release flags") + SET(CMAKE_CXX_FLAGS "-O3 -march=native -mtune=native -msse4.2 -DNDEBUG") + ENDIF() + # -g + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -Wall -Wextra -fno-nonansi-builtins") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp") + ADD_DEFINITIONS( + -DGCC + ) +ENDIF(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC) + +# Set build directories +SET( EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin ) +SET( LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib ) + +# Add subdirectories with the projects +ADD_SUBDIRECTORY( Base ) +ADD_SUBDIRECTORY( MathLib ) +ADD_SUBDIRECTORY( SimpleTests/MatrixTests ) + + diff --git a/MathLib/CMakeLists.txt b/MathLib/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..07597457dc76a27b94258c6492ece9bcf88e750a --- /dev/null +++ b/MathLib/CMakeLists.txt @@ -0,0 +1,25 @@ +# Source files +SET( HEADERS + amuxCRS.h + CRSMatrix.h + CRSMatrixPThreads.h + CRSMatrixOpenMP.h + CRSSymMatrix.h + sparse.h + SparseMatrixBase.h +) + +SET( SOURCES + amuxCRS.cpp +) + +INCLUDE_DIRECTORIES ( + . + ${PROJECT_BINARY_DIR}/Base +) + +# Create the library +ADD_LIBRARY( MathLib STATIC ${HEADERS} ${SOURCES} ) + +SET_TARGET_PROPERTIES(MathLib PROPERTIES LINKER_LANGUAGE CXX) + diff --git a/MathLib/CRSMatrix.h b/MathLib/CRSMatrix.h new file mode 100644 index 0000000000000000000000000000000000000000..f040e654276b375e4fb2c61e2ada60845275e180 --- /dev/null +++ b/MathLib/CRSMatrix.h @@ -0,0 +1,55 @@ +#ifndef CRSMATRIX_H +#define CRSMATRIX_H + +#include <string> +#include <fstream> +#include <iostream> +#include "SparseMatrixBase.h" +#include "sparse.h" +#include "amuxCRS.h" + +template<class T> class CRSMatrix : public SparseMatrixBase<T> +{ +public: + CRSMatrix(std::string const &fname) : + SparseMatrixBase<T>(), + _row_ptr(NULL), _col_idx(NULL), _data(NULL) + { + std::ifstream in(fname.c_str(), std::ios::in | std::ios::binary); + if (in) { + CS_read(in, SparseMatrixBase<T>::_n_rows, _row_ptr, _col_idx, _data); + SparseMatrixBase<T>::_n_cols = SparseMatrixBase<T>::_n_rows; + in.close(); + } else { + std::cout << "cannot open " << fname << std::endl; + } + } + + CRSMatrix(unsigned n, unsigned *iA, unsigned *jA, T* A) : + SparseMatrixBase<T>(n,n), _row_ptr(iA), _col_idx(jA), _data(A) + {} + + CRSMatrix(unsigned n1) : + SparseMatrixBase<T>(n1, n1), _row_ptr(NULL), _col_idx(NULL), _data(NULL) + {} + + virtual ~CRSMatrix() + { + delete [] _row_ptr; + delete [] _col_idx; + delete [] _data; + } + + virtual void amux(T d, T const * const x, T *y) const + { + amuxCRS(d, SparseMatrixBase<T>::_n_rows, _row_ptr, _col_idx, _data, x, y); + } + +protected: + unsigned *_row_ptr; + unsigned *_col_idx; + T* _data; +}; + +#endif + diff --git a/MathLib/CRSMatrixDiagPrecond.h b/MathLib/CRSMatrixDiagPrecond.h new file mode 100644 index 0000000000000000000000000000000000000000..2335eedf001f7cf4b6af353402fc9a9fd2fc2bf8 --- /dev/null +++ b/MathLib/CRSMatrixDiagPrecond.h @@ -0,0 +1,40 @@ +#ifndef CRSMATRIXDIAGPRECOND_H +#define CRSMATRIXDIAGPRECOND_H + +#include <omp.h> + +#include "CRSMatrix.h" +#include "sparse.h" + +class CRSMatrixDiagPrecond : public CRSMatrix<double> +{ +public: + CRSMatrixDiagPrecond (std::string const &fname, unsigned num_of_threads=1) + : CRSMatrix<double>(fname, num_of_threads), _inv_diag(NULL) + { + _inv_diag = new double[_n_rows]; + if (!generateDiagPrecond (_n_rows, _row_ptr, _col_idx, _data, _inv_diag)) { + std::cout << "Could not create diagonal preconditioner" << std::endl; + } + } + + void precondApply(double* x) const { + omp_set_num_threads( _num_of_threads ); + { + unsigned k; + #pragma omp parallel for + for (k=0; k<_n_rows; ++k) { + x[k] = _inv_diag[k]*x[k]; + } + } + } + + ~CRSMatrixDiagPrecond() { + delete [] _inv_diag; + } +private: + double *_inv_diag; +}; + +#endif + diff --git a/MathLib/CRSMatrixOpenMP.h b/MathLib/CRSMatrixOpenMP.h new file mode 100644 index 0000000000000000000000000000000000000000..009be74ee2991377c9cc3e9cf70158d906160c51 --- /dev/null +++ b/MathLib/CRSMatrixOpenMP.h @@ -0,0 +1,42 @@ +/* + * CRSMatrixOpenMP.h + * + * Created on: Aug 8, 2011 + * Author: TF + */ + +#ifndef CRSMATRIXOPENMP_H_ +#define CRSMATRIXOPENMP_H_ + +#include <string> + +#include "CRSMatrix.h" +#include "amuxCRS.h" + +template<class T> class CRSMatrixOpenMP : public CRSMatrix<T> { +public: + CRSMatrixOpenMP(std::string const &fname, unsigned num_of_threads) : + CRSMatrix<T>(fname), _num_of_threads (num_of_threads) + {} + + CRSMatrixOpenMP(unsigned n, unsigned *iA, unsigned *jA, T* A, unsigned num_of_threads) : + CRSMatrix<T>(n, iA, jA, A), _num_of_threads (num_of_threads) + {} + + CRSMatrixOpenMP(unsigned n1) : + CRSMatrix<T>(n1), _num_of_threads (1) + {} + + virtual ~CRSMatrixOpenMP() + {} + + virtual void amux(T d, T const * const x, T *y) const + { + amuxCRSParallelOpenMP(d, SparseMatrixBase<T>::_n_rows, CRSMatrix<T>::_row_ptr, CRSMatrix<T>::_col_idx, CRSMatrix<T>::_data, x, y, _num_of_threads); + } + +private: + unsigned _num_of_threads; +}; + +#endif /* CRSMATRIXOPENMP_H_ */ diff --git a/MathLib/CRSMatrixPThreads.h b/MathLib/CRSMatrixPThreads.h new file mode 100644 index 0000000000000000000000000000000000000000..7c56d9b89488bd1ca1516acc08889cbcf2f67f16 --- /dev/null +++ b/MathLib/CRSMatrixPThreads.h @@ -0,0 +1,46 @@ +/* + * CRSMatrixPThreads.h + * + * Created on: Aug 2, 2011 + * Author: TF + */ + +#ifndef CRSMATRIXPTHREADS_H +#define CRSMATRIXPTHREADS_H + +#include <string> + +#include "SparseMatrixBase.h" +#include "sparse.h" +#include "CRSMatrix.h" +#include "amuxCRS.h" + +template<class T> class CRSMatrixPThreads : public CRSMatrix<T> +{ +public: + CRSMatrixPThreads(std::string const &fname, unsigned num_of_threads) : + CRSMatrix<T>(fname), _num_of_threads (num_of_threads) + {} + + CRSMatrixPThreads(unsigned n, unsigned *iA, unsigned *jA, T* A, unsigned num_of_threads) : + CRSMatrix<T>(n, iA, jA, A), _num_of_threads (num_of_threads) + {} + + CRSMatrixPThreads(unsigned n1) : + CRSMatrix<T>(n1), _num_of_threads (1) + {} + + virtual ~CRSMatrixPThreads() + {} + + virtual void amux(T d, T const * const x, T *y) const + { + amuxCRSParallelPThreads(d, SparseMatrixBase<T>::_n_rows, CRSMatrix<T>::_row_ptr, CRSMatrix<T>::_col_idx, CRSMatrix<T>::_data, x, y, _num_of_threads); + } + +protected: + unsigned _num_of_threads; +}; + +#endif + diff --git a/MathLib/CRSSymMatrix.h b/MathLib/CRSSymMatrix.h new file mode 100644 index 0000000000000000000000000000000000000000..37a75ed86f7966a1d3d543a81bf0ba6ddafeb6c0 --- /dev/null +++ b/MathLib/CRSSymMatrix.h @@ -0,0 +1,64 @@ +/* + * CRSSymMatrix.h + * + * Created on: Jul 22, 2011 + * Author: fischeth + */ + +#ifndef CRSSYMMATRIX_H_ +#define CRSSYMMATRIX_H_ + +#include "CRSMatrix.h" + +template<class T> class CRSSymMatrix : public CRSMatrix<T> +{ +public: + CRSSymMatrix(std::string const &fname) + : CRSMatrix<T> (fname) + { + unsigned nnz (0); + + // count number of non-zeros in the upper triangular part + for (unsigned i = 0; i < SparseMatrixBase<T>::_n_rows; i++) { + unsigned idx = CRSMatrix<T>::_row_ptr[i+1]; + for (unsigned j = CRSMatrix<T>::_row_ptr[i]; j < idx; j++) + if (CRSMatrix<T>::_col_idx[j] >= i) + ++nnz; + } + + double *A_new (new double[nnz]); + unsigned *jA_new (new unsigned[nnz]); + unsigned *iA_new (new unsigned[SparseMatrixBase<T>::_n_rows+1]); + + iA_new[0] = nnz = 0; + + for (unsigned i = 0; i < SparseMatrixBase<T>::_n_rows; i++) { + const unsigned idx (CRSMatrix<T>::_row_ptr[i+1]); + for (unsigned j = CRSMatrix<T>::_row_ptr[i]; j < idx; j++) { + if (CRSMatrix<T>::_col_idx[j] >= i) { + A_new[nnz] = CRSMatrix<T>::_data[j]; + jA_new[nnz++] = CRSMatrix<T>::_col_idx[j]; + } + } + iA_new[i+1] = nnz; + } + + std::swap(CRSMatrix<T>::_row_ptr, iA_new); + std::swap(CRSMatrix<T>::_col_idx, jA_new); + std::swap(CRSMatrix<T>::_data, A_new); + + delete[] iA_new; + delete[] jA_new; + delete[] A_new; + } + + virtual ~CRSSymMatrix() {} + + void amux(T d, T const * const x, T *y) const + { + amuxCRSSym (d, SparseMatrixBase<T>::_n_rows, CRSMatrix<T>::_row_ptr, CRSMatrix<T>::_col_idx, CRSMatrix<T>::_data, x, y); + } + +}; + +#endif /* CRSSYMMATRIX_H_ */ diff --git a/MathLib/SparseMatrixBase.h b/MathLib/SparseMatrixBase.h new file mode 100644 index 0000000000000000000000000000000000000000..831818a1b13e7231d32183101612e0e7912ee4cf --- /dev/null +++ b/MathLib/SparseMatrixBase.h @@ -0,0 +1,21 @@ +#ifndef SPARSEMATRIXBASE_H +#define SPARSEMATRIXBASE_H + +template<class T> class SparseMatrixBase +{ +public: + SparseMatrixBase(unsigned n1, unsigned n2) : _n_rows(n1), _n_cols(n2) { } + SparseMatrixBase() : _n_rows(0), _n_cols(0) { } + virtual void amux(T d, T const * const x, T *y) const = 0; // y +=d*Ax + virtual ~SparseMatrixBase() { } + unsigned getNRows () const { return _n_rows; } + unsigned getNCols () const { return _n_cols; } + +protected: + unsigned _n_rows; + unsigned _n_cols; +}; + + +#endif + diff --git a/MathLib/amuxCRS.cpp b/MathLib/amuxCRS.cpp new file mode 100644 index 0000000000000000000000000000000000000000..336527d0bd6d12a44ddac62f1c25f12ff6cee420 --- /dev/null +++ b/MathLib/amuxCRS.cpp @@ -0,0 +1,148 @@ +#include "amuxCRS.h" +#include <omp.h> +#include <omp.h> +#include <pthread.h> + +void amuxCRS (double a, + unsigned n, unsigned const * const iA, unsigned const * const jA, + double const * const A, double const * const x, double* y) +{ + for (unsigned i(0); i<n; i++) { + y[i] = 0.0; + const unsigned end (iA[i+1]); + for (unsigned j(iA[i]); j<end; j++) { + y[i] += A[j] * x[jA[j]]; + } + y[i] *= a; + } +} + +struct MatMultThreadParam { + MatMultThreadParam (double scalar_factor, unsigned beg_row, unsigned end_row, + unsigned const * const iA, unsigned const * const jA, + double const * const A, double const * const x, double* y) : + _a (scalar_factor), _beg_row(beg_row), _end_row(end_row), + _row_ptr(iA), _col_idx(jA), _data(A), _x(x), _y(y) + {} + + double _a; + unsigned _beg_row; + unsigned _end_row; + unsigned const * const _row_ptr; + unsigned const * const _col_idx; + double const * const _data; + double const * const _x; + double * _y; +}; + +extern "C" { +void* amuxCRSpthread (void* ptr) +{ + MatMultThreadParam *thread_param ((MatMultThreadParam*)(ptr)); + const double a (thread_param->_a); + const unsigned beg_row (thread_param->_beg_row); + const unsigned end_row (thread_param->_end_row); + unsigned const * const iA (thread_param->_row_ptr); + unsigned const * const jA (thread_param->_col_idx); + double const * const A (thread_param->_data); + double const * const x (thread_param->_x); + double* y(thread_param->_y); + + for (unsigned i(beg_row); i<end_row; i++) { + y[i] = 0.0; + const unsigned end (iA[i+1]); + for (unsigned j(iA[i]); j<end; j++) { + y[i] += A[j] * x[jA[j]]; + } + y[i] *= a; + } + return NULL; +} +} // end extern "C" + +void amuxCRSParallelPThreads (double a, + unsigned n, unsigned const * const iA, unsigned const * const jA, + double const * const A, double const * const x, double* y, + unsigned num_of_pthreads) +{ +#ifdef HAVE_PTHREADS + // fill thread data objects + MatMultThreadParam** thread_param_array (new MatMultThreadParam*[num_of_pthreads]); + double step_size ((double)(n)/(double)(num_of_pthreads)); + for (unsigned k(0); k<num_of_pthreads; k++) { + const unsigned beg (static_cast<unsigned>(k*step_size)); + const unsigned end (static_cast<unsigned>((k+1)*step_size)); + thread_param_array[k] = new MatMultThreadParam (a, beg, end, iA, jA, A, x, y); + } + + // allocate thread_array and return value array + pthread_t *thread_array (new pthread_t[num_of_pthreads]); + int *ret_vals (new int[num_of_pthreads]); + + // create threads + for (unsigned k(0); k<num_of_pthreads; k++) { + ret_vals[k] = pthread_create( &(thread_array[k]), NULL, amuxCRSpthread, thread_param_array[k]); + } + + // join threads + for (unsigned k(0); k<num_of_pthreads; k++) { + pthread_join (thread_array[k], NULL); + } + + delete [] ret_vals; + for (unsigned k(0); k<num_of_pthreads; k++) + delete thread_param_array[k]; + delete [] thread_param_array; + delete [] thread_array; +#else + amuxCRS (a, n, iA, jA, A, x, y); +#endif +} + +void amuxCRSParallelOpenMP (double a, + unsigned n, unsigned const * const iA, unsigned const * const jA, + double const * const A, double const * const x, double* y, + unsigned num_of_omp_threads) +{ + unsigned i; + omp_set_num_threads(num_of_omp_threads); + { + #pragma omp parallel for + for (i=0; i<n; i++) { + y[i] = 0.0; + const unsigned end (iA[i+1]); + for (unsigned j(iA[i]); j<end; j++) { + y[i] += A[j] * x[jA[j]]; + } + y[i] *= a; + } + } +} + +void amuxCRSSym (double a, + unsigned n, unsigned const * const iA, unsigned const * const jA, + double const * const A, double const * const x, double* y) +{ + for (unsigned i(0); i<n; i++) { + y[i] = 0.0; + } + + for (unsigned i(0); i<n; i++) { + unsigned j (iA[i]); + // handle diagonal + if (jA[j] == i) { + y[i] += A[j] * x[jA[j]]; + j++; + } + const unsigned end (iA[i+1]); + for (; j<end; j++) { + y[i] += A[j] * x[jA[j]]; + y[jA[j]] += A[j] * x[i]; + } + } + + for (unsigned i(0); i<n; i++) { + y[i] *= a; + } +} + diff --git a/MathLib/amuxCRS.h b/MathLib/amuxCRS.h new file mode 100644 index 0000000000000000000000000000000000000000..24ec77d6fa41dac6530ab06821e5cf96a3213246 --- /dev/null +++ b/MathLib/amuxCRS.h @@ -0,0 +1,22 @@ +#ifndef AMUXCRS_H +#define AMUXCRS_H + +void amuxCRS (double a, + unsigned n, unsigned const * const iA, unsigned const * const jA, + double const * const A, double const * const x, double* y); + +void amuxCRSParallelPThreads (double a, + unsigned n, unsigned const * const iA, unsigned const * const jA, + double const * const A, double const * const x, double* y, + unsigned num_of_pthreads); + +void amuxCRSParallelOpenMP (double a, + unsigned n, unsigned const * const iA, unsigned const * const jA, + double const * const A, double const * const x, double* y, + unsigned num_of_omp_threads); + +void amuxCRSSym (double a, + unsigned n, unsigned const * const iA, unsigned const * const jA, + double const * const A, double const * const x, double* y); + +#endif diff --git a/MathLib/sparse.h b/MathLib/sparse.h new file mode 100644 index 0000000000000000000000000000000000000000..44ecf09e79b58078d235b8bfccd847d8102b4cc4 --- /dev/null +++ b/MathLib/sparse.h @@ -0,0 +1,88 @@ +#ifndef SPARSE_H +#define SPARSE_H + +#include <iostream> +#include <cassert> + +extern void CS_write(char*, unsigned, unsigned*, unsigned*, double*); +extern void CS_read(char*, unsigned&, unsigned*&, unsigned*&, double*&); + +template<class T> void +CS_write(std::ostream &os, unsigned n, unsigned* iA, unsigned* jA, T* A) +{ + os.write((char*) &n, sizeof(unsigned)); + os.write((char*) iA, (n+1)*sizeof(unsigned)); + os.write((char*) jA, iA[n]*sizeof(unsigned)); + os.write((char*) A, iA[n]*sizeof(T)); +} + +template<class T> void +CS_read(std::istream &is, unsigned &n, unsigned* &iA, unsigned* &jA, T* &A) +{ + is.read((char*) &n, sizeof(unsigned)); + if (iA != NULL) { + delete [] iA; + delete [] jA; + delete [] A; + } + iA = new unsigned[n+1]; + assert(iA!=NULL); + is.read((char*) iA, (n+1)*sizeof(unsigned)); + + jA = new unsigned[iA[n]]; + assert(jA!=NULL); + is.read((char*) jA, iA[n]*sizeof(unsigned)); + + A = new T[iA[n]]; + assert(A!=NULL); + is.read((char*) A, iA[n]*sizeof(T)); + +#ifndef NDEBUG + // do simple checks + if (iA[0]!=0) + std::cerr << std::endl + << "CRS matrix: array iA doesn't start with 0" << std::endl; + + unsigned i = 0; + while (i<iA[n] && jA[i]<n) ++i; + if (i<iA[n]) + std::cerr << std::endl + << "CRS matrix: the " << i << "th entry of jA has the value " + << jA[i] << ", which is out of bounds." << std::endl; +#endif +} + +void CS_transp(unsigned n, double* A, unsigned* jA, unsigned *iA, + double* B, unsigned *jB, unsigned *iB) +{ + unsigned nnz = iA[n]; + unsigned *inz = new unsigned[n]; + + for (unsigned i=0; i<n; ++i) inz[i] = 0; + + // compute number of entries of each column in A + for (unsigned l=0; l<nnz; ++l) inz[jA[l]]++; + + // create iB + iB[0] = nnz = 0; + for (unsigned i=0; i<n; ++i) { + nnz += inz[i]; + inz[i] = 0; + iB[i+1] = nnz; + } + + // create arrays jB, B + unsigned l = iA[0]; + for (unsigned i=0; i<n; ++i) { + while (l<iA[i+1]) { + unsigned j = jA[l]; + unsigned k = iB[j] + inz[j]++; + B[k] = A[l++]; + jB[k] = i; + } + } + + delete [] inz; +} + +#endif diff --git a/SimpleTests/MatrixTests/.MatMult.cpp.swp b/SimpleTests/MatrixTests/.MatMult.cpp.swp new file mode 100644 index 0000000000000000000000000000000000000000..808689bb3f0aefe083b5aa63d6b6f520e7d2869f Binary files /dev/null and b/SimpleTests/MatrixTests/.MatMult.cpp.swp differ diff --git a/SimpleTests/MatrixTests/CMakeLists.txt b/SimpleTests/MatrixTests/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..08a920431b8ac1f63950cc94cc0133be33015ec8 --- /dev/null +++ b/SimpleTests/MatrixTests/CMakeLists.txt @@ -0,0 +1,26 @@ +## pthread ## +SET ( CMAKE_THREAD_PREFER_PTHREAD On ) +FIND_PACKAGE( Threads ) +IF ( CMAKE_USE_PTHREADS_INIT ) + SET (HAVE_PTHREADS TRUE) + MESSAGE (STATUS "pthread library found." ) +ENDIF (CMAKE_USE_PTHREADS_INIT ) + +INCLUDE_DIRECTORIES( + . + ../../Base/ + ../../MathLib/ +) + +# Create the executable +ADD_EXECUTABLE( MatMult + MatMult.cpp + ${SOURCES} + ${HEADERS} +) + +TARGET_LINK_LIBRARIES ( MatMult + Base + MathLib +) + diff --git a/SimpleTests/MatrixTests/MatMult.cpp b/SimpleTests/MatrixTests/MatMult.cpp new file mode 100644 index 0000000000000000000000000000000000000000..182e119d6deef48289d4e1fcf7037af6cef90236 --- /dev/null +++ b/SimpleTests/MatrixTests/MatMult.cpp @@ -0,0 +1,116 @@ +#include <fstream> +#include <iostream> +#include <cmath> +#include <limits> +#include <omp.h> +#include <cstdlib> +#include "sparse.h" +#include "CRSMatrix.h" +#include "CRSMatrixOpenMP.h" +#include "CRSMatrixPThreads.h" +#include "RunTimeTimer.h" +#include "CPUTimeTimer.h" + +int main(int argc, char *argv[]) +{ + if (argc < 4) { + std::cout << "Usage: " << argv[0] << " num_of_threads matrix number_of_multiplications resultfile" << std::endl; + exit (1); + } + + // read number of threads + unsigned n_threads (1); + n_threads = atoi (argv[1]); + + // read the number of multiplication to execute + unsigned n_mults (0); + n_mults = atoi (argv[3]); + + std::string fname_mat (argv[2]); + + bool verbose (true); + + // *** reading matrix in crs format from file + std::ifstream in(fname_mat.c_str(), std::ios::in | std::ios::binary); + double *A(NULL); + unsigned *iA(NULL), *jA(NULL), n; + if (in) { + if (verbose) { + std::cout << "reading matrix from " << fname_mat << " ... " << std::flush; + } + RunTimeTimer timer; + timer.start(); + CS_read(in, n, iA, jA, A); + timer.stop(); + if (verbose) { + std::cout << "ok, " << timer.elapsed() << " s)" << std::endl; + } + } else { + std::cout << "error reading matrix from " << fname_mat << std::endl; + } + unsigned nnz(iA[n]); + if (verbose) { + std::cout << "Parameters read: n=" << n << ", nnz=" << nnz << std::endl; + } + +/* + // test: fill all nnz entries with 1 + for (unsigned k(0); k<nnz; k++) A[k] = 2.0; +*/ + + CRSMatrix<double> mat (n, iA, jA, A); +// CRSMatrixOpenMP<double> mat (n, iA, jA, A, n_threads); +// CRSMatrixPThreads<double> mat (n, iA, jA, A, n_threads); + + double *x(new double[n]); + double *y(new double[n]); + + for (unsigned k(0); k<n; ++k) + x[k] = 1.0; + + if (verbose) { + std::cout << "matrix vector multiplication with Toms amuxCRS (" << n_threads << " threads) ... " << std::flush; + } + RunTimeTimer run_timer; + CPUTimeTimer cpu_timer; + run_timer.start(); + cpu_timer.start(); + for (size_t k(0); k<n_mults; k++) { +// std::cout << "mult " << k << " ... " << std::flush; + mat.amux (1.0, x, y); +// std::cout << "ok" << std::endl; + } + cpu_timer.stop(); + run_timer.stop(); + +/* + // test result of matrix vector mult + std::cout << "simple test of matrix vector mult ... " << std::flush; + for (unsigned k(0); k<n; k++) { + if (std::fabs(y[k] - 2*(iA[k+1]-iA[k])) > std::numeric_limits<double>::min()) { + std::cout << "value y[" << k << "] = " << y[k] << " not equal to number of entries in row " << k << ", that is " << iA[k+1]-iA[k] << std::endl; + } + } +*/ + + if (verbose) { + std::cout << "done [" +<< cpu_timer.elapsed() << " sec cpu time], [" << run_timer.elapsed() << " sec run time]" << std::endl; + } else { + if (argc == 5) { + std::ofstream result_os (argv[4], std::ios::app); + if (result_os) { + result_os << cpu_timer.elapsed() << "\t" << run_timer.elapsed() << std::endl; + } + result_os.close(); + } else { + std::cout << cpu_timer.elapsed() << "\t" << run_timer.elapsed() << std::endl; + } + } + + delete [] x; + delete [] y; + + return 0; +} +