一种残膜回收机防缠绕挑膜装置的制 一种秧草收获机用电力驱动行走机构

面向深度学习端侧推理的内存分配方法及装置与流程

2022-03-05 10:34:54 来源:中国专利 TAG:


1.本发明涉及资源分配技术领域,特别涉及一种面向深度学习端侧推理的内存分配方法及装置。


背景技术:

2.深度学习技术在图像、文字和声音的识别与处理等领域上取得了远超传统算法的效果,但一般来说深度模型的运算需要更多硬件资源,这对深度学习技术在端侧设备(一般指功耗资源受限的小微设备)上的应用落地造成了一定阻碍。为了加快深度模型的推理速度、降低资源占用,在软件层面除了替换低时间复杂度的优化算法外,还需要针对内存分配操作进行全局优化。
3.深度神经网络一般由几十到几百层组成,每层都会读取输入数据、存储输出数据并传递给后续层,不同层之间通过数据的依赖关系相关联,形成树状甚至环状的网络结构。该性质决定了执行深度模型推理时的内存分配有如下特点:
4.1、不同类型或不同参数的层所需输出缓冲区、内部缓冲区的大小不同,且差异较大
5.2、各层的输出缓冲区有自己的生命周期,有的很快结束,有的存在时间很长
6.3、对于相同尺寸的输入数据,大部分情况下各层输出数据的尺寸不会变化
7.以上特点决定了,深度学习端侧推理引擎的内存分配流程非常复杂、但相对可控,因而对内存分配的优化难度高、潜力大。如何更好的分配,使得深度模型在运行期间占用更少内存(和显存),是本专利重点处理的问题。
8.现有深度端侧推理的内存分配方式多是沿用传统软件的内存管理方案,从简单到复杂依次可以分为:
9.1、直接用c 标准库分配内存,不干预分配算法
10.a)在模型加载期间为每层分别向系统申请内存(显存同理),直到模型销毁再释放。内存总占用量最大,缓冲区缺少复用,运行速度也不是最优的
11.b)只在用到缓冲区时申请内存,用完立即释放。内存峰值占用较低,但仍可以优化;还会导致内存碎片的问题
12.2、维护内存池,根据各缓冲区的生命周期回收内存
13.a)内存池各节点一次只分配给一个缓冲区,缓冲区销毁时回收节点,如果不够则申请新内存块;
14.b)维护节点树:当一个结点容量大于缓冲区所需大小时,构造子节点表示分配出去的和空闲的内存块;缓冲区销毁时回收节点,并将相邻空闲节点融合;
15.为了追求更高的计算速度、较低的内存占用,目前流行的深度学习端侧推理引擎大都采用了内存池方案,比如阿里巴巴团队推出的mnn引擎就采用了节点树模式,相比于早期项目caffe的全局固定预分配、腾讯ncnn引擎的缺乏拆分机制的内存池等模式,在内存占用上有一定优势。
16.现有方案中相对最优的是基于节点树的内存池方案,但该方案仍然有不少问题。
17.节点树的方案中,实际维护了多个互不相交的内存“桶”,每个桶的大小在创建时固定,如果桶中空闲区域足够大,则为缓冲区分配桶内空间、创建子节点存储记录结果,否则创建新的满足大小需求的桶。因此,在不同大小的缓冲区不断创建和销毁后,在很多桶内会分散着或零或整的空闲区域,这些空间互不相连。如果需要创建新的较大缓冲区,即使两个空闲区域的总大小足够容纳,但实际执行中也只能申请新的内存。这就造成了一定程度的空间浪费。
18.申请新内存时,由于已分配的内存桶的具体地址并不确定、过往传出的缓冲区指针难以修改,因此通常不能使用realloc函数直接扩展桶的尾部(空闲区域)到能容纳新缓冲区的位置,而必须直接申请满足新缓冲区大小的内存,此处也提供了较大的优化空间。


技术实现要素:

19.本发明旨在至少在一定程度上解决相关技术中的技术问题之一。
20.为此,本发明的第一个目的在于提出一种面向深度学习端侧推理的内存分配方法,这种方法可以在分配过程中充分利用各层缓冲区的生命周期信息进行决策,不断融合空闲内存碎片,动态调整已分配的地址空间,提升内存的复用比例并降低总体占用。
21.本发明的第二个目的在于提出一种面向深度学习端侧推理的内存分配装置。
22.为达上述目的,本发明第一方面实施例提出了种面向深度学习端侧推理的内存分配方法,包括:
23.获取所有缓冲区的生命周期信息;
24.根据所述生命周期信息的顺序,跟踪各地址区域分配的缓冲区及所述各地址区域分配的缓冲区变化情况;
25.根据所述缓冲区变化情况进行空闲内存移动操作和内存池动态扩张操作,所述空闲内存移动操作,包括分析已占用地址上的各缓冲区的生命周期信息,找出特定的可移动缓冲区和移动目标地址,根据目标缓冲区和周围缓冲区的生命周期信息,在空闲区域中找出容纳若干缓冲区的空闲内存;以及,
26.所述内存池动态扩张操作包括扩张虚拟内存池的空间和按需移动先前缓冲区;
27.在完成所述空闲内存移动操作和内存池动态扩张操作之后,分配结果实例化。
28.另外,根据本发明上述实施例的面向深度学习端侧推理的内存分配方法还可以具有以下附加的技术特征:
29.进一步地,在本发明的一个实施例中,所述在信息收集阶段获取所有缓冲区的生命周期信息,包括:
30.基于硬件参数和软件配置,自底向上地逐层进行形状推导,得的所有缓冲区的尺寸信息,以及根据深度网络的层间连接关系,获得不同缓冲区之间创建、销毁的先后顺序。
31.进一步地,在本发明的一个实施例中,所述根据所述生命周期信息的顺序,跟踪各地址区域分配的缓冲区及所述各地址区域分配的缓冲区变化情况,包括:
32.基于深度模型、配置参数和输入图像的尺寸获得包括大小、创建时间戳和销毁所述时间戳在内的输出特征图和中间结果缓冲区的生命周期信息,在动态分配时,缓冲区创建时得到的地址范围非固定,并追踪各地址区域上的曾经出现的缓冲区信息。
33.进一步地,在本发明的一个实施例中,所述方法,还包括:
34.在所述获取所有缓冲区的生命周期信息之后,按照所述生命周期信息的顺序进行内存分配的模拟,计算出各缓冲区对应的偏移量;以及,
35.在所述根据所述生命周期信息的顺序,跟踪各地址区域分配的缓冲区及所述各地址区域分配的缓冲区变化情况之后,根据内存池总大小申请内存,并按照偏移量信息计算出内存地址修改缓冲区对象。
36.进一步地,在本发明的一个实施例中,所述空闲内存移动操作,还包括:
37.在测试现有空闲内存时,添加一定的约束条件,在固定长度流程内进行尝试,如果找不到则放弃。
38.进一步地,在本发明的一个实施例中,所述内存池动态扩张操作,还包括:
39.扩张位置按照所述生命周期信息根据预设规则筛选出来,选择临近空闲空间以及生命周期最靠前的缓冲区,在所述临近空闲空间以及生命周期最靠前的缓冲区附近插入容纳新缓冲区所需空间,并移动其它缓冲区到新的位置。
40.本发明实施例的面向深度学习端侧推理的内存分配方法,通过获取所有缓冲区的生命周期信息;根据生命周期信息的顺序,跟踪各地址区域分配的缓冲区及各地址区域分配的缓冲区变化情况;根据缓冲区变化情况进行空闲内存移动操作和内存池动态扩张操作,空闲内存移动操作,包括分析已占用地址上的各缓冲区的生命周期信息,找出特定的可移动缓冲区和移动目标地址,根据目标缓冲区和周围缓冲区的生命周期信息,在空闲区域中找出容纳若干缓冲区的空闲内存;以及,内存池动态扩张操作包括扩张虚拟内存池的空间和按需移动先前缓冲区;在完成空闲内存移动操作和内存池动态扩张操作之后,分配结果实例化。本发明可以在分配过程中充分利用各层缓冲区的生命周期信息进行决策,不断融合空闲内存碎片,动态调整已分配的地址空间,提升内存的复用比例并降低总体占用。
41.为达上述目的,本发明第二方面实施例提出了一种面向深度学习端侧推理的内存分配装置,包括:
42.信息收集模块,用于获取所有缓冲区的生命周期信息;
43.动态虚拟分配模块,用于根据所述生命周期信息的顺序,跟踪各地址区域分配的缓冲区及所述各地址区域分配的缓冲区变化情况;
44.内存操作模块,用于根据所述缓冲区变化情况进行空闲内存移动操作和内存池动态扩张操作,所述空闲内存移动操作,包括分析已占用地址上的各缓冲区的生命周期信息,找出特定的可移动缓冲区和移动目标地址,根据目标缓冲区和周围缓冲区的生命周期信息,在空闲区域中找出容纳若干缓冲区的空闲内存;以及,
45.所述内存池动态扩张操作包括扩张虚拟内存池的空间和按需移动先前缓冲区;
46.分配结果实例化模块,用于在完成所述空闲内存移动操作和内存池动态扩张操作之后,分配结果实例化。
47.本发明实施例的面向深度学习端侧推理的内存分配装置,通过信息收集模块,用于获取所有缓冲区的生命周期信息;动态虚拟分配模块,用于根据生命周期信息的顺序,跟踪各地址区域分配的缓冲区及各地址区域分配的缓冲区变化情况;内存操作模块,用于根据缓冲区变化情况进行空闲内存移动操作和内存池动态扩张操作,空闲内存移动操作,包括分析已占用地址上的各缓冲区的生命周期信息,找出特定的可移动缓冲区和移动目标地
址,根据目标缓冲区和周围缓冲区的生命周期信息,在空闲区域中找出容纳若干缓冲区的空闲内存;以及,内存池动态扩张操作包括扩张虚拟内存池的空间和按需移动先前缓冲区;分配结果实例化模块,用于在完成空闲内存移动操作和内存池动态扩张操作之后,分配结果实例化。本发明可以在分配过程中充分利用各层缓冲区的生命周期信息进行决策,不断融合空闲内存碎片,动态调整已分配的地址空间,提升内存的复用比例并降低总体占用。
48.本发明的有益效果为:
49.本发明针对深度模型结构复杂、但相对稳定的特性,改进传统的内存池方案,基于全局的内存分配需求优化分配策略,可以使端侧设备上的深度推理引擎在运行期间占用更少内存(显存同理)、提高访存的局域性,有助于加快计算速度、节约能耗,并且降低了对端侧设备硬件规格的要求。
50.本发明附加的方面和优点将在下面的描述中部分给出,部分将从下面的描述中变得明显,或通过本发明的实践了解到。
附图说明
51.本发明上述的和/或附加的方面和优点从下面结合附图对实施例的描述中将变得明显和容易理解,其中:
52.图1为根据本发明一个实施例的面向深度学习端侧推理的内存分配方法的流程图;
53.图2为根据本发明一个实施例的面向深度学习端侧推理的内存分配示意图;
54.图3为根据本发明一个实施例的面向深度学习端侧推理的内存分配装置的结构示意图。
具体实施方式
55.下面详细描述本发明的实施例,实施例的示例在附图中示出,其中自始至终相同或类似的标号表示相同或类似的元件或具有相同或类似功能的元件。下面通过参考附图描述的实施例是示例性的,旨在用于解释本发明,而不能理解为对本发明的限制。
56.下面参考附图描述本发明实施例的面向深度学习端侧推理的内存分配方法和装置。
57.本发明提出一种面向深度学习端侧推理需求优化的内存分配方法,可以在分配过程中充分利用各层缓冲区的生命周期信息进行决策,不断融合空闲内存碎片,动态调整已分配的地址空间,提升内存的复用比例并降低总体占用。具体来说,本发明提出的端侧推理内存分配方法包括四个要点:全程信息追踪、分配虚拟化、空闲内存移动、内存池动态扩张,如图2所示。
58.图1为本发明实施例所提供的一种面向深度学习端侧推理的内存分配方法的流程图。
59.如图1所示,该面向深度学习端侧推理的内存分配方法包括:
60.步骤s1,获取所有缓冲区的生命周期信息。
61.具体地,在信息收集阶段,自底向上地逐层推导出网络各层缓冲区的生命周期信息。
62.可以理解的是,首先需要获取所有缓冲区的生命周期信息。在某一模型加载后,基于硬件参数、软件配置(如模型输入的最大尺寸等),可以自底向上地逐层进行形状推导,得出所有缓冲区的尺寸信息,根据深度网络的层间连接关系,还可以获知不同缓冲区之间创建、销毁的先后顺序。这些信息共同构成了缓冲区的生命周期信息,是不可变的。本阶段不修改缓冲区的内存地址属性。
63.步骤s2,根据生命周期信息的顺序,跟踪各地址区域分配的缓冲区及所述各地址区域分配的缓冲区变化情况。
64.可以理解的是,在动态虚拟分配阶段,全程跟踪各地址区域分配的缓冲区及其变化情况。给定深度模型、配置参数和输入图像的最大尺寸,就可以推导出包括大小、创建“时间戳”(先后顺序)和销毁时间戳在内的输出特征图、中间结果缓冲区等的生命周期信息,它们一旦生成即可视为常量,在动态虚拟分配阶段全局可用,是优化分配策略的重要基础。动态分配时,缓冲区创建时得到的地址范围不是固定的,其后(即使是销毁后)也可能被移动到其它地址,期间需要始终追踪各地址区域上的曾经出现的缓冲区信息。
65.作为一种示例,信息收集阶段完成后,按照生命周期顺序进行内存分配的模拟,计算出各缓冲区所对应的“偏移量”,而不是直接分配具有现实意义的内存地址。动态分配阶段完成后,再根据内存池总大小向操作系统(或其它内存分配器)申请一整块内存,并按照偏移量信息计算出内存地址修改缓冲区对象。该方法可以避开无关内存申请对内存池方案的干扰,得到整块连续可用内存,在增加访存局部性的同时也减少了系统调用开销,提高模型推理效率。
66.步骤s3,根据缓冲区变化情况进行空闲内存移动操作和内存池动态扩张操作,空闲内存移动操作,包括分析已占用地址上的各缓冲区的生命周期信息,找出特定的可移动缓冲区和移动目标地址,根据目标缓冲区和周围缓冲区的生命周期信息,在空闲区域中找出容纳若干缓冲区的空闲内存;以及,内存池动态扩张操作包括扩张虚拟内存池的空间和按需移动先前缓冲区。
67.可以理解的是,本发明提出的空闲内存移动可理解为:在动态虚拟分配阶段,如果找不到足以容纳某缓冲区的空闲内存,则尝试移动部分已分配缓冲区到其它空闲区域,使得某一空闲区域扩大到足以容纳的程度。该步骤需要分析已占用地址上的各缓冲区生命周期,找出符合条件的可移动缓冲区、移动目标地址,还应当参考目标缓冲区和周围缓冲区的生命周期信息,在空闲区域中找出更合适的一个。由于深度网络层数较多,缓冲区生命周期复杂,在测试现有空闲内存时,还需要添加一定的约束条件,在固定长度流程内进行尝试,如果找不到则放弃。
68.本发明提出的内存池动态扩张具体理解为:在动态虚拟分配阶段,如果无法找到方案使某缓冲区可以被现有空闲区域容纳,则扩张虚拟内存池的空间、按需移动先前缓冲区。扩张位置需要按照生命周期信息根据一定规则筛选出来,一般选择临近空闲空间,且生命周期最为靠近的一个缓冲区,在其附近插入容纳新缓冲区所需空间,并移动其它缓冲区到新的位置。
69.下面通过参考附图描述的示例性实施例,对本发明实施例做进一步解释,但不限于此。
70.如图2所示,动态虚拟分配,可以分为以下过程:
71.a)分配虚拟化
72.基于全局的生命周期信息,可以在数学上把整个内存申请流程模拟出来,并加以优化,其模拟结果将和实际分配的内存地址一一对应。本阶段执行该虚拟分配操作。
73.模拟的分配流程仍为,按照缓冲区生命的周期,从先到后依次执行创建、销毁操作。在创建某一缓冲区时,可能会移动任何已分配的缓冲区。
74.b)空闲内存分配
75.假设当前时刻t,已分配的缓冲区有a
t
=[a1,a2,

,a
t
],大小和生命周期属性记为size(a),start(a),end(a),当前存在的缓冲区有a

