OmniSciDB  6686921089
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 #include <stdexcept>
34 
35 extern bool g_bigint_count;
36 
37 ColSlotContext::ColSlotContext(const std::vector<Analyzer::Expr*>& col_expr_list,
38  const std::vector<int64_t>& col_exprs_to_not_project) {
39  // Note that non-projected col exprs could be projected cols that we can lazy fetch or
40  // grouped cols with keyless hash
41  if (!col_exprs_to_not_project.empty()) {
42  CHECK_EQ(col_expr_list.size(), col_exprs_to_not_project.size());
43  }
44  size_t col_expr_idx = 0;
45  col_to_slot_map_.resize(col_expr_list.size());
46  for (const auto col_expr : col_expr_list) {
47  if (!col_exprs_to_not_project.empty() &&
48  col_exprs_to_not_project[col_expr_idx] != -1) {
49  addSlotForColumn(0, 0, col_expr_idx);
50  ++col_expr_idx;
51  continue;
52  }
53  if (!col_expr) {
54  // row index
55  addSlotForColumn(sizeof(int64_t), col_expr_idx);
56  } else {
57  const auto agg_info = get_target_info(col_expr, g_bigint_count);
58  const auto chosen_type = get_compact_type(agg_info);
59 
60  if ((chosen_type.is_string() && chosen_type.get_compression() == kENCODING_NONE) ||
61  chosen_type.is_array()) {
62  addSlotForColumn(sizeof(int64_t), col_expr_idx);
63  addSlotForColumn(sizeof(int64_t), col_expr_idx);
64  ++col_expr_idx;
65  continue;
66  }
67  if (chosen_type.is_geometry()) {
68  if (dynamic_cast<const Analyzer::GeoExpr*>(col_expr)) {
69  CHECK_EQ(chosen_type.get_type(), kPOINT);
70  // Pointer/offset into varlen buffer
71  addSlotForColumn(sizeof(int64_t), col_expr_idx);
72  const int64_t arr_size =
73  chosen_type.get_compression() == kENCODING_GEOINT ? 8 : 16;
75  .insert(std::make_pair(slot_sizes_.size() - 1, arr_size))
76  .second);
77  } else {
78  for (auto i = 0; i < chosen_type.get_physical_coord_cols(); ++i) {
79  addSlotForColumn(sizeof(int64_t), col_expr_idx);
80  addSlotForColumn(sizeof(int64_t), col_expr_idx);
81  }
82  }
83  ++col_expr_idx;
84  continue;
85  }
86 
87  const auto col_expr_bitwidth = get_bit_width(chosen_type);
88 
89  CHECK_EQ(size_t(0), col_expr_bitwidth % 8);
90  addSlotForColumn(static_cast<int8_t>(col_expr_bitwidth >> 3), col_expr_idx);
91  // for average, we'll need to keep the count as well
92  if (agg_info.agg_kind == kAVG) {
93  CHECK(agg_info.is_agg);
94  addSlotForColumn(sizeof(int64_t), col_expr_idx);
95  }
96  }
97  ++col_expr_idx;
98  }
99 }
100 
101 void ColSlotContext::setAllSlotsSize(const int8_t slot_width_size) {
102  const SlotSize ss{slot_width_size, slot_width_size};
103  std::fill(slot_sizes_.begin(), slot_sizes_.end(), ss);
104 }
105 
106 void ColSlotContext::setAllSlotsPaddedSize(const int8_t padded_size) {
107  for (auto& slot_size : slot_sizes_) {
108  slot_size.padded_size = padded_size;
109  }
110 }
111 
112 void ColSlotContext::setAllUnsetSlotsPaddedSize(const int8_t padded_size) {
113  for (auto& slot_size : slot_sizes_) {
114  if (slot_size.padded_size < 0) {
115  slot_size.padded_size = padded_size;
116  }
117  }
118 }
119 
121  for (auto& slot_size : slot_sizes_) {
122  slot_size.padded_size = slot_size.logical_size;
123  }
124 }
125 
127  for (const auto& slot_size : slot_sizes_) {
128  CHECK_GE(slot_size.logical_size, 0);
129  CHECK_LE(slot_size.logical_size, slot_size.padded_size);
130  }
131 }
132 
134  return col_to_slot_map_.size();
135 }
137  return slot_sizes_.size();
138 }
139 
141  return std::accumulate(slot_sizes_.cbegin(),
142  slot_sizes_.cend(),
143  size_t(0),
144  [](size_t sum, const auto& slot_size) {
145  CHECK_GE(slot_size.padded_size, 0);
146  return sum + static_cast<size_t>(slot_size.padded_size);
147  });
148 }
149 
152 }
153 
154 size_t ColSlotContext::getAlignedPaddedSizeForRange(const size_t end) const {
155  return std::accumulate(slot_sizes_.cbegin(),
156  slot_sizes_.cbegin() + end,
157  size_t(0),
158  [](size_t sum, const auto& slot_size) {
159  CHECK_GE(slot_size.padded_size, 0);
160  const auto chosen_bytes =
161  static_cast<size_t>(slot_size.padded_size);
162  if (chosen_bytes == sizeof(int64_t)) {
163  return align_to_int64(sum) + chosen_bytes;
164  } else {
165  return sum + chosen_bytes;
166  }
167  });
168 }
169 
170 size_t ColSlotContext::getTotalBytesOfColumnarBuffers(const size_t entry_count) const {
171  const auto total_bytes = std::accumulate(
172  slot_sizes_.cbegin(),
173  slot_sizes_.cend(),
174  size_t(0),
175  [entry_count](size_t sum, const auto& slot_size) {
176  CHECK_GE(slot_size.padded_size, 0);
177  return sum +
178  align_to_int64(static_cast<size_t>(slot_size.padded_size) * entry_count);
179  });
180  return align_to_int64(total_bytes);
181 }
182 
183 int8_t ColSlotContext::getMinPaddedByteSize(const int8_t actual_min_byte_width) const {
184  if (slot_sizes_.empty()) {
185  return actual_min_byte_width;
186  }
187  const auto min_padded_size = std::min_element(
188  slot_sizes_.cbegin(), slot_sizes_.cend(), [](const auto& lhs, const auto& rhs) {
189  return lhs.padded_size < rhs.padded_size;
190  });
191  return std::min(min_padded_size->padded_size, actual_min_byte_width);
192 }
193 
195  if (slot_sizes_.empty()) {
196  return 8;
197  }
198  size_t compact_width{0};
199  for (const auto& slot_size : slot_sizes_) {
200  if (slot_size.padded_size != 0) {
201  compact_width = slot_size.padded_size;
202  break;
203  }
204  }
205  if (!compact_width) {
206  return 0;
207  }
208  CHECK_GT(compact_width, size_t(0));
209  for (const auto& slot_size : slot_sizes_) {
210  if (slot_size.padded_size == 0) {
211  continue;
212  }
213  CHECK_EQ(static_cast<size_t>(slot_size.padded_size), compact_width);
214  }
215  return compact_width;
216 }
217 
218 size_t ColSlotContext::getColOnlyOffInBytes(const size_t slot_idx) const {
219  CHECK_LT(slot_idx, slot_sizes_.size());
220  auto offset_bytes = getAlignedPaddedSizeForRange(slot_idx);
221  if (slot_sizes_[slot_idx].padded_size == sizeof(int64_t)) {
222  offset_bytes = align_to_int64(offset_bytes);
223  }
224  return offset_bytes;
225 }
226 
228  return slot_sizes_.empty();
229 }
230 
232  slot_sizes_.clear();
233  col_to_slot_map_.clear();
234 }
235 
237  size_t total_bytes{0};
238  for (size_t slot_idx = 0; slot_idx < slot_sizes_.size(); slot_idx++) {
239  auto chosen_bytes = slot_sizes_[slot_idx].padded_size;
240  if (chosen_bytes == sizeof(int64_t)) {
241  const auto aligned_total_bytes = align_to_int64(total_bytes);
242  CHECK_GE(aligned_total_bytes, total_bytes);
243  if (slot_idx >= 1) {
244  const auto padding = aligned_total_bytes - total_bytes;
245  CHECK(padding == 0 || padding == 4);
246  slot_sizes_[slot_idx - 1].padded_size += padding;
247  }
248  total_bytes = aligned_total_bytes;
249  }
250  total_bytes += chosen_bytes;
251  }
252  if (!sort_on_gpu) {
253  const auto aligned_total_bytes = align_to_int64(total_bytes);
254  CHECK_GE(aligned_total_bytes, total_bytes);
255  const auto padding = aligned_total_bytes - total_bytes;
256  CHECK(padding == 0 || padding == 4);
257  slot_sizes_.back().padded_size += padding;
258  }
259 }
260 
262  const std::vector<std::tuple<int8_t, int8_t>>& slots_for_col) {
263  const auto col_idx = col_to_slot_map_.size();
264  col_to_slot_map_.emplace_back();
265  for (const auto& slot_info : slots_for_col) {
266  addSlotForColumn(std::get<1>(slot_info), std::get<0>(slot_info), col_idx);
267  }
268 }
269 
270 void ColSlotContext::addSlotForColumn(const int8_t logical_size,
271  const size_t column_idx) {
272  addSlotForColumn(-1, logical_size, column_idx);
273 }
274 
275 void ColSlotContext::addSlotForColumn(const int8_t padded_size,
276  const int8_t logical_size,
277  const size_t column_idx) {
278  CHECK_LT(column_idx, col_to_slot_map_.size());
279  col_to_slot_map_[column_idx].push_back(slot_sizes_.size());
280  slot_sizes_.emplace_back(SlotSize{padded_size, logical_size});
281 }
282 
283 int64_t ColSlotContext::varlenOutputElementSize(const size_t slot_idx) const {
284  const auto varlen_map_it = varlen_output_slot_map_.find(slot_idx);
285  if (varlen_map_it == varlen_output_slot_map_.end()) {
286  throw std::runtime_error("Failed to find varlen map entry for slot " +
287  std::to_string(slot_idx));
288  }
289  return varlen_map_it->second;
290 }
Defines data structures for the semantic analysis phase of query processing.
int8_t getMinPaddedByteSize(const int8_t actual_min_byte_width) const
#define CHECK_EQ(x, y)
Definition: Logger.h:217
void alignPaddedSlots(const bool sort_on_gpu)
std::unordered_map< SlotIndex, ArraySize > varlen_output_slot_map_
TargetInfo get_target_info(const PointerType target_expr, const bool bigint_count)
Definition: TargetInfo.h:92
#define CHECK_GE(x, y)
Definition: Logger.h:222
size_t getAllSlotsPaddedSize() const
size_t getAllSlotsAlignedPaddedSize() const
std::vector< std::vector< size_t > > col_to_slot_map_
std::vector< SlotSize > slot_sizes_
#define CHECK_GT(x, y)
Definition: Logger.h:221
void setAllSlotsSize(const int8_t slot_width_size)
std::string to_string(char const *&&v)
size_t getColOnlyOffInBytes(const size_t slot_idx) const
const SQLTypeInfo get_compact_type(const TargetInfo &target)
size_t get_bit_width(const SQLTypeInfo &ti)
DEVICE void fill(ARGS &&...args)
Definition: gpu_enabled.h:60
size_t getCompactByteWidth() const
Provides column info and slot info for the output buffer and some metadata helpers.
size_t getAlignedPaddedSizeForRange(const size_t end) const
bool g_bigint_count
DEVICE auto accumulate(ARGS &&...args)
Definition: gpu_enabled.h:42
void validate() const
int64_t varlenOutputElementSize(const size_t slot_idx) const
void addColumn(const std::vector< std::tuple< int8_t, int8_t >> &slots_for_col)
#define CHECK_LT(x, y)
Definition: Logger.h:219
#define CHECK_LE(x, y)
Definition: Logger.h:220
void setAllSlotsPaddedSize(const int8_t padded_size)
size_t getTotalBytesOfColumnarBuffers(const size_t entry_count) const
void addSlotForColumn(const int8_t logical_size, const size_t column_idx)
size_t getSlotCount() const
void setAllSlotsPaddedSizeToLogicalSize()
#define CHECK(condition)
Definition: Logger.h:209
size_t getColCount() const
void sort_on_gpu(int64_t *val_buff, int32_t *idx_buff, const uint64_t entry_count, const bool desc, const uint32_t chosen_bytes, ThrustAllocator &alloc)
void setAllUnsetSlotsPaddedSize(const int8_t padded_size)
Definition: sqldefs.h:72
FORCE_INLINE HOST DEVICE T align_to_int64(T addr)