chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,708 @@
|
||||
// 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/phi/backends/xpu/enforce_xpu.h"
|
||||
#include "paddle/phi/backends/xpu/xpu_header.h"
|
||||
#include "paddle/phi/core/kernel_registry.h"
|
||||
|
||||
namespace phi {
|
||||
namespace fusion {
|
||||
class ResnetBasicBlockAttr {
|
||||
public:
|
||||
explicit ResnetBasicBlockAttr(const XPUContext &dev_ctx,
|
||||
const DenseTensor &x_in,
|
||||
const DenseTensor &filter1_in,
|
||||
const DenseTensor &scale1_in,
|
||||
const DenseTensor &bias1_in,
|
||||
const DenseTensor &mean1_in,
|
||||
const DenseTensor &var1_in,
|
||||
const DenseTensor &filter2_in,
|
||||
const DenseTensor &scale2_in,
|
||||
const DenseTensor &bias2_in,
|
||||
const DenseTensor &mean2_in,
|
||||
const DenseTensor &var2_in,
|
||||
const optional<DenseTensor> &filter3_in,
|
||||
const optional<DenseTensor> &scale3_in,
|
||||
const optional<DenseTensor> &bias3_in,
|
||||
const optional<DenseTensor> &mean3_in,
|
||||
const optional<DenseTensor> &var3_in,
|
||||
int stride1_in,
|
||||
int stride2_in,
|
||||
int stride3_in,
|
||||
int padding1_in,
|
||||
int padding2_in,
|
||||
int padding3_in,
|
||||
int dilation1_in,
|
||||
int dilation2_in,
|
||||
int dilation3_in,
|
||||
int group_in,
|
||||
float momentum_in,
|
||||
float epsilon_in,
|
||||
const std::string &data_format_in,
|
||||
bool has_shortcut_in,
|
||||
bool use_global_stats_in,
|
||||
bool is_test_in,
|
||||
bool trainable_statistics_in,
|
||||
const std::string &act_type_in,
|
||||
bool find_conv_input_max_in,
|
||||
DenseTensor *out,
|
||||
DenseTensor *conv1,
|
||||
DenseTensor *saved_mean1,
|
||||
DenseTensor *saved_invstd1,
|
||||
DenseTensor *mean1_out,
|
||||
DenseTensor *var1_out,
|
||||
DenseTensor *conv2,
|
||||
DenseTensor *conv2_input,
|
||||
DenseTensor *saved_mean2,
|
||||
DenseTensor *saved_invstd2,
|
||||
DenseTensor *mean2_out,
|
||||
DenseTensor *var2_out,
|
||||
DenseTensor *conv3,
|
||||
DenseTensor *saved_mean3,
|
||||
DenseTensor *saved_invstd3,
|
||||
DenseTensor *mean3_out,
|
||||
DenseTensor *var3_out,
|
||||
DenseTensor *max_input1,
|
||||
DenseTensor *max_filter1,
|
||||
DenseTensor *max_input2,
|
||||
DenseTensor *max_filter2,
|
||||
DenseTensor *max_input3,
|
||||
DenseTensor *max_filter3) {
|
||||
padding1 = padding1_in;
|
||||
padding2 = padding2_in;
|
||||
padding3 = padding3_in;
|
||||
stride1 = stride1_in;
|
||||
stride2 = stride2_in;
|
||||
stride3 = stride3_in;
|
||||
dilation1 = dilation1_in;
|
||||
dilation2 = dilation2_in;
|
||||
dilation3 = dilation3_in;
|
||||
group = group_in;
|
||||
|
||||
eps = static_cast<double>(epsilon_in);
|
||||
momentum = static_cast<double>(momentum_in);
|
||||
has_shortcut = has_shortcut_in;
|
||||
find_max = find_conv_input_max_in;
|
||||
|
||||
const auto is_test = is_test_in;
|
||||
const auto use_global_stats = use_global_stats_in;
|
||||
const auto trainable_stats = trainable_statistics_in;
|
||||
|
||||
bool test_mode = is_test && (!trainable_stats);
|
||||
global_stats = test_mode || use_global_stats;
|
||||
|
||||
// init shape
|
||||
auto input1 = &x_in;
|
||||
auto filter1 = &filter1_in;
|
||||
auto conv1_out = conv1;
|
||||
auto filter2 = &filter2_in;
|
||||
auto conv2_out = conv2;
|
||||
conv1_input_shape = vectorize<int>(input1->dims());
|
||||
conv1_output_shape = vectorize<int>(conv1_out->dims());
|
||||
conv1_filter_shape = vectorize<int>(filter1->dims());
|
||||
conv1_filter_numel = filter1->numel();
|
||||
conv1_input_numel = input1->numel();
|
||||
conv1_output_numel = conv1_out->numel();
|
||||
|
||||
conv2_input_shape = vectorize<int>(conv1_out->dims());
|
||||
conv2_output_shape = vectorize<int>(conv2_out->dims());
|
||||
conv2_filter_shape = vectorize<int>(filter2->dims());
|
||||
conv2_filter_numel = filter2->numel();
|
||||
conv2_input_numel = conv1_out->numel();
|
||||
conv2_output_numel = conv2_out->numel();
|
||||
|
||||
if (has_shortcut) {
|
||||
auto filter3 = filter3_in.get_ptr();
|
||||
auto conv3_out = conv3;
|
||||
conv3_input_shape = vectorize<int>(input1->dims());
|
||||
conv3_output_shape = vectorize<int>(conv3_out->dims());
|
||||
conv3_filter_shape = vectorize<int>(filter3->dims());
|
||||
conv3_filter_numel = filter3->numel();
|
||||
conv3_input_numel = input1->numel();
|
||||
conv3_output_numel = conv3_out->numel();
|
||||
}
|
||||
}
|
||||
|
||||
int padding1;
|
||||
int padding2;
|
||||
int padding3;
|
||||
int stride1;
|
||||
int stride2;
|
||||
int stride3;
|
||||
int dilation1;
|
||||
int dilation2;
|
||||
int dilation3;
|
||||
int group;
|
||||
|
||||
double eps;
|
||||
double momentum;
|
||||
|
||||
bool has_shortcut;
|
||||
bool find_max;
|
||||
bool global_stats;
|
||||
|
||||
std::vector<int> conv1_input_shape;
|
||||
std::vector<int> conv1_output_shape;
|
||||
std::vector<int> conv1_filter_shape;
|
||||
std::vector<int> conv2_input_shape;
|
||||
std::vector<int> conv2_output_shape;
|
||||
std::vector<int> conv2_filter_shape;
|
||||
std::vector<int> conv3_input_shape;
|
||||
std::vector<int> conv3_output_shape;
|
||||
std::vector<int> conv3_filter_shape;
|
||||
|
||||
int conv1_filter_numel;
|
||||
int conv2_filter_numel;
|
||||
int conv3_filter_numel;
|
||||
int conv1_input_numel;
|
||||
int conv2_input_numel;
|
||||
int conv3_input_numel;
|
||||
int conv1_output_numel;
|
||||
int conv2_output_numel;
|
||||
int conv3_output_numel;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static inline void xpu_conv2d(xpu::Context *ctx,
|
||||
const T *input_data,
|
||||
const T *filter_data,
|
||||
T *output_data,
|
||||
float *input_max_data,
|
||||
float *filter_max_data,
|
||||
const std::vector<int> &input_shape,
|
||||
const std::vector<int> &filter_shape,
|
||||
int padding,
|
||||
int stride,
|
||||
int dilation,
|
||||
int group) {
|
||||
std::vector<int64_t> ksize{filter_shape[2], filter_shape[3]};
|
||||
std::vector<int64_t> stride_vec{stride, stride};
|
||||
std::vector<int64_t> dilation_vec{dilation, dilation};
|
||||
std::vector<int64_t> padding_vec{padding, padding};
|
||||
int64_t N = static_cast<int64_t>(input_shape[0]);
|
||||
int64_t C = static_cast<int64_t>(input_shape[1]);
|
||||
int64_t H = static_cast<int64_t>(input_shape[2]);
|
||||
int64_t W = static_cast<int64_t>(input_shape[3]);
|
||||
|
||||
int r = xpu::conv2d<T, T, T, int16_t>(ctx,
|
||||
input_data,
|
||||
filter_data,
|
||||
output_data,
|
||||
N,
|
||||
C,
|
||||
H,
|
||||
W,
|
||||
filter_shape[0],
|
||||
ksize,
|
||||
stride_vec,
|
||||
padding_vec,
|
||||
dilation_vec,
|
||||
group,
|
||||
input_max_data,
|
||||
filter_max_data,
|
||||
nullptr,
|
||||
true);
|
||||
PADDLE_ENFORCE_XDNN_SUCCESS(r, "conv2d");
|
||||
}
|
||||
|
||||
template <typename T, typename Context>
|
||||
void ResNetBasicBlockXPUKernel(const Context &dev_ctx,
|
||||
const DenseTensor &x_in,
|
||||
const DenseTensor &filter1_in,
|
||||
const DenseTensor &scale1_in,
|
||||
const DenseTensor &bias1_in,
|
||||
const DenseTensor &mean1_in,
|
||||
const DenseTensor &var1_in,
|
||||
const DenseTensor &filter2_in,
|
||||
const DenseTensor &scale2_in,
|
||||
const DenseTensor &bias2_in,
|
||||
const DenseTensor &mean2_in,
|
||||
const DenseTensor &var2_in,
|
||||
const optional<DenseTensor> &filter3_in,
|
||||
const optional<DenseTensor> &scale3_in,
|
||||
const optional<DenseTensor> &bias3_in,
|
||||
const optional<DenseTensor> &mean3_in,
|
||||
const optional<DenseTensor> &var3_in,
|
||||
int stride1,
|
||||
int stride2,
|
||||
int stride3,
|
||||
int padding1,
|
||||
int padding2,
|
||||
int padding3,
|
||||
int dilation1,
|
||||
int dilation2,
|
||||
int dilation3,
|
||||
int group,
|
||||
float momentum_in,
|
||||
float epsilon,
|
||||
const std::string &data_format,
|
||||
bool has_shortcut,
|
||||
bool use_global_stats,
|
||||
bool is_test,
|
||||
bool trainable_statistics,
|
||||
const std::string &act_type,
|
||||
bool find_conv_input_max,
|
||||
DenseTensor *out,
|
||||
DenseTensor *conv1,
|
||||
DenseTensor *saved_mean1,
|
||||
DenseTensor *saved_invstd1,
|
||||
DenseTensor *mean1_out,
|
||||
DenseTensor *var1_out,
|
||||
DenseTensor *conv2,
|
||||
DenseTensor *conv2_input,
|
||||
DenseTensor *saved_mean2,
|
||||
DenseTensor *saved_invstd2,
|
||||
DenseTensor *mean2_out,
|
||||
DenseTensor *var2_out,
|
||||
DenseTensor *conv3,
|
||||
DenseTensor *saved_mean3,
|
||||
DenseTensor *saved_invstd3,
|
||||
DenseTensor *mean3_out,
|
||||
DenseTensor *var3_out,
|
||||
DenseTensor *max_input1,
|
||||
DenseTensor *max_filter1,
|
||||
DenseTensor *max_input2,
|
||||
DenseTensor *max_filter2,
|
||||
DenseTensor *max_input3,
|
||||
DenseTensor *max_filter3) {
|
||||
using XPUType = typename XPUTypeTrait<T>::Type;
|
||||
|
||||
// input
|
||||
const DenseTensor *x = &x_in;
|
||||
const DenseTensor *filter1 = &filter1_in;
|
||||
const DenseTensor *scale1 = &scale1_in;
|
||||
const DenseTensor *bias1 = &bias1_in;
|
||||
const DenseTensor *filter2 = &filter2_in;
|
||||
const DenseTensor *scale2 = &scale2_in;
|
||||
const DenseTensor *bias2 = &bias2_in;
|
||||
|
||||
// output
|
||||
DenseTensor *conv1_output = conv1;
|
||||
DenseTensor *conv2_output = conv2;
|
||||
DenseTensor *output = out;
|
||||
|
||||
auto x_data = reinterpret_cast<const XPUType *>(x->data<T>());
|
||||
auto conv1_filter_data =
|
||||
reinterpret_cast<const XPUType *>(filter1->data<T>());
|
||||
auto conv2_filter_data =
|
||||
reinterpret_cast<const XPUType *>(filter2->data<T>());
|
||||
auto conv1_output_data =
|
||||
reinterpret_cast<XPUType *>(dev_ctx.template Alloc<T>(conv1_output));
|
||||
auto conv2_input_data =
|
||||
reinterpret_cast<XPUType *>(dev_ctx.template Alloc<T>(conv2_input));
|
||||
auto conv2_output_data =
|
||||
reinterpret_cast<XPUType *>(dev_ctx.template Alloc<T>(conv2_output));
|
||||
auto scale1_data = scale1->data<float>();
|
||||
auto scale2_data = scale2->data<float>();
|
||||
auto bias1_data = bias1->data<float>();
|
||||
auto bias2_data = bias2->data<float>();
|
||||
auto output_data =
|
||||
reinterpret_cast<XPUType *>(dev_ctx.template Alloc<T>(output));
|
||||
|
||||
float *conv1_input_max_data = nullptr;
|
||||
float *conv1_filter_max_data = nullptr;
|
||||
float *conv2_input_max_data = nullptr;
|
||||
float *conv2_filter_max_data = nullptr;
|
||||
float *conv3_input_max_data = nullptr;
|
||||
float *conv3_filter_max_data = nullptr;
|
||||
|
||||
ResnetBasicBlockAttr attr(dev_ctx,
|
||||
x_in,
|
||||
filter1_in,
|
||||
scale1_in,
|
||||
bias1_in,
|
||||
mean1_in,
|
||||
var1_in,
|
||||
filter2_in,
|
||||
scale2_in,
|
||||
bias2_in,
|
||||
mean2_in,
|
||||
var2_in,
|
||||
filter3_in,
|
||||
scale3_in,
|
||||
bias3_in,
|
||||
mean3_in,
|
||||
var3_in,
|
||||
stride1,
|
||||
stride2,
|
||||
stride3,
|
||||
padding1,
|
||||
padding2,
|
||||
padding3,
|
||||
dilation1,
|
||||
dilation2,
|
||||
dilation3,
|
||||
group,
|
||||
momentum_in,
|
||||
epsilon,
|
||||
data_format,
|
||||
has_shortcut,
|
||||
use_global_stats,
|
||||
is_test,
|
||||
trainable_statistics,
|
||||
act_type,
|
||||
find_conv_input_max,
|
||||
out,
|
||||
conv1,
|
||||
saved_mean1,
|
||||
saved_invstd1,
|
||||
mean1_out,
|
||||
var1_out,
|
||||
conv2,
|
||||
conv2_input,
|
||||
saved_mean2,
|
||||
saved_invstd2,
|
||||
mean2_out,
|
||||
var2_out,
|
||||
conv3,
|
||||
saved_mean3,
|
||||
saved_invstd3,
|
||||
mean3_out,
|
||||
var3_out,
|
||||
max_input1,
|
||||
max_filter1,
|
||||
max_input2,
|
||||
max_filter2,
|
||||
max_input3,
|
||||
max_filter3);
|
||||
|
||||
// init find max
|
||||
if (attr.find_max) {
|
||||
conv1_input_max_data = dev_ctx.template Alloc<float>(max_input1);
|
||||
conv1_filter_max_data = dev_ctx.template Alloc<float>(max_filter1);
|
||||
|
||||
conv2_input_max_data = dev_ctx.template Alloc<float>(max_input2);
|
||||
conv2_filter_max_data = dev_ctx.template Alloc<float>(max_filter2);
|
||||
|
||||
if (attr.has_shortcut) {
|
||||
conv3_input_max_data = dev_ctx.template Alloc<float>(max_input3);
|
||||
conv3_filter_max_data = dev_ctx.template Alloc<float>(max_filter3);
|
||||
}
|
||||
}
|
||||
|
||||
xpu::ctx_guard RAII_GUARD(dev_ctx.x_context());
|
||||
int r = XPU_SUCCESS;
|
||||
|
||||
// 1. short
|
||||
const XPUType *z_out_data = nullptr;
|
||||
if (attr.has_shortcut) {
|
||||
DenseTensor *conv3_out = conv3;
|
||||
const DenseTensor *filter3 = filter3_in.get_ptr();
|
||||
auto conv3_filter_data =
|
||||
reinterpret_cast<const XPUType *>(filter3->data<T>());
|
||||
auto conv3_output_data =
|
||||
reinterpret_cast<XPUType *>(dev_ctx.template Alloc<T>(conv3_out));
|
||||
|
||||
XPUType *conv3_input_l3_data = nullptr;
|
||||
XPUType *conv3_filter_l3_data =
|
||||
RAII_GUARD.alloc_l3_or_gm<XPUType>(attr.conv3_filter_numel);
|
||||
|
||||
if (attr.find_max) {
|
||||
r = xpu::findmax_copy_fusion(dev_ctx.x_context(),
|
||||
x_data,
|
||||
conv3_input_max_data,
|
||||
conv3_input_l3_data,
|
||||
attr.conv3_input_numel);
|
||||
PADDLE_ENFORCE_XDNN_SUCCESS(r, "findmax_copy_fusion");
|
||||
|
||||
r = xpu::findmax_copy_fusion(dev_ctx.x_context(),
|
||||
conv3_filter_data,
|
||||
conv3_filter_max_data,
|
||||
conv3_filter_l3_data,
|
||||
attr.conv3_filter_numel);
|
||||
PADDLE_ENFORCE_XDNN_SUCCESS(r, "findmax_copy_fusion");
|
||||
}
|
||||
|
||||
xpu_conv2d(dev_ctx.x_context(),
|
||||
conv3_input_l3_data != nullptr ? conv3_input_l3_data : x_data,
|
||||
conv3_filter_l3_data,
|
||||
conv3_output_data,
|
||||
conv3_input_max_data,
|
||||
conv3_filter_max_data,
|
||||
attr.conv3_input_shape,
|
||||
attr.conv3_filter_shape,
|
||||
attr.padding3,
|
||||
attr.stride3,
|
||||
attr.dilation3,
|
||||
attr.group);
|
||||
|
||||
// bn3
|
||||
const DenseTensor *scale3 = scale3_in.get_ptr();
|
||||
const DenseTensor *bias3 = bias3_in.get_ptr();
|
||||
auto bias3_data = bias3->data<float>();
|
||||
auto scale3_data = scale3->data<float>();
|
||||
|
||||
auto bn3_output_data = RAII_GUARD.alloc<XPUType>(attr.conv3_output_numel);
|
||||
PADDLE_ENFORCE_XDNN_NOT_NULL(bn3_output_data);
|
||||
|
||||
if (!attr.global_stats) {
|
||||
DenseTensor *running_mean3 = mean3_out;
|
||||
DenseTensor *running_var3 = var3_out;
|
||||
|
||||
auto saved_mean3_data = dev_ctx.template Alloc<float>(saved_mean3);
|
||||
auto saved_invstd3_data = dev_ctx.template Alloc<float>(saved_invstd3);
|
||||
auto running_mean3_data = dev_ctx.template Alloc<float>(running_mean3);
|
||||
auto running_var3_data = dev_ctx.template Alloc<float>(running_var3);
|
||||
|
||||
r = xpu::batch_norm_fusion<XPUType>(dev_ctx.x_context(),
|
||||
conv3_output_data,
|
||||
bn3_output_data,
|
||||
attr.conv3_output_shape[0],
|
||||
attr.conv3_output_shape[1],
|
||||
attr.conv3_output_shape[3],
|
||||
attr.conv3_output_shape[3],
|
||||
attr.eps,
|
||||
attr.momentum,
|
||||
scale3_data,
|
||||
bias3_data,
|
||||
saved_mean3_data,
|
||||
saved_invstd3_data,
|
||||
running_mean3_data,
|
||||
running_var3_data,
|
||||
true,
|
||||
nullptr,
|
||||
xpu::Activation_t::LINEAR,
|
||||
nullptr,
|
||||
0);
|
||||
PADDLE_ENFORCE_XDNN_SUCCESS(r, "batch_norm_fusion");
|
||||
} else {
|
||||
const auto *mean3 = mean3_in.get_ptr();
|
||||
const auto *var3 = var3_in.get_ptr();
|
||||
const auto *mean3_data = mean3->data<float>();
|
||||
const auto *variance3_data = var3->data<float>();
|
||||
r = xpu::batch_norm_infer<XPUType>(dev_ctx.x_context(),
|
||||
conv3_output_data,
|
||||
bn3_output_data,
|
||||
attr.conv3_output_shape[0],
|
||||
attr.conv3_output_shape[1],
|
||||
attr.conv3_output_shape[2],
|
||||
attr.conv3_output_shape[3],
|
||||
attr.eps,
|
||||
scale3_data,
|
||||
bias3_data,
|
||||
mean3_data,
|
||||
variance3_data,
|
||||
true);
|
||||
PADDLE_ENFORCE_XDNN_SUCCESS(r, "batch_norm_infer");
|
||||
}
|
||||
z_out_data = reinterpret_cast<const XPUType *>(bn3_output_data);
|
||||
} else {
|
||||
z_out_data = x_data;
|
||||
}
|
||||
|
||||
// 2. conv1
|
||||
XPUType *conv1_input_l3_data = nullptr;
|
||||
XPUType *conv1_filter_l3_data =
|
||||
RAII_GUARD.alloc_l3_or_gm<XPUType>(attr.conv1_filter_numel);
|
||||
if (attr.find_max) {
|
||||
r = xpu::findmax_copy_fusion(dev_ctx.x_context(),
|
||||
x_data,
|
||||
conv1_input_max_data,
|
||||
conv1_input_l3_data,
|
||||
attr.conv1_input_numel);
|
||||
PADDLE_ENFORCE_XDNN_SUCCESS(r, "findmax_copy_fusion");
|
||||
|
||||
r = xpu::findmax_copy_fusion(dev_ctx.x_context(),
|
||||
conv1_filter_data,
|
||||
conv1_filter_max_data,
|
||||
conv1_filter_l3_data,
|
||||
attr.conv1_filter_numel);
|
||||
PADDLE_ENFORCE_XDNN_SUCCESS(r, "findmax_copy_fusion");
|
||||
}
|
||||
xpu_conv2d(dev_ctx.x_context(),
|
||||
conv1_input_l3_data != nullptr ? conv1_input_l3_data : x_data,
|
||||
conv1_filter_l3_data,
|
||||
conv1_output_data,
|
||||
conv1_input_max_data,
|
||||
conv1_filter_max_data,
|
||||
attr.conv1_input_shape,
|
||||
attr.conv1_filter_shape,
|
||||
attr.padding1,
|
||||
attr.stride1,
|
||||
attr.dilation1,
|
||||
attr.group);
|
||||
|
||||
// 3. bn1 + relu
|
||||
if (!attr.global_stats) {
|
||||
DenseTensor *running_mean1 = mean1_out;
|
||||
DenseTensor *running_var1 = var1_out;
|
||||
|
||||
auto saved_mean1_data = dev_ctx.template Alloc<float>(saved_mean1);
|
||||
auto saved_invstd1_data = dev_ctx.template Alloc<float>(saved_invstd1);
|
||||
auto running_mean1_data = dev_ctx.template Alloc<float>(running_mean1);
|
||||
auto running_var1_data = dev_ctx.template Alloc<float>(running_var1);
|
||||
|
||||
r = xpu::batch_norm_fusion<XPUType>(dev_ctx.x_context(),
|
||||
conv1_output_data,
|
||||
conv2_input_data,
|
||||
attr.conv1_output_shape[0],
|
||||
attr.conv1_output_shape[1],
|
||||
attr.conv1_output_shape[2],
|
||||
attr.conv1_output_shape[3],
|
||||
attr.eps,
|
||||
attr.momentum,
|
||||
scale1_data,
|
||||
bias1_data,
|
||||
saved_mean1_data,
|
||||
saved_invstd1_data,
|
||||
running_mean1_data,
|
||||
running_var1_data,
|
||||
true,
|
||||
nullptr,
|
||||
xpu::Activation_t::RELU,
|
||||
nullptr,
|
||||
0);
|
||||
PADDLE_ENFORCE_XDNN_SUCCESS(r, "batch_norm_fusion");
|
||||
} else {
|
||||
// bn --> relu
|
||||
auto bn1_output_data = RAII_GUARD.alloc<XPUType>(attr.conv1_output_numel);
|
||||
PADDLE_ENFORCE_XDNN_NOT_NULL(bn1_output_data);
|
||||
|
||||
const auto *mean1 = &mean1_in;
|
||||
const auto *var1 = &var1_in;
|
||||
const auto *mean_data = mean1->data<float>();
|
||||
const auto *variance_data = var1->data<float>();
|
||||
r = xpu::batch_norm_infer<XPUType>(dev_ctx.x_context(),
|
||||
conv1_output_data,
|
||||
bn1_output_data,
|
||||
attr.conv1_output_shape[0],
|
||||
attr.conv1_output_shape[1],
|
||||
attr.conv1_output_shape[2],
|
||||
attr.conv1_output_shape[3],
|
||||
attr.eps,
|
||||
scale1_data,
|
||||
bias1_data,
|
||||
mean_data,
|
||||
variance_data,
|
||||
true);
|
||||
PADDLE_ENFORCE_XDNN_SUCCESS(r, "batch_norm_infer");
|
||||
|
||||
r = xpu::relu(dev_ctx.x_context(),
|
||||
bn1_output_data,
|
||||
conv2_input_data,
|
||||
attr.conv1_output_numel);
|
||||
PADDLE_ENFORCE_XDNN_SUCCESS(r, "relu");
|
||||
}
|
||||
|
||||
// 4. conv2
|
||||
XPUType *conv2_input_l3_data = nullptr;
|
||||
XPUType *conv2_filter_l3_data =
|
||||
RAII_GUARD.alloc_l3_or_gm<XPUType>(attr.conv2_filter_numel);
|
||||
if (attr.find_max) {
|
||||
conv2_input_max_data = dev_ctx.template Alloc<float>(max_input2);
|
||||
conv2_filter_max_data = dev_ctx.template Alloc<float>(max_filter2);
|
||||
|
||||
r = xpu::findmax_copy_fusion(dev_ctx.x_context(),
|
||||
conv2_input_data,
|
||||
conv2_input_max_data,
|
||||
conv2_input_l3_data,
|
||||
attr.conv2_input_numel);
|
||||
PADDLE_ENFORCE_XDNN_SUCCESS(r, "findmax_copy_fusion");
|
||||
|
||||
r = xpu::findmax_copy_fusion(dev_ctx.x_context(),
|
||||
conv2_filter_data,
|
||||
conv2_filter_max_data,
|
||||
conv2_filter_l3_data,
|
||||
attr.conv2_filter_numel);
|
||||
PADDLE_ENFORCE_XDNN_SUCCESS(r, "findmax_copy_fusion");
|
||||
}
|
||||
xpu_conv2d(
|
||||
dev_ctx.x_context(),
|
||||
conv2_input_l3_data != nullptr ? conv2_input_l3_data : conv2_input_data,
|
||||
conv2_filter_l3_data,
|
||||
conv2_output_data,
|
||||
conv2_input_max_data,
|
||||
conv2_filter_max_data,
|
||||
attr.conv2_input_shape,
|
||||
attr.conv2_filter_shape,
|
||||
attr.padding2,
|
||||
attr.stride2,
|
||||
attr.dilation2,
|
||||
attr.group);
|
||||
|
||||
// 5. bn2
|
||||
if (!attr.global_stats) {
|
||||
DenseTensor *saved_var2 = saved_invstd2;
|
||||
DenseTensor *running_mean2 = mean2_out;
|
||||
DenseTensor *running_var2 = var2_out;
|
||||
|
||||
auto saved_mean2_data = dev_ctx.template Alloc<float>(saved_mean2);
|
||||
auto saved_var2_data = dev_ctx.template Alloc<float>(saved_var2);
|
||||
auto running_mean2_data = dev_ctx.template Alloc<float>(running_mean2);
|
||||
auto running_var2_data = dev_ctx.template Alloc<float>(running_var2);
|
||||
|
||||
r = xpu::batch_norm_fusion<XPUType>(dev_ctx.x_context(),
|
||||
conv2_output_data,
|
||||
output_data,
|
||||
attr.conv2_output_shape[0],
|
||||
attr.conv2_output_shape[1],
|
||||
attr.conv2_output_shape[2],
|
||||
attr.conv2_output_shape[3],
|
||||
attr.eps,
|
||||
attr.momentum,
|
||||
scale2_data,
|
||||
bias2_data,
|
||||
saved_mean2_data,
|
||||
saved_var2_data,
|
||||
running_mean2_data,
|
||||
running_var2_data,
|
||||
true,
|
||||
z_out_data,
|
||||
xpu::Activation_t::RELU,
|
||||
nullptr,
|
||||
0);
|
||||
PADDLE_ENFORCE_XDNN_SUCCESS(r, "batch_norm_fusion");
|
||||
} else {
|
||||
auto bn2_out_data = RAII_GUARD.alloc<XPUType>(attr.conv2_output_numel);
|
||||
PADDLE_ENFORCE_XDNN_NOT_NULL(bn2_out_data);
|
||||
|
||||
const auto *mean2 = &mean2_in;
|
||||
const auto *var2 = &var2_in;
|
||||
const auto *mean_data = mean2->data<float>();
|
||||
const auto *variance_data = var2->data<float>();
|
||||
r = xpu::batch_norm_infer<XPUType>(dev_ctx.x_context(),
|
||||
conv2_output_data,
|
||||
bn2_out_data,
|
||||
attr.conv2_output_shape[0],
|
||||
attr.conv2_output_shape[1],
|
||||
attr.conv2_output_shape[2],
|
||||
attr.conv2_output_shape[3],
|
||||
attr.eps,
|
||||
scale2_data,
|
||||
bias2_data,
|
||||
mean_data,
|
||||
variance_data,
|
||||
true);
|
||||
PADDLE_ENFORCE_XDNN_SUCCESS(r, "batch_norm_infer");
|
||||
|
||||
r = xpu::add_activation_fusion<XPUType>(dev_ctx.x_context(),
|
||||
bn2_out_data,
|
||||
z_out_data,
|
||||
output_data,
|
||||
output->numel(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
xpu::Activation_t::RELU);
|
||||
PADDLE_ENFORCE_XDNN_SUCCESS(r, "add_activation_fusion");
|
||||
}
|
||||
}
|
||||
} // namespace fusion
|
||||
} // namespace phi
|
||||
|
||||
PD_REGISTER_KERNEL(resnet_basic_block,
|
||||
XPU,
|
||||
ALL_LAYOUT,
|
||||
phi::fusion::ResNetBasicBlockXPUKernel,
|
||||
float) {}
|
||||
Reference in New Issue
Block a user