-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Can't use cirq.Simulator() in a multiprocessing closure (unable to pickle) #3717
Comments
I agree this is an issue. However, I think a subtle problem with your solution of |
Yes, that's very important to point out. In my specific case, it works since I'm just using the |
Could you have each process create its own simulator instead of pickling one? Otherwise, maybe we extract the RNG from simulator itself and instead pass it explicitly into 'run' etc? Then each process can just create its own rng to use. |
I have a tiny bit of experience with this from having hit similar problems in the past. The Python I think the following covers the most common solutions:
In terms of what's viable for Cirq, it seems like (3) might not be an option because of the variety of computing backends that might be used by people running Cirq, so that would leave (1) or (2). Approach (2) is hacky but if the situation where the problem occurs is entirely wrapped up inside Cirq somewhere, and only in a single module, then maybe that wouldn't be too bad? Otherwise, (1) is some ways cleaner. There are not that many places in Cirq where A couple of concerns about (1) come to mind: first, users might end up using |
we could also change the constructor's default argument from |
You have to be a little bit careful because if you get a bunch of these simulators creating themselves at the same time in each process, they could happen to get seeded to the same state if they draw their seed from the current time. |
Did we give up on this problem? Just ran into it myself with |
You can generate a list of unique seeds in the main process and pass them zipped with circuits to the mapped worker function. That way each function call would have a unique seed to create its own simulator. |
It's still kindof annoying that you need to generate a bunch of random seeds in the case where you're not actually using any randomness, i.e. if you're calling |
When using python's
multiprocessing
, the function closure must be pickleable so that it can be shipped off to the subprocesses. This means you can't use lambdas or anything. A common workaround is to define a helper closure classFails! With the very cryptic "TypeError: can't pickle module objects" But I'm not pickleing a module object!! Well, after some digging and a hat tip to https://stackoverflow.com/a/59832602, we actually are. Our old friend
np.random
, which is the default random generator. A partial solution is to explicitly constructcirq.Simulator(seed=np.random.RandomState())
, but be very careful; see below.The text was updated successfully, but these errors were encountered: