A. 并行总线:单片机的单总线如何架构和设计的
首先单片机是一个8bit的mcu所以处理器结构很简单,他的时钟周期低,然后几个时钟周期才处理一条指令,所以用单总线就已经足够了,不需要将数据和指令分开的并行总线,因为快速读进来以后也是等待,没有太多的意义。
因为单片机是单总线,所以他的外设和memory都是利用这个总线进行统一的编址和访问。相当于所有的东西都挂到了这条总线上面来。
B. 多内存控制器能否并行访问DDR同体同行数据
严格的说DDR应该叫DDR SDRAM,人们习惯称为DDR,部分初学者也常看到DDR SDRAM,就认为是SDRAM。DDR SDRAM是Double Data Rate SDRAM的缩写,是双倍速率同步动态随机存储器的意思。DDR内存是在SDRAM内存基础上发展而来的,仍然沿用SDRAM生产体系,因此对于内存厂商而言,只需对制造普通SDRAM的设备稍加改进,即可实现DDR内存的生产,可有效的降低成本。
C. AGP显卡的特点与功能
AGP(Accelerate Graphical Port),加速图形接口。随着显示芯片的发展,PCI总线日益无法满足其需求。英特尔于1996年7月正式推出了AGP接口,它是一种显示卡专用的局部总线。严格的说,AGP不能称为总线,它与PCI总线不同,因为它是点对点连接,即连接控制芯片和AGP显示卡,但在习惯上我们依然称其为AGP总线。AGP接口是基于PCI 2.1 版规范并进行扩充修改而成,工作频率为66MHz。
◆ AGP总线直接与主板的北桥芯片相连,且通过该接口让显示芯片与系统主内存直接相连,避免了窄带宽的PCI总线形成的系统瓶颈,增加3D图形数据传输速度,同时在显存不足的情况下还可以调用系统主内存。所以它拥有很高的传输速率,这是PCI等总线无法与其相比拟的。
由于采用了数据读写的流水线操作减少了内存等待时间,数据传输速度有了很大提高;具有133MHz及更高的数据传输频率;地址信号与数据信号分离可提高随机内存访问的速度;采用并行操作允许在CPU访问系统RAM的同时AGP显示卡访问AGP内存;显示带宽也不与其它设备共享,从而进一步提高了系统性能。
AGP标准在使用32位总线时,有66MHz和133MHz两种工作频率,最高数据传输率为266Mbps和533Mbps,而PCI总线理论上的最大传输率仅为133Mbps。目前最高规格的AGP 8X模式下,数据传输速度达到了2.1GB/s。
AGP接口的发展经历了AGP1.0(AGP1X、AGP2X)、AGP2.0(AGP Pro、AGP4X)、AGP3.0(AGP8X)等阶段,其传输速度也从最早的AGP1X的266MB/S的带宽发展到了AGP8X的2.1GB/S。
AGP 1.0(AGP1X、AGP2X)
1996年7月AGP 1.0 图形标准问世,分为1X和2X两种模式,数据传输带宽分别达到了266MB/s和533MB/s。这种图形接口规范是在66MHz PCI2.1规范基础上经过扩充和加强而形成的,其工作频率为66MHz,工作电压为3.3v,在一段时间内基本满足了显示设备与系统交换数据的需要。这种规范中的AGP带宽很小,现在已经被淘汰了,只有在前几年的老主板上还见得到。
AGP2.0(AGP4X)
显示芯片的飞速发展,图形卡单位时间内所能处理的数据呈几何级数成倍增长,AGP 1.0 图形标准越来越难以满足技术的进步了,由此AGP 2.0便应运而生了。1998年5月份,AGP 2.0 规范正式发布,工作频率依然是66MHz,但工作电压降低到了1.5v,并且增加了4x模式,这样它的数据传输带宽达到了1066MB/sec,数据传输能力大大地增强了。
◆ AGP Pro
AGP Pro接口与AGP 2.0同时推出,这是一种为了满足显示设备功耗日益加大的现实而研发的图形接口标准,应用该技术的图形接口主要的特点是比AGP 4x略长一些,其加长部分可容纳更多的电源引脚,使得这种接口可以驱动功耗更大(25-110w)或者处理能力更强大的AGP显卡。这种标准其实是专为高端图形工作站而设计的,完全兼容AGP 4x规范,使得AGP 4x的显卡也可以插在这种插槽中正常使用。AGP Pro在原有AGP插槽的两侧进行延伸,提供额外的电能。它是用来增强,而不是取代现有AGP插槽的功能。根据所能提供能量的不同,可以把AGP Pro细分为AGP Pro110和AGP Pro50。在某些高档台式机主板上也能见到AGP Pro插槽,例如华硕的许多主板。
AGP 3.0(AGP8X)
2000年8月,Intel推出AGP3.0规范,工作电压降到0.8V,并增加了8x模式,这样它的数据传输带宽达到了2133MB/sec,数据传输能力相对于AGP 4X成倍增长,能较好的满足当前显示设备的带宽需求。
AGP接口的模式传输方式
不同AGP接口的模式传输方式不同。1X模式的AGP,工作频率达到了PCI总线的两倍—66MHz,传输带宽理论上可达到266MB/s。AGP 2X工作频率同样为66MHz,但是它使用了正负沿(一个时钟周期的上升沿和下降沿)触发的工作方式,在这种触发方式中在一个时钟周期的上升沿和下降沿各传送一次数据,从而使得一个工作周期先后被触发两次,使传输带宽达到了加倍的目的,而这种触发信号的工作频率为133MHz,这样AGP 2X的传输带宽就达到了266MB/s×2(触发次数)=533MB/s的高度。AGP 4X仍使用了这种信号触发方式,只是利用两个触发信号在每个时钟周期的下降沿分别引起两次触发,从而达到了在一个时钟周期中触发4次的目的,这样在理论上它就可以达到266MB/s×2(单信号触发次数)×2(信号个数)=1066MB/s的带宽了。在AGP 8X规范中,这种触发模式仍然使用,只是触发信号的工作频率变成266MHz,两个信号触发点也变成了每个时钟周期的上升沿,单信号触发次数为4次,这样它在一个时钟周期所能传输的数据就从AGP4X的4倍变成了8倍,理论传输带宽将可达到266MB/s×4(单信号触发次数)×2(信号个数)=2133MB/s的高度了。
目前常用的AGP接口为AGP4X、AGP PRO、AGP通用及AGP8X接口。需要说明的是由于AGP3.0显卡的额定电压为0.8—1.5V,因此不能把AGP8X的显卡插接到AGP1.0规格的插槽中。这就是说AGP8X规格与旧有的AGP1X/2X模式不兼容。而对于AGP4X系统,AGP8X显卡仍旧在其上工作,但仅会以AGP4X模式工作,无法发挥AGP8X的优势。
http://publish.it168.com/cword/1316.shtml
PCI E
PCI-Express是最新的总线和接口标准,它原来的名称为“3GIO”,是由英特尔提出的,很明显英特尔的意思是它代表着下一代I/O接口标准。交由PCI-SIG(PCI特殊兴趣组织)认证发布后才改名为“PCI-Express”。这个新标准将全面取代现行的PCI和AGP,最终实现总线标准的统一。它的主要优势就是数据传输速率高,目前最高可达到10GB/s以上,而且还有相当大的发展潜力。PCI Express也有多种规格,从PCI Express 1X到PCI Express 16X,能满足现在和将来一定时间内出现的低速设备和高速设备的需求。能支持PCI Express的主要是英特尔的i915和i925系列芯片组。当然要实现全面取代PCI和AGP也需要一个相当长的过程,就象当初PCI取代ISA一样,都会有个过渡的过程。
PCI Express(以下简称PCI-E)采用了目前业内流行的点对点串行连接,比起PCI以及更早期的计算机总线的共享并行架构,每个设备都有自己的专用连接,不需要向整个总线请求带宽,而且可以把数据传输率提高到一个很高的频率,达到PCI所不能提供的高带宽。相对于传统PCI总线在单一时间周期内只能实现单向传输,PCI-E的双单工连接能提供更高的传输速率和质量,它们之间的差异跟半双工和全双工类似。
PCI-E的接口根据总线位宽不同而有所差异,包括X1、X4、X8以及X16,而X2模式将用于内部接口而非插槽模式。PCI-E规格从1条通道连接到32条通道连接,有非常强的伸缩性,以满足不同系统设备对数据传输带宽不同的需求。此外,较短的PCI-E卡可以插入较长的PCI-E插槽中使用,PCI-E接口还能够支持热拔插,这也是个不小的飞跃。PCI-E X1的250MB/秒传输速度已经可以满足主流声效芯片、网卡芯片和存储设备对数据传输带宽的需求,但是远远无法满足图形芯片对数据传输带宽的需求。 因此,用于取代AGP接口的PCI-E接口位宽为X16,能够提供5GB/s的带宽,即便有编码上的损耗但仍能够提供约为4GB/s左右的实际带宽,远远超过AGP 8X的2.1GB/s的带宽。
尽管PCI-E技术规格允许实现X1(250MB/秒),X2,X4,X8,X12,X16和X32通道规格,但是依目前形式来看,PCI-E X1和PCI-E X16已成为PCI-E主流规格,同时很多芯片组厂商在南桥芯片当中添加对PCI-E X1的支持,在北桥芯片当中添加对PCI-E X16的支持。除去提供极高数据传输带宽之外,PCI-E因为采用串行数据包方式传递数据,所以PCI-E接口每个针脚可以获得比传统I/O标准更多的带宽,这样就可以降低PCI-E设备生产成本和体积。另外,PCI-E也支持高阶电源管理,支持热插拔,支持数据同步传输,为优先传输数据进行带宽优化。
http://ke..com/view/238809.htm
***********************************************************
APG显卡: 比如GF4 MX440/G FX5700/G FX5200 /G FX6200/ATI 9550
PCI-E显卡:比如ATI X300/X550/X700/X1300/X1500等以上
还有GF 7100LE/7300LE/7300GT/7600GS/7900等以上
D. 哪种内存技术允许同时访问两个内存模块 1双面 2sram 3双通道 4ecc
双通道内存技术允许同时访问两个内存模块。
双通道内存技术其实就是双通道内存控制技术,能有效地提高内存总带宽,从而适应新的微处理器的数据传输、处理的需要。它的技术核心在于芯片组(北桥)可以在两个不同的数据通道上分别寻址、读取数据R内存可以达到128位的带宽。
双通道内存技术的优点:
1、能够带来2倍的内存带宽,从而可以那些与必须内存数据进行频繁交换的软件得到极大的好处,譬如SPEC Viewperf、3DMAX、IBM Data Explorer、Lightscape等。
2、在板载显卡共享内存的时候,双通道技术带来的高内存带宽可以帮助显卡在游戏中获得更为流畅的速度,以3Dmark2001Se为例,其得分成绩的差距,可以拉大到15-40%。
(4)并行架构内存访问扩展阅读
双通道内存对于笔记本的缺点:
1、必须构架在支持双通道的主板上,并且必须要有两条相同容量、类型内存条。英特尔的双通道对于内存类型和容量要求很高,两根内存条必须完全一致。而SIS和VIA的双通道主板则允许不同容量和类型的内存共存,只要是两根内存条就行。
2、双通道内存控制技术在普通的游戏和应用上,与单通道的差距极小。
3、需要购买支持双通道内存控制技术的主板和两根内存条,而这需要更多的成本。
4、双通道的接法,对于初手来说十分重要,一旦接法不正确,将无法使双通道起作用。
5、双通道内存架构,其超频比较困难,这就限制了喜欢DIY超频用户。
E. 哪种内存技术允许同时访问两个内存模块
双通道内存技术允许同时访问两个内存模块。
双通道内存技术其实就是双通道内存控制技术,能有效地提高内存总带宽,从而适应新的微处理器的数据传输、处理的需要。
它的技术核心在于芯片组(北桥)可以在两个不同的数据通道上分别寻址、读取数据R内存可以达到128位的带宽。
双通道内存技术的优点:
1、能够带来2倍的内存带宽,从而可以那些与必须内存数据进行频繁交换的软件得到极大的好处,譬如SPEC Viewperf、3DMAX、IBM Data Explorer、Lightscape等。
2、在板载显卡共享内存的时候,双通道技术带来的高内存带宽可以帮助显卡在游戏中获得更为流畅的速度,以3Dmark2001Se为例,其得分成绩的差距,可以拉大到15-40%。
(5)并行架构内存访问扩展阅读:
应用:
双通道内存主要是依靠主板北桥的控制技术,与内存本身无关。
目前支持双通道内存技术的主板有Intel的i865和i875系列,SIS的SIS655、658系列,nVIDIAD的nFORCE2系列等。
Intel最先推出的支持双通道内存技术的芯片组为E7205和E7500系列。
双通道内存的安装有一定的要求。
主板的内存插槽的颜色和布局一般都有区分。
如果是Intel的i865和i875系列,主板一般有4个DIMM插槽,每两根一组,每组颜色一般不一样,每一个组代表一个内存通道,只有当两组通道上都同时安装了内存条时,才能使内存工作在双通道模式下。
另外要注意对称安装,即第一个通道第1个插槽搭配第二个通道第1个插槽,依此类推。用户只要按不同的颜色搭配,对号入座地安装即可。
如果在相同颜色的插槽上安装内存条,则只能工作在单通道模式。而nFORCE2系列主板同样有两个64bit的内存控制器,其中A控制器只支持一根内存插槽,B通道则支持两根。
A、B插槽之间有一段距离,以方便用户识别。
A通道的内存插槽在颜色上也可能与B通道两个内存插槽不同,用户只要将一根内存插入独立的内存插槽而将另外一根插到另外两个彼此靠近的内存插槽就能组建成双通道模式。
此外,如果全部插满内存,也能建立双通道模式,而且nForce2主板在组建双通道模式时对内存容量乃至型号都没有严格的要求,使用方便。
如果安装方法正确,在主板开机自检时,屏幕显示内存的工作模式(如DDR333 Dual Channel Mode Enabled、激活双通道模式等),则内存已经工作在双通道模式。
F. 并行处理的并行算法的基本策略
在并行处理技术中所使用的算法主要遵循三种策略:
1.分而治之法:也就是把多个任务分解到多个处理器或多个计算机中,然后再按照一定的拓扑结构来进行求解。
2.重新排序法:分别采用静态或动态的指令词度方式。
3.显式/隐式并行性结合:显式指的是并行语言通过编译形成并行程序,隐式指的是串行语言通过编译形成并行程序,显式/隐式并行性结合的关键就在于并行编译,而并行编译涉及到语句、程序段、进程以及各级程序的并行性。
二、并行性描述定义
利用计算机语言进行并行性描述的时候主要有三种方案:
1.语言扩展方案:也就是利用各种语言的库函数来进行并行性功能的扩展。
2.编译制导法:也称为智能编译,它是隐式并行策略的体现,主要是由并行编译系统进行程序表示、控制流的分析、相关分析、优化分析和并行化划分,由相关分析得到方法库管理方案,由优化分析得到知识库管理方案,由并行化划分得到程序重构,从而形成并行程序。
3.新的语言结构法:这是显式并行策略的体现。也就是建立一种全新的并行语言的体系,而这种并行语言通过编译就能直接形成并行程序。
三、并行软件
并行软件可分成并行系统软件和并行应用软件两大类,并行系统软件主要指并行编译系统和并行操作系统,并行应用软件主要指各种软件工具和应用软件包。在软件中所牵涉到的程序的并行性主要是指程序的相关性和网络互连两方面。
1.程序的相关性:程序的相关性主要分为数据相关、控制相关和资源相关三类。
数据相关说明的是语句之间的有序关系,主要有流相关、反相关、输出相关、I/O相关和求知相关等,这种关系在程序运行前就可以通过分析程序确定下来。数据相关是一种偏序关系,程序中并不是每一对语句的成员都是相关联的。可以通过分析程序的数据相关,把程序中一些不存在相关性的指令并行地执行,以提高程序运行的速度。
控制相关指的是语句执行次序在运行前不能确定的情况。它一般是由转移指令引起的,只有在程序执行到一定的语句时才能判断出语句的相关性。控制相关常使正在开发的并行性中止,为了开发更多的并行性,必须用编译技术克服控制相关。
而资源相关则与系统进行的工作无关,而与并行事件利用整数部件、浮点部件、寄存器和存储区等共享资源时发生的冲突有关。软件的并行性主要是由程序的控制相关和数据相关性决定的。在并行性开发时往往把程序划分成许多的程序段——颗粒。颗粒的规模也称为粒度,它是衡量软件进程所含计算量的尺度,一般用细、中、粗来描述。划分的粒度越细,各子系统间的通信时延也越低,并行性就越高,但系统开销也越大。因此,我们在进行程序组合优化的时候应该选择适当的粒度,并且把通讯时延尽可能放在程序段中进行,还可以通过软硬件适配和编译优化的手段来提高程序的并行度。
2.网络互连:将计算机子系统互连在一起或构造多处理机或多计算机时可使用静态或动态拓扑结构的网络。静态网络由点一点直接相连而成,这种连接方式在程序执行过程中不会改变,常用来实现集中式系统的子系统之间或分布式系统的多个计算结点之间的固定连接。动态网络是用开关通道实现的,它可动态地改变结构,使之与用户程序中的通信要求匹配。动态网络包括总线、交叉开关和多级网络,常用于共享存储型多处理机中。在网络上的消息传递主要通过寻径来实现。常见的寻径方式有存储转发寻径和虫蚀寻径等。在存储转发网络中以长度固定的包作为信息流的基本单位,每个结点有一个包缓冲区,包从源结点经过一系列中间结点到达目的结点。存储转发网络的时延与源和目的之间的距离(段数)成正比。而在新型的计算机系统中采用虫蚀寻径,把包进一步分成一些固定长度的片,与结点相连的硬件寻径器中有片缓冲区。消息从源传送到目的结点要经过一系列寻径器。同一个包中所有的片以流水方式顺序传送,不同的包可交替地传送,但不同包的片不能交叉,以免被送到错误的目的地。虫蚀寻径的时延几乎与源和目的之间的距离无关。在寻径中产生的死锁问题可以由虚拟通道来解决。虚拟通道是两个结点间的逻辑链,它由源结点的片缓冲区、结点间的物理通道以及接收结点的片缓冲区组成。物理通道由所有的虚拟通道分时地共享。虚拟通道虽然可以避免死锁,但可能会使每个请求可用的有效通道频宽降低。因此,在确定虚拟通道数目时,需要对网络吞吐量和通信时延折衷考虑。
四、硬件技术在硬件技术方面主要从处理机、存储器和流水线三个方面来实现并行。
1.处理机:主要的处理机系列包括CISC、RISC、超标量、VL1W、超流水线、向量以及符号处理机。
传统的处理机属于复杂指令系统计算(CISC)结构。指令系统大,指令格式可变,通用寄存器个数较少,基本上使用合一的指令与数据高速缓存,时钟频率较低,CPI较高,大多数利用ROM 实现微码控制CPU,而当今的精简指令系统计算(RISC)处理机指令格式简单规范,面向寄存器堆,采用重叠寄存器窗口技术,具有多级Cache,多种流水线结构,强调编译优化技术,时钟频率快,CPI低,大多数用硬连线控制CPU。
CISC或RISC标量处理机都可以采用超标量或向量结构来改善性能。标量处理机在每个周期内只发射一条指令并要求周期只完成从流水线来的一条指令。而在超标量处理机中,使用了多指令流水线,每个周期要发射多条指令并产生多个结果。由于希望程序中有许多的指令级并行性,因此超标量处理机更要依靠优化编译器去开发并行性。
VL1W 结构是将水平微码和超标量处理这两种普遍采用的概念结合起来产生的。典型的超长指令字VL1W 机器指令字长度有数百位。在VLlW 处理机中,多个功能部件是并发工作的,所有的功能部件共享使用公用大型寄存器堆,由功能部件同时执行的各种操作是用VL1W 指令来同步的,每条指令可指定多个操作。VL1W 指令译码比超标量指令容易,但在开发不同数量的并行性时总是需要不同的指令系统。VL1W 主要是开发标量操作之间的并行性,它的成功与否很大程度取决于代码压缩的效率,其结构和任何传统的通用处理机完全不兼容。即使同一结构的不同实现也不大可能做到彼此二进制兼容。VL1W 的主要优点在于它的硬件结构和指令系统简单,在科学应用领域可以发挥良好作用,但在一般应用场合可能并不很好用。
向量处理机对数组执行向量指令,每条指令都包含一串重复的操作。它是专门设计用来完成向量运算的协处理机,通常用于多流水线超级计算机中。向量处理机可以利用循环级展开所得的并行性,它可以附属于任何标量处理机。专用的向量流水线可以在循环控制中消除某些软件开销,它的效果与优化编译器将顺序代码向量化的性能很有关系。从理论上说,向量机可以具有和超标量处理机同样的性能,因此可以说向量机的并行性与超标量机相同。
符号处理机是为AI应用而研制的,已用于定理证明、模式识别、专家系统、知识工程、文本检索、科学以及机器智能等许多应用领域。在这些应用中,数据和知识表达式、原语操作、算法特性、存储器、I/0和通信以及专用的结构特性与数值计算是不一样的,符号处理机也称为逻辑程序设计语言处理机、表处理语言处理机或符号变换器。符号处理并不和数值数据打交道,它处理的是逻辑程序、符号表、对象、剧本、黑板、产生式系统、语义网络、框架以及人工神经网络等问题。这些操作需要专门的指令系统,通常不使用浮点操作。
2.存储器:存储设备按容量和存取时间从低到高可分为寄存器、高速缓存、主存储器、磁盘设备和磁带机五个层次。较低层存储设备与较高层的相比,存取速度较快、容量较小,每字节成本较高、带宽较宽、传输单位较小。
存放在存储器层次结构中的信息满足三个重要特性:包含性、一致性和局部性。所谓包含性,指的是一个信息字的复制品可以在比它高的所有层中找到,而如果在高层中丢失了一个信息,则在比它低的所有层中此信息也将丢失。CPU 和高速缓存之间的信息传送是按字进行的,高速缓存和主存储器间用块作为数据传送的基本单位,主存和磁盘之间又是以页面为基本单位来传送信息的,而在磁盘和磁带机之间的数据传送则是按文件级处理的。所谓一致性要求的是同一个信息项与后继存储器层次上的副本是一致的。也就是说,如果在高速缓存中的一个字被修改过,那么在所有更高层上该字的副本也必须立即或最后加以修改。为了尽量减少存储器层次结构的有效存取时间,通常把频繁使用的信息放在较低层次。维护存储器层次结构一致性一般有两种策略,一种是写直达策略,也就是如果,则立即在所有高层存储器中进行同样的修改;另一种是写回策略,也就是在较低层中对信息进行修改后并不立即在高层存储器中进行相应的修改,而是等到该信息将被替换或将从低层中消失时才在所有高层存储器中进行同样的修改。甚至可以将写直达和写回策略的优点结合起来,形成写一次协议来维护存储器的一致性。
存储器的层次结构是在一种程序行为——访问的局部性基础上开发出来的。主要有时间局部性、空间局部性和顺序局部性。时间局部性指的是最近的访问项很可能在不久的将来再次被访问。它往往会引起对最近使用区域的集中访问。空间局部性表示一种趋势,指的是一个进程访问的各项其地址彼此很近。顺序局部性指的是在典型程序中,除非是转移指令,一般指令都是顺序执行的。
在多处理机系统中一般使用共享存储器。对共享存储器的组织一般采用低位交叉、高位交叉、高低位交叉三种方法。低位交叉又称并发存取,它是把相邻的地址放在相邻的存储器模块中,在访问时不容易产生冲突,并行性较好,但可靠性容错能力和扩展性均较差。高位交叉又称允许同时存取,它是把相邻地址分配到同一个存储器模块中,可靠性、容错能力和扩展性均较强,但访问时易产生冲突,带宽较窄,并行性较差。高低位交叉存取又称C—s存取,它是结合了高位交叉和低位交叉两种方法的优点,既解决了冲突问题,又能有效地提高容错能力和并行性,最适合于向量处理机结构。
3.流水线:流水线技术主要有指令流水线技术和运算流水线技术两种。
指令流水线技术主要目的是要提高计算机的运行效率和吞吐率。它主要通过设置预取指令缓冲区、设置多功能部件、进行内部数据定向、采取适当的指令调度策略来实现。指令调度的策略主要有静态和动态两种,静态词度是基于软件的,主要由编译器完成,动态词度是基于硬件的,主要是通过硬件技术进行。
运算流水线主要有单功能流水线和多功能流水线两种。其中多功能流水线又可分为静态流水线和动态流水线。静态流水线技术只用来实现确定的功能,而动态流水线可以在不同时间重新组合,实现不同的功能,它除流线连接外,还允许前馈和反馈连接,因此也称为非线性流水线。这些前馈和反馈连接使得进入流水线的相继事件的词度变得很不简单。由于这些连接,流水线不一定从最后一段输出。根据不同的数据流动模式,人们可以用同一条流水线求得不同功能的值。
并行计算机发展简述
40 年代开始的现代计算机发展历程可以分为两个明显的发展时代:串行计算时代、并行计算时代。每一个计算时代都从体系结构发展开始,接着是系统软件(特别是编译器与操作系统)、应用软件,最后随着问题求解环境的发展而达到顶峰。创建和使用并行计算机的主要原因是因为并行计算机是解决单处理器速度瓶颈的最好方法之一。
并行计算机是由一组处理单元组成的,这组处理单元通过相互之间的通信与协作,以更快的速度共同完成一项大规模的计算任务。因此,并行计算机的两个最主要的组成部分是计算节点和节点间的通信与协作机制。并行计算机体系结构的发展也主要体现在计算节点性能的提高以及节点间通信技术的改进两方面。
60 年代初期,由于晶体管以及磁芯存储器的出现,处理单元变得越来越小,存储器也更加小巧和廉价。这些技术发展的结果导致了并行计算机的出现,这一时期的并行计算机多是规模不大的共享存储多处理器系统,即所谓大型主机(Mainframe)。IBM360 是这一时期的典型代表。
到了60 年代末期,同一个处理器开始设置多个功能相同的功能单元,流水线技术也出现了。与单纯提高时钟频率相比,这些并行特性在处理器内部的应用大大提高了并行计算机系统的性能。伊利诺依大学和Burroughs 公司此时开始实施IlliacIV 计划,研制一台64 个CPU 的SIMD 主机系统,它涉及到硬件技术、体系结构、I/O 设备、操作系统、程序设计语言直至应用程序在内的众多研究课题。不过,当一台规模大大缩小了的16CPU 系统终于在1975 年面世时,整个计算机界已经发生了巨大变化。
首先是存储系统概念的革新,提出虚拟存储和缓存的思想。IBM360/85 系统与360/91是属于同一系列的两个机型,360/91 的主频高于360/85,所选用的内存速度也较快,并且采用了动态调度的指令流水线;但是,360/85 的整体性能却高于360/91,唯一的原因就是前者采用了缓存技术,而后者则没有。
其次是半导体存储器开始代替磁芯存储器。最初,半导体存储器只是在某些机器被用作缓存,而CDC7600 则率先全面采用这种体积更小、速度更快、可以直接寻址的半导体存储器,磁芯存储器从此退出了历史舞台。与此同时,集成电路也出现了,并迅速应用到了计算机中。元器件技术的这两大革命性突破,使得IlliacIV 的设计者们在底层硬件以及并行体系结构方面提出的种种改进都大为逊色。
1976 年CRAY-1 问世以后,向量计算机从此牢牢地控制着整个高性能计算机市场15 年。CRAY-1 对所使用的逻辑电路进行了精心的设计,采用了我们如今称为RISC 的精简指令集,还引入了向量寄存器,以完成向量运算。这一系列全新技术手段的使用,使CRAY-1 的主频达到了80MHz。
微处理器随着机器的字长从4 位、8 位、16 位一直增加到32 位,其性能也随之显着提高。正是因为看到了微处理器的这种潜力,卡内基- 梅隆大学开始在当时流行的DECPDP11 小型计算机的基础上研制成功一台由16 个PDP11/40 处理机通过交叉开关与16 个共享存储器模块相连接而成的共享存储多处理器系统C.mmp。
从80 年代开始,微处理器技术一直在高速前进。稍后又出现了非常适合于SMP 方式的总线协议,而伯克利加州大学则对总线协议进行了扩展,提出了Cache 一致性问题的处理方案。从此,C.mmp 开创出的共享存储多处理器之路越走越宽;现在,这种体系结构已经基本上统治了服务器和桌面工作站市场。
同一时期,基于消息传递机制的并行计算机也开始不断涌现。80 年代中期,加州理工成功地将64 个i8086/i8087 处理器通过超立方体互连结构连结起来。此后,便先后出现了Intel iPSC 系列、INMOS Transputer 系列,Intel Paragon 以及IBM SP 的前身Vulcan 等基于消息传递机制的并行计算机。
80 年代末到90 年代初,共享存储器方式的大规模并行计算机又获得了新的发展。IBM将大量早期RISC 微处理器通过蝶形互连网络连结起来。人们开始考虑如何才能在实现共享存储器缓存一致的同时,使系统具有一定的可扩展性(Scalability)。90 年代初期,斯坦福大学提出了DASH 计划,它通过维护一个保存有每一缓存块位置信息的目录结构来实现分布式共享存储器的缓存一致性。后来,IEEE 在此基础上提出了缓存一致性协议的标准。
90 年代以来,主要的几种体系结构开始走向融合。属于数据并行类型的CM-5 除大量采用商品化的微处理器以外,也允许用户层的程序传递一些简单的消息;CRAY T3D是一台NUMA 结构的共享存储型并行计算机,但是它也提供了全局同步机制、消息队列机制,并采取了一些减少消息传递延迟的技术。
随着商品化微处理器、网络设备的发展,以及MPI/PVM 等并行编程标准的发布,机群架构的并行计算机出现。IBM SP2 系列机群系统就是其中的典型代表。在这些系统中,各个节点采用的都是标准的商品化计算机,它们之间通过高速网络连接起来。
今天,越来越多的并行计算机系统采用商品化的微处理器加上商品化的互连网络构造,这种分布存储的并行计算机系统称为机群。国内几乎所有的高性能计算机厂商都生产这种具有极高性能价格比的高性能计算机,并行计算机就进入了一个新的时代,并行计算的应用达到了前所未有的广度和深度。
并行计算机随着微处理芯片的发展,已经进入了一个新时代。目前并行计算机的性能已经突破20PFLOPS,正在向百亿亿次发展。我国并行计算机的研制已经走在世界前列。2003年由联想公司生产的深腾6800 在2003 年11 月世界TOP500 排名中位列第14 名,2004 年曙光公司生产的曙光4000A 在2004 年6 月的世界TOP500 排名中位列第10 名,这是我国公开发布的高性能计算机在世界TOP500 中首次进入前十名,这标志着我国在并行计算机系统的研制和生产中已经赶上了国际先进水平,为提高我国的科学研究水平奠定了物质基础。2013年国际超级计算机大会最新发布的世界超级计算机500强排名中,国防科技大学研制的天河二号超级计算机系统,以峰值计算速度每秒5.49亿亿次、持续计算速度每秒3.39亿亿次双精度浮点运算的优异性能位居榜首。
从TOP500 的前10 名来看,美国仍然是超级计算机的最大拥有者。按照世界TOP500 的统计数据来分析,美国在计算能力上占有近全世界的一半,在TOP500 中的所有计算机中拥有的数量超过50%。
G. 单核cpu的并行过程,求解答
CPU并行编程概述
并行编程的演化
一个自然而然的问题是:为什么要用并行编程?在20世纪70年代、80年代甚至90年代的一部分时间里,我们对单线程编程(或者称为串行编程)非常满意。你可以编写一个程序来完成一项任务。执行结束后,它会给你一个结果。任务完成,每个人都会很开心!虽然任务已经完成,但是如果你正在做一个每秒需要数百万甚至数十亿次计算的粒子模拟,或者正在对具有成千上万像素的图像进行处理,你会希望程序运行得更快一些,这意味着你需要更快的CPU。
在2004年以前,CPU制造商IBM、英特尔和AMD都可以为你提供越来越快的处理器,处理器时钟频率从16 MHz、20 MHz、66 MHz、100 MHz,逐渐提高到200 MHz、333 MHz、466 MHz⋯⋯看起来它们可以不断地提高CPU的速度,也就是可以不断地提高CPU的性能。但到2004年时,由于技术限制,CPU速度的提高不能持续下去的趋势已经很明显了。这就需要其他技术来继续提供更高的性能。CPU制造商的解决方案是将两个CPU放在一个CPU内,即使这两个CPU的工作速度都低于单个CPU。例如,与工作在300 MHz速度上的单核CPU相比,以200 MHz速度工作的两个CPU(制造商称它们为核心)加在一起每秒可以执行更多的计算(也就是说,直观上看2×200 > 300)。
听上去像梦一样的“单CPU多核心”的故事变成了现实,这意味着程序员现在必须学习并行编程方法来利用这两个核心。如果一个CPU可以同时执行两个程序,那么程序员必须编写这两个程序。但是,这可以转化为两倍的程序运行速度吗?如果不能,那我们的2×200 > 300的想法是有问题的。如果一个核心没有足够的工作会怎么样?也就是说,只有一个核心是真正忙碌的,而另一个核心却什么都不做?这样的话,还不如用一个300 MHz的单核。引入多核后,许多类似的问题就非常突出了,只有通过编程才能高效地利用这些核心。
核心越多,并行性越高
程序员不能简单地忽略CPU制造商每年推出的更多数量的核心。2015年,英特尔在市场上推出8核台式机处理器i7-5960X[11]和10核工作站处理器,如Xeon E7-8870 [14]。很明显,这种多核狂热在可预见的未来会持续下去。并行编程从2000年年初的一种奇异的编程模型转变为2015年唯一被接受的编程模型。这种现象并不局限于台式电脑。在移动处理器方面,iPhone和Android手机都有2个或4个核。预计未来几年,移动领域的核心数量将不断增加。
那么,什么是线程?要回答这个问题,让我们来看看8核INTEL CPU i7-5960X [11]。 INTEL的文档说这是一个8C/16T CPU。换句话说,它有8个核心,但可以执行16个线程。你也许听到过并行编程被错误地称为多核编程。正确的术语应该是多线程编程。这是因为当CPU制造商开始设计多核架构时,他们很快意识到通过共享一些核心资源(如高速缓存)来实现在一个核心中同时执行两项任务并不困难。
类比1.1:核心与线程
图1-1显示了两个兄弟Fred和Jim,他们是拥有两台拖拉机的农民。每天,他们开车从农舍到椰子树所在的地方,收获椰子并把它们带回农舍。他们用拖拉机内的锤子来收获(处理)椰子。整个收获过程由两个独立但有序的任务组成,每个任务需要30秒:任务1是从拖拉机走向椰子树,每次带回1颗椰子。任务2是用锤子敲碎(处理)它们,并将它们存放在拖拉机内。Fred每分钟可以处理1颗椰子,而Jim每分钟也可以处理1颗椰子。综合起来,他们俩每分钟可以处理2颗椰子。
一天,Fred的拖拉机发生了故障。他把拖拉机留在修理厂,并把椰子锤忘在了拖拉机内。回到农舍的时候已经太迟了,但他们仍然有工作要做。只使用Jim的拖拉机和里面的1把椰子锤,他们还能每分钟处理2颗椰子吗?
核心与线程
让我们来看看图1-1中描述的类比1.1。如果收获1颗椰子需要完成两个连续的任务(我们将它们称为线程):线程1从树上摘取1颗椰子并花费30秒将它带回拖拉机,线程2花费30秒用拖拉机内的锤子敲碎(处理)该椰子,这样可以在60秒内收获1颗椰子(每分钟1颗椰子)。如果Jim和Fred各自都有自己的拖拉机,他们可以简单地收获两倍多的椰子(每分钟2颗椰子),因为在收获每颗椰子时,他们可以共享从拖拉机到椰子树的道路,并且他们各自拥有自己的锤子。
在这个类比中,一台拖拉机就是一个核心,收获一颗椰子就是针对一个数据单元的程序执行。椰子是数据单元,每个人(Jim、Fred)是一个执行线程,需要使用椰子锤。椰子锤是执行单元,就像核心中的ALU一样。该程序由两个互相依赖的线程组成:在线程1执行结束之前,你无法执行线程2。收获的椰子数量意味着程序性能。性能越高,Jim和Fred销售椰子挣的钱就越多。可以将椰子树看作内存,你可以从中获得一个数据单元(椰子),这样在线程1中摘取一颗椰子的过程就类似于从内存中读取数据单元。
并行化更多的是线程还是核心
现在,让我们看看如果Fred的拖拉机发生故障后会发生什么。过去他们每分钟都能收获两颗椰子,但现在他们只有一台拖拉机和一把椰子锤。他们把拖拉机开到椰子树附近,并停在那儿。他们必须依次地执行线程1(Th1)和线程2(Th2)来收获1颗椰子。他们都离开拖拉机,并在30秒内走到椰子树那儿,从而完成了Th1。他们带回挑好的椰子,现在,他们必须敲碎椰子。但因为只有1把椰子锤,他们不能同时执行Th2。Fred不得不等Jim先敲碎他的椰子,并且在Jim敲碎后,他才开始敲。这需要另外的30+30秒,最终他们在90秒内收获2颗椰子。虽然效率不如每分钟2颗椰子,但他们的性能仍然从每分钟1颗提升至每分钟1.5颗椰子。
收获一些椰子后,Jim问了自己一个问题:“为什么我要等Fred敲碎椰子?当他敲椰子时,我可以立即走向椰子树,并摘获下1颗椰子,因为Th1和Th2需要的时间完全相同,我们肯定不会遇到需要等待椰子锤空闲的状态。在Fred摘取1颗椰子回来的时候,我会敲碎我的椰子,这样我们俩都可以是100%的忙碌。”这个天才的想法让他们重新回到每分钟2颗椰子的速度,甚至不需要额外的拖拉机。重要的是,Jim重新设计了程序,也就是线程执行的顺序,让所有的线程永远都不会陷入等待核心内部共享资源(比如拖拉机内的椰子锤)的状态。正如我们将很快看到的,核心内部的共享资源包括ALU、FPU、高速缓存等,现在,不要担心这些。
我在这个类比中描述了两个配置场景,一个是2个核心(2C),每个核心可以执行一个单线程(1T);另一个是能够执行2个线程(2T)的单个核心(1C)。在CPU领域将两种配置称为2C/2T与lC/2T。换句话说,有两种方法可以让一个程序同时执行2个线程:2C/2T(2个核心,每个核心都可以执行1个线程—就像Jim和Fred的两台单独的拖拉机一样)或者lC/2T(单个核心,能够执行2个线程—就像Jim和Fred共享的单台拖拉机一样)。尽管从程序员的角度来看,它们都意味着具有执行2个线程的能力,但从硬件的角度来看,它们是非常不同的,这要求程序员充分意识到需要共享资源的线程的含义。否则,线程数量的性能优势可能会消失。再次提醒一下:全能的INTEL i7-5960X [11] CPU是8C/l6T,它有8个核心,每个核心能够执行2个线程。
图1-2显示了三种情况:a)是具有2个独立核心的2C/2T情况;b)是具有糟糕编程的1C/2T情况,每分钟只能收获1.5颗椰子;c)是对椰子锤的需求永远不会同时发生的顺序正确版本,每分钟可以收获2颗椰子。
核心资源共享的影响
Jim为自己的发现感到自豪,他们的速度提高到每分钟2颗椰子,Jim希望继续创造一些方法来用一台拖拉机完成更多的工作。一天,他对Fred说:“我买了一把新的自动椰子锤,它在10秒内就能敲碎1颗椰子。”他们对这一发现非常满意,立即出发并将拖拉机停在椰子树旁。这次他们知道在开始收获前必须先做好计划⋯⋯
Fred问道:“如果我们的Th1需要30秒,而Th2需要10秒,并且我们唯一需要共享资源的任务是Th2(椰子锤),我们应该如何收获椰子?”答案对他们来说很清楚:唯一重要的是线程的执行顺序(即程序的设计),应确保他们永远不会遇到两人同时执行Th2并需要唯一的椰子锤(即共享核心资源)的情况。换句话说,它们的程序由两个互相依赖的线程组成:Th1需要30秒,并且不需要共享(内存)资源,因为两个人可以同时步行到椰子树。Th2需要10秒并且不能同时执行,因为他们需要共享(核心)资源:椰子锤。由于每颗椰子需要30+10=40秒的总执行时间,他们能够期望的最好结果是40秒收获2颗椰子,如
图1-2 d所示。如果每个人都按顺序执行Th1和Th2,且不等待任何共享资源,则会发生这种情况。所以,他们的平均速度将是每分钟3颗椰子(即每颗椰子平均20秒)。
内存资源共享的影响
用新的椰子锤实现了每分钟收获3颗椰子后,Jim和Fred第二天开始工作时看到了可怕的一幕。因为昨晚的一场大雨阻塞了半边道路,从拖拉机到椰子树的道路今天只能由一个人通行。所以,他们再次制订计划⋯⋯现在,他们有2个线程,每个线程都需要一个不能共享的资源。Th1(30秒—表示为30s)只能由一人执行,而Th2(10s)也只能由一人执行。怎么办?
考虑多种选择后,他们意识到其速度的限制因素是Th1,他们能达到的最好目标是30秒收获1颗椰子。当可以同时执行Th1(共享内存访问)时,每个人可以顺序地执行10+30s,并且两个人都可以持续运行而无须访问共享资源。但是现在没有办法对这些线程进行排序。他们能够期望的最好结果是执行10+30s并等待20s,因为在此期间两人都需要访问内存。他们的速度回到平均每分钟2颗椰子,如图1-2 e所示。
这场大雨使他们的速度降低到每分钟2颗椰子。Th2不再重要,因为一个人可以不慌不忙地敲椰子,而另一个人正在去摘取椰子的路上。Fred提出了这样一个想法:他们应该从农舍再拿一把(较慢)椰子锤来帮忙。然而,这对于此时的情况绝对没有帮助,因为收获速度的限制因素是Th1。这种来自于某个资源的限制因素被称为资源竞争。这个例子展示了当访问内存是我们程序执行速度的限制因素时会发生什么。处理数据的速度有多快(即核心运行速度)已无关紧要。我们将受到数据获取速度的限制。即使Fred有一把可以在1秒钟内敲碎椰子的椰子锤,但如果存在内存访问竞争,他们仍然会被限制为每分钟2颗椰子。在本书中,我们将区分两种不同类型的程序:核心密集型,该类型不大依赖于内存访问速度;存储密集型,该类型对内存访问速度高度敏感,正如我刚才提到的那样。
第一个串行程序
我们已经理解了椰子世界中的并行编程,现在是时候将这些知识应用于真实计算机编程了。我会先介绍一个串行(即单线程)程序,然后将其并行化。我们的第一个串行程序imf?lip.c读入图1-3(左)中的小狗图片并将其水平(中)或垂直(右)翻转。为了简化程序的解释,我们将使用Bitmap(BMP)图像格式,并将结果也输出为BMP格式。这是一种非常容易理解的图像格式,可以让我们专注于程序本身。不要担心本章中的细节,它们很快就会被解释清楚,目前可以只关注高层的功能。
imflip.c源文件可以在Unix提示符下编译和执行,如下所示:
gcc imflip.c -o imflip
./imflip dogL.bmp dogh.bmp V
在命令行中用“H”指定水平翻转图像(图1-3中),用“V”指定垂直翻转(图1-3右侧)。你将看到如下所示的输出(数字可能不同,取决于你电脑的速度):
Input BMP File name : dogL.bmp (3200×2400)
Output BMP File name : dogh.bmp (3200×2400)
Total execution time : 81.0233 ms (10.550 ns per pixel)
运行该程序的CPU速度非常快,以致我必须将原始的640×480的图像dog.bmp扩展为3200×2400的dogL.bmp,这样它的运行时间才能被测量出来;dogL.bmp的每个维度扩大到原来的5倍,因此比dog.bmp大25倍。统计时间时,我们必须在图像翻转开始和结束时记录CPU的时钟。
理解数据传输速度
从磁盘读取图像的过程(无论是SSD还是硬盘驱动器)应该从执行时间中扣除,这很重要。换句话说,我们从磁盘读取图像,并确保它位于内存中(在我们的数组中),然后只统计翻转操作所需的时间。由于不同硬件部件的数据传输速度存在巨大差异,我们需要分别分析在磁盘、内存和CPU上花费的时间。
在本书将要编写的众多并行程序中,我们重点关注CPU执行时间和内存访问时间,因为我们可以控制它们。磁盘访问时间(称为I/O时间)通常在单线程中就达到极限,因而几乎看不到多线程编程的好处。另外,请记住,当我们开始GPU编程时,较慢的I/O速度会严重困扰我们,因为I/O是计算机中速度最慢的部分,并且从CPU到GPU的数据传输要通过I/O子系统的PCI express总线进行,因此我们将面临如何将数据更快地提供给GPU的挑战。没有人说GPU编程很容易!为了让你了解不同硬件部件的传输速度,我在下面列举了一些:
典型的网卡(NIC)具有1 Gbps的传输速度(千兆比特每秒或一亿比特每秒)。这些卡俗称“千兆网卡”或“Gig网卡”。请注意,1 Gbps只是“原始数据”的数量,其中包括大量的校验码和其他同步信号。传输的实际数据量少于此数量的一半。我的目的是给读者一个大致的概念,这个细节对我们来说并不重要。
即使连接到具有6 Gbps峰值传输速度的SATA3接口,典型的硬盘驱动器(HDD)也几乎无法达到1 Gbps〜2 Gbps的传输速度。HDD的机械读写性质根本不能实现快速的数据访问。传输速度甚至不是硬盘的最大问题,最大问题是定位时间。HDD的机械磁头需要一段时间在旋转的金属柱面上定位需要的数据,这迫使它在磁头到达数据所在位置前必须等待。如果数据以不规则的方式分布(即碎片式的存放),则可能需要毫秒(ms)级的时间。因此,HDD的传输速度可能远远低于它所连接的SATA3总线的峰值速度。
连接到USB 2.0端口的闪存磁盘的峰值传输速度为480 Mbps(兆比特每秒或百万比特每秒)。但是,USB 3.0标准具有更快的5 Gbps传输速度。更新的USB 3.1可以达到10 Gbps左右的传输速率。由于闪存磁盘使用闪存构建,它不需要查找时间,只需提供地址即可直接访问数据。
典型的固态硬盘(SSD)可以连接在SATA3接口上,达到接近4 Gbps〜5 Gbps的读取速度。因此,实际上SSD是唯一可以达到SATA3接口峰值速度的设备,即以预期的6 Gbps峰值速率传输数据。
一旦数据从I/O(SDD、HDD或闪存磁盘)传输到CPU的内存中,传输速度就会大大提高。已发展到第6代的Core i7系列(i7-6xxx),更高端的Xeon CPU使用DDR2、DDR3和DDR4内存技术,内存到CPU的传输速度为20 GBps〜60 GBps(千兆字节每秒)。注意这个速度是千兆字节。一个字节有8个比特,为与其他较慢的设备进行比较,转换为存储访问速度时为160 Gbps〜480 Gbps(千兆比特每秒)。
正如我们将在第二部分及以后所看到的,GPU内部存储器子系统的传输速度可以达到100 GBps〜1000 GBps。例如,新的Pascal系列GPU就具有接近后者的内部存储传输速率。转换后为8000 Gbps,比CPU内部存储器快一个数量级,比闪存磁盘快3个数量级,比HDD快近4个数量级。
imflip.c中的main( )函数
代码1.1中所示的程序会读取一些命令行参数,并按照命令行参数垂直或水平地翻转输入图像。命令行参数由C放入argv数组中。
clock( )函数以毫秒为单位统计时间。重复执行奇数次(例如129次)操作可以提高时间统计的准确性,操作重复次数在"#define REPS 129"行中指定。该数字可以根据你的系统更改。
ReadBMP( )函数从磁盘读取源图像,WriteBMP( )将处理后的(即翻转的)图像写回磁盘。从磁盘读取图像和将图像写入磁盘的时间定义为I/O时间,我们从处理时间中去除它们。这就是为什么我在实际的图像翻转代码之间添加"start = clock( )"和"stop = c1ock( )"行,这些代码对已在内存中的图像进行翻转操作,因此有意地排除了I/O时间。
在输出所用时间之前,imf?lip.c程序会使用一些free( )函数释放所有由ReadBMP( )分配的内存以避免内存泄漏。
代码1.1:imflip.c的main( ){⋯}
imflip.c中的main( )函数读取3个命令行参数,用以确定输入和输出的BMP图像文件名以及翻转方向(水平或垂直)。该操作会重复执行多次(REPS)以提高计时的准确性。
垂直翻转行:FlipImageV( )
代码1.2中的FlipImageV( )遍历每一列,并交换该列中互为垂直镜像的两个像素的值。有关Bitmap(BMP)图像的函数存放在另一个名为ImageStuff.c的文件中,ImageStuff.h是对应的头文件,我们将在下一章详细解释它们。图像的每个像素都以“struct Pixel”类型存储,包含unsigned char类型的该像素的R、G和B颜色分量。由于unsigned char占用1个字节,所以每个像素需要3个字节来存储。
ReadBMP( )函数将图像的宽度和高度分别放在两个变量ip.Hpixels和ip.Vpixels中。存储一行图像需要的字节数在ip.Hbytes中。FlipImageV( )函数包含两层循环:外层循环遍历图像的ip.Hbytes,也就是每一列,内层循环一次交换一组对应的垂直翻转像素。
代码1.2:imflip.c⋯FlipImageV( ){⋯}
对图像的行做垂直翻转,每个像素都会被读取并替换为镜像行中的相应像素。
水平翻转列:FlipImageH( )
imf?lip.c的FlipImageH( )实现图像的水平翻转,如代码1.3所示。除了内层循环相反,该函数与垂直翻转的操作完全相同。每次交换使用“struct Pixel”类型的临时像素变量pix。
由于每行像素以3个字节存储,即RGB、RGB、RGB⋯⋯因此访问连续的像素需要一次读取3个字节。这些细节将在下一节介绍。现在我们需要知道的是,以下几行代码:
只是读取位于垂直的第row行和水平的第col列处的一个像素。像素的蓝色分量在地址img[row][col]处,绿色分量在地址img[row][col+1]处,红色分量在img[row][col+2]处。在下一章中我们将看到,指向图像起始地址的指针img由ReadBMP( )为其分配空间,然后由main( )传递给FlipImageH( )函数。
代码1.3:imflip.cFlipImageH( ){⋯}
进行水平翻转时,每个像素都将被读取并替换为镜像列中相应的像素。
H. 在并行计算中,不同计算机之间需要数据通信,我想实现的是:多台计算机共享服务器内存中的数据
从原理上来说,你现有的环境为多计算机(multi-computer),而你想要的是共享内存式的共享模式,这是很难做到的。共享内存模式一般对应于多处理器(multi-processor)的结构,其与多计算机是MIMD的两个实例。多计算机一般使用消息传递共享模式,经典的是MPI。你的需求其实很早就有人提出来了,类似于DSM模型,即distributed shared memory,不过那个绝不是靠普通PC机搭出来的,也绝不是走网线的,一定是大厂商定制开发的,所以这个你就别想了。另一种解决方案是靠高层抽象,将消息传递抽象成共享存储,但效率比较低,不过貌似大规模分布式系统已采用这种方案,对小型系统没啥优势的。
综上所述,用于并行计算的多计算机使用共享内存模式很难办到。