├── .gitattributes ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── .gitmodules ├── AnnService.users.props ├── AnnService ├── Aggregator.vcxproj ├── Aggregator.vcxproj.filters ├── BalancedDataPartition.vcxproj ├── BalancedDataPartition.vcxproj.filters ├── CMakeLists.txt ├── Client.vcxproj ├── Client.vcxproj.filters ├── CoreLibrary.vcxproj ├── CoreLibrary.vcxproj.filters ├── GPUCoreLibrary.vcxproj ├── GPUCoreLibrary.vcxproj.filters ├── GPUIndexBuilder.vcxproj ├── GPUIndexBuilder.vcxproj.filters ├── GPUSSDServing.vcxproj ├── GPUSSDServing.vcxproj.filters ├── IndexBuilder.vcxproj ├── IndexBuilder.vcxproj.filters ├── IndexSearcher.vcxproj ├── IndexSearcher.vcxproj.filters ├── Quantizer.vcxproj ├── Quantizer.vcxproj.filters ├── SSDServing.vcxproj ├── SSDServing.vcxproj.filters ├── Server.vcxproj ├── Server.vcxproj.filters ├── SocketLib.vcxproj ├── SocketLib.vcxproj.filters ├── inc │ ├── Aggregator │ │ ├── AggregatorContext.h │ │ ├── AggregatorExecutionContext.h │ │ ├── AggregatorService.h │ │ └── AggregatorSettings.h │ ├── Client │ │ ├── ClientWrapper.h │ │ └── Options.h │ ├── Core │ │ ├── BKT │ │ │ ├── Index.h │ │ │ └── ParameterDefinitionList.h │ │ ├── Common.h │ │ ├── Common │ │ │ ├── BKTree.h │ │ │ ├── CommonUtils.h │ │ │ ├── Dataset.h │ │ │ ├── DistanceUtils.h │ │ │ ├── FineGrainedLock.h │ │ │ ├── Heap.h │ │ │ ├── IQuantizer.h │ │ │ ├── InstructionUtils.h │ │ │ ├── KDTree.h │ │ │ ├── KNearestNeighborhoodGraph.h │ │ │ ├── Labelset.h │ │ │ ├── NeighborhoodGraph.h │ │ │ ├── OPQQuantizer.h │ │ │ ├── PQQuantizer.h │ │ │ ├── QueryResultSet.h │ │ │ ├── RelativeNeighborhoodGraph.h │ │ │ ├── SIMDUtils.h │ │ │ ├── TruthSet.h │ │ │ ├── WorkSpace.h │ │ │ ├── WorkSpacePool.h │ │ │ └── cuda │ │ │ │ ├── Distance.hxx │ │ │ │ ├── GPUKNNDistance.hxx │ │ │ │ ├── GPUQuantizer.hxx │ │ │ │ ├── KNN.hxx │ │ │ │ ├── Kmeans.hxx │ │ │ │ ├── PerfTestGPU.hxx │ │ │ │ ├── Refine.hxx │ │ │ │ ├── TPtree.hxx │ │ │ │ ├── TailNeighbors.hxx │ │ │ │ ├── ThreadHeap.hxx │ │ │ │ ├── log.hxx │ │ │ │ └── params.h │ │ ├── CommonDataStructure.h │ │ ├── DefinitionList.h │ │ ├── KDT │ │ │ ├── Index.h │ │ │ └── ParameterDefinitionList.h │ │ ├── MetadataSet.h │ │ ├── MultiIndexScan.h │ │ ├── ResultIterator.h │ │ ├── SPANN │ │ │ ├── Compressor.h │ │ │ ├── ExtraFullGraphSearcher.h │ │ │ ├── IExtraSearcher.h │ │ │ ├── Index.h │ │ │ ├── Options.h │ │ │ ├── ParameterDefinitionList.h │ │ │ └── SPANNResultIterator.h │ │ ├── SearchQuery.h │ │ ├── SearchResult.h │ │ ├── VectorIndex.h │ │ └── VectorSet.h │ ├── Helper │ │ ├── ArgumentsParser.h │ │ ├── AsyncFileReader.h │ │ ├── Base64Encode.h │ │ ├── CommonHelper.h │ │ ├── Concurrent.h │ │ ├── ConcurrentSet.h │ │ ├── DiskIO.h │ │ ├── DynamicNeighbors.h │ │ ├── LockFree.h │ │ ├── Logging.h │ │ ├── SimpleIniReader.h │ │ ├── StringConvert.h │ │ ├── ThreadPool.h │ │ ├── VectorSetReader.h │ │ └── VectorSetReaders │ │ │ ├── DefaultReader.h │ │ │ ├── MemoryReader.h │ │ │ ├── TxtReader.h │ │ │ └── XvecReader.h │ ├── Quantizer │ │ └── Training.h │ ├── SSDServing │ │ ├── SSDIndex.h │ │ ├── SelectHead.h │ │ ├── Utils.h │ │ └── main.h │ ├── Server │ │ ├── QueryParser.h │ │ ├── SearchExecutionContext.h │ │ ├── SearchExecutor.h │ │ ├── SearchService.h │ │ ├── ServiceContext.h │ │ └── ServiceSettings.h │ └── Socket │ │ ├── Client.h │ │ ├── Common.h │ │ ├── Connection.h │ │ ├── ConnectionManager.h │ │ ├── Packet.h │ │ ├── RemoteSearchQuery.h │ │ ├── ResourceManager.h │ │ ├── Server.h │ │ └── SimpleSerialization.h ├── packages.config └── src │ ├── Aggregator │ ├── AggregatorContext.cpp │ ├── AggregatorExecutionContext.cpp │ ├── AggregatorService.cpp │ ├── AggregatorSettings.cpp │ └── main.cpp │ ├── BalancedDataPartition │ └── main.cpp │ ├── Client │ ├── ClientWrapper.cpp │ ├── Options.cpp │ └── main.cpp │ ├── Core │ ├── BKT │ │ └── BKTIndex.cpp │ ├── Common │ │ ├── CommonUtils.cpp │ │ ├── DistanceUtils.cpp │ │ ├── IQuantizer.cpp │ │ ├── InstructionUtils.cpp │ │ ├── Kernel.cu │ │ ├── NeighborhoodGraph.cpp │ │ ├── SIMDUtils.cpp │ │ └── TruthSet.cpp │ ├── KDT │ │ └── KDTIndex.cpp │ ├── MetadataSet.cpp │ ├── MultiIndexScan.cpp │ ├── ResultIterator.cpp │ ├── SPANN │ │ └── SPANNIndex.cpp │ ├── SPANNResultIterator.cpp │ ├── VectorIndex.cpp │ └── VectorSet.cpp │ ├── Helper │ ├── ArgumentsParser.cpp │ ├── AsyncFileReader.cpp │ ├── Base64Encode.cpp │ ├── CommonHelper.cpp │ ├── Concurrent.cpp │ ├── DynamicNeighbors.cpp │ ├── SimpleIniReader.cpp │ ├── VectorSetReader.cpp │ └── VectorSetReaders │ │ ├── DefaultReader.cpp │ │ ├── TxtReader.cpp │ │ └── XvecReader.cpp │ ├── IndexBuilder │ └── main.cpp │ ├── IndexSearcher │ └── main.cpp │ ├── Quantizer │ └── main.cpp │ ├── SSDServing │ └── main.cpp │ ├── Server │ ├── QueryParser.cpp │ ├── SearchExecutionContext.cpp │ ├── SearchExecutor.cpp │ ├── SearchService.cpp │ ├── ServiceContext.cpp │ ├── ServiceSettings.cpp │ └── main.cpp │ └── Socket │ ├── Client.cpp │ ├── Common.cpp │ ├── Connection.cpp │ ├── ConnectionManager.cpp │ ├── Packet.cpp │ ├── RemoteSearchQuery.cpp │ └── Server.cpp ├── CMakeLists.txt ├── Dockerfile ├── Dockerfile.cuda ├── GPUSupport └── CMakeLists.txt ├── LICENSE ├── MANIFEST.in ├── README.md ├── SECURITY.md ├── SPTAG.WinRT.nuspec ├── SPTAG.nuspec ├── SPTAG.sdf ├── SPTAG.sln ├── SPTAG.targets ├── Test ├── CMakeLists.txt ├── Test.vcxproj ├── Test.vcxproj.filters ├── WinRTTest │ ├── WinRTTest.cpp │ ├── WinRTTest.vcxproj │ ├── WinRTTest.vcxproj.filters │ └── packages.config ├── cuda │ ├── buildssd_test.cu │ ├── common.hxx │ ├── cuda_tests.cpp │ ├── distance_tests.cu │ ├── gpu_pq_perf.cu │ ├── knn_tests.cu │ ├── pq_perf.cpp │ └── tptree_tests.cu ├── inc │ └── Test.h ├── packages.config └── src │ ├── AlgoTest.cpp │ ├── Base64HelperTest.cpp │ ├── CommonHelperTest.cpp │ ├── ConcurrentTest.cpp │ ├── DistanceTest.cpp │ ├── FilterTest.cpp │ ├── IniReaderTest.cpp │ ├── IterativeScanTest.cpp │ ├── MultiIndexExperiment.cpp │ ├── MultiIndexScanTest.cpp │ ├── PerfTest.cpp │ ├── ReconstructIndexSimilarityTest.cpp │ ├── SIMDTest.cpp │ ├── SSDServingTest.cpp │ ├── StringConvertTest.cpp │ ├── main.cpp │ └── make_gist_sptag.py ├── Tools ├── OPQ │ ├── OPQ_gpu_train_infer.py │ └── README.md └── nni-auto-tune │ ├── README.md │ ├── config.yml │ ├── config_aml.yml │ ├── dataset.py │ ├── main.py │ ├── model.py │ ├── picture │ ├── fashion-mnist-784-euclidean.png │ ├── glove-100-angular.png │ ├── glove-25-angular.png │ ├── nytimes-256-angular.png │ └── sift-128-euclidean.png │ ├── plot.py │ ├── preprocessing.py │ ├── runner.py │ ├── search_space.json │ └── search_space_small.json ├── Wrappers ├── CLRCore.vcxproj ├── CLRCore.vcxproj.filters ├── CMakeLists.txt ├── CsharpClient.vcxproj ├── CsharpClient.vcxproj.filters ├── CsharpCore.vcxproj ├── CsharpCore.vcxproj.filters ├── JavaClient.vcxproj ├── JavaClient.vcxproj.filters ├── JavaCore.vcxproj ├── JavaCore.vcxproj.filters ├── PythonClient.vcxproj ├── PythonClient.vcxproj.filters ├── PythonCore.vcxproj ├── PythonCore.vcxproj.filters ├── WinRT │ ├── AnnIndex.cpp │ ├── AnnIndex.h │ ├── AnnIndex.idl │ ├── PropertySheet.props │ ├── SPTAG.WinRT.targets │ ├── SPTAG.WinRT.vcxproj │ ├── SPTAG.def │ ├── packages.config │ ├── pch.cpp │ └── pch.h ├── inc │ ├── CLRCoreInterface.h │ ├── ClientInterface.h │ ├── CoreInterface.h │ ├── CsharpClient.i │ ├── CsharpCommon.i │ ├── CsharpCore.i │ ├── JavaClient.i │ ├── JavaCommon.i │ ├── JavaCore.i │ ├── ManagedObject.h │ ├── PythonClient.i │ ├── PythonCommon.i │ ├── PythonCore.i │ └── TransferDataType.h ├── packages.config └── src │ ├── AssemblyInfo.cpp │ ├── CLRCoreInterface.cpp │ ├── ClientInterface.cpp │ └── CoreInterface.cpp ├── azure-pipelines.yml ├── datasets └── SPACEV1B │ ├── LICENSE │ ├── README.md │ ├── query.bin │ ├── query_log.bin │ ├── truth.bin │ └── vectors.bin │ ├── vectors_1.bin │ ├── vectors_10.bin │ ├── vectors_11.bin │ ├── vectors_12.bin │ ├── vectors_13.bin │ ├── vectors_14.bin │ ├── vectors_15.bin │ ├── vectors_16.bin │ ├── vectors_17.bin │ ├── vectors_18.bin │ ├── vectors_19.bin │ ├── vectors_2.bin │ ├── vectors_20.bin │ ├── vectors_21.bin │ ├── vectors_22.bin │ ├── vectors_23.bin │ ├── vectors_24.bin │ ├── vectors_25.bin │ ├── vectors_26.bin │ ├── vectors_27.bin │ ├── vectors_28.bin │ ├── vectors_29.bin │ ├── vectors_3.bin │ ├── vectors_30.bin │ ├── vectors_31.bin │ ├── vectors_32.bin │ ├── vectors_33.bin │ ├── vectors_4.bin │ ├── vectors_5.bin │ ├── vectors_6.bin │ ├── vectors_7.bin │ ├── vectors_8.bin │ └── vectors_9.bin ├── docs ├── GettingStart.md ├── LinuxInstallation.md ├── Parameters.md ├── Tutorial.ipynb ├── WindowsInstallation.md ├── examples │ ├── QuickstartGuide.ipynb │ ├── features_extractor.py │ └── requirements.txt └── img │ ├── sptag.png │ ├── swigpath.PNG │ └── visualstudio.png ├── setup.py └── setup.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | *.bin filter=lfs diff=lfs merge=lfs -text 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Click on '....' 14 | 3. Scroll down to '....' 15 | 4. See error 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Screenshots** 21 | If applicable, add screenshots to help explain your problem. 22 | 23 | **Desktop (please complete the following information):** 24 | - OS: [e.g. iOS] 25 | - Browser [e.g. chrome, safari] 26 | - Version [e.g. 22] 27 | 28 | **Smartphone (please complete the following information):** 29 | - Device: [e.g. iPhone6] 30 | - OS: [e.g. iOS8.1] 31 | - Browser [e.g. stock browser, safari] 32 | - Version [e.g. 22] 33 | 34 | **Additional context** 35 | Add any other context about the problem here. 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ThirdParty/zstd"] 2 | path = ThirdParty/zstd 3 | url = https://github.com/facebook/zstd 4 | branch = release 5 | -------------------------------------------------------------------------------- /AnnService.users.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $(SystemVersionDef) %(AdditionalOptions) 8 | 9 | 10 | 11 | 12 | $(SolutionDir)\$(Platform)\$(Configuration)\ 13 | $(SolutionDir)\$(Platform)\$(Configuration)\ 14 | 15 | 16 | 3.9 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /AnnService/Aggregator.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Header Files 16 | 17 | 18 | Header Files 19 | 20 | 21 | Header Files 22 | 23 | 24 | Header Files 25 | 26 | 27 | 28 | 29 | Source Files 30 | 31 | 32 | Source Files 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | Source Files 42 | 43 | 44 | Source Files 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /AnnService/BalancedDataPartition.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Source Files 23 | 24 | 25 | -------------------------------------------------------------------------------- /AnnService/Client.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | Source Files 19 | 20 | 21 | Source Files 22 | 23 | 24 | 25 | 26 | Header Files 27 | 28 | 29 | Header Files 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /AnnService/GPUIndexBuilder.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {c260e4c4-ec44-4d50-941f-078454da2a89} 6 | 7 | 8 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 9 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 10 | 11 | 12 | 13 | 14 | Source Files 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /AnnService/GPUSSDServing.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {5bf17d80-3c16-4aef-918c-6994296bb320} 6 | 7 | 8 | {edefc9a5-628e-4695-aaad-22951d646b18} 9 | 10 | 11 | 12 | 13 | Header Files 14 | 15 | 16 | Header Files 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /AnnService/IndexBuilder.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /AnnService/IndexSearcher.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /AnnService/Quantizer.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /AnnService/SSDServing.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {d5aba8fd-7ec7-458a-b728-ae5eaea04e43} 6 | 7 | 8 | {6835b7a3-6818-4a89-89c0-fc6527dbf613} 9 | 10 | 11 | 12 | 13 | Header Files 14 | 15 | 16 | Header Files 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /AnnService/Server.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Header Files 16 | 17 | 18 | Header Files 19 | 20 | 21 | Header Files 22 | 23 | 24 | Header Files 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | Source Files 42 | 43 | 44 | Source Files 45 | 46 | 47 | Source Files 48 | 49 | 50 | Source Files 51 | 52 | 53 | Source Files 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /AnnService/SocketLib.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Header Files 16 | 17 | 18 | Header Files 19 | 20 | 21 | Header Files 22 | 23 | 24 | Header Files 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | 43 | 44 | Source Files 45 | 46 | 47 | Source Files 48 | 49 | 50 | Source Files 51 | 52 | 53 | Source Files 54 | 55 | 56 | Source Files 57 | 58 | 59 | Source Files 60 | 61 | 62 | Source Files 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /AnnService/inc/Aggregator/AggregatorContext.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_AGGREGATOR_AGGREGATORCONTEXT_H_ 5 | #define _SPTAG_AGGREGATOR_AGGREGATORCONTEXT_H_ 6 | 7 | #include "inc/Socket/Common.h" 8 | #include "inc/Core/VectorSet.h" 9 | #include "AggregatorSettings.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace SPTAG 16 | { 17 | namespace Aggregator 18 | { 19 | 20 | enum RemoteMachineStatus : uint8_t 21 | { 22 | Disconnected = 0, 23 | 24 | Connecting, 25 | 26 | Connected 27 | }; 28 | 29 | 30 | struct RemoteMachine 31 | { 32 | RemoteMachine(); 33 | 34 | std::string m_address; 35 | 36 | std::string m_port; 37 | 38 | Socket::ConnectionID m_connectionID; 39 | 40 | std::atomic m_status; 41 | }; 42 | 43 | class AggregatorContext 44 | { 45 | public: 46 | AggregatorContext(const std::string& p_filePath); 47 | 48 | ~AggregatorContext(); 49 | 50 | bool IsInitialized() const; 51 | 52 | const std::vector>& GetRemoteServers() const; 53 | 54 | const std::shared_ptr& GetSettings() const; 55 | 56 | const std::shared_ptr& GetCenters() const; 57 | 58 | private: 59 | std::vector> m_remoteServers; 60 | 61 | std::shared_ptr m_centers; 62 | 63 | std::shared_ptr m_settings; 64 | 65 | bool m_initialized; 66 | }; 67 | 68 | } // namespace Aggregator 69 | } // namespace AnnService 70 | 71 | 72 | #endif // _SPTAG_AGGREGATOR_AGGREGATORCONTEXT_H_ 73 | -------------------------------------------------------------------------------- /AnnService/inc/Aggregator/AggregatorExecutionContext.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_AGGREGATOR_AGGREGATOREXECUTIONCONTEXT_H_ 5 | #define _SPTAG_AGGREGATOR_AGGREGATOREXECUTIONCONTEXT_H_ 6 | 7 | #include "inc/Socket/RemoteSearchQuery.h" 8 | #include "inc/Socket/Packet.h" 9 | 10 | #include 11 | #include 12 | 13 | namespace SPTAG 14 | { 15 | namespace Aggregator 16 | { 17 | 18 | typedef std::shared_ptr AggregatorResult; 19 | 20 | class AggregatorExecutionContext 21 | { 22 | public: 23 | AggregatorExecutionContext(std::size_t p_totalServerNumber, 24 | Socket::PacketHeader p_requestHeader); 25 | 26 | ~AggregatorExecutionContext(); 27 | 28 | std::size_t GetServerNumber() const; 29 | 30 | AggregatorResult& GetResult(std::size_t p_num); 31 | 32 | const Socket::PacketHeader& GetRequestHeader() const; 33 | 34 | bool IsCompletedAfterFinsh(std::uint32_t p_finishedCount); 35 | 36 | private: 37 | std::atomic m_unfinishedCount; 38 | 39 | std::vector m_results; 40 | 41 | Socket::PacketHeader m_requestHeader; 42 | 43 | }; 44 | 45 | 46 | 47 | 48 | } // namespace Aggregator 49 | } // namespace AnnService 50 | 51 | 52 | #endif // _SPTAG_AGGREGATOR_AGGREGATOREXECUTIONCONTEXT_H_ 53 | 54 | -------------------------------------------------------------------------------- /AnnService/inc/Aggregator/AggregatorService.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_AGGREGATOR_AGGREGATORSERVICE_H_ 5 | #define _SPTAG_AGGREGATOR_AGGREGATORSERVICE_H_ 6 | 7 | #include "AggregatorContext.h" 8 | #include "AggregatorExecutionContext.h" 9 | #include "inc/Socket/Server.h" 10 | #include "inc/Socket/Client.h" 11 | #include "inc/Socket/ResourceManager.h" 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace SPTAG 21 | { 22 | namespace Aggregator 23 | { 24 | 25 | class AggregatorService 26 | { 27 | public: 28 | AggregatorService(); 29 | 30 | ~AggregatorService(); 31 | 32 | bool Initialize(); 33 | 34 | void Run(); 35 | 36 | private: 37 | 38 | void StartClient(); 39 | 40 | void StartListen(); 41 | 42 | void WaitForShutdown(); 43 | 44 | void ConnectToPendingServers(); 45 | 46 | void AddToPendingServers(std::shared_ptr p_remoteServer); 47 | 48 | void SearchRequestHanlder(Socket::ConnectionID p_localConnectionID, Socket::Packet p_packet); 49 | 50 | void SearchResponseHanlder(Socket::ConnectionID p_localConnectionID, Socket::Packet p_packet); 51 | 52 | void AggregateResults(std::shared_ptr p_exectionContext); 53 | 54 | std::shared_ptr GetContext(); 55 | 56 | private: 57 | typedef std::function AggregatorCallback; 58 | 59 | std::shared_ptr m_aggregatorContext; 60 | 61 | std::shared_ptr m_socketServer; 62 | 63 | std::shared_ptr m_socketClient; 64 | 65 | bool m_initalized; 66 | 67 | std::unique_ptr m_threadPool; 68 | 69 | boost::asio::io_context m_ioContext; 70 | 71 | boost::asio::signal_set m_shutdownSignals; 72 | 73 | std::vector> m_pendingConnectServers; 74 | 75 | std::mutex m_pendingConnectServersMutex; 76 | 77 | boost::asio::deadline_timer m_pendingConnectServersTimer; 78 | 79 | Socket::ResourceManager m_aggregatorCallbackManager; 80 | }; 81 | 82 | 83 | 84 | } // namespace Aggregator 85 | } // namespace AnnService 86 | 87 | 88 | #endif // _SPTAG_AGGREGATOR_AGGREGATORSERVICE_H_ 89 | -------------------------------------------------------------------------------- /AnnService/inc/Aggregator/AggregatorSettings.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_AGGREGATOR_AGGREGATORSETTINGS_H_ 5 | #define _SPTAG_AGGREGATOR_AGGREGATORSETTINGS_H_ 6 | 7 | #include "../Core/Common.h" 8 | 9 | #include 10 | 11 | namespace SPTAG 12 | { 13 | namespace Aggregator 14 | { 15 | 16 | struct AggregatorSettings 17 | { 18 | AggregatorSettings(); 19 | 20 | std::string m_listenAddr; 21 | 22 | std::string m_listenPort; 23 | 24 | std::uint32_t m_searchTimeout; 25 | 26 | SizeType m_threadNum; 27 | 28 | SizeType m_socketThreadNum; 29 | 30 | std::string m_centers; 31 | 32 | VectorValueType m_valueType; 33 | 34 | SizeType m_topK; 35 | 36 | DistCalcMethod m_distMethod; 37 | }; 38 | 39 | 40 | 41 | 42 | } // namespace Aggregator 43 | } // namespace AnnService 44 | 45 | 46 | #endif // _SPTAG_AGGREGATOR_AGGREGATORSETTINGS_H_ 47 | 48 | -------------------------------------------------------------------------------- /AnnService/inc/Client/ClientWrapper.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_CLIENT_CLIENTWRAPPER_H_ 5 | #define _SPTAG_CLIENT_CLIENTWRAPPER_H_ 6 | 7 | #include "inc/Socket/Client.h" 8 | #include "inc/Socket/RemoteSearchQuery.h" 9 | #include "inc/Socket/ResourceManager.h" 10 | #include "Options.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | namespace SPTAG 22 | { 23 | namespace Client 24 | { 25 | 26 | class ClientWrapper 27 | { 28 | public: 29 | typedef std::function Callback; 30 | 31 | ClientWrapper(const ClientOptions& p_options); 32 | 33 | ~ClientWrapper(); 34 | 35 | void SendQueryAsync(const Socket::RemoteQuery& p_query, 36 | Callback p_callback, 37 | const ClientOptions& p_options); 38 | 39 | void WaitAllFinished(); 40 | 41 | bool IsAvailable() const; 42 | 43 | private: 44 | typedef std::pair ConnectionPair; 45 | 46 | Socket::PacketHandlerMapPtr GetHandlerMap(); 47 | 48 | void DecreaseUnfnishedJobCount(); 49 | 50 | const ConnectionPair& GetConnection(); 51 | 52 | void SearchResponseHanlder(Socket::ConnectionID p_localConnectionID, Socket::Packet p_packet); 53 | 54 | void HandleDeadConnection(Socket::ConnectionID p_cid); 55 | 56 | private: 57 | ClientOptions m_options; 58 | 59 | std::unique_ptr m_client; 60 | 61 | std::atomic m_unfinishedJobCount; 62 | 63 | std::atomic_bool m_isWaitingFinish; 64 | 65 | std::condition_variable m_waitingQueue; 66 | 67 | std::mutex m_waitingMutex; 68 | 69 | std::vector m_connections; 70 | 71 | std::atomic m_spinCountOfConnection; 72 | 73 | Socket::ResourceManager m_callbackManager; 74 | }; 75 | 76 | 77 | } // namespace Socket 78 | } // namespace SPTAG 79 | 80 | #endif // _SPTAG_CLIENT_OPTIONS_H_ 81 | -------------------------------------------------------------------------------- /AnnService/inc/Client/Options.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_CLIENT_OPTIONS_H_ 5 | #define _SPTAG_CLIENT_OPTIONS_H_ 6 | 7 | #include "inc/Helper/ArgumentsParser.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace SPTAG 14 | { 15 | namespace Client 16 | { 17 | 18 | class ClientOptions : public Helper::ArgumentsParser 19 | { 20 | public: 21 | ClientOptions(); 22 | 23 | virtual ~ClientOptions(); 24 | 25 | std::string m_serverAddr; 26 | 27 | std::string m_serverPort; 28 | 29 | // in milliseconds. 30 | std::uint32_t m_searchTimeout; 31 | 32 | std::uint32_t m_threadNum; 33 | 34 | std::uint32_t m_socketThreadNum; 35 | 36 | }; 37 | 38 | 39 | } // namespace Socket 40 | } // namespace SPTAG 41 | 42 | #endif // _SPTAG_CLIENT_OPTIONS_H_ 43 | -------------------------------------------------------------------------------- /AnnService/inc/Core/Common/FineGrainedLock.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_COMMON_FINEGRAINEDLOCK_H_ 5 | #define _SPTAG_COMMON_FINEGRAINEDLOCK_H_ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace SPTAG 13 | { 14 | namespace COMMON 15 | { 16 | class FineGrainedLock { 17 | public: 18 | FineGrainedLock() { 19 | m_locks.reset(new std::mutex[PoolSize + 1]); 20 | } 21 | ~FineGrainedLock() {} 22 | 23 | std::mutex& operator[](SizeType idx) { 24 | unsigned index = hash_func((unsigned)idx); 25 | return m_locks[index]; 26 | } 27 | 28 | const std::mutex& operator[](SizeType idx) const { 29 | unsigned index = hash_func((unsigned)idx); 30 | return m_locks[index]; 31 | } 32 | private: 33 | static const int PoolSize = 32767; 34 | std::unique_ptr m_locks; 35 | 36 | inline unsigned hash_func(unsigned idx) const 37 | { 38 | return ((unsigned)(idx * 99991) + _rotl(idx, 2) + 101) & PoolSize; 39 | } 40 | }; 41 | } 42 | } 43 | 44 | #endif // _SPTAG_COMMON_FINEGRAINEDLOCK_H_ -------------------------------------------------------------------------------- /AnnService/inc/Core/Common/IQuantizer.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_COMMON_QUANTIZER_H_ 5 | #define _SPTAG_COMMON_QUANTIZER_H_ 6 | 7 | #include "inc/Core/Common.h" 8 | #include 9 | #include "inc/Core/CommonDataStructure.h" 10 | #include "DistanceUtils.h" 11 | 12 | namespace SPTAG 13 | { 14 | namespace COMMON 15 | { 16 | class IQuantizer 17 | { 18 | public: 19 | virtual float L2Distance(const std::uint8_t* pX, const std::uint8_t* pY) const = 0; 20 | 21 | virtual float CosineDistance(const std::uint8_t* pX, const std::uint8_t* pY) const = 0; 22 | 23 | template 24 | std::function DistanceCalcSelector(SPTAG::DistCalcMethod p_method) const; 25 | 26 | virtual void QuantizeVector(const void* vec, std::uint8_t* vecout, bool ADC = true) const = 0; 27 | 28 | virtual SizeType QuantizeSize() const = 0; 29 | 30 | virtual void ReconstructVector(const std::uint8_t* qvec, void* vecout) const = 0; 31 | 32 | virtual SizeType ReconstructSize() const = 0; 33 | 34 | virtual DimensionType ReconstructDim() const = 0; 35 | 36 | virtual std::uint64_t BufferSize() const = 0; 37 | 38 | virtual ErrorCode SaveQuantizer(std::shared_ptr p_out) const = 0; 39 | 40 | virtual ErrorCode LoadQuantizer(std::shared_ptr p_in) = 0; 41 | 42 | virtual ErrorCode LoadQuantizer(uint8_t* raw_bytes) = 0; 43 | 44 | static std::shared_ptr LoadIQuantizer(std::shared_ptr p_in); 45 | 46 | static std::shared_ptr LoadIQuantizer(SPTAG::ByteArray bytes); 47 | 48 | virtual bool GetEnableADC() const = 0; 49 | 50 | virtual void SetEnableADC(bool enableADC) = 0; 51 | 52 | virtual QuantizerType GetQuantizerType() const = 0; 53 | 54 | virtual VectorValueType GetReconstructType() const = 0; 55 | 56 | virtual DimensionType GetNumSubvectors() const = 0; 57 | 58 | virtual int GetBase() const = 0; 59 | 60 | virtual float* GetL2DistanceTables() = 0; 61 | 62 | template 63 | T* GetCodebooks(); 64 | }; 65 | } 66 | } 67 | 68 | #endif // _SPTAG_COMMON_QUANTIZER_H_ 69 | -------------------------------------------------------------------------------- /AnnService/inc/Core/Common/InstructionUtils.h: -------------------------------------------------------------------------------- 1 | #ifndef _SPTAG_COMMON_INSTRUCTIONUTILS_H_ 2 | #define _SPTAG_COMMON_INSTRUCTIONUTILS_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifndef GPU 10 | 11 | #ifndef _MSC_VER 12 | #include 13 | #include 14 | #include 15 | 16 | void cpuid(int info[4], int InfoType); 17 | 18 | #else 19 | #include 20 | #define cpuid(info, x) __cpuidex(info, x, 0) 21 | #endif 22 | 23 | #endif 24 | 25 | namespace SPTAG { 26 | namespace COMMON { 27 | 28 | class InstructionSet 29 | { 30 | // forward declarations 31 | class InstructionSet_Internal; 32 | 33 | public: 34 | // getters 35 | static bool AVX(void); 36 | static bool SSE(void); 37 | static bool SSE2(void); 38 | static bool AVX2(void); 39 | static bool AVX512(void); 40 | static void PrintInstructionSet(void); 41 | 42 | private: 43 | static const InstructionSet_Internal CPU_Rep; 44 | 45 | class InstructionSet_Internal 46 | { 47 | public: 48 | InstructionSet_Internal(); 49 | bool HW_SSE; 50 | bool HW_SSE2; 51 | bool HW_AVX; 52 | bool HW_AVX2; 53 | bool HW_AVX512; 54 | }; 55 | }; 56 | } 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /AnnService/inc/Core/Common/KNearestNeighborhoodGraph.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_COMMON_KNG_H_ 5 | #define _SPTAG_COMMON_KNG_H_ 6 | 7 | #include "NeighborhoodGraph.h" 8 | 9 | namespace SPTAG 10 | { 11 | namespace COMMON 12 | { 13 | class KNearestNeighborhoodGraph : public NeighborhoodGraph 14 | { 15 | public: 16 | KNearestNeighborhoodGraph() { m_pNeighborhoodGraph.SetName("NNG"); } 17 | 18 | void RebuildNeighbors(VectorIndex* index, const SizeType node, SizeType* nodes, const BasicResult* queryResults, const int numResults) { 19 | DimensionType count = 0; 20 | for (int j = 0; j < numResults && count < m_iNeighborhoodSize; j++) { 21 | const BasicResult& item = queryResults[j]; 22 | if (item.VID < 0) break; 23 | if (item.VID == node) continue; 24 | nodes[count++] = item.VID; 25 | } 26 | for (DimensionType j = count; j < m_iNeighborhoodSize; j++) nodes[j] = -1; 27 | } 28 | 29 | void InsertNeighbors(VectorIndex* index, const SizeType node, SizeType insertNode, float insertDist) 30 | { 31 | std::lock_guard lock(m_dataUpdateLock[node]); 32 | 33 | SizeType* nodes = m_pNeighborhoodGraph[node]; 34 | SizeType tmpNode; 35 | float tmpDist; 36 | for (DimensionType k = 0; k < m_iNeighborhoodSize; k++) 37 | { 38 | tmpNode = nodes[k]; 39 | if (tmpNode < -1) break; 40 | 41 | if (tmpNode < 0 || (tmpDist = index->ComputeDistance(index->GetSample(node), index->GetSample(tmpNode))) > insertDist 42 | || (insertDist == tmpDist && insertNode < tmpNode)) 43 | { 44 | nodes[k] = insertNode; 45 | while (tmpNode >= 0 && ++k < m_iNeighborhoodSize && nodes[k] >= -1) 46 | { 47 | std::swap(tmpNode, nodes[k]); 48 | } 49 | break; 50 | } 51 | } 52 | } 53 | }; 54 | } 55 | } 56 | #endif -------------------------------------------------------------------------------- /AnnService/inc/Core/Common/SIMDUtils.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_COMMON_SIMDUTILS_H_ 5 | #define _SPTAG_COMMON_SIMDUTILS_H_ 6 | 7 | #include 8 | #include 9 | 10 | #include "CommonUtils.h" 11 | #include "InstructionUtils.h" 12 | 13 | namespace SPTAG 14 | { 15 | namespace COMMON 16 | { 17 | template 18 | using SumCalcReturn = void(*)(T*, const T*, DimensionType); 19 | template 20 | inline SumCalcReturn SumCalcSelector(); 21 | 22 | class SIMDUtils 23 | { 24 | public: 25 | template 26 | static void ComputeSum_Naive(T* pX, const T* pY, DimensionType length) 27 | { 28 | const T* pEnd1 = pX + length; 29 | while (pX < pEnd1) { 30 | *pX++ += *pY++; 31 | } 32 | } 33 | 34 | static void ComputeSum_SSE(std::int8_t* pX, const std::int8_t* pY, DimensionType length); 35 | static void ComputeSum_AVX(std::int8_t* pX, const std::int8_t* pY, DimensionType length); 36 | static void ComputeSum_AVX512(std::int8_t* pX, const std::int8_t* pY, DimensionType length); 37 | 38 | static void ComputeSum_SSE(std::uint8_t* pX, const std::uint8_t* pY, DimensionType length); 39 | static void ComputeSum_AVX(std::uint8_t* pX, const std::uint8_t* pY, DimensionType length); 40 | static void ComputeSum_AVX512(std::uint8_t* pX, const std::uint8_t* pY, DimensionType length); 41 | 42 | static void ComputeSum_SSE(std::int16_t* pX, const std::int16_t* pY, DimensionType length); 43 | static void ComputeSum_AVX(std::int16_t* pX, const std::int16_t* pY, DimensionType length); 44 | static void ComputeSum_AVX512(std::int16_t* pX, const std::int16_t* pY, DimensionType length); 45 | 46 | static void ComputeSum_SSE(float* pX, const float* pY, DimensionType length); 47 | static void ComputeSum_AVX(float* pX, const float* pY, DimensionType length); 48 | static void ComputeSum_AVX512(float* pX, const float* pY, DimensionType length); 49 | 50 | template 51 | static inline void ComputeSum(T* p1, const T* p2, DimensionType length) 52 | { 53 | auto func = SumCalcSelector(); 54 | return func(p1, p2, length); 55 | } 56 | }; 57 | 58 | template 59 | inline SumCalcReturn SumCalcSelector() 60 | { 61 | if (InstructionSet::AVX512()) 62 | { 63 | return &(SIMDUtils::ComputeSum_AVX512); 64 | } 65 | bool isSize4 = (sizeof(T) == 4); 66 | if (InstructionSet::AVX2() || (isSize4 && InstructionSet::AVX())) 67 | { 68 | return &(SIMDUtils::ComputeSum_AVX); 69 | } 70 | if (InstructionSet::SSE2() || (isSize4 && InstructionSet::SSE())) 71 | { 72 | return &(SIMDUtils::ComputeSum_SSE); 73 | } 74 | return &(SIMDUtils::ComputeSum_Naive); 75 | } 76 | } 77 | } 78 | 79 | #endif // _SPTAG_COMMON_SIMDUTILS_H_ 80 | -------------------------------------------------------------------------------- /AnnService/inc/Core/Common/WorkSpacePool.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_COMMON_WORKSPACEPOOL_H_ 5 | #define _SPTAG_COMMON_WORKSPACEPOOL_H_ 6 | 7 | #include "WorkSpace.h" 8 | #include "inc/Helper/ConcurrentSet.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace SPTAG 15 | { 16 | namespace COMMON 17 | { 18 | 19 | template 20 | class WorkSpacePool 21 | { 22 | public: 23 | WorkSpacePool() {} 24 | 25 | ~WorkSpacePool() 26 | { 27 | std::shared_ptr workspace; 28 | while (m_workSpacePool.try_pop(workspace)) 29 | { 30 | workspace.reset(); 31 | } 32 | T::Reset(); 33 | } 34 | 35 | std::shared_ptr Rent() 36 | { 37 | std::shared_ptr workSpace; 38 | { 39 | if (m_workSpacePool.try_pop(workSpace)) 40 | { 41 | } 42 | else 43 | { 44 | workSpace.reset(new T(m_workSpace)); 45 | } 46 | } 47 | return workSpace; 48 | } 49 | 50 | void Return(const std::shared_ptr& p_workSpace) 51 | { 52 | m_workSpacePool.push(p_workSpace); 53 | } 54 | 55 | void Init(int size, ...) 56 | { 57 | va_list args; 58 | va_start(args, size); 59 | m_workSpace.Initialize(args); 60 | va_end(args); 61 | for (int i = 0; i < size; i++) 62 | { 63 | std::shared_ptr workSpace(new T(m_workSpace)); 64 | m_workSpacePool.push(std::move(workSpace)); 65 | } 66 | } 67 | 68 | private: 69 | Helper::Concurrent::ConcurrentQueue> m_workSpacePool; 70 | T m_workSpace; 71 | }; 72 | 73 | } 74 | } 75 | 76 | #endif // _SPTAG_COMMON_WORKSPACEPOOL_H_ 77 | -------------------------------------------------------------------------------- /AnnService/inc/Core/Common/cuda/log.hxx: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #pragma once 24 | 25 | #include 26 | //#include 27 | #include 28 | #include 29 | #include 30 | using namespace std; 31 | 32 | #include "params.h" 33 | 34 | enum log_level_t { 35 | LOG_NOTHING, 36 | LOG_CRITICAL, 37 | LOG_ERROR, 38 | LOG_WARNING, 39 | LOG_INFO, 40 | LOG_DEBUG 41 | }; 42 | 43 | 44 | #define LOG_ALL(f_, ...) printf((f_), ##__VA_ARGS__) 45 | #define DLOG_ALL(f_, ...) {if(threadIdx.x==0 && blockIdx.x==0 && blockIdx.y==0) printf((f_), ##__VA_ARGS__); } 46 | 47 | #if LOG_LEVEL >= 1 48 | #define LOG_CRIT(f_, ...) printf((f_), ##__VA_ARGS__) 49 | #define DLOG_CRIT(f_, ...) {if(threadIdx.x==0 && blockIdx.x==0) printf((f_), ##__VA_ARGS__); } 50 | #else 51 | #define LOG_CRIT(f_, ...) {} 52 | #define DLOG_CRIT(f_, ...) {} 53 | #endif 54 | 55 | #if LOG_LEVEL >= 2 56 | #define LOG_ERR(f_, ...) printf((f_), ##__VA_ARGS__) 57 | #define DLOG_ERR(f_, ...) {if(threadIdx.x==0 && blockIdx.x==0) printf((f_), ##__VA_ARGS__); } 58 | #else 59 | #define LOG_ERR(f_, ...) {} 60 | #define DLOG_ERR(f_, ...) {} 61 | #endif 62 | 63 | #if LOG_LEVEL >= 3 64 | #define LOG_WARN(f_, ...) printf((f_), ##__VA_ARGS__) 65 | #define DLOG_WARN(f_, ...) {if(threadIdx.x==0 && blockIdx.x==0) printf((f_), ##__VA_ARGS__); } 66 | #else 67 | #define LOG_WARN(f_, ...) {} 68 | #define DLOG_WARN(f_, ...) {} 69 | #endif 70 | 71 | #if LOG_LEVEL >= 4 72 | #define LOG_INFO(f_, ...) printf((f_), ##__VA_ARGS__) 73 | #define DLOG_INFO(f_, ...) {if(threadIdx.x==0 && blockIdx.x==0) printf((f_), ##__VA_ARGS__); } 74 | #else 75 | #define LOG_INFO(f_, ...) {} 76 | #define DLOG_INFO(f_, ...) {} 77 | #endif 78 | 79 | #if LOG_LEVEL >= 5 80 | #define LOG_DEBUG(f_, ...) printf((f_), ##__VA_ARGS__) 81 | #define DLOG_DEBUG(f_, ...) {if(threadIdx.x==0 && blockIdx.x==0) printf((f_), ##__VA_ARGS__); } 82 | #else 83 | #define LOG_DEBUG(f_, ...) {} 84 | #define DLOG_DEBUG(f_, ...) {} 85 | #endif 86 | 87 | #define STR_EXPAND(arg) #arg 88 | #define STR(arg) STR_EXPAND(arg) 89 | -------------------------------------------------------------------------------- /AnnService/inc/Core/MultiIndexScan.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_MULTI_INDEX_SCAN_H 5 | #define _SPTAG_MULTI_INDEX_SCAN_H 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "ResultIterator.h" 17 | #include "VectorIndex.h" 18 | #include 19 | namespace SPTAG 20 | { 21 | class MultiIndexScan 22 | { 23 | public: 24 | MultiIndexScan(); 25 | MultiIndexScan(std::vector> vecIndices, 26 | std::vector p_targets, 27 | unsigned int k, 28 | float (*rankFunction)(std::vector), 29 | bool useTimer, 30 | int termCondVal, 31 | int searchLimit 32 | ); 33 | ~MultiIndexScan(); 34 | void Init(std::vector> vecIndices, 35 | std::vector p_targets, 36 | std::vector weight, 37 | unsigned int k, 38 | bool useTimer, 39 | int termCondVal, 40 | int searchLimit); 41 | bool Next(BasicResult& result); 42 | void Close(); 43 | 44 | private: 45 | std::vector> indexIters; 46 | std::vector> fwdLUTs; 47 | std::unordered_set seenSet; 48 | std::vector p_data_array; 49 | std::vector weight; 50 | 51 | unsigned int k; 52 | 53 | 54 | 55 | bool useTimer; 56 | unsigned int termCondVal; 57 | int searchLimit; 58 | std::chrono::time_point t_start; 59 | 60 | float (*func)(std::vector); 61 | 62 | unsigned int consecutive_drops; 63 | 64 | bool terminate; 65 | using pq_item = std::pair; 66 | class pq_item_compare 67 | { 68 | public: 69 | bool operator()(const pq_item& lhs, const pq_item& rhs) 70 | { 71 | return lhs.first < rhs.first; 72 | } 73 | }; 74 | std::priority_queue, pq_item_compare> pq; 75 | std::stack outputStk; 76 | float WeightedRankFunc(std::vector); 77 | 78 | }; 79 | } // namespace SPTAG 80 | #endif 81 | -------------------------------------------------------------------------------- /AnnService/inc/Core/ResultIterator.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_RESULT_ITERATOR_H 5 | #define _SPTAG_RESULT_ITERATOR_H 6 | 7 | #include 8 | 9 | #include "VectorIndex.h" 10 | #include "SearchQuery.h" 11 | 12 | typedef SPTAG::VectorIndex VectorIndex; 13 | typedef SPTAG::ByteArray ByteArray; 14 | typedef SPTAG::QueryResult QueryResult; 15 | 16 | class ResultIterator 17 | { 18 | public: 19 | ResultIterator(const void* p_index, const void* p_target, bool p_searchDeleted, int p_workspaceBatch); 20 | 21 | ~ResultIterator(); 22 | 23 | void* GetWorkSpace(); 24 | 25 | virtual std::shared_ptr Next(int batch); 26 | 27 | virtual bool GetRelaxedMono(); 28 | 29 | virtual void Close(); 30 | 31 | const void* GetTarget(); 32 | 33 | protected: 34 | const VectorIndex* m_index; 35 | const void* m_target; 36 | ByteArray m_byte_target; 37 | std::shared_ptr m_queryResult; 38 | void* m_workspace; 39 | bool m_searchDeleted; 40 | bool m_isFirstResult; 41 | int m_batch = 1; 42 | }; 43 | 44 | #endif -------------------------------------------------------------------------------- /AnnService/inc/Core/SPANN/SPANNResultIterator.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_SPANN_RESULT_ITERATOR_H 5 | #define _SPTAG_SPANN_RESULT_ITERATOR_H 6 | 7 | #include 8 | 9 | #include "inc/Core/SPANN/Index.h" 10 | #include "inc/Core/SearchQuery.h" 11 | #include "inc/Core/ResultIterator.h" 12 | #include "inc/Core/Common/WorkSpace.h" 13 | #include "inc/Core/SPANN/IExtraSearcher.h" 14 | 15 | namespace SPTAG 16 | { 17 | namespace SPANN 18 | { 19 | template 20 | class SPANNResultIterator : public ResultIterator 21 | { 22 | public: 23 | SPANNResultIterator(const Index* p_spannIndex, const VectorIndex* p_index, const void* p_target, 24 | std::unique_ptr p_extraWorkspace, 25 | int p_batch): ResultIterator(p_index, p_target, false, p_batch), 26 | m_spannIndex(p_spannIndex), 27 | m_extraWorkspace(std::move(p_extraWorkspace)) 28 | { 29 | m_headQueryResult = std::make_unique(p_target, p_batch, false); 30 | } 31 | 32 | ~SPANNResultIterator() 33 | { 34 | Close(); 35 | } 36 | 37 | virtual std::shared_ptr Next(int batch) 38 | { 39 | if (m_queryResult == nullptr) { 40 | m_queryResult = std::make_unique(m_target, batch, true); 41 | } 42 | else if (batch <= m_queryResult->GetResultNum()) { 43 | m_queryResult->SetResultNum(batch); 44 | } 45 | else { 46 | batch = m_queryResult->GetResultNum(); 47 | } 48 | 49 | m_queryResult->Reset(); 50 | if (m_workspace == nullptr) return m_queryResult; 51 | 52 | int resultCount = 0; 53 | m_spannIndex->SearchIndexIterative(*m_headQueryResult, *m_queryResult, 54 | (COMMON::WorkSpace*)GetWorkSpace(), m_extraWorkspace.get(), batch, resultCount, m_isFirstResult); 55 | m_isFirstResult = false; 56 | 57 | for (int i = 0; i < resultCount; i++) 58 | { 59 | m_queryResult->GetResult(i)->RelaxedMono = m_extraWorkspace->m_relaxedMono; 60 | } 61 | m_queryResult->SetResultNum(resultCount); 62 | return m_queryResult; 63 | } 64 | 65 | virtual bool GetRelaxedMono() 66 | { 67 | if (m_extraWorkspace == nullptr) return false; 68 | 69 | return m_extraWorkspace->m_relaxedMono; 70 | } 71 | 72 | virtual void Close() 73 | { 74 | ResultIterator::Close(); 75 | if (m_extraWorkspace != nullptr) { 76 | m_spannIndex->SearchIndexIterativeEnd(std::move(m_extraWorkspace)); 77 | m_extraWorkspace = nullptr; 78 | } 79 | } 80 | 81 | private: 82 | const Index* m_spannIndex; 83 | std::unique_ptr m_headQueryResult; 84 | std::unique_ptr m_extraWorkspace; 85 | }; 86 | }// namespace SPANN 87 | } // namespace SPTAG 88 | #endif 89 | -------------------------------------------------------------------------------- /AnnService/inc/Core/SearchResult.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_SEARCHRESULT_H_ 5 | #define _SPTAG_SEARCHRESULT_H_ 6 | 7 | #include "CommonDataStructure.h" 8 | 9 | namespace SPTAG 10 | { 11 | struct NodeDistPair 12 | { 13 | SizeType node; 14 | float distance; 15 | 16 | NodeDistPair(SizeType _node = -1, float _distance = MaxDist) : node(_node), distance(_distance) {} 17 | 18 | inline bool operator < (const NodeDistPair& rhs) const 19 | { 20 | return distance < rhs.distance; 21 | } 22 | 23 | inline bool operator > (const NodeDistPair& rhs) const 24 | { 25 | return distance > rhs.distance; 26 | } 27 | }; 28 | 29 | struct Edge 30 | { 31 | SizeType node; 32 | float distance; 33 | SizeType tonode; 34 | Edge() : node(MaxSize), distance(MaxDist), tonode(MaxSize) {} 35 | }; 36 | 37 | struct EdgeCompare 38 | { 39 | inline bool operator()(const Edge& a, int b) const 40 | { 41 | return a.node < b; 42 | }; 43 | 44 | inline bool operator()(int a, const Edge& b) const 45 | { 46 | return a < b.node; 47 | }; 48 | 49 | inline bool operator()(const Edge& a, const Edge& b) const 50 | { 51 | if (a.node == b.node) 52 | { 53 | if (a.distance == b.distance) 54 | { 55 | return a.tonode < b.tonode; 56 | } 57 | 58 | return a.distance < b.distance; 59 | } 60 | 61 | return a.node < b.node; 62 | }; 63 | }; 64 | 65 | struct BasicResult 66 | { 67 | SizeType VID; 68 | float Dist; 69 | ByteArray Meta; 70 | bool RelaxedMono; 71 | 72 | BasicResult() : VID(-1), Dist(MaxDist), RelaxedMono(false) {} 73 | 74 | BasicResult(SizeType p_vid, float p_dist) : VID(p_vid), Dist(p_dist), RelaxedMono(false) {} 75 | 76 | BasicResult(SizeType p_vid, float p_dist, ByteArray p_meta) : VID(p_vid), Dist(p_dist), Meta(p_meta), RelaxedMono(false) {} 77 | BasicResult(SizeType p_vid, float p_dist, ByteArray p_meta, bool p_relaxedMono) : VID(p_vid), Dist(p_dist), Meta(p_meta), RelaxedMono(p_relaxedMono) {} 78 | }; 79 | 80 | } // namespace SPTAG 81 | 82 | #endif // _SPTAG_SEARCHRESULT_H_ 83 | -------------------------------------------------------------------------------- /AnnService/inc/Core/VectorSet.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_VECTORSET_H_ 5 | #define _SPTAG_VECTORSET_H_ 6 | 7 | #include "CommonDataStructure.h" 8 | 9 | namespace SPTAG 10 | { 11 | 12 | class VectorSet 13 | { 14 | public: 15 | VectorSet(); 16 | 17 | virtual ~VectorSet(); 18 | 19 | virtual VectorValueType GetValueType() const = 0; 20 | 21 | virtual void* GetVector(SizeType p_vectorID) const = 0; 22 | 23 | virtual void* GetData() const = 0; 24 | 25 | virtual DimensionType Dimension() const = 0; 26 | 27 | virtual SizeType Count() const = 0; 28 | 29 | virtual bool Available() const = 0; 30 | 31 | virtual ErrorCode Save(const std::string& p_vectorFile) const = 0; 32 | 33 | virtual ErrorCode AppendSave(const std::string& p_vectorFile) const = 0; 34 | 35 | virtual SizeType PerVectorDataSize() const = 0; 36 | 37 | virtual void Normalize(int p_threads) = 0; 38 | }; 39 | 40 | 41 | class BasicVectorSet : public VectorSet 42 | { 43 | public: 44 | BasicVectorSet(const ByteArray& p_bytesArray, 45 | VectorValueType p_valueType, 46 | DimensionType p_dimension, 47 | SizeType p_vectorCount); 48 | 49 | virtual ~BasicVectorSet(); 50 | 51 | virtual VectorValueType GetValueType() const; 52 | 53 | virtual void* GetVector(SizeType p_vectorID) const; 54 | 55 | virtual void* GetData() const; 56 | 57 | virtual DimensionType Dimension() const; 58 | 59 | virtual SizeType Count() const; 60 | 61 | virtual bool Available() const; 62 | 63 | virtual ErrorCode Save(const std::string& p_vectorFile) const; 64 | 65 | virtual ErrorCode AppendSave(const std::string& p_vectorFile) const; 66 | 67 | virtual SizeType PerVectorDataSize() const; 68 | 69 | virtual void Normalize(int p_threads); 70 | 71 | private: 72 | ByteArray m_data; 73 | 74 | VectorValueType m_valueType; 75 | 76 | DimensionType m_dimension; 77 | 78 | SizeType m_vectorCount; 79 | 80 | size_t m_perVectorDataSize; 81 | }; 82 | 83 | } // namespace SPTAG 84 | 85 | #endif // _SPTAG_VECTORSET_H_ 86 | -------------------------------------------------------------------------------- /AnnService/inc/Helper/Base64Encode.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_HELPER_BASE64ENCODE_H_ 5 | #define _SPTAG_HELPER_BASE64ENCODE_H_ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace SPTAG 12 | { 13 | namespace Helper 14 | { 15 | namespace Base64 16 | { 17 | 18 | bool Encode(const std::uint8_t* p_in, std::size_t p_inLen, char* p_out, std::size_t& p_outLen); 19 | 20 | bool Encode(const std::uint8_t* p_in, std::size_t p_inLen, std::ostream& p_out, std::size_t& p_outLen); 21 | 22 | bool Decode(const char* p_in, std::size_t p_inLen, std::uint8_t* p_out, std::size_t& p_outLen); 23 | 24 | std::size_t CapacityForEncode(std::size_t p_inLen); 25 | 26 | std::size_t CapacityForDecode(std::size_t p_inLen); 27 | 28 | 29 | } // namespace Base64 30 | } // namespace Helper 31 | } // namespace SPTAG 32 | 33 | #endif // _SPTAG_HELPER_BASE64ENCODE_H_ 34 | -------------------------------------------------------------------------------- /AnnService/inc/Helper/CommonHelper.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_HELPER_COMMONHELPER_H_ 5 | #define _SPTAG_HELPER_COMMONHELPER_H_ 6 | 7 | #include "inc/Core/Common.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | namespace SPTAG 18 | { 19 | namespace Helper 20 | { 21 | namespace StrUtils 22 | { 23 | 24 | void ToLowerInPlace(std::string& p_str); 25 | 26 | std::vector SplitString(const std::string& p_str, const std::string& p_separator); 27 | 28 | std::pair FindTrimmedSegment(const char* p_begin, 29 | const char* p_end, 30 | const std::function& p_isSkippedChar); 31 | 32 | bool StartsWith(const char* p_str, const char* p_prefix); 33 | 34 | bool StrEqualIgnoreCase(const char* p_left, const char* p_right); 35 | 36 | std::string ReplaceAll(const std::string& orig, const std::string& from, const std::string& to); 37 | 38 | } // namespace StrUtils 39 | } // namespace Helper 40 | } // namespace SPTAG 41 | 42 | #endif // _SPTAG_HELPER_COMMONHELPER_H_ 43 | -------------------------------------------------------------------------------- /AnnService/inc/Helper/Concurrent.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_HELPER_CONCURRENT_H_ 5 | #define _SPTAG_HELPER_CONCURRENT_H_ 6 | 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | namespace SPTAG 14 | { 15 | namespace Helper 16 | { 17 | namespace Concurrent 18 | { 19 | 20 | class SpinLock 21 | { 22 | public: 23 | SpinLock() = default; 24 | 25 | void Lock() noexcept 26 | { 27 | while (m_lock.test_and_set(std::memory_order_acquire)) 28 | { 29 | } 30 | } 31 | 32 | void Unlock() noexcept 33 | { 34 | m_lock.clear(std::memory_order_release); 35 | } 36 | 37 | SpinLock(const SpinLock&) = delete; 38 | SpinLock& operator = (const SpinLock&) = delete; 39 | 40 | private: 41 | std::atomic_flag m_lock = ATOMIC_FLAG_INIT; 42 | }; 43 | 44 | template 45 | class LockGuard { 46 | public: 47 | LockGuard(Lock& lock) noexcept 48 | : m_lock(lock) { 49 | lock.Lock(); 50 | } 51 | 52 | LockGuard(Lock& lock, std::adopt_lock_t) noexcept 53 | : m_lock(lock) {} 54 | 55 | ~LockGuard() { 56 | m_lock.Unlock(); 57 | } 58 | 59 | LockGuard(const LockGuard&) = delete; 60 | LockGuard& operator=(const LockGuard&) = delete; 61 | 62 | private: 63 | Lock& m_lock; 64 | }; 65 | 66 | 67 | class WaitSignal 68 | { 69 | public: 70 | WaitSignal(); 71 | 72 | WaitSignal(std::uint32_t p_unfinished); 73 | 74 | ~WaitSignal(); 75 | 76 | void Reset(std::uint32_t p_unfinished); 77 | 78 | void Wait(); 79 | 80 | void FinishOne(); 81 | 82 | private: 83 | std::atomic m_unfinished; 84 | 85 | std::atomic_bool m_isWaiting; 86 | 87 | std::mutex m_mutex; 88 | 89 | std::condition_variable m_cv; 90 | }; 91 | 92 | 93 | } // namespace Base64 94 | } // namespace Helper 95 | } // namespace SPTAG 96 | 97 | #endif // _SPTAG_HELPER_CONCURRENT_H_ 98 | -------------------------------------------------------------------------------- /AnnService/inc/Helper/DynamicNeighbors.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace SPTAG { 6 | namespace Helper { 7 | class DynamicNeighbors 8 | { 9 | public: 10 | DynamicNeighbors(const int* p_data, const int p_length); 11 | 12 | ~DynamicNeighbors(); 13 | 14 | int operator[](const int p_id) const; 15 | 16 | int Size() const; 17 | 18 | private: 19 | const int* const c_data; 20 | 21 | const int c_length; 22 | }; 23 | 24 | 25 | class DynamicNeighborsSet 26 | { 27 | public: 28 | DynamicNeighborsSet(const char* p_filePath); 29 | 30 | ~DynamicNeighborsSet(); 31 | 32 | DynamicNeighbors operator[](const int p_id) const; 33 | 34 | int VectorCount() const 35 | { 36 | return m_vectorCount; 37 | } 38 | 39 | private: 40 | std::unique_ptr m_data; 41 | 42 | std::unique_ptr m_neighborOffset; 43 | 44 | int m_vectorCount; 45 | }; 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /AnnService/inc/Helper/SimpleIniReader.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_HELPER_INIREADER_H_ 5 | #define _SPTAG_HELPER_INIREADER_H_ 6 | 7 | #include "inc/Core/Common.h" 8 | #include "StringConvert.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | namespace SPTAG 17 | { 18 | namespace Helper 19 | { 20 | 21 | // Simple INI Reader with basic functions. Case insensitive. 22 | class IniReader 23 | { 24 | public: 25 | typedef std::map ParameterValueMap; 26 | 27 | IniReader(); 28 | 29 | ~IniReader(); 30 | 31 | ErrorCode LoadIniFile(const std::string& p_iniFilePath); 32 | 33 | ErrorCode LoadIni(std::shared_ptr p_input); 34 | 35 | bool DoesSectionExist(const std::string& p_section) const; 36 | 37 | bool DoesParameterExist(const std::string& p_section, const std::string& p_param) const; 38 | 39 | const ParameterValueMap& GetParameters(const std::string& p_section) const; 40 | 41 | template 42 | DataType GetParameter(const std::string& p_section, const std::string& p_param, const DataType& p_defaultVal) const; 43 | 44 | void SetParameter(const std::string& p_section, const std::string& p_param, const std::string& p_val); 45 | 46 | private: 47 | bool GetRawValue(const std::string& p_section, const std::string& p_param, std::string& p_value) const; 48 | 49 | template 50 | static inline DataType ConvertStringTo(std::string&& p_str, const DataType& p_defaultVal); 51 | 52 | private: 53 | const static ParameterValueMap c_emptyParameters; 54 | 55 | std::map> m_parameters; 56 | }; 57 | 58 | 59 | template 60 | DataType 61 | IniReader::GetParameter(const std::string& p_section, const std::string& p_param, const DataType& p_defaultVal) const 62 | { 63 | std::string value; 64 | if (!GetRawValue(p_section, p_param, value)) 65 | { 66 | return p_defaultVal; 67 | } 68 | 69 | return ConvertStringTo(std::move(value), p_defaultVal); 70 | } 71 | 72 | 73 | template 74 | inline DataType 75 | IniReader::ConvertStringTo(std::string&& p_str, const DataType& p_defaultVal) 76 | { 77 | DataType value; 78 | if (Convert::ConvertStringTo(p_str.c_str(), value)) 79 | { 80 | return value; 81 | } 82 | 83 | return p_defaultVal; 84 | } 85 | 86 | 87 | template <> 88 | inline std::string 89 | IniReader::ConvertStringTo(std::string&& p_str, const std::string& p_defaultVal) 90 | { 91 | return std::move(p_str); 92 | } 93 | 94 | 95 | } // namespace Helper 96 | } // namespace SPTAG 97 | 98 | #endif // _SPTAG_HELPER_INIREADER_H_ 99 | -------------------------------------------------------------------------------- /AnnService/inc/Helper/VectorSetReader.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_HELPER_VECTORSETREADER_H_ 5 | #define _SPTAG_HELPER_VECTORSETREADER_H_ 6 | 7 | #include "inc/Core/Common.h" 8 | #include "inc/Core/VectorSet.h" 9 | #include "inc/Core/MetadataSet.h" 10 | #include "inc/Helper/ArgumentsParser.h" 11 | 12 | #include 13 | 14 | namespace SPTAG 15 | { 16 | namespace Helper 17 | { 18 | 19 | class ReaderOptions : public ArgumentsParser 20 | { 21 | public: 22 | ReaderOptions(VectorValueType p_valueType, DimensionType p_dimension, VectorFileType p_fileType, std::string p_vectorDelimiter = "|", std::uint32_t p_threadNum = 32, bool p_normalized = false); 23 | 24 | ~ReaderOptions(); 25 | 26 | SPTAG::VectorValueType m_inputValueType; 27 | 28 | DimensionType m_dimension; 29 | 30 | SPTAG::VectorFileType m_inputFileType; 31 | 32 | std::string m_vectorDelimiter; 33 | 34 | std::uint32_t m_threadNum; 35 | 36 | bool m_normalized; 37 | }; 38 | 39 | class VectorSetReader 40 | { 41 | public: 42 | VectorSetReader(std::shared_ptr p_options); 43 | 44 | virtual ~VectorSetReader(); 45 | 46 | virtual ErrorCode LoadFile(const std::string& p_filePath) = 0; 47 | 48 | virtual std::shared_ptr GetVectorSet(SizeType start = 0, SizeType end = -1) const = 0; 49 | 50 | virtual std::shared_ptr GetMetadataSet() const = 0; 51 | 52 | virtual bool IsNormalized() const { return m_options->m_normalized; } 53 | 54 | static std::shared_ptr CreateInstance(std::shared_ptr p_options); 55 | 56 | protected: 57 | std::shared_ptr m_options; 58 | }; 59 | 60 | 61 | 62 | } // namespace Helper 63 | } // namespace SPTAG 64 | 65 | #endif // _SPTAG_HELPER_VECTORSETREADER_H_ 66 | -------------------------------------------------------------------------------- /AnnService/inc/Helper/VectorSetReaders/DefaultReader.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_HELPER_VECTORSETREADERS_DEFAULTREADER_H_ 5 | #define _SPTAG_HELPER_VECTORSETREADERS_DEFAULTREADER_H_ 6 | 7 | #include "inc/Helper/VectorSetReader.h" 8 | 9 | namespace SPTAG 10 | { 11 | namespace Helper 12 | { 13 | 14 | class DefaultVectorReader : public VectorSetReader 15 | { 16 | public: 17 | DefaultVectorReader(std::shared_ptr p_options); 18 | 19 | virtual ~DefaultVectorReader(); 20 | 21 | virtual ErrorCode LoadFile(const std::string& p_filePaths); 22 | 23 | virtual std::shared_ptr GetVectorSet(SizeType start = 0, SizeType end = -1) const; 24 | 25 | virtual std::shared_ptr GetMetadataSet() const; 26 | 27 | private: 28 | std::string m_vectorOutput; 29 | 30 | std::string m_metadataConentOutput; 31 | 32 | std::string m_metadataIndexOutput; 33 | }; 34 | 35 | 36 | 37 | } // namespace Helper 38 | } // namespace SPTAG 39 | 40 | #endif // _SPTAG_HELPER_VECTORSETREADERS_DEFAULTREADER_H_ 41 | -------------------------------------------------------------------------------- /AnnService/inc/Helper/VectorSetReaders/MemoryReader.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_HELPER_VECTORSETREADERS_MEMORYREADER_H_ 5 | #define _SPTAG_HELPER_VECTORSETREADERS_MEMORYREADER_H_ 6 | 7 | #include "inc/Helper/VectorSetReader.h" 8 | 9 | namespace SPTAG 10 | { 11 | namespace Helper 12 | { 13 | 14 | class MemoryVectorReader : public VectorSetReader 15 | { 16 | public: 17 | MemoryVectorReader(std::shared_ptr p_options, std::shared_ptr p_vectors) : 18 | VectorSetReader(p_options), m_vectors(p_vectors) 19 | {} 20 | 21 | virtual ~MemoryVectorReader() {} 22 | 23 | virtual ErrorCode LoadFile(const std::string& p_filePaths) { return ErrorCode::Success; } 24 | 25 | virtual std::shared_ptr GetVectorSet(SizeType start = 0, SizeType end = -1) const 26 | { 27 | if (end < 0 || end > m_vectors->Count()) end = m_vectors->Count(); 28 | return std::shared_ptr(new BasicVectorSet(ByteArray((std::uint8_t*)(m_vectors->GetVector(start)), (end - start) * m_vectors->PerVectorDataSize(), false), 29 | m_vectors->GetValueType(), 30 | m_vectors->Dimension(), 31 | end - start)); 32 | } 33 | 34 | virtual std::shared_ptr GetMetadataSet() const { return nullptr; } 35 | 36 | private: 37 | std::shared_ptr m_vectors; 38 | }; 39 | 40 | } // namespace Helper 41 | } // namespace SPTAG 42 | 43 | #endif // _SPTAG_HELPER_VECTORSETREADERS_MEMORYREADER_H_ 44 | -------------------------------------------------------------------------------- /AnnService/inc/Helper/VectorSetReaders/TxtReader.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_HELPER_VECTORSETREADERS_TXTREADER_H_ 5 | #define _SPTAG_HELPER_VECTORSETREADERS_TXTREADER_H_ 6 | 7 | #include "inc/Helper/VectorSetReader.h" 8 | #include "inc/Helper/Concurrent.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace SPTAG 15 | { 16 | namespace Helper 17 | { 18 | 19 | class TxtVectorReader : public VectorSetReader 20 | { 21 | public: 22 | TxtVectorReader(std::shared_ptr p_options); 23 | 24 | virtual ~TxtVectorReader(); 25 | 26 | virtual ErrorCode LoadFile(const std::string& p_filePaths); 27 | 28 | virtual std::shared_ptr GetVectorSet(SizeType start = 0, SizeType end = -1) const; 29 | 30 | virtual std::shared_ptr GetMetadataSet() const; 31 | 32 | private: 33 | typedef std::pair FileInfoPair; 34 | 35 | static std::vector GetFileSizes(const std::string& p_filePaths); 36 | 37 | ErrorCode LoadFileInternal(const std::string& p_filePath, 38 | std::uint32_t p_subtaskID, 39 | std::uint32_t p_fileBlockID, 40 | std::size_t p_fileBlockSize); 41 | 42 | ErrorCode MergeData(); 43 | 44 | template 45 | bool TranslateVector(char* p_str, DataType* p_vector) 46 | { 47 | DimensionType eleCount = 0; 48 | char* next = p_str; 49 | while ((*next) != '\0') 50 | { 51 | while ((*next) != '\0' && m_options->m_vectorDelimiter.find(*next) == std::string::npos) 52 | { 53 | ++next; 54 | } 55 | 56 | bool reachEnd = ('\0' == (*next)); 57 | *next = '\0'; 58 | if (p_str != next) 59 | { 60 | if (eleCount >= m_options->m_dimension) 61 | { 62 | return false; 63 | } 64 | 65 | if (!Helper::Convert::ConvertStringTo(p_str, p_vector[eleCount++])) 66 | { 67 | return false; 68 | } 69 | } 70 | 71 | if (reachEnd) 72 | { 73 | break; 74 | } 75 | 76 | ++next; 77 | p_str = next; 78 | } 79 | 80 | return eleCount == m_options->m_dimension; 81 | } 82 | 83 | private: 84 | std::uint32_t m_subTaskCount; 85 | 86 | std::size_t m_subTaskBlocksize; 87 | 88 | std::atomic m_totalRecordCount; 89 | 90 | std::atomic m_totalRecordVectorBytes; 91 | 92 | std::vector m_subTaskRecordCount; 93 | 94 | std::string m_vectorOutput; 95 | 96 | std::string m_metadataConentOutput; 97 | 98 | std::string m_metadataIndexOutput; 99 | 100 | Helper::Concurrent::WaitSignal m_waitSignal; 101 | }; 102 | 103 | 104 | 105 | } // namespace Helper 106 | } // namespace SPTAG 107 | 108 | #endif // _SPTAG_HELPER_VECTORSETREADERS_TXTREADER_H_ 109 | -------------------------------------------------------------------------------- /AnnService/inc/Helper/VectorSetReaders/XvecReader.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_HELPER_VECTORSETREADERS_XVECREADER_H_ 5 | #define _SPTAG_HELPER_VECTORSETREADERS_XVECREADER_H_ 6 | 7 | #include "inc/Helper/VectorSetReader.h" 8 | 9 | namespace SPTAG 10 | { 11 | namespace Helper 12 | { 13 | 14 | class XvecVectorReader : public VectorSetReader 15 | { 16 | public: 17 | XvecVectorReader(std::shared_ptr p_options); 18 | 19 | virtual ~XvecVectorReader(); 20 | 21 | virtual ErrorCode LoadFile(const std::string& p_filePaths); 22 | 23 | virtual std::shared_ptr GetVectorSet(SizeType start = 0, SizeType end = -1) const; 24 | 25 | virtual std::shared_ptr GetMetadataSet() const; 26 | 27 | private: 28 | std::string m_vectorOutput; 29 | }; 30 | 31 | 32 | 33 | } // namespace Helper 34 | } // namespace SPTAG 35 | 36 | #endif // _SPTAG_HELPER_VECTORSETREADERS_XVECREADER_H_ 37 | -------------------------------------------------------------------------------- /AnnService/inc/SSDServing/Utils.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #pragma once 5 | #include 6 | 7 | namespace SPTAG { 8 | namespace SSDServing { 9 | namespace Utils { 10 | typedef std::chrono::steady_clock SteadClock; 11 | 12 | double getMsInterval(std::chrono::steady_clock::time_point start, std::chrono::steady_clock::time_point end) { 13 | return (std::chrono::duration_cast(end - start).count() * 1.0) / 1000.0; 14 | } 15 | 16 | double getSecInterval(std::chrono::steady_clock::time_point start, std::chrono::steady_clock::time_point end) { 17 | return (std::chrono::duration_cast(end - start).count() * 1.0) / 1000.0; 18 | } 19 | 20 | double getMinInterval(std::chrono::steady_clock::time_point start, std::chrono::steady_clock::time_point end) { 21 | return (std::chrono::duration_cast(end - start).count() * 1.0) / 60.0; 22 | } 23 | 24 | /// Clock class 25 | class StopW { 26 | private: 27 | std::chrono::steady_clock::time_point time_begin; 28 | public: 29 | StopW() { 30 | time_begin = std::chrono::steady_clock::now(); 31 | } 32 | 33 | double getElapsedMs() { 34 | std::chrono::steady_clock::time_point time_end = std::chrono::steady_clock::now(); 35 | return getMsInterval(time_begin, time_end); 36 | } 37 | 38 | double getElapsedSec() { 39 | std::chrono::steady_clock::time_point time_end = std::chrono::steady_clock::now(); 40 | return getSecInterval(time_begin, time_end); 41 | } 42 | 43 | double getElapsedMin() { 44 | std::chrono::steady_clock::time_point time_end = std::chrono::steady_clock::now(); 45 | return getMinInterval(time_begin, time_end); 46 | } 47 | 48 | void reset() { 49 | time_begin = std::chrono::steady_clock::now(); 50 | } 51 | }; 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /AnnService/inc/SSDServing/main.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #pragma once 5 | #include 6 | #include 7 | #include "inc/Core/Common.h" 8 | 9 | namespace SPTAG { 10 | namespace SSDServing { 11 | 12 | int BootProgram(bool forANNIndexTestTool, 13 | std::map>* config_map, 14 | const char* configurationPath = nullptr, 15 | SPTAG::VectorValueType valueType = SPTAG::VectorValueType::Undefined, 16 | SPTAG::DistCalcMethod distCalcMethod = SPTAG::DistCalcMethod::Undefined, 17 | const char* dataFilePath = nullptr, 18 | const char* indexFilePath = nullptr); 19 | 20 | const std::string SEC_BASE = "Base"; 21 | const std::string SEC_SELECT_HEAD = "SelectHead"; 22 | const std::string SEC_BUILD_HEAD = "BuildHead"; 23 | const std::string SEC_BUILD_SSD_INDEX = "BuildSSDIndex"; 24 | const std::string SEC_SEARCH_SSD_INDEX = "SearchSSDIndex"; 25 | } 26 | } -------------------------------------------------------------------------------- /AnnService/inc/Server/QueryParser.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_SERVER_QUERYPARSER_H_ 5 | #define _SPTAG_SERVER_QUERYPARSER_H_ 6 | 7 | #include "../Core/Common.h" 8 | #include "../Core/CommonDataStructure.h" 9 | #include "inc/Helper/StringConvert.h" 10 | 11 | #include 12 | 13 | namespace SPTAG 14 | { 15 | namespace Service 16 | { 17 | 18 | template 19 | ErrorCode 20 | ConvertVectorFromString(const std::vector& p_source, ByteArray& p_dest, SizeType& p_dimension) 21 | { 22 | p_dimension = (SizeType)p_source.size(); 23 | p_dest = ByteArray::Alloc(p_dimension * sizeof(ValueType)); 24 | ValueType* arr = reinterpret_cast(p_dest.Data()); 25 | for (std::size_t i = 0; i < p_source.size(); ++i) 26 | { 27 | if (!Helper::Convert::ConvertStringTo(p_source[i], arr[i])) 28 | { 29 | p_dest.Clear(); 30 | p_dimension = 0; 31 | return ErrorCode::Fail; 32 | } 33 | } 34 | return ErrorCode::Success; 35 | } 36 | 37 | class QueryParser 38 | { 39 | public: 40 | typedef std::pair OptionPair; 41 | 42 | QueryParser(); 43 | 44 | ~QueryParser(); 45 | 46 | ErrorCode Parse(const std::string& p_query, const char* p_vectorSeparator); 47 | 48 | const std::vector& GetVectorElements() const; 49 | 50 | const std::vector& GetOptions() const; 51 | 52 | const char* GetVectorBase64() const; 53 | 54 | SizeType GetVectorBase64Length() const; 55 | 56 | private: 57 | std::vector m_options; 58 | 59 | std::vector m_vectorElements; 60 | 61 | const char* m_vectorBase64; 62 | 63 | SizeType m_vectorBase64Length; 64 | 65 | ByteArray m_dataHolder; 66 | 67 | static const char* c_defaultVectorSeparator; 68 | }; 69 | 70 | 71 | } // namespace Server 72 | } // namespace AnnService 73 | 74 | 75 | #endif // _SPTAG_SERVER_QUERYPARSER_H_ 76 | -------------------------------------------------------------------------------- /AnnService/inc/Server/SearchExecutionContext.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_SERVER_SEARCHEXECUTIONCONTEXT_H_ 5 | #define _SPTAG_SERVER_SEARCHEXECUTIONCONTEXT_H_ 6 | 7 | #include "inc/Core/VectorIndex.h" 8 | #include "inc/Core/SearchQuery.h" 9 | #include "inc/Socket/RemoteSearchQuery.h" 10 | #include "ServiceSettings.h" 11 | #include "QueryParser.h" 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | 18 | namespace SPTAG 19 | { 20 | namespace Service 21 | { 22 | 23 | typedef Socket::IndexSearchResult SearchResult; 24 | 25 | class SearchExecutionContext 26 | { 27 | public: 28 | SearchExecutionContext(const std::shared_ptr& p_serviceSettings); 29 | 30 | ~SearchExecutionContext(); 31 | 32 | ErrorCode ParseQuery(const std::string& p_query); 33 | 34 | ErrorCode ExtractOption(); 35 | 36 | ErrorCode ExtractVector(VectorValueType p_targetType); 37 | 38 | void AddResults(std::string p_indexName, QueryResult& p_results); 39 | 40 | std::vector& GetResults(); 41 | 42 | const std::vector& GetResults() const; 43 | 44 | const ByteArray& GetVector() const; 45 | 46 | const std::vector& GetSelectedIndexNames() const; 47 | 48 | const SizeType GetVectorDimension() const; 49 | 50 | const std::vector& GetOptions() const; 51 | 52 | const SizeType GetResultNum() const; 53 | 54 | const bool GetExtractMetadata() const; 55 | 56 | private: 57 | const std::shared_ptr c_serviceSettings; 58 | 59 | QueryParser m_queryParser; 60 | 61 | std::vector m_indexNames; 62 | 63 | ByteArray m_vector; 64 | 65 | SizeType m_vectorDimension; 66 | 67 | std::vector m_results; 68 | 69 | VectorValueType m_inputValueType; 70 | 71 | bool m_extractMetadata; 72 | 73 | SizeType m_resultNum; 74 | }; 75 | 76 | } // namespace Server 77 | } // namespace AnnService 78 | 79 | 80 | #endif // _SPTAG_SERVER_SEARCHEXECUTIONCONTEXT_H_ 81 | -------------------------------------------------------------------------------- /AnnService/inc/Server/SearchExecutor.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_SERVER_SEARCHEXECUTOR_H_ 5 | #define _SPTAG_SERVER_SEARCHEXECUTOR_H_ 6 | 7 | #include "ServiceContext.h" 8 | #include "ServiceSettings.h" 9 | #include "SearchExecutionContext.h" 10 | #include "QueryParser.h" 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace SPTAG 17 | { 18 | namespace Service 19 | { 20 | 21 | class SearchExecutor 22 | { 23 | public: 24 | typedef std::function)> CallBack; 25 | 26 | SearchExecutor(std::string p_queryString, 27 | std::shared_ptr p_serviceContext, 28 | const CallBack& p_callback); 29 | 30 | ~SearchExecutor(); 31 | 32 | void Execute(); 33 | 34 | private: 35 | void ExecuteInternal(); 36 | 37 | void SelectIndex(); 38 | 39 | private: 40 | CallBack m_callback; 41 | 42 | const std::shared_ptr c_serviceContext; 43 | 44 | std::shared_ptr m_executionContext; 45 | 46 | std::string m_queryString; 47 | 48 | std::vector> m_selectedIndex; 49 | }; 50 | 51 | 52 | } // namespace Server 53 | } // namespace AnnService 54 | 55 | 56 | #endif // _SPTAG_SERVER_SEARCHEXECUTOR_H_ 57 | -------------------------------------------------------------------------------- /AnnService/inc/Server/SearchService.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_SERVER_SERVICE_H_ 5 | #define _SPTAG_SERVER_SERVICE_H_ 6 | 7 | #include "ServiceContext.h" 8 | #include "../Socket/Server.h" 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace SPTAG 18 | { 19 | namespace Service 20 | { 21 | 22 | class SearchExecutionContext; 23 | 24 | class SearchService 25 | { 26 | public: 27 | SearchService(); 28 | 29 | ~SearchService(); 30 | 31 | bool Initialize(int p_argNum, char* p_args[]); 32 | 33 | void Run(); 34 | 35 | private: 36 | void RunSocketMode(); 37 | 38 | void RunInteractiveMode(); 39 | 40 | void SearchHanlder(Socket::ConnectionID p_localConnectionID, Socket::Packet p_packet); 41 | 42 | void SearchHanlderCallback(std::shared_ptr p_exeContext, 43 | Socket::Packet p_srcPacket); 44 | 45 | private: 46 | enum class ServeMode : std::uint8_t 47 | { 48 | Interactive, 49 | 50 | Socket 51 | }; 52 | 53 | std::shared_ptr m_serviceContext; 54 | 55 | std::shared_ptr m_socketServer; 56 | 57 | bool m_initialized; 58 | 59 | ServeMode m_serveMode; 60 | 61 | std::unique_ptr m_threadPool; 62 | 63 | boost::asio::io_context m_ioContext; 64 | 65 | boost::asio::signal_set m_shutdownSignals; 66 | }; 67 | 68 | 69 | } // namespace Server 70 | } // namespace AnnService 71 | 72 | 73 | #endif // _SPTAG_SERVER_SERVICE_H_ 74 | -------------------------------------------------------------------------------- /AnnService/inc/Server/ServiceContext.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_SERVER_SERVICECONTEX_H_ 5 | #define _SPTAG_SERVER_SERVICECONTEX_H_ 6 | 7 | #include "inc/Core/VectorIndex.h" 8 | #include "ServiceSettings.h" 9 | 10 | #include 11 | #include 12 | 13 | namespace SPTAG 14 | { 15 | namespace Service 16 | { 17 | 18 | class ServiceContext 19 | { 20 | public: 21 | ServiceContext(const std::string& p_configFilePath); 22 | 23 | ~ServiceContext(); 24 | 25 | const std::map>& GetIndexMap() const; 26 | 27 | const std::shared_ptr& GetServiceSettings() const; 28 | 29 | bool IsInitialized() const; 30 | 31 | private: 32 | bool m_initialized; 33 | 34 | std::shared_ptr m_settings; 35 | 36 | std::map> m_fullIndexList; 37 | }; 38 | 39 | 40 | } // namespace Server 41 | } // namespace AnnService 42 | 43 | #endif // _SPTAG_SERVER_SERVICECONTEX_H_ 44 | 45 | -------------------------------------------------------------------------------- /AnnService/inc/Server/ServiceSettings.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_SERVER_SERVICESTTINGS_H_ 5 | #define _SPTAG_SERVER_SERVICESTTINGS_H_ 6 | 7 | #include "../Core/Common.h" 8 | 9 | #include 10 | 11 | namespace SPTAG 12 | { 13 | namespace Service 14 | { 15 | 16 | struct ServiceSettings 17 | { 18 | ServiceSettings(); 19 | 20 | std::string m_vectorSeparator; 21 | 22 | std::string m_listenAddr; 23 | 24 | std::string m_listenPort; 25 | 26 | SizeType m_defaultMaxResultNumber; 27 | 28 | SizeType m_threadNum; 29 | 30 | SizeType m_socketThreadNum; 31 | }; 32 | 33 | 34 | 35 | 36 | } // namespace Server 37 | } // namespace AnnService 38 | 39 | 40 | #endif // _SPTAG_SERVER_SERVICESTTINGS_H_ 41 | 42 | -------------------------------------------------------------------------------- /AnnService/inc/Socket/Client.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_SOCKET_CLIENT_H_ 5 | #define _SPTAG_SOCKET_CLIENT_H_ 6 | 7 | #include "inc/Core/Common.h" 8 | #include "Connection.h" 9 | #include "ConnectionManager.h" 10 | #include "Packet.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace SPTAG 18 | { 19 | namespace Socket 20 | { 21 | 22 | class Client 23 | { 24 | public: 25 | typedef std::function ConnectCallback; 26 | 27 | Client(const PacketHandlerMapPtr& p_handlerMap, 28 | std::size_t p_threadNum, 29 | std::uint32_t p_heartbeatIntervalSeconds); 30 | 31 | ~Client(); 32 | 33 | ConnectionID ConnectToServer(const std::string& p_address, 34 | const std::string& p_port, 35 | SPTAG::ErrorCode& p_ec); 36 | 37 | void AsyncConnectToServer(const std::string& p_address, 38 | const std::string& p_port, 39 | ConnectCallback p_callback); 40 | 41 | void SendPacket(ConnectionID p_connection, Packet p_packet, std::function p_callback); 42 | 43 | void SetEventOnConnectionClose(std::function p_event); 44 | 45 | private: 46 | void KeepIoContext(); 47 | 48 | private: 49 | std::atomic_bool m_stopped; 50 | 51 | std::uint32_t m_heartbeatIntervalSeconds; 52 | 53 | boost::asio::io_context m_ioContext; 54 | 55 | boost::asio::deadline_timer m_deadlineTimer; 56 | 57 | std::shared_ptr m_connectionManager; 58 | 59 | std::vector m_threadPool; 60 | 61 | const PacketHandlerMapPtr c_requestHandlerMap; 62 | }; 63 | 64 | 65 | } // namespace Socket 66 | } // namespace SPTAG 67 | 68 | #endif // _SPTAG_SOCKET_CLIENT_H_ 69 | -------------------------------------------------------------------------------- /AnnService/inc/Socket/Common.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_SOCKET_COMMON_H_ 5 | #define _SPTAG_SOCKET_COMMON_H_ 6 | 7 | #include 8 | 9 | namespace SPTAG 10 | { 11 | namespace Socket 12 | { 13 | 14 | typedef std::uint32_t ConnectionID; 15 | 16 | typedef std::uint32_t ResourceID; 17 | 18 | extern const ConnectionID c_invalidConnectionID; 19 | 20 | extern const ResourceID c_invalidResourceID; 21 | 22 | } // namespace Socket 23 | } // namespace SPTAG 24 | 25 | #endif // _SPTAG_SOCKET_COMMON_H_ 26 | -------------------------------------------------------------------------------- /AnnService/inc/Socket/Connection.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_SOCKET_CONNECTION_H_ 5 | #define _SPTAG_SOCKET_CONNECTION_H_ 6 | 7 | #include "Packet.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | namespace SPTAG 18 | { 19 | namespace Socket 20 | { 21 | 22 | class ConnectionManager; 23 | 24 | class Connection : public std::enable_shared_from_this 25 | { 26 | public: 27 | typedef std::shared_ptr Ptr; 28 | 29 | Connection(ConnectionID p_connectionID, 30 | boost::asio::ip::tcp::socket&& p_socket, 31 | const PacketHandlerMapPtr& p_handlerMap, 32 | std::weak_ptr p_connectionManager); 33 | 34 | void Start(); 35 | 36 | void Stop(); 37 | 38 | void StartHeartbeat(std::size_t p_intervalSeconds); 39 | 40 | void AsyncSend(Packet p_packet, std::function p_callback); 41 | 42 | ConnectionID GetConnectionID() const; 43 | 44 | ConnectionID GetRemoteConnectionID() const; 45 | 46 | Connection(const Connection&) = delete; 47 | Connection& operator=(const Connection&) = delete; 48 | 49 | private: 50 | void AsyncReadHeader(); 51 | 52 | void AsyncReadBody(); 53 | 54 | void HandleReadHeader(boost::system::error_code p_ec, std::size_t p_bytesTransferred); 55 | 56 | void HandleReadBody(boost::system::error_code p_ec, std::size_t p_bytesTransferred); 57 | 58 | void SendHeartbeat(std::size_t p_intervalSeconds); 59 | 60 | void SendRegister(); 61 | 62 | void HandleHeartbeatRequest(); 63 | 64 | void HandleRegisterRequest(); 65 | 66 | void HandleRegisterResponse(); 67 | 68 | void HandleNoHandlerResponse(); 69 | 70 | void OnConnectionFail(const boost::system::error_code& p_ec); 71 | 72 | private: 73 | const ConnectionID c_connectionID; 74 | 75 | ConnectionID m_remoteConnectionID; 76 | 77 | const std::weak_ptr c_connectionManager; 78 | 79 | const PacketHandlerMapPtr c_handlerMap; 80 | 81 | boost::asio::ip::tcp::socket m_socket; 82 | 83 | boost::asio::io_context::strand m_strand; 84 | 85 | boost::asio::deadline_timer m_heartbeatTimer; 86 | 87 | std::uint8_t m_packetHeaderReadBuffer[PacketHeader::c_bufferSize]; 88 | 89 | Packet m_packetRead; 90 | 91 | std::atomic_bool m_stopped; 92 | 93 | std::atomic_bool m_heartbeatStarted; 94 | }; 95 | 96 | 97 | } // namespace Socket 98 | } // namespace SPTAG 99 | 100 | #endif // _SPTAG_SOCKET_CONNECTION_H_ 101 | -------------------------------------------------------------------------------- /AnnService/inc/Socket/ConnectionManager.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_SOCKET_CONNECTIONMANAGER_H_ 5 | #define _SPTAG_SOCKET_CONNECTIONMANAGER_H_ 6 | 7 | #include "Connection.h" 8 | #include "inc/Helper/Concurrent.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | namespace SPTAG 19 | { 20 | namespace Socket 21 | { 22 | 23 | class ConnectionManager : public std::enable_shared_from_this 24 | { 25 | public: 26 | ConnectionManager(); 27 | 28 | ConnectionID AddConnection(boost::asio::ip::tcp::socket&& p_socket, 29 | const PacketHandlerMapPtr& p_handlerMap, 30 | std::uint32_t p_heartbeatIntervalSeconds); 31 | 32 | void RemoveConnection(ConnectionID p_connectionID); 33 | 34 | Connection::Ptr GetConnection(ConnectionID p_connectionID); 35 | 36 | void SetEventOnRemoving(std::function p_event); 37 | 38 | void StopAll(); 39 | 40 | private: 41 | inline static std::uint32_t GetPosition(ConnectionID p_connectionID); 42 | 43 | private: 44 | static constexpr std::uint32_t c_connectionPoolSize = 1 << 8; 45 | 46 | static constexpr std::uint32_t c_connectionPoolMask = c_connectionPoolSize - 1; 47 | 48 | struct ConnectionItem 49 | { 50 | ConnectionItem(); 51 | 52 | std::atomic_bool m_isEmpty; 53 | 54 | Connection::Ptr m_connection; 55 | }; 56 | 57 | // Start from 1. 0 means not assigned. 58 | std::atomic m_nextConnectionID; 59 | 60 | std::atomic m_connectionCount; 61 | 62 | std::array m_connections; 63 | 64 | Helper::Concurrent::SpinLock m_spinLock; 65 | 66 | std::function m_eventOnRemoving; 67 | }; 68 | 69 | 70 | } // namespace Socket 71 | } // namespace SPTAG 72 | 73 | #endif // _SPTAG_SOCKET_CONNECTIONMANAGER_H_ 74 | -------------------------------------------------------------------------------- /AnnService/inc/Socket/RemoteSearchQuery.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_SOCKET_REMOTESEARCHQUERY_H_ 5 | #define _SPTAG_SOCKET_REMOTESEARCHQUERY_H_ 6 | 7 | #include "inc/Core/CommonDataStructure.h" 8 | #include "inc/Core/SearchQuery.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace SPTAG 17 | { 18 | namespace Socket 19 | { 20 | 21 | // TODO: use Bond replace below structures. 22 | 23 | struct RemoteQuery 24 | { 25 | static constexpr std::uint16_t MajorVersion() { return 1; } 26 | static constexpr std::uint16_t MirrorVersion() { return 0; } 27 | 28 | enum class QueryType : std::uint8_t 29 | { 30 | String = 0 31 | }; 32 | 33 | RemoteQuery(); 34 | 35 | std::size_t EstimateBufferSize() const; 36 | 37 | std::uint8_t* Write(std::uint8_t* p_buffer) const; 38 | 39 | const std::uint8_t* Read(const std::uint8_t* p_buffer); 40 | 41 | 42 | QueryType m_type; 43 | 44 | std::string m_queryString; 45 | }; 46 | 47 | 48 | struct IndexSearchResult 49 | { 50 | std::string m_indexName; 51 | 52 | QueryResult m_results; 53 | }; 54 | 55 | 56 | struct RemoteSearchResult 57 | { 58 | static constexpr std::uint16_t MajorVersion() { return 1; } 59 | static constexpr std::uint16_t MirrorVersion() { return 0; } 60 | 61 | enum class ResultStatus : std::uint8_t 62 | { 63 | Success = 0, 64 | 65 | Timeout = 1, 66 | 67 | FailedNetwork = 2, 68 | 69 | FailedExecute = 3, 70 | 71 | Dropped = 4 72 | }; 73 | 74 | RemoteSearchResult(); 75 | 76 | RemoteSearchResult(const RemoteSearchResult& p_right); 77 | 78 | RemoteSearchResult(RemoteSearchResult&& p_right); 79 | 80 | RemoteSearchResult& operator=(RemoteSearchResult&& p_right); 81 | 82 | std::size_t EstimateBufferSize() const; 83 | 84 | std::uint8_t* Write(std::uint8_t* p_buffer) const; 85 | 86 | const std::uint8_t* Read(const std::uint8_t* p_buffer); 87 | 88 | 89 | ResultStatus m_status; 90 | 91 | std::vector m_allIndexResults; 92 | }; 93 | 94 | 95 | 96 | } // namespace SPTAG 97 | } // namespace Socket 98 | 99 | #endif // _SPTAG_SOCKET_REMOTESEARCHQUERY_H_ 100 | -------------------------------------------------------------------------------- /AnnService/inc/Socket/Server.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_SOCKET_SERVER_H_ 5 | #define _SPTAG_SOCKET_SERVER_H_ 6 | 7 | #include "Connection.h" 8 | #include "ConnectionManager.h" 9 | #include "Packet.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace SPTAG 16 | { 17 | namespace Socket 18 | { 19 | 20 | class Server 21 | { 22 | public: 23 | Server(const std::string& p_address, 24 | const std::string& p_port, 25 | const PacketHandlerMapPtr& p_handlerMap, 26 | std::size_t p_threadNum); 27 | 28 | ~Server(); 29 | 30 | void StartListen(); 31 | 32 | void SendPacket(ConnectionID p_connection, Packet p_packet, std::function p_callback); 33 | 34 | void SetEventOnConnectionClose(std::function p_event); 35 | 36 | private: 37 | void StartAccept(); 38 | 39 | private: 40 | boost::asio::io_context m_ioContext; 41 | 42 | boost::asio::ip::tcp::acceptor m_acceptor; 43 | 44 | std::shared_ptr m_connectionManager; 45 | 46 | std::vector m_threadPool; 47 | 48 | const PacketHandlerMapPtr m_requestHandlerMap; 49 | }; 50 | 51 | 52 | } // namespace Socket 53 | } // namespace SPTAG 54 | 55 | #endif // _SPTAG_SOCKET_SERVER_H_ 56 | -------------------------------------------------------------------------------- /AnnService/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /AnnService/src/Aggregator/AggregatorExecutionContext.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #include "inc/Aggregator/AggregatorExecutionContext.h" 5 | 6 | using namespace SPTAG; 7 | using namespace SPTAG::Aggregator; 8 | 9 | AggregatorExecutionContext::AggregatorExecutionContext(std::size_t p_totalServerNumber, 10 | Socket::PacketHeader p_requestHeader) 11 | : m_requestHeader(std::move(p_requestHeader)) 12 | { 13 | m_results.clear(); 14 | m_results.resize(p_totalServerNumber); 15 | 16 | m_unfinishedCount = static_cast(p_totalServerNumber); 17 | } 18 | 19 | 20 | AggregatorExecutionContext::~AggregatorExecutionContext() 21 | { 22 | } 23 | 24 | 25 | std::size_t 26 | AggregatorExecutionContext::GetServerNumber() const 27 | { 28 | return m_results.size(); 29 | } 30 | 31 | 32 | AggregatorResult& 33 | AggregatorExecutionContext::GetResult(std::size_t p_num) 34 | { 35 | return m_results[p_num]; 36 | } 37 | 38 | 39 | const Socket::PacketHeader& 40 | AggregatorExecutionContext::GetRequestHeader() const 41 | { 42 | return m_requestHeader; 43 | } 44 | 45 | 46 | bool 47 | AggregatorExecutionContext::IsCompletedAfterFinsh(std::uint32_t p_finishedCount) 48 | { 49 | auto lastCount = m_unfinishedCount.fetch_sub(p_finishedCount); 50 | return lastCount <= p_finishedCount; 51 | } 52 | -------------------------------------------------------------------------------- /AnnService/src/Aggregator/AggregatorSettings.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #include "inc/Aggregator/AggregatorSettings.h" 5 | 6 | using namespace SPTAG; 7 | using namespace SPTAG::Aggregator; 8 | 9 | AggregatorSettings::AggregatorSettings() 10 | : m_searchTimeout(100), 11 | m_threadNum(8), 12 | m_socketThreadNum(8) 13 | { 14 | } 15 | -------------------------------------------------------------------------------- /AnnService/src/Aggregator/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #include "inc/Aggregator/AggregatorService.h" 5 | 6 | SPTAG::Aggregator::AggregatorService g_service; 7 | 8 | int main(int argc, char* argv[]) 9 | { 10 | if (!g_service.Initialize()) 11 | { 12 | return 1; 13 | } 14 | 15 | g_service.Run(); 16 | 17 | return 0; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /AnnService/src/Client/Options.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #include "inc/Client/Options.h" 5 | #include "inc/Helper/StringConvert.h" 6 | 7 | #include 8 | 9 | using namespace SPTAG; 10 | using namespace SPTAG::Client; 11 | 12 | ClientOptions::ClientOptions() 13 | : m_searchTimeout(9000), 14 | m_threadNum(1), 15 | m_socketThreadNum(2) 16 | { 17 | AddRequiredOption(m_serverAddr, "-s", "--server", "Server address."); 18 | AddRequiredOption(m_serverPort, "-p", "--port", "Server port."); 19 | AddOptionalOption(m_searchTimeout, "-t", "", "Search timeout."); 20 | AddOptionalOption(m_threadNum, "-cth", "", "Client Thread Number."); 21 | AddOptionalOption(m_socketThreadNum, "-sth", "", "Socket Thread Number."); 22 | } 23 | 24 | 25 | ClientOptions::~ClientOptions() 26 | { 27 | } 28 | -------------------------------------------------------------------------------- /AnnService/src/Client/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #include "inc/Client/Options.h" 5 | #include "inc/Client/ClientWrapper.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace SPTAG; 12 | 13 | std::unique_ptr g_client; 14 | 15 | int main(int argc, char** argv) 16 | { 17 | SPTAG::Client::ClientOptions options; 18 | if (!options.Parse(argc - 1, argv + 1)) 19 | { 20 | return 1; 21 | } 22 | 23 | g_client.reset(new SPTAG::Client::ClientWrapper(options)); 24 | if (!g_client->IsAvailable()) 25 | { 26 | return 1; 27 | } 28 | 29 | g_client->WaitAllFinished(); 30 | SPTAGLIB_LOG(Helper::LogLevel::LL_Info, "connection done\n"); 31 | 32 | std::string line; 33 | std::cout << "Query: " << std::flush; 34 | while (std::getline(std::cin, line)) 35 | { 36 | if (line.empty()) 37 | { 38 | break; 39 | } 40 | 41 | SPTAG::Socket::RemoteQuery query; 42 | query.m_type = SPTAG::Socket::RemoteQuery::QueryType::String; 43 | query.m_queryString = std::move(line); 44 | 45 | SPTAG::Socket::RemoteSearchResult result; 46 | auto callback = [&result](SPTAG::Socket::RemoteSearchResult p_result) 47 | { 48 | result = std::move(p_result); 49 | }; 50 | 51 | g_client->SendQueryAsync(query, callback, options); 52 | g_client->WaitAllFinished(); 53 | 54 | std::cout << "Status: " << static_cast(result.m_status) << std::endl; 55 | 56 | for (const auto& indexRes : result.m_allIndexResults) 57 | { 58 | std::cout << "Index: " << indexRes.m_indexName << std::endl; 59 | 60 | int idx = 0; 61 | for (const auto& res : indexRes.m_results) 62 | { 63 | std::cout << "------------------" << std::endl; 64 | std::cout << "DocIndex: " << res.VID << " Distance: " << res.Dist; 65 | if (indexRes.m_results.WithMeta()) 66 | { 67 | const auto& metadata = indexRes.m_results.GetMetadata(idx); 68 | std::cout << " MetaData: " << std::string((char*)metadata.Data(), metadata.Length()); 69 | } 70 | std::cout << std::endl; 71 | ++idx; 72 | } 73 | } 74 | 75 | std::cout << "Query: " << std::flush; 76 | } 77 | 78 | return 0; 79 | } 80 | 81 | -------------------------------------------------------------------------------- /AnnService/src/Core/Common/CommonUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "inc/Core/Common/CommonUtils.h" 2 | #include "inc/Core/Common/DistanceUtils.h" 3 | 4 | using namespace SPTAG; 5 | using namespace SPTAG::COMMON; 6 | 7 | 8 | #define DefineVectorValueType(Name, Type) template int Utils::GetBase(); 9 | #include "inc/Core/DefinitionList.h" 10 | #undef DefineVectorValueType 11 | 12 | template 13 | void Utils::BatchNormalize(T* data, SizeType row, DimensionType col, int base, int threads) 14 | { 15 | #pragma omp parallel for num_threads(threads) 16 | for (SizeType i = 0; i < row; i++) 17 | { 18 | SPTAG::COMMON::Utils::Normalize(data + i * (size_t)col, col, base); 19 | } 20 | } 21 | 22 | #define DefineVectorValueType(Name, Type) template void Utils::BatchNormalize(Type* data, SizeType row, DimensionType col, int base, int threads); 23 | #include "inc/Core/DefinitionList.h" 24 | #undef DefineVectorValueType -------------------------------------------------------------------------------- /AnnService/src/Core/Common/NeighborhoodGraph.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #include "inc/Core/Common/NeighborhoodGraph.h" 5 | #include "inc/Core/Common/KNearestNeighborhoodGraph.h" 6 | #include "inc/Core/Common/RelativeNeighborhoodGraph.h" 7 | 8 | using namespace SPTAG::COMMON; 9 | 10 | std::shared_ptr NeighborhoodGraph::CreateInstance(std::string type) 11 | { 12 | std::shared_ptr res; 13 | if (type == "RNG") 14 | { 15 | res.reset(new RelativeNeighborhoodGraph); 16 | } 17 | else if (type == "NNG") 18 | { 19 | res.reset(new KNearestNeighborhoodGraph); 20 | } 21 | return res; 22 | } -------------------------------------------------------------------------------- /AnnService/src/Core/ResultIterator.cpp: -------------------------------------------------------------------------------- 1 | #include "inc/Core/ResultIterator.h" 2 | 3 | 4 | 5 | struct UniqueHandler { 6 | std::unique_ptr m_handler; 7 | }; 8 | 9 | ResultIterator::ResultIterator(const void* p_index, const void* p_target, bool p_searchDeleted, int p_workspaceBatch) 10 | :m_index((const VectorIndex*)p_index), 11 | m_target(p_target), 12 | m_searchDeleted(p_searchDeleted) 13 | { 14 | m_workspace = new UniqueHandler; 15 | ((UniqueHandler*)m_workspace)->m_handler = std::move(m_index->RentWorkSpace(p_workspaceBatch)); 16 | m_isFirstResult = true; 17 | } 18 | 19 | ResultIterator::~ResultIterator() 20 | { 21 | Close(); 22 | } 23 | 24 | void* ResultIterator::GetWorkSpace() 25 | { 26 | if (m_workspace == nullptr) return nullptr; 27 | return (((UniqueHandler*)m_workspace)->m_handler).get(); 28 | } 29 | 30 | std::shared_ptr ResultIterator::Next(int batch) 31 | { 32 | if (m_queryResult == nullptr) { 33 | m_queryResult = std::make_unique(m_target, batch, true); 34 | } 35 | else if (batch <= m_queryResult->GetResultNum()) { 36 | m_queryResult->SetResultNum(batch); 37 | } 38 | else { 39 | batch = m_queryResult->GetResultNum(); 40 | } 41 | 42 | m_queryResult->Reset(); 43 | if (m_workspace == nullptr) return m_queryResult; 44 | 45 | int resultCount = 0; 46 | m_index->SearchIndexIterativeNext(*m_queryResult, (((UniqueHandler*)m_workspace)->m_handler).get(), batch, resultCount, m_isFirstResult, m_searchDeleted); 47 | m_isFirstResult = false; 48 | for (int i = 0; i < resultCount; i++) 49 | { 50 | m_queryResult->GetResult(i)->RelaxedMono = (((UniqueHandler*)m_workspace)->m_handler)->m_relaxedMono; 51 | } 52 | m_queryResult->SetResultNum(resultCount); 53 | return m_queryResult; 54 | } 55 | 56 | bool ResultIterator::GetRelaxedMono() 57 | { 58 | if (m_workspace == nullptr) return false; 59 | 60 | return (((UniqueHandler*)m_workspace)->m_handler)->m_relaxedMono; 61 | } 62 | 63 | // Add end into destructor. 64 | void ResultIterator::Close() 65 | { 66 | if (m_workspace != nullptr) { 67 | m_index->SearchIndexIterativeEnd(std::move(((UniqueHandler*)m_workspace)->m_handler)); 68 | delete m_workspace; 69 | m_workspace = nullptr; 70 | } 71 | } 72 | 73 | const void* ResultIterator::GetTarget() 74 | { 75 | return m_target; 76 | } 77 | // namespace SPTAG 78 | -------------------------------------------------------------------------------- /AnnService/src/Core/SPANNResultIterator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | #include "inc/Core/SPANNResultIterator.h" 3 | 4 | namespace SPTAG 5 | { 6 | namespace SPANN 7 | { 8 | template 9 | SPANNResultIterator::SPANNResultIterator(const Index* p_index, const void* p_target, 10 | std::shared_ptr headWorkspace, 11 | std::shared_ptr extraWorkspace, 12 | int batch) 13 | :m_index(p_index), 14 | m_target(p_target), 15 | m_headWorkspace(headWorkspace), 16 | m_extraWorkspace(extraWorkspace), 17 | m_batch(batch) 18 | { 19 | m_headQueryResult = std::make_unique(p_target, batch, false); 20 | m_queryResult = std::make_unique(p_target, 1, true); 21 | m_isFirstResult = true; 22 | } 23 | 24 | template 25 | SPANNResultIterator::~SPANNResultIterator() 26 | { 27 | if (m_index != nullptr && m_headWorkspace != nullptr && m_extraWorkspace != nullptr) { 28 | m_index->SearchIndexIterativeEnd(m_headWorkspace, m_extraWorkspace); 29 | } 30 | m_headQueryResult = nullptr; 31 | m_queryResult = nullptr; 32 | } 33 | 34 | template 35 | bool SPANNResultIterator::Next(BasicResult& result) 36 | { 37 | m_queryResult->Reset(); 38 | m_index->SearchIndexIterativeNext(*m_headQueryResult, *m_queryResult, m_headWorkspace, m_extraWorkspace, m_isFirstResult); 39 | m_isFirstResult = false; 40 | if (m_queryResult->GetResult(0) == nullptr || m_queryResult->GetResult(0)->VID < 0) 41 | { 42 | return false; 43 | } 44 | result.VID = m_queryResult->GetResult(0)->VID; 45 | result.Dist = m_queryResult->GetResult(0)->Dist; 46 | result.Meta = m_queryResult->GetResult(0)->Meta; 47 | return true; 48 | } 49 | 50 | // Add end into destructor. 51 | template 52 | void SPANNResultIterator::Close() 53 | { 54 | if (m_headWorkspace != nullptr && m_extraWorkspace != nullptr) { 55 | m_index->SearchIndexIterativeEnd(m_headWorkspace, m_extraWorkspace); 56 | m_headWorkspace = nullptr; 57 | m_extraWorkspace = nullptr; 58 | } 59 | } 60 | 61 | template 62 | QueryResult* SPANNResultIterator::GetQuery() const 63 | { 64 | return m_queryResult.get(); 65 | } 66 | } // namespace SPANN 67 | } // namespace SPTAG 68 | */ 69 | -------------------------------------------------------------------------------- /AnnService/src/Helper/ArgumentsParser.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #include "inc/Helper/ArgumentsParser.h" 5 | 6 | using namespace SPTAG::Helper; 7 | 8 | 9 | ArgumentsParser::IArgument::IArgument() 10 | { 11 | } 12 | 13 | 14 | ArgumentsParser::IArgument::~IArgument() 15 | { 16 | } 17 | 18 | 19 | ArgumentsParser::ArgumentsParser() 20 | { 21 | } 22 | 23 | 24 | ArgumentsParser::~ArgumentsParser() 25 | { 26 | } 27 | 28 | 29 | bool 30 | ArgumentsParser::Parse(int p_argc, char** p_args) 31 | { 32 | while (p_argc > 0) 33 | { 34 | int last = p_argc; 35 | for (auto& option : m_arguments) 36 | { 37 | if (!option->ParseValue(p_argc, p_args)) 38 | { 39 | SPTAGLIB_LOG(Helper::LogLevel::LL_Empty, "Failed to parse args around \"%s\"\n", *p_args); 40 | PrintHelp(); 41 | return false; 42 | } 43 | } 44 | 45 | if (last == p_argc) 46 | { 47 | p_argc -= 1; 48 | p_args += 1; 49 | } 50 | } 51 | 52 | bool isValid = true; 53 | for (auto& option : m_arguments) 54 | { 55 | if (option->IsRequiredButNotSet()) 56 | { 57 | SPTAGLIB_LOG(Helper::LogLevel::LL_Empty, "Required option not set:\n "); 58 | option->PrintDescription(); 59 | SPTAGLIB_LOG(Helper::LogLevel::LL_Empty, "\n"); 60 | isValid = false; 61 | } 62 | } 63 | 64 | if (!isValid) 65 | { 66 | SPTAGLIB_LOG(Helper::LogLevel::LL_Empty, "\n"); 67 | PrintHelp(); 68 | return false; 69 | } 70 | 71 | return true; 72 | } 73 | 74 | 75 | void 76 | ArgumentsParser::PrintHelp() 77 | { 78 | SPTAGLIB_LOG(Helper::LogLevel::LL_Empty, "Usage: "); 79 | for (auto& option : m_arguments) 80 | { 81 | SPTAGLIB_LOG(Helper::LogLevel::LL_Empty, "\n "); 82 | option->PrintDescription(); 83 | } 84 | 85 | SPTAGLIB_LOG(Helper::LogLevel::LL_Empty, "\n\n"); 86 | } 87 | -------------------------------------------------------------------------------- /AnnService/src/Helper/Concurrent.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #include "inc/Helper/Concurrent.h" 5 | 6 | using namespace SPTAG; 7 | using namespace SPTAG::Helper::Concurrent; 8 | 9 | WaitSignal::WaitSignal() 10 | : m_isWaiting(false), 11 | m_unfinished(0) 12 | { 13 | } 14 | 15 | 16 | WaitSignal::WaitSignal(std::uint32_t p_unfinished) 17 | : m_isWaiting(false), 18 | m_unfinished(p_unfinished) 19 | { 20 | } 21 | 22 | 23 | WaitSignal::~WaitSignal() 24 | { 25 | std::lock_guard guard(m_mutex); 26 | if (m_isWaiting) 27 | { 28 | m_cv.notify_all(); 29 | } 30 | } 31 | 32 | 33 | void 34 | WaitSignal::Reset(std::uint32_t p_unfinished) 35 | { 36 | std::lock_guard guard(m_mutex); 37 | if (m_isWaiting) 38 | { 39 | m_cv.notify_all(); 40 | } 41 | 42 | m_isWaiting = false; 43 | m_unfinished = p_unfinished; 44 | } 45 | 46 | 47 | void 48 | WaitSignal::Wait() 49 | { 50 | std::unique_lock lock(m_mutex); 51 | if (m_unfinished > 0) 52 | { 53 | m_isWaiting = true; 54 | m_cv.wait(lock); 55 | } 56 | } 57 | 58 | 59 | void 60 | WaitSignal::FinishOne() 61 | { 62 | if (1 == m_unfinished.fetch_sub(1)) 63 | { 64 | std::lock_guard guard(m_mutex); 65 | if (m_isWaiting) 66 | { 67 | m_isWaiting = false; 68 | m_cv.notify_all(); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /AnnService/src/Helper/DynamicNeighbors.cpp: -------------------------------------------------------------------------------- 1 | #include "inc/Helper/DynamicNeighbors.h" 2 | #include "inc/Core/Common.h" 3 | 4 | using namespace SPTAG::Helper; 5 | 6 | DynamicNeighbors::DynamicNeighbors(const int* p_data, const int p_length) 7 | : c_data(p_data), 8 | c_length(p_length) 9 | { 10 | } 11 | 12 | 13 | DynamicNeighbors:: ~DynamicNeighbors() 14 | { 15 | } 16 | 17 | 18 | int 19 | DynamicNeighbors::operator[](const int p_id) const 20 | { 21 | if (p_id < c_length && p_id >= 0) 22 | { 23 | return c_data[p_id]; 24 | } 25 | 26 | return -1; 27 | } 28 | 29 | 30 | int 31 | DynamicNeighbors::Size() const 32 | { 33 | return c_length; 34 | } 35 | 36 | 37 | DynamicNeighborsSet::DynamicNeighborsSet(const char* p_filePath) 38 | { 39 | auto fp = f_createIO(); 40 | if (fp == nullptr || !fp->Initialize(p_filePath, std::ios::binary | std::ios::in)) { 41 | SPTAGLIB_LOG(Helper::LogLevel::LL_Error, "Failed open graph file: %s\n", p_filePath); 42 | throw std::runtime_error("Opening graph file failed"); 43 | } 44 | 45 | if (fp->ReadBinary(sizeof(m_vectorCount), (char*)&m_vectorCount) != sizeof(m_vectorCount)) { 46 | SPTAGLIB_LOG(Helper::LogLevel::LL_Error, "Failed to read DynamicNeighborsSet!\n"); 47 | throw std::runtime_error("reading DynamicNeighborsSet failed"); 48 | } 49 | 50 | m_neighborOffset.reset(new int[m_vectorCount + 1]); 51 | m_neighborOffset[0] = 0; 52 | if (fp->ReadBinary(m_vectorCount * sizeof(int), (char*)(m_neighborOffset.get() + 1)) != m_vectorCount * sizeof(int)) { 53 | SPTAGLIB_LOG(Helper::LogLevel::LL_Error, "Failed to read DynamicNeighborsSet!\n"); 54 | throw std::runtime_error("reading DynamicNeighborsSet failed"); 55 | } 56 | 57 | size_t graphSize = static_cast(m_neighborOffset[m_vectorCount]); 58 | SPTAGLIB_LOG(Helper::LogLevel::LL_Error, "Vector count: %d, Graph size: %zu\n", m_vectorCount, graphSize); 59 | 60 | m_data.reset(new int[graphSize]); 61 | auto readSize = fp->ReadBinary(graphSize * sizeof(int), (char*)(m_data.get())); 62 | if (readSize != graphSize * sizeof(int)) { 63 | SPTAGLIB_LOG(Helper::LogLevel::LL_Error, 64 | "Failed read graph: size not match, expected %zu, actually %zu\n", 65 | static_cast(graphSize * sizeof(int)), 66 | static_cast(readSize)); 67 | throw std::runtime_error("Graph size doesn't match expected"); 68 | } 69 | } 70 | 71 | 72 | DynamicNeighborsSet::~DynamicNeighborsSet() 73 | { 74 | } 75 | 76 | 77 | DynamicNeighbors DynamicNeighborsSet::operator[](const int p_id) const 78 | { 79 | if (p_id >= m_vectorCount) 80 | { 81 | return DynamicNeighbors(nullptr, 0); 82 | } 83 | 84 | return DynamicNeighbors(m_data.get() + static_cast(m_neighborOffset[p_id]), 85 | m_neighborOffset[p_id + 1] - m_neighborOffset[p_id]); 86 | } 87 | -------------------------------------------------------------------------------- /AnnService/src/Helper/VectorSetReader.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #include "inc/Helper/VectorSetReader.h" 5 | #include "inc/Helper/VectorSetReaders/DefaultReader.h" 6 | #include "inc/Helper/VectorSetReaders/TxtReader.h" 7 | #include "inc/Helper/VectorSetReaders/XvecReader.h" 8 | 9 | using namespace SPTAG; 10 | using namespace SPTAG::Helper; 11 | 12 | 13 | ReaderOptions::ReaderOptions(VectorValueType p_valueType, DimensionType p_dimension, VectorFileType p_fileType, std::string p_vectorDelimiter, std::uint32_t p_threadNum, bool p_normalized) 14 | : m_inputValueType(p_valueType), m_dimension(p_dimension), m_inputFileType(p_fileType), m_vectorDelimiter(p_vectorDelimiter), m_threadNum(p_threadNum), m_normalized(p_normalized) 15 | { 16 | AddOptionalOption(m_threadNum, "-t", "--thread", "Thread Number."); 17 | AddOptionalOption(m_vectorDelimiter, "-dl", "--delimiter", "Vector delimiter."); 18 | AddOptionalOption(m_normalized, "-norm", "--normalized", "Vector is normalized."); 19 | AddRequiredOption(m_dimension, "-d", "--dimension", "Dimension of vector."); 20 | AddRequiredOption(m_inputValueType, "-v", "--vectortype", "Input vector data type. Default is float."); 21 | AddRequiredOption(m_inputFileType, "-f", "--filetype", "Input file type (DEFAULT, TXT, XVEC). Default is DEFAULT."); 22 | } 23 | 24 | 25 | ReaderOptions::~ReaderOptions() 26 | { 27 | } 28 | 29 | 30 | VectorSetReader::VectorSetReader(std::shared_ptr p_options) 31 | : m_options(p_options) 32 | { 33 | } 34 | 35 | 36 | VectorSetReader:: ~VectorSetReader() 37 | { 38 | } 39 | 40 | 41 | std::shared_ptr 42 | VectorSetReader::CreateInstance(std::shared_ptr p_options) 43 | { 44 | if (p_options->m_inputFileType == VectorFileType::DEFAULT) { 45 | return std::make_shared(p_options); 46 | } 47 | else if (p_options->m_inputFileType == VectorFileType::TXT) { 48 | return std::make_shared(p_options); 49 | } 50 | else if (p_options->m_inputFileType == VectorFileType::XVEC) { 51 | return std::make_shared(p_options); 52 | } 53 | return nullptr; 54 | } 55 | 56 | 57 | -------------------------------------------------------------------------------- /AnnService/src/Server/ServiceContext.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #include "inc/Server/ServiceContext.h" 5 | #include "inc/Helper/SimpleIniReader.h" 6 | #include "inc/Helper/CommonHelper.h" 7 | #include "inc/Helper/StringConvert.h" 8 | 9 | using namespace SPTAG; 10 | using namespace SPTAG::Service; 11 | 12 | 13 | ServiceContext::ServiceContext(const std::string& p_configFilePath) 14 | : m_initialized(false) 15 | { 16 | Helper::IniReader iniReader; 17 | if (ErrorCode::Success != iniReader.LoadIniFile(p_configFilePath)) 18 | { 19 | return; 20 | } 21 | 22 | m_settings.reset(new ServiceSettings); 23 | 24 | m_settings->m_listenAddr = iniReader.GetParameter("Service", "ListenAddr", std::string("0.0.0.0")); 25 | m_settings->m_listenPort = iniReader.GetParameter("Service", "ListenPort", std::string("8000")); 26 | m_settings->m_threadNum = iniReader.GetParameter("Service", "ThreadNumber", static_cast(8)); 27 | m_settings->m_socketThreadNum = iniReader.GetParameter("Service", "SocketThreadNumber", static_cast(8)); 28 | 29 | m_settings->m_defaultMaxResultNumber = iniReader.GetParameter("QueryConfig", "DefaultMaxResultNumber", static_cast(10)); 30 | m_settings->m_vectorSeparator = iniReader.GetParameter("QueryConfig", "DefaultSeparator", std::string("|")); 31 | 32 | const std::string emptyStr; 33 | 34 | std::string indexListStr = iniReader.GetParameter("Index", "List", emptyStr); 35 | const auto& indexList = Helper::StrUtils::SplitString(indexListStr, ","); 36 | 37 | for (const auto& indexName : indexList) 38 | { 39 | std::string sectionName("Index_"); 40 | sectionName += indexName.c_str(); 41 | if (!iniReader.DoesParameterExist(sectionName, "IndexFolder")) 42 | { 43 | continue; 44 | } 45 | 46 | std::string indexFolder = iniReader.GetParameter(sectionName, "IndexFolder", emptyStr); 47 | 48 | std::shared_ptr vectorIndex; 49 | if (ErrorCode::Success == VectorIndex::LoadIndex(indexFolder, vectorIndex)) 50 | { 51 | vectorIndex->SetIndexName(indexName); 52 | m_fullIndexList.emplace(indexName, vectorIndex); 53 | } 54 | else 55 | { 56 | SPTAGLIB_LOG(Helper::LogLevel::LL_Error, "Failed loading index: %s\n", indexName.c_str()); 57 | } 58 | } 59 | 60 | m_initialized = true; 61 | } 62 | 63 | 64 | ServiceContext::~ServiceContext() 65 | { 66 | 67 | } 68 | 69 | 70 | const std::map>& 71 | ServiceContext::GetIndexMap() const 72 | { 73 | return m_fullIndexList; 74 | } 75 | 76 | 77 | const std::shared_ptr& 78 | ServiceContext::GetServiceSettings() const 79 | { 80 | return m_settings; 81 | } 82 | 83 | 84 | bool 85 | ServiceContext::IsInitialized() const 86 | { 87 | return m_initialized; 88 | } 89 | -------------------------------------------------------------------------------- /AnnService/src/Server/ServiceSettings.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #include "inc/Server/ServiceSettings.h" 5 | 6 | using namespace SPTAG; 7 | using namespace SPTAG::Service; 8 | 9 | 10 | ServiceSettings::ServiceSettings() 11 | : m_defaultMaxResultNumber(10), 12 | m_threadNum(12) 13 | { 14 | } 15 | -------------------------------------------------------------------------------- /AnnService/src/Server/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #include "inc/Server/SearchService.h" 5 | 6 | SPTAG::Service::SearchService g_service; 7 | 8 | int main(int argc, char* argv[]) 9 | { 10 | if (!g_service.Initialize(argc, argv)) 11 | { 12 | return 1; 13 | } 14 | 15 | g_service.Run(); 16 | 17 | return 0; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /AnnService/src/Socket/Common.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #include "inc/Socket/Common.h" 5 | 6 | 7 | using namespace SPTAG::Socket; 8 | 9 | const ConnectionID SPTAG::Socket::c_invalidConnectionID = 0; 10 | 11 | const ResourceID SPTAG::Socket::c_invalidResourceID = 0; 12 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/oss/mirror/docker.io/library/ubuntu:20.04 2 | WORKDIR /app 3 | 4 | ENV DEBIAN_FRONTEND=noninteractive 5 | 6 | RUN apt-get update && apt-get -y install wget build-essential swig cmake git libnuma-dev python3.8-dev python3-distutils gcc-8 g++-8 \ 7 | libboost-filesystem-dev libboost-test-dev libboost-serialization-dev libboost-regex-dev libboost-serialization-dev libboost-regex-dev libboost-thread-dev libboost-system-dev 8 | 9 | RUN wget https://bootstrap.pypa.io/get-pip.py && python3.8 get-pip.py && python3.8 -m pip install numpy 10 | 11 | ENV PYTHONPATH=/app/Release 12 | 13 | COPY CMakeLists.txt ./ 14 | COPY AnnService ./AnnService/ 15 | COPY Test ./Test/ 16 | COPY Wrappers ./Wrappers/ 17 | COPY GPUSupport ./GPUSupport/ 18 | COPY ThirdParty ./ThirdParty/ 19 | 20 | RUN export CC=/usr/bin/gcc-8 && export CXX=/usr/bin/g++-8 && mkdir build && cd build && cmake .. && make -j && cd .. 21 | -------------------------------------------------------------------------------- /Dockerfile.cuda: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/mirror/nvcr/nvidia/cuda:11.8.0-base-ubuntu20.04 2 | WORKDIR /app 3 | 4 | ENV DEBIAN_FRONTEND=noninteractive 5 | 6 | RUN apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/3bf863cc.pub 7 | 8 | RUN apt-get -y install wget build-essential swig cmake git libnuma-dev python3.8-dev python3-distutils gcc-8 g++-8 \ 9 | libboost-filesystem-dev libboost-test-dev libboost-serialization-dev libboost-regex-dev libboost-serialization-dev libboost-regex-dev libboost-thread-dev libboost-system-dev 10 | 11 | RUN wget https://bootstrap.pypa.io/get-pip.py && python3.8 get-pip.py && python3.8 -m pip install numpy 12 | 13 | RUN git clone https://github.com/NVIDIA/cub && cd cub && git checkout c3cceac && cp -r cub /usr/include/ && cd .. 14 | 15 | RUN wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-ubuntu2004.pin && mv cuda-ubuntu2004.pin /etc/apt/preferences.d/cuda-repository-pin-600 \ 16 | && wget https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda-repo-ubuntu2004-11-8-local_11.8.0-520.61.05-1_amd64.deb \ 17 | && dpkg -i cuda-repo-ubuntu2004-11-8-local_11.8.0-520.61.05-1_amd64.deb && cp /var/cuda-repo-ubuntu2004-11-8-local/cuda-*-keyring.gpg /usr/share/keyrings/ \ 18 | && apt-get update && apt-get install -y cuda-toolkit-11-8 19 | 20 | LABEL com.nvidia.volumes.needed="nvidia_driver" 21 | LABEL com.nvidia.cuda.version="11.8.0" 22 | 23 | ENV PATH /usr/local/nvidia/bin:/usr/local/cuda/bin:${PATH} 24 | ENV LD_LIBRARY_PATH /usr/local/cuda/lib64:/usr/local/nvidia/lib:/usr/local/nvidia/lib64:${LD_LIBRARY_PATH} 25 | 26 | ENV NVIDIA_VISIBLE_DEVICES all 27 | ENV NVIDIA_DRIVER_CAPABILITIES compute,utility 28 | ENV NVIDIA_REQUIRE_CUDA "cuda>=11.0" 29 | 30 | 31 | ENV PYTHONPATH=/app/Release 32 | 33 | COPY CMakeLists.txt ./ 34 | COPY AnnService ./AnnService/ 35 | COPY Test ./Test/ 36 | COPY Wrappers ./Wrappers/ 37 | COPY GPUSupport ./GPUSupport/ 38 | COPY ThirdParty ./ThirdParty/ 39 | 40 | RUN export CC=/usr/bin/gcc-8 && export CXX=/usr/bin/g++-8 && mkdir build && cd build && cmake .. && make -j && cd .. 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include sptag *.py _SPTAG* *.so *.dll Server.exe server -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /SPTAG.WinRT.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SPTAG.WinRT 5 | 1.2.13-mainOPQ-CoreLib-SPANN-withsource-a6b7604 6 | SPTAG.WinRT 7 | cheqi,haidwa,mingqli 8 | cheqi,haidwa,mingqli,zhah 9 | false 10 | https://github.com/microsoft/SPTAG 11 | https://github.com/microsoft/SPTAG 12 | SPTAG (Space Partition Tree And Graph) is a library for large scale vector approximate nearest neighbor search scenario released by Microsoft Research (MSR) and Microsoft Bing. 13 | publish with commit microsoft/add python version in wheel package/a6b7604 14 | Copyright © Microsoft 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /SPTAG.sdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/SPTAG/4ecf2495eb6187b555c0a6ee7d3b5394d5362183/SPTAG.sdf -------------------------------------------------------------------------------- /SPTAG.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | x64 6 | <_nugetNativeFolder>$(MSBuildThisFileDirectory)..\runtimes\win-$(Native-Platform)\native\ 7 | 8 | 9 | 10 | 11 | %(FileName)%(Extension) 12 | PreserveNewest 13 | 14 | 15 | -------------------------------------------------------------------------------- /Test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation. All rights reserved. 2 | # Licensed under the MIT License. 3 | 4 | if (NOT LIBRARYONLY) 5 | if(NOT WIN32) 6 | ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK) 7 | message (STATUS "BOOST_TEST_DYN_LINK") 8 | endif() 9 | 10 | find_package(Boost 1.66 COMPONENTS system thread serialization wserialization regex filesystem unit_test_framework) 11 | if (Boost_FOUND) 12 | include_directories (${Boost_INCLUDE_DIR}) 13 | link_directories (${Boost_LIBRARY_DIR}) 14 | message (STATUS "Found Boost.") 15 | message (STATUS "Include Path: ${Boost_INCLUDE_DIRS}") 16 | message (STATUS "Library Path: ${Boost_LIBRARY_DIRS}") 17 | message (STATUS "Library: ${Boost_LIBRARIES}") 18 | else() 19 | message (FATAL_ERROR "Could not find Boost 1.67!") 20 | endif() 21 | 22 | include_directories(${PROJECT_SOURCE_DIR}/AnnService ${PROJECT_SOURCE_DIR}/Test) 23 | 24 | file(GLOB TEST_HDR_FILES ${PROJECT_SOURCE_DIR}/Test/inc/Test.h) 25 | file(GLOB TEST_SRC_FILES ${PROJECT_SOURCE_DIR}/Test/src/*.cpp) 26 | add_executable(SPTAGTest ${TEST_SRC_FILES} ${TEST_HDR_FILES}) 27 | target_link_libraries(SPTAGTest SPTAGLibStatic ssdservingLib ${Boost_LIBRARIES}) 28 | 29 | install(TARGETS SPTAGTest 30 | RUNTIME DESTINATION bin 31 | ARCHIVE DESTINATION lib 32 | LIBRARY DESTINATION lib) 33 | endif() 34 | -------------------------------------------------------------------------------- /Test/Test.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | Source Files 53 | 54 | 55 | Source Files 56 | 57 | 58 | Source Files 59 | 60 | 61 | Source Files 62 | 63 | 64 | Source Files 65 | 66 | 67 | 68 | 69 | Header Files 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /Test/WinRTTest/WinRTTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | extern "C" __declspec(dllexport) winrt::SPTAG::LogLevel SPTAG_GetLoggerLevel() { return winrt::SPTAG::LogLevel::Empty; } 10 | 11 | using namespace winrt; 12 | using namespace Windows::Security::Cryptography; 13 | using namespace Windows::Data::Json; 14 | 15 | JsonObject CreateJsonObject(bool v) { auto js = JsonObject{}; js.Insert(L"value", JsonValue::CreateBooleanValue(v)); return js; } 16 | JsonObject CreateJsonObject(std::wstring_view v) { auto js = JsonObject{}; js.Insert(L"value", JsonValue::CreateStringValue(v)); return js; } 17 | template JsonObject CreateJsonObject(const wchar_t(&v)[N]) { return CreateJsonObject(winrt::hstring(v)); } 18 | JsonObject CreateJsonObject(double v) { auto js = JsonObject{}; js.Insert(L"value", JsonValue::CreateNumberValue(v)); return js; } 19 | JsonObject CreateJsonObject(nullptr_t) { auto js = JsonObject{}; js.Insert(L"value", JsonValue::CreateNullValue()); return js; } 20 | 21 | template 22 | winrt::array_view Serialize(const T& value) { 23 | JsonObject json = CreateJsonObject(value); 24 | auto str = json.Stringify(); 25 | auto ibuffer = CryptographicBuffer::ConvertStringToBinary(str, BinaryStringEncoding::Utf16LE); 26 | auto start = ibuffer.data(); 27 | winrt::com_array _array(start, start + ibuffer.Length()); 28 | return _array; 29 | } 30 | 31 | winrt::hstring Deserialize(winrt::array_view v) { 32 | std::wstring_view sv { reinterpret_cast(v.begin()), v.size() / sizeof(wchar_t) }; 33 | std::wstring wstr {sv}; 34 | JsonObject js; 35 | if (JsonObject::TryParse(wstr, js)) { 36 | auto value = js.GetNamedValue(L"value"); 37 | return value.Stringify(); 38 | } else { 39 | return winrt::hstring{ wstr }; 40 | } 41 | } 42 | 43 | int main() 44 | { 45 | SPTAG::AnnIndex idx; 46 | using embedding_t = std::array; 47 | auto b = CryptographicBuffer::ConvertStringToBinary(L"first one", BinaryStringEncoding::Utf16LE); 48 | idx.AddWithMetadata(embedding_t{ 1, 0 }, winrt::com_array(b.data(), b.data() + b.Length())); 49 | idx.AddWithMetadata(embedding_t{ 0, 1, 0 }, Serialize(L"second one")); 50 | idx.AddWithMetadata(embedding_t{ 0, 0.5f, 0.7f, 0 }, Serialize(3.14)); 51 | idx.AddWithMetadata(embedding_t{ 0, 0.7f, 0.5f, 0 }, Serialize(true)); 52 | idx.AddWithMetadata(embedding_t{ 0, 0.7f, 0.8f, 0 }, Serialize(L"fifth")); 53 | 54 | auto res = idx.Search(embedding_t{ 0.f, 0.99f, 0.01f }, 12); 55 | for (const winrt::SPTAG::SearchResult& r : res) { 56 | std::wcout << Deserialize(r.Metadata()); 57 | std::wcout << L" -- " << r.Distance() << L"\n"; 58 | } 59 | 60 | auto folder = winrt::Windows::Storage::KnownFolders::DocumentsLibrary(); 61 | auto file = folder.CreateFileAsync(L"vector_index", winrt::Windows::Storage::CreationCollisionOption::ReplaceExisting).get(); 62 | idx.Save(file); 63 | 64 | SPTAG::AnnIndex idx2; 65 | idx2.Load(file); 66 | 67 | } 68 | 69 | -------------------------------------------------------------------------------- /Test/WinRTTest/WinRTTest.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Test/WinRTTest/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Test/cuda/common.hxx: -------------------------------------------------------------------------------- 1 | //#include "inc/Core/Common/cuda/KNN.hxx" 2 | #include 3 | #include 4 | 5 | #define CHECK_ERRS(errs) \ 6 | if(errs > 0) { \ 7 | SPTAGLIB_LOG(SPTAG::Helper::LogLevel::LL_Info, "%d errors found\n", errs); \ 8 | } 9 | 10 | #define CHECK_VAL(val,exp,errs) \ 11 | if(val != exp) { \ 12 | errs++; \ 13 | SPTAGLIB_LOG(SPTAG::Helper::LogLevel::LL_Error, "%s != %s\n",#val,#exp); \ 14 | } 15 | 16 | #define CHECK_VAL_LT(val,exp,errs) \ 17 | if(val > exp) { \ 18 | errs++; \ 19 | SPTAGLIB_LOG(SPTAG::Helper::LogLevel::LL_Error, "%s > %s\n",#val,#exp); \ 20 | } 21 | 22 | #define GPU_CHECK_VAL(val,exp,dtype,errs) \ 23 | dtype temp; \ 24 | CUDA_CHECK(cudaMemcpy(&temp, val, sizeof(dtype), cudaMemcpyDeviceToHost)); \ 25 | float eps = 0.01; \ 26 | if((float)temp>0.0 && ((float)temp*(1.0+eps) < (float)(exp) || (float)temp*(1.0-eps) > (float)(exp))) { \ 27 | errs++; \ 28 | SPTAGLIB_LOG(SPTAG::Helper::LogLevel::LL_Error, "%s != %s\n",#val,#exp); \ 29 | } 30 | 31 | 32 | template 33 | T* create_dataset(size_t rows, int dim) { 34 | 35 | srand(0); 36 | T* h_data = new T[rows*dim]; 37 | for(size_t i=0; i::value) { 39 | h_data[i] = (rand()/(float)RAND_MAX); 40 | } 41 | else if(std::is_same::value) { 42 | h_data[i] = static_cast((rand()%INT_MAX)); 43 | } 44 | else if(std::is_same::value) { 45 | h_data[i] = static_cast((rand()%127)); 46 | } 47 | else if(std::is_same::value) { 48 | h_data[i] = static_cast((rand()%127)); 49 | } 50 | } 51 | return h_data; 52 | } 53 | /* 54 | __global__ void count_leaf_sizes(LeafNode* leafs, int* node_ids, int N, int internal_nodes); 55 | __global__ void assign_leaf_points_in_batch(LeafNode* leafs, int* leaf_points, int* node_ids, int N, int internal_nodes, int min_id, int max_id); 56 | __global__ void assign_leaf_points_out_batch(LeafNode* leafs, int* leaf_points, int* node_ids, int N, int internal_nodes, int min_id, int max_id); 57 | __global__ void compute_mean(KEYTYPE* split_keys, int* node_sizes, int num_nodes); 58 | __global__ void initialize_rands(curandState* states, int iter); 59 | */ 60 | -------------------------------------------------------------------------------- /Test/cuda/cuda_tests.cpp: -------------------------------------------------------------------------------- 1 | //#include "test_kernels.cu" 2 | 3 | #define BOOST_TEST_MODULE GPU 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | int GPUBuildKNNTest(); 13 | 14 | BOOST_AUTO_TEST_CASE(RandomTests) { 15 | BOOST_CHECK(1 == 1); 16 | 17 | int errors = GPUBuildKNNTest(); 18 | printf("outside\n"); 19 | BOOST_CHECK(errors == 0); 20 | } 21 | 22 | /* 23 | int GPUTestDistance_All(); 24 | 25 | BOOST_AUTO_TEST_CASE(DistanceTests) { 26 | int errs = GPUTestDistance_All(); 27 | BOOST_CHECK(errs == 0); 28 | } 29 | 30 | int GPUBuildTPTTest(); 31 | 32 | BOOST_AUTO_TEST_CASE(TPTreeTests) { 33 | int errs = GPUBuildTPTTest(); 34 | BOOST_CHECK(errs == 0); 35 | } 36 | 37 | int GPUBuildSSDTest_All(); 38 | 39 | BOOST_AUTO_TEST_CASE(BuildSSDTests) { 40 | int errs = GPUBuildSSDTest_All(); 41 | BOOST_CHECK(errs == 0); 42 | } 43 | */ 44 | -------------------------------------------------------------------------------- /Test/inc/Test.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | -------------------------------------------------------------------------------- /Test/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Test/src/Base64HelperTest.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #include "inc/Test.h" 5 | #include "inc/Helper/Base64Encode.h" 6 | 7 | #include 8 | 9 | BOOST_AUTO_TEST_SUITE(Base64Test) 10 | 11 | BOOST_AUTO_TEST_CASE(Base64EncDec) 12 | { 13 | using namespace SPTAG::Helper::Base64; 14 | 15 | const size_t bufferSize = 1 << 10; 16 | std::unique_ptr rawBuffer(new uint8_t[bufferSize]); 17 | std::unique_ptr encBuffer(new char[bufferSize]); 18 | std::unique_ptr rawBuffer2(new uint8_t[bufferSize]); 19 | 20 | for (size_t inputSize = 1; inputSize < 128; ++inputSize) 21 | { 22 | for (size_t i = 0; i < inputSize; ++i) 23 | { 24 | rawBuffer[i] = static_cast(i); 25 | } 26 | 27 | size_t encBufLen = CapacityForEncode(inputSize); 28 | BOOST_CHECK(encBufLen < bufferSize); 29 | 30 | size_t encOutLen = 0; 31 | BOOST_CHECK(Encode(rawBuffer.get(), inputSize, encBuffer.get(), encOutLen)); 32 | BOOST_CHECK(encBufLen >= encOutLen); 33 | 34 | size_t decBufLen = CapacityForDecode(encOutLen); 35 | BOOST_CHECK(decBufLen < bufferSize); 36 | 37 | size_t decOutLen = 0; 38 | BOOST_CHECK(Decode(encBuffer.get(), encOutLen, rawBuffer.get(), decOutLen)); 39 | BOOST_CHECK(decBufLen >= decOutLen); 40 | } 41 | } 42 | 43 | BOOST_AUTO_TEST_SUITE_END() -------------------------------------------------------------------------------- /Test/src/CommonHelperTest.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #include "inc/Test.h" 5 | #include "inc/Helper/CommonHelper.h" 6 | 7 | #include 8 | 9 | BOOST_AUTO_TEST_SUITE(CommonHelperTest) 10 | 11 | 12 | BOOST_AUTO_TEST_CASE(ToLowerInPlaceTest) 13 | { 14 | auto runTestCase = [](std::string p_input, const std::string& p_expected) 15 | { 16 | SPTAG::Helper::StrUtils::ToLowerInPlace(p_input); 17 | BOOST_CHECK(p_input == p_expected); 18 | }; 19 | 20 | runTestCase("abc", "abc"); 21 | runTestCase("ABC", "abc"); 22 | runTestCase("abC", "abc"); 23 | runTestCase("Upper-Case", "upper-case"); 24 | runTestCase("123!-=aBc", "123!-=abc"); 25 | } 26 | 27 | 28 | BOOST_AUTO_TEST_CASE(SplitStringTest) 29 | { 30 | std::string input("seg1 seg2 seg3 seg4"); 31 | 32 | const auto& segs = SPTAG::Helper::StrUtils::SplitString(input, " "); 33 | BOOST_CHECK(segs.size() == 4); 34 | BOOST_CHECK(segs[0] == "seg1"); 35 | BOOST_CHECK(segs[1] == "seg2"); 36 | BOOST_CHECK(segs[2] == "seg3"); 37 | BOOST_CHECK(segs[3] == "seg4"); 38 | } 39 | 40 | 41 | BOOST_AUTO_TEST_CASE(FindTrimmedSegmentTest) 42 | { 43 | using namespace SPTAG::Helper::StrUtils; 44 | std::string input("\t Space End \r\n\t"); 45 | 46 | const auto& pos = FindTrimmedSegment(input.c_str(), 47 | input.c_str() + input.size(), 48 | [](char p_val)->bool 49 | { 50 | return std::isspace(p_val) > 0; 51 | }); 52 | 53 | BOOST_CHECK(pos.first == input.c_str() + 2); 54 | BOOST_CHECK(pos.second == input.c_str() + 13); 55 | } 56 | 57 | 58 | BOOST_AUTO_TEST_CASE(StartsWithTest) 59 | { 60 | using namespace SPTAG::Helper::StrUtils; 61 | 62 | BOOST_CHECK(StartsWith("Abcd", "A")); 63 | BOOST_CHECK(StartsWith("Abcd", "Ab")); 64 | BOOST_CHECK(StartsWith("Abcd", "Abc")); 65 | BOOST_CHECK(StartsWith("Abcd", "Abcd")); 66 | 67 | BOOST_CHECK(!StartsWith("Abcd", "a")); 68 | BOOST_CHECK(!StartsWith("Abcd", "F")); 69 | BOOST_CHECK(!StartsWith("Abcd", "AF")); 70 | BOOST_CHECK(!StartsWith("Abcd", "AbF")); 71 | BOOST_CHECK(!StartsWith("Abcd", "AbcF")); 72 | BOOST_CHECK(!StartsWith("Abcd", "Abcde")); 73 | } 74 | 75 | 76 | BOOST_AUTO_TEST_CASE(StrEqualIgnoreCaseTest) 77 | { 78 | using namespace SPTAG::Helper::StrUtils; 79 | 80 | BOOST_CHECK(StrEqualIgnoreCase("Abcd", "Abcd")); 81 | BOOST_CHECK(StrEqualIgnoreCase("Abcd", "abcd")); 82 | BOOST_CHECK(StrEqualIgnoreCase("Abcd", "abCD")); 83 | BOOST_CHECK(StrEqualIgnoreCase("Abcd-123", "abcd-123")); 84 | BOOST_CHECK(StrEqualIgnoreCase(" ZZZ", " zzz")); 85 | 86 | BOOST_CHECK(!StrEqualIgnoreCase("abcd", "abcd1")); 87 | BOOST_CHECK(!StrEqualIgnoreCase("Abcd", " abcd")); 88 | BOOST_CHECK(!StrEqualIgnoreCase("000", "OOO")); 89 | } 90 | 91 | 92 | 93 | BOOST_AUTO_TEST_SUITE_END() -------------------------------------------------------------------------------- /Test/src/IniReaderTest.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #include "inc/Test.h" 5 | #include "inc/Helper/SimpleIniReader.h" 6 | 7 | #include 8 | 9 | BOOST_AUTO_TEST_SUITE(IniReaderTest) 10 | 11 | BOOST_AUTO_TEST_CASE(IniReaderLoadTest) 12 | { 13 | std::ofstream tmpIni("temp.ini"); 14 | tmpIni << "[Common]" << std::endl; 15 | tmpIni << "; Comment " << std::endl; 16 | tmpIni << "Param1=1" << std::endl; 17 | tmpIni << "Param2=Exp=2" << std::endl; 18 | 19 | tmpIni.close(); 20 | 21 | SPTAG::Helper::IniReader reader; 22 | BOOST_CHECK(SPTAG::ErrorCode::Success == reader.LoadIniFile("temp.ini")); 23 | 24 | BOOST_CHECK(reader.DoesSectionExist("Common")); 25 | BOOST_CHECK(reader.DoesParameterExist("Common", "Param1")); 26 | BOOST_CHECK(reader.DoesParameterExist("Common", "Param2")); 27 | 28 | BOOST_CHECK(!reader.DoesSectionExist("NotExist")); 29 | BOOST_CHECK(!reader.DoesParameterExist("NotExist", "Param1")); 30 | BOOST_CHECK(!reader.DoesParameterExist("Common", "ParamNotExist")); 31 | 32 | BOOST_CHECK(1 == reader.GetParameter("Common", "Param1", 0)); 33 | BOOST_CHECK(0 == reader.GetParameter("Common", "ParamNotExist", 0)); 34 | 35 | BOOST_CHECK(std::string("Exp=2") == reader.GetParameter("Common", "Param2", std::string())); 36 | BOOST_CHECK(std::string("1") == reader.GetParameter("Common", "Param1", std::string())); 37 | BOOST_CHECK(std::string() == reader.GetParameter("Common", "ParamNotExist", std::string())); 38 | } 39 | 40 | BOOST_AUTO_TEST_SUITE_END() -------------------------------------------------------------------------------- /Test/src/SIMDTest.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | // #include 5 | #include 6 | #include "inc/Test.h" 7 | #include "inc/Core/Common/SIMDUtils.h" 8 | 9 | 10 | template 11 | static void ComputeSum(T *pX, const T *pY, SPTAG::DimensionType length) 12 | { 13 | const T* pEnd1 = pX + length; 14 | while (pX < pEnd1) { 15 | *pX++ += *pY++; 16 | } 17 | } 18 | 19 | template 20 | T random(int high = RAND_MAX, int low = 0) // Generates a random value. 21 | { 22 | return (T)(low + float(high - low)*(std::rand()/static_cast(RAND_MAX + 1.0))); 23 | } 24 | 25 | template 26 | void test(int high) { 27 | SPTAG::DimensionType dimension = random(256, 2); 28 | T *X = new T[dimension], *Y = new T[dimension]; 29 | BOOST_ASSERT(X != nullptr && Y != nullptr); 30 | for (SPTAG::DimensionType i = 0; i < dimension; i++) { 31 | X[i] = random(high, -high); 32 | Y[i] = random(high, -high); 33 | } 34 | T *X_copy = new T[dimension]; 35 | for (SPTAG::DimensionType i = 0; i < dimension; i++) { 36 | X_copy[i] = X[i]; 37 | } 38 | ComputeSum(X, Y, dimension); 39 | SPTAG::COMMON::SIMDUtils::ComputeSum(X_copy, Y, dimension); 40 | for (SPTAG::DimensionType i = 0; i < dimension; i++) { 41 | BOOST_CHECK_CLOSE_FRACTION(double(X[i]), double(X_copy[i]), 1e-5); 42 | } 43 | 44 | delete[] X; 45 | delete[] Y; 46 | delete[] X_copy; 47 | } 48 | 49 | BOOST_AUTO_TEST_SUITE(SIMDTest) 50 | 51 | BOOST_AUTO_TEST_CASE(TestDistanceComputation) 52 | { 53 | test(1); 54 | test(127); 55 | test(32767); 56 | } 57 | 58 | 59 | BOOST_AUTO_TEST_SUITE_END() 60 | -------------------------------------------------------------------------------- /Test/src/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #define BOOST_TEST_MAIN 5 | #define BOOST_TEST_MODULE Main 6 | #include "inc/Test.h" 7 | 8 | #include 9 | #include 10 | 11 | using namespace boost::unit_test; 12 | 13 | class SPTAGVisitor : public test_tree_visitor 14 | { 15 | public: 16 | void visit(test_case const& test) 17 | { 18 | std::string prefix(2, '\t'); 19 | std::cout << prefix << "Case: " << test.p_name << std::endl; 20 | } 21 | 22 | bool test_suite_start(test_suite const& suite) 23 | { 24 | std::string prefix(1, '\t'); 25 | std::cout << prefix << "Suite: " << suite.p_name << std::endl; 26 | return true; 27 | } 28 | }; 29 | 30 | struct GlobalFixture 31 | { 32 | GlobalFixture() 33 | { 34 | SPTAGVisitor visitor; 35 | traverse_test_tree(framework::master_test_suite(), visitor, false); 36 | } 37 | 38 | }; 39 | 40 | BOOST_TEST_GLOBAL_FIXTURE(GlobalFixture); 41 | 42 | -------------------------------------------------------------------------------- /Test/src/make_gist_sptag.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import numpy as np 3 | import faiss 4 | 5 | def DEFAULT_read(fname, np_type): 6 | buf = np.fromfile(fname, dtype='int32') 7 | n = buf[0] 8 | d = buf[1] 9 | print(buf.shape) 10 | print(n) 11 | print(d) 12 | #assert((n*d) % (buf.shape[0] - 2) == 0) 13 | return buf[2:].view(np_type).reshape(n, d).copy() 14 | 15 | def DEFAULT_write(fname, m): 16 | with open(fname, 'wb') as f: 17 | np.array(m.shape[0], dtype=np.int32).tofile(f) 18 | np.array(m.shape[1], dtype=np.int32).tofile(f) 19 | m.tofile(f) 20 | 21 | def codebooks_write(fname, m): 22 | with open(fname, 'wb') as f: 23 | np.array(m.shape[0], dtype=np.int32).tofile(f) 24 | np.array(m.shape[1], dtype=np.int32).tofile(f) 25 | np.array(m.shape[2], dtype=np.int32).tofile(f) 26 | m.tofile(f) 27 | 28 | def ivecs_write(fname, m): 29 | n, d = m.shape 30 | m1 = np.empty((n, d + 1), dtype='int32') 31 | m1[:, 0] = d 32 | m1[:, 1:] = m 33 | m1.tofile(fname) 34 | 35 | 36 | def fvecs_write(fname, m): 37 | m = m.astype('float32') 38 | ivecs_write(fname, m.view('int32')) 39 | 40 | def ivecs_read(fname): 41 | a = np.fromfile(fname, dtype='int32') 42 | d = a[0] 43 | return a.reshape(-1, d + 1)[:, 1:].copy() 44 | 45 | 46 | def fvecs_read(fname): 47 | return ivecs_read(fname).view('float32') 48 | 49 | 50 | def sanitize(x): 51 | return np.ascontiguousarray(x, dtype='float32') 52 | 53 | def main(): 54 | xd = fvecs_read("D:\data\gist\gist_base.fvecs") 55 | xq = fvecs_read("D:\data\gist\gist_query.fvecs") 56 | xt = fvecs_read("D:\data\gist\gist_learn.fvecs") 57 | 58 | 59 | index = faiss.IndexFlatL2(xd.shape[1]) 60 | index.add(sanitize(xd)) 61 | 62 | pqidx = faiss.IndexPQ(xd.shape[1], int(xd.shape[1] / 2), 8) 63 | pqidx.train(sanitize(xt)) 64 | centroids = faiss.vector_to_array(pqidx.pq.centroids) 65 | print(centroids.shape) 66 | centroids = centroids.reshape(int(xd.shape[1] / 2), 256, 2) 67 | 68 | DEFAULT_write("gist_vector.bin", xd) 69 | DEFAULT_write("gist_query.bin", xq) 70 | codebooks_write("gist_codebook.bin", centroids) 71 | 72 | main() -------------------------------------------------------------------------------- /Tools/OPQ/README.md: -------------------------------------------------------------------------------- 1 | # OPQ gpu training and inference tool 2 | 3 | ## Package Requirements (tbd) 4 | 5 | 1. Python>=3.7 6 | 2. numpy>=1.18.1 7 | 3. faiss>=1.7.0 8 | 4. LibVQ 9 | 10 | 11 | ## Parameter Sample 12 | --data_file [input_path]\vectors.bin.0 --query_file [model_path]\query.bin --output_truth [output_path] --output_dir [output_path]\5474\cluster_unzip --task 0 --data_type float32 --k 5 --dim 1024 --B 1000000 --Q 1000 --D L2 --data_format DEFAULT --T 18 --train_samples 1000000 --quan_type opq --quan_dim 1024 --output_quantizer quantizer.bin --output_quan_vector_file dssm_vectors.bin --output_rec_vector_file vectors.bin --quan_test 1 --data_normalize 0 --query_normalize 0 13 | -------------------------------------------------------------------------------- /Tools/nni-auto-tune/config.yml: -------------------------------------------------------------------------------- 1 | experimentName: sift128 2 | trialConcurrency: 4 3 | maxExperimentDuration: 168h 4 | searchSpaceFile: search_space.json 5 | trialCommand: python main.py --train_file sift-128-euclidean.hdf5 6 | 7 | tuner: 8 | name: TPE 9 | classArgs: 10 | optimize_mode: maximize 11 | 12 | trainingService: 13 | platform: local 14 | 15 | -------------------------------------------------------------------------------- /Tools/nni-auto-tune/config_aml.yml: -------------------------------------------------------------------------------- 1 | experimentName: sift128 2 | trialConcurrency: 4 3 | maxExperimentDuration: 168h 4 | searchSpaceFile: search_space.json 5 | 6 | trialCommand: 7 | python --version; 8 | pip --version; 9 | pip install -i https://test.pypi.org/simple/ sptag; 10 | git clone https://github.com/microsoft/SPTAG.git; 11 | cd SPTAG/tools/nni-auto-tune; 12 | wget http://ann-benchmarks.com/sift-128-euclidean.hdf5; 13 | python main.py --train_file sift-128-euclidean.hdf5 14 | 15 | tuner: 16 | name: TPE 17 | classArgs: 18 | optimize_mode: maximize 19 | 20 | trainingService: 21 | platform: aml 22 | dockerImage: msranni/nni 23 | subscriptionId: 24 | resourceGroup: 25 | workspaceName: 26 | computeTarget: -------------------------------------------------------------------------------- /Tools/nni-auto-tune/picture/fashion-mnist-784-euclidean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/SPTAG/4ecf2495eb6187b555c0a6ee7d3b5394d5362183/Tools/nni-auto-tune/picture/fashion-mnist-784-euclidean.png -------------------------------------------------------------------------------- /Tools/nni-auto-tune/picture/glove-100-angular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/SPTAG/4ecf2495eb6187b555c0a6ee7d3b5394d5362183/Tools/nni-auto-tune/picture/glove-100-angular.png -------------------------------------------------------------------------------- /Tools/nni-auto-tune/picture/glove-25-angular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/SPTAG/4ecf2495eb6187b555c0a6ee7d3b5394d5362183/Tools/nni-auto-tune/picture/glove-25-angular.png -------------------------------------------------------------------------------- /Tools/nni-auto-tune/picture/nytimes-256-angular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/SPTAG/4ecf2495eb6187b555c0a6ee7d3b5394d5362183/Tools/nni-auto-tune/picture/nytimes-256-angular.png -------------------------------------------------------------------------------- /Tools/nni-auto-tune/picture/sift-128-euclidean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/SPTAG/4ecf2495eb6187b555c0a6ee7d3b5394d5362183/Tools/nni-auto-tune/picture/sift-128-euclidean.png -------------------------------------------------------------------------------- /Tools/nni-auto-tune/runner.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation. 2 | # Licensed under the MIT license. 3 | 4 | from model import metrics 5 | import time 6 | import os 7 | import psutil 8 | 9 | 10 | def run_individual_query(algo, 11 | X_train, 12 | X_test, 13 | distance, 14 | k, 15 | run_count=1, 16 | max_mem=-1): 17 | 18 | best_search_time = float('inf') 19 | for i in range(run_count): 20 | print('Run %d/%d...' % (i + 1, run_count)) 21 | # a bit dumb but can't be a scalar since of Python's scoping rules 22 | n_items_processed = [0] 23 | 24 | def single_query(v): 25 | start = time.time() 26 | candidates = algo.query(v, k) 27 | if max_mem > 0 and psutil.Process( 28 | os.getpid()).memory_info().rss > max_mem: 29 | raise MemoryError 30 | total = (time.time() - start) 31 | 32 | candidates = [ 33 | (int(idx), 34 | float(metrics[distance]['distance'](v, X_train[idx]))) # noqa 35 | for idx in candidates 36 | ] 37 | n_items_processed[0] += 1 38 | if n_items_processed[0] % 1000 == 0: 39 | print('Processed %d/%d queries...' % 40 | (n_items_processed[0], len(X_test))) 41 | if len(candidates) > k: 42 | print('warning: algorithm returned %d results, but k' 43 | ' is only %d)' % (len(candidates), k)) 44 | return (total, candidates) 45 | 46 | results = [single_query(x) for x in X_test] 47 | 48 | total_time = sum(t for t, _ in results) 49 | total_candidates = sum(len(candidates) for _, candidates in results) 50 | search_time = total_time / len(X_test) 51 | avg_candidates = total_candidates / len(X_test) 52 | best_search_time = min(best_search_time, search_time) 53 | 54 | attrs = { 55 | "best_search_time": best_search_time, 56 | "candidates": avg_candidates, 57 | "name": 'BKT', 58 | "run_count": run_count, 59 | "distance": distance, 60 | "count": int(k) 61 | } 62 | 63 | return (attrs, results) 64 | -------------------------------------------------------------------------------- /Tools/nni-auto-tune/search_space.json: -------------------------------------------------------------------------------- 1 | { 2 | "BKTKmeansK": {"_type": "quniform", "_value": [4,32,8]}, 3 | "Samples": {"_type": "quniform", "_value": [1000, 10000, 2000]}, 4 | "TPTNumber": {"_type": "quniform", "_value": [32, 192, 16]}, 5 | "RefineIterations": {"_type": "choice", "_value": [2, 3]}, 6 | "NeighborhoodSize": {"_type": "quniform", "_value": [16, 192, 8]}, 7 | "CEF": {"_type": "quniform", "_value": [1000, 2000,100]}, 8 | "MaxCheckForRefineGraph": {"_type": "quniform", "_value": [4096, 16324, 1024]}, 9 | "NumberOfInitialDynamicPivots": {"_type": "quniform", "_value": [1, 50, 10]}, 10 | "GraphNeighborhoodScale": {"_type": "choice", "_value": [2, 3, 4]}, 11 | "NumberOfOtherDynamicPivots": {"_type": "quniform", "_value": [1, 10, 2]} 12 | } 13 | 14 | -------------------------------------------------------------------------------- /Tools/nni-auto-tune/search_space_small.json: -------------------------------------------------------------------------------- 1 | { 2 | "BKTKmeansK": {"_type": "choice", "_value": [4,8,16,32]}, 3 | "CEF": {"_type": "choice", "_value": [1000, 1100, 1200, 1400, 1800,2000]} 4 | } 5 | 6 | -------------------------------------------------------------------------------- /Wrappers/CLRCore.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {ba4289c4-f872-4dbc-a57f-7b415614afb3} 14 | 15 | 16 | 17 | 18 | Header Files 19 | 20 | 21 | Header Files 22 | 23 | 24 | 25 | 26 | Source Files 27 | 28 | 29 | Source Files 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Wrappers/CsharpClient.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | 34 | 35 | Resource Files 36 | 37 | 38 | Resource Files 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Wrappers/CsharpCore.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {ba4289c4-f872-4dbc-a57f-7b415614afb3} 14 | 15 | 16 | 17 | 18 | Header Files 19 | 20 | 21 | Header Files 22 | 23 | 24 | 25 | 26 | Source Files 27 | 28 | 29 | Source Files 30 | 31 | 32 | 33 | 34 | Resources 35 | 36 | 37 | Resources 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Wrappers/JavaClient.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | 34 | 35 | Resource Files 36 | 37 | 38 | Resource Files 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Wrappers/JavaCore.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {ba4289c4-f872-4dbc-a57f-7b415614afb3} 14 | 15 | 16 | 17 | 18 | Header Files 19 | 20 | 21 | Header Files 22 | 23 | 24 | 25 | 26 | Source Files 27 | 28 | 29 | Source Files 30 | 31 | 32 | 33 | 34 | Resources 35 | 36 | 37 | Resources 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Wrappers/PythonClient.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | 34 | 35 | Resource Files 36 | 37 | 38 | Resource Files 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Wrappers/PythonCore.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {ba4289c4-f872-4dbc-a57f-7b415614afb3} 14 | 15 | 16 | 17 | 18 | Header Files 19 | 20 | 21 | Header Files 22 | 23 | 24 | 25 | 26 | Source Files 27 | 28 | 29 | Source Files 30 | 31 | 32 | 33 | 34 | Resources 35 | 36 | 37 | Resources 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Wrappers/WinRT/AnnIndex.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "AnnIndex.g.h" 4 | #include "SearchResult.g.h" 5 | #include "inc/Core/VectorIndex.h" 6 | #include "inc/Core/SearchQuery.h" 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | template 13 | struct ReadOnlyProperty { 14 | ReadOnlyProperty() = default; 15 | ReadOnlyProperty(const T& value) : m_value(value) {} 16 | T operator()() const noexcept { return m_value; } 17 | T m_value{}; 18 | }; 19 | 20 | template 21 | struct Property : ReadOnlyProperty { 22 | void operator()(const T& value) { m_value = value; } 23 | }; 24 | 25 | namespace sptag = ::SPTAG; 26 | namespace winrt::SPTAG::implementation 27 | { 28 | using EmbeddingVector = winrt::array_view; 29 | 30 | struct SearchResult : SearchResultT { 31 | winrt::com_array Metadata() { return winrt::com_array(m_metadata); } 32 | std::vector m_metadata; 33 | ReadOnlyProperty Distance; 34 | 35 | SearchResult() = default; 36 | SearchResult(winrt::array_view metadata, float d) : m_metadata(metadata.begin(), metadata.end()), Distance(d) {} 37 | SearchResult(uint8_t* metadata, size_t length, float d) : m_metadata(metadata, metadata + length), Distance(d) {} 38 | }; 39 | 40 | 41 | struct AnnIndex : AnnIndexT 42 | { 43 | sptag::DimensionType m_dimension{ }; 44 | sptag::VectorValueType m_inputValueType{ sptag::VectorValueType::Float }; 45 | 46 | 47 | AnnIndex() { 48 | sptag::SetLogger(std::make_shared(sptag::Helper::LogLevel::LL_Empty)); 49 | m_index = sptag::VectorIndex::CreateInstance(sptag::IndexAlgoType::BKT, sptag::GetEnumValueType()); 50 | } 51 | 52 | void AddWithMetadata(array_view data, array_view metadata); 53 | 54 | void Save(winrt::Windows::Storage::StorageFile file); 55 | void Load(winrt::Windows::Storage::StorageFile file); 56 | 57 | SPTAG::SearchResult GetResultFromMetadata(const sptag::BasicResult& r) const; 58 | 59 | winrt::Windows::Foundation::Collections::IVector Search(EmbeddingVector p_data, uint32_t p_resultNum) const; 60 | 61 | std::shared_ptr m_index; 62 | template 63 | void _AddWithMetadataImpl(EmbeddingVector p_data, T metadata); 64 | }; 65 | 66 | } 67 | 68 | namespace winrt::SPTAG::factory_implementation 69 | { 70 | struct AnnIndex : AnnIndexT {}; 71 | } 72 | -------------------------------------------------------------------------------- /Wrappers/WinRT/AnnIndex.idl: -------------------------------------------------------------------------------- 1 | namespace SPTAG 2 | { 3 | 4 | enum LogLevel 5 | { 6 | Debug = 0, 7 | Info, 8 | Status, 9 | Warning, 10 | Error, 11 | Assert, 12 | Count, 13 | Empty 14 | }; 15 | 16 | [default_interface] 17 | runtimeclass SearchResult 18 | { 19 | UInt8[] Metadata {get; }; 20 | Single Distance{ get; }; 21 | }; 22 | 23 | [default_interface] 24 | runtimeclass AnnIndex 25 | { 26 | AnnIndex(); 27 | [default_overload] 28 | void AddWithMetadata(Single[] data, UInt8[] metadata); 29 | 30 | void Save(Windows.Storage.StorageFile file); 31 | void Load(Windows.Storage.StorageFile file); 32 | Windows.Foundation.Collections.IVector Search(Single[] vector, UInt32 neighborCount); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Wrappers/WinRT/PropertySheet.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Wrappers/WinRT/SPTAG.WinRT.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | x86 6 | $(Platform) 7 | <_nugetNativeFolder>$(MSBuildThisFileDirectory)..\..\runtimes\win10-$(Native-Platform)\native\ 8 | 9 | 10 | 11 | 12 | SPTAG.dll 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Wrappers/WinRT/SPTAG.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE 3 | DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE 4 | -------------------------------------------------------------------------------- /Wrappers/WinRT/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Wrappers/WinRT/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | -------------------------------------------------------------------------------- /Wrappers/WinRT/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | -------------------------------------------------------------------------------- /Wrappers/inc/ClientInterface.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_PW_CLIENTINTERFACE_H_ 5 | #define _SPTAG_PW_CLIENTINTERFACE_H_ 6 | 7 | #include "TransferDataType.h" 8 | #include "inc/Socket/Client.h" 9 | #include "inc/Socket/ResourceManager.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | class AnnClient 16 | { 17 | public: 18 | AnnClient(const char* p_serverAddr, const char* p_serverPort); 19 | 20 | ~AnnClient(); 21 | 22 | void SetTimeoutMilliseconds(int p_timeout); 23 | 24 | void SetSearchParam(const char* p_name, const char* p_value); 25 | 26 | void ClearSearchParam(); 27 | 28 | std::shared_ptr Search(ByteArray p_data, int p_resultNum, const char* p_valueType, bool p_withMetaData); 29 | 30 | bool IsConnected() const; 31 | 32 | private: 33 | std::string CreateSearchQuery(const ByteArray& p_data, 34 | int p_resultNum, 35 | bool p_extractMetadata, 36 | SPTAG::VectorValueType p_valueType); 37 | 38 | SPTAG::Socket::PacketHandlerMapPtr GetHandlerMap(); 39 | 40 | void SearchResponseHanlder(SPTAG::Socket::ConnectionID p_localConnectionID, 41 | SPTAG::Socket::Packet p_packet); 42 | 43 | private: 44 | typedef std::function Callback; 45 | 46 | std::uint32_t m_timeoutInMilliseconds; 47 | 48 | std::string m_server; 49 | 50 | std::string m_port; 51 | 52 | std::unique_ptr m_socketClient; 53 | 54 | std::atomic m_connectionID; 55 | 56 | SPTAG::Socket::ResourceManager m_callbackManager; 57 | 58 | std::unordered_map m_params; 59 | 60 | std::mutex m_paramMutex; 61 | }; 62 | 63 | #endif // _SPTAG_PW_CLIENTINTERFACE_H_ 64 | -------------------------------------------------------------------------------- /Wrappers/inc/CoreInterface.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_PW_COREINTERFACE_H_ 5 | #define _SPTAG_PW_COREINTERFACE_H_ 6 | 7 | #include "TransferDataType.h" 8 | #include "inc/Core/Common.h" 9 | #include "inc/Core/VectorIndex.h" 10 | 11 | typedef int SizeType; 12 | typedef int DimensionType; 13 | 14 | class AnnIndex 15 | { 16 | public: 17 | AnnIndex(DimensionType p_dimension); 18 | 19 | AnnIndex(const char* p_algoType, const char* p_valueType, DimensionType p_dimension); 20 | 21 | ~AnnIndex(); 22 | 23 | void SetBuildParam(const char* p_name, const char* p_value, const char* p_section); 24 | 25 | void SetSearchParam(const char* p_name, const char* p_value, const char* p_section); 26 | 27 | bool LoadQuantizer(const char* p_quantizerFile); 28 | 29 | void SetQuantizerADC(bool p_adc); 30 | 31 | ByteArray QuantizeVector(ByteArray p_data, int p_num); 32 | 33 | ByteArray ReconstructVector(ByteArray p_data, int p_num); 34 | 35 | bool BuildSPANN(bool p_normalized); 36 | 37 | bool BuildSPANNWithMetaData(ByteArray p_meta, SizeType p_num, bool p_withMetaIndex, bool p_normalized); 38 | 39 | bool Build(ByteArray p_data, SizeType p_num, bool p_normalized); 40 | 41 | bool BuildWithMetaData(ByteArray p_data, ByteArray p_meta, SizeType p_num, bool p_withMetaIndex, bool p_normalized); 42 | 43 | std::shared_ptr GetIterator(ByteArray p_target); 44 | 45 | std::shared_ptr Search(ByteArray p_data, int p_resultNum); 46 | 47 | std::shared_ptr SearchWithMetaData(ByteArray p_data, int p_resultNum); 48 | 49 | std::shared_ptr BatchSearch(ByteArray p_data, int p_vectorNum, int p_resultNum, bool p_withMetaData); 50 | 51 | bool ReadyToServe() const; 52 | 53 | void UpdateIndex(); 54 | 55 | bool Save(const char* p_saveFile) const; 56 | 57 | bool Add(ByteArray p_data, SizeType p_num, bool p_normalized); 58 | 59 | bool AddWithMetaData(ByteArray p_data, ByteArray p_meta, SizeType p_num, bool p_withMetaIndex, bool p_normalized); 60 | 61 | bool Delete(ByteArray p_data, SizeType p_num); 62 | 63 | bool DeleteByMetaData(ByteArray p_meta); 64 | 65 | uint64_t CalculateBufferSize(); 66 | 67 | ByteArray Dump(ByteArray p_blobs); 68 | 69 | static AnnIndex LoadFromDump(ByteArray p_config, ByteArray p_blobs); 70 | 71 | static AnnIndex Load(const char* p_loaderFile); 72 | 73 | static AnnIndex Merge(const char* p_indexFilePath1, const char* p_indexFilePath2); 74 | 75 | private: 76 | AnnIndex(const std::shared_ptr& p_index); 77 | 78 | std::shared_ptr m_index; 79 | 80 | size_t m_inputVectorSize; 81 | 82 | DimensionType m_dimension; 83 | 84 | SPTAG::IndexAlgoType m_algoType; 85 | 86 | SPTAG::VectorValueType m_inputValueType; 87 | }; 88 | 89 | #endif // _SPTAG_PW_COREINTERFACE_H_ 90 | -------------------------------------------------------------------------------- /Wrappers/inc/CsharpClient.i: -------------------------------------------------------------------------------- 1 | %module CSHARPSPTAGClient 2 | 3 | %{ 4 | #include "inc/ClientInterface.h" 5 | %} 6 | 7 | %include 8 | %shared_ptr(AnnClient) 9 | %shared_ptr(RemoteSearchResult) 10 | %include "CsharpCommon.i" 11 | 12 | %{ 13 | #define SWIG_FILE_WITH_INIT 14 | %} 15 | 16 | %include "ClientInterface.h" 17 | -------------------------------------------------------------------------------- /Wrappers/inc/CsharpCore.i: -------------------------------------------------------------------------------- 1 | %module CSHARPSPTAG 2 | 3 | %{ 4 | #include "inc/CoreInterface.h" 5 | #include "inc/Core/ResultIterator.h" 6 | %} 7 | 8 | %include 9 | %include 10 | %shared_ptr(AnnIndex) 11 | %shared_ptr(QueryResult) 12 | %shared_ptr(ResultIterator) 13 | %include "CsharpCommon.i" 14 | 15 | %{ 16 | #define SWIG_FILE_WITH_INIT 17 | %} 18 | 19 | %include "CoreInterface.h" 20 | %include "../../AnnService/inc/Core/SearchResult.h" 21 | %include "../../AnnService/inc/Core/ResultIterator.h" -------------------------------------------------------------------------------- /Wrappers/inc/JavaClient.i: -------------------------------------------------------------------------------- 1 | %module JAVASPTAGClient 2 | 3 | %{ 4 | #include "inc/ClientInterface.h" 5 | %} 6 | 7 | %include 8 | %shared_ptr(AnnClient) 9 | %shared_ptr(RemoteSearchResult) 10 | %include "JavaCommon.i" 11 | 12 | %{ 13 | #define SWIG_FILE_WITH_INIT 14 | %} 15 | 16 | %include "ClientInterface.h" 17 | -------------------------------------------------------------------------------- /Wrappers/inc/JavaCommon.i: -------------------------------------------------------------------------------- 1 | #ifdef SWIGJAVA 2 | 3 | %typemap(jni) ByteArray "jbyteArray" 4 | %typemap(jtype) ByteArray "byte[]" 5 | %typemap(jstype) ByteArray "byte[]" 6 | %typemap(in) ByteArray { 7 | $1.Set((std::uint8_t*)JCALL2(GetByteArrayElements, jenv, $input, 0), 8 | JCALL1(GetArrayLength, jenv, $input), false); 9 | } 10 | %typemap(out) ByteArray { 11 | $result = JCALL1(NewByteArray, jenv, $1.Length()); 12 | JCALL4(SetByteArrayRegion, jenv, $result, 0, $1.Length(), (jbyte *)$1.Data()); 13 | if ($1.Length() > 0) delete[] $1.Data(); 14 | } 15 | %typemap(javain) ByteArray "$javainput" 16 | %typemap(javaout) ByteArray { return $jnicall; } 17 | 18 | %typemap(jni) std::shared_ptr "jobjectArray" 19 | %typemap(jtype) std::shared_ptr "BasicResult[]" 20 | %typemap(jstype) std::shared_ptr "BasicResult[]" 21 | %typemap(out) std::shared_ptr { 22 | jclass retClass = jenv->FindClass("BasicResult"); 23 | int len = $1->GetResultNum(); 24 | $result = jenv->NewObjectArray(len, retClass, NULL); 25 | for (int i = 0; i < len; i++) { 26 | auto& meta = $1->GetMetadata(i); 27 | jbyteArray bptr = jenv->NewByteArray(meta.Length()); 28 | jenv->SetByteArrayRegion(bptr, 0, meta.Length(), (jbyte *)meta.Data()); 29 | jenv->SetObjectArrayElement(jresult, i, jenv->NewObject(retClass, jenv->GetMethodID(retClass, "", "(IF[BZ)V"), (jint)($1->GetResult(i)->VID), (jfloat)($1->GetResult(i)->Dist), bptr, (jboolean)($1->GetResult(i)->RelaxedMono))); 30 | } 31 | } 32 | %typemap(javaout) std::shared_ptr { return $jnicall; } 33 | 34 | %typemap(jni) std::shared_ptr "jobjectArray" 35 | %typemap(jtype) std::shared_ptr "BasicResult[]" 36 | %typemap(jstype) std::shared_ptr "BasicResult[]" 37 | %typemap(out) std::shared_ptr { 38 | int combinelen = 0; 39 | int nodelen = (int)(($1->m_allIndexResults).size()); 40 | for (int i = 0; i < nodelen; i++) { 41 | combinelen += $1->m_allIndexResults[i].m_results.GetResultNum(); 42 | } 43 | jclass retClass = jenv->FindClass("BasicResult"); 44 | $result = jenv->NewObjectArray(combinelen, retClass, NULL); 45 | int id = 0; 46 | for (int i = 0; i < nodelen; i++) { 47 | for (int j = 0; j < $1->m_allIndexResults[i].m_results.GetResultNum(); j++) { 48 | auto& ptr = $1->m_allIndexResults[i].m_results; 49 | auto& meta = ptr.GetMetadata(j); 50 | jbyteArray bptr = jenv->NewByteArray(meta.Length()); 51 | jenv->SetByteArrayRegion(bptr, 0, meta.Length(), (jbyte *)meta.Data()); 52 | jenv->SetObjectArrayElement(jresult, id, jenv->NewObject(retClass, jenv->GetMethodID(retClass, "", "(IF[BZ)V"), (jint)(ptr.GetResult(j)->VID), (jfloat)(ptr.GetResult(j)->Dist), bptr, (jboolean)(ptr.GetResult(j)->RelaxedMono))); 53 | id++; 54 | } 55 | } 56 | } 57 | %typemap(javaout) std::shared_ptr { 58 | return $jnicall; 59 | } 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /Wrappers/inc/JavaCore.i: -------------------------------------------------------------------------------- 1 | %module JAVASPTAG 2 | 3 | %{ 4 | #include "inc/CoreInterface.h" 5 | #include "inc/Core/ResultIterator.h" 6 | %} 7 | 8 | %include 9 | %include 10 | %shared_ptr(AnnIndex) 11 | %shared_ptr(QueryResult) 12 | %shared_ptr(ResultIterator) 13 | %include "JavaCommon.i" 14 | 15 | %{ 16 | #define SWIG_FILE_WITH_INIT 17 | %} 18 | 19 | %include "CoreInterface.h" 20 | %include "../../AnnService/inc/Core/SearchResult.h" 21 | %include "../../AnnService/inc/Core/ResultIterator.h" 22 | -------------------------------------------------------------------------------- /Wrappers/inc/ManagedObject.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #pragma once 5 | #include "inc/Helper/StringConvert.h" 6 | 7 | using namespace System; 8 | using namespace System::Runtime::InteropServices; 9 | 10 | namespace Microsoft 11 | { 12 | namespace ANN 13 | { 14 | namespace SPTAGManaged 15 | { 16 | /// 17 | /// hold a pointer to an umnanaged object from the core project 18 | /// 19 | template 20 | public ref class ManagedObject 21 | { 22 | protected: 23 | T* m_Instance; 24 | 25 | public: 26 | ManagedObject(T* instance) 27 | :m_Instance(instance) 28 | { 29 | } 30 | 31 | ManagedObject(T& instance) 32 | { 33 | m_Instance = new T(instance); 34 | } 35 | 36 | /// 37 | /// destructor, which is called whenever delete an object with delete keyword 38 | /// 39 | virtual ~ManagedObject() 40 | { 41 | if (m_Instance != nullptr) 42 | { 43 | delete m_Instance; 44 | } 45 | } 46 | 47 | /// 48 | /// finalizer which is called by Garbage Collector whenever it destroys the wrapper object. 49 | /// 50 | !ManagedObject() 51 | { 52 | if (m_Instance != nullptr) 53 | { 54 | delete m_Instance; 55 | } 56 | } 57 | 58 | T* GetInstance() 59 | { 60 | return m_Instance; 61 | } 62 | 63 | static const char* string_to_char_array(String^ string) 64 | { 65 | const char* str = (const char*)(Marshal::StringToHGlobalAnsi(string)).ToPointer(); 66 | return str; 67 | } 68 | 69 | template 70 | static T string_to(String^ string) 71 | { 72 | T data; 73 | SPTAG::Helper::Convert::ConvertStringTo(string_to_char_array(string), data); 74 | return data; 75 | } 76 | }; 77 | } 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /Wrappers/inc/PythonClient.i: -------------------------------------------------------------------------------- 1 | %module SPTAGClient 2 | 3 | %{ 4 | #include "inc/ClientInterface.h" 5 | %} 6 | 7 | %include 8 | %shared_ptr(AnnClient) 9 | %shared_ptr(RemoteSearchResult) 10 | %include "PythonCommon.i" 11 | 12 | %{ 13 | #define SWIG_FILE_WITH_INIT 14 | %} 15 | 16 | %include "ClientInterface.h" -------------------------------------------------------------------------------- /Wrappers/inc/PythonCore.i: -------------------------------------------------------------------------------- 1 | %module SPTAG 2 | 3 | %{ 4 | #include "inc/CoreInterface.h" 5 | #include "inc/Core/ResultIterator.h" 6 | %} 7 | 8 | %include 9 | %include 10 | %shared_ptr(AnnIndex) 11 | %shared_ptr(QueryResult) 12 | %shared_ptr(ResultIterator) 13 | %include "PythonCommon.i" 14 | 15 | %{ 16 | #define SWIG_FILE_WITH_INIT 17 | %} 18 | 19 | %include "CoreInterface.h" 20 | %include "../../AnnService/inc/Core/ResultIterator.h" -------------------------------------------------------------------------------- /Wrappers/inc/TransferDataType.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | #ifndef _SPTAG_PW_TRANSFERDATATYPE_H_ 5 | #define _SPTAG_PW_TRANSFERDATATYPE_H_ 6 | 7 | #include "inc/Core/CommonDataStructure.h" 8 | #include "inc/Core/SearchQuery.h" 9 | #include "inc/Core/ResultIterator.h" 10 | #include "inc/Socket/RemoteSearchQuery.h" 11 | 12 | typedef SPTAG::ByteArray ByteArray; 13 | 14 | typedef SPTAG::QueryResult QueryResult; 15 | 16 | typedef SPTAG::BasicResult BasicResult; 17 | 18 | typedef SPTAG::Socket::RemoteSearchResult RemoteSearchResult; 19 | 20 | #endif // _SPTAG_PW_TRANSFERDATATYPE_H_ 21 | -------------------------------------------------------------------------------- /Wrappers/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Wrappers/src/AssemblyInfo.cpp: -------------------------------------------------------------------------------- 1 | using namespace System; 2 | using namespace System::Reflection; 3 | using namespace System::Runtime::CompilerServices; 4 | using namespace System::Runtime::InteropServices; 5 | using namespace System::Security::Permissions; 6 | 7 | // 8 | // General Information about an assembly is controlled through the following 9 | // set of attributes. Change these attribute values to modify the information 10 | // associated with an assembly. 11 | // 12 | [assembly:AssemblyTitleAttribute(L"CLRCore")]; 13 | [assembly:AssemblyDescriptionAttribute(L"")]; 14 | [assembly:AssemblyConfigurationAttribute(L"")]; 15 | [assembly:AssemblyCompanyAttribute(L"")]; 16 | [assembly:AssemblyProductAttribute(L"CLRCore")]; 17 | [assembly:AssemblyCopyrightAttribute(L"Copyright (c) 2019")]; 18 | [assembly:AssemblyTrademarkAttribute(L"")]; 19 | [assembly:AssemblyCultureAttribute(L"")]; 20 | 21 | // 22 | // Version information for an assembly consists of the following four values: 23 | // 24 | // Major Version 25 | // Minor Version 26 | // Build Number 27 | // Revision 28 | // 29 | // You can specify all the value or you can default the Revision and Build Numbers 30 | // by using the '*' as shown below: 31 | 32 | [assembly:AssemblyVersionAttribute("1.0.*")]; 33 | 34 | [assembly:ComVisible(false)]; 35 | 36 | [assembly:CLSCompliantAttribute(true)]; -------------------------------------------------------------------------------- /datasets/SPACEV1B/README.md: -------------------------------------------------------------------------------- 1 | # SPACEV1B: A billion-Scale vector dataset for text descriptors 2 | This is a dataset released by Microsoft from SpaceV, Bing web vector search scenario, for large scale vector search related research usage. It consists of more than one billion document vectors 3 | and 29K+ query vectors encoded by Microsoft SpaceV Superior model. This model is trained to capture generic intent representation for both documents and queries. 4 | The goal is to match the query vector to the closest document vectors in order to achieve topk relevant documents for each query. 5 | 6 | ## Introduction 7 | 8 | This dataset contains: 9 | 10 | * [vectors.bin](vectors.bin): It contains 1,402,020,720 100-dimensional int8-type document descriptors. 11 | * [query.bin](query.bin): It contains 29,316 100-dimensional int8-type query descriptors. 12 | * [truth.bin](truth.bin): It contains 100 nearest ground truth(include vector ids and distances) of 29,316 queries according to L2 distance. 13 | * [query_log.bin](query_log.bin): It contains 94,162 100-dimensional int8-type history query descriptors. 14 | 15 | ## How to read the vectors, queries, and truth 16 | 17 | ```python 18 | import struct 19 | import numpy as np 20 | import os 21 | 22 | part_count = len(os.listdir('vectors.bin')) 23 | for i in range(1, part_count + 1): 24 | fvec = open(os.path.join('vectors.bin', 'vectors_%d.bin' % i), 'rb') 25 | if i == 1: 26 | vec_count = struct.unpack('i', fvec.read(4))[0] 27 | vec_dimension = struct.unpack('i', fvec.read(4))[0] 28 | vecbuf = bytearray(vec_count * vec_dimension) 29 | vecbuf_offset = 0 30 | while True: 31 | part = fvec.read(1048576) 32 | if len(part) == 0: break 33 | vecbuf[vecbuf_offset: vecbuf_offset + len(part)] = part 34 | vecbuf_offset += len(part) 35 | fvec.close() 36 | X = np.frombuffer(vecbuf, dtype=np.int8).reshape((vec_count, vec_dimension)) 37 | 38 | fq = open('query.bin', 'rb') 39 | q_count = struct.unpack('i', fq.read(4))[0] 40 | q_dimension = struct.unpack('i', fq.read(4))[0] 41 | queries = np.frombuffer(fq.read(q_count * q_dimension), dtype=np.int8).reshape((q_count, q_dimension)) 42 | 43 | ftruth = open('truth.bin', 'rb') 44 | t_count = struct.unpack('i', ftruth.read(4))[0] 45 | topk = struct.unpack('i', ftruth.read(4))[0] 46 | truth_vids = np.frombuffer(ftruth.read(t_count * topk * 4), dtype=np.int32).reshape((t_count, topk)) 47 | truth_distances = np.frombuffer(ftruth.read(t_count * topk * 4), dtype=np.float32).reshape((t_count, topk)) 48 | ``` 49 | 50 | ## License 51 | 52 | The entire dataset is under [O-UDA license](LICENSE) -------------------------------------------------------------------------------- /datasets/SPACEV1B/query.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6a531887daca721f633da2b92dacc0aa4c3512aef8ae671031e825ce7134a9e6 3 | size 2931608 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/query_log.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d4768ea964b595302b08f0b9ef484d7003b2e7848f2f7baf9e2b4bbb3bb36c49 3 | size 9416208 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/truth.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:94d385c2f34b1f2899f276d87c14a67ef969dcb473e44753261af05ad62461bc 3 | size 23452808 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_1.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:802f735e6bd1472bacdd93eedf8d1305291659117c2b5e3ca9ac38feb89509af 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_10.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ca7053c8582853c7a9984b56be8b9954cd8cbeda159b9b63fa5a56f776561be2 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_11.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b42ee98dbdf215d9c03e99d3c3ac401e615433d70119c7411c689884159773d1 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_12.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0dd7f1a25a6aa53622fa3d66a35af760bccd187a82bbe39a0bf79c681b646289 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_13.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:69d09f33ba230ee9b38e6fc1bf949c7f57b755c49ae8cdaf13ebf14b12272fe5 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_14.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d575a0ec126bfd3ffb6a3dfb7c36ad94c71a398c0a77b0462620feaa7181cbfb 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_15.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0286768443fbdd55ec0ffd25cecf85121aafef6c65226dc2008dda2ece5c7c8e 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_16.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b600774407a1446fcac0748c7beb5fa4214737bf406c2a162ccbb84254c5041d 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_17.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5fb2167810380da46d894428ff8f2c61de05c9616a6343f1fa6d084759abb062 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_18.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d2e69b2f20fb99063944379667b8b9dc33d672079fe6e744d83076c2de5b1ecc 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_19.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1942f09f15c34c1e141a2bdb31138efcfda9a9fe5671c757e6b6a2e509864d65 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_2.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c8f772d430aa817bbd60319486dce7390924a7b71c3038312c89ab93a6382d43 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_20.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2becd2dcedb147d6c3927fa3b6f2d0f5ede03870efad8c8d04055e25694d60b2 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_21.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0cc41b1a8f6b3fb8ef87dd918b8f12433f1a4bac5711260e6722e9172de14754 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_22.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8cb1780b449120a124d71d4a6e5268c1ac2ec57bf27bb37c23a859b41702f3b8 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_23.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b04df15421deb05670f21f34a26b4c0d108e5dd0bc8e3024701e46a90bd2d222 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_24.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2ec09e657776aec02783886de7448642a85ddb004d70df0d10537a7837d076f5 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_25.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a4a3c0ccf4da399397f01748b54f686a416cd5719c126ec93ce9effa124debe3 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_26.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:20c541f53d1e0772a270df12543dc0d715b4edb17ca415ebdf45065d2440525f 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_27.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:69c820cd585cb7883e6489e1e96f8a943be7800bb21e25ed88cff1b63a11a660 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_28.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d82070201cb0b34fa38579118ad01ba13efb62d8b45e30867ab763e7794ced54 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_29.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a11ce9f677543ab2f4b71d199e41e2026020c23a47147f536cbdd93a4266fcd8 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_3.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:787c77685a1603d4aa7f2b4b7f9e19ddff2d828ea21554aca52c82e8d7a6a755 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_30.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e426936bcc481e878b6f7ec32c1cb85438d23f63c0dd27330149f64053475a8d 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_31.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:351d25192805efc17f8fc588c872b907ca2b907ca9cb0d3f1413ea1d8fc09a8f 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_32.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:142c672c7c1f1e0df93ac87a3d39466c9a7fb199309761ba21771bb1f5d2de86 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_33.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e7bb8962700f6b240481d462a6e0f1a997d085857690cf63b5b5be9270e17b5e 3 | size 2763118568 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_4.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d2f3526062048781bdc36d3b0c80ce49c26a4874206109ff79064de2b3acc4dc 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_5.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7b94a7e08eb31cf2fbe7d24b1e12b23f1341a75aeed96e4885f288333fdfdfbc 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_6.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a2b2699313be8e6ca09dc67b3267b6bf42ab2ac350c1198041b2fa9778b7905c 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_7.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7960bac8a7579fcaf27a17271a49d0d61f13bbf6397712f513892e84fe89a7d0 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_8.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6f968cbd5bd1eb53722373ffedeb6bed9659a69a01df030e39f67a755418ca45 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /datasets/SPACEV1B/vectors.bin/vectors_9.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f50e029134bc17703be6bc69748953ef2c9bb81b29d2286bda4d006d8bfce34c 3 | size 4294967295 4 | -------------------------------------------------------------------------------- /docs/LinuxInstallation.md: -------------------------------------------------------------------------------- 1 | # Setup SPTAG on Ubuntu 2 | 3 | In this section, will describe how to setup SPTAG on Ubuntu machine. 4 | 5 | 1. Update ubuntu and build env 6 | ``` 7 | sudo apt-get update && sudo apt-get install build-essential 8 | ``` 9 | 2. Install cmake 10 | 11 | - Download cmake. You can find the cmake releases [here](https://github.com/Kitware/CMake/releases). 12 | ```bash 13 | # e.g. download cmake version 3.14.7 14 | wget https://github.com/Kitware/CMake/releases/download/v3.14.7/cmake-3.14.7-Linux-x86_64.sh -P opt/ 15 | ``` 16 | - Follow these instructions: 17 | 1. `chmod +x opt/cmake-3..sh` (chmod makes the script executable) 18 | 2. `sudo bash opt/cmake-3..sh` 19 | 3. The script installs to a target directory so in order to get the `cmake` command, make a symbolic link from the target directory where cmake was extracted to: `sudo ln -s /cmake-3./bin/* /usr/local/bin` 20 | 4. `cmake --version` Note: If you encounter this error: *The program 'cmake' is currently not installed*, Please try the command from step 3 again with a full path (e.g. `sudo ln -s /home//SPTAG/opt/cmake-3.-Linux-x86_64/bin/* /usr/local/bin`) 21 | 22 | 5. Install boost 23 | - Download boost 1.67 version: 24 | ```bash 25 | wget https://netix.dl.sourceforge.net/project/boost/boost/1.67.0/boost_1_67_0.tar.gz 26 | ``` 27 | (There are some [version mis-matching issues](https://github.com/microsoft/SPTAG/issues/26) and reported on github issue) 28 | 29 | 6. Extract and install 30 | ```bash 31 | tar -xzvf boost* 32 | cd boost_1_67_0 33 | ./bootstrap.sh --prefix=/usr/local 34 | ./b2 35 | sudo ./b2 install 36 | sudo apt-get install swig 37 | ``` 38 | 39 | 7. Generate a Release folder in the code directory which will contain all the build targets: 40 | ```bash 41 | mkdir build 42 | cd build && cmake .. && make 43 | ``` 44 | 45 | 8. Add SPTAG module to python path 46 | ```bash 47 | # so python can find the SPTAG module 48 | ENV PYTHONPATH=/app/Release 49 | ``` 50 | -------------------------------------------------------------------------------- /docs/WindowsInstallation.md: -------------------------------------------------------------------------------- 1 | ## Requirements 2 | 3 | ### swig >= 3.0 4 | 5 | Steps to install SWIG: 6 | 7 | 1. Download the latest SWIG binary from http://www.swig.org/download.html, if you need a specific version, windows binaries are located at https://sourceforge.net/projects/swig/files/swigwin/. Once downloaded, please unzip to a local folder (prefarably inside the SPTAG folder) 8 | 2. Add the path where it was unzipped to the environment PATH example: `C:\Sptag\swigwin-3.0.12\` in System properties 9 | 10 | ### cmake >= 3.12.0 11 | 12 | 1. If you have Visual Studio 2019 you already have the required tools to compile, please ensure you have the `Desktop Development with C++` selected to get all the tools, just ensure this option is enabled in the installation workloads 13 | 2. If not, please download cmake 14 | 15 | ![Visual Studio](img/visualstudio.png) 16 | 17 | ### boost == 1.67.0 18 | 19 | Boost's precompiled binaries are available at https://sourceforge.net/projects/boost/files/boost-binaries/1.67.0/ (to avoid compiling from scratch) 20 | 21 | 1. Select the lastest version for 1.67.0 (boost_1_67_0-msvc-14.1-64.exe) 22 | 2. Launch the installation 23 | 3. Add the folder path to PATH environment variable, for instance `C:\Sptag\boost_1_67_0\` 24 | 25 | On the off chance of needing to build boost, because you encountered this message during the Build step `Could NOT find Boost (missing: system thread serialization wserialization regex filesystem)`, try the following 26 | 1. Locate and run `bootstrap.bat`, this creates a file called `b2.exe` 27 | 2. Run the generated exe (in this case `b2.exe`), be patient this may take +1 hr 28 | 3. Once complete, the built libraries will be located in `\stage\lib` (or something along the lines) 29 | 30 | ## Build 31 | 32 | 1. git clone [microsoft/SPTAG](https://github.com/microsoft/SPTAG/) 33 | 2. Go the folder location where you cloned the repo in the command prompt and execute the following commands: 34 | ``` 35 | mkdir build 36 | cd build 37 | cmake -A x64 .. 38 | ``` 39 | 5. From the build folder, open SPTAGLib.sln solution in Visual Studio and compile all projects 40 | 41 | 6. [..]/build/release contains now all components needed, add this path to PYTHONPATH environment variable to reference the required modules 42 | -------------------------------------------------------------------------------- /docs/examples/requirements.txt: -------------------------------------------------------------------------------- 1 | numpy==1.24.2 2 | matplotlib==2.2.2 3 | Keras==2.11.0 4 | Pillow==10.0.1 5 | scikit_learn==0.24.2 6 | -------------------------------------------------------------------------------- /docs/img/sptag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/SPTAG/4ecf2495eb6187b555c0a6ee7d3b5394d5362183/docs/img/sptag.png -------------------------------------------------------------------------------- /docs/img/swigpath.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/SPTAG/4ecf2495eb6187b555c0a6ee7d3b5394d5362183/docs/img/swigpath.PNG -------------------------------------------------------------------------------- /docs/img/visualstudio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/SPTAG/4ecf2495eb6187b555c0a6ee7d3b5394d5362183/docs/img/visualstudio.png -------------------------------------------------------------------------------- /setup.txt: -------------------------------------------------------------------------------- 1 | pip < 21.4 2 | setuptools < 61 3 | wheel < 0.38 --------------------------------------------------------------------------------