
De nos jours, lorsque les réseaux de neurones labourent les étendues du Big Data et que l'intelligence artificielle se demande s'il est rentable pour lui de se faire payer pour son travail dans Bitcoin, la tâche que j'ai eue de trouver la bibliothèque multiplateforme ouverte la plus rapide pour télécharger, enregistrer et transcoder des fichiers graphiques ressemblait à un véritable anachronisme . Mais en fait, cette tâche est plus pertinente que jamais - pour toutes les technologies de vision par ordinateur et d'apprentissage automatique, des gigaoctets d'images doivent être téléchargés, et parfois les données intermédiaires doivent être enregistrées sous forme d'images. Il est donc très souhaitable de le faire de la manière la plus rapide. Dans cet article, nous trouverons la bibliothèque que nous recherchons et, plus important encore, nous traiterons d'un produit très utile qui simplifie considérablement les tâches similaires et bien d'autres - Google Benchmark.
Ainsi, l'énoncé exact du problème indique: dans l'application, les fichiers jpeg et tiff avec une profondeur de couleur de 24 et 8 bits, ainsi que le bmp 32 bits sont chargés en mémoire. Les tailles d'image vont de minuscule (32x32 pixels) à grande, avec une résolution de 15K. Au cours du processus, les fichiers sont modifiés, après quoi ils doivent être enregistrés sur le disque dans les formats spécifiés. Et cela devrait être fait par une bibliothèque open source multiplateforme qui offre des performances maximales sur les processeurs Intel modernes avec la prise en charge des instructions vectorielles AVX2. La bibliothèque prend également en charge la bibliothèque de formats de texture compressée DirectX DXT1. Le
composant d'imagerie Windows est considéré comme la référence en matière de performances - le cadre standard pour travailler avec des images sur Windows, c'est-à-dire que vous devez trouver une bibliothèque qui fonctionne sur un pied d'égalité ou plus rapidement que WIC.
Mais l'exigence la plus importante est qu'une solution soit nécessaire dès maintenant, mais mieux hier.
Rencontrez les bibliothèques pour travailler avec bmp, tiff, jpeg
La solution commence par une étape évidente et simple, bien que pas très rapide - une étude approfondie de
Wikileaks github ,
stackoverflow et autres google à la recherche de candidats appropriés pour le rôle de la bibliothèque souhaitée. Il y en avait peu:
- FreeImage . Un shell sur les fameuses librairies LibJPEG, LibPNG, LibTIFF. Le support DXT1 est présent via le plugin. L'inconvénient est que la qualité de l'enregistrement jpeg dans l'API est définie de manière trop discrète - 100, 75,50 et 25%. Pour modifier ce paramètre, vous devrez comprendre et modifier le code. Le projet est vivant et en développement - la dernière version 3.18.0 est sortie le 31 juillet 2018. L'assemblage sous Windows est trivial, tous les composants sont construits automatiquement.
- Cimg Il s'agit d'un wrapper de fichier d'en-tête C ++ sur un ancien paquet d'
artefacts ImageMagick . Le paquet nécessite une build-installation séparée, il est également possible de l'utiliser directement, en contournant Cimg. Il a beaucoup de possibilités pour travailler avec des images: filtres, transformations, définition de la morphologie, etc. Prend en charge HDR, ne prend pas en charge DXT1. - DevIL ( Bibliothèque d'images du développeur ). Une bibliothèque C de style OpenGL très simple. Il contient un shell sur LibJPEG, LibPNG, LibTIFF, mais possède également de nombreuses fonctionnalités intégrées, prend également en charge de nombreux formats d'image, y compris DXT1. Pour l'assemblage, utilisez CMake. La plupart des dépendances, y compris LibJPEG, LibPNG, LibTIFF, ne sont pas incluses dans DevIL et doivent être téléchargées et compilées séparément séparément. La dernière mise à jour de DevIL concernant le système de construction est datée du 01/01/2017, et la précédente s'est généralement produite en 2014, donc s'il y a des problèmes avec la bibliothèque, il peut y avoir des problèmes avec leur solution.
- OpenImageIO . Il se positionne comme un outil de développement de logiciels professionnels pour travailler avec des images. Il prend en charge sous forme de plug-ins de travail avec de nombreux formats photo exotiques et même vidéo. Build for Windows nécessite Boost et Qt 4. précompilés. Il n'y a pas de version assemblée prête à l'emploi pour les tests.
- Boost GIL (Generic Image Library) Boost et c'est tout. Mais pas tous. Cette bibliothèque contient également un wrapper sur LibJPEG, LibPNG et LibTIFF.
- SDL_image 2.0 Utilisé avec la bibliothèque SDL et, vous allez en rire, mais contient également un shell sur LibJPEG, LibPNG et LibTIFF.
Toutes les bibliothèques trouvées ont été compilées sous Windows en utilisant le niveau maximal d'optimisation du compilateur Visual Studio et du commutateur / arch: AVX2.
Il en va de même pour les bibliothèques LibJPEG, LibPNG et LibTIFF, afin d'accélérer le travail extrait du nouveau package de
bibliothèque OpenCV .
Rencontrez le Google Benchmark
La prochaine étape de la solution est également évidente: la création d'un point de référence pour comparer les performances des bibliothèques trouvées et l'utilisation de la bibliothèque de micro-analyse de Google Benchmark, largement connue dans les cercles étroits, la rendent simple et rapide.
Google Benchmark peut mesurer avec précision les performances des morceaux de code que vous avez insérés dans le corps du cycle C ++ 11.
static void BM_foo1(benchmark::State& state) {
dans les fonctions enregistrées comme référence
Et exécutez-les:
BENCHMARK_MAIN();
Ensuite, émettez un rapport au format spécifié - sortie console, json, csv.
Le rapport contiendra des données sur le système d'exécution (processeur, configuration du cache), le temps de fonctionnement global total de chacune des fonctions mesurées, ainsi que le temps nécessaire au processeur. Ces temps diffèrent généralement - le premier, par exemple, inclut un délai de lecture / écriture, et le second pour les tests de référence multithread est la somme du temps de fonctionnement de tous les cœurs.
Le dernier paramètre affiché par Google benchmark est le nombre d'itérations effectuées pour la fonction, qui est nécessaire pour une mesure précise statistiquement correcte de son temps de fonctionnement. Le système le sélectionne vous-même, automatiquement, en effectuant des mesures préliminaires.
Qu'est-ce qu'une «mesure précise» du temps d'exécution? Vous pouvez rédiger des dissertations sur ce sujet, mais dans ce cas il suffit de dire que:
- Par défaut, la mesure est en grappes de processeurs, c'est-à-dire que l'ordre théorique de précision est exactement le suivant. La sortie par défaut est en nanosecondes;
- les résultats de tous les tests que j'ai vus sont très stables d'un lancement à l'autre;
- selon mes données de renseignement, le benchmark de Google est utilisé et entièrement approuvé par ses résultats par les développeurs de logiciels informatiques embarqués de l'une des plus grandes entreprises automobiles du monde. Nous allons donc croire.
La seule chose à laquelle il faut faire attention: Google benchmark ne fournit pas de "nettoyage" du cache entre les débuts des itérations de référence. Si nécessaire, vous devez vous en occuper vous-même.
Mais le benchmark de Google peut faire beaucoup d'autres choses:
- calculer la complexité asymptotique de l'algorithme (O);
- travailler correctement avec des benchmarks multi-threads, mesurer leur durée non pas en ticks du processeur, mais en mode «temps réel» (horloge murale);
- utiliser votre propre fonction de mesure du temps "manuelle", qui peut être utile, par exemple, pour mesurer le travail sur le GPU;
- définir automatiquement des repères avec différents ensembles d'arguments pour un corps donné de la fonction mesurée;
- montrer la valeur moyenne, la médiane et l'écart type pour plusieurs démarrages de l'indice de référence;
- Définissez vos propres compteurs et balises qui seront reflétés dans le rapport de référence Google.
Le benchmark Google est téléchargé à partir
du référentiel github , assemblé pour la plate-forme appropriée à l'aide de Cmake (l'assembly Visual Studio est disponible pour Windows), la bibliothèque résultante sera liée à votre projet (dans le cas de Windows, un lien avec la bibliothèque shlwapi sera également requis), le fichier d'en-tête du benchmark sera ajouté à votre code .h, après quoi tout fonctionne comme décrit ci-dessus.
Si cela ne fonctionne pas, le seul endroit, à part le
site déjà indiqué , où vous pouvez obtenir au moins des informations et de l'aide sur le benchmark Google est un
forum spécialisé sur les produits .
Dans notre cas, tout a fonctionné sans problème. Après avoir communiqué avec les clients, 4 benchmarks ont été définis, qui se chargent et se sauvegardent sous un nom différent:
- Fichier jpeg 8 bits avec une résolution de 15k
- Fichier jpeg 24 bits avec une résolution de 15k
- Fichier tiff 24 bits avec une résolution de 15k
- Fichier bmp 32 bits avec une résolution de 32x32
Rencontrez les résultats
Il était initialement prévu que toutes les bibliothèques trouvées, c'est-à-dire FreeImage, Cimg, DevIL, OpenImageIO, Boost GIL et SDL_image 2.0, participeront aux tests de comparaison avec le composant d'imagerie Windows (WIC). Mais les trois dernières bibliothèques, en fonction de "monstres" tels que Boost et SDL, ont été invitées par les clients à partir en réserve en cas d'urgence, si la bibliothèque souhaitée n'est pas trouvée parmi les trois premières. Et, heureusement, elle a été retrouvée. Mais pas immédiatement.
Ce qui suit est un rapport généré par Google benchmark, qui montre que:
- FreeImage complètement avec un score d'écrasement perd le WIC dans tous les tests, donc il ne peut plus être pris en compte.
- Cimg perd WIC proprement partout, sauf pour le chargement de tiff, où il est légèrement (moins de 5%) plus rapide. Hélas, il devra également être supprimé. De plus, cela s'applique à l'utilisation directe du package ImageMagick.
Reste la bibliothèque DevIL. Il montre d'excellents résultats en cas de chargement de bmp et de tiff (3 et 2,8 fois plus élevé que WIC!), Jpeg noir et blanc (1,75x meilleur que WIC), mais il ralentit un peu lors du chargement d'un jpeg 24 bits régulier - il le fait par 3 % plus lent que WIC.
08/15/18 11:15:44 Running c:\WIC\WIC_test\Release\WIC_test.exe Run on (8 X 4008 MHz CPU s) CPU Caches: L1 Data 32K (x4) L1 Instruction 32K (x4) L2 Unified 262K (x4) L3 Unified 8388K (x1) |
Benchmark | Time | CPU | Iterations |
BM_WIC8jpeg | 72 ms | 70 ms | 11 |
BM_cimg8jpeg | 562 ms | 52 ms | 10 |
BM_FreeImage8jpeg | 147 ms | 144 ms | 5 |
BM_devIL8jpeg | 41 ms | 41 ms | 17 |
|
BM_WIC24jpeg | 266 ms | 260 ms | 3 |
BM_cimg24jpeg | 656 ms | 128 ms | 6 |
BM_FreeImage24jpeg | 594 ms | 594 ms | 1 |
BM_devIL24jpeg | 276 ms | 276 ms | 3 |
|
BM_WIC24tiff | 844 ms | 844 ms | 1 |
BM_cimg24tiff | 808 ms | 131 ms | 5 |
BM_FreeImage24tiff | 953 ms | 938 ms | 1 |
BM_devIL24tiff | 305 ms | 305 ms | 2 |
|
BM_WIC32 | 3 ms | 3 ms | 236 |
BM_cimg32 | 71 ms | 7 ms | 90 |
BM_FreeImage32 | 6 ms | 5 ms | 112 |
BM_devIL32 | 1 ms | 1 ms | 747 |
Bien sûr, DevIL pourrait également être rejeté à ce stade, mais ici une autre bibliothèque apparaît dans le cadre -
Libjpeg-turbo .
Sa sortie peut être facilement satisfaite par des applaudissements -
Libjpeg-turbo est une bibliothèque multiplateforme qui implémente entièrement la fonctionnalité libjpeg (API) et ajoute sa propre fonctionnalité (par exemple, en travaillant avec des tampons 32 bits). Dans le même temps, pour l'architecture x86, Libjpeg-turbo utilise activement les instructions vectorielles (SSE2, AVX2) et, selon ses créateurs, est 2 à 6 fois plus rapide que libjpeg (!)
Par conséquent, l'étape suivante consiste à créer DevIL avec Libjpeg-turbo au lieu de libjpeg. Libjpeg-turbo avec l'aide de CMake construit Visual Studio sans problème, puis presque immédiatement (avec le remplacement du seul #define, qui détermine la version de libjpeg dans le fichier d'en-tête DevIL) commence à fonctionner dans le cadre de DevIL.
Par conséquent, le rapport de référence Google ressemble à ceci:
Benchmark | Time | CPU | Iterations |
BM_WIC8jpeg | 72 ms | 68 ms | 9 |
BM_cimg8jpeg | 565 ms | 39 ms | 10 |
BM_FreeImage8jpeg | 148 ms | 141 ms | 5 |
BM_devIL8jpeg | 31 ms | 31 ms | 24 |
|
BM_WIC24jpeg | 269 ms | 266 ms | 2 |
BM_cimg24jpeg | 675 ms | 131 ms | 5 |
BM_FreeImage24jpeg | 604 ms | 594 ms | 1 |
BM_devIL24jpeg | 149 ms | 150 ms | 5 |
|
BM_WIC24tiff | 833 ms | 828 ms | 1 |
BM_cimg24tiff | 785 ms | 138 ms | 5 |
BM_FreeImage24tiff | 943 ms | 938 ms | 1 |
BM_devIL24tiff | 318 ms | 320 ms | 2 |
|
BM_WIC32 | 4 ms | 3 ms | 236 |
BM_cimg32 | 74 ms | 8 ms | 56 |
BM_FreeImage32 | 6 ms | 5 ms | 100 |
BM_devIL32 | 1 ms | 1 ms | 747 |
Bien sûr, les améliorations de performances avec jpeg ne sont même pas doubles par rapport à libjpeg, mais cela devrait être le cas - car la supériorité de vitesse ne s'applique qu'au codage / décodage jpeg, et le test inclut les frais généraux de lecture / écriture d'un fichier.
Mais on peut voir qu'en moyenne, DevIL est plus rapide que WIC dans le cas de jpeg 8 bits
2,3 fois, jpeg 24 bits
1,8 fois, tiff 24 bits -
2,7 fois, bmp 32 bits -
3,5 fois.
Le problème est résolu. Trois jours ouvrables d'été avant les vacances ont été entièrement consacrés à la décision. Bien sûr, s'il y en avait un peu plus, il serait possible qu'il y ait une bibliothèque avec des résultats encore plus impressionnants, et si c'était beaucoup plus, alors j'écrirais peut-être la bibliothèque que je cherchais moi-même.
Mais même ce qui est impressionnant. Par conséquent, si vous recherchez une bibliothèque multiplateforme pour travailler avec des fichiers graphiques qui est rapide et facile dans tous les sens, alors faites attention à
DevIL , et si vous avez besoin de faire rapidement et avec précision des mesures comparatives du code, alors la
référence Google est à votre service.