Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@ inline std::vector<std::string> Session::GetInputNames() const {
size_t node_count = GetInputCount();
std::vector<std::string> out(node_count);
for (size_t i = 0; i < node_count; i++) {
char* tmp = GetInputName(i, allocator);
out[i] = tmp;
allocator.Free(tmp); // prevent memory leak
auto tmp = GetInputNameAllocated(i, allocator);
out[i] = tmp.get();
}
return out;
}
Expand All @@ -47,9 +46,8 @@ inline std::vector<std::string> Session::GetOutputNames() const {
size_t node_count = GetOutputCount();
std::vector<std::string> out(node_count);
for (size_t i = 0; i < node_count; i++) {
char* tmp = GetOutputName(i, allocator);
out[i] = tmp;
allocator.Free(tmp); // prevent memory leak
auto tmp = GetOutputNameAllocated(i, allocator);
out[i] = tmp.get();
}
return out;
}
Expand All @@ -59,9 +57,8 @@ inline std::vector<std::string> Session::GetOverridableInitializerNames() const
size_t init_count = GetOverridableInitializerCount();
std::vector<std::string> out(init_count);
for (size_t i = 0; i < init_count; i++) {
char* tmp = GetOverridableInitializerName(i, allocator);
out[i] = tmp;
allocator.Free(tmp); // prevent memory leak
auto tmp = GetOverridableInitializerNameAllocated(i, allocator);
out[i] = tmp.get();
}
return out;
}
Expand Down
69 changes: 69 additions & 0 deletions include/onnxruntime/core/session/onnxruntime_cxx_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,16 @@ struct TypeInfo;
struct Value;
struct ModelMetadata;

// Light functor to release memory with OrtAllocator
namespace detail {
struct AllocatedFree {
OrtAllocator* allocator_;
explicit AllocatedFree(OrtAllocator* allocator)
: allocator_(allocator) {}
void operator()(void* ptr) const { allocator_->Free(allocator_, ptr); }
};
} // namespace detail

/** \brief The Env (Environment)
*
* The Env holds the logging state used by all other objects.
Expand Down Expand Up @@ -436,10 +446,69 @@ struct Session : Base<OrtSession> {
size_t GetOutputCount() const; ///< Returns the number of model outputs
size_t GetOverridableInitializerCount() const; ///< Returns the number of inputs that have defaults that can be overridden

/** \deprecated use GetInputNameAllocated()
* [[deprecated]]
* This interface produces a pointer that must be released
* by the specified allocator and is often leaked. Not exception safe.
*/
char* GetInputName(size_t index, OrtAllocator* allocator) const; ///< Wraps OrtApi::SessionGetInputName
/** \deprecated use GetOutputNameAllocated()
* [[deprecated]]
* This interface produces a pointer that must be released
* by the specified allocator and is often leaked. Not exception safe.
*/
char* GetOutputName(size_t index, OrtAllocator* allocator) const; ///< Wraps OrtApi::SessionGetOutputName

using AllocatedStringPtr = std::unique_ptr<char, detail::AllocatedFree>;

/** \brief Returns a copy of input name at the specified index. Replaces GetInputName().
*
* \param index must less than the value returned by GetInputCount()
* \param allocator to allocate memory for the copy of the name returned
* \return a instance of smart pointer that would deallocate the buffer when out of scope.
* The OrtAllocator instances must be valid at the point of memory release.
*/
AllocatedStringPtr GetInputNameAllocated(size_t index, OrtAllocator* allocator) const;

/** \brief Returns a copy of output name at then specified index.
*
* \param index must less than the value returned by GetOutputCount()
* \param allocator to allocate memory for the copy of the name returned
* \return a instance of smart pointer that would deallocate the buffer when out of scope.
* The OrtAllocator instances must be valid at the point of memory release.
*/
AllocatedStringPtr GetOutputNameAllocated(size_t index, OrtAllocator* allocator) const;

/** \deprecated use GetOverridableInitializerNameAllocated()
* [[deprecated]]
* This interface produces a pointer that must be released
* by the specified allocator and is often leaked. Not exception safe.
*/
char* GetOverridableInitializerName(size_t index, OrtAllocator* allocator) const; ///< Wraps OrtApi::SessionGetOverridableInitializerName

/** \brief Returns a copy of the overridable initializer name at then specified index.
*
* \param index must less than the value returned by GetOverridableInitializerCount()
* \param allocator to allocate memory for the copy of the name returned
* \return a instance of smart pointer that would deallocate the buffer when out of scope.
* The OrtAllocator instances must be valid at the point of memory release.
*/
AllocatedStringPtr GetOverridableInitializerNameAllocated(size_t index, OrtAllocator* allocator) const; ///< Wraps OrtApi::SessionGetOverridableInitializerName

/** \deprecated use EndProfilingAllocated()
* [[deprecated]]
* This interface produces a pointer that must be released
* by the specified allocator and is often leaked. Not exception safe.
*/
char* EndProfiling(OrtAllocator* allocator) const; ///< Wraps OrtApi::SessionEndProfiling

/** \brief Returns a copy of the profiling file name.
*
* \param allocator to allocate memory for the copy of the string returned
* \return a instance of smart pointer that would deallocate the buffer when out of scope.
* The OrtAllocator instances must be valid at the point of memory release.
*/
AllocatedStringPtr EndProfilingAllocated(OrtAllocator* allocator) const; ///< Wraps OrtApi::SessionEndProfiling
uint64_t GetProfilingStartTimeNs() const; ///< Wraps OrtApi::SessionGetProfilingStartTimeNs
ModelMetadata GetModelMetadata() const; ///< Wraps OrtApi::SessionGetModelMetadata

Expand Down
24 changes: 24 additions & 0 deletions include/onnxruntime/core/session/onnxruntime_cxx_inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -656,18 +656,42 @@ inline char* Session::GetOutputName(size_t index, OrtAllocator* allocator) const
return out;
}

inline Session::AllocatedStringPtr Session::GetInputNameAllocated(size_t index, OrtAllocator* allocator) const {
char* out;
ThrowOnError(GetApi().SessionGetInputName(p_, index, allocator, &out));
return AllocatedStringPtr(out, detail::AllocatedFree(allocator));
}

inline Session::AllocatedStringPtr Session::GetOutputNameAllocated(size_t index, OrtAllocator* allocator) const {
char* out;
ThrowOnError(GetApi().SessionGetOutputName(p_, index, allocator, &out));
return AllocatedStringPtr(out, detail::AllocatedFree(allocator));
}

inline char* Session::GetOverridableInitializerName(size_t index, OrtAllocator* allocator) const {
char* out;
ThrowOnError(GetApi().SessionGetOverridableInitializerName(p_, index, allocator, &out));
return out;
}

inline Session::AllocatedStringPtr Session::GetOverridableInitializerNameAllocated(size_t index, OrtAllocator* allocator) const {
char* out;
ThrowOnError(GetApi().SessionGetOverridableInitializerName(p_, index, allocator, &out));
return AllocatedStringPtr(out, detail::AllocatedFree(allocator));
}

inline char* Session::EndProfiling(OrtAllocator* allocator) const {
char* out;
ThrowOnError(GetApi().SessionEndProfiling(p_, allocator, &out));
return out;
}

inline Session::AllocatedStringPtr Session::EndProfilingAllocated(OrtAllocator* allocator) const {
char* out;
ThrowOnError(GetApi().SessionEndProfiling(p_, allocator, &out));
return AllocatedStringPtr(out, detail::AllocatedFree(allocator));
}

inline uint64_t Session::GetProfilingStartTimeNs() const {
uint64_t out;
ThrowOnError(GetApi().SessionGetProfilingStartTimeNs(p_, &out));
Expand Down
5 changes: 2 additions & 3 deletions onnxruntime/test/onnx/dataitem_request.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,9 @@ std::pair<EXECUTE_RESULT, TIME_SPEC> DataTaskRequestContext::RunImpl() {
size_t output_count = session_.GetOutputCount();
std::vector<std::string> output_names(output_count);
for (size_t i = 0; i != output_count; ++i) {
char* output_name = session_.GetOutputName(i, default_allocator_);
auto output_name = session_.GetOutputNameAllocated(i, default_allocator_);
assert(output_name != nullptr);
output_names[i] = output_name;
Ort::ThrowOnError(Ort::GetApi().AllocatorFree(default_allocator_, output_name));
output_names[i] = output_name.get();
}

TIME_SPEC start_time;
Expand Down
8 changes: 4 additions & 4 deletions onnxruntime/test/opaque_api/test_opaque_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,14 @@ TEST(OpaqueApiTest, RunModelWithOpaqueInputOutput) {
// Expecting one input
size_t num_input_nodes = session.GetInputCount();
EXPECT_EQ(num_input_nodes, 1U);
const char* input_name = session.GetInputName(0, allocator);
auto input_name = session.GetInputNameAllocated(0, allocator);

size_t num_output_nodes = session.GetOutputCount();
EXPECT_EQ(num_output_nodes, 1U);
const char* output_name = session.GetOutputName(0, allocator);
auto output_name = session.GetOutputNameAllocated(0, allocator);

const char* const input_names[] = {input_name};
const char* const output_names[] = {output_name};
const char* const input_names[] = {input_name.get()};
const char* const output_names[] = {output_name.get()};

// Input
const std::string input_string{"hi, hello, high, highest"};
Expand Down
5 changes: 2 additions & 3 deletions onnxruntime/test/perftest/ort_test_session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -529,10 +529,9 @@ select from 'TF8', 'TF16', 'UINT8', 'FLOAT', 'ITENSOR'. \n)");
output_names_.resize(output_count);
Ort::AllocatorWithDefaultOptions a;
for (size_t i = 0; i != output_count; ++i) {
char* output_name = session_.GetOutputName(i, a);
auto output_name = session_.GetOutputNameAllocated(i, a);
assert(output_name != nullptr);
output_names_[i] = output_name;
a.Free(output_name);
output_names_[i] = output_name.get();
}
output_names_raw_ptr.resize(output_count);
for (size_t i = 0; i != output_count; ++i) {
Expand Down
22 changes: 12 additions & 10 deletions onnxruntime/test/shared_lib/test_inference.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1422,9 +1422,10 @@ TEST(CApiTest, override_initializer) {
size_t init_count = session.GetOverridableInitializerCount();
ASSERT_EQ(init_count, 1U);

char* f1_init_name = session.GetOverridableInitializerName(0, allocator.get());
ASSERT_TRUE(strcmp("F1", f1_init_name) == 0);
allocator->Free(f1_init_name);
{
auto f1_init_name = session.GetOverridableInitializerNameAllocated(0, allocator.get());
ASSERT_TRUE(strcmp("F1", f1_init_name.get()) == 0);
}

Ort::TypeInfo init_type_info = session.GetOverridableInitializerTypeInfo(0);
ASSERT_EQ(ONNX_TYPE_TENSOR, init_type_info.GetONNXType());
Expand Down Expand Up @@ -1466,10 +1467,10 @@ TEST(CApiTest, end_profiling) {
session_options_1.EnableProfiling("profile_prefix");
#endif
Ort::Session session_1(*ort_env, MODEL_WITH_CUSTOM_MODEL_METADATA, session_options_1);
char* profile_file = session_1.EndProfiling(allocator.get());

ASSERT_TRUE(std::string(profile_file).find("profile_prefix") != std::string::npos);
allocator->Free(profile_file);
{
auto profile_file = session_1.EndProfilingAllocated(allocator.get());
ASSERT_TRUE(std::string(profile_file.get()).find("profile_prefix") != std::string::npos);
}
// Create session with profiling disabled
Ort::SessionOptions session_options_2;
#ifdef _WIN32
Expand All @@ -1478,9 +1479,10 @@ TEST(CApiTest, end_profiling) {
session_options_2.DisableProfiling();
#endif
Ort::Session session_2(*ort_env, MODEL_WITH_CUSTOM_MODEL_METADATA, session_options_2);
profile_file = session_2.EndProfiling(allocator.get());
ASSERT_TRUE(std::string(profile_file) == std::string());
allocator->Free(profile_file);
{
auto profile_file = session_2.EndProfilingAllocated(allocator.get());
ASSERT_TRUE(std::string(profile_file.get()) == std::string());
}
}

TEST(CApiTest, get_profiling_start_time) {
Expand Down