Algorithme séquentiel. La version séquentielle de l’algorithme est basée sur la méth-
ode de séparation et d’évaluation (branch and bound). Cet algorithme prend en entrée
le nombre de villes, et une matrice de coût, et retourne la longueur du chemin mini-
mal (min_path). Il a une complexité de O(n!) dans le pire des cas. Il n’explore pas
les chemins plus long que le meilleur chemin déjà rencontré, il écarte donc les branches
inutiles. Cette technique d’élagage améliore considérablement les performances de l’al-
gorithme mais introduit également des irrégularités dans l’espace de recherche. La pro-
fondeur de la recherche nécessaire pour parcourir une des branches dépend de l’ordre
dans lequel les branches ont été fouillées.
Algorithme multi-threadé. Ici, on a créé une file d’attente de tâches (branches de
recherche) à partir de laquelle chaque thread prend les tâches à exécuter. La génération des
tâches se fait de manière séquentielle car le temps nécessaire pour le faire est négligeable.
Dès qu’un thread se retrouve sans tâche, il prend une nouvelle tâche dans la file d’attente.
Le nombre de tâches qui doivent être générées change en fonction du nombre de threads
et est défini par le paramètre max_hops (le nombre minimum de niveaux de l’arbre de
recherche). Le nombre total t(l, n)de tâches en fonction des niveaux let des nvilles peut
être déterminé par la relation de récurrence suivante : ∀l∈[0, n[,t(l, n) = 1 si l= 0 et
t(l, n) = t(l−1, n)∗(n−l)sinon.
Algorithme distribué. Cet algorithme reçoit comme paramètre supplémentaire le
nombre de postes n_postes à utiliser. Pour chaque poste, n_threads threads sont créés,
donc on a un total de n_threads ∗n_postes threads. Dans chaque poste, l’exécution est
similaire à celle du cas multi-threadé. La seule différence est que, lorsque le min_path
est mise à jour dans un poste, cette mise à jour est diffusée à tous les autres postes afin
qu’ils puissent aussi l’utiliser pour optimiser leur exécution. À la fin de l’exécution, un
des postes imprime la solution. Chaque poste poste_id ne travaille que sur les tâches qui
lui ont été assignées. Pour ce faire, nous définissons le nombre de tâches (regroupées en
partitions) par poste. Lorsque les postes sont à court de tâches, ils demandent d’autres
partitions au poste maître. Pour réduire le nombre de communications, le poste maître en-
voie des partitions de taille décroissante à chaque demande [7]. En effet, comme les tailles
des tâches sont irrégulières, la distribution d’un nombre de plus en plus petit de partitions
vers la fin de l’exécution pourrait réduire le déséquilibre de charge entre les postes. Dans
ce cas, pour chaque demande, le poste maître envoie un ensemble de partitions Set le
poste poste_id travaille sur des tâches telles que task_index mod n_partitions ∈S.
Comme la génération des tâches se fait au niveau local, la quantité de données transférées
peut être minimisée.
4. Adaptation du TSP à une Plate-forme Manycœur
Nous avons présenté dans la section 3 un aperçu des algorithmes de résolution du TSP.
Toutefois, les différences architecturales entre les plates-formes multicœur et manycœur
nous obligent à faire des adaptations du code. Dans cette section, nous discutons des
adaptations effectuées avec le cas particulier du manycœur MPPA-256.
La bibliothèque Pthreads est installée sur les deux plates-formes testées. Dans la ver-
sion multi-threadé du code, min_path est implémenté en utilisant une variable partagée
qui est accessible par tous les threads. Les opérations d’écriture sur cette variable (c.a.d.
quand un thread trouve un chemin plus court) sont protégées par un verrou pour éviter les
situations de compétition. Contrairement aux opérations d’écriture sur cette variable, les
opérations de lecture ne sont pas protégées pour que le parallélisme ne soit pas limité.