Files
2026-07-13 12:40:42 +08:00

627 lines
17 KiB
C++

// Copyright (c) 2022 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
#if !defined(_WIN32)
#include <memory>
#include <tuple>
#include <type_traits>
#include <typeindex>
#include <typeinfo>
#include <vector>
#include "paddle/common/exception.h"
#include "paddle/phi/capi/include/c_device_context.h"
#include "paddle/phi/capi/include/c_infer_meta_context.h"
#include "paddle/phi/capi/include/c_int_array.h"
#include "paddle/phi/capi/include/c_kernel_context.h"
#include "paddle/phi/capi/include/c_kernel_factory.h"
#include "paddle/phi/capi/include/c_kernel_registry.h"
#include "paddle/phi/capi/include/c_meta_tensor.h"
#include "paddle/phi/capi/include/c_place.h"
#include "paddle/phi/capi/include/c_scalar.h"
#include "paddle/phi/capi/include/c_tensor.h"
#include "paddle/phi/capi/include/data_type.h"
#include "paddle/utils/optional.h"
#define PD_CHECK_STATUS(status) PD_CHECK(status == C_SUCCESS)
namespace phi {
namespace capi {
using LegacyLoD = std::vector<std::vector<size_t>>;
using LoD = LegacyLoD;
template <typename T>
static inline PD_List PDListFromVector(std::vector<T>* vec) {
PD_List list;
list.data = reinterpret_cast<void*>(vec->data());
list.size = vec->size();
return list;
}
template <typename T>
static inline std::vector<T> PDListToVector(PD_List list) {
return std::vector<T>(static_cast<T*>(list.data),
static_cast<T*>(list.data) + list.size);
}
inline std::vector<int64_t> PD_TensorGetDims(PD_Tensor* tensor,
PD_Status* status) {
int64_t ndims = PD_TensorGetNumDims(tensor, status);
if (ndims > 0) {
std::vector<int64_t> shape(ndims);
for (int64_t i = 0; i < ndims; ++i) {
shape[i] = PD_TensorGetDim(tensor, i, status);
}
return shape;
}
return std::vector<int64_t>();
}
inline std::vector<int64_t> PD_TensorGetStrides(PD_Tensor* tensor,
PD_Status* status) {
int64_t nstrides = PD_TensorGetNumStrides(tensor, status);
if (nstrides > 0) {
std::vector<int64_t> shape(nstrides);
for (int64_t i = 0; i < nstrides; ++i) {
shape[i] = PD_TensorGetStride(tensor, i, status);
}
return shape;
}
return std::vector<int64_t>();
}
inline std::vector<int64_t> PD_MetaTensorGetDims(PD_MetaTensor* tensor,
PD_Status* status) {
int64_t ndims = PD_MetaTensorGetNumDims(tensor, status);
if (ndims > 0) {
std::vector<int64_t> shape(ndims);
for (int64_t i = 0; i < ndims; ++i) {
shape[i] = PD_MetaTensorGetDim(tensor, i, status);
}
return shape;
}
return std::vector<int64_t>();
}
inline std::vector<int64_t> PD_MetaTensorGetStrides(PD_MetaTensor* tensor,
PD_Status* status) {
int64_t nstrides = PD_MetaTensorGetNumStrides(tensor, status);
if (nstrides > 0) {
std::vector<int64_t> shape(nstrides);
for (int64_t i = 0; i < nstrides; ++i) {
shape[i] = PD_MetaTensorGetStride(tensor, i, status);
}
return shape;
}
return std::vector<int64_t>();
}
template <typename T>
class WrapperBase {
public:
explicit WrapperBase(T* ptr, bool own = false) : data_(ptr), own_(own) {}
inline T* raw_data() const { return data_; }
inline bool own_data() const { return own_; }
inline void reset(const T* ptr) { data_ = ptr; }
private:
T* data_;
bool own_;
};
class DenseTensor : public WrapperBase<PD_Tensor> {
public:
DenseTensor() : WrapperBase(PD_NewTensor(), true) {}
explicit DenseTensor(PD_Tensor* tensor) : WrapperBase(tensor) {}
~DenseTensor() {
if (own_data()) {
PD_DeleteTensor(raw_data());
}
}
bool valid() const {
C_Status status;
auto ret = PD_TensorIsValid(raw_data(), &status);
PD_CHECK_STATUS(status);
return ret;
}
bool initialized() const {
C_Status status;
auto ret = PD_TensorIsInitialized(raw_data(), &status);
PD_CHECK_STATUS(status);
return ret;
}
void* Holder() const {
C_Status status;
auto holder = PD_TensorGetHolder(raw_data(), &status);
PD_CHECK_STATUS(status);
return holder;
}
size_t offset() const {
C_Status status;
auto offset = PD_TensorGetOffset(raw_data(), &status);
PD_CHECK_STATUS(status);
return offset;
}
std::vector<int64_t> dims() const {
C_Status status;
auto dimension = PD_TensorGetDims(raw_data(), &status);
PD_CHECK_STATUS(status);
return dimension;
}
std::vector<int64_t> strides() const {
C_Status status;
auto strides = PD_TensorGetStrides(raw_data(), &status);
PD_CHECK_STATUS(status);
return strides;
}
PD_DataType dtype() const {
C_Status status;
auto data_type = PD_TensorGetPDDataType(raw_data(), &status);
PD_CHECK_STATUS(status);
return data_type;
}
PD_DataLayout layout() const {
C_Status status;
auto data_layout = PD_TensorGetDataLayout(raw_data(), &status);
PD_CHECK_STATUS(status);
return data_layout;
}
int64_t numel() const {
C_Status status;
auto element_count = PD_TensorGetElementCount(raw_data(), &status);
PD_CHECK_STATUS(status);
return element_count;
}
int64_t memory_size() const {
C_Status status;
auto byte_size = PD_TensorGetByteSize(raw_data(), &status);
PD_CHECK_STATUS(status);
return byte_size;
}
LegacyLoD lod() const {
PD_List data, offset;
C_Status status;
PD_TensorGetLoD(raw_data(), &data, &offset, &status);
PD_CHECK_STATUS(status);
LegacyLoD lod_;
auto ptr = static_cast<size_t*>(data.data);
auto offset_ptr = static_cast<size_t*>(offset.data);
for (size_t i = 0; i < offset.size - 1; ++i) {
lod_.emplace_back(ptr + offset_ptr[i], ptr + offset_ptr[i + 1]);
}
delete[] ptr;
delete[] offset_ptr;
return lod_;
}
void ResetLoD(const LegacyLoD& lod) {
std::vector<size_t> data, offset;
offset.push_back(0);
for (const auto& item : lod) {
data.insert(data.cend(), item.cbegin(), item.cend());
offset.push_back(item.size());
}
PD_List data_list, offset_list;
data_list = PDListFromVector(&data);
offset_list = PDListFromVector(&offset);
C_Status status;
PD_TensorResetLoD(raw_data(), data_list, offset_list, &status);
PD_CHECK_STATUS(status);
}
void Resize(const std::vector<int64_t>& dims) {
C_Status status;
PD_TensorSetDims(raw_data(), dims.size(), dims.data(), &status);
PD_CHECK_STATUS(status);
}
void set_offset(const int64_t& offset) {
C_Status status;
PD_TensorSetOffset(raw_data(), offset, &status);
PD_CHECK_STATUS(status);
}
void set_strides(const std::vector<int64_t>& strides) {
C_Status status;
PD_TensorSetStrides(raw_data(), strides.size(), strides.data(), &status);
PD_CHECK_STATUS(status);
}
void set_dtype(PD_DataType data_type) {
C_Status status;
PD_TensorSetDataType(raw_data(), data_type, &status);
PD_CHECK_STATUS(status);
}
void set_layout(PD_DataLayout data_layout) {
C_Status status;
PD_TensorSetDataLayout(raw_data(), data_layout, &status);
PD_CHECK_STATUS(status);
}
template <typename T>
T* data() const {
C_Status status;
auto ptr = PD_TensorGetDataPointer(raw_data(), &status);
PD_CHECK_STATUS(status);
return static_cast<T*>(ptr);
}
DenseTensor& ShareDataWith(const DenseTensor& src) {
C_Status status;
PD_TensorShareDataWith(raw_data(), src.raw_data(), &status);
PD_CHECK_STATUS(status);
return *this;
}
void share_lod(const DenseTensor& src) {
C_Status status;
PD_TensorShareLoDWith(raw_data(), src.raw_data(), &status);
PD_CHECK_STATUS(status);
}
};
class DeviceContext : public WrapperBase<PD_DeviceContext> {
public:
explicit DeviceContext(PD_DeviceContext* context)
: WrapperBase<PD_DeviceContext>(context) {}
void* stream() const {
C_Status status;
auto stream_ = PD_DeviceContextGetStream(raw_data(), &status);
PD_CHECK_STATUS(status);
return stream_;
}
void* Alloc(DenseTensor* tensor,
PD_DataType dtype,
int64_t requested_size = 0) const {
C_Status status;
auto ptr = PD_DeviceContextAllocateTensor(
raw_data(), tensor->raw_data(), requested_size, dtype, &status);
PD_CHECK_STATUS(status);
return static_cast<void*>(ptr);
}
template <typename T>
T* Alloc(DenseTensor* tensor, int64_t requested_size = 0) const {
C_Status status;
auto ptr =
PD_DeviceContextAllocateTensor(raw_data(),
tensor->raw_data(),
requested_size,
phi::capi::CppTypeToPDType<T>::Type(),
&status);
PD_CHECK_STATUS(status);
return static_cast<T*>(ptr);
}
void* HostAlloc(DenseTensor* tensor,
PD_DataType dtype,
int64_t requested_size = 0) const {
C_Status status;
auto ptr = PD_DeviceContextAllocateTensor(
nullptr, tensor->raw_data(), requested_size, dtype, &status);
PD_CHECK_STATUS(status);
return static_cast<void*>(ptr);
}
template <typename T>
T* HostAlloc(DenseTensor* tensor, int64_t requested_size = 0) const {
C_Status status;
auto ptr =
PD_DeviceContextAllocateTensor(nullptr,
tensor->raw_data(),
requested_size,
phi::capi::CppTypeToPDType<T>::Type(),
&status);
PD_CHECK_STATUS(status);
return static_cast<T*>(ptr);
}
uint64_t seed() const {
C_Status status;
auto seed_val = PD_DeviceContextGetSeed(raw_data(), &status);
PD_CHECK_STATUS(status);
return seed_val;
}
void seed(uint64_t seed_val) const {
C_Status status;
PD_DeviceContextSetSeed(raw_data(), seed_val, &status);
PD_CHECK_STATUS(status);
}
uint64_t random() const {
C_Status status;
auto rand_val = PD_DeviceContextGetRandom(raw_data(), &status);
PD_CHECK_STATUS(status);
return rand_val;
}
};
class Scalar : public WrapperBase<PD_Scalar> {
public:
explicit Scalar(PD_Scalar* scalar) : WrapperBase<PD_Scalar>(scalar) {}
PD_DataType dtype() const { return PD_ScalarGetDataType(raw_data()); }
template <typename T>
inline T to() const;
};
template <>
inline bool Scalar::to<bool>() const {
return PD_ScalarGetBoolData(raw_data());
}
template <>
inline float Scalar::to<float>() const {
return PD_ScalarGetFloat32Data(raw_data());
}
template <>
inline double Scalar::to<double>() const {
return PD_ScalarGetFloat64Data(raw_data());
}
template <>
inline uint8_t Scalar::to<uint8_t>() const {
return PD_ScalarGetUInt8Data(raw_data());
}
template <>
inline uint16_t Scalar::to<uint16_t>() const {
return PD_ScalarGetUInt16Data(raw_data());
}
template <>
inline uint32_t Scalar::to<uint32_t>() const {
return PD_ScalarGetUInt32Data(raw_data());
}
template <>
inline uint64_t Scalar::to<uint64_t>() const {
return PD_ScalarGetUInt64Data(raw_data());
}
template <>
inline int8_t Scalar::to<int8_t>() const {
return PD_ScalarGetInt8Data(raw_data());
}
template <>
inline int16_t Scalar::to<int16_t>() const {
return PD_ScalarGetInt16Data(raw_data());
}
template <>
inline int32_t Scalar::to<int32_t>() const {
return PD_ScalarGetInt32Data(raw_data());
}
template <>
inline int64_t Scalar::to<int64_t>() const {
return PD_ScalarGetInt64Data(raw_data());
}
class IntArray : WrapperBase<PD_IntArray> {
public:
explicit IntArray(PD_IntArray* int_array)
: WrapperBase<PD_IntArray>(int_array) {}
size_t size() const { return PD_IntArrayGetElementCount(raw_data()); }
std::vector<int64_t> GetData() const {
auto list = PD_IntArrayGetDataPointer(raw_data());
auto data = reinterpret_cast<int64_t*>(list.data);
std::vector<int64_t> ret(data, data + list.size);
return ret;
}
};
class Place : WrapperBase<PD_Place> {
public:
explicit Place(PD_Place* place) : WrapperBase<PD_Place>(place) {}
bool is_host() { return PD_PlaceIsHost(raw_data()); }
int8_t GetDeviceID() { return PD_PlaceGetDeviceId(raw_data()); }
};
class TensorArgDef : WrapperBase<PD_TensorArgDef> {
public:
explicit TensorArgDef(PD_TensorArgDef* tensor_arg_def)
: WrapperBase<PD_TensorArgDef>(tensor_arg_def) {}
// TensorArgDef& SetBackend() {
// return *this;
// }
TensorArgDef& SetDataLayout(PD_DataLayout in_layout) {
C_Status status;
PD_TensorArgDefSetDataLayout(raw_data(), in_layout, &status);
PD_CHECK_STATUS(status);
return *this;
}
TensorArgDef& SetDataType(PD_DataType in_dtype) {
C_Status status;
PD_TensorArgDefSetDataType(raw_data(), in_dtype, &status);
PD_CHECK_STATUS(status);
return *this;
}
};
class KernelArgsDef : WrapperBase<PD_KernelArgsDef> {
public:
explicit KernelArgsDef(PD_KernelArgsDef* kernel_args_def)
: WrapperBase<PD_KernelArgsDef>(kernel_args_def) {}
std::vector<TensorArgDef> input_defs() {
C_Status status;
auto list = PD_KernelArgsDefGetInputArgDefs(raw_data(), &status);
PD_CHECK_STATUS(status);
auto ptr = reinterpret_cast<PD_TensorArgDef**>(list.data);
std::vector<TensorArgDef> ret;
for (size_t i = 0; i < list.size; ++i) {
ret.emplace_back(ptr[i]);
}
PD_DeletePointerList(list);
return ret;
}
std::vector<TensorArgDef> output_defs() {
C_Status status;
auto list = PD_KernelArgsDefGetOutputArgDefs(raw_data(), &status);
PD_CHECK_STATUS(status);
auto ptr = reinterpret_cast<PD_TensorArgDef**>(list.data);
std::vector<TensorArgDef> ret;
for (size_t i = 0; i < list.size; ++i) {
ret.emplace_back(ptr[i]);
}
PD_DeletePointerList(list);
return ret;
}
};
class KernelKey : WrapperBase<PD_KernelKey> {
public:
explicit KernelKey(PD_KernelKey* kernel_key)
: WrapperBase<PD_KernelKey>(kernel_key) {}
PD_DataLayout layout() const {
PD_Status status;
auto layout_ = PD_KernelKeyGetLayout(raw_data(), &status);
PD_CHECK_STATUS(status);
return layout_;
}
PD_DataType dtype() const {
PD_Status status;
auto dtype_ = PD_KernelKeyGetDataType(raw_data(), &status);
PD_CHECK_STATUS(status);
return dtype_;
}
};
class Kernel : WrapperBase<PD_Kernel> {
public:
explicit Kernel(PD_Kernel* kernel) : WrapperBase<PD_Kernel>(kernel) {}
KernelArgsDef args_def() const {
C_Status status;
auto ptr = PD_KernelGetArgsDef(raw_data(), &status);
PD_CHECK_STATUS(status);
return KernelArgsDef(ptr);
}
TensorArgDef InputAt(size_t idx) { return args_def().input_defs()[idx]; }
TensorArgDef OutputAt(size_t idx) { return args_def().output_defs()[idx]; }
};
class MetaTensor : WrapperBase<PD_MetaTensor> {
public:
explicit MetaTensor(PD_MetaTensor* meta_tensor)
: WrapperBase<PD_MetaTensor>(meta_tensor) {}
std::vector<int64_t> dims() const {
C_Status status;
auto dimension = PD_MetaTensorGetDims(raw_data(), &status);
PD_CHECK_STATUS(status);
return dimension;
}
std::vector<int64_t> strides() const {
C_Status status;
auto strides = PD_MetaTensorGetStrides(raw_data(), &status);
PD_CHECK_STATUS(status);
return strides;
}
PD_DataType dtype() const {
C_Status status;
auto data_type = PD_MetaTensorGetPDDataType(raw_data(), &status);
PD_CHECK_STATUS(status);
return data_type;
}
PD_DataLayout layout() const {
C_Status status;
auto data_layout = PD_MetaTensorGetDataLayout(raw_data(), &status);
PD_CHECK_STATUS(status);
return data_layout;
}
int64_t numel() const {
C_Status status;
auto element_count = PD_MetaTensorGetElementCount(raw_data(), &status);
PD_CHECK_STATUS(status);
return element_count;
}
void set_dims(const std::vector<int64_t>& dims) {
C_Status status;
PD_MetaTensorSetDims(raw_data(), dims.size(), dims.data(), &status);
PD_CHECK_STATUS(status);
}
void set_strides(const std::vector<int64_t>& strides) {
C_Status status;
PD_MetaTensorSetStrides(
raw_data(), strides.size(), strides.data(), &status);
PD_CHECK_STATUS(status);
}
void set_dtype(PD_DataType data_type) {
C_Status status;
PD_MetaTensorSetDataType(raw_data(), data_type, &status);
PD_CHECK_STATUS(status);
}
void set_layout(PD_DataLayout data_layout) {
C_Status status;
PD_MetaTensorSetDataLayout(raw_data(), data_layout, &status);
PD_CHECK_STATUS(status);
}
};
} // namespace capi
} // namespace phi
#endif