OmniSciDB  04ee39c94c
anonymous_namespace{ResultSetReduction.cpp} Namespace Reference

Functions

bool use_multithreaded_reduction (const size_t entry_count)
 
size_t get_row_qw_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)
 
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)
 
ALWAYS_INLINE void fill_empty_key_32 (int32_t *key_ptr_i32, const size_t key_count)
 
ALWAYS_INLINE void fill_empty_key_64 (int64_t *key_ptr_i64, const size_t key_count)
 
int64_t get_component (const int8_t *group_by_buffer, const size_t comp_sz, const size_t index=0)
 
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)
 
ALWAYS_INLINE void check_watchdog (const size_t sample_seed)
 
GroupValueInfo get_matching_group_value_columnar_reduction (int64_t *groups_buffer, const uint32_t h, const int64_t *key, const uint32_t key_qw_count, const size_t entry_count)
 
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)
 
template<typename T = int64_t>
GroupValueInfo get_matching_group_value_reduction (int64_t *groups_buffer, const uint32_t h, const T *key, const uint32_t key_count, const QueryMemoryDescriptor &query_mem_desc, const int64_t *that_buff_i64, const size_t that_entry_idx, const size_t that_entry_count, const uint32_t row_size_quad)
 
GroupValueInfo get_matching_group_value_reduction (int64_t *groups_buffer, const uint32_t h, const int64_t *key, const uint32_t key_count, const size_t key_width, const QueryMemoryDescriptor &query_mem_desc, const int64_t *that_buff_i64, const size_t that_entry_idx, const size_t that_entry_count, const uint32_t row_size_quad)
 

Function Documentation

◆ check_watchdog()

ALWAYS_INLINE void anonymous_namespace{ResultSetReduction.cpp}::check_watchdog ( const size_t  sample_seed)

Definition at line 386 of file ResultSetReduction.cpp.

References dynamic_watchdog(), g_enable_dynamic_watchdog, and UNLIKELY.

Referenced by ResultSetStorage::reduceEntriesNoCollisionsColWise(), ResultSetStorage::reduceOneEntryBaseline(), and ResultSetStorage::reduceOneEntryNoCollisionsRowWise().

386  {
387  if (UNLIKELY(g_enable_dynamic_watchdog && (sample_seed & 0x3F) == 0 &&
388  dynamic_watchdog())) {
389  // TODO(alex): distinguish between the deadline and interrupt
390  throw std::runtime_error(
391  "Query execution has exceeded the time limit or was interrupted during result "
392  "set reduction");
393  }
394 }
bool dynamic_watchdog()
bool g_enable_dynamic_watchdog
Definition: Execute.cpp:70
#define UNLIKELY(x)
Definition: likely.h:20
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fill_empty_key_32()

ALWAYS_INLINE void anonymous_namespace{ResultSetReduction.cpp}::fill_empty_key_32 ( int32_t *  key_ptr_i32,
const size_t  key_count 
)

Definition at line 90 of file ResultSetReduction.cpp.

References ALWAYS_INLINE, and EMPTY_KEY_32.

Referenced by fill_empty_key(), and ResultSetStorage::initializeRowWise().

90  {
91  for (size_t i = 0; i < key_count; ++i) {
92  key_ptr_i32[i] = EMPTY_KEY_32;
93  }
94 }
#define EMPTY_KEY_32
+ Here is the caller graph for this function:

◆ fill_empty_key_64()

ALWAYS_INLINE void anonymous_namespace{ResultSetReduction.cpp}::fill_empty_key_64 ( int64_t *  key_ptr_i64,
const size_t  key_count 
)

Definition at line 97 of file ResultSetReduction.cpp.

References EMPTY_KEY_64.

Referenced by fill_empty_key(), and ResultSetStorage::initializeRowWise().

97  {
98  for (size_t i = 0; i < key_count; ++i) {
99  key_ptr_i64[i] = EMPTY_KEY_64;
100  }
101 }
#define EMPTY_KEY_64
+ Here is the caller graph for this function:

◆ fill_slots()

void anonymous_namespace{ResultSetReduction.cpp}::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 
)

Definition at line 66 of file ResultSetReduction.cpp.

References ALWAYS_INLINE, QueryMemoryDescriptor::didOutputColumnar(), get_row_qw_count(), get_slot_off_quad(), QueryMemoryDescriptor::getBufferColSlotCount(), QueryMemoryDescriptor::getGroupbyColCount(), and slot_offset_colwise().

Referenced by get_matching_group_value_reduction(), ResultSetStorage::moveOneEntryToBuffer(), and ResultSetStorage::reduceOneEntryBaseline().

71  {
72  const auto slot_count = query_mem_desc.getBufferColSlotCount();
73  const auto key_count = query_mem_desc.getGroupbyColCount();
74  if (query_mem_desc.didOutputColumnar()) {
75  for (size_t i = 0, dst_slot_off = 0; i < slot_count;
76  ++i, dst_slot_off += dst_entry_count) {
77  dst_entry[dst_slot_off] =
78  src_buff[slot_offset_colwise(src_entry_idx, i, key_count, src_entry_count)];
79  }
80  } else {
81  const auto row_ptr = src_buff + get_row_qw_count(query_mem_desc) * src_entry_idx;
82  const auto slot_off_quad = get_slot_off_quad(query_mem_desc);
83  for (size_t i = 0; i < slot_count; ++i) {
84  dst_entry[i] = row_ptr[slot_off_quad + i];
85  }
86  }
87 }
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 get_slot_off_quad(const QueryMemoryDescriptor &query_mem_desc)
size_t get_row_qw_count(const QueryMemoryDescriptor &query_mem_desc)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_component()

int64_t anonymous_namespace{ResultSetReduction.cpp}::get_component ( const int8_t *  group_by_buffer,
const size_t  comp_sz,
const size_t  index = 0 
)
inline

Definition at line 103 of file ResultSetReduction.cpp.

References CHECK.

Referenced by ResultSetStorage::reduceSingleRow().

105  {
106  int64_t ret = std::numeric_limits<int64_t>::min();
107  switch (comp_sz) {
108  case 1: {
109  ret = group_by_buffer[index];
110  break;
111  }
112  case 2: {
113  const int16_t* buffer_ptr = reinterpret_cast<const int16_t*>(group_by_buffer);
114  ret = buffer_ptr[index];
115  break;
116  }
117  case 4: {
118  const int32_t* buffer_ptr = reinterpret_cast<const int32_t*>(group_by_buffer);
119  ret = buffer_ptr[index];
120  break;
121  }
122  case 8: {
123  const int64_t* buffer_ptr = reinterpret_cast<const int64_t*>(group_by_buffer);
124  ret = buffer_ptr[index];
125  break;
126  }
127  default:
128  CHECK(false);
129  }
130  return ret;
131 }
#define CHECK(condition)
Definition: Logger.h:187
+ Here is the caller graph for this function:

◆ get_group_value_columnar_reduction()

GroupValueInfo anonymous_namespace{ResultSetReduction.cpp}::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 
)

Definition at line 722 of file ResultSetReduction.cpp.

References get_matching_group_value_columnar_reduction(), groups_buffer_entry_count, and key_hash().

Referenced by ResultSetStorage::reduceOneEntryBaseline().

726  {
727  uint32_t h = key_hash(key, key_qw_count, sizeof(int64_t)) % groups_buffer_entry_count;
729  groups_buffer, h, key, key_qw_count, groups_buffer_entry_count);
730  if (matching_gvi.first) {
731  return matching_gvi;
732  }
733  uint32_t h_probe = (h + 1) % groups_buffer_entry_count;
734  while (h_probe != h) {
736  groups_buffer, h_probe, key, key_qw_count, groups_buffer_entry_count);
737  if (matching_gvi.first) {
738  return matching_gvi;
739  }
740  h_probe = (h_probe + 1) % groups_buffer_entry_count;
741  }
742  return {nullptr, true};
743 }
ALWAYS_INLINE DEVICE uint32_t key_hash(const int64_t *key, const uint32_t key_count, const uint32_t key_byte_width)
const int64_t const uint32_t groups_buffer_entry_count
const int64_t const uint32_t const uint32_t key_qw_count
GroupValueInfo get_matching_group_value_columnar_reduction(int64_t *groups_buffer, const uint32_t h, const int64_t *key, const uint32_t key_qw_count, const size_t entry_count)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_matching_group_value_columnar_reduction()

GroupValueInfo anonymous_namespace{ResultSetReduction.cpp}::get_matching_group_value_columnar_reduction ( int64_t *  groups_buffer,
const uint32_t  h,
const int64_t *  key,
const uint32_t  key_qw_count,
const size_t  entry_count 
)

Definition at line 696 of file ResultSetReduction.cpp.

References EMPTY_KEY_64, and key_qw_count.

