Files
paddlepaddle--paddle/paddle/cinn/runtime/cpu/onednn_math.cc
T
2026-07-13 12:40:42 +08:00

234 lines
9.4 KiB
C++

// Copyright (c) 2021 CINN 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/cinn/runtime/cpu/onednn_math.h"
#include <vector>
#include "paddle/cinn/backends/extern_func_jit_register.h"
#include "paddle/cinn/optim/ir_simplify.h"
#include "paddle/common/enforce.h"
using dnnl::algorithm;
using dnnl::memory;
using tag = memory::format_tag;
using dt = memory::data_type;
void cinn_cpu_onednn_softmax_fp32(int batch,
int channel,
int h,
int w,
int axis,
cinn_buffer_t* inputs,
cinn_buffer_t* out) {
auto engine = dnnl::engine(dnnl::engine::kind::cpu, 0);
dnnl::stream engine_stream(engine);
memory::dims src_dims = {batch, channel};
if (h != 1) src_dims.push_back(h);
if (w != 1) src_dims.push_back(w);
int size = src_dims.size();
auto format_tag = tag::nc;
switch (size) {
case 2:
format_tag = tag::ab;
break;
case 3:
format_tag = tag::abc;
break;
case 4:
format_tag = tag::abcd;
break;
default:
std::stringstream ss;
ss << "wrong dim: " << size;
PADDLE_THROW(::common::errors::InvalidArgument(ss.str()));
break;
}
auto src_md = memory::desc(src_dims, dt::f32, format_tag);
auto src_mem =
memory(src_md, engine, reinterpret_cast<float*>(inputs->memory));
auto dst_mem = memory(src_md, engine, reinterpret_cast<float*>(out->memory));
auto softmax_pd =
dnnl::softmax_forward::primitive_desc(engine,
dnnl::prop_kind::forward_inference,
dnnl::algorithm::softmax_accurate,
src_md,
src_md,
axis);
auto softmax_prim = dnnl::softmax_forward(softmax_pd);
softmax_prim.execute(engine_stream,
{{DNNL_ARG_SRC, src_mem}, {DNNL_ARG_DST, dst_mem}});
engine_stream.wait();
}
void cinn_cpu_onednn_conv2d_nchw_fp32(int batch_size,
int c_in,
int input_h,
int input_w,
int c_out,
int group,
int filter_h,
int filter_w,
int pad_h,
int pad_w,
int stride_h,
int stride_w,
int dilation_h,
int dilation_w,
cinn_buffer_t* inputs,
cinn_buffer_t* weights,
cinn_buffer_t* out) {
auto cpu_engine = dnnl::engine(dnnl::engine::kind::cpu, 0);
dnnl::stream cpu_stream(cpu_engine);
memory::dims conv_src_tz = {batch_size, c_in, input_h, input_w};
memory::dims conv_weights_tz = {c_out, c_in, filter_h, filter_w};
if (group > 1) {
conv_weights_tz = {group, c_out / group, c_in / group, filter_h, filter_w};
}
int out_h =
(input_h - ((filter_h - 1) * dilation_h + 1) + 2 * pad_h) / stride_h + 1;
int out_w =
(input_w - ((filter_w - 1) * dilation_w + 1) + 2 * pad_w) / stride_w + 1;
memory::dims conv_dst_tz = {batch_size, c_out, out_h, out_w};
memory::dims conv_strides = {stride_h, stride_w};
memory::dims conv_paddings = {pad_h, pad_w};
memory::dims conv_dilations = {dilation_h - 1, dilation_w - 1};
auto conv_user_src_memory = memory({{conv_src_tz}, dt::f32, tag::nchw},
cpu_engine,
reinterpret_cast<float*>(inputs->memory));
auto conv_user_weights_memory =
memory({{conv_weights_tz}, dt::f32, group > 1 ? tag::goihw : tag::oihw},
cpu_engine,
reinterpret_cast<float*>(weights->memory));
auto conv_user_dst_memory = memory({{conv_dst_tz}, dt::f32, tag::nchw},
cpu_engine,
reinterpret_cast<float*>(out->memory));
auto conv_src_md = memory::desc({conv_src_tz}, dt::f32, tag::any);
auto conv_weights_md = memory::desc({conv_weights_tz}, dt::f32, tag::any);
auto conv_dst_md = memory::desc({conv_dst_tz}, dt::f32, tag::nchw);
auto conv_prim_desc = dnnl::convolution_forward::primitive_desc(
cpu_engine,
dnnl::prop_kind::forward_inference,
dnnl::algorithm::convolution_direct,
conv_src_md,
conv_weights_md,
conv_dst_md,
conv_strides,
conv_dilations,
conv_paddings,
conv_paddings);
auto conv_src_memory = conv_user_src_memory;
auto conv_weights_memory = conv_user_weights_memory;
auto conv_dst_memory = conv_user_dst_memory;
if (conv_prim_desc.dst_desc() != conv_user_dst_memory.get_desc()) {
conv_dst_memory = memory(conv_prim_desc.dst_desc(), cpu_engine);
}
auto conv = dnnl::convolution_forward(conv_prim_desc);
conv.execute(cpu_stream,
{{DNNL_ARG_SRC, conv_src_memory},
{DNNL_ARG_WEIGHTS, conv_weights_memory},
{DNNL_ARG_DST, conv_dst_memory}});
if (conv_prim_desc.dst_desc() != conv_user_dst_memory.get_desc()) {
dnnl::reorder(conv_dst_memory, conv_user_dst_memory)
.execute(cpu_stream, conv_dst_memory, conv_user_dst_memory);
} else {
conv_user_dst_memory = conv_dst_memory;
}
cpu_stream.wait();
}
CINN_REGISTER_HELPER(cinn_cpu_onednn) {
using namespace cinn; // NOLINT
using backends::FunctionProto;
auto host_target = cinn::common::DefaultHostTarget();
FunctionProto::shape_inference_t inference_shape_conv2d_nchw =
[](const std::vector<Expr>& args, int offset) {
PADDLE_ENFORCE_EQ(args.size(),
16UL,
::common::errors::InvalidArgument(
"Wrong number of arguments passed in."));
auto N = cinn::optim::ArithSimplify(args[0]);
int input_h = cinn::optim::ArithSimplify(args[2]).as_int32();
int input_w = cinn::optim::ArithSimplify(args[3]).as_int32();
auto c_out = cinn::optim::ArithSimplify(args[4]);
int filter_h = cinn::optim::ArithSimplify(args[6]).as_int32();
int filter_w = cinn::optim::ArithSimplify(args[7]).as_int32();
int pad_h = cinn::optim::ArithSimplify(args[8]).as_int32();
int pad_w = cinn::optim::ArithSimplify(args[9]).as_int32();
int stride_h = cinn::optim::ArithSimplify(args[10]).as_int32();
int stride_w = cinn::optim::ArithSimplify(args[11]).as_int32();
int dilation_h = cinn::optim::ArithSimplify(args[12]).as_int32();
int dilation_w = cinn::optim::ArithSimplify(args[13]).as_int32();
int out_h = (input_h - ((filter_h - 1) * dilation_h + 1) + 2 * pad_h) /
stride_h +
1;
int out_w = (input_w - ((filter_w - 1) * dilation_w + 1) + 2 * pad_w) /
stride_w +
1;
std::vector<Expr> shape;
shape.push_back(N);
shape.push_back(c_out);
shape.push_back(Expr(out_h));
shape.push_back(Expr(out_w));
return shape;
};
REGISTER_EXTERN_FUNC_HELPER(cinn_cpu_onednn_conv2d_nchw_fp32, host_target)
.SetRetType<void>()
.AddInputType<int>() // batch_size
.AddInputType<int>() // c_in
.AddInputType<int>() // input_h
.AddInputType<int>() // input_w
.AddInputType<int>() // c_out
.AddInputType<int>() // group
.AddInputType<int>() // filter_h
.AddInputType<int>() // filter_w
.AddInputType<int>() // pad_h
.AddInputType<int>() // pad_w
.AddInputType<int>() // stride_h
.AddInputType<int>() // stride_w
.AddInputType<int>() // dilation_h
.AddInputType<int>() // dilation_w
.AddInputType<cinn_buffer_t*>() // inputs
.AddInputType<cinn_buffer_t*>() // weights
.AddOutputType<cinn_buffer_t*>() // out
.SetShapeInference(inference_shape_conv2d_nchw)
.End();
REGISTER_EXTERN_FUNC_HELPER(cinn_cpu_onednn_softmax_fp32, host_target)
.SetRetType<void>()
.AddInputType<int>() // batch_size
.AddInputType<int>() // c_in
.AddInputType<int>() // h
.AddInputType<int>() // w
.AddInputType<int>() // axis
.AddInputType<cinn_buffer_t*>() // inputs
.AddOutputType<cinn_buffer_t*>() // out
.SetShapeInference(FunctionProto::ShapeFollowNthArgument(5))
.End();
return true;
}