From ddad139b863c6570e6f476d6ab9df3a9a3b3052f Mon Sep 17 00:00:00 2001 From: Rahul Rampure Date: Tue, 4 Nov 2025 19:27:10 +0530 Subject: [PATCH 1/6] add basic GPU bindings --- faiss.go | 1 - faiss_avx2.go | 9 +++++++ faiss_generic.go | 9 +++++++ gpu.go | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 faiss_avx2.go create mode 100644 faiss_generic.go create mode 100644 gpu.go diff --git a/faiss.go b/faiss.go index a7087e7..26275a4 100644 --- a/faiss.go +++ b/faiss.go @@ -5,7 +5,6 @@ package faiss /* -#cgo LDFLAGS: -lfaiss_c #include #include diff --git a/faiss_avx2.go b/faiss_avx2.go new file mode 100644 index 0000000..05824df --- /dev/null +++ b/faiss_avx2.go @@ -0,0 +1,9 @@ +//go:build avx2 +// +build avx2 + +package faiss + +/* +#cgo LDFLAGS: -lfaiss_c_avx2 +*/ +import "C" diff --git a/faiss_generic.go b/faiss_generic.go new file mode 100644 index 0000000..2605ab3 --- /dev/null +++ b/faiss_generic.go @@ -0,0 +1,9 @@ +//go:build !avx2 +// +build !avx2 + +package faiss + +/* +#cgo LDFLAGS: -lfaiss_c +*/ +import "C" diff --git a/gpu.go b/gpu.go new file mode 100644 index 0000000..9323a6c --- /dev/null +++ b/gpu.go @@ -0,0 +1,69 @@ +package faiss + +/* +#include +#include +#include +#include +*/ +import "C" +import ( + "errors" +) + +// NumGPUs returns the number of available GPU devices. +func NumGPUs() (int, error) { + var rv C.int + c := C.faiss_get_num_gpus(&rv) + if c != 0 { + return 0, errors.New("error getting number of GPUs") + } + return int(rv), nil +} + +// SyncDevice synchronizes the CPU against the specified device. +// This forces the CPU to wait until all preceding commands on +// the specified GPU device have completed. +func SyncDevice(device int) error { + c := C.faiss_gpu_sync_device(C.int(device)) + if c != 0 { + return errors.New("error synchronizing device") + } + return nil +} + +// TransferToGPU transfers a CPU index to the specified GPU device. +func TransferToGPU(index Index, device int) (Index, error) { + var gpuResource *C.FaissStandardGpuResources + c := C.faiss_StandardGpuResources_new(&gpuResource) + if c != 0 { + return nil, errors.New("error initializing GPU resources") + } + var gpuIndex *C.FaissGpuIndex + c = C.faiss_index_cpu_to_gpu( + gpuResource, + C.int(device), + index.cPtr(), + &gpuIndex, + ) + if c != 0 { + return nil, errors.New("error transferring index to GPU") + } + return &faissIndex{ + idx: gpuIndex, + }, nil +} + +func TransferToCPU(index Index, device int) (Index, error) { + var cpuIndex *C.FaissIndex + c := C.faiss_index_gpu_to_cpu( + index.cPtr(), + &cpuIndex, + ) + if c != 0 { + return nil, errors.New("error transferring index to CPU") + } + return &faissIndex{ + idx: cpuIndex, + }, nil +} From 9ff4c943c0ffa1ae77a14527432faead7109e659 Mon Sep 17 00:00:00 2001 From: Rahul Rampure Date: Wed, 5 Nov 2025 22:57:12 +0530 Subject: [PATCH 2/6] refactor --- gpu.go | 65 ++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/gpu.go b/gpu.go index 9323a6c..3d0a4d1 100644 --- a/gpu.go +++ b/gpu.go @@ -9,6 +9,8 @@ package faiss import "C" import ( "errors" + "fmt" + "unsafe" ) // NumGPUs returns the number of available GPU devices. @@ -32,38 +34,61 @@ func SyncDevice(device int) error { return nil } +type GPUIndexImpl struct { + Index + gpuResource *C.FaissStandardGpuResources +} + +func (g *GPUIndexImpl) Close() { + if g.Index != nil { + g.Index.Close() + } + if g.gpuResource != nil { + C.faiss_StandardGpuResources_free(g.gpuResource) + g.gpuResource = nil + } +} + // TransferToGPU transfers a CPU index to the specified GPU device. -func TransferToGPU(index Index, device int) (Index, error) { +// Returns the GPU index, a cleanup function, and any error encountered. +func TransferToGPU(index *IndexImpl, device int) (*GPUIndexImpl, error) { var gpuResource *C.FaissStandardGpuResources - c := C.faiss_StandardGpuResources_new(&gpuResource) - if c != 0 { - return nil, errors.New("error initializing GPU resources") + if code := C.faiss_StandardGpuResources_new(&gpuResource); code != 0 { + return nil, fmt.Errorf("failed to initialize GPU resources: error code %d", code) } - var gpuIndex *C.FaissGpuIndex - c = C.faiss_index_cpu_to_gpu( + + var gpuIdx *C.FaissGpuIndex + code := C.faiss_index_cpu_to_gpu( gpuResource, C.int(device), index.cPtr(), - &gpuIndex, + &gpuIdx, ) - if c != 0 { - return nil, errors.New("error transferring index to GPU") + if code != 0 { + C.faiss_StandardGpuResources_free(gpuResource) + return nil, fmt.Errorf("failed to transfer index to GPU device %d: error code %d", device, code) } - return &faissIndex{ - idx: gpuIndex, + + idx := &faissIndex{ + idx: (*C.FaissIndex)(unsafe.Pointer(gpuIdx)), + } + + return &GPUIndexImpl{ + Index: &IndexImpl{idx}, + gpuResource: gpuResource, }, nil } -func TransferToCPU(index Index, device int) (Index, error) { +// TransferToCPU transfers a GPU index back to CPU memory. +func TransferToCPU(gpuIndex *GPUIndexImpl) (*IndexImpl, error) { var cpuIndex *C.FaissIndex - c := C.faiss_index_gpu_to_cpu( - index.cPtr(), - &cpuIndex, - ) - if c != 0 { - return nil, errors.New("error transferring index to CPU") + if code := C.faiss_index_gpu_to_cpu(gpuIndex.cPtr(), &cpuIndex); code != 0 { + return nil, fmt.Errorf("failed to transfer index to CPU: error code %d", code) } - return &faissIndex{ + + idx := &faissIndex{ idx: cpuIndex, - }, nil + } + + return &IndexImpl{idx}, nil } From 03a9151407c67a26cf9e6bbbeabce1419d2813bc Mon Sep 17 00:00:00 2001 From: Rahul Rampure Date: Thu, 6 Nov 2025 12:53:18 +0530 Subject: [PATCH 3/6] Free memory API --- gpu.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gpu.go b/gpu.go index 3d0a4d1..d6d0fed 100644 --- a/gpu.go +++ b/gpu.go @@ -34,6 +34,15 @@ func SyncDevice(device int) error { return nil } +func FreeMemory(device int) (uint64, error) { + var freeBytes C.size_t + c := C.faiss_get_free_memory(C.int(device), &freeBytes) + if c != 0 { + return 0, fmt.Errorf("error getting free memory for device %d", device) + } + return uint64(freeBytes), nil +} + type GPUIndexImpl struct { Index gpuResource *C.FaissStandardGpuResources From 7f7445ef121b165d23777fb18c19b70401a20e3d Mon Sep 17 00:00:00 2001 From: Rahul Rampure Date: Thu, 6 Nov 2025 19:12:49 +0530 Subject: [PATCH 4/6] remove unused method --- gpu.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/gpu.go b/gpu.go index d6d0fed..fcfa053 100644 --- a/gpu.go +++ b/gpu.go @@ -23,17 +23,6 @@ func NumGPUs() (int, error) { return int(rv), nil } -// SyncDevice synchronizes the CPU against the specified device. -// This forces the CPU to wait until all preceding commands on -// the specified GPU device have completed. -func SyncDevice(device int) error { - c := C.faiss_gpu_sync_device(C.int(device)) - if c != 0 { - return errors.New("error synchronizing device") - } - return nil -} - func FreeMemory(device int) (uint64, error) { var freeBytes C.size_t c := C.faiss_get_free_memory(C.int(device), &freeBytes) From e7c7650acb5533d68a1da063c8c5b1908166130e Mon Sep 17 00:00:00 2001 From: Rahul Rampure Date: Thu, 13 Nov 2025 19:11:52 +0530 Subject: [PATCH 5/6] revert --- faiss.go | 1 + faiss_avx2.go | 9 --------- faiss_generic.go | 9 --------- 3 files changed, 1 insertion(+), 18 deletions(-) delete mode 100644 faiss_avx2.go delete mode 100644 faiss_generic.go diff --git a/faiss.go b/faiss.go index 26275a4..a7087e7 100644 --- a/faiss.go +++ b/faiss.go @@ -5,6 +5,7 @@ package faiss /* +#cgo LDFLAGS: -lfaiss_c #include #include diff --git a/faiss_avx2.go b/faiss_avx2.go deleted file mode 100644 index 05824df..0000000 --- a/faiss_avx2.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build avx2 -// +build avx2 - -package faiss - -/* -#cgo LDFLAGS: -lfaiss_c_avx2 -*/ -import "C" diff --git a/faiss_generic.go b/faiss_generic.go deleted file mode 100644 index 2605ab3..0000000 --- a/faiss_generic.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build !avx2 -// +build !avx2 - -package faiss - -/* -#cgo LDFLAGS: -lfaiss_c -*/ -import "C" From 684e60c1a818b961c07135aaed7624be15b815d3 Mon Sep 17 00:00:00 2001 From: Rahul Rampure Date: Thu, 13 Nov 2025 19:15:12 +0530 Subject: [PATCH 6/6] fix bindings --- gpu.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/gpu.go b/gpu.go index fcfa053..3981d83 100644 --- a/gpu.go +++ b/gpu.go @@ -38,8 +38,12 @@ type GPUIndexImpl struct { } func (g *GPUIndexImpl) Close() { + if g == nil { + return + } if g.Index != nil { g.Index.Close() + g.Index = nil } if g.gpuResource != nil { C.faiss_StandardGpuResources_free(g.gpuResource) @@ -48,8 +52,10 @@ func (g *GPUIndexImpl) Close() { } // TransferToGPU transfers a CPU index to the specified GPU device. -// Returns the GPU index, a cleanup function, and any error encountered. func TransferToGPU(index *IndexImpl, device int) (*GPUIndexImpl, error) { + if index == nil { + return nil, errors.New("index cannot be nil") + } var gpuResource *C.FaissStandardGpuResources if code := C.faiss_StandardGpuResources_new(&gpuResource); code != 0 { return nil, fmt.Errorf("failed to initialize GPU resources: error code %d", code) @@ -79,6 +85,9 @@ func TransferToGPU(index *IndexImpl, device int) (*GPUIndexImpl, error) { // TransferToCPU transfers a GPU index back to CPU memory. func TransferToCPU(gpuIndex *GPUIndexImpl) (*IndexImpl, error) { + if gpuIndex == nil { + return nil, errors.New("gpuIndex cannot be nil") + } var cpuIndex *C.FaissIndex if code := C.faiss_index_gpu_to_cpu(gpuIndex.cPtr(), &cpuIndex); code != 0 { return nil, fmt.Errorf("failed to transfer index to CPU: error code %d", code)