elementwise_mul_op.cc 7.2 KB
Newer Older
1
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.
2

L
Luo Tao 已提交
3 4 5
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
6

L
Luo Tao 已提交
7
    http://www.apache.org/licenses/LICENSE-2.0
8

L
Luo Tao 已提交
9 10 11 12 13
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */
14

W
Wu Yi 已提交
15
#include "paddle/fluid/operators/elementwise/elementwise_mul_op.h"
16
#include <memory>
S
sneaxiy 已提交
17
#include <string>
W
Wu Yi 已提交
18
#include "paddle/fluid/operators/elementwise/elementwise_op.h"
19 20
#include "paddle/fluid/platform/complex128.h"
#include "paddle/fluid/platform/complex64.h"
S
sneaxiy 已提交
21 22 23 24

namespace paddle {
namespace operators {

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
template <typename T>
struct SameDimsElemwiseMul<
    platform::CPUDeviceContext, T,
    typename std::enable_if<std::is_floating_point<T>::value>::type> {
  void operator()(const framework::ExecutionContext &ctx,
                  const framework::Tensor *x, const framework::Tensor *y,
                  framework::Tensor *z) {
    auto blas = math::GetBlas<platform::CPUDeviceContext, T>(ctx);
    blas.VMUL(x->numel(), x->data<T>(), y->data<T>(), z->data<T>());
  }
};

template <typename T>
struct SameDimsElemwiseMul<
    platform::CPUDeviceContext, T,
    typename std::enable_if<!std::is_floating_point<T>::value>::type> {
  void operator()(const framework::ExecutionContext &ctx,
                  const framework::Tensor *x, const framework::Tensor *y,
                  framework::Tensor *z) {
    auto eigen_x = framework::EigenVector<T>::Flatten(*x);
    auto eigen_y = framework::EigenVector<T>::Flatten(*y);
    auto eigen_z = framework::EigenVector<T>::Flatten(*z);
    auto &place = *ctx.template device_context<platform::CPUDeviceContext>()
                       .eigen_device();
    eigen_z.device(place) = eigen_x * eigen_y;
  }
};

53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
class ElementwiseMulOpMaker : public ElementwiseOpMaker {
 protected:
  std::string GetName() const override { return "Mul"; }
  std::string GetEquation() const override { return "Out = X \\\\odot Y"; }

  void AddInputX() override {
    AddInput("X",
             "(Variable), Tensor or LoDTensor of any dimensions. Its dtype "
             "should be int32, int64, float32, float64.");
  }

  void AddInputY() override {
    AddInput("Y",
             "(Variable), Tensor or LoDTensor of any dimensions. Its dtype "
             "should be int32, int64, float32, float64.");
  }

  std::string GetOpFuntionality() const override {
    return "Multiply two tensors element-wise";
  }
};

H
hong 已提交
75 76
template <typename T>
class ElementwiseMulOpGradMaker : public framework::SingleGradOpMaker<T> {
S
sneaxiy 已提交
77
 public:
H
hong 已提交
78
  using framework::SingleGradOpMaker<T>::SingleGradOpMaker;
S
sneaxiy 已提交
79 80

 protected:
81
  void Apply(GradOpPtr<T> op) const override {
S
sneaxiy 已提交
82
    op->SetType("elementwise_mul_grad");
H
hong 已提交
83 84 85 86 87 88
    op->SetInput("X", this->Input("X"));
    op->SetInput("Y", this->Input("Y"));
    op->SetInput(framework::GradVarName("Out"), this->OutputGrad("Out"));
    op->SetAttrMap(this->Attrs());
    op->SetOutput(framework::GradVarName("X"), this->InputGrad("X"));
    op->SetOutput(framework::GradVarName("Y"), this->InputGrad("Y"));
S
sneaxiy 已提交
89 90 91
  }
};

H
hong 已提交
92 93
template <typename T>
class ElementwiseMulDoubleGradMaker : public framework::SingleGradOpMaker<T> {
94
 public:
H
hong 已提交
95
  using framework::SingleGradOpMaker<T>::SingleGradOpMaker;
96 97

