Skip to content
Draft
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
21 changes: 19 additions & 2 deletions ci/run_cudf_benchmark_smoketests.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#!/bin/bash
# SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION.
# SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

set -euo pipefail

repo_root="$(dirname "$(realpath "${BASH_SOURCE[0]}")")/.."

# Support customizing the benchmarks' install location
# First, try the installed location (CI/conda environments)
installed_benchmark_location="${INSTALL_PREFIX:-${CONDA_PREFIX:-/usr}}/bin/benchmarks/libcudf/"
Expand All @@ -22,12 +24,22 @@ else
fi

EXITCODE=0
validation_dir="$(mktemp -d)"
ndsh_scale_factor=1
trap 'rm -rf "${validation_dir}"' EXIT
# Run all nvbench benchmarks with --profile and rmm_mode=cuda
for bench in *_NVBENCH; do
if [[ -x "$bench" && -f "$bench" ]]; then
start_time=$(date +%s)
echo "Running $bench with --profile..."
"./$bench" --profile --devices 0 -q --rmm_mode cuda
args=(--profile --devices 0 -q --rmm_mode cuda)
if [[ "$bench" == NDSH_* ]]; then
args+=(--axis "scale_factor=${ndsh_scale_factor}")
if [[ "$bench" =~ ^NDSH_Q([0-9]{2})_NVBENCH$ ]]; then
args+=(--output_directory "${validation_dir}/q${BASH_REMATCH[1]}")
fi
fi
"./$bench" "${args[@]}"
SUITEERROR=$?
end_time=$(date +%s)
duration=$((end_time - start_time))
Expand All @@ -40,5 +52,10 @@ for bench in *_NVBENCH; do
fi
done

python "${repo_root}/ci/validate_ndsh_benchmarks.py" \
--output-dir "${validation_dir}" \
--sql-dir "${repo_root}/cpp/libcudf_streaming/benchmarks/streaming/ndsh/sql" \
--scale-factor "${ndsh_scale_factor}"

echo "Test script exiting with value: $EXITCODE"
exit ${EXITCODE}
130 changes: 130 additions & 0 deletions ci/validate_ndsh_benchmarks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#!/usr/bin/env python3
# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

import argparse
import math
import numbers
from pathlib import Path

import duckdb

QUERIES = (
"q01",
"q02",
"q03",
"q04",
"q05",
"q06",
"q07",
"q08",
"q09",
"q10",
"q11",
"q12",
"q13",
"q14",
"q15",
"q16",
"q17",
"q18",
"q19",
"q20",
"q21",
"q22",
)
EXPECTED_NAMES = {
"q18": [
"c_name",
"c_custkey",
"o_orderkey",
"o_orderdate",
"o_totalprice",
"sum(l_quantity)",
]
}


def values_equal(actual, expected):
if actual is None or expected is None:
return actual is expected
if isinstance(actual, numbers.Number) and isinstance(
expected, numbers.Number
):
return math.isclose(
float(actual), float(expected), rel_tol=0.0, abs_tol=0.01
)
return actual == expected


def validate_query(query_name, sql_dir, output_dir, scale_factor=0.01):
connection = duckdb.connect()
for path in (output_dir / query_name / "input").glob("*.parquet"):
table_name = path.stem.replace('"', '""')
parquet_path = str(path).replace("'", "''")
connection.execute(
f'CREATE VIEW "{table_name}" AS '
f"SELECT * FROM read_parquet('{parquet_path}')"
)

parameters = (
{"scale_factor": scale_factor} if query_name == "q11" else None
)
expected = connection.execute(
(sql_dir / f"{query_name}.sql").read_text(), parameters
)
expected_names = [column[0] for column in expected.description]
expected_rows = expected.fetchall()

result_path = output_dir / query_name / "results" / f"{query_name}.parquet"
actual = connection.execute(
"SELECT * FROM read_parquet(?)", [str(result_path)]
)
actual_names = [column[0] for column in actual.description]
actual_rows = actual.fetchall()

expected_names = EXPECTED_NAMES.get(query_name, expected_names)
if actual_names != expected_names:
return f"column names differ: {actual_names} != {expected_names}"
if len(actual_rows) != len(expected_rows):
return f"row counts differ: {len(actual_rows)} != {len(expected_rows)}"

for row_index, (actual_row, expected_row) in enumerate(
zip(actual_rows, expected_rows, strict=True)
):
for column_name, actual_value, expected_value in zip(
actual_names, actual_row, expected_row, strict=True
):
if not values_equal(actual_value, expected_value):
return (
f"row {row_index}, column {column_name} differs: "
f"{actual_value!r} != {expected_value!r}"
)
return None


def main():
parser = argparse.ArgumentParser(
description="Validate NDS-H benchmark Parquet results against DuckDB"
)
parser.add_argument("--output-dir", type=Path, required=True)
parser.add_argument("--sql-dir", type=Path, required=True)
parser.add_argument("--scale-factor", type=float, default=0.01)
args = parser.parse_args()

failed = False
for query_name in QUERIES:
error = validate_query(
query_name, args.sql_dir, args.output_dir, args.scale_factor
)
if error is None:
print(f"{query_name}: PASSED")
else:
failed = True
print(f"{query_name}: FAILED: {error}")

raise SystemExit(failed)


if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions conda/environments/all_cuda-129_arch-aarch64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ dependencies:
- dask-cuda==26.10.*,>=0.0.0a0
- dlpack>=0.8,<1.0
- doxygen=1.9.1
- duckdb
- fastavro>=0.22.9
- flatbuffers==24.3.25
- fsspec>=0.6.0
Expand Down
1 change: 1 addition & 0 deletions conda/environments/all_cuda-129_arch-x86_64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ dependencies:
- dask-cuda==26.10.*,>=0.0.0a0
- dlpack>=0.8,<1.0
- doxygen=1.9.1
- duckdb
- fastavro>=0.22.9
- flatbuffers==24.3.25
- fsspec>=0.6.0
Expand Down
1 change: 1 addition & 0 deletions conda/environments/all_cuda-133_arch-aarch64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ dependencies:
- dask-cuda==26.10.*,>=0.0.0a0
- dlpack>=0.8,<1.0
- doxygen=1.9.1
- duckdb
- fastavro>=0.22.9
- flatbuffers==24.3.25
- fsspec>=0.6.0
Expand Down
1 change: 1 addition & 0 deletions conda/environments/all_cuda-133_arch-x86_64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ dependencies:
- dask-cuda==26.10.*,>=0.0.0a0
- dlpack>=0.8,<1.0
- doxygen=1.9.1
- duckdb
- fastavro>=0.22.9
- flatbuffers==24.3.25
- fsspec>=0.6.0
Expand Down
4 changes: 4 additions & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1600,6 +1600,10 @@ if(CUDF_BUILD_BENCHMARKS)
add_subdirectory(benchmarks)
endif()

if(CUDF_BUILD_TESTS)
rapids_test_install_relocatable(INSTALL_COMPONENT_SET testing DESTINATION bin/gtests/libcudf)
endif()

# ##################################################################################################
# * install targets -------------------------------------------------------------------------------
rapids_cmake_install_lib_dir(lib_dir)
Expand Down
40 changes: 40 additions & 0 deletions cpp/benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,29 @@ target_include_directories(
"$<BUILD_INTERFACE:${CUDF_SOURCE_DIR}/src>"
)

if(CUDF_BUILD_TESTS)
add_executable(NDSH_DATA_GENERATOR_TEST common/ndsh_data_generator/ndsh_data_generator_test.cpp)
set_target_properties(
NDSH_DATA_GENERATOR_TEST
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "$<BUILD_INTERFACE:${CUDF_BINARY_DIR}/gtests>"
INSTALL_RPATH "\$ORIGIN/../../../lib"
CXX_STANDARD 20
CXX_STANDARD_REQUIRED ON
)
target_link_libraries(
NDSH_DATA_GENERATOR_TEST PRIVATE ndsh_data_generator cudf::cudftestutil_objects
$<TARGET_NAME_IF_EXISTS:conda_env>
)
rapids_cuda_set_runtime(NDSH_DATA_GENERATOR_TEST USE_STATIC ON)
rapids_test_add(
NAME NDSH_DATA_GENERATOR_TEST
COMMAND NDSH_DATA_GENERATOR_TEST
GPUS 1
PERCENT 15
INSTALL_COMPONENT_SET testing
)
endif()

# ##################################################################################################
# * compiler function -----------------------------------------------------------------------------

Expand Down Expand Up @@ -125,10 +148,27 @@ ConfigureNVBench(TRANSPOSE_NVBENCH transpose/transpose.cpp)
# ##################################################################################################
# * nds-h benchmark --------------------------------------------------------------------------------
ConfigureNVBench(NDSH_Q01_NVBENCH ndsh/q01.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q02_NVBENCH ndsh/q02.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q03_NVBENCH ndsh/q03.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q04_NVBENCH ndsh/q04.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q05_NVBENCH ndsh/q05.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q06_NVBENCH ndsh/q06.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q07_NVBENCH ndsh/q07.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q08_NVBENCH ndsh/q08.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q09_NVBENCH ndsh/q09.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q10_NVBENCH ndsh/q10.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q11_NVBENCH ndsh/q11.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q12_NVBENCH ndsh/q12.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q13_NVBENCH ndsh/q13.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q14_NVBENCH ndsh/q14.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q15_NVBENCH ndsh/q15.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q16_NVBENCH ndsh/q16.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q17_NVBENCH ndsh/q17.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q18_NVBENCH ndsh/q18.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q19_NVBENCH ndsh/q19.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q20_NVBENCH ndsh/q20.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q21_NVBENCH ndsh/q21.cpp ndsh/utilities.cpp)
ConfigureNVBench(NDSH_Q22_NVBENCH ndsh/q22.cpp ndsh/utilities.cpp)

# ##################################################################################################
# * filter benchmark -------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

