From 868ece90f1b76248ba36532037d3b90d61b8f681 Mon Sep 17 00:00:00 2001 From: ravishankar Date: Tue, 12 Nov 2024 08:38:06 -0800 Subject: [PATCH 1/9] add distance based stoppage --- apps/search_memory_index.cpp | 14 +++- old_baseline/baseline_r64_k10.txt | 84 +++++++++++++++++++ old_baseline/baseline_r64_k100.txt | 21 +++++ old_baseline/baseline_r64_k25.txt | 70 ++++++++++++++++ old_baseline/baseline_r64_k50.txt | 56 +++++++++++++ old_baseline/baseline_r64_l100.txt | 10 +++ prec40M/baseline_r64_k10.txt | 84 +++++++++++++++++++ prec40M/baseline_r64_k100.txt | 21 +++++ prec40M/baseline_r64_k25.txt | 70 ++++++++++++++++ prec40M/baseline_r64_k50.txt | 56 +++++++++++++ .../early_stop_1pc_r64_k10.txt | 84 +++++++++++++++++++ .../early_stop_1pc_r64_k100.txt | 21 +++++ .../early_stop_1pc_r64_k25.txt | 70 ++++++++++++++++ .../early_stop_1pc_r64_k50.txt | 56 +++++++++++++ run-search.sh | 5 ++ src/index.cpp | 26 ++++++ 16 files changed, 745 insertions(+), 3 deletions(-) create mode 100644 old_baseline/baseline_r64_k10.txt create mode 100644 old_baseline/baseline_r64_k100.txt create mode 100644 old_baseline/baseline_r64_k25.txt create mode 100644 old_baseline/baseline_r64_k50.txt create mode 100644 old_baseline/baseline_r64_l100.txt create mode 100644 prec40M/baseline_r64_k10.txt create mode 100644 prec40M/baseline_r64_k100.txt create mode 100644 prec40M/baseline_r64_k25.txt create mode 100644 prec40M/baseline_r64_k50.txt create mode 100644 prec40M/distance-based-stop/early_stop_1pc_r64_k10.txt create mode 100644 prec40M/distance-based-stop/early_stop_1pc_r64_k100.txt create mode 100644 prec40M/distance-based-stop/early_stop_1pc_r64_k25.txt create mode 100644 prec40M/distance-based-stop/early_stop_1pc_r64_k50.txt create mode 100644 run-search.sh diff --git a/apps/search_memory_index.cpp b/apps/search_memory_index.cpp index 1a9acc285..5dc1ea11f 100644 --- a/apps/search_memory_index.cpp +++ b/apps/search_memory_index.cpp @@ -109,9 +109,9 @@ int search_memory_index(diskann::Metric &metric, const std::string &index_path, } else { - std::cout << std::setw(4) << "Ls" << std::setw(12) << qps_title << std::setw(18) << "Avg dist cmps" + std::cout << std::setw(4) << "Ls" << std::setw(12) << qps_title << std::setw(18) << "Avg dist cmps" << std::setw(18) << "Avg hops" << std::setw(20) << "Mean Latency (mus)" << std::setw(15) << "99.9 Latency"; - table_width += 4 + 12 + 18 + 20 + 15; + table_width += 4 + 12 + 18 + 18+ 20 + 15; } uint32_t recalls_to_print = 0; const uint32_t first_recall = print_all_recalls ? 1 : recall_at; @@ -131,9 +131,11 @@ int search_memory_index(diskann::Metric &metric, const std::string &index_path, std::vector> query_result_dists(Lvec.size()); std::vector latency_stats(query_num, 0); std::vector cmp_stats; + std::vector hop_stats; if (not tags || filtered_search) { cmp_stats = std::vector(query_num, 0); + hop_stats = std::vector(query_num, 0); } std::vector query_result_tags; @@ -171,6 +173,7 @@ int search_memory_index(diskann::Metric &metric, const std::string &index_path, query_result_ids[test_id].data() + i * recall_at, query_result_dists[test_id].data() + i * recall_at); cmp_stats[i] = retval.second; + hop_stats[i] = retval.first; } else if (metric == diskann::FAST_L2) { @@ -203,6 +206,10 @@ int search_memory_index(diskann::Metric &metric, const std::string &index_path, ->search(query + i * query_aligned_dim, recall_at, L, query_result_ids[test_id].data() + i * recall_at) .second; + hop_stats[i] = index + ->search(query + i * query_aligned_dim, recall_at, L, + query_result_ids[test_id].data() + i * recall_at) + .first; } auto qe = std::chrono::high_resolution_clock::now(); std::chrono::duration diff = qe - qs; @@ -231,6 +238,7 @@ int search_memory_index(diskann::Metric &metric, const std::string &index_path, std::accumulate(latency_stats.begin(), latency_stats.end(), 0.0) / static_cast(query_num); float avg_cmps = (float)std::accumulate(cmp_stats.begin(), cmp_stats.end(), 0) / (float)query_num; + float avg_hops = (float)std::accumulate(hop_stats.begin(), hop_stats.end(), 0) / (float)query_num; if (tags && !filtered_search) { @@ -239,7 +247,7 @@ int search_memory_index(diskann::Metric &metric, const std::string &index_path, } else { - std::cout << std::setw(4) << L << std::setw(12) << displayed_qps << std::setw(18) << avg_cmps + std::cout << std::setw(4) << L << std::setw(12) << displayed_qps << std::setw(18) << avg_cmps << std::setw(18) << avg_hops << std::setw(20) << (float)mean_latency << std::setw(15) << (float)latency_stats[(uint64_t)(0.999 * query_num)]; } diff --git a/old_baseline/baseline_r64_k10.txt b/old_baseline/baseline_r64_k10.txt new file mode 100644 index 000000000..6b9af1d0e --- /dev/null +++ b/old_baseline/baseline_r64_k10.txt @@ -0,0 +1,84 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.40021s +From graph header, expected_file_size: 7438757948, _max_observed_degree: 64, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100.......done. Index has 40469609 nodes and 1819219872 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 48 threads to search + Ls QPS Avg dist cmps Mean Latency (mus) 99.9 Latency Recall@10 +================================================================================= + 10 51557.93 1324.67 913.18 9792.77 43.13 + 20 33640.81 2021.14 1420.26 3249.95 58.38 + 30 25210.59 2617.97 1896.59 4469.27 66.24 + 40 20547.19 3168.06 2326.82 5450.12 71.25 + 50 17328.33 3687.22 2760.19 6599.82 74.44 + 60 14980.50 4195.96 3193.32 7739.67 76.98 + 70 13341.03 4685.40 3588.47 8306.07 78.78 + 80 11462.47 5171.15 4176.58 11172.33 80.21 + 90 10723.69 5654.48 4462.36 10865.74 81.53 + 100 9782.57 6129.37 4892.21 12162.22 82.58 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_10_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_10_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_20_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_20_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_30_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_30_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_40_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_40_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_60_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_60_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_70_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_70_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_80_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_80_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_90_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_90_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. diff --git a/old_baseline/baseline_r64_k100.txt b/old_baseline/baseline_r64_k100.txt new file mode 100644 index 000000000..b6c634e16 --- /dev/null +++ b/old_baseline/baseline_r64_k100.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.40809s +From graph header, expected_file_size: 7438757948, _max_observed_degree: 64, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100.......done. Index has 40469609 nodes and 1819219872 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 48 threads to search + Ls QPS Avg dist cmps Mean Latency (mus) 99.9 Latency Recall@100 +================================================================================= + 100 10331.70 6129.37 4626.05 11214.14 66.81 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +bin: #pts = 13265, #dims = 100, size = 5306008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +bin: #pts = 13265, #dims = 100, size = 5306008B +Finished writing bin. diff --git a/old_baseline/baseline_r64_k25.txt b/old_baseline/baseline_r64_k25.txt new file mode 100644 index 000000000..eaf63e5de --- /dev/null +++ b/old_baseline/baseline_r64_k25.txt @@ -0,0 +1,70 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.48129s +From graph header, expected_file_size: 7438757948, _max_observed_degree: 64, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100.......done. Index has 40469609 nodes and 1819219872 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 48 threads to search + Ls QPS Avg dist cmps Mean Latency (mus) 99.9 Latency Recall@25 +================================================================================= + 30 25253.53 2617.97 1885.01 10497.99 60.18 + 40 20654.60 3168.06 2316.21 5201.40 65.38 + 50 17413.17 3687.22 2747.47 6720.12 68.82 + 60 15010.45 4195.96 3187.87 7331.08 71.60 + 70 13300.10 4685.40 3599.56 8146.48 73.66 + 80 11990.02 5171.15 3991.75 8909.45 75.35 + 90 10918.86 5654.48 4385.05 9846.92 76.87 + 100 9976.54 6129.37 4799.29 10763.89 78.14 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_30_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_30_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_40_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_40_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_60_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_60_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_70_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_70_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_80_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_80_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_90_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_90_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. diff --git a/old_baseline/baseline_r64_k50.txt b/old_baseline/baseline_r64_k50.txt new file mode 100644 index 000000000..45e6b863f --- /dev/null +++ b/old_baseline/baseline_r64_k50.txt @@ -0,0 +1,56 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.39346s +From graph header, expected_file_size: 7438757948, _max_observed_degree: 64, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100.......done. Index has 40469609 nodes and 1819219872 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Mean Latency (mus) 99.9 Latency Recall@50 +================================================================================= + 50 750.71 3687.22 1332.03 15081.17 62.96 + 60 664.89 4195.96 1503.96 13729.61 65.92 + 70 595.61 4685.40 1678.89 12513.98 68.19 + 80 539.72 5171.15 1852.77 12737.32 70.07 + 90 493.28 5654.48 2027.21 12803.06 71.76 + 100 453.69 6129.37 2204.12 15871.16 73.17 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_60_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_60_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_70_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_70_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_80_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_80_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_90_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_90_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. diff --git a/old_baseline/baseline_r64_l100.txt b/old_baseline/baseline_r64_l100.txt new file mode 100644 index 000000000..b86d0c55f --- /dev/null +++ b/old_baseline/baseline_r64_l100.txt @@ -0,0 +1,10 @@ +Starting index build with R: 64 Lbuild: 100 alpha: 1.2 #threads: 48 +Using AVX2 distance computation DistanceL2Int8. +Using only first 40469609 from file.. +Starting index build with 40469609 points... + 0% of index build completed. 0.247099% of index build completed. 0.494198% of index build completed. 0.741297% of index build completed. 0.988396% of index build completed. 1.2355% of index build completed. 1.48259% of index build completed. 1.72969% of index build completed. 1.97679% of index build completed. 2.22389% of index build completed. 2.47099% of index build completed. 2.71809% of index build completed. 2.96519% of index build completed. 3.21229% of index build completed. 3.45939% of index build completed. 3.70649% of index build completed. 3.95358% of index build completed. 4.20068% of index build completed. 4.44778% of index build completed. 4.69488% of index build completed. 4.94198% of index build completed. 5.18908% of index build completed. 5.43618% of index build completed. 5.68328% of index build completed. 5.93038% of index build completed. 6.17748% of index build completed. 6.42457% of index build completed. 6.67167% of index build completed. 6.91877% of index build completed. 7.16587% of index build completed. 7.41297% of index build completed. 7.66007% of index build completed. 7.90717% of index build completed. 8.15427% of index build completed. 8.40137% of index build completed. 8.64847% of index build completed. 8.89556% of index build completed. 9.14266% of index build completed. 9.38976% of index build completed. 9.63686% of index build completed. 9.88396% of index build completed. 10.1311% of index build completed. 10.3782% of index build completed. 10.6253% of index build completed. 10.8724% of index build completed. 11.1195% of index build completed. 11.3666% of index build completed. 11.6137% of index build completed. 11.8608% of index build completed. 12.1079% of index build completed. 12.355% of index build completed. 12.602% of index build completed. 12.8491% of index build completed. 13.0962% of index build completed. 13.3433% of index build completed. 13.5904% of index build completed. 13.8375% of index build completed. 14.0846% of index build completed. 14.3317% of index build completed. 14.5788% of index build completed. 14.8259% of index build completed. 15.073% of index build completed. 15.3201% of index build completed. 15.5672% of index build completed. 15.8143% of index build completed. 16.0614% of index build completed. 16.3085% of index build completed. 16.5556% of index build completed. 16.8027% of index build completed. 17.0498% of index build completed. 17.2969% of index build completed. 17.544% of index build completed. 17.7911% of index build completed. 18.0382% of index build completed. 18.2853% of index build completed. 18.5324% of index build completed. 18.7795% of index build completed. 19.0266% of index build completed. 19.2737% of index build completed. 19.5208% of index build completed. 19.7679% of index build completed. 20.015% of index build completed. 20.2621% of index build completed. 20.5092% of index build completed. 20.7563% of index build completed. 21.0034% of index build completed. 21.2505% of index build completed. 21.4976% of index build completed. 21.7447% of index build completed. 21.9918% of index build completed. 22.2389% of index build completed. 22.486% of index build completed. 22.7331% of index build completed. 22.9802% of index build completed. 23.2273% of index build completed. 23.4744% of index build completed. 23.7215% of index build completed. 23.9686% of index build completed. 24.2157% of index build completed. 24.4628% of index build completed. 24.7099% of index build completed. 24.957% of index build completed. 25.2041% of index build completed. 25.4512% of index build completed. 25.6983% of index build completed. 25.9454% of index build completed. 26.1925% of index build completed. 26.4396% of index build completed. 26.6867% of index build completed. 26.9338% of index build completed. 27.1809% of index build completed. 27.428% of index build completed. 27.6751% of index build completed. 27.9222% of index build completed. 28.1693% of index build completed. 28.4164% of index build completed. 28.6635% of index build completed. 28.9106% of index build completed. 29.1577% of index build completed. 29.4048% of index build completed. 29.6519% of index build completed. 29.899% of index build completed. 30.1461% of index build completed. 30.3932% of index build completed. 30.6403% of index build completed. 30.8874% of index build completed. 31.1345% of index build completed. 31.3816% of index build completed. 31.6287% of index build completed. 31.8758% of index build completed. 32.1229% of index build completed. 32.37% of index build completed. 32.6171% of index build completed. 32.8642% of index build completed. 33.1113% of index build completed. 33.3584% of index build completed. 33.6055% of index build completed. 33.8526% of index build completed. 34.0997% of index build completed. 34.3468% of index build completed. 34.5939% of index build completed. 34.841% of index build completed. 35.0881% of index build completed. 35.3352% of index build completed. 35.5823% of index build completed. 35.8294% of index build completed. 36.0765% of index build completed. 36.3236% of index build completed. 36.5707% of index build completed. 36.8178% of index build completed. 37.0649% of index build completed. 37.3119% of index build completed. 37.559% of index build completed. 37.8061% of index build completed. 38.0532% of index build completed. 38.3003% of index build completed. 38.5474% of index build completed. 38.7945% of index build completed. 39.0416% of index build completed. 39.2887% of index build completed. 39.5358% of index build completed. 39.7829% of index build completed. 40.03% of index build completed. 40.2771% of index build completed. 40.5242% of index build completed. 40.7713% of index build completed. 41.0184% of index build completed. 41.2655% of index build completed. 41.5126% of index build completed. 41.7597% of index build completed. 42.0068% of index build completed. 42.2539% of index build completed. 42.501% of index build completed. 42.7481% of index build completed. 42.9952% of index build completed. 43.2423% of index build completed. 43.4894% of index build completed. 43.7365% of index build completed. 43.9836% of index build completed. 44.2307% of index build completed. 44.4778% of index build completed. 44.7249% of index build completed. 44.972% of index build completed. 45.2191% of index build completed. 45.4662% of index build completed. 45.7133% of index build completed. 45.9604% of index build completed. 46.2075% of index build completed. 46.4546% of index build completed. 46.7017% of index build completed. 46.9488% of index build completed. 47.1959% of index build completed. 47.443% of index build completed. 47.6901% of index build completed. 47.9372% of index build completed. 48.1843% of index build completed. 48.4314% of index build completed. 48.6785% of index build completed. 48.9256% of index build completed. 49.1727% of index build completed. 49.4198% of index build completed. 49.6669% of index build completed. 49.914% of index build completed. 50.1611% of index build completed. 50.4082% of index build completed. 50.6553% of index build completed. 50.9024% of index build completed. 51.1495% of index build completed. 51.3966% of index build completed. 51.6437% of index build completed. 51.8908% of index build completed. 52.1379% of index build completed. 52.385% of index build completed. 52.6321% of index build completed. 52.8792% of index build completed. 53.1263% of index build completed. 53.3734% of index build completed. 53.6205% of index build completed. 53.8676% of index build completed. 54.1147% of index build completed. 54.3618% of index build completed. 54.6089% of index build completed. 54.856% of index build completed. 55.1031% of index build completed. 55.3502% of index build completed. 55.5973% of index build completed. 55.8444% of index build completed. 56.0915% of index build completed. 56.3386% of index build completed. 56.5857% of index build completed. 56.8328% of index build completed. 57.0799% of index build completed. 57.327% of index build completed. 57.5741% of index build completed. 57.8212% of index build completed. 58.0683% of index build completed. 58.3154% of index build completed. 58.5625% of index build completed. 58.8096% of index build completed. 59.0567% of index build completed. 59.3038% of index build completed. 59.5509% of index build completed. 59.798% of index build completed. 60.0451% of index build completed. 60.2922% of index build completed. 60.5393% of index build completed. 60.7864% of index build completed. 61.0335% of index build completed. 61.2806% of index build completed. 61.5277% of index build completed. 61.7748% of index build completed. 62.0218% of index build completed. 62.2689% of index build completed. 62.516% of index build completed. 62.7631% of index build completed. 63.0102% of index build completed. 63.2573% of index build completed. 63.5044% of index build completed. 63.7515% of index build completed. 63.9986% of index build completed. 64.2457% of index build completed. 64.4928% of index build completed. 64.7399% of index build completed. 64.987% of index build completed. 65.2341% of index build completed. 65.4812% of index build completed. 65.7283% of index build completed. 65.9754% of index build completed. 66.2225% of index build completed. 66.4696% of index build completed. 66.7167% of index build completed. 66.9638% of index build completed. 67.2109% of index build completed. 67.458% of index build completed. 67.7051% of index build completed. 67.9522% of index build completed. 68.1993% of index build completed. 68.4464% of index build completed. 68.6935% of index build completed. 68.9406% of index build completed. 69.1877% of index build completed. 69.4348% of index build completed. 69.6819% of index build completed. 69.929% of index build completed. 70.1761% of index build completed. 70.4232% of index build completed. 70.6703% of index build completed. 70.9174% of index build completed. 71.1645% of index build completed. 71.4116% of index build completed. 71.6587% of index build completed. 71.9058% of index build completed. 72.1529% of index build completed. 72.4% of index build completed. 72.6471% of index build completed. 72.8942% of index build completed. 73.1413% of index build completed. 73.3884% of index build completed. 73.6355% of index build completed. 73.8826% of index build completed. 74.1297% of index build completed. 74.3768% of index build completed. 74.6239% of index build completed. 74.871% of index build completed. 75.1181% of index build completed. 75.3652% of index build completed. 75.6123% of index build completed. 75.8594% of index build completed. 76.1065% of index build completed. 76.3536% of index build completed. 76.6007% of index build completed. 76.8478% of index build completed. 77.0949% of index build completed. 77.342% of index build completed. 77.5891% of index build completed. 77.8362% of index build completed. 78.0833% of index build completed. 78.3304% of index build completed. 78.5775% of index build completed. 78.8246% of index build completed. 79.0717% of index build completed. 79.3188% of index build completed. 79.5659% of index build completed. 79.813% of index build completed. 80.0601% of index build completed. 80.3072% of index build completed. 80.5543% of index build completed. 80.8014% of index build completed. 81.0485% of index build completed. 81.2956% of index build completed. 81.5427% of index build completed. 81.7898% of index build completed. 82.0369% of index build completed. 82.284% of index build completed. 82.5311% of index build completed. 82.7782% of index build completed. 83.0253% of index build completed. 83.2724% of index build completed. 83.5195% of index build completed. 83.7666% of index build completed. 84.0137% of index build completed. 84.2608% of index build completed. 84.5079% of index build completed. 84.755% of index build completed. 85.0021% of index build completed. 85.2492% of index build completed. 85.4963% of index build completed. 85.7434% of index build completed. 85.9905% of index build completed. 86.2376% of index build completed. 86.4847% of index build completed. 86.7317% of index build completed. 86.9788% of index build completed. 87.2259% of index build completed. 87.473% of index build completed. 87.7201% of index build completed. 87.9672% of index build completed. 88.2143% of index build completed. 88.4614% of index build completed. 88.7085% of index build completed. 88.9556% of index build completed. 89.2027% of index build completed. 89.4498% of index build completed. 89.6969% of index build completed. 89.944% of index build completed. 90.1911% of index build completed. 90.4382% of index build completed. 90.6853% of index build completed. 90.9324% of index build completed. 91.1795% of index build completed. 91.4266% of index build completed. 91.6737% of index build completed. 91.9208% of index build completed. 92.1679% of index build completed. 92.415% of index build completed. 92.6621% of index build completed. 92.9092% of index build completed. 93.1563% of index build completed. 93.4034% of index build completed. 93.6505% of index build completed. 93.8976% of index build completed. 94.1447% of index build completed. 94.3918% of index build completed. 94.6389% of index build completed. 94.886% of index build completed. 95.1331% of index build completed. 95.3802% of index build completed. 95.6273% of index build completed. 95.8744% of index build completed. 96.1215% of index build completed. 96.3686% of index build completed. 96.6157% of index build completed. 96.8628% of index build completed. 97.1099% of index build completed. 97.357% of index build completed. 97.6041% of index build completed. 97.8512% of index build completed. 98.0983% of index build completed. 98.3454% of index build completed. 98.5925% of index build completed. 98.8396% of index build completed. 99.0867% of index build completed. 99.3338% of index build completed. 99.5809% of index build completed. 99.828% of index build completed.Starting final cleanup..done. Link time: 3495.63s +Index built with degree: max:64 avg:44.9527 min:1 count(deg<2):1019259 +Robust Prune Calls: 108594089 +Indexing time: 3504.72 +Not saving tags as they are not enabled. +Time taken for save: 19.6696s. diff --git a/prec40M/baseline_r64_k10.txt b/prec40M/baseline_r64_k10.txt new file mode 100644 index 000000000..b24e59680 --- /dev/null +++ b/prec40M/baseline_r64_k10.txt @@ -0,0 +1,84 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.33364s +From graph header, expected_file_size: 7438757948, _max_observed_degree: 64, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100.......done. Index has 40469609 nodes and 1819219872 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@10 +=================================================================================================== + 10 1176.02 1324.67 25.15 850.27 3232.74 43.13 + 20 819.47 2021.14 38.20 1220.24 4711.67 58.38 + 30 602.84 2617.97 49.73 1658.77 6214.68 66.24 + 40 470.64 3168.06 60.58 2124.69 6657.69 71.25 + 50 396.33 3687.22 70.97 2523.10 9243.96 74.44 + 60 344.13 4195.96 81.27 2905.83 9802.10 76.98 + 70 305.17 4685.40 91.30 3276.85 12570.57 78.78 + 80 274.43 5171.15 101.32 3643.83 12268.22 80.21 + 90 249.33 5654.48 111.37 4010.62 14590.95 81.53 + 100 229.07 6129.37 121.32 4365.34 14753.94 82.58 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_10_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_10_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_20_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_20_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_30_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_30_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_40_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_40_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_60_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_60_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_70_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_70_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_80_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_80_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_90_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_90_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. diff --git a/prec40M/baseline_r64_k100.txt b/prec40M/baseline_r64_k100.txt new file mode 100644 index 000000000..93b86df0d --- /dev/null +++ b/prec40M/baseline_r64_k100.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.37236s +From graph header, expected_file_size: 7438757948, _max_observed_degree: 64, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100.......done. Index has 40469609 nodes and 1819219872 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@100 +=================================================================================================== + 100 217.00 6129.37 121.32 4608.19 13353.83 66.81 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +bin: #pts = 13265, #dims = 100, size = 5306008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +bin: #pts = 13265, #dims = 100, size = 5306008B +Finished writing bin. diff --git a/prec40M/baseline_r64_k25.txt b/prec40M/baseline_r64_k25.txt new file mode 100644 index 000000000..c52c4d3fa --- /dev/null +++ b/prec40M/baseline_r64_k25.txt @@ -0,0 +1,70 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.36738s +From graph header, expected_file_size: 7438757948, _max_observed_degree: 64, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100.......done. Index has 40469609 nodes and 1819219872 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@25 +=================================================================================================== + 30 535.01 2617.97 49.73 1869.07 6384.29 60.18 + 40 471.19 3168.06 60.58 2122.23 7482.87 65.38 + 50 400.24 3687.22 70.97 2498.41 7306.91 68.82 + 60 344.31 4195.96 81.27 2904.30 10851.25 71.60 + 70 305.49 4685.40 91.30 3273.41 11079.77 73.66 + 80 274.40 5171.15 101.32 3644.27 13173.09 75.35 + 90 249.78 5654.48 111.37 4003.45 14204.55 76.87 + 100 228.86 6129.37 121.32 4369.40 14582.85 78.14 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_30_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_30_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_40_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_40_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_60_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_60_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_70_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_70_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_80_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_80_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_90_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_90_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. diff --git a/prec40M/baseline_r64_k50.txt b/prec40M/baseline_r64_k50.txt new file mode 100644 index 000000000..9f4a83f1b --- /dev/null +++ b/prec40M/baseline_r64_k50.txt @@ -0,0 +1,56 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.3678s +From graph header, expected_file_size: 7438757948, _max_observed_degree: 64, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100.......done. Index has 40469609 nodes and 1819219872 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@50 +=================================================================================================== + 50 363.96 3687.22 70.97 2747.47 8534.45 62.96 + 60 344.07 4195.96 81.27 2906.31 10733.88 65.92 + 70 305.54 4685.40 91.30 3272.87 10640.61 68.19 + 80 274.47 5171.15 101.32 3643.38 13795.25 70.07 + 90 249.35 5654.48 111.37 4010.40 14678.43 71.76 + 100 228.82 6129.37 121.32 4370.23 17002.81 73.17 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_60_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_60_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_70_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_70_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_80_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_80_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_90_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_90_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. diff --git a/prec40M/distance-based-stop/early_stop_1pc_r64_k10.txt b/prec40M/distance-based-stop/early_stop_1pc_r64_k10.txt new file mode 100644 index 000000000..746101b85 --- /dev/null +++ b/prec40M/distance-based-stop/early_stop_1pc_r64_k10.txt @@ -0,0 +1,84 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.38647s +From graph header, expected_file_size: 7438757948, _max_observed_degree: 64, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100.......done. Index has 40469609 nodes and 1819219872 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@10 +=================================================================================================== + 10 5601.33 331.51 7.73 178.50 1213.03 6.83 + 20 7570.89 332.91 7.77 132.06 872.51 6.86 + 30 7235.70 332.92 7.77 138.18 850.40 6.86 + 40 7103.38 332.92 7.77 140.75 857.32 6.86 + 50 6943.05 332.92 7.77 144.00 868.61 6.86 + 60 6923.15 332.92 7.77 144.41 870.57 6.86 + 70 6128.61 357.67 8.26 163.14 938.15 7.44 + 80 5765.07 381.73 8.75 173.43 936.66 8.22 + 90 5597.03 392.64 8.97 178.64 939.07 8.60 + 100 4863.46 438.01 10.00 205.59 956.61 9.65 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_10_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_10_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_20_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_20_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_30_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_30_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_40_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_40_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_60_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_60_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_70_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_70_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_80_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_80_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_90_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_90_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. diff --git a/prec40M/distance-based-stop/early_stop_1pc_r64_k100.txt b/prec40M/distance-based-stop/early_stop_1pc_r64_k100.txt new file mode 100644 index 000000000..3b556b8a4 --- /dev/null +++ b/prec40M/distance-based-stop/early_stop_1pc_r64_k100.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.42052s +From graph header, expected_file_size: 7438757948, _max_observed_degree: 64, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100.......done. Index has 40469609 nodes and 1819219872 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@100 +=================================================================================================== + 100 3806.55 438.01 10.00 262.67 1432.43 5.57 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +bin: #pts = 13265, #dims = 100, size = 5306008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +bin: #pts = 13265, #dims = 100, size = 5306008B +Finished writing bin. diff --git a/prec40M/distance-based-stop/early_stop_1pc_r64_k25.txt b/prec40M/distance-based-stop/early_stop_1pc_r64_k25.txt new file mode 100644 index 000000000..729e13f5e --- /dev/null +++ b/prec40M/distance-based-stop/early_stop_1pc_r64_k25.txt @@ -0,0 +1,70 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.41602s +From graph header, expected_file_size: 7438757948, _max_observed_degree: 64, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100.......done. Index has 40469609 nodes and 1819219872 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@25 +=================================================================================================== + 30 5281.62 332.92 7.77 189.31 1354.39 5.83 + 40 7050.04 332.92 7.77 141.82 863.16 5.83 + 50 6997.94 332.92 7.77 142.87 877.10 5.83 + 60 6873.09 332.92 7.77 145.47 868.20 5.83 + 70 6157.34 357.67 8.26 162.38 951.35 6.32 + 80 5790.40 381.73 8.75 172.67 927.46 7.00 + 90 5606.04 392.64 8.97 178.35 900.73 7.33 + 100 4926.95 438.01 10.00 202.94 953.73 8.21 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_30_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_30_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_40_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_40_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_60_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_60_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_70_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_70_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_80_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_80_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_90_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_90_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +bin: #pts = 13265, #dims = 25, size = 1326508B +Finished writing bin. diff --git a/prec40M/distance-based-stop/early_stop_1pc_r64_k50.txt b/prec40M/distance-based-stop/early_stop_1pc_r64_k50.txt new file mode 100644 index 000000000..9e6475cb2 --- /dev/null +++ b/prec40M/distance-based-stop/early_stop_1pc_r64_k50.txt @@ -0,0 +1,56 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.41114s +From graph header, expected_file_size: 7438757948, _max_observed_degree: 64, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100.......done. Index has 40469609 nodes and 1819219872 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@50 +=================================================================================================== + 50 5148.20 332.92 7.77 194.21 1346.07 4.94 + 60 6898.92 332.92 7.77 144.92 860.76 4.94 + 70 6218.21 357.67 8.26 160.79 930.09 5.34 + 80 5745.99 381.73 8.75 174.01 910.59 5.91 + 90 5635.25 392.64 8.97 177.43 923.18 6.18 + 100 4940.16 438.01 10.00 202.39 984.91 6.93 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_60_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_60_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_70_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_70_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_80_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_80_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_90_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_90_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. diff --git a/run-search.sh b/run-search.sh new file mode 100644 index 000000000..52cb8e4d3 --- /dev/null +++ b/run-search.sh @@ -0,0 +1,5 @@ +cd build +./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 10 -L 10 20 30 40 50 60 70 80 90 100 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early_stop_1pc_r64_k10.txt +./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 25 -L 30 40 50 60 70 80 90 100 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early_stop_1pc_r64_k25.txt +./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 50 -L 50 60 70 80 90 100 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early_stop_1pc_r64_k50.txt +./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 100 -L 100 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early_stop_1pc_r64_k100.txt \ No newline at end of file diff --git a/src/index.cpp b/src/index.cpp index bf93344fa..0e613f391 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -880,11 +880,28 @@ std::pair Index::iterate_to_fixed_point( uint32_t hops = 0; uint32_t cmps = 0; + float prev_distance_to_query = 0.0; while (best_L_nodes.has_unexpanded_node()) { auto nbr = best_L_nodes.closest_unexpanded(); auto n = nbr.id; + hops++; + if(search_invocation){ + std::vector id_scratch_temp = {n}; + std::vector dist_scratch_temp = {0.0}; + compute_dists(id_scratch_temp, dist_scratch_temp); + float change_in_distance = std::abs(dist_scratch_temp[0] - prev_distance_to_query); + if (best_L_nodes.size() == Lsize && (float)(change_in_distance/(dist_scratch_temp[0] + 1e-6)) < 0.01){ + break; + } + prev_distance_to_query = dist_scratch_temp[0]; + //diskann::cout<<"Iteration/Hop: #"< Index::iterate_to_fixed_point( best_L_nodes.insert(Neighbor(id_scratch[m], dist_scratch[m])); } } + // if (search_invocation){ + // diskann::cout<<"Total Iterations/Hops: "<expanded_nodes_vec().size()<expanded_nodes_vec()){ + // diskann::cout< Date: Thu, 21 Nov 2024 10:41:18 +0530 Subject: [PATCH 2/9] update early stoppage --- include/index.h | 2 +- include/neighbor.h | 43 +++++++++++++++++++++++++--- src/index.cpp | 70 ++++++++++++++++++++++++++++++---------------- 3 files changed, 86 insertions(+), 29 deletions(-) diff --git a/include/index.h b/include/index.h index b9bf4f384..a5326db4e 100644 --- a/include/index.h +++ b/include/index.h @@ -257,7 +257,7 @@ template clas // The query to use is placed in scratch->aligned_query std::pair iterate_to_fixed_point(InMemQueryScratch *scratch, const uint32_t Lindex, - const std::vector &init_ids, bool use_filter, + const size_t K, const std::vector &init_ids, bool use_filter, const std::vector &filters, bool search_invocation); void search_for_point_and_prune(int location, uint32_t Lindex, std::vector &pruned_list, diff --git a/include/neighbor.h b/include/neighbor.h index d7c0c25ed..2dc6145d4 100644 --- a/include/neighbor.h +++ b/include/neighbor.h @@ -52,11 +52,12 @@ class NeighborPriorityQueue // set item or it has a greated distance than the final // item in the set. The set cursor that is used to pop() the // next item will be set to the lowest index of an uncheck item - void insert(const Neighbor &nbr) - { + int insert(const Neighbor &nbr, const size_t K) + { + int return_val = 0; if (_size == _capacity && _data[_size - 1] < nbr) { - return; + return 0; } size_t lo = 0, hi = _size; @@ -70,7 +71,7 @@ class NeighborPriorityQueue } else if (_data[mid].id == nbr.id) { - return; + return 0; } else { @@ -83,6 +84,9 @@ class NeighborPriorityQueue std::memmove(&_data[lo + 1], &_data[lo], (_size - lo) * sizeof(Neighbor)); } _data[lo] = {nbr.id, nbr.distance}; + if(lo < K){ + return_val = 1; + } if (_size < _capacity) { _size++; @@ -91,6 +95,37 @@ class NeighborPriorityQueue { _cur = lo; } + return return_val; + } + + int check_in_top_k(const Neighbor &nbr, size_t K) + { + if (_size == _capacity && _data[_size - 1] < nbr) + { + return 0; + } + + size_t lo = 0, hi = _size; + while (lo < hi) + { + size_t mid = (lo + hi) >> 1; + if (nbr < _data[mid]) + { + hi = mid; + } + else if (_data[mid].id == nbr.id) + { + return 0; + } + else + { + lo = mid + 1; + } + } + if(lo < K){ + return 1; + } + return 0; } Neighbor closest_unexpanded() diff --git a/src/index.cpp b/src/index.cpp index 0e613f391..3fec494c3 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -4,7 +4,8 @@ #include #include - +#include +#include #include "boost/dynamic_bitset.hpp" #include "index_factory.h" #include "memory_mapper.h" @@ -790,7 +791,7 @@ bool Index::detect_common_filters(uint32_t point_id, bool searc template std::pair Index::iterate_to_fixed_point( - InMemQueryScratch *scratch, const uint32_t Lsize, const std::vector &init_ids, bool use_filter, + InMemQueryScratch *scratch, const uint32_t Lsize, const size_t K, const std::vector &init_ids, bool use_filter, const std::vector &filter_labels, bool search_invocation) { std::vector &expanded_nodes = scratch->pool(); @@ -880,25 +881,41 @@ std::pair Index::iterate_to_fixed_point( uint32_t hops = 0; uint32_t cmps = 0; + std::queue last_K_insertions; + int x = 5; + int y = 0; float prev_distance_to_query = 0.0; + while (best_L_nodes.has_unexpanded_node()) - { + { + hops++; + + // Check if the sum of elements of the deque is less than y, if yes then exit the loop + int sum_last_K_insertions = 0; + std::queue temp_queue = last_K_insertions; + while (!temp_queue.empty()) { + sum_last_K_insertions += temp_queue.front(); + temp_queue.pop(); + } + if (sum_last_K_insertions <= y && hops >= x) { + break; + } + auto nbr = best_L_nodes.closest_unexpanded(); auto n = nbr.id; - hops++; if(search_invocation){ - std::vector id_scratch_temp = {n}; - std::vector dist_scratch_temp = {0.0}; - compute_dists(id_scratch_temp, dist_scratch_temp); - float change_in_distance = std::abs(dist_scratch_temp[0] - prev_distance_to_query); - if (best_L_nodes.size() == Lsize && (float)(change_in_distance/(dist_scratch_temp[0] + 1e-6)) < 0.01){ - break; - } - prev_distance_to_query = dist_scratch_temp[0]; - //diskann::cout<<"Iteration/Hop: #"< id_scratch_temp = {n}; + // std::vector dist_scratch_temp = {0.0}; + // compute_dists(id_scratch_temp, dist_scratch_temp); + // float change_in_distance = std::abs(dist_scratch_temp[0] - prev_distance_to_query); + // if (best_L_nodes.size() == Lsize && (float)(change_in_distance/(dist_scratch_temp[0] + 1e-6)) < 0.01){ + // break; + // } + // prev_distance_to_query = dist_scratch_temp[0]; + diskann::cout<<"Iteration/Hop: #"< Index::iterate_to_fixed_point( cmps += (uint32_t)id_scratch.size(); // Insert pairs into the pool of candidates + int insertions_this_iter = 0; for (size_t m = 0; m < id_scratch.size(); ++m) - { - best_L_nodes.insert(Neighbor(id_scratch[m], dist_scratch[m])); + { + insertions_this_iter += best_L_nodes.insert(Neighbor(id_scratch[m], dist_scratch[m])); + } + last_K_insertions.push(insertions_this_iter); + if (last_K_insertions.size() > x) { + last_K_insertions.pop(); } } // if (search_invocation){ @@ -1013,7 +1035,7 @@ void Index::search_for_point_and_prune(int location, uint32_t L if (!use_filter) { _data_store->get_vector(location, scratch->aligned_query()); - iterate_to_fixed_point(scratch, Lindex, init_ids, false, unused_filter_label, false); + iterate_to_fixed_point(scratch, Lindex, Lindex, init_ids, false, unused_filter_label, false); } else { @@ -1028,7 +1050,7 @@ void Index::search_for_point_and_prune(int location, uint32_t L tl.unlock(); _data_store->get_vector(location, scratch->aligned_query()); - iterate_to_fixed_point(scratch, filteredLindex, filter_specific_start_nodes, true, + iterate_to_fixed_point(scratch, filteredLindex, Lindex, filter_specific_start_nodes, true, _location_to_labels[location], false); // combine candidate pools obtained with filter and unfiltered criteria. @@ -1042,7 +1064,7 @@ void Index::search_for_point_and_prune(int location, uint32_t L scratch->clear(); _data_store->get_vector(location, scratch->aligned_query()); - iterate_to_fixed_point(scratch, Lindex, init_ids, false, unused_filter_label, false); + iterate_to_fixed_point(scratch, Lindex, Lindex, init_ids, false, unused_filter_label, false); for (auto unfiltered_neighbour : scratch->pool()) { @@ -2009,7 +2031,7 @@ std::pair Index::search(const T *query, con _data_store->preprocess_query(query, scratch); - auto retval = iterate_to_fixed_point(scratch, L, init_ids, false, unused_filter_label, true); + auto retval = iterate_to_fixed_point(scratch, L, K, init_ids, false, unused_filter_label, true); NeighborPriorityQueue &best_L_nodes = scratch->best_l_nodes(); @@ -2113,7 +2135,7 @@ std::pair Index::search_with_filters(const filter_vec.emplace_back(filter_label); _data_store->preprocess_query(query, scratch); - auto retval = iterate_to_fixed_point(scratch, L, init_ids, true, filter_vec, true); + auto retval = iterate_to_fixed_point(scratch, L, K, init_ids, true, filter_vec, true); auto best_L_nodes = scratch->best_l_nodes(); @@ -2197,14 +2219,14 @@ size_t Index::search_with_tags(const T *query, const uint64_t K if (!use_filters) { const std::vector unused_filter_label; - iterate_to_fixed_point(scratch, L, init_ids, false, unused_filter_label, true); + iterate_to_fixed_point(scratch, L, K, init_ids, false, unused_filter_label, true); } else { std::vector filter_vec; auto converted_label = this->get_converted_label(filter_label); filter_vec.push_back(converted_label); - iterate_to_fixed_point(scratch, L, init_ids, true, filter_vec, true); + iterate_to_fixed_point(scratch, L, K, init_ids, true, filter_vec, true); } NeighborPriorityQueue &best_L_nodes = scratch->best_l_nodes(); From f0632690920a7dea7f8a7fb9616e8c543300b513 Mon Sep 17 00:00:00 2001 From: ravishankar Date: Thu, 21 Nov 2024 02:20:33 -0800 Subject: [PATCH 3/9] add early stop results --- include/neighbor.h | 11 +++------- .../early_stop_r64_k10.txt | 21 +++++++++++++++++++ .../early_stop_r64_k100.txt | 21 +++++++++++++++++++ .../early_stop_r64_k30.txt | 21 +++++++++++++++++++ .../early_stop_r64_k50.txt | 21 +++++++++++++++++++ .../early_stop_r64_k10.txt | 21 +++++++++++++++++++ .../early_stop_r64_k100.txt | 21 +++++++++++++++++++ .../early_stop_r64_k30.txt | 21 +++++++++++++++++++ .../early_stop_r64_k50.txt | 21 +++++++++++++++++++ run-search.sh | 8 +++---- src/index.cpp | 7 ++++--- 11 files changed, 179 insertions(+), 15 deletions(-) create mode 100644 prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k10.txt create mode 100644 prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k100.txt create mode 100644 prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k30.txt create mode 100644 prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k50.txt create mode 100644 prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k10.txt create mode 100644 prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k100.txt create mode 100644 prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k30.txt create mode 100644 prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k50.txt diff --git a/include/neighbor.h b/include/neighbor.h index 2dc6145d4..4bf09bdbd 100644 --- a/include/neighbor.h +++ b/include/neighbor.h @@ -52,12 +52,11 @@ class NeighborPriorityQueue // set item or it has a greated distance than the final // item in the set. The set cursor that is used to pop() the // next item will be set to the lowest index of an uncheck item - int insert(const Neighbor &nbr, const size_t K) + void insert(const Neighbor &nbr) { - int return_val = 0; if (_size == _capacity && _data[_size - 1] < nbr) { - return 0; + return; } size_t lo = 0, hi = _size; @@ -71,7 +70,7 @@ class NeighborPriorityQueue } else if (_data[mid].id == nbr.id) { - return 0; + return; } else { @@ -84,9 +83,6 @@ class NeighborPriorityQueue std::memmove(&_data[lo + 1], &_data[lo], (_size - lo) * sizeof(Neighbor)); } _data[lo] = {nbr.id, nbr.distance}; - if(lo < K){ - return_val = 1; - } if (_size < _capacity) { _size++; @@ -95,7 +91,6 @@ class NeighborPriorityQueue { _cur = lo; } - return return_val; } int check_in_top_k(const Neighbor &nbr, size_t K) diff --git a/prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k10.txt b/prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k10.txt new file mode 100644 index 000000000..2e631b6e4 --- /dev/null +++ b/prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k10.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.34163s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@10 +=================================================================================================== + 300 297.52 4601.87 35.50 3361.06 18919.91 83.78 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. diff --git a/prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k100.txt b/prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k100.txt new file mode 100644 index 000000000..a8b414d72 --- /dev/null +++ b/prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k100.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.33751s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@100 +=================================================================================================== + 300 102.53 12864.34 101.10 9753.06 31099.98 83.13 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 100, size = 5306008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 100, size = 5306008B +Finished writing bin. diff --git a/prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k30.txt b/prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k30.txt new file mode 100644 index 000000000..ad8fbfaad --- /dev/null +++ b/prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k30.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.39128s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@30 +=================================================================================================== + 300 194.45 6906.99 53.39 5142.73 21151.91 83.44 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 30, size = 1591808B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 30, size = 1591808B +Finished writing bin. diff --git a/prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k50.txt b/prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k50.txt new file mode 100644 index 000000000..5b4b8ec16 --- /dev/null +++ b/prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k50.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.34222s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@50 +=================================================================================================== + 300 151.71 8831.58 68.59 6591.33 25331.64 83.30 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. diff --git a/prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k10.txt b/prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k10.txt new file mode 100644 index 000000000..ffc3ac47c --- /dev/null +++ b/prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k10.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.34911s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@10 +=================================================================================================== + 300 419.11 3264.07 25.29 2385.95 16366.58 75.74 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. diff --git a/prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k100.txt b/prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k100.txt new file mode 100644 index 000000000..4d7789c11 --- /dev/null +++ b/prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k100.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.34336s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@100 +=================================================================================================== + 300 154.61 8652.72 67.20 6468.04 23300.55 76.09 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 100, size = 5306008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 100, size = 5306008B +Finished writing bin. diff --git a/prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k30.txt b/prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k30.txt new file mode 100644 index 000000000..9e86cfc72 --- /dev/null +++ b/prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k30.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.34291s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@30 +=================================================================================================== + 300 281.03 4781.82 36.85 3558.22 19045.44 76.26 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 30, size = 1591808B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 30, size = 1591808B +Finished writing bin. diff --git a/prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k50.txt b/prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k50.txt new file mode 100644 index 000000000..ef52d025f --- /dev/null +++ b/prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k50.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.35146s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@50 +=================================================================================================== + 300 220.81 5992.72 46.23 4528.76 20761.37 76.03 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. diff --git a/run-search.sh b/run-search.sh index 52cb8e4d3..d67889045 100644 --- a/run-search.sh +++ b/run-search.sh @@ -1,5 +1,5 @@ cd build -./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 10 -L 10 20 30 40 50 60 70 80 90 100 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early_stop_1pc_r64_k10.txt -./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 25 -L 30 40 50 60 70 80 90 100 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early_stop_1pc_r64_k25.txt -./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 50 -L 50 60 70 80 90 100 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early_stop_1pc_r64_k50.txt -./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 100 -L 100 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early_stop_1pc_r64_k100.txt \ No newline at end of file +./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 10 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/insert-based-stop-x-10-y-0/early_stop_r64_k10.txt +./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 30 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/insert-based-stop-x-10-y-0/early_stop_r64_k30.txt +./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 50 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/insert-based-stop-x-10-y-0/early_stop_r64_k50.txt +./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 100 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/insert-based-stop-x-10-y-0/early_stop_r64_k100.txt \ No newline at end of file diff --git a/src/index.cpp b/src/index.cpp index 3fec494c3..a5b92a312 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -882,7 +882,7 @@ std::pair Index::iterate_to_fixed_point( uint32_t cmps = 0; std::queue last_K_insertions; - int x = 5; + int x = 10; int y = 0; float prev_distance_to_query = 0.0; @@ -913,7 +913,7 @@ std::pair Index::iterate_to_fixed_point( // break; // } // prev_distance_to_query = dist_scratch_temp[0]; - diskann::cout<<"Iteration/Hop: #"< Index::iterate_to_fixed_point( int insertions_this_iter = 0; for (size_t m = 0; m < id_scratch.size(); ++m) { - insertions_this_iter += best_L_nodes.insert(Neighbor(id_scratch[m], dist_scratch[m])); + insertions_this_iter += best_L_nodes.check_in_top_k(Neighbor(id_scratch[m], dist_scratch[m]), K); + best_L_nodes.insert(Neighbor(id_scratch[m], dist_scratch[m])); } last_K_insertions.push(insertions_this_iter); if (last_K_insertions.size() > x) { From 08aa75d65c43f281bf5d0687724353eb104b4bf1 Mon Sep 17 00:00:00 2001 From: ravishankar Date: Sun, 24 Nov 2024 19:59:41 -0800 Subject: [PATCH 4/9] add early stop results --- include/neighbor.h | 8 +++---- .../early_stop_r150_k10.txt | 21 +++++++++++++++++++ .../early_stop_r150_k100.txt | 21 +++++++++++++++++++ .../early_stop_r150_k30.txt | 21 +++++++++++++++++++ .../early_stop_r150_k50.txt | 21 +++++++++++++++++++ .../reduce_prune_r150_l300.txt | 9 ++++++++ .../early_stop_r150_k10.txt | 21 +++++++++++++++++++ .../early_stop_r150_k100.txt | 21 +++++++++++++++++++ .../early_stop_r150_k30.txt | 21 +++++++++++++++++++ .../early_stop_r150_k50.txt | 21 +++++++++++++++++++ ...op_r64_k10.txt => early_stop_r150_k10.txt} | 0 ..._r64_k100.txt => early_stop_r150_k100.txt} | 0 ...op_r64_k30.txt => early_stop_r150_k30.txt} | 0 ...op_r64_k50.txt => early_stop_r150_k50.txt} | 0 ...op_r64_k10.txt => early_stop_r150_k10.txt} | 0 ..._r64_k100.txt => early_stop_r150_k100.txt} | 0 ...op_r64_k30.txt => early_stop_r150_k30.txt} | 0 ...op_r64_k50.txt => early_stop_r150_k50.txt} | 0 run-build.sh | 2 ++ run-search.sh | 8 +++---- src/index.cpp | 2 +- 21 files changed, 188 insertions(+), 9 deletions(-) create mode 100644 prec40M/early-stop-build-x-10-y-0/early_stop_r150_k10.txt create mode 100644 prec40M/early-stop-build-x-10-y-0/early_stop_r150_k100.txt create mode 100644 prec40M/early-stop-build-x-10-y-0/early_stop_r150_k30.txt create mode 100644 prec40M/early-stop-build-x-10-y-0/early_stop_r150_k50.txt create mode 100644 prec40M/early-stop-build-x-10-y-0/reduce_prune_r150_l300.txt create mode 100644 prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k10.txt create mode 100644 prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k100.txt create mode 100644 prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k30.txt create mode 100644 prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k50.txt rename prec40M/k-insert-stop-x-10-y-0/{early_stop_r64_k10.txt => early_stop_r150_k10.txt} (100%) rename prec40M/k-insert-stop-x-10-y-0/{early_stop_r64_k100.txt => early_stop_r150_k100.txt} (100%) rename prec40M/k-insert-stop-x-10-y-0/{early_stop_r64_k30.txt => early_stop_r150_k30.txt} (100%) rename prec40M/k-insert-stop-x-10-y-0/{early_stop_r64_k50.txt => early_stop_r150_k50.txt} (100%) rename prec40M/k-insert-stop-x-5-y-0/{early_stop_r64_k10.txt => early_stop_r150_k10.txt} (100%) rename prec40M/k-insert-stop-x-5-y-0/{early_stop_r64_k100.txt => early_stop_r150_k100.txt} (100%) rename prec40M/k-insert-stop-x-5-y-0/{early_stop_r64_k30.txt => early_stop_r150_k30.txt} (100%) rename prec40M/k-insert-stop-x-5-y-0/{early_stop_r64_k50.txt => early_stop_r150_k50.txt} (100%) create mode 100644 run-build.sh diff --git a/include/neighbor.h b/include/neighbor.h index 4bf09bdbd..d1b972c11 100644 --- a/include/neighbor.h +++ b/include/neighbor.h @@ -117,10 +117,10 @@ class NeighborPriorityQueue lo = mid + 1; } } - if(lo < K){ - return 1; - } - return 0; + // if(lo < K){ + // return 1; + // } + return 1; } Neighbor closest_unexpanded() diff --git a/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k10.txt b/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k10.txt new file mode 100644 index 000000000..5fda0e33d --- /dev/null +++ b/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k10.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.32297s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@10 +=================================================================================================== + 300 42.83 25015.15 202.91 23346.59 68870.16 97.93 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. diff --git a/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k100.txt b/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k100.txt new file mode 100644 index 000000000..b5d2f41a8 --- /dev/null +++ b/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k100.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.30586s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@100 +=================================================================================================== + 300 53.70 25015.15 202.91 18620.22 41585.87 91.35 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 100, size = 5306008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 100, size = 5306008B +Finished writing bin. diff --git a/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k30.txt b/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k30.txt new file mode 100644 index 000000000..9a11979c7 --- /dev/null +++ b/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k30.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.3682s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@30 +=================================================================================================== + 300 44.48 25015.15 202.91 22483.01 83358.17 96.07 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 30, size = 1591808B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 30, size = 1591808B +Finished writing bin. diff --git a/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k50.txt b/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k50.txt new file mode 100644 index 000000000..63072e06b --- /dev/null +++ b/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k50.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.3699s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@50 +=================================================================================================== + 300 53.67 25015.15 202.91 18630.79 42221.48 94.55 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. diff --git a/prec40M/early-stop-build-x-10-y-0/reduce_prune_r150_l300.txt b/prec40M/early-stop-build-x-10-y-0/reduce_prune_r150_l300.txt new file mode 100644 index 000000000..d8ba62d04 --- /dev/null +++ b/prec40M/early-stop-build-x-10-y-0/reduce_prune_r150_l300.txt @@ -0,0 +1,9 @@ +Starting index build with R: 150 Lbuild: 300 alpha: 1.2 #threads: 48 +Using AVX2 distance computation DistanceL2Int8. +Using only first 40469609 from file.. +Starting index build with 40469609 points... + 0% of index build completed. 0.247099% of index build completed. 0.494198% of index build completed. 0.741297% of index build completed. 0.988396% of index build completed. 1.2355% of index build completed. 1.48259% of index build completed. 1.72969% of index build completed. 1.97679% of index build completed. 2.22389% of index build completed. 2.47099% of index build completed. 2.71809% of index build completed. 2.96519% of index build completed. 3.21229% of index build completed. 3.45939% of index build completed. 3.70649% of index build completed. 3.95358% of index build completed. 4.20068% of index build completed. 4.44778% of index build completed. 4.69488% of index build completed. 4.94198% of index build completed. 5.18908% of index build completed. 5.43618% of index build completed. 5.68328% of index build completed. 5.93038% of index build completed. 6.17748% of index build completed. 6.42457% of index build completed. 6.67167% of index build completed. 6.91877% of index build completed. 7.16587% of index build completed. 7.41297% of index build completed. 7.66007% of index build completed. 7.90717% of index build completed. 8.15427% of index build completed. 8.40137% of index build completed. 8.64847% of index build completed. 8.89556% of index build completed. 9.14266% of index build completed. 9.38976% of index build completed. 9.63686% of index build completed. 9.88396% of index build completed. 10.1311% of index build completed. 10.3782% of index build completed. 10.6253% of index build completed. 10.8724% of index build completed. 11.1195% of index build completed. 11.3666% of index build completed. 11.6137% of index build completed. 11.8608% of index build completed. 12.1079% of index build completed. 12.355% of index build completed. 12.602% of index build completed. 12.8491% of index build completed. 13.0962% of index build completed. 13.3433% of index build completed. 13.5904% of index build completed. 13.8375% of index build completed. 14.0846% of index build completed. 14.3317% of index build completed. 14.5788% of index build completed. 14.8259% of index build completed. 15.073% of index build completed. 15.3201% of index build completed. 15.5672% of index build completed. 15.8143% of index build completed. 16.0614% of index build completed. 16.3085% of index build completed. 16.5556% of index build completed. 16.8027% of index build completed. 17.0498% of index build completed. 17.2969% of index build completed. 17.544% of index build completed. 17.7911% of index build completed. 18.0382% of index build completed. 18.2853% of index build completed. 18.5324% of index build completed. 18.7795% of index build completed. 19.0266% of index build completed. 19.2737% of index build completed. 19.5208% of index build completed. 19.7679% of index build completed. 20.015% of index build completed. 20.2621% of index build completed. 20.5092% of index build completed. 20.7563% of index build completed. 21.0034% of index build completed. 21.2505% of index build completed. 21.4976% of index build completed. 21.7447% of index build completed. 21.9918% of index build completed. 22.2389% of index build completed. 22.486% of index build completed. 22.7331% of index build completed. 22.9802% of index build completed. 23.2273% of index build completed. 23.4744% of index build completed. 23.7215% of index build completed. 23.9686% of index build completed. 24.2157% of index build completed. 24.4628% of index build completed. 24.7099% of index build completed. 24.957% of index build completed. 25.2041% of index build completed. 25.4512% of index build completed. 25.6983% of index build completed. 25.9454% of index build completed. 26.1925% of index build completed. 26.4396% of index build completed. 26.6867% of index build completed. 26.9338% of index build completed. 27.1809% of index build completed. 27.428% of index build completed. 27.6751% of index build completed. 27.9222% of index build completed. 28.1693% of index build completed. 28.4164% of index build completed. 28.6635% of index build completed. 28.9106% of index build completed. 29.1577% of index build completed. 29.4048% of index build completed. 29.6519% of index build completed. 29.899% of index build completed. 30.1461% of index build completed. 30.3932% of index build completed. 30.6403% of index build completed. 30.8874% of index build completed. 31.1345% of index build completed. 31.3816% of index build completed. 31.6287% of index build completed. 31.8758% of index build completed. 32.1229% of index build completed. 32.37% of index build completed. 32.6171% of index build completed. 32.8642% of index build completed. 33.1113% of index build completed. 33.3584% of index build completed. 33.6055% of index build completed. 33.8526% of index build completed. 34.0997% of index build completed. 34.3468% of index build completed. 34.5939% of index build completed. 34.841% of index build completed. 35.0881% of index build completed. 35.3352% of index build completed. 35.5823% of index build completed. 35.8294% of index build completed. 36.0765% of index build completed. 36.3236% of index build completed. 36.5707% of index build completed. 36.8178% of index build completed. 37.0649% of index build completed. 37.3119% of index build completed. 37.559% of index build completed. 37.8061% of index build completed. 38.0532% of index build completed. 38.3003% of index build completed. 38.5474% of index build completed. 38.7945% of index build completed. 39.0416% of index build completed. 39.2887% of index build completed. 39.5358% of index build completed. 39.7829% of index build completed. 40.03% of index build completed. 40.2771% of index build completed. 40.5242% of index build completed. 40.7713% of index build completed. 41.0184% of index build completed. 41.2655% of index build completed. 41.5126% of index build completed. 41.7597% of index build completed. 42.0068% of index build completed. 42.2539% of index build completed. 42.501% of index build completed. 42.7481% of index build completed. 42.9952% of index build completed. 43.2423% of index build completed. 43.4894% of index build completed. 43.7365% of index build completed. 43.9836% of index build completed. 44.2307% of index build completed. 44.4778% of index build completed. 44.7249% of index build completed. 44.972% of index build completed. 45.2191% of index build completed. 45.4662% of index build completed. 45.7133% of index build completed. 45.9604% of index build completed. 46.2075% of index build completed. 46.4546% of index build completed. 46.7017% of index build completed. 46.9488% of index build completed. 47.1959% of index build completed. 47.443% of index build completed. 47.6901% of index build completed. 47.9372% of index build completed. 48.1843% of index build completed. 48.4314% of index build completed. 48.6785% of index build completed. 48.9256% of index build completed. 49.1727% of index build completed. 49.4198% of index build completed. 49.6669% of index build completed. 49.914% of index build completed. 50.1611% of index build completed. 50.4082% of index build completed. 50.6553% of index build completed. 50.9024% of index build completed. 51.1495% of index build completed. 51.3966% of index build completed. 51.6437% of index build completed. 51.8908% of index build completed. 52.1379% of index build completed. 52.385% of index build completed. 52.6321% of index build completed. 52.8792% of index build completed. 53.1263% of index build completed. 53.3734% of index build completed. 53.6205% of index build completed. 53.8676% of index build completed. 54.1147% of index build completed. 54.3618% of index build completed. 54.6089% of index build completed. 54.856% of index build completed. 55.1031% of index build completed. 55.3502% of index build completed. 55.5973% of index build completed. 55.8444% of index build completed. 56.0915% of index build completed. 56.3386% of index build completed. 56.5857% of index build completed. 56.8328% of index build completed. 57.0799% of index build completed. 57.327% of index build completed. 57.5741% of index build completed. 57.8212% of index build completed. 58.0683% of index build completed. 58.3154% of index build completed. 58.5625% of index build completed. 58.8096% of index build completed. 59.0567% of index build completed. 59.3038% of index build completed. 59.5509% of index build completed. 59.798% of index build completed. 60.0451% of index build completed. 60.2922% of index build completed. 60.5393% of index build completed. 60.7864% of index build completed. 61.0335% of index build completed. 61.2806% of index build completed. 61.5277% of index build completed. 61.7748% of index build completed. 62.0218% of index build completed. 62.2689% of index build completed. 62.516% of index build completed. 62.7631% of index build completed. 63.0102% of index build completed. 63.2573% of index build completed. 63.5044% of index build completed. 63.7515% of index build completed. 63.9986% of index build completed. 64.2457% of index build completed. 64.4928% of index build completed. 64.7399% of index build completed. 64.987% of index build completed. 65.2341% of index build completed. 65.4812% of index build completed. 65.7283% of index build completed. 65.9754% of index build completed. 66.2225% of index build completed. 66.4696% of index build completed. 66.7167% of index build completed. 66.9638% of index build completed. 67.2109% of index build completed. 67.458% of index build completed. 67.7051% of index build completed. 67.9522% of index build completed. 68.1993% of index build completed. 68.4464% of index build completed. 68.6935% of index build completed. 68.9406% of index build completed. 69.1877% of index build completed. 69.4348% of index build completed. 69.6819% of index build completed. 69.929% of index build completed. 70.1761% of index build completed. 70.4232% of index build completed. 70.6703% of index build completed. 70.9174% of index build completed. 71.1645% of index build completed. 71.4116% of index build completed. 71.6587% of index build completed. 71.9058% of index build completed. 72.1529% of index build completed. 72.4% of index build completed. 72.6471% of index build completed. 72.8942% of index build completed. 73.1413% of index build completed. 73.3884% of index build completed. 73.6355% of index build completed. 73.8826% of index build completed. 74.1297% of index build completed. 74.3768% of index build completed. 74.6239% of index build completed. 74.871% of index build completed. 75.1181% of index build completed. 75.3652% of index build completed. 75.6123% of index build completed. 75.8594% of index build completed. 76.1065% of index build completed. 76.3536% of index build completed. 76.6007% of index build completed. 76.8478% of index build completed. 77.0949% of index build completed. 77.342% of index build completed. 77.5891% of index build completed. 77.8362% of index build completed. 78.0833% of index build completed. 78.3304% of index build completed. 78.5775% of index build completed. 78.8246% of index build completed. 79.0717% of index build completed. 79.3188% of index build completed. 79.5659% of index build completed. 79.813% of index build completed. 80.0601% of index build completed. 80.3072% of index build completed. 80.5543% of index build completed. 80.8014% of index build completed. 81.0485% of index build completed. 81.2956% of index build completed. 81.5427% of index build completed. 81.7898% of index build completed. 82.0369% of index build completed. 82.284% of index build completed. 82.5311% of index build completed. 82.7782% of index build completed. 83.0253% of index build completed. 83.2724% of index build completed. 83.5195% of index build completed. 83.7666% of index build completed. 84.0137% of index build completed. 84.2608% of index build completed. 84.5079% of index build completed. 84.755% of index build completed. 85.0021% of index build completed. 85.2492% of index build completed. 85.4963% of index build completed. 85.7434% of index build completed. 85.9905% of index build completed. 86.2376% of index build completed. 86.4847% of index build completed. 86.7317% of index build completed. 86.9788% of index build completed. 87.2259% of index build completed. 87.473% of index build completed. 87.7201% of index build completed. 87.9672% of index build completed. 88.2143% of index build completed. 88.4614% of index build completed. 88.7085% of index build completed. 88.9556% of index build completed. 89.2027% of index build completed. 89.4498% of index build completed. 89.6969% of index build completed. 89.944% of index build completed. 90.1911% of index build completed. 90.4382% of index build completed. 90.6853% of index build completed. 90.9324% of index build completed. 91.1795% of index build completed. 91.4266% of index build completed. 91.6737% of index build completed. 91.9208% of index build completed. 92.1679% of index build completed. 92.415% of index build completed. 92.6621% of index build completed. 92.9092% of index build completed. 93.1563% of index build completed. 93.4034% of index build completed. 93.6505% of index build completed. 93.8976% of index build completed. 94.1447% of index build completed. 94.3918% of index build completed. 94.6389% of index build completed. 94.886% of index build completed. 95.1331% of index build completed. 95.3802% of index build completed. 95.6273% of index build completed. 95.8744% of index build completed. 96.1215% of index build completed. 96.3686% of index build completed. 96.6157% of index build completed. 96.8628% of index build completed. 97.1099% of index build completed. 97.357% of index build completed. 97.6041% of index build completed. 97.8512% of index build completed. 98.0983% of index build completed. 98.3454% of index build completed. 98.5925% of index build completed. 98.8396% of index build completed. 99.0867% of index build completed. 99.3338% of index build completed. 99.5809% of index build completed. 99.828% of index build completed.Starting final cleanup..done. Link time: 14655.5s +Index built with degree: max:150 avg:105.554 min:1 count(deg<2):574117 +Indexing time: 14674.7 +Not saving tags as they are not enabled. +Time taken for save: 38.3406s. diff --git a/prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k10.txt b/prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k10.txt new file mode 100644 index 000000000..ebae58ffa --- /dev/null +++ b/prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k10.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.34877s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@10 +=================================================================================================== + 300 53.56 25015.15 202.91 18671.99 43509.42 97.93 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 10, size = 530608B +Finished writing bin. diff --git a/prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k100.txt b/prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k100.txt new file mode 100644 index 000000000..0c32db705 --- /dev/null +++ b/prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k100.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.34179s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@100 +=================================================================================================== + 300 53.51 25015.15 202.91 18689.31 44566.99 91.35 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 100, size = 5306008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 100, size = 5306008B +Finished writing bin. diff --git a/prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k30.txt b/prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k30.txt new file mode 100644 index 000000000..0862aa842 --- /dev/null +++ b/prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k30.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.32514s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@30 +=================================================================================================== + 300 53.30 25015.15 202.91 18761.52 43157.76 96.07 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 30, size = 1591808B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 30, size = 1591808B +Finished writing bin. diff --git a/prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k50.txt b/prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k50.txt new file mode 100644 index 000000000..173a381cb --- /dev/null +++ b/prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k50.txt @@ -0,0 +1,21 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.31941s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@50 +=================================================================================================== + 300 53.39 25015.15 202.91 18730.34 43019.43 94.55 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. diff --git a/prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k10.txt b/prec40M/k-insert-stop-x-10-y-0/early_stop_r150_k10.txt similarity index 100% rename from prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k10.txt rename to prec40M/k-insert-stop-x-10-y-0/early_stop_r150_k10.txt diff --git a/prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k100.txt b/prec40M/k-insert-stop-x-10-y-0/early_stop_r150_k100.txt similarity index 100% rename from prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k100.txt rename to prec40M/k-insert-stop-x-10-y-0/early_stop_r150_k100.txt diff --git a/prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k30.txt b/prec40M/k-insert-stop-x-10-y-0/early_stop_r150_k30.txt similarity index 100% rename from prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k30.txt rename to prec40M/k-insert-stop-x-10-y-0/early_stop_r150_k30.txt diff --git a/prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k50.txt b/prec40M/k-insert-stop-x-10-y-0/early_stop_r150_k50.txt similarity index 100% rename from prec40M/k-insert-stop-x-10-y-0/early_stop_r64_k50.txt rename to prec40M/k-insert-stop-x-10-y-0/early_stop_r150_k50.txt diff --git a/prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k10.txt b/prec40M/k-insert-stop-x-5-y-0/early_stop_r150_k10.txt similarity index 100% rename from prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k10.txt rename to prec40M/k-insert-stop-x-5-y-0/early_stop_r150_k10.txt diff --git a/prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k100.txt b/prec40M/k-insert-stop-x-5-y-0/early_stop_r150_k100.txt similarity index 100% rename from prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k100.txt rename to prec40M/k-insert-stop-x-5-y-0/early_stop_r150_k100.txt diff --git a/prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k30.txt b/prec40M/k-insert-stop-x-5-y-0/early_stop_r150_k30.txt similarity index 100% rename from prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k30.txt rename to prec40M/k-insert-stop-x-5-y-0/early_stop_r150_k30.txt diff --git a/prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k50.txt b/prec40M/k-insert-stop-x-5-y-0/early_stop_r150_k50.txt similarity index 100% rename from prec40M/k-insert-stop-x-5-y-0/early_stop_r64_k50.txt rename to prec40M/k-insert-stop-x-5-y-0/early_stop_r150_k50.txt diff --git a/run-build.sh b/run-build.sh new file mode 100644 index 000000000..eb5f7a1ee --- /dev/null +++ b/run-build.sh @@ -0,0 +1,2 @@ +cd build +./apps/build_memory_index --data_path /nvmessd1/fbv4/prec40M.bin --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_earlystop_memory_index_r150_l300 -R 150 -L 300 -T 48 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/reduce_prune_r150_l300.txt \ No newline at end of file diff --git a/run-search.sh b/run-search.sh index d67889045..bc2d44af9 100644 --- a/run-search.sh +++ b/run-search.sh @@ -1,5 +1,5 @@ cd build -./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 10 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/insert-based-stop-x-10-y-0/early_stop_r64_k10.txt -./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 30 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/insert-based-stop-x-10-y-0/early_stop_r64_k30.txt -./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 50 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/insert-based-stop-x-10-y-0/early_stop_r64_k50.txt -./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 100 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/insert-based-stop-x-10-y-0/early_stop_r64_k100.txt \ No newline at end of file +./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 10 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k10.txt +./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 30 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k30.txt +./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 50 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k50.txt +./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 100 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k100.txt \ No newline at end of file diff --git a/src/index.cpp b/src/index.cpp index a5b92a312..3498cd024 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -890,7 +890,7 @@ std::pair Index::iterate_to_fixed_point( { hops++; - // Check if the sum of elements of the deque is less than y, if yes then exit the loop + // Check if the sum of elements of the queue is less than y, if yes then exit the loop int sum_last_K_insertions = 0; std::queue temp_queue = last_K_insertions; while (!temp_queue.empty()) { From 1f66698341a1cf9ebc70f9dacf6354a5a51cd7b5 Mon Sep 17 00:00:00 2001 From: ravishankar Date: Mon, 2 Dec 2024 22:46:54 -0800 Subject: [PATCH 5/9] add some results --- ...r64_k50.txt => baseline_r150_l300_k50.txt} | 38 ++++----- prec40M/baseline_r64_k10.txt | 84 ------------------- prec40M/baseline_r64_k100.txt | 21 ----- prec40M/baseline_r64_k25.txt | 70 ---------------- ..._build_&_search_r150_l300_k50_x10_y0_L.txt | 84 +++++++++++++++++++ .../early_stop_build_r150_l300_x10_y0_L.txt} | 8 +- .../early_stop_r150_k10.txt | 21 ----- .../early_stop_r150_k100.txt | 21 ----- .../early_stop_r150_k30.txt | 21 ----- .../early_stop_r150_k50.txt | 21 ----- ...rly_stop_search_r150_l300_k50_x10_y0_K.txt | 84 +++++++++++++++++++ ...rly_stop_search_r150_l300_k50_x10_y0_L.txt | 84 +++++++++++++++++++ ...arly_stop_search_r150_l300_k50_x5_y0_K.txt | 84 +++++++++++++++++++ ...arly_stop_search_r150_l300_k50_x5_y0_L.txt | 84 +++++++++++++++++++ .../early_stop_r150_k10.txt | 0 .../early_stop_r150_k100.txt | 0 .../early_stop_r150_k30.txt | 0 .../early_stop_r150_k50.txt | 0 .../early_stop_r150_k10.txt | 0 .../early_stop_r150_k100.txt | 0 .../early_stop_r150_k30.txt | 0 .../early_stop_r150_k50.txt | 0 .../early_stop_r150_k10.txt | 0 .../early_stop_r150_k100.txt | 0 .../early_stop_r150_k30.txt | 0 .../early_stop_r150_k50.txt | 0 run-build.sh | 2 +- run-search.sh | 9 +- src/index.cpp | 18 ++-- 29 files changed, 458 insertions(+), 296 deletions(-) rename prec40M/{baseline_r64_k50.txt => baseline_r150_l300_k50.txt} (59%) delete mode 100644 prec40M/baseline_r64_k10.txt delete mode 100644 prec40M/baseline_r64_k100.txt delete mode 100644 prec40M/baseline_r64_k25.txt create mode 100644 prec40M/build_&_search/early_stop_build_&_search_r150_l300_k50_x10_y0_L.txt rename prec40M/{early-stop-build-x-10-y-0/reduce_prune_r150_l300.txt => build_&_search/early_stop_build_r150_l300_x10_y0_L.txt} (98%) delete mode 100644 prec40M/early-stop-build-x-10-y-0/early_stop_r150_k10.txt delete mode 100644 prec40M/early-stop-build-x-10-y-0/early_stop_r150_k100.txt delete mode 100644 prec40M/early-stop-build-x-10-y-0/early_stop_r150_k30.txt delete mode 100644 prec40M/early-stop-build-x-10-y-0/early_stop_r150_k50.txt create mode 100644 prec40M/search_only/early_stop_search_r150_l300_k50_x10_y0_K.txt create mode 100644 prec40M/search_only/early_stop_search_r150_l300_k50_x10_y0_L.txt create mode 100644 prec40M/search_only/early_stop_search_r150_l300_k50_x5_y0_K.txt create mode 100644 prec40M/search_only/early_stop_search_r150_l300_k50_x5_y0_L.txt rename prec40M/{k-insert-stop-x-10-y-0 => search_only/early_stop_x10_y0_K}/early_stop_r150_k10.txt (100%) rename prec40M/{k-insert-stop-x-10-y-0 => search_only/early_stop_x10_y0_K}/early_stop_r150_k100.txt (100%) rename prec40M/{k-insert-stop-x-10-y-0 => search_only/early_stop_x10_y0_K}/early_stop_r150_k30.txt (100%) rename prec40M/{k-insert-stop-x-10-y-0 => search_only/early_stop_x10_y0_K}/early_stop_r150_k50.txt (100%) rename prec40M/{insert-based-stop-x-10-y-0 => search_only/early_stop_x10_y0_L}/early_stop_r150_k10.txt (100%) rename prec40M/{insert-based-stop-x-10-y-0 => search_only/early_stop_x10_y0_L}/early_stop_r150_k100.txt (100%) rename prec40M/{insert-based-stop-x-10-y-0 => search_only/early_stop_x10_y0_L}/early_stop_r150_k30.txt (100%) rename prec40M/{insert-based-stop-x-10-y-0 => search_only/early_stop_x10_y0_L}/early_stop_r150_k50.txt (100%) rename prec40M/{k-insert-stop-x-5-y-0 => search_only/early_stop_x5_y0_K}/early_stop_r150_k10.txt (100%) rename prec40M/{k-insert-stop-x-5-y-0 => search_only/early_stop_x5_y0_K}/early_stop_r150_k100.txt (100%) rename prec40M/{k-insert-stop-x-5-y-0 => search_only/early_stop_x5_y0_K}/early_stop_r150_k30.txt (100%) rename prec40M/{k-insert-stop-x-5-y-0 => search_only/early_stop_x5_y0_K}/early_stop_r150_k50.txt (100%) diff --git a/prec40M/baseline_r64_k50.txt b/prec40M/baseline_r150_l300_k50.txt similarity index 59% rename from prec40M/baseline_r64_k50.txt rename to prec40M/baseline_r150_l300_k50.txt index 9f4a83f1b..70e809979 100644 --- a/prec40M/baseline_r64_k50.txt +++ b/prec40M/baseline_r150_l300_k50.txt @@ -3,20 +3,20 @@ Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... Metadata: #pts = 13265, #dims = 100... Using AVX2 distance computation DistanceL2Int8. -Resizing took: 1.3678s -From graph header, expected_file_size: 7438757948, _max_observed_degree: 64, _start: 11890341, file_frozen_pts: 0 -Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100.......done. Index has 40469609 nodes and 1819219872 out-edges, _start is set to 11890341 +Resizing took: 1.35062s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 Index loaded Using 1 threads to search Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@50 =================================================================================================== - 50 363.96 3687.22 70.97 2747.47 8534.45 62.96 - 60 344.07 4195.96 81.27 2906.31 10733.88 65.92 - 70 305.54 4685.40 91.30 3272.87 10640.61 68.19 - 80 274.47 5171.15 101.32 3643.38 13795.25 70.07 - 90 249.35 5654.48 111.37 4010.40 14678.43 71.76 - 100 228.82 6129.37 121.32 4370.23 17002.81 73.17 + 50 204.00 7149.92 55.00 4901.96 15809.95 79.69 + 100 122.17 11640.27 91.23 8185.00 21637.09 87.33 + 150 90.58 15499.88 122.88 11039.73 25685.82 90.61 + 200 73.30 18942.36 151.51 13642.69 30741.64 92.49 + 250 62.50 22119.38 178.28 15998.88 33482.66 93.71 + 300 55.09 25015.15 202.91 18151.68 37464.98 94.55 Done searching. Now saving results Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin bin: #pts = 13265, #dims = 50, size = 2653008B @@ -24,33 +24,33 @@ Finished writing bin. Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin bin: #pts = 13265, #dims = 50, size = 2653008B Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_60_idx_uint32.bin +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin bin: #pts = 13265, #dims = 50, size = 2653008B Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_60_dists_float.bin +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin bin: #pts = 13265, #dims = 50, size = 2653008B Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_70_idx_uint32.bin +Writing bin: /home/rakri/avarhade/Dump/tmp_150_idx_uint32.bin bin: #pts = 13265, #dims = 50, size = 2653008B Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_70_dists_float.bin +Writing bin: /home/rakri/avarhade/Dump/tmp_150_dists_float.bin bin: #pts = 13265, #dims = 50, size = 2653008B Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_80_idx_uint32.bin +Writing bin: /home/rakri/avarhade/Dump/tmp_200_idx_uint32.bin bin: #pts = 13265, #dims = 50, size = 2653008B Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_80_dists_float.bin +Writing bin: /home/rakri/avarhade/Dump/tmp_200_dists_float.bin bin: #pts = 13265, #dims = 50, size = 2653008B Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_90_idx_uint32.bin +Writing bin: /home/rakri/avarhade/Dump/tmp_250_idx_uint32.bin bin: #pts = 13265, #dims = 50, size = 2653008B Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_90_dists_float.bin +Writing bin: /home/rakri/avarhade/Dump/tmp_250_dists_float.bin bin: #pts = 13265, #dims = 50, size = 2653008B Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin bin: #pts = 13265, #dims = 50, size = 2653008B Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin bin: #pts = 13265, #dims = 50, size = 2653008B Finished writing bin. diff --git a/prec40M/baseline_r64_k10.txt b/prec40M/baseline_r64_k10.txt deleted file mode 100644 index b24e59680..000000000 --- a/prec40M/baseline_r64_k10.txt +++ /dev/null @@ -1,84 +0,0 @@ -Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. -Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 -Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... -Metadata: #pts = 13265, #dims = 100... -Using AVX2 distance computation DistanceL2Int8. -Resizing took: 1.33364s -From graph header, expected_file_size: 7438757948, _max_observed_degree: 64, _start: 11890341, file_frozen_pts: 0 -Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100.......done. Index has 40469609 nodes and 1819219872 out-edges, _start is set to 11890341 -Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 -Index loaded -Using 1 threads to search - Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@10 -=================================================================================================== - 10 1176.02 1324.67 25.15 850.27 3232.74 43.13 - 20 819.47 2021.14 38.20 1220.24 4711.67 58.38 - 30 602.84 2617.97 49.73 1658.77 6214.68 66.24 - 40 470.64 3168.06 60.58 2124.69 6657.69 71.25 - 50 396.33 3687.22 70.97 2523.10 9243.96 74.44 - 60 344.13 4195.96 81.27 2905.83 9802.10 76.98 - 70 305.17 4685.40 91.30 3276.85 12570.57 78.78 - 80 274.43 5171.15 101.32 3643.83 12268.22 80.21 - 90 249.33 5654.48 111.37 4010.62 14590.95 81.53 - 100 229.07 6129.37 121.32 4365.34 14753.94 82.58 -Done searching. Now saving results -Writing bin: /home/rakri/avarhade/Dump/tmp_10_idx_uint32.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_10_dists_float.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_20_idx_uint32.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_20_dists_float.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_30_idx_uint32.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_30_dists_float.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_40_idx_uint32.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_40_dists_float.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_60_idx_uint32.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_60_dists_float.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_70_idx_uint32.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_70_dists_float.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_80_idx_uint32.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_80_dists_float.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_90_idx_uint32.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_90_dists_float.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. diff --git a/prec40M/baseline_r64_k100.txt b/prec40M/baseline_r64_k100.txt deleted file mode 100644 index 93b86df0d..000000000 --- a/prec40M/baseline_r64_k100.txt +++ /dev/null @@ -1,21 +0,0 @@ -Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. -Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 -Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... -Metadata: #pts = 13265, #dims = 100... -Using AVX2 distance computation DistanceL2Int8. -Resizing took: 1.37236s -From graph header, expected_file_size: 7438757948, _max_observed_degree: 64, _start: 11890341, file_frozen_pts: 0 -Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100.......done. Index has 40469609 nodes and 1819219872 out-edges, _start is set to 11890341 -Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 -Index loaded -Using 1 threads to search - Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@100 -=================================================================================================== - 100 217.00 6129.37 121.32 4608.19 13353.83 66.81 -Done searching. Now saving results -Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin -bin: #pts = 13265, #dims = 100, size = 5306008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin -bin: #pts = 13265, #dims = 100, size = 5306008B -Finished writing bin. diff --git a/prec40M/baseline_r64_k25.txt b/prec40M/baseline_r64_k25.txt deleted file mode 100644 index c52c4d3fa..000000000 --- a/prec40M/baseline_r64_k25.txt +++ /dev/null @@ -1,70 +0,0 @@ -Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. -Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 -Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... -Metadata: #pts = 13265, #dims = 100... -Using AVX2 distance computation DistanceL2Int8. -Resizing took: 1.36738s -From graph header, expected_file_size: 7438757948, _max_observed_degree: 64, _start: 11890341, file_frozen_pts: 0 -Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r64_l100.......done. Index has 40469609 nodes and 1819219872 out-edges, _start is set to 11890341 -Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 -Index loaded -Using 1 threads to search - Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@25 -=================================================================================================== - 30 535.01 2617.97 49.73 1869.07 6384.29 60.18 - 40 471.19 3168.06 60.58 2122.23 7482.87 65.38 - 50 400.24 3687.22 70.97 2498.41 7306.91 68.82 - 60 344.31 4195.96 81.27 2904.30 10851.25 71.60 - 70 305.49 4685.40 91.30 3273.41 11079.77 73.66 - 80 274.40 5171.15 101.32 3644.27 13173.09 75.35 - 90 249.78 5654.48 111.37 4003.45 14204.55 76.87 - 100 228.86 6129.37 121.32 4369.40 14582.85 78.14 -Done searching. Now saving results -Writing bin: /home/rakri/avarhade/Dump/tmp_30_idx_uint32.bin -bin: #pts = 13265, #dims = 25, size = 1326508B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_30_dists_float.bin -bin: #pts = 13265, #dims = 25, size = 1326508B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_40_idx_uint32.bin -bin: #pts = 13265, #dims = 25, size = 1326508B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_40_dists_float.bin -bin: #pts = 13265, #dims = 25, size = 1326508B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin -bin: #pts = 13265, #dims = 25, size = 1326508B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin -bin: #pts = 13265, #dims = 25, size = 1326508B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_60_idx_uint32.bin -bin: #pts = 13265, #dims = 25, size = 1326508B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_60_dists_float.bin -bin: #pts = 13265, #dims = 25, size = 1326508B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_70_idx_uint32.bin -bin: #pts = 13265, #dims = 25, size = 1326508B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_70_dists_float.bin -bin: #pts = 13265, #dims = 25, size = 1326508B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_80_idx_uint32.bin -bin: #pts = 13265, #dims = 25, size = 1326508B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_80_dists_float.bin -bin: #pts = 13265, #dims = 25, size = 1326508B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_90_idx_uint32.bin -bin: #pts = 13265, #dims = 25, size = 1326508B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_90_dists_float.bin -bin: #pts = 13265, #dims = 25, size = 1326508B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin -bin: #pts = 13265, #dims = 25, size = 1326508B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin -bin: #pts = 13265, #dims = 25, size = 1326508B -Finished writing bin. diff --git a/prec40M/build_&_search/early_stop_build_&_search_r150_l300_k50_x10_y0_L.txt b/prec40M/build_&_search/early_stop_build_&_search_r150_l300_k50_x10_y0_L.txt new file mode 100644 index 000000000..db499a82f --- /dev/null +++ b/prec40M/build_&_search/early_stop_build_&_search_r150_l300_k50_x10_y0_L.txt @@ -0,0 +1,84 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.41201s +From graph header, expected_file_size: 17246453220, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_earlystop_memory_index_r150_l300_x_10_y_0_L.......done. Index has 40469609 nodes and 4271143690 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@50 +=================================================================================================== + 50 205.79 6879.70 55.44 4859.33 22760.29 78.55 + 100 124.62 11202.62 92.05 8024.39 27475.83 86.26 + 150 92.43 14903.85 123.93 10818.76 32318.81 89.65 + 200 75.20 18226.06 152.88 13298.50 36122.13 91.56 + 250 64.19 21264.22 179.71 15579.23 40343.23 92.85 + 300 56.38 24139.46 205.31 17736.63 44439.92 93.76 + 350 50.56 26824.08 229.53 19777.54 50537.66 94.43 + 400 46.00 29438.52 253.23 21740.69 51937.45 94.96 + 450 42.21 31964.18 276.29 23689.72 56824.03 95.43 + 500 39.25 34315.37 297.92 25478.36 61234.52 95.79 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_150_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_150_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_200_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_200_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_250_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_250_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_350_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_350_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_400_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_400_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_450_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_450_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_500_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_500_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. diff --git a/prec40M/early-stop-build-x-10-y-0/reduce_prune_r150_l300.txt b/prec40M/build_&_search/early_stop_build_r150_l300_x10_y0_L.txt similarity index 98% rename from prec40M/early-stop-build-x-10-y-0/reduce_prune_r150_l300.txt rename to prec40M/build_&_search/early_stop_build_r150_l300_x10_y0_L.txt index d8ba62d04..2480933cc 100644 --- a/prec40M/early-stop-build-x-10-y-0/reduce_prune_r150_l300.txt +++ b/prec40M/build_&_search/early_stop_build_r150_l300_x10_y0_L.txt @@ -2,8 +2,8 @@ Starting index build with R: 150 Lbuild: 300 alpha: 1.2 #threads: 48 Using AVX2 distance computation DistanceL2Int8. Using only first 40469609 from file.. Starting index build with 40469609 points... - 0% of index build completed. 0.247099% of index build completed. 0.494198% of index build completed. 0.741297% of index build completed. 0.988396% of index build completed. 1.2355% of index build completed. 1.48259% of index build completed. 1.72969% of index build completed. 1.97679% of index build completed. 2.22389% of index build completed. 2.47099% of index build completed. 2.71809% of index build completed. 2.96519% of index build completed. 3.21229% of index build completed. 3.45939% of index build completed. 3.70649% of index build completed. 3.95358% of index build completed. 4.20068% of index build completed. 4.44778% of index build completed. 4.69488% of index build completed. 4.94198% of index build completed. 5.18908% of index build completed. 5.43618% of index build completed. 5.68328% of index build completed. 5.93038% of index build completed. 6.17748% of index build completed. 6.42457% of index build completed. 6.67167% of index build completed. 6.91877% of index build completed. 7.16587% of index build completed. 7.41297% of index build completed. 7.66007% of index build completed. 7.90717% of index build completed. 8.15427% of index build completed. 8.40137% of index build completed. 8.64847% of index build completed. 8.89556% of index build completed. 9.14266% of index build completed. 9.38976% of index build completed. 9.63686% of index build completed. 9.88396% of index build completed. 10.1311% of index build completed. 10.3782% of index build completed. 10.6253% of index build completed. 10.8724% of index build completed. 11.1195% of index build completed. 11.3666% of index build completed. 11.6137% of index build completed. 11.8608% of index build completed. 12.1079% of index build completed. 12.355% of index build completed. 12.602% of index build completed. 12.8491% of index build completed. 13.0962% of index build completed. 13.3433% of index build completed. 13.5904% of index build completed. 13.8375% of index build completed. 14.0846% of index build completed. 14.3317% of index build completed. 14.5788% of index build completed. 14.8259% of index build completed. 15.073% of index build completed. 15.3201% of index build completed. 15.5672% of index build completed. 15.8143% of index build completed. 16.0614% of index build completed. 16.3085% of index build completed. 16.5556% of index build completed. 16.8027% of index build completed. 17.0498% of index build completed. 17.2969% of index build completed. 17.544% of index build completed. 17.7911% of index build completed. 18.0382% of index build completed. 18.2853% of index build completed. 18.5324% of index build completed. 18.7795% of index build completed. 19.0266% of index build completed. 19.2737% of index build completed. 19.5208% of index build completed. 19.7679% of index build completed. 20.015% of index build completed. 20.2621% of index build completed. 20.5092% of index build completed. 20.7563% of index build completed. 21.0034% of index build completed. 21.2505% of index build completed. 21.4976% of index build completed. 21.7447% of index build completed. 21.9918% of index build completed. 22.2389% of index build completed. 22.486% of index build completed. 22.7331% of index build completed. 22.9802% of index build completed. 23.2273% of index build completed. 23.4744% of index build completed. 23.7215% of index build completed. 23.9686% of index build completed. 24.2157% of index build completed. 24.4628% of index build completed. 24.7099% of index build completed. 24.957% of index build completed. 25.2041% of index build completed. 25.4512% of index build completed. 25.6983% of index build completed. 25.9454% of index build completed. 26.1925% of index build completed. 26.4396% of index build completed. 26.6867% of index build completed. 26.9338% of index build completed. 27.1809% of index build completed. 27.428% of index build completed. 27.6751% of index build completed. 27.9222% of index build completed. 28.1693% of index build completed. 28.4164% of index build completed. 28.6635% of index build completed. 28.9106% of index build completed. 29.1577% of index build completed. 29.4048% of index build completed. 29.6519% of index build completed. 29.899% of index build completed. 30.1461% of index build completed. 30.3932% of index build completed. 30.6403% of index build completed. 30.8874% of index build completed. 31.1345% of index build completed. 31.3816% of index build completed. 31.6287% of index build completed. 31.8758% of index build completed. 32.1229% of index build completed. 32.37% of index build completed. 32.6171% of index build completed. 32.8642% of index build completed. 33.1113% of index build completed. 33.3584% of index build completed. 33.6055% of index build completed. 33.8526% of index build completed. 34.0997% of index build completed. 34.3468% of index build completed. 34.5939% of index build completed. 34.841% of index build completed. 35.0881% of index build completed. 35.3352% of index build completed. 35.5823% of index build completed. 35.8294% of index build completed. 36.0765% of index build completed. 36.3236% of index build completed. 36.5707% of index build completed. 36.8178% of index build completed. 37.0649% of index build completed. 37.3119% of index build completed. 37.559% of index build completed. 37.8061% of index build completed. 38.0532% of index build completed. 38.3003% of index build completed. 38.5474% of index build completed. 38.7945% of index build completed. 39.0416% of index build completed. 39.2887% of index build completed. 39.5358% of index build completed. 39.7829% of index build completed. 40.03% of index build completed. 40.2771% of index build completed. 40.5242% of index build completed. 40.7713% of index build completed. 41.0184% of index build completed. 41.2655% of index build completed. 41.5126% of index build completed. 41.7597% of index build completed. 42.0068% of index build completed. 42.2539% of index build completed. 42.501% of index build completed. 42.7481% of index build completed. 42.9952% of index build completed. 43.2423% of index build completed. 43.4894% of index build completed. 43.7365% of index build completed. 43.9836% of index build completed. 44.2307% of index build completed. 44.4778% of index build completed. 44.7249% of index build completed. 44.972% of index build completed. 45.2191% of index build completed. 45.4662% of index build completed. 45.7133% of index build completed. 45.9604% of index build completed. 46.2075% of index build completed. 46.4546% of index build completed. 46.7017% of index build completed. 46.9488% of index build completed. 47.1959% of index build completed. 47.443% of index build completed. 47.6901% of index build completed. 47.9372% of index build completed. 48.1843% of index build completed. 48.4314% of index build completed. 48.6785% of index build completed. 48.9256% of index build completed. 49.1727% of index build completed. 49.4198% of index build completed. 49.6669% of index build completed. 49.914% of index build completed. 50.1611% of index build completed. 50.4082% of index build completed. 50.6553% of index build completed. 50.9024% of index build completed. 51.1495% of index build completed. 51.3966% of index build completed. 51.6437% of index build completed. 51.8908% of index build completed. 52.1379% of index build completed. 52.385% of index build completed. 52.6321% of index build completed. 52.8792% of index build completed. 53.1263% of index build completed. 53.3734% of index build completed. 53.6205% of index build completed. 53.8676% of index build completed. 54.1147% of index build completed. 54.3618% of index build completed. 54.6089% of index build completed. 54.856% of index build completed. 55.1031% of index build completed. 55.3502% of index build completed. 55.5973% of index build completed. 55.8444% of index build completed. 56.0915% of index build completed. 56.3386% of index build completed. 56.5857% of index build completed. 56.8328% of index build completed. 57.0799% of index build completed. 57.327% of index build completed. 57.5741% of index build completed. 57.8212% of index build completed. 58.0683% of index build completed. 58.3154% of index build completed. 58.5625% of index build completed. 58.8096% of index build completed. 59.0567% of index build completed. 59.3038% of index build completed. 59.5509% of index build completed. 59.798% of index build completed. 60.0451% of index build completed. 60.2922% of index build completed. 60.5393% of index build completed. 60.7864% of index build completed. 61.0335% of index build completed. 61.2806% of index build completed. 61.5277% of index build completed. 61.7748% of index build completed. 62.0218% of index build completed. 62.2689% of index build completed. 62.516% of index build completed. 62.7631% of index build completed. 63.0102% of index build completed. 63.2573% of index build completed. 63.5044% of index build completed. 63.7515% of index build completed. 63.9986% of index build completed. 64.2457% of index build completed. 64.4928% of index build completed. 64.7399% of index build completed. 64.987% of index build completed. 65.2341% of index build completed. 65.4812% of index build completed. 65.7283% of index build completed. 65.9754% of index build completed. 66.2225% of index build completed. 66.4696% of index build completed. 66.7167% of index build completed. 66.9638% of index build completed. 67.2109% of index build completed. 67.458% of index build completed. 67.7051% of index build completed. 67.9522% of index build completed. 68.1993% of index build completed. 68.4464% of index build completed. 68.6935% of index build completed. 68.9406% of index build completed. 69.1877% of index build completed. 69.4348% of index build completed. 69.6819% of index build completed. 69.929% of index build completed. 70.1761% of index build completed. 70.4232% of index build completed. 70.6703% of index build completed. 70.9174% of index build completed. 71.1645% of index build completed. 71.4116% of index build completed. 71.6587% of index build completed. 71.9058% of index build completed. 72.1529% of index build completed. 72.4% of index build completed. 72.6471% of index build completed. 72.8942% of index build completed. 73.1413% of index build completed. 73.3884% of index build completed. 73.6355% of index build completed. 73.8826% of index build completed. 74.1297% of index build completed. 74.3768% of index build completed. 74.6239% of index build completed. 74.871% of index build completed. 75.1181% of index build completed. 75.3652% of index build completed. 75.6123% of index build completed. 75.8594% of index build completed. 76.1065% of index build completed. 76.3536% of index build completed. 76.6007% of index build completed. 76.8478% of index build completed. 77.0949% of index build completed. 77.342% of index build completed. 77.5891% of index build completed. 77.8362% of index build completed. 78.0833% of index build completed. 78.3304% of index build completed. 78.5775% of index build completed. 78.8246% of index build completed. 79.0717% of index build completed. 79.3188% of index build completed. 79.5659% of index build completed. 79.813% of index build completed. 80.0601% of index build completed. 80.3072% of index build completed. 80.5543% of index build completed. 80.8014% of index build completed. 81.0485% of index build completed. 81.2956% of index build completed. 81.5427% of index build completed. 81.7898% of index build completed. 82.0369% of index build completed. 82.284% of index build completed. 82.5311% of index build completed. 82.7782% of index build completed. 83.0253% of index build completed. 83.2724% of index build completed. 83.5195% of index build completed. 83.7666% of index build completed. 84.0137% of index build completed. 84.2608% of index build completed. 84.5079% of index build completed. 84.755% of index build completed. 85.0021% of index build completed. 85.2492% of index build completed. 85.4963% of index build completed. 85.7434% of index build completed. 85.9905% of index build completed. 86.2376% of index build completed. 86.4847% of index build completed. 86.7317% of index build completed. 86.9788% of index build completed. 87.2259% of index build completed. 87.473% of index build completed. 87.7201% of index build completed. 87.9672% of index build completed. 88.2143% of index build completed. 88.4614% of index build completed. 88.7085% of index build completed. 88.9556% of index build completed. 89.2027% of index build completed. 89.4498% of index build completed. 89.6969% of index build completed. 89.944% of index build completed. 90.1911% of index build completed. 90.4382% of index build completed. 90.6853% of index build completed. 90.9324% of index build completed. 91.1795% of index build completed. 91.4266% of index build completed. 91.6737% of index build completed. 91.9208% of index build completed. 92.1679% of index build completed. 92.415% of index build completed. 92.6621% of index build completed. 92.9092% of index build completed. 93.1563% of index build completed. 93.4034% of index build completed. 93.6505% of index build completed. 93.8976% of index build completed. 94.1447% of index build completed. 94.3918% of index build completed. 94.6389% of index build completed. 94.886% of index build completed. 95.1331% of index build completed. 95.3802% of index build completed. 95.6273% of index build completed. 95.8744% of index build completed. 96.1215% of index build completed. 96.3686% of index build completed. 96.6157% of index build completed. 96.8628% of index build completed. 97.1099% of index build completed. 97.357% of index build completed. 97.6041% of index build completed. 97.8512% of index build completed. 98.0983% of index build completed. 98.3454% of index build completed. 98.5925% of index build completed. 98.8396% of index build completed. 99.0867% of index build completed. 99.3338% of index build completed. 99.5809% of index build completed. 99.828% of index build completed.Starting final cleanup..done. Link time: 14655.5s -Index built with degree: max:150 avg:105.554 min:1 count(deg<2):574117 -Indexing time: 14674.7 + 0% of index build completed. 0.247099% of index build completed. 0.494198% of index build completed. 0.741297% of index build completed. 0.988396% of index build completed. 1.2355% of index build completed. 1.48259% of index build completed. 1.72969% of index build completed. 1.97679% of index build completed. 2.22389% of index build completed. 2.47099% of index build completed. 2.71809% of index build completed. 2.96519% of index build completed. 3.21229% of index build completed. 3.45939% of index build completed. 3.70649% of index build completed. 3.95358% of index build completed. 4.20068% of index build completed. 4.44778% of index build completed. 4.69488% of index build completed. 4.94198% of index build completed. 5.18908% of index build completed. 5.43618% of index build completed. 5.68328% of index build completed. 5.93038% of index build completed. 6.17748% of index build completed. 6.42457% of index build completed. 6.67167% of index build completed. 6.91877% of index build completed. 7.16587% of index build completed. 7.41297% of index build completed. 7.66007% of index build completed. 7.90717% of index build completed. 8.15427% of index build completed. 8.40137% of index build completed. 8.64847% of index build completed. 8.89556% of index build completed. 9.14266% of index build completed. 9.38976% of index build completed. 9.63686% of index build completed. 9.88396% of index build completed. 10.1311% of index build completed. 10.3782% of index build completed. 10.6253% of index build completed. 10.8724% of index build completed. 11.1195% of index build completed. 11.3666% of index build completed. 11.6137% of index build completed. 11.8608% of index build completed. 12.1079% of index build completed. 12.355% of index build completed. 12.602% of index build completed. 12.8491% of index build completed. 13.0962% of index build completed. 13.3433% of index build completed. 13.5904% of index build completed. 13.8375% of index build completed. 14.0846% of index build completed. 14.3317% of index build completed. 14.5788% of index build completed. 14.8259% of index build completed. 15.073% of index build completed. 15.3201% of index build completed. 15.5672% of index build completed. 15.8143% of index build completed. 16.0614% of index build completed. 16.3085% of index build completed. 16.5556% of index build completed. 16.8027% of index build completed. 17.0498% of index build completed. 17.2969% of index build completed. 17.544% of index build completed. 17.7911% of index build completed. 18.0382% of index build completed. 18.2853% of index build completed. 18.5324% of index build completed. 18.7795% of index build completed. 19.0266% of index build completed. 19.2737% of index build completed. 19.5208% of index build completed. 19.7679% of index build completed. 20.015% of index build completed. 20.2621% of index build completed. 20.5092% of index build completed. 20.7563% of index build completed. 21.0034% of index build completed. 21.2505% of index build completed. 21.4976% of index build completed. 21.7447% of index build completed. 21.9918% of index build completed. 22.2389% of index build completed. 22.486% of index build completed. 22.7331% of index build completed. 22.9802% of index build completed. 23.2273% of index build completed. 23.4744% of index build completed. 23.7215% of index build completed. 23.9686% of index build completed. 24.2157% of index build completed. 24.4628% of index build completed. 24.7099% of index build completed. 24.957% of index build completed. 25.2041% of index build completed. 25.4512% of index build completed. 25.6983% of index build completed. 25.9454% of index build completed. 26.1925% of index build completed. 26.4396% of index build completed. 26.6867% of index build completed. 26.9338% of index build completed. 27.1809% of index build completed. 27.428% of index build completed. 27.6751% of index build completed. 27.9222% of index build completed. 28.1693% of index build completed. 28.4164% of index build completed. 28.6635% of index build completed. 28.9106% of index build completed. 29.1577% of index build completed. 29.4048% of index build completed. 29.6519% of index build completed. 29.899% of index build completed. 30.1461% of index build completed. 30.3932% of index build completed. 30.6403% of index build completed. 30.8874% of index build completed. 31.1345% of index build completed. 31.3816% of index build completed. 31.6287% of index build completed. 31.8758% of index build completed. 32.1229% of index build completed. 32.37% of index build completed. 32.6171% of index build completed. 32.8642% of index build completed. 33.1113% of index build completed. 33.3584% of index build completed. 33.6055% of index build completed. 33.8526% of index build completed. 34.0997% of index build completed. 34.3468% of index build completed. 34.5939% of index build completed. 34.841% of index build completed. 35.0881% of index build completed. 35.3352% of index build completed. 35.5823% of index build completed. 35.8294% of index build completed. 36.0765% of index build completed. 36.3236% of index build completed. 36.5707% of index build completed. 36.8178% of index build completed. 37.0649% of index build completed. 37.3119% of index build completed. 37.559% of index build completed. 37.8061% of index build completed. 38.0532% of index build completed. 38.3003% of index build completed. 38.5474% of index build completed. 38.7945% of index build completed. 39.0416% of index build completed. 39.2887% of index build completed. 39.5358% of index build completed. 39.7829% of index build completed. 40.03% of index build completed. 40.2771% of index build completed. 40.5242% of index build completed. 40.7713% of index build completed. 41.0184% of index build completed. 41.2655% of index build completed. 41.5126% of index build completed. 41.7597% of index build completed. 42.0068% of index build completed. 42.2539% of index build completed. 42.501% of index build completed. 42.7481% of index build completed. 42.9952% of index build completed. 43.2423% of index build completed. 43.4894% of index build completed. 43.7365% of index build completed. 43.9836% of index build completed. 44.2307% of index build completed. 44.4778% of index build completed. 44.7249% of index build completed. 44.972% of index build completed. 45.2191% of index build completed. 45.4662% of index build completed. 45.7133% of index build completed. 45.9604% of index build completed. 46.2075% of index build completed. 46.4546% of index build completed. 46.7017% of index build completed. 46.9488% of index build completed. 47.1959% of index build completed. 47.443% of index build completed. 47.6901% of index build completed. 47.9372% of index build completed. 48.1843% of index build completed. 48.4314% of index build completed. 48.6785% of index build completed. 48.9256% of index build completed. 49.1727% of index build completed. 49.4198% of index build completed. 49.6669% of index build completed. 49.914% of index build completed. 50.1611% of index build completed. 50.4082% of index build completed. 50.6553% of index build completed. 50.9024% of index build completed. 51.1495% of index build completed. 51.3966% of index build completed. 51.6437% of index build completed. 51.8908% of index build completed. 52.1379% of index build completed. 52.385% of index build completed. 52.6321% of index build completed. 52.8792% of index build completed. 53.1263% of index build completed. 53.3734% of index build completed. 53.6205% of index build completed. 53.8676% of index build completed. 54.1147% of index build completed. 54.3618% of index build completed. 54.6089% of index build completed. 54.856% of index build completed. 55.1031% of index build completed. 55.3502% of index build completed. 55.5973% of index build completed. 55.8444% of index build completed. 56.0915% of index build completed. 56.3386% of index build completed. 56.5857% of index build completed. 56.8328% of index build completed. 57.0799% of index build completed. 57.327% of index build completed. 57.5741% of index build completed. 57.8212% of index build completed. 58.0683% of index build completed. 58.3154% of index build completed. 58.5625% of index build completed. 58.8096% of index build completed. 59.0567% of index build completed. 59.3038% of index build completed. 59.5509% of index build completed. 59.798% of index build completed. 60.0451% of index build completed. 60.2922% of index build completed. 60.5393% of index build completed. 60.7864% of index build completed. 61.0335% of index build completed. 61.2806% of index build completed. 61.5277% of index build completed. 61.7748% of index build completed. 62.0218% of index build completed. 62.2689% of index build completed. 62.516% of index build completed. 62.7631% of index build completed. 63.0102% of index build completed. 63.2573% of index build completed. 63.5044% of index build completed. 63.7515% of index build completed. 63.9986% of index build completed. 64.2457% of index build completed. 64.4928% of index build completed. 64.7399% of index build completed. 64.987% of index build completed. 65.2341% of index build completed. 65.4812% of index build completed. 65.7283% of index build completed. 65.9754% of index build completed. 66.2225% of index build completed. 66.4696% of index build completed. 66.7167% of index build completed. 66.9638% of index build completed. 67.2109% of index build completed. 67.458% of index build completed. 67.7051% of index build completed. 67.9522% of index build completed. 68.1993% of index build completed. 68.4464% of index build completed. 68.6935% of index build completed. 68.9406% of index build completed. 69.1877% of index build completed. 69.4348% of index build completed. 69.6819% of index build completed. 69.929% of index build completed. 70.1761% of index build completed. 70.4232% of index build completed. 70.6703% of index build completed. 70.9174% of index build completed. 71.1645% of index build completed. 71.4116% of index build completed. 71.6587% of index build completed. 71.9058% of index build completed. 72.1529% of index build completed. 72.4% of index build completed. 72.6471% of index build completed. 72.8942% of index build completed. 73.1413% of index build completed. 73.3884% of index build completed. 73.6355% of index build completed. 73.8826% of index build completed. 74.1297% of index build completed. 74.3768% of index build completed. 74.6239% of index build completed. 74.871% of index build completed. 75.1181% of index build completed. 75.3652% of index build completed. 75.6123% of index build completed. 75.8594% of index build completed. 76.1065% of index build completed. 76.3536% of index build completed. 76.6007% of index build completed. 76.8478% of index build completed. 77.0949% of index build completed. 77.342% of index build completed. 77.5891% of index build completed. 77.8362% of index build completed. 78.0833% of index build completed. 78.3304% of index build completed. 78.5775% of index build completed. 78.8246% of index build completed. 79.0717% of index build completed. 79.3188% of index build completed. 79.5659% of index build completed. 79.813% of index build completed. 80.0601% of index build completed. 80.3072% of index build completed. 80.5543% of index build completed. 80.8014% of index build completed. 81.0485% of index build completed. 81.2956% of index build completed. 81.5427% of index build completed. 81.7898% of index build completed. 82.0369% of index build completed. 82.284% of index build completed. 82.5311% of index build completed. 82.7782% of index build completed. 83.0253% of index build completed. 83.2724% of index build completed. 83.5195% of index build completed. 83.7666% of index build completed. 84.0137% of index build completed. 84.2608% of index build completed. 84.5079% of index build completed. 84.755% of index build completed. 85.0021% of index build completed. 85.2492% of index build completed. 85.4963% of index build completed. 85.7434% of index build completed. 85.9905% of index build completed. 86.2376% of index build completed. 86.4847% of index build completed. 86.7317% of index build completed. 86.9788% of index build completed. 87.2259% of index build completed. 87.473% of index build completed. 87.7201% of index build completed. 87.9672% of index build completed. 88.2143% of index build completed. 88.4614% of index build completed. 88.7085% of index build completed. 88.9556% of index build completed. 89.2027% of index build completed. 89.4498% of index build completed. 89.6969% of index build completed. 89.944% of index build completed. 90.1911% of index build completed. 90.4382% of index build completed. 90.6853% of index build completed. 90.9324% of index build completed. 91.1795% of index build completed. 91.4266% of index build completed. 91.6737% of index build completed. 91.9208% of index build completed. 92.1679% of index build completed. 92.415% of index build completed. 92.6621% of index build completed. 92.9092% of index build completed. 93.1563% of index build completed. 93.4034% of index build completed. 93.6505% of index build completed. 93.8976% of index build completed. 94.1447% of index build completed. 94.3918% of index build completed. 94.6389% of index build completed. 94.886% of index build completed. 95.1331% of index build completed. 95.3802% of index build completed. 95.6273% of index build completed. 95.8744% of index build completed. 96.1215% of index build completed. 96.3686% of index build completed. 96.6157% of index build completed. 96.8628% of index build completed. 97.1099% of index build completed. 97.357% of index build completed. 97.6041% of index build completed. 97.8512% of index build completed. 98.0983% of index build completed. 98.3454% of index build completed. 98.5925% of index build completed. 98.8396% of index build completed. 99.0867% of index build completed. 99.3338% of index build completed. 99.5809% of index build completed. 99.828% of index build completed.Starting final cleanup..done. Link time: 14110.7s +Index built with degree: max:150 avg:105.54 min:1 count(deg<2):574870 +Indexing time: 14120.8 Not saving tags as they are not enabled. -Time taken for save: 38.3406s. +Time taken for save: 28.7461s. diff --git a/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k10.txt b/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k10.txt deleted file mode 100644 index 5fda0e33d..000000000 --- a/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k10.txt +++ /dev/null @@ -1,21 +0,0 @@ -Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. -Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 -Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... -Metadata: #pts = 13265, #dims = 100... -Using AVX2 distance computation DistanceL2Int8. -Resizing took: 1.32297s -From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 -Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 -Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 -Index loaded -Using 1 threads to search - Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@10 -=================================================================================================== - 300 42.83 25015.15 202.91 23346.59 68870.16 97.93 -Done searching. Now saving results -Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin -bin: #pts = 13265, #dims = 10, size = 530608B -Finished writing bin. diff --git a/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k100.txt b/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k100.txt deleted file mode 100644 index b5d2f41a8..000000000 --- a/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k100.txt +++ /dev/null @@ -1,21 +0,0 @@ -Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. -Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 -Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... -Metadata: #pts = 13265, #dims = 100... -Using AVX2 distance computation DistanceL2Int8. -Resizing took: 1.30586s -From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 -Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 -Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 -Index loaded -Using 1 threads to search - Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@100 -=================================================================================================== - 300 53.70 25015.15 202.91 18620.22 41585.87 91.35 -Done searching. Now saving results -Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin -bin: #pts = 13265, #dims = 100, size = 5306008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin -bin: #pts = 13265, #dims = 100, size = 5306008B -Finished writing bin. diff --git a/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k30.txt b/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k30.txt deleted file mode 100644 index 9a11979c7..000000000 --- a/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k30.txt +++ /dev/null @@ -1,21 +0,0 @@ -Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. -Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 -Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... -Metadata: #pts = 13265, #dims = 100... -Using AVX2 distance computation DistanceL2Int8. -Resizing took: 1.3682s -From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 -Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 -Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 -Index loaded -Using 1 threads to search - Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@30 -=================================================================================================== - 300 44.48 25015.15 202.91 22483.01 83358.17 96.07 -Done searching. Now saving results -Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin -bin: #pts = 13265, #dims = 30, size = 1591808B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin -bin: #pts = 13265, #dims = 30, size = 1591808B -Finished writing bin. diff --git a/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k50.txt b/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k50.txt deleted file mode 100644 index 63072e06b..000000000 --- a/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k50.txt +++ /dev/null @@ -1,21 +0,0 @@ -Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. -Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 -Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... -Metadata: #pts = 13265, #dims = 100... -Using AVX2 distance computation DistanceL2Int8. -Resizing took: 1.3699s -From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 -Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 -Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 -Index loaded -Using 1 threads to search - Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@50 -=================================================================================================== - 300 53.67 25015.15 202.91 18630.79 42221.48 94.55 -Done searching. Now saving results -Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. diff --git a/prec40M/search_only/early_stop_search_r150_l300_k50_x10_y0_K.txt b/prec40M/search_only/early_stop_search_r150_l300_k50_x10_y0_K.txt new file mode 100644 index 000000000..7af630670 --- /dev/null +++ b/prec40M/search_only/early_stop_search_r150_l300_k50_x10_y0_K.txt @@ -0,0 +1,84 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 2.54451s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@50 +=================================================================================================== + 50 103.14 7149.92 55.00 9695.56 43790.95 79.69 + 100 93.59 8718.79 67.67 10685.09 43798.63 83.13 + 150 83.29 8828.62 68.56 12006.17 63147.71 83.29 + 200 69.66 8831.40 68.59 14354.46 98533.82 83.30 + 250 79.34 8831.58 68.59 12603.72 60889.81 83.30 + 300 86.38 8831.58 68.59 11576.72 45677.29 83.30 + 350 78.09 8831.58 68.59 12805.55 67069.02 83.30 + 400 77.27 8831.58 68.59 12941.84 63518.28 83.30 + 450 76.49 8831.58 68.59 13073.44 64098.41 83.30 + 500 73.66 8831.58 68.59 13575.05 73795.97 83.30 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_150_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_150_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_200_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_200_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_250_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_250_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_350_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_350_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_400_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_400_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_450_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_450_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_500_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_500_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. diff --git a/prec40M/search_only/early_stop_search_r150_l300_k50_x10_y0_L.txt b/prec40M/search_only/early_stop_search_r150_l300_k50_x10_y0_L.txt new file mode 100644 index 000000000..3d3e21465 --- /dev/null +++ b/prec40M/search_only/early_stop_search_r150_l300_k50_x10_y0_L.txt @@ -0,0 +1,84 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.35261s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@50 +=================================================================================================== + 50 198.75 7149.92 55.00 5031.34 22593.96 79.69 + 100 118.69 11640.27 91.23 8425.49 27716.19 87.33 + 150 88.00 15499.88 122.88 11363.82 32365.00 90.61 + 200 71.21 18942.36 151.51 14041.94 36769.11 92.49 + 250 60.84 22119.38 178.28 16437.29 41746.58 93.71 + 300 53.51 25015.15 202.91 18686.43 46725.85 94.55 + 350 47.99 27811.66 226.88 20837.03 51399.47 95.19 + 400 43.52 30522.28 250.33 22975.24 56028.80 95.70 + 450 40.11 33087.46 272.69 24931.99 60298.46 96.11 + 500 37.61 35495.27 293.78 26588.03 63596.32 96.43 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_150_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_150_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_200_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_200_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_250_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_250_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_350_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_350_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_400_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_400_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_450_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_450_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_500_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_500_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. diff --git a/prec40M/search_only/early_stop_search_r150_l300_k50_x5_y0_K.txt b/prec40M/search_only/early_stop_search_r150_l300_k50_x5_y0_K.txt new file mode 100644 index 000000000..cb3a2e15a --- /dev/null +++ b/prec40M/search_only/early_stop_search_r150_l300_k50_x5_y0_K.txt @@ -0,0 +1,84 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 2.67896s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@50 +=================================================================================================== + 50 92.70 5826.41 44.82 10787.55 54707.85 75.56 + 100 103.06 5992.70 46.22 9702.70 50245.97 76.03 + 150 118.29 5992.72 46.23 8453.61 43668.85 76.03 + 200 83.78 5992.72 46.23 11935.34 102525.97 76.03 + 250 114.22 5992.72 46.23 8754.73 45815.66 76.03 + 300 90.91 5992.72 46.23 10999.88 59534.30 76.03 + 350 100.15 5992.72 46.23 9985.23 49787.56 76.03 + 400 110.68 5992.72 46.23 9034.44 45854.38 76.03 + 450 97.91 5992.72 46.23 10213.48 51556.87 76.03 + 500 101.96 5992.72 46.23 9807.39 48884.99 76.03 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_150_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_150_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_200_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_200_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_250_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_250_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_350_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_350_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_400_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_400_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_450_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_450_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_500_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_500_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. diff --git a/prec40M/search_only/early_stop_search_r150_l300_k50_x5_y0_L.txt b/prec40M/search_only/early_stop_search_r150_l300_k50_x5_y0_L.txt new file mode 100644 index 000000000..29e1bd925 --- /dev/null +++ b/prec40M/search_only/early_stop_search_r150_l300_k50_x5_y0_L.txt @@ -0,0 +1,84 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 2.73975s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@50 +=================================================================================================== + 50 138.48 5826.41 44.82 7221.22 41937.95 75.56 + 100 84.11 8608.48 66.84 11889.23 53452.88 82.88 + 150 68.15 10925.24 85.45 14674.08 66056.72 86.48 + 200 58.07 13030.90 102.54 17219.57 78579.05 88.72 + 250 49.56 14996.30 118.66 20178.49 94388.32 90.28 + 300 44.64 16868.74 134.20 22402.45 105835.72 91.43 + 350 40.18 18684.84 149.37 24887.01 114521.68 92.34 + 400 35.84 20391.02 163.74 27904.45 135528.23 93.06 + 450 33.22 22096.57 178.15 30099.77 127465.85 93.66 + 500 28.97 23637.48 191.27 34514.04 160248.77 94.14 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_150_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_150_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_200_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_200_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_250_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_250_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_350_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_350_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_400_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_400_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_450_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_450_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_500_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_500_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. diff --git a/prec40M/k-insert-stop-x-10-y-0/early_stop_r150_k10.txt b/prec40M/search_only/early_stop_x10_y0_K/early_stop_r150_k10.txt similarity index 100% rename from prec40M/k-insert-stop-x-10-y-0/early_stop_r150_k10.txt rename to prec40M/search_only/early_stop_x10_y0_K/early_stop_r150_k10.txt diff --git a/prec40M/k-insert-stop-x-10-y-0/early_stop_r150_k100.txt b/prec40M/search_only/early_stop_x10_y0_K/early_stop_r150_k100.txt similarity index 100% rename from prec40M/k-insert-stop-x-10-y-0/early_stop_r150_k100.txt rename to prec40M/search_only/early_stop_x10_y0_K/early_stop_r150_k100.txt diff --git a/prec40M/k-insert-stop-x-10-y-0/early_stop_r150_k30.txt b/prec40M/search_only/early_stop_x10_y0_K/early_stop_r150_k30.txt similarity index 100% rename from prec40M/k-insert-stop-x-10-y-0/early_stop_r150_k30.txt rename to prec40M/search_only/early_stop_x10_y0_K/early_stop_r150_k30.txt diff --git a/prec40M/k-insert-stop-x-10-y-0/early_stop_r150_k50.txt b/prec40M/search_only/early_stop_x10_y0_K/early_stop_r150_k50.txt similarity index 100% rename from prec40M/k-insert-stop-x-10-y-0/early_stop_r150_k50.txt rename to prec40M/search_only/early_stop_x10_y0_K/early_stop_r150_k50.txt diff --git a/prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k10.txt b/prec40M/search_only/early_stop_x10_y0_L/early_stop_r150_k10.txt similarity index 100% rename from prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k10.txt rename to prec40M/search_only/early_stop_x10_y0_L/early_stop_r150_k10.txt diff --git a/prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k100.txt b/prec40M/search_only/early_stop_x10_y0_L/early_stop_r150_k100.txt similarity index 100% rename from prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k100.txt rename to prec40M/search_only/early_stop_x10_y0_L/early_stop_r150_k100.txt diff --git a/prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k30.txt b/prec40M/search_only/early_stop_x10_y0_L/early_stop_r150_k30.txt similarity index 100% rename from prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k30.txt rename to prec40M/search_only/early_stop_x10_y0_L/early_stop_r150_k30.txt diff --git a/prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k50.txt b/prec40M/search_only/early_stop_x10_y0_L/early_stop_r150_k50.txt similarity index 100% rename from prec40M/insert-based-stop-x-10-y-0/early_stop_r150_k50.txt rename to prec40M/search_only/early_stop_x10_y0_L/early_stop_r150_k50.txt diff --git a/prec40M/k-insert-stop-x-5-y-0/early_stop_r150_k10.txt b/prec40M/search_only/early_stop_x5_y0_K/early_stop_r150_k10.txt similarity index 100% rename from prec40M/k-insert-stop-x-5-y-0/early_stop_r150_k10.txt rename to prec40M/search_only/early_stop_x5_y0_K/early_stop_r150_k10.txt diff --git a/prec40M/k-insert-stop-x-5-y-0/early_stop_r150_k100.txt b/prec40M/search_only/early_stop_x5_y0_K/early_stop_r150_k100.txt similarity index 100% rename from prec40M/k-insert-stop-x-5-y-0/early_stop_r150_k100.txt rename to prec40M/search_only/early_stop_x5_y0_K/early_stop_r150_k100.txt diff --git a/prec40M/k-insert-stop-x-5-y-0/early_stop_r150_k30.txt b/prec40M/search_only/early_stop_x5_y0_K/early_stop_r150_k30.txt similarity index 100% rename from prec40M/k-insert-stop-x-5-y-0/early_stop_r150_k30.txt rename to prec40M/search_only/early_stop_x5_y0_K/early_stop_r150_k30.txt diff --git a/prec40M/k-insert-stop-x-5-y-0/early_stop_r150_k50.txt b/prec40M/search_only/early_stop_x5_y0_K/early_stop_r150_k50.txt similarity index 100% rename from prec40M/k-insert-stop-x-5-y-0/early_stop_r150_k50.txt rename to prec40M/search_only/early_stop_x5_y0_K/early_stop_r150_k50.txt diff --git a/run-build.sh b/run-build.sh index eb5f7a1ee..62abd468c 100644 --- a/run-build.sh +++ b/run-build.sh @@ -1,2 +1,2 @@ cd build -./apps/build_memory_index --data_path /nvmessd1/fbv4/prec40M.bin --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_earlystop_memory_index_r150_l300 -R 150 -L 300 -T 48 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/reduce_prune_r150_l300.txt \ No newline at end of file +./apps/build_memory_index --data_path /nvmessd1/fbv4/prec40M.bin --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_earlystop_memory_index_r150_l300_x_10_y_0_L -R 150 -L 300 -T 48 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build_r150_l300_x10_y0_L.txt \ No newline at end of file diff --git a/run-search.sh b/run-search.sh index bc2d44af9..0256d859d 100644 --- a/run-search.sh +++ b/run-search.sh @@ -1,5 +1,6 @@ cd build -./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 10 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k10.txt -./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 30 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k30.txt -./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 50 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k50.txt -./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 100 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k100.txt \ No newline at end of file +# ./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 10 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k10.txt +# ./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 30 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k30.txt +# ./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 50 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k50.txt +# ./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 100 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k100.txt +./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 50 -L 50 100 150 200 250 300 350 400 450 500 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/search_only/early_stop_search_r150_l300_k50_x5_y0_L.txt \ No newline at end of file diff --git a/src/index.cpp b/src/index.cpp index 3498cd024..3747ec26d 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -881,8 +881,8 @@ std::pair Index::iterate_to_fixed_point( uint32_t hops = 0; uint32_t cmps = 0; - std::queue last_K_insertions; - int x = 10; + std::queue last_insertions; + int x = 5; int y = 0; float prev_distance_to_query = 0.0; @@ -891,13 +891,13 @@ std::pair Index::iterate_to_fixed_point( hops++; // Check if the sum of elements of the queue is less than y, if yes then exit the loop - int sum_last_K_insertions = 0; - std::queue temp_queue = last_K_insertions; + int sum_last_insertions = 0; + std::queue temp_queue = last_insertions; while (!temp_queue.empty()) { - sum_last_K_insertions += temp_queue.front(); + sum_last_insertions += temp_queue.front(); temp_queue.pop(); } - if (sum_last_K_insertions <= y && hops >= x) { + if (sum_last_insertions <= y && hops >= x) { break; } @@ -1007,9 +1007,9 @@ std::pair Index::iterate_to_fixed_point( insertions_this_iter += best_L_nodes.check_in_top_k(Neighbor(id_scratch[m], dist_scratch[m]), K); best_L_nodes.insert(Neighbor(id_scratch[m], dist_scratch[m])); } - last_K_insertions.push(insertions_this_iter); - if (last_K_insertions.size() > x) { - last_K_insertions.pop(); + last_insertions.push(insertions_this_iter); + if (last_insertions.size() > x) { + last_insertions.pop(); } } // if (search_invocation){ From 0c83bb90abe1e6c87d242ae48e42b86d4d48fb7f Mon Sep 17 00:00:00 2001 From: ravishankar Date: Tue, 3 Dec 2024 05:23:52 -0800 Subject: [PATCH 6/9] update reruns --- ...arly_stop_search_r150_l300_k50_x5_y0_L.txt | 42 ++++--------------- run-search.sh | 2 +- 2 files changed, 8 insertions(+), 36 deletions(-) diff --git a/prec40M/search_only/early_stop_search_r150_l300_k50_x5_y0_L.txt b/prec40M/search_only/early_stop_search_r150_l300_k50_x5_y0_L.txt index 29e1bd925..305dc9af8 100644 --- a/prec40M/search_only/early_stop_search_r150_l300_k50_x5_y0_L.txt +++ b/prec40M/search_only/early_stop_search_r150_l300_k50_x5_y0_L.txt @@ -3,7 +3,7 @@ Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... Metadata: #pts = 13265, #dims = 100... Using AVX2 distance computation DistanceL2Int8. -Resizing took: 2.73975s +Resizing took: 2.72896s From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 @@ -11,16 +11,12 @@ Index loaded Using 1 threads to search Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@50 =================================================================================================== - 50 138.48 5826.41 44.82 7221.22 41937.95 75.56 - 100 84.11 8608.48 66.84 11889.23 53452.88 82.88 - 150 68.15 10925.24 85.45 14674.08 66056.72 86.48 - 200 58.07 13030.90 102.54 17219.57 78579.05 88.72 - 250 49.56 14996.30 118.66 20178.49 94388.32 90.28 - 300 44.64 16868.74 134.20 22402.45 105835.72 91.43 - 350 40.18 18684.84 149.37 24887.01 114521.68 92.34 - 400 35.84 20391.02 163.74 27904.45 135528.23 93.06 - 450 33.22 22096.57 178.15 30099.77 127465.85 93.66 - 500 28.97 23637.48 191.27 34514.04 160248.77 94.14 + 50 143.87 5826.41 44.82 6950.25 32920.13 75.56 + 100 85.51 8608.48 66.84 11693.88 54980.88 82.88 + 150 74.34 10925.24 85.45 13450.85 44510.98 86.48 + 200 58.23 13030.90 102.54 17171.86 88702.41 88.72 + 250 46.48 14996.30 118.66 21516.11 118291.45 90.28 + 300 42.52 16868.74 134.20 23517.47 139291.89 91.43 Done searching. Now saving results Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin bin: #pts = 13265, #dims = 50, size = 2653008B @@ -58,27 +54,3 @@ Finished writing bin. Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin bin: #pts = 13265, #dims = 50, size = 2653008B Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_350_idx_uint32.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_350_dists_float.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_400_idx_uint32.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_400_dists_float.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_450_idx_uint32.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_450_dists_float.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_500_idx_uint32.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_500_dists_float.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. diff --git a/run-search.sh b/run-search.sh index 0256d859d..55849aec6 100644 --- a/run-search.sh +++ b/run-search.sh @@ -3,4 +3,4 @@ cd build # ./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 30 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k30.txt # ./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 50 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k50.txt # ./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 100 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k100.txt -./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 50 -L 50 100 150 200 250 300 350 400 450 500 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/search_only/early_stop_search_r150_l300_k50_x5_y0_L.txt \ No newline at end of file +./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 50 -L 50 100 150 200 250 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/search_only/early_stop_search_r150_l300_k50_x5_y0_L.txt \ No newline at end of file From 8c4d91f6dea5d9052d6740eaaa997a31417e23b8 Mon Sep 17 00:00:00 2001 From: ravishankar Date: Tue, 3 Dec 2024 07:44:16 -0800 Subject: [PATCH 7/9] remove results --- prec40M/baseline_r150_l300_k50.txt | 56 ------------------------------ 1 file changed, 56 deletions(-) delete mode 100644 prec40M/baseline_r150_l300_k50.txt diff --git a/prec40M/baseline_r150_l300_k50.txt b/prec40M/baseline_r150_l300_k50.txt deleted file mode 100644 index 70e809979..000000000 --- a/prec40M/baseline_r150_l300_k50.txt +++ /dev/null @@ -1,56 +0,0 @@ -Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. -Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 -Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... -Metadata: #pts = 13265, #dims = 100... -Using AVX2 distance computation DistanceL2Int8. -Resizing took: 1.35062s -From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 -Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 -Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 -Index loaded -Using 1 threads to search - Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@50 -=================================================================================================== - 50 204.00 7149.92 55.00 4901.96 15809.95 79.69 - 100 122.17 11640.27 91.23 8185.00 21637.09 87.33 - 150 90.58 15499.88 122.88 11039.73 25685.82 90.61 - 200 73.30 18942.36 151.51 13642.69 30741.64 92.49 - 250 62.50 22119.38 178.28 15998.88 33482.66 93.71 - 300 55.09 25015.15 202.91 18151.68 37464.98 94.55 -Done searching. Now saving results -Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_150_idx_uint32.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_150_dists_float.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_200_idx_uint32.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_200_dists_float.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_250_idx_uint32.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_250_dists_float.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. -Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin -bin: #pts = 13265, #dims = 50, size = 2653008B -Finished writing bin. From 7c9521fb44a733cf8af92800f99caf172e364dfd Mon Sep 17 00:00:00 2001 From: ravishankar Date: Tue, 3 Dec 2024 19:54:13 -0800 Subject: [PATCH 8/9] add more results --- ...arly_stop_search_r150_l300_k50_x7_y0_L.txt | 56 +++++++++++++++++++ run-search.sh | 2 +- src/index.cpp | 2 +- 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 prec40M/search_only/early_stop_search_r150_l300_k50_x7_y0_L.txt diff --git a/prec40M/search_only/early_stop_search_r150_l300_k50_x7_y0_L.txt b/prec40M/search_only/early_stop_search_r150_l300_k50_x7_y0_L.txt new file mode 100644 index 000000000..201faa774 --- /dev/null +++ b/prec40M/search_only/early_stop_search_r150_l300_k50_x7_y0_L.txt @@ -0,0 +1,56 @@ +Reading (with alignment) bin file /nvmessd1/fbv4/queries384d.bin ...Metadata: #pts = 13265, #dims = 384, aligned_dim = 384... allocating aligned memory of 5093760 bytes... done. Copying data to mem_aligned buffer... done. +Opened: /nvmessd1/fbv4/gt100_prec40M, size: 10612008, cache_size: 10612008 +Reading truthset file /nvmessd1/fbv4/gt100_prec40M ... +Metadata: #pts = 13265, #dims = 100... +Using AVX2 distance computation DistanceL2Int8. +Resizing took: 1.39078s +From graph header, expected_file_size: 18732710752, _max_observed_degree: 150, _start: 11890341, file_frozen_pts: 0 +Loading vamana graph /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300.......done. Index has 40469609 nodes and 4642708073 out-edges, _start is set to 11890341 +Num frozen points:0 _nd: 40469609 _start: 11890341 size(_location_to_tag): 0 size(_tag_to_location):0 Max points: 40469609 +Index loaded +Using 1 threads to search + Ls QPS Avg dist cmps Avg hops Mean Latency (mus) 99.9 Latency Recall@50 +=================================================================================================== + 50 219.83 6571.48 50.53 4549.00 22603.01 78.15 + 100 138.20 10162.82 79.23 7236.04 27292.48 85.50 + 150 105.45 13149.50 103.48 9482.81 29771.95 88.87 + 200 86.58 15806.06 125.31 11550.14 34007.52 90.86 + 250 74.60 18226.08 145.43 13404.36 36635.31 92.18 + 300 66.05 20523.22 164.73 15140.81 41088.31 93.15 +Done searching. Now saving results +Writing bin: /home/rakri/avarhade/Dump/tmp_50_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_50_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_100_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_150_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_150_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_200_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_200_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_250_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_250_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_idx_uint32.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. +Writing bin: /home/rakri/avarhade/Dump/tmp_300_dists_float.bin +bin: #pts = 13265, #dims = 50, size = 2653008B +Finished writing bin. diff --git a/run-search.sh b/run-search.sh index 55849aec6..3869bcaf6 100644 --- a/run-search.sh +++ b/run-search.sh @@ -3,4 +3,4 @@ cd build # ./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 30 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k30.txt # ./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 50 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k50.txt # ./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 100 -L 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/early-stop-build-x-10-y-0/early_stop_r150_k100.txt -./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 50 -L 50 100 150 200 250 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/search_only/early_stop_search_r150_l300_k50_x5_y0_L.txt \ No newline at end of file +./apps/search_memory_index --data_type int8 --dist_fn l2 --index_path_prefix /nvmessd1/fbv4/avarhade/prec40M_memory_index_r150_l300 --gt_file /nvmessd1/fbv4/gt100_prec40M --query_file /nvmessd1/fbv4/queries384d.bin --result_path /home/rakri/avarhade/Dump/tmp -K 50 -L 50 100 150 200 250 300 -T 1 > /home/rakri/avarhade/DiskANN/prec40M/search_only/early_stop_search_r150_l300_k50_x7_y0_L.txt \ No newline at end of file diff --git a/src/index.cpp b/src/index.cpp index 3747ec26d..08056508a 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -882,7 +882,7 @@ std::pair Index::iterate_to_fixed_point( uint32_t cmps = 0; std::queue last_insertions; - int x = 5; + int x = 7; int y = 0; float prev_distance_to_query = 0.0; From 5dc2eea0cf8a1c8ee542b5ac2148a9e62543f3c7 Mon Sep 17 00:00:00 2001 From: Amey Varhade Date: Fri, 6 Dec 2024 10:06:05 +0530 Subject: [PATCH 9/9] add plots --- plot.py | 85 +++++++++++++++++++++++++++++++ prec40M/dist_comps_vs_recall.png | Bin 0 -> 34975 bytes prec40M/hops_vs_recall.png | Bin 0 -> 32927 bytes prec40M/latency_vs_recall.png | Bin 0 -> 42330 bytes prec40M/qps_vs_recall.png | Bin 0 -> 41680 bytes 5 files changed, 85 insertions(+) create mode 100644 plot.py create mode 100644 prec40M/dist_comps_vs_recall.png create mode 100644 prec40M/hops_vs_recall.png create mode 100644 prec40M/latency_vs_recall.png create mode 100644 prec40M/qps_vs_recall.png diff --git a/plot.py b/plot.py new file mode 100644 index 000000000..111ecfb49 --- /dev/null +++ b/plot.py @@ -0,0 +1,85 @@ +import matplotlib.pyplot as plt + +# Data for different configurations +configurations = [ + { + 'label': 'baseline', + 'recall': [80.60, 88.66, 92.12, 94.05, 95.26, 96.09], + 'QPS': [204.00, 122.17, 90.58, 73.30, 62.50, 55.09], + 'avg_dist_cmps': [7716.33, 13663.56, 19477.48, 25174.82, 30768.75, 36281.84], + 'avg_hops': [59.49, 108.56, 158.08, 207.77, 257.52, 307.35], + 'mean_latency': [4901.96, 8185.00, 11039.73, 13642.69, 15998.88, 18151.68] + }, + { + 'label': 'x=5', + 'recall': [75.56, 82.88, 86.48, 88.72, 90.28, 91.43], + 'QPS': [138.48, 84.11, 68.15, 58.07, 49.56, 44.64], + 'avg_dist_cmps': [5826.41, 8608.48, 10925.24, 13030.90, 14996.30, 16868.74], + 'avg_hops': [44.82, 66.84, 85.45, 102.54, 118.66, 134.20], + 'mean_latency': [7221.22, 11889.23, 14674.08, 17219.57, 20178.49, 22402.45] + }, + { + 'label': 'x=7', + 'recall': [78.15, 85.50, 88.87, 90.86, 92.18, 93.15], + 'QPS': [219.83, 138.20, 105.45, 86.58, 74.60, 66.05], + 'avg_dist_cmps': [6571.48, 10162.82, 13149.50, 15806.06, 18226.08, 20523.22], + 'avg_hops': [50.53, 79.23, 103.48, 125.31, 145.43, 164.73], + 'mean_latency': [4549.00, 7236.04, 9482.81, 11550.14, 13404.36, 15140.81] + }, + { + 'label': 'x=10', + 'recall': [79.69, 87.33, 90.61, 92.49, 93.71, 94.55], + 'QPS': [198.75, 118.69, 88.00, 71.21, 60.84, 53.51], + 'avg_dist_cmps': [7149.92, 11640.27, 15499.88, 18942.36, 22119.38, 25015.15], + 'avg_hops': [55.00, 91.23, 122.88, 151.51, 178.28, 202.91], + 'mean_latency': [5031.34, 8425.49, 11363.82, 14041.94, 16437.29, 18686.43] + } + # Add more configurations here +] + +# Colors for different configurations +colors = ['b', 'g', 'r', 'y'] + +# Plot latency vs recall +plt.figure() +for i, config in enumerate(configurations): + plt.plot(config['mean_latency'], config['recall'], marker='o', color=colors[i % len(colors)], label=config['label']) +plt.xlabel('Mean Latency (mus)') +plt.ylabel('Recall@50') +plt.title('Mean Latency vs Recall') +plt.legend() +plt.grid(True) +plt.savefig('prec40M/latency_vs_recall.png') + +# Plot QPS vs recall +plt.figure() +for i, config in enumerate(configurations): + plt.plot(config['QPS'], config['recall'], marker='o', color=colors[i % len(colors)], label=config['label']) +plt.xlabel('QPS') +plt.ylabel('Recall@50') +plt.title('QPS vs Recall') +plt.legend() +plt.grid(True) +plt.savefig('prec40M/qps_vs_recall.png') + +# Plot hops vs recall +plt.figure() +for i, config in enumerate(configurations): + plt.plot(config['avg_hops'], config['recall'], marker='o', color=colors[i % len(colors)], label=config['label']) +plt.xlabel('Avg Hops') +plt.ylabel('Recall@50') +plt.title('Avg Hops vs Recall') +plt.legend() +plt.grid(True) +plt.savefig('prec40M/hops_vs_recall.png') + +# Plot dist comps vs recall +plt.figure() +for i, config in enumerate(configurations): + plt.plot(config['avg_dist_cmps'], config['recall'], marker='o', color=colors[i % len(colors)], label=config['label']) +plt.xlabel('Avg Dist Comps') +plt.ylabel('Recall@50') +plt.title('Avg Dist Comps vs Recall') +plt.legend() +plt.grid(True) +plt.savefig('prec40M/dist_comps_vs_recall.png') diff --git a/prec40M/dist_comps_vs_recall.png b/prec40M/dist_comps_vs_recall.png new file mode 100644 index 0000000000000000000000000000000000000000..3198dc1167de04ad4b2d1c127fc6bf94eaf8aa2d GIT binary patch literal 34975 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 N+G)DSB%k3J`Y*J`K(YV; literal 0 HcmV?d00001 diff --git a/prec40M/qps_vs_recall.png b/prec40M/qps_vs_recall.png new file mode 100644 index 0000000000000000000000000000000000000000..350ce899e92ffa8ff2ef87504a121aea0734775c GIT binary patch literal 41680 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%0AfCKV4nlvPHTr-4#fcU_#mRt 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

R-kG8_&o5R|9!rkqfophCd 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