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

DAG任务编排的方法、装置、电子设备和存储介质与流程

2022-07-13 12:41:12 来源:中国专利 TAG:

dag任务编排的方法、装置、电子设备和存储介质
技术领域
1.本发明涉及有向无环图(dag)任务领域。


背景技术:

2.有向无环图(dag)任务可以应用于多个场景,例如在搜索推荐场景中可以用dag图来执行策略,在算法平台任务调度中可以用算子之间拼接成的dag图来调度执行、在人群圈选任务中,query也可解析成dag图的方式,每个节点就是具体的交、并、补执行逻辑。
3.目前业界很少有返回依赖的dag调度框架,现有的方式集中在每个线程处理一个节点,一般的步骤为:
4.1.定义dag调度流程图,如图1所示,共有13个节点;
5.2.基于每个节点定义计算逻辑,形成异步执行方法;
6.3.定义线程池;
7.4.通过解析节点之间的关系,基于线程池,为每个阶段分配一个线程执行,13个节点分配13个线程池;
8.5.组织返回依赖,同步生成最终结果。
9.现有技术的缺点主要在于以下几个方面:
10.第一:每个节点都利用一个线程,导致线程上线文切换频繁,不能充分利用线程资源;
11.第二:目前业界dag调度框架都比较重,很难以轻量级的方式引入项目。


技术实现要素:

12.下文呈现各种示例性技术方案的概述。在以下概述中可以进行一些简化和省略,其意在突出并介绍各种示例性技术方案的一些方面,但不限制本发明的范围。将在后续部分呈现足以允许本领域的普通技术人员产生并使用本发明概念的示例性技术方案的详细描述。
13.本发明的技术方案提供一种dag任务编排的方法,包括:定义dag调度依赖图;定义dag对象,通过dag调度依赖图,实例化dag对象;构建图链的dag图,从图链的dag图的根节点开始遍历,将每条遍历路径切割成若干个上下文链,切割条件为以下三个任意之一:当前节点的入度为1并且当前上下文的链的最后一个节点的出度为1;当前节点的入度为0;当前节点的入度为1且出度为0;定义线程池,为每个上下文链分配线程池;基于线程池,定义异步任务;提交任务给线程池执行,并获取最终结果。
14.可选地,还包括:用guava来定义异步任务。
15.可选地,还包括:把所有上下文链按照原有图上的上下游关系填充到一开始构建的图链的dag图。
16.可选地,还包括:循环遍历所有的根节点,直至遍历完所有根节点,形成新的图链的dag图。
17.可选地,还包括:采用拓扑排序的方式把图链遍历出来。
18.可选地,还包括:基于遍历的结果,不停异步提交任务。
19.本发明的另一个技术方案还提供一种dag任务编排的装置,包括:dag图切割模块,被配置为:定义dag调度依赖图;定义dag对象,通过dag调度依赖图,实例化dag对象;构建图链的dag图,从图链的dag图的根节点开始遍历,将每条遍历路径切割成若干个上下文链,切割条件为以下三个任意之一:当前节点的入度为1并且当前上下文的链的最后一个节点的出度为1;当前节点的入度为0;当前节点的入度为1且出度为0;任务处理模块,被配置为:定义线程池,为每个上下文链分配线程池;基于线程池,定义异步任务;提交任务给线程池执行,并获取最终结果。
20.可选地,任务处理模块还包括guava,用guava来定义异步任务。
21.可选地,任务处理模块还被配置为:把所有上下文链按照原有图上的上下游关系填充到一开始构建的图链的dag图。
22.可选地,任务处理模块还被配置为:循环遍历所有的根节点,直至遍历完所有根节点,形成新的图链的dag图。
23.可选地,任务处理模块还被配置为:采用拓扑排序的方式把图链遍历出来。
24.可选地,任务处理模块还被配置为:基于遍历的结果,不停异步提交任务。
25.本发明的另一个技术方案还提供了一种电子设备,包括:处理器、存储器以及存储在存储器上运行的计算机程序,所述处理器执行计算机程序时实现上述任一个技术方案所述的方法的步骤。
26.本发明的另一个技术方案还提供了一种计算机可读存储介质,所述计算机程序被处理器执行时实现上述任一个技术方案所述的方法的步骤。
27.本发明的技术方案主要具有以下几个发面的有益效果:
28.第一:相对与现有技术的dag执行框架更加的轻量级;
29.第二:基于图切割的方式尽可能的任务放在一个线程里边执行的过程大大减少了线程之间的切换,性能更高;
30.第三:支持了诸如算法平台dag任务依赖执行、人群圈选dag并行执行、搜索推荐dag策略执行等多个场景,应用广泛。
附图说明
31.为了更好地理解各种示例性实施例,可以参考附图,在附图中:
32.图1示出了现有技术的dag任务编排的方法的流程示意图;
33.图2示出了实施例提供的dag任务编排的方法的流程示意图;
34.图3示出了实施例提供的dag任务编排的方法中部分步骤的示意图;
35.图4示出了实施例提供的dag任务编排的装置的结构示意图。
36.为了便于理解,相同的附图标记已用于指代具有基本上相同或类似结构和/或基本上相同或类似功能的元件。
具体实施方式
37.描述和图式示出了本发明的原理。因此,将了解,本领域的技术人员将能够设计各
种布置,尽管本文中未明确地描述或示出所述布置,但所述布置体现本发明的原理且包括在本发明的范围内。此外,本文中所引述的所有例子主要旨在明确地用于教学目的,以帮助读者理解本发明的原理和由发明人提供的用以深化本领域的概念,并且所有例子应视为并不限于此类特定引述的例子和条件。另外,如本文中所使用,除非另有指示(例如,“或另外”或“或在替代方案中”),否则术语“或”是指非排他性的或(即,和/或)。并且,本文中所描述的各种实施例不一定相互排斥,因为一些实施例可以与一个或多个其它实施例组合以形成新的实施例。
38.术语解释:
39.dag(directed acyclic graph):泛指图论里的有向无环图。
40.任务编排:任务的异步调度与执行。
41.第一个实施例提供了一种dag任务编排的方法。图2示出了实施例提供的dag任务编排的方法的流程示意图,所述方法包括:
42.s101:定义dag调度依赖图,可通过后台拖拽配置;
43.s102:定义dag对象,通过解析后台拖拽配置的dag调度依赖图,实例化dag对象;
44.s103:构建图链的dag图,从图链的dag图的根节点开始遍历,将每条遍历路径进行切割,切割条件为以下三个任意之一:当前节点的入度为1并且当前上下文的链的最后一个节点的出度为1;当前节点的入度为0;当前节点的入度为1且出度为0;将每条路径的节点切割成若干个上下文链。
45.原始的情况下(见图3的左半部分)会为每个节点分配一个线程去执行,当在高并发场景下会因为线程之前的频繁切换导致不必要的性能损失,实施例采用了一种dag图的切割方式,把图3的左半部分切割成右半部分的graphchain(一种新节点的叫法),为每个graphchain赋予对应的线程,这样就能保证具有单一连接的节点能够在一个线程里边计算完成,大大减少了线程之间的切换带来的性能损耗。
46.具体的切割stage过程如下:
47.第一步:构建graphchain的有向无环dag图,包括多个节点,节点即可以是模型、也可以是策略,类似图3的左半部分。
48.第二步:从上述图的根节点开始循环遍历,这里采用深度优先的遍历方式,每个根节点都会对应一条遍历路径。例如在图3左半部分中,根节点是模型1、策略4和模型2,遍历的路径可以包括:第一条是模型1、策略3、策略5、策略8、策略13、策略11、策略12;第二条是策略4、策略6、策略8、策略13、策略11、策略12;第三条是模型2、策略7、策略9或策略10、策略11、策略12。每个节点包括入度和出度,入度是指向该节点的路径数目,出度是从该节点指向其他节点的路径数目。
49.第三步:针对每条遍历路径进行切割,切割条件为以下三个任意之一:第一个是当前节点的入度为1并且当前上下文的链chain的最后一个节点的出度为1,或者第二个是当前节点的入度为0,或者第三个是当前节点的入度为1、出度为0,满足此条件的将该节点增加到上下文的chain里去。当前上下文的链chain是指遍历当前节点之前的节点形成的链。
50.下面开始举例,如图3左半边所示,遍历第一条路径:模型1、策略3、策略5、策略8、策略13、策略11、策略12。
51.在遍历根节点模型1时,当前节点入度为0,满足上述第二个条件,则将模型1增加
到第一个上下文的chain里去,形成该第一个上下文chain里的第一个节点。
52.在遍历节点策略3时,当前节点入度为1,当前上下文chain是模型1,当前上下文chain最后一个节点是模型1,当前上下文chain最后一个节点模型1的出度为1,满足上述第一个条件,则将策略3增加到上下文的chain里去,现在第一个上下文chain里有两个节点,分别是模型1和策略3。
53.在遍历节点策略5时,当前节点入度为1,当前上下文chain是模型1和策略3,当前上下文chain最后一个节点是策略3,当前上下文chain最后一个节点策略3的出度为1,满足上述第一个条件,则增加到上下文的chain里去,现在第一个上下文chain里有三个节点,分别是模型1、策略3和策略5。
54.在遍历节点策略8时,当前节点入度为2,当前上下文chain是模型1、策略3和策略5,当前上下文chain最后一个节点是策略5,当前上下文chain最后一个节点策略5的出度为1,不满足上述任何一个条件,则重新形成一个新的上下文的chain,第二上下文的chain。
55.在遍历节点策略13时,当前节点入度为1,当前上下文chain是策略8,当前上下文chain最后一个节点是策略8,当前上下文chain最后一个节点策略8的出度为1,满足上述第一个条件,则增加到该上下文的chain里去,现在第二上下文chain里有二个节点,分别是策略8和策略13。
56.在遍历节点策略11时,当前节点入度为3,当前上下文chain是模型8、策略13,当前上下文chain最后一个节点是策略13,当前上下文chain最后一个节点策略13的出度为1,不满足上述任何一个条件,则重新形成一个新的上下文的chain,即第三上下文的chain。
57.在遍历节点策略12时,当前节点入度为1,出度为0,满足上述第三个条件,则增加到该上下文的chain里去,现在第三上下文chain里有二个节点,分别是策略11和策略12。
58.遍历完第一路径,形成了三个上下文的chain,如灰色框所示,每一个会色框代表一个上下文chain,第一上下文链chain包括模型1、策略3、策略5;第二上下文chain包括策略8、策略13;第三上下文chain包括策略11、策略12;
59.遍历第二路径:策略4、策略6、策略8、策略13、策略11、策略12;原理跟第一路径是一样的,可以看到第二路径中的策略4满足第二个条件,策略6满足第一个条件,因此策略4和策略6这两个节点形成第四上下文chain,第二路径中其他节点策略8、策略13、策略11、策略12跟第一路径中的节点是一样的,无需重复计算。
60.遍历第三路径:模型2、策略7、策略9或策略10、策略11、策略12;原理也一样,模型2满足第二个条件,策略7满足第一个条件,策略9或策略10、策略11不满足任意一个条件,因此策略2和策略7这两个节点形成第五上下文chain,策略9形成第六上下文chain,策略10形成第七上下文chain,策略11、策略12已经计算过,无需重复计算。
61.综上,遍历完所有路径后,总共形成了七个上下文链。
62.第四步:把遍历出来的所有上下文链chain按照原有图上的上下游关系填充到一开始定义的graphchain的dag图里。
63.第五步:循环所有的根节点,直至遍历完所有根节点,形成新的graphchain-dag生成了,如图3的右半部分图:每个灰色底色框的就是一个graphchain节点,总共有七个graphchain节点。
64.s104:定义线程池,为每个上下文chain(每个graphchain节点)分配一个线程池。
图3左半部分原先需要13个线程池,现在图3右半部分只需要7个线程池。
65.s105:可以基于google的guava来定义异步任务提交器,dag的执行过程可以采用guava里的futures。基于线程池,定义异步任务。例如第一上下文链chain(包括模型1、策略3、策略5)作为一个线程池,可以与第四上下文chain(策略4和策略6)的线程池、第五上下文chain(包括策略2和策略7)的线程池同时工作。
66.具体的执行过程如下:
67.第一步:采用拓扑排序的方式把graphchain遍历出来,例如图3右半部分的七个graphchain。
68.第二步:基于遍历的结果,不停异步提交任务。
69.异步执行的核心代码如下:
[0070][0071]
[0072]
s106:提交任务给线程池执行,并获取最终结果。
[0073]
相对与开源的dag执行框架更加的轻量级,基于图切割的方式尽可能的任务放在一个线程里边执行的过程大大减少了线程之间的切换,性能更高。
[0074]
因搜索推荐场景策略大部分可以分配到一个线程里边,整体策略dag执行相较于其他方案能够提升20% 。
[0075]
也可以支持了诸如算法平台dag任务依赖执行、人群圈选dag并行执行、搜索推荐dag策略执行的场景。
[0076]
第二个实施例还提供了一种dag任务编排的装置,如图4所示,dag任务编排的装置,包括:dag图切割模块401和任务处理模块402。
[0077]
dag图切割模块401,被配置为:定义dag调度依赖图;定义dag对象,通过dag调度依赖图,实例化dag对象;构建图链的dag图,从图链的dag图的根节点开始遍历,将每条遍历路径切割成若干个上下文链,切割条件为以下三个任意之一:当前节点的入度为1并且当前上下文的链的最后一个节点的出度为1;当前节点的入度为0;当前节点的入度为1且出度为0;
[0078]
具体的切割stage过程如下:
[0079]
第一步:构建graphchain的有向无环dag图,包括多个节点,节点即可以是模型、也可以是策略,类似图3左半部分。
[0080]
第二步:从上述图的根节点开始循环遍历,这里采用深度优先的遍历方式,每个根节点都会对应一条遍历路径。例如在图3左半部分中,根节点是模型1、策略4和模型2,遍历的路径可以包括:第一条是模型1、策略3、策略5、策略8、策略13、策略11、策略12;第二条是策略4、策略6、策略8、策略13、策略11、策略12;第三条是模型2、策略7、策略9或策略10、策略11、策略12。每个节点包括入度和出度,入度是指向该节点的路径数目,出度是从该节点指向其他节点的路径数目。
[0081]
第三步:针对每条遍历路径进行切割,切割条件为以下三个任意之一:第一个是当前节点的入度为1并且当前上下文的链chain的最后一个节点的出度为1,或者第二个是当前节点的入度为0,或者第三个是当前节点的入度为1、出度为0,满足此条件的将该节点增加到上下文的chain里去。当前上下文的链chain是指遍历当前节点之前的节点形成的链。
[0082]
下面开始举例,如图3左半边所示,遍历第一条路径:模型1、策略3、策略5、策略8、策略13、策略11、策略12。
[0083]
在遍历根节点模型1时,当前节点入度为0,满足上述第二个条件,则将模型1增加到第一个上下文的chain里去,形成该第一个上下文chain里的第一个节点。
[0084]
在遍历节点策略3时,当前节点入度为1,当前上下文chain是模型1,当前上下文chain最后一个节点是模型1,当前上下文chain最后一个节点模型1的出度为1,满足上述第一个条件,则将策略3增加到上下文的chain里去,现在第一个上下文chain里有两个节点,分别是模型1和策略3。
[0085]
在遍历节点策略5时,当前节点入度为1,当前上下文chain是模型1和策略3,当前上下文chain最后一个节点是策略3,当前上下文chain最后一个节点策略3的出度为1,满足上述第一个条件,则增加到上下文的chain里去,现在第一个上下文chain里有三个节点,分别是模型1、策略3和策略5。
[0086]
在遍历节点策略8时,当前节点入度为2,当前上下文chain是模型1、策略3和策略
5,当前上下文chain最后一个节点是策略5,当前上下文chain最后一个节点策略5的出度为1,不满足上述任何一个条件,则重新形成一个新的上下文的chain,第二上下文的chain。
[0087]
在遍历节点策略13时,当前节点入度为1,当前上下文chain是策略8,当前上下文chain最后一个节点是策略8,当前上下文chain最后一个节点策略8的出度为1,满足上述第一个条件,则增加到该上下文的chain里去,现在第二上下文chain里有二个节点,分别是策略8和策略13。
[0088]
在遍历节点策略11时,当前节点入度为3,当前上下文chain是模型8、策略13,当前上下文chain最后一个节点是策略13,当前上下文chain最后一个节点策略13的出度为1,不满足上述任何一个条件,则重新形成一个新的上下文的chain,即第三上下文的chain。
[0089]
在遍历节点策略12时,当前节点入度为1,出度为0,满足上述第三个条件,则增加到该上下文的chain里去,现在第三上下文chain里有二个节点,分别是策略11和策略12。
[0090]
遍历完第一路径,形成了三个上下文的chain,如灰色框所示,每一个会色框代表一个上下文chain,第一上下文链chain包括模型1、策略3、策略5;第二上下文chain包括策略8、策略13;第三上下文chain包括策略11、策略12;
[0091]
遍历第二路径:策略4、策略6、策略8、策略13、策略11、策略12;原理跟第一路径是一样的,可以看到第二路径中的策略4满足第二个条件,策略6满足第一个条件,因此策略4和策略6这两个节点形成第四上下文chain,第二路径中其他节点策略8、策略13、策略11、策略12跟第一路径中的节点是一样的,无需重复计算。
[0092]
遍历第三路径:模型2、策略7、策略9或策略10、策略11、策略12;原理也一样,模型2满足第二个条件,策略7满足第一个条件,策略9或策略10、策略11不满足任意一个条件,因此策略2和策略7这两个节点形成第五上下文chain,策略9形成第六上下文chain,策略10形成第七上下文chain,策略11、策略12已经计算过,无需重复计算。
[0093]
综上,遍历完所有路径后,总共形成了七个上下文链。
[0094]
第四步:把遍历出来的所有上下文链chain按照原有图上的上下游关系填充到一开始定义的graphchain的dag图里。
[0095]
第五步:循环所有的根节点,直至遍历完所有根节点,形成新的graphchain-dag生成了,如图3的右半部分图:每个灰色底色框的就是一个graphchain节点,总共有七个graphchain节点。
[0096]
任务处理模块402,被配置为:定义线程池,为每个上下文链分配线程池;基于线程池,定义异步任务;提交任务给线程池执行,并获取最终结果。
[0097]
可以基于google的guava来定义异步任务提交器,dag的执行过程可以采用guava里的futures。基于线程池,定义异步任务。例如第一上下文链chain(包括模型1、策略3、策略5)作为一个线程池,可以与第四上下文chain(策略4和策略6)的线程池、第五上下文chain(包括策略2和策略7)的线程池同时工作。
[0098]
具体的执行过程如下:
[0099]
第一步:采用拓扑排序的方式把graphchain遍历出来,例如图3右半部分的七个graphchain。
[0100]
第二步:基于遍历的结果,不停异步提交任务。
[0101]
异步执行的核心代码如下:
[0102][0103][0104]
可选地,任务处理模块还包括guava,用guava来定义异步任务。
[0105]
第三个实施例还提供了一种电子设备,包括:处理器、存储器以及存储在存储器上运行的计算机程序,所述处理器执行计算机程序时实现上述任一实施例方法的步骤,例如步骤s101至s106,或者所述处理器执行所述计算机程序时实现上述各实施例中各模块/单元的功能,例如单元201至202的功能。所述计算机程序可以被分割成一个或多个模块/单元,所述一个或者多个模块/单元被存储在所述存储器中,并由所述处理器执行。所述一个或多个模块/单元可以是能够完成特定功能的一系列计算机程序指令段,该指令段用于描述所述计算机程序在所述电子设备中的执行过程。
[0106]
所述电子设备可以是智能手机等移动终端,或者是桌上型计算机、笔记本、掌上电脑及云端服务器等计算设备。所述电子设备可包括,但不仅限于,处理器、存储器,可以包括
更多或更少的部件,或者组合某些部件,例如所述电子设备还可以包括输入输出设备、网络接入设备、总线等。所称处理器可以是中央处理单元(central processing unit,cpu),还可以是其他通用处理器、数字消息队列的管理器(digital signal processor,dsp)、专用集成电路(application specific integrated circuit,asic)、现成可编程门阵列(field programmable gate array,fpga)或者其他可编程逻辑器件、分立门或者晶体管逻辑器件、分立硬件组件等。通用处理器可以是微处理器或者该处理器也可以是任何常规的处理器等。所述存储器可以是所述电子设备的内部存储单元,例如电子设备的硬盘或内存。所述存储器也可以是所述电子设备的外部存储设备,例如所述电子设备上配备的插接式硬盘,智能存储卡(smart media card,smc),安全数字(secure digital,sd)卡,闪存卡(flash card)等。进一步地,所述存储器还可以既包括所述电子设备的内部存储单元也包括外部存储设备。
[0107]
第四个实施例还提供了一种计算机可读存储介质,所述计算机程序被处理器执行时实现上述任一实施例方法的步骤。
[0108]
在本技术各个实施例中的各功能单元可以集成在一个处理单元中,也可以是各个单元单独物理存在,也可以两个或两个以上单元集成在一个单元中。上述集成的单元既可以采用硬件的形式实现,也可以采用软件功能单元的形式实现。所述集成的模块/单元如果以软件功能单元的形式实现并作为独立的产品销售或使用时,可以存储在一个计算机可读取存储介质中。基于这样的理解,本技术实现上述实施例方法中的全部或部分流程,也可以通过计算机程序来指令相关的硬件来完成,所述的计算机程序可存储于一计算机可读存储介质中,该计算机程序在被处理器执行时,可实现上述各个方法实施例的步骤。其中,所述计算机程序包括计算机程序代码,所述计算机程序代码可以为源代码形式、对象代码形式、可执行文件或某些中间形式等。所述计算机可读介质可以包括:能够携带所述计算机程序代码的任何实体或装置、记录介质、u盘、移动硬盘、磁碟、光盘、计算机存储器、只读存储器(read-only memory,rom)、随机存取存储器(random access memory,ram)、电载波信号、电信信号以及软件分发介质等。需要说明的是,所述计算机可读介质包含的内容可以根据司法管辖区内立法和专利实践的要求进行适当的增减,例如在某些司法管辖区,根据立法和专利实践,计算机可读介质不包括电载波信号和电信信号。
[0109]
所属领域的技术人员可以清楚地了解到,为了描述的方便和简洁,仅以上述各功能单元、模块的划分进行举例说明,实际应用中,可以根据需要而将上述功能分配由不同的功能单元、模块完成,即将所述装置的内部结构划分成不同的功能单元或模块,以完成以上描述的全部或者部分功能。实施例中的各功能单元、模块可以集成在一个处理单元中,也可以是各个单元单独物理存在,也可以两个或两个以上单元集成在一个单元中,上述集成的单元既可以采用硬件的形式实现,也可以采用软件功能单元的形式实现。另外,各功能单元、模块的具体名称也只是为了便于相互区分,并不用于限制本技术的保护范围。上述系统中单元、模块的具体工作过程,可以参考前述方法实施例中的对应过程,在此不再赘述。
[0110]
在上述实施例中,对各个实施例的描述都各有侧重,某个实施例中没有详述或记载的部分,可以参见其它实施例的相关描述。本领域普通技术人员可以意识到,结合本文中所公开的实施例描述的各示例的单元及算法步骤,能够以电子硬件、或者计算机软件和电子硬件的结合来实现。这些功能究竟以硬件还是软件方式来执行,取决于技术方案的特定
应用和设计约束条件。专业技术人员可以对每个特定的应用来使用不同方法来实现所描述的功能,但是这种实现不应认为超出本技术的范围。
[0111]
在本技术所提供的实施例中,应该理解到,所揭露的系统、电子设备和方法,可以通过其它的方式实现。例如,以上所描述的系统、电子设备实施例仅仅是示意性的,例如,所述模块或单元的划分,仅仅为一种逻辑功能划分,实际实现时可以有另外的划分方式,例如多个单元或组件可以结合或者可以集成到另一个系统,或一些特征可以忽略,或不执行。另外,所显示或讨论的相互之间的耦合或直接耦合或通讯连接可以是通过一些接口,系统或单元的间接耦合或通讯连接,可以是电性,机械或其它的形式。所述作为分离部件说明的单元可以是或者也可以不是物理上分开的,作为单元显示的部件可以是或者也可以不是物理单元,即可以位于一个地方,或者也可以分布到多个网络单元上。可以根据实际的需要选择其中的部分或者全部单元来实现本实施例方案的目的。
[0112]
以上所述实施例仅用以说明本技术的技术方案,而非对其限制;尽管参照前述实施例对本技术进行了详细的说明,本领域的普通技术人员应当理解:其依然可以对前述各实施例所记载的技术方案进行修改,或者对其中部分技术特征进行等同替换;而这些修改或者替换,并不使相应技术方案的本质脱离本技术各实施例技术方案的精神和范围,均应包含在本技术的保护范围之内。
再多了解一些

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

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

相关文献