Skip to content

Commit b0e1aa0

Browse files
authored
Merge pull request #36 from sirius-db/devesh/optimized_result_formatter
Optimized result formatter
2 parents 8be33ee + 13d9d22 commit b0e1aa0

11 files changed

Lines changed: 214 additions & 517 deletions

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ set(EXTENSION_SOURCES
5959
src/gpu_buffer_manager.cpp
6060
src/gpu_columns.cpp
6161
src/gpu_expression_executor.cpp
62+
src/gpu_query_result.cpp
6263
)
6364
add_subdirectory(src/operator)
6465
add_subdirectory(src/plan)

docs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ conda install -c rapidsai -c conda-forge -c nvidia rapidsai::libcudf
4343
Set the environment variables `USE_CUDF` to 1 and `LIBCUDF_ENV_PREFIX` to the conda environment's path. For example, if we installed miniconda in `~/miniconda3` and installed libcudf in the conda environment `libcudf-env`, then we would set the `LIBCUDF_ENV_PREFIX` to `~/miniconda3/envs/libcudf-env`.
4444
```
4545
export USE_CUDF=1
46-
export LIBCUDF_ENV_PREFIX = {PATH to libcudf-env}
46+
export LIBCUDF_ENV_PREFIX={PATH to libcudf-env}
4747
```
4848

4949
### Clone the Sirius repository

queries/devesh_test_queries/q10_group_by_test.sql

Lines changed: 0 additions & 31 deletions
This file was deleted.

queries/devesh_test_queries/string_group_and_order_by.txt

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/cuda/operator/materialize.cu

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ __global__ void create_cpu_strings(duckdb_string_type* gpu_strings, char* cpu_ch
153153
}
154154
}
155155

