A 2nd implementation conforming to vector creation [need optimization]

This commit is contained in:
2020-11-30 18:42:09 +02:00
parent 2398be8e50
commit e3b96138c8
11 changed files with 863 additions and 161 deletions
+5
View File
@@ -14,14 +14,19 @@
#include <v3.h>
#include <v4.h>
/*
* Defines for different version of the exercise
*/
#define V12 2
#define V3 3
#define V4 4
// Fail-safe verision selection
#if !defined CODE_VERSION
#define CODE_VERSION V4
#endif
// matrix alias template dispatcher based on pre-define flag from compiler (see Makefile)
#if CODE_VERSION == V12
using namespace v12;
using matrix = v12::matrix;
+249 -66
View File
@@ -168,25 +168,42 @@ Matrix<DataType, IndexType, Type> make_Matrix(IndexType s) {
return Matrix<DataType, IndexType, Type>(new DataType[Matrix<DataType, IndexType, Type>::capacity(s)], s);
}
template<typename DataType, typename IndexType>
using CooVal = std::tuple<DataType, IndexType, IndexType>;
/**
* A simple sparse matrix implementation.
*
* We use CSC format and provide get/set functionalities for each (i,j) item
* on the matrix. We also provide a () overload using a proxy SpMatVal object.
* This way the user can:
* \code
* auto v = A(3,4);
* A(3, 4) = 7;
* \endcode
*
* We also provide getCol() and getRow() functions witch return a viwer/iterator to rows and
* columns of the matrix. In the case of a symmetric matrix instead of a row we return the
* equivalent column. This way we gain speed due to CSC format nature.
*
* @tparam DataType The type for values
* @tparam IndexType The type for indexes
* @tparam Type The Matrix type (FULL or SYMMETRIC)
*/
template<typename DataType, typename IndexType, MatrixType Type>
struct SpMat {
using dataType = DataType; //!< meta:export of underling data type
using indexType = IndexType; //!< meta:export of underling index type
static constexpr MatrixType matrixType = Type; //!< export of array type
friend class SpMatCol<DataType, IndexType>;
friend class SpMatRow<DataType, IndexType>;
friend class SpMatVal<DataType, IndexType>;
friend struct SpMatCol<DataType, IndexType>;
friend struct SpMatRow<DataType, IndexType>;
friend struct SpMatVal<DataType, IndexType>;
/*!
* \name Obj lifetime
*/
//! @{
//! allocation with init value ctor
//! Default ctor with optional memory allocations
SpMat(IndexType n=IndexType{}, IndexType nnz=IndexType{}) :
values(nnz, DataType{}),
rows(nnz, IndexType{}),
@@ -194,6 +211,7 @@ struct SpMat {
N(n),
NNZ(nnz) { }
//! A ctor using csc array data
SpMat(IndexType n, IndexType nnz, const IndexType* row, const IndexType* col) :
values(nnz, 1),
rows(row, row+nnz),
@@ -201,6 +219,7 @@ struct SpMat {
N(n),
NNZ(nnz) { }
//! ctor using csc array data with value array
SpMat(IndexType n, IndexType nnz, const DataType* v, const IndexType* row, const IndexType* col) :
values(v, v+nnz),
rows(row, row+nnz),
@@ -208,6 +227,7 @@ struct SpMat {
N(n),
NNZ(nnz) { }
//! ctor vectors of row/col and default value for values array
SpMat(IndexType n, IndexType nnz, const DataType v, const std::vector<IndexType>& row, const std::vector<IndexType>& col) :
values(nnz, v),
rows (row),
@@ -219,38 +239,72 @@ struct SpMat {
SpMat(SpMat&& a) noexcept { moves(std::move(a)); }
//! move
SpMat& operator=(SpMat&& a) noexcept { moves(std::move(a)); return *this; }
SpMat(const SpMat& a) = delete; //!< No copy ctor
SpMat& operator=(const SpMat& a) = delete; //!< No copy assignment
SpMat(const SpMat& a) = delete; //!< make sure there are no copies
SpMat& operator=(const SpMat& a) = delete; //!< make sure there are no copies
//! @}
//! \name Data exposure
//! @{
//! \return the dimension of the matrix
IndexType size() noexcept { return N; }
//! After construction size configuration tool
IndexType size(IndexType n) {
col_ptr.resize(n+1);
return N = n;
}
//! \return the NNZ of the matrix
IndexType capacity() noexcept { return NNZ; }
//! After construction NNZ size configuration tool
IndexType capacity(IndexType nnz) {
values.reserve(nnz);
rows.reserve(nnz);
return NNZ;
}
// getters for row arrays of the struct (unused)
std::vector<DataType>& getValues() noexcept { return values; }
std::vector<IndexType>& getRows() noexcept { return rows; }
std::vector<IndexType>& getCols() noexcept { return col_ptr; }
/*!
* Return a proxy SpMatVal object with read and write capabilities.
* @param i The row number
* @param j The column number
* @return tHE SpMatVal object
*/
SpMatVal<DataType, IndexType> operator()(IndexType i, IndexType j) {
return SpMatVal<DataType, IndexType>(this, get(i, j), i, j);
}
/*!
* A read item functionality using binary search to find the correct row
*
* @param i The row number
* @param j The column number
* @return The value of the item or DataType{} if is not present.
*/
DataType get(IndexType i, IndexType j) {
IndexType idx;
bool found;
std::tie(idx, found) =find_idx(rows, col_ptr[j], col_ptr[j+1], i);
return (found) ? values[idx] : 0;
IndexType end, idx =find_idx(rows, col_ptr[j], end=col_ptr[j+1], i);
return (idx != end) ? values[idx] : 0;
}
/*!
* A write item functionality.
*
* First we search if the matrix has already a value in (i, j) position.
* If so we just change it to a new value. If not we add the item on the matrix.
*
* @note
* We don't increase the NNZ value of the struct. We expect the user has already
* change the NNZ value to the right one using @see capacity() function.
*
* @param i The row number
* @param j The column number
* @return The new value of the item .
*/
DataType set(DataType v, IndexType i, IndexType j) {
IndexType idx; bool found;
std::tie(idx, found) = find_idx(rows, col_ptr[j], col_ptr[j+1], i);
std::tie(idx, found) = find2_idx(rows, col_ptr[j], col_ptr[j+1], i);
if (found)
return values[idx] = v; // we don't change NNZ even if we write "0"
else {
@@ -264,34 +318,47 @@ struct SpMat {
}
}
/*!
* Get a view of a CSC column
* @param j The column to get
* @return The SpMatCol object @see SpMatCol
*/
SpMatCol<DataType, IndexType> getCol(IndexType j) {
return SpMatCol<DataType, IndexType>(this, col_ptr[j], col_ptr[j+1]);
}
/*!
* Get a view of a CSC row
*
* In case of a SYMMETRIC matrix we can return a column instead.
*
* @param j The row to get
* @return The SpMatCol object @see SpMatCol
*/
template<MatrixType AT= Type>
std::enable_if_t<AT==MatrixType::SYMMETRIC, SpMatCol<DataType, IndexType>>
getRow(IndexType i) {
return getCol(i);
}
/*!
* Get a view of a CSC row
*
* @param j The row to get
* @return The SpMatRow object @see SpMatRow
*/
template<MatrixType AT= Type>
std::enable_if_t<AT==MatrixType::FULL, SpMatCol<DataType, IndexType>>
getRow(IndexType i) {
return SpMatRow<DataType, IndexType>(this, i);
}
// iterator support
// values only iterator support
DataType* begin() noexcept { return values.begin(); }
DataType* end() noexcept { return values.end(); }
//! @}
/*!
* \name Safe iteration API
*
* This api automates the iteration over the array based on
* MatrixType
*/
//! @{
//! A small iteration helper
template<typename F, typename... Args>
void for_each_in (IndexType begin, IndexType end, F&& lambda, Args&&... args) {
for (IndexType it=begin ; it<end ; ++it) {
@@ -299,15 +366,45 @@ struct SpMat {
}
}
//! @}
// operations
// friend operations for printing
template<typename D, typename I, MatrixType T> friend void print(SpMat<D, I, T>& mat);
template<typename D, typename I, MatrixType T> friend void print_dense(SpMat<D, I, T>& mat);
private:
// index-find helper
std::pair<IndexType, bool> find_idx(const std::vector<IndexType>& v, IndexType begin, IndexType end, IndexType match) {
/*!
* A small binary search implementation using index for begin-end instead of iterators.
*
* \param v Reference to vector to search
* \param begin The vector's index to begin
* \param end The vector's index to end
* \param match What to search
* @return The index of the item or end on failure.
*/
IndexType find_idx(const std::vector<IndexType>& v, IndexType begin, IndexType end, IndexType match) {
IndexType b = begin, e = end-1;
while (true) {
IndexType m = (b+e)/2;
if (v[m] == match) return m;
else if (b >= e) return end;
else {
if (v[m] < match) b = m +1;
else e = m -1;
}
}
return end;
}
/*!
* find helper for set using index for begin-end instead of iterators.
*
* We search for the item or a place to add the item.
* So we return the index if we find it. Otherwise we return the place to add it.
*
* \param v Reference to vector to search
* \param begin The vector's index to begin
* \param end The vector's index to end
* \param match What to search
*/
std::pair<IndexType, bool> find2_idx(const std::vector<IndexType>& v, IndexType begin, IndexType end, IndexType match) {
for ( ; begin < end ; ++begin) {
if (match == v[begin]) return std::make_pair(begin, true);
else if (match < v[begin]) return std::make_pair(begin, false);
@@ -324,38 +421,58 @@ private:
}
//! \name Data
//! @{
std::vector<DataType> values {};
std::vector<IndexType> rows{};
std::vector<IndexType> col_ptr{1,0};
IndexType N{0};
IndexType NNZ{0};
std::vector<DataType> values {}; //!< vector to store the values of the matrix
std::vector<IndexType> rows{}; //!< vector to store the row information
std::vector<IndexType> col_ptr{1,0}; //!< vector to stor the column pointers
IndexType N{0}; //!< The dimension of the matrix (square)
IndexType NNZ{0}; //!< The NNZ (capacity of the matrix)
//! @}
};
/*!
* A view/iterator hybrid object for SpMat columns.
*
* This object provides access to a column of a SpMat. The public functionalities
* allow data access using indexes instead of iterators. We prefer indexes over iterators
* because we can apply the same index to different inner vector of SpMat without conversion.
*
* @tparam DataType
* @tparam IndexType
*/
template<typename DataType, typename IndexType>
struct SpMatCol {
using owner_t = SpMat<DataType, IndexType>;
/*!
* ctor using column pointers for begin-end. own is pointer to SpMat.
*/
SpMatCol(owner_t* own, const IndexType begin, const IndexType end) noexcept :
owner_(own), index_(begin), begin_(begin), end_(end) {
vindex_ = vIndexCalc(index_);
}
SpMatCol() = default;
SpMatCol(const SpMatCol&) = delete;
SpMatCol& operator=(const SpMatCol&)= delete;
SpMatCol(const SpMatCol&) = delete; //!< make sure there are no copies
SpMatCol& operator=(const SpMatCol&)= delete; //!< make sure there are no copies
SpMatCol(SpMatCol&&) = default;
SpMatCol& operator=(SpMatCol&&) = default;
//! a simple dereference operator, like an iterator
DataType operator* () {
return get();
}
//! Increment operator acts on index(), like an iterator
SpMatCol& operator++ () { advance(); return *this; }
SpMatCol& operator++ (int) { SpMatCol& p = *this; advance(); return p; }
//! () operator acts as member access (like a view)
DataType operator()(IndexType x) {
return (x == index())? get() : DataType{};
}
//! = operator acts as member assignment (like a view)
DataType operator= (DataType v) { return owner_->values[index_] = v; }
// iterator like handlers
// these return a virtual index value based on the items position on the full matrix
// but the move of the index is just a ++ away.
IndexType index() noexcept { return vindex_; }
const IndexType index() const noexcept { return vindex_; }
IndexType begin() noexcept { return vIndexCalc(begin_); }
@@ -363,6 +480,13 @@ struct SpMatCol {
IndexType end() noexcept { return owner_->N; }
const IndexType end() const noexcept { return owner_->N; }
/*!
* Multiplication operator
* @tparam C Universal reference for the type right half site column
*
* @param c The right hand site matrix
* @return The value of the inner product of two vectors
*/
template <typename C>
DataType operator* (C&& c) {
static_assert(std::is_same<remove_cvref_t<C>, SpMatCol<DataType, IndexType>>(), "");
@@ -380,25 +504,42 @@ struct SpMatCol {
}
private:
//! small tool to increase the index pointers to SpMat matrix
void advance() noexcept {
++index_;
vindex_ = vIndexCalc(index_);
}
//! tool to translate between col_ptr indexes and SpMat "virtual" full matrix indexes
IndexType vIndexCalc(IndexType idx) {
return (idx < end_) ? owner_->rows[idx] : end();
}
//! small get tool
DataType get() { return owner_->values[index_]; }
owner_t* owner_{nullptr};
IndexType vindex_ {IndexType{}};
IndexType index_{IndexType{}};
IndexType begin_{IndexType{}};
IndexType end_{IndexType{}};
owner_t* owner_ {nullptr}; //!< Pointer to owner SpMat. SpMatCol is just a view
IndexType vindex_ {IndexType{}}; //!< Virtual index of full matrix
IndexType index_ {IndexType{}}; //!< index to SpMat::rows
IndexType begin_ {IndexType{}}; //!< beginning index of the column in SpMat::rows
IndexType end_ {IndexType{}}; //!< ending index of the column in SpMat::rows
};
/*!
* A view/iterator hybrid object for SpMat rows.
*
* This object provides access to a column of a SpMat. The public functionalities
* allow data access using indexes instead of iterators. We prefer indexes over iterators
* because we can apply the same index to different inner vector of SpMat without conversion.
*
* @tparam DataType
* @tparam IndexType
*/
template<typename DataType, typename IndexType>
struct SpMatRow {
using owner_t = SpMat<DataType, IndexType>;
/*!
* ctor using virtual full matrix row index. own is pointer to SpMat.
*/
SpMatRow(owner_t* own, const IndexType row) noexcept :
owner_(own), vindex_(IndexType{}), row_(row), index_(IndexType{}),
begin_(IndexType{}), end_(owner_->NNZ) {
@@ -410,20 +551,29 @@ struct SpMatRow {
advance();
}
SpMatRow() = default;
SpMatRow(const SpMatRow&) = delete;
SpMatRow& operator=(const SpMatRow&)= delete;
SpMatRow(const SpMatRow&) = delete; //!< make sure there are no copies
SpMatRow& operator=(const SpMatRow&)= delete; //!< make sure there are no copies
SpMatRow(SpMatRow&&) = default;
SpMatRow& operator=(SpMatRow&&) = default;
//! a simple dereference operator, like an iterator
DataType operator* () {
return get();
}
//! Increment operator acts on index(), like an iterator
//! here the increment is a O(N) process.
SpMatRow& operator++ () { advance(); return *this; }
SpMatRow& operator++ (int) { SpMatRow& p = *this; advance(); return p; }
//! () operator acts as member access (like a view)
DataType operator()(IndexType x) {
return (x == index())? get() : DataType{};
}
//! = operator acts as member assignment (like a view)
DataType operator= (DataType v) { return owner_->values[index_] = v; }
// iterator like handlers
// these return a virtual index value based on the items position on the full matrix
// but the move of the index is just a ++ away.
IndexType index() noexcept { return vindex_; }
const IndexType index() const noexcept { return vindex_; }
IndexType begin() noexcept { return vIndexCalc(begin_); }
@@ -431,6 +581,13 @@ struct SpMatRow {
IndexType end() noexcept { return owner_->N; }
const IndexType end() const noexcept { return owner_->N; }
/*!
* Multiplication operator
* @tparam C Universal reference for the type right half site column
*
* @param c The right hand site matrix
* @return The value of the inner product of two vectors
*/
template <typename C>
DataType operator* (C&& c) {
static_assert(std::is_same<remove_cvref_t<C>, SpMatCol<DataType, IndexType>>(), "");
@@ -447,70 +604,96 @@ struct SpMatRow {
return v;
}
private:
//! small tool to increase the index pointers to SpMat matrix
//! We have to search the entire rows vector in SpMat to find the next
//! virtual row position.
//! time complexity O(N)
void advance() noexcept {
do
++index_;
while(index_ != end_ && owner_->rows[index_] != row_);
vindex_ = vIndexCalc(index_);
}
//! tool to translate between col_ptr indexes and SpMat "virtual" full matrix indexes
IndexType vIndexCalc(IndexType idx) {
for(IndexType i =0 ; i<(owner_->N+1) ; ++i)
if (idx < owner_->col_ptr[i])
return i-1;
return end();
}
//! small get tool
DataType get() { return owner_->values[index_]; }
owner_t* owner_ {nullptr};
IndexType vindex_ {IndexType{}};
IndexType row_ {IndexType{}};
IndexType index_ {IndexType{}};
IndexType begin_ {IndexType{}};
IndexType end_ {IndexType{}};
owner_t* owner_ {nullptr}; //!< Pointer to owner SpMat. SpMatCol is just a view
IndexType vindex_ {IndexType{}}; //!< Virtual index of full matrix
IndexType row_ {IndexType{}}; //!< The virtual full matrix row of the object
IndexType index_ {IndexType{}}; //!< index to SpMat::rows
IndexType begin_ {IndexType{}}; //!< beginning index of the column in SpMat::rows
IndexType end_ {IndexType{}}; //!< ending index of the column in SpMat::rows
};
/*!
* A proxy SpMat value object/view.
*
* This object acts as proxy to provide read/write access to an SpMat item.
*
* @tparam DataType The type of the values of the SpMat matrix
* @tparam IndexType The type of the indexes of the SpMat matrix
*/
template<typename DataType, typename IndexType>
struct SpMatVal {
using owner_t = SpMat<DataType, IndexType>;
//!< ctor using all value-row-column data, plus a pointer to owner SpMat object
SpMatVal(owner_t* own, DataType v, IndexType i, IndexType j) :
owner_(own), v_(v), i_(i), j_(j) { }
SpMatVal() = default;
SpMatVal(const SpMatVal&) = delete;
SpMatVal& operator=(const SpMatVal&) = delete;
SpMatVal(const SpMatVal&) = delete; //!< make sure there are no copies
SpMatVal& operator=(const SpMatVal&) = delete; //!< make sure there are no copies
SpMatVal(SpMatVal&&) = default;
SpMatVal& operator=(SpMatVal&&) = default;
//! Operator to return the DataType value implicitly
operator DataType() { return v_; }
//! Operator to write back to owner the assigned value
//! for ex: A(2,3) = 5;
SpMatVal& operator=(DataType v) {
v_ = v;
owner_->set(v_, i_, j_);
return *this;
}
private:
owner_t* owner_{nullptr};;
DataType v_{DataType{}};
IndexType i_{IndexType{}};
IndexType j_{IndexType{}};
owner_t* owner_{nullptr}; //!< Pointer to owner SpMat. SpMatVal is just a view.
DataType v_{DataType{}}; //!< The value of the row-column pair (for speed)
IndexType i_{IndexType{}}; //!< The row
IndexType j_{IndexType{}}; //!< the column
};
enum class InputMatrix{
GENERATE,
MTX
};
//! enumerator for input matrix type.
enum class InputMatrix{ UNSPECIFIED, GENERATE, MTX };
//! enumerator for output handling
enum class OutputMode{ STD, FILE };
/*!
* Session option for each invocation of the executable
*/
struct session_t {
std::size_t size {0};
double probability {0};
InputMatrix inputMatrix {InputMatrix::GENERATE};
std::ifstream mtxFile {};
std::size_t print_size {80};
bool timing {false};
bool print {false};
bool makeSymmetric {false};
InputMatrix inputMatrix {InputMatrix::UNSPECIFIED}; //!< Source of the matrix
std::ifstream mtxFile {}; //!< matrix file in MatrixMarket format
std::size_t gen_size {}; //!< size of the matrix if we select to generate a random one
double gen_prob {}; //!< probability of the binomial distribution for the matrix
//!< if we generate one
OutputMode outputMode {OutputMode::STD}; //!< Type of the output file
std::ofstream outFile {}; //!< File to use for output
std::size_t max_threads {}; //!< Maximum threads to use
bool timing {false}; //!< Enable timing prints of the program
bool verbose {false}; //!< Flag to enable verbose output to stdout
bool makeSymmetric {true}; //!< symmetric matrix creation flag (true by default)
bool validate_mtx {false}; //!< Flag to request mtx input data triangular validation.
bool print_count {false}; //!< Flag to request total count printing
bool mtx_print {false}; //!< matrix print flag
std::size_t mtx_print_size {}; //!< matrix print size
};
extern session_t session;
+108 -25
View File
@@ -17,6 +17,10 @@
#include <impl.hpp>
#include <config.h>
/*!
* A small RAII utility to memory allocation arrays.
* @tparam T The type of pointer for the memory
*/
template <typename T>
struct buffer_t {
buffer_t(size_t s) { p = new T[s]; }
@@ -34,8 +38,14 @@ private:
T* p{nullptr};
};
/*!
* A toolbox for MatrixMarket format handling
*/
struct Mtx {
/*!
* A template version of the coo2csc function provided by PDS lab stuff.
*/
template<typename I>
static void coo2csc(I *row, I *col, I const* row_coo, I const* col_coo, I nnz, I n, I isOneBased) {
// ----- cannot assume that input is already 0!
@@ -70,6 +80,12 @@ struct Mtx {
}
}
/*!
* Utility to check if a matrix input is strictly triangular or not.
* @tparam I Index type
* @param file Reference to input file stream
* @return The status of the operation
*/
template<typename I>
static bool is_triangular (std::ifstream& file) {
std::string line, token;
@@ -105,6 +121,14 @@ struct Mtx {
return true;
}
/*!
* A utility to load an MatrixMarket file to memory
* @tparam DataT The data type
* @tparam IndexT The indexes type
* @param M Reference to matrix for output
* @param file Reference to input file stream to read from
* @return The status of the operation
*/
template<typename DataT, typename IndexT, MatrixType MatrixT>
static bool load (SpMat<DataT, IndexT, MatrixT>& M, std::ifstream& file) {
std::string line, token;
@@ -139,60 +163,119 @@ struct Mtx {
if (line[0] == '%') continue;
IndexT i, j;
ss >> i >> j;
if (session.makeSymmetric) {
if (LU == Z) {
LU = (i<j) ? UPPER: LOWER;
}
if ((LU==LOWER && j<i) || (LU==UPPER && i<j)) {
coo_row[cnt] = i;
coo_col[cnt++] = j;
if (LU == Z) {
LU = (i<j) ? UPPER: LOWER;
}
// ignore all values outside the triangle area
if ((LU==LOWER && j<i) || (LU==UPPER && i<j)) {
coo_row[cnt] = i;
coo_col[cnt++] = j;
if (session.makeSymmetric) {
coo_row[cnt] = j;
coo_col[cnt++] = i;
}
}
else {
coo_row[cnt] = i;
coo_col[cnt++] = j;
}
break;
}
}
coo2csc(&row[0], &col[0], &coo_row[0], &coo_col[0], cnt, n1, 1);
M = SpMat<DataT, IndexT, MatrixT>(n1, cnt, &row[0], &col[0]);
return true;
if (cnt) {
// convert and construct
coo2csc(&row[0], &col[0], &coo_row[0], &coo_col[0], cnt, n1, 1);
M = SpMat<DataT, IndexT, MatrixT>(n1, cnt, &row[0], &col[0]);
return true;
}
return false;
}
};
/*!
* A small timing utility based on chrono.
*/
struct Timing{
using Tpoint = std::chrono::steady_clock::time_point;
using microseconds = std::chrono::microseconds;
using milliseconds = std::chrono::milliseconds;
using seconds = std::chrono::seconds;
//! tool to mark the starting point
Tpoint start () noexcept { return start_ = std::chrono::steady_clock::now(); }
//! tool to mark the ending point
Tpoint stop () noexcept { return stop_ = std::chrono::steady_clock::now(); }
auto dt () noexcept {
return std::chrono::duration_cast<std::chrono::microseconds>(stop_ - start_).count();
}
void print_dt () noexcept {
auto t = stop_ - start_;
if (std::chrono::duration_cast<microseconds>(t).count() < 10000)
std::cout << "time: " << std::to_string(std::chrono::duration_cast<microseconds>(t).count()) << " [usec]\n";
else if (std::chrono::duration_cast<milliseconds>(t).count() < 10000)
std::cout << "time: " << std::to_string(std::chrono::duration_cast<milliseconds>(t).count()) << " [msec]\n";
else
std::cout << "time: " << std::to_string(std::chrono::duration_cast<seconds>(t).count()) << " [sec]\n";
//! tool to print the time interval
void print_dt (const char* what) noexcept {
if (session.timing) {
auto t = stop_ - start_;
if (std::chrono::duration_cast<microseconds>(t).count() < 10000)
std::cout << "[Timing]: " << what << ": " << std::to_string(std::chrono::duration_cast<microseconds>(t).count()) << " [usec]\n";
else if (std::chrono::duration_cast<milliseconds>(t).count() < 10000)
std::cout << "[Timing]: " << what << ": " << std::to_string(std::chrono::duration_cast<milliseconds>(t).count()) << " [msec]\n";
else
std::cout << "[Timing]: " << what << ": " << std::to_string(std::chrono::duration_cast<seconds>(t).count()) << " [sec]\n";
}
}
private:
Tpoint start_;
Tpoint stop_;
};
/*!
* A Logger for entire programm.
*/
struct Log {
struct Endl {} endl; //!< a tag objec to to use it as a new line request.
//! We provide logging via << operator
template<typename T>
Log& operator<< (T&& t) {
if (session.verbose) {
if (line_) {
std::cout << "[Log]: " << t;
line_ = false;
}
else
std::cout << t;
}
return *this;
}
// overload for special end line handling
Log& operator<< (Endl e) { (void)e;
if (session.verbose) {
std::cout << '\n';
line_ = true;
}
return *this;
}
private:
bool line_ {true};
};
extern Log logger;
//! Total count result printing function
template<typename F>
void triangle_out (value_t s, F&& f) {
f << "Total triangles: " << s << '\n';
}
//! vector out result printing function
template<typename F>
void vector_out (std::vector<value_t>& v, F&& f) {
size_t idx{};
f << "id,c3\n";
for (auto& it : v) f << idx++ <<',' << it << '\n';
f << '\n';
}
/*
* Public non-template api.
* We use matrix alias template. So it has to be defined somewhere
*/
void init_ER_graph (matrix& A, double p);
void print_ER_graph (matrix& A);
void print_graph (matrix& A);
void threads_info ();
#endif /* UTILS_H_ */
+27 -1
View File
@@ -9,13 +9,39 @@
#ifndef V3_H_
#define V3_H_
#include <iostream>
#include <mutex>
#include <impl.hpp>
#if defined CILK
#include <cilk/cilk.h>
#include <cilk/cilk_api.h>
#include <cilk/reducer_opadd.h>
#elif defined OMP
#include <omp.h>
#elif defined THREADS
#include <thread>
#else
#endif
namespace v3 {
//! Select a data representation suited for V3.
using matrix = SpMat<int, int>;
int triang_count (matrix& A);
using index_t = typename matrix::indexType; //!< syntactic sugar alias for index type
using value_t = typename matrix::dataType; //!< syntactic sugar alias for value type
/*
* Common api for all the versions
*/
int nworkers();
std::vector<value_t> triang_v(matrix& A);
value_t triang_count (std::vector<value_t>& c);
};
#endif /* V3_H_ */
+28 -1
View File
@@ -9,13 +9,40 @@
#ifndef V4_H_
#define V4_H_
#include <iostream>
#include <string>
#include <mutex>
#include <impl.hpp>
#if defined CILK
#include <cilk/cilk.h>
#include <cilk/cilk_api.h>
#include <cilk/reducer_opadd.h>
#elif defined OMP
#include <omp.h>
#elif defined THREADS
#include <thread>
#else
#endif
namespace v4 {
//! Select a data representation suited for V3.
using matrix = SpMat<int, int>;
int triang_count (matrix& A);
using index_t = typename matrix::indexType; //!< syntactic sugar alias for index type
using value_t = typename matrix::dataType; //!< syntactic sugar alias for value type
/*
* Common api for all the versions
*/
int nworkers();
std::vector<value_t> triang_v(matrix& A);
value_t triang_count (std::vector<value_t>& c);
};
#endif /* V4_H_ */