t
=[a
′1,a
′2,

,a
′n](n随t变换),缓冲区之间的间隔表示为s={si|1≤i≤n,}(si可能为空),则我们的目标是寻找可以容纳a
t 1
的s
i,j

[0076]
如果找到多个空闲区域{sk}均可以容纳a
t 1
,则筛选规则为:
[0077]
空闲空间size(sk)小的优先
[0078]
空闲区域左右位置的缓冲区a
′k和a

k 1
,其销毁时间戳和a
t 1
接近的优先
[0079]
start(a
t 2
)和start(a
t 1
)之间将要销毁的缓冲区个数
[0080]
以上规则只是一些常用条件,不分先后。还可以添加一些策略,对各项规则评分、加权,得出最终的结果
[0081]
c)空闲内存移动
[0082]
如果找不到足够容纳a
t 1
的sk,则尝试“移动空闲内存”,即寻找sj,sk使得:
[0083]
size(sj) size(sk)≥size(a
t 1
)
[0084]

i≤x≤j
size(a

x
)≤size(sk),且min
i≤x≤j
start(a

x
)≥start(sk)
[0085]
其中start(sk)表示sk最近一次达到现有大小的时间戳。
[0086]
如果存在满足条件的i、j、k,则可以将{a

x
|i≤x≤j}移动到sk处,相当于将sk的一部分移动到sj左侧并融合,得到可以容纳a
t 1
的大型空闲区域。如果存在j≤i≤n满足上述不等式,也可以移动sk到sj右侧。
[0087]
和上一子步骤b)类似,如果存在多种j、k,则可以根据销毁时间戳等条件对其排序,选择更合适的一组。
[0088]
上述条件也可以扩展为,存在k1到km使得三个不等式同时成立。此时第二项约束条件的两个不等式均可按sk拆分为多份,只需要分别满足大小和起始时间的约束条件即可。
[0089]
另外,考虑到sk内部不同区域的start(

)不同,实际检查时可以用更细致的检查条件来判断{a

x
|i≤x≤j}是否合适。
[0090]
d)内存池动态扩张
[0091]
如果步骤c)仍未找到合适的空闲区域,则需要挑选sk来扩张内存池总大小。挑选条件为和步骤b)类似:
[0092]
size(sk)接近size(a
t 1
)的优先
[0093]
左右缓冲区a
′k和a