156-
void materializeStringColumnToDuckdbFormat(GPUColumn* column, char* column_char_write_buffer, string_t* column_string_write_buffer) {
156+
void materializeStringColumnToDuckdbFormat(shared_ptr<GPUColumn> column, char* column_char_write_buffer, string_t* column_string_write_buffer) {
157157
// First copy the characters from the GPU to the CPU
158158
SIRIUS_LOG_DEBUG("Materialize String Column to Duckdb format");
159159
SETUP_TIMING();

src/gpu_query_result.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#include "gpu_query_result.hpp"
2+
#include "duckdb/common/to_string.hpp"
3+
#include "duckdb/main/client_context.hpp"
4+
#include "duckdb/common/box_renderer.hpp"
5+
6+
namespace duckdb {
7+
8+
void GPUResultCollection::SetCapacity(size_t capacity) {
9+
data_chunks = new DataChunk[capacity];
10+
}
11+
12+
void GPUResultCollection::AddChunk(DataChunk& chunk) {
13+
num_rows += chunk.size();
14+
data_chunks[write_idx].Move(chunk);
15+
write_idx += 1;
16+
}
17+
18+
unique_ptr<DataChunk> GPUResultCollection::GetNext() {
19+
// We have returned all of the values then return the empty result
20+
if(read_idx >= write_idx) {
21+
return nullptr;
22+
}
23+
24+
// Create a result that references the value in the buffer
25+
DataChunk& return_chunk = data_chunks[read_idx];
26+
unique_ptr<DataChunk> result_value = make_uniq<DataChunk>();
27+
28+
result_value->InitializeEmpty(return_chunk.GetTypes());
29+
result_value->SetCardinality(return_chunk.size());
30+
for(int col = 0; col < return_chunk.data.size(); col++) {
31+
result_value->data[col].Reference(return_chunk.data[col]);
32+
}
33+
read_idx += 1;
34+
num_rows -= result_value->size();
35+
36+
return result_value;
37+
}
38+
39+
GPUQueryResult::GPUQueryResult(StatementType statement_type, StatementProperties properties,
40+
vector<string> names, vector<LogicalType> types, ClientProperties client_properties, unique_ptr<GPUResultCollection> result_collection)
41+
: QueryResult(QueryResultType::MATERIALIZED_RESULT, statement_type, std::move(properties), types,
42+
std::move(names), std::move(client_properties)), result_collection(std::move(result_collection)) {
43+
44+
}
45+
46+
string GPUQueryResult::ToString() {
47+
std::string result("GPUQueryResult");
48+
return result;
49+
}
50+
51+
string GPUQueryResult::ToBox(ClientContext &context, const BoxRendererConfig &config) {
52+
std::string result("BoxedGPUQueryResult");
53+
return result;
54+
}
55+
56+
idx_t GPUQueryResult::RowCount() const {
57+
idx_t row_count = (idx_t) result_collection->size();
58+
return row_count;
59+
}
60+
61+
unique_ptr<DataChunk> GPUQueryResult::Fetch() {
62+
return FetchRaw();
63+
}
64+
65+
Value GPUQueryResult::GetValue(idx_t column, idx_t index) {
66+
throw InternalException("GetValue not implemented for GPUQueryResult");
67+
}
68+
69+
unique_ptr<DataChunk> GPUQueryResult::FetchRaw() {
70+
return result_collection->GetNext();
71+
}
72+
73+
}

src/include/gpu_query_result.hpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#pragma once
2+
3+
#include "helper/common.h"
4+
#include "utils.hpp"
5+
#include "duckdb/common/winapi.hpp"
6+
#include "duckdb/main/query_result.hpp"
7+
8+
namespace duckdb {
9+
10+
class GPUResultCollection {
11+
public:
12+
GPUResultCollection() : read_idx(0), write_idx(0), num_rows(0), data_chunks(nullptr) {
13+
14+
}
15+
16+
void SetCapacity(size_t capacity);
17+
void AddChunk(DataChunk& chunk);
18+
unique_ptr<DataChunk> GetNext();
19+
20+
size_t size() {
21+
return num_rows;
22+
}
23+
24+
~GPUResultCollection() {
25+
if(data_chunks != nullptr) {
26+
delete[] data_chunks;
27+
}
28+
}
29+
30+
DataChunk* data_chunks;
31+
size_t num_rows;
32+
size_t write_idx;
33+
size_t read_idx;
34+
};
35+
36+
// The reason we need to implement our own QueryResult is that duckdb's MaterializedQueryResult
37+
// in constructed by passing in a ColumnDataCollection which makes a copy of the data when we try
38+
// to Append DataChunks to it. By implement our own basic QueryResult we can bypass this unncessary
39+
// copy
40+
class GPUQueryResult : public QueryResult {
41+
public:
42+
DUCKDB_API GPUQueryResult(StatementType statement_type, StatementProperties properties, vector<string> names,
43+
vector<LogicalType> types, ClientProperties client_properties, unique_ptr<GPUResultCollection> result_collection);
44+
45+
//! Fetches a DataChunk from the query result.
46+
//! This will consume the result (i.e. the result can only be scanned once with this function)
47+
DUCKDB_API unique_ptr<DataChunk> Fetch() override;
48+
DUCKDB_API unique_ptr<DataChunk> FetchRaw() override;
49+
//! Converts the QueryResult to a string
50+
DUCKDB_API string ToString() override;
51+
DUCKDB_API string ToBox(ClientContext &context, const BoxRendererConfig &config) override;
52+
53+
//! Gets the (index) value of the (column index) column.
54+
//! Note: this is very slow. Scanning over the underlying collection is much faster.
55+
DUCKDB_API Value GetValue(idx_t column, idx_t index);
56+
57+
DUCKDB_API idx_t RowCount() const;
58+
59+
private:
60+
// The actual chunks we want to return
61+
unique_ptr<GPUResultCollection> result_collection;
62+
};
63+
64+
}

src/include/operator/gpu_physical_result_collector.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "gpu_physical_operator.hpp"
44
#include "duckdb/common/enums/statement_type.hpp"
55
#include "gpu_buffer_manager.hpp"
6+
#include "gpu_query_result.hpp"
67
#include "duckdb/common/types/column/column_data_collection.hpp"
78

89
namespace duckdb {
@@ -47,7 +48,7 @@ class GPUPhysicalResultCollector : public GPUPhysicalOperator {
4748
class GPUPhysicalMaterializedCollector : public GPUPhysicalResultCollector {
4849
public:
4950
GPUPhysicalMaterializedCollector(GPUPreparedStatementData &data);
50-
unique_ptr<ColumnDataCollection> collection;
51+
unique_ptr<GPUResultCollection> result_collection;
5152
// ColumnDataAppendState append_state;
5253
// bool parallel;
5354

0 commit comments

Comments
 (0)