Files
paddlepaddle--paddle/paddle/ap/include/kernel_dispatch/dispatch_ctx_method_class.h
T
2026-07-13 12:40:42 +08:00

247 lines
9.7 KiB
C++

// 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.
#pragma once
#include "paddle/ap/include/axpr/data_type_util.h"
#include "paddle/ap/include/axpr/method_class.h"
#include "paddle/ap/include/axpr/naive_class_ops.h"
#include "paddle/ap/include/axpr/value.h"
#include "paddle/ap/include/axpr/value_method_class.h"
#include "paddle/ap/include/kernel_dispatch/device_ctx_method_class.h"
#include "paddle/ap/include/kernel_dispatch/dispatch_ctx.h"
#include "paddle/ap/include/rt_module/function_method_class.h"
namespace ap::kernel_dispatch {
using ap::axpr::BuiltinBinaryFunc;
using ap::axpr::BuiltinFuncType;
using ap::axpr::BuiltinUnaryFunc;
using ap::axpr::CppDataType;
using ap::axpr::CppPointerType;
using ap::axpr::DataType;
using ap::axpr::DataValue;
using ap::axpr::MethodClass;
using ap::axpr::PointerType;
using ap::axpr::PointerValue;
namespace detail {
template <typename Val>
Result<Val> DispatchCtxGetInputs(const DispatchCtx<Val>& ctx,
const std::string& attr_name) {
return ctx->raw_ctx->inputs;
}
template <typename Val>
Result<Val> DispatchCtxGetOutputs(const DispatchCtx<Val>& ctx,
const std::string& attr_name) {
return ctx->raw_ctx->outputs;
}
template <typename Val>
Result<Val> DispatchCtxGetDeviceCtx(const DispatchCtx<Val>& ctx,
const std::string& attr_name) {
return GetDeviceCtxClass().New(ctx->raw_ctx->device_ctx);
}
template <typename Val>
Result<adt::List<ArgValue>> GetKernelArgs(const Val& args) {
const Result<adt::List<Val>>& arg_list =
args.template TryGet<adt::List<Val>>();
ADT_RETURN_IF_ERR(arg_list);
adt::List<ArgValue> ret;
ret->reserve(arg_list.GetOkValue()->size());
for (const auto& arg : *arg_list.GetOkValue()) {
const Result<ArgValue>& arg_value = CastToArgValue(arg);
ADT_RETURN_IF_ERR(arg_value);
ret->emplace_back(arg_value.GetOkValue());
}
return ret;
}
template <typename Val>
Result<Val> LaunchCuda(const Val& self_val, const std::vector<Val>& args) {
ADT_CHECK(args.size() == 4) << TypeError{
std::string() +
"DispatchCtx.launch_cuda take 6 arguments (including self) but " +
std::to_string(args.size()) + " were given."};
ADT_LET_CONST_REF(ctx, axpr::Get<DispatchCtx<Val>>(self_val));
ADT_LET_CONST_REF(func_name, args.at(0).template TryGet<std::string>());
ADT_LET_CONST_REF(num_blocks, args.at(1).template TryGet<int64_t>());
ADT_LET_CONST_REF(num_threads, args.at(2).template TryGet<int64_t>());
ADT_LET_CONST_REF(kernel_args, GetKernelArgs(args.at(3)));
ADT_RETURN_IF_ERR(ctx->raw_ctx->LaunchCudaKernel(
func_name, num_blocks, num_threads, kernel_args));
return adt::Nothing{};
}
template <typename Val, BuiltinFuncType<Val> BuiltinFunc>
Result<Val> MakeDispatchCtxMethod(const DispatchCtx<Val>& ctx,
const std::string&) {
return ap::axpr::Method<Val>{ctx, BuiltinFuncType<Val>{BuiltinFunc}};
}
template <typename Val, typename T>
Result<Val> DispatchCtxType(const DispatchCtx<Val>& ctx, const std::string&) {
return ap::axpr::TypeImpl<T>{};
}
template <typename Val>
using KernelCtxGettAttrT = Result<Val> (*)(const DispatchCtx<Val>& ctx,
const std::string&);
template <typename Val>
Result<Val> DispatchCtxGetAttr(const DispatchCtx<Val>& ctx,
const std::string& name) {
static const std::unordered_map<std::string, KernelCtxGettAttrT<Val>> map{
{ap::axpr::TypeImpl<ap::axpr::DataValue>{}.Name(),
&DispatchCtxType<Val, ap::axpr::DataValue>},
{"inputs", &DispatchCtxGetInputs<Val>},
{"outputs", &DispatchCtxGetOutputs<Val>},
{"device_ctx", &DispatchCtxGetDeviceCtx},
};
const auto& iter = map.find(name);
if (iter == map.end()) {
return AttributeError{std::string("'DispatchCtx' has no attribute '") +
name + "'"};
}
return iter->second(ctx, name);
}
} // namespace detail
template <typename ValueT>
struct DispatchCtxMethodClass {
using This = DispatchCtxMethodClass;
using Self = DispatchCtx<ValueT>;
static adt::Result<axpr::Value> ToString(
const axpr::Value& self_val, const std::vector<axpr::Value>& args) {
ADT_LET_CONST_REF(self, self_val.template CastTo<Self>());
const void* ptr = self.__adt_rc_shared_ptr_raw_ptr();
std::ostringstream ss;
ss << "<DispatchCtx object at " << ptr << ">";
return ss.str();
}
static adt::Result<ValueT> GetAttr(const ValueT& self_val,
const std::vector<ValueT>& args) {
ADT_LET_CONST_REF(self, axpr::Get<Self>(self_val));
ADT_CHECK(args.size() == 1);
const auto& attr_name_val = args.at(0);
ADT_LET_CONST_REF(attr_name, attr_name_val.template TryGet<std::string>());
if (attr_name == "kernel_dispatch_const_data") {
return self->kernel_dispatch_const_data;
}
return detail::DispatchCtxGetAttr<ValueT>(self, attr_name);
}
static adt::Result<ValueT> StaticGetInputIndexByName(
const ValueT& self_val, const std::vector<ValueT>& args) {
ADT_LET_CONST_REF(self, axpr::Get<Self>(self_val));
ADT_CHECK(args.size() == 1) << adt::errors::TypeError{
std::string() +
"'DispatchCtx.get_input_index_by_name' takes 1 argument but " +
std::to_string(args.size()) + " were given."};
ADT_LET_CONST_REF(tensor_name, args.at(0).template TryGet<std::string>())
<< adt::errors::TypeError{
std::string() +
"the argument 1 of 'DispatchCtx.get_input_index_by_name' should "
"be str (not '" +
axpr::GetTypeName(args.at(0)) + "')."};
return This{}.GetInputIndexByName(self, tensor_name);
}
adt::Result<ValueT> GetInputIndexByName(const Self& self,
const std::string& tensor_name) {
const auto& data = self->kernel_dispatch_const_data;
ADT_LET_CONST_REF(
name2idx,
data->template TryGet<axpr::AttrMap<axpr::SerializableValue>>(
"__builtin_ap_kernel_input_name_to_index"));
ADT_LET_CONST_REF(index, name2idx->template TryGet<int64_t>(tensor_name));
return index;
}
static adt::Result<ValueT> StaticGetOutputIndexByName(
const ValueT& self_val, const std::vector<ValueT>& args) {
ADT_LET_CONST_REF(self, axpr::Get<Self>(self_val));
ADT_CHECK(args.size() == 1) << adt::errors::TypeError{
std::string() +
"'DispatchCtx.get_output_index_by_name' takes 1 argument but " +
std::to_string(args.size()) + " were given."};
ADT_LET_CONST_REF(tensor_name, args.at(0).template TryGet<std::string>())
<< adt::errors::TypeError{
std::string() +
"the argument 1 of 'DispatchCtx.get_output_index_by_name' "
"should be str (not '" +
axpr::GetTypeName(args.at(0)) + "')."};
return This{}.GetOutputIndexByName(self, tensor_name);
}
static adt::Result<ValueT> StaticGetSoFunction(
const ValueT& self_val, const std::vector<ValueT>& args) {
ADT_LET_CONST_REF(self, axpr::Get<Self>(self_val));
ADT_CHECK(args.size() == 1) << adt::errors::TypeError{
std::string() +
"'DispatchCtx.get_so_function()' takes 1 argument but " +
std::to_string(args.size()) + " were given."};
ADT_LET_CONST_REF(function_name, args.at(0).template TryGet<std::string>())
<< adt::errors::TypeError{
std::string() +
"the argument 1 of 'DispatchCtx.get_so_function()' "
"should be str (not '" +
axpr::GetTypeName(args.at(0)) + "')."};
ADT_LET_CONST_REF(
rt_module,
self->raw_ctx->rt_module
.template TryGet<std::shared_ptr<const ap::rt_module::Module>>());
ADT_LET_CONST_REF(function, rt_module->Get(function_name))
<< adt::errors::TypeError{
std::string() +
"DispatchCtx.get_so_function() failed. so function '" +
function_name + "' not found"};
return rt_module::GetSoFunctionClass().New(function);
}
adt::Result<ValueT> GetOutputIndexByName(const Self& self,
const std::string& tensor_name) {
const auto& data = self->kernel_dispatch_const_data;
ADT_LET_CONST_REF(
name2idx,
data->template TryGet<axpr::AttrMap<axpr::SerializableValue>>(
"__builtin_ap_kernel_output_name_to_index"));
ADT_LET_CONST_REF(index, name2idx->template TryGet<int64_t>(tensor_name));
return index;
}
};
template <typename ValueT>
axpr::TypeImpl<axpr::BuiltinClassInstance<ValueT>> GetDispatchCtxClass() {
using Methods = DispatchCtxMethodClass<ValueT>;
static auto cls(
axpr::MakeBuiltinClass<ValueT>("DispatchCtx", [&](const auto& Yield) {
Yield("__str__", &Methods::ToString);
Yield("__getattr__", &Methods::GetAttr);
Yield("get_input_index_by_name", &Methods::StaticGetInputIndexByName);
Yield("get_output_index_by_name", &Methods::StaticGetOutputIndexByName);
Yield("get_so_function", &Methods::StaticGetSoFunction);
}));
using Self = typename Methods::Self;
return axpr::MakeGlobalNaiveClassOps<Self>(cls);
}
} // namespace ap::kernel_dispatch