Skip to content

Conversation

@yf225
Copy link
Contributor

@yf225 yf225 commented Oct 30, 2019

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.py to 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_bias is renamed to bias.
  • input_channels is renamed to in_channels.
  • output_channels is renamed to out_channels.
  • The value of transposed doesn't affect the behavior of Conv{1,2,3}d layers anymore. Users should migrate their code to use ConvTranspose{1,2,3}d layers instead. Note that ConvTranspose{1,2,3}d cannot be used in a Sequential module because Sequential module doesn't support modules with forward method that can take optional arguments. Users should create their own wrapper for ConvTranspose{1,2,3}d and have its forward method just accept a tensor, if they want to use it in a Sequential module.
    For example:
struct ConvTranspose2dWrapperImpl : public torch::nn::ConvTranspose2dImpl {
  using torch::nn::ConvTranspose2dImpl::ConvTranspose2dImpl;

  torch::Tensor forward(const torch::Tensor& input) {
    return torch::nn::ConvTranspose2dImpl::forward(input, c10::nullopt);
  }
};

TORCH_MODULE(ConvTranspose2dWrapper);

torch::nn::Sequential sequential(
  ConvTranspose2dWrapper(torch::nn::ConvTranspose2dOptions(3, 3, 4));

@yf225 yf225 added the module: cpp Related to C++ API label Oct 30, 2019
@yf225 yf225 force-pushed the fix_conv branch 2 times, most recently from cf623a4 to 7fa2034 Compare October 30, 2019 21:05
@yf225 yf225 force-pushed the fix_conv branch 12 times, most recently from 6496e0e to 5caa26e Compare October 30, 2019 22:48
int64_t output_channels,
ExpandingArray<1> kernel_size)
: Conv1dImpl(ConvOptions<1>(input_channels, output_channels, kernel_size)) {
}
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 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.

@yf225 yf225 requested a review from pbelevich October 30, 2019 23:10

Conv1dImpl::Conv1dImpl(
ConvOptions<1> options_)
: ConvImpl(std::move(options_).transposed(false).output_padding(0)) {}
Copy link
Contributor

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?

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

Copy link
Contributor

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

Copy link
Contributor Author

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&&).

Copy link
Contributor Author

@yf225 yf225 Nov 1, 2019

Choose a reason for hiding this comment

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


Conv2dImpl::Conv2dImpl(
ConvOptions<2> options_)
: ConvImpl(std::move(options_).transposed(false).output_padding(0)) {}
Copy link
Contributor

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?

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 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)) {}
Copy link
Contributor

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?

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 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 {
Copy link
Contributor

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

Copy link
Contributor Author

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.

@kostmo
Copy link
Member

kostmo commented Oct 31, 2019

CircleCI build failures summary

As of commit 7b1928c:

  • 9/9 failures introduced in this PR
  • 0/9 recognized as flaky

Here are the reasons each build failed:

Job Step Log excerpt
pytorch_linux_xenial_py3_6_gcc5_4_test Test \'vision::models::_googlenetimpl::BasicConv2dImpl::BasicConv2dImpl(torch::nn::Conv2dOptions)\':\n/tmp/pip-req-build-749j85ij/torchvision/csrc/models/googlenet.cpp:15:43: error:
pytorch_linux_xenial_py2_7_9_test Test \'vision::models::_googlenetimpl::BasicConv2dImpl::BasicConv2dImpl(torch::nn::Conv2dOptions)\':\n/tmp/pip-req-build-i5YY9i/torchvision/csrc/models/googlenet.cpp:15:43: error:
pytorch_linux_xenial_py3_clang5_asan_test Test \'vision::models::_googlenetimpl::BasicConv2dImpl::BasicConv2dImpl(torch::nn::Conv2dOptions)\':\n/tmp/pip-req-build-p0u75rcb/torchvision/csrc/models/googlenet.cpp:15:43: error:
pytorch_linux_xenial_cuda9_cudnn7_py3_nogpu_test Test \'vision::models::_googlenetimpl::BasicConv2dImpl::BasicConv2dImpl(torch::nn::Conv2dOptions)\':\n/tmp/pip-req-build-emu3mj_x/torchvision/csrc/models/googlenet.cpp:15:43: error:
pytorch_xla_linux_xenial_py3_6_clang7_test Test \'vision::models::_googlenetimpl::BasicConv2dImpl::BasicConv2dImpl(torch::nn::Conv2dOptions)\':\n/tmp/pip-req-build-6uh4sdpl/torchvision/csrc/models/googlenet.cpp:15:43: error:
pytorch_linux_xenial_cuda9_cudnn7_py3_NO_AVX_NO_AVX2_test Test \'vision::models::_googlenetimpl::BasicConv2dImpl::BasicConv2dImpl(torch::nn::Conv2dOptions)\':\n/tmp/pip-req-build-wcrgw6uj/torchvision/csrc/models/googlenet.cpp:15:43: error:
pytorch_linux_xenial_cuda9_cudnn7_py3_slow_test Test \'vision::models::_googlenetimpl::BasicConv2dImpl::BasicConv2dImpl(torch::nn::Conv2dOptions)\':\n/tmp/pip-req-build-m6gj8v3w/torchvision/csrc/models/googlenet.cpp:15:43: error:
pytorch_linux_xenial_cuda9_cudnn7_py3_NO_AVX2_test Test \'vision::models::_googlenetimpl::BasicConv2dImpl::BasicConv2dImpl(torch::nn::Conv2dOptions)\':\n/tmp/pip-req-build-y107hrvp/torchvision/csrc/models/googlenet.cpp:15:43: error:
pytorch_linux_xenial_cuda9_cudnn7_py3_test Test \'vision::models::_googlenetimpl::BasicConv2dImpl::BasicConv2dImpl(torch::nn::Conv2dOptions)\':\n/tmp/pip-req-build-7ktb6o2i/torchvision/csrc/models/googlenet.cpp:15:43: error:

This comment was automatically generated by Dr. CI.
Follow this link to opt-out of these comments for your Pull Requests.

Please report bugs/suggestions on the GitHub issue tracker.

This comment has been revised 20 time(s).

@yf225 yf225 added the module: bc-breaking Related to a BC-breaking change label Oct 31, 2019
@yf225 yf225 requested a review from pbelevich October 31, 2019 19:30
Copy link
Contributor

@facebook-github-bot facebook-github-bot left a 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.

Copy link
Contributor

@facebook-github-bot facebook-github-bot left a 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.

Copy link
Contributor

@facebook-github-bot facebook-github-bot left a 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.

@yf225 yf225 changed the title C++/Python API parity for Conv{1,2,3}d layers C++/Python API parity for Conv{1,2,3}d layers, and add F::conv{1,2,3}d functionals Nov 13, 2019
Copy link
Contributor

@facebook-github-bot facebook-github-bot left a 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
Copy link
Contributor

@yf225 merged this pull request in b37c235.

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

Labels

Merged module: bc-breaking Related to a BC-breaking change module: cpp Related to C++ API

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants