Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/ python graph API and strongly typed ID #252

Merged
merged 19 commits into from
Mar 7, 2024
11 changes: 9 additions & 2 deletions include/ion/builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,21 @@ class Builder {
~Builder();

/**
* Adding new node to the graph.
* Adding new node to the builder.
* @arg k: The key of the node which should be matched with second argument of ION_REGISTER_BUILDING_BLOCK().
*/
Node add(const std::string& name);

/**
* Adding new node to the specific graph.
* @arg k: The key of the node which should be matched with second argument of ION_REGISTER_BUILDING_BLOCK().
* @arg id: graph unique identifier
*/
Node add(const std::string& name, const std::string& graph_id);

/**
*
* Adding new node to the graph.
* @arg k: The key of the node which should be matched with second argument of ION_REGISTER_BUILDING_BLOCK().
*/
Graph add_graph(const std::string& name);

Expand Down
8 changes: 8 additions & 0 deletions include/ion/c_ion.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ typedef struct ion_node_t_ *ion_node_t;
typedef struct ion_builder_t_ *ion_builder_t;
typedef struct ion_buffer_t_ *ion_buffer_t;
typedef struct ion_port_map_t_ *ion_port_map_t;
typedef struct ion_graph_t_ *ion_graph_t;

int ion_port_create(ion_port_t *, const char *, ion_type_t, int);
int ion_port_create_with_index(ion_port_t *, ion_port_t , int);
Expand Down Expand Up @@ -62,6 +63,7 @@ int ion_builder_create(ion_builder_t *);
int ion_builder_destroy(ion_builder_t);
int ion_builder_set_target(ion_builder_t, const char *);
int ion_builder_with_bb_module(ion_builder_t, const char *);
int ion_builder_add_graph(ion_builder_t, const char *, ion_graph_t *);
int ion_builder_add_node(ion_builder_t, const char *, ion_node_t *);
int ion_builder_compile(ion_builder_t, const char *, ion_builder_compile_option_t option);
int ion_builder_save(ion_builder_t, const char *);
Expand All @@ -76,6 +78,12 @@ int ion_buffer_destroy(ion_buffer_t);
int ion_buffer_write(ion_buffer_t, void *, int size);
int ion_buffer_read(ion_buffer_t, void *, int size);

int ion_graph_create(ion_graph_t *, ion_builder_t, const char *);
int ion_graph_add_node(ion_graph_t, const char*, ion_node_t *);
int ion_graph_destroy(ion_graph_t);
int ion_graph_run(ion_graph_t);
int ion_graph_create_with_multiple(ion_graph_t *, ion_graph_t obj1, ion_graph_t obj2);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm considering more straitforward naming. e.g. ion_graph_create_from_2 ? Do you have any better idea?


[[deprecated("ion_port_bind* can be used instead of ion_port_map.")]]
int ion_port_map_create(ion_port_map_t *);
[[deprecated("ion_port_bind* can be used instead of ion_port_map.")]]
Expand Down
30 changes: 28 additions & 2 deletions include/ion/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ class Node {
struct Impl {
std::string id;
std::string name;
std::string graph_id;
Halide::Target target;
std::vector<Param> params;
std::vector<Port> ports;
std::vector<Halide::Internal::AbstractGenerator::ArgInfo> arginfos;

Impl(): id(), name(), target(), params(), ports() {}

Impl(const std::string& id_, const std::string& name_, const Halide::Target& target_);
Impl(const std::string& id_, const std::string& name_, const Halide::Target& target_, const std::string& graph_id_);
};

public:
Expand Down Expand Up @@ -76,7 +77,7 @@ class Node {
*/
template<typename... Args>
Node operator()(Args ...args) {
set_iport(std::vector<Port>{args...});
set_iport(create_ports_vector(args...));
return *this;
}

Expand Down Expand Up @@ -126,6 +127,31 @@ class Node {
{
}

Node(const std::string& id, const std::string& name, const Halide::Target& target, const std::string& graph_id)
: impl_(new Impl{id, name, target, graph_id})
{
}


template<typename... Args>
std::vector<Port> create_ports_vector(Args... args) const {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please clarify necessity of the wrapper function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the confusion, this is unnecessary and I delete it

return {get_iport(args)...};
}

Port get_iport(Port arg) const {
// if input is port
return arg;
}

template<typename T>
Port get_iport(Halide::Buffer<T>& arg) const {
// if input is halide buffer
if (impl_->graph_id.empty())
return Port(arg);
else
return Port(arg, impl_->graph_id);
}

std::shared_ptr<Impl> impl_;
};

Expand Down
52 changes: 35 additions & 17 deletions include/ion/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class Port {
private:
struct Impl {
std::string id;
std::string graph_id;
Channel pred_chan;
std::set<Channel> succ_chans;

Expand All @@ -64,12 +65,12 @@ class Port {
std::unordered_map<uint32_t, const void *> instances;

Impl();
Impl(const std::string& pid, const std::string& pn, const Halide::Type& t, int32_t d);
Impl(const std::string& pid, const std::string& pn, const Halide::Type& t, int32_t d, const std::string& gid );
};

public:

Port() : impl_(new Impl("", "", Halide::Type(), 0)), index_(-1) {}
Port() : impl_(new Impl("", "", Halide::Type(), 0, "")), index_(-1) {}

Port(const std::shared_ptr<Impl>& impl, int32_t index) : impl_(impl), index_(index) {}

Expand All @@ -78,38 +79,54 @@ class Port {
* @arg k: The key of the port which should be matched with BuildingBlock Input/Output name.
* @arg t: The type of the value.
*/
Port(const std::string& n, Halide::Type t) : impl_(new Impl("", n, t, 0)), index_(-1) {}
Port(const std::string& n, Halide::Type t) : impl_(new Impl("", n, t, 0, "")), index_(-1) {}

/**
* Construct new port for vector value.
* @arg k: The key of the port which should be matched with BuildingBlock Input/Output name.
* @arg t: The type of the element value.
* @arg d: The dimension of the port. The range is 1 to 4.
*/
Port(const std::string& n, Halide::Type t, int32_t d) : impl_(new Impl("", n, t, d)), index_(-1) {}
Port(const std::string& n, Halide::Type t, int32_t d) : impl_(new Impl("", n, t, d, "")), index_(-1) {}

/**
* Construct new port from scalar pointer
*/
template<typename T,
typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
Port(T *vptr) : impl_(new Impl("", Halide::Internal::unique_name("_ion_port_"), Halide::type_of<T>(), 0)), index_(-1) {
Port(T *vptr) : impl_(new Impl("", Halide::Internal::unique_name("_ion_port_"), Halide::type_of<T>(), 0, "")), index_(-1) {
this->bind(vptr);
}

/**
* Construct new port from buffer
*/
template<typename T>
Port(const Halide::Buffer<T>& buf) : impl_(new Impl("", buf.name(), buf.type(), buf.dimensions())), index_(-1) {
Port(const Halide::Buffer<T>& buf) : impl_(new Impl("", buf.name(), buf.type(), buf.dimensions(), "")), index_(-1) {
this->bind(buf);
}

/**
* Construct new port from buffer and bind graph id to port
*/
template<typename T>
Port(const Halide::Buffer<T>& buf, const std::string& gid) : impl_(new Impl("", buf.name(), buf.type(), buf.dimensions(), gid)), index_(-1) {
this->bind(buf);
}

/**
* Construct new port from array of buffer
*/
template<typename T>
Port(const std::vector<Halide::Buffer<T>>& bufs) : impl_(new Impl("", unify_name(bufs), Halide::type_of<T>(), unify_dimension(bufs))), index_(-1) {
Port(const std::vector<Halide::Buffer<T>>& bufs) : impl_(new Impl("", unify_name(bufs), Halide::type_of<T>(), unify_dimension(bufs), "")), index_(-1) {
this->bind(bufs);
}

/**
* Construct new port from array of buffer and bind graph id to port
*/
template<typename T>
Port(const std::vector<Halide::Buffer<T>>& bufs, const std::string& gid) : impl_(new Impl("", unify_name(bufs), Halide::type_of<T>(), unify_dimension(bufs), gid)), index_(-1) {
this->bind(bufs);
}

Expand All @@ -123,6 +140,7 @@ class Port {
int32_t dimensions() const { return impl_->dimensions; }
int32_t size() const { return static_cast<int32_t>(impl_->params.size()); }
int32_t index() const { return index_; }
const std::string& graph_id() const { return impl_->graph_id; }

// Setter
void set_index(int index) { index_ = index; }
Expand Down Expand Up @@ -153,9 +171,9 @@ class Port {
void bind(T *v) {
auto i = index_ == -1 ? 0 : index_;
if (has_pred()) {
impl_->params[i] = Halide::Internal::Parameter{Halide::type_of<T>(), false, 0, argument_name(pred_id(), pred_name(), i)};
impl_->params[i] = Halide::Internal::Parameter{Halide::type_of<T>(), false, 0, argument_name(pred_id(), pred_name(), i, graph_id())};
} else {
impl_->params[i] = Halide::Internal::Parameter{type(), false, dimensions(), argument_name(pred_id(), pred_name(), i)};
impl_->params[i] = Halide::Internal::Parameter{type(), false, dimensions(), argument_name(pred_id(), pred_name(), i,graph_id())};
}

impl_->instances[i] = v;
Expand All @@ -166,9 +184,9 @@ class Port {
void bind(const Halide::Buffer<T>& buf) {
auto i = index_ == -1 ? 0 : index_;
if (has_pred()) {
impl_->params[i] = Halide::Internal::Parameter{buf.type(), true, buf.dimensions(), argument_name(pred_id(), pred_name(), i)};
impl_->params[i] = Halide::Internal::Parameter{buf.type(), true, buf.dimensions(), argument_name(pred_id(), pred_name(), i,graph_id())};
} else {
impl_->params[i] = Halide::Internal::Parameter{type(), true, dimensions(), argument_name(pred_id(), pred_name(), i)};
impl_->params[i] = Halide::Internal::Parameter{type(), true, dimensions(), argument_name(pred_id(), pred_name(), i,graph_id())};
}

impl_->instances[i] = buf.raw_buffer();
Expand All @@ -178,9 +196,9 @@ class Port {
void bind(const std::vector<Halide::Buffer<T>>& bufs) {
for (int i=0; i<static_cast<int>(bufs.size()); ++i) {
if (has_pred()) {
impl_->params[i] = Halide::Internal::Parameter{bufs[i].type(), true, bufs[i].dimensions(), argument_name(pred_id(), pred_name(), i)};
impl_->params[i] = Halide::Internal::Parameter{bufs[i].type(), true, bufs[i].dimensions(), argument_name(pred_id(), pred_name(), i, graph_id())};
} else {
impl_->params[i] = Halide::Internal::Parameter{type(), true, dimensions(), argument_name(pred_id(), pred_name(), i)};
impl_->params[i] = Halide::Internal::Parameter{type(), true, dimensions(), argument_name(pred_id(), pred_name(), i, graph_id())};
}

impl_->instances[i] = bufs[i].raw_buffer();
Expand All @@ -199,7 +217,7 @@ class Port {
if (es.size() <= i) {
es.resize(i+1, Halide::Expr());
}
es[i] = Halide::Internal::Variable::make(type(), argument_name(pred_id(), pred_name(), i), param);
es[i] = Halide::Internal::Variable::make(type(), argument_name(pred_id(), pred_name(), i, graph_id()), param);
}
return es;
}
Expand All @@ -220,7 +238,7 @@ class Port {
args.push_back(Halide::Var::implicit(i));
args_expr.push_back(Halide::Var::implicit(i));
}
Halide::Func f(param.type(), param.dimensions(), argument_name(pred_id(), pred_name(), i) + "_im");
Halide::Func f(param.type(), param.dimensions(), argument_name(pred_id(), pred_name(), i, graph_id()) + "_im");
f(args) = Halide::Internal::Call::make(param, args_expr);
fs[i] = f;
}
Expand All @@ -234,7 +252,7 @@ class Port {
args.resize(i+1, Halide::Argument());
}
auto kind = dimensions() == 0 ? Halide::Argument::InputScalar : Halide::Argument::InputBuffer;
args[i] = Halide::Argument(argument_name(pred_id(), pred_name(), i), kind, type(), dimensions(), Halide::ArgumentEstimates());
args[i] = Halide::Argument(argument_name(pred_id(), pred_name(), i, graph_id()), kind, type(), dimensions(), Halide::ArgumentEstimates());
}
return args;
}
Expand All @@ -257,7 +275,7 @@ class Port {
* pid and pn is stored in both pred and succ,
* then it will determined through pipeline build process.
*/
Port(const std::string& pid, const std::string& pn) : impl_(new Impl(pid, pn, Halide::Type(), 0)), index_(-1) {}
Port(const std::string& pid, const std::string& pn) : impl_(new Impl(pid, pn, Halide::Type(), 0, "")), index_(-1) {}

std::shared_ptr<Impl> impl_;

Expand Down
2 changes: 1 addition & 1 deletion include/ion/port_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class PortMap {
template<typename T>
[[deprecated("Port::bind can be used instead of PortMap.")]]
void set(Port port, T v) {
auto& buf(scalar_buffer_[argument_name(port.pred_id(), port.pred_name(), port.index())]);
auto& buf(scalar_buffer_[argument_name(port.pred_id(), port.pred_name(), port.index(), "")]);
buf.resize(sizeof(v));
std::memcpy(buf.data(), &v, sizeof(v));
port.bind(reinterpret_cast<T*>(buf.data()));
Expand Down
2 changes: 1 addition & 1 deletion include/ion/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace ion {

class Port;

std::string argument_name(const std::string& node_id, const std::string& name, int32_t index);
std::string argument_name(const std::string& node_id, const std::string& name, int32_t index, const std::string& graph_id);

std::string array_name(const std::string& port_name, size_t i);

Expand Down
7 changes: 7 additions & 0 deletions src/builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ Node Builder::add(const std::string& name)
return n;
}

Node Builder::add(const std::string& name, const std::string& graph_id)
{
Node n(sole::uuid4().str(), name, impl_->target, graph_id);
impl_->nodes.push_back(n);
return n;
}

Graph Builder::add_graph(const std::string& name) {
Graph g(*this, name);
impl_->graphs.push_back(g);
Expand Down
Loading
Loading