-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: x/exp/rand: add NewLockedSource #25988
Comments
CC @robpike |
This seems reasonable, but I'd like to hold off changing exp/rand's API too much until the various proposals about the future of the math/rand package are resolved. |
@robpike, I'd like to start contributing. Can you help me understand the above? It seems to me that EDIT: I'm worried the above sounds much more confrontational than intended. I'm genuinely trying to understand the process here so I can help. |
x/exp/rand was created as a possible replacement for math/rand for Go 2. As such, x/exp/rand is intended to provide the same API as math/rand. Changing the API of x/exp/rand complicates the decision of whether to use it as a replacement for math/rand. |
@ianlancetaylor that's a great explanation and it makes a lot of sense. Thank you. I'll point out, however, that there are already changes to the API in |
Makes sense, but my point about holding off still holds. The interface and some internals for math/rand have also changed lately, and I would like to bring exp/rand into sync before moving on with exp/rand. I'll plan to do that soon. |
Thanks @robpike. Is there anything I can do then to help you sync these packages and solidify their future direction? |
It is part of the point of exp/rand to not have to lock the source, by making it cheap enough to have lots of them and high enough quality not to worry about correlations between sources. Putting a NewLockedSource API in the package goes against the idea for the package's model. |
@robpike I've understood that that was a goal. I see how that makes it feasible to give a very large number of goroutines their own Consider, for instance, a discrete function such as the one below. This is already concurrency safe (but is at risk of some other code changing the seed) and is utilized concurrently by many, many goroutines.
Re-writing this to utilize the model you're proposing in
Neither of these is a good option and afaict, they're the only two options that the model you're proposing would give me. |
@krancour You can use a |
@thaustad I could. It might be slightly more efficient than writing my own wrapper around a That is to say, let's bring this back to my chief complaint about
My question is: Who doesn't want both of those? So whether using a This isn't about me not wanting to write a few extra lines of code. This is about eliminating surprising and dangerous behavior from the standard library. |
I see. At least you have a third option. I can't say I have had much use for both features. I usually need more than one random number and then I prefer a single lock for all of them. The It might be suprising, but I think it encourages better code. Novice Gophers has to understand how to access shared objects early on anyway. Another way to go is to remove |
Good point. And that's where your I do, however, stand by my assertion that there being no out-of-the-box option that is both concurrency safe and guaranteed not to be re-seeded by someone else is going to catch novice gophers unaware. I've been writing Go code for four years and when I first became aware of this, I was like, "Wut??"
⬆️So much ❤️ for that idea. As long as the seed automatically is initialized with something reasonable (like Unix time nanoseconds or something) that could work. The only downside I could see to that is it might sometimes be desirable to use a hard-coded seed to ensure determinism when using |
Since Rob said to hold off, marking this proposal-hold. |
Determinism for randomised analyses is a crucial attribute of any language that is used for these kinds of things. Go is used for these kinds of things, so removing the capacity to specify a seed is a non-starter. |
@kortschak I don't think the suggestion I was commenting on (the one you quoted) would have ruled out specifying any seed you want for a given source (e.g. at the time it is created). I think the suggestion had more to do with eliminating the avenue for potentially re-seeding a shared, package-level source, which leaves anyone who uses it vulnerable to the possibility that someone has reseeded using a constant value. |
I don't see how you can have one without the other. The PRNG |
If the shared package-level source were automatically seeded with a sensible (and not static) value, which could not be altered after the fact with a package-level function call, you could still do what you want to do (provide your own seed) by not using the package-level source and initializing you own source instead-- which is what you should already be doing now anyway if you care about never having the rug pulled out from under you. |
Yeah, you're right. |
@kortschak candid questions: how do you maintain determinism for randomised analyses in Go with randomised map iterations? I believe code that must be deterministic would need to ensure that no map iterations occur at all, anywhere (or go through great extent to remedy the randomness they induce). |
I removed the reference to time in the runtime here when I absolutely need to iterate over maps directly (when I'm debugging an issue that needs this), otherwise I sort a slice of the kv pairs (this is what is done for analyses where order of iteration matters). |
This related issue makes a case for
math/rand
exporting some implementation ofSource
that is concurrency safe.Pursuant to that, this change exports
LockedSource
fromgolang.org/x/exp/rand
. That seems like a nice start, however, withLockedSource
's attributes still being unexported and with there being no constructor-like function for instantiating a newLockedSource
, there remains no practical way to initialize variables of that type.I want to propose the addition of a new package-level function
NewLockedSource(seed uint64) Source
ingolang.org/x/exp/rand
.I'm happy to PR this myself if there's some consensus that this is a reasonable change.
The text was updated successfully, but these errors were encountered: