• Aucun résultat trouvé

Primitives de stockage et de représentation des données

Nous définissons de nouveaux types pour le stockage et la représentation des données en nous ap- puyant sur les types de base du Haskell. Pour la plupart, nous n’allons utiliser que la redéfinition des identificateurs des types déjà existants afin d’introduire au type l’information sémantique qui nous ser- vira à être clair et compréhensible dans les définitions complexes. Notons que les identificateurs de type dans Haskell doivent commencer par une lettre majuscule.

Deux mot clés du Haskell sont dédiés à ce but, data et type. Le mot clé data qui définit un véritable nouveau type de données, e.g. la définition

data AB= A | B

définit le type énumératif avec deux identificateurs possibles – A et B. Le mot clé type définit un nouvel identificateur du type en se basant sur les types déjà existants ou sur leur combinaison. Par exemple, l’expression

type B= A

définit un nouvel identificateur B comme étant le même type que l’identificateur A. Ou encore, l’expres- sion

type B= (A, A)

définit un nouvel identificateur B comme un tuple dont les deux éléments sont du type A. 4.3.1 Types de base

4.3.1.1 Indexation

Les numéros entiers seront utilisés pour exprimer les indices lors de l’indexation des éléments des arrays ou des listes. Nous pourrions utiliser directement les valeurs d’un type de Haskell, Int, mais nous préférons redéfinir son identificateur en une forme plus courte, I, qui va s’avérer très utile dans les défi- nitions plus longues.

type I = Int

4.3.1.2 Flux de données

La structure présente dans Haskell et convenable pour le stockage et le travail avec les données en stream (sur les flux de données) est celle d’une liste. La liste dans Haskell est définie, en utilisant la classe list, par le constructeur []. La liste est polymorphe et elle ne peut contenir que des éléments du même type. Par exemple, l’expression [] définit une liste vide et l’expression

xs = [ ’ x ’,’ y ’,’ z ’ ]

définit une liste xs dont les éléments sont des caractères, le premier élément a la valeur ’x’, le deuxième la valeur ’y’ et le troisième la valeur ’z’.

L’indexation des éléments dans une liste est effectuée par !! (double point d’exclamation) et com- mence à partir de 0. Ainsi, le premier élément détient l’index 0, le deuxième 1, etc. Par exemple, l’ex- pression

xs ! ! 1

rendra la valeur du deuxième élément, c’est-à-dire ’y’.

La deuxième manière de construire une liste est celle que nous avons déjà mentionnée (page 62) et qui utilise le constructeur : (deux-points). Celui est très utile lors de la composition des listes à partir des éléments, e.g. l’expression

ys = 1:2:3: [ ]

crée une liste ys qui est égale à [1, 2, 3].

La liste est un type essentiel dans les langages fonctionnels, Haskell inclus. Ainsi, les fonctions sur les listes sont incorporées dans Prelude, le cœur du Haskell. Pour plus de précision nous renvoyons le lecteur vers le manuelJon03 du langage Haskell. Nous allons utiliser les listes par la suite dans nos

algorithmes pour exprimer explicitement la notion d’un stream et pour ordonner des données lors d’un traitement en flux.

4.3.1.3 Types de données paquetées pour le traitement SIMD

Le traitement des données sur une architecture SIMD est un traitement en parallèle. Ainsi, il faut avoir des structures de données qui seraient convenables à un tel traitement. Pour le traitement stream sur les processeurs avec les capacités SIMD, nous utilisons des blocs de données élémentaires du même type regroupés dans un type composé qui constitue la base pour notre travail. Nous parlons ainsi des types de données paquetées. Ces types sont appelés dans la littérature également les données vectorielles.

Même si dans nos traitements nous pouvons rencontrer les vraies données vectorielles comme c’est le cas chez les coordonnés x, y, z, w sur les cartes graphiques, dans la plus grande partie de nos algorithmes, les données que nous traitons ne correspondent pas à un vrai vecteur d’un point de vue mathématique mais plutôt à des groupes de pixels. C’est la raison pourquoi nous préférons garder le terme données paquetées pour nos propos car nous pensons que l’appellation "paqueté" reflète mieux la réalité. De plus, elle correspond à un terme que nous trouvons dans la littérature anglaise – "packed-vector".