 protected:
98
  void Apply(GradOpPtr<T> op) const override {
99
    op->SetType("elementwise_mul_grad_grad");
H
hong 已提交
100 101 102 103 104
    op->SetInput("X", this->Input("X"));
    op->SetInput("Y", this->Input("Y"));
    op->SetInput("DOut", this->Input(framework::GradVarName("Out")));
    op->SetInput("DDX", this->OutputGrad(framework::GradVarName("X")));
    op->SetInput("DDY", this->OutputGrad(framework::GradVarName("Y")));
105

H
hong 已提交
106
    op->SetAttrMap(this->Attrs());
107

H
hong 已提交
108 109 110
    op->SetOutput("DDOut", this->InputGrad(framework::GradVarName("Out")));
    op->SetOutput(framework::GradVarName("X"), this->InputGrad("X"));
    op->SetOutput(framework::GradVarName("Y"), this->InputGrad("Y"));
111 112 113
  }
};

S
sneaxiy 已提交
114 115 116
}  // namespace operators
}  // namespace paddle

117
namespace ops = paddle::operators;
118
REGISTER_OPERATOR(elementwise_mul, ops::ElementwiseMulOp,
S
sneaxiy 已提交
119
                  ops::ElementwiseMulOpMaker, ops::ElementwiseOpInferVarType,
H
hong 已提交
120 121 122 123 124 125 126
                  ops::ElementwiseMulOpGradMaker<paddle::framework::OpDesc>,
                  ops::ElementwiseMulOpGradMaker<paddle::imperative::OpBase>);
REGISTER_OPERATOR(
    elementwise_mul_grad, ops::ElementwiseOpGrad,
    ops::ElementwiseMulDoubleGradMaker<paddle::framework::OpDesc>,
    ops::ElementwiseMulDoubleGradMaker<paddle::imperative::OpBase>);

127
REGISTER_OPERATOR(elementwise_mul_grad_grad, ops::ElementwiseOpDoubleGrad,
128
                  ops::ElementwiseDoubleGradOpInplaceInferer);
S
sneaxiy 已提交
129

130 131
REGISTER_OP_CPU_KERNEL(
    elementwise_mul,
Q
QI JUN 已提交
132 133 134
    ops::ElementwiseMulKernel<paddle::platform::CPUDeviceContext, float>,
    ops::ElementwiseMulKernel<paddle::platform::CPUDeviceContext, double>,
    ops::ElementwiseMulKernel<paddle::platform::CPUDeviceContext, int>,
135 136 137 138 139
    ops::ElementwiseMulKernel<paddle::platform::CPUDeviceContext, int64_t>,
    ops::ElementwiseMulKernel<paddle::platform::CPUDeviceContext,
                              paddle::platform::complex64>,
    ops::ElementwiseMulKernel<paddle::platform::CPUDeviceContext,
                              paddle::platform::complex128>);
140 141
REGISTER_OP_CPU_KERNEL(
    elementwise_mul_grad,
Q
QI JUN 已提交
142 143 144
    ops::ElementwiseMulGradKernel<paddle::platform::CPUDeviceContext, float>,
    ops::ElementwiseMulGradKernel<paddle::platform::CPUDeviceContext, double>,
    ops::ElementwiseMulGradKernel<paddle::platform::CPUDeviceContext, int>,
145 146 147 148 149
    ops::ElementwiseMulGradKernel<paddle::platform::CPUDeviceContext, int64_t>,
    ops::ElementwiseMulGradKernel<paddle::platform::CPUDeviceContext,
                                  paddle::platform::complex64>,
    ops::ElementwiseMulGradKernel<paddle::platform::CPUDeviceContext,
                                  paddle::platform::complex128>);
150 151 152 153 154 155 156 157 158
REGISTER_OP_CPU_KERNEL(
    elementwise_mul_grad_grad,
    ops::ElementwiseMulDoubleGradKernel<paddle::platform::CPUDeviceContext,
                                        float>,
    ops::ElementwiseMulDoubleGradKernel<paddle::platform::CPUDeviceContext,
                                        double>,
    ops::ElementwiseMulDoubleGradKernel<paddle::platform::CPUDeviceContext,
                                        int>,
    ops::ElementwiseMulDoubleGradKernel<paddle::platform::CPUDeviceContext,
159 160 161 162 163
                                        int64_t>,
    ops::ElementwiseMulDoubleGradKernel<paddle::platform::CPUDeviceContext,
                                        paddle::platform::complex64>,
    ops::ElementwiseMulDoubleGradKernel<paddle::platform::CPUDeviceContext,
                                        paddle::platform::complex128>);
164 165 166 167 168 169 170 171 172

REGISTER_OP_VERSION(elementwise_mul)
    .AddCheckpoint(
        R"ROC(Register elementwise_mul for adding the attribute of Scale_y)ROC",
        paddle::framework::compatible::OpVersionDesc().NewAttr(
            "Scale_y",
            "In order to support the function of scaling the input Y when "
            "using the operator of elementwise_mul.",
            1.0f));