Skip to content

Commit

Permalink
Refactor optimization passes to subfolder
Browse files Browse the repository at this point in the history
  • Loading branch information
kraiskil committed May 18, 2023
1 parent d21f194 commit 74abde7
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 76 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ add_library(onnx2c_lib STATIC
src/node.cc
src/tensor.cc
src/util.cc
src/optimization_passes/unionize_tensors.cpp
${CMAKE_CURRENT_BINARY_DIR}/onnx.pb.cc
src/nodes/cast.cc
src/nodes/constantofshape.cc
Expand Down
76 changes: 0 additions & 76 deletions src/graph.cc
Original file line number Diff line number Diff line change
Expand Up @@ -584,80 +584,4 @@ void Graph::replaceWithQuantized(std::vector<Tensor*> &inputs)
}


// add t to union. Return allocated union number
uint32_t Graph::add_to_free_union(Tensor *t)
{
unsigned u=0;
// Check if tensor is already allocated to an union
for( ; u<tensor_unions.size(); u++ )
if( tensor_unions[u] == t)
return u;

// If not, search for free unions
u=0;
for( ; u<tensor_unions.size(); u++ )
if( tensor_unions[u] == NULL ) {
tensor_unions[u] = t;
t->assign_union(u);
return u;
}

// All unions in use, need a new one
LOG(TRACE) << "No free unions, creating a new one" << std::endl;
tensor_unions.push_back(t);
t->assign_union( tensor_unions.size()-1 );
return t->union_no;
}
void Graph::mark_union_unoccupied(uint32_t u)
{
tensor_unions[u]=NULL;
}
// tag intermediate (graph internal) tensors
// with union numbers so they can share memory
// in a temporal fashion
void Graph::unionize_tensors(void)
{
for( auto n : nodes ) {
n->isResolved = false;
}

for( auto n : nodes ) {

// for each output tensor of node
for( auto o : n->outputs ) {
// assign tensor to next free union
// if it is an internal tensor that gets
// calculated by a node.
if( o->is_used() == false )
continue;
if( o->isIO == true )
continue;
// the Constant node is a bit weird - this check must be in
if( o->isConst == true )
continue;
if( o->initialize == true )
continue;
add_to_free_union(o);
}
// mark node as resolved
n->isResolved = true;

// Check if union slots can be re-used
for( unsigned ui=0; ui < tensor_unions.size(); ui++ ) {
Tensor *t = tensor_unions[ui];
// skip free slots
if ( t==NULL )
continue;

// when all the consumers of this tensors have consumed it
// the tensor is nolonger needed, and the union is free to host
// a new tensor
bool all_resolved = true;
for( auto c : t->consumers )
all_resolved &= c->isResolved;
if (all_resolved)
mark_union_unoccupied(ui);
}
}
}

12 changes: 12 additions & 0 deletions src/optimization_passes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
This folder contains the optimization passes onnx2c runs.

Due to lack of up-front design, and surplus development time later,
these passes are not stand-alone, but rather a part of the (ever
increasingly pointless) Graph object.

Setting up a mechanism of stand-alone optimization passes that can
mutate the Graph via a public API sounds like a cleanup task that
would make the code look much cleaner.

But add a few optimization passes before starting to design such an API.

81 changes: 81 additions & 0 deletions src/optimization_passes/unionize_tensors.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#include "graph.h"
#include <cstdint>

using namespace toC;
// add t to union. Return allocated union number
uint32_t Graph::add_to_free_union(Tensor *t)
{
unsigned u=0;
// Check if tensor is already allocated to an union
for( ; u<tensor_unions.size(); u++ )
if( tensor_unions[u] == t)
return u;

// If not, search for free unions
u=0;
for( ; u<tensor_unions.size(); u++ )
if( tensor_unions[u] == NULL ) {
tensor_unions[u] = t;
t->assign_union(u);
return u;
}

// All unions in use, need a new one
LOG(TRACE) << "No free unions, creating a new one" << std::endl;
tensor_unions.push_back(t);
t->assign_union( tensor_unions.size()-1 );
return t->union_no;
}
void Graph::mark_union_unoccupied(uint32_t u)
{
tensor_unions[u]=NULL;
}
// tag intermediate (graph internal) tensors
// with union numbers so they can share memory
// in a temporal fashion
void Graph::unionize_tensors(void)
{
for( auto n : nodes ) {
n->isResolved = false;
}

for( auto n : nodes ) {

// for each output tensor of node
for( auto o : n->outputs ) {
// assign tensor to next free union
// if it is an internal tensor that gets
// calculated by a node.
if( o->is_used() == false )
continue;
if( o->isIO == true )
continue;
// the Constant node is a bit weird - this check must be in
if( o->isConst == true )
continue;
if( o->initialize == true )
continue;
add_to_free_union(o);
}
// mark node as resolved
n->isResolved = true;

// Check if union slots can be re-used
for( unsigned ui=0; ui < tensor_unions.size(); ui++ ) {
Tensor *t = tensor_unions[ui];
// skip free slots
if ( t==NULL )
continue;

// when all the consumers of this tensors have consumed it
// the tensor is nolonger needed, and the union is free to host
// a new tensor
bool all_resolved = true;
for( auto c : t->consumers )
all_resolved &= c->isResolved;
if (all_resolved)
mark_union_unoccupied(ui);
}
}
}

0 comments on commit 74abde7

Please sign in to comment.