轻量级高性能推理引擎MNN 学习笔记 02.MNN主要API
1. MNN 主要API
注意:本学习笔记只介绍了我在学习过程中常用的API ,更多MNN API 请参考官方文档。
1.1. 推理时操作流程
- 创建Interpreter : createFromFile()
- 通过Interpreter创建Session :createSession()
- 设置输入数据: getSessionInput()、map()、unmap()、copyFromHostTensor()
- 通过Session进行推理: runSession()
- 获取推理结果 :getSessionOutput()、map()、unmap()、copyToHostTensor()
- 释放Interpreter:delete
1.2. Interpreter
使用MNN推理时,有两个层级的抽象,分别是解释器Interpreter
和会话Session
。Interpreter
是模型数据的持有者;Session
通过Interpreter
创建,是推理数据的持有者。多个推理可以共用同一个模型,即多个Session
可以共用一个Interpreter
。
在创建完Session
,且不再创建Session
或更新训练模型数据时,Interpreter
可以通过releaseModel
函数释放模型数据,以节省内存。
1.2.1. 创建Interpreter
通过磁盘文件创建
/*** @brief create net from file.* @param file given file.* @return created net if success, NULL otherwise.*/
static Interpreter* createFromFile(const char* file);
函数返回的Interpreter
实例是通过new
创建的,务必在不再需要时,通过delete
释放,以免造成内存泄露。
1.3. Session
一般通过Interpreter::createSession
创建Session
:
/*** @brief create session with schedule config. created session will be managed in net.* @param config session schedule config.* @return created session if success, NULL otherwise.*/
Session* createSession(const ScheduleConfig& config);
函数返回的Session
实例是由Interpreter
管理,随着Interpreter
销毁而释放,一般不需要关注。也可以在不再需要时,调用Interpreter::releaseSessio
n释放,减少内存占用。
创建Session
一般而言需要较长耗时,而Session
在多次推理过程中可以重复使用,建议只创建一次多次使用。
1.4. ScheduleConfig
简易模式:不需要额外设置调度配置,函数会根据模型结构自动识别出调度路径、输入输出,例如:
ScheduleConfig conf;
Session* session = interpreter->createSession(conf); // 创建Session
这种模式下采用CPU推理。
高级模式:需要设置调度配置,例如:
/** session schedule config */
struct ScheduleConfig {/** which tensor should be kept */std::vector<std::string> saveTensors;/** forward type */MNNForwardType type = MNN_FORWARD_CPU;/** CPU:number of threads in parallel , Or GPU: mode setting*/union {int numThread = 4;int mode;};/** subpath to run */struct Path {std::vector<std::string> inputs;std::vector<std::string> outputs;enum Mode {/*** Op Mode* - inputs means the source op, can NOT be empty.* - outputs means the sink op, can be empty.* The path will start from source op, then flow when encounter the sink op.* The sink op will not be compute in this path.*/Op = 0,/*** Tensor Mode* - inputs means the inputs tensors, can NOT be empty.* - outputs means the outputs tensors, can NOT be empty.* It will find the pipeline that compute outputs from inputs.*/Tensor = 1};/** running mode */Mode mode = Op;};Path path;/** backup backend used to create execution when desinated backend do NOT support any op */MNNForwardType backupType = MNN_FORWARD_CPU;/** extra backend config */BackendConfig* backendConfig = nullptr;
};
推理时,主选后端由type
指定,默认为CPU
。若模型中存在主选后端不支持的算子,这些算子会使用由backupType
指定的备选后端运行。
推理路径包括由path
的inputs
到outputs
途径的所有算子,在不指定时,会根据模型结构自动识别。为了节约内存,MNN
会复用outputs
之外的tensor
内存。如果需要保留中间tensor
的结果,可以使用saveTensors
保留tensor
结果,避免内存复用。
CPU
推理时,并发数与线程数可以由numThread
修改。numThread
决定并发数的多少,但具体线程数和并发效率,不完全取决于numThread
:
-
iOS
,线程数由系统GCD
决定; -
启用
MNN_USE_THREAD_POOL
时,线程数取决于第一次配置的大于1的numThread
; -
OpenMP
,线程数全局设置,实际线程数取决于最后一次配置的numThread
;
GPU
推理时,可以通过mode
来设置GPU
运行的一些参量选择(暂时只支持OpenCL
)。GPU
mode
参数如下:
typedef enum {// choose one tuning mode OnlyMNN_GPU_TUNING_NONE = 1 << 0,/* Forbidden tuning, performance not good */MNN_GPU_TUNING_HEAVY = 1 << 1,/* heavily tuning, usually not suggested */MNN_GPU_TUNING_WIDE = 1 << 2,/* widely tuning, performance good. Default */MNN_GPU_TUNING_NORMAL = 1 << 3,/* normal tuning, performance may be ok */MNN_GPU_TUNING_FAST = 1 << 4,/* fast tuning, performance may not good */// choose one opencl memory mode Only/* User can try OpenCL_MEMORY_BUFFER and OpenCL_MEMORY_IMAGE both, then choose the better one according to performance*/MNN_GPU_MEMORY_BUFFER = 1 << 6,/* User assign mode */MNN_GPU_MEMORY_IMAGE = 1 << 7,/* User assign mode */
} MNNGpuMode;
目前支持tuning
力度以及GPU
memory
用户可自由设置。例如:
MNN::ScheduleConfig config;
config.mode = MNN_GPU_TUNING_NORMAL | MNN_GPU_MEMORY_IMAGE;
tuning
力度选取越高,第一次初始化耗时越多,推理性能越佳。如果介意初始化时间过长,可以选取MNN_GPU_TUNING_FAST
或者MNN_GPU_TUNING_NONE
,也可以同时通过下面的cache
机制,第二次之后就不会慢。GPU_Memory
用户可以指定使用MNN_GPU_MEMORY_BUFFER
或者MNN_GPU_MEMORY_IMAGE
,用户可以选择性能更佳的那一种。如果不设定,框架会采取默认判断帮你选取(不保证一定性能最优)。
上述CPU
的numThread
和GPU
的mode
,采用union
联合体方式,共用同一片内存。用户在设置的时候numThread
和mode
只需要设置一种即可,不要重复设置。
对于GPU
初始化较慢的问题,提供了Cache
机制。后续可以直接加载cache
提升初始化速度。
- 具体可以参考tools/cpp/MNNV2Basic.cpp里面setCacheFile设置cache方法进行使用。
- 当模型推理输入尺寸有有限的多种时,每次resizeSession后调用updateCacheFile更新cache文件。
- 当模型推理输入尺寸无限随机变化时,建议config.mode设为1,关闭MNN_GPU_TUNING。
1.5. 输入数据
1.5.1. 获取输入tensor
/*** @brief get input tensor for given name.* @param session given session.* @param name given name. if NULL, return first input.* @return tensor if found, NULL otherwise.*/
Tensor* getSessionInput(const Session* session, const char* name);/*** @brief get all input tensors.* @param session given session.* @return all output tensors mapped with name.*/
const std::map<std::string, Tensor*>& getSessionInputAll(const Session* session) const;
Interpreter
上提供了两个用于获取输入Tensor
的方法:getSessionInput
用于获取单个输入tensor
, getSessionInputAll
用于获取输入tensor
映射。
在只有一个输入tensor
时,可以在调用getSessionInput
时传入NULL
以获取tensor
。
1.5.2. 【推荐】映射填充数据
映射输入Tensor的内存,部分后端可以免数据拷贝
auto input = interpreter->getSessionInput(session, NULL);
void* host = input->map(MNN::Tensor::MAP_TENSOR_WRITE, input->getDimensionType());
// fill host memory data
input->unmap(MNN::Tensor::MAP_TENSOR_WRITE, input->getDimensionType(), host);
1.5.3. 【不推荐】拷贝填充数据
NCHW
示例,适用 ONNX
/ Caffe
/ Torchscripts
转换而来的模型:
auto inputTensor = interpreter->getSessionInput(session, NULL);
auto nchwTensor = new Tensor(inputTensor, Tensor::CAFFE);
// nchwTensor-host<float>()[x] = ...
inputTensor->copyFromHostTensor(nchwTensor);
delete nchwTensor;
通过这类拷贝数据的方式,用户只需要关注自己创建的tensor
的数据布局,copyFromHostTensor
会负责处理数据布局上的转换(如需)和后端间的数据拷贝(如需)。
1.6. 运行会话
MNN
中,Interpreter
一共提供了三个接口用于运行Session
,但一般来说,简易运行就足够满足绝对部分场景。
1.6.1. 简易运行
/*** @brief run session.* @param session given session.* @return result of running.*/
ErrorCode runSession(Session* session) const;
1.7. 获取输出tensor
/*** @brief get output tensor for given name.* @param session given session.* @param name given name. if NULL, return first output.* @return tensor if found, NULL otherwise.*/
Tensor* getSessionOutput(const Session* session, const char* name);/*** @brief get all output tensors.* @param session given session.* @return all output tensors mapped with name.*/
const std::map<std::string, Tensor*>& getSessionOutputAll(const Session* session) const;
Interpreter
上提供了两个用于获取输出Tensor
的方法:getSessionOutput
用于获取单个输出tensor
, getSessionOutputAll
用于获取输出tensor
映射。
在只有一个输出tensor
时,可以在调用getSessionOutput
时传入NULL
以获取tensor
。
1.7.1. 【推荐】映射输出数据
映射输出Tensor的内存数据,部分后端可以免数据拷贝
auto outputTensor = net->getSessionOutput(session, NULL);
void* host = outputTensor->map(MNN::Tensor::MAP_TENSOR_READ, outputTensor->getDimensionType());
// use host memory by yourself
outputTensor->unmap(MNN::Tensor::MAP_TENSOR_READ, outputTensor->getDimensionType(), host);
1.7.2. 【不推荐】拷贝输出数据
NCHW
示例,适用 ONNX
/ Caffe
/ Torchscripts
转换而来的模型:
auto outputTensor = interpreter->getSessionOutput(session, NULL);
auto nchwTensor = new Tensor(outputTensor, Tensor::CAFFE);
outputTensor->copyToHostTensor(nchwTensor);
auto score = nchwTensor->host<float>()[0];
auto index = nchwTensor->host<float>()[1];
// ...
delete nchwTensor;
通过这类拷贝数据的方式,用户只需要关注自己创建的tensor
的数据布局,copyToHostTensor
会负责处理数据布局上的转换(如需)和后端间的数据拷贝(如需)
enum
MNNForwardType
缺省值是 MNN_FORWARD_CPU =0 ,即表示采用CPU后端进行推理。
typedef enum {MNN_FORWARD_CPU = 0,/*Firtly find the first available backends not equal to CPUIf no other backends, use cpu*/MNN_FORWARD_AUTO = 4,/*Hand write metal*/MNN_FORWARD_METAL = 1,/*NVIDIA GPU API*/MNN_FORWARD_CUDA = 2,/*Android / Common Device GPU API*/MNN_FORWARD_OPENCL = 3,MNN_FORWARD_OPENGL = 6,MNN_FORWARD_VULKAN = 7,/*Android 8.1's NNAPI or CoreML for ios*/MNN_FORWARD_NN = 5,/*User can use API from Backend.hpp to add or search Backend*/MNN_FORWARD_USER_0 = 8,MNN_FORWARD_USER_1 = 9,MNN_FORWARD_USER_2 = 10,MNN_FORWARD_USER_3 = 11,MNN_FORWARD_ALL = 12,/* Apply arm extension instruction set to accelerate some Ops, this forward typeis only used in MNN internal, and will be active automatically when user set forward typeto be MNN_FORWARD_CPU and extension instruction set is valid on hardware.*/MNN_FORWARD_CPU_EXTENSION = 13,// use for shared memory on android deviceMNN_MEMORY_AHARDWAREBUFFER = 14
} MNNForwardType;
1.8. 参考
- Session API使用 — MNN-Doc 2.1.1 documentation
相关文章:
轻量级高性能推理引擎MNN 学习笔记 02.MNN主要API
1. MNN 主要API 注意:本学习笔记只介绍了我在学习过程中常用的API ,更多MNN API 请参考官方文档。 1.1. 推理时操作流程 创建Interpreter : createFromFile()通过Interpreter创建Session :createSession()设置输入数据: getSes…...
STM32 ADC 模数转换器详解:原理、配置与应用
STM32 ADC 模数转换器详解:原理、配置与应用 在嵌入式系统中,模数转换(ADC)是实现传感器信号采集、信号处理等任务的关键环节。STM32 微控制器作为一款功能强大的 32 位微控制器,其内置的 ADC 模块为开发者提供了高效…...
18.Excel数据透视表:第1部分创建数据透视表
一 什么是数据透视表 通过万花筒可以用不同的方式査看里面画面图像,在excel中可以将数据透视表看作是对准数据的万花筒,用不同角度去观察数据,也可以旋转数据,对数据进行重新排列,对大量的数据可以快速的汇总和建立交叉…...
AI 模型训练轻量化技术在军事领域的实战应用与技术解析
AI 模型训练轻量化技术在军事领域的实战应用与技术解析 一、引言 在人工智能与军事领域深度融合的当下,AI 模型训练轻量化技术正成为破解战场资源限制的关键钥匙。通过模型压缩、量化、剪枝等核心技术,轻量化模型在算力受限、通信不稳定的复杂战场环境中…...
科学养生,开启健康生活
在快节奏的现代生活中,健康养生成为人们关注的焦点。科学合理的养生方式,无需依赖传统医学理论,也能有效提升生活质量,为身体注入活力。 均衡饮食是养生的基础。每天应保证摄入足够的蛋白质、碳水化合物和脂肪,同时…...
高效跨平台文件传输与管理的工具
软件介绍 这款名为 Coolmuster Mobile Transfer 的工具是一款多平台支持的文件传输工具,能高效地在不同设备间进行文件传输与管理。 适用场景 它适用于多种场景,无论是个人文件整理、家庭成员间资料共享,还是企业场景下的工作文件处理&…...
如何优化 Linux 服务器的磁盘 I/O 性能
# 优化 Linux 服务器磁盘 I/O 性能的全面指南 ## 1. 识别 I/O 瓶颈 首先确定是否存在 I/O 瓶颈以及瓶颈位置: bash # 使用 iostat 查看磁盘 I/O 统计 iostat -x 1 # 使用 iotop 查看进程级 I/O 使用情况 iotop # 使用 vmstat 查看系统整体 I/O 情况 vmstat 1 …...
Python基础学习-Day23
目录 基础概念转换器(transformer)估计器(estimator)管道(pipeline) 实例pipeline 基础概念 pipeline在机器学习领域可以翻译为“管道”,也可以翻译为“流水线”,是机器学习中一个重…...
【Ubuntu】扩充磁盘大小
sudo apt-get install gparted 安装完成后,搜索gparted软件,打开gparted 参考...
数据治理域——日志数据采集设计
摘要 本文主要介绍了Web页面端日志采集的设计。首先阐述了页面浏览日志采集,包括客户端日志采集的实现方式、采集内容及技术亮点。接着介绍了无线客户端端日志采集,包括UserTrack的核心设计、移动端与浏览器端采集差异以及典型应用场景崩溃分析。最后探…...
Dinky 安装部署并配置提交 Flink Yarn 任务
官方文档 https://www.dinky.org.cn/docs/1.1/deploy_guide/normal_deploy 版本 dinky 1.1.0、1.2.3 当前最新发布版本为 1.2.3 ,但是官方文档最新稳定版为 1.1 ,所以先选择 1.1.0,验证通过后,再尝试 1.2.3 ,发现 1…...
杰理-701-手表sdk无法电脑连接经典蓝牙
杰理-701-手表sdk无法电脑连接经典蓝牙 只有手机可以连接经典蓝牙播放音乐,电脑无法连接,需要关闭emitter功能 交流q群:187115320...
Timsort 算法
文章目录 1 基础理解1.1 定义和原理1.2 工作原理 2 算法实现2.1 Python 代码实现2.1.1 代码2.1.2 核心逻辑计算最小运行长度(calc_min_run(n))插入排序(insertion_sort(arr, left, right)) 2.2 Java 代码实现2.3 C 代码实现 3 逻辑…...
Go构建高并发权重抽奖系统:从设计到优化全流程指南
引言:为何需要专业抽奖系统? 在现代互联网应用中,抽奖系统被广泛用于营销活动、用户激励等场景。一个好的抽奖系统需要满足: 公平性:确保概率分布准确高性能:支持高并发抽奖请求安全性:防止作…...
深度学习计算
深度学习的飞速发展离不开强大的计算能力支撑。从张量计算到 GPU 加速,从自动微分到分布式计算,深度学习计算的每一项技术都如同精密仪器中的关键齿轮,推动着模型性能的不断提升。本文深入剖析深度学习计算的核心技术、优化策略以及前沿趋势&…...
【Bluedroid】蓝牙 HID DEVICE 初始化流程源码解析
本文深入剖析Android蓝牙协议栈中HID设备(BT-HD)服务的初始化与启用流程,从接口初始化、服务掩码管理、服务请求路由到属性回调通知,完整展现蓝牙HID服务激活的技术路径。通过代码逻辑梳理,揭示服务启用的核心机制&…...
Kotlin 中的 Unit 类型的作用以及 Java 中 Void 的区别
在 Kotlin 中,Unit 类型和 Java 中的 void 关键字都用于表示“没有返回值”的函数,但它们在设计理念、类型系统和实际使用中有显著的区别。 1 Kotlin 中的 Unit 类型 表示无返回值: 当函数不返回有意义的值时,Kotlin 使用 Unit …...
Gemini 2.5 推动视频理解进入新时代
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
Spark Streaming 内部运行机制详解
核心思想:将实时数据流切割为“微批次”,利用 Spark Core 的批处理能力进行准实时计算。 1. 核心流程拆解 数据接收(Input Data Stream) 输入源:Kafka、Flume、Socket 等实时数据流。 接收器(Receiver&…...
Feign+Resilience4j实现微服务熔断机制:原理与实战
引言:为什么需要熔断器? 在微服务架构中,服务间的依赖调用变得非常普遍。想象一下这样的场景:订单服务依赖支付服务,支付服务又依赖银行网关服务。如果银行网关服务出现故障,故障会向上蔓延,导…...
什么是SparkONYarn模式
1. 什么是 Spark on YARN? Spark on YARN 是 Apache Spark 的一种部署模式,允许 Spark 应用程序在 Hadoop YARN 集群上运行,充分利用 YARN 的资源管理和调度能力。这种模式将 Spark 与 Hadoop 生态深度集成,使企业能够在同一集群…...
鸿蒙北向应用开发: deveco5.0 创建开源鸿蒙项目
本地已经安装deveco5.0 使用5.0创建开源鸿蒙项目 文件->新建->新建项目 直接创建空项目,一路默认 next 直接编译项目 直接连接开源鸿蒙5.0开发板编译会提示 compatibleSdkVersion and releaseType of the app do not match the apiVersion and releaseType on the dev…...
操作系统:内存管理
目录 1、主要目标 2、核心概念和技术 2.1 物理内存与虚拟内存 2.2 内存分页机制 2.3 页面置换算法 3、监控与性能优化 3.1 查看物理内存 3.2 查看虚拟内存 3.3 性能问题 1> 内存不足(OOM) 2> 内存泄漏 3> 内存碎片 3.4 性能优化策…...
腾讯优化DeepSeek的DeepEP通信框架:开启AI大模型训练新时代
事件背景 在人工智能(AI)技术迅猛发展的当下,大规模AI模型训练的需求与日俱增。高效的数据通信成为了提升AI模型训练效率的关键环节。混合专家模型(MoE)作为一种高效的大模型架构,通过动态分配专家网络处理…...
CSP-J普及组第一轮真题单选题专项训练(二)
CSP-J普及组第一轮真题单选题专项训练(二) (共15题,每2分,共30分;每题有且有一个正确选项) 1、一个 32 位整型变量占用()个字节。 A. 32 B. 128 C. 4 D. 8 2、在内存储器中每个存储单元都被赋予一个唯一的序号,称为 A、下标 B、序号 C、地址 D、编号 3、编译器的主要…...
Android加固工具测评:易盾、顶象、360加固哪款更好用?
应用安全已经成为每个开发者和企业关注的核心问题。随着黑客技术的不断升级,单一的安全措施已经无法有效应对各种复杂的攻击威胁。Android加固工具应运而生,成为了提升应用安全的关键利器。这些加固工具通过代码混淆、加密、防篡改等技术手段,…...
C++ 字符格式化输出
文章目录 一、简介二、实现代码三、实现效果 一、简介 这里使用std标准库简单实现一个字符格式化输出,方便后续的使用,它有点类似Qt中的QString操作。 二、实现代码 FMTString.hpp #pragma once#include <cmath> #include <cstdio> #include…...
内存中的“BANK”
一、BANK的定义与物理结构 基本概念 BANK(存储体) 是内存芯片内部的一个逻辑或物理分区,每个BANK由存储单元阵列、地址解码电路和缓冲器组成,用于分块管理内存操作。 作用:通过并行操作减少访问冲突,提升内…...
D-Pointer(Pimpl)设计模式(指向实现的指针)
Qt 的 D-Pointer(Pimpl)设计模式 1. Pimpl 模式简介 Pimpl(Pointer to Implementation)是一种设计模式,用于将类的接口与实现分离,从而隐藏实现细节,降低编译依赖,提高代码的可维护…...
XA协议和Tcc
基于 XA 协议的两阶段提交 (2PC)。这是一种分布式事务协议,旨在保证在多个参与者(通常是不同的数据库或资源管理器)共同参与的事务中,所有参与者要么都提交事务,要么都回滚事务,从而维护数据的一致性。 你…...
我们该如何使用DeepSeek帮我们减负?
在当今信息爆炸的时代,如何快速获取、筛选和分析信息已经成为各行各业的重要能力。而DeepSeek作为一种先进的智能搜索和信息挖掘工具,能够帮助用户快速找到所需的信息,并从海量数据中提取出有用的洞见。在这篇博文中,我们将深入探…...
25.5.13
感觉很久没有写算法题了,先来个滑动队列模板题试试水,就是用双端队列来实现会很方便,拿结构体来记录是第几个数和数的值即可,再定义两个双端队列,一个使他的值单调递增一个使他的值单调递减 使队头元素为最大值或者是最…...
软件测试——面试八股文(入门篇)
今天给大家分享软件测试面试题入门篇,看看大家能答对几题 一、 请你说一说测试用例的边界 参考回答: 边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法。通常边界值分析法是作为对等价类划分法的补充,这种情况下ÿ…...
脑机接口技术:开启人类与机器融合的新时代
摘要 脑机接口(BCI)技术作为一项前沿科技,正在逐步打破人类与机器之间的沟通障碍,为医疗、娱乐、教育等多个领域带来前所未有的变革。本文将详细介绍脑机接口技术的基本原理、发展现状、应用场景以及面临的挑战和未来发展趋势&…...
当三维地理信息遇上气象预警:电网安全如何实现“先知先觉”?
极端天气频发的当下,一场台风、一次暴雨就可能让电力系统陷入瘫痪。但你知道吗?如今的电网已能通过三维地理信息与气象数据的深度融合,在灾害来临前精准锁定风险,甚至将停电事故减少七成以上。这背后,正是国网电力空间…...
C++ string数据查找、string数据替换、string子串获取
string查找示例见下,代码见下,以及对应运行结果见下: #include<iostream>using namespace std;int main() {// 1string s1 "hellooooworld";cout << s1.find("oooo") << endl;// 2cout << (in…...
2025.5.13山东大学软件学院计算机图形学期末考试回忆版本
2025.5.13山东大学软件学院计图期末考试回忆版本 学院:软件学院 老师:周元峰、魏广顺 一、简述题(2024原题一) 1.图形绘制流水线的组成和作用 2.双缓冲机制是什么,有什么作用? 3.Delaunay三角化的四条…...
思极地图使用
思极地图api文档:思极地图开放平台 | 思极地图API SDK 思极地图SDK: <script src"https://map.sgcc.com.cn/maps?v3.0.0"></script> <script src"https://map.sgcc.com.cn/products/js-sdk/v3/assets/js/jquery-1.11.1.min.js&quo…...
Fiori学习专题四十一:表单控件
上节课我们学习了一些单一控件的使用,但是我们发现在页面内每个控件都占用了一行,这样子就显得不太好看,这节课我们引入一个表单控件来美化一下这个页面。 1.学习表单控件FORM之前我们先了解下哪些情况会使用到表单控件,最常见的场…...
基于STM32、HAL库的TDA7719TR音频接口芯片驱动程序设计
一、简介: TDA7719TR 是 NXP Semiconductors 推出的高性能音频处理芯片,专为汽车音响系统设计。它集成了 AM/FM 收音机调谐器、音频处理和音量控制功能,支持 I2C 控制接口,非常适合与 STM32 微控制器配合使用。 二、硬件接口: 典型的 STM32L4 与 TDA7719TR 硬件连接如下…...
Baklib智能云平台加速企业数据治理
Baklib数据治理核心优势 Baklib作为新一代企业级知识中台,其数据治理能力建立在全资产统一管理与智能化处理框架的双重基础之上。通过构建知识中台的核心架构,平台实现了图文、音视频等多模态数据的标准化存储与动态标签体系,有效解决传统管…...
面试中被问到谈谈你对threadlocal的理解
ThreadLocal 的核心理解 1. 基本概念 ThreadLocal 是 Java 提供的线程局部变量机制,用于在多线程环境中为每个线程维护独立的变量副本,实现线程隔离。其核心思想是空间换时间,通过避免共享变量带来的同步开销,提升并发性能。 2…...
Spring Boot 应用中实现基本的 SSE 功能
SSE 技术简介 SSE(Server-Sent Events)是一种允许服务器主动向客户端推送数据的技术。它基于 HTTP 长连接,使用简单,特别适合实时数据更新场景,如股票行情、新闻推送等。与 WebSocket 相比,SSE 更轻量级&a…...
【2025最新】Windows系统装VSCode搭建C/C++开发环境(附带所有安装包)
文章目录 为什么选择VSCode作为C/C开发工具?一、VSCode安装过程(超简单!)二、VSCode中文界面设置(再也不用对着英文发愁!)三、安装C/C插件(编程必备神器!)四、…...
【MyBatis-8】MyBatis对象关联查询详解:高效处理复杂关系映射
在实际业务开发中,我们经常需要处理对象之间的关联关系,如一对一、一对多、多对多等。MyBatis作为一款优秀的持久层框架,提供了强大的对象关联查询能力。本文将深入探讨MyBatis中各种关联查询的实现方式、适用场景及最佳实践。 1. MyBatis关…...
Java基础(IO)
所有操作都在内存,不能长时间保存,IO主要在硬盘,可以长时间保存。 一、File类 File类被定义为文件和目录路径名的抽象表示形式,这是因为 File 类既可以表示文件也可以表示目录,他们都通过对应的路径来描述。 提供构…...
Trae IDE:AI深度集成的智能开发环境
(以高效人机协作重塑编程体验) 概述 Trae IDE(发音 /treɪ/)是一款深度集成AI能力的现代化开发工具,结合传统IDE的完备功能与前沿AI技术,提供智能问答、代码自动补全、跨文件编程及AI Agent驱动的自动化开…...
网站开发过程中样式忽然不显示问题
老规矩,先听故事:今天我开发网站时候遇到一个问题,就开发的这个网站在默认127.0.0.1运行样式有bug显示不出来,之前都可以,就完全一样的代码,之前可以正常运行显示,今天忽然就不行了,…...
双种群进化算法:动态约束处理与资源分配解决约束多目标优化问题
双种群进化算法:动态约束处理与资源分配解决约束多目标优化问题 一、引言 约束多目标优化问题(CMOPs)在工程设计、资源分配等领域广泛存在,其核心是在满足多个约束条件的同时优化多个目标函数。传统方法往往难以平衡约束满足与目…...
如何在 CentOS 7 虚拟机上配置静态 IP 地址并保持重启后 SSH 连接
在使用 CentOS 7 的虚拟机时,我们通常需要配置静态 IP 地址,以确保在每次虚拟机重启后能够通过 SSH 连接。本文将介绍如何在 CentOS 7 系统中配置静态 IP 地址,并确保配置在系统重启后依然生效。 步骤 1:检查虚拟机网络接口 首先…...