Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1950 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  gestion des variables dans une dll multithread ?

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

gestion des variables dans une dll multithread ?

n°1094841
chicotruss
Posté le 24-05-2005 à 13:20:31  profilanswer
 

Salut,
 
voila mon problème:
 
Je suis entrain de coder une interface java pour réaliser des taches variées (ex: encodage video, audio, (de)multiplexage, cryptage, etc.).
La plupart de ces opérations sont réalisées par des programmes C/C++. J'interface donc les fonctions C necessaires via la JNI (Java Native Interface, utilisation de fonction C en Java) ce qui nécéssite de recompiler les programmes C/C++ comme des dll. Jusque la pas de problème.
 
Maintenant, j'aimerais pouvoir lancer plusieurs taches identiques en même temps (ex: deux encodages audio) qui vont donc utiliser la même dll.
Chaque thread est lancé depuis Java (java.exe[|javaw.exe]) et donc ils s'executent tous dans le meme process. J'en suit donc revenu a un cas similaire à un prog C/C++ qui génére plusieurs thread, chacun pouvant faire appel "simultanément" à une même fonction d'une dll.
 
1. je suppose que je dois compiler ma dll en multithread. OUI|NON ?
 
2. Comment ca ce déroule en interne au niveau des variables ? Est ce que ca pose un problème de partage si une meme fonction est appellée au même moment par 2 threads du même process ? (je demande ca car je crois que la dll fournit une instance du code par process et non par thread).
 
3. Le prog C/C++ original contient des variables globales qui sont donc partagées entre tous les process qui utilisent la dll (enfin, je crois). Quelqu'un a t'il une idée pour que je puisse gérer une sorte d'environnement par thread (ex: si on peut executer une fonction des que le thread reprend la main et affecter les variables globales avec les siennes) ?
 

mood
Publicité
Posté le 24-05-2005 à 13:20:31  profilanswer
 

n°1427848
Fouge
Posté le 20-08-2006 à 00:20:51  profilanswer
 

UP car ça m'interesse (même si c'est vieux).

n°1430837
TNZ
Ryzen 9 5950X powered ...
Posté le 24-08-2006 à 17:13:48  profilanswer
 

1. j'crois que c'est clair :D
 
2. Dans la mesure où le process dispose d'un seul espace d'adressage. Donc les variables globales (statiques ou non) seront accédées par tous les threads à l'identique. Le plus important pour des fonctions utilisées par des threads est qu'elles soient réentrantes, CàD que tout les éléments variables soient locaux (passage de paramètres et variables locales). A partir du moment où tu introduis une variable globale ou dynamique commune à plusieurs thread, tu es obligé de gérer un mutex lecteur/écrivain.
 
3. Pour les variables globales des DLL, tout dépend si elles sont statiques ou pas (et je crois me souvenir que la liste des symboles visibles d'une DLL doit être donnée explicitement). Et pour répondre à ta question, la solution reste à réentrance avec un pointeur sur un contexte (une struct somme toute) alloué dynamiquement lors de la création du thread.
 
Vala, :)

n°1430891
Fouge
Posté le 24-08-2006 à 17:41:54  profilanswer
 

TNZ a écrit :

Dans la mesure où le process dispose d'un seul espace d'adressage. Donc les variables globales (statiques ou non) seront accédées par tous les threads à l'identique.

C'est ce que je voulais savoir, et je l'ai vérifié par moi-même.
 
Je vais expliquer mon cas. J'utilise une librairie qui faits des calcul. Celle-ci utilise, en "interne", des variables globales. Pour moi à priori peu importe, du moment que le résultat est bon :)
Je lance le calcul dans un thread, tout va bien. Seulement, je décide d'en lancer un 2ème (dans un autre thread) et là, les résultats sont délirant. C'est dû à ces fameuses variables globales qui ne peuvent pas etre utilisées pour plusieurs calculs en même temps.
Je décide donc, juste pour tester car je n'ai pas eu d'infos claires là-dessus, de créer une DLL (avec les fonctions et les variables globales de la librairie en question) et de charger explicitement (via LoadLibrary et GetProcAddress) cette DLL dans chaque thread. Juste pour voir si elles accèdent au même espace mémoire ou si les variables sont dupliquées. Mais non, j'ai le même problème comme je le craignais.
 
La seule solution que je vois c'est de supprimer ces variables globales de 2 manières :
1) les rendre locales et faire des passages par adresse
2) créer une classe avec variables membre
Mais cette bibliothèque est énorme, pas simple à "gérer" donc je n'enviseage aucune de ces 2 solutions.
 
Sachant que je ne veux pas qu'il y ait de "temps mort" (chaque thread est totalement indépendant et doit tourner "à fond" ) existe-t-il une autre solution que je ne connais pas ?


Message édité par Fouge le 24-08-2006 à 17:43:52
n°1430907
TNZ
Ryzen 9 5950X powered ...
Posté le 24-08-2006 à 18:06:27  profilanswer
 

Ce que tu dis en fait, c'est que ce n'est pas réentrant ! :D
 
Le coup de la classe avec variables membre revient à gérer un contexte (une struct) unique au thread. Au final, si tu veux des éléments communs à plusieurs thread il n'y a que 2 cas de figure :  
 
1. Non-réentrant
Il faut gérer un mutex d'accès à la ressource (sur la fonction ou la variable au choix)
 
2. Réentrant
Avoir les variables de calculs dans une zone mémoire "réservée" au thread appelant. Typiquement, la pile CàD les variables locales et le passage de paramètres.


Message édité par TNZ le 24-08-2006 à 18:07:07
n°1430921
Fouge
Posté le 24-08-2006 à 18:17:28  profilanswer
 

Ok, donc :
- soit j'utilise les mutex, ce qui signifira je suppose, qu'il y aura des "temps mort".
- soit la réentrance, en utilisant l'une des 2 méthodes que j'ai évoqué.
- soit j'ai rien compris à ce que tu m'as dit :D

n°1431133
tbp
Posté le 25-08-2006 à 06:55:34  profilanswer
 

Il y a d'autres options, en fait c'est un chouya plus compliqué.
 
D'une part il y a la découpe logique, partiellement imputable au langage. Pour faire bref, les "globales" requierent un arbitrage. On peut, par vague ordre décroissant de coût et croissant de siouxerie, soit faire appel à l'OS - les fameux semaphore/mutex/etc - mais c'est couteux surtout en cas de contention et ça implique le scheduler, soit regler soi-meme l'exlusion par exemple avec des spinlocks, soit utiliser des structures lock-free ou mieux wait-free, ou encore assurer la coherence par l'emploi de primitives atomiques - au sens large. Les deux dernieres options se recoupent et peuvent etre particulierement délicates à mettre en oeuvre :)
 
Mais il n'y a pas qu'une distinction "logique", sur une machine NUMA - disons une babasse avec plusieurs processeurs AMD - il y a effectivement une mémoire locale. Il est donc d'autant plus important de faire attention à la localité. La pile, même sur un OS moisis comme xp, est allouée localement. Après, ça devient plus délicat; une des recettes est sinon d'utiliser VirtualAlloc et/ou de toucher la mémoire à chaque page. Ou les TLS, mais c'est bancal.
 
Ce que je viens d'écrire n'est pas exhaustif mais devrait permettre qques recherches fructueuses sur google.

n°1431181
TNZ
Ryzen 9 5950X powered ...
Posté le 25-08-2006 à 09:32:44  profilanswer
 

Fouge » t'as tout compris :)

n°1431194
Fouge
Posté le 25-08-2006 à 09:47:18  profilanswer
 

tbp> Ok, là ça dépasse mes compétences mais j'avais jeter un oeil, j'vais sans doute apprendre des choses interessantes.
 
Et merci à vous 2 :jap:

