-
Notifications
You must be signed in to change notification settings - Fork 26.3k
C++/Python API parity for Conv{1,2,3}d layers, and add F::conv{1,2,3}d functionals #28917
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
Conversation
cf623a4 to
7fa2034
Compare
6496e0e to
5caa26e
Compare
| int64_t output_channels, | ||
| ExpandingArray<1> kernel_size) | ||
| : Conv1dImpl(ConvOptions<1>(input_channels, output_channels, kernel_size)) { | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved the constructor that takes input_channels, output_channels, kernel_size into each of the Conv{1,2,3}d subclasses, so that they can call each dimension's specific constructor that takes options (which contains specialized logic). This mirrors the design of the Python version.
|
|
||
| Conv1dImpl::Conv1dImpl( | ||
| ConvOptions<1> options_) | ||
| : ConvImpl(std::move(options_).transposed(false).output_padding(0)) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reason to use std::move here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is because we pass options_ by value here, as a result we can use std::move as an optimization. The reason for passing options_ by value is that we want to be able to change options_ in-place (updating its transposed_ and output_padding_ fields) before passing it to the ConvImpl constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct me if I'm wrong, but std::move() casts options_ to rvalue-reference, but I don't see any move-ctor or move assignment operators that can accept rvalue-references, neither in ConvOptions nor in ConvImpl
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The move-ctor for ConvOptions will be created by the compiler automatically. Per https://en.cppreference.com/w/cpp/language/move_constructor:
If no user-defined move constructors are provided for a class type (struct, class, or union), and all of the following is true:
~ there are no user-declared copy constructors;
~ there are no user-declared copy assignment operators;
~ there are no user-declared move assignment operators;
~ there are no user-declared destructors;
then the compiler will declare a move constructor as a non-explicit inline public member of its class with the signature T::T(T&&).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ConvImpl has a constructor that accepts const ConvOptions<D>&, and we can pass an rvalue by const reference (https://stackoverflow.com/questions/36102728/why-is-it-allowed-to-pass-r-values-by-const-reference-but-not-by-normal-referenc) :D
|
|
||
| Conv2dImpl::Conv2dImpl( | ||
| ConvOptions<2> options_) | ||
| : ConvImpl(std::move(options_).transposed(false).output_padding(0)) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reason to use std::move here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is because we pass options_ by value here, as a result we can use std::move as an optimization. The reason for passing options_ by value is that we want to be able to change options_ in-place (updating its transposed_ and output_padding_ fields) before passing it to the ConvImpl constructor.
|
|
||
| Conv3dImpl::Conv3dImpl( | ||
| ConvOptions<3> options_) | ||
| : ConvImpl(std::move(options_).transposed(false).output_padding(0)) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reason to use std::move here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is because we pass options_ by value here, as a result we can use std::move as an optimization. The reason for passing options_ by value is that we want to be able to change options_ in-place (updating its transposed_ and output_padding_ fields) before passing it to the ConvImpl constructor.
|
|
||
| /// Options for a `D`-dimensional convolution module. | ||
| template <size_t D> | ||
| struct ConvOptions { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sometimes we have TORCH_API before classname, sometimes not...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right this is actually intentional - in https://github.com/pytorch/pytorch/blob/master/CONTRIBUTING.md#windows-development-tips:
However, there is one important counterexample to this principle: if you want a templated function to be instantiated at the call site, do NOT mark it with *_API (if you do mark it, you'll have to explicitly instantiate all of the specializations used by the call sites.)
Although we do explicitly instantiate all the specializations of ConvOptions in torch/csrc/api/src/nn/options/conv.cpp, I think it might still be a good idea to not put TORCH_API here, which is also consistent with how other templatized Options are implemented.
CircleCI build failures summaryAs of commit 7b1928c:
Here are the reasons each build failed:
This comment was automatically generated by Dr. CI. Please report bugs/suggestions on the GitHub issue tracker. This comment has been revised 20 time(s). |
facebook-github-bot
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yf225 has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
facebook-github-bot
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yf225 has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
facebook-github-bot
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yf225 has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
facebook-github-bot
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yf225 has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
This PR changes the implementation of C++ Conv{1,2,3}d layers to exactly match the Python version, and add F::conv{1,2,3}d functionals. For more thorough testing, I will rely on the parity test mechanism which uses values from
common_nn.pyto generate the inputs and options that we are interested in testing.This PR is BC-breaking in the following way:
In
Conv{1,2,3}dOptions:with_biasis renamed tobias.input_channelsis renamed toin_channels.output_channelsis renamed toout_channels.transposeddoesn't affect the behavior ofConv{1,2,3}dlayers anymore. Users should migrate their code to useConvTranspose{1,2,3}dlayers instead. Note thatConvTranspose{1,2,3}dcannot be used in aSequentialmodule becauseSequentialmodule doesn't support modules with forward method that can take optional arguments. Users should create their own wrapper forConvTranspose{1,2,3}dand have its forward method just accept a tensor, if they want to use it in aSequentialmodule.For example: