- UID
- 1
- 精华
- 积分
- 76361
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
世上常有尴尬事:
·使用了GPU加速,结果性能还不如CPU处理的(gpujpeg, libjpeg-turbo);
·使用了多线程加速,结果CPU使用率上去了但性能却还不如单线程的(7z);
·使用了SIMD指令集加速,结果性能还不如FPU的浮点处理(这里我就不说了)。
·使用了非阻塞套接字,然后无任务状态下CPU使用率100%的……
关于第一条:本想着大量处理JPG图像将其解压为BMP,然后绘制到窗口上的。一开始用了gpujpeg,编译需要装CUDA,装上调试,1000张1080p的JPG图像,每张200K左右,解压总共需要8秒。作为对比,传统libjpeg的解压速度是16秒解压完;用Windows的COM组件解压,则需要20秒。
本来觉得8秒已经够快了吧,但发现用libjpeg-turbo则更快,只需要5秒。后面仔细检查了情况,发现是如下原因:
jpg格式的压缩为霍夫曼压缩+DFT压缩。它是先将原图进行DFT处理,切去频率大的部分,然后再把得到的数据用霍夫曼树进行压缩(类似于zip那样的算法),单张图霍夫曼压缩的部分只能用CPU解,因为不能并行处理;而DFT压缩的解压虽然用GPU或许会更快,但你要用GPU处理图像,你必须先把图像上传到显存,处理完之后,你还要再把它从显存上下载下来。总体下来就慢了。
libjpeg-turbo用SIMD指令集进行DFT变换,不需要将JPG文件的内容上传到显存,也不需要从显存下载处理好的图像。SIMD指令集的加速效果还是十分显著的,作为对比的FPU处理方式就慢得多了。从libjpeg与libjpeg-turbo的解压速度的直观比较上来看,SIMD指令集似乎是比FPU指令集快4倍的(这也是预期的效果)。
关于第二条:用7z压缩一个超级大的玩意儿,比如一个30GB的BDMV镜像,这玩意儿本身就很难被压缩,然后我弄了4个线程去压缩它,压缩选项是极限压缩,固实设定是完全固实,字典大小、单词大小被我设置到最大,然后压缩快结束的时候,内存占了快31G,整体压缩比98%,相当于没压。整体花费了多少时间我记不太清楚,但总之那会儿我电脑都没得玩,只能躺床睡觉。第二天,我用7z压缩一个40GB的BDMV的镜像,压缩比设置还是一样,但线程被我调到单线程。于是内存占用差不多5G左右,最后压缩完,整体上,感觉和上次那个30GB的耗时差不多……
或许各种不定因素很多吧,但其实我觉得压缩文件本身就不是能进行并行处理的事情,尤其是非常在意压缩比的情况(其实压缩BDMV不需要在意压缩比,但我习惯了设置那样的压缩比来压缩)。它霍夫曼数算法并没有什么能进行并行处理的地方,就算是给字典添加单词,同时对字典操作的线程也只能有一个,而收集单词的时候,你有可能遇到信息熵很大的文件,那就每个没遇到的数据都是单词,多线程处理的话似乎意义非常小。只有在大量压缩小文件的时候,我觉得多线程处理才会有加速效果。
关于第三条:这是某人打算用它来实现圆周率10000位的运算……好了,具体我不说了,大家都懂的。计算圆周率根本用不着浮点数运算。
关于第四条:咳咳……这是我自己的锅。其实我写的那个玩意儿可以保证在访问数据量特别大、同时进行几万个长连接的时候也能做到不搞爆堆并且都处理得过来。但为了实现这种效果,我不让它切时间片,它要是切时间片了,可能就会影响效率……结果就是在闲置的时候它也完全不usleep(0)结局可想而知。
其实应该先判断有没有任务要做,都没有了,那就usleep()。不能滥用usleep()也不能不用,根据不同的系统,要讲究不同的优化方式。尤其是Windows的时间片是1毫秒,这点其实更应该尽量多发挥单线程的优势——切换上下文频率低,CPU负担小。
|
|