chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
cinn_cc_test(test_dfs_walker SRCS dfs_walker_test.cc DEPS gtest glog)
|
||||
cinn_cc_test(test_dfs_topo_walker SRCS dfs_topo_walker_test.cc DEPS gtest glog)
|
||||
cinn_cc_test(test_cinn_value SRCS cinn_value_test.cc DEPS cinncore)
|
||||
cinn_cc_test(test_axis SRCS axis_test.cc DEPS cinncore)
|
||||
|
||||
cinn_cc_test(dim_expr_converter_test SRCS dim_expr_converter_test.cc DEPS
|
||||
cinncore)
|
||||
cinn_cc_test(broadcast_tree_test SRCS broadcast_tree_test.cc DEPS cinncore)
|
||||
|
||||
cinn_cc_test(test_equation_graph_topo_walker SRCS
|
||||
equation_graph_topo_walker_test.cc DEPS gtest glog)
|
||||
cinn_cc_test(test_type SRCS type_test.cc DEPS cinncore)
|
||||
cinn_cc_test(test_topo_walker SRCS topo_walker_test.cc DEPS gtest glog)
|
||||
cinn_cc_test(test_shared SRCS shared_test.cc DEPS cinncore)
|
||||
cinn_cc_test(test_is_reachable_predicator SRCS is_reachable_predicator_test.cc
|
||||
DEPS gtest glog)
|
||||
cinn_cc_test(test_integer_set SRCS integer_set_test.cc DEPS cinncore)
|
||||
if(WITH_CUDA)
|
||||
cinn_nv_test(test_fp16_bf16_cuda SRCS float16_bfloat16_cuda_test.cu DEPS
|
||||
gtest glog)
|
||||
endif()
|
||||
cinn_cc_test(test_fp16_bf16_host SRCS float16_bfloat16_host_test.cc DEPS gtest
|
||||
glog)
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2023 CINN Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "paddle/cinn/common/axis.h"
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "paddle/cinn/utils/string.h"
|
||||
|
||||
namespace cinn {
|
||||
namespace common {
|
||||
|
||||
TEST(AXISNAME, BASE) {
|
||||
ASSERT_EQ(axis_name(0), std::string("i"));
|
||||
ASSERT_EQ(axis_name(1), std::string("j"));
|
||||
ASSERT_EQ(axis_name(22), std::string("ii"));
|
||||
ASSERT_EQ(axis_name(44), std::string("iii"));
|
||||
}
|
||||
|
||||
TEST(AXISNAME, CHECK_RESERVED) {
|
||||
ASSERT_TRUE(IsAxisNameReserved("i"));
|
||||
ASSERT_TRUE(IsAxisNameReserved("j"));
|
||||
ASSERT_TRUE(IsAxisNameReserved("ii"));
|
||||
ASSERT_TRUE(IsAxisNameReserved("iiiiiiiiii"));
|
||||
ASSERT_FALSE(IsAxisNameReserved("ijk"));
|
||||
ASSERT_FALSE(IsAxisNameReserved("iiiiiiiiiij"));
|
||||
ASSERT_FALSE(IsAxisNameReserved("x"));
|
||||
}
|
||||
|
||||
} // namespace common
|
||||
} // namespace cinn
|
||||
@@ -0,0 +1,118 @@
|
||||
// Copyright (c) 2024 PaddlePaddle Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "paddle/cinn/common/broadcast_tree.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace cinn::common {
|
||||
using namespace symbol; // NOLINT
|
||||
|
||||
namespace {
|
||||
|
||||
DimExpr MakeBroadcastDimExpr(const DimExpr& expr1, const DimExpr& expr2) {
|
||||
List<DimExpr> operands{expr1, expr2};
|
||||
return Broadcast<DimExpr>{operands};
|
||||
}
|
||||
|
||||
bool DimExprNonBroadcast(const DimExpr& dim_expr) {
|
||||
if (dim_expr.Has<Broadcast<DimExpr>>()) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void CheckLeafNonBroadcast(const BroadcastLeaf& leaf) {
|
||||
for (const auto& operands : *leaf) {
|
||||
for (const auto& operand : operands) {
|
||||
ASSERT_TRUE(DimExprNonBroadcast(operand));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckInnerBranchNonBroadcast(
|
||||
const BroadcastBranch<BroadcastTree>& branch) {
|
||||
const auto& [_, lhs_eq_rhs_tree, lhs_eq_one_tree, rhs_eq_one_tree] =
|
||||
branch.tuple();
|
||||
ASSERT_TRUE(lhs_eq_rhs_tree.Has<BroadcastLeaf>());
|
||||
ASSERT_TRUE(lhs_eq_one_tree.Has<BroadcastLeaf>());
|
||||
ASSERT_TRUE(rhs_eq_one_tree.Has<BroadcastLeaf>());
|
||||
CheckLeafNonBroadcast(lhs_eq_rhs_tree.Get<BroadcastLeaf>());
|
||||
CheckLeafNonBroadcast(lhs_eq_one_tree.Get<BroadcastLeaf>());
|
||||
CheckLeafNonBroadcast(rhs_eq_one_tree.Get<BroadcastLeaf>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(BroadcastTree, Naive) {
|
||||
DimExpr expr1("S1");
|
||||
DimExpr expr2("S2");
|
||||
DimExpr expr3("S3");
|
||||
DimExpr expr4("S4");
|
||||
std::vector<DimExpr> tensor_shape{expr1,
|
||||
expr2,
|
||||
MakeBroadcastDimExpr(expr1, expr2),
|
||||
MakeBroadcastDimExpr(expr3, expr4)};
|
||||
BroadcastLeaf leaf = adt::List<std::vector<DimExpr>>{tensor_shape};
|
||||
int num_of_leaves = 0;
|
||||
BroadcastTree tree = ConstructBroadcastTree(leaf, &num_of_leaves);
|
||||
ASSERT_TRUE(tree.Has<BroadcastBranch<BroadcastTree>>());
|
||||
const auto& branch = tree.Get<BroadcastBranch<BroadcastTree>>();
|
||||
const auto& [cstr_broadcastable,
|
||||
lhs_eq_rhs_tree,
|
||||
lhs_eq_one_tree,
|
||||
rhs_eq_one_tree] = branch.tuple();
|
||||
ASSERT_EQ(cstr_broadcastable->lhs, DimExpr("S1"));
|
||||
ASSERT_EQ(cstr_broadcastable->rhs, DimExpr("S2"));
|
||||
ASSERT_TRUE(lhs_eq_rhs_tree.Has<BroadcastBranch<BroadcastTree>>());
|
||||
ASSERT_TRUE(lhs_eq_one_tree.Has<BroadcastBranch<BroadcastTree>>());
|
||||
ASSERT_TRUE(rhs_eq_one_tree.Has<BroadcastBranch<BroadcastTree>>());
|
||||
CheckInnerBranchNonBroadcast(
|
||||
lhs_eq_rhs_tree.Get<BroadcastBranch<BroadcastTree>>());
|
||||
CheckInnerBranchNonBroadcast(
|
||||
lhs_eq_one_tree.Get<BroadcastBranch<BroadcastTree>>());
|
||||
CheckInnerBranchNonBroadcast(
|
||||
rhs_eq_one_tree.Get<BroadcastBranch<BroadcastTree>>());
|
||||
}
|
||||
|
||||
TEST(BroadcastTree, SimplifyConstantBroadcast) {
|
||||
DimExpr expr1("S1");
|
||||
DimExpr expr2("S2");
|
||||
DimExpr expr3("S3");
|
||||
DimExpr expr4(4);
|
||||
std::vector<DimExpr> tensor_shape{expr1,
|
||||
expr2,
|
||||
MakeBroadcastDimExpr(expr1, expr2),
|
||||
MakeBroadcastDimExpr(expr3, expr4)};
|
||||
BroadcastLeaf leaf = adt::List<std::vector<DimExpr>>{tensor_shape};
|
||||
int num_of_leaves = 0;
|
||||
BroadcastTree tree = ConstructBroadcastTree(leaf, &num_of_leaves);
|
||||
ASSERT_TRUE(tree.Has<BroadcastBranch<BroadcastTree>>());
|
||||
const auto& branch = tree.Get<BroadcastBranch<BroadcastTree>>();
|
||||
const auto& [cstr_broadcastable,
|
||||
lhs_eq_rhs_tree,
|
||||
lhs_eq_one_tree,
|
||||
rhs_eq_one_tree] = branch.tuple();
|
||||
ASSERT_EQ(cstr_broadcastable->lhs, DimExpr("S1"));
|
||||
ASSERT_EQ(cstr_broadcastable->rhs, DimExpr("S2"));
|
||||
ASSERT_TRUE(lhs_eq_rhs_tree.Has<BroadcastLeaf>());
|
||||
ASSERT_TRUE(lhs_eq_one_tree.Has<BroadcastLeaf>());
|
||||
ASSERT_TRUE(rhs_eq_one_tree.Has<BroadcastLeaf>());
|
||||
CheckLeafNonBroadcast(lhs_eq_rhs_tree.Get<BroadcastLeaf>());
|
||||
CheckLeafNonBroadcast(lhs_eq_one_tree.Get<BroadcastLeaf>());
|
||||
CheckLeafNonBroadcast(rhs_eq_one_tree.Get<BroadcastLeaf>());
|
||||
}
|
||||
|
||||
} // namespace cinn::common
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2021 CINN Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "paddle/cinn/common/cinn_value.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "paddle/cinn/common/common.h"
|
||||
#include "paddle/cinn/common/ir_util.h"
|
||||
#include "paddle/cinn/ir/ir.h"
|
||||
#include "paddle/cinn/ir/ir_printer.h"
|
||||
|
||||
namespace cinn {
|
||||
namespace common {
|
||||
|
||||
TEST(CINNValue, test) {
|
||||
{
|
||||
CINNValue value(32);
|
||||
ASSERT_EQ(int(value), 32); // NOLINT
|
||||
}
|
||||
{
|
||||
CINNValue value(32.f);
|
||||
ASSERT_NEAR(float(value), 32.f, 1e-6); // NOLINT
|
||||
}
|
||||
}
|
||||
|
||||
TEST(CINNValue, buffer) {
|
||||
cinn_buffer_t* v = nullptr;
|
||||
CINNValue value(v);
|
||||
ASSERT_EQ((cinn_buffer_t*)value, nullptr);
|
||||
}
|
||||
|
||||
TEST(CINNValue, Expr) {
|
||||
Expr a(1);
|
||||
|
||||
{
|
||||
CINNValue value(a);
|
||||
ASSERT_TRUE(a == value);
|
||||
}
|
||||
|
||||
{
|
||||
CINNValue copied = CINNValue(a);
|
||||
ASSERT_TRUE(copied == cinn::common::make_const(1));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace common
|
||||
} // namespace cinn
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2023 CINN Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "paddle/cinn/common/dfs_topo_walker.h"
|
||||
|
||||
namespace cinn {
|
||||
namespace common {
|
||||
|
||||
TEST(DfsTopoWalker, simple) {
|
||||
std::vector<std::pair<int, int>> edges{
|
||||
{0, 1}, {2, 3}, {1, 3}, {0, 3}, {3, 4}};
|
||||
DfsTopoWalker<int> walker(
|
||||
[&](int node, const std::function<void(int)>& NodeHandler) {
|
||||
for (const auto& pair : edges) {
|
||||
if (pair.second == node) {
|
||||
NodeHandler(pair.first);
|
||||
}
|
||||
}
|
||||
},
|
||||
[&](int node, const std::function<void(int)>& NodeHandler) {
|
||||
for (const auto& pair : edges) {
|
||||
if (pair.first == node) {
|
||||
NodeHandler(pair.second);
|
||||
}
|
||||
}
|
||||
});
|
||||
std::vector<int> sources{0, 2};
|
||||
std::vector<int> outputs;
|
||||
walker(sources.begin(), sources.end(), [&](int node) {
|
||||
outputs.push_back(node);
|
||||
});
|
||||
for (auto output : outputs) {
|
||||
LOG(INFO) << output;
|
||||
}
|
||||
std::vector<int> expected{0, 1, 2, 3, 4};
|
||||
EXPECT_TRUE((outputs == expected));
|
||||
}
|
||||
|
||||
} // namespace common
|
||||
} // namespace cinn
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright (c) 2023 CINN Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "paddle/cinn/common/dfs_walker.h"
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace cinn {
|
||||
namespace common {
|
||||
|
||||
TEST(DfsWalker, simple_on_push) {
|
||||
DfsWalker<int> visitor(
|
||||
[](int node, const std::function<void(int)>& NodeHandler) {
|
||||
if (node == 0) {
|
||||
NodeHandler(3);
|
||||
} else if (node == 1) {
|
||||
NodeHandler(2);
|
||||
NodeHandler(3);
|
||||
} else if (node == 2 || node == 3) {
|
||||
NodeHandler(4);
|
||||
}
|
||||
});
|
||||
std::vector<int> sources{0, 1};
|
||||
std::vector<int> outputs;
|
||||
visitor(sources.begin(), sources.end(), [&](int node) {
|
||||
LOG(ERROR) << node;
|
||||
outputs.push_back(node);
|
||||
});
|
||||
std::vector<int> expected{0, 3, 4, 1, 2};
|
||||
EXPECT_TRUE((outputs == expected));
|
||||
}
|
||||
|
||||
TEST(DfsWalker, simple_on_pop) {
|
||||
DfsWalker<int> visitor(
|
||||
[](int node, const std::function<void(int)>& NodeHandler) {
|
||||
if (node == 0) {
|
||||
NodeHandler(3);
|
||||
} else if (node == 1) {
|
||||
NodeHandler(2);
|
||||
NodeHandler(3);
|
||||
} else if (node == 2 || node == 3) {
|
||||
NodeHandler(4);
|
||||
}
|
||||
});
|
||||
std::vector<int> sources{0, 1};
|
||||
std::vector<int> outputs;
|
||||
visitor(
|
||||
sources.begin(),
|
||||
sources.end(),
|
||||
[](int) {},
|
||||
[&](int node) {
|
||||
LOG(ERROR) << node;
|
||||
outputs.push_back(node);
|
||||
});
|
||||
std::vector<int> expected{4, 3, 0, 2, 1};
|
||||
EXPECT_TRUE((outputs == expected));
|
||||
}
|
||||
|
||||
} // namespace common
|
||||
} // namespace cinn
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "paddle/cinn/common/dim_expr_converter.h"
|
||||
#include "paddle/cinn/common/ir_util.h"
|
||||
#include "paddle/cinn/ir/ir_printer.h"
|
||||
|
||||
namespace cinn::common::test {
|
||||
|
||||
using namespace symbol; // NOLINT
|
||||
|
||||
TEST(Convert, AddExpr) {
|
||||
List<DimExpr> num_lists{DimExpr(4), DimExpr(5), DimExpr("sym_0")};
|
||||
DimExpr dim_expr{Add<DimExpr>{num_lists}};
|
||||
ir::Expr src_expr = DimExprConverter().ConvertToIrExpr(dim_expr);
|
||||
|
||||
ir::Expr expr1 =
|
||||
ir::Add::Make(ir::Expr(std::int64_t(4)), ir::Expr(std::int64_t(5)));
|
||||
ir::Expr dst_expr =
|
||||
ir::Add::Make(expr1,
|
||||
ir::_Var_::Make(ir::Expr(static_cast<int64_t>(1)),
|
||||
ir::Expr(INT32_MAX),
|
||||
"sym_0",
|
||||
/* is_reduce = */ false,
|
||||
/* is_symbolic_constant = */ true));
|
||||
ASSERT_TRUE(MathEqual(src_expr, dst_expr));
|
||||
}
|
||||
|
||||
TEST(Convert, SubExpr) {
|
||||
DimExpr dim_expr = DimExpr(4) - DimExpr("sym_0");
|
||||
ir::Expr src_expr = DimExprConverter().ConvertToIrExpr(dim_expr);
|
||||
|
||||
ir::Expr expr1 =
|
||||
ir::Sub::Make(ir::Expr(std::int64_t(0)),
|
||||
ir::_Var_::Make(ir::Expr(static_cast<int64_t>(1)),
|
||||
ir::Expr(INT32_MAX),
|
||||
"sym_0",
|
||||
/* is_reduce = */ false,
|
||||
/* is_symbolic_constant = */ true));
|
||||
ir::Expr dst_expr = ir::Add::Make(ir::Expr(std::int64_t(4)), expr1);
|
||||
ASSERT_TRUE(MathEqual(src_expr, dst_expr));
|
||||
}
|
||||
|
||||
TEST(Convert, MulExpr) {
|
||||
List<DimExpr> num_lists{DimExpr(4), DimExpr(5), DimExpr("sym_0")};
|
||||
DimExpr dim_expr{Mul<DimExpr>{num_lists}};
|
||||
ir::Expr src_expr = DimExprConverter().ConvertToIrExpr(dim_expr);
|
||||
|
||||
ir::Expr expr1 =
|
||||
ir::Mul::Make(ir::Expr(std::int64_t(4)), ir::Expr(std::int64_t(5)));
|
||||
ir::Expr dst_expr =
|
||||
ir::Mul::Make(expr1,
|
||||
ir::_Var_::Make(ir::Expr(static_cast<int64_t>(1)),
|
||||
ir::Expr(INT32_MAX),
|
||||
"sym_0",
|
||||
/* is_reduce = */ false,
|
||||
/* is_symbolic_constant = */ true));
|
||||
ASSERT_TRUE(MathEqual(src_expr, dst_expr));
|
||||
}
|
||||
|
||||
TEST(Convert, MaxExpr) {
|
||||
List<DimExpr> num_lists{DimExpr(4), DimExpr(5), DimExpr("sym_0")};
|
||||
DimExpr dim_expr{Max<DimExpr>{num_lists}};
|
||||
ir::Expr src_expr = DimExprConverter().ConvertToIrExpr(dim_expr);
|
||||
|
||||
std::ostringstream stream;
|
||||
stream << src_expr;
|
||||
ASSERT_EQ(stream.str(), "cinn_max(cinn_max(4ll, 5ll), sym_0)");
|
||||
}
|
||||
|
||||
TEST(Convert, MinExpr) {
|
||||
List<DimExpr> num_lists{DimExpr(4), DimExpr(5), DimExpr("sym_0")};
|
||||
DimExpr dim_expr{Min<DimExpr>{num_lists}};
|
||||
ir::Expr src_expr = DimExprConverter().ConvertToIrExpr(dim_expr);
|
||||
|
||||
std::ostringstream stream;
|
||||
stream << src_expr;
|
||||
ASSERT_EQ(stream.str(), "cinn_min(cinn_min(4ll, 5ll), sym_0)");
|
||||
}
|
||||
|
||||
} // namespace cinn::common::test
|
||||
@@ -0,0 +1,116 @@
|
||||
// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// TODO(yifan): Add unittest here
|
||||
#include "paddle/cinn/common/equation_graph_topo_walker.h"
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace adt {
|
||||
namespace common {
|
||||
|
||||
using VT = int;
|
||||
using FT = std::string;
|
||||
/*
|
||||
Graph ex:
|
||||
|
||||
1-> "1->10" -> 10
|
||||
2-> "2->20" -> 20
|
||||
*/
|
||||
|
||||
TEST(EquationGraphTopoWalker, simple1) {
|
||||
auto F4V = [](VT variable, const std::function<void(FT)>& visitor) {
|
||||
if (variable == 1) {
|
||||
visitor("1->10");
|
||||
} else if (variable == 2) {
|
||||
visitor("2->20");
|
||||
}
|
||||
};
|
||||
auto InV4F = [](FT function, const std::function<void(VT)>& visitor) {
|
||||
if (function == "1->10") {
|
||||
visitor(1);
|
||||
} else if (function == "2->20") {
|
||||
visitor(2);
|
||||
}
|
||||
};
|
||||
auto OutV4F = [](FT function, const std::function<void(VT)>& visitor) {
|
||||
if (function == "1->10") {
|
||||
visitor(10);
|
||||
} else if (function == "2->20") {
|
||||
visitor(20);
|
||||
}
|
||||
};
|
||||
cinn::EquationGraphTopoWalker<VT, FT> walker(F4V, InV4F, OutV4F);
|
||||
std::vector<FT> outputs;
|
||||
std::function<void(FT)> FunctionVisitor = [&](FT function) {
|
||||
outputs.push_back(function);
|
||||
};
|
||||
walker.WalkFunction(1, FunctionVisitor);
|
||||
|
||||
std::vector<FT> expected{"1->10"};
|
||||
EXPECT_TRUE((outputs == expected));
|
||||
}
|
||||
|
||||
/*
|
||||
Graph ex:
|
||||
|
||||
1 -> "1->10, 1->11" -> 10
|
||||
-> 11
|
||||
2 -> "2->20" -> 20
|
||||
3 -> "3->30, 3->31" -> 30
|
||||
-> 31
|
||||
*/
|
||||
TEST(EquationGraphTopoWalker, simple2) {
|
||||
auto F4V = [](VT variable, const std::function<void(FT)>& visitor) {
|
||||
if (variable == 1) {
|
||||
visitor("1->10, 1->11");
|
||||
} else if (variable == 2) {
|
||||
visitor("2->20");
|
||||
} else if (variable == 3) {
|
||||
visitor("3->30, 3->31");
|
||||
}
|
||||
};
|
||||
auto InV4F = [](FT function, const std::function<void(VT)>& visitor) {
|
||||
if (function == "1->10, 1->11") {
|
||||
visitor(1);
|
||||
} else if (function == "2->20") {
|
||||
visitor(2);
|
||||
} else if (function == "3->30, 3->31") {
|
||||
visitor(3);
|
||||
}
|
||||
};
|
||||
auto OutV4F = [](FT function, const std::function<void(VT)>& visitor) {
|
||||
if (function == "1->10, 1->11") {
|
||||
visitor(10);
|
||||
visitor(11);
|
||||
} else if (function == "2->20") {
|
||||
visitor(20);
|
||||
} else if (function == "3->30, 3->31") {
|
||||
visitor(30);
|
||||
visitor(31);
|
||||
}
|
||||
};
|
||||
cinn::EquationGraphTopoWalker<VT, FT> walker(F4V, InV4F, OutV4F);
|
||||
std::vector<VT> outputs;
|
||||
std::function<void(VT)> VariableVisitor = [&](VT variable) {
|
||||
outputs.push_back(variable);
|
||||
};
|
||||
walker.WalkVariable(1, VariableVisitor);
|
||||
std::vector<VT> expected{1, 10, 11};
|
||||
EXPECT_TRUE((outputs == expected));
|
||||
}
|
||||
|
||||
} // namespace common
|
||||
} // namespace adt
|
||||
@@ -0,0 +1,286 @@
|
||||
// Copyright (c) 2021 CINN Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <random>
|
||||
#include <vector>
|
||||
#include "paddle/cinn/common/bfloat16.h"
|
||||
#include "paddle/cinn/common/float16.h"
|
||||
#include "paddle/common/enforce.h"
|
||||
|
||||
namespace cinn {
|
||||
namespace common {
|
||||
|
||||
#define CUDA_CALL(func) \
|
||||
{ \
|
||||
auto status = func; \
|
||||
if (status != cudaSuccess) { \
|
||||
std::stringstream ss; \
|
||||
ss << "CUDA Error : " << cudaGetErrorString(status); \
|
||||
PADDLE_THROW(::common::errors::Fatal(ss.str())); \
|
||||
} \
|
||||
}
|
||||
|
||||
class CudaMem {
|
||||
public:
|
||||
CudaMem() = default;
|
||||
|
||||
void* mutable_data(size_t bytes) {
|
||||
PADDLE_ENFORCE_GT(
|
||||
bytes,
|
||||
0,
|
||||
::common::errors::InvalidArgument("Cannot allocate empty memory!"));
|
||||
if (ptr) {
|
||||
PADDLE_ENFORCE_EQ(
|
||||
bytes,
|
||||
bytes_,
|
||||
::common::errors::InvalidArgument("Try allocate memory twice!"));
|
||||
return ptr;
|
||||
}
|
||||
CUDA_CALL(cudaMalloc(&ptr, bytes));
|
||||
bytes_ = bytes;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* mutable_data(size_t num) {
|
||||
return reinterpret_cast<T*>(mutable_data(num * sizeof(T)));
|
||||
}
|
||||
|
||||
void* data() const {
|
||||
PADDLE_ENFORCE_NOT_NULL(ptr,
|
||||
::common::errors::InvalidArgument(
|
||||
"Pointer is null; please ensure it is properly "
|
||||
"initialized before use."));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* data() const {
|
||||
return reinterpret_cast<T*>(data());
|
||||
}
|
||||
|
||||
void MemcpyFromHost(const void* src,
|
||||
size_t bytes,
|
||||
cudaStream_t stream = nullptr) {
|
||||
PADDLE_ENFORCE_LE(
|
||||
bytes,
|
||||
bytes_,
|
||||
::common::errors::InvalidArgument("Too many data need copy"));
|
||||
CUDA_CALL(cudaMemcpyAsync(ptr, src, bytes, cudaMemcpyHostToDevice, stream));
|
||||
}
|
||||
|
||||
void MemcpyToHost(void* dst, size_t bytes, cudaStream_t stream = nullptr) {
|
||||
PADDLE_ENFORCE_LE(
|
||||
bytes,
|
||||
bytes_,
|
||||
::common::errors::InvalidArgument("Too many data need copy"));
|
||||
CUDA_CALL(cudaMemcpyAsync(dst, ptr, bytes, cudaMemcpyDeviceToHost, stream));
|
||||
}
|
||||
|
||||
~CudaMem() {
|
||||
if (ptr) {
|
||||
cudaFree(ptr);
|
||||
}
|
||||
bytes_ = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void* ptr{nullptr};
|
||||
size_t bytes_{0};
|
||||
};
|
||||
|
||||
__global__ void cast_fp32_to_fp16_cuda_kernel(const float* input,
|
||||
const int num,
|
||||
float16* out) {
|
||||
int idx = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (idx < num) {
|
||||
out[idx] = float16(input[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
__global__ void cast_fp16_to_fp32_cuda_kernel(const float16* input,
|
||||
const int num,
|
||||
float* out) {
|
||||
int idx = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (idx < num) {
|
||||
out[idx] = static_cast<float>(input[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
__global__ void test_fp16_cuda_kernel(const float16* x,
|
||||
const float16* y,
|
||||
const int num,
|
||||
float16* out) {
|
||||
int idx = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (idx < num) {
|
||||
float16 x_i = x[idx], y_i = y[idx];
|
||||
x_i += float16(1);
|
||||
|
||||
out[idx] = (x_i + y_i) * (x_i - y_i);
|
||||
}
|
||||
}
|
||||
|
||||
__global__ void cast_fp32_to_bf16_cuda_kernel(const float* input,
|
||||
const int num,
|
||||
bfloat16* out) {
|
||||
int idx = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (idx < num) {
|
||||
out[idx] = bfloat16(input[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
__global__ void cast_bf16_to_fp32_cuda_kernel(const bfloat16* input,
|
||||
const int num,
|
||||
float* out) {
|
||||
int idx = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (idx < num) {
|
||||
out[idx] = static_cast<float>(input[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
__global__ void test_bf16_cuda_kernel(const bfloat16* x,
|
||||
const bfloat16* y,
|
||||
const int num,
|
||||
bfloat16* out) {
|
||||
int idx = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (idx < num) {
|
||||
bfloat16 x_i = x[idx], y_i = y[idx];
|
||||
x_i += bfloat16(1);
|
||||
|
||||
out[idx] = (x_i + y_i) * (x_i - y_i);
|
||||
}
|
||||
}
|
||||
|
||||
__global__ void test_fp32_cuda_kernel(const float* x,
|
||||
const float* y,
|
||||
const int num,
|
||||
float* out) {
|
||||
int idx = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (idx < num) {
|
||||
float x_i = x[idx], y_i = y[idx];
|
||||
x_i += 1.0f;
|
||||
|
||||
out[idx] = (x_i + y_i) * (x_i - y_i);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FP16_BF16, basic_cuda) {
|
||||
#ifdef CUDA_VERSION
|
||||
LOG(INFO) << "CUDA version: " << CUDA_VERSION;
|
||||
#endif
|
||||
|
||||
int num = 2048;
|
||||
|
||||
cudaStream_t stream;
|
||||
CUDA_CALL(cudaStreamCreate(&stream));
|
||||
|
||||
dim3 block = 1024;
|
||||
dim3 grid = (num + block.x - 1) / block.x;
|
||||
|
||||
std::vector<float> x_fp32_host(num), y_fp32_host(num);
|
||||
{ // step1 : generate input data
|
||||
std::random_device r;
|
||||
std::default_random_engine eng(r());
|
||||
std::uniform_real_distribution<float> dis(1e-5f, 1.0f);
|
||||
|
||||
for (int i = 0; i < num; ++i) {
|
||||
x_fp32_host[i] = dis(eng);
|
||||
y_fp32_host[i] = dis(eng);
|
||||
}
|
||||
}
|
||||
|
||||
CudaMem x_fp32_device, y_fp32_device, out_fp32_device;
|
||||
{ // step2 : compute fp32 result
|
||||
auto x_fp32_ptr = x_fp32_device.mutable_data<float>(num);
|
||||
auto y_fp32_ptr = y_fp32_device.mutable_data<float>(num);
|
||||
auto out_fp32_ptr = out_fp32_device.mutable_data<float>(num);
|
||||
|
||||
x_fp32_device.MemcpyFromHost(
|
||||
x_fp32_host.data(), num * sizeof(float), stream);
|
||||
y_fp32_device.MemcpyFromHost(
|
||||
y_fp32_host.data(), num * sizeof(float), stream);
|
||||
|
||||
test_fp32_cuda_kernel<<<grid, block, 0, stream>>>(
|
||||
x_fp32_ptr, y_fp32_ptr, num, out_fp32_ptr);
|
||||
}
|
||||
|
||||
CudaMem x_fp16_device, y_fp16_device, out_fp16_device;
|
||||
CudaMem x_bf16_device, y_bf16_device, out_bf16_device;
|
||||
{ // step3 : compute fp16/bf16 result
|
||||
// step3.1 : compute fp16 result
|
||||
auto x_fp16_ptr = x_fp16_device.mutable_data<float16>(num);
|
||||
auto y_fp16_ptr = y_fp16_device.mutable_data<float16>(num);
|
||||
auto out_fp16_ptr = out_fp16_device.mutable_data<float16>(num);
|
||||
|
||||
cast_fp32_to_fp16_cuda_kernel<<<grid, block, 0, stream>>>(
|
||||
x_fp32_device.data<float>(), num, x_fp16_ptr);
|
||||
cast_fp32_to_fp16_cuda_kernel<<<grid, block, 0, stream>>>(
|
||||
y_fp32_device.data<float>(), num, y_fp16_ptr);
|
||||
|
||||
test_fp16_cuda_kernel<<<grid, block, 0, stream>>>(
|
||||
x_fp16_ptr, y_fp16_ptr, num, out_fp16_ptr);
|
||||
|
||||
// step3.2 : compute bf16 result
|
||||
auto x_bf16_ptr = x_bf16_device.mutable_data<bfloat16>(num);
|
||||
auto y_bf16_ptr = y_bf16_device.mutable_data<bfloat16>(num);
|
||||
auto out_bf16_ptr = out_bf16_device.mutable_data<bfloat16>(num);
|
||||
|
||||
cast_fp32_to_bf16_cuda_kernel<<<grid, block, 0, stream>>>(
|
||||
x_fp32_device.data<float>(), num, x_bf16_ptr);
|
||||
cast_fp32_to_bf16_cuda_kernel<<<grid, block, 0, stream>>>(
|
||||
y_fp32_device.data<float>(), num, y_bf16_ptr);
|
||||
|
||||
test_bf16_cuda_kernel<<<grid, block, 0, stream>>>(
|
||||
x_bf16_ptr, y_bf16_ptr, num, out_bf16_ptr);
|
||||
}
|
||||
|
||||
CudaMem fp32res_fp16_device;
|
||||
CudaMem fp32res_bf16_device;
|
||||
{ // step4 : cast fp16/bf16 result to fp32 result
|
||||
// step4.1 : cast fp16 result to fp32 result
|
||||
auto fp32res_fp16_ptr = fp32res_fp16_device.mutable_data<float>(num);
|
||||
cast_fp16_to_fp32_cuda_kernel<<<grid, block, 0, stream>>>(
|
||||
out_fp16_device.data<float16>(), num, fp32res_fp16_ptr);
|
||||
|
||||
// step4.2 : cast bf16 result to fp32 result
|
||||
auto fp32res_bf16_ptr = fp32res_bf16_device.mutable_data<float>(num);
|
||||
cast_bf16_to_fp32_cuda_kernel<<<grid, block, 0, stream>>>(
|
||||
out_bf16_device.data<bfloat16>(), num, fp32res_bf16_ptr);
|
||||
}
|
||||
|
||||
std::vector<float> out_fp32_host(num), out_fp16_host(num), out_bf16_host(num);
|
||||
{ // step5 : copy result from device to host
|
||||
out_fp32_device.MemcpyToHost(
|
||||
out_fp32_host.data(), num * sizeof(float), stream);
|
||||
fp32res_fp16_device.MemcpyToHost(
|
||||
out_fp16_host.data(), num * sizeof(float), stream);
|
||||
fp32res_bf16_device.MemcpyToHost(
|
||||
out_bf16_host.data(), num * sizeof(float), stream);
|
||||
}
|
||||
|
||||
CUDA_CALL(cudaStreamSynchronize(stream));
|
||||
|
||||
for (int i = 0; i < num; ++i) {
|
||||
ASSERT_NEAR(out_fp32_host[i], out_fp16_host[i], 1e-2f);
|
||||
ASSERT_NEAR(out_fp32_host[i], out_bf16_host[i], 1e-1f);
|
||||
}
|
||||
|
||||
CUDA_CALL(cudaStreamDestroy(stream));
|
||||
}
|
||||
|
||||
} // namespace common
|
||||
} // namespace cinn
|
||||
@@ -0,0 +1,104 @@
|
||||
// Copyright (c) 2021 CINN Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
#include "paddle/cinn/common/bfloat16.h"
|
||||
#include "paddle/cinn/common/float16.h"
|
||||
|
||||
namespace cinn {
|
||||
namespace common {
|
||||
|
||||
std::vector<float16> test_fp16_host_kernel(const float16* x,
|
||||
const float16* y,
|
||||
const int num) {
|
||||
std::vector<float16> out(num);
|
||||
for (int idx = 0; idx < num; ++idx) {
|
||||
float16 x_i = x[idx], y_i = y[idx];
|
||||
x_i += float16(1);
|
||||
|
||||
out[idx] = (x_i + y_i) * (x_i - y_i);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::vector<bfloat16> test_bf16_host_kernel(const bfloat16* x,
|
||||
const bfloat16* y,
|
||||
const int num) {
|
||||
std::vector<bfloat16> out(num);
|
||||
for (int idx = 0; idx < num; ++idx) {
|
||||
bfloat16 x_i = x[idx], y_i = y[idx];
|
||||
x_i += bfloat16(1);
|
||||
|
||||
out[idx] = (x_i + y_i) * (x_i - y_i);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::vector<float> test_fp32_host_kernel(const float* x,
|
||||
const float* y,
|
||||
const int num) {
|
||||
std::vector<float> out(num);
|
||||
for (int idx = 0; idx < num; ++idx) {
|
||||
float x_i = x[idx], y_i = y[idx];
|
||||
x_i += 1.0f;
|
||||
|
||||
out[idx] = (x_i + y_i) * (x_i - y_i);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
TEST(FP16_BF16, basic_host) {
|
||||
int num = 2048;
|
||||
// int num = 2;
|
||||
std::vector<float16> x_fp16(num), y_fp16(num);
|
||||
std::vector<bfloat16> x_bf16(num), y_bf16(num);
|
||||
std::vector<float> x_fp32(num), y_fp32(num);
|
||||
|
||||
std::random_device r;
|
||||
std::default_random_engine eng(r());
|
||||
std::uniform_real_distribution<float> dis(1e-5f, 1.0f);
|
||||
|
||||
for (int i = 0; i < num; ++i) {
|
||||
x_fp16[i] = x_fp32[i] = dis(eng);
|
||||
y_fp16[i] = y_fp32[i] = dis(eng);
|
||||
|
||||
x_fp16[i] = x_fp32[i];
|
||||
y_fp16[i] = y_fp32[i];
|
||||
|
||||
x_bf16[i] = x_fp32[i];
|
||||
y_bf16[i] = y_fp32[i];
|
||||
}
|
||||
|
||||
auto out_fp16 = test_fp16_host_kernel(x_fp16.data(), y_fp16.data(), num);
|
||||
ASSERT_EQ(out_fp16.size(), num);
|
||||
|
||||
auto out_bf16 = test_bf16_host_kernel(x_bf16.data(), y_bf16.data(), num);
|
||||
ASSERT_EQ(out_bf16.size(), num);
|
||||
|
||||
auto out_fp32 = test_fp32_host_kernel(x_fp32.data(), y_fp32.data(), num);
|
||||
ASSERT_EQ(out_fp32.size(), num);
|
||||
|
||||
for (int i = 0; i < num; ++i) {
|
||||
ASSERT_NEAR(static_cast<float>(out_fp16[i]), out_fp32[i], 1e-2f);
|
||||
ASSERT_NEAR(static_cast<float>(out_bf16[i]), out_fp32[i], 1e-1f);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace common
|
||||
} // namespace cinn
|
||||
@@ -0,0 +1,341 @@
|
||||
// Copyright (c) 2023 CINN Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "paddle/cinn/common/integer_set.h"
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include "paddle/cinn/ir/op/ir_operators.h"
|
||||
|
||||
namespace cinn {
|
||||
namespace common {
|
||||
|
||||
class TestSymbolicExprAnalyzer : public ::testing::Test {
|
||||
public:
|
||||
void SetUp() override {
|
||||
// Var is [lower_bound, upper_bound)
|
||||
i = ir::Var(ir::Expr(0), ir::Expr(7), "i"); // i ∈ [0, 7)
|
||||
j = ir::Var(ir::Expr(0), ir::Expr(15), "j"); // j ∈ [0, 15)
|
||||
// CasInterval is [lower_bound, upper_bound]
|
||||
var_intervals = {
|
||||
{"i", CasInterval(i->lower_bound, i->upper_bound - 1)}, // i ∈ [0, 6]
|
||||
{"j", CasInterval(j->lower_bound, j->upper_bound - 1)}, // j ∈ [0, 14]
|
||||
};
|
||||
}
|
||||
|
||||
ir::Var i;
|
||||
ir::Var j;
|
||||
cas_intervals_t var_intervals;
|
||||
SymbolicExprAnalyzer analyzer{var_intervals};
|
||||
};
|
||||
|
||||
TEST_F(TestSymbolicExprAnalyzer, bound) {
|
||||
ir::Expr e1 = i + j;
|
||||
EXPECT_EQ(analyzer.LowerBound(e1), ir::Expr(0));
|
||||
EXPECT_EQ(analyzer.UpperBound(e1), ir::Expr(20)); // 6 + 14 = 20
|
||||
|
||||
ir::Expr e2 = 16 * i + j;
|
||||
EXPECT_EQ(analyzer.LowerBound(e2), ir::Expr(0));
|
||||
EXPECT_EQ(analyzer.UpperBound(e2), ir::Expr(110)); // 16 * 6 + 14 = 110
|
||||
|
||||
ir::Expr e3 = 16 * i + j + 1;
|
||||
EXPECT_EQ(analyzer.LowerBound(e3), ir::Expr(1));
|
||||
EXPECT_EQ(analyzer.UpperBound(e3), ir::Expr(111)); // 16 * 6 + 15 = 111
|
||||
|
||||
ir::Expr e4 = (16 * i + j) / 16;
|
||||
EXPECT_EQ(analyzer.LowerBound(e4), ir::Expr(0));
|
||||
EXPECT_EQ(analyzer.UpperBound(e4), ir::Expr(6)); // 110 / 16 = 6
|
||||
|
||||
ir::Expr e5 = (16 * i + j) % 16;
|
||||
EXPECT_EQ(analyzer.LowerBound(e5), ir::Expr(0));
|
||||
EXPECT_EQ(analyzer.UpperBound(e5), ir::Expr(14)); // 110 % 16
|
||||
|
||||
ir::Expr e6 = i - j;
|
||||
EXPECT_EQ(analyzer.LowerBound(e6), ir::Expr(-14)); // 0 - 14
|
||||
EXPECT_EQ(analyzer.UpperBound(e6), ir::Expr(6)); // 6 - 0
|
||||
|
||||
ir::Expr e7 = 0 - i - j;
|
||||
EXPECT_EQ(analyzer.LowerBound(e7), ir::Expr(-20)); // 0 - 6 - 14
|
||||
EXPECT_EQ(analyzer.UpperBound(e7), ir::Expr(0)); // 0 - 0 - 0
|
||||
|
||||
ir::Expr e8 = -1 * i - j;
|
||||
EXPECT_EQ(analyzer.LowerBound(e8), ir::Expr(-20)); // -1 * 6 - 14
|
||||
EXPECT_EQ(analyzer.UpperBound(e8), ir::Expr(0)); // -1 * 0 - 0
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolicExprAnalyzer, compare) {
|
||||
// case 1
|
||||
ir::Expr e1 = 4 * i + 2 * j;
|
||||
ir::Expr e2 = 2 * i + j;
|
||||
|
||||
EXPECT_TRUE(analyzer.ProveEQ(e1, e1).value() &&
|
||||
analyzer.Prove(ir::EQ::Make(e1, e1)).value());
|
||||
EXPECT_FALSE(analyzer.ProveEQ(e1, e2).has_value() ||
|
||||
analyzer.Prove(ir::EQ::Make(e1, e2)).has_value());
|
||||
EXPECT_FALSE(analyzer.ProveNE(e1, e1).value() &&
|
||||
analyzer.Prove(ir::NE::Make(e1, e1)).value());
|
||||
EXPECT_FALSE(analyzer.ProveNE(e1, e2).has_value() ||
|
||||
analyzer.Prove(ir::NE::Make(e1, e2)).has_value());
|
||||
|
||||
EXPECT_TRUE(analyzer.ProveGE(e1, e2).value() &&
|
||||
analyzer.Prove(e1 >= e2).value());
|
||||
EXPECT_FALSE(analyzer.ProveGE(e2, e1).has_value() ||
|
||||
analyzer.Prove(e2 >= e1).has_value());
|
||||
EXPECT_TRUE(analyzer.ProveLE(e2, e1).value() &&
|
||||
analyzer.Prove(e2 <= e1).value());
|
||||
EXPECT_FALSE(analyzer.ProveLE(e1, e2).has_value() ||
|
||||
analyzer.Prove(e1 <= e2).has_value());
|
||||
|
||||
EXPECT_FALSE(analyzer.ProveGT(e1, e2).has_value() ||
|
||||
analyzer.Prove(e1 > e2).has_value());
|
||||
EXPECT_FALSE(analyzer.ProveGT(e2, e1).value() &&
|
||||
analyzer.Prove(e2 > e1).value());
|
||||
EXPECT_FALSE(analyzer.ProveLT(e2, e1).has_value() ||
|
||||
analyzer.Prove(e2 < e1).has_value());
|
||||
EXPECT_FALSE(analyzer.ProveLT(e1, e2).value() &&
|
||||
analyzer.Prove(e1 < e2).value());
|
||||
|
||||
// case 2
|
||||
ir::Expr e3 = i + j + 1;
|
||||
ir::Expr e4 = i + j;
|
||||
|
||||
EXPECT_TRUE(analyzer.ProveEQ(e3, e3).value() &&
|
||||
analyzer.Prove(ir::EQ::Make(e3, e3)).value());
|
||||
EXPECT_FALSE(analyzer.ProveEQ(e3, e4).value() &&
|
||||
analyzer.Prove(ir::EQ::Make(e3, e4)).value());
|
||||
EXPECT_TRUE(analyzer.ProveNE(e3, e4).value() &&
|
||||
analyzer.Prove(ir::NE::Make(e3, e4)).value());
|
||||
EXPECT_FALSE(analyzer.ProveNE(e4, e4).value() &&
|
||||
analyzer.Prove(ir::NE::Make(e4, e4)).value());
|
||||
|
||||
EXPECT_TRUE(analyzer.ProveGE(e3, e4).value() &&
|
||||
analyzer.Prove(e3 >= e4).value());
|
||||
EXPECT_FALSE(analyzer.ProveGE(e4, e3).value() &&
|
||||
analyzer.Prove(e4 >= e3).value());
|
||||
EXPECT_TRUE(analyzer.ProveLE(e4, e3).value() &&
|
||||
analyzer.Prove(e4 <= e3).value());
|
||||
EXPECT_FALSE(analyzer.ProveLE(e3, e4).value() &&
|
||||
analyzer.Prove(e3 <= e4).value());
|
||||
|
||||
EXPECT_TRUE(analyzer.ProveGT(e3, e4).value() &&
|
||||
analyzer.Prove(e3 > e4).value());
|
||||
EXPECT_FALSE(analyzer.ProveGT(e4, e3).value() &&
|
||||
analyzer.Prove(e4 > e3).value());
|
||||
EXPECT_TRUE(analyzer.ProveLT(e4, e3).value() &&
|
||||
analyzer.Prove(e4 < e3).value());
|
||||
EXPECT_FALSE(analyzer.ProveLT(e3, e4).value() &&
|
||||
analyzer.Prove(e3 < e4).value());
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolicExprAnalyzer, Divisible) {
|
||||
auto x = ir::Var(ir::Expr(1), ir::Expr(7), "x");
|
||||
auto y = ir::Var(ir::Expr(1), ir::Expr(15), "y");
|
||||
auto S = ir::Var(ir::Expr(16), ir::Expr(256), "S");
|
||||
|
||||
cas_intervals_t divisible_var_intervals = {
|
||||
{"x", CasInterval(x->lower_bound, x->upper_bound - ir::Expr(1))},
|
||||
{"y", CasInterval(y->lower_bound, y->upper_bound - ir::Expr(1))},
|
||||
{"S", CasInterval(S->lower_bound, S->upper_bound - ir::Expr(1))},
|
||||
};
|
||||
SymbolicExprAnalyzer divisible_analyzer{divisible_var_intervals};
|
||||
|
||||
// case 1
|
||||
ir::Expr e1 = 4 * x + 2 * y * x;
|
||||
ir::Expr e2 = x;
|
||||
ir::Expr e3 = y;
|
||||
|
||||
EXPECT_TRUE(divisible_analyzer.ProveDivisible(e1, e2).value_or(false));
|
||||
EXPECT_FALSE(divisible_analyzer.ProveDivisible(e1, e3).value_or(false));
|
||||
|
||||
// case 2
|
||||
ir::Expr e4 = y + y * x + 4 * y - x * y;
|
||||
|
||||
EXPECT_TRUE(divisible_analyzer.ProveDivisible(e4, e3).value_or(false));
|
||||
EXPECT_FALSE(divisible_analyzer.ProveDivisible(e4, e2).value_or(false));
|
||||
|
||||
// case 3
|
||||
ir::Expr e5 = x / y + x + y;
|
||||
|
||||
EXPECT_FALSE(divisible_analyzer.ProveDivisible(e5, e3).value_or(false));
|
||||
EXPECT_FALSE(divisible_analyzer.ProveDivisible(e5, e2).value_or(false));
|
||||
|
||||
// case 4
|
||||
ir::Expr e6 = S * x / 4 + x * y;
|
||||
|
||||
EXPECT_FALSE(divisible_analyzer.ProveDivisible(e6, e2).value_or(false));
|
||||
EXPECT_FALSE(divisible_analyzer.ProveDivisible(e6, e3).value_or(false));
|
||||
|
||||
ir::Expr e7 = 16 * x / 4 + x * y;
|
||||
|
||||
EXPECT_TRUE(divisible_analyzer.ProveDivisible(e7, e2).value_or(false));
|
||||
EXPECT_FALSE(divisible_analyzer.ProveDivisible(e7, e3).value_or(false));
|
||||
}
|
||||
|
||||
TEST(SingleIntervalIntSet, constant) {
|
||||
SingleIntervalIntSet empty_set(ir::Expr(0), ir::Expr(-1));
|
||||
SingleIntervalIntSet all_set(SymbolicExprLimit::negative_inf,
|
||||
SymbolicExprLimit::positive_inf);
|
||||
SingleIntervalIntSet single_point(ir::Expr(0), ir::Expr(0));
|
||||
SingleIntervalIntSet interval_0_2_set(ir::Expr(0), ir::Expr(2));
|
||||
SingleIntervalIntSet interval_0_4_set(ir::Expr(0), ir::Expr(4));
|
||||
SingleIntervalIntSet interval_2_6_set(ir::Expr(2), ir::Expr(6));
|
||||
SingleIntervalIntSet interval_8_9_set(ir::Expr(8), ir::Expr(9));
|
||||
|
||||
EXPECT_TRUE(empty_set.ProveEmpty().value());
|
||||
EXPECT_FALSE(empty_set.ProveAll().value());
|
||||
EXPECT_FALSE(all_set.ProveEmpty().value());
|
||||
EXPECT_TRUE(all_set.ProveAll().value());
|
||||
EXPECT_TRUE(single_point.ProvePoint().value());
|
||||
EXPECT_FALSE(interval_0_2_set.ProvePoint().value());
|
||||
EXPECT_TRUE(interval_0_2_set.ProveSubSet(interval_0_4_set).value());
|
||||
EXPECT_FALSE(interval_0_4_set.ProveSubSet(interval_0_2_set).value());
|
||||
EXPECT_FALSE(interval_0_2_set.ProveSuperSet(interval_0_4_set).value());
|
||||
EXPECT_TRUE(interval_0_4_set.ProveSuperSet(interval_0_2_set).value());
|
||||
|
||||
EXPECT_TRUE(ProveEQ(interval_0_2_set, interval_0_2_set).value());
|
||||
EXPECT_FALSE(ProveEQ(interval_0_2_set, interval_0_4_set).value());
|
||||
|
||||
SingleIntervalIntSet union_0_6_set =
|
||||
ProvedUnion(interval_0_2_set, interval_2_6_set).value();
|
||||
EXPECT_EQ(union_0_6_set.Min(), ir::Expr(0));
|
||||
EXPECT_EQ(union_0_6_set.Max(), ir::Expr(6));
|
||||
union_0_6_set = ProvedUnion(interval_2_6_set, interval_0_2_set).value();
|
||||
EXPECT_EQ(union_0_6_set.Min(), ir::Expr(0));
|
||||
EXPECT_EQ(union_0_6_set.Max(), ir::Expr(6));
|
||||
SingleIntervalIntSet union_0_4_set =
|
||||
ProvedUnion(interval_0_2_set, interval_0_4_set).value();
|
||||
EXPECT_EQ(union_0_4_set.Min(), ir::Expr(0));
|
||||
EXPECT_EQ(union_0_4_set.Max(), ir::Expr(4));
|
||||
union_0_4_set = ProvedUnion(interval_0_4_set, interval_0_2_set).value();
|
||||
EXPECT_EQ(union_0_4_set.Min(), ir::Expr(0));
|
||||
EXPECT_EQ(union_0_4_set.Max(), ir::Expr(4));
|
||||
SingleIntervalIntSet union_0_9_set =
|
||||
ProvedUnion(interval_0_4_set, interval_8_9_set).value();
|
||||
EXPECT_EQ(union_0_9_set.Min(), ir::Expr(0));
|
||||
EXPECT_EQ(union_0_9_set.Max(), ir::Expr(9));
|
||||
union_0_9_set = ProvedUnion(interval_8_9_set, interval_0_4_set).value();
|
||||
EXPECT_EQ(union_0_9_set.Min(), ir::Expr(0));
|
||||
EXPECT_EQ(union_0_9_set.Max(), ir::Expr(9));
|
||||
|
||||
SingleIntervalIntSet intersect_0_2_set =
|
||||
ProvedIntersect(interval_0_2_set, interval_0_4_set).value();
|
||||
EXPECT_EQ(intersect_0_2_set.Min(), ir::Expr(0));
|
||||
EXPECT_EQ(intersect_0_2_set.Max(), ir::Expr(2));
|
||||
intersect_0_2_set =
|
||||
ProvedIntersect(interval_0_4_set, interval_0_2_set).value();
|
||||
EXPECT_EQ(intersect_0_2_set.Min(), ir::Expr(0));
|
||||
EXPECT_EQ(intersect_0_2_set.Max(), ir::Expr(2));
|
||||
SingleIntervalIntSet intersect_2_2_set =
|
||||
ProvedIntersect(interval_0_2_set, interval_2_6_set).value();
|
||||
EXPECT_EQ(intersect_2_2_set.Min(), ir::Expr(2));
|
||||
EXPECT_EQ(intersect_2_2_set.Max(), ir::Expr(2));
|
||||
intersect_2_2_set =
|
||||
ProvedIntersect(interval_2_6_set, interval_0_2_set).value();
|
||||
EXPECT_EQ(intersect_2_2_set.Min(), ir::Expr(2));
|
||||
EXPECT_EQ(intersect_2_2_set.Max(), ir::Expr(2));
|
||||
SingleIntervalIntSet intersect_empty_set =
|
||||
ProvedIntersect(interval_0_4_set, interval_8_9_set).value();
|
||||
EXPECT_TRUE(intersect_empty_set.ProveEmpty().value());
|
||||
intersect_empty_set =
|
||||
ProvedIntersect(interval_8_9_set, interval_0_4_set).value();
|
||||
EXPECT_TRUE(intersect_empty_set.ProveEmpty().value());
|
||||
}
|
||||
|
||||
TEST(SingleIntervalIntSet, case_0) {
|
||||
ir::Var S0 = ir::Var(ir::Expr(0), ir::Expr(7), "S0");
|
||||
ir::Expr e1 = S0 * 16;
|
||||
ir::Expr e2 = S0 * 16 + 7;
|
||||
ir::Expr e3 = S0 * 16 + 15;
|
||||
SingleIntervalIntSet empty_set(e2, e1);
|
||||
SingleIntervalIntSet single_point(e3, e3);
|
||||
SingleIntervalIntSet set_0(e1, e2);
|
||||
SingleIntervalIntSet set_1(e1, e3);
|
||||
|
||||
EXPECT_TRUE(empty_set.ProveEmpty().value());
|
||||
EXPECT_FALSE(empty_set.ProveAll().value());
|
||||
EXPECT_TRUE(single_point.ProvePoint().value());
|
||||
EXPECT_FALSE(set_0.ProvePoint().value());
|
||||
EXPECT_TRUE(ProveEQ(set_0, set_0).value());
|
||||
EXPECT_FALSE(ProveEQ(set_0, set_1).value());
|
||||
|
||||
EXPECT_TRUE(set_0.ProveSubSet(set_1).value());
|
||||
EXPECT_FALSE(set_1.ProveSubSet(set_0).value());
|
||||
EXPECT_FALSE(set_0.ProveSuperSet(set_1).value());
|
||||
EXPECT_TRUE(set_1.ProveSuperSet(set_0).value());
|
||||
|
||||
EXPECT_TRUE(ProveEQ(ProvedUnion(set_0, set_1).value(), set_1).value());
|
||||
EXPECT_TRUE(ProveEQ(ProvedIntersect(set_0, set_1).value(), set_0).value());
|
||||
EXPECT_TRUE(ProveEQ(ProvedUnion(set_1, single_point).value(), set_1).value());
|
||||
EXPECT_TRUE(
|
||||
ProveEQ(ProvedIntersect(set_1, single_point).value(), single_point)
|
||||
.value());
|
||||
EXPECT_TRUE(ProveEQ(ProvedUnion(set_0, empty_set).value(), set_0).value());
|
||||
EXPECT_TRUE(
|
||||
ProveEQ(ProvedIntersect(set_0, empty_set).value(), empty_set).value());
|
||||
EXPECT_TRUE(ProveEQ(ProvedUnion(set_0, single_point).value(), set_1).value());
|
||||
EXPECT_TRUE(ProvedIntersect(set_0, single_point).value().ProveEmpty());
|
||||
}
|
||||
|
||||
TEST(SingleIntervalIntSet, case_1) {
|
||||
ir::Var S0 = ir::Var(ir::Expr(0), ir::Expr(7), "S0");
|
||||
ir::Var S1 = ir::Var(ir::Expr(0), ir::Expr(15), "S1");
|
||||
ir::Expr e1 = S0 * 16;
|
||||
ir::Expr e2 = S0 * 16 + S1;
|
||||
ir::Expr e3 = S0 * 16 + S1 * 2 + 1;
|
||||
SingleIntervalIntSet empty_set(e3, e1);
|
||||
SingleIntervalIntSet single_point(e3, e3);
|
||||
SingleIntervalIntSet set_0(e1, e2);
|
||||
SingleIntervalIntSet set_1(e1, e3);
|
||||
|
||||
EXPECT_TRUE(empty_set.ProveEmpty().value());
|
||||
EXPECT_FALSE(empty_set.ProveAll().value());
|
||||
EXPECT_TRUE(single_point.ProvePoint().value());
|
||||
EXPECT_FALSE(set_0.ProvePoint().has_value());
|
||||
EXPECT_TRUE(ProveEQ(set_0, set_0).value());
|
||||
EXPECT_FALSE(ProveEQ(set_0, set_1).value());
|
||||
|
||||
EXPECT_TRUE(set_0.ProveSubSet(set_1).value());
|
||||
EXPECT_FALSE(set_1.ProveSubSet(set_0).value());
|
||||
EXPECT_FALSE(set_0.ProveSuperSet(set_1).value());
|
||||
EXPECT_TRUE(set_1.ProveSuperSet(set_0).value());
|
||||
|
||||
EXPECT_TRUE(ProveEQ(ProvedUnion(set_0, set_1).value(), set_1).value());
|
||||
EXPECT_TRUE(ProveEQ(ProvedIntersect(set_0, set_1).value(), set_0).value());
|
||||
EXPECT_TRUE(ProveEQ(ProvedUnion(set_1, single_point).value(), set_1).value());
|
||||
EXPECT_TRUE(
|
||||
ProveEQ(ProvedIntersect(set_1, single_point).value(), single_point)
|
||||
.value());
|
||||
EXPECT_TRUE(ProveEQ(ProvedUnion(set_0, empty_set).value(), set_0).value());
|
||||
EXPECT_TRUE(
|
||||
ProveEQ(ProvedIntersect(set_0, empty_set).value(), empty_set).value());
|
||||
EXPECT_TRUE(ProveEQ(ProvedUnion(set_0, single_point).value(), set_1).value());
|
||||
EXPECT_TRUE(
|
||||
ProvedIntersect(set_0, single_point).value().ProveEmpty().value());
|
||||
}
|
||||
|
||||
TEST(SingleIntervalIntSet, case_2) {
|
||||
ir::Var S = ir::Var(ir::Expr(0), ir::Expr(1), "S"); // S ∈ [0, 1)
|
||||
|
||||
SingleIntervalIntSet set_0{S, S + Expr(1)}; // [0, 1]
|
||||
SingleIntervalIntSet set_1{Expr(0), Expr(1)}; // [0, 1]
|
||||
SingleIntervalIntSet set_2{Expr(0), Expr(2)}; // [0, 2]
|
||||
|
||||
EXPECT_TRUE(ProveEQ(set_0, set_1).value());
|
||||
EXPECT_FALSE(ProveEQ(set_0, set_2).value());
|
||||
EXPECT_TRUE(set_0.ProveSubSet(set_2).value());
|
||||
EXPECT_TRUE(set_2.ProveSuperSet(set_0).value());
|
||||
}
|
||||
|
||||
} // namespace common
|
||||
} // namespace cinn
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2023 CINN Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "paddle/cinn/common/is_reachable_predicator.h"
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace cinn {
|
||||
namespace common {
|
||||
|
||||
TEST(IsReachablePredicator, simple) {
|
||||
IsReachablePredicator<int> IsReachable(
|
||||
// Get min depth
|
||||
[](int x) { return std::abs(x); },
|
||||
// Get max depth
|
||||
[](int x) { return std::abs(x); },
|
||||
// visit next node
|
||||
[](int x, const std::function<void(int)>& Handler) {
|
||||
Handler(x + (x / std::abs(x)));
|
||||
});
|
||||
EXPECT_TRUE(IsReachable(33, 99, [](int) {}));
|
||||
EXPECT_FALSE(IsReachable(33, -99, [](int) {}));
|
||||
}
|
||||
|
||||
} // namespace common
|
||||
} // namespace cinn
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2021 CINN Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "paddle/cinn/common/shared.h"
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "paddle/cinn/common/object.h"
|
||||
|
||||
namespace cinn {
|
||||
namespace common {
|
||||
|
||||
struct A : public Object {
|
||||
const char *type_info() const override { return "A"; }
|
||||
|
||||
Shared<A> other;
|
||||
};
|
||||
|
||||
class B : public Object {};
|
||||
|
||||
TEST(Shared, test) {
|
||||
Shared<A> a_ref(make_shared<A>());
|
||||
ASSERT_EQ(ref_count(a_ref.get()).val(), 1);
|
||||
|
||||
{ // local copy
|
||||
Shared<A> b = a_ref;
|
||||
EXPECT_EQ(ref_count(a_ref.get()).val(), 2);
|
||||
ASSERT_EQ(ref_count(b.get()).val(), 2);
|
||||
}
|
||||
|
||||
ASSERT_EQ(ref_count(a_ref.get()).val(), 1);
|
||||
}
|
||||
|
||||
TEST(Shared, cycle_share) {
|
||||
{
|
||||
Shared<A> a_ref(make_shared<A>());
|
||||
a_ref->other = a_ref;
|
||||
ASSERT_EQ(a_ref->__ref_count__.val(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace common
|
||||
} // namespace cinn
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2023 CINN Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "paddle/cinn/common/topo_walker.h"
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace cinn {
|
||||
namespace common {
|
||||
|
||||
TEST(TopoWalker, simple) {
|
||||
std::vector<std::pair<int, int>> edges{
|
||||
{0, 3}, {1, 2}, {1, 3}, {2, 3}, {3, 4}};
|
||||
TopoWalker<int> visitor(
|
||||
[&](int node, const std::function<void(int)>& NodeHandler) {
|
||||
for (const auto& pair : edges) {
|
||||
if (pair.second == node) {
|
||||
NodeHandler(pair.first);
|
||||
}
|
||||
}
|
||||
},
|
||||
[&](int node, const std::function<void(int)>& NodeHandler) {
|
||||
for (const auto& pair : edges) {
|
||||
if (pair.first == node) {
|
||||
NodeHandler(pair.second);
|
||||
}
|
||||
}
|
||||
});
|
||||
std::vector<int> sources{0, 1};
|
||||
std::vector<int> outputs;
|
||||
visitor(sources.begin(), sources.end(), [&](int node) {
|
||||
outputs.push_back(node);
|
||||
});
|
||||
std::vector<int> expected{0, 1, 2, 3, 4};
|
||||
EXPECT_TRUE((outputs == expected));
|
||||
}
|
||||
|
||||
} // namespace common
|
||||
} // namespace cinn
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2021 CINN Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "paddle/cinn/common/type.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace cinn::common {
|
||||
|
||||
TEST(Type, basic) {
|
||||
LOG(INFO) << I32();
|
||||
|
||||
auto i32 = I32();
|
||||
LOG(INFO) << I32();
|
||||
|
||||
LOG(INFO) << F32();
|
||||
LOG(INFO) << type_of<float>();
|
||||
}
|
||||
|
||||
} // namespace cinn::common
|
||||
Reference in New Issue
Block a user