Ticket UUID: | 416643 | |||
Title: | rand() has identical results in threads. | |||
Type: | Bug | Version: | obsolete: 8.4a2 | |
Submitter: | davygrvy | Created on: | 2001-04-17 11:27:49 | |
Subsystem: | 47. Bytecode Compiler | Assigned To: | msofer | |
Priority: | 5 Medium | Severity: | ||
Status: | Closed | Last Modified: | 2001-05-08 05:16:08 | |
Resolution: | Fixed | Closed By: | msofer | |
Closed on: | 2001-05-07 22:16:08 | |||
Description: |
This is having difficulty on windows. Isn't the c- runtime supposed to handle this situation just fine? I'm perplexed by this: package require Thread foreach a {1 2 3 4 5 6} { set threads($a) [thread::create { proc doit {} { puts [expr {rand()}] }; thread::wait }] } foreach a {1 2 3 4 5 6} { thread::send -async $threads($a) doit } foreach a {1 2 3 4 5 6} { thread::send -async $threads($a) thread::exit } C:\Program Files\Tcl\bin>tclsh84t % source test.tcl % 0.0541875106535 0.0541875106535 0.0541875106535 0.0541875106535 0.0541875106535 0.0541875106535 I really don't think this is a Tcl inherit to Tcl, but does show an interesting behavior. Changing the run to be syncronous got this: package require Thread foreach a {1 2 3 4 5 6} { thread::create { puts [expr {rand()}] } } % source test.tcl 0.11639496317 0.366838779471 0.366838779471 0.484234318363 0.609456226513 % 0.726851765405 The docs state "Each interpreter has it's own seed." on the expr man page, but I tend to disagree after seeing the above. Where's the seeding happening? Should Tcl_CreateInterp() do the seeding? | |||
User Comments: |
msofer added on 2001-05-08 05:16:08:
Logged In: YES user_id=148712 Patch committed. dgp added on 2001-04-30 01:35:18: Logged In: YES user_id=80530 The patch looks OK to me. I think I would add a more detailed explanation in the comment about why the Tcl_GetCurrentThread call is there, maybe even a link back to this bug report. I'm assigning this to the proper Category for final maintainer review and commit. davygrvy added on 2001-04-26 08:01:39: Logged In: YES user_id=7549 Don, I hand this to you. I can handle this from script anyways, so it's no rush. davygrvy added on 2001-04-21 05:36:17: Logged In: YES user_id=7549 This seems to work Ok, too. iPtr->randSeed = TclpGetClicks() ^ ((long) Tcl_GetCurrentThread() << ((TclpGetClicks() % 10) + 17)); davygrvy added on 2001-04-20 10:20:41: File Added - 5549: rand_patch.txt davygrvy added on 2001-04-20 08:49:36: Logged In: YES user_id=7549 Don, I'm happy with the attached patch. These are the results for me (on windows) running the first code snippit: source test2.tcl % 0.928865028046 0.515779082904 0.648316936404 0.315270977707 0.826455665671 0.931451399779 source test2.tcl % 0.878650014232 0.370051698 0.808093390804 0.0654099826074 0.547328303357 0.958690000679 source test2.tcl % 0.210988179879 0.774670734897 0.41666902854 0.185170308307 0.105992445772 0.954533711986 info patch 8.4a3 % If I remember correctly, Thread IDs on UNIX have smaller numbers then on windows and might not effectively shift TclpGetClicks deeply enough. I'll leave the math up someone more qualified than myself. davygrvy added on 2001-04-18 06:15:59: Logged In: YES user_id=7549 Say I do update and rebuild for the HEAD, and all threads do hit line 4087, tclExecute.c: iPtr->randSeed = TclpGetClicks(); and for the sake of discussion, TclpGetClicks() returns the exact same result for all threads running in parallel. Even with a higher resolution of the timer, the *possibility* for a same seed value still exists. Would it make sense to have the thread extension do this for me by pre-seeding so even if parallel threads call rand () at the exact same moment, the return will be different? dgp added on 2001-04-18 05:13:28: Logged In: YES user_id=80530 Ah. I see you report this on Windows. Do you still see this behavior using the latest CVS HEAD sources (8.4a3)? Since 8.4a2 was released, Kevin Kenny enhanced TclpGetTime to get much finer "clicks" resolution on Windows. That might take care of this. If you're really using 8.4a2, that rules out the new rand() code too, since it was added since then. dgp added on 2001-04-18 04:52:23: Logged In: YES user_id=80530 Since I just rewrote rand() for Tcl 8.4a2 and Tcl 8.3.3, I want to find out whether this is something new I broke or not. davygrvy added on 2001-04-18 04:49:03: Logged In: YES user_id=7549 I haven't checked 8.3.2 or 8.3.3, yet. It could be possible that all 6 threads hit this bit of code at the exact same time (line 4087, tclExecute.c): iPtr->randSeed = TclpGetClicks(); I leave this up to you guys. I'm not sure if this is really a "bug" or not. I can send all the threads a seed when I start them. I can get around the behavior in script. I don't know if this warrants a sluething. dgp added on 2001-04-18 03:07:37: Logged In: YES user_id=80530 Is this a new problem, or does it also exist in Tcl 8.3.2? Tcl has it's own rand() implementation -- it does not call a system rand() -- so this problem is a problem with Tcl. There is one seed per interp: iPtr->randSeed, and it is initialized in ExprRandFunc() in generic/tclExecute.c. davygrvy added on 2001-04-17 18:31:21: Logged In: YES user_id=7549 wait a sec... 2 of those in the syncronous test were identical. This is interesting :) |
Attachments:
- rand_patch.txt [download] added by davygrvy on 2001-04-20 10:20:40. [details]