feat: 整理子项目结构,实现一部分导入

Signed-off-by: YdrMaster <ydrml@hotmail.com>
This commit is contained in:
YdrMaster 2023-04-20 14:47:05 +08:00
parent 9cfe223953
commit cc62a3216d
16 changed files with 320 additions and 5 deletions

View File

@ -62,6 +62,7 @@ endif()
include_directories(include)
add_subdirectory(optimization)
include_directories(optimization/include)
# Pybind11
add_subdirectory(3rd-party/pybind11)

View File

@ -5,4 +5,4 @@
namespace infini {
void start_interpreter();
} // namespace infini
} // namespace infini

View File

@ -4,6 +4,8 @@ project(optimization LANGUAGES CXX C)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_CXX_FLAGS "$ENV{CMAKE_CXX_FLAGS} -fPIC")
file(GLOB_RECURSE SRC src/*.h src/*.cc src/*.cpp)
add_library(optimization ${SRC})

View File

@ -0,0 +1,3 @@
#pragma once
#include "../../src/mutation.h"

View File

@ -4,6 +4,8 @@
#include <cstring>
#include <vector>
namespace optimization {
/// @brief Stores tensor data。
struct Data {
/// @brief `cpu_data` is stored in the memory space,
@ -28,3 +30,5 @@ struct Data {
return ans;
}
};
} // namespace optimization

View File

@ -1,5 +1,7 @@
#include "data_type.h"
using namespace optimization;
size_t DataType::size() const {
switch (id) {
case DataTypeId::FLOAT:

View File

@ -3,6 +3,8 @@
#include <cstddef>
#include <cstdint>
namespace optimization {
enum class DataTypeId : uint8_t {
UNDEFINED,
FLOAT,
@ -41,3 +43,5 @@ template <> inline DataType ty<bool>() { return {DataTypeId::BOOL}; }
template <> inline DataType ty<double>() { return {DataTypeId::DOUBLE}; }
template <> inline DataType ty<uint32_t>() { return {DataTypeId::UINT32}; }
template <> inline DataType ty<uint64_t>() { return {DataTypeId::UINT64}; }
} // namespace optimization

View File

@ -1,5 +1,7 @@
#include "graph.h"
using namespace optimization;
static size_t GRAPH_ID = 1;
Unigraph::Unigraph() : id(GRAPH_ID++) {}

View File

@ -3,6 +3,8 @@
#include "op_type.h"
#include "tensor.h"
namespace optimization {
/// @brief a struct to represent an operator in the computation graph.
/// The ownership of an `Operator` belongs to one `Unigraph`.
struct Operator {
@ -49,3 +51,5 @@ struct Unigraph {
Vec<Arc<Tensor>> outputs //
);
};
} // namespace optimization

View File

@ -1,7 +1,10 @@
#include "mutation.h"
#include <unordered_set>
Vec<std::pair<Unigraph, SingleOperator>> split_each(Unigraph &&g) {
using namespace optimization;
Vec<std::pair<Unigraph, SingleOperator>>
optimization::split_each(Unigraph &&g) {
Vec<std::pair<Unigraph, SingleOperator>> ans;
for (auto &op : g.operators) {
auto &[g, t] = ans.emplace_back();
@ -10,7 +13,7 @@ Vec<std::pair<Unigraph, SingleOperator>> split_each(Unigraph &&g) {
return ans;
}
float memory_usage(Unigraph const &g) {
float optimization::memory_usage(Unigraph const &g) {
std::unordered_set<size_t> mark;
uintptr_t memory;
for (const auto &op : g.operators)

View File

@ -3,6 +3,8 @@
#include "graph.h"
#include <functional>
namespace optimization {
/// @brief A candidate subgraph mutant.
struct Mutant {
/// @brief The mutated subgraph.
@ -165,3 +167,5 @@ template <class t> Vec<size_t> list_size(Vec<SubGraph<t>> const &list) {
[](const auto &e) { return e.mutants.size(); });
return ans;
}
} // namespace optimization

View File

@ -2,6 +2,8 @@
#include <cstdint>
namespace optimization {
enum class OpType : uint16_t {
Abs,
Acos,
@ -190,3 +192,5 @@ enum class OpType : uint16_t {
Where,
Xor,
};
} // namespace optimization

View File

@ -1,6 +1,8 @@
#include "tensor.h"
#include <numeric>
using namespace optimization;
Arc<Tensor> Tensor::share(Vec<size_t> shape, DataType data_type, Data data) {
return Arc<Tensor>(
new Tensor(std::move(shape), std::move(data_type), std::move(data)));

View File

@ -6,6 +6,8 @@
#include <unordered_map>
#include <vector>
namespace optimization {
/// @brief Defines a template alias for `std::vector`.
template <class t> using Vec = std::vector<t>;
@ -45,6 +47,25 @@ struct Tensor {
/// @return A `shared_ptr<Tensor>`.
static Arc<Tensor> share(Vec<size_t> shape, DataType data_type, Data data);
/// @brief A static factory method to create a `shared_ptr<Tensor>` with
/// single data.
/// @tparam t Data type.
/// @param val Data value.
/// @return A `shared_ptr<Tensor>`.
template <class t> static Arc<Tensor> share_single(t val) {
return Tensor::share({1}, ty<t>(), Data::cpu<t>({val}));
}
/// @brief A static factory method to create a `shared_ptr<Tensor>` with
/// 1D data.
/// @tparam t Data type.
/// @param val Data value.
/// @return A `shared_ptr<Tensor>`.
template <class t> static Arc<Tensor> share_vec(Vec<t> val) {
return Tensor::share({val.size()}, ty<t>(),
Data::cpu<t>(std::move(val)));
}
/// @brief Calculates the size of the tensor in bytes.
/// @return Memory usage in bytes.
size_t size() const;
@ -53,3 +74,5 @@ struct Tensor {
/// @brief Constructor is private and only accessible by the factory method.
Tensor(Vec<size_t> &&, DataType &&, Data &&);
};
} // namespace optimization

View File

@ -2,6 +2,8 @@
#include <iostream>
#include <unordered_set>
using namespace optimization;
int main() {
try {
Unigraph g;

View File

@ -1,4 +1,9 @@
#include "core/graph.h"
#include "operators/concat.h"
#include "operators/conv.h"
#include "operators/gather.h"
#include "operators/unary.h"
#include "optimization/common.h"
#include <algorithm>
#include <queue>
@ -114,13 +119,262 @@ bool GraphObj::topo_sort() {
return this->sorted = true;
}
optimization::DataType cast(DataType ty) {
#define IT(A, B) \
if (ty == DataType::A) \
return {optimization::DataTypeId::B};
IT(Float32, FLOAT) //
else IT(UInt32, UINT32) //
else IT(UInt8, UINT8) //
else IT(Int8, INT8) //
else IT(UInt16, UINT16) //
else IT(Int16, INT16) //
else IT(Int32, INT32) //
else IT(Int64, INT64) //
else IT_ASSERT(false, "unsupported data type");
#undef IT
}
optimization::OpType cast(OpType ty) {
#define IT(A, B) \
case OpType::A: \
return optimization::OpType::B
switch (ty) {
IT(Abs, Abs);
IT(Add, Add);
IT(And, And);
IT(AvgPool, AveragePool);
IT(BatchNorm, BatchNormalization);
IT(Cast, Cast);
IT(Clip, Clip);
IT(Concat, Concat);
IT(Conv, Conv);
IT(ConvTrans, ConvTranspose);
IT(Cos, Cos);
IT(Div, Div);
IT(Dropout, Dropout);
IT(Erf, Erf);
IT(Exp, Exp);
IT(Flatten, Flatten);
IT(Gather, Gather);
IT(Identity, Identity);
IT(Log, Log);
IT(Matmul, MatMul);
IT(MaxPool, MaxPool);
IT(Mul, Mul);
IT(Neg, Neg);
IT(Not, Not);
IT(Or, Or);
IT(PRelu, PRelu);
IT(Pad, Pad);
IT(Pow, Pow);
IT(ReduceMean, ReduceMean);
IT(Relu, Relu);
IT(Reshape, Reshape);
IT(Resize, Resize);
IT(Shape, Shape);
IT(Sigmoid, Sigmoid);
IT(Sin, Sin);
IT(SinH, Sinh);
IT(Slice, Slice);
IT(Softmax, Softmax);
IT(Split, Split);
IT(Sqrt, Sqrt);
IT(Sub, Sub);
IT(Tan, Tan);
IT(TanH, Tanh);
IT(Transpose, Transpose);
IT(Xor, Xor);
default:
IT_ASSERT(false);
break;
}
#undef IT
}
void GraphObj::optimize() {
for (auto &op : ops) {
namespace opt = optimization;
topo_sort();
#define I(PTR) reinterpret_cast<uintptr_t>((PTR).get())
unordered_map<uintptr_t, opt::Arc<opt::Tensor>> tensors;
for (const auto &t : this->getTensors()) {
const auto dims = t->getDims();
opt::Vec<size_t> shape(dims.size());
std::transform(dims.begin(), dims.end(), shape.begin(),
[](auto x) { return static_cast<size_t>(x); });
opt::Data data{};
if (t->hasData()) {
auto origin = t->getDataBlob();
data.cpu_data.resize(t->getBytes());
memcpy(data.cpu_data.data(), origin->getPtr<uint8_t *>(),
data.cpu_data.size());
}
tensors[I(t)] =
opt::Tensor::share(shape, cast(t->getDType()), std::move(data));
}
opt::Unigraph ans;
for (const auto &op : this->getOperators()) {
const auto inputs = op->getInputs(), outputs = op->getOutputs();
opt::Vec<opt::Arc<opt::Tensor>> in(inputs.size()), out(outputs.size());
std::transform(inputs.begin(), inputs.end(), in.begin(),
[&](auto x) { return tensors[I(x)]; });
std::transform(outputs.begin(), outputs.end(), out.begin(),
[&](auto x) { return tensors[I(x)]; });
switch (op->getOpType()) {
case OpType::Abs:
ans.push_operator(opt::OpType::Abs, std::move(in), std::move(out));
break;
case OpType::ACos:
ans.push_operator(opt::OpType::Acos, std::move(in), std::move(out));
break;
case OpType::ACosH:
ans.push_operator(opt::OpType::Acosh, std::move(in),
std::move(out));
break;
case OpType::Add:
ans.push_operator(opt::OpType::Add, std::move(in), std::move(out));
break;
case OpType::And:
ans.push_operator(opt::OpType::And, std::move(in), std::move(out));
break;
case OpType::ASin:
ans.push_operator(opt::OpType::Asin, std::move(in), std::move(out));
break;
case OpType::ASinH:
ans.push_operator(opt::OpType::Asinh, std::move(in),
std::move(out));
break;
case OpType::ATan:
ans.push_operator(opt::OpType::Atan, std::move(in), std::move(out));
break;
case OpType::ATanH:
ans.push_operator(opt::OpType::Atanh, std::move(in),
std::move(out));
break;
case OpType::AvgPool:
ans.push_operator(opt::OpType::AveragePool, std::move(in),
std::move(out));
break;
case OpType::BatchNorm:
ans.push_operator(opt::OpType::BatchNormalization, std::move(in),
std::move(out));
break;
case OpType::BitLeftShift:
in.push_back(opt::Tensor::share_single<uint8_t>(0));
ans.push_operator(opt::OpType::BitShift, std::move(in),
std::move(out));
break;
case OpType::BitRightShift:
in.push_back(opt::Tensor::share_single<uint8_t>(1));
ans.push_operator(opt::OpType::BitShift, std::move(in),
std::move(out));
break;
case OpType::BitAnd:
ans.push_operator(opt::OpType::BitwiseAnd, std::move(in),
std::move(out));
break;
case OpType::BitNot:
ans.push_operator(opt::OpType::BitwiseNot, std::move(in),
std::move(out));
break;
case OpType::BitOr:
ans.push_operator(opt::OpType::BitwiseOr, std::move(in),
std::move(out));
break;
case OpType::BitXor:
ans.push_operator(opt::OpType::BitwiseXor, std::move(in),
std::move(out));
break;
case OpType::Cast:
ans.push_operator(opt::OpType::Cast, std::move(in), std::move(out));
break;
case OpType::Ceil:
ans.push_operator(opt::OpType::Ceil, std::move(in), std::move(out));
break;
case OpType::Clip: {
auto obj = as<ClipObj>(op);
auto min = obj->getMin();
auto max = obj->getMax();
in.push_back(
opt::Tensor::share_single<float>(min ? *min : -INFINITY));
in.push_back(
opt::Tensor::share_single<float>(max ? *max : INFINITY));
ans.push_operator(opt::OpType::Clip, std::move(in), std::move(out));
} break;
case OpType::Concat:
in.push_back(
opt::Tensor::share_single<int>(as<ConcatObj>(op)->getDim()));
ans.push_operator(opt::OpType::Concat, std::move(in),
std::move(out));
break;
case OpType::Conv: {
auto obj = as<ConvObj>(op);
in.push_back(opt::Tensor::share_vec<size_t>(
{(size_t)obj->getDh(), (size_t)obj->getDw()}));
in.push_back(opt::Tensor::share_vec<size_t>(
{(size_t)obj->getPh(), (size_t)obj->getPw()}));
in.push_back(opt::Tensor::share_vec<size_t>(
{(size_t)obj->getSh(), (size_t)obj->getSw()}));
ans.push_operator(opt::OpType::Conv, std::move(in), std::move(out));
} break;
case OpType::Cos:
ans.push_operator(opt::OpType::Cos, std::move(in), std::move(out));
break;
case OpType::CosH:
ans.push_operator(opt::OpType::Cosh, std::move(in), std::move(out));
break;
case OpType::Div:
ans.push_operator(opt::OpType::Div, std::move(in), std::move(out));
break;
case OpType::Dropout:
ans.push_operator(opt::OpType::Dropout, std::move(in),
std::move(out));
break;
case OpType::Exp:
ans.push_operator(opt::OpType::Exp, std::move(in), std::move(out));
break;
case OpType::Flatten:
ans.push_operator(opt::OpType::Flatten, std::move(in),
std::move(out));
break;
case OpType::Floor:
ans.push_operator(opt::OpType::Floor, std::move(in),
std::move(out));
break;
case OpType::Gather:
in.push_back(
opt::Tensor::share_single<int>(as<GatherObj>(op)->getAxis()));
ans.push_operator(opt::OpType::Gather, std::move(in),
std::move(out));
break;
case OpType::GreaterThan:
ans.push_operator(opt::OpType::Greater, std::move(in),
std::move(out));
break;
case OpType::GreaterEqual:
ans.push_operator(opt::OpType::GreaterOrEqual, std::move(in),
std::move(out));
break;
case OpType::Identity:
ans.push_operator(opt::OpType::Identity, std::move(in),
std::move(out));
break;
default:
break;
}
}
#undef I
}
void GraphObj::dataMalloc() {
@ -191,7 +445,8 @@ void GraphObj::replaceConnection(Tensor oldTensor, Tensor newTensor,
// tensor's "source" and "target" must be in "ops".
// tensor has no "source" and no "target" must not exist.
// "inputs" or "outputs" of operators must be in "tensors"
// "predecessors" and "successors" of an operator of "ops" must be in "ops".
// "predecessors" and "successors" of an operator of "ops" must be in
// "ops".
bool GraphObj::checkValid() const {
for (auto tensor : tensors) {
IT_ASSERT(!(tensor->getTargets().size() == 0 &&