Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 14 additions & 2 deletions cpp/benchmarks/string/replace.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2021-2025, NVIDIA CORPORATION.
* SPDX-FileCopyrightText: Copyright (c) 2021-2026, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/

Expand All @@ -14,6 +14,8 @@

#include <nvbench/nvbench.cuh>

#include <vector>

enum replace_type { scalar, slice, multi };

static void bench_replace(nvbench::state& state)
Expand Down Expand Up @@ -51,6 +53,16 @@ static void bench_replace(nvbench::state& state)
cudf::string_scalar repl("0123456789");
state.exec(nvbench::exec_tag::sync,
[&](nvbench::launch& launch) { cudf::strings::replace_slice(input, repl, 1, 10); });
} else if (api == "column") {
// Per-row targets and replacements — same length as input
std::vector<std::string> t_vals(num_rows, "+");
std::vector<std::string> r_vals(num_rows, "-");
cudf::test::strings_column_wrapper targets_col(t_vals.begin(), t_vals.end());
cudf::test::strings_column_wrapper repls_col(r_vals.begin(), r_vals.end());
cudf::strings_column_view targets(targets_col);
cudf::strings_column_view repls(repls_col);
state.exec(nvbench::exec_tag::sync,
[&](nvbench::launch& launch) { cudf::strings::replace(input, targets, repls); });
}
}

Expand All @@ -59,4 +71,4 @@ NVBENCH_BENCH(bench_replace)
.add_int64_axis("min_width", {0})
.add_int64_axis("max_width", {32, 64, 128, 256})
.add_int64_axis("num_rows", {32768, 262144, 2097152})
.add_string_axis("api", {"scalar", "multi", "slice"});
.add_string_axis("api", {"scalar", "multi", "slice", "column"});
38 changes: 37 additions & 1 deletion cpp/include/cudf/strings/replace.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2019-2024, NVIDIA CORPORATION.
* SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
Expand Down Expand Up @@ -101,6 +101,42 @@ std::unique_ptr<column> replace_slice(
rmm::cuda_stream_view stream = cudf::get_default_stream(),
rmm::device_async_resource_ref mr = cudf::get_current_device_resource_ref());

/**
* @brief Replaces, per row, all occurrences of `targets[i]` within `input[i]` with `repls[i]`.
*
* For each row `i`, this function searches `input[i]` for the substring `targets[i]`
* and replaces every occurrence with `repls[i]`. If `targets[i]` is an empty string,
* `input[i]` is copied unchanged. If `targets[i]` is not found,
* the output entry is a copy of `input[i]`.
*
* Output row `i` is null if any of `input[i]`, `targets[i]`, or `repls[i]` is null.
*
* @code{.pseudo}
* Example:
* input = ["hello world", "foo bar", "aaa"]
* targets = ["o", "bar", "a"]
* repls = ["0", "BAR", "X"]
* result = replace(input, targets, repls)
* result is now ["hell0 w0rld", "foo BAR", "XXX"]
* @endcode
*
* @throw std::invalid_argument if `targets.size() != input.size()`
* @throw std::invalid_argument if `repls.size() != input.size()`
*
* @param input Strings column for this operation
* @param targets Per-row strings to search for within each input string
* @param repls Per-row replacement strings used when the corresponding target is found
* @param stream CUDA stream used for device memory operations and kernel launches
* @param mr Device memory resource used to allocate the returned column's device memory
* @return New strings column
*/
std::unique_ptr<column> replace(
strings_column_view const& input,
strings_column_view const& targets,
strings_column_view const& repls,
rmm::cuda_stream_view stream = cudf::get_default_stream(),
rmm::device_async_resource_ref mr = cudf::get_current_device_resource_ref());

