IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Se servir du multithreading pour accélérer le temps d'exécution de vos batches
Un tutoriel d'Immobilis

Le , par Immobilis

54PARTAGES

1  0 
Bonjour à tous,

J'ai écrit un tutoriel à propos de l'utilisation du multithreading dans une application de traitement par lots (batch): http://immobilis.developpez.com/tuto...tielle-batchs/

N'hésitez pas à me dire ce que vous en pensez. Si vous avez des questions n'hésitez pas à les poster ici, j'aurai plaisir à y répondre.

Merci d'avance.

Immo

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de Nathanael Marchand
Rédacteur https://www.developpez.com
Le 07/12/2012 à 23:16
J'ai fait mumuse avec un code proche de ta solution et en y ajoutant la TPL.
Ben pour tous, c'est grosso modo la même chose... J'ai pas fait l'étape sauvegarder dans un fichier car flemme mais ca n'a rien de bloquant.
A chaque fois on est capable de chronométrer le temps par appel et le temps total. Ca supporte aisément plus de 64 tâches (je n'utilise pas de WaitHandle.WaitAll)
En fait, ce qui est surtout déterminant (et en fait ce qui est complètement masqué dans ton article) c'est la capacité du client à traiter les tâches de manière concurrente. Tu remarqueras que dans mon exemple j'utilise un WCF en console pour avoir totalement la main sur le parallélisme. Toutes les requêtes sont indépendantes et une instance de service par requête.
Code : Sélectionner tout
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall)]
Code : Sélectionner tout
1
2
3
4
5
<serviceBehaviors>
	<behavior name="HelloWorldBehavior">
		<serviceThrottling maxConcurrentCalls="10"/>
	</behavior>
</serviceBehaviors>
D'après moi c'est au fournisseur de brider son service en fonction de ce qu'il peut recevoir et non pas au consommateur. Du coup, y'a pas vraiment de raisons de brider côté client. Et quand bien même tu voudrais brider, tu pourrais totalement avec le sémaphore.
1  0 
Avatar de Nathanael Marchand
Rédacteur https://www.developpez.com
Le 25/11/2012 à 12:38
Question bête mais pourquoi ne pas utiliser la TPL ?
0  0 
Avatar de Immobilis
Expert éminent https://www.developpez.com
Le 25/11/2012 à 13:04
Salut
Citation Envoyé par Nathanael Marchand Voir le message
TPL ?
La quoi?

[EDIT]La Task Parallel Library? Ben je connaissais pas.

A l'époque, j'ai trouvé une solution avec mes connaissances du moment et le Framework imposé (3.5). Bon, pour le tutoriel , j'ai utilisé le FW 4.5 et VS Ultimate. Je vais regarder ça.

Merci
0  0 
Avatar de Immobilis
Expert éminent https://www.developpez.com
Le 06/12/2012 à 12:46
Citation Envoyé par Nathanael Marchand Voir le message
pourquoi ne pas utiliser la TPL ?
Effectivement, cette bibliothèque semble très pratique.

Toutefois, je n'ai pas trouvé de méthode/implémentation pour reproduire le comportement "flux tendu". Il y a bien les "tâches de continuation" mais il faudrait gérer la possibilité de démarrer un nombre variable de tâches (ex: 10). Une fois finie, chaque tâche doit lancer la suivante jusqu'à ce que toute la pile ait été traitée. C'est faisable, mais du coup on ne profite pas forcement des capacités de la TPL.

Sachant qu'on ne connait pas le nombre de tâches ni le nombre de flux simultanés, l'utilisation de "child task" ou "nested task" ne nécessiterait-il pas la création d'une fonction récursive? Il faut que je teste cela, mais il me semble que la tâche parent ne serait pas collectée par le garbage collector tant que tous les enfants n'ont pas été collectés. Du coup, j'ai peur que des ressources partagées (ex: traitement sur des fichiers) ne restent bloquées.

Dans mon exemple, c'est le manager qui créé les tâches. Il y a donc pas d'interactions entre ces dernières.

Qu'en penses-tu?
0  0 
Avatar de Nathanael Marchand
Rédacteur https://www.developpez.com
Le 06/12/2012 à 13:17
J'ai pas tout compris

T'as un cas d'utilisation simple, que j'y reflechisse ?

