Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions backends/samsung/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ if(${ANDROID})
enn_backend
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/enn_backend.cpp
${CMAKE_CURRENT_LIST_DIR}/enn_executor.cpp
${CMAKE_CURRENT_LIST_DIR}/enn_shared_memory_manager.cpp
${CMAKE_CURRENT_LIST_DIR}/enn_api_implementation.cpp
)
endif()
39 changes: 20 additions & 19 deletions backends/samsung/runtime/enn_api_implementation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,32 +33,27 @@ void* loadApiFunction(void* handle, const char* name, bool optional) {
return fn;
}

std::mutex EnnApi::instance_mutex_;

EnnApi* EnnApi::getEnnApiInstance() {
std::lock_guard<std::mutex> lgd(instance_mutex_);
static EnnApi enn_api;
if (!enn_api.getInitialize()) {
auto status = enn_api.loadApiLib();
if (status == Error::Ok) {
ENN_LOG_INFO("Loading ENN API library Completed.")
enn_api.initialize_ = true;
} else {
ENN_LOG_ERROR("Failed to load enn api library. %s", dlerror());
}
}
return &enn_api;
}

EnnApi::~EnnApi() {
std::lock_guard<std::mutex> lgd(instance_mutex_);
if (getInitialize()) {
unloadApiLib();
EnnApi::EnnApi() {
auto status = loadApiLib();
if (status == Error::Ok) {
ET_LOG(Info, "Loading ENN API library Completed.");
EnnInitialize();
initialize_ = true;
} else {
ET_LOG(Error, "Failed to load enn api library. %s", dlerror());
}
}

bool EnnApi::getInitialize() const {
return initialize_;
EnnApi::~EnnApi() {
if (initialize_) {
EnnDeinitialize();
unloadApiLib();
}
}

Error EnnApi::loadApiLib() {
Expand All @@ -76,6 +71,7 @@ Error EnnApi::loadApiLib() {
ENN_LOAD_API_FUNC(libenn_public_api_, EnnUnsetFastIpc, this);
ENN_LOAD_API_FUNC(libenn_public_api_, EnnExecuteModelFastIpc, this);
ENN_LOAD_API_FUNC(libenn_public_api_, EnnExecuteModel, this);
ENN_LOAD_API_FUNC(libenn_public_api_, EnnCreateBuffer, this);
ENN_LOAD_API_FUNC(
libenn_public_api_, EnnExecuteModelWithSessionIdAsync, this);
ENN_LOAD_API_FUNC(libenn_public_api_, EnnExecuteModelWithSessionIdWait, this);
Expand All @@ -87,13 +83,18 @@ Error EnnApi::loadApiLib() {
ENN_LOAD_API_FUNC(libenn_public_api_, EnnBufferCommit, this);
ENN_LOAD_API_FUNC(libenn_public_api_, EnnGetBuffersInfo, this);
ENN_LOAD_API_FUNC(libenn_public_api_, EnnReleaseBuffers, this);
ENN_LOAD_API_FUNC(libenn_public_api_, EnnCreateBuffer, this);
ENN_LOAD_API_FUNC(libenn_public_api_, EnnReleaseBuffer, this);
ENN_LOAD_API_FUNC(
libenn_public_api_, EnnGetFileDescriptorFromEnnBuffer, this);
ENN_LOAD_API_FUNC(libenn_public_api_, EnnOpenModelFromFd, this);

return Error::Ok;
}

Error EnnApi::unloadApiLib() {
if (dlclose(libenn_public_api_) != 0) {
ENN_LOG_ERROR("Failed to close ENN API library. %s", dlerror());
ET_LOG(Error, "Failed to close ENN API library. %s", dlerror());
return Error::Internal;
}
libenn_public_api_ = nullptr;
Expand Down
18 changes: 17 additions & 1 deletion backends/samsung/runtime/enn_api_implementation.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class EnnApi {
const char* va,
const uint32_t size,
EnnModelId* model_id);
EnnReturn (*EnnOpenModelFromFd)(int _fd, EnnModelId* model_id);
EnnReturn (*EnnSetFastIpc)(void);
EnnReturn (*EnnUnsetFastIpc)(void);
EnnReturn (*EnnExecuteModelFastIpc)(
Expand Down Expand Up @@ -67,6 +68,13 @@ class EnnApi {
NumberOfBuffersInfo* buffers_info);
EnnReturn (
*EnnReleaseBuffers)(EnnBufferPtr* buffers, const int32_t numOfBuffers);
EnnReturn (*EnnCreateBuffer)(
const uint32_t req_size,
const uint32_t ion_flag,
EnnBufferPtr* out);
EnnReturn (*EnnReleaseBuffer)(EnnBufferPtr buf);
EnnReturn (
*EnnGetFileDescriptorFromEnnBuffer)(EnnBufferPtr buffer, int32_t* fd);

private:
static std::mutex instance_mutex_;
Expand All @@ -75,7 +83,7 @@ class EnnApi {
void* libenn_public_api_ = nullptr;
static std::atomic<int> ref_count_;

EnnApi() = default;
EnnApi();
bool getInitialize() const;
Error loadApiLib();
Error unloadApiLib();
Expand Down Expand Up @@ -120,6 +128,14 @@ typedef EnnReturn (*EnnGetBuffersInfo_fn)(
NumberOfBuffersInfo* buffers_info);
typedef EnnReturn (
*EnnReleaseBuffers_fn)(EnnBufferPtr* buffers, const int32_t numOfBuffers);
typedef EnnReturn (*EnnCreateBuffer_fn)(
const uint32_t req_size,
const uint32_t ion_flag,
EnnBufferPtr* out);
typedef EnnReturn (*EnnReleaseBuffer_fn)(EnnBufferPtr buf);
typedef EnnReturn (
*EnnGetFileDescriptorFromEnnBuffer_fn)(EnnBufferPtr buffer, int32_t* fd);
typedef EnnReturn (*EnnOpenModelFromFd_fn)(int _fd, EnnModelId* model_id);

} // namespace enn
} // namespace executor
Expand Down
1 change: 1 addition & 0 deletions backends/samsung/runtime/enn_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <executorch/backends/samsung/runtime/enn_executor.h>
#include <executorch/backends/samsung/runtime/logging.h>
#include <executorch/backends/samsung/runtime/profile.hpp>

#include <executorch/runtime/backend/interface.h>
#include <executorch/runtime/core/error.h>
#include <executorch/runtime/core/evalue.h>
Expand Down
48 changes: 42 additions & 6 deletions backends/samsung/runtime/enn_executor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@
*
*/
#include <executorch/backends/samsung/runtime/enn_executor.h>
#include <executorch/backends/samsung/runtime/enn_shared_memory_manager.h>
#include <executorch/backends/samsung/runtime/logging.h>
#include <executorch/backends/samsung/runtime/profile.hpp>
#include <inttypes.h>

#include <android/log.h>
#include <inttypes.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include <fstream>
#include <string>
#include <vector>
Expand All @@ -19,23 +24,54 @@ namespace torch {
namespace executor {
namespace enn {

uint32_t get_size_from_fd(int fd) {
if (fd < 0) {
ET_LOG(Error, "get_size_from_fd(), invalid fd(%d)\n", fd);
return 0;
} else {
off_t file_size = lseek(fd, 0, SEEK_END);
if (file_size < 0) {
return 0;
} else {
return static_cast<uint32_t>(file_size);
}
}
}

Error EnnExecutor::initialize(const char* binary_buf_addr, size_t buf_size) {
EXYNOS_ATRACE_FUNCTION_LINE();
auto _sm_instance = executorch::backends::enn::shared_memory_manager::
SharedMemoryManager::getInstance();
const EnnApi* enn_api_inst = EnnApi::getEnnApiInstance();
auto ret = enn_api_inst->EnnInitialize();
ET_CHECK_OR_RETURN_ERROR(
ret == ENN_RET_SUCCESS, Internal, "Enn initialize failed.");
EnnReturn ret;

ET_LOG(Info, "Start to open model %p, %ld", binary_buf_addr, buf_size);
ret = enn_api_inst->EnnOpenModelFromMemory(
binary_buf_addr, buf_size, &model_id_);

EnnBufferPtr _out;
if (_sm_instance->query(&_out, binary_buf_addr, buf_size)) {
int fd;
if (_out->va == binary_buf_addr &&
!enn_api_inst->EnnGetFileDescriptorFromEnnBuffer(_out, &fd)) {
ret = enn_api_inst->EnnOpenModelFromFd(fd, &model_id_);
ET_LOG(Info, "Opened Model From File Descriptor");
if (ret == ENN_RET_SUCCESS) {
ET_LOG(Info, "Buffer Loading finished with fd, so fd would be closed");
_sm_instance->free(_out->va);
}
}
}
if (!model_id_) {
ET_LOG(Info, "Opened Model From Memory");
ret = enn_api_inst->EnnOpenModelFromMemory(
binary_buf_addr, buf_size, &model_id_);
}
ET_CHECK_OR_RETURN_ERROR(
ret == ENN_RET_SUCCESS,
Internal,
"Failed to load Enn model from buffer %d",
(int)ret);
ET_LOG(Info, "Open successfully.");

NumberOfBuffersInfo buffers_info;
ret = enn_api_inst->EnnAllocateAllBuffersWithSessionId(
model_id_, &alloc_buffer_, &buffers_info, 0, true);
Expand Down
2 changes: 1 addition & 1 deletion backends/samsung/runtime/enn_executor.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class EnnExecutor {
~EnnExecutor();

private:
EnnModelId model_id_;
EnnModelId model_id_ = 0ULL;
EnnBufferPtr* alloc_buffer_ = nullptr;
int32_t num_of_inputs_ = 0;
int32_t num_of_outputs_ = 0;
Expand Down
102 changes: 102 additions & 0 deletions backends/samsung/runtime/enn_shared_memory_manager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright (c) 2025 Samsung Electronics Co. LTD
* All rights reserved
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*
*/
#include <executorch/backends/samsung/runtime/enn_api_implementation.h>
#include <executorch/backends/samsung/runtime/enn_shared_memory_manager.h>
#include <executorch/backends/samsung/runtime/enn_type.h>
#include <executorch/backends/samsung/runtime/logging.h>
#include <executorch/runtime/core/error.h>

#include <mutex>
#include <vector>

using namespace torch::executor::enn;
using namespace torch::executor;

namespace executorch {
namespace backends {
namespace enn {
namespace shared_memory_manager {

static std::mutex instance_mutex_;

SharedMemoryManager* SharedMemoryManager::getInstance() {
static SharedMemoryManager instance;
return &instance;
}

void* SharedMemoryManager::alloc(const size_t size) {
std::lock_guard<std::mutex> lgd(instance_mutex_);
auto enn_api_inst = EnnApi::getEnnApiInstance();
EnnBufferPtr bufferPtr;
auto ret = enn_api_inst->EnnCreateBuffer(size, 0, &bufferPtr);
if (ret) {
ET_LOG(Error, "Buffer Creation Error");
return nullptr;
}
EnnBufferPtrList.emplace_back(bufferPtr);
return bufferPtr->va;
}

bool SharedMemoryManager::query(
EnnBufferPtr* out,
const void* ptr,
const size_t size) {
std::lock_guard<std::mutex> lgd(instance_mutex_);
auto enn_api_inst = EnnApi::getEnnApiInstance();
for (const auto& buffer : EnnBufferPtrList) {
if (buffer->va <= ptr &&
ptr < static_cast<char*>(buffer->va) + buffer->size) {
int fd;
auto ret = enn_api_inst->EnnGetFileDescriptorFromEnnBuffer(buffer, &fd);
if (ret) {
ET_LOG(
Info,
"va: %p, size: %zu is in LUT, but failed to get FileDescriptor",
ptr,
size);
return false;
}
*out = buffer;
return true;
}
}
ET_LOG(Info, "va: %p, size: %zu is not in LUT", ptr, size);
*out = nullptr;
return false;
}

void SharedMemoryManager::free(void* ptr) {
free(ptr, {});
}
void SharedMemoryManager::free(void* ptr, std::align_val_t alignment) {
std::lock_guard<std::mutex> lgd(instance_mutex_);
auto enn_api_inst = EnnApi::getEnnApiInstance();
for (auto it = EnnBufferPtrList.begin(); it != EnnBufferPtrList.end(); ++it) {
if ((*it)->va == ptr) {
ET_LOG(
Info,
"va(%p), size(%d), offset(%d) is erased from LUT",
ptr,
(*it)->size,
(*it)->offset);
auto ret = enn_api_inst->EnnReleaseBuffer(*it);
if (ret) {
ET_LOG(Error, "Failed to destroy buffer: %p", ptr);
}
EnnBufferPtrList.erase(it);
ET_LOG(Info, "Buffer Erased(%p)", ptr);
return;
}
}
}

} // namespace shared_memory_manager
} // namespace enn
} // namespace backends
} // namespace executorch
47 changes: 47 additions & 0 deletions backends/samsung/runtime/enn_shared_memory_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2025 Samsung Electronics Co. LTD
* All rights reserved
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*
*/
#pragma once

#include <executorch/backends/samsung/runtime/enn_api_implementation.h>
#include <executorch/backends/samsung/runtime/enn_type.h>
#include <executorch/runtime/core/error.h>

#include <vector>

using namespace torch::executor::enn;

namespace executorch {
namespace backends {
namespace enn {
namespace shared_memory_manager {

class SharedMemoryManager {
public:
static SharedMemoryManager* getInstance();

SharedMemoryManager() = default;
~SharedMemoryManager() = default;
SharedMemoryManager(const SharedMemoryManager&) = delete;
SharedMemoryManager& operator=(const SharedMemoryManager&) = delete;
SharedMemoryManager(SharedMemoryManager&&) = delete;
SharedMemoryManager& operator=(SharedMemoryManager&&) = delete;

void* alloc(const size_t size);
void free(void* ptr);
void free(void* ptr, std::align_val_t alignment);
bool query(EnnBufferPtr* out, const void* ptr, const size_t size);

private:
std::vector<EnnBufferPtr> EnnBufferPtrList;
};

} // namespace shared_memory_manager
} // namespace enn
} // namespace backends
} // namespace executorch
Loading
Loading