DPDK代码级调优之__rte_cache_aligned

原创 Linux阅码场 2022-02-23 08:00


黄鹏,目前就职于某网络安全公司,主要工作内容是DPDK应用程序性能调优,从事过企业级路由器维护与开发;面对问题衷于也善于求真,探求事物本质。



Part1引言


DPDKData Plane Development Kit)是由英特尔,6WIND等多家公司开发,主要基于Linux系统运行,用于快速数据包处理的函数库与驱动集合,可以极大提高数据处理性能和吞吐量,提高数据面应用程序的工作效率。其主要特点和优势有以下几点:


  • 1、 主程序运行在用户态,程序宕掉,不会影响系统崩溃,除非把内存都写坏;

  • 2、 报文收取方面,通过DMA加寄存器的使用实现了报文零拷贝;使用轮询代替中断;

  • 3、 对于具有多队列特性的网卡,可配置RSS功能,将不同队列绑定到不同的CPU核,进而完成报文收取的高效性;

  • 4、 内存管理方面,有一套完整的内存池API,避免程序频繁的mallocfree导致内存产生大量碎片;

  • 5、 TLB方面,通过使用大页表(一般的页表为2K/4KDPDK使用2M大页表)来减少TLB miss以提升性能;

  • 6、 常见的报文处理模型有pipelineRTCRun to Complite)两种,在多核情况下,使用报文批处理的技术时,势必会用到报文队列;DPDK提供了一套无锁队列(rte_ring)来提高报文的入队和出队的性能;

  • 7、 报文结构体mbuf经过精心设计,使其常用数据在同一个cache line不跨行,维持cache的热度;且mbuf头部预留128字节(DPDK默认值,用户可自己修改)供用户自定义并使用;

  • 8、 Cache方面,有预取APIrte_prefetch0)来提高/维持cache热度;数据结构体方面提供了__rte_cache_aligned将数据结构体进行cache line对其,避免在多核编程情况下,使用全局时,发生cache一致性问题导致CPU利用率不高问题;

  • 9、 针对网络开发(路由、防火墙、边缘网关等)DPDK还拥有ACLFlowLPM(最长前缀匹配)等一系列组件,加速了软件开发实现;若追求完美,自己实现也是很nice的。


Part2源起


本文中主要讲述数据结构体cache line对齐对性能的影响。


写之前,在这里先给大伙拜个晚到的新年快乐,祝福各位在2022这个虎年,虎虎生威、升职加薪、万事如意。


作为小老弟的我,从去年年底(大概是1112份左右),一时兴起决定使用开源的数据平面套件DPDK以及开源的quagga中的vtysh来实现自己的一个小小的防火墙软件,底层操作系统选用的是Centos7.2_1511 minimal这个发行版本。初生牛犊不怕虎,在公司内部使用了将近9个月DPDK,也算是有那么一些肤浅的认识,以及一些其他算法、报文处理流程上的开发经验,就直接开始上手干了,一天一天码一点,蜗牛式行动;这两天完成了最小的报文转发系统,较为完整的CLI命令行。


就在前些天,遇到了这么个事,事情经过大概如下:个人码好了最小的报文转发系统,兴致勃勃的使用IXIA Network打流仪器和设备,来进行测试下当前性能。


当时测试的时候,采用的配置是:分配一个核用于报文收发、两个核用于处理报文路由查询和邻居表查询,预期结果是:一对10GE接口、64字节能够达到线速的30%


但是,就是这个但是,实际测试结果呢,很是让我伤心,一开始只有可怜的11.25%,使用Intel Vtue软件定位分析后,性能能够到13.75%了,这个和自己心中的目标相差甚远。当时使用了perf top查看了下cache利用率以及IPC数值,结果如下:



 

一看Cache-misses75%,心中凉凉,IPCinsn per cycle)为2.43CPU配置是:


CPU MHz:               2194.839


BogoMIPS:              4389.67


Virtualization:        VT-x


L1d cache:             32K


L1i cache:             32K


L2 cache:              1024K


L3 cache:              14080K


NUMA node0 CPU(s):     0-19

 

后来,又在忙里偷闲,折腾折腾,发现当时测试有个问题,那就是数据处理核虽然分配的是两个核,但是实际只使用了一个核在进行数据处理(使用的命令是perf top -C cpuid),找了一下问题在哪里呢?