/**
* @brief Replaces substrings matching a list of targets with the corresponding
* replacement strings.
Expand Down
1 change: 1 addition & 0 deletions cpp/src/interop/to_arrow_host.cu
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ struct dispatch_to_arrow_host {
: column.null_mask(),
bitmap->buffer.size_bytes,
stream));
stream.synchronize(); // ensures the bitmap is not destroyed before the copy is completed
return NANOARROW_OK;
}

Expand Down
2 changes: 1 addition & 1 deletion cpp/src/io/json/host_tree_algorithms.cu
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,7 @@ std::
column_categories.cbegin(),
expected_types.begin(),
[](auto exp, auto cat) { return exp == NUM_NODE_CLASSES ? cat : exp; });
cudf::detail::cuda_memcpy_async<NodeT>(d_column_tree.node_categories, expected_types, stream);
cudf::detail::cuda_memcpy<NodeT>(d_column_tree.node_categories, expected_types, stream);

return {is_pruned, is_mixed_pruned, columns};
}
Expand Down
1 change: 1 addition & 0 deletions cpp/src/io/orc/reader_impl_chunking.cu
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,7 @@ void reader_impl::load_next_stripe_data(read_mode mode)
CUDF_CUDA_TRY(
cudf::detail::memcpy_async(dev_dst, host_buffer->data(), host_buffer->size(), _stream));
}
_stream.synchronize();

for (auto& task : device_read_tasks) { // if there were device reads
CUDF_EXPECTS(task.first.get() == task.second, "Unexpected discrepancy in bytes read.");
Expand Down
3 changes: 1 addition & 2 deletions cpp/src/io/parquet/reader_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,7 @@ void reader_impl::decode_page_data(read_mode mode, size_t skip_rows, size_t num_
std::fill(
host_offsets_vector.begin(), host_offsets_vector.end(), std::numeric_limits<size_t>::max());
// Initialize the initial string offsets vector from the host vector
initial_str_offsets =
cudf::detail::make_device_uvector_async(host_offsets_vector, _stream, _mr);
initial_str_offsets = cudf::detail::make_device_uvector(host_offsets_vector, _stream, _mr);
chunk_nested_str_data.host_to_device_async(_stream);
}

Expand Down
4 changes: 2 additions & 2 deletions cpp/src/io/parquet/reader_impl_chunking_utils.cu
Original file line number Diff line number Diff line change
Expand Up @@ -715,8 +715,8 @@ rmm::device_uvector<size_t> compute_decompression_scratch_sizes(
return cudf::io::detail::get_decompression_scratch_size(d);
});

rmm::device_uvector<size_t> d_temp_cost = cudf::detail::make_device_uvector_async(
temp_cost, stream, cudf::get_current_device_resource_ref());
rmm::device_uvector<size_t> d_temp_cost =
cudf::detail::make_device_uvector(temp_cost, stream, cudf::get_current_device_resource_ref());

std::array codecs{compression_type::BROTLI,
compression_type::GZIP,
Expand Down
1 change: 1 addition & 0 deletions cpp/src/io/parquet/reader_impl_preprocess_utils.cu
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ void fill_in_page_info(host_span<ColumnChunkDesc> chunks,
iter,
iter + num_pages,
copy_page_info{d_page_indexes, pages});
stream.synchronize(); // ensures the page_indexes is not destroyed before the copy is completed
}

std::string encoding_to_string(Encoding encoding)
Expand Down
1 change: 1 addition & 0 deletions cpp/src/io/parquet/stats_filter_helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ class stats_caster_base {
auto d_chars = cudf::detail::make_device_uvector_async(host_chars, stream, mr);
auto d_offsets = cudf::detail::make_device_uvector_async(offsets, stream, mr);
auto d_sizes = cudf::detail::make_device_uvector_async(sizes, stream, mr);
stream.synchronize(); // ensures the vectors are not destroyed before the copy is completed
return {std::move(d_chars), std::move(d_offsets), std::move(d_sizes)};
}

Expand Down
2 changes: 1 addition & 1 deletion cpp/src/jit/helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ column_views_to_device(std::span<ColumnView const> views,
}

rmm::device_uvector<DeviceView> device_array{handles.size(), stream, mr};
cudf::detail::cuda_memcpy_async<DeviceView>(device_array, host_array, stream);
cudf::detail::cuda_memcpy<DeviceView>(device_array, host_array, stream);

return std::make_tuple(std::move(handles), std::move(device_array));
}
Expand Down
1 change: 1 addition & 0 deletions cpp/src/join/sort_merge_join.cu
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,7 @@ sort_merge_join::left_join(table_view const& left,
sizes[1] = preprocessed_right_indices->size();

batched_copy(input_iterators.begin(), output_iterators.begin(), sizes.begin(), 2, stream);
stream.synchronize(); // ensures the vectors are not destroyed before the copy is completed
}

// Append filtered null rows with JoinNoMatch for right side
Expand Down
1 change: 1 addition & 0 deletions cpp/src/reshape/table_to_array.cu
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ void table_to_array_impl(table_view const& input,

cudf::detail::batched_memcpy_async(
d_srcs.begin(), d_dsts.begin(), sizes, num_columns, stream.value());
stream.synchronize(); // ensures h_srcs and h_dsts are not destroyed before the copy is done
}

struct table_to_array_dispatcher {
Expand Down
4 changes: 2 additions & 2 deletions cpp/src/strings/convert/convert_datetime.cu
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ struct format_compiler {
}

// copy format_items to device memory
d_items = cudf::detail::make_device_uvector_async(
items, stream, cudf::get_current_device_resource_ref());
d_items =
cudf::detail::make_device_uvector(items, stream, cudf::get_current_device_resource_ref());
}

device_span<format_item const> format_items() { return device_span<format_item const>(d_items); }
Expand Down
6 changes: 3 additions & 3 deletions cpp/src/strings/filter_chars.cu
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2020-2025, NVIDIA CORPORATION.
* SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/

Expand Down Expand Up @@ -123,8 +123,8 @@ std::unique_ptr<column> filter_characters(
characters_to_filter.begin(), characters_to_filter.end(), htable.begin(), [](auto entry) {
return char_range{entry.first, entry.second};
});
rmm::device_uvector<char_range> table = cudf::detail::make_device_uvector_async(
htable, stream, cudf::get_current_device_resource_ref());
rmm::device_uvector<char_range> table =
cudf::detail::make_device_uvector(htable, stream, cudf::get_current_device_resource_ref());

auto d_strings = column_device_view::create(strings.parent(), stream);

Expand Down
4 changes: 2 additions & 2 deletions cpp/src/strings/regex/regexec.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2019-2025, NVIDIA CORPORATION. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

Expand Down Expand Up @@ -106,7 +106,7 @@ std::unique_ptr<reprog_device, std::function<void(reprog_device*)>> reprog_devic
d_prog->_prog_size = memsize + sizeof(reprog_device);

// copy flat prog to device memory
cudf::detail::cuda_memcpy_async<u_char>(*d_buffer, h_buffer, stream);
cudf::detail::cuda_memcpy<u_char>(*d_buffer, h_buffer, stream);

// build deleter to cleanup device memory
auto deleter = [d_buffer](reprog_device* t) {
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/strings/replace/backref_re.cu
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ std::unique_ptr<column> replace_with_backrefs(strings_column_view const& input,
// parse the repl string for back-ref indicators
auto group_count = std::min(99, d_prog->group_counts()); // group count should NOT exceed 99
auto const parse_result = parse_backrefs(replacement, group_count);
rmm::device_uvector<backref_type> backrefs = cudf::detail::make_device_uvector_async(
rmm::device_uvector<backref_type> backrefs = cudf::detail::make_device_uvector(
parse_result.second, stream, cudf::get_current_device_resource_ref());
string_scalar repl_scalar(
parse_result.first, true, stream, cudf::get_current_device_resource_ref());
Expand Down
4 changes: 2 additions & 2 deletions cpp/src/strings/replace/multi_re.cu
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2019-2025, NVIDIA CORPORATION.
* SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/

Expand Down Expand Up @@ -171,7 +171,7 @@ std::unique_ptr<column> replace_re(strings_column_view const& input,
return *prog;
});
auto d_progs =
cudf::detail::make_device_uvector_async(progs, stream, cudf::get_current_device_resource_ref());
cudf::detail::make_device_uvector(progs, stream, cudf::get_current_device_resource_ref());

auto const d_strings = column_device_view::create(input.parent(), stream);
auto const d_repls = column_device_view::create(replacements.parent(), stream);
Expand Down
Loading
Loading