Université de Paris Sud
——–
Master IST - M2Pro
DSP
Tri et filtre médian
1 Introduction
Le filtrage médian est un filtre non linéaire de la famille des filtres d’ordre. Le filtrage médian
est très robuste à différents types de bruits, comme le bruit gaussien ou le bruit impulsionnel.
Le principal inconvénient du médian est sa complexité mathématique en O(n2)pour calculer le
médian de néléments. Son autre inconvénient est que dans sa formulation classique (sous forme
de tri) il est impossible de paralléliser certaines parties de l’algorithme à cause des dépendances
de données. Le but de ce TP est de réaliser différentes implantations du filtre médian notamment
l’implantation d’un algorithme parallélisable par morceau, qui pourra tirer partie des nombre-
seuses unités de calcul d’un processeur VLIW.
L’ensemble du TP est réalisable en C sur une machine classique, seule la dernière partie (as-
sembleur linéaire) ne peut se faire que sous l’environnement Code Composer Studio. Il est donc
envisageable (fortement conseillé) de préparer le TP.
Un type utilisateur (user data type) va être défini pour séparer les variables de l’algorithme des
variables liées au codage des boucles : typedef short int16 ; qui devra être présent dans votre
code C.
2 Algorithme de tri
Les algorithmes de tris peuvent être classés en trois catégories : les algorithmes classiques comme
le tri par sélection ou le tri par insertion, les algorithmes rapides comme le tri par fusion ou le
tri rapide et les algorithmes lents mais réguliers comme le tri à bulles.
Les algorithmes classiques et lents une complexité en O(n2)alors que les algorithmes rapides
ont une complexité en nlog(n), car il est nécessaire de réaliser n2(respectivement nlog(n))
comparaisons pour trier nvaleurs.
L’implantation classique se fera en suivant les étapes suivantes :
1. Ecrivez une fonction tri_selection(int16 *T, int n) qui implémente le tri par sélection.
Validez l’algorithme (en mode Debug) avec comme valeurs de test les valeurs suivantes :
9,7,8,3,1,2,6,4,5.
2. Ecrivez une fonction tri_bulles(int16 *T, int n) qui implémente le tri à bulles. Validez
(ne pas oublier de mélanger le tableau avant chaque appel à une routine de tri ...).
3. Mesurez les performances de votre implantation (en mode Release) via le filtrage d’un
tableau de de Nvaleurs générées aléatoirement via la fonction void rand16(int16 *T, int
n) ;. Le nom du tableau source sera Xet le nom du tableau destination sera Y. Ces tableaux
pourront être défini de manière statique int16 X[N], Y[N]. Mesurez le temps d’exécution
pour N[20,40,60,80,100].
4. Le modèle de temps d’exécution qu’on cherche à appliquer est t(n) = a2x2+a1x+a0.
Faites une régression quadratique au sens des moindres carrés pour chaque jeu de mesures.
Si vous avez oublié comment cela se calcule ... allez sur le site Alpha de Wolfram Research
(http://www.wolframalpha.com) et tapez quadratic fit calculator dans la zone de
1
saisie puis adaptez l’exemple donné. L’éditeur de Mathematica propose en ligne une très
grande partie des fonctionnalités de Mathématica. Pour chaque fit, indiquez le coefficient
de corrélation R2. Conclure
Nota : vous pouvez éventuellement faire des mesures avec des valeurs de Nplus grandes, par
exemple la série de valeurs N[50,100,150,200] donne de meilleures résultats, mais cela prend
beaucoup plus de temps...
La fonction rand16 utilisera un générateur aléatoire à congruence linéaire :
y=f(x)=(ax +b)mod c(1)
avec a, b, c premiers entre eux (on pourra prendre a= 11,b= 13,c= 17).
Dans la suite on utilisera le tri par sélection comme tri de référence.
3 Médian classique
Plutôt que de faire un filtrage classique (FIR) sur un voisinage de taille k, nous allons utiliser
un filtre d’ordre : ici un filtre médian.
L’algorithme classique du filtre médian repose sur l’utilisation d’un algorithme de tri. Soit un
tableau de kvaleurs à trier. La valeur médiane est la valeur se trouvant au milieu du tableau, en
k/2. Dans toute la suite, ksera égal à 9. Pour produire la case Y[i], on copie kvaleurs centrées
en X[i]: les cases X[ik/2] àX[i+k/2] sont copiées dans kvariables elles mêmes copiées dans
un tableau interne (de kcases) à la routine de tri). Ce tableau est trié et la routine renvoie le
médian.
1. Ecrire une fonction median9Array qui utilise l’algorithme de tri par sélection et qui renvoie
la valeur médiane. Le prototype de la fonction est :
int16 median9(int16 a, int16 b, int16 c, int16 d, int16 e, int16 f, int16 g, int16
h, int16 i) ;. Pour chaque case
2. Valider l’algorithme (en mode Debug) avec comme valeurs de test les valeurs suivantes :
9,7,8,3,1,2,6,4,5.
3. Mesurer les performances de votre implantation (en mode Release) via le filtrage d’un
tableau Xde N= 100 valeurs générées aléatoirement via la fonction void rand16(int16
*T, int n) ;. Le nom du tableau source sera Xet le nom du tableau destination sera Y.
Ces tableaux pourront être défini de manière statique int16 X[N], Y[N]. essayez plusieurs
valeurs de Npour calculer un modèle de temps de calcul.
La fonction rand16 utilisera un générateur aléatoire à congruence linéaire :
y=f(x)=(ax +b)mod c(2)
avec a, b, c premiers entre eux (on pourra prendre a= 11,b= 13,c= 17).
4 Médian rapide
4.1 Présentation de l’algorithme
Lorsque kest un carré, il existe un algorithme bien plus astucieux et qui peut être paralléliser par
partie. L’algorithme est le suivant (dans notre cas, nous avons 3×3valeurs à trier). Premièrement,
ces 3×3valeurs sont représentées en 2D.
Soient les 9valeurs suivantes à trier représentée en 2D :
2
a b c
d e f
g h i
(3)
L’algorithme d’extraction du médian est composé de trois étapes :
étape 1 : trier chaque ligne, tri de {a, b, c}tri de {d, e, f}et tri de {g, h, i}
étape 2 : trier chaque colonne, tri de {a, d, g}, tri de {b, e, h}, tri de {c, f, i}
étape 3 : trier la diagonale secondaire, {g, e, c}: le médian se trouve alors au milieu dans la
variable e
4.2 Démonstration
Chaque étape crée une relation d’ordre partiel par ligne (respectivement par colonne). La figure
1 décrit la construction de ces relations d’ordre. La flèche signifiant la relation “supérieur à
A B C
D E F
G H I
A' B' C'
D' E' F'
G' H' I'
A" B" C"
D" E" F"
G" H" I"
état initial lignes triées colonnes triées
Figure 1 – tri par ligne et par colonne
En appliquant une une rotation de 45 degré au schéma, (figure 2), on voit que les trois points du
haut (A,Det B) sont les trois plus petits (même si Det Bne sont pas triés). De même,
les trois points du bas (H,Fet I) sont les trois plus grands. La médiane est donc forcément
parmi les trois points du milieu (G,Eet C) qu’il ne reste plus qu’à trier. Une ces trois points
triés, la valeur est en E. CQFD ! A noter qu’il n’y a pas de relation d’ordre total : par exemple
on peut observer que Aest plus petit que Bet D, mais il n’y a pas de relation entre Bet
D. Idem pour I,Fet H.
A"
B"
C"
D"
E"
F"
G"
H"
I"
CEG
diagonale triée
Figure 2 – Extraction du médian
4.3 Implantation du tri
Au lieu d’utiliser le tri par sélection ou le tri par insertion pour trier les valeurs par 3 (en ligne
ou en colonne), c’est le tri à bulles qui va être utilisé car il a la particularité d’avoir une structure
itérative régulière. Il s’implante particulièrement bien en VHDL et sur DSP VLIW (ainsi que
3
sur tout processeur doté d’instructions à exécution conditionnelle – aussi appellées instructions
gardées –). Soit l’opérateur mM (pour minMax) qui prend en entrée deux valeurs et qui renvoie
les deux valeurs triées (la valeur de gauche est la valeur min, la valeur de droite est la valeur
max) :
mM(a, b) = (min(a, b),max(a, b)) (4)
L’opérateur mM peut aussi être vu comme une simple permutation si b < a (dans le cas contraire
rien n’est fait) :
mM(a, b) = ((b, a)si b<a
(b, a)sinon (5)
Trier a, b, c consister à :
1. trier a, b :mM(a, b)
2. trier b, c :mM(b, c)
3. trier a, b :mM(a, b)
A la fin la plus petite valeur est en a, la plus grande est en cet la valeur médiane au milieu en
b. C’est le principe du tri à bulles qui fait remonter les plus petites valeurs en début de tableau,
et les plus grandes en fin de tableau (figure 3).
A B C
m M
m M
A B C
A B C
A B C
m M
Figure 3 – principe du tri à bulles appliqué à 3 valeurs
4.4 Implantation via des fonctions
1. Faire un schéma montrant les différents calculs pouvant être fait en parallèle
2. Ecrire une fonction qui renvoie le minimum de 2 nombres, dont le prototype est :
int16 min16(int16 a, int16 b) ;
3. Ecrire une fonction qui renvoie le maximum de 2 nombres, dont le prototype est :
int16 max16(int16 a, int16 b) ;
4. Ecrire une fonction minMax16 utilisant les fonctions min16 et max16 avec passage par adresse
des arguments et qui renvoie dans le premier argument le minimum et dans le second le
maximum. Le protype de la fonction est :
void minMax16(int16 *a, int16 *b) ;
4
5. Ecrire une fonction tri qui tri valeurs valeurs passées par adresse. Cette fonction utilisera
la fonction minMax16. Le prototype de la fonction est :
void tri3(int16 *a, int16 *b, int16 *c) ;
6. Ecrire une fonction median9 qui prend 9 valeurs en argument et qui implante l’algorithme
rapide. Le prototype de la fonction est :
int16 median9(int16 x0, int16 x1, int16 x2, int16 x3, int16 x4, int16 x5, int16 x6,
int16 x7, int16 x8) ;
7. Valider l’algorithme (en mode Debug)
8. Mesurer les performances (en mode Release). Quel est le gain ?
4.5 Implantation via des MACROS
Afin d’accélérer cet algorithme, on décide de remplacer les appels de fonctions par des appels de
macros (une solution intermédiaire aurait été d’appliquer des fonctions d’inlining).
1. Ecrire une macro MINMAX16(a,b)
2. Ecrire une macro TRI3(a,b,c)
3. Ecrire une macro MEDIAN9(a,b,c,d,e,f,g,h,i)
4. Valider l’algorithme (en mode Debug)
5. Mesurer les performances (en mode Release) de cette nouvelle implantation. Quel est le
gain ?
4.6 Implantation via l’assembleur linéaire
ADD3 .macro x0,x1,x2,s
ADD x0,x1,s
ADD x2,s,s
.endm
Table 1 – exemple de macro en assembleur linéaire C6x
Le langage C est très riche mais ne permet pas d’exprimer certaines optimisations liées à l’archi-
tecture du DSP, comme :
les instructions exécutées conditionnellement à l’état d’une variable : [cond] ADD a,b,c
les instructions pouvant s’exécuter en parallèle, au même cycle : ADD a,b,c || ADD e,f,g
toute combinaison d’instructions parallèles à exécution conditionnelle.
1. Ecrire une macro assembleur MINMAX16(a,b)
2. Ecrire une macro assembleur TRI(a,b,c)
3. Ecrire une fonction assembleur MEDIAN9_SA qui renvoie le médian. Le prototype de la fonc-
tion est :
MEDIAN9_SA(a,b,c,d,e,f,g,h,i)
4. Valider l’algorithme (en mode Debug)
5. Mesurer les performances (en mode Release) de cette nouvelle implantation. Quel est le
gain ?
Une macro commence par le mot clé .macro et se termine par .endm (Tab. 1).
5
1 / 6 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !