异构计算综述

fea8404f7943c8012d8541944f843f27.png

异构计算(Heterogeneous computing)

异构计算(Heterogeneous computing)技术从80年代中期产生,由于它能经济有效地获取高性能计算能力、可扩展性好、计算资源利用率高、发展潜力巨大,目前已成为并行/分布计算领域中的研究热点之一。本文主要介绍了CPU+GPU基础知识及其异构系统体系结构(CUDA)和基于OpenCL的异构系统,并且总结了两种结构的特点,从而对异构计算有了更深的理解。

1、引言

异构计算主要是指使用不同类型指令集和体系架构的计算单元组成系统的计算方式。常见的计算单元类别包括CPU、GPU等协处理器、DSP、ASIC、FPGA 等。我们常说的并行计算正是异构计算中的重要组成部分异构计算近年来得到更多关注,主要是因为通过提升CPU时钟频率和内核数量而提高计算能力的传统方式遇到了散热和能耗瓶颈。而与此同时,GPU等专用计算单元虽然工作频率较低,具有更多的内核数和并行计算能力,总体性能/芯片面积的比和性能/功耗比都很高,却远远没有得到充分利用。CPU的设计让其比较擅长于处理不规则数据结构和不可预测的存取模式,以及递归算法、分支密集型代码和单线程程序。这类程序任务拥有复杂的指令调度、循环、分支、逻辑判断以及执行等步骤。而GPU擅于处理规则数据结构和可预测存取模式。而APU的设计理念则正是让CPU和GPU完美合作,集合两者的长处,用异构计算来达到整体性能的最佳化。目前,已经有50款领先的应用能够利用AMD APU进行加速,而后续的应用也将陆续到来——异构计算普及的一刻应该是近在咫尺了。

1.1 CPU和GPU的本质区别

(1) CPU特点

a) CPU的目标是快速执行单一指令流;

b) CPU将其用于乱序执行、寄存器重命名、分支预测以及巨大的cache上,这些设计都是为了加速单一线程的执行速度

c) CPU利用cache来降低内存访问延迟

d) CPU通过大量的cache和分支预测来降低延迟,这些机制消耗了大量的晶体管的电能;

e) CPU每个核心支持1~2个线程;

f) CPU切换线程的代价是数百个时钟周期;

g) CPU通过SIMD(单指令多数据)来处理矢量数据;

h)Intel的CPU没有集成内存控制器

(2)GPU特点

a) GPU的目标是快速执行大量的并行指令流。

b)GPU将晶体管用于处理器阵列、多线程管理、共享内存、内存控制器,这些设计并不着眼于提高单一线程的执行速度,而是为了使GPU可以同时执行成千上万的线程,实现线程间通信,并提供极高的内存带宽。

c) GPU使用cache来放大内存带宽

d) GPU通过同时运行上千个线程来隐藏延迟,等待内存访问的线程会被切换掉,e) GPU切换线程不耗时间。

f)对于支持CUDA的GPU,每个流处理器可以同时处理1024个线程。

g) GPU切换线程的代价是0,事实上GPU通常每个时钟周期都切换线程。

h) GPU则使用SIMT(单指令多线程),SIMT的好处是无需开发者费力把数据凑成合适的矢量长度,并且SIMT允许每个线程有不同的分支。

j) 支持CUDA的GPU集成有8个内存控制器,GPU的内存带宽通常是CPU 的十倍

1.2 GPU计算模型

内核是执行模型的核心,能在设备上执行。当一个内核执行之前,需要指定一个N-维的范围(NDRange)。一个NDRange是一个一维、二维或三维的索引空间。还需要指定全局工作节点的数目,工作组中节点的数目。如图NDRange 所示,全局工作节点的范围为{12, 12},工作组的节点范围为{4, 4},总共有9个工作组。如果定义向量为1024维,特别地,我们可以定义全局工作节点为1024,工作组中节点为128,则总共有8个组。定义工作组主要是为有些仅需在组内交换数据的程序提供方便。当然工作节点数目的多少要受到设备的限制。如果一个设备有1024个处理节点,则1024维的向量,每个节点计算一次就能完成。而如果一个设备仅有128个处理节点,那么每个节点需要计算8次。合理设置节点数目,工作组数目能提高程序的并行度。

6630e8491890ef12fd233031e4f8b72f.png图1.GPU计算模型

CPU的长项是整数计算,GPU的优势则是浮点计算。对于整机性能而言,CPU和GPU都是性能的保障,合理的搭配才是重中之重,才能给用户带来最强的综合性能。

1.3异构计算分类及发展方向

目前的趋势,增加并行的性能,而不是时钟频率。我们的重点是在一个节点,几乎是充分利用指令级并行性。这意味着,提高性能,必须来自多芯片,多核或多上下文并行。Flynn的分类法在硬件定义了四个级别的并行:(1)单指令单数据(SISD)(2)单指令多数据流(SIMD)(3)多指令单数据(MISD)(4)多指令多数据(MIMD)

此外,两个细分MIMD单程序多数据(SPMD),以及多个程序多数据(MPMD),我们使用这些术语来描述架构。

d8c3a98ffd457cf5feeba2cb008abd75.png图2.架构

单芯片CBEA,如图所示(a),由一个传统的CPU核心和8个SIMD加速器核心。这是一个非常灵活的架构,每个核心可以运行单独MPMD时尚和沟通方案,快速通过片上总线。其主要设计标准得到了最大限度降低消耗的功率。图中(b)显示了多线程SIMD加速器结合一个标准的多核CPU核心的GPU。GPU 具有优异的带宽和计算性能,对很少或根本没有同步运行的SPMD方案进行了优化。它是专为高性能的图形,其中的数据吞吐量是关键。最后,图中(c)显示了FPGA逻辑块阵列组成和一个标准的多核心CPU的组合。FPGA的片上,也可以纳入正规的CPU核心,使得它本身就是一个异构芯片。FPGA可视为用户定义的应用程序的专用集成电路(ASIC)的可重构。他们提供充分确定性的表现,是专为高吞吐量,例如,在电信方面的应用。

目前异构并行计算向着以下几个方向发展:(1)集群计算。这是传统高性能计算的领域。但是今天高性能计算已经演变成了异构并行计算的一部分,越来越多的高性能计算集群使用GPU、MIC、FPGA等。(2)单机计算。推动单机计算向异构并行计算发展的主要动力是游戏、计算机辅助设计等,而主要表现是GPU+CPU的异构计算。(3)移动计算。近几年发展表明,人们对手机的需求比对PC的需求更大。目前几乎所有的移动芯片解决方案都是异构的,除了有CPU、GPU之外,还有视频编解码单元、音频处理单元。倾向于把更多工作内容转移到手机上,但是为了保证续航时间,移动处理器的设计一开始就不是以高性能为目标,这使得要在移动处理器上获取高性能是比较困难的。(4)嵌入式计算。在一些恶劣工作环境下,只有DSP和FPGA能够满足要求。

2、异构计算系统

2.1 CPU+GPU 异构系统体系结构

计算机系统一般都配置了CPU 和GPU,GPU传统上只负责图形渲染,大部分的仸务都由CPU 来完成。随着图形渲染的数据量越来越大、计算也越来越复杂,GPU 的可编程性和幵行性也随之增强。目前,主流GPU 的计算能力、存储带宽、性价比与同期的CPU 相比更具竞争力。下面以支持CUDA(Computing Unified Device Architecture) 的GPU为例来说明CPU+GPU 异构计算系统的体系结构。支持CUDA 的GPU 通常由数个线程处理器簇。TPC(Thread Processor Cluster)组成,如:NVIDIA GeForce 9800 GX2 由2个TPC组成双核GPU;NVIDIA GeForce 9800 GTX 只含有一个TPC。每个TPC 由若干流多处理器SM(Streaming Multi-processor)组成,一个SM 包含8个线程处理器TP(threaded processor)和一定大小的共享存储空间(Shared Memory),另外,GPU还提供了全局的存储器(Global Memory or Video Memory)和一定数量的全局只读的纹理缓存(Texture Cache)和常缓存(Constant Cache)。GPU与CPU间的数据传输通过PCIE 通道来完成,该数据传输通道可能成为性能瓶颈。CPU+GPU 异构系统的整体结构如下图所示。

16de28c4b233ddcc3257eae18e24b972.png图3.CPU+GPU异构系统体系结构

2.1.2 CUDA执行模型

CUDA 源程序由运行于host(CPU)上的控制程序和运行于device(GPU)上的计算核心(kernel)两部分组成。每一个kernel 由一组相同大小的线程块(thread block)来幵行执行,同一线程块里面的线程通过共享存储空间来协作完成计算,线程块间是相互独立的。运行时,每一个线程块会被分派到一个流多处理器SM上运行,它们共享大小为16KB 的共享存储空间。为了管理运行各种不同程序的数百个线程,SM 采用了一种称为SIMT(single instruction multiple thread,SIMT)的新架构。SIMT 单元以32 个幵行线程为一组来创建、管理、调度和执行线程,这样的线程组称为warp 块。多个warp 块可以组成一个线程块,一个线程块将会分派到一个SM 上,SM 会将各线程映射到一个TP核心上,各TP 使用自己的指令地址和寄存器状态独立执行。构成SIMT warp块的各个线程在同一个程序地址一起启动,也可随意分支、独立执行。为一个SM 指定了一个或多个要执行的线程块时,它会将其分成warp 块,幵由SIMT单元迚行调度。将块分割为warp 块的方法总是相同的,每个warp 块都包含连续的线程,递增线程ID,第一个warp 块中包含线程0。每収出一条指令时,SIMT单元都会选择一个已准备好执行的warp 块,幵将下一条指令収送到该warp 块的活动线程,其执行调度过程示意如下图所示。

ed866fdeba903fdbb482e9c5d49f7717.png图4.CUDA执行模型

2.1.3协作框架

由于PCIE 数据传输通道会成为CPU+GPU 异构系统的性能瓶颈,因此,保证通信传输开销取得最优解的情况下,更有利于优化通信开销取得期望解,GPU与CPU如何协作完成求解问题,最大限度较少数据在CPU 与GPU之间的频繁传输显得尤为重要。为此参考文献之处写作框架如下:

d84d0df00186f184bbd9de4a948c179e.png图5.CPU+GPU协作框架

2.2.3实验评估分析

为了验证本文提出的协作框架的有效性和高效性,选择了计算密集型应用图像置乱变换作为测试用例。实验环境配置如下:

(1) Intel Core2 Quad 2.33Ghz ,4GB内存,Microsoft Visual Studio 2005

(2) GeForce GTX280,1GB 显存,16KB Shared Memory,CUDA toolkit 和SDK 2.0,NVIDIA Driver for Microsoft Windows XP(177.98)

551008bce7be8edfc21e02f42a243a25.png图6.运行时间比较

2.3基于OpenCL的异构系统并行编程

使用GPU进行通用计算是近些年的热点研究领域。传统的通用计算主要依靠图形API,这给不熟悉图形应用的用户带来了极大的不便。为了克服该缺陷,出现了NVIDIA CUDA和ATI Stream等编程模型,给编程带来了极大的灵活性。但是在程序移植性方面,NVIDIA GP和AMD GPU互不兼容。并且今天的计算机系统通常包含高度并行的CPU、GPU和其它类型的处理器,让软件开发人员充分合理的利用这些异构处理平台的优势变得非常重要。

0bd4fde86587438a6b1ee06c16871550.png

针对上述问题,OpenCL一种新的并行计算技术出现,使用它可以调用计算机内全部计算资源,包括CPU、GPU和其它处理器,为软件开发人员能够方便高效的利用异构处理平台、充分挖掘计算机中所有计算设备的性能潜力提供了充分保障。用OpenCL包含一个用来协调异构处理器间并行计算的API,和一个基于ISOC99跨平台的编程语言,且能与OpenGL、OpenGL ES和其它图形类API 高效互通,具有跨平台、兼容性好等特点,极大地方便了软件开发人员的编程工作,将大大地推动并行计算的发展。在诸如分子模拟、流体模拟、碰撞模拟、生物应用以及电信、金融、证券数据分析、医疗等各种领域都将具有良好的应用前景。本章节以OpenCL的架构、软件框架及实现原理等为基础,对OpenCL进行描述,并将OpenCL与CUDA等通用计算技术进行对比,突出OpenCL的优越性。

2.3.1OpenCL架构

(1)平台架构

该模型描述内部单元之间的关系,如图1所示。主机可以是个人计算机或超级计算机。设备可以是CPU、GPU、DSP或其它处理器。每个OpenCL设备包含若干计算单元,每个计算单元又由若干处理单元组成。

be82de783d7f0630f238639157ab79dd.png图7.平台模型

OpenCL通过平台实现主机与设备间的交互操作。主机管理着整个平台上的所有计算资源,所有OpenCL应用程序都是从主机端启动并在主机端结束的。应用程序运行时由主机提交命令,在设备上的处理单元中执行计算。每个计算单元内所有的处理单元都会执行相同的一套指令程。每个处理单元以单指令多数据SIMD或单程序多数据SPMD模式运行指令流。

(2)执行模型

OpenCL执行两类程序:内核程序和主机程序;前者由若干个OpenCL设备执行,后者由主机执行。OpenCL通过主机程序定义上下文并创建一个被称为命令队列的数据结构来管理内核程序的执行。在命令队列中,内核程序可顺序执行也可乱序执行。

每当主机提交内核程序到设备上执行时,系统便会创建一个N维(N可取1,2,3)的索引空间NDRange。如下图所示。内核程序将索引空间中的每一点用一个工作项(work-item)来表示,将若干个工作项划分成一个工作组(work group)。在一个计算单元内可运行同一工作组中的工作项,并且该组内的工作可以并发执行在多个处理单元上。

99cb8fe9dbb5d17c3405ca7d451a1604.png图8.执行模型索引空间

(3)内存模型

设备上有4块存储区域可以提供给工作项进行访问:

(a)全局内存:所有工作项对其中的任意数据都可以读写,容量较大,但访问延迟较高。

(b)常数内存:全局内存的一部分,但工作项对其中的任意数据只能进行读操作。

(c)局部内存:对特定工作组可见,该工作组中所有工作项可以对其中的任意数据进行读写操作。局部内存通常位于片上,访问速度较快,但容量有限。(d)私有内存:该区域中的数据只对单独的工作项可见。内存模型如下图所示。

29bab63987969684840d41bbef42df29.png图9.内存模型

一个kernal既不能访问主机内存也不能动态分配全局内存和常数内存,所有的内存都是由主机进行管理。下表描述了内核与主机对内存区域的分配以及访问情况。

3817e529a10ca0f946e9433f78dc8f66.png

(4)编程模型

数据并行和任务并行是OpenCL可以支持的两种并行编程模型,同时两者的混合模型也得到支持。通常情况下,OpenCL采用的首要模型是数据并行,而对多核CPU主要采用任务并行。在数据并行编程模型中,一系列的指令会作用到内存对象的多个元素上。严格来说,数据并行要求内存对象单元与工作项保持一对一的映射,而在实际应用中,并不要求严格按照这种方式。在数据并行编程模型中,OpenCL又提供了一种分级方式,有两种方法:显式分级模型和隐式分级模型;前者要求开发人员指出工作项的总数和工作项所属的工作组;而后者仅需要开发人员定义工作项的总数,对于工作项的划分则根据OpenCL的实现来管理。

在任务并行编程模型上,每个工作项都相当于在一个单一的计算单元内,该单元内只有单一工作组,该工作组只有该工作项本身在执行。

2.3.2OpenCL软件架构

OpenCL软件框架包含三部分:OpenCL平台层、OpenCL运行时和OpenCL 编译器。如下图所示。在OpenCL平台层上,开发人员可以查询系统中的平台数目并选定运行平台,在指定的平台上选择必要的计算设备并对它们进行初始化,然后可以建立上下文,并创建命令队列。执行内核程序、读、写及复制缓冲区和同步操作等都是通过命令队列中的命令实现的。一个命令队列和一个OpenCL设备是一对一的关系。在OpenCL运行时中,开发人员建立内核实例,并将其映射到正确的内存空间中,接着在命令队列中排队执行内核。OpenCL编译器负责编译运行在设备上的程序,并创建可执行程序。

300ec906611a9795cb7ebe819f5948a9.png图10.OpenCL软件架构

2.3.3 FPGA作为异构运算

随着FPGA的广泛使用,成本逐步降低,作为软件定义实现快速在线指令优化,对整个编译器、运行框架、OS产生巨大影响。新架构对软件的挑战:

1)支持CPU+FPGA融合并行的计算框架,包括FPGA编译和高层语言设计。

2)大规模分布式FPGA资源管理与调度

3)高性能FPGA算法库。

异构计算主要是指使用不同类型指令集和体系架构的计算单元组成系统的计算方式。常见的计算单元类别包括CPU、GPU、DSP、ASIC、FPGA等。

FPGA和GPU/CPU对比具有以下不同:

1.软件定义的硬件架构:GPU/CPU硬件固定,其并行性设计是适应固定硬件。而FPGA的硬件逻辑可以通过软件动态改变,从硬件的角度来适配软件,从而获得更高的计算性能。

2.更高并行性、能效比:FPGA拥有更丰富的计算资源组件,从而能够满足更多并行计算需求。并且能够充分发掘软件算法中的并行性,降低功耗。

同时,新架构融合CPU+FPGA,将成为一种发展趋势:

  1. 异构核首次作为一等公民:通过CPU+FPGA的融合设计,由主机+外设的Offloading模式转变为异构多核片上系统设计,CPU与FPGA地位等同,通信方式由板级转向片内。

2. OpenCL带来了FPGA的编程革命:提高了FPGA的可编程性,将程序员从复杂的硬件电路设计中解救出来,更专注于系统/算法的设计。

48fc141f80e5146bb5d36c5eef89fdbd.png

2.4 总结

根据下表可以看出,两者采用了不同的开发语言:

(1)CUDA采用的是CUDA C作为开发语言,是一种类C的编程语言,它包含对C语言的最小扩展集和一个运行时库,编写的文件由NVCC编译器编译。CUDA C对C语言的扩展集引入了变量类型限定符、函数类型限定符等,

(2)OpenCL采用的是基于ISO C99的OpenCL C语言,也是一种类C的编程语言。但OpenCL C引入了一些函数限定符、变量限定符,并且支持C语言中原有的一些数据类型,还增加了一些新的数据类型如half类型、内建的矢量数据类型等,OpenCL C还提供了丰富的内建函数,其中有些内建函数名和C语言的库函数相同,只是实现有所不同。OpenCL C为开发者提供的是统一的编程语言,适合在各种处理器上实现通用计算,并且程序移植性好。

表1.CUDA与OpenCL术语对比 8f668805811079d66a05d78815388357.png表2.CUDA与OpenCL特点对比 a35afef1c9e1edc7511e31114b5fc226.png

3、异构计算的典型应用

异构计算并不神秘,目前已渗透各个领域,不仅是PC领域,也包括了手持移动设备领域、行业领域,甚至是云计算、分布式计算领域。事实上,异构计算至少在应用端(前台)并不像它的名字这样生涩,很多应用里面,都有异构计算的身影。小到网页及视频加速,大到DNA计算、蛋白质计算、气象运算,都能和异构计算搭上关系。但都有一定的限制,如_global_函数类型限定符用于声明内核函数,只能在设备上执行,从主机调用。

3.1 AMD视频稳定技术

视频是和大家息息相关高频应用。而AMD、英特尔和NVIDIA在视频领域都有GPU加速/解码/转码技术——这一点大家都知道了。但还有些技术可能大家还不了解,比如图像稳定技术。

我们时常遇到抖动的视频,这种抖动可能源于拍摄者的手不稳,也可能是因为长焦拍摄。无论如何,AMD通过异构计算拿出了解决方案:2011年中,AMD 宣布了“Steady Video”技术,可以实时对抖动画面进行稳定化处理。不过由于缺乏播放软件的支持,该技术一直是“只闻其声,不见其形”,真正的应用并不多。而在AFDS 2012上,这一技术的升级版再度出击——与去年不同的是,如今,你使用APU平台笔记本,抑或是使用带有AMD独显,就能实实在在地感受到这一技术带来的良好特性。

YouTube视频在线播放目前已经能够一键开启Steady Video技术(绝大部分和主流浏览器都支持),而且,这种技术甚至已经能够在Windows Media Player 上实现!

b35c4e9bf5a80e860447c5631da29cee.png

我们在A10-4600M APU笔记本上进行了实测(Win 7系统),以佳能SX30 IS拍摄.mov格式的视频。实测中我们发现,只要视频初期存在抖动,在用Windows Media Player进行播放时,Steady Video功能就会自动开启——这时,在播放界面的右下角会短暂出现Steady Video的图标,说明该功能正在启用。而我们用35倍光学变焦拍摄的视频,其图像稳定的效果非常显著!

Steady Video是一个很典型的异构计算应用,因为它并非完全采用GPU而解放CPU资源,而是将实时的视频图像处理任务进行了智能分工,分别交给CPU 和GPU共同完成。

3.2 人脸识别

人脸识别是生物识别这个大范畴中的一类,目前广泛地运用在日常的娱乐生活中,相机拍照、摄像头人脸识别登录,甚至是目前很火的摄像头动作感应游戏,都是基于人脸识别系统的。那么,人脸识别怎么会和异构计算扯上关系的呢?

人脸识别系统后台有面部模型,而其识别工作方式可能是这样的(不同软件会有区别):先把画面分成若干区域,大家可理解为一个区域对应一个识别框。然后,针对识别框进行识别和判定。每个识别框不是完全独立的,而是有大量重复区域。也就是说,整个画面会被分成海量的区域(识别框)。工作量如此大的“重复简单劳动”,让CPU来运算就很头疼了——因为它得一个一个地(特指单核CPU)比对、判定,就像跑马拉松;而GPU的核非常多,可同时对多个识别框进行比对和判定,效率大大提升。

014291fcdf5d916e4b63bea70d9d6bb5.png

或许有人会说:CPU速度快,可以弥补数量的不足。但人脸识别绝非图示那么简单。举例来说,如果识别框的大小设定不对(如下图),就无法正常识别到人脸。那么在完成一次全画面识别后,需让识别框变大点再从头开始——这样看来,就是恐怖的工作量了。一张1920×1080分辨率的静态图片若经多次识别框大小调整并最终找到人脸,识别(框)总量大概为4百万个!如果是动态视频(等同于人脸跟踪),每秒的运算量还要翻几十倍!很显然,这类工作是GPU的专长。同时,GPU还会引入新的算法,会将画面先分为若干独立区域,利用面部模型先排除掉完全无人脸特征的区域,然后对剩下的区域进行并行计算(识别),效率可大幅提升。

3.3星云计算

星云计算,这个词对于咱普通人可能觉得有些陌生,只知道通过各种太空望远镜和卫星拍摄的星云图、星系图好漂亮!不过宇宙中有数不清的星星,一个星系可能就有上万亿颗星星(银河系有400亿颗),而目前探知的星系就有1250亿个……

如果天文学家要演示和模拟星球的运行和分布,将一个星系图线性放大到星球图,会是多大的工作量呢!?很显然,内核不多的CPU干这个活儿是难以想象的。拥有上千流处理器的GPU干起来效率就高多了。通过GPU的加速,可以实现多至数百万个运算星体的的处理工作,图像缩放时可达60帧/秒,观看者完全感觉不到停顿。

7ae008f956523472cdc979f07739408d.png

当然,如果纯粹是GPU运算,CPU就闲着了,所以,如果能够动态结合CPU 极高的频率和GPU的并行运算能力,效率就能得到最大的提升。在这个应用中,节能不是第一要素,而是在固定的投入下发挥出最大工作效率,这也是异构计算的目的之一。

12ace13018e22c6942fd83d06532dc42.png

Zynq MPSOC 电子书免费下载

 

ebf8c938146552e3b1feba2ccf99f05b.png

FPGA、Zynq 和 Zynq MPSoC简析及架构分析

Heterogeneous Computing with OpenCL 2.0 teaches OpenCL and parallel programming for complex systems that may include a variety of device architectures: multi-core CPUs, GPUs, and fully-integrated Accelerated Processing Units (APUs). This fully-revised edition includes the latest enhancements in OpenCL 2.0 including: • Shared virtual memory to increase programming flexibility and reduce data transfers that consume resources • Dynamic parallelism which reduces processor load and avoids bottlenecks • Improved imaging support and integration with OpenGL Designed to work on multiple platforms, OpenCL will help you more effectively program for a heterogeneous future. Written by leaders in the parallel computing and OpenCL communities, this book explores memory spaces, optimization techniques, extensions, debugging and profiling. Multiple case studies and examples illustrate high-performance algorithms, distributing work across heterogeneous systems, embedded domain-specific languages, and will give you hands-on OpenCL experience to address a range of fundamental parallel algorithms. Updated content to cover the latest developments in OpenCL 2.0, including improvements in memory handling, parallelism, and imaging support Explanations of principles and strategies to learn parallel programming with OpenCL, from understanding the abstraction models to thoroughly testing and debugging complete applications Example code covering image analytics, web plugins, particle simulations, video editing, performance optimization, and more
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OpenFPGA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值