Je dois préparer une formation pour les consultants de ma boite sur la TPL, mi janvier. Quand j'aurais un peu de temps, je la coucherai sur un article, n'hésite pas à m'y indiquer tes préoccupations, ca ne peut que m'aider
0  0 
Avatar de Immobilis
Expert éminent https://www.developpez.com
Le 06/12/2012 à 22:41
Citation Envoyé par Nathanael Marchand Voir le message
T'as un cas d'utilisation simple, que j'y reflechisse ?
Le cas du tuto: http://immobilis.developpez.com/tuto...atches/#LIII-F
  1. Faire 1000 appels sur un service web;
  2. Enregistrer la réponse qui peut arriver après un temps d'attente de 1 à 10 secondes.
  3. Mettre le moins de temps possible.
A+
0  0 
Avatar de Nathanael Marchand
Rédacteur https://www.developpez.com
Le 07/12/2012 à 10:28
Je comprends pas tout à fait ta problématique de flux tendu mais bon...
Pour le coup, Task derrière c'est plus ou moins le même principe que ThreadPool...
Quand tu fais 1000appels aléatoires, tu a pas peur que le facteur aléatoire influence les tests ? Il faudrait vérifier que le temps moyen soit identique à chaque test.
0  0 
Avatar de Immobilis
Expert éminent https://www.developpez.com
Le 07/12/2012 à 11:18
Citation Envoyé par Nathanael Marchand Voir le message
Je comprends pas tout à fait ta problématique de flux tendu mais bon...
A mince. Du coup, tu n'est peut-être pas le seul. Je précise donc.

Dans le tutoriel, je présente trois façons de faire du multithreading. Les deux premières sont celles qu'on trouve couramment sur internet:

  1. Tous les threads en même temps => écarté car surcharge le serveur;
  2. Une salve de threads (en utilisant le pool et un waithandle) => écarté car WaitAny ne permet pas de savoir combien de threads ont terminé (donc on ne sait pas combien on peut en relancer) et WaitAll provoque des temps morts (des threads ont fini mais le signal n'est pas envoyé car d'autres sont encore en train de travailler).

Le terme "flux tendu" indique qu'il ne doit pas y avoir de temps mort. Grâce aux évènements, chaque thread indique quand il a fini. Le manager peut lancer un nouveau thread dès qu'un se libère. On maintient un nombre déterminé de threads en action. Cela permet de tirer parti des ressources des différents systèmes au maximum (voir la comparaison des temps).

Est-ce plus clair?
0  0 
Avatar de antoine.debyser
Membre confirmé https://www.developpez.com
Le 07/12/2012 à 11:49
Bonjour,

Plusieurs point m'avez surpris à la lecture du tutoriel.
Notamment sur les liens entre les résultats et la version suivante. Par exemple pas besoin de thread pool pour pouvoir répondre à tous les besoins.

Mais revenons au sujet, à la lecture du cas du thread pool, je me suis posé la question suivante :
- la découpe en "salve" de thread, comme tu dis, est elle vraiment nescessaire? n'est ce pas dans le périmètre du thread pool?

Apres test, en local, le thread pool semble bien répondre à ce besoin, c'est à dire que tous les thread ne sont pas lancé dans la foulé. Il est possible de définir la limite soit même, Bref seul "i" thread sur les "n" tourne en même temps.

Du coup on peut faire un "WaitAll", pour attendre la fin de tous les thread, il n'y aurra pas de temps de mort, on aurra une vrai mesure du temps total, et la possibilité d'agrégé tous les retours.

Au niveau de TPL, il me semble que créer une class dérivé de TaskScheduler permet d'obtenir le meme comportement.
Le principe de chainage correspond à un autre besoin. Celui qu'une tache ne doit pas être exécuté avant une autre.
0  0 
Avatar de Nathanael Marchand
Rédacteur https://www.developpez.com
Le 07/12/2012 à 12:41
Ah ben là, en effet je confirme les propos de antoine.debyser, dans le cas du ThreadPool ca fait double pooling et c'est déconseillé

Cependant, j'ai déjà eu des cas ou une librairie tierce (Oracle pour ne pas la citer) utilisait également le ThreadPool et on avait des conflits: On crééait n taches via le ThreadPool, chaque tâche ouvrait une connection base de données. Or sur Oracle, dans le driver, l'ouverture se base aussi sur le ThreadPool et l'action n'était jamais dépilée : deadlock !
0  0