En théorie, nous pouvons choisir une taille arbitraire du type de données paquetées, en pratique nous sommes restreints par le choix de l’architecture finale et par ses capacités. La plupart des architec- tures contemporaines possèdent des types paquetés de 4 à 16 éléments (cf. les technologies multimédia, tab. 1.2, page 21, dans le chapitre Motivation). Sur les architectures spéciales et dédiées nous pouvons trouver un nombre plus élevé d’éléments dans un type paqueté (de 64 à 256), e.g. prototype du processeur dynamiquement reconfigurable Vision chipKKI04ou le système IMAP-VISIONPJ00.

Un exemple du type paqueté iu8vec8 (notation MorphoMediaBra05) regroupant 8 éléments unsigned

integer de 8 bit est présenté sur la fig. 4.1. Ainsi, la largeur totale du type paqueté iu8vec8 est de 64 bit et nous pouvons l’utiliser pour un travail avec des architectures possédant des instructions multimédia pour ce type, notamment les processeurs compatibles SHmediaBra02, processeurs compatibles MMX™,

les processeurs issus de l’architecture IA-64 d’Intel ou les processeurs issus de l’architecture AMD64 d’AMD.

iu87 iu86 iu85 iu84 iu83 iu82 iu81 iu80 63 56 55 4847 4039 3231 2423 1615 87 0 bit no.

FIG. 4.1 : Structure du type de données paquetées iu8vec8 (notation MorphoMediaBra05) qui est composée de

8 éléments du type iu8 (integer unsigned 8 bit)

L’expression de ces types en formalisme fonctionnel est simple. Nous allons utiliser le type du Has- kell Array, même si dans Haskell nous avions encore une autre possibilité - les listes. Il nous est plus naturel d’utiliser les arrays, car de leur essence, les types paquetés sont les arrays 1D. De plus, l’utilisa- tion des arrays pour l’expression des données paquetées nous permet de faire une distinction claire entre les données statiques, exprimées par les arrays, et les données dynamiques, exprimées par les listes et décrivant les streams lors d’un traitement en flux, comme défini dans la section précédente, cf. 4.3.1.2.

Pour ces raisons, nous définissons un nouvel identificateur du type, PVec (correspondant au pacekd vector), en nous basant sur le type Array du Haskell.

type PVec = Array

Pour pouvoir initialiser une variable du type PVec, nous définissons la fonction pvec qui crée un array d’une dimension à partir d’une liste des éléments. Le premier paramètre correspond aux tuples des bornes minimales et maximales, respectivement. Le deuxième paramètre est la liste des tuples index-élément, respectivement. Cette définition est une spécialisation de la fonction standard du Haskell array pour une dimension.

pvec :: ( I , I ) → [ ( I ,α) ] → PVec I α pvec i e = array i e

4.3.1.4 Images, arrays, vecteurs

Nous allons utiliser un type interne du Haskell, Array, pour le stockage des données matricielles et tensorielles. Ce type va nous servir au stockage d’images, textures, des arrays 2D ou des vecteurs. Pour des raisons de clarté et de simplicité de compréhension dans les définitions plus longues, nous allons définir pour ce type un nouvel identificateur plus court, Ar.

Expliquons son utilisation sur quelques exemples des signatures de type pour les array polymorphes de 1 et 2 dimensions. Elles seront employées par la suite dans les définitions des fonctions maniant ces structures de données :

• Ar I α – array d’une dimension, dont les index sont du type I et dont les élements sont du type

polymorphe α,

• Ar (I, I) α – array de deux dimensions, dont les index sont des tuples (I, I) et dont les élements sont

du type polymorphe α,

• Ar (I, I) Int – array de deux dimensions, dont les index sont des tuples (I, I) et dont les élements

sont du type précis, entier, Int,

• Ar (I, I) (Ar (I, I) α) – array de deux dimensions, dont les index sont des tuples (I, I) et dont les

éléments sont des arrays de deux dimensions Ar (I, I) α.

• Ar (I, I) (PVec I α) – array de deux dimensions, dont les index sont des tuples (I, I) et dont les

éléments sont des arrays paquetés PVec I α.