// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. // // 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. #include "paddle/phi/kernels/gaussian_kernel.h" #include #include "paddle/phi/backends/gpu/gpu_context.h" #include "paddle/phi/common/amp_type_traits.h" #include "paddle/phi/core/dense_tensor.h" #include "paddle/phi/core/generator.h" #include "paddle/phi/core/kernel_registry.h" #include "paddle/phi/kernels/funcs/distribution_helper.h" #include "paddle/phi/kernels/funcs/index_impl.cu.h" namespace phi { template struct GaussianGenerator { T mean_, std_; unsigned int seed_; unsigned int offset_ = 0; __host__ __device__ GaussianGenerator(T mean, T std, int seed) : mean_(mean), std_(std), seed_(seed) {} __host__ __device__ GaussianGenerator(T mean, T std, int seed, int offset) : mean_(mean), std_(std), seed_(seed), offset_(offset) {} __host__ __device__ T operator()(const unsigned int n) const { thrust::minstd_rand rng; rng.seed(seed_); using MT = typename phi::dtype::MPTypeTrait::Type; thrust::normal_distribution dist(static_cast(mean_), static_cast(std_)); unsigned int new_n = n + offset_; rng.discard(new_n); MT out = dist(rng); return static_cast(out); } }; template void GaussianKernel(const Context& dev_ctx, const IntArray& shape, float mean, float std, int seed, DataType dtype, DenseTensor* out) { out->Resize(phi::make_ddim(shape.GetData())); dev_ctx.template Alloc(out); if (seed == 0) { // use global Generator seed using MT = typename phi::dtype::MPTypeTrait::Type; funcs::normal_distribution dist; funcs::normal_transform trans(static_cast(mean), static_cast(std)); funcs::distribution_and_transform(dev_ctx, out, dist, trans); } else { // use OP seed auto func = GaussianGenerator(static_cast(mean), static_cast(std), seed); IndexKernel>(dev_ctx, out, func); } } } // namespace phi PD_REGISTER_KERNEL(gaussian, GPU, ALL_LAYOUT, phi::GaussianKernel, phi::dtype::float16, phi::dtype::bfloat16, float, double) {}