Oui désolé pas encore le réflexe de donner mon architecture, je code pour windows comme on peut le deviner avec l'appel à Sleep().
Oui désolé pas encore le réflexe de donner mon architecture, je code pour windows comme on peut le deviner avec l'appel à Sleep().
c'est drôle on dirait que c'est ta seule façon de dire au gensEnvoyé par Charlemagne
"j'ai raison et je vous emmerde"
Envoyé par Charlemagne
Ben non, on ne parle pas du même rand() là.Envoyé par Charlemagne
- Toi, tu parles du rand() POSIX, qui ne RISQUE PAS de donner la même valeur pour les deux threads, justement parce qu'il n'est pas thread-safe.
- Nous, on parle du rand() Windows, CELUI QUI DONNE LE PROBLÈME DU P.O.
Donc, c'est toi qui es à côté de la plaque.
Ce qui confirme que rand() en multithread est dépendant de l'architecture, puisque le C standard n'a pas de notion de multithread.
Et donc, SOUS L'ARCHITECTURE DE MICROSOFT, rand() est thread-safe.
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Charlemagne peut être que sous POSIX ca marche pas comme ça.
Mais alors ce problème n'arriverait jamais. Donc si le P.O. a ce problème, il est sous autre chose que POSIX. Tu n'as qu'a essayer sur POSIX tu verras que les valeurs ne seront pas les mêmes.
Pour essayer de comprendre le problème, j'ai fais le code suivant:
Et voilà un example du fichier que j'obtiens:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 #include "windows.h" #include <time.h> #include <fstream> using namespace std; std::ofstream file; int hasard(int min, int max) { return (int) (min + ((float) rand() / RAND_MAX * (max - min + 1))); } DWORD WINAPI ThreadProc1( LPVOID lpParam ) { int st = 0; for (int i=0; i<10; i++) { st = hasard(100,1000); file << "t1:" << st << endl; Sleep(st); } return 0; } DWORD WINAPI ThreadProc2( LPVOID lpParam ) { int st = 0; for (int i=0; i<10; i++) { st = hasard(100,1000); file << "t2:" << st << endl; Sleep(st); } return 0; } int main(int argc, char* argv[]) { HANDLE hThread[2]; DWORD dwThread1Id; DWORD dwThread2Id; file.open("c:/temp/test.txt"); // create thread 1 hThread[0] = CreateThread( NULL, 0, ThreadProc1, NULL, 0, &dwThread1Id); // create thread 2 hThread[1] = CreateThread( NULL, 0, ThreadProc2, NULL, 0, &dwThread2Id); WaitForMultipleObjects(2, hThread, TRUE, INFINITE); file.close(); return 0; }
J'ai ensuite essayé de mettre des srand(time(NULL)) un peu de partout, mais ça n'a rien changét1:101
t2:101
t1:607
t2:607
t1:274
t2:274
t1:828
t2:828
t1:627
t2:627
t1:532
t2:532
t1:415
t2:415
t1:907
t2:907
t1:841
t2:841
t1:772
t2:772![]()
Merci pour cette précision r0d car j'ai la même sortie pour mon code.
la ca marche.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 #include "windows.h" #include <iostream> #include <time.h> #include <fstream> using namespace std; int hasard(int min, int max) { return (int) (min + ((float) rand() / RAND_MAX * (max - min + 1))); } DWORD WINAPI ThreadProc1( LPVOID lpParam ) { srand(time(NULL)); int st = 0; for (int i=0; i<10; i++) { st = hasard(100,1000); cout << "t1:" << st << endl; Sleep(st); } return 0; } DWORD WINAPI ThreadProc2( LPVOID lpParam ) { srand(time(NULL) + 10); int st = 0; for (int i=0; i<10; i++) { st = hasard(100,1000); cout << "t2:" << st << endl; Sleep(st); } return 0; } int main(int argc, char* argv[]) { HANDLE thread1; HANDLE thread2; DWORD dwThread1Id; DWORD dwThread2Id; // create thread 1 thread1 = CreateThread( NULL, 0, ThreadProc1, NULL, 0, &dwThread1Id); // create thread 2 thread2 = CreateThread( NULL, 0, ThreadProc2, NULL, 0, &dwThread2Id); cin.get(); return 0; }
Un appel à srand(time(NULL)), et 1 à srand(time(NULL) + 10)
Je viens de trouver une solution. Je ne sais pas si elle est vraiment bonne, mais elle fonctionne. Elle consiste à modifier la graine (seed) des srand:
edit: grilled
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 DWORD WINAPI ThreadProc1( LPVOID lpParam ) { srand(10); int st = 0; for (int i=0; i<10; i++) { st = hasard(100,1000); file << "t1:" << st << endl; Sleep(st); } return 0; } DWORD WINAPI ThreadProc2( LPVOID lpParam ) { srand(100); int st = 0; for (int i=0; i<10; i++) { st = hasard(100,1000); file << "t2:" << st << endl; Sleep(st); } return 0; }![]()
Si tout s'exécute dans la même seconde, srand(time(NULL)) ne changera rien.
À ce moment-là, un srand(GetCurrentThreadId()) serait plus intéressant.
Ou alors, un srand(GetCurrentThreadId() ^ rand()) pour profiter de la graine courante, qui elle, peut avoir été obtenue par srand(time(NULL)).
Edit: Mince, double-grillé.
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Merci messieurs 2 bonnes réponses à 2 min d'intervalle c'est pas mal.
Je vais tester tout ça avant de marquer le poste comme "résolu".
Merci encore !
Envoyé par Mongaulois
![]()
par contre on sait maintenant grace a "moulins à vent" que ça marchera que sous windows et donc pas portable.
Aprés je croit que boost as ce qu'il faut pour les nombre aleatoire (a verifier)
Edit: Ca marchera toujours sous posix, même si la fonction n'est pas thread-safe.
Au fait : Quelqu'un a testé ceci, sous Windows ?
(oui, j'ai la flemme).
Envoyé par Médinoc
PS: Tiens, bizarrement, Charlot se tait dès qu'on lui montre qu'il est en tort et qu'il répond à côté. On n'a jamais "nié l'existence de \"races\" sous POSIX", on a seulement dit qu'on n'était pas sous POSIX...
À la prochaine, Don Quichotte!
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
On ignorait le système
Si Windows n'utilise pas de variable statique pour son rand() (jusqu'à preuve du contraire j'en doute fort, car Windows réimplémente les fonctions standard) c'est peut-être thread-safe.
Si il compile son programme sous d'autres systèmes, les données aléatoires seront faussées...
Je dis depuis le départ qu'utiliser stand n'est pas suffisant pour garantir des suites aléatoires indépendantes. (tu remarqueras Médinoc "des SUITES")
Sur d'autres systèmes, c'est vrai qu'il y a une variable statique, donc les données aléatoires sont faussées mais pas identiques.
Ben non, on n'ignorait pas le système, car le multithread, ça dépend du système, et le comportement observé dépendait lui-même du système.Envoyé par Charlemagne
Et dans la version Microsoft, il y a probablement une variable statique, mais dans du thread-local storage (TLS), qui peut être utilisé statiquement (avec certaines restrictions).
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
De plus, invoquer la documentation POSIX, ce n'est pas "ignorer le système" : C'est supposer un système POSIX...![]()
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
"Sur d'autres système": pour Windows t'en sais rien (moi non plus d'ailleurs)Envoyé par coyotte507
"mais pas identiques": 't'en sais rien, et puis identique à quoi (entres elles, d'un thread à l'autre...)
"les données aléatoires sont faussées" je ne dis rien d'autre de puis le début!
"probablement"= Tu n'en sais rienEnvoyé par Médinoc
Non, j'invoquais un exemple de mes propos avec une argumentation.Envoyé par Medinoc
C'est mieux que ton "probablement" laché en l'air...
Ce n'est pas le comportement qu'on peut obtenir avec une suite partagée, sauf dans des cas très, très improbable de race conditions spécifiques répétées pour chaque nombre. La probabilité que ça arrive diminue exponentiellement à mesure que la suite s'allonge."mais pas identiques": 't'en sais rien
Ce n'est pas spécifiquement documenté dans cette fonction-là, mais ça l'est dans d'autres, comme strtok(), qui, dans l'implémentation Microsoft, est thread-safe mais pas réentrante :"probablement"= Tu n'en sais rien
De plus, le fait que la graine aléatoire courante (la séquence, quoi) soit locale à un thread est la seule explication compatible avec les comportements observés, et la plus probable connaissant les habitudes de Microsoft.Each function uses a static variable for parsing the string into tokens. If multiple or simultaneous calls are made to the same function, a high potential for data corruption and inaccurate results exists. Therefore, do not attempt to call the same function simultaneously for different strings and be aware of calling one of these functions from within a loop where another routine may be called that uses the same function. However, calling this function simultaneously from multiple threads does not have undesirable effects.
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Et donc, si y'a bien une variable statique (c'est plus que probable pour Windows également) , les suites sont faussées. Je n'en dis pas plus (tout comme la doc POSIX)
Alors que pour l'instant personne ne trouve ne doc sur le sujet? Faire confiance à Microsoft ?! c'est un autre débas!la plus probable connaissant les habitudes de Microsoft.
Partager