Logo ROOT   6.08/07
Reference Guide
DataLoader.h
Go to the documentation of this file.
1 // @(#)root/tmva/tmva/dnn:$Id$
2 // Author: Simon Pfreundschuh 08/08/16
3 
4 /*************************************************************************
5  * Copyright (C) 2016, Simon Pfreundschuh *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /////////////////////////////////////////////////////////////////////
13 // Generic data loader for neural network input data. Provides a //
14 // high level abstraction for the transfer of training data to the //
15 // device. //
16 /////////////////////////////////////////////////////////////////////
17 
18 #ifndef TMVA_DNN_DATALOADER
19 #define TMVA_DNN_DATALOADER
20 
21 #include "TMatrix.h"
22 #include <vector>
23 #include <iostream>
24 
25 #include "TMVA/Event.h"
26 
27 namespace TMVA {
28 namespace DNN {
29 
30 //
31 // Input Data Types
32 //______________________________________________________________________________
33 using MatrixInput_t = std::pair<const TMatrixT<Double_t> &,
35 using TMVAInput_t = std::vector<Event*>;
36 
37 using IndexIterator_t = typename std::vector<size_t>::iterator;
38 
39 /** TBatch
40  *
41  * Class representing training batches consisting of a matrix of input data
42  * and a matrix of output data. The input and output data can be accessed using
43  * the GetInput() and GetOutput() member functions.
44  *
45  * \tparam AArchitecture The underlying architecture.
46  */
47 //______________________________________________________________________________
48 template <typename AArchitecture>
49 class TBatch
50 {
51 private:
52 
53  using Matrix_t = typename AArchitecture::Matrix_t;
54 
57 
58 public:
59 
60  TBatch(Matrix_t &, Matrix_t &);
61  TBatch(const TBatch &) = default;
62  TBatch( TBatch &&) = default;
63  TBatch & operator=(const TBatch &) = default;
64  TBatch & operator=( TBatch &&) = default;
65 
66  /** Return the matrix representing the input data. */
68  /** Return the matrix representing the output data. */
70 };
71 
72 template<typename Data_t, typename AArchitecture> class TDataLoader;
73 
74 /** TBatchIterator
75  *
76  * Simple iterator class for the iterations over the training batches in
77  * a given data set represented by a TDataLoader object.
78  *
79  * \tparam AData The input data type.
80  * \tparam AArchitecture The underlying architecture type.
81  */
82 template<typename Data_t, typename AArchitecture>
84 {
85 private:
86 
88  size_t fBatchIndex;
89 
90 public:
91 
92 TBatchIterator(TDataLoader<Data_t, AArchitecture> & dataLoader, size_t index = 0)
93 : fDataLoader(dataLoader), fBatchIndex(index)
94 {
95  // Nothing to do here.
96 }
97 
98  TBatch<AArchitecture> operator*() {return fDataLoader.GetBatch();}
99  TBatchIterator operator++() {fBatchIndex++; return *this;}
100  bool operator!=(const TBatchIterator & other) {
101  return fBatchIndex != other.fBatchIndex;
102  }
103 };
104 
105 /** TDataLoader
106  *
107  * Service class managing the streaming of the training data from the input data
108  * type to the accelerator device or the CPU. A TDataLoader object manages a number
109  * of host and device buffer pairs that are used in a round-robin manner for the
110  * transfer of batches to the device.
111  *
112  * Each TDataLoader object has an associated batch size and a number of total
113  * samples in the dataset. One epoch is the number of buffers required to transfer
114  * the complete training set. Using the begin() and end() member functions allows
115  * the user to iterate over the batches in one epoch.
116  *
117  * \tparam AData The input data type.
118  * \tparam AArchitecture The achitecture class of the underlying architecture.
119  */
120 template<typename Data_t, typename AArchitecture>
121 class TDataLoader
122 {
123 private:
124 
125  using HostBuffer_t = typename AArchitecture::HostBuffer_t;
126  using DeviceBuffer_t = typename AArchitecture::DeviceBuffer_t;
127  using Matrix_t = typename AArchitecture::Matrix_t;
129 
130  const Data_t & fData;
131 
132  size_t fNSamples;
133  size_t fBatchSize;
136  size_t fBatchIndex;
137 
138  size_t fNStreams; ///< Number of buffer pairs.
139  std::vector<DeviceBuffer_t> fDeviceBuffers;
140  std::vector<HostBuffer_t> fHostBuffers;
141 
142  std::vector<size_t> fSampleIndices; ///< Ordering of the samples in the epoch.
143 
144 public:
145 
146  TDataLoader(const Data_t & data, size_t nSamples, size_t batchSize,
147  size_t nInputFeatures, size_t nOutputFeatures, size_t nStreams = 1);
148  TDataLoader(const TDataLoader &) = default;
149  TDataLoader( TDataLoader &&) = default;
150  TDataLoader & operator=(const TDataLoader &) = default;
151  TDataLoader & operator=( TDataLoader &&) = default;
152 
153  /** Copy input matrix into the given host buffer. Function to be specialized by
154  * the architecture-specific backend. */
155  void CopyInput(HostBuffer_t &buffer, IndexIterator_t begin, size_t batchSize);
156  /** Copy output matrix into the given host buffer. Function to be specialized
157  * by the architecture-spcific backend. */
158  void CopyOutput(HostBuffer_t &buffer, IndexIterator_t begin, size_t batchSize);
159 
162  {
163  return TBatchIterator<Data_t, AArchitecture>(*this, fNSamples / fBatchSize);
164  }
165 
166  /** Shuffle the order of the samples in the batch. The shuffling is indirect,
167  * i.e. only the indices are shuffled. No input data is moved by this
168  * routine. */
169  void Shuffle();
170 
171  /** Return the next batch from the training set. The TDataLoader object
172  * keeps an internal counter that cycles over the batches in the training
173  * set. */
174  TBatch<AArchitecture> GetBatch();
175 
176 };
177 
178 //
179 // TBatch Class.
180 //______________________________________________________________________________
181 template<typename AArchitecture>
182 TBatch<AArchitecture>::TBatch(Matrix_t & inputMatrix, Matrix_t & outputMatrix)
183  : fInputMatrix(inputMatrix), fOutputMatrix(outputMatrix)
184 {
185  // Nothing to do here.
186 }
187 
188 //
189 // TDataLoader Class.
190 //______________________________________________________________________________
191 template<typename Data_t, typename AArchitecture>
193  const Data_t & data, size_t nSamples, size_t batchSize,
194  size_t nInputFeatures, size_t nOutputFeatures, size_t nStreams)
195  : fData(data), fNSamples(nSamples), fBatchSize(batchSize),
196  fNInputFeatures(nInputFeatures), fNOutputFeatures(nOutputFeatures),
197  fBatchIndex(0), fNStreams(nStreams), fDeviceBuffers(), fHostBuffers(),
198  fSampleIndices()
199 {
200  size_t inputMatrixSize = fBatchSize * fNInputFeatures;
201  size_t outputMatrixSize = fBatchSize * fNOutputFeatures;
202 
203  for (size_t i = 0; i < fNStreams; i++)
204  {
205  fHostBuffers.push_back(HostBuffer_t(inputMatrixSize + outputMatrixSize));
206  fDeviceBuffers.push_back(DeviceBuffer_t(inputMatrixSize + outputMatrixSize));
207  }
208 
209  fSampleIndices.reserve(fNSamples);
210  for (size_t i = 0; i < fNSamples; i++) {
211  fSampleIndices.push_back(i);
212  }
213 }
214 
215 //______________________________________________________________________________
216 template<typename Data_t, typename AArchitecture>
218 {
219  fBatchIndex %= (fNSamples / fBatchSize); // Cycle through samples.
220 
221 
222  size_t inputMatrixSize = fBatchSize * fNInputFeatures;
223  size_t outputMatrixSize = fBatchSize * fNOutputFeatures;
224 
225  size_t streamIndex = fBatchIndex % fNStreams;
226  HostBuffer_t & hostBuffer = fHostBuffers[streamIndex];
227  DeviceBuffer_t & deviceBuffer = fDeviceBuffers[streamIndex];
228 
229  HostBuffer_t inputHostBuffer = hostBuffer.GetSubBuffer(0, inputMatrixSize);
230  HostBuffer_t outputHostBuffer = hostBuffer.GetSubBuffer(inputMatrixSize,
231  outputMatrixSize);
232 
233  DeviceBuffer_t inputDeviceBuffer = deviceBuffer.GetSubBuffer(0, inputMatrixSize);
234  DeviceBuffer_t outputDeviceBuffer = deviceBuffer.GetSubBuffer(inputMatrixSize,
235  outputMatrixSize);
236  size_t sampleIndex = fBatchIndex * fBatchSize;
237  IndexIterator_t sampleIndexIterator = fSampleIndices.begin() + sampleIndex;
238 
239  CopyInput(inputHostBuffer, sampleIndexIterator, fBatchSize);
240  CopyOutput(outputHostBuffer, sampleIndexIterator, fBatchSize);
241 
242  deviceBuffer.CopyFrom(hostBuffer);
243  Matrix_t inputMatrix(inputDeviceBuffer, fBatchSize, fNInputFeatures);
244  Matrix_t outputMatrix(outputDeviceBuffer, fBatchSize, fNOutputFeatures);
245 
246  fBatchIndex++;
247  return TBatch<AArchitecture>(inputMatrix, outputMatrix);
248 }
249 
250 //______________________________________________________________________________
251 template<typename Data_t, typename AArchitecture>
253 {
254  std::random_shuffle(fSampleIndices.begin(), fSampleIndices.end());
255 }
256 
257 } // namespace DNN
258 } // namespace TMVA
259 
260 #endif
TBatch< AArchitecture > operator*()
Definition: DataLoader.h:98
Matrix_t & GetInput()
Return the matrix representing the input data.
Definition: DataLoader.h:67
Matrix_t fOutputMatrix
Definition: DataLoader.h:56
void CopyOutput(HostBuffer_t &buffer, IndexIterator_t begin, size_t batchSize)
Copy output matrix into the given host buffer.
TBatch< AArchitecture > GetBatch()
Return the next batch from the training set.
Definition: DataLoader.h:217
const Data_t & fData
Definition: DataLoader.h:130
typename std::vector< size_t >::iterator IndexIterator_t
Definition: DataLoader.h:37
void CopyInput(HostBuffer_t &buffer, IndexIterator_t begin, size_t batchSize)
Copy input matrix into the given host buffer.
size_t fNStreams
Number of buffer pairs.
Definition: DataLoader.h:138
bool operator!=(const TBatchIterator &other)
Definition: DataLoader.h:100
TDataLoader< Data_t, AArchitecture > & fDataLoader
Definition: DataLoader.h:87
typename AArchitecture::Matrix_t Matrix_t
Definition: DataLoader.h:127
TBatchIterator operator++()
Definition: DataLoader.h:99
BatchIterator_t begin()
Definition: DataLoader.h:160
TBatchIterator(TDataLoader< Data_t, AArchitecture > &dataLoader, size_t index=0)
Definition: DataLoader.h:92
typename AArchitecture::DeviceBuffer_t DeviceBuffer_t
Definition: DataLoader.h:126
Matrix_t fInputMatrix
Definition: DataLoader.h:55
TBatch(Matrix_t &, Matrix_t &)
Definition: DataLoader.h:182
std::vector< Event * > TMVAInput_t
Definition: DataLoader.h:35
typename AArchitecture::Matrix_t Matrix_t
Definition: DataLoader.h:53
typename AArchitecture::HostBuffer_t HostBuffer_t
Definition: DataLoader.h:125
void Shuffle()
Shuffle the order of the samples in the batch.
Definition: DataLoader.h:252
TDataLoader.
Definition: DataLoader.h:72
TBatch & operator=(const TBatch &)=default
TDataLoader(const Data_t &data, size_t nSamples, size_t batchSize, size_t nInputFeatures, size_t nOutputFeatures, size_t nStreams=1)
Definition: DataLoader.h:192
std::vector< size_t > fSampleIndices
Ordering of the samples in the epoch.
Definition: DataLoader.h:142
Abstract ClassifierFactory template that handles arbitrary types.
std::vector< DeviceBuffer_t > fDeviceBuffers
Definition: DataLoader.h:139
std::vector< HostBuffer_t > fHostBuffers
Definition: DataLoader.h:140
Matrix_t & GetOutput()
Return the matrix representing the output data.
Definition: DataLoader.h:69
BatchIterator_t end()
Definition: DataLoader.h:161
TBatchIterator.
Definition: DataLoader.h:83
std::pair< const TMatrixT< Double_t > &, const TMatrixT< Double_t > & > MatrixInput_t
Definition: DataLoader.h:34