OmniSciDB  29e35f4d58
ResultSetStorage Class Reference

#include <ResultSet.h>

+ Collaboration diagram for ResultSetStorage:

Public Member Functions

 ResultSetStorage (const std::vector< TargetInfo > &targets, const QueryMemoryDescriptor &query_mem_desc, int8_t *buff, const bool buff_is_provided)
 
void reduce (const ResultSetStorage &that, const std::vector< std::string > &serialized_varlen_buffer, const ReductionCode &reduction_code) const
 
void rewriteAggregateBufferOffsets (const std::vector< std::string > &serialized_varlen_buffer) const
 
int8_t * getUnderlyingBuffer () const
 
template<class KeyType >
void moveEntriesToBuffer (int8_t *new_buff, const size_t new_entry_count) const
 
template<class KeyType >
void moveOneEntryToBuffer (const size_t entry_index, int64_t *new_buff_i64, const size_t new_entry_count, const size_t key_count, const size_t row_qw_count, const int64_t *src_buff, const size_t key_byte_width) const
 
void updateEntryCount (const size_t new_entry_count)
 

Static Public Member Functions

static bool reduceSingleRow (const int8_t *row_ptr, const int8_t warp_count, const bool is_columnar, const bool replace_bitmap_ptr_with_bitmap_sz, std::vector< int64_t > &agg_vals, const QueryMemoryDescriptor &query_mem_desc, const std::vector< TargetInfo > &targets, const std::vector< int64_t > &agg_init_vals)
 

Private Member Functions

void reduceEntriesNoCollisionsColWise (int8_t *this_buff, const int8_t *that_buff, const ResultSetStorage &that, const size_t start_index, const size_t end_index, const std::vector< std::string > &serialized_varlen_buffer) const
 
void copyKeyColWise (const size_t entry_idx, int8_t *this_buff, const int8_t *that_buff) const
 
bool isEmptyEntry (const size_t entry_idx, const int8_t *buff) const
 
bool isEmptyEntry (const size_t entry_idx) const
 
bool isEmptyEntryColumnar (const size_t entry_idx, const int8_t *buff) const
 
void reduceOneEntryBaseline (int8_t *this_buff, const int8_t *that_buff, const size_t i, const size_t that_entry_count, const ResultSetStorage &that) const
 
void reduceOneEntrySlotsBaseline (int64_t *this_entry_slots, const int64_t *that_buff, const size_t that_entry_idx, const size_t that_entry_count, const ResultSetStorage &that) const
 
void initializeBaselineValueSlots (int64_t *this_entry_slots) const
 
void reduceOneSlotBaseline (int64_t *this_buff, const size_t this_slot, const int64_t *that_buff, const size_t that_entry_count, const size_t that_slot, const TargetInfo &target_info, const size_t target_logical_idx, const size_t target_slot_idx, const size_t init_agg_val_idx, const ResultSetStorage &that) const
 
ALWAYS_INLINE void reduceOneSlotSingleValue (int8_t *this_ptr1, const TargetInfo &target_info, const size_t target_slot_idx, const size_t init_agg_val_idx, const int8_t *that_ptr1) const
 
ALWAYS_INLINE void reduceOneSlot (int8_t *this_ptr1, int8_t *this_ptr2, const int8_t *that_ptr1, const int8_t *that_ptr2, const TargetInfo &target_info, const size_t target_logical_idx, const size_t target_slot_idx, const size_t init_agg_val_idx, const ResultSetStorage &that, const size_t first_slot_idx_for_target, const std::vector< std::string > &serialized_varlen_buffer) const
 
void reduceOneCountDistinctSlot (int8_t *this_ptr1, const int8_t *that_ptr1, const size_t target_logical_idx, const ResultSetStorage &that) const
 
void fillOneEntryRowWise (const std::vector< int64_t > &entry)
 
void fillOneEntryColWise (const std::vector< int64_t > &entry)
 
void initializeRowWise () const
 
void initializeColWise () const
 
void addCountDistinctSetPointerMapping (const int64_t remote_ptr, const int64_t ptr)
 
int64_t mappedPtr (const int64_t) const
 

Private Attributes

const std::vector< TargetInfotargets_
 
QueryMemoryDescriptor query_mem_desc_
 
int8_t * buff_
 
const bool buff_is_provided_
 
std::vector< int64_t > target_init_vals_
 
std::unordered_map< int64_t, int64_t > count_distinct_sets_mapping_
 

Friends

class ResultSet
 
class ResultSetManager
 

Detailed Description

Definition at line 80 of file ResultSet.h.

Constructor & Destructor Documentation

◆ ResultSetStorage()

ResultSetStorage::ResultSetStorage ( const std::vector< TargetInfo > &  targets,
const QueryMemoryDescriptor query_mem_desc,
int8_t *  buff,
const bool  buff_is_provided 
)

Definition at line 44 of file ResultSet.cpp.

References kAPPROX_COUNT_DISTINCT, kAVG, kCOUNT, kSAMPLE, null_val_bit_pattern(), takes_float_argument(), target_init_vals_, and targets_.

48  : targets_(targets)
49  , query_mem_desc_(query_mem_desc)
50  , buff_(buff)
51  , buff_is_provided_(buff_is_provided) {
52  for (const auto& target_info : targets_) {
53  if (target_info.agg_kind == kCOUNT ||
54  target_info.agg_kind == kAPPROX_COUNT_DISTINCT) {
55  target_init_vals_.push_back(0);
56  continue;
57  }
58  if (!target_info.sql_type.get_notnull()) {
59  int64_t init_val =
60  null_val_bit_pattern(target_info.sql_type, takes_float_argument(target_info));
61  target_init_vals_.push_back(target_info.is_agg ? init_val : 0);
62  } else {
63  target_init_vals_.push_back(target_info.is_agg ? 0xdeadbeef : 0);
64  }
65  if (target_info.agg_kind == kAVG) {
66  target_init_vals_.push_back(0);
67  } else if (target_info.agg_kind == kSAMPLE && target_info.sql_type.is_geometry()) {
68  for (int i = 1; i < 2 * target_info.sql_type.get_physical_coord_cols(); i++) {
69  target_init_vals_.push_back(0);
70  }
71  } else if (target_info.agg_kind == kSAMPLE && target_info.sql_type.is_varlen()) {
72  target_init_vals_.push_back(0);
73  }
74  }
75 }
const std::vector< TargetInfo > targets_
Definition: ResultSet.h:203
std::vector< int64_t > target_init_vals_
Definition: ResultSet.h:207
bool takes_float_argument(const TargetInfo &target_info)
Definition: TargetInfo.h:121
int64_t null_val_bit_pattern(const SQLTypeInfo &ti, const bool float_argument_input)
const bool buff_is_provided_
Definition: ResultSet.h:206
int8_t * buff_
Definition: ResultSet.h:205
Definition: sqldefs.h:76
Definition: sqldefs.h:72
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
+ Here is the call graph for this function:

Member Function Documentation

◆ addCountDistinctSetPointerMapping()

void ResultSetStorage::addCountDistinctSetPointerMapping ( const int64_t  remote_ptr,
const int64_t  ptr 
)
private

Definition at line 841 of file ResultSet.cpp.

References CHECK.

Referenced by updateEntryCount().

842  {
843  const auto it_ok = count_distinct_sets_mapping_.emplace(remote_ptr, ptr);
844  CHECK(it_ok.second);
845 }
std::unordered_map< int64_t, int64_t > count_distinct_sets_mapping_
Definition: ResultSet.h:213
#define CHECK(condition)
Definition: Logger.h:193
+ Here is the caller graph for this function:

◆ copyKeyColWise()

void ResultSetStorage::copyKeyColWise ( const size_t  entry_idx,
int8_t *  this_buff,
const int8_t *  that_buff 
) const
private

Definition at line 476 of file ResultSetReduction.cpp.

References CHECK, QueryMemoryDescriptor::didOutputColumnar(), QueryMemoryDescriptor::getGroupbyColCount(), QueryMemoryDescriptor::getPrependedGroupColOffInBytes(), QueryMemoryDescriptor::groupColWidth(), and query_mem_desc_.

Referenced by reduceEntriesNoCollisionsColWise(), and updateEntryCount().

478  {
480  for (size_t group_idx = 0; group_idx < query_mem_desc_.getGroupbyColCount();
481  group_idx++) {
482  // if the column corresponds to a group key
483  const auto column_offset_bytes =
485  auto lhs_key_ptr = this_buff + column_offset_bytes;
486  auto rhs_key_ptr = that_buff + column_offset_bytes;
487  switch (query_mem_desc_.groupColWidth(group_idx)) {
488  case 8:
489  *(reinterpret_cast<int64_t*>(lhs_key_ptr) + entry_idx) =
490  *(reinterpret_cast<const int64_t*>(rhs_key_ptr) + entry_idx);
491  break;
492  case 4:
493  *(reinterpret_cast<int32_t*>(lhs_key_ptr) + entry_idx) =
494  *(reinterpret_cast<const int32_t*>(rhs_key_ptr) + entry_idx);
495  break;
496  case 2:
497  *(reinterpret_cast<int16_t*>(lhs_key_ptr) + entry_idx) =
498  *(reinterpret_cast<const int16_t*>(rhs_key_ptr) + entry_idx);
499  break;
500  case 1:
501  *(reinterpret_cast<int8_t*>(lhs_key_ptr) + entry_idx) =
502  *(reinterpret_cast<const int8_t*>(rhs_key_ptr) + entry_idx);
503  break;
504  default:
505  CHECK(false);
506  break;
507  }
508  }
509 }
int8_t groupColWidth(const size_t key_idx) const
#define CHECK(condition)
Definition: Logger.h:193
size_t getPrependedGroupColOffInBytes(const size_t group_idx) const
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fillOneEntryColWise()

void ResultSetStorage::fillOneEntryColWise ( const std::vector< int64_t > &  entry)
private

Definition at line 1143 of file ResultSetReduction.cpp.

References buff_, CHECK, CHECK_EQ, QueryMemoryDescriptor::didOutputColumnar(), QueryMemoryDescriptor::getBufferColSlotCount(), QueryMemoryDescriptor::getEntryCount(), QueryMemoryDescriptor::getGroupbyColCount(), key_offset_colwise(), query_mem_desc_, slot_offset_colwise(), and target_init_vals_.

Referenced by updateEntryCount().

1143  {
1145  CHECK_EQ(size_t(1), query_mem_desc_.getEntryCount());
1146  const auto slot_count = query_mem_desc_.getBufferColSlotCount();
1147  const auto key_count = query_mem_desc_.getGroupbyColCount();
1148  CHECK_EQ(slot_count + key_count, entry.size());
1149  auto this_buff = reinterpret_cast<int64_t*>(buff_);
1150 
1151  for (size_t i = 0; i < key_count; i++) {
1152  const auto key_offset = key_offset_colwise(0, i, 1);
1153  this_buff[key_offset] = entry[i];
1154  }
1155 
1156  for (size_t i = 0; i < target_init_vals_.size(); i++) {
1157  const auto slot_offset = slot_offset_colwise(0, i, key_count, 1);
1158  this_buff[slot_offset] = entry[key_count + i];
1159  }
1160 }
#define CHECK_EQ(x, y)
Definition: Logger.h:201
std::vector< int64_t > target_init_vals_
Definition: ResultSet.h:207
size_t slot_offset_colwise(const size_t entry_idx, const size_t slot_idx, const size_t key_count, const size_t entry_count)
size_t key_offset_colwise(const size_t entry_idx, const size_t key_idx, const size_t entry_count)
int8_t * buff_
Definition: ResultSet.h:205
#define CHECK(condition)
Definition: Logger.h:193
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fillOneEntryRowWise()

void ResultSetStorage::fillOneEntryRowWise ( const std::vector< int64_t > &  entry)
private

Definition at line 1090 of file ResultSetReduction.cpp.

References buff_, CHECK, CHECK_EQ, QueryMemoryDescriptor::didOutputColumnar(), QueryMemoryDescriptor::getBufferColSlotCount(), QueryMemoryDescriptor::getEffectiveKeyWidth(), QueryMemoryDescriptor::getEntryCount(), QueryMemoryDescriptor::getGroupbyColCount(), key_offset_rowwise(), query_mem_desc_, slot_offset_rowwise(), and target_init_vals_.

Referenced by updateEntryCount().

1090  {
1091  const auto slot_count = query_mem_desc_.getBufferColSlotCount();
1092  const auto key_count = query_mem_desc_.getGroupbyColCount();
1093  CHECK_EQ(slot_count + key_count, entry.size());
1094  auto this_buff = reinterpret_cast<int64_t*>(buff_);
1096  CHECK_EQ(size_t(1), query_mem_desc_.getEntryCount());
1097  const auto key_off = key_offset_rowwise(0, key_count, slot_count);
1098  CHECK_EQ(query_mem_desc_.getEffectiveKeyWidth(), sizeof(int64_t));
1099  for (size_t i = 0; i < key_count; ++i) {
1100  this_buff[key_off + i] = entry[i];
1101  }
1102  const auto first_slot_off = slot_offset_rowwise(0, 0, key_count, slot_count);
1103  for (size_t i = 0; i < target_init_vals_.size(); ++i) {
1104  this_buff[first_slot_off + i] = entry[key_count + i];
1105  }
1106 }
size_t slot_offset_rowwise(const size_t entry_idx, const size_t slot_idx, const size_t key_count, const size_t slot_count)
#define CHECK_EQ(x, y)
Definition: Logger.h:201
std::vector< int64_t > target_init_vals_
Definition: ResultSet.h:207
int8_t * buff_
Definition: ResultSet.h:205
size_t key_offset_rowwise(const size_t entry_idx, const size_t key_count, const size_t slot_count)
#define CHECK(condition)
Definition: Logger.h:193
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
size_t getEffectiveKeyWidth() const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getUnderlyingBuffer()

int8_t * ResultSetStorage::getUnderlyingBuffer ( ) const

Definition at line 77 of file ResultSet.cpp.

References buff_.

Referenced by anonymous_namespace{Execute.cpp}::permute_storage_columnar(), and anonymous_namespace{Execute.cpp}::permute_storage_row_wise().

77  {
78  return buff_;
79 }
int8_t * buff_
Definition: ResultSet.h:205
+ Here is the caller graph for this function:

◆ initializeBaselineValueSlots()

void ResultSetStorage::initializeBaselineValueSlots ( int64_t *  this_entry_slots) const
private

Definition at line 1182 of file ResultSetReduction.cpp.

References CHECK, QueryMemoryDescriptor::didOutputColumnar(), QueryMemoryDescriptor::getEntryCount(), query_mem_desc_, and target_init_vals_.

Referenced by updateEntryCount().

1182  {
1183  CHECK(entry_slots);
1185  size_t slot_off = 0;
1186  for (size_t j = 0; j < target_init_vals_.size(); ++j) {
1187  entry_slots[slot_off] = target_init_vals_[j];
1188  slot_off += query_mem_desc_.getEntryCount();
1189  }
1190  } else {
1191  for (size_t j = 0; j < target_init_vals_.size(); ++j) {
1192  entry_slots[j] = target_init_vals_[j];
1193  }
1194  }
1195 }
std::vector< int64_t > target_init_vals_
Definition: ResultSet.h:207
#define CHECK(condition)
Definition: Logger.h:193
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ initializeColWise()

void ResultSetStorage::initializeColWise ( ) const
private

Definition at line 1162 of file ResultSetReduction.cpp.

References buff_, CHECK, EMPTY_KEY_64, QueryMemoryDescriptor::getEntryCount(), QueryMemoryDescriptor::getGroupbyColCount(), QueryMemoryDescriptor::hasKeylessHash(), key_offset_colwise(), query_mem_desc_, slot_offset_colwise(), and target_init_vals_.

Referenced by updateEntryCount().

1162  {
1163  const auto key_count = query_mem_desc_.getGroupbyColCount();
1164  auto this_buff = reinterpret_cast<int64_t*>(buff_);
1166  for (size_t key_idx = 0; key_idx < key_count; ++key_idx) {
1167  const auto first_key_off =
1169  for (size_t i = 0; i < query_mem_desc_.getEntryCount(); ++i) {
1170  this_buff[first_key_off + i] = EMPTY_KEY_64;
1171  }
1172  }
1173  for (size_t target_idx = 0; target_idx < target_init_vals_.size(); ++target_idx) {
1174  const auto first_val_off =
1175  slot_offset_colwise(0, target_idx, key_count, query_mem_desc_.getEntryCount());
1176  for (size_t i = 0; i < query_mem_desc_.getEntryCount(); ++i) {
1177  this_buff[first_val_off + i] = target_init_vals_[target_idx];
1178  }
1179  }
1180 }
#define EMPTY_KEY_64
std::vector< int64_t > target_init_vals_
Definition: ResultSet.h:207
size_t slot_offset_colwise(const size_t entry_idx, const size_t slot_idx, const size_t key_count, const size_t entry_count)
size_t key_offset_colwise(const size_t entry_idx, const size_t key_idx, const size_t entry_count)
int8_t * buff_
Definition: ResultSet.h:205
#define CHECK(condition)
Definition: Logger.h:193
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ initializeRowWise()

void ResultSetStorage::initializeRowWise ( ) const
private

Definition at line 1108 of file ResultSetReduction.cpp.

References align_to_int64(), buff_, CHECK, CHECK_EQ, anonymous_namespace{ResultSetReduction.cpp}::fill_empty_key_32(), anonymous_namespace{ResultSetReduction.cpp}::fill_empty_key_64(), get_key_bytes_rowwise(), get_row_bytes(), QueryMemoryDescriptor::getEffectiveKeyWidth(), QueryMemoryDescriptor::getEntryCount(), QueryMemoryDescriptor::getGroupbyColCount(), QueryMemoryDescriptor::hasKeylessHash(), query_mem_desc_, and target_init_vals_.

Referenced by updateEntryCount().

1108  {
1109  const auto key_count = query_mem_desc_.getGroupbyColCount();
1110  const auto row_size = get_row_bytes(query_mem_desc_);
1111  CHECK_EQ(row_size % 8, 0u);
1112  const auto key_bytes_with_padding =
1116  case 4: {
1117  for (size_t i = 0; i < query_mem_desc_.getEntryCount(); ++i) {
1118  auto row_ptr = buff_ + i * row_size;
1119  fill_empty_key_32(reinterpret_cast<int32_t*>(row_ptr), key_count);
1120  auto slot_ptr = reinterpret_cast<int64_t*>(row_ptr + key_bytes_with_padding);
1121  for (size_t j = 0; j < target_init_vals_.size(); ++j) {
1122  slot_ptr[j] = target_init_vals_[j];
1123  }
1124  }
1125  break;
1126  }
1127  case 8: {
1128  for (size_t i = 0; i < query_mem_desc_.getEntryCount(); ++i) {
1129  auto row_ptr = buff_ + i * row_size;
1130  fill_empty_key_64(reinterpret_cast<int64_t*>(row_ptr), key_count);
1131  auto slot_ptr = reinterpret_cast<int64_t*>(row_ptr + key_bytes_with_padding);
1132  for (size_t j = 0; j < target_init_vals_.size(); ++j) {
1133  slot_ptr[j] = target_init_vals_[j];
1134  }
1135  }
1136  break;
1137  }
1138  default:
1139  CHECK(false);
1140  }
1141 }
#define CHECK_EQ(x, y)
Definition: Logger.h:201
std::vector< int64_t > target_init_vals_
Definition: ResultSet.h:207
ALWAYS_INLINE void fill_empty_key_32(int32_t *key_ptr_i32, const size_t key_count)
size_t get_row_bytes(const QueryMemoryDescriptor &query_mem_desc)
int8_t * buff_
Definition: ResultSet.h:205
#define CHECK(condition)
Definition: Logger.h:193
ALWAYS_INLINE void fill_empty_key_64(int64_t *key_ptr_i64, const size_t key_count)
size_t get_key_bytes_rowwise(const QueryMemoryDescriptor &query_mem_desc)
FORCE_INLINE HOST DEVICE T align_to_int64(T addr)
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
size_t getEffectiveKeyWidth() const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ isEmptyEntry() [1/2]

bool ResultSetStorage::isEmptyEntry ( const size_t  entry_idx,
const int8_t *  buff 
) const
private

Definition at line 2039 of file ResultSetIteration.cpp.

References CHECK, CHECK_GE, CHECK_LT, QueryMemoryDescriptor::didOutputColumnar(), EMPTY_KEY_32, EMPTY_KEY_64, get_byteoff_of_slot(), QueryMemoryDescriptor::getEffectiveKeyWidth(), QueryMemoryDescriptor::getPaddedSlotWidthBytes(), QueryMemoryDescriptor::getQueryDescriptionType(), QueryMemoryDescriptor::getTargetIdxForKey(), GroupByPerfectHash, QueryMemoryDescriptor::hasKeylessHash(), NonGroupedAggregate, ResultSet::query_mem_desc_, read_int_from_buff(), and row_ptr_rowwise().

Referenced by reduceOneEntryBaseline(), rewriteAggregateBufferOffsets(), and updateEntryCount().