k 1
,其销毁时间戳和a
t 1
接近的优先
[0094]
另外最右侧空闲区域sn不需要遵守第一项条件。
[0095]
得到合适的sk后,将所有位于right(sk)右侧的缓冲区(包括已销毁的)统一右移size(a
t 1
)-size(sk)的距离,即可将内存池扩充到适当大小。
[0096]
如果a
t 2
等相邻的后续缓冲区的生命周期和a
t 1
也相连,那么可以一次性扩张∑isize(a
t i
)大小。
[0097]
步骤s4,在完成空闲内存移动操作和内存池动态扩张操作之后,分配结果实例化。
[0098]
可以理解的是,基于以上要点,将会得到一个局部最优的虚拟内存分配结果,接下来可以执行第三阶段,申请内存、将“基址 偏移量”写入缓冲区对象,也可以将分配结果缓存下来以备未来复用。因此本发明通过更复杂的内存分配流程,在第一次分配的预热环节后,可以实现降低总内存用量、提高分配效率的效果。
[0099]
具体的,所有虚拟分配操作均完成后,基于内存池的最终大小向系统或其它模块申请内存,以返回的地址为基础,和各缓冲区的虚拟地址相加即可得到实际可用的缓冲区地址。更新缓冲区后,该模型可以反复运行,而不需要再次执行生命周期信息收集相关步骤和动态虚拟分配相关步骤。
[0100]
如果需要并行执行同一模型,申请一块相同大小的内存,并将所有旧缓冲区的地址统一添加偏移即可生成新的缓冲区对象,大大简化了新环境的准备工作。
[0101]
虚拟分配的结果也可以做持久化,之后在相同硬件环境和参数条件下直接加载分配结果即可。
[0102]
本发明实施例的面向深度学习端侧推理的内存分配方法,通过获取所有缓冲区的生命周期信息;根据生命周期信息的顺序,跟踪各地址区域分配的缓冲区及各地址区域分配的缓冲区变化情况;根据缓冲区变化情况进行空闲内存移动操作和内存池动态扩张操作,空闲内存移动操作,包括分析已占用地址上的各缓冲区的生命周期信息,找出特定的可移动缓冲区和移动目标地址,根据目标缓冲区和周围缓冲区的生命周期信息,在空闲区域中找出容纳若干缓冲区的空闲内存;以及,内存池动态扩张操作包括扩张虚拟内存池的空间和按需移动先前缓冲区;在完成空闲内存移动操作和内存池动态扩张操作之后,分配结果实例化。本发明可以在分配过程中充分利用各层缓冲区的生命周期信息进行决策,不断融合空闲内存碎片,动态调整已分配的地址空间,提升内存的复用比例并降低总体占用。
[0103]
图3为根据本发明一个实施例的面向深度学习端侧推理的内存分配装置的结构示意图。
[0104]
如图3所示,该装置10包括:信息收集模块100、动态虚拟分配模块200、内存操作模块300和分配结果实例化模块400。
[0105]
信息收集模块100,用于获取所有缓冲区的生命周期信息;
[0106]
动态虚拟分配模块200,用于根据生命周期信息的顺序,跟踪各地址区域分配的缓冲区及所述各地址区域分配的缓冲区变化情况;
[0107]
内存操作模块300,用于根据缓冲区变化情况进行空闲内存移动操作和内存池动态扩张操作,空闲内存移动操作,包括分析已占用地址上的各缓冲区的生命周期信息,找出特定的可移动缓冲区和移动目标地址,根据目标缓冲区和周围缓冲区的生命周期信息,在空闲区域中找出容纳若干缓冲区的空闲内存;以及,
[0108]
内存池动态扩张操作包括扩张虚拟内存池的空间和按需移动先前缓冲区;
[0109]
分配结果实例化模块400,用于在完成空闲内存移动操作和内存池动态扩张操作之后,分配结果实例化。
[0110]
进一步地,上述信息收集模块100,还用于:
[0111]
基于硬件参数和软件配置,自底向上地逐层进行形状推导,得的所有缓冲区的尺
寸信息,以及根据深度网络的层间连接关系,获得不同缓冲区之间创建、销毁的先后顺序。
[0112]
进一步地,上述动态虚拟分配模块200,还用于:
[0113]
基于深度模型、配置参数和输入图像的尺寸获得包括大小、创建时间戳和销毁所述时间戳在内的输出特征图和中间结果缓冲区的生命周期信息,在动态分配时,缓冲区创建时得到的地址范围非固定,并追踪各地址区域上的曾经出现的缓冲区信息。
[0114]
进一步地,还包括分配虚拟化模块,用于:
[0115]
在获取所有缓冲区的生命周期信息之后,按照生命周期信息的顺序进行内存分配的模拟,计算出各缓冲区对应的偏移量;以及,
[0116]
在根据所述生命周期信息的顺序,跟踪各地址区域分配的缓冲区及所述各地址区域分配的缓冲区变化情况之后,根据内存池总大小申请内存,并按照偏移量信息计算出内存地址修改缓冲区对象。
[0117]
根据本发明实施例的面向深度学习端侧推理的内存分配装置,通过信息收集模块,用于获取所有缓冲区的生命周期信息;动态虚拟分配模块,用于根据生命周期信息的顺序,跟踪各地址区域分配的缓冲区及各地址区域分配的缓冲区变化情况;内存操作模块,用于根据缓冲区变化情况进行空闲内存移动操作和内存池动态扩张操作,空闲内存移动操作,包括分析已占用地址上的各缓冲区的生命周期信息,找出特定的可移动缓冲区和移动目标地址,根据目标缓冲区和周围缓冲区的生命周期信息,在空闲区域中找出容纳若干缓冲区的空闲内存;以及,内存池动态扩张操作包括扩张虚拟内存池的空间和按需移动先前缓冲区;分配结果实例化模块,用于在完成空闲内存移动操作和内存池动态扩张操作之后,分配结果实例化。本发明可以在分配过程中充分利用各层缓冲区的生命周期信息进行决策,不断融合空闲内存碎片,动态调整已分配的地址空间,提升内存的复用比例并降低总体占用。
[0118]
此外,术语“第一”、“第二”仅用于描述目的,而不能理解为指示或暗示相对重要性或者隐含指明所指示的技术特征的数量。由此,限定有“第一”、“第二”的特征可以明示或者隐含地包括至少一个该特征。在本发明的描述中,“多个”的含义是至少两个,例如两个,三个等,除非另有明确具体的限定。
[0119]
在本说明书的描述中,参考术语“一个实施例”、“一些实施例”、“示例”、“具体示例”、或“一些示例”等的描述意指结合该实施例或示例描述的具体特征、结构、材料或者特点包含于本发明的至少一个实施例或示例中。在本说明书中,对上述术语的示意性表述不必须针对的是相同的实施例或示例。而且,描述的具体特征、结构、材料或者特点可以在任一个或多个实施例或示例中以合适的方式结合。此外,在不相互矛盾的情况下,本领域的技术人员可以将本说明书中描述的不同实施例或示例以及不同实施例或示例的特征进行结合和组合。
[0120]
尽管上面已经示出和描述了本发明的实施例,可以理解的是,上述实施例是示例性的,不能理解为对本发明的限制,本领域的普通技术人员在本发明的范围内可以对上述实施例进行变化、修改、替换和变型。
再多了解一些

本文用于企业家、创业者技术爱好者查询,结果仅供参考。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

相关文献