Last active
October 28, 2016 16:54
-
-
Save justheuristic/177467f866cd4f8b4a7b8150a47a5953 to your computer and use it in GitHub Desktop.
Parallel minibatch iterator for tensorflow and theano
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| ## What is it? | |
| # mostly from http://stackoverflow.com/questions/7323664/python-generator-pre-fetch | |
| The only parameter here is | |
| """ | |
| ###background generator (from your generator) | |
| import threading | |
| import sys | |
| if sys.version_info >= (3, 0): | |
| import queue as Queue | |
| else: | |
| import Queue | |
| class BackgroundGenerator(threading.Thread): | |
| def __init__(self, generator, max_prefetch=1): | |
| """ | |
| This function transforms generator into a background-thead generator. | |
| :param generator: generator or genexp or any | |
| It can be used with any minibatch generator. | |
| It is quite lightweight, but not entirely weightless. | |
| Using global variables inside generator is not recommended (may rise GIL and zero-out the benefit of having a background thread.) | |
| The ideal use case is when everything it requires is store inside it and everything it outputs is passed through queue. | |
| There's no restriction on reading/writing files or retrieving URLs [or whatever] wlilst iterating. | |
| :param max_prefetch: defines, how many iterations (at most) can background generator keep stored at any moment of time. | |
| Whenever there's already max_prefetch batches stored in queue, the background process will halt until one of these batches is dequeued. | |
| !Default max_prefetch=1 is okay unless you deal with some weird file IO in your generator! | |
| Setting max_prefetch to -1 lets it store as many batches as it can, which will work slightly (if any) faster, but will require storing | |
| all batches in memory. If you use infinite generator with max_prefetch=-1, it will exceed the RAM size unless dequeued quickly enough. | |
| """ | |
| threading.Thread.__init__(self) | |
| self.queue = Queue.Queue(max_prefetch) | |
| self.generator = generator | |
| self.daemon = True | |
| self.start() | |
| def run(self): | |
| for item in self.generator: | |
| self.queue.put(item) | |
| self.queue.put(None) | |
| def next(self): | |
| next_item = self.queue.get() | |
| if next_item is None: | |
| raise StopIteration | |
| return next_item | |
| # Python 3 compatibility | |
| def __next__(self): | |
| return self.next() | |
| def __iter__(self): | |
| return self | |
| #decorator | |
| class background: | |
| def __init__(self,max_prefetch=1): | |
| self.max_prefetch = max_prefetch | |
| def __call__(self,gen): | |
| def bg_generator(*args,**kwargs): | |
| return BackgroundGenerator(gen(*args,**kwargs)) | |
| return bg_generator | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment