Faiss.NET.Interop
1.0.0-preview.8
dotnet add package Faiss.NET.Interop --version 1.0.0-preview.8
NuGet\Install-Package Faiss.NET.Interop -Version 1.0.0-preview.8
<PackageReference Include="Faiss.NET.Interop" Version="1.0.0-preview.8" />
<PackageVersion Include="Faiss.NET.Interop" Version="1.0.0-preview.8" />
<PackageReference Include="Faiss.NET.Interop" />
paket add Faiss.NET.Interop --version 1.0.0-preview.8
#r "nuget: Faiss.NET.Interop, 1.0.0-preview.8"
#:package Faiss.NET.Interop@1.0.0-preview.8
#addin nuget:?package=Faiss.NET.Interop&version=1.0.0-preview.8&prerelease
#tool nuget:?package=Faiss.NET.Interop&version=1.0.0-preview.8&prerelease
Faiss.NET
High-performance C#/.NET bindings for Faiss.
Faiss.NET gives you near-native performance with clean, idiomatic C# wrappers while staying as close as possible to the original Faiss API.
- Faiss v1.15.1
- .NET 9.0
BETA: This library is considered stable and ready for initial usage testwise.
Development Roadmap
About 90% is done. I am reworking the class hierarchy to make the api as elegant as possible. This includes preventing most of the footguns there are with faiss, including making the compiler enforce all the rules.
12.08.2026: The groundwork is almost finished. I still need to polish some rough edges like the IDSelector (internal stuff) but most of this library is basically complete, stable and usable.
As soon as the PRs noted below get merged and I fix some minor stuff I will publish preview release 6. I am really happy with the progress and looking forward.
01.09.2026: Feature set is basically complete (except the remaining features which are based on faiss PRs below). I am reworking the test suite.
02.11:2026: Library is stable. Waiting for faiss upstream to merge the missing PRs noted below.
- Adding bindings for
distances_c.h - Improving class hierarchy and generic constraints design to further prevent footguns (~ September 2026)
- Adding more tests (~ October 2026)
- Adding example project (~ December 2026)
- Adding remaining functionality to IndexShards, IndexReplicas, IndexRefineFlat and GPU indexes (Waiting for faiss PRs to merge: #5516, #5514, #5513, #5512, #5511) (~ December 2026)
- v1.0 Release π (~ December 2026)
Features
- Thin, "bare-metal" bindings with minimal overhead
- Extensions on top bindings for excellent DX
- Cross-platform support (Windows, Linux, macOS all x64 & arm64)
- Strongly-typed wrappers + generic factory for all Faiss indexes
- GPU acceleration (CUDA & ROCm)
- Human written (no AI slop)
- It just worksβ’
Table of Contents
Installation
Prerequisites
Windows
winget install --id Microsoft.VCRedist.2015+.x64 --silent
Linux
Make sure you are on a system with glibc version 2.38 or greater.
sudo apt-get install -y libopenblas0 libgomp1
macOS
brew install libomp
NuGet Package
Pick either the CPU only or the CPU + GPU support NuGet, do not mix on the same platform, it would cause undefined behavior.
CPU only
dotnet add package Faiss.NET.Native
CPU+GPU
CUDA
dotnet add package Faiss.NET.Gpu.Native.Cuda # Linux only
dotnet add package Faiss.NET.Native.Windows
dotnet add package Faiss.NET.Native.MacOS
ROCm
dotnet add package Faiss.NET.Gpu.Native.Rocm # Linux x64 only
dotnet add package Faiss.NET.Native.Windows
dotnet add package Faiss.NET.Native.MacOS
Usage
Quick start
using Faiss.Cpu.Extensions;
using Faiss.Cpu.Indexes.Flat;
using var index = new IndexFlatL2(dimensions: 4);
index.Add([1, 2, 3, 4]);
using var result = index.Search([1, 2, 3, 4], k: 1);
var label = result.Labels[0]; // 0
var distance = result.Distances[0]; // 0f
RAG Embeddings
using Faiss.Cpu.Extensions;
using Faiss.Cpu.Indexes.Approximate;
using Faiss.Cpu.Indexes.Mapped;
using Faiss.Cpu.Search;
using Faiss.Cpu.Search.Parameters;
using Faiss.Cpu.Selectors;
using Faiss.Models;
var index = new IndexHNSW(dimensions: 4, metricType: MetricType.InnerProduct); // No `using`: ownership is handed to mappedIndex below
using var mappedIndex = new IndexIDMap<IndexHNSW>(index, takeOwnership: true); // `index` is closed from here on; use mappedIndex.SubIndex
mappedIndex.Add([new[] { 1f, 2f, 3f, 4f }, new[] { 2f, 3f, 4f, 1f }, new[] { 3f, 4f, 1f, 2f }, new[] { 4f, 1f, 2f, 3f }], [4, 3, 2, 1]);
var queryNeighborsCount = 2; // K
var searchResult = mappedIndex.SearchWithParams(new [] {1f, 1f, 2f, 3f}, queryNeighborsCount, new SearchParameters(new IDSelectorRange(2, 4)));
QueryResults queryResult = searchResult.GetQueryResults(0);
for (int i = 0; i < searchResult.K; i++)
{
float distance = queryResult.Distances[i];
long label = queryResult.Labels[i];
Console.WriteLine($"Rank {i}: label={label}, dist={distance}");
}
Serialization/Deserialization
using Faiss.Cpu.Extensions;
using Faiss.Cpu.Indexes.Binary;
using Faiss.Cpu.Serializer;
using var index = new IndexBinaryFlat(4);
index.Add([1, 2, 3, 4]);
BinaryIndexSerializer.Write(index, "my_index.faiss");
using var readIndex = BinaryIndexDeserializer.Read<IndexBinaryFlat>( "my_index.faiss");
var reconstructed = readIndex.Reconstruct(0); // [1, 2, 3, 4]
Approximate indexes with Factory
The factory string mirrors the upstream Faiss API: HNSW32, IVF256,Flat, PQ8x12, and so on.
using Faiss.Cpu.Extensions;
using Faiss.Cpu.Factory;
using Faiss.Cpu.Indexes.Factory;
using var index = IndexFactory.Create<GenericFloatIndex>("HNSW32", dimensions: 128);
index.Add([1f, 2f, 3f, 4f]);
using var result = index.Search([1f, 2f, 3f, 4f], k: 1);
Ownership
Composite indexes (IndexIDMap, IndexIVFFlat, IndexPreTransform, IndexShards, β¦) wrap other indexes. Who frees the wrapped index is decided once, at construction:
takeOwnership: true(orownQuantizer,ownSubIndex, β¦): the composite frees it. Your original reference is closed immediately; use the composite's view instead (e.g.IndexIDMap.SubIndex), which is valid until the composite is disposed.takeOwnership: false: you keep ownership and keep using your object. The composite keeps it alive while it needs it, so disposing yours early is safe.- Clone, deserialization and the factory return composites that own their parts; exposed parts are views.
using var map = new IndexIDMap<IndexFlatL2>(new IndexFlatL2(dimensions: 4), takeOwnership: true);
map.Add([new[] { 1f, 2f, 3f, 4f }], [42]);
long count = map.SubIndex.TotalCount; // 1
Misuse fails with ObjectDisposedException instead of corrupting memory; nothing needs to be disposed in a particular order.
GPU acceleration
using Faiss.Cpu.Extensions;
using Faiss.Cpu.Indexes.Flat;
using Faiss.Gpu;
using Faiss.Gpu.Resources;
using var cpuIndex = new IndexFlatIP(dimensions: 4);
cpuIndex.Add([1f, 2f, 3f, 4f]);
using var gpuResources = new GpuResourcesProvider();
using var gpuIndex = GpuIndexProvider.TransferToGpu(gpuResources, cpuIndex, deviceId: 0); // GpuIndexFlatIP
using var searchResult = gpuIndex.Search([1f, 2f, 3f, 4f], k: 1);
var results = searchResult.Length; // 1
using var transferredCpuIndex = GpuIndexProvider.TransferToCpu(gpuIndex); // IndexFlatIP
results = searchResult.Length; // 1
Supported Platforms
| Platform | x64 | arm64 |
|---|---|---|
| Windows | β | β |
| Linux | β | β |
| macOS | β | β |
GPU Acceleration
| Backend | Platform | x64 | arm64 |
|---|---|---|---|
| CUDA | Linux | β | β |
| ROCm | Linux | β | β |
Supported CUDA GPUs
| Compute Capability | Architecture | Example GPUs |
|---|---|---|
| 75 | Turing | RTX 20-series, Tesla T4 |
| 80 | Ampere | A100 |
| 86 | Ampere | RTX 30-series, A40, A10, A16, A30 |
| 89 | Ada Lovelace | RTX 40-series, L40, L40S, L4 |
| 90 | Hopper | H100, H200 |
| 100 | Blackwell | B200, GB200, B300 (10.3) |
| 120 | Blackwell | RTX 50-series, DGX Spark (GB10, 12.1) |
Supported ROCm GPUs
| GFX Architecture | Architecture | Example GPUs |
|---|---|---|
| gfx90a | CDNA2 | AMD Instinct MI210, MI250, MI250X |
| gfx942 | CDNA3 | AMD Instinct MI300A, MI300X, MI325X |
| gfx950 | CDNA4 | AMD Instinct MI355X, MI350 series |
| gfx1030 / 1031 / 1032 | RDNA2 | Radeon RX 6600β6900 series |
| gfx1100 / 1101 / 1102 | RDNA3 | Radeon RX 7700β7900 series |
| gfx1200 / 1201 | RDNA4 | Radeon RX 9060 series and RX 9070 series |
<details> <summary>
Background
</summary>
I was unhappy with the existing .NET bindings for faiss out there including crashes in prod caused by those which took a while to find out what the cause was (segmentation fault by bad pointer usage through the .NET faiss library). Seeing other bindings being completely out-of-date and way too old I decided to do it myself.
My goal is to have amazing DX including guardrails that make it really hard to do something wrong, all enforced by the compiler.
Made with β₯οΈ
</details>
License
See the LICENSE file for details.
Faiss.NET is not affiliated with Meta or the original Faiss project.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- No dependencies.
NuGet packages (5)
Showing the top 5 NuGet packages that depend on Faiss.NET.Interop:
| Package | Downloads |
|---|---|
|
Faiss.NET.Native.Linux
Native Linux (x64 and arm64) binaries for Faiss.NET. |
|
|
Faiss.NET.Native.MacOS
Native MacOS (x64 and arm64) binaries for Faiss.NET. |
|
|
Faiss.NET.Native
Cross-platform native binaries meta-package for Faiss.NET. Includes Linux, Windows, and macOS runtimes. |
|
|
Faiss.NET.Native.Windows
Native Windows (x64 and arm64) binaries for Faiss.NET. |
|
|
Faiss.NET.Gpu
GPU extension for Faiss.NET. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0-preview.8 | 0 | 11/3/2026 |
| 1.0.0-preview.7 | 49 | 11/2/2026 |
| 1.0.0-preview.6 | 90 | 10/29/2026 |
| 1.0.0-preview.5 | 275 | 5/18/2026 |
| 1.0.0-preview.4 | 236 | 4/30/2026 |
| 1.0.0-preview.3 | 104 | 3/31/2026 |
| 1.0.0-preview.2 | 99 | 3/30/2026 |