Skip to content

Commit 1e89f62

Browse files
authored
Fix Memory cleanup issues for GPU and CPU index (#44)
Signed-off-by: Rajvaibhav Rahane <[email protected]>
1 parent 4f2732e commit 1e89f62

File tree

5 files changed

+69
-21
lines changed

5 files changed

+69
-21
lines changed

remote_vector_index_builder/core/common/models/index_builder/faiss/faiss_gpu_index_cagra_builder.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,14 +195,15 @@ def build_gpu_index(
195195
raise Exception(f"Failed to create faiss GPU index config: {str(e)}") from e
196196

197197
try:
198-
gpu_resources = faiss.StandardGpuResources()
199-
200198
# Configure the distance metric
201199
metric = configure_metric(space_type)
202200

203201
# Create GPU CAGRA index with specified configuration
204202
faiss_gpu_index = faiss.GpuIndexCagra(
205-
gpu_resources, dataset_dimension, metric, faiss_gpu_index_config
203+
faiss.StandardGpuResources(),
204+
dataset_dimension,
205+
metric,
206+
faiss_gpu_index_config,
206207
)
207208

208209
# Create ID mapping layer to preserve document IDs
@@ -218,7 +219,9 @@ def build_gpu_index(
218219
except Exception as e:
219220
if faiss_gpu_index is not None:
220221
faiss_gpu_index.thisown = True
221-
del faiss_gpu_index
222+
faiss_gpu_index.__swig_destroy__(faiss_gpu_index)
222223
if faiss_index_id_map is not None:
223-
del faiss_index_id_map
224+
faiss_index_id_map.thisown = True
225+
faiss_index_id_map.own_fields = False
226+
faiss_index_id_map.__swig_destroy__(faiss_index_id_map)
224227
raise Exception(f"Failed to create faiss GPU index: {str(e)}") from e

remote_vector_index_builder/core/common/models/index_builder/faiss/faiss_index_hnsw_cagra_builder.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,17 +78,21 @@ def convert_gpu_to_cpu_index(
7878
cpu_index.base_level_only = self.base_level_only
7979

8080
# Copy GPU index to CPU index
81-
gpu_index = faiss_gpu_build_index_output.gpu_index
82-
gpu_index.copyTo(cpu_index)
81+
faiss_gpu_build_index_output.gpu_index.copyTo(cpu_index)
82+
83+
# Remove reference of GPU Index from the IndexIDMap
84+
faiss_gpu_build_index_output.index_id_map.index = None
8385

8486
# Update the ID map index with the CPU index
8587
index_id_map = faiss_gpu_build_index_output.index_id_map
88+
89+
# Remove reference of the IndexIDMap from the GPU Build Index Output before cleanup
8690
faiss_gpu_build_index_output.index_id_map = None
91+
8792
index_id_map.index = cpu_index
8893

8994
# Free memory taken by GPU Index
90-
del gpu_index
91-
del faiss_gpu_build_index_output
95+
faiss_gpu_build_index_output.cleanup()
9296

9397
return FaissCpuBuildIndexOutput(
9498
cpu_index=cpu_index, index_id_map=index_id_map
@@ -121,7 +125,7 @@ def write_cpu_index(
121125
cpu_build_index_output.index_id_map, cpu_index_output_file_path
122126
)
123127
# Free memory taken by CPU Index
124-
del cpu_build_index_output
128+
cpu_build_index_output.cleanup()
125129
except IOError as io_error:
126130
raise Exception(
127131
f"Failed to write index to file {cpu_index_output_file_path}: {str(io_error)}"

remote_vector_index_builder/core/common/models/index_builder/response/faiss_cpu_build_index_output.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,40 @@ class FaissCpuBuildIndexOutput:
2121
index_id_map: faiss.IndexIDMap
2222

2323
def __del__(self):
24+
self.cleanup()
25+
26+
def cleanup(self):
2427
"""
25-
Destructor to clean up FAISS resources.
28+
Clean up method for FAISS resources.
2629
Ensures memory is properly freed when the object is destroyed.
2730
2831
The method handles cleanup by
2932
explicitly deleting the internal Index and Vectors data
3033
"""
3134
try:
35+
# Cleanup the CPU Index explicitly after it is succussfully persisted to disc
36+
# OR if the orchestrator fails after creating the CPU Index
37+
# and before the CPU Index is persisted to disc
3238
if self.cpu_index:
3339
# Delete the internal Index
34-
del self.cpu_index
40+
self.cpu_index.thisown = True
41+
42+
cpu_index = self.cpu_index
43+
self.cpu_index = None
44+
cpu_index.__swig_destroy__(cpu_index)
45+
46+
# Delete the IndexIDMap not containing any underlying Index
47+
# This block runs after the CPU Index is cleaned up
48+
# if the CPU Index is succussfully persisted to disc
49+
# OR if the orchestrator fails after creating the CPU Index
50+
# and before the CPU Index is persisted to disc
3551
if self.index_id_map:
3652
# Delete the vectors, vector ids stored as part of the IndexIDMap
37-
self.index_id_map.own_fields = True
38-
del self.index_id_map
53+
self.index_id_map.own_fields = False
54+
self.index_id_map.thisown = True
55+
56+
index_id_map = self.index_id_map
57+
self.index_id_map = None
58+
index_id_map.__swig_destroy__(index_id_map)
3959
except Exception as e:
4060
print(f"Error during cleanup of FaissCpuBuildIndexOutput: {e}")

remote_vector_index_builder/core/common/models/index_builder/response/faiss_gpu_build_index_output.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,42 @@ class FaissGpuBuildIndexOutput:
2020
index_id_map: faiss.IndexIDMap
2121

2222
def __del__(self):
23+
self.cleanup()
24+
25+
def cleanup(self):
2326
"""
24-
Destructor to clean up FAISS resources.
27+
Clean up method for FAISS resources.
2528
Ensures memory is properly freed when the object is destroyed.
2629
2730
The method handles cleanup by
2831
explicitly deleting the internal Index and Vectors data
2932
"""
3033
try:
34+
# Cleanup the GPU Index explicitly if the CPU Index was successfully created
35+
# OR if the orchestrator fails after creating a GPU Index and
36+
# before the CPU Index is created, and replaced GPU Index in the IndexIDMap
3137
if self.gpu_index:
3238
# Delete the internal Index
33-
del self.gpu_index
39+
40+
if self.index_id_map:
41+
self.index_id_map.index = None
42+
self.gpu_index.thisown = True
43+
44+
gpu_index = self.gpu_index
45+
self.gpu_index = None
46+
gpu_index.__swig_destroy__(gpu_index)
47+
48+
# A reference to IndexIDMap is maintained until the underlying GPU Index is replaced by a CPU Index
49+
# This block runs if the orchestrator fails before the successful replacement
3450
if self.index_id_map:
35-
self.index_id_map.index = None
3651
# Delete the vectors, vector ids stored as part of the IndexIDMap
37-
self.index_id_map.own_fields = True
38-
del self.index_id_map
52+
self.index_id_map.thisown = True
53+
self.index_id_map.own_fields = False
54+
55+
self.index_id_map.index = None
56+
57+
index_id_map = self.index_id_map
58+
self.index_id_map = None
59+
index_id_map.__swig_destroy__(index_id_map)
3960
except Exception as e:
4061
print(f"Error during cleanup of FaissGpuBuildIndexOutput: {e}")

remote_vector_index_builder/core/index_builder/faiss/faiss_index_build_service.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,14 @@ def build_index(
107107
# Clean up GPU Index Response if orchestrator failed after GPU Index Creation
108108
if faiss_gpu_build_index_output is not None:
109109
try:
110-
del faiss_gpu_build_index_output
110+
faiss_gpu_build_index_output.cleanup()
111111
except Exception as e:
112112
print(f"Warning: Failed to clean up GPU index response: {str(e)}")
113113

114114
# Clean up CPU Index Response if orchestrator failed after CPU Index Creation
115115
if faiss_cpu_build_index_output is not None:
116116
try:
117-
del faiss_cpu_build_index_output
117+
faiss_cpu_build_index_output.cleanup()
118118
except Exception as e:
119119
print(f"Warning: Failed to clean up CPU index response: {str(e)}")
120120
raise Exception(

0 commit comments

Comments
 (0)