Files
paddlepaddle--paddle/paddle/phi/kernels/gpu/lrn_kernel.cu
T
2026-07-13 12:40:42 +08:00

165 lines
5.5 KiB
Plaintext

// Copyright (c) 2024 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/common/enforce.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/lrn_kernel_impl.h"
namespace phi {
template <typename T>
__global__ void KeCMRNormFillScale(int img_size,
const T* in,
T* mid,
int C,
int H,
int W,
int size,
T k,
T alpha,
const DataLayout data_layout) {
const int64_t idx =
static_cast<int64_t>(threadIdx.x) +
static_cast<int64_t>(blockIdx.x) * static_cast<int64_t>(blockDim.x);
if (idx < img_size) {
const int64_t w = idx % W;
const int64_t h = (idx / W) % H;
const int64_t n = idx / W / H;
const int64_t offset =
(data_layout != DataLayout::NHWC ? (n * C * H + h) * W + w
: ((n * H + h) * W + w) * C);
in += offset;
mid += offset;
const int64_t step = static_cast<int64_t>(H) * W;
const int pre_pad = (size - 1) / 2;
const int post_pad = size - pre_pad - 1;
T accum = 0;
int64_t index = 0;
while (index < C + post_pad) {
if (index < C) {
int64_t in_idx =
(data_layout != DataLayout::NHWC ? index * step : index);
T val = in[in_idx];
accum += val * val;
}
if (index >= size) {
int64_t in_idx =
(data_layout != DataLayout::NHWC ? (index - size) * step
: index - size);
T val = in[in_idx];
accum -= val * val;
}
if (index >= post_pad) {
int64_t mid_idx =
(data_layout != DataLayout::NHWC ? (index - post_pad) * step
: index - post_pad);
mid[mid_idx] = k + accum * alpha;
}
++index;
}
}
}
template <typename T>
__global__ void KeCMRNormOutput(
int input_size, const T* in, const T* mid, T negative_beta, T* out) {
const int index = threadIdx.x + blockIdx.x * blockDim.x;
if (index < input_size) {
out[index] = in[index] * pow(mid[index], negative_beta);
}
}
template <typename T>
void CrossMapNormal(const GPUContext& dev_ctx,
const T* inputs,
T* outputs,
T* mid,
int64_t N,
int64_t C,
int64_t H,
int64_t W,
int n,
T k,
T alpha,
T beta,
const DataLayout data_layout) {
const int64_t img_size = N * H * W;
const int64_t input_size = img_size * C;
PADDLE_ENFORCE_LE_INT_MAX(img_size, "lrn img_size");
PADDLE_ENFORCE_LE_INT_MAX(input_size, "lrn input_size");
PADDLE_ENFORCE_LE_INT_MAX(C, "lrn C");
PADDLE_ENFORCE_LE_INT_MAX(H, "lrn H");
PADDLE_ENFORCE_LE_INT_MAX(W, "lrn W");
const int block_size = 1024;
const int64_t fill_grid_size = (img_size + block_size - 1) / block_size;
PADDLE_ENFORCE_LE_UINT32_MAX(fill_grid_size, "lrn fill grid");
const uint32_t fill_grid = static_cast<uint32_t>(fill_grid_size);
KeCMRNormFillScale<T><<<fill_grid, block_size, 0, dev_ctx.stream()>>>(
static_cast<int>(img_size),
inputs,
mid,
static_cast<int>(C),
static_cast<int>(H),
static_cast<int>(W),
n,
k,
alpha,
data_layout);
const int64_t output_grid_size = (input_size + block_size - 1) / block_size;
PADDLE_ENFORCE_LE_UINT32_MAX(output_grid_size, "lrn output grid");
const uint32_t output_grid = static_cast<uint32_t>(output_grid_size);
KeCMRNormOutput<T><<<output_grid, block_size, 0, dev_ctx.stream()>>>(
static_cast<int>(input_size), inputs, mid, -beta, outputs);
}
template <typename T>
struct LRNFunctor<GPUContext, T> {
void operator()(const GPUContext& dev_ctx,
const DenseTensor& input,
DenseTensor* out,
DenseTensor* mid,
int64_t N,
int64_t C,
int64_t H,
int64_t W,
int n,
T k,
T alpha,
T beta,
const DataLayout data_layout) {
CrossMapNormal<T>(dev_ctx,
input.data<T>(),
dev_ctx.Alloc<T>(out),
dev_ctx.Alloc<T>(mid),
N,
C,
H,
W,
n,
k,
alpha,
beta,
data_layout);
}
};
template struct LRNFunctor<GPUContext, float>;
template struct LRNFunctor<GPUContext, double>;
} // namespace phi
PD_REGISTER_KERNEL(lrn, GPU, ALL_LAYOUT, phi::LRNKernel, float) {}