diff --git a/AnnService/inc/Core/Common/BKTree.h b/AnnService/inc/Core/Common/BKTree.h index f56e9f597..e06ffa108 100644 --- a/AnnService/inc/Core/Common/BKTree.h +++ b/AnnService/inc/Core/Common/BKTree.h @@ -54,10 +54,12 @@ namespace SPTAG KmeansArgs(int k, DimensionType dim, SizeType datasize, int threadnum, DistCalcMethod distMethod, const std::shared_ptr& quantizer = nullptr) : _K(k), _DK(k), _D(dim), _RD(dim), _T(threadnum), _M(distMethod), m_pQuantizer(quantizer){ if (m_pQuantizer) { + SPTAGLIB_LOG(Helper::LogLevel::LL_Info, "KmeansArgs: Using quantizer!\n"); _RD = m_pQuantizer->ReconstructDim(); fComputeDistance = m_pQuantizer->DistanceCalcSelector(distMethod); } else { + SPTAGLIB_LOG(Helper::LogLevel::LL_Info, "KmeansArgs: Using none quantizer!\n"); fComputeDistance = COMMON::DistanceCalcSelector(distMethod); } @@ -179,7 +181,7 @@ namespace SPTAG currCenters[j] /= args.counts[k]; } - if (args._M == DistCalcMethod::Cosine) { + if (args._M != DistCalcMethod::L2) { COMMON::Utils::Normalize(currCenters, args._RD, COMMON::Utils::GetBase()); } diff --git a/AnnService/inc/Core/Common/OPQQuantizer.h b/AnnService/inc/Core/Common/OPQQuantizer.h index 250a29f7e..2592e8f7f 100644 --- a/AnnService/inc/Core/Common/OPQQuantizer.h +++ b/AnnService/inc/Core/Common/OPQQuantizer.h @@ -24,7 +24,7 @@ namespace SPTAG OPQQuantizer(); - OPQQuantizer(DimensionType NumSubvectors, SizeType KsPerSubvector, DimensionType DimPerSubvector, bool EnableADC, std::unique_ptr&& Codebooks, std::unique_ptr&& OPQMatrix); + OPQQuantizer(DimensionType NumSubvectors, SizeType KsPerSubvector, DimensionType DimPerSubvector, bool EnableADC, std::unique_ptr&& Codebooks, std::unique_ptr&& OPQMatrix, DistCalcMethod distMethod); virtual void QuantizeVector(const void* vec, std::uint8_t* vecout, bool ADC = true) const; @@ -78,7 +78,8 @@ namespace SPTAG } template - OPQQuantizer::OPQQuantizer(DimensionType NumSubvectors, SizeType KsPerSubvector, DimensionType DimPerSubvector, bool EnableADC, std::unique_ptr&& Codebooks, std::unique_ptr&& OPQMatrix) : m_OPQMatrix(std::move(OPQMatrix)), PQQuantizer::PQQuantizer(NumSubvectors, KsPerSubvector, DimPerSubvector, EnableADC, std::move(Codebooks)), m_matrixDim(NumSubvectors * DimPerSubvector) + OPQQuantizer::OPQQuantizer(DimensionType NumSubvectors, SizeType KsPerSubvector, DimensionType DimPerSubvector, bool EnableADC, std::unique_ptr&& Codebooks, std::unique_ptr&& OPQMatrix, DistCalcMethod distMethod) : + m_OPQMatrix(std::move(OPQMatrix)), PQQuantizer::PQQuantizer(NumSubvectors, KsPerSubvector, DimPerSubvector, EnableADC, std::move(Codebooks), distMethod), m_matrixDim(NumSubvectors * DimPerSubvector) { m_InitMatrixTranspose(); } diff --git a/AnnService/inc/Core/Common/PQQuantizer.h b/AnnService/inc/Core/Common/PQQuantizer.h index 5bece0225..8f0f00599 100644 --- a/AnnService/inc/Core/Common/PQQuantizer.h +++ b/AnnService/inc/Core/Common/PQQuantizer.h @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #ifndef _SPTAG_COMMON_PQQUANTIZER_H_ @@ -7,6 +7,7 @@ #include "CommonUtils.h" #include "DistanceUtils.h" #include "IQuantizer.h" +#include "inc/Helper/StringConvert.h" #include #include #include @@ -25,7 +26,7 @@ namespace SPTAG public: PQQuantizer(); - PQQuantizer(DimensionType NumSubvectors, SizeType KsPerSubvector, DimensionType DimPerSubvector, bool EnableADC, std::unique_ptr&& Codebooks); + PQQuantizer(DimensionType NumSubvectors, SizeType KsPerSubvector, DimensionType DimPerSubvector, bool EnableADC, std::unique_ptr&& Codebooks, DistCalcMethod distMethod); ~PQQuantizer(); @@ -84,6 +85,7 @@ namespace SPTAG DimensionType m_DimPerSubvector; SizeType m_BlockSize; bool m_EnableADC; + DistCalcMethod m_distMethod; inline SizeType m_DistIndexCalc(SizeType i, SizeType j, SizeType k) const; void InitializeDistanceTables(); @@ -93,12 +95,13 @@ namespace SPTAG }; template - PQQuantizer::PQQuantizer() : m_NumSubvectors(0), m_KsPerSubvector(0), m_DimPerSubvector(0), m_BlockSize(0), m_EnableADC(false) + PQQuantizer::PQQuantizer() : m_NumSubvectors(0), m_KsPerSubvector(0), m_DimPerSubvector(0), m_BlockSize(0), m_EnableADC(false), m_distMethod(DistCalcMethod::L2) { } template - PQQuantizer::PQQuantizer(DimensionType NumSubvectors, SizeType KsPerSubvector, DimensionType DimPerSubvector, bool EnableADC, std::unique_ptr&& Codebooks) : m_NumSubvectors(NumSubvectors), m_KsPerSubvector(KsPerSubvector), m_DimPerSubvector(DimPerSubvector), m_BlockSize(KsPerSubvector* KsPerSubvector), m_codebooks(std::move(Codebooks)), m_EnableADC(EnableADC) + PQQuantizer::PQQuantizer(DimensionType NumSubvectors, SizeType KsPerSubvector, DimensionType DimPerSubvector, bool EnableADC, std::unique_ptr&& Codebooks, DistCalcMethod distMethod) : + m_NumSubvectors(NumSubvectors), m_KsPerSubvector(KsPerSubvector), m_DimPerSubvector(DimPerSubvector), m_BlockSize(KsPerSubvector* KsPerSubvector), m_codebooks(std::move(Codebooks)), m_EnableADC(EnableADC), m_distMethod(distMethod) { InitializeDistanceTables(); } @@ -131,8 +134,20 @@ namespace SPTAG float PQQuantizer::CosineDistance(const std::uint8_t* pX, const std::uint8_t* pY) const // pX must be query distance table for ADC { - SPTAGLIB_LOG(Helper::LogLevel::LL_Error, "Quantizer does not support CosineDistance!\n"); - return 0; + float out = 0; + if (GetEnableADC()) { + float* ptr = (float*)pX; + for (int i = 0; i < m_NumSubvectors; i++) { + out += ptr[pY[i]]; + ptr += m_KsPerSubvector; + } + } + else { + for (int i = 0; i < m_NumSubvectors; i++) { + out += m_L2DistanceTables[m_DistIndexCalc(i, pX[i], pY[i])]; + } + } + return out; } template @@ -140,7 +155,7 @@ namespace SPTAG { if (ADC && GetEnableADC()) { - auto distCalc = DistanceCalcSelector(DistCalcMethod::L2); + auto distCalc = COMMON::DistanceCalcSelector(m_distMethod); float* ADCtable = (float*) vecout; T* subcodebooks = m_codebooks.get(); T* subvec = (T*)vec; @@ -157,7 +172,7 @@ namespace SPTAG } else { - auto distCalc = DistanceCalcSelector(DistCalcMethod::L2); + auto distCalc = COMMON::DistanceCalcSelector(DistCalcMethod::L2); T* subvec = (T*)vec; T* subcodebooks = m_codebooks.get(); for (int i = 0; i < m_NumSubvectors; i++) { @@ -220,7 +235,7 @@ namespace SPTAG std::uint64_t PQQuantizer::BufferSize() const { return sizeof(T) * m_NumSubvectors * m_KsPerSubvector * m_DimPerSubvector + - sizeof(DimensionType) + sizeof(SizeType) + sizeof(DimensionType) + sizeof(VectorValueType) + sizeof(QuantizerType); + sizeof(DimensionType) + sizeof(SizeType) + sizeof(DimensionType) + sizeof(VectorValueType) + sizeof(QuantizerType) + sizeof(DistCalcMethod); } template @@ -234,6 +249,7 @@ namespace SPTAG IOBINARY(p_out, WriteBinary, sizeof(SizeType), (char*)&m_KsPerSubvector); IOBINARY(p_out, WriteBinary, sizeof(DimensionType), (char*)&m_DimPerSubvector); IOBINARY(p_out, WriteBinary, sizeof(T) * m_NumSubvectors * m_KsPerSubvector * m_DimPerSubvector, (char*)m_codebooks.get()); + IOBINARY(p_out, WriteBinary, sizeof(DistCalcMethod), (char*)&m_distMethod); SPTAGLIB_LOG(Helper::LogLevel::LL_Info, "Saving quantizer: Subvectors:%d KsPerSubvector:%d DimPerSubvector:%d\n", m_NumSubvectors, m_KsPerSubvector, m_DimPerSubvector); return ErrorCode::Success; } @@ -252,6 +268,13 @@ namespace SPTAG SPTAGLIB_LOG(Helper::LogLevel::LL_Info, "sizeof(T): %s.\n", std::to_string(sizeof(T)).c_str()); IOBINARY(p_in, ReadBinary, sizeof(T) * m_NumSubvectors * m_KsPerSubvector * m_DimPerSubvector, (char*)m_codebooks.get()); SPTAGLIB_LOG(Helper::LogLevel::LL_Info, "After read codebooks.\n"); + + if (p_in->ReadBinary(sizeof(DistCalcMethod), (char*)&m_distMethod) != sizeof(DistCalcMethod)) { + m_distMethod = DistCalcMethod::L2; + } + + SPTAGLIB_LOG(Helper::LogLevel::LL_Info, "After read dist: %s.\n", Helper::Convert::ConvertToString(m_distMethod).c_str()); + m_BlockSize = m_KsPerSubvector * m_KsPerSubvector; InitializeDistanceTables(); @@ -275,8 +298,17 @@ namespace SPTAG m_codebooks = std::make_unique(m_NumSubvectors * m_KsPerSubvector * m_DimPerSubvector); SPTAGLIB_LOG(Helper::LogLevel::LL_Info, "sizeof(T): %s.\n", std::to_string(sizeof(T)).c_str()); std::memcpy(m_codebooks.get(), raw_bytes, sizeof(T) * m_NumSubvectors * m_KsPerSubvector * m_DimPerSubvector); + raw_bytes += sizeof(T) * m_NumSubvectors * m_KsPerSubvector * m_DimPerSubvector; SPTAGLIB_LOG(Helper::LogLevel::LL_Info, "After read codebooks.\n"); - + + m_distMethod = *(DistCalcMethod*)raw_bytes; + raw_bytes += sizeof(DistCalcMethod); + if (m_distMethod >= DistCalcMethod::Undefined) { + m_distMethod = DistCalcMethod::L2; + raw_bytes -= sizeof(DistCalcMethod); + } + SPTAGLIB_LOG(Helper::LogLevel::LL_Info, "After read dist: %s.\n", Helper::Convert::ConvertToString(m_distMethod).c_str()); + m_BlockSize = m_KsPerSubvector * m_KsPerSubvector; InitializeDistanceTables(); SPTAGLIB_LOG(Helper::LogLevel::LL_Info, "Loaded quantizer: Subvectors:%d KsPerSubvector:%d DimPerSubvector:%d\n", m_NumSubvectors, m_KsPerSubvector, m_DimPerSubvector); @@ -334,13 +366,13 @@ namespace SPTAG void PQQuantizer::InitializeDistanceTables() { auto temp_m_L2DistanceTables = std::make_unique(m_BlockSize * m_NumSubvectors); - auto L2Dist = DistanceCalcSelector(DistCalcMethod::L2); + auto distFunc = COMMON::DistanceCalcSelector(m_distMethod); for (int i = 0; i < m_NumSubvectors; i++) { SizeType baseIdx = i * m_KsPerSubvector * m_DimPerSubvector; for (int j = 0; j < m_KsPerSubvector; j++) { for (int k = 0; k < m_KsPerSubvector; k++) { - temp_m_L2DistanceTables[m_DistIndexCalc(i, j, k)] = L2Dist(&m_codebooks[baseIdx + j * m_DimPerSubvector], &m_codebooks[baseIdx + k * m_DimPerSubvector], m_DimPerSubvector); + temp_m_L2DistanceTables[m_DistIndexCalc(i, j, k)] = distFunc(&m_codebooks[baseIdx + j * m_DimPerSubvector], &m_codebooks[baseIdx + k * m_DimPerSubvector], m_DimPerSubvector); } } } diff --git a/AnnService/inc/Quantizer/Training.h b/AnnService/inc/Quantizer/Training.h index 718dbbb8b..d15d42f47 100644 --- a/AnnService/inc/Quantizer/Training.h +++ b/AnnService/inc/Quantizer/Training.h @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -13,7 +14,7 @@ using namespace SPTAG; class QuantizerOptions : public Helper::ReaderOptions { public: - QuantizerOptions(SizeType trainingSamples, bool debug, float lambda, SPTAG::QuantizerType qtype, std::string qfile, DimensionType qdim, std::string fullvecs, std::string recvecs) : Helper::ReaderOptions(VectorValueType::Float, 0, VectorFileType::TXT, "|", 32), m_trainingSamples(trainingSamples), m_debug(debug), m_KmeansLambda(lambda), m_quantizerType(qtype), m_outputQuantizerFile(qfile), m_quantizedDim(qdim), m_outputFullVecFile(fullvecs), m_outputReconstructVecFile(recvecs) + QuantizerOptions(SizeType trainingSamples, bool debug, float lambda, SPTAG::QuantizerType qtype, SPTAG::DistCalcMethod dm, std::string qfile, DimensionType qdim, std::string fullvecs, std::string recvecs) : Helper::ReaderOptions(VectorValueType::Float, 0, VectorFileType::TXT, "|", 32), m_trainingSamples(trainingSamples), m_debug(debug), m_KmeansLambda(lambda), m_quantizerType(qtype), m_distMethod(dm), m_outputQuantizerFile(qfile), m_quantizedDim(qdim), m_outputFullVecFile(fullvecs), m_outputReconstructVecFile(recvecs) { AddRequiredOption(m_inputFiles, "-i", "--input", "Input raw data."); AddRequiredOption(m_outputFile, "-o", "--output", "Output quantized vectors."); @@ -29,6 +30,7 @@ class QuantizerOptions : public Helper::ReaderOptions AddOptionalOption(m_KmeansLambda, "-kml", "--lambda", "Kmeans lambda parameter."); AddOptionalOption(m_outputFullVecFile, "-ofv", "--output_full", "Output Uncompressed vectors."); AddOptionalOption(m_outputFullVecFile, "-orv", "--output_reconstruct", "Output reconstructed vectors."); + AddOptionalOption(m_distMethod, "-dist", "--distance_function", "The distance calculation method."); } ~QuantizerOptions() {} @@ -53,6 +55,8 @@ class QuantizerOptions : public Helper::ReaderOptions SPTAG::QuantizerType m_quantizerType; + SPTAG::DistCalcMethod m_distMethod; + bool m_debug; float m_KmeansLambda; @@ -73,21 +77,19 @@ std::unique_ptr TrainPQQuantizer(std::shared_ptr options, #pragma omp parallel for for (int codebookIdx = 0; codebookIdx < options->m_quantizedDim; codebookIdx++) { SPTAGLIB_LOG(Helper::LogLevel::LL_Info, "Training Codebook %d.\n", codebookIdx); - auto kargs = COMMON::KmeansArgs(numCentroids, subdim, raw_vectors->Count(), options->m_threadNum, DistCalcMethod::L2, nullptr); - auto dset = COMMON::Dataset(raw_vectors->Count(), subdim, blockRows, raw_vectors->Count()); + COMMON::Dataset dset(raw_vectors->Count(), subdim, blockRows, raw_vectors->Count()); for (int vectorIdx = 0; vectorIdx < raw_vectors->Count(); vectorIdx++) { - auto raw_addr = reinterpret_cast(raw_vectors->GetVector(vectorIdx)) + (codebookIdx * subdim); - auto dset_addr = dset[vectorIdx]; - for (int k = 0; k < subdim; k++) { - dset_addr[k] = raw_addr[k]; - } + T* raw_addr = reinterpret_cast(raw_vectors->GetVector(vectorIdx)) + (codebookIdx * subdim); + T* dset_addr = dset[vectorIdx]; + std::memcpy(dset_addr, raw_addr, sizeof(T)*subdim); } std::vector localindices; localindices.resize(dset.R()); for (SizeType il = 0; il < localindices.size(); il++) localindices[il] = il; + auto kargs = COMMON::KmeansArgs(numCentroids, subdim, raw_vectors->Count(), options->m_threadNum, options->m_distMethod, nullptr); auto nclusters = COMMON::KmeansClustering(dset, localindices, 0, dset.R(), kargs, options->m_trainingSamples, options->m_KmeansLambda, options->m_debug, nullptr); std::vector reverselocalindex; @@ -120,4 +122,4 @@ std::unique_ptr TrainPQQuantizer(std::shared_ptr options, } return codebooks; -} \ No newline at end of file +} diff --git a/AnnService/src/Core/Common/DistanceUtils.cpp b/AnnService/src/Core/Common/DistanceUtils.cpp index 5c86cadff..979df6562 100644 --- a/AnnService/src/Core/Common/DistanceUtils.cpp +++ b/AnnService/src/Core/Common/DistanceUtils.cpp @@ -416,14 +416,34 @@ float DistanceUtils::ComputeL2Distance_SSE(const std::uint8_t* pX, const std::ui } float diff = DIFF128[0] + DIFF128[1] + DIFF128[2] + DIFF128[3]; + float c1; + uint8_t a, b; while (pX < pEnd4) { - float c1 = ((float)(*pX++) - (float)(*pY++)); diff += c1 * c1; - c1 = ((float)(*pX++) - (float)(*pY++)); diff += c1 * c1; - c1 = ((float)(*pX++) - (float)(*pY++)); diff += c1 * c1; - c1 = ((float)(*pX++) - (float)(*pY++)); diff += c1 * c1; + a = (*pX); b = (*pY); + c1 = a + 0.0f - b; + pX++; pY++; + diff += c1 * c1; + + a = (*pX); b = (*pY); + c1 = a + 0.0f - b; + pX++; pY++; + diff += c1 * c1; + + a = (*pX); b = (*pY); + c1 = a + 0.0f - b; + pX++; pY++; + diff += c1 * c1; + + a = (*pX); b = (*pY); + c1 = a + 0.0f - b; + pX++; pY++; + diff += c1 * c1; } while (pX < pEnd1) { - float c1 = ((float)(*pX++) - (float)(*pY++)); diff += c1 * c1; + a = (*pX); b = (*pY); + c1 = a + 0.0f - b; + pX++; pY++; + diff += c1 * c1; } return diff; } @@ -445,14 +465,34 @@ float DistanceUtils::ComputeL2Distance_AVX(const std::uint8_t* pX, const std::ui } float diff = DIFF128[0] + DIFF128[1] + DIFF128[2] + DIFF128[3]; + float c1; + uint8_t a, b; while (pX < pEnd4) { - float c1 = ((float)(*pX++) - (float)(*pY++)); diff += c1 * c1; - c1 = ((float)(*pX++) - (float)(*pY++)); diff += c1 * c1; - c1 = ((float)(*pX++) - (float)(*pY++)); diff += c1 * c1; - c1 = ((float)(*pX++) - (float)(*pY++)); diff += c1 * c1; + a = (*pX); b = (*pY); + c1 = a + 0.0f - b; + pX++; pY++; + diff += c1 * c1; + + a = (*pX); b = (*pY); + c1 = a + 0.0f - b; + pX++; pY++; + diff += c1 * c1; + + a = (*pX); b = (*pY); + c1 = a + 0.0f - b; + pX++; pY++; + diff += c1 * c1; + + a = (*pX); b = (*pY); + c1 = a + 0.0f - b; + pX++; pY++; + diff += c1 * c1; } while (pX < pEnd1) { - float c1 = ((float)(*pX++) - (float)(*pY++)); diff += c1 * c1; + a = (*pX); b = (*pY); + c1 = a + 0.0f - b; + pX++; pY++; + diff += c1 * c1; } return diff; } @@ -484,14 +524,34 @@ float DistanceUtils::ComputeL2Distance_AVX512(const std::uint8_t* pX, const std: } float diff = DIFF128[0] + DIFF128[1] + DIFF128[2] + DIFF128[3]; + float c1; + uint8_t a, b; while (pX < pEnd4) { - float c1 = ((float)(*pX++) - (float)(*pY++)); diff += c1 * c1; - c1 = ((float)(*pX++) - (float)(*pY++)); diff += c1 * c1; - c1 = ((float)(*pX++) - (float)(*pY++)); diff += c1 * c1; - c1 = ((float)(*pX++) - (float)(*pY++)); diff += c1 * c1; + a = (*pX); b = (*pY); + c1 = a + 0.0f - b; + pX++; pY++; + diff += c1 * c1; + + a = (*pX); b = (*pY); + c1 = a + 0.0f - b; + pX++; pY++; + diff += c1 * c1; + + a = (*pX); b = (*pY); + c1 = a + 0.0f - b; + pX++; pY++; + diff += c1 * c1; + + a = (*pX); b = (*pY); + c1 = a + 0.0f - b; + pX++; pY++; + diff += c1 * c1; } while (pX < pEnd1) { - float c1 = ((float)(*pX++) - (float)(*pY++)); diff += c1 * c1; + a = (*pX); b = (*pY); + c1 = a + 0.0f - b; + pX++; pY++; + diff += c1 * c1; } return diff; } diff --git a/AnnService/src/Quantizer/main.cpp b/AnnService/src/Quantizer/main.cpp index 5b61712b8..940416e8b 100644 --- a/AnnService/src/Quantizer/main.cpp +++ b/AnnService/src/Quantizer/main.cpp @@ -33,7 +33,7 @@ void QuantizeAndSave(std::shared_ptr& vectorRead #pragma omp parallel for for (int i = 0; i < set->Count(); i++) { - quantizer->QuantizeVector(set->GetVector(i), (uint8_t*)quantized_vectors->GetVector(i)); + quantizer->QuantizeVector(set->GetVector(i), (uint8_t*)quantized_vectors->GetVector(i), false); } ErrorCode code; @@ -68,7 +68,7 @@ void QuantizeAndSave(std::shared_ptr& vectorRead int main(int argc, char* argv[]) { - std::shared_ptr options = std::make_shared(10000, true, 0.0f, SPTAG::QuantizerType::None, std::string(), -1, std::string(), std::string()); + std::shared_ptr options = std::make_shared(10000, true, 0.0f, SPTAG::QuantizerType::None, SPTAG::DistCalcMethod::L2, std::string(), -1, std::string(), std::string()); if (!options->Parse(argc - 1, argv + 1)) { @@ -116,7 +116,7 @@ int main(int argc, char* argv[]) { #define DefineVectorValueType(Name, Type) \ case VectorValueType::Name: \ - quantizer.reset(new COMMON::PQQuantizer(options->m_quantizedDim, 256, (DimensionType)(options->m_dimension/options->m_quantizedDim), false, TrainPQQuantizer(options, set, quantized_vectors))); \ + quantizer.reset(new COMMON::PQQuantizer(options->m_quantizedDim, 256, (DimensionType)(options->m_dimension/options->m_quantizedDim), false, TrainPQQuantizer(options, set, quantized_vectors), options->m_distMethod)); \ break; #include "inc/Core/DefinitionList.h" diff --git a/Test/src/ReconstructIndexSimilarityTest.cpp b/Test/src/ReconstructIndexSimilarityTest.cpp index e7cf7a2ff..739d9b839 100644 --- a/Test/src/ReconstructIndexSimilarityTest.cpp +++ b/Test/src/ReconstructIndexSimilarityTest.cpp @@ -236,7 +236,7 @@ void GenerateReconstructData(std::shared_ptr& real_vecset, std::share } std::cout << "Building Finish!" << std::endl; - quantizer = std::make_shared>(M, Ks, QuanDim, false, std::move(codebooks)); + quantizer = std::make_shared>(M, Ks, QuanDim, false, std::move(codebooks), distCalcMethod); auto ptr = SPTAG::f_createIO(); if (ptr == nullptr || !ptr->Initialize(CODEBOOK_FILE.c_str(), std::ios::binary | std::ios::out)) { BOOST_ASSERT("Canot Open CODEBOOK_FILE to write!" == "Error"); diff --git a/Wrappers/inc/PythonCommon.i b/Wrappers/inc/PythonCommon.i index c27b3e5fd..846ab3d9e 100644 --- a/Wrappers/inc/PythonCommon.i +++ b/Wrappers/inc/PythonCommon.i @@ -22,8 +22,14 @@ { PyList_SetItem(dstVecIDs, i, PyInt_FromLong(res.VID)); PyList_SetItem(dstVecDists, i, PyFloat_FromDouble(res.Dist)); - if (res.RelaxedMono) PyList_SetItem(dstRelaxMono, i, Py_True); - else PyList_SetItem(dstRelaxMono, i, Py_False); + if (res.RelaxedMono) { + Py_INCREF(Py_True); + PyList_SetItem(dstRelaxMono, i, Py_True); + } + else { + Py_INCREF(Py_False); + PyList_SetItem(dstRelaxMono, i, Py_False); + } i++; } @@ -58,8 +64,14 @@ { PyList_Append(dstVecIDs, PyInt_FromLong(res.VID)); PyList_Append(dstVecDists, PyFloat_FromDouble(res.Dist)); - if (res.RelaxedMono) PyList_Append(dstRelaxMono, Py_True); - else PyList_Append(dstRelaxMono, Py_False); + if (res.RelaxedMono) { + Py_INCREF(Py_True); + PyList_Append(dstRelaxMono, Py_True); + } + else { + Py_INCREF(Py_False); + PyList_Append(dstRelaxMono, Py_False); + } } if (indexRes.m_results.WithMeta())