Skip to content

Commit db5ca84

Browse files
committed
Implement Exynos backend
Implement backend and executor for exynos. Signed-off-by: chong-chen <[email protected]> Signed-off-by: jiseong.oh <[email protected]>
1 parent f6f95bf commit db5ca84

File tree

8 files changed

+642
-0
lines changed

8 files changed

+642
-0
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Copyright (c) 2025 Samsung Electronics Co. LTD
2+
# All rights reserved
3+
#
4+
# This source code is licensed under the BSD-style license found in the
5+
# LICENSE file in the root directory of this source tree.
6+
7+
# logging
8+
target_sources(
9+
enn_logging PUBLIC ${CMAKE_CURRENT_LIST_DIR}/logging.h
10+
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/logging.cpp
11+
)
12+
13+
if(${ANDROID})
14+
# backend
15+
target_sources(enn_backend PRIVATE
16+
${CMAKE_CURRENT_LIST_DIR}/enn_backend.cpp
17+
${CMAKE_CURRENT_LIST_DIR}/enn_executor.cpp
18+
${CMAKE_CURRENT_LIST_DIR}/enn_api_implementation.cpp
19+
)
20+
endif()
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright (c) 2025 Samsung Electronics Co. LTD
3+
* All rights reserved
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*
8+
*/
9+
#include <dlfcn.h>
10+
#include <executorch/backends/samsung/runtime/enn_api_implementation.h>
11+
#include <executorch/backends/samsung/runtime/logging.h>
12+
13+
#define ENN_LOAD_API_FUNC(handle, name, enn_api_ptr) \
14+
enn_api_ptr->name = \
15+
reinterpret_cast<name##_fn>(loadApiFunction(handle, #name, false)); \
16+
if (enn_api_ptr->name == nullptr) { \
17+
ENN_LOG_ERROR("Unable to access symbols in enn api library: %s", #name); \
18+
dlclose(handle); \
19+
return Error::Internal; \
20+
}
21+
22+
namespace torch {
23+
namespace executor {
24+
namespace enn {
25+
void* loadApiFunction(void* handle, const char* name, bool optional) {
26+
if (handle == nullptr) {
27+
return nullptr;
28+
}
29+
void* fn = dlsym(handle, name);
30+
if (fn == nullptr && !optional) {
31+
ENN_LOG_WARN("Failed to load function %s", name);
32+
}
33+
return fn;
34+
}
35+
36+
std::mutex EnnApi::instance_mutex_;
37+
38+
EnnApi* EnnApi::getEnnApiInstance() {
39+
std::lock_guard<std::mutex> lgd(instance_mutex_);
40+
static EnnApi enn_api;
41+
if (!enn_api.getInitialize()) {
42+
auto status = enn_api.loadApiLib();
43+
if (status == Error::Ok) {
44+
enn_api.initialize_ = true;
45+
}
46+
}
47+
return &enn_api;
48+
}
49+
50+
EnnApi::~EnnApi() {
51+
if (getInitialize()) {
52+
unloadApiLib();
53+
}
54+
}
55+
56+
bool EnnApi::getInitialize() const {
57+
return initialize_;
58+
}
59+
60+
Error EnnApi::loadApiLib() {
61+
const char enn_api_lib_name[] = "libenn_public_api_cpp.so";
62+
libenn_public_api_ = dlopen(enn_api_lib_name, RTLD_NOW | RTLD_LOCAL);
63+
ET_CHECK_OR_RETURN_ERROR(
64+
libenn_public_api_ != nullptr, Internal, "Lib load failed.")
65+
66+
ENN_LOAD_API_FUNC(libenn_public_api_, EnnInitialize, this);
67+
ENN_LOAD_API_FUNC(libenn_public_api_, EnnSetPreferencePerfMode, this);
68+
ENN_LOAD_API_FUNC(libenn_public_api_, EnnGetPreferencePerfMode, this);
69+
ENN_LOAD_API_FUNC(libenn_public_api_, EnnOpenModel, this);
70+
ENN_LOAD_API_FUNC(libenn_public_api_, EnnOpenModelFromMemory, this);
71+
ENN_LOAD_API_FUNC(libenn_public_api_, EnnSetFastIpc, this);
72+
ENN_LOAD_API_FUNC(libenn_public_api_, EnnUnsetFastIpc, this);
73+
ENN_LOAD_API_FUNC(libenn_public_api_, EnnExecuteModelFastIpc, this);
74+
ENN_LOAD_API_FUNC(libenn_public_api_, EnnExecuteModel, this);
75+
ENN_LOAD_API_FUNC(
76+
libenn_public_api_, EnnExecuteModelWithSessionIdAsync, this);
77+
ENN_LOAD_API_FUNC(libenn_public_api_, EnnExecuteModelWithSessionIdWait, this);
78+
ENN_LOAD_API_FUNC(libenn_public_api_, EnnCloseModel, this);
79+
ENN_LOAD_API_FUNC(libenn_public_api_, EnnDeinitialize, this);
80+
ENN_LOAD_API_FUNC(libenn_public_api_, EnnAllocateAllBuffers, this);
81+
ENN_LOAD_API_FUNC(
82+
libenn_public_api_, EnnAllocateAllBuffersWithSessionId, this);
83+
ENN_LOAD_API_FUNC(libenn_public_api_, EnnBufferCommit, this);
84+
ENN_LOAD_API_FUNC(libenn_public_api_, EnnGetBuffersInfo, this);
85+
ENN_LOAD_API_FUNC(libenn_public_api_, EnnReleaseBuffers, this);
86+
87+
return Error::Ok;
88+
}
89+
90+
Error EnnApi::unloadApiLib() {
91+
if (dlclose(libenn_public_api_) != 0) {
92+
ENN_LOG_ERROR("Failed to close enn public api library. %s", dlerror());
93+
return Error::Internal;
94+
};
95+
return Error::Ok;
96+
}
97+
98+
} // namespace enn
99+
} // namespace executor
100+
} // namespace torch
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* Copyright (c) 2025 Samsung Electronics Co. LTD
3+
* All rights reserved
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*
8+
*/
9+
#pragma once
10+
#include <enn_api/include/enn_api-type.h>
11+
#include <executorch/runtime/core/error.h>
12+
13+
#include <atomic>
14+
#include <cstdint>
15+
#include <memory>
16+
#include <mutex>
17+
18+
namespace torch {
19+
namespace executor {
20+
namespace enn {
21+
22+
class EnnApi {
23+
public:
24+
EnnApi(const EnnApi&) = delete;
25+
EnnApi& operator=(const EnnApi&) = delete;
26+
EnnApi(EnnApi&&) = delete;
27+
EnnApi& operator=(EnnApi&&) = delete;
28+
~EnnApi();
29+
30+
static EnnApi* getEnnApiInstance();
31+
32+
EnnReturn (*EnnInitialize)(void);
33+
EnnReturn (*EnnSetPreferencePerfMode)(const uint32_t val);
34+
EnnReturn (*EnnGetPreferencePerfMode)(uint32_t* val_ptr);
35+
EnnReturn (*EnnOpenModel)(const char* model_file, EnnModelId* model_id);
36+
EnnReturn (*EnnOpenModelFromMemory)(
37+
const char* va,
38+
const uint32_t size,
39+
EnnModelId* model_id);
40+
EnnReturn (*EnnSetFastIpc)(void);
41+
EnnReturn (*EnnUnsetFastIpc)(void);
42+
EnnReturn (*EnnExecuteModelFastIpc)(
43+
const EnnModelId model_id,
44+
int client_sleep_usec);
45+
EnnReturn (*EnnExecuteModel)(const EnnModelId model_id);
46+
EnnReturn (*EnnExecuteModelWithSessionIdAsync)(
47+
const EnnModelId model_id,
48+
const int session_id);
49+
EnnReturn (*EnnCloseModel)(const EnnModelId model_id);
50+
EnnReturn (*EnnDeinitialize)(void);
51+
EnnReturn (*EnnAllocateAllBuffers)(
52+
const EnnModelId model_id,
53+
EnnBufferPtr** out_buffers,
54+
NumberOfBuffersInfo* out_buffers_info);
55+
EnnReturn (*EnnAllocateAllBuffersWithSessionId)(
56+
const EnnModelId model_id,
57+
EnnBufferPtr** out_buffers,
58+
NumberOfBuffersInfo* out_buffers_info,
59+
const int session_id,
60+
const bool do_commit);
61+
EnnReturn (*EnnExecuteModelWithSessionIdWait)(
62+
const EnnModelId model_id,
63+
const int session_id);
64+
EnnReturn (*EnnBufferCommit)(const EnnModelId model_id);
65+
EnnReturn (*EnnGetBuffersInfo)(
66+
const EnnModelId model_id,
67+
NumberOfBuffersInfo* buffers_info);
68+
EnnReturn (
69+
*EnnReleaseBuffers)(EnnBufferPtr* buffers, const int32_t numOfBuffers);
70+
71+
private:
72+
static std::mutex instance_mutex_;
73+
std::atomic_bool initialize_ = false;
74+
// Pointer to the dlopen libs
75+
void* libenn_public_api_ = nullptr;
76+
77+
EnnApi() = default;
78+
bool getInitialize() const;
79+
Error loadApiLib();
80+
Error unloadApiLib();
81+
};
82+
83+
typedef EnnReturn (*EnnInitialize_fn)(void);
84+
typedef EnnReturn (*EnnSetPreferencePerfMode_fn)(const uint32_t val);
85+
typedef EnnReturn (*EnnGetPreferencePerfMode_fn)(uint32_t* val_ptr);
86+
typedef EnnReturn (
87+
*EnnOpenModel_fn)(const char* model_file, EnnModelId* model_id);
88+
typedef EnnReturn (*EnnOpenModelFromMemory_fn)(
89+
const char* va,
90+
const uint32_t size,
91+
EnnModelId* model_id);
92+
typedef EnnReturn (*EnnSetFastIpc_fn)(void);
93+
typedef EnnReturn (*EnnUnsetFastIpc_fn)(void);
94+
typedef EnnReturn (*EnnExecuteModelFastIpc_fn)(
95+
const EnnModelId model_id,
96+
int client_sleep_usec);
97+
typedef EnnReturn (*EnnExecuteModel_fn)(const EnnModelId model_id);
98+
typedef EnnReturn (*EnnExecuteModelWithSessionIdAsync_fn)(
99+
const EnnModelId model_id,
100+
const int session_id);
101+
typedef EnnReturn (*EnnCloseModel_fn)(const EnnModelId model_id);
102+
typedef EnnReturn (*EnnDeinitialize_fn)(void);
103+
typedef EnnReturn (*EnnAllocateAllBuffers_fn)(
104+
const EnnModelId model_id,
105+
EnnBufferPtr** out_buffers,
106+
NumberOfBuffersInfo* out_buffers_info);
107+
typedef EnnReturn (*EnnAllocateAllBuffersWithSessionId_fn)(
108+
const EnnModelId model_id,
109+
EnnBufferPtr** out_buffers,
110+
NumberOfBuffersInfo* out_buffers_info,
111+
const int session_id,
112+
const bool do_commit);
113+
typedef EnnReturn (*EnnExecuteModelWithSessionIdWait_fn)(
114+
const EnnModelId model_id,
115+
const int session_id);
116+
typedef EnnReturn (*EnnBufferCommit_fn)(const EnnModelId model_id);
117+
typedef EnnReturn (*EnnGetBuffersInfo_fn)(
118+
const EnnModelId model_id,
119+
NumberOfBuffersInfo* buffers_info);
120+
typedef EnnReturn (
121+
*EnnReleaseBuffers_fn)(EnnBufferPtr* buffers, const int32_t numOfBuffers);
122+
123+
} // namespace enn
124+
} // namespace executor
125+
} // namespace torch
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Copyright (c) 2025 Samsung Electronics Co. LTD
3+
* All rights reserved
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*
8+
*/
9+
#include <executorch/backends/samsung/runtime/enn_executor.h>
10+
#include <executorch/backends/samsung/runtime/logging.h>
11+
#include <executorch/runtime/backend/interface.h>
12+
#include <executorch/runtime/core/error.h>
13+
#include <executorch/runtime/core/evalue.h>
14+
#include <executorch/runtime/platform/profiler.h>
15+
16+
#include <memory>
17+
#include <vector>
18+
19+
#pragma clang diagnostic ignored "-Wglobal-constructors"
20+
21+
namespace torch {
22+
namespace executor {
23+
24+
class EnnBackend final : public PyTorchBackendInterface {
25+
public:
26+
~EnnBackend() = default;
27+
28+
bool is_available() const override {
29+
return true;
30+
}
31+
32+
Result<DelegateHandle*> init(
33+
BackendInitContext& context,
34+
FreeableBuffer* processed,
35+
ArrayRef<CompileSpec> compile_specs) const override {
36+
auto executor = ET_ALLOCATE_INSTANCE_OR_RETURN_ERROR(
37+
context.get_runtime_allocator(), enn::EnnExecutor);
38+
const char* binary_buf_addr =
39+
reinterpret_cast<const char*>(processed->data());
40+
size_t buf_size = processed->size();
41+
Error err = executor->initialize(binary_buf_addr, buf_size);
42+
if (err != Error::Ok) {
43+
ENN_LOG_ERROR("Exynos backend initialize failed.");
44+
executor->~EnnExecutor();
45+
return err;
46+
}
47+
return executor;
48+
}
49+
50+
Error execute(
51+
BackendExecutionContext& context,
52+
DelegateHandle* handle,
53+
EValue** args) const override {
54+
auto executor = static_cast<enn::EnnExecutor*>(handle);
55+
56+
std::vector<enn::DataBuffer> inputs;
57+
std::vector<enn::DataBuffer> outputs;
58+
for (int32_t index = 0;
59+
index < executor->getInputSize() + executor->getOutputSize();
60+
index++) {
61+
ET_CHECK_OR_RETURN_ERROR(
62+
args[index]->isTensor(),
63+
InvalidArgument,
64+
"Expected argument to delegate at index %u to be a Tensor, but got %" PRIu32,
65+
index,
66+
static_cast<uint32_t>(args[index]->tag));
67+
Tensor* tensor = &args[index]->toTensor();
68+
enn::DataBuffer data_buffer = {
69+
.buf_ptr_ = tensor->mutable_data_ptr<void*>(),
70+
.size_ = tensor->nbytes()};
71+
if (index < executor->getInputSize()) {
72+
inputs.push_back(data_buffer);
73+
} else {
74+
outputs.push_back(data_buffer);
75+
}
76+
}
77+
return err;
78+
}
79+
80+
void destroy(DelegateHandle* handle) const override {
81+
if (handle != nullptr) {
82+
auto executor = static_cast<enn::EnnExecutor*>(handle);
83+
executor->~EnnExecutor();
84+
}
85+
}
86+
}; // namespace executor
87+
88+
namespace {
89+
auto cls = EnnBackend();
90+
Backend backend{"ExynosBackend", &cls};
91+
static auto success_with_compiler = register_backend(backend);
92+
} // namespace
93+
94+
} // namespace executor
95+
} // namespace torch

0 commit comments

Comments
 (0)