我再将报文收取上来后,使用hash.rss % 数据转发核,将其报文分配到不同的数据转发核对应Packet Ring中,但是呢,hash.rss一直未0;继续找原因发现接口的RSS功能我根本就没有开启。此时,心中甚是欢喜,想着一个核能达到13.75%了,两个也就能够直接到27%了,后面在继续调整调整,增加cache命中率啥的,性能也就差不多能到30%了,没有再继续深入探究了,毕竟还有一个更重要的流程ACL功能未开发。


Part3追寻



有了这次经验,突然想起,做性能调优,通常都需要对代码进行打桩,我为何不在代码中进行打桩统计一些CPU利用率呢?比如,之前测试,我已经完成了CPU利用率打桩代码,通过CLI类似于show lcore utili的命令来查看没有个逻辑核的CPU利用率,也就能更早的发现问题了。所以接下里的闲暇时光里,就来完成打桩代码的测试。这里先抛个砖,开发人员一般都会很忌讳进行增设统计值相关的代码,因为这个写的不好会造成很大的性能损耗,然而这事今天被我遇上了。


为了实现CPU利用率打桩代码,我基本的思路是这样的:统计一个周期内,空闲时间和正常报文被处理的时间,使用 execute time * 100 / (exexcute time + idle time)完成CPU利用率的粗略计算,所以很快的在代码中写下入了如下的代码:


typedef struct cpu_stats_s {

time_t sum_idle;

time_t sum_exec;

uint16_t utili;

    uint16_t lcore;

    uint16_t lcore_role;

} cpu_stats_t, *pcpu_stats_t;

 

cpu_stats_t gcpu_stat[MAX_LCORE];

在报文收发或者处理(路由查找、邻接查找)中写下了如下结构:

uint64_t st_tm = rte_rdtsc();

if (空闲)

gcpu_stat[lcore_id].sum_idle = rte_rdtsc() – st_tm;

else {

报文处理流程

gcpu_stat[lcore_id].sum_exec = rte_rdtsc() – st_tm;

}

再在非DPDK绑定的核或者叫做DPDKmaster-lcore上启动一个线程每个2秒,计算出每个lcore cpu的使用率。


同时也将CLI命令:show lcore utili命令编写完成,就在自己家中验证。搭建了一个简单的拓扑(本地环境很简陋):


  • 1、 Windows中使用Vmware搞了Linux虚拟机,使用tcpreplay一直回放报文来实现打流

使用命令:sar -n DEV 1可以看到发送速率在350pps单向。


  • 2、 在淘宝上买了一个硬件盒子,J4125 + I211网卡(千兆)

将编写好的程序放上去,开始打流,再使用perf工具,执行如下命令:


perf stat -e cycles,bus-cycles,ref-cycles,instructions,cache-references, cache misses,branches,branch-misses -p 4978 sleep 15

结果如下:

 



当我看到了,insns per cycle 0.29时,心中有些不安。我再次使用以前的程序,为带有CPU利用率打桩代码,测试结果如下:

 


这个差距不是一点点。然后,我继续查找了相关资料,想了解下insns per cycle的含义。

参考:https://blog.csdn.net/witsmakemen/article/details/17715775?_t_t_t=0.45848739612847567


文中解释说道:


  • instructions:任务执行期间产生的处理器指令数,IPCinstructions perf cycleIPC是评价处理器与应用程序性能的重要指标。(很多指令需要多个处理周期才能执行完毕),IPC越大越好,说明程序充分利用了处理器的特征。


心中一颤,我叉嘞,我写的啥玩意儿哇,这么多年,还是没长进。又继续想想怎么改进呢,不能因为就这个CPU利用率打桩代码就废了性能哇(毕竟这种非功能性需求还是非常有必要存在的)。


于是心中新生一计“良策”,CPU利用率的精度我降低点,不用那么高,将cycle统计改为统计进入空闲流程的次数。代码大致结构如下:


if (空闲)

gcpu_stat[lcore_id].sum_idle += 1;

else {

报文处理流程

gcpu_stat[lcore_id].sum_exec += 1; //这里加1也可改为批量处理的报文个数

// gcpu_stat[lcore_id].sum_exec += 64;

}


然后又将其,部署到设备上进行验证,测试结果如下:

 


此时,insns per cycle已经来到了0.59了,相比于之前的0.29还是增加了不少,将近一倍了,毕竟之前的每次轮询里面都调用了两次rte_rdtsc()函数(这个函数再高效也经不起我这么小闹腾哇),但是离1.19还是有一倍的差距。就继续胡思乱想,反正就是自己的做小玩意儿,多折腾折腾,看看自己到底能多少能耐,能想到哪一层。


一直在基于DPDK做开发的都知道,DPDK提供了一些原子操作rte_atomic64_initrte_atomic64_inc等相关API接口,用来提升类似自增操作的性能的。于是,我火速将以前的自增操作或为rte_atomic64_XX相关API,期待性能有提升(IPC值增加)。结果:

 


很明显事与愿违,不是预期的结果能,IPC值,几乎没啥变化。


Part4柳暗花明又一村


此时已经是下午3点多了,上床躺会儿休息休息再战。


其实吧,没咋睡着,脑袋停不下来了。之前呢,也也一直再看增加cache命中率的一些博客或技术文档和一些提升cache命中率的代码级手段。比如说:字节对齐之类的技术,以及依稀记得常常举的计算二维数组累积和的问题:基于按行进行二维数组累积和的性能优于基于按列进行二维数组累积和。因为,假定一位含有164字节的元素,在64位系统下,一个cache line刚好为64字节;因此,基于按行计算优于基于按列计算,cache命中率更高,更少的数据cache换入换出。


注意:假定设定变量int array[4][16],在计算第一行时,sum += array[0][0 … 15]计算机怎么就自动将后15个元素自动加载到了cache line了呢?但是呢,实时确认如此,就是“自动”加载到了和array[0]同一个cache line了(这一点我也一直没想明白,先跳过)。


基于这个思路,回头再来看看,我改过编写的数据结构体和全局变量的定义:


typedef struct cpu_stats_s {

time_t sum_idle;// 8 字节

time_t sum_exec;// 8字节

uint16_t utili;// 2字节

    uint16_t lcore;    // 2字节

    uint16_t lcore_role; //2字节,总24字节

} cpu_stats_t, *pcpu_stats_t;

 

cpu_stats_t gcpu_stat[MAX_LCORE];


假定,报文收取与发送的CPU1核,报文处理核为23


CPU 1计算CPU使用率时,访问gcpu_stat[1]时,参数刚刚讲的数组那个问题,同时是不是也会把gcpu_stat[2]的数据加载更新到CPU1核的cache缓存(L2/L1)中;又如,CPU2在访问gcpu_stat[2]计算时,是不是又要将gcpu_stat[3]加载至CPU2cache缓存中;CPU 2计算更新gcpu_stat[2]后,由于其又存在CPU 1,为了cache的一致性是不是又要去刷新CPU1中的cache,这里涉及到Cache一致性问题了,我这里没有完全的说明cache一致性问题。


但是基于这个思路,萌生的想法就是:把数据结构体cpu_stats_t空间填充到结构体大小为64字节。代码如下:


typedef struct cpu_stats_s {

time_t sum_idle;// 8 字节

time_t sum_exec;// 8字节

uint16_t utili;// 2字节

    uint16_t lcore;    // 2字节

uint16_t lcore_role; //2字节 

uint16_t reserver;  // 2字节,总24字节

uint64_t rarray[5];  40 字节

} cpu_stats_t, *pcpu_stats_t;


继续,将程序部署到设备上,进行验证,结果如下:


 

此时,嘴角微微上翘,IPC值来到了1.09距离1.19相差0.1,心中慢慢的放松下来了。


总结这次经验就是,在如下条件:


1、 全局数组,元素类型为结构体时

2、 每个核操作一个数组元素


我们需要保持该结构体数据cache line对齐,在DPDK编程中,处理我们自己进行结构体填充外,是否还有别的方法,毕竟自己填充太麻烦了,还要去计算需要填充多少字节。


我们需要了解Cache Line对齐和Cache一致性,将这些非常抽象的概念具体化,然后在实际使用,在对数据结构设计时多加考虑这些问题。


其实在DPDK中有这么一个宏:__rte_cache_aligned 来标记结构体按cache行对齐。最后,数据结构体如下:


typedef struct cpu_stats_s {

time_t sum_idle;// 8 字节

time_t sum_exec;// 8字节

uint16_t utili;// 2字节

    uint16_t lcore;    // 2字节

uint16_t lcore_role; //2字节 

uint16_t reserver;  // 2字节,总24字节

uint64_t rarray[5];  40 字节

} cpu_stats_t, *pcpu_stats_t __rte_cache_aligned;


