nnet-matrix-buffer.h
Go to the documentation of this file.
1 // nnet/nnet-matrix-buffer.h
2 
3 // Copyright 2016 Brno University of Technology (author: Karel Vesely)
4 
5 // See ../../COPYING for clarification regarding multiple authors
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 // http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
15 // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
16 // MERCHANTABLITY OR NON-INFRINGEMENT.
17 // See the Apache 2 License for the specific language governing permissions and
18 // limitations under the License.
19 
20 
21 #ifndef KALDI_NNET_NNET_MATRIX_BUFFER_H_
22 #define KALDI_NNET_NNET_MATRIX_BUFFER_H_
23 
24 #include <utility>
25 #include <vector>
26 #include <list>
27 #include <string>
28 
29 #include "itf/options-itf.h"
30 #include "util/common-utils.h"
31 #include "matrix/kaldi-matrix.h"
32 
33 
34 namespace kaldi {
35 namespace nnet1 {
36 
39 
41  matrix_buffer_size(3 * 1024) // 3 x 1GB,
42  { }
43 
44  void Register(OptionsItf *opts) {
45  opts->Register("matrix-buffer-size", &matrix_buffer_size,
46  "Capacity of buffer for feature matrices, in MB.");
47  }
48 };
49 
50 
61 class MatrixBuffer {
62  public:
64  reader_(NULL),
65  current_(NULL),
66  preferred_length_(0)
67  { }
68 
70  { }
71 
74  KALDI_ASSERT(SizeInBytes() == 0);
75  reader_ = reader;
76  opts_ = opts;
77 
78  Read();
79  }
80 
81  bool Done() {
82  return (reader_->Done() && NumPairs() <= 1);
83  }
84 
85  void Next();
86 
87  void ResetLength() {
88  preferred_length_ = 0;
89  }
90 
91  std::string Key() {
92  return current_->first;
93  }
95  return current_->second;
96  }
97 
99  size_t SizeInBytes() const;
100 
102  size_t SizeInMegaBytes() const;
103 
105  size_t NumPairs() const;
106 
107  private:
108 
109  void Read();
110  void DisposeValue();
111 
113 
114  typedef std::pair<std::string,Matrix<BaseFloat> > PairType;
115  typedef std::list<PairType> ListType;
116  typedef std::map<size_t, ListType> BufferType;
117  BufferType buffer_;
118 
119  PairType* current_;
120 
122 
124 };
125 
127  KALDI_ASSERT(!buffer_.empty());
128 
129  // remove old 'Value()' matrix,
130  DisposeValue();
131 
132  // start re-filling,
133  if (SizeInMegaBytes() < 0.5 * opts_.matrix_buffer_size) {
134  Read();
135  }
136 
137  KALDI_ASSERT(!buffer_.empty());
138 
139  // randomly select 'length' present in the 'map',
140  // (weighted by total #frames in the bin),
141  if (preferred_length_ == 0) {
142  int32 longest = (--buffer_.end())->first;
143  // pre-fill the vector of 'keys',
144  std::vector<int32> keys;
145  BufferType::iterator it;
146  for (it = buffer_.begin(); it != buffer_.end(); ++it) {
147  int32 key = it->first; // i.e. NumRows() of matrices in the bin,
148  int32 frames_in_bin = it->second.size() * key;
149  for (int32 i = 0; i < frames_in_bin; i += longest) {
150  keys.push_back(key); // keys are repeated,
151  }
152  }
153  // choose the key,
154  std::vector<int32>::iterator it2 = keys.begin();
155  std::advance(it2, rand() % keys.size());
156  preferred_length_ = (*it2); // NumRows(), key of the 'map',
157  }
158 
159  // select list by 'preferred_length_',
160  BufferType::iterator it = buffer_.lower_bound(preferred_length_);
161  if (it == buffer_.end()) { --it; } // or the last one,
162 
163  // take a front element 'ptr' from that list,
164  current_ = &(it->second.front());
165 }
166 
168  size_t ans = 0;
169  for (BufferType::const_iterator it = buffer_.begin(); it != buffer_.end(); ++it) {
170  for (ListType::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) {
171  ans += it2->second.SizeInBytes();
172  }
173  }
174  return ans;
175 }
176 
178  return (SizeInBytes() / (1024 * 1024));
179 }
180 
181 size_t MatrixBuffer::NumPairs() const {
182  size_t ans = 0;
183  for (BufferType::const_iterator it = buffer_.begin(); it != buffer_.end(); ++it) {
184  ans += it->second.size();
185  }
186  return ans;
187 }
188 
190  if (!reader_->Done())
191  KALDI_LOG << "Read() started... Buffer size in MB: "
192  << SizeInMegaBytes() << ", max " << opts_.matrix_buffer_size
193  << ", having " << NumPairs() << " utterances.";
194  for ( ; !reader_->Done(); reader_->Next()) {
195  // see if we are full,
196  if (SizeInMegaBytes() > opts_.matrix_buffer_size) {
197  KALDI_LOG << "Read() finished... Buffer size in MB: "
198  << SizeInMegaBytes() << ", max " << opts_.matrix_buffer_size
199  << ", having " << NumPairs() << " utterances.";
200  break;
201  }
202  // get matrix,
203  const std::string& key = reader_->Key();
204  const Matrix<BaseFloat>& mat = reader_->Value();
205  size_t num_rows = mat.NumRows();
206  // see if 'num_rows' already in keys,
207  if (buffer_.find(num_rows) == buffer_.end()) {
208  buffer_[num_rows] = ListType(); // add empty list,
209  }
210  // add matrix to the buffer,
211  buffer_[num_rows].push_back(PairType(key, mat));
212  }
213 }
214 
216  // remove old 'Value()' matrix,
217  if (current_ != NULL) {
218  size_t r = current_->second.NumRows();
219  KALDI_ASSERT(current_ == &(buffer_[r].front()));
220  // remove the (key,value) pair,
221  buffer_[r].pop_front();
222  // eventually remove the 'NumRows()' key,
223  if (buffer_[r].empty()) { buffer_.erase(r); }
224  current_ = NULL;
225  }
226 }
227 
228 
229 } // namespace nnet1
230 } // namespace kaldi
231 
232 #endif // KALDI_NNET_NNET_MATRIX_BUFFER_H_
233 
void Init(SequentialBaseFloatMatrixReader *reader, MatrixBufferOptions opts=MatrixBufferOptions())
PairType * current_
The currently active (key,value) pair,.
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
Matrix< BaseFloat > Value()
std::list< PairType > ListType
BufferType buffer_
Buffer indexed by &#39;NumRows()&#39;,.
kaldi::int32 int32
std::pair< std::string, Matrix< BaseFloat > > PairType
void DisposeValue()
removes &#39;current_&#39; from data structure,
SequentialBaseFloatMatrixReader * reader_
virtual void Register(const std::string &name, bool *ptr, const std::string &doc)=0
void Read()
fills the buffer,
std::map< size_t, ListType > BufferType
A templated class for reading objects sequentially from an archive or script file; see The Table conc...
Definition: kaldi-table.h:287
size_t NumPairs() const
Total number of (key,matrix) pairs in the buffer,.
A buffer for caching (utterance-key, feature-matrix) pairs.
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
MatrixIndexT NumRows() const
Returns number of rows (or zero for empty matrix).
Definition: kaldi-matrix.h:64
size_t SizeInMegaBytes() const
Total amount of features in the buffer (Mega-bytes),.
size_t SizeInBytes() const
Total amount of features in the buffer (bytes),.
#define KALDI_LOG
Definition: kaldi-error.h:153