Optimisation algorithme d'érosion - C++ - Programmation
Marsh Posté le 21-11-2008 à 15:41:39
Déjà, tu pourrais peut-être multithreader le traitement non !? Chaque thread traite une image, et donc si multi-core ou autre, le traitement dans son ensemble peut-être largement accéléré !?
Marsh Posté le 21-11-2008 à 16:19:27
stop, stop Stop.
Avant d'aller plus loin, il faut optimiser ton algo pr etre cache friendly, ce qui represente des gains de l'ordre de 5à 10.
Donc, faut maximiser la localité spatiale en découpant ton image en bloc carré de taille approximativement égale à celle d'un bloc de cache line (genre 32x32 ou 16x16) et appliquer ton algo dessus.
En gros tu te retrouve avec 4 nid de boucle : un sur les tuile en x, en y et pour chaque tuile en x et y.
Aprés, l'accès des tableaux 2D est mieux si ton tableau est 2D au sens des NRC, ce que ne supporte pas forcement shared_array. J'ai deja poster 5 fois le code, je te laisse faire la recherche.
Ensuite, vectorise en utilisant SSE2
La déjà tu devrais avoir gagner en 10 et 40.
Si ca va pas assez vite , alors oui : boost::thread.
PS :aussi, on evite d'allouer de la mémoire dans les fonctions de calcul On passe la sortie en paramètre references
PS2 : factorise tes calculs d'adresse aussi
Marsh Posté le 21-11-2008 à 22:40:50
Okay, super, je vais aller voir tout ça.
Merci
Marsh Posté le 22-11-2008 à 02:34:49
Joel F a écrit : stop, stop Stop. |
Avant d'aller aussi là, on en revient à la définition des fonctions Height et Width, est-ce inliné ou pas, et surtout est-ce que ça va être relu à chaque appel ou pas.
Et surtout la traditionnelle histoire sur la boucleavec gcc, est-ce qu'il va optimisé le j*h ou bien est-ce qu'il va falloir préférer du j += h; ...
ma question bonus ça serait: est-ce que si on passe sur du stockage bit à bit on peut y gagner en localité (et bien déroulant les tests/sets des 8 bits) ou bien est-ce que les opérations sur les bits sont plus lentes et mieux vaut lire un bon vieil octet ? t'as déjà comparé ?
Marsh Posté le 22-11-2008 à 11:09:43
Joel F a écrit : non car les perfs sont atroces. |
Si t as un lien vers un article/bench/post qui parle de ca je suis interesse.
Marsh Posté le 22-11-2008 à 11:28:56
la mailing de boost contient pas de sujet à ce propos.
gil c'est bien pr les io. le reste ...
aprés moi, vu que c'est mon boulot d'implanter ce genre de truc, j'ai regardé le source de gil. C'est pas cahce-friendly, ca itére avec de siterateurs au lieu d'index ... bref.
Marsh Posté le 22-11-2008 à 11:29:41
Taz a écrit :
|
oui d'ou mon PS
Taz a écrit :
|
Plus trop maintenant. avec gcc 4.3+, la différence est de l'ordre du bruit des mesures sur Intel.
Taz a écrit :
|
ca sert à rien, parole d'expert . Je serais aussi enclin à stocker des uchar plutot que des bool dont la taille varie en fonction du compilo.
Marsh Posté le 22-11-2008 à 11:31:09
Je viens de tester un utilisant les trucs que je file en TP. J'arrive à 13 cycles par point pr une erosion sans optimisation. Soit, 2.8ms pour une image 720*576
sur un PC à 2GHz. Soit un x480 de mieux que le code original. Je subodore que les fonctions d'acces au taille sont pas inline et que tu meurt en allouant ton image résultat dans ta fonction.
Le code :
Code :
|
Citation :
|
Marsh Posté le 22-11-2008 à 16:47:00
Merci pour l'info.
Un petit site pas mal en passant:
http://www.cellperformance.com/mike_acton/
avec certains articles chouettes comme http://www.cellperformance.com/mik [...] _keyw.html
et le dernier papier de Drepper (GNU libc entre autres) avec un bon chapitre 6 sur le cache avec un petit exemple
http://people.redhat.com/drepper/cpumemory.pdf
Marsh Posté le 22-11-2008 à 17:15:36
mike acton est pas mal.
par contre, en general, le cache suffit pr ce genre de truc. les optim de fsb ou de vram : bof ^^
Deja si tout le mode faisait du LCS patten et du blocking dans ces nids d eboucles :E ca serait pas mal
Marsh Posté le 22-11-2008 à 21:05:28
C'ets una rticle du genre que j'utilise pr mes cours d'archi. Va fallori que je me mettes à jour
Marsh Posté le 29-06-2009 à 12:56:41
Bonjour,
Je ressors ce thread car j'ai eu récemment à réimplémenter cet algo et j'avoue être assez perplexe sur les gains que j'obtiens après une optimisation vis a vis du cache...
voici mon algo:
Operator.hpp
Code :
|
main.cpp
Code :
|
Bilan, la version cache friendly ne m'apporte quasi aucune amélioration sur les vidéos sur lesquelles je travaille (en CIF)
Citation : |
Si j'augmente la taille (du 4CIF comme dans l'exemple posté)
Citation : |
C'est toujours pas folichon folichon comme amélioration... Bon, niveau perf, honnêtement, ça me va... je me demandais juste si vous aviez une explication du si peu de gain que j'obtiens... Ou, peut-être ai-je encore fait une grosse erreur...
Merci
[edit] qq infos sur ma config, je suis sous Linux avec gcc 4.4.0-3, le tout compilé en O2
Marsh Posté le 29-06-2009 à 13:11:19
euh y a qd meme 13 CYCLES de gagné par points
Sinon -O3 aussi car pas sur que -O2 inline à fond.
Tu gagneras aussi à pas faire de if(std::abs()) dans tes boucles, t'as pas beosin de ça (cf vieux post)
Pour aller plus loin, SIMDisation ou bien allocation alignée sur la cache-line
Marsh Posté le 29-06-2009 à 13:23:10
Oui, j'ai essayé avec SSE2.. mais très mal fait
Ce qu'il y a c'est qu'avec mon érosion en 4 connexité avec un rayon de 1, ça fait pas beaucoup nombres donc mes vecteurs sont pas suffisamment remplit...
Du coup, j'avais cassé complètement les perfs (le compilo & le proc se débrouillent mieux sans moi)
Je pense qu'il faudrait que je déploie les boucles pour remplir mieux les vecteurs...
Marsh Posté le 29-06-2009 à 13:45:30
Je pense surtout que ta convolution etait mal vectorisé
Elimine le if deja tu verras, ca ira mieux.
Pour ref:
http://www.hipeac.net/system/files [...] evised.pdf
Saute le passage sur le CELL, les optimsiations présentées sont valides sur x86 et cie.
Marsh Posté le 29-06-2009 à 13:54:01
Le if, c'est bon je ne l'ai pas... Il est juste présent dans la version générique, j'ai fait une spécialisation pour un rayon de 1 (et 2 et 3)
Et merci, pour le document je vais étudier ça
[edit]
Après dans les versions générique je pense que j'ai vraiment besoin de faire les if(abs()), car je souhaite assurer une distance en 4 connexité
Marsh Posté le 29-06-2009 à 14:01:15
ha... je vais voir
[edit]
On est d'accord, je sors pas de la zone allouée. Mais par contre, je passe en 8 connexité si j'enlève le if non ?
Marsh Posté le 29-06-2009 à 16:15:49
Amonchakai a écrit : ha... je vais voir |
Oui certes.
Marsh Posté le 03-07-2009 à 15:53:04
Hello,
Bon, Il s'agit juste un post un peu inutile...
Mais je voulais juste redire merci au sujet de l'article qui a été mis en lien précédemment. Il y a plein de choses intéressantes dedans (il s'avère que j'ai beaucoup de boulot sur mes convolutions par des filtres 2D). Mais, il contient plein de bon principes (notament des réponses a des questions que je me posais sur l'apport du regroupement des calculs...)
Donc merci encore
# Avec SSE2, j'arrive maintenant a gratter encore quelques 40%. donc c'est pas mal du tout (et ça a eu le mérite d'être instructif)
Marsh Posté le 27-07-2009 à 18:16:27
Amonchakai, plutot que de te lancer dans de l'optimisation bas-niveau direct, re-reflechis peut-etre au probleme initial.
De maniere generale, l'erosion/dilatation, c'est du rafistolage, ça se generalise tres mal et c'est bourrain.
T'as regarde du cote du water-shedding ?
Si tu tiens réellement a jouer avec dilatations/erosions, lance une convolution avec un filtre gaussien a la con, tu reduira le nombre d'iterations necessaires pour bien decouper tes fourmis
Marsh Posté le 28-07-2009 à 11:17:29
water-shedding c'est quand meme la massue bien lente pour ce genre de probleme.
Par contre oui, gaussian blur avant.
Marsh Posté le 28-07-2009 à 11:37:22
Hello,
Merci pour cette remarque. Mais en réalité j'avais réglé le problème en générant une image de référence sans fourmi et soustrait cette image aux images contenant les fourmis + un seuillage.
Ca marche plutôt bien.
Pour ce qui est de l'érosion/dilatation j'en ais juste eu besoin récemment pour un algo d'ouverture/fermeture par reconstruction... Et j'ai lu des papiers qui décrivaient une implémentation efficace à base d'érosion et de dilatation...
enfin, merci pour l'aide
Marsh Posté le 21-11-2008 à 15:14:42
Bonjour,
Je travaille sur une application qui a pour but de suivre des entités (des fourmis) sur des vidéo. Pour extraire les fourmis des images de la vidéo, je pratique une différence par rapport à une image de référence sur laquelle il n'y a aucune entité. J'obtiens ainsi une image qui ressemble à ça :
Comme on peut le voir l'image binaire est très bruité, pour la nettoyer je voudrai passer par une érosion. L'implémentation de l'algorithme en lui-même ne pose pas vraiment de problème. Le fait est surtout que l'exécution est plutôt lente... En effet, actuellement, je met environ 1s pour traiter une image de 720x576 pxl. Mon souci c'est qu'a raison de 25/s ça va prendre des heures a traiter la vidéo de 25min...
Donc je me demandais, si par hasard vous ne verriez pas une idée pour optimiser mon algo :
Car là, à par aller voir les optimisation du côté de l'accès au cache... je vois pas trop ce que je peux faire...
Après je me dit que ce sera pas l'algorithme le plus couteux, donc si il y a pas d'autres solutions que de traiter l'accès au cache. Je ferai mieux de laisser tomber et d'aller voir la suite (je perdrai moins de mon temps...)
Merci
[edit] si vous avez d'autres idées qu'une érosion pour nettoyer l'image je suis preneur aussi
Message édité par Amonchakai le 21-11-2008 à 15:20:31