Skip to content

[RELAY][PASS] add a relay pass to count #macs of a model#2609

Merged
yzhliu merged 14 commits intoapache:masterfrom
yidawang:count_macs
Feb 20, 2019
Merged

[RELAY][PASS] add a relay pass to count #macs of a model#2609
yzhliu merged 14 commits intoapache:masterfrom
yidawang:count_macs

Conversation

@yidawang
Copy link
Contributor

@yidawang yidawang commented Feb 16, 2019

ATT. Currently it only counts the macs of direct CONV 2D and Dense.

@icemelon9 @zhiics @yzhliu

@eqy
Copy link
Contributor

eqy commented Feb 16, 2019

Currently the number of real MACs can be dependent on the algorithm used (e.g., when winograd is suitable). Do we plan to consider these cases?

@yidawang yidawang changed the title add a relay pass to count #macs of a model [RELAY][PASS] add a relay pass to count #macs of a model Feb 16, 2019
@yidawang
Copy link
Contributor Author

Currently the number of real MACs can be dependent on the algorithm used (e.g., when winograd is suitable). Do we plan to consider these cases?

Yes, we can gradually improve the coverage.

Array<Expr> args = call_node->args;
CHECK(args.size() == 2)
<< "The number of input arguments of a CONV 2D node should be 2.";
const auto* expr0 = args[0]->checked_type().as<TensorTypeNode>();
Copy link
Member

Choose a reason for hiding this comment

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

expr0 -> type? because it's actually a type node instead of an expr node.

return 0;
}
Array<Expr> args = call_node->args;
CHECK(args.size() == 2)
Copy link
Member

Choose a reason for hiding this comment

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

I am not sure if we still need these checks. Are they supposed to be valid already since we have already inferred types.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it wouldn't hurt. This code can still run with warning if the infer type pass is not called.

Array<Expr> args = call_node->args;
CHECK(args.size() == 2)
<< "The number of input arguments of a Dense node should be 2.";
const auto* expr0 = args[0]->checked_type().as<TensorTypeNode>();
Copy link
Member

Choose a reason for hiding this comment

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

same as above, probably more descriptive name, like data_type and weight_type


int64_t GetCartesianProd(Array<IndexExpr> arr) {
int64_t ret = 1;
for (int i = 0; i < arr.size(); i++) {
Copy link
Member

Choose a reason for hiding this comment

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

int -> size_t since arr.size() is size_t or probably just for (const auto& it : arr)

dshape2 = (m, k)
data1 = relay.var("data1", shape=dshape1)
data2 = relay.var("data2", shape=dshape2)
gemm = relay.nn.dense(
Copy link
Member

Choose a reason for hiding this comment

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

one liner ?

import tvm
from tvm import relay
import sys
sys.path.append('../frontend/mxnet')
Copy link
Member

Choose a reason for hiding this comment

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

Sorry, why do we need to add it to the system path?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is to import the model_zoo from this path correctly. I am happy to change to a more elegant solution if any suggestion.

Copy link
Member

Choose a reason for hiding this comment

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

I actually suggest to remove the resnet test, as no one can verify the correctness of the test by eyeball. And later if the algorithm changes or enhanced, it will also be a pain to deal with such test.

class MacCounter : private ExprVisitor {
public:
MacCounter() {
count_ = 0;
Copy link
Member

Choose a reason for hiding this comment

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

two space indent

const auto* data_type = args[0]->checked_type().as<TensorTypeNode>();
Array<IndexExpr> data_shape = data_type->shape;
CHECK(data_shape.size() == 4)
<< "The dimension of an input tensor to Dense node should be 4.";
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
<< "The dimension of an input tensor to Dense node should be 4.";
<< "The dimension of an input tensor to Conv2D node should be 4.";

some non-4D conv implement also use Conv2dAttrs though... I think the dimension of input & output does not really matter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If a non-4D conv uses Conv2dAttrs, perhaps we should pick it out, otherwise the output wouldn't make sense?

count_ += ComputeConv2DMacs(call_node);
} else if (IsDenseNode(call_node)) {
count_ += ComputeDenseMacs(call_node);
}
Copy link
Member

Choose a reason for hiding this comment

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

should we log somewhere to remind users the pass only calculates MAC for Conv2D and Dense?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a log info in the beginning of the pass.

Copy link
Member

@yzhliu yzhliu left a comment

Choose a reason for hiding this comment

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

@eqy @zhiics Please take a look again.

int32_t C_ind = Layout(data_layout).Indexof('C');
int32_t c_ind = Layout(data_layout).Indexof('c');
CHECK(C_ind != -1 || c_ind != -1)
<< "There is no input channel dimension.";
Copy link
Member

Choose a reason for hiding this comment

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

C_ind must exist actually.

@zhiics
Copy link
Member

zhiics commented Feb 19, 2019

LGTM

@yzhliu yzhliu merged commit 615fd69 into apache:master Feb 20, 2019
@yzhliu
Copy link
Member

yzhliu commented Feb 20, 2019

Thanks @yidawang @zhiics @eqy This is merged now.

@tqchen
Copy link
Member

tqchen commented Feb 20, 2019

Thanks, @yidawang @zhiics @eqy @yzhliu . Some followup comments would be nice to address as a followup:

  • So far the code uses hard-code pattern matching, it is a bit hard to generalize when we add ops
  • Avoid the use of dynamic_cast, mainly because it requires RTTI features. In our case, static_cast and our build in generic type checking good for most cases

wweic pushed a commit to neo-ai/tvm that referenced this pull request Feb 20, 2019
* add a relay pass to count #macs of a model

* remove unnecessary includes

* fix end-of-file issues

* address review comments

* remove test resnet

* address more review comments

* use data layout string to locate the input channel

* fix bug in conv 2d output tensor checking

* C must exist
@yidawang yidawang deleted the count_macs branch February 21, 2019 20:09
@yidawang
Copy link
Contributor Author

Thanks for the feedback, @tqchen

As the MAC counting is an estimation, we only take those computationally-intensive ops into account. Therefore, I don't envision that we will extend it to many ops. We can definitely switch to your suggested attribute registration style if necessary. We will add new ops as needed.

I will send out a quick PR to fix the dynamic cast issue soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants