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

[TOPI][Relay][OP] Add a strided_set operation. #4303

Merged
merged 10 commits into from
Dec 3, 2019

Conversation

abergeron
Copy link
Contributor

This adds essentially the inverse of strided_slice where you set the values selected to a new set of values. The result is a new tensor that is a copy of the first input with some values replaced.

@abergeron
Copy link
Contributor Author

I did the necessary rebase.

@yzhliu
Copy link
Member

yzhliu commented Nov 14, 2019

is it used in dl frameworks?

@tqchen
Copy link
Member

tqchen commented Nov 15, 2019

cc @jroesch @junrushao1994 can you also take a look?

Comment on lines 315 to 318
ls = len(strides)
if ls < n:
strides = list(strides)
strides[ls:] = [1] * (n - ls)
Copy link
Member

Choose a reason for hiding this comment

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

You can make it slightly shorter.

strides = list(strides) + [1] * (n - len(strides))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

Comment on lines 320 to 323
if lb < n:
begin = list(begin)
for i in range(lb, n):
begin.append(0 if strides[i] >= 0 else inputs.shape[i])
Copy link
Member

Choose a reason for hiding this comment

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

same here

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 a bit different because the value to append might be different at each index. It depends on the stride for that index. I'm not sure how to shorten that.

Copy link
Member

Choose a reason for hiding this comment

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

It’s fine, no worries :-)

Comment on lines 325 to 329
if le < n:
end = list(end)
for i in range(le, n):
lim = inputs[0].shape[i] + 1
end.append(lim if strides[i] >= 0 else -lim)
Copy link
Member

Choose a reason for hiding this comment

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

same here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same as for begin.

@junrushao
Copy link
Member

@yzhliu I think this is something like a[strides] = b

# Convert negative indexes
for i in range(n):
begin[i] = tvm.if_then_else(begin[i] < 0,
begin[i] + a.shape[i],
Copy link
Member

Choose a reason for hiding this comment

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

Even begin[i] + a.shape[i] could trigger OOB. I am not sure how to assert the bound...Could anyone help here?

Copy link
Contributor Author

@abergeron abergeron Nov 15, 2019

Choose a reason for hiding this comment

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

By OOB do you mean out of bounds of the indexed array? If yes, that is not a problem because the code will never try to fetch indices that are out the array shape.

This code just tries to handle numpy-style negative indexing (starts from the end of the array) just like strided_slice does.

Copy link
Member

Choose a reason for hiding this comment

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

Yep, I don’t have much idea about this either

Copy link
Contributor Author

@abergeron abergeron Nov 17, 2019

Choose a reason for hiding this comment

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

Even if the logical result is very similar to strided_slice the implementation has a difference.

In this operation: a[begin:end:stride] = b

The core kernel loops over all valid indexes for a and check if that index is part of the values selected by the combination of begin, end and stride. If it is, it will compute the corresponding index in b and map the output to that value. Otherwise it will pick up the value from a at that index.

In all cases it doesn't matter if begin, end, or stride doesn't fall within the bounds of a because they are never used to directly or indirectly index into a.

begin[i] + a.shape[i],
begin[i])
end[i] = tvm.if_then_else(end[i] < 0,
end[i] + a.shape[i],
Copy link
Member

Choose a reason for hiding this comment

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

Same here. OOB is not completely detected.

within_index(begin[i], end[i], strides[i], indices[i]))
index_tuple.append(
make_idx(begin[i], end[i], strides[i], a.shape[i], indices[i]))
#return tvm.all(*from_val)
Copy link
Member

Choose a reason for hiding this comment

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

Shall we remove those 4 lines?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, of course.

@abergeron
Copy link
Contributor Author

@yzhliu It can be used for the gradient of strided_slice in Relay, but is also an operation we need for myia (https://github.com/mila-iqia/myia).

@junrushao1994 Yes it is that operation.

@yzhliu
Copy link
Member

yzhliu commented Nov 18, 2019

@abergeron Got it. Thanks.
@junrushao1994 would you review again?

v : relay.Expr
The data to be set.

begin: list of int
Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you for adding this op. Currently @yongwww is modifying strided_slice(#4312) to support begin, end and strides to be expression instead of just list of int. The reason is that in some DL frameworks, begin, end or strides can be a tensor. Also making it more dynamic can help us when building other ops, such as NMS. Considering this op is similar to strided_slice, should we keep it align with stride_slice, and allow begin, end and strides to be Expr?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That could be done, yes. The underlying TOPI op does support TVM expressions so it shouldn't be too hard to do.

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 now done.

b_np = np.asarray(begin).astype('int32')
e_np = np.asarray(end).astype('int32')
out_npy = topi.testing.strided_set_python(
x_np, v_np, begin, end, strides) + 1
Copy link
Member

Choose a reason for hiding this comment

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

just for curiosity, why is +1 needed here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It mirrors the +1 in topi expression above. As to why this does +1 at all, I don't know, but strided_slice does that so I did the same.

@abergeron
Copy link
Contributor Author

Can this move forward?

Copy link
Member

@yongwww yongwww left a comment

Choose a reason for hiding this comment

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

lgtm

@tqchen
Copy link
Member

tqchen commented Dec 3, 2019

cc @yzhliu

@tqchen
Copy link
Member

tqchen commented Dec 3, 2019

@junrushao1994 please https://docs.tvm.ai/contribute/code_review.html#approve-and-request-changes-explicitly

if there is not further comment, i propose to merge it in 24 hours

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.

LGTM

@tqchen tqchen merged commit 6d88c98 into apache:master Dec 3, 2019
@tqchen
Copy link
Member

tqchen commented Dec 3, 2019

tmoreau89 pushed a commit to tmoreau89/tvm that referenced this pull request Dec 3, 2019
zxy844288792 pushed a commit to zxy844288792/tvm that referenced this pull request Dec 13, 2019
zxy844288792 pushed a commit to neo-ai/tvm that referenced this pull request Dec 13, 2019
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