/* * @Author: xiewenji 527774126@qq.com * @Date: 2025-09-03 10:44:31 * @LastEditors: xiewenji 527774126@qq.com * @LastEditTime: 2025-09-06 22:29:55 * @FilePath: /AI_SO_Test/AIEngineModule/src/AIModel_Impl.cpp * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ #include "AIModel_Impl.h" #include "CUDA_DataChange.cuh" AIModel_Impl::AIModel_Impl() { m_bInitSuccess = false; m_GPU_Engine.clear(); m_modelNodeList.clear(); m_pNode_input_0 = NULL; m_pNode_input_1 = NULL; m_pNode_output_0 = NULL; m_pNode_output_1 = NULL; m_pNode_output_2 = NULL; m_DetGPUStream.clear(); m_nLast_GPUStreamIdx.store(0); m_nALLStreamNum = 0; } AIModel_Impl::~AIModel_Impl() { } int AIModel_Impl::Init(AIModelRun_Config config) { m_modelRun_Config.Copy(config); printf(">>> %s Init Start \n", m_modelRun_Config.strName.c_str()); if (m_bInitSuccess) { printf("strName %s Init Success %d ************ return \n", m_modelRun_Config.strName.c_str(), m_bInitSuccess); return 0; } int re = 0; re = ModelRunConfigCheck(m_modelRun_Config); if (re != 0) { printf("strName %s Init Error =%d run Config error \n", m_modelRun_Config.strName.c_str(), re); return re; } // 不同显卡 单独 载入模型 if (m_modelRun_Config.gpuconfig.gpu_0) { re = LoadEngine(0); // 加载失败 if (re != 0) { } } if (m_modelRun_Config.gpuconfig.gpu_1) { re = LoadEngine(1); // 加载失败 if (re != 0) { } } int nGPUNum = m_GPU_Engine.size(); // 模型载入失败 if (nGPUNum <= 0 || nGPUNum > 2) { printf(" %s model Init error \n", m_modelRun_Config.strName.c_str()); return 2; } for (int i = 0; i < m_modelNodeList.size(); i++) { if (m_modelNodeList.at(i).type == AI_Buffer_Type_INPUT) { if (m_pNode_input_0 == NULL) { m_pNode_input_0 = &m_modelNodeList.at(i); input_0.copy(*m_pNode_input_0); } else { m_pNode_input_1 = &m_modelNodeList.at(i); input_1.copy(*m_pNode_input_1); } } else { if (m_pNode_output_0 == NULL) { m_pNode_output_0 = &m_modelNodeList.at(i); output_0.copy(*m_pNode_output_0); } else if (m_pNode_output_1 == NULL) { m_pNode_output_1 = &m_modelNodeList.at(i); output_1.copy(*m_pNode_output_1); } else { m_pNode_output_2 = &m_modelNodeList.at(i); output_2.copy(*m_pNode_output_2); } } } if (m_pNode_input_0 == NULL || m_pNode_output_0 == NULL) { printf(" %s model Init error \n", m_modelRun_Config.strName.c_str()); return 3; } int streamNum = m_GPU_Engine.at(0)->cudaSteams.size(); // 生产推理用的 参数信息 if (m_GPU_Engine.size() > 1) { if (m_GPU_Engine.at(0)->cudaSteams.size() != m_GPU_Engine.at(1)->cudaSteams.size()) { printf(" %s model Init error \n", m_modelRun_Config.strName.c_str()); return 3; } } if (streamNum <= 0) { printf(" %s model Init streamNum error \n", m_modelRun_Config.strName.c_str()); return 4; } // 显示初始化信息 if (true) { printf("Model Name :%s GUP engine Num %ld\n", m_modelRun_Config.strName.c_str(), m_GPU_Engine.size()); for (const auto &ge : m_GPU_Engine) { printf(" gpu %d status %d strem Num %ld \n", ge->nGPUIdx, ge->bsucc, ge->cudaSteams.size()); for (const auto &psteam : ge->cudaSteams) { printf(" steam %d \n", psteam->nstreamIdx); for (const auto &pcon : psteam->streamConfigList) { printf(" type %d [chw] %d %d %d input %p output %p\n", pcon->nodeConfig.type, pcon->nodeConfig.channel, pcon->nodeConfig.height, pcon->nodeConfig.width, pcon->gpu_buffers, pcon->gpu_ImgData); } } } } // 把所有gup 的所有stream 都放到一起,方便调用。 for (int i = 0; i < streamNum; i++) { for (int igpu = 0; igpu < nGPUNum; igpu++) { std::shared_ptr temDetStream = std::make_shared(); temDetStream->nGPUIdx = m_GPU_Engine.at(igpu)->nGPUIdx; temDetStream->engine = m_GPU_Engine.at(igpu)->engine; temDetStream->cuda_stream = m_GPU_Engine.at(igpu)->cudaSteams.at(i); m_DetGPUStream.push_back(temDetStream); } } m_nALLStreamNum = m_DetGPUStream.size(); printf("========********* Model Name :%s GUP engine Num %ld **************=============\n", m_modelRun_Config.strName.c_str(), m_GPU_Engine.size()); for (const auto steam : m_DetGPUStream) { printf(">>> gpu %d stream %d \n", steam->nGPUIdx, steam->cuda_stream->nstreamIdx); } m_bInitSuccess = true; // warm-up:首次推理会触发 TensorRT/CUDA 懒初始化(kernel 加载、workspace 分配、首次 enqueueV3 建图等), // 提前用一张空图预热,避免首张检测图耗时飙升。 { cv::Mat warmIn = InitMat(m_pNode_input_0->channel, m_pNode_input_0->width, m_pNode_input_0->height); cv::Mat warmOut; int warmRe = AIDet(warmIn, warmOut); if (warmRe != 0) { printf("%s warm-up error = %d\n", m_modelRun_Config.strName.c_str(), warmRe); } } return 0; } cv::Mat AIModel_Impl::InitMat(int channel, int w, int h) { if (w <= 0 || h <= 0 || channel <= 0 || channel > 3) { return cv::Mat(); } cv::Mat dst; if (channel == 1) { dst = cv::Mat(h, w, CV_8UC1, cv::Scalar(0)); } else { dst = cv::Mat(h, w, CV_8UC3, cv::Scalar(0, 0, 0)); } return dst; } int AIModel_Impl::AIDet(const cv::Mat &inImg, cv::Mat &outimg) { // 1、准备数据 if (m_pNode_input_0 == NULL || m_pNode_output_0 == NULL) { printf("AIDet: Node Config INput output Node error \n"); return 1; } // std::this_thread::sleep_for(std::chrono::milliseconds(2)); // Sleep for 100 milliseconds uchar *p_indata_0 = (uchar *)inImg.data; outimg = InitMat(m_pNode_output_0->channel, m_pNode_output_0->width, m_pNode_output_0->height); uchar *p_outdata_1 = (uchar *)outimg.data; if (!m_bInitSuccess) { return 2; } AI_Det_In_1_Out_1(m_pNode_input_0, m_pNode_output_0, p_indata_0, p_outdata_1); return 0; } int AIModel_Impl::AIDet(const cv::Mat &inImg, cv::Mat &outimg0, cv::Mat &outimg1) { return 0; } int AIModel_Impl::AIClass(const cv::Mat &inImg, float *fmaxScore) { // 1、准备数据 if (m_pNode_input_0 == NULL || m_pNode_output_0 == NULL) { printf("AIDet: Node Config INput output Node error \n"); return -1; } if (!m_bInitSuccess) { return -2; } uchar *p_indata_0 = (uchar *)inImg.data; int class_dix = 0; class_dix = AI_Det_In_1_Out_1_class(p_indata_0, fmaxScore); return class_dix; } // 检测模型的运行参数是否合法,是否正常 int AIModel_Impl::ModelRunConfigCheck(AIModelRun_Config &runConfig) { // GPU 数量判断 if (runConfig.gpuconfig.GetNum() == 0) { return 1; } if (runConfig.strPath == "") { printf(" %s model path is error \n", runConfig.strName.c_str()); return 2; } if (runConfig.Stream_num <= 0) { runConfig.Stream_num = 1; } if (runConfig.Stream_num > 4) { runConfig.Stream_num = 4; } return 0; } // 载入模型。。。。 int AIModel_Impl::LoadEngine(int ngpuIdx) { std::shared_ptr gpuEngine = std::make_shared(); gpuEngine->engine = std::make_shared(ngpuIdx); gpuEngine->nGPUIdx = ngpuIdx; if (!gpuEngine->engine) { printf("Engine Create error\n"); return -1; } // 1、加载模型 bool reload = gpuEngine->engine->loadFromFile(m_modelRun_Config.strPath); if (!reload) { printf("GPU %d Load error %s\n", ngpuIdx, m_modelRun_Config.strPath.c_str()); printf("Load model error\n"); return -2; } printf("%s GPU %d Load succ %s\n", m_modelRun_Config.strName.c_str(), ngpuIdx, m_modelRun_Config.strPath.c_str()); // 2、 解析 egengine的 相关信息 int re = GetEngineInfo1(gpuEngine); if (re != 0) { return re; } // 没有输入输出 节点。 if (m_modelNodeList.size() <= 0 || m_modelNodeList.size() > MAX_MODEL_NODE_NUM) { printf("Load model input output error\n"); return -3; } cudaSetDevice(ngpuIdx); // 3、 申请显存 for (int i = 0; i < m_modelRun_Config.Stream_num; i++) { std::shared_ptr cudasteam = std::make_shared(); cudasteam->nstreamIdx = i; if (cudaStreamCreate(&cudasteam->stream) != cudaSuccess) { printf("Failed to create CUDA stream\n"); return -4; } cudasteam->context = std::unique_ptr( gpuEngine->engine->engine_->createExecutionContext()); // printf("----- stream %d \n", i); // 初始化 数据 内存 for (int j = 0; j < m_modelNodeList.size(); j++) { std::shared_ptr steamNodeconfig = std::make_shared(); steamNodeconfig->nodeConfig.copy(m_modelNodeList.at(j)); cudaMalloc(&steamNodeconfig->gpu_buffers, steamNodeconfig->nodeConfig.floatsize); cudaMalloc(&steamNodeconfig->gpu_ImgData, steamNodeconfig->nodeConfig.ucharsize); // 分类 的模型 if (m_modelRun_Config.IsClass) { if (steamNodeconfig->cpu_floatData) { delete steamNodeconfig->cpu_floatData; steamNodeconfig->cpu_floatData = NULL; } steamNodeconfig->cpu_floatData = new float[steamNodeconfig->nodeConfig.datalength]; } printf("-----******GPU %d stream %d cuda malloc %d inOrout %d [chw] %d*%d*%d \n", ngpuIdx, i, j, steamNodeconfig->nodeConfig.type, steamNodeconfig->nodeConfig.channel, steamNodeconfig->nodeConfig.height, steamNodeconfig->nodeConfig.width); if (m_modelNodeList.at(j).type == AI_Buffer_Type_INPUT) { if (cudasteam->pstreamNode_input_0 == nullptr) { cudasteam->pstreamNode_input_0 = steamNodeconfig; } else { cudasteam->pstreamNode_input_1 = steamNodeconfig; } } else { if (cudasteam->pstreamNode_output_0 == nullptr) { cudasteam->pstreamNode_output_0 = steamNodeconfig; } else if (cudasteam->pstreamNode_output_1 == nullptr) { cudasteam->pstreamNode_output_1 = steamNodeconfig; } else { cudasteam->pstreamNode_output_2 = steamNodeconfig; } } cudasteam->streamConfigList.push_back(steamNodeconfig); } gpuEngine->cudaSteams.push_back(cudasteam); } gpuEngine->bsucc = true; m_GPU_Engine.push_back(gpuEngine); return 0; } int AIModel_Impl::GetEngineInfo1(std::shared_ptr &pgpuengine) { int nInputNum = pgpuengine->engine->getNbBindings(); m_modelNodeList.erase(m_modelNodeList.begin(), m_modelNodeList.end()); m_modelNodeList.clear(); for (int i = 0; i < nInputNum; i++) { Node_Config node_config; std::string name = pgpuengine->engine->getBindingName(i); node_config.name = name; Dims dims = pgpuengine->engine->getBindingDims(i); if (pgpuengine->engine->bindingIsInput(i)) { std::cout << "Input: " << name << "\n"; node_config.type = AI_Buffer_Type_INPUT; } else { std::cout << "Output: " << name << "\n"; node_config.type = AI_Buffer_Type_OUTPUT; } std::cout << "dims.nbDims: " << dims.nbDims << "\n"; if (dims.nbDims == 4) { switch (m_modelRun_Config.inputType) { case Input_CHW: node_config.channel = dims.d[1]; node_config.height = dims.d[2]; node_config.width = dims.d[3]; break; case Input_HWC: node_config.height = dims.d[1]; node_config.width = dims.d[2]; node_config.channel = dims.d[3]; break; default: node_config.channel = dims.d[1]; node_config.height = dims.d[2]; node_config.width = dims.d[3]; break; } } else if (dims.nbDims == 3) { switch (m_modelRun_Config.inputType) { case Input_CHW: node_config.channel = dims.d[0]; node_config.height = dims.d[1]; node_config.width = dims.d[2]; break; case Input_HWC: node_config.height = dims.d[0]; node_config.width = dims.d[1]; node_config.channel = dims.d[2]; break; default: node_config.channel = dims.d[0]; node_config.height = dims.d[1]; node_config.width = dims.d[2]; break; } } else if (dims.nbDims == 2) { node_config.channel = 1; node_config.height = dims.d[0]; node_config.width = dims.d[1]; } else if (dims.nbDims == 1) { node_config.channel = 1; node_config.height = dims.d[0]; node_config.width = 1; } else { printf("engine C H W is error\n"); return -2; } node_config.CalDataSize(); m_modelNodeList.push_back(node_config); printf("dim: "); for (int di = 0; di < dims.nbDims; di++) { printf(" %ld ", dims.d[di]); } printf(" \n"); printf("C H W [%d %d %d]\n", node_config.channel, node_config.height, node_config.width); } return 0; } int AIModel_Impl::AI_Det_In_1_Out_1(Node_Config *pConfig_in, Node_Config *pConfig_out, const unsigned char *p_indata_0, unsigned char *p_outdata_1) { // printf("=== s1 "); std::shared_ptr pdetStream; if (GetStream(pdetStream) != 0 || !pdetStream) { printf("AI_Det_In_1_Out_1: GetStream error \n"); return 3; } // printf("=== s2 "); std::lock_guard lock(pdetStream->AI_mutex); // printf(" ss g %d s %d -- ", pdetStream->nGPUIdx, pdetStream->cuda_stream->nstreamIdx); // // 设置 显卡ID cudaSetDevice(pdetStream->nGPUIdx); cudaMemcpyAsync(pdetStream->cuda_stream->pstreamNode_input_0->gpu_ImgData, p_indata_0, pConfig_in->ucharsize, cudaMemcpyHostToDevice, pdetStream->cuda_stream->stream); // // // 在显存中 图片数据从 uchar 转到 float Cuda_ucharToFloat_stream((unsigned char *)pdetStream->cuda_stream->pstreamNode_input_0->gpu_ImgData, (float *)pdetStream->cuda_stream->pstreamNode_input_0->gpu_buffers, pConfig_in->datalength, pdetStream->cuda_stream->stream); pdetStream->cuda_stream->context->setTensorAddress(pConfig_in->name.c_str(), pdetStream->cuda_stream->pstreamNode_input_0->gpu_buffers); pdetStream->cuda_stream->context->setTensorAddress(pConfig_out->name.c_str(), pdetStream->cuda_stream->pstreamNode_output_0->gpu_buffers); pdetStream->cuda_stream->context->enqueueV3(pdetStream->cuda_stream->stream); Cuda_FloatTouchar_stream((float *)pdetStream->cuda_stream->pstreamNode_output_0->gpu_buffers, (unsigned char *)pdetStream->cuda_stream->pstreamNode_output_0->gpu_ImgData, pConfig_out->datalength, pdetStream->cuda_stream->stream); cudaMemcpyAsync(p_outdata_1, pdetStream->cuda_stream->pstreamNode_output_0->gpu_ImgData, pConfig_out->ucharsize, cudaMemcpyDeviceToHost, pdetStream->cuda_stream->stream); cudaStreamSynchronize(pdetStream->cuda_stream->stream); // printf("**ee g %d s %d ** \n", pdetStream->nGPUIdx, pdetStream->cuda_stream->nstreamIdx); return 0; } int AIModel_Impl::GetStream(std::shared_ptr &pdetStream) { if (m_nALLStreamNum <= 0 || m_DetGPUStream.empty()) { return 1; } // 多线程并发时原子轮询分配 stream: int sidx = m_nLast_GPUStreamIdx.load(); while (true) { int next = sidx + 1; if (next >= m_nALLStreamNum) { next = 0; } if (m_nLast_GPUStreamIdx.compare_exchange_weak(sidx, next)) { sidx = next; break; } // CAS 失败时 sidx 已被更新为当前实际值,重新计算 next } pdetStream = m_DetGPUStream.at(sidx); return 0; } int AIModel_Impl::AI_Det_In_1_Out_1_class(unsigned char *p_indata_0, float *fmaxScore) { std::shared_ptr pdetStream; if (GetStream(pdetStream) != 0 || !pdetStream) { printf("AI_Det_In_1_Out_1_class: GetStream error \n"); *fmaxScore = 0.0f; return -3; } // printf("=== s2 "); std::lock_guard lock(pdetStream->AI_mutex); // printf(" ss g %d s %d -- ", pdetStream->nGPUIdx, pdetStream->cuda_stream->nstreamIdx); // // 设置 显卡ID std::shared_ptr p_input_0 = pdetStream->cuda_stream->pstreamNode_input_0; std::shared_ptr p_output_0 = pdetStream->cuda_stream->pstreamNode_output_0; cudaSetDevice(pdetStream->nGPUIdx); cudaMemcpyAsync(p_input_0->gpu_ImgData, p_indata_0, p_input_0->nodeConfig.ucharsize, cudaMemcpyHostToDevice, pdetStream->cuda_stream->stream); // // // 在显存中 图片数据从 uchar 转到 float Cuda_ucharToFloat_stream((unsigned char *)p_input_0->gpu_ImgData, (float *)p_input_0->gpu_buffers, p_input_0->nodeConfig.datalength, pdetStream->cuda_stream->stream); pdetStream->cuda_stream->context->setTensorAddress(p_input_0->nodeConfig.name.c_str(), p_input_0->gpu_buffers); pdetStream->cuda_stream->context->setTensorAddress(p_output_0->nodeConfig.name.c_str(), p_output_0->gpu_buffers); pdetStream->cuda_stream->context->enqueueV3(pdetStream->cuda_stream->stream); cudaMemcpyAsync(p_output_0->cpu_floatData, p_output_0->gpu_buffers, p_output_0->nodeConfig.floatsize, cudaMemcpyDeviceToHost, pdetStream->cuda_stream->stream); cudaStreamSynchronize(pdetStream->cuda_stream->stream); int label = F2softmaxId(p_output_0->cpu_floatData, p_output_0->nodeConfig.datalength, fmaxScore); return label; } int AIModel_Impl::F2softmaxId(float *data, int class_num, float *fmaxScore) { int cls_num = class_num; float total = 0; for (int i = 0; i < cls_num; i++) { // std::cout<<"data["<