2039  {
2042  return false;
2043  }
2045  return isEmptyEntryColumnar(entry_idx, buff);
2046  }
2051  CHECK_LT(static_cast<size_t>(query_mem_desc_.getTargetIdxForKey()),
2052  target_init_vals_.size());
2053  const auto rowwise_target_ptr = row_ptr_rowwise(buff, query_mem_desc_, entry_idx);
2054  const auto target_slot_off =
2056  return read_int_from_buff(rowwise_target_ptr + target_slot_off,
2060  } else {
2061  const auto keys_ptr = row_ptr_rowwise(buff, query_mem_desc_, entry_idx);
2063  case 4:
2066  return *reinterpret_cast<const int32_t*>(keys_ptr) == EMPTY_KEY_32;
2067  case 8:
2068  return *reinterpret_cast<const int64_t*>(keys_ptr) == EMPTY_KEY_64;
2069  default:
2070  CHECK(false);
2071  return true;
2072  }
2073  }
2074 }
#define EMPTY_KEY_64
std::vector< int64_t > target_init_vals_
Definition: ResultSet.h:207
#define CHECK_GE(x, y)
Definition: Logger.h:206
int64_t read_int_from_buff(const int8_t *ptr, const int8_t compact_sz)
const int8_t getPaddedSlotWidthBytes(const size_t slot_idx) const
size_t get_byteoff_of_slot(const size_t slot_idx, const QueryMemoryDescriptor &query_mem_desc)
T row_ptr_rowwise(T buff, const QueryMemoryDescriptor &query_mem_desc, const size_t entry_idx)
int32_t getTargetIdxForKey() const
#define CHECK_LT(x, y)
Definition: Logger.h:203
#define CHECK(condition)
Definition: Logger.h:193
#define EMPTY_KEY_32
bool isEmptyEntryColumnar(const size_t entry_idx, const int8_t *buff) const
QueryDescriptionType getQueryDescriptionType() const
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
size_t getEffectiveKeyWidth() const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ isEmptyEntry() [2/2]

bool ResultSetStorage::isEmptyEntry ( const size_t  entry_idx) const
private

Definition at line 2127 of file ResultSetIteration.cpp.

2127  {
2128  return isEmptyEntry(entry_idx, buff_);
2129 }
bool isEmptyEntry(const size_t entry_idx, const int8_t *buff) const
int8_t * buff_
Definition: ResultSet.h:205

◆ isEmptyEntryColumnar()

bool ResultSetStorage::isEmptyEntryColumnar ( const size_t  entry_idx,
const int8_t *  buff 
) const
private

Definition at line 2080 of file ResultSetIteration.cpp.

References anonymous_namespace{ResultSetIteration.cpp}::advance_col_buff_to_slot(), CHECK, CHECK_GE, CHECK_LT, QueryMemoryDescriptor::didOutputColumnar(), EMPTY_KEY_16, EMPTY_KEY_32, EMPTY_KEY_64, EMPTY_KEY_8, QueryMemoryDescriptor::getGroupbyColCount(), QueryMemoryDescriptor::getPaddedSlotWidthBytes(), QueryMemoryDescriptor::getPrependedGroupColOffInBytes(), QueryMemoryDescriptor::getQueryDescriptionType(), QueryMemoryDescriptor::getTargetIdxForKey(), GroupByPerfectHash, QueryMemoryDescriptor::groupColWidth(), QueryMemoryDescriptor::hasKeylessHash(), NonGroupedAggregate, Projection, ResultSet::query_mem_desc_, read_int_from_buff(), and ResultSet::targets_.

Referenced by reduceEntriesNoCollisionsColWise(), and updateEntryCount().

2081  {
2085  return false;
2086  }
2091  CHECK_LT(static_cast<size_t>(query_mem_desc_.getTargetIdxForKey()),
2092  target_init_vals_.size());
2093  const auto col_buff = advance_col_buff_to_slot(
2095  const auto entry_buff =
2096  col_buff + entry_idx * query_mem_desc_.getPaddedSlotWidthBytes(
2098  return read_int_from_buff(entry_buff,
2102  } else {
2103  // it's enough to find the first group key which is empty
2105  return reinterpret_cast<const int64_t*>(buff)[entry_idx] == EMPTY_KEY_64;
2106  } else {
2108  const auto target_buff = buff + query_mem_desc_.getPrependedGroupColOffInBytes(0);
2109  switch (query_mem_desc_.groupColWidth(0)) {
2110  case 8:
2111  return reinterpret_cast<const int64_t*>(target_buff)[entry_idx] == EMPTY_KEY_64;
2112  case 4:
2113  return reinterpret_cast<const int32_t*>(target_buff)[entry_idx] == EMPTY_KEY_32;
2114  case 2:
2115  return reinterpret_cast<const int16_t*>(target_buff)[entry_idx] == EMPTY_KEY_16;
2116  case 1:
2117  return reinterpret_cast<const int8_t*>(target_buff)[entry_idx] == EMPTY_KEY_8;
2118  default:
2119  CHECK(false);
2120  }
2121  }
2122  return false;
2123  }
2124  return false;
2125 }
#define EMPTY_KEY_64
const std::vector< TargetInfo > targets_
Definition: ResultSet.h:203
std::vector< int64_t > target_init_vals_
Definition: ResultSet.h:207
#define CHECK_GE(x, y)
Definition: Logger.h:206
int64_t read_int_from_buff(const int8_t *ptr, const int8_t compact_sz)
const int8_t getPaddedSlotWidthBytes(const size_t slot_idx) const
const int8_t * advance_col_buff_to_slot(const int8_t *buff, const QueryMemoryDescriptor &query_mem_desc, const std::vector< TargetInfo > &targets, const size_t slot_idx, const bool separate_varlen_storage)
#define EMPTY_KEY_8
int8_t groupColWidth(const size_t key_idx) const
int32_t getTargetIdxForKey() const
#define CHECK_LT(x, y)
Definition: Logger.h:203
#define EMPTY_KEY_16
#define CHECK(condition)
Definition: Logger.h:193
#define EMPTY_KEY_32
QueryDescriptionType getQueryDescriptionType() const
size_t getPrependedGroupColOffInBytes(const size_t group_idx) const
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mappedPtr()

int64_t ResultSetStorage::mappedPtr ( const int64_t  remote_ptr) const
private

Definition at line 847 of file ResultSet.cpp.

Referenced by updateEntryCount().

847  {
848  const auto it = count_distinct_sets_mapping_.find(remote_ptr);
849  // Due to the removal of completely zero bitmaps in a distributed transfer there will be
850  // remote ptr that do not not exists. Return 0 if no pointer found
851  if (it == count_distinct_sets_mapping_.end()) {
852  return int64_t(0);
853  }
854  return it->second;
855 }
std::unordered_map< int64_t, int64_t > count_distinct_sets_mapping_
Definition: ResultSet.h:213
+ Here is the caller graph for this function:

◆ moveEntriesToBuffer()

template<class KeyType >
void ResultSetStorage::moveEntriesToBuffer ( int8_t *  new_buff,
const size_t  new_entry_count 
) const

Definition at line 888 of file ResultSetReduction.cpp.

References buff_, CHECK, CHECK_GT, cpu_threads(), anonymous_namespace{ResultSetReduction.cpp}::get_row_qw_count(), QueryMemoryDescriptor::getEffectiveKeyWidth(), QueryMemoryDescriptor::getEntryCount(), QueryMemoryDescriptor::getGroupbyColCount(), QueryMemoryDescriptor::getQueryDescriptionType(), GroupByBaselineHash, QueryMemoryDescriptor::hasKeylessHash(), query_mem_desc_, and anonymous_namespace{ResultSetReduction.cpp}::use_multithreaded_reduction().

889  {
891  CHECK_GT(new_entry_count, query_mem_desc_.getEntryCount());
892  auto new_buff_i64 = reinterpret_cast<int64_t*>(new_buff);
893  const auto key_count = query_mem_desc_.getGroupbyColCount();
896  const auto src_buff = reinterpret_cast<const int64_t*>(buff_);
897  const auto row_qw_count = get_row_qw_count(query_mem_desc_);
898  const auto key_byte_width = query_mem_desc_.getEffectiveKeyWidth();
899 
901  const size_t thread_count = cpu_threads();
902  std::vector<std::future<void>> move_threads;
903 
904  for (size_t thread_idx = 0; thread_idx < thread_count; ++thread_idx) {
905  const auto thread_entry_count =
906  (query_mem_desc_.getEntryCount() + thread_count - 1) / thread_count;
907  const auto start_index = thread_idx * thread_entry_count;
908  const auto end_index =
909  std::min(start_index + thread_entry_count, query_mem_desc_.getEntryCount());
910  move_threads.emplace_back(std::async(
911  std::launch::async,
912  [this,
913  src_buff,
914  new_buff_i64,
915  new_entry_count,
916  start_index,
917  end_index,
918  key_count,
919  row_qw_count,
920  key_byte_width] {
921  for (size_t entry_idx = start_index; entry_idx < end_index; ++entry_idx) {
922  moveOneEntryToBuffer<KeyType>(entry_idx,
923  new_buff_i64,
924  new_entry_count,
925  key_count,
926  row_qw_count,
927  src_buff,
928  key_byte_width);
929  }
930  }));
931  }
932  for (auto& move_thread : move_threads) {
933  move_thread.wait();
934  }
935  for (auto& move_thread : move_threads) {
936  move_thread.get();
937  }
938  } else {
939  for (size_t entry_idx = 0; entry_idx < query_mem_desc_.getEntryCount(); ++entry_idx) {
940  moveOneEntryToBuffer<KeyType>(entry_idx,
941  new_buff_i64,
942  new_entry_count,
943  key_count,
944  row_qw_count,
945  src_buff,
946  key_byte_width);
947  }
948  }
949 }
#define CHECK_GT(x, y)
Definition: Logger.h:205
int8_t * buff_
Definition: ResultSet.h:205
bool use_multithreaded_reduction(const size_t entry_count)
#define CHECK(condition)
Definition: Logger.h:193
size_t get_row_qw_count(const QueryMemoryDescriptor &query_mem_desc)
QueryDescriptionType getQueryDescriptionType() const
int cpu_threads()
Definition: thread_count.h:25
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
size_t getEffectiveKeyWidth() const
+ Here is the call graph for this function:

◆ moveOneEntryToBuffer()

template<class KeyType >
void ResultSetStorage::moveOneEntryToBuffer ( const size_t  entry_index,
int64_t *  new_buff_i64,
const size_t  new_entry_count,
const size_t  key_count,
const size_t  row_qw_count,
const int64_t *  src_buff,
const size_t  key_byte_width 
) const

Definition at line 952 of file ResultSetReduction.cpp.

References CHECK, QueryMemoryDescriptor::didOutputColumnar(), anonymous_namespace{ResultSetReduction.cpp}::fill_slots(), get_group_value(), get_group_value_columnar(), QueryMemoryDescriptor::getEntryCount(), key_offset_colwise(), anonymous_namespace{ResultSetReduction.cpp}::make_key(), and query_mem_desc_.

