OmniSciDB  ba1bac9284
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
QueryOutputBufferMemoryManager.h
Go to the documentation of this file.
1 /*
2  * Copyright 2021 OmniSci, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
18 
19 /*
20  QueryOutputBufferMemoryManager manages the memory of output column
21  buffers using the following approach:
22 
23  1. Before executing a table function, a memory manager of output
24  columns buffers is initiated (when entering launchCpuCode). This
25  step includes creating output Column instances that will passed as
26  arguments to the table functions. The pointers to the output Column
27  instances are saved within the memory manager so that the instances
28  ptr and size members can be updated when the number of output
29  columns rows is set and the buffers of output columns are allocated.
30 
31  2. If the number of rows of output columns is known,
32  `set_output_row_size` is called before executing the table
33  function. Otherwise (when
34  exe_unit.table_func.hasTableFunctionSpecifiedParameter() evaluates
35  to true), it is expected that the table function will call
36  `set_output_row_size` to set the number of rows of output columns.
37  Calling `set_output_row_size` will also update the output Column
38  instances members.
39 
40  3. The table function is expected to return the final number of rows
41  of output columns. It must not be greater than the count specified
42  in the `set_output_row_size` call but may be a smaller value.
43 
44  4. After returning the table function, one can access the output
45  Column instances until the memory manager of output columns is
46  destroyed (when leaving launchCpuCode). The buffers of output
47  columns are now owned by the ResultSet instance.
48 
49 */
50 
52  std::unique_ptr<QueryMemoryInitializer> query_buffers;
53 
54  /*
55  QueryOutputBufferMemoryManager is a dynamic singleton:
56  `get_singleton()` returns a pointer to the singleton instance when
57  in the scope of QueryOutputBufferMemoryManager life-time,
58  otherwise returns nullptr. For internal usage.
59  */
61  static QueryOutputBufferMemoryManager* instance = nullptr;
62  return instance;
63  }
64 
66  Executor* executor,
67  std::vector<const int8_t*>& col_buf_ptrs,
68  std::shared_ptr<RowSetMemoryOwner> row_set_mem_owner)
69  : exe_unit_(exe_unit)
70  , executor_(executor)
71  , col_buf_ptrs_(col_buf_ptrs)
72  , row_set_mem_owner_(row_set_mem_owner)
73  , output_num_rows_(0) {
74  set_singleton(this); // start of singleton life
75  auto num_out_columns = get_ncols();
76  output_col_buf_ptrs.reserve(num_out_columns);
77  output_column_ptrs.reserve(num_out_columns);
78  for (size_t i = 0; i < num_out_columns; i++) {
79  output_col_buf_ptrs.emplace_back(nullptr);
80  output_column_ptrs.emplace_back(nullptr);
81  }
82  }
83 
85  set_singleton(nullptr); // end of singleton life
86  }
87 
88  // Return the number of output columns
89  size_t get_ncols() const { return exe_unit_.target_exprs.size(); }
90 
91  // Return the number of rows of output columns.
92  size_t get_nrows() const { return output_num_rows_; }
93 
94  // Store the pointer to output Column instance
95  void set_output_column(int32_t index, int8_t* ptr) {
96  CHECK(index >= 0 && index < static_cast<int32_t>(get_ncols()));
97  CHECK(ptr);
98  output_column_ptrs[index] = ptr;
99  }
100 
101  void allocate_output_buffers(int64_t output_num_rows) {
102  CHECK_EQ(output_num_rows_, 0); // re-allocation of output buffers is not supported
103  output_num_rows_ = output_num_rows;
104  auto num_out_columns = get_ncols();
106  output_num_rows, // divide by row multiplier???
108  /*is_table_function=*/true);
109  query_mem_desc.setOutputColumnar(true);
110 
111  for (size_t i = 0; i < num_out_columns; i++) {
112  // All outputs padded to 8 bytes
113  query_mem_desc.addColSlotInfo({std::make_tuple(8, 8)});
114  }
115 
116  query_buffers = std::make_unique<QueryMemoryInitializer>(
117  exe_unit_,
119  /*device_id=*/0,
122  std::vector<std::vector<const int8_t*>>{col_buf_ptrs_},
123  std::vector<std::vector<uint64_t>>{{0}}, // frag offsets
125  nullptr,
126  executor_);
127 
128  // The members layout of Column must match with Column defined in
129  // OmniSciTypes.h
130  struct Column {
131  int8_t* ptr;
132  int64_t size;
133  // just for debugging:
134  std::string toString() const {
135  return "Column{" + ::toString(ptr) + ", " + ::toString(size) + "}";
136  }
137  };
138 
139  auto group_by_buffers_ptr = query_buffers->getGroupByBuffersPtr();
140  CHECK(group_by_buffers_ptr);
141  auto output_buffers_ptr = reinterpret_cast<int64_t*>(group_by_buffers_ptr[0]);
142  for (size_t i = 0; i < num_out_columns; i++) {
143  Column* col = reinterpret_cast<Column*>(output_column_ptrs[i]);
144  CHECK(col);
145  output_col_buf_ptrs[i] = output_buffers_ptr + i * output_num_rows_;
146  // set the members of output Column instances:
147  col->ptr = reinterpret_cast<int8_t*>(output_col_buf_ptrs[i]);
148  col->size = output_num_rows_;
149  }
150  }
151 
152  private:
154  auto& instance_ = get_singleton();
155  // ensure being singleton
156  if (instance) {
157  CHECK(instance_ == nullptr);
158  } else {
159  CHECK(instance_ != nullptr);
160  }
161  instance_ = instance;
162  }
163 
165  Executor* executor_;
166  // Pointers to the buffers of input Columns
167  std::vector<const int8_t*>& col_buf_ptrs_;
168  //
169  std::shared_ptr<RowSetMemoryOwner> row_set_mem_owner_;
170  // Pointers to the buffers of output Columns
171  std::vector<int64_t*> output_col_buf_ptrs;
172  // Number of rows of output Columns
174  // Pointers to output Column instances
175  std::vector<int8_t*> output_column_ptrs;
176 };
std::unique_ptr< QueryMemoryInitializer > query_buffers
#define CHECK_EQ(x, y)
Definition: Logger.h:214
QueryOutputBufferMemoryManager(const TableFunctionExecutionUnit &exe_unit, Executor *executor, std::vector< const int8_t * > &col_buf_ptrs, std::shared_ptr< RowSetMemoryOwner > row_set_mem_owner)
static void set_singleton(QueryOutputBufferMemoryManager *instance)
std::string toString(const ExtArgumentType &sig_type)
void set_output_column(int32_t index, int8_t *ptr)
DEVICE int64_t size() const
Definition: OmniSciTypes.h:167
void setOutputColumnar(const bool val)
void allocate_output_buffers(int64_t output_num_rows)
static QueryOutputBufferMemoryManager *& get_singleton()
const TableFunctionExecutionUnit & exe_unit_
std::vector< const int8_t * > & col_buf_ptrs_
#define CHECK(condition)
Definition: Logger.h:206
std::vector< Analyzer::Expr * > target_exprs
void addColSlotInfo(const std::vector< std::tuple< int8_t, int8_t >> &slots_for_col)
std::shared_ptr< RowSetMemoryOwner > row_set_mem_owner_