OmniSciDB  b24e664e58
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
InValuesBitmap.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 MapD Technologies, 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 "RuntimeFunctions.h"
27 #include "Shared/Logger.h"
28 
29 #include <boost/multiprecision/cpp_int.hpp>
30 #include <limits>
31 
32 using checked_int64_t = boost::multiprecision::number<
33  boost::multiprecision::cpp_int_backend<64,
34  64,
35  boost::multiprecision::signed_magnitude,
36  boost::multiprecision::checked,
37  void>>;
38 
39 InValuesBitmap::InValuesBitmap(const std::vector<int64_t>& values,
40  const int64_t null_val,
41  const Data_Namespace::MemoryLevel memory_level,
42  const int device_count,
43  Data_Namespace::DataMgr* data_mgr)
44  : rhs_has_null_(false)
45  , null_val_(null_val)
46  , memory_level_(memory_level)
47  , device_count_(device_count) {
48 #ifdef HAVE_CUDA
50  memory_level == Data_Namespace::GPU_LEVEL);
51 #else
53 #endif // HAVE_CUDA
54  if (values.empty()) {
55  return;
56  }
57  min_val_ = std::numeric_limits<int64_t>::max();
58  max_val_ = std::numeric_limits<int64_t>::min();
59  for (const auto value : values) {
60  if (value == null_val) {
61  rhs_has_null_ = true;
62  continue;
63  }
64  if (value < min_val_) {
65  min_val_ = value;
66  }
67  if (value > max_val_) {
68  max_val_ = value;
69  }
70  }
71  if (max_val_ < min_val_) {
72  CHECK_EQ(std::numeric_limits<int64_t>::max(), min_val_);
73  CHECK_EQ(std::numeric_limits<int64_t>::min(), max_val_);
75  return;
76  }
77  const int64_t MAX_BITMAP_BITS{8 * 1000 * 1000 * 1000L};
78  const auto bitmap_sz_bits =
79  static_cast<int64_t>(checked_int64_t(max_val_) - min_val_ + 1);
80  if (bitmap_sz_bits > MAX_BITMAP_BITS) {
81  throw FailedToCreateBitmap();
82  }
83  const auto bitmap_sz_bytes = bitmap_bits_to_bytes(bitmap_sz_bits);
84  auto cpu_bitset = static_cast<int8_t*>(checked_calloc(bitmap_sz_bytes, 1));
85  for (const auto value : values) {
86  if (value == null_val) {
87  continue;
88  }
89  agg_count_distinct_bitmap(reinterpret_cast<int64_t*>(&cpu_bitset), value, min_val_);
90  }
91 #ifdef HAVE_CUDA
93  for (int device_id = 0; device_id < device_count_; ++device_id) {
94  auto gpu_bitset = CudaAllocator::alloc(data_mgr, bitmap_sz_bytes, device_id);
95  copy_to_gpu(data_mgr,
96  reinterpret_cast<CUdeviceptr>(gpu_bitset),
97  cpu_bitset,
98  bitmap_sz_bytes,
99  device_id);
100  bitsets_.push_back(gpu_bitset);
101  }
102  free(cpu_bitset);
103  } else {
104  bitsets_.push_back(cpu_bitset);
105  }
106 #else
108  bitsets_.push_back(cpu_bitset);
109 #endif // HAVE_CUDA
110 }
111 
113  if (bitsets_.empty()) {
114  return;
115  }
117  CHECK_EQ(size_t(1), bitsets_.size());
118  free(bitsets_.front());
119  }
120 }
121 
122 llvm::Value* InValuesBitmap::codegen(llvm::Value* needle, Executor* executor) const {
123  std::vector<std::shared_ptr<const Analyzer::Constant>> constants_owned;
124  std::vector<const Analyzer::Constant*> constants;
125  for (const auto bitset : bitsets_) {
126  const int64_t bitset_handle = reinterpret_cast<int64_t>(bitset);
127  const auto bitset_handle_literal = std::dynamic_pointer_cast<Analyzer::Constant>(
128  Parser::IntLiteral::analyzeValue(bitset_handle));
129  CHECK(bitset_handle_literal);
130  CHECK_EQ(kENCODING_NONE, bitset_handle_literal->get_type_info().get_compression());
131  constants_owned.push_back(bitset_handle_literal);
132  constants.push_back(bitset_handle_literal.get());
133  }
134  const auto needle_i64 = executor->cgen_state_->castToTypeIn(needle, 64);
135  const auto null_bool_val =
136  static_cast<int8_t>(inline_int_null_val(SQLTypeInfo(kBOOLEAN, false)));
137  if (bitsets_.empty()) {
138  return executor->cgen_state_->emitCall("bit_is_set",
139  {executor->cgen_state_->llInt(int64_t(0)),
140  needle_i64,
141  executor->cgen_state_->llInt(int64_t(0)),
142  executor->cgen_state_->llInt(int64_t(0)),
143  executor->cgen_state_->llInt(null_val_),
144  executor->cgen_state_->llInt(null_bool_val)});
145  }
146  CodeGenerator code_generator(executor);
147  const auto bitset_handle_lvs =
148  code_generator.codegenHoistedConstants(constants, kENCODING_NONE, 0);
149  CHECK_EQ(size_t(1), bitset_handle_lvs.size());
150  return executor->cgen_state_->emitCall(
151  "bit_is_set",
152  {executor->cgen_state_->castToTypeIn(bitset_handle_lvs.front(), 64),
153  needle_i64,
154  executor->cgen_state_->llInt(min_val_),
155  executor->cgen_state_->llInt(max_val_),
156  executor->cgen_state_->llInt(null_val_),
157  executor->cgen_state_->llInt(null_bool_val)});
158 }
159 
161  return bitsets_.empty();
162 }
163 
165  return rhs_has_null_;
166 }
#define CHECK_EQ(x, y)
Definition: Logger.h:198
static std::shared_ptr< Analyzer::Expr > analyzeValue(const int64_t intval)
Definition: ParserNode.cpp:112
bool hasNull() const
size_t bitmap_bits_to_bytes(const size_t bitmap_sz)
static int8_t * alloc(Data_Namespace::DataMgr *data_mgr, const size_t num_bytes, const int device_id)
CHECK(cgen_state)
void copy_to_gpu(Data_Namespace::DataMgr *data_mgr, CUdeviceptr dst, const void *src, const size_t num_bytes, const int device_id)
Definition: GpuMemUtils.cpp:31
std::vector< llvm::Value * > codegenHoistedConstants(const std::vector< const Analyzer::Constant * > &constants, const EncodingType enc_type, const int dict_id)
Definition: ConstantIR.cpp:287
std::vector< int8_t * > bitsets_
void * checked_calloc(const size_t nmemb, const size_t size)
Definition: checked_alloc.h:48
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 64, 64, boost::multiprecision::signed_magnitude, boost::multiprecision::checked, void > > checked_int64_t
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)
SQLTypeInfoCore< ArrayContextTypeSizer, ExecutorTypePackaging, DateTimeFacilities > SQLTypeInfo
Definition: sqltypes.h:852
const int64_t null_val_
llvm::Value * codegen(llvm::Value *needle, Executor *executor) const
bool g_enable_watchdog false
Definition: Execute.cpp:71
const int device_count_
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
ALWAYS_INLINE void agg_count_distinct_bitmap(int64_t *agg, const int64_t val, const int64_t min_val)
bool isEmpty() const
const Data_Namespace::MemoryLevel memory_level_