OmniSciDB  5ade3759e0
ColSlotContext.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2019 OmniSci, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
25 #include "ColSlotContext.h"
26 
27 #include "../BufferCompaction.h"
28 
29 #include <Analyzer/Analyzer.h>
30 #include <Shared/SqlTypesLayout.h>
31 
32 #include <numeric>
33 
34 extern bool g_bigint_count;
35 
36 ColSlotContext::ColSlotContext(const std::vector<Analyzer::Expr*>& col_expr_list,
37  const std::vector<ssize_t>& col_exprs_to_not_project) {
38  // Note that non-projected col exprs could be projected cols that we can lazy fetch or
39  // grouped cols with keyless hash
40  if (!col_exprs_to_not_project.empty()) {
41  CHECK_EQ(col_expr_list.size(), col_exprs_to_not_project.size());
42  }
43  size_t col_expr_idx = 0;
44  col_to_slot_map_.resize(col_expr_list.size());
45  for (const auto col_expr : col_expr_list) {
46  if (!col_exprs_to_not_project.empty() &&
47  col_exprs_to_not_project[col_expr_idx] != -1) {
48  addSlotForColumn(0, 0, col_expr_idx);
49  ++col_expr_idx;
50  continue;
51  }
52  if (!col_expr) {
53  // row index
54  addSlotForColumn(sizeof(int64_t), col_expr_idx);
55  } else {
56  const auto agg_info = get_target_info(col_expr, g_bigint_count);
57  const auto chosen_type = get_compact_type(agg_info);
58 
59  if ((chosen_type.is_string() && chosen_type.get_compression() == kENCODING_NONE) ||
60  chosen_type.is_array()) {
61  addSlotForColumn(sizeof(int64_t), col_expr_idx);
62  addSlotForColumn(sizeof(int64_t), col_expr_idx);
63  ++col_expr_idx;
64  continue;
65  }
66  if (chosen_type.is_geometry()) {
67  for (auto i = 0; i < chosen_type.get_physical_coord_cols(); ++i) {
68  addSlotForColumn(sizeof(int64_t), col_expr_idx);
69  addSlotForColumn(sizeof(int64_t), col_expr_idx);
70  }
71  ++col_expr_idx;
72  continue;
73  }
74 
75  const auto col_expr_bitwidth = get_bit_width(chosen_type);
76 
77  CHECK_EQ(size_t(0), col_expr_bitwidth % 8);
78  addSlotForColumn(static_cast<int8_t>(col_expr_bitwidth >> 3), col_expr_idx);
79  // for average, we'll need to keep the count as well
80  if (agg_info.agg_kind == kAVG) {
81  CHECK(agg_info.is_agg);
82  addSlotForColumn(sizeof(int64_t), col_expr_idx);
83  }
84  }
85  ++col_expr_idx;
86  }
87 }
88 
89 void ColSlotContext::setAllSlotsSize(const int8_t slot_width_size) {
90  const SlotSize ss{slot_width_size, slot_width_size};
91  std::fill(slot_sizes_.begin(), slot_sizes_.end(), ss);
92 }
93 
94 void ColSlotContext::setAllSlotsPaddedSize(const int8_t padded_size) {
95  for (auto& slot_size : slot_sizes_) {
96  slot_size.padded_size = padded_size;
97  }
98 }
99 
100 void ColSlotContext::setAllUnsetSlotsPaddedSize(const int8_t padded_size) {
101  for (auto& slot_size : slot_sizes_) {
102  if (slot_size.padded_size < 0) {
103  slot_size.padded_size = padded_size;
104  }
105  }
106 }
107 
109  for (auto& slot_size : slot_sizes_) {
110  slot_size.padded_size = slot_size.logical_size;
111  }
112 }
113 
115  for (const auto& slot_size : slot_sizes_) {
116  CHECK_GE(slot_size.logical_size, 0);
117  CHECK_LE(slot_size.logical_size, slot_size.padded_size);
118  }
119 }
120 
122  return col_to_slot_map_.size();
123 }
125  return slot_sizes_.size();
126 }
127 
129  return std::accumulate(slot_sizes_.cbegin(),
130  slot_sizes_.cend(),
131  size_t(0),
132  [](size_t sum, const auto& slot_size) {
133  CHECK_GE(slot_size.padded_size, 0);
134  return sum + static_cast<size_t>(slot_size.padded_size);
135  });
136 }
137 
140 }
141 
142 size_t ColSlotContext::getAlignedPaddedSizeForRange(const size_t end) const {
143  return std::accumulate(slot_sizes_.cbegin(),
144  slot_sizes_.cbegin() + end,
145  size_t(0),
146  [](size_t sum, const auto& slot_size) {
147  CHECK_GE(slot_size.padded_size, 0);
148  const auto chosen_bytes =
149  static_cast<size_t>(slot_size.padded_size);
150  if (chosen_bytes == sizeof(int64_t)) {
151  return align_to_int64(sum) + chosen_bytes;
152  } else {
153  return sum + chosen_bytes;
154  }
155  });
156 }
157 
158 size_t ColSlotContext::getTotalBytesOfColumnarBuffers(const size_t entry_count) const {
159  const auto total_bytes = std::accumulate(
160  slot_sizes_.cbegin(),
161  slot_sizes_.cend(),
162  size_t(0),
163  [entry_count](size_t sum, const auto& slot_size) {
164  CHECK_GE(slot_size.padded_size, 0);
165  return sum +
166  align_to_int64(static_cast<size_t>(slot_size.padded_size) * entry_count);
167  });
168  return align_to_int64(total_bytes);
169 }
170 
171 int8_t ColSlotContext::getMinPaddedByteSize(const int8_t actual_min_byte_width) const {
172  if (slot_sizes_.empty()) {
173  return actual_min_byte_width;
174  }
175  const auto min_padded_size = std::min_element(
176  slot_sizes_.cbegin(), slot_sizes_.cend(), [](const auto& lhs, const auto& rhs) {
177  return lhs.padded_size < rhs.padded_size;
178  });
179  return std::min(min_padded_size->padded_size, actual_min_byte_width);
180 }
181 
183  if (slot_sizes_.empty()) {
184  return 8;
185  }
186  size_t compact_width{0};
187  for (const auto& slot_size : slot_sizes_) {
188  if (slot_size.padded_size != 0) {
189  compact_width = slot_size.padded_size;
190  break;
191  }
192  }
193  if (!compact_width) {
194  return 0;
195  }
196  CHECK_GT(compact_width, size_t(0));
197  for (const auto& slot_size : slot_sizes_) {
198  if (slot_size.padded_size == 0) {
199  continue;
200  }
201  CHECK_EQ(static_cast<size_t>(slot_size.padded_size), compact_width);
202  }
203  return compact_width;
204 }
205 
206 size_t ColSlotContext::getColOnlyOffInBytes(const size_t slot_idx) const {
207  CHECK_LT(slot_idx, slot_sizes_.size());
208  auto offset_bytes = getAlignedPaddedSizeForRange(slot_idx);
209  if (slot_sizes_[slot_idx].padded_size == sizeof(int64_t)) {
210  offset_bytes = align_to_int64(offset_bytes);
211  }
212  return offset_bytes;
213 }
214 
216  return slot_sizes_.empty();
217 }
218 
220  slot_sizes_.clear();
221  col_to_slot_map_.clear();
222 }
223 
225  size_t total_bytes{0};
226  for (size_t slot_idx = 0; slot_idx < slot_sizes_.size(); slot_idx++) {
227  auto chosen_bytes = slot_sizes_[slot_idx].padded_size;
228  if (chosen_bytes == sizeof(int64_t)) {
229  const auto aligned_total_bytes = align_to_int64(total_bytes);
230  CHECK_GE(aligned_total_bytes, total_bytes);
231  if (slot_idx >= 1) {
232  const auto padding = aligned_total_bytes - total_bytes;
233  CHECK(padding == 0 || padding == 4);
234  slot_sizes_[slot_idx - 1].padded_size += padding;
235  }
236  total_bytes = aligned_total_bytes;
237  }
238  total_bytes += chosen_bytes;
239  }
240  if (!sort_on_gpu) {
241  const auto aligned_total_bytes = align_to_int64(total_bytes);
242  CHECK_GE(aligned_total_bytes, total_bytes);
243  const auto padding = aligned_total_bytes - total_bytes;
244  CHECK(padding == 0 || padding == 4);
245  slot_sizes_.back().padded_size += padding;
246  }
247 }
248 
250  const std::vector<std::tuple<int8_t, int8_t>>& slots_for_col) {
251  const auto col_idx = col_to_slot_map_.size();
252  col_to_slot_map_.emplace_back();
253  for (const auto& slot_info : slots_for_col) {
254  addSlotForColumn(std::get<1>(slot_info), std::get<0>(slot_info), col_idx);
255  }
256 }
257 
258 void ColSlotContext::addSlotForColumn(const int8_t logical_size,
259  const size_t column_idx) {
260  addSlotForColumn(-1, logical_size, column_idx);
261 }
262 
263 void ColSlotContext::addSlotForColumn(const int8_t padded_size,
264  const int8_t logical_size,
265  const size_t column_idx) {
266  CHECK_LT(column_idx, col_to_slot_map_.size());
267  col_to_slot_map_[column_idx].push_back(slot_sizes_.size());
268  slot_sizes_.emplace_back(SlotSize{padded_size, logical_size});
269 }
size_t getColCount() const
Defines data structures for the semantic analysis phase of query processing.
#define CHECK_EQ(x, y)
Definition: Logger.h:195
void alignPaddedSlots(const bool sort_on_gpu)
size_t getSlotCount() const
bool g_bigint_count
int8_t getMinPaddedByteSize(const int8_t actual_min_byte_width) const
TargetInfo get_target_info(const PointerType target_expr, const bool bigint_count)
Definition: TargetInfo.h:65
#define CHECK_GE(x, y)
Definition: Logger.h:200
std::vector< std::vector< size_t > > col_to_slot_map_
std::vector< SlotSize > slot_sizes_
#define CHECK_GT(x, y)
Definition: Logger.h:199
void setAllSlotsSize(const int8_t slot_width_size)
size_t getTotalBytesOfColumnarBuffers(const size_t entry_count) const
const SQLTypeInfo get_compact_type(const TargetInfo &target)
size_t get_bit_width(const SQLTypeInfo &ti)
size_t getAllSlotsPaddedSize() const
Provides column info and slot info for the output buffer and some metadata helpers.
void addColumn(const std::vector< std::tuple< int8_t, int8_t >> &slots_for_col)
#define CHECK_LT(x, y)
Definition: Logger.h:197
#define CHECK_LE(x, y)
Definition: Logger.h:198
void setAllSlotsPaddedSize(const int8_t padded_size)
size_t getCompactByteWidth() const
size_t getAllSlotsAlignedPaddedSize() const
void addSlotForColumn(const int8_t logical_size, const size_t column_idx)
size_t getAlignedPaddedSizeForRange(const size_t end) const
void setAllSlotsPaddedSizeToLogicalSize()
#define CHECK(condition)
Definition: Logger.h:187
size_t getColOnlyOffInBytes(const size_t slot_idx) const
void setAllUnsetSlotsPaddedSize(const int8_t padded_size)
Definition: sqldefs.h:71
FORCE_INLINE HOST DEVICE T align_to_int64(T addr)
void validate() const
void sort_on_gpu(int64_t *val_buff, int32_t *key_buff, const uint64_t entry_count, const bool desc, const uint32_t chosen_bytes, ThrustAllocator &alloc)