mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-07-18 18:52:16 +00:00
Consolidate MLTypeCallDispatcher classes (#6651)
This commit is contained in:
parent
e6de0eb813
commit
b2cddc5337
52 changed files with 277 additions and 276 deletions
|
|
@ -7,6 +7,7 @@
|
|||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "boost/mp11.hpp"
|
||||
|
|
@ -16,11 +17,6 @@
|
|||
#include "core/framework/data_types.h"
|
||||
#include "core/graph/onnx_protobuf.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
//TODO: fix the warning in CallableDispatchableRetHelper
|
||||
#pragma warning(disable : 4702)
|
||||
#endif
|
||||
namespace onnxruntime {
|
||||
namespace utils {
|
||||
|
||||
|
|
@ -223,6 +219,7 @@ inline bool IsPrimitiveDataType(const PrimitiveDataTypeBase* prim_type) {
|
|||
// This implementation contains a workaround for GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226
|
||||
// GCC until very recently does not support template parameter pack expansion within lambda context.
|
||||
namespace mltype_dispatcher_internal {
|
||||
|
||||
// T - type handled by this helper
|
||||
class CallableDispatchableHelper {
|
||||
int32_t dt_type_; // Type currently dispatched
|
||||
|
|
@ -242,7 +239,6 @@ class CallableDispatchableHelper {
|
|||
}
|
||||
|
||||
void CheckCalledOnce() {
|
||||
ORT_ENFORCE(called_ < 2, "Check for duplicate types in MLTypeCallDispatcher");
|
||||
ORT_ENFORCE(called_ == 1, "Unsupported data type: ", dt_type_);
|
||||
}
|
||||
};
|
||||
|
|
@ -256,7 +252,7 @@ struct UnsupportedTypeDefaultPolicy {
|
|||
};
|
||||
|
||||
// Helper with the result type
|
||||
template <class Ret, class UnsupportedPolicy = UnsupportedTypeDefaultPolicy<Ret>>
|
||||
template <class Ret, class UnsupportedPolicy>
|
||||
class CallableDispatchableRetHelper {
|
||||
int32_t dt_type_; // Type currently dispatched
|
||||
size_t called_;
|
||||
|
|
@ -266,8 +262,6 @@ class CallableDispatchableRetHelper {
|
|||
explicit CallableDispatchableRetHelper(int32_t dt_type) noexcept : dt_type_(dt_type), called_(0), result_() {}
|
||||
|
||||
Ret Get() {
|
||||
// See if there were multiple invocations.It is a bug.
|
||||
ORT_ENFORCE(called_ < 2, "Check for duplicate types in MLTypeCallDispatcherRet");
|
||||
// No type was invoked
|
||||
if (called_ == 0) {
|
||||
result_ = UnsupportedPolicy()(dt_type_);
|
||||
|
|
@ -286,103 +280,89 @@ class CallableDispatchableRetHelper {
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using TensorProtoElementTypeConstant =
|
||||
std::integral_constant<ONNX_NAMESPACE::TensorProto_DataType, ToTensorProtoElementType<T>()>;
|
||||
|
||||
using UndefinedTensorProtoElementTypeConstant =
|
||||
std::integral_constant<ONNX_NAMESPACE::TensorProto_DataType, ONNX_NAMESPACE::TensorProto_DataType_UNDEFINED>;
|
||||
|
||||
} // namespace mltype_dispatcher_internal
|
||||
|
||||
// This class helps to efficiently dispatch calls for templated
|
||||
// kernel implementation functions that has no return value.
|
||||
// If your implementation function must return a value such as Status
|
||||
// Use MLTypeCallDispatcherRet class.
|
||||
//
|
||||
// The first template parameter is a template<T> struct/class functor
|
||||
// that must implement operator() with arbitrary number of arguments
|
||||
// and void return turn. It must return Ret type if you are using MLTypeCallDispatcherRet.
|
||||
// Fn must be default constructible.
|
||||
//
|
||||
// Types is a type list that are supported by this kernel implementation.
|
||||
// There should be no duplicate types. An exception will be thrown if there
|
||||
// a duplicate.
|
||||
//
|
||||
// The constructor accepts an enum that is obtained from
|
||||
// input_tensor->DataType()->AsPrimitiveType()->GetDataType().
|
||||
// Fn will be called only once the type designated by dt_type value.
|
||||
// If current dt_type is not handled, the Dispatcher will throw an exception.
|
||||
//
|
||||
template <template <typename> class Fn, typename... Types>
|
||||
/**
|
||||
* This class helps to efficiently dispatch calls to implementation function
|
||||
* objects with a tensor element type template argument.
|
||||
*
|
||||
* The constructor accepts a value corresponding to a tensor element type.
|
||||
* For example, it can be obtained from:
|
||||
* input_tensor->GetElementType()
|
||||
*
|
||||
* The Invoke member functions will instantiate and invoke the provided
|
||||
* function object template, Fn. Fn must be default constructible. Fn must also
|
||||
* have a tensor element type template argument. This type template argument
|
||||
* will be the type that corresponds to the value given in the constructor.
|
||||
* These functions accept and forward arbitrary function arguments. They ensure
|
||||
* that Fn is called once with the type specified in the constructor.
|
||||
*
|
||||
* @tparam Types The types supported by the implementation. This should be a
|
||||
* set of ONNX tensor element types that are supported by ORT.
|
||||
*/
|
||||
template <typename... Types>
|
||||
class MLTypeCallDispatcher {
|
||||
using SupportedTypeList = TypeList<Types...>;
|
||||
using SupportedTensorProtoElementTypeList =
|
||||
boost::mp11::mp_transform<
|
||||
mltype_dispatcher_internal::TensorProtoElementTypeConstant, SupportedTypeList>;
|
||||
|
||||
static_assert(
|
||||
boost::mp11::mp_and<
|
||||
boost::mp11::mp_is_set<SupportedTensorProtoElementTypeList>,
|
||||
boost::mp11::mp_not<
|
||||
boost::mp11::mp_set_contains<
|
||||
SupportedTensorProtoElementTypeList,
|
||||
mltype_dispatcher_internal::UndefinedTensorProtoElementTypeConstant>>>::value,
|
||||
"Types must map to a unique set of ONNX tensor element data types supported by ORT.");
|
||||
|
||||
int32_t dt_type_;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param dt_type The value corresponding to the tensor element type to be
|
||||
* dispatched to. This can be obtained from
|
||||
* input_tensor->GetElementType() or
|
||||
* utils::ToTensorProtoElementType<T>().
|
||||
*/
|
||||
explicit MLTypeCallDispatcher(int32_t dt_type) noexcept : dt_type_(dt_type) {}
|
||||
|
||||
template <typename... Args>
|
||||
void Invoke(Args&&... args) const {
|
||||
mltype_dispatcher_internal::CallableDispatchableHelper helper(dt_type_);
|
||||
int results[] = {0, helper.template Invoke<Types>(Fn<Types>(), std::forward<Args>(args)...)...};
|
||||
ORT_UNUSED_PARAMETER(results);
|
||||
helper.CheckCalledOnce();
|
||||
}
|
||||
};
|
||||
|
||||
// Version of the MLTypeDispatcher with a return type.
|
||||
// Return type of Fn must return type convertible to Ret
|
||||
// The value of the return type will be the return value
|
||||
// of the function for type T which was specified for execution.
|
||||
template <class Ret, template <typename> class Fn, typename... Types>
|
||||
class MLTypeCallDispatcherRet {
|
||||
int32_t dt_type_;
|
||||
|
||||
public:
|
||||
explicit MLTypeCallDispatcherRet(int32_t dt_type) noexcept : dt_type_(dt_type) {}
|
||||
|
||||
template <typename... Args>
|
||||
Ret Invoke(Args&&... args) const {
|
||||
mltype_dispatcher_internal::CallableDispatchableRetHelper<Ret> helper(dt_type_);
|
||||
int results[] = {0, helper.template Invoke<Types>(Fn<Types>(), std::forward<Args>(args)...)...};
|
||||
ORT_UNUSED_PARAMETER(results);
|
||||
return helper.Get();
|
||||
}
|
||||
|
||||
template <class UnsupportedPolicy, typename... Args>
|
||||
Ret InvokeWithUnsupportedPolicy(Args&&... args) const {
|
||||
mltype_dispatcher_internal::CallableDispatchableRetHelper<Ret, UnsupportedPolicy> helper(dt_type_);
|
||||
int results[] = {0, helper.template Invoke<Types>(Fn<Types>(), std::forward<Args>(args)...)...};
|
||||
ORT_UNUSED_PARAMETER(results);
|
||||
return helper.Get();
|
||||
}
|
||||
};
|
||||
|
||||
// Version of MLTypeCallDispatcher that takes supported types as class-level template parameters.
|
||||
// This enables easier use with type list representations of the supported types.
|
||||
// The invocation-related template parameters like Fn move to the individual Invoke() methods.
|
||||
// TODO consolidate this with the other MLTypeCallDispatcher classes
|
||||
// can add additional methods to cover their usages, but need to update call sites
|
||||
template <typename... Types>
|
||||
class MLTypeCallDispatcher2 {
|
||||
static_assert(boost::mp11::mp_is_set<TypeList<Types...>>::value,
|
||||
"MLTypeCallDispatcher requires a set of unique types.");
|
||||
|
||||
int32_t dt_type_;
|
||||
|
||||
public:
|
||||
explicit MLTypeCallDispatcher2(int32_t dt_type) noexcept : dt_type_(dt_type) {}
|
||||
|
||||
/**
|
||||
* Invokes Fn<T> with the specified arguments.
|
||||
*
|
||||
* @tparam Fn The function object template.
|
||||
* @tparam Args The argument types.
|
||||
*/
|
||||
template <template <typename> class Fn, typename... Args>
|
||||
void Invoke(Args&&... args) const {
|
||||
mltype_dispatcher_internal::CallableDispatchableHelper helper(dt_type_);
|
||||
|
||||
static_cast<void>(std::array<int, sizeof...(Types)>{
|
||||
helper.template Invoke<Types>(Fn<Types>(), std::forward<Args>(args)...)...});
|
||||
|
||||
// avoid "unused parameter" warning for the case where Types is empty
|
||||
static_cast<void>(std::array<int, sizeof...(Args)>{(ORT_UNUSED_PARAMETER(args), 0)...});
|
||||
|
||||
helper.CheckCalledOnce();
|
||||
InvokeWithLeadingTemplateArgs<Fn, TypeList<>>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes Fn<..., T> with leading template arguments and the specified arguments.
|
||||
*
|
||||
* @tparam Fn The function object template.
|
||||
* @tparam LeadingTemplateArgTypeList A type list of the leading template arguments.
|
||||
* @tparam Args The argument types.
|
||||
*/
|
||||
template <template <typename...> class Fn, typename LeadingTemplateArgTypeList, typename... Args>
|
||||
void InvokeWithLeadingTemplateArgs(Args&&... args) const {
|
||||
static_assert(
|
||||
boost::mp11::mp_is_list<LeadingTemplateArgTypeList>::value,
|
||||
"LeadingTemplateArgTypeList must be a type list (e.g., onnxruntime::TypeList<T1, T2, ...>).");
|
||||
|
||||
mltype_dispatcher_internal::CallableDispatchableHelper helper(dt_type_);
|
||||
|
||||
// given LeadingTemplateArgTypeList is a type list L<U1, U2, ...>,
|
||||
// call helper.Invoke() with Fn<U1, U2, ..., T> for each T in Types
|
||||
static_cast<void>(std::array<int, sizeof...(Types)>{
|
||||
helper.template Invoke<Types>(
|
||||
boost::mp11::mp_apply<Fn, boost::mp11::mp_push_back<LeadingTemplateArgTypeList, Types>>(),
|
||||
|
|
@ -393,11 +373,49 @@ class MLTypeCallDispatcher2 {
|
|||
|
||||
helper.CheckCalledOnce();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes Fn<T> with the specified arguments and returns the result.
|
||||
*
|
||||
* @tparam Ret The return type. Fn should return a type convertible to Ret.
|
||||
* @tparam Fn The function object template.
|
||||
* @tparam Args The argument types.
|
||||
*/
|
||||
template <class Ret, template <typename> class Fn, typename... Args>
|
||||
Ret InvokeRet(Args&&... args) const {
|
||||
return InvokeRetWithUnsupportedPolicy<
|
||||
Ret, Fn, mltype_dispatcher_internal::UnsupportedTypeDefaultPolicy<Ret>>(
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes Fn<T> with the specified arguments and returns the result.
|
||||
*
|
||||
* @tparam Ret The return type. Fn should return a type convertible to Ret.
|
||||
* @tparam Fn The function object template.
|
||||
* @tparam UnsupportedPolicy The policy used to handle unsupported types.
|
||||
* See mltype_dispatcher_internal::UnsupportedTypeDefaultPolicy
|
||||
* for an example.
|
||||
* @tparam Args The argument types.
|
||||
*/
|
||||
template <class Ret, template <typename> class Fn, class UnsupportedPolicy, typename... Args>
|
||||
Ret InvokeRetWithUnsupportedPolicy(Args&&... args) const {
|
||||
mltype_dispatcher_internal::CallableDispatchableRetHelper<Ret, UnsupportedPolicy> helper(dt_type_);
|
||||
|
||||
// call helper.Invoke() with Fn<T> for each T in Types
|
||||
static_cast<void>(std::array<int, sizeof...(Types)>{
|
||||
helper.template Invoke<Types>(Fn<Types>(), std::forward<Args>(args)...)...});
|
||||
|
||||
// avoid "unused parameter" warning for the case where Types is empty
|
||||
static_cast<void>(std::array<int, sizeof...(Args)>{(ORT_UNUSED_PARAMETER(args), 0)...});
|
||||
|
||||
return helper.Get();
|
||||
}
|
||||
};
|
||||
|
||||
// the type MLTypeCallDispatcher2<T...> given a type list L<T...>
|
||||
// the type MLTypeCallDispatcher<T...> given a type list L<T...>
|
||||
template <typename L>
|
||||
using MLTypeCallDispatcherFromTypeList = boost::mp11::mp_apply<MLTypeCallDispatcher2, L>;
|
||||
using MLTypeCallDispatcherFromTypeList = boost::mp11::mp_apply<MLTypeCallDispatcher, L>;
|
||||
|
||||
namespace data_types_internal {
|
||||
|
||||
|
|
@ -553,7 +571,3 @@ bool IsOpaqueType(MLDataType ml_type, const char* domain, const char* name);
|
|||
|
||||
} // namespace utils
|
||||
} // namespace onnxruntime
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -77,8 +77,8 @@ Status Inverse::Compute(OpKernelContext* ctx) const {
|
|||
}
|
||||
|
||||
std::function<void(ptrdiff_t)> fn = [elem_type, input, output, rows, cols](ptrdiff_t batch_num) {
|
||||
utils::MLTypeCallDispatcher<ComputeImpl, float, double, MLFloat16> t_disp(elem_type);
|
||||
t_disp.Invoke(input, output, batch_num, rows, cols);
|
||||
utils::MLTypeCallDispatcher<float, double, MLFloat16> t_disp(elem_type);
|
||||
t_disp.Invoke<ComputeImpl>(input, output, batch_num, rows, cols);
|
||||
};
|
||||
|
||||
concurrency::ThreadPool::TryBatchParallelFor(ctx->GetOperatorThreadPool(), num_batches, std::move(fn), 0);
|
||||
|
|
|
|||
|
|
@ -153,8 +153,9 @@ Status Inverse::ComputeInternal(OpKernelContext* ctx) const {
|
|||
CUDA_RETURN_IF_ERROR(cudaMemsetAsync(info.get(), 0, num_batches, Stream()));
|
||||
IAllocatorUniquePtr<int> pivots = GetScratchBuffer<int>(rows * num_batches);
|
||||
|
||||
utils::MLTypeCallDispatcherRet<Status, ComputeImpl, float, double, MLFloat16> t_disp(input->GetElementType());
|
||||
return t_disp.Invoke(Stream(), Base::CublasHandle(), this, *input, *output, info, pivots, num_batches, rows);
|
||||
utils::MLTypeCallDispatcher<float, double, MLFloat16> t_disp(input->GetElementType());
|
||||
return t_disp.InvokeRet<Status, ComputeImpl>(
|
||||
Stream(), Base::CublasHandle(), this, *input, *output, info, pivots, num_batches, rows);
|
||||
}
|
||||
|
||||
} // namespace cuda
|
||||
|
|
|
|||
|
|
@ -62,16 +62,14 @@ Status BiasSoftmax::ComputeInternal(OpKernelContext* ctx) const {
|
|||
const int broadcast_size = N / static_cast<int>(X_shape.SizeToDimension(broadcast_axis));
|
||||
|
||||
const size_t elem_size = X->DataType()->Size();
|
||||
utils::MLTypeCallDispatcher<double, float, MLFloat16> t_disp(X->GetElementType());
|
||||
|
||||
if (D <= 1024 && D * elem_size <= 4096) {
|
||||
// expect thread blocks can fill SM at high occupancy without overflowing registers
|
||||
utils::MLTypeCallDispatcher<DispatchBiasSoftmaxForward, double, float, MLFloat16>
|
||||
t_disp(X->GetElementType());
|
||||
t_disp.Invoke(Stream(), Y, X, B, D, N, D, broadcast_size);
|
||||
t_disp.Invoke<DispatchBiasSoftmaxForward>(Stream(), Y, X, B, D, N, D, broadcast_size);
|
||||
} else {
|
||||
// need to fallback to add kernel + CUDA DNN library softmax call :/
|
||||
utils::MLTypeCallDispatcher<DispatchBiasSoftMaxForwardViaDnnLibrary, double, float, MLFloat16>
|
||||
t_disp(X->GetElementType());
|
||||
t_disp.Invoke(Stream(), CudnnHandle(), D, N, broadcast_axis, softmax_axis, X_shape, X, B_shape, B, Y);
|
||||
t_disp.Invoke<DispatchBiasSoftMaxForwardViaDnnLibrary>(Stream(), CudnnHandle(), D, N, broadcast_axis, softmax_axis, X_shape, X, B_shape, B, Y);
|
||||
}
|
||||
|
||||
return Status::OK();
|
||||
|
|
|
|||
|
|
@ -65,16 +65,15 @@ Status BiasSoftmax::ComputeInternal(OpKernelContext* ctx) const {
|
|||
const int broadcast_size = N / static_cast<int>(X_shape.SizeToDimension(broadcast_axis));
|
||||
|
||||
const size_t elem_size = X->DataType()->Size();
|
||||
utils::MLTypeCallDispatcher<float, MLFloat16> t_disp(X->GetElementType());
|
||||
|
||||
if (D <= 1024 && D * elem_size <= 4096) {
|
||||
// expect thread blocks can fill SM at high occupancy without overflowing registers
|
||||
utils::MLTypeCallDispatcher<DispatchBiasSoftmaxForward, float, MLFloat16>
|
||||
t_disp(X->GetElementType());
|
||||
t_disp.Invoke(Stream(), Y, X, B, D, N, D, broadcast_size);
|
||||
t_disp.Invoke<DispatchBiasSoftmaxForward>(Stream(), Y, X, B, D, N, D, broadcast_size);
|
||||
} else {
|
||||
// need to fallback to add kernel + CUDA DNN library softmax call :/
|
||||
utils::MLTypeCallDispatcher<DispatchBiasSoftMaxForwardViaDnnLibrary, float, MLFloat16>
|
||||
t_disp(X->GetElementType());
|
||||
t_disp.Invoke(Stream(), MiopenHandle(), D, N, broadcast_axis, softmax_axis, X_shape, X, B_shape, B, Y);
|
||||
t_disp.Invoke<DispatchBiasSoftMaxForwardViaDnnLibrary>(
|
||||
Stream(), MiopenHandle(), D, N, broadcast_axis, softmax_axis, X_shape, X, B_shape, B, Y);
|
||||
}
|
||||
|
||||
return Status::OK();
|
||||
|
|
|
|||
|
|
@ -954,8 +954,9 @@ common::Status SparseTensorProtoToDenseTensorProto(const ONNX_NAMESPACE::SparseT
|
|||
void* sparse_data = sparse_data_storage.get();
|
||||
size_t element_size = 0;
|
||||
// We want to this list to match the one used below in DenseTensorToSparseTensorProto()
|
||||
MLTypeCallDispatcherRet<Status, GetElementSize, float, int8_t, uint8_t> type_disp(type);
|
||||
ORT_RETURN_IF_ERROR(type_disp.InvokeWithUnsupportedPolicy<UnsupportedSparseDataType>(element_size));
|
||||
MLTypeCallDispatcher<float, int8_t, uint8_t> type_disp(type);
|
||||
ORT_RETURN_IF_ERROR(
|
||||
(type_disp.InvokeRetWithUnsupportedPolicy<Status, GetElementSize, UnsupportedSparseDataType>(element_size)));
|
||||
|
||||
// by putting the data into a std::string we can avoid a copy as set_raw_data can do a std::move
|
||||
// into the TensorProto. however to actually write to the buffer we have created in the std::string we need
|
||||
|
|
@ -1076,8 +1077,9 @@ common::Status DenseTensorToSparseTensorProto(const ONNX_NAMESPACE::TensorProto&
|
|||
std::unique_ptr<uint8_t[]> dense_raw_data;
|
||||
ORT_RETURN_IF_ERROR(UnpackInitializerData(dense_proto, model_path, dense_raw_data, tensor_bytes_size));
|
||||
size_t element_size = 0;
|
||||
MLTypeCallDispatcherRet<Status, GetElementSize, float, int8_t, uint8_t> type_disp(data_type);
|
||||
ORT_RETURN_IF_ERROR(type_disp.InvokeWithUnsupportedPolicy<UnsupportedSparseDataType>(element_size));
|
||||
MLTypeCallDispatcher<float, int8_t, uint8_t> type_disp(data_type);
|
||||
ORT_RETURN_IF_ERROR(
|
||||
(type_disp.InvokeRetWithUnsupportedPolicy<Status, GetElementSize, UnsupportedSparseDataType>(element_size)));
|
||||
|
||||
switch (element_size) {
|
||||
case 1: {
|
||||
|
|
|
|||
|
|
@ -44,11 +44,11 @@ optional<float> GetScalarConstantInitializer(const Graph& graph, const NodeArg&
|
|||
}
|
||||
|
||||
float scalar{};
|
||||
utils::MLTypeCallDispatcherRet<
|
||||
Status, ExtractScalarAsFloatDispatchTarget,
|
||||
utils::MLTypeCallDispatcher<
|
||||
uint32_t, uint64_t, int32_t, int64_t, MLFloat16, float, double, BFloat16>
|
||||
dispatcher{initializer->data_type()};
|
||||
ORT_THROW_IF_ERROR(dispatcher.Invoke(*initializer, graph.ModelPath(), scalar));
|
||||
ORT_THROW_IF_ERROR(
|
||||
(dispatcher.InvokeRet<Status, ExtractScalarAsFloatDispatchTarget>(*initializer, graph.ModelPath(), scalar)));
|
||||
|
||||
return {scalar};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,10 +95,9 @@ struct CallRangeImpl {
|
|||
Status Range::Compute(OpKernelContext* ctx) const {
|
||||
const auto* input_tensor = ctx->Input<Tensor>(0);
|
||||
if (input_tensor == nullptr) return Status(common::ONNXRUNTIME, common::FAIL, "input count mismatch");
|
||||
utils::MLTypeCallDispatcherRet<Status, range_internal::CallRangeImpl,
|
||||
int32_t, float, int64_t, double, int16_t>
|
||||
utils::MLTypeCallDispatcher<int32_t, float, int64_t, double, int16_t>
|
||||
t_disp(input_tensor->GetElementType());
|
||||
return t_disp.Invoke(ctx);
|
||||
return t_disp.InvokeRet<Status, range_internal::CallRangeImpl>(ctx);
|
||||
}
|
||||
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -74,10 +74,10 @@ Status Clip::Compute(OpKernelContext* ctx) const {
|
|||
const auto* max = ctx->Input<Tensor>(2);
|
||||
Tensor* Y = ctx->Output(0, X->Shape());
|
||||
|
||||
utils::MLTypeCallDispatcher<ComputeImpl, float, double, int8_t, uint8_t, int64_t, uint64_t>
|
||||
utils::MLTypeCallDispatcher<float, double, int8_t, uint8_t, int64_t, uint64_t>
|
||||
t_disp(X->GetElementType());
|
||||
|
||||
t_disp.Invoke(X, min, max, Y);
|
||||
t_disp.Invoke<ComputeImpl>(X, min, max, Y);
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -724,9 +724,9 @@ Status Min_8::Compute(OpKernelContext* context) const {
|
|||
return MinMaxMLFloat16<true>(*this, context);
|
||||
break;
|
||||
default:
|
||||
utils::MLTypeCallDispatcherRet<Status, ComputeImpl, float, double, int32_t, uint32_t, int64_t, uint64_t>
|
||||
utils::MLTypeCallDispatcher<float, double, int32_t, uint32_t, int64_t, uint64_t>
|
||||
t_disp(dt_type);
|
||||
return t_disp.Invoke(*this, context);
|
||||
return t_disp.InvokeRet<Status, ComputeImpl>(*this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -784,9 +784,9 @@ Status Max_8::Compute(OpKernelContext* context) const {
|
|||
return MinMaxMLFloat16<false>(*this, context);
|
||||
break;
|
||||
default:
|
||||
utils::MLTypeCallDispatcherRet<Status, ComputeImpl, float, double, int32_t, uint32_t, int64_t, uint64_t>
|
||||
utils::MLTypeCallDispatcher<float, double, int32_t, uint32_t, int64_t, uint64_t>
|
||||
t_disp(dt_type);
|
||||
return t_disp.Invoke(*this, context);
|
||||
return t_disp.InvokeRet<Status, ComputeImpl>(*this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1671,10 +1671,10 @@ Status Mod::Compute(OpKernelContext* context) const {
|
|||
mod_internal::BroadCastMFloat16FMod(context);
|
||||
break;
|
||||
default:
|
||||
utils::MLTypeCallDispatcher<mod_internal::CallModImpl, uint8_t, int8_t, uint16_t, int16_t,
|
||||
uint32_t, int32_t, uint64_t, int64_t>
|
||||
utils::MLTypeCallDispatcher<uint8_t, int8_t, uint16_t, int16_t,
|
||||
uint32_t, int32_t, uint64_t, int64_t>
|
||||
t_disp(dt_type);
|
||||
t_disp.Invoke(fmod_, context);
|
||||
t_disp.Invoke<mod_internal::CallModImpl>(fmod_, context);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -115,10 +115,10 @@ Status Sign::Compute(OpKernelContext* ctx) const {
|
|||
SignMLFloat16(input, output);
|
||||
break;
|
||||
default:
|
||||
utils::MLTypeCallDispatcher<CallSignImpl, float, double, int8_t, uint8_t,
|
||||
utils::MLTypeCallDispatcher<float, double, int8_t, uint8_t,
|
||||
int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t>
|
||||
t_disp(dtype);
|
||||
t_disp.Invoke(input, output);
|
||||
t_disp.Invoke<CallSignImpl>(input, output);
|
||||
break;
|
||||
}
|
||||
return Status::OK();
|
||||
|
|
|
|||
|
|
@ -169,10 +169,10 @@ struct Normalizer::CallNormalizerImpl {
|
|||
Status Normalizer::Compute(OpKernelContext* context) const {
|
||||
const auto& input_tensor_ptr = *context->Input<Tensor>(0);
|
||||
|
||||
utils::MLTypeCallDispatcherRet<Status, CallNormalizerImpl, float, double, int64_t, int32_t>
|
||||
utils::MLTypeCallDispatcher<float, double, int64_t, int32_t>
|
||||
t_disp(input_tensor_ptr.GetElementType());
|
||||
|
||||
auto status = t_disp.Invoke(this, context);
|
||||
auto status = t_disp.InvokeRet<Status, CallNormalizerImpl>(this, context);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -132,9 +132,9 @@ Status Pool<float, AveragePool>::Compute(OpKernelContext* context) const {
|
|||
|
||||
|
||||
Status MaxPoolV8::Compute(OpKernelContext* context) const {
|
||||
utils::MLTypeCallDispatcherRet<Status, ComputeHelper, float, double, int8_t, uint8_t>
|
||||
utils::MLTypeCallDispatcher<float, double, int8_t, uint8_t>
|
||||
t_disp(context->Input<Tensor>(0)->GetElementType());
|
||||
return t_disp.Invoke(this, context);
|
||||
return t_disp.InvokeRet<Status, ComputeHelper>(this, context);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
|
|
|||
|
|
@ -74,9 +74,9 @@ Status Shrink::Compute(OpKernelContext* p_op_kernel_context) const {
|
|||
const auto* input = p_op_kernel_context->Input<Tensor>(0);
|
||||
auto* output = p_op_kernel_context->Output(0, input->Shape());
|
||||
// bool, std::string are not supported.
|
||||
utils::MLTypeCallDispatcherRet<Status, shrink_internal::CallShrinkImpl, float, double, MLFloat16, BFloat16, int8_t, uint8_t,
|
||||
int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t>
|
||||
utils::MLTypeCallDispatcher<float, double, MLFloat16, BFloat16, int8_t, uint8_t,
|
||||
int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t>
|
||||
t_disp(input->GetElementType());
|
||||
return t_disp.Invoke(input, output, bias_, lambd_);
|
||||
return t_disp.InvokeRet<Status, shrink_internal::CallShrinkImpl>(input, output, bias_, lambd_);
|
||||
}
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -97,10 +97,9 @@ Status Range::ComputeInternal(OpKernelContext* ctx) const {
|
|||
return Status(common::ONNXRUNTIME, common::FAIL, "input count mismatch");
|
||||
}
|
||||
|
||||
utils::MLTypeCallDispatcherRet<Status, cuda_range_internal::CallCudaRangeImpl, int32_t,
|
||||
float, int64_t, double, int16_t>
|
||||
utils::MLTypeCallDispatcher<int32_t, float, int64_t, double, int16_t>
|
||||
t_disp(input_tensor->GetElementType());
|
||||
return t_disp.Invoke(Stream(), ctx);
|
||||
return t_disp.InvokeRet<Status, cuda_range_internal::CallCudaRangeImpl>(Stream(), ctx);
|
||||
}
|
||||
|
||||
} // namespace cuda
|
||||
|
|
|
|||
|
|
@ -121,10 +121,10 @@ Status Clip::ComputeInternal(OpKernelContext* ctx) const {
|
|||
const auto* max = ctx->Input<Tensor>(2);
|
||||
Tensor* Y = ctx->Output(0, X->Shape());
|
||||
|
||||
utils::MLTypeCallDispatcher<ComputeImpl, float, double, int8_t, uint8_t, int64_t, uint64_t>
|
||||
utils::MLTypeCallDispatcher<float, double, int8_t, uint8_t, int64_t, uint64_t>
|
||||
t_disp(X->GetElementType());
|
||||
|
||||
t_disp.Invoke(Stream(), X, min, max, Y);
|
||||
t_disp.Invoke<ComputeImpl>(Stream(), X, min, max, Y);
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ Status VariadicElementwiseOp<VariadicElementwiseOpTag, SupportedElementTypes...>
|
|||
}
|
||||
|
||||
const auto element_type = first_input_tensor.GetElementType();
|
||||
utils::MLTypeCallDispatcher<SupportedElementTypes...> dispatcher(element_type);
|
||||
|
||||
// special case for no broadcasting and few enough inputs
|
||||
if (input_count <= k_max_input_batch_size &&
|
||||
|
|
@ -154,17 +155,12 @@ Status VariadicElementwiseOp<VariadicElementwiseOpTag, SupportedElementTypes...>
|
|||
|
||||
// special case for no broadcasting and 2 inputs
|
||||
if (input_count == 2) {
|
||||
utils::MLTypeCallDispatcherRet<Status, BinaryImplDispatchTarget, SupportedElementTypes...> dispatcher(element_type);
|
||||
ORT_RETURN_IF_ERROR(dispatcher.Invoke(Stream(), input_tensors[0], input_tensors[1], output_tensor));
|
||||
|
||||
return Status::OK();
|
||||
return dispatcher.template InvokeRet<Status, BinaryImplDispatchTarget>(
|
||||
Stream(), input_tensors[0], input_tensors[1], output_tensor);
|
||||
}
|
||||
|
||||
utils::MLTypeCallDispatcherRet<Status, NoBroadcastBatchImplDispatchTarget, SupportedElementTypes...> dispatcher(
|
||||
element_type);
|
||||
ORT_RETURN_IF_ERROR(dispatcher.Invoke(Stream(), input_tensors, output_tensor));
|
||||
|
||||
return Status::OK();
|
||||
return dispatcher.template InvokeRet<Status, NoBroadcastBatchImplDispatchTarget>(
|
||||
Stream(), input_tensors, output_tensor);
|
||||
}
|
||||
|
||||
// compute output shape first, using broadcast rule
|
||||
|
|
@ -179,20 +175,13 @@ Status VariadicElementwiseOp<VariadicElementwiseOpTag, SupportedElementTypes...>
|
|||
|
||||
// special case for 2 inputs
|
||||
if (input_count == 2) {
|
||||
utils::MLTypeCallDispatcherRet<Status, BinaryImplDispatchTarget, SupportedElementTypes...> dispatcher(element_type);
|
||||
ORT_RETURN_IF_ERROR(dispatcher.Invoke(Stream(), input_tensors[0], input_tensors[1], output_tensor));
|
||||
|
||||
return Status::OK();
|
||||
return dispatcher.template InvokeRet<Status, BinaryImplDispatchTarget>(
|
||||
Stream(), input_tensors[0], input_tensors[1], output_tensor);
|
||||
}
|
||||
|
||||
// general case for more than 2 inputs
|
||||
{
|
||||
utils::MLTypeCallDispatcherRet<Status, GeneralImplDispatchTarget, SupportedElementTypes...> dispatcher(
|
||||
element_type);
|
||||
ORT_RETURN_IF_ERROR(dispatcher.Invoke(Stream(), input_tensors, output_tensor));
|
||||
}
|
||||
|
||||
return Status::OK();
|
||||
return dispatcher.template InvokeRet<Status, GeneralImplDispatchTarget>(
|
||||
Stream(), input_tensors, output_tensor);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@ Status Dropout::ComputeInternal(OpKernelContext* context) const {
|
|||
float ratio_data = default_ratio_;
|
||||
auto ratio = context->Input<Tensor>(1);
|
||||
if (ratio) {
|
||||
utils::MLTypeCallDispatcher<GetRatioDataImpl, float, MLFloat16, double> t_disp(ratio->GetElementType());
|
||||
t_disp.Invoke(ratio, ratio_data);
|
||||
utils::MLTypeCallDispatcher<float, MLFloat16, double> t_disp(ratio->GetElementType());
|
||||
t_disp.Invoke<GetRatioDataImpl>(ratio, ratio_data);
|
||||
}
|
||||
|
||||
const Tensor* training_mode = context->Input<Tensor>(2);
|
||||
|
|
@ -102,12 +102,16 @@ Status Dropout::ComputeInternal(OpKernelContext* context) const {
|
|||
|
||||
PhiloxGenerator& generator = generator_ ? *generator_ : PhiloxGenerator::Default();
|
||||
|
||||
using SupportedTypes = onnxruntime::TypeList<
|
||||
#if defined(CUDA_VERSION) && CUDA_VERSION >= 11000
|
||||
utils::MLTypeCallDispatcher<DropoutComputeImpl, float, MLFloat16, double, BFloat16> t_disp(X->GetElementType());
|
||||
float, MLFloat16, double, BFloat16
|
||||
#else
|
||||
utils::MLTypeCallDispatcher<DropoutComputeImpl, float, MLFloat16, double> t_disp(X->GetElementType());
|
||||
float, MLFloat16, double
|
||||
#endif
|
||||
t_disp.Invoke(GetDeviceProp(), Stream(), N, ratio_data, generator, *X, *Y, mask_data);
|
||||
>;
|
||||
|
||||
utils::MLTypeCallDispatcherFromTypeList<SupportedTypes> t_disp(X->GetElementType());
|
||||
t_disp.Invoke<DropoutComputeImpl>(GetDeviceProp(), Stream(), N, ratio_data, generator, *X, *Y, mask_data);
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -203,9 +203,9 @@ Status GatherND<TIndex>::ComputeInternal(OpKernelContext* context) const {
|
|||
|
||||
const void* const kernel_input_data = input_tensor->DataRaw();
|
||||
void* const kernel_output_data = output_tensor->MutableDataRaw();
|
||||
utils::MLTypeCallDispatcher<GatherNDComputeImpl, GATHER_ND_T_DATA_TYPES>
|
||||
t_disp(input_tensor->GetElementType());
|
||||
t_disp.Invoke(Stream(), num_slices, slice_size, kernel_input_data, kernel_output_data, input_slice_offsets_buffer.get());
|
||||
utils::MLTypeCallDispatcher<GATHER_ND_T_DATA_TYPES> t_disp(input_tensor->GetElementType());
|
||||
t_disp.Invoke<GatherNDComputeImpl>(
|
||||
Stream(), num_slices, slice_size, kernel_input_data, kernel_output_data, input_slice_offsets_buffer.get());
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,12 +163,13 @@ Status ScatterElements::ComputeInternal(OpKernelContext* context) const {
|
|||
fdm_indices_strides[i] = fast_divmod(static_cast<int>(indices_strides[i]));
|
||||
}
|
||||
|
||||
utils::MLTypeCallDispatcherRet<Status, ComputeImpl, float, MLFloat16, int16_t, int8_t, int32_t,
|
||||
int64_t, uint8_t, uint16_t, uint32_t, uint64_t, double, bool>
|
||||
utils::MLTypeCallDispatcher<float, MLFloat16, int16_t, int8_t, int32_t,
|
||||
int64_t, uint8_t, uint16_t, uint32_t, uint64_t, double, bool>
|
||||
t_disp(data_tensor->GetElementType());
|
||||
return t_disp.Invoke(Stream(), data_tensor, updates_tensor, indices_tensor, output_tensor, rank,
|
||||
input_data_size, buffer_input_dims, buffer_input_strides, indices_size,
|
||||
buffer_indices_dims, fdm_indices_strides, axis);
|
||||
return t_disp.InvokeRet<Status, ComputeImpl>(
|
||||
Stream(), data_tensor, updates_tensor, indices_tensor, output_tensor, rank,
|
||||
input_data_size, buffer_input_dims, buffer_input_strides, indices_size,
|
||||
buffer_indices_dims, fdm_indices_strides, axis);
|
||||
}
|
||||
|
||||
} // namespace cuda
|
||||
|
|
|
|||
|
|
@ -1283,10 +1283,11 @@ ORT_STATUS_PTR OrtGetValueImplSeqOfTensors(_In_ const OrtValue* p_ml_value, int
|
|||
auto& one_tensor = data.Get(index);
|
||||
|
||||
using namespace c_api_internal;
|
||||
utils::MLTypeCallDispatcherRet<OrtStatusPtr, CallGetValueImpl, float, double, MLFloat16, BFloat16, bool, std::string,
|
||||
int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t>
|
||||
utils::MLTypeCallDispatcher<float, double, MLFloat16, BFloat16, bool, std::string,
|
||||
int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t>
|
||||
t_disp(one_tensor.GetElementType());
|
||||
return t_disp.template InvokeWithUnsupportedPolicy<UnsupportedReturnFailStatus>(allocator, one_tensor, out);
|
||||
return t_disp.template InvokeRetWithUnsupportedPolicy<OrtStatusPtr, CallGetValueImpl, UnsupportedReturnFailStatus>(
|
||||
allocator, one_tensor, out);
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
|
@ -1489,11 +1490,12 @@ static ORT_STATUS_PTR OrtCreateValueImplSeqHelper(const OrtValue* const* in, siz
|
|||
}
|
||||
|
||||
OrtStatus* st{};
|
||||
utils::MLTypeCallDispatcherRet<OrtStatus*, CallCreateValueImpl, bool, float, double, std::string,
|
||||
MLFloat16, BFloat16, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t>
|
||||
utils::MLTypeCallDispatcher<bool, float, double, std::string,
|
||||
MLFloat16, BFloat16, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t>
|
||||
t_disp(one_tensor.GetElementType());
|
||||
|
||||
st = t_disp.InvokeWithUnsupportedPolicy<UnsupportedReturnFailStatus>(one_tensor, tensors[idx]);
|
||||
st = t_disp.InvokeRetWithUnsupportedPolicy<OrtStatus*, CallCreateValueImpl, UnsupportedReturnFailStatus>(
|
||||
one_tensor, tensors[idx]);
|
||||
|
||||
if (st) {
|
||||
return st;
|
||||
|
|
|
|||
|
|
@ -63,8 +63,8 @@ class CatImputerTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<CatImputerTransformerImpl, float, double, std::string> t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
utils::MLTypeCallDispatcher<float, double, std::string> t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke<CatImputerTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -155,10 +155,10 @@ struct ForecastingPivotTransformerImpl {
|
|||
|
||||
const auto elem_type = input_tensor->GetElementType();
|
||||
|
||||
utils::MLTypeCallDispatcher<CopyImputedColumnsImpl,
|
||||
int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t,
|
||||
float, double, bool, std::string> t_disp(elem_type);
|
||||
t_disp.Invoke(input_tensor, output_tensor_imputed, row_idx_record, input_matrix_size, num_output_rows);
|
||||
utils::MLTypeCallDispatcher<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t,
|
||||
float, double, bool, std::string>
|
||||
t_disp(elem_type);
|
||||
t_disp.Invoke<CopyImputedColumnsImpl>(input_tensor, output_tensor_imputed, row_idx_record, input_matrix_size, num_output_rows);
|
||||
}
|
||||
|
||||
// Prepare the horizon Output(uint32)
|
||||
|
|
@ -177,9 +177,8 @@ class ForecastingPivotTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<ForecastingPivotTransformerImpl, float, double>
|
||||
t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx, _num_pivot_columns);
|
||||
utils::MLTypeCallDispatcher<float, double> t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke<ForecastingPivotTransformerImpl>(ctx, _num_pivot_columns);
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,10 +65,10 @@ class FromStringTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<FromStringTransformerImpl, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
utils::MLTypeCallDispatcher<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
int64_t, uint64_t, float, double, bool, std::string>
|
||||
t_disp(result_type_);
|
||||
t_disp.Invoke(ctx);
|
||||
t_disp.Invoke<FromStringTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,10 +57,10 @@ class HashOneHotVectorizerTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<HashOneHotVectorizerTransformerImpl, int8_t, uint8_t, int16_t, uint16_t, int32_t,
|
||||
utils::MLTypeCallDispatcher<int8_t, uint8_t, int16_t, uint16_t, int32_t,
|
||||
uint32_t, int64_t, uint64_t, float, double, bool, std::string>
|
||||
t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
t_disp.Invoke<HashOneHotVectorizerTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@ class ImputationMarkerTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<ImputationMarkerTransformerImpl, float, double, std::string> t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
utils::MLTypeCallDispatcher<float, double, std::string> t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke<ImputationMarkerTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -48,10 +48,10 @@ class LabelEncoderTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<LabelEncoderTransformerImpl, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
utils::MLTypeCallDispatcher<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
int64_t, uint64_t, float, double, bool, std::string>
|
||||
t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
t_disp.Invoke<LabelEncoderTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -93,9 +93,8 @@ class LagLeadOperatorTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<LagLeadOperatorTransformerImpl, float, double>
|
||||
t_disp(ctx->Input<Tensor>(2)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
utils::MLTypeCallDispatcher<float, double> t_disp(ctx->Input<Tensor>(2)->GetElementType());
|
||||
t_disp.Invoke<LagLeadOperatorTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -71,10 +71,10 @@ class MaxAbsScalerTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<MaxAbsScalerTransformerImpl, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
utils::MLTypeCallDispatcher<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
int64_t, uint64_t, float, double>
|
||||
t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
t_disp.Invoke<MaxAbsScalerTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -63,8 +63,8 @@ class MeanImputerTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<MeanImputerTransformerImpl, float, double> t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
utils::MLTypeCallDispatcher<float, double> t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke<MeanImputerTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -77,8 +77,8 @@ class MedianImputerTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<MedianImputerTransformerImpl, float, double, std::string> t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
utils::MLTypeCallDispatcher<float, double, std::string> t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke<MedianImputerTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@ class MinMaxImputerTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<MinMaxImputerTransformerImpl, float, double, std::string> t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
utils::MLTypeCallDispatcher<float, double, std::string> t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke<MinMaxImputerTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -48,10 +48,10 @@ class MinMaxScalerTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<MinMaxScalerTransformerImpl, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
utils::MLTypeCallDispatcher<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
int64_t, uint64_t, float, double>
|
||||
t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
t_disp.Invoke<MinMaxScalerTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@ class MissingDummiesTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<MissingDummiesTransformerImpl, float, double, std::string> t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
utils::MLTypeCallDispatcher<float, double, std::string> t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke<MissingDummiesTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@ class ModeImputerTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<ModeImputerTransformerImpl, float, double, std::string> t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
utils::MLTypeCallDispatcher<float, double, std::string> t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke<ModeImputerTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -72,10 +72,10 @@ class NormalizeTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<NormalizeTransformerImpl, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
utils::MLTypeCallDispatcher<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
int64_t, uint64_t, float, double>
|
||||
t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
t_disp.Invoke<NormalizeTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -48,9 +48,10 @@ class NumericalizeTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<NumericalizeTransformerImpl, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
int64_t, uint64_t, float, double, std::string> t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
utils::MLTypeCallDispatcher<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
int64_t, uint64_t, float, double, std::string>
|
||||
t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke<NumericalizeTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -57,10 +57,10 @@ class OneHotEncoderTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<OneHotEncoderTransformerImpl, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
utils::MLTypeCallDispatcher<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
int64_t, uint64_t, float, double, bool, std::string>
|
||||
t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
t_disp.Invoke<OneHotEncoderTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -65,9 +65,8 @@ class PCATransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<PCATransformerImpl, float, double>
|
||||
t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
utils::MLTypeCallDispatcher<float, double> t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke<PCATransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -71,10 +71,10 @@ class RobustScalerTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<RobustScalerTransformerImpl, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
utils::MLTypeCallDispatcher<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
int64_t, uint64_t, float, double>
|
||||
t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
t_disp.Invoke<RobustScalerTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -91,9 +91,8 @@ class AnalyticalRollingWindowTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
|
||||
utils::MLTypeCallDispatcher<AnalyticalRollingWindowTransformerImpl, float, double> t_disp(ctx->Input<Tensor>(2)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
utils::MLTypeCallDispatcher<float, double> t_disp(ctx->Input<Tensor>(2)->GetElementType());
|
||||
t_disp.Invoke<AnalyticalRollingWindowTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
@ -104,9 +103,8 @@ class SimpleRollingWindowTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
|
||||
utils::MLTypeCallDispatcher<SimpleRollingWindowTransformerImpl, float, double> t_disp(ctx->Input<Tensor>(2)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
utils::MLTypeCallDispatcher<float, double> t_disp(ctx->Input<Tensor>(2)->GetElementType());
|
||||
t_disp.Invoke<SimpleRollingWindowTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -89,10 +89,10 @@ void ShortGrainDropperTransformerImpl(OpKernelContext* ctx) {
|
|||
|
||||
const auto elem_type = variadic_input_tensor->GetElementType();
|
||||
|
||||
utils::MLTypeCallDispatcher<CopyNonDroppedColumnsImpl,
|
||||
int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t,
|
||||
float, double, bool, std::string> t_disp(elem_type);
|
||||
t_disp.Invoke(variadic_input_tensor, output_after_drop_tensor, rows_to_drop, input_row_size);
|
||||
utils::MLTypeCallDispatcher<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t,
|
||||
float, double, bool, std::string>
|
||||
t_disp(elem_type);
|
||||
t_disp.Invoke<CopyNonDroppedColumnsImpl>(variadic_input_tensor, output_after_drop_tensor, rows_to_drop, input_row_size);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -48,10 +48,10 @@ class StandardScaleWrapperTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<StandardScaleWrapperTransformerImpl, int8_t, uint8_t, int16_t, uint16_t, int32_t,
|
||||
utils::MLTypeCallDispatcher<int8_t, uint8_t, int16_t, uint16_t, int32_t,
|
||||
uint32_t, int64_t, uint64_t, float, double>
|
||||
t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
t_disp.Invoke<StandardScaleWrapperTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -48,10 +48,10 @@ class StringTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<StringTransformerImpl, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
utils::MLTypeCallDispatcher<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
int64_t, uint64_t, float, double, bool, std::string>
|
||||
t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
t_disp.Invoke<StringTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -265,10 +265,10 @@ struct TimeSeriesImputerTransformerImpl {
|
|||
|
||||
const auto elem_type = variadic_input_tensor->GetElementType();
|
||||
|
||||
utils::MLTypeCallDispatcher<GenerateImputedColumnsImpl,
|
||||
int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t,
|
||||
float, double, bool, std::string> t_disp(elem_type);
|
||||
t_disp.Invoke(variadic_input_tensor, output_after_impute_tensor, is_row_imputed, input_row_size);
|
||||
utils::MLTypeCallDispatcher<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t,
|
||||
float, double, bool, std::string>
|
||||
t_disp(elem_type);
|
||||
t_disp.Invoke<GenerateImputedColumnsImpl>(variadic_input_tensor, output_after_impute_tensor, is_row_imputed, input_row_size);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,9 +65,8 @@ class TruncatedSVDTransformer final : public OpKernel {
|
|||
}
|
||||
|
||||
Status Compute(OpKernelContext* ctx) const override {
|
||||
utils::MLTypeCallDispatcher<TruncatedSVDTransformerImpl, float, double>
|
||||
t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke(ctx);
|
||||
utils::MLTypeCallDispatcher<float, double> t_disp(ctx->Input<Tensor>(1)->GetElementType());
|
||||
t_disp.Invoke<TruncatedSVDTransformerImpl>(ctx);
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -74,8 +74,8 @@ Status GatherNDGrad::Compute(OpKernelContext* context) const {
|
|||
}
|
||||
|
||||
ORT_RETURN_IF_NOT(nullptr == p.input_str_base, "nullptr != p.input_str_base");
|
||||
utils::MLTypeCallDispatcher<GatherNDGradComputeImpl, float, double> t_disp(update_tensor->GetElementType());
|
||||
t_disp.Invoke(p, update_tensor);
|
||||
utils::MLTypeCallDispatcher<float, double> t_disp(update_tensor->GetElementType());
|
||||
t_disp.Invoke<GatherNDGradComputeImpl>(p, update_tensor);
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,11 +76,8 @@ Status BiasGeluGrad_dX<GeluComputationMode>::ComputeInternal(OpKernelContext* co
|
|||
|
||||
const auto input_size = input_shape.Size(), bias_size = bias_shape.Size();
|
||||
|
||||
utils::MLTypeCallDispatcher<
|
||||
KernelLaunchDispatcher,
|
||||
ALL_IEEE_FLOAT_DATA_TYPES>
|
||||
dispatcher{X->GetElementType()};
|
||||
dispatcher.Invoke(Stream(), input_size, bias_size, *dY, *X, *B, *dX);
|
||||
utils::MLTypeCallDispatcher<ALL_IEEE_FLOAT_DATA_TYPES> dispatcher{X->GetElementType()};
|
||||
dispatcher.Invoke<KernelLaunchDispatcher>(Stream(), input_size, bias_size, *dY, *X, *B, *dX);
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ Status Scale<T>::ComputeInternal(OpKernelContext* context) const {
|
|||
typedef typename ToCudaType<T>::MappedType CudaT;
|
||||
float scale_value;
|
||||
auto scale_tensor = context->Input<Tensor>(1);
|
||||
utils::MLTypeCallDispatcher<GetScaleValueImpl, float, double, MLFloat16, int64_t, int32_t> t_disp(scale_tensor->GetElementType());
|
||||
t_disp.Invoke(scale_tensor, scale_value);
|
||||
utils::MLTypeCallDispatcher<float, double, MLFloat16, int64_t, int32_t> t_disp(scale_tensor->GetElementType());
|
||||
t_disp.Invoke<GetScaleValueImpl>(scale_tensor, scale_value);
|
||||
|
||||
if (scale_down_) {
|
||||
scale_value = 1.0f / scale_value;
|
||||
|
|
|
|||
|
|
@ -73,14 +73,14 @@ Status DropoutGrad::ComputeInternal(OpKernelContext* context) const {
|
|||
float ratio_data = default_ratio_;
|
||||
auto ratio = context->Input<Tensor>(2);
|
||||
if (ratio) {
|
||||
utils::MLTypeCallDispatcher<GetRatioDataImpl, ALL_IEEE_FLOAT_DATA_TYPES> t_disp(ratio->GetElementType());
|
||||
t_disp.Invoke(ratio, ratio_data);
|
||||
utils::MLTypeCallDispatcher<ALL_IEEE_FLOAT_DATA_TYPES> t_disp(ratio->GetElementType());
|
||||
t_disp.Invoke<GetRatioDataImpl>(ratio, ratio_data);
|
||||
}
|
||||
|
||||
auto dX = context->Output(0, shape);
|
||||
|
||||
utils::MLTypeCallDispatcher<DropoutGradComputeImpl, ALL_IEEE_FLOAT_DATA_TYPES> t_disp(dY->GetElementType());
|
||||
t_disp.Invoke(Stream(), N, *dY, mask_data, ratio_data, *dX);
|
||||
utils::MLTypeCallDispatcher<ALL_IEEE_FLOAT_DATA_TYPES> t_disp(dY->GetElementType());
|
||||
t_disp.Invoke<DropoutGradComputeImpl>(Stream(), N, *dY, mask_data, ratio_data, *dX);
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
|
@ -165,8 +165,8 @@ Status BiasDropout::ComputeInternal(OpKernelContext* context) const {
|
|||
float ratio_data = default_ratio_;
|
||||
auto ratio = context->Input<Tensor>(3);
|
||||
if (ratio) {
|
||||
utils::MLTypeCallDispatcher<GetRatioDataImpl, ALL_IEEE_FLOAT_DATA_TYPES> t_disp(ratio->GetElementType());
|
||||
t_disp.Invoke(ratio, ratio_data);
|
||||
utils::MLTypeCallDispatcher<ALL_IEEE_FLOAT_DATA_TYPES> t_disp(ratio->GetElementType());
|
||||
t_disp.Invoke<GetRatioDataImpl>(ratio, ratio_data);
|
||||
}
|
||||
|
||||
//Check for inference mode.
|
||||
|
|
@ -186,8 +186,9 @@ Status BiasDropout::ComputeInternal(OpKernelContext* context) const {
|
|||
const fast_divmod fdm_dim(gsl::narrow_cast<int>(dim));
|
||||
PhiloxGenerator& generator = generator_ ? *generator_ : PhiloxGenerator::Default();
|
||||
|
||||
utils::MLTypeCallDispatcherRet<Status, BiasDropoutComputeImpl, ALL_IEEE_FLOAT_DATA_TYPES> t_disp(X->GetElementType());
|
||||
return t_disp.Invoke(GetDeviceProp(), Stream(), N, fdm_dim, ratio_data, generator, *X, *bias, residual, *Y, mask_data);
|
||||
utils::MLTypeCallDispatcher<ALL_IEEE_FLOAT_DATA_TYPES> t_disp(X->GetElementType());
|
||||
return t_disp.InvokeRet<Status, BiasDropoutComputeImpl>(
|
||||
GetDeviceProp(), Stream(), N, fdm_dim, ratio_data, generator, *X, *bias, residual, *Y, mask_data);
|
||||
}
|
||||
|
||||
} // namespace cuda
|
||||
|
|
|
|||
|
|
@ -129,11 +129,11 @@ Status GatherElementsGrad::ComputeInternal(OpKernelContext* context) const {
|
|||
fdm_indices_strides[i] = fast_divmod(static_cast<int>(indices_strides[i]));
|
||||
}
|
||||
|
||||
utils::MLTypeCallDispatcherRet<Status, ComputeImpl, MLFloat16, float, double>
|
||||
t_disp(dY->GetElementType());
|
||||
return t_disp.Invoke(Stream(), dY, indices_tensor, dX, rank,
|
||||
buffer_output_dims, buffer_input_strides, indices_size,
|
||||
buffer_indices_dims, fdm_indices_strides, axis);
|
||||
utils::MLTypeCallDispatcher<MLFloat16, float, double> t_disp(dY->GetElementType());
|
||||
return t_disp.InvokeRet<Status, ComputeImpl>(
|
||||
Stream(), dY, indices_tensor, dX, rank,
|
||||
buffer_output_dims, buffer_input_strides, indices_size,
|
||||
buffer_indices_dims, fdm_indices_strides, axis);
|
||||
}
|
||||
|
||||
} // namespace cuda
|
||||
|
|
|
|||
|
|
@ -96,9 +96,9 @@ Status GatherNDGrad<TIndex>::ComputeInternal(OpKernelContext* context) const {
|
|||
|
||||
const void* const kernel_input_data = update_tensor->DataRaw();
|
||||
void* const kernel_output_data = output_tensor->MutableDataRaw();
|
||||
utils::MLTypeCallDispatcher<GatherNDGradComputeImpl, ALL_IEEE_FLOAT_DATA_TYPES>
|
||||
t_disp(update_tensor->GetElementType());
|
||||
t_disp.Invoke(Stream(), num_slices, slice_size, kernel_input_data, kernel_output_data, input_slice_offsets_buffer.get());
|
||||
utils::MLTypeCallDispatcher<ALL_IEEE_FLOAT_DATA_TYPES> t_disp(update_tensor->GetElementType());
|
||||
t_disp.Invoke<GatherNDGradComputeImpl>(
|
||||
Stream(), num_slices, slice_size, kernel_input_data, kernel_output_data, input_slice_offsets_buffer.get());
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue