File indexing completed on 2025-01-18 10:10:57
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 #ifndef TMVA_DNN_TENSORDATALOADER
0028 #define TMVA_DNN_TENSORDATALOADER
0029
0030 #include "TMatrix.h"
0031 #include "TMVA/Event.h"
0032 #include <algorithm>
0033 #include <vector>
0034 #include <utility>
0035
0036 namespace TMVA {
0037 class DataSetInfo;
0038 namespace DNN {
0039
0040
0041
0042
0043 using TensorInput =
0044 std::tuple<const std::vector<TMatrixT<Double_t>> &, const TMatrixT<Double_t> &, const TMatrixT<Double_t> &>;
0045
0046 using TMVAInput_t = std::tuple<const std::vector<Event *> &, const DataSetInfo &>;
0047 using IndexIterator_t = typename std::vector<size_t>::iterator;
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 template <typename Architecture_t>
0059 class TTensorBatch {
0060 public:
0061 using Matrix_t = typename Architecture_t::Matrix_t;
0062 using Tensor_t = typename Architecture_t::Tensor_t;
0063
0064 private:
0065 Tensor_t fInputTensor;
0066 Matrix_t fOutputMatrix;
0067 Matrix_t fWeightMatrix;
0068
0069 public:
0070 TTensorBatch(Tensor_t &, Matrix_t &, Matrix_t &);
0071 TTensorBatch(const TTensorBatch &) = default;
0072 TTensorBatch(TTensorBatch &&) = default;
0073 TTensorBatch &operator=(const TTensorBatch &) = default;
0074 TTensorBatch &operator=(TTensorBatch &&) = default;
0075
0076
0077 Tensor_t &GetInput() { return fInputTensor; }
0078
0079 Matrix_t &GetOutput() { return fOutputMatrix; }
0080
0081 Matrix_t &GetWeights() { return fWeightMatrix; }
0082 };
0083
0084 template <typename Data_t, typename Architecture_t>
0085 class TTensorDataLoader;
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 template <typename Data_t, typename Architecture_t>
0096 class TTensorBatchIterator {
0097 private:
0098 TTensorDataLoader<Data_t, Architecture_t> &fTensorDataLoader;
0099 size_t fBatchIndex;
0100
0101 public:
0102 TTensorBatchIterator(TTensorDataLoader<Data_t, Architecture_t> &tensorDataLoader, size_t index = 0)
0103 : fTensorDataLoader(tensorDataLoader), fBatchIndex(index)
0104 {
0105
0106 }
0107
0108 TTensorBatch<Architecture_t> operator*() { return fTensorDataLoader.GetTensorBatch(); }
0109 TTensorBatchIterator operator++()
0110 {
0111 fBatchIndex++;
0112 return *this;
0113 }
0114 bool operator!=(const TTensorBatchIterator &other) { return fBatchIndex != other.fBatchIndex; }
0115 };
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132 template <typename Data_t, typename Architecture_t>
0133 class TTensorDataLoader {
0134 private:
0135 using HostBuffer_t = typename Architecture_t::HostBuffer_t;
0136 using DeviceBuffer_t = typename Architecture_t::DeviceBuffer_t;
0137 using Matrix_t = typename Architecture_t::Matrix_t;
0138 using Tensor_t = typename Architecture_t::Tensor_t;
0139 using Shape_t = typename Architecture_t::Tensor_t::Shape_t;
0140 using BatchIterator_t = TTensorBatchIterator<Data_t, Architecture_t>;
0141
0142 const Data_t &fData;
0143 size_t fNSamples;
0144 size_t fBatchSize;
0145 Shape_t fInputLayout;
0146 size_t fBatchDepth;
0147 size_t fBatchHeight;
0148 size_t fBatchWidth;
0149 size_t fNOutputFeatures;
0150 size_t fBatchIndex;
0151
0152
0153 size_t fNStreams;
0154 std::vector<DeviceBuffer_t> fDeviceBuffers;
0155 std::vector<HostBuffer_t> fHostBuffers;
0156
0157 std::vector<size_t> fSampleIndices;
0158
0159 public:
0160
0161 TTensorDataLoader(const Data_t &data, size_t nSamples, size_t batchSize, const Shape_t & inputLayout,
0162 const Shape_t & batchLayout, size_t nOutputFeatures, size_t nStreams = 1);
0163
0164 TTensorDataLoader(const TTensorDataLoader &) = default;
0165 TTensorDataLoader(TTensorDataLoader &&) = default;
0166 TTensorDataLoader &operator=(const TTensorDataLoader &) = default;
0167 TTensorDataLoader &operator=(TTensorDataLoader &&) = default;
0168
0169
0170
0171 void CopyTensorInput(HostBuffer_t &buffer, IndexIterator_t begin);
0172
0173
0174 void CopyTensorOutput(HostBuffer_t &buffer, IndexIterator_t begin);
0175
0176
0177 void CopyTensorWeights(HostBuffer_t &buffer, IndexIterator_t begin);
0178
0179 BatchIterator_t begin() { return TTensorBatchIterator<Data_t, Architecture_t>(*this); }
0180 BatchIterator_t end() { return TTensorBatchIterator<Data_t, Architecture_t>(*this, fNSamples / fBatchSize); }
0181
0182
0183
0184
0185 template<typename RNG>
0186 void Shuffle(RNG & rng);
0187
0188
0189
0190
0191 TTensorBatch<Architecture_t> GetTensorBatch();
0192 };
0193
0194
0195
0196
0197 template <typename Architecture_t>
0198 TTensorBatch<Architecture_t>::TTensorBatch(Tensor_t &inputTensor, Matrix_t &outputMatrix,
0199 Matrix_t &weightMatrix)
0200 : fInputTensor(inputTensor), fOutputMatrix(outputMatrix), fWeightMatrix(weightMatrix)
0201 {
0202
0203 }
0204
0205
0206
0207
0208 template <typename Data_t, typename Architecture_t>
0209 TTensorDataLoader<Data_t, Architecture_t>::TTensorDataLoader(const Data_t &data, size_t nSamples, size_t batchSize,
0210 const Shape_t & inputLayout, const Shape_t & batchLayout,
0211 size_t nOutputFeatures, size_t nStreams)
0212 : fData(data), fNSamples(nSamples), fBatchSize(batchSize), fInputLayout(inputLayout), fBatchDepth(batchLayout[0]), fBatchHeight(batchLayout[1]),
0213 fBatchWidth(batchLayout[2]), fNOutputFeatures(nOutputFeatures), fBatchIndex(0), fNStreams(nStreams), fDeviceBuffers(),
0214 fHostBuffers(), fSampleIndices()
0215 {
0216 size_t inputTensorSize = fBatchDepth * fBatchHeight * fBatchWidth;
0217 size_t outputMatrixSize = fBatchSize * fNOutputFeatures;
0218 size_t weightMatrixSize = fBatchSize;
0219
0220 for (size_t i = 0; i < fNStreams; i++) {
0221 fHostBuffers.push_back(HostBuffer_t(inputTensorSize + outputMatrixSize + weightMatrixSize));
0222 fDeviceBuffers.push_back(DeviceBuffer_t(inputTensorSize + outputMatrixSize + weightMatrixSize));
0223 }
0224
0225 fSampleIndices.reserve(fNSamples);
0226 for (size_t i = 0; i < fNSamples; i++) {
0227 fSampleIndices.push_back(i);
0228 }
0229 }
0230
0231
0232 template <typename Data_t, typename Architecture_t>
0233 TTensorBatch<Architecture_t> TTensorDataLoader<Data_t, Architecture_t>::GetTensorBatch()
0234 {
0235 fBatchIndex %= (fNSamples / fBatchSize);
0236
0237 size_t inputTensorSize = fBatchDepth * fBatchHeight * fBatchWidth;
0238 size_t outputMatrixSize = fBatchSize * fNOutputFeatures;
0239 size_t weightMatrixSize = fBatchSize;
0240
0241 size_t streamIndex = fBatchIndex % fNStreams;
0242 HostBuffer_t &hostBuffer = fHostBuffers[streamIndex];
0243 DeviceBuffer_t &deviceBuffer = fDeviceBuffers[streamIndex];
0244
0245 HostBuffer_t inputHostBuffer = hostBuffer.GetSubBuffer(0, inputTensorSize);
0246 HostBuffer_t outputHostBuffer = hostBuffer.GetSubBuffer(inputTensorSize, outputMatrixSize);
0247 HostBuffer_t weightHostBuffer = hostBuffer.GetSubBuffer(inputTensorSize + outputMatrixSize, weightMatrixSize);
0248
0249 DeviceBuffer_t inputDeviceBuffer = deviceBuffer.GetSubBuffer(0, inputTensorSize);
0250 DeviceBuffer_t outputDeviceBuffer = deviceBuffer.GetSubBuffer(inputTensorSize, outputMatrixSize);
0251 DeviceBuffer_t weightDeviceBuffer = deviceBuffer.GetSubBuffer(inputTensorSize + outputMatrixSize, weightMatrixSize);
0252
0253
0254
0255
0256
0257 size_t sampleIndex = fBatchIndex * fBatchSize;
0258 IndexIterator_t sampleIndexIterator = fSampleIndices.begin() + sampleIndex;
0259
0260 CopyTensorInput(inputHostBuffer, sampleIndexIterator);
0261 CopyTensorOutput(outputHostBuffer, sampleIndexIterator);
0262 CopyTensorWeights(weightHostBuffer, sampleIndexIterator);
0263
0264 deviceBuffer.CopyFrom(hostBuffer);
0265
0266 assert(fInputLayout.size() == 3);
0267 Tensor_t inputTensor = Architecture_t::CreateTensor( inputDeviceBuffer, fBatchSize, fInputLayout[0], fInputLayout[1], fInputLayout[2] );
0268
0269 if (fBatchDepth == 1 && fBatchHeight == fBatchSize && fInputLayout[0] == 1 && fInputLayout[1] == 1){
0270 inputTensor = Tensor_t( inputDeviceBuffer, {fBatchSize, fInputLayout.back() }, Tensor_t::MemoryLayout::ColumnMajor );
0271 }
0272
0273 Matrix_t outputMatrix(outputDeviceBuffer, fBatchSize, fNOutputFeatures);
0274 Matrix_t weightMatrix(weightDeviceBuffer, fBatchSize, 1);
0275
0276 fBatchIndex++;
0277
0278
0279 return TTensorBatch<Architecture_t>(inputTensor, outputMatrix, weightMatrix);
0280 }
0281
0282
0283 template <typename Data_t, typename Architecture_t>
0284 template <typename RNG>
0285 void TTensorDataLoader<Data_t, Architecture_t>::Shuffle(RNG & rng)
0286 {
0287 std::shuffle(fSampleIndices.begin(), fSampleIndices.end(), rng);
0288 }
0289
0290 }
0291 }
0292
0293 #endif