#include "ndsh_data_generator.hpp"

#include <cudf_test/base_fixture.hpp>

#include <cudf/reduction.hpp>
#include <cudf/scalar/scalar.hpp>

#include <gtest/gtest.h>

struct NDSHDataGeneratorTest : public cudf::test::BaseFixture {};

TEST_F(NDSHDataGeneratorTest, ScaleFactorPointZeroOne)
{
constexpr double scale_factor = 0.01;

auto [orders, lineitem, part] = cudf::datagen::generate_orders_lineitem_part(scale_factor);
auto partsupp = cudf::datagen::generate_partsupp(scale_factor);
auto supplier = cudf::datagen::generate_supplier(scale_factor);
auto customer = cudf::datagen::generate_customer(scale_factor);
auto nation = cudf::datagen::generate_nation();
auto region = cudf::datagen::generate_region();

auto const expect_cardinality =
[](cudf::table const& table, cudf::size_type rows, cudf::size_type columns) {
EXPECT_EQ(table.num_rows(), rows);
EXPECT_EQ(table.num_columns(), columns);
};

expect_cardinality(*orders, 15'000, 9);
EXPECT_GE(lineitem->num_rows(), 15'000);
EXPECT_LE(lineitem->num_rows(), 105'000);
EXPECT_EQ(lineitem->num_columns(), 16);
expect_cardinality(*part, 2'000, 9);
expect_cardinality(*partsupp, 8'000, 5);
expect_cardinality(*supplier, 100, 7);
expect_cardinality(*customer, 1'500, 8);
expect_cardinality(*nation, 25, 4);
expect_cardinality(*region, 5, 3);

auto const expect_supplier_key_range = [](cudf::column_view const& keys,
cudf::size_type supplier_rows) {
EXPECT_EQ(keys.null_count(), 0);
auto const [minimum, maximum] = cudf::minmax(keys);
auto const min_key = static_cast<cudf::numeric_scalar<cudf::size_type> const*>(minimum.get());
auto const max_key = static_cast<cudf::numeric_scalar<cudf::size_type> const*>(maximum.get());
EXPECT_GE(min_key->value(), 1);
EXPECT_LE(max_key->value(), supplier_rows);
};

expect_supplier_key_range(lineitem->view().column(2), supplier->num_rows());
expect_supplier_key_range(partsupp->view().column(1), supplier->num_rows());
}
12 changes: 7 additions & 5 deletions cpp/benchmarks/common/ndsh_data_generator/table_helpers.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION.
* SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

Expand Down Expand Up @@ -145,13 +145,14 @@ std::unique_ptr<cudf::table> perform_left_join(cudf::table_view const& left_inpu
* @param mr Device memory resource used to allocate the returned column's device memory
*/
[[nodiscard]] std::unique_ptr<cudf::column> calculate_l_suppkey(cudf::column_view const& l_partkey,
cudf::size_type scale_factor,
double scale_factor,
cudf::size_type num_rows,
rmm::cuda_stream_view stream,
rmm::device_async_resource_ref mr)
{
CUDF_BENCHMARK_RANGE();
// Expression: (l_partkey + (i * (s/4 + (int)(l_partkey - 1)/s))) % s + 1
auto const supplier_count = static_cast<cudf::size_type>(scale_factor * 10'000);

// Generate the `s` col
auto s_empty = cudf::make_numeric_column(
Expand All @@ -160,7 +161,7 @@ std::unique_ptr<cudf::table> perform_left_join(cudf::table_view const& left_inpu
auto s = cudf::fill(s_empty->view(),
0,
num_rows,
cudf::numeric_scalar<cudf::size_type>(scale_factor * 10'000),
cudf::numeric_scalar<cudf::size_type>(supplier_count),
stream,
mr);

Expand Down Expand Up @@ -217,13 +218,14 @@ std::unique_ptr<cudf::table> perform_left_join(cudf::table_view const& left_inpu
*/
[[nodiscard]] std::unique_ptr<cudf::column> calculate_ps_suppkey(
cudf::column_view const& ps_partkey,
cudf::size_type scale_factor,
double scale_factor,
cudf::size_type num_rows,
rmm::cuda_stream_view stream,
rmm::device_async_resource_ref mr)
{
CUDF_BENCHMARK_RANGE();
// Expression: ps_suppkey = (ps_partkey + (i * (s/4 + (int)(ps_partkey - 1)/s))) % s + 1
auto const supplier_count = static_cast<cudf::size_type>(scale_factor * 10'000);

// Generate the `s` col
auto s_empty = cudf::make_numeric_column(
Expand All @@ -232,7 +234,7 @@ std::unique_ptr<cudf::table> perform_left_join(cudf::table_view const& left_inpu
auto s = cudf::fill(s_empty->view(),
0,
num_rows,
cudf::numeric_scalar<cudf::size_type>(scale_factor * 10'000),
cudf::numeric_scalar<cudf::size_type>(supplier_count),
stream,
mr);

Expand Down
Loading
Loading