Skip to content

Instantly share code, notes, and snippets.

@justheuristic
Last active October 28, 2016 16:54
Show Gist options
  • Select an option

  • Save justheuristic/177467f866cd4f8b4a7b8150a47a5953 to your computer and use it in GitHub Desktop.

Select an option

Save justheuristic/177467f866cd4f8b4a7b8150a47a5953 to your computer and use it in GitHub Desktop.
Parallel minibatch iterator for tensorflow and theano
"""
## 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
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment