"launch/dynamo-run/README.md" did not exist on "6e0cfbd967147e4d48ab0542127760939c0a2b68"
Commit 546b4279 authored by limm's avatar limm
Browse files

add csrc and mmdeploy module

parent 502f4fb9
Pipeline #2810 canceled with stages
// Copyright (c) OpenMMLab. All rights reserved.
#ifndef MMDEPLOY_SRC_CORE_NET_H_
#define MMDEPLOY_SRC_CORE_NET_H_
#include "mmdeploy/core/mpl/span.h"
#include "mmdeploy/core/registry.h"
#include "mmdeploy/core/tensor.h"
#include "mmdeploy/core/value.h"
namespace mmdeploy::framework {
class Net {
public:
virtual ~Net() = default;
virtual Result<void> Init(const Value& cfg) = 0;
virtual Result<void> Deinit() = 0;
virtual Result<Span<Tensor>> GetInputTensors() = 0;
virtual Result<Span<Tensor>> GetOutputTensors() = 0;
virtual Result<void> Reshape(Span<TensorShape> input_shapes) = 0;
virtual Result<void> Forward() = 0;
virtual Result<void> ForwardAsync(Event* event) = 0;
};
MMDEPLOY_DECLARE_REGISTRY(Net, std::unique_ptr<Net>(const Value& config));
} // namespace mmdeploy::framework
#endif // MMDEPLOY_SRC_CORE_NET_H_
// Copyright (c) OpenMMLab. All rights reserved.
#include "operator.h"
#include <algorithm>
#include "mmdeploy/core/utils/formatter.h"
namespace mmdeploy::graph {
Result<void> Gather(const Value::Array& array, const vector<int>& idxs, Value::Array& output) {
if (idxs.empty()) {
return success();
}
auto max_idx = *max_element(begin(idxs), end(idxs));
if (array.size() <= max_idx) {
return Status(eOutOfRange);
}
output.reserve(output.size() + idxs.size());
for (const auto& idx : idxs) {
output.push_back(array[idx]);
}
return success();
}
Result<void> Gather(Value::Array&& array, const vector<int>& idxs, Value::Array& output) {
if (idxs.empty()) {
return success();
}
auto max_idx = *max_element(begin(idxs), end(idxs));
if (array.size() <= max_idx) {
return Status(eOutOfRange);
}
output.reserve(output.size() + idxs.size());
for (const auto& idx : idxs) {
output.push_back(std::move(array[idx]));
}
return success();
}
Result<void> Gather(const Value::Object& object, const vector<std::string>& keys,
Value::Array& output) {
output.reserve(output.size() + keys.size());
try {
for (const auto& key : keys) {
output.push_back(object.at(key));
}
} catch (const std::out_of_range& e) {
return Status(eOutOfRange);
}
return success();
}
Result<void> Gather(Value::Object&& object, const vector<std::string>& keys, Value::Array& output) {
output.reserve(output.size() + keys.size());
try {
for (const auto& key : keys) {
output.push_back(std::move(object.at(key)));
}
} catch (const std::out_of_range& e) {
return Status(eOutOfRange);
}
return success();
}
Result<void> Scatter(Value::Array array, const vector<int>& idxs, Value::Array& output) {
if (array.size() < idxs.size()) {
return Status(eOutOfRange);
}
for (int i = 0; i < idxs.size(); ++i) {
output[idxs[i]] = std::move(array[i]);
}
return success();
}
Result<void> Scatter(Value::Array array, const vector<std::string>& keys, Value::Object& output) {
if (array.size() < keys.size()) {
return Status(eOutOfRange);
}
for (int i = 0; i < keys.size(); ++i) {
output.emplace(keys[i], std::move(array[i]));
}
return success();
}
Result<Value> DistribOA(const Value& oa) {
if (!oa.is_object()) {
return Status(eInvalidArgument);
}
Value ao = ValueType::kArray;
for (auto inner = oa.begin(); inner != oa.end(); ++inner) {
if (!inner->is_array()) {
return Status(eInvalidArgument);
}
if (ao.empty()) {
for (int i = 0; i < inner->size(); ++i) ao.push_back(ValueType::kObject);
}
if (inner->size() != oa.size()) {
return Status(eInvalidArgument);
}
for (int i = 0; i < inner->size(); ++i) {
ao[i][inner.key()] = (*inner)[i];
}
}
return ao;
}
Result<Value> DistribAO(const Value& ao) {
if (!ao.is_array()) {
return Status(eInvalidArgument);
}
Value oa = ValueType::kObject;
for (const auto& inner : ao) {
if (inner.is_object()) {
return Status(eInvalidArgument);
}
if (oa.empty()) {
for (auto item = inner.begin(); item != inner.end(); ++item) {
oa[item.key()] = ValueType::kObject;
}
}
if (inner.size() != oa.size()) {
return Status(eInvalidArgument);
}
for (auto item = inner.begin(); item != inner.end(); ++item) {
if (!oa.contains(item.key())) {
return Status(eInvalidArgument);
}
oa[item.key()].push_back(*item);
}
}
return oa;
}
Result<Value> DistribAA(const Value& a) {
if (!a.is_array()) {
return Status(eInvalidArgument);
}
auto ta = Value::Array{};
for (const auto& inner : a.get_ref<const Value::Array&>()) {
if (!inner.is_array()) {
return Status(eInvalidArgument);
}
if (ta.empty()) {
ta.reserve(inner.size());
for (int i = 0; i < inner.size(); ++i) {
ta.emplace_back(Value::kArray);
}
}
if (inner.size() != ta.size()) {
return Status(eInvalidArgument);
}
for (int i = 0; i < inner.size(); ++i) {
ta[i].push_back(inner[i]);
}
}
return ta;
}
std::tuple<Value::Array, std::vector<int>> FlattenArray(Value::Array values,
const vector<bool>& predicate) {
assert(values.size() == predicate.size());
std::vector<int> indices;
for (int i = 0; i < values.size(); ++i) {
if (predicate[i]) {
std::vector<int> idx;
std::tie(values[i], idx) = Flatten(values[i]).value();
if (indices.empty()) {
indices.swap(idx);
} else {
assert(idx == indices);
}
}
}
return {std::move(values), std::move(indices)};
}
Value::Array UnflattenArray(Value::Array values, const vector<int>& index,
const vector<bool>& predicate) {
assert(values.size() == predicate.size());
for (int i = 0; i < values.size(); ++i) {
if (predicate[i]) {
values[i] = Unflatten(std::move(values[i]), index).value();
}
}
return values;
}
Value::Array BroadcastArray(Value::Array values, const vector<int>& index,
const vector<bool>& predicate) {
assert(values.size() == predicate.size());
for (int i = 0; i < values.size(); ++i) {
if (predicate[i]) {
assert(values[i].is_array());
auto& val = values[i].array();
Value::Array ret(index.size() - 1);
for (int j = 0; j < ret.size(); ++j) {
ret[j] = val[index[j]];
}
values[i] = std::move(ret);
}
}
return values;
}
} // namespace mmdeploy::graph
// Copyright (c) OpenMMLab. All rights reserved.
#ifndef MMDEPLOY_SRC_EXPERIMENTAL_PIPELINE_OPERATOR_H_
#define MMDEPLOY_SRC_EXPERIMENTAL_PIPELINE_OPERATOR_H_
#include "mmdeploy/core/value.h"
namespace mmdeploy::graph {
using std::string;
using std::tuple;
using std::vector;
MMDEPLOY_API Result<void> Gather(const Value::Array& array, const vector<int>& idxs,
Value::Array& output);
MMDEPLOY_API Result<void> Gather(Value::Array&& array, const vector<int>& idxs,
Value::Array& output);
MMDEPLOY_API Result<void> Gather(const Value::Object& object, const vector<std::string>& keys,
Value::Array& output);
MMDEPLOY_API Result<void> Gather(Value::Object&& object, const vector<std::string>& keys,
Value::Array& output);
MMDEPLOY_API Result<void> Scatter(Value::Array array, const vector<int>& idxs,
Value::Array& output);
MMDEPLOY_API Result<void> Scatter(Value::Array array, const vector<std::string>& keys,
Value::Object& output);
inline Result<Value::Array> Gather(const Value::Array& array, const vector<int>& idxs) {
Value::Array output;
OUTCOME_TRY(Gather(array, idxs, output));
return output;
}
inline Result<Value::Array> Gather(Value::Array&& array, const vector<int>& idxs) {
Value::Array output;
OUTCOME_TRY(Gather(std::move(array), idxs, output));
return output;
}
inline Result<Value::Array> Gather(const Value::Object& object, const vector<std::string>& keys) {
Value::Array output;
OUTCOME_TRY(Gather(object, keys, output));
return output;
}
inline Result<Value::Array> Gather(Value::Object&& object, const vector<std::string>& keys) {
Value::Array output;
OUTCOME_TRY(Gather(std::move(object), keys, output));
return output;
}
inline Result<Value::Array> Scatter(Value::Array array, const vector<int>& idxs) {
Value::Array output(idxs.size(), Value::kNull);
OUTCOME_TRY(Scatter(std::move(array), idxs, output));
return output;
}
inline Result<Value::Object> Scatter(Value::Array array, const vector<std::string>& keys) {
Value::Object output;
OUTCOME_TRY(Scatter(std::move(array), keys, output));
return output;
}
template <class V, std::enable_if_t<is_value_v<std::decay_t<V>>, bool> = true>
Result<tuple<Value, vector<int>>> Flatten(V&& input) {
if (!input.is_array()) {
return Status(eInvalidArgument);
}
Value output = ValueType::kArray;
std::vector<int> idxs;
for (int i = 0; i < input.size(); ++i) {
auto inner = std::forward<V>(input)[i];
if (!inner.is_array()) {
return Status(eInvalidArgument);
}
for (auto& item : inner) {
output.push_back(std::move(item));
idxs.push_back(i);
}
}
idxs.push_back(static_cast<int>(input.size()));
return {output, idxs};
}
template <class V, std::enable_if_t<is_value_v<std::decay_t<V>>, bool> = true>
Result<Value> Unflatten(V&& input, const vector<int>& idxs) {
if (!input.is_array()) {
return Status(eInvalidArgument);
}
Value output = ValueType::kArray;
for (int i = 0; i < idxs.back(); ++i) {
output.push_back(ValueType::kArray);
}
for (int i = 0; i < input.size(); ++i) {
if (idxs[i] >= output.size()) {
return Status(eInvalidArgument);
}
output[idxs[i]].push_back(std::forward<V>(input)[i]);
}
return output;
}
// object of arrays -> array of objects, all arrays must be of same length
MMDEPLOY_API Result<Value> DistribOA(const Value& oa);
// array of objects -> object of arrays, all objects must be isomorphic
MMDEPLOY_API Result<Value> DistribAO(const Value& ao);
// array of arrays -> array of arrays, this is equivalent to transpose
MMDEPLOY_API Result<Value> DistribAA(const Value& a);
MMDEPLOY_API std::tuple<Value::Array, std::vector<int>> FlattenArray(Value::Array values,
const vector<bool>& predicate);
MMDEPLOY_API Value::Array UnflattenArray(Value::Array values, const vector<int>& index,
const vector<bool>& predicate);
MMDEPLOY_API Value::Array BroadcastArray(Value::Array values, const std::vector<int>& index,
const vector<bool>& predicate);
} // namespace mmdeploy::graph
#endif // MMDEPLOY_SRC_EXPERIMENTAL_PIPELINE_OPERATOR_H_
// Copyright (c) OpenMMLab. All rights reserved.
#include "mmdeploy/core/profiler.h"
#include <iomanip>
namespace mmdeploy {
namespace profiler {
Event* Scope::Add(Event::Type type, Index index, TimePoint time_point) {
return profiler_->AddEvent({this, type, index, time_point});
}
Scope* Scope::CreateScope(std::string_view name) {
auto node = children_.emplace_back(profiler_->CreateScope(name));
node->parent_ = this;
return node;
}
void Scope::Dump(Scope* scope, std::ofstream& ofs) {
ofs << scope->name_ << " " << (void*)scope << " ";
for (auto& child : scope->children_) {
ofs << (void*)child << " ";
}
ofs << "\n";
for (const auto& child : scope->children_) {
Dump(child, ofs);
}
}
ScopedCounter::ScopedCounter(Scope* scope) {
if (scope) {
start_ = scope->Add(Event::kStart, scope->next_.fetch_add(1, std::memory_order_relaxed),
Clock::now());
}
}
ScopedCounter::~ScopedCounter() {
if (start_) {
start_->scope->Add(Event::kEnd, start_->index, Clock::now());
}
}
Profiler::Profiler(std::string_view path) : path_(path) { root_ = CreateScope("."); }
Scope* Profiler::CreateScope(std::string_view name) {
auto& node = nodes_.emplace_back();
node.profiler_ = this;
node.name_ = name;
return &node;
}
Event* Profiler::AddEvent(Event e) {
auto uptr = std::make_unique<Event>(e);
Event* pe = uptr.get();
events_.enqueue(std::move(uptr));
return pe;
}
void Profiler::Release() {
std::ofstream ofs(path_);
root_->Dump(ofs);
ofs << "----\n";
std::unique_ptr<Event> item;
std::vector<std::unique_ptr<Event>> vec;
while (events_.try_dequeue(item)) {
vec.push_back(std::move(item));
}
std::sort(vec.begin(), vec.end(),
[](const std::unique_ptr<Event>& a, const std::unique_ptr<Event>& b) {
return a->time_point < b->time_point;
});
for (int i = 0; i < vec.size(); i++) {
ofs << (void*)vec[i]->scope << " " << vec[i]->type << " " << vec[i]->index << " "
<< std::chrono::duration_cast<std::chrono::microseconds>(vec[i]->time_point -
vec[0]->time_point)
.count()
<< "\n";
}
}
} // namespace profiler
} // namespace mmdeploy
// Copyright (c) OpenMMLab. All rights reserved.
#ifndef MMDEPLOY_CSRC_MMDEPLOY_CORE_PROFILER_H_
#define MMDEPLOY_CSRC_MMDEPLOY_CORE_PROFILER_H_
#include <atomic>
#include <chrono>
#include <deque>
#include <fstream>
#include <iostream>
#include <string>
#include <string_view>
#include <vector>
#include "concurrentqueue.h"
#include "mmdeploy/core/logger.h"
#include "mmdeploy/core/macro.h"
#include "mmdeploy/core/value.h"
namespace mmdeploy {
namespace profiler {
struct Profiler;
struct Scope;
using Clock = std::conditional_t<std::chrono::high_resolution_clock::is_steady,
std::chrono::high_resolution_clock, std::chrono::steady_clock>;
using TimePoint = Clock::time_point;
using Index = uint64_t;
struct Event {
enum Type { kStart, kEnd };
Scope* scope;
Type type;
Index index;
TimePoint time_point;
};
struct MMDEPLOY_API Scope {
Scope() = default;
Scope(const Scope&) = delete;
Scope(Scope&&) noexcept = delete;
Scope& operator=(const Scope&) = delete;
Scope& operator=(Scope&&) noexcept = delete;
Event* Add(Event::Type type, Index index, TimePoint time_point);
Scope* CreateScope(std::string_view name);
void Dump(Scope* scope, std::ofstream& ofs);
void Dump(std::ofstream& ofs) { Dump(this, ofs); }
Profiler* profiler_{};
Scope* parent_{};
std::vector<Scope*> children_;
std::atomic<Index> next_{};
std::string name_;
};
struct MMDEPLOY_API ScopedCounter {
explicit ScopedCounter(Scope* scope);
~ScopedCounter();
Event* start_{};
};
struct MMDEPLOY_API Profiler {
explicit Profiler(std::string_view path);
Scope* CreateScope(std::string_view name);
Event* AddEvent(Event e);
Scope* scope() const noexcept { return root_; }
void Release();
std::string path_;
std::deque<Scope> nodes_;
moodycamel::ConcurrentQueue<std::unique_ptr<Event>> events_;
Scope* root_{};
};
} // namespace profiler
MMDEPLOY_REGISTER_TYPE_ID(profiler::Scope*, 10);
} // namespace mmdeploy
#endif // MMDEPLOY_CSRC_MMDEPLOY_GRAPH_PROFILER_H_
// Copyright (c) OpenMMLab. All rights reserved.
#include "mmdeploy/core/registry.h"
#include <algorithm>
#include <cassert>
#include "mmdeploy/core/logger.h"
namespace mmdeploy {
namespace _registry {
struct Registry<void>::Impl {
template <typename It>
auto convert(It u, It v) {
return std::pair{creators_.begin() + (u - names_.begin()),
creators_.begin() + (v - names_.begin())};
}
Creator<void>* Get(const string_view& name, int version) {
const auto& [u, v] = std::equal_range(names_.begin(), names_.end(), name);
const auto& [i, j] = convert(u, v);
if (version == -1) {
if (auto n = j - i; n == 1) {
return *i;
}
return nullptr;
}
for (const auto& creator : iterator_range(i, j)) {
if (creator->version() == version) {
return creator;
}
}
return nullptr;
}
bool Add(Creator<void>& creator) {
const auto& [u, v] = std::equal_range(names_.begin(), names_.end(), creator.name());
const auto& [i, j] = convert(u, v);
if (i != j) {
for (const auto& other : iterator_range(i, j)) {
if (creator.version() == other->version()) {
MMDEPLOY_WARN("Adding duplicated creator ({}, {}).", creator.name(), creator.version());
return false;
}
}
}
names_.insert(v, creator.name());
creators_.insert(j, &creator);
return true;
}
Span<Creator<void>*> Creators() { return creators_; }
std::vector<Creator<void>*> creators_;
std::vector<string_view> names_;
};
Registry<void>::Registry() : impl_(std::make_unique<Impl>()) {}
Registry<void>::~Registry() = default;
bool Registry<void>::AddCreator(Creator<void>& creator) {
assert(impl_);
return impl_->Add(creator);
}
Creator<void>* Registry<void>::GetCreator(const std::string_view& name, int version) {
assert(impl_);
return impl_->Get(name, version);
}
Span<Creator<void>*> Registry<void>::Creators() {
assert(impl_);
return impl_->Creators();
}
} // namespace _registry
} // namespace mmdeploy
// Copyright (c) OpenMMLab. All rights reserved.
#ifndef MMDEPLOY_REGISTRY_H
#define MMDEPLOY_REGISTRY_H
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
#include "mmdeploy/core/macro.h"
#include "mmdeploy/core/mpl/span.h"
namespace mmdeploy {
template <typename T>
struct basic_type {
using type = T;
};
template <typename Iterator>
class iterator_range {
public:
explicit iterator_range(Iterator first, Iterator last) : first_(first), last_(last) {}
explicit iterator_range(std::pair<Iterator, Iterator> range)
: iterator_range(range.first, range.second) {}
auto begin() noexcept { return first_; }
auto end() noexcept { return last_; }
private:
Iterator first_;
Iterator last_;
};
namespace _registry {
using std::optional;
using std::string_view;
template <typename T, typename = void>
struct _get_signature {
static_assert(!std::is_same_v<T, T>, "tag T is not associated with a signature");
};
template <typename T>
using get_signature_t = decltype(get_signature(basic_type<T>{}));
template <typename T>
struct _get_signature<T, std::void_t<get_signature_t<T>>> {
using type = typename get_signature_t<T>::type;
};
template <typename T>
using GetSignature = typename _get_signature<T>::type;
template <typename Tag>
class Creator;
template <>
class MMDEPLOY_API Creator<void> {
public:
virtual ~Creator() = default;
virtual string_view name() const noexcept = 0;
virtual int version() const noexcept { return 0; }
};
template <typename Ret, typename... Args>
class MMDEPLOY_API Creator<Ret(Args...)> : public Creator<void> {
public:
virtual Ret Create(Args... args) = 0;
};
template <typename Tag>
class SimpleCreator;
template <typename Ret, typename... Args>
class SimpleCreator<Ret(Args...)> : public Creator<Ret(Args...)> {
public:
using FunctionType = std::function<Ret(Args...)>;
SimpleCreator(const string_view& name, int version, FunctionType func)
: name_(name), version_(version), func_(std::move(func)) {}
string_view name() const noexcept override { return name_; }
int version() const noexcept override { return version_; }
Ret Create(Args... args) override { return func_(args...); }
private:
std::string name_;
int version_;
FunctionType func_;
};
template <typename Tag>
class Registry;
template <>
class MMDEPLOY_API Registry<void> {
public:
Registry();
~Registry();
bool AddCreator(Creator<void>& creator);
Creator<void>* GetCreator(const string_view& name, int version);
Span<Creator<void>*> Creators();
private:
struct Impl;
std::unique_ptr<Impl> impl_;
};
template <typename Signature>
struct _result_of;
template <typename R, typename... As>
struct _result_of<R(As...)> {
using type = R;
};
template <typename Tag>
class Registry : public Registry<void> {
public:
using Signature = GetSignature<Tag>;
using CreatorType = Creator<Signature>;
// workaround for gcc-10.2 (https://github.com/open-mmlab/mmdeploy/issues/1796)
Registry() : Registry<void>{} {}
bool Add(CreatorType& creator) & { return AddCreator(creator); }
CreatorType* Get(const string_view& name, int version) & {
return static_cast<CreatorType*>(GetCreator(name, version));
}
CreatorType* Get(const string_view& name) & { return Get(name, -1); }
template <typename... Args>
auto Create(const std::pair<string_view, int>& desc,
Args&&... args) & -> optional<typename _result_of<Signature>::type> {
if (auto creator = Get(desc.first, desc.second); creator) {
return creator->Create((Args &&) args...);
} else {
return std::nullopt;
}
}
template <typename... Args>
auto Create(const string_view& name, Args&&... args) & {
return Create(std::pair{name, -1}, (Args &&) args...);
}
Span<CreatorType*> Creators() & {
auto creators = Registry<void>::Creators();
return {reinterpret_cast<CreatorType**>(creators.data()), creators.size()};
}
auto List() & {
std::vector<std::pair<string_view, int>> list;
for (const auto& creator : Creators()) {
list.emplace_back(creator->name(), creator->version());
}
return list;
}
};
template <typename Tag>
auto gRegistry() -> decltype((get_registry(basic_type<Tag>{}))) {
return get_registry(basic_type<Tag>{});
}
template <typename F>
class Registerer {
public:
explicit Registerer(F f) : func_(std::move(f)) { func_(); }
private:
F func_;
};
} // namespace _registry
using _registry::gRegistry;
using _registry::Registerer;
using _registry::Registry;
template <typename Tag>
using Creator = _registry::Creator<_registry::GetSignature<Tag>>;
template <typename Tag>
using SimpleCreator = _registry::SimpleCreator<_registry::GetSignature<Tag>>;
} // namespace mmdeploy
// Specify creator signature for tag
#define MMDEPLOY_CREATOR_SIGNATURE(tag, signature) \
::mmdeploy::basic_type<signature> get_signature(::mmdeploy::basic_type<tag>);
#define MMDEPLOY_DECLARE_REGISTRY(tag, signature) \
MMDEPLOY_CREATOR_SIGNATURE(tag, signature) \
MMDEPLOY_API ::mmdeploy::Registry<tag>& get_registry(::mmdeploy::basic_type<tag>);
#define MMDEPLOY_DECLARE_REGISTRY_EXPAND(tag, signature) \
MMDEPLOY_CREATOR_SIGNATURE(tag, MMDEPLOY_PP_EXPAND signature) \
MMDEPLOY_API ::mmdeploy::Registry<tag>& get_registry(::mmdeploy::basic_type<tag>);
#define MMDEPLOY_DEFINE_REGISTRY(tag) \
::mmdeploy::Registry<tag>& get_registry(::mmdeploy::basic_type<tag>) { \
static ::mmdeploy::Registry<tag> instance{}; \
return instance; \
}
#define MMDEPLOY_REGISTER_CREATOR(tag, creator_type) \
static ::mmdeploy::Registerer MMDEPLOY_ANONYMOUS_VARIABLE(register_){ \
[creator = creator_type{}]() mutable { ::mmdeploy::gRegistry<tag>().Add(creator); }};
#define MMDEPLOY_CREATOR_DESC(name, version) #name, version
#define MMDEPLOY_REGISTER_FACTORY_FUNC(tag, creator_desc, func) \
static ::mmdeploy::Registerer MMDEPLOY_ANONYMOUS_VARIABLE(register_){ \
[creator = \
::mmdeploy::SimpleCreator<tag>(MMDEPLOY_CREATOR_DESC creator_desc, func)]() mutable { \
::mmdeploy::gRegistry<tag>().Add(creator); \
}};
#endif // MMDEPLOY_REGISTRY_H
// Copyright (c) OpenMMLab. All rights reserved.
#ifndef MMDEPLOY_SRC_CORE_SERIALIZATION_H_
#define MMDEPLOY_SRC_CORE_SERIALIZATION_H_
#include <iostream>
#include <tuple>
#include <type_traits>
#include <utility>
#include "mmdeploy/core/macro.h"
#include "mmdeploy/core/mpl/detected.h"
#include "mmdeploy/core/mpl/type_traits.h"
#include "mmdeploy/core/status_code.h"
namespace mmdeploy {
#define MMDEPLOY_ARCHIVE_NVP(archive, ...) archive(MMDEPLOY_PP_MAP(MMDEPLOY_NVP, __VA_ARGS__))
#define MMDEPLOY_ARCHIVE_MEMBERS(...) \
template <typename Archive> \
void serialize(Archive &archive) { \
MMDEPLOY_ARCHIVE_NVP(archive, __VA_ARGS__); \
}
#define MMDEPLOY_NVP(var) \
::mmdeploy::NamedValue { std::forward_as_tuple(#var, var) }
template <typename NameT, typename ValueT>
class NamedValue {
public:
explicit NamedValue(std::tuple<NameT, ValueT> &&data) : data_(std::move(data)) {}
template <typename Archive>
void serialize(Archive &archive) {
archive.named_value(std::forward<NameT>(std::get<0>(data_)),
std::forward<ValueT>(std::get<1>(data_)));
}
std::tuple<NameT, ValueT> &data() { return data_; }
private:
std::tuple<NameT, ValueT> data_;
};
template <typename T>
struct array_tag {
explicit array_tag(std::size_t size) : size_(size) {}
std::size_t size() const { return size_; }
std::size_t size_;
};
template <typename T>
struct object_tag {};
template <typename T>
using mapped_type_t = typename T::mapped_type;
template <typename T>
using has_mapped_type = detail::is_detected<mapped_type_t, T>;
template <typename T>
using get_size_t = decltype(std::declval<T>().size());
template <typename T>
using has_size = detail::is_detected<get_size_t, T>;
template <typename T>
using reserve_t = decltype(std::declval<T>().reserve(std::size_t{0}));
template <typename T>
using has_reserve = detail::is_detected<reserve_t, T>;
namespace detail {
template <typename Archive, typename T, typename U = uncvref_t<T>,
typename ValueType = typename U::value_type,
std::enable_if_t<!std::is_same_v<U, std::string>, int> = 0>
auto save(Archive &archive, T &&iterable)
-> std::void_t<decltype(iterable.begin(), iterable.end())> {
if constexpr (has_size<T>::value) {
archive.init(array_tag<ValueType>(iterable.size()));
}
for (auto &&x : iterable) {
archive.item(std::forward<decltype(x)>(x));
}
}
template <typename T0, typename T1>
class KeyValue {
public:
explicit KeyValue(std::tuple<T0, T1> &&data) : data_(std::move(data)) {}
template <typename Archive>
void serialize(Archive &archive) {
archive.named_value("key", std::forward<T0>(std::get<0>(data_)));
archive.named_value("value", std::forward<T1>(std::get<1>(data_)));
}
std::tuple<T0, T1> &data() { return data_; }
private:
std::tuple<T0, T1> data_;
};
template <typename Archive, typename T, typename U = uncvref_t<T>,
typename KeyType = typename U::key_type, typename MappedType = typename U::mapped_type,
std::enable_if_t<!std::is_constructible_v<std::string, KeyType>, int> = 0>
auto save(Archive &archive, T &object) -> std::void_t<decltype(object.begin(), object.end())> {
if constexpr (has_size<T>::value) {
// TODO: provide meaningful type info
archive.init(array_tag<void>(object.size()));
}
for (auto &&[k, v] : object) {
archive.item(KeyValue{
std::forward_as_tuple(std::forward<decltype(k)>(k), std::forward<decltype(v)>(v))});
}
}
template <typename Archive, typename T, typename U = uncvref_t<T>,
typename KeyType = typename U::key_type, typename MappedType = typename U::mapped_type,
std::enable_if_t<std::is_constructible_v<std::string, KeyType>, int> = 0>
auto save(Archive &archive, T &object) -> std::void_t<decltype(object.begin(), object.end())> {
if constexpr (has_size<T>::value) {
archive.init(object_tag<MappedType>());
}
for (auto &&[k, v] : object) {
archive.named_value(std::forward<decltype(k)>(k), std::forward<decltype(v)>(v));
}
}
template <typename Archive, typename T, std::size_t... Is>
void save_tuple_impl(Archive &archive, T &&tuple, std::index_sequence<Is...>) {
(archive.item(std::get<Is>(std::forward<T>(tuple))), ...);
}
template <typename Archive, typename... Ts>
void save(Archive &archive, const std::tuple<Ts...> &tuple) {
save_tuple_impl(archive, tuple, std::index_sequence_for<Ts...>{});
}
template <typename Archive, typename T, size_t... Is>
void load_tuple_impl(Archive &archive, T &tuple, std::index_sequence<Is...>) {
(archive.item(std::get<Is>(tuple)), ...);
}
template <typename Archive, typename T, std::size_t N>
void save(Archive &archive, T (&v)[N]) {
archive.init(array_tag<T>(N));
for (std::size_t i = 0; i < N; ++i) {
archive.item(v[i]);
}
}
template <typename Archive, typename... Ts>
void load(Archive &archive, std::tuple<Ts...> &tuple) {
std::size_t size{};
archive.init(size);
if (size != sizeof...(Ts)) {
throw_exception(eShapeMismatch);
}
load_tuple_impl(archive, tuple, std::index_sequence_for<Ts...>{});
}
template <typename Archive, typename T, typename U = uncvref_t<T>,
typename ValueType = typename U::value_type,
std::enable_if_t<!std::is_same_v<U, std::string>, int> = 0>
auto load(Archive &&archive, T &&vec) -> std::void_t<decltype(vec.push_back(ValueType{}))> {
std::size_t size{};
archive.init(size);
vec.clear();
for (std::size_t i = 0; i < size; ++i) {
ValueType v{};
archive.item(v);
vec.push_back(std::move(v));
}
}
template <typename Archive, typename T, std::size_t N>
void load(Archive &archive, std::array<T, N> &v) {
std::size_t size{};
archive.init(size);
for (std::size_t i = 0; i < size; ++i) {
archive.item(v[i]);
}
}
template <typename Archive, typename T, std::size_t N>
void load(Archive &archive, T (&v)[N]) {
std::size_t size{};
archive.init(size);
for (std::size_t i = 0; i < size; ++i) {
archive.item(v[i]);
}
}
template <typename Archive, typename T, typename U = uncvref_t<T>,
typename ValueType = typename U::value_type,
std::enable_if_t<std::conjunction_v<std::is_default_constructible<ValueType>,
std::negation<has_mapped_type<U>>>,
int> = 0>
auto load(Archive &&archive, T &&set)
-> std::void_t<decltype(set.insert(std::declval<ValueType>()))> {
std::size_t size{};
archive.init(size);
for (std::size_t i = 0; i < size; ++i) {
ValueType v{};
archive.item(v);
set.insert(std::move(v));
}
}
template <
typename Archive, typename T, typename U = uncvref_t<T>,
typename KeyType = typename U::key_type, typename MappedType = typename U::mapped_type,
std::enable_if_t<std::conjunction_v<std::negation<std::is_constructible<KeyType, std::string>>,
std::is_default_constructible<KeyType>,
std::is_default_constructible<MappedType>>,
int> = 0>
void load(Archive &&archive, T &&object) {
std::size_t size{};
archive.init(size);
for (std::size_t i = 0; i < size; ++i) {
KeyType key;
MappedType mapped;
archive.item(KeyValue{std::tie(key, mapped)});
object.insert({std::move(key), std::move(mapped)});
};
}
template <typename Archive, typename T, typename U = uncvref_t<T>,
typename KeyType = typename U::key_type, typename MappedType = typename U::mapped_type,
std::enable_if_t<std::conjunction_v<std::is_constructible<KeyType, std::string>,
std::is_default_constructible<MappedType>>,
int> = 0>
void load(Archive &&archive, T &&object) {
std::size_t size{};
archive.init(size);
for (std::size_t i = 0; i < size; ++i) {
std::string name;
MappedType value{};
archive.named_value(name, value);
object.insert({std::move(name), std::move(value)});
}
}
struct save_fn {
template <typename Archive, typename T>
auto operator()(Archive &&a, T &&v) const
-> decltype(save(std::forward<Archive>(a), std::forward<T>(v))) {
return save(std::forward<Archive>(a), std::forward<T>(v));
}
};
struct load_fn {
template <typename Archive, typename T>
auto operator()(Archive &&a, T &&v) const
-> decltype(load(std::forward<Archive>(a), std::forward<T>(v))) {
return load(std::forward<Archive>(a), std::forward<T>(v));
}
};
struct serialize_fn {
template <typename Archive, typename T>
auto operator()(Archive &&a, T &&v) const
-> decltype(serialize(std::forward<Archive>(a), std::forward<T>(v))) {
return serialize(std::forward<Archive>(a), std::forward<T>(v));
}
};
} // namespace detail
namespace {
constexpr inline detail::save_fn save{};
constexpr inline detail::load_fn load{};
constexpr inline detail::serialize_fn serialize{};
} // namespace
template <typename T = void, typename SFINAE = void>
struct adl_serializer;
template <typename, typename>
struct adl_serializer {
template <typename Archive, typename T>
static auto save(Archive &&a, T &&v)
-> decltype(::mmdeploy::save(std::forward<Archive>(a), std::forward<T>(v))) {
::mmdeploy::save(std::forward<Archive>(a), std::forward<T>(v));
}
template <typename Archive, typename T>
static auto load(Archive &&a, T &&v)
-> decltype(::mmdeploy::load(std::forward<Archive>(a), std::forward<T>(v))) {
::mmdeploy::load(std::forward<Archive>(a), std::forward<T>(v));
}
template <typename Archive, typename T>
static auto serialize(Archive &&a, T &&v)
-> decltype(::mmdeploy::serialize(std::forward<Archive>(a), std::forward<T>(v))) {
::mmdeploy::serialize(std::forward<Archive>(a), std::forward<T>(v));
}
};
}; // namespace mmdeploy
#endif // MMDEPLOY_SRC_CORE_SERIALIZATION_H_
// Copyright (c) OpenMMLab. All rights reserved.
#include "mmdeploy/core/status_code.h"
#include "mmdeploy/core/logger.h"
#include "mmdeploy/core/utils/source_location.h"
namespace mmdeploy {
void StatusDomain::_do_throw_exception(
const SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const {
assert(code.domain() == *this);
const auto &c = static_cast<const StatusCode &>(code); // NOLINT
throw SYSTEM_ERROR2_NAMESPACE::status_error(c);
}
using string_ref = SYSTEM_ERROR2_NAMESPACE::status_code_domain::string_ref;
using atomic_refcounted_string_ref =
SYSTEM_ERROR2_NAMESPACE::status_code_domain::atomic_refcounted_string_ref;
string_ref Status::message() const {
std::string ret;
try {
#if MMDEPLOY_STATUS_USE_SOURCE_LOCATION
#if MMDEPLOY_HAS_SOURCE_LOCATION
ret = fmt::format("{} ({}) @ {}:{}", to_string(ec), (int32_t)ec, file, line);
#else
ret = fmt::format("{} ({})", to_string(ec), (int32_t)ec);
#endif
#elif MMDEPLOY_STATUS_USE_STACKTRACE
ret = fmt::format("{} ({}), stacktrace:\n{}", to_string(ec), (int32_t)ec, st.to_string());
#else
ret = fmt::format("{} ({})", to_string(ec), (int32_t)ec);
#endif
} catch (...) {
return string_ref("Failed to retrieve message for status");
}
if (auto p = static_cast<char *>(malloc(ret.size() + 1))) {
memcpy(p, ret.c_str(), ret.size() + 1);
return atomic_refcounted_string_ref(p, ret.size());
} else {
return string_ref("Failed to allocate memory to store error string");
}
}
} // namespace mmdeploy
// Copyright (c) OpenMMLab. All rights reserved.
#ifndef MMDEPLOY_SRC_CORE_STATUS_CODE_H_
#define MMDEPLOY_SRC_CORE_STATUS_CODE_H_
#include <system_error>
#include "mmdeploy/core/macro.h"
#include "outcome-experimental.hpp"
#if MMDEPLOY_STATUS_USE_SOURCE_LOCATION
#include "mmdeploy/core/utils/source_location.h"
#elif MMDEPLOY_STATUS_USE_STACKTRACE
#include "mmdeploy/core/utils/stacktrace.h"
#endif
namespace mmdeploy {
// clang-format off
enum class ErrorCode: int32_t {
eSuccess = 0,
eInvalidArgument = 1,
eNotSupported = 2,
eOutOfRange = 3,
eOutOfMemory = 4,
eFileNotExist = 5,
eFail = 6,
eShapeMismatch = 7,
eEntryNotFound = 8,
eNotReady = 9,
eUnknown = -1,
};
// clang-format on
#define USING_ERROR_CODE(code) constexpr inline const auto code = ErrorCode::code // NOLINT
// note that eSuccess is not brought to the outer namespace on purpose
USING_ERROR_CODE(eInvalidArgument);
USING_ERROR_CODE(eNotSupported);
USING_ERROR_CODE(eOutOfRange);
USING_ERROR_CODE(eOutOfMemory);
USING_ERROR_CODE(eFileNotExist);
USING_ERROR_CODE(eFail);
USING_ERROR_CODE(eShapeMismatch);
USING_ERROR_CODE(eEntryNotFound);
USING_ERROR_CODE(eNotReady);
USING_ERROR_CODE(eUnknown);
inline const char *to_string(ErrorCode code) {
switch (code) {
case ErrorCode::eSuccess:
return "success";
case ErrorCode::eInvalidArgument:
return "invalid argument";
case ErrorCode::eNotSupported:
return "not supported";
case ErrorCode::eOutOfRange:
return "out of range";
case ErrorCode::eOutOfMemory:
return "out of memory";
case ErrorCode::eFileNotExist:
return "file not exist";
case ErrorCode::eShapeMismatch:
return "shape mismatch";
case ErrorCode::eEntryNotFound:
return "entry not found";
case ErrorCode::eNotReady:
return "not ready";
default:
return "unknown";
}
}
struct MMDEPLOY_API Status {
ErrorCode ec{};
Status() = default;
SYSTEM_ERROR2_NAMESPACE::status_code_domain::string_ref message() const;
bool operator==(const ErrorCode &b) const noexcept { return ec == b; }
#if MMDEPLOY_STATUS_USE_SOURCE_LOCATION
const char *file{""};
int line{};
explicit Status(ErrorCode _ec, SourceLocation location = SourceLocation::current())
: ec(_ec), file(location.file_name()), line(static_cast<int>(location.line())) {}
#elif MMDEPLOY_STATUS_USE_STACKTRACE
Stacktrace st;
explicit Status(ErrorCode _ec, Stacktrace _st = Stacktrace(0)) : ec(_ec), st(std::move(_st)) {}
#else
explicit Status(ErrorCode _ec) : ec(_ec) {}
#endif
};
class StatusDomain;
using StatusCode = SYSTEM_ERROR2_NAMESPACE::status_code<StatusDomain>;
class MMDEPLOY_API StatusDomain : public SYSTEM_ERROR2_NAMESPACE::status_code_domain {
using _base = status_code_domain;
public:
using value_type = Status;
constexpr explicit StatusDomain(typename _base::unique_id_type id = 0x3584b6716049efb4) noexcept
: _base(id) {}
StatusDomain(const StatusDomain &) = default;
StatusDomain(StatusDomain &&) = default;
StatusDomain &operator=(const StatusDomain &) = default;
StatusDomain &operator=(StatusDomain &&) = default;
~StatusDomain() = default;
static inline constexpr const StatusDomain &get();
string_ref name() const noexcept override {
static string_ref v("mmdeploy");
return v;
}
// clang-format off
bool _do_failure(const SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const noexcept override {
assert(code.domain() == *this);
auto &c = static_cast<const StatusCode &>(code); // NOLINT
return c.value().ec != ErrorCode::eSuccess;
}
bool _do_equivalent(
const SYSTEM_ERROR2_NAMESPACE::status_code<void> &code1,
const SYSTEM_ERROR2_NAMESPACE::status_code<void> &code2) const noexcept override {
assert(code1.domain() == *this);
if (code1.domain() == *this && code2.domain() == *this) {
auto &c1 = static_cast<const StatusCode &>(code1); // NOLINT
auto &c2 = static_cast<const StatusCode &>(code2); // NOLINT
return c1.value().ec == c2.value().ec;
}
return false;
}
SYSTEM_ERROR2_NAMESPACE::generic_code _generic_code(
const SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const noexcept override {
assert(code.domain() == *this);
return SYSTEM_ERROR2_NAMESPACE::errc::unknown;
}
string_ref _do_message(
const SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const noexcept override {
assert(code.domain() == *this);
auto &c = static_cast<const StatusCode &>(code); // NOLINT
return c.value().message();
}
// clang-format on
void _do_throw_exception(const SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const override;
};
constexpr inline StatusDomain status_domain;
inline constexpr const StatusDomain &StatusDomain::get() { return status_domain; }
inline StatusCode make_status_code(StatusCode::value_type v) {
return StatusCode(SYSTEM_ERROR2_NAMESPACE::in_place, static_cast<StatusCode::value_type &&>(v));
}
using OUTCOME_V2_NAMESPACE::failure;
using OUTCOME_V2_NAMESPACE::in_place_type;
using OUTCOME_V2_NAMESPACE::success;
inline bool operator==(const StatusCode &sc, ErrorCode ec) noexcept { return sc.value().ec == ec; }
inline bool operator==(ErrorCode ec, const StatusCode &sc) noexcept { return sc.value().ec == ec; }
using Error = SYSTEM_ERROR2_NAMESPACE::errored_status_code<StatusDomain>;
using Exception = SYSTEM_ERROR2_NAMESPACE::status_error<StatusDomain>;
template <typename T>
struct Result : OUTCOME_V2_NAMESPACE::experimental::status_result<T, Error> {
using OUTCOME_V2_NAMESPACE::experimental::status_result<T, Error>::status_result;
};
#if MMDEPLOY_STATUS_USE_SOURCE_LOCATION
[[noreturn]] inline void throw_exception(ErrorCode ec,
SourceLocation location = SourceLocation::current()) {
Error(Status(ec, location)).throw_exception();
}
#elif MMDEPLOY_STATUS_USE_STACKTRACE
[[noreturn]] inline void throw_exception(ErrorCode ec, Stacktrace stacktrace = Stacktrace(0)) {
Error(Status(ec, std::move(stacktrace))).throw_exception();
}
#else
[[noreturn]] inline void throw_exception(const ErrorCode ec) {
Error(Status(ec)).throw_exception();
}
#endif
template <typename T>
struct is_result : std::false_type {};
template <typename T>
struct is_result<Result<T>> : std::true_type {};
template <typename T>
inline constexpr bool is_result_v = is_result<T>::value;
} // namespace mmdeploy
#endif // MMDEPLOY_SRC_CORE_STATUS_CODE_H_
// Copyright (c) OpenMMLab. All rights reserved.
#include "tensor.h"
#include <algorithm>
#include <numeric>
#include <sstream>
#include "mmdeploy/core/logger.h"
#include "mmdeploy/core/utils/formatter.h"
using std::stringstream;
namespace mmdeploy::framework {
static inline int64_t element_size(DataType data_type) {
switch (data_type) {
case DataType::kFLOAT:
return 4;
case DataType::kHALF:
return 2;
case DataType::kINT8:
return 1;
case DataType::kINT32:
return 4;
case DataType::kINT64:
return 8;
default:
return 0;
}
}
inline static std::string shape_string(const TensorShape& shape) {
if (shape.empty()) {
return "0";
}
stringstream ss;
ss << shape[0];
for (size_t i = 1; i < shape.size(); ++i) ss << "," << shape[i];
return ss.str();
}
Tensor::Tensor(const TensorDesc& desc, Allocator allocator)
: desc_(desc), allocator_(std::move(allocator)) {
buffer_ = Buffer(desc.device, byte_size(), allocator_);
}
Tensor::Tensor(const TensorDesc& desc, Buffer buffer) // NOLINT
: desc_(desc), buffer_(std::move(buffer)) {}
Tensor::Tensor(const TensorDesc& desc, std::shared_ptr<void> data) {
desc_ = desc;
buffer_ = Buffer(desc.device, byte_size(), std::move(data));
}
static inline int64_t get_size(const std::vector<int64_t>& shape) {
if (shape.empty()) {
return 0;
}
auto _size = std::accumulate(begin(shape), end(shape), 1LL, std::multiplies<>());
return std::max(0LL, _size);
}
int64_t Tensor::size() const { return get_size(shape()); }
int64_t Tensor::byte_size() const { return size() * element_size(data_type()); }
const TensorDesc& Tensor::desc() const { return desc_; }
const TensorShape& Tensor::shape() const { return desc_.shape; }
DataType Tensor::data_type() const { return desc_.data_type; }
const char* Tensor::name() const { return desc_.name.c_str(); }
const Buffer& Tensor::buffer() const { return buffer_; }
Buffer& Tensor::buffer() {
Allocate();
return buffer_;
}
Device Tensor::device() const { return desc_.device; }
void Tensor::Reshape(const TensorShape& shape) {
bool is_same_size = size() == get_size(shape);
desc_.shape = shape;
if (buffer_ && !is_same_size) {
// re-allocate buffer
buffer_ = {};
Allocate();
}
}
void Tensor::Squeeze() {
desc_.shape.erase(std::remove(desc_.shape.begin(), desc_.shape.end(), 1), desc_.shape.end());
}
void Tensor::Squeeze(int dim) {
if (shape(dim) == 1) {
desc_.shape.erase(desc_.shape.begin() + dim);
}
}
Result<void> Tensor::CopyFrom(const Tensor& tensor, Stream stream) {
if (desc_.shape.empty() || tensor.desc().shape.empty()) {
MMDEPLOY_ERROR("uninitialized tensor");
return Status(eInvalidArgument);
}
if (!(desc_.shape == tensor.desc().shape)) {
MMDEPLOY_ERROR("mismatched shape {} vs {}", shape_string(desc_.shape),
shape_string(tensor.desc().shape));
return Status(eShapeMismatch);
}
if (desc_.data_type != tensor.desc().data_type) {
MMDEPLOY_ERROR("mismatched data type {} vs {}", desc_.data_type, tensor.desc().data_type);
return Status(eShapeMismatch);
}
Allocate();
if (!stream) {
auto device = desc_.device.is_device() ? desc_.device : tensor.desc().device;
auto default_stream = Stream::GetDefault(device);
OUTCOME_TRY(default_stream.Copy(tensor.buffer(), buffer_, tensor.byte_size()));
} else {
OUTCOME_TRY(stream.Copy(tensor.buffer(), buffer_, tensor.byte_size()));
}
return success();
}
Result<void> Tensor::CopyTo(Tensor& tensor, Stream stream) const {
if (desc_.shape.empty() || tensor.desc().shape.empty()) {
MMDEPLOY_ERROR("uninitialized tensor");
return Status(eInvalidArgument);
}
if (!(desc_.shape == tensor.desc().shape)) {
MMDEPLOY_ERROR("mismatched shape {} vs {}", shape_string(desc_.shape),
shape_string(tensor.desc().shape));
return Status(eShapeMismatch);
}
if (desc_.data_type != tensor.desc().data_type) {
MMDEPLOY_ERROR("mismatched data type {} vs {}", desc_.data_type, tensor.desc().data_type);
return Status(eShapeMismatch);
}
tensor.Allocate();
if (!stream) {
Device device = desc_.device.is_device() ? desc_.device : tensor.desc().device;
Stream default_stream = Stream::GetDefault(device);
return default_stream.Copy(buffer_, tensor.buffer(), byte_size());
} else {
return stream.Copy(buffer_, tensor.buffer(), byte_size());
}
}
Result<void> Tensor::CopyFrom(void* host_ptr, Stream stream) {
if (nullptr == host_ptr) {
return Status(eInvalidArgument);
}
if (desc_.shape.empty()) {
MMDEPLOY_ERROR("uninitialized tensor");
return Status(eInvalidArgument);
}
Allocate();
if (!stream) {
auto default_stream = Stream::GetDefault(desc_.device);
return default_stream.Copy(host_ptr, buffer_, byte_size());
} else {
return stream.Copy(host_ptr, buffer_, byte_size());
}
}
Result<void> Tensor::CopyTo(void* host_ptr, Stream stream) const {
if (nullptr == host_ptr) {
return Status(eInvalidArgument);
}
if (desc_.shape.empty()) {
MMDEPLOY_ERROR("uninitialized tensor");
return Status(eInvalidArgument);
}
if (!stream) {
auto default_stream = Stream::GetDefault(desc_.device);
return default_stream.Copy(buffer_, host_ptr, byte_size());
} else {
return stream.Copy(buffer_, host_ptr, byte_size());
}
}
void Tensor::Allocate() {
if (!buffer_) {
auto _desc = desc();
*this = Tensor(_desc, allocator_);
}
}
Tensor Tensor::Slice(int start, int end) {
Tensor slice = *this;
slice.desc_.shape[0] = 1;
auto bytes = element_size(desc_.data_type) * get_size(slice.desc_.shape);
slice.desc_.shape[0] = end - start;
slice.buffer_ = Buffer(buffer(), start * bytes, (end - start) * bytes);
return slice;
}
TensorShape::value_type Tensor::shape(int dim) const { return desc().shape[dim]; }
} // namespace mmdeploy::framework
// Copyright (c) OpenMMLab. All rights reserved.
#ifndef CORE_TENSOR_H
#define CORE_TENSOR_H
#include <string>
#include <vector>
#include "mmdeploy/core/device.h"
#include "mmdeploy/core/types.h"
namespace mmdeploy {
namespace framework {
using TensorShape = std::vector<int64_t>;
struct TensorDesc {
Device device;
DataType data_type{DataType::kFLOAT};
TensorShape shape;
std::string name;
};
class MMDEPLOY_API Tensor {
public:
Tensor() = default;
Tensor(const Tensor&) = default;
Tensor(Tensor&&) noexcept = default;
Tensor& operator=(const Tensor&) = default;
Tensor& operator=(Tensor&&) noexcept = default;
Tensor(const TensorDesc& desc, Allocator allocator = {}); // NOLINT
Tensor(const TensorDesc& desc, Buffer buffer);
Tensor(const TensorDesc& desc, std::shared_ptr<void> data);
~Tensor() = default;
const TensorDesc& desc() const;
const TensorShape& shape() const;
TensorShape::value_type shape(int dim) const;
DataType data_type() const;
const char* name() const;
int64_t size() const;
int64_t byte_size() const;
const Buffer& buffer() const;
Buffer& buffer();
Device device() const;
void Reshape(const TensorShape& shape);
void Squeeze();
void Squeeze(int dim);
Tensor Slice(int start, int end);
Tensor Slice(int index) { return Slice(index, index + 1); }
Result<void> CopyFrom(const Tensor& tensor, Stream stream = {});
Result<void> CopyTo(Tensor& tensor, Stream stream = {}) const;
Result<void> CopyFrom(void* host_ptr, Stream stream = {});
Result<void> CopyTo(void* host_ptr, Stream stream = {}) const;
Allocator allocator() { return allocator_; }
template <typename T = void>
T* data() {
return GetNative<T*>(buffer());
}
template <typename T = void, typename U = std::add_const_t<T> >
U* data() const {
return GetNative<U*>(buffer());
}
private:
void Allocate();
TensorDesc desc_;
Allocator allocator_;
Buffer buffer_;
};
// static_assert(sizeof(Tensor) == 80);
} // namespace framework
MMDEPLOY_REGISTER_TYPE_ID(framework::Tensor, 6);
} // namespace mmdeploy
#endif // !CORE_TENSOR_H
// Copyright (c) OpenMMLab. All rights reserved.
#ifndef CORE_TYPES_H
#define CORE_TYPES_H
#include <cstdint>
typedef int err_t;
namespace mmdeploy {
// clang-format off
enum class PixelFormat : int32_t {
kBGR,
kRGB,
kGRAYSCALE,
kNV12,
kNV21,
kBGRA,
kCOUNT
};
enum class DataType : int32_t {
kFLOAT,
kHALF,
kINT8,
kINT32,
kINT64,
kCOUNT
};
// clang-format on
namespace pixel_formats {
constexpr auto kBGR = PixelFormat::kBGR;
constexpr auto kRGB = PixelFormat::kRGB;
constexpr auto kGRAY = PixelFormat::kGRAYSCALE;
constexpr auto kNV12 = PixelFormat::kNV12;
constexpr auto kNV21 = PixelFormat::kNV21;
constexpr auto kBGRA = PixelFormat::kBGRA;
} // namespace pixel_formats
namespace data_types {
constexpr auto kFLOAT = DataType::kFLOAT;
constexpr auto kHALF = DataType::kHALF;
constexpr auto kINT8 = DataType::kINT8;
constexpr auto kINT32 = DataType::kINT32;
constexpr auto kINT64 = DataType::kINT64;
} // namespace data_types
class NonCopyable {
public:
NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator=(const NonCopyable&) = delete;
};
class NonMovable {
public:
NonMovable() = default;
NonMovable(const NonCopyable&) = delete;
NonMovable& operator=(const NonCopyable&) = delete;
NonMovable(NonMovable&&) noexcept = delete;
NonMovable& operator=(NonMovable&&) noexcept = delete;
};
} // namespace mmdeploy
#endif // !CORE_TYPES_H
// Copyright (c) OpenMMLab. All rights reserved.
#include "mmdeploy/core/utils/device_utils.h"
#include "mmdeploy/core/logger.h"
namespace mmdeploy::framework {
Result<Mat> MakeAvailableOnDevice(const Mat& src, const Device& device, Stream& stream) {
if (src.device() == device) {
return src;
}
Mat dst{src.height(), src.width(), src.pixel_format(), src.type(), device};
OUTCOME_TRY(stream.Copy(src.buffer(), dst.buffer(), dst.byte_size()));
// ! When the target device is different from stream's device (e.g. DtoH), insert a sync op as
// computation on dst won't be synchronized with stream
if (device != stream.GetDevice()) {
OUTCOME_TRY(stream.Wait());
}
return dst;
}
Result<Tensor> MakeAvailableOnDevice(const Tensor& src, const Device& device, Stream& stream) {
if (src.device() == device) {
return src;
}
TensorDesc desc{device, src.data_type(), src.shape(), src.name()};
Tensor dst(desc);
OUTCOME_TRY(stream.Copy(src.buffer(), dst.buffer(), src.byte_size()));
// ! When the target device is different from stream's device (e.g. DtoH), insert a sync op as
// computation on dst won't be synchronized with stream
if (device != stream.GetDevice()) {
OUTCOME_TRY(stream.Wait());
}
return dst;
}
} // namespace mmdeploy::framework
// Copyright (c) OpenMMLab. All rights reserved.
#ifndef MMDEPLOY_TRANSFORM_UTILS_H
#define MMDEPLOY_TRANSFORM_UTILS_H
#include <utility>
#include "mmdeploy/core/mat.h"
#include "mmdeploy/core/tensor.h"
namespace mmdeploy::framework {
/**
*
* @param src
* @param device
* @param stream
* @return
*/
MMDEPLOY_API Result<Mat> MakeAvailableOnDevice(const Mat& src, const Device& device,
Stream& stream);
/**
*
* @param src
* @param device
* @param stream
* @return
*/
MMDEPLOY_API Result<Tensor> MakeAvailableOnDevice(const Tensor& src, const Device& device,
Stream& stream);
} // namespace mmdeploy::framework
#endif // MMDEPLOY_TRANSFORM_UTILS_H
// Copyright (c) OpenMMLab. All rights reserved.
#ifndef MMDEPLOY_CSRC_CORE_UTILS_FILESYSTEM_H_
#define MMDEPLOY_CSRC_CORE_UTILS_FILESYSTEM_H_
#if __GNUC__ >= 8 || _MSC_VER || __clang_major__ >= 7
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif
#endif // MMDEPLOY_CSRC_CORE_UTILS_FILESYSTEM_H_
// Copyright (c) OpenMMLab. All rights reserved.
#include "mmdeploy/core/utils/formatter.h"
#include "mmdeploy/archive/json_archive.h"
#include "mmdeploy/core/value.h"
namespace mmdeploy {
std::string format_value(const Value& value) { return mmdeploy::to_json(value).dump(2); }
} // namespace mmdeploy
// Copyright (c) OpenMMLab. All rights reserved.
#ifndef MMDEPLOY_SRC_UTILS_FORMATTER_H_
#define MMDEPLOY_SRC_UTILS_FORMATTER_H_
#include <ostream>
#include <utility>
#include "mmdeploy/core/logger.h"
#include "mmdeploy/core/types.h"
#include "spdlog/fmt/ostr.h"
#if FMT_VERSION >= 50000
#include "spdlog/fmt/bundled/ostream.h"
#include "spdlog/fmt/bundled/ranges.h"
#else
#include <type_traits>
#endif
namespace mmdeploy {
class Value;
MMDEPLOY_API std::string format_value(const Value& value);
inline std::string to_string(PixelFormat format) {
switch (format) {
case PixelFormat::kBGR:
return "BGR";
case PixelFormat::kRGB:
return "RGB";
case PixelFormat::kGRAYSCALE:
return "GRAYSCALE";
case PixelFormat::kNV12:
return "NV12";
case PixelFormat::kNV21:
return "NV21";
case PixelFormat::kBGRA:
return "BGRA";
default:
return "invalid_format_enum";
}
}
inline std::string to_string(DataType type) {
switch (type) {
case DataType::kFLOAT:
return "FLOAT";
case DataType::kHALF:
return "HALF";
case DataType::kINT8:
return "INT8";
case DataType::kINT32:
return "INT32";
case DataType::kINT64:
return "INT64";
default:
return "invalid_data_type_enum";
}
}
inline std::ostream& operator<<(std::ostream& os, PixelFormat format) {
return os << to_string(format);
}
inline std::ostream& operator<<(std::ostream& os, DataType type) { return os << to_string(type); }
} // namespace mmdeploy
namespace fmt {
#if FMT_VERSION >= 50000
// `Value` maybe an incomplete type at this point, making `operator<<` not usable
template <>
struct formatter<mmdeploy::Value> {
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
template <typename Context>
auto format(const mmdeploy::Value& value, Context& ctx) {
return format_to(ctx.out(), "{}", mmdeploy::format_value(value));
}
};
#else
inline void format_arg(BasicFormatter<char>& f, const char*, const mmdeploy::Value& d) {
f.writer() << mmdeploy::format_value(d);
}
template <typename T>
auto format_arg(BasicFormatter<char>& f, const char*, const T& v)
-> std::void_t<decltype(begin(v), end(v))> {
f.writer() << "[";
bool first = true;
for (const auto& x : v) {
f.writer() << (first ? "" : ", ") << fmt::format("{}", x);
first = false;
}
f.writer() << "]";
}
template <class Tuple, size_t... Is>
void format_tuple_impl(BasicFormatter<char>& f, const Tuple& t, std::index_sequence<Is...>) {
constexpr int last = sizeof...(Is) - 1;
f.writer() << "(";
((f.writer() << fmt::format("{}", std::get<Is>(t)) << (Is != last ? ", " : "")), ...);
f.writer() << ")";
}
template <typename... Ts>
void format_arg(BasicFormatter<char>& f, const char*, const std::tuple<Ts...>& t) {
format_tuple_impl(f, t, std::index_sequence_for<Ts...>{});
}
#endif
} // namespace fmt
#endif // MMDEPLOY_SRC_UTILS_FORMATTER_H_
// Copyright (c) OpenMMLab. All rights reserved.
#ifndef MMDEPLOY_SRC_UTILS_SOURCE_LOCATION_H_
#define MMDEPLOY_SRC_UTILS_SOURCE_LOCATION_H_
// clang-format off
#if __has_include(<source_location>) && (!_MSC_VER || __cplusplus >= 202002L)
#include <source_location>
#if __cpp_lib_source_location >= 201907L
#define MMDEPLOY_HAS_SOURCE_LOCATION 1
namespace mmdeploy {
using SourceLocation = std::source_location;
}
#endif
#endif
#ifndef MMDEPLOY_HAS_SOURCE_LOCATION
#if __has_include(<experimental/source_location>)
#include <experimental/source_location>
#if __cpp_lib_experimental_source_location >= 201505L
#define MMDEPLOY_HAS_SOURCE_LOCATION 1
namespace mmdeploy {
using SourceLocation = std::experimental::source_location;
}
#endif
#endif
#endif
// clang-format on
#ifndef MMDEPLOY_HAS_SOURCE_LOCATION
#include <cstdint>
namespace mmdeploy {
class SourceLocation {
public:
constexpr SourceLocation() noexcept = default;
SourceLocation(const SourceLocation&) = default;
SourceLocation(SourceLocation&&) noexcept = default;
constexpr std::uint_least32_t line() const noexcept { return 0; };
constexpr std::uint_least32_t column() const noexcept { return 0; }
constexpr const char* file_name() const noexcept { return ""; }
constexpr const char* function_name() const noexcept { return ""; }
static constexpr SourceLocation current() noexcept { return {}; }
};
} // namespace mmdeploy
#endif
#endif // MMDEPLOY_SRC_UTILS_SOURCE_LOCATION_H_
// Copyright (c) OpenMMLab. All rights reserved.
#include "mmdeploy/core/utils/stacktrace.h"
#if MMDEPLOY_STATUS_USE_STACKTRACE
#define BOOST_STACKTRACE_USE_BACKTRACE
#include "boost/stacktrace.hpp"
namespace mmdeploy {
struct Stacktrace::Impl {
boost::stacktrace::stacktrace st_;
};
Stacktrace::~Stacktrace() = default;
Stacktrace::Stacktrace(int)
: impl_(new Impl{boost::stacktrace::stacktrace(1, static_cast<std::size_t>(-1))}) {}
Stacktrace::Stacktrace() noexcept = default;
Stacktrace::Stacktrace(const Stacktrace& other) : impl_(std::make_unique<Impl>(*other.impl_)) {}
Stacktrace::Stacktrace(Stacktrace&& other) noexcept : impl_(std::move(other.impl_)) {}
Stacktrace& Stacktrace::operator=(Stacktrace&& other) noexcept {
impl_ = std::move(other.impl_);
return *this;
}
Stacktrace& Stacktrace::operator=(const Stacktrace& other) {
impl_ = std::make_unique<Impl>(*other.impl_);
return *this;
}
std::string Stacktrace::to_string() const {
if (impl_) {
return boost::stacktrace::to_string(impl_->st_);
}
return "";
}
} // namespace mmdeploy
#else
#include <string>
namespace mmdeploy {
struct Stacktrace::Impl {};
Stacktrace::~Stacktrace() = default;
Stacktrace::Stacktrace(int) {}
Stacktrace::Stacktrace() noexcept = default;
Stacktrace::Stacktrace(const Stacktrace&) {}
Stacktrace::Stacktrace(Stacktrace&&) noexcept {}
Stacktrace& Stacktrace::operator=(Stacktrace&&) noexcept { return *this; }
Stacktrace& Stacktrace::operator=(const Stacktrace&) { return *this; }
std::string Stacktrace::to_string() const {
return "the library is compiled with no stacktrace support";
}
} // namespace mmdeploy
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment