uniform_random_op.cc 6.7 KB
Newer Older
1
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.
Y
Yu Yang 已提交
2

L
Luo Tao 已提交
3 4 5 6 7 8 9 10 11 12 13
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

    http://www.apache.org/licenses/LICENSE-2.0

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. */
Y
Yi Wang 已提交
14 15
#include "paddle/fluid/framework/op_registry.h"
#include "paddle/fluid/framework/operator.h"
Y
Yu Yang 已提交
16 17 18

namespace paddle {
namespace operators {
Y
Yu Yang 已提交
19

Q
qijun 已提交
20 21 22 23
// It seems that Eigen::Tensor::random in GPU will SEGFAULT.
// Use std::random and thrust::random(thrust is a std library in CUDA) to
// implement uniform random.
template <typename T>
Y
Yu Yang 已提交
24
class CPUUniformRandomKernel : public framework::OpKernel<T> {
Q
qijun 已提交
25
 public:
C
chengduo 已提交
26 27
  void Compute(const framework::ExecutionContext &ctx) const override {
    framework::Tensor *tensor = nullptr;
Y
Yancey1989 已提交
28 29 30 31
    auto out_var = ctx.OutputVar("Out");
    if (out_var->IsType<framework::LoDTensor>()) {
      tensor = out_var->GetMutable<framework::LoDTensor>();
    } else if (out_var->IsType<framework::SelectedRows>()) {
T
tangwei12 已提交
32
      auto shape = ctx.Attr<std::vector<int64_t>>("shape");
C
chengduo 已提交
33
      auto *selected_rows = out_var->GetMutable<framework::SelectedRows>();
34
      tensor = selected_rows->mutable_value();
Y
Yancey1989 已提交
35
      tensor->Resize(framework::make_ddim(shape));
36
      selected_rows->mutable_rows()->reserve(shape[0]);
Y
Yancey1989 已提交
37
    } else {
Y
Yancey1989 已提交
38 39
      PADDLE_THROW(
          "uniform_random_op's output only"
T
tangwei12 已提交
40
          "supports SelectedRows and LoDTensor");
Y
Yancey1989 已提交
41
    }
C
chengduo 已提交
42
    T *data = tensor->mutable_data<T>(ctx.GetPlace());
Q
Qiao Longfei 已提交
43
    unsigned int seed = static_cast<unsigned int>(ctx.Attr<int>("seed"));
Q
qijun 已提交
44 45 46 47 48 49
    std::minstd_rand engine;
    if (seed == 0) {
      seed = std::random_device()();
    }
    engine.seed(seed);
    std::uniform_real_distribution<T> dist(
Q
Qiao Longfei 已提交
50 51
        static_cast<T>(ctx.Attr<float>("min")),
        static_cast<T>(ctx.Attr<float>("max")));
52
    int64_t size = tensor->numel();
Q
qijun 已提交
53
    for (int64_t i = 0; i < size; ++i) {
Q
qijun 已提交
54 55
      data[i] = dist(engine);
    }
56 57 58 59 60 61 62 63 64 65 66 67 68
    unsigned int diag_num =
        static_cast<unsigned int>(ctx.Attr<int>("diag_num"));
    unsigned int diag_step =
        static_cast<unsigned int>(ctx.Attr<int>("diag_step"));
    auto diag_val = static_cast<T>(ctx.Attr<float>("diag_val"));
    if (diag_num > 0) {
      PADDLE_ENFORCE_GT(size, (diag_num - 1) * (diag_step + 1),
                        "The index of diagonal elements is out of bounds");
      for (int64_t i = 0; i < diag_num; ++i) {
        int64_t pos = i * diag_step + i;
        data[pos] = diag_val;
      }
    }
Q
qijun 已提交
69 70 71
  }
};

Y
Yu Yang 已提交
72
class UniformRandomOp : public framework::OperatorWithKernel {
Y
Yu Yang 已提交
73 74 75
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

C
chengduo 已提交
76
  void InferShape(framework::InferShapeContext *ctx) const override {
77 78
    PADDLE_ENFORCE_EQ(ctx->HasOutput("Out"), true,
                      "Output(Out) of UniformRandomOp should not be null.");
79

80 81 82
    PADDLE_ENFORCE_LT(ctx->Attrs().Get<float>("min"),
                      ctx->Attrs().Get<float>("max"),
                      "uniform_random's min must less then max");
T
tangwei12 已提交
83
    auto &shape = ctx->Attrs().Get<std::vector<int64_t>>("shape");
84 85 86 87
    PADDLE_ENFORCE_GE(ctx->Attrs().Get<int>("diag_num"), 0,
                      "diag_num must greater than or equal 0");
    PADDLE_ENFORCE_GE(ctx->Attrs().Get<int>("diag_step"), 0,
                      "diag_step must greater than or equal 0");
Q
qijun 已提交
88
    std::vector<int64_t> temp;
Q
QI JUN 已提交
89 90
    temp.reserve(shape.size());
    for (auto dim : shape) {
Q
qijun 已提交
91 92
      temp.push_back(static_cast<int64_t>(dim));
    }
Q
Qiao Longfei 已提交
93
    ctx->SetOutputDim("Out", framework::make_ddim(temp));
Y
Yu Yang 已提交
94
  }
Y
Yu Yang 已提交
95

96
 protected:
97
  framework::OpKernelType GetExpectedKernelType(
C
chengduo 已提交
98
      const framework::ExecutionContext &ctx) const override {
Y
Yu Yang 已提交
99
    return framework::OpKernelType(
100
        static_cast<framework::proto::VarType::Type>(ctx.Attr<int>("dtype")),
Q
QI JUN 已提交
101
        ctx.GetPlace());
Y
Yu Yang 已提交
102
  }
Y
Yu Yang 已提交
103 104
};

Y
Yu Yang 已提交
105
class UniformRandomOpMaker : public framework::OpProtoAndCheckerMaker {
Y
Yu Yang 已提交
106
 public:
Y
Yu Yang 已提交
107
  void Make() override {
Y
yuyang18 已提交
108
    AddOutput("Out", "The output tensor of uniform random op");
109
    AddComment(R"DOC(
110
This operator initializes a tensor with random values sampled from a
Y
yuyang18 已提交
111
uniform distribution. The random result is in set [min, max].
112

Y
Yu Yang 已提交
113
)DOC");
T
tangwei12 已提交
114
    AddAttr<std::vector<int64_t>>("shape", "The shape of the output tensor");
Y
yuyang18 已提交
115
    AddAttr<float>("min", "Minimum value of uniform random. [default -1.0].")
116
        .SetDefault(-1.0f);
Y
yuyang18 已提交
117
    AddAttr<float>("max", "Maximun value of uniform random. [default 1.0].")
118
        .SetDefault(1.0f);
Q
qijun 已提交
119
    AddAttr<int>("seed",
120
                 "Random seed used for generating samples. "
121 122
                 "0 means use a seed generated by the system."
                 "Note that if seed is not 0, this operator will always "
Y
yuyang18 已提交
123
                 "generate the same random numbers every time. [default 0].")
Q
qijun 已提交
124
        .SetDefault(0);
125 126 127 128 129 130 131 132
    AddAttr<int>("diag_num",
                 "The number of diag elements. Note that if "
                 "diag_num is 0, it means without diag init.[default 0].")
        .SetDefault(0);
    AddAttr<int>("diag_step", "The step between two diag element.[default 0].")
        .SetDefault(0);
    AddAttr<float>("diag_val", "The value of diag element. [default 1.0].")
        .SetDefault(1.0f);
Y
yuyang18 已提交
133
    AddAttr<int>("dtype", "Output tensor data type. [default 5(FP32)].")
134
        .SetDefault(framework::proto::VarType::FP32);
Y
Yu Yang 已提交
135 136
  }
};
Y
Yancey1989 已提交
137 138 139

class UniformRandomOpVarTypeInference : public framework::VarTypeInference {
 public:
M
minqiyang 已提交
140 141
  void operator()(framework::InferVarTypeContext *ctx) const override {
    auto out_var_name = ctx->Output("Out").front();
C
chengduo 已提交
142
    auto var_data_type = static_cast<framework::proto::VarType::Type>(
M
minqiyang 已提交
143
        boost::get<int>(ctx->GetAttr("dtype")));
C
chengduo 已提交
144

M
minqiyang 已提交
145 146 147
    if (ctx->GetType(out_var_name) !=
        framework::proto::VarType::SELECTED_ROWS) {
      ctx->SetType(out_var_name, framework::proto::VarType::LOD_TENSOR);
Y
Yancey1989 已提交
148
    }
M
minqiyang 已提交
149
    ctx->SetDataType(out_var_name, var_data_type);
Y
Yancey1989 已提交
150 151 152
  }
};

Y
Yu Yang 已提交
153 154 155
}  // namespace operators
}  // namespace paddle

Y
Yancey1989 已提交
156 157 158 159 160
REGISTER_OPERATOR(uniform_random, paddle::operators::UniformRandomOp,
                  paddle::operators::UniformRandomOpMaker,
                  paddle::framework::EmptyGradOpMaker,
                  paddle::operators::UniformRandomOpVarTypeInference);

Q
qijun 已提交
161
REGISTER_OP_CPU_KERNEL(uniform_random,
162 163
                       paddle::operators::CPUUniformRandomKernel<float>,
                       paddle::operators::CPUUniformRandomKernel<double>);
164 165 166
REGISTER_OP_CPU_KERNEL(uniform_random_batch_size_like,
                       paddle::operators::CPUUniformRandomKernel<float>,
                       paddle::operators::CPUUniformRandomKernel<double>);