Skip to content

Conversation

@nuka137
Copy link
Contributor

@nuka137 nuka137 commented Oct 6, 2019

Add torch::nn::Softmax module support for the C++ API

Related Issue: #25883

Reviewer: @yf225

/// Options for the `Softmax` module.
struct TORCH_API SoftmaxOptions {
// Dimension along which Softmax will be computed.
TORCH_ARG(int, dim);
Copy link
Contributor

@pbelevich pbelevich Oct 6, 2019

Choose a reason for hiding this comment

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

Please add a constructor with dim parameter taking default value, as @yf225 asked here, see HardshrinkOptions as an example

Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest to have -1 as a default value

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks. I fixed it.

Copy link
Contributor

Choose a reason for hiding this comment

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

After discussion with the team we agreed that we should use c10::optional<int64_t> instead of just int here. The default value should be c10::nullopt. I'm sorry for for misleading you.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@pbelevich

No problem. Thanks for the instruction.
Does this rule also apply to torch::Dtype ?

Copy link
Contributor

Choose a reason for hiding this comment

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

dim should be a non-optional argument because allowing it to be null is already deprecated in Python version, and the C++ version should just match the newest Python version behavior.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, I fixed it to make dim non-optional argument.

@nuka137
Copy link
Contributor Author

nuka137 commented Oct 6, 2019

@pbelevich

Thanks for reviewing this PR.
I fixed all comments you reviewed.

@pbelevich pbelevich self-requested a review October 7, 2019 16:04

if (dim == -1) {
int input_dim = input.dim();
if (input_dim == 0 || input_dim == 1 || input_dim == 3) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please extract this to _get_softmax_dim(...) as it is in python and reuse it in LogSoftmax. Use TORCH_WARN for the warning.

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

/// Options for the `Softmax` module.
struct TORCH_API SoftmaxOptions {
// Dimension along which Softmax will be computed.
TORCH_ARG(int, dim);
Copy link
Contributor

Choose a reason for hiding this comment

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

After discussion with the team we agreed that we should use c10::optional<int64_t> instead of just int here. The default value should be c10::nullopt. I'm sorry for for misleading you.

Copy link
Contributor

@yf225 yf225 left a comment

Choose a reason for hiding this comment

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

@nuka137 Thanks so much for the great contribution! I left some comments mostly regarding the design of SoftmaxOptions.

ret = 1;
}
return ret;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

In the Python version, this function is for maintaining backward compatibility for the use cases where people don't pass the dim argument to torch.nn.functional.softmax. Since torch::nn::functional::softmax in C++ API is a new addition, we don't need to maintain any backward compatibility, and we should remove this function and make dim a non-optional argument to match the newest Python API design.

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 understood the background and deleted the function _get_softmax_dim.

// The desired data type of returned tensor.
// If specified, the input tensor is casted to dtype before the operation
// is performed. This is useful for preventing data type overflows.
TORCH_ARG(torch::Dtype, dtype);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think semantically dtype is not one of the options of a softmax function/module, because it doesn't control how the softmax function itself should perform the computation, but rather how the returned tensor should be stored, which is rather mechanical than mathematical.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, deleted dtype from SoftmaxOptions.

/// Options for the `Softmax` module.
struct TORCH_API SoftmaxOptions {
// Dimension along which Softmax will be computed.
TORCH_ARG(int, dim);
Copy link
Contributor

Choose a reason for hiding this comment

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

dim should be a non-optional argument because allowing it to be null is already deprecated in Python version, and the C++ version should just match the newest Python version behavior.


/// Options for the Softmax functional and module.
struct TORCH_API SoftmaxOptions {
SoftmaxOptions(int dim = -1, torch::Dtype dtype = torch::Dtype::Undefined);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it should be

Suggested change
SoftmaxOptions(int dim = -1, torch::Dtype dtype = torch::Dtype::Undefined);
SoftmaxOptions(int dim);

because dim shouldn't be an optional argument.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for your suggestion. I fixed it.

if (dtype != torch::Dtype::Undefined) {
stream << "dtype=" << options.dtype();
}
stream << ")";
Copy link
Contributor

Choose a reason for hiding this comment

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

To match the Python version, we can just print dim in pretty_print.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed it to print dim only.

return ret;
}

inline Tensor softmax(const Tensor& input, const SoftmaxOptions& options) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the signature should be

Suggested change
inline Tensor softmax(const Tensor& input, const SoftmaxOptions& options) {
inline Tensor softmax(const Tensor& input, const SoftmaxOptions& options, c10::optional<torch::Dtype> dtype = c10::nullopt) {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for your suggestion. I fixed it.

@nuka137
Copy link
Contributor Author

nuka137 commented Oct 8, 2019

@yf225

Thanks for reviewing.
I fixed all issues. Could you check this PR again?

SoftmaxOptions(int dim);

// Dimension along which Softmax will be computed.
TORCH_ARG(int, dim);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should make dim have int64_t type, because that's the type of tensor dimensions for C++ tensors.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, fixed it

/// about the exact behavior of this module.
class TORCH_API SoftmaxImpl : public torch::nn::Cloneable<SoftmaxImpl> {
public:
explicit SoftmaxImpl(const SoftmaxOptions& options_);
Copy link
Contributor

Choose a reason for hiding this comment

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

We should also add explicit SoftmaxImpl(int64_t dim) : SoftmaxImpl(SoftmaxOptions(dim)) {} here, to serve the torch::nn::Softmax(/*dim=*/3) use case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed it.

int dim = options.dim();
Tensor ret;

if (dtype == torch::Dtype::Undefined) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We should change this to

Suggested change
if (dtype == torch::Dtype::Undefined) {
if (dtype == c10::nullopt) {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, I missed this part. Now, it was fixed.


inline Tensor softmax(const Tensor& input, const SoftmaxOptions& options,
c10::optional<torch::Dtype> dtype = c10::nullopt) {
int dim = options.dim();
Copy link
Contributor

Choose a reason for hiding this comment

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

We should change here accordingly:

Suggested change
int dim = options.dim();
int64_t dim = options.dim();

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks. I fixed it.


TEST_F(FunctionalTest, Softmax) {
auto input = torch::arange(10, torch::kFloat).reshape({2, 5});
auto output = F::softmax(input, SoftmaxOptions(1));
Copy link
Contributor

Choose a reason for hiding this comment

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

We can change this to

Suggested change
auto output = F::softmax(input, SoftmaxOptions(1));
auto output = F::softmax(input, /*dim=*/1);

to also test SoftmaxOptions's implicit constructor. ;)

Copy link
Contributor Author

@nuka137 nuka137 Oct 9, 2019

Choose a reason for hiding this comment

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

Fixed it.

}

TEST_F(ModulesTest, Softmax) {
Softmax m(SoftmaxOptions(1));
Copy link
Contributor

Choose a reason for hiding this comment

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

We can change this to

Suggested change
Softmax m(SoftmaxOptions(1));
Softmax m(/*dim=*/1);

to also test SoftmaxOptions's implicit constructor. ;)

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 also fixed as well.

@yf225
Copy link
Contributor

yf225 commented Oct 9, 2019

@nuka137 I think similar issues in this PR also exist in Softmin / LogSoftmax / Softmax2d, and it would be awesome to change them as well. Thanks so much for the fantastic work!

@nuka137
Copy link
Contributor Author

nuka137 commented Oct 9, 2019

@yf225

Fixed again all comments you reviewed.

similar issues in this PR also exist in Softmin / LogSoftmax / Softmax2d

Sure. I will change these PR when this PR is merged.
Thanks.

Copy link
Contributor

@yf225 yf225 left a comment

Choose a reason for hiding this comment

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

Thanks so much for the awesome work @nuka137! I will merge this today :D

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 is landing 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 28a1806.

facebook-github-bot pushed a commit that referenced this pull request Oct 13, 2019
Summary:
Add torch::nn::Softmax2d module support for the C++ API.
Softmax2d only supports module in Python API, so this PR adds only module support as well.

This PR is WIP because it uses the function in #27446 .
After #27446 is merged, I will remove WIP.

Related Issue: #25883

Reviewer: yf225
Pull Request resolved: #27509

Differential Revision: D17899715

Pulled By: yf225

fbshipit-source-id: bd891bc995f5a92bf4f5405f8bf07d1bd5de2479
thiagocrepaldi pushed a commit to thiagocrepaldi/pytorch that referenced this pull request Feb 4, 2020
Summary:
Add torch::nn::Softmax module support for the C++ API

Related Issue: pytorch#25883

Reviewer: yf225
Pull Request resolved: pytorch#27446

Differential Revision: D17839546

Pulled By: yf225

fbshipit-source-id: 7c7fb55111b261614de7c3a75fa1019fbde93c67
thiagocrepaldi pushed a commit to thiagocrepaldi/pytorch that referenced this pull request Feb 4, 2020
Summary:
Add torch::nn::Softmax2d module support for the C++ API.
Softmax2d only supports module in Python API, so this PR adds only module support as well.

This PR is WIP because it uses the function in pytorch#27446 .
After pytorch#27446 is merged, I will remove WIP.

Related Issue: pytorch#25883

Reviewer: yf225
Pull Request resolved: pytorch#27509

Differential Revision: D17899715

Pulled By: yf225

fbshipit-source-id: bd891bc995f5a92bf4f5405f8bf07d1bd5de2479
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Merged module: cpp Related to C++ API

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants