Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions onnxruntime/core/graph/conv_add_fusion.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,27 +36,42 @@ Status ConvAddFusion::Apply(onnxruntime::Graph& graph, bool& modified) const {

// Currently, fusion is only supported for float or double data type.
if (!Initializer::IsSupportedDataType(add_B_tensor_proto) ||
conv_W_tensor_proto->dims_size() != 4 ||
add_B_tensor_proto->dims_size() != 3 ||
conv_W_tensor_proto->dims_size() < 4 ||
add_B_tensor_proto->dims_size() != conv_W_tensor_proto->dims_size() - 1 ||
conv_W_tensor_proto->dims(0) != add_B_tensor_proto->dims(0)) {
continue;
}

// The dimensions of add_B should be equal to 1 except first dimension.
bool flag = false;
for (int i = 1; i < add_B_tensor_proto->dims_size(); i++) {
if (add_B_tensor_proto->dims(i) != 1) {
flag = true;
break;
}
}

if (flag) {
continue;
}

const ONNX_NAMESPACE::TensorProto* conv_B_tensor_proto = nullptr;
if (conv_inputs.size() == 3) {
graph.GetInitializedTensor(conv_inputs[2]->Name(), conv_B_tensor_proto);

if (!Initializer::IsSupportedDataType(conv_B_tensor_proto) ||
conv_B_tensor_proto->data_type() != add_B_tensor_proto->data_type() ||
conv_B_tensor_proto->dims_size() != 1 ||
add_B_tensor_proto->dims_size() != 3 ||
conv_B_tensor_proto->dims(0) != add_B_tensor_proto->dims(0)) {
continue;
}

auto conv_B = std::make_unique<Initializer>(conv_B_tensor_proto);
auto add_B = std::make_unique<Initializer>(add_B_tensor_proto);

if (conv_B->size() != add_B->size()) {
continue;
}
// Calculate new value of initializers of conv node
conv_B->add(*add_B);

Expand Down
35 changes: 26 additions & 9 deletions onnxruntime/core/graph/conv_mul_fusion.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,29 @@ Status ConvMulFusion::Apply(onnxruntime::Graph& graph, bool& modified) const {
if (!Initializer::IsSupportedDataType(conv_W_tensor_proto) ||
!Initializer::IsSupportedDataType(mul_B_tensor_proto) ||
conv_W_tensor_proto->data_type() != mul_B_tensor_proto->data_type() ||
!(conv_W_tensor_proto->dims_size() > 2 && conv_W_tensor_proto->dims(0) == mul_B_tensor_proto->dims(0))) {
conv_W_tensor_proto->dims_size() < 4 ||
!(mul_B_tensor_proto->dims_size() == 0 ||
(mul_B_tensor_proto->dims_size() == conv_W_tensor_proto->dims_size() - 1 &&
conv_W_tensor_proto->dims(0) == mul_B_tensor_proto->dims(0)))) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does this have the same problem as the conv_add_fusion where the other dims of the multiplier should be 1?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, it is better to check it.

continue;
}

auto conv_W = std::make_unique<Initializer>(conv_W_tensor_proto);
auto mul_B = std::make_unique<Initializer>(mul_B_tensor_proto);
// The dimensions of mul_B should be equal to 1 except first dimension.
if (mul_B_tensor_proto->dims_size() != 0) {
bool flag = false;
for (int i = 1; i < mul_B_tensor_proto->dims_size(); i++) {
if (mul_B_tensor_proto->dims(i) != 1) {
flag = true;
break;
}
}

if (conv_W->data_type() != mul_B->data_type() ||
!(conv_W->dims().size() > 2 && conv_W->dims()[0] == mul_B->dims()[0])) {
continue;
if (flag) {
continue;
}
}
auto conv_W = std::make_unique<Initializer>(conv_W_tensor_proto);
auto mul_B = std::make_unique<Initializer>(mul_B_tensor_proto);

const ONNX_NAMESPACE::TensorProto* conv_B_tensor_proto = nullptr;
std::unique_ptr<Initializer> conv_B = nullptr;
Expand All @@ -57,17 +69,22 @@ Status ConvMulFusion::Apply(onnxruntime::Graph& graph, bool& modified) const {

if (!Initializer::IsSupportedDataType(conv_B_tensor_proto) ||
conv_B_tensor_proto->data_type() != mul_B_tensor_proto->data_type() ||
conv_B_tensor_proto->dims_size() != 1 || mul_B_tensor_proto->dims_size() != 3 ||
conv_B_tensor_proto->dims(0) != mul_B_tensor_proto->dims(0)) {
conv_B_tensor_proto->dims_size() != 1 || (mul_B_tensor_proto->dims_size() != 0 &&
conv_B_tensor_proto->dims(0) != mul_B_tensor_proto->dims(0))) {
continue;
}
conv_B = std::make_unique<Initializer>(conv_B_tensor_proto);
}

// Calculate new value of initializers of conv node
conv_W->scale_by_axis(*mul_B, 1);

if (conv_inputs.size() == 3) {
conv_B->mul(*mul_B);
if (mul_B_tensor_proto->dims_size() != 0) {
conv_B->mul(*mul_B);
} else {
conv_B->scale_by_axis(*mul_B, 0);
}
}

// Create new initializers of conv
Expand Down
91 changes: 62 additions & 29 deletions onnxruntime/core/graph/initializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,19 +190,22 @@ class Initializer final {
return dims_;
}

size_t size() const { return size_; }
int64_t size() const { return size_; }

Initializer& add(float value) {
int64_t n = size();
switch (data_type_) {
case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: {
for (int i = 0; i < size_; i++) {
data<float>()[i] += value;
float* dst = data<float>();
for (int i = 0; i < n; i++) {
dst[i] += value;
}
break;
}
case ONNX_NAMESPACE::TensorProto_DataType_DOUBLE: {
for (int i = 0; i < size_; i++) {
data<double>()[i] += value;
double* dst = data<double>();
for (int i = 0; i < n; i++) {
dst[i] += value;
}
break;
}
Expand All @@ -213,16 +216,21 @@ class Initializer final {
}

Initializer& add(const Initializer& other) {
int64_t n = size();
switch (data_type_) {
case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: {
for (int i = 0; i < size_; i++) {
data<float>()[i] += other.data<float>()[i];
float* dst = data<float>();
const float* src = other.data<float>();
for (int i = 0; i < n; i++) {
dst[i] += src[i];
}
break;
}
case ONNX_NAMESPACE::TensorProto_DataType_DOUBLE: {
for (int i = 0; i < size_; i++) {
data<double>()[i] += other.data<double>()[i];
double* dst = data<double>();
const double* src = other.data<double>();
for (int i = 0; i < n; i++) {
dst[i] += src[i];
}
break;
}
Expand All @@ -232,16 +240,21 @@ class Initializer final {
return *this;
}
Initializer& sub(const Initializer& other) {
int64_t n = size();
switch (data_type_) {
case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: {
for (int i = 0; i < size_; i++) {
data<float>()[i] -= other.data<float>()[i];
float* dst = data<float>();
const float* src = other.data<float>();
for (int i = 0; i < n; i++) {
dst[i] -= src[i];
}
break;
}
case ONNX_NAMESPACE::TensorProto_DataType_DOUBLE: {
for (int i = 0; i < size_; i++) {
data<double>()[i] -= other.data<double>()[i];
double* dst = data<double>();
const double* src = other.data<double>();
for (int i = 0; i < n; i++) {
dst[i] -= src[i];
}
break;
}
Expand All @@ -252,16 +265,21 @@ class Initializer final {
}

Initializer& mul(const Initializer& other) {
int64_t n = size();
switch (data_type_) {
case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: {
for (int i = 0; i < size_; i++) {
data<float>()[i] *= other.data<float>()[i];
float* dst = data<float>();
const float* src = other.data<float>();
for (int i = 0; i < n; i++) {
dst[i] *= src[i];
}
break;
}
case ONNX_NAMESPACE::TensorProto_DataType_DOUBLE: {
for (int i = 0; i < size_; i++) {
data<double>()[i] *= other.data<double>()[i];
double* dst = data<double>();
const double* src = other.data<double>();
for (int i = 0; i < n; i++) {
dst[i] *= src[i];
}
break;
}
Expand All @@ -271,16 +289,21 @@ class Initializer final {
return *this;
}
Initializer& div(const Initializer& other) {
int64_t n = size();
switch (data_type_) {
case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: {
for (int i = 0; i < size_; i++) {
data<float>()[i] /= other.data<float>()[i];
float* dst = data<float>();
const float* src = other.data<float>();
for (int i = 0; i < n; i++) {
dst[i] /= src[i];
}
break;
}
case ONNX_NAMESPACE::TensorProto_DataType_DOUBLE: {
for (int i = 0; i < size_; i++) {
data<double>()[i] /= other.data<double>()[i];
double* dst = data<double>();
const double* src = other.data<double>();
for (int i = 0; i < n; i++) {
dst[i] /= src[i];
}
break;
}
Expand All @@ -291,16 +314,19 @@ class Initializer final {
}

Initializer& sqrt() {
int64_t n = size();
switch (data_type_) {
case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: {
for (int i = 0; i < size_; i++) {
data<float>()[i] = std::sqrt(data<float>()[i]);
float* dst = data<float>();
for (int i = 0; i < n; i++) {
dst[i] = std::sqrt(dst[i]);
}
break;
}
case ONNX_NAMESPACE::TensorProto_DataType_DOUBLE: {
for (int i = 0; i < size_; i++) {
data<double>()[i] = std::sqrt(data<double>()[i]);
double* dst = data<double>();
for (int i = 0; i < n; i++) {
dst[i] = std::sqrt(dst[i]);
}
break;
}
Expand All @@ -316,19 +342,26 @@ class Initializer final {
num *= dims_[k];
}

int64_t n = size()/num;
switch (data_type_) {
case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: {
for (int64_t i = 0; i < dims_[0]; i++) {
float* dst = data<float>();
const float* src = other.data<float>();
for (int i = 0; i < n; i++) {
int index = other.size() == 1 ? 0 : i;
for (int64_t j = 0; j < num; j++) {
data<float>()[i * num + j] *= other.data<float>()[i];
dst[i * num + j] *= src[index];
}
}
break;
}
case ONNX_NAMESPACE::TensorProto_DataType_DOUBLE: {
for (int64_t i = 0; i < dims_[0]; i++) {
double* dst = data<double>();
const double* src = other.data<double>();
for (int i = 0; i < n; i++) {
int index = other.size() == 1 ? 0 : i;
for (int64_t j = 0; j < num; j++) {
data<double>()[i * num + j] *= other.data<double>()[i];
dst[i * num + j] *= src[index];
}
}
break;
Expand Down
Loading