Referenced by get_group_value_columnar_reduction().

700  {
701  auto off = h;
702  const auto old_key =
703  __sync_val_compare_and_swap(&groups_buffer[off], EMPTY_KEY_64, *key);
704  if (old_key == EMPTY_KEY_64) {
705  for (size_t i = 0; i < key_qw_count; ++i) {
706  groups_buffer[off] = key[i];
707  off += entry_count;
708  }
709  return {&groups_buffer[off], true};
710  }
711  off = h;
712  for (size_t i = 0; i < key_qw_count; ++i) {
713  if (groups_buffer[off] != key[i]) {
714  return {nullptr, true};
715  }
716  off += entry_count;
717  }
718  return {&groups_buffer[off], false};
719 }
#define EMPTY_KEY_64
const int64_t const uint32_t const uint32_t key_qw_count
+ Here is the caller graph for this function:

◆ get_matching_group_value_reduction() [1/2]

template<typename T = int64_t>
GroupValueInfo anonymous_namespace{ResultSetReduction.cpp}::get_matching_group_value_reduction ( int64_t *  groups_buffer,
const uint32_t  h,
const T *  key,
const uint32_t  key_count,
const QueryMemoryDescriptor query_mem_desc,
const int64_t *  that_buff_i64,
const size_t  that_entry_idx,
const size_t  that_entry_count,
const uint32_t  row_size_quad 
)

Definition at line 752 of file ResultSetReduction.cpp.

References cas_cst, fill_slots(), get_slot_off_quad(), QueryMemoryDescriptor::getEntryCount(), load_cst, and store_cst.

761  {
762  auto off = h * row_size_quad;
763  T empty_key = get_empty_key<T>();
764  T write_pending = get_empty_key<T>() - 1;
765  auto row_ptr = reinterpret_cast<T*>(groups_buffer + off);
766  const auto slot_off_quad = get_slot_off_quad(query_mem_desc);
767  const bool success = cas_cst(row_ptr, &empty_key, write_pending);
768  if (success) {
769  fill_slots(groups_buffer + off + slot_off_quad,
770  query_mem_desc.getEntryCount(),
771  that_buff_i64,
772  that_entry_idx,
773  that_entry_count,
774  query_mem_desc);
775  if (key_count > 1) {
776  memcpy(row_ptr + 1, key + 1, (key_count - 1) * sizeof(T));
777  }
778  store_cst(row_ptr, *key);
779  return {groups_buffer + off + slot_off_quad, true};
780  }
781  while (load_cst(row_ptr) == write_pending) {
782  // spin until the winning thread has finished writing the entire key and the init
783  // value
784  }
785  for (size_t i = 0; i < key_count; ++i) {
786  if (load_cst(row_ptr + i) != key[i]) {
787  return {nullptr, true};
788  }
789  }
790  return {groups_buffer + off + slot_off_quad, false};
791 }
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)
size_t get_slot_off_quad(const QueryMemoryDescriptor &query_mem_desc)
#define store_cst(ptr, val)
#define cas_cst(ptr, expected, desired)
#define load_cst(ptr)
+ Here is the call graph for this function:

◆ get_matching_group_value_reduction() [2/2]

GroupValueInfo anonymous_namespace{ResultSetReduction.cpp}::get_matching_group_value_reduction ( int64_t *  groups_buffer,
const uint32_t  h,
const int64_t *  key,
const uint32_t  key_count,
const size_t  key_width,
const QueryMemoryDescriptor query_mem_desc,
const int64_t *  that_buff_i64,
const size_t  that_entry_idx,
const size_t  that_entry_count,
const uint32_t  row_size_quad 
)
inline

Definition at line 797 of file ResultSetReduction.cpp.

References CHECK.

Referenced by get_group_value_reduction().

807  {
808  switch (key_width) {
809  case 4:
810  return get_matching_group_value_reduction(groups_buffer,
811  h,
812  reinterpret_cast<const int32_t*>(key),
813  key_count,
814  query_mem_desc,
815  that_buff_i64,
816  that_entry_idx,
817  that_entry_count,
818  row_size_quad);
819  case 8:
820  return get_matching_group_value_reduction(groups_buffer,
821  h,
822  key,
823  key_count,
824  query_mem_desc,
825  that_buff_i64,
826  that_entry_idx,
827  that_entry_count,
828  row_size_quad);
829  default:
830  CHECK(false);
831  return {nullptr, true};
832  }
833 }
#define CHECK(condition)
Definition: Logger.h:187
GroupValueInfo get_matching_group_value_reduction(int64_t *groups_buffer, const uint32_t h, const int64_t *key, const uint32_t key_count, const size_t key_width, const QueryMemoryDescriptor &query_mem_desc, const int64_t *that_buff_i64, const size_t that_entry_idx, const size_t that_entry_count, const uint32_t row_size_quad)
+ Here is the caller graph for this function:

