Décodeur PNG le plus rapide for.NET

notre serveur Web doit traiter plusieurs compositions de grandes images ensemble avant d'envoyer les résultats aux clients web. Ce processus est critique car le serveur peut recevoir plusieurs milliers de requêtes par heure.

en ce moment notre solution charge des fichiers PNG (environ 1MB chacun) à partir de la HD et les envoie sur la carte vidéo afin que la composition soit faite sur le GPU. Nous avons d'abord essayé de charger nos images en utilisant le décodeur PNG exposé par L'API XNA. Nous avons vu les performances n'était pas trop bon.

pour comprendre si le problème était le chargement à partir de la HD ou le décodage du PNG, nous avons modifié cela en chargeant le fichier dans un flux de mémoire, puis en envoyant ce flux de mémoire au décodeur .NET PNG. La différence de performance en utilisant XNA ou en utilisant le système.Windows.Média.L'imagerie.La classe PngBitmapDecoder n'est pas significative. Nous obtenons grosso modo les mêmes niveaux de performance.

nos benchmarks montrent les performances suivantes résultats:

  • charger les images à partir du disque: 37.76 ms 1%
  • décoder PNGs: 2816.97 ms 77%
  • Charger les images sur le Matériel Vidéo: 196.67 ms 5%
  • Composition: 87.80 ms 2%
  • Obtenir la composition de Matériel Vidéo: 166.21 ms 5%
  • Encoder vers PNG: 318,13 ms 9%
  • stocker sur disque: 3,96 ms 0%
  • Nettoyage: 53.00 ms 1%

Total: 3680.50 ms 100%

à Partir de ces résultats nous voyons que les parties les plus lentes sont lors du décodage de la PNG.

nous nous demandons donc s'il n'y aurait pas un décodeur PNG que nous pourrions utiliser pour réduire le temps de décodage PNG. Nous avons également envisagé de garder les images non compressées sur le disque dur, mais alors chaque image serait de 10Mo de taille au lieu de 1Mo et comme il y a plusieurs dizaines de milliers de ces images stockées sur le disque dur, il n'est pas possible de les stocker toutes sans compression.

modifier: Plus d'informations utiles:

  • le benchmark simule le chargement de 20 images PNG et leur assemblage. Cela correspondra à peu près au type de demandes que nous obtiendrons dans l'environnement de production.
  • chaque image utilisée dans la composition est de taille 1600x1600.
  • la solution impliquera jusqu'à 10 serveurs équilibrés de charge comme celui dont nous discutons ici. Donc, un effort supplémentaire de développement de logiciel pourrait valoir les économies sur le matériel coût.
  • la mise en cache des images source décodées est quelque chose que nous envisageons, mais chaque composition sera probablement faite avec des images source complètement différentes, donc les pertes de cache seront élevées et le gain de performance, faible.
  • les benchmarks ont été faits avec une carte vidéo merdique, donc on peut s'attendre à ce que le décodage PNG soit encore plus un goulot de performance en utilisant une carte vidéo décente.
26
demandé sur sboisse 2012-07-03 18:35:54

4 réponses

Il y a une autre option. C'est-à-dire que vous écrivez votre propre décodeur PNG basé sur GPU. Vous pouvez utiliser OpenCL pour effectuer cette opération assez efficacement (et effectuer votre composition en utilisant OpenGL qui peut partager des ressources avec OpenCL). Il est également possible d'intercaler transfert et décodage pour un débit maximum. Si c'est un itinéraire que vous pouvez/voulez poursuivre, je peux fournir plus d'informations.

voici quelques ressources sur le DÉFLAT basé sur le GPU (et GONFLER.)

  1. Accélérer la compression sans perte avec Gpu
  2. gpu-bloc de compression utiliser CUDA sur Google code.
  3. Floating point de compression de données à 75 Go/s sur un GPU - notez que ceci n'utilise pas de gonfler / dégonfler mais un nouveau schéma de compression/décompression parallèle qui est plus favorable aux GPU.

Espérons que cette aide!

6
répondu Ani 2012-07-03 16:19:00

Avez-vous essayé les 2 choses.

1)

Multi thread it, il y a plusieurs façons de le faire, mais l'une serait une méthode "all in". Basicly spawn x quantité de threads, pour le proccess complet.

2)

Peut-être envisager D'avoir XX thread faire tout le travail CPU, et ensuite l'alimenter au fil GPU.

votre question est très bien formulée pour être un nouvel utilisateur, mais certaines informations sur le senario pourrait être utiles? Parlons-nous d'un travail par lot ou de photos de service en temps réel? Est-ce que les images 10k changent?

ressources Matérielles

Vous devez également tenir compte des ressources matérielles dont vous disposez. Normalement, les 2 choses les moins chères sont la puissance CPU et l'espace disque, donc si vous avez seulement 10k images qui changent rapidement, puis les convertir tous dans un format qui plus rapide à gérer pourrait être le moyen de aller.



trivial multi thread

Une autre chose à considérer lors de la multithreading, est que son normalement intelligent pour faire les fils dans priorité BellowNormal.Donc vous ne faites pas tout le système "lag". Vous devez expérimenter un peu avec la quantité de threads à utiliser, si votre chance vous pouvez obtenir près de 100% de gain de vitesse pr CORE, mais cela dépend beaucoup du matériel et du code que vous exécutez.

j'utilise normalement Environnement.ProcessorCount pour obtenir le CPU actuel comte et de travailler à partir de là :)

4
répondu EKS 2012-07-03 15:30:22

Vous avez plusieurs options

  • Améliorer la performance du processus de décodage

    vous pouvez implémenter un autre décodeur png plus rapide (libpng est une bibliothèque standard qui pourrait être plus rapide) Vous pouvez passer à un autre format d'image qui utilise une compression plus simple/plus rapide

  • Paralléliser

    utilisez les capacités de traitement en parallèle de .NET pour le décodage simultané. Il est probable que le décodage soit en clair cela pourrait vous aider si vous utilisez des machines multicore

  • stocker les fichiers non compressés mais sur un périphérique qui compresse

    Par exemple un dossier compressé ou même un ssd sandforce. Cela va encore compresser mais différemment et surcharger d'autres logiciels avec la décompression. Je ne suis pas sûr que cela aidera vraiment et je ne tenterai cela qu'en dernier recours.

2
répondu IvoTops 2012-07-03 15:44:51

j'ai écrit un pur c# PNG coder / decoder ( PngCs ) , vous pouvez lui donner un look. Mais je doute fort qu'il ait une meilleure permance de vitesse [*], il n'est pas très optimisé, il essaie plutôt de minimiser l'utilisation de la mémoire pour traiter d'énormes images (il encode/décode séquentiellement, ligne par ligne). Mais peut-être qu'il vous Sert de boilerplate pour brancher une meilleure implémentation de compression/décompression. Comme je le vois, le goulot d'étranglement de la vitesse est zlib( gonflant / déflater), qui (contrairement à Java) n'est pas implémenté nativement en C# -j'ai utilisé une bibliothèque SharpZipLib, avec du code géré pur C#; cela ne peut pas être très efficace.

je suis un peu surpris, cependant, que dans vos tests le décodage était tellement plus lent que l'encodage. Cela me semble étrange, parce que, dans la plupart des algorithmes de compression (peut-être en tout; et sûrement en zlib) l'encodage est beaucoup plus intensif sur ordinateur que le décodage. Êtes-vous sûr de cela? (Par exemple, speedtest lire et écrit 5000x5000 images RGB8 (pas très compressible, environ 20 Mo sur disque) me donne environ 4,5 secondes pour l'écriture et 1,5 secondes pour la lecture). Peut-être y a-t-il un autre facteur à part le décodage PNG pur?

[*] mise à jour: nouvelles versions (depuis 1.1.14) qui ont plusieurs optimisations; si vous pouvez utiliser .Net 4.5, spécialement, il devrait fournir une meilleure vitesse de décodage.

2
répondu leonbloy 2013-02-28 22:50:01