-
Notifications
You must be signed in to change notification settings - Fork 80
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
Parallel uniform sampling #471
base: master
Are you sure you want to change the base?
Conversation
nestedsamplers classes can probably be removed at some point
Pull Request Test Coverage Report for Build 7952108689Details
💛 - Coveralls |
!!!! This is an excellent proposed change! Very interested to see how the other internal refactoring might also work. |
and unify it all in one class The only thing I had to disable is the 'custom sampler' test in test_misc
Thanks @joshspeagle |
The demonstration of this patch. The following uniform sampling of Eggbox with single bound 9490it [03:16, 48.25it/s, +1000 | bound: 999 | nc: 1 | ncall: 12943702 | eff(%): 0.081 | loglstar: -inf < 243.000 < inf | logz: 235.863 +/- 0.078 | dlogz: 0.000 > 0.100] And if I bump the number of threads to 36 , it takes 50 seconds. I.e. basically it scales properly, while previously uniform sampler basically didn't really scale with multiple threads. import numpy as np
import dynesty
import multiprocessing as mp
nlive = 1000
def loglike_egg(x):
logl = ((2 + np.cos(x[0] / 2) * np.cos(x[1] / 2))**5)
return logl
def prior_transform_egg(x):
return x * 10 * np.pi
LOGZ_TRUTH = 235.856
def test_bounds():
bound, sample = 'single', 'unif'
# stress test various boundaries
ndim = 2
rstate = np.random.default_rng(444)
with mp.Pool(4) as poo:
sampler = dynesty.NestedSampler(loglike_egg,
prior_transform_egg,
ndim,
nlive=nlive,
bound=bound,
sample=sample,
rstate=rstate,
pool=poo,
queue_size=4)
sampler.run_nested(dlogz=0.1, print_progress=True)
assert (abs(LOGZ_TRUTH - sampler.results.logz[-1])
< 5. * sampler.results.logzerr[-1])
if __name__ == '__main__':
test_bounds() |
rearrange sampler arguments to make them more logical
It would be great to have some review of this patch @joshspeagle if you have time, before the patch gets bigger. My current thinking is the patch is mostly positive with a few negatives listed below:
Among things I'd like to do, but I don't want to do in this patch: I think with this patch it's becoming easier to do #391. We already now can pack update_slice or update_rwalk in SliceSampler RWalkSampler objects and make sure that things like history dynesty/py/dynesty/nestedsamplers.py Line 145 in 3f10025
|
In Bilby, we rely on the custom sampler (see here), although I'd love to see this supported in dynesty. We mostly use this to allow additional data to be passed through the kwargs, specifically current live points. |
Thanks for the link @ColmTalbot. I think those interfaces will certainly break with this patch, which is I think unfortunate, but I think if we combine this change with the new sampler interface ( #391), hopefully it'll be worthwhile. What I need to implement the new way of sampling is to formalize the exact interface for those 'inner samplers' (rwalk/slice/uniform) It is clear each sampler needs the sample() interface as defined in sampling.py, |
This is a preliminary version of patch that enables parallel uniform sampling.
The idea is to get away from this propose/evolve for uniform distributions where evolve doesn't really do anything other than evaluate logl on a single pt, but instead make propose a no-op for uniform, and evolve() actually do the sampling inside the boundary till a satisfactory pt is found.
While implementing this I realized that after some changes all the different samplers in nestedsamplers.py may not need to be there as they do something very similar (but that's tbd).
ATM some tests fail, but I think that's fixable.
Also some class members had to be renamed. I.e. .bound attribute is really misleading in the classes as it was storing the list of all the historic bounds, so I renamed that to bound_list.