-
Notifications
You must be signed in to change notification settings - Fork 184
Switch to public RAFT numpy_serialize APIs #2038
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -9,6 +9,7 @@ | |||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| #include <raft/core/error.hpp> | ||||||||||||||||||||||||
| #include <raft/core/mdspan_types.hpp> | ||||||||||||||||||||||||
| #include <raft/core/numpy_serializer.hpp> | ||||||||||||||||||||||||
| #include <raft/core/resources.hpp> | ||||||||||||||||||||||||
| #include <raft/core/serialize.hpp> | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
@@ -875,7 +876,7 @@ extern "C" cuvsError_t cuvsCagraDeserialize(cuvsResources_t res, | |||||||||||||||||||||||
| if (!is) { RAFT_FAIL("Cannot open file %s", filename); } | ||||||||||||||||||||||||
| char dtype_string[4]; | ||||||||||||||||||||||||
| is.read(dtype_string, 4); | ||||||||||||||||||||||||
| auto dtype = raft::detail::numpy_serializer::parse_descr(std::string(dtype_string, 4)); | ||||||||||||||||||||||||
| auto dtype = raft::numpy_serializer::parse_descr(std::string(dtype_string, 4)); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
Comment on lines
877
to
880
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guard the dtype prefix read before Line 878 reads 4 bytes but does not validate read length before parsing on Line 879. Corrupt/truncated files can produce invalid dtype decoding. Proposed fix- char dtype_string[4];
- is.read(dtype_string, 4);
- auto dtype = raft::numpy_serializer::parse_descr(std::string(dtype_string, 4));
+ char dtype_string[4] = {};
+ is.read(dtype_string, sizeof(dtype_string));
+ RAFT_EXPECTS(is.gcount() == static_cast<std::streamsize>(sizeof(dtype_string)),
+ "Failed to read dtype header from %s",
+ filename);
+ auto dtype =
+ raft::numpy_serializer::parse_descr(std::string(dtype_string, sizeof(dtype_string)));📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||
| index->dtype.bits = dtype.itemsize * 8; | ||||||||||||||||||||||||
| if (dtype.kind == 'f' && dtype.itemsize == 4) { | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
|
|
||
| /* | ||
| * SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION. | ||
| * SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION. | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
|
|
@@ -9,6 +9,7 @@ | |
|
|
||
| #include <raft/core/error.hpp> | ||
| #include <raft/core/mdspan_types.hpp> | ||
| #include <raft/core/numpy_serializer.hpp> | ||
| #include <raft/core/resources.hpp> | ||
| #include <raft/core/serialize.hpp> | ||
| #include <raft/util/cudart_utils.hpp> | ||
|
|
@@ -301,7 +302,7 @@ extern "C" cuvsError_t cuvsIvfFlatDeserialize(cuvsResources_t res, | |
| if (!is) { RAFT_FAIL("Cannot open file %s", filename); } | ||
| char dtype_string[4]; | ||
| is.read(dtype_string, 4); | ||
| auto dtype = raft::detail::numpy_serializer::parse_descr(std::string(dtype_string, 4)); | ||
| auto dtype = raft::numpy_serializer::parse_descr(std::string(dtype_string, 4)); | ||
|
|
||
|
Comment on lines
303
to
306
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fail early on short dtype-header reads. Line 304 reads the dtype prefix without checking byte count before parsing on Line 305. This should be validated to handle malformed files safely. Proposed fix- char dtype_string[4];
- is.read(dtype_string, 4);
- auto dtype = raft::numpy_serializer::parse_descr(std::string(dtype_string, 4));
+ char dtype_string[4] = {};
+ is.read(dtype_string, sizeof(dtype_string));
+ RAFT_EXPECTS(is.gcount() == static_cast<std::streamsize>(sizeof(dtype_string)),
+ "Failed to read dtype header from %s",
+ filename);
+ auto dtype =
+ raft::numpy_serializer::parse_descr(std::string(dtype_string, sizeof(dtype_string)));🤖 Prompt for AI Agents |
||
| index->dtype.bits = dtype.itemsize * 8; | ||
| if (dtype.kind == 'f' && dtype.itemsize == 4) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| /* | ||
| * SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION. | ||
| * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION. | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
|
|
@@ -10,6 +10,7 @@ | |
| #include <cuvs/neighbors/common.hpp> | ||
| #include <dlpack/dlpack.h> | ||
| #include <raft/core/error.hpp> | ||
| #include <raft/core/numpy_serializer.hpp> | ||
| #include <raft/core/serialize.hpp> | ||
|
|
||
| #include "../core/exceptions.hpp" | ||
|
|
@@ -401,7 +402,7 @@ extern "C" cuvsError_t cuvsMultiGpuCagraDeserialize(cuvsResources_t res, | |
| if (!is) { RAFT_FAIL("Cannot open file %s", filename); } | ||
| char dtype_string[4]; | ||
| is.read(dtype_string, 4); | ||
| auto dtype = raft::detail::numpy_serializer::parse_descr(std::string(dtype_string, 4)); | ||
| auto dtype = raft::numpy_serializer::parse_descr(std::string(dtype_string, 4)); | ||
| is.close(); | ||
|
Comment on lines
403
to
406
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validate dtype header reads before parsing. On Line 404 and Line 435, the 4-byte read is not validated. Truncated files can pass partial/garbage bytes into Proposed fix- char dtype_string[4];
- is.read(dtype_string, 4);
- auto dtype = raft::numpy_serializer::parse_descr(std::string(dtype_string, 4));
+ char dtype_string[4] = {};
+ is.read(dtype_string, sizeof(dtype_string));
+ RAFT_EXPECTS(is.gcount() == static_cast<std::streamsize>(sizeof(dtype_string)),
+ "Failed to read dtype header from %s",
+ filename);
+ auto dtype =
+ raft::numpy_serializer::parse_descr(std::string(dtype_string, sizeof(dtype_string)));
@@
- char dtype_string[4];
- is.read(dtype_string, 4);
- auto dtype = raft::numpy_serializer::parse_descr(std::string(dtype_string, 4));
+ char dtype_string[4] = {};
+ is.read(dtype_string, sizeof(dtype_string));
+ RAFT_EXPECTS(is.gcount() == static_cast<std::streamsize>(sizeof(dtype_string)),
+ "Failed to read dtype header from %s",
+ filename);
+ auto dtype =
+ raft::numpy_serializer::parse_descr(std::string(dtype_string, sizeof(dtype_string)));Also applies to: 434-437 🤖 Prompt for AI Agents |
||
|
|
||
| index->dtype.bits = dtype.itemsize * 8; | ||
|
|
@@ -432,7 +433,7 @@ extern "C" cuvsError_t cuvsMultiGpuCagraDistribute(cuvsResources_t res, | |
| if (!is) { RAFT_FAIL("Cannot open file %s", filename); } | ||
| char dtype_string[4]; | ||
| is.read(dtype_string, 4); | ||
| auto dtype = raft::detail::numpy_serializer::parse_descr(std::string(dtype_string, 4)); | ||
| auto dtype = raft::numpy_serializer::parse_descr(std::string(dtype_string, 4)); | ||
| is.close(); | ||
|
|
||
| index->dtype.bits = dtype.itemsize * 8; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| /* | ||
| * SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION. | ||
| * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION. | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
|
|
@@ -10,6 +10,7 @@ | |
| #include <cuvs/neighbors/ivf_flat.hpp> | ||
| #include <dlpack/dlpack.h> | ||
| #include <raft/core/error.hpp> | ||
| #include <raft/core/numpy_serializer.hpp> | ||
| #include <raft/core/serialize.hpp> | ||
|
|
||
| #include "../core/exceptions.hpp" | ||
|
|
@@ -398,7 +399,7 @@ extern "C" cuvsError_t cuvsMultiGpuIvfFlatDeserialize(cuvsResources_t res, | |
| if (!is) { RAFT_FAIL("Cannot open file %s", filename); } | ||
| char dtype_string[4]; | ||
| is.read(dtype_string, 4); | ||
| auto dtype = raft::detail::numpy_serializer::parse_descr(std::string(dtype_string, 4)); | ||
| auto dtype = raft::numpy_serializer::parse_descr(std::string(dtype_string, 4)); | ||
| is.close(); | ||
|
Comment on lines
400
to
403
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validate header read length before calling Both blocks parse the dtype descriptor immediately after 💡 Proposed fix (apply in both deserialize and distribute)- char dtype_string[4];
- is.read(dtype_string, 4);
- auto dtype = raft::numpy_serializer::parse_descr(std::string(dtype_string, 4));
+ char dtype_string[4]{};
+ if (!is.read(dtype_string, sizeof(dtype_string))) {
+ RAFT_FAIL("Invalid or truncated index header in file %s", filename);
+ }
+ auto dtype =
+ raft::numpy_serializer::parse_descr(std::string(dtype_string, sizeof(dtype_string)));Also applies to: 431-434 🤖 Prompt for AI Agents |
||
|
|
||
| index->dtype.bits = dtype.itemsize * 8; | ||
|
|
@@ -429,7 +430,7 @@ extern "C" cuvsError_t cuvsMultiGpuIvfFlatDistribute(cuvsResources_t res, | |
| if (!is) { RAFT_FAIL("Cannot open file %s", filename); } | ||
| char dtype_string[4]; | ||
| is.read(dtype_string, 4); | ||
| auto dtype = raft::detail::numpy_serializer::parse_descr(std::string(dtype_string, 4)); | ||
| auto dtype = raft::numpy_serializer::parse_descr(std::string(dtype_string, 4)); | ||
| is.close(); | ||
|
|
||
| index->dtype.bits = dtype.itemsize * 8; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| /* | ||
| * SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION. | ||
| * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION. | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
|
|
@@ -10,6 +10,7 @@ | |
| #include <cuvs/neighbors/ivf_pq.hpp> | ||
| #include <dlpack/dlpack.h> | ||
| #include <raft/core/error.hpp> | ||
| #include <raft/core/numpy_serializer.hpp> | ||
| #include <raft/core/serialize.hpp> | ||
|
|
||
| #include "../core/exceptions.hpp" | ||
|
|
@@ -390,7 +391,7 @@ extern "C" cuvsError_t cuvsMultiGpuIvfPqDeserialize(cuvsResources_t res, | |
| if (!is) { RAFT_FAIL("Cannot open file %s", filename); } | ||
| char dtype_string[4]; | ||
| is.read(dtype_string, 4); | ||
| auto dtype = raft::detail::numpy_serializer::parse_descr(std::string(dtype_string, 4)); | ||
| auto dtype = raft::numpy_serializer::parse_descr(std::string(dtype_string, 4)); | ||
| is.close(); | ||
|
Comment on lines
392
to
395
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validate Line 393 does not verify that 4 bytes were actually read. A short read can propagate invalid bytes into Proposed fix- char dtype_string[4];
- is.read(dtype_string, 4);
- auto dtype = raft::numpy_serializer::parse_descr(std::string(dtype_string, 4));
+ char dtype_string[4] = {};
+ is.read(dtype_string, sizeof(dtype_string));
+ RAFT_EXPECTS(is.gcount() == static_cast<std::streamsize>(sizeof(dtype_string)),
+ "Failed to read dtype header from %s",
+ filename);
+ auto dtype =
+ raft::numpy_serializer::parse_descr(std::string(dtype_string, sizeof(dtype_string)));🤖 Prompt for AI Agents |
||
|
|
||
| index->dtype.bits = dtype.itemsize * 8; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,13 @@ | ||
| # ============================================================================= | ||
| # cmake-format: off | ||
| # SPDX-FileCopyrightText: Copyright (c) 2023-2025, NVIDIA CORPORATION. | ||
| # SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # cmake-format: on | ||
|
|
||
| # Use RAPIDS_VERSION_MAJOR_MINOR from rapids_config.cmake | ||
| set(RAFT_VERSION "${RAPIDS_VERSION_MAJOR_MINOR}") | ||
| set(RAFT_FORK "rapidsai") | ||
| set(RAFT_PINNED_TAG "${rapids-cmake-checkout-tag}") | ||
| set(RAFT_FORK "julianmi") | ||
| set(RAFT_PINNED_TAG "expose-public-npy-helpers") | ||
|
Comment on lines
+9
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "Checking upstream dependency status (rapidsai/raft PR `#3003`)..."
curl -s https://api.github.com/repos/rapidsai/raft/pulls/3003 \
| jq '{state, merged, merge_commit_sha, head_repo: .head.repo.full_name, head_ref: .head.ref, base_ref: .base.ref}'
echo
echo "Checking whether expose-public-npy-helpers exists in official and fork repos..."
git ls-remote --heads https://github.com/rapidsai/raft.git expose-public-npy-helpers || true
git ls-remote --tags https://github.com/rapidsai/raft.git expose-public-npy-helpers || true
git ls-remote --heads https://github.com/julianmi/raft.git expose-public-npy-helpers || true
git ls-remote --tags https://github.com/julianmi/raft.git expose-public-npy-helpers || trueRepository: rapidsai/cuvs Length of output: 407 🏁 Script executed: cat -n cpp/cmake/thirdparty/get_raft.cmakeRepository: rapidsai/cuvs Length of output: 3417 🏁 Script executed: # Search for any comments or related discussions about this fork usage
rg "expose-public-npy-helpers|RAFT_FORK|julianmi" --type cmake --type markdown -C 3Repository: rapidsai/cuvs Length of output: 9046 🏁 Script executed: # Check git history for when this fork was introduced and any commit messages
git log --oneline -20 -- cpp/cmake/thirdparty/get_raft.cmakeRepository: rapidsai/cuvs Length of output: 109 🏁 Script executed: # Search for any open or recent PRs that might explain the fork usage
git log --all --oneline --grep="raft\|RAFT" | head -30Repository: rapidsai/cuvs Length of output: 1759 Avoid hard-pinning production builds to a personal RAFT fork/ref. This introduces a supply-chain risk for CI and releases if that fork/ref is rewritten or removed. The Suggested hardening-set(RAFT_FORK "julianmi")
-set(RAFT_PINNED_TAG "expose-public-npy-helpers")
+set(RAFT_FORK "rapidsai")
+set(RAFT_PINNED_TAG "${rapids-cmake-checkout-tag}")
+
+set(CUVS_RAFT_FORK_OVERRIDE "" CACHE STRING "Optional RAFT fork override for temporary testing")
+set(CUVS_RAFT_TAG_OVERRIDE "" CACHE STRING "Optional RAFT tag/branch override for temporary testing")
+
+if(CUVS_RAFT_FORK_OVERRIDE)
+ set(RAFT_FORK "${CUVS_RAFT_FORK_OVERRIDE}")
+endif()
+if(CUVS_RAFT_TAG_OVERRIDE)
+ set(RAFT_PINNED_TAG "${CUVS_RAFT_TAG_OVERRIDE}")
+endif()🤖 Prompt for AI Agents |
||
|
|
||
| function(find_and_configure_raft) | ||
| set(oneValueArgs VERSION FORK PINNED_TAG BUILD_STATIC_DEPS ENABLE_NVTX ENABLE_MNMG_DEPENDENCIES CLONE_ON_PIN) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guard against truncated header reads before parsing dtype.
Line 243 reads 4 bytes but never checks success. On short/corrupt files, Line 244 may parse uninitialized bytes.
💡 Proposed fix
🤖 Prompt for AI Agents