Skip to content
This repository has been archived by the owner on Jun 15, 2023. It is now read-only.

Commit

Permalink
Performance and bugfix update
Browse files Browse the repository at this point in the history
* moved all reordering capabilities to separate branch in order to boost performance
* avoid copies wherever possible. Copying a dd::Edge requires 3x the memory of passing it by reference. Additionally, passing const references mitigates unwanted side effects.
* fixed bug in dd::Package::add2 where the wrong value of the complex numbers was retrieved
* removed unused parameters in DDexport

Signed-off-by: Lukas Burgholzer <lukas.burgholzer@jku.at>
  • Loading branch information
burgholzer committed Feb 9, 2021
1 parent a6f611d commit 14730c6
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 1,087 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ endif()

project( dd_package
LANGUAGES CXX
VERSION 1.1.1
VERSION 1.2.0
DESCRIPTION "Library to handle decisions diagrams and corresponding operations")

set_property(GLOBAL PROPERTY USE_FOLDERS ON)
Expand Down
4 changes: 2 additions & 2 deletions include/DDexport.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ namespace dd {
std::ostream& matrixEdge(const Edge& from, const Edge& to, short idx, std::ostream& os, bool edgeLabels=false, bool classic=false);
std::ostream& coloredMatrixEdge(const Edge& from, const Edge& to, short idx, std::ostream& os, bool edgeLabels=false, bool classic=false);

std::ostream& vectorEdge(const Edge& from, const Edge& to, short idx, std::ostream& os, bool edgeLabels=false, bool classic=false);
std::ostream& coloredVectorEdge(const Edge& from, const Edge& to, short idx, std::ostream& os, bool edgeLabels=false, bool classic=false);
std::ostream& vectorEdge(const Edge& from, const Edge& to, short idx, std::ostream& os, bool edgeLabels = false);
std::ostream& coloredVectorEdge(const Edge& from, const Edge& to, short idx, std::ostream& os, bool edgeLabels = false);

void toDot(const Edge& e, std::ostream& os, bool isVector = false, bool colored=true, bool edgeLabels=false, bool classic=false);
void export2Dot(Edge basic, const std::string& outputFilename, bool isVector = false, bool colored=true, bool edgeLabels=false, bool classic=false, bool show = true);
Expand Down
98 changes: 27 additions & 71 deletions include/DDpackage.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,6 @@ namespace dd {
constexpr unsigned int LIST_CHUNK_SIZE = 2000;
constexpr unsigned short MAXN = 128; // max no. of inputs

enum ComputeMatrixPropertiesMode {
Disabled, Enabled, Recompute
};

typedef struct Node *NodePtr;

struct Edge {
Expand All @@ -63,12 +59,9 @@ namespace dd {
struct Node {
NodePtr next; // link for unique table and available space chain
Edge e[NEDGE]; // edges out of this node
Complex normalizationFactor; // stores normalization factor
unsigned int ref; // reference count
short v; // variable index (nonterminal) value (-1 for terminal)
bool ident, symm; // special matrices flags
ComputeMatrixPropertiesMode computeMatrixProperties; // indicates whether to compute matrix properties
unsigned int reuseCount;
};

// list definitions for breadth first traversals (e.g. printing)
Expand Down Expand Up @@ -101,7 +94,6 @@ namespace dd {
transp,
conjTransp,
kron,
renormalize,
none,
ct_count //ct_count must be the final element

Expand Down Expand Up @@ -144,10 +136,6 @@ namespace dd {
short line[MAXN];
};

enum DynamicReorderingStrategy {
None, Sifting, Random, Window3
};

enum Mode {
Vector, Matrix, ModeCount
};
Expand Down Expand Up @@ -187,10 +175,9 @@ namespace dd {

unsigned int currentNodeGCLimit = GCLIMIT1; // current garbage collection limit
unsigned int currentComplexGCLimit = CN::GCLIMIT1; // current complex garbage collection limit
std::array<int, MAXN> active{ }; // number of active nodes for each variable
std::array<unsigned int, MAXN> active{ }; // number of active nodes for each variable
unsigned long nodecount = 0; // node count in unique table
unsigned long peaknodecount = 0; // records peak node count in unique table
// mostly for debugging in reordering

std::array<unsigned long, ct_count> nOps{}; // operation counters
std::array<unsigned long, ct_count> CTlook{}, CThit{}; // counters for gathering compute table hit stats
Expand All @@ -199,48 +186,39 @@ namespace dd {
std::vector<NodePtr> allocated_node_chunks;

Mode mode{Mode::Vector};
ComputeMatrixPropertiesMode computeMatrixProperties = Enabled; // enable/disable computation of matrix properties

/// private helper routines
void initComputeTable();
NodePtr getNode();


Edge multiply2(Edge& x, Edge& y, unsigned short var);
ComplexValue innerProduct(Edge x, Edge y, int var);
Edge multiply2(const Edge& x, const Edge& y, unsigned short var);
ComplexValue innerProduct(const Edge& x, const Edge& y, int var);
Edge trace(const Edge& a, const std::bitset<MAXN>& eliminate, unsigned short alreadyEliminated = 0);
Edge kronecker2(Edge x, Edge y);
Edge kronecker2(const Edge& x, const Edge& y);

void checkSpecialMatrices(NodePtr p);

static uintptr_t UThash(NodePtr p);
Edge UTlookup(Edge e, bool keep_node = false);
std::string UTcheck(Edge e) const;


Edge UT_update_node(Edge e, std::size_t previous_hash, Edge in);
Edge UTlookup(const Edge& e, bool keep_node = false);
std::string UTcheck(const Edge& e) const;

static inline unsigned long CThash(const Edge& a, const Edge& b, CTkind which);
static inline unsigned long CThash2(NodePtr a, const ComplexValue& aw, NodePtr b, const ComplexValue& bw, CTkind which);
static inline unsigned short TThash(unsigned short n, unsigned short t, const short line[]);

unsigned int nodeCount(const Edge& e, std::unordered_set<NodePtr>& v) const;
ComplexValue getVectorElement(Edge e, unsigned long long int element);
ComplexValue getVectorElement(const Edge& e, unsigned long long int element);
ListElementPtr newListElement();

public:
// edges pointing to zero and one DD constants
constexpr static Edge DDone{ terminalNode, ComplexNumbers::ONE };
constexpr static Edge DDzero{ terminalNode, ComplexNumbers::ZERO };

// The following variables are supposed to be read only. Tread carefully if you change them!

// The following variables are supposed to be read only. Treat carefully if you change them!
unsigned long long node_allocations = 0; // Number of nodes allocated by getNode()
unsigned long activeNodeCount = 0; // number of active nodes
unsigned long unnormalizedNodes = 0; // active nodes that need renormalization
unsigned int node_substitutions = 0; // number of nodes substituted during reordering
unsigned int node_collapses = 0; // number of nodes collapses during reordering
unsigned int exchange_base_cases = 0; // number of nodes substituted during reordering
unsigned long maxActive = 0; // maximum number of active nodes
unsigned long gc_calls{}; // number of calls to the garbage collector
unsigned long gc_runs{}; // number of times the GC actually ran
Expand Down Expand Up @@ -290,45 +268,28 @@ namespace dd {


// operations on DDs
Edge multiply(Edge x, Edge y);
Edge add(Edge x, Edge y);
Edge add2(Edge x, Edge y);
Edge multiply(const Edge& x, const Edge& y);
Edge add(const Edge& x, const Edge& y);
Edge add2(const Edge& x, const Edge& y);
Edge transpose(const Edge& a);
Edge conjugateTranspose(Edge a);
Edge normalize(Edge& e, bool cached);
Edge conjugateTranspose(const Edge& a);
Edge normalize(const Edge& e, bool cached);
Edge partialTrace(const Edge& a, const std::bitset<MAXN>& eliminate);
ComplexValue trace(const Edge& a);
ComplexValue innerProduct(Edge x, Edge y);
fp fidelity(Edge x, Edge y);
Edge kronecker(Edge x, Edge y);
Edge extend(Edge e, unsigned short h = 0, unsigned short l = 0);

// functions for dynamic reordering
void recomputeMatrixProperties(Edge in);
void markForMatrixPropertyRecomputation(Edge in);
void resetNormalizationFactor(Edge in, Complex defaultValue);
Edge renormalize(Edge in);
Edge renormalize2(Edge in);
void reuseNonterminal(short v, const Edge *edge, NodePtr p, Edge in);
void exchange(unsigned short i, unsigned short j);
dd::Edge exchange2(unsigned short i, unsigned short j, std::map<unsigned short, unsigned short> &varMap, Edge in);
void exchangeBaseCase(unsigned short i, Edge in);
void exchangeBaseCase2(NodePtr p, unsigned short index, Edge in);
Edge dynamicReorder(Edge in, std::map<unsigned short, unsigned short>& varMap, DynamicReorderingStrategy strat = None);
std::tuple<Edge, unsigned int, unsigned int> sifting(Edge in, std::map<unsigned short, unsigned short>& varMap);
Edge random(Edge in, std::map<unsigned short, unsigned short> &varMap, std::mt19937_64 &mt);
Edge window3(Edge in, std::map<unsigned short, unsigned short>& varMap);

ComplexValue innerProduct(const Edge& x, const Edge& y);
fp fidelity(const Edge& x, const Edge& y);
Edge kronecker(const Edge& x, const Edge& y);
Edge extend(const Edge& e, unsigned short h = 0, unsigned short l = 0);

// utility
/// Traverse DD and return product of edge weights along the way
ComplexValue getValueByPath(Edge e, std::string elements);
ComplexValue getValueByPath(const Edge& e, std::string elements);
/// Calculate the size of the DD pointed to by e
unsigned int size(const Edge& e);

// reference counting and garbage collection
void incRef(Edge &e);
void decRef(Edge &e);
void incRef(const Edge &e);
void decRef(const Edge &e);
void garbageCollect(bool force = false);

// checks
Expand All @@ -353,24 +314,19 @@ namespace dd {
void printDD(const Edge& e, unsigned int limit);
void printUniqueTable(unsigned short n);

void toDot(Edge e, std::ostream& oss, bool isVector = false);
void export2Dot(Edge basic, const std::string& outputFilename, bool isVector = false, bool show = true);
void toDot(const Edge& e, std::ostream& oss, bool isVector = false);
void export2Dot(const Edge& basic, const std::string& outputFilename, bool isVector = false, bool show = true);

// debugging
void debugnode(NodePtr p) const;
std::string debugnode_line(NodePtr p) const;
bool is_locally_consistent_dd(Edge e);
bool is_locally_consistent_dd2(Edge e);
bool is_globally_consistent_dd(Edge e);

void fill_consistency_counter(Edge edge, std::map<ComplexTableEntry*, long>& weight_map, std::map<NodePtr , unsigned long>& node_map);
void check_consistency_counter(Edge edge, const std::map<ComplexTableEntry*, long>& weight_map, const std::map<NodePtr , unsigned long>& node_map);
bool is_locally_consistent_dd(const Edge& e);
bool is_locally_consistent_dd2(const Edge& e);
bool is_globally_consistent_dd(const Edge& e);

void substitute_node(short index, Edge original, Edge substitute, Edge in);
void substitute_node_ut(short index, Edge original, Edge substitute, Edge in);
void substitute_node_dd(short index, Edge parent, Edge original, Edge substitute, Edge in);
void fill_consistency_counter(const Edge& edge, std::map<ComplexTableEntry*, long>& weight_map, std::map<NodePtr , unsigned long>& node_map);
void check_consistency_counter(const Edge& edge, const std::map<ComplexTableEntry*, long>& weight_map, const std::map<NodePtr , unsigned long>& node_map);

void check_node_is_really_gone(NodePtr pNode, Edge in);
};
}
#endif
1 change: 0 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ add_library(${PROJECT_NAME}
${CMAKE_CURRENT_SOURCE_DIR}/DDdebug.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DDcomplex.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DDexport.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DDreorder.cpp
${${PROJECT_NAME}_SOURCE_DIR}/include/DDpackage.h
${${PROJECT_NAME}_SOURCE_DIR}/include/DDcomplex.h
${${PROJECT_NAME}_SOURCE_DIR}/include/DDexport.h)
Expand Down
30 changes: 5 additions & 25 deletions src/DDdebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ namespace dd {
std::stringstream sst;
sst << "0x" << std::hex << reinterpret_cast<std::uintptr_t>(p) << std::dec
<< "[v=" << p->v
<< " nf=" << p->normalizationFactor
<< " uc=" << p->reuseCount
<< " ref=" << p->ref
<< " hash=" << UThash(p)
<< " UT=" << UTcheck({p, CN::ZERO})
Expand All @@ -42,20 +40,7 @@ namespace dd {
std::clog << std::flush;
}

void Package::check_node_is_really_gone(NodePtr pNode, Edge in) {
if(isTerminal(in)) {
return;
}
if(in.p == pNode) {
throw std::runtime_error("Found forbidden node");
}

for(const auto& child: in.p->e) {
check_node_is_really_gone(pNode, child);
}
}

bool Package::is_locally_consistent_dd(Edge e) {
bool Package::is_locally_consistent_dd(const Edge& e) {
assert(CN::ONE.r->val == 1 && CN::ONE.i->val == 0);
assert(CN::ZERO.r->val == 0 && CN::ZERO.i->val == 0);

Expand All @@ -68,7 +53,7 @@ namespace dd {
return result;
}

bool Package::is_locally_consistent_dd2(Edge e) {
bool Package::is_locally_consistent_dd2(const Edge& e) {
auto *ptr_r = CN::get_sane_pointer(e.w.r);
auto *ptr_i = CN::get_sane_pointer(e.w.i);

Expand Down Expand Up @@ -106,7 +91,7 @@ namespace dd {
return true;
}

bool Package::is_globally_consistent_dd(Edge e) {
bool Package::is_globally_consistent_dd(const Edge& e) {
std::map<ComplexTableEntry *, long> weight_counter;
std::map<NodePtr, unsigned long> node_counter;
//std::clog << "CHECKING GLOBAL CONSISTENCY\n";
Expand All @@ -128,7 +113,7 @@ namespace dd {
return true;
}

void Package::fill_consistency_counter(Edge edge, std::map<ComplexTableEntry *, long> &weight_map, std::map<NodePtr, unsigned long> &node_map) {
void Package::fill_consistency_counter(const Edge& edge, std::map<ComplexTableEntry *, long> &weight_map, std::map<NodePtr, unsigned long> &node_map) {
weight_map[CN::get_sane_pointer(edge.w.r)]++;
weight_map[CN::get_sane_pointer(edge.w.i)]++;

Expand All @@ -148,12 +133,10 @@ namespace dd {
}


void Package::check_consistency_counter(Edge edge, const std::map<ComplexTableEntry *, long> &weight_map, const std::map<NodePtr, unsigned long> &node_map) {
void Package::check_consistency_counter(const Edge& edge, const std::map<ComplexTableEntry *, long> &weight_map, const std::map<NodePtr, unsigned long> &node_map) {
auto* r_ptr = CN::get_sane_pointer(edge.w.r);
auto* i_ptr = CN::get_sane_pointer(edge.w.i);

assert(edge.p->normalizationFactor == CN::ONE);

if(weight_map.at(r_ptr) > r_ptr->ref && r_ptr != CN::ONE.r && r_ptr != CN::ZERO.i) {
std::clog << "\nOffending weight: " << edge.w << "\n";
std::clog << "Bits: " << std::hexfloat << CN::val(edge.w.r) << " " << CN::val(edge.w.i) << std::defaultfloat << "\n";
Expand Down Expand Up @@ -220,7 +203,6 @@ namespace dd {
auto hitRatioAdd = CTlook[ad] == 0 ? 0 : (double) CThit[ad] / (double) CTlook[ad];
auto hitRatioMul = CTlook[mult] == 0 ? 0 : (double) CThit[mult] / (double) CTlook[mult];
auto hitRatioKron = ((CTlook[kron] == 0) ? 0 : (double) CThit[kron] / (double) CTlook[kron]);
auto hitRatioRenormalize = ((CTlook[CTkind::renormalize] == 0) ? 0 : (double) CThit[CTkind::renormalize] / (double) CTlook[CTkind::renormalize]);


std::cout << "\nDD statistics:"
Expand All @@ -230,12 +212,10 @@ namespace dd {
<< "\n add: " << nOps[ad]
<< "\n mult: " << nOps[mult]
<< "\n kron: " << nOps[kron]
<< "\n renormalize: " << nOps[CTkind::renormalize]
<< "\n Compute table hit ratios (hits/looks/ratio):"
<< "\n adds: " << CThit[ad] << " / " << CTlook[ad] << " / " << hitRatioAdd
<< "\n mult: " << CThit[mult] << " / " << CTlook[mult] << " / " << hitRatioMul
<< "\n kron: " << CThit[kron] << " / " << CTlook[kron] << " / " << hitRatioKron
<< "\n renormalize: " << CThit[CTkind::renormalize] << " / " << CTlook[CTkind::renormalize] << " / " << hitRatioRenormalize
<< "\n UniqueTable:"
<< "\n Collisions: " << UTcol
<< "\n Matches: " << UTmatch
Expand Down
8 changes: 4 additions & 4 deletions src/DDexport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ namespace dd {
return os;
}

std::ostream& vectorEdge(const Edge& from, const Edge& to, short idx, std::ostream& os, bool edgeLabels, bool classic) {
std::ostream& vectorEdge(const Edge& from, const Edge& to, short idx, std::ostream& os, bool edgeLabels) {
auto fromlabel = ((uintptr_t)from.p & 0x001fffffu) >> 1u;
auto tolabel = ((uintptr_t)to.p & 0x001fffffu) >> 1u;

Expand All @@ -259,7 +259,7 @@ namespace dd {
return os;
}

std::ostream& coloredVectorEdge(const Edge& from, const Edge& to, short idx, std::ostream& os, bool edgeLabels, bool classic) {
std::ostream& coloredVectorEdge(const Edge& from, const Edge& to, short idx, std::ostream& os, bool edgeLabels) {
auto fromlabel = ((uintptr_t)from.p & 0x001fffffu) >> 1u;
auto tolabel = ((uintptr_t)to.p & 0x001fffffu) >> 1u;

Expand Down Expand Up @@ -346,9 +346,9 @@ namespace dd {

if (isVector) {
if (colored) {
coloredVectorEdge(*node, edge, i, oss, edgeLabels, classic);
coloredVectorEdge(*node, edge, i, oss, edgeLabels);
} else {
vectorEdge(*node, edge, i, oss, edgeLabels, classic);
vectorEdge(*node, edge, i, oss, edgeLabels);
}
} else {
if (colored) {
Expand Down
Loading

0 comments on commit 14730c6

Please sign in to comment.