OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
InValuesBitmap.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "InValuesBitmap.h"
18 #include "CodeGenerator.h"
19 #include "Execute.h"
20 #ifdef HAVE_CUDA
21 #include "GpuMemUtils.h"
22 #endif // HAVE_CUDA
23 #include "../Parser/ParserNode.h"
24 #include "../Shared/checked_alloc.h"
25 #include "GroupByAndAggregate.h"
26 #include "Logger/Logger.h"
28 #include "RuntimeFunctions.h"
29 
30 #include <limits>
31 
32 extern int64_t g_bitmap_memory_limit;
33 
34 InValuesBitmap::InValuesBitmap(const std::vector<int64_t>& values,
35  const int64_t null_val,
36  const Data_Namespace::MemoryLevel memory_level,
37  const int device_count,
38  Data_Namespace::DataMgr* data_mgr)
39  : rhs_has_null_(false)
40  , null_val_(null_val)
41  , memory_level_(memory_level)
42  , device_count_(device_count)
43  , data_mgr_(data_mgr) {
44 #ifdef HAVE_CUDA
46  memory_level == Data_Namespace::GPU_LEVEL);
47 #else
49 #endif // HAVE_CUDA
50  if (values.empty()) {
51  return;
52  }
53  min_val_ = std::numeric_limits<int64_t>::max();
54  max_val_ = std::numeric_limits<int64_t>::min();
55  for (const auto value : values) {
56  if (value == null_val) {
57  rhs_has_null_ = true;
58  continue;
59  }
60  if (value < min_val_) {
61  min_val_ = value;
62  }
63  if (value > max_val_) {
64  max_val_ = value;
65  }
66  }
67  if (max_val_ < min_val_) {
68  CHECK_EQ(std::numeric_limits<int64_t>::max(), min_val_);
69  CHECK_EQ(std::numeric_limits<int64_t>::min(), max_val_);
71  return;
72  }
73  uint64_t const bitmap_sz_bits_minus_one = max_val_ - min_val_;
74  if (static_cast<uint64_t>(g_bitmap_memory_limit) <= bitmap_sz_bits_minus_one) {
75  throw FailedToCreateBitmap();
76  }
77  // bitmap_sz_bytes = ceil(bitmap_sz_bits / 8.0) = (bitmap_sz_bits-1) / 8 + 1
78  uint64_t const bitmap_sz_bytes = bitmap_sz_bits_minus_one / 8 + 1;
79  auto cpu_bitset = static_cast<int8_t*>(checked_calloc(bitmap_sz_bytes, 1));
80  for (const auto value : values) {
81  if (value == null_val) {
82  continue;
83  }
85  reinterpret_cast<int64_t*>(&cpu_bitset), value, min_val_, 0);
86  }
87 #ifdef HAVE_CUDA
89  for (int device_id = 0; device_id < device_count_; ++device_id) {
90  auto device_allocator = std::make_unique<CudaAllocator>(
91  data_mgr_, device_id, getQueryEngineCudaStreamForDevice(device_id));
92  gpu_buffers_.emplace_back(
93  data_mgr->alloc(Data_Namespace::GPU_LEVEL, device_id, bitmap_sz_bytes));
94  auto gpu_bitset = gpu_buffers_.back()->getMemoryPtr();
95  device_allocator->copyToDevice(gpu_bitset, cpu_bitset, bitmap_sz_bytes);
96  bitsets_.push_back(gpu_bitset);
97  }
98  free(cpu_bitset);
99  } else {
100  bitsets_.push_back(cpu_bitset);
101  }
102 #else
104  bitsets_.push_back(cpu_bitset);
105 #endif // HAVE_CUDA
106 }
107 
109  if (bitsets_.empty()) {
110  return;
111  }
113  CHECK_EQ(size_t(1), bitsets_.size());
114  free(bitsets_.front());
115  } else {
116  CHECK(data_mgr_);
117  for (auto& gpu_buffer : gpu_buffers_) {
118  data_mgr_->free(gpu_buffer);
119  }
120  }
121 }
122 
123 llvm::Value* InValuesBitmap::codegen(llvm::Value* needle, Executor* executor) const {
124  AUTOMATIC_IR_METADATA(executor->cgen_state_.get());
125  std::vector<std::shared_ptr<const Analyzer::Constant>> constants_owned;
126  std::vector<const Analyzer::Constant*> constants;
127  for (const auto bitset : bitsets_) {
128  const int64_t bitset_handle = reinterpret_cast<int64_t>(bitset);
129  const auto bitset_handle_literal = std::dynamic_pointer_cast<Analyzer::Constant>(
130  Parser::IntLiteral::analyzeValue(bitset_handle));
131  CHECK(bitset_handle_literal);
132  CHECK_EQ(kENCODING_NONE, bitset_handle_literal->get_type_info().get_compression());
133  constants_owned.push_back(bitset_handle_literal);
134  constants.push_back(bitset_handle_literal.get());
135  }
136  const auto needle_i64 = executor->cgen_state_->castToTypeIn(needle, 64);
137  const auto null_bool_val =
138  static_cast<int8_t>(inline_int_null_val(SQLTypeInfo(kBOOLEAN, false)));
139  auto pi8_ty =
140  llvm::PointerType::get(get_int_type(8, executor->cgen_state_->context_), 0);
141  if (bitsets_.empty()) {
142  auto empty_bitmap = executor->cgen_state_->llInt(int64_t(0));
143  auto empty_bitmap_ptr =
144  executor->cgen_state_->ir_builder_.CreateIntToPtr(empty_bitmap, pi8_ty);
145  return executor->cgen_state_->emitCall("bit_is_set",
146  {empty_bitmap_ptr,
147  needle_i64,
148  executor->cgen_state_->llInt(int64_t(0)),
149  executor->cgen_state_->llInt(int64_t(0)),
150  executor->cgen_state_->llInt(null_val_),
151  executor->cgen_state_->llInt(null_bool_val)});
152  }
153  CodeGenerator code_generator(executor);
154  const auto bitset_handle_lvs =
155  code_generator.codegenHoistedConstants(constants, kENCODING_NONE, {});
156  CHECK_EQ(size_t(1), bitset_handle_lvs.size());
157  auto bitset_ptr = executor->cgen_state_->ir_builder_.CreateIntToPtr(
158  bitset_handle_lvs.front(), pi8_ty);
159  return executor->cgen_state_->emitCall("bit_is_set",
160  {bitset_ptr,
161  needle_i64,
162  executor->cgen_state_->llInt(min_val_),
163  executor->cgen_state_->llInt(max_val_),
164  executor->cgen_state_->llInt(null_val_),
165  executor->cgen_state_->llInt(null_bool_val)});
166 }
167 
169  return bitsets_.empty();
170 }
171 
173  return rhs_has_null_;
174 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
static std::shared_ptr< Analyzer::Expr > analyzeValue(const int64_t intval)
Definition: ParserNode.cpp:165
bool hasNull() const
RUNTIME_EXPORT ALWAYS_INLINE void agg_count_distinct_bitmap(int64_t *agg, const int64_t val, const int64_t min_val, const int64_t bucket_size)
std::vector< llvm::Value * > codegenHoistedConstants(const std::vector< const Analyzer::Constant * > &constants, const EncodingType enc_type, const shared::StringDictKey &dict_id)
Definition: ConstantIR.cpp:373
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
std::vector< int8_t * > bitsets_
std::vector< Data_Namespace::AbstractBuffer * > gpu_buffers_
void * checked_calloc(const size_t nmemb, const size_t size)
Definition: checked_alloc.h:53
int64_t g_bitmap_memory_limit
#define AUTOMATIC_IR_METADATA(CGENSTATE)
InValuesBitmap(const std::vector< int64_t > &values, const int64_t null_val, const Data_Namespace::MemoryLevel memory_level, const int device_count, Data_Namespace::DataMgr *data_mgr)
const int64_t null_val_
llvm::Value * codegen(llvm::Value *needle, Executor *executor) const
Data_Namespace::DataMgr * data_mgr_
CUstream getQueryEngineCudaStreamForDevice(int device_num)
Definition: QueryEngine.cpp:7
data_mgr_(data_mgr)
bool g_enable_watchdog false
Definition: Execute.cpp:80
const int device_count_
#define CHECK(condition)
Definition: Logger.h:291
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
device_count_(device_count)
void free(AbstractBuffer *buffer)
Definition: DataMgr.cpp:564
bool isEmpty() const
AbstractBuffer * alloc(const MemoryLevel memoryLevel, const int deviceId, const size_t numBytes)
Definition: DataMgr.cpp:555
const Data_Namespace::MemoryLevel memory_level_
memory_level_(memory_level)