0

嵌入式人工智能课程(华清远见)

四分卫
6天前 10

获课:xingkeit.top/5943/


嵌入式人工智能开发:C/C++与Python协同开发总结

聊这个话题之前,我想先说一个真实的项目经历。去年我们在一个边缘计算盒子上做工业缺陷检测,设备用的是ARM架构的Linux系统,算力不算强但够用。模型的训练和数据处理当然是用Python,几行代码就能把数据加载、增强、训练跑起来,效率很高。但模型训练完之后要部署到那个小盒子上,问题就来了——Python脚本加上依赖的环境,内存占用直接飙到三四百兆,推理一张图还要两三秒,根本没法用。

后来我们换了个思路:用Python做训练和原型验证,把训练好的模型转换出来,用C++写推理引擎,再通过Cython把C++的推理接口暴露给Python,两边协同工作。这一套改完之后,内存降到了一百兆以内,推理时间也缩短到了几百毫秒。这个经历让我深刻体会到,在嵌入式AI这个领域,C++和Python不是二选一,而是各取所长、协同作战。

为什么Python在嵌入式AI中不可或缺?答案很直接:生态。不管是PyTorch还是TensorFlow,不管是YOLO还是Hugging Face,AI领域的几乎所有工具链都是优先支持Python的。你要做数据预处理,pandas和numpy上手就用;你要做模型训练,几行代码就能开始;你要做可视化,matplotlib和tensorboard帮你把损失曲线画得清清楚楚。在算法的快速迭代阶段,Python的开发效率是C++没法比的。一个算法工程师用Python可能一天能跑通十几个实验,换成C++可能还在写数据加载器。

但Python的短板也很明显。在资源受限的嵌入式设备上,Python的解释器开销、动态类型、垃圾回收,每一个都是性能杀手。更麻烦的是,Python的运行时本身就要占不少内存——一个最小的Python环境,几兆到几十兆就出去了,这对只有几百兆内存的嵌入式设备来说是个不小的负担。再加上GIL的限制,Python在多核并行方面的表现也不尽如人意。

C++的优势刚好补上了这些短板。没有运行时开销,没有垃圾回收的停顿,内存可以精确控制,极致情况下甚至可以不用动态内存分配,全部静态分配。对于嵌入式设备来说,C++写出来的程序,体积小、启动快、运行稳。一个C++写的推理引擎,可能只有几百KB,而同样的Python推理脚本加上依赖,可能要几十MB起步。另外,C++对硬件的控制能力也更强,可以直接操作内存地址、配置外设寄存器、管理中断,这些在底层驱动和硬件加速器的调用中往往是必需的。

但C++在AI开发中的短板也很明显。训练一个深度学习模型用C++写,那工作量太大了,而且社区支持远不如Python。做数据探索和可视化,C++也没有Python那么方便。如果整个项目全部用C++写,开发周期可能会拉得很长。

所以现实的选择就是协同。把Python用在它擅长的地方,把C++用在它擅长的地方,两者之间搭一座桥。

协同开发的几种模式,我在实战中都有尝试,各有适用场景。

第一种是训练与推理分离。这是最常见的模式。Python端负责数据清洗、模型训练、超参数搜索,训练好的模型导出成通用的格式,比如ONNX或者TFLite。C++端负责加载模型、执行推理、集成到嵌入式设备的业务逻辑中。训练和推理完全解耦,两边各自迭代。我们之前的缺陷检测项目用的就是这个模式,Python端不断优化模型,C++端负责把模型跑得又快又稳。

第二种是Python调用C++扩展。有些计算密集型的模块,比如特定的图像预处理算法、自定义的算子,用Python写太慢,用C++写好了再包装成Python的扩展模块。Cython、pybind11、cffi,这几个工具都能做这件事。这样算法工程师可以在Python里正常调用这些模块,但实际执行的是编译好的C++代码,速度可以快几十倍。而且接口用起来和普通Python函数没区别,对上层代码几乎透明。

第三种是C++内嵌Python解释器。这个模式相对小众,但在某些场景下很有用。比如你的嵌入式主程序是用C++写的,但希望保留一定的动态扩展能力,允许用户或者运维人员写Python脚本来定制某些行为。C++可以内嵌一个Python解释器,把一些变量暴露给Python脚本,执行完再把结果取回来。这相当于给C++程序开了一个“热插拔”的脚本接口。

在实战中,协同开发也有不少坑需要注意。

第一个坑是数据传递的开销。Python和C++之间传递大量数据,尤其是图片、点云这种大块数据,序列化和拷贝的开销很可观。我们的经验是:尽量让数据留在同一块内存里,避免来回拷贝。比如用pybind11的时候,可以传递numpy数组的指针给C++函数,C++直接操作这块内存,不需要复制。如果数据量特别大,可以考虑用共享内存,Python和C++进程通过共享内存交换数据,效率更高。

第二个坑是内存管理边界。Python有垃圾回收,C++要手动管理内存。当两者混合时,谁负责分配、谁负责释放,必须在设计时就约定清楚。常见的做法是:谁分配谁释放。C++分配的内存,C++负责释放,Python只是借用;Python分配的内存,传给C++使用时,C++不能擅自释放。pybind11和一些工具提供了智能指针的自动转换,能减轻不少负担。

第三个坑是异常处理的跨语言传播。C++里抛出的异常,如果不做特殊处理,传到Python层就是一段乱码或者直接崩溃。需要把C++的异常捕获住,转换成Python的异常类型再抛出。同样,Python的异常传到C++层也需要正确处理。这些胶水代码虽然枯燥,但少了它会带来很多难以调试的问题。

第四个坑是依赖管理。一个混合了Python和C++的项目,依赖往往更复杂。Python那边有requirements.txt或者pyproject.toml,C++那边有CMake或者Makefile,两者还要协调版本、编译器、链接库。我们后来采用了容器化的方案——用Docker把整个开发环境固定下来,不管是训练还是交叉编译,都在同一个容器里进行。这样环境一致性的问题基本解决了。

回顾这些经历,我最大的体会是:嵌入式AI开发的核心能力,不是只会Python或者只会C++,而是能够根据场景,判断“这段代码该用什么语言写”。原型验证阶段,大胆用Python追求效率;产品落地阶段,关键路径用C++追求性能。两者不是对立的,而是同一个工具箱里的不同工具。

最后想说,如果你是做嵌入式AI开发的,不要被语言之争带偏了节奏。C++和Python谁更好这种问题没有意义,有意义的是:你的设备资源有多少?你的开发周期有多长?你的团队熟悉什么?在这些约束下,找到最合适的组合。大多数时候,答案是两者都用。



本站不存储任何实质资源,该帖为网盘用户发布的网盘链接介绍帖,本文内所有链接指向的云盘网盘资源,其版权归版权方所有!其实际管理权为帖子发布者所有,本站无法操作相关资源。如您认为本站任何介绍帖侵犯了您的合法版权,请发送邮件 [email protected] 进行投诉,我们将在确认本文链接指向的资源存在侵权后,立即删除相关介绍帖子!
最新回复 (0)

    暂无评论

请先登录后发表评论!

返回
请先登录后发表评论!