n°1926214
iglance7
Posté le 23-09-2009 à 17:59:48  profilanswer
 

j'ai eu le même souci mais avec une fonction "non thread-safe", c à dire une fonction non réentrante. il s'agit de la fonction avcodec_open() de libavcodec (projet FFmpeg). je voulais développer une application capable de décoder deux flux vidéo en même temps (deux threads séparés).  
 
Le problème est que l'appel a cet fonction (avcodec_open) pose des problèmes (même avec le mécanisme de l'exclusion mutuelle ça ne fonctionne pas).
 
pour tester vraiment est-ce-que le probleme viens de cette fonction, j'ai séparer les deux threads dans deux programme principaux séparés : Thread1 dans le programme 1, et Thread 2 dans P2. j'ai lancé les deux programme Un après l'autre. le Premier s'exécute bien, le deuxième genère des messages d'erreur prouvenant de la bibliothèque qui englobe la fonction avcodec_open.
 
Etant tt a fait conscient que la modéfication d'une tel fonction de décodage nécessite de revoir tt le fonctionnement de la bibliothèque, c ki est impossible avec le manque de temps que j'ai et mes capacités limitées en C.
 
une idée ou un commentaire de votre part serais sans doute constructif et  très intéressant.  

mood
Publicité
Posté le 23-09-2009 à 17:59:48  profilanswer
 

n°1926216
tbp
Posté le 23-09-2009 à 18:15:48  profilanswer
 

Moche. C'est moche. Et à problème moche, solution moche (mochons nous, donc; ok je sors).
Au lieu de threads, utilisez des process+IPC (ou sur un OS digne de ce nom, clone avec les flags qui vont bien); en mappant les données ça ne devrait pas être trop pénalisant, sauf à ce que vous ayez besoin de merger ce que est produit par exemple (vs simplement écrire directement ou il faut).

n°1926249
Joel F
Real men use unique_ptr
Posté le 23-09-2009 à 22:23:49  profilanswer
 

le vrai probleme c'ets d'avoir des fonctions de thread non reentrantes, pas d'utiliser des thread.

n°1926267
tbp
Posté le 23-09-2009 à 23:08:13  profilanswer
 

Une fois isolé, disons dans un process, on se tamponne de l'absence de reentrance; pour rappel iglance7 ne peut/veut pas toucher à la bibliothèque fautive.

n°1926351
bjone
Insert booze to continue
Posté le 24-09-2009 à 11:54:48  profilanswer
 

J'ai eu le même problème avec une bibliothèque de décomposition convexe de géométrie (pour avoir des petites enveloppes convexes de collision pour un moteur physique), j'ai fait comme tbp, j'ai fait un process externe + memmap.

n°1926373
Joel F
Real men use unique_ptr
Posté le 24-09-2009 à 13:42:43  profilanswer
 

tbp: OK j'avais pas vu ce detail. A ce moment oui, process etc

n°1926517
Fouge
Posté le 24-09-2009 à 21:11:10  profilanswer
 

Vu que j'ai toujours mon flag sur ce topic, je vous donne la solution que j'ai finalement adopté pour mon problème. La DLL en question, je l'ai dupliqué (autant de fichier que de thread) et chacune était chargée dynamiquement par un thread. Du coup, chaque thread accède à un espace mémoire différent et tout se passe bien malgré les variables globales.
C'était de loin la solution la plus simple et la plus rapide, modifier la librairie n'était pas une solution raisonnable (en terme de temps passé).


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  gestion des variables dans une dll multithread ?

 

Sujets relatifs
Du nom des variables...pb gestion reception et envoie sur un xterm
Variables accessibles dans plusieurs fichiersGestion de lévenement clavier
variables de sessionRecuperez des noms de dossier dans des variables
Gestion des sprites avec ImageList en Delphi ?Gestion de la mémoire en delphi?
Gestion des GIF et/ou des PNG sous vb.net 
Plus de sujets relatifs à : gestion des variables dans une dll multithread ?


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR