kokoro.best / cpp /src /ax_model_runner /ax_engine_impl.hpp
inoryQwQ's picture
Upload folder using huggingface_hub (part 3)
71e354e verified
Raw
History Blame Contribute Delete
10.6 kB
/**************************************************************************************************
*
* Copyright (c) 2019-2026 Axera Semiconductor (Ningbo) Co., Ltd. All Rights Reserved.
*
* This source file is the property of Axera Semiconductor (Ningbo) Co., Ltd. and
* may not be copied or distributed in any isomorphic form without the prior
* written consent of Axera Semiconductor (Ningbo) Co., Ltd.
*
**************************************************************************************************/
#if defined (CHIP_AX650) || defined(CHIP_AX630C) || defined(CHIP_AX620Q)
#pragma once
#include <vector>
#include <string>
#include <string.h>
#include <ax_sys_api.h>
#include "ax_model_runner.hpp"
#include "ax_engine_api.h"
#include "ax_engine_guard.hpp"
#include "utils/memory_utils.hpp"
#include "utils/logger.h"
#if defined (CHIP_AX650)
#include "ax_dmadim_api.h"
#endif
#define AX_IO_CMM_ALIGN_SIZE 128
class AxModelRunner::Impl {
public:
Impl():
m_handle(nullptr),
m_pIOinfo(nullptr),
m_input_num(0),
m_output_num(0),
m_loaded(false) {
memset(&m_io, 0, sizeof(AX_ENGINE_IO_T));
}
~Impl() {
unload_model();
}
int load_model(const char* model_path, AX_IO_BUFFER_STRATEGY_T strategy, int device_index) {
if (!utils::file_exist(std::string(model_path))) {
ALOGE("model path %s not exist!", model_path);
return -1;
}
AX_CHAR *pModelBufferVirAddr = nullptr;
AX_U32 nModelBufferSize = 0;
MMap model_buffer(model_path);
pModelBufferVirAddr = (char*)model_buffer.data();
nModelBufferSize = model_buffer.size();
auto freeModelBuffer = [&]() {
model_buffer.close_file();
return;
};
int ret = AX_ENGINE_CreateHandle(&m_handle, pModelBufferVirAddr, nModelBufferSize);
if (0 != ret) {
ALOGE("AX_ENGINE_CreateHandle failed! ret=0x%x", ret);
freeModelBuffer();
return ret;
}
ret = AX_ENGINE_CreateContext(m_handle);
if (0 != ret) {
ALOGE("AX_ENGINE_CreateContext failed! ret=0x%x", ret);
freeModelBuffer();
return ret;
}
m_strategy = strategy;
ret = _prepare_io();
if (0 != ret) {
ALOGE("_prepare_io failed! ret=0x%x", ret);
freeModelBuffer();
_free_io();
return ret;
}
freeModelBuffer();
m_loaded = (ret == 0);
return ret;
}
int unload_model(void) {
int ret = 0;
if (m_handle != 0) {
ALOGD("Detroy engine handle");
ret = AX_ENGINE_DestroyHandle(m_handle);
m_handle = 0;
_free_io();
}
return ret;
}
int run(void) {
if (m_strategy == AX_IO_BUFFER_STRATEGY_CACHED) {
for (int index = 0; index < m_input_num; index++) {
_cache_io_flush(m_io.pInputs[index]);
}
}
int ret = AX_ENGINE_RunSync(m_handle, &m_io);
if (0 != ret) {
ALOGE("AX_ENGINE_RunSync failed! ret=0x%x", ret);
return ret;
}
return ret;
}
int set_input(int index, void* data) {
if (index < 0) index += m_input_num;
if (index > m_input_num - 1) {
ALOGE("index(%d) exceed input_num(%d)", index, m_input_num);
return -1;
}
if (!data) {
ALOGE("data is null");
return -1;
}
memcpy(m_io.pInputs[index].pVirAddr, data, m_io.pInputs[index].nSize);
return 0;
}
int set_inputs(const std::vector<void*>& datas) {
for (int index = 0; index < m_input_num; index++) {
void* data = datas[index];
if (!data) {
ALOGE("index %d data is null", index);
return -1;
}
memcpy(m_io.pInputs[index].pVirAddr, data, m_io.pInputs[index].nSize);
}
return 0;
}
int set_input_dma(int dst_index, AxModelRunner& src_model, int src_index) {
#if defined (CHIP_AX650)
AX_U64 phySrc = src_model.get_output_phy_addr(src_index);
AX_U64 phyDst = this->get_input_phy_addr(dst_index);
int size = src_model.get_output_size(src_index);
int ret = AX_DMA_MemCopy(phyDst, phySrc, (AX_U64)size);
if (ret) {
ALOGW("AX_DMA_MemCopy failed! ret=0x%x, fallback to sys memcpy", ret);
this->set_input(dst_index, src_model.get_output_ptr(src_index));
return 0;
}
return 0;
#else
this->set_input(dst_index, src_model.get_output_ptr(src_index));
return 0;
#endif
}
int get_output(int index, void* data) {
if (m_strategy == AX_IO_BUFFER_STRATEGY_CACHED)
_cache_io_flush(m_io.pOutputs[index]);
memcpy(data, m_io.pOutputs[index].pVirAddr, m_io.pOutputs[index].nSize);
return 0;
}
int get_outputs(const std::vector<void*>& datas) {
for (int index = 0; index < m_output_num; index++) {
void* data = datas[index];
if (!data) {
ALOGE("index %d data is null", index);
return -1;
}
if (m_strategy == AX_IO_BUFFER_STRATEGY_CACHED)
_cache_io_flush(m_io.pOutputs[index]);
memcpy(data, m_io.pOutputs[index].pVirAddr, m_io.pOutputs[index].nSize);
}
return 0;
}
inline int get_input_num(void) {
return m_input_num;
}
inline int get_output_num(void) {
return m_output_num;
}
inline void* get_input_ptr(int index) {
return m_io.pInputs[index].pVirAddr;
}
void* get_output_ptr(int index) {
if (m_strategy == AX_IO_BUFFER_STRATEGY_CACHED)
_cache_io_flush(m_io.pOutputs[index]);
return m_io.pOutputs[index].pVirAddr;
}
inline AX_U64 get_input_phy_addr(int index) {
return m_io.pInputs[index].phyAddr;
}
inline AX_U64 get_output_phy_addr(int index) {
return m_io.pOutputs[index].phyAddr;
}
inline const char* get_input_name(int index) {
return m_input_names[index].c_str();
}
inline const char* get_output_name(int index) {
return m_output_names[index].c_str();
}
inline int get_input_size(int index) {
return m_pIOinfo->pInputs[index].nSize;
}
inline int get_output_size(int index) {
return m_pIOinfo->pOutputs[index].nSize;
}
std::vector<int> get_input_shape(int index) {
std::vector<int> shape;
shape.resize(m_pIOinfo->pInputs[index].nShapeSize);
for (int i = 0; i < shape.size(); i++) {
shape[i] = m_pIOinfo->pInputs[index].pShape[i];
}
return shape;
}
std::vector<int> get_output_shape(int index) {
std::vector<int> shape;
shape.resize(m_pIOinfo->pOutputs[index].nShapeSize);
for (int i = 0; i < shape.size(); i++) {
shape[i] = m_pIOinfo->pOutputs[index].pShape[i];
}
return shape;
}
private:
int _prepare_io() {
int ret = AX_ENGINE_GetIOInfo(m_handle, &m_pIOinfo);
if (0 != ret) {
ALOGE("AX_ENGINE_GetIOInfo failed! ret=0x%x", ret);
return ret;
}
m_input_num = m_pIOinfo->nInputSize;
m_output_num = m_pIOinfo->nOutputSize;
m_io.nInputSize = m_pIOinfo->nInputSize;
m_io.nOutputSize = m_pIOinfo->nOutputSize;
m_io.pInputs = new AX_ENGINE_IO_BUFFER_T[m_pIOinfo->nInputSize];
m_io.pOutputs = new AX_ENGINE_IO_BUFFER_T[m_pIOinfo->nOutputSize];
for (int i = 0; i < m_pIOinfo->nInputSize; i++) {
const char* layer_name = m_pIOinfo->pInputs[i].pName;
m_input_names.push_back(std::string(layer_name));
ret = _alloc_io_buffer(m_io.pInputs[i], m_pIOinfo->pInputs[i], m_strategy);
if (0 != ret) {
ALOGE("_alloc_io_buffer for input[%d] failed! ret=0x%x", i, ret);
return ret;
}
}
for (int i = 0; i < m_pIOinfo->nOutputSize; i++) {
const char* layer_name = m_pIOinfo->pOutputs[i].pName;
m_output_names.push_back(std::string(layer_name));
ret = _alloc_io_buffer(m_io.pOutputs[i], m_pIOinfo->pOutputs[i], m_strategy);
if (0 != ret) {
ALOGE("_alloc_io_buffer for output[%d] failed! ret=0x%x", i, ret);
return ret;
}
}
return ret;
}
void _free_io() {
for (size_t i = 0; i < m_io.nInputSize; i++) {
if (0 != m_io.pInputs[i].phyAddr)
AX_SYS_MemFree(m_io.pInputs[i].phyAddr, m_io.pInputs[i].pVirAddr);
}
for (size_t i = 0; i < m_io.nOutputSize; i++) {
if (0 != m_io.pOutputs[i].phyAddr)
AX_SYS_MemFree(m_io.pOutputs[i].phyAddr, m_io.pOutputs[i].pVirAddr);
}
delete[] m_io.pInputs;
delete[] m_io.pOutputs;
memset(&m_io, 0, sizeof(AX_ENGINE_IO_T));
}
int _alloc_io_buffer(AX_ENGINE_IO_BUFFER_T &buffer,
const AX_ENGINE_IOMETA_T &meta, AX_IO_BUFFER_STRATEGY_T strategy) {
int ret = 0;
memset(&buffer, 0, sizeof(AX_ENGINE_IO_BUFFER_T));
buffer.nSize = meta.nSize;
if (AX_IO_BUFFER_STRATEGY_DEFAULT == strategy) {
AX_SYS_MemAlloc((AX_U64*)&buffer.phyAddr,
(AX_VOID**)&buffer.pVirAddr,
meta.nSize, AX_IO_CMM_ALIGN_SIZE, (const AX_S8*)meta.pName);
} else {
AX_SYS_MemAllocCached((AX_U64*)&buffer.phyAddr,
(AX_VOID**)&buffer.pVirAddr,
meta.nSize, AX_IO_CMM_ALIGN_SIZE, (const AX_S8*)meta.pName);
}
return ret;
}
void _cache_io_flush(AX_ENGINE_IO_BUFFER_T &buffer) {
if (buffer.phyAddr != 0) {
AX_SYS_MflushCache(buffer.phyAddr, buffer.pVirAddr, buffer.nSize);
}
}
private:
AX_ENGINE_HANDLE m_handle;
AX_ENGINE_IO_T m_io;
AX_ENGINE_IO_INFO_T* m_pIOinfo;
int m_input_num;
int m_output_num;
AX_IO_BUFFER_STRATEGY_T m_strategy;
std::vector<std::string> m_input_names;
std::vector<std::string> m_output_names;
bool m_loaded;
AxEngineGuard m_engine_guard;
};
#endif