◆ get_row_qw_count()

size_t anonymous_namespace{ResultSetReduction.cpp}::get_row_qw_count ( const QueryMemoryDescriptor query_mem_desc)

Definition at line 48 of file ResultSetReduction.cpp.

References CHECK_EQ, and get_row_bytes().

Referenced by fill_slots(), ResultSetStorage::moveEntriesToBuffer(), ResultSetStorage::reduceOneEntryBaseline(), and ResultSetStorage::reduceOneEntrySlotsBaseline().

48  {
49  const auto row_bytes = get_row_bytes(query_mem_desc);
50  CHECK_EQ(size_t(0), row_bytes % 8);
51  return row_bytes / 8;
52 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
size_t get_row_bytes(const QueryMemoryDescriptor &query_mem_desc)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ make_key()

std::vector<int64_t> anonymous_namespace{ResultSetReduction.cpp}::make_key ( const int64_t *  buff,
const size_t  entry_count,
const size_t  key_count 
)

Definition at line 54 of file ResultSetReduction.cpp.

Referenced by ResultSetStorage::moveOneEntryToBuffer(), and ResultSetStorage::reduceOneEntryBaseline().

56  {
57  std::vector<int64_t> key;
58  size_t off = 0;
59  for (size_t i = 0; i < key_count; ++i) {
60  key.push_back(buff[off]);
61  off += entry_count;
62  }
63  return key;
64 }
+ Here is the caller graph for this function:

◆ run_reduction_code()

void anonymous_namespace{ResultSetReduction.cpp}::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 
)

Definition at line 133 of file ResultSetReduction.cpp.

References ReductionCode::execution_engine, ReductionCode::func_ptr, ReductionCode::ir_reduce_loop, and ReductionCode::s_reduction_mutex.

Referenced by ResultSetStorage::reduce().

141  {
142  int err = 0;
143  if (reduction_code.func_ptr) {
144  err = reduction_code.func_ptr(this_buff,
145  that_buff,
146  start_entry_index,
147  end_entry_index,
148  that_entry_count,
149  this_qmd,
150  that_qmd,
151  serialized_varlen_buffer);
152  } else {
153  std::lock_guard<std::mutex> reduction_guard(ReductionCode::s_reduction_mutex);
154  auto start_entry_index_gv = llvm::GenericValue();
155  start_entry_index_gv.IntVal = llvm::APInt(32, start_entry_index);
156  auto end_entry_index_gv = llvm::GenericValue();
157  end_entry_index_gv.IntVal = llvm::APInt(32, end_entry_index);
158  auto that_entry_count_gv = llvm::GenericValue();
159  that_entry_count_gv.IntVal = llvm::APInt(32, that_entry_count);
160  const auto ret = reduction_code.execution_engine->runFunction(
161  reduction_code.ir_reduce_loop,
162  {llvm::GenericValue(this_buff),
163  llvm::GenericValue(const_cast<int8_t*>(that_buff)),
164  start_entry_index_gv,
165  end_entry_index_gv,
166  that_entry_count_gv,
167  llvm::GenericValue(const_cast<void*>(this_qmd)),
168  llvm::GenericValue(const_cast<void*>(that_qmd)),
169  llvm::GenericValue(const_cast<void*>(serialized_varlen_buffer))});
170  err = ret.IntVal.getSExtValue();
171  }
172  if (err) {
173  throw std::runtime_error(
174  "Query execution has exceeded the time limit or was interrupted during result "
175  "set reduction");
176  }
177 }
static std::mutex s_reduction_mutex
llvm::Function * ir_reduce_loop
llvm::ExecutionEngine * execution_engine
+ Here is the caller graph for this function:

◆ use_multithreaded_reduction()

bool anonymous_namespace{ResultSetReduction.cpp}::use_multithreaded_reduction ( const size_t  entry_count)

Definition at line 44 of file ResultSetReduction.cpp.

Referenced by ResultSetStorage::moveEntriesToBuffer(), and ResultSetStorage::reduce().

44  {
45  return entry_count > 100000;
46 }
+ Here is the caller graph for this function: