Skip to content

Commit 8d3c4c2

Browse files
committed
Store layer2 models in array instead of vector.
1 parent 8a89d8f commit 8d3c4c2

1 file changed

Lines changed: 23 additions & 10 deletions

File tree

include/rmi/rmi.hpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@ class Rmi
3333
using layer2_type = Layer2;
3434

3535
protected:
36-
std::size_t n_keys_; ///< The number of keys the index was built on.
37-
layer1_type l1_; ///< The layer1 model.
38-
std::vector<layer2_type> l2_; ///< The vector of layer2 models.
36+
std::size_t n_keys_; ///< The number of keys the index was built on.
37+
std::size_t layer2_size_; ///< The number of models in layer2.
38+
layer1_type l1_; ///< The layer1 model.
39+
layer2_type *l2_; ///< The array of layer2 models.
3940

4041
public:
4142
/**
@@ -59,12 +60,13 @@ class Rmi
5960
template<typename RandomIt>
6061
Rmi(RandomIt first, RandomIt last, const std::size_t layer2_size)
6162
: n_keys_(std::distance(first, last))
63+
, layer2_size_(layer2_size)
6264
{
6365
// Train layer1.
6466
l1_ = layer1_type(first, last, 0, static_cast<double>(layer2_size) / n_keys_); // train with compression
6567

6668
// Train layer2.
67-
l2_ = std::vector<layer2_type>(layer2_size);
69+
l2_ = new layer2_type[layer2_size];
6870
std::size_t segment_start = 0;
6971
std::size_t segment_id = 0;
7072
// Assign each key to its segment.
@@ -73,28 +75,33 @@ class Rmi
7375
std::size_t pred_segment_id = get_segment_id(*pos);
7476
// If a key is assigned to a new segment, all models must be trained up to the new segment.
7577
if (pred_segment_id > segment_id) {
76-
l2_[segment_id] = layer2_type(first + segment_start, pos, segment_start);
78+
new (&l2_[segment_id]) layer2_type(first + segment_start, pos, segment_start);
7779
for (std::size_t j = segment_id + 1; j < pred_segment_id; ++j) {
78-
l2_[j] = layer2_type(pos - 1, pos, i - 1); // train other models on last key in previous segment
80+
new (&l2_[j]) layer2_type(pos - 1, pos, i - 1); // train other models on last key in previous segment
7981
}
8082
segment_id = pred_segment_id;
8183
segment_start = i;
8284
}
8385
}
8486
// Train remaining models.
85-
l2_[segment_id] = layer2_type(first + segment_start, last, segment_start);
87+
new (&l2_[segment_id]) layer2_type(first + segment_start, last, segment_start);
8688
for (std::size_t j = segment_id + 1; j < layer2_size; ++j) {
87-
l2_[j] = layer2_type(last - 1, last, n_keys_ - 1); // train remaining models on last key
89+
new (&l2_[j]) layer2_type(last - 1, last, n_keys_ - 1); // train remaining models on last key
8890
}
8991
}
9092

93+
/**
94+
* Destructor.
95+
*/
96+
~Rmi() { delete[] l2_; }
97+
9198
/**
9299
* Returns the id of the segment @p key belongs to.
93100
* @param key to get segment id for
94101
* @return segment id of the given key
95102
*/
96103
std::size_t get_segment_id(const key_type key) const {
97-
return std::clamp<double>(l1_.predict(key), 0, l2_.size() - 1);
104+
return std::clamp<double>(l1_.predict(key), 0, layer2_size_ - 1);
98105
}
99106

100107
/**
@@ -114,12 +121,18 @@ class Rmi
114121
*/
115122
std::size_t n_keys() const { return n_keys_; }
116123

124+
/**
125+
* Returns the number of models in layer2.
126+
* @return the number of models in layer2
127+
*/
128+
std::size_t layer2_size() const { return layer2_size_; }
129+
117130
/**
118131
* Returns the size of the index in bytes.
119132
* @return index size in bytes
120133
*/
121134
std::size_t size_in_bytes() {
122-
return l1_.size_in_bytes() + l2_.size() * l2_[0].size_in_bytes() + sizeof(n_keys_);
135+
return l1_.size_in_bytes() + layer2_size_ * l2_[0].size_in_bytes() + sizeof(n_keys_) + sizeof(layer2_size_);
123136
}
124137
};
125138

0 commit comments

Comments
 (0)