提交 a0cfffb7 编写于 作者: X Xinqi

remove graph and profile


Former-commit-id: 589d05919b70ea234b73ce3d169007df07050918
上级 5e085f69
......@@ -2,16 +2,11 @@
#define ONEFLOW_CORE_REGISTER_LAZY_BLOB_H_
#include "oneflow/core/register/blob.h"
#include "oneflow/core/graph/graph.h"
#include "oneflow/core/common/util.h"
#include "oneflow/core/common/preprocessor.h"
namespace oneflow {
#define LAZY_EVALUATE(T, var) \
for (LazyBlobVarBuilder<T> var(std::make_unique<LazyBlobGraph>()); var.Touch() == 0; \
var.graph().Evaluate())
#if defined(_MSC_VER)
#define ALWAYS_INLINE __forceinline inline
#elif defined(__GNUC__) || defined(__GNUG__) || defined(__clang__)
......@@ -20,16 +15,7 @@ namespace oneflow {
#define ALWAYS_INLINE inline
#endif
class Slice final {
public:
Slice(int64_t x);
~Slice() = default;
};
class LazyBlobEdge;
class LazyBlobGraph;
class LazyBlobNode : public Node<LazyBlobNode, LazyBlobEdge> {
class LazyBlobNode {
public:
virtual ~LazyBlobNode() = default;
......@@ -39,58 +25,30 @@ class LazyBlobNode : public Node<LazyBlobNode, LazyBlobEdge> {
virtual void Evaluate(Blob* output_blob) const = 0;
// Getters
const LazyBlobGraph* graph() const { return graph_; }
const Blob* backend_blob() const { return backend_blob_; }
const Shape& shape() const { return shape_; }
DataType data_type() const { return data_type_; }
// Setters
LazyBlobGraph* mut_graph() const { return graph_; }
protected:
LazyBlobNode(LazyBlobGraph* graph, const Shape& shape, DataType data_type);
LazyBlobNode(LazyBlobGraph* graph, Blob* backend_blob);
LazyBlobNode(const Shape& shape, DataType data_type)
: backend_blob_(nullptr), shape_(shape), data_type_(data_type) {}
LazyBlobNode(Blob* backend_blob)
: backend_blob_(backend_blob),
shape_(backend_blob->shape()),
data_type_(backend_blob->data_type()) {}
Blob* mut_backend_blob() const { return backend_blob_; }
private:
LazyBlobGraph* graph_;
Blob* backend_blob_;
Shape shape_;
DataType data_type_;
};
class LazyBlobEdge final : public Edge<LazyBlobNode, LazyBlobEdge> {
public:
OF_DISALLOW_COPY_AND_MOVE(LazyBlobEdge);
LazyBlobEdge() = default;
~LazyBlobEdge() = default;
};
class LazyBlobGraph final : public Graph<LazyBlobNode, LazyBlobEdge> {
public:
OF_DISALLOW_COPY_AND_MOVE(LazyBlobGraph);
LazyBlobGraph() = default;
~LazyBlobGraph() = default;
void Evaluate() const {
TopoForEachNode([](const LazyBlobNode* blob_node) { blob_node->Evaluate(); });
}
bool IsBlobAssigned(const Blob* blob) const {
return assigned_blob_.find(blob) != assigned_blob_.end();
}
void AddAssignedBlob(const Blob* blob) { CHECK(assigned_blob_.emplace(blob).second); }
private:
HashSet<const Blob*> assigned_blob_;
};
template<typename DerivedT>
class LazyBlobIf : public LazyBlobNode {
public:
const static bool is_element_wise = false;
OF_DISALLOW_COPY_AND_MOVE(LazyBlobIf);
virtual ~LazyBlobIf() = default;
virtual void Evaluate(Blob* output_blob) const override {
......@@ -105,26 +63,9 @@ class LazyBlobIf : public LazyBlobNode {
}
}
/*
LazyBlobNode& operator()(const Slice& dim0) { UNIMPLEMENTED(); }
LazyBlobNode& operator()(const Slice& dim0, const Slice& dim1) { UNIMPLEMENTED(); }
LazyBlobNode& operator()(const Slice& dim0, const Slice& dim1, const Slice& dim2) {
UNIMPLEMENTED();
}
LazyBlobNode& operator()(const Slice& dim0, const Slice& dim1, const Slice& dim2,
const Slice& dim3) {
UNIMPLEMENTED();
}
LazyBlobNode& operator()(const Slice& dim0, const Slice& dim1, const Slice& dim2,
const Slice& dim3, const Slice& dim4) {
UNIMPLEMENTED();
}
*/
protected:
LazyBlobIf(LazyBlobGraph* graph, const Shape& shape, DataType data_type)
: LazyBlobNode(graph, shape, data_type) {}
LazyBlobIf(LazyBlobGraph* graph, Blob* backend_blob) : LazyBlobNode(graph, backend_blob) {}
LazyBlobIf(const Shape& shape, DataType data_type) : LazyBlobNode(shape, data_type) {}
LazyBlobIf(Blob* backend_blob) : LazyBlobNode(backend_blob) {}
private:
void Evaluate1(Blob* output_blob) const;
......@@ -140,33 +81,26 @@ class VarLazyBlob final : public LazyBlobIf<VarLazyBlob<T>> {
typedef T dtype;
const static bool is_element_wise = true;
OF_DISALLOW_COPY_AND_MOVE(VarLazyBlob);
VarLazyBlob(LazyBlobGraph* graph, Blob* backend_blob)
: LazyBlobIf<VarLazyBlob<T>>(graph, backend_blob),
VarLazyBlob(Blob* backend_blob)
: LazyBlobIf<VarLazyBlob<T>>(backend_blob),
dptr_(backend_blob->mut_dptr<T>()),
dim0_next_dim_count_(ShapeDefaultedNextDimCount(backend_blob->shape(), 0)),
dim1_next_dim_count_(ShapeDefaultedNextDimCount(backend_blob->shape(), 1)),
dim2_next_dim_count_(ShapeDefaultedNextDimCount(backend_blob->shape(), 2)),
dim3_next_dim_count_(ShapeDefaultedNextDimCount(backend_blob->shape(), 3)),
dim4_next_dim_count_(ShapeDefaultedNextDimCount(backend_blob->shape(), 4)),
value_lazy_blob_node_(nullptr) {
dim4_next_dim_count_(ShapeDefaultedNextDimCount(backend_blob->shape(), 4)) {
CHECK_EQ(GetDataType<T>::value, backend_blob->data_type());
}
VarLazyBlob<T>& operator=(const LazyBlobNode& value_lazy_blob_node) {
CHECK(value_lazy_blob_node.backend_blob() == nullptr);
CHECK(!this->graph()->IsBlobAssigned(this->backend_blob()))
<< "a blob should be only assigned once";
CHECK(this->shape() == value_lazy_blob_node.shape());
value_lazy_blob_node_ = &value_lazy_blob_node;
this->mut_graph()->AddAssignedBlob(this->backend_blob());
value_lazy_blob_node.Evaluate(this->mut_backend_blob());
return *this;
}
void Evaluate(Blob* output_blob) const override {
CHECK(output_blob == nullptr);
if (value_lazy_blob_node_ == nullptr) { return; }
value_lazy_blob_node_->Evaluate(this->mut_backend_blob());
// Do nothing
}
ALWAYS_INLINE dtype At(int64_t dim0) const { return dptr_[dim0]; }
......@@ -197,7 +131,6 @@ class VarLazyBlob final : public LazyBlobIf<VarLazyBlob<T>> {
const int64_t dim2_next_dim_count_;
const int64_t dim3_next_dim_count_;
const int64_t dim4_next_dim_count_;
const LazyBlobNode* value_lazy_blob_node_;
};
template<template<typename> class CoreFunc, typename XT>
......@@ -207,10 +140,8 @@ class UnaryExpresionLazyBlob final : public LazyBlobIf<UnaryExpresionLazyBlob<Co
typedef decltype(CoreFunc<T>::Invoke(*(const T*)nullptr)) dtype;
const static bool is_element_wise = true;
OF_DISALLOW_COPY_AND_MOVE(UnaryExpresionLazyBlob);
explicit UnaryExpresionLazyBlob(const XT& x)
: LazyBlobIf<UnaryExpresionLazyBlob<CoreFunc, XT>>(x.mut_graph(), x.shape(),
GetDataType<dtype>::value),
explicit UnaryExpresionLazyBlob(XT&& x)
: LazyBlobIf<UnaryExpresionLazyBlob<CoreFunc, XT>>(x.shape(), GetDataType<dtype>::value),
x_(x) {}
ALWAYS_INLINE dtype At(int64_t dim0) const { return CoreFunc<T>::Invoke(x_.At(dim0)); }
......@@ -248,17 +179,13 @@ class BinaryExpresionLazyBlob final : public LazyBlobIf<BinaryExpresionLazyBlob<
typedef decltype(CoreFunc<T>::Invoke(*(const T*)nullptr, *(const T*)nullptr)) dtype;
const static bool is_element_wise = true;
OF_DISALLOW_COPY_AND_MOVE(BinaryExpresionLazyBlob);
BinaryExpresionLazyBlob(const XT& x, const YT& y)
: LazyBlobIf<BinaryExpresionLazyBlob<CoreFunc, XT, YT>>(x.mut_graph(), x.shape(),
GetDataType<dtype>::value),
BinaryExpresionLazyBlob(XT&& x, YT&& y)
: LazyBlobIf<BinaryExpresionLazyBlob<CoreFunc, XT, YT>>(x.shape(), GetDataType<dtype>::value),
x_(x),
y_(y) {
CHECK(x.shape() == y.shape());
}
static ALWAYS_INLINE typename XT::dtype CoreInvoke(const XT& x, int64_t i) { return x.At(i); }
ALWAYS_INLINE dtype At(int64_t dim0) const {
return CoreFunc<T>::Invoke(x_.At(dim0), y_.At(dim0));
}
......@@ -297,10 +224,8 @@ class BroadcastLazyBlob final : public LazyBlobIf<BroadcastLazyBlob<XT>> {
public:
typedef typename XT::dtype dtype;
OF_DISALLOW_MOVE(BroadcastLazyBlob);
BroadcastLazyBlob(const BroadcastLazyBlob<XT>&) = default;
BroadcastLazyBlob(const XT& x, const Shape& shape)
: LazyBlobIf<BroadcastLazyBlob<XT>>(x.mut_graph(), shape, GetDataType<dtype>::value),
BroadcastLazyBlob(XT&& x, const Shape& shape)
: LazyBlobIf<BroadcastLazyBlob<XT>>(shape, GetDataType<dtype>::value),
x_(x),
dim0_size_(DefaultedShapeAt(0)),
dim1_size_(DefaultedShapeAt(1)),
......@@ -346,29 +271,15 @@ class BroadcastLazyBlob final : public LazyBlobIf<BroadcastLazyBlob<XT>> {
};
template<typename T>
class LazyBlobVarBuilder final {
class LazyBlobBuilder final {
public:
OF_DISALLOW_COPY_AND_MOVE(LazyBlobVarBuilder);
explicit LazyBlobVarBuilder(std::unique_ptr<LazyBlobGraph>&& graph)
: graph_(std::move(graph)), touched_cnt_(0) {}
OF_DISALLOW_COPY_AND_MOVE(LazyBlobBuilder);
LazyBlobBuilder() = default;
// for define lazy blob var
template<typename dtype = T>
VarLazyBlob<dtype>& operator()(Blob* blob) {
auto* lazy_blob = new VarLazyBlob<dtype>(graph_.get(), blob);
graph_->AddAllocatedNode(lazy_blob);
return *lazy_blob;
template<typename DT = T>
VarLazyBlob<DT> operator()(Blob* blob) {
return VarLazyBlob<DT>(blob);
}
// Getter
const LazyBlobGraph& graph() const { return *graph_; }
// never use Touch() in your code
int32_t Touch() { return touched_cnt_++; }
private:
std::unique_ptr<LazyBlobGraph> graph_;
int32_t touched_cnt_;
};
#define LAZY_BLOB_BINARY_CORE_OP_FUNC_SEQ \
......@@ -414,53 +325,37 @@ OF_PP_FOR_EACH_TUPLE(DECLARE_LAZY_BLOB_UNARY_CORE, LAZY_BLOB_UNARY_CORE_OP_FUNC_
template<template<typename> class LazyBlobCoreFunc, typename XT, typename YT = XT>
typename std::enable_if<std::is_base_of<LazyBlobNode, XT>::value
&& std::is_base_of<LazyBlobNode, YT>::value,
BinaryExpresionLazyBlob<LazyBlobCoreFunc, XT, YT>>::type&
BuildBinaryLazyBlob(XT& x, YT& y) {
auto* ret = new BinaryExpresionLazyBlob<LazyBlobCoreFunc, XT, YT>(x, y);
CHECK(x.graph() == y.graph());
CHECK(x.shape() == y.shape());
LazyBlobGraph* graph = x.mut_graph();
LazyBlobNode* base_ret = ret;
graph->AddAllocatedNode(base_ret);
Connect(dynamic_cast<LazyBlobNode*>(&x), graph->NewEdge(), base_ret);
Connect(dynamic_cast<LazyBlobNode*>(&y), graph->NewEdge(), base_ret);
if (x.backend_blob() == nullptr) { CHECK_EQ(x.out_edges().size(), 1); }
if (y.backend_blob() == nullptr) { CHECK_EQ(y.out_edges().size(), 1); }
return *ret;
BinaryExpresionLazyBlob<LazyBlobCoreFunc, XT, YT>>::type
BuildBinaryLazyBlob(XT&& x, YT&& y) {
return BinaryExpresionLazyBlob<LazyBlobCoreFunc, XT, YT>(std::move(x), std::move(y));
}
#define OVERLOAD_BINARY_LAZY_BLOB_OP_FUNC(name, op, ret_type) \
template<typename XType, typename YType = XType, \
typename XT = typename std::remove_reference<XType>::type, \
typename YT = typename std::remove_reference<YType>::type> \
typename std::enable_if<std::is_base_of<LazyBlobNode, XT>::value \
&& std::is_base_of<LazyBlobNode, YT>::value, \
BinaryExpresionLazyBlob<LazyBlobCore##name, XT, YT>>::type& \
operator op(XType& x, YType& y) { \
return BuildBinaryLazyBlob<LazyBlobCore##name, XT, YT>(x, y); \
#define OVERLOAD_BINARY_LAZY_BLOB_OP_FUNC(name, op, ret_type) \
template<typename XType, typename YType = XType, \
typename XT = typename std::remove_reference<XType>::type, \
typename YT = typename std::remove_reference<YType>::type> \
typename std::enable_if<std::is_base_of<LazyBlobNode, XT>::value \
&& std::is_base_of<LazyBlobNode, YT>::value, \
BinaryExpresionLazyBlob<LazyBlobCore##name, XT, YT>>::type \
operator op(XType&& x, YType&& y) { \
return BuildBinaryLazyBlob<LazyBlobCore##name, XT, YT>(std::move(x), std::move(y)); \
}
OF_PP_FOR_EACH_TUPLE(OVERLOAD_BINARY_LAZY_BLOB_OP_FUNC, LAZY_BLOB_BINARY_CORE_OP_FUNC_SEQ);
#undef OVERLOAD_BINARY_LAZY_BLOB_OP_FUNC
template<template<typename> class LazyBlobCoreFunc, typename XT>
typename std::enable_if<std::is_base_of<LazyBlobNode, XT>::value,
UnaryExpresionLazyBlob<LazyBlobCoreFunc, XT>>::type&
BuildUnaryLazyBlob(XT& x) {
auto* ret = new UnaryExpresionLazyBlob<LazyBlobCoreFunc, XT>(x);
LazyBlobGraph* graph = x.mut_graph();
LazyBlobNode* base_ret = ret;
graph->AddAllocatedNode(base_ret);
Connect(&x, graph->NewEdge(), base_ret);
if (x.backend_blob() == nullptr) { CHECK_EQ(x.out_edges().size(), 1); }
return *ret;
UnaryExpresionLazyBlob<LazyBlobCoreFunc, XT>>::type
BuildUnaryLazyBlob(XT&& x) {
return UnaryExpresionLazyBlob<LazyBlobCoreFunc, XT>(std::move(x));
}
#define OVERLOAD_UNARY_LAZY_BLOB_OP_FUNC(name, op, ret_type) \
template<typename XType, typename XT = typename std::remove_reference<XType>::type> \
typename std::enable_if<std::is_base_of<LazyBlobNode, XT>::value, \
UnaryExpresionLazyBlob<LazyBlobCore##name, XT>>::type& \
operator op(XType& x) { \
return BuildUnaryLazyBlob<LazyBlobCore##name, XT>(x); \
UnaryExpresionLazyBlob<LazyBlobCore##name, XT>>::type \
operator op(XType&& x) { \
return BuildUnaryLazyBlob<LazyBlobCore##name, XT>(std::move(x)); \
}
OF_PP_FOR_EACH_TUPLE(OVERLOAD_UNARY_LAZY_BLOB_OP_FUNC, LAZY_BLOB_UNARY_CORE_OP_FUNC_SEQ);
#undef OVERLOAD_UNARY_LAZY_BLOB_OP_FUNC
......@@ -563,15 +458,6 @@ void LazyBlobIf<DerivedT>::Evaluate5(Blob* output_blob) const {
}
}
LazyBlobNode::LazyBlobNode(LazyBlobGraph* graph, const Shape& shape, DataType data_type)
: graph_(graph), backend_blob_(nullptr), shape_(shape), data_type_(data_type) {}
LazyBlobNode::LazyBlobNode(LazyBlobGraph* graph, Blob* backend_blob)
: graph_(graph),
backend_blob_(backend_blob),
shape_(backend_blob->shape()),
data_type_(backend_blob->data_type()) {}
} // namespace oneflow
#endif // ONEFLOW_CORE_REGISTER_LAZY_BLOB_H_
......@@ -27,9 +27,10 @@ void LazyEvaluate() {
Blob* x4_blob = TestBlob();
Blob* ret_blob = TestBlob();
int64_t start = GetCurTime();
LAZY_EVALUATE(int32_t, lazy) {
{
LazyBlobBuilder<int32_t> lazy;
lazy(ret_blob) = lazy(x0_blob) * lazy(x1_blob) * (lazy(x0_blob) + lazy(x1_blob))
* (lazy(x2_blob) + lazy(x3_blob) + lazy(x4_blob));
* (lazy(x2_blob), lazy(x3_blob), lazy(x4_blob));
}
int64_t end = GetCurTime();
std::cout << "lazy evaluation: " << end - start << std::endl;
......
......@@ -20,7 +20,10 @@ TEST(LazyEvaluation, simple_add) {
CHECK_EQ(x_blob->dptr<int32_t>(), data.data());
std::vector<int32_t> ret_data{0};
Blob* ret_blob = NewTestBlob(blob_desc, ret_data.data());
LAZY_EVALUATE(int32_t, var) { var(ret_blob) = var(x_blob) + var(x_blob); }
{
LazyBlobBuilder<int32_t> lazy;
lazy(ret_blob) = lazy(x_blob) + lazy(x_blob);
}
ASSERT_EQ(ret_blob->dptr<int32_t>()[0], 2);
}
......@@ -31,10 +34,11 @@ TEST(LazyEvaluation, simple_mul) {
CHECK_EQ(x_blob->dptr<int32_t>(), data.data());
std::vector<int32_t> ret_data{0};
Blob* ret_blob = NewTestBlob(blob_desc, ret_data.data());
LAZY_EVALUATE(int32_t, var) {
auto& val0 = var(x_blob) + var(x_blob);
auto& val1 = var(x_blob) + var(x_blob) + var(x_blob);
var(ret_blob) = val0 * val1;
{
LazyBlobBuilder<int32_t> lazy;
const auto& val0 = lazy(x_blob) + lazy(x_blob);
const auto& val1 = lazy(x_blob) + lazy(x_blob) + lazy(x_blob);
lazy(ret_blob) = val0 * val1;
}
ASSERT_EQ(ret_blob->dptr<int32_t>()[0], 6);
}
......@@ -47,7 +51,10 @@ TEST(LazyEvaluation, add) {
CHECK_EQ(x_blob->dptr<int32_t>(), data.data());
std::vector<int32_t> ret_data(data);
Blob* ret_blob = NewTestBlob(blob_desc, ret_data.data());
LAZY_EVALUATE(int32_t, var) { var(ret_blob) = var(x_blob) + var(x_blob); }
{
LazyBlobBuilder<int32_t> lazy;
lazy(ret_blob) = lazy(x_blob) + lazy(x_blob);
}
FOR_RANGE(int32_t, i, 0, data.size()) { ASSERT_EQ(ret_blob->dptr<int32_t>()[i], i * 2); }
}
......@@ -59,10 +66,11 @@ TEST(LazyEvaluation, mul) {
CHECK_EQ(x_blob->dptr<int32_t>(), data.data());
std::vector<int32_t> ret_data(data);
Blob* ret_blob = NewTestBlob(blob_desc, ret_data.data());
LAZY_EVALUATE(int32_t, var) {
auto& val0 = var(x_blob) + var(x_blob);
auto& val1 = var(x_blob) + var(x_blob) + var(x_blob);
var(ret_blob) = val0 * val1;
{
LazyBlobBuilder<int32_t> lazy;
const auto& val0 = lazy(x_blob) + lazy(x_blob);
const auto& val1 = lazy(x_blob) + lazy(x_blob) + lazy(x_blob);
lazy(ret_blob) = val0 * val1;
}
FOR_RANGE(int32_t, i, 0, data.size()) { ASSERT_EQ(ret_blob->dptr<int32_t>()[i], i * i * 6); }
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册