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
18 changes: 18 additions & 0 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ jobs:
- changed-files
- checks
- clang-tidy
- conda-cpp-build-cpu
- conda-cpp-build
- conda-cpp-tests
- conda-cpp-checks
Expand Down Expand Up @@ -169,6 +170,23 @@ jobs:
arch: "amd64"
container_image: "rapidsai/ci-conda:26.06-latest"
script: "ci/run_clang_tidy.sh"
conda-cpp-build-cpu:
needs: [checks, changed-files]
permissions:
actions: read
contents: read
id-token: write
packages: read
pull-requests: read
secrets: inherit # zizmor: ignore[secrets-inherit]
uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@release/26.06
if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp
with:
build_type: pull-request
node_type: cpu16
arch: "amd64"
container_image: "rapidsai/ci-conda:26.06-latest"
script: "env NVFOREST_EXTRA_CMAKE_ARGS=-DNVFOREST_ENABLE_GPU=OFF ci/build_cpp.sh"
conda-cpp-build:
needs: checks
permissions:
Expand Down
1 change: 1 addition & 0 deletions conda/recipes/libnvforest/recipe.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ cache:
CMAKE_CXX_COMPILER_LAUNCHER: ${{ env.get("CMAKE_CXX_COMPILER_LAUNCHER") }}
CMAKE_GENERATOR: ${{ env.get("CMAKE_GENERATOR") }}
NVCC_APPEND_FLAGS: ${{ env.get("NVCC_APPEND_FLAGS", default="") }}
NVFOREST_EXTRA_CMAKE_ARGS: ${{ env.get("NVFOREST_EXTRA_CMAKE_ARGS", default="") }}
PARALLEL_LEVEL: ${{ env.get("PARALLEL_LEVEL", default="8") }}
RAPIDS_ARTIFACTS_DIR: ${{ env.get("RAPIDS_ARTIFACTS_DIR", default="") }}
SCCACHE_BUCKET: ${{ env.get("SCCACHE_BUCKET", default="") }}
Expand Down
6 changes: 3 additions & 3 deletions cpp/include/nvforest/exceptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ struct unusable_model_exception : std::exception {
/** Exception indicating model import failed */
struct model_import_error : std::exception {
model_import_error() : model_import_error("Error while importing model") {}
model_import_error(char const* msg) : msg_{msg} {}
virtual char const* what() const noexcept { return msg_; }
model_import_error(std::string msg) : msg_{msg} {}
virtual char const* what() const noexcept { return msg_.c_str(); }

private:
char const* msg_;
std::string msg_;
};

/**
Expand Down
8 changes: 8 additions & 0 deletions cpp/include/nvforest/forest_model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
#include <nvforest/detail/raft_proto/handle.hpp>
#include <nvforest/infer_kind.hpp>

#ifdef NVFOREST_ENABLE_GPU
#include <cuda_runtime_api.h>
#endif

Comment thread
coderabbitai[bot] marked this conversation as resolved.
#include <cstddef>
#include <type_traits>
#include <variant>
Expand Down Expand Up @@ -289,7 +293,11 @@ struct forest_model {
int current_device_id;
if (out_mem_type == raft_proto::device_type::gpu ||
in_mem_type == raft_proto::device_type::gpu) {
#ifdef NVFOREST_ENABLE_GPU
raft_proto::cuda_check(cudaGetDevice(&current_device_id));
#else
throw raft_proto::gpu_unsupported("Tried to use GPU memory in CPU-only build");
#endif
} else {
current_device_id = -1;
}
Expand Down
27 changes: 19 additions & 8 deletions cpp/include/nvforest/treelite_importer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <treelite/tree.h>

#include <cmath>
#include <string>
#include <variant>

namespace nvforest {
Expand Down Expand Up @@ -351,24 +352,34 @@ struct treelite_importer {
*processed_tl_model.get(), align_bytes, use_double_precision, dev_type, device, stream);
}

ASSERT(tl_model.num_target == 1, "nvForest does not support multi-target model");
if (tl_model.num_target != 1) {
throw model_import_error("nvForest does not support multi-target model");
}
// Check tree annotation (assignment)
if (tl_model.task_type == treelite::TaskType::kMultiClf) {
if (tl_model.num_class.Empty() || tl_model.num_class[0] <= 0) {
throw model_import_error("MultiClf model must define positive num_class");
}
// Must be either vector leaf or grove-per-class
if (tl_model.leaf_vector_shape[1] > 1) { // vector-leaf
ASSERT(tl_model.leaf_vector_shape[1] == int(tl_model.num_class[0]),
"Vector leaf must be equal to num_class = %d",
tl_model.num_class[0]);
if (tl_model.leaf_vector_shape[1] != int(tl_model.num_class[0])) {
throw model_import_error("Vector leaf must be equal to num_class = " +
std::to_string(tl_model.num_class[0]));
}
auto tree_count = num_trees(tl_model);
for (decltype(tree_count) tree_id = 0; tree_id < tree_count; ++tree_id) {
ASSERT(tl_model.class_id[tree_id] == -1, "Tree %d has invalid class assignment", tree_id);
if (tl_model.class_id[tree_id] != -1) {
throw model_import_error("Tree " + std::to_string(tree_id) +
" has invalid class assignment");
}
}
} else { // grove-per-class
auto tree_count = num_trees(tl_model);
for (decltype(tree_count) tree_id = 0; tree_id < tree_count; ++tree_id) {
ASSERT(tl_model.class_id[tree_id] == int(tree_id % tl_model.num_class[0]),
"Tree %d has invalid class assignment",
tree_id);
if (tl_model.class_id[tree_id] != int(tree_id % tl_model.num_class[0])) {
throw model_import_error("Tree " + std::to_string(tree_id) +
Comment thread
coderabbitai[bot] marked this conversation as resolved.
" has invalid class assignment");
}
}
}
}
Expand Down
15 changes: 13 additions & 2 deletions cpp/tests/treelite_importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

#include <nvforest/detail/raft_proto/device_type.hpp>
#include <nvforest/detail/raft_proto/handle.hpp>
#include <nvforest/postproc_ops.hpp>
#include <nvforest/tree_layout.hpp>
#include <nvforest/treelite_importer.hpp>
Expand Down Expand Up @@ -337,7 +338,12 @@ TEST(TreeliteImporter, DegenerateTree)
auto fil_model = import_from_treelite_model(*tl_model, tree_layout::breadth_first);
ASSERT_FALSE(fil_model.has_vector_leaves());

auto handle = raft::handle_t{};
#ifdef NVFOREST_ENABLE_GPU
auto raft_handle = raft::handle_t{};
auto handle = raft_proto::handle_t{raft_handle};
#else
auto handle = raft_proto::handle_t{};
#endif
auto X = std::vector<double>{0.0};
auto preds = std::vector<double>(1, 0.0);
auto expected_preds = std::vector<double>{1.0};
Expand All @@ -358,7 +364,12 @@ TEST(TreeliteImporter, DegenerateTreeWithVectorLeaf)
auto fil_model = import_from_treelite_model(*tl_model, tree_layout::breadth_first);
ASSERT_TRUE(fil_model.has_vector_leaves());

auto handle = raft::handle_t{};
#ifdef NVFOREST_ENABLE_GPU
auto raft_handle = raft::handle_t{};
auto handle = raft_proto::handle_t{raft_handle};
#else
auto handle = raft_proto::handle_t{};
#endif
auto X = std::vector<double>{0.0};
auto preds = std::vector<double>(2, 0.0);
auto expected_preds = std::vector<double>{0.5, 0.5};
Expand Down
Loading