验证结果,IPC和之前手动填充的结构体略多0.02左右的。


Part5回眸Cache与Cache一致性


简而言之,缓存是缓冲内存访问的地方,并且可能拥有您请求的数据的副本。通常人们认为缓存(可能不止一个)是堆叠的;CPU 位于顶部,然后是一层或多层缓存,然后是主内存。在此层次结构中,缓存按其级别进行量化。离CPU最近的缓存称为一级缓存,简称L1,缓存逐级递增,直到到达主存。


Cache具有三种操作模式:回写write back)、直写write through)和直通passthrough)(这里不具体解释)。


对于一个特定的缓存可以是直写回写。直写意味着缓存可以存储数据的副本,但写入必须在下一层完成,然后才能向上一层发出完成信号。回写意味着一旦数据存储在缓存中,就可以认为写入完成。对于回写缓存,只要写入的数据没有被传输,缓存行就被认为是脏的,因为它最终必须被写出到下面的级别。


缓存的基本问题之一:一致性


那么缓存的基本问题之一便是:cache一致性问题。当行中的数据与存储在被缓存的主存储器中的数据相同时,缓存行被称为一致的。如果不是这样,则高速缓存行被称为不连贯。缺乏连贯性会导致两个特殊问题。


1、缺乏连贯性


  • 第一个问题是所有缓存都可能出现的问题,即陈旧数据。在这种情况下,主内存中的数据已更改,但尚未更新缓存以反映更改。这通常表现为不正确的读取,如图 1 所示。这是一个暂时性错误,因为正确的数据位于主存储器中;只需要告诉缓存将其带入即可。


 

1


  • 第二个问题只发生在回写缓存中,它会导致数据的实际破坏,而且更加隐蔽。如图 2 所示,内存中的数据已更改,并且它也已通过 CPU 写入缓存单独更改。因为缓存必须一次写出一行,所以现在无法协调更改——要么必须清除缓存行而不写入,丢失 CPU 的更改,要么必须写出行,从而丢失更改做主内存。所有程序员都必须避免达到数据破坏不可避免的地步;他们可以通过明智地使用各种缓存管理 API 来做到这一点。


 

2


2、缓存行干扰


两组独立数据位于同一高速缓存行中的情况,可能导致上述数据破坏,称为高速缓存行干扰。如果您在内存中布局数据结构,避免这种情况的一般规则是,永远不要将可以在缓存之外修改的数据与 CPU 通常使用的数据混合在一起。如果您绝对必须违反此规则,请确保结构的所有外部可修改元素都对齐 L1_CACHE_BYTES,这是在编译时设置为您的代码可能运行的所有处理器的最大可能缓存宽度值的值。

本文中的问题,这个两个问题应该是都遇上了。因为,对于CPU 1操作数组元素gcpu_stat[1]时,被同时加载的gcpu_stat[2]不属于CPU1常用使用的数据;其次是CPU1回写gcpu_stat[1]时,缓存必须写出一行,连带了gcpu_stat[2]的数据,便有了后来的故事。

文中内容,完全凭本次实际编程得出的一些经验,未必都是正确的。错误的地方还请各位点出,修正。

再次给各位拜个年!2022.02.19

 

Part6参考链接


1、 https://blog.csdn.net/witsmakemen/article/details/17715775?_t_t_t=0.45848739612847567

2、 https://www.linuxjournal.com/article/7105

3、 https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/cache.html

 


