Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REVIEW] Port scatter to libcudf++ #3354

Merged
merged 50 commits into from
Nov 25, 2019
Merged
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
4759231
Merge branch 'libcudf++-scatter' of https://github.com/shwina/cudf in…
trevorsm7 Nov 11, 2019
67fd0f1
Address comments on the scatter API
trevorsm7 Nov 12, 2019
230b9c2
Add scatter detail header
trevorsm7 Nov 12, 2019
c2264c4
Add skeleton implementation of scatter
trevorsm7 Nov 12, 2019
4ef6e0a
Add scatter to yaml and CMake
trevorsm7 Nov 12, 2019
5eeb9b7
Implement inversion of scatter map to gather map
trevorsm7 Nov 12, 2019
cec81d0
Replace invert_map with column_scatterer
trevorsm7 Nov 13, 2019
86f18d8
Use index_converter to handle negative indices
trevorsm7 Nov 13, 2019
153355a
Add basic scatter test and fix first bug
trevorsm7 Nov 13, 2019
a4ec7f2
Replace for loop with transform
trevorsm7 Nov 13, 2019
2c1da1a
Update changelog
trevorsm7 Nov 13, 2019
9884d8c
Merge branch 'branch-0.11' of https://github.com/rapidsai/cudf into f…
trevorsm7 Nov 13, 2019
5dd8a0b
Implement bitmask scatter using modified gather
trevorsm7 Nov 14, 2019
dbc1f03
Add column copy util with option to add null mask
trevorsm7 Nov 14, 2019
9336c59
Add scatter bitmask implementation
trevorsm7 Nov 15, 2019
a63f8ca
Refactor scatter to use gather_bitmask_kernel
trevorsm7 Nov 15, 2019
58b4b56
Fix bug with target column getting all nulls
trevorsm7 Nov 15, 2019
26fdabe
Merge branch 'branch-0.11' of https://github.com/rapidsai/cudf into f…
trevorsm7 Nov 15, 2019
26e5056
Add column_scalar_scatterer and test
trevorsm7 Nov 16, 2019
045ddf1
Use permutation iterator for dereferencing scalar
trevorsm7 Nov 19, 2019
72f6b76
Add scalar scatter bitmask and tests
trevorsm7 Nov 19, 2019
a67e80f
Add untyped scatter tests
trevorsm7 Nov 19, 2019
9c40032
Add scatter index type tests
trevorsm7 Nov 19, 2019
26d5b4a
Add invalid scatter map type tests
trevorsm7 Nov 19, 2019
160265f
Add empty scatter map tests
trevorsm7 Nov 19, 2019
d1815ad
Merge branch 'branch-0.11' of https://github.com/rapidsai/cudf into f…
trevorsm7 Nov 19, 2019
0ecf6e0
Use scalar_type_t instead of fixed_width_scalar
trevorsm7 Nov 19, 2019
513f4e5
Try to fix ubuntu16.04-cuda9.2 build error
trevorsm7 Nov 20, 2019
2fa9039
Merge branch 'branch-0.11' of https://github.com/rapidsai/cudf into f…
trevorsm7 Nov 20, 2019
3752c8a
Refactor mask allocation out of column_scatterer
trevorsm7 Nov 21, 2019
b941158
Refactor column_scatter to take iterator
trevorsm7 Nov 21, 2019
cdd0453
Add gather.hpp to meta.yaml
trevorsm7 Nov 21, 2019
f639221
Use zip_iterator and for_each in gather_bitmask
trevorsm7 Nov 21, 2019
f0618f7
Strings scatter detail function
davidwendt Nov 21, 2019
56d85ea
change to iterator interface
davidwendt Nov 21, 2019
b2a9866
Merge branch 'branch-0.11' into fea-strings-scatter
davidwendt Nov 21, 2019
df37104
update changelog
davidwendt Nov 21, 2019
4e374aa
Merge branch 'fea-strings-scatter' of https://github.com/davidwendt/c…
trevorsm7 Nov 21, 2019
c07f790
Merge branch 'branch-0.11' of https://github.com/rapidsai/cudf into f…
trevorsm7 Nov 21, 2019
e4f0146
Update gather_bitmask_kernel changes for PR 3303
trevorsm7 Nov 21, 2019
14e1f60
Add scatter strings support using PR 3440
trevorsm7 Nov 22, 2019
fbf9cec
Remove legacy headers from copying.hpp
trevorsm7 Nov 22, 2019
6e401dc
Use rmm::device_vector instead of thrust::
trevorsm7 Nov 22, 2019
d5c261e
Merge branch 'branch-0.11' of https://github.com/rapidsai/cudf into f…
trevorsm7 Nov 22, 2019
2769f98
Use set_null_mask from PR 3172
trevorsm7 Nov 22, 2019
f440fef
Fix gather_bitmask_kernel indentation
trevorsm7 Nov 22, 2019
da7097d
Used fixed block size with gather_bitmask_kernel
trevorsm7 Nov 22, 2019
ab52ced
Replace zip iterator for_each with transform
trevorsm7 Nov 22, 2019
43cf206
Sometimes a for loop is the best thing
trevorsm7 Nov 22, 2019
33b3cc4
Apply suggestions from code review
trevorsm7 Nov 25, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
- PR #2971 Added initial gather and scatter methods for strings_column_view
- PR #3133 Port NVStrings to cudf column: count_characters and count_bytes
- PR #2991 Added strings column functions concatenate and join_strings
- PR #3028 Port gather and scatter to libcudf++
- PR #3028 Port gather to libcudf++
trevorsm7 marked this conversation as resolved.
Show resolved Hide resolved
- PR #3135 Add nvtx utilities to cudf::nvtx namespace
- PR #3021 Java host side concat of serialized buffers
- PR #3138 Move unary files to legacy
Expand Down Expand Up @@ -125,6 +125,7 @@
- PR #3294 Update to arrow-cpp and pyarrow 0.15.1
- PR #3310 Add `row_hasher` and `element_hasher` utilities
- PR #3286 Clean up the starter code on README
- PR #3354 Port gather and scatter to libcudf++
trevorsm7 marked this conversation as resolved.
Show resolved Hide resolved
- PR #3322 Port NVStrings pad operations to cudf strings column
- PR #3345 Add cache member for number of characters in string_view class
- PR #3299 Define and implement new `is_sorted` APIs
Expand All @@ -138,6 +139,7 @@
- PR #3303 Define and implement new stream compaction APIs `copy_if`, `drop_nulls`,
`apply_boolean_mask`, `drop_duplicate` and `unique_count`.
- PR #3387 Strings column gather function
- PR #3440 Strings column scatter function
- PR #3389 Move quantiles.hpp + group_quantiles.hpp files to legacy
- PR #3398 Move reshape.hpp files to legacy
- PR #3425 Strings column copy_if_else implementation
Expand Down
2 changes: 2 additions & 0 deletions conda/recipes/libcudf/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ test:
commands:
- test -f $PREFIX/lib/libcudf.so
- test -f $PREFIX/lib/libcudftestutil.a
- test -f $PREFIX/include/cudf/detail/gather.hpp
- test -f $PREFIX/include/cudf/detail/scatter.hpp
trevorsm7 marked this conversation as resolved.
Show resolved Hide resolved
- test -f $PREFIX/include/cudf/legacy/bitmask.hpp
- test -f $PREFIX/include/cudf/legacy/column.hpp
- test -f $PREFIX/include/cudf/legacy/reshape.hpp
Expand Down
2 changes: 2 additions & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,8 @@ add_library(cudf
src/utilities/nvtx/nvtx_utils.cpp
src/utilities/nvtx/legacy/nvtx_utils.cpp
src/copying/copy.cpp
src/copying/gather.cu
src/copying/scatter.cu
src/copying/copy.cu
src/copying/slice.cpp
src/copying/split.cpp
Expand Down
90 changes: 81 additions & 9 deletions cpp/include/cudf/copying.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@

#pragma once

#include "cudf.h"
#include "types.hpp"
#include <cudf/cudf.h>
#include <cudf/types.hpp>
#include <cudf/scalar/scalar.hpp>
#include <cudf/column/column_view.hpp>
#include <cudf/table/table.hpp>

Expand Down Expand Up @@ -48,14 +46,89 @@ namespace experimental {
* rows in the source columns to rows in the destination columns.
* @param[in] check_bounds Optionally perform bounds checking on the values
* of `gather_map` and throw an error if any of its values are out of bounds.
* @params[in] mr The resource to use for all allocations
* @return cudf::table Result of the gather
* @param[in] mr The resource to use for all allocations
* @return std::unique_ptr<table> Result of the gather
*/
std::unique_ptr<table> gather(table_view const& source_table, column_view const& gather_map,
bool check_bounds = false,
rmm::mr::device_memory_resource* mr = rmm::mr::get_default_resource());
bool check_bounds = false,
rmm::mr::device_memory_resource* mr = rmm::mr::get_default_resource());

/**
* @brief Scatters the rows of the source table into a copy of the target table
* according to a scatter map.
*
* Scatters values from the source table into the target table out-of-place,
* returning a "destination table". The scatter is performed according to a
* scatter map such that row `scatter_map[i]` of the destination table gets row
* `i` of the source table. All other rows of the destination table equal
* corresponding rows of the target table.
*
* The number of columns in source must match the number of columns in target
* and their corresponding datatypes must be the same.
*
* If the same index appears more than once in the scatter map, the result is
* undefined.
*
* A negative value `i` in the `scatter_map` is interpreted as `i+n`, where `n`
* is the number of rows in the `target` table.
*
* @throws `cudf::logic_error` if `check_bounds == true` and an index exists in
* `scatter_map` outside the range `[-n, n)`, where `n` is the number of rows in
* the target table. If `check_bounds == false`, the behavior is undefined.
*
* @param source The input columns containing values to be scattered into the
* target columns
* @param scatter_map A non-nullable column of integral indices that maps the
* rows in the source table to rows in the target table. The size must be equal
* to or less than the number of elements in the source columns.
* @param target The set of columns into which values from the source_table
* are to be scattered
* @param check_bounds Optionally perform bounds checking on the values of
* `scatter_map` and throw an error if any of its values are out of bounds.
* @param mr The resource to use for all allocations
* @return Result of scattering values from source to target
*---------------------------------------------------------------------------**/
std::unique_ptr<table> scatter(
table_view const& source, column_view const& scatter_map,
table_view const& target, bool check_bounds = false,
rmm::mr::device_memory_resource* mr = rmm::mr::get_default_resource());

/**
* @brief Scatters a row of scalar values into a copy of the target table
harrism marked this conversation as resolved.
Show resolved Hide resolved
* according to a scatter map.
*
* Scatters values from the source row into the target table out-of-place,
* returning a "destination table". The scatter is performed according to a
* scatter map such that row `scatter_map[i]` of the destination table is
* replaced by the source row. All other rows of the destination table equal
* corresponding rows of the target table.
*
* The number of elements in source must match the number of columns in target
* and their corresponding datatypes must be the same.
*
* If the same index appears more than once in the scatter map, the result is
* undefined.
*
* @throws `cudf::logic_error` if `check_bounds == true` and an index exists in
* `scatter_map` outside the range `[-n, n)`, where `n` is the number of rows in
* the target table. If `check_bounds == false`, the behavior is undefined.
*
* @param source The input scalars containing values to be scattered into the
* target columns
* @param indices A non-nullable column of integral indices that indicate
* the rows in the target table to be replaced by source.
* @param target The set of columns into which values from the source_table
* are to be scattered
* @param check_bounds Optionally perform bounds checking on the values of
* `scatter_map` and throw an error if any of its values are out of bounds.
* @param mr The resource to use for all allocations
* @return Result of scattering values from source to target
*---------------------------------------------------------------------------**/
std::unique_ptr<table> scatter(
std::vector<std::unique_ptr<scalar>> const& source, column_view const& indices,
table_view const& target, bool check_bounds = false,
rmm::mr::device_memory_resource* mr = rmm::mr::get_default_resource());


/** ---------------------------------------------------------------------------*
* @brief Indicates when to allocate a mask, based on an existing mask.
* ---------------------------------------------------------------------------**/
Expand All @@ -65,7 +138,6 @@ enum class mask_allocation_policy {
ALWAYS ///< Allocate a null mask, regardless of input
};


/*
* Initializes and returns an empty column of the same type as the `input`.
*
Expand Down
15 changes: 8 additions & 7 deletions cpp/include/cudf/detail/gather.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,9 @@ __global__ void gather_bitmask_kernel(table_device_view source_table,

for (size_type i = 0; i < source_table.num_columns(); i++) {

constexpr int warp_size = 32;

column_device_view source_col = source_table.column(i);

if (source_col.has_nulls()) {
if (masks[i] != nullptr) {
size_type destination_row_base = blockIdx.x * blockDim.x;
cudf::size_type valid_count_accumulate = 0;

Expand All @@ -72,14 +70,17 @@ __global__ void gather_bitmask_kernel(table_device_view source_table,
size_type source_row =
thread_active ? gather_map[destination_row] : 0;

bool source_bit_is_valid = source_col.has_nulls()
? source_col.is_valid_nocheck(source_row)
: true;
bool bit_is_valid;
if (ignore_out_of_bounds && (source_row < 0 || source_row >= source_col.size())) {
bit_is_valid = thread_active && bit_is_set(masks[i], destination_row);
} else {
bit_is_valid = source_col.is_valid(source_row);
}

// Use ballot to find all valid bits in this warp and create the output
// bitmask element
const uint32_t valid_warp =
__ballot_sync(0xffffffff, thread_active && source_bit_is_valid);
__ballot_sync(0xffffffff, thread_active && bit_is_valid);

const size_type valid_index = word_index(destination_row);

Expand Down
110 changes: 110 additions & 0 deletions cpp/include/cudf/detail/scatter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright (c) 2019, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once

#include <cudf/column/column_view.hpp>
#include <cudf/table/table_view.hpp>
#include <cudf/table/table.hpp>

#include <memory>

namespace cudf {
namespace experimental {
namespace detail {

/**
* @brief Scatters the rows of the source table into a copy of the target table
* according to a scatter map.
*
* Scatters values from the source table into the target table out-of-place,
* returning a "destination table". The scatter is performed according to a
* scatter map such that row `scatter_map[i]` of the destination table gets row
* `i` of the source table. All other rows of the destination table equal
* corresponding rows of the target table.
*
* The number of columns in source must match the number of columns in target
* and their corresponding datatypes must be the same.
*
* A negative value `i` in the `scatter_map` is interpreted as `i+n`, where `n`
* is the number of rows in the `target` table.
*
* If the same index appears more than once in the scatter map, the result is
* undefined.
*
* @throws `cudf::logic_error` if `check_bounds == true` and an index exists in
* `scatter_map` outside the range `[-n, n)`, where `n` is the number of rows in
* the target table. If `check_bounds == false`, the behavior is undefined.
*
* @param source The input columns containing values to be scattered into the
* target columns
* @param scatter_map A non-nullable column of integral indices that maps the
* rows in the source table to rows in the target table. The size must be equal
* to or less than the number of elements in the source columns.
* @param target The set of columns into which values from the source_table
* are to be scattered
* @param check_bounds Optionally perform bounds checking on the values of
* `scatter_map` and throw an error if any of its values are out of bounds.
* @param mr The resource to use for all allocations
* @param stream The stream to use for CUDA operations
* @return Result of scattering values from source to target
*---------------------------------------------------------------------------**/
std::unique_ptr<table> scatter(
table_view const& source, column_view const& scatter_map,
table_view const& target, bool check_bounds = false,
rmm::mr::device_memory_resource* mr = rmm::mr::get_default_resource(),
cudaStream_t stream = 0);

/**
* @brief Scatters a row of scalar values into a copy of the target table
* according to a scatter map.
*
* Scatters values from the source row into the target table out-of-place,
* returning a "destination table". The scatter is performed according to a
* scatter map such that row `scatter_map[i]` of the destination table is
* replaced by the source row. All other rows of the destination table equal
* corresponding rows of the target table.
*
* The number of elements in source must match the number of columns in target
* and their corresponding datatypes must be the same.
*
* If the same index appears more than once in the scatter map, the result is
* undefined.
*
* @throws `cudf::logic_error` if `check_bounds == true` and an index exists in
* `scatter_map` outside the range `[-n, n)`, where `n` is the number of rows in
* the target table. If `check_bounds == false`, the behavior is undefined.
*
* @param source The input scalars containing values to be scattered into the
* target columns
* @param indices A non-nullable column of integral indices that indicate
* the rows in the target table to be replaced by source.
* @param target The set of columns into which values from the source_table
* are to be scattered
* @param check_bounds Optionally perform bounds checking on the values of
* `scatter_map` and throw an error if any of its values are out of bounds.
* @param mr The resource to use for all allocations
* @param stream The stream to use for CUDA operations
* @return Result of scattering values from source to target
*---------------------------------------------------------------------------**/
std::unique_ptr<table> scatter(
std::vector<std::unique_ptr<scalar>> const& source, column_view const& indices,
table_view const& target, bool check_bounds = false,
rmm::mr::device_memory_resource* mr = rmm::mr::get_default_resource(),
cudaStream_t stream = 0);

} // namespace detail
} // namespace experimental
} // namespace cudf
Loading