958  {
959  const auto key_off =
962  : row_qw_count * entry_index;
963  const auto key_ptr = reinterpret_cast<const KeyType*>(&src_buff[key_off]);
964  if (*key_ptr == get_empty_key<KeyType>()) {
965  return;
966  }
967  int64_t* new_entries_ptr{nullptr};
969  const auto key =
970  make_key(&src_buff[key_off], query_mem_desc_.getEntryCount(), key_count);
971  new_entries_ptr =
972  get_group_value_columnar(new_buff_i64, new_entry_count, &key[0], key_count);
973  } else {
974  new_entries_ptr = get_group_value(new_buff_i64,
975  new_entry_count,
976  &src_buff[key_off],
977  key_count,
978  key_byte_width,
979  row_qw_count,
980  nullptr);
981  }
982  CHECK(new_entries_ptr);
983  fill_slots(new_entries_ptr,
984  new_entry_count,
985  src_buff,
986  entry_index,
989 }
NEVER_INLINE DEVICE int64_t * get_group_value_columnar(int64_t *groups_buffer, const uint32_t groups_buffer_entry_count, const int64_t *key, const uint32_t key_qw_count)
void fill_slots(int64_t *dst_entry, const size_t dst_entry_count, const int64_t *src_buff, const size_t src_entry_idx, const size_t src_entry_count, const QueryMemoryDescriptor &query_mem_desc)
std::vector< int64_t > make_key(const int64_t *buff, const size_t entry_count, const size_t key_count)
NEVER_INLINE DEVICE int64_t * get_group_value(int64_t *groups_buffer, const uint32_t groups_buffer_entry_count, const int64_t *key, const uint32_t key_count, const uint32_t key_width, const uint32_t row_size_quad, const int64_t *init_vals)
size_t key_offset_colwise(const size_t entry_idx, const size_t key_idx, const size_t entry_count)
#define CHECK(condition)
Definition: Logger.h:193
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
+ Here is the call graph for this function:

◆ reduce()

void ResultSetStorage::reduce ( const ResultSetStorage that,
const std::vector< std::string > &  serialized_varlen_buffer,
const ReductionCode reduction_code 
) const

Definition at line 199 of file ResultSetReduction.cpp.

References buff_, CHECK, CHECK_EQ, CHECK_GE, CHECK_GT, cpu_threads(), QueryMemoryDescriptor::didOutputColumnar(), QueryMemoryDescriptor::getEntryCount(), QueryMemoryDescriptor::getQueryDescriptionType(), GroupByBaselineHash, GroupByPerfectHash, ReductionCode::ir_reduce_loop, NonGroupedAggregate, query_mem_desc_, reduceEntriesNoCollisionsColWise(), reduceOneEntryBaseline(), anonymous_namespace{ResultSetReduction.cpp}::run_reduction_code(), and anonymous_namespace{ResultSetReduction.cpp}::use_multithreaded_reduction().

Referenced by reduceOneSlotSingleValue().

201  {
202  auto entry_count = query_mem_desc_.getEntryCount();
203  CHECK_GT(entry_count, size_t(0));
211  }
212  const auto that_entry_count = that.query_mem_desc_.getEntryCount();
215  CHECK_GE(entry_count, that_entry_count);
216  break;
217  default:
218  CHECK_EQ(entry_count, that_entry_count);
219  }
220  auto this_buff = buff_;
221  CHECK(this_buff);
222  auto that_buff = that.buff_;
223  CHECK(that_buff);
226  if (!serialized_varlen_buffer.empty()) {
227  throw std::runtime_error(
228  "Projection of variable length targets with baseline hash group by is not yet "
229  "supported in Distributed mode");
230  }
231  if (use_multithreaded_reduction(that_entry_count)) {
232  const size_t thread_count = cpu_threads();
233  std::vector<std::future<void>> reduction_threads;
234  for (size_t thread_idx = 0; thread_idx < thread_count; ++thread_idx) {
235  const auto thread_entry_count =
236  (that_entry_count + thread_count - 1) / thread_count;
237  const auto start_index = thread_idx * thread_entry_count;
238  const auto end_index =
239  std::min(start_index + thread_entry_count, that_entry_count);
240  reduction_threads.emplace_back(std::async(
241  std::launch::async,
242  [this,
243  this_buff,
244  that_buff,
245  start_index,
246  end_index,
247  that_entry_count,
248  &reduction_code,
249  &that] {
250  if (reduction_code.ir_reduce_loop) {
251  run_reduction_code(reduction_code,
252  this_buff,
253  that_buff,
254  start_index,
255  end_index,
256  that_entry_count,
257  &query_mem_desc_,
258  &that.query_mem_desc_,
259  nullptr);
260  } else {
261  for (size_t entry_idx = start_index; entry_idx < end_index; ++entry_idx) {
262  reduceOneEntryBaseline(
263  this_buff, that_buff, entry_idx, that_entry_count, that);
264  }
265  }
266  }));
267  }
268  for (auto& reduction_thread : reduction_threads) {
269  reduction_thread.wait();
270  }
271  for (auto& reduction_thread : reduction_threads) {
272  reduction_thread.get();
273  }
274  } else {
275  if (reduction_code.ir_reduce_loop) {
276  run_reduction_code(reduction_code,
277  this_buff,
278  that_buff,
279  0,
280  that_entry_count,
281  that_entry_count,
283  &that.query_mem_desc_,
284  nullptr);
285  } else {
286  for (size_t i = 0; i < that_entry_count; ++i) {
287  reduceOneEntryBaseline(this_buff, that_buff, i, that_entry_count, that);
288  }
289  }
290  }
291  return;
292  }
293  if (use_multithreaded_reduction(entry_count)) {
294  const size_t thread_count = cpu_threads();
295  std::vector<std::future<void>> reduction_threads;
296  for (size_t thread_idx = 0; thread_idx < thread_count; ++thread_idx) {
297  const auto thread_entry_count = (entry_count + thread_count - 1) / thread_count;
298  const auto start_index = thread_idx * thread_entry_count;
299  const auto end_index = std::min(start_index + thread_entry_count, entry_count);
301  reduction_threads.emplace_back(std::async(std::launch::async,
302  [this,
303  this_buff,
304  that_buff,
305  start_index,
306  end_index,
307  &that,
308  &serialized_varlen_buffer] {
310  this_buff,
311  that_buff,
312  that,
313  start_index,
314  end_index,
315  serialized_varlen_buffer);
316  }));
317  } else {
318  reduction_threads.emplace_back(std::async(std::launch::async,
319  [this,
320  this_buff,
321  that_buff,
322  start_index,
323  end_index,
324  that_entry_count,
325  &reduction_code,
326  &that,
327  &serialized_varlen_buffer] {
328  CHECK(reduction_code.ir_reduce_loop);
330  reduction_code,
331  this_buff,
332  that_buff,
333  start_index,
334  end_index,
335  that_entry_count,
337  &that.query_mem_desc_,
338  &serialized_varlen_buffer);
339  }));
340  }
341  }
342  for (auto& reduction_thread : reduction_threads) {
343  reduction_thread.wait();
344  }
345  for (auto& reduction_thread : reduction_threads) {
346  reduction_thread.get();
347  }
348  } else {
351  that_buff,
352  that,
353  0,
355  serialized_varlen_buffer);
356  } else {
357  CHECK(reduction_code.ir_reduce_loop);
358  run_reduction_code(reduction_code,
359  this_buff,
360  that_buff,
361  0,
362  entry_count,
363  that_entry_count,
365  &that.query_mem_desc_,
366  &serialized_varlen_buffer);
367  }
368  }
369 }
#define CHECK_EQ(x, y)
Definition: Logger.h:201
void run_reduction_code(const ReductionCode &reduction_code, int8_t *this_buff, const int8_t *that_buff, const int32_t start_entry_index, const int32_t end_entry_index, const int32_t that_entry_count, const void *this_qmd, const void *that_qmd, const void *serialized_varlen_buffer)
void reduceOneEntryBaseline(int8_t *this_buff, const int8_t *that_buff, const size_t i, const size_t that_entry_count, const ResultSetStorage &that) const
std::unique_ptr< Function > ir_reduce_loop
#define CHECK_GE(x, y)
Definition: Logger.h:206
#define CHECK_GT(x, y)
Definition: Logger.h:205
int8_t * buff_
Definition: ResultSet.h:205
bool use_multithreaded_reduction(const size_t entry_count)
#define CHECK(condition)
Definition: Logger.h:193
void reduceEntriesNoCollisionsColWise(int8_t *this_buff, const int8_t *that_buff, const ResultSetStorage &that, const size_t start_index, const size_t end_index, const std::vector< std::string > &serialized_varlen_buffer) const
QueryDescriptionType getQueryDescriptionType() const
int cpu_threads()
Definition: thread_count.h:25
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduceEntriesNoCollisionsColWise()

void ResultSetStorage::reduceEntriesNoCollisionsColWise ( int8_t *  this_buff,
const int8_t *  that_buff,
const ResultSetStorage that,
const size_t  start_index,
const size_t  end_index,
const std::vector< std::string > &  serialized_varlen_buffer 
) const
private

Definition at line 385 of file ResultSetReduction.cpp.

References advance_to_next_columnar_target_buff(), CHECK, anonymous_namespace{ResultSetReduction.cpp}::check_watchdog(), copyKeyColWise(), get_cols_ptr(), QueryMemoryDescriptor::getColSlotContext(), QueryMemoryDescriptor::getPaddedSlotWidthBytes(), QueryMemoryDescriptor::hasKeylessHash(), isEmptyEntryColumnar(), kAVG, kSAMPLE, LIKELY, query_mem_desc_, reduceOneSlot(), targets_, and UNLIKELY.

Referenced by reduce(), and updateEntryCount().

