Skip to content

Conversation

@tqchen
Copy link
Member

@tqchen tqchen commented Oct 2, 2018

  • Changed ShapeExpr->IndexExpr as it is mostly used for index
  • port conv2d from nnvm spec, with the following changes:
    • kernel_size, channels are no longer mandatory
    • layout->data_layout
    • kernel_layout -> weight_layout(to be consistent with the weight, data argument name)
    • bias is no longer attached to conv2d
  • Port layout.h into relay with minimum modification

This PR represents what is generally need to be done to port an NNVM operator to relay, most of the logic remains the same

  • Implement the TypeRelation function
    • The shapes represented by IndexExpr(symbolic integer)
    • User reporter->Assign to set the inferred result
    • Use reporter->AssertEQ to assert symbolic integer equivalence
      • It will return false if there is an unsatisfied constraint
  • Use tvm::Attrs to replace of dmlc::Parameter
  • We switch to directly create python wrappers by calling into positional functions so that the operator signature is explicit in python.

Examples

Although I am not completely happy with the current python DSL API(relay.ir_builder). The example test case does show some interesting improvement over what we can do previously, for example, we can already do limited symbolic inference with batch dimension as symbolic

def test_conv2d_infer_type():
    # symbolic in batch dimension
    ib = relay.ir_builder.IRBuilder()
    n, c, h, w = tvm.var("n"), 10, 224, 224
    x = ib.param("x", relay.ty.TensorType((n, c, h, w), "float32"))
    w = ib.param("w", relay.ty.IncompleteType())

    with ib.function(x, w) as func:
        ib.ret(relay.nn.conv2d(x.var, w.var,
                               kernel_size=(3, 3),
                               padding=(1, 1),
                               channels=2))
    ib.ret(func)
    func = relay.ir_pass.infer_type(ib.env, func.to_func())
    ftype = func.checked_type()
    assert ftype.ret_type == relay.ty.TensorType(
        (n, 2, 224, 224), "float32")
    assert ftype.arg_types[1] == relay.ty.TensorType(
        (10, 2, 3, 3), "float32")

    # infer by shape of w, mixed precision
    ib = relay.ir_builder.IRBuilder()
    n, c, h, w = tvm.var("n"), 10, 224, 224
    x = ib.param("x", relay.ty.TensorType((n, c, h, w), "int8"))
    w = ib.param("w", relay.ty.TensorType((2, 10, 3, 3), "int8"))
    with ib.function(x, w) as func:
        ib.ret(relay.nn.conv2d(x.var, w.var, out_dtype="int32"))
    ib.ret(func)
    func = relay.ir_pass.infer_type(ib.env, func.to_func())
    ftype = func.checked_type()
    assert ftype.ret_type == relay.ty.TensorType(
        (n, 2, 222, 222), "int32")

@tqchen
Copy link
Member Author

tqchen commented Oct 2, 2018

@junrushao
Copy link
Member

Rushing for an exam. Will check it out tomorrow evening.

* indicates the split dimension.
* return undefined layout if "__undef__" is passed.
*/
inline Layout(const std::string& layout) { // NOLINT(*)
Copy link
Member

Choose a reason for hiding this comment

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

I think there is no need to have inline. Definitions inside a class will be treated as inlined automatically. Same to the methods that implemented in this class below.

* \return shape in target layout
*/
inline std::vector<IndexExpr> ConvertLayout(
std::vector<IndexExpr> src,
Copy link
Member

Choose a reason for hiding this comment

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

const &?

Copy link
Member Author

Choose a reason for hiding this comment

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

const is not used in here as it can be used for copy-elison when directly returning it

}

inline std::vector<IndexExpr> ConvertLayout(
Array<IndexExpr> src,
Copy link
Member

Choose a reason for hiding this comment

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

const & ?

void ShapeEqual(Array<ShapeExpr> s1, Array<ShapeExpr> s2) {}
void ShapeEqual(Array<IndexExpr> s1, Array<IndexExpr> s2) {}

void VisitType_(const TensorTypeNode *tt1, const Type& t2) final {
Copy link
Member

Choose a reason for hiding this comment

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

TensorTypeNode* tt1

<< ": invalid factor size " << factor
<< " before dimension " << c;
CHECK_EQ(superdim_pos_[pos], -1) << "Invalid layout " << layout
<< ": duplicate dimension " << c;
Copy link
Contributor

Choose a reason for hiding this comment

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

remove two space?

int pos = c - 'a';
CHECK_GT(factor, 0) << "Invalid layout " << layout << ": invalid factor size "
<< factor << " for dimension " << c;
CHECK_EQ(subdim_pos_[pos], -1) << "Invalid layout " << layout
Copy link
Contributor

Choose a reason for hiding this comment

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

remove two space to align

ib.ret(func)
func = relay.ir_pass.infer_type(ib.env, func.to_func())
ftype = func.checked_type()
assert ftype.ret_type == relay.ty.TensorType(
Copy link
Contributor

Choose a reason for hiding this comment

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

@tqchen
I tried some hands on with this test case and observed this comparison hold good only for the dtype not for shape.

Am I missing some thing here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Can you elaborate? The testcase should works for shape as well

Copy link
Contributor

Choose a reason for hiding this comment

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

assert ftype.ret_type == relay.ty.TensorType((n, 2, 224, 224), "float32")

To

assert ftype.ret_type == relay.ty.TensorType((n, 2, 100, 100), "float32")

doesn't fail.

Copy link
Member Author

Choose a reason for hiding this comment

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

Great catch, this is actually due to a problem in alpha_eq comparator, I have fixed this in recent commit

@tqchen
Copy link
Member Author

tqchen commented Oct 4, 2018

@MarisaKirisame @zhiics Thanks for the comments, i have fixed them

Number of groups for grouped convolution.
data_layout : str, optional
Layout of the input.
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 mention the possible options for data_layout, weight_layout etc?

Copy link
Contributor

Choose a reason for hiding this comment

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

@junrushao1994

It can be a sample then complete list if required.
The possible options list is very long and is explained in layout header.

Copy link
Member

@junrushao junrushao Oct 4, 2018

Choose a reason for hiding this comment

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

@srkreddy1238 My comment here is too picky. Definitely It is not a big deal.

I am just a little bit worried whether Python frontend users will be willing to check C APIs described in tvm::relay::ConvAttrs defined in include/tvm/relay/attrs/nn.h.

@zhiics
Copy link
Member

zhiics commented Oct 4, 2018

@tqchen Seems some test cases failed. Please fix them.

@tqchen
Copy link
Member Author

tqchen commented Oct 4, 2018

Thanks @srkreddy1238 's comment uncovering the problem of alpha eq, this leads to a few more problems to be uncovered. It is a good reminder for us to have good test coverage, in light of that. I have added more test cases for conv2d including the layout transformation.

@zhiics @srkreddy1238 @MarisaKirisame please review again

Copy link
Contributor

@srkreddy1238 srkreddy1238 left a comment

Choose a reason for hiding this comment

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

Layout conversion on oshape is also addressed now & LGTM.

Number of groups for grouped convolution.
data_layout : str, optional
Layout of the input.
Copy link
Contributor

Choose a reason for hiding this comment

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

@junrushao1994

It can be a sample then complete list if required.
The possible options list is very long and is explained in layout header.

Copy link
Member

@junrushao junrushao left a comment

Choose a reason for hiding this comment

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

The PR looks good to me.

Number of groups for grouped convolution.
data_layout : str, optional
Layout of the input.
Copy link
Member

@junrushao junrushao Oct 4, 2018

Choose a reason for hiding this comment

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

@srkreddy1238 My comment here is too picky. Definitely It is not a big deal.

I am just a little bit worried whether Python frontend users will be willing to check C APIs described in tvm::relay::ConvAttrs defined in include/tvm/relay/attrs/nn.h.

@tqchen tqchen merged commit 9afde69 into apache:master Oct 4, 2018
@tqchen
Copy link
Member Author

tqchen commented Oct 4, 2018

Thanks @junrushao1994 @srkreddy1238 @zhiics @MarisaKirisame this is now merged. I agree with @junrushao1994 that we might want to list common options here, maybe not all of them

FrozenGene pushed a commit to FrozenGene/tvm that referenced this pull request Dec 27, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants