我们的Web服务器需要在将结果发送到Web客户端之前将多个大型图像组合在一起。此过程对性能至关重要,因为服务器每小时可以收到数千个请求。
现在我们的解决方案从HD加载PNG文件(每个大约1MB)并将它们发送到视频卡,以便在GPU上完成合成。我们首先尝试使用XNA API公开的PNG解码器加载我们的图像。我们看到表现不太好。
要了解问题是从HD加载还是解码PNG,我们通过将文件加载到内存流中,然后将该内存流发送到.NET PNG解码器来修改它。使用XNA或使用System.Windows.Media.Imaging.PngBitmapDecoder类的性能差异并不重要。我们大致得到了相同的性能水平。
我们的基准测试显示以下表现结果:
总计:3680.50ms 100%
根据这些结果,我们看到解码PNG时最慢的部分。
所以我们想知道是否会有一个我们可以使用的PNG解码器,这将允许我们减少PNG解码时间。我们还考虑将图像保持在硬盘上不压缩,但是每个图像的大小为10MB而不是1MB,并且由于硬盘上存储了数万个这样的图像,因此无法存储它们。压缩。
编辑:更有用的信息:
答案 0 :(得分:6)
还有另一种选择。也就是说,您编写自己的基于GPU的PNG解码器。您可以使用OpenCL来相当有效地执行此操作(并使用可与OpenCL共享资源的OpenGL执行组合)。还可以交错传输和解码以获得最大吞吐量。如果这是您可以/想要追求的路线,我可以提供更多信息。
以下是与基于GPU的DEFLATE(和INFLATE)相关的一些资源。
希望这有帮助!
答案 1 :(得分:4)
你有没有尝试过以下两件事。
1)
多线程它,有几种方法可以做到这一点,但一种方法是“全进”方法。基本上完全生成X线程数量,用于完整过程。
2)
也许考虑让XX线程完成所有CPU工作,然后将其提供给GPU线程。
您的问题非常适合作为新用户,但有关Senario的一些信息可能有用吗? 我们是在实时谈论批量作业还是服务图片? 10k图片会改变吗?
硬件资源
您还应该考虑到您所拥有的硬件资源。
Normaly最便宜的两件事就是CPU电源和磁盘空间,所以如果你只有10k的图片可以轻易改变,那么将它们全部转换成一种更快速处理的格式可能就是这样。
多线程琐事
在进行多线程处理时要考虑的另一件事是,使用BellowNormal优先级的线程是非常聪明的。所以你不要让整个系统“滞后”。你必须尝试使用一定数量的线程,如果运气好,你可以获得接近100%的速度pr CORE增益,但这取决于你运行的硬件和代码。
我正式使用Environment.ProcessorCount来获取当前的CPU数量并从那里开始工作:)
答案 2 :(得分:2)
你有多个选项
提高解码过程的性能
你可以实现另一个更快的png解码器 (libpng是一个可能更快的标准库) 您可以切换到使用更简单/更快的可解码压缩的另一种图片格式
并行化
使用.NET并行处理功能进行并发解码。解码可能是单线程的,因此如果您在多核计算机上运行,这可能会有所帮助
将文件解压缩但存储在压缩设备上
例如压缩文件夹甚至是sandforce ssd。 这仍然会压缩但不同并且减轻了其他软件的负担。我不确定这会有什么帮助,只会尝试这个作为最后的手段。
答案 3 :(得分:2)
我写了一个纯C#PNG编码器/解码器(PngCs),你可能想看看。 但我非常怀疑它会有更好的速度[*],它没有高度优化,而是试图最小化处理大图像的内存使用(它按顺序逐行编码/解码)。但也许它可以作为样板来插入一些更好的压缩/解压缩实现。正如我所看到的,速度瓶颈是zlib(inflater / deflater),它(与Java相反)并没有在C#本地实现 - 我使用了SharpZipLib库,使用纯C#托管代码;这不是非常有效。
然而,我有点惊讶,在你的测试中,解码比编码慢得多。这对我来说似乎很奇怪,因为在大多数压缩算法中(可能在所有;并且肯定在zlib中)编码比解码更加计算机密集。 你确定吗? (例如,这个speedtest读取和写入5000x5000 RGB8图像(不是非常可压缩,磁盘上大约20MB)给了我大约4.5秒的写入时间和1.5秒的读取时间。除了纯PNG解码外,还有其他因素吗?[*]更新:有多个优化的新版本(自1.1.14开始);如果你可以使用.Net 4.5,特别是它应该提供更好的解码速度。