391  {
392  // TODO(adb / saman): Support column wise output when serializing distributed agg
393  // functions
394  CHECK(serialized_varlen_buffer.empty());
395 
396  const auto& col_slot_context = query_mem_desc_.getColSlotContext();
397 
398  auto this_crt_col_ptr = get_cols_ptr(this_buff, query_mem_desc_);
399  auto that_crt_col_ptr = get_cols_ptr(that_buff, query_mem_desc_);
400  for (size_t target_idx = 0; target_idx < targets_.size(); ++target_idx) {
401  const auto& agg_info = targets_[target_idx];
402  const auto& slots_for_col = col_slot_context.getSlotsForCol(target_idx);
403 
404  bool two_slot_target{false};
405  if (agg_info.is_agg &&
406  (agg_info.agg_kind == kAVG ||
407  (agg_info.agg_kind == kSAMPLE && agg_info.sql_type.is_varlen()))) {
408  // Note that this assumes if one of the slot pairs in a given target is an array,
409  // all slot pairs are arrays. Currently this is true for all geo targets, but we
410  // should better codify and store this information in the future
411  two_slot_target = true;
412  }
413 
414  for (size_t target_slot_idx = slots_for_col.front();
415  target_slot_idx < slots_for_col.back() + 1;
416  target_slot_idx += 2) {
417  const auto this_next_col_ptr = advance_to_next_columnar_target_buff(
418  this_crt_col_ptr, query_mem_desc_, target_slot_idx);
419  const auto that_next_col_ptr = advance_to_next_columnar_target_buff(
420  that_crt_col_ptr, query_mem_desc_, target_slot_idx);
421 
422  for (size_t entry_idx = start_index; entry_idx < end_index; ++entry_idx) {
423  check_watchdog(entry_idx);
424  if (isEmptyEntryColumnar(entry_idx, that_buff)) {
425  continue;
426  }
428  // copy the key from right hand side
429  copyKeyColWise(entry_idx, this_buff, that_buff);
430  }
431  auto this_ptr1 =
432  this_crt_col_ptr +
433  entry_idx * query_mem_desc_.getPaddedSlotWidthBytes(target_slot_idx);
434  auto that_ptr1 =
435  that_crt_col_ptr +
436  entry_idx * query_mem_desc_.getPaddedSlotWidthBytes(target_slot_idx);
437  int8_t* this_ptr2{nullptr};
438  const int8_t* that_ptr2{nullptr};
439  if (UNLIKELY(two_slot_target)) {
440  this_ptr2 =
441  this_next_col_ptr +
442  entry_idx * query_mem_desc_.getPaddedSlotWidthBytes(target_slot_idx + 1);
443  that_ptr2 =
444  that_next_col_ptr +
445  entry_idx * query_mem_desc_.getPaddedSlotWidthBytes(target_slot_idx + 1);
446  }
447  reduceOneSlot(this_ptr1,
448  this_ptr2,
449  that_ptr1,
450  that_ptr2,
451  agg_info,
452  target_idx,
453  target_slot_idx,
454  target_slot_idx,
455  that,
456  slots_for_col.front(),
457  serialized_varlen_buffer);
458  }
459 
460  this_crt_col_ptr = this_next_col_ptr;
461  that_crt_col_ptr = that_next_col_ptr;
462  if (UNLIKELY(two_slot_target)) {
463  this_crt_col_ptr = advance_to_next_columnar_target_buff(
464  this_crt_col_ptr, query_mem_desc_, target_slot_idx + 1);
465  that_crt_col_ptr = advance_to_next_columnar_target_buff(
466  that_crt_col_ptr, query_mem_desc_, target_slot_idx + 1);
467  }
468  }
469  }
470 }
void copyKeyColWise(const size_t entry_idx, int8_t *this_buff, const int8_t *that_buff) const
const std::vector< TargetInfo > targets_
Definition: ResultSet.h:203
T advance_to_next_columnar_target_buff(T target_ptr, const QueryMemoryDescriptor &query_mem_desc, const size_t target_slot_idx)
const int8_t getPaddedSlotWidthBytes(const size_t slot_idx) const
ALWAYS_INLINE void check_watchdog(const size_t sample_seed)
#define LIKELY(x)
Definition: likely.h:19
#define UNLIKELY(x)
Definition: likely.h:20
ALWAYS_INLINE void reduceOneSlot(int8_t *this_ptr1, int8_t *this_ptr2, const int8_t *that_ptr1, const int8_t *that_ptr2, const TargetInfo &target_info, const size_t target_logical_idx, const size_t target_slot_idx, const size_t init_agg_val_idx, const ResultSetStorage &that, const size_t first_slot_idx_for_target, const std::vector< std::string > &serialized_varlen_buffer) const
#define CHECK(condition)
Definition: Logger.h:193
const ColSlotContext & getColSlotContext() const
bool isEmptyEntryColumnar(const size_t entry_idx, const int8_t *buff) const
T get_cols_ptr(T buff, const QueryMemoryDescriptor &query_mem_desc)
Definition: sqldefs.h:72
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduceOneCountDistinctSlot()

void ResultSetStorage::reduceOneCountDistinctSlot ( int8_t *  this_ptr1,
const int8_t *  that_ptr1,
const size_t  target_logical_idx,
const ResultSetStorage that 
) const
private

Definition at line 1542 of file ResultSetReduction.cpp.

References CHECK, CHECK_LT, count_distinct_set_union(), QueryMemoryDescriptor::getCountDistinctDescriptor(), QueryMemoryDescriptor::getCountDistinctDescriptorsSize(), Invalid, and query_mem_desc_.

Referenced by reduceOneSlot(), and updateEntryCount().

1545  {
1547  const auto& old_count_distinct_desc =
1548  query_mem_desc_.getCountDistinctDescriptor(target_logical_idx);
1549  CHECK(old_count_distinct_desc.impl_type_ != CountDistinctImplType::Invalid);
1550  const auto& new_count_distinct_desc =
1551  that.query_mem_desc_.getCountDistinctDescriptor(target_logical_idx);
1552  CHECK(old_count_distinct_desc.impl_type_ == new_count_distinct_desc.impl_type_);
1553  CHECK(this_ptr1 && that_ptr1);
1554  auto old_set_ptr = reinterpret_cast<const int64_t*>(this_ptr1);
1555  auto new_set_ptr = reinterpret_cast<const int64_t*>(that_ptr1);
1557  *new_set_ptr, *old_set_ptr, new_count_distinct_desc, old_count_distinct_desc);
1558 }
void count_distinct_set_union(const int64_t new_set_handle, const int64_t old_set_handle, const CountDistinctDescriptor &new_count_distinct_desc, const CountDistinctDescriptor &old_count_distinct_desc)
size_t getCountDistinctDescriptorsSize() const
#define CHECK_LT(x, y)
Definition: Logger.h:203
#define CHECK(condition)
Definition: Logger.h:193
const CountDistinctDescriptor & getCountDistinctDescriptor(const size_t idx) const
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduceOneEntryBaseline()

void ResultSetStorage::reduceOneEntryBaseline ( int8_t *  this_buff,
const int8_t *  that_buff,
const size_t  i,
const size_t  that_entry_count,
const ResultSetStorage that 
) const
private

Definition at line 777 of file ResultSetReduction.cpp.

References CHECK, anonymous_namespace{ResultSetReduction.cpp}::check_watchdog(), QueryMemoryDescriptor::didOutputColumnar(), anonymous_namespace{ResultSetReduction.cpp}::fill_slots(), anonymous_namespace{ResultSetReduction.cpp}::get_group_value_columnar_reduction(), QueryMemoryDescriptor::getEntryCount(), QueryMemoryDescriptor::getGroupbyColCount(), QueryMemoryDescriptor::getQueryDescriptionType(), GroupByBaselineHash, QueryMemoryDescriptor::hasKeylessHash(), isEmptyEntry(), key_offset_colwise(), anonymous_namespace{ResultSetReduction.cpp}::make_key(), query_mem_desc_, and reduceOneEntrySlotsBaseline().

Referenced by reduce(), and updateEntryCount().

781  {
782  check_watchdog(that_entry_idx);
783  const auto key_count = query_mem_desc_.getGroupbyColCount();
788  const auto key_off =
790  if (isEmptyEntry(that_entry_idx, that_buff)) {
791  return;
792  }
793  int64_t* this_entry_slots{nullptr};
794  auto this_buff_i64 = reinterpret_cast<int64_t*>(this_buff);
795  auto that_buff_i64 = reinterpret_cast<const int64_t*>(that_buff);
796  bool empty_entry = false;
797  const auto key = make_key(&that_buff_i64[key_off], that_entry_count, key_count);
798  std::tie(this_entry_slots, empty_entry) = get_group_value_columnar_reduction(
799  this_buff_i64, query_mem_desc_.getEntryCount(), &key[0], key_count);
800  CHECK(this_entry_slots);
801  if (empty_entry) {
802  fill_slots(this_entry_slots,
804  that_buff_i64,
805  that_entry_idx,
806  that_entry_count,
808  return;
809  }
811  this_entry_slots, that_buff_i64, that_entry_idx, that_entry_count, that);
812 }
void fill_slots(int64_t *dst_entry, const size_t dst_entry_count, const int64_t *src_buff, const size_t src_entry_idx, const size_t src_entry_count, const QueryMemoryDescriptor &query_mem_desc)
GroupValueInfo get_group_value_columnar_reduction(int64_t *groups_buffer, const uint32_t groups_buffer_entry_count, const int64_t *key, const uint32_t key_qw_count)
std::vector< int64_t > make_key(const int64_t *buff, const size_t entry_count, const size_t key_count)
bool isEmptyEntry(const size_t entry_idx, const int8_t *buff) const
void reduceOneEntrySlotsBaseline(int64_t *this_entry_slots, const int64_t *that_buff, const size_t that_entry_idx, const size_t that_entry_count, const ResultSetStorage &that) const
ALWAYS_INLINE void check_watchdog(const size_t sample_seed)
size_t key_offset_colwise(const size_t entry_idx, const size_t key_idx, const size_t entry_count)
#define CHECK(condition)
Definition: Logger.h:193
QueryDescriptionType getQueryDescriptionType() const
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduceOneEntrySlotsBaseline()

void ResultSetStorage::reduceOneEntrySlotsBaseline ( int64_t *  this_entry_slots,
const int64_t *  that_buff,
const size_t  that_entry_idx,
const size_t  that_entry_count,
const ResultSetStorage that 
) const
private

Definition at line 814 of file ResultSetReduction.cpp.

References advance_slot(), CHECK, QueryMemoryDescriptor::didOutputColumnar(), QueryMemoryDescriptor::getEntryCount(), QueryMemoryDescriptor::getGroupbyColCount(), QueryMemoryDescriptor::getTargetGroupbyIndex(), query_mem_desc_, reduceOneSlotBaseline(), slot_offset_colwise(), QueryMemoryDescriptor::targetGroupbyIndicesSize(), and targets_.

Referenced by reduceOneEntryBaseline(), and updateEntryCount().

818  {
820  const auto key_count = query_mem_desc_.getGroupbyColCount();
821  size_t j = 0;
822  size_t init_agg_val_idx = 0;
823  for (size_t target_logical_idx = 0; target_logical_idx < targets_.size();
824  ++target_logical_idx) {
825  const auto& target_info = targets_[target_logical_idx];
826  const auto that_slot_off = slot_offset_colwise(
827  that_entry_idx, init_agg_val_idx, key_count, that_entry_count);
828  const auto this_slot_off = init_agg_val_idx * query_mem_desc_.getEntryCount();
829  reduceOneSlotBaseline(this_entry_slots,
830  this_slot_off,
831  that_buff,
832  that_entry_count,
833  that_slot_off,
834  target_info,
835  target_logical_idx,
836  j,
837  init_agg_val_idx,
838  that);
840  init_agg_val_idx = advance_slot(init_agg_val_idx, target_info, false);
841  } else {
842  if (query_mem_desc_.getTargetGroupbyIndex(target_logical_idx) < 0) {
843  init_agg_val_idx = advance_slot(init_agg_val_idx, target_info, false);
844  }
845  }
846  j = advance_slot(j, target_info, false);
847  }
848 }
const std::vector< TargetInfo > targets_
Definition: ResultSet.h:203
ssize_t getTargetGroupbyIndex(const size_t target_idx) const
size_t slot_offset_colwise(const size_t entry_idx, const size_t slot_idx, const size_t key_count, const size_t entry_count)
size_t advance_slot(const size_t j, const TargetInfo &target_info, const bool separate_varlen_storage)
void reduceOneSlotBaseline(int64_t *this_buff, const size_t this_slot, const int64_t *that_buff, const size_t that_entry_count, const size_t that_slot, const TargetInfo &target_info, const size_t target_logical_idx, const size_t target_slot_idx, const size_t init_agg_val_idx, const ResultSetStorage &that) const
size_t targetGroupbyIndicesSize() const
#define CHECK(condition)
Definition: Logger.h:193
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduceOneSlot()

void ResultSetStorage::reduceOneSlot ( int8_t *  this_ptr1,
int8_t *  this_ptr2,
const int8_t *  that_ptr1,
const int8_t *  that_ptr2,
const TargetInfo target_info,
const size_t  target_logical_idx,
const size_t  target_slot_idx,
const size_t  init_agg_val_idx,
const ResultSetStorage that,
const size_t  first_slot_idx_for_target,
const std::vector< std::string > &  serialized_varlen_buffer 
) const
private

