Commit 51513e15 authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

Fixing erroneous git push



Signed-off-by: Mccaskey, Alex's avatarAlex McCaskey <mccaskeyaj@ornl.gov>
parent 10a01bf8
set(LIBRARY_NAME exatn-runtime-graph)
file(GLOB SRC boost/DirectedBoostGraph.cpp GraphActivator.cpp)
file(GLOB SRC
tensor_exec_state.cpp
boost/directed_boost_graph.cpp
graph_activator.cpp)
usfunctiongetresourcesource(TARGET ${LIBRARY_NAME} OUT SRC)
usfunctiongeneratebundleinit(TARGET ${LIBRARY_NAME} OUT SRC)
......
#include "directed_boost_graph.hpp"
using namespace boost;
namespace exatn {
namespace runtime {
DirectedBoostGraph::DirectedBoostGraph() {
dag_ = std::make_shared<d_adj_list>();
}
VertexIdType DirectedBoostGraph::addOperation(std::shared_ptr<TensorOperation> op) {
auto vid = add_vertex(*dag_);
(*dag_)[vid].properties = std::move(std::make_shared<TensorOpNode>(op));
(*dag_)[vid].properties->setId(vid); //DAG node id is stored in the node properties
return vid; //new node id in the DAG
}
void DirectedBoostGraph::addDependency(VertexIdType dependent, VertexIdType dependee) {
add_edge(vertex(dependent,*dag_), vertex(dependee,*dag_), *dag_);
return;
}
TensorOpNode & DirectedBoostGraph::getNodeProperties(VertexIdType vertex_id) {
return *((*dag_)[vertex_id].properties);
}
void DirectedBoostGraph::setNodeExecuting(VertexIdType vertex_id) {
(*dag_)[vertex_id].properties->setExecuting();
return;
}
void DirectedBoostGraph::setNodeExecuted(VertexIdType vertex_id, int error_code) {
(*dag_)[vertex_id].properties->setExecuted(error_code);
return;
}
bool DirectedBoostGraph::nodeExecuting(VertexIdType vertex_id) {
return (*dag_)[vertex_id].properties->isExecuting();
}
bool DirectedBoostGraph::nodeExecuted(VertexIdType vertex_id) {
return (*dag_)[vertex_id].properties->isExecuted();
}
bool DirectedBoostGraph::dependencyExists(VertexIdType vertex_id1, VertexIdType vertex_id2) {
auto vid1 = vertex(vertex_id1, *dag_);
auto vid2 = vertex(vertex_id2, *dag_);
auto p = edge(vid1, vid2, *dag_);
return p.second;
}
std::size_t DirectedBoostGraph::degree(VertexIdType vertex_id) {
//return boost::degree(vertex(vertex_id, *dag_), *dag_);
return getNeighborList(vertex_id).size();
}
std::size_t DirectedBoostGraph::getNumDependencies() {
return num_edges(*dag_);
}
std::size_t DirectedBoostGraph::getNumNodes() {
return num_vertices(*dag_);
}
std::vector<VertexIdType> DirectedBoostGraph::getNeighborList(VertexIdType vertex_id) {
std::vector<VertexIdType> l;
typedef typename boost::property_map<d_adj_list, boost::vertex_index_t>::type IndexMap;
IndexMap indexMap = get(boost::vertex_index, *dag_);
typedef typename boost::graph_traits<d_adj_list>::adjacency_iterator adjacency_iterator;
std::pair<adjacency_iterator, adjacency_iterator> neighbors =
boost::adjacent_vertices(vertex(vertex_id, *dag_), *dag_);
for (; neighbors.first != neighbors.second; ++neighbors.first) {
VertexIdType neighborIdx = indexMap[*neighbors.first];
l.push_back(neighborIdx);
}
return l;
}
void DirectedBoostGraph::computeShortestPath(VertexIdType startIndex,
std::vector<double> & distances,
std::vector<VertexIdType> & paths) {
typename property_map<d_adj_list, edge_weight_t>::type weightmap =
get(edge_weight, *dag_);
std::vector<VertexIdType> p(num_vertices(*dag_));
std::vector<std::size_t> d(num_vertices(*dag_));
d_vertex_type s = vertex(startIndex, *dag_);
dijkstra_shortest_paths(
*dag_, s,
predecessor_map(boost::make_iterator_property_map(
p.begin(), get(boost::vertex_index, *dag_)))
.distance_map(boost::make_iterator_property_map(
d.begin(), get(boost::vertex_index, *dag_))));
for (const auto & di: d) distances.push_back(static_cast<double>(di));
for (const auto & pi: p) paths.push_back(pi);
return;
}
} // namespace runtime
} // namespace exatn
/** ExaTN:: Tensor Runtime: Directed acyclic graph of tensor operations
REVISION: 2019/07/24
Copyright (C) 2018-2019 Tiffany Mintz, Dmitry Lyakh, Alex McCaskey
Copyright (C) 2018-2019 Oak Ridge National Laboratory (UT-Battelle)
Rationale:
(a) Tensor graph is a directed acyclic graph in which vertices
represent tensor operations and directed edges represent
dependencies between them: A directed edge from node1 to
node2 indicates that node1 depends on node2. Each DAG node
has its unique integer vertex id (VertexIdType) returned
when the node is added to the DAG.
(b) The tensor graph contains:
1. The DAG implementation (in the directed Boost graph subclass);
2. The DAG execution state (TensorExecState data member).
**/
#ifndef EXATN_RUNTIME_DAG_HPP_
#define EXATN_RUNTIME_DAG_HPP_
#include "tensor_graph.hpp"
#include "tensor_operation.hpp"
#include "tensor.hpp"
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dag_shortest_paths.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/eccentricity.hpp>
#include <boost/graph/exterior_property.hpp>
#include <boost/graph/floyd_warshall_shortest.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/property_map/property_map.hpp>
#include <type_traits>
#include <string>
#include <memory>
#include <mutex>
using namespace boost;
namespace exatn {
namespace runtime {
struct DirectedBoostVertex {
std::shared_ptr<TensorOpNode> properties; //properties of the DAG node
};
using d_adj_list = adjacency_list<vecS, vecS, directedS, DirectedBoostVertex,
boost::property<boost::edge_weight_t, double>>;
using DirectedGraphType = std::shared_ptr<d_adj_list>;
using d_vertex_type = typename boost::graph_traits<adjacency_list<
vecS, vecS, directedS, DirectedBoostVertex,
boost::property<boost::edge_weight_t, double>>>::vertex_descriptor;
using d_edge_type = typename boost::graph_traits<adjacency_list<
vecS, vecS, directedS, DirectedBoostVertex,
boost::property<boost::edge_weight_t, double>>>::edge_descriptor;
static_assert(std::is_same<d_vertex_type,VertexIdType>::value,"Vertex id type mismatch!");
class DirectedBoostGraph : public TensorGraph {
public:
DirectedBoostGraph();
DirectedBoostGraph(const DirectedBoostGraph &) = delete;
DirectedBoostGraph & operator=(const DirectedBoostGraph &) = delete;
DirectedBoostGraph(DirectedBoostGraph &&) noexcept = default;
DirectedBoostGraph & operator=(DirectedBoostGraph &&) noexcept = default;
~DirectedBoostGraph() = default;
VertexIdType addOperation(std::shared_ptr<TensorOperation> op) override;
void addDependency(VertexIdType dependent,
VertexIdType dependee) override;
TensorOpNode & getNodeProperties(VertexIdType vertex_id) override;
void setNodeExecuting(VertexIdType vertex_id) override;
void setNodeExecuted(VertexIdType vertex_id,
int error_code = 0) override;
bool nodeExecuting(VertexIdType vertex_id) override;
bool nodeExecuted(VertexIdType vertex_id) override;
bool dependencyExists(VertexIdType vertex_id1,
VertexIdType vertex_id2) override;
std::size_t degree(VertexIdType vertex_id) override;
std::size_t getNumDependencies() override;
std::size_t getNumNodes() override;
std::vector<VertexIdType> getNeighborList(VertexIdType vertex_id) override;
void computeShortestPath(VertexIdType startIndex,
std::vector<double> & distances,
std::vector<VertexIdType> & paths) override;
const std::string name() const override {
return "boost-digraph";
}
const std::string description() const override {
return "Directed acyclic graph of tensor operations";
}
std::shared_ptr<TensorGraph> clone() override {
return std::make_shared<DirectedBoostGraph>();
}
inline void lock() {mtx_.lock();}
inline void unlock() {mtx_.unlock();}
protected:
DirectedGraphType dag_; //std::shared_ptr<d_adj_list>
std::recursive_mutex mtx_; //object access mutex
};
} // namespace runtime
} // namespace exatn
#endif //EXATN_RUNTIME_DAG_HPP_
exatn_add_test(DirectedBoostGraphTester DirectedBoostGraphTester.cpp)
target_include_directories(DirectedBoostGraphTester PRIVATE ${CMAKE_SOURCE_DIR}/src/runtime/graph/boost ${CMAKE_SOURCE_DIR}/src/runtime/graph ${CMAKE_SOURCE_DIR}/src/exatn ${CMAKE_SOURCE_DIR}/tpls/mpark-variant)
target_link_libraries(DirectedBoostGraphTester PRIVATE exatn-runtime-graph Boost::graph)
target_link_libraries(DirectedBoostGraphTester PRIVATE exatn-numerics exatn-runtime-graph Boost::graph)
......@@ -11,14 +11,14 @@
* Alexander J. McCaskey - initial API and implementation
*******************************************************************************/
#include <gtest/gtest.h>
#include "DirectedBoostGraph.hpp"
#include "directed_boost_graph.hpp"
using namespace boost;
using namespace exatn;
TEST(DirectedGraphTester, checkConstruction) {
// Implement this when we have TensorOp
// Implement this when we have TensorOperation
}
int main(int argc, char **argv) {
......
#include "directed_boost_graph.hpp"
#include "cppmicroservices/BundleActivator.h"
#include "cppmicroservices/BundleContext.h"
#include <memory>
#include <set>
using namespace cppmicroservices;
namespace {
/**
*/
class US_ABI_LOCAL GraphActivator : public BundleActivator {
public:
GraphActivator() {}
/**
*/
void Start(BundleContext context) {
auto g = std::make_shared<exatn::runtime::DirectedBoostGraph>();
context.RegisterService<exatn::runtime::TensorGraph>(g);
}
/**
*/
void Stop(BundleContext /*context*/) {}
};
} // namespace
CPPMICROSERVICES_EXPORT_BUNDLE_ACTIVATOR(GraphActivator)
/** ExaTN:: Tensor Runtime: Tensor graph execution state
REVISION: 2019/07/23
Copyright (C) 2018-2019 Dmitry Lyakh, Tiffany Mintz, Alex McCaskey
Copyright (C) 2018-2019 Oak Ridge National Laboratory (UT-Battelle)
**/
#include "tensor_exec_state.hpp"
#include <iostream>
namespace exatn {
namespace runtime {
int TensorExecState::incrTensorUpdate(const Tensor & tensor)
{
auto tens_hash = tensor.getTensorHash();
this->lock();
auto iter = tensor_update_cnt_.find(tens_hash);
if(iter == tensor_update_cnt_.end()){
auto pos = tensor_update_cnt_.emplace(std::make_pair(tens_hash,0));
iter = pos.first;
}
auto & count = iter->second;
++count;
this->unlock();
return count;
}
int TensorExecState::decrTensorUpdate(const Tensor & tensor)
{
auto tens_hash = tensor.getTensorHash();
this->lock();
auto iter = tensor_update_cnt_.find(tens_hash);
assert(iter != tensor_update_cnt_.end());
auto & count = iter->second;
--count;
this->unlock();
return count;
}
void TensorExecState::updateLastTensorRead(const Tensor & tensor, VertexIdType node_id)
{
auto tens_hash = tensor.getTensorHash();
this->lock();
auto iter = tensor_last_read_.find(tens_hash);
if(iter == tensor_last_read_.end()){
auto pos = tensor_last_read_.emplace(std::make_pair(tens_hash,node_id));
}else{
iter->second = node_id;
}
this->unlock();
return;
}
void TensorExecState::updateLastTensorWrite(const Tensor & tensor, VertexIdType node_id)
{
auto tens_hash = tensor.getTensorHash();
this->lock();
auto iter = tensor_last_write_.find(tens_hash);
if(iter == tensor_last_write_.end()){
auto pos = tensor_last_write_.emplace(std::make_pair(tens_hash,node_id));
}else{
iter->second = node_id;
}
this->unlock();
return;
}
void TensorExecState::clearLastTensorRead(const Tensor & tensor)
{
auto tens_hash = tensor.getTensorHash();
this->lock();
assert(tensor_last_read_.erase(tens_hash) == 1);
this->unlock();
return;
}
void TensorExecState::clearLastTensorWrite(const Tensor & tensor)
{
auto tens_hash = tensor.getTensorHash();
this->lock();
assert(tensor_last_write_.erase(tens_hash) == 1);
this->unlock();
return;
}
void TensorExecState::registerDependencyFreeNode(VertexIdType node_id)
{
this->lock();
nodes_ready_.emplace_back(node_id);
this->unlock();
return;
}
bool TensorExecState::extractDependencyFreeNode(VertexIdType * node_id)
{
this->lock();
bool empty = nodes_ready_.empty();
if(!empty){
*node_id = nodes_ready_.front();
nodes_ready_.pop_front();
}
this->unlock();
return !empty;
}
void TensorExecState::registerExecutingNode(VertexIdType node_id)
{
this->lock();
nodes_executing_.emplace_back(node_id);
this->unlock();
return;
}
bool TensorExecState::extractExecutingNode(VertexIdType * node_id)
{
this->lock();
bool empty = nodes_executing_.empty();
if(!empty){
*node_id = nodes_executing_.front();
nodes_executing_.pop_front();
}
this->unlock();
return !empty;
}
} // namespace runtime
} // namespace exatn
/** ExaTN:: Tensor Runtime: Tensor graph execution state
REVISION: 2019/07/23
Copyright (C) 2018-2019 Dmitry Lyakh, Tiffany Mintz, Alex McCaskey
Copyright (C) 2018-2019 Oak Ridge National Laboratory (UT-Battelle)
Rationale:
(a) Tensor graph is a directed acyclic graph in which vertices
represent tensor operations and directed edges represent
dependencies between them: A directed edge from node1 to
node2 indicates that node1 depends on node2. Each DAG node
has its unique integer vertex id (VertexIdType) returned
when the node is added to the DAG.
(b) The tensor graph contains:
1. The DAG implementation (in the DirectedBoostGraph subclass);
2. The DAG execution state (TensorExecState data member).
**/
#ifndef EXATN_RUNTIME_TENSOR_EXEC_STATE_HPP_
#define EXATN_RUNTIME_TENSOR_EXEC_STATE_HPP_
#include "tensor_operation.hpp"
#include "tensor.hpp"
#include <unordered_map>
#include <list>
#include <memory>
#include <mutex>
namespace exatn {
namespace runtime {
// Tensor Graph node id (DirectedBoostGraph vertex descriptor):
using VertexIdType = std::size_t; //must match with boost::graph vertex descriptor type
// Tensor implementation:
using numerics::TensorHashType; //each numerics::Tensor has its unique integer hash
using numerics::Tensor;
using numerics::TensorOperation;
class TensorExecState {
public:
TensorExecState() = default;
TensorExecState(const TensorExecState &) = delete;
TensorExecState & operator=(const TensorExecState &) = delete;
TensorExecState(TensorExecState &&) noexcept = default;
TensorExecState & operator=(TensorExecState &&) noexcept = default;
~TensorExecState() = default;
/** Registers an update operation on a tensor in the DAG.
Returns the updated outstanding update count on the tensor. **/
int incrTensorUpdate(const Tensor & tensor);
/** Registers completion of an update operation on a tensor in the DAG.
Returns the updated outstanding update count on the tensor. **/
int decrTensorUpdate(const Tensor & tensor);
/** Updates the last DAG node id performing a read on a given tensor. **/
void updateLastTensorRead(const Tensor & tensor, VertexIdType node_id);
/** Updates the last DAG node id performing a write on a given tensor. **/
void updateLastTensorWrite(const Tensor & tensor, VertexIdType node_id);
/** Clears the last read on a tensor **/
void clearLastTensorRead(const Tensor & tensor);
/** Clears the last write on a tensor. **/
void clearLastTensorWrite(const Tensor & tensor);
/** Registers a DAG node without dependencies. **/
void registerDependencyFreeNode(VertexIdType node_id);
/** Extracts a dependency-free node from the list.
Returns FALSE if no such node exists. **/
bool extractDependencyFreeNode(VertexIdType * node_id);
/** Registers a DAG node as being executed. **/
void registerExecutingNode(VertexIdType node_id);
/** Extracts an executed DAG node from the list. **/
bool extractExecutingNode(VertexIdType * node_id);
inline void lock() {mtx_.lock();}
inline void unlock() {mtx_.unlock();}
private:
/** Table for tracking the execution status on a given tensor:
Tensor Hash --> Number of outstanding update operations on the Tensor **/
std::unordered_map<TensorHashType,int> tensor_update_cnt_;
/** Table for tracking last read or write access on a given tensor:
Tensor Hash --> Last node of DAG performing read or write on the Tensor **/
std::unordered_map<TensorHashType,VertexIdType> tensor_last_read_;
std::unordered_map<TensorHashType,VertexIdType> tensor_last_write_;
/** List of dependency-free unexecuted DAG nodes **/
std::list<VertexIdType> nodes_ready_;
/** List of the currently executed DAG nodes **/
std::list<VertexIdType> nodes_executing_;
/** Object access mutex **/
std::recursive_mutex mtx_;
};
} // namespace runtime
} // namespace exatn
#endif //EXATN_RUNTIME_TENSOR_EXEC_STATE_HPP_
/** ExaTN:: Tensor Runtime: Directed acyclic graph of tensor operations
REVISION: 2019/07/23
Copyright (C) 2018-2019 Tiffany Mintz, Dmitry Lyakh, Alex McCaskey
Copyright (C) 2018-2019 Oak Ridge National Laboratory (UT-Battelle)
Rationale:
(a) Tensor graph is a directed acyclic graph in which vertices
represent tensor operations and directed edges represent
dependencies between them: A directed edge from node1 to
node2 indicates that node1 depends on node2. Each DAG node
has its unique integer vertex id (VertexIdType) returned
when the node is added to the DAG.
(b) The tensor graph contains:
1. The DAG implementation (in the directed Boost graph subclass);
2. The DAG execution state (TensorExecState data member).
**/
#ifndef EXATN_RUNTIME_TENSOR_GRAPH_HPP_
#define EXATN_RUNTIME_TENSOR_GRAPH_HPP_
#include "Identifiable.hpp"
#include "tensor_exec_state.hpp"
#include "tensor_operation.hpp"
#include "tensor.hpp"
#include <vector>
#include <memory>
#include <mutex>
namespace exatn {
namespace runtime {
// Tensor Graph node
class TensorOpNode {
public:
TensorOpNode():
op_(nullptr), is_noop_(true), executing_(false), executed_(false), error_(0)
{}
TensorOpNode(std::shared_ptr<TensorOperation> tens_op):
op_(tens_op), is_noop_(false), executing_(false), executed_(false), error_(0)
{}
TensorOpNode(const TensorOpNode &) = delete;
TensorOpNode & operator=(const TensorOpNode &) = delete;