mirror of
https://github.com/zebrajr/pytorch.git
synced 2025-12-06 12:20:52 +01:00
Improve TypeMeta (#11502)
Summary: Pull Request resolved: https://github.com/pytorch/pytorch/pull/11502 TypeMeta now is only a pointer to a TypeMetaData structure, of which there is exactly one global instance per type. This reduces the size of everything storing a TypeMeta (Tensor, Blob, ...) and potentially improves performance. Also, this diff gets rid of the type name registry in favor of static strings. Experiments (summary: 1-3% perf gain) - Service Lab: https://our.intern.facebook.com/intern/servicelab/30712497/ -> No significant results found. - Mobile Lab c10bench.json: https://our.intern.facebook.com/intern/fblearner/details/75984908/ -> 1-3% perf gain - Mobile Lab c10bench default: https://our.intern.facebook.com/intern/fblearner/details/75984999/ -> 2-3% perf gain - adindexer canary: https://our.intern.facebook.com/intern/ads/canary/413002142824203076 -> no significant changes (benchmark too noisy) - adfinder canary: https://our.intern.facebook.com/intern/ads/canary/413002166737860362 -> no significant changes (benchmark too noisy) Reviewed By: dzhulgakov Differential Revision: D9763422 fbshipit-source-id: fc08937f114af5ff9f3ddbe7c7e396942868cdf5
This commit is contained in:
parent
ac9bb8ecef
commit
6f664d3917
|
|
@ -69,8 +69,9 @@ enum class ScalarType : int8_t {
|
|||
};
|
||||
|
||||
static inline DataType scalarTypeToDataType(ScalarType scalar_type) {
|
||||
#define DEFINE_CASE(ctype,name,_) \
|
||||
case ScalarType:: name : return caffe2::TypeMeta::Id<ctype>();
|
||||
#define DEFINE_CASE(ctype, name, _) \
|
||||
case ScalarType::name: \
|
||||
return caffe2::TypeIdentifier::Get<ctype>();
|
||||
|
||||
switch(scalar_type) {
|
||||
AT_FORALL_SCALAR_TYPES_WITH_COMPLEX(DEFINE_CASE)
|
||||
|
|
@ -93,9 +94,9 @@ static inline caffe2::TypeMeta scalarTypeToTypeMeta(ScalarType scalar_type) {
|
|||
}
|
||||
|
||||
static inline ScalarType dataTypeToScalarType(DataType dtype) {
|
||||
#define DEFINE_IF(ctype,name,_) \
|
||||
if (dtype == caffe2::TypeMeta::Id<ctype>()) { \
|
||||
return ScalarType:: name; \
|
||||
#define DEFINE_IF(ctype, name, _) \
|
||||
if (dtype == caffe2::TypeIdentifier::Get<ctype>()) { \
|
||||
return ScalarType::name; \
|
||||
}
|
||||
AT_FORALL_SCALAR_TYPES_WITH_COMPLEX(DEFINE_IF)
|
||||
#undef DEFINE_IF
|
||||
|
|
|
|||
|
|
@ -10,28 +10,24 @@
|
|||
using std::string;
|
||||
|
||||
namespace caffe2 {
|
||||
|
||||
std::unordered_map<TypeIdentifier, string>& gTypeNames() {
|
||||
static std::unordered_map<TypeIdentifier, string> g_type_names;
|
||||
return g_type_names;
|
||||
}
|
||||
|
||||
std::unordered_set<string>& gRegisteredTypeNames() {
|
||||
static std::unordered_set<string> g_registered_type_names;
|
||||
return g_registered_type_names;
|
||||
}
|
||||
|
||||
std::mutex& gTypeRegistrationMutex() {
|
||||
static std::mutex g_type_registration_mutex;
|
||||
return g_type_registration_mutex;
|
||||
}
|
||||
|
||||
void TypeMeta::_ThrowRuntimeTypeLogicError(const std::string& msg) {
|
||||
namespace detail {
|
||||
C10_EXPORT void _ThrowRuntimeTypeLogicError(const string& msg) {
|
||||
// In earlier versions it used to be std::abort() but it's a bit hard-core
|
||||
// for a library
|
||||
AT_ERROR(msg);
|
||||
}
|
||||
|
||||
const TypeMetaData _typeMetaDataInstance_uninitialized_ = detail::TypeMetaData(0, nullptr, nullptr, nullptr, TypeIdentifier::uninitialized(), "nullptr (uninitialized)");
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// TODO Inlineable on non-MSVC like other preallocated ids?
|
||||
template<>
|
||||
C10_EXPORT const detail::TypeMetaData* TypeMeta::_typeMetaDataInstance<detail::_Uninitialized>() noexcept {
|
||||
return &detail::_typeMetaDataInstance_uninitialized_;
|
||||
}
|
||||
|
||||
|
||||
TypeIdentifier TypeIdentifier::createTypeId() {
|
||||
static std::atomic<TypeIdentifier::underlying_type> counter(
|
||||
TypeMeta::Id<_CaffeHighestPreallocatedTypeId>().underlyingId());
|
||||
|
|
@ -44,46 +40,39 @@ TypeIdentifier TypeIdentifier::createTypeId() {
|
|||
return TypeIdentifier(new_value);
|
||||
}
|
||||
|
||||
CAFFE_DEFINE_KNOWN_TYPE(float);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(int);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(std::string);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(bool);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(uint8_t);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(int8_t);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(uint16_t);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(int16_t);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(int64_t);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(double);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(char);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(at::Half);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(std::unique_ptr<std::mutex>);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(std::unique_ptr<std::atomic<bool>>);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(std::vector<int32_t>);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(std::vector<int64_t>);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(std::vector<unsigned long>);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(bool*);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(char*);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(int*);
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(0, uint8_t)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(1, int8_t)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(2, int16_t)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(3, int)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(4, int64_t)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(5, at::Half)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(6, float)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(7, double)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(8, at::ComplexHalf)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(9, std::complex<float>)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(10, std::complex<double>)
|
||||
// 11 = undefined type id
|
||||
// 12 = Tensor (defined in tensor.cc)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(13, std::string)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(14, bool)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(15, uint16_t)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(16, char)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(17, std::unique_ptr<std::mutex>)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(18, std::unique_ptr<std::atomic<bool>>)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(19, std::vector<int32_t>)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(20, std::vector<int64_t>)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(21, std::vector<unsigned long>)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(22, bool*)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(23, char*)
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(24, int*)
|
||||
|
||||
// see typeid.h for details.
|
||||
#if defined(_MSC_VER) || defined(__APPLE__) || \
|
||||
(defined(__ANDROID__) && !defined(__LP64__))
|
||||
CAFFE_DEFINE_KNOWN_TYPE(long);
|
||||
CAFFE_DEFINE_KNOWN_TYPE(std::vector<long>);
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(25, long);
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(26, std::vector<long>);
|
||||
#endif
|
||||
|
||||
CAFFE_DEFINE_KNOWN_TYPE(_CaffeHighestPreallocatedTypeId);
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(27, _CaffeHighestPreallocatedTypeId)
|
||||
|
||||
namespace {
|
||||
// This single registerer exists solely for us to be able to name a TypeMeta
|
||||
// for unintializied blob. You should not use this struct yourself - it is
|
||||
// intended to be only instantiated once here.
|
||||
struct UninitializedTypeNameRegisterer {
|
||||
UninitializedTypeNameRegisterer() {
|
||||
gTypeNames()[TypeIdentifier::uninitialized()] = "nullptr (uninitialized)";
|
||||
}
|
||||
};
|
||||
static UninitializedTypeNameRegisterer g_uninitialized_type_name_registerer;
|
||||
|
||||
} // namespace
|
||||
} // namespace caffe2
|
||||
|
|
|
|||
|
|
@ -17,18 +17,29 @@
|
|||
|
||||
#include <exception>
|
||||
|
||||
#include "ATen/core/Error.h"
|
||||
#include "caffe2/core/macros.h"
|
||||
#include "ATen/core/Backtrace.h"
|
||||
#include "ATen/core/Macros.h"
|
||||
#include "ATen/core/C++17.h"
|
||||
#include "ATen/core/Error.h"
|
||||
#include "ATen/core/Half.h"
|
||||
#include "ATen/core/IdWrapper.h"
|
||||
#include "ATen/core/Macros.h"
|
||||
|
||||
/*
|
||||
* TypeIdentifier is a small type containing an id.
|
||||
* Types must be registered using CAFFE_KNOWN_TYPE() for them to have a type id.
|
||||
* If a type is registered, you can also create an object containing meta data
|
||||
* like constructor, destructor, stringified name, ... about the type by calling
|
||||
* TypeMeta::Make<T>. This returns a TypeMeta() object, which is basically just
|
||||
* a pointer to the type information, so it's cheap to pass around.
|
||||
*/
|
||||
|
||||
// TODO: This file is still in the caffe2 namespace, despite living
|
||||
// in the ATen directory. This is because the macro CAFFE_DECLARE_KNOWN_TYPE
|
||||
// defines a template specialization, which relies on the namespace of TypeMeta
|
||||
// matching the namespace where the macro is called. This requires us to
|
||||
// fix all of the call-sites, which I want to do later. So the namespace
|
||||
// is not fixed at the moment.
|
||||
// in the ATen directory. This is because the macro
|
||||
// CAFFE_KNOWN_TYPE defines a template specialization, which relies
|
||||
// on the namespace of TypeMeta matching the namespace where the macro is
|
||||
// called. This requires us to fix all of the call-sites, which I want to do
|
||||
// later. So the namespace is not fixed at the moment.
|
||||
|
||||
// Make at::Half a fundamental type.
|
||||
namespace std {
|
||||
|
|
@ -39,8 +50,6 @@ struct is_fundamental<at::Half> : std::true_type {
|
|||
|
||||
namespace caffe2 {
|
||||
|
||||
class TypeMeta;
|
||||
|
||||
/**
|
||||
* A type id is a unique id for a given C++ type.
|
||||
* You need to register your types using CAFFE_KNOWN_TYPE(MyType) to be able to
|
||||
|
|
@ -62,7 +71,15 @@ class CAFFE2_API TypeIdentifier final
|
|||
return TypeIdentifier(11);
|
||||
}
|
||||
|
||||
const char* name() const noexcept;
|
||||
/**
|
||||
* Returns the unique id for the given type T. The id is unique for the type T
|
||||
* in the sense that for any two different types, their ids are different; for
|
||||
* the same type T, the id remains the same over different calls of the
|
||||
* function. However, this is not guaranteed over different runs, as the id
|
||||
* is generated during run-time. Do NOT serialize the id for storage.
|
||||
*/
|
||||
template <typename T>
|
||||
CAFFE2_API static TypeIdentifier Get();
|
||||
|
||||
private:
|
||||
constexpr explicit TypeIdentifier(uint16_t id) : IdWrapper(id) {}
|
||||
|
|
@ -91,55 +108,193 @@ AT_DEFINE_HASH_FOR_IDWRAPPER(caffe2::TypeIdentifier)
|
|||
|
||||
namespace caffe2 {
|
||||
|
||||
CAFFE2_API std::unordered_map<TypeIdentifier, std::string>& gTypeNames();
|
||||
CAFFE2_API std::unordered_set<std::string>& gRegisteredTypeNames();
|
||||
namespace detail {
|
||||
|
||||
inline const char* TypeIdentifier::name() const noexcept {
|
||||
auto it = gTypeNames().find(*this);
|
||||
assert(it != gTypeNames().end());
|
||||
return it->second.c_str();
|
||||
// This struct holds the actual type information. There will be
|
||||
// one allocated per type. TypeMeta objects will then point to the struct
|
||||
// instance for the type they're configured for.
|
||||
struct TypeMetaData final {
|
||||
using PlacementNew = void(void*, size_t);
|
||||
using TypedCopy = void(const void*, void*, size_t);
|
||||
using TypedDestructor = void(void*, size_t);
|
||||
|
||||
TypeMetaData() = delete;
|
||||
constexpr TypeMetaData(
|
||||
size_t itemsize,
|
||||
PlacementNew* ctor,
|
||||
TypedCopy* copy,
|
||||
TypedDestructor* dtor,
|
||||
TypeIdentifier id,
|
||||
const char* name) noexcept
|
||||
: itemsize_(itemsize), ctor_(ctor), copy_(copy), dtor_(dtor), id_(id), name_(name) {}
|
||||
|
||||
size_t itemsize_;
|
||||
PlacementNew* ctor_;
|
||||
TypedCopy* copy_;
|
||||
TypedDestructor* dtor_;
|
||||
TypeIdentifier id_;
|
||||
const char* name_;
|
||||
};
|
||||
|
||||
// Mechanism for throwing errors which can't be prevented at compile time
|
||||
// due to type erasure. E.g. somebody calling TypeMeta::copy() for
|
||||
// non-copyable type. Right now just throws exception but is implemented
|
||||
// in .cpp to manage dependencies
|
||||
CAFFE2_API void _ThrowRuntimeTypeLogicError(const std::string& msg);
|
||||
|
||||
/**
|
||||
* Placement new function for the type.
|
||||
*/
|
||||
template <typename T>
|
||||
inline void _Ctor(void* ptr, size_t n) {
|
||||
T* typed_ptr = static_cast<T*>(ptr);
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
new (typed_ptr + i) T;
|
||||
}
|
||||
}
|
||||
|
||||
CAFFE2_API std::mutex& gTypeRegistrationMutex();
|
||||
|
||||
template <typename T>
|
||||
struct TypeNameRegisterer {
|
||||
TypeNameRegisterer(TypeIdentifier id, const std::string& literal_name) {
|
||||
std::lock_guard<std::mutex> guard(gTypeRegistrationMutex());
|
||||
#ifdef __GXX_RTTI
|
||||
(void)literal_name;
|
||||
inline void _CtorNotDefault(void* /*ptr*/, size_t /*n*/) {
|
||||
_ThrowRuntimeTypeLogicError(
|
||||
"Type " + std::string(at::demangle_type<T>()) +
|
||||
" is not default-constructible.");
|
||||
}
|
||||
|
||||
std::string name = at::demangle(typeid(T).name());
|
||||
// If we are in RTTI mode, we will also use this opportunity to do sanity
|
||||
// check if there are duplicated ids registered for the same type. This
|
||||
// usually happens when one does not do RTLD_GLOBAL, which is often the
|
||||
// case in Python. The way we do the check is to make sure that there are
|
||||
// no duplicated names registered - this could be done by checking the
|
||||
// uniqueness of names.
|
||||
if (gRegisteredTypeNames().count(name)) {
|
||||
AT_ERROR("typeid.h: Type name ", name, " was registered twice. "
|
||||
"This should not happen. Things to check:\n"
|
||||
"1. Did you add a new CAFFE_KNOWN_TYPE? If so, check that "
|
||||
"it is not duplicated with an existing CAFFE_KNOWN_TYPE.\n"
|
||||
"2. Did you build and install PyTorch and Caffe2 separately? "
|
||||
"For example, this would be the case if you ran scripts/onnx/install.sh or "
|
||||
"scripts/onnx/install-develop.sh prior to Aug 12, 2018 "
|
||||
"(commit 1756daaa7530d). If so, rebuild using the environment variable "
|
||||
" FULL_CAFFE2=1 (if you build latest master, the ONNX scripts are "
|
||||
"updated to do this for you.) "
|
||||
"For more context, see https://github.com/pytorch/pytorch/issues/10460");
|
||||
}
|
||||
gRegisteredTypeNames().insert(name);
|
||||
gTypeNames()[id] = name;
|
||||
#else // __GXX_RTTI
|
||||
if (literal_name.empty()) {
|
||||
gTypeNames()[id] = "(RTTI disabled, cannot show name)";
|
||||
} else {
|
||||
gTypeNames()[id] = literal_name;
|
||||
}
|
||||
#endif // __GXX_RTTI
|
||||
template<
|
||||
typename T,
|
||||
c10::guts::enable_if_t<
|
||||
std::is_fundamental<T>::value || std::is_pointer<T>::value>* = nullptr>
|
||||
inline constexpr TypeMetaData::PlacementNew* _PickCtor() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
c10::guts::enable_if_t<
|
||||
!(std::is_fundamental<T>::value || std::is_pointer<T>::value) &&
|
||||
std::is_default_constructible<T>::value
|
||||
>* = nullptr>
|
||||
inline constexpr TypeMetaData::PlacementNew* _PickCtor() {
|
||||
return &_Ctor<T>;
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
c10::guts::enable_if_t<
|
||||
!(std::is_fundamental<T>::value || std::is_pointer<T>::value) &&
|
||||
!std::is_default_constructible<T>::value
|
||||
>* = nullptr>
|
||||
inline constexpr TypeMetaData::PlacementNew* _PickCtor() {
|
||||
return &_CtorNotDefault<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Typed copy function for classes.
|
||||
*/
|
||||
template <typename T>
|
||||
inline void _Copy(const void* src, void* dst, size_t n) {
|
||||
const T* typed_src = static_cast<const T*>(src);
|
||||
T* typed_dst = static_cast<T*>(dst);
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
typed_dst[i] = typed_src[i];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A placeholder function for types that do not allow assignment.
|
||||
*/
|
||||
template <typename T>
|
||||
inline void _CopyNotAllowed(const void* /*src*/, void* /*dst*/, size_t /*n*/) {
|
||||
_ThrowRuntimeTypeLogicError(
|
||||
"Type " + std::string(at::demangle_type<T>()) +
|
||||
" does not allow assignment.");
|
||||
}
|
||||
|
||||
template<
|
||||
typename T,
|
||||
c10::guts::enable_if_t<std::is_fundamental<T>::value || std::is_pointer<T>::value>* = nullptr
|
||||
>
|
||||
inline constexpr TypeMetaData::TypedCopy* _PickCopy() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
c10::guts::enable_if_t<
|
||||
!(std::is_fundamental<T>::value || std::is_pointer<T>::value) &&
|
||||
std::is_copy_assignable<T>::value
|
||||
>* = nullptr>
|
||||
inline constexpr TypeMetaData::TypedCopy* _PickCopy() {
|
||||
return &_Copy<T>;
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
c10::guts::enable_if_t<
|
||||
!(std::is_fundamental<T>::value || std::is_pointer<T>::value) &&
|
||||
!std::is_copy_assignable<T>::value
|
||||
>* = nullptr>
|
||||
inline constexpr TypeMetaData::TypedCopy* _PickCopy() {
|
||||
return &_CopyNotAllowed<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor for non-fundamental types.
|
||||
*/
|
||||
template <typename T>
|
||||
inline void _Dtor(void* ptr, size_t n) {
|
||||
T* typed_ptr = static_cast<T*>(ptr);
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
typed_ptr[i].~T();
|
||||
}
|
||||
}
|
||||
|
||||
template<
|
||||
typename T,
|
||||
c10::guts::enable_if_t<std::is_fundamental<T>::value || std::is_pointer<T>::value>* = nullptr
|
||||
>
|
||||
inline constexpr TypeMetaData::TypedDestructor* _PickDtor() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<
|
||||
typename T,
|
||||
c10::guts::enable_if_t<!(std::is_fundamental<T>::value || std::is_pointer<T>::value)>* = nullptr
|
||||
>
|
||||
inline constexpr TypeMetaData::TypedDestructor* _PickDtor() {
|
||||
return &_Dtor<T>;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const char* __TypeName() noexcept;
|
||||
|
||||
template <class T>
|
||||
const char* _TypeName() noexcept {
|
||||
static const char* literal_name = __TypeName<T>();
|
||||
#ifdef __GXX_RTTI
|
||||
std::ignore = literal_name; // suppress unused warning
|
||||
static const std::string name = at::demangle(typeid(T).name());
|
||||
return name.c_str();
|
||||
#else
|
||||
return literal_name;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline TypeMetaData _makeTypeMetaDataInstance() {
|
||||
return {
|
||||
sizeof(T),
|
||||
_PickCtor<T>(),
|
||||
_PickCopy<T>(),
|
||||
_PickDtor<T>(),
|
||||
TypeIdentifier::Get<T>(),
|
||||
_TypeName<T>()
|
||||
};
|
||||
}
|
||||
|
||||
class _Uninitialized final {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* TypeMeta is a thin class that allows us to store the type of a container such
|
||||
|
|
@ -149,243 +304,127 @@ struct TypeNameRegisterer {
|
|||
*/
|
||||
class CAFFE2_API TypeMeta {
|
||||
public:
|
||||
using PlacementNew = void(void*, size_t);
|
||||
using TypedCopy = void(const void*, void*, size_t);
|
||||
using TypedDestructor = void(void*, size_t);
|
||||
using PlacementNew = detail::TypeMetaData::PlacementNew;
|
||||
using TypedCopy = detail::TypeMetaData::TypedCopy;
|
||||
using TypedDestructor = detail::TypeMetaData::TypedDestructor;
|
||||
|
||||
/** Create a dummy TypeMeta object. To create a TypeMeta object for a specific
|
||||
* type, use TypeMeta::Make<T>().
|
||||
*/
|
||||
TypeMeta() noexcept
|
||||
: id_(TypeIdentifier::uninitialized()),
|
||||
itemsize_(0),
|
||||
ctor_(nullptr),
|
||||
copy_(nullptr),
|
||||
dtor_(nullptr) {}
|
||||
TypeMeta() noexcept;
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*/
|
||||
TypeMeta(const TypeMeta& src) noexcept = default;
|
||||
constexpr TypeMeta(const TypeMeta& src) noexcept = default;
|
||||
|
||||
/**
|
||||
* Assignment operator.
|
||||
*/
|
||||
TypeMeta& operator=(const TypeMeta& src) noexcept = default;
|
||||
AT_CPP14_CONSTEXPR TypeMeta& operator=(const TypeMeta& src) noexcept =
|
||||
default;
|
||||
|
||||
TypeMeta(TypeMeta&& rhs) noexcept = default;
|
||||
constexpr TypeMeta(TypeMeta&& rhs) noexcept = default;
|
||||
|
||||
private:
|
||||
// TypeMeta can only be created by Make, making sure that we do not
|
||||
// create incorrectly mixed up TypeMeta objects.
|
||||
TypeMeta(
|
||||
TypeIdentifier i,
|
||||
size_t s,
|
||||
PlacementNew* ctor,
|
||||
TypedCopy* copy,
|
||||
TypedDestructor* dtor) noexcept
|
||||
: id_(i), itemsize_(s), ctor_(ctor), copy_(copy), dtor_(dtor) {}
|
||||
|
||||
// Mechanism for throwing errors which can't be prevented at compile time
|
||||
// due to type erasure. E.g. somebody calling TypeMeta::copy() for
|
||||
// non-copiable type. Right now just throws exception but is implemented
|
||||
// in .cpp to manage dependencies
|
||||
static void _ThrowRuntimeTypeLogicError(const std::string& msg);
|
||||
constexpr TypeMeta(const detail::TypeMetaData* data) noexcept : data_(data) {}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns the type id.
|
||||
*/
|
||||
const TypeIdentifier& id() const noexcept {
|
||||
return id_;
|
||||
constexpr TypeIdentifier id() const noexcept {
|
||||
return data_->id_;
|
||||
}
|
||||
/**
|
||||
* Returns the size of the item.
|
||||
*/
|
||||
const size_t& itemsize() const noexcept {
|
||||
return itemsize_;
|
||||
constexpr size_t itemsize() const noexcept {
|
||||
return data_->itemsize_;
|
||||
}
|
||||
/**
|
||||
* Returns the placement new function pointer for individual items.
|
||||
*/
|
||||
PlacementNew* ctor() const noexcept {
|
||||
return ctor_;
|
||||
constexpr PlacementNew* ctor() const noexcept {
|
||||
return data_->ctor_;
|
||||
}
|
||||
/**
|
||||
* Returns the typed copy function pointer for individual iterms.
|
||||
*/
|
||||
TypedCopy* copy() const noexcept {
|
||||
return copy_;
|
||||
constexpr TypedCopy* copy() const noexcept {
|
||||
return data_->copy_;
|
||||
}
|
||||
/**
|
||||
* Returns the destructor function pointer for individual items.
|
||||
*/
|
||||
TypedDestructor* dtor() const noexcept {
|
||||
return dtor_;
|
||||
constexpr TypedDestructor* dtor() const noexcept {
|
||||
return data_->dtor_;
|
||||
}
|
||||
/**
|
||||
* Returns a printable name for the type.
|
||||
*/
|
||||
const char* name() const noexcept {
|
||||
auto it = gTypeNames().find(id_);
|
||||
assert(it != gTypeNames().end());
|
||||
return it->second.c_str();
|
||||
constexpr const char* name() const noexcept {
|
||||
return data_->name_;
|
||||
}
|
||||
|
||||
friend bool operator==(const TypeMeta& lhs, const TypeMeta& rhs) noexcept;
|
||||
|
||||
template <typename T>
|
||||
bool Match() const noexcept {
|
||||
return (id_ == Id<T>());
|
||||
constexpr bool Match() const noexcept {
|
||||
return (*this == Make<T>());
|
||||
}
|
||||
|
||||
// Below are static functions that can be called by passing a specific type.
|
||||
|
||||
/**
|
||||
* Returns the unique id for the given type T. The id is unique for the type T
|
||||
* in the sense that for any two different types, their id are different; for
|
||||
* the same type T, the id remains the same over different calls of the
|
||||
* function. However, this is not guaranteed over different runs, as the id
|
||||
* is generated during run-time. Do NOT serialize the id for storage.
|
||||
*/
|
||||
template <typename T>
|
||||
CAFFE2_API static TypeIdentifier Id();
|
||||
template <class T>
|
||||
static TypeIdentifier Id() noexcept {
|
||||
return TypeIdentifier::Get<T>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the item size of the type. This is equivalent to sizeof(T).
|
||||
*/
|
||||
template <typename T>
|
||||
static size_t ItemSize() {
|
||||
template <class T>
|
||||
static const char* TypeName() noexcept {
|
||||
return Make<T>().name();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static constexpr size_t ItemSize() noexcept {
|
||||
return sizeof(T);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the registered printable name of the type.
|
||||
*
|
||||
* Works for only the ones registered with CAFFE_KNOWN_TYPE
|
||||
*/
|
||||
template <typename T>
|
||||
static const char* TypeName() {
|
||||
auto it = gTypeNames().find(Id<T>());
|
||||
assert(it != gTypeNames().end());
|
||||
return it->second.c_str();
|
||||
}
|
||||
|
||||
/**
|
||||
* Placement new function for the type.
|
||||
*/
|
||||
template <typename T>
|
||||
static void _Ctor(void* ptr, size_t n) {
|
||||
T* typed_ptr = static_cast<T*>(ptr);
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
new (typed_ptr + i) T;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void _CtorNotDefault(void* /*ptr*/, size_t /*n*/) {
|
||||
_ThrowRuntimeTypeLogicError(
|
||||
"Type " + std::string(at::demangle_type<T>()) +
|
||||
" is not default-constructible.");
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<std::is_default_constructible<T>::value>::type* =
|
||||
nullptr>
|
||||
static inline PlacementNew* _PickCtor() {
|
||||
return _Ctor<T>;
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<!std::is_default_constructible<T>::value>::type* =
|
||||
nullptr>
|
||||
static inline PlacementNew* _PickCtor() {
|
||||
return _CtorNotDefault<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Typed copy function for classes.
|
||||
*/
|
||||
template <typename T>
|
||||
static void _Copy(const void* src, void* dst, size_t n) {
|
||||
const T* typed_src = static_cast<const T*>(src);
|
||||
T* typed_dst = static_cast<T*>(dst);
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
typed_dst[i] = typed_src[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A placeholder function for types that do not allow assignment.
|
||||
*/
|
||||
template <typename T>
|
||||
static void _CopyNotAllowed(
|
||||
const void* /*src*/,
|
||||
void* /*dst*/,
|
||||
size_t /*n*/) {
|
||||
_ThrowRuntimeTypeLogicError(
|
||||
"Type " + std::string(at::demangle_type<T>()) +
|
||||
" does not allow assignment.");
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<std::is_copy_assignable<T>::value>::type* =
|
||||
nullptr>
|
||||
static inline TypedCopy* _PickCopy() {
|
||||
return _Copy<T>;
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename std::enable_if<!std::is_copy_assignable<T>::value>::type* =
|
||||
nullptr>
|
||||
static inline TypedCopy* _PickCopy() {
|
||||
return _CopyNotAllowed<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor for non-fundamental types.
|
||||
*/
|
||||
template <typename T>
|
||||
static void _Dtor(void* ptr, size_t n) {
|
||||
T* typed_ptr = static_cast<T*>(ptr);
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
typed_ptr[i].~T();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a TypeMeta object that corresponds to the typename T.
|
||||
*/
|
||||
template <typename T>
|
||||
static typename std::enable_if<
|
||||
std::is_fundamental<T>::value || std::is_pointer<T>::value,
|
||||
TypeMeta>::type
|
||||
Make() {
|
||||
return TypeMeta(Id<T>(), ItemSize<T>(), nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typename std::enable_if<
|
||||
!(std::is_fundamental<T>::value || std::is_pointer<T>::value),
|
||||
TypeMeta>::type
|
||||
Make() {
|
||||
return TypeMeta(
|
||||
Id<T>(), ItemSize<T>(), _PickCtor<T>(), _PickCopy<T>(), _Dtor<T>);
|
||||
static TypeMeta Make() {
|
||||
// The instance pointed to is declared here, but defined in a .cpp file.
|
||||
// We need to silence the compiler warning about using an undefined
|
||||
// variable template. '-Wpragmas' and '-Wunknown-warning-option' has to be
|
||||
// disabled for compilers that don't know '-Wundefined-var-template' and
|
||||
// would error at our attempt to disable it.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||
#pragma GCC diagnostic ignored "-Wunknown-warning-option"
|
||||
#pragma GCC diagnostic ignored "-Wundefined-var-template"
|
||||
return TypeMeta(_typeMetaDataInstance<T>());
|
||||
#pragma GCC diagnostic pop
|
||||
}
|
||||
|
||||
private:
|
||||
TypeIdentifier id_;
|
||||
size_t itemsize_;
|
||||
PlacementNew* ctor_;
|
||||
TypedCopy* copy_;
|
||||
TypedDestructor* dtor_;
|
||||
const detail::TypeMetaData* data_;
|
||||
|
||||
template<class T>
|
||||
CAFFE2_API static const detail::TypeMetaData* _typeMetaDataInstance() noexcept;
|
||||
};
|
||||
|
||||
template<>
|
||||
C10_EXPORT const detail::TypeMetaData* TypeMeta::_typeMetaDataInstance<detail::_Uninitialized>() noexcept;
|
||||
|
||||
inline TypeMeta::TypeMeta() noexcept : data_(_typeMetaDataInstance<detail::_Uninitialized>()) {}
|
||||
|
||||
inline bool operator==(const TypeMeta& lhs, const TypeMeta& rhs) noexcept {
|
||||
return (lhs.id_ == rhs.id_);
|
||||
return (lhs.data_ == rhs.data_);
|
||||
}
|
||||
inline bool operator!=(const TypeMeta& lhs, const TypeMeta& rhs) noexcept {
|
||||
return !operator==(lhs, rhs);
|
||||
|
|
@ -395,10 +434,10 @@ inline bool operator!=(const TypeMeta& lhs, const TypeMeta& rhs) noexcept {
|
|||
* Register unique id for a type so it can be used in TypeMeta context, e.g. be
|
||||
* used as a type for Blob or for Tensor elements.
|
||||
*
|
||||
* CAFFE_KNOWN_TYPE does explicit instantiation of TypeMeta::Id<T> template
|
||||
* function and thus needs to be put in a single translation unit (.cpp file)
|
||||
* for a given type T. Other translation units that use type T as a type of the
|
||||
* caffe2::Blob or element type of caffe2::Tensor need to depend on the
|
||||
* CAFFE_KNOWN_TYPE does explicit instantiation of TypeIdentifier::Get<T>
|
||||
* template function and thus needs to be put in a single translation unit (.cpp
|
||||
* file) for a given type T. Other translation units that use type T as a type
|
||||
* of the caffe2::Blob or element type of caffe2::Tensor need to depend on the
|
||||
* translation unit that contains CAFFE_KNOWN_TYPE declaration via regular
|
||||
* linkage dependencies.
|
||||
*
|
||||
|
|
@ -411,86 +450,140 @@ inline bool operator!=(const TypeMeta& lhs, const TypeMeta& rhs) noexcept {
|
|||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51930
|
||||
// and as a result, we define these two macros slightly differently.
|
||||
#if defined(_MSC_VER) || defined(__clang__)
|
||||
#define _CAFFE_KNOWN_TYPE_DEFINE_TYPEMETADATA_INSTANCE(T, Counter) \
|
||||
namespace detail { \
|
||||
const TypeMetaData MACRO_CONCAT(_typeMetaDataInstance_, Counter) = \
|
||||
_makeTypeMetaDataInstance<T>(); \
|
||||
} \
|
||||
template<> \
|
||||
C10_EXPORT const detail::TypeMetaData* TypeMeta::_typeMetaDataInstance<T>() noexcept { \
|
||||
return &MACRO_CONCAT(detail::_typeMetaDataInstance_, Counter); \
|
||||
}
|
||||
#define CAFFE_KNOWN_TYPE(T) \
|
||||
template <> \
|
||||
C10_EXPORT TypeIdentifier TypeMeta::Id<T>() { \
|
||||
C10_EXPORT TypeIdentifier TypeIdentifier::Get<T>() { \
|
||||
static const TypeIdentifier type_id = TypeIdentifier::createTypeId(); \
|
||||
static TypeNameRegisterer<T> registerer(type_id, #T); \
|
||||
return type_id; \
|
||||
}
|
||||
} \
|
||||
namespace detail { \
|
||||
template <> \
|
||||
C10_EXPORT const char* __TypeName<T>() noexcept { \
|
||||
return #T; \
|
||||
} \
|
||||
} \
|
||||
_CAFFE_KNOWN_TYPE_DEFINE_TYPEMETADATA_INSTANCE(T, __COUNTER__)
|
||||
#else // defined(_MSC_VER) || defined(__clang__)
|
||||
#define _CAFFE_KNOWN_TYPE_DEFINE_TYPEMETADATA_INSTANCE(T, Counter) \
|
||||
namespace detail { \
|
||||
const TypeMetaData MACRO_CONCAT(_typeMetaDataInstance_, Counter) = \
|
||||
_makeTypeMetaDataInstance<T>(); \
|
||||
} \
|
||||
template<> \
|
||||
const detail::TypeMetaData* TypeMeta::_typeMetaDataInstance<T>() noexcept { \
|
||||
return &MACRO_CONCAT(detail::_typeMetaDataInstance_, Counter); \
|
||||
}
|
||||
#define CAFFE_KNOWN_TYPE(T) \
|
||||
template <> \
|
||||
TypeIdentifier TypeMeta::Id<T>() { \
|
||||
TypeIdentifier TypeIdentifier::Get<T>() { \
|
||||
static const TypeIdentifier type_id = TypeIdentifier::createTypeId(); \
|
||||
static TypeNameRegisterer<T> registerer(type_id, #T); \
|
||||
return type_id; \
|
||||
}
|
||||
} \
|
||||
namespace detail { \
|
||||
template <> \
|
||||
const char* __TypeName<T>() noexcept { \
|
||||
return #T; \
|
||||
} \
|
||||
} \
|
||||
_CAFFE_KNOWN_TYPE_DEFINE_TYPEMETADATA_INSTANCE(T, __COUNTER__)
|
||||
#endif // defined(_MSC_VER) || defined(__clang__)
|
||||
|
||||
/**
|
||||
* CAFFE_DECLARE_KNOWN_TYPE and CAFFE_DEFINE_KNOWN_TYPE are used
|
||||
* CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE is used
|
||||
* to preallocate ids for types that are queried very often so that they
|
||||
* can be resolved at compile time. Please use CAFFE_KNOWN_TYPE() instead
|
||||
* for your own types to allocate dynamic ids for them.
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
#define CAFFE_DECLARE_KNOWN_TYPE(PreallocatedId, T) \
|
||||
template <> \
|
||||
inline CAFFE2_API TypeIdentifier TypeMeta::Id<T>() { \
|
||||
return TypeIdentifier(PreallocatedId); \
|
||||
#define CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(PreallocatedId, T) \
|
||||
template <> \
|
||||
inline C10_EXPORT TypeIdentifier TypeIdentifier::Get<T>() { \
|
||||
return TypeIdentifier(PreallocatedId); \
|
||||
} \
|
||||
namespace detail { \
|
||||
template <> \
|
||||
inline C10_EXPORT const char* __TypeName<T>() noexcept { \
|
||||
return #T; \
|
||||
} \
|
||||
}
|
||||
#define CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(Id, T) \
|
||||
namespace detail { \
|
||||
const TypeMetaData \
|
||||
MACRO_CONCAT(_typeMetaDataInstance_preallocated_, Id) \
|
||||
= _makeTypeMetaDataInstance<T>(); \
|
||||
} \
|
||||
template<> \
|
||||
C10_EXPORT const detail::TypeMetaData* TypeMeta::_typeMetaDataInstance<T>() noexcept { \
|
||||
return &MACRO_CONCAT(detail::_typeMetaDataInstance_preallocated_, Id); \
|
||||
}
|
||||
#else // _MSC_VER
|
||||
#define CAFFE_DECLARE_KNOWN_TYPE(PreallocatedId, T) \
|
||||
template <> \
|
||||
inline TypeIdentifier TypeMeta::Id<T>() { \
|
||||
return TypeIdentifier(PreallocatedId); \
|
||||
#define _CAFFE_KNOWN_TYPE_DEFINE_PREALLOCATED_TYPEMETADATA_INSTANCE(Id, T) \
|
||||
namespace detail { \
|
||||
C10_EXPORT extern const TypeMetaData \
|
||||
MACRO_CONCAT(_typeMetaDataInstance_preallocated_, Id); \
|
||||
} \
|
||||
template<> \
|
||||
inline const detail::TypeMetaData* TypeMeta::_typeMetaDataInstance<T>() noexcept { \
|
||||
return &MACRO_CONCAT(detail::_typeMetaDataInstance_preallocated_, Id); \
|
||||
}
|
||||
#define CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(PreallocatedId, T) \
|
||||
template <> \
|
||||
inline C10_EXPORT TypeIdentifier TypeIdentifier::Get<T>() { \
|
||||
return TypeIdentifier(PreallocatedId); \
|
||||
} \
|
||||
namespace detail { \
|
||||
template <> \
|
||||
inline C10_EXPORT const char* __TypeName<T>() noexcept { \
|
||||
return #T; \
|
||||
} \
|
||||
} \
|
||||
_CAFFE_KNOWN_TYPE_DEFINE_PREALLOCATED_TYPEMETADATA_INSTANCE(PreallocatedId, T)
|
||||
#define CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(Id, T) \
|
||||
namespace detail { \
|
||||
const TypeMetaData MACRO_CONCAT(_typeMetaDataInstance_preallocated_, Id) \
|
||||
= _makeTypeMetaDataInstance<T>(); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define CONCAT_IMPL(x, y) x##y
|
||||
#define MACRO_CONCAT(x, y) CONCAT_IMPL(x, y)
|
||||
|
||||
#define CAFFE_DEFINE_KNOWN_TYPE(T) \
|
||||
namespace { \
|
||||
TypeNameRegisterer<T> MACRO_CONCAT(registerer, __COUNTER__)( \
|
||||
TypeMeta::Id<T>(), \
|
||||
#T); \
|
||||
}
|
||||
|
||||
class Tensor;
|
||||
|
||||
// Note: we have preallocated the numbers so they line up exactly
|
||||
// with at::ScalarType's numbering. All other numbers do not matter.
|
||||
|
||||
struct _CaffeHighestPreallocatedTypeId final {};
|
||||
|
||||
CAFFE_DECLARE_KNOWN_TYPE(0, uint8_t)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(1, int8_t)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(2, int16_t)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(3, int)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(4, int64_t)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(5, at::Half)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(6, float)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(7, double)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(8, at::ComplexHalf)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(9, std::complex<float>)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(10, std::complex<double>)
|
||||
// TODO static_assert number of declare/define align
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(0, uint8_t)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(1, int8_t)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(2, int16_t)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(3, int)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(4, int64_t)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(5, at::Half)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(6, float)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(7, double)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(8, at::ComplexHalf)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(9, std::complex<float>)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(10, std::complex<double>)
|
||||
// 11 = undefined type id
|
||||
|
||||
CAFFE_DECLARE_KNOWN_TYPE(12, Tensor)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(13, std::string)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(14, bool)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(15, uint16_t)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(16, char)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(17, std::unique_ptr<std::mutex>)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(18, std::unique_ptr<std::atomic<bool>>)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(19, std::vector<int32_t>)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(20, std::vector<int64_t>)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(21, std::vector<unsigned long>)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(22, bool*)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(23, char*)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(24, int*)
|
||||
// 12 = Tensor (defined in tensor.h)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(13, std::string)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(14, bool)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(15, uint16_t)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(16, char)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(17, std::unique_ptr<std::mutex>)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(18, std::unique_ptr<std::atomic<bool>>)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(19, std::vector<int32_t>)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(20, std::vector<int64_t>)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(21, std::vector<unsigned long>)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(22, bool*)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(23, char*)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(24, int*)
|
||||
|
||||
// For some of the compilers, long is definied separately from int32_t and
|
||||
// int64_t. As a result we will need to actually define them separately.
|
||||
|
|
@ -498,9 +591,9 @@ CAFFE_DECLARE_KNOWN_TYPE(24, int*)
|
|||
// explicitly. Explicit long type annotation may go away in the future.
|
||||
#if defined(_MSC_VER) || defined(__APPLE__) || \
|
||||
(defined(__ANDROID__) && !defined(__LP64__))
|
||||
CAFFE_DECLARE_KNOWN_TYPE(25, long)
|
||||
CAFFE_DECLARE_KNOWN_TYPE(26, std::vector<long>)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(25, long)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(26, std::vector<long>)
|
||||
#endif
|
||||
|
||||
CAFFE_DECLARE_KNOWN_TYPE(27, _CaffeHighestPreallocatedTypeId)
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(27, _CaffeHighestPreallocatedTypeId)
|
||||
} // namespace caffe2
|
||||
|
|
|
|||
|
|
@ -29,4 +29,7 @@
|
|||
classname(const classname&) = delete; \
|
||||
classname& operator=(const classname&) = delete
|
||||
|
||||
#define CONCAT_IMPL(x, y) x##y
|
||||
#define MACRO_CONCAT(x, y) CONCAT_IMPL(x, y)
|
||||
|
||||
#endif // C10_MACROS_MACROS_H_
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
namespace caffe2 {
|
||||
|
||||
CAFFE_DEFINE_KNOWN_TYPE(Tensor);
|
||||
CAFFE_DEFINE_PREALLOCATED_KNOWN_TYPE(12, Tensor);
|
||||
|
||||
TensorPrinter::TensorPrinter(
|
||||
const std::string& tensor_name,
|
||||
|
|
|
|||
|
|
@ -435,6 +435,8 @@ class CAFFE2_API Tensor final {
|
|||
}
|
||||
};
|
||||
|
||||
CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(12, Tensor)
|
||||
|
||||
using TensorCPU = Tensor;
|
||||
|
||||
constexpr int k_limit_default_ = 1000;
|
||||
|
|
|
|||
|
|
@ -127,8 +127,7 @@ TEST(TypeMetaTest, CtorDtorAndCopy) {
|
|||
// gtest seems to have some problem with function pointers and
|
||||
// clang right now... Disabling it.
|
||||
// TODO: figure out the real cause.
|
||||
EXPECT_EQ(meta_b.copy(),
|
||||
&(TypeMeta::_CopyNotAllowed<ClassNoAssignment>));
|
||||
EXPECT_EQ(meta_b.copy(), &(detail::_CopyNotAllowed<ClassNoAssignment>));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user