// Copyright (c) 2021 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/dot_kernel.h" #include "paddle/common/enforce.h" #include "paddle/phi/backends/gpu/gpu_context.h" #include "paddle/phi/core/kernel_registry.h" #include "paddle/phi/kernels/funcs/blas/blas.h" #include "paddle/phi/kernels/funcs/eigen/common.h" #include "paddle/phi/kernels/full_kernel.h" #include "paddle/phi/kernels/funcs/eigen/eigen_function.h" namespace phi { template void DotKernel(const Context& dev_ctx, const DenseTensor& x, const DenseTensor& y, DenseTensor* out) { if (x.numel() == 0 || y.numel() == 0) { // x[2, 1], y[2, 0], out[2] Full(dev_ctx, out->dims(), 0, out); return; } if (out->numel() <= 0) { return; } auto x_data = x.data(); auto y_data = y.data(); dev_ctx.template Alloc(out); auto out_data = out->data(); if (out->dims().size() == 0) { #ifdef PADDLE_WITH_CUDA if constexpr (std::is_same_v || std::is_same_v) { auto eigen_out = EigenScalar::From(*out); auto eigen_x = EigenVector::Flatten(x); auto eigen_y = EigenVector::Flatten(y); auto& dev = *dev_ctx.eigen_device(); eigen_out.device(dev) = (eigen_x * eigen_y).sum(); } else { PADDLE_ENFORCE_LE_INT_MAX(x.numel(), "dot CUDOT n"); PADDLE_ENFORCE_LE_INT_MAX(x.strides()[0], "dot CUDOT incx"); const int n = static_cast(x.numel()); int incx = static_cast(x.strides()[0]); int incy = static_cast(x.strides()[0]); if (n == 1) { incx = 1; incy = 1; } auto blas = funcs::GetBlas(dev_ctx); blas.CUDOT(n, x_data, incx, y_data, incy, out_data); } #else auto eigen_out = EigenScalar::From(*out); auto eigen_x = EigenVector::Flatten(x); auto eigen_y = EigenVector::Flatten(y); auto& dev = *dev_ctx.eigen_device(); eigen_out.device(dev) = (eigen_x * eigen_y).sum(); #endif } else { auto eigen_out = EigenVector::From(*out); auto eigen_x = EigenMatrix::From(x); auto eigen_y = EigenMatrix::From(y); auto& dev = *dev_ctx.eigen_device(); eigen_out.device(dev) = (eigen_x * eigen_y).sum(Eigen::DSizes(1)); } } } // namespace phi using complex64 = phi::complex64; using complex128 = phi::complex128; PD_REGISTER_KERNEL(dot, GPU, ALL_LAYOUT, phi::DotKernel, float, double, int, int64_t, complex64, complex128, phi::float16, phi::bfloat16) {}