Linux阅码场 专业的Linux技术社区和Linux操作系统学习平台,内容涉及Linux内核,Linux内存管理,Linux进程管理,Linux文件系统和IO,Linux性能调优,Linux设备驱动以及Linux虚拟化和云计算等各方各面.
评论 (0)
  •     根据 IEC术语,瞬态过电压是指持续时间几个毫秒及以下的过高电压,通常是以高阻尼(快速衰减)形式出现,波形可以是振荡的,也可以是非振荡的。    瞬态过电压的成因和机理,IEC 60664-1给出了以下四种:    1. 自然放电,最典型的例子是雷击,感应到电力线路上,并通过电网配电系统传输,抵达用户端;        2. 电网中非特定感性负载通断。例如热处理工厂、机加工工厂对
    电子知识打边炉 2025-04-07 22:59 101浏览
  • 曾几何时,汽车之家可是汽车资讯平台领域响当当的“扛把子”。2005 年成立之初,它就像一位贴心的汽车小助手,一下子就抓住了大家的心。它不仅吸引了海量用户,更是成为汽车厂商和经销商眼中的“香饽饽”,广告投放、合作推广不断,营收和利润一路高歌猛进,2013年成功在纽交所上市,风光无限。2021年更是在香港二次上市,达到了发展的巅峰,当年3月15日上市首日,港股股价一度高达184.6港元,市值可观。然而,如今的汽车之家却陷入了困境,业务下滑明显。业务增长瓶颈从近年来汽车之家公布的财报数据来看,情况不容
    用户1742991715177 2025-04-07 21:48 86浏览
  •     在研究Corona现象时发现:临界电压与介电材料表面的清洁程度有关。表面越清洁的介电材料,临界电压越高;表面污染物越多的地方,越容易“爬电”。关于Corona现象,另见基础理论第007篇。    这里说的“污染物”,定义为——可能影响介电强度或表面电阻率的固体、液体或气体(电离气体)的任何情况。    IEC 60664-1 (对应GB/T 16935.1-2023) 定义了 Pollution Degree,中文术语是“污染等
    电子知识打边炉 2025-04-07 22:06 78浏览
  • 贞光科技作为三星电机车规电容代理商,针对电动汽车领域日益复杂的电容选型难题,提供全方位一站式解决方案。面对高温稳定性、高可靠性、高纹波电流和小型化等严苛要求,三星车规电容凭借完整产品矩阵和卓越技术优势,完美满足BMS、电机控制器和OBC等核心系统需求。无论技术选型、供应链保障、样品测试还是成本优化,贞光科技助力客户在电动汽车产业高速发展中占据技术先机。在电动汽车技术高速发展的今天,作为汽车电子系统中不可或缺的关键元器件,电容的选型已成为困扰许多工程师和采购人员的难题。如何在众多参数和型号中找到最
    贞光科技 2025-04-07 17:06 65浏览
  • 在人工智能技术飞速发展的今天,语音交互正以颠覆性的方式重塑我们的生活体验。WTK6900系列语音识别芯片凭借其离线高性能、抗噪远场识别、毫秒级响应的核心优势,为智能家居领域注入全新活力。以智能风扇为起点,我们开启一场“解放双手”的科技革命,让每一缕凉风都随“声”而至。一、核心技术:精准识别,无惧环境挑战自适应降噪,听懂你的每一句话WTK6900系列芯片搭载前沿信号处理技术,通过自适应降噪算法,可智能过滤环境噪声干扰。无论是家中电视声、户外虫鸣声,还是厨房烹饪的嘈杂声,芯片均能精准提取有效指令,识
    广州唯创电子 2025-04-08 08:40 134浏览
  • 在全球电子产业面临供应链波动、技术迭代和市场需求变化等多重挑战的背景下,安博电子始终秉持“让合作伙伴赢得更多一点”的核心理念,致力于打造稳健、高效、可持续的全球供应链体系。依托覆盖供应商管理、品质检测、智能交付的全链路品控体系,安博电子不仅能确保电子元器件的高可靠性与一致性,更以高透明的供应链管理模式,助力客户降低风险、提升运营效率,推动行业标准升级,与全球合作伙伴共同塑造更具前瞻性的产业生态。动态优选机制:构建纯净供应链生态安博电子将供应商管理视为供应链安全的根基。打造动态优选管控体系,以严格
    电子资讯报 2025-04-07 17:06 74浏览
  • HDMI从2.1版本开始采用FRL传输模式,和2.0及之前的版本不同。两者在物理层信号上有所区别,这就需要在一些2.1版本的电路设计上增加匹配电路,使得2.1版本的电路能够向下兼容2.0及之前版本。2.1版本的信号特性下面截取自2.1版本规范定义,可以看到2.1版本支持直流耦合和交流耦合,其共模电压和AVCC相关,信号摆幅在400mV-1200mV2.0及之前版本的信号特性HDMI2.0及之前版本采用TMDS信号物理层,其结构和参数如下:兼容设计根据以上规范定义,可以看出TMDS信号的共模电压范
    durid 2025-04-08 19:01 94浏览
  • 在追求环境质量升级与产业效能突破的当下,温湿度控制正成为横跨多个行业领域的核心命题。作为环境参数中的关键指标,温湿度的精准调控不仅承载着人们对舒适人居环境的期待,更深度关联着工业生产、科研实验及仓储物流等场景的运营效率与安全标准。从应用场景上看,智能家居领域要求温湿度系统实现与人体节律的协同调节,半导体洁净车间要求控制温湿度范围及其波动以保障良品率,而现代化仓储物流体系则依赖温湿度的实时监测预防各种产品的腐损与锈化。温湿度传感器作为实现温湿度监测的关键元器件,其重要性正在各行各业中凸显而出。温湿
    华普微HOPERF 2025-04-07 10:05 123浏览
  • 医疗影像设备(如CT、MRI、超声诊断仪等)对PCB的精度、可靠性和信号完整性要求极高。这类设备需要处理微伏级信号、高频数据传输,同时需通过严格的EMC/EMI测试。制造此类PCB需从材料选择、层叠设计、工艺控制等多维度优化。以下是关键技术与经验分享。 1. 材料选择:高频与生物兼容性优先医疗影像设备PCB常采用 Rogers RO4000系列 或 Isola FR4高速材料,以降低介电损耗并保证信号稳定性。例如,捷多邦在客户案例中曾为某超声探头厂商推荐 Rogers RO4350B
    捷多邦 2025-04-07 10:22 105浏览
  • 及时生产 JIT(Just In Time)的起源JIT 起源于 20 世纪 70 年代爆发的全球石油危机和由此引发的自然资源短缺,这对仰赖进口原物料发展经济的日本冲击最大。当时日本的生产企业为了增强竞争力、提高产品利润,在原物料成本难以降低的情况下,只能从生产和流通过程中寻找利润源,降低库存、库存和运输等方面的生产性费用。根据这种思想,日本丰田汽车公司创立的一种具有特色的现代化生产方式,即 JIT,并由此取得了意想不到的成果。由于它不断地用于汽车生产,随后被越来越多的许多行业和企业所采用,为日
    优思学院 2025-04-07 11:56 103浏览
  • 文/Leon编辑/cc孙聪颖‍转手绢、跳舞、骑车、后空翻,就在宇树、智元等独角兽企业率领“机器人大军”入侵短视频时,却有资本和科技大佬向此产业泼了一盆冷水。金沙江创投管理合伙人朱啸虎近日突然对人形机器人发难,他表示“最近几个月正在批量退出人形机器人公司”。“只是买回去做研究的,或者买回去做展示的,这种都不是我们意义上的商业化,谁会花十几万买一个机器人去干这些活?”朱啸虎吐槽。不过,朱啸虎的观点很快就遭到驳斥,众擎机器人的创始人、董事长赵同阳回怼道:“(朱啸虎)甚至问出了人形机器人在这个阶段有什么
    华尔街科技眼 2025-04-07 19:24 123浏览
  •   工业自动化领域电磁兼容与接地系统深度剖析   一、电磁兼容(EMC)基础认知   定义及关键意义   电磁兼容性(EMC),指的是设备或者系统在既定的电磁环境里,不但能按预期功能正常运转,而且不会对周边其他设备或系统造成难以承受的电磁干扰。在工业自动化不断发展的当下,大功率电机、变频器等设备被大量应用,现场总线、工业网络等技术也日益普及,致使工业自动化系统所处的电磁环境变得愈发复杂,电磁兼容(EMC)问题也越发严峻。   ​电磁兼容三大核心要素   屏蔽:屏蔽旨在切断电磁波的传播路
    北京华盛恒辉软件开发 2025-04-07 22:55 160浏览
  • 在万物互联时代,智能化安防需求持续升级,传统报警系统已难以满足实时性、可靠性与安全性并重的要求。WT2003H-16S低功耗语音芯片方案,以4G实时音频传输、超低功耗设计、端云加密交互为核心,重新定义智能报警设备的性能边界,为家庭、工业、公共安防等领域提供高效、稳定的安全守护。一、技术内核:五大核心突破,构建全场景安防基座1. 双模音频传输,灵活应对复杂场景实时音频流传输:内置高灵敏度MIC,支持环境音实时采集,通过4G模块直接上传至云端服务器,响应速度低至毫秒级,适用于火灾警报、紧急呼救等需即
    广州唯创电子 2025-04-08 08:59 111浏览
我要评论
0
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