Bonjour à tous,
Je vous pose d'abord ma question précise, puis je vous raconte pourquoi elle est apparue:
Disposant d'une liste d'objets pondérés (par des floats ou int positifs), comment créer une liste L de ces objets tels que:
- Chaque objet O soit présent a peu prés len(L) *O.pondération dans L
- Chaque objet soit présent au moins une fois (sauf peut etre ceux de pondération nulles)
- L'entrelacement soit maximum (ou grand) : je veux le maximum d'objets différents et différents de O entre deux apparitions successives de O dans L (et ceux pour tous les objets O).
- De longueur pas trop importante.
Merci d'avance pour vos suggestions. Voici maintenant la petite histoire pour ceux qui ont le courage:
J'utilise les générateurs afin de simuler du threading sous Python. Le principe est le suivant:
* Un thread est un générateur
* thread.start() revient à rajouter thread à un conteneur ThreadPool
* ThreadPool est reponsable de la boucle principale de ce réacteur. Cette boucle s'occupe d'appeler successivement iter() sur chaque generateur contenu dans ThreadPool.
Une petite remarque:
J'ai découvert Twisted depuis, et j'ai réalisé qu'il s'agissait d'implémenter un réacteur,en favorisant les générateurs plutot que les callbacks. Pour l'instant j'en reste à mon implémentation, mais je passerai peut etre en Twisted un jour.
Voici le problème:
Comment définir des priorités associées à chaque thread, qui fasse que la boucle principale du réacteur apelle plus souvent les thread à haute priorité ?
J'utilise pour l'instant une solution fruste:
- Une priorité est un entier, ou None (priorité normale)
- A chaque itération n dans la boucle du réacteur, je choisis un thread avec priorité si n%priorité == 0, s'il existe, sinon je choisis le prochain thread sans priorité.
Cette solution:
- Est approximative ,mais cela ne me dérange pas : appeler un thread 12 fois en 20 sec un thread que je comptais appeler seulement 10 fois n'est pas un problème pour moi. Je n'ai pas besoin de controler exactement la priorité, seulement de manière approchée.
- Etait rapide à coder
- N'ajoute pas beaucoup de surcharge au méchanisme de réacteur (par exemple: pas besoin de stocker combien de fois chaque thread a été appelé)
- Assure l'entremèlement des tâches. Par exemple, assure que tous les threads sans priorité sont appelés une fois chacun avant d'en rappeler un une seconde fois.
- Mais elle a une limitation sérieuse. Les priorités doivent être uniques, entières et souvent des nombres premiers, car si thread1.prio divise thread2.prio, thread2 sera en général masquée. C'est problématique dès que j'ai besoin de définir la priorité de beaucoup de tâches
Je cherche à aller au plus vite tout en restant efficace (il faut que le code propre au réacteur soit rapide pour laisser au threads le temps de tourner). Je pensais à la solution suivante:
* Les priorités sont des floats.
* A chaque itération, je tire au hasard le thread à éxécuter, en tenant compte des pondérations = priorités.
Je pense que la question devient vite difficile, et je voulais avoir votre sentiment sur les points suivants:
- Il est préférable d'utiliser une librairie toute prête comme Twisted (je ne sais pas si Twisted permet de pondérer ses générateurs)
- Choisir au hasard les taches à effectuer dans un réacteur me semble être une bêtise. En effet on ne controle plus l'entremèlement des taches, et respecter exactement les probabilités n'est pas vital pour moi.
- Ce dernier point pourrait être contourné en utilisant des outils avancés de simulation aléatoire, comme une Monte-Carlo Markov-Chain (tirages non indépendants).
Partager