Definition at line 1402 of file ResultSetReduction.cpp.

References TargetInfo::agg_kind, AGGREGATE_ONE_COUNT, AGGREGATE_ONE_NULLABLE_VALUE, AGGREGATE_ONE_NULLABLE_VALUE_SMALL, CHECK, CHECK_EQ, CHECK_LT, logger::FATAL, SQLTypeInfoCore< TYPE_FACET_PACK >::get_elem_type(), get_width_for_slot(), QueryMemoryDescriptor::getPaddedSlotWidthBytes(), QueryMemoryDescriptor::getTargetGroupbyIndex(), TargetInfo::is_agg, is_distinct_target(), SQLTypeInfoCore< TYPE_FACET_PACK >::is_geometry(), SQLTypeInfoCore< TYPE_FACET_PACK >::is_string(), SQLTypeInfoCore< TYPE_FACET_PACK >::is_varlen(), QueryMemoryDescriptor::isLogicalSizedColumnsAllowed(), kAPPROX_COUNT_DISTINCT, kAVG, kCOUNT, kMAX, kMIN, kSAMPLE, kSINGLE_VALUE, kSUM, LOG, query_mem_desc_, reduceOneCountDistinctSlot(), reduceOneSlotSingleValue(), TargetInfo::sql_type, takes_float_argument(), target_init_vals_, and QueryMemoryDescriptor::targetGroupbyIndicesSize().

Referenced by reduceEntriesNoCollisionsColWise(), reduceOneSlotBaseline(), and updateEntryCount().

1413  {
1415  if (query_mem_desc_.getTargetGroupbyIndex(target_logical_idx) >= 0) {
1416  return;
1417  }
1418  }
1419  CHECK_LT(init_agg_val_idx, target_init_vals_.size());
1420  const bool float_argument_input = takes_float_argument(target_info);
1421  const auto chosen_bytes =
1422  get_width_for_slot(target_slot_idx, float_argument_input, query_mem_desc_);
1423  auto init_val = target_init_vals_[init_agg_val_idx];
1424 
1425  if (target_info.is_agg && target_info.agg_kind == kSINGLE_VALUE) {
1427  this_ptr1, target_info, target_logical_idx, init_agg_val_idx, that_ptr1);
1428  } else if (target_info.is_agg && target_info.agg_kind != kSAMPLE) {
1429  switch (target_info.agg_kind) {
1430  case kCOUNT:
1431  case kAPPROX_COUNT_DISTINCT: {
1432  if (is_distinct_target(target_info)) {
1433  CHECK_EQ(static_cast<size_t>(chosen_bytes), sizeof(int64_t));
1434  reduceOneCountDistinctSlot(this_ptr1, that_ptr1, target_logical_idx, that);
1435  break;
1436  }
1437  CHECK_EQ(int64_t(0), init_val);
1438  AGGREGATE_ONE_COUNT(this_ptr1, that_ptr1, chosen_bytes);
1439  break;
1440  }
1441  case kAVG: {
1442  // Ignore float argument compaction for count component for fear of its overflow
1443  AGGREGATE_ONE_COUNT(this_ptr2,
1444  that_ptr2,
1445  query_mem_desc_.getPaddedSlotWidthBytes(target_slot_idx));
1446  }
1447  // fall thru
1448  case kSUM: {
1450  sum, this_ptr1, that_ptr1, init_val, chosen_bytes, target_info);
1451  break;
1452  }
1453  case kMIN: {
1454  if (static_cast<size_t>(chosen_bytes) <= sizeof(int16_t)) {
1456  min, this_ptr1, that_ptr1, init_val, chosen_bytes, target_info);
1457  } else {
1459  min, this_ptr1, that_ptr1, init_val, chosen_bytes, target_info);
1460  }
1461  break;
1462  }
1463  case kMAX: {
1464  if (static_cast<size_t>(chosen_bytes) <= sizeof(int16_t)) {
1466  max, this_ptr1, that_ptr1, init_val, chosen_bytes, target_info);
1467  } else {
1469  max, this_ptr1, that_ptr1, init_val, chosen_bytes, target_info);
1470  }
1471  break;
1472  }
1473  default:
1474  CHECK(false);
1475  }
1476  } else {
1477  switch (chosen_bytes) {
1478  case 1: {
1480  const auto rhs_proj_col = *reinterpret_cast<const int8_t*>(that_ptr1);
1481  if (rhs_proj_col != init_val) {
1482  *reinterpret_cast<int8_t*>(this_ptr1) = rhs_proj_col;
1483  }
1484  break;
1485  }
1486  case 2: {
1488  const auto rhs_proj_col = *reinterpret_cast<const int16_t*>(that_ptr1);
1489  if (rhs_proj_col != init_val) {
1490  *reinterpret_cast<int16_t*>(this_ptr1) = rhs_proj_col;
1491  }
1492  break;
1493  }
1494  case 4: {
1495  CHECK(target_info.agg_kind != kSAMPLE ||
1497  const auto rhs_proj_col = *reinterpret_cast<const int32_t*>(that_ptr1);
1498  if (rhs_proj_col != init_val) {
1499  *reinterpret_cast<int32_t*>(this_ptr1) = rhs_proj_col;
1500  }
1501  break;
1502  }
1503  case 8: {
1504  auto rhs_proj_col = *reinterpret_cast<const int64_t*>(that_ptr1);
1505  if ((target_info.agg_kind == kSAMPLE && target_info.sql_type.is_varlen()) &&
1506  !serialized_varlen_buffer.empty()) {
1507  size_t length_to_elems{0};
1508  if (target_info.sql_type.is_geometry()) {
1509  // TODO: Assumes hard-coded sizes for geometry targets
1510  length_to_elems = target_slot_idx == first_slot_idx_for_target ? 1 : 4;
1511  } else {
1512  const auto& elem_ti = target_info.sql_type.get_elem_type();
1513  length_to_elems = target_info.sql_type.is_string() ? 1 : elem_ti.get_size();
1514  }
1515 
1516  CHECK_LT(static_cast<size_t>(rhs_proj_col), serialized_varlen_buffer.size());
1517  const auto& varlen_bytes_str = serialized_varlen_buffer[rhs_proj_col];
1518  const auto str_ptr = reinterpret_cast<const int8_t*>(varlen_bytes_str.c_str());
1519  *reinterpret_cast<int64_t*>(this_ptr1) =
1520  reinterpret_cast<const int64_t>(str_ptr);
1521  *reinterpret_cast<int64_t*>(this_ptr2) =
1522  static_cast<int64_t>(varlen_bytes_str.size() / length_to_elems);
1523  } else {
1524  if (rhs_proj_col != init_val) {
1525  *reinterpret_cast<int64_t*>(this_ptr1) = rhs_proj_col;
1526  }
1527  if ((target_info.agg_kind == kSAMPLE && target_info.sql_type.is_varlen())) {
1528  CHECK(this_ptr2 && that_ptr2);
1529  *reinterpret_cast<int64_t*>(this_ptr2) =
1530  *reinterpret_cast<const int64_t*>(that_ptr2);
1531  }
1532  }
1533 
1534  break;
1535  }
1536  default:
1537  LOG(FATAL) << "Invalid slot width: " << chosen_bytes;
1538  }
1539  }
1540 }
#define CHECK_EQ(x, y)
Definition: Logger.h:201
ssize_t getTargetGroupbyIndex(const size_t target_idx) const
std::vector< int64_t > target_init_vals_
Definition: ResultSet.h:207
SQLTypeInfo sql_type
Definition: TargetInfo.h:42
#define LOG(tag)
Definition: Logger.h:188
bool is_varlen() const
Definition: sqltypes.h:491
bool takes_float_argument(const TargetInfo &target_info)
Definition: TargetInfo.h:121
const int8_t getPaddedSlotWidthBytes(const size_t slot_idx) const
Definition: sqldefs.h:73
#define AGGREGATE_ONE_NULLABLE_VALUE( agg_kind__, val_ptr__, other_ptr__, init_val__, chosen_bytes__, agg_info__)
bool is_agg
Definition: TargetInfo.h:40
ALWAYS_INLINE void reduceOneSlotSingleValue(int8_t *this_ptr1, const TargetInfo &target_info, const size_t target_slot_idx, const size_t init_agg_val_idx, const int8_t *that_ptr1) const
Definition: sqldefs.h:75
bool is_distinct_target(const TargetInfo &target_info)
Definition: TargetInfo.h:117
SQLTypeInfoCore get_elem_type() const
Definition: sqltypes.h:659
size_t targetGroupbyIndicesSize() const
SQLAgg agg_kind
Definition: TargetInfo.h:41
#define AGGREGATE_ONE_NULLABLE_VALUE_SMALL( agg_kind__, val_ptr__, other_ptr__, init_val__, chosen_bytes__, agg_info__)
void reduceOneCountDistinctSlot(int8_t *this_ptr1, const int8_t *that_ptr1, const size_t target_logical_idx, const ResultSetStorage &that) const
#define CHECK_LT(x, y)
Definition: Logger.h:203
#define AGGREGATE_ONE_COUNT(val_ptr__, other_ptr__, chosen_bytes__)
Definition: sqldefs.h:76
#define CHECK(condition)
Definition: Logger.h:193
bool is_geometry() const
Definition: sqltypes.h:489
int8_t get_width_for_slot(const size_t target_slot_idx, const bool float_argument_input, const QueryMemoryDescriptor &query_mem_desc)
Definition: sqldefs.h:74
Definition: sqldefs.h:72
bool is_string() const
Definition: sqltypes.h:477
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduceOneSlotBaseline()

void ResultSetStorage::reduceOneSlotBaseline ( int64_t *  this_buff,
const size_t  this_slot,
const int64_t *  that_buff,
const size_t  that_entry_count,
const size_t  that_slot,
const TargetInfo target_info,
const size_t  target_logical_idx,
const size_t  target_slot_idx,
const size_t  init_agg_val_idx,
const ResultSetStorage that 
) const
private

Definition at line 850 of file ResultSetReduction.cpp.

References TargetInfo::agg_kind, CHECK, QueryMemoryDescriptor::didOutputColumnar(), QueryMemoryDescriptor::getEntryCount(), TargetInfo::is_agg, SQLTypeInfoCore< TYPE_FACET_PACK >::is_varlen(), kAVG, kSAMPLE, query_mem_desc_, reduceOneSlot(), and TargetInfo::sql_type.

Referenced by reduceOneEntrySlotsBaseline(), and updateEntryCount().

