title: Getting some form of keras multi-processing/threading to work on Windows
body: <p>In order to speed up data augmentation for training a neural network, I am trying to have some form of parallel processing for feeding my GPU with data. At the moment the limitation is how fast I generate augmented data, not how fast the GPU trains the network.</p>
  
  <p>If I try to use <code>multiprocessing=True</code> with a generator, I get the following error with keras 2.2.0 in Python 3.6.6 under Windows 10 (v1083) 64-bit:</p>
  
  <blockquote>
    <p>ValueError: Using a generator with <code>use_multiprocessing=True</code> is not
    supported on Windows (no marshalling of generators across process
    boundaries). Instead, use single thread/process or multithreading.</p>
  </blockquote>
  
  <p>I found e.g. <a href="https://github.com/matterport/Mask_RCNN/issues/13" rel="noreferrer">the following</a> on GitHub so this is an expected behavior with keras under Windows. That link seemed to suggest moving to a sequence instead of a generator (even though the error message seems to suggest to use multithreading, but I also could not figure out how to use multithreading with keras instead of multi-processing - I may have overlooked it in the documentation, but I just did not find it). So, I used the the code below (modifying an example using a sequence), but that also achieves no speed-up or in the variant with <code>use_multiprocessing=True</code> just freezes up.</p>
  
  <p>Am I missing something obvious here for how to get some form of parallel generator going? </p>
  
  <p>Minimal (non-)working example:</p>
  
  <pre><code>from keras.utils import Sequence
  from keras.models import Sequential
  from keras.layers import Dense
  from keras.utils import to_categorical
  import numpy as np
  
  class DummySequence(Sequence):
  
      def __init__(self, x_set, y_set, batch_size):
          self.x, self.y = x_set, y_set
          self.batch_size = batch_size
  
      def __len__(self):
          return int(np.ceil(len(self.x) / float(self.batch_size)))
  
      def __getitem__(self, idx):        
          batch_x = self.x[idx * self.batch_size:(idx + 1) * self.batch_size]
          batch_y = self.y[idx * self.batch_size:(idx + 1) * self.batch_size]
  
          return np.array(batch_x), np.array(batch_y)
  
  
  
  x = np.random.random((100, 3))
  y = to_categorical(np.random.random(100) &gt; .5).astype(int)
  
  seq = DummySequence(x, y, 10)
  
  model = Sequential()
  model.add(Dense(32, input_dim=3))
  model.add(Dense(2, activation='softmax'))
  model.compile(optimizer='rmsprop',
                loss='categorical_crossentropy',
                metrics=['accuracy'])
  
  print('single worker')
  model.fit_generator(generator=seq, 
                      steps_per_epoch = 100,
                      epochs = 2, 
                      verbose=2,
                      workers=1)
  print('achieves no speed-up')
  model.fit_generator(generator=seq, 
                      steps_per_epoch = 100,
                      epochs = 2, 
                      verbose=2,
                      workers=6,
                      use_multiprocessing=False)
  print('Does not run')
  model.fit_generator(generator=seq, 
                      steps_per_epoch = 100,
                      epochs = 2, 
                      verbose=2,
                      workers=6,
                      use_multiprocessing=True)
  </code></pre>