OpenCL异构并行计算:原理、机制与优化实践

所需积分/C币:27 2016-02-25 14:22:02 9.82MB PDF
收藏 收藏 5
举报

OpenCL异构并行计算:原理、机制与优化实践 此为试读书籍,不全,下载请注意
第1章异构并行计算的过去、现状和未来3 整),每个核心具有32KB一级数据缓存( LI Cache),48KB一级指令缓存,4个核心共享 512KB到2MB二级缓存(L2 Cache)。多核处理器通 常会共享主板上的物理内存 ARM Cortex③-A72 3)多路。硬件生产商会将多个多核处理器互联 ARM CoreSight" Multicore Debug and Trace (如AMD的HT( Hyper Transport)总线)在同一个主 NEON ARMV8-A SIMD engine 板上,各个多核处理器之间通常共享缓存(如三级缓 32b/64b CPU Floating Point 存或 eDRAM)或内存来交换数据。由于主板的设计4 Cache 32kB D- Cache Core 会导致NUMA(非一致性内存访问)特性,感兴趣的 with parity W/ECC 234 读者可参考刘文志(花名风辰)的著作《并行算法设 ACP SCU L2 Cache W/ECC (512kB -2MB 计与性能优化》中的2.6节 128-bit AMBA 4 ACE or AMBA5 CHI Coherent Bus Interface 多核和向量化是现代处理器提升性能的两种主 要途径,今天的绝大多数处理器都已经是多核向量化 图1-2 ARM Cortex-A72多核向量 处理器架构 处理器。在介绍为什么多核或向量化处理器如此流行 之前,先让我们了解一下之前的单核标量处理器遇到了什么问题 1.11单核标量处理器的困境 在2005年之前,大多数处理器都是单核的,一些处理器已经开始支持向量化(如X86 处理器支持的MMX(多媒体扩展)和SSE(流式SIMD扩展)指令集),但是绝大多数应用 程序并没有进行向量化,故绝大多数代码只能利用到单核处理器的标量性能。对于单核标量 处理器(或者运行在单核向量处理器上的标量代码)来说,处理器生产商只能考虑如何提升 单核标量处理器的性能。处理器生产商通过提升单核标量处理器的频率和指令级并行处理能 力(即提升指令流水线性能)来提升处理器的计算性能,如图1-3所示 从图1-3中可以看出,在2005年之前,单核标量处理器的性能基本上是每18个月近似 提升一倍,这称为摩尔定律。关于摩尔定律有许多不同的表述,也有一些表述上的不同和争 议,本节就不追究其原因和细节,只简单地称“单核标量处理器性能每18个月提升一倍” 为摩尔定律。 在2005年之前,单核标量处理器性能提升能满足摩尔定律的时期称为提升软件性能的 免费午餐”时期,因为单核标量代码的性能可以满足摩尔定律描述的速度提升,在这个前提 下,应用程序无须修改,只需要等待下一代处理器的推岀,到时现在的代码自然就能够跑得 更快。处理器生产商、研究人员和软件开发人员都非常髙兴且享受摩尔定律带来的成果 1)对处理器生产商来说,能够稳定地推岀性能更好的产品能够帮助他们顺利推动产品的 更新换代,卖出更多新产品,淘汰旧产品,获得更多利润。处理器生产商获得了更多利润就能 够进一步增加研发投入,以推岀性能更好的产品。对处理器生产商来说,这是一个良性循环。 ⊙机械工业出版社华章公司出版,书号978-7-11150102-2。 4◆ OpencL异构并行计算:原理、机制与优化实践 2)对研究人员来说,他们基于当前处理器的计算能力来设计应用,获得研究结果,并 依据摩尔定律来估计下一代处理器能够提供的性能,设计在下一代处理器上能够快速运行的 应用。在下一代处理器推出后,就可以获得更好的结果。 3)对软件开发人员来说,无须花费太多精力来优化程序性能,只需要建议老板购买新 硬件即可获得性能提升。 4)在这种处理器生产商和软件开发人员相互促进的良性循环下:软件开发人员依据当 时处理器的性能设计应用,并依据摩尔定律对下一代处理器的性能提出预期(设计在下一代 处理器上能够流畅运行的应用),处理器生产商生产新处理器以满足摩尔定律对性能的要求 并将新处理器卖给软件开发人员,周而复始,相互促进。 Transistors (thousands Single-thread Perfo ( SpecINT requena 10 (MHZ Typical Pc (Watts) Number of 10 197519801985199019952000200520102015 年份 图1-3处理器频率、性能、功耗和核数变化 Original data collected and plotted by M.Horowitz, F. Labonte, O. Shacham, K. Olukotun, L. Hammond and C Batten Dotted line extrapolations by C. morre 在205年之后,单核标量处理器的性能基本上达到顶峰,很难进一步大幅度(超过 10%)提升性能。在回答为什么单核标量处理器的性能无法接着以摩尔定律要求的速度提升 之前,先让我们看一下,在20035年之前单核标量处理器如何提升性能,因为只有知道之前 如何提升性能,才能知道为什么不能以同样的方式接着提升性能。 1.1.1单核标量处理器如何提高性能 在2005年之前,单核标量处理器以近似摩尔定律的方式提升性能,其主要通过以下几 种方式提升性能 1)提升处理器的时钟频率:处理器的时钟频率表示处理器1秒内可以运行多少个基本 第1章异构并行计算的过去、现状和末来◆5 操作,这些基本操作需要一个时钟周期运行。在某个固定的处理器上,一些复杂的操作可能 需要多个时钟才能执行完成,或由多个基本操作组成。一条指令从开始到执行完成所需要的 时钟周期数,称为指令的延迟。一个具体的操作在不同的处理器上,其所花费的时钟周期数 量可以相同,也可以不同。通过提升某个单核标量处理器的时钟频率,在指令的延迟保持不 变的前提下,处理器1秒内就可以执行更多的基本操作,这提升了处理器上运行的所有指令 的执行速度。 2)提升指令级并行能力:单核标量处理器上具有许多不同的部件,每个部件执行不同 的指令操作,如有的部件负责从内存中加载数据,有些部件负责计算乘加指令,一些部件负 责计算内存地址。如果能够让多条做不同动作的指令同时操作,那么多个部件就可以同时进 行指令操作,这称为指令级并行。如果在一个处理器上,能够同时操作3条指令,在提升指 令级并行能力后,它可能能够同时处理多达5条指令。提升指令级并行能力并没有减少某条 指令的延迟,但是它提升了处理器能够同时处理的指令数量 在“免费午餐”时期,通过提升处理器的时钟频率以大幅度提升性能,如图1-3中的绿 线°所示。而通过将一条指令拆分成多个阶段以提高指令级并行能力已得到广泛使用,关于 为什么将一条指令拆分成多个阶段能够提高处理器的性能,以经典的5阶段流水线为例,请 参考图1-4。 tO t2 t4 t6 周期时间t IF ID EX MEM WB IF ID EX MEM WB 12 IF MEM WB 13 IF D EX MEM WB IF ID EX MEM WB IF ID EX MEM WB IF EX MEM WB i7 IF IDEⅩ MEM WB 18 IF ID EX MEM WB IF D EX MEM WB 指令序列 图1-4流水线示例 五阶段流水线将指令的执行过程划分成:取指令( Instruction fetch,IF)、指令解码 ( Instruction decode,ID)、执行( Execution,EX)、访存( Memory access,MEM)和写回( Write Back,WB)。同时假设处理器支持两条流水线同时操作。在开始执行时(to),有两条指令 (i0,ⅱi1)在取指令;在t时,指令i、ⅱ在解码,而两条新指令i、i3可以进行取指令操作 在口2时,又有两条新指令i4、ⅰ5进行取指令操作,而此时指令设、i3进行解码操作,而指令 i0、ⅱ正在执行;在t3时,又有两条新指令i、进行取指令操作,而此时指令i4、i5进行 解码操作,而指令i、i3正在执行,指令i0、i正在访存;在t4时,又有两条新指令i8、i 在进行取指令操作,而此时指令j6、i进行指令解码操作,指令i、i4正在执行,指令i ⊙图1-3中从上向下数,第三条线为绿色线,本书为单色印刷,特为读者指出,带来不便,敬请谅解。 6◆ OpencL异构并行计算:原理、机制与优化实践 i3正在访存,指令i0、i正在写回,写回结束后,指令i0、i就完成了,以此类推,在随后 的每个周期内,都会有两条指令执行完成,两条新指令加入执行。从整体来看,若没有使用 流水线执行,则原来需要5个周期才能完成2个操作,而使用流水线执行后,则每个周期能 够完成2个操作。 要完全利用硬件指令流水线的所有性能,程序代码需要提供足够多样(不同种类)的指 令,编译器需要从源代码中获得足够多的信息以安排流水线获得最好性能。另外,不是所有 的指令都需要执行硬件指令流水线的所有阶段,现代处理器采用了许多不同的办法来处理这 个问题。这里就不展开讨论这些问题了 在介绍完单核标量处理器如何提升性能之后,我们接着来了解单核标量处理器无法继续 以摩尔定律的速度提升性能,即为什么单核标量处理器性能到达瓶颈。 1.1.2为什么单核标量处理器性能到达瓶颈 1.1.1节提到,在2005年之前,提升单核标量处理器性能以满足摩尔定律描述的速度提 升,而在2005年之后,单核标量处理器的性能不能再以摩尔定律的速度提升,这主要是因为 )功耗限制了频率的继续提升:从物理定理来看,随着处理器工艺制程的推进,处理 器的最大功耗(主要是漏电功耗)越来越大,大致来说处理器的功耗和处理器的频率的三次 方近似成正比(硬件设计实践中有许多方法降低指数,具体细节请读者参考相关著作,笔者 就不详细解释了),这意味着随着处理器频率的増加,处理器功耗会大幅度増加。处理器功耗 增加,则处理器工作时越来越热,对散热系统的要求会越来越高。而今天散热系统已经从风 冷、散热片、水冷到油冷。在处理器散热要求已经达到现实环境、技术能够满足的界限情况 下,如果再增加频率,那么硬件组件可能不能正常工作,甚至烧掉 2)提升指令级并行遇到瓶颈:指令级并行能够让处理器的多个不同的流水线组件同时 工作。如图1-4所示,在一条指令取指的阶段,另外一条指令正在解码,与此同时其他的指 令正在计算、写回存储器等。指令级并行能够增大处理器组件的利用率,极大地提高处理器 的性能。但是要利用好处理器的指令级并行能力需要代码优化人员、编译器作者和处理器设 计师共同努力。处理器设计师在硬件层次提供了重排缓冲区( Reorder buffer,ROB)、发射队 列( Issue queue)和寄存器重命名单元( register renaming)等来挖掘指令执行时的不相关性。 硬件层面的支持能够挖掘岀软件层面不知道的信息,如是否存在存储器别名。编译器作者要 让编译器合理安排生成的指令,尽量让生成的指令没有依赖性,或者让依赖指令的距离足够 远,合理重用寄存器等。代码优化人员需要以编译器和处理器友好的方式编写代码,以便编 译器生成处理器能够高效执行的代码。为了提髙硬件的指令级并行执行能力,处理器设计通 常会增加硬件流水线的级次,而现在这一方法也达到其局限。 在提升指令级并行遇到瓶颈后,硬件设计师通过增加硬件寄存器的长度提升性能。例 如,原来寄存器长度为32位,现在提升到128位,这意味着如果原来一个寄存器只能保存 个单精度浮点数据,而现在一个寄存器能够保存4个这样的数据。如果同时增加指令的操 第1章异构并行计算的过去、现状和未来7 作能力,让指令可以同时对一个128位的向量寄存器中的数据进行操作,那么就能够成倍地 增加处理器的吞吐量,这称为SIMD向量化。SIMD向量化也是一种数据并行形式的指令级 并行,通过向量化,硬件只需要增加很少的单元就能够成倍地提升峰值性能 由于散热导致处理器的频率不能接着提升,硬件生产商转而采用将多个处理器组成到 个芯片上,这称为多核。通过稍微降低频率和电压,多核处理器能够以稍微増加的功耗获得 更高的性能。 1.2多核并行计算与向量化的出现 由于散热技术和硬件生产技术无法满足提高处理器频率对功耗的设计要求,现代处理器 的频率近似停滞。为了提供更高性能的处理器,处理器硬件生产商通过增加寄存器的宽度和 指令的宽度来同时处理多个数据,这称为向量化。多核和向量化的出现提升了处理器的执行 力。通过稍微降低频率,现在的散热技术能够满足处理器对功耗的需求 今天的绝大多数处理器,如Ⅹ86多核CPU、ARM多核CPU、GPU及DSP等,都已经 是多核向量处理器。多核和向量化的出现满足了应用对计算能力的需求,但是它们也带来了 两个重要的问题:如何编程以发挥多核和向量的计算能力;如何保证随着核数和向量长度的 增加,性能的提升依旧接近线性 1.2.1为什么会有多核 多核通过复制处理器核心成倍增加了处理器的计算能力,多核的岀现除了功耗的原因 外,还有许多其他的原因。 许多应用需要同时进行许多不相关的处理,如希望用户界面在不影响用户处理的同时进 行计算,以提升用户体验;如网页服务器需要同时满足多个用户的访问请求。多核能够支持 线程级并行处理,通过将线程映射到硬件核心上,以同时处理多个不同的请求,提高用户使 用体验。 随着数据量越来越大,处理大量数据需要的计算性能的需求也越来越大,如科学计算领 域需要长时间、细精度的模拟以重现真实系统;深度学习系统需要在大量数据集上训练以调 整模型,通常其运行时间需要几天、几周。应用对性能的要求促使处理器硬件生产商想方设 法、不断提升处理器的性能 如果处理器生产商没有办法提供性能更好的处理器,他就没有办法要求用户为他的新处 理器埋单。 1.22为什么会有向量化 许多算法、应用中具有向量级并行(数据并行)能力,如一些算法需要对多个不同数据 执行同一个操作,如代码清单1-1所示。 8◆ OpencL异构并行计算:原理、机制与优化实践 代码清单1-1向量化示例代码 for (int i =0: i n i++) m128 da alil m128 db c[i]= mm add ps(da, db)i 代码使用128位向量处理单精度数据,那么每次可以同时处理4个数据。 向量化提升了处理器的计算能力,能够满足应用软件对计算性能的需求。同时向量化并 没有大幅度增加处理器功耗。 1.2.3如何利用多核和向量化的能力 要同时发挥向量化和多核的计算能力,必须要编写向量化和多线程代码。这通常表现为 两种实现方式:①分别编写向量化代码和线程级代码;②统一编写向量化代码和多线程代码。 常见的编程语言,如Cl1!C++11和Java等语言本身已经内置了线程级并行能力,而其他 的语言则需要使用语言自身的机制。要发挥多核向量处理器的向量计算能力,则需要使用硬件 生产商提供的内联汇编(也称为内置函数)。例如, Intel/AMD为其X86处理器提供了SSE/AVX 指令集的C语言内置函数,ARM也为其CPU处理器提供了NEON指令集的C语言内置函数。 些新岀现的C编程语言扩展,如CUDA和 OpenCL,它们通过层次化的线程/编程模 型使得一份代码同时支持向量化和多核。目前CUDA和 OpenCL已经广泛应用在基于GPU 的异构并行计算中。 OpenCL不但支持GPU,还支持Ⅹ86CPU和ARM,一些移动处理器的GPU也开始支 持 OpenCl,如高通的 adreno系列、 Imagnation Technology的 PowerVr系列和ARM的Mali 系列都已经支持 OpenCl。目前一些FPGA和DSP的厂商也已经提供了 OpenCL的支持 1.2.4多核和向量化的难点 虽然多核和向量化能够大幅度地提升代码性能,但是它依旧面临许多现实的困境 1)无论是向量化还是多核并行化,这两者都意味着需要并行化代码,依据 Amdahl定 律,程序中的串行代码比例限制了并行化代码能够取得的最好效果。一个比较简单的示例 是:如果你的代码中有10%的代码是必须要串行执行的,那么无论你怎么优化,都不可能获 得超过10倍的加速。 2)现在的多核向量处理器(尤其是X86)为了减少获取数据的延迟,使用了大量的缓存 来保存多次重复访问的数据,在很多情况下,缓存能够增加程序的现实计算能力。但是缓存 并不贡献硬件的原生计算能力,这意味着实际上处理器的大量缓存并没有用来提升硬件的计 算能力(从某种程度上说,缓存是对处理器资源的一种浪费)。 3)有些代码不能使用多核并行化或向量化。一些算法的运算具有内在的串行特点,因 第1章异构并行计算的过去、现状和末来9 此必须要串行执行。如果代码无法多核并行化或向量化,那么多核向量处理器的一些计算能 力就会浪费。 4)在许多情况下,要发挥向量化和多核的计算能力,可能需要多份代码,这增加了代 码维护代价。要编写向量化代码或多核并行代码,需要分析代码中数据和操作的依赖关系, 处理任务和数据划分,并将其高效地映射到向量化和多核硬件上。 5)在一些应用严格的应用场景下,限制了其不能允许向量化和多线程导致的计算结果 出现偏差。 虽然多核和向量化具有许多现实的困难,但是软件开发人员和硬件设计人员正在紧密合 作,以减轻这些因素的影响。 1.3异构并行计算的崛起 从2007年 NVIDIA推岀CUDA计算环境开始,异构并行计算逐渐得到大众的认同,从 学术界走向了工业界。异构并行计算包含两个子概念:异构和并行。 1)异构是指异构并行计算需要同时处理多个不同架构的计算平台的问题,如目前主流 的异构并行计算平台X86+GPU、X86+FPGA,以及目前正在研发中的 ARM/Power+GPU。 2)并行是指异构并行计算主要采用并行的编程方式,无论是X86处理器,还是ARM 和GPU处理器以及DSP,这里所有的处理器都是多核向量处理器,要发挥多种处理器混合 平台的性能也必须要采用并行的编程方式 最先拥抱异构并行计算的领域是科学计算,如分子动力学模拟中需要长时间的运算,使 用Ⅹ86+GPU的异构并行模式能够将模拟时间由几周缩短为1周或几天 异构并行计算的出现缓解了处理器发展面临的两个主要问题:性能问题和功耗问题。 1)由于不同的硬件适合处理不同的计算问题。合理地将不同类型的计算分发到异构平 台的不同硬件上能够获得更好的计算性能,如将需要短时间运行的串行计算分发给X86,而 将需要长时间运行的并行计算部分分发给GPU。 2)由于采用为特定应用优化的处理器。处理器设计可以依据应用的具体特点来优化, 故功耗方面也会获得更好的结果。 在性能和功耗都比较重要的情况下,如何衡量处理器的性能就变得复杂起来,对于计算 性能至上的应用来说,性能更为重要。而对于功耗有特殊要求的应用来说,性能功耗比可能 更为合适。性能功耗比,即每瓦功耗能够支撑的处理器计算能力。 1.3.1 GPGPU的理念 在 NVIDIA推岀其CUDA计算环境之前,许多科学家就已经意识到如果能够利用GPU 提供的强大计算能力来计算一些通用运算,那么就能够获得很高的计算速度。但是那个时候 的GPU(姑且称之为GPU)还是为图形渲染特殊设计的流水线,那时GPU的每个部件都是 10◆ OpencL异构并行计算:原理、机制与优化实践 为了图形渲染的某一个阶段特殊设计。渲染一个图形需要顺序地经过所有流水线的处理。在 邶个时代,要使用GPU计算,则必须要将算法映射成图形的渲染过程,那时用来进行图形 编程的主要应用编程接口是 OpengL,故更明确的说法是:使用 OpengL将计算过程映射成 为图形渲染过程,进而达成计算的目的,这称之为 GPGPU。 由于需要将计算过程映射为图形的渲染过程,故编写 GPGPU程序需要专家级的GPU硬 件的图形渲染知识和 Opengl编程知识。 1.32cUDA的崛起 在2007年, NVIDIA推出了GTX8800GPU,与之前为图形渲染的每个阶段独立设计流 水线不同,GTX8800采用了统一的渲染架构,同一处理器会处理图形渲染的全部流水线,这 不仅提升了硬件的利用率,获得了图形渲染的高性能;同时统一架构也使得在GPU上进行 通用计算更为容易。为了和传统的 GPGPU计算相区别,称之为GPU计算时代。 在 NVIDIA推出GTX8800的同时, NVIDIA也推出了其通用GPU计算编程工具 CUDA,在一开始, NVIDIA称CUDA是计算统一设备架构( Computing Unified Device Architecture)的缩写,但是今天CUDA的范围已经远远超出了 NVIDIA当初的定义,CUDA 已经成为 NVIDIA通用GPU并行计算编程平台和编程模型的抽象,故其已经变成了一个 符号,一个生态系统。 CUDA平台本身提供了 CUDA O语言扩展,相比普通C语言, CUDA C增加了使用 NVIDIAGPU进行通用计算必不可少的一些语言扩展,其他功能则都通过函数库提供。 CUDA O以CC艹语法为基础而设计,因此对熟悉C系列语言的程序员来说,CUDA 的语法比较容易掌握。另外CUDA只对 ANSI O进行了最小的扩展,以实现其关键特性:线 程按照两个层次进行组织、共享存储器( shared memory)和栅栏( barrier)同步。 由于CUDA完美地结合了C语言的指针抽象, NVIDIA不断升级其CUDA计算平台, CUDA获得了大量科学计算人员的认可,已经成为目前世界上使用最广泛的并行计算平台。 通过CUDA, NVIDIA成功打破了 Intel在超算市场上的绝对主导地位。在今天,大多数大中 小型超算中心中都有GPU的身影 由于CUDA由NⅥIDIA一家设计,并未被 Intel和AMD等接受,因此目前使用CUDA 编写的程序只支持 NVIDIA GPU,而 OpenCl的出现解决了这一问题。 1.3.3 OpenCL横空出世 O p en CL全称为 Open Computing Language(开放计算语言),先由 Apple设计,后来交 由 Khronos group维护,是异构平台并行编程的开放的标准,也是一个编程框架。 Khronos Group是一个非盈利性技术组织,维护着多个开放的工业标准,并且得到了业界的广泛支持。 OpenCL的设计借鉴了CUDA的成功经验,并尽可能地支持多核CPU、GPU或其他加速器。 OpenCL不但支持数据并行,还支持任务并行。同时 OpenCl内建了多GPU并行的支持。这

...展开详情
试读 81P OpenCL异构并行计算:原理、机制与优化实践
立即下载 低至0.43元/次 身份认证VIP会员低至7折
    一个资源只可评论一次,评论内容不能少于5个字
    zhangrui_idol 还可以吧,,。。。。
    2018-10-09
    回复
    Law-Yao 入门、提高都很有帮助~~
    2018-05-07
    回复
    ugidlqh 非常感谢分享。太有用了。
    2018-05-01
    回复
    carolove 很不错的书籍。第一次研究opencl希望可以引入门
    2017-12-16
    回复
    呆萌院长 完整版的书,挺赞的,支持下~
    2017-08-09
    回复
    xum513 还不错! 就是不太清楚
    2017-06-08
    回复
    branze http://download.csdn.net/detail/branze/9765024 这有个1分的
    2017-02-27
    回复
    ykey001 还可以,就是希望早点有全部内容.
    2017-02-22
    回复
    roc1984 不完整啊,好贵
    2017-02-19
    回复
    张凯歌 还不错!希望能拜读全部内容
    2016-11-19
    回复
    • 签到新秀

      累计签到获取,不积跬步,无以至千里,继续坚持!
    关注 私信 TA的资源
    上传资源赚积分,得勋章
    最新推荐
    OpenCL异构并行计算:原理、机制与优化实践 27积分/C币 立即下载
    1/81
    OpenCL异构并行计算:原理、机制与优化实践第1页
    OpenCL异构并行计算:原理、机制与优化实践第2页
    OpenCL异构并行计算:原理、机制与优化实践第3页
    OpenCL异构并行计算:原理、机制与优化实践第4页
    OpenCL异构并行计算:原理、机制与优化实践第5页
    OpenCL异构并行计算:原理、机制与优化实践第6页
    OpenCL异构并行计算:原理、机制与优化实践第7页
    OpenCL异构并行计算:原理、机制与优化实践第8页
    OpenCL异构并行计算:原理、机制与优化实践第9页
    OpenCL异构并行计算:原理、机制与优化实践第10页
    OpenCL异构并行计算:原理、机制与优化实践第11页
    OpenCL异构并行计算:原理、机制与优化实践第12页
    OpenCL异构并行计算:原理、机制与优化实践第13页
    OpenCL异构并行计算:原理、机制与优化实践第14页
    OpenCL异构并行计算:原理、机制与优化实践第15页
    OpenCL异构并行计算:原理、机制与优化实践第16页
    OpenCL异构并行计算:原理、机制与优化实践第17页
    OpenCL异构并行计算:原理、机制与优化实践第18页
    OpenCL异构并行计算:原理、机制与优化实践第19页
    OpenCL异构并行计算:原理、机制与优化实践第20页

    试读已结束,剩余61页未读...

    27积分/C币 立即下载 >