适用于.NET的最快PNG解码器

在将结果发送到Web客户端之前,我们的Web服务器需要将大量图像组合在一起。 此过程对性能至关重要,因为服务器每小时可以接收数千个请求。

现在我们的解决方案从HD加载PNG文件(每个大约1MB)并将它们发送到video卡,以便在GPU上完成合成。 我们首先尝试使用XNA API公开的PNG解码器加载我们的图像。 我们看到表现不太好。

要了解问题是从HD加载还是解码PNG,我们通过在内存流中加载文件,然后将该内存流发送到.NET PNG解码器来修改它。 使用XNA或使用System.Windows.Media.Imaging.PngBitmapDecoder类的性能差异并不重要。 我们大致得到了相同的性能水平。

我们的基准测试显示以下性能结果:

  • 从磁盘加载图像:37.76ms 1%
  • 解码PNG:2816.97ms 77%
  • 在video硬件上加载图像:196.67ms 5%
  • 成分:87.80ms 2%
  • 从video硬件获取作曲结果:166.21ms 5%
  • 编码为PNG:318.13ms 9%
  • 存储到磁盘:3.96ms 0%
  • 清理:53.00ms 1%

总计:3680.50ms 100%

从这些结果中我们看到最慢的部分是解码PNG时。

所以我们想知道是否会有我们可以使用的PNG解码器,这将允许我们减少PNG解码时间。 我们还考虑将图像保持在硬盘上不压缩,但是每个图像的大小为10MB而不是1MB,并且由于硬盘上存储了数万个这样的图像,因此无法存储它们。压缩。

编辑:更有用的信息:

  • 基准测试模拟加载20个PNG图像并将它们合成在一起。 这大致对应于我们将在生产环境中获得的请求类型。
  • 组合物中使用的每个图像的尺寸为1600×1600。
  • 该解决方案将涉及多达10个负载均衡的服务器,就像我们在这里讨论的那样。 因此额外的软件开发工作可能值得节省硬件成本。
  • 我们正在考虑缓存解码的源图像,但每种组合很可能使用完全不同的源图像完成,因此缓存未命中率高,性能提升低。
  • 基准测试是用一个糟糕的video卡完成的,所以我们可以期待使用体面的video卡将PNG解码更加成为性能瓶颈。

还有另一种选择。 也就是说,你编写自己的基于GPU的PNG解码器。 您可以使用OpenCL来相当有效地执行此操作(并使用可与OpenCL共享资源的OpenGL执行组合)。 还可以交错传输和解码以获得最大吞吐量。 如果这是您可以/想要追求的路线,我可以提供更多信息。

以下是与基于GPU的DEFLATE(和INFLATE)相关的一些资源。

  1. 使用GPU加速无损压缩
  2. 在Google代码上使用CUDA进行gpu-block-compression 。
  3. GPU上的浮点数据压缩速度为75 Gb / s – 请注意,这不是使用INFLATE / DEFLATE,而是一种新的并行压缩/解压缩方案,它更适合GPU。

希望这可以帮助!

你有没有尝试过以下两件事。

1)
multithreading吧,有几种方法可以做到这一点,但其中一种方法是“全进”方法。 基本上完全生成X线程数量,用于完整进程。

2)
也许考虑让XX线程完成所有CPU工作,然后将其提供给GPU线程。

您的问题非常适合作为新用户,但有关Senario的一些信息可能有用吗? 我们是在实时谈论批量作业还是服务图片? 10k图片会改变吗?

硬件资源
您还应该考虑到您所拥有的硬件资源。 通常,2个最便宜的东西是CPU功率和磁盘空间,所以如果你只有10k的图片可以轻易改变,那么将它们全部转换为更快速处理的格式可能是最佳选择。

multithreading琐事
在进行multithreading处理时要考虑的另一件事是,使用BellowNormal优先级的线程非常聪明。所以你不要让整个系统“滞后”。 你必须尝试使用​​一定数量的线程,如果运气好,你可以获得接近100%的速度pr CORE,但这取决于你运行的硬件和代码。

我正式使用Environment.ProcessorCount来获取当前的CPU数量并从那里开始工作:)

你有多种选择

  • 提高解码过程的性能

    您可以实现另一个更快的png解码器(libpng是一个可能更快的标准库)您可以切换到使用更简单/更快的可解码压缩的另一种图片格式

  • 并行

    使用.NET并行处理function进行并发解码。 解码可能是单线程的,因此如果您在多核计算机上运行,​​这可能会有所帮助

  • 将文件未压缩存储在压缩的设备上

    例如压缩文件夹甚至是sandforce ssd。 这仍然会压缩但不同并且减轻了其他软件的负担。 我不确定这会有什么帮助,只会尝试这个作为最后的手段。

我写了一个纯C#PNG编码器/解码器( PngCs ),你可能想看一看。 但我非常怀疑它会有更好的速度[*],它没有高度优化,而是试图最小化处理大图像的内存使用(它按顺序逐行编码/解码)。 但也许它可以作为一个样板来插入一些更好的压缩/解压缩实现。 正如我所看到的,速度瓶颈是zlib(inflater / deflater),它(与Java相反)在C#中没有本地实现 – 我使用的是SharpZipLib库,带有纯C#托管代码; 这不是非常有效。

然而,我有点惊讶,在你的测试中,解码比编码慢得多。 这对我来说似乎很奇怪,因为在大多数压缩算法中(可能在所有;并且肯定在zlib中)编码比解码更加计算机密集。 你确定吗? (例如,这个读取和写入5000×5000 RGB8图像的速度测试(不是非常可压缩,磁盘上大约20MB)给了我大约4.5秒的写入时间和1.5秒的读取时间。 除了纯PNG解码外,还有其他因素吗?

[*]更新:有多个优化的新版本(自1.1.14起); 如果你可以使用.Net 4.5,特别是它应该提供更好的解码速度。