由于工作变动的缘故,博客一直没有更新什么新的内容,说起来很是惭愧,开始是因为到岗的是一家互联网公司,有自己的专业网站可以写博客,为了支持公司的发展,就另开了一个生活性质的博客,后来是因为去了一家网游公司,我不说大家也都知道,网游公司都是很忙的,加班是家常便饭,基本上没有时间写博客了,2010年春节刚过,有感于自己对技术积累和技术沉淀的怠懈,决定还是坚持写点东西,有时间的话,就把手头的工作总结总结,没时间的话,就把以前写的一些东西发出来,就当是温故而知新吧,闲话少说,言归正传,这里先发一篇旧文,是在2005年底写的,当时公司为了利用充分发挥多显卡的性能优势,而SLI和CrossFile技术又有这样或者那样的限制,使用很不灵活,公司的想法是能否实现:只要用户的显卡有多块,不管是ATI的还是NVIDIA的,就可以充分利用起来,而且可以根据程序定制,指定某块显卡具体的工作内容,比如应用需要在一个复杂场景中播放电影,那么A卡只管播放电影,而B卡只管渲染场景等应用。经过研究和试验,虽然取得了一定的成果,但最终并没有完全达到公司的要求。事过4年,其中的技术或者结论可能已经时过境迁,成了昨日黄花。现把文章提供出来,全文一字未改,希望能给大家开发类似的应用提供一些有益的启迪和参考。
多显卡非SLI模式并行工作机理总结
自从接受多显卡并行工作机理探索任务后,经过一段时间的钻研和试验,已经在试验机上成功的实现了多显卡并行工作。现将试验的平台,试验方法和试验结果做一个总结,以指导后续的应用工作,并对将来可能进行的二次研发工作作个参考。
要实现多显卡并行工作,首先必须让操作系统在硬件层次上识别多个显卡。对windows系统而言,必须在“桌面”――“属性”――“设置”中选择对应的显卡,然后勾选“将windows桌面扩展到该监视器上”选项。因为默认情况下,每个显卡都会对应一个监视器的(即使该显卡没有配置监视器),这样该监视器所对应的显卡就会被激活。Windows系统的API才能获得并使用该显卡。
其次的任务就是在软件层面上使用该显卡了。对于当前的主流显卡(Nvidia和ATI显卡),显卡的驱动程序并没有提供单独对显卡进行设置和操作的API函数(Nvidia的显卡是通过nvcpl.dll动态库来提供检测和设置SLI模式的API的),因此,要对所使用的显卡直接进行设置是不可能的。必须另辟蹊径。在windows系统中,显卡和显示器在概念上是比较混淆的,所谓的Device Context在MSDN中有的时候说的是显卡,而有的时候又说的是显示器,更多的时候表述的是一个抽象的类似窗口的东西。使用API函数CreateDC可以直接指定显卡的ID来创建显卡DC,但是OpenGL中创建环境的命令不能直接使用这个DC来创建RC及其它环境。D3D虽然有API函数CreateDevice可以指定显卡序号来创建D3D的渲染DC,但是根据试验结果,当窗口在不同的显示器上显示时,其显卡的执行是不同的,也就是说,该函数指定的显卡创建环境并不能确定最终的渲染显卡,通过在OpenGL官网和其它网站发帖讨论,以及给Nvidia研发人员发E-mail求助,最终确认:Windows系统中,如果窗口显示在那个监视器中时,默认的就使用的是该监视器所接的显卡来完成窗口的绘制工作。根据这个机理,对于多显卡的应用环境而言,可以让OpenGL创建的窗口显示在对应的默认监视器上(没有监视器的显卡也可以设置监视器),则相当于间接的使用了该显卡。根据以上机理,创建了试验平台并完成了试验。
一:试验配置
硬件配置:华硕nForce4(SLI)主板、AMDAthlon(64)3200+、NvidiaGeforce128M6600GT(主卡位置)、NvidiaQuadro128MFX540(副卡位置)、双Philips170S5。
软件配置:windowsXPsp2、vc6、opengl2、ICDdriver81.95。
二:试验内容
做了两个测试demo,使用同样的ogl函数,VBO+显示列表+glsl的Shader渲染。窗口显示在不同的显示器上。每个demo有3个版本,为:普通渲染,PBUFFER渲染和FBO渲染。并对每个显卡都设置了同样的测试环境(关闭全屏反锯齿、关闭各项异性过滤,关闭垂直同步)。测试过程分单卡的3种模式、双卡单开的3种模式、双卡双开不同模式。
三:试验结果
试验结果直接体现在窗口的刷帧速度Fps上。Fps显示的结果包括:每帧渲染的时间+每帧消息处理的时间+每帧的窗口刷新时间(前后缓存交换时间)。窗口大小统一为800x600,Pbuffer和FBO的RTT大小也是800x600。载入的模型分为简单模型(4个模型+4张256x256tga图片)和复杂模型(26个模型+26张1024x1024图片)2类。其中,单显卡测试时,在系统启动时,bios中SLI选项设置:Single Card Mode。进入系统后,只能测试主显卡6600FT。对FX540进行单显卡测试是在双显卡测试模式下,在桌面属性中,选中监视器2,然后勾选“使用该设备做为主监视器”选项,并将监视器中的“将windows桌面扩展到该显示器”的勾去掉后测试的。双显卡测试时,在系统启动的时候,进入bios设置SLI选项设置为:Dual Card Mode。在双显卡模式下,启动后,如果不在桌面属性中设置“将windows桌面扩展到该显示器”选项,则其结果跟单卡模式下一样。双卡模式下,设置了桌面扩展后,测试了开1个demo和2个demo的各种情况,各项测试结果如下表:
单显卡渲染模式 | |||||||
单独打开Geforce6600GT测试demo |
单独打开QuadroFX540测试demo | ||||||
简单模型 |
复杂模型 |
简单模型 |
复杂模型 | ||||
普通 |
1360 |
普通 |
522 |
普通 |
1976 |
普通 |
378 |
Pbuffer |
640 |
Pbuffer |
328 |
Pbuffer |
460 |
Pbuffer |
216 |
FBO |
810 |
FBO |
400 |
FBO |
642 |
FBO |
262 |
双显卡渲染模式 | |||||||
单独打开Geforce6600GT测试demo |
单独打开QuadroFX540测试demo | ||||||
简单模型 |
复杂模型 |
简单模型 |
复杂模型 | ||||
普通 |
1358 |
普通 |
520 |
普通 |
980 |
普通 |
324 |
Pbuffer |
600 |
Pbuffer |
215 |
Pbuffer |
373 |
Pbuffer |
198 |
FBO |
695-807 |
FBO |
246-386 |
FBO |
340-383 |
FBO |
95-118 |
同时打开Geforce6600GT测试demo和QuadroFX540测试demo | |||||||
简单模型 |
复杂模型 | ||||||
6600GT |
Fps |
FX540 |
Fps |
6600GT |
Fps |
FX540 |
Fps |
普通 |
1320 |
普通 |
960 |
普通 |
518 |
普通 |
323 |
普通 |
718 |
Pbuffer |
356 |
普通 |
304 |
Pbuffer |
153 |
普通 |
790-1180 |
FBO |
215-377 |
普通 |
274-480 |
FBO |
91-117 |
Pbuffer |
372 |
普通 |
372 |
Pbuffer |
128 |
普通 |
128 |
Pbuffer |
332 |
Pbuffer |
166 |
Pbuffer |
123 |
Pbuffer |
82 |
Pbuffer |
332-234 |
FBO |
166-234 |
Pbuffer |
107-75 |
FBO |
54-70 |
FBO |
181-796 |
普通 |
545-588 |
FBO |
86-388 |
普通 |
171-233 |
FBO |
154-510 |
Pbuffer |
232-245 |
FBO |
78-246 |
Pbuffer |
108-124 |
FBO |
150-675 |
FBO |
227-304 |
FBO |
63-368 |
FBO |
63-95 |
四:结果分析
根据以上试验数据和试验现象,可以归纳出以下结果:
1> 单显卡模式下,FX540的普通渲染帧率达到1976,大大超过6600GT普通渲染的1360。双显卡模式下,FX540的普通渲染帧率大幅下降,只有980,与单显卡模式下的帧率相比,降低差不多一半。
2> 普通渲染测试demo中,6600GT在单显卡和双显卡模式下的帧率基本持平,其中,双demo打开时,FX540普通渲染没有影响它的帧率,FX540FBO渲染对帧率影响较小。FX540Pbuffer模式下,帧率大幅降低。超过了一半(1300-600)。
3> 双卡双demo测试下,只要有Pbuffer渲染的demo运行,则无论是6600GT还是FX540,帧率都有大幅下降,这是因为无论是主卡测试demo中的Pbuffer还是副卡测试程序的Pbuffer,其始终在副卡FX540上创建,并且不随窗口的移动而转换,显示的时候,双Pbuffer的创建和来回的数据传送消耗了大量的时间。
4> 只有在6600GT普通渲染-FX540普通渲染、6600GT普通渲染-FX540FBO渲染、6600GTFBO渲染-FX540普通渲染3种情况下,6600GT的帧率才和单卡模式下的帧率基本持平。
5> FBO渲染的demo初始打开时,其帧率都未能达到其应有的帧率,只有将窗口最小化或者从一个显示器移到另一个显示器再移回来后,其帧率才提高到稳定水平,初步估计,是因为FBO绑定的纹理未能及时的与其相应的FBO转移到同一张显卡上所致。
6> 对于Pbuffer渲染程序,无论是6600GT或者FX540的demo,只要窗口显示在副监视器上的话,则程序只能使用ESC退出,使用关闭窗口会出现wglMakeCurrent错误,反之,只要在主窗口上显示的话,则不会出现任何错误。初步判断,这个是driver的一个bug。
7> 可以肯定的说,对于不同的ogl程序,只要其窗口显示在不同的显卡上,则其所有的ogl命令都是在对应的显卡上执行的。但对于应用程序如何分配显存,比如纹理创建、VBO保存、Pbuffer和FBO的空间分配。则没法确定,这些都是在driver中实现的,没办法debug到driver内部的话,是没办法得到的。
五:试验结论
对于大多数的应用程序,如果能够在SLI模式下达到目的话,最好使用SLI模式,因为SLI模式在driver内部实现了对2个显卡的控制操作,对外部而言,相当于一个显卡。并且据Nvidia官方人员称,其帧率提高约为1.9倍(但同时在OpenGL官网上,也有Nvidia人员称,SLI只对“帧填充瓶颈”的应用程序有效,并非所有的应用程序性能都可以提高)。
对于必须单独控制显卡才能完成的应用程序,则在现阶段情况下,其应用范围受到限制,无论是主卡还是副卡,都不能使用Pbuffer,否则其主卡副卡的帧率都有大副下降,且规律性不强。其行为受显卡的driver控制,除非显卡driver公布了可以明确指定显卡的API函数,否则,研究失去价值。试想:如果其行为由显卡driver的研发人员根据某种规则分配的话,那么,因为其API未公开,其不会为这种行为负责,换言之,在driver升级了以后,其规则有可能改变。每次driver升级都有可能导致新的问题,研发成本太大。另一方面,如果其行为不是driver研发人员根据规则分配,而是随机的行为,则毫无规律可言,研发失去意义。从另一方面讲,不同的显卡厂商其driver的内部实现都不尽相同,如果不是遵循统一公开的API接口的话,根据某一类显卡实现的并行机制有可能在别的显卡上问题多多,应用范围受限。
六:试验总结
综上所述,鉴于目前研究的结果和研究的意义来看,本研究结果可以应用到受限的应用程序环境中,进一步的研究有待于项目的迫切需要和当前软硬件的进一步发展而定。当前情况下,继续研究下去的意义已经不大。
七:试验截图(部分)
1>主卡Pbuffer-副卡普通渲染
2>主卡普通-副卡Pbuffer
2005-12-7