Commit 57bf474
Fix int/size_t signedness mismatches in HNSW add (#5116)
Summary:
Pull Request resolved: #5116
The `hnsw_add_vertices()` function in both `IndexHNSW.cpp` and `IndexBinaryHNSW.cpp` accepts `size_t n0` and `size_t n` parameters, but the loop variables and counters inside were declared as `int`. This caused signed/unsigned comparison mismatches and implicit narrowing conversions. This diff fixes all such mismatches with six targeted changes:
1. **Loop variables `i0`, `i1`, `j` changed from `int` to `size_t`; OpenMP loop variable `i` changed from `int` to `int64_t`**: These variables derive from `n` (which is `size_t`) and are used as indices into `std::vector<int> order(n)`. Using `int` produced signed/unsigned comparison warnings in loop conditions (`j < i1`, `i < i1`) and risked undefined behavior via signed integer overflow for indices above `INT_MAX` (~2.1B). The outer variables use `size_t` to match the function parameter types. The OpenMP `for` loop variable uses `int64_t` because MSVC enforces that OpenMP loop counters must have signed integral types (`error C3016`), and `size_t` (unsigned) violates this requirement. `int64_t` is signed, 64-bit, and compatible with both the `size_t` loop bounds and MSVC OpenMP.
2. **`int n0 = ntotal` changed to `size_t n0 = ntotal` in `add()` methods**: `ntotal` is `idx_t` (`int64_t`), and `n0` is passed directly to `hnsw_add_vertices(..., size_t n0, ...)`. The `int` declaration caused an implicit 64-to-32-bit narrowing conversion at the call site.
3. **`printf` format specifiers changed from `%d` to `%zu`**: Required to match the new `size_t` types. Using `%d` with `size_t` arguments is undefined behavior per the C standard.
4. **`prev_display` sentinel logic refactored**: The old pattern used `int prev_display = verbose ? 0 : -1` with a `prev_display >= 0` guard, encoding a boolean in a signed integer sentinel. This was incompatible with the `size_t` migration (cannot represent -1). Replaced with an explicit `bool do_display` flag and `size_t prev_display = 0`, which is semantically identical and clearer.
5. **`std::make_unique<IndexBinaryFlat>(d_).release()` simplified to `new IndexBinaryFlat(d_)`**: The `make_unique().release()` pattern creates a `unique_ptr` only to immediately release ownership, which is equivalent to `new` but with unnecessary intermediate allocation tracking. Since `storage` is a raw pointer with `own_fields = true` ownership semantics (deleted in the destructor), plain `new` matches the established Faiss ownership pattern used throughout the codebase.
6. **`static_cast<int>` added at `rand_int()` call sites**: The `int`-to-`size_t` migration changed `i1 - j` from `int` to `size_t`, introducing a new `clang-diagnostic-shorten-64-to-32` warning when passed to `rand_int(int max)`. The explicit cast documents the intentional narrowing. The value is safe: `i1 - j` represents the remaining elements in a single HNSW level bucket, bounded well below `INT_MAX`.
All changes are mechanical. No functional changes.
Reviewed By: junjieqi
Differential Revision: D101353511
fbshipit-source-id: a4a44b6a5436a77d97d47389db52b8721b2f97c41 parent 582246b commit 57bf474
2 files changed
Lines changed: 27 additions & 23 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
99 | 99 | | |
100 | 100 | | |
101 | 101 | | |
102 | | - | |
| 102 | + | |
103 | 103 | | |
104 | 104 | | |
105 | 105 | | |
106 | 106 | | |
107 | | - | |
| 107 | + | |
108 | 108 | | |
109 | 109 | | |
110 | | - | |
| 110 | + | |
111 | 111 | | |
112 | 112 | | |
113 | 113 | | |
114 | | - | |
115 | | - | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
116 | 118 | | |
117 | 119 | | |
118 | 120 | | |
| |||
121 | 123 | | |
122 | 124 | | |
123 | 125 | | |
124 | | - | |
125 | | - | |
| 126 | + | |
| 127 | + | |
126 | 128 | | |
127 | 129 | | |
128 | | - | |
| 130 | + | |
129 | 131 | | |
130 | 132 | | |
131 | 133 | | |
| |||
138 | 140 | | |
139 | 141 | | |
140 | 142 | | |
141 | | - | |
| 143 | + | |
142 | 144 | | |
143 | | - | |
| 145 | + | |
144 | 146 | | |
145 | 147 | | |
146 | 148 | | |
| |||
176 | 178 | | |
177 | 179 | | |
178 | 180 | | |
179 | | - | |
| 181 | + | |
180 | 182 | | |
181 | 183 | | |
182 | 184 | | |
| |||
257 | 259 | | |
258 | 260 | | |
259 | 261 | | |
260 | | - | |
| 262 | + | |
261 | 263 | | |
262 | 264 | | |
263 | 265 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
122 | 122 | | |
123 | 123 | | |
124 | 124 | | |
125 | | - | |
| 125 | + | |
126 | 126 | | |
127 | 127 | | |
128 | 128 | | |
129 | 129 | | |
130 | | - | |
| 130 | + | |
131 | 131 | | |
132 | 132 | | |
133 | | - | |
| 133 | + | |
134 | 134 | | |
135 | 135 | | |
136 | 136 | | |
137 | | - | |
138 | | - | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
139 | 141 | | |
140 | 142 | | |
141 | 143 | | |
| |||
146 | 148 | | |
147 | 149 | | |
148 | 150 | | |
149 | | - | |
150 | | - | |
| 151 | + | |
| 152 | + | |
151 | 153 | | |
152 | 154 | | |
153 | 155 | | |
154 | 156 | | |
155 | 157 | | |
156 | 158 | | |
157 | | - | |
| 159 | + | |
158 | 160 | | |
159 | 161 | | |
160 | 162 | | |
| |||
171 | 173 | | |
172 | 174 | | |
173 | 175 | | |
174 | | - | |
| 176 | + | |
175 | 177 | | |
176 | | - | |
| 178 | + | |
177 | 179 | | |
178 | 180 | | |
179 | 181 | | |
| |||
349 | 351 | | |
350 | 352 | | |
351 | 353 | | |
352 | | - | |
| 354 | + | |
353 | 355 | | |
354 | 356 | | |
355 | 357 | | |
| |||
0 commit comments