859  {
861  int8_t* this_ptr2{nullptr};
862  const int8_t* that_ptr2{nullptr};
863  if (target_info.is_agg &&
864  (target_info.agg_kind == kAVG ||
865  (target_info.agg_kind == kSAMPLE && target_info.sql_type.is_varlen()))) {
866  const auto this_count_off = query_mem_desc_.getEntryCount();
867  const auto that_count_off = that_entry_count;
868  this_ptr2 = reinterpret_cast<int8_t*>(&this_buff[this_slot + this_count_off]);
869  that_ptr2 = reinterpret_cast<const int8_t*>(&that_buff[that_slot + that_count_off]);
870  }
871  reduceOneSlot(reinterpret_cast<int8_t*>(&this_buff[this_slot]),
872  this_ptr2,
873  reinterpret_cast<const int8_t*>(&that_buff[that_slot]),
874  that_ptr2,
875  target_info,
876  target_logical_idx,
877  target_slot_idx,
878  init_agg_val_idx,
879  that,
880  target_slot_idx, // dummy, for now
881  {});
882 }
SQLTypeInfo sql_type
Definition: TargetInfo.h:42
bool is_varlen() const
Definition: sqltypes.h:491
bool is_agg
Definition: TargetInfo.h:40
SQLAgg agg_kind
Definition: TargetInfo.h:41
ALWAYS_INLINE void reduceOneSlot(int8_t *this_ptr1, int8_t *this_ptr2, const int8_t *that_ptr1, const int8_t *that_ptr2, const TargetInfo &target_info, const size_t target_logical_idx, const size_t target_slot_idx, const size_t init_agg_val_idx, const ResultSetStorage &that, const size_t first_slot_idx_for_target, const std::vector< std::string > &serialized_varlen_buffer) const
#define CHECK(condition)
Definition: Logger.h:193
Definition: sqldefs.h:72
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduceOneSlotSingleValue()

void ResultSetStorage::reduceOneSlotSingleValue ( int8_t *  this_ptr1,
const TargetInfo target_info,
const size_t  target_slot_idx,
const size_t  init_agg_val_idx,
const int8_t *  that_ptr1 
) const
private

Definition at line 1354 of file ResultSetReduction.cpp.

References CHECK, logger::FATAL, get_width_for_slot(), SQLTypeInfoCore< TYPE_FACET_PACK >::is_varlen(), QueryMemoryDescriptor::isLogicalSizedColumnsAllowed(), LOG, query_mem_desc_, reduce(), TargetInfo::sql_type, takes_float_argument(), and target_init_vals_.

Referenced by reduceOneSlot(), and updateEntryCount().

1358  {
1359  const bool float_argument_input = takes_float_argument(target_info);
1360  const auto chosen_bytes =
1361  get_width_for_slot(target_slot_idx, float_argument_input, query_mem_desc_);
1362  auto init_val = target_init_vals_[init_agg_val_idx];
1363 
1364  auto reduce = [&](auto const& size_tag) {
1365  using CastTarget = std::decay_t<decltype(size_tag)>;
1366  const auto lhs_proj_col = *reinterpret_cast<const CastTarget*>(this_ptr1);
1367  const auto rhs_proj_col = *reinterpret_cast<const CastTarget*>(that_ptr1);
1368  if (rhs_proj_col == init_val) {
1369  // ignore
1370  } else if (lhs_proj_col == init_val) {
1371  *reinterpret_cast<CastTarget*>(this_ptr1) = rhs_proj_col;
1372  } else if (lhs_proj_col != rhs_proj_col) {
1373  throw std::runtime_error("Multiple distinct values encountered");
1374  }
1375  };
1376 
1377  switch (chosen_bytes) {
1378  case 1: {
1380  reduce(int8_t());
1381  break;
1382  }
1383  case 2: {
1385  reduce(int16_t());
1386  break;
1387  }
1388  case 4: {
1389  reduce(int32_t());
1390  break;
1391  }
1392  case 8: {
1393  CHECK(!target_info.sql_type.is_varlen());
1394  reduce(int64_t());
1395  break;
1396  }
1397  default:
1398  LOG(FATAL) << "Invalid slot width: " << chosen_bytes;
1399  }
1400 }
std::vector< int64_t > target_init_vals_
Definition: ResultSet.h:207
void reduce(const ResultSetStorage &that, const std::vector< std::string > &serialized_varlen_buffer, const ReductionCode &reduction_code) const
SQLTypeInfo sql_type
Definition: TargetInfo.h:42
#define LOG(tag)
Definition: Logger.h:188
bool is_varlen() const
Definition: sqltypes.h:491
bool takes_float_argument(const TargetInfo &target_info)
Definition: TargetInfo.h:121
#define CHECK(condition)
Definition: Logger.h:193
int8_t get_width_for_slot(const size_t target_slot_idx, const bool float_argument_input, const QueryMemoryDescriptor &query_mem_desc)
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reduceSingleRow()

bool ResultSetStorage::reduceSingleRow ( const int8_t *  row_ptr,
const int8_t  warp_count,
const bool  is_columnar,
const bool  replace_bitmap_ptr_with_bitmap_sz,
std::vector< int64_t > &  agg_vals,
const QueryMemoryDescriptor query_mem_desc,
const std::vector< TargetInfo > &  targets,
const std::vector< int64_t > &  agg_init_vals 
)
static

Definition at line 1560 of file ResultSetReduction.cpp.

References agg_col_count, AGGREGATE_ONE_COUNT, AGGREGATE_ONE_NULLABLE_COUNT, AGGREGATE_ONE_NULLABLE_VALUE, AGGREGATE_ONE_NULLABLE_VALUE_SMALL, CHECK, CHECK_EQ, CHECK_GE, count_distinct_set_size(), QueryMemoryDescriptor::didOutputColumnar(), logger::ERROR, get_compact_type(), anonymous_namespace{ResultSetReduction.cpp}::get_component(), QueryMemoryDescriptor::getColOnlyOffInBytes(), QueryMemoryDescriptor::getCountDistinctDescriptor(), QueryMemoryDescriptor::getPaddedSlotWidthBytes(), QueryMemoryDescriptor::getRowSize(), QueryMemoryDescriptor::getSlotCount(), QueryMemoryDescriptor::getTargetIdxForKey(), QueryMemoryDescriptor::hasKeylessHash(), is_distinct_target(), kAPPROX_COUNT_DISTINCT, kAVG, kCOUNT, kMAX, kMIN, kSAMPLE, kSUM, LOG, and takes_float_argument().

Referenced by QueryExecutionContext::groupBufferToDeinterleavedResults(), and updateEntryCount().

1567  {
1568  const size_t agg_col_count{agg_vals.size()};
1569  const auto row_size = query_mem_desc.getRowSize();
1570  CHECK_EQ(agg_col_count, query_mem_desc.getSlotCount());
1571  CHECK_GE(agg_col_count, targets.size());
1572  CHECK_EQ(is_columnar, query_mem_desc.didOutputColumnar());
1573  CHECK(query_mem_desc.hasKeylessHash());
1574  std::vector<int64_t> partial_agg_vals(agg_col_count, 0);
1575  bool discard_row = true;
1576  for (int8_t warp_idx = 0; warp_idx < warp_count; ++warp_idx) {
1577  bool discard_partial_result = true;
1578  for (size_t target_idx = 0, agg_col_idx = 0;
1579  target_idx < targets.size() && agg_col_idx < agg_col_count;
1580  ++target_idx, ++agg_col_idx) {
1581  const auto& agg_info = targets[target_idx];
1582  const bool float_argument_input = takes_float_argument(agg_info);
1583  const auto chosen_bytes = float_argument_input
1584  ? sizeof(float)
1585  : query_mem_desc.getPaddedSlotWidthBytes(agg_col_idx);
1586  auto partial_bin_val = get_component(
1587  row_ptr + query_mem_desc.getColOnlyOffInBytes(agg_col_idx), chosen_bytes);
1588  partial_agg_vals[agg_col_idx] = partial_bin_val;
1589  if (is_distinct_target(agg_info)) {
1590  CHECK_EQ(int8_t(1), warp_count);
1591  CHECK(agg_info.is_agg && (agg_info.agg_kind == kCOUNT ||
1592  agg_info.agg_kind == kAPPROX_COUNT_DISTINCT));
1593  partial_bin_val = count_distinct_set_size(
1594  partial_bin_val, query_mem_desc.getCountDistinctDescriptor(target_idx));
1595  if (replace_bitmap_ptr_with_bitmap_sz) {
1596  partial_agg_vals[agg_col_idx] = partial_bin_val;
1597  }
1598  }
1599  if (kAVG == agg_info.agg_kind) {
1600  CHECK(agg_info.is_agg && !agg_info.is_distinct);
1601  ++agg_col_idx;
1602  partial_bin_val = partial_agg_vals[agg_col_idx] =
1603  get_component(row_ptr + query_mem_desc.getColOnlyOffInBytes(agg_col_idx),
1604  query_mem_desc.getPaddedSlotWidthBytes(agg_col_idx));
1605  }
1606  if (agg_col_idx == static_cast<size_t>(query_mem_desc.getTargetIdxForKey()) &&
1607  partial_bin_val != agg_init_vals[query_mem_desc.getTargetIdxForKey()]) {
1608  CHECK(agg_info.is_agg);
1609  discard_partial_result = false;
1610  }
1611  }
1612  row_ptr += row_size;
1613  if (discard_partial_result) {
1614  continue;
1615  }
1616  discard_row = false;
1617  for (size_t target_idx = 0, agg_col_idx = 0;
1618  target_idx < targets.size() && agg_col_idx < agg_col_count;
1619  ++target_idx, ++agg_col_idx) {
1620  auto partial_bin_val = partial_agg_vals[agg_col_idx];
1621  const auto& agg_info = targets[target_idx];
1622  const bool float_argument_input = takes_float_argument(agg_info);
1623  const auto chosen_bytes = float_argument_input
1624  ? sizeof(float)
1625  : query_mem_desc.getPaddedSlotWidthBytes(agg_col_idx);
1626  const auto& chosen_type = get_compact_type(agg_info);
1627  if (agg_info.is_agg && agg_info.agg_kind != kSAMPLE) {
1628  try {
1629  switch (agg_info.agg_kind) {
1630  case kCOUNT:
1633  reinterpret_cast<int8_t*>(&agg_vals[agg_col_idx]),
1634  reinterpret_cast<int8_t*>(&partial_agg_vals[agg_col_idx]),
1635  agg_init_vals[agg_col_idx],
1636  chosen_bytes,
1637  agg_info);
1638  break;
1639  case kAVG:
1640  // Ignore float argument compaction for count component for fear of its
1641  // overflow
1643  reinterpret_cast<int8_t*>(&agg_vals[agg_col_idx + 1]),
1644  reinterpret_cast<int8_t*>(&partial_agg_vals[agg_col_idx + 1]),
1645  query_mem_desc.getPaddedSlotWidthBytes(agg_col_idx));
1646  // fall thru
1647  case kSUM:
1649  sum,
1650  reinterpret_cast<int8_t*>(&agg_vals[agg_col_idx]),
1651  reinterpret_cast<int8_t*>(&partial_agg_vals[agg_col_idx]),
1652  agg_init_vals[agg_col_idx],
1653  chosen_bytes,
1654  agg_info);
1655  break;
1656  case kMIN:
1657  if (static_cast<size_t>(chosen_bytes) <= sizeof(int16_t)) {
1659  min,
1660  reinterpret_cast<int8_t*>(&agg_vals[agg_col_idx]),
1661  reinterpret_cast<int8_t*>(&partial_agg_vals[agg_col_idx]),
1662  agg_init_vals[agg_col_idx],
1663  chosen_bytes,
1664  agg_info);
1665  } else {
1667  min,
1668  reinterpret_cast<int8_t*>(&agg_vals[agg_col_idx]),
1669  reinterpret_cast<int8_t*>(&partial_agg_vals[agg_col_idx]),
1670  agg_init_vals[agg_col_idx],
1671  chosen_bytes,
1672  agg_info);
1673  }
1674  break;
1675  case kMAX:
1676  if (static_cast<size_t>(chosen_bytes) <= sizeof(int16_t)) {
1678  max,
1679  reinterpret_cast<int8_t*>(&agg_vals[agg_col_idx]),
1680  reinterpret_cast<int8_t*>(&partial_agg_vals[agg_col_idx]),
1681  agg_init_vals[agg_col_idx],
1682  chosen_bytes,
1683  agg_info);
1684  } else {
1686  max,
1687  reinterpret_cast<int8_t*>(&agg_vals[agg_col_idx]),
1688  reinterpret_cast<int8_t*>(&partial_agg_vals[agg_col_idx]),
1689  agg_init_vals[agg_col_idx],
1690  chosen_bytes,
1691  agg_info);
1692  }
1693  break;
1694  default:
1695  CHECK(false);
1696  break;
1697  }
1698  } catch (std::runtime_error& e) {
1699  // TODO(miyu): handle the case where chosen_bytes < 8
1700  LOG(ERROR) << e.what();
1701  }
1702  if (chosen_type.is_integer() || chosen_type.is_decimal()) {
1703  switch (chosen_bytes) {
1704  case 8:
1705  break;
1706  case 4: {
1707  int32_t ret = *reinterpret_cast<const int32_t*>(&agg_vals[agg_col_idx]);
1708  if (!(agg_info.agg_kind == kCOUNT && ret != agg_init_vals[agg_col_idx])) {
1709  agg_vals[agg_col_idx] = static_cast<int64_t>(ret);
1710  }
1711  break;
1712  }
1713  default:
1714  CHECK(false);
1715  }
1716  }
1717  if (kAVG == agg_info.agg_kind) {
1718  ++agg_col_idx;
1719  }
1720  } else {
1721  if (agg_info.agg_kind == kSAMPLE) {
1722  CHECK(!agg_info.sql_type.is_varlen())
1723  << "Interleaved bins reduction not supported for variable length "
1724  "arguments "
1725  "to SAMPLE";
1726  }
1727  if (agg_vals[agg_col_idx]) {
1728  if (agg_info.agg_kind == kSAMPLE) {
1729  continue;
1730  }
1731  CHECK_EQ(agg_vals[agg_col_idx], partial_bin_val);
1732  } else {
1733  agg_vals[agg_col_idx] = partial_bin_val;
1734  }
1735  }
1736  }
1737  }
1738  return discard_row;
1739 }
#define CHECK_EQ(x, y)
Definition: Logger.h:201
const int64_t const uint32_t const uint32_t const uint32_t agg_col_count
int64_t get_component(const int8_t *group_by_buffer, const size_t comp_sz, const size_t index=0)
#define LOG(tag)
Definition: Logger.h:188
#define CHECK_GE(x, y)
Definition: Logger.h:206
bool takes_float_argument(const TargetInfo &target_info)
Definition: TargetInfo.h:121
const int8_t getPaddedSlotWidthBytes(const size_t slot_idx) const
Definition: sqldefs.h:73
const SQLTypeInfo get_compact_type(const TargetInfo &target)
#define AGGREGATE_ONE_NULLABLE_VALUE( agg_kind__, val_ptr__, other_ptr__, init_val__, chosen_bytes__, agg_info__)
int64_t count_distinct_set_size(const int64_t set_handle, const CountDistinctDescriptor &count_distinct_desc)
Definition: CountDistinct.h:75
Definition: sqldefs.h:75
bool is_distinct_target(const TargetInfo &target_info)
Definition: TargetInfo.h:117
#define AGGREGATE_ONE_NULLABLE_VALUE_SMALL( agg_kind__, val_ptr__, other_ptr__, init_val__, chosen_bytes__, agg_info__)
int32_t getTargetIdxForKey() const
size_t getColOnlyOffInBytes(const size_t col_idx) const
#define AGGREGATE_ONE_COUNT(val_ptr__, other_ptr__, chosen_bytes__)
Definition: sqldefs.h:76
#define AGGREGATE_ONE_NULLABLE_COUNT( val_ptr__, other_ptr__, init_val__, chosen_bytes__, agg_info__)
#define CHECK(condition)
Definition: Logger.h:193
const CountDistinctDescriptor & getCountDistinctDescriptor(const size_t idx) const
Definition: sqldefs.h:74
Definition: sqldefs.h:72
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ rewriteAggregateBufferOffsets()

void ResultSetStorage::rewriteAggregateBufferOffsets ( const std::vector< std::string > &  serialized_varlen_buffer) const

Definition at line 513 of file ResultSetReduction.cpp.

References advance_slot(), advance_target_ptr_row_wise(), align_to_int64(), buff_, CHECK, CHECK_GT, CHECK_LT, QueryMemoryDescriptor::didOutputColumnar(), get_key_bytes_rowwise(), QueryMemoryDescriptor::getEntryCount(), QueryMemoryDescriptor::getPaddedSlotWidthBytes(), isEmptyEntry(), kSAMPLE, query_mem_desc_, row_ptr_rowwise(), and targets_.

514  {
515  if (serialized_varlen_buffer.empty()) {
516  return;
517  }
518 
520  auto entry_count = query_mem_desc_.getEntryCount();
521  CHECK_GT(entry_count, size_t(0));
522  CHECK(buff_);
523 
524  // Row-wise iteration, consider moving to separate function
525  for (size_t i = 0; i < entry_count; ++i) {
526  if (isEmptyEntry(i, buff_)) {
527  continue;
528  }
529  const auto key_bytes = get_key_bytes_rowwise(query_mem_desc_);
530  const auto key_bytes_with_padding = align_to_int64(key_bytes);
531  auto rowwise_targets_ptr =
532  row_ptr_rowwise(buff_, query_mem_desc_, i) + key_bytes_with_padding;
533  size_t target_slot_idx = 0;
534  for (size_t target_logical_idx = 0; target_logical_idx < targets_.size();
535  ++target_logical_idx) {
536  const auto& target_info = targets_[target_logical_idx];
537  if (target_info.sql_type.is_varlen() && target_info.is_agg) {
538  CHECK(target_info.agg_kind == kSAMPLE);
539  auto ptr1 = rowwise_targets_ptr;
540  auto slot_idx = target_slot_idx;
541  auto ptr2 = ptr1 + query_mem_desc_.getPaddedSlotWidthBytes(slot_idx);
542  auto offset = *reinterpret_cast<const int64_t*>(ptr1);
543 
544  const auto& elem_ti = target_info.sql_type.get_elem_type();
545  size_t length_to_elems =
546  target_info.sql_type.is_string() || target_info.sql_type.is_geometry()
547  ? 1
548  : elem_ti.get_size();
549  if (target_info.sql_type.is_geometry()) {
550  for (int j = 0; j < target_info.sql_type.get_physical_coord_cols(); j++) {
551  if (j > 0) {
552  ptr1 = ptr2 + query_mem_desc_.getPaddedSlotWidthBytes(slot_idx + 1);
553  ptr2 = ptr1 + query_mem_desc_.getPaddedSlotWidthBytes(slot_idx + 2);
554  slot_idx += 2;
555  length_to_elems = 4;
556  }
557  CHECK_LT(static_cast<size_t>(offset), serialized_varlen_buffer.size());
558  const auto& varlen_bytes_str = serialized_varlen_buffer[offset++];
559  const auto str_ptr =
560  reinterpret_cast<const int8_t*>(varlen_bytes_str.c_str());
561  CHECK(ptr1);
562  *reinterpret_cast<int64_t*>(ptr1) = reinterpret_cast<const int64_t>(str_ptr);
563  CHECK(ptr2);
564  *reinterpret_cast<int64_t*>(ptr2) =
565  static_cast<int64_t>(varlen_bytes_str.size() / length_to_elems);
566  }
567  } else {
568  CHECK_LT(static_cast<size_t>(offset), serialized_varlen_buffer.size());
569  const auto& varlen_bytes_str = serialized_varlen_buffer[offset];
570  const auto str_ptr = reinterpret_cast<const int8_t*>(varlen_bytes_str.c_str());
571  CHECK(ptr1);
572  *reinterpret_cast<int64_t*>(ptr1) = reinterpret_cast<const int64_t>(str_ptr);
573  CHECK(ptr2);
574  *reinterpret_cast<int64_t*>(ptr2) =
575  static_cast<int64_t>(varlen_bytes_str.size() / length_to_elems);
576  }
577  }
578 
579  rowwise_targets_ptr = advance_target_ptr_row_wise(
580  rowwise_targets_ptr, target_info, target_slot_idx, query_mem_desc_, false);
581  target_slot_idx = advance_slot(target_slot_idx, target_info, false);
582  }
583  }
584 
585  return;
586 }
const std::vector< TargetInfo > targets_
Definition: ResultSet.h:203
T advance_target_ptr_row_wise(T target_ptr, const TargetInfo &target_info, const size_t slot_idx, const QueryMemoryDescriptor &query_mem_desc, const bool separate_varlen_storage)
#define CHECK_GT(x, y)
Definition: Logger.h:205
const int8_t getPaddedSlotWidthBytes(const size_t slot_idx) const
bool isEmptyEntry(const size_t entry_idx, const int8_t *buff) const
size_t advance_slot(const size_t j, const TargetInfo &target_info, const bool separate_varlen_storage)
T row_ptr_rowwise(T buff, const QueryMemoryDescriptor &query_mem_desc, const size_t entry_idx)
#define CHECK_LT(x, y)
Definition: Logger.h:203
int8_t * buff_
Definition: ResultSet.h:205
#define CHECK(condition)
Definition: Logger.h:193
size_t get_key_bytes_rowwise(const QueryMemoryDescriptor &query_mem_desc)
FORCE_INLINE HOST DEVICE T align_to_int64(T addr)
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:204
+ Here is the call graph for this function:

◆ updateEntryCount()

void ResultSetStorage::updateEntryCount ( const size_t  new_entry_count)
inline

Friends And Related Function Documentation

◆ ResultSet

◆ ResultSetManager

friend class ResultSetManager
friend

Definition at line 216 of file ResultSet.h.

Member Data Documentation

◆ buff_

◆ buff_is_provided_

const bool ResultSetStorage::buff_is_provided_
private

Definition at line 206 of file ResultSet.h.

◆ count_distinct_sets_mapping_

std::unordered_map<int64_t, int64_t> ResultSetStorage::count_distinct_sets_mapping_
private

Definition at line 213 of file ResultSet.h.

◆ query_mem_desc_

◆ target_init_vals_

std::vector<int64_t> ResultSetStorage::target_init_vals_
private

◆ targets_

const std::vector<TargetInfo> ResultSetStorage::targets_
private

The documentation for this class was generated from the following files: