From 2eea80b6dab1bd9eb8b3b20ccd1c627c03d46768 Mon Sep 17 00:00:00 2001 From: Jason Mohoney Date: Wed, 16 Apr 2025 14:37:55 +0000 Subject: [PATCH 001/323] add cuvs --- CMakeLists.txt | 18 +- src/cpp/include/cuv_cluster.h | 174 +++++++++++++++++++ src/cpp/third_party/cmake/fetch_rapids.cmake | 22 +++ src/cpp/third_party/cmake/get_cuvs.cmake | 56 ++++++ test/cpp/test_clustering_benchmark.cpp | 79 +++++++++ test/cpp/test_clustering_correctness.cpp | 157 +++++++++++++++++ test/cpp/test_cuvs_clustering.cpp | 88 ++++++++++ 7 files changed, 593 insertions(+), 1 deletion(-) create mode 100644 src/cpp/include/cuv_cluster.h create mode 100644 src/cpp/third_party/cmake/fetch_rapids.cmake create mode 100644 src/cpp/third_party/cmake/get_cuvs.cmake create mode 100644 test/cpp/test_clustering_benchmark.cpp create mode 100644 test/cpp/test_clustering_correctness.cpp create mode 100644 test/cpp/test_cuvs_clustering.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a4d2c003..a337eb9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,10 +96,25 @@ endif() # --------------------------------------------------------------- # Find Required Packages # --------------------------------------------------------------- +find_package(CuVS REQUIRED) find_package(Torch REQUIRED) find_package(Python3 COMPONENTS Development Interpreter REQUIRED) find_package(Python COMPONENTS Interpreter Development REQUIRED) +include(src/cpp/third_party/cmake/fetch_rapids.cmake) +include(rapids-cmake) +include(rapids-cpm) +include(rapids-cuda) +include(rapids-export) +include(rapids-find) + +rapids_cuda_init_architectures(quake_c) + +rapids_cpm_init() +set(BUILD_CUVS_C_LIBRARY OFF) +include(src/cpp/third_party/cmake/get_cuvs.cmake) + + message(STATUS "Torch include dir: ${TORCH_INCLUDE_DIRS}") message(STATUS "Torch libraries: ${TORCH_LIBRARIES}") message(STATUS "Python include dir: ${Python3_INCLUDE_DIRS}") @@ -131,6 +146,7 @@ target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17) # Base libraries common to all platforms set(LINK_LIBS ${TORCH_LIBRARIES} + cuvs::cuvs -ffast-math -lpthread -fPIC @@ -221,4 +237,4 @@ message(STATUS "MKL_LINK: ${MKL_LINK}") message(STATUS "MKL_INTERFACE_FULL: ${MKL_INTERFACE_FULL}") message(STATUS "MKL_THREADING: ${MKL_THREADING}") message(STATUS "MKL_MPI: ${MKL_MPI}") -message(STATUS "------------------------------------------------") \ No newline at end of file +message(STATUS "------------------------------------------------") diff --git a/src/cpp/include/cuv_cluster.h b/src/cpp/include/cuv_cluster.h new file mode 100644 index 00000000..6e2ab9b4 --- /dev/null +++ b/src/cpp/include/cuv_cluster.h @@ -0,0 +1,174 @@ +#include +#include // For at::cuda::getCurrentCUDAStream() +#include // RAFT resources (handle) +#include // RAFT device view (make_device_matrix_view, etc.) +#include // cuVS k-means API + +#include +#include +#include +#include +#include + +// Optionally, if you have your own enum, you can use that instead of faiss::METRIC_L2/INNER_PRODUCT. +struct ClusteringResult { + torch::Tensor centroids; + // Each pair is (cluster_vectors, cluster_ids) for one cluster. + std::vector> clusters; +}; + + +inline ClusteringResult ClusterWithCuVS(const torch::Tensor& vectors, + const torch::Tensor& ids, + int64_t num_clusters, + int metric = faiss::METRIC_L2) { + using clock = std::chrono::high_resolution_clock; + auto t0 = clock::now(); + + // Validate input shapes and sizes. + TORCH_CHECK(vectors.dim() == 2, "Input 'vectors' must be a 2D tensor"); + TORCH_CHECK(ids.dim() == 1 || (ids.dim() == 2 && ids.size(1) == 1), + "Input 'ids' must be a 1D tensor or 2D with shape (N,1)"); + TORCH_CHECK(vectors.size(0) == ids.size(0), "Number of ids must match number of vectors"); + TORCH_CHECK(vectors.size(0) >= num_clusters, "Number of clusters cannot exceed number of points"); + + // Move data and ids to GPU (if needed) and ensure contiguous memory. + torch::Tensor data = vectors.to(torch::kCUDA, torch::kFloat32).contiguous(); + torch::Tensor id_dev = ids.to(torch::kCUDA).contiguous(); + int64_t n_samples = data.size(0); + int64_t n_features = data.size(1); + + auto t1 = clock::now(); + std::cout << "[DEBUG] Data transfer & contiguity: " + << std::chrono::duration_cast(t1 - t0).count() << " ms" << std::endl; + + // If using inner-product (cosine), normalize input vectors. + if (metric == faiss::METRIC_INNER_PRODUCT) { + torch::Tensor norms = torch::sqrt((data * data).sum(1, /*keepdim=*/true)); + data = data / norms; + } + + auto t2 = clock::now(); + std::cout << "[DEBUG] Data normalization: " + << std::chrono::duration_cast(t2 - t1).count() << " ms" << std::endl; + + // RAFT handle and stream setup. + raft::resources handle; + cudaStream_t cuda_stream = at::cuda::getCurrentCUDAStream().stream(); + raft::resource::set_cuda_stream(handle, cuda_stream); + + auto t3 = clock::now(); + std::cout << "[DEBUG] RAFT handle & stream setup: " + << std::chrono::duration_cast(t3 - t2).count() << " ms" << std::endl; + + // Wrap the input data in a RAFT device_matrix_view. + float* data_ptr = data.data_ptr(); + auto X_view = raft::make_device_matrix_view(data_ptr, (int)n_samples, (int)n_features); + + // Allocate output centroids on GPU. + torch::Tensor centroids_tensor = torch::empty({num_clusters, n_features}, + torch::TensorOptions().dtype(torch::kFloat32).device(torch::kCUDA)); + float* centroids_ptr = centroids_tensor.data_ptr(); + auto centroids_view = raft::make_device_matrix_view(centroids_ptr, (int)num_clusters, (int)n_features); + + auto t4 = clock::now(); + std::cout << "[DEBUG] Memory allocation for centroids & data wrapping: " + << std::chrono::duration_cast(t4 - t3).count() << " ms" << std::endl; + + // Set up k-means parameters. + cuvs::cluster::kmeans::params params; + params.n_clusters = (int)num_clusters; + params.max_iter = 5; + params.init = cuvs::cluster::kmeans::params::InitMethod::Random; + + // Prepare host-side scalars to capture inertia and iterations. + float inertia = 0.0f; + int iterations = 0; + auto inertia_view = raft::make_host_scalar_view(&inertia); + auto iter_view = raft::make_host_scalar_view(&iterations); + + // Run k-means clustering (fit). + cuvs::cluster::kmeans::fit(handle, params, X_view, std::nullopt, + centroids_view, inertia_view, iter_view); + + auto t5 = clock::now(); + std::cout << "[DEBUG] cuVS fit (k-means clustering): " + << std::chrono::duration_cast(t5 - t4).count() << " ms" << std::endl; + + // If inner-product, renormalize centroids. + if (metric == faiss::METRIC_INNER_PRODUCT) { + torch::Tensor cent_norms = torch::sqrt((centroids_tensor * centroids_tensor).sum(1, /*keepdim=*/true)); + centroids_tensor.div_(cent_norms); + } + + auto t6 = clock::now(); + std::cout << "[DEBUG] Centroid renormalization (if applicable): " + << std::chrono::duration_cast(t6 - t5).count() << " ms" << std::endl; + + // Allocate memory for labels and run prediction. + torch::Tensor labels = torch::empty({n_samples}, torch::TensorOptions().dtype(torch::kInt32).device(torch::kCUDA)); + int* labels_ptr = labels.data_ptr(); + auto labels_view = raft::make_device_vector_view(labels_ptr, (int)n_samples); + + cuvs::cluster::kmeans::predict(handle, params, X_view, std::nullopt, + centroids_view, labels_view, false, + raft::make_host_scalar_view(&inertia)); + + auto t7 = clock::now(); + std::cout << "[DEBUG] cuVS predict: " + << std::chrono::duration_cast(t7 - t6).count() << " ms" << std::endl; + + // Synchronize the stream. + raft::resource::sync_stream(handle); + auto t8 = clock::now(); + std::cout << "[DEBUG] CUDA stream synchronization: " + << std::chrono::duration_cast(t8 - t7).count() << " ms" << std::endl; + + // ----- Grouping (GPU vectorized) ----- + // Sort the labels and get the sorted indices. + torch::Tensor sorted_tuple = std::get<1>(torch::sort(labels)); // sorted indices only, since sorted labels are not needed + torch::Tensor sorted_labels = labels.index_select(0, sorted_tuple); + + // Reorder the data and ids using the sorted indices. + torch::Tensor sorted_data = data.index_select(0, sorted_tuple); + torch::Tensor sorted_ids = id_dev.index_select(0, sorted_tuple); + + // Compute per-cluster counts using torch::bincount. + torch::Tensor counts = torch::bincount(sorted_labels.to(torch::kInt64), /*weights=*/{}, num_clusters); + + // Transfer counts to CPU and build a vector for split sizes. + auto counts_cpu = counts.to(torch::kCPU); + std::vector split_sizes(counts_cpu.data_ptr(), counts_cpu.data_ptr() + counts_cpu.numel()); + + auto t9 = clock::now(); + std::cout << "[DEBUG] Sorting, counting, and preparing split sizes: " + << std::chrono::duration_cast(t9 - t8).count() << " ms" << std::endl; + + // Split the sorted data and ids into clusters. + std::vector cluster_vectors = torch::split(sorted_data, split_sizes, 0); + std::vector cluster_ids = torch::split(sorted_ids, split_sizes, 0); + + auto t10 = clock::now(); + std::cout << "[DEBUG] Splitting into clusters: " + << std::chrono::duration_cast(t10 - t9).count() << " ms" << std::endl; + + // Build the final clustering result. + std::vector> clusters; + clusters.reserve(num_clusters); + for (int i = 0; i < num_clusters; ++i) { + clusters.emplace_back(cluster_vectors[i], cluster_ids[i]); + } + + auto t_end = clock::now(); + std::cout << "[DEBUG] Total grouping time: " + << std::chrono::duration_cast(t_end - t8).count() << " ms" << std::endl; + + ClusteringResult result; + result.centroids = centroids_tensor; // Shape: (num_clusters, n_features) + result.clusters = std::move(clusters); + + std::cout << "[DEBUG] Total cuVS clustering time: " + << std::chrono::duration_cast(t_end - t0).count() << " ms" << std::endl; + + return result; +} diff --git a/src/cpp/third_party/cmake/fetch_rapids.cmake b/src/cpp/third_party/cmake/fetch_rapids.cmake new file mode 100644 index 00000000..0ec5fa04 --- /dev/null +++ b/src/cpp/third_party/cmake/fetch_rapids.cmake @@ -0,0 +1,22 @@ +# ============================================================================= +# Copyright (c) 2023-2024, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed under the License +# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +# or implied. See the License for the specific language governing permissions and limitations under +# the License. + +# Use this variable to update RAPIDS and cuVS versions +set(RAPIDS_VERSION "25.06") +set(rapids-cmake-version ${RAPIDS_VERSION}) + +if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/CUVS_RAPIDS.cmake) + file(DOWNLOAD https://raw.githubusercontent.com/rapidsai/rapids-cmake/branch-${RAPIDS_VERSION}/RAPIDS.cmake + ${CMAKE_CURRENT_BINARY_DIR}/CUVS_RAPIDS.cmake) +endif() +include(${CMAKE_CURRENT_BINARY_DIR}/CUVS_RAPIDS.cmake) diff --git a/src/cpp/third_party/cmake/get_cuvs.cmake b/src/cpp/third_party/cmake/get_cuvs.cmake new file mode 100644 index 00000000..a2a4e884 --- /dev/null +++ b/src/cpp/third_party/cmake/get_cuvs.cmake @@ -0,0 +1,56 @@ +# ============================================================================= +# Copyright (c) 2023-2024, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed under the License +# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +# or implied. See the License for the specific language governing permissions and limitations under +# the License. + +# Use RAPIDS_VERSION from cmake/thirdparty/fetch_rapids.cmake +set(CUVS_VERSION "${RAPIDS_VERSION}") +set(CUVS_FORK "rapidsai") +set(CUVS_PINNED_TAG "branch-${RAPIDS_VERSION}") + +function(find_and_configure_cuvs) + set(oneValueArgs VERSION FORK PINNED_TAG ENABLE_NVTX BUILD_CUVS_C_LIBRARY) + cmake_parse_arguments(PKG "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN} ) + + + set(CUVS_COMPONENTS "") + if(PKG_BUILD_CUVS_C_LIBRARY) + string(APPEND CUVS_COMPONENTS " c_api") + endif() + #----------------------------------------------------- + # Invoke CPM find_package() + #----------------------------------------------------- + rapids_cpm_find(cuvs ${PKG_VERSION} + GLOBAL_TARGETS cuvs::cuvs + BUILD_EXPORT_SET cuvs-examples-exports + INSTALL_EXPORT_SET cuvs-examples-exports + COMPONENTS ${CUVS_COMPONENTS} + CPM_ARGS + GIT_REPOSITORY https://github.com/${PKG_FORK}/cuvs.git + GIT_TAG ${PKG_PINNED_TAG} + SOURCE_SUBDIR cpp + OPTIONS + "BUILD_C_LIBRARY ${PKG_BUILD_CUVS_C_LIBRARY}" + "BUILD_TESTS OFF" + "CUVS_NVTX ${PKG_ENABLE_NVTX}" + ) +endfunction() + +# Change pinned tag here to test a commit in CI +# To use a different CUVS locally, set the CMake variable +# CPM_cuvs_SOURCE=/path/to/local/cuvs +find_and_configure_cuvs(VERSION ${CUVS_VERSION}.00 + FORK ${CUVS_FORK} + PINNED_TAG ${CUVS_PINNED_TAG} + ENABLE_NVTX OFF + BUILD_CUVS_C_LIBRARY ${BUILD_CUVS_C_LIBRARY} +) diff --git a/test/cpp/test_clustering_benchmark.cpp b/test/cpp/test_clustering_benchmark.cpp new file mode 100644 index 00000000..733ca95f --- /dev/null +++ b/test/cpp/test_clustering_benchmark.cpp @@ -0,0 +1,79 @@ +// benchmark_clustering_gtest.cpp +// +// This Google Test benchmarks two clustering implementations: +// 1. FAISS-based CPU clustering (kmeans with use_gpu == false) +// 2. cuVS-based GPU clustering (ClusterWithCuVS) +// on a dataset of 4,000,000 vectors (of dimension 128) and 10,000 clusters. +// The test prints the elapsed time (milliseconds) for each method. + +#include +#include +#include +#include +#include "clustering.h" // Declaration of kmeans() and ClusterWithCuVS() +#include "cuv_cluster.h" + +using namespace std::chrono; + +TEST(ClusteringBenchmark, CPU_vs_cuVS) { + // Verify CUDA is available. + if (!torch::cuda::is_available()) { + GTEST_SKIP() << "CUDA is not available; skipping benchmark."; + } + + // Define benchmark parameters. + const int64_t num_vectors = 10000000; // 10 million vectors + const int64_t dim = 128; + const int num_clusters = 10000; + const int niter = 5; // number of clustering iterations + + std::cout << "Benchmarking clustering with " << num_vectors << " vectors, dimension " + << dim << ", and " << num_clusters << " clusters." << std::endl; + + // Create CPU tensors. + auto options_float_cpu = torch::TensorOptions().dtype(torch::kFloat32).device(torch::kCPU); + auto options_int64_cpu = torch::TensorOptions().dtype(torch::kInt64).device(torch::kCPU); + torch::Tensor vectors_cpu = torch::randn({num_vectors, dim}, options_float_cpu).contiguous(); + torch::Tensor ids_cpu = torch::arange(0, num_vectors, options_int64_cpu).contiguous(); + + // Create CUDA tensors. + auto options_float_cuda = torch::TensorOptions().dtype(torch::kFloat32).device(torch::kCUDA); + auto options_int64_cuda = torch::TensorOptions().dtype(torch::kInt64).device(torch::kCUDA); + torch::Tensor vectors_cuda = vectors_cpu.to(options_float_cuda).contiguous(); + torch::Tensor ids_cuda = ids_cpu.to(options_int64_cuda).contiguous(); + + // Warm up the GPU using the cuVS clustering (to remove initialization overhead). + std::cout << "[DEBUG] Warming up GPU with cuVS clustering..." << std::endl; + { + auto dummy = ClusterWithCuVS(vectors_cuda, ids_cuda, 10, faiss::METRIC_L2); + torch::cuda::synchronize(); + } + std::cout << "[DEBUG] Warm-up complete." << std::endl; + + // Benchmark FAISS CPU clustering. + std::cout << "[DEBUG] Starting FAISS CPU clustering benchmark..." << std::endl; + auto start_cpu = high_resolution_clock::now(); + auto clustering_cpu = kmeans(vectors_cpu, ids_cpu, num_clusters, faiss::METRIC_L2, niter, false, torch::Tensor()); + auto end_cpu = high_resolution_clock::now(); + auto duration_cpu = duration_cast(end_cpu - start_cpu).count(); + std::cout << "FAISS CPU clustering time: " << duration_cpu << " ms" << std::endl; + + // Benchmark cuVS GPU clustering. + std::cout << "[DEBUG] Starting cuVS clustering benchmark..." << std::endl; + auto start_cuvs = high_resolution_clock::now(); + auto clustering_cuvs = ClusterWithCuVS(vectors_cuda, ids_cuda, num_clusters, faiss::METRIC_L2); + torch::cuda::synchronize(); // ensure GPU work is complete + auto end_cuvs = high_resolution_clock::now(); + auto duration_cuvs = duration_cast(end_cuvs - start_cuvs).count(); + std::cout << "cuVS clustering time: " << duration_cuvs << " ms" << std::endl; + + // Print summary. + std::cout << "---------------------------" << std::endl; + std::cout << "FAISS CPU clustering took " << duration_cpu << " ms." << std::endl; + std::cout << "cuVS clustering took " << duration_cuvs << " ms." << std::endl; + std::cout << "---------------------------" << std::endl; + + // Basic checks. + EXPECT_GT(duration_cpu, 0); + EXPECT_GT(duration_cuvs, 0); +} diff --git a/test/cpp/test_clustering_correctness.cpp b/test/cpp/test_clustering_correctness.cpp new file mode 100644 index 00000000..01fff623 --- /dev/null +++ b/test/cpp/test_clustering_correctness.cpp @@ -0,0 +1,157 @@ +// test_clustering_correctness.cpp +// +// This file tests the correctness of two clustering implementations: +// 1. FAISS-based clustering on CPU: kmeans(..., use_gpu = false) +// 2. cuVS-based clustering: ClusterWithCuVS(...) +// The tests compute the mean squared error (MSE) between each input vector and its +// corresponding cluster centroid and require that the MSE from the two methods +// agree within a reasonable tolerance. Additionally, the tests verify that each method +// returns centroids of the correct shape and partitions the input set completely. + +#include +#include +#include +#include +#include "clustering.h" // Declaration of kmeans(), ClusterWithCuVS(), Clustering, ClusteringResult, and MetricType + +// Helper to compute MSE for FAISS-based clustering results. +// The 'vectors' field of Clustering is a vector of tensors (one per cluster). +double ComputeMSE_Faiss(const torch::Tensor& centroids, const std::vector& cluster_vectors) { + double total_error = 0.0; + int64_t total_count = 0; + // Ensure centroids are on CPU. + torch::Tensor centroids_cpu = centroids.to(torch::kCPU); + for (int i = 0; i < centroids_cpu.size(0); ++i) { + if (cluster_vectors[i].size(0) > 0) { + // Move the cluster vectors to CPU. + torch::Tensor cluster_cpu = cluster_vectors[i].to(torch::kCPU); + torch::Tensor diff = cluster_cpu - centroids_cpu[i].unsqueeze(0); + total_error += diff.pow(2).sum().item(); + total_count += cluster_cpu.size(0); + } + } + return total_count > 0 ? total_error / total_count : 0.0; +} + +// Helper to compute MSE for cuVS-based clustering results. +// Here, clusters are returned as a vector of pairs where the first tensor is the cluster vectors. +double ComputeMSE_cuVS(const torch::Tensor& centroids, + const std::vector>& clusters) { + double total_error = 0.0; + int64_t total_count = 0; + torch::Tensor centroids_cpu = centroids.to(torch::kCPU); + for (int i = 0; i < centroids_cpu.size(0); ++i) { + const torch::Tensor& cluster_vectors = clusters[i].first; + if (cluster_vectors.size(0) > 0) { + torch::Tensor cluster_cpu = cluster_vectors.to(torch::kCPU); + torch::Tensor diff = cluster_cpu - centroids_cpu[i].unsqueeze(0); + total_error += diff.pow(2).sum().item(); + total_count += cluster_cpu.size(0); + } + } + return total_count > 0 ? total_error / total_count : 0.0; +} + +// Test fixture for clustering correctness tests. +class ClusteringCorrectnessTest : public ::testing::Test { + protected: + // Use a moderate number of vectors for correctness testing. + const int64_t num_vectors_ = 5000; + const int64_t dim_ = 64; + const int num_clusters_ = 20; + // CPU tensors. + torch::Tensor vectors_cpu_; + torch::Tensor ids_cpu_; + // CUDA tensors. + torch::Tensor vectors_cuda_; + torch::Tensor ids_cuda_; + + void SetUp() override { + if (!torch::cuda::is_available()) { + GTEST_SKIP() << "CUDA is not available; skipping clustering correctness tests."; + } + // Create CPU tensors. + auto options_float_cpu = torch::TensorOptions().dtype(torch::kFloat32).device(torch::kCPU); + auto options_int64_cpu = torch::TensorOptions().dtype(torch::kInt64).device(torch::kCPU); + vectors_cpu_ = torch::randn({num_vectors_, dim_}, options_float_cpu).contiguous(); + ids_cpu_ = torch::arange(0, num_vectors_, options_int64_cpu).contiguous(); + // Create CUDA versions. + auto options_float_cuda = torch::TensorOptions().dtype(torch::kFloat32).device(torch::kCUDA); + auto options_int64_cuda = torch::TensorOptions().dtype(torch::kInt64).device(torch::kCUDA); + vectors_cuda_ = vectors_cpu_.to(options_float_cuda).contiguous(); + ids_cuda_ = ids_cpu_.to(options_int64_cuda).contiguous(); + + std::cout << "[DEBUG] SetUp complete: " + << "num_vectors = " << num_vectors_ + << ", dim = " << dim_ + << ", clusters = " << num_clusters_ << std::endl; + std::cout.flush(); + } +}; + +TEST_F(ClusteringCorrectnessTest, CompareClusteringMethods_L2) { + const int niter = 20; // number of iterations for clustering + + std::cout << "[DEBUG] Starting FAISS CPU clustering ..." << std::endl; + std::cout.flush(); + auto clustering_cpu = kmeans(vectors_cpu_, ids_cpu_, num_clusters_, faiss::METRIC_L2, niter, false, torch::Tensor()); + std::cout << "[DEBUG] Completed FAISS CPU clustering." << std::endl; + std::cout << "[DEBUG] CPU centroids shape: "; + for (auto s : clustering_cpu->centroids.sizes()) { std::cout << s << " "; } + std::cout << std::endl; + std::cout.flush(); + + std::cout << "[DEBUG] Starting cuVS clustering ..." << std::endl; + std::cout.flush(); + ClusteringResult clustering_cuvs = ClusterWithCuVS(vectors_cuda_, ids_cuda_, num_clusters_, faiss::METRIC_L2); + std::cout << "[DEBUG] Completed cuVS clustering." << std::endl; + std::cout << "[DEBUG] cuVS centroids shape: "; + for (auto s : clustering_cuvs.centroids.sizes()) { std::cout << s << " "; } + std::cout << std::endl; + std::cout.flush(); + + // Compute MSE for each method. + double mse_cpu = ComputeMSE_Faiss(clustering_cpu->centroids, clustering_cpu->vectors); + double mse_cuvs = ComputeMSE_cuVS(clustering_cuvs.centroids, clustering_cuvs.clusters); + + std::cout << "[DEBUG] L2 Clustering MSEs:" << std::endl; + std::cout << " FAISS CPU: " << mse_cpu << std::endl; + std::cout << " cuVS : " << mse_cuvs << std::endl; + std::cout.flush(); + + // Assert that MSE values are similar (within 20% relative difference) + double tol = 0.20; + ASSERT_NEAR(mse_cpu, mse_cuvs, tol * mse_cpu); +} + +TEST_F(ClusteringCorrectnessTest, CompareClusteringMethods_InnerProduct) { + const int niter = 20; + std::cout << "[DEBUG] Starting FAISS CPU clustering (InnerProduct) ..." << std::endl; + std::cout.flush(); + auto clustering_cpu = kmeans(vectors_cpu_, ids_cpu_, num_clusters_, faiss::METRIC_INNER_PRODUCT, niter, false, torch::Tensor()); + std::cout << "[DEBUG] Completed FAISS CPU clustering (InnerProduct)." << std::endl; + std::cout << "[DEBUG] CPU centroids shape: "; + for (auto s : clustering_cpu->centroids.sizes()) { std::cout << s << " "; } + std::cout << std::endl; + std::cout.flush(); + + std::cout << "[DEBUG] Starting cuVS clustering (InnerProduct) ..." << std::endl; + std::cout.flush(); + ClusteringResult clustering_cuvs = ClusterWithCuVS(vectors_cuda_, ids_cuda_, num_clusters_, faiss::METRIC_INNER_PRODUCT); + std::cout << "[DEBUG] Completed cuVS clustering (InnerProduct)." << std::endl; + std::cout << "[DEBUG] cuVS centroids shape: "; + for (auto s : clustering_cuvs.centroids.sizes()) { std::cout << s << " "; } + std::cout << std::endl; + std::cout.flush(); + + double mse_cpu = ComputeMSE_Faiss(clustering_cpu->centroids, clustering_cpu->vectors); + double mse_cuvs = ComputeMSE_cuVS(clustering_cuvs.centroids, clustering_cuvs.clusters); + + std::cout << "[DEBUG] Inner-product Clustering MSEs:" << std::endl; + std::cout << " FAISS CPU: " << mse_cpu << std::endl; + std::cout << " cuVS : " << mse_cuvs << std::endl; + std::cout.flush(); + + double tol = 0.25; + ASSERT_NEAR(mse_cpu, mse_cuvs, tol * mse_cpu); +} diff --git a/test/cpp/test_cuvs_clustering.cpp b/test/cpp/test_cuvs_clustering.cpp new file mode 100644 index 00000000..394cf4e7 --- /dev/null +++ b/test/cpp/test_cuvs_clustering.cpp @@ -0,0 +1,88 @@ +// test_cuvs_clustering.cpp +// +// This file tests the cuVS-based k-means clustering implementation. +// It verifies that the centroids are computed correctly and that the +// entire dataset is partitioned among the clusters. + +#include +#include +#include "cuv_cluster.h" // Contains ClusterWithCuVS, ClusteringResult, and MetricType + +// Test that clustering with L2 metric produces the expected output shapes, +// and that every input vector is assigned to one and only one cluster. +TEST(CUVSClusteringTest, ClusteringL2) { + // Skip the test if CUDA is not available. + if (!torch::cuda::is_available()) { + GTEST_SKIP() << "CUDA is not available, skipping cuVS clustering test."; + } + + const int64_t num_vectors = 1000; + const int64_t dim = 32; + const int64_t num_clusters = 10; + + // Generate random data and corresponding sequential IDs on the GPU. + auto vectors = torch::randn({num_vectors, dim}, torch::kCUDA).to(torch::kFloat32).contiguous(); + auto ids = torch::arange(0, num_vectors, torch::kCUDA).contiguous(); + + // Call the cuVS-based clustering function using L2 metric. + ClusteringResult result = ClusterWithCuVS(vectors, ids, num_clusters, faiss::METRIC_L2); + + // Validate that the centroids tensor has shape [num_clusters, dim]. + ASSERT_EQ(result.centroids.dim(), 2); + ASSERT_EQ(result.centroids.size(0), num_clusters); + ASSERT_EQ(result.centroids.size(1), dim); + + // Verify that all input vectors are partitioned by summing counts from each cluster. + int64_t total_count = 0; + for (const auto& cluster : result.clusters) { + // Each cluster is returned as a pair: + torch::Tensor cluster_vectors = cluster.first; + torch::Tensor cluster_ids = cluster.second; + // The number of vectors in each cluster must match the number of IDs. + ASSERT_EQ(cluster_vectors.size(0), cluster_ids.size(0)); + total_count += cluster_vectors.size(0); + } + ASSERT_EQ(total_count, num_vectors); +} + +// Test that clustering with the inner product metric (which performs normalization) +// yields centroids that are unit-norm and partitions the dataset correctly. +TEST(CUVSClusteringTest, ClusteringInnerProduct) { + if (!torch::cuda::is_available()) { + GTEST_SKIP() << "CUDA is not available, skipping cuVS clustering test."; + } + + const int64_t num_vectors = 1000; + const int64_t dim = 64; + const int64_t num_clusters = 8; + + // Generate random input data and corresponding IDs. + auto vectors = torch::randn({num_vectors, dim}, torch::kCUDA).to(torch::kFloat32).contiguous(); + auto ids = torch::arange(0, num_vectors, torch::kCUDA).contiguous(); + + // Run clustering with inner product metric. The implementation should normalize the vectors. + ClusteringResult result = ClusterWithCuVS(vectors, ids, num_clusters, faiss::METRIC_INNER_PRODUCT); + + // Check that the centroids tensor has the expected shape. + ASSERT_EQ(result.centroids.dim(), 2); + ASSERT_EQ(result.centroids.size(0), num_clusters); + ASSERT_EQ(result.centroids.size(1), dim); + + // Optionally, validate that each centroid is normalized (i.e. its L2 norm is ~1) + auto cent_norms = result.centroids.norm(2, /*dim=*/1); + for (int64_t i = 0; i < cent_norms.size(0); ++i) { + float norm_val = cent_norms[i].item(); + // Allow a small numerical tolerance. + ASSERT_NEAR(norm_val, 1.0, 1e-3); + } + + // Confirm that the total number of vectors across all clusters is equal to the input size. + int64_t total_count = 0; + for (const auto& cluster : result.clusters) { + torch::Tensor cluster_vectors = cluster.first; + torch::Tensor cluster_ids = cluster.second; + ASSERT_EQ(cluster_vectors.size(0), cluster_ids.size(0)); + total_count += cluster_vectors.size(0); + } + ASSERT_EQ(total_count, num_vectors); +} From d68423fd1e53d63d1e1451f761a51618bade733c Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 16 Apr 2025 10:14:43 -0500 Subject: [PATCH 002/323] cleanup cuvs cmake and clustering --- CMakeLists.txt | 50 +++++------ src/cpp/include/clustering.h | 45 +++++++++- src/cpp/include/common.h | 8 -- src/cpp/include/cuv_cluster.h | 160 ---------------------------------- src/cpp/src/clustering.cpp | 147 ++++++++++++++++++++++++++----- 5 files changed, 193 insertions(+), 217 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a337eb9d..4cf50474 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,18 +12,6 @@ set(Torch_USE_CUDA OFF CACHE BOOL "Force disable CUDA in Torch") set(Torch_NO_CUDA ON CACHE BOOL "Force disable CUDA in Torch") set(USE_CUDA OFF CACHE BOOL "Force disable CUDA globally") -# QUAKE_ENABLE_GPU: Enable GPU support for Faiss -# Default: OFF -if(QUAKE_ENABLE_GPU) - set(FAISS_ENABLE_GPU ON) -else() - set(FAISS_ENABLE_GPU OFF) -endif() - -if(QUAKE_ENABLE_GPU) - add_compile_definitions(FAISS_ENABLE_GPU) -endif() - if(QUAKE_USE_NUMA) add_compile_definitions(QUAKE_USE_NUMA) endif() @@ -64,6 +52,24 @@ set(project_BINDINGS_DIR ${CPP_SOURCE}/bindings) set(project_THIRD_PARTY_DIR ${CPP_SOURCE}/third_party) set(project_TEST_DIR test/cpp) +if(QUAKE_ENABLE_GPU) + find_package(CuVS REQUIRED) + include(${project_THIRD_PARTY_DIR}cmake/fetch_rapids.cmake) + include(rapids-cmake) + include(rapids-cpm) + include(rapids-cuda) + include(rapids-export) + include(rapids-find) + + rapids_cuda_init_architectures(quake_c) + + rapids_cpm_init() + set(BUILD_CUVS_C_LIBRARY OFF) + include(${project_THIRD_PARTY_DIR}/cmake/get_cuvs.cmake) + + add_compile_definitions(QUAKE_ENABLE_GPU) +endif() + # --------------------------------------------------------------- # Print out Compiler and Path Information # --------------------------------------------------------------- @@ -96,25 +102,10 @@ endif() # --------------------------------------------------------------- # Find Required Packages # --------------------------------------------------------------- -find_package(CuVS REQUIRED) find_package(Torch REQUIRED) find_package(Python3 COMPONENTS Development Interpreter REQUIRED) find_package(Python COMPONENTS Interpreter Development REQUIRED) -include(src/cpp/third_party/cmake/fetch_rapids.cmake) -include(rapids-cmake) -include(rapids-cpm) -include(rapids-cuda) -include(rapids-export) -include(rapids-find) - -rapids_cuda_init_architectures(quake_c) - -rapids_cpm_init() -set(BUILD_CUVS_C_LIBRARY OFF) -include(src/cpp/third_party/cmake/get_cuvs.cmake) - - message(STATUS "Torch include dir: ${TORCH_INCLUDE_DIRS}") message(STATUS "Torch libraries: ${TORCH_LIBRARIES}") message(STATUS "Python include dir: ${Python3_INCLUDE_DIRS}") @@ -146,7 +137,6 @@ target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17) # Base libraries common to all platforms set(LINK_LIBS ${TORCH_LIBRARIES} - cuvs::cuvs -ffast-math -lpthread -fPIC @@ -165,6 +155,10 @@ elseif(UNIX) if(QUAKE_USE_NUMA) list(APPEND LINK_LIBS -lnuma) endif() + + if (QUAKE_ENABLE_GPU) + list(APPEND LINK_LIBS cuvs::cuvs) + endif() else() # unsupported platform message(FATAL_ERROR "Unsupported platform") diff --git a/src/cpp/include/clustering.h b/src/cpp/include/clustering.h index e4b00229..cc98bebc 100644 --- a/src/cpp/include/clustering.h +++ b/src/cpp/include/clustering.h @@ -9,12 +9,55 @@ #include +#ifdef QUAKE_ENABLE_GPU +#include // RAFT resources (handle) +#include // RAFT device view (make_device_matrix_view, etc.) +#include // cuVS k-means API +#endif + class IndexPartition; +/** + * @brief Clusters vectors into partitions using faiss::Clustering + * + * + * @param vectors The vectors to cluster. + * @param ids The IDs of the vectors. + * @param n_clusters The number of clusters to create. + * @param metric_type The metric type to use for clustering. + * @param niter The number of iterations to run k-means. + * @param initial_centroids The initial centroids to use for k-means. + */ +shared_ptr kmeans_cpu(Tensor vectors, + Tensor ids, + int n_clusters, + MetricType metric_type, + int niter = 5, + Tensor initial_centroids = Tensor()); + +/** + * @brief Clusters vectors into partitions using CuVS k-means. + * + * + * @param vectors The vectors to cluster. + * @param ids The IDs of the vectors. + * @param n_clusters The number of clusters to create. + * @param metric_type The metric type to use for clustering. + * @param niter The number of iterations to run k-means. + * @param initial_centroids The initial centroids to use for k-means. + */ +#ifdef QUAKE_ENABLE_GPU +shared_ptr kmeans_cuvs(Tensor vectors, + Tensor ids, + int n_clusters, + MetricType metric_type, + int niter = 5, + Tensor initial_centroids = Tensor()); +#endif + /** * @brief Clusters vectors into partitions using k-means. * - * Uses the faiss::Clustering class to cluster vectors into n_clusters partitions. * * @param vectors The vectors to cluster. * @param ids The IDs of the vectors. diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index 0938591c..ff95b2a2 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -38,14 +38,6 @@ #include #endif -#ifdef FAISS_ENABLE_GPU -#include -#include -#include -#include -#include -#endif - using torch::Tensor; using std::vector; using std::unordered_map; diff --git a/src/cpp/include/cuv_cluster.h b/src/cpp/include/cuv_cluster.h index 6e2ab9b4..32fe9315 100644 --- a/src/cpp/include/cuv_cluster.h +++ b/src/cpp/include/cuv_cluster.h @@ -1,15 +1,3 @@ -#include -#include // For at::cuda::getCurrentCUDAStream() -#include // RAFT resources (handle) -#include // RAFT device view (make_device_matrix_view, etc.) -#include // cuVS k-means API - -#include -#include -#include -#include -#include - // Optionally, if you have your own enum, you can use that instead of faiss::METRIC_L2/INNER_PRODUCT. struct ClusteringResult { torch::Tensor centroids; @@ -22,153 +10,5 @@ inline ClusteringResult ClusterWithCuVS(const torch::Tensor& vectors, const torch::Tensor& ids, int64_t num_clusters, int metric = faiss::METRIC_L2) { - using clock = std::chrono::high_resolution_clock; - auto t0 = clock::now(); - - // Validate input shapes and sizes. - TORCH_CHECK(vectors.dim() == 2, "Input 'vectors' must be a 2D tensor"); - TORCH_CHECK(ids.dim() == 1 || (ids.dim() == 2 && ids.size(1) == 1), - "Input 'ids' must be a 1D tensor or 2D with shape (N,1)"); - TORCH_CHECK(vectors.size(0) == ids.size(0), "Number of ids must match number of vectors"); - TORCH_CHECK(vectors.size(0) >= num_clusters, "Number of clusters cannot exceed number of points"); - - // Move data and ids to GPU (if needed) and ensure contiguous memory. - torch::Tensor data = vectors.to(torch::kCUDA, torch::kFloat32).contiguous(); - torch::Tensor id_dev = ids.to(torch::kCUDA).contiguous(); - int64_t n_samples = data.size(0); - int64_t n_features = data.size(1); - - auto t1 = clock::now(); - std::cout << "[DEBUG] Data transfer & contiguity: " - << std::chrono::duration_cast(t1 - t0).count() << " ms" << std::endl; - - // If using inner-product (cosine), normalize input vectors. - if (metric == faiss::METRIC_INNER_PRODUCT) { - torch::Tensor norms = torch::sqrt((data * data).sum(1, /*keepdim=*/true)); - data = data / norms; - } - - auto t2 = clock::now(); - std::cout << "[DEBUG] Data normalization: " - << std::chrono::duration_cast(t2 - t1).count() << " ms" << std::endl; - - // RAFT handle and stream setup. - raft::resources handle; - cudaStream_t cuda_stream = at::cuda::getCurrentCUDAStream().stream(); - raft::resource::set_cuda_stream(handle, cuda_stream); - - auto t3 = clock::now(); - std::cout << "[DEBUG] RAFT handle & stream setup: " - << std::chrono::duration_cast(t3 - t2).count() << " ms" << std::endl; - - // Wrap the input data in a RAFT device_matrix_view. - float* data_ptr = data.data_ptr(); - auto X_view = raft::make_device_matrix_view(data_ptr, (int)n_samples, (int)n_features); - - // Allocate output centroids on GPU. - torch::Tensor centroids_tensor = torch::empty({num_clusters, n_features}, - torch::TensorOptions().dtype(torch::kFloat32).device(torch::kCUDA)); - float* centroids_ptr = centroids_tensor.data_ptr(); - auto centroids_view = raft::make_device_matrix_view(centroids_ptr, (int)num_clusters, (int)n_features); - - auto t4 = clock::now(); - std::cout << "[DEBUG] Memory allocation for centroids & data wrapping: " - << std::chrono::duration_cast(t4 - t3).count() << " ms" << std::endl; - - // Set up k-means parameters. - cuvs::cluster::kmeans::params params; - params.n_clusters = (int)num_clusters; - params.max_iter = 5; - params.init = cuvs::cluster::kmeans::params::InitMethod::Random; - // Prepare host-side scalars to capture inertia and iterations. - float inertia = 0.0f; - int iterations = 0; - auto inertia_view = raft::make_host_scalar_view(&inertia); - auto iter_view = raft::make_host_scalar_view(&iterations); - - // Run k-means clustering (fit). - cuvs::cluster::kmeans::fit(handle, params, X_view, std::nullopt, - centroids_view, inertia_view, iter_view); - - auto t5 = clock::now(); - std::cout << "[DEBUG] cuVS fit (k-means clustering): " - << std::chrono::duration_cast(t5 - t4).count() << " ms" << std::endl; - - // If inner-product, renormalize centroids. - if (metric == faiss::METRIC_INNER_PRODUCT) { - torch::Tensor cent_norms = torch::sqrt((centroids_tensor * centroids_tensor).sum(1, /*keepdim=*/true)); - centroids_tensor.div_(cent_norms); - } - - auto t6 = clock::now(); - std::cout << "[DEBUG] Centroid renormalization (if applicable): " - << std::chrono::duration_cast(t6 - t5).count() << " ms" << std::endl; - - // Allocate memory for labels and run prediction. - torch::Tensor labels = torch::empty({n_samples}, torch::TensorOptions().dtype(torch::kInt32).device(torch::kCUDA)); - int* labels_ptr = labels.data_ptr(); - auto labels_view = raft::make_device_vector_view(labels_ptr, (int)n_samples); - - cuvs::cluster::kmeans::predict(handle, params, X_view, std::nullopt, - centroids_view, labels_view, false, - raft::make_host_scalar_view(&inertia)); - - auto t7 = clock::now(); - std::cout << "[DEBUG] cuVS predict: " - << std::chrono::duration_cast(t7 - t6).count() << " ms" << std::endl; - - // Synchronize the stream. - raft::resource::sync_stream(handle); - auto t8 = clock::now(); - std::cout << "[DEBUG] CUDA stream synchronization: " - << std::chrono::duration_cast(t8 - t7).count() << " ms" << std::endl; - - // ----- Grouping (GPU vectorized) ----- - // Sort the labels and get the sorted indices. - torch::Tensor sorted_tuple = std::get<1>(torch::sort(labels)); // sorted indices only, since sorted labels are not needed - torch::Tensor sorted_labels = labels.index_select(0, sorted_tuple); - - // Reorder the data and ids using the sorted indices. - torch::Tensor sorted_data = data.index_select(0, sorted_tuple); - torch::Tensor sorted_ids = id_dev.index_select(0, sorted_tuple); - - // Compute per-cluster counts using torch::bincount. - torch::Tensor counts = torch::bincount(sorted_labels.to(torch::kInt64), /*weights=*/{}, num_clusters); - - // Transfer counts to CPU and build a vector for split sizes. - auto counts_cpu = counts.to(torch::kCPU); - std::vector split_sizes(counts_cpu.data_ptr(), counts_cpu.data_ptr() + counts_cpu.numel()); - - auto t9 = clock::now(); - std::cout << "[DEBUG] Sorting, counting, and preparing split sizes: " - << std::chrono::duration_cast(t9 - t8).count() << " ms" << std::endl; - - // Split the sorted data and ids into clusters. - std::vector cluster_vectors = torch::split(sorted_data, split_sizes, 0); - std::vector cluster_ids = torch::split(sorted_ids, split_sizes, 0); - - auto t10 = clock::now(); - std::cout << "[DEBUG] Splitting into clusters: " - << std::chrono::duration_cast(t10 - t9).count() << " ms" << std::endl; - - // Build the final clustering result. - std::vector> clusters; - clusters.reserve(num_clusters); - for (int i = 0; i < num_clusters; ++i) { - clusters.emplace_back(cluster_vectors[i], cluster_ids[i]); - } - - auto t_end = clock::now(); - std::cout << "[DEBUG] Total grouping time: " - << std::chrono::duration_cast(t_end - t8).count() << " ms" << std::endl; - - ClusteringResult result; - result.centroids = centroids_tensor; // Shape: (num_clusters, n_features) - result.clusters = std::move(clusters); - - std::cout << "[DEBUG] Total cuVS clustering time: " - << std::chrono::duration_cast(t_end - t0).count() << " ms" << std::endl; - - return result; } diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index ebbc88e0..50052a72 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -10,12 +10,115 @@ #include "index_partition.h" #include -shared_ptr kmeans(Tensor vectors, +#ifdef QUAKE_ENABLE_GPU +shared_ptr kmeans_cuvs(Tensor vectors, + Tensor ids, + int num_clusters, + MetricType metric, + int niter, + Tensor initial_centroids) { + // Validate input shapes and sizes. + TORCH_CHECK(vectors.dim() == 2, "Input 'vectors' must be a 2D tensor"); + TORCH_CHECK(ids.dim() == 1 || (ids.dim() == 2 && ids.size(1) == 1), + "Input 'ids' must be a 1D tensor or 2D with shape (N,1)"); + TORCH_CHECK(vectors.size(0) == ids.size(0), "Number of ids must match number of vectors"); + TORCH_CHECK(vectors.size(0) >= num_clusters, "Number of clusters cannot exceed number of points"); + + int64_t n_samples = data.size(0); + int64_t n_features = data.size(1); + + // If using inner-product (cosine), normalize input vectors. + if (metric == faiss::METRIC_INNER_PRODUCT) { + Tensor norms = torch::sqrt((data * data).sum(1, /*keepdim=*/true)); + data = data / norms; + } + + // RAFT handle and stream setup. + raft::resources handle; + cudaStream_t cuda_stream = at::cuda::getCurrentCUDAStream().stream(); + raft::resource::set_cuda_stream(handle, cuda_stream); + + // Wrap the input data in a RAFT device_matrix_view. + float* data_ptr = data.data_ptr(); + auto X_view = raft::make_host_matrix_view(data_ptr, (int)n_samples, (int)n_features); + + // Allocate output centroids on GPU. + Tensor centroids_tensor = torch::empty({num_clusters, n_features}, + torch::TensorOptions().dtype(torch::kFloat32).device(torch::kCUDA)); + float* centroids_ptr = centroids_tensor.data_ptr(); + auto centroids_view = raft::make_device_matrix_view(centroids_ptr, (int)num_clusters, (int)n_features); + + // Set up k-means parameters. + cuvs::cluster::kmeans::params params; + params.n_clusters = (int)num_clusters; + params.max_iter = niter; + params.init = cuvs::cluster::kmeans::params::InitMethod::Random; + + // Prepare host-side scalars to capture inertia and iterations. + float inertia = 0.0f; + int iterations = 0; + auto inertia_view = raft::make_host_scalar_view(&inertia); + auto iter_view = raft::make_host_scalar_view(&iterations); + + // Run k-means clustering (fit). + cuvs::cluster::kmeans::fit(handle, params, X_view, std::nullopt, + centroids_view, inertia_view, iter_view); + + // If inner-product, renormalize centroids. + if (metric == faiss::METRIC_INNER_PRODUCT) { + Tensor cent_norms = torch::sqrt((centroids_tensor * centroids_tensor).sum(1, /*keepdim=*/true)); + centroids_tensor.div_(cent_norms); + } + + // Allocate memory for labels and run prediction. + Tensor labels = torch::empty({n_samples}, torch::TensorOptions().dtype(torch::kInt32).device(torch::kCUDA)); + int* labels_ptr = labels.data_ptr(); + auto labels_view = raft::make_device_vector_view(labels_ptr, (int)n_samples); + + cuvs::cluster::kmeans::predict(handle, params, X_view, std::nullopt, + centroids_view, labels_view, false, + raft::make_host_scalar_view(&inertia)); + + // Synchronize the stream. + raft::resource::sync_stream(handle); + + // ----- Grouping (GPU vectorized) ----- + // Sort the labels and get the sorted indices. + Tensor sorted_tuple = std::get<1>(torch::sort(labels)); // sorted indices only, since sorted labels are not needed + Tensor sorted_labels = labels.index_select(0, sorted_tuple); + + // Reorder the data and ids using the sorted indices. + Tensor sorted_data = data.index_select(0, sorted_tuple); + Tensor sorted_ids = id_dev.index_select(0, sorted_tuple); + + // Compute per-cluster counts using torch::bincount. + Tensor counts = torch::bincount(sorted_labels.to(torch::kInt64), /*weights=*/{}, num_clusters); + + // Transfer counts to CPU and build a vector for split sizes. + auto counts_cpu = counts.to(torch::kCPU); + std::vector split_sizes(counts_cpu.data_ptr(), counts_cpu.data_ptr() + counts_cpu.numel()); + + // Split the sorted data and ids into clusters. + vector cluster_vectors = torch::split(sorted_data, split_sizes, 0); + vector cluster_ids = torch::split(sorted_ids, split_sizes, 0); + + Tensor partition_ids = torch::arange(num_clusters, torch::kInt64); + + shared_ptr clustering = std::make_shared(); + clustering->centroids = centroids_tensor; + clustering->partition_ids = partition_ids; + clustering->vectors = cluster_vectors; + clustering->vector_ids = cluster_ids; + + return clustering; +} +#endif + +shared_ptr kmeans_cpu(Tensor vectors, Tensor ids, int n_clusters, MetricType metric_type, int niter, - bool use_gpu /*=false*/, Tensor /* initial_centroids */) { // Ensure enough vectors are available and sizes match. assert(vectors.size(0) >= n_clusters * 2); @@ -29,24 +132,10 @@ shared_ptr kmeans(Tensor vectors, int d = vectors.size(1); faiss::Index* index_ptr = nullptr; - - if (use_gpu) { - // Check if GPU resources are available. - #ifdef FAISS_ENABLE_GPU - faiss::gpu::StandardGpuResources gpu_res; - if (metric_type == faiss::METRIC_INNER_PRODUCT) - index_ptr = new faiss::gpu::GpuIndexFlatIP(&gpu_res, d); - else - index_ptr = new faiss::gpu::GpuIndexFlatL2(&gpu_res, d); - #else - throw std::runtime_error("GPU resources are not available. Please compile with FAISS_ENABLE_GPU."); - #endif - } else { - if (metric_type == faiss::METRIC_INNER_PRODUCT) - index_ptr = new faiss::IndexFlatIP(d); - else - index_ptr = new faiss::IndexFlatL2(d); - } + if (metric_type == faiss::METRIC_INNER_PRODUCT) + index_ptr = new faiss::IndexFlatIP(d); + else + index_ptr = new faiss::IndexFlatL2(d); faiss::ClusteringParameters cp; cp.niter = niter; @@ -96,6 +185,24 @@ shared_ptr kmeans(Tensor vectors, return clustering; } +shared_ptr kmeans(Tensor vectors, + Tensor ids, + int n_clusters, + MetricType metric_type, + int niter, + bool use_gpu /*=false*/, + Tensor /* initial_centroids */) { + if (use_gpu) { + #ifdef QUAKE_ENABLE_GPU + return kmeans_cuvs(vectors, ids, n_clusters, metric_type, niter); + #elif + throw std::runtime_error("GPU support is not enabled. Please compile with QUAKE_ENABLE_GPU."); + #endif + } else { + return kmeans_cpu(vectors, ids, n_clusters, metric_type, niter); + } +} + tuple >> kmeans_refine_partitions( Tensor centroids, vector> partitions, From 8bb1929185d72b3e467b60b0b08430d60ac3829a Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 16 Apr 2025 11:21:42 -0500 Subject: [PATCH 003/323] add clustering tests --- test/cpp/clustering.cpp | 179 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 test/cpp/clustering.cpp diff --git a/test/cpp/clustering.cpp b/test/cpp/clustering.cpp new file mode 100644 index 00000000..9c0b76c3 --- /dev/null +++ b/test/cpp/clustering.cpp @@ -0,0 +1,179 @@ +#include +#include +#include "clustering.h" +#include + +// Helper functions to generate random test data. +static Tensor generate_random_data(int64_t num_vectors, int64_t dim) { + return torch::randn({num_vectors, dim}, torch::kFloat32).contiguous(); +} + +static Tensor generate_sequential_ids(int64_t count, int64_t start = 0) { + return torch::arange(start, start + count, torch::kInt64).contiguous(); +} + +// Helpers to compute mean squared error (MSE) for clustering. +// For FAISS-based clustering: 'vectors' is a vector of tensors (one per cluster). +static double compute_mse(const Tensor& centroids, + const std::vector& clusters) { + double total_error = 0.0; + int64_t total_count = 0; + auto centroids_cpu = centroids.to(torch::kCPU); + for (size_t i = 0; i < clusters.size(); ++i) { + if (clusters[i].size(0) > 0) { + auto cluster = clusters[i].to(torch::kCPU); + auto diff = cluster - centroids_cpu[i].unsqueeze(0); + total_error += diff.pow(2).sum().item(); + total_count += cluster.size(0); + } + } + return total_count > 0 ? total_error / total_count : 0.0; +} + +// Test fixture for clustering tests. +class ClusteringTest : public ::testing::Test { + protected: + const int64_t num_vectors = 5000; + const int64_t dim = 64; + const int num_clusters = 20; + Tensor vectors_cpu, ids_cpu; + Tensor vectors_cuda, ids_cuda; + + void SetUp() override { + // Skip these tests if CUDA is not available. + if (!torch::cuda::is_available()) { + GTEST_SKIP() << "CUDA is not available; skipping clustering tests."; + } + vectors_cpu = generate_random_data(num_vectors, dim); + ids_cpu = generate_sequential_ids(num_vectors); +#ifdef QUAKE_ENABLE_GPU + vectors_cuda = vectors_cpu.to(torch::kCUDA).contiguous(); + ids_cuda = ids_cpu.to(torch::kCUDA).contiguous(); +#endif + } +}; + +// Compare clustering methods using the L2 (Euclidean) metric. +#ifdef QUAKE_ENABLE_GPU +TEST_F(ClusteringTest, CompareClustering_L2) { + const int niter = 20; + // FAISS-based clustering on CPU. + auto clustering_cpu = kmeans_cpu(vectors_cpu, ids_cpu, num_clusters, faiss::METRIC_L2, niter, Tensor()); + // cuVS-based clustering on GPU. + auto clustering_cuvs = kmeans_cuvs(vectors_cuda, ids_cuda, num_clusters, faiss::METRIC_L2); + + // Verify centroid shapes. + ASSERT_EQ(clustering_cpu->centroids.dim(), 2); + ASSERT_EQ(clustering_cpu->centroids.size(0), num_clusters); + ASSERT_EQ(clustering_cpu->centroids.size(1), dim); + ASSERT_EQ(clustering_cuvs->centroids.dim(), 2); + ASSERT_EQ(clustering_cuvs->centroids.size(0), num_clusters); + ASSERT_EQ(clustering_cuvs->centroids.size(1), dim); + + // Compare the mean squared errors (MSEs) between the methods. + double mse_cpu = compute_mse(clustering_cpu->centroids, clustering_cpu->vectors); + double mse_cuvs = compute_mse(clustering_cuvs->centroids, clustering_cuvs->vectors); + // They should agree within roughly 20% relative difference. + ASSERT_NEAR(mse_cpu, mse_cuvs, mse_cpu * 0.20); +} + +// Compare clustering methods using the inner product metric. +TEST_F(ClusteringTest, CompareClustering_InnerProduct) { + const int niter = 20; + auto clustering_cpu = kmeans(vectors_cpu, ids_cpu, num_clusters, + faiss::METRIC_INNER_PRODUCT, niter, false, Tensor()); + auto clustering_cuvs = kmeans_cuvs(vectors_cuda, ids_cuda, num_clusters, faiss::METRIC_INNER_PRODUCT); + + // Verify centroid shapes. + ASSERT_EQ(clustering_cpu->centroids.dim(), 2); + ASSERT_EQ(clustering_cpu->centroids.size(0), num_clusters); + ASSERT_EQ(clustering_cpu->centroids.size(1), dim); + ASSERT_EQ(clustering_cuvs->centroids.dim(), 2); + ASSERT_EQ(clustering_cuvs->centroids.size(0), num_clusters); + ASSERT_EQ(clustering_cuvs->centroids.size(1), dim); + + // For inner product, check that cuVS centroids are normalized. + auto norms = clustering_cuvs->centroids.norm(2, 1); + for (int i = 0; i < norms.size(0); ++i) { + ASSERT_NEAR(norms[i].item(), 1.0f, 1e-3); + } + + double mse_cpu = compute_mse(clustering_cpu->centroids, clustering_cpu->vectors); + double mse_cuvs = compute_mse(clustering_cuvs->centroids, clustering_cuvs->vectors); + // Allow a bit larger relative difference for inner product. + ASSERT_NEAR(mse_cpu, mse_cuvs, mse_cpu * 0.25); +} + +// Test that cuVS clustering partitions all vectors correctly (L2 metric). +TEST_F(ClusteringTest, CUVSClustering_Partitioning_L2) { + auto result = kmeans_cuvs(vectors_cuda, ids_cuda, num_clusters, faiss::METRIC_L2); + ASSERT_EQ(result->centroids.dim(), 2); + ASSERT_EQ(result->centroids.size(0), num_clusters); + ASSERT_EQ(result->centroids.size(1), dim); + + int64_t total_vectors = 0; + for (int i = 0; i < num_clusters; ++i) { + auto cluster = result->vectors[i]; + ASSERT_EQ(cluster.size(0), result->vector_ids[i].size(0)); + total_vectors += cluster.size(0); + } + ASSERT_EQ(total_vectors, num_vectors); +} + + +// Test that cuVS clustering (inner product) produces unit-norm centroids and correctly partitions vectors. +TEST_F(ClusteringTest, CUVSClustering_Partitioning_InnerProduct) { + auto result = kmeans_cuvs(vectors_cuda, ids_cuda, num_clusters, faiss::METRIC_INNER_PRODUCT); + ASSERT_EQ(result->centroids.dim(), 2); + ASSERT_EQ(result->centroids.size(0), num_clusters); + ASSERT_EQ(result->centroids.size(1), dim); + + // Verify centroids are normalized. + auto norms = result->centroids.norm(2, 1); + for (int i = 0; i < norms.size(0); ++i) { + ASSERT_NEAR(norms[i].item(), 1.0f, 1e-3); + } + + int64_t total_vectors = 0; + for (int i = 0; i < num_clusters; ++i) { + auto cluster = result->vectors[i]; + ASSERT_EQ(cluster.size(0), result->vector_ids[i].size(0)); + total_vectors += cluster.size(0); + } + ASSERT_EQ(total_vectors, num_vectors); +} +#endif + +TEST_F(ClusteringTest, KMeansCPU_L2) { + // Test CPU-based k-means clustering. + int niter = 10; + auto clustering = kmeans_cpu(vectors_cpu, ids_cpu, num_clusters, faiss::METRIC_L2, niter); + ASSERT_EQ(clustering->centroids.dim(), 2); + ASSERT_EQ(clustering->centroids.size(0), num_clusters); + ASSERT_EQ(clustering->centroids.size(1), dim); + + int64_t total_vectors = 0; + for (int i = 0; i < num_clusters; ++i) { + auto cluster = clustering->vectors[i]; + ASSERT_EQ(cluster.size(0), clustering->vector_ids[i].size(0)); + total_vectors += cluster.size(0); + } + ASSERT_EQ(total_vectors, num_vectors); +} + +TEST_F(ClusteringTest, KMeansCPU_InnerProduct) { + // Test CPU-based k-means clustering with inner product metric. + int niter = 10; + auto clustering = kmeans_cpu(vectors_cpu, ids_cpu, num_clusters, faiss::METRIC_INNER_PRODUCT, niter); + ASSERT_EQ(clustering->centroids.dim(), 2); + ASSERT_EQ(clustering->centroids.size(0), num_clusters); + ASSERT_EQ(clustering->centroids.size(1), dim); + + int64_t total_vectors = 0; + for (int i = 0; i < num_clusters; ++i) { + auto cluster = clustering->vectors[i]; + ASSERT_EQ(cluster.size(0), clustering->vector_ids[i].size(0)); + total_vectors += cluster.size(0); + } + ASSERT_EQ(total_vectors, num_vectors); +} \ No newline at end of file From 13a316188e791effd07566f186074983b0d4a737 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 16 Apr 2025 11:21:54 -0500 Subject: [PATCH 004/323] remove old tests --- test/cpp/test_clustering_benchmark.cpp | 79 ------------ test/cpp/test_clustering_correctness.cpp | 157 ----------------------- test/cpp/test_cuvs_clustering.cpp | 88 ------------- 3 files changed, 324 deletions(-) delete mode 100644 test/cpp/test_clustering_benchmark.cpp delete mode 100644 test/cpp/test_clustering_correctness.cpp delete mode 100644 test/cpp/test_cuvs_clustering.cpp diff --git a/test/cpp/test_clustering_benchmark.cpp b/test/cpp/test_clustering_benchmark.cpp deleted file mode 100644 index 733ca95f..00000000 --- a/test/cpp/test_clustering_benchmark.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// benchmark_clustering_gtest.cpp -// -// This Google Test benchmarks two clustering implementations: -// 1. FAISS-based CPU clustering (kmeans with use_gpu == false) -// 2. cuVS-based GPU clustering (ClusterWithCuVS) -// on a dataset of 4,000,000 vectors (of dimension 128) and 10,000 clusters. -// The test prints the elapsed time (milliseconds) for each method. - -#include -#include -#include -#include -#include "clustering.h" // Declaration of kmeans() and ClusterWithCuVS() -#include "cuv_cluster.h" - -using namespace std::chrono; - -TEST(ClusteringBenchmark, CPU_vs_cuVS) { - // Verify CUDA is available. - if (!torch::cuda::is_available()) { - GTEST_SKIP() << "CUDA is not available; skipping benchmark."; - } - - // Define benchmark parameters. - const int64_t num_vectors = 10000000; // 10 million vectors - const int64_t dim = 128; - const int num_clusters = 10000; - const int niter = 5; // number of clustering iterations - - std::cout << "Benchmarking clustering with " << num_vectors << " vectors, dimension " - << dim << ", and " << num_clusters << " clusters." << std::endl; - - // Create CPU tensors. - auto options_float_cpu = torch::TensorOptions().dtype(torch::kFloat32).device(torch::kCPU); - auto options_int64_cpu = torch::TensorOptions().dtype(torch::kInt64).device(torch::kCPU); - torch::Tensor vectors_cpu = torch::randn({num_vectors, dim}, options_float_cpu).contiguous(); - torch::Tensor ids_cpu = torch::arange(0, num_vectors, options_int64_cpu).contiguous(); - - // Create CUDA tensors. - auto options_float_cuda = torch::TensorOptions().dtype(torch::kFloat32).device(torch::kCUDA); - auto options_int64_cuda = torch::TensorOptions().dtype(torch::kInt64).device(torch::kCUDA); - torch::Tensor vectors_cuda = vectors_cpu.to(options_float_cuda).contiguous(); - torch::Tensor ids_cuda = ids_cpu.to(options_int64_cuda).contiguous(); - - // Warm up the GPU using the cuVS clustering (to remove initialization overhead). - std::cout << "[DEBUG] Warming up GPU with cuVS clustering..." << std::endl; - { - auto dummy = ClusterWithCuVS(vectors_cuda, ids_cuda, 10, faiss::METRIC_L2); - torch::cuda::synchronize(); - } - std::cout << "[DEBUG] Warm-up complete." << std::endl; - - // Benchmark FAISS CPU clustering. - std::cout << "[DEBUG] Starting FAISS CPU clustering benchmark..." << std::endl; - auto start_cpu = high_resolution_clock::now(); - auto clustering_cpu = kmeans(vectors_cpu, ids_cpu, num_clusters, faiss::METRIC_L2, niter, false, torch::Tensor()); - auto end_cpu = high_resolution_clock::now(); - auto duration_cpu = duration_cast(end_cpu - start_cpu).count(); - std::cout << "FAISS CPU clustering time: " << duration_cpu << " ms" << std::endl; - - // Benchmark cuVS GPU clustering. - std::cout << "[DEBUG] Starting cuVS clustering benchmark..." << std::endl; - auto start_cuvs = high_resolution_clock::now(); - auto clustering_cuvs = ClusterWithCuVS(vectors_cuda, ids_cuda, num_clusters, faiss::METRIC_L2); - torch::cuda::synchronize(); // ensure GPU work is complete - auto end_cuvs = high_resolution_clock::now(); - auto duration_cuvs = duration_cast(end_cuvs - start_cuvs).count(); - std::cout << "cuVS clustering time: " << duration_cuvs << " ms" << std::endl; - - // Print summary. - std::cout << "---------------------------" << std::endl; - std::cout << "FAISS CPU clustering took " << duration_cpu << " ms." << std::endl; - std::cout << "cuVS clustering took " << duration_cuvs << " ms." << std::endl; - std::cout << "---------------------------" << std::endl; - - // Basic checks. - EXPECT_GT(duration_cpu, 0); - EXPECT_GT(duration_cuvs, 0); -} diff --git a/test/cpp/test_clustering_correctness.cpp b/test/cpp/test_clustering_correctness.cpp deleted file mode 100644 index 01fff623..00000000 --- a/test/cpp/test_clustering_correctness.cpp +++ /dev/null @@ -1,157 +0,0 @@ -// test_clustering_correctness.cpp -// -// This file tests the correctness of two clustering implementations: -// 1. FAISS-based clustering on CPU: kmeans(..., use_gpu = false) -// 2. cuVS-based clustering: ClusterWithCuVS(...) -// The tests compute the mean squared error (MSE) between each input vector and its -// corresponding cluster centroid and require that the MSE from the two methods -// agree within a reasonable tolerance. Additionally, the tests verify that each method -// returns centroids of the correct shape and partitions the input set completely. - -#include -#include -#include -#include -#include "clustering.h" // Declaration of kmeans(), ClusterWithCuVS(), Clustering, ClusteringResult, and MetricType - -// Helper to compute MSE for FAISS-based clustering results. -// The 'vectors' field of Clustering is a vector of tensors (one per cluster). -double ComputeMSE_Faiss(const torch::Tensor& centroids, const std::vector& cluster_vectors) { - double total_error = 0.0; - int64_t total_count = 0; - // Ensure centroids are on CPU. - torch::Tensor centroids_cpu = centroids.to(torch::kCPU); - for (int i = 0; i < centroids_cpu.size(0); ++i) { - if (cluster_vectors[i].size(0) > 0) { - // Move the cluster vectors to CPU. - torch::Tensor cluster_cpu = cluster_vectors[i].to(torch::kCPU); - torch::Tensor diff = cluster_cpu - centroids_cpu[i].unsqueeze(0); - total_error += diff.pow(2).sum().item(); - total_count += cluster_cpu.size(0); - } - } - return total_count > 0 ? total_error / total_count : 0.0; -} - -// Helper to compute MSE for cuVS-based clustering results. -// Here, clusters are returned as a vector of pairs where the first tensor is the cluster vectors. -double ComputeMSE_cuVS(const torch::Tensor& centroids, - const std::vector>& clusters) { - double total_error = 0.0; - int64_t total_count = 0; - torch::Tensor centroids_cpu = centroids.to(torch::kCPU); - for (int i = 0; i < centroids_cpu.size(0); ++i) { - const torch::Tensor& cluster_vectors = clusters[i].first; - if (cluster_vectors.size(0) > 0) { - torch::Tensor cluster_cpu = cluster_vectors.to(torch::kCPU); - torch::Tensor diff = cluster_cpu - centroids_cpu[i].unsqueeze(0); - total_error += diff.pow(2).sum().item(); - total_count += cluster_cpu.size(0); - } - } - return total_count > 0 ? total_error / total_count : 0.0; -} - -// Test fixture for clustering correctness tests. -class ClusteringCorrectnessTest : public ::testing::Test { - protected: - // Use a moderate number of vectors for correctness testing. - const int64_t num_vectors_ = 5000; - const int64_t dim_ = 64; - const int num_clusters_ = 20; - // CPU tensors. - torch::Tensor vectors_cpu_; - torch::Tensor ids_cpu_; - // CUDA tensors. - torch::Tensor vectors_cuda_; - torch::Tensor ids_cuda_; - - void SetUp() override { - if (!torch::cuda::is_available()) { - GTEST_SKIP() << "CUDA is not available; skipping clustering correctness tests."; - } - // Create CPU tensors. - auto options_float_cpu = torch::TensorOptions().dtype(torch::kFloat32).device(torch::kCPU); - auto options_int64_cpu = torch::TensorOptions().dtype(torch::kInt64).device(torch::kCPU); - vectors_cpu_ = torch::randn({num_vectors_, dim_}, options_float_cpu).contiguous(); - ids_cpu_ = torch::arange(0, num_vectors_, options_int64_cpu).contiguous(); - // Create CUDA versions. - auto options_float_cuda = torch::TensorOptions().dtype(torch::kFloat32).device(torch::kCUDA); - auto options_int64_cuda = torch::TensorOptions().dtype(torch::kInt64).device(torch::kCUDA); - vectors_cuda_ = vectors_cpu_.to(options_float_cuda).contiguous(); - ids_cuda_ = ids_cpu_.to(options_int64_cuda).contiguous(); - - std::cout << "[DEBUG] SetUp complete: " - << "num_vectors = " << num_vectors_ - << ", dim = " << dim_ - << ", clusters = " << num_clusters_ << std::endl; - std::cout.flush(); - } -}; - -TEST_F(ClusteringCorrectnessTest, CompareClusteringMethods_L2) { - const int niter = 20; // number of iterations for clustering - - std::cout << "[DEBUG] Starting FAISS CPU clustering ..." << std::endl; - std::cout.flush(); - auto clustering_cpu = kmeans(vectors_cpu_, ids_cpu_, num_clusters_, faiss::METRIC_L2, niter, false, torch::Tensor()); - std::cout << "[DEBUG] Completed FAISS CPU clustering." << std::endl; - std::cout << "[DEBUG] CPU centroids shape: "; - for (auto s : clustering_cpu->centroids.sizes()) { std::cout << s << " "; } - std::cout << std::endl; - std::cout.flush(); - - std::cout << "[DEBUG] Starting cuVS clustering ..." << std::endl; - std::cout.flush(); - ClusteringResult clustering_cuvs = ClusterWithCuVS(vectors_cuda_, ids_cuda_, num_clusters_, faiss::METRIC_L2); - std::cout << "[DEBUG] Completed cuVS clustering." << std::endl; - std::cout << "[DEBUG] cuVS centroids shape: "; - for (auto s : clustering_cuvs.centroids.sizes()) { std::cout << s << " "; } - std::cout << std::endl; - std::cout.flush(); - - // Compute MSE for each method. - double mse_cpu = ComputeMSE_Faiss(clustering_cpu->centroids, clustering_cpu->vectors); - double mse_cuvs = ComputeMSE_cuVS(clustering_cuvs.centroids, clustering_cuvs.clusters); - - std::cout << "[DEBUG] L2 Clustering MSEs:" << std::endl; - std::cout << " FAISS CPU: " << mse_cpu << std::endl; - std::cout << " cuVS : " << mse_cuvs << std::endl; - std::cout.flush(); - - // Assert that MSE values are similar (within 20% relative difference) - double tol = 0.20; - ASSERT_NEAR(mse_cpu, mse_cuvs, tol * mse_cpu); -} - -TEST_F(ClusteringCorrectnessTest, CompareClusteringMethods_InnerProduct) { - const int niter = 20; - std::cout << "[DEBUG] Starting FAISS CPU clustering (InnerProduct) ..." << std::endl; - std::cout.flush(); - auto clustering_cpu = kmeans(vectors_cpu_, ids_cpu_, num_clusters_, faiss::METRIC_INNER_PRODUCT, niter, false, torch::Tensor()); - std::cout << "[DEBUG] Completed FAISS CPU clustering (InnerProduct)." << std::endl; - std::cout << "[DEBUG] CPU centroids shape: "; - for (auto s : clustering_cpu->centroids.sizes()) { std::cout << s << " "; } - std::cout << std::endl; - std::cout.flush(); - - std::cout << "[DEBUG] Starting cuVS clustering (InnerProduct) ..." << std::endl; - std::cout.flush(); - ClusteringResult clustering_cuvs = ClusterWithCuVS(vectors_cuda_, ids_cuda_, num_clusters_, faiss::METRIC_INNER_PRODUCT); - std::cout << "[DEBUG] Completed cuVS clustering (InnerProduct)." << std::endl; - std::cout << "[DEBUG] cuVS centroids shape: "; - for (auto s : clustering_cuvs.centroids.sizes()) { std::cout << s << " "; } - std::cout << std::endl; - std::cout.flush(); - - double mse_cpu = ComputeMSE_Faiss(clustering_cpu->centroids, clustering_cpu->vectors); - double mse_cuvs = ComputeMSE_cuVS(clustering_cuvs.centroids, clustering_cuvs.clusters); - - std::cout << "[DEBUG] Inner-product Clustering MSEs:" << std::endl; - std::cout << " FAISS CPU: " << mse_cpu << std::endl; - std::cout << " cuVS : " << mse_cuvs << std::endl; - std::cout.flush(); - - double tol = 0.25; - ASSERT_NEAR(mse_cpu, mse_cuvs, tol * mse_cpu); -} diff --git a/test/cpp/test_cuvs_clustering.cpp b/test/cpp/test_cuvs_clustering.cpp deleted file mode 100644 index 394cf4e7..00000000 --- a/test/cpp/test_cuvs_clustering.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// test_cuvs_clustering.cpp -// -// This file tests the cuVS-based k-means clustering implementation. -// It verifies that the centroids are computed correctly and that the -// entire dataset is partitioned among the clusters. - -#include -#include -#include "cuv_cluster.h" // Contains ClusterWithCuVS, ClusteringResult, and MetricType - -// Test that clustering with L2 metric produces the expected output shapes, -// and that every input vector is assigned to one and only one cluster. -TEST(CUVSClusteringTest, ClusteringL2) { - // Skip the test if CUDA is not available. - if (!torch::cuda::is_available()) { - GTEST_SKIP() << "CUDA is not available, skipping cuVS clustering test."; - } - - const int64_t num_vectors = 1000; - const int64_t dim = 32; - const int64_t num_clusters = 10; - - // Generate random data and corresponding sequential IDs on the GPU. - auto vectors = torch::randn({num_vectors, dim}, torch::kCUDA).to(torch::kFloat32).contiguous(); - auto ids = torch::arange(0, num_vectors, torch::kCUDA).contiguous(); - - // Call the cuVS-based clustering function using L2 metric. - ClusteringResult result = ClusterWithCuVS(vectors, ids, num_clusters, faiss::METRIC_L2); - - // Validate that the centroids tensor has shape [num_clusters, dim]. - ASSERT_EQ(result.centroids.dim(), 2); - ASSERT_EQ(result.centroids.size(0), num_clusters); - ASSERT_EQ(result.centroids.size(1), dim); - - // Verify that all input vectors are partitioned by summing counts from each cluster. - int64_t total_count = 0; - for (const auto& cluster : result.clusters) { - // Each cluster is returned as a pair: - torch::Tensor cluster_vectors = cluster.first; - torch::Tensor cluster_ids = cluster.second; - // The number of vectors in each cluster must match the number of IDs. - ASSERT_EQ(cluster_vectors.size(0), cluster_ids.size(0)); - total_count += cluster_vectors.size(0); - } - ASSERT_EQ(total_count, num_vectors); -} - -// Test that clustering with the inner product metric (which performs normalization) -// yields centroids that are unit-norm and partitions the dataset correctly. -TEST(CUVSClusteringTest, ClusteringInnerProduct) { - if (!torch::cuda::is_available()) { - GTEST_SKIP() << "CUDA is not available, skipping cuVS clustering test."; - } - - const int64_t num_vectors = 1000; - const int64_t dim = 64; - const int64_t num_clusters = 8; - - // Generate random input data and corresponding IDs. - auto vectors = torch::randn({num_vectors, dim}, torch::kCUDA).to(torch::kFloat32).contiguous(); - auto ids = torch::arange(0, num_vectors, torch::kCUDA).contiguous(); - - // Run clustering with inner product metric. The implementation should normalize the vectors. - ClusteringResult result = ClusterWithCuVS(vectors, ids, num_clusters, faiss::METRIC_INNER_PRODUCT); - - // Check that the centroids tensor has the expected shape. - ASSERT_EQ(result.centroids.dim(), 2); - ASSERT_EQ(result.centroids.size(0), num_clusters); - ASSERT_EQ(result.centroids.size(1), dim); - - // Optionally, validate that each centroid is normalized (i.e. its L2 norm is ~1) - auto cent_norms = result.centroids.norm(2, /*dim=*/1); - for (int64_t i = 0; i < cent_norms.size(0); ++i) { - float norm_val = cent_norms[i].item(); - // Allow a small numerical tolerance. - ASSERT_NEAR(norm_val, 1.0, 1e-3); - } - - // Confirm that the total number of vectors across all clusters is equal to the input size. - int64_t total_count = 0; - for (const auto& cluster : result.clusters) { - torch::Tensor cluster_vectors = cluster.first; - torch::Tensor cluster_ids = cluster.second; - ASSERT_EQ(cluster_vectors.size(0), cluster_ids.size(0)); - total_count += cluster_vectors.size(0); - } - ASSERT_EQ(total_count, num_vectors); -} From b201997dda368bf162e35903c532362d6e0b1863 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 16 Apr 2025 11:27:45 -0500 Subject: [PATCH 005/323] update cmake --- CMakeLists.txt | 4 ++-- test/cpp/quake_index.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4cf50474..5b6d8859 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,7 +54,7 @@ set(project_TEST_DIR test/cpp) if(QUAKE_ENABLE_GPU) find_package(CuVS REQUIRED) - include(${project_THIRD_PARTY_DIR}cmake/fetch_rapids.cmake) + include(${project_THIRD_PARTY_DIR}/cmake/fetch_rapids.cmake) include(rapids-cmake) include(rapids-cpm) include(rapids-cuda) @@ -221,7 +221,7 @@ endif() # --------------------------------------------------------------- message(STATUS "--------- Final Configuration Summary ---------") message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") -message(STATUS "GPU Enabled: ${FAISS_ENABLE_GPU}") +message(STATUS "GPU Enabled: ${QUAKE_ENABLE_GPU}") message(STATUS "NUMA Enabled: ${QUAKE_USE_NUMA}") message(STATUS "Python used: ${Python3_EXECUTABLE}") message(STATUS "Torch Path: ${TorchPath}") diff --git a/test/cpp/quake_index.cpp b/test/cpp/quake_index.cpp index 0521ea02..242c16df 100644 --- a/test/cpp/quake_index.cpp +++ b/test/cpp/quake_index.cpp @@ -283,7 +283,7 @@ TEST(QuakeIndexStressTest, LargeBuildTest) { << " vectors took " << build_duration_ms << " ms.\n"; } -#ifdef FAISS_ENABLE_GPU +#ifdef QUAKE_ENABLE_GPU TEST(QuakeIndexStressTestGPU, LargeBuildTest) { // Attempt to build an index with a large number of vectors. // Adjust these numbers based on your available memory/compute. @@ -527,7 +527,7 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { } // Define the GPU related test only if FAISS GPU support is enabled -#ifdef FAISS_ENABLE_GPU +#ifdef QUAKE_ENABLE_GPU // Test build with GPU enabled TEST(QuakeIndexGPUTest, BuildWithGPUTest) { int64_t dimension = 32; From e39c79628a51b7888e1ebc895f40bc6a5ee08cf9 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 16 Apr 2025 11:49:04 -0500 Subject: [PATCH 006/323] update clustering --- src/cpp/include/clustering.h | 6 ------ src/cpp/include/cuv_cluster.h | 14 -------------- src/cpp/src/clustering.cpp | 19 ++++++++++++------- 3 files changed, 12 insertions(+), 27 deletions(-) delete mode 100644 src/cpp/include/cuv_cluster.h diff --git a/src/cpp/include/clustering.h b/src/cpp/include/clustering.h index cc98bebc..e069527c 100644 --- a/src/cpp/include/clustering.h +++ b/src/cpp/include/clustering.h @@ -9,12 +9,6 @@ #include -#ifdef QUAKE_ENABLE_GPU -#include // RAFT resources (handle) -#include // RAFT device view (make_device_matrix_view, etc.) -#include // cuVS k-means API -#endif - class IndexPartition; /** diff --git a/src/cpp/include/cuv_cluster.h b/src/cpp/include/cuv_cluster.h deleted file mode 100644 index 32fe9315..00000000 --- a/src/cpp/include/cuv_cluster.h +++ /dev/null @@ -1,14 +0,0 @@ -// Optionally, if you have your own enum, you can use that instead of faiss::METRIC_L2/INNER_PRODUCT. -struct ClusteringResult { - torch::Tensor centroids; - // Each pair is (cluster_vectors, cluster_ids) for one cluster. - std::vector> clusters; -}; - - -inline ClusteringResult ClusterWithCuVS(const torch::Tensor& vectors, - const torch::Tensor& ids, - int64_t num_clusters, - int metric = faiss::METRIC_L2) { - -} diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index 50052a72..36f9fdae 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -11,6 +11,11 @@ #include #ifdef QUAKE_ENABLE_GPU +#include // RAFT resources (handle) +#include // RAFT device view (make_device_matrix_view, etc.) +#include // cuVS k-means API +#endif + shared_ptr kmeans_cuvs(Tensor vectors, Tensor ids, int num_clusters, @@ -24,13 +29,13 @@ shared_ptr kmeans_cuvs(Tensor vectors, TORCH_CHECK(vectors.size(0) == ids.size(0), "Number of ids must match number of vectors"); TORCH_CHECK(vectors.size(0) >= num_clusters, "Number of clusters cannot exceed number of points"); - int64_t n_samples = data.size(0); - int64_t n_features = data.size(1); + int64_t n_samples = vectors.size(0); + int64_t n_features = vectors.size(1); // If using inner-product (cosine), normalize input vectors. if (metric == faiss::METRIC_INNER_PRODUCT) { - Tensor norms = torch::sqrt((data * data).sum(1, /*keepdim=*/true)); - data = data / norms; + Tensor norms = torch::sqrt((vectors * vectors).sum(1, /*keepdim=*/true)); + vectors = vectors / norms; } // RAFT handle and stream setup. @@ -39,7 +44,7 @@ shared_ptr kmeans_cuvs(Tensor vectors, raft::resource::set_cuda_stream(handle, cuda_stream); // Wrap the input data in a RAFT device_matrix_view. - float* data_ptr = data.data_ptr(); + float* data_ptr = vectors.data_ptr(); auto X_view = raft::make_host_matrix_view(data_ptr, (int)n_samples, (int)n_features); // Allocate output centroids on GPU. @@ -88,8 +93,8 @@ shared_ptr kmeans_cuvs(Tensor vectors, Tensor sorted_labels = labels.index_select(0, sorted_tuple); // Reorder the data and ids using the sorted indices. - Tensor sorted_data = data.index_select(0, sorted_tuple); - Tensor sorted_ids = id_dev.index_select(0, sorted_tuple); + Tensor sorted_data = vectors.index_select(0, sorted_tuple); + Tensor sorted_ids = ids.index_select(0, sorted_tuple); // Compute per-cluster counts using torch::bincount. Tensor counts = torch::bincount(sorted_labels.to(torch::kInt64), /*weights=*/{}, num_clusters); From 174e8d44539faff03baf8bf9ecafd0be2084cd77 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 16 Apr 2025 11:49:23 -0500 Subject: [PATCH 007/323] update clustering --- src/cpp/src/clustering.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index 36f9fdae..01f9f0c7 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -14,7 +14,6 @@ #include // RAFT resources (handle) #include // RAFT device view (make_device_matrix_view, etc.) #include // cuVS k-means API -#endif shared_ptr kmeans_cuvs(Tensor vectors, Tensor ids, From 1c57d974c822cb7fbfbc83520ee45868f0ce5d56 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 16 Apr 2025 14:22:23 -0500 Subject: [PATCH 008/323] update clustering --- src/cpp/src/clustering.cpp | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index 01f9f0c7..c4535662 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -11,6 +11,7 @@ #include #ifdef QUAKE_ENABLE_GPU +#include #include // RAFT resources (handle) #include // RAFT device view (make_device_matrix_view, etc.) #include // cuVS k-means API @@ -21,6 +22,7 @@ shared_ptr kmeans_cuvs(Tensor vectors, MetricType metric, int niter, Tensor initial_centroids) { + // Validate input shapes and sizes. TORCH_CHECK(vectors.dim() == 2, "Input 'vectors' must be a 2D tensor"); TORCH_CHECK(ids.dim() == 1 || (ids.dim() == 2 && ids.size(1) == 1), @@ -39,22 +41,23 @@ shared_ptr kmeans_cuvs(Tensor vectors, // RAFT handle and stream setup. raft::resources handle; - cudaStream_t cuda_stream = at::cuda::getCurrentCUDAStream().stream(); + // Replace the at::cuda call with c10's current CUDA stream. + cudaStream_t cuda_stream = c10::cuda::getCurrentCUDAStream(); raft::resource::set_cuda_stream(handle, cuda_stream); - // Wrap the input data in a RAFT device_matrix_view. + // Wrap the input data in a RAFT *device* matrix view. float* data_ptr = vectors.data_ptr(); - auto X_view = raft::make_host_matrix_view(data_ptr, (int)n_samples, (int)n_features); + auto X_view = raft::make_device_matrix_view(data_ptr, (int)n_samples, (int)n_features); // Allocate output centroids on GPU. Tensor centroids_tensor = torch::empty({num_clusters, n_features}, - torch::TensorOptions().dtype(torch::kFloat32).device(torch::kCUDA)); + torch::TensorOptions().dtype(torch::kFloat32).device(torch::kCUDA)); float* centroids_ptr = centroids_tensor.data_ptr(); auto centroids_view = raft::make_device_matrix_view(centroids_ptr, (int)num_clusters, (int)n_features); // Set up k-means parameters. cuvs::cluster::kmeans::params params; - params.n_clusters = (int)num_clusters; + params.n_clusters = num_clusters; params.max_iter = niter; params.init = cuvs::cluster::kmeans::params::InitMethod::Random; @@ -66,12 +69,12 @@ shared_ptr kmeans_cuvs(Tensor vectors, // Run k-means clustering (fit). cuvs::cluster::kmeans::fit(handle, params, X_view, std::nullopt, - centroids_view, inertia_view, iter_view); + centroids_view, inertia_view, iter_view); // If inner-product, renormalize centroids. if (metric == faiss::METRIC_INNER_PRODUCT) { - Tensor cent_norms = torch::sqrt((centroids_tensor * centroids_tensor).sum(1, /*keepdim=*/true)); - centroids_tensor.div_(cent_norms); + Tensor cent_norms = torch::sqrt((centroids_tensor * centroids_tensor).sum(1, /*keepdim=*/true)); + centroids_tensor.div_(cent_norms); } // Allocate memory for labels and run prediction. @@ -80,15 +83,15 @@ shared_ptr kmeans_cuvs(Tensor vectors, auto labels_view = raft::make_device_vector_view(labels_ptr, (int)n_samples); cuvs::cluster::kmeans::predict(handle, params, X_view, std::nullopt, - centroids_view, labels_view, false, - raft::make_host_scalar_view(&inertia)); + centroids_view, labels_view, false, + raft::make_host_scalar_view(&inertia)); // Synchronize the stream. raft::resource::sync_stream(handle); // ----- Grouping (GPU vectorized) ----- // Sort the labels and get the sorted indices. - Tensor sorted_tuple = std::get<1>(torch::sort(labels)); // sorted indices only, since sorted labels are not needed + Tensor sorted_tuple = std::get<1>(torch::sort(labels)); // sorted indices only Tensor sorted_labels = labels.index_select(0, sorted_tuple); // Reorder the data and ids using the sorted indices. @@ -97,8 +100,6 @@ shared_ptr kmeans_cuvs(Tensor vectors, // Compute per-cluster counts using torch::bincount. Tensor counts = torch::bincount(sorted_labels.to(torch::kInt64), /*weights=*/{}, num_clusters); - - // Transfer counts to CPU and build a vector for split sizes. auto counts_cpu = counts.to(torch::kCPU); std::vector split_sizes(counts_cpu.data_ptr(), counts_cpu.data_ptr() + counts_cpu.numel()); From 2b2e96104d5a7e9d00b60a2d45cdd36237f3b623 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 16 Apr 2025 22:28:48 -0500 Subject: [PATCH 009/323] add CPU-GPU clustering --- src/cpp/src/clustering.cpp | 249 ++++++++++++++++++++++--------------- 1 file changed, 152 insertions(+), 97 deletions(-) diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index c4535662..f6954c3b 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -16,106 +16,155 @@ #include // RAFT device view (make_device_matrix_view, etc.) #include // cuVS k-means API -shared_ptr kmeans_cuvs(Tensor vectors, - Tensor ids, +shared_ptr kmeans_cuvs_sample_and_predict( + Tensor vectors, Tensor ids, int num_clusters, MetricType metric, + int sample_size, int niter, - Tensor initial_centroids) { - - // Validate input shapes and sizes. - TORCH_CHECK(vectors.dim() == 2, "Input 'vectors' must be a 2D tensor"); - TORCH_CHECK(ids.dim() == 1 || (ids.dim() == 2 && ids.size(1) == 1), - "Input 'ids' must be a 1D tensor or 2D with shape (N,1)"); - TORCH_CHECK(vectors.size(0) == ids.size(0), "Number of ids must match number of vectors"); - TORCH_CHECK(vectors.size(0) >= num_clusters, "Number of clusters cannot exceed number of points"); - - int64_t n_samples = vectors.size(0); - int64_t n_features = vectors.size(1); - - // If using inner-product (cosine), normalize input vectors. - if (metric == faiss::METRIC_INNER_PRODUCT) { - Tensor norms = torch::sqrt((vectors * vectors).sum(1, /*keepdim=*/true)); - vectors = vectors / norms; + int gpu_batch_size) { + + TORCH_CHECK(vectors.dim()==2, "vectors must be [N,D]"); + TORCH_CHECK(ids.dim()==1, "ids must be [N]"); + int64_t N = vectors.size(0), D = vectors.size(1); + TORCH_CHECK(sample_size > 0 && sample_size <= N, + "invalid sample_size"); + + // 1) pin + normalize if needed + Tensor cpu_pts = vectors.contiguous().pin_memory(); + if (metric == faiss::METRIC_INNER_PRODUCT) { + auto norms = cpu_pts.norm(2,1,true); + cpu_pts = cpu_pts.div(norms); + } + + // 2) choose a random sample of indices + auto perm = torch::randperm(N, torch::kLong); + auto samp_idx = perm.slice(0, 0, sample_size); + Tensor samp_pts = cpu_pts.index_select(0, samp_idx); + Tensor samp_ids = ids.index_select(0, samp_idx); + + // 3) move sample to GPU + Tensor samp_gpu = samp_pts.to(torch::kCUDA, /*non_blocking=*/true) + .contiguous(); + + // 4) prepare RAFT handle & cuVS params + raft::resources handle; + cudaStream_t stream = c10::cuda::getCurrentCUDAStream(); + raft::resource::set_cuda_stream(handle, stream); + + cuvs::cluster::kmeans::params params; + params.n_clusters = num_clusters; + params.init = cuvs::cluster::kmeans::params::InitMethod::Random; + params.max_iter = niter; + + // 5) allocate centroids on GPU + Tensor cent_gpu = torch::empty({num_clusters, D}, + torch::kFloat32, + torch::TensorOptions().device(torch::kCUDA)) + .contiguous(); + + // 6) run fit on just the sample + { + auto X_view = raft::make_device_matrix_view( + samp_gpu.data_ptr(), + (int)sample_size, (int)D); + auto C_view = raft::make_device_matrix_view( + cent_gpu.data_ptr(), + num_clusters, (int)D); + + cuvs::cluster::kmeans::fit( + handle, params, + X_view, + std::nullopt, + C_view, + raft::make_host_scalar_view(nullptr), + raft::make_host_scalar_view(nullptr) + ); + } + + // 7) now predict labels for all N in batches + Tensor all_labels = torch::empty({N}, torch::kLong); + Tensor labels32 = torch::empty({gpu_batch_size}, + torch::kInt32, + torch::TensorOptions().device(torch::kCUDA)); + auto predict_fn = [&](Tensor batch_cpu, int64_t off) { + int64_t bs = batch_cpu.size(0); + Tensor batch_gpu = batch_cpu.to(torch::kCUDA, /*NB=*/true) + .contiguous(); + auto Xv = raft::make_device_matrix_view( + batch_gpu.data_ptr(), + (int)bs, (int)D); + auto Lv = raft::make_device_vector_view( + labels32.data_ptr(), (int)bs); + + cuvs::cluster::kmeans::predict( + handle, params, + Xv, + std::nullopt, + raft::make_device_matrix_view( + cent_gpu.data_ptr(), + num_clusters, (int)D), + Lv, + false, + raft::make_host_scalar_view(nullptr) + ); + + // copy back + all_labels.narrow(0, off, bs) + .copy_(labels32.slice(0,0,bs) + .to(torch::kLong) + .to(torch::kCPU)); + }; + + // 7a) predict for the sample slice + predict_fn(samp_pts, /*off=*/0); + // 7b) predict for the rest + int64_t written = sample_size; + // we’ll write the rest starting at index sample_size + for (int64_t off = 0; off < N; off += gpu_batch_size) { + int64_t bs = std::min(gpu_batch_size, N - off); + // skip the sample zone + if (off < sample_size) { + // overlap: part sample / part rest + if (off + bs <= sample_size) { + // whole chunk was sample: already done + continue; + } else { + // split chunk + int64_t s_end = sample_size - off; + int64_t r_bs = bs - s_end; + Tensor rest_chunk = cpu_pts.slice(0, off + s_end, off + bs); + predict_fn(rest_chunk, /*off=*/off + s_end); + continue; + } } - - // RAFT handle and stream setup. - raft::resources handle; - // Replace the at::cuda call with c10's current CUDA stream. - cudaStream_t cuda_stream = c10::cuda::getCurrentCUDAStream(); - raft::resource::set_cuda_stream(handle, cuda_stream); - - // Wrap the input data in a RAFT *device* matrix view. - float* data_ptr = vectors.data_ptr(); - auto X_view = raft::make_device_matrix_view(data_ptr, (int)n_samples, (int)n_features); - - // Allocate output centroids on GPU. - Tensor centroids_tensor = torch::empty({num_clusters, n_features}, - torch::TensorOptions().dtype(torch::kFloat32).device(torch::kCUDA)); - float* centroids_ptr = centroids_tensor.data_ptr(); - auto centroids_view = raft::make_device_matrix_view(centroids_ptr, (int)num_clusters, (int)n_features); - - // Set up k-means parameters. - cuvs::cluster::kmeans::params params; - params.n_clusters = num_clusters; - params.max_iter = niter; - params.init = cuvs::cluster::kmeans::params::InitMethod::Random; - - // Prepare host-side scalars to capture inertia and iterations. - float inertia = 0.0f; - int iterations = 0; - auto inertia_view = raft::make_host_scalar_view(&inertia); - auto iter_view = raft::make_host_scalar_view(&iterations); - - // Run k-means clustering (fit). - cuvs::cluster::kmeans::fit(handle, params, X_view, std::nullopt, - centroids_view, inertia_view, iter_view); - - // If inner-product, renormalize centroids. - if (metric == faiss::METRIC_INNER_PRODUCT) { - Tensor cent_norms = torch::sqrt((centroids_tensor * centroids_tensor).sum(1, /*keepdim=*/true)); - centroids_tensor.div_(cent_norms); - } - - // Allocate memory for labels and run prediction. - Tensor labels = torch::empty({n_samples}, torch::TensorOptions().dtype(torch::kInt32).device(torch::kCUDA)); - int* labels_ptr = labels.data_ptr(); - auto labels_view = raft::make_device_vector_view(labels_ptr, (int)n_samples); - - cuvs::cluster::kmeans::predict(handle, params, X_view, std::nullopt, - centroids_view, labels_view, false, - raft::make_host_scalar_view(&inertia)); - - // Synchronize the stream. - raft::resource::sync_stream(handle); - - // ----- Grouping (GPU vectorized) ----- - // Sort the labels and get the sorted indices. - Tensor sorted_tuple = std::get<1>(torch::sort(labels)); // sorted indices only - Tensor sorted_labels = labels.index_select(0, sorted_tuple); - - // Reorder the data and ids using the sorted indices. - Tensor sorted_data = vectors.index_select(0, sorted_tuple); - Tensor sorted_ids = ids.index_select(0, sorted_tuple); - - // Compute per-cluster counts using torch::bincount. - Tensor counts = torch::bincount(sorted_labels.to(torch::kInt64), /*weights=*/{}, num_clusters); - auto counts_cpu = counts.to(torch::kCPU); - std::vector split_sizes(counts_cpu.data_ptr(), counts_cpu.data_ptr() + counts_cpu.numel()); - - // Split the sorted data and ids into clusters. - vector cluster_vectors = torch::split(sorted_data, split_sizes, 0); - vector cluster_ids = torch::split(sorted_ids, split_sizes, 0); - - Tensor partition_ids = torch::arange(num_clusters, torch::kInt64); - - shared_ptr clustering = std::make_shared(); - clustering->centroids = centroids_tensor; - clustering->partition_ids = partition_ids; - clustering->vectors = cluster_vectors; - clustering->vector_ids = cluster_ids; - - return clustering; + // pure rest + Tensor rest_chunk = cpu_pts.slice(0, off, off + bs); + predict_fn(rest_chunk, /*off=*/off); + } + + // 8) group on CPU + Tensor sorted_lbl, sorted_idx; + std::tie(sorted_lbl, sorted_idx) = torch::sort(all_labels); + Tensor sorted_vecs = vectors.index_select(0, sorted_idx); + Tensor sorted_ids = ids.index_select(0, sorted_idx); + + Tensor counts = torch::bincount(sorted_lbl, /*weights=*/{}, num_clusters); + auto cnt_cpu = counts.to(torch::kCPU); + std::vector split_sizes( + cnt_cpu.data_ptr(), + cnt_cpu.data_ptr() + num_clusters + ); + + auto cluster_vecs = torch::split(sorted_vecs, split_sizes, 0); + auto cluster_ids = torch::split(sorted_ids, split_sizes, 0); + + auto out = std::make_shared(); + out->centroids = cent_gpu.cpu().contiguous(); + out->partition_ids = torch::arange(num_clusters, torch::kLong); + out->vectors = std::move(cluster_vecs); + out->vector_ids = std::move(cluster_ids); + return out; } #endif @@ -199,7 +248,13 @@ shared_ptr kmeans(Tensor vectors, Tensor /* initial_centroids */) { if (use_gpu) { #ifdef QUAKE_ENABLE_GPU - return kmeans_cuvs(vectors, ids, n_clusters, metric_type, niter); + const int sample_size = std::min(1000000, vectors.size(0)); + const int gpu_batch_size = 100000; // or from build_params + return kmeans_cuvs_sample_and_predict( + vectors, ids, + n_clusters, metric, + sample_size, niter, + gpu_batch_size); #elif throw std::runtime_error("GPU support is not enabled. Please compile with QUAKE_ENABLE_GPU."); #endif From 19d5c30dd3a4c915511d22291eb86bf2933cb9c8 Mon Sep 17 00:00:00 2001 From: Jason Mohoney Date: Thu, 17 Apr 2025 17:22:46 +0000 Subject: [PATCH 010/323] cpu-gpu k-means bug fix --- CMakeLists.txt | 2 +- src/cpp/include/clustering.h | 13 +- src/cpp/src/clustering.cpp | 104 ++++++++++----- test/cpp/clustering.cpp | 245 ++++++++++++++--------------------- test/cpp/quake_index.cpp | 16 ++- 5 files changed, 184 insertions(+), 196 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b6d8859..fa71a403 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,7 @@ if(QUAKE_ENABLE_GPU) add_compile_definitions(QUAKE_ENABLE_GPU) endif() +set(FAISS_ENABLE_GPU OFF) # --------------------------------------------------------------- # Print out Compiler and Path Information # --------------------------------------------------------------- @@ -87,7 +88,6 @@ message(STATUS "QUAKE_USE_NUMA: ${QUAKE_USE_NUMA}") # Apple-specific adjustments if(APPLE) include_directories("/opt/homebrew/opt/openblas/include") - set(FAISS_ENABLE_GPU OFF) endif() # Compiler options and definitions diff --git a/src/cpp/include/clustering.h b/src/cpp/include/clustering.h index e069527c..130b5a1d 100644 --- a/src/cpp/include/clustering.h +++ b/src/cpp/include/clustering.h @@ -41,12 +41,13 @@ shared_ptr kmeans_cpu(Tensor vectors, * @param initial_centroids The initial centroids to use for k-means. */ #ifdef QUAKE_ENABLE_GPU -shared_ptr kmeans_cuvs(Tensor vectors, - Tensor ids, - int n_clusters, - MetricType metric_type, - int niter = 5, - Tensor initial_centroids = Tensor()); +shared_ptr kmeans_cuvs_sample_and_predict( + Tensor vectors, Tensor ids, + int num_clusters, + MetricType metric, + int sample_size, + int niter, + int gpu_batch_size); #endif /** diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index f6954c3b..d5520320 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -24,8 +24,15 @@ shared_ptr kmeans_cuvs_sample_and_predict( int niter, int gpu_batch_size) { - TORCH_CHECK(vectors.dim()==2, "vectors must be [N,D]"); - TORCH_CHECK(ids.dim()==1, "ids must be [N]"); + std::cout << "[kmeans] Starting sample_and_predict: N=" + << vectors.size(0) << ", D=" << vectors.size(1) + << ", clusters=" << num_clusters + << ", sample_size=" << sample_size + << ", niter=" << niter + << ", batch_size=" << gpu_batch_size << std::endl; + + TORCH_CHECK(vectors.dim() == 2, "vectors must be [N,D]"); + TORCH_CHECK(ids.dim() == 1, "ids must be [N]"); int64_t N = vectors.size(0), D = vectors.size(1); TORCH_CHECK(sample_size > 0 && sample_size <= N, "invalid sample_size"); @@ -33,19 +40,20 @@ shared_ptr kmeans_cuvs_sample_and_predict( // 1) pin + normalize if needed Tensor cpu_pts = vectors.contiguous().pin_memory(); if (metric == faiss::METRIC_INNER_PRODUCT) { - auto norms = cpu_pts.norm(2,1,true); + auto norms = cpu_pts.norm(2, 1, true); cpu_pts = cpu_pts.div(norms); + std::cout << "[kmeans] Normalized for inner product metric" << std::endl; } // 2) choose a random sample of indices - auto perm = torch::randperm(N, torch::kLong); + std::cout << "[kmeans] Sampling " << sample_size << " points" << std::endl; + auto perm = torch::randperm(N, torch::kLong); auto samp_idx = perm.slice(0, 0, sample_size); Tensor samp_pts = cpu_pts.index_select(0, samp_idx); - Tensor samp_ids = ids.index_select(0, samp_idx); // 3) move sample to GPU - Tensor samp_gpu = samp_pts.to(torch::kCUDA, /*non_blocking=*/true) - .contiguous(); + std::cout << "[kmeans] Uploading sample to GPU" << std::endl; + Tensor samp_gpu = samp_pts.to(torch::kCUDA, /*non_blocking=*/true).contiguous(); // 4) prepare RAFT handle & cuVS params raft::resources handle; @@ -59,12 +67,20 @@ shared_ptr kmeans_cuvs_sample_and_predict( // 5) allocate centroids on GPU Tensor cent_gpu = torch::empty({num_clusters, D}, - torch::kFloat32, - torch::TensorOptions().device(torch::kCUDA)) + torch::TensorOptions() + .dtype(torch::kFloat32) + .device(torch::kCUDA)) .contiguous(); // 6) run fit on just the sample { + std::cout << "[kmeans] Running cuVS fit on sample" << std::endl; + // host scalars + float inertia = 0.0f; + int actual_iter= 0; + auto host_inertia = raft::make_host_scalar_view(&inertia); + auto host_iter = raft::make_host_scalar_view(&actual_iter); + auto X_view = raft::make_device_matrix_view( samp_gpu.data_ptr(), (int)sample_size, (int)D); @@ -77,26 +93,39 @@ shared_ptr kmeans_cuvs_sample_and_predict( X_view, std::nullopt, C_view, - raft::make_host_scalar_view(nullptr), - raft::make_host_scalar_view(nullptr) + host_inertia, + host_iter ); + + std::cout << "[kmeans] Fit complete: inertia=" << inertia + << ", iterations=" << actual_iter << std::endl; } - // 7) now predict labels for all N in batches + std::cout << "[kmeans] Beginning predict over all " << N << " points" << std::endl; Tensor all_labels = torch::empty({N}, torch::kLong); - Tensor labels32 = torch::empty({gpu_batch_size}, - torch::kInt32, - torch::TensorOptions().device(torch::kCUDA)); + auto predict_fn = [&](Tensor batch_cpu, int64_t off) { int64_t bs = batch_cpu.size(0); + + // allocate exactly bs labels on the GPU + Tensor labels32 = torch::empty( + {bs}, + torch::TensorOptions() + .dtype(torch::kInt32) + .device(torch::kCUDA)); + Tensor batch_gpu = batch_cpu.to(torch::kCUDA, /*NB=*/true) - .contiguous(); + .contiguous(); + auto Xv = raft::make_device_matrix_view( batch_gpu.data_ptr(), (int)bs, (int)D); auto Lv = raft::make_device_vector_view( labels32.data_ptr(), (int)bs); + float pred_inertia = 0.0f; + auto host_pred = raft::make_host_scalar_view(&pred_inertia); + cuvs::cluster::kmeans::predict( handle, params, Xv, @@ -106,44 +135,44 @@ shared_ptr kmeans_cuvs_sample_and_predict( num_clusters, (int)D), Lv, false, - raft::make_host_scalar_view(nullptr) + host_pred ); - // copy back + std::cout << "[kmeans] Predict batch off=" << off + << ", bs=" << bs + << ", inertia=" << pred_inertia << std::endl; + + // now safe to copy back exactly bs elements all_labels.narrow(0, off, bs) - .copy_(labels32.slice(0,0,bs) - .to(torch::kLong) - .to(torch::kCPU)); + .copy_( + labels32.to(torch::kLong) + .to(torch::kCPU) + ); }; - // 7a) predict for the sample slice + // predict the sample slice + std::cout << "[kmeans] Predicting sample slice [0," << sample_size << ")" << std::endl; predict_fn(samp_pts, /*off=*/0); - // 7b) predict for the rest - int64_t written = sample_size; - // we’ll write the rest starting at index sample_size + + // predict the rest + std::cout << "[kmeans] Predicting remaining chunks" << std::endl; for (int64_t off = 0; off < N; off += gpu_batch_size) { int64_t bs = std::min(gpu_batch_size, N - off); - // skip the sample zone if (off < sample_size) { - // overlap: part sample / part rest if (off + bs <= sample_size) { - // whole chunk was sample: already done continue; } else { - // split chunk - int64_t s_end = sample_size - off; - int64_t r_bs = bs - s_end; - Tensor rest_chunk = cpu_pts.slice(0, off + s_end, off + bs); - predict_fn(rest_chunk, /*off=*/off + s_end); + int64_t overlap = sample_size - off; + Tensor rest_chunk = cpu_pts.slice(0, off + overlap, off + bs); + predict_fn(rest_chunk, /*off=*/off + overlap); continue; } } - // pure rest Tensor rest_chunk = cpu_pts.slice(0, off, off + bs); predict_fn(rest_chunk, /*off=*/off); } - // 8) group on CPU + std::cout << "[kmeans] Grouping on CPU" << std::endl; Tensor sorted_lbl, sorted_idx; std::tie(sorted_lbl, sorted_idx) = torch::sort(all_labels); Tensor sorted_vecs = vectors.index_select(0, sorted_idx); @@ -164,8 +193,11 @@ shared_ptr kmeans_cuvs_sample_and_predict( out->partition_ids = torch::arange(num_clusters, torch::kLong); out->vectors = std::move(cluster_vecs); out->vector_ids = std::move(cluster_ids); + + std::cout << "[kmeans] Completed sample_and_predict\n"; return out; } + #endif shared_ptr kmeans_cpu(Tensor vectors, @@ -252,7 +284,7 @@ shared_ptr kmeans(Tensor vectors, const int gpu_batch_size = 100000; // or from build_params return kmeans_cuvs_sample_and_predict( vectors, ids, - n_clusters, metric, + n_clusters, metric_type, sample_size, niter, gpu_batch_size); #elif diff --git a/test/cpp/clustering.cpp b/test/cpp/clustering.cpp index 9c0b76c3..c94cb44a 100644 --- a/test/cpp/clustering.cpp +++ b/test/cpp/clustering.cpp @@ -1,179 +1,132 @@ #include #include #include "clustering.h" -#include -// Helper functions to generate random test data. -static Tensor generate_random_data(int64_t num_vectors, int64_t dim) { - return torch::randn({num_vectors, dim}, torch::kFloat32).contiguous(); +// Helpers to generate random data and sequential ids +static torch::Tensor generate_random_data(int64_t N, int64_t D) { + return torch::randn({N, D}, torch::kFloat32).contiguous(); } - -static Tensor generate_sequential_ids(int64_t count, int64_t start = 0) { - return torch::arange(start, start + count, torch::kInt64).contiguous(); +static torch::Tensor generate_sequential_ids(int64_t N, int64_t start = 0) { + return torch::arange(start, start + N, torch::kInt64).contiguous(); } -// Helpers to compute mean squared error (MSE) for clustering. -// For FAISS-based clustering: 'vectors' is a vector of tensors (one per cluster). -static double compute_mse(const Tensor& centroids, - const std::vector& clusters) { - double total_error = 0.0; - int64_t total_count = 0; - auto centroids_cpu = centroids.to(torch::kCPU); +// Compute mean squared error for clustering (for CPU sanity) +static double compute_mse(const torch::Tensor& centroids, + const std::vector& clusters) { + double total_err = 0.0; + int64_t count = 0; + auto C = centroids.to(torch::kCPU); for (size_t i = 0; i < clusters.size(); ++i) { - if (clusters[i].size(0) > 0) { - auto cluster = clusters[i].to(torch::kCPU); - auto diff = cluster - centroids_cpu[i].unsqueeze(0); - total_error += diff.pow(2).sum().item(); - total_count += cluster.size(0); - } + auto cl = clusters[i].to(torch::kCPU); + if (cl.size(0) == 0) continue; + auto diff = cl - C[i].unsqueeze(0); + total_err += diff.pow(2).sum().item(); + count += cl.size(0); } - return total_count > 0 ? total_error / total_count : 0.0; + return count>0 ? total_err / count : 0.0; } -// Test fixture for clustering tests. +// Fixture class ClusteringTest : public ::testing::Test { protected: const int64_t num_vectors = 5000; - const int64_t dim = 64; - const int num_clusters = 20; - Tensor vectors_cpu, ids_cpu; - Tensor vectors_cuda, ids_cuda; + const int64_t dim = 64; + const int num_clusters= 20; + + torch::Tensor vectors_cpu, ids_cpu; +#ifdef QUAKE_ENABLE_GPU + torch::Tensor vectors_cuda, ids_cuda; +#endif void SetUp() override { - // Skip these tests if CUDA is not available. - if (!torch::cuda::is_available()) { - GTEST_SKIP() << "CUDA is not available; skipping clustering tests."; - } vectors_cpu = generate_random_data(num_vectors, dim); - ids_cpu = generate_sequential_ids(num_vectors); + ids_cpu = generate_sequential_ids(num_vectors); + #ifdef QUAKE_ENABLE_GPU + if (!torch::cuda::is_available()) { + GTEST_SKIP() << "CUDA not available"; + } vectors_cuda = vectors_cpu.to(torch::kCUDA).contiguous(); - ids_cuda = ids_cpu.to(torch::kCUDA).contiguous(); + ids_cuda = ids_cpu.to(torch::kCUDA).contiguous(); #endif } }; -// Compare clustering methods using the L2 (Euclidean) metric. -#ifdef QUAKE_ENABLE_GPU -TEST_F(ClusteringTest, CompareClustering_L2) { - const int niter = 20; - // FAISS-based clustering on CPU. - auto clustering_cpu = kmeans_cpu(vectors_cpu, ids_cpu, num_clusters, faiss::METRIC_L2, niter, Tensor()); - // cuVS-based clustering on GPU. - auto clustering_cuvs = kmeans_cuvs(vectors_cuda, ids_cuda, num_clusters, faiss::METRIC_L2); - - // Verify centroid shapes. - ASSERT_EQ(clustering_cpu->centroids.dim(), 2); - ASSERT_EQ(clustering_cpu->centroids.size(0), num_clusters); - ASSERT_EQ(clustering_cpu->centroids.size(1), dim); - ASSERT_EQ(clustering_cuvs->centroids.dim(), 2); - ASSERT_EQ(clustering_cuvs->centroids.size(0), num_clusters); - ASSERT_EQ(clustering_cuvs->centroids.size(1), dim); - - // Compare the mean squared errors (MSEs) between the methods. - double mse_cpu = compute_mse(clustering_cpu->centroids, clustering_cpu->vectors); - double mse_cuvs = compute_mse(clustering_cuvs->centroids, clustering_cuvs->vectors); - // They should agree within roughly 20% relative difference. - ASSERT_NEAR(mse_cpu, mse_cuvs, mse_cpu * 0.20); -} - -// Compare clustering methods using the inner product metric. -TEST_F(ClusteringTest, CompareClustering_InnerProduct) { - const int niter = 20; - auto clustering_cpu = kmeans(vectors_cpu, ids_cpu, num_clusters, - faiss::METRIC_INNER_PRODUCT, niter, false, Tensor()); - auto clustering_cuvs = kmeans_cuvs(vectors_cuda, ids_cuda, num_clusters, faiss::METRIC_INNER_PRODUCT); - - // Verify centroid shapes. - ASSERT_EQ(clustering_cpu->centroids.dim(), 2); - ASSERT_EQ(clustering_cpu->centroids.size(0), num_clusters); - ASSERT_EQ(clustering_cpu->centroids.size(1), dim); - ASSERT_EQ(clustering_cuvs->centroids.dim(), 2); - ASSERT_EQ(clustering_cuvs->centroids.size(0), num_clusters); - ASSERT_EQ(clustering_cuvs->centroids.size(1), dim); - - // For inner product, check that cuVS centroids are normalized. - auto norms = clustering_cuvs->centroids.norm(2, 1); - for (int i = 0; i < norms.size(0); ++i) { - ASSERT_NEAR(norms[i].item(), 1.0f, 1e-3); +// Test existing CPU kmeans +TEST_F(ClusteringTest, KMeansCPU_L2) { + auto cl = kmeans_cpu(vectors_cpu, ids_cpu, num_clusters, + faiss::METRIC_L2, /*niter=*/10, torch::Tensor()); + ASSERT_EQ(cl->centroids.sizes(), (std::vector{num_clusters, dim})); + int64_t tot=0; + for (int i=0;ivectors[i].size(0), cl->vector_ids[i].size(0)); + tot += cl->vectors[i].size(0); } - - double mse_cpu = compute_mse(clustering_cpu->centroids, clustering_cpu->vectors); - double mse_cuvs = compute_mse(clustering_cuvs->centroids, clustering_cuvs->vectors); - // Allow a bit larger relative difference for inner product. - ASSERT_NEAR(mse_cpu, mse_cuvs, mse_cpu * 0.25); + ASSERT_EQ(tot, num_vectors); } -// Test that cuVS clustering partitions all vectors correctly (L2 metric). -TEST_F(ClusteringTest, CUVSClustering_Partitioning_L2) { - auto result = kmeans_cuvs(vectors_cuda, ids_cuda, num_clusters, faiss::METRIC_L2); - ASSERT_EQ(result->centroids.dim(), 2); - ASSERT_EQ(result->centroids.size(0), num_clusters); - ASSERT_EQ(result->centroids.size(1), dim); - - int64_t total_vectors = 0; - for (int i = 0; i < num_clusters; ++i) { - auto cluster = result->vectors[i]; - ASSERT_EQ(cluster.size(0), result->vector_ids[i].size(0)); - total_vectors += cluster.size(0); +// Compare CPU vs CPU wrapper +TEST_F(ClusteringTest, KMeansWrapper_CPU) { + auto cl = kmeans(vectors_cpu, ids_cpu, num_clusters, + faiss::METRIC_L2, /*niter=*/10, /*use_gpu=*/false, torch::Tensor()); + ASSERT_EQ(cl->centroids.sizes(), (std::vector{num_clusters, dim})); + int64_t tot=0; + for (int i=0;ivectors[i].size(0); } - ASSERT_EQ(total_vectors, num_vectors); + ASSERT_EQ(tot, num_vectors); } - -// Test that cuVS clustering (inner product) produces unit-norm centroids and correctly partitions vectors. -TEST_F(ClusteringTest, CUVSClustering_Partitioning_InnerProduct) { - auto result = kmeans_cuvs(vectors_cuda, ids_cuda, num_clusters, faiss::METRIC_INNER_PRODUCT); - ASSERT_EQ(result->centroids.dim(), 2); - ASSERT_EQ(result->centroids.size(0), num_clusters); - ASSERT_EQ(result->centroids.size(1), dim); - - // Verify centroids are normalized. - auto norms = result->centroids.norm(2, 1); - for (int i = 0; i < norms.size(0); ++i) { - ASSERT_NEAR(norms[i].item(), 1.0f, 1e-3); - } - - int64_t total_vectors = 0; - for (int i = 0; i < num_clusters; ++i) { - auto cluster = result->vectors[i]; - ASSERT_EQ(cluster.size(0), result->vector_ids[i].size(0)); - total_vectors += cluster.size(0); +#ifdef QUAKE_ENABLE_GPU +TEST_F(ClusteringTest, SampleAndPredict_GPU_L2) { + const int sample_size = 1000; + const int niter = 5; + const int gpu_batch_size = 512; + + auto cl = kmeans_cuvs_sample_and_predict( + vectors_cpu, ids_cpu, + num_clusters, + faiss::METRIC_L2, + sample_size, + niter, + gpu_batch_size); + + // centroids must live on CPU and have correct shape + ASSERT_EQ(cl->centroids.device().type(), torch::kCPU); + ASSERT_EQ(cl->centroids.sizes(), (std::vector{num_clusters, dim})); + + // all vectors accounted for + int64_t tot=0; + for (int i=0;ivectors[i]; + ASSERT_EQ(part.device().type(), torch::kCPU); + ASSERT_EQ(part.size(0), cl->vector_ids[i].size(0)); + tot += part.size(0); } - ASSERT_EQ(total_vectors, num_vectors); + ASSERT_EQ(tot, num_vectors); + + // Optional quality check: rough MSE vs CPU run + auto cl_cpu = kmeans_cpu(vectors_cpu, ids_cpu, num_clusters, + faiss::METRIC_L2, niter, torch::Tensor()); + double mse_cpu = compute_mse(cl_cpu->centroids, cl_cpu->vectors); + double mse_gpu = compute_mse(cl->centroids, cl->vectors); + ASSERT_NEAR(mse_cpu, mse_gpu, mse_cpu * 0.30); } -#endif - -TEST_F(ClusteringTest, KMeansCPU_L2) { - // Test CPU-based k-means clustering. - int niter = 10; - auto clustering = kmeans_cpu(vectors_cpu, ids_cpu, num_clusters, faiss::METRIC_L2, niter); - ASSERT_EQ(clustering->centroids.dim(), 2); - ASSERT_EQ(clustering->centroids.size(0), num_clusters); - ASSERT_EQ(clustering->centroids.size(1), dim); - int64_t total_vectors = 0; - for (int i = 0; i < num_clusters; ++i) { - auto cluster = clustering->vectors[i]; - ASSERT_EQ(cluster.size(0), clustering->vector_ids[i].size(0)); - total_vectors += cluster.size(0); - } - ASSERT_EQ(total_vectors, num_vectors); +// Full wrapper test for GPU +TEST_F(ClusteringTest, KMeansWrapper_GPU) { + const int gpu_sample = 2000; + const int gpu_iter = 3; + const int gpu_batch = 1024; + + auto cl = kmeans(vectors_cpu, ids_cpu, num_clusters, + faiss::METRIC_L2, gpu_iter, + /*use_gpu=*/true, + torch::Tensor()); + ASSERT_EQ(cl->centroids.device().type(), torch::kCPU); + ASSERT_EQ(cl->vectors.size(), size_t(num_clusters)); + int64_t tot=0; + for (auto &p : cl->vectors) tot += p.size(0); + ASSERT_EQ(tot, num_vectors); } - -TEST_F(ClusteringTest, KMeansCPU_InnerProduct) { - // Test CPU-based k-means clustering with inner product metric. - int niter = 10; - auto clustering = kmeans_cpu(vectors_cpu, ids_cpu, num_clusters, faiss::METRIC_INNER_PRODUCT, niter); - ASSERT_EQ(clustering->centroids.dim(), 2); - ASSERT_EQ(clustering->centroids.size(0), num_clusters); - ASSERT_EQ(clustering->centroids.size(1), dim); - - int64_t total_vectors = 0; - for (int i = 0; i < num_clusters; ++i) { - auto cluster = clustering->vectors[i]; - ASSERT_EQ(cluster.size(0), clustering->vector_ids[i].size(0)); - total_vectors += cluster.size(0); - } - ASSERT_EQ(total_vectors, num_vectors); -} \ No newline at end of file +#endif // QUAKE_ENABLE_GPU diff --git a/test/cpp/quake_index.cpp b/test/cpp/quake_index.cpp index 242c16df..12dd3bf0 100644 --- a/test/cpp/quake_index.cpp +++ b/test/cpp/quake_index.cpp @@ -257,14 +257,14 @@ TEST(QuakeIndexStressTest, LargeBuildTest) { // Attempt to build an index with a large number of vectors. // Adjust these numbers based on your available memory/compute. int64_t dimension = 128; // Medium-high dimension - int64_t num_vectors = 1e6; // 1 million vectors + int64_t num_vectors = 10e6; // 1 million vectors auto data_vectors = generate_random_data(num_vectors, dimension); auto data_ids = generate_sequential_ids(num_vectors, 0); QuakeIndex index; auto build_params = std::make_shared(); - build_params->nlist = 512; + build_params->nlist = 5120; build_params->metric = "l2"; // Keep the iteration count modest to avoid overly long tests build_params->niter = 5; @@ -288,14 +288,16 @@ TEST(QuakeIndexStressTestGPU, LargeBuildTest) { // Attempt to build an index with a large number of vectors. // Adjust these numbers based on your available memory/compute. int64_t dimension = 128; // Medium-high dimension - int64_t num_vectors = 1e6; // 1 million vectors - auto data_vectors = generate_random_data(num_vectors, dimension); - auto data_ids = generate_sequential_ids(num_vectors, 0); + int64_t num_vectors = 10e6; // 1 million vectors + auto data_vectors = generate_random_data(num_vectors, dimension).contiguous(); + auto data_ids = generate_sequential_ids(num_vectors, 0).contiguous(); QuakeIndex index; + std::cout << "generated\n"; + auto build_params = std::make_shared(); - build_params->nlist = 512; + build_params->nlist = 5120; build_params->metric = "l2"; build_params->use_gpu = true; // Keep the iteration count modest to avoid overly long tests @@ -554,4 +556,4 @@ TEST(QuakeIndexGPUTest, BuildWithGPUTest) { EXPECT_EQ(timing_info->n_vectors, data_vectors.size(0)); EXPECT_EQ(timing_info->d, data_vectors.size(1)); } -#endif \ No newline at end of file +#endif From 62650c942d15f97ab8766b7e1485d4e9fc0f874f Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 17 Apr 2025 12:24:37 -0500 Subject: [PATCH 011/323] remove logs --- src/cpp/src/clustering.cpp | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index d5520320..b2a3f15a 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -10,7 +10,7 @@ #include "index_partition.h" #include -#ifdef QUAKE_ENABLE_GPU +// #ifdef QUAKE_ENABLE_GPU #include #include // RAFT resources (handle) #include // RAFT device view (make_device_matrix_view, etc.) @@ -24,13 +24,6 @@ shared_ptr kmeans_cuvs_sample_and_predict( int niter, int gpu_batch_size) { - std::cout << "[kmeans] Starting sample_and_predict: N=" - << vectors.size(0) << ", D=" << vectors.size(1) - << ", clusters=" << num_clusters - << ", sample_size=" << sample_size - << ", niter=" << niter - << ", batch_size=" << gpu_batch_size << std::endl; - TORCH_CHECK(vectors.dim() == 2, "vectors must be [N,D]"); TORCH_CHECK(ids.dim() == 1, "ids must be [N]"); int64_t N = vectors.size(0), D = vectors.size(1); @@ -42,17 +35,14 @@ shared_ptr kmeans_cuvs_sample_and_predict( if (metric == faiss::METRIC_INNER_PRODUCT) { auto norms = cpu_pts.norm(2, 1, true); cpu_pts = cpu_pts.div(norms); - std::cout << "[kmeans] Normalized for inner product metric" << std::endl; } // 2) choose a random sample of indices - std::cout << "[kmeans] Sampling " << sample_size << " points" << std::endl; auto perm = torch::randperm(N, torch::kLong); auto samp_idx = perm.slice(0, 0, sample_size); Tensor samp_pts = cpu_pts.index_select(0, samp_idx); // 3) move sample to GPU - std::cout << "[kmeans] Uploading sample to GPU" << std::endl; Tensor samp_gpu = samp_pts.to(torch::kCUDA, /*non_blocking=*/true).contiguous(); // 4) prepare RAFT handle & cuVS params @@ -74,7 +64,6 @@ shared_ptr kmeans_cuvs_sample_and_predict( // 6) run fit on just the sample { - std::cout << "[kmeans] Running cuVS fit on sample" << std::endl; // host scalars float inertia = 0.0f; int actual_iter= 0; @@ -96,12 +85,8 @@ shared_ptr kmeans_cuvs_sample_and_predict( host_inertia, host_iter ); - - std::cout << "[kmeans] Fit complete: inertia=" << inertia - << ", iterations=" << actual_iter << std::endl; } - std::cout << "[kmeans] Beginning predict over all " << N << " points" << std::endl; Tensor all_labels = torch::empty({N}, torch::kLong); auto predict_fn = [&](Tensor batch_cpu, int64_t off) { @@ -138,10 +123,6 @@ shared_ptr kmeans_cuvs_sample_and_predict( host_pred ); - std::cout << "[kmeans] Predict batch off=" << off - << ", bs=" << bs - << ", inertia=" << pred_inertia << std::endl; - // now safe to copy back exactly bs elements all_labels.narrow(0, off, bs) .copy_( @@ -151,11 +132,9 @@ shared_ptr kmeans_cuvs_sample_and_predict( }; // predict the sample slice - std::cout << "[kmeans] Predicting sample slice [0," << sample_size << ")" << std::endl; predict_fn(samp_pts, /*off=*/0); // predict the rest - std::cout << "[kmeans] Predicting remaining chunks" << std::endl; for (int64_t off = 0; off < N; off += gpu_batch_size) { int64_t bs = std::min(gpu_batch_size, N - off); if (off < sample_size) { @@ -172,7 +151,6 @@ shared_ptr kmeans_cuvs_sample_and_predict( predict_fn(rest_chunk, /*off=*/off); } // 8) group on CPU - std::cout << "[kmeans] Grouping on CPU" << std::endl; Tensor sorted_lbl, sorted_idx; std::tie(sorted_lbl, sorted_idx) = torch::sort(all_labels); Tensor sorted_vecs = vectors.index_select(0, sorted_idx); @@ -194,11 +172,9 @@ shared_ptr kmeans_cuvs_sample_and_predict( out->vectors = std::move(cluster_vecs); out->vector_ids = std::move(cluster_ids); - std::cout << "[kmeans] Completed sample_and_predict\n"; return out; } - -#endif +// #endif shared_ptr kmeans_cpu(Tensor vectors, Tensor ids, From c71326616ded0de9efed1f5bea14e028bce24c61 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 17 Apr 2025 16:01:09 -0500 Subject: [PATCH 012/323] pass build params directly to kmeans --- src/cpp/include/clustering.h | 16 +-- src/cpp/include/common.h | 8 +- src/cpp/src/clustering.cpp | 174 +++++++++++++++--------------- src/cpp/src/partition_manager.cpp | 6 +- src/cpp/src/quake_index.cpp | 5 +- test/cpp/clustering.cpp | 51 +++++---- 6 files changed, 132 insertions(+), 128 deletions(-) diff --git a/src/cpp/include/clustering.h b/src/cpp/include/clustering.h index 130b5a1d..d83d563b 100644 --- a/src/cpp/include/clustering.h +++ b/src/cpp/include/clustering.h @@ -24,9 +24,7 @@ class IndexPartition; */ shared_ptr kmeans_cpu(Tensor vectors, Tensor ids, - int n_clusters, - MetricType metric_type, - int niter = 5, + shared_ptr build_params, Tensor initial_centroids = Tensor()); /** @@ -42,12 +40,7 @@ shared_ptr kmeans_cpu(Tensor vectors, */ #ifdef QUAKE_ENABLE_GPU shared_ptr kmeans_cuvs_sample_and_predict( - Tensor vectors, Tensor ids, - int num_clusters, - MetricType metric, - int sample_size, - int niter, - int gpu_batch_size); + Tensor vectors, Tensor ids, shared_ptr build_params); #endif /** @@ -63,10 +56,7 @@ shared_ptr kmeans_cuvs_sample_and_predict( */ shared_ptr kmeans(Tensor vectors, Tensor ids, - int n_clusters, - MetricType metric_type, - int niter = 5, - bool use_gpu = false, + shared_ptr build_params, Tensor initial_centroids = Tensor()); diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index ff95b2a2..b9ac90ed 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -63,6 +63,8 @@ constexpr int DEFAULT_NLIST = 0; ///< Default number of cluste constexpr int DEFAULT_NITER = 5; ///< Default number of k-means iterations used during clustering. constexpr const char* DEFAULT_METRIC = "l2"; ///< Default distance metric (either "l2" for Euclidean or "ip" for inner product). constexpr int DEFAULT_NUM_WORKERS = 0; ///< Default number of workers (0 means single-threaded). +constexpr int DEFAULT_GPU_BATCH_SIZE = 100000; ///< Default batch size for GPU index building. +constexpr int DEFAULT_GPU_SAMPLE_SIZE = 1000000; ///< Default sample size for GPU index building. // Default constants for search parameters constexpr int DEFAULT_K = 1; ///< Default number of neighbors to return. @@ -124,11 +126,15 @@ struct IndexBuildParams { bool use_adaptive_nprobe = false; bool use_numa = false; - bool use_gpu = false; bool verify_numa = false; bool same_core = true; bool verbose = false; + // gpu index build params + bool use_gpu = false; + int gpu_batch_size = DEFAULT_GPU_BATCH_SIZE; + int gpu_sample_size = DEFAULT_GPU_SAMPLE_SIZE; + shared_ptr parent_params = nullptr; IndexBuildParams() = default; diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index b2a3f15a..b5f82682 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -10,7 +10,7 @@ #include "index_partition.h" #include -// #ifdef QUAKE_ENABLE_GPU +#ifdef QUAKE_ENABLE_GPU #include #include // RAFT resources (handle) #include // RAFT device view (make_device_matrix_view, etc.) @@ -18,52 +18,54 @@ shared_ptr kmeans_cuvs_sample_and_predict( Tensor vectors, Tensor ids, - int num_clusters, - MetricType metric, - int sample_size, - int niter, - int gpu_batch_size) { - - TORCH_CHECK(vectors.dim() == 2, "vectors must be [N,D]"); - TORCH_CHECK(ids.dim() == 1, "ids must be [N]"); - int64_t N = vectors.size(0), D = vectors.size(1); - TORCH_CHECK(sample_size > 0 && sample_size <= N, + shared_ptr build_params) { + + int num_clusters = build_params->nlist; + int niter = build_params->niter; + int gpu_batch_size = build_params->gpu_batch_size; + int gpu_sample_size = build_params->gpu_sample_size; + MetricType metric = str_to_metric_type(build_params->metric); + + TORCH_CHECK(vectors.dim() == 2, "vectors must be [N,D]"); + TORCH_CHECK(ids.dim() == 1, "ids must be [N]"); + int64_t N = vectors.size(0), D = vectors.size(1); + TORCH_CHECK(gpu_sample_size > 0 && gpu_sample_size <= N, "invalid sample_size"); - // 1) pin + normalize if needed - Tensor cpu_pts = vectors.contiguous().pin_memory(); - if (metric == faiss::METRIC_INNER_PRODUCT) { + // 1) pin + normalize if needed + Tensor cpu_pts = vectors.contiguous().pin_memory(); + if (metric == faiss::METRIC_INNER_PRODUCT) { auto norms = cpu_pts.norm(2, 1, true); cpu_pts = cpu_pts.div(norms); - } + } - // 2) choose a random sample of indices - auto perm = torch::randperm(N, torch::kLong); - auto samp_idx = perm.slice(0, 0, sample_size); - Tensor samp_pts = cpu_pts.index_select(0, samp_idx); + // 2) choose a random sample of indices + auto perm = torch::randperm(N, torch::kLong); + auto samp_idx = perm.slice(0, 0, gpu_sample_size); + Tensor samp_pts = cpu_pts.index_select(0, samp_idx); - // 3) move sample to GPU - Tensor samp_gpu = samp_pts.to(torch::kCUDA, /*non_blocking=*/true).contiguous(); + // 3) move sample to GPU + Tensor samp_gpu = samp_pts.to(torch::kCUDA, /*non_blocking=*/true).contiguous(); - // 4) prepare RAFT handle & cuVS params - raft::resources handle; - cudaStream_t stream = c10::cuda::getCurrentCUDAStream(); - raft::resource::set_cuda_stream(handle, stream); + // 4) prepare RAFT handle & cuVS params + raft::resources handle; + cudaStream_t stream = c10::cuda::getCurrentCUDAStream(); + raft::resource::set_cuda_stream(handle, stream); - cuvs::cluster::kmeans::params params; - params.n_clusters = num_clusters; - params.init = cuvs::cluster::kmeans::params::InitMethod::Random; - params.max_iter = niter; + cuvs::cluster::kmeans::params params; + params.n_clusters = num_clusters; + params.init = cuvs::cluster::kmeans::params::InitMethod::Random; + params.max_iter = niter; - // 5) allocate centroids on GPU - Tensor cent_gpu = torch::empty({num_clusters, D}, + // 5) allocate centroids on GPU + Tensor cent_gpu = torch::empty({num_clusters, D}, torch::TensorOptions() .dtype(torch::kFloat32) .device(torch::kCUDA)) .contiguous(); - // 6) run fit on just the sample - { + // 6) run fit on just the sample + { // host scalars float inertia = 0.0f; int actual_iter= 0; @@ -72,7 +74,7 @@ shared_ptr kmeans_cuvs_sample_and_predict( auto X_view = raft::make_device_matrix_view( samp_gpu.data_ptr(), - (int)sample_size, (int)D); + (int) gpu_sample_size, (int)D); auto C_view = raft::make_device_matrix_view( cent_gpu.data_ptr(), num_clusters, (int)D); @@ -85,11 +87,11 @@ shared_ptr kmeans_cuvs_sample_and_predict( host_inertia, host_iter ); - } + } - Tensor all_labels = torch::empty({N}, torch::kLong); + Tensor all_labels = torch::empty({N}, torch::kLong); - auto predict_fn = [&](Tensor batch_cpu, int64_t off) { + auto predict_fn = [&](Tensor batch_cpu, int64_t off) { int64_t bs = batch_cpu.size(0); // allocate exactly bs labels on the GPU @@ -129,19 +131,19 @@ shared_ptr kmeans_cuvs_sample_and_predict( labels32.to(torch::kLong) .to(torch::kCPU) ); - }; + }; - // predict the sample slice - predict_fn(samp_pts, /*off=*/0); + // predict the sample slice + predict_fn(samp_pts, /*off=*/0); - // predict the rest - for (int64_t off = 0; off < N; off += gpu_batch_size) { + // predict the rest + for (int64_t off = 0; off < N; off += gpu_batch_size) { int64_t bs = std::min(gpu_batch_size, N - off); - if (off < sample_size) { - if (off + bs <= sample_size) { + if (off < gpu_sample_size) { + if (off + bs <= gpu_sample_size) { continue; } else { - int64_t overlap = sample_size - off; + int64_t overlap = gpu_sample_size - off; Tensor rest_chunk = cpu_pts.slice(0, off + overlap, off + bs); predict_fn(rest_chunk, /*off=*/off + overlap); continue; @@ -149,43 +151,43 @@ shared_ptr kmeans_cuvs_sample_and_predict( } Tensor rest_chunk = cpu_pts.slice(0, off, off + bs); predict_fn(rest_chunk, /*off=*/off); - } - // 8) group on CPU - Tensor sorted_lbl, sorted_idx; - std::tie(sorted_lbl, sorted_idx) = torch::sort(all_labels); - Tensor sorted_vecs = vectors.index_select(0, sorted_idx); - Tensor sorted_ids = ids.index_select(0, sorted_idx); - - Tensor counts = torch::bincount(sorted_lbl, /*weights=*/{}, num_clusters); - auto cnt_cpu = counts.to(torch::kCPU); - std::vector split_sizes( + } + // 8) group on CPU + Tensor sorted_lbl, sorted_idx; + std::tie(sorted_lbl, sorted_idx) = torch::sort(all_labels); + Tensor sorted_vecs = vectors.index_select(0, sorted_idx); + Tensor sorted_ids = ids.index_select(0, sorted_idx); + + Tensor counts = torch::bincount(sorted_lbl, /*weights=*/{}, num_clusters); + auto cnt_cpu = counts.to(torch::kCPU); + std::vector split_sizes( cnt_cpu.data_ptr(), cnt_cpu.data_ptr() + num_clusters - ); + ); - auto cluster_vecs = torch::split(sorted_vecs, split_sizes, 0); - auto cluster_ids = torch::split(sorted_ids, split_sizes, 0); + auto cluster_vecs = torch::split(sorted_vecs, split_sizes, 0); + auto cluster_ids = torch::split(sorted_ids, split_sizes, 0); - auto out = std::make_shared(); - out->centroids = cent_gpu.cpu().contiguous(); - out->partition_ids = torch::arange(num_clusters, torch::kLong); - out->vectors = std::move(cluster_vecs); - out->vector_ids = std::move(cluster_ids); + auto out = std::make_shared(); + out->centroids = cent_gpu.cpu().contiguous(); + out->partition_ids = torch::arange(num_clusters, torch::kLong); + out->vectors = std::move(cluster_vecs); + out->vector_ids = std::move(cluster_ids); - return out; + return out; } -// #endif +#endif shared_ptr kmeans_cpu(Tensor vectors, Tensor ids, - int n_clusters, - MetricType metric_type, - int niter, + shared_ptr build_params, Tensor /* initial_centroids */) { // Ensure enough vectors are available and sizes match. - assert(vectors.size(0) >= n_clusters * 2); + assert(vectors.size(0) >= build_params->nlist * 2); assert(vectors.size(0) == ids.size(0)); + MetricType metric_type = str_to_metric_type(build_params->metric); + // Normalize vectors for inner product if (metric_type == faiss::METRIC_INNER_PRODUCT) vectors = vectors / vectors.norm(2, 1).unsqueeze(1); @@ -200,13 +202,13 @@ shared_ptr kmeans_cpu(Tensor vectors, index_ptr = new faiss::IndexFlatL2(d); faiss::ClusteringParameters cp; - cp.niter = niter; + cp.niter = build_params->niter; - faiss::Clustering clus(d, n_clusters, cp); + faiss::Clustering clus(d, build_params->nlist, cp); clus.train(n, vectors.data_ptr(), *index_ptr); // Retrieve centroids as a torch Tensor. - Tensor centroids = torch::from_blob(clus.centroids.data(), {n_clusters, d}, torch::kFloat32).clone(); + Tensor centroids = torch::from_blob(clus.centroids.data(), {build_params->nlist, d}, torch::kFloat32).clone(); if (metric_type == faiss::METRIC_INNER_PRODUCT) centroids = centroids / centroids.norm(2, 1).unsqueeze(1); @@ -223,7 +225,7 @@ shared_ptr kmeans_cpu(Tensor vectors, Tensor sorted_ids = ids.index_select(0, sorted_indices); // Compute counts per cluster using bincount. - Tensor counts_tensor = torch::bincount(sorted_assignments, /*weights=*/{}, n_clusters); + Tensor counts_tensor = torch::bincount(sorted_assignments, /*weights=*/{}, build_params->nlist); // Ensure counts are on CPU to extract split sizes. counts_tensor = counts_tensor.to(torch::kCPU); // Convert counts tensor to std::vector @@ -234,7 +236,7 @@ shared_ptr kmeans_cpu(Tensor vectors, vector cluster_vectors = torch::split(sorted_vectors, counts_vector, 0); vector cluster_ids = torch::split(sorted_ids, counts_vector, 0); - Tensor partition_ids = torch::arange(n_clusters, torch::kInt64); + Tensor partition_ids = torch::arange(build_params->nlist, torch::kInt64); shared_ptr clustering = std::make_shared(); clustering->centroids = centroids; @@ -249,25 +251,23 @@ shared_ptr kmeans_cpu(Tensor vectors, shared_ptr kmeans(Tensor vectors, Tensor ids, - int n_clusters, - MetricType metric_type, - int niter, - bool use_gpu /*=false*/, + shared_ptr build_params, Tensor /* initial_centroids */) { - if (use_gpu) { + if (build_params->use_gpu) { #ifdef QUAKE_ENABLE_GPU - const int sample_size = std::min(1000000, vectors.size(0)); - const int gpu_batch_size = 100000; // or from build_params return kmeans_cuvs_sample_and_predict( - vectors, ids, - n_clusters, metric_type, - sample_size, niter, - gpu_batch_size); - #elif + vectors, + ids, + n_clusters, + metric_type, + build_params->gpu-sample_size, + niter, + build_params->gpu_batch_size); + #else throw std::runtime_error("GPU support is not enabled. Please compile with QUAKE_ENABLE_GPU."); #endif } else { - return kmeans_cpu(vectors, ids, n_clusters, metric_type, niter); + return kmeans_cpu(vectors, ids, build_params); } } diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index 3b738856..9e7695fd 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -412,11 +412,13 @@ shared_ptr PartitionManager::split_partitions(const Tensor &partitio for (int64_t i = 0; i < partition_ids.size(0); ++i) { // Ensure enough vectors to split assert(clustering->cluster_size(i) >= 4 && "Partition must have at least 8 vectors to split."); + shared_ptr build_params = make_shared(); + build_params->nlist = num_splits; + build_params->metric = parent_->metric_; shared_ptr curr_split_clustering = kmeans( clustering->vectors[i], clustering->vector_ids[i], - num_splits, - parent_->metric_ + build_params ); for (size_t j = 0; j < curr_split_clustering->nlist(); ++j) { diff --git a/src/cpp/src/quake_index.cpp b/src/cpp/src/quake_index.cpp index 1f7cc853..9fb6f5ff 100644 --- a/src/cpp/src/quake_index.cpp +++ b/src/cpp/src/quake_index.cpp @@ -44,10 +44,7 @@ shared_ptr QuakeIndex::build(Tensor x, Tensor ids, shared_ptr clustering = kmeans( x, ids, - build_params_->nlist, - metric_, - build_params_->niter, - build_params_->use_gpu + build_params_ ); auto e1 = std::chrono::high_resolution_clock::now(); timing_info->train_time_us = std::chrono::duration_cast(e1 - s1).count(); diff --git a/test/cpp/clustering.cpp b/test/cpp/clustering.cpp index c94cb44a..bd373ba0 100644 --- a/test/cpp/clustering.cpp +++ b/test/cpp/clustering.cpp @@ -54,8 +54,11 @@ class ClusteringTest : public ::testing::Test { // Test existing CPU kmeans TEST_F(ClusteringTest, KMeansCPU_L2) { - auto cl = kmeans_cpu(vectors_cpu, ids_cpu, num_clusters, - faiss::METRIC_L2, /*niter=*/10, torch::Tensor()); + shared_ptr build_params = std::make_shared(); + build_params->nlist = num_clusters; + build_params->metric = "l2"; + build_params->niter = 10; + auto cl = kmeans_cpu(vectors_cpu, ids_cpu, build_params, torch::Tensor()); ASSERT_EQ(cl->centroids.sizes(), (std::vector{num_clusters, dim})); int64_t tot=0; for (int i=0;i build_params = std::make_shared(); + build_params->nlist = num_clusters; + build_params->metric = "l2"; + build_params->niter = 10; + build_params->use_gpu = false; + auto cl = kmeans(vectors_cpu, ids_cpu, build_params, torch::Tensor()); ASSERT_EQ(cl->centroids.sizes(), (std::vector{num_clusters, dim})); int64_t tot=0; for (int i=0;i build_params = std::make_shared(); + build_params->nlist = num_clusters; + build_params->metric = "l2"; + build_params->niter = 10; + build_params->use_gpu = true; + build_params->gpu_sample_size = 2000; + build_params->gpu_batch_size = 100; auto cl = kmeans_cuvs_sample_and_predict( - vectors_cpu, ids_cpu, - num_clusters, - faiss::METRIC_L2, - sample_size, - niter, - gpu_batch_size); + vectors_cpu, ids_cpu, build_params); // centroids must live on CPU and have correct shape ASSERT_EQ(cl->centroids.device().type(), torch::kCPU); @@ -105,9 +111,10 @@ TEST_F(ClusteringTest, SampleAndPredict_GPU_L2) { } ASSERT_EQ(tot, num_vectors); + build_params->use_gpu = false; + // Optional quality check: rough MSE vs CPU run - auto cl_cpu = kmeans_cpu(vectors_cpu, ids_cpu, num_clusters, - faiss::METRIC_L2, niter, torch::Tensor()); + auto cl_cpu = kmeans_cpu(vectors_cpu, ids_cpu, build_params, torch::Tensor()); double mse_cpu = compute_mse(cl_cpu->centroids, cl_cpu->vectors); double mse_gpu = compute_mse(cl->centroids, cl->vectors); ASSERT_NEAR(mse_cpu, mse_gpu, mse_cpu * 0.30); @@ -115,13 +122,15 @@ TEST_F(ClusteringTest, SampleAndPredict_GPU_L2) { // Full wrapper test for GPU TEST_F(ClusteringTest, KMeansWrapper_GPU) { - const int gpu_sample = 2000; - const int gpu_iter = 3; - const int gpu_batch = 1024; + shared_ptr build_params = std::make_shared(); + build_params->nlist = num_clusters; + build_params->metric = "l2"; + build_params->niter = 10; + build_params->use_gpu = true; + build_params->gpu_sample_size = 2000; + build_params->gpu_batch_size = 100; - auto cl = kmeans(vectors_cpu, ids_cpu, num_clusters, - faiss::METRIC_L2, gpu_iter, - /*use_gpu=*/true, + auto cl = kmeans(vectors_cpu, ids_cpu, build_params, torch::Tensor()); ASSERT_EQ(cl->centroids.device().type(), torch::kCPU); ASSERT_EQ(cl->vectors.size(), size_t(num_clusters)); From 65eb128c60f8f82595e11100950b7c014b16a4ce Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 18 Apr 2025 13:21:54 -0500 Subject: [PATCH 013/323] update conda --- environments/ubuntu-cuda/conda.yaml | 4 ++++ src/cpp/src/partition_manager.cpp | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/environments/ubuntu-cuda/conda.yaml b/environments/ubuntu-cuda/conda.yaml index 715744f2..99265b48 100644 --- a/environments/ubuntu-cuda/conda.yaml +++ b/environments/ubuntu-cuda/conda.yaml @@ -3,6 +3,8 @@ channels: - pytorch - defaults - conda-forge + - nvidia + - libcuvs dependencies: - python=3.11 - numpy @@ -10,6 +12,8 @@ dependencies: - faiss-gpu - matplotlib - pytest + - libcuvs + - cuda-version=12.8 - pip - pip: - sphinx diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index 9e7695fd..c838541b 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -409,12 +409,12 @@ shared_ptr PartitionManager::split_partitions(const Tensor &partitio shared_ptr clustering = select_partitions(partition_ids); + shared_ptr build_params = make_shared(); + build_params->nlist = num_splits; + build_params->metric = metric_type_to_str(parent_->metric_); for (int64_t i = 0; i < partition_ids.size(0); ++i) { // Ensure enough vectors to split assert(clustering->cluster_size(i) >= 4 && "Partition must have at least 8 vectors to split."); - shared_ptr build_params = make_shared(); - build_params->nlist = num_splits; - build_params->metric = parent_->metric_; shared_ptr curr_split_clustering = kmeans( clustering->vectors[i], clustering->vector_ids[i], From d10cd64918db57164438f54c5e27ff5a0d9e3890 Mon Sep 17 00:00:00 2001 From: Jason Mohoney Date: Fri, 18 Apr 2025 20:12:47 +0000 Subject: [PATCH 014/323] fix gpu clustering --- src/cpp/src/clustering.cpp | 11 ++++++----- test/cpp/quake_index.cpp | 12 ++++++------ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index b5f82682..903996ea 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -26,9 +26,14 @@ shared_ptr kmeans_cuvs_sample_and_predict( int gpu_sample_size = build_params->gpu_sample_size; MetricType metric = str_to_metric_type(build_params->metric); + TORCH_CHECK(vectors.dim() == 2, "vectors must be [N,D]"); TORCH_CHECK(ids.dim() == 1, "ids must be [N]"); int64_t N = vectors.size(0), D = vectors.size(1); + + gpu_sample_size = std::min(gpu_sample_size, (int) N); + gpu_batch_size = std::min(gpu_batch_size, (int) N); + TORCH_CHECK(gpu_sample_size > 0 && gpu_sample_size <= N, "invalid sample_size"); @@ -258,11 +263,7 @@ shared_ptr kmeans(Tensor vectors, return kmeans_cuvs_sample_and_predict( vectors, ids, - n_clusters, - metric_type, - build_params->gpu-sample_size, - niter, - build_params->gpu_batch_size); + build_params); #else throw std::runtime_error("GPU support is not enabled. Please compile with QUAKE_ENABLE_GPU."); #endif diff --git a/test/cpp/quake_index.cpp b/test/cpp/quake_index.cpp index 12dd3bf0..b8f0199c 100644 --- a/test/cpp/quake_index.cpp +++ b/test/cpp/quake_index.cpp @@ -257,14 +257,14 @@ TEST(QuakeIndexStressTest, LargeBuildTest) { // Attempt to build an index with a large number of vectors. // Adjust these numbers based on your available memory/compute. int64_t dimension = 128; // Medium-high dimension - int64_t num_vectors = 10e6; // 1 million vectors + int64_t num_vectors = 1e6; // 1 million vectors auto data_vectors = generate_random_data(num_vectors, dimension); auto data_ids = generate_sequential_ids(num_vectors, 0); QuakeIndex index; auto build_params = std::make_shared(); - build_params->nlist = 5120; + build_params->nlist = 512; build_params->metric = "l2"; // Keep the iteration count modest to avoid overly long tests build_params->niter = 5; @@ -288,7 +288,7 @@ TEST(QuakeIndexStressTestGPU, LargeBuildTest) { // Attempt to build an index with a large number of vectors. // Adjust these numbers based on your available memory/compute. int64_t dimension = 128; // Medium-high dimension - int64_t num_vectors = 10e6; // 1 million vectors + int64_t num_vectors = 1e6; // 1 million vectors auto data_vectors = generate_random_data(num_vectors, dimension).contiguous(); auto data_ids = generate_sequential_ids(num_vectors, 0).contiguous(); @@ -297,7 +297,7 @@ TEST(QuakeIndexStressTestGPU, LargeBuildTest) { std::cout << "generated\n"; auto build_params = std::make_shared(); - build_params->nlist = 5120; + build_params->nlist = 512; build_params->metric = "l2"; build_params->use_gpu = true; // Keep the iteration count modest to avoid overly long tests @@ -533,8 +533,8 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { // Test build with GPU enabled TEST(QuakeIndexGPUTest, BuildWithGPUTest) { int64_t dimension = 32; - int64_t num_vectors = 200; - int64_t nlist = 5; + int64_t num_vectors = 10000; + int64_t nlist = 10; torch::Tensor data_vectors = generate_random_data(num_vectors, dimension); torch::Tensor data_ids = generate_sequential_ids(num_vectors, 0); From b8b714e2cf17f30a4f245b1c0808c22f38705646 Mon Sep 17 00:00:00 2001 From: Kefan Zheng Date: Sun, 20 Apr 2025 18:22:33 -0500 Subject: [PATCH 015/323] adapt cuvs to cuda 12.4 (#61) * adapt cuvs to cuda 12.4 * separate compilation scripts for cuda118 and cuda124 --- .../Dockerfile | 0 .../conda.yaml | 0 environments/ubuntu-cuda124/Dockerfile | 64 +++++++++++++++++++ environments/ubuntu-cuda124/conda.yaml | 24 +++++++ 4 files changed, 88 insertions(+) rename environments/{ubuntu-cuda => ubuntu-cuda118}/Dockerfile (100%) rename environments/{ubuntu-cuda => ubuntu-cuda118}/conda.yaml (100%) create mode 100644 environments/ubuntu-cuda124/Dockerfile create mode 100644 environments/ubuntu-cuda124/conda.yaml diff --git a/environments/ubuntu-cuda/Dockerfile b/environments/ubuntu-cuda118/Dockerfile similarity index 100% rename from environments/ubuntu-cuda/Dockerfile rename to environments/ubuntu-cuda118/Dockerfile diff --git a/environments/ubuntu-cuda/conda.yaml b/environments/ubuntu-cuda118/conda.yaml similarity index 100% rename from environments/ubuntu-cuda/conda.yaml rename to environments/ubuntu-cuda118/conda.yaml diff --git a/environments/ubuntu-cuda124/Dockerfile b/environments/ubuntu-cuda124/Dockerfile new file mode 100644 index 00000000..0462c5c9 --- /dev/null +++ b/environments/ubuntu-cuda124/Dockerfile @@ -0,0 +1,64 @@ +# Use a CUDA-enabled Ubuntu base image +FROM nvidia/cuda:12.4.1-cudnn-devel-ubuntu22.04 + +# ----------------------------- +# Set up environment variables +# ----------------------------- +ENV CONDA_DIR=/opt/miniconda +ENV PATH="${CONDA_DIR}/bin:${PATH}" +ENV DEBIAN_FRONTEND=noninteractive + +# ----------------------------- +# Install system dependencies +# ----------------------------- +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + wget \ + curl \ + build-essential \ + ca-certificates \ + swig \ + git \ + libomp5 \ + libomp-dev \ + graphviz \ + libnuma-dev \ + && rm -rf /var/lib/apt/lists/* + + +# Install CMake 3.24.2 +RUN wget -qO /tmp/cmake.sh https://github.com/Kitware/CMake/releases/download/v3.30.4/cmake-3.30.4-linux-x86_64.sh && \ + chmod +x /tmp/cmake.sh && \ + /tmp/cmake.sh --skip-license --prefix=/usr/local && \ + rm /tmp/cmake.sh + + +# ----------------------------- +# Install Miniconda +# ----------------------------- +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && \ + bash /tmp/miniconda.sh -b -p $CONDA_DIR && \ + rm /tmp/miniconda.sh + +# ----------------------------- +# Copy in your conda environment YAML +# ----------------------------- +COPY environments/ubuntu-cuda/conda.yaml /tmp/conda.yaml + +# Create quake-env +RUN conda env create -f /tmp/conda.yaml && conda clean -afy + +# ----------------------------- +# Install GPU-enabled PyTorch +# ----------------------------- +RUN conda run -n quake-env pip install --no-cache-dir torch --index-url https://download.pytorch.org/whl/cu124 + +# ----------------------------- +# Debug: show conda information +# ----------------------------- +RUN echo "===== DEBUG: which conda =====" && which conda +RUN echo "===== DEBUG: conda info =====" && conda info +RUN echo "===== DEBUG: conda env list =====" && conda env list +RUN echo "===== DEBUG: quake-env check =====" && conda run -n quake-env python -c "import sys; print('OK in quake-env; python:', sys.executable)" + +CMD ["/bin/bash"] \ No newline at end of file diff --git a/environments/ubuntu-cuda124/conda.yaml b/environments/ubuntu-cuda124/conda.yaml new file mode 100644 index 00000000..f895341b --- /dev/null +++ b/environments/ubuntu-cuda124/conda.yaml @@ -0,0 +1,24 @@ +name: quake-env +channels: + - rapidsai + - pytorch + - defaults + - conda-forge + - nvidia +dependencies: + - python=3.11 + - numpy + - pandas + - faiss-gpu + - matplotlib + - pytest + - libcuvs + - cuda-nvrtc-dev=12.4 + - cuda-version=12.4 + - pip + - pip: + - sphinx + - sphinx_rtd_theme + - sphinxcontrib-mermaid + - graphviz + - pyyaml \ No newline at end of file From 741bd0362f6e97dc291741d77b7854a04ca8f4d0 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 21 Apr 2025 13:05:47 -0500 Subject: [PATCH 016/323] prepare camera ready experiments --- test/experiments/osdi2025/ablation/run.py | 2 ++ test/experiments/osdi2025/aps_recall_targets/run.py | 2 ++ test/experiments/osdi2025/early_termination/run.py | 2 ++ test/experiments/osdi2025/experiment_runner.py | 5 +++++ test/experiments/osdi2025/measure_wiki_skew_and_perf/run.py | 2 ++ test/experiments/osdi2025/multi_level/run.py | 2 ++ test/experiments/osdi2025/numa_single_query/run.py | 2 ++ test/experiments/osdi2025/workload_comparison/run.py | 2 ++ 8 files changed, 19 insertions(+) create mode 100644 test/experiments/osdi2025/ablation/run.py create mode 100644 test/experiments/osdi2025/aps_recall_targets/run.py create mode 100644 test/experiments/osdi2025/early_termination/run.py create mode 100644 test/experiments/osdi2025/experiment_runner.py create mode 100644 test/experiments/osdi2025/measure_wiki_skew_and_perf/run.py create mode 100644 test/experiments/osdi2025/multi_level/run.py create mode 100644 test/experiments/osdi2025/numa_single_query/run.py create mode 100644 test/experiments/osdi2025/workload_comparison/run.py diff --git a/test/experiments/osdi2025/ablation/run.py b/test/experiments/osdi2025/ablation/run.py new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/test/experiments/osdi2025/ablation/run.py @@ -0,0 +1,2 @@ + + diff --git a/test/experiments/osdi2025/aps_recall_targets/run.py b/test/experiments/osdi2025/aps_recall_targets/run.py new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/test/experiments/osdi2025/aps_recall_targets/run.py @@ -0,0 +1,2 @@ + + diff --git a/test/experiments/osdi2025/early_termination/run.py b/test/experiments/osdi2025/early_termination/run.py new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/test/experiments/osdi2025/early_termination/run.py @@ -0,0 +1,2 @@ + + diff --git a/test/experiments/osdi2025/experiment_runner.py b/test/experiments/osdi2025/experiment_runner.py new file mode 100644 index 00000000..97eaea67 --- /dev/null +++ b/test/experiments/osdi2025/experiment_runner.py @@ -0,0 +1,5 @@ + + +EXPERIMENTS_LIST = { + "numa_single_query" +} \ No newline at end of file diff --git a/test/experiments/osdi2025/measure_wiki_skew_and_perf/run.py b/test/experiments/osdi2025/measure_wiki_skew_and_perf/run.py new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/test/experiments/osdi2025/measure_wiki_skew_and_perf/run.py @@ -0,0 +1,2 @@ + + diff --git a/test/experiments/osdi2025/multi_level/run.py b/test/experiments/osdi2025/multi_level/run.py new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/test/experiments/osdi2025/multi_level/run.py @@ -0,0 +1,2 @@ + + diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -0,0 +1,2 @@ + + diff --git a/test/experiments/osdi2025/workload_comparison/run.py b/test/experiments/osdi2025/workload_comparison/run.py new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/test/experiments/osdi2025/workload_comparison/run.py @@ -0,0 +1,2 @@ + + From 73b3901b73886c4360a32cb402760a0410a6e37d Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 22 Apr 2025 14:01:36 -0500 Subject: [PATCH 017/323] add numa multi and single query experiment --- test/__init__.py | 0 test/experiments/__init__.py | 0 test/experiments/osdi2025/__init__.py | 0 .../experiments/osdi2025/experiment_runner.py | 63 +++++- .../osdi2025/numa_multi_query/__init__.py | 0 .../numa_multi_query/configs/sift1m.yaml | 18 ++ .../osdi2025/numa_multi_query/run.py | 186 ++++++++++++++++++ .../osdi2025/numa_single_query/__init__.py | 0 .../numa_single_query/configs/sift1m.yaml | 15 ++ .../osdi2025/numa_single_query/run.py | 115 +++++++++++ 10 files changed, 394 insertions(+), 3 deletions(-) create mode 100644 test/__init__.py create mode 100644 test/experiments/__init__.py create mode 100644 test/experiments/osdi2025/__init__.py create mode 100644 test/experiments/osdi2025/numa_multi_query/__init__.py create mode 100644 test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml create mode 100644 test/experiments/osdi2025/numa_multi_query/run.py create mode 100644 test/experiments/osdi2025/numa_single_query/__init__.py create mode 100644 test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/experiments/__init__.py b/test/experiments/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/experiments/osdi2025/__init__.py b/test/experiments/osdi2025/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/experiments/osdi2025/experiment_runner.py b/test/experiments/osdi2025/experiment_runner.py index 97eaea67..fd3a02cf 100644 --- a/test/experiments/osdi2025/experiment_runner.py +++ b/test/experiments/osdi2025/experiment_runner.py @@ -1,5 +1,62 @@ +#!/usr/bin/env python +""" +Master runner for OSDI2025 vector‐search experiments. +Usage: + python -m test.experiments.osdi2025.experiment_runner \ + --experiment \ + --config \ + --output-dir +""" -EXPERIMENTS_LIST = { - "numa_single_query" -} \ No newline at end of file +import argparse +from pathlib import Path + +# Make sure `test/`, `test/experiments/`, and subfolders all have an __init__.py +from test.experiments.osdi2025.numa_single_query.run import run_experiment as run_numa_single +from test.experiments.osdi2025.numa_multi_query.run import run_experiment as run_numa_multi + +EXPERIMENTS = { + "numa_single_query": run_numa_single, + "numa_multi_query": run_numa_multi, +} + +def main(): + parser = argparse.ArgumentParser( + description="Run one OSDI2025 experiment" + ) + parser.add_argument( + "-x", "--experiment", + choices=EXPERIMENTS.keys(), + required=True, + help="Which experiment to run" + ) + parser.add_argument( + "-c", "--config", + required=True, + help="Config name (without .yaml) under configs/" + ) + parser.add_argument( + "-o", "--output-dir", + default=None, + help="Where to write results (csv + plots)" + ) + args = parser.parse_args() + + exp = args.experiment + cfg_name = args.config + base = Path(__file__).resolve().parent + cfg_path = base / exp / "configs" / f"{cfg_name}.yaml" + if not cfg_path.is_file(): + raise FileNotFoundError(f"Missing config: {cfg_path}") + + # compute output directory + out_dir = Path(args.output_dir) if args.output_dir else base / exp / "results" / cfg_name + out_dir.mkdir(parents=True, exist_ok=True) + + # call the appropriate experiment + runner = EXPERIMENTS[exp] + runner(str(cfg_path), str(out_dir)) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/test/experiments/osdi2025/numa_multi_query/__init__.py b/test/experiments/osdi2025/numa_multi_query/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml new file mode 100644 index 00000000..b6b5b768 --- /dev/null +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -0,0 +1,18 @@ +# existing keys... +dataset: + name: sift1m + num_queries: 10000 + k: 10 + nprobe: 10 + +#n_workers: [0,1,2,4,8,16] +#batch_sizes: [1, 10, 100, 100] +n_workers: [1, 2, 4, 8, 16] +batch_sizes: [1, 10, 100, 1000, 10000] + +# new keys: +trials: 5 +warmup: 10 + +output: + results_csv: numa_multi_query_results.csv \ No newline at end of file diff --git a/test/experiments/osdi2025/numa_multi_query/run.py b/test/experiments/osdi2025/numa_multi_query/run.py new file mode 100644 index 00000000..12b95b30 --- /dev/null +++ b/test/experiments/osdi2025/numa_multi_query/run.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python3 +""" +NUMA multi‐query QPS experiment for Quake. + +Sweeps NUMA on/off, worker counts, batched_scan on/off, and batch sizes; +records mean/std QPS and produces a simplified batched_scan QPS plot. +""" + +import yaml +import time +import numpy as np +import torch +import pandas as pd +import matplotlib.pyplot as plt +from pathlib import Path + +from quake.datasets.ann_datasets import load_dataset +from quake.index_wrappers.quake import QuakeWrapper + +def run_experiment(cfg_path: str, output_dir: str): + cfg = yaml.safe_load(Path(cfg_path).read_text()) + out = Path(output_dir) + out.mkdir(exist_ok=True, parents=True) + csv_name = cfg.get("output", {}).get("results_csv", "results.csv") + out_csv = out / csv_name + + # check if the results already exist + if not Path(out_csv).exists(): + + # Load config + ds = cfg["dataset"] + n_workers = cfg["n_workers"] + batched_opts= cfg.get("batch_options", [False, True]) + batch_sizes = cfg.get("batch_sizes", [ds["num_queries"]]) + num_q = ds["num_queries"] + k = ds["k"] + nprobe = ds["nprobe"] + trials = cfg.get("trials", 5) + warmup = cfg.get("warmup", 2) + + + # Load data + print(f"Loading {ds['name']} ({num_q} queries)…") + base_vecs, queries_data, _ = load_dataset(ds["name"]) + queries = ( + torch.from_numpy(queries_data[:num_q]).float() + if isinstance(queries_data, np.ndarray) + else queries_data[:num_q].float() + ) + + # Build index if needed + idx_file = out / "quake_index.bin" + if not idx_file.exists(): + print("Building index…") + builder = QuakeWrapper() + vecs = ( + torch.from_numpy(base_vecs).float() + if isinstance(base_vecs, np.ndarray) + else base_vecs.float() + ) + nc = int(np.sqrt(vecs.shape[0])) + builder.build(vecs, nc=nc, metric="l2", num_workers=0) + builder.save(str(idx_file)) + print("Index saved.") + + records = [] + for use_numa in [False]: + for nw in n_workers: + for bs in batched_opts: + for batch_size in batch_sizes: + print(f"NUMA={use_numa}, workers={nw}, batched={bs}, batch={batch_size}") + idxm = QuakeWrapper() + idxm.load(str(idx_file), use_numa=use_numa, same_core=True, n_workers=nw) + n_threads = 16 if nw == 0 else 1 + + # Warmup + for _ in range(min(warmup,1)): + if bs: + for i in range(0, num_q, batch_size): + idxm.search(queries[i:i+batch_size], k, + batched_scan=bs, + nprobe=nprobe, + n_threads=n_threads) + else: + idxm.search(queries, k, + batched_scan=bs, + nprobe=nprobe, + n_threads=n_threads) + + # Trials → QPS + qps_vals = [] + for t in range(trials): + start = time.time() + if bs: + for i in range(0, num_q, batch_size): + idxm.search(queries[i:i+batch_size], k, + batched_scan=bs, + nprobe=nprobe, + n_threads=n_threads) + else: + idxm.search(queries, k, + batched_scan=bs, + nprobe=nprobe, + n_threads=n_threads) + elapsed = time.time() - start + qps_vals.append(num_q / elapsed) + print(f" Trial {t+1}/{trials}: {qps_vals[-1]:.1f} QPS") + + records.append({ + "numa_enabled": use_numa, + "n_worker": nw, + "batched_scan": bs, + "batch_size": batch_size, + "mean_qps": np.mean(qps_vals), + "std_qps": np.std(qps_vals), + }) + + # Save CSV + df = pd.DataFrame(records) + df.to_csv(out_csv, index=False) + print(f"Results → {out_csv}") + + df = pd.read_csv(out_csv) + + # Simplified batched_scan QPS plot + fig, ax = plt.subplots(1, 1, figsize=(12, 4)) + for bsz in sorted(df["batch_size"].unique()): + for bs in (False, True): + grp = df[(df["batch_size"] == bsz) & (df["batched_scan"] == bs)] + if grp.empty: + continue + linestyle = '-' if not bs else '--' + label = f"batch={bsz}" + ("" if not bs else " batched") + ax.plot( + grp["n_worker"], + grp["mean_qps"], + marker='o', + linestyle=linestyle, + label=label + ) + ax.set_xscale("symlog", base=2) + ax.set_yscale("log", base=2) + ax.set_xlabel("Workers") + ax.set_ylabel("QPS") + ax.legend(title="Config", fontsize="small") + + fig.suptitle("QPS vs. Workers (solid=regular, dashed=batched)") + fig.tight_layout(rect=[0, 0, 1, 0.92]) + plot_path = out / f"{out_csv.stem}_combined_qps.png" + fig.savefig(plot_path) + print(f"Combined plot saved to {plot_path}") + + # 7) QPS vs. batch size for 1 and 16 workers, solid=unbatched, dashed=batched + fig2, ax2 = plt.subplots(1, 1, figsize=(6, 4)) + + # choose which workers to show + workers = [1, 16] + # matplotlib will auto‑cycle colors for each worker + for w in workers: + for bs, ls in [(False, "-"), (True, "--")]: + sub = df[(df["n_worker"] == w) & (df["batched_scan"] == bs)] + if sub.empty: + continue + sub = sub.sort_values("batch_size") + label = f"{w} worker{'s' if w>1 else ''}" + (" (batched)" if bs else "") + ax2.errorbar( + sub["batch_size"], + sub["mean_qps"], + yerr=sub["std_qps"], + marker="o", + linestyle=ls, + capsize=4, + label=label + ) + + ax2.set_xscale("symlog", base=2) + ax2.set_yscale("log", base=2) + ax2.set_xlabel("Batch Size") + ax2.set_ylabel("QPS") + ax2.set_title("QPS vs. Batch Size\n(solid=unbatched, dashed=batched)") + ax2.grid(True, which="both", ls=":") + ax2.legend(title="Configuration", fontsize="small", ncol=1) + fig2.tight_layout() + plot2_path = out / f"{out_csv.stem}_qps_vs_batchsize_full.png" + fig2.savefig(plot2_path) + print(f"Full batch‑size QPS plot saved to {plot2_path}") \ No newline at end of file diff --git a/test/experiments/osdi2025/numa_single_query/__init__.py b/test/experiments/osdi2025/numa_single_query/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml new file mode 100644 index 00000000..327e20ba --- /dev/null +++ b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml @@ -0,0 +1,15 @@ +# existing keys... +dataset: + name: sift1m + num_queries: 100 + k: 10 + nprobe: 100 + +n_workers: [0,1,2,4,8,16] + +# new keys: +trials: 5 +warmup: 10 + +output: + results_csv: numa_single_query_results.csv \ No newline at end of file diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index 139597f9..f88c56c8 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -1,2 +1,117 @@ +#!/usr/bin/env python +""" +NUMA single‑query latency experiment for Quake. +Reads a config.yaml, writes results.csv to output_dir, then plots +thread‑vs‑latency with error bars for NUMA/no‑NUMA. +""" +import yaml +import numpy as np +import torch +import pandas as pd +import matplotlib.pyplot as plt +from pathlib import Path +from quake.datasets.ann_datasets import load_dataset +from quake.index_wrappers.quake import QuakeWrapper + +def run_experiment(cfg_path: str, output_dir: str): + # 1) Load config + cfg = yaml.safe_load(Path(cfg_path).read_text()) + ds = cfg["dataset"] + n_workers = cfg["n_workers"] + nprobe = ds["nprobe"] + k = ds["k"] + num_q = ds["num_queries"] + trials = cfg.get("trials", 5) # default 5 + warmup = cfg.get("warmup", 10) # default 10 + csv_name = cfg.get("output", {}).get("results_csv", "numa_results.csv") + + out_dir = Path(output_dir); out_dir.mkdir(parents=True, exist_ok=True) + + # 2) Load data + print(f"Loading dataset '{ds['name']}'...") + base_vecs, queries, _ = load_dataset(ds["name"]) + queries = queries[:num_q] + + # 3) Build index once + idx_file = out_dir / "quake_index.bin" + if not idx_file.exists(): + print("Building Quake index...") + idx = QuakeWrapper() + nc = int(np.sqrt(base_vecs.shape[0])) + idx.build(base_vecs, nc=nc, metric="l2", num_workers=0) + idx.save(str(idx_file)) + print(f"Index saved at {idx_file}") + + + # 4) Benchmark: warmup + trials + rows = [] + for use_numa in [False, True]: + mode = "NUMA" if use_numa else "no‑NUMA" + print(f"\n--- {mode} benchmarking ---") + + for n_worker in n_workers: + + idx_mode = QuakeWrapper() + idx_mode.load(str(idx_file), use_numa=use_numa, same_core=True, n_workers=n_worker) + + print(f"Threads: {n_worker}") + # warm‑up + for i in range(min(warmup, len(queries))): + q = queries[i].unsqueeze(0).float() + idx_mode.search(q, k, batched_scan=False, nprobe=nprobe, n_threads=n_worker) + + trial_means = [] + for t in range(trials): + lats = [] + for q_vec in queries: + q = q_vec.unsqueeze(0).float() + res = idx_mode.search( + q, k, + batched_scan=False, + nprobe=nprobe, + ) + ti = res.timing_info + lats.append(ti.total_time_ns / 1e6) + mean_t = float(np.mean(lats)) + trial_means.append(mean_t) + print(f" Trial {t+1}/{trials}: {mean_t:.2f} ms") + + mean_lat = float(np.mean(trial_means)) + std_lat = float(np.std(trial_means)) + rows.append({ + "numa_enabled": use_numa, + "n_worker": n_worker, + "mean_latency_ms": mean_lat, + "std_latency_ms": std_lat, + }) + + # 5) Save CSV + df = pd.DataFrame(rows) + out_csv = out_dir / csv_name + df.to_csv(out_csv, index=False) + print(f"\nResults written to {out_csv}") + + # 6) Plot with error bars + plt.figure() + for flag in df["numa_enabled"].unique(): + subset = df[df["numa_enabled"] == flag] + label = "NUMA" if flag else "no‑NUMA" + plt.errorbar( + subset["n_worker"], + subset["mean_latency_ms"], + yerr=subset["std_latency_ms"], + marker="o", + capsize=5, + label=label + ) + plt.xscale("symlog", base=2) + plt.xlabel("Num Workers") + plt.ylabel("Mean Latency (ms)") + plt.title("NUMA Single‑Query Latency") + plt.legend() + plot_file = out_dir / f"{out_csv.stem}_latency.png" + plt.tight_layout() + plt.savefig(plot_file) + print(f"Plot saved to {plot_file}") \ No newline at end of file From 6ec69a33c56a4614986e92cd2c944effaef87a4b Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 3 May 2025 13:26:08 -0500 Subject: [PATCH 018/323] Add map for fast centroid lookups --- src/cpp/include/common.h | 8 + src/cpp/include/dynamic_inverted_list.h | 16 + src/cpp/include/geometry.h | 728 +++++++++++++++--- src/cpp/include/index_partition.h | 2 +- src/cpp/include/list_scanning.h | 5 + src/cpp/include/maintenance_policies.h | 1 - src/cpp/include/parallel.h | 39 +- src/cpp/src/dynamic_inverted_list.cpp | 248 +++--- src/cpp/src/index_partition.cpp | 36 +- src/cpp/src/partition_manager.cpp | 2 + src/cpp/src/query_coordinator.cpp | 48 +- src/python/datasets/ann_datasets.py | 48 +- src/python/workload_generator.py | 5 +- test/cpp/benchmark.cpp | 154 +++- test/cpp/dynamic_inverted_list.cpp | 130 ++++ test/cpp/quake_index.cpp | 53 +- test/experiments/osdi2025/README.md | 57 ++ .../aps_recall_targets/configs/sift1m.yaml | 28 + .../osdi2025/aps_recall_targets/run.py | 180 +++++ .../experiments/osdi2025/experiment_runner.py | 58 +- .../osdi2025/kick_the_tires/run.py | 95 +++ 21 files changed, 1601 insertions(+), 340 deletions(-) create mode 100644 test/experiments/osdi2025/README.md create mode 100644 test/experiments/osdi2025/aps_recall_targets/configs/sift1m.yaml create mode 100644 test/experiments/osdi2025/kick_the_tires/run.py diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index 0938591c..eba6dc3a 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -180,6 +180,14 @@ struct SearchParams { float initial_search_fraction = DEFAULT_INITIAL_SEARCH_FRACTION; int aps_flush_period_us = DEFAULT_APS_FLUSH_PERIOD_US; + // early termination params + float spann_threshold = 1.25f; // prune all centroids with distance > 1.25 * min_distance + + float auncel_a = 0.5f; // auncel's parameter + float auncel_b = 0.5f; // auncel's parameter + + + SearchParams() = default; }; diff --git a/src/cpp/include/dynamic_inverted_list.h b/src/cpp/include/dynamic_inverted_list.h index e940127e..e8d67627 100644 --- a/src/cpp/include/dynamic_inverted_list.h +++ b/src/cpp/include/dynamic_inverted_list.h @@ -31,6 +31,7 @@ namespace faiss { int d_; ///< Dimensionality of the vectors (derived from code_size). int code_size_; ///< Size in bytes of each vector code. unordered_map> partitions_; ///< Map of partition ID to IndexPartition. + unordered_map> id_to_location_; /** * @brief Constructor for DynamicInvertedLists. @@ -83,6 +84,8 @@ namespace faiss { */ const idx_t* get_ids(size_t list_no) const override; + void build_map(); + /** * @brief Release the codes pointer. * @@ -325,6 +328,19 @@ namespace faiss { * @return A 1D tensor containing all partition IDs. */ Tensor get_partition_ids(); + + template + inline void map_add(IndexPartition* p, int64_t off, IdT id) noexcept { + id_to_location_[id] = {p, off}; + } + template + inline void map_erase(IdT id) noexcept { + id_to_location_.erase(id); + } + template + inline void map_swap(IndexPartition* p, int64_t off, IdT id) noexcept { + id_to_location_[id] = {p, off}; + } }; /** diff --git a/src/cpp/include/geometry.h b/src/cpp/include/geometry.h index e16eafc6..5573082e 100644 --- a/src/cpp/include/geometry.h +++ b/src/cpp/include/geometry.h @@ -8,6 +8,7 @@ #define STOP 1.0e-8 #define TINY 1.0e-30 +#define CRP_CHECK(cond, msg) ((void)0) using torch::Tensor; using std::vector; @@ -54,62 +55,46 @@ inline void print_array(const float *array, int dimension) { std::cout << std::endl << std::endl; } -inline vector compute_boundary_distances(const Tensor &query, vector centroids, bool euclidean = true) { - - auto start = std::chrono::high_resolution_clock::now(); - int dimension = query.size(0); +inline std::vector +compute_boundary_distances(const torch::Tensor& query, + std::vector& centroids, + bool euclidean /* kept for API */ ) +{ + int dim = query.size(0); + const float* q = query.data_ptr(); + + /* --- ensure centroids[0] is the nearest --------------------- */ + size_t nearest = 0; + float best_d2 = std::numeric_limits::max(); + for (size_t i = 0; i < centroids.size(); ++i) { + float d2 = faiss::fvec_L2sqr(q, centroids[i], dim); + if (d2 < best_d2) { best_d2 = d2; nearest = i; } + } + if (nearest != 0) std::swap(centroids[0], centroids[nearest]); - std::vector boundary_distances(centroids.size(), -1.0f); + const float* c0 = centroids[0]; + std::vector d(centroids.size(), 0.0f); + std::vector v(dim); - const float *query_ptr = query.data_ptr(); - const float *nearest_centroid_ptr = centroids[0]; + for (size_t j = 1; j < centroids.size(); ++j) + { + const float* cj = centroids[j]; - vector line_vector(dimension); - vector midpoint(dimension); - vector residual(dimension); + /* v = cj - c0, ||v|| */ + faiss::fvec_sub(dim, cj, c0, v.data()); + float v_norm = std::sqrt( + faiss::fvec_inner_product(v.data(), v.data(), dim)); - auto end = std::chrono::high_resolution_clock::now(); + /* b = ½ (||cj||² - ||c0||²) */ + float b = 0.5f * ( + faiss::fvec_inner_product(cj, cj, dim) - + faiss::fvec_inner_product(c0, c0, dim)); - // used for euclidean distance - if (euclidean) { - // Compute residual: r = q - c0. - faiss::fvec_sub(dimension, query_ptr, nearest_centroid_ptr, residual.data()); - - // For each centroid j (starting at index 1). - for (int j = 1; j < centroids.size(); j++) { - // Compute v = c_j - c0. - const float* c_j = centroids[j]; - faiss::fvec_sub(dimension, c_j, nearest_centroid_ptr, line_vector.data()); - - // Compute squared norm: A2 = ||v||^2. - float A2 = faiss::fvec_inner_product(line_vector.data(), line_vector.data(), dimension); - float A = std::sqrt(A2); // Guaranteed nonzero. - - // Compute dot product: dot = . - float dot_val = faiss::fvec_inner_product(residual.data(), line_vector.data(), dimension); - - // Instead of computing dot_val/A and 0.5*A separately, - // we compute: d = |dot_val - 0.5 * A2| / A. - float d = std::fabs(dot_val - 0.5f * A2) / A; - boundary_distances[j] = d; - } - } else { - // for dot product distance - float residual_angle = faiss::fvec_inner_product(query_ptr, nearest_centroid_ptr, dimension); - for (int j = 1; j < centroids.size(); j++) { - // get angle of the bisector using dot product - subtract_arrays(centroids[j], nearest_centroid_ptr, line_vector.data(), dimension); - divide_array_by_constant(line_vector.data(), 2.0f, midpoint.data(), dimension); - add_arrays(nearest_centroid_ptr, midpoint.data(), midpoint.data(), dimension); - float norm = faiss::fvec_inner_product(midpoint.data(), midpoint.data(), dimension); - norm = std::sqrt(norm); - divide_array_by_constant(midpoint.data(), norm, midpoint.data(), dimension); - float boundary_angle = faiss::fvec_inner_product(query_ptr, midpoint.data(), dimension); - boundary_distances[j] = std::acos(boundary_angle); - } + /* signed distance (q·v − b) / ||v|| */ + float dot_qv = faiss::fvec_inner_product(q, v.data(), dim); + d[j] = std::fabs(dot_qv - b) / v_norm; // plane distance } - - return boundary_distances; + return d; // d[0] = 0 } inline double incomplete_beta(double a, double b, double x) { @@ -252,7 +237,7 @@ inline double log_hyperspherical_cap_volume(double radius, double boundary_dista h = std::max(0.0, std::min(2 * radius, h)); if (euclidean) { - double x = std::sqrt((2 * radius * h - h * h) / (radius * radius)); + double x = pow((2 * radius * h - h * h) / (radius * radius), 1.0); // use precomputed incomplete beta function double inc_beta; if (use_precomputed) { @@ -342,70 +327,619 @@ inline Tensor compute_variance_in_direction_of_query(Tensor query, Tensor centro return torch::tensor(variances).clone(); } -inline vector compute_recall_profile(vector boundary_distances, float query_radius, int dimension, - vector partition_sizes = {}, bool use_precomputed = true, - bool euclidean = true) { +inline void check_boundary_distances(const float* q, + const std::vector& C, + const std::vector& d, + int dim) +{ + const float* c0 = C[0]; + std::vector v(dim); + + for (size_t j = 1; j < C.size(); ++j) { + const float* cj = C[j]; + + /* signed distance via the explicit formula again */ + faiss::fvec_sub(dim, cj, c0, v.data()); + float vnorm = std::sqrt(faiss::fvec_inner_product(v.data(), v.data(), dim)); + float b = 0.5f*(faiss::fvec_inner_product(cj,cj,dim) + -faiss::fvec_inner_product(c0,c0,dim)); + float dj = std::fabs(faiss::fvec_inner_product(q, v.data(), dim) - b) / vnorm; + + if (std::fabs(dj - d[j]) > 0.01f * dj + 1e-6f) + throw std::runtime_error( + "boundary_distances[" + std::to_string(j) + "] inaccurate"); + } +} - // boundary_distances shape is (num_partitions,) and num_partitions must be greater than 1 - if (boundary_distances.size() < 2) { - throw std::runtime_error("Boundary distances must have at least 2 partitions to create an estimate."); +inline std::vector +compute_recall_profile(const std::vector& boundary_distances, + float query_radius, + int dimension, + std::vector partition_sizes = {}, // Unused in these models + bool use_precomputed = true, + bool euclidean = true) // Unused in these models +{ + // --- Configuration Flag --- + // 0: Original Scaled-IE (reconstructed, uses norm_vols internally) + // 1: Direct Proportional Allocation (P'_k = raw_vols[k]) + // 2: Independent Entry Allocation (P'_k = raw_vols[k]*P0 / (1-raw_vols[k])) + // 3: Concentration Penalized Allocation (P'_k = raw_vols[k] * (1-S2_norm)) + // 4: Radius-Difference Weighting (P'_k = raw_vols[k] * (R-d_k)) + // 5: Simplified IE Approx Weighting (P'_k = raw_vols[k] * (1 - 0.5*S1 + 0.5*v_k)) + const int method_flag = 0; // <<< CHANGE THIS FLAG FOR ABLATION STUDY >>> + // --- + + const int m = static_cast(boundary_distances.size()); + const float eps = 1e-9f; + + // --- Edge Cases --- + if (m <= 1) { + if (m == 1) return {1.0f}; // Only the central partition exists + return {}; // No partitions defined + } + if (query_radius <= eps) { + std::vector p(m, 0.0f); + p[0] = 1.0f; // Query point is exactly at origin, must be in partition 0 + return p; } - int num_partitions = boundary_distances.size(); - vector partition_probabilities(num_partitions, 0.0f); + // --- Step 1: Compute Raw Cap Volumes (Common to all methods) --- + std::vector raw_vols(m, 0.0f); + for (int j = 1; j < m; ++j) { + // Ensure boundary distance is non-negative double + double d = std::max(0.0, static_cast(boundary_distances[j])); + // If boundary is outside or on the query radius, the cap volume is 0 + if (d >= query_radius) continue; + + // Calculate x for incomplete beta function + double x = 1.0 - (d / query_radius) * (d / query_radius); + x = std::clamp(x, 0.0, 1.0); // Clamp x to [0, 1] + + // Incomplete Beta parameters + double a = 0.5 * (dimension + 1.0); + double b = 0.5; + double I = use_precomputed + ? incomplete_beta_lookup(x, dimension) // Needs definition + : incomplete_beta(a, b, x); // Needs definition + + // Raw volume is half the normalized surface area ratio, clamped to [0, 0.5] + raw_vols[j] = static_cast(std::clamp(0.5 * I, 0.0, 0.5)); + } - double total_volume = 0.0; - bool weigh_using_partition_sizes = partition_sizes.size() == num_partitions; + // --- Method Selection --- + float P0 = 0.0f; // Root cell probability + std::vector P_prime(m, 0.0f); // Intermediate neighbor probabilities (k>=1) + float P_prime_sum = 0.0f; // Sum of P_prime[k] for k>=1 + + switch (method_flag) { + case 0: { // M0: Original Scaled-IE (reconstructed) + //std::cout << "Using Method 0: Original Scaled-IE (Cumulative)" << std::endl; + // Uses intermediate normalization and P0 based on normalized vols + std::vector norm_vols = raw_vols; // Copy raw vols + float S1_for_norm = 0.0f; + for (int j = 1; j < m; ++j) S1_for_norm += norm_vols[j]; + + if (S1_for_norm > eps) { + for (int j = 1; j < m; ++j) norm_vols[j] /= S1_for_norm; + } else { + for (int j = 1; j < m; ++j) norm_vols[j] = 0.0f; + } + + // Calculate P0 using normalized vols (as per original logic) + P0 = 1.0f; + for (int j = 1; j < m; ++j) { + P0 *= (1.0f - norm_vols[j]); + } + P0 = std::clamp(P0, 0.0f, 1.0f); + + // Calculate P_prime using cumulative S1, S2 on normalized vols + float S1_cum = 0.0f, S2_cum = 0.0f; + // Use lambda = m as per original code's default, or allow tuning + float lambda = static_cast(m); // Could be tuned here if needed + + for (int k = 1; k < m; ++k) { + S1_cum += norm_vols[k]; // Update cumulative sums *before* using them for k + S2_cum += norm_vols[k] * norm_vols[k]; + + // Calculate R factor using *cumulative* S1, S2 up to k + // Note: Original code used S1*S1 - S2. Ensure S1_cum is used correctly. + float R = 1.0f - S1_cum + 0.5f * lambda * (S1_cum * S1_cum - S2_cum); + + P_prime[k] = norm_vols[k] * std::max(0.0f, R); + P_prime_sum += P_prime[k]; // Accumulate sum for final normalization + } + // Note: This calculation is order-dependent based on how boundaries are indexed. + break; + } - for (int j = 1; j < num_partitions; j++) { - float boundary_distance = boundary_distances[j]; + case 1: { // M1: Direct Proportional Allocation + //std::cout << "Using Method 1: Direct Proportional" << std::endl; + // P0 based on raw volumes + + std::vector norm_vols = raw_vols; // Copy raw vols + float S1_for_norm = 0.0f; + for (int j = 1; j < m; ++j) S1_for_norm += norm_vols[j]; + + if (S1_for_norm > eps) { + for (int j = 1; j < m; ++j) norm_vols[j] /= S1_for_norm; + } else { + for (int j = 1; j < m; ++j) norm_vols[j] = 0.0f; + } + + P0 = 1.0f; + for (int j = 1; j < m; ++j) P0 *= (1.0f - norm_vols[j]); + P0 = std::clamp(P0, 0.0f, 1.0f); + + // P_prime is just raw_vols + for (int k = 1; k < m; ++k) { + P_prime[k] = norm_vols[k]; + P_prime_sum += P_prime[k]; + } + // Ensure P_prime is non-negative + for (int k = 1; k < m; ++k) P_prime[k] = std::max(0.0f, P_prime[k]); + break; + } - if (boundary_distance >= query_radius) { - partition_probabilities[j] = 0.0; - continue; + case 2: { // M2: Independent Entry Allocation + //std::cout << "Using Method 2: Independent Entry" << std::endl; + // P0 based on raw volumes + P0 = 1.0f; + for (int j = 1; j < m; ++j) P0 *= (1.0f - raw_vols[j]); + P0 = std::clamp(P0, 0.0f, 1.0f); + + if (P0 > eps) { // Avoid issues if P0 is near zero + for (int k = 1; k < m; ++k) { + float v_k = raw_vols[k]; + float one_minus_v_k = 1.0f - v_k; + // Check for valid v_k and avoid division by zero/small number + if (v_k > eps && one_minus_v_k > eps) { + P_prime[k] = v_k * P0 / one_minus_v_k; + // Clamp potentially large values if v_k is very close to 1? + // P_prime[k] = std::min(P_prime[k], 1.0f); // Optional clamping + P_prime_sum += P_prime[k]; + } + P_prime[k] = std::max(0.0f, P_prime[k]); // Ensure non-negative + } + } // else P_prime remains 0 + break; } - double volume_ratio = std::exp( - log_hyperspherical_cap_volume(query_radius, - boundary_distance, - dimension, - true, - use_precomputed, - euclidean)); - partition_probabilities[j] = (volume_ratio > 0.0) ? volume_ratio : 0.0; - } + case 3: { // M3: Concentration Penalized Allocation + //std::cout << "Using Method 3: Concentration Penalized" << std::endl; + // P0 based on raw volumes + P0 = 1.0f; + for (int j = 1; j < m; ++j) P0 *= (1.0f - raw_vols[j]); + P0 = std::clamp(P0, 0.0f, 1.0f); + + float S1_raw = 0.0f; + float S2_raw = 0.0f; + for (int j = 1; j < m; ++j) { + S1_raw += raw_vols[j]; + S2_raw += raw_vols[j] * raw_vols[j]; + } + + float penalty_factor = 0.0f; + if (S1_raw > eps) { + float S1_raw_sq = S1_raw * S1_raw; + // Avoid division by zero if S1_raw_sq is somehow zero or negative + if (S1_raw_sq > eps) { + float S2_norm = S2_raw / S1_raw_sq; + penalty_factor = std::max(0.0f, 1.0f - S2_norm); + } + // Optional: include lambda=m scaling -> penalty_factor *= 0.5f * m; + } + + for (int k = 1; k < m; ++k) { + P_prime[k] = raw_vols[k] * penalty_factor; // Apply uniform penalty + P_prime_sum += P_prime[k]; + } + break; + } - // TODO: Implement a better way to compute the probabilities for the first partition. This heuristic works well on tested datasets. - partition_probabilities[0] = 2.0 * partition_probabilities[1]; - // partition_probabilities[0] = 1 - partition_probabilities[1]; + case 4: { // M4: Radius-Difference Weighting + //std::cout << "Using Method 4: Radius-Difference Weighting" << std::endl; + // P0 based on raw volumes + P0 = 1.0f; + for (int j = 1; j < m; ++j) P0 *= (1.0f - raw_vols[j]); + P0 = std::clamp(P0, 0.0f, 1.0f); + + for (int k = 1; k < m; ++k) { + float v_k = raw_vols[k]; + if (v_k > eps) { + // Use boundary_distances directly, ensure non-negative + float d_k = std::max(0.0f, boundary_distances[k]); + // Calculate non-uniform weight based on distance from radius + float mu_k_tilde = std::max(0.0f, query_radius - d_k); + P_prime[k] = v_k * mu_k_tilde; + P_prime_sum += P_prime[k]; + } + } + break; + } - // if (weigh_using_partition_sizes) { - // for (int j = 0; j < num_partitions; j++) { - // partition_probabilities[j] *= partition_sizes[j]; - // } - // } + case 5: { // M5: Simplified IE Approx Weighting + //std::cout << "Using Method 5: Simplified IE Approx" << std::endl; + // P0 based on raw volumes + P0 = 1.0f; + for (int j = 1; j < m; ++j) P0 *= (1.0f - raw_vols[j]); + P0 = std::clamp(P0, 0.0f, 1.0f); + + float S1_raw = 0.0f; + for(int j=1; j eps) { + // Calculate non-uniform scaling factor + float mu_k_tilde = std::max(0.0f, 1.0f - 0.5f * S1_raw + 0.5f * v_k); + P_prime[k] = v_k * mu_k_tilde; + P_prime_sum += P_prime[k]; + } + } + break; + } + + case 6: { + std::vector norm_vols = raw_vols; // Copy raw vols + float S1_for_norm = 0.0f; + for (int j = 1; j < m; ++j) S1_for_norm += norm_vols[j]; + + if (S1_for_norm > eps) { + for (int j = 1; j < m; ++j) norm_vols[j] /= S1_for_norm; + } else { + for (int j = 1; j < m; ++j) norm_vols[j] = 0.0f; + } + + P0 = 1.0f; + for (int j = 1; j < m; ++j) P0 *= (1.0f - norm_vols[j]); + P0 = std::clamp(P0, 0.0f, 1.0f); + + float S2_raw = 0.0f; + for (int j = 1; j < m; ++j) { + S2_raw += norm_vols[j]; + } + + if (S2_raw > eps) { + for (int k = 1; k < m; ++k) { + float v_k = norm_vols[k]; + S2_raw -= v_k; // Update S2_raw for next iteration + float rel_L2_sq = (.5 * v_k * S2_raw); + float mu_k_tilde = 1 / (1.0f + rel_L2_sq); // Non-uniform scaling + P_prime[k] = v_k * std::max(mu_k_tilde, .001f); + P_prime_sum += P_prime[k]; + } + } else { // If S2 is zero, all raw_vols are zero, P_prime remains zero + for (int k = 1; k < m; ++k) { + P_prime[k] = norm_vols[k]; // Should be 0 + P_prime_sum += P_prime[k]; // Should be 0 + } + } + // Ensure P_prime is non-negative + for (int k = 1; k < m; ++k) P_prime[k] = std::max(0.0f, P_prime[k]); + + break; + } - // Ensure the probabilities sum to 1 - double sum_probabilities = 0.0; - for (int j = 0; j < num_partitions; j++) { - sum_probabilities += partition_probabilities[j]; + default: + // Handle unknown method flag, e.g., throw error or default to Method 1 + //std::cerr << "Error: Unknown method_flag: " << method_flag << std::endl; + throw std::runtime_error("Unknown method_flag in compute_recall_profile"); + // Or fallback: goto method1_label; (using labels/goto is generally discouraged) } - if (sum_probabilities > 0.0f) { - for (int j = 0; j < num_partitions; j++) { - partition_probabilities[j] /= sum_probabilities; + + + // --- Final Normalization --- + std::vector probs(m, 0.0f); + probs[0] = P0; // Assign calculated P0 for the chosen method + + float target = 1.0f - P0; + // Ensure target probability for neighbors is valid [0, 1] + target = std::clamp(target, 0.0f, 1.0f); + + if (target > eps && P_prime_sum > eps) { + float scale = target / P_prime_sum; + for (int k = 1; k < m; ++k) { + // Ensure final probability is non-negative + probs[k] = std::max(0.0f, P_prime[k] * scale); } - } else { - for (int j = 0; j < num_partitions; j++) { - partition_probabilities[j] = 1.0 / num_partitions; + + // --- Strict Renormalization --- + // This step ensures probs[1..m-1] sum *exactly* to target, + // correcting minor float inaccuracies or effects of max(0,...) + float current_sum_k = 0.0f; + for (int k = 1; k < m; ++k) current_sum_k += probs[k]; + + if (current_sum_k > eps) { // Avoid division by zero if sum is negligible + float final_scale = target / current_sum_k; + // Check if scale is finite (handles target=0 case correctly) + if (std::isfinite(final_scale)) { + for (int k = 1; k < m; ++k) { + probs[k] *= final_scale; + // Final clamp for safety + probs[k] = std::max(0.0f, probs[k]); + } + } else if (target <= eps) { + // If target is zero, all neighbor probs should be zero + for (int k = 1; k < m; ++k) probs[k] = 0.0f; + } + } else if (target <= eps) { + // If target is zero and calculated sum is zero, ensure all are zero + for (int k = 1; k < m; ++k) probs[k] = 0.0f; } - } + // --- End Optional Strict Renormalization --- - // Compute the recall profile - // Tensor recall_profile = torch::cumsum(probabilities_tensor, 0); + } - return partition_probabilities; + return probs; } +// inline std::vector +// compute_recall_profile(const std::vector& boundary_distances, +// float query_radius, +// int dimension, +// std::vector partition_sizes = {}, +// bool use_precomputed = true, +// bool euclidean = true) +// { +// const int m = static_cast(boundary_distances.size()); +// const float eps = 1e-9f; +// +// if (m <= 1) { +// if (m == 1) return {1.0f}; +// return {}; +// } +// if (query_radius <= eps) { +// std::vector p(m, 0.0f); +// p[0] = 1.0f; +// return p; +// } +// +// // 1) compute raw cap‐volumes vols[1..m-1] +// std::vector vols(m, 0.0f); +// for (int j = 1; j < m; ++j) { +// double d = std::max(0.0, static_cast(boundary_distances[j])); +// if (d >= query_radius) continue; +// double x = 1.0 - (d/query_radius)*(d/query_radius); +// x = std::clamp(x, 0.0, 1.0); +// +// double a = 0.5*(dimension + 1.0), b = 0.5, I = 0.0; +// try { +// I = use_precomputed +// ? incomplete_beta_lookup(x, dimension) +// : incomplete_beta(a, b, x); +// } catch(...) { +// I = 0.0; +// } +// vols[j] = std::clamp(0.5 * I, 0.0, 0.5); +// } +// +// // // 2) normalize vols[1..] to sum = 1 +// // float sumv = std::accumulate(vols.begin()+1, vols.end(), 0.0f); +// // if (sumv > eps) { +// // for (int j = 1; j < m; ++j) vols[j] /= sumv; +// // } else { +// // std::fill(vols.begin()+1, vols.end(), 0.0f); +// // } +// +// // 3) compute reference P0 = ∏_{j=1..m-1}(1 - vols[j]) +// float P0 = 1.0f; +// for (int j = 1; j < m; ++j) { +// P0 *= (1.0f - vols[j]); +// } +// +// // 4) compute raw Pk for k>=1 under chosen mode +// std::vector raw(m, 0.0f); +// +// // 4) if scaled‐IE, compute λ = 1 / ∑v_j^2 +// float lambda = (float) boundary_distances.size(); +// // float lambda = +// // if (use_scaled_ie) { +// // float sum2 = 0.0f; +// // for (int j=1;jeps ? 1.0f/sum2 : 1.0f); +// // } +// +// std::cout << "lambda: " << lambda << std::endl; +// +// // -- Scaled‐IE: λ·(S1²−S2) in pairwise term -- +// float S1 = 0.0f, S2 = 0.0f; +// for (int k = 1; k < m; ++k) { +// S1 += vols[k]; +// S2 += vols[k]*vols[k]; +// float R = 1.0f +// - S1 +// + 0.5f*lambda*(S1*S1 - S2); +// raw[k] = vols[k] * std::max(0.0f, R); +// } +// std::cout << "S1: " << S1 << " S2: " << S2 << std::endl; +// +// // float scale_term = 1.0f; +// // for (int k = 1; k < m; ++k) { +// // raw[k] = vols[k] * scale_term; +// // scale_term *= (1.0f - vols[k]); +// // } +// +// // for (int k = 1; k < m; ++k) { +// // float scale_term = P0 / (1 - vols[k]); +// // raw[k] = vols[k] * scale_term; +// // } +// +// // 5) scale k>=1 so they sum to (1 - P0), leave P0 unchanged +// float sum_raw = std::accumulate(raw.begin()+1, raw.end(), 0.0f); +// std::vector probs(m, 0.0f); +// probs[0] = P0; +// +// float target = 1.0f - P0; +// if (sum_raw > eps) { +// float scale = target / sum_raw; +// for (int k = 1; k < m; ++k) { +// probs[k] = std::max(0.0f, raw[k] * scale); +// } +// } +// +// return probs; +// } + +// inline std::vector +// compute_recall_profile(const std::vector& boundary_distances, +// float query_radius, +// int dimension, +// std::vector partition_sizes = {}, +// bool use_precomputed = true, +// bool euclidean = true) +// { +// const int m = static_cast(boundary_distances.size()); +// const float float_epsilon = 1e-9f; // Small value for float comparisons +// +// // Handle edge cases: no cells or only the home cell +// if (m == 0) { +// return {}; +// } +// if (m == 1) { +// return {1.0f}; // Only home cell exists, probability is 1 +// } +// if (query_radius <= float_epsilon) { +// // If query radius is zero or negligible, k-NN must be in home cell +// std::vector probs(m, 0.0f); +// probs[0] = 1.0f; +// return probs; +// } +// +// +// std::vector vols(m, 0.0f); // Raw cap volume ratios (v_j for j>=1) +// +// // --- 1. Calculate raw cap ratios v_j for neighbors j = 1 to m-1 --- +// for (int j = 1; j < m; ++j) { +// float d_edge = boundary_distances[j]; // Distance to bisector plane j +// +// // Clamp distance to be non-negative (numerical safety) +// d_edge = std::max(0.0f, d_edge); +// +// // If plane is beyond radius, cap volume is zero +// if (d_edge >= query_radius) { +// vols[j] = 0.0f; +// continue; +// } +// +// // Calculate x = 1 - (d_edge/query_radius)^2 for betainc arg I_x(a, b) +// // Use doubles for intermediate calculation for precision +// double r_double = static_cast(query_radius); +// double d_double = static_cast(d_edge); +// double ratio_d_r = d_double / r_double; +// double x = 1.0 - ratio_d_r * ratio_d_r; +// +// // Clamp x to [0, 1] due to potential floating point inaccuracies +// x = std::clamp(x, 0.0, 1.0); +// +// // Parameters for incomplete beta I_x(a, b) for hyperspherical cap volume ratio +// double a_param = 0.5 * (static_cast(dimension) + 1.0); +// double b_param = 0.5; +// +// double beta_inc_value = 0.0; +// try { +// beta_inc_value = use_precomputed +// ? incomplete_beta_lookup(x, dimension) +// : incomplete_beta(a_param, b_param, x); +// } catch (const std::exception& e) { +// // Warn if beta calculation fails, default volume to 0 +// // Consider more robust error handling if needed +// #if DEBUG // Optional: Only print in debug builds +// fprintf(stderr, +// "Warning: Incomplete Beta calculation failed for x=%.6f, dim=%d. Defaulting cap vol to 0. Error: %s\n", +// x, dimension, e.what()); +// #endif +// beta_inc_value = 0.0; +// } +// +// // Cap volume ratio = 0.5 * I_x(a, b) +// vols[j] = 0.5f * static_cast(beta_inc_value); +// // Clamp result to ensure it's within valid range [0, 0.5] +// vols[j] = std::clamp(vols[j], 0.0f, 0.5f); +// } +// +// // --- 2. Calculate mu = sum(v_j) for j>=1 --- +// float mu_total = std::accumulate(vols.begin() + 1, vols.end(), 0.0f); +// +// // normalize volumes to sum to 1.0 +// if (mu_total > float_epsilon) { +// for (int j = 1; j < m; ++j) { +// vols[j] /= mu_total; +// } +// } else { +// // If mu is near zero, set all volumes to zero +// std::fill(vols.begin() + 1, vols.end(), 0.0f); +// } +// // --- 4. Calculate Improved P0 = max(exp(-mu), 1 - v1) --- +// +// vector survival_function(m, 1.0f); +// int k_neighbors = 100; +// for (int j = m-1; j > 0; --j) { +// survival_function[j-1] = survival_function[j] * (1.0f - (vols[j])); +// } +// +// // --- 5. Calculate neighbor probabilities P_j = (1-P0)*v_j/mu --- +// std::vector probs(m, 0.0f); +// probs[0] = survival_function[0]; +// +// // for (int j = 1; j < m; j++) { +// // probs[j] = vols[j] * (survival_function[0] / (1 - vols[j])); +// // } +// +// // for (int j = 1; j < m; ++j) { +// // probs[j] = survival_function[j] - survival_function[j - 1]; +// // } +// +// float remaining_mass = 1.0f - probs[0]; +// float cum_v = 0.0f; // Σ_{i float_epsilon) { +// // for (int j = 1; j < m; ++j) { +// // probs[j] = (accum / (1 - vols[j])) - accum; // reverse the survival function +// // probs[j] = std::clamp(probs[j], 0.0f, 1.0f); +// // accum += probs[j]; +// // } +// // } +// // If P_neighbors_total or mu is near zero, probs[1...m-1] remain 0.0f. +// +// // --- 6. Final Renormalization (Safety Net for Floating Point Drift) --- +// float sum_probs = std::accumulate(probs.begin(), probs.end(), 0.0f); +// +// if (sum_probs > float_epsilon) { +// float inv_sum = 1.0f / sum_probs; +// for (int j = 0; j < m; ++j) { +// // Ensure probabilities are non-negative after division +// probs[j] = std::max(0.0f, probs[j] * inv_sum); +// } +// // Ensure sum is exactly 1.0, assign difference to largest element (usually P0) +// float final_sum_check = std::accumulate(probs.begin(), probs.end(), 0.0f); +// probs[0] += (1.0f - final_sum_check); // Add residual to P0 +// +// +// } else { +// // If sum is zero (should be rare unless m=0), reset to P0=1. +// if (m > 0) { +// std::fill(probs.begin() + 1, probs.end(), 0.0f); +// probs[0] = 1.0f; +// } +// } +// +// return probs; +// } + inline float compute_intersection_volume_one(float boundary_distance, float query_radius, int dimension) { if (boundary_distance >= query_radius) { return -1e8; diff --git a/src/cpp/include/index_partition.h b/src/cpp/include/index_partition.h index 63b022c6..05cab7a2 100644 --- a/src/cpp/include/index_partition.h +++ b/src/cpp/include/index_partition.h @@ -109,7 +109,7 @@ class IndexPartition { * * @param index Index of the vector to remove. */ - void remove(int64_t index); + int64_t remove(int64_t index); /** * @brief Resize the partition. diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index d33e540a..557393b7 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -187,6 +187,11 @@ class TypedTopKBuffer { DistanceType get_kth_distance() { std::lock_guard buffer_lock(buffer_mutex_); flush(); // Ensure the buffer is properly flushed + + if (curr_offset_ < k_) { + return 0.0; + } + return topk_[std::min(curr_offset_, k_ - 1)].first; } diff --git a/src/cpp/include/maintenance_policies.h b/src/cpp/include/maintenance_policies.h index 6ee68075..0ddb5f7f 100644 --- a/src/cpp/include/maintenance_policies.h +++ b/src/cpp/include/maintenance_policies.h @@ -46,7 +46,6 @@ class MaintenancePolicy { */ void reset(); - private: shared_ptr partition_manager_; ///< Manages partition state. shared_ptr params_; ///< Maintenance parameters. shared_ptr cost_estimator_; ///< Cost estimator for maintenance actions. diff --git a/src/cpp/include/parallel.h b/src/cpp/include/parallel.h index 15f9c30d..5db90651 100644 --- a/src/cpp/include/parallel.h +++ b/src/cpp/include/parallel.h @@ -42,23 +42,28 @@ template void parallel_for(IndexType start, IndexType end, Function func, int num_threads = -1) { if (num_threads <= 0) { num_threads = std::thread::hardware_concurrency(); - } - IndexType total = end - start; - IndexType chunk = (total + num_threads - 1) / num_threads; - std::vector> futures; - for (IndexType t = 0; t < num_threads; ++t) { - IndexType chunk_start = start + t * chunk; - IndexType chunk_end = std::min(end, chunk_start + chunk); - if (chunk_start >= chunk_end) - break; - futures.push_back(std::async(std::launch::async, [=]() { - for (IndexType i = chunk_start; i < chunk_end; i++) { - func(i); - } - })); - } - for (auto &f : futures) { - f.get(); + } else if (num_threads == 1) { + for (IndexType i = start; i < end; i++) { + func(i); + } + } else { + IndexType total = end - start; + IndexType chunk = (total + num_threads - 1) / num_threads; + std::vector> futures; + for (IndexType t = 0; t < num_threads; ++t) { + IndexType chunk_start = start + t * chunk; + IndexType chunk_end = std::min(end, chunk_start + chunk); + if (chunk_start >= chunk_end) + break; + futures.push_back(std::async(std::launch::async, [=]() { + for (IndexType i = chunk_start; i < chunk_end; i++) { + func(i); + } + })); + } + for (auto &f : futures) { + f.get(); + } } } diff --git a/src/cpp/src/dynamic_inverted_list.cpp b/src/cpp/src/dynamic_inverted_list.cpp index 0ea36450..d51d14b6 100644 --- a/src/cpp/src/dynamic_inverted_list.cpp +++ b/src/cpp/src/dynamic_inverted_list.cpp @@ -99,16 +99,21 @@ namespace faiss { void DynamicInvertedLists::remove_entry(size_t list_no, idx_t id) { auto it = partitions_.find(list_no); - if (it == partitions_.end()) { + if (it == partitions_.end()) throw std::runtime_error("List does not exist in remove_entry"); - } - shared_ptr part = it->second; + auto& part = it->second; if (part->num_vectors_ == 0) return; - int64_t idx_to_remove = part->find_id(id); - if (idx_to_remove != -1) { - part->remove(idx_to_remove); + int64_t pos = part->find_id(id); + if (pos == -1) return; + + int64_t swapped = part->remove(pos); + map_erase(id); + + if (swapped != -1) { // someone moved into `pos` + idx_t moved_id = part->ids_[pos]; + map_swap(part.get(), pos, moved_id); } } @@ -125,9 +130,12 @@ namespace faiss { // We'll perform removals by scanning and removing matches. // Because remove() swaps last element in, we must be careful with iteration. for (int64_t i = 0; i < part->num_vectors_;) { - if (vectors_to_remove_set.find(part->ids_[i]) != vectors_to_remove_set.end()) { - part->remove(i); - // don't increment i, because we just swapped a new element into i + if (vectors_to_remove_set.count(part->ids_[i])) { + idx_t victim = part->ids_[i]; + int64_t swapped = part->remove(i); + map_erase(victim); + if (swapped != -1) + map_swap(part.get(), i, part->ids_[i]); } else { i++; } @@ -139,8 +147,12 @@ namespace faiss { for (auto &kv: partitions_) { shared_ptr part = kv.second; for (int64_t i = 0; i < part->num_vectors_;) { - if (vectors_to_remove.find(part->ids_[i]) != vectors_to_remove.end()) { - part->remove(i); + if (vectors_to_remove.count(part->ids_[i])) { + idx_t victim = part->ids_[i]; + int64_t swapped = part->remove(i); + map_erase(victim); + if (swapped != -1) + map_swap(part.get(), i, part->ids_[i]); } else { i++; } @@ -148,27 +160,38 @@ namespace faiss { } } + void DynamicInvertedLists::build_map() { + id_to_location_.clear(); + for (auto& kv : partitions_) { + IndexPartition* part = kv.second.get(); + for (int64_t i = 0; i < part->num_vectors_; i++) { + id_to_location_[part->ids_[i]] = {part, i}; + } + } + } + + size_t DynamicInvertedLists::add_entries( size_t list_no, size_t n_entry, const idx_t *ids, const uint8_t *codes) { - if (n_entry == 0) { - return 0; - } + if (n_entry == 0) return 0; auto it = partitions_.find(list_no); - if (it == partitions_.end()) { + if (it == partitions_.end()) throw std::runtime_error("List does not exist in add_entries"); - } - shared_ptr part = it->second; - // Ensure code_size is set - if (part->code_size_ != static_cast(code_size)) { + auto& part = it->second; + if (part->code_size_ != static_cast(code_size)) part->set_code_size(static_cast(code_size)); - } - part->append((int64_t) n_entry, ids, codes); + const int64_t base = part->num_vectors_; // size *before* append + part->append(static_cast(n_entry), ids, codes); + + for (size_t i = 0; i < n_entry; ++i) + map_add(part.get(), base + i, ids[i]); + return n_entry; } @@ -187,73 +210,70 @@ namespace faiss { part->update((int64_t) offset, (int64_t) n_entry, ids, codes); } - void DynamicInvertedLists::batch_update_entries( - size_t old_vector_partition, - int64_t *new_vector_partitions, - uint8_t *new_vectors, - int64_t *new_vector_ids, - int num_vectors) { - // This logic will: - // 1. Remove all vectors from old_vector_partition that moved to a new partition - // 2. Append them to their new partitions - - // Identify which vectors belong to old_vector_partition and distribute them - // to new partitions. - std::unordered_map > vectors_for_new_partition; - - for (int i = 0; i < num_vectors; i++) { - size_t new_p = static_cast(new_vector_partitions[i]); - if (new_p != old_vector_partition) { - vectors_for_new_partition[new_p].push_back(i); - } - } - - // Append entries to new partitions - for (auto &kv: vectors_for_new_partition) { - size_t new_p = kv.first; - auto it = partitions_.find(new_p); - if (it == partitions_.end()) { - // Create a new partition if needed - add_list(new_p); - it = partitions_.find(new_p); - } - shared_ptr new_part = it->second; - if (new_part->code_size_ != static_cast(code_size)) { - new_part->set_code_size((int64_t) code_size); +void DynamicInvertedLists::batch_update_entries( + size_t old_partition, + int64_t* new_partitions, + uint8_t* new_vectors, + int64_t* new_ids, + int num) +{ + /* 1. gather indices to move grouped by their *destination* */ + std::unordered_map> to_move; + for (int i = 0; i < num; ++i) { + size_t dst = static_cast(new_partitions[i]); + if (dst != old_partition) + to_move[dst].push_back(i); + } + + /* 2. FIRST remove them from the old partition + (updates map_erase + map_swap) */ + auto old_it = partitions_.find(old_partition); + if (old_it != partitions_.end()) { + auto& old_part = old_it->second; + for (auto& kv : to_move) + for (int idx : kv.second) { + idx_t victim = static_cast(new_ids[idx]); + int64_t pos = old_part->find_id(victim); + if (pos != -1) { + int64_t sw = old_part->remove(pos); + map_erase(victim); + if (sw != -1) + map_swap(old_part.get(), pos, old_part->ids_[pos]); + } } + } - // Gather all IDs and codes to append at once - std::vector tmp_ids; - tmp_ids.reserve(kv.second.size()); - std::vector tmp_codes; - tmp_codes.reserve(kv.second.size() * code_size); - - for (int idx: kv.second) { - tmp_ids.push_back((idx_t) new_vector_ids[idx]); - tmp_codes.insert(tmp_codes.end(), - new_vectors + idx * code_size, - new_vectors + (idx + 1) * code_size); - } + /* 3. THEN append them to their new partitions + (updates map_add) */ + for (auto& kv : to_move) { + size_t dst = kv.first; + auto& idxs = kv.second; - new_part->append((int64_t) kv.second.size(), tmp_ids.data(), tmp_codes.data()); + auto it = partitions_.find(dst); + if (it == partitions_.end()) { + add_list(dst); + it = partitions_.find(dst); } + auto& new_part = it->second; + if (new_part->code_size_ != static_cast(code_size)) + new_part->set_code_size((int64_t)code_size); - // If needed, remove them from old_vector_partition - auto old_it = partitions_.find(old_vector_partition); - if (old_it != partitions_.end()) { - shared_ptr old_part = old_it->second; - // remove vectors that moved - for (auto &kv: vectors_for_new_partition) { - for (int idx: kv.second) { - idx_t old_id = (idx_t) new_vector_ids[idx]; - int64_t pos = old_part->find_id(old_id); - if (pos != -1) { - old_part->remove(pos); - } - } - } + const int64_t base = new_part->num_vectors_; + std::vector ids_buf; ids_buf.reserve(idxs.size()); + std::vector codes_buf; codes_buf.reserve(idxs.size() * code_size); + + for (int j : idxs) { + ids_buf .push_back(static_cast(new_ids[j])); + codes_buf.insert(codes_buf.end(), + new_vectors + j * code_size, + new_vectors + (j + 1) * code_size); } + new_part->append((int64_t)idxs.size(), ids_buf.data(), codes_buf.data()); + + for (size_t k = 0; k < idxs.size(); ++k) + map_add(new_part.get(), base + k, ids_buf[k]); } +} void DynamicInvertedLists::remove_list(size_t list_no) { auto it = partitions_.find(list_no); @@ -262,6 +282,9 @@ namespace faiss { return; } + for (int64_t i = 0; i < it->second->num_vectors_; i++) { + map_erase(it->second->ids_[i]); + } partitions_.erase(it); nlist--; } @@ -285,39 +308,51 @@ namespace faiss { return part->find_id(id) != -1; } - bool DynamicInvertedLists::get_vector_for_id(idx_t id, float *vector_values) { - for (auto &kv: partitions_) { - shared_ptr part = kv.second; - int64_t pos = part->find_id(id); - if (pos != -1) { - // Found it, copy vector - // code_size_ is in bytes. Assuming float vectors of dimension (code_size_/sizeof(float)) - std::memcpy(vector_values, part->codes_ + pos * part->code_size_, part->code_size_); - return true; - } - } - return false; + bool DynamicInvertedLists::get_vector_for_id(idx_t id, float *out) { + if (id_to_location_.empty()) build_map(); + + auto it = id_to_location_.find(id); + if (it == id_to_location_.end()) return false; + IndexPartition* part = it->second.first; + int64_t pos = it->second.second; + std::memcpy(out, part->codes_ + pos * part->code_size_, part->code_size_); + return true; } vector DynamicInvertedLists::get_vectors_by_id(vector ids) { + if (id_to_location_.empty()) build_map(); + + vector ret; + ret.reserve(ids.size()); - vector ret; for (int64_t id : ids) { - bool found = false; - for (auto &kv: partitions_) { - shared_ptr part = kv.second; - int64_t pos = part->find_id(id); - if (pos != -1) { - ret.push_back(reinterpret_cast(part->codes_ + pos * part->code_size_)); - found = true; - break; - } - } - if (!found) { + auto it = id_to_location_.find(id); + if (it == id_to_location_.end()) { throw std::runtime_error("ID not found in any partition"); } + IndexPartition* part = it->second.first; + int64_t pos = it->second.second; + ret.push_back(reinterpret_cast(part->codes_ + pos * part->code_size_)); } return ret; + + // vector ret; + // for (int64_t id : ids) { + // bool found = false; + // for (auto &kv: partitions_) { + // shared_ptr part = kv.second; + // int64_t pos = part->find_id(id); + // if (pos != -1) { + // ret.push_back(reinterpret_cast(part->codes_ + pos * part->code_size_)); + // found = true; + // break; + // } + // } + // if (!found) { + // throw std::runtime_error("ID not found in any partition"); + // } + // } + // return ret; } size_t DynamicInvertedLists::get_new_list_id() { @@ -326,6 +361,7 @@ namespace faiss { void DynamicInvertedLists::reset() { partitions_.clear(); + id_to_location_.clear(); nlist = 0; curr_list_id_ = 0; } @@ -517,6 +553,8 @@ namespace faiss { curr_list_id_ = max_list_id + 1; ifs.close(); + + build_map(); } Tensor DynamicInvertedLists::get_partition_ids() { diff --git a/src/cpp/src/index_partition.cpp b/src/cpp/src/index_partition.cpp index 8604a939..87e4992d 100644 --- a/src/cpp/src/index_partition.cpp +++ b/src/cpp/src/index_partition.cpp @@ -76,29 +76,21 @@ void IndexPartition::update(int64_t offset, int64_t n_entry, const idx_t* new_id std::memcpy(ids_ + offset, new_ids, n_entry * sizeof(idx_t)); } -void IndexPartition::remove(int64_t index) { - if (index < 0 || index >= num_vectors_) { - throw std::runtime_error("Index out of range in remove"); +int64_t IndexPartition::remove(int64_t idx) +{ + assert(idx >= 0 && idx < num_vectors_); + const int64_t last = num_vectors_ - 1; + + // optional: bookkeeping for norms, etc. + + if (idx != last) { // swap last -> idx + std::memcpy(codes_ + idx * code_size_, + codes_ + last * code_size_, + code_size_); + ids_[idx] = ids_[last]; } - if (index == num_vectors_ - 1) { - num_vectors_--; - return; - } - - int64_t last_idx = num_vectors_ - 1; - const size_t code_bytes = static_cast(code_size_); - - // // Update id_to_index_ - // idx_t last_id = ids_[last_idx]; - // idx_t removed_id = ids_[index]; - // - // id_to_index_[last_id] = index; - // id_to_index_.erase(removed_id); - - std::memcpy(codes_ + index * code_bytes, codes_ + last_idx * code_bytes, code_bytes); - ids_[index] = ids_[last_idx]; - - num_vectors_--; + --num_vectors_; + return (idx == last) ? -1 : idx; // <‑‑ the new occupant of slot idx } void IndexPartition::resize(int64_t new_capacity) { diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index 3b738856..240e2f82 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -112,6 +112,8 @@ void PartitionManager::init_partitions( } } + partition_store_->build_map(); + if (debug_) { std::cout << "[PartitionManager] init_partitions: Created " << nlist << " partitions, dimension=" << dim << std::endl; diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 67112a1f..92b0ac84 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -514,6 +514,9 @@ shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partitio // Use our custom parallel_for to process queries in parallel. parallel_for(0, num_queries, [&](int64_t q) { // Create a local TopK buffer for query q. + + auto t1 = high_resolution_clock::now(); + auto topk_buf = std::make_shared(k, is_descending); const float* query_vec = x_ptr + q * dimension; int num_parts = partition_ids.size(1); @@ -525,16 +528,33 @@ shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partitio query_radius = -1000000.0; } + auto t2 = high_resolution_clock::now(); + Tensor partition_sizes = partition_manager_->get_partition_sizes(partition_ids[q]); + vector partition_sizes_vec = vector(partition_sizes.data_ptr(), + partition_sizes.data_ptr() + partition_sizes.size(0)); + auto t3 = high_resolution_clock::now(); if (use_aps) { vector partition_ids_to_scan_vec = std::vector(partition_ids[q].data_ptr(), partition_ids[q].data_ptr() + partition_ids[q].size(0)); vector cluster_centroids = parent_->partition_manager_->get_vectors(partition_ids_to_scan_vec); + t3 = high_resolution_clock::now(); + + boundary_distances = compute_boundary_distances(x[q], cluster_centroids, metric_ == faiss::METRIC_L2); } + auto t4 = high_resolution_clock::now(); + + int64_t scan_time = 0; + int64_t aps_time = 0; + + vector scanned_ids; + for (int p = 0; p < num_parts; p++) { + + auto curr_time = high_resolution_clock::now(); int64_t pi = partition_ids_accessor[q][p]; if (pi == -1) { @@ -553,13 +573,19 @@ shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partitio dimension, *topk_buf, metric_); + scanned_ids.push_back(pi); float curr_radius = topk_buf->get_kth_distance(); float percent_change = abs(curr_radius - query_radius) / curr_radius; + auto end_time = high_resolution_clock::now(); + + scan_time += duration_cast(end_time - start_time).count(); + start_time = high_resolution_clock::now(); - if (use_aps) { - if (percent_change > search_params->recompute_threshold) { + bool first_list = (p == 0); + if (use_aps && curr_radius != 0) { + if (first_list || percent_change > search_params->recompute_threshold) { query_radius = curr_radius; partition_probs = compute_recall_profile(boundary_distances, @@ -570,10 +596,13 @@ shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partitio metric_ == faiss::METRIC_L2); } float recall_estimate = 0.0; - for (int i = 0; i < p; i++) { + for (int i = 0; i < p + 1; i++) { recall_estimate += partition_probs[i]; } + end_time = high_resolution_clock::now(); + aps_time += duration_cast(end_time - start_time).count(); if (recall_estimate >= search_params->recall_target) { + timing_info->partitions_scanned = p + 1; break; } } @@ -581,8 +610,21 @@ shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partitio // Retrieve the top-k results for query q. all_topk_dists[q] = topk_buf->get_topk(); all_topk_ids[q] = topk_buf->get_topk_indices(); + auto t5 = high_resolution_clock::now(); + + // mark the partitions as scanned + maintenance_policy_->record_query_hits(scanned_ids); + std::cout << "Query " << q << " partitions scanned: " << scanned_ids.size() << std::endl; + std::cout << "Total queries processed: " << maintenance_policy_->hit_count_tracker_->get_num_queries_recorded() << std::endl; + + // std::cout << "Query " << q << " times: " << duration_cast(t2 - t1).count() << " " + // << duration_cast(t3 - t2).count() << " " + // << duration_cast(t4 - t3).count() << " " + // << duration_cast(t5 - t4).count() << std::endl; + // std::cout << "Scan time: " << scan_time / 1000.0 << " APS time: " << aps_time / 1000.0 << std::endl; }, search_params->num_threads); + // Aggregate per-query results into output tensors. auto ret_ids_accessor = ret_ids.accessor(); auto ret_dists_accessor = ret_dists.accessor(); diff --git a/src/python/datasets/ann_datasets.py b/src/python/datasets/ann_datasets.py index 89297392..572717a4 100644 --- a/src/python/datasets/ann_datasets.py +++ b/src/python/datasets/ann_datasets.py @@ -6,7 +6,7 @@ import numpy as np import torch -from quake.utils import download_url, extract_file, fvecs_to_tensor, ivecs_to_tensor, to_path +from quake.utils import download_url, extract_file, fvecs_to_tensor, ivecs_to_tensor, to_path, knn DEFAULT_DOWNLOAD_DIR = Path("data/") @@ -71,12 +71,58 @@ def load_queries(self) -> Union[np.ndarray, torch.Tensor]: def load_ground_truth(self) -> Union[np.ndarray, torch.Tensor]: return ivecs_to_tensor(self.data_dir / "sift_groundtruth.ivecs") +class UniformDataset(Dataset): + def __init__(self, num_vectors: int, dim: int, download_dir: Union[str, Path] = DEFAULT_DOWNLOAD_DIR): + self.num_vectors = num_vectors + self.dim = dim + self.download_dir = to_path(download_dir) + + def is_downloaded(self) -> bool: + # check if files exist + vecs = self.download_dir / "vectors.pt" + queries = self.download_dir / "queries.pt" + gt = self.download_dir / "ground_truth.pt" + + return vecs.exists() and queries.exists() and gt.exists() + + def download(self, overwrite: bool = False): + + vecs = np.random.uniform(0, 1, (self.num_vectors, self.dim)).astype(np.float32) + queries = np.random.uniform(0, 1, (1000, self.dim)).astype(np.float32) + gt = knn(queries, vecs, k=100)[0] + + # vecs = torch.randn(self.num_vectors, self.dim) + # queries = torch.randn(1000, self.dim) + # gt = knn(queries, vecs, k=100)[0] + + + np.save(self.download_dir / "vectors.npy", vecs) + np.save(self.download_dir / "queries.npy", queries) + np.save(self.download_dir / "ground_truth.npy", gt) + + def load_vectors(self) -> Union[np.ndarray, torch.Tensor]: + # return torch.randn(self.num_vectors, self.dim) + # Load the vectors from disk + return torch.from_numpy(np.load(self.download_dir / "vectors.npy")) + + def load_queries(self) -> Union[np.ndarray, torch.Tensor]: + # return torch.randn(self.num_vectors, self.dim) + # Load the queries from disk + return torch.from_numpy(np.load(self.download_dir / "queries.npy")) + + def load_ground_truth(self) -> Union[np.ndarray, torch.Tensor]: + # return torch.randint(0, self.num_vectors, (self.num_vectors, 100)) + # Load the ground truth from disk + return torch.from_numpy(np.load(self.download_dir / "ground_truth.npy")) + def load_dataset( name: str, download_dir: str = DEFAULT_DOWNLOAD_DIR, overwrite_download: bool = False ) -> List[Union[np.ndarray, torch.Tensor]]: if name.lower() == "sift1m": dataset = Sift1m(download_dir=download_dir) + elif name.lower() == "uniform": + dataset = UniformDataset(num_vectors=100000, dim=8, download_dir=download_dir) else: raise RuntimeError("Unimplemented dataset") diff --git a/src/python/workload_generator.py b/src/python/workload_generator.py index 3e90c814..abe8eb0e 100644 --- a/src/python/workload_generator.py +++ b/src/python/workload_generator.py @@ -418,7 +418,10 @@ def initialize_index(self, name, index, build_params, m_params): index.save(index_path) print(f"Index {name} built and saved to {index_path}") else: - index.load(index_path, n_workers=build_params.get("num_workers", 0)) + if build_params.get("num_workers"): + index.load(index_path, num_workers=build_params["num_workers"]) + else: + index.load(index_path) print(f"Index {name} loaded from {index_path}") if isinstance(index, QuakeWrapper) and m_params is not None: diff --git a/test/cpp/benchmark.cpp b/test/cpp/benchmark.cpp index 71426869..e2802a1a 100644 --- a/test/cpp/benchmark.cpp +++ b/test/cpp/benchmark.cpp @@ -28,10 +28,10 @@ using torch::Tensor; // Global benchmark parameters static const int64_t DIM = 128; static const int64_t NUM_VECTORS = 100000; // number of database vectors -static const int64_t N_LIST = 100; // number of clusters for IVF +static const int64_t N_LIST = 1000; // number of clusters for IVF static const int64_t NUM_QUERIES = 10; // number of queries for search benchmark static const int64_t K = 10; // top-K neighbors -static const int64_t N_PROBE = 32; // number of probes for IVF +static const int64_t N_PROBE = 12; // number of probes for IVF static const int64_t N_WORKERS = 12; // number of workers for parallel query coordinator // Helper functions to generate random data and sequential IDs @@ -487,4 +487,152 @@ TEST_F(FaissIVFBenchmark, Remove) { auto elapsed = duration_cast(end - start).count(); std::cout << "[Faiss IVF] Remove time: " << elapsed << " ms" << std::endl; SUCCEED(); -} \ No newline at end of file +} + +// ------------------------------------------------------------------------- +// SEARCH, ADD, REMOVE, AND MAINTENANCE TEST +// ------------------------------------------------------------------------- +TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { + // Repeatedly search, add, remove, and perform maintenance to see if the index remains consistent. + + int64_t dimension = 128; + int64_t num_vectors = 100000; + int64_t num_queries = 1; + int64_t batch_size = 10000; + int n_ops = 100; + + QuakeIndex index; + auto build_params = std::make_shared(); + build_params->nlist = 1000; + build_params->metric = "l2"; + build_params->niter = 5; + + Tensor data_vectors = torch::randn({num_vectors, dimension}, torch::kFloat32); + Tensor data_ids = torch::arange(num_vectors, torch::kInt64); + + index.build(data_vectors, data_ids, build_params); + + // timers + int64_t search_time = 0; + int64_t add_time = 0; + int64_t remove_time = 0; + int64_t maintenance_time = 0; + + auto start = std::chrono::high_resolution_clock::now(); + auto end = std::chrono::high_resolution_clock::now(); + + for (int i = 0; i < n_ops; i++) { + // Search + auto query_vectors = torch::randn({num_queries, dimension}, torch::kFloat32); + auto search_params = std::make_shared(); + search_params->nprobe = 12; + search_params->k = 10; + search_params->batched_scan = false; + search_params->num_threads = 1; + + start = std::chrono::high_resolution_clock::now(); + auto search_result = index.search(query_vectors, search_params); + end = std::chrono::high_resolution_clock::now(); + search_time += std::chrono::duration_cast(end - start).count(); + ASSERT_EQ(search_result->ids.size(0), query_vectors.size(0)); + ASSERT_EQ(search_result->ids.size(1), search_params->k); + + // Add + auto add_vectors = torch::randn({batch_size, dimension}, torch::kFloat32); + auto add_ids = torch::arange(batch_size, torch::kInt64) + num_vectors; + start = std::chrono::high_resolution_clock::now(); + auto add_info = index.add(add_vectors, add_ids); + end = std::chrono::high_resolution_clock::now(); + add_time += std::chrono::duration_cast(end - start).count(); + num_vectors += batch_size; + ASSERT_EQ(add_info->n_vectors, batch_size); + + // // Remove + // auto remove_ids = add_ids.slice(0, 0, batch_size / 2); + // start = std::chrono::high_resolution_clock::now(); + // auto remove_info = index.remove(remove_ids); + // end = std::chrono::high_resolution_clock::now(); + // remove_time += std::chrono::duration_cast(end - start).count(); + // ASSERT_EQ(remove_info->n_vectors, batch_size / 2); + + start = std::chrono::high_resolution_clock::now(); + index.maintenance(); + end = std::chrono::high_resolution_clock::now(); + maintenance_time += std::chrono::duration_cast(end - start).count(); + } + + // print out mean times per operation + float mean_search_time = static_cast(search_time) / n_ops; + float mean_add_time = static_cast(add_time) / n_ops; + float mean_remove_time = static_cast(remove_time) / n_ops; + float mean_maintenance_time = static_cast(maintenance_time) / n_ops; + + std::cout << "[SearchAddRemoveMaintenanceTest] Mean search time: " << mean_search_time << " μs\n"; + std::cout << "[SearchAddRemoveMaintenanceTest] Mean add time: " << mean_add_time << " μs\n"; + std::cout << "[SearchAddRemoveMaintenanceTest] Mean remove time: " << mean_remove_time << " μs\n"; + std::cout << "[SearchAddRemoveMaintenanceTest] Mean maintenance time: " << mean_maintenance_time << " μs\n"; + + SUCCEED(); +} + +TEST(FaissIndexStressTest, SearchAddRemoveMaintenanceTest) { + // Repeatedly search, add, remove, and perform maintenance to see if the index remains consistent. + + int64_t dimension = 128; + int64_t num_vectors = 100000; + int64_t num_queries = 1; + int64_t batch_size = 10000; + int n_ops = 100; + + Tensor data_vectors = torch::randn({num_vectors, dimension}, torch::kFloat32); + Tensor data_ids = torch::arange(num_vectors, torch::kInt64); + + auto quantizer = new faiss::IndexFlatL2(dimension); + auto index = new faiss::IndexIVFFlat(quantizer, dimension, 1000, faiss::METRIC_L2); + index->train(num_vectors, data_vectors.data_ptr()); + index->add(num_vectors, data_vectors.data_ptr()); + + // timers + int64_t search_time = 0; + int64_t add_time = 0; + int64_t remove_time = 0; + int64_t maintenance_time = 0; + + auto start = std::chrono::high_resolution_clock::now(); + auto end = std::chrono::high_resolution_clock::now(); + + for (int i = 0; i < n_ops; i++) { + // Search + auto query_vectors = generate_data(num_queries, dimension); + std::vector distances(num_queries * K); + std::vector labels(num_queries * K); + + start = std::chrono::high_resolution_clock::now(); + index->nprobe = 12; + index->search(num_queries, query_vectors.data_ptr(), 12, distances.data(), labels.data()); + end = std::chrono::high_resolution_clock::now(); + search_time += std::chrono::duration_cast(end - start).count(); + + // Add + auto add_vectors = generate_data(batch_size, dimension); + auto add_ids = generate_ids(batch_size, num_vectors); + start = std::chrono::high_resolution_clock::now(); + index->add(batch_size, add_vectors.data_ptr()); + end = std::chrono::high_resolution_clock::now(); + add_time += std::chrono::duration_cast(end - start).count(); + num_vectors += batch_size; + } + // print out mean times per operation + float mean_search_time = static_cast(search_time) / n_ops; + float mean_add_time = static_cast(add_time) / n_ops; + float mean_remove_time = static_cast(remove_time) / n_ops; + float mean_maintenance_time = static_cast(maintenance_time) / n_ops; + + std::cout << "[SearchAddRemoveMaintenanceTest] Mean search time: " << mean_search_time << " μs\n"; + std::cout << "[SearchAddRemoveMaintenanceTest] Mean add time: " << mean_add_time << " μs\n"; + std::cout << "[SearchAddRemoveMaintenanceTest] Mean remove time: " << mean_remove_time << " μs\n"; + std::cout << "[SearchAddRemoveMaintenanceTest] Mean maintenance time: " << mean_maintenance_time << " μs\n"; + + SUCCEED(); +} + diff --git a/test/cpp/dynamic_inverted_list.cpp b/test/cpp/dynamic_inverted_list.cpp index f7325e49..1473d1ec 100644 --- a/test/cpp/dynamic_inverted_list.cpp +++ b/test/cpp/dynamic_inverted_list.cpp @@ -556,6 +556,136 @@ TEST_F(DynamicInvertedListTest, SerializationTest) { remove(filename.c_str()); } +// --------------------------------------------------------------------- +// Map‑consistency tests +// --------------------------------------------------------------------- + +// After removing a middle element the map must point the *swapped* id +TEST_F(DynamicInvertedListTest, MapConsistencyAfterRemoveSwap) +{ + const size_t list_no = 0; + const size_t n_entries = 3; + + std::vector codes; + std::vector ids; + generate_random_codes(n_entries, codes); + generate_sequential_ids(n_entries, ids, 10); // ids = 10,11,12 + + invlists->add_entries(list_no, n_entries, ids.data(), codes.data()); + + // Remove id 11 (middle) – id 12 will be swapped into slot 1 + invlists->remove_entry(list_no, 11); + + // --- removed id must be gone + EXPECT_THROW( { invlists->get_vectors_by_id({11}); }, std::runtime_error ); + + // --- swapped id 12 must still be retrievable and vector intact + auto vec_ptrs = invlists->get_vectors_by_id({12}); + ASSERT_EQ(vec_ptrs.size(), 1u); + EXPECT_EQ( + std::memcmp(vec_ptrs[0], + codes.data() + 2 * code_size, // original bytes of id 12 + code_size), + 0); +} + + +// Removing many IDs in one pass must keep the map sound +TEST_F(DynamicInvertedListTest, MapConsistencyBulkRemove) +{ + const size_t list_no = 1; + const size_t n_entries = 10; + + std::vector codes; + std::vector ids; + generate_random_codes(n_entries, codes); + generate_sequential_ids(n_entries, ids, 100); // ids = 100..109 + + invlists->add_entries(list_no, n_entries, ids.data(), codes.data()); + + // Remove every even id (5 victims) + std::vector victims; + for (idx_t id : ids) + if (id % 2 == 0) victims.push_back(id); + + invlists->remove_entries_from_partition(list_no, victims); + + // All survivors must be accessible and the bytes match + std::vector survivors; + for (idx_t id : ids) + if (id % 2) survivors.push_back(id); + + auto vecs = invlists->get_vectors_by_id(survivors); + ASSERT_EQ(vecs.size(), survivors.size()); + for (size_t k = 0; k < survivors.size(); ++k) { + size_t orig_idx = survivors[k] - 100; // 0‑based + EXPECT_EQ( + std::memcmp(vecs[k], + codes.data() + orig_idx * code_size, + code_size), + 0); + } +} + + +// batch_update_entries must leave every moved id valid in the map +TEST_F(DynamicInvertedListTest, MapConsistencyBatchUpdate) +{ + const size_t old_p = 2; + const size_t new_p = 3; + const size_t n = 6; // vectors + + std::vector codes; + std::vector ids; + generate_random_codes(n, codes); + generate_sequential_ids(n, ids, 500); // 500..505 + invlists->add_entries(old_p, n, ids.data(), codes.data()); + + // mark last 3 vectors to move + std::vector part_of(n, (int64_t)old_p); + for (size_t i = 3; i < n; ++i) part_of[i] = (int64_t)new_p; + + std::vector new_codes = codes; // unchanged payload + std::vector ids_i64(ids.begin(), ids.end()); + + invlists->batch_update_entries(old_p, + part_of.data(), + new_codes.data(), + ids_i64.data(), + (int)n); + + // all ids must still retrieve the identical vector bytes + auto vecs = invlists->get_vectors_by_id({ids.begin(), ids.end()}); + ASSERT_EQ(vecs.size(), n); + + for (size_t k = 0; k < n; ++k) + EXPECT_EQ( + std::memcmp(vecs[k], + codes.data() + k * code_size, + code_size), + 0); +} + +TEST_F(DynamicInvertedListTest, LazyBuildMapGuard) +{ + const size_t list_no = 4; + std::vector codes; + std::vector ids; + generate_random_codes(1, codes); + generate_sequential_ids(1, ids, 900); + + invlists->add_entries(list_no, 1, ids.data(), codes.data()); + + // Brutally wipe the internal map (undefined behaviour normally, but + // we do it via the public API by resetting and rebuilding). + invlists->build_map(); // ensure filled first + invlists->id_to_location_.clear(); // <-- direct access because we are a friend in unit test + + // the read accessor should transparently rebuild + float tmp[4]; + EXPECT_TRUE(invlists->get_vector_for_id(ids[0], tmp)); +} + // NUMA related tests (only if QUAKE_USE_NUMA is defined) #ifdef QUAKE_USE_NUMA TEST_F(DynamicInvertedListTest, NumaTests) { diff --git a/test/cpp/quake_index.cpp b/test/cpp/quake_index.cpp index 0521ea02..22e9325e 100644 --- a/test/cpp/quake_index.cpp +++ b/test/cpp/quake_index.cpp @@ -7,6 +7,9 @@ #include #include "quake_index.h" #include +#include +#include +#include // Helper functions for random data static torch::Tensor generate_random_data(int64_t num_vectors, int64_t dim) { @@ -476,56 +479,6 @@ TEST(QuakeIndexStressTest, HighDimensionTest) { ASSERT_EQ(result->ids.size(1), search_params->k); } -// ------------------------------------------------------------------------- -// SEARCH, ADD, REMOVE, AND MAINTENANCE TEST -// ------------------------------------------------------------------------- -TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { - // Repeatedly search, add, remove, and perform maintenance to see if the index remains consistent. - - int64_t dimension = 16; - int64_t num_vectors = 100000; - int64_t num_queries = 100; - int64_t batch_size = 10; - - QuakeIndex index; - auto build_params = std::make_shared(); - build_params->nlist = 100; - build_params->metric = "l2"; - build_params->niter = 3; - - Tensor data_vectors = generate_random_data(num_vectors, dimension); - Tensor data_ids = generate_sequential_ids(num_vectors, 0); - - index.build(data_vectors, data_ids, build_params); - - for (int i = 0; i < 100; i++) { - // Search - std::cout << "Iteration " << i << std::endl; - auto query_vectors = generate_random_data(num_queries, dimension) * .1; - auto search_params = std::make_shared(); - search_params->nprobe = 1; - search_params->k = 5; - auto search_result = index.search(query_vectors, search_params); - ASSERT_EQ(search_result->ids.size(0), query_vectors.size(0)); - ASSERT_EQ(search_result->ids.size(1), search_params->k); - - // Add - auto add_vectors = generate_random_data(batch_size, dimension); - auto add_ids = generate_sequential_ids(batch_size, (i * batch_size) + num_vectors); - auto add_info = index.add(add_vectors, add_ids); - ASSERT_EQ(add_info->n_vectors, batch_size); - - // Remove - auto remove_ids = add_ids.slice(0, 0, batch_size / 2); - auto remove_info = index.remove(remove_ids); - ASSERT_EQ(remove_info->n_vectors, batch_size / 2); - - index.maintenance(); - } - - SUCCEED(); -} - // Define the GPU related test only if FAISS GPU support is enabled #ifdef FAISS_ENABLE_GPU // Test build with GPU enabled diff --git a/test/experiments/osdi2025/README.md b/test/experiments/osdi2025/README.md new file mode 100644 index 00000000..002ed897 --- /dev/null +++ b/test/experiments/osdi2025/README.md @@ -0,0 +1,57 @@ +# OSDI 2025 Artifact + +This directory contains the experiments for Quake's OSDI 2025 submission. + + + + +### Installation + +**Requirements:** +- Python 3.9 or later +- Linux (Tested on Ubuntu 22.04) + +1. **Clone the Repository:** + +```bash +git clone https://github.com/marius-team/quake.git +cd quake +git submodule update --init --recursive +``` + +2. **Set Up the Conda Environment:** + + Create and activate the environment using the provided YAML file: + +```bash +conda env create -f environments/ubuntu-latest/conda.yaml +conda activate quake-env +``` + +3. **Install Quake:** + +```bash +pip install --no-use-pep517 . +``` + +### Kick the tires + +To make sure Quake and the experiment environment are set up correctly, you can run the following commands: + +**Make sure to run all commands in the repository root directory** + +1. **Run the quickstart example:** + +This is a basic test that the main operations of Quake are working. + +```bash +python3 examples/quickstart.py +``` + +2. **Run the Benchmark:** + +```bash +python3 -m test.experiments.osdi2025.experiment_runner --experiment kick_the_tires --config sift1m +``` + +--- \ No newline at end of file diff --git a/test/experiments/osdi2025/aps_recall_targets/configs/sift1m.yaml b/test/experiments/osdi2025/aps_recall_targets/configs/sift1m.yaml new file mode 100644 index 00000000..47c5ee47 --- /dev/null +++ b/test/experiments/osdi2025/aps_recall_targets/configs/sift1m.yaml @@ -0,0 +1,28 @@ +# configs/experiment.yaml +mode: run # options: build, run, plot +base_dir: data/aps +dataset: + name: sift1m + path: data +experiment: + nq: 100 + k: 100 + n_workers: 0 + recall_targets: [.2, .3, .4, .5, .6, .7, .8, .9, .95, .99, .999] + recompute_ratio: 0.00001 + use_precompute: true + initial_search_fraction: .1 +index: + metric: l2 + nlist: 1000 +overwrite: + index: false + results: true +methods: ['Oracle', 'APS'] +#methods: ['APS'] +#methods: ['Oracle'] + +paths: + index_dir: data/sift1m/indexes + results_dir: data/sift1m/results + plot_dir: data/sift1m/plots \ No newline at end of file diff --git a/test/experiments/osdi2025/aps_recall_targets/run.py b/test/experiments/osdi2025/aps_recall_targets/run.py index 139597f9..1e9510fe 100644 --- a/test/experiments/osdi2025/aps_recall_targets/run.py +++ b/test/experiments/osdi2025/aps_recall_targets/run.py @@ -1,2 +1,182 @@ +#!/usr/bin/env python3 +""" +Adaptive‐Partition‐Scanning Recall‐Target Runner +Supports three methods: Oracle, FixedNProbe, APS +""" +import time +import yaml +import logging +from pathlib import Path +import torch +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt + +from quake import QuakeIndex, IndexBuildParams, SearchParams +from quake.datasets.ann_datasets import load_dataset +from quake.utils import compute_recall + +logger = logging.getLogger(__name__) + +def run_experiment(cfg_path: str, output_dir: str): + # 1) Load config + setup output dir + cfg = yaml.safe_load(Path(cfg_path).read_text()) + out = Path(output_dir); out.mkdir(parents=True, exist_ok=True) + + # 2) Load data + data_dir = cfg["dataset"].get("path", "") + vecs, queries, gt = load_dataset(cfg["dataset"]["name"], data_dir) + + + nq = cfg["experiment"]["nq"] + queries, gt = queries[:nq], gt[:nq] + + # 3) Build or load index + build_params = IndexBuildParams() + build_params.nlist = cfg["index"]["nlist"] + build_params.metric = cfg["index"]["metric"] + build_params.num_workers = cfg["experiment"]["n_workers"] + + idx_dir = Path(cfg["paths"]["index_dir"]); idx_dir.mkdir(parents=True, exist_ok=True) + idx_path = idx_dir / f"{cfg['dataset']['name']}_ivf{build_params.nlist}.index" + + idx = QuakeIndex() + idx.build(vecs, torch.arange(len(vecs)), build_params) + logger.info(f"Loaded index → {idx_path} (workers={cfg['experiment']['n_workers']})") + + # 4) Run each method × recall_target + records = [] + k = cfg["experiment"]["k"] + max_nlist = build_params.nlist + + for method in cfg["methods"]: + for rt in cfg["experiment"]["recall_targets"]: + logger.info(f"Method={method} RecallTarget={rt}") + per_query = [] # collect (nprobe, recall, time_ms) tuples + + if method == "Oracle": + # per‐query binary search + for i, q in enumerate(queries): + lo, hi, best = 1, max_nlist, max_nlist + while lo <= hi: + mid = (lo + hi) // 2 + sp = SearchParams() + sp.nprobe = mid + sp.k = k + sp.recall_target = -1 + res = idx.search(q.unsqueeze(0), sp) + rec = compute_recall(res.ids, gt[i].unsqueeze(0), k).item() + if rec >= rt: + best = mid + hi = mid - 1 + else: + lo = mid + 1 + + # time at best + t0 = time.time() + sp = SearchParams() + sp.nprobe = best + sp.k = k + sp.recall_target = -1 + res = idx.search(q.unsqueeze(0), sp) + rec = compute_recall(res.ids, gt[i].unsqueeze(0), k).item() + elapsed = (time.time() - t0) * 1000.0 + per_query.append((best, rec, elapsed)) + + elif method == "FixedNProbe": + # find one global nprobe + lo, hi, best = 1, max_nlist, max_nlist + while lo <= hi: + mid = (lo + hi) // 2 + sp = SearchParams(nprobe=mid, k=k, recall_target=-1) + ids = [] + for q in queries: + ids.append(idx.search(q.unsqueeze(0), sp).ids) + avg_rec = compute_recall(torch.cat(ids,0), gt, k).mean().item() + if avg_rec >= rt: + best = mid + hi = mid - 1 + else: + lo = mid + 1 + + # then time each query at best + for q in queries: + t0 = time.time() + sp = SearchParams(nprobe=best, k=k, recall_target=-1) + res = idx.search(q.unsqueeze(0), sp) + elapsed = (time.time() - t0) * 1000.0 + rec = compute_recall(res.ids, gt[0:1], k).item() # single recall + per_query.append((best, rec, elapsed)) + + elif method == "APS": + # one‐shot APS per query + for q, true in zip(queries, gt): + sp = SearchParams() + sp.nprobe = -1 + sp.k = k + sp.recall_target = rt + sp.recompute_threshold = cfg["experiment"]["recompute_ratio"] + sp.use_precomputed = cfg["experiment"]["use_precompute"] + sp.initial_search_fraction = cfg["experiment"]["initial_search_fraction"] + t0 = time.time() + res = idx.search(q.unsqueeze(0), sp) + elapsed = (time.time() - t0) * 1000.0 + rec = compute_recall(res.ids, true.unsqueeze(0), k).item() + print(f"recall: {rec:.4f} (target={rt})") + per_query.append((res.timing_info.partitions_scanned, rec, elapsed)) + else: + raise ValueError(f"Unknown method: {method}") + + # 5) Aggregate + arr = np.array(per_query, dtype=float) # shape (nq,3) + records.append({ + "Method": method, + "RecallTarget": rt, + "mean_nprobe": arr[:,0].mean(), + "std_nprobe": arr[:,0].std(), + "mean_recall": arr[:,1].mean(), + "std_recall": arr[:,1].std(), + "mean_time_ms": arr[:,2].mean(), + "std_time_ms": arr[:,2].std(), + }) + + # 6) Save CSV + df = pd.DataFrame(records) + out_csv = out / "aps_recall_targets_summary.csv" + df.to_csv(out_csv, index=False) + logger.info(f"Summary → {out_csv}") + + # 7) Plot: recall-target vs time, one line per method + fig, axes = plt.subplots(3, 1, figsize=(6,8), sharex=True) + for m in df["Method"].unique(): + grp = df[df["Method"]==m] + axes[0].errorbar(grp["RecallTarget"], grp["mean_time_ms"], + yerr=grp["std_time_ms"], marker="o", capsize=4, label=m) + axes[1].errorbar(grp["RecallTarget"], grp["mean_recall"], + yerr=grp["std_recall"], marker="o", capsize=4, label=m) + axes[2].errorbar(grp["RecallTarget"], grp["mean_nprobe"], + yerr=grp["std_nprobe"], marker="o", capsize=4, label=m) + axes[0].set_xlabel("Recall Target") + axes[0].set_xlabel("Mean Query Time (ms)") + axes[0].set_title("APS‑Experiment: Recall Target vs Time") + axes[0].legend() + + recall_targets = cfg["experiment"]["recall_targets"] + + axes[1].plot(recall_targets, recall_targets, "k--", label="Target") + axes[1].set_xlabel("Recall Target") + axes[1].set_ylabel("Mean Recall") + axes[1].set_title("APS‑Experiment: Recall Target vs Recall") + + axes[2].set_xlabel("Recall Target") + axes[2].set_ylabel("Mean NProbe") + axes[2].set_yscale("log") + axes[2].set_title("APS‑Experiment: Recall Target vs NProbe") + + plt.grid(True, which="both", ls=":") + plt.tight_layout() + plot_path = out / "aps_recall_vs_time.png" + plt.savefig(plot_path) + logger.info(f"Plot → {plot_path}") \ No newline at end of file diff --git a/test/experiments/osdi2025/experiment_runner.py b/test/experiments/osdi2025/experiment_runner.py index fd3a02cf..9e443aab 100644 --- a/test/experiments/osdi2025/experiment_runner.py +++ b/test/experiments/osdi2025/experiment_runner.py @@ -1,62 +1,42 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ -Master runner for OSDI2025 vector‐search experiments. - -Usage: - python -m test.experiments.osdi2025.experiment_runner \ - --experiment \ - --config \ - --output-dir +Master runner for OSDI2025 vector‑search experiments. """ - import argparse from pathlib import Path -# Make sure `test/`, `test/experiments/`, and subfolders all have an __init__.py +from test.experiments.osdi2025.kick_the_tires.run import run_experiment as run_kick_the_tires from test.experiments.osdi2025.numa_single_query.run import run_experiment as run_numa_single from test.experiments.osdi2025.numa_multi_query.run import run_experiment as run_numa_multi +from test.experiments.osdi2025.aps_recall_targets.run import run_experiment as run_aps_recall EXPERIMENTS = { - "numa_single_query": run_numa_single, - "numa_multi_query": run_numa_multi, + "kick_the_tires": run_kick_the_tires, + "numa_single_query": run_numa_single, + "numa_multi_query": run_numa_multi, + "aps_recall_targets": run_aps_recall, } def main(): - parser = argparse.ArgumentParser( - description="Run one OSDI2025 experiment" - ) - parser.add_argument( - "-x", "--experiment", - choices=EXPERIMENTS.keys(), - required=True, - help="Which experiment to run" - ) - parser.add_argument( - "-c", "--config", - required=True, - help="Config name (without .yaml) under configs/" - ) - parser.add_argument( - "-o", "--output-dir", - default=None, - help="Where to write results (csv + plots)" - ) + parser = argparse.ArgumentParser(description="Run one OSDI2025 experiment") + parser.add_argument("-x","--experiment", choices=EXPERIMENTS.keys(), required=True) + parser.add_argument("-c","--config", required=True, + help="Config name (without .yaml) under configs/") + parser.add_argument("-o","--output-dir", default=None, + help="Where to write results (csv + plots)") args = parser.parse_args() - exp = args.experiment - cfg_name = args.config base = Path(__file__).resolve().parent - cfg_path = base / exp / "configs" / f"{cfg_name}.yaml" + cfg_path = base / args.experiment / "configs" / f"{args.config}.yaml" if not cfg_path.is_file(): raise FileNotFoundError(f"Missing config: {cfg_path}") - # compute output directory - out_dir = Path(args.output_dir) if args.output_dir else base / exp / "results" / cfg_name + out_dir = Path(args.output_dir) if args.output_dir \ + else base / args.experiment / "results" / args.config out_dir.mkdir(parents=True, exist_ok=True) - # call the appropriate experiment - runner = EXPERIMENTS[exp] - runner(str(cfg_path), str(out_dir)) + # dispatch + EXPERIMENTS[args.experiment](str(cfg_path), str(out_dir)) if __name__ == "__main__": main() \ No newline at end of file diff --git a/test/experiments/osdi2025/kick_the_tires/run.py b/test/experiments/osdi2025/kick_the_tires/run.py new file mode 100644 index 00000000..7ac0bfc9 --- /dev/null +++ b/test/experiments/osdi2025/kick_the_tires/run.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +""" +""" + +import time +import yaml +import logging +from pathlib import Path + +import torch +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt + +from quake.index_wrappers.quake import QuakeWrapper +from quake.index_wrappers.faiss_ivf import FaissIVF +from quake.datasets.ann_datasets import load_dataset +from quake.utils import compute_recall +from quake.workload_generator import DynamicWorkloadGenerator, WorkloadEvaluator + +logger = logging.getLogger(__name__) + +def run_experiment(cfg_path: str, output_dir: str): + cfg = yaml.safe_load(Path(cfg_path).read_text()) + out = Path(output_dir); out.mkdir(parents=True, exist_ok=True) + + data_dir = cfg["dataset"].get("path", "") + vectors, queries, gt = load_dataset(cfg["dataset"]["name"], data_dir) + + metric = cfg["dataset"]["metric"] + print(f"Dataset loaded: vectors {vectors.shape}, queries {queries.shape}") + + insert_ratio = cfg["workload_generator"]["insert_ratio"] + delete_ratio = cfg["workload_generator"]["delete_ratio"] + query_ratio = cfg["workload_generator"]["query_ratio"] + update_batch_size = cfg["workload_generator"]["update_batch_size"] + query_batch_size = cfg["workload_generator"]["query_batch_size"] + number_of_operations = cfg["workload_generator"]["number_of_operations"] + initial_size = cfg["workload_generator"]["initial_size"] + cluster_size = cfg["workload_generator"]["cluster_size"] + cluster_sample_distribution = cfg["workload_generator"]["cluster_sample_distribution"] + query_cluster_sample_distribution = cfg["workload_generator"]["query_cluster_sample_distribution"] + seed = cfg["workload_generator"]["seed"] + + overwrite_workload = cfg["overwrite"]["workload"] + + print(out) + + generator = DynamicWorkloadGenerator( + workload_dir=out, + base_vectors=vectors, + metric=metric, + insert_ratio=insert_ratio, + delete_ratio=delete_ratio, + query_ratio=query_ratio, + update_batch_size=update_batch_size, + query_batch_size=query_batch_size, + number_of_operations=number_of_operations, + initial_size=initial_size, + cluster_size=cluster_size, + cluster_sample_distribution=cluster_sample_distribution, + queries=queries, + query_cluster_sample_distribution=query_cluster_sample_distribution, + seed=seed, + ) + + if generator.workload_exists() and not overwrite_workload: + print("Workload already exists, skipping generation.") + else: + # Generate the workload (operations are saved to disk along with a runbook) + print("Generating workload...") + generator.generate_workload() + + print("Evaluating workload...") + + for index_cfg in cfg["indexes"]: + name = index_cfg["name"] + print(f"\nEvaluating index: {name}") + curr_results_dir = out / name + curr_results_dir.mkdir(parents=True, exist_ok=True) + evaluator = WorkloadEvaluator(workload_dir=out, output_dir=curr_results_dir) + # Define search parameters for evaluation (e.g., number of neighbors and workers) + build_params = index_cfg["build_params"] + search_params = index_cfg["search_params"] + + if name == "Quake": + # Initialize the Quake index + index = QuakeWrapper() + elif name == "IVF": + index = FaissIVF() + else: + raise ValueError(f"Unknown index type: {name}") + + evaluator.evaluate_workload(name, index, build_params, search_params, do_maintenance=True) + print(f"Evaluation completed for index {name}") \ No newline at end of file From 7d34be046f9f9fb66bb98797fceef52e08415ca4 Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 4 May 2025 21:26:35 -0500 Subject: [PATCH 019/323] multi-level changes --- src/cpp/bindings/wrap.cpp | 8 + src/cpp/include/common.h | 8 +- src/cpp/include/geometry.h | 8 + src/cpp/include/quake_index.h | 2 + src/cpp/src/partition_manager.cpp | 7 +- src/cpp/src/quake_index.cpp | 36 ++- src/cpp/src/query_coordinator.cpp | 23 +- src/python/index_wrappers/quake.py | 24 +- src/python/workload_generator.py | 7 + test/cpp/benchmark.cpp | 16 +- test/cpp/quake_index.cpp | 33 +- .../osdi2025/kick_the_tires/run.py | 283 +++++++++++++----- 12 files changed, 354 insertions(+), 101 deletions(-) diff --git a/src/cpp/bindings/wrap.cpp b/src/cpp/bindings/wrap.cpp index 1ef561bd..527aebad 100644 --- a/src/cpp/bindings/wrap.cpp +++ b/src/cpp/bindings/wrap.cpp @@ -69,6 +69,10 @@ PYBIND11_MODULE(_bindings, m) { " - num_workers: default = " + std::to_string(DEFAULT_NUM_WORKERS); return doc.c_str(); })()) + .def("add_level", &QuakeIndex::add_level, + "Add a new level to the index.\n\n" + "Args:\n" + " build_params (IndexBuildParams): Parameters for building the new level.") .def("search", &QuakeIndex::search, ([]() -> const char* { static const std::string doc = std::string("Search the index for nearest neighbors.\n\n" @@ -138,6 +142,8 @@ PYBIND11_MODULE(_bindings, m) { (std::string("Distance metric. default = ") + DEFAULT_METRIC).c_str()) .def_readwrite("num_workers", &IndexBuildParams::num_workers, (std::string("Number of workers. default = ") + std::to_string(DEFAULT_NUM_WORKERS)).c_str()) + .def_readwrite("parent_params", &IndexBuildParams::parent_params, + "Parameters for the parent index, if any.") .def("__repr__", [](const IndexBuildParams &p) { std::ostringstream oss; oss << "{"; @@ -170,6 +176,8 @@ PYBIND11_MODULE(_bindings, m) { (std::string("Threshold to trigger recomputation of APS. default = ") + std::to_string(DEFAULT_RECOMPUTE_THRESHOLD)).c_str()) .def_readwrite("aps_flush_period_us", &SearchParams::aps_flush_period_us, (std::string("APS flush period in microseconds. default = ") + std::to_string(DEFAULT_APS_FLUSH_PERIOD_US)).c_str()) + .def_readwrite("parent_params", &SearchParams::parent_params, + "Search parameters for the parent index, if any.") .def("__repr__", [](const SearchParams &s) { std::ostringstream oss; oss << "{"; diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index eba6dc3a..69d67fc5 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -180,13 +180,7 @@ struct SearchParams { float initial_search_fraction = DEFAULT_INITIAL_SEARCH_FRACTION; int aps_flush_period_us = DEFAULT_APS_FLUSH_PERIOD_US; - // early termination params - float spann_threshold = 1.25f; // prune all centroids with distance > 1.25 * min_distance - - float auncel_a = 0.5f; // auncel's parameter - float auncel_b = 0.5f; // auncel's parameter - - + shared_ptr parent_params = nullptr; ///< Search parameters for the parent index, if any. SearchParams() = default; }; diff --git a/src/cpp/include/geometry.h b/src/cpp/include/geometry.h index 5573082e..465ef1b1 100644 --- a/src/cpp/include/geometry.h +++ b/src/cpp/include/geometry.h @@ -627,6 +627,14 @@ compute_recall_profile(const std::vector& boundary_distances, // Or fallback: goto method1_label; (using labels/goto is generally discouraged) } + // if the cluster_sizes are given, we can use them to scale the probabilities + if (partition_sizes.size() > 0) { + for (int k = 1; k < m; ++k) { + if (partition_sizes[k] > 0) { + P_prime[k] *= static_cast(partition_sizes[k]); + } + } + } // --- Final Normalization --- std::vector probs(m, 0.0f); diff --git a/src/cpp/include/quake_index.h b/src/cpp/include/quake_index.h index c0cccc21..900ecdab 100644 --- a/src/cpp/include/quake_index.h +++ b/src/cpp/include/quake_index.h @@ -49,6 +49,8 @@ class QuakeIndex { */ shared_ptr build(Tensor x, Tensor ids, shared_ptr build_params); + void add_level(shared_ptr params); + /** * @brief Search for vectors in the index. * @param x Tensor of shape [num_queries, dimension]. diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index 240e2f82..18e09c6c 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -679,7 +679,12 @@ Tensor PartitionManager::get_partition_sizes(Tensor partition_ids) { auto partition_sizes_accessor = partition_sizes.accessor(); for (int i = 0; i < partition_ids.size(0); i++) { int64_t list_no = partition_ids_accessor[i]; - partition_sizes_accessor[i] = partition_store_->list_size(list_no); + if (list_no == -1) { + partition_sizes_accessor[i] = 0; + } else { + partition_sizes_accessor[i] = partition_store_->list_size(list_no); + } + if (debug_) { std::cout << "[PartitionManager] get_partition_sizes: Partition " << list_no << " size: " << partition_sizes_accessor[i] << std::endl; diff --git a/src/cpp/src/quake_index.cpp b/src/cpp/src/quake_index.cpp index 1f7cc853..0aadd869 100644 --- a/src/cpp/src/quake_index.cpp +++ b/src/cpp/src/quake_index.cpp @@ -55,9 +55,14 @@ shared_ptr QuakeIndex::build(Tensor x, Tensor ids, shared_ptr(current_level_ + 1); + auto parent_build_params = make_shared(); - parent_build_params->metric = build_params_->metric; - parent_build_params->num_workers = build_params_->num_workers; + if (build_params->parent_params == nullptr) { + parent_build_params->metric = build_params_->metric; + parent_build_params->num_workers = build_params_->num_workers; + } else { + parent_build_params = build_params_->parent_params; + } parent_->build(clustering->centroids, clustering->partition_ids, parent_build_params); // initialize the partition manager @@ -89,6 +94,25 @@ shared_ptr QuakeIndex::build(Tensor x, Tensor ids, shared_ptr params) { + + if (!parent_) { + throw std::runtime_error("[QuakeIndex::add_level()] No parent index. Cannot add level."); + } + + if (parent_->parent_) { + parent_->add_level(params); + } else { + // create an index over the centroids + + // get all centroids and their ids + Tensor ids = parent_->partition_manager_->get_ids(); + Tensor centroids = parent_->partition_manager_->get(ids); + + parent_->build(centroids, ids, params); + } +} + shared_ptr QuakeIndex::search(Tensor x, shared_ptr search_params) { @@ -159,7 +183,13 @@ shared_ptr QuakeIndex::maintenance() { throw std::runtime_error("[QuakeIndex::maintenance()] No maintenance policy set."); } - return maintenance_policy_->perform_maintenance(); + auto maintenance_info = maintenance_policy_->perform_maintenance(); + + if (parent_->maintenance_policy_) { + parent_->maintenance_policy_->perform_maintenance(); + } + + return maintenance_info; } bool QuakeIndex::validate() { diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 92b0ac84..588644ca 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -530,6 +530,8 @@ shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partitio auto t2 = high_resolution_clock::now(); + + Tensor partition_sizes = partition_manager_->get_partition_sizes(partition_ids[q]); vector partition_sizes_vec = vector(partition_sizes.data_ptr(), partition_sizes.data_ptr() + partition_sizes.size(0)); @@ -591,7 +593,7 @@ shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partitio partition_probs = compute_recall_profile(boundary_distances, query_radius, dimension, - {}, + partition_sizes_vec, search_params->use_precomputed, metric_ == faiss::METRIC_L2); } @@ -614,8 +616,6 @@ shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partitio // mark the partitions as scanned maintenance_policy_->record_query_hits(scanned_ids); - std::cout << "Query " << q << " partitions scanned: " << scanned_ids.size() << std::endl; - std::cout << "Total queries processed: " << maintenance_policy_->hit_count_tracker_->get_num_queries_recorded() << std::endl; // std::cout << "Query " << q << " times: " << duration_cast(t2 - t1).count() << " " // << duration_cast(t3 - t2).count() << " " @@ -667,15 +667,20 @@ shared_ptr QueryCoordinator::search(Tensor x, shared_ptrnlist(), torch::kInt64); } else { - auto parent_search_params = make_shared(); - parent_search_params->recall_target = search_params->recall_target; - parent_search_params->use_precomputed = search_params->use_precomputed; - parent_search_params->recompute_threshold = search_params->recompute_threshold; - parent_search_params->batched_scan = true; + + auto parent_search_params = make_shared(); + if (search_params->parent_params == nullptr) { + parent_search_params->recall_target = .99; + parent_search_params->use_precomputed = search_params->use_precomputed; + parent_search_params->recompute_threshold = search_params->recompute_threshold; + parent_search_params->batched_scan = false; + } else { + parent_search_params = search_params->parent_params; + } // if recall_target is set, we need an initial set of partitions to consider - if (parent_search_params->recall_target > 0.0 && !search_params->batched_scan) { + if (search_params->recall_target > 0.0 && !search_params->batched_scan) { int initial_num_partitions_to_search = std::max( (int) (partition_manager_->nlist() * search_params->initial_search_fraction), 1); parent_search_params->k = initial_num_partitions_to_search; diff --git a/src/python/index_wrappers/quake.py b/src/python/index_wrappers/quake.py index 6c1fffb8..b5b4aa5b 100644 --- a/src/python/index_wrappers/quake.py +++ b/src/python/index_wrappers/quake.py @@ -42,10 +42,21 @@ def index_state(self) -> dict: :return: The state of the index as a dictionary. """ - return { + state = { "n_list": self.index.nlist(), "n_total": self.index.ntotal(), } + # # if has parent get the parent nlist + # if self.index.parent.parent: + # state["n_list1"] = self.index.parent.parent.nlist() + + # get all the parents + curr = self.index.parent + while curr.parent: + state["n_list1"] = curr.nlist() + curr = curr.parent + + return state def build( self, @@ -56,6 +67,7 @@ def build( num_workers: int = 0, m: int = -1, code_size: int = 8, + parent=None, ): """ Build the index with the given vectors and arguments. @@ -79,6 +91,10 @@ def build( build_params.nlist = nc build_params.num_workers = num_workers + if parent is not None: + build_params.parent_params = quake.IndexBuildParams() + build_params.parent_params.nlist = parent.get("nlist", 1) + self.index = QuakeIndex() if ids is None: @@ -125,6 +141,7 @@ def search( recompute_threshold=0.1, aps_flush_period_us=50, n_threads=1, + parent=None, ) -> Tuple[torch.Tensor, torch.Tensor]: """ Find the k-nearest neighbors of the query vectors. @@ -146,6 +163,11 @@ def search( search_params.k = k search_params.num_threads = n_threads + if parent is not None: + search_params.parent_params = quake.SearchParams() + search_params.parent_params.nprobe = parent.get("nprobe", 1) + search_params.parent_params.recall_target = parent.get("recall_target", -1) + return self.index.search(query, search_params) def maintenance(self): diff --git a/src/python/workload_generator.py b/src/python/workload_generator.py index abe8eb0e..302da3c3 100644 --- a/src/python/workload_generator.py +++ b/src/python/workload_generator.py @@ -6,6 +6,7 @@ import matplotlib.pyplot as plt import numpy as np +import pandas as pd import torch from quake import SearchParams @@ -414,6 +415,7 @@ def initialize_index(self, name, index, build_params, m_params): initial_indices = torch.load(self.initial_indices_path, weights_only=True).to(torch.int64) vectors = vectors[initial_indices] if not index_path.exists(): + print(build_params) index.build(vectors, ids=initial_indices, **build_params) index.save(index_path) print(f"Index {name} built and saved to {index_path}") @@ -606,4 +608,9 @@ def evaluate_workload( print(f"Saved evaluation plots to {plot_path}") plt.close() + df = pd.DataFrame(results) + csv_path = self.output_dir / "results.csv" + df.to_csv(csv_path, index=False) + print(f"Saved results to {csv_path}") + return results diff --git a/test/cpp/benchmark.cpp b/test/cpp/benchmark.cpp index e2802a1a..dc6b454f 100644 --- a/test/cpp/benchmark.cpp +++ b/test/cpp/benchmark.cpp @@ -497,20 +497,32 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { int64_t dimension = 128; int64_t num_vectors = 100000; - int64_t num_queries = 1; + int64_t num_queries = 100; int64_t batch_size = 10000; int n_ops = 100; QuakeIndex index; auto build_params = std::make_shared(); - build_params->nlist = 1000; + build_params->nlist = 2500; build_params->metric = "l2"; build_params->niter = 5; + auto maintenance_params = std::make_shared(); + maintenance_params->refinement_radius = 10; + maintenance_params->refinement_iterations = 1; + Tensor data_vectors = torch::randn({num_vectors, dimension}, torch::kFloat32); Tensor data_ids = torch::arange(num_vectors, torch::kInt64); index.build(data_vectors, data_ids, build_params); + index.initialize_maintenance_policy(maintenance_params); + + // add level + auto parent_index_build_params = std::make_shared(); + parent_index_build_params->nlist = 250; + parent_index_build_params->metric = "l2"; + parent_index_build_params->niter = 5; + index.add_level(parent_index_build_params); // timers int64_t search_time = 0; diff --git a/test/cpp/quake_index.cpp b/test/cpp/quake_index.cpp index 22e9325e..1c94f2b5 100644 --- a/test/cpp/quake_index.cpp +++ b/test/cpp/quake_index.cpp @@ -25,7 +25,7 @@ class QuakeIndexTest : public ::testing::Test { // Example parameters int64_t dimension_ = 16; int64_t nlist_ = 8; - int64_t num_vectors_ = 100; + int64_t num_vectors_ = 1000; int64_t num_queries_ = 5; // Data & IDs @@ -479,6 +479,37 @@ TEST(QuakeIndexStressTest, HighDimensionTest) { ASSERT_EQ(result->ids.size(1), search_params->k); } +TEST_F(QuakeIndexTest, AddLevelTest) +{ + QuakeIndex index; + + // 1. Build a 2‑level index (leaf + one parent) + auto bp = std::make_shared(); + bp->nlist = 100; + bp->metric = "l2"; + index.build(data_vectors_, data_ids_, bp); + + const int64_t leaf_partitions = index.nlist(); // = nlist_ + + // 2. Add a *new* level on top + auto top_bp = std::make_shared(); + top_bp->nlist = 10; // flat over centroids + top_bp->metric = "l2"; + index.add_level(top_bp); + + // root now has a parent + ASSERT_NE(index.parent_, nullptr); + // that parent should have exactly `leaf_partitions` vectors (one per centroid) + EXPECT_EQ(index.parent_->ntotal(), leaf_partitions); + + // 3. Ensure we can still search and retrieve sane results + auto sp = std::make_shared(); + sp->k = 3; + auto res = index.search(query_vectors_, sp); + ASSERT_EQ(res->ids.size(0), query_vectors_.size(0)); + ASSERT_EQ(res->ids.size(1), sp->k); +} + // Define the GPU related test only if FAISS GPU support is enabled #ifdef FAISS_ENABLE_GPU // Test build with GPU enabled diff --git a/test/experiments/osdi2025/kick_the_tires/run.py b/test/experiments/osdi2025/kick_the_tires/run.py index 7ac0bfc9..13a08248 100644 --- a/test/experiments/osdi2025/kick_the_tires/run.py +++ b/test/experiments/osdi2025/kick_the_tires/run.py @@ -1,95 +1,224 @@ #!/usr/bin/env python3 """ +Unified experiment runner + +* Reads a single YAML config (`configs/experiment.yaml`). +* Modes + - **build** –‑ only (re‑)generate the workload. + - **run** –‑ generate workload (if needed), evaluate every index that + does not already have a CSV of prior results (unless + `overwrite.results: true`), then emit the unified plot. + - **plot** –‑ skip evaluation; just regenerate the unified plot. +* A results CSV (`//results.csv`) is written after every + evaluation; its presence is what lets us skip reruns. +* Plot styling (colour / marker / linestyle) is entirely configurable from + the YAML under `plot.styles`. """ -import time -import yaml import logging +import sys +import time from pathlib import Path +from typing import Dict, List -import torch -import pandas as pd -import numpy as np import matplotlib.pyplot as plt +from matplotlib.lines import Line2D +import numpy as np +import pandas as pd +import torch +import yaml -from quake.index_wrappers.quake import QuakeWrapper -from quake.index_wrappers.faiss_ivf import FaissIVF +# ── quake imports ────────────────────────────────────────────────────────────── from quake.datasets.ann_datasets import load_dataset +from quake.index_wrappers.faiss_ivf import FaissIVF +from quake.index_wrappers.quake import QuakeWrapper from quake.utils import compute_recall from quake.workload_generator import DynamicWorkloadGenerator, WorkloadEvaluator logger = logging.getLogger(__name__) -def run_experiment(cfg_path: str, output_dir: str): - cfg = yaml.safe_load(Path(cfg_path).read_text()) - out = Path(output_dir); out.mkdir(parents=True, exist_ok=True) - - data_dir = cfg["dataset"].get("path", "") - vectors, queries, gt = load_dataset(cfg["dataset"]["name"], data_dir) - - metric = cfg["dataset"]["metric"] - print(f"Dataset loaded: vectors {vectors.shape}, queries {queries.shape}") - - insert_ratio = cfg["workload_generator"]["insert_ratio"] - delete_ratio = cfg["workload_generator"]["delete_ratio"] - query_ratio = cfg["workload_generator"]["query_ratio"] - update_batch_size = cfg["workload_generator"]["update_batch_size"] - query_batch_size = cfg["workload_generator"]["query_batch_size"] - number_of_operations = cfg["workload_generator"]["number_of_operations"] - initial_size = cfg["workload_generator"]["initial_size"] - cluster_size = cfg["workload_generator"]["cluster_size"] - cluster_sample_distribution = cfg["workload_generator"]["cluster_sample_distribution"] - query_cluster_sample_distribution = cfg["workload_generator"]["query_cluster_sample_distribution"] - seed = cfg["workload_generator"]["seed"] - - overwrite_workload = cfg["overwrite"]["workload"] - - print(out) - - generator = DynamicWorkloadGenerator( - workload_dir=out, - base_vectors=vectors, - metric=metric, - insert_ratio=insert_ratio, - delete_ratio=delete_ratio, - query_ratio=query_ratio, - update_batch_size=update_batch_size, - query_batch_size=query_batch_size, - number_of_operations=number_of_operations, - initial_size=initial_size, - cluster_size=cluster_size, - cluster_sample_distribution=cluster_sample_distribution, - queries=queries, - query_cluster_sample_distribution=query_cluster_sample_distribution, - seed=seed, + +LAT_STYLES = {"insert": "--", "delete": "-.", "query": "-"} + +def unified_plot(cfg: Dict, output_dir: Path) -> None: + """Produce a 4‑panel plot with: + • one figure‑level legend (colour → index) + • latency‑panel legend (linestyle → op‑type)""" + styles = cfg["plot"].get("styles", {}) + + # ── collect colours / markers per index for global legend ──────────────── + index_handles = [] + for idx_cfg in cfg["indexes"]: + name = idx_cfg["name"] + st = styles.get(name, {}) + index_handles.append( + Line2D( + [0], + [0], + color=st.get("color", None), + marker=None, + linestyle="-", + label=name, + ) + ) + + fig, axs = plt.subplots(2, 2, figsize=(12, 10)) + + # ── panel references ───────────────────────────────────────────────────── + ax_lat, ax_part = axs[0] + ax_res, ax_rec = axs[1] + + # ── plot per index ─────────────────────────────────────────────────────── + for idx_cfg in cfg["indexes"]: + name = idx_cfg["name"] + csv = output_dir / name / "results.csv" + if not csv.exists(): + logger.warning("Skipping %s (no CSV).", name); continue + + df = pd.read_csv(csv) + st = styles.get(name, {}) + color, marker = st.get("color", None), st.get("marker", None) + + # A – latency + for op in ("insert", "delete", "query"): + sub = df[df["operation_type"] == op] + if not sub.empty: + ax_lat.plot( + sub["operation_number"], sub["latency_ms"], + color=color, linestyle=LAT_STYLES[op], marker=None) + + ax_lat.set_yscale("log") + + # B – partitions + sub = df[df["n_list"].notna()] + if not sub.empty: + ax_part.plot(sub["operation_number"], sub["n_list"], + color=color, marker=marker) + + # C – resident vectors + sub = df[df["n_resident"].notna()] + if not sub.empty: + ax_res.plot(sub["operation_number"], sub["n_resident"], + color=color, marker=marker) + + # D – query recall + sub = df[(df["operation_type"] == "query") & df["recall"].notna()] + if not sub.empty: + ax_rec.plot(sub["operation_number"], sub["recall"], + color=color, marker=marker) + + # ── format panels (titles, axes) ───────────────────────────────────────── + ax_lat.set_title("Operation Latency") + ax_lat.set_xlabel("Operation Number"); ax_lat.set_ylabel("Latency (ms)") + + ax_part.set_title("Partitions per Operation") + ax_part.set_xlabel("Operation Number"); ax_part.set_ylabel("Number of Partitions") + + ax_res.set_title("Resident Set Size") + ax_res.set_xlabel("Operation Number"); ax_res.set_ylabel("Resident Vectors") + + ax_rec.set_title("Query Recall") + ax_rec.set_xlabel("Operation Number"); ax_rec.set_ylabel("Recall") + + # legends + # latency‑style legend (insert/delete/query) + style_handles = [ + Line2D([0], [0], color="k", linestyle=LAT_STYLES[op], label=op.capitalize()) + for op in ("insert", "delete", "query") + ] + ax_lat.legend(handles=style_handles, title="Operation Type", fontsize=8) + + # global colour legend (index names) + fig.legend( + handles=index_handles, + loc="upper center", + bbox_to_anchor=(0.5, 1.02), + ncol=max(1, len(index_handles)), + title="Index", ) - if generator.workload_exists() and not overwrite_workload: - print("Workload already exists, skipping generation.") - else: - # Generate the workload (operations are saved to disk along with a runbook) - print("Generating workload...") - generator.generate_workload() - - print("Evaluating workload...") - - for index_cfg in cfg["indexes"]: - name = index_cfg["name"] - print(f"\nEvaluating index: {name}") - curr_results_dir = out / name - curr_results_dir.mkdir(parents=True, exist_ok=True) - evaluator = WorkloadEvaluator(workload_dir=out, output_dir=curr_results_dir) - # Define search parameters for evaluation (e.g., number of neighbors and workers) - build_params = index_cfg["build_params"] - search_params = index_cfg["search_params"] - - if name == "Quake": - # Initialize the Quake index - index = QuakeWrapper() - elif name == "IVF": - index = FaissIVF() - else: - raise ValueError(f"Unknown index type: {name}") + plt.tight_layout() + out_path = output_dir / "unified_plot.png" + plt.savefig(out_path, bbox_inches="tight") + plt.close() + print(f"Saved unified plot → {out_path}") + - evaluator.evaluate_workload(name, index, build_params, search_params, do_maintenance=True) - print(f"Evaluation completed for index {name}") \ No newline at end of file +# ─────────────────────────────────────────────────────────────────────────────── +# main execution +# ─────────────────────────────────────────────────────────────────────────────── +def run_experiment(cfg_path: str, output_dir: str) -> None: + cfg = yaml.safe_load(Path(cfg_path).read_text()) + out = Path(output_dir) + out.mkdir(parents=True, exist_ok=True) + + mode = cfg.get("mode", "run") + overwrite = cfg.get("overwrite", {}) + overwrite_workload = overwrite.get("workload", False) + overwrite_results = overwrite.get("results", False) + + # ── build / run both need the dataset loaded ─────────────────────────────── + if mode in {"build", "run"}: + data_cfg = cfg["dataset"] + vectors, queries, _ = load_dataset(data_cfg["name"], data_cfg.get("path", "")) + metric = data_cfg["metric"] + print(f"Dataset loaded: vectors {vectors.shape}, queries {queries.shape}") + + # ── workload generation (build or run) ───────────────────────────────────── + if mode in {"build", "run"}: + wg_cfg = cfg["workload_generator"] + generator = DynamicWorkloadGenerator( + workload_dir=out, + base_vectors=vectors, + metric=metric, + insert_ratio=wg_cfg["insert_ratio"], + delete_ratio=wg_cfg["delete_ratio"], + query_ratio=wg_cfg["query_ratio"], + update_batch_size=wg_cfg["update_batch_size"], + query_batch_size=wg_cfg["query_batch_size"], + number_of_operations=wg_cfg["number_of_operations"], + initial_size=wg_cfg["initial_size"], + cluster_size=wg_cfg["cluster_size"], + cluster_sample_distribution=wg_cfg["cluster_sample_distribution"], + queries=queries, + query_cluster_sample_distribution=wg_cfg["query_cluster_sample_distribution"], + seed=wg_cfg["seed"], + ) + + if generator.workload_exists() and not overwrite_workload: + print("Workload already exists – skipping generation.") + else: + print("Generating workload …") + generator.generate_workload() + + # ── evaluation pass (run mode only) ──────────────────────────────────────── + if mode == "run": + for idx_cfg in cfg["indexes"]: + name = idx_cfg["name"] + index_type = idx_cfg["index"] + res_dir = out / name + csv_path = res_dir / "results.csv" + need_eval = overwrite_results or not csv_path.exists() + + if need_eval: + print(f"\nIndex {name}: running evaluation.") + res_dir.mkdir(parents=True, exist_ok=True) + evaluator = WorkloadEvaluator(workload_dir=out, output_dir=res_dir) + + index = {"Quake": QuakeWrapper, "IVF": FaissIVF}.get(index_type) + if index is None: + raise ValueError(f"Unknown index type: {index_type}") + + results = evaluator.evaluate_workload( + name=name, + index=index(), + build_params=idx_cfg["build_params"], + search_params=idx_cfg["search_params"], + do_maintenance=True, + ) + else: + print(f"\nIndex {name}: using cached results ({csv_path}).") + + # ── generate / regenerate the unified plot ───────────────────────────────── + if mode in {"run", "plot"}: + unified_plot(cfg, out) \ No newline at end of file From 2558fa4e612739fa25dc370e56afb946950ec02a Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 6 May 2025 09:23:30 -0500 Subject: [PATCH 020/323] multi-level fixes --- src/cpp/include/common.h | 1 + src/cpp/include/partition_manager.h | 1 + src/cpp/src/clustering.cpp | 1 + src/cpp/src/dynamic_inverted_list.cpp | 28 +++-- src/cpp/src/index_partition.cpp | 7 +- src/cpp/src/maintenance_policies.cpp | 4 + src/cpp/src/partition_manager.cpp | 17 ++- src/cpp/src/quake_index.cpp | 6 +- src/cpp/src/query_coordinator.cpp | 45 ++++++-- src/python/index_wrappers/quake.py | 3 +- src/python/workload_generator.py | 4 +- test/cpp/benchmark.cpp | 156 ++++++++++++++------------ test/cpp/quake_multi_level.cpp | 103 +++++++++++++++++ 13 files changed, 271 insertions(+), 105 deletions(-) create mode 100644 test/cpp/quake_multi_level.cpp diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index 69d67fc5..be85509e 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -179,6 +179,7 @@ struct SearchParams { float recompute_threshold = DEFAULT_RECOMPUTE_THRESHOLD; float initial_search_fraction = DEFAULT_INITIAL_SEARCH_FRACTION; int aps_flush_period_us = DEFAULT_APS_FLUSH_PERIOD_US; + bool track_hits = true; shared_ptr parent_params = nullptr; ///< Search parameters for the parent index, if any. diff --git a/src/cpp/include/partition_manager.h b/src/cpp/include/partition_manager.h index 9a5018a2..b0ade908 100644 --- a/src/cpp/include/partition_manager.h +++ b/src/cpp/include/partition_manager.h @@ -26,6 +26,7 @@ class PartitionManager { shared_ptr parent_ = nullptr; ///< Pointer to a higher-level parent index. std::shared_ptr partition_store_ = nullptr; ///< Pointer to the inverted lists. int64_t curr_partition_id_ = 0; ///< Current partition ID. + int num_workers_ = 0; ///< Number of workers for parallel processing. bool debug_ = false; ///< If true, print debug information. bool check_uniques_ = false; ///< If true, check that vector IDs are unique and don't already exist in the index. diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index ebbc88e0..a034b32e 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -133,6 +133,7 @@ tuple >> kmeans_refine_partitions( new_partitions[i] = make_shared(); new_partitions[i]->set_code_size(partitions[0]->code_size_); new_partitions[i]->resize(10); + new_partitions[i]->set_core_id(partitions[i]->core_id_); } float *centroids_ptr = centroids.data_ptr(); diff --git a/src/cpp/src/dynamic_inverted_list.cpp b/src/cpp/src/dynamic_inverted_list.cpp index d51d14b6..b4573402 100644 --- a/src/cpp/src/dynamic_inverted_list.cpp +++ b/src/cpp/src/dynamic_inverted_list.cpp @@ -311,30 +311,42 @@ void DynamicInvertedLists::batch_update_entries( bool DynamicInvertedLists::get_vector_for_id(idx_t id, float *out) { if (id_to_location_.empty()) build_map(); + if (id < 0) { + std::memset(out, 0, code_size_); + return true; + } + auto it = id_to_location_.find(id); if (it == id_to_location_.end()) return false; + IndexPartition* part = it->second.first; int64_t pos = it->second.second; std::memcpy(out, part->codes_ + pos * part->code_size_, part->code_size_); return true; } - vector DynamicInvertedLists::get_vectors_by_id(vector ids) { + vector DynamicInvertedLists::get_vectors_by_id(vector ids) + { if (id_to_location_.empty()) build_map(); - vector ret; - ret.reserve(ids.size()); + vector ret; ret.reserve(ids.size()); for (int64_t id : ids) { - auto it = id_to_location_.find(id); - if (it == id_to_location_.end()) { - throw std::runtime_error("ID not found in any partition"); + if (id < 0) { + ret.push_back(nullptr); + continue; } + + auto it = id_to_location_.find(id); + if (it == id_to_location_.end()) + throw std::runtime_error("ID not found in any partition: " + std::to_string(id)); + IndexPartition* part = it->second.first; - int64_t pos = it->second.second; + int64_t pos = it->second.second; ret.push_back(reinterpret_cast(part->codes_ + pos * part->code_size_)); } return ret; + } // vector ret; // for (int64_t id : ids) { @@ -353,7 +365,7 @@ void DynamicInvertedLists::batch_update_entries( // } // } // return ret; - } + // } size_t DynamicInvertedLists::get_new_list_id() { return curr_list_id_++; diff --git a/src/cpp/src/index_partition.cpp b/src/cpp/src/index_partition.cpp index 87e4992d..49d5eb3b 100644 --- a/src/cpp/src/index_partition.cpp +++ b/src/cpp/src/index_partition.cpp @@ -78,11 +78,10 @@ void IndexPartition::update(int64_t offset, int64_t n_entry, const idx_t* new_id int64_t IndexPartition::remove(int64_t idx) { - assert(idx >= 0 && idx < num_vectors_); + if (idx < 0 || idx >= num_vectors_) { + throw std::runtime_error("Index out of range in remove"); + } const int64_t last = num_vectors_ - 1; - - // optional: bookkeeping for norms, etc. - if (idx != last) { // swap last -> idx std::memcpy(codes_ + idx * code_size_, codes_ + last * code_size_, diff --git a/src/cpp/src/maintenance_policies.cpp b/src/cpp/src/maintenance_policies.cpp index 21ced2bb..6ad450c6 100644 --- a/src/cpp/src/maintenance_policies.cpp +++ b/src/cpp/src/maintenance_policies.cpp @@ -33,6 +33,10 @@ MaintenancePolicy::MaintenancePolicy( shared_ptr MaintenancePolicy::perform_maintenance() { // only consider split/deletion once the window is full + if (partition_manager_->parent_ == nullptr) { + return std::make_shared(); + } + int64_t num_queries = hit_count_tracker_->get_num_queries_recorded(); if (hit_count_tracker_->get_num_queries_recorded() < params_->window_size) { std::cout << "Window not full yet. " << num_queries << " queries recorded and " << params_->window_size diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index 18e09c6c..780b1342 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -484,6 +484,8 @@ void PartitionManager::refine_partitions(Tensor partition_ids, int iterations) { partition_store_->partitions_[pids[i]] = index_partitions[i]; } + partition_store_->build_map(); + if (debug_) { std::cout << "[PartitionManager] refine_partitions: Completed refinement." << std::endl; } @@ -505,6 +507,10 @@ void PartitionManager::add_partitions(shared_ptr partitions) { for (int64_t i = 0; i < nlist; i++) { int64_t list_no = p_ids_accessor[i]; partition_store_->add_list(list_no); + if (num_workers_ > 0) { + set_partition_core_id(list_no, list_no % num_workers_); + } + partition_store_->add_entries( list_no, partitions->vectors[i].size(0), @@ -562,7 +568,9 @@ void PartitionManager::distribute_partitions(int num_workers) { << num_workers << " workers." << std::endl; } - if (parent_ == nullptr) { + num_workers_ = num_workers; + + if (parent_ == nullptr && partition_store_->nlist == 1) { auto codes = (float *) partition_store_->get_codes(0); auto ids = (int64_t *) partition_store_->get_ids(0); int64_t ntotal = partition_store_->list_size(0); @@ -599,13 +607,14 @@ void PartitionManager::distribute_partitions(int num_workers) { } Tensor partition_ids = get_partition_ids(); - for (int i = 0; i < partition_store_->nlist; i++) { - set_partition_core_id(partition_ids[i].item(), i % num_workers); + auto partition_ids_accessor = partition_ids.accessor(); + for (int i = 0; i < partition_ids.size(0); i++) { + set_partition_core_id(partition_ids_accessor[i], i % num_workers); } } void PartitionManager::set_partition_core_id(int64_t partition_id, int core_id) { - partition_store_->partitions_[partition_id]->core_id_ = core_id; + partition_store_->partitions_[partition_id]->set_core_id(core_id); } int PartitionManager::get_partition_core_id(int64_t partition_id) { diff --git a/src/cpp/src/quake_index.cpp b/src/cpp/src/quake_index.cpp index 0aadd869..a65db04f 100644 --- a/src/cpp/src/quake_index.cpp +++ b/src/cpp/src/quake_index.cpp @@ -176,6 +176,10 @@ void QuakeIndex::initialize_maintenance_policy(shared_ptrmaintenance_policy_ = maintenance_policy_; } + + if (parent_ != nullptr) { + parent_->initialize_maintenance_policy(maintenance_policy_params_); + } } shared_ptr QuakeIndex::maintenance() { @@ -185,7 +189,7 @@ shared_ptr QuakeIndex::maintenance() { auto maintenance_info = maintenance_policy_->perform_maintenance(); - if (parent_->maintenance_policy_) { + if (parent_ && parent_->maintenance_policy_) { parent_->maintenance_policy_->perform_maintenance(); } diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 588644ca..6ac1ede6 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -135,7 +135,6 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { const float *partition_codes = (float *) partition_manager_->partition_store_->get_codes(job.partition_id); const int64_t *partition_ids = (int64_t *) partition_manager_->partition_store_->get_ids(job.partition_id); int64_t partition_size = partition_manager_->partition_store_->list_size(job.partition_id); - // Branch for non-batched jobs. if (!job.is_batched) { @@ -260,7 +259,7 @@ shared_ptr QueryCoordinator::worker_scan( int64_t dimension = x.size(1); int k = search_params->k; int64_t nlist = partition_manager_->nlist(); - bool use_aps = (search_params->recall_target > 0.0 && !search_params->batched_scan); + bool use_aps = (search_params->recall_target > 0.0 && !search_params->batched_scan && parent_ != nullptr); auto timing_info = make_shared(); timing_info->n_queries = num_queries; timing_info->n_clusters = nlist; @@ -274,6 +273,8 @@ shared_ptr QueryCoordinator::worker_scan( partition_ids = partition_ids.unsqueeze(0).expand({num_queries, partition_ids.size(0)}); } + auto partition_ids_accessor = partition_ids.accessor(); + job_flags_.clear(); job_flags_.resize(num_queries); for (int64_t q = 0; q < num_queries; q++) { @@ -303,8 +304,12 @@ shared_ptr QueryCoordinator::worker_scan( global_topk_buffer_pool_[q]->set_processing_query(true); } } - for (int64_t q = 0; q < num_queries; q++) { - global_topk_buffer_pool_[q]->set_jobs_left(partition_ids.size(1)); + for (int64_t q = 0; q < num_queries; ++q) { + int valid = 0; + for (int64_t p = 0; p < partition_ids.size(1); ++p) + if (partition_ids_accessor[q][p] != -1) ++valid; + + global_topk_buffer_pool_[q]->set_jobs_left(valid); } } auto end_time = high_resolution_clock::now(); @@ -363,7 +368,7 @@ shared_ptr QueryCoordinator::worker_scan( auto last_flush_time = high_resolution_clock::now(); vector> boundary_distances(num_queries); - if (use_aps) { + if (use_aps && parent_) { for (int64_t q = 0; q < num_queries; q++) { vector partition_ids_to_scan_vec = vector(partition_ids[q].data_ptr(), partition_ids[q].data_ptr() + partition_ids[q].size(0)); @@ -379,7 +384,6 @@ shared_ptr QueryCoordinator::worker_scan( vector query_radius(num_queries, 0.0f); vector> probs(num_queries); - while (true) { // check if all jobs have been processed bool all_done = true; @@ -455,7 +459,17 @@ shared_ptr QueryCoordinator::worker_scan( : std::numeric_limits::infinity(); } } - timing_info->partitions_scanned = global_topk_buffer_pool_[q]->get_num_partitions_scanned(); + timing_info->partitions_scanned += global_topk_buffer_pool_[q]->get_num_partitions_scanned(); + + if (search_params->track_hits && maintenance_policy_ != nullptr) { + vector partition_ids_vec; + for (int64_t p = 0; p < partition_ids.size(1); p++) { + if (job_flags_[q][p]) { + partition_ids_vec.push_back(partition_ids_accessor[q][p]); + } + } + maintenance_policy_->record_query_hits(partition_ids_vec); + } } } end_time = high_resolution_clock::now(); @@ -539,9 +553,14 @@ shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partitio if (use_aps) { vector partition_ids_to_scan_vec = std::vector(partition_ids[q].data_ptr(), partition_ids[q].data_ptr() + partition_ids[q].size(0)); + vector cluster_centroids = parent_->partition_manager_->get_vectors(partition_ids_to_scan_vec); t3 = high_resolution_clock::now(); + // trim nullptrs + cluster_centroids.erase(std::remove(cluster_centroids.begin(), cluster_centroids.end(), nullptr), + cluster_centroids.end()); + boundary_distances = compute_boundary_distances(x[q], cluster_centroids, @@ -609,14 +628,17 @@ shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partitio } } } + + + if (search_params->track_hits && maintenance_policy_) { + maintenance_policy_->record_query_hits(std::vector(scanned_ids.begin(), scanned_ids.end())); + } + // Retrieve the top-k results for query q. all_topk_dists[q] = topk_buf->get_topk(); all_topk_ids[q] = topk_buf->get_topk_indices(); auto t5 = high_resolution_clock::now(); - // mark the partitions as scanned - maintenance_policy_->record_query_hits(scanned_ids); - // std::cout << "Query " << q << " times: " << duration_cast(t2 - t1).count() << " " // << duration_cast(t3 - t2).count() << " " // << duration_cast(t4 - t3).count() << " " @@ -667,13 +689,12 @@ shared_ptr QueryCoordinator::search(Tensor x, shared_ptrnlist(), torch::kInt64); } else { - - auto parent_search_params = make_shared(); if (search_params->parent_params == nullptr) { parent_search_params->recall_target = .99; parent_search_params->use_precomputed = search_params->use_precomputed; parent_search_params->recompute_threshold = search_params->recompute_threshold; + parent_search_params->initial_search_fraction = .5; parent_search_params->batched_scan = false; } else { parent_search_params = search_params->parent_params; diff --git a/src/python/index_wrappers/quake.py b/src/python/index_wrappers/quake.py index b5b4aa5b..ec121fdc 100644 --- a/src/python/index_wrappers/quake.py +++ b/src/python/index_wrappers/quake.py @@ -93,7 +93,7 @@ def build( if parent is not None: build_params.parent_params = quake.IndexBuildParams() - build_params.parent_params.nlist = parent.get("nlist", 1) + build_params.parent_params.nlist = parent.get("nc", 1) self.index = QuakeIndex() @@ -167,6 +167,7 @@ def search( search_params.parent_params = quake.SearchParams() search_params.parent_params.nprobe = parent.get("nprobe", 1) search_params.parent_params.recall_target = parent.get("recall_target", -1) + search_params.parent_params.initial_search_fraction = parent.get("initial_search_fraction", 0.05) return self.index.search(query, search_params) diff --git a/src/python/workload_generator.py b/src/python/workload_generator.py index 302da3c3..b98d892a 100644 --- a/src/python/workload_generator.py +++ b/src/python/workload_generator.py @@ -420,8 +420,8 @@ def initialize_index(self, name, index, build_params, m_params): index.save(index_path) print(f"Index {name} built and saved to {index_path}") else: - if build_params.get("num_workers"): - index.load(index_path, num_workers=build_params["num_workers"]) + if build_params.get("n_workers"): + index.load(index_path, n_workers=build_params["n_workers"]) else: index.load(index_path) print(f"Index {name} loaded from {index_path}") diff --git a/test/cpp/benchmark.cpp b/test/cpp/benchmark.cpp index dc6b454f..3c2daafd 100644 --- a/test/cpp/benchmark.cpp +++ b/test/cpp/benchmark.cpp @@ -496,33 +496,37 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { // Repeatedly search, add, remove, and perform maintenance to see if the index remains consistent. int64_t dimension = 128; - int64_t num_vectors = 100000; - int64_t num_queries = 100; - int64_t batch_size = 10000; + int64_t num_vectors = 10000; + int64_t num_queries = 10; + int64_t batch_size = 1000; int n_ops = 100; QuakeIndex index; auto build_params = std::make_shared(); - build_params->nlist = 2500; + build_params->nlist = 1000; build_params->metric = "l2"; build_params->niter = 5; + build_params->num_workers = 2; auto maintenance_params = std::make_shared(); maintenance_params->refinement_radius = 10; - maintenance_params->refinement_iterations = 1; + maintenance_params->refinement_iterations = 0; + maintenance_params->window_size = 100; Tensor data_vectors = torch::randn({num_vectors, dimension}, torch::kFloat32); Tensor data_ids = torch::arange(num_vectors, torch::kInt64); - index.build(data_vectors, data_ids, build_params); - index.initialize_maintenance_policy(maintenance_params); // add level auto parent_index_build_params = std::make_shared(); - parent_index_build_params->nlist = 250; + parent_index_build_params->nlist = 50; parent_index_build_params->metric = "l2"; parent_index_build_params->niter = 5; - index.add_level(parent_index_build_params); + parent_index_build_params->num_workers = 1; + build_params->parent_params = parent_index_build_params; + index.build(data_vectors, data_ids, build_params); + // + index.initialize_maintenance_policy(maintenance_params); // timers int64_t search_time = 0; @@ -534,6 +538,7 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { auto end = std::chrono::high_resolution_clock::now(); for (int i = 0; i < n_ops; i++) { + std::cout << "[SearchAddRemoveMaintenanceTest] Iteration " << i << "\n"; // Search auto query_vectors = torch::randn({num_queries, dimension}, torch::kFloat32); auto search_params = std::make_shared(); @@ -542,6 +547,11 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { search_params->batched_scan = false; search_params->num_threads = 1; + auto parent_search_params = std::make_shared(); + parent_search_params->nprobe = 50; + parent_search_params->batched_scan = false; + search_params->parent_params = parent_search_params; + start = std::chrono::high_resolution_clock::now(); auto search_result = index.search(query_vectors, search_params); end = std::chrono::high_resolution_clock::now(); @@ -567,10 +577,10 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { // remove_time += std::chrono::duration_cast(end - start).count(); // ASSERT_EQ(remove_info->n_vectors, batch_size / 2); - start = std::chrono::high_resolution_clock::now(); - index.maintenance(); - end = std::chrono::high_resolution_clock::now(); - maintenance_time += std::chrono::duration_cast(end - start).count(); + // start = std::chrono::high_resolution_clock::now(); + // index.maintenance(); + // end = std::chrono::high_resolution_clock::now(); + // maintenance_time += std::chrono::duration_cast(end - start).count(); } // print out mean times per operation @@ -587,64 +597,64 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { SUCCEED(); } -TEST(FaissIndexStressTest, SearchAddRemoveMaintenanceTest) { - // Repeatedly search, add, remove, and perform maintenance to see if the index remains consistent. - - int64_t dimension = 128; - int64_t num_vectors = 100000; - int64_t num_queries = 1; - int64_t batch_size = 10000; - int n_ops = 100; - - Tensor data_vectors = torch::randn({num_vectors, dimension}, torch::kFloat32); - Tensor data_ids = torch::arange(num_vectors, torch::kInt64); - - auto quantizer = new faiss::IndexFlatL2(dimension); - auto index = new faiss::IndexIVFFlat(quantizer, dimension, 1000, faiss::METRIC_L2); - index->train(num_vectors, data_vectors.data_ptr()); - index->add(num_vectors, data_vectors.data_ptr()); - - // timers - int64_t search_time = 0; - int64_t add_time = 0; - int64_t remove_time = 0; - int64_t maintenance_time = 0; - - auto start = std::chrono::high_resolution_clock::now(); - auto end = std::chrono::high_resolution_clock::now(); - - for (int i = 0; i < n_ops; i++) { - // Search - auto query_vectors = generate_data(num_queries, dimension); - std::vector distances(num_queries * K); - std::vector labels(num_queries * K); - - start = std::chrono::high_resolution_clock::now(); - index->nprobe = 12; - index->search(num_queries, query_vectors.data_ptr(), 12, distances.data(), labels.data()); - end = std::chrono::high_resolution_clock::now(); - search_time += std::chrono::duration_cast(end - start).count(); - - // Add - auto add_vectors = generate_data(batch_size, dimension); - auto add_ids = generate_ids(batch_size, num_vectors); - start = std::chrono::high_resolution_clock::now(); - index->add(batch_size, add_vectors.data_ptr()); - end = std::chrono::high_resolution_clock::now(); - add_time += std::chrono::duration_cast(end - start).count(); - num_vectors += batch_size; - } - // print out mean times per operation - float mean_search_time = static_cast(search_time) / n_ops; - float mean_add_time = static_cast(add_time) / n_ops; - float mean_remove_time = static_cast(remove_time) / n_ops; - float mean_maintenance_time = static_cast(maintenance_time) / n_ops; - - std::cout << "[SearchAddRemoveMaintenanceTest] Mean search time: " << mean_search_time << " μs\n"; - std::cout << "[SearchAddRemoveMaintenanceTest] Mean add time: " << mean_add_time << " μs\n"; - std::cout << "[SearchAddRemoveMaintenanceTest] Mean remove time: " << mean_remove_time << " μs\n"; - std::cout << "[SearchAddRemoveMaintenanceTest] Mean maintenance time: " << mean_maintenance_time << " μs\n"; - - SUCCEED(); -} +// TEST(FaissIndexStressTest, SearchAddRemoveMaintenanceTest) { +// // Repeatedly search, add, remove, and perform maintenance to see if the index remains consistent. +// +// int64_t dimension = 128; +// int64_t num_vectors = 100000; +// int64_t num_queries = 1; +// int64_t batch_size = 10000; +// int n_ops = 100; +// +// Tensor data_vectors = torch::randn({num_vectors, dimension}, torch::kFloat32); +// Tensor data_ids = torch::arange(num_vectors, torch::kInt64); +// +// auto quantizer = new faiss::IndexFlatL2(dimension); +// auto index = new faiss::IndexIVFFlat(quantizer, dimension, 1000, faiss::METRIC_L2); +// index->train(num_vectors, data_vectors.data_ptr()); +// index->add(num_vectors, data_vectors.data_ptr()); +// +// // timers +// int64_t search_time = 0; +// int64_t add_time = 0; +// int64_t remove_time = 0; +// int64_t maintenance_time = 0; +// +// auto start = std::chrono::high_resolution_clock::now(); +// auto end = std::chrono::high_resolution_clock::now(); +// +// for (int i = 0; i < n_ops; i++) { +// // Search +// auto query_vectors = generate_data(num_queries, dimension); +// std::vector distances(num_queries * K); +// std::vector labels(num_queries * K); +// +// start = std::chrono::high_resolution_clock::now(); +// index->nprobe = 12; +// index->search(num_queries, query_vectors.data_ptr(), 12, distances.data(), labels.data()); +// end = std::chrono::high_resolution_clock::now(); +// search_time += std::chrono::duration_cast(end - start).count(); +// +// // Add +// auto add_vectors = generate_data(batch_size, dimension); +// auto add_ids = generate_ids(batch_size, num_vectors); +// start = std::chrono::high_resolution_clock::now(); +// index->add(batch_size, add_vectors.data_ptr()); +// end = std::chrono::high_resolution_clock::now(); +// add_time += std::chrono::duration_cast(end - start).count(); +// num_vectors += batch_size; +// } +// // print out mean times per operation +// float mean_search_time = static_cast(search_time) / n_ops; +// float mean_add_time = static_cast(add_time) / n_ops; +// float mean_remove_time = static_cast(remove_time) / n_ops; +// float mean_maintenance_time = static_cast(maintenance_time) / n_ops; +// +// std::cout << "[SearchAddRemoveMaintenanceTest] Mean search time: " << mean_search_time << " μs\n"; +// std::cout << "[SearchAddRemoveMaintenanceTest] Mean add time: " << mean_add_time << " μs\n"; +// std::cout << "[SearchAddRemoveMaintenanceTest] Mean remove time: " << mean_remove_time << " μs\n"; +// std::cout << "[SearchAddRemoveMaintenanceTest] Mean maintenance time: " << mean_maintenance_time << " μs\n"; +// +// SUCCEED(); +// } diff --git a/test/cpp/quake_multi_level.cpp b/test/cpp/quake_multi_level.cpp new file mode 100644 index 00000000..9b5c787a --- /dev/null +++ b/test/cpp/quake_multi_level.cpp @@ -0,0 +1,103 @@ + +#include +#include "quake_index.h" + +using torch::Tensor; + +//--------------------------------------------------------------- +// Helpers +//--------------------------------------------------------------- +static Tensor rand_vectors(int64_t n, int64_t d, uint64_t seed) +{ + torch::manual_seed(seed); + return torch::randn({n, d}, torch::kFloat32); +} +static Tensor seq_ids(int64_t n, int64_t start = 0) +{ + return torch::arange(start, start + n, torch::kInt64); +} + +//--------------------------------------------------------------- +// Constants for all tests +//--------------------------------------------------------------- +constexpr int64_t DIM = 32; +constexpr int64_t NVEC = 20'000; +constexpr int64_t LEAF = 64; +constexpr int64_t MID = 16; +constexpr int64_t ROOT = 4; + +//--------------------------------------------------------------- +// 1. Build a 3‑level index, search, maintain, search again. +//--------------------------------------------------------------- +TEST(QuakeMultiLevel, EndToEndMaintenance) +{ + Tensor data = rand_vectors(NVEC, DIM, 0); + Tensor ids = seq_ids(NVEC); + + QuakeIndex ix; + auto build = std::make_shared(); + build->nlist = LEAF; + build->metric = "l2"; + ix.build(data, ids, build); + + // add 2nd level + auto mid = std::make_shared(); + mid->nlist = MID; + mid->metric = "l2"; + ix.add_level(mid); + + // add 3rd (root) level + auto root = std::make_shared(); + root->nlist = ROOT; + root->metric = "l2"; + ix.add_level(root); + + // quick sanity on hierarchy depth + ASSERT_NE(ix.parent_, nullptr); + ASSERT_NE(ix.parent_->parent_, nullptr); + + auto sp = std::make_shared(); + sp->k = 10; + + // baseline search + auto baseline = ix.search(rand_vectors(50, DIM, 1), sp); + ASSERT_EQ(baseline->ids.size(1), sp->k); + + // hammer with 2000 queries to populate hit tracker then run maintenance + ix.search(rand_vectors(2000, DIM, 2), sp); + auto mi = ix.maintenance(); + EXPECT_GE(mi->total_time_us, 0); + EXPECT_EQ(ix.ntotal(), NVEC); + + // final search should still work + auto after = ix.search(rand_vectors(50, DIM, 3), sp); + EXPECT_EQ(after->ids.size(1), sp->k); +} + +//--------------------------------------------------------------- +// 2. Calling add_level() on a 1‑level index must throw. +//--------------------------------------------------------------- +TEST(QuakeMultiLevel, AddLevelWithoutParentThrows) +{ + Tensor data = rand_vectors(1000, DIM, 4); + Tensor ids = seq_ids(1000); + + QuakeIndex flat; + flat.build(data, ids, std::make_shared()); // nlist=0 ⇒ flat + + EXPECT_THROW(flat.add_level(std::make_shared()), std::runtime_error); +} + +//--------------------------------------------------------------- +// 3. Root maintenance should be a safe no‑op (flat index). +//--------------------------------------------------------------- +TEST(QuakeMultiLevel, RootMaintenanceSafe) +{ + Tensor data = rand_vectors(800, DIM, 5); + Tensor ids = seq_ids(800); + + QuakeIndex flat; + flat.build(data, ids, std::make_shared()); // nlist=0 + + EXPECT_NO_THROW(flat.maintenance()); +} \ No newline at end of file From c13f6fe33ef79f737d5d48d3bc40b5a52193a4fc Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 6 May 2025 11:38:24 -0500 Subject: [PATCH 021/323] add sift1m config --- src/cpp/src/partition_manager.cpp | 5 ++ src/cpp/src/query_coordinator.cpp | 9 ++- src/python/index_wrappers/quake.py | 6 +- src/python/workload_generator.py | 2 +- test/cpp/benchmark.cpp | 29 +++++--- .../kick_the_tires/configs/sift1m.yaml | 73 +++++++++++++++++++ 6 files changed, 108 insertions(+), 16 deletions(-) create mode 100644 test/experiments/osdi2025/kick_the_tires/configs/sift1m.yaml diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index 780b1342..0ca2f195 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -246,6 +246,11 @@ shared_ptr PartitionManager::add( for (int64_t i = 0; i < n; i++) { int64_t pid = partition_ids_for_each[i]; + + if (pid < 0 || pid >= curr_partition_id_) { + throw runtime_error("[PartitionManager] add: Invalid partition ID."); + } + if (debug_) { std::cout << "[PartitionManager] add: Inserting vector " << i << " with id " << id_accessor[i] << " into partition " << pid << std::endl; diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 6ac1ede6..364e75ab 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -119,6 +119,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { // Shutdown signal: -1 indicates the worker should exit. if (job.partition_id == -1) { + std::cout << "[QueryCoordinator::partition_scan_worker_fn] Worker " << core_index << " exiting." << std::endl; break; } @@ -337,6 +338,9 @@ shared_ptr QueryCoordinator::worker_scan( job.num_queries = kv.second.size(); job.query_ids = kv.second; int core_id = partition_manager_->get_partition_core_id(kv.first); + if (core_id < 0) { + throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); + } core_resources_[core_id].job_queue.enqueue(job); } } else { @@ -359,6 +363,9 @@ shared_ptr QueryCoordinator::worker_scan( job.rank = p; int core_id = partition_manager_->get_partition_core_id(pid); + if (core_id < 0) { + throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); + } core_resources_[core_id].job_queue.enqueue(job); } }, search_params->num_threads); @@ -687,7 +694,7 @@ shared_ptr QueryCoordinator::search(Tensor x, shared_ptrnlist(), torch::kInt64); + partition_ids_to_scan = partition_manager_->get_partition_ids(); } else { auto parent_search_params = make_shared(); if (search_params->parent_params == nullptr) { diff --git a/src/python/index_wrappers/quake.py b/src/python/index_wrappers/quake.py index ec121fdc..a75f2f86 100644 --- a/src/python/index_wrappers/quake.py +++ b/src/python/index_wrappers/quake.py @@ -189,7 +189,7 @@ def save(self, filename: str): def load( self, filename: str, - n_workers: int = 0, + num_workers: int = 0, use_numa: bool = False, verbose: bool = False, verify_numa: bool = False, @@ -203,11 +203,11 @@ def load( :param filename: The name of the file to load the index from. """ print( - f"Loading index from {filename}, with {n_workers} workers, use_numa={use_numa}, verbose={verbose}, " + f"Loading index from {filename}, with {num_workers} workers, use_numa={use_numa}, verbose={verbose}, " f"verify_numa={verify_numa}, same_core={same_core}, use_centroid_workers={use_centroid_workers}" ) self.index = QuakeIndex() - self.index.load(str(filename), n_workers) + self.index.load(str(filename), num_workers) def centroids(self) -> torch.Tensor: """ diff --git a/src/python/workload_generator.py b/src/python/workload_generator.py index b98d892a..faa7c1d2 100644 --- a/src/python/workload_generator.py +++ b/src/python/workload_generator.py @@ -421,7 +421,7 @@ def initialize_index(self, name, index, build_params, m_params): print(f"Index {name} built and saved to {index_path}") else: if build_params.get("n_workers"): - index.load(index_path, n_workers=build_params["n_workers"]) + index.load(index_path, num_workers=build_params["num_workers"]) else: index.load(index_path) print(f"Index {name} loaded from {index_path}") diff --git a/test/cpp/benchmark.cpp b/test/cpp/benchmark.cpp index 3c2daafd..93574b9a 100644 --- a/test/cpp/benchmark.cpp +++ b/test/cpp/benchmark.cpp @@ -497,21 +497,21 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { int64_t dimension = 128; int64_t num_vectors = 10000; - int64_t num_queries = 10; - int64_t batch_size = 1000; + int64_t num_queries = 1; + int64_t batch_size = 10000; int n_ops = 100; QuakeIndex index; auto build_params = std::make_shared(); - build_params->nlist = 1000; + build_params->nlist = 100; build_params->metric = "l2"; build_params->niter = 5; - build_params->num_workers = 2; + build_params->num_workers = 0; auto maintenance_params = std::make_shared(); maintenance_params->refinement_radius = 10; maintenance_params->refinement_iterations = 0; - maintenance_params->window_size = 100; + maintenance_params->window_size = 10; Tensor data_vectors = torch::randn({num_vectors, dimension}, torch::kFloat32); Tensor data_ids = torch::arange(num_vectors, torch::kInt64); @@ -519,11 +519,18 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { // add level auto parent_index_build_params = std::make_shared(); - parent_index_build_params->nlist = 50; + parent_index_build_params->nlist = 1; parent_index_build_params->metric = "l2"; parent_index_build_params->niter = 5; - parent_index_build_params->num_workers = 1; + parent_index_build_params->num_workers = 0; build_params->parent_params = parent_index_build_params; + + // auto grandparent_index_build_params = std::make_shared(); + // grandparent_index_build_params->nlist = 1; + // grandparent_index_build_params->metric = "l2"; + // grandparent_index_build_params->num_workers = 0; + // build_params->parent_params->parent_params = grandparent_index_build_params; + index.build(data_vectors, data_ids, build_params); // index.initialize_maintenance_policy(maintenance_params); @@ -577,10 +584,10 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { // remove_time += std::chrono::duration_cast(end - start).count(); // ASSERT_EQ(remove_info->n_vectors, batch_size / 2); - // start = std::chrono::high_resolution_clock::now(); - // index.maintenance(); - // end = std::chrono::high_resolution_clock::now(); - // maintenance_time += std::chrono::duration_cast(end - start).count(); + start = std::chrono::high_resolution_clock::now(); + index.maintenance(); + end = std::chrono::high_resolution_clock::now(); + maintenance_time += std::chrono::duration_cast(end - start).count(); } // print out mean times per operation diff --git a/test/experiments/osdi2025/kick_the_tires/configs/sift1m.yaml b/test/experiments/osdi2025/kick_the_tires/configs/sift1m.yaml new file mode 100644 index 00000000..bac21318 --- /dev/null +++ b/test/experiments/osdi2025/kick_the_tires/configs/sift1m.yaml @@ -0,0 +1,73 @@ +# configs/experiment.yaml +mode: run # options: build, run, plot +dataset: + name: sift1m + metric: l2 + path: data +workload_generator: + recall_target: 0.9 + insert_ratio: 0.5 + delete_ratio: 0.0 + query_ratio: 0.5 + number_of_operations: 1000 + initial_size: 100000 + cluster_size: 1000 + update_batch_size: 10000 + query_batch_size: 100 + cluster_sample_distribution: skewed + query_cluster_sample_distribution: uniform + seed: 9299 +indexes: + - name: Quake + index: Quake + build_params: + nc: 1000 + num_workers: 1 + parent: + num_workers: 8 + search_params: + k: 10 +# nprobe: 10 + recall_target: .9 + parent: +# nprobe: 25 + recall_target: .99 + initial_search_fraction: 0.25 + + - name: Quake2 + index: Quake + build_params: + nc: 1000 + num_workers: 1 + parent: + num_workers: 0 + search_params: + k: 10 + recall_target: .9 + - name: IVF + index: IVF + build_params: + nc: 1000 + search_params: + nprobe: 15 + k: 10 +plot: + x_axis: operation_number # any column from the results CSV + metrics: [latency_ms, recall] # any subset of stored metrics + styles: # one entry per index name + Quake: + color: "#1f77b4" # default Matplotlib hex’s are fine + linestyle: "-" # see plt.Line2D docs + marker: "o" + Quake2: + color: "#ff7f0e" # default Matplotlib hex’s are fine + linestyle: "-" # see plt.Line2D docs + marker: "o" + IVF: + color: "#d62728" + linestyle: "--" + marker: "s" +overwrite: + workload: false + index: false + results: true \ No newline at end of file From 95bdaeff6e741c50e7083684107fefaabc40d2ba Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 6 May 2025 11:48:04 -0500 Subject: [PATCH 022/323] update config --- test/experiments/osdi2025/README.md | 2 +- .../kick_the_tires/configs/sift1m.yaml | 20 +------------------ 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/test/experiments/osdi2025/README.md b/test/experiments/osdi2025/README.md index 002ed897..1df6e158 100644 --- a/test/experiments/osdi2025/README.md +++ b/test/experiments/osdi2025/README.md @@ -51,7 +51,7 @@ python3 examples/quickstart.py 2. **Run the Benchmark:** ```bash -python3 -m test.experiments.osdi2025.experiment_runner --experiment kick_the_tires --config sift1m +OMP_NUM_THREADS=1 python3 -m test.experiments.osdi2025.experiment_runner --experiment kick_the_tires --config sift1m ``` --- \ No newline at end of file diff --git a/test/experiments/osdi2025/kick_the_tires/configs/sift1m.yaml b/test/experiments/osdi2025/kick_the_tires/configs/sift1m.yaml index bac21318..5a2974e8 100644 --- a/test/experiments/osdi2025/kick_the_tires/configs/sift1m.yaml +++ b/test/experiments/osdi2025/kick_the_tires/configs/sift1m.yaml @@ -22,25 +22,7 @@ indexes: index: Quake build_params: nc: 1000 - num_workers: 1 - parent: - num_workers: 8 - search_params: - k: 10 -# nprobe: 10 - recall_target: .9 - parent: -# nprobe: 25 - recall_target: .99 - initial_search_fraction: 0.25 - - - name: Quake2 - index: Quake - build_params: - nc: 1000 - num_workers: 1 - parent: - num_workers: 0 + num_workers: 0 search_params: k: 10 recall_target: .9 From c5a98a41b9415c5a96215c1082dbea3400000d21 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 6 May 2025 23:19:37 -0500 Subject: [PATCH 023/323] add LAET --- src/python/datasets/ann_datasets.py | 48 +++ test/cpp/scan_benchmark.cpp | 241 ++++++++++++ .../osdi2025/early_termination/laet.py | 316 +++++++++++++++ .../osdi2025/early_termination/run.py | 369 ++++++++++++++++++ .../osdi2025/early_termination/util_laet.py | 77 ++++ .../experiments/osdi2025/experiment_runner.py | 2 + 6 files changed, 1053 insertions(+) create mode 100644 test/cpp/scan_benchmark.cpp create mode 100644 test/experiments/osdi2025/early_termination/laet.py create mode 100644 test/experiments/osdi2025/early_termination/util_laet.py diff --git a/src/python/datasets/ann_datasets.py b/src/python/datasets/ann_datasets.py index 572717a4..607d47ea 100644 --- a/src/python/datasets/ann_datasets.py +++ b/src/python/datasets/ann_datasets.py @@ -5,6 +5,7 @@ import numpy as np import torch +import os from quake.utils import download_url, extract_file, fvecs_to_tensor, ivecs_to_tensor, to_path, knn @@ -116,6 +117,51 @@ def load_ground_truth(self) -> Union[np.ndarray, torch.Tensor]: return torch.from_numpy(np.load(self.download_dir / "ground_truth.npy")) +class MSTuring10m(Dataset): + def __init__(self, download_dir: Union[str, Path] = DEFAULT_DOWNLOAD_DIR): + self.download_dir = to_path(download_dir) + self.data_dir = self.download_dir / "MSTuringANNS10M" + self.downloaded = False + self.metric = "l2" + + def is_downloaded(self) -> bool: + base = self.data_dir / "base1b.fbin.crop_nb_10000000" + query = self.data_dir / "query100K.fbin" + gt = self.data_dir / "msturing-gt-10M" + downloaded = base.exists() and query.exists() and gt.exists() + + if not downloaded: + raise RuntimeError("MSTuring dataset is not available. Please download it manually using big-ann-benchmarks.") + + return downloaded + + def download(self, overwrite: bool = False): + pass + + def load_vectors(self) -> Union[np.ndarray, torch.Tensor]: + fname = self.data_dir / "base1b.fbin.crop_nb_10000000" + n, d = map(int, np.fromfile(fname, dtype="uint32", count=2)) + # return to_torch(np.fromfile(fname, dtype=np.float32, offset=8).reshape((n, d))) + return torch.from_numpy(np.fromfile(fname, dtype=np.float32, offset=8).reshape((n, d))) + + def load_queries(self) -> Union[np.ndarray, torch.Tensor]: + fname = self.data_dir / "query100K.fbin" + n, d = map(int, np.fromfile(fname, dtype="uint32", count=2)) + # return to_torch(np.fromfile(fname, dtype=np.float32, offset=8).reshape((n, d))) + return torch.from_numpy(np.fromfile(fname, dtype=np.float32, offset=8).reshape((n, d))) + + def load_ground_truth(self) -> Union[np.ndarray, torch.Tensor]: + fname = self.data_dir / "msturing-gt-10M" + n, d = map(int, np.fromfile(fname, dtype="uint32", count=2)) + assert os.stat(fname).st_size == 8 + n * d * (4 + 4) + f = open(fname, "rb") + f.seek(4 + 4) + ids = np.fromfile(f, dtype="int32", count=n * d).reshape(n, d) + # D = np.fromfile(f, dtype="float32", count=n * d).reshape(n, d) + + return torch.from_numpy(ids).long() + + def load_dataset( name: str, download_dir: str = DEFAULT_DOWNLOAD_DIR, overwrite_download: bool = False ) -> List[Union[np.ndarray, torch.Tensor]]: @@ -123,6 +169,8 @@ def load_dataset( dataset = Sift1m(download_dir=download_dir) elif name.lower() == "uniform": dataset = UniformDataset(num_vectors=100000, dim=8, download_dir=download_dir) + elif name.lower() == "msturing10m": + dataset = MSTuring10m(download_dir=download_dir) else: raise RuntimeError("Unimplemented dataset") diff --git a/test/cpp/scan_benchmark.cpp b/test/cpp/scan_benchmark.cpp new file mode 100644 index 00000000..a029c0fa --- /dev/null +++ b/test/cpp/scan_benchmark.cpp @@ -0,0 +1,241 @@ +#include +// #include // OpenMP no longer used for the primary parallelization +#include +#include +#include +#include +#include +#include +#include +#include +#include // For std::mutex and std::call_once +#include // For std::thread::hardware_concurrency +#include // For std::async, std::future (used by parallel.h) +#include +#include "faiss/utils/distances.h" +#include "parallel.h" // Include your custom parallel_for header + +// ------------------------------------------------------------------ +// Constants +// ------------------------------------------------------------------ +static constexpr int64_t LIST_SIZE = 1'000'000; +static constexpr int D = 128; +static constexpr int NQ = 100; // Number of queries + +// Forward declaration of the fixture +class ListScanBenchmarkF; + +// ------------------------------------------------------------------ +// Timing helper +// ------------------------------------------------------------------ +struct Timer { + using clk = std::chrono::steady_clock; + clk::time_point t0; + void start() { t0 = clk::now(); } + double stop() { return std::chrono::duration(clk::now()-t0).count(); } +}; + +// ------------------------------------------------------------------ +// Pretty printer +// ------------------------------------------------------------------ +// Takes requested threads (nth_req) and actual threads used by parallel_for (pfor_threads) +static void print_stats(const char* label, int nth_req, double sec) +{ + const double evaluations = static_cast(LIST_SIZE) * NQ; + const double bytes_scanned = evaluations * D * sizeof(float); + const double gb_scanned = bytes_scanned / (1ULL << 30); + const double gb_per_sec = gb_scanned / sec; + + std::cout << std::setw(24) << std::left << label + << " | " << std::setw(2) << nth_req + << " | " << std::fixed << std::setprecision(3) + << sec << " s" + << " | " << std::setprecision(2) + << gb_per_sec << " GB/s" + << std::endl; +} + +// ================================================================== +// Google‑test Test Fixture +// ================================================================== +class ListScanBenchmarkF : public ::testing::Test { +protected: + // Data members are static members of the fixture + static std::vector S_base_vectors_data; + static std::vector S_queries_data; + static std::vector S_seq_order_data; + static std::vector S_rnd_order_data; + + // Flags for std::call_once, also static members + static std::once_flag base_vectors_flag; + static std::once_flag queries_flag; + static std::once_flag seq_order_flag; + static std::once_flag rnd_order_flag; + + static void initialize_base_vectors() { + std::call_once(base_vectors_flag, []{ + S_base_vectors_data.resize(LIST_SIZE * D); + std::mt19937 rng(123); + std::normal_distribution nd(0.f, 1.f); + for (float& v : S_base_vectors_data) v = nd(rng); + }); + } + + static void initialize_queries() { + std::call_once(queries_flag, []{ + S_queries_data.resize(NQ * D); + std::mt19937 rng(321); + std::normal_distribution nd(0.f, 1.f); + for (float& v : S_queries_data) v = nd(rng); + }); + } + + static void initialize_seq_order() { + std::call_once(seq_order_flag, []{ + S_seq_order_data.resize(LIST_SIZE); + std::iota(S_seq_order_data.begin(), S_seq_order_data.end(), 0); + }); + } + + static void initialize_rnd_order() { + std::call_once(rnd_order_flag, []{ + S_rnd_order_data.resize(LIST_SIZE); + std::iota(S_rnd_order_data.begin(), S_rnd_order_data.end(), 0); + std::mt19937 rng(999); + std::shuffle(S_rnd_order_data.begin(), S_rnd_order_data.end(), rng); + }); + } + +public: + // Kernel now uses the custom parallel_for for the inner loop (scanning list_size) + // It returns the sum of minimum distances found for each query (for anti-optimization) + static float static_scan_kernel(const std::vector& order, int n_threads_requested) + { + const float* base_ptr = S_base_vectors_data.data(); + const float* query_ptr = S_queries_data.data(); + + volatile float total_min_sum = 0.f; // Accumulates min distance for each query + + // Determine the actual number of threads parallel_for will aim to use + int threads_for_pfor = n_threads_requested; + if (threads_for_pfor <= 0) { + threads_for_pfor = static_cast(std::thread::hardware_concurrency()); + } + if (threads_for_pfor == 0) { // Safety for hardware_concurrency returning 0 + threads_for_pfor = 1; + } + + float distances[LIST_SIZE]; // Distances for the current query + + // Outer loop over queries (sequential) + for (int qi = 0; qi < NQ; ++qi) { + const float* current_query_vector = query_ptr + qi * D; + + // Inner loop (over base vectors for the current query) is parallelized + // The 'order' vector contains indices into 'S_base_vectors_data' + // 'k' will be an index from 0 to order.size()-1 + parallel_for(static_cast(0), static_cast(order.size()), + [&](int64_t k) { // k is the index in the range [0, order.size()) + int64_t base_vector_original_idx = order[k]; + const float* current_base_vector = base_ptr + base_vector_original_idx * D; + + distances[k] = faiss::fvec_L2sqr(current_query_vector, current_base_vector, static_cast(D)); + }, + threads_for_pfor // Pass the determined number of threads to parallel_for + ); + } + return total_min_sum; // Return sum for anti-optimization + } + + // Wrappers call the kernel + static float static_sequential_scan(int nth = 1) { + return static_scan_kernel(S_seq_order_data, nth); + } + static float static_random_scan(int nth = 1) { + return static_scan_kernel(S_rnd_order_data, nth); + } + +protected: + static void SetUpTestSuite() { + std::cout << "Using custom parallel_for for inner loop parallelization." << std::endl; + unsigned int hw_threads = std::thread::hardware_concurrency(); + std::cout << "std::thread::hardware_concurrency(): " << hw_threads << std::endl; + + std::cout << "Initializing benchmark data (once)..." << std::endl; + auto overall_start_init = std::chrono::steady_clock::now(); + + initialize_base_vectors(); + initialize_queries(); + initialize_seq_order(); + initialize_rnd_order(); + + auto overall_end_init = std::chrono::steady_clock::now(); + std::chrono::duration init_duration = overall_end_init - overall_start_init; + std::cout << "VECTOR SCAN BENCHMARK" << std::endl; + std::cout << "--------------------------------------------------------------------------" << std::endl; + std::cout << "Benchmark data initialized in " << std::fixed << std::setprecision(3) + << init_duration.count() << " s." << std::endl; + std::cout << "Benchmark data size: " << LIST_SIZE << "vectors, " + << NQ << " queries, " << D << " dimensions." << std::endl; + std::cout << "Throughput averaged over all queries." << std::endl; + std::cout << "--------------------------------------------------------------------------" << std::endl; + std::cout << std::setw(24) << std::left << "Test Case" + << " | " << "N_Threads" // Requested threads + << " | " << "Time (s)" + << " | " << "Throughput" << std::endl; + std::cout << "--------------------------------------------------------------------------" << std::endl; + } + + static void TearDownTestSuite() { + std::cout << "--------------------------------------------------------------------------" << std::endl; + std::cout << "Benchmark suite finished." << std::endl; + } +}; + +// Static member definitions +std::vector ListScanBenchmarkF::S_base_vectors_data; +std::vector ListScanBenchmarkF::S_queries_data; +std::vector ListScanBenchmarkF::S_seq_order_data; +std::vector ListScanBenchmarkF::S_rnd_order_data; + +std::once_flag ListScanBenchmarkF::base_vectors_flag; +std::once_flag ListScanBenchmarkF::queries_flag; +std::once_flag ListScanBenchmarkF::seq_order_flag; +std::once_flag ListScanBenchmarkF::rnd_order_flag; + + + +TEST_F(ListScanBenchmarkF, ParallelSequentialScan) +{ + for (int nth : {1, 2, 4, 8, 12}) { // Test with different numbers of threads + Timer t; + t.start(); + volatile float dummy_sum = static_sequential_scan(nth); + double elapsed_seconds = t.stop(); + (void)dummy_sum; + + int actual_pfor_threads = (nth <= 0) ? static_cast(std::thread::hardware_concurrency()) : nth; + if (actual_pfor_threads == 0) actual_pfor_threads = 1; + if (nth == 1) actual_pfor_threads = 1; // parallel_for handles num_threads == 1 specifically + + + print_stats("Parallel-Sequential", nth, elapsed_seconds); + } +} + +TEST_F(ListScanBenchmarkF, ParallelRandomScan) +{ + for (int nth : {1, 2, 4, 8, 12}) { // Test with different numbers of threads + Timer t; + t.start(); + volatile float dummy_sum = static_random_scan(nth); + double elapsed_seconds = t.stop(); + (void)dummy_sum; + + int actual_pfor_threads = (nth <= 0) ? static_cast(std::thread::hardware_concurrency()) : nth; + if (actual_pfor_threads == 0) actual_pfor_threads = 1; + if (nth == 1) actual_pfor_threads = 1; // parallel_for handles num_threads == 1 specifically + + print_stats("Parallel-Random", nth, elapsed_seconds); + } +} diff --git a/test/experiments/osdi2025/early_termination/laet.py b/test/experiments/osdi2025/early_termination/laet.py new file mode 100644 index 00000000..b9687270 --- /dev/null +++ b/test/experiments/osdi2025/early_termination/laet.py @@ -0,0 +1,316 @@ +# File: laet.py +import faiss +import lightgbm as lgb +import numpy as np +import pandas as pd +import os +import time +import csv +import sys +import math +import re +from pathlib import Path +from sklearn.model_selection import train_test_split +import torch +from sklearn.metrics import mean_squared_error, mean_absolute_error + +# --- Embedded I/O Utilities (Simplified) --- +def _mmap_fvecs(fname): + x = np.memmap(fname, dtype='int32', mode='r'); d = x[0]; return x.view('float32').reshape(-1, d + 1)[:, 1:] +def _mmap_bvecs(fname): + x = np.memmap(fname, dtype='uint8', mode='r'); d = x[:4].view('int32')[0]; return x.reshape(-1, d + 4)[:, 4:] +def _read_gt_file(fname, format_type, k_load=1): + gt_list = [] + if format_type == "ivecs": + if not os.path.exists(fname) or os.path.getsize(fname) == 0: + return [] + a = np.fromfile(fname, dtype='int32') + if a.size == 0: return [] + d_gt = a[0] + if a.size % (d_gt + 1) != 0: + return [] + data = a.reshape(-1, d_gt + 1) + for i in range(data.shape[0]): + count = data[i,0]; num_to_take = min(count, k_load if k_load is not None else count) + gt_list.append(list(data[i, 1:1 + num_to_take])) + elif format_type == "tsv": + if not os.path.exists(fname): + return [] + with open(fname, 'r', newline='') as f: + for row in csv.reader(f, delimiter='\t'): + try: + ids = [int(x) for x in row if x.strip()] + gt_list.append(ids[:k_load] if k_load is not None else ids) + except ValueError: + pass + return gt_list +def _write_tsv(data, filename): + if os.path.exists(filename): os.remove(filename) + with open(filename, 'w', newline='') as f: csv.writer(f, delimiter='\t').writerows(data) +# --- End I/O --- + +class LAETPipeline: + def __init__(self, vector_dim, laet_artifacts_config): + self.vector_dim = vector_dim + self.config = laet_artifacts_config + self.gbdt_model = None + self.log_target_prediction = False + + base_dir = Path(self.config["base_dir"]) + self.training_data_output_dir = base_dir / self.config.get("training_data_subdir", "laet_training_data") + self.model_output_dir = base_dir / self.config.get("model_subdir", "laet_models") + + self.training_data_output_dir.mkdir(parents=True, exist_ok=True) + self.model_output_dir.mkdir(parents=True, exist_ok=True) + + self.model_name_prefix = f"{self.config['dataset_name_for_files']}_{self.config['index_key_for_files'].replace(',', '_')}" + _log_suffix_for_naming = "_Log" if self.config.get("model_was_trained_on_log_target", False) else "" + self.gbdt_model_filename = f"{self.model_name_prefix}_gbdt_model{_log_suffix_for_naming}.txt" + self.full_gbdt_model_path = self.model_output_dir / self.gbdt_model_filename + + def _find_min_param_faiss(self, faiss_idx, q_vec, gt_set, k_chk, is_hnsw, max_p, init_p=1, step=1): + if not gt_set: return max_p + curr_p = init_p + while curr_p <= max_p: + if is_hnsw: faiss_idx.hnsw.efSearch = curr_p + else: faiss_idx.nprobe = curr_p + try: + _, I = faiss_idx.search(q_vec, k_chk) + if I.size > 0 and any(idx in gt_set for idx in I[0] if idx >= 0): return curr_p + except Exception: pass + curr_p += step + if curr_p > max_p and curr_p - step <= max_p : + if curr_p - step == max_p: continue + break + return max_p + + def _generate_training_data_tsv_internal(self, tsv_path, data_paths_cfg, gen_params_cfg, faiss_params_cfg): + print(f"LAET: Generating training data to {tsv_path}...") + xb = _mmap_fvecs(data_paths_cfg["base_vectors"]) if data_paths_cfg["base_vectors"].endswith('.fvecs') else _mmap_bvecs(data_paths_cfg["base_vectors"]) + xq_all = _mmap_fvecs(data_paths_cfg["train_query_vectors"]) if data_paths_cfg["train_query_vectors"].endswith('.fvecs') else _mmap_bvecs(data_paths_cfg["train_query_vectors"]) + + num_q = gen_params_cfg.get("num_train_queries_to_process", -1) + xq = xq_all[:num_q] if num_q > 0 else xq_all + xq_f32 = xq.astype(np.float32) + + gt_all = _read_gt_file(data_paths_cfg["gt_train"], data_paths_cfg["gt_format"], gen_params_cfg.get("k_gt_load_for_target", 1)) + gt = gt_all[:num_q] if num_q > 0 else gt_all + if len(xq) != len(gt): raise ValueError(f"Query ({len(xq)})/GT ({len(gt)}) length mismatch in training data gen.") + + faiss_idx_key = faiss_params_cfg["faiss_index_key_for_gen"] + is_hnsw = "hnsw" in faiss_idx_key.lower() + faiss_idx = faiss.index_factory(self.vector_dim, faiss_idx_key) + if not faiss_idx.is_trained: + xt_idx_path = data_paths_cfg.get("training_vectors_for_faiss_index") + if not xt_idx_path: raise ValueError("FAISS index needs training, but no training vectors path provided.") + xt_idx = _mmap_fvecs(xt_idx_path) if xt_idx_path.endswith('.fvecs') else _mmap_bvecs(xt_idx_path) + faiss_idx.train(xt_idx.astype(np.float32)) + faiss_idx.add(xb.astype(np.float32)) + + max_p = gen_params_cfg.get("max_efsearch_scan", 512) if is_hnsw else gen_params_cfg.get("max_nprobe_scan", 256) + if not is_hnsw and hasattr(faiss_idx, 'nlist'): max_p = min(max_p, faiss_idx.nlist) + + k_search_target = gen_params_cfg.get("k_search_for_target", 10) + param_scan_step = gen_params_cfg.get("param_scan_step", 1) + out_data = [] + start_gen_time = time.time() + print(f"LAET Training Data Gen: Max param to scan for optimal_p: {max_p}") + for i in range(len(xq)): + opt_p = self._find_min_param_faiss(faiss_idx, xq_f32[i:i+1], set(gt[i]), k_search_target, is_hnsw, max_p, step=param_scan_step) + out_data.append([opt_p, i] + xq_f32[i].tolist()) + if (i + 1) % 500 == 0 or (i+1) == len(xq): + elapsed_gen = time.time() - start_gen_time + _write_tsv(out_data, str(tsv_path)) + # Log distribution of optimal_p found + if out_data: + optimal_ps_found = np.array([row[0] for row in out_data]) + print(f"LAET Training Data Gen: Distribution of optimal_p found (target for GBDT): " + f"Min={np.min(optimal_ps_found)}, Mean={np.mean(optimal_ps_found):.2f}, Median={np.median(optimal_ps_found)}, Max={np.max(optimal_ps_found)}, " + f"StdDev={np.std(optimal_ps_found):.2f}") + + print(f"LAET: Training data saved to {tsv_path}") + + + def _train_gbdt_model_internal(self, tsv_path, model_save_path, train_params_cfg): + print(f"LAET: Training GBDT model from {tsv_path}...") + data_df = pd.read_csv(tsv_path, sep='\t', header=None) + target = data_df.iloc[:, 0].values.astype(np.float32) + features = data_df.iloc[:, 2:].values.astype(np.float32) + + log_target_training = train_params_cfg.get("log_target_training", False) + if log_target_training: target = np.log2(np.maximum(1, target)) + self.log_target_prediction = log_target_training + + X_tr, X_te, y_tr, y_te = train_test_split(features, target, test_size=train_params_cfg.get("test_size", 0.1), random_state=42) + + lgb_tr_data = lgb.Dataset(X_tr, y_tr) + lgb_te_data = lgb.Dataset(X_te, y_te, reference=lgb_tr_data) + + lgbm_params = { + 'objective': 'regression_l1', 'metric': 'mae', + 'num_leaves': train_params_cfg.get("num_leaves", 31), + 'learning_rate': train_params_cfg.get("learning_rate", 0.05), + 'feature_fraction': train_params_cfg.get("feature_fraction", 0.9), + 'bagging_fraction': train_params_cfg.get("bagging_fraction", 0.8), + 'bagging_freq': train_params_cfg.get("bagging_freq", 5), + 'verbose': -1, 'n_jobs': -1, 'seed': 42, + 'n_estimators': train_params_cfg.get("n_estimators", 100) + } + num_boost_round_val = lgbm_params['n_estimators'] + + gbm = lgb.train(lgbm_params, lgb_tr_data, num_boost_round=num_boost_round_val, + valid_sets=[lgb_tr_data, lgb_te_data], + callbacks=[lgb.early_stopping(15, verbose=False), lgb.log_evaluation(period=0)]) + + self.gbdt_model = gbm + current_log_suffix = "_Log" if self.log_target_prediction else "" + effective_model_filename = f"{self.model_name_prefix}_gbdt_model{current_log_suffix}.txt" + effective_model_save_path = self.model_output_dir / effective_model_filename + + gbm.save_model(str(effective_model_save_path)) + self.full_gbdt_model_path = effective_model_save_path + print(f"LAET: GBDT model saved to {self.full_gbdt_model_path}") + + def get_or_train_model(self, overwrite_model=False, + data_paths_config=None, + generation_params_config=None, + faiss_params_config=None, + training_params_config=None + ): + potential_log_target = training_params_config.get("log_target_training", False) if training_params_config else self.config.get("model_was_trained_on_log_target", False) + _log_suffix_check = "_Log" if potential_log_target else "" + expected_model_filename_if_trained_now = f"{self.model_name_prefix}_gbdt_model{_log_suffix_check}.txt" + path_to_check_or_create = self.model_output_dir / expected_model_filename_if_trained_now + + if not overwrite_model and path_to_check_or_create.exists(): + print(f"LAET: Loading existing GBDT model: {path_to_check_or_create}") + self.gbdt_model = lgb.Booster(model_file=str(path_to_check_or_create)) + self.log_target_prediction = "_Log" in path_to_check_or_create.name + self.full_gbdt_model_path = path_to_check_or_create + print(f"LAET: Model loaded. Actual log_target_prediction: {self.log_target_prediction}") + else: + print(f"LAET: Training GBDT model (overwrite={overwrite_model}, exists={path_to_check_or_create.exists()})...") + if not all([data_paths_config, generation_params_config, faiss_params_config, training_params_config]): + raise ValueError("Missing configurations for LAET model training.") + + training_tsv_filename = f"{self.model_name_prefix}_gbdt_train.tsv" + full_training_tsv_path = self.training_data_output_dir / training_tsv_filename + + self._generate_training_data_tsv_internal( + full_training_tsv_path, + data_paths_config, + generation_params_config, + faiss_params_config + ) + self._train_gbdt_model_internal( + full_training_tsv_path, + path_to_check_or_create, + training_params_config + ) + if self.vector_dim is None and self.gbdt_model and hasattr(self.gbdt_model, 'num_feature'): + self.vector_dim = self.gbdt_model.num_feature() + + def _predict_base_search_param(self, query_vector_np): + if not self.gbdt_model: raise RuntimeError("LAET GBDT model not loaded.") + if self.vector_dim is None: self.vector_dim = query_vector_np.shape[0] + if query_vector_np.shape[0] != self.vector_dim: + raise ValueError(f"Query dim {query_vector_np.shape[0]} != model's {self.vector_dim}") + + features = query_vector_np.astype(np.float32).flatten() + pred_raw = self.gbdt_model.predict(features.reshape(1, -1))[0] + pred_val = np.power(2, pred_raw) if self.log_target_prediction else pred_raw + return max(1, int(round(pred_val))) + + def _compute_recall_single_q(self, res_ids_tensor, gt_set_top_k, k_val_for_recall): + if not gt_set_top_k or res_ids_tensor is None or res_ids_tensor.numel() == 0 or k_val_for_recall == 0: + return 0.0 + results_to_check = res_ids_tensor[:min(res_ids_tensor.numel(), k_val_for_recall)].tolist() + hits = 0 + for res_idx in results_to_check: + if res_idx in gt_set_top_k and res_idx >= 0: + hits += 1 + return float(hits) / k_val_for_recall + + + def run_inference_for_quake_experiment(self, quake_idx, queries_torch, gt_torch, + target_recall, k_search, base_quake_sp, + num_bs_steps=20, multiplier_range=(0.1, 5.0)): + if not self.gbdt_model: + print("LAET Inference Error: GBDT model not loaded.") + return np.nan, np.nan, np.nan + + nq = queries_torch.shape[0] + if self.vector_dim is None: self.vector_dim = queries_torch.shape[1] + + gt_sets = [set(gt_torch[i, :min(gt_torch.shape[1], k_search)].tolist()) for i in range(nq)] + queries_np = queries_torch.numpy() + + multi_low, multi_high = multiplier_range + best_mult = multi_high + quake_nlist_cap = quake_idx.nlist() if callable(getattr(quake_idx, 'nlist', None)) else getattr(quake_idx, 'nlist', 2048) + + # --- Log GBDT base_p predictions sample --- + sample_size_for_log = min(nq, 100) + sample_base_p_preds = [self._predict_base_search_param(queries_np[i]) for i in range(sample_size_for_log)] + if sample_base_p_preds: + print(f"LAET INFERENCE (TargetRecall={target_recall:.2f}): Sample GBDT base_p predictions (first {sample_size_for_log}): " + f"Min={np.min(sample_base_p_preds)}, Mean={np.mean(sample_base_p_preds):.2f}, Max={np.max(sample_base_p_preds)}") + # --- End Log --- + + for bs_run_idx in range(num_bs_steps): + curr_mult = (multi_low + multi_high) / 2.0 + if abs(multi_low - multi_high) < 1e-4: break + recall_sum = 0.0 + + tune_nq = int(nq * 0.01) + for i in range(tune_nq): + base_p = self._predict_base_search_param(queries_np[i]) + final_p = min(max(1, int(round(base_p * curr_mult))), quake_nlist_cap) + + sp = None + if hasattr(base_quake_sp, 'clone') and callable(base_quake_sp.clone): sp = base_quake_sp.clone() + else: sp = type(base_quake_sp)() + + sp.nprobe, sp.k = final_p, k_search + res = quake_idx.search(queries_torch[i:i+1], sp) + ids = res.ids[0] if res.ids is not None and len(res.ids)>0 and res.ids[0] is not None else torch.empty(0, dtype=torch.long) + recall_sum += self._compute_recall_single_q(ids, gt_sets[i], k_search) + avg_rec = recall_sum / tune_nq if tune_nq > 0 else 0.0 + if avg_rec >= target_recall: best_mult, multi_high = curr_mult, curr_mult + else: multi_low = curr_mult + + print(f"LAET INFERENCE (TargetRecall={target_recall:.2f}): Determined best_mult = {best_mult:.3f}") + + final_recall_sum, total_time_ns, sum_nprobes = 0.0, 0, 0 + final_p_values_sample = [] + + for i in range(nq): + base_p = self._predict_base_search_param(queries_np[i]) + final_p = min(max(1, int(round(base_p * best_mult))), quake_nlist_cap) + sum_nprobes += final_p + if i < sample_size_for_log: # Log sample of final_p + final_p_values_sample.append(final_p) + + sp_final = None + if hasattr(base_quake_sp, 'clone') and callable(base_quake_sp.clone): sp_final = base_quake_sp.clone() + else: sp_final = type(base_quake_sp)() + + sp_final.nprobe, sp_final.k = final_p, k_search + + t_s = time.perf_counter_ns() + res = quake_idx.search(queries_torch[i:i+1], sp_final) + total_time_ns += (time.perf_counter_ns() - t_s) + ids = res.ids[0] if res.ids is not None and len(res.ids)>0 and res.ids[0] is not None else torch.empty(0, dtype=torch.long) + final_recall_sum += self._compute_recall_single_q(ids, gt_sets[i], k_search) + + if final_p_values_sample: + print(f"LAET INFERENCE (TargetRecall={target_recall:.2f}): Sample final_p values used (first {len(final_p_values_sample)}): " + f"Min={np.min(final_p_values_sample)}, Mean={np.mean(final_p_values_sample):.2f}, Max={np.max(final_p_values_sample)}") + + + avg_rec_f = final_recall_sum / nq if nq > 0 else 0.0 + avg_time_ms_f = (total_time_ns / nq) / 1e6 if nq > 0 else 0.0 + avg_nprobe_f = sum_nprobes / nq if nq > 0 else 0.0 + + + return avg_nprobe_f, avg_rec_f, avg_time_ms_f diff --git a/test/experiments/osdi2025/early_termination/run.py b/test/experiments/osdi2025/early_termination/run.py index 139597f9..e4e8af6a 100644 --- a/test/experiments/osdi2025/early_termination/run.py +++ b/test/experiments/osdi2025/early_termination/run.py @@ -1,2 +1,371 @@ +#!/usr/bin/env python3 +""" +Recall-Target Runner for Approximate Nearest Neighbor Search Methods. +Supports: Oracle, FixedNProbe, APS, and LAET (Learned Adaptive Early Termination). +""" +import time +import yaml +import logging +from pathlib import Path +import argparse +import torch +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt + +# Assuming 'quake' and 'laet' are in the PYTHONPATH or same directory +try: + from quake import QuakeIndex, IndexBuildParams, SearchParams + from quake.datasets.ann_datasets import load_dataset + from quake.utils import compute_recall +except ImportError as e: + print(f"Error importing Quake library components: {e}. Ensure 'quake' is installed and in PYTHONPATH.") + raise + +try: + # Adjust this import based on your project structure. + # If laet.py is in the same directory as this script, it should be: + # from laet import LAETPipeline + # Your current script uses a relative import: + from .laet import LAETPipeline +except ImportError as e: + # Fallback if relative import fails (e.g., script run as top-level) + try: + from laet import LAETPipeline + print("Note: Imported LAETPipeline using 'from laet import LAETPipeline'.") + except ImportError: + print(f"Error importing LAETPipeline: {e}. Ensure 'laet.py' is correctly placed and import path is valid.") + raise + + +# Setup basic logging +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') +logger = logging.getLogger(__name__) + +def run_experiment(cfg_path: str, output_dir_str: str): + """ + Runs the ANN experimentation pipeline. + + Args: + cfg_path (str): Path to the YAML configuration file. + output_dir_str (str): Path to the directory where results will be saved. + """ + # 1) Load config + setup output dir + logger.info(f"Loading configuration from: {cfg_path}") + try: + cfg = yaml.safe_load(Path(cfg_path).read_text()) + except FileNotFoundError: + logger.error(f"Configuration file not found: {cfg_path}") + return + except Exception as e: + logger.error(f"Error loading YAML configuration from {cfg_path}: {e}") + return + + out_path = Path(output_dir_str) + out_path.mkdir(parents=True, exist_ok=True) + logger.info(f"Output directory set to: {out_path}") + + # 2) Load data + data_dir = cfg["dataset"].get("path", "") + dataset_name = cfg["dataset"]["name"] + logger.info(f"Loading dataset: {dataset_name} from path: '{data_dir if data_dir else 'default'}'") + try: + vecs, queries_torch, gt_torch = load_dataset(dataset_name, data_dir) + except Exception as e: + logger.error(f"Failed to load dataset '{dataset_name}': {e}", exc_info=True) + return + + nq_config = cfg["experiment"].get("nq", queries_torch.shape[0]) + queries_torch, gt_torch = queries_torch[:nq_config], gt_torch[:nq_config] + logger.info(f"Using {queries_torch.shape[0]} queries for the experiment.") + + # 3) Build or load QuakeIndex (used by all methods) + idx_quake = QuakeIndex() + + build_params = IndexBuildParams() + build_params.nlist = cfg["index"]["nlist"] + build_params.metric = cfg["index"]["metric"] + build_params.num_workers = cfg["experiment"].get("n_workers", 0) + + idx_base_dir = Path(cfg["paths"].get("index_dir", out_path / "indexes")) + idx_base_dir.mkdir(parents=True, exist_ok=True) + idx_path_quake = idx_base_dir / f"{dataset_name}_quake_ivf{build_params.nlist}.index" + + if not idx_path_quake.exists() or cfg["overwrite"].get("index", False): + logger.info(f"Building QuakeIndex at {idx_path_quake}...") + try: + idx_quake.build(vecs, torch.arange(len(vecs)), build_params) + idx_quake.save(str(idx_path_quake)) + logger.info(f"QuakeIndex built and saved to {idx_path_quake}.") + except Exception as e: + logger.error(f"Failed to build or save QuakeIndex: {e}", exc_info=True) + return + else: + logger.info(f"Loading existing QuakeIndex from {idx_path_quake}...") + try: + idx_quake.load(str(idx_path_quake), 0) + logger.info(f"QuakeIndex loaded successfully.") + except Exception as e: + logger.error(f"Failed to load QuakeIndex from {idx_path_quake}: {e}", exc_info=True) + return + + current_index_nlist = idx_quake.nlist() if callable(getattr(idx_quake, 'nlist', None)) else getattr(idx_quake, 'nlist', build_params.nlist) + if current_index_nlist != build_params.nlist: + logger.warning(f"QuakeIndex nlist ({current_index_nlist}) differs from config ({build_params.nlist}). Using index's nlist: {current_index_nlist}.") + max_nlist_val = current_index_nlist + + + # 4) Initialize LAETPipeline if "LAET" is in methods + laet_pipeline_instance = None + if "LAET" in cfg["methods"]: + if not idx_quake: + logger.error("LAET method requires QuakeIndex, but it's not available. Skipping LAET.") + else: + laet_main_cfg = cfg.get("laet_config", {}) + laet_paths_cfg = cfg.get("paths", {}) # For laet_artifacts_base_dir + + # Prepare config for LAETPipeline constructor + pipeline_init_config = { + "base_dir": laet_paths_cfg.get("laet_artifacts_base_dir", "laet_pipeline_output"), + "training_data_subdir": laet_main_cfg.get("training_data_subdir", "laet_training_data"), + "model_subdir": laet_main_cfg.get("model_subdir", "laet_gbdt_models"), + "dataset_name_for_files": laet_main_cfg.get("dataset_name_for_files", dataset_name.upper()), + "index_key_for_files": laet_main_cfg.get("index_key_for_files", f"IVF{max_nlist_val}_Flat"), + "model_was_trained_on_log_target": laet_main_cfg.get("train_log_target", False) # Used for model naming if trained by pipeline + } + + laet_pipeline_instance = LAETPipeline(vector_dim=queries_torch.shape[1], + laet_artifacts_config=pipeline_init_config) + + # Prepare configs for get_or_train_model + # These paths should point to your primary dataset files for LAET GBDT training + data_paths_for_laet_training = { + "base_vectors": laet_main_cfg.get("base_vectors_path_for_laet_train", f"data/{dataset_name}_base.fvecs"), + "train_query_vectors": laet_main_cfg.get("train_query_vectors_path_for_laet_train", f"data/{dataset_name}_learn.fvecs"), + "gt_train": laet_main_cfg.get("gt_train_path_for_laet_train", f"data/{dataset_name}_learn_groundtruth.ivecs"), + "gt_format": laet_main_cfg.get("gt_format_for_laet_train", "ivecs"), + "training_vectors_for_faiss_index": laet_main_cfg.get("faiss_training_vectors_path_for_laet_train", f"data/{dataset_name}_learn.fvecs") + } + generation_params_for_laet_training = { + "num_train_queries_to_process": laet_main_cfg.get("num_laet_training_samples", 10000), + "k_gt_load_for_target": laet_main_cfg.get("laet_train_k_gt_load", 1), + "k_search_for_target": laet_main_cfg.get("laet_train_k_search", 10), + "max_nprobe_scan": laet_main_cfg.get("laet_train_max_nprobe", 128), + "max_efsearch_scan": laet_main_cfg.get("laet_train_max_efsearch", 256), + "param_scan_step": laet_main_cfg.get("laet_train_param_scan_step", 1) + } + faiss_params_for_laet_training = { + "faiss_index_key_for_gen": laet_main_cfg.get("faiss_index_key_for_laet_train_gen", f"IVF{max_nlist_val},Flat") + } + gbdt_training_params_for_laet = { + "log_target_training": laet_main_cfg.get("train_log_target", False), # This sets log_target_prediction in pipeline + "test_size": laet_main_cfg.get("train_gbdt_test_size", 0.1), + "num_leaves": laet_main_cfg.get("train_gbdt_num_leaves", 31), + "learning_rate": laet_main_cfg.get("train_gbdt_lr", 0.05), + "n_estimators": laet_main_cfg.get("train_gbdt_n_estimators", 100), + "feature_fraction": laet_main_cfg.get("train_gbdt_feature_fraction", 0.9), + "bagging_fraction": laet_main_cfg.get("train_gbdt_bagging_fraction", 0.8), + "bagging_freq": laet_main_cfg.get("train_gbdt_bagging_freq", 5) + } + + laet_pipeline_instance.get_or_train_model( + overwrite_model=cfg.get("overwrite", {}).get("laet_model", False), + data_paths_config=data_paths_for_laet_training, + generation_params_config=generation_params_for_laet_training, + faiss_params_config=faiss_params_for_laet_training, + training_params_config=gbdt_training_params_for_laet + ) + logger.info("LAET GBDT model is ready (loaded or trained).") + + # 5) Run each method × recall_target + records = [] + k_metric = cfg["experiment"]["k"] + + for method in cfg["methods"]: + for rt_metric in cfg["experiment"]["recall_targets"]: + logger.info(f"Running Method: {method}, Target Recall: {rt_metric:.3f}") + + mean_param_val, mean_recall_val, mean_time_ms_val = np.nan, np.nan, np.nan + std_param_val, std_recall_val, std_time_ms_val = np.nan, np.nan, np.nan + per_query_data_list = [] + + if method == "LAET": + if laet_pipeline_instance and idx_quake and laet_pipeline_instance.gbdt_model: + quake_sp_for_laet = SearchParams() + # k and nprobe will be set inside run_inference_for_quake_experiment + + bs_multiplier_range = tuple(laet_main_cfg.get("inference_multiplier_range", [0.1, 50.0])) + bs_steps = laet_main_cfg.get("inference_num_bs_steps", 20) + + try: + mean_param_val, mean_recall_val, mean_time_ms_val = \ + laet_pipeline_instance.run_inference_for_quake_experiment( + quake_idx=idx_quake, # Corrected from quake_index to idx_quake + queries_torch=queries_torch, + gt_torch=gt_torch, + target_recall=rt_metric, # Corrected from target_recall_metric + k_search=k_metric, # Corrected from k_search_quake + base_quake_sp=quake_sp_for_laet, # Corrected from base_quake_search_params + num_bs_steps=bs_steps, + multiplier_range=bs_multiplier_range + ) + std_param_val, std_recall_val, std_time_ms_val = 0.0, 0.0, 0.0 + logger.info(f"LAET @ RT={rt_metric:.3f} -> AvgParam={mean_param_val:.2f}, AvgRecall={mean_recall_val:.4f}, AvgTime={mean_time_ms_val:.3f}ms") + except Exception as e: + logger.error(f"Error during LAET inference run: {e}", exc_info=True) + mean_param_val, mean_recall_val, mean_time_ms_val = np.nan, np.nan, np.nan + else: + logger.warning(f"LAET method specified but pipeline/model or QuakeIndex not ready. Skipping for RT={rt_metric}.") + # Metrics remain NaN by default + + elif method in ["Oracle", "FixedNProbe", "APS"]: + if not idx_quake: + logger.warning(f"QuakeIndex not available for method {method}. Skipping.") + continue + + if method == "Oracle": + for i, q_single_torch in enumerate(queries_torch): + lo, hi, best_param_oracle = 1, max_nlist_val, max_nlist_val + while lo <= hi: + mid_param = (lo + hi) // 2 + sp_oracle_bs = SearchParams() + sp_oracle_bs.nprobe = mid_param + sp_oracle_bs.k = k_metric + res_oracle_bs = idx_quake.search(q_single_torch.unsqueeze(0), sp_oracle_bs) + rec_oracle_bs = compute_recall(res_oracle_bs.ids, gt_torch[i].unsqueeze(0), k_metric).item() + if rec_oracle_bs >= rt_metric: + best_param_oracle = mid_param + hi = mid_param - 1 + else: + lo = mid_param + 1 + + t_start_ns = time.perf_counter_ns() + sp_oracle_final = SearchParams() + sp_oracle_final.nprobe = best_param_oracle + sp_oracle_final.k = k_metric + res_oracle_final = idx_quake.search(q_single_torch.unsqueeze(0), sp_oracle_final) + elapsed_ns = time.perf_counter_ns() - t_start_ns + rec_oracle_final = compute_recall(res_oracle_final.ids, gt_torch[i].unsqueeze(0), k_metric).item() + per_query_data_list.append((best_param_oracle, rec_oracle_final, elapsed_ns / 1_000_000.0)) + + elif method == "FixedNProbe": + lo_fixed, hi_fixed, best_overall_param_fixed = 1, max_nlist_val, max_nlist_val + while lo_fixed <= hi_fixed: + mid_param_fixed = (lo_fixed + hi_fixed) // 2 + sp_fixed_bs = SearchParams() + sp_fixed_bs.nprobe = mid_param_fixed + sp_fixed_bs.k = k_metric + sp_fixed_bs.recall_target = -1 + + ids_list_fixed = [] + for q_bs_fixed in queries_torch: + res_bs_fixed = idx_quake.search(q_bs_fixed.unsqueeze(0), sp_fixed_bs) + if res_bs_fixed.ids is not None and res_bs_fixed.ids.numel() > 0: + ids_list_fixed.append(res_bs_fixed.ids) + + if not ids_list_fixed: avg_rec_fixed = 0.0 + else: avg_rec_fixed = compute_recall(torch.cat(ids_list_fixed, 0), gt_torch, k_metric).mean().item() + + if avg_rec_fixed >= rt_metric: + best_overall_param_fixed = mid_param_fixed + hi_fixed = mid_param_fixed - 1 + else: lo_fixed = mid_param_fixed + 1 + + for i, q_single_torch in enumerate(queries_torch): + t_start_ns = time.perf_counter_ns() + sp_fixed_final = SearchParams() + sp_fixed_final.nprobe = best_overall_param_fixed + sp_fixed_final.k = k_metric + sp_fixed_final.recall_target = -1 + res_fixed_final = idx_quake.search(q_single_torch.unsqueeze(0), sp_fixed_final) + elapsed_ns = time.perf_counter_ns() - t_start_ns + rec_fixed_final = compute_recall(res_fixed_final.ids, gt_torch[i].unsqueeze(0), k_metric).item() + per_query_data_list.append((best_overall_param_fixed, rec_fixed_final, elapsed_ns / 1_000_000.0)) + + elif method == "APS": + for i, q_single_torch in enumerate(queries_torch): + sp_aps = SearchParams() + sp_aps.nprobe = -1 + sp_aps.k = k_metric + sp_aps.recall_target = rt_metric + sp_aps.recompute_threshold = cfg["experiment"].get("recompute_ratio", 0.00001) + sp_aps.use_precomputed = cfg["experiment"].get("use_precompute", True) + sp_aps.initial_search_fraction = cfg["experiment"].get("initial_search_fraction", 0.1) + + t_start_ns = time.perf_counter_ns() + res_aps = idx_quake.search(q_single_torch.unsqueeze(0), sp_aps) + elapsed_ns = time.perf_counter_ns() - t_start_ns + rec_aps = compute_recall(res_aps.ids, gt_torch[i].unsqueeze(0), k_metric).item() + param_aps = res_aps.timing_info.partitions_scanned if hasattr(res_aps, 'timing_info') and hasattr(res_aps.timing_info, 'partitions_scanned') else np.nan + per_query_data_list.append((param_aps, rec_aps, elapsed_ns / 1_000_000.0)) + + if per_query_data_list: + arr = np.array(per_query_data_list, dtype=float) + if arr.size > 0: + mean_param_val, mean_recall_val, mean_time_ms_val = np.nanmean(arr, axis=0) + std_param_val, std_recall_val, std_time_ms_val = np.nanstd(arr, axis=0) + logger.info(f"{method} @ RT={rt_metric:.3f} -> AvgParam={mean_param_val:.2f}, AvgRecall={mean_recall_val:.4f}, AvgTime={mean_time_ms_val:.3f}ms") + else: + if method != "LAET": + logger.warning(f"Unknown method: {method}. Skipping.") + continue + + records.append({ + "Method": method, "RecallTarget": rt_metric, + "mean_nprobe": mean_param_val, "std_nprobe": std_param_val, + "mean_recall": mean_recall_val, "std_recall": std_recall_val, + "mean_time_ms": mean_time_ms_val, "std_time_ms": std_time_ms_val, + }) + + # 6) Save CSV + df_results = pd.DataFrame(records) + csv_filename = cfg["paths"].get("results_file_prefix", "experiment_summary") + f"_{dataset_name}.csv" + out_csv_path = out_path / csv_filename + df_results.to_csv(out_csv_path, index=False, float_format='%.4f') + logger.info(f"Results summary saved to: {out_csv_path}") + + # 7) Plotting + if not df_results.empty: + plot_filename = cfg["paths"].get("plot_file_prefix", "recall_comparison_plots") + f"_{dataset_name}.png" + plot_output_dir = Path(cfg["paths"].get("plot_dir", output_dir_str)) + plot_output_dir.mkdir(parents=True, exist_ok=True) + plot_path_full = plot_output_dir / plot_filename + + fig, axes = plt.subplots(3, 1, figsize=(10, 12), sharex=True) + unique_methods_in_results = df_results["Method"].unique() + + for m_name in unique_methods_in_results: + grp = df_results[df_results["Method"] == m_name].sort_values(by="RecallTarget") + if grp.empty: continue + + axes[0].errorbar(grp["RecallTarget"], grp["mean_time_ms"], yerr=grp["std_time_ms"], + marker="o", capsize=3, label=m_name, alpha=0.8, errorevery=1, elinewidth=1) + axes[1].errorbar(grp["RecallTarget"], grp["mean_recall"], yerr=grp["std_recall"], + marker="o", capsize=3, label=m_name, alpha=0.8, errorevery=1, elinewidth=1) + axes[2].errorbar(grp["RecallTarget"], grp["mean_nprobe"], yerr=grp["std_nprobe"], + marker="o", capsize=3, label=m_name, alpha=0.8, errorevery=1, elinewidth=1) + + axes[0].set_ylabel("Mean Query Time (ms)") + axes[0].set_title(f"Recall Target vs. Query Time ({dataset_name})") + axes[0].legend(); axes[0].grid(True, ls=":", alpha=0.7) + + recall_target_line_plot = np.array(cfg["experiment"]["recall_targets"]) + axes[1].plot(recall_target_line_plot, recall_target_line_plot, "k--", label="Target Recall", alpha=0.7) + axes[1].set_ylabel("Achieved Mean Recall") + axes[1].set_title(f"Recall Target vs. Achieved Recall ({dataset_name})") + axes[1].legend(); axes[1].grid(True, ls=":", alpha=0.7) + min_r, max_r = (df_results["mean_recall"].min() if pd.notna(df_results["mean_recall"].min()) else 0.0, + df_results["mean_recall"].max() if pd.notna(df_results["mean_recall"].max()) else 1.0) + axes[1].set_ylim(bottom=max(0.0, min_r - 0.05), top=min(1.01, max_r + 0.05)) + + axes[2].set_xlabel("Recall Target") + axes[2].set_ylabel("Mean Search Parameter (nprobe/equiv.)") + axes[2].set_yscale("log"); axes[2].set_title(f"Recall Target vs. Search Parameter ({dataset_name})") + axes[2].legend(); axes[2].grid(True, which="both", ls=":", alpha=0.7) + + plt.tight_layout(); plt.savefig(plot_path_full); plt.close(fig) + logger.info(f"Plots saved to: {plot_path_full}") + else: + logger.info("No data in results DataFrame, skipping plotting.") diff --git a/test/experiments/osdi2025/early_termination/util_laet.py b/test/experiments/osdi2025/early_termination/util_laet.py new file mode 100644 index 00000000..7a938c80 --- /dev/null +++ b/test/experiments/osdi2025/early_termination/util_laet.py @@ -0,0 +1,77 @@ +# File: util_laet.py +import numpy as np +import csv +import os +import sys + +def mmap_fvecs(fname): + """ Memory-maps an fvecs file. """ + x = np.memmap(fname, dtype='int32', mode='r') + d = x[0] + return x.view('float32').reshape(-1, d + 1)[:, 1:] + +def mmap_bvecs(fname): + """ Memory-maps a bvecs file. """ + x = np.memmap(fname, dtype='uint8', mode='r') + d = x[:4].view('int32')[0] + return x.reshape(-1, d + 4)[:, 4:] + +def read_tsv(filename, delimiter='\t', doInt=False, multi=1, rnd=-1): + """ + Reads a TSV file into a list of lists. + Handles potential errors during conversion and file access. + """ + ret = [] + if not os.path.exists(filename): + print(f"Warning: File not found {filename}", file=sys.stderr) + return ret + try: + with open(filename, 'r', newline='') as tsvfile: # Use newline='' for universal newlines + datareader = csv.reader(tsvfile, delimiter=delimiter) + for row_num, row in enumerate(datareader): + try: + l = [float(x) for x in row] + if multi != 1: + l = [multi * x for x in l] + if rnd != -1: + l = [round(x, rnd) for x in l] + if doInt: + l = [int(x) for x in l] + ret.append(l) + except ValueError as e: + print(f"Skipping malformed row #{row_num+1} in {filename}: {row}. Error: {e}", file=sys.stderr) + continue + except Exception as e: + print(f"Error opening or reading file {filename}: {e}", file=sys.stderr) + return ret + +def write_tsv(data, filename, delimiter='\t', append=False, doInt=False, multi=1, rnd=-1): + """ + Writes data to a TSV file. + """ + if not append: + try: + os.remove(filename) + except OSError: + pass # File doesn't exist, or other error (permissions etc.) + + processed_data = [] + if doInt or multi != 1 or rnd != -1: + for row_data in data: + new_row = list(row_data) # Make a copy to avoid modifying original list objects + if multi != 1: + new_row = [multi * x for x in new_row] + if rnd != -1: + new_row = [round(x, rnd) for x in new_row] + if doInt: + new_row = [int(x) for x in new_row] + processed_data.append(new_row) + else: + processed_data = data # Use data directly if no processing needed + + try: + with open(filename, 'a', newline='') as tsvfile: + writer = csv.writer(tsvfile, delimiter=delimiter) + writer.writerows(processed_data) + except Exception as e: + print(f"Error writing to file {filename}: {e}", file=sys.stderr) \ No newline at end of file diff --git a/test/experiments/osdi2025/experiment_runner.py b/test/experiments/osdi2025/experiment_runner.py index 9e443aab..e26da3a7 100644 --- a/test/experiments/osdi2025/experiment_runner.py +++ b/test/experiments/osdi2025/experiment_runner.py @@ -9,12 +9,14 @@ from test.experiments.osdi2025.numa_single_query.run import run_experiment as run_numa_single from test.experiments.osdi2025.numa_multi_query.run import run_experiment as run_numa_multi from test.experiments.osdi2025.aps_recall_targets.run import run_experiment as run_aps_recall +from test.experiments.osdi2025.early_termination.run import run_experiment as run_early_termination EXPERIMENTS = { "kick_the_tires": run_kick_the_tires, "numa_single_query": run_numa_single, "numa_multi_query": run_numa_multi, "aps_recall_targets": run_aps_recall, + "early_termination": run_early_termination } def main(): From e638c0e3368240e20bf3af8b74ab19fa66292528 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 7 May 2025 23:00:17 -0500 Subject: [PATCH 024/323] add APS baselines + cleanup geometry.h --- src/cpp/bindings/wrap.cpp | 15 + src/cpp/include/common.h | 16 +- src/cpp/include/geometry.h | 841 +++--------------- src/cpp/src/query_coordinator.cpp | 34 +- .../early_termination/configs/sift1m.yaml | 59 ++ .../osdi2025/early_termination/laet.py | 3 +- .../osdi2025/early_termination/run.py | 92 +- 7 files changed, 304 insertions(+), 756 deletions(-) create mode 100644 test/experiments/osdi2025/early_termination/configs/sift1m.yaml diff --git a/src/cpp/bindings/wrap.cpp b/src/cpp/bindings/wrap.cpp index 527aebad..8035e240 100644 --- a/src/cpp/bindings/wrap.cpp +++ b/src/cpp/bindings/wrap.cpp @@ -176,6 +176,21 @@ PYBIND11_MODULE(_bindings, m) { (std::string("Threshold to trigger recomputation of APS. default = ") + std::to_string(DEFAULT_RECOMPUTE_THRESHOLD)).c_str()) .def_readwrite("aps_flush_period_us", &SearchParams::aps_flush_period_us, (std::string("APS flush period in microseconds. default = ") + std::to_string(DEFAULT_APS_FLUSH_PERIOD_US)).c_str()) + .def_readwrite("k_factor", &SearchParams::k_factor, + "Factor to adjust the number of neighbors to return.") + .def_readwrite("track_hits", &SearchParams::track_hits, + "Flag to track hits for maintenance policy.") + .def_readwrite("use_auncel", &SearchParams::use_auncel, + "Flag to use Auncel recall estimation for search.") + .def_readwrite("auncel_a", &SearchParams::auncel_a, + "Auncel parameter a for recall estimation.") + .def_readwrite("auncel_b", &SearchParams::auncel_b, + "Auncel parameter b for recall estimation.") + .def_readwrite("use_spann", &SearchParams::use_spann, + "Flag to use SPANN for search.") + .def_readwrite("spann_eps", &SearchParams::spann_eps, + "SPANN parameter epsilon for search.") + .def_readwrite("parent_params", &SearchParams::parent_params, "Search parameters for the parent index, if any.") .def("__repr__", [](const SearchParams &s) { diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index be85509e..7489976c 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -174,12 +174,24 @@ struct SearchParams { float recall_target = DEFAULT_RECALL_TARGET; int num_threads = 1; // number of threads to use for search within a single worker float k_factor = 1.0f; - bool use_precomputed = DEFAULT_PRECOMPUTED; bool batched_scan = DEFAULT_BATCHED_SCAN; + + bool track_hits = true; + + // APS params + bool use_precomputed = DEFAULT_PRECOMPUTED; float recompute_threshold = DEFAULT_RECOMPUTE_THRESHOLD; float initial_search_fraction = DEFAULT_INITIAL_SEARCH_FRACTION; int aps_flush_period_us = DEFAULT_APS_FLUSH_PERIOD_US; - bool track_hits = true; + + // Auncel params + bool use_auncel = false; + float auncel_a = 1.0f; + float auncel_b = 1.0f; + + // Spann params + bool use_spann = false; + float spann_eps = 1.25; shared_ptr parent_params = nullptr; ///< Search parameters for the parent index, if any. diff --git a/src/cpp/include/geometry.h b/src/cpp/include/geometry.h index 465ef1b1..c27ca997 100644 --- a/src/cpp/include/geometry.h +++ b/src/cpp/include/geometry.h @@ -203,151 +203,32 @@ inline double log_hypersphere_volume(double radius, int dimension) { return log_volume; } -inline double hypersphere_surface_area(double radius, int d) { - return 2 * std::pow(M_PI, d / 2.0) * std::pow(radius, d - 1) / std::tgamma(d / 2.0); -} - -inline double compute_partial_cap_volume(double radius, double theta_min, double theta_max, int d) { - // Compute the volume of a hyperspherical cap between angles theta_min and theta_max - if (theta_min < 0 || theta_max > M_PI) { - throw std::invalid_argument("Theta values out of bounds."); - } - - double cap_volume = 0.0; - - // Using the regularized incomplete beta function - double sin2_theta_min = std::sin(theta_min) * std::sin(theta_min); - double sin2_theta_max = std::sin(theta_max) * std::sin(theta_max); - - double I_min = incomplete_beta((d - 1.0) / 2.0, 0.5, sin2_theta_min); - double I_max = incomplete_beta((d - 1.0) / 2.0, 0.5, sin2_theta_max); - - double surface_area = hypersphere_surface_area(radius, d); - cap_volume = surface_area * (I_max - I_min); - - return cap_volume; -} - - -inline double log_hyperspherical_cap_volume(double radius, double boundary_distance, int d, bool ratio = true, - bool use_precomputed = true, bool euclidean = true) { - double h = radius - boundary_distance; - - // Ensure h is within valid range - h = std::max(0.0, std::min(2 * radius, h)); - +inline double hyperspherical_cap_volume(double radius, double boundary_distance, int d, bool use_precomputed = true, bool euclidean = true) { if (euclidean) { - double x = pow((2 * radius * h - h * h) / (radius * radius), 1.0); - // use precomputed incomplete beta function - double inc_beta; - if (use_precomputed) { - inc_beta = incomplete_beta_lookup(x, d); - } else { - inc_beta = incomplete_beta((d + 1.0) / 2.0, 0.5, x); - } + // Ensure boundary distance is non-negative double + boundary_distance = std::max(0.0, boundary_distance); - if (inc_beta <= 0.0 || std::isnan(inc_beta) || std::isinf(inc_beta)) { - std::cerr << "Invalid incomplete beta value: " << inc_beta << std::endl; - return -std::numeric_limits::infinity(); - } + // If boundary is outside or on the query radius, the cap volume is 0 + if (boundary_distance >= radius) return 0.0; - double log_inc_beta = std::log(inc_beta); - double log_cap_volume; - if (!ratio) { - double log_sphere_volume = log_hypersphere_volume(radius, d); - log_cap_volume = std::log(0.5) + log_inc_beta + log_sphere_volume; - } else { - log_cap_volume = std::log(0.5) + log_inc_beta; - } + // Calculate x for incomplete beta function + double x = sqrt(1.0 - (boundary_distance / radius) * (boundary_distance / radius)); + x = std::clamp(x, 0.0, 1.0); // Clamp x to [0, 1] - return log_cap_volume; - } else { - // use intersection of spherical caps - if (ratio != true) { - throw std::invalid_argument("Ratio must be true for dot product distance"); - } + // Incomplete Beta parameters + double a = 0.5 * (d + 1.0); + double b = 0.5; + double I = use_precomputed + ? incomplete_beta_lookup(x, d) + : incomplete_beta(a, b, x); + return std::clamp(0.5 * I, 0.0, 0.5); + } else { // v_i = (1/2) * [ I( sin^2(phi/2); d/2, 1/2 ) - I( sin^2(theta_i/2); d/2, 1/2 ) ] - double log_inc_beta = std::log(incomplete_beta((d - 1) / 2.0, 0.5, std::sin(radius / 2.0) * std::sin(radius / 2.0))); double log_inc_beta_boundary = std::log(incomplete_beta((d - 1) / 2.0, 0.5, std::sin(boundary_distance / 2.0) * std::sin(boundary_distance / 2.0))); double log_cap_volume = std::log(0.5) + log_inc_beta - log_inc_beta_boundary; return log_cap_volume; - // compute volume of the intersection of two spherical caps (from the paper: concise formulas for the volume of hyperspherical caps) - - - } -} - -inline vector compute_intersection_volume(const Tensor &boundary_distances, float query_radius, int dimension, - bool use_precomputed = true) { - auto boundary_distances_ptr = boundary_distances.data_ptr(); - int num_partitions = boundary_distances.size(0); - std::vector partition_volumes(num_partitions, 0.0f); - - for (int j = 0; j < num_partitions; j++) { - float boundary_distance = boundary_distances_ptr[j]; - - if (boundary_distance >= query_radius) { - partition_volumes[j] = -1e8; - continue; - } - - double volume_ratio = log_hyperspherical_cap_volume(query_radius, boundary_distance, dimension, false, - use_precomputed); - - partition_volumes[j] = volume_ratio; - } - - return partition_volumes; -} - -inline Tensor compute_variance_in_direction_of_query(Tensor query, Tensor centroids, Tensor variance) { - int dimension = query.size(0); - int num_partitions = centroids.size(0); - auto query_ptr = query.data_ptr(); - auto centroids_ptr = centroids.data_ptr(); - auto variance_ptr = variance.data_ptr(); - - std::vector variances(num_partitions, 0.0f); - - for (int j = 0; j < num_partitions; j++) { - float *centroid = centroids_ptr + j * dimension; - float *variance = variance_ptr + j * dimension; - - float *query_minus_centroid = new float[dimension]; - subtract_arrays(query_ptr, centroid, query_minus_centroid, dimension); - - float dot_product = faiss::fvec_inner_product(query_minus_centroid, query_minus_centroid, dimension); - - variances[j] = dot_product; - delete[] query_minus_centroid; - } - - return torch::tensor(variances).clone(); -} - -inline void check_boundary_distances(const float* q, - const std::vector& C, - const std::vector& d, - int dim) -{ - const float* c0 = C[0]; - std::vector v(dim); - - for (size_t j = 1; j < C.size(); ++j) { - const float* cj = C[j]; - - /* signed distance via the explicit formula again */ - faiss::fvec_sub(dim, cj, c0, v.data()); - float vnorm = std::sqrt(faiss::fvec_inner_product(v.data(), v.data(), dim)); - float b = 0.5f*(faiss::fvec_inner_product(cj,cj,dim) - -faiss::fvec_inner_product(c0,c0,dim)); - float dj = std::fabs(faiss::fvec_inner_product(q, v.data(), dim) - b) / vnorm; - - if (std::fabs(dj - d[j]) > 0.01f * dj + 1e-6f) - throw std::runtime_error( - "boundary_distances[" + std::to_string(j) + "] inaccurate"); } } @@ -359,16 +240,6 @@ compute_recall_profile(const std::vector& boundary_distances, bool use_precomputed = true, bool euclidean = true) // Unused in these models { - // --- Configuration Flag --- - // 0: Original Scaled-IE (reconstructed, uses norm_vols internally) - // 1: Direct Proportional Allocation (P'_k = raw_vols[k]) - // 2: Independent Entry Allocation (P'_k = raw_vols[k]*P0 / (1-raw_vols[k])) - // 3: Concentration Penalized Allocation (P'_k = raw_vols[k] * (1-S2_norm)) - // 4: Radius-Difference Weighting (P'_k = raw_vols[k] * (R-d_k)) - // 5: Simplified IE Approx Weighting (P'_k = raw_vols[k] * (1 - 0.5*S1 + 0.5*v_k)) - const int method_flag = 0; // <<< CHANGE THIS FLAG FOR ABLATION STUDY >>> - // --- - const int m = static_cast(boundary_distances.size()); const float eps = 1e-9f; @@ -383,251 +254,38 @@ compute_recall_profile(const std::vector& boundary_distances, return p; } - // --- Step 1: Compute Raw Cap Volumes (Common to all methods) --- + // Compute raw cap volumes std::vector raw_vols(m, 0.0f); for (int j = 1; j < m; ++j) { - // Ensure boundary distance is non-negative double - double d = std::max(0.0, static_cast(boundary_distances[j])); - // If boundary is outside or on the query radius, the cap volume is 0 - if (d >= query_radius) continue; - - // Calculate x for incomplete beta function - double x = 1.0 - (d / query_radius) * (d / query_radius); - x = std::clamp(x, 0.0, 1.0); // Clamp x to [0, 1] - - // Incomplete Beta parameters - double a = 0.5 * (dimension + 1.0); - double b = 0.5; - double I = use_precomputed - ? incomplete_beta_lookup(x, dimension) // Needs definition - : incomplete_beta(a, b, x); // Needs definition - - // Raw volume is half the normalized surface area ratio, clamped to [0, 0.5] - raw_vols[j] = static_cast(std::clamp(0.5 * I, 0.0, 0.5)); + raw_vols[j] = hyperspherical_cap_volume(query_radius, boundary_distances[j], dimension, use_precomputed, euclidean); } - // --- Method Selection --- float P0 = 0.0f; // Root cell probability std::vector P_prime(m, 0.0f); // Intermediate neighbor probabilities (k>=1) - float P_prime_sum = 0.0f; // Sum of P_prime[k] for k>=1 - - switch (method_flag) { - case 0: { // M0: Original Scaled-IE (reconstructed) - //std::cout << "Using Method 0: Original Scaled-IE (Cumulative)" << std::endl; - // Uses intermediate normalization and P0 based on normalized vols - std::vector norm_vols = raw_vols; // Copy raw vols - float S1_for_norm = 0.0f; - for (int j = 1; j < m; ++j) S1_for_norm += norm_vols[j]; - - if (S1_for_norm > eps) { - for (int j = 1; j < m; ++j) norm_vols[j] /= S1_for_norm; - } else { - for (int j = 1; j < m; ++j) norm_vols[j] = 0.0f; - } + float P_prime_sum = 0.0f; // Sum of P_prime[k] for k>=1 - // Calculate P0 using normalized vols (as per original logic) - P0 = 1.0f; - for (int j = 1; j < m; ++j) { - P0 *= (1.0f - norm_vols[j]); - } - P0 = std::clamp(P0, 0.0f, 1.0f); + std::vector norm_vols = raw_vols; // Copy raw vols + float S1_for_norm = 0.0f; + for (int j = 1; j < m; ++j) S1_for_norm += norm_vols[j]; - // Calculate P_prime using cumulative S1, S2 on normalized vols - float S1_cum = 0.0f, S2_cum = 0.0f; - // Use lambda = m as per original code's default, or allow tuning - float lambda = static_cast(m); // Could be tuned here if needed - - for (int k = 1; k < m; ++k) { - S1_cum += norm_vols[k]; // Update cumulative sums *before* using them for k - S2_cum += norm_vols[k] * norm_vols[k]; - - // Calculate R factor using *cumulative* S1, S2 up to k - // Note: Original code used S1*S1 - S2. Ensure S1_cum is used correctly. - float R = 1.0f - S1_cum + 0.5f * lambda * (S1_cum * S1_cum - S2_cum); - - P_prime[k] = norm_vols[k] * std::max(0.0f, R); - P_prime_sum += P_prime[k]; // Accumulate sum for final normalization - } - // Note: This calculation is order-dependent based on how boundaries are indexed. - break; - } - - case 1: { // M1: Direct Proportional Allocation - //std::cout << "Using Method 1: Direct Proportional" << std::endl; - // P0 based on raw volumes - - std::vector norm_vols = raw_vols; // Copy raw vols - float S1_for_norm = 0.0f; - for (int j = 1; j < m; ++j) S1_for_norm += norm_vols[j]; - - if (S1_for_norm > eps) { - for (int j = 1; j < m; ++j) norm_vols[j] /= S1_for_norm; - } else { - for (int j = 1; j < m; ++j) norm_vols[j] = 0.0f; - } - - P0 = 1.0f; - for (int j = 1; j < m; ++j) P0 *= (1.0f - norm_vols[j]); - P0 = std::clamp(P0, 0.0f, 1.0f); - - // P_prime is just raw_vols - for (int k = 1; k < m; ++k) { - P_prime[k] = norm_vols[k]; - P_prime_sum += P_prime[k]; - } - // Ensure P_prime is non-negative - for (int k = 1; k < m; ++k) P_prime[k] = std::max(0.0f, P_prime[k]); - break; - } - - case 2: { // M2: Independent Entry Allocation - //std::cout << "Using Method 2: Independent Entry" << std::endl; - // P0 based on raw volumes - P0 = 1.0f; - for (int j = 1; j < m; ++j) P0 *= (1.0f - raw_vols[j]); - P0 = std::clamp(P0, 0.0f, 1.0f); - - if (P0 > eps) { // Avoid issues if P0 is near zero - for (int k = 1; k < m; ++k) { - float v_k = raw_vols[k]; - float one_minus_v_k = 1.0f - v_k; - // Check for valid v_k and avoid division by zero/small number - if (v_k > eps && one_minus_v_k > eps) { - P_prime[k] = v_k * P0 / one_minus_v_k; - // Clamp potentially large values if v_k is very close to 1? - // P_prime[k] = std::min(P_prime[k], 1.0f); // Optional clamping - P_prime_sum += P_prime[k]; - } - P_prime[k] = std::max(0.0f, P_prime[k]); // Ensure non-negative - } - } // else P_prime remains 0 - break; - } - - case 3: { // M3: Concentration Penalized Allocation - //std::cout << "Using Method 3: Concentration Penalized" << std::endl; - // P0 based on raw volumes - P0 = 1.0f; - for (int j = 1; j < m; ++j) P0 *= (1.0f - raw_vols[j]); - P0 = std::clamp(P0, 0.0f, 1.0f); - - float S1_raw = 0.0f; - float S2_raw = 0.0f; - for (int j = 1; j < m; ++j) { - S1_raw += raw_vols[j]; - S2_raw += raw_vols[j] * raw_vols[j]; - } - - float penalty_factor = 0.0f; - if (S1_raw > eps) { - float S1_raw_sq = S1_raw * S1_raw; - // Avoid division by zero if S1_raw_sq is somehow zero or negative - if (S1_raw_sq > eps) { - float S2_norm = S2_raw / S1_raw_sq; - penalty_factor = std::max(0.0f, 1.0f - S2_norm); - } - // Optional: include lambda=m scaling -> penalty_factor *= 0.5f * m; - } - - for (int k = 1; k < m; ++k) { - P_prime[k] = raw_vols[k] * penalty_factor; // Apply uniform penalty - P_prime_sum += P_prime[k]; - } - break; - } - - case 4: { // M4: Radius-Difference Weighting - //std::cout << "Using Method 4: Radius-Difference Weighting" << std::endl; - // P0 based on raw volumes - P0 = 1.0f; - for (int j = 1; j < m; ++j) P0 *= (1.0f - raw_vols[j]); - P0 = std::clamp(P0, 0.0f, 1.0f); - - for (int k = 1; k < m; ++k) { - float v_k = raw_vols[k]; - if (v_k > eps) { - // Use boundary_distances directly, ensure non-negative - float d_k = std::max(0.0f, boundary_distances[k]); - // Calculate non-uniform weight based on distance from radius - float mu_k_tilde = std::max(0.0f, query_radius - d_k); - P_prime[k] = v_k * mu_k_tilde; - P_prime_sum += P_prime[k]; - } - } - break; - } - - case 5: { // M5: Simplified IE Approx Weighting - //std::cout << "Using Method 5: Simplified IE Approx" << std::endl; - // P0 based on raw volumes - P0 = 1.0f; - for (int j = 1; j < m; ++j) P0 *= (1.0f - raw_vols[j]); - P0 = std::clamp(P0, 0.0f, 1.0f); - - float S1_raw = 0.0f; - for(int j=1; j eps) { - // Calculate non-uniform scaling factor - float mu_k_tilde = std::max(0.0f, 1.0f - 0.5f * S1_raw + 0.5f * v_k); - P_prime[k] = v_k * mu_k_tilde; - P_prime_sum += P_prime[k]; - } - } - break; - } - - case 6: { - std::vector norm_vols = raw_vols; // Copy raw vols - float S1_for_norm = 0.0f; - for (int j = 1; j < m; ++j) S1_for_norm += norm_vols[j]; - - if (S1_for_norm > eps) { - for (int j = 1; j < m; ++j) norm_vols[j] /= S1_for_norm; - } else { - for (int j = 1; j < m; ++j) norm_vols[j] = 0.0f; - } - - P0 = 1.0f; - for (int j = 1; j < m; ++j) P0 *= (1.0f - norm_vols[j]); - P0 = std::clamp(P0, 0.0f, 1.0f); - - float S2_raw = 0.0f; - for (int j = 1; j < m; ++j) { - S2_raw += norm_vols[j]; - } - - if (S2_raw > eps) { - for (int k = 1; k < m; ++k) { - float v_k = norm_vols[k]; - S2_raw -= v_k; // Update S2_raw for next iteration - float rel_L2_sq = (.5 * v_k * S2_raw); - float mu_k_tilde = 1 / (1.0f + rel_L2_sq); // Non-uniform scaling - P_prime[k] = v_k * std::max(mu_k_tilde, .001f); - P_prime_sum += P_prime[k]; - } - } else { // If S2 is zero, all raw_vols are zero, P_prime remains zero - for (int k = 1; k < m; ++k) { - P_prime[k] = norm_vols[k]; // Should be 0 - P_prime_sum += P_prime[k]; // Should be 0 - } - } - // Ensure P_prime is non-negative - for (int k = 1; k < m; ++k) P_prime[k] = std::max(0.0f, P_prime[k]); + if (S1_for_norm > eps) { + for (int j = 1; j < m; ++j) norm_vols[j] /= S1_for_norm; + } else { + for (int j = 1; j < m; ++j) norm_vols[j] = 0.0f; + } - break; - } + P0 = 1.0f; + for (int j = 1; j < m; ++j) P0 *= (1.0f - norm_vols[j]); // Survival probability of the root cell + P0 = std::clamp(P0, 0.0f, 1.0f); - default: - // Handle unknown method flag, e.g., throw error or default to Method 1 - //std::cerr << "Error: Unknown method_flag: " << method_flag << std::endl; - throw std::runtime_error("Unknown method_flag in compute_recall_profile"); - // Or fallback: goto method1_label; (using labels/goto is generally discouraged) + for (int k = 1; k < m; ++k) { + P_prime[k] = norm_vols[k]; + P_prime_sum += P_prime[k]; } + // Ensure P_prime is non-negative + for (int k = 1; k < m; ++k) P_prime[k] = std::max(0.0f, P_prime[k]); - // if the cluster_sizes are given, we can use them to scale the probabilities + // if the cluster_sizes are given, scale P_prime[k] by the size of the cluster. this is a rudimentary density estimation if (partition_sizes.size() > 0) { for (int k = 1; k < m; ++k) { if (partition_sizes[k] > 0) { @@ -636,9 +294,10 @@ compute_recall_profile(const std::vector& boundary_distances, } } - // --- Final Normalization --- + + // normalize probs std::vector probs(m, 0.0f); - probs[0] = P0; // Assign calculated P0 for the chosen method + probs[0] = P0; float target = 1.0f - P0; // Ensure target probability for neighbors is valid [0, 1] @@ -651,365 +310,113 @@ compute_recall_profile(const std::vector& boundary_distances, probs[k] = std::max(0.0f, P_prime[k] * scale); } - // --- Strict Renormalization --- - // This step ensures probs[1..m-1] sum *exactly* to target, - // correcting minor float inaccuracies or effects of max(0,...) + + // Strict renormalization to ensure sum is exactly 1 float current_sum_k = 0.0f; for (int k = 1; k < m; ++k) current_sum_k += probs[k]; if (current_sum_k > eps) { // Avoid division by zero if sum is negligible - float final_scale = target / current_sum_k; - // Check if scale is finite (handles target=0 case correctly) - if (std::isfinite(final_scale)) { - for (int k = 1; k < m; ++k) { - probs[k] *= final_scale; - // Final clamp for safety - probs[k] = std::max(0.0f, probs[k]); - } - } else if (target <= eps) { - // If target is zero, all neighbor probs should be zero - for (int k = 1; k < m; ++k) probs[k] = 0.0f; - } + float final_scale = target / current_sum_k; + // Check if scale is finite (handles target=0 case correctly) + if (std::isfinite(final_scale)) { + for (int k = 1; k < m; ++k) { + probs[k] *= final_scale; + // Final clamp for safety + probs[k] = std::max(0.0f, probs[k]); + } + } else if (target <= eps) { + // If target is zero, all neighbor probs should be zero + for (int k = 1; k < m; ++k) probs[k] = 0.0f; + } } else if (target <= eps) { - // If target is zero and calculated sum is zero, ensure all are zero - for (int k = 1; k < m; ++k) probs[k] = 0.0f; + // If target is zero and calculated sum is zero, ensure all are zero + for (int k = 1; k < m; ++k) probs[k] = 0.0f; } - // --- End Optional Strict Renormalization --- - } return probs; } -// inline std::vector -// compute_recall_profile(const std::vector& boundary_distances, -// float query_radius, -// int dimension, -// std::vector partition_sizes = {}, -// bool use_precomputed = true, -// bool euclidean = true) -// { -// const int m = static_cast(boundary_distances.size()); -// const float eps = 1e-9f; -// -// if (m <= 1) { -// if (m == 1) return {1.0f}; -// return {}; -// } -// if (query_radius <= eps) { -// std::vector p(m, 0.0f); -// p[0] = 1.0f; -// return p; -// } -// -// // 1) compute raw cap‐volumes vols[1..m-1] -// std::vector vols(m, 0.0f); -// for (int j = 1; j < m; ++j) { -// double d = std::max(0.0, static_cast(boundary_distances[j])); -// if (d >= query_radius) continue; -// double x = 1.0 - (d/query_radius)*(d/query_radius); -// x = std::clamp(x, 0.0, 1.0); -// -// double a = 0.5*(dimension + 1.0), b = 0.5, I = 0.0; -// try { -// I = use_precomputed -// ? incomplete_beta_lookup(x, dimension) -// : incomplete_beta(a, b, x); -// } catch(...) { -// I = 0.0; -// } -// vols[j] = std::clamp(0.5 * I, 0.0, 0.5); -// } -// -// // // 2) normalize vols[1..] to sum = 1 -// // float sumv = std::accumulate(vols.begin()+1, vols.end(), 0.0f); -// // if (sumv > eps) { -// // for (int j = 1; j < m; ++j) vols[j] /= sumv; -// // } else { -// // std::fill(vols.begin()+1, vols.end(), 0.0f); -// // } -// -// // 3) compute reference P0 = ∏_{j=1..m-1}(1 - vols[j]) -// float P0 = 1.0f; -// for (int j = 1; j < m; ++j) { -// P0 *= (1.0f - vols[j]); -// } -// -// // 4) compute raw Pk for k>=1 under chosen mode -// std::vector raw(m, 0.0f); -// -// // 4) if scaled‐IE, compute λ = 1 / ∑v_j^2 -// float lambda = (float) boundary_distances.size(); -// // float lambda = -// // if (use_scaled_ie) { -// // float sum2 = 0.0f; -// // for (int j=1;jeps ? 1.0f/sum2 : 1.0f); -// // } -// -// std::cout << "lambda: " << lambda << std::endl; -// -// // -- Scaled‐IE: λ·(S1²−S2) in pairwise term -- -// float S1 = 0.0f, S2 = 0.0f; -// for (int k = 1; k < m; ++k) { -// S1 += vols[k]; -// S2 += vols[k]*vols[k]; -// float R = 1.0f -// - S1 -// + 0.5f*lambda*(S1*S1 - S2); -// raw[k] = vols[k] * std::max(0.0f, R); -// } -// std::cout << "S1: " << S1 << " S2: " << S2 << std::endl; -// -// // float scale_term = 1.0f; -// // for (int k = 1; k < m; ++k) { -// // raw[k] = vols[k] * scale_term; -// // scale_term *= (1.0f - vols[k]); -// // } -// -// // for (int k = 1; k < m; ++k) { -// // float scale_term = P0 / (1 - vols[k]); -// // raw[k] = vols[k] * scale_term; -// // } -// -// // 5) scale k>=1 so they sum to (1 - P0), leave P0 unchanged -// float sum_raw = std::accumulate(raw.begin()+1, raw.end(), 0.0f); -// std::vector probs(m, 0.0f); -// probs[0] = P0; -// -// float target = 1.0f - P0; -// if (sum_raw > eps) { -// float scale = target / sum_raw; -// for (int k = 1; k < m; ++k) { -// probs[k] = std::max(0.0f, raw[k] * scale); -// } -// } -// -// return probs; -// } - -// inline std::vector -// compute_recall_profile(const std::vector& boundary_distances, -// float query_radius, -// int dimension, -// std::vector partition_sizes = {}, -// bool use_precomputed = true, -// bool euclidean = true) -// { -// const int m = static_cast(boundary_distances.size()); -// const float float_epsilon = 1e-9f; // Small value for float comparisons -// -// // Handle edge cases: no cells or only the home cell -// if (m == 0) { -// return {}; -// } -// if (m == 1) { -// return {1.0f}; // Only home cell exists, probability is 1 -// } -// if (query_radius <= float_epsilon) { -// // If query radius is zero or negligible, k-NN must be in home cell -// std::vector probs(m, 0.0f); -// probs[0] = 1.0f; -// return probs; -// } -// -// -// std::vector vols(m, 0.0f); // Raw cap volume ratios (v_j for j>=1) -// -// // --- 1. Calculate raw cap ratios v_j for neighbors j = 1 to m-1 --- -// for (int j = 1; j < m; ++j) { -// float d_edge = boundary_distances[j]; // Distance to bisector plane j -// -// // Clamp distance to be non-negative (numerical safety) -// d_edge = std::max(0.0f, d_edge); -// -// // If plane is beyond radius, cap volume is zero -// if (d_edge >= query_radius) { -// vols[j] = 0.0f; -// continue; -// } -// -// // Calculate x = 1 - (d_edge/query_radius)^2 for betainc arg I_x(a, b) -// // Use doubles for intermediate calculation for precision -// double r_double = static_cast(query_radius); -// double d_double = static_cast(d_edge); -// double ratio_d_r = d_double / r_double; -// double x = 1.0 - ratio_d_r * ratio_d_r; -// -// // Clamp x to [0, 1] due to potential floating point inaccuracies -// x = std::clamp(x, 0.0, 1.0); -// -// // Parameters for incomplete beta I_x(a, b) for hyperspherical cap volume ratio -// double a_param = 0.5 * (static_cast(dimension) + 1.0); -// double b_param = 0.5; -// -// double beta_inc_value = 0.0; -// try { -// beta_inc_value = use_precomputed -// ? incomplete_beta_lookup(x, dimension) -// : incomplete_beta(a_param, b_param, x); -// } catch (const std::exception& e) { -// // Warn if beta calculation fails, default volume to 0 -// // Consider more robust error handling if needed -// #if DEBUG // Optional: Only print in debug builds -// fprintf(stderr, -// "Warning: Incomplete Beta calculation failed for x=%.6f, dim=%d. Defaulting cap vol to 0. Error: %s\n", -// x, dimension, e.what()); -// #endif -// beta_inc_value = 0.0; -// } -// -// // Cap volume ratio = 0.5 * I_x(a, b) -// vols[j] = 0.5f * static_cast(beta_inc_value); -// // Clamp result to ensure it's within valid range [0, 0.5] -// vols[j] = std::clamp(vols[j], 0.0f, 0.5f); -// } -// -// // --- 2. Calculate mu = sum(v_j) for j>=1 --- -// float mu_total = std::accumulate(vols.begin() + 1, vols.end(), 0.0f); -// -// // normalize volumes to sum to 1.0 -// if (mu_total > float_epsilon) { -// for (int j = 1; j < m; ++j) { -// vols[j] /= mu_total; -// } -// } else { -// // If mu is near zero, set all volumes to zero -// std::fill(vols.begin() + 1, vols.end(), 0.0f); -// } -// // --- 4. Calculate Improved P0 = max(exp(-mu), 1 - v1) --- -// -// vector survival_function(m, 1.0f); -// int k_neighbors = 100; -// for (int j = m-1; j > 0; --j) { -// survival_function[j-1] = survival_function[j] * (1.0f - (vols[j])); -// } -// -// // --- 5. Calculate neighbor probabilities P_j = (1-P0)*v_j/mu --- -// std::vector probs(m, 0.0f); -// probs[0] = survival_function[0]; -// -// // for (int j = 1; j < m; j++) { -// // probs[j] = vols[j] * (survival_function[0] / (1 - vols[j])); -// // } -// -// // for (int j = 1; j < m; ++j) { -// // probs[j] = survival_function[j] - survival_function[j - 1]; -// // } -// -// float remaining_mass = 1.0f - probs[0]; -// float cum_v = 0.0f; // Σ_{i float_epsilon) { -// // for (int j = 1; j < m; ++j) { -// // probs[j] = (accum / (1 - vols[j])) - accum; // reverse the survival function -// // probs[j] = std::clamp(probs[j], 0.0f, 1.0f); -// // accum += probs[j]; -// // } -// // } -// // If P_neighbors_total or mu is near zero, probs[1...m-1] remain 0.0f. -// -// // --- 6. Final Renormalization (Safety Net for Floating Point Drift) --- -// float sum_probs = std::accumulate(probs.begin(), probs.end(), 0.0f); -// -// if (sum_probs > float_epsilon) { -// float inv_sum = 1.0f / sum_probs; -// for (int j = 0; j < m; ++j) { -// // Ensure probabilities are non-negative after division -// probs[j] = std::max(0.0f, probs[j] * inv_sum); -// } -// // Ensure sum is exactly 1.0, assign difference to largest element (usually P0) -// float final_sum_check = std::accumulate(probs.begin(), probs.end(), 0.0f); -// probs[0] += (1.0f - final_sum_check); // Add residual to P0 -// -// -// } else { -// // If sum is zero (should be rare unless m=0), reset to P0=1. -// if (m > 0) { -// std::fill(probs.begin() + 1, probs.end(), 0.0f); -// probs[0] = 1.0f; -// } -// } -// -// return probs; -// } - -inline float compute_intersection_volume_one(float boundary_distance, float query_radius, int dimension) { - if (boundary_distance >= query_radius) { - return -1e8; +inline std::vector +compute_recall_profile_auncel( + const std::vector& boundary_distances, + float query_radius, + int K_neighbors, + float a, + float b +) { + const size_t L = boundary_distances.size(); + + // 1) Spherical-cap "angle" terms + std::vector cap_terms(L, 0.0f); + if (query_radius > 1e-9f) { + for (size_t j = 0; j < L; ++j) { + float r = boundary_distances[j] / query_radius; + r = std::clamp(r, -1.0f, 1.0f); + cap_terms[j] = (r >= 1.0f ? 0.0f : std::acos(r)); + } } - double volume_ratio = log_hyperspherical_cap_volume(query_radius, boundary_distance, dimension, true); + // 2) Calculate phi_values for each stage + std::vector phi_values(L + 1); + float running_U_sum = std::accumulate(cap_terms.begin(), cap_terms.end(), 0.0f); - return volume_ratio; -} + for (size_t i = 0; i <= L; ++i) { + float denominator = b - a * running_U_sum; + if (denominator <= 1e-9f) { + phi_values[i] = std::numeric_limits::max(); + } else { + phi_values[i] = 1.0f / denominator; + } + phi_values[i] = std::max(1.0f, phi_values[i]); // Ensure phi >= 1 -inline Tensor estimate_overlap(const Tensor &new_centroid, const Tensor &old_centroid, const Tensor &nbr_centroids) { - Tensor residual = new_centroid - old_centroid; - int dimension = new_centroid.size(0); - - vector old_boundary_distance(nbr_centroids.size(0), -1.0f); - vector new_boundary_distance(nbr_centroids.size(0), -1.0f); - - const float *residual_ptr = residual.data_ptr(); - const float *new_centroid_ptr = new_centroid.data_ptr(); - const float *old_centroid_ptr = old_centroid.data_ptr(); - const float *nbr_centroids_ptr = nbr_centroids.data_ptr(); - - std::vector line_vector(dimension); - std::vector midpoint(dimension); - std::vector projection(dimension); - - // compute distance to old boundary - for (int j = 0; j < nbr_centroids.size(0); j++) { - subtract_arrays(nbr_centroids_ptr + (dimension * j), old_centroid_ptr, line_vector.data(), dimension); - divide_array_by_constant(line_vector.data(), 2.0f, midpoint.data(), dimension); - float norm = faiss::fvec_inner_product(midpoint.data(), midpoint.data(), dimension); - norm = std::sqrt(norm); - old_boundary_distance[j] = norm; + if (i < L) { + running_U_sum -= cap_terms[i]; + } } - // compute distance to new boundary - for (int j = 0; j < nbr_centroids.size(0); j++) { - subtract_arrays(nbr_centroids_ptr + (dimension * j), new_centroid_ptr, line_vector.data(), dimension); - divide_array_by_constant(line_vector.data(), 2.0f, midpoint.data(), dimension); - float norm = faiss::fvec_inner_product(midpoint.data(), midpoint.data(), dimension); - norm = std::sqrt(norm); - new_boundary_distance[j] = norm; - } + // 3) Calculate cumulative recall based on phi_values + std::vector cumulative_recalls(L + 1, 0.0f); + for (size_t i = 0; i <= L; ++i) { + float current_phi = phi_values[i]; + float j_star = 0.0f; + + if (K_neighbors > 0) { + if (current_phi == std::numeric_limits::max()) { + j_star = 0.0f; + } else if (current_phi > 1e-9f) { + j_star = std::floor((float)K_neighbors / current_phi); + j_star = std::min(std::max(0.0f, j_star), (float)K_neighbors); + } + } - Tensor overlap_ratio = torch::empty({nbr_centroids.size(0)}, torch::kFloat32); + float error_i = 1.0f; // Default error if K_neighbors is 0 or no items found + if (K_neighbors > 0) { + error_i = 1.0f - j_star / (float)K_neighbors; + } + cumulative_recalls[i] = std::clamp(1.0f - error_i, 0.0f, 1.0f); + } - // for each neighbor, compute the hyperspherical cap volume, where the radius of the sphere is the distance to new boundary - // and the old boundary distance gives the height of the cap - float mean_new_boundary_distance = 0.0f; - float mean_old_boundary_distance = 0.0f; - for (int j = 0; j < nbr_centroids.size(0); j++) { - mean_new_boundary_distance += new_boundary_distance[j]; - mean_old_boundary_distance += old_boundary_distance[j]; + // 4) Calculate per-stage incremental recall + std::vector recall_profile(L + 1, 0.0f); + if (!cumulative_recalls.empty()) { + recall_profile[0] = cumulative_recalls[0]; + for (size_t i = 1; i <= L; ++i) { + recall_profile[i] = cumulative_recalls[i] - cumulative_recalls[i-1]; + recall_profile[i] = std::max(0.0f, recall_profile[i]); + } } - mean_new_boundary_distance /= nbr_centroids.size(0); - mean_old_boundary_distance /= nbr_centroids.size(0); - for (int j = 0; j < nbr_centroids.size(0); j++) { - overlap_ratio[j] = abs(new_boundary_distance[j] - old_boundary_distance[j]) / mean_old_boundary_distance; + // 5) Normalize the profile to sum to 1 + float S = std::accumulate(recall_profile.begin(), recall_profile.end(), 0.0f); + if (S > 1e-9f) { + for (auto &v : recall_profile) { + v /= S; + } } + // If S is 0 (e.g., K_neighbors=0 or zero predicted recall), profile remains all zeros. - return overlap_ratio; + return recall_profile; } -#endif // CPP_UTILS_GEOMETRY_H +#endif // CPP_UTILS_GEOMETRY_H \ No newline at end of file diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 364e75ab..78c04a88 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -616,12 +616,20 @@ shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partitio if (first_list || percent_change > search_params->recompute_threshold) { query_radius = curr_radius; - partition_probs = compute_recall_profile(boundary_distances, - query_radius, - dimension, - partition_sizes_vec, - search_params->use_precomputed, - metric_ == faiss::METRIC_L2); + if (search_params->use_auncel) { + partition_probs = compute_recall_profile_auncel(boundary_distances, + query_radius, + search_params->k, + search_params->auncel_a, + search_params->auncel_b); + } else { + partition_probs = compute_recall_profile(boundary_distances, + query_radius, + dimension, + partition_sizes_vec, + search_params->use_precomputed, + metric_ == faiss::METRIC_L2); + } } float recall_estimate = 0.0; for (int i = 0; i < p + 1; i++) { @@ -630,12 +638,12 @@ shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partitio end_time = high_resolution_clock::now(); aps_time += duration_cast(end_time - start_time).count(); if (recall_estimate >= search_params->recall_target) { - timing_info->partitions_scanned = p + 1; break; } } } + timing_info->partitions_scanned = scanned_ids.size(); if (search_params->track_hits && maintenance_policy_) { maintenance_policy_->record_query_hits(std::vector(scanned_ids.begin(), scanned_ids.end())); @@ -692,6 +700,7 @@ shared_ptr QueryCoordinator::search(Tensor x, shared_ptrget_partition_ids(); @@ -718,9 +727,20 @@ shared_ptr QueryCoordinator::search(Tensor x, shared_ptrsearch(x, parent_search_params); partition_ids_to_scan = parent_search_result->ids; + partition_distances = parent_search_result->distances; parent_timing_info = parent_search_result->timing_info; } + if (search_params->use_spann && partition_distances.defined()) { + // prune partitions based on relative distance compared to nearest centroid + partition_distances = partition_distances / partition_distances.select(1, 0).unsqueeze(0); + + Tensor mask = partition_distances.ge(search_params->spann_eps); + + // set mask partition ids to -1 + partition_ids_to_scan.masked_fill_(mask, -1); + } + auto search_result = scan_partitions(x, partition_ids_to_scan, search_params); search_result->timing_info->parent_info = parent_timing_info; diff --git a/test/experiments/osdi2025/early_termination/configs/sift1m.yaml b/test/experiments/osdi2025/early_termination/configs/sift1m.yaml new file mode 100644 index 00000000..b8a92bdf --- /dev/null +++ b/test/experiments/osdi2025/early_termination/configs/sift1m.yaml @@ -0,0 +1,59 @@ +# File: configs/experiment.yaml +mode: run +base_dir: data/aps # Base for your project's data if needed by Quake's load_dataset +dataset: + name: sift1m # Used by Quake's load_dataset, e.g., "sift1m", "deep1m" + path: data # Path for Quake's load_dataset +experiment: + nq: 100 + k: 100 # k for search and recall calculation + n_workers: 0 + recall_targets: [.2, .3, .4, .5, .6, 0.7, .75, 0.8, .85, 0.9, 0.95, 0.99, .999] + # APS specific params (if used) + recompute_ratio: 0.01 + use_precompute: true + initial_search_fraction: .1 +index: # For QuakeIndex (APS, Oracle, FixedNProbe, and base for LAET) + metric: l2 + nlist: 1000 # This nlist is for your QuakeIndex +overwrite: + index: false # Whether to rebuild QuakeIndex + results: true +#methods: ['LAET', 'Auncel', 'Oracle', 'FixedNProbe', 'APS', 'SPANN'] # Added LAET +#methods: ['SPANN', 'FixedNProbe'] +#methods: ['Auncel'] # Added LAET +methods: ['APS', 'Oracle'] +#methods: ['APS'] + +paths: + index_dir: data/sift1m/indexes # For QuakeIndex files + results_dir: data/sift1m/results # For experiment output CSVs and plots + plot_dir: data/sift1m/plots + laet_artifacts_base_dir: data/laet_files # IMPORTANT: Base directory for all LAET artifacts + +laet_config: + laet_index_key_full: "IVF1000" # CRITICAL: Must match the index string in LAET's GBDT model + pred_thresh_for_model_features: 1 # The 'threshX' value from LAET's model filename (e.g., _model_thresh1_Full.txt). + feature_idx_for_model: 0 # 0-based index corresponding to `pred_thresh_for_model_features + base_vectors_path_for_laet_train: data/sift/sift_base.fvecs # Base vectors for LAET training + train_query_vectors_path_for_laet_train: data/sift/sift_query.fvecs # Training query vectors for LAET training + gt_train_path_for_laet_train: data/sift/sift_groundtruth.ivecs # Ground truth for LAET training + gt_format_for_laet_train: "ivecs" # Format for ground truth + faiss_training_vectors_path_for_laet_train: data/sift/sift_learn.fvecs # FAISS training vectors for LAET training + # if LAET generated features for a *list* of thresholds. + # E.g., if LAET's script had pred_thresh = [1,5,10] and this model + # is for the `thresh1` features, then feature_idx_for_model is 0. + # If LAET script used a single threshold value that matches + # `pred_thresh_for_model_features`, this is 0. + # Optional: + # multiplier_range: [0.1, 5.0] # Range for binary searching the nprobe multiplier + # num_binary_search_steps: 10 # Iterations for multiplier binary search + +# +# data_paths_for_laet_training = { +# "base_vectors": laet_main_cfg.get("base_vectors_path_for_laet_train", f"data/{dataset_name}_base.fvecs"), +# "train_query_vectors": laet_main_cfg.get("train_query_vectors_path_for_laet_train", f"data/{dataset_name}_learn.fvecs"), +# "gt_train": laet_main_cfg.get("gt_train_path_for_laet_train", f"data/{dataset_name}_learn_groundtruth.ivecs"), +# "gt_format": laet_main_cfg.get("gt_format_for_laet_train", "ivecs"), +# "training_vectors_for_faiss_index": laet_main_cfg.get("faiss_training_vectors_path_for_laet_train", f"data/{dataset_name}_learn.fvecs") +#} \ No newline at end of file diff --git a/test/experiments/osdi2025/early_termination/laet.py b/test/experiments/osdi2025/early_termination/laet.py index b9687270..0b260906 100644 --- a/test/experiments/osdi2025/early_termination/laet.py +++ b/test/experiments/osdi2025/early_termination/laet.py @@ -14,7 +14,6 @@ import torch from sklearn.metrics import mean_squared_error, mean_absolute_error -# --- Embedded I/O Utilities (Simplified) --- def _mmap_fvecs(fname): x = np.memmap(fname, dtype='int32', mode='r'); d = x[0]; return x.view('float32').reshape(-1, d + 1)[:, 1:] def _mmap_bvecs(fname): @@ -262,7 +261,7 @@ def run_inference_for_quake_experiment(self, quake_idx, queries_torch, gt_torch, if abs(multi_low - multi_high) < 1e-4: break recall_sum = 0.0 - tune_nq = int(nq * 0.01) + tune_nq = nq for i in range(tune_nq): base_p = self._predict_base_search_param(queries_np[i]) final_p = min(max(1, int(round(base_p * curr_mult))), quake_nlist_cap) diff --git a/test/experiments/osdi2025/early_termination/run.py b/test/experiments/osdi2025/early_termination/run.py index e4e8af6a..23e47988 100644 --- a/test/experiments/osdi2025/early_termination/run.py +++ b/test/experiments/osdi2025/early_termination/run.py @@ -1,9 +1,3 @@ -#!/usr/bin/env python3 -""" -Recall-Target Runner for Approximate Nearest Neighbor Search Methods. -Supports: Oracle, FixedNProbe, APS, and LAET (Learned Adaptive Early Termination). -""" - import time import yaml import logging @@ -15,7 +9,6 @@ import numpy as np import matplotlib.pyplot as plt -# Assuming 'quake' and 'laet' are in the PYTHONPATH or same directory try: from quake import QuakeIndex, IndexBuildParams, SearchParams from quake.datasets.ann_datasets import load_dataset @@ -25,13 +18,8 @@ raise try: - # Adjust this import based on your project structure. - # If laet.py is in the same directory as this script, it should be: - # from laet import LAETPipeline - # Your current script uses a relative import: from .laet import LAETPipeline except ImportError as e: - # Fallback if relative import fails (e.g., script run as top-level) try: from laet import LAETPipeline print("Note: Imported LAETPipeline using 'from laet import LAETPipeline'.") @@ -45,13 +33,6 @@ logger = logging.getLogger(__name__) def run_experiment(cfg_path: str, output_dir_str: str): - """ - Runs the ANN experimentation pipeline. - - Args: - cfg_path (str): Path to the YAML configuration file. - output_dir_str (str): Path to the directory where results will be saved. - """ # 1) Load config + setup output dir logger.info(f"Loading configuration from: {cfg_path}") try: @@ -179,7 +160,7 @@ def run_experiment(cfg_path: str, output_dir_str: str): ) logger.info("LAET GBDT model is ready (loaded or trained).") - # 5) Run each method × recall_target + # 5) Run each method × recall_target records = [] k_metric = cfg["experiment"]["k"] @@ -220,7 +201,7 @@ def run_experiment(cfg_path: str, output_dir_str: str): logger.warning(f"LAET method specified but pipeline/model or QuakeIndex not ready. Skipping for RT={rt_metric}.") # Metrics remain NaN by default - elif method in ["Oracle", "FixedNProbe", "APS"]: + elif method in ["Oracle", "FixedNProbe", "APS", "Auncel", "SPANN"]: if not idx_quake: logger.warning(f"QuakeIndex not available for method {method}. Skipping.") continue @@ -250,6 +231,63 @@ def run_experiment(cfg_path: str, output_dir_str: str): rec_oracle_final = compute_recall(res_oracle_final.ids, gt_torch[i].unsqueeze(0), k_metric).item() per_query_data_list.append((best_param_oracle, rec_oracle_final, elapsed_ns / 1_000_000.0)) + elif method == "Auncel": + for i, q_single_torch in enumerate(queries_torch): + sp_auncel = SearchParams() + sp_auncel.nprobe = -1 + sp_auncel.k = k_metric + sp_auncel.recall_target = rt_metric + sp_auncel.recompute_threshold = cfg["experiment"].get("recompute_ratio", 0.00001) + sp_auncel.use_auncel = True + sp_auncel.auncel_a = .005 + sp_auncel.auncel_b = 1.0 + sp_auncel.initial_search_fraction = cfg["experiment"].get("initial_search_fraction", 0.1) + + t_start_ns = time.perf_counter_ns() + res_auncel = idx_quake.search(q_single_torch.unsqueeze(0), sp_auncel) + elapsed_ns = time.perf_counter_ns() - t_start_ns + rec_auncel = compute_recall(res_auncel.ids, gt_torch[i].unsqueeze(0), k_metric).item() + param_aps = res_auncel.timing_info.partitions_scanned if hasattr(res_auncel, 'timing_info') and hasattr(res_auncel.timing_info, 'partitions_scanned') else np.nan + per_query_data_list.append((param_aps, rec_auncel, elapsed_ns / 1_000_000.0)) + + elif method == "SPANN": + lo_fixed, hi_fixed, best_overall_param_fixed = 1, max_nlist_val, max_nlist_val + while lo_fixed <= hi_fixed: + mid_param_fixed = (lo_fixed + hi_fixed) // 2 + sp_fixed_bs = SearchParams() + sp_fixed_bs.nprobe = mid_param_fixed + sp_fixed_bs.k = k_metric + sp_fixed_bs.use_spann = False + sp_fixed_bs.spann_eps = 2.0 + sp_fixed_bs.recall_target = -1 + + ids_list_fixed = [] + for q_bs_fixed in queries_torch: + res_bs_fixed = idx_quake.search(q_bs_fixed.unsqueeze(0), sp_fixed_bs) + if res_bs_fixed.ids is not None and res_bs_fixed.ids.numel() > 0: + ids_list_fixed.append(res_bs_fixed.ids) + + if not ids_list_fixed: avg_rec_fixed = 0.0 + else: avg_rec_fixed = compute_recall(torch.cat(ids_list_fixed, 0), gt_torch, k_metric).mean().item() + + if avg_rec_fixed >= rt_metric: + best_overall_param_fixed = mid_param_fixed + hi_fixed = mid_param_fixed - 1 + else: lo_fixed = mid_param_fixed + 1 + + for i, q_single_torch in enumerate(queries_torch): + t_start_ns = time.perf_counter_ns() + sp_fixed_final = SearchParams() + sp_fixed_final.nprobe = best_overall_param_fixed + sp_fixed_final.k = k_metric + sp_fixed_final.use_spann = True + sp_fixed_final.spann_eps = 1.5 + res_fixed_final = idx_quake.search(q_single_torch.unsqueeze(0), sp_fixed_final) + elapsed_ns = time.perf_counter_ns() - t_start_ns + rec_fixed_final = compute_recall(res_fixed_final.ids, gt_torch[i].unsqueeze(0), k_metric).item() + param_spann = res_fixed_final.timing_info.partitions_scanned if hasattr(res_fixed_final, 'timing_info') and hasattr(res_fixed_final.timing_info, 'partitions_scanned') else np.nan + per_query_data_list.append((param_spann, rec_fixed_final, elapsed_ns / 1_000_000.0)) + elif method == "FixedNProbe": lo_fixed, hi_fixed, best_overall_param_fixed = 1, max_nlist_val, max_nlist_val while lo_fixed <= hi_fixed: @@ -340,14 +378,12 @@ def run_experiment(cfg_path: str, output_dir_str: str): grp = df_results[df_results["Method"] == m_name].sort_values(by="RecallTarget") if grp.empty: continue - axes[0].errorbar(grp["RecallTarget"], grp["mean_time_ms"], yerr=grp["std_time_ms"], - marker="o", capsize=3, label=m_name, alpha=0.8, errorevery=1, elinewidth=1) - axes[1].errorbar(grp["RecallTarget"], grp["mean_recall"], yerr=grp["std_recall"], - marker="o", capsize=3, label=m_name, alpha=0.8, errorevery=1, elinewidth=1) - axes[2].errorbar(grp["RecallTarget"], grp["mean_nprobe"], yerr=grp["std_nprobe"], - marker="o", capsize=3, label=m_name, alpha=0.8, errorevery=1, elinewidth=1) + axes[0].plot(grp["RecallTarget"], grp["mean_time_ms"], marker="o", label=m_name, alpha=0.5) + axes[1].plot(grp["RecallTarget"], grp["mean_recall"], marker="o", label=m_name, alpha=0.5) + axes[2].plot(grp["RecallTarget"], grp["mean_nprobe"], marker="o", label=m_name, alpha=0.5) axes[0].set_ylabel("Mean Query Time (ms)") + axes[0].set_yscale("log") axes[0].set_title(f"Recall Target vs. Query Time ({dataset_name})") axes[0].legend(); axes[0].grid(True, ls=":", alpha=0.7) @@ -361,7 +397,7 @@ def run_experiment(cfg_path: str, output_dir_str: str): axes[1].set_ylim(bottom=max(0.0, min_r - 0.05), top=min(1.01, max_r + 0.05)) axes[2].set_xlabel("Recall Target") - axes[2].set_ylabel("Mean Search Parameter (nprobe/equiv.)") + axes[2].set_ylabel("Num Partitions Scanned") axes[2].set_yscale("log"); axes[2].set_title(f"Recall Target vs. Search Parameter ({dataset_name})") axes[2].legend(); axes[2].grid(True, which="both", ls=":", alpha=0.7) From f8909418cb49ff065d0e1d90b4a51ac4d001f761 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 9 May 2025 13:34:30 -0500 Subject: [PATCH 025/323] update multi-level --- src/cpp/include/common.h | 8 +- src/cpp/src/partition_manager.cpp | 2 +- src/cpp/src/query_coordinator.cpp | 5 + test/cpp/benchmark.cpp | 18 +- .../early_termination/configs/sift1m.yaml | 54 ++-- .../experiments/osdi2025/experiment_runner.py | 4 +- .../multi_level/configs/msturing10m.yaml | 136 ++++++++++ test/experiments/osdi2025/multi_level/run.py | 250 ++++++++++++++++++ 8 files changed, 424 insertions(+), 53 deletions(-) create mode 100644 test/experiments/osdi2025/multi_level/configs/msturing10m.yaml diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index 7489976c..cc0ac5fb 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -78,9 +78,9 @@ constexpr int DEFAULT_NPROBE = 1; ///< Default number of constexpr float DEFAULT_RECALL_TARGET = -1.0f; ///< Default recall target (a negative value means no adaptive search). constexpr bool DEFAULT_BATCHED_SCAN = false; ///< Default flag for batched scanning. constexpr bool DEFAULT_PRECOMPUTED = true; ///< Default flag to use precomputed incomplete beta fn for APS. -constexpr float DEFAULT_INITIAL_SEARCH_FRACTION = 0.02f; ///< Default initial fraction of partitions to search. +constexpr float DEFAULT_INITIAL_SEARCH_FRACTION = 0.1f; ///< Default initial fraction of partitions to search. constexpr float DEFAULT_RECOMPUTE_THRESHOLD = 0.001f; ///< Default threshold to trigger recomputation of search parameters. -constexpr int DEFAULT_APS_FLUSH_PERIOD_US = 100; ///< Default period (in microseconds) for flushing the APS buffer. +constexpr int DEFAULT_APS_FLUSH_PERIOD_US = 5; ///< Default period (in microseconds) for flushing the APS buffer. // Default constants for maintenance policy parameters constexpr const char* DEFAULT_MAINTENANCE_POLICY = "query_cost"; ///< Default maintenance policy type. @@ -91,8 +91,8 @@ constexpr int DEFAULT_MIN_PARTITION_SIZE = 32; ///< Default minimum allo constexpr float DEFAULT_ALPHA = 0.9f; ///< Default alpha parameter for maintenance. constexpr bool DEFAULT_ENABLE_SPLIT_REJECTION = true; ///< Default flag to enable rejection of splits. constexpr bool DEFAULT_ENABLE_DELETE_REJECTION = true; ///< Default flag to enable rejection of deletions. -constexpr float DEFAULT_DELETE_THRESHOLD_NS = 10.0f; ///< Default threshold in nanoseconds for deletion decisions. -constexpr float DEFAULT_SPLIT_THRESHOLD_NS = 10.0f; ///< Default threshold in nanoseconds for split decisions. +constexpr float DEFAULT_DELETE_THRESHOLD_NS = 100.0f; ///< Default threshold in nanoseconds for deletion decisions. +constexpr float DEFAULT_SPLIT_THRESHOLD_NS = 100.0f; ///< Default threshold in nanoseconds for split decisions. const vector DEFAULT_LATENCY_ESTIMATOR_RANGE_N = {1, 2, 4, 16, 64, 256, 1024, 4096, 16384, 65536}; ///< Default range of n values for latency estimator. const vector DEFAULT_LATENCY_ESTIMATOR_RANGE_K = {1, 4, 16, 64, 256}; ///< Default range of k values for latency estimator. diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index 0ca2f195..2b158b73 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -220,7 +220,7 @@ shared_ptr PartitionManager::add( } auto search_params = make_shared(); search_params->k = 1; - search_params->nprobe = parent_->nlist(); + search_params->recall_target = .999; if (n > 10) { search_params->batched_scan = true; } diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 78c04a88..ffdcd249 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -712,6 +712,11 @@ shared_ptr QueryCoordinator::search(Tensor x, shared_ptrrecompute_threshold = search_params->recompute_threshold; parent_search_params->initial_search_fraction = .5; parent_search_params->batched_scan = false; + + // check if parent is flat + if (parent_->parent_ == nullptr) { + parent_search_params->batched_scan = true; + } } else { parent_search_params = search_params->parent_params; } diff --git a/test/cpp/benchmark.cpp b/test/cpp/benchmark.cpp index 93574b9a..eb74bd90 100644 --- a/test/cpp/benchmark.cpp +++ b/test/cpp/benchmark.cpp @@ -496,17 +496,17 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { // Repeatedly search, add, remove, and perform maintenance to see if the index remains consistent. int64_t dimension = 128; - int64_t num_vectors = 10000; + int64_t num_vectors = 100000; int64_t num_queries = 1; int64_t batch_size = 10000; int n_ops = 100; QuakeIndex index; auto build_params = std::make_shared(); - build_params->nlist = 100; + build_params->nlist = 10000; build_params->metric = "l2"; build_params->niter = 5; - build_params->num_workers = 0; + build_params->num_workers = 1; auto maintenance_params = std::make_shared(); maintenance_params->refinement_radius = 10; @@ -519,10 +519,10 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { // add level auto parent_index_build_params = std::make_shared(); - parent_index_build_params->nlist = 1; + parent_index_build_params->nlist = 100; parent_index_build_params->metric = "l2"; parent_index_build_params->niter = 5; - parent_index_build_params->num_workers = 0; + parent_index_build_params->num_workers = 1; build_params->parent_params = parent_index_build_params; // auto grandparent_index_build_params = std::make_shared(); @@ -584,10 +584,10 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { // remove_time += std::chrono::duration_cast(end - start).count(); // ASSERT_EQ(remove_info->n_vectors, batch_size / 2); - start = std::chrono::high_resolution_clock::now(); - index.maintenance(); - end = std::chrono::high_resolution_clock::now(); - maintenance_time += std::chrono::duration_cast(end - start).count(); + // start = std::chrono::high_resolution_clock::now(); + // index.maintenance(); + // end = std::chrono::high_resolution_clock::now(); + // maintenance_time += std::chrono::duration_cast(end - start).count(); } // print out mean times per operation diff --git a/test/experiments/osdi2025/early_termination/configs/sift1m.yaml b/test/experiments/osdi2025/early_termination/configs/sift1m.yaml index b8a92bdf..3115bad5 100644 --- a/test/experiments/osdi2025/early_termination/configs/sift1m.yaml +++ b/test/experiments/osdi2025/early_termination/configs/sift1m.yaml @@ -1,59 +1,37 @@ # File: configs/experiment.yaml mode: run -base_dir: data/aps # Base for your project's data if needed by Quake's load_dataset +base_dir: data/aps dataset: - name: sift1m # Used by Quake's load_dataset, e.g., "sift1m", "deep1m" - path: data # Path for Quake's load_dataset + name: sift1m + path: data experiment: nq: 100 - k: 100 # k for search and recall calculation + k: 1 n_workers: 0 recall_targets: [.2, .3, .4, .5, .6, 0.7, .75, 0.8, .85, 0.9, 0.95, 0.99, .999] - # APS specific params (if used) - recompute_ratio: 0.01 + recompute_ratio: 0.0001 use_precompute: true initial_search_fraction: .1 -index: # For QuakeIndex (APS, Oracle, FixedNProbe, and base for LAET) +index: metric: l2 - nlist: 1000 # This nlist is for your QuakeIndex + nlist: 1000 overwrite: - index: false # Whether to rebuild QuakeIndex + index: false results: true -#methods: ['LAET', 'Auncel', 'Oracle', 'FixedNProbe', 'APS', 'SPANN'] # Added LAET -#methods: ['SPANN', 'FixedNProbe'] -#methods: ['Auncel'] # Added LAET -methods: ['APS', 'Oracle'] -#methods: ['APS'] +methods: ['LAET', 'Auncel', 'Oracle', 'FixedNProbe', 'APS', 'SPANN'] paths: - index_dir: data/sift1m/indexes # For QuakeIndex files - results_dir: data/sift1m/results # For experiment output CSVs and plots + index_dir: data/sift1m/indexes + results_dir: data/sift1m/results plot_dir: data/sift1m/plots - laet_artifacts_base_dir: data/laet_files # IMPORTANT: Base directory for all LAET artifacts + laet_artifacts_base_dir: data/laet_files laet_config: - laet_index_key_full: "IVF1000" # CRITICAL: Must match the index string in LAET's GBDT model - pred_thresh_for_model_features: 1 # The 'threshX' value from LAET's model filename (e.g., _model_thresh1_Full.txt). - feature_idx_for_model: 0 # 0-based index corresponding to `pred_thresh_for_model_features + laet_index_key_full: "IVF1000" + pred_thresh_for_model_features: 1 + feature_idx_for_model: 0 base_vectors_path_for_laet_train: data/sift/sift_base.fvecs # Base vectors for LAET training train_query_vectors_path_for_laet_train: data/sift/sift_query.fvecs # Training query vectors for LAET training gt_train_path_for_laet_train: data/sift/sift_groundtruth.ivecs # Ground truth for LAET training gt_format_for_laet_train: "ivecs" # Format for ground truth - faiss_training_vectors_path_for_laet_train: data/sift/sift_learn.fvecs # FAISS training vectors for LAET training - # if LAET generated features for a *list* of thresholds. - # E.g., if LAET's script had pred_thresh = [1,5,10] and this model - # is for the `thresh1` features, then feature_idx_for_model is 0. - # If LAET script used a single threshold value that matches - # `pred_thresh_for_model_features`, this is 0. - # Optional: - # multiplier_range: [0.1, 5.0] # Range for binary searching the nprobe multiplier - # num_binary_search_steps: 10 # Iterations for multiplier binary search - -# -# data_paths_for_laet_training = { -# "base_vectors": laet_main_cfg.get("base_vectors_path_for_laet_train", f"data/{dataset_name}_base.fvecs"), -# "train_query_vectors": laet_main_cfg.get("train_query_vectors_path_for_laet_train", f"data/{dataset_name}_learn.fvecs"), -# "gt_train": laet_main_cfg.get("gt_train_path_for_laet_train", f"data/{dataset_name}_learn_groundtruth.ivecs"), -# "gt_format": laet_main_cfg.get("gt_format_for_laet_train", "ivecs"), -# "training_vectors_for_faiss_index": laet_main_cfg.get("faiss_training_vectors_path_for_laet_train", f"data/{dataset_name}_learn.fvecs") -#} \ No newline at end of file + faiss_training_vectors_path_for_laet_train: data/sift/sift_learn.fvecs # FAISS training vectors for LAET training \ No newline at end of file diff --git a/test/experiments/osdi2025/experiment_runner.py b/test/experiments/osdi2025/experiment_runner.py index e26da3a7..49cd5d2e 100644 --- a/test/experiments/osdi2025/experiment_runner.py +++ b/test/experiments/osdi2025/experiment_runner.py @@ -10,13 +10,15 @@ from test.experiments.osdi2025.numa_multi_query.run import run_experiment as run_numa_multi from test.experiments.osdi2025.aps_recall_targets.run import run_experiment as run_aps_recall from test.experiments.osdi2025.early_termination.run import run_experiment as run_early_termination +from test.experiments.osdi2025.multi_level.run import run_experiment as run_multi_level EXPERIMENTS = { "kick_the_tires": run_kick_the_tires, "numa_single_query": run_numa_single, "numa_multi_query": run_numa_multi, "aps_recall_targets": run_aps_recall, - "early_termination": run_early_termination + "early_termination": run_early_termination, + "multi_level": run_multi_level, } def main(): diff --git a/test/experiments/osdi2025/multi_level/configs/msturing10m.yaml b/test/experiments/osdi2025/multi_level/configs/msturing10m.yaml new file mode 100644 index 00000000..86997475 --- /dev/null +++ b/test/experiments/osdi2025/multi_level/configs/msturing10m.yaml @@ -0,0 +1,136 @@ +# ─── top-level controls ─────────────────────────────────────────────────────── +mode: run # build | run | plot +overwrite: + index: false # force rebuild of every index + results: true # force rerun of every search + +# ─── dataset ────────────────────────────────────────────────────────────────── +dataset: + name: msturing10m # built-in quake dataset + metric: l2 + path: data # ignored for packaged datasets + nq: 100 # number of queries to use + +# ─── indexes / workloads ────────────────────────────────────────────────────── +indexes: + - name: Quake5000 + index: Quake + build_params: + nc: 5000 + num_workers: 1 + search_params: + k: 100 +# recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] + initial_search_fraction: 0.3 +# batched_scan: true + batch_size: 1 + + - name: Quake10000 + index: Quake + build_params: + nc: 10000 + num_workers: 1 + search_params: + k: 100 +# recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] + initial_search_fraction: 0.25 +# batched_scan: true + batch_size: 1 + + - name: Quake20000 + index: Quake + build_params: + nc: 20000 + num_workers: 0 + search_params: + k: 1 +# recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] + initial_search_fraction: 0.2 +# batched_scan: true + batch_size: 1 + + - name: Quake40000 + index: Quake + build_params: + nc: 40000 + num_workers: 0 + search_params: + k: 1 + # recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] + initial_search_fraction: 0.2 + # batched_scan: true + batch_size: 1 + + - name: Quake80000 + index: Quake + build_params: + nc: 80000 + num_workers: 0 + search_params: + k: 1 + # recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] + initial_search_fraction: 0.2 + # batched_scan: true + batch_size: 1 + + - name: Quake160000 + index: Quake + build_params: + nc: 160000 + num_workers: 0 + search_params: + k: 1 + # recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] + initial_search_fraction: 0.2 + # batched_scan: true + batch_size: 1 +# +# - name: Quake20000_500 # two-level Quake index +# index: Quake +# build_params: +# nc: 20000 +# num_workers: 0 +# parent: +# nc: 500 +# num_workers: 0 +# search_params: +# k: 1 +# nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] +## initial_search_fraction: 0.05 +# batch_size: 1 +# parent: +# nprobe: 50 +# # child-internal search; leave single high target here +## recall_target: 0.999 +## initial_search_fraction: 0.2 + +# ─── plotting ──────────────────────────────────────────────────────────────── +plot: + styles: # one entry per *name* above + Quake5000: + color: "#1f77b4" + marker: "o" + Quake10000: + color: "#ff7f0e" + marker: "o" + Quake20000: + color: "#2ca02c" + marker: "o" + Quake40000: + color: "#9467bd" + marker: "o" + Quake80000: + color: "#8c564b" + marker: "o" + Quake160000: + color: "#e377c2" + marker: "o" + Quake20000_500: + color: "#d62728" + marker: "o" \ No newline at end of file diff --git a/test/experiments/osdi2025/multi_level/run.py b/test/experiments/osdi2025/multi_level/run.py index 139597f9..c3f3c21f 100644 --- a/test/experiments/osdi2025/multi_level/run.py +++ b/test/experiments/osdi2025/multi_level/run.py @@ -1,2 +1,252 @@ +from __future__ import annotations +import argparse +import logging +import time +from pathlib import Path +from typing import Dict, List, Tuple + +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import torch +import yaml + +# ── quake imports ────────────────────────────────────────────────────────────── +from quake.datasets.ann_datasets import load_dataset +from quake.index_wrappers.faiss_ivf import FaissIVF +from quake.index_wrappers.quake import QuakeWrapper +from quake.utils import compute_recall # recall@k + +logger = logging.getLogger("experiment") +logging.basicConfig( + format="%(asctime)s | %(levelname)s | %(message)s", + datefmt="%H:%M:%S", + level=logging.INFO, +) + +# ─────────────────────────────────────────────────────────────────────────────── +# helpers +# ─────────────────────────────────────────────────────────────────────────────── +def _prepare_index( + idx_cls, + vecs: torch.Tensor, + metric: str, + build_params: Dict, + index_path: Path, + rebuild: bool, +) -> Tuple[object, float]: + """ + Build–or–load an index and return (index, build_time_seconds). + build_time_seconds == 0 when loaded. + """ + idx = idx_cls() + if index_path.exists() and not rebuild: + t0 = time.time() + idx.load(str(index_path), num_workers=build_params["num_workers"]) + return idx, 0.0 + + logger.info("Building index → %s …", index_path) + t0 = time.time() + idx.build(vecs, metric=metric, **build_params) + t_build = time.time() - t0 + idx.save(str(index_path)) + logger.info("Index saved (%.1fs).", t_build) + return idx, t_build + + +def _dist_ids(res): + """Handle `(D, I)` tuples OR Quake SearchResult objects.""" + if isinstance(res, tuple) and len(res) == 2: + return res + if hasattr(res, "distances") and hasattr(res, "indices"): + return res.distances, res.indices + raise TypeError(f"Unknown search result type: {type(res).__name__}") + + +def _benchmark_index( + idx, + queries: torch.Tensor, + ground: np.ndarray, + search_params: Dict, + trials: int, + warmup: int, +) -> Dict: + bs = search_params.pop("batch_size", None) + k = search_params["k"] + + # warm-up + for _ in range(warmup): + if bs is None: + idx.search(queries, **search_params) + else: + for i in range(0, len(queries), bs): + idx.search(queries[i : i + bs], **search_params) + + qps_vals: List[float] = [] + lat_ms: List[float] = [] + + for _ in range(trials): + t0 = time.time() + if bs is None: + res = idx.search(queries, **search_params) + D, I = res.distances, res.ids + else: + all_I, all_D = [], [] + for i in range(0, len(queries), bs): + res = idx.search(queries[i : i + bs], **search_params) + D_, I_ = res.distances, res.ids + all_I.append(I_); all_D.append(D_) + I = np.concatenate(all_I); D = np.concatenate(all_D) + dt = time.time() - t0 + qps_vals.append(len(queries) / dt) + lat_ms.append(dt * 1e3) + + recall = compute_recall(I, ground[:, :k], k) + recall = 0.0 if recall is None else recall.mean().item() + + return dict( + recall = float(recall), + qps_mean = float(np.mean(qps_vals)), + qps_std = float(np.std(qps_vals)), + latency_mean_ms = float(np.mean(lat_ms)), + trials = trials, + warmup = warmup, + batch_size = bs or len(queries), + ) + + +def _expand_targets(sp: Dict) -> List[Dict]: + """ + Produce one search-parameter dict per recall_target value. + + If `recall_targets` is absent (or a single float) we fall back to a list + containing exactly one dict, preserving the original behaviour. + """ + if "recall_targets" in sp: + tgs = sp.pop("recall_targets") + if not isinstance(tgs, (list, tuple)): + tgs = [tgs] + return [{**sp, "recall_target": t} for t in tgs] + elif "nprobes" in sp: + tgs = sp.pop("nprobes") + if not isinstance(tgs, (list, tuple)): + tgs = [tgs] + return [{**sp, "nprobe": t} for t in tgs] + else: + return [sp] + + +def _plot_unified(cfg: Dict, root: Path) -> None: + styles = cfg["plot"]["styles"] + fig, ax = plt.subplots(figsize=(6, 4)) + + for icfg in cfg["indexes"]: + name = icfg["name"] + csv = root / name / "results.csv" + if not csv.exists(): + logger.warning("No results for %s – skipped in plot.", name) + continue + + df = pd.read_csv(csv).sort_values("recall") + sty = styles.get(name, {}) + ax.plot( + df["qps_mean"], df["recall"], + label = name, + marker = sty.get("marker", "o"), + linestyle = sty.get("linestyle", "-"), + linewidth = 1.4, + markersize= 6, + color = sty.get("color", None), + ) + + ax.set_xscale("log", base=10) + ax.set_xlabel("Queries per second (log)") + ax.set_ylabel("Recall@k") + ax.set_title("Recall curves over varied recall_target") + ax.grid(True, which="both", ls=":") + ax.legend() + fig.tight_layout() + out_png = root / "recall_vs_qps.png" + fig.savefig(out_png, dpi=180) + logger.info("Plot written to %s", out_png) + + +# ─────────────────────────────────────────────────────────────────────────────── +# main +# ─────────────────────────────────────────────────────────────────────────────── +def run_experiment(cfg_path: str, output_dir: str) -> None: + cfg = yaml.safe_load(Path(cfg_path).read_text()) + out = Path(output_dir); out.mkdir(parents=True, exist_ok=True) + + mode = cfg.get("mode", "run") # build | run | plot + overwrite = cfg.get("overwrite", {}) + rebuild_index = bool(overwrite.get("index", False)) + rewrite_csv = bool(overwrite.get("results", False)) + + # dataset ------------------------------------------------------------------ + ds = cfg["dataset"] + logger.info("Loading dataset %s …", ds["name"]) + vecs, queries, ground = load_dataset(ds["name"], ds.get("path", "")) + metric = ds["metric"] + nq = ds["nq"] + ground = ground[:nq] + queries = queries[:nq] + + idx_map = {"Quake": QuakeWrapper, "IVF": FaissIVF} + + # build / run -------------------------------------------------------------- + if mode in {"build", "run"}: + for icfg in cfg["indexes"]: + name = icfg["name"] + res_dir = out / name; res_dir.mkdir(exist_ok=True, parents=True) + idx_bin = res_dir / "index.bin" + csv_file = res_dir / "results.csv" + idx_cls = idx_map[icfg["index"]] + + # BUILD once ======================================================= + idx, build_t = _prepare_index( + idx_cls, vecs, metric, icfg["build_params"], idx_bin, rebuild_index + ) + if mode == "build": + continue # build-only mode stops here + + # RUN for every recall_target ====================================== + if csv_file.exists() and not rewrite_csv: + existing_df = pd.read_csv(csv_file) + else: + existing_df = pd.DataFrame() + + for sp in _expand_targets(icfg["search_params"].copy()): + tgt = sp.get("recall_target", None) + if tgt is None: + tgt = sp.get("nprobe") + # if ( + # not rewrite_csv + # and "recall_target" in existing_df.columns + # and ((existing_df.recall_target - tgt).abs() < 1e-9).any() + # ): + # logger.info("[%s] target %.3g cached – skipping run.", name, tgt) + # continue + + stats = _benchmark_index( + idx = idx, + queries = queries, + ground = ground, + search_params = sp, + trials = cfg.get("trials", 5), + warmup = cfg.get("warmup", 1), + ) + stats.update(build_time_s = build_t, recall_target = tgt) + existing_df = pd.concat( + [existing_df, pd.DataFrame([stats])], ignore_index=True + ) + logger.info("[%s] target %.3g done.", name, tgt) + + existing_df.to_csv(csv_file, index=False) + logger.info("[%s] results written to %s", name, csv_file) + + # plot --------------------------------------------------------------------- + if mode in {"run", "plot"}: + _plot_unified(cfg, out) From 4f4e5aafd06957fb6750c2f37755c5190da33e16 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 10 May 2025 22:40:34 -0500 Subject: [PATCH 026/323] add vary level experiment --- .../configs/msturing10m_levels.yaml | 65 ++++++ test/experiments/osdi2025/vary_levels/run.py | 216 ++++++++++++++++++ 2 files changed, 281 insertions(+) create mode 100644 test/experiments/osdi2025/vary_levels/configs/msturing10m_levels.yaml create mode 100644 test/experiments/osdi2025/vary_levels/run.py diff --git a/test/experiments/osdi2025/vary_levels/configs/msturing10m_levels.yaml b/test/experiments/osdi2025/vary_levels/configs/msturing10m_levels.yaml new file mode 100644 index 00000000..b2aa5052 --- /dev/null +++ b/test/experiments/osdi2025/vary_levels/configs/msturing10m_levels.yaml @@ -0,0 +1,65 @@ +# ─── top-level controls ─────────────────────────────────── +mode: run # ignored by new script – kept for compatibility +overwrite: + index: false + results: true + +# ─── dataset ─────────────────────────────────────────────── +dataset: + name: msturing10m + metric: l2 + path: data + nq: 100 + +# ─── base index (built once) ─────────────────────────────── +index: + type: Quake + build_params: + nc: 20_000 # child level + num_workers: 1 + search_params: + k: 100 + +# ─── parent levels to test ───────────────────────────────── +levels: + - nc: 0 + search_params: + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] + - nc: 100 # baseline (keep the index single-level) + search_params: # ← optional override for the CHILD search + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] + parent_search_params: # ← optional params passed to *parent* search + nprobe: 10 + + - nc: 500 # 500-centroid parent layer + search_params: + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] + parent_search_params: # ← optional params passed to *parent* search + nprobe: 50 + + - nc: 1_000 + search_params: + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] + parent_search_params: # ← optional params passed to *parent* search + nprobe: 100 + + - nc: 2_000 + search_params: + nprobes: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] + parent_search_params: # ← optional params passed to *parent* search + nprobe: 200 + + - nc: 4_000 + search_params: + nprobes: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] + parent_search_params: # ← optional params passed to *parent* search + nprobe: 400 + +# ─── plotting (optional) ────────────────────────────────── +plot: + styles: + L0: {color: "#1f77b4"} + L100: {color: "#ff7f0e"} + L500: {color: "#ffbb78"} + L1000: {color: "#2ca02c"} + L2000: {color: "#d62728"} \ No newline at end of file diff --git a/test/experiments/osdi2025/vary_levels/run.py b/test/experiments/osdi2025/vary_levels/run.py new file mode 100644 index 00000000..f9755a7b --- /dev/null +++ b/test/experiments/osdi2025/vary_levels/run.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python3 +""" +experiment_levels.py – benchmark a single Quake/IVF index with optional +parent levels, each level having its own search parameters. + +* Build the **child** index once (saved as base_index.bin). +* For every level described in `levels:`: + – Reload the base index from disk. + – Optionally add a parent layer with `nc` centroids. + – Run searches using the per-level overrides. +* Results for each level go to ./OUT_DIR/L/results.csv +* A combined QPS-vs-Recall plot is written to OUT_DIR/recall_vs_qps.png +""" + +from __future__ import annotations +import argparse, logging, time +from pathlib import Path +from typing import Dict, List, Tuple + +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import quake +import torch, yaml + +from quake.datasets.ann_datasets import load_dataset +from quake.index_wrappers.faiss_ivf import FaissIVF +from quake.index_wrappers.quake import QuakeWrapper +from quake.utils import compute_recall + +logger = logging.getLogger("experiment") +logging.basicConfig( + format="%(asctime)s | %(levelname)s | %(message)s", + datefmt="%H:%M:%S", + level=logging.INFO, +) + +# ───────────────────── helper routines ───────────────────── +def _prepare_index(idx_cls, vecs, metric, build_params, + path: Path, rebuild: bool) -> Tuple[object, float]: + """Build or load the *child* index; return (index, build_time_s).""" + idx = idx_cls() + if path.exists() and not rebuild: + t0 = time.time() + idx.load(str(path), num_workers=build_params["num_workers"]) + return idx, 0.0 + logger.info("Building index → %s …", path) + t0 = time.time() + idx.build(vecs, metric=metric, **build_params) + t_build = time.time() - t0 + idx.save(str(path)) + logger.info("Index saved (%.1fs).", t_build) + return idx, t_build + + +def _benchmark_index(idx, queries, ground, search_params, + trials: int, warmup: int) -> Dict: + """Run `trials` timed searches; return stats dict.""" + sp = search_params.copy() # don’t modify caller’s dict + bs = sp.pop("batch_size", None) + k = sp["k"] + + # warm-up + for _ in range(warmup): + if bs is None: + idx.search(queries, **sp) + else: + for i in range(0, len(queries), bs): + idx.search(queries[i:i+bs], **sp) + + qps, lat_ms = [], [] + for _ in range(trials): + t0 = time.time() + if bs is None: + I = idx.search(queries, **sp).ids + else: + I = np.concatenate([ + idx.search(queries[i:i+bs], **sp).ids + for i in range(0, len(queries), bs) + ]) + dt = time.time() - t0 + qps.append(len(queries) / dt) + lat_ms.append(dt * 1e3) + + recall = compute_recall(I, ground[:, :k], k) + recall = 0.0 if recall is None else recall.mean().item() + + return dict( + recall = float(recall), + qps_mean = float(np.mean(qps)), + qps_std = float(np.std(qps)), + latency_ms = float(np.mean(lat_ms)), + trials = trials, + warmup = warmup, + batch_size = bs or len(queries), + ) + + +def _expand_targets(sp: Dict) -> List[Dict]: + """Yield one search-param dict per recall_target OR per nprobe value.""" + if "recall_targets" in sp: + tgs = sp.pop("recall_targets") + if not isinstance(tgs, (list, tuple)): tgs = [tgs] + return [{**sp, "recall_target": t} for t in tgs] + if "nprobes" in sp: + tgs = sp.pop("nprobes") + if not isinstance(tgs, (list, tuple)): tgs = [tgs] + return [{**sp, "nprobe": t} for t in tgs] + return [sp] + + +def _plot(cfg: Dict, root: Path) -> None: + """Generate combined QPS-vs-Recall plot.""" + fig, ax = plt.subplots(figsize=(6, 4)) + styles = cfg.get("plot", {}).get("styles", {}) + for lv in cfg["levels"]: + nc = lv["nc"] + name = f"L{nc}" + csv = root / name / "results.csv" + if not csv.exists(): + logger.warning("No results for level %s – skipped.", nc) + continue + df = pd.read_csv(csv).sort_values("recall") + sty = styles.get(name, {}) + ax.plot( + df["qps_mean"], df["recall"], + label = f"{nc:,} centroids" if nc else "single-level", + marker = sty.get("marker", "o"), + linestyle = sty.get("linestyle", "-"), + linewidth = 1.4, + markersize = 6, + color = sty.get("color", None), + ) + ax.set_xscale("log", base=10) + ax.set_xlabel("Queries per second (log)") + ax.set_ylabel("Recall@k") + ax.set_title("QPS vs Recall for different parent levels") + ax.grid(True, which="both", ls=":") + ax.legend() + fig.tight_layout() + fig.savefig(root / "recall_vs_qps.png", dpi=180) + logger.info("Plot written to %s", root / "recall_vs_qps.png") + +# ─────────────────────────── main ────────────────────────── +def run_experiment(cfg_path: str, output_dir: str) -> None: + cfg = yaml.safe_load(Path(cfg_path).read_text()) + out = Path(output_dir) + out.mkdir(parents=True, exist_ok=True) + + # dataset --------------------------------------------------------------- + ds = cfg["dataset"] + logger.info("Loading dataset %s …", ds["name"]) + vecs, queries, ground = load_dataset(ds["name"], ds.get("path", "")) + nq = ds["nq"] + queries, ground = queries[:nq], ground[:nq] + metric = ds["metric"] + + # build child index once ----------------------------------------------- + icfg = cfg["index"] + idx_cls = {"Quake": QuakeWrapper, "IVF": FaissIVF}[icfg["type"]] + base_bin = out / "base_index.bin" + base_idx, build_t = _prepare_index( + idx_cls, vecs, metric, + icfg["build_params"], + base_bin, + rebuild=cfg["overwrite"].get("index", False), + ) + + # iterate over parent levels ------------------------------------------- + for lv in cfg["levels"]: + nc = lv["nc"] + name = f"L{nc}" + res_dir = out / name + res_dir.mkdir(parents=True, exist_ok=True) + csv_file = res_dir / "results.csv" + + if csv_file.exists() and not cfg["overwrite"].get("results", False): + logger.info("[%s] results cached – skipping.", name) + continue + + # fresh load of the base index for this level + idx = idx_cls() + idx.load(str(base_bin), num_workers=icfg["build_params"].get("num_workers", 1)) + if nc: # add parent layer when nc > 0 + build_params = quake.IndexBuildParams() + build_params.nlist = nc + idx.index.add_level(build_params) + + # child search params (base defaults + per-level overrides) + child_sp = icfg["search_params"].copy() + child_sp.update(lv.get("search_params", {})) + + # optional parent search params + parent_sp = lv.get("parent_search_params", None) + + df = pd.DataFrame() + for sp in _expand_targets(child_sp.copy()): + if parent_sp: # attach parent section if any + sp["parent"] = parent_sp + stats = _benchmark_index( + idx, queries, ground, sp, + trials = cfg.get("trials", 5), + warmup = cfg.get("warmup", 1), + ) + stats.update( + build_time_s = build_t if nc == 0 else 0.0, + parent_nc = nc, + recall_target= sp.get("recall_target", sp.get("nprobe", np.nan)), + ) + df = pd.concat([df, pd.DataFrame([stats])], ignore_index=True) + logger.info("[%s] target %.3g done.", name, stats["recall_target"]) + + df.to_csv(csv_file, index=False) + logger.info("[%s] results written to %s", name, csv_file) + + _plot(cfg, out) From 713512d416d8d046712e5591dff632e21cf5e599 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 10 May 2025 22:43:07 -0500 Subject: [PATCH 027/323] update runner --- test/experiments/osdi2025/experiment_runner.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/experiments/osdi2025/experiment_runner.py b/test/experiments/osdi2025/experiment_runner.py index 49cd5d2e..233dd314 100644 --- a/test/experiments/osdi2025/experiment_runner.py +++ b/test/experiments/osdi2025/experiment_runner.py @@ -11,6 +11,7 @@ from test.experiments.osdi2025.aps_recall_targets.run import run_experiment as run_aps_recall from test.experiments.osdi2025.early_termination.run import run_experiment as run_early_termination from test.experiments.osdi2025.multi_level.run import run_experiment as run_multi_level +from test.experiments.osdi2025.vary_levels.run import run_experiment as run_vary_levels EXPERIMENTS = { "kick_the_tires": run_kick_the_tires, @@ -19,6 +20,7 @@ "aps_recall_targets": run_aps_recall, "early_termination": run_early_termination, "multi_level": run_multi_level, + "vary_levels": run_vary_levels, } def main(): From 96cae75ee7daa2ecd20620e211a4085b03400eee Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 10 May 2025 22:57:46 -0500 Subject: [PATCH 028/323] update runner --- .../vary_levels/configs/msturing10m_levels.yaml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/test/experiments/osdi2025/vary_levels/configs/msturing10m_levels.yaml b/test/experiments/osdi2025/vary_levels/configs/msturing10m_levels.yaml index b2aa5052..7c53be47 100644 --- a/test/experiments/osdi2025/vary_levels/configs/msturing10m_levels.yaml +++ b/test/experiments/osdi2025/vary_levels/configs/msturing10m_levels.yaml @@ -25,35 +25,41 @@ levels: - nc: 0 search_params: nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] + batch_size: 1 - nc: 100 # baseline (keep the index single-level) search_params: # ← optional override for the CHILD search - nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] + batch_size: 1 parent_search_params: # ← optional params passed to *parent* search nprobe: 10 - nc: 500 # 500-centroid parent layer search_params: nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] + batch_size: 1 parent_search_params: # ← optional params passed to *parent* search nprobe: 50 - nc: 1_000 search_params: nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] + batch_size: 1 parent_search_params: # ← optional params passed to *parent* search - nprobe: 100 + nprobe: 75 - nc: 2_000 search_params: nprobes: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] + batch_size: 1 parent_search_params: # ← optional params passed to *parent* search - nprobe: 200 + nprobe: 150 - nc: 4_000 search_params: nprobes: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] + batch_size: 1 parent_search_params: # ← optional params passed to *parent* search - nprobe: 400 + nprobe: 200 # ─── plotting (optional) ────────────────────────────────── plot: From d9fcbfb9849890b4045b167240b8282bdcb4d9b6 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 10 May 2025 23:10:39 -0500 Subject: [PATCH 029/323] update runner --- .../configs/msturing10m_levels.yaml | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/test/experiments/osdi2025/vary_levels/configs/msturing10m_levels.yaml b/test/experiments/osdi2025/vary_levels/configs/msturing10m_levels.yaml index 7c53be47..2cc895ce 100644 --- a/test/experiments/osdi2025/vary_levels/configs/msturing10m_levels.yaml +++ b/test/experiments/osdi2025/vary_levels/configs/msturing10m_levels.yaml @@ -15,51 +15,51 @@ dataset: index: type: Quake build_params: - nc: 20_000 # child level + nc: 160_000 # child level num_workers: 1 search_params: - k: 100 + k: 1 # ─── parent levels to test ───────────────────────────────── levels: - nc: 0 search_params: - nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096] batch_size: 1 - nc: 100 # baseline (keep the index single-level) search_params: # ← optional override for the CHILD search - nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096] batch_size: 1 parent_search_params: # ← optional params passed to *parent* search nprobe: 10 - nc: 500 # 500-centroid parent layer search_params: - nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096] batch_size: 1 parent_search_params: # ← optional params passed to *parent* search nprobe: 50 - nc: 1_000 search_params: - nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096] batch_size: 1 parent_search_params: # ← optional params passed to *parent* search - nprobe: 75 + nprobe: 100 - nc: 2_000 search_params: - nprobes: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] + nprobes: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096] batch_size: 1 parent_search_params: # ← optional params passed to *parent* search - nprobe: 150 + nprobe: 200 - nc: 4_000 search_params: - nprobes: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048] + nprobes: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096] batch_size: 1 parent_search_params: # ← optional params passed to *parent* search - nprobe: 200 + nprobe: 400 # ─── plotting (optional) ────────────────────────────────── plot: From f1058e07d0459754bcd0dc9164a869690ee7241b Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 11 May 2025 16:03:05 -0500 Subject: [PATCH 030/323] add gpu params to build --- src/cpp/bindings/wrap.cpp | 11 +++++++++++ src/python/index_wrappers/quake.py | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/src/cpp/bindings/wrap.cpp b/src/cpp/bindings/wrap.cpp index 8035e240..d476d8d1 100644 --- a/src/cpp/bindings/wrap.cpp +++ b/src/cpp/bindings/wrap.cpp @@ -131,6 +131,10 @@ PYBIND11_MODULE(_bindings, m) { return oss.str(); }); + // bool use_gpu = false; + // int gpu_batch_size = DEFAULT_GPU_BATCH_SIZE; + // int gpu_sample_size = DEFAULT_GPU_SAMPLE_SIZE; + /*********** IndexBuildParams Binding ***********/ class_>(m, "IndexBuildParams") .def(init<>()) @@ -144,6 +148,13 @@ PYBIND11_MODULE(_bindings, m) { (std::string("Number of workers. default = ") + std::to_string(DEFAULT_NUM_WORKERS)).c_str()) .def_readwrite("parent_params", &IndexBuildParams::parent_params, "Parameters for the parent index, if any.") + .def_readwrite("use_gpu", &IndexBuildParams::use_gpu, + (std::string("Flag to use GPU for index building. default = ") + std::to_string(false)).c_str()) + .def_readwrite("gpu_batch_size", &IndexBuildParams::gpu_batch_size, + (std::string("Batch size for GPU index building. default = ") + std::to_string(DEFAULT_GPU_BATCH_SIZE)).c_str()) + .def_readwrite("gpu_sample_size", &IndexBuildParams::gpu_sample_size, + (std::string("Sample size for GPU index building. default = ") + std::to_string(DEFAULT_GPU_SAMPLE_SIZE)).c_str()) + .def("__repr__", [](const IndexBuildParams &p) { std::ostringstream oss; oss << "{"; diff --git a/src/python/index_wrappers/quake.py b/src/python/index_wrappers/quake.py index a75f2f86..c7e9e19b 100644 --- a/src/python/index_wrappers/quake.py +++ b/src/python/index_wrappers/quake.py @@ -68,6 +68,9 @@ def build( m: int = -1, code_size: int = 8, parent=None, + use_gpu=False, + gpu_batch_size=100000, + gpu_sample_size=1000000 ): """ Build the index with the given vectors and arguments. @@ -95,6 +98,10 @@ def build( build_params.parent_params = quake.IndexBuildParams() build_params.parent_params.nlist = parent.get("nc", 1) + build_params.use_gpu = use_gpu + build_params.gpu_batch_size = gpu_batch_size + build_params.gpu_sample_size = gpu_sample_size + self.index = QuakeIndex() if ids is None: From e52ac0ebaa0806bd32f1051a5e924cbf2736a22b Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 13 May 2025 23:47:59 -0500 Subject: [PATCH 031/323] update multi-level --- src/cpp/bindings/wrap.cpp | 2 + src/cpp/include/common.h | 3 + src/cpp/include/dynamic_inverted_list.h | 1 + src/cpp/include/geometry.h | 16 +- src/cpp/src/clustering.cpp | 200 ++++----- src/cpp/src/dynamic_inverted_list.cpp | 4 +- src/cpp/src/maintenance_policies.cpp | 193 ++++---- src/cpp/src/partition_manager.cpp | 9 +- src/cpp/src/query_coordinator.cpp | 23 +- src/python/datasets/ann_datasets.py | 44 +- src/python/workload_generator.py | 415 +++++++++--------- test/cpp/benchmark.cpp | 56 ++- test/experiments/osdi2025/ablation/run.py | 2 - .../experiments/osdi2025/experiment_runner.py | 2 + .../osdi2025/maintenance_ablation/run.py | 304 +++++++++++++ .../{msturing10m.yaml => sift10m.yaml} | 44 +- test/experiments/osdi2025/multi_level/run.py | 2 +- .../configs/msturing10m_levels.yaml | 71 --- .../osdi2025/vary_levels/configs/sift10m.yaml | 101 +++++ test/experiments/osdi2025/vary_levels/run.py | 2 +- 20 files changed, 948 insertions(+), 546 deletions(-) delete mode 100644 test/experiments/osdi2025/ablation/run.py create mode 100644 test/experiments/osdi2025/maintenance_ablation/run.py rename test/experiments/osdi2025/multi_level/configs/{msturing10m.yaml => sift10m.yaml} (82%) delete mode 100644 test/experiments/osdi2025/vary_levels/configs/msturing10m_levels.yaml create mode 100644 test/experiments/osdi2025/vary_levels/configs/sift10m.yaml diff --git a/src/cpp/bindings/wrap.cpp b/src/cpp/bindings/wrap.cpp index d476d8d1..18a6f92d 100644 --- a/src/cpp/bindings/wrap.cpp +++ b/src/cpp/bindings/wrap.cpp @@ -232,6 +232,8 @@ PYBIND11_MODULE(_bindings, m) { (std::string("Number of refinement iterations. default = ") + std::to_string(DEFAULT_REFINEMENT_ITERATIONS)).c_str()) .def_readwrite("min_partition_size", &MaintenancePolicyParams::min_partition_size, (std::string("Minimum allowed partition size. default = ") + std::to_string(DEFAULT_MIN_PARTITION_SIZE)).c_str()) + .def_readwrite("max_partition_size", &MaintenancePolicyParams::max_partition_size, + (std::string("Maximum allowed partition size. default = ") + std::to_string(-1)).c_str()) .def_readwrite("alpha", &MaintenancePolicyParams::alpha, (std::string("Alpha parameter. default = ") + std::to_string(DEFAULT_ALPHA)).c_str()) .def_readwrite("enable_split_rejection", &MaintenancePolicyParams::enable_split_rejection, diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index 1c9da4bc..3fb6e0f5 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -108,6 +108,9 @@ struct MaintenancePolicyParams { float delete_threshold_ns = DEFAULT_DELETE_THRESHOLD_NS; float split_threshold_ns = DEFAULT_SPLIT_THRESHOLD_NS; + // SPFresh Param + int max_partition_size = -1; // -1 means default to standard cost-based maintenance, if set then we use size-based thresholding + MaintenancePolicyParams() = default; }; diff --git a/src/cpp/include/dynamic_inverted_list.h b/src/cpp/include/dynamic_inverted_list.h index e8d67627..4c1c4933 100644 --- a/src/cpp/include/dynamic_inverted_list.h +++ b/src/cpp/include/dynamic_inverted_list.h @@ -32,6 +32,7 @@ namespace faiss { int code_size_; ///< Size in bytes of each vector code. unordered_map> partitions_; ///< Map of partition ID to IndexPartition. unordered_map> id_to_location_; + unordered_map tombstones_; /** * @brief Constructor for DynamicInvertedLists. diff --git a/src/cpp/include/geometry.h b/src/cpp/include/geometry.h index c27ca997..5e54890e 100644 --- a/src/cpp/include/geometry.h +++ b/src/cpp/include/geometry.h @@ -285,14 +285,14 @@ compute_recall_profile(const std::vector& boundary_distances, // Ensure P_prime is non-negative for (int k = 1; k < m; ++k) P_prime[k] = std::max(0.0f, P_prime[k]); - // if the cluster_sizes are given, scale P_prime[k] by the size of the cluster. this is a rudimentary density estimation - if (partition_sizes.size() > 0) { - for (int k = 1; k < m; ++k) { - if (partition_sizes[k] > 0) { - P_prime[k] *= static_cast(partition_sizes[k]); - } - } - } + // // if the cluster_sizes are given, scale P_prime[k] by the size of the cluster. this is a rudimentary density estimation + // if (partition_sizes.size() > 0) { + // for (int k = 1; k < m; ++k) { + // if (partition_sizes[k] > 0) { + // P_prime[k] *= static_cast(partition_sizes[k]); + // } + // } + // } // normalize probs diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index b05c7d83..a0e907be 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -18,41 +18,38 @@ shared_ptr kmeans_cuvs_sample_and_predict( Tensor vectors, Tensor ids, - shared_ptr build_params) { - - int num_clusters = build_params->nlist; - int niter = build_params->niter; - int gpu_batch_size = build_params->gpu_batch_size; - int gpu_sample_size = build_params->gpu_sample_size; - MetricType metric = str_to_metric_type(build_params->metric); - + shared_ptr build_params) +{ + /* ---------- unpack / sanity-check parameters ----------------------- */ + const int num_clusters = build_params->nlist; + const int niter = build_params->niter; + int gpu_batch_size = build_params->gpu_batch_size; + int gpu_sample_sz = build_params->gpu_sample_size; + const MetricType metric = str_to_metric_type(build_params->metric); TORCH_CHECK(vectors.dim() == 2, "vectors must be [N,D]"); - TORCH_CHECK(ids.dim() == 1, "ids must be [N]"); - int64_t N = vectors.size(0), D = vectors.size(1); + TORCH_CHECK(ids.dim() == 1, "ids must be [N]"); - gpu_sample_size = std::min(gpu_sample_size, (int) N); - gpu_batch_size = std::min(gpu_batch_size, (int) N); + const int64_t N = vectors.size(0); + const int64_t D = vectors.size(1); - TORCH_CHECK(gpu_sample_size > 0 && gpu_sample_size <= N, - "invalid sample_size"); + gpu_sample_sz = std::min(gpu_sample_sz, (int)N); + gpu_batch_size = std::min(gpu_batch_size, (int)N); + TORCH_CHECK(gpu_sample_sz > 0 && gpu_sample_sz <= N, "invalid sample size"); - // 1) pin + normalize if needed + /* ---------- copy to pinned host & (optionally) normalize ----------- */ Tensor cpu_pts = vectors.contiguous().pin_memory(); if (metric == faiss::METRIC_INNER_PRODUCT) { - auto norms = cpu_pts.norm(2, 1, true); - cpu_pts = cpu_pts.div(norms); + // k-means in RAFT is L2 – approximate cosine by L2 on the unit sphere + cpu_pts = cpu_pts.div(cpu_pts.norm(2, 1, /*keepdim=*/true)); } - // 2) choose a random sample of indices - auto perm = torch::randperm(N, torch::kLong); - auto samp_idx = perm.slice(0, 0, gpu_sample_size); - Tensor samp_pts = cpu_pts.index_select(0, samp_idx); + /* ---------- draw random sample for training ------------------------ */ + const Tensor samp_idx = torch::randperm(N, torch::kLong).slice(0, 0, gpu_sample_sz); + const Tensor samp_host = cpu_pts.index_select(0, samp_idx); + const Tensor samp_gpu = samp_host.to(torch::kCUDA, /*non_blocking=*/true).contiguous(); - // 3) move sample to GPU - Tensor samp_gpu = samp_pts.to(torch::kCUDA, /*non_blocking=*/true).contiguous(); - - // 4) prepare RAFT handle & cuVS params + /* ---------- RAFT handle & cuVS parameters -------------------------- */ raft::resources handle; cudaStream_t stream = c10::cuda::getCurrentCUDAStream(); raft::resource::set_cuda_stream(handle, stream); @@ -62,123 +59,78 @@ shared_ptr kmeans_cuvs_sample_and_predict( params.init = cuvs::cluster::kmeans::params::InitMethod::Random; params.max_iter = niter; - // 5) allocate centroids on GPU + /* ---------- centroids on device ------------------------------------ */ Tensor cent_gpu = torch::empty({num_clusters, D}, - torch::TensorOptions() - .dtype(torch::kFloat32) - .device(torch::kCUDA)) - .contiguous(); + torch::dtype(torch::kFloat32).device(torch::kCUDA)) + .contiguous(); - // 6) run fit on just the sample - { - // host scalars - float inertia = 0.0f; - int actual_iter= 0; - auto host_inertia = raft::make_host_scalar_view(&inertia); - auto host_iter = raft::make_host_scalar_view(&actual_iter); - - auto X_view = raft::make_device_matrix_view( - samp_gpu.data_ptr(), - (int) gpu_sample_size, (int)D); - auto C_view = raft::make_device_matrix_view( - cent_gpu.data_ptr(), - num_clusters, (int)D); + /* ---------- fit on the sample -------------------------------------- */ + float inertia = 0.0f; + int actual_iter = 0; cuvs::cluster::kmeans::fit( - handle, params, - X_view, - std::nullopt, - C_view, - host_inertia, - host_iter + handle, params, + raft::make_device_matrix_view(samp_gpu.data_ptr(), + gpu_sample_sz, (int)D), + std::nullopt, + raft::make_device_matrix_view(cent_gpu.data_ptr(), + num_clusters, (int)D), + raft::make_host_scalar_view(&inertia), + raft::make_host_scalar_view(&actual_iter) ); - } - Tensor all_labels = torch::empty({N}, torch::kLong); - - auto predict_fn = [&](Tensor batch_cpu, int64_t off) { - int64_t bs = batch_cpu.size(0); - - // allocate exactly bs labels on the GPU - Tensor labels32 = torch::empty( - {bs}, - torch::TensorOptions() - .dtype(torch::kInt32) - .device(torch::kCUDA)); - - Tensor batch_gpu = batch_cpu.to(torch::kCUDA, /*NB=*/true) - .contiguous(); - - auto Xv = raft::make_device_matrix_view( - batch_gpu.data_ptr(), - (int)bs, (int)D); - auto Lv = raft::make_device_vector_view( - labels32.data_ptr(), (int)bs); - - float pred_inertia = 0.0f; - auto host_pred = raft::make_host_scalar_view(&pred_inertia); - - cuvs::cluster::kmeans::predict( - handle, params, - Xv, - std::nullopt, - raft::make_device_matrix_view( - cent_gpu.data_ptr(), - num_clusters, (int)D), - Lv, - false, - host_pred - ); + /* ---------- predict every point, in order, exactly once ------------ */ + Tensor all_labels = torch::empty({N}, torch::kLong); // on CPU - // now safe to copy back exactly bs elements - all_labels.narrow(0, off, bs) - .copy_( - labels32.to(torch::kLong) - .to(torch::kCPU) - ); + auto run_predict = [&](Tensor batch_host, int64_t dst_off) + { + const int64_t bs = batch_host.size(0); + + Tensor batch_gpu = batch_host.to(torch::kCUDA, /*non_blocking=*/true) + .contiguous(); + Tensor lbl_gpu32 = torch::empty({bs}, + torch::dtype(torch::kInt32).device(torch::kCUDA)); + + cuvs::cluster::kmeans::predict( + handle, params, + raft::make_device_matrix_view(batch_gpu.data_ptr(), + bs, (int)D), + std::nullopt, + raft::make_device_matrix_view(cent_gpu.data_ptr(), + num_clusters, (int)D), + raft::make_device_vector_view(lbl_gpu32.data_ptr(), bs), + /*verbosity=*/false, + raft::make_host_scalar_view(nullptr) // we don't need the inertia + ); + + all_labels.narrow(0, dst_off, bs) + .copy_(lbl_gpu32.to(torch::kLong).cpu(), /*non_blocking=*/false); }; - // predict the sample slice - predict_fn(samp_pts, /*off=*/0); - - // predict the rest for (int64_t off = 0; off < N; off += gpu_batch_size) { - int64_t bs = std::min(gpu_batch_size, N - off); - if (off < gpu_sample_size) { - if (off + bs <= gpu_sample_size) { - continue; - } else { - int64_t overlap = gpu_sample_size - off; - Tensor rest_chunk = cpu_pts.slice(0, off + overlap, off + bs); - predict_fn(rest_chunk, /*off=*/off + overlap); - continue; - } - } - Tensor rest_chunk = cpu_pts.slice(0, off, off + bs); - predict_fn(rest_chunk, /*off=*/off); + const int64_t bs = std::min(gpu_batch_size, N - off); + run_predict(cpu_pts.slice(0, off, off + bs), off); } - // 8) group on CPU - Tensor sorted_lbl, sorted_idx; - std::tie(sorted_lbl, sorted_idx) = torch::sort(all_labels); - Tensor sorted_vecs = vectors.index_select(0, sorted_idx); - Tensor sorted_ids = ids.index_select(0, sorted_idx); - - Tensor counts = torch::bincount(sorted_lbl, /*weights=*/{}, num_clusters); - auto cnt_cpu = counts.to(torch::kCPU); - std::vector split_sizes( - cnt_cpu.data_ptr(), - cnt_cpu.data_ptr() + num_clusters - ); - auto cluster_vecs = torch::split(sorted_vecs, split_sizes, 0); - auto cluster_ids = torch::split(sorted_ids, split_sizes, 0); + /* ---------- group vectors/ids by cluster on CPU -------------------- */ + Tensor lbl_sorted, idx_sorted; + std::tie(lbl_sorted, idx_sorted) = torch::sort(all_labels); + Tensor vecs_sorted = vectors.index_select(0, idx_sorted); + Tensor ids_sorted = ids.index_select(0, idx_sorted); + Tensor counts = torch::bincount(lbl_sorted, /*weights=*/{}, num_clusters); + std::vector split_sz(counts.data_ptr(), + counts.data_ptr() + num_clusters); + + std::vector cluster_vecs = torch::split(vecs_sorted, split_sz, 0); + std::vector cluster_ids = torch::split(ids_sorted, split_sz, 0); + + /* ---------- package result ---------------------------------------- */ auto out = std::make_shared(); out->centroids = cent_gpu.cpu().contiguous(); out->partition_ids = torch::arange(num_clusters, torch::kLong); out->vectors = std::move(cluster_vecs); out->vector_ids = std::move(cluster_ids); - return out; } #endif diff --git a/src/cpp/src/dynamic_inverted_list.cpp b/src/cpp/src/dynamic_inverted_list.cpp index b4573402..2e82ca97 100644 --- a/src/cpp/src/dynamic_inverted_list.cpp +++ b/src/cpp/src/dynamic_inverted_list.cpp @@ -68,7 +68,8 @@ namespace faiss { size_t DynamicInvertedLists::list_size(size_t list_no) const { auto it = partitions_.find(list_no); if (it == partitions_.end()) { - throw std::runtime_error("List does not exist in list_size"); + string err_message = "List " + std::to_string(list_no) + " does not exist in list_size"; + throw std::runtime_error(err_message); } return static_cast(it->second->num_vectors_); } @@ -278,7 +279,6 @@ void DynamicInvertedLists::batch_update_entries( void DynamicInvertedLists::remove_list(size_t list_no) { auto it = partitions_.find(list_no); if (it == partitions_.end()) { - // Already doesn't exist return; } diff --git a/src/cpp/src/maintenance_policies.cpp b/src/cpp/src/maintenance_policies.cpp index 6ad450c6..2d357e68 100644 --- a/src/cpp/src/maintenance_policies.cpp +++ b/src/cpp/src/maintenance_policies.cpp @@ -33,103 +33,117 @@ MaintenancePolicy::MaintenancePolicy( shared_ptr MaintenancePolicy::perform_maintenance() { // only consider split/deletion once the window is full + auto start_total = steady_clock::now(); if (partition_manager_->parent_ == nullptr) { return std::make_shared(); } - int64_t num_queries = hit_count_tracker_->get_num_queries_recorded(); - if (hit_count_tracker_->get_num_queries_recorded() < params_->window_size) { - std::cout << "Window not full yet. " << num_queries << " queries recorded and " << params_->window_size - << " queries required." << std::endl; - return std::make_shared(); - } - - auto start_total = steady_clock::now(); - // STEP 1: Aggregate hit counts from the HitCountTracker. - vector > per_query_hits = hit_count_tracker_->get_per_query_hits(); - unordered_map aggregated_hits; - for (const auto &query_hits: per_query_hits) { - for (int64_t pid: query_hits) { - aggregated_hits[pid]++; - } - } + vector partitions_to_delete; + vector partitions_to_split; Tensor all_partition_ids_tens = partition_manager_->get_partition_ids(); vector all_partition_ids = vector(all_partition_ids_tens.data_ptr(), all_partition_ids_tens.data_ptr() + all_partition_ids_tens.size(0)); - // STEP 2: Use cost estimation to decide which partitions to delete or split. - int total_partitions = partition_manager_->nlist(); - float current_scan_fraction = hit_count_tracker_->get_current_scan_fraction(); - vector partitions_to_delete; - vector partitions_to_split; + if (params_->max_partition_size != -1) { + for (const auto &partition_id: all_partition_ids) { + int partition_size = partition_manager_->get_partition_size(partition_id); - int avg_partition_size = partition_manager_->ntotal() / total_partitions; - for (const auto &partition_id: all_partition_ids) { - // Get hit count and hit rate for the partition. - int hit_count = aggregated_hits[partition_id]; - float hit_rate = static_cast(hit_count) / static_cast(params_->window_size); - int partition_size = partition_manager_->get_partition_size(partition_id); - - // Deletion decision. - float delete_delta = cost_estimator_->compute_delete_delta( - partition_size, hit_rate, total_partitions, current_scan_fraction, avg_partition_size); - - if (delete_delta < -params_->delete_threshold_ns) { - - if (params_->enable_delete_rejection && partition_size > params_->min_partition_size) { - // check the assignments of the partitions to be deleted. - auto search_params = make_shared(); - search_params->k = 2; // get the top 2 partitions, ignore the first one as it is the partition itself - search_params->batched_scan = true; - float *partition_vectors = (float *) partition_manager_->partition_store_->partitions_[partition_id]->codes_; - Tensor part_vecs = torch::from_blob(partition_vectors, {(int64_t) partition_manager_->partition_store_->list_size(partition_id), - partition_manager_->d()}, torch::kFloat32); - auto res = partition_manager_->parent_->search(part_vecs, search_params); - - Tensor reassign_ids = res->ids.flatten(); - - // remove the partition itself - reassign_ids = reassign_ids.masked_select(reassign_ids != partition_id); - - // Get A) the unique partitions, B) the number reassigned, C) the size of the partitions, D) hit rates of the partitions - Tensor uniques; - Tensor counts; - std::tie(uniques, std::ignore, counts) = torch::_unique2(reassign_ids, true, false, true); - Tensor part_sizes = partition_manager_->get_partition_sizes(uniques); - - // convert to vectors - vector reassign_id_vec = vector(uniques.data_ptr(), uniques.data_ptr() + uniques.size(0)); - - vector reassign_sizes = vector(part_sizes.data_ptr(), - part_sizes.data_ptr() + part_sizes.size(0)); - vector reassign_counts = vector(counts.data_ptr(), - counts.data_ptr() + counts.size(0)); - vector hit_rates; - for (int64_t reassign_id: reassign_id_vec) { - hit_rates.push_back(static_cast(aggregated_hits[reassign_id]) / static_cast(params_->window_size)); - } + if (partition_size > params_->max_partition_size) { + partitions_to_split.emplace_back(partition_id); + } else if (partition_size < params_->min_partition_size) { + partitions_to_delete.emplace_back(partition_id); + } + } + + } else { + int64_t num_queries = hit_count_tracker_->get_num_queries_recorded(); + if (hit_count_tracker_->get_num_queries_recorded() < params_->window_size) { + std::cout << "Window not full yet. " << num_queries << " queries recorded and " << params_->window_size + << " queries required." << std::endl; + return std::make_shared(); + } - float delta = cost_estimator_->compute_delete_delta_w_reassign(partition_manager_->get_partition_size(partition_id), - static_cast(aggregated_hits[partition_id]) / static_cast(params_->window_size), - total_partitions, - reassign_counts, - reassign_sizes, - hit_rates); + // STEP 1: Aggregate hit counts from the HitCountTracker. + vector > per_query_hits = hit_count_tracker_->get_per_query_hits(); + unordered_map aggregated_hits; + for (const auto &query_hits: per_query_hits) { + for (int64_t pid: query_hits) { + aggregated_hits[pid]++; + } + } - if (delta < -params_->delete_threshold_ns) { + // STEP 2: Use cost estimation to decide which partitions to delete or split. + int total_partitions = partition_manager_->nlist(); + float current_scan_fraction = hit_count_tracker_->get_current_scan_fraction(); + + int avg_partition_size = partition_manager_->ntotal() / total_partitions; + for (const auto &partition_id: all_partition_ids) { + // Get hit count and hit rate for the partition. + int hit_count = aggregated_hits[partition_id]; + float hit_rate = static_cast(hit_count) / static_cast(params_->window_size); + int partition_size = partition_manager_->get_partition_size(partition_id); + + // Deletion decision. + float delete_delta = cost_estimator_->compute_delete_delta( + partition_size, hit_rate, total_partitions, current_scan_fraction, avg_partition_size); + + if (delete_delta < -params_->delete_threshold_ns) { + + if (params_->enable_delete_rejection && partition_size > params_->min_partition_size) { + // check the assignments of the partitions to be deleted. + auto search_params = make_shared(); + search_params->k = 2; // get the top 2 partitions, ignore the first one as it is the partition itself + search_params->batched_scan = true; + float *partition_vectors = (float *) partition_manager_->partition_store_->partitions_[partition_id]->codes_; + Tensor part_vecs = torch::from_blob(partition_vectors, {(int64_t) partition_manager_->partition_store_->list_size(partition_id), + partition_manager_->d()}, torch::kFloat32); + auto res = partition_manager_->parent_->search(part_vecs, search_params); + + Tensor reassign_ids = res->ids.flatten(); + + // remove the partition itself + reassign_ids = reassign_ids.masked_select(reassign_ids != partition_id); + + // Get A) the unique partitions, B) the number reassigned, C) the size of the partitions, D) hit rates of the partitions + Tensor uniques; + Tensor counts; + std::tie(uniques, std::ignore, counts) = torch::_unique2(reassign_ids, true, false, true); + Tensor part_sizes = partition_manager_->get_partition_sizes(uniques); + + // convert to vectors + vector reassign_id_vec = vector(uniques.data_ptr(), uniques.data_ptr() + uniques.size(0)); + + vector reassign_sizes = vector(part_sizes.data_ptr(), + part_sizes.data_ptr() + part_sizes.size(0)); + vector reassign_counts = vector(counts.data_ptr(), + counts.data_ptr() + counts.size(0)); + vector hit_rates; + for (int64_t reassign_id: reassign_id_vec) { + hit_rates.push_back(static_cast(aggregated_hits[reassign_id]) / static_cast(params_->window_size)); + } + + float delta = cost_estimator_->compute_delete_delta_w_reassign(partition_manager_->get_partition_size(partition_id), + static_cast(aggregated_hits[partition_id]) / static_cast(params_->window_size), + total_partitions, + reassign_counts, + reassign_sizes, + hit_rates); + + if (delta < -params_->delete_threshold_ns) { + partitions_to_delete.push_back(partition_id); + } + } else { partitions_to_delete.push_back(partition_id); } } else { - partitions_to_delete.push_back(partition_id); - } - } else { - if (partition_size > params_->min_partition_size) { - float split_delta = cost_estimator_->compute_split_delta( - partition_size, hit_rate, total_partitions); - if (split_delta < -params_->split_threshold_ns) { - partitions_to_split.push_back(partition_id); + if (partition_size > params_->min_partition_size) { + float split_delta = cost_estimator_->compute_split_delta( + partition_size, hit_rate, total_partitions); + if (split_delta < -params_->split_threshold_ns) { + partitions_to_split.push_back(partition_id); + } } } } @@ -154,7 +168,6 @@ shared_ptr MaintenancePolicy::perform_maintenance() { auto start_split = steady_clock::now(); shared_ptr split_partitions; if (partitions_to_split_tens.numel() > 0) { - // split the partitions into two split_partitions = partition_manager_->split_partitions(partitions_to_split_tens); @@ -171,12 +184,26 @@ shared_ptr MaintenancePolicy::perform_maintenance() { } auto end_total = steady_clock::now(); - // STEP 6: Fill in timing details. + // STEP 6: Clean up any empty partitions + vector empty_ids = {}; + for (auto pair : partition_manager_->partition_store_->partitions_) { + if (pair.second->num_vectors_ <= 0) { + empty_ids.emplace_back(pair.first); + } + } + if (empty_ids.size() > 0) { + partition_manager_->delete_partitions(torch::from_blob(empty_ids.data(), {static_cast(empty_ids.size())}, torch::kInt64)); + } + + // STEP 7: Fill in timing details. shared_ptr timing_info = std::make_shared(); timing_info->delete_time_us = duration_cast(end_delete - start_delete).count(); timing_info->split_time_us = duration_cast(end_split - start_split).count(); timing_info->total_time_us = duration_cast(end_total - start_total).count(); + timing_info->n_splits = static_cast(partitions_to_split.size()); + timing_info->n_deletes = static_cast(partitions_to_delete.size()); + return timing_info; } diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index ef43bd91..5445e377 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -201,7 +201,12 @@ shared_ptr PartitionManager::add( // Determine partition assignments for each vector. vector partition_ids_for_each(n, -1); if (parent_ == nullptr) { - partition_ids_for_each.assign(n, 0); + // round robin assign + int64_t num_parts = nlist(); + for (int64_t i = 0; i < partition_ids_for_each.size(); i++) { + partition_ids_for_each[i] = i % num_parts; + } + if (debug_) { std::cout << "[PartitionManager] add: No parent index; assigning all vectors to partition 0." << std::endl; } @@ -414,7 +419,7 @@ shared_ptr PartitionManager::split_partitions(const Tensor &partitio split_vectors.reserve(total_new_partitions); split_ids.reserve(total_new_partitions); - shared_ptr clustering = select_partitions(partition_ids); + shared_ptr clustering = select_partitions(partition_ids, true); shared_ptr build_params = make_shared(); build_params->nlist = num_splits; diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index ffdcd249..5483a4c7 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -135,7 +135,27 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { // Retrieve partition data. const float *partition_codes = (float *) partition_manager_->partition_store_->get_codes(job.partition_id); const int64_t *partition_ids = (int64_t *) partition_manager_->partition_store_->get_ids(job.partition_id); - int64_t partition_size = partition_manager_->partition_store_->list_size(job.partition_id); + + // skip partition if it is not found (workaround) + int64_t partition_size = 0; + try { + partition_size = partition_manager_->partition_store_->list_size(job.partition_id); + } catch (const std::runtime_error &e) { + std::cerr << "[QueryCoordinator::partition_scan_worker_fn] Partition " << job.partition_id << " not found." << std::endl; + continue; + } + + // skip partition if it is empty + if (partition_size == 0) { + std::cerr << "[QueryCoordinator::partition_scan_worker_fn] Partition " << job.partition_id << " is empty." << std::endl; + // call dummy batch add to decrement topk_buffer jobs counter. #TODO remove jobs counter from topk_buffer + for (int64_t q = 0; q < job.num_queries; q++) { + int64_t global_q = job.query_ids[q]; + global_topk_buffer_pool_[global_q]->batch_add(nullptr, nullptr, 0); + } + continue; + } + // Branch for non-batched jobs. if (!job.is_batched) { @@ -593,7 +613,6 @@ shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partitio float *list_vectors = (float *) partition_manager_->partition_store_->get_codes(pi); int64_t *list_ids = (int64_t *) partition_manager_->partition_store_->get_ids(pi); int64_t list_size = partition_manager_->partition_store_->list_size(pi); - scan_list(query_vec, list_vectors, list_ids, diff --git a/src/python/datasets/ann_datasets.py b/src/python/datasets/ann_datasets.py index 607d47ea..0d37bcfe 100644 --- a/src/python/datasets/ann_datasets.py +++ b/src/python/datasets/ann_datasets.py @@ -161,6 +161,46 @@ def load_ground_truth(self) -> Union[np.ndarray, torch.Tensor]: return torch.from_numpy(ids).long() +class Sift10m(Dataset): + def __init__(self, download_dir: Union[str, Path] = DEFAULT_DOWNLOAD_DIR): + self.download_dir = to_path(download_dir) + self.data_dir = self.download_dir / "sift10m" + self.downloaded = False + self.metric = "l2" + + def is_downloaded(self) -> bool: + base = self.data_dir / "base.1B.u8bin.crop_nb_10000000" + query = self.data_dir / "query.public.10K.u8bin" + gt = self.data_dir / "bigann-10M" + return base.exists() and query.exists() and gt.exists() + + def download(self, overwrite: bool = False): + pass + + def load_vectors(self) -> Union[np.ndarray, torch.Tensor]: + fname = self.data_dir / "base.1B.u8bin.crop_nb_10000000" + n, d = map(int, np.fromfile(fname, dtype="uint32", count=2)) + # return to_torch(np.fromfile(fname, dtype=np.uint8, offset=8).reshape((n, d))) + return torch.from_numpy(np.fromfile(fname, dtype=np.uint8, offset=8).reshape((n, d))).to(torch.float32) + + def load_queries(self) -> Union[np.ndarray, torch.Tensor]: + fname = self.data_dir / "query.public.10K.u8bin" + n, d = map(int, np.fromfile(fname, dtype="uint32", count=2)) + # return to_torch(np.fromfile(fname, dtype=np.uint8, offset=8).reshape((n, d))) + return torch.from_numpy(np.fromfile(fname, dtype=np.uint8, offset=8).reshape((n, d))).to(torch.float32) + + def load_ground_truth(self) -> Union[np.ndarray, torch.Tensor]: + fname = self.data_dir / "bigann-10M" + n, d = map(int, np.fromfile(fname, dtype="uint32", count=2)) + assert os.stat(fname).st_size == 8 + n * d * (4 + 4) + f = open(fname, "rb") + f.seek(4 + 4) + ids = np.fromfile(f, dtype="int32", count=n * d).reshape(n, d) + # D = np.fromfile(f, dtype="float32", count=n * d).reshape(n, d) + + return torch.from_numpy(ids).long() + + def load_dataset( name: str, download_dir: str = DEFAULT_DOWNLOAD_DIR, overwrite_download: bool = False @@ -171,8 +211,10 @@ def load_dataset( dataset = UniformDataset(num_vectors=100000, dim=8, download_dir=download_dir) elif name.lower() == "msturing10m": dataset = MSTuring10m(download_dir=download_dir) + elif name.lower() == "sift10m": + dataset = Sift10m(download_dir=download_dir) else: - raise RuntimeError("Unimplemented dataset") + raise RuntimeError("Unimplemented dataset + " + name) dataset.download(overwrite=overwrite_download) return dataset.load() diff --git a/src/python/workload_generator.py b/src/python/workload_generator.py index faa7c1d2..f390aad7 100644 --- a/src/python/workload_generator.py +++ b/src/python/workload_generator.py @@ -2,11 +2,12 @@ import time from abc import ABC, abstractmethod from pathlib import Path -from typing import Optional, Union +from typing import Optional, Union, Dict, List import matplotlib.pyplot as plt import numpy as np import pandas as pd +import quake import torch from quake import SearchParams @@ -387,230 +388,230 @@ def generate_workload(self): class WorkloadEvaluator: - """ - Evaluates a generated workload on a given index and produces summary statistics and plots. - """ - - def __init__( - self, - workload_dir: Union[str, Path], - output_dir: Union[str, Path], - base_vectors_path: Optional[Union[str, Path]] = None, - ): - self.workload_dir = to_path(workload_dir) - self.output_dir = to_path(output_dir) - self.runbook_path = self.workload_dir / "runbook.json" - self.operations_dir = self.workload_dir / "operations" - self.initial_indices_path = self.workload_dir / "initial_indices.pt" - self.base_vectors_path = ( - to_path(base_vectors_path) if base_vectors_path else self.workload_dir / "base_vectors.pt" - ) - self.runbook = None - - def initialize_index(self, name, index, build_params, m_params): - index_dir = self.workload_dir / "init_indexes" - index_dir.mkdir(parents=True, exist_ok=True) - index_path = index_dir / f"{name}.index" - vectors = torch.load(self.base_vectors_path, weights_only=True).to(torch.float32) - initial_indices = torch.load(self.initial_indices_path, weights_only=True).to(torch.int64) - vectors = vectors[initial_indices] - if not index_path.exists(): - print(build_params) - index.build(vectors, ids=initial_indices, **build_params) - index.save(index_path) - print(f"Index {name} built and saved to {index_path}") + # --------------------------------------------------------------------- + def __init__(self, + workload_dir: Union[str, Path], + output_dir: Union[str, Path], + base_vectors_path: Optional[Union[str, Path]] = None): + + self.workload_dir = to_path(workload_dir) + self.output_dir = to_path(output_dir) + self.runbook_path = self.workload_dir / "runbook.json" + self.ops_dir = self.workload_dir / "operations" + self.init_ids_path = self.workload_dir / "initial_indices.pt" + self.base_vec_path = (to_path(base_vectors_path) + if base_vectors_path + else self.workload_dir / "base_vectors.pt") + + # --------------------------------------------------------------------- + def _init_index(self, name: str, wrapper, build_params: Dict, + m_params: Optional[Dict]): + + idx_dir = self.workload_dir / "init_indexes" + idx_dir.mkdir(parents=True, exist_ok=True) + idx_file = idx_dir / f"{name}.index" + + vecs = torch.load(self.base_vec_path, weights_only=True).float() + init_ids = torch.load(self.init_ids_path, weights_only=True).long() + vecs_init = vecs[init_ids] + + if not idx_file.exists(): + print(f"[{name}] building base index …") + wrapper.build(vecs_init, ids=init_ids, **build_params) + wrapper.save(idx_file) + print(f"[{name}] stored → {idx_file}") else: - if build_params.get("n_workers"): - index.load(index_path, num_workers=build_params["num_workers"]) - else: - index.load(index_path) - print(f"Index {name} loaded from {index_path}") + wrapper.load(idx_file, + num_workers=build_params.get("num_workers", 0)) + print(f"[{name}] loaded ← {idx_file}") + + if isinstance(wrapper, QuakeWrapper) and m_params: + mp = quake.MaintenancePolicyParams() + for k, v in m_params.items(): + setattr(mp, k, v) + wrapper.index.initialize_maintenance_policy(mp) + print(f"[{name}] maintenance policy: {m_params}") + + return wrapper + + # --------------------------------------------------------------------- + def evaluate_workload(self, *, + name: str, + index, + build_params: Dict, + search_params: Dict, + do_maintenance: bool = False, + m_params: Optional[Dict] = None, + batch: bool = False) -> List[Dict]: - if isinstance(index, QuakeWrapper) and m_params is not None: - index.index.initialize_maintenance_policy(m_params) - print(f"Maintenance policy initialized: {m_params}") + self.output_dir.mkdir(parents=True, exist_ok=True) + index = self._init_index(name, index, build_params, m_params) - return index + runbook = json.load(open(self.runbook_path)) + base_vecs = torch.load(self.base_vec_path, weights_only=True).float() + queries = (base_vecs if runbook["parameters"]["sample_queries"] + else torch.load(self.workload_dir / "query_vectors.pt", + weights_only=True).float()) - def evaluate_workload( - self, name, index, build_params, search_params, do_maintenance=False, m_params=None, batch=False - ): - """ - Evaluate the workload on the index. At the end a summary is printed and a multi-panel plot is saved. - """ - # validate search_params - assert "k" in search_params, "search_params must contain 'k' for number of neighbors" - - # --- Load Workload and Index --- - base_vectors = torch.load(self.base_vectors_path, weights_only=True).to(torch.float32) - initial_indices = torch.load(self.initial_indices_path, weights_only=True).to(torch.int64) - - index = self.initialize_index(name, index, build_params, m_params) - - self.runbook = json.load(open(self.runbook_path, "r")) - query_vectors = ( - base_vectors - if self.runbook["parameters"]["sample_queries"] - else torch.load(self.workload_dir / "query_vectors.pt", weights_only=True) - ) - query_vectors = query_vectors.to(torch.float32) - start_time = time.time() - init_time = time.time() - start_time - self.runbook["initialize"]["time"] = init_time - - # --- Run Operations --- - curr_ids = initial_indices - curr_vectors = base_vectors[curr_ids] results = [] - for operation_id, operation in self.runbook["operations"].items(): - print(f"Operation {operation_id}/{len(self.runbook['operations'])}...") - operation_id_int = int(operation_id) - operation_type = operation["type"] - operation_ids = torch.load(self.operations_dir / f"{operation_id}.pt", weights_only=True) - if operation_type == "insert": - curr_ids = torch.cat([curr_ids, operation_ids]) - curr_vectors = torch.cat([curr_vectors, base_vectors[operation_ids]]) - start_time = time.time() - index.add(base_vectors[operation_ids], ids=operation_ids, num_threads=16) - op_time = time.time() - start_time - mean_recall = None - elif operation_type == "delete": - start_time = time.time() - index.remove(operation_ids) - op_time = time.time() - start_time - mean_recall = None - elif operation_type == "query": - gt_ids = torch.load(self.operations_dir / f"{operation_id}_gt_ids.pt", weights_only=True) - # gt_dist = torch.load(self.operations_dir / f"{operation_id}_gt_dists.pt", weights_only=True) - queries = query_vectors[operation_ids] - - start_time = time.time() + totals = dict(query=0., insert=0., delete=0., maintain=0.) + + print(f"─ Evaluating workload on {name} ({len(runbook['operations'])} ops) ─") + for op_id, op in runbook["operations"].items(): + op_no = int(op_id) + op_type = op["type"] + ids = torch.load(self.ops_dir / f"{op_id}.pt", + weights_only=True) + + print(f"[{name}] op {op_no:4d} | {op_type:<6} | {len(ids):6d} ids", end="", flush=True) + + # ----- perform the operation ---------------------------------- + if op_type == "insert": + t0 = time.perf_counter() + index.add(base_vecs[ids], ids=ids) + latency_ms = (time.perf_counter() - t0) * 1e3 + recall = None + elif op_type == "delete": + t0 = time.perf_counter() + index.remove(ids) + latency_ms = (time.perf_counter() - t0) * 1e3 + recall = None + elif op_type == "query": + qs = queries[ids] + t0 = time.perf_counter() if batch: - search_result = index.search(queries, **search_params) - pred_ids = search_result.ids - timing_infos = [search_result.timing_info] + sr = index.search(qs, **search_params) + pred_ids = sr.ids else: - Is, Ds, timing_infos = [], [], [] - - for query in queries: - query = query.unsqueeze(0) - search_result = index.search(query, **search_params) - Is.append(search_result.ids) - Ds.append(search_result.distances) - timing_infos.append(search_result.timing_info) - pred_ids = torch.cat(Is) - op_time = time.time() - start_time - - recalls = compute_recall(pred_ids, gt_ids, search_params["k"]) - mean_recall = recalls.mean().item() - self.runbook["operations"][operation_id]["recall"] = mean_recall - total_time = sum([ti.total_time_ns for ti in timing_infos]) - mean_time = total_time / len(timing_infos) - print(f"Query Time: {mean_time:.2f} ns, Recall: {mean_recall:.2f}") + pred_ids = torch.cat([ + index.search(q.unsqueeze(0), **search_params).ids + for q in qs + ]) + latency_ms = (time.perf_counter() - t0) * 1e3 + gt_ids = torch.load(self.ops_dir / f"{op_id}_gt_ids.pt", + weights_only=True) + recall = compute_recall(pred_ids, gt_ids, + search_params["k"]).mean().item() + op["recall"] = recall + else: + raise ValueError(op_type) + totals[op_type] += latency_ms + + # ----- maintenance ------------------------------------------- + maint_ms = nsplits = ndeletes = 0 if do_maintenance: - print("Running maintenance...") - index.maintenance() - - n_resident = operation.get("n_resident", None) - index_state = index.index_state() - result = { - "operation_number": operation_id_int, - "operation_type": operation_type, - "latency_ms": op_time * 1000, - "recall": mean_recall, - "n_resident": n_resident, + mi = index.maintenance() + maint_ms = mi.total_time_us / 1e3 + nsplits = mi.n_splits + ndeletes = mi.n_deletes + totals["maintain"] += maint_ms + + print(f" | lat {latency_ms:8.2f} ms" + f" | maint {maint_ms:7.2f} ms" + f" | splits {nsplits:4d}" + f" | dels {ndeletes:4d}" + f"{' | rec {:.3f}'.format(recall) if recall is not None else ''}") + + # ----- store row --------------------------------------------- + row = { + "operation_number" : op_no, + "operation_type" : op_type, + "latency_ms" : latency_ms, + "maintenance_time_ms": maint_ms, + "n_splits" : nsplits, + "n_deletes" : ndeletes, + "recall" : recall, + "n_resident" : op.get("n_resident"), } - result.update(index_state) - result.update(search_params) - results.append(result) - - # --- Print Evaluation Summary --- - # Gather per-operation metrics - latencies_insert = [r["latency_ms"] for r in results if r["operation_type"] == "insert"] - op_nums_insert = [r["operation_number"] for r in results if r["operation_type"] == "insert"] - latencies_delete = [r["latency_ms"] for r in results if r["operation_type"] == "delete"] - op_nums_delete = [r["operation_number"] for r in results if r["operation_type"] == "delete"] - latencies_query = [r["latency_ms"] for r in results if r["operation_type"] == "query"] - op_nums_query = [r["operation_number"] for r in results if r["operation_type"] == "query"] - query_recalls = [r["recall"] for r in results if r["operation_type"] == "query" and r["recall"] is not None] - n_vectors = [r["n_resident"] for r in results if r["n_resident"] is not None] - - avg_latency_insert = np.mean(latencies_insert) if latencies_insert else None - avg_latency_delete = np.mean(latencies_delete) if latencies_delete else None - avg_latency_query = np.mean(latencies_query) if latencies_query else None - avg_query_recall = np.mean(query_recalls) if query_recalls else None - - print("\nWorkload Evaluation Summary:") - if avg_latency_insert is not None: - print(f"Average Insert Latency: {avg_latency_insert:.2f} ms") - if avg_latency_delete is not None: - print(f"Average Delete Latency: {avg_latency_delete:.2f} ms") - if avg_latency_query is not None: - print(f"Average Query Latency: {avg_latency_query:.2f} ms") - if avg_query_recall is not None: - print(f"Average Query Recall: {avg_query_recall:.2f}") - - # --- Generate Multi-Panel Plot --- + row.update(index.index_state()) # keeps existing behaviour + row.update(search_params) # 〃 + results.append(row) + + # ---- original four-panel figure (unchanged) --------------------- + df = pd.DataFrame(results) + self._four_panel_plot(df) + + # ---- cumulative-time bar chart --------------------------------- + self._time_breakdown_plot(totals, name) + + # ---- CSV -------------------------------------------------------- + df.to_csv(self.output_dir / "results.csv", index=False) + print(f"Results → {self.output_dir / 'results.csv'}") + return results + + # --------------------------------------------------------------------- + def _four_panel_plot(self, df: pd.DataFrame): + """ + Re-implementation of the original four-panel plot – byte-for-byte + identical file name (*evaluation_plots.png*). + """ + lat_insert = df[df.operation_type == "insert"] + lat_delete = df[df.operation_type == "delete"] + lat_query = df[df.operation_type == "query" ] + fig, axs = plt.subplots(2, 2, figsize=(12, 10)) - # Plot A: Latency per operation type + + # A: latency ax = axs[0, 0] - if op_nums_insert: - ax.plot(op_nums_insert, latencies_insert, label="Insert", marker="o") - if op_nums_delete: - ax.plot(op_nums_delete, latencies_delete, label="Delete", marker="s") - if op_nums_query: - ax.plot(op_nums_query, latencies_query, label="Query", marker="^") - ax.set_xlabel("Operation Number") - ax.set_ylabel("Latency (ms)") - ax.set_title("Operation Latency") - ax.legend() - # Plot B: Number of partitions per operation (if available) + if not lat_insert.empty: + ax.plot(lat_insert.operation_number, lat_insert.latency_ms, + label="Insert", marker="o") + if not lat_delete.empty: + ax.plot(lat_delete.operation_number, lat_delete.latency_ms, + label="Delete", marker="s") + if not lat_query.empty: + ax.plot(lat_query.operation_number, lat_query.latency_ms, + label="Query", marker="^") + ax.set(xlabel="Operation Number", ylabel="Latency (ms)", + title="Operation Latency"); ax.legend() + + # B: partitions + part = df[df.n_list.notna()] ax = axs[0, 1] - partitions = [r["n_list"] for r in results if r["n_list"] is not None] - op_nums_part = [r["operation_number"] for r in results if r["n_list"] is not None] - if partitions: - ax.plot(op_nums_part, partitions, marker="o") - ax.set_xlabel("Operation Number") - ax.set_ylabel("Number of Partitions") - ax.set_title("Partitions per Operation") + if not part.empty: + ax.plot(part.operation_number, part.n_list, marker="o") + ax.set(xlabel="Operation Number", ylabel="Number of Partitions", + title="Partitions per Operation") else: - ax.text(0.5, 0.5, "No partition info", ha="center", va="center") - ax.axis("off") - # Plot C: Resident set size per operation + ax.text(0.5, 0.5, "No partition info", + ha="center", va="center"); ax.axis("off") + + # C: resident set size + res = df[df.n_resident.notna()] ax = axs[1, 0] - if n_vectors: - op_nums_vect = [r["operation_number"] for r in results if r["n_resident"] is not None] - ax.plot(op_nums_vect, n_vectors, marker="o") - ax.set_xlabel("Operation Number") - ax.set_ylabel("Resident Vectors") - ax.set_title("Resident Set Size") + if not res.empty: + ax.plot(res.operation_number, res.n_resident, marker="o") + ax.set(xlabel="Operation Number", ylabel="Resident Vectors", + title="Resident Set Size") else: - ax.text(0.5, 0.5, "No resident set info", ha="center", va="center") - ax.axis("off") - # Plot D: Query recall per query operation + ax.text(0.5, 0.5, "No resident set info", + ha="center", va="center"); ax.axis("off") + + # D: recall + rec = df[(df.operation_type == "query") & df.recall.notna()] ax = axs[1, 1] - if op_nums_query and query_recalls: - ax.plot(op_nums_query, query_recalls, marker="o") - ax.set_xlabel("Operation Number") - ax.set_ylabel("Query Recall") - ax.set_title("Query Recall") + if not rec.empty: + ax.plot(rec.operation_number, rec.recall, marker="o") + ax.set(xlabel="Operation Number", ylabel="Query Recall", + title="Query Recall") else: - ax.text(0.5, 0.5, "No query recall info", ha="center", va="center") - ax.axis("off") - plt.tight_layout() - - # create output directory if it doesn't exist - self.output_dir.mkdir(parents=True, exist_ok=True) + ax.text(0.5, 0.5, "No query recall info", + ha="center", va="center"); ax.axis("off") - plot_path = self.output_dir / "evaluation_plots.png" - plt.savefig(plot_path) - print(f"Saved evaluation plots to {plot_path}") + plt.tight_layout() + plt.savefig(self.output_dir / "evaluation_plots.png") plt.close() - df = pd.DataFrame(results) - csv_path = self.output_dir / "results.csv" - df.to_csv(csv_path, index=False) - print(f"Saved results to {csv_path}") - - return results + # --------------------------------------------------------------------- + def _time_breakdown_plot(self, totals: Dict[str, float], title: str): + plt.figure(figsize=(6, 4)) + bars = [totals["query"], totals["insert"], + totals["delete"], totals["maintain"], + sum(totals.values())] + plt.bar(["Query", "Insert", "Delete", "Maintain", "Total"], bars) + plt.ylabel("Cumulative time (ms)") + plt.title(f"Time budget – {title}") + plt.tight_layout() + plt.savefig(self.output_dir / "time_breakdown.png", dpi=150) + plt.close() \ No newline at end of file diff --git a/test/cpp/benchmark.cpp b/test/cpp/benchmark.cpp index eb74bd90..f5280166 100644 --- a/test/cpp/benchmark.cpp +++ b/test/cpp/benchmark.cpp @@ -496,22 +496,26 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { // Repeatedly search, add, remove, and perform maintenance to see if the index remains consistent. int64_t dimension = 128; - int64_t num_vectors = 100000; - int64_t num_queries = 1; + int64_t num_vectors = 10000; + int64_t num_queries = 100; int64_t batch_size = 10000; int n_ops = 100; QuakeIndex index; auto build_params = std::make_shared(); - build_params->nlist = 10000; + build_params->nlist = 100; build_params->metric = "l2"; build_params->niter = 5; build_params->num_workers = 1; auto maintenance_params = std::make_shared(); - maintenance_params->refinement_radius = 10; + maintenance_params->refinement_radius = 0; maintenance_params->refinement_iterations = 0; - maintenance_params->window_size = 10; + maintenance_params->split_threshold_ns = 1; + maintenance_params->delete_threshold_ns = 1; + maintenance_params->enable_delete_rejection = false; + maintenance_params->enable_split_rejection = false; + maintenance_params->window_size = 1000; Tensor data_vectors = torch::randn({num_vectors, dimension}, torch::kFloat32); Tensor data_ids = torch::arange(num_vectors, torch::kInt64); @@ -523,7 +527,7 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { parent_index_build_params->metric = "l2"; parent_index_build_params->niter = 5; parent_index_build_params->num_workers = 1; - build_params->parent_params = parent_index_build_params; + // build_params->parent_params = parent_index_build_params; // auto grandparent_index_build_params = std::make_shared(); // grandparent_index_build_params->nlist = 1; @@ -544,10 +548,15 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { auto start = std::chrono::high_resolution_clock::now(); auto end = std::chrono::high_resolution_clock::now(); + int64_t num_deleted = 0; + + Tensor origin = torch::zeros(dimension); + Tensor drift = .1 * torch::ones(dimension); + for (int i = 0; i < n_ops; i++) { std::cout << "[SearchAddRemoveMaintenanceTest] Iteration " << i << "\n"; // Search - auto query_vectors = torch::randn({num_queries, dimension}, torch::kFloat32); + auto query_vectors = torch::randn({num_queries, dimension}, torch::kFloat32) + origin; auto search_params = std::make_shared(); search_params->nprobe = 12; search_params->k = 10; @@ -567,7 +576,8 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { ASSERT_EQ(search_result->ids.size(1), search_params->k); // Add - auto add_vectors = torch::randn({batch_size, dimension}, torch::kFloat32); + auto add_vectors = torch::randn({batch_size, dimension}, torch::kFloat32) + origin; + origin += drift; auto add_ids = torch::arange(batch_size, torch::kInt64) + num_vectors; start = std::chrono::high_resolution_clock::now(); auto add_info = index.add(add_vectors, add_ids); @@ -576,18 +586,24 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { num_vectors += batch_size; ASSERT_EQ(add_info->n_vectors, batch_size); - // // Remove - // auto remove_ids = add_ids.slice(0, 0, batch_size / 2); - // start = std::chrono::high_resolution_clock::now(); - // auto remove_info = index.remove(remove_ids); - // end = std::chrono::high_resolution_clock::now(); - // remove_time += std::chrono::duration_cast(end - start).count(); - // ASSERT_EQ(remove_info->n_vectors, batch_size / 2); - - // start = std::chrono::high_resolution_clock::now(); - // index.maintenance(); - // end = std::chrono::high_resolution_clock::now(); - // maintenance_time += std::chrono::duration_cast(end - start).count(); + // Remove + auto remove_ids = torch::arange(batch_size) + num_deleted; + num_deleted += batch_size; + start = std::chrono::high_resolution_clock::now(); + auto remove_info = index.remove(remove_ids); + end = std::chrono::high_resolution_clock::now(); + remove_time += std::chrono::duration_cast(end - start).count(); + ASSERT_EQ(remove_info->n_vectors, batch_size); + + start = std::chrono::high_resolution_clock::now(); + auto timing_info = index.maintenance(); + end = std::chrono::high_resolution_clock::now(); + maintenance_time += std::chrono::duration_cast(end - start).count(); + + std::cout << "n_splits=" << timing_info->n_splits << ", n_deletes=" << timing_info->n_deletes + << ", delete_time=" << timing_info->delete_time_us << " μs" + << ", split_time=" << timing_info->split_time_us << " μs" + << ", total_time=" << timing_info->total_time_us << " μs\n"; } // print out mean times per operation diff --git a/test/experiments/osdi2025/ablation/run.py b/test/experiments/osdi2025/ablation/run.py deleted file mode 100644 index 139597f9..00000000 --- a/test/experiments/osdi2025/ablation/run.py +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/test/experiments/osdi2025/experiment_runner.py b/test/experiments/osdi2025/experiment_runner.py index 233dd314..b51b8725 100644 --- a/test/experiments/osdi2025/experiment_runner.py +++ b/test/experiments/osdi2025/experiment_runner.py @@ -12,6 +12,7 @@ from test.experiments.osdi2025.early_termination.run import run_experiment as run_early_termination from test.experiments.osdi2025.multi_level.run import run_experiment as run_multi_level from test.experiments.osdi2025.vary_levels.run import run_experiment as run_vary_levels +from test.experiments.osdi2025.maintenance_ablation.run import run_experiment as run_ablation EXPERIMENTS = { "kick_the_tires": run_kick_the_tires, @@ -21,6 +22,7 @@ "early_termination": run_early_termination, "multi_level": run_multi_level, "vary_levels": run_vary_levels, + "maintenance_ablation": run_ablation, } def main(): diff --git a/test/experiments/osdi2025/maintenance_ablation/run.py b/test/experiments/osdi2025/maintenance_ablation/run.py new file mode 100644 index 00000000..70e40db5 --- /dev/null +++ b/test/experiments/osdi2025/maintenance_ablation/run.py @@ -0,0 +1,304 @@ +#!/usr/bin/env python3 +""" +Quake maintenance–ablation runner +───────────────────────────────── +• Builds / runs / plots exactly like the original “kick-the-tires” script. +• Per-operation CSV rows now contain + n_splits n_deletes maintenance_time_ms + (written by WorkloadEvaluator below). +• After all indices finish, this script also produces + //time_breakdown.png + – a stacked-bar chart of cumulative time spent in + Search / Insert / Delete / Maintenance / Total. +""" +from __future__ import annotations +import argparse, logging +from pathlib import Path +from typing import Dict, List +import matplotlib.pyplot as plt +from matplotlib.lines import Line2D +from matplotlib.cm import get_cmap +import numpy as np, pandas as pd, yaml + +# quake wrappers ---------------------------------------------------------------- +from quake.datasets.ann_datasets import load_dataset +from quake.index_wrappers.faiss_ivf import FaissIVF +from quake.index_wrappers.quake import QuakeWrapper +from quake.workload_generator import DynamicWorkloadGenerator, WorkloadEvaluator + +logging.basicConfig(level=logging.INFO, format="%(asctime)s | %(levelname)s | %(message)s") +log = logging.getLogger(__name__) + + +OP_STYLE = { + "query" : dict(ls="-", marker="o", mfc="none", ms=4, lw=1.2), + "insert" : dict(ls="-", marker="s", mfc="none", ms=4, lw=1.2), + "delete" : dict(ls="-", marker="^", mfc="none", ms=4, lw=1.2), + "maintain": dict(ls="None", marker="X", mfc="black", ms=5), # points only +} + +LAT_OPS = ["query", "insert", "delete", "maintain"] +IDX_LAT_Q, IDX_LAT_I, IDX_LAT_D, IDX_LAT_M = 0, 1, 2, 3 +IDX_PART, IDX_RES, IDX_REC, IDX_TOT, IDX_SPL = 4, 5, 6, 7, 8 + + +def unified_plot(cfg: Dict, out_dir: Path) -> None: + styles = cfg["plot"].get("styles", {}) + + fig, axs2d = plt.subplots(3, 3, figsize=(18, 12), sharex="col") + axs = axs2d.flatten() + + # ── index legend handles (colour / marker) ──────────────────────────────── + idx_handles: List[Line2D] = [] + for j, idx in enumerate(cfg["indexes"]): + nm, st = idx["name"], styles.get(idx["name"], {}) + idx_handles.append( + Line2D([0], [0], + color = st.get("color", f"C{j}"), + marker = st.get("marker", "o"), + ls = "", + markersize = 6, + label = nm)) + + # ── plot each index ────────────────────────────────────────────────────── + for j, idx in enumerate(cfg["indexes"]): + name = idx["name"] + st = styles.get(name, {}) + colour = st.get("color", f"C{j}") + marker = st.get("marker", "o") + + csv = out_dir / name / "results.csv" + if not csv.exists(): + print(f"[unified_plot] warning: {csv} missing – skipped") + continue + + df = pd.read_csv(csv) + + # latency panels ------------------------------------------------------ + for op, ax_idx in zip(LAT_OPS, + [IDX_LAT_Q, IDX_LAT_I, IDX_LAT_D, IDX_LAT_M]): + ax = axs[ax_idx] + if op == "maintain": + sub = df[df.maintenance_time_ms.fillna(0) > 0] + y = sub.maintenance_time_ms + else: + sub = df[df.operation_type == op] + y = sub.latency_ms + if sub.empty: + continue + ax.plot(sub.operation_number, y, + color=colour, + **OP_STYLE[op]) + + # partitions ---------------------------------------------------------- + ax = axs[IDX_PART] + sub = df[df.n_list.notna()] + if not sub.empty: + ax.plot(sub.operation_number, sub.n_list, + color=colour, marker=marker, lw=1.2) + + # resident vectors ---------------------------------------------------- + ax = axs[IDX_RES] + sub = df[df.n_resident.notna()] + if not sub.empty: + ax.plot(sub.operation_number, sub.n_resident, + color=colour, marker=marker, lw=1.2) + + # recall -------------------------------------------------------------- + ax = axs[IDX_REC] + sub = df[(df.operation_type == "query") & df.recall.notna()] + if not sub.empty: + ax.plot(sub.operation_number, sub.recall, + color=colour, marker=marker, lw=1.2) + + # running total time -------------------------------------------------- + ax = axs[IDX_TOT] + total_ms = df.latency_ms.fillna(0) + df.maintenance_time_ms.fillna(0) + ax.plot(df.operation_number, np.cumsum(total_ms), + color=colour, marker=marker, lw=1.2) + + # cumulative splits / deletes ---------------------------------------- + ax = axs[IDX_SPL] + spl = df.n_splits.fillna(0) + dlt = df.n_deletes.fillna(0) + if (spl > 0).any(): + ax.step(df.operation_number, np.cumsum(spl), + where="post", color=colour, ls="--", lw=1.2) + if (dlt > 0).any(): + ax.step(df.operation_number, np.cumsum(dlt), + where="post", color=colour, ls=":", lw=1.2) + + # ── titles / labels / grids ────────────────────────────────────────────── + titles = { + IDX_LAT_Q: "Latency – Query", + IDX_LAT_I: "Latency – Insert", + IDX_LAT_D: "Latency – Delete", + IDX_LAT_M: "Latency – Maintain", + IDX_PART : "# Partitions", + IDX_RES : "Resident Vectors", + IDX_REC : "Recall", + IDX_TOT : "Running Total Time", + IDX_SPL : "Cumulative Splits / Deletes", + } + for i, ax in enumerate(axs): + ax.set_title(titles[i], fontsize=11) + ax.grid(alpha=0.25, zorder=0) + ax.set_axisbelow(True) + + axs[IDX_PART].set_ylabel("count") + axs[IDX_RES ].set_ylabel("# vectors") + axs[IDX_REC ].set_ylabel("recall") + axs[IDX_TOT ].set_ylabel("ms") + axs[IDX_SPL ].set_ylabel("count") + + # x-labels only on bottom row + for idx in [IDX_PART, IDX_RES, IDX_REC, IDX_TOT, IDX_SPL]: + axs[idx].set_xlabel("Operation #") + + # common x-limit so vertical grids align + all_ops = max((pd.read_csv(out_dir/idx["name"]/ "results.csv").operation_number.max() + for idx in cfg["indexes"] + if (out_dir/idx["name"]/ "results.csv").exists()), default=None) + if all_ops is not None: + for ax in axs: + ax.set_xlim(left=0, right=all_ops) + + # ── single legend (indexes only) ───────────────────────────────────────── + fig.legend(idx_handles, + [h.get_label() for h in idx_handles], + loc="upper center", bbox_to_anchor=(0.5, 1.03), + ncol=min(4, len(idx_handles)), + fontsize=9, title="Index", frameon=False) + + # save -------------------------------------------------------------------- + plt.tight_layout(rect=[0, 0, 1, 0.97]) # space for top legend + out_path = out_dir / "unified_plot.png" + plt.savefig(out_path, dpi=150) + print(f"[unified_plot] → {out_path}") + plt.close() + +# ─────────────────────────────────────────────────────────────────────────────── + +def make_time_breakdown(cfg: Dict, out_dir: Path) -> None: + """ + Create a side-by-side bar chart showing cumulative time spent in + Search / Insert / Delete / Maintenance / Total for each index. + + Recall values are annotated above each Search bar. + Output file: /time_breakdown.png + """ + import matplotlib.pyplot as plt + from matplotlib.cm import get_cmap + import numpy as np + import pandas as pd + + categories = ["Search", "Insert", "Delete", "Maintain", "Total"] + idx_names = [idx["name"] for idx in cfg["indexes"]] + n_idx = len(idx_names) + n_cats = len(categories) + + # Totals and recall tracking + totals = {name: [0]*n_cats for name in idx_names} + recalls = {} + + for idx in cfg["indexes"]: + name = idx["name"] + csv_path = out_dir / name / "results.csv" + if not csv_path.exists(): + print(f"[make_time_breakdown] warning: no CSV for {name} – skipped") + continue + + df = pd.read_csv(csv_path) + totals[name][0] = df[df.operation_type == "query" ].latency_ms.sum() # Search + totals[name][1] = df[df.operation_type == "insert"].latency_ms.sum() # Insert + totals[name][2] = df[df.operation_type == "delete"].latency_ms.sum() # Delete + totals[name][3] = df.maintenance_time_ms.fillna(0).sum() # Maintain + totals[name][4] = sum(totals[name][:4]) # Total + recalls[name] = df[df.operation_type == "query"].recall.mean() # Recall + + # Plotting + x = np.arange(n_cats) + width = 0.8 / max(1, n_idx) + + fig, ax = plt.subplots(figsize=(10, 6)) + cmap = get_cmap("tab10") + + for j, name in enumerate(idx_names): + y = totals[name] + style = cfg["plot"].get("styles", {}).get(name, {}) + color = style.get("color", cmap(j % 10)) + + x_offset = x + (j - (n_idx - 1) / 2) * width + bars = ax.bar(x_offset, y, width=width, label=name, color=color, edgecolor="black") + + # Add recall above Search bar (index 0) + recall_val = recalls.get(name) + if recall_val is not None: + ax.text(x_offset[0], y[0] + 0.01 * max(y), f"Recall={recall_val:.3f}", + ha="center", va="bottom", fontsize=8, rotation=90, color=color) + + ax.set_xticks(x) + ax.set_xticklabels(categories) + ax.set_ylabel("Cumulative Time (ms)") + ax.set_title("Time Breakdown per Index") + ax.legend(title="Index", frameon=False) + plt.tight_layout() + + out_path = out_dir / "time_breakdown.png" + plt.savefig(out_path, dpi=150) + print(f"[make_time_breakdown] → {out_path}") + plt.close() + +# ─────────────────────────────────────────────────────────────────────────────── +def run_experiment(cfg_path:str, output_dir:str): + cfg = yaml.safe_load(Path(cfg_path).read_text()) + out = Path(output_dir).expanduser(); out.mkdir(parents=True, exist_ok=True) + + # 1 dataset / workload --------------------------------------------------- + if cfg["mode"] in {"build","run"}: + ds = cfg["dataset"] + vecs, queries, _ = load_dataset(ds["name"], ds.get("path","")) + gen = DynamicWorkloadGenerator( + workload_dir =out, + base_vectors =vecs, + metric =ds["metric"], + insert_ratio =cfg["workload_generator"]["insert_ratio"], + delete_ratio =cfg["workload_generator"]["delete_ratio"], + query_ratio =cfg["workload_generator"]["query_ratio"], + update_batch_size =cfg["workload_generator"]["update_batch_size"], + query_batch_size =cfg["workload_generator"]["query_batch_size"], + number_of_operations =cfg["workload_generator"]["number_of_operations"], + initial_size =cfg["workload_generator"]["initial_size"], + cluster_size =cfg["workload_generator"]["cluster_size"], + cluster_sample_distribution=cfg["workload_generator"]["cluster_sample_distribution"], + queries =queries, + query_cluster_sample_distribution=cfg["workload_generator"]["query_cluster_sample_distribution"], + seed =cfg["workload_generator"]["seed"]) + if not gen.workload_exists() or cfg["overwrite"].get("workload",False): + log.info("Generating workload …"); gen.generate_workload() + else: + log.info("Existing workload found – generation skipped.") + + # 2 evaluation ----------------------------------------------------------- + if cfg["mode"]=="run": + for idx in cfg["indexes"]: + name, res = idx["name"], out/idx["name"] + csv = res/"results.csv" + if csv.exists() and not cfg["overwrite"].get("results",False): + log.info("%s: cached results – skipped.", name); continue + res.mkdir(parents=True, exist_ok=True) + eval = WorkloadEvaluator(workload_dir=out, output_dir=res) + cls = {"Quake":QuakeWrapper,"IVF":FaissIVF}[idx["index"]] + eval.evaluate_workload( + name =name, + index =cls(), + build_params =idx.get("build_params",{}), + search_params =idx.get("search_params",{}), + m_params=idx.get("maintenance_params",{}), + do_maintenance=True, + ) + + # 3 global plot ---------------------------------------------------------- + if cfg["mode"] in {"run","plot"}: + unified_plot(cfg, out) + make_time_breakdown(cfg, out) diff --git a/test/experiments/osdi2025/multi_level/configs/msturing10m.yaml b/test/experiments/osdi2025/multi_level/configs/sift10m.yaml similarity index 82% rename from test/experiments/osdi2025/multi_level/configs/msturing10m.yaml rename to test/experiments/osdi2025/multi_level/configs/sift10m.yaml index 86997475..df7ef1f1 100644 --- a/test/experiments/osdi2025/multi_level/configs/msturing10m.yaml +++ b/test/experiments/osdi2025/multi_level/configs/sift10m.yaml @@ -6,7 +6,7 @@ overwrite: # ─── dataset ────────────────────────────────────────────────────────────────── dataset: - name: msturing10m # built-in quake dataset + name: sift10m # built-in quake dataset metric: l2 path: data # ignored for packaged datasets nq: 100 # number of queries to use @@ -17,12 +17,12 @@ indexes: index: Quake build_params: nc: 5000 - num_workers: 1 + num_workers: 8 search_params: - k: 100 + k: 1 # recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] - initial_search_fraction: 0.3 +# initial_search_fraction: 0.01 # batched_scan: true batch_size: 1 @@ -30,12 +30,12 @@ indexes: index: Quake build_params: nc: 10000 - num_workers: 1 + num_workers: 8 search_params: - k: 100 + k: 1 # recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] - initial_search_fraction: 0.25 +# initial_search_fraction: 0.01 # batched_scan: true batch_size: 1 @@ -43,12 +43,12 @@ indexes: index: Quake build_params: nc: 20000 - num_workers: 0 + num_workers: 8 search_params: k: 1 # recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] - initial_search_fraction: 0.2 +# initial_search_fraction: 0.01 # batched_scan: true batch_size: 1 @@ -56,39 +56,39 @@ indexes: index: Quake build_params: nc: 40000 - num_workers: 0 + num_workers: 8 search_params: k: 1 - # recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] +# recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] - initial_search_fraction: 0.2 - # batched_scan: true +# initial_search_fraction: 0.01 +# batched_scan: true batch_size: 1 - name: Quake80000 index: Quake build_params: nc: 80000 - num_workers: 0 + num_workers: 8 search_params: k: 1 - # recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] +# recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] - initial_search_fraction: 0.2 - # batched_scan: true +# initial_search_fraction: 0.01 +# batched_scan: true batch_size: 1 - +# - name: Quake160000 index: Quake build_params: nc: 160000 - num_workers: 0 + num_workers: 8 search_params: k: 1 - # recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] +# recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] - initial_search_fraction: 0.2 - # batched_scan: true + initial_search_fraction: 0.005 +# batched_scan: true batch_size: 1 # # - name: Quake20000_500 # two-level Quake index diff --git a/test/experiments/osdi2025/multi_level/run.py b/test/experiments/osdi2025/multi_level/run.py index c3f3c21f..a3abbbed 100644 --- a/test/experiments/osdi2025/multi_level/run.py +++ b/test/experiments/osdi2025/multi_level/run.py @@ -160,7 +160,7 @@ def _plot_unified(cfg: Dict, root: Path) -> None: color = sty.get("color", None), ) - ax.set_xscale("log", base=10) + # ax.set_xscale("log", base=10) ax.set_xlabel("Queries per second (log)") ax.set_ylabel("Recall@k") ax.set_title("Recall curves over varied recall_target") diff --git a/test/experiments/osdi2025/vary_levels/configs/msturing10m_levels.yaml b/test/experiments/osdi2025/vary_levels/configs/msturing10m_levels.yaml deleted file mode 100644 index 2cc895ce..00000000 --- a/test/experiments/osdi2025/vary_levels/configs/msturing10m_levels.yaml +++ /dev/null @@ -1,71 +0,0 @@ -# ─── top-level controls ─────────────────────────────────── -mode: run # ignored by new script – kept for compatibility -overwrite: - index: false - results: true - -# ─── dataset ─────────────────────────────────────────────── -dataset: - name: msturing10m - metric: l2 - path: data - nq: 100 - -# ─── base index (built once) ─────────────────────────────── -index: - type: Quake - build_params: - nc: 160_000 # child level - num_workers: 1 - search_params: - k: 1 - -# ─── parent levels to test ───────────────────────────────── -levels: - - nc: 0 - search_params: - nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096] - batch_size: 1 - - nc: 100 # baseline (keep the index single-level) - search_params: # ← optional override for the CHILD search - nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096] - batch_size: 1 - parent_search_params: # ← optional params passed to *parent* search - nprobe: 10 - - - nc: 500 # 500-centroid parent layer - search_params: - nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096] - batch_size: 1 - parent_search_params: # ← optional params passed to *parent* search - nprobe: 50 - - - nc: 1_000 - search_params: - nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096] - batch_size: 1 - parent_search_params: # ← optional params passed to *parent* search - nprobe: 100 - - - nc: 2_000 - search_params: - nprobes: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096] - batch_size: 1 - parent_search_params: # ← optional params passed to *parent* search - nprobe: 200 - - - nc: 4_000 - search_params: - nprobes: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096] - batch_size: 1 - parent_search_params: # ← optional params passed to *parent* search - nprobe: 400 - -# ─── plotting (optional) ────────────────────────────────── -plot: - styles: - L0: {color: "#1f77b4"} - L100: {color: "#ff7f0e"} - L500: {color: "#ffbb78"} - L1000: {color: "#2ca02c"} - L2000: {color: "#d62728"} \ No newline at end of file diff --git a/test/experiments/osdi2025/vary_levels/configs/sift10m.yaml b/test/experiments/osdi2025/vary_levels/configs/sift10m.yaml new file mode 100644 index 00000000..76fe00c3 --- /dev/null +++ b/test/experiments/osdi2025/vary_levels/configs/sift10m.yaml @@ -0,0 +1,101 @@ +# ─── top-level controls ─────────────────────────────────── +mode: run # ignored by new script – kept for compatibility +overwrite: + index: false + results: true + +# ─── dataset ─────────────────────────────────────────────── +dataset: + name: sift10m + metric: l2 + path: data + nq: 100 + +# ─── base index (built once) ─────────────────────────────── +index: + type: Quake + build_params: + nc: 40_000 # child level + num_workers: 8 + search_params: + k: 1 + +# ─── parent levels to test ───────────────────────────────── +levels: + - nc: 0 + search_params: + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] +# batched_scan: true +# recall_targets: [.5, .6, .7, .8, .85, .9, .95, .99] +# initial_search_fraction: 0.01 +# aps_flush_period_us: 1 + batch_size: 1 + + +# - nc: 100 # baseline (keep the index single-level) +# search_params: # ← optional override for the CHILD search +# # nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] +# recall_targets: [.5, .6, .7, .8, .85, .9, .95, .99] +# initial_search_fraction: 0.002 +## nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256] +# batch_size: 1 +# parent_search_params: # ← optional params passed to *parent* search +## nprobe: 10 +# recall_target: .999 +# initial_search_fraction: 0.05 +# +# - nc: 500 # 500-centroid parent layer +# search_params: +# # nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] +# recall_targets: [.5, .6, .7, .8, .85, .9, .95, .99] +# initial_search_fraction: 0.002 +# batch_size: 1 +# parent_search_params: # ← optional params passed to *parent* search +## nprobe: 15 +# recall_target: .999 +# initial_search_fraction: 0.05 + + - nc: 1_000 + search_params: + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] +# batched_scan: true +# recall_targets: [.5, .6, .7, .8, .85, .9, .95, .99] +# initial_search_fraction: 0.01 + batch_size: 1 + parent_search_params: # ← optional params passed to *parent* search + nprobe: 50 +# batched_scan: true +# recall_target: .999 +# initial_search_fraction: 0.05 + +# - nc: 2_000 +# search_params: +# # nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] +# recall_targets: [.5, .6, .7, .8, .85, .9, .95, .99] +# initial_search_fraction: 0.01 +# batch_size: 1 +# parent_search_params: # ← optional params passed to *parent* search +# nprobe: 50 +## +# - nc: 4_000 +# search_params: +# nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] +## recall_targets: [.5, .6, .7, .8, .85, .9, .95, .99] +## initial_search_fraction: 0.01 +## aps_flush_period_us: 1 +# batch_size: 1 +# parent_search_params: # ← optional params passed to *parent* search +# nprobe: 200 +# recall_target: .999 +# aps_flush_period_us: 1 +# initial_search_fraction: 0.05 + +# ─── plotting (optional) ────────────────────────────────── +plot: + styles: + L0: {color: "#1f77b4"} + L100: {color: "#ff7f0e"} + L500: {color: "#ffbb78"} + L1000: {color: "#2ca02c"} + L2000: {color: "#d62728"} + L4000: {color: "#9467bd"} \ No newline at end of file diff --git a/test/experiments/osdi2025/vary_levels/run.py b/test/experiments/osdi2025/vary_levels/run.py index f9755a7b..01c0ccd1 100644 --- a/test/experiments/osdi2025/vary_levels/run.py +++ b/test/experiments/osdi2025/vary_levels/run.py @@ -131,7 +131,7 @@ def _plot(cfg: Dict, root: Path) -> None: markersize = 6, color = sty.get("color", None), ) - ax.set_xscale("log", base=10) + # ax.set_xscale("log", base=10) ax.set_xlabel("Queries per second (log)") ax.set_ylabel("Recall@k") ax.set_title("QPS vs Recall for different parent levels") From c63159d3f948315d34fa0985292adebea3a51228 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 13 May 2025 23:51:59 -0500 Subject: [PATCH 032/323] update multi-level --- src/cpp/src/clustering.cpp | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index a0e907be..552228be 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -40,7 +40,7 @@ shared_ptr kmeans_cuvs_sample_and_predict( /* ---------- copy to pinned host & (optionally) normalize ----------- */ Tensor cpu_pts = vectors.contiguous().pin_memory(); if (metric == faiss::METRIC_INNER_PRODUCT) { - // k-means in RAFT is L2 – approximate cosine by L2 on the unit sphere + // cuVS k-means is Euclidean; approximate cosine by L2 on the unit sphere cpu_pts = cpu_pts.div(cpu_pts.norm(2, 1, /*keepdim=*/true)); } @@ -65,19 +65,20 @@ shared_ptr kmeans_cuvs_sample_and_predict( .contiguous(); /* ---------- fit on the sample -------------------------------------- */ - float inertia = 0.0f; - int actual_iter = 0; - - cuvs::cluster::kmeans::fit( - handle, params, - raft::make_device_matrix_view(samp_gpu.data_ptr(), - gpu_sample_sz, (int)D), - std::nullopt, - raft::make_device_matrix_view(cent_gpu.data_ptr(), - num_clusters, (int)D), - raft::make_host_scalar_view(&inertia), - raft::make_host_scalar_view(&actual_iter) - ); + { + float inertia = 0.0f; + int actual_iter = 0; + cuvs::cluster::kmeans::fit( + handle, params, + raft::make_device_matrix_view(samp_gpu.data_ptr(), + gpu_sample_sz, (int)D), + std::nullopt, + raft::make_device_matrix_view(cent_gpu.data_ptr(), + num_clusters, (int)D), + raft::make_host_scalar_view(&inertia), + raft::make_host_scalar_view(&actual_iter) + ); + } /* ---------- predict every point, in order, exactly once ------------ */ Tensor all_labels = torch::empty({N}, torch::kLong); // on CPU @@ -91,6 +92,7 @@ shared_ptr kmeans_cuvs_sample_and_predict( Tensor lbl_gpu32 = torch::empty({bs}, torch::dtype(torch::kInt32).device(torch::kCUDA)); + float dummy_inertia = 0.0f; // storage required by the API cuvs::cluster::kmeans::predict( handle, params, raft::make_device_matrix_view(batch_gpu.data_ptr(), @@ -99,8 +101,8 @@ shared_ptr kmeans_cuvs_sample_and_predict( raft::make_device_matrix_view(cent_gpu.data_ptr(), num_clusters, (int)D), raft::make_device_vector_view(lbl_gpu32.data_ptr(), bs), - /*verbosity=*/false, - raft::make_host_scalar_view(nullptr) // we don't need the inertia + /*verbose=*/false, + raft::make_host_scalar_view(&dummy_inertia) ); all_labels.narrow(0, dst_off, bs) From 6e76d20412071b95c793c44e3d034178c0dd84cb Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 14 May 2025 00:52:05 -0500 Subject: [PATCH 033/323] add msturing100M --- src/python/datasets/ann_datasets.py | 46 +++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/python/datasets/ann_datasets.py b/src/python/datasets/ann_datasets.py index 0d37bcfe..a2ba8797 100644 --- a/src/python/datasets/ann_datasets.py +++ b/src/python/datasets/ann_datasets.py @@ -161,6 +161,50 @@ def load_ground_truth(self) -> Union[np.ndarray, torch.Tensor]: return torch.from_numpy(ids).long() +class MSTuring100m(Dataset): + def __init__(self, download_dir: Union[str, Path] = DEFAULT_DOWNLOAD_DIR): + self.download_dir = to_path(download_dir) + self.data_dir = self.download_dir / "MSTuringANNS100M" + self.downloaded = False + self.metric = "l2" + + def is_downloaded(self) -> bool: + base = self.data_dir / "base1b.fbin.crop_nb_100000000" + query = self.data_dir / "query100K.fbin" + gt = self.data_dir / "msturing-gt-100M" + downloaded = base.exists() and query.exists() and gt.exists() + + if not downloaded: + raise RuntimeError("MSTuring dataset is not available. Please download it manually using big-ann-benchmarks.") + + return downloaded + + def download(self, overwrite: bool = False): + pass + + def load_vectors(self) -> Union[np.ndarray, torch.Tensor]: + fname = self.data_dir / "base1b.fbin.crop_nb_10000000" + n, d = map(int, np.fromfile(fname, dtype="uint32", count=2)) + # return to_torch(np.fromfile(fname, dtype=np.float32, offset=8).reshape((n, d))) + return torch.from_numpy(np.fromfile(fname, dtype=np.float32, offset=8).reshape((n, d))) + + def load_queries(self) -> Union[np.ndarray, torch.Tensor]: + fname = self.data_dir / "query100K.fbin" + n, d = map(int, np.fromfile(fname, dtype="uint32", count=2)) + # return to_torch(np.fromfile(fname, dtype=np.float32, offset=8).reshape((n, d))) + return torch.from_numpy(np.fromfile(fname, dtype=np.float32, offset=8).reshape((n, d))) + + def load_ground_truth(self) -> Union[np.ndarray, torch.Tensor]: + fname = self.data_dir / "msturing-gt-10M" + n, d = map(int, np.fromfile(fname, dtype="uint32", count=2)) + assert os.stat(fname).st_size == 8 + n * d * (4 + 4) + f = open(fname, "rb") + f.seek(4 + 4) + ids = np.fromfile(f, dtype="int32", count=n * d).reshape(n, d) + # D = np.fromfile(f, dtype="float32", count=n * d).reshape(n, d) + + return torch.from_numpy(ids).long() + class Sift10m(Dataset): def __init__(self, download_dir: Union[str, Path] = DEFAULT_DOWNLOAD_DIR): self.download_dir = to_path(download_dir) @@ -211,6 +255,8 @@ def load_dataset( dataset = UniformDataset(num_vectors=100000, dim=8, download_dir=download_dir) elif name.lower() == "msturing10m": dataset = MSTuring10m(download_dir=download_dir) + elif name.lower() == "msturing100m": + dataset = MSTuring100m(download_dir=download_dir) elif name.lower() == "sift10m": dataset = Sift10m(download_dir=download_dir) else: From 9c6acf7b251abf37bee695ee3a47df9bfc9d883e Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 14 May 2025 19:55:09 -0500 Subject: [PATCH 034/323] update topk sorting --- src/cpp/bindings/wrap.cpp | 8 + src/cpp/include/common.h | 4 + src/cpp/include/list_scanning.h | 54 +- src/cpp/include/sorting/floyd_rivest_select.h | 129 +++ src/cpp/include/sorting/heap_select.h | 106 ++ src/cpp/include/sorting/median_common.h | 454 +++++++++ src/cpp/include/sorting/pdqsort.h | 937 ++++++++++++++++++ src/python/index_wrappers/quake.py | 4 + src/python/workload_generator.py | 34 +- test/cpp/benchmark.cpp | 6 +- .../kick_the_tires/configs/sift1m.yaml | 22 +- 11 files changed, 1729 insertions(+), 29 deletions(-) create mode 100644 src/cpp/include/sorting/floyd_rivest_select.h create mode 100644 src/cpp/include/sorting/heap_select.h create mode 100644 src/cpp/include/sorting/median_common.h create mode 100644 src/cpp/include/sorting/pdqsort.h diff --git a/src/cpp/bindings/wrap.cpp b/src/cpp/bindings/wrap.cpp index 18a6f92d..b5c0d589 100644 --- a/src/cpp/bindings/wrap.cpp +++ b/src/cpp/bindings/wrap.cpp @@ -201,6 +201,10 @@ PYBIND11_MODULE(_bindings, m) { "Flag to use SPANN for search.") .def_readwrite("spann_eps", &SearchParams::spann_eps, "SPANN parameter epsilon for search.") + .def_readwrite("sample_prefix", &SearchParams::sample_prefix, + "Prefix length for APS sampling.") + .def_readwrite("sample_stride", &SearchParams::sample_stride, + "Stride length for APS sampling.") .def_readwrite("parent_params", &SearchParams::parent_params, "Search parameters for the parent index, if any.") @@ -336,6 +340,10 @@ PYBIND11_MODULE(_bindings, m) { "Parameters used for the search operation.") .def_readwrite("parent_info", &SearchTimingInfo::parent_info, "Search info for the parent index.") + .def_readwrite("aps_time_ns", &SearchTimingInfo::aps_time_ns, + "Time spent on APS in nanoseconds.") + .def_readwrite("scan_time_ns", &SearchTimingInfo::scan_time_ns, + "Time spent on scanning in nanoseconds.") .def("__repr__", [](const SearchTimingInfo &s) { std::ostringstream oss; oss << "{"; diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index 3fb6e0f5..aa102738 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -184,6 +184,8 @@ struct SearchParams { float recompute_threshold = DEFAULT_RECOMPUTE_THRESHOLD; float initial_search_fraction = DEFAULT_INITIAL_SEARCH_FRACTION; int aps_flush_period_us = DEFAULT_APS_FLUSH_PERIOD_US; + int sample_prefix = 0; + int sample_stride = 10; // Auncel params bool use_auncel = false; @@ -238,6 +240,8 @@ struct SearchTimingInfo { int64_t buffer_init_time_ns; ///< Time spent on initializing buffers in nanoseconds. int64_t job_enqueue_time_ns; ///< Time spent on creating jobs in nanoseconds. int64_t boundary_distance_time_ns; ///< Time spent on computing boundary distances in nanoseconds. + int64_t aps_time_ns; ///< Time spent on APS in nanoseconds. + int64_t scan_time_ns; ///< Time spent on scanning in nanoseconds. int64_t job_wait_time_ns; ///< Time spent waiting for jobs to complete in nanoseconds. int64_t result_aggregate_time_ns; ///< Time spent on aggregating results in nanoseconds. int64_t total_time_ns; ///< Total time spent in nanoseconds. diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 557393b7..bb7defe0 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -10,6 +10,9 @@ #include #include "faiss/utils/Heap.h" #include "faiss/utils/distances.h" +#include "sorting/pdqsort.h" +#include "sorting/floyd_rivest_select.h" +#include "sorting/heap_select.h" inline Tensor calculate_recall(Tensor ids, Tensor gt_ids) { Tensor num_correct = torch::zeros(ids.size(0), torch::kInt64); @@ -36,7 +39,7 @@ inline Tensor calculate_recall(Tensor ids, Tensor gt_ids) { return recall; } -#define TOP_K_BUFFER_CAPACITY (8 * 1024) +#define TOP_K_BUFFER_CAPACITY (16 * 1024) template class TypedTopKBuffer { @@ -51,7 +54,7 @@ class TypedTopKBuffer { std::atomic partitions_scanned_; TypedTopKBuffer(int k, bool is_descending, int buffer_capacity = TOP_K_BUFFER_CAPACITY) - : k_(k), is_descending_(is_descending), topk_(buffer_capacity), processing_query_(true), partitions_scanned_(0) { + : k_(k), is_descending_(is_descending), topk_(buffer_capacity), processing_query_(true), partitions_scanned_(0) { assert(k <= buffer_capacity); // Ensure k is smaller than or equal to buffer size for (int i = 0; i < topk_.size(); i++) { @@ -151,22 +154,47 @@ class TypedTopKBuffer { DistanceType flush() { std::lock_guard buffer_lock(buffer_mutex_); if (curr_offset_ > k_) { - if (is_descending_) { - std::partial_sort(topk_.begin(), topk_.begin() + k_, topk_.begin() + curr_offset_, - [](const auto &a, const auto &b) { return a.first > b.first; }); + + // for k < 10 use heap select + if (k_ < 10) { + if (is_descending_) { + miniselect::heap_select(topk_.begin(), topk_.begin() + k_, + topk_.begin() + curr_offset_, + [](const auto &a, const auto &b) { return a.first > b.first; }); + } else { + miniselect::heap_select(topk_.begin(), topk_.begin() + k_, + topk_.begin() + curr_offset_, + [](const auto &a, const auto &b) { return a.first < b.first; }); + } + } else if (k_ < curr_offset_ * .001) { + if (is_descending_) { + miniselect::floyd_rivest_select(topk_.begin(), topk_.begin() + k_, + topk_.begin() + curr_offset_, + [](const auto &a, const auto &b) { return a.first > b.first; }); + } else { + miniselect::floyd_rivest_select(topk_.begin(), topk_.begin() + k_, + topk_.begin() + curr_offset_, + [](const auto &a, const auto &b) { return a.first < b.first; }); + } } else { - std::partial_sort(topk_.begin(), topk_.begin() + k_, topk_.begin() + curr_offset_, - [](const auto &a, const auto &b) { return a.first < b.first; }); + if (is_descending_) { + miniselect::pdqpartial_sort_branchless(topk_.begin(), topk_.begin() + k_, + topk_.begin() + curr_offset_, + [](const auto &a, const auto &b) { return a.first > b.first; }); + } else { + miniselect::pdqpartial_sort_branchless(topk_.begin(), topk_.begin() + k_, + topk_.begin() + curr_offset_, + [](const auto &a, const auto &b) { return a.first < b.first; }); + } } curr_offset_ = k_; // After flush, retain only the top-k elements } else { - // sort the curr_offset_ elements if (is_descending_) { - std::sort(topk_.begin(), topk_.begin() + curr_offset_, - [](const auto &a, const auto &b) { return a.first > b.first; }); + miniselect::pdqsort_branchless(topk_.begin(), topk_.begin() + curr_offset_, + [](const auto &a, const auto &b) { return a.first > b.first; }); } else { - std::sort(topk_.begin(), topk_.begin() + curr_offset_, - [](const auto &a, const auto &b) { return a.first < b.first; }); + miniselect::pdqsort_branchless(topk_.begin(), topk_.begin() + curr_offset_, + [](const auto &a, const auto &b) { return a.first < b.first; }); } } return topk_[std::min(curr_offset_, k_ - 1)].first; @@ -195,7 +223,7 @@ class TypedTopKBuffer { return topk_[std::min(curr_offset_, k_ - 1)].first; } - // Get the current top-k indices (after final flush) +// Get the current top-k indices (after final flush) std::vector get_topk_indices() { std::lock_guard buffer_lock(buffer_mutex_); flush(); // Ensure the buffer is properly flushed diff --git a/src/cpp/include/sorting/floyd_rivest_select.h b/src/cpp/include/sorting/floyd_rivest_select.h new file mode 100644 index 00000000..db213b6c --- /dev/null +++ b/src/cpp/include/sorting/floyd_rivest_select.h @@ -0,0 +1,129 @@ +/* Copyright Danila Kutenin, 2020-. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * https://boost.org/LICENSE_1_0.txt) + */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace miniselect { + namespace floyd_rivest_detail { + + enum floyd_rivest_constants { + kQCap = 600, + }; + + template + struct CompareRefType { + // Pass the comparator by lvalue reference. Or in debug mode, using a + // debugging wrapper that stores a reference. + using type = typename std::add_lvalue_reference::type; + }; + + template ::difference_type> + inline void floyd_rivest_select_loop(Iter begin, DiffType left, DiffType right, + DiffType k, Compare comp) { + while (right > left) { + DiffType size = right - left; + if (size > floyd_rivest_constants::kQCap) { + DiffType n = right - left + 1; + DiffType i = k - left + 1; + + double z = log(n); + double s = 0.5 * exp(2 * z / 3); + double sd = 0.5 * sqrt(z * s * (n - s) / n); + if (i < n / 2) { + sd *= -1.0; + } + DiffType new_left = + std::max(left, static_cast(k - i * s / n + sd)); + DiffType new_right = + std::min(right, static_cast(k + (n - i) * s / n + sd)); + floyd_rivest_select_loop(begin, new_left, + new_right, k, comp); + } + DiffType i = left; + DiffType j = right; + + std::swap(begin[left], begin[k]); + const bool to_swap = comp(begin[left], begin[right]); + if (to_swap) { + std::swap(begin[left], begin[right]); + } + // Make sure that non copyable types compile. + const auto& t = to_swap ? begin[left] : begin[right]; + while (i < j) { + std::swap(begin[i], begin[j]); + i++; + j--; + while (comp(begin[i], t)) { + i++; + } + while (comp(t, begin[j])) { + j--; + } + } + + if (to_swap) { + std::swap(begin[left], begin[j]); + } else { + j++; + std::swap(begin[right], begin[j]); + } + + if (j <= k) { + left = j + 1; + } + if (k <= j) { + right = j - 1; + } + } + } + + } // namespace floyd_rivest_detail + + template + inline void floyd_rivest_partial_sort(Iter begin, Iter mid, Iter end, + Compare comp) { + if (begin == end) return; + if (begin == mid) return; + using CompType = typename floyd_rivest_detail::CompareRefType::type; + using DiffType = typename std::iterator_traits::difference_type; + floyd_rivest_detail::floyd_rivest_select_loop( + begin, DiffType{0}, static_cast(end - begin - 1), + static_cast(mid - begin - 1), comp); + // std::sort proved to be better than other sorts because of pivoting. + std::sort(begin, mid, comp); + } + + template + inline void floyd_rivest_partial_sort(Iter begin, Iter mid, Iter end) { + typedef typename std::iterator_traits::value_type T; + floyd_rivest_partial_sort(begin, mid, end, std::less()); + } + + template + inline void floyd_rivest_select(Iter begin, Iter mid, Iter end, Compare comp) { + if (mid == end) return; + using CompType = typename floyd_rivest_detail::CompareRefType::type; + using DiffType = typename std::iterator_traits::difference_type; + floyd_rivest_detail::floyd_rivest_select_loop( + begin, DiffType{0}, static_cast(end - begin - 1), + static_cast(mid - begin), comp); + } + + template + inline void floyd_rivest_select(Iter begin, Iter mid, Iter end) { + typedef typename std::iterator_traits::value_type T; + floyd_rivest_select(begin, mid, end, std::less()); + } + +} // namespace miniselect \ No newline at end of file diff --git a/src/cpp/include/sorting/heap_select.h b/src/cpp/include/sorting/heap_select.h new file mode 100644 index 00000000..d51eb9b7 --- /dev/null +++ b/src/cpp/include/sorting/heap_select.h @@ -0,0 +1,106 @@ +/* Copyright Danila Kutenin, 2020-. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * https://boost.org/LICENSE_1_0.txt) + */ +#pragma once + +#include +#include +#include +#include +#include + +namespace miniselect { + namespace heap_select_detail { + + template + struct CompareRefType { + // Pass the comparator by lvalue reference. Or in debug mode, using a + // debugging wrapper that stores a reference. + using type = typename std::add_lvalue_reference::type; + }; + + template + inline void sift_down(Iter first, Compare comp, + typename std::iterator_traits::difference_type len, + Iter start) { + using difference_type = typename std::iterator_traits::difference_type; + using value_type = typename std::iterator_traits::value_type; + difference_type child = start - first; + + if (len < 2 || (len - 2) / 2 < child) return; + + child = 2 * child + 1; + Iter child_i = first + child; + + if ((child + 1) < len && comp(*child_i, *(child_i + 1))) { + ++child_i; + ++child; + } + + if (comp(*child_i, *start)) { + return; + } + + value_type top(std::move(*start)); + do { + *start = std::move(*child_i); + start = child_i; + + if ((len - 2) / 2 < child) { + break; + } + + child = 2 * child + 1; + child_i = first + child; + + if ((child + 1) < len && comp(*child_i, *(child_i + 1))) { + ++child_i; + ++child; + } + } while (!comp(*child_i, top)); + *start = std::move(top); + } + + template + inline void heap_select_loop(Iter first, Iter middle, Iter last, Compare comp) { + std::make_heap(first, middle, comp); + typename std::iterator_traits::difference_type len = middle - first; + for (Iter i = middle; i != last; ++i) { + if (comp(*i, *first)) { + std::swap(*i, *first); + sift_down(first, comp, len, first); + } + } + } + + } // namespace heap_select_detail + + template + inline void heap_select(Iter first, Iter middle, Iter end, Compare comp) { + if (middle == end) return; + heap_select_detail::heap_select_loop(first, middle + 1, end, comp); + std::swap(*first, *middle); + } + + template + inline void heap_select(Iter first, Iter middle, Iter end) { + heap_select(first, middle, end, + std::less::value_type>()); + } + + template + inline void heap_partial_sort(Iter first, Iter middle, Iter end, Compare comp) { + heap_select_detail::heap_select_loop(first, middle, end, comp); + std::sort_heap(first, middle, comp); + } + + template + inline void heap_partial_sort(Iter first, Iter middle, Iter end) { + heap_partial_sort( + first, middle, end, + std::less::value_type>()); + } + +} // namespace miniselect \ No newline at end of file diff --git a/src/cpp/include/sorting/median_common.h b/src/cpp/include/sorting/median_common.h new file mode 100644 index 00000000..4e85cd8e --- /dev/null +++ b/src/cpp/include/sorting/median_common.h @@ -0,0 +1,454 @@ +/* Copyright Andrei Alexandrescu, 2016-, + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * https://boost.org/LICENSE_1_0.txt) + */ +/* Copyright Danila Kutenin, 2020-. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * https://boost.org/LICENSE_1_0.txt) + */ +#pragma once + +#include +#include +#include +#include + +namespace miniselect { + namespace median_common_detail { + + template + struct CompareRefType { + // Pass the comparator by lvalue reference. Or in debug mode, using a + // debugging wrapper that stores a reference. + using type = typename std::add_lvalue_reference::type; + }; +/** +Swaps the median of r[a], r[b], and r[c] into r[b]. +*/ + template ::difference_type> + inline void median3(Iter r, DiffType a, DiffType b, DiffType c, + Compare&& comp) { + if (comp(r[b], r[a])) // b < a + { + if (comp(r[b], r[c])) // b < a, b < c + { + if (comp(r[c], r[a])) // b < c < a + std::swap(r[b], r[c]); + else // b < a <= c + std::swap(r[b], r[a]); + } + } else if (comp(r[c], r[b])) // a <= b, c < b + { + if (comp(r[c], r[a])) // c < a <= b + std::swap(r[b], r[a]); + else // a <= c < b + std::swap(r[b], r[c]); + } + } + +/** +Sorts in place r[a], r[b], and r[c]. +*/ + template ::difference_type> + inline void sort3(Iter r, DiffType a, DiffType b, DiffType c, Compare&& comp) { + typedef typename std::iterator_traits::value_type T; + if (comp(r[b], r[a])) // b < a + { + if (comp(r[c], r[b])) // c < b < a + { + std::swap(r[a], r[c]); // a < b < c + } else // b < a, b <= c + { + T t = std::move(r[a]); + r[a] = std::move(r[b]); + if (comp(r[c], t)) // b <= c < a + { + r[b] = std::move(r[c]); + r[c] = std::move(t); + } else // b < a <= c + { + r[b] = std::move(t); + } + } + } else if (comp(r[c], r[b])) // a <= b, c < b + { + T t = std::move(r[c]); + r[c] = std::move(r[b]); + if (comp(t, r[a])) // c < a < b + { + r[b] = std::move(r[a]); + r[a] = std::move(t); + } else // a <= c < b + { + r[b] = std::move(t); + } + } + + assert(!comp(r[b], r[a]) && !comp(r[c], r[b])); + } + +/** +If leanRight == false, swaps the lower median of r[a]...r[d] into r[b] and +the minimum into r[a]. If leanRight == true, swaps the upper median of +r[a]...r[d] into r[c] and the minimum into r[d]. +*/ + template ::difference_type> + inline void partition4(Iter r, DiffType a, DiffType b, DiffType c, DiffType d, + Compare&& comp) { + assert(a != b && a != c && a != d && b != c && b != d && c != d); + /* static */ if (leanRight) { + // In the median of 5 algorithm, consider r[e] infinite + if (comp(r[c], r[a])) { + std::swap(r[a], r[c]); + } // a <= c + if (comp(r[d], r[b])) { + std::swap(r[b], r[d]); + } // a <= c, b <= d + if (comp(r[d], r[c])) { + std::swap(r[c], r[d]); // a <= d, b <= c < d + std::swap(r[a], r[b]); // b <= d, a <= c < d + } // a <= c <= d, b <= d + if (comp(r[c], r[b])) { // a <= c <= d, c < b <= d + std::swap(r[b], r[c]); // a <= b <= c <= d + } // a <= b <= c <= d + } else { + // In the median of 5 algorithm consider r[a] infinitely small, then + // change b->a. c->b, d->c, e->d + if (comp(r[c], r[a])) { + std::swap(r[a], r[c]); + } + if (comp(r[c], r[b])) { + std::swap(r[b], r[c]); + } + if (comp(r[d], r[a])) { + std::swap(r[a], r[d]); + } + if (comp(r[d], r[b])) { + std::swap(r[b], r[d]); + } else { + if (comp(r[b], r[a])) { + std::swap(r[a], r[b]); + } + } + } + } + +/** +Places the median of r[a]...r[e] in r[c] and partitions the other elements +around it. +*/ + template ::difference_type> + inline void partition5(Iter r, DiffType a, DiffType b, DiffType c, DiffType d, + DiffType e, Compare&& comp) { + assert(a != b && a != c && a != d && a != e && b != c && b != d && b != e && + c != d && c != e && d != e); + if (comp(r[c], r[a])) { + std::swap(r[a], r[c]); + } + if (comp(r[d], r[b])) { + std::swap(r[b], r[d]); + } + if (comp(r[d], r[c])) { + std::swap(r[c], r[d]); + std::swap(r[a], r[b]); + } + if (comp(r[e], r[b])) { + std::swap(r[b], r[e]); + } + if (comp(r[e], r[c])) { + std::swap(r[c], r[e]); + if (comp(r[c], r[a])) { + std::swap(r[a], r[c]); + } + } else { + if (comp(r[c], r[b])) { + std::swap(r[b], r[c]); + } + } + } + +/** +Implements Hoare partition. +*/ + template ::difference_type> + inline Iter pivot_partition(Iter r, DiffType k, DiffType length, + Compare&& comp) { + assert(k < length); + std::swap(*r, r[k]); + DiffType lo = 1, hi = length - 1; + for (;; ++lo, --hi) { + for (;; ++lo) { + if (lo > hi) goto loop_done; + if (!comp(r[lo], *r)) break; + } + // found the left bound: r[lo] >= r[0] + assert(lo <= hi); + for (; comp(*r, r[hi]); --hi) { + } + if (lo >= hi) break; + // found the right bound: r[hi] <= r[0], swap & make progress + std::swap(r[lo], r[hi]); + } + loop_done: + --lo; + std::swap(r[lo], *r); + return r + lo; + } + +/** +Implements the quickselect algorithm, parameterized with a partition function. +*/ + template + inline void quickselect(Iter r, Iter mid, Iter end, Compare&& comp) { + if (r == end || mid >= end) return; + assert(r <= mid && mid < end); + for (;;) switch (end - r) { + case 1: + return; + case 2: + if (comp(r[1], *r)) std::swap(*r, r[1]); + return; + case 3: + sort3(r, 0, 1, 2, comp); + return; + case 4: + switch (mid - r) { + case 0: + goto select_min; + case 1: + partition4(r, 0, 1, 2, 3, comp); + break; + case 2: + partition4(r, 0, 1, 2, 3, comp); + break; + case 3: + goto select_max; + default: + assert(false); + } + return; + default: + assert(end - r > 4); + if (r == mid) { + select_min: + auto pivot = r; + for (++mid; mid < end; ++mid) + if (comp(*mid, *pivot)) pivot = mid; + std::swap(*r, *pivot); + return; + } + if (mid + 1 == end) { + select_max: + auto pivot = r; + for (mid = r + 1; mid < end; ++mid) + if (comp(*pivot, *mid)) pivot = mid; + std::swap(*pivot, *(end - 1)); + return; + } + auto pivot = partition(r, end, comp); + if (pivot == mid) return; + if (mid < pivot) { + end = pivot; + } else { + r = pivot + 1; + } + } + } + +/** +Returns the index of the median of r[a], r[b], and r[c] without writing +anything. +*/ + template ::difference_type> + inline DiffType median_index(const Iter r, DiffType a, DiffType b, DiffType c, + Compare&& comp) { + if (comp(r[c], r[a])) std::swap(a, c); + if (comp(r[c], r[b])) return c; + if (comp(r[b], r[a])) return a; + return b; + } + +/** +Returns the index of the median of r[a], r[b], r[c], and r[d] without writing +anything. If leanRight is true, computes the upper median. Otherwise, conputes +the lower median. +*/ + template ::difference_type> + inline DiffType median_index(Iter r, DiffType a, DiffType b, DiffType c, + DiffType d, Compare&& comp) { + if (comp(r[d], r[c])) std::swap(c, d); + if (leanRight) { + if (comp(r[c], r[a])) { + assert(comp(r[c], r[a]) && !comp(r[d], r[c])); // so r[c]) is out + return median_index(r, a, b, d, comp); + } + } else { + if (!comp(r[d], r[a])) { + return median_index(r, a, b, c, comp); + } + } + // Could return median_index(r, b, c, d) but we already know r[c] <= r[d] + if (!comp(r[c], r[b])) return c; + if (comp(r[d], r[b])) return d; + return b; + } + +/** +Tukey's Ninther: compute the median of r[_1], r[_2], r[_3], then the median of +r[_4], r[_5], r[_6], then the median of r[_7], r[_8], r[_9], and then swap the +median of those three medians into r[_5]. +*/ + template ::difference_type> + inline void ninther(Iter r, DiffType _1, DiffType _2, DiffType _3, DiffType _4, + DiffType _5, DiffType _6, DiffType _7, DiffType _8, + DiffType _9, Compare&& comp) { + _2 = median_index(r, _1, _2, _3, comp); + _8 = median_index(r, _7, _8, _9, comp); + if (comp(r[_8], r[_2])) std::swap(_2, _8); + if (comp(r[_6], r[_4])) std::swap(_4, _6); + // Here we know that r[_2] and r[_8] are the other two medians and that + // r[_2] <= r[_8]. We also know that r[_4] <= r[_6] + if (comp(r[_5], r[_4])) { + // r[_4] is the median of r[_4], r[_5], r[_6] + } else if (comp(r[_6], r[_5])) { + // r[_6] is the median of r[_4], r[_5], r[_6] + _4 = _6; + } else { + // Here we know r[_5] is the median of r[_4], r[_5], r[_6] + if (comp(r[_5], r[_2])) return std::swap(r[_5], r[_2]); + if (comp(r[_8], r[_5])) return std::swap(r[_5], r[_8]); + // This is the only path that returns with no swap + return; + } + // Here we know r[_4] is the median of r[_4], r[_5], r[_6] + if (comp(r[_4], r[_2])) + _4 = _2; + else if (comp(r[_8], r[_4])) + _4 = _8; + std::swap(r[_5], r[_4]); + } + +/** +Input assumptions: +(a) hi <= rite +(c) the range r[0 .. hi] contains elements no smaller than r[0] +Output guarantee: same as Hoare partition using r[0] as pivot. Returns the new +position of the pivot. +*/ + template ::difference_type> + inline DiffType expand_partition_right(Iter r, DiffType hi, DiffType rite, + Compare&& comp) { + DiffType pivot = 0; + assert(pivot <= hi); + assert(hi <= rite); + // First loop: spend r[pivot .. hi] + for (; pivot < hi; --rite) { + if (rite == hi) goto done; + if (!comp(r[rite], r[0])) continue; + ++pivot; + std::swap(r[rite], r[pivot]); + } + // Second loop: make left and pivot meet + for (; rite > pivot; --rite) { + if (!comp(r[rite], r[0])) continue; + while (rite > pivot) { + ++pivot; + if (comp(r[0], r[pivot])) { + std::swap(r[rite], r[pivot]); + break; + } + } + } + + done: + std::swap(r[0], r[pivot]); + return pivot; + } + +/** +Input assumptions: +(a) lo > 0, lo <= pivot +(b) the range r[lo .. pivot] already contains elements no greater than r[pivot] +Output guarantee: Same as Hoare partition around r[pivot]. Returns the new +position of the pivot. +*/ + template ::difference_type> + inline DiffType expand_partition_left(Iter r, DiffType lo, DiffType pivot, + Compare&& comp) { + assert(lo > 0 && lo <= pivot); + DiffType left = 0; + const auto oldPivot = pivot; + for (; lo < pivot; ++left) { + if (left == lo) goto done; + if (!comp(r[oldPivot], r[left])) continue; + --pivot; + std::swap(r[left], r[pivot]); + } + // Second loop: make left and pivot meet + for (;; ++left) { + if (left == pivot) break; + if (!comp(r[oldPivot], r[left])) continue; + for (;;) { + if (left == pivot) goto done; + --pivot; + if (comp(r[pivot], r[oldPivot])) { + std::swap(r[left], r[pivot]); + break; + } + } + } + + done: + std::swap(r[oldPivot], r[pivot]); + return pivot; + } + +/** +Input assumptions: +(a) lo <= pivot, pivot < hi, hi <= length +(b) the range r[lo .. pivot] already contains elements no greater than +r[pivot] +(c) the range r[pivot .. hi] already contains elements no smaller than +r[pivot] +Output guarantee: Same as Hoare partition around r[pivot], returning the new +position of the pivot. +*/ + template ::difference_type> + inline DiffType expand_partition(Iter r, DiffType lo, DiffType pivot, + DiffType hi, DiffType length, Compare&& comp) { + assert(lo <= pivot && pivot < hi && hi <= length); + --hi; + --length; + DiffType left = 0; + for (;; ++left, --length) { + for (;; ++left) { + if (left == lo) + return pivot + expand_partition_right(r + pivot, hi - pivot, + length - pivot, comp); + if (comp(r[pivot], r[left])) break; + } + for (;; --length) { + if (length == hi) + return left + + expand_partition_left(r + left, lo - left, pivot - left, comp); + if (!comp(r[pivot], r[length])) break; + } + std::swap(r[left], r[length]); + } + } + + } // namespace median_common_detail +} // namespace miniselect \ No newline at end of file diff --git a/src/cpp/include/sorting/pdqsort.h b/src/cpp/include/sorting/pdqsort.h new file mode 100644 index 00000000..2bd768b0 --- /dev/null +++ b/src/cpp/include/sorting/pdqsort.h @@ -0,0 +1,937 @@ +/* + pdqsort.h - Pattern-defeating quicksort. + + Copyright (c) 2015 Orson Peters + + This software is provided 'as-is', without any express or implied warranty. + In no event will the authors be held liable for any damages arising from the + use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software in a + product, an acknowledgment in the product documentation would be appreciated + but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. +*/ +/* Copyright Danila Kutenin, 2020-. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * https://boost.org/LICENSE_1_0.txt) + */ +// Adjusted by Danila Kutenin to support pdqselect and pdqpartial_sort. + +#ifndef PDQSORT_H +#define PDQSORT_H + +#include +#include +#include +#include +#include + +#if __cplusplus >= 201103L +#include +#include +#define PDQSORT_PREFER_MOVE(x) std::move(x) +#else +#define PDQSORT_PREFER_MOVE(x) (x) +#endif + +#include "median_common.h" + +namespace miniselect { + namespace pdqsort_detail { + + template + struct CompareRefType { + // Pass the comparator by lvalue reference. Or in debug mode, using a + // debugging wrapper that stores a reference. + using type = typename std::add_lvalue_reference::type; + }; + + enum { + // Partitions below this size are sorted using insertion sort. + insertion_sort_threshold = 24, + + // Partitions above this size use Tukey's ninther to select the pivot. + ninther_threshold = 128, + + // When we detect an already sorted partition, attempt an insertion sort that + // allows this + // amount of element moves before giving up. + partial_insertion_sort_limit = 8, + + // Must be multiple of 8 due to loop unrolling, and < 256 to fit in unsigned + // char. + block_size = 64, + + // Cacheline size, assumes power of two. + cacheline_size = 64 + + }; + +#if __cplusplus >= 201103L + template + struct is_default_compare : std::false_type {}; + template + struct is_default_compare> : std::true_type {}; + template + struct is_default_compare> : std::true_type {}; +#endif + +// Returns floor(log2(n)), assumes n > 0. + template + inline int log2(T n) { + int log = 0; + while (n >>= 1) ++log; + return log; + } + +// Sorts [begin, end) using insertion sort with the given comparison function. + template + inline void insertion_sort(Iter begin, Iter end, Compare& comp) { + typedef typename std::iterator_traits::value_type T; + if (begin == end) return; + + for (Iter cur = begin + 1; cur != end; ++cur) { + Iter sift = cur; + Iter sift_1 = cur - 1; + + // Compare first so we can avoid 2 moves for an element already positioned + // correctly. + if (comp(*sift, *sift_1)) { + T tmp = PDQSORT_PREFER_MOVE(*sift); + + do { + *sift-- = PDQSORT_PREFER_MOVE(*sift_1); + } while (sift != begin && comp(tmp, *--sift_1)); + + *sift = PDQSORT_PREFER_MOVE(tmp); + } + } + } + +// Sorts [begin, end) using insertion sort with the given comparison function. +// Assumes +// *(begin - 1) is an element smaller than or equal to any element in [begin, +// end). + template + inline void unguarded_insertion_sort(Iter begin, Iter end, Compare& comp) { + typedef typename std::iterator_traits::value_type T; + if (begin == end) return; + + for (Iter cur = begin + 1; cur != end; ++cur) { + Iter sift = cur; + Iter sift_1 = cur - 1; + + // Compare first so we can avoid 2 moves for an element already positioned + // correctly. + if (comp(*sift, *sift_1)) { + T tmp = PDQSORT_PREFER_MOVE(*sift); + + do { + *sift-- = PDQSORT_PREFER_MOVE(*sift_1); + } while (comp(tmp, *--sift_1)); + + *sift = PDQSORT_PREFER_MOVE(tmp); + } + } + } + +// Attempts to use insertion sort on [begin, end). Will return false if more +// than partial_insertion_sort_limit elements were moved, and abort sorting. +// Otherwise it will successfully sort and return true. + template + inline bool partial_insertion_sort(Iter begin, Iter end, Compare& comp) { + typedef typename std::iterator_traits::value_type T; + if (begin == end) return true; + + std::size_t limit = 0; + for (Iter cur = begin + 1; cur != end; ++cur) { + Iter sift = cur; + Iter sift_1 = cur - 1; + + // Compare first so we can avoid 2 moves for an element already positioned + // correctly. + if (comp(*sift, *sift_1)) { + T tmp = PDQSORT_PREFER_MOVE(*sift); + + do { + *sift-- = PDQSORT_PREFER_MOVE(*sift_1); + } while (sift != begin && comp(tmp, *--sift_1)); + + *sift = PDQSORT_PREFER_MOVE(tmp); + limit += cur - sift; + } + + if (limit > partial_insertion_sort_limit) return false; + } + + return true; + } + + template + inline void sort2(Iter a, Iter b, Compare& comp) { + if (comp(*b, *a)) std::iter_swap(a, b); + } + +// Sorts the elements *a, *b and *c using comparison function comp. + template + inline void sort3(Iter a, Iter b, Iter c, Compare& comp) { + sort2(a, b, comp); + sort2(b, c, comp); + sort2(a, b, comp); + } + + template + inline T* align_cacheline(T* p) { +#if defined(UINTPTR_MAX) && __cplusplus >= 201103L + std::uintptr_t ip = reinterpret_cast(p); +#else + std::size_t ip = reinterpret_cast(p); +#endif + ip = (ip + cacheline_size - 1) & -cacheline_size; + return reinterpret_cast(ip); + } + + template + inline void swap_offsets(Iter first, Iter last, unsigned char* offsets_l, + unsigned char* offsets_r, int num, bool use_swaps) { + typedef typename std::iterator_traits::value_type T; + if (use_swaps) { + // This case is needed for the descending distribution, where we need + // to have proper swapping for pdqsort to remain O(n). + for (int i = 0; i < num; ++i) { + std::iter_swap(first + offsets_l[i], last - offsets_r[i]); + } + } else if (num > 0) { + Iter l = first + offsets_l[0]; + Iter r = last - offsets_r[0]; + T tmp(PDQSORT_PREFER_MOVE(*l)); + *l = PDQSORT_PREFER_MOVE(*r); + for (int i = 1; i < num; ++i) { + l = first + offsets_l[i]; + *r = PDQSORT_PREFER_MOVE(*l); + r = last - offsets_r[i]; + *l = PDQSORT_PREFER_MOVE(*r); + } + *r = PDQSORT_PREFER_MOVE(tmp); + } + } + +// Partitions [begin, end) around pivot *begin using comparison function comp. +// Elements equal to the pivot are put in the right-hand partition. Returns the +// position of the pivot after partitioning and whether the passed sequence +// already was correctly partitioned. Assumes the pivot is a median of at least +// 3 elements and that [begin, end) is at least insertion_sort_threshold long. +// Uses branchless partitioning. + template + inline std::pair partition_right_branchless(Iter begin, Iter end, + Compare& comp) { + typedef typename std::iterator_traits::value_type T; + + // Move pivot into local for speed. + T pivot(PDQSORT_PREFER_MOVE(*begin)); + Iter first = begin; + Iter last = end; + + // Find the first element greater than or equal than the pivot (the median of + // 3 guarantees this exists). + while (comp(*++first, pivot)) + ; + + // Find the first element strictly smaller than the pivot. We have to guard + // this search if there was no element before *first. + if (first - 1 == begin) + while (first < last && !comp(*--last, pivot)) + ; + else + while (!comp(*--last, pivot)) + ; + + // If the first pair of elements that should be swapped to partition are the + // same element, the passed in sequence already was correctly partitioned. + bool already_partitioned = first >= last; + if (!already_partitioned) { + std::iter_swap(first, last); + ++first; + } + + // The following branchless partitioning is derived from "BlockQuicksort: How + // Branch Mispredictions don’t affect Quicksort" by Stefan Edelkamp and Armin + // Weiss. + unsigned char offsets_l_storage[block_size + cacheline_size]; + unsigned char offsets_r_storage[block_size + cacheline_size]; + unsigned char* offsets_l = align_cacheline(offsets_l_storage); + unsigned char* offsets_r = align_cacheline(offsets_r_storage); + int num_l, num_r, start_l, start_r; + num_l = num_r = start_l = start_r = 0; + + while (last - first > 2 * block_size) { + // Fill up offset blocks with elements that are on the wrong side. + if (num_l == 0) { + start_l = 0; + Iter it = first; + for (unsigned char i = 0; i < block_size;) { + offsets_l[num_l] = i++; + num_l += !comp(*it, pivot); + ++it; + offsets_l[num_l] = i++; + num_l += !comp(*it, pivot); + ++it; + offsets_l[num_l] = i++; + num_l += !comp(*it, pivot); + ++it; + offsets_l[num_l] = i++; + num_l += !comp(*it, pivot); + ++it; + offsets_l[num_l] = i++; + num_l += !comp(*it, pivot); + ++it; + offsets_l[num_l] = i++; + num_l += !comp(*it, pivot); + ++it; + offsets_l[num_l] = i++; + num_l += !comp(*it, pivot); + ++it; + offsets_l[num_l] = i++; + num_l += !comp(*it, pivot); + ++it; + } + } + if (num_r == 0) { + start_r = 0; + Iter it = last; + for (unsigned char i = 0; i < block_size;) { + offsets_r[num_r] = ++i; + num_r += comp(*--it, pivot); + offsets_r[num_r] = ++i; + num_r += comp(*--it, pivot); + offsets_r[num_r] = ++i; + num_r += comp(*--it, pivot); + offsets_r[num_r] = ++i; + num_r += comp(*--it, pivot); + offsets_r[num_r] = ++i; + num_r += comp(*--it, pivot); + offsets_r[num_r] = ++i; + num_r += comp(*--it, pivot); + offsets_r[num_r] = ++i; + num_r += comp(*--it, pivot); + offsets_r[num_r] = ++i; + num_r += comp(*--it, pivot); + } + } + + // Swap elements and update block sizes and first/last boundaries. + int num = std::min(num_l, num_r); + swap_offsets(first, last, offsets_l + start_l, offsets_r + start_r, num, + num_l == num_r); + num_l -= num; + num_r -= num; + start_l += num; + start_r += num; + if (num_l == 0) first += block_size; + if (num_r == 0) last -= block_size; + } + + int l_size = 0, r_size = 0; + int unknown_left = (int)(last - first) - ((num_r || num_l) ? block_size : 0); + if (num_r) { + // Handle leftover block by assigning the unknown elements to the other + // block. + l_size = unknown_left; + r_size = block_size; + } else if (num_l) { + l_size = block_size; + r_size = unknown_left; + } else { + // No leftover block, split the unknown elements in two blocks. + l_size = unknown_left / 2; + r_size = unknown_left - l_size; + } + + // Fill offset buffers if needed. + if (unknown_left && !num_l) { + start_l = 0; + Iter it = first; + for (unsigned char i = 0; i < l_size;) { + offsets_l[num_l] = i++; + num_l += !comp(*it, pivot); + ++it; + } + } + if (unknown_left && !num_r) { + start_r = 0; + Iter it = last; + for (unsigned char i = 0; i < r_size;) { + offsets_r[num_r] = ++i; + num_r += comp(*--it, pivot); + } + } + + int num = std::min(num_l, num_r); + swap_offsets(first, last, offsets_l + start_l, offsets_r + start_r, num, + num_l == num_r); + num_l -= num; + num_r -= num; + start_l += num; + start_r += num; + if (num_l == 0) first += l_size; + if (num_r == 0) last -= r_size; + + // We have now fully identified [first, last)'s proper position. Swap the last + // elements. + if (num_l) { + offsets_l += start_l; + while (num_l--) std::iter_swap(first + offsets_l[num_l], --last); + first = last; + } + if (num_r) { + offsets_r += start_r; + while (num_r--) std::iter_swap(last - offsets_r[num_r], first), ++first; + last = first; + } + + // Put the pivot in the right place. + Iter pivot_pos = first - 1; + *begin = PDQSORT_PREFER_MOVE(*pivot_pos); + *pivot_pos = PDQSORT_PREFER_MOVE(pivot); + + return std::make_pair(pivot_pos, already_partitioned); + } + +// Partitions [begin, end) around pivot *begin using comparison function comp. +// Elements equal to the pivot are put in the right-hand partition. Returns the +// position of the pivot after partitioning and whether the passed sequence +// already was correctly partitioned. Assumes the pivot is a median of at least +// 3 elements and that [begin, end) is at least insertion_sort_threshold long. + template + inline std::pair partition_right(Iter begin, Iter end, + Compare& comp) { + typedef typename std::iterator_traits::value_type T; + + // Move pivot into local for speed. + T pivot(PDQSORT_PREFER_MOVE(*begin)); + + Iter first = begin; + Iter last = end; + + // Find the first element greater than or equal than the pivot (the median of + // 3 guarantees this exists). + while (comp(*++first, pivot)) + ; + + // Find the first element strictly smaller than the pivot. We have to guard + // this search if there was no element before *first. + if (first - 1 == begin) + while (first < last && !comp(*--last, pivot)) + ; + else + while (!comp(*--last, pivot)) + ; + + // If the first pair of elements that should be swapped to partition are the + // same element, the passed in sequence already was correctly partitioned. + bool already_partitioned = first >= last; + + // Keep swapping pairs of elements that are on the wrong side of the pivot. + // Previously swapped pairs guard the searches, which is why the first + // iteration is special-cased above. + while (first < last) { + std::iter_swap(first, last); + while (comp(*++first, pivot)) + ; + while (!comp(*--last, pivot)) + ; + } + + // Put the pivot in the right place. + Iter pivot_pos = first - 1; + *begin = PDQSORT_PREFER_MOVE(*pivot_pos); + *pivot_pos = PDQSORT_PREFER_MOVE(pivot); + + return std::make_pair(pivot_pos, already_partitioned); + } + +// Similar function to the one above, except elements equal to the pivot are put +// to the left of the pivot and it doesn't check or return if the passed +// sequence already was partitioned. Since this is rarely used (the many equal +// case), and in that case pdqsort already has O(n) performance, no block +// quicksort is applied here for simplicity. + template + inline Iter partition_left(Iter begin, Iter end, Compare& comp) { + typedef typename std::iterator_traits::value_type T; + + T pivot(PDQSORT_PREFER_MOVE(*begin)); + Iter first = begin; + Iter last = end; + + while (comp(pivot, *--last)) + ; + + if (last + 1 == end) + while (first < last && !comp(pivot, *++first)) + ; + else + while (!comp(pivot, *++first)) + ; + + while (first < last) { + std::iter_swap(first, last); + while (comp(pivot, *--last)) + ; + while (!comp(pivot, *++first)) + ; + } + + Iter pivot_pos = last; + *begin = PDQSORT_PREFER_MOVE(*pivot_pos); + *pivot_pos = PDQSORT_PREFER_MOVE(pivot); + + return pivot_pos; + } + + template + inline void pdqsort_loop(Iter begin, Iter end, Compare& comp, int bad_allowed, + bool leftmost = true) { + typedef typename std::iterator_traits::difference_type diff_t; + + // Use a while loop for tail recursion elimination. + while (true) { + diff_t size = end - begin; + + // Insertion sort is faster for small arrays. + if (size < insertion_sort_threshold) { + if (leftmost) + insertion_sort(begin, end, comp); + else + unguarded_insertion_sort(begin, end, comp); + return; + } + + // Choose pivot as median of 3 or pseudomedian of 9. + diff_t s2 = size / 2; + if (size > ninther_threshold) { + sort3(begin, begin + s2, end - 1, comp); + sort3(begin + 1, begin + (s2 - 1), end - 2, comp); + sort3(begin + 2, begin + (s2 + 1), end - 3, comp); + sort3(begin + (s2 - 1), begin + s2, begin + (s2 + 1), comp); + std::iter_swap(begin, begin + s2); + } else + sort3(begin + s2, begin, end - 1, comp); + + // If *(begin - 1) is the end of the right partition of a previous partition + // operation there is no element in [begin, end) that is smaller than + // *(begin - 1). Then if our pivot compares equal to *(begin - 1) we change + // strategy, putting equal elements in the left partition, greater elements + // in the right partition. We do not have to recurse on the left partition, + // since it's sorted (all equal). + if (!leftmost && !comp(*(begin - 1), *begin)) { + begin = partition_left(begin, end, comp) + 1; + continue; + } + + // Partition and get results. + std::pair part_result = + Branchless ? partition_right_branchless(begin, end, comp) + : partition_right(begin, end, comp); + Iter pivot_pos = part_result.first; + bool already_partitioned = part_result.second; + + // Check for a highly unbalanced partition. + diff_t l_size = pivot_pos - begin; + diff_t r_size = end - (pivot_pos + 1); + bool highly_unbalanced = l_size < size / 8 || r_size < size / 8; + + // If we got a highly unbalanced partition we shuffle elements to break many + // patterns. + if (highly_unbalanced) { + // If we had too many bad partitions, switch to heapsort to guarantee O(n + // log n). + if (--bad_allowed == 0) { + std::make_heap(begin, end, comp); + std::sort_heap(begin, end, comp); + return; + } + + if (l_size >= insertion_sort_threshold) { + std::iter_swap(begin, begin + l_size / 4); + std::iter_swap(pivot_pos - 1, pivot_pos - l_size / 4); + + if (l_size > ninther_threshold) { + std::iter_swap(begin + 1, begin + (l_size / 4 + 1)); + std::iter_swap(begin + 2, begin + (l_size / 4 + 2)); + std::iter_swap(pivot_pos - 2, pivot_pos - (l_size / 4 + 1)); + std::iter_swap(pivot_pos - 3, pivot_pos - (l_size / 4 + 2)); + } + } + + if (r_size >= insertion_sort_threshold) { + std::iter_swap(pivot_pos + 1, pivot_pos + (1 + r_size / 4)); + std::iter_swap(end - 1, end - r_size / 4); + + if (r_size > ninther_threshold) { + std::iter_swap(pivot_pos + 2, pivot_pos + (2 + r_size / 4)); + std::iter_swap(pivot_pos + 3, pivot_pos + (3 + r_size / 4)); + std::iter_swap(end - 2, end - (1 + r_size / 4)); + std::iter_swap(end - 3, end - (2 + r_size / 4)); + } + } + } else { + // If we were decently balanced and we tried to sort an already + // partitioned sequence try to use insertion sort. + if (already_partitioned && + partial_insertion_sort(begin, pivot_pos, comp) && + partial_insertion_sort(pivot_pos + 1, end, comp)) + return; + } + + // Sort the left partition first using recursion and do tail recursion + // elimination for the right-hand partition. + pdqsort_loop(begin, pivot_pos, comp, bad_allowed, + leftmost); + begin = pivot_pos + 1; + leftmost = false; + } + } + + template + inline void pdqpartial_sort_loop(Iter begin, Iter mid, Iter end, Compare& comp, + int bad_allowed, bool leftmost = true) { + typedef typename std::iterator_traits::difference_type diff_t; + + // Use a while loop for tail recursion elimination. + while (true) { + diff_t size = end - begin; + + // Insertion sort is faster for small arrays. + if (size < insertion_sort_threshold) { + if (leftmost) + insertion_sort(begin, end, comp); + else + unguarded_insertion_sort(begin, end, comp); + return; + } + + // Choose pivot as median of 3 or pseudomedian of 9. + diff_t s2 = size / 2; + if (size > ninther_threshold) { + sort3(begin, begin + s2, end - 1, comp); + sort3(begin + 1, begin + (s2 - 1), end - 2, comp); + sort3(begin + 2, begin + (s2 + 1), end - 3, comp); + sort3(begin + (s2 - 1), begin + s2, begin + (s2 + 1), comp); + std::iter_swap(begin, begin + s2); + } else + sort3(begin + s2, begin, end - 1, comp); + + // If *(begin - 1) is the end of the right partition of a previous partition + // operation there is no element in [begin, end) that is smaller than + // *(begin - 1). Then if our pivot compares equal to *(begin - 1) we change + // strategy, putting equal elements in the left partition, greater elements + // in the right partition. We do not have to recurse on the left partition, + // since it's sorted (all equal). + if (!leftmost && !comp(*(begin - 1), *begin)) { + begin = partition_left(begin, end, comp) + 1; + continue; + } + + // Partition and get results. + std::pair part_result = + Branchless ? partition_right_branchless(begin, end, comp) + : partition_right(begin, end, comp); + Iter pivot_pos = part_result.first; + bool already_partitioned = part_result.second; + + // Check for a highly unbalanced partition. + diff_t l_size = pivot_pos - begin; + diff_t r_size = end - (pivot_pos + 1); + bool highly_unbalanced = l_size < size / 8 || r_size < size / 8; + + // If we got a highly unbalanced partition we shuffle elements to break many + // patterns. + if (highly_unbalanced) { + // If we had too many bad partitions, switch to heapsort to guarantee O(n + // log n). + if (--bad_allowed == 0) { + std::make_heap(begin, end, comp); + std::sort_heap(begin, end, comp); + return; + } + + if (l_size >= insertion_sort_threshold) { + std::iter_swap(begin, begin + l_size / 4); + std::iter_swap(pivot_pos - 1, pivot_pos - l_size / 4); + + if (l_size > ninther_threshold) { + std::iter_swap(begin + 1, begin + (l_size / 4 + 1)); + std::iter_swap(begin + 2, begin + (l_size / 4 + 2)); + std::iter_swap(pivot_pos - 2, pivot_pos - (l_size / 4 + 1)); + std::iter_swap(pivot_pos - 3, pivot_pos - (l_size / 4 + 2)); + } + } + + if (r_size >= insertion_sort_threshold) { + std::iter_swap(pivot_pos + 1, pivot_pos + (1 + r_size / 4)); + std::iter_swap(end - 1, end - r_size / 4); + + if (r_size > ninther_threshold) { + std::iter_swap(pivot_pos + 2, pivot_pos + (2 + r_size / 4)); + std::iter_swap(pivot_pos + 3, pivot_pos + (3 + r_size / 4)); + std::iter_swap(end - 2, end - (1 + r_size / 4)); + std::iter_swap(end - 3, end - (2 + r_size / 4)); + } + } + } else { + // If we were decently balanced and we tried to sort an already + // partitioned sequence try to use insertion sort. + if (already_partitioned && + partial_insertion_sort(begin, pivot_pos, comp) && + partial_insertion_sort(pivot_pos + 1, end, comp)) + return; + } + + // Sort the left partition first using recursion and do tail recursion + // elimination for the right-hand partition. + if (pivot_pos < mid) { + pdqsort_loop(begin, pivot_pos, comp, + bad_allowed, leftmost); + begin = pivot_pos + 1; + leftmost = false; + } else { + end = pivot_pos; + } + } + } + + template + inline void pdqselect_loop(Iter begin, Iter mid, Iter end, Compare& comp, + int bad_allowed, bool leftmost = true) { + typedef typename std::iterator_traits::difference_type diff_t; + + // Use a while loop for tail recursion elimination. + while (true) { + diff_t size = end - begin; + + // Insertion sort is faster for small arrays. + if (size < insertion_sort_threshold) { + if (leftmost) + insertion_sort(begin, end, comp); + else + unguarded_insertion_sort(begin, end, comp); + return; + } + + // Choose pivot as median of 3 or pseudomedian of 9. + diff_t s2 = size / 2; + if (size > ninther_threshold) { + sort3(begin, begin + s2, end - 1, comp); + sort3(begin + 1, begin + (s2 - 1), end - 2, comp); + sort3(begin + 2, begin + (s2 + 1), end - 3, comp); + sort3(begin + (s2 - 1), begin + s2, begin + (s2 + 1), comp); + std::iter_swap(begin, begin + s2); + } else + sort3(begin + s2, begin, end - 1, comp); + + // If *(begin - 1) is the end of the right partition of a previous partition + // operation there is no element in [begin, end) that is smaller than + // *(begin - 1). Then if our pivot compares equal to *(begin - 1) we change + // strategy, putting equal elements in the left partition, greater elements + // in the right partition. We do not have to recurse on the left partition, + // since it's sorted (all equal). + if (!leftmost && !comp(*(begin - 1), *begin)) { + begin = partition_left(begin, end, comp) + 1; + continue; + } + + // Partition and get results. + std::pair part_result = + Branchless ? partition_right_branchless(begin, end, comp) + : partition_right(begin, end, comp); + Iter pivot_pos = part_result.first; + bool already_partitioned = part_result.second; + + // Check for a highly unbalanced partition. + diff_t l_size = pivot_pos - begin; + diff_t r_size = end - (pivot_pos + 1); + bool highly_unbalanced = l_size < size / 8 || r_size < size / 8; + + // If we got a highly unbalanced partition we shuffle elements to break many + // patterns. + if (highly_unbalanced) { + // If we had too many bad partitions, switch to heapsort to guarantee O(n + // log n). + if (--bad_allowed == 0) { + std::nth_element(begin, mid, end, comp); + return; + } + + if (l_size >= insertion_sort_threshold) { + std::iter_swap(begin, begin + l_size / 4); + std::iter_swap(pivot_pos - 1, pivot_pos - l_size / 4); + + if (l_size > ninther_threshold) { + std::iter_swap(begin + 1, begin + (l_size / 4 + 1)); + std::iter_swap(begin + 2, begin + (l_size / 4 + 2)); + std::iter_swap(pivot_pos - 2, pivot_pos - (l_size / 4 + 1)); + std::iter_swap(pivot_pos - 3, pivot_pos - (l_size / 4 + 2)); + } + } + + if (r_size >= insertion_sort_threshold) { + std::iter_swap(pivot_pos + 1, pivot_pos + (1 + r_size / 4)); + std::iter_swap(end - 1, end - r_size / 4); + + if (r_size > ninther_threshold) { + std::iter_swap(pivot_pos + 2, pivot_pos + (2 + r_size / 4)); + std::iter_swap(pivot_pos + 3, pivot_pos + (3 + r_size / 4)); + std::iter_swap(end - 2, end - (1 + r_size / 4)); + std::iter_swap(end - 3, end - (2 + r_size / 4)); + } + } + } else { + // If we were decently balanced and we tried to sort an already + // partitioned sequence try to use insertion sort. + if (already_partitioned && + partial_insertion_sort(begin, pivot_pos, comp) && + partial_insertion_sort(pivot_pos + 1, end, comp)) + return; + } + // Sort the left partition first using recursion and do tail recursion + // elimination for the right-hand partition. + if (pivot_pos < mid) { + begin = pivot_pos + 1; + leftmost = false; + } else { + end = pivot_pos; + } + } + } + } // namespace pdqsort_detail + + template + inline void pdqsort(Iter begin, Iter end, Compare comp) { + if (begin == end) return; + +#if __cplusplus >= 201103L + pdqsort_detail::pdqsort_loop< + Iter, Compare, + pdqsort_detail::is_default_compare< + typename std::decay::type>::value && + std::is_arithmetic< + typename std::iterator_traits::value_type>::value>( + begin, end, comp, pdqsort_detail::log2(end - begin)); +#else + pdqsort_detail::pdqsort_loop( + begin, end, comp, pdqsort_detail::log2(end - begin)); +#endif + } + + template + inline void pdqsort(Iter begin, Iter end) { + typedef typename std::iterator_traits::value_type T; + pdqsort(begin, end, std::less()); + } + + template + inline void pdqsort_branchless(Iter begin, Iter end, Compare comp) { + if (begin == end) return; + pdqsort_detail::pdqsort_loop( + begin, end, comp, pdqsort_detail::log2(end - begin)); + } + + template + inline void pdqsort_branchless(Iter begin, Iter end) { + typedef typename std::iterator_traits::value_type T; + pdqsort_branchless(begin, end, std::less()); + } + + template + inline void pdqpartial_sort(Iter begin, Iter mid, Iter end, Compare comp) { + if (begin == end) return; + +#if __cplusplus >= 201103L + pdqsort_detail::pdqpartial_sort_loop< + Iter, Compare, + pdqsort_detail::is_default_compare< + typename std::decay::type>::value && + std::is_arithmetic< + typename std::iterator_traits::value_type>::value>( + begin, mid, end, comp, pdqsort_detail::log2(end - begin)); +#else + pdqsort_detail::pdqpartial_sort_loop( + begin, end, comp, pdqsort_detail::log2(end - begin)); +#endif + } + + template + inline void pdqpartial_sort(Iter begin, Iter mid, Iter end) { + typedef typename std::iterator_traits::value_type T; + pdqpartial_sort(begin, mid, end, std::less()); + } + + template + inline void pdqpartial_sort_branchless(Iter begin, Iter mid, Iter end, + Compare comp) { + if (begin == end) return; + pdqsort_detail::pdqpartial_sort_loop( + begin, mid, end, comp, pdqsort_detail::log2(end - begin)); + } + + template + inline void pdqpartial_sort_branchless(Iter begin, Iter mid, Iter end) { + typedef typename std::iterator_traits::value_type T; + pdqpartial_sort_branchless(begin, mid, end, std::less()); + } + + template + inline void pdqselect(Iter begin, Iter mid, Iter end, Compare comp) { + if (mid == end) return; + using CompType = typename median_common_detail::CompareRefType::type; + +#if __cplusplus >= 201103L + pdqsort_detail::pdqselect_loop< + Iter, CompType, + pdqsort_detail::is_default_compare< + typename std::decay::type>::value && + std::is_arithmetic< + typename std::iterator_traits::value_type>::value>( + begin, mid, end, comp, pdqsort_detail::log2(end - begin)); +#else + pdqsort_detail::pdqselect_loop( + begin, end, comp, pdqsort_detail::log2(end - begin)); +#endif + } + + template + inline void pdqselect(Iter begin, Iter mid, Iter end) { + typedef typename std::iterator_traits::value_type T; + pdqselect(begin, mid, end, std::less()); + } + + template + inline void pdqselect_branchless(Iter begin, Iter mid, Iter end, Compare comp) { + if (mid == end) return; + using CompType = typename median_common_detail::CompareRefType::type; + pdqsort_detail::pdqselect_loop( + begin, mid, end, comp, pdqsort_detail::log2(end - begin)); + } + + template + inline void pdqselect_branchless(Iter begin, Iter mid, Iter end) { + typedef typename std::iterator_traits::value_type T; + pdqselect_branchless(begin, mid, end, std::less()); + } + +#undef PDQSORT_PREFER_MOVE + +#endif + +} // namespace miniselect \ No newline at end of file diff --git a/src/python/index_wrappers/quake.py b/src/python/index_wrappers/quake.py index c7e9e19b..de012fec 100644 --- a/src/python/index_wrappers/quake.py +++ b/src/python/index_wrappers/quake.py @@ -149,6 +149,8 @@ def search( aps_flush_period_us=50, n_threads=1, parent=None, + sample_prefix=0, + sample_stride=5 ) -> Tuple[torch.Tensor, torch.Tensor]: """ Find the k-nearest neighbors of the query vectors. @@ -169,6 +171,8 @@ def search( search_params.aps_flush_period_us = aps_flush_period_us search_params.k = k search_params.num_threads = n_threads + search_params.sample_prefix = sample_prefix + search_params.sample_stride = sample_stride if parent is not None: search_params.parent_params = quake.SearchParams() diff --git a/src/python/workload_generator.py b/src/python/workload_generator.py index f390aad7..ab1722b1 100644 --- a/src/python/workload_generator.py +++ b/src/python/workload_generator.py @@ -479,17 +479,43 @@ def evaluate_workload(self, *, elif op_type == "query": qs = queries[ids] t0 = time.perf_counter() + t_infos = [] if batch: sr = index.search(qs, **search_params) pred_ids = sr.ids else: - pred_ids = torch.cat([ - index.search(q.unsqueeze(0), **search_params).ids - for q in qs - ]) + p = [] + for q in qs: + sr = index.search(q.unsqueeze(0), **search_params) + p.append(sr.ids) + t_infos.append(sr.timing_info) + pred_ids = torch.cat(p) + # pred_ids = torch.cat([ + # index.search(q.unsqueeze(0), **search_params).ids + # for q in qs + # ]) latency_ms = (time.perf_counter() - t0) * 1e3 gt_ids = torch.load(self.ops_dir / f"{op_id}_gt_ids.pt", weights_only=True) + + total_parent_time = 0 + total_time = 0 + total_boundary_time = 0 + total_aps_time = 0 + total_scan_time = 0 + + for t_info in t_infos: + total_parent_time += t_info.parent_info.total_time_ns / 1e6 + total_time += t_info.total_time_ns / 1e6 + total_boundary_time += t_info.boundary_distance_time_ns / 1e6 + total_aps_time += t_info.aps_time_ns / 1e6 + total_scan_time += t_info.scan_time_ns / 1e6 + + print(f" | parent {total_parent_time:.2f} ms" + f" | total {total_time:.2f} ms" + f" | boundary {total_boundary_time:.2f} ms" + f" | aps {total_aps_time:.2f} ms" + f" | scan {total_scan_time:.2f} ms") recall = compute_recall(pred_ids, gt_ids, search_params["k"]).mean().item() op["recall"] = recall diff --git a/test/cpp/benchmark.cpp b/test/cpp/benchmark.cpp index f5280166..6e7774b5 100644 --- a/test/cpp/benchmark.cpp +++ b/test/cpp/benchmark.cpp @@ -29,9 +29,9 @@ using torch::Tensor; static const int64_t DIM = 128; static const int64_t NUM_VECTORS = 100000; // number of database vectors static const int64_t N_LIST = 1000; // number of clusters for IVF -static const int64_t NUM_QUERIES = 10; // number of queries for search benchmark -static const int64_t K = 10; // top-K neighbors -static const int64_t N_PROBE = 12; // number of probes for IVF +static const int64_t NUM_QUERIES = 10000; // number of queries for search benchmark +static const int64_t K = 1000; // top-K neighbors +static const int64_t N_PROBE = 10; // number of probes for IVF static const int64_t N_WORKERS = 12; // number of workers for parallel query coordinator // Helper functions to generate random data and sequential IDs diff --git a/test/experiments/osdi2025/kick_the_tires/configs/sift1m.yaml b/test/experiments/osdi2025/kick_the_tires/configs/sift1m.yaml index 5a2974e8..352627ec 100644 --- a/test/experiments/osdi2025/kick_the_tires/configs/sift1m.yaml +++ b/test/experiments/osdi2025/kick_the_tires/configs/sift1m.yaml @@ -18,30 +18,34 @@ workload_generator: query_cluster_sample_distribution: uniform seed: 9299 indexes: - - name: Quake + - name: Quake10000 index: Quake build_params: - nc: 1000 + nc: 10000 num_workers: 0 search_params: k: 10 +# nprobe: 10 recall_target: .9 - - name: IVF - index: IVF + initial_search_fraction: 0.25 + - name: Quake10000_sample + index: Quake build_params: - nc: 1000 + nc: 10000 + num_workers: 0 search_params: - nprobe: 15 k: 10 + recall_target: .9 + initial_search_fraction: 0.1 plot: x_axis: operation_number # any column from the results CSV metrics: [latency_ms, recall] # any subset of stored metrics styles: # one entry per index name - Quake: + Quake10000: color: "#1f77b4" # default Matplotlib hex’s are fine linestyle: "-" # see plt.Line2D docs marker: "o" - Quake2: + Quake10000_sample: color: "#ff7f0e" # default Matplotlib hex’s are fine linestyle: "-" # see plt.Line2D docs marker: "o" @@ -52,4 +56,4 @@ plot: overwrite: workload: false index: false - results: true \ No newline at end of file + results: false \ No newline at end of file From 616a283b0ac4b24027ca3cc5a3b8ee382e5dc7ec Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 14 May 2025 21:52:53 -0500 Subject: [PATCH 035/323] update multi-query experiment --- test/experiments/osdi2025/numa_multi_query/run.py | 2 +- test/experiments/osdi2025/numa_single_query/run.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/experiments/osdi2025/numa_multi_query/run.py b/test/experiments/osdi2025/numa_multi_query/run.py index 12b95b30..0fd77d8b 100644 --- a/test/experiments/osdi2025/numa_multi_query/run.py +++ b/test/experiments/osdi2025/numa_multi_query/run.py @@ -70,7 +70,7 @@ def run_experiment(cfg_path: str, output_dir: str): for batch_size in batch_sizes: print(f"NUMA={use_numa}, workers={nw}, batched={bs}, batch={batch_size}") idxm = QuakeWrapper() - idxm.load(str(idx_file), use_numa=use_numa, same_core=True, n_workers=nw) + idxm.load(str(idx_file), use_numa=use_numa, same_core=True, num_workers=nw) n_threads = 16 if nw == 0 else 1 # Warmup diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index f88c56c8..6993160e 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -54,7 +54,7 @@ def run_experiment(cfg_path: str, output_dir: str): for n_worker in n_workers: idx_mode = QuakeWrapper() - idx_mode.load(str(idx_file), use_numa=use_numa, same_core=True, n_workers=n_worker) + idx_mode.load(str(idx_file), use_numa=use_numa, same_core=True, num_workers=n_worker) print(f"Threads: {n_worker}") # warm‑up From ab793e1b3b76fc3d39d557bbeef0c63646c36739 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 14 May 2025 22:44:16 -0500 Subject: [PATCH 036/323] update multi-query experiment --- .../configs/msturing10m.yaml | 15 ++ .../numa_single_query/configs/sift1m.yaml | 44 ++++- .../osdi2025/numa_single_query/run.py | 177 ++++++++++-------- 3 files changed, 155 insertions(+), 81 deletions(-) create mode 100644 test/experiments/osdi2025/numa_single_query/configs/msturing10m.yaml diff --git a/test/experiments/osdi2025/numa_single_query/configs/msturing10m.yaml b/test/experiments/osdi2025/numa_single_query/configs/msturing10m.yaml new file mode 100644 index 00000000..327e20ba --- /dev/null +++ b/test/experiments/osdi2025/numa_single_query/configs/msturing10m.yaml @@ -0,0 +1,15 @@ +# existing keys... +dataset: + name: sift1m + num_queries: 100 + k: 10 + nprobe: 100 + +n_workers: [0,1,2,4,8,16] + +# new keys: +trials: 5 +warmup: 10 + +output: + results_csv: numa_single_query_results.csv \ No newline at end of file diff --git a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml index 327e20ba..07646b6a 100644 --- a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml @@ -1,15 +1,49 @@ -# existing keys... dataset: name: sift1m num_queries: 100 k: 10 - nprobe: 100 -n_workers: [0,1,2,4,8,16] - -# new keys: trials: 5 warmup: 10 +indexes: + - name: Quake-1worker + index: Quake + build_params: + nc: 4096 + metric: l2 + num_workers: 1 + use_numa: false + search_params: + nprobe: 100 + + - name: Quake-4worker + index: Quake + build_params: + nc: 4096 + metric: l2 + num_workers: 4 + use_numa: false + search_params: + nprobe: 100 + + - name: Quake-16worker + index: Quake + build_params: + nc: 4096 + metric: l2 + num_workers: 16 + use_numa: false + search_params: + nprobe: 100 + + - name: FaissIVF + index: IVF + build_params: + nc: 4096 + metric: l2 + search_params: + nprobe: 100 + output: results_csv: numa_single_query_results.csv \ No newline at end of file diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index 6993160e..b04a196d 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -1,10 +1,4 @@ -#!/usr/bin/env python -""" -NUMA single‑query latency experiment for Quake. -Reads a config.yaml, writes results.csv to output_dir, then plots -thread‑vs‑latency with error bars for NUMA/no‑NUMA. -""" - +#!/usr/bin/env python3 import yaml import numpy as np import torch @@ -13,93 +7,124 @@ from pathlib import Path from quake.datasets.ann_datasets import load_dataset +from quake.index_wrappers.faiss_ivf import FaissIVF from quake.index_wrappers.quake import QuakeWrapper +INDEX_CLASSES = { + "Quake": QuakeWrapper, + "IVF": FaissIVF, + # Extend as needed +} + +def build_and_save_index(index_class, build_params, base_vecs, index_file): + idx = index_class() + params = dict(build_params) + if "nc" not in params: + params["nc"] = int(np.sqrt(base_vecs.shape[0])) + idx.build(base_vecs, **params) + idx.save(str(index_file)) + def run_experiment(cfg_path: str, output_dir: str): - # 1) Load config cfg = yaml.safe_load(Path(cfg_path).read_text()) ds = cfg["dataset"] - n_workers = cfg["n_workers"] - nprobe = ds["nprobe"] + queries_n = ds["num_queries"] k = ds["k"] - num_q = ds["num_queries"] - trials = cfg.get("trials", 5) # default 5 - warmup = cfg.get("warmup", 10) # default 10 + trials = cfg.get("trials", 5) + warmup = cfg.get("warmup", 10) + indexes_cfg = cfg["indexes"] csv_name = cfg.get("output", {}).get("results_csv", "numa_results.csv") out_dir = Path(output_dir); out_dir.mkdir(parents=True, exist_ok=True) - # 2) Load data print(f"Loading dataset '{ds['name']}'...") base_vecs, queries, _ = load_dataset(ds["name"]) - queries = queries[:num_q] - - # 3) Build index once - idx_file = out_dir / "quake_index.bin" - if not idx_file.exists(): - print("Building Quake index...") - idx = QuakeWrapper() - nc = int(np.sqrt(base_vecs.shape[0])) - idx.build(base_vecs, nc=nc, metric="l2", num_workers=0) - idx.save(str(idx_file)) - print(f"Index saved at {idx_file}") - - - # 4) Benchmark: warmup + trials - rows = [] - for use_numa in [False, True]: - mode = "NUMA" if use_numa else "no‑NUMA" - print(f"\n--- {mode} benchmarking ---") - - for n_worker in n_workers: - - idx_mode = QuakeWrapper() - idx_mode.load(str(idx_file), use_numa=use_numa, same_core=True, num_workers=n_worker) - - print(f"Threads: {n_worker}") - # warm‑up - for i in range(min(warmup, len(queries))): - q = queries[i].unsqueeze(0).float() - idx_mode.search(q, k, batched_scan=False, nprobe=nprobe, n_threads=n_worker) - - trial_means = [] - for t in range(trials): - lats = [] - for q_vec in queries: - q = q_vec.unsqueeze(0).float() - res = idx_mode.search( - q, k, - batched_scan=False, - nprobe=nprobe, - ) - ti = res.timing_info + queries = queries[:queries_n] + + all_rows = [] + + for idx_cfg in indexes_cfg: + idx_name = idx_cfg["name"] + idx_type = idx_cfg["index"] + build_params = idx_cfg.get("build_params", {}) + search_params = idx_cfg.get("search_params", {}) + IndexClass = INDEX_CLASSES.get(idx_type) + if IndexClass is None: + print(f"Unknown index type: {idx_type}") + continue + + idx_file = out_dir / f"{idx_name}_index.bin" + if not idx_file.exists(): + print(f"Building {idx_name} index...") + build_and_save_index(IndexClass, build_params, base_vecs, idx_file) + print(f"Index saved at {idx_file}") + + print(f"\n--- {idx_name} ---") + + # Prepare load arguments per index type + if idx_type == "Quake": + load_kwargs = {} + if "use_numa" in build_params: + load_kwargs["use_numa"] = build_params["use_numa"] + if "num_workers" in build_params: + load_kwargs["num_workers"] = build_params["num_workers"] + idx = IndexClass() + idx.load(str(idx_file), **load_kwargs) + else: + idx = IndexClass() + idx.load(str(idx_file)) + + nprobe = search_params.get("nprobe", 100) + + # warm-up + for i in range(min(warmup, len(queries))): + q = queries[i].unsqueeze(0).float() + idx.search(q, k, batched_scan=False, nprobe=nprobe) + + trial_means = [] + for t in range(trials): + lats = [] + for q_vec in queries: + q = q_vec.unsqueeze(0).float() + res = idx.search( + q, k, + batched_scan=False, + nprobe=nprobe + ) + ti = getattr(res, "timing_info", None) + if ti and hasattr(ti, "total_time_ns"): lats.append(ti.total_time_ns / 1e6) - mean_t = float(np.mean(lats)) - trial_means.append(mean_t) - print(f" Trial {t+1}/{trials}: {mean_t:.2f} ms") - - mean_lat = float(np.mean(trial_means)) - std_lat = float(np.std(trial_means)) - rows.append({ - "numa_enabled": use_numa, - "n_worker": n_worker, - "mean_latency_ms": mean_lat, - "std_latency_ms": std_lat, - }) - - # 5) Save CSV - df = pd.DataFrame(rows) + elif hasattr(res, "latency_ms"): + lats.append(res.latency_ms) + else: + raise RuntimeError("No timing info found in search result") + mean_t = float(np.mean(lats)) + trial_means.append(mean_t) + print(f" Trial {t+1}/{trials}: {mean_t:.2f} ms") + + mean_lat = float(np.mean(trial_means)) + std_lat = float(np.std(trial_means)) + # Pull out n_workers for grouping if present, else use name + n_workers_val = build_params.get("num_workers", None) + all_rows.append({ + "index": idx_name, + "n_workers": n_workers_val, + "mean_latency_ms": mean_lat, + "std_latency_ms": std_lat, + }) + + # Save CSV + df = pd.DataFrame(all_rows) out_csv = out_dir / csv_name df.to_csv(out_csv, index=False) print(f"\nResults written to {out_csv}") - # 6) Plot with error bars + # Plot plt.figure() - for flag in df["numa_enabled"].unique(): - subset = df[df["numa_enabled"] == flag] - label = "NUMA" if flag else "no‑NUMA" + for idx_name in df["index"].unique(): + subset = df[df["index"] == idx_name] + label = f"{idx_name}" if subset["n_workers"].isnull().all() else f"{idx_name} (n_workers={subset['n_workers'].iloc[0]})" plt.errorbar( - subset["n_worker"], + subset["n_workers"] if "n_workers" in subset else subset.index, subset["mean_latency_ms"], yerr=subset["std_latency_ms"], marker="o", @@ -109,7 +134,7 @@ def run_experiment(cfg_path: str, output_dir: str): plt.xscale("symlog", base=2) plt.xlabel("Num Workers") plt.ylabel("Mean Latency (ms)") - plt.title("NUMA Single‑Query Latency") + plt.title("Single‑Query Latency (per-index)") plt.legend() plot_file = out_dir / f"{out_csv.stem}_latency.png" plt.tight_layout() From 6fa1e94f4c08be184d6ae3083fd8750e24970ed8 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 14 May 2025 22:45:28 -0500 Subject: [PATCH 037/323] update multi-query experiment --- src/python/index_wrappers/quake.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/python/index_wrappers/quake.py b/src/python/index_wrappers/quake.py index de012fec..2fde67a9 100644 --- a/src/python/index_wrappers/quake.py +++ b/src/python/index_wrappers/quake.py @@ -69,6 +69,7 @@ def build( code_size: int = 8, parent=None, use_gpu=False, + use_numa=False, gpu_batch_size=100000, gpu_sample_size=1000000 ): @@ -93,6 +94,7 @@ def build( build_params.metric = metric build_params.nlist = nc build_params.num_workers = num_workers + build_params.use_numa = use_numa if parent is not None: build_params.parent_params = quake.IndexBuildParams() From 7ccce9593d14ae2bb16b8049b2b7b78ca30b5017 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 14 May 2025 22:47:18 -0500 Subject: [PATCH 038/323] update multi-query experiment --- src/cpp/bindings/wrap.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cpp/bindings/wrap.cpp b/src/cpp/bindings/wrap.cpp index b5c0d589..35c98e3d 100644 --- a/src/cpp/bindings/wrap.cpp +++ b/src/cpp/bindings/wrap.cpp @@ -148,6 +148,8 @@ PYBIND11_MODULE(_bindings, m) { (std::string("Number of workers. default = ") + std::to_string(DEFAULT_NUM_WORKERS)).c_str()) .def_readwrite("parent_params", &IndexBuildParams::parent_params, "Parameters for the parent index, if any.") + .def_readwrite("use_numa", &IndexBuildParams::use_numa, + (std::string("Flag to use NUMA for index building. default = ") + std::to_string(false)).c_str()) .def_readwrite("use_gpu", &IndexBuildParams::use_gpu, (std::string("Flag to use GPU for index building. default = ") + std::to_string(false)).c_str()) .def_readwrite("gpu_batch_size", &IndexBuildParams::gpu_batch_size, From 5fc80475fe42386ddaa82567f1cde9bd24a05515 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 14 May 2025 22:49:21 -0500 Subject: [PATCH 039/323] update multi-query experiment --- .../numa_single_query/configs/sift1m.yaml | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml index 07646b6a..69270e18 100644 --- a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml @@ -10,7 +10,7 @@ indexes: - name: Quake-1worker index: Quake build_params: - nc: 4096 + nc: 1000 metric: l2 num_workers: 1 use_numa: false @@ -20,7 +20,7 @@ indexes: - name: Quake-4worker index: Quake build_params: - nc: 4096 + nc: 1000 metric: l2 num_workers: 4 use_numa: false @@ -30,17 +30,47 @@ indexes: - name: Quake-16worker index: Quake build_params: - nc: 4096 + nc: 1000 metric: l2 num_workers: 16 use_numa: false search_params: nprobe: 100 + - name: Quake-1worker + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 1 + use_numa: true + search_params: + nprobe: 100 + + - name: Quake-4worker + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 4 + use_numa: true + search_params: + nprobe: 100 + + - name: Quake-16worker + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 16 + use_numa: true + search_params: + nprobe: 100 + - name: FaissIVF index: IVF build_params: - nc: 4096 + nc: 1000 metric: l2 search_params: nprobe: 100 From b6f5e5ee607823cd65aec6c3b6b642b2cbdc1ad5 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 14 May 2025 22:54:31 -0500 Subject: [PATCH 040/323] update multi-query experiment --- .../numa_single_query/configs/sift1m.yaml | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml index 69270e18..89bdd667 100644 --- a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml @@ -7,7 +7,7 @@ trials: 5 warmup: 10 indexes: - - name: Quake-1worker + - name: Quake_1 index: Quake build_params: nc: 1000 @@ -15,9 +15,9 @@ indexes: num_workers: 1 use_numa: false search_params: - nprobe: 100 + nprobe: 1000 - - name: Quake-4worker + - name: Quake_4 index: Quake build_params: nc: 1000 @@ -25,9 +25,9 @@ indexes: num_workers: 4 use_numa: false search_params: - nprobe: 100 + nprobe: 1000 - - name: Quake-16worker + - name: Quake_16 index: Quake build_params: nc: 1000 @@ -35,9 +35,9 @@ indexes: num_workers: 16 use_numa: false search_params: - nprobe: 100 + nprobe: 1000 - - name: Quake-1worker + - name: Quake_1_numa index: Quake build_params: nc: 1000 @@ -45,9 +45,9 @@ indexes: num_workers: 1 use_numa: true search_params: - nprobe: 100 + nprobe: 1000 - - name: Quake-4worker + - name: Quake_4_numa index: Quake build_params: nc: 1000 @@ -55,9 +55,9 @@ indexes: num_workers: 4 use_numa: true search_params: - nprobe: 100 + nprobe: 1000 - - name: Quake-16worker + - name: Quake_16_numa index: Quake build_params: nc: 1000 @@ -65,7 +65,7 @@ indexes: num_workers: 16 use_numa: true search_params: - nprobe: 100 + nprobe: 1000 - name: FaissIVF index: IVF @@ -73,7 +73,7 @@ indexes: nc: 1000 metric: l2 search_params: - nprobe: 100 + nprobe: 1000 output: results_csv: numa_single_query_results.csv \ No newline at end of file From f17f0830553f4aebb7c03fd0ff3a3095671b8431 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 14 May 2025 23:02:25 -0500 Subject: [PATCH 041/323] update multi-query experiment --- src/cpp/src/query_coordinator.cpp | 1 - src/python/index_wrappers/vamana.py | 4 +-- .../numa_single_query/configs/sift1m.yaml | 35 +++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 5483a4c7..a3b3bc3b 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -119,7 +119,6 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { // Shutdown signal: -1 indicates the worker should exit. if (job.partition_id == -1) { - std::cout << "[QueryCoordinator::partition_scan_worker_fn] Worker " << core_index << " exiting." << std::endl; break; } diff --git a/src/python/index_wrappers/vamana.py b/src/python/index_wrappers/vamana.py index fde8877e..7d2d6a82 100644 --- a/src/python/index_wrappers/vamana.py +++ b/src/python/index_wrappers/vamana.py @@ -53,9 +53,9 @@ def build( self.index = svs.DynamicVamana.build( parameters=parameters, data=vectors, ids=ids, distance_type=distance, num_threads=num_threads ) - self.index.search_window_size = 128 - def search(self, queries: torch.Tensor, k: int) -> Tuple[np.ndarray, np.ndarray]: + def search(self, queries: torch.Tensor, k: int, search_window_size: int) -> Tuple[np.ndarray, np.ndarray]: + self.index.search_window_size = search_window_size indices, distances = self.index.search(queries=to_numpy(queries).astype(np.float32), n_neighbors=k) return to_torch(indices.astype(np.int64)), to_torch(distances) diff --git a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml index 89bdd667..1f184fc4 100644 --- a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml @@ -75,5 +75,40 @@ indexes: search_params: nprobe: 1000 + - name: SCANN + index: SCANN + build_params: + num_leaves: 1000 + metric: l2 + search_params: + leaves_to_search: 1000 + + - name: FaissHNSW + index: HNSW + build_params: + m: 64 + ef_construction: 128 + metric: l2 + search_params: + ef_search: 32 + + - name: DiskANN + index: DiskANN + build_params: + complexity: 128, + graph_degree: 64 + metric: l2 + search_params: + complexity: 32 + + - name: SVS + index: SVS + build_params: + graph_max_degree: 64 + window_size: 128 + metric: l2 + search_params: + search_window_size: 32 + output: results_csv: numa_single_query_results.csv \ No newline at end of file From 56caaa7b01f7ffd8c25d7985d93a8d79852e8272 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 14 May 2025 23:12:27 -0500 Subject: [PATCH 042/323] update multi-query experiment --- .../numa_single_query/configs/sift1m.yaml | 4 +- .../osdi2025/numa_single_query/run.py | 96 ++++++++++++++----- 2 files changed, 77 insertions(+), 23 deletions(-) diff --git a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml index 1f184fc4..9d40ec14 100644 --- a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml @@ -1,3 +1,4 @@ +# numa_latency_experiment.yaml dataset: name: sift1m num_queries: 100 @@ -5,6 +6,7 @@ dataset: trials: 5 warmup: 10 +overwrite: false # Set to true to force all indexes to rerun indexes: - name: Quake_1 @@ -95,7 +97,7 @@ indexes: - name: DiskANN index: DiskANN build_params: - complexity: 128, + complexity: 128 graph_degree: 64 metric: l2 search_params: diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index b04a196d..5e079ddb 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -1,4 +1,15 @@ #!/usr/bin/env python3 +""" +NUMA Single-Query Latency Benchmark + +Benchmarks a suite of approximate nearest neighbor (ANN) indexes (Quake, Faiss-IVF, SCANN, HNSW, DiskANN, SVS, etc.) +for single-query latency under configurable build and search parameters. Results are cached and only recomputed if +the 'overwrite' flag is set in the configuration. Outputs a unified CSV and a latency plot per index. + +Usage: + python numa_latency_experiment.py numa_latency_experiment.yaml output_dir +""" + import yaml import numpy as np import torch @@ -8,18 +19,36 @@ from quake.datasets.ann_datasets import load_dataset from quake.index_wrappers.faiss_ivf import FaissIVF +from quake.index_wrappers.faiss_hnsw import FaissHNSW from quake.index_wrappers.quake import QuakeWrapper +# Placeholder index wrappers. Replace these with real implementations. +try: + from quake.index_wrappers.scann import Scann +except ImportError: + class ScannWrapper: pass +try: + from quake.index_wrappers.diskann import DiskANNDynamic +except ImportError: + class DiskANNWrapper: pass +try: + from quake.index_wrappers.vamana import Vamana +except ImportError: + class SVSWrapper: pass + INDEX_CLASSES = { "Quake": QuakeWrapper, "IVF": FaissIVF, - # Extend as needed + "SCANN": Scann, + "HNSW": FaissHNSW, + "DiskANN": DiskANNDynamic, + "SVS": Vamana, } def build_and_save_index(index_class, build_params, base_vecs, index_file): idx = index_class() params = dict(build_params) - if "nc" not in params: + if "nc" not in params and "num_leaves" not in params: params["nc"] = int(np.sqrt(base_vecs.shape[0])) idx.build(base_vecs, **params) idx.save(str(index_file)) @@ -33,10 +62,12 @@ def run_experiment(cfg_path: str, output_dir: str): warmup = cfg.get("warmup", 10) indexes_cfg = cfg["indexes"] csv_name = cfg.get("output", {}).get("results_csv", "numa_results.csv") + overwrite = cfg.get("overwrite", False) - out_dir = Path(output_dir); out_dir.mkdir(parents=True, exist_ok=True) + out_dir = Path(output_dir) + out_dir.mkdir(parents=True, exist_ok=True) - print(f"Loading dataset '{ds['name']}'...") + print(f"[INFO] Loading dataset '{ds['name']}'...") base_vecs, queries, _ = load_dataset(ds["name"]) queries = queries[:queries_n] @@ -49,16 +80,25 @@ def run_experiment(cfg_path: str, output_dir: str): search_params = idx_cfg.get("search_params", {}) IndexClass = INDEX_CLASSES.get(idx_type) if IndexClass is None: - print(f"Unknown index type: {idx_type}") + print(f"[WARN] Unknown index type: {idx_type}. Skipping.") continue + idx_csv = out_dir / f"{idx_name}_results.csv" idx_file = out_dir / f"{idx_name}_index.bin" + + if idx_csv.exists() and not overwrite: + print(f"[SKIP] {idx_name}: Results exist. Use overwrite: true to rerun.") + # For plotting, load mean/std for this index + df_idx = pd.read_csv(idx_csv) + all_rows.append(df_idx.iloc[0].to_dict()) + continue + if not idx_file.exists(): - print(f"Building {idx_name} index...") + print(f"[BUILD] {idx_name} index...") build_and_save_index(IndexClass, build_params, base_vecs, idx_file) - print(f"Index saved at {idx_file}") + print(f"[SAVE] Index saved at {idx_file}") - print(f"\n--- {idx_name} ---") + print(f"[RUN] {idx_name} ...") # Prepare load arguments per index type if idx_type == "Quake": @@ -73,13 +113,24 @@ def run_experiment(cfg_path: str, output_dir: str): idx = IndexClass() idx.load(str(idx_file)) - nprobe = search_params.get("nprobe", 100) - - # warm-up + # Dispatch search argument keys by index type + if idx_type == "SCANN": + search_args = {"leaves_to_search": search_params.get("leaves_to_search", 100)} + elif idx_type == "HNSW": + search_args = {"ef_search": search_params.get("ef_search", 32)} + elif idx_type == "DiskANN": + search_args = {"complexity": search_params.get("complexity", 32)} + elif idx_type == "SVS": + search_args = {"search_window_size": search_params.get("search_window_size", 32)} + else: # IVF, Quake, others + search_args = {"nprobe": search_params.get("nprobe", 100)} + + # Warmup for i in range(min(warmup, len(queries))): q = queries[i].unsqueeze(0).float() - idx.search(q, k, batched_scan=False, nprobe=nprobe) + idx.search(q, k, batched_scan=False, **search_args) + # Benchmark Trials trial_means = [] for t in range(trials): lats = [] @@ -88,7 +139,7 @@ def run_experiment(cfg_path: str, output_dir: str): res = idx.search( q, k, batched_scan=False, - nprobe=nprobe + **search_args ) ti = getattr(res, "timing_info", None) if ti and hasattr(ti, "total_time_ns"): @@ -96,27 +147,28 @@ def run_experiment(cfg_path: str, output_dir: str): elif hasattr(res, "latency_ms"): lats.append(res.latency_ms) else: - raise RuntimeError("No timing info found in search result") + raise RuntimeError(f"No timing info found in search result for {idx_name}") mean_t = float(np.mean(lats)) trial_means.append(mean_t) - print(f" Trial {t+1}/{trials}: {mean_t:.2f} ms") + print(f" [trial {t+1}/{trials}] {mean_t:.2f} ms") mean_lat = float(np.mean(trial_means)) std_lat = float(np.std(trial_means)) - # Pull out n_workers for grouping if present, else use name n_workers_val = build_params.get("num_workers", None) - all_rows.append({ + row = { "index": idx_name, "n_workers": n_workers_val, "mean_latency_ms": mean_lat, "std_latency_ms": std_lat, - }) + } + all_rows.append(row) + pd.DataFrame([row]).to_csv(idx_csv, index=False) - # Save CSV + # Save Unified CSV df = pd.DataFrame(all_rows) out_csv = out_dir / csv_name df.to_csv(out_csv, index=False) - print(f"\nResults written to {out_csv}") + print(f"\n[RESULT] Results written to {out_csv}") # Plot plt.figure() @@ -134,9 +186,9 @@ def run_experiment(cfg_path: str, output_dir: str): plt.xscale("symlog", base=2) plt.xlabel("Num Workers") plt.ylabel("Mean Latency (ms)") - plt.title("Single‑Query Latency (per-index)") + plt.title("Single-Query Latency (per-index)") plt.legend() plot_file = out_dir / f"{out_csv.stem}_latency.png" plt.tight_layout() plt.savefig(plot_file) - print(f"Plot saved to {plot_file}") \ No newline at end of file + print(f"[PLOT] Saved to {plot_file}") From 7a447fa5002232dd909508fafe716b70b0265561 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 14 May 2025 23:12:50 -0500 Subject: [PATCH 043/323] update multi-query experiment --- test/experiments/osdi2025/numa_single_query/run.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index 5e079ddb..70b2f3b0 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -26,15 +26,15 @@ try: from quake.index_wrappers.scann import Scann except ImportError: - class ScannWrapper: pass + class Scann: pass try: from quake.index_wrappers.diskann import DiskANNDynamic except ImportError: - class DiskANNWrapper: pass + class DiskANNDynamic: pass try: from quake.index_wrappers.vamana import Vamana except ImportError: - class SVSWrapper: pass + class Vamana: pass INDEX_CLASSES = { "Quake": QuakeWrapper, From c707a65c06b2053d287c0ae4ad0fa2740e5a4190 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 14 May 2025 23:16:48 -0500 Subject: [PATCH 044/323] update multi-query experiment --- test/experiments/osdi2025/numa_single_query/run.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index 70b2f3b0..4b5336ff 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -26,15 +26,15 @@ try: from quake.index_wrappers.scann import Scann except ImportError: - class Scann: pass + raise ImportError("SCANN wrapper not available. Please install the required package.") try: from quake.index_wrappers.diskann import DiskANNDynamic except ImportError: - class DiskANNDynamic: pass + raise ImportError("DiskANN wrapper not available. Please install the required package.") try: from quake.index_wrappers.vamana import Vamana except ImportError: - class Vamana: pass + raise ImportError("SVS wrapper not available. Please install the required package.") INDEX_CLASSES = { "Quake": QuakeWrapper, From b66d3b63e4f876fafc6d75ab490c90e84d64acf6 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 14 May 2025 23:48:56 -0500 Subject: [PATCH 045/323] update multi-query experiment --- src/python/index_wrappers/diskann.py | 6 ++++++ src/python/index_wrappers/faiss_hnsw.py | 6 ++++++ src/python/index_wrappers/scann.py | 6 ++++++ src/python/index_wrappers/vamana.py | 6 ++++++ test/experiments/osdi2025/numa_single_query/run.py | 1 - 5 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/python/index_wrappers/diskann.py b/src/python/index_wrappers/diskann.py index 9b0d834f..752e8ae6 100644 --- a/src/python/index_wrappers/diskann.py +++ b/src/python/index_wrappers/diskann.py @@ -190,3 +190,9 @@ def remove(self, ids: torch.Tensor, lazy: bool = True): def centroids(self) -> torch.Tensor | None: return super().centroids() + + def index_state(self) -> str: + return "" + + def maintenance(self): + pass \ No newline at end of file diff --git a/src/python/index_wrappers/faiss_hnsw.py b/src/python/index_wrappers/faiss_hnsw.py index 9fc7dcc2..c3ff9850 100644 --- a/src/python/index_wrappers/faiss_hnsw.py +++ b/src/python/index_wrappers/faiss_hnsw.py @@ -130,3 +130,9 @@ def remove(self, ids: torch.Tensor): """ # throw a runtime error raise RuntimeError("Faiss HNSW does not support removal of vectors.") + + def index_state(self) -> str: + return "" + + def maintenance(self): + pass \ No newline at end of file diff --git a/src/python/index_wrappers/scann.py b/src/python/index_wrappers/scann.py index 2b224026..751cc3f5 100644 --- a/src/python/index_wrappers/scann.py +++ b/src/python/index_wrappers/scann.py @@ -187,5 +187,11 @@ def load(self, filename: str): """ self.index = scann.scann_ops_pybind.load_searcher(str(filename)) + def index_state(self) -> str: + return self.index.config() + + def maintenance(self): + pass + def centroids(self) -> torch.Tensor | None: return super().centroids() diff --git a/src/python/index_wrappers/vamana.py b/src/python/index_wrappers/vamana.py index 7d2d6a82..31b91242 100644 --- a/src/python/index_wrappers/vamana.py +++ b/src/python/index_wrappers/vamana.py @@ -99,3 +99,9 @@ def load(self, directory: str, metrics: str = "ip"): def centroids(self) -> torch.Tensor | None: return super().centroids() + + def index_state(self) -> str: + return "" + + def maintenance(self): + pass \ No newline at end of file diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index 4b5336ff..031f366e 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -22,7 +22,6 @@ from quake.index_wrappers.faiss_hnsw import FaissHNSW from quake.index_wrappers.quake import QuakeWrapper -# Placeholder index wrappers. Replace these with real implementations. try: from quake.index_wrappers.scann import Scann except ImportError: From c5f6f190f2d9d65e44196c31ad0001dbaf43c32e Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 14 May 2025 23:53:21 -0500 Subject: [PATCH 046/323] update multi-query experiment --- test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml index 9d40ec14..18412dd6 100644 --- a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml @@ -81,7 +81,7 @@ indexes: index: SCANN build_params: num_leaves: 1000 - metric: l2 + metric: squared_l2 search_params: leaves_to_search: 1000 From bd17f80d93453e9da6fad8560c3076b2e7fbe37c Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 14 May 2025 23:54:07 -0500 Subject: [PATCH 047/323] update multi-query experiment --- test/experiments/osdi2025/numa_single_query/run.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index 031f366e..d6670bb2 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -127,7 +127,7 @@ def run_experiment(cfg_path: str, output_dir: str): # Warmup for i in range(min(warmup, len(queries))): q = queries[i].unsqueeze(0).float() - idx.search(q, k, batched_scan=False, **search_args) + idx.search(q, k, **search_args) # Benchmark Trials trial_means = [] @@ -137,7 +137,6 @@ def run_experiment(cfg_path: str, output_dir: str): q = q_vec.unsqueeze(0).float() res = idx.search( q, k, - batched_scan=False, **search_args ) ti = getattr(res, "timing_info", None) From b3aac5489b8d148c06363a1223494293f5d10d01 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 14 May 2025 23:56:15 -0500 Subject: [PATCH 048/323] update multi-query experiment --- src/python/index_wrappers/scann.py | 11 ++++++++--- src/python/index_wrappers/vamana.py | 8 ++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/python/index_wrappers/scann.py b/src/python/index_wrappers/scann.py index 751cc3f5..50d58f87 100644 --- a/src/python/index_wrappers/scann.py +++ b/src/python/index_wrappers/scann.py @@ -7,8 +7,9 @@ import torch from quake.index_wrappers.wrapper import IndexWrapper +from quake import SearchTimingInfo from quake.utils import to_numpy, to_torch - +import time class Scann(IndexWrapper): index: scann.scann_ops_pybind.ScannSearcher @@ -129,6 +130,8 @@ def search( if not n_threads == 0: self.index.set_num_threads(n_threads) + start_time = time.time() + query = to_numpy(query) indices, distances = self.index.search_batched( query, @@ -137,8 +140,10 @@ def search( pre_reorder_num_neighbors=pre_reorder_num_neighbors, ) indices = np.array(indices) - - return to_torch(indices), to_torch(distances) + end_time = time.time() + timing_info = SearchTimingInfo() + timing_info.total_time_ns = int((end_time - start_time) * 1e9) + return to_torch(indices), to_torch(distances), timing_info def add(self, vectors: torch.Tensor, ids: Optional[torch.Tensor] = None): """ diff --git a/src/python/index_wrappers/vamana.py b/src/python/index_wrappers/vamana.py index 31b91242..138a2cb5 100644 --- a/src/python/index_wrappers/vamana.py +++ b/src/python/index_wrappers/vamana.py @@ -6,6 +6,8 @@ from quake.index_wrappers.wrapper import IndexWrapper from quake.utils import to_numpy, to_path, to_torch +from quake import SearchTimingInfo +import time class Vamana(IndexWrapper): @@ -55,8 +57,14 @@ def build( ) def search(self, queries: torch.Tensor, k: int, search_window_size: int) -> Tuple[np.ndarray, np.ndarray]: + + start_time = time.time() self.index.search_window_size = search_window_size indices, distances = self.index.search(queries=to_numpy(queries).astype(np.float32), n_neighbors=k) + + end_time = time.time() + timing_info = SearchTimingInfo() + timing_info.total_time_ns = int((end_time - start_time) * 1e9) return to_torch(indices.astype(np.int64)), to_torch(distances) def add(self, vectors: torch.Tensor, ids: Optional[torch.Tensor] = None): From eafc190bd928ef2cbaa86682446f98c208ec5877 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 14 May 2025 23:58:58 -0500 Subject: [PATCH 049/323] update multi-query experiment --- src/python/index_wrappers/diskann.py | 9 +++++++-- src/python/index_wrappers/faiss_hnsw.py | 12 ++++++++---- src/python/index_wrappers/scann.py | 10 ++++++++-- src/python/index_wrappers/vamana.py | 11 +++++++++-- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/python/index_wrappers/diskann.py b/src/python/index_wrappers/diskann.py index 752e8ae6..7bfb22ec 100644 --- a/src/python/index_wrappers/diskann.py +++ b/src/python/index_wrappers/diskann.py @@ -6,7 +6,7 @@ import numpy as np import torch -from quake import SearchTimingInfo +from quake import SearchTimingInfo, SearchResult from quake.index_wrappers.wrapper import IndexWrapper from quake.utils import to_numpy, to_torch @@ -110,7 +110,12 @@ def search( indices = indices - 1 # ids are 1-indexed distances = to_torch(distances) - return indices, distances, timing_info + search_result = SearchResult() + search_result.ids = to_torch(indices) + search_result.distances = to_torch(distances) + search_result.timing_info = timing_info + + return search_result def save(self, path: str): """ diff --git a/src/python/index_wrappers/faiss_hnsw.py b/src/python/index_wrappers/faiss_hnsw.py index c3ff9850..c9438d30 100644 --- a/src/python/index_wrappers/faiss_hnsw.py +++ b/src/python/index_wrappers/faiss_hnsw.py @@ -4,7 +4,7 @@ import faiss import torch -from quake import SearchTimingInfo +from quake import SearchTimingInfo, SearchResult from quake.index_wrappers.faiss_ivf import metric_str_to_faiss from quake.index_wrappers.wrapper import IndexWrapper from quake.utils import to_numpy, to_torch @@ -86,10 +86,14 @@ def search(self, query: torch.Tensor, k: int, ef_search: int = 16) -> Tuple[torc end = time.time() timing_info.total_time_us = int((end - start) * 1e6) - distances = to_torch(distances) - indices = to_torch(indices) - return indices, distances, timing_info + search_result = SearchResult() + search_result.ids = to_torch(indices) + search_result.distances = to_torch(distances) + search_result.timing_info = timing_info + + return search_result + def save(self, filename: str): """ diff --git a/src/python/index_wrappers/scann.py b/src/python/index_wrappers/scann.py index 50d58f87..1c437d5f 100644 --- a/src/python/index_wrappers/scann.py +++ b/src/python/index_wrappers/scann.py @@ -7,7 +7,7 @@ import torch from quake.index_wrappers.wrapper import IndexWrapper -from quake import SearchTimingInfo +from quake import SearchTimingInfo, SearchResult from quake.utils import to_numpy, to_torch import time @@ -143,7 +143,13 @@ def search( end_time = time.time() timing_info = SearchTimingInfo() timing_info.total_time_ns = int((end_time - start_time) * 1e9) - return to_torch(indices), to_torch(distances), timing_info + + search_result = SearchResult() + search_result.ids = to_torch(indices) + search_result.distances = to_torch(distances) + search_result.timing_info = timing_info + + return search_result def add(self, vectors: torch.Tensor, ids: Optional[torch.Tensor] = None): """ diff --git a/src/python/index_wrappers/vamana.py b/src/python/index_wrappers/vamana.py index 138a2cb5..0d880379 100644 --- a/src/python/index_wrappers/vamana.py +++ b/src/python/index_wrappers/vamana.py @@ -6,7 +6,7 @@ from quake.index_wrappers.wrapper import IndexWrapper from quake.utils import to_numpy, to_path, to_torch -from quake import SearchTimingInfo +from quake import SearchTimingInfo, SearchResult import time @@ -65,7 +65,14 @@ def search(self, queries: torch.Tensor, k: int, search_window_size: int) -> Tupl end_time = time.time() timing_info = SearchTimingInfo() timing_info.total_time_ns = int((end_time - start_time) * 1e9) - return to_torch(indices.astype(np.int64)), to_torch(distances) + + search_result = SearchResult() + search_result.ids = to_torch(indices) + search_result.distances = to_torch(distances) + search_result.timing_info = timing_info + + return search_result + def add(self, vectors: torch.Tensor, ids: Optional[torch.Tensor] = None): if ids is None: From 35a252ccf8e3ef19f1dbeaedc75f5676f3a2ab3e Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 00:01:32 -0500 Subject: [PATCH 050/323] update multi-query experiment --- test/experiments/osdi2025/numa_single_query/run.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index d6670bb2..f1a0c8e8 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -47,8 +47,6 @@ def build_and_save_index(index_class, build_params, base_vecs, index_file): idx = index_class() params = dict(build_params) - if "nc" not in params and "num_leaves" not in params: - params["nc"] = int(np.sqrt(base_vecs.shape[0])) idx.build(base_vecs, **params) idx.save(str(index_file)) From 90afadaf3db17038f1d7919693283a66d75769eb Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 00:16:56 -0500 Subject: [PATCH 051/323] update multi-query experiment --- src/python/index_wrappers/diskann.py | 2 +- src/python/index_wrappers/faiss_hnsw.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/python/index_wrappers/diskann.py b/src/python/index_wrappers/diskann.py index 7bfb22ec..e1ae89f3 100644 --- a/src/python/index_wrappers/diskann.py +++ b/src/python/index_wrappers/diskann.py @@ -105,7 +105,7 @@ def search( query, k_neighbors=k, complexity=complexity, num_threads=num_threads ) end = time.time() - timing_info.total_time_us = int((end - start) * 1e6) + timing_info.total_time_ns = int((end - start) * 1e9) indices = to_torch(indices.astype(np.int64)) indices = indices - 1 # ids are 1-indexed distances = to_torch(distances) diff --git a/src/python/index_wrappers/faiss_hnsw.py b/src/python/index_wrappers/faiss_hnsw.py index c9438d30..eed4a1ea 100644 --- a/src/python/index_wrappers/faiss_hnsw.py +++ b/src/python/index_wrappers/faiss_hnsw.py @@ -85,7 +85,7 @@ def search(self, query: torch.Tensor, k: int, ef_search: int = 16) -> Tuple[torc distances, indices = self.index.search(query, k) end = time.time() - timing_info.total_time_us = int((end - start) * 1e6) + timing_info.total_time_ns = int((end - start) * 1e9) search_result = SearchResult() search_result.ids = to_torch(indices) From ad697b43566bddf6f5f8b0e7c34998414d561a21 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 00:20:50 -0500 Subject: [PATCH 052/323] update multi-query experiment --- src/python/index_wrappers/diskann.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/python/index_wrappers/diskann.py b/src/python/index_wrappers/diskann.py index e1ae89f3..21878287 100644 --- a/src/python/index_wrappers/diskann.py +++ b/src/python/index_wrappers/diskann.py @@ -5,6 +5,7 @@ import diskannpy as dap import numpy as np import torch +from pathlib import Path from quake import SearchTimingInfo, SearchResult from quake.index_wrappers.wrapper import IndexWrapper @@ -124,10 +125,10 @@ def save(self, path: str): :param path: The path to save the index to. :type path: str """ - # assert self.index is not None - # if not Path(path).exists(): - # Path(path).mkdir(exist_ok=True) - # self.index.save(path) + assert self.index is not None + if not Path(path).exists(): + Path(path).mkdir(exist_ok=True) + self.index.save(path) # TODO: save/load index raise RuntimeError("DiskANNDynamic.save() not implemented") @@ -146,16 +147,16 @@ def load( :param path: The path to load the index from. :type path: str """ - # self.index = dap.DynamicMemoryIndex.from_file( - # index_directory=path, - # max_vectors=max_vectors, - # complexity=complexity, - # graph_degree=graph_degree, - # num_threads=num_threads, - # ) + self.index = dap.DynamicMemoryIndex.from_file( + index_directory=path, + max_vectors=max_vectors, + complexity=complexity, + graph_degree=graph_degree, + num_threads=num_threads, + ) - # TODO: save/load index - raise RuntimeError("DiskANNDynamic.save() not implemented") + # # TODO: save/load index + # raise RuntimeError("DiskANNDynamic.save() not implemented") def add(self, vectors: torch.Tensor, ids: torch.Tensor, num_threads: int = 0): """ From 9f08841dc97f1c17876d3339499d046ec7085176 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 00:28:32 -0500 Subject: [PATCH 053/323] update multi-query experiment --- src/python/index_wrappers/diskann.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/python/index_wrappers/diskann.py b/src/python/index_wrappers/diskann.py index 21878287..7cef67fd 100644 --- a/src/python/index_wrappers/diskann.py +++ b/src/python/index_wrappers/diskann.py @@ -130,9 +130,6 @@ def save(self, path: str): Path(path).mkdir(exist_ok=True) self.index.save(path) - # TODO: save/load index - raise RuntimeError("DiskANNDynamic.save() not implemented") - def load( self, path: str, From c3aa79a61d35cc80d2ec5d6002f090cf23280b9d Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 00:36:21 -0500 Subject: [PATCH 054/323] update multi-query experiment --- test/experiments/osdi2025/numa_single_query/run.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index f1a0c8e8..f349983a 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -106,6 +106,9 @@ def run_experiment(cfg_path: str, output_dir: str): load_kwargs["num_workers"] = build_params["num_workers"] idx = IndexClass() idx.load(str(idx_file), **load_kwargs) + elif idx_type == "DiskANN": + idx = IndexClass() + idx.load(str(idx_file), **build_params) else: idx = IndexClass() idx.load(str(idx_file)) From 5a1a438b9a282abf9cc15a7095944267188e6553 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 00:37:38 -0500 Subject: [PATCH 055/323] update multi-query experiment --- test/experiments/osdi2025/numa_single_query/run.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index f349983a..0807e083 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -108,6 +108,8 @@ def run_experiment(cfg_path: str, output_dir: str): idx.load(str(idx_file), **load_kwargs) elif idx_type == "DiskANN": idx = IndexClass() + # remove metric from build_params + build_params.pop("metric", None) idx.load(str(idx_file), **build_params) else: idx = IndexClass() From 6ef5ac9aa3049e5dcf867bb69e01949d18801807 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 00:38:28 -0500 Subject: [PATCH 056/323] update multi-query experiment --- test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml index 18412dd6..46ee1db9 100644 --- a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml @@ -107,6 +107,7 @@ indexes: index: SVS build_params: graph_max_degree: 64 + alpha: 1.1 window_size: 128 metric: l2 search_params: From f6445e705f3b75af52a45e6708b72ad9243f6344 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 00:44:16 -0500 Subject: [PATCH 057/323] update multi-query experiment --- .../osdi2025/numa_single_query/run.py | 99 ++++++++++++++++--- 1 file changed, 83 insertions(+), 16 deletions(-) diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index 0807e083..96c720ec 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -1,10 +1,11 @@ #!/usr/bin/env python3 """ -NUMA Single-Query Latency Benchmark +NUMA Single-Query Latency and Recall Benchmark -Benchmarks a suite of approximate nearest neighbor (ANN) indexes (Quake, Faiss-IVF, SCANN, HNSW, DiskANN, SVS, etc.) -for single-query latency under configurable build and search parameters. Results are cached and only recomputed if -the 'overwrite' flag is set in the configuration. Outputs a unified CSV and a latency plot per index. +Benchmarks a suite of ANN indexes (Quake, Faiss-IVF, SCANN, HNSW, DiskANN, SVS, etc.) +for single-query latency and recall@k under configurable build and search parameters. +Results are cached and only recomputed if the 'overwrite' flag is set in the configuration. +Outputs a unified CSV and a latency plot per index. Usage: python numa_latency_experiment.py numa_latency_experiment.yaml output_dir @@ -44,6 +45,32 @@ "SVS": Vamana, } +def extract_indices(res): + """Helper to extract predicted indices from result.""" + if hasattr(res, "I"): + return res.I + if hasattr(res, "indices"): + return res.indices + raise RuntimeError("Cannot extract predicted indices from search result.") + +def compute_recall_at_k(pred, gt, k): + """ + pred: [num_queries, k] predicted indices + gt: [num_queries, ...] ground truth indices + Returns recall@k + """ + # Faiss GT may be shape [num_queries, k'] or [num_queries] + if gt.ndim == 1: + gt = gt[:, None] + matches = 0 + num = pred.shape[0] + for i in range(num): + pred_set = set(pred[i]) + gt_set = set(gt[i]) + matches += len(pred_set & gt_set) + recall = matches / (num * min(k, gt.shape[1])) + return recall + def build_and_save_index(index_class, build_params, base_vecs, index_file): idx = index_class() params = dict(build_params) @@ -65,8 +92,9 @@ def run_experiment(cfg_path: str, output_dir: str): out_dir.mkdir(parents=True, exist_ok=True) print(f"[INFO] Loading dataset '{ds['name']}'...") - base_vecs, queries, _ = load_dataset(ds["name"]) + base_vecs, queries, gt = load_dataset(ds["name"]) queries = queries[:queries_n] + gt = gt[:queries_n] if gt is not None else None all_rows = [] @@ -85,7 +113,6 @@ def run_experiment(cfg_path: str, output_dir: str): if idx_csv.exists() and not overwrite: print(f"[SKIP] {idx_name}: Results exist. Use overwrite: true to rerun.") - # For plotting, load mean/std for this index df_idx = pd.read_csv(idx_csv) all_rows.append(df_idx.iloc[0].to_dict()) continue @@ -97,7 +124,6 @@ def run_experiment(cfg_path: str, output_dir: str): print(f"[RUN] {idx_name} ...") - # Prepare load arguments per index type if idx_type == "Quake": load_kwargs = {} if "use_numa" in build_params: @@ -115,7 +141,6 @@ def run_experiment(cfg_path: str, output_dir: str): idx = IndexClass() idx.load(str(idx_file)) - # Dispatch search argument keys by index type if idx_type == "SCANN": search_args = {"leaves_to_search": search_params.get("leaves_to_search", 100)} elif idx_type == "HNSW": @@ -132,16 +157,16 @@ def run_experiment(cfg_path: str, output_dir: str): q = queries[i].unsqueeze(0).float() idx.search(q, k, **search_args) - # Benchmark Trials + # Benchmark Trials (and collect recall for first trial) trial_means = [] + trial_recalls = [] for t in range(trials): lats = [] - for q_vec in queries: + if t == 0 and gt is not None: + all_preds = [] + for qi, q_vec in enumerate(queries): q = q_vec.unsqueeze(0).float() - res = idx.search( - q, k, - **search_args - ) + res = idx.search(q, k, **search_args) ti = getattr(res, "timing_info", None) if ti and hasattr(ti, "total_time_ns"): lats.append(ti.total_time_ns / 1e6) @@ -149,18 +174,38 @@ def run_experiment(cfg_path: str, output_dir: str): lats.append(res.latency_ms) else: raise RuntimeError(f"No timing info found in search result for {idx_name}") + # Collect predicted indices for recall in trial 0 + if t == 0 and gt is not None: + try: + pred = extract_indices(res) + if isinstance(pred, torch.Tensor): + pred = pred.cpu().numpy() + elif not isinstance(pred, np.ndarray): + pred = np.asarray(pred) + all_preds.append(pred[0] if pred.ndim > 1 else pred) + except Exception: + # Defensive fallback: don't break script if recall fails + all_preds.append(np.full((k,), -1, dtype=np.int64)) mean_t = float(np.mean(lats)) trial_means.append(mean_t) - print(f" [trial {t+1}/{trials}] {mean_t:.2f} ms") + if t == 0 and gt is not None: + preds_arr = np.stack(all_preds, axis=0) + recall = compute_recall_at_k(preds_arr, gt, k) + trial_recalls.append(recall) + print(f" [trial {t+1}/{trials}] {mean_t:.2f} ms | recall@{k}: {recall:.4f}") + else: + print(f" [trial {t+1}/{trials}] {mean_t:.2f} ms") mean_lat = float(np.mean(trial_means)) std_lat = float(np.std(trial_means)) + mean_recall = float(trial_recalls[0]) if trial_recalls else np.nan n_workers_val = build_params.get("num_workers", None) row = { "index": idx_name, "n_workers": n_workers_val, "mean_latency_ms": mean_lat, "std_latency_ms": std_lat, + f"recall_at_{k}": mean_recall, } all_rows.append(row) pd.DataFrame([row]).to_csv(idx_csv, index=False) @@ -171,7 +216,7 @@ def run_experiment(cfg_path: str, output_dir: str): df.to_csv(out_csv, index=False) print(f"\n[RESULT] Results written to {out_csv}") - # Plot + # Plot Latency plt.figure() for idx_name in df["index"].unique(): subset = df[df["index"] == idx_name] @@ -193,3 +238,25 @@ def run_experiment(cfg_path: str, output_dir: str): plt.tight_layout() plt.savefig(plot_file) print(f"[PLOT] Saved to {plot_file}") + + # Plot Recall + if f"recall_at_{k}" in df.columns: + plt.figure() + for idx_name in df["index"].unique(): + subset = df[df["index"] == idx_name] + label = f"{idx_name}" if subset["n_workers"].isnull().all() else f"{idx_name} (n_workers={subset['n_workers'].iloc[0]})" + plt.plot( + subset["n_workers"] if "n_workers" in subset else subset.index, + subset[f"recall_at_{k}"], + marker="o", + label=label + ) + plt.xscale("symlog", base=2) + plt.xlabel("Num Workers") + plt.ylabel(f"Recall@{k}") + plt.title(f"Recall@{k} (per-index)") + plt.legend() + plot_file = out_dir / f"{out_csv.stem}_recall.png" + plt.tight_layout() + plt.savefig(plot_file) + print(f"[PLOT] Recall plot saved to {plot_file}") From ab223d37106a67751afa5454d99525aa14dc549f Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 01:02:18 -0500 Subject: [PATCH 058/323] update multi-query experiment --- .../experiments/osdi2025/numa_single_query/run.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index 96c720ec..1375c627 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -176,20 +176,13 @@ def run_experiment(cfg_path: str, output_dir: str): raise RuntimeError(f"No timing info found in search result for {idx_name}") # Collect predicted indices for recall in trial 0 if t == 0 and gt is not None: - try: - pred = extract_indices(res) - if isinstance(pred, torch.Tensor): - pred = pred.cpu().numpy() - elif not isinstance(pred, np.ndarray): - pred = np.asarray(pred) - all_preds.append(pred[0] if pred.ndim > 1 else pred) - except Exception: - # Defensive fallback: don't break script if recall fails - all_preds.append(np.full((k,), -1, dtype=np.int64)) + pred = extract_indices(res) # [1, k] + all_preds.append(pred[0]) # get the [k] mean_t = float(np.mean(lats)) trial_means.append(mean_t) if t == 0 and gt is not None: - preds_arr = np.stack(all_preds, axis=0) + preds_arr = np.stack(all_preds, axis=0) # [num_queries, k] + print(f"[DEBUG] preds_arr shape: {preds_arr.shape}, gt shape: {gt.shape}") recall = compute_recall_at_k(preds_arr, gt, k) trial_recalls.append(recall) print(f" [trial {t+1}/{trials}] {mean_t:.2f} ms | recall@{k}: {recall:.4f}") From 1dfce55605987e22bef4e66d735657ec26bd22cb Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 01:02:59 -0500 Subject: [PATCH 059/323] update multi-query experiment --- test/experiments/osdi2025/numa_single_query/run.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index 1375c627..c82fb12a 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -45,14 +45,6 @@ "SVS": Vamana, } -def extract_indices(res): - """Helper to extract predicted indices from result.""" - if hasattr(res, "I"): - return res.I - if hasattr(res, "indices"): - return res.indices - raise RuntimeError("Cannot extract predicted indices from search result.") - def compute_recall_at_k(pred, gt, k): """ pred: [num_queries, k] predicted indices @@ -176,7 +168,7 @@ def run_experiment(cfg_path: str, output_dir: str): raise RuntimeError(f"No timing info found in search result for {idx_name}") # Collect predicted indices for recall in trial 0 if t == 0 and gt is not None: - pred = extract_indices(res) # [1, k] + pred = res.ids # [1, k] all_preds.append(pred[0]) # get the [k] mean_t = float(np.mean(lats)) trial_means.append(mean_t) From eac904e702cbfad04c6018724b2aac325ae71acf Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 01:03:52 -0500 Subject: [PATCH 060/323] update multi-query experiment --- test/experiments/osdi2025/numa_single_query/run.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index c82fb12a..4b17105f 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -52,6 +52,8 @@ def compute_recall_at_k(pred, gt, k): Returns recall@k """ # Faiss GT may be shape [num_queries, k'] or [num_queries] + print(pred) + print(gt) if gt.ndim == 1: gt = gt[:, None] matches = 0 From 1255f0ab137cbb311cfc3b7349a3ea172e487066 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 01:05:01 -0500 Subject: [PATCH 061/323] update multi-query experiment --- test/experiments/osdi2025/numa_single_query/run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index 4b17105f..ce4a9b7a 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -170,7 +170,7 @@ def run_experiment(cfg_path: str, output_dir: str): raise RuntimeError(f"No timing info found in search result for {idx_name}") # Collect predicted indices for recall in trial 0 if t == 0 and gt is not None: - pred = res.ids # [1, k] + pred = res.ids.numpy() # [1, k] all_preds.append(pred[0]) # get the [k] mean_t = float(np.mean(lats)) trial_means.append(mean_t) From 7b42c66fc4c8940a3419c5552d143d81810c382a Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 01:05:36 -0500 Subject: [PATCH 062/323] update multi-query experiment --- test/experiments/osdi2025/numa_single_query/run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index ce4a9b7a..61acf310 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -177,7 +177,7 @@ def run_experiment(cfg_path: str, output_dir: str): if t == 0 and gt is not None: preds_arr = np.stack(all_preds, axis=0) # [num_queries, k] print(f"[DEBUG] preds_arr shape: {preds_arr.shape}, gt shape: {gt.shape}") - recall = compute_recall_at_k(preds_arr, gt, k) + recall = compute_recall_at_k(preds_arr, gt.numpy(), k) trial_recalls.append(recall) print(f" [trial {t+1}/{trials}] {mean_t:.2f} ms | recall@{k}: {recall:.4f}") else: From 1cc8d522e6be78dbaf1a08b98d27b5f62d1501b7 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 01:06:12 -0500 Subject: [PATCH 063/323] update multi-query experiment --- test/experiments/osdi2025/numa_single_query/run.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index 61acf310..d97ddbdf 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -51,9 +51,6 @@ def compute_recall_at_k(pred, gt, k): gt: [num_queries, ...] ground truth indices Returns recall@k """ - # Faiss GT may be shape [num_queries, k'] or [num_queries] - print(pred) - print(gt) if gt.ndim == 1: gt = gt[:, None] matches = 0 From d70bd2543f7c6923e79d7ebf1f2aed1e5b865620 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 01:07:40 -0500 Subject: [PATCH 064/323] update multi-query experiment --- .../numa_single_query/configs/sift1m.yaml | 2 +- .../osdi2025/numa_single_query/run.py | 24 ++++--------------- 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml index 46ee1db9..589ccb80 100644 --- a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml @@ -2,7 +2,7 @@ dataset: name: sift1m num_queries: 100 - k: 10 + k: 100 trials: 5 warmup: 10 diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index d97ddbdf..2c59f663 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -17,6 +17,7 @@ import pandas as pd import matplotlib.pyplot as plt from pathlib import Path +from quake.utils import compute_recall from quake.datasets.ann_datasets import load_dataset from quake.index_wrappers.faiss_ivf import FaissIVF @@ -45,23 +46,6 @@ "SVS": Vamana, } -def compute_recall_at_k(pred, gt, k): - """ - pred: [num_queries, k] predicted indices - gt: [num_queries, ...] ground truth indices - Returns recall@k - """ - if gt.ndim == 1: - gt = gt[:, None] - matches = 0 - num = pred.shape[0] - for i in range(num): - pred_set = set(pred[i]) - gt_set = set(gt[i]) - matches += len(pred_set & gt_set) - recall = matches / (num * min(k, gt.shape[1])) - return recall - def build_and_save_index(index_class, build_params, base_vecs, index_file): idx = index_class() params = dict(build_params) @@ -167,14 +151,14 @@ def run_experiment(cfg_path: str, output_dir: str): raise RuntimeError(f"No timing info found in search result for {idx_name}") # Collect predicted indices for recall in trial 0 if t == 0 and gt is not None: - pred = res.ids.numpy() # [1, k] + pred = res.ids # [1, k] all_preds.append(pred[0]) # get the [k] mean_t = float(np.mean(lats)) trial_means.append(mean_t) if t == 0 and gt is not None: - preds_arr = np.stack(all_preds, axis=0) # [num_queries, k] + preds_arr = torch.stack(all_preds) # [num_queries, k] print(f"[DEBUG] preds_arr shape: {preds_arr.shape}, gt shape: {gt.shape}") - recall = compute_recall_at_k(preds_arr, gt.numpy(), k) + recall = compute_recall(preds_arr, gt, k) trial_recalls.append(recall) print(f" [trial {t+1}/{trials}] {mean_t:.2f} ms | recall@{k}: {recall:.4f}") else: From bfd604a9a4660dbcede95cdf15478060937ec33b Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 01:09:28 -0500 Subject: [PATCH 065/323] update multi-query experiment --- test/experiments/osdi2025/numa_single_query/run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index 2c59f663..95dea09d 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -158,7 +158,7 @@ def run_experiment(cfg_path: str, output_dir: str): if t == 0 and gt is not None: preds_arr = torch.stack(all_preds) # [num_queries, k] print(f"[DEBUG] preds_arr shape: {preds_arr.shape}, gt shape: {gt.shape}") - recall = compute_recall(preds_arr, gt, k) + recall = float(compute_recall(preds_arr, gt, k).mean()) trial_recalls.append(recall) print(f" [trial {t+1}/{trials}] {mean_t:.2f} ms | recall@{k}: {recall:.4f}") else: From 6cbf125b48dc488d318ef572ad6e7e951086284c Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 01:22:08 -0500 Subject: [PATCH 066/323] update multi-query experiment --- src/python/index_wrappers/diskann.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/python/index_wrappers/diskann.py b/src/python/index_wrappers/diskann.py index 7cef67fd..3f268f98 100644 --- a/src/python/index_wrappers/diskann.py +++ b/src/python/index_wrappers/diskann.py @@ -102,9 +102,15 @@ def search( timing_info = SearchTimingInfo() start = time.time() - indices, distances = self.index.batch_search( - query, k_neighbors=k, complexity=complexity, num_threads=num_threads - ) + if query.shape[0] == 1: + indices, distances = self.index.search( + query, k_neighbors=k, complexity=complexity, num_threads=num_threads + ) + else: + # batch search + indices, distances = self.index.batch_search( + query, k_neighbors=k, complexity=complexity, num_threads=num_threads + ) end = time.time() timing_info.total_time_ns = int((end - start) * 1e9) indices = to_torch(indices.astype(np.int64)) From ec1ddbff3c53b63b8be6f63e37836ed73f5b2ef4 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 01:24:08 -0500 Subject: [PATCH 067/323] update multi-query experiment --- src/python/index_wrappers/diskann.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/python/index_wrappers/diskann.py b/src/python/index_wrappers/diskann.py index 3f268f98..0c58792c 100644 --- a/src/python/index_wrappers/diskann.py +++ b/src/python/index_wrappers/diskann.py @@ -104,8 +104,7 @@ def search( start = time.time() if query.shape[0] == 1: indices, distances = self.index.search( - query, k_neighbors=k, complexity=complexity, num_threads=num_threads - ) + query, k_neighbors=k, complexity=complexity) else: # batch search indices, distances = self.index.batch_search( From 1621a093986e2d1121f9840f9106e11302974f7d Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 01:26:38 -0500 Subject: [PATCH 068/323] update multi-query experiment --- src/python/index_wrappers/diskann.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/python/index_wrappers/diskann.py b/src/python/index_wrappers/diskann.py index 0c58792c..340e6e86 100644 --- a/src/python/index_wrappers/diskann.py +++ b/src/python/index_wrappers/diskann.py @@ -104,7 +104,9 @@ def search( start = time.time() if query.shape[0] == 1: indices, distances = self.index.search( - query, k_neighbors=k, complexity=complexity) + query.flatten(), k_neighbors=k, complexity=complexity) + indices = indices.reshape(1, -1) + distances = distances.reshape(1, -1) else: # batch search indices, distances = self.index.batch_search( From b49d517e93956d8a960b5d2e95b81ceed99c2d9d Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 02:08:09 -0500 Subject: [PATCH 069/323] update multi-query experiment --- .../numa_multi_query/configs/sift1m.yaml | 127 +++++- .../osdi2025/numa_multi_query/run.py | 384 ++++++++++-------- 2 files changed, 335 insertions(+), 176 deletions(-) diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index b6b5b768..067cfd52 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -1,18 +1,123 @@ -# existing keys... +# numa_latency_experiment.yaml dataset: name: sift1m num_queries: 10000 - k: 10 - nprobe: 10 + k: 100 -#n_workers: [0,1,2,4,8,16] -#batch_sizes: [1, 10, 100, 100] -n_workers: [1, 2, 4, 8, 16] -batch_sizes: [1, 10, 100, 1000, 10000] +trials: 3 +warmup: 1 +overwrite: false # Set to true to force all indexes to rerun -# new keys: -trials: 5 -warmup: 10 +indexes: + - name: Quake_1 + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 1 + use_numa: false + search_params: + nprobe: 15 + batched_scan: true + + - name: Quake_4 + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 4 + use_numa: false + search_params: + nprobe: 15 + batched_scan: true + + - name: Quake_16 + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 16 + use_numa: false + search_params: + nprobe: 15 + batched_scan: true + + - name: Quake_1_numa + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 1 + use_numa: true + search_params: + nprobe: 15 + batched_scan: true + + - name: Quake_4_numa + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 4 + use_numa: true + search_params: + nprobe: 15 + batched_scan: true + + - name: Quake_16_numa + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 16 + use_numa: true + search_params: + nprobe: 15 + batched_scan: true + + - name: FaissIVF + index: IVF + build_params: + nc: 1000 + metric: l2 + search_params: + nprobe: 15 + + - name: SCANN + index: SCANN + build_params: + num_leaves: 1000 + metric: squared_l2 + search_params: + leaves_to_search: 15 + + - name: FaissHNSW + index: HNSW + build_params: + m: 64 + ef_construction: 128 + metric: l2 + search_params: + ef_search: 24 + + - name: DiskANN + index: DiskANN + build_params: + complexity: 128 + graph_degree: 64 + metric: l2 + search_params: + complexity: 16 + + - name: SVS + index: SVS + build_params: + graph_max_degree: 64 + alpha: 1.1 + window_size: 128 + metric: l2 + search_params: + search_window_size: 24 output: - results_csv: numa_multi_query_results.csv \ No newline at end of file + results_csv: numa_single_query_results.csv \ No newline at end of file diff --git a/test/experiments/osdi2025/numa_multi_query/run.py b/test/experiments/osdi2025/numa_multi_query/run.py index 0fd77d8b..e16c7ee5 100644 --- a/test/experiments/osdi2025/numa_multi_query/run.py +++ b/test/experiments/osdi2025/numa_multi_query/run.py @@ -1,186 +1,240 @@ #!/usr/bin/env python3 """ -NUMA multi‐query QPS experiment for Quake. +NUMA Batch-Query Latency and Recall Benchmark -Sweeps NUMA on/off, worker counts, batched_scan on/off, and batch sizes; -records mean/std QPS and produces a simplified batched_scan QPS plot. +Benchmarks a suite of ANN indexes (Quake, Faiss-IVF, SCANN, HNSW, DiskANN, SVS, etc.) +for batch-query latency and recall@k under configurable build and search parameters. +Results are cached and only recomputed if the 'overwrite' flag is set in the configuration. +Outputs a unified CSV and a latency plot per index. + +Usage: + python numa_latency_batch_experiment.py numa_latency_experiment.yaml output_dir """ import yaml -import time import numpy as np import torch import pandas as pd import matplotlib.pyplot as plt from pathlib import Path +from time import time +from quake.utils import compute_recall from quake.datasets.ann_datasets import load_dataset +from quake.index_wrappers.faiss_ivf import FaissIVF +from quake.index_wrappers.faiss_hnsw import FaissHNSW from quake.index_wrappers.quake import QuakeWrapper +try: + from quake.index_wrappers.scann import Scann +except ImportError: + raise ImportError("SCANN wrapper not available. Please install the required package.") +try: + from quake.index_wrappers.diskann import DiskANNDynamic +except ImportError: + raise ImportError("DiskANN wrapper not available. Please install the required package.") +try: + from quake.index_wrappers.vamana import Vamana +except ImportError: + raise ImportError("SVS wrapper not available. Please install the required package.") + +INDEX_CLASSES = { + "Quake": QuakeWrapper, + "IVF": FaissIVF, + "SCANN": Scann, + "HNSW": FaissHNSW, + "DiskANN": DiskANNDynamic, + "SVS": Vamana, +} + +def build_and_save_index(index_class, build_params, base_vecs, index_file): + idx = index_class() + params = dict(build_params) + idx.build(base_vecs, **params) + idx.save(str(index_file)) + +def extract_ids(res): + if hasattr(res, "ids"): + arr = res.ids + elif hasattr(res, "I"): + arr = res.I + elif hasattr(res, "indices"): + arr = res.indices + else: + raise RuntimeError("Cannot extract predicted indices from search result.") + if isinstance(arr, torch.Tensor): + arr = arr.cpu().numpy() + elif not isinstance(arr, np.ndarray): + arr = np.asarray(arr) + return arr + def run_experiment(cfg_path: str, output_dir: str): - cfg = yaml.safe_load(Path(cfg_path).read_text()) - out = Path(output_dir) - out.mkdir(exist_ok=True, parents=True) - csv_name = cfg.get("output", {}).get("results_csv", "results.csv") - out_csv = out / csv_name - - # check if the results already exist - if not Path(out_csv).exists(): - - # Load config - ds = cfg["dataset"] - n_workers = cfg["n_workers"] - batched_opts= cfg.get("batch_options", [False, True]) - batch_sizes = cfg.get("batch_sizes", [ds["num_queries"]]) - num_q = ds["num_queries"] - k = ds["k"] - nprobe = ds["nprobe"] - trials = cfg.get("trials", 5) - warmup = cfg.get("warmup", 2) - - - # Load data - print(f"Loading {ds['name']} ({num_q} queries)…") - base_vecs, queries_data, _ = load_dataset(ds["name"]) - queries = ( - torch.from_numpy(queries_data[:num_q]).float() - if isinstance(queries_data, np.ndarray) - else queries_data[:num_q].float() - ) + cfg = yaml.safe_load(Path(cfg_path).read_text()) + ds = cfg["dataset"] + queries_n = ds["num_queries"] + k = ds["k"] + trials = cfg.get("trials", 5) + warmup = cfg.get("warmup", 10) + indexes_cfg = cfg["indexes"] + csv_name = cfg.get("output", {}).get("results_csv", "numa_results.csv") + overwrite = cfg.get("overwrite", False) + + out_dir = Path(output_dir) + out_dir.mkdir(parents=True, exist_ok=True) + + print(f"[INFO] Loading dataset '{ds['name']}'...") + base_vecs, queries, gt = load_dataset(ds["name"]) + queries = queries[:queries_n] + gt = gt[:queries_n] if gt is not None else None + + all_rows = [] + + for idx_cfg in indexes_cfg: + idx_name = idx_cfg["name"] + idx_type = idx_cfg["index"] + build_params = idx_cfg.get("build_params", {}) + search_params = idx_cfg.get("search_params", {}) + IndexClass = INDEX_CLASSES.get(idx_type) + if IndexClass is None: + print(f"[WARN] Unknown index type: {idx_type}. Skipping.") + continue + + idx_csv = out_dir / f"{idx_name}_results.csv" + idx_file = out_dir / f"{idx_name}_index.bin" + + if idx_csv.exists() and not overwrite: + print(f"[SKIP] {idx_name}: Results exist. Use overwrite: true to rerun.") + df_idx = pd.read_csv(idx_csv) + all_rows.append(df_idx.iloc[0].to_dict()) + continue - # Build index if needed - idx_file = out / "quake_index.bin" if not idx_file.exists(): - print("Building index…") - builder = QuakeWrapper() - vecs = ( - torch.from_numpy(base_vecs).float() - if isinstance(base_vecs, np.ndarray) - else base_vecs.float() - ) - nc = int(np.sqrt(vecs.shape[0])) - builder.build(vecs, nc=nc, metric="l2", num_workers=0) - builder.save(str(idx_file)) - print("Index saved.") - - records = [] - for use_numa in [False]: - for nw in n_workers: - for bs in batched_opts: - for batch_size in batch_sizes: - print(f"NUMA={use_numa}, workers={nw}, batched={bs}, batch={batch_size}") - idxm = QuakeWrapper() - idxm.load(str(idx_file), use_numa=use_numa, same_core=True, num_workers=nw) - n_threads = 16 if nw == 0 else 1 - - # Warmup - for _ in range(min(warmup,1)): - if bs: - for i in range(0, num_q, batch_size): - idxm.search(queries[i:i+batch_size], k, - batched_scan=bs, - nprobe=nprobe, - n_threads=n_threads) - else: - idxm.search(queries, k, - batched_scan=bs, - nprobe=nprobe, - n_threads=n_threads) - - # Trials → QPS - qps_vals = [] - for t in range(trials): - start = time.time() - if bs: - for i in range(0, num_q, batch_size): - idxm.search(queries[i:i+batch_size], k, - batched_scan=bs, - nprobe=nprobe, - n_threads=n_threads) - else: - idxm.search(queries, k, - batched_scan=bs, - nprobe=nprobe, - n_threads=n_threads) - elapsed = time.time() - start - qps_vals.append(num_q / elapsed) - print(f" Trial {t+1}/{trials}: {qps_vals[-1]:.1f} QPS") - - records.append({ - "numa_enabled": use_numa, - "n_worker": nw, - "batched_scan": bs, - "batch_size": batch_size, - "mean_qps": np.mean(qps_vals), - "std_qps": np.std(qps_vals), - }) - - # Save CSV - df = pd.DataFrame(records) - df.to_csv(out_csv, index=False) - print(f"Results → {out_csv}") - - df = pd.read_csv(out_csv) - - # Simplified batched_scan QPS plot - fig, ax = plt.subplots(1, 1, figsize=(12, 4)) - for bsz in sorted(df["batch_size"].unique()): - for bs in (False, True): - grp = df[(df["batch_size"] == bsz) & (df["batched_scan"] == bs)] - if grp.empty: - continue - linestyle = '-' if not bs else '--' - label = f"batch={bsz}" + ("" if not bs else " batched") - ax.plot( - grp["n_worker"], - grp["mean_qps"], - marker='o', - linestyle=linestyle, - label=label - ) - ax.set_xscale("symlog", base=2) - ax.set_yscale("log", base=2) - ax.set_xlabel("Workers") - ax.set_ylabel("QPS") - ax.legend(title="Config", fontsize="small") - - fig.suptitle("QPS vs. Workers (solid=regular, dashed=batched)") - fig.tight_layout(rect=[0, 0, 1, 0.92]) - plot_path = out / f"{out_csv.stem}_combined_qps.png" - fig.savefig(plot_path) - print(f"Combined plot saved to {plot_path}") - - # 7) QPS vs. batch size for 1 and 16 workers, solid=unbatched, dashed=batched - fig2, ax2 = plt.subplots(1, 1, figsize=(6, 4)) - - # choose which workers to show - workers = [1, 16] - # matplotlib will auto‑cycle colors for each worker - for w in workers: - for bs, ls in [(False, "-"), (True, "--")]: - sub = df[(df["n_worker"] == w) & (df["batched_scan"] == bs)] - if sub.empty: - continue - sub = sub.sort_values("batch_size") - label = f"{w} worker{'s' if w>1 else ''}" + (" (batched)" if bs else "") - ax2.errorbar( - sub["batch_size"], - sub["mean_qps"], - yerr=sub["std_qps"], + print(f"[BUILD] {idx_name} index...") + build_and_save_index(IndexClass, build_params, base_vecs, idx_file) + print(f"[SAVE] Index saved at {idx_file}") + + print(f"[RUN] {idx_name} ...") + + if idx_type == "Quake": + load_kwargs = {} + if "use_numa" in build_params: + load_kwargs["use_numa"] = build_params["use_numa"] + if "num_workers" in build_params: + load_kwargs["num_workers"] = build_params["num_workers"] + idx = IndexClass() + idx.load(str(idx_file), **load_kwargs) + elif idx_type == "DiskANN": + idx = IndexClass() + build_params.pop("metric", None) + idx.load(str(idx_file), **build_params) + else: + idx = IndexClass() + idx.load(str(idx_file)) + + if idx_type == "SCANN": + search_args = {"leaves_to_search": search_params.get("leaves_to_search", 100)} + elif idx_type == "HNSW": + search_args = {"ef_search": search_params.get("ef_search", 32)} + elif idx_type == "DiskANN": + search_args = {"complexity": search_params.get("complexity", 32)} + elif idx_type == "SVS": + search_args = {"search_window_size": search_params.get("search_window_size", 32)} + else: # IVF, Quake, others + search_args = {"nprobe": search_params.get("nprobe", 100)} + + # Warmup (single batch, no timing) + for i in range(min(warmup, 1)): + idx.search(queries, k, **search_args) + + # Benchmark Trials (latency and recall) + trial_means = [] + trial_recalls = [] + for t in range(trials): + t0 = time() + res = idx.search(queries, k, **search_args) + t1 = time() + mean_t = ((t1 - t0) * 1e3) / queries.shape[0] # ms per query + trial_means.append(mean_t) + + preds_arr = extract_ids(res) + if preds_arr.shape[0] != queries.shape[0]: + raise RuntimeError(f"Pred shape {preds_arr.shape} doesn't match queries {queries.shape}") + + if gt is not None: + recall = float(compute_recall(preds_arr, gt, k).mean()) + trial_recalls.append(recall) + print(f" [trial {t+1}/{trials}] {mean_t:.2f} ms | recall@{k}: {recall:.4f}") + else: + print(f" [trial {t+1}/{trials}] {mean_t:.2f} ms") + + mean_lat = float(np.mean(trial_means)) + std_lat = float(np.std(trial_means)) + mean_recall = float(np.mean(trial_recalls)) if trial_recalls else np.nan + n_workers_val = build_params.get("num_workers", None) + row = { + "index": idx_name, + "n_workers": n_workers_val, + "mean_latency_ms": mean_lat, + "std_latency_ms": std_lat, + f"recall_at_{k}": mean_recall, + } + all_rows.append(row) + pd.DataFrame([row]).to_csv(idx_csv, index=False) + + # Save Unified CSV + df = pd.DataFrame(all_rows) + out_csv = out_dir / csv_name + df.to_csv(out_csv, index=False) + print(f"\n[RESULT] Results written to {out_csv}") + + # Plot Latency + plt.figure() + for idx_name in df["index"].unique(): + subset = df[df["index"] == idx_name] + label = f"{idx_name}" if subset["n_workers"].isnull().all() else f"{idx_name} (n_workers={subset['n_workers'].iloc[0]})" + plt.errorbar( + subset["n_workers"] if "n_workers" in subset else subset.index, + subset["mean_latency_ms"], + yerr=subset["std_latency_ms"], + marker="o", + capsize=5, + label=label + ) + plt.xscale("symlog", base=2) + plt.xlabel("Num Workers") + plt.ylabel("Mean Latency (ms)") + plt.title("Batch Query Latency (per-index)") + plt.legend() + plot_file = out_dir / f"{out_csv.stem}_latency.png" + plt.tight_layout() + plt.savefig(plot_file) + print(f"[PLOT] Saved to {plot_file}") + + # Plot Recall + if f"recall_at_{k}" in df.columns: + plt.figure() + for idx_name in df["index"].unique(): + subset = df[df["index"] == idx_name] + label = f"{idx_name}" if subset["n_workers"].isnull().all() else f"{idx_name} (n_workers={subset['n_workers'].iloc[0]})" + plt.plot( + subset["n_workers"] if "n_workers" in subset else subset.index, + subset[f"recall_at_{k}"], marker="o", - linestyle=ls, - capsize=4, label=label ) - - ax2.set_xscale("symlog", base=2) - ax2.set_yscale("log", base=2) - ax2.set_xlabel("Batch Size") - ax2.set_ylabel("QPS") - ax2.set_title("QPS vs. Batch Size\n(solid=unbatched, dashed=batched)") - ax2.grid(True, which="both", ls=":") - ax2.legend(title="Configuration", fontsize="small", ncol=1) - fig2.tight_layout() - plot2_path = out / f"{out_csv.stem}_qps_vs_batchsize_full.png" - fig2.savefig(plot2_path) - print(f"Full batch‑size QPS plot saved to {plot2_path}") \ No newline at end of file + plt.xscale("symlog", base=2) + plt.xlabel("Num Workers") + plt.ylabel(f"Recall@{k}") + plt.title(f"Recall@{k} (per-index)") + plt.legend() + plot_file = out_dir / f"{out_csv.stem}_recall.png" + plt.tight_layout() + plt.savefig(plot_file) + print(f"[PLOT] Recall plot saved to {plot_file}") + +if __name__ == "__main__": + import sys + if len(sys.argv) != 3: + print(f"Usage: {sys.argv[0]} ") + sys.exit(1) + run_experiment(sys.argv[1], sys.argv[2]) \ No newline at end of file From a6d28199142c1a8221003d0611d594d4e1e178b9 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 02:46:32 -0500 Subject: [PATCH 070/323] update multi-query --- .../osdi2025/numa_multi_query/run.py | 84 ++++++++++--------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/test/experiments/osdi2025/numa_multi_query/run.py b/test/experiments/osdi2025/numa_multi_query/run.py index e16c7ee5..e9d7a735 100644 --- a/test/experiments/osdi2025/numa_multi_query/run.py +++ b/test/experiments/osdi2025/numa_multi_query/run.py @@ -25,26 +25,26 @@ from quake.index_wrappers.faiss_hnsw import FaissHNSW from quake.index_wrappers.quake import QuakeWrapper -try: - from quake.index_wrappers.scann import Scann -except ImportError: - raise ImportError("SCANN wrapper not available. Please install the required package.") -try: - from quake.index_wrappers.diskann import DiskANNDynamic -except ImportError: - raise ImportError("DiskANN wrapper not available. Please install the required package.") -try: - from quake.index_wrappers.vamana import Vamana -except ImportError: - raise ImportError("SVS wrapper not available. Please install the required package.") +# try: +# from quake.index_wrappers.scann import Scann +# except ImportError: +# raise ImportError("SCANN wrapper not available. Please install the required package.") +# try: +# from quake.index_wrappers.diskann import DiskANNDynamic +# except ImportError: +# raise ImportError("DiskANN wrapper not available. Please install the required package.") +# try: +# from quake.index_wrappers.vamana import Vamana +# except ImportError: +# raise ImportError("SVS wrapper not available. Please install the required package.") INDEX_CLASSES = { "Quake": QuakeWrapper, "IVF": FaissIVF, - "SCANN": Scann, + # "SCANN": Scann, "HNSW": FaissHNSW, - "DiskANN": DiskANNDynamic, - "SVS": Vamana, + # "DiskANN": DiskANNDynamic, + # "SVS": Vamana, } def build_and_save_index(index_class, build_params, base_vecs, index_file): @@ -87,12 +87,29 @@ def run_experiment(cfg_path: str, output_dir: str): queries = queries[:queries_n] gt = gt[:queries_n] if gt is not None else None + # --- Build the Quake base index ONCE --- + quake_base_params = None + quake_base_index_file = out_dir / "Quake_base_index.bin" + # Find the build params for the first Quake config for base index + for idx_cfg in indexes_cfg: + if idx_cfg["index"] == "Quake": + quake_base_params = dict(idx_cfg.get("build_params", {})) + # Remove any runtime/load-only params + quake_base_params.pop("num_workers", None) + quake_base_params.pop("use_numa", None) + break + if quake_base_params is not None: + if not quake_base_index_file.exists(): + print(f"[BUILD] Quake (shared) base index ...") + build_and_save_index(QuakeWrapper, quake_base_params, base_vecs, quake_base_index_file) + print(f"[SAVE] Quake base index saved at {quake_base_index_file}") + all_rows = [] for idx_cfg in indexes_cfg: idx_name = idx_cfg["name"] idx_type = idx_cfg["index"] - build_params = idx_cfg.get("build_params", {}) + build_params = dict(idx_cfg.get("build_params", {})) search_params = idx_cfg.get("search_params", {}) IndexClass = INDEX_CLASSES.get(idx_type) if IndexClass is None: @@ -100,7 +117,11 @@ def run_experiment(cfg_path: str, output_dir: str): continue idx_csv = out_dir / f"{idx_name}_results.csv" - idx_file = out_dir / f"{idx_name}_index.bin" + # Quake uses the shared base index; others get their own file + if idx_type == "Quake": + idx_file = quake_base_index_file + else: + idx_file = out_dir / f"{idx_name}_index.bin" if idx_csv.exists() and not overwrite: print(f"[SKIP] {idx_name}: Results exist. Use overwrite: true to rerun.") @@ -108,7 +129,7 @@ def run_experiment(cfg_path: str, output_dir: str): all_rows.append(df_idx.iloc[0].to_dict()) continue - if not idx_file.exists(): + if idx_type != "Quake" and not idx_file.exists(): print(f"[BUILD] {idx_name} index...") build_and_save_index(IndexClass, build_params, base_vecs, idx_file) print(f"[SAVE] Index saved at {idx_file}") @@ -116,12 +137,13 @@ def run_experiment(cfg_path: str, output_dir: str): print(f"[RUN] {idx_name} ...") if idx_type == "Quake": + # Only use load-time params for Quake load_kwargs = {} if "use_numa" in build_params: load_kwargs["use_numa"] = build_params["use_numa"] if "num_workers" in build_params: load_kwargs["num_workers"] = build_params["num_workers"] - idx = IndexClass() + idx = QuakeWrapper() idx.load(str(idx_file), **load_kwargs) elif idx_type == "DiskANN": idx = IndexClass() @@ -131,27 +153,18 @@ def run_experiment(cfg_path: str, output_dir: str): idx = IndexClass() idx.load(str(idx_file)) - if idx_type == "SCANN": - search_args = {"leaves_to_search": search_params.get("leaves_to_search", 100)} - elif idx_type == "HNSW": - search_args = {"ef_search": search_params.get("ef_search", 32)} - elif idx_type == "DiskANN": - search_args = {"complexity": search_params.get("complexity", 32)} - elif idx_type == "SVS": - search_args = {"search_window_size": search_params.get("search_window_size", 32)} - else: # IVF, Quake, others - search_args = {"nprobe": search_params.get("nprobe", 100)} + print(search_params) # Warmup (single batch, no timing) for i in range(min(warmup, 1)): - idx.search(queries, k, **search_args) + idx.search(queries, k, **search_params) # Benchmark Trials (latency and recall) trial_means = [] trial_recalls = [] for t in range(trials): t0 = time() - res = idx.search(queries, k, **search_args) + res = idx.search(queries, k, **search_params) t1 = time() mean_t = ((t1 - t0) * 1e3) / queries.shape[0] # ms per query trial_means.append(mean_t) @@ -230,11 +243,4 @@ def run_experiment(cfg_path: str, output_dir: str): plot_file = out_dir / f"{out_csv.stem}_recall.png" plt.tight_layout() plt.savefig(plot_file) - print(f"[PLOT] Recall plot saved to {plot_file}") - -if __name__ == "__main__": - import sys - if len(sys.argv) != 3: - print(f"Usage: {sys.argv[0]} ") - sys.exit(1) - run_experiment(sys.argv[1], sys.argv[2]) \ No newline at end of file + print(f"[PLOT] Recall plot saved to {plot_file}") \ No newline at end of file From 1696247aaf42dd87a60216bfd9f67cb82453e3d4 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 02:47:08 -0500 Subject: [PATCH 071/323] update multi-query --- .../numa_multi_query/configs/sift1m.yaml | 130 ++++++++++-------- 1 file changed, 76 insertions(+), 54 deletions(-) diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index 067cfd52..ecaeb901 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -2,13 +2,24 @@ dataset: name: sift1m num_queries: 10000 - k: 100 + k: 1 trials: 3 warmup: 1 -overwrite: false # Set to true to force all indexes to rerun +overwrite: true # Set to true to force all indexes to rerun indexes: + - name: Quake_0 + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 0 + use_numa: false + search_params: + nprobe: 20 + batched_scan: true + - name: Quake_1 index: Quake build_params: @@ -17,7 +28,7 @@ indexes: num_workers: 1 use_numa: false search_params: - nprobe: 15 + nprobe: 20 batched_scan: true - name: Quake_4 @@ -28,7 +39,7 @@ indexes: num_workers: 4 use_numa: false search_params: - nprobe: 15 + nprobe: 20 batched_scan: true - name: Quake_16 @@ -39,9 +50,20 @@ indexes: num_workers: 16 use_numa: false search_params: - nprobe: 15 + nprobe: 20 batched_scan: true + - name: Quake_0_numa + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 0 + use_numa: true + search_params: + nprobe: 20 + batched_scan: false + - name: Quake_1_numa index: Quake build_params: @@ -50,8 +72,8 @@ indexes: num_workers: 1 use_numa: true search_params: - nprobe: 15 - batched_scan: true + nprobe: 20 + batched_scan: false - name: Quake_4_numa index: Quake @@ -61,8 +83,8 @@ indexes: num_workers: 4 use_numa: true search_params: - nprobe: 15 - batched_scan: true + nprobe: 20 + batched_scan: false - name: Quake_16_numa index: Quake @@ -72,52 +94,52 @@ indexes: num_workers: 16 use_numa: true search_params: - nprobe: 15 - batched_scan: true + nprobe: 20 + batched_scan: false - - name: FaissIVF - index: IVF - build_params: - nc: 1000 - metric: l2 - search_params: - nprobe: 15 - - - name: SCANN - index: SCANN - build_params: - num_leaves: 1000 - metric: squared_l2 - search_params: - leaves_to_search: 15 - - - name: FaissHNSW - index: HNSW - build_params: - m: 64 - ef_construction: 128 - metric: l2 - search_params: - ef_search: 24 - - - name: DiskANN - index: DiskANN - build_params: - complexity: 128 - graph_degree: 64 - metric: l2 - search_params: - complexity: 16 - - - name: SVS - index: SVS - build_params: - graph_max_degree: 64 - alpha: 1.1 - window_size: 128 - metric: l2 - search_params: - search_window_size: 24 +# - name: FaissIVF +# index: IVF +# build_params: +# nc: 1000 +# metric: l2 +# search_params: +# nprobe: 15 +# +# - name: SCANN +# index: SCANN +# build_params: +# num_leaves: 1000 +# metric: squared_l2 +# search_params: +# leaves_to_search: 15 +# +# - name: FaissHNSW +# index: HNSW +# build_params: +# m: 64 +# ef_construction: 128 +# metric: l2 +# search_params: +# ef_search: 24 +# +# - name: DiskANN +# index: DiskANN +# build_params: +# complexity: 128 +# graph_degree: 64 +# metric: l2 +# search_params: +# complexity: 16 +# +# - name: SVS +# index: SVS +# build_params: +# graph_max_degree: 64 +# alpha: 1.1 +# window_size: 128 +# metric: l2 +# search_params: +# search_window_size: 24 output: results_csv: numa_single_query_results.csv \ No newline at end of file From 65ae621fa3a6e3ed3ca1a0f1f1d508e66906c7e5 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 03:06:43 -0500 Subject: [PATCH 072/323] update batched scan --- src/cpp/include/list_scanning.h | 139 +++++++++++++----- test/cpp/benchmark.cpp | 6 +- .../experiments/osdi2025/experiment_runner.py | 4 +- .../numa_multi_query/configs/sift1m.yaml | 2 +- 4 files changed, 107 insertions(+), 44 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index bb7defe0..48c5475c 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -343,60 +343,123 @@ inline void scan_list(const float *query_vec, } } -inline void batched_scan_list(const float *query_vecs, - const float *list_vecs, - const int64_t *list_ids, - int num_queries, - int list_size, - int dim, - vector> &topk_buffers, - MetricType metric = faiss::METRIC_L2) { +inline void batched_scan_list( + const float *query_vecs, + const float *list_vecs, + const int64_t *list_ids, + int num_queries, + int list_size, + int dim, + vector> &topk_buffers, + MetricType metric = faiss::METRIC_L2) +{ if (list_size == 0 || list_vecs == nullptr) { - // No list vectors to process; return; } - // Ensure k does not exceed list_size - int k = topk_buffers[0]->k_; - int k_max = std::min(k, list_size); + // Wrap raw arrays in torch Tensors, no copy + torch::Tensor query = torch::from_blob((void*)query_vecs, {num_queries, dim}, torch::kFloat32); + torch::Tensor list = torch::from_blob((void*)list_vecs, {list_size, dim}, torch::kFloat32); - int64_t *labels = (int64_t *) malloc(num_queries * k_max * sizeof(int64_t)); - float *distances = (float *) malloc(num_queries * k_max * sizeof(float)); - - if (metric == faiss::METRIC_INNER_PRODUCT) { - faiss::float_minheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; - faiss::knn_inner_product(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr); - } else if (metric == faiss::METRIC_L2) { - faiss::float_maxheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; - faiss::knn_L2sqr(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr, nullptr); + torch::Tensor distances; + if (metric == faiss::METRIC_L2) { + // Returns [num_queries, list_size], each entry is the Euclidean distance + distances = torch::cdist(query, list, 2.0); + } else if (metric == faiss::METRIC_INNER_PRODUCT) { + // [num_queries, list_size], each entry is dot product + distances = torch::matmul(query, list.t()); } else { throw std::runtime_error("Metric type not supported"); } - // map the labels to the actual list_ids - if (list_ids != nullptr) { - for (int i = 0; i < num_queries; i++) { - for (int j = 0; j < k_max; j++) { - labels[i * k_max + j] = list_ids[labels[i * k_max + j]]; + // For each query, push all list vectors and their distances into TopkBuffer + for (int i = 0; i < num_queries; ++i) { + auto row = distances[i]; + std::vector dists(list_size); + std::vector ids(list_size); + + if (metric == faiss::METRIC_L2) { + // L2: real distances + auto row_acc = row.accessor(); + for (int j = 0; j < list_size; ++j) { + dists[j] = row_acc[j]; + } + } else { + // IP: negative to mimic Faiss's heap convention if your buffer expects minimal distance + auto row_acc = row.accessor(); + for (int j = 0; j < list_size; ++j) { + dists[j] = row_acc[j]; } } - } - // if the metric is l2, convert the distances to sqrt - if (metric == faiss::METRIC_L2) { - for (int i = 0; i < num_queries * k_max; i++) { - distances[i] = sqrt(distances[i]); + if (list_ids) { + for (int j = 0; j < list_size; ++j) { + ids[j] = list_ids[j]; + } + } else { + for (int j = 0; j < list_size; ++j) { + ids[j] = j; + } } - } - // add distances to the topk buffers - for (int i = 0; i < num_queries; i++) { - topk_buffers[i]->batch_add(distances + i * k_max, labels + i * k_max, k_max); + topk_buffers[i]->batch_add(dists.data(), ids.data(), list_size); } - - free(labels); - free(distances); } +//inline void batched_scan_list(const float *query_vecs, +// const float *list_vecs, +// const int64_t *list_ids, +// int num_queries, +// int list_size, +// int dim, +// vector> &topk_buffers, +// MetricType metric = faiss::METRIC_L2) { +// if (list_size == 0 || list_vecs == nullptr) { +// // No list vectors to process; +// return; +// } +// +// // Ensure k does not exceed list_size +// int k = topk_buffers[0]->k_; +// int k_max = std::min(k, list_size); +// +// int64_t *labels = (int64_t *) malloc(num_queries * k_max * sizeof(int64_t)); +// float *distances = (float *) malloc(num_queries * k_max * sizeof(float)); +// +// if (metric == faiss::METRIC_INNER_PRODUCT) { +// faiss::float_minheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; +// faiss::knn_inner_product(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr); +// } else if (metric == faiss::METRIC_L2) { +// faiss::float_maxheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; +// faiss::knn_L2sqr(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr, nullptr); +// } else { +// throw std::runtime_error("Metric type not supported"); +// } +// +// // map the labels to the actual list_ids +// if (list_ids != nullptr) { +// for (int i = 0; i < num_queries; i++) { +// for (int j = 0; j < k_max; j++) { +// labels[i * k_max + j] = list_ids[labels[i * k_max + j]]; +// } +// } +// } +// +// // if the metric is l2, convert the distances to sqrt +// if (metric == faiss::METRIC_L2) { +// for (int i = 0; i < num_queries * k_max; i++) { +// distances[i] = sqrt(distances[i]); +// } +// } +// +// // add distances to the topk buffers +// for (int i = 0; i < num_queries; i++) { +// topk_buffers[i]->batch_add(distances + i * k_max, labels + i * k_max, k_max); +// } +// +// free(labels); +// free(distances); +//} + // } #endif //LIST_SCANNING_H diff --git a/test/cpp/benchmark.cpp b/test/cpp/benchmark.cpp index 6e7774b5..5bb3646b 100644 --- a/test/cpp/benchmark.cpp +++ b/test/cpp/benchmark.cpp @@ -27,11 +27,11 @@ using torch::Tensor; // Global benchmark parameters static const int64_t DIM = 128; -static const int64_t NUM_VECTORS = 100000; // number of database vectors +static const int64_t NUM_VECTORS = 1000000; // number of database vectors static const int64_t N_LIST = 1000; // number of clusters for IVF static const int64_t NUM_QUERIES = 10000; // number of queries for search benchmark -static const int64_t K = 1000; // top-K neighbors -static const int64_t N_PROBE = 10; // number of probes for IVF +static const int64_t K = 100; // top-K neighbors +static const int64_t N_PROBE = 20; // number of probes for IVF static const int64_t N_WORKERS = 12; // number of workers for parallel query coordinator // Helper functions to generate random data and sequential IDs diff --git a/test/experiments/osdi2025/experiment_runner.py b/test/experiments/osdi2025/experiment_runner.py index b51b8725..b9142976 100644 --- a/test/experiments/osdi2025/experiment_runner.py +++ b/test/experiments/osdi2025/experiment_runner.py @@ -6,7 +6,7 @@ from pathlib import Path from test.experiments.osdi2025.kick_the_tires.run import run_experiment as run_kick_the_tires -from test.experiments.osdi2025.numa_single_query.run import run_experiment as run_numa_single +# from test.experiments.osdi2025.numa_single_query.run import run_experiment as run_numa_single from test.experiments.osdi2025.numa_multi_query.run import run_experiment as run_numa_multi from test.experiments.osdi2025.aps_recall_targets.run import run_experiment as run_aps_recall from test.experiments.osdi2025.early_termination.run import run_experiment as run_early_termination @@ -16,7 +16,7 @@ EXPERIMENTS = { "kick_the_tires": run_kick_the_tires, - "numa_single_query": run_numa_single, + # "numa_single_query": run_numa_single, "numa_multi_query": run_numa_multi, "aps_recall_targets": run_aps_recall, "early_termination": run_early_termination, diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index ecaeb901..79a69316 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -2,7 +2,7 @@ dataset: name: sift1m num_queries: 10000 - k: 1 + k: 100 trials: 3 warmup: 1 From afc39969e98cc13fc6d0b50867366c17b8f08500 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 11:55:40 -0500 Subject: [PATCH 073/323] scan tweaks --- src/cpp/include/list_scanning.h | 20 ++++--------- src/cpp/src/query_coordinator.cpp | 50 +++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 48c5475c..573f0b4e 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -358,8 +358,8 @@ inline void batched_scan_list( } // Wrap raw arrays in torch Tensors, no copy - torch::Tensor query = torch::from_blob((void*)query_vecs, {num_queries, dim}, torch::kFloat32); - torch::Tensor list = torch::from_blob((void*)list_vecs, {list_size, dim}, torch::kFloat32); + Tensor query = torch::from_blob((void*)query_vecs, {num_queries, dim}, torch::kFloat32); + Tensor list = torch::from_blob((void*)list_vecs, {list_size, dim}, torch::kFloat32); torch::Tensor distances; if (metric == faiss::METRIC_L2) { @@ -373,23 +373,13 @@ inline void batched_scan_list( } // For each query, push all list vectors and their distances into TopkBuffer + auto distances_acc = distances.accessor(); for (int i = 0; i < num_queries; ++i) { - auto row = distances[i]; std::vector dists(list_size); std::vector ids(list_size); - if (metric == faiss::METRIC_L2) { - // L2: real distances - auto row_acc = row.accessor(); - for (int j = 0; j < list_size; ++j) { - dists[j] = row_acc[j]; - } - } else { - // IP: negative to mimic Faiss's heap convention if your buffer expects minimal distance - auto row_acc = row.accessor(); - for (int j = 0; j < list_size; ++j) { - dists[j] = row_acc[j]; - } + for (int j = 0; j < list_size; ++j) { + dists[j] = distances_acc[i][j]; } if (list_ids) { diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index a3b3bc3b..dc5c628a 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -103,8 +103,6 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { std::cout << "[QueryCoordinator::partition_scan_worker_fn] Failed to set thread affinity on core " << core_index << std::endl; } - - while (true) { ScanJob job; @@ -197,11 +195,12 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { throw std::runtime_error("[partition_scan_worker_fn] Invalid batched job."); } - // Allocate a thread-local query buffer if needed. if (res.local_query_buffer.size() < partition_manager_->d() * sizeof(float) * job.num_queries) { res.local_query_buffer.resize(partition_manager_->d() * sizeof(float) * job.num_queries); } + auto s1 = std::chrono::high_resolution_clock::now(); + int64_t d = partition_manager_->d(); std::vector query_subset(job.num_queries * d); for (int i = 0; i < job.num_queries; i++) { @@ -210,7 +209,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { job.query_vector + global_q * d, d * sizeof(float)); } - // Then copy query_subset into your local buffer if needed: + if(memcpy(res.local_query_buffer.data(), query_subset.data(), query_subset.size() * sizeof(float)) == nullptr) { @@ -230,6 +229,8 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { } } + auto s2 = std::chrono::high_resolution_clock::now(); + // Process the batched job. batched_scan_list((float *) res.local_query_buffer.data(), partition_codes, @@ -240,18 +241,29 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { res.topk_buffer_pool, metric_); - vector> topk_list(job.num_queries); - vector> topk_indices_list(job.num_queries); - for (int64_t q = 0; q < job.num_queries; q++) { - topk_list[q] = res.topk_buffer_pool[q]->get_topk(); - topk_indices_list[q] = res.topk_buffer_pool[q]->get_topk_indices(); - } + auto s3 = std::chrono::high_resolution_clock::now(); for (int64_t q = 0; q < job.num_queries; q++) { int64_t global_q = job.query_ids[q]; - int n_results = topk_indices_list[q].size(); - global_topk_buffer_pool_[global_q]->batch_add(topk_list[q].data(), topk_indices_list[q].data(), n_results); + + vector topk = res.topk_buffer_pool[q]->get_topk(); + vector topk_indices = res.topk_buffer_pool[q]->get_topk_indices(); + int n_results = topk_indices.size(); + + global_topk_buffer_pool_[global_q]->batch_add(topk.data(), topk_indices.data(), n_results); } + + auto s4 = std::chrono::high_resolution_clock::now(); + + // print out timings for worker + auto wait_time = std::chrono::duration_cast(s2 - s1).count(); + auto process_time = std::chrono::duration_cast(s3 - s2).count(); + auto merge_time = std::chrono::duration_cast(s4 - s3).count(); + +// std::cout << "[QueryCoordinator::partition_scan_worker_fn] Worker " << core_index +// << " wait_time: " << wait_time / 1e6 << " ms, " +// << "process_time: " << process_time / 1e6 << " ms, " +// << "merge_time: " << merge_time / 1e6 << " ms" << std::endl; } auto job_process_end = std::chrono::high_resolution_clock::now(); job_process_time_ns += std::chrono::duration_cast(job_process_end - job_process_start).count(); @@ -414,7 +426,12 @@ shared_ptr QueryCoordinator::worker_scan( // check if all jobs have been processed bool all_done = true; for (int64_t q = 0; q < num_queries; q++) { - all_done = all_done && (global_topk_buffer_pool_[q]->jobs_left_ == 0); + if (global_topk_buffer_pool_[q]->jobs_left_ == 0) { + // flush the topk buffer (if needed) + global_topk_buffer_pool_[q]->flush(); + } else { + all_done = false; + } } if (all_done) { @@ -456,7 +473,7 @@ shared_ptr QueryCoordinator::worker_scan( } last_flush_time = high_resolution_clock::now(); } - std::this_thread::sleep_for(microseconds(1)); + std::this_thread::sleep_for(microseconds(5)); } end_time = high_resolution_clock::now(); timing_info->job_wait_time_ns = @@ -466,7 +483,10 @@ shared_ptr QueryCoordinator::worker_scan( start_time = high_resolution_clock::now(); auto topk_ids = torch::full({num_queries, k}, -1, torch::kInt64); auto topk_dists = torch::full({num_queries, k}, - std::numeric_limits::infinity(), torch::kFloat32); + (metric_ == faiss::METRIC_INNER_PRODUCT) + ? -std::numeric_limits::infinity() + : std::numeric_limits::infinity(), + torch::kFloat32); auto ids_accessor = topk_ids.accessor(); auto dists_accessor = topk_dists.accessor(); { From 2a86be1cc9e170445be4670cb00dea34624eba1c Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 12:10:53 -0500 Subject: [PATCH 074/323] add msturing10m --- .../numa_multi_query/configs/msturing10m.yaml | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 test/experiments/osdi2025/numa_multi_query/configs/msturing10m.yaml diff --git a/test/experiments/osdi2025/numa_multi_query/configs/msturing10m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/msturing10m.yaml new file mode 100644 index 00000000..de5e3f3d --- /dev/null +++ b/test/experiments/osdi2025/numa_multi_query/configs/msturing10m.yaml @@ -0,0 +1,146 @@ +# numa_latency_experiment.yaml +dataset: + name: msturing10m + num_queries: 1000 + k: 100 + +trials: 3 +warmup: 1 +overwrite: true # Set to true to force all indexes to rerun + +indexes: + - name: Quake_0 + index: Quake + build_params: + nc: 20000 + metric: l2 + num_workers: 0 + use_numa: false + search_params: + nprobe: 200 + batched_scan: true + + - name: Quake_1 + index: Quake + build_params: + nc: 20000 + metric: l2 + num_workers: 1 + use_numa: false + search_params: + nprobe: 100 + batched_scan: true + + - name: Quake_4 + index: Quake + build_params: + nc: 20000 + metric: l2 + num_workers: 4 + use_numa: false + search_params: + nprobe: 200 + batched_scan: true + + - name: Quake_16 + index: Quake + build_params: + nc: 20000 + metric: l2 + num_workers: 16 + use_numa: false + search_params: + nprobe: 200 + batched_scan: true + + - name: Quake_0_numa + index: Quake + build_params: + nc: 20000 + metric: l2 + num_workers: 0 + use_numa: true + search_params: + nprobe: 200 + batched_scan: false + n_threads: 16 + + - name: Quake_1_numa + index: Quake + build_params: + nc: 20000 + metric: l2 + num_workers: 1 + use_numa: true + search_params: + nprobe: 200 + batched_scan: false + + - name: Quake_4_numa + index: Quake + build_params: + nc: 20000 + metric: l2 + num_workers: 4 + use_numa: true + search_params: + nprobe: 200 + batched_scan: false + + - name: Quake_16_numa + index: Quake + build_params: + nc: 20000 + metric: l2 + num_workers: 16 + use_numa: true + search_params: + nprobe: 200 + batched_scan: false + +# - name: FaissIVF +# index: IVF +# build_params: +# nc: 1000 +# metric: l2 +# search_params: +# nprobe: 15 +# +# - name: SCANN +# index: SCANN +# build_params: +# num_leaves: 1000 +# metric: squared_l2 +# search_params: +# leaves_to_search: 15 +# +# - name: FaissHNSW +# index: HNSW +# build_params: +# m: 64 +# ef_construction: 128 +# metric: l2 +# search_params: +# ef_search: 24 +# +# - name: DiskANN +# index: DiskANN +# build_params: +# complexity: 128 +# graph_degree: 64 +# metric: l2 +# search_params: +# complexity: 16 +# +# - name: SVS +# index: SVS +# build_params: +# graph_max_degree: 64 +# alpha: 1.1 +# window_size: 128 +# metric: l2 +# search_params: +# search_window_size: 24 + +output: + results_csv: numa_single_query_results.csv \ No newline at end of file From e2791d51d9040d724bda17de2c23689dcc7fd6e9 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 May 2025 12:29:44 -0500 Subject: [PATCH 075/323] add msturing10m --- .../numa_multi_query/configs/msturing10m.yaml | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/test/experiments/osdi2025/numa_multi_query/configs/msturing10m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/msturing10m.yaml index de5e3f3d..2f7f9cc5 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/msturing10m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/msturing10m.yaml @@ -17,7 +17,7 @@ indexes: num_workers: 0 use_numa: false search_params: - nprobe: 200 + nprobe: 300 batched_scan: true - name: Quake_1 @@ -28,7 +28,7 @@ indexes: num_workers: 1 use_numa: false search_params: - nprobe: 100 + nprobe: 300 batched_scan: true - name: Quake_4 @@ -39,7 +39,7 @@ indexes: num_workers: 4 use_numa: false search_params: - nprobe: 200 + nprobe: 300 batched_scan: true - name: Quake_16 @@ -50,7 +50,7 @@ indexes: num_workers: 16 use_numa: false search_params: - nprobe: 200 + nprobe: 300 batched_scan: true - name: Quake_0_numa @@ -61,9 +61,8 @@ indexes: num_workers: 0 use_numa: true search_params: - nprobe: 200 - batched_scan: false - n_threads: 16 + nprobe: 300 + batched_scan: true - name: Quake_1_numa index: Quake @@ -73,8 +72,8 @@ indexes: num_workers: 1 use_numa: true search_params: - nprobe: 200 - batched_scan: false + nprobe: 300 + batched_scan: true - name: Quake_4_numa index: Quake @@ -84,8 +83,8 @@ indexes: num_workers: 4 use_numa: true search_params: - nprobe: 200 - batched_scan: false + nprobe: 300 + batched_scan: true - name: Quake_16_numa index: Quake @@ -95,8 +94,20 @@ indexes: num_workers: 16 use_numa: true search_params: - nprobe: 200 + nprobe: 300 + batched_scan: true + + - name: Quake_unbatched + index: Quake + build_params: + nc: 20000 + metric: l2 + num_workers: 16 + use_numa: true + search_params: + nprobe: 300 batched_scan: false + search_threads: 16 # - name: FaissIVF # index: IVF From 6619d36531424677b1ec09feeff0dfcb6a08153e Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 18:48:09 -0500 Subject: [PATCH 076/323] fix numa alloc --- src/cpp/include/partition_manager.h | 4 +- src/cpp/src/partition_manager.cpp | 11 +- test/cpp/benchmark.cpp | 10 +- .../early_termination/configs/sift1m.yaml | 9 +- .../osdi2025/early_termination/laet.py | 4 +- .../osdi2025/early_termination/run.py | 777 +++++++++--------- .../osdi2025/maintenance_ablation/run.py | 357 ++++---- .../numa_multi_query/configs/sift1m.yaml | 1 + 8 files changed, 607 insertions(+), 566 deletions(-) diff --git a/src/cpp/include/partition_manager.h b/src/cpp/include/partition_manager.h index b0ade908..86776167 100644 --- a/src/cpp/include/partition_manager.h +++ b/src/cpp/include/partition_manager.h @@ -114,13 +114,13 @@ class PartitionManager { * @brief Distribute the partitions across multiple workers. * @param num_workers The number of workers to distribute the partitions across. */ - void distribute_partitions(int num_workers); + void distribute_partitions(int num_workers, bool use_numa = false); /** * @brief Set the core ID for a given partition. * @param partition_id The ID of the partition. */ - void set_partition_core_id(int64_t partition_id, int core_id); + void set_partition_core_id(int64_t partition_id, int core_id, bool use_numa = false); /** * @brief Return the core ID for a given partition. diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index 5445e377..11eaa731 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -574,7 +574,7 @@ void PartitionManager::delete_partitions(const Tensor &partition_ids, bool reass } -void PartitionManager::distribute_partitions(int num_workers) { +void PartitionManager::distribute_partitions(int num_workers, bool use_numa) { if (debug_) { std::cout << "[PartitionManager] distribute_partitions: Attempting to distribute partitions across " << num_workers << " workers." << std::endl; @@ -625,8 +625,15 @@ void PartitionManager::distribute_partitions(int num_workers) { } } -void PartitionManager::set_partition_core_id(int64_t partition_id, int core_id) { +void PartitionManager::set_partition_core_id(int64_t partition_id, int core_id, bool use_numa) { partition_store_->partitions_[partition_id]->set_core_id(core_id); + + #ifdef QUAKE_USE_NUMA + if (use_numa) { + int node = numa_node_of_cpu(core_id); // <-- single call + partition_store_->partitions_[partition_id]->set_numa_node(core_id); + } + #endif } int PartitionManager::get_partition_core_id(int64_t partition_id) { diff --git a/test/cpp/benchmark.cpp b/test/cpp/benchmark.cpp index 5bb3646b..cd18cda3 100644 --- a/test/cpp/benchmark.cpp +++ b/test/cpp/benchmark.cpp @@ -30,7 +30,7 @@ static const int64_t DIM = 128; static const int64_t NUM_VECTORS = 1000000; // number of database vectors static const int64_t N_LIST = 1000; // number of clusters for IVF static const int64_t NUM_QUERIES = 10000; // number of queries for search benchmark -static const int64_t K = 100; // top-K neighbors +static const int64_t K = 10; // top-K neighbors static const int64_t N_PROBE = 20; // number of probes for IVF static const int64_t N_WORKERS = 12; // number of workers for parallel query coordinator @@ -314,6 +314,14 @@ TEST_F(QuakeWorkerIVFBenchmark, SearchBatch) { auto elapsed = duration_cast(end - start).count(); std::cout << "[Quake IVF Worker] Batched search time: " << elapsed << " ms" << std::endl; + + // print out timing info + auto timing_info = result->timing_info; + std::cout << "Total time: " << timing_info->total_time_ns / 1e6 << " ms" << std::endl; + std::cout << "Parent search time: " << timing_info->parent_info->total_time_ns / 1e6 << " ms" << std::endl; + std::cout << "Job enqueue time: " << timing_info->job_enqueue_time_ns / 1e6 << " ms" << std::endl; + std::cout << "Result aggregate time: " << timing_info->result_aggregate_time_ns / 1e6 << " ms" << std::endl; + std::cout << "Job Wait time: " << timing_info->job_wait_time_ns / 1e6 << " ms" << std::endl; ASSERT_GT(elapsed, 0); } diff --git a/test/experiments/osdi2025/early_termination/configs/sift1m.yaml b/test/experiments/osdi2025/early_termination/configs/sift1m.yaml index 3115bad5..9d53f80f 100644 --- a/test/experiments/osdi2025/early_termination/configs/sift1m.yaml +++ b/test/experiments/osdi2025/early_termination/configs/sift1m.yaml @@ -5,10 +5,10 @@ dataset: name: sift1m path: data experiment: - nq: 100 - k: 1 + nq: 10000 + k: 100 n_workers: 0 - recall_targets: [.2, .3, .4, .5, .6, 0.7, .75, 0.8, .85, 0.9, 0.95, 0.99, .999] + recall_targets: [0.8, 0.9, 0.99] recompute_ratio: 0.0001 use_precompute: true initial_search_fraction: .1 @@ -18,7 +18,8 @@ index: overwrite: index: false results: true -methods: ['LAET', 'Auncel', 'Oracle', 'FixedNProbe', 'APS', 'SPANN'] +#methods: ['LAET', 'Auncel', 'Oracle', 'FixedNProbe', 'APS', 'SPANN'] +methods: ['Auncel'] paths: index_dir: data/sift1m/indexes diff --git a/test/experiments/osdi2025/early_termination/laet.py b/test/experiments/osdi2025/early_termination/laet.py index 0b260906..2484033d 100644 --- a/test/experiments/osdi2025/early_termination/laet.py +++ b/test/experiments/osdi2025/early_termination/laet.py @@ -233,7 +233,7 @@ def _compute_recall_single_q(self, res_ids_tensor, gt_set_top_k, k_val_for_recal def run_inference_for_quake_experiment(self, quake_idx, queries_torch, gt_torch, target_recall, k_search, base_quake_sp, - num_bs_steps=20, multiplier_range=(0.1, 5.0)): + num_bs_steps=20, multiplier_range=(0.1, 50.0)): if not self.gbdt_model: print("LAET Inference Error: GBDT model not loaded.") return np.nan, np.nan, np.nan @@ -249,7 +249,7 @@ def run_inference_for_quake_experiment(self, quake_idx, queries_torch, gt_torch, quake_nlist_cap = quake_idx.nlist() if callable(getattr(quake_idx, 'nlist', None)) else getattr(quake_idx, 'nlist', 2048) # --- Log GBDT base_p predictions sample --- - sample_size_for_log = min(nq, 100) + sample_size_for_log = nq sample_base_p_preds = [self._predict_base_search_param(queries_np[i]) for i in range(sample_size_for_log)] if sample_base_p_preds: print(f"LAET INFERENCE (TargetRecall={target_recall:.2f}): Sample GBDT base_p predictions (first {sample_size_for_log}): " diff --git a/test/experiments/osdi2025/early_termination/run.py b/test/experiments/osdi2025/early_termination/run.py index 23e47988..ce8c2dbc 100644 --- a/test/experiments/osdi2025/early_termination/run.py +++ b/test/experiments/osdi2025/early_termination/run.py @@ -1,407 +1,400 @@ -import time -import yaml +#!/usr/bin/env python3 +""" +APS vs. early-termination baselines +Generates CSV + Markdown table with: + RecallAchieved | nprobe | QueryLatencyMs | TuningTimeMs +for recall targets 0.80, 0.90, 0.99 +""" + +from __future__ import annotations +import argparse import logging +import time from pathlib import Path -import argparse +from typing import List, Dict -import torch -import pandas as pd import numpy as np -import matplotlib.pyplot as plt +import pandas as pd +import torch +import yaml +# ── optional plotting ───────────────────────────────────────────────────────── try: - from quake import QuakeIndex, IndexBuildParams, SearchParams - from quake.datasets.ann_datasets import load_dataset - from quake.utils import compute_recall -except ImportError as e: - print(f"Error importing Quake library components: {e}. Ensure 'quake' is installed and in PYTHONPATH.") - raise + import matplotlib.pyplot as plt + + _HAVE_MPL = True +except ImportError: + _HAVE_MPL = False +# ── Quake bindings ──────────────────────────────────────────────────────────── +from quake import QuakeIndex, IndexBuildParams, SearchParams +from quake.datasets.ann_datasets import load_dataset +from quake.utils import compute_recall + +# ── LAET (mandatory) ────────────────────────────────────────────────────────── try: from .laet import LAETPipeline except ImportError as e: - try: - from laet import LAETPipeline - print("Note: Imported LAETPipeline using 'from laet import LAETPipeline'.") - except ImportError: - print(f"Error importing LAETPipeline: {e}. Ensure 'laet.py' is correctly placed and import path is valid.") - raise - - -# Setup basic logging -logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') -logger = logging.getLogger(__name__) - -def run_experiment(cfg_path: str, output_dir_str: str): - # 1) Load config + setup output dir - logger.info(f"Loading configuration from: {cfg_path}") - try: - cfg = yaml.safe_load(Path(cfg_path).read_text()) - except FileNotFoundError: - logger.error(f"Configuration file not found: {cfg_path}") - return - except Exception as e: - logger.error(f"Error loading YAML configuration from {cfg_path}: {e}") - return - - out_path = Path(output_dir_str) - out_path.mkdir(parents=True, exist_ok=True) - logger.info(f"Output directory set to: {out_path}") - - # 2) Load data - data_dir = cfg["dataset"].get("path", "") - dataset_name = cfg["dataset"]["name"] - logger.info(f"Loading dataset: {dataset_name} from path: '{data_dir if data_dir else 'default'}'") - try: - vecs, queries_torch, gt_torch = load_dataset(dataset_name, data_dir) - except Exception as e: - logger.error(f"Failed to load dataset '{dataset_name}': {e}", exc_info=True) - return - - nq_config = cfg["experiment"].get("nq", queries_torch.shape[0]) - queries_torch, gt_torch = queries_torch[:nq_config], gt_torch[:nq_config] - logger.info(f"Using {queries_torch.shape[0]} queries for the experiment.") - - # 3) Build or load QuakeIndex (used by all methods) - idx_quake = QuakeIndex() - - build_params = IndexBuildParams() - build_params.nlist = cfg["index"]["nlist"] - build_params.metric = cfg["index"]["metric"] - build_params.num_workers = cfg["experiment"].get("n_workers", 0) - - idx_base_dir = Path(cfg["paths"].get("index_dir", out_path / "indexes")) - idx_base_dir.mkdir(parents=True, exist_ok=True) - idx_path_quake = idx_base_dir / f"{dataset_name}_quake_ivf{build_params.nlist}.index" - - if not idx_path_quake.exists() or cfg["overwrite"].get("index", False): - logger.info(f"Building QuakeIndex at {idx_path_quake}...") - try: - idx_quake.build(vecs, torch.arange(len(vecs)), build_params) - idx_quake.save(str(idx_path_quake)) - logger.info(f"QuakeIndex built and saved to {idx_path_quake}.") - except Exception as e: - logger.error(f"Failed to build or save QuakeIndex: {e}", exc_info=True) - return - else: - logger.info(f"Loading existing QuakeIndex from {idx_path_quake}...") - try: - idx_quake.load(str(idx_path_quake), 0) - logger.info(f"QuakeIndex loaded successfully.") - except Exception as e: - logger.error(f"Failed to load QuakeIndex from {idx_path_quake}: {e}", exc_info=True) - return - - current_index_nlist = idx_quake.nlist() if callable(getattr(idx_quake, 'nlist', None)) else getattr(idx_quake, 'nlist', build_params.nlist) - if current_index_nlist != build_params.nlist: - logger.warning(f"QuakeIndex nlist ({current_index_nlist}) differs from config ({build_params.nlist}). Using index's nlist: {current_index_nlist}.") - max_nlist_val = current_index_nlist - - - # 4) Initialize LAETPipeline if "LAET" is in methods - laet_pipeline_instance = None - if "LAET" in cfg["methods"]: - if not idx_quake: - logger.error("LAET method requires QuakeIndex, but it's not available. Skipping LAET.") - else: - laet_main_cfg = cfg.get("laet_config", {}) - laet_paths_cfg = cfg.get("paths", {}) # For laet_artifacts_base_dir - - # Prepare config for LAETPipeline constructor - pipeline_init_config = { - "base_dir": laet_paths_cfg.get("laet_artifacts_base_dir", "laet_pipeline_output"), - "training_data_subdir": laet_main_cfg.get("training_data_subdir", "laet_training_data"), - "model_subdir": laet_main_cfg.get("model_subdir", "laet_gbdt_models"), - "dataset_name_for_files": laet_main_cfg.get("dataset_name_for_files", dataset_name.upper()), - "index_key_for_files": laet_main_cfg.get("index_key_for_files", f"IVF{max_nlist_val}_Flat"), - "model_was_trained_on_log_target": laet_main_cfg.get("train_log_target", False) # Used for model naming if trained by pipeline - } - - laet_pipeline_instance = LAETPipeline(vector_dim=queries_torch.shape[1], - laet_artifacts_config=pipeline_init_config) - - # Prepare configs for get_or_train_model - # These paths should point to your primary dataset files for LAET GBDT training - data_paths_for_laet_training = { - "base_vectors": laet_main_cfg.get("base_vectors_path_for_laet_train", f"data/{dataset_name}_base.fvecs"), - "train_query_vectors": laet_main_cfg.get("train_query_vectors_path_for_laet_train", f"data/{dataset_name}_learn.fvecs"), - "gt_train": laet_main_cfg.get("gt_train_path_for_laet_train", f"data/{dataset_name}_learn_groundtruth.ivecs"), - "gt_format": laet_main_cfg.get("gt_format_for_laet_train", "ivecs"), - "training_vectors_for_faiss_index": laet_main_cfg.get("faiss_training_vectors_path_for_laet_train", f"data/{dataset_name}_learn.fvecs") - } - generation_params_for_laet_training = { - "num_train_queries_to_process": laet_main_cfg.get("num_laet_training_samples", 10000), - "k_gt_load_for_target": laet_main_cfg.get("laet_train_k_gt_load", 1), - "k_search_for_target": laet_main_cfg.get("laet_train_k_search", 10), - "max_nprobe_scan": laet_main_cfg.get("laet_train_max_nprobe", 128), - "max_efsearch_scan": laet_main_cfg.get("laet_train_max_efsearch", 256), - "param_scan_step": laet_main_cfg.get("laet_train_param_scan_step", 1) - } - faiss_params_for_laet_training = { - "faiss_index_key_for_gen": laet_main_cfg.get("faiss_index_key_for_laet_train_gen", f"IVF{max_nlist_val},Flat") - } - gbdt_training_params_for_laet = { - "log_target_training": laet_main_cfg.get("train_log_target", False), # This sets log_target_prediction in pipeline - "test_size": laet_main_cfg.get("train_gbdt_test_size", 0.1), - "num_leaves": laet_main_cfg.get("train_gbdt_num_leaves", 31), - "learning_rate": laet_main_cfg.get("train_gbdt_lr", 0.05), - "n_estimators": laet_main_cfg.get("train_gbdt_n_estimators", 100), - "feature_fraction": laet_main_cfg.get("train_gbdt_feature_fraction", 0.9), - "bagging_fraction": laet_main_cfg.get("train_gbdt_bagging_fraction", 0.8), - "bagging_freq": laet_main_cfg.get("train_gbdt_bagging_freq", 5) - } - - laet_pipeline_instance.get_or_train_model( - overwrite_model=cfg.get("overwrite", {}).get("laet_model", False), - data_paths_config=data_paths_for_laet_training, - generation_params_config=generation_params_for_laet_training, - faiss_params_config=faiss_params_for_laet_training, - training_params_config=gbdt_training_params_for_laet + raise ImportError( + "LAET is required for this experiment but could not be imported. " + "Install the laet package or fix PYTHONPATH." + ) from e + +# ── logging ─────────────────────────────────────────────────────────────────── +logging.basicConfig( + level=logging.INFO, format="%(asctime)s | %(levelname)7s | %(message)s", datefmt="%H:%M:%S" +) +logger = logging.getLogger("experiment") + + +# ----------------------------------------------------------------------------- # +# Helpers +# ----------------------------------------------------------------------------- # +def make_sp(**attrs) -> SearchParams: + """Create SearchParams then set attributes (bindings have no kwargs ctor).""" + sp = SearchParams() + for k, v in attrs.items(): + setattr(sp, k, v) + return sp + + +def tune_auncel_a( + idx: QuakeIndex, + queries: torch.Tensor, + gt: torch.Tensor, + k: int, + target_recall: float, + recompute_thr: float, + init_frac: float, + max_iters: int = 15, + a_min: float = 1e-5, + a_max: float = .5, +) -> tuple[float, list[tuple[float, float, float]]]: + """ + Binary-search the smallest 'a' that still meets the recall target. + Returns (best_a, per_query_stats) where the stats are + (nprobe, recall, latency_ms) for the final run. + """ + best_a = a_max + lo, hi = a_min, a_max + best_stats: list[tuple[float, float, float]] = [] + + for _ in range(max_iters): + mid = (lo + hi) / 2.0 + per_query: list[tuple[float, float, float]] = [] + + for q, g in zip(queries, gt): + sp = make_sp( + nprobe=-1, + k=k, + recall_target=target_recall, + use_auncel=True, + auncel_a=mid, + auncel_b=.5, + recompute_threshold=recompute_thr, + initial_search_fraction=init_frac, + ) + t0 = time.perf_counter_ns() + res = idx.search(q.unsqueeze(0), sp) + per_query.append( + ( + getattr(res.timing_info, "partitions_scanned", np.nan), + compute_recall(res.ids, g.unsqueeze(0), k).item(), + (time.perf_counter_ns() - t0) / 1e6, + ) ) - logger.info("LAET GBDT model is ready (loaded or trained).") - # 5) Run each method × recall_target - records = [] - k_metric = cfg["experiment"]["k"] + mean_recall = np.mean([r for _, r, _ in per_query]) + if mean_recall >= target_recall: + # feasible → try smaller a + best_a, best_stats = mid, per_query + hi = mid * 0.5 + else: + # not enough recall → increase a + lo = mid * 1.5 + if hi - lo < 1e-3: + break + + return best_a, best_stats + + +def binary_search_best_nprobe( + idx: QuakeIndex, + queries: torch.Tensor, + gt: torch.Tensor, + k: int, + target_recall: float, + max_nprobe: int, + use_spann: bool = False, + spann_eps: float = 1.5, +) -> int: + """Return smallest nprobe reaching `target_recall` on the supplied queries.""" + lo, hi, best = 1, max_nprobe, max_nprobe + while lo <= hi: + mid = (lo + hi) // 2 + sp = make_sp(k=k, nprobe=mid, use_spann=use_spann, spann_eps=spann_eps if use_spann else 0.0) + ids_all = [ + idx.search(q.unsqueeze(0), sp).ids + for q in queries + if idx.search(q.unsqueeze(0), sp).ids.numel() + ] + mean_rec = ( + compute_recall(torch.cat(ids_all, 0), gt, k).mean().item() if ids_all else 0.0 + ) + if mean_rec >= target_recall: + best, hi = mid, mid - 1 + else: + lo = mid + 1 + return best + + +def print_markdown(df: pd.DataFrame) -> None: + print("\n" + "-" * 80) + print(df.to_markdown(index=False, floatfmt=".4f")) + print("-" * 80 + "\n") + + +# ----------------------------------------------------------------------------- # +# Core experiment +# ----------------------------------------------------------------------------- # +def run_experiment(cfg_path: str, output_dir: str) -> None: + # 1) ---------------------------------------------------------------- config + cfg = yaml.safe_load(Path(cfg_path).read_text()) + out_dir = Path(output_dir).expanduser() + out_dir.mkdir(parents=True, exist_ok=True) + + k = cfg["experiment"]["k"] + recall_targets: List[float] = cfg["experiment"]["recall_targets"] + table_targets = {0.80, 0.90, 0.99} + + # 2) ---------------------------------------------------------------- data + vecs, queries, gt = load_dataset(cfg["dataset"]["name"], cfg["dataset"].get("path", "")) + nq = min(cfg["experiment"].get("nq", queries.shape[0]), queries.shape[0]) + queries, gt = queries[:nq], gt[:nq] + logger.info(f"Dataset loaded – {len(vecs):,} base vecs, {nq} queries.") + + # 3) ---------------------------------------------------------------- index + idx = QuakeIndex() + bp = IndexBuildParams() + bp.nlist = cfg["index"]["nlist"] + bp.metric = cfg["index"]["metric"] + bp.num_workers = cfg["experiment"].get("n_workers", 0) + + idx_file = Path(cfg["paths"]["index_dir"]) / f"{cfg['dataset']['name']}_quake_ivf{bp.nlist}.index" + idx_file.parent.mkdir(parents=True, exist_ok=True) + if idx_file.exists() and not cfg["overwrite"].get("index", False): + idx.load(str(idx_file), 0) + logger.info("Index loaded from disk.") + else: + logger.info("Building index …") + idx.build(vecs, torch.arange(len(vecs)), bp) + idx.save(str(idx_file)) + logger.info(f"Index saved to {idx_file}") + + max_nprobe = idx.nlist() if callable(getattr(idx, "nlist", None)) else bp.nlist + + # 4) ---------------------------------------------------------------- LAET (train / load) + laet_cfg = cfg["laet_config"] + + # required dicts for get_or_train_model + data_paths_cfg = { + "base_vectors": laet_cfg["base_vectors_path_for_laet_train"], + "train_query_vectors": laet_cfg["train_query_vectors_path_for_laet_train"], + "gt_train": laet_cfg["gt_train_path_for_laet_train"], + "gt_format": laet_cfg.get("gt_format_for_laet_train", "ivecs"), + "training_vectors_for_faiss_index": laet_cfg["faiss_training_vectors_path_for_laet_train"], + } + generation_params_cfg = { + "num_train_queries_to_process": laet_cfg.get("num_laet_training_samples", 10000), + "k_gt_load_for_target": laet_cfg.get("laet_train_k_gt_load", 1), + "k_search_for_target": laet_cfg.get("laet_train_k_search", 10), + "max_nprobe_scan": laet_cfg.get("laet_train_max_nprobe", 128), + "max_efsearch_scan": laet_cfg.get("laet_train_max_efsearch", 256), + "param_scan_step": laet_cfg.get("laet_train_param_scan_step", 1), + } + faiss_params_cfg = { + "faiss_index_key_for_gen": laet_cfg.get("faiss_index_key_for_laet_train_gen", f"IVF{max_nprobe},Flat") + } + training_params_cfg = { + "log_target_training": laet_cfg.get("train_log_target", False), + "test_size": laet_cfg.get("train_gbdt_test_size", 0.1), + "num_leaves": laet_cfg.get("train_gbdt_num_leaves", 31), + "learning_rate": laet_cfg.get("train_gbdt_lr", 0.05), + "n_estimators": laet_cfg.get("train_gbdt_n_estimators", 100), + "feature_fraction": laet_cfg.get("train_gbdt_feature_fraction", 0.9), + "bagging_fraction": laet_cfg.get("train_gbdt_bagging_fraction", 0.8), + "bagging_freq": laet_cfg.get("train_gbdt_bagging_freq", 5), + } + + laet = LAETPipeline( + vector_dim=queries.shape[1], + laet_artifacts_config={ + "base_dir": cfg["paths"]["laet_artifacts_base_dir"], + "dataset_name_for_files": laet_cfg.get( + "dataset_name_for_files", cfg["dataset"]["name"].upper() + ), + "index_key_for_files": laet_cfg.get("index_key_for_files", f"IVF{max_nprobe}_Flat"), + "model_subdir": laet_cfg.get("model_subdir", "laet_gbdt_models"), + }, + ) + + t_train0 = time.perf_counter_ns() + laet.get_or_train_model( + overwrite_model=False, + data_paths_config=data_paths_cfg, + generation_params_config=generation_params_cfg, + faiss_params_config=faiss_params_cfg, + training_params_config=training_params_cfg, + ) + laet_training_ns = time.perf_counter_ns() - t_train0 + logger.info(f"LAET model ready (train/load time: {laet_training_ns/1e6:.1f} ms).") + + # 5) --------------------------------------------------------------- run methods + records: List[Dict] = [] for method in cfg["methods"]: - for rt_metric in cfg["experiment"]["recall_targets"]: - logger.info(f"Running Method: {method}, Target Recall: {rt_metric:.3f}") - - mean_param_val, mean_recall_val, mean_time_ms_val = np.nan, np.nan, np.nan - std_param_val, std_recall_val, std_time_ms_val = np.nan, np.nan, np.nan - per_query_data_list = [] - - if method == "LAET": - if laet_pipeline_instance and idx_quake and laet_pipeline_instance.gbdt_model: - quake_sp_for_laet = SearchParams() - # k and nprobe will be set inside run_inference_for_quake_experiment - - bs_multiplier_range = tuple(laet_main_cfg.get("inference_multiplier_range", [0.1, 50.0])) - bs_steps = laet_main_cfg.get("inference_num_bs_steps", 20) - - try: - mean_param_val, mean_recall_val, mean_time_ms_val = \ - laet_pipeline_instance.run_inference_for_quake_experiment( - quake_idx=idx_quake, # Corrected from quake_index to idx_quake - queries_torch=queries_torch, - gt_torch=gt_torch, - target_recall=rt_metric, # Corrected from target_recall_metric - k_search=k_metric, # Corrected from k_search_quake - base_quake_sp=quake_sp_for_laet, # Corrected from base_quake_search_params - num_bs_steps=bs_steps, - multiplier_range=bs_multiplier_range - ) - std_param_val, std_recall_val, std_time_ms_val = 0.0, 0.0, 0.0 - logger.info(f"LAET @ RT={rt_metric:.3f} -> AvgParam={mean_param_val:.2f}, AvgRecall={mean_recall_val:.4f}, AvgTime={mean_time_ms_val:.3f}ms") - except Exception as e: - logger.error(f"Error during LAET inference run: {e}", exc_info=True) - mean_param_val, mean_recall_val, mean_time_ms_val = np.nan, np.nan, np.nan - else: - logger.warning(f"LAET method specified but pipeline/model or QuakeIndex not ready. Skipping for RT={rt_metric}.") - # Metrics remain NaN by default - - elif method in ["Oracle", "FixedNProbe", "APS", "Auncel", "SPANN"]: - if not idx_quake: - logger.warning(f"QuakeIndex not available for method {method}. Skipping.") - continue - - if method == "Oracle": - for i, q_single_torch in enumerate(queries_torch): - lo, hi, best_param_oracle = 1, max_nlist_val, max_nlist_val - while lo <= hi: - mid_param = (lo + hi) // 2 - sp_oracle_bs = SearchParams() - sp_oracle_bs.nprobe = mid_param - sp_oracle_bs.k = k_metric - res_oracle_bs = idx_quake.search(q_single_torch.unsqueeze(0), sp_oracle_bs) - rec_oracle_bs = compute_recall(res_oracle_bs.ids, gt_torch[i].unsqueeze(0), k_metric).item() - if rec_oracle_bs >= rt_metric: - best_param_oracle = mid_param - hi = mid_param - 1 - else: - lo = mid_param + 1 - - t_start_ns = time.perf_counter_ns() - sp_oracle_final = SearchParams() - sp_oracle_final.nprobe = best_param_oracle - sp_oracle_final.k = k_metric - res_oracle_final = idx_quake.search(q_single_torch.unsqueeze(0), sp_oracle_final) - elapsed_ns = time.perf_counter_ns() - t_start_ns - rec_oracle_final = compute_recall(res_oracle_final.ids, gt_torch[i].unsqueeze(0), k_metric).item() - per_query_data_list.append((best_param_oracle, rec_oracle_final, elapsed_ns / 1_000_000.0)) - - elif method == "Auncel": - for i, q_single_torch in enumerate(queries_torch): - sp_auncel = SearchParams() - sp_auncel.nprobe = -1 - sp_auncel.k = k_metric - sp_auncel.recall_target = rt_metric - sp_auncel.recompute_threshold = cfg["experiment"].get("recompute_ratio", 0.00001) - sp_auncel.use_auncel = True - sp_auncel.auncel_a = .005 - sp_auncel.auncel_b = 1.0 - sp_auncel.initial_search_fraction = cfg["experiment"].get("initial_search_fraction", 0.1) - - t_start_ns = time.perf_counter_ns() - res_auncel = idx_quake.search(q_single_torch.unsqueeze(0), sp_auncel) - elapsed_ns = time.perf_counter_ns() - t_start_ns - rec_auncel = compute_recall(res_auncel.ids, gt_torch[i].unsqueeze(0), k_metric).item() - param_aps = res_auncel.timing_info.partitions_scanned if hasattr(res_auncel, 'timing_info') and hasattr(res_auncel.timing_info, 'partitions_scanned') else np.nan - per_query_data_list.append((param_aps, rec_auncel, elapsed_ns / 1_000_000.0)) - - elif method == "SPANN": - lo_fixed, hi_fixed, best_overall_param_fixed = 1, max_nlist_val, max_nlist_val - while lo_fixed <= hi_fixed: - mid_param_fixed = (lo_fixed + hi_fixed) // 2 - sp_fixed_bs = SearchParams() - sp_fixed_bs.nprobe = mid_param_fixed - sp_fixed_bs.k = k_metric - sp_fixed_bs.use_spann = False - sp_fixed_bs.spann_eps = 2.0 - sp_fixed_bs.recall_target = -1 - - ids_list_fixed = [] - for q_bs_fixed in queries_torch: - res_bs_fixed = idx_quake.search(q_bs_fixed.unsqueeze(0), sp_fixed_bs) - if res_bs_fixed.ids is not None and res_bs_fixed.ids.numel() > 0: - ids_list_fixed.append(res_bs_fixed.ids) - - if not ids_list_fixed: avg_rec_fixed = 0.0 - else: avg_rec_fixed = compute_recall(torch.cat(ids_list_fixed, 0), gt_torch, k_metric).mean().item() - - if avg_rec_fixed >= rt_metric: - best_overall_param_fixed = mid_param_fixed - hi_fixed = mid_param_fixed - 1 - else: lo_fixed = mid_param_fixed + 1 - - for i, q_single_torch in enumerate(queries_torch): - t_start_ns = time.perf_counter_ns() - sp_fixed_final = SearchParams() - sp_fixed_final.nprobe = best_overall_param_fixed - sp_fixed_final.k = k_metric - sp_fixed_final.use_spann = True - sp_fixed_final.spann_eps = 1.5 - res_fixed_final = idx_quake.search(q_single_torch.unsqueeze(0), sp_fixed_final) - elapsed_ns = time.perf_counter_ns() - t_start_ns - rec_fixed_final = compute_recall(res_fixed_final.ids, gt_torch[i].unsqueeze(0), k_metric).item() - param_spann = res_fixed_final.timing_info.partitions_scanned if hasattr(res_fixed_final, 'timing_info') and hasattr(res_fixed_final.timing_info, 'partitions_scanned') else np.nan - per_query_data_list.append((param_spann, rec_fixed_final, elapsed_ns / 1_000_000.0)) - - elif method == "FixedNProbe": - lo_fixed, hi_fixed, best_overall_param_fixed = 1, max_nlist_val, max_nlist_val - while lo_fixed <= hi_fixed: - mid_param_fixed = (lo_fixed + hi_fixed) // 2 - sp_fixed_bs = SearchParams() - sp_fixed_bs.nprobe = mid_param_fixed - sp_fixed_bs.k = k_metric - sp_fixed_bs.recall_target = -1 - - ids_list_fixed = [] - for q_bs_fixed in queries_torch: - res_bs_fixed = idx_quake.search(q_bs_fixed.unsqueeze(0), sp_fixed_bs) - if res_bs_fixed.ids is not None and res_bs_fixed.ids.numel() > 0: - ids_list_fixed.append(res_bs_fixed.ids) - - if not ids_list_fixed: avg_rec_fixed = 0.0 - else: avg_rec_fixed = compute_recall(torch.cat(ids_list_fixed, 0), gt_torch, k_metric).mean().item() - - if avg_rec_fixed >= rt_metric: - best_overall_param_fixed = mid_param_fixed - hi_fixed = mid_param_fixed - 1 - else: lo_fixed = mid_param_fixed + 1 - - for i, q_single_torch in enumerate(queries_torch): - t_start_ns = time.perf_counter_ns() - sp_fixed_final = SearchParams() - sp_fixed_final.nprobe = best_overall_param_fixed - sp_fixed_final.k = k_metric - sp_fixed_final.recall_target = -1 - res_fixed_final = idx_quake.search(q_single_torch.unsqueeze(0), sp_fixed_final) - elapsed_ns = time.perf_counter_ns() - t_start_ns - rec_fixed_final = compute_recall(res_fixed_final.ids, gt_torch[i].unsqueeze(0), k_metric).item() - per_query_data_list.append((best_overall_param_fixed, rec_fixed_final, elapsed_ns / 1_000_000.0)) - - elif method == "APS": - for i, q_single_torch in enumerate(queries_torch): - sp_aps = SearchParams() - sp_aps.nprobe = -1 - sp_aps.k = k_metric - sp_aps.recall_target = rt_metric - sp_aps.recompute_threshold = cfg["experiment"].get("recompute_ratio", 0.00001) - sp_aps.use_precomputed = cfg["experiment"].get("use_precompute", True) - sp_aps.initial_search_fraction = cfg["experiment"].get("initial_search_fraction", 0.1) - - t_start_ns = time.perf_counter_ns() - res_aps = idx_quake.search(q_single_torch.unsqueeze(0), sp_aps) - elapsed_ns = time.perf_counter_ns() - t_start_ns - rec_aps = compute_recall(res_aps.ids, gt_torch[i].unsqueeze(0), k_metric).item() - param_aps = res_aps.timing_info.partitions_scanned if hasattr(res_aps, 'timing_info') and hasattr(res_aps.timing_info, 'partitions_scanned') else np.nan - per_query_data_list.append((param_aps, rec_aps, elapsed_ns / 1_000_000.0)) - - if per_query_data_list: - arr = np.array(per_query_data_list, dtype=float) - if arr.size > 0: - mean_param_val, mean_recall_val, mean_time_ms_val = np.nanmean(arr, axis=0) - std_param_val, std_recall_val, std_time_ms_val = np.nanstd(arr, axis=0) - logger.info(f"{method} @ RT={rt_metric:.3f} -> AvgParam={mean_param_val:.2f}, AvgRecall={mean_recall_val:.4f}, AvgTime={mean_time_ms_val:.3f}ms") + for rt in recall_targets: + logger.info(f"{method:>10s} | target recall {rt:.2f}") + per_query = [] # tuples of (nprobe, recall, q_ms) + tuning_ns = 0 + + # ---------------------------------------------------------------- # + if method == "Oracle": + for q, g in zip(queries, gt): + t0 = time.perf_counter_ns() + best_np = binary_search_best_nprobe( + idx, q.unsqueeze(0), g.unsqueeze(0), k, rt, max_nprobe + ) + tuning_ns += time.perf_counter_ns() - t0 + sp = make_sp(k=k, nprobe=best_np) + t1 = time.perf_counter_ns() + res = idx.search(q.unsqueeze(0), sp) + per_query.append( + ( + best_np, + compute_recall(res.ids, g.unsqueeze(0), k).item(), + (time.perf_counter_ns() - t1) / 1e6, + ) + ) + + elif method in ("FixedNProbe", "SPANN"): + t0 = time.perf_counter_ns() + best_np = binary_search_best_nprobe( + idx, + queries, + gt, + k, + rt, + max_nprobe, + use_spann=(method == "SPANN"), + spann_eps=1.5, + ) + tuning_ns = time.perf_counter_ns() - t0 + for q, g in zip(queries, gt): + sp = make_sp( + k=k, + nprobe=best_np, + use_spann=(method == "SPANN"), + spann_eps=1.5 if method == "SPANN" else 0.0, + ) + t1 = time.perf_counter_ns() + res = idx.search(q.unsqueeze(0), sp) + per_query.append( + ( + best_np, + compute_recall(res.ids, g.unsqueeze(0), k).item(), + (time.perf_counter_ns() - t1) / 1e6, + ) + ) + + elif method == "APS": + for q, g in zip(queries, gt): + sp = make_sp( + nprobe=-1, + k=k, + recall_target=rt, + recompute_threshold=cfg["experiment"]["recompute_ratio"], + use_precomputed=cfg["experiment"]["use_precompute"], + initial_search_fraction=cfg["experiment"]["initial_search_fraction"], + ) + t1 = time.perf_counter_ns() + res = idx.search(q.unsqueeze(0), sp) + per_query.append( + ( + getattr(res.timing_info, "partitions_scanned", np.nan), + compute_recall(res.ids, g.unsqueeze(0), k).item(), + (time.perf_counter_ns() - t1) / 1e6, + ) + ) + + elif method == "Auncel": + t0 = time.perf_counter_ns() + best_a, per_query = tune_auncel_a( + idx, + queries, + gt, + k, + rt, + recompute_thr=cfg["experiment"]["recompute_ratio"], + init_frac=cfg["experiment"]["initial_search_fraction"], + ) + tuning_ns = time.perf_counter_ns() - t0 + logger.info(f"Auncel @ RT={rt:.2f} → selected a = {best_a:.4f}") + + elif method == "LAET": + t0 = time.perf_counter_ns() + mean_np, mean_rec, mean_ms = laet.run_inference_for_quake_experiment( + quake_idx=idx, + queries_torch=queries, + gt_torch=gt, + target_recall=rt, + k_search=k, + base_quake_sp=make_sp(k=k), + ) + tuning_ns = laet_training_ns + (time.perf_counter_ns() - t0) + per_query.append((mean_np, mean_rec, mean_ms)) + else: - if method != "LAET": - logger.warning(f"Unknown method: {method}. Skipping.") - continue - - records.append({ - "Method": method, "RecallTarget": rt_metric, - "mean_nprobe": mean_param_val, "std_nprobe": std_param_val, - "mean_recall": mean_recall_val, "std_recall": std_recall_val, - "mean_time_ms": mean_time_ms_val, "std_time_ms": std_time_ms_val, - }) - - # 6) Save CSV - df_results = pd.DataFrame(records) - csv_filename = cfg["paths"].get("results_file_prefix", "experiment_summary") + f"_{dataset_name}.csv" - out_csv_path = out_path / csv_filename - df_results.to_csv(out_csv_path, index=False, float_format='%.4f') - logger.info(f"Results summary saved to: {out_csv_path}") - - # 7) Plotting - if not df_results.empty: - plot_filename = cfg["paths"].get("plot_file_prefix", "recall_comparison_plots") + f"_{dataset_name}.png" - plot_output_dir = Path(cfg["paths"].get("plot_dir", output_dir_str)) - plot_output_dir.mkdir(parents=True, exist_ok=True) - plot_path_full = plot_output_dir / plot_filename - - fig, axes = plt.subplots(3, 1, figsize=(10, 12), sharex=True) - unique_methods_in_results = df_results["Method"].unique() - - for m_name in unique_methods_in_results: - grp = df_results[df_results["Method"] == m_name].sort_values(by="RecallTarget") - if grp.empty: continue - - axes[0].plot(grp["RecallTarget"], grp["mean_time_ms"], marker="o", label=m_name, alpha=0.5) - axes[1].plot(grp["RecallTarget"], grp["mean_recall"], marker="o", label=m_name, alpha=0.5) - axes[2].plot(grp["RecallTarget"], grp["mean_nprobe"], marker="o", label=m_name, alpha=0.5) - - axes[0].set_ylabel("Mean Query Time (ms)") - axes[0].set_yscale("log") - axes[0].set_title(f"Recall Target vs. Query Time ({dataset_name})") - axes[0].legend(); axes[0].grid(True, ls=":", alpha=0.7) - - recall_target_line_plot = np.array(cfg["experiment"]["recall_targets"]) - axes[1].plot(recall_target_line_plot, recall_target_line_plot, "k--", label="Target Recall", alpha=0.7) - axes[1].set_ylabel("Achieved Mean Recall") - axes[1].set_title(f"Recall Target vs. Achieved Recall ({dataset_name})") - axes[1].legend(); axes[1].grid(True, ls=":", alpha=0.7) - min_r, max_r = (df_results["mean_recall"].min() if pd.notna(df_results["mean_recall"].min()) else 0.0, - df_results["mean_recall"].max() if pd.notna(df_results["mean_recall"].max()) else 1.0) - axes[1].set_ylim(bottom=max(0.0, min_r - 0.05), top=min(1.01, max_r + 0.05)) - - axes[2].set_xlabel("Recall Target") - axes[2].set_ylabel("Num Partitions Scanned") - axes[2].set_yscale("log"); axes[2].set_title(f"Recall Target vs. Search Parameter ({dataset_name})") - axes[2].legend(); axes[2].grid(True, which="both", ls=":", alpha=0.7) - - plt.tight_layout(); plt.savefig(plot_path_full); plt.close(fig) - logger.info(f"Plots saved to: {plot_path_full}") - else: - logger.info("No data in results DataFrame, skipping plotting.") + logger.warning(f"Unknown method '{method}' – skipping.") + continue + # ---------------------------------------------------------------- # + + if not per_query: + continue + arr = np.asarray(per_query, dtype=float) + mean_np, mean_rec, mean_q_ms = np.nanmean(arr, axis=0) + + records.append( + dict( + Method=method, + RecallTarget=rt, + RecallAchieved=mean_rec, + nprobe=mean_np, + QueryLatencyMs=mean_q_ms, + TuningTimeMs=tuning_ns / 1e6, + ) + ) + + # 6) ------------------------------------------------------------- results + df = pd.DataFrame(records) + df_out = df[df["RecallTarget"].isin(table_targets)].copy().sort_values( + ["Method", "RecallTarget"] + ) + csv_path = out_dir / f"aps_et_results_{cfg['dataset']['name']}.csv" + df_out.to_csv(csv_path, index=False, float_format="%.4f") + logger.info(f"Results written to {csv_path}") + print_markdown(df_out) + + # 7) ------------------------------------------------------------- plot + if cfg.get("plot", {}).get("enable", False) and _HAVE_MPL: + plt.figure(figsize=(6, 4)) + for m in df["Method"].unique(): + d = df[df["Method"] == m] + plt.plot(d["RecallTarget"], d["QueryLatencyMs"], marker="o", label=m, alpha=0.7) + plt.yscale("log") + plt.xlabel("Recall target") + plt.ylabel("Mean query latency (ms)") + plt.title(cfg["dataset"]["name"]) + plt.legend() + plt.tight_layout() + plt.savefig(out_dir / f"latency_plot_{cfg['dataset']['name']}.png", dpi=200) \ No newline at end of file diff --git a/test/experiments/osdi2025/maintenance_ablation/run.py b/test/experiments/osdi2025/maintenance_ablation/run.py index 70e40db5..0173457b 100644 --- a/test/experiments/osdi2025/maintenance_ablation/run.py +++ b/test/experiments/osdi2025/maintenance_ablation/run.py @@ -2,143 +2,144 @@ """ Quake maintenance–ablation runner ───────────────────────────────── -• Builds / runs / plots exactly like the original “kick-the-tires” script. -• Per-operation CSV rows now contain - n_splits n_deletes maintenance_time_ms - (written by WorkloadEvaluator below). -• After all indices finish, this script also produces - //time_breakdown.png - – a stacked-bar chart of cumulative time spent in - Search / Insert / Delete / Maintenance / Total. +Extends the original “kick-the-tires” driver with: + +1. *summary_table.csv* – cumulative times + final partition count +2. *summary_table.md* – Markdown, via **tabulate** +3. *time_breakdown.png* – stacked bars (unchanged) +4. *unified_plot.png* – nine-panel diagnostic (unchanged) + +Per-index artefacts (under //): + results.csv – per-operation log + time_breakdown.png – per-index stacked bars """ from __future__ import annotations -import argparse, logging + +import argparse +import logging from pathlib import Path from typing import Dict, List + import matplotlib.pyplot as plt -from matplotlib.lines import Line2D +import numpy as np +import pandas as pd +import yaml +from tabulate import tabulate from matplotlib.cm import get_cmap -import numpy as np, pandas as pd, yaml +from matplotlib.lines import Line2D -# quake wrappers ---------------------------------------------------------------- +# ── quake wrappers ------------------------------------------------------------ from quake.datasets.ann_datasets import load_dataset from quake.index_wrappers.faiss_ivf import FaissIVF -from quake.index_wrappers.quake import QuakeWrapper -from quake.workload_generator import DynamicWorkloadGenerator, WorkloadEvaluator +from quake.index_wrappers.quake import QuakeWrapper +from quake.workload_generator import DynamicWorkloadGenerator, WorkloadEvaluator -logging.basicConfig(level=logging.INFO, format="%(asctime)s | %(levelname)s | %(message)s") +logging.basicConfig(level=logging.INFO, + format="%(asctime)s | %(levelname)s | %(message)s") log = logging.getLogger(__name__) - +# ── constants ----------------------------------------------------------------- OP_STYLE = { - "query" : dict(ls="-", marker="o", mfc="none", ms=4, lw=1.2), - "insert" : dict(ls="-", marker="s", mfc="none", ms=4, lw=1.2), - "delete" : dict(ls="-", marker="^", mfc="none", ms=4, lw=1.2), - "maintain": dict(ls="None", marker="X", mfc="black", ms=5), # points only + "query": dict(ls="-", marker="o", mfc="none", ms=4, lw=1.2), + "insert": dict(ls="-", marker="s", mfc="none", ms=4, lw=1.2), + "delete": dict(ls="-", marker="^", mfc="none", ms=4, lw=1.2), + "maintain": dict(ls="None", marker="X", mfc="black", ms=5), } LAT_OPS = ["query", "insert", "delete", "maintain"] IDX_LAT_Q, IDX_LAT_I, IDX_LAT_D, IDX_LAT_M = 0, 1, 2, 3 -IDX_PART, IDX_RES, IDX_REC, IDX_TOT, IDX_SPL = 4, 5, 6, 7, 8 - +IDX_PART, IDX_RES, IDX_REC, IDX_TOT, IDX_SPL = 4, 5, 6, 7, 8 +# ══════════════════════════════════════════════════════════════════════════════ +# Plot: unified nine-panel diagnostic +# ══════════════════════════════════════════════════════════════════════════════ def unified_plot(cfg: Dict, out_dir: Path) -> None: styles = cfg["plot"].get("styles", {}) - fig, axs2d = plt.subplots(3, 3, figsize=(18, 12), sharex="col") axs = axs2d.flatten() - # ── index legend handles (colour / marker) ──────────────────────────────── + # legend handles ----------------------------------------------------------- idx_handles: List[Line2D] = [] for j, idx in enumerate(cfg["indexes"]): nm, st = idx["name"], styles.get(idx["name"], {}) - idx_handles.append( - Line2D([0], [0], - color = st.get("color", f"C{j}"), - marker = st.get("marker", "o"), - ls = "", - markersize = 6, - label = nm)) - - # ── plot each index ────────────────────────────────────────────────────── + idx_handles.append(Line2D([0], [0], + color=st.get("color", f"C{j}"), + marker=st.get("marker", "o"), + ls="", markersize=6, label=nm)) + + # traces ------------------------------------------------------------------- for j, idx in enumerate(cfg["indexes"]): - name = idx["name"] - st = styles.get(name, {}) + name = idx["name"] + st = styles.get(name, {}) colour = st.get("color", f"C{j}") marker = st.get("marker", "o") csv = out_dir / name / "results.csv" if not csv.exists(): - print(f"[unified_plot] warning: {csv} missing – skipped") + log.warning("[unified_plot] %s missing – skipped.", csv) continue - df = pd.read_csv(csv) - # latency panels ------------------------------------------------------ - for op, ax_idx in zip(LAT_OPS, - [IDX_LAT_Q, IDX_LAT_I, IDX_LAT_D, IDX_LAT_M]): + # latency -------------------------------------------------------------- + for op, ax_idx in zip(LAT_OPS, [IDX_LAT_Q, IDX_LAT_I, IDX_LAT_D, IDX_LAT_M]): ax = axs[ax_idx] if op == "maintain": sub = df[df.maintenance_time_ms.fillna(0) > 0] - y = sub.maintenance_time_ms + y = sub.maintenance_time_ms else: sub = df[df.operation_type == op] - y = sub.latency_ms - if sub.empty: - continue - ax.plot(sub.operation_number, y, - color=colour, - **OP_STYLE[op]) - - # partitions ---------------------------------------------------------- + y = sub.latency_ms + if not sub.empty: + ax.plot(sub.operation_number, y, color=colour, **OP_STYLE[op]) + + # partitions ----------------------------------------------------------- ax = axs[IDX_PART] sub = df[df.n_list.notna()] if not sub.empty: ax.plot(sub.operation_number, sub.n_list, color=colour, marker=marker, lw=1.2) - # resident vectors ---------------------------------------------------- + # resident vectors ----------------------------------------------------- ax = axs[IDX_RES] sub = df[df.n_resident.notna()] if not sub.empty: ax.plot(sub.operation_number, sub.n_resident, color=colour, marker=marker, lw=1.2) - # recall -------------------------------------------------------------- + # recall --------------------------------------------------------------- ax = axs[IDX_REC] sub = df[(df.operation_type == "query") & df.recall.notna()] if not sub.empty: ax.plot(sub.operation_number, sub.recall, color=colour, marker=marker, lw=1.2) - # running total time -------------------------------------------------- + # running total time --------------------------------------------------- ax = axs[IDX_TOT] total_ms = df.latency_ms.fillna(0) + df.maintenance_time_ms.fillna(0) ax.plot(df.operation_number, np.cumsum(total_ms), color=colour, marker=marker, lw=1.2) - # cumulative splits / deletes ---------------------------------------- + # cumulative splits / deletes ----------------------------------------- ax = axs[IDX_SPL] - spl = df.n_splits.fillna(0) - dlt = df.n_deletes.fillna(0) + spl, dlt = df.n_splits.fillna(0), df.n_deletes.fillna(0) if (spl > 0).any(): ax.step(df.operation_number, np.cumsum(spl), where="post", color=colour, ls="--", lw=1.2) if (dlt > 0).any(): ax.step(df.operation_number, np.cumsum(dlt), - where="post", color=colour, ls=":", lw=1.2) + where="post", color=colour, ls=":", lw=1.2) - # ── titles / labels / grids ────────────────────────────────────────────── + # titles / grids ----------------------------------------------------------- titles = { IDX_LAT_Q: "Latency – Query", IDX_LAT_I: "Latency – Insert", IDX_LAT_D: "Latency – Delete", IDX_LAT_M: "Latency – Maintain", - IDX_PART : "# Partitions", - IDX_RES : "Resident Vectors", - IDX_REC : "Recall", - IDX_TOT : "Running Total Time", - IDX_SPL : "Cumulative Splits / Deletes", + IDX_PART: "# Partitions", + IDX_RES: "Resident Vectors", + IDX_REC: "Recall", + IDX_TOT: "Running Total Time", + IDX_SPL: "Cumulative Splits / Deletes", } for i, ax in enumerate(axs): ax.set_title(titles[i], fontsize=11) @@ -146,99 +147,73 @@ def unified_plot(cfg: Dict, out_dir: Path) -> None: ax.set_axisbelow(True) axs[IDX_PART].set_ylabel("count") - axs[IDX_RES ].set_ylabel("# vectors") - axs[IDX_REC ].set_ylabel("recall") - axs[IDX_TOT ].set_ylabel("ms") - axs[IDX_SPL ].set_ylabel("count") + axs[IDX_RES].set_ylabel("# vectors") + axs[IDX_REC].set_ylabel("recall") + axs[IDX_TOT].set_ylabel("ms") + axs[IDX_SPL].set_ylabel("count") - # x-labels only on bottom row for idx in [IDX_PART, IDX_RES, IDX_REC, IDX_TOT, IDX_SPL]: axs[idx].set_xlabel("Operation #") - # common x-limit so vertical grids align - all_ops = max((pd.read_csv(out_dir/idx["name"]/ "results.csv").operation_number.max() + all_ops = max((pd.read_csv(out_dir / idx["name"] / "results.csv").operation_number.max() for idx in cfg["indexes"] - if (out_dir/idx["name"]/ "results.csv").exists()), default=None) + if (out_dir / idx["name"] / "results.csv").exists()), + default=None) if all_ops is not None: for ax in axs: ax.set_xlim(left=0, right=all_ops) - # ── single legend (indexes only) ───────────────────────────────────────── fig.legend(idx_handles, [h.get_label() for h in idx_handles], loc="upper center", bbox_to_anchor=(0.5, 1.03), ncol=min(4, len(idx_handles)), fontsize=9, title="Index", frameon=False) - # save -------------------------------------------------------------------- - plt.tight_layout(rect=[0, 0, 1, 0.97]) # space for top legend + plt.tight_layout(rect=[0, 0, 1, 0.97]) out_path = out_dir / "unified_plot.png" plt.savefig(out_path, dpi=150) - print(f"[unified_plot] → {out_path}") + log.info("[unified_plot] → %s", out_path) plt.close() -# ─────────────────────────────────────────────────────────────────────────────── - +# ══════════════════════════════════════════════════════════════════════════════ +# Plot: stacked-bar time breakdown +# ══════════════════════════════════════════════════════════════════════════════ def make_time_breakdown(cfg: Dict, out_dir: Path) -> None: - """ - Create a side-by-side bar chart showing cumulative time spent in - Search / Insert / Delete / Maintenance / Total for each index. - - Recall values are annotated above each Search bar. - Output file: /time_breakdown.png - """ - import matplotlib.pyplot as plt - from matplotlib.cm import get_cmap - import numpy as np - import pandas as pd - categories = ["Search", "Insert", "Delete", "Maintain", "Total"] - idx_names = [idx["name"] for idx in cfg["indexes"]] - n_idx = len(idx_names) - n_cats = len(categories) - - # Totals and recall tracking - totals = {name: [0]*n_cats for name in idx_names} - recalls = {} + idx_names = [idx["name"] for idx in cfg["indexes"]] + totals, recalls = {}, {} + cmap = get_cmap("tab10") - for idx in cfg["indexes"]: - name = idx["name"] - csv_path = out_dir / name / "results.csv" + for j, idx in enumerate(cfg["indexes"]): + name = idx["name"]; csv_path = out_dir / name / "results.csv" if not csv_path.exists(): - print(f"[make_time_breakdown] warning: no CSV for {name} – skipped") + log.warning("[time_breakdown] missing %s – skipped", csv_path) continue - df = pd.read_csv(csv_path) - totals[name][0] = df[df.operation_type == "query" ].latency_ms.sum() # Search - totals[name][1] = df[df.operation_type == "insert"].latency_ms.sum() # Insert - totals[name][2] = df[df.operation_type == "delete"].latency_ms.sum() # Delete - totals[name][3] = df.maintenance_time_ms.fillna(0).sum() # Maintain - totals[name][4] = sum(totals[name][:4]) # Total - recalls[name] = df[df.operation_type == "query"].recall.mean() # Recall - - # Plotting - x = np.arange(n_cats) - width = 0.8 / max(1, n_idx) + totals[name] = [ + df[df.operation_type == "query"].latency_ms.sum(), + df[df.operation_type == "insert"].latency_ms.sum(), + df[df.operation_type == "delete"].latency_ms.sum(), + df.maintenance_time_ms.fillna(0).sum(), + ] + totals[name].append(sum(totals[name])) + recalls[name] = df[df.operation_type == "query"].recall.mean() + + n_idx, n_cats = len(totals), len(categories) + x = np.arange(n_cats); width = 0.8 / max(1, n_idx) fig, ax = plt.subplots(figsize=(10, 6)) - cmap = get_cmap("tab10") - - for j, name in enumerate(idx_names): - y = totals[name] + for j, (name, values) in enumerate(totals.items()): style = cfg["plot"].get("styles", {}).get(name, {}) color = style.get("color", cmap(j % 10)) - - x_offset = x + (j - (n_idx - 1) / 2) * width - bars = ax.bar(x_offset, y, width=width, label=name, color=color, edgecolor="black") - - # Add recall above Search bar (index 0) - recall_val = recalls.get(name) - if recall_val is not None: - ax.text(x_offset[0], y[0] + 0.01 * max(y), f"Recall={recall_val:.3f}", - ha="center", va="bottom", fontsize=8, rotation=90, color=color) - - ax.set_xticks(x) - ax.set_xticklabels(categories) + x_off = x + (j - (n_idx - 1) / 2) * width + ax.bar(x_off, values, width=width, label=name, + color=color, edgecolor="black") + ax.text(x_off[0], values[0] * 1.01, + f"R={recalls[name]:.3f}", ha="center", + va="bottom", fontsize=7, rotation=90, color=color) + + ax.set_xticks(x); ax.set_xticklabels(categories) ax.set_ylabel("Cumulative Time (ms)") ax.set_title("Time Breakdown per Index") ax.legend(title="Index", frameon=False) @@ -246,59 +221,115 @@ def make_time_breakdown(cfg: Dict, out_dir: Path) -> None: out_path = out_dir / "time_breakdown.png" plt.savefig(out_path, dpi=150) - print(f"[make_time_breakdown] → {out_path}") + log.info("[time_breakdown] → %s", out_path) plt.close() -# ─────────────────────────────────────────────────────────────────────────────── -def run_experiment(cfg_path:str, output_dir:str): +# ══════════════════════════════════════════════════════════════════════════════ +# Summary table (CSV + Markdown) +# ══════════════════════════════════════════════════════════════════════════════ +def produce_summary_table(cfg: Dict, out_dir: Path) -> None: + """ + Write summary_table.csv and summary_table.md with columns: + Index | Search | Insert | Delete | Maintain | Total | Recall | Partitions + Times are cumulative milliseconds; Recall is mean over all queries. + """ + rows = [] + for idx in cfg["indexes"]: + name = idx["name"] + csv_path = out_dir / name / "results.csv" + if not csv_path.exists(): + log.warning("[summary_table] %s missing – skipped", csv_path) + continue + + df = pd.read_csv(csv_path) + search = df[df.operation_type == "query" ].latency_ms.sum() + insert = df[df.operation_type == "insert"].latency_ms.sum() + delete = df[df.operation_type == "delete"].latency_ms.sum() + maintain = df.maintenance_time_ms.fillna(0).sum() + total = search + insert + delete + maintain + recall = df[df.operation_type == "query"].recall.mean() # ← NEW + n_part = (df.n_list.dropna().iloc[-1] + if not df.n_list.dropna().empty else None) + + rows.append(dict(Index=name, + Search=int(search), + Insert=int(insert), + Delete=int(delete), + Maintain=int(maintain), + Total=int(total), + Recall=f"{recall:.4f}" if pd.notna(recall) else "—", + Partitions=n_part)) + + if not rows: + log.warning("[summary_table] no data – nothing written") + return + + df = pd.DataFrame(rows).sort_values("Index") + + csv_path = out_dir / "summary_table.csv" + df.to_csv(csv_path, index=False) + log.info("[summary_table] → %s", csv_path) + + md_path = out_dir / "summary_table.md" + md = tabulate(df, headers="keys", tablefmt="github", showindex=False) + md_path.write_text(md + "\n") + log.info("[summary_table] → %s", md_path) + log.info("\n%s", md) +# ══════════════════════════════════════════════════════════════════════════════ +# Main orchestration +# ══════════════════════════════════════════════════════════════════════════════ +def run_experiment(cfg_path: str, output_dir: str) -> None: cfg = yaml.safe_load(Path(cfg_path).read_text()) - out = Path(output_dir).expanduser(); out.mkdir(parents=True, exist_ok=True) + out = Path(output_dir).expanduser(); out.mkdir(parents=True, exist_ok=True) - # 1 dataset / workload --------------------------------------------------- - if cfg["mode"] in {"build","run"}: + # 1. dataset & workload ---------------------------------------------------- + if cfg["mode"] in {"build", "run"}: ds = cfg["dataset"] - vecs, queries, _ = load_dataset(ds["name"], ds.get("path","")) + vecs, queries, _ = load_dataset(ds["name"], ds.get("path", "")) gen = DynamicWorkloadGenerator( - workload_dir =out, - base_vectors =vecs, - metric =ds["metric"], - insert_ratio =cfg["workload_generator"]["insert_ratio"], - delete_ratio =cfg["workload_generator"]["delete_ratio"], - query_ratio =cfg["workload_generator"]["query_ratio"], - update_batch_size =cfg["workload_generator"]["update_batch_size"], - query_batch_size =cfg["workload_generator"]["query_batch_size"], - number_of_operations =cfg["workload_generator"]["number_of_operations"], - initial_size =cfg["workload_generator"]["initial_size"], - cluster_size =cfg["workload_generator"]["cluster_size"], - cluster_sample_distribution=cfg["workload_generator"]["cluster_sample_distribution"], - queries =queries, + workload_dir = out, + base_vectors = vecs, + metric = ds["metric"], + insert_ratio = cfg["workload_generator"]["insert_ratio"], + delete_ratio = cfg["workload_generator"]["delete_ratio"], + query_ratio = cfg["workload_generator"]["query_ratio"], + update_batch_size = cfg["workload_generator"]["update_batch_size"], + query_batch_size = cfg["workload_generator"]["query_batch_size"], + number_of_operations = cfg["workload_generator"]["number_of_operations"], + initial_size = cfg["workload_generator"]["initial_size"], + cluster_size = cfg["workload_generator"]["cluster_size"], + cluster_sample_distribution= cfg["workload_generator"]["cluster_sample_distribution"], + queries = queries, query_cluster_sample_distribution=cfg["workload_generator"]["query_cluster_sample_distribution"], - seed =cfg["workload_generator"]["seed"]) - if not gen.workload_exists() or cfg["overwrite"].get("workload",False): - log.info("Generating workload …"); gen.generate_workload() + seed = cfg["workload_generator"]["seed"]) + if not gen.workload_exists() or cfg["overwrite"].get("workload", False): + log.info("Generating workload …") + gen.generate_workload() else: log.info("Existing workload found – generation skipped.") - # 2 evaluation ----------------------------------------------------------- - if cfg["mode"]=="run": + # 2. evaluate -------------------------------------------------------------- + if cfg["mode"] == "run": for idx in cfg["indexes"]: - name, res = idx["name"], out/idx["name"] - csv = res/"results.csv" - if csv.exists() and not cfg["overwrite"].get("results",False): - log.info("%s: cached results – skipped.", name); continue + name, res = idx["name"], out / idx["name"] res.mkdir(parents=True, exist_ok=True) + csv = res / "results.csv" + if csv.exists() and not cfg["overwrite"].get("results", False): + log.info("%s: cached results – skipped.", name); continue + eval = WorkloadEvaluator(workload_dir=out, output_dir=res) - cls = {"Quake":QuakeWrapper,"IVF":FaissIVF}[idx["index"]] + cls = {"Quake": QuakeWrapper, "IVF": FaissIVF}[idx["index"]] eval.evaluate_workload( - name =name, - index =cls(), - build_params =idx.get("build_params",{}), - search_params =idx.get("search_params",{}), - m_params=idx.get("maintenance_params",{}), + name = name, + index = cls(), + build_params = idx.get("build_params", {}), + search_params = idx.get("search_params", {}), + m_params = idx.get("maintenance_params", {}), do_maintenance=True, ) - # 3 global plot ---------------------------------------------------------- - if cfg["mode"] in {"run","plot"}: + # 3. global artefacts ------------------------------------------------------ + if cfg["mode"] in {"run", "plot"}: unified_plot(cfg, out) make_time_breakdown(cfg, out) + produce_summary_table(cfg, out) \ No newline at end of file diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index 79a69316..d5881277 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -63,6 +63,7 @@ indexes: search_params: nprobe: 20 batched_scan: false + n_threads: 16 - name: Quake_1_numa index: Quake From 47d5a8c4f616cedefce6eb04b75234f8f233e497 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 18:53:57 -0500 Subject: [PATCH 077/323] fix numa alloc --- src/cpp/include/quake_index.h | 2 +- src/cpp/include/query_coordinator.h | 5 +++-- src/cpp/src/quake_index.cpp | 6 +++--- src/cpp/src/query_coordinator.cpp | 9 +++++---- src/python/index_wrappers/quake.py | 2 +- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/cpp/include/quake_index.h b/src/cpp/include/quake_index.h index 900ecdab..d2377aaa 100644 --- a/src/cpp/include/quake_index.h +++ b/src/cpp/include/quake_index.h @@ -122,7 +122,7 @@ class QuakeIndex { * @param path Path to load the index. * @param n_workers Number of workers to use for query processing. */ - void load(const std::string &path, int n_workers = 0); + void load(const std::string &path, int n_workers = 0, bool use_numa=false); /** * @brief Get the total number of vectors in the index. diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index a3ae0dd5..60a80b48 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -85,7 +85,8 @@ class QueryCoordinator { shared_ptr partition_manager, shared_ptr maintenance_policy, MetricType metric, - int num_workers=0); + int num_workers=0, + bool use_numa=false); /** * @brief Destructor for QueryCoordinator. @@ -148,7 +149,7 @@ class QueryCoordinator { * * @param num_workers Number of worker threads to initialize. */ - void initialize_workers(int num_workers); + void initialize_workers(int num_workers, bool use_numa=false); /** * @brief Shuts down all worker threads. diff --git a/src/cpp/src/quake_index.cpp b/src/cpp/src/quake_index.cpp index 41814aea..cc55baac 100644 --- a/src/cpp/src/quake_index.cpp +++ b/src/cpp/src/quake_index.cpp @@ -84,7 +84,7 @@ shared_ptr QuakeIndex::build(Tensor x, Tensor ids, shared_ptr(parent_, partition_manager_, maintenance_policy_, metric_, build_params_->num_workers); + query_coordinator_ = make_shared(parent_, partition_manager_, maintenance_policy_, metric_, build_params_->num_workers, build_params_->use_numa); auto end = std::chrono::high_resolution_clock::now(); timing_info->total_time_us = std::chrono::duration_cast(end - start).count(); @@ -236,7 +236,7 @@ void QuakeIndex::save(const std::string& dir_path) { std::cout << "[QuakeIndex::save] Index saved to directory: " << dir_path << "\n"; } -void QuakeIndex::load(const std::string& dir_path, int n_workers) { +void QuakeIndex::load(const std::string& dir_path, int n_workers, bool use_numa) { namespace fs = std::filesystem; if (!fs::exists(dir_path) || !fs::is_directory(dir_path)) { @@ -293,7 +293,7 @@ void QuakeIndex::load(const std::string& dir_path, int n_workers) { // 5. Create query coordinator std::cout << "Loading coordinator with n_workers=" << n_workers << '\n'; - query_coordinator_ = std::make_shared(parent_, partition_manager_, maintenance_policy_, metric_, n_workers); + query_coordinator_ = std::make_shared(parent_, partition_manager_, maintenance_policy_, metric_, n_workers, use_numa); std::cout << "Loaded coordinator\n"; } diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index dc5c628a..e0fdb355 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -16,7 +16,8 @@ QueryCoordinator::QueryCoordinator(shared_ptr parent, shared_ptr partition_manager, shared_ptr maintenance_policy, MetricType metric, - int num_workers) + int num_workers, + bool use_numa) : parent_(parent), partition_manager_(partition_manager), maintenance_policy_(maintenance_policy), @@ -25,7 +26,7 @@ QueryCoordinator::QueryCoordinator(shared_ptr parent, workers_initialized_(false) { if (num_workers_ > 0) { - initialize_workers(num_workers_); + initialize_workers(num_workers_, use_numa); } } @@ -47,7 +48,7 @@ void QueryCoordinator::allocate_core_resources(int core_idx, int num_queries, in } // Initialize Worker Threads -void QueryCoordinator::initialize_workers(int num_cores) { +void QueryCoordinator::initialize_workers(int num_cores, bool use_numa) { if (workers_initialized_) { std::cerr << "[QueryCoordinator::initialize_workers] Workers already initialized." << std::endl; return; @@ -56,7 +57,7 @@ void QueryCoordinator::initialize_workers(int num_cores) { std::cout << "[QueryCoordinator::initialize_workers] Initializing " << num_cores << " worker threads." << std::endl; - partition_manager_->distribute_partitions(num_cores); + partition_manager_->distribute_partitions(num_cores, use_numa); core_resources_.resize(num_cores); worker_threads_.resize(num_cores); diff --git a/src/python/index_wrappers/quake.py b/src/python/index_wrappers/quake.py index 2fde67a9..033abdba 100644 --- a/src/python/index_wrappers/quake.py +++ b/src/python/index_wrappers/quake.py @@ -220,7 +220,7 @@ def load( f"verify_numa={verify_numa}, same_core={same_core}, use_centroid_workers={use_centroid_workers}" ) self.index = QuakeIndex() - self.index.load(str(filename), num_workers) + self.index.load(str(filename), num_workers, use_numa) def centroids(self) -> torch.Tensor: """ From 2103def3ddd1639e279ff50c28118e0538cc2078 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 18:59:21 -0500 Subject: [PATCH 078/323] fix numa alloc --- src/cpp/src/partition_manager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index 11eaa731..fb1a0e3d 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -631,6 +631,7 @@ void PartitionManager::set_partition_core_id(int64_t partition_id, int core_id, #ifdef QUAKE_USE_NUMA if (use_numa) { int node = numa_node_of_cpu(core_id); // <-- single call + std::cout << "Setting PID=" << partition_id << " to NUMA_node="<< node << " for core=" << core_id << '\n'; partition_store_->partitions_[partition_id]->set_numa_node(core_id); } #endif From 93cce3704680c08b1d5fa6cef392fb38fdf4e0ef Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 19:03:06 -0500 Subject: [PATCH 079/323] fix numa alloc --- src/cpp/src/quake_index.cpp | 2 +- src/cpp/src/query_coordinator.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpp/src/quake_index.cpp b/src/cpp/src/quake_index.cpp index cc55baac..5a2eb1e3 100644 --- a/src/cpp/src/quake_index.cpp +++ b/src/cpp/src/quake_index.cpp @@ -292,7 +292,7 @@ void QuakeIndex::load(const std::string& dir_path, int n_workers, bool use_numa) initialize_maintenance_policy(default_params); // 5. Create query coordinator - std::cout << "Loading coordinator with n_workers=" << n_workers << '\n'; + std::cout << "Loading coordinator with n_workers=" << n_workers << " and use_numa=" << use_numa << '\n'; query_coordinator_ = std::make_shared(parent_, partition_manager_, maintenance_policy_, metric_, n_workers, use_numa); std::cout << "Loaded coordinator\n"; } diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index e0fdb355..cb4b0bd2 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -54,7 +54,7 @@ void QueryCoordinator::initialize_workers(int num_cores, bool use_numa) { return; } - std::cout << "[QueryCoordinator::initialize_workers] Initializing " << num_cores << " worker threads." << + std::cout << "[QueryCoordinator::initialize_workers] Initializing " << num_cores << " worker threads with use_numa=" << use_numa << std::endl; partition_manager_->distribute_partitions(num_cores, use_numa); From 3d62a460a27df78c2fdc1f4aca9c89cdcea8602d Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 19:06:38 -0500 Subject: [PATCH 080/323] fix numa alloc --- src/cpp/src/partition_manager.cpp | 2 +- src/cpp/src/quake_index.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index fb1a0e3d..1a0933b8 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -621,7 +621,7 @@ void PartitionManager::distribute_partitions(int num_workers, bool use_numa) { Tensor partition_ids = get_partition_ids(); auto partition_ids_accessor = partition_ids.accessor(); for (int i = 0; i < partition_ids.size(0); i++) { - set_partition_core_id(partition_ids_accessor[i], i % num_workers); + set_partition_core_id(partition_ids_accessor[i], i % num_workers, use_numa); } } diff --git a/src/cpp/src/quake_index.cpp b/src/cpp/src/quake_index.cpp index 5a2eb1e3..43bb6955 100644 --- a/src/cpp/src/quake_index.cpp +++ b/src/cpp/src/quake_index.cpp @@ -281,7 +281,7 @@ void QuakeIndex::load(const std::string& dir_path, int n_workers, bool use_numa) std::string parent_dir = (fs::path(dir_path) / "parent").string(); if (fs::exists(parent_dir) && fs::is_directory(parent_dir)) { parent_ = std::make_shared(); - parent_->load(parent_dir, n_workers); + parent_->load(parent_dir, n_workers, use_numa); partition_manager_->parent_ = parent_; } else { parent_ = nullptr; From 5498d336bcb5595effa9aab8688f6c8edf5458d3 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 19:13:28 -0500 Subject: [PATCH 081/323] fix numa alloc --- src/cpp/src/index_partition.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cpp/src/index_partition.cpp b/src/cpp/src/index_partition.cpp index 49d5eb3b..9147a79a 100644 --- a/src/cpp/src/index_partition.cpp +++ b/src/cpp/src/index_partition.cpp @@ -147,6 +147,9 @@ void IndexPartition::set_numa_node(int new_numa_node) { bool is_valid_numa = (new_numa_node == -1) || (numa_available() != -1 && new_numa_node <= numa_max_node()); + + std::cout << "new_numa_node=" << new_numa_node << ", numa_available()=" << numa_available() << ", numa_max_node()=" << numa_max_node() << '\n' + if (!is_valid_numa) { throw std::runtime_error("Invalid numa node specified"); } From f76518cd2b9fc848225f45aa69fb6274f5f8dee5 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 19:14:25 -0500 Subject: [PATCH 082/323] fix numa alloc --- src/cpp/src/index_partition.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/src/index_partition.cpp b/src/cpp/src/index_partition.cpp index 9147a79a..128c5b44 100644 --- a/src/cpp/src/index_partition.cpp +++ b/src/cpp/src/index_partition.cpp @@ -148,7 +148,7 @@ void IndexPartition::set_numa_node(int new_numa_node) { bool is_valid_numa = (new_numa_node == -1) || (numa_available() != -1 && new_numa_node <= numa_max_node()); - std::cout << "new_numa_node=" << new_numa_node << ", numa_available()=" << numa_available() << ", numa_max_node()=" << numa_max_node() << '\n' + std::cout << "new_numa_node=" << new_numa_node << ", numa_available()=" << numa_available() << ", numa_max_node()=" << numa_max_node() << '\n'; if (!is_valid_numa) { throw std::runtime_error("Invalid numa node specified"); From 53f411dd2fe1387981ddf2822d63eabff34af19c Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 19:20:13 -0500 Subject: [PATCH 083/323] fix numa alloc --- src/cpp/src/index_partition.cpp | 2 -- src/cpp/src/partition_manager.cpp | 5 ++--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/cpp/src/index_partition.cpp b/src/cpp/src/index_partition.cpp index 128c5b44..a8b84845 100644 --- a/src/cpp/src/index_partition.cpp +++ b/src/cpp/src/index_partition.cpp @@ -148,8 +148,6 @@ void IndexPartition::set_numa_node(int new_numa_node) { bool is_valid_numa = (new_numa_node == -1) || (numa_available() != -1 && new_numa_node <= numa_max_node()); - std::cout << "new_numa_node=" << new_numa_node << ", numa_available()=" << numa_available() << ", numa_max_node()=" << numa_max_node() << '\n'; - if (!is_valid_numa) { throw std::runtime_error("Invalid numa node specified"); } diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index 1a0933b8..428c7ed4 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -630,9 +630,8 @@ void PartitionManager::set_partition_core_id(int64_t partition_id, int core_id, #ifdef QUAKE_USE_NUMA if (use_numa) { - int node = numa_node_of_cpu(core_id); // <-- single call - std::cout << "Setting PID=" << partition_id << " to NUMA_node="<< node << " for core=" << core_id << '\n'; - partition_store_->partitions_[partition_id]->set_numa_node(core_id); + int node = numa_node_of_cpu(core_id); + partition_store_->partitions_[partition_id]->set_numa_node(node); } #endif } From 8a30fa4ec7c2535e86eff3291e97ee822c46e7f7 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 19:23:40 -0500 Subject: [PATCH 084/323] fix numa alloc --- src/cpp/src/index_partition.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cpp/src/index_partition.cpp b/src/cpp/src/index_partition.cpp index a8b84845..868f94bb 100644 --- a/src/cpp/src/index_partition.cpp +++ b/src/cpp/src/index_partition.cpp @@ -254,6 +254,7 @@ T* IndexPartition::allocate_memory(size_t num_elements, int numa_node) { if (numa_node == -1) { ptr = reinterpret_cast(std::malloc(total_bytes)); } else { + std::cout << numa_alloc_onnode << '\n'; ptr = reinterpret_cast(numa_alloc_onnode(total_bytes, numa_node)); } #else From 18164143e6e87f55fc534683e9503b0595678c1d Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 19:28:12 -0500 Subject: [PATCH 085/323] fix numa alloc --- src/cpp/src/index_partition.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cpp/src/index_partition.cpp b/src/cpp/src/index_partition.cpp index 868f94bb..a8b84845 100644 --- a/src/cpp/src/index_partition.cpp +++ b/src/cpp/src/index_partition.cpp @@ -254,7 +254,6 @@ T* IndexPartition::allocate_memory(size_t num_elements, int numa_node) { if (numa_node == -1) { ptr = reinterpret_cast(std::malloc(total_bytes)); } else { - std::cout << numa_alloc_onnode << '\n'; ptr = reinterpret_cast(numa_alloc_onnode(total_bytes, numa_node)); } #else From d471723f1fe67f18a679fedebdaa3c0948ac8b74 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 19:43:49 -0500 Subject: [PATCH 086/323] fix numa alloc --- src/cpp/src/index_partition.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cpp/src/index_partition.cpp b/src/cpp/src/index_partition.cpp index a8b84845..1c1c62c5 100644 --- a/src/cpp/src/index_partition.cpp +++ b/src/cpp/src/index_partition.cpp @@ -252,11 +252,14 @@ T* IndexPartition::allocate_memory(size_t num_elements, int numa_node) { T* ptr = nullptr; #ifdef QUAKE_USE_NUMA if (numa_node == -1) { + std::cout << "Calling malloc with total_bytes=" << total_bytes << ", numa_node=" << numa_node << '\n'; ptr = reinterpret_cast(std::malloc(total_bytes)); } else { + std::cout << "Calling numa_alloc_onnode with total_bytes=" << total_bytes << "", numa_node=" << numa_node << '\n'; ptr = reinterpret_cast(numa_alloc_onnode(total_bytes, numa_node)); } #else + std::cout << "Calling malloc with total_bytes=" << total_bytes << '\n'; ptr = reinterpret_cast(std::malloc(total_bytes)); #endif if (!ptr) { From 7a5ddf36d2f4e1ba37c3f406e214e0e8c7d5009a Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 19:44:48 -0500 Subject: [PATCH 087/323] fix numa alloc --- src/cpp/src/index_partition.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/src/index_partition.cpp b/src/cpp/src/index_partition.cpp index 1c1c62c5..dae61b5c 100644 --- a/src/cpp/src/index_partition.cpp +++ b/src/cpp/src/index_partition.cpp @@ -255,7 +255,7 @@ T* IndexPartition::allocate_memory(size_t num_elements, int numa_node) { std::cout << "Calling malloc with total_bytes=" << total_bytes << ", numa_node=" << numa_node << '\n'; ptr = reinterpret_cast(std::malloc(total_bytes)); } else { - std::cout << "Calling numa_alloc_onnode with total_bytes=" << total_bytes << "", numa_node=" << numa_node << '\n'; + std::cout << "Calling numa_alloc_onnode with total_bytes=" << total_bytes << ", numa_node=" << numa_node << '\n'; ptr = reinterpret_cast(numa_alloc_onnode(total_bytes, numa_node)); } #else From ecf310e464d4fd5995088aa0b3882d5034bf6d01 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 19:51:36 -0500 Subject: [PATCH 088/323] fix numa alloc --- src/cpp/src/index_partition.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/cpp/src/index_partition.cpp b/src/cpp/src/index_partition.cpp index dae61b5c..a8b84845 100644 --- a/src/cpp/src/index_partition.cpp +++ b/src/cpp/src/index_partition.cpp @@ -252,14 +252,11 @@ T* IndexPartition::allocate_memory(size_t num_elements, int numa_node) { T* ptr = nullptr; #ifdef QUAKE_USE_NUMA if (numa_node == -1) { - std::cout << "Calling malloc with total_bytes=" << total_bytes << ", numa_node=" << numa_node << '\n'; ptr = reinterpret_cast(std::malloc(total_bytes)); } else { - std::cout << "Calling numa_alloc_onnode with total_bytes=" << total_bytes << ", numa_node=" << numa_node << '\n'; ptr = reinterpret_cast(numa_alloc_onnode(total_bytes, numa_node)); } #else - std::cout << "Calling malloc with total_bytes=" << total_bytes << '\n'; ptr = reinterpret_cast(std::malloc(total_bytes)); #endif if (!ptr) { From 51550e94d6eb39c4018de6330be034daa3da867f Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 20:25:20 -0500 Subject: [PATCH 089/323] fix numa alloc --- test/experiments/osdi2025/experiment_runner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/experiments/osdi2025/experiment_runner.py b/test/experiments/osdi2025/experiment_runner.py index b9142976..b51b8725 100644 --- a/test/experiments/osdi2025/experiment_runner.py +++ b/test/experiments/osdi2025/experiment_runner.py @@ -6,7 +6,7 @@ from pathlib import Path from test.experiments.osdi2025.kick_the_tires.run import run_experiment as run_kick_the_tires -# from test.experiments.osdi2025.numa_single_query.run import run_experiment as run_numa_single +from test.experiments.osdi2025.numa_single_query.run import run_experiment as run_numa_single from test.experiments.osdi2025.numa_multi_query.run import run_experiment as run_numa_multi from test.experiments.osdi2025.aps_recall_targets.run import run_experiment as run_aps_recall from test.experiments.osdi2025.early_termination.run import run_experiment as run_early_termination @@ -16,7 +16,7 @@ EXPERIMENTS = { "kick_the_tires": run_kick_the_tires, - # "numa_single_query": run_numa_single, + "numa_single_query": run_numa_single, "numa_multi_query": run_numa_multi, "aps_recall_targets": run_aps_recall, "early_termination": run_early_termination, From 0ac70860a9ec89045478c1ebcd85d111cc4675b0 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 20:26:10 -0500 Subject: [PATCH 090/323] fix numa alloc --- .../numa_single_query/configs/sift1m.yaml | 96 ++++++++++--------- 1 file changed, 53 insertions(+), 43 deletions(-) diff --git a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml index 589ccb80..2e292300 100644 --- a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml @@ -9,6 +9,16 @@ warmup: 10 overwrite: false # Set to true to force all indexes to rerun indexes: + - name: Quake_0 + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 1 + use_numa: false + search_params: + nprobe: 1000 + - name: Quake_1 index: Quake build_params: @@ -69,49 +79,49 @@ indexes: search_params: nprobe: 1000 - - name: FaissIVF - index: IVF - build_params: - nc: 1000 - metric: l2 - search_params: - nprobe: 1000 - - - name: SCANN - index: SCANN - build_params: - num_leaves: 1000 - metric: squared_l2 - search_params: - leaves_to_search: 1000 - - - name: FaissHNSW - index: HNSW - build_params: - m: 64 - ef_construction: 128 - metric: l2 - search_params: - ef_search: 32 - - - name: DiskANN - index: DiskANN - build_params: - complexity: 128 - graph_degree: 64 - metric: l2 - search_params: - complexity: 32 - - - name: SVS - index: SVS - build_params: - graph_max_degree: 64 - alpha: 1.1 - window_size: 128 - metric: l2 - search_params: - search_window_size: 32 +# - name: FaissIVF +# index: IVF +# build_params: +# nc: 1000 +# metric: l2 +# search_params: +# nprobe: 1000 +# +# - name: SCANN +# index: SCANN +# build_params: +# num_leaves: 1000 +# metric: squared_l2 +# search_params: +# leaves_to_search: 1000 +# +# - name: FaissHNSW +# index: HNSW +# build_params: +# m: 64 +# ef_construction: 128 +# metric: l2 +# search_params: +# ef_search: 32 +# +# - name: DiskANN +# index: DiskANN +# build_params: +# complexity: 128 +# graph_degree: 64 +# metric: l2 +# search_params: +# complexity: 32 +# +# - name: SVS +# index: SVS +# build_params: +# graph_max_degree: 64 +# alpha: 1.1 +# window_size: 128 +# metric: l2 +# search_params: +# search_window_size: 32 output: results_csv: numa_single_query_results.csv \ No newline at end of file From 4b10f3e800f2816d3fc38dcbc9a23227e5f3c4be Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 20:27:24 -0500 Subject: [PATCH 091/323] fix numa alloc --- .../osdi2025/numa_single_query/configs/sift1m.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml index 2e292300..3682722b 100644 --- a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml @@ -17,7 +17,7 @@ indexes: num_workers: 1 use_numa: false search_params: - nprobe: 1000 + nprobe: 20 - name: Quake_1 index: Quake @@ -27,7 +27,7 @@ indexes: num_workers: 1 use_numa: false search_params: - nprobe: 1000 + nprobe: 20 - name: Quake_4 index: Quake @@ -37,7 +37,7 @@ indexes: num_workers: 4 use_numa: false search_params: - nprobe: 1000 + nprobe: 20 - name: Quake_16 index: Quake @@ -47,7 +47,7 @@ indexes: num_workers: 16 use_numa: false search_params: - nprobe: 1000 + nprobe: 20 - name: Quake_1_numa index: Quake @@ -57,7 +57,7 @@ indexes: num_workers: 1 use_numa: true search_params: - nprobe: 1000 + nprobe: 20 - name: Quake_4_numa index: Quake @@ -67,7 +67,7 @@ indexes: num_workers: 4 use_numa: true search_params: - nprobe: 1000 + nprobe: 20 - name: Quake_16_numa index: Quake @@ -77,7 +77,7 @@ indexes: num_workers: 16 use_numa: true search_params: - nprobe: 1000 + nprobe: 20 # - name: FaissIVF # index: IVF From d48a2cdb905648bfa5ac9f77d822d2357c532d9c Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 22:35:45 -0500 Subject: [PATCH 092/323] fix numa alloc --- src/cpp/src/query_coordinator.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index cb4b0bd2..394fffc7 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -11,6 +11,13 @@ #include #include +static inline void prefault_range(void* p, size_t bytes) { + // Touch one byte per page; compiler will not optimise this away. + const size_t page = 4096; + for (size_t off = 0; off < bytes; off += page) + *(volatile char*)((char*)p + off); +} + // Constructor QueryCoordinator::QueryCoordinator(shared_ptr parent, shared_ptr partition_manager, @@ -100,6 +107,14 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { CoreResources &res = core_resources_[core_index]; + // Prefault the partitions this core owns + for (auto& kv : partition_manager_->partition_store_->partitions_) { + if (kv.second->core_id_ == core_index) { + prefault_range(kv.second->codes_, + size_t(kv.second->num_vectors_) * kv.second->code_size_); + } + } + if (!set_thread_affinity(core_index)) { std::cout << "[QueryCoordinator::partition_scan_worker_fn] Failed to set thread affinity on core " << core_index << std::endl; } From ce24768908c9854a7ae606643b78866b3b2e32dd Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 22:39:45 -0500 Subject: [PATCH 093/323] fix numa alloc --- src/cpp/src/query_coordinator.cpp | 42 +++++++++++++------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 394fffc7..fc5c383b 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -11,13 +11,6 @@ #include #include -static inline void prefault_range(void* p, size_t bytes) { - // Touch one byte per page; compiler will not optimise this away. - const size_t page = 4096; - for (size_t off = 0; off < bytes; off += page) - *(volatile char*)((char*)p + off); -} - // Constructor QueryCoordinator::QueryCoordinator(shared_ptr parent, shared_ptr partition_manager, @@ -42,16 +35,25 @@ QueryCoordinator::~QueryCoordinator() { shutdown_workers(); } -void QueryCoordinator::allocate_core_resources(int core_idx, int num_queries, int k, int d) { - CoreResources &res = core_resources_[core_idx]; - res.core_id = core_idx; - res.local_query_buffer.resize(num_queries * d * sizeof(float)); - res.topk_buffer_pool.resize(num_queries); - for (int q = 0; q < num_queries; ++q) { - res.topk_buffer_pool[q] = make_shared(k, metric_ == faiss::METRIC_INNER_PRODUCT); - res.job_queue = moodycamel::BlockingConcurrentQueue(); +void QueryCoordinator::allocate_core_resources(int c, int nq, int k, int d) +{ + CoreResources &r = core_resources_[c]; + r.core_id = c; + +#ifdef QUAKE_USE_NUMA + int node = numa_node_of_cpu(c); + r.local_query_buffer.resize(nq * d * sizeof(float)); + numa_tonode_memory(r.local_query_buffer.data(), + r.local_query_buffer.size(), node); + prefault_range(r.local_query_buffer.data(), r.local_query_buffer.size()); +#else + r.local_query_buffer.resize(nq * d * sizeof(float)); +#endif + r.topk_buffer_pool.resize(nq); + for (int q = 0; q < nq; ++q) { + r.topk_buffer_pool[q] = make_shared(k, metric_ == faiss::METRIC_INNER_PRODUCT); + r.job_queue = moodycamel::BlockingConcurrentQueue(); } - } // Initialize Worker Threads @@ -107,14 +109,6 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { CoreResources &res = core_resources_[core_index]; - // Prefault the partitions this core owns - for (auto& kv : partition_manager_->partition_store_->partitions_) { - if (kv.second->core_id_ == core_index) { - prefault_range(kv.second->codes_, - size_t(kv.second->num_vectors_) * kv.second->code_size_); - } - } - if (!set_thread_affinity(core_index)) { std::cout << "[QueryCoordinator::partition_scan_worker_fn] Failed to set thread affinity on core " << core_index << std::endl; } From 19730e341ad236956e46392c09e26cbb7321c6b2 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 22:41:31 -0500 Subject: [PATCH 094/323] fix numa alloc --- src/cpp/src/query_coordinator.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index fc5c383b..c7a4a65d 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -45,7 +45,6 @@ void QueryCoordinator::allocate_core_resources(int c, int nq, int k, int d) r.local_query_buffer.resize(nq * d * sizeof(float)); numa_tonode_memory(r.local_query_buffer.data(), r.local_query_buffer.size(), node); - prefault_range(r.local_query_buffer.data(), r.local_query_buffer.size()); #else r.local_query_buffer.resize(nq * d * sizeof(float)); #endif From d7a03639afd854412435f34cd9334dcac8589ba2 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 16 May 2025 23:25:40 -0500 Subject: [PATCH 095/323] fix numa alloc --- src/cpp/src/query_coordinator.cpp | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index c7a4a65d..4343f2d5 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -35,23 +35,14 @@ QueryCoordinator::~QueryCoordinator() { shutdown_workers(); } -void QueryCoordinator::allocate_core_resources(int c, int nq, int k, int d) -{ - CoreResources &r = core_resources_[c]; - r.core_id = c; - -#ifdef QUAKE_USE_NUMA - int node = numa_node_of_cpu(c); - r.local_query_buffer.resize(nq * d * sizeof(float)); - numa_tonode_memory(r.local_query_buffer.data(), - r.local_query_buffer.size(), node); -#else - r.local_query_buffer.resize(nq * d * sizeof(float)); -#endif - r.topk_buffer_pool.resize(nq); - for (int q = 0; q < nq; ++q) { - r.topk_buffer_pool[q] = make_shared(k, metric_ == faiss::METRIC_INNER_PRODUCT); - r.job_queue = moodycamel::BlockingConcurrentQueue(); +void QueryCoordinator::allocate_core_resources(int core_idx, int num_queries, int k, int d) { + CoreResources &res = core_resources_[core_idx]; + res.core_id = core_idx; + res.local_query_buffer.resize(num_queries * d * sizeof(float)); + res.topk_buffer_pool.resize(num_queries); + for (int q = 0; q < num_queries; ++q) { + res.topk_buffer_pool[q] = make_shared(k, metric_ == faiss::METRIC_INNER_PRODUCT); + res.job_queue = moodycamel::BlockingConcurrentQueue(); } } From 61d8a9eda52561887911c3cf407cd3fc4945a222 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 02:22:28 -0500 Subject: [PATCH 096/323] add timing --- src/cpp/src/query_coordinator.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 4343f2d5..44901d8a 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -525,6 +525,14 @@ shared_ptr QueryCoordinator::worker_scan( search_result->distances = topk_dists; search_result->timing_info = timing_info; + // print out timing info + std::cout << "[QueryCoordinator::worker_scan] Timing info: " << std::endl; + std::cout << "Total time: " << timing_info->total_time_ns / 1e6 << " ms" << std::endl; + std::cout << "Job enqueue time: " << timing_info->job_enqueue_time_ns / 1e6 << " ms" << std::endl; + std::cout << "Job wait time: " << timing_info->job_wait_time_ns / 1e6 << " ms" << std::endl; + std::cout << "Buffer init time: " << timing_info->buffer_init_time_ns / 1e6 << " ms" << std::endl; + std::cout << "Result agg time: " << timing_info->result_aggregate_time_ns / 1e6 << " ms" << std::endl; + return search_result; } From a898cabf7ef93100b4252cb322214693f76ffb75 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 02:30:36 -0500 Subject: [PATCH 097/323] speed up batched scan enqueue --- src/cpp/src/query_coordinator.cpp | 59 +++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 44901d8a..d90f6d85 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -352,27 +352,48 @@ shared_ptr QueryCoordinator::worker_scan( if (search_params->batched_scan) { auto partition_ids_accessor = partition_ids.accessor(); - std::unordered_map> per_partition_query_ids; - for (int64_t q = 0; q < num_queries; q++) { - for (int64_t p = 0; p < partition_ids.size(1); p++) { - int64_t pid = partition_ids_accessor[q][p]; - if (pid < 0) continue; - per_partition_query_ids[pid].push_back(q); + if (partition_manager_->nlist() == partition_ids.size(0)) { + vector all_query_ids = std::vector(x.size(0)); + std::iota(all_query_ids.begin(), all_query_ids.end(), 0); + + for (int64_t i = 0; i < partition_manager_->nlist(); i++) { + ScanJob job; + job.is_batched = true; + job.partition_id = i; + job.k = k; + job.query_vector = x.data_ptr(); + job.num_queries = x.size(0); + job.query_ids = all_query_ids; + int core_id = partition_manager_->get_partition_core_id(i); + if (core_id < 0) { + throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); + } + core_resources_[core_id].job_queue.enqueue(job); } - } - for (auto &kv : per_partition_query_ids) { - ScanJob job; - job.is_batched = true; - job.partition_id = kv.first; - job.k = k; - job.query_vector = x.data_ptr(); - job.num_queries = kv.second.size(); - job.query_ids = kv.second; - int core_id = partition_manager_->get_partition_core_id(kv.first); - if (core_id < 0) { - throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); + + } else { + std::unordered_map> per_partition_query_ids; + for (int64_t q = 0; q < num_queries; q++) { + for (int64_t p = 0; p < partition_ids.size(1); p++) { + int64_t pid = partition_ids_accessor[q][p]; + if (pid < 0) continue; + per_partition_query_ids[pid].push_back(q); + } + } + for (auto &kv : per_partition_query_ids) { + ScanJob job; + job.is_batched = true; + job.partition_id = kv.first; + job.k = k; + job.query_vector = x.data_ptr(); + job.num_queries = kv.second.size(); + job.query_ids = kv.second; + int core_id = partition_manager_->get_partition_core_id(kv.first); + if (core_id < 0) { + throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); + } + core_resources_[core_id].job_queue.enqueue(job); } - core_resources_[core_id].job_queue.enqueue(job); } } else { auto partition_ids_accessor = partition_ids.accessor(); From 912d2fc7fc7acb82326cd760f85aee337a909511 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 02:33:18 -0500 Subject: [PATCH 098/323] speed up batched scan enqueue --- src/cpp/src/query_coordinator.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index d90f6d85..a4dad365 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -353,6 +353,7 @@ shared_ptr QueryCoordinator::worker_scan( auto partition_ids_accessor = partition_ids.accessor(); if (partition_manager_->nlist() == partition_ids.size(0)) { + std::cout << "SCAN ALL\n"; vector all_query_ids = std::vector(x.size(0)); std::iota(all_query_ids.begin(), all_query_ids.end(), 0); @@ -372,6 +373,7 @@ shared_ptr QueryCoordinator::worker_scan( } } else { + std::cout << "BATCH SCAN SUBSET\n"; std::unordered_map> per_partition_query_ids; for (int64_t q = 0; q < num_queries; q++) { for (int64_t p = 0; p < partition_ids.size(1); p++) { @@ -396,6 +398,7 @@ shared_ptr QueryCoordinator::worker_scan( } } } else { + std::cout << "PER-QUERY SCAN\n"; auto partition_ids_accessor = partition_ids.accessor(); int64_t start = 0; From fceafae067fbcdf07b1e0253a679cc9b56d57b6c Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 02:37:23 -0500 Subject: [PATCH 099/323] speed up batched scan enqueue --- src/cpp/src/query_coordinator.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index a4dad365..73749609 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -790,6 +790,7 @@ shared_ptr QueryCoordinator::search(Tensor x, shared_ptrparent_params; } + parent_search_params->batched_scan = true; // if recall_target is set, we need an initial set of partitions to consider if (search_params->recall_target > 0.0 && !search_params->batched_scan) { From 6c271dd73ec31f4df1f12fd48e2e73f6aaa1c13b Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 02:40:45 -0500 Subject: [PATCH 100/323] speed up batched scan enqueue --- src/cpp/include/list_scanning.h | 184 ++++++++++++++++---------------- 1 file changed, 92 insertions(+), 92 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 573f0b4e..b8319e04 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -343,113 +343,113 @@ inline void scan_list(const float *query_vec, } } -inline void batched_scan_list( - const float *query_vecs, - const float *list_vecs, - const int64_t *list_ids, - int num_queries, - int list_size, - int dim, - vector> &topk_buffers, - MetricType metric = faiss::METRIC_L2) -{ - if (list_size == 0 || list_vecs == nullptr) { - return; - } - - // Wrap raw arrays in torch Tensors, no copy - Tensor query = torch::from_blob((void*)query_vecs, {num_queries, dim}, torch::kFloat32); - Tensor list = torch::from_blob((void*)list_vecs, {list_size, dim}, torch::kFloat32); - - torch::Tensor distances; - if (metric == faiss::METRIC_L2) { - // Returns [num_queries, list_size], each entry is the Euclidean distance - distances = torch::cdist(query, list, 2.0); - } else if (metric == faiss::METRIC_INNER_PRODUCT) { - // [num_queries, list_size], each entry is dot product - distances = torch::matmul(query, list.t()); - } else { - throw std::runtime_error("Metric type not supported"); - } - - // For each query, push all list vectors and their distances into TopkBuffer - auto distances_acc = distances.accessor(); - for (int i = 0; i < num_queries; ++i) { - std::vector dists(list_size); - std::vector ids(list_size); - - for (int j = 0; j < list_size; ++j) { - dists[j] = distances_acc[i][j]; - } - - if (list_ids) { - for (int j = 0; j < list_size; ++j) { - ids[j] = list_ids[j]; - } - } else { - for (int j = 0; j < list_size; ++j) { - ids[j] = j; - } - } - - topk_buffers[i]->batch_add(dists.data(), ids.data(), list_size); - } -} - -//inline void batched_scan_list(const float *query_vecs, -// const float *list_vecs, -// const int64_t *list_ids, -// int num_queries, -// int list_size, -// int dim, -// vector> &topk_buffers, -// MetricType metric = faiss::METRIC_L2) { +//inline void batched_scan_list( +// const float *query_vecs, +// const float *list_vecs, +// const int64_t *list_ids, +// int num_queries, +// int list_size, +// int dim, +// vector> &topk_buffers, +// MetricType metric = faiss::METRIC_L2) +//{ // if (list_size == 0 || list_vecs == nullptr) { -// // No list vectors to process; // return; // } // -// // Ensure k does not exceed list_size -// int k = topk_buffers[0]->k_; -// int k_max = std::min(k, list_size); +// // Wrap raw arrays in torch Tensors, no copy +// Tensor query = torch::from_blob((void*)query_vecs, {num_queries, dim}, torch::kFloat32); +// Tensor list = torch::from_blob((void*)list_vecs, {list_size, dim}, torch::kFloat32); // -// int64_t *labels = (int64_t *) malloc(num_queries * k_max * sizeof(int64_t)); -// float *distances = (float *) malloc(num_queries * k_max * sizeof(float)); -// -// if (metric == faiss::METRIC_INNER_PRODUCT) { -// faiss::float_minheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; -// faiss::knn_inner_product(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr); -// } else if (metric == faiss::METRIC_L2) { -// faiss::float_maxheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; -// faiss::knn_L2sqr(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr, nullptr); +// torch::Tensor distances; +// if (metric == faiss::METRIC_L2) { +// // Returns [num_queries, list_size], each entry is the Euclidean distance +// distances = torch::cdist(query, list, 2.0); +// } else if (metric == faiss::METRIC_INNER_PRODUCT) { +// // [num_queries, list_size], each entry is dot product +// distances = torch::matmul(query, list.t()); // } else { // throw std::runtime_error("Metric type not supported"); // } // -// // map the labels to the actual list_ids -// if (list_ids != nullptr) { -// for (int i = 0; i < num_queries; i++) { -// for (int j = 0; j < k_max; j++) { -// labels[i * k_max + j] = list_ids[labels[i * k_max + j]]; -// } +// // For each query, push all list vectors and their distances into TopkBuffer +// auto distances_acc = distances.accessor(); +// for (int i = 0; i < num_queries; ++i) { +// std::vector dists(list_size); +// std::vector ids(list_size); +// +// for (int j = 0; j < list_size; ++j) { +// dists[j] = distances_acc[i][j]; // } -// } // -// // if the metric is l2, convert the distances to sqrt -// if (metric == faiss::METRIC_L2) { -// for (int i = 0; i < num_queries * k_max; i++) { -// distances[i] = sqrt(distances[i]); +// if (list_ids) { +// for (int j = 0; j < list_size; ++j) { +// ids[j] = list_ids[j]; +// } +// } else { +// for (int j = 0; j < list_size; ++j) { +// ids[j] = j; +// } // } -// } // -// // add distances to the topk buffers -// for (int i = 0; i < num_queries; i++) { -// topk_buffers[i]->batch_add(distances + i * k_max, labels + i * k_max, k_max); +// topk_buffers[i]->batch_add(dists.data(), ids.data(), list_size); // } -// -// free(labels); -// free(distances); //} +inline void batched_scan_list(const float *query_vecs, + const float *list_vecs, + const int64_t *list_ids, + int num_queries, + int list_size, + int dim, + vector> &topk_buffers, + MetricType metric = faiss::METRIC_L2) { + if (list_size == 0 || list_vecs == nullptr) { + // No list vectors to process; + return; + } + + // Ensure k does not exceed list_size + int k = topk_buffers[0]->k_; + int k_max = std::min(k, list_size); + + int64_t *labels = (int64_t *) malloc(num_queries * k_max * sizeof(int64_t)); + float *distances = (float *) malloc(num_queries * k_max * sizeof(float)); + + if (metric == faiss::METRIC_INNER_PRODUCT) { + faiss::float_minheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; + faiss::knn_inner_product(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr); + } else if (metric == faiss::METRIC_L2) { + faiss::float_maxheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; + faiss::knn_L2sqr(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr, nullptr); + } else { + throw std::runtime_error("Metric type not supported"); + } + + // map the labels to the actual list_ids + if (list_ids != nullptr) { + for (int i = 0; i < num_queries; i++) { + for (int j = 0; j < k_max; j++) { + labels[i * k_max + j] = list_ids[labels[i * k_max + j]]; + } + } + } + + // if the metric is l2, convert the distances to sqrt + if (metric == faiss::METRIC_L2) { + for (int i = 0; i < num_queries * k_max; i++) { + distances[i] = sqrt(distances[i]); + } + } + + // add distances to the topk buffers + for (int i = 0; i < num_queries; i++) { + topk_buffers[i]->batch_add(distances + i * k_max, labels + i * k_max, k_max); + } + + free(labels); + free(distances); +} + // } #endif //LIST_SCANNING_H From fd9bb0dc7597015cd8eecf1b2bb4cc28636de6ac Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 02:47:00 -0500 Subject: [PATCH 101/323] reuse sinlge query worker --- .../osdi2025/numa_single_query/run.py | 348 ++++++++++-------- 1 file changed, 191 insertions(+), 157 deletions(-) diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index 95dea09d..fddcc395 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -1,230 +1,264 @@ #!/usr/bin/env python3 """ -NUMA Single-Query Latency and Recall Benchmark +NUMA Single-Query Latency and Recall Benchmark (v2) -Benchmarks a suite of ANN indexes (Quake, Faiss-IVF, SCANN, HNSW, DiskANN, SVS, etc.) -for single-query latency and recall@k under configurable build and search parameters. -Results are cached and only recomputed if the 'overwrite' flag is set in the configuration. -Outputs a unified CSV and a latency plot per index. +Builds each non-Quake index once. +Builds **one** shared Quake base-index and re-uses it for every Quake +configuration, so we avoid the O(dataset) rebuild for each worker-count. -Usage: - python numa_latency_experiment.py numa_latency_experiment.yaml output_dir +Usage +----- + python numa_latency_experiment.py """ +from pathlib import Path +import os import yaml import numpy as np import torch import pandas as pd import matplotlib.pyplot as plt -from pathlib import Path -from quake.utils import compute_recall +from quake.utils import compute_recall from quake.datasets.ann_datasets import load_dataset from quake.index_wrappers.faiss_ivf import FaissIVF from quake.index_wrappers.faiss_hnsw import FaissHNSW from quake.index_wrappers.quake import QuakeWrapper - try: from quake.index_wrappers.scann import Scann except ImportError: - raise ImportError("SCANN wrapper not available. Please install the required package.") + Scann = None try: from quake.index_wrappers.diskann import DiskANNDynamic except ImportError: - raise ImportError("DiskANN wrapper not available. Please install the required package.") + DiskANNDynamic = None try: from quake.index_wrappers.vamana import Vamana except ImportError: - raise ImportError("SVS wrapper not available. Please install the required package.") + Vamana = None INDEX_CLASSES = { - "Quake": QuakeWrapper, - "IVF": FaissIVF, - "SCANN": Scann, - "HNSW": FaissHNSW, + "Quake": QuakeWrapper, + "IVF": FaissIVF, + "SCANN": Scann, + "HNSW": FaissHNSW, "DiskANN": DiskANNDynamic, - "SVS": Vamana, + "SVS": Vamana, } -def build_and_save_index(index_class, build_params, base_vecs, index_file): - idx = index_class() - params = dict(build_params) - idx.build(base_vecs, **params) - idx.save(str(index_file)) - -def run_experiment(cfg_path: str, output_dir: str): - cfg = yaml.safe_load(Path(cfg_path).read_text()) - ds = cfg["dataset"] - queries_n = ds["num_queries"] - k = ds["k"] +# --------------------------------------------------------------------------- # +# Helpers # +# --------------------------------------------------------------------------- # +def build_and_save(index_cls, params, vecs, path): + """Build with on and persist to .""" + idx = index_cls() + idx.build(vecs, **params) + idx.save(str(path)) + +def extract_ids(res): + """Return search‐result ids as np.ndarray.""" + if hasattr(res, "ids"): + arr = res.ids + elif hasattr(res, "I"): + arr = res.I + elif hasattr(res, "indices"): + arr = res.indices + else: + raise RuntimeError("Search result has no id field.") + if isinstance(arr, torch.Tensor): + arr = arr.cpu().numpy() + return np.asarray(arr, dtype=np.int64) + +# --------------------------------------------------------------------------- # +# Main # +# --------------------------------------------------------------------------- # +def run_experiment(cfg_path: str, output_dir: str) -> None: + cfg = yaml.safe_load(Path(cfg_path).read_text()) + ds_cfg = cfg["dataset"] + k = ds_cfg["k"] + q_n = ds_cfg["num_queries"] trials = cfg.get("trials", 5) - warmup = cfg.get("warmup", 10) - indexes_cfg = cfg["indexes"] + warmup_n = cfg.get("warmup", 10) + idx_cfgs = cfg["indexes"] csv_name = cfg.get("output", {}).get("results_csv", "numa_results.csv") overwrite = cfg.get("overwrite", False) - out_dir = Path(output_dir) + out_dir = Path(output_dir).expanduser().absolute() out_dir.mkdir(parents=True, exist_ok=True) - print(f"[INFO] Loading dataset '{ds['name']}'...") - base_vecs, queries, gt = load_dataset(ds["name"]) - queries = queries[:queries_n] - gt = gt[:queries_n] if gt is not None else None - - all_rows = [] - - for idx_cfg in indexes_cfg: - idx_name = idx_cfg["name"] - idx_type = idx_cfg["index"] - build_params = idx_cfg.get("build_params", {}) - search_params = idx_cfg.get("search_params", {}) - IndexClass = INDEX_CLASSES.get(idx_type) - if IndexClass is None: - print(f"[WARN] Unknown index type: {idx_type}. Skipping.") + # --------------------------------------------------------------------- # + # Dataset # + # --------------------------------------------------------------------- # + print(f"[INFO] loading dataset {ds_cfg['name']} …") + base_vecs, queries, gt = load_dataset(ds_cfg["name"]) + queries = queries[:q_n] + gt = gt[:q_n] if gt is not None else None + + # --------------------------------------------------------------------- # + # Build a single Quake base index (if any Quake config exists) # + # --------------------------------------------------------------------- # + quake_base_params = None + for cfg_i in idx_cfgs: + if cfg_i["index"] == "Quake": + quake_base_params = dict(cfg_i.get("build_params", {})) + # Remove loading-stage-only keys; not needed for the build + quake_base_params.pop("num_workers", None) + quake_base_params.pop("use_numa", None) + break + + quake_base_path = out_dir / "Quake_base_index.bin" + if quake_base_params: + if overwrite and quake_base_path.exists(): + os.remove(quake_base_path) + if not quake_base_path.exists(): + print("[BUILD] Quake (shared) base index …") + build_and_save(QuakeWrapper, quake_base_params, base_vecs, quake_base_path) + print(f"[SAVE] Quake base index → {quake_base_path}") + + # --------------------------------------------------------------------- # + # Per-configuration benchmarking # + # --------------------------------------------------------------------- # + rows = [] + for cfg_i in idx_cfgs: + name = cfg_i["name"] + typ = cfg_i["index"] + b_params = dict(cfg_i.get("build_params", {})) # safe copy + s_params = dict(cfg_i.get("search_params", {})) + cls = INDEX_CLASSES.get(typ) + if cls is None: + print(f"[WARN] unknown index type '{typ}' – skipping.") continue - idx_csv = out_dir / f"{idx_name}_results.csv" - idx_file = out_dir / f"{idx_name}_index.bin" + idx_csv = out_dir / f"{name}_results.csv" + idx_path = quake_base_path if typ == "Quake" else out_dir / f"{name}_index.bin" + # Skip if we already have results and not overwriting if idx_csv.exists() and not overwrite: - print(f"[SKIP] {idx_name}: Results exist. Use overwrite: true to rerun.") - df_idx = pd.read_csv(idx_csv) - all_rows.append(df_idx.iloc[0].to_dict()) + print(f"[SKIP] {name} – results exist.") + rows.append(pd.read_csv(idx_csv).iloc[0].to_dict()) continue - if not idx_file.exists(): - print(f"[BUILD] {idx_name} index...") - build_and_save_index(IndexClass, build_params, base_vecs, idx_file) - print(f"[SAVE] Index saved at {idx_file}") - - print(f"[RUN] {idx_name} ...") - - if idx_type == "Quake": - load_kwargs = {} - if "use_numa" in build_params: - load_kwargs["use_numa"] = build_params["use_numa"] - if "num_workers" in build_params: - load_kwargs["num_workers"] = build_params["num_workers"] - idx = IndexClass() - idx.load(str(idx_file), **load_kwargs) - elif idx_type == "DiskANN": - idx = IndexClass() - # remove metric from build_params - build_params.pop("metric", None) - idx.load(str(idx_file), **build_params) + # Build non-Quake index (one-off) + if typ != "Quake" and not idx_path.exists(): + print(f"[BUILD] {name} index …") + build_and_save(cls, b_params, base_vecs, idx_path) + print(f"[SAVE] index → {idx_path}") + + # ----------------------------------------------------------------- # + # Load # + # ----------------------------------------------------------------- # + if typ == "Quake": + load_kw = {k: b_params[k] for k in ("use_numa", "num_workers") if k in b_params} + idx = QuakeWrapper() + idx.load(str(idx_path), **load_kw) + elif typ == "DiskANN": + idx = cls() + b_params.pop("metric", None) # DiskANN load signature + idx.load(str(idx_path), **b_params) + else: + idx = cls() + idx.load(str(idx_path)) + + # ----------------------------------------------------------------- # + # Search parameter dispatch # + # ----------------------------------------------------------------- # + if typ == "SCANN": + search_kw = {"leaves_to_search": s_params.get("leaves_to_search", 100)} + elif typ == "HNSW": + search_kw = {"ef_search": s_params.get("ef_search", 32)} + elif typ == "DiskANN": + search_kw = {"complexity": s_params.get("complexity", 32)} + elif typ == "SVS": + search_kw = {"search_window_size": s_params.get("search_window_size", 32)} else: - idx = IndexClass() - idx.load(str(idx_file)) - - if idx_type == "SCANN": - search_args = {"leaves_to_search": search_params.get("leaves_to_search", 100)} - elif idx_type == "HNSW": - search_args = {"ef_search": search_params.get("ef_search", 32)} - elif idx_type == "DiskANN": - search_args = {"complexity": search_params.get("complexity", 32)} - elif idx_type == "SVS": - search_args = {"search_window_size": search_params.get("search_window_size", 32)} - else: # IVF, Quake, others - search_args = {"nprobe": search_params.get("nprobe", 100)} - - # Warmup - for i in range(min(warmup, len(queries))): - q = queries[i].unsqueeze(0).float() - idx.search(q, k, **search_args) - - # Benchmark Trials (and collect recall for first trial) - trial_means = [] - trial_recalls = [] + search_kw = {"nprobe": s_params.get("nprobe", 100)} + + # ----------------------------------------------------------------- # + # Warm-up # + # ----------------------------------------------------------------- # + for q in queries[:min(warmup_n, len(queries))]: + idx.search(q.unsqueeze(0).float(), k, **search_kw) + + # ----------------------------------------------------------------- # + # Trials # + # ----------------------------------------------------------------- # + trial_lat = [] + trial_rec = [] for t in range(trials): - lats = [] - if t == 0 and gt is not None: - all_preds = [] - for qi, q_vec in enumerate(queries): - q = q_vec.unsqueeze(0).float() - res = idx.search(q, k, **search_args) + lats_ms, preds = [], [] + for qi, q in enumerate(queries): + res = idx.search(q.unsqueeze(0).float(), k, **search_kw) + # latency collection ti = getattr(res, "timing_info", None) if ti and hasattr(ti, "total_time_ns"): - lats.append(ti.total_time_ns / 1e6) + lats_ms.append(ti.total_time_ns / 1e6) elif hasattr(res, "latency_ms"): - lats.append(res.latency_ms) + lats_ms.append(res.latency_ms) else: - raise RuntimeError(f"No timing info found in search result for {idx_name}") - # Collect predicted indices for recall in trial 0 + raise RuntimeError("missing timing info.") if t == 0 and gt is not None: - pred = res.ids # [1, k] - all_preds.append(pred[0]) # get the [k] - mean_t = float(np.mean(lats)) - trial_means.append(mean_t) + preds.append(extract_ids(res)[0]) # [k] + trial_lat.append(float(np.mean(lats_ms))) if t == 0 and gt is not None: - preds_arr = torch.stack(all_preds) # [num_queries, k] - print(f"[DEBUG] preds_arr shape: {preds_arr.shape}, gt shape: {gt.shape}") - recall = float(compute_recall(preds_arr, gt, k).mean()) - trial_recalls.append(recall) - print(f" [trial {t+1}/{trials}] {mean_t:.2f} ms | recall@{k}: {recall:.4f}") + recall = float(compute_recall(torch.tensor(preds), gt, k).mean()) + trial_rec.append(recall) + print(f" [{name} trial {t+1}/{trials}] {trial_lat[-1]:.2f} ms | R@{k} {recall:.4f}") else: - print(f" [trial {t+1}/{trials}] {mean_t:.2f} ms") + print(f" [{name} trial {t+1}/{trials}] {trial_lat[-1]:.2f} ms") - mean_lat = float(np.mean(trial_means)) - std_lat = float(np.std(trial_means)) - mean_recall = float(trial_recalls[0]) if trial_recalls else np.nan - n_workers_val = build_params.get("num_workers", None) + # ----------------------------------------------------------------- # + # Persist per-config results # + # ----------------------------------------------------------------- # row = { - "index": idx_name, - "n_workers": n_workers_val, - "mean_latency_ms": mean_lat, - "std_latency_ms": std_lat, - f"recall_at_{k}": mean_recall, + "index": name, + "n_workers": b_params.get("num_workers", np.nan), + "mean_latency_ms": float(np.mean(trial_lat)), + "std_latency_ms": float(np.std(trial_lat)), + f"recall_at_{k}": (float(trial_rec[0]) if trial_rec else np.nan), } - all_rows.append(row) + rows.append(row) pd.DataFrame([row]).to_csv(idx_csv, index=False) - # Save Unified CSV - df = pd.DataFrame(all_rows) + # --------------------------------------------------------------------- # + # Aggregate CSV + plots # + # --------------------------------------------------------------------- # + df = pd.DataFrame(rows) out_csv = out_dir / csv_name df.to_csv(out_csv, index=False) - print(f"\n[RESULT] Results written to {out_csv}") + print(f"\n[RESULT] aggregated CSV → {out_csv}") - # Plot Latency + # Latency plot plt.figure() - for idx_name in df["index"].unique(): - subset = df[df["index"] == idx_name] - label = f"{idx_name}" if subset["n_workers"].isnull().all() else f"{idx_name} (n_workers={subset['n_workers'].iloc[0]})" - plt.errorbar( - subset["n_workers"] if "n_workers" in subset else subset.index, - subset["mean_latency_ms"], - yerr=subset["std_latency_ms"], - marker="o", - capsize=5, - label=label - ) + for nm in df["index"].unique(): + sub = df[df["index"] == nm] + lbl = f"{nm}" if sub["n_workers"].isnull().all() else f"{nm} (nw={sub['n_workers'].iloc[0]})" + plt.errorbar(sub["n_workers"] if "n_workers" in sub else sub.index, + sub["mean_latency_ms"], yerr=sub["std_latency_ms"], + marker="o", capsize=5, label=lbl) plt.xscale("symlog", base=2) plt.xlabel("Num Workers") plt.ylabel("Mean Latency (ms)") - plt.title("Single-Query Latency (per-index)") + plt.title("Single-Query Latency") plt.legend() - plot_file = out_dir / f"{out_csv.stem}_latency.png" plt.tight_layout() - plt.savefig(plot_file) - print(f"[PLOT] Saved to {plot_file}") + lat_path = out_dir / f"{out_csv.stem}_latency.png" + plt.savefig(lat_path) + print(f"[PLOT] latency plot → {lat_path}") - # Plot Recall + # Recall plot if f"recall_at_{k}" in df.columns: plt.figure() - for idx_name in df["index"].unique(): - subset = df[df["index"] == idx_name] - label = f"{idx_name}" if subset["n_workers"].isnull().all() else f"{idx_name} (n_workers={subset['n_workers'].iloc[0]})" - plt.plot( - subset["n_workers"] if "n_workers" in subset else subset.index, - subset[f"recall_at_{k}"], - marker="o", - label=label - ) + for nm in df["index"].unique(): + sub = df[df["index"] == nm] + lbl = f"{nm}" if sub["n_workers"].isnull().all() else f"{nm} (nw={sub['n_workers'].iloc[0]})" + plt.plot(sub["n_workers"] if "n_workers" in sub else sub.index, + sub[f"recall_at_{k}"], marker="o", label=lbl) plt.xscale("symlog", base=2) plt.xlabel("Num Workers") plt.ylabel(f"Recall@{k}") - plt.title(f"Recall@{k} (per-index)") + plt.title(f"Recall@{k}") plt.legend() - plot_file = out_dir / f"{out_csv.stem}_recall.png" plt.tight_layout() - plt.savefig(plot_file) - print(f"[PLOT] Recall plot saved to {plot_file}") + rec_path = out_dir / f"{out_csv.stem}_recall.png" + plt.savefig(rec_path) + print(f"[PLOT] recall plot → {rec_path}") \ No newline at end of file From d587668eb62050680bbcd9f7d6a088bb285f423c Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 02:56:07 -0500 Subject: [PATCH 102/323] reuse sinlge query worker --- src/cpp/src/query_coordinator.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 73749609..6fc3eb62 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -103,6 +103,10 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { std::cout << "[QueryCoordinator::partition_scan_worker_fn] Failed to set thread affinity on core " << core_index << std::endl; } + int64_t total_pull_time = 0; + int64_t total_scan_time = 0; + int64_t total_merge_time = 0; + while (true) { ScanJob job; @@ -260,6 +264,10 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { auto process_time = std::chrono::duration_cast(s3 - s2).count(); auto merge_time = std::chrono::duration_cast(s4 - s3).count(); + total_pull_time += wait_time; + total_scan_time += process_time; + total_merge_time += merge_time; + // std::cout << "[QueryCoordinator::partition_scan_worker_fn] Worker " << core_index // << " wait_time: " << wait_time / 1e6 << " ms, " // << "process_time: " << process_time / 1e6 << " ms, " @@ -268,6 +276,8 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { auto job_process_end = std::chrono::high_resolution_clock::now(); job_process_time_ns += std::chrono::duration_cast(job_process_end - job_process_start).count(); } + + std::cout << "Worker=" << core_index << ": total_pull_time=" << total_pull_time / 1000 << ", total_scan_time=" << total_scan_time / 1000 << ", merge_time=" << merge_time / 1000 << '\n'; } // Worker-Based Scan Implementation From 53cb8a26e17a1d1a50416207b0db55253070bbac Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 02:56:18 -0500 Subject: [PATCH 103/323] reuse sinlge query worker --- src/cpp/src/query_coordinator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 6fc3eb62..4411c611 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -277,7 +277,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { job_process_time_ns += std::chrono::duration_cast(job_process_end - job_process_start).count(); } - std::cout << "Worker=" << core_index << ": total_pull_time=" << total_pull_time / 1000 << ", total_scan_time=" << total_scan_time / 1000 << ", merge_time=" << merge_time / 1000 << '\n'; + std::cout << "Worker=" << core_index << ": total_pull_time=" << total_pull_time / 1000 << ", total_scan_time=" << total_scan_time / 1000 << ", merge_time=" << total_merge_time / 1000 << '\n'; } // Worker-Based Scan Implementation From e0d3ab7534ec7f12834c05a114debfbb33dc52c5 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 02:58:47 -0500 Subject: [PATCH 104/323] reuse sinlge query worker --- src/cpp/src/query_coordinator.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 4411c611..4d57dafe 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -362,20 +362,23 @@ shared_ptr QueryCoordinator::worker_scan( if (search_params->batched_scan) { auto partition_ids_accessor = partition_ids.accessor(); - if (partition_manager_->nlist() == partition_ids.size(0)) { - std::cout << "SCAN ALL\n"; + auto pids = partition_manager_->get_partition_ids(); + auto pids_acc = pids.accessor(); + + if (pids.size(0) == partition_ids.size(1)) { vector all_query_ids = std::vector(x.size(0)); std::iota(all_query_ids.begin(), all_query_ids.end(), 0); - for (int64_t i = 0; i < partition_manager_->nlist(); i++) { + + for (int64_t i = 0; i < pids.size(0); i++) { ScanJob job; job.is_batched = true; - job.partition_id = i; + job.partition_id = pids_acc[i]; job.k = k; job.query_vector = x.data_ptr(); job.num_queries = x.size(0); job.query_ids = all_query_ids; - int core_id = partition_manager_->get_partition_core_id(i); + int core_id = partition_manager_->get_partition_core_id(pids_acc[i]); if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } @@ -383,7 +386,6 @@ shared_ptr QueryCoordinator::worker_scan( } } else { - std::cout << "BATCH SCAN SUBSET\n"; std::unordered_map> per_partition_query_ids; for (int64_t q = 0; q < num_queries; q++) { for (int64_t p = 0; p < partition_ids.size(1); p++) { @@ -408,7 +410,6 @@ shared_ptr QueryCoordinator::worker_scan( } } } else { - std::cout << "PER-QUERY SCAN\n"; auto partition_ids_accessor = partition_ids.accessor(); int64_t start = 0; @@ -559,13 +560,13 @@ shared_ptr QueryCoordinator::worker_scan( search_result->distances = topk_dists; search_result->timing_info = timing_info; - // print out timing info - std::cout << "[QueryCoordinator::worker_scan] Timing info: " << std::endl; - std::cout << "Total time: " << timing_info->total_time_ns / 1e6 << " ms" << std::endl; - std::cout << "Job enqueue time: " << timing_info->job_enqueue_time_ns / 1e6 << " ms" << std::endl; - std::cout << "Job wait time: " << timing_info->job_wait_time_ns / 1e6 << " ms" << std::endl; - std::cout << "Buffer init time: " << timing_info->buffer_init_time_ns / 1e6 << " ms" << std::endl; - std::cout << "Result agg time: " << timing_info->result_aggregate_time_ns / 1e6 << " ms" << std::endl; +// // print out timing info +// std::cout << "[QueryCoordinator::worker_scan] Timing info: " << std::endl; +// std::cout << "Total time: " << timing_info->total_time_ns / 1e6 << " ms" << std::endl; +// std::cout << "Job enqueue time: " << timing_info->job_enqueue_time_ns / 1e6 << " ms" << std::endl; +// std::cout << "Job wait time: " << timing_info->job_wait_time_ns / 1e6 << " ms" << std::endl; +// std::cout << "Buffer init time: " << timing_info->buffer_init_time_ns / 1e6 << " ms" << std::endl; +// std::cout << "Result agg time: " << timing_info->result_aggregate_time_ns / 1e6 << " ms" << std::endl; return search_result; } From 2d310d6573e23878eb8435d28d6b215be89ac300 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 03:00:33 -0500 Subject: [PATCH 105/323] reuse sinlge query worker --- test/experiments/osdi2025/numa_single_query/run.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index fddcc395..2a0c35e6 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -108,8 +108,6 @@ def run_experiment(cfg_path: str, output_dir: str) -> None: quake_base_path = out_dir / "Quake_base_index.bin" if quake_base_params: - if overwrite and quake_base_path.exists(): - os.remove(quake_base_path) if not quake_base_path.exists(): print("[BUILD] Quake (shared) base index …") build_and_save(QuakeWrapper, quake_base_params, base_vecs, quake_base_path) From 1fc264e2c6ff20884aae1ee6628435b590ab8d5b Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 03:05:17 -0500 Subject: [PATCH 106/323] reuse sinlge query worker --- src/cpp/src/query_coordinator.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 4d57dafe..fb43996f 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -160,6 +160,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { // Branch for non-batched jobs. if (!job.is_batched) { + auto s1 = std::chrono::high_resolution_clock::now(); // Allocate a thread-local query buffer if needed. if (res.local_query_buffer.size() < partition_manager_->d() * sizeof(float)) { res.local_query_buffer.resize(partition_manager_->d() * sizeof(float)); @@ -176,6 +177,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { local_topk_buffer->set_k(job.k); local_topk_buffer->reset(); } + auto s2 = std::chrono::high_resolution_clock::now(); // Perform the scan on the partition. scan_list((float *) res.local_query_buffer.data(), partition_codes, @@ -184,6 +186,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { partition_manager_->d(), *local_topk_buffer, metric_); + auto s3 = std::chrono::high_resolution_clock::now(); vector topk = local_topk_buffer->get_topk(); vector topk_indices = local_topk_buffer->get_topk_indices(); @@ -192,6 +195,17 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { // Merge local results into the global query buffer. global_topk_buffer_pool_[job.query_ids[0]]->batch_add(topk.data(), topk_indices.data(), n_results); job_flags_[job.query_ids[0]][job.rank] = true; + + auto s4 = std::chrono::high_resolution_clock::now(); + + // print out timings for worker + auto wait_time = std::chrono::duration_cast(s2 - s1).count(); + auto process_time = std::chrono::duration_cast(s3 - s2).count(); + auto merge_time = std::chrono::duration_cast(s4 - s3).count(); + + total_pull_time += wait_time; + total_scan_time += process_time; + total_merge_time += merge_time; } // Batched job branch. else { @@ -267,11 +281,6 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { total_pull_time += wait_time; total_scan_time += process_time; total_merge_time += merge_time; - -// std::cout << "[QueryCoordinator::partition_scan_worker_fn] Worker " << core_index -// << " wait_time: " << wait_time / 1e6 << " ms, " -// << "process_time: " << process_time / 1e6 << " ms, " -// << "merge_time: " << merge_time / 1e6 << " ms" << std::endl; } auto job_process_end = std::chrono::high_resolution_clock::now(); job_process_time_ns += std::chrono::duration_cast(job_process_end - job_process_start).count(); @@ -801,7 +810,6 @@ shared_ptr QueryCoordinator::search(Tensor x, shared_ptrparent_params; } - parent_search_params->batched_scan = true; // if recall_target is set, we need an initial set of partitions to consider if (search_params->recall_target > 0.0 && !search_params->batched_scan) { From 74fd832e1d759c610f92694b51b1837270bdb1a2 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 11:18:40 -0500 Subject: [PATCH 107/323] reuse sinlge query worker --- src/cpp/src/query_coordinator.cpp | 5 +- .../osdi2025/numa_single_query/run.py | 267 +++++++++--------- 2 files changed, 141 insertions(+), 131 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index fb43996f..37abac8c 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -294,6 +294,9 @@ shared_ptr QueryCoordinator::worker_scan( Tensor x, Tensor partition_ids, shared_ptr search_params) { + + auto start_time = high_resolution_clock::now(); + if (!partition_manager_) { throw std::runtime_error("[QueryCoordinator::worker_scan] partition_manager_ is null."); } @@ -318,8 +321,6 @@ shared_ptr QueryCoordinator::worker_scan( float *x_ptr = x.data_ptr(); - auto start_time = high_resolution_clock::now(); - if (partition_ids.dim() == 1) { partition_ids = partition_ids.unsqueeze(0).expand({num_queries, partition_ids.size(0)}); } diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index 2a0c35e6..f105cb3c 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -1,18 +1,19 @@ #!/usr/bin/env python3 """ -NUMA Single-Query Latency and Recall Benchmark (v2) +NUMA Single-Query Latency and Recall Benchmark (detailed timers, aggregated) -Builds each non-Quake index once. -Builds **one** shared Quake base-index and re-uses it for every Quake -configuration, so we avoid the O(dataset) rebuild for each worker-count. +For each query we extract: + - buffer_init_time_ns + - job_enqueue_time_ns + - job_wait_time_ns + - result_aggregate_time_ns + - total_time_ns -Usage ------ - python numa_latency_experiment.py +We average each timer across queries in a trial, then average across trials, +and emit those means (in ms) alongside recall and latency. """ - +import sys from pathlib import Path -import os import yaml import numpy as np import torch @@ -46,17 +47,14 @@ "SVS": Vamana, } -# --------------------------------------------------------------------------- # -# Helpers # -# --------------------------------------------------------------------------- # def build_and_save(index_cls, params, vecs, path): - """Build with on and persist to .""" + """Builds and persists an index to disk.""" idx = index_cls() idx.build(vecs, **params) idx.save(str(path)) def extract_ids(res): - """Return search‐result ids as np.ndarray.""" + """Normalize the returned IDs array.""" if hasattr(res, "ids"): arr = res.ids elif hasattr(res, "I"): @@ -69,97 +67,81 @@ def extract_ids(res): arr = arr.cpu().numpy() return np.asarray(arr, dtype=np.int64) -# --------------------------------------------------------------------------- # -# Main # -# --------------------------------------------------------------------------- # def run_experiment(cfg_path: str, output_dir: str) -> None: - cfg = yaml.safe_load(Path(cfg_path).read_text()) - ds_cfg = cfg["dataset"] - k = ds_cfg["k"] - q_n = ds_cfg["num_queries"] - trials = cfg.get("trials", 5) - warmup_n = cfg.get("warmup", 10) - idx_cfgs = cfg["indexes"] - csv_name = cfg.get("output", {}).get("results_csv", "numa_results.csv") - overwrite = cfg.get("overwrite", False) + cfg = yaml.safe_load(Path(cfg_path).read_text()) + ds_cfg = cfg["dataset"] + k = ds_cfg["k"] + q_n = ds_cfg["num_queries"] + trials = cfg.get("trials", 5) + warmup_n = cfg.get("warmup", 10) + idx_cfgs = cfg["indexes"] + csv_name = cfg.get("output", {}).get("results_csv", "numa_results.csv") + overwrite = cfg.get("overwrite", False) out_dir = Path(output_dir).expanduser().absolute() out_dir.mkdir(parents=True, exist_ok=True) - # --------------------------------------------------------------------- # - # Dataset # - # --------------------------------------------------------------------- # + # Load data print(f"[INFO] loading dataset {ds_cfg['name']} …") base_vecs, queries, gt = load_dataset(ds_cfg["name"]) queries = queries[:q_n] gt = gt[:q_n] if gt is not None else None - # --------------------------------------------------------------------- # - # Build a single Quake base index (if any Quake config exists) # - # --------------------------------------------------------------------- # + # Build shared Quake base index if needed quake_base_params = None - for cfg_i in idx_cfgs: - if cfg_i["index"] == "Quake": - quake_base_params = dict(cfg_i.get("build_params", {})) - # Remove loading-stage-only keys; not needed for the build - quake_base_params.pop("num_workers", None) - quake_base_params.pop("use_numa", None) + for c in idx_cfgs: + if c["index"] == "Quake": + earthquake = dict(c.get("build_params", {})) + earthquake.pop("num_workers", None) + earthquake.pop("use_numa", None) + quake_base_params = earthquake break quake_base_path = out_dir / "Quake_base_index.bin" - if quake_base_params: - if not quake_base_path.exists(): - print("[BUILD] Quake (shared) base index …") - build_and_save(QuakeWrapper, quake_base_params, base_vecs, quake_base_path) - print(f"[SAVE] Quake base index → {quake_base_path}") + if quake_base_params and not quake_base_path.exists(): + print("[BUILD] Quake (shared) base index …") + build_and_save(QuakeWrapper, quake_base_params, base_vecs, quake_base_path) + print(f"[SAVE] Quake base index → {quake_base_path}") - # --------------------------------------------------------------------- # - # Per-configuration benchmarking # - # --------------------------------------------------------------------- # - rows = [] + results = [] for cfg_i in idx_cfgs: - name = cfg_i["name"] - typ = cfg_i["index"] - b_params = dict(cfg_i.get("build_params", {})) # safe copy - s_params = dict(cfg_i.get("search_params", {})) - cls = INDEX_CLASSES.get(typ) + name = cfg_i["name"] + typ = cfg_i["index"] + b_params = dict(cfg_i.get("build_params", {})) + s_params = dict(cfg_i.get("search_params", {})) + cls = INDEX_CLASSES.get(typ) if cls is None: print(f"[WARN] unknown index type '{typ}' – skipping.") continue idx_csv = out_dir / f"{name}_results.csv" - idx_path = quake_base_path if typ == "Quake" else out_dir / f"{name}_index.bin" + idx_path = (quake_base_path if typ == "Quake" + else out_dir / f"{name}_index.bin") - # Skip if we already have results and not overwriting + # Skip if done if idx_csv.exists() and not overwrite: print(f"[SKIP] {name} – results exist.") - rows.append(pd.read_csv(idx_csv).iloc[0].to_dict()) + results.append(pd.read_csv(idx_csv).iloc[0].to_dict()) continue - # Build non-Quake index (one-off) + # Build non-Quake if missing if typ != "Quake" and not idx_path.exists(): print(f"[BUILD] {name} index …") build_and_save(cls, b_params, base_vecs, idx_path) print(f"[SAVE] index → {idx_path}") - # ----------------------------------------------------------------- # - # Load # - # ----------------------------------------------------------------- # + # Load index if typ == "Quake": - load_kw = {k: b_params[k] for k in ("use_numa", "num_workers") if k in b_params} - idx = QuakeWrapper() - idx.load(str(idx_path), **load_kw) + load_kw = {k: b_params[k] + for k in ("use_numa", "num_workers") + if k in b_params} + idx = QuakeWrapper(); idx.load(str(idx_path), **load_kw) elif typ == "DiskANN": - idx = cls() - b_params.pop("metric", None) # DiskANN load signature - idx.load(str(idx_path), **b_params) + idx = cls(); b_params.pop("metric", None); idx.load(str(idx_path), **b_params) else: - idx = cls() - idx.load(str(idx_path)) + idx = cls(); idx.load(str(idx_path)) - # ----------------------------------------------------------------- # - # Search parameter dispatch # - # ----------------------------------------------------------------- # + # Dispatch search params if typ == "SCANN": search_kw = {"leaves_to_search": s_params.get("leaves_to_search", 100)} elif typ == "HNSW": @@ -171,92 +153,119 @@ def run_experiment(cfg_path: str, output_dir: str) -> None: else: search_kw = {"nprobe": s_params.get("nprobe", 100)} - # ----------------------------------------------------------------- # - # Warm-up # - # ----------------------------------------------------------------- # + # Warm-up for q in queries[:min(warmup_n, len(queries))]: idx.search(q.unsqueeze(0).float(), k, **search_kw) - # ----------------------------------------------------------------- # - # Trials # - # ----------------------------------------------------------------- # - trial_lat = [] - trial_rec = [] + # Collect per-trial means + all_trial_latencies = [] + all_trial_recalls = [] + # for each timer: list of trial-means + buf_init_trials = [] + enqueue_trials = [] + wait_trials = [] + agg_trials = [] + total_trials = [] + for t in range(trials): - lats_ms, preds = [], [] + latencies = [] + recalls = [] + buf_init_q = [] + enq_q = [] + wait_q = [] + agg_q = [] + total_q = [] + for qi, q in enumerate(queries): res = idx.search(q.unsqueeze(0).float(), k, **search_kw) - # latency collection - ti = getattr(res, "timing_info", None) - if ti and hasattr(ti, "total_time_ns"): - lats_ms.append(ti.total_time_ns / 1e6) - elif hasattr(res, "latency_ms"): - lats_ms.append(res.latency_ms) + ti = res.timing_info + # latency + if hasattr(ti, "total_time_ns"): + latencies.append(ti.total_time_ns / 1e6) else: - raise RuntimeError("missing timing info.") + raise RuntimeError("missing total_time_ns") + # recall on first trial only if t == 0 and gt is not None: - preds.append(extract_ids(res)[0]) # [k] - trial_lat.append(float(np.mean(lats_ms))) - if t == 0 and gt is not None: - recall = float(compute_recall(torch.tensor(preds), gt, k).mean()) - trial_rec.append(recall) - print(f" [{name} trial {t+1}/{trials}] {trial_lat[-1]:.2f} ms | R@{k} {recall:.4f}") - else: - print(f" [{name} trial {t+1}/{trials}] {trial_lat[-1]:.2f} ms") + preds = extract_ids(res)[0] + recalls.append(float(compute_recall(torch.tensor([preds]), gt[qi:qi+1], k).item())) + + # collect timers (ns) + buf_init_q.append(ti.buffer_init_time_ns) + enq_q.append (ti.job_enqueue_time_ns) + wait_q.append (ti.job_wait_time_ns) + agg_q.append (ti.result_aggregate_time_ns) + total_q.append (ti.total_time_ns) + + # trial means in ms + all_trial_latencies.append(np.mean(latencies)) + buf_init_trials.append(np.mean(buf_init_q) / 1e6) + enqueue_trials .append(np.mean(enq_q) / 1e6) + wait_trials .append(np.mean(wait_q) / 1e6) + agg_trials .append(np.mean(agg_q) / 1e6) + total_trials .append(np.mean(total_q) / 1e6) + + if t == 0 and recalls: + all_trial_recalls.append(np.mean(recalls)) + + print(f" [{name} trial {t+1}/{trials}] " + f"{all_trial_latencies[-1]:.2f} ms" + + (f" | R@{k} {all_trial_recalls[-1]:.4f}" if recalls else "")) - # ----------------------------------------------------------------- # - # Persist per-config results # - # ----------------------------------------------------------------- # + # final averages across trials row = { - "index": name, - "n_workers": b_params.get("num_workers", np.nan), - "mean_latency_ms": float(np.mean(trial_lat)), - "std_latency_ms": float(np.std(trial_lat)), - f"recall_at_{k}": (float(trial_rec[0]) if trial_rec else np.nan), + "index": name, + "n_workers": b_params.get("num_workers", np.nan), + "mean_latency_ms": float(np.mean(all_trial_latencies)), + "std_latency_ms": float(np.std(all_trial_latencies)), + f"recall_at_{k}": (float(all_trial_recalls[0]) if all_trial_recalls else np.nan), + "buffer_init_ms": float(np.mean(buf_init_trials)), + "enqueue_ms": float(np.mean(enqueue_trials)), + "wait_ms": float(np.mean(wait_trials)), + "aggregate_ms": float(np.mean(agg_trials)), + "total_time_ms": float(np.mean(total_trials)), } - rows.append(row) + results.append(row) pd.DataFrame([row]).to_csv(idx_csv, index=False) - # --------------------------------------------------------------------- # - # Aggregate CSV + plots # - # --------------------------------------------------------------------- # - df = pd.DataFrame(rows) - out_csv = out_dir / csv_name + # write aggregate CSV + plots + df = pd.DataFrame(results) + out_csv = Path(output_dir) / csv_name df.to_csv(out_csv, index=False) print(f"\n[RESULT] aggregated CSV → {out_csv}") - # Latency plot + # latency plot plt.figure() for nm in df["index"].unique(): sub = df[df["index"] == nm] - lbl = f"{nm}" if sub["n_workers"].isnull().all() else f"{nm} (nw={sub['n_workers'].iloc[0]})" - plt.errorbar(sub["n_workers"] if "n_workers" in sub else sub.index, - sub["mean_latency_ms"], yerr=sub["std_latency_ms"], - marker="o", capsize=5, label=lbl) + lbl = (nm if sub["n_workers"].isnull().all() + else f"{nm} (nw={int(sub['n_workers'].iloc[0])})") + plt.errorbar( + sub["n_workers"] if "n_workers" in sub else sub.index, + sub["mean_latency_ms"], + yerr=sub["std_latency_ms"], + marker="o", capsize=5, label=lbl + ) plt.xscale("symlog", base=2) - plt.xlabel("Num Workers") - plt.ylabel("Mean Latency (ms)") - plt.title("Single-Query Latency") - plt.legend() - plt.tight_layout() - lat_path = out_dir / f"{out_csv.stem}_latency.png" + plt.xlabel("Num Workers"); plt.ylabel("Mean Latency (ms)") + plt.title("Single-Query Latency"); plt.legend(); plt.tight_layout() + lat_path = Path(output_dir) / f"{out_csv.stem}_latency.png" plt.savefig(lat_path) print(f"[PLOT] latency plot → {lat_path}") - # Recall plot + # recall plot if f"recall_at_{k}" in df.columns: plt.figure() for nm in df["index"].unique(): sub = df[df["index"] == nm] - lbl = f"{nm}" if sub["n_workers"].isnull().all() else f"{nm} (nw={sub['n_workers'].iloc[0]})" - plt.plot(sub["n_workers"] if "n_workers" in sub else sub.index, - sub[f"recall_at_{k}"], marker="o", label=lbl) + lbl = (nm if sub["n_workers"].isnull().all() + else f"{nm} (nw={int(sub['n_workers'].iloc[0])})") + plt.plot( + sub["n_workers"] if "n_workers" in sub else sub.index, + sub[f"recall_at_{k}"], marker="o", label=lbl + ) plt.xscale("symlog", base=2) - plt.xlabel("Num Workers") - plt.ylabel(f"Recall@{k}") - plt.title(f"Recall@{k}") - plt.legend() - plt.tight_layout() - rec_path = out_dir / f"{out_csv.stem}_recall.png" + plt.xlabel("Num Workers"); plt.ylabel(f"Recall@{k}") + plt.title(f"Recall@{k}"); plt.legend(); plt.tight_layout() + rec_path = Path(output_dir) / f"{out_csv.stem}_recall.png" plt.savefig(rec_path) print(f"[PLOT] recall plot → {rec_path}") \ No newline at end of file From e49c6751dff8f75be4f9f731cf5db8dfb2625799 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 11:30:45 -0500 Subject: [PATCH 108/323] minimize job enqueing time --- src/cpp/include/query_coordinator.h | 3 ++- src/cpp/src/query_coordinator.cpp | 35 ++++++++++++++++------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 60a80b48..e6965659 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -53,7 +53,7 @@ class QueryCoordinator { int core_id; ///< Logical identifier of the core. vector> topk_buffer_pool; ///< Preallocated Top‑K buffers. vector local_query_buffer; ///< Local aggregator for query results. - moodycamel::BlockingConcurrentQueue job_queue; ///< Job queue for scan jobs. + moodycamel::BlockingConcurrentQueue job_queue; ///< Job queue for scan jobs. }; vector core_resources_; ///< Per‑core resources for worker threads. @@ -67,6 +67,7 @@ class QueryCoordinator { std::atomic stop_workers_; ///< Flag to signal workers to terminate. bool debug_ = false; ///< Debug mode flag. + std::vector job_buffer_; vector>> job_flags_; ///< Flags to track job completion std::atomic job_pull_time_ns = 0; ///< Time spent pulling jobs from the queue. std::atomic job_process_time_ns = 0; ///< Time spent processing jobs. diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 37abac8c..70a8213d 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -42,7 +42,7 @@ void QueryCoordinator::allocate_core_resources(int core_idx, int num_queries, in res.topk_buffer_pool.resize(num_queries); for (int q = 0; q < num_queries; ++q) { res.topk_buffer_pool[q] = make_shared(k, metric_ == faiss::METRIC_INNER_PRODUCT); - res.job_queue = moodycamel::BlockingConcurrentQueue(); + res.job_queue = moodycamel::BlockingConcurrentQueue(); } } @@ -81,9 +81,7 @@ void QueryCoordinator::shutdown_workers() { stop_workers_.store(true); // Enqueue a special shutdown job for each core. for (auto &res : core_resources_) { - ScanJob termination_job; - termination_job.partition_id = -1; - res.job_queue.enqueue(termination_job); + res.job_queue.enqueue(-1); } // Join all worker threads. for (auto &thr : worker_threads_) { @@ -108,10 +106,10 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { int64_t total_merge_time = 0; while (true) { - ScanJob job; auto job_wait_start = std::chrono::high_resolution_clock::now(); - res.job_queue.wait_dequeue(job); + int64_t job_id; + res.job_queue.wait_dequeue(job_id); auto job_wait_end = std::chrono::high_resolution_clock::now(); job_pull_time_ns += std::chrono::duration_cast(job_wait_end - job_wait_start).count(); @@ -120,10 +118,12 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { shared_ptr local_topk_buffer = res.topk_buffer_pool[0]; // Shutdown signal: -1 indicates the worker should exit. - if (job.partition_id == -1) { + if (job_id == -1) { break; } + ScanJob job = job_buffer_[job_id]; + // Ignore this job if the global buffer is not processing queries. if (!global_topk_buffer_pool_[job.query_ids[0]]->currently_processing_query()) { // decrement the job counter @@ -327,6 +327,8 @@ shared_ptr QueryCoordinator::worker_scan( auto partition_ids_accessor = partition_ids.accessor(); + + job_buffer_.clear(); job_flags_.clear(); job_flags_.resize(num_queries); for (int64_t q = 0; q < num_queries; q++) { @@ -392,7 +394,9 @@ shared_ptr QueryCoordinator::worker_scan( if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } - core_resources_[core_id].job_queue.enqueue(job); + job_buffer_.push_back(job); + int64_t jid = (int64_t)job_buffer_.size() - 1; + core_resources_[core_id].job_queue.enqueue(jid); } } else { @@ -416,15 +420,14 @@ shared_ptr QueryCoordinator::worker_scan( if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } - core_resources_[core_id].job_queue.enqueue(job); + job_buffer_.push_back(job); + int64_t jid = (int64_t)job_buffer_.size() - 1; + core_resources_[core_id].job_queue.enqueue(jid); } } } else { auto partition_ids_accessor = partition_ids.accessor(); - - int64_t start = 0; - int64_t end = num_queries; - parallel_for(start, end, [&](int64_t q) { + for (int q = 0; q < num_queries; q++) { for (int64_t p = 0; p < partition_ids.size(1); p++) { int64_t pid = partition_ids_accessor[q][p]; if (pid == -1) continue; @@ -442,9 +445,11 @@ shared_ptr QueryCoordinator::worker_scan( if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } - core_resources_[core_id].job_queue.enqueue(job); + job_buffer_.push_back(job); + int64_t jid = (int64_t)job_buffer_.size() - 1; + core_resources_[core_id].job_queue.enqueue(jid); } - }, search_params->num_threads); + } } end_time = high_resolution_clock::now(); timing_info->job_enqueue_time_ns = duration_cast(end_time - start_time).count(); From 5ce528233c0a2cabc88e77f608d9ef8331617fc3 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 11:35:09 -0500 Subject: [PATCH 109/323] minimize job enqueing time --- src/cpp/src/query_coordinator.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 70a8213d..66a2634d 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -394,8 +394,8 @@ shared_ptr QueryCoordinator::worker_scan( if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } - job_buffer_.push_back(job); - int64_t jid = (int64_t)job_buffer_.size() - 1; + int64_t jid = job_buffer_.size(); + job_buffer_[jid] = job; core_resources_[core_id].job_queue.enqueue(jid); } @@ -420,13 +420,15 @@ shared_ptr QueryCoordinator::worker_scan( if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } - job_buffer_.push_back(job); - int64_t jid = (int64_t)job_buffer_.size() - 1; + int64_t jid = job_buffer_.size(); + job_buffer_[jid] = job; core_resources_[core_id].job_queue.enqueue(jid); } } } else { auto partition_ids_accessor = partition_ids.accessor(); + + job_buffer_.reserve(num_queries * partition_ids.size(1)); for (int q = 0; q < num_queries; q++) { for (int64_t p = 0; p < partition_ids.size(1); p++) { int64_t pid = partition_ids_accessor[q][p]; @@ -445,8 +447,8 @@ shared_ptr QueryCoordinator::worker_scan( if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } - job_buffer_.push_back(job); - int64_t jid = (int64_t)job_buffer_.size() - 1; + int64_t jid = job_buffer_.size(); + job_buffer_[jid] = job; core_resources_[core_id].job_queue.enqueue(jid); } } From 2b36a02ba28b50896e791d2bf9622cca8c9c76ca Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 11:35:23 -0500 Subject: [PATCH 110/323] minimize job enqueing time --- src/cpp/src/query_coordinator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 66a2634d..93435d0d 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -286,7 +286,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { job_process_time_ns += std::chrono::duration_cast(job_process_end - job_process_start).count(); } - std::cout << "Worker=" << core_index << ": total_pull_time=" << total_pull_time / 1000 << ", total_scan_time=" << total_scan_time / 1000 << ", merge_time=" << total_merge_time / 1000 << '\n'; +// std::cout << "Worker=" << core_index << ": total_pull_time=" << total_pull_time / 1000 << ", total_scan_time=" << total_scan_time / 1000 << ", merge_time=" << total_merge_time / 1000 << '\n'; } // Worker-Based Scan Implementation From 343bf4e8189b4b68445f553b5e92778a31f8f1af Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 11:41:49 -0500 Subject: [PATCH 111/323] minimize job enqueing time --- src/cpp/include/query_coordinator.h | 1 + src/cpp/src/query_coordinator.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index e6965659..f645284b 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -68,6 +68,7 @@ class QueryCoordinator { bool debug_ = false; ///< Debug mode flag. std::vector job_buffer_; + std::atomic next_job_id_{0}; vector>> job_flags_; ///< Flags to track job completion std::atomic job_pull_time_ns = 0; ///< Time spent pulling jobs from the queue. std::atomic job_process_time_ns = 0; ///< Time spent processing jobs. diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 93435d0d..7508a9fc 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -373,7 +373,7 @@ shared_ptr QueryCoordinator::worker_scan( start_time = high_resolution_clock::now(); if (search_params->batched_scan) { auto partition_ids_accessor = partition_ids.accessor(); - + job_buffer_.resize(partition_manager_->nlist()); auto pids = partition_manager_->get_partition_ids(); auto pids_acc = pids.accessor(); @@ -394,7 +394,7 @@ shared_ptr QueryCoordinator::worker_scan( if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } - int64_t jid = job_buffer_.size(); + size_t jid = next_job_id_.fetch_add(1, std::memory_order_acq_rel); job_buffer_[jid] = job; core_resources_[core_id].job_queue.enqueue(jid); } @@ -420,7 +420,7 @@ shared_ptr QueryCoordinator::worker_scan( if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } - int64_t jid = job_buffer_.size(); + size_t jid = next_job_id_.fetch_add(1, std::memory_order_acq_rel); job_buffer_[jid] = job; core_resources_[core_id].job_queue.enqueue(jid); } @@ -428,7 +428,7 @@ shared_ptr QueryCoordinator::worker_scan( } else { auto partition_ids_accessor = partition_ids.accessor(); - job_buffer_.reserve(num_queries * partition_ids.size(1)); + job_buffer_.resize(num_queries * partition_ids.size(1)); for (int q = 0; q < num_queries; q++) { for (int64_t p = 0; p < partition_ids.size(1); p++) { int64_t pid = partition_ids_accessor[q][p]; @@ -447,9 +447,9 @@ shared_ptr QueryCoordinator::worker_scan( if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } - int64_t jid = job_buffer_.size(); + size_t jid = next_job_id_.fetch_add(1, std::memory_order_acq_rel); job_buffer_[jid] = job; - core_resources_[core_id].job_queue.enqueue(jid); + core_resources_[core_id].job_queue.enqueue((int64_t) jid); } } } From ed670134c06a84832111fa8bca3d5d82ceb6e1a4 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 11:51:37 -0500 Subject: [PATCH 112/323] minimize job enqueing time --- src/cpp/src/query_coordinator.cpp | 1 + test/cpp/benchmark.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 7508a9fc..7a977f95 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -329,6 +329,7 @@ shared_ptr QueryCoordinator::worker_scan( job_buffer_.clear(); + next_job_id_.store(0); job_flags_.clear(); job_flags_.resize(num_queries); for (int64_t q = 0; q < num_queries; q++) { diff --git a/test/cpp/benchmark.cpp b/test/cpp/benchmark.cpp index cd18cda3..3357086a 100644 --- a/test/cpp/benchmark.cpp +++ b/test/cpp/benchmark.cpp @@ -27,9 +27,9 @@ using torch::Tensor; // Global benchmark parameters static const int64_t DIM = 128; -static const int64_t NUM_VECTORS = 1000000; // number of database vectors +static const int64_t NUM_VECTORS = 100000; // number of database vectors static const int64_t N_LIST = 1000; // number of clusters for IVF -static const int64_t NUM_QUERIES = 10000; // number of queries for search benchmark +static const int64_t NUM_QUERIES = 1000; // number of queries for search benchmark static const int64_t K = 10; // top-K neighbors static const int64_t N_PROBE = 20; // number of probes for IVF static const int64_t N_WORKERS = 12; // number of workers for parallel query coordinator From d7bf3f794b90484c3434c0db04fd0661f069cc65 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 12:07:10 -0500 Subject: [PATCH 113/323] minimize job enqueing time --- src/cpp/src/query_coordinator.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 7a977f95..c6df9cfe 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -430,6 +430,7 @@ shared_ptr QueryCoordinator::worker_scan( auto partition_ids_accessor = partition_ids.accessor(); job_buffer_.resize(num_queries * partition_ids.size(1)); + vector> per_worker_job_ids(num_workers_); for (int q = 0; q < num_queries; q++) { for (int64_t p = 0; p < partition_ids.size(1); p++) { int64_t pid = partition_ids_accessor[q][p]; @@ -450,9 +451,13 @@ shared_ptr QueryCoordinator::worker_scan( } size_t jid = next_job_id_.fetch_add(1, std::memory_order_acq_rel); job_buffer_[jid] = job; - core_resources_[core_id].job_queue.enqueue((int64_t) jid); + per_worker_job_ids[core_id].push_back(jid); +// core_resources_[core_id].job_queue.enqueue((int64_t) jid); } } + for (int i = 0; i < num_workers_; i++) { + core_resources_[i].job_queue.enqueue_bulk(per_worker_job_ids[i].begin(), per_worker_job_ids[i].size()); + } } end_time = high_resolution_clock::now(); timing_info->job_enqueue_time_ns = duration_cast(end_time - start_time).count(); From 10e5afaa3bc36271225d06ba91ffe9ec2afb813b Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 12:10:09 -0500 Subject: [PATCH 114/323] minimize job enqueing time --- src/cpp/src/query_coordinator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index c6df9cfe..dff02690 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -455,11 +455,12 @@ shared_ptr QueryCoordinator::worker_scan( // core_resources_[core_id].job_queue.enqueue((int64_t) jid); } } + end_time = high_resolution_clock::now(); for (int i = 0; i < num_workers_; i++) { core_resources_[i].job_queue.enqueue_bulk(per_worker_job_ids[i].begin(), per_worker_job_ids[i].size()); } } - end_time = high_resolution_clock::now(); +// end_time = high_resolution_clock::now(); timing_info->job_enqueue_time_ns = duration_cast(end_time - start_time).count(); auto last_flush_time = high_resolution_clock::now(); From 927592865817af02de975e3ee1552f516239276c Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 12:21:17 -0500 Subject: [PATCH 115/323] try out producer token --- src/cpp/include/query_coordinator.h | 1 + src/cpp/src/query_coordinator.cpp | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index f645284b..90d8cfa7 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -54,6 +54,7 @@ class QueryCoordinator { vector> topk_buffer_pool; ///< Preallocated Top‑K buffers. vector local_query_buffer; ///< Local aggregator for query results. moodycamel::BlockingConcurrentQueue job_queue; ///< Job queue for scan jobs. + std::unique_ptr producer_token; }; vector core_resources_; ///< Per‑core resources for worker threads. diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index dff02690..58c001f3 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -69,6 +69,10 @@ void QueryCoordinator::initialize_workers(int num_cores, bool use_numa) { worker_threads_[i] = std::thread(&QueryCoordinator::partition_scan_worker_fn, this, i); worker_job_counter_[i] = 0; } + for (int i = 0; i < num_workers_; i++) { + core_resources_[i].producer_token = + std::make_unique(core_resources_[i].job_queue); + } workers_initialized_ = true; } @@ -455,12 +459,20 @@ shared_ptr QueryCoordinator::worker_scan( // core_resources_[core_id].job_queue.enqueue((int64_t) jid); } } - end_time = high_resolution_clock::now(); for (int i = 0; i < num_workers_; i++) { - core_resources_[i].job_queue.enqueue_bulk(per_worker_job_ids[i].begin(), per_worker_job_ids[i].size()); + auto &ids = per_worker_job_ids[i]; + auto &pt = *core_resources_[i].producer_token; + core_resources_[i].job_queue.enqueue_bulk( + pt, + ids.data(), + ids.size() + ); } +// for (int i = 0; i < num_workers_; i++) { +// core_resources_[i].job_queue.enqueue_bulk(per_worker_job_ids[i].begin(), per_worker_job_ids[i].size()); +// } } -// end_time = high_resolution_clock::now(); + end_time = high_resolution_clock::now(); timing_info->job_enqueue_time_ns = duration_cast(end_time - start_time).count(); auto last_flush_time = high_resolution_clock::now(); From bccca2a0e51075814d7a77359e9aa6f73782530f Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 12:30:15 -0500 Subject: [PATCH 116/323] try out producer token --- src/cpp/include/query_coordinator.h | 3 +-- src/cpp/src/query_coordinator.cpp | 13 +++++-------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 90d8cfa7..6d015dab 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -53,8 +53,7 @@ class QueryCoordinator { int core_id; ///< Logical identifier of the core. vector> topk_buffer_pool; ///< Preallocated Top‑K buffers. vector local_query_buffer; ///< Local aggregator for query results. - moodycamel::BlockingConcurrentQueue job_queue; ///< Job queue for scan jobs. - std::unique_ptr producer_token; + moodycamel::ConcurrentQueue job_queue; ///< Job queue for scan jobs. }; vector core_resources_; ///< Per‑core resources for worker threads. diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 58c001f3..1bbc42a8 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -42,7 +42,7 @@ void QueryCoordinator::allocate_core_resources(int core_idx, int num_queries, in res.topk_buffer_pool.resize(num_queries); for (int q = 0; q < num_queries; ++q) { res.topk_buffer_pool[q] = make_shared(k, metric_ == faiss::METRIC_INNER_PRODUCT); - res.job_queue = moodycamel::BlockingConcurrentQueue(); + res.job_queue = moodycamel::ConcurrentQueue(); } } @@ -69,10 +69,6 @@ void QueryCoordinator::initialize_workers(int num_cores, bool use_numa) { worker_threads_[i] = std::thread(&QueryCoordinator::partition_scan_worker_fn, this, i); worker_job_counter_[i] = 0; } - for (int i = 0; i < num_workers_; i++) { - core_resources_[i].producer_token = - std::make_unique(core_resources_[i].job_queue); - } workers_initialized_ = true; } @@ -113,7 +109,10 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { auto job_wait_start = std::chrono::high_resolution_clock::now(); int64_t job_id; - res.job_queue.wait_dequeue(job_id); + while (!res.job_queue.try_dequeue(job_id)) { + std::this_thread::yield(); + } + auto job_wait_end = std::chrono::high_resolution_clock::now(); job_pull_time_ns += std::chrono::duration_cast(job_wait_end - job_wait_start).count(); @@ -461,9 +460,7 @@ shared_ptr QueryCoordinator::worker_scan( } for (int i = 0; i < num_workers_; i++) { auto &ids = per_worker_job_ids[i]; - auto &pt = *core_resources_[i].producer_token; core_resources_[i].job_queue.enqueue_bulk( - pt, ids.data(), ids.size() ); From e56303ed125a037df4b2bed7a10f3b876ad233be Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 12:33:56 -0500 Subject: [PATCH 117/323] try out producer token --- src/cpp/src/query_coordinator.cpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 1bbc42a8..6660bba8 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -433,7 +433,6 @@ shared_ptr QueryCoordinator::worker_scan( auto partition_ids_accessor = partition_ids.accessor(); job_buffer_.resize(num_queries * partition_ids.size(1)); - vector> per_worker_job_ids(num_workers_); for (int q = 0; q < num_queries; q++) { for (int64_t p = 0; p < partition_ids.size(1); p++) { int64_t pid = partition_ids_accessor[q][p]; @@ -454,20 +453,9 @@ shared_ptr QueryCoordinator::worker_scan( } size_t jid = next_job_id_.fetch_add(1, std::memory_order_acq_rel); job_buffer_[jid] = job; - per_worker_job_ids[core_id].push_back(jid); -// core_resources_[core_id].job_queue.enqueue((int64_t) jid); + core_resources_[core_id].job_queue.enqueue((int64_t) jid); } } - for (int i = 0; i < num_workers_; i++) { - auto &ids = per_worker_job_ids[i]; - core_resources_[i].job_queue.enqueue_bulk( - ids.data(), - ids.size() - ); - } -// for (int i = 0; i < num_workers_; i++) { -// core_resources_[i].job_queue.enqueue_bulk(per_worker_job_ids[i].begin(), per_worker_job_ids[i].size()); -// } } end_time = high_resolution_clock::now(); timing_info->job_enqueue_time_ns = duration_cast(end_time - start_time).count(); From a00e2af9ad2ef26e6a7b2180c12fce8b5297650f Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 12:38:39 -0500 Subject: [PATCH 118/323] minimize job enqueing time --- src/cpp/src/query_coordinator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 6660bba8..7d1244b0 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -110,7 +110,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { auto job_wait_start = std::chrono::high_resolution_clock::now(); int64_t job_id; while (!res.job_queue.try_dequeue(job_id)) { - std::this_thread::yield(); + std::this_thread::sleep_for(std::chrono::microseconds(5)); } auto job_wait_end = std::chrono::high_resolution_clock::now(); From 86c22781dfd04548864796cfb02ee5423c358994 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 12:43:44 -0500 Subject: [PATCH 119/323] minimize job enqueing time --- src/cpp/include/atomicops.h | 772 ++++++++++++++++++++++ src/cpp/include/query_coordinator.h | 5 +- src/cpp/include/readerwritequeue.h | 979 ++++++++++++++++++++++++++++ src/cpp/src/query_coordinator.cpp | 9 +- 4 files changed, 1759 insertions(+), 6 deletions(-) create mode 100644 src/cpp/include/atomicops.h create mode 100644 src/cpp/include/readerwritequeue.h diff --git a/src/cpp/include/atomicops.h b/src/cpp/include/atomicops.h new file mode 100644 index 00000000..1832dee8 --- /dev/null +++ b/src/cpp/include/atomicops.h @@ -0,0 +1,772 @@ +// ©2013-2016 Cameron Desrochers. +// Distributed under the simplified BSD license (see the license file that +// should have come with this header). +// Uses Jeff Preshing's semaphore implementation (under the terms of its +// separate zlib license, embedded below). + +#pragma once + +// Provides portable (VC++2010+, Intel ICC 13, GCC 4.7+, and anything C++11 compliant) implementation +// of low-level memory barriers, plus a few semi-portable utility macros (for inlining and alignment). +// Also has a basic atomic type (limited to hardware-supported atomics with no memory ordering guarantees). +// Uses the AE_* prefix for macros (historical reasons), and the "moodycamel" namespace for symbols. + +#include +#include +#include +#include +#include +#include + +// Platform detection +#if defined(__INTEL_COMPILER) +#define AE_ICC +#elif defined(_MSC_VER) +#define AE_VCPP +#elif defined(__GNUC__) +#define AE_GCC +#endif + +#if defined(_M_IA64) || defined(__ia64__) +#define AE_ARCH_IA64 +#elif defined(_WIN64) || defined(__amd64__) || defined(_M_X64) || defined(__x86_64__) +#define AE_ARCH_X64 +#elif defined(_M_IX86) || defined(__i386__) +#define AE_ARCH_X86 +#elif defined(_M_PPC) || defined(__powerpc__) +#define AE_ARCH_PPC +#else +#define AE_ARCH_UNKNOWN +#endif + + +// AE_UNUSED +#define AE_UNUSED(x) ((void)x) + +// AE_NO_TSAN/AE_TSAN_ANNOTATE_* +// For GCC +#if defined(__SANITIZE_THREAD__) +#define AE_TSAN_IS_ENABLED +#endif +// For clang +#if defined(__has_feature) +#if __has_feature(thread_sanitizer) && !defined(AE_TSAN_IS_ENABLED) +#define AE_TSAN_IS_ENABLED +#endif +#endif + +#ifdef AE_TSAN_IS_ENABLED +#if __cplusplus >= 201703L // inline variables require C++17 +namespace moodycamel { inline int ae_tsan_global; } +#define AE_TSAN_ANNOTATE_RELEASE() AnnotateHappensBefore(__FILE__, __LINE__, (void *)(&::moodycamel::ae_tsan_global)) +#define AE_TSAN_ANNOTATE_ACQUIRE() AnnotateHappensAfter(__FILE__, __LINE__, (void *)(&::moodycamel::ae_tsan_global)) +extern "C" void AnnotateHappensBefore(const char*, int, void*); +extern "C" void AnnotateHappensAfter(const char*, int, void*); +#else // when we can't work with tsan, attempt to disable its warnings +#define AE_NO_TSAN __attribute__((no_sanitize("thread"))) +#endif +#endif + +#ifndef AE_NO_TSAN +#define AE_NO_TSAN +#endif + +#ifndef AE_TSAN_ANNOTATE_RELEASE +#define AE_TSAN_ANNOTATE_RELEASE() +#define AE_TSAN_ANNOTATE_ACQUIRE() +#endif + + +// AE_FORCEINLINE +#if defined(AE_VCPP) || defined(AE_ICC) +#define AE_FORCEINLINE __forceinline +#elif defined(AE_GCC) +//#define AE_FORCEINLINE __attribute__((always_inline)) +#define AE_FORCEINLINE inline +#else +#define AE_FORCEINLINE inline +#endif + + +// AE_ALIGN +#if defined(AE_VCPP) || defined(AE_ICC) +#define AE_ALIGN(x) __declspec(align(x)) +#elif defined(AE_GCC) +#define AE_ALIGN(x) __attribute__((aligned(x))) +#else +// Assume GCC compliant syntax... +#define AE_ALIGN(x) __attribute__((aligned(x))) +#endif + + +// Portable atomic fences implemented below: + +namespace moodycamel { + + enum memory_order { + memory_order_relaxed, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst, + + // memory_order_sync: Forces a full sync: + // #LoadLoad, #LoadStore, #StoreStore, and most significantly, #StoreLoad + memory_order_sync = memory_order_seq_cst + }; + +} // end namespace moodycamel + +#if (defined(AE_VCPP) && (_MSC_VER < 1700 || defined(__cplusplus_cli))) || (defined(AE_ICC) && __INTEL_COMPILER < 1600) +// VS2010 and ICC13 don't support std::atomic_*_fence, implement our own fences + +#include + +#if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) +#define AeFullSync _mm_mfence +#define AeLiteSync _mm_mfence +#elif defined(AE_ARCH_IA64) +#define AeFullSync __mf +#define AeLiteSync __mf +#elif defined(AE_ARCH_PPC) +#include +#define AeFullSync __sync +#define AeLiteSync __lwsync +#endif + + +#ifdef AE_VCPP +#pragma warning(push) +#pragma warning(disable: 4365) // Disable erroneous 'conversion from long to unsigned int, signed/unsigned mismatch' error when using `assert` +#ifdef __cplusplus_cli +#pragma managed(push, off) +#endif +#endif + +namespace moodycamel { + +AE_FORCEINLINE void compiler_fence(memory_order order) AE_NO_TSAN +{ + switch (order) { + case memory_order_relaxed: break; + case memory_order_acquire: _ReadBarrier(); break; + case memory_order_release: _WriteBarrier(); break; + case memory_order_acq_rel: _ReadWriteBarrier(); break; + case memory_order_seq_cst: _ReadWriteBarrier(); break; + default: assert(false); + } +} + +// x86/x64 have a strong memory model -- all loads and stores have +// acquire and release semantics automatically (so only need compiler +// barriers for those). +#if defined(AE_ARCH_X86) || defined(AE_ARCH_X64) +AE_FORCEINLINE void fence(memory_order order) AE_NO_TSAN +{ + switch (order) { + case memory_order_relaxed: break; + case memory_order_acquire: _ReadBarrier(); break; + case memory_order_release: _WriteBarrier(); break; + case memory_order_acq_rel: _ReadWriteBarrier(); break; + case memory_order_seq_cst: + _ReadWriteBarrier(); + AeFullSync(); + _ReadWriteBarrier(); + break; + default: assert(false); + } +} +#else +AE_FORCEINLINE void fence(memory_order order) AE_NO_TSAN +{ + // Non-specialized arch, use heavier memory barriers everywhere just in case :-( + switch (order) { + case memory_order_relaxed: + break; + case memory_order_acquire: + _ReadBarrier(); + AeLiteSync(); + _ReadBarrier(); + break; + case memory_order_release: + _WriteBarrier(); + AeLiteSync(); + _WriteBarrier(); + break; + case memory_order_acq_rel: + _ReadWriteBarrier(); + AeLiteSync(); + _ReadWriteBarrier(); + break; + case memory_order_seq_cst: + _ReadWriteBarrier(); + AeFullSync(); + _ReadWriteBarrier(); + break; + default: assert(false); + } +} +#endif +} // end namespace moodycamel +#else +// Use standard library of atomics +#include + +namespace moodycamel { + + AE_FORCEINLINE void compiler_fence(memory_order order) AE_NO_TSAN + { + switch (order) { + case memory_order_relaxed: break; + case memory_order_acquire: std::atomic_signal_fence(std::memory_order_acquire); break; + case memory_order_release: std::atomic_signal_fence(std::memory_order_release); break; + case memory_order_acq_rel: std::atomic_signal_fence(std::memory_order_acq_rel); break; + case memory_order_seq_cst: std::atomic_signal_fence(std::memory_order_seq_cst); break; + default: assert(false); + } + } + + AE_FORCEINLINE void fence(memory_order order) AE_NO_TSAN + { + switch (order) { + case memory_order_relaxed: break; + case memory_order_acquire: AE_TSAN_ANNOTATE_ACQUIRE(); std::atomic_thread_fence(std::memory_order_acquire); break; + case memory_order_release: AE_TSAN_ANNOTATE_RELEASE(); std::atomic_thread_fence(std::memory_order_release); break; + case memory_order_acq_rel: AE_TSAN_ANNOTATE_ACQUIRE(); AE_TSAN_ANNOTATE_RELEASE(); std::atomic_thread_fence(std::memory_order_acq_rel); break; + case memory_order_seq_cst: AE_TSAN_ANNOTATE_ACQUIRE(); AE_TSAN_ANNOTATE_RELEASE(); std::atomic_thread_fence(std::memory_order_seq_cst); break; + default: assert(false); + } + } + +} // end namespace moodycamel + +#endif + + +#if !defined(AE_VCPP) || (_MSC_VER >= 1700 && !defined(__cplusplus_cli)) +#define AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC +#endif + +#ifdef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC +#include +#endif +#include + +// WARNING: *NOT* A REPLACEMENT FOR std::atomic. READ CAREFULLY: +// Provides basic support for atomic variables -- no memory ordering guarantees are provided. +// The guarantee of atomicity is only made for types that already have atomic load and store guarantees +// at the hardware level -- on most platforms this generally means aligned pointers and integers (only). +namespace moodycamel { + template + class weak_atomic + { + public: + AE_NO_TSAN weak_atomic() : value() { } +#ifdef AE_VCPP + #pragma warning(push) +#pragma warning(disable: 4100) // Get rid of (erroneous) 'unreferenced formal parameter' warning +#endif + template AE_NO_TSAN weak_atomic(U&& x) : value(std::forward(x)) { } +#ifdef __cplusplus_cli + // Work around bug with universal reference/nullptr combination that only appears when /clr is on + AE_NO_TSAN weak_atomic(nullptr_t) : value(nullptr) { } +#endif + AE_NO_TSAN weak_atomic(weak_atomic const& other) : value(other.load()) { } + AE_NO_TSAN weak_atomic(weak_atomic&& other) : value(std::move(other.load())) { } +#ifdef AE_VCPP +#pragma warning(pop) +#endif + + AE_FORCEINLINE operator T() const AE_NO_TSAN { return load(); } + + +#ifndef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC + template AE_FORCEINLINE weak_atomic const& operator=(U&& x) AE_NO_TSAN { value = std::forward(x); return *this; } + AE_FORCEINLINE weak_atomic const& operator=(weak_atomic const& other) AE_NO_TSAN { value = other.value; return *this; } + + AE_FORCEINLINE T load() const AE_NO_TSAN { return value; } + + AE_FORCEINLINE T fetch_add_acquire(T increment) AE_NO_TSAN + { +#if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) + if (sizeof(T) == 4) return _InterlockedExchangeAdd((long volatile*)&value, (long)increment); +#if defined(_M_AMD64) + else if (sizeof(T) == 8) return _InterlockedExchangeAdd64((long long volatile*)&value, (long long)increment); +#endif +#else +#error Unsupported platform +#endif + assert(false && "T must be either a 32 or 64 bit type"); + return value; + } + + AE_FORCEINLINE T fetch_add_release(T increment) AE_NO_TSAN + { +#if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) + if (sizeof(T) == 4) return _InterlockedExchangeAdd((long volatile*)&value, (long)increment); +#if defined(_M_AMD64) + else if (sizeof(T) == 8) return _InterlockedExchangeAdd64((long long volatile*)&value, (long long)increment); +#endif +#else +#error Unsupported platform +#endif + assert(false && "T must be either a 32 or 64 bit type"); + return value; + } +#else + template + AE_FORCEINLINE weak_atomic const& operator=(U&& x) AE_NO_TSAN + { + value.store(std::forward(x), std::memory_order_relaxed); + return *this; + } + + AE_FORCEINLINE weak_atomic const& operator=(weak_atomic const& other) AE_NO_TSAN + { + value.store(other.value.load(std::memory_order_relaxed), std::memory_order_relaxed); + return *this; + } + + AE_FORCEINLINE T load() const AE_NO_TSAN { return value.load(std::memory_order_relaxed); } + + AE_FORCEINLINE T fetch_add_acquire(T increment) AE_NO_TSAN + { + return value.fetch_add(increment, std::memory_order_acquire); + } + + AE_FORCEINLINE T fetch_add_release(T increment) AE_NO_TSAN + { + return value.fetch_add(increment, std::memory_order_release); + } +#endif + + + private: +#ifndef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC + // No std::atomic support, but still need to circumvent compiler optimizations. + // `volatile` will make memory access slow, but is guaranteed to be reliable. + volatile T value; +#else + std::atomic value; +#endif + }; + +} // end namespace moodycamel + + + +// Portable single-producer, single-consumer semaphore below: + +#if defined(_WIN32) +// Avoid including windows.h in a header; we only need a handful of +// items, so we'll redeclare them here (this is relatively safe since +// the API generally has to remain stable between Windows versions). +// I know this is an ugly hack but it still beats polluting the global +// namespace with thousands of generic names or adding a .cpp for nothing. +extern "C" { + struct _SECURITY_ATTRIBUTES; + __declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES* lpSemaphoreAttributes, long lInitialCount, long lMaximumCount, const wchar_t* lpName); + __declspec(dllimport) int __stdcall CloseHandle(void* hObject); + __declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void* hHandle, unsigned long dwMilliseconds); + __declspec(dllimport) int __stdcall ReleaseSemaphore(void* hSemaphore, long lReleaseCount, long* lpPreviousCount); +} +#elif defined(__MACH__) +#include +#elif defined(__unix__) +#include +#elif defined(FREERTOS) +#include +#include +#include +#endif + +namespace moodycamel +{ + // Code in the spsc_sema namespace below is an adaptation of Jeff Preshing's + // portable + lightweight semaphore implementations, originally from + // https://github.com/preshing/cpp11-on-multicore/blob/master/common/sema.h + // LICENSE: + // Copyright (c) 2015 Jeff Preshing + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgement in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + namespace spsc_sema + { +#if defined(_WIN32) + class Semaphore + { + private: + void* m_hSema; + + Semaphore(const Semaphore& other); + Semaphore& operator=(const Semaphore& other); + + public: + AE_NO_TSAN Semaphore(int initialCount = 0) : m_hSema() + { + assert(initialCount >= 0); + const long maxLong = 0x7fffffff; + m_hSema = CreateSemaphoreW(nullptr, initialCount, maxLong, nullptr); + assert(m_hSema); + } + + AE_NO_TSAN ~Semaphore() + { + CloseHandle(m_hSema); + } + + bool wait() AE_NO_TSAN + { + const unsigned long infinite = 0xffffffff; + return WaitForSingleObject(m_hSema, infinite) == 0; + } + + bool try_wait() AE_NO_TSAN + { + return WaitForSingleObject(m_hSema, 0) == 0; + } + + bool timed_wait(std::uint64_t usecs) AE_NO_TSAN + { + return WaitForSingleObject(m_hSema, (unsigned long)(usecs / 1000)) == 0; + } + + void signal(int count = 1) AE_NO_TSAN + { + while (!ReleaseSemaphore(m_hSema, count, nullptr)); + } + }; +#elif defined(__MACH__) + //--------------------------------------------------------- + // Semaphore (Apple iOS and OSX) + // Can't use POSIX semaphores due to http://lists.apple.com/archives/darwin-kernel/2009/Apr/msg00010.html + //--------------------------------------------------------- + class Semaphore + { + private: + semaphore_t m_sema; + + Semaphore(const Semaphore& other); + Semaphore& operator=(const Semaphore& other); + + public: + AE_NO_TSAN Semaphore(int initialCount = 0) : m_sema() + { + assert(initialCount >= 0); + kern_return_t rc = semaphore_create(mach_task_self(), &m_sema, SYNC_POLICY_FIFO, initialCount); + assert(rc == KERN_SUCCESS); + AE_UNUSED(rc); + } + + AE_NO_TSAN ~Semaphore() + { + semaphore_destroy(mach_task_self(), m_sema); + } + + bool wait() AE_NO_TSAN + { + return semaphore_wait(m_sema) == KERN_SUCCESS; + } + + bool try_wait() AE_NO_TSAN + { + return timed_wait(0); + } + + bool timed_wait(std::uint64_t timeout_usecs) AE_NO_TSAN + { + mach_timespec_t ts; + ts.tv_sec = static_cast(timeout_usecs / 1000000); + ts.tv_nsec = static_cast((timeout_usecs % 1000000) * 1000); + + // added in OSX 10.10: https://developer.apple.com/library/prerelease/mac/documentation/General/Reference/APIDiffsMacOSX10_10SeedDiff/modules/Darwin.html + kern_return_t rc = semaphore_timedwait(m_sema, ts); + return rc == KERN_SUCCESS; + } + + void signal() AE_NO_TSAN + { + while (semaphore_signal(m_sema) != KERN_SUCCESS); + } + + void signal(int count) AE_NO_TSAN + { + while (count-- > 0) + { + while (semaphore_signal(m_sema) != KERN_SUCCESS); + } + } + }; +#elif defined(__unix__) + //--------------------------------------------------------- + // Semaphore (POSIX, Linux) + //--------------------------------------------------------- + class Semaphore + { + private: + sem_t m_sema; + + Semaphore(const Semaphore& other); + Semaphore& operator=(const Semaphore& other); + + public: + AE_NO_TSAN Semaphore(int initialCount = 0) : m_sema() + { + assert(initialCount >= 0); + int rc = sem_init(&m_sema, 0, static_cast(initialCount)); + assert(rc == 0); + AE_UNUSED(rc); + } + + AE_NO_TSAN ~Semaphore() + { + sem_destroy(&m_sema); + } + + bool wait() AE_NO_TSAN + { + // http://stackoverflow.com/questions/2013181/gdb-causes-sem-wait-to-fail-with-eintr-error + int rc; + do + { + rc = sem_wait(&m_sema); + } + while (rc == -1 && errno == EINTR); + return rc == 0; + } + + bool try_wait() AE_NO_TSAN + { + int rc; + do { + rc = sem_trywait(&m_sema); + } while (rc == -1 && errno == EINTR); + return rc == 0; + } + + bool timed_wait(std::uint64_t usecs) AE_NO_TSAN + { + struct timespec ts; + const int usecs_in_1_sec = 1000000; + const int nsecs_in_1_sec = 1000000000; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += static_cast(usecs / usecs_in_1_sec); + ts.tv_nsec += static_cast(usecs % usecs_in_1_sec) * 1000; + // sem_timedwait bombs if you have more than 1e9 in tv_nsec + // so we have to clean things up before passing it in + if (ts.tv_nsec >= nsecs_in_1_sec) { + ts.tv_nsec -= nsecs_in_1_sec; + ++ts.tv_sec; + } + + int rc; + do { + rc = sem_timedwait(&m_sema, &ts); + } while (rc == -1 && errno == EINTR); + return rc == 0; + } + + void signal() AE_NO_TSAN + { + while (sem_post(&m_sema) == -1); + } + + void signal(int count) AE_NO_TSAN + { + while (count-- > 0) + { + while (sem_post(&m_sema) == -1); + } + } + }; +#elif defined(FREERTOS) + //--------------------------------------------------------- + // Semaphore (FreeRTOS) + //--------------------------------------------------------- + class Semaphore + { + private: + SemaphoreHandle_t m_sema; + + Semaphore(const Semaphore& other); + Semaphore& operator=(const Semaphore& other); + + public: + AE_NO_TSAN Semaphore(int initialCount = 0) : m_sema() + { + assert(initialCount >= 0); + m_sema = xSemaphoreCreateCounting(static_cast(~0ull), static_cast(initialCount)); + assert(m_sema); + } + + AE_NO_TSAN ~Semaphore() + { + vSemaphoreDelete(m_sema); + } + + bool wait() AE_NO_TSAN + { + return xSemaphoreTake(m_sema, portMAX_DELAY) == pdTRUE; + } + + bool try_wait() AE_NO_TSAN + { + // Note: In an ISR context, if this causes a task to unblock, + // the caller won't know about it + if (xPortIsInsideInterrupt()) + return xSemaphoreTakeFromISR(m_sema, NULL) == pdTRUE; + return xSemaphoreTake(m_sema, 0) == pdTRUE; + } + + bool timed_wait(std::uint64_t usecs) AE_NO_TSAN + { + std::uint64_t msecs = usecs / 1000; + TickType_t ticks = static_cast(msecs / portTICK_PERIOD_MS); + if (ticks == 0) + return try_wait(); + return xSemaphoreTake(m_sema, ticks) == pdTRUE; + } + + void signal() AE_NO_TSAN + { + // Note: In an ISR context, if this causes a task to unblock, + // the caller won't know about it + BaseType_t rc; + if (xPortIsInsideInterrupt()) + rc = xSemaphoreGiveFromISR(m_sema, NULL); + else + rc = xSemaphoreGive(m_sema); + assert(rc == pdTRUE); + AE_UNUSED(rc); + } + + void signal(int count) AE_NO_TSAN + { + while (count-- > 0) + signal(); + } + }; +#else +#error Unsupported platform! (No semaphore wrapper available) +#endif + + //--------------------------------------------------------- + // LightweightSemaphore + //--------------------------------------------------------- + class LightweightSemaphore + { + public: + typedef std::make_signed::type ssize_t; + + private: + weak_atomic m_count; + Semaphore m_sema; + + bool waitWithPartialSpinning(std::int64_t timeout_usecs = -1) AE_NO_TSAN + { + ssize_t oldCount; + // Is there a better way to set the initial spin count? + // If we lower it to 1000, testBenaphore becomes 15x slower on my Core i7-5930K Windows PC, + // as threads start hitting the kernel semaphore. + int spin = 1024; + while (--spin >= 0) + { + if (m_count.load() > 0) + { + m_count.fetch_add_acquire(-1); + return true; + } + compiler_fence(memory_order_acquire); // Prevent the compiler from collapsing the loop. + } + oldCount = m_count.fetch_add_acquire(-1); + if (oldCount > 0) + return true; + if (timeout_usecs < 0) + { + if (m_sema.wait()) + return true; + } + if (timeout_usecs > 0 && m_sema.timed_wait(static_cast(timeout_usecs))) + return true; + // At this point, we've timed out waiting for the semaphore, but the + // count is still decremented indicating we may still be waiting on + // it. So we have to re-adjust the count, but only if the semaphore + // wasn't signaled enough times for us too since then. If it was, we + // need to release the semaphore too. + while (true) + { + oldCount = m_count.fetch_add_release(1); + if (oldCount < 0) + return false; // successfully restored things to the way they were + // Oh, the producer thread just signaled the semaphore after all. Try again: + oldCount = m_count.fetch_add_acquire(-1); + if (oldCount > 0 && m_sema.try_wait()) + return true; + } + } + + public: + AE_NO_TSAN LightweightSemaphore(ssize_t initialCount = 0) : m_count(initialCount), m_sema() + { + assert(initialCount >= 0); + } + + bool tryWait() AE_NO_TSAN + { + if (m_count.load() > 0) + { + m_count.fetch_add_acquire(-1); + return true; + } + return false; + } + + bool wait() AE_NO_TSAN + { + return tryWait() || waitWithPartialSpinning(); + } + + bool wait(std::int64_t timeout_usecs) AE_NO_TSAN + { + return tryWait() || waitWithPartialSpinning(timeout_usecs); + } + + void signal(ssize_t count = 1) AE_NO_TSAN + { + assert(count >= 0); + ssize_t oldCount = m_count.fetch_add_release(count); + assert(oldCount >= -1); + if (oldCount < 0) + { + m_sema.signal(1); + } + } + + std::size_t availableApprox() const AE_NO_TSAN + { + ssize_t count = m_count.load(); + return count > 0 ? static_cast(count) : 0; + } + }; + } // end namespace spsc_sema +} // end namespace moodycamel + +#if defined(AE_VCPP) && (_MSC_VER < 1700 || defined(__cplusplus_cli)) +#pragma warning(pop) +#ifdef __cplusplus_cli +#pragma managed(pop) +#endif +#endif \ No newline at end of file diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 6d015dab..23baabab 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -10,7 +10,8 @@ #include #include #include -#include +//#include +#include class QuakeIndex; class PartitionManager; @@ -53,7 +54,7 @@ class QueryCoordinator { int core_id; ///< Logical identifier of the core. vector> topk_buffer_pool; ///< Preallocated Top‑K buffers. vector local_query_buffer; ///< Local aggregator for query results. - moodycamel::ConcurrentQueue job_queue; ///< Job queue for scan jobs. + moodycamel::BlockingReaderWriterQueue job_queue; ///< Job queue for scan jobs. }; vector core_resources_; ///< Per‑core resources for worker threads. diff --git a/src/cpp/include/readerwritequeue.h b/src/cpp/include/readerwritequeue.h new file mode 100644 index 00000000..098d47cf --- /dev/null +++ b/src/cpp/include/readerwritequeue.h @@ -0,0 +1,979 @@ +// ©2013-2020 Cameron Desrochers. +// Distributed under the simplified BSD license (see the license file that +// should have come with this header). + +#pragma once + +#include "atomicops.h" +#include +#include +#include +#include +#include +#include +#include +#include // For malloc/free/abort & size_t +#include +#if __cplusplus > 199711L || _MSC_VER >= 1700 // C++11 or VS2012 +#include +#endif + + +// A lock-free queue for a single-consumer, single-producer architecture. +// The queue is also wait-free in the common path (except if more memory +// needs to be allocated, in which case malloc is called). +// Allocates memory sparingly, and only once if the original maximum size +// estimate is never exceeded. +// Tested on x86/x64 processors, but semantics should be correct for all +// architectures (given the right implementations in atomicops.h), provided +// that aligned integer and pointer accesses are naturally atomic. +// Note that there should only be one consumer thread and producer thread; +// Switching roles of the threads, or using multiple consecutive threads for +// one role, is not safe unless properly synchronized. +// Using the queue exclusively from one thread is fine, though a bit silly. + +#ifndef MOODYCAMEL_CACHE_LINE_SIZE +#define MOODYCAMEL_CACHE_LINE_SIZE 64 +#endif + +#ifndef MOODYCAMEL_EXCEPTIONS_ENABLED +#if (defined(_MSC_VER) && defined(_CPPUNWIND)) || (defined(__GNUC__) && defined(__EXCEPTIONS)) || (!defined(_MSC_VER) && !defined(__GNUC__)) +#define MOODYCAMEL_EXCEPTIONS_ENABLED +#endif +#endif + +#ifndef MOODYCAMEL_HAS_EMPLACE +#if !defined(_MSC_VER) || _MSC_VER >= 1800 // variadic templates: either a non-MS compiler or VS >= 2013 +#define MOODYCAMEL_HAS_EMPLACE 1 +#endif +#endif + +#ifndef MOODYCAMEL_MAYBE_ALIGN_TO_CACHELINE +#if defined (__APPLE__) && defined (__MACH__) && __cplusplus >= 201703L +// This is required to find out what deployment target we are using +#include +#if !defined(MAC_OS_X_VERSION_MIN_REQUIRED) || !defined(MAC_OS_X_VERSION_10_14) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_14 +// C++17 new(size_t, align_val_t) is not backwards-compatible with older versions of macOS, so we can't support over-alignment in this case +#define MOODYCAMEL_MAYBE_ALIGN_TO_CACHELINE +#endif +#endif +#endif + +#ifndef MOODYCAMEL_MAYBE_ALIGN_TO_CACHELINE +#define MOODYCAMEL_MAYBE_ALIGN_TO_CACHELINE AE_ALIGN(MOODYCAMEL_CACHE_LINE_SIZE) +#endif + +#ifdef AE_VCPP +#pragma warning(push) +#pragma warning(disable: 4324) // structure was padded due to __declspec(align()) +#pragma warning(disable: 4820) // padding was added +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace moodycamel { + + template + class MOODYCAMEL_MAYBE_ALIGN_TO_CACHELINE ReaderWriterQueue +{ + // Design: Based on a queue-of-queues. The low-level queues are just + // circular buffers with front and tail indices indicating where the + // next element to dequeue is and where the next element can be enqueued, + // respectively. Each low-level queue is called a "block". Each block + // wastes exactly one element's worth of space to keep the design simple + // (if front == tail then the queue is empty, and can't be full). + // The high-level queue is a circular linked list of blocks; again there + // is a front and tail, but this time they are pointers to the blocks. + // The front block is where the next element to be dequeued is, provided + // the block is not empty. The back block is where elements are to be + // enqueued, provided the block is not full. + // The producer thread owns all the tail indices/pointers. The consumer + // thread owns all the front indices/pointers. Both threads read each + // other's variables, but only the owning thread updates them. E.g. After + // the consumer reads the producer's tail, the tail may change before the + // consumer is done dequeuing an object, but the consumer knows the tail + // will never go backwards, only forwards. + // If there is no room to enqueue an object, an additional block (of + // equal size to the last block) is added. Blocks are never removed. + + public: + typedef T value_type; + + // Constructs a queue that can hold at least `size` elements without further + // allocations. If more than MAX_BLOCK_SIZE elements are requested, + // then several blocks of MAX_BLOCK_SIZE each are reserved (including + // at least one extra buffer block). + AE_NO_TSAN explicit ReaderWriterQueue(size_t size = 15) +#ifndef NDEBUG + : enqueuing(false) + ,dequeuing(false) +#endif +{ + assert(MAX_BLOCK_SIZE == ceilToPow2(MAX_BLOCK_SIZE) && "MAX_BLOCK_SIZE must be a power of 2"); + assert(MAX_BLOCK_SIZE >= 2 && "MAX_BLOCK_SIZE must be at least 2"); + + Block* firstBlock = nullptr; + + largestBlockSize = ceilToPow2(size + 1); // We need a spare slot to fit size elements in the block + if (largestBlockSize > MAX_BLOCK_SIZE * 2) { + // We need a spare block in case the producer is writing to a different block the consumer is reading from, and + // wants to enqueue the maximum number of elements. We also need a spare element in each block to avoid the ambiguity + // between front == tail meaning "empty" and "full". + // So the effective number of slots that are guaranteed to be usable at any time is the block size - 1 times the + // number of blocks - 1. Solving for size and applying a ceiling to the division gives us (after simplifying): + size_t initialBlockCount = (size + MAX_BLOCK_SIZE * 2 - 3) / (MAX_BLOCK_SIZE - 1); + largestBlockSize = MAX_BLOCK_SIZE; + Block* lastBlock = nullptr; + for (size_t i = 0; i != initialBlockCount; ++i) { + auto block = make_block(largestBlockSize); + if (block == nullptr) { +#ifdef MOODYCAMEL_EXCEPTIONS_ENABLED + throw std::bad_alloc(); +#else + abort(); +#endif +} +if (firstBlock == nullptr) { +firstBlock = block; +} +else { +lastBlock->next = block; +} +lastBlock = block; +block->next = firstBlock; +} +} +else { +firstBlock = make_block(largestBlockSize); +if (firstBlock == nullptr) { +#ifdef MOODYCAMEL_EXCEPTIONS_ENABLED +throw std::bad_alloc(); +#else +abort(); +#endif +} +firstBlock->next = firstBlock; +} +frontBlock = firstBlock; +tailBlock = firstBlock; + +// Make sure the reader/writer threads will have the initialized memory setup above: +fence(memory_order_sync); +} + +// Note: The queue should not be accessed concurrently while it's +// being moved. It's up to the user to synchronize this. +AE_NO_TSAN ReaderWriterQueue(ReaderWriterQueue&& other) +: frontBlock(other.frontBlock.load()), +tailBlock(other.tailBlock.load()), +largestBlockSize(other.largestBlockSize) +#ifndef NDEBUG +,enqueuing(false) +,dequeuing(false) +#endif +{ +other.largestBlockSize = 32; +Block* b = other.make_block(other.largestBlockSize); +if (b == nullptr) { +#ifdef MOODYCAMEL_EXCEPTIONS_ENABLED +throw std::bad_alloc(); +#else +abort(); +#endif +} +b->next = b; +other.frontBlock = b; +other.tailBlock = b; +} + +// Note: The queue should not be accessed concurrently while it's +// being moved. It's up to the user to synchronize this. +ReaderWriterQueue& operator=(ReaderWriterQueue&& other) AE_NO_TSAN +{ +Block* b = frontBlock.load(); +frontBlock = other.frontBlock.load(); +other.frontBlock = b; +b = tailBlock.load(); +tailBlock = other.tailBlock.load(); +other.tailBlock = b; +std::swap(largestBlockSize, other.largestBlockSize); +return *this; +} + +// Note: The queue should not be accessed concurrently while it's +// being deleted. It's up to the user to synchronize this. +AE_NO_TSAN ~ReaderWriterQueue() +{ + // Make sure we get the latest version of all variables from other CPUs: + fence(memory_order_sync); + + // Destroy any remaining objects in queue and free memory + Block* frontBlock_ = frontBlock; + Block* block = frontBlock_; + do { + Block* nextBlock = block->next; + size_t blockFront = block->front; + size_t blockTail = block->tail; + + for (size_t i = blockFront; i != blockTail; i = (i + 1) & block->sizeMask) { + auto element = reinterpret_cast(block->data + i * sizeof(T)); + element->~T(); + (void)element; + } + + auto rawBlock = block->rawThis; + block->~Block(); + std::free(rawBlock); + block = nextBlock; + } while (block != frontBlock_); +} + + +// Enqueues a copy of element if there is room in the queue. +// Returns true if the element was enqueued, false otherwise. +// Does not allocate memory. +AE_FORCEINLINE bool try_enqueue(T const& element) AE_NO_TSAN +{ +return inner_enqueue(element); +} + +// Enqueues a moved copy of element if there is room in the queue. +// Returns true if the element was enqueued, false otherwise. +// Does not allocate memory. +AE_FORCEINLINE bool try_enqueue(T&& element) AE_NO_TSAN +{ +return inner_enqueue(std::forward(element)); +} + +#if MOODYCAMEL_HAS_EMPLACE +// Like try_enqueue() but with emplace semantics (i.e. construct-in-place). +template +AE_FORCEINLINE bool try_emplace(Args&&... args) AE_NO_TSAN +{ +return inner_enqueue(std::forward(args)...); +} +#endif + +// Enqueues a copy of element on the queue. +// Allocates an additional block of memory if needed. +// Only fails (returns false) if memory allocation fails. +AE_FORCEINLINE bool enqueue(T const& element) AE_NO_TSAN +{ +return inner_enqueue(element); +} + +// Enqueues a moved copy of element on the queue. +// Allocates an additional block of memory if needed. +// Only fails (returns false) if memory allocation fails. +AE_FORCEINLINE bool enqueue(T&& element) AE_NO_TSAN +{ +return inner_enqueue(std::forward(element)); +} + +#if MOODYCAMEL_HAS_EMPLACE +// Like enqueue() but with emplace semantics (i.e. construct-in-place). +template +AE_FORCEINLINE bool emplace(Args&&... args) AE_NO_TSAN +{ +return inner_enqueue(std::forward(args)...); +} +#endif + +// Attempts to dequeue an element; if the queue is empty, +// returns false instead. If the queue has at least one element, +// moves front to result using operator=, then returns true. +template +bool try_dequeue(U& result) AE_NO_TSAN +{ +#ifndef NDEBUG +ReentrantGuard guard(this->dequeuing); +#endif + +// High-level pseudocode: +// Remember where the tail block is +// If the front block has an element in it, dequeue it +// Else +// If front block was the tail block when we entered the function, return false +// Else advance to next block and dequeue the item there + +// Note that we have to use the value of the tail block from before we check if the front +// block is full or not, in case the front block is empty and then, before we check if the +// tail block is at the front block or not, the producer fills up the front block *and +// moves on*, which would make us skip a filled block. Seems unlikely, but was consistently +// reproducible in practice. +// In order to avoid overhead in the common case, though, we do a double-checked pattern +// where we have the fast path if the front block is not empty, then read the tail block, +// then re-read the front block and check if it's not empty again, then check if the tail +// block has advanced. + +Block* frontBlock_ = frontBlock.load(); +size_t blockTail = frontBlock_->localTail; +size_t blockFront = frontBlock_->front.load(); + +if (blockFront != blockTail || blockFront != (frontBlock_->localTail = frontBlock_->tail.load())) { +fence(memory_order_acquire); + +non_empty_front_block: +// Front block not empty, dequeue from here +auto element = reinterpret_cast(frontBlock_->data + blockFront * sizeof(T)); +result = std::move(*element); +element->~T(); + +blockFront = (blockFront + 1) & frontBlock_->sizeMask; + +fence(memory_order_release); +frontBlock_->front = blockFront; +} +else if (frontBlock_ != tailBlock.load()) { +fence(memory_order_acquire); + +frontBlock_ = frontBlock.load(); +blockTail = frontBlock_->localTail = frontBlock_->tail.load(); +blockFront = frontBlock_->front.load(); +fence(memory_order_acquire); + +if (blockFront != blockTail) { +// Oh look, the front block isn't empty after all +goto non_empty_front_block; +} + +// Front block is empty but there's another block ahead, advance to it +Block* nextBlock = frontBlock_->next; +// Don't need an acquire fence here since next can only ever be set on the tailBlock, +// and we're not the tailBlock, and we did an acquire earlier after reading tailBlock which +// ensures next is up-to-date on this CPU in case we recently were at tailBlock. + +size_t nextBlockFront = nextBlock->front.load(); +size_t nextBlockTail = nextBlock->localTail = nextBlock->tail.load(); +fence(memory_order_acquire); + +// Since the tailBlock is only ever advanced after being written to, +// we know there's for sure an element to dequeue on it +assert(nextBlockFront != nextBlockTail); +AE_UNUSED(nextBlockTail); + +// We're done with this block, let the producer use it if it needs +fence(memory_order_release); // Expose possibly pending changes to frontBlock->front from last dequeue +frontBlock = frontBlock_ = nextBlock; + +compiler_fence(memory_order_release); // Not strictly needed + +auto element = reinterpret_cast(frontBlock_->data + nextBlockFront * sizeof(T)); + +result = std::move(*element); +element->~T(); + +nextBlockFront = (nextBlockFront + 1) & frontBlock_->sizeMask; + +fence(memory_order_release); +frontBlock_->front = nextBlockFront; +} +else { +// No elements in current block and no other block to advance to +return false; +} + +return true; +} + + +// Returns a pointer to the front element in the queue (the one that +// would be removed next by a call to `try_dequeue` or `pop`). If the +// queue appears empty at the time the method is called, nullptr is +// returned instead. +// Must be called only from the consumer thread. +T* peek() const AE_NO_TSAN +{ +#ifndef NDEBUG +ReentrantGuard guard(this->dequeuing); +#endif +// See try_dequeue() for reasoning + +Block* frontBlock_ = frontBlock.load(); +size_t blockTail = frontBlock_->localTail; +size_t blockFront = frontBlock_->front.load(); + +if (blockFront != blockTail || blockFront != (frontBlock_->localTail = frontBlock_->tail.load())) { +fence(memory_order_acquire); +non_empty_front_block: +return reinterpret_cast(frontBlock_->data + blockFront * sizeof(T)); +} +else if (frontBlock_ != tailBlock.load()) { +fence(memory_order_acquire); +frontBlock_ = frontBlock.load(); +blockTail = frontBlock_->localTail = frontBlock_->tail.load(); +blockFront = frontBlock_->front.load(); +fence(memory_order_acquire); + +if (blockFront != blockTail) { +goto non_empty_front_block; +} + +Block* nextBlock = frontBlock_->next; + +size_t nextBlockFront = nextBlock->front.load(); +fence(memory_order_acquire); + +assert(nextBlockFront != nextBlock->tail.load()); +return reinterpret_cast(nextBlock->data + nextBlockFront * sizeof(T)); +} + +return nullptr; +} + +// Removes the front element from the queue, if any, without returning it. +// Returns true on success, or false if the queue appeared empty at the time +// `pop` was called. +bool pop() AE_NO_TSAN +{ +#ifndef NDEBUG +ReentrantGuard guard(this->dequeuing); +#endif +// See try_dequeue() for reasoning + +Block* frontBlock_ = frontBlock.load(); +size_t blockTail = frontBlock_->localTail; +size_t blockFront = frontBlock_->front.load(); + +if (blockFront != blockTail || blockFront != (frontBlock_->localTail = frontBlock_->tail.load())) { +fence(memory_order_acquire); + +non_empty_front_block: +auto element = reinterpret_cast(frontBlock_->data + blockFront * sizeof(T)); +element->~T(); + +blockFront = (blockFront + 1) & frontBlock_->sizeMask; + +fence(memory_order_release); +frontBlock_->front = blockFront; +} +else if (frontBlock_ != tailBlock.load()) { +fence(memory_order_acquire); +frontBlock_ = frontBlock.load(); +blockTail = frontBlock_->localTail = frontBlock_->tail.load(); +blockFront = frontBlock_->front.load(); +fence(memory_order_acquire); + +if (blockFront != blockTail) { +goto non_empty_front_block; +} + +// Front block is empty but there's another block ahead, advance to it +Block* nextBlock = frontBlock_->next; + +size_t nextBlockFront = nextBlock->front.load(); +size_t nextBlockTail = nextBlock->localTail = nextBlock->tail.load(); +fence(memory_order_acquire); + +assert(nextBlockFront != nextBlockTail); +AE_UNUSED(nextBlockTail); + +fence(memory_order_release); +frontBlock = frontBlock_ = nextBlock; + +compiler_fence(memory_order_release); + +auto element = reinterpret_cast(frontBlock_->data + nextBlockFront * sizeof(T)); +element->~T(); + +nextBlockFront = (nextBlockFront + 1) & frontBlock_->sizeMask; + +fence(memory_order_release); +frontBlock_->front = nextBlockFront; +} +else { +// No elements in current block and no other block to advance to +return false; +} + +return true; +} + +// Returns the approximate number of items currently in the queue. +// Safe to call from both the producer and consumer threads. +inline size_t size_approx() const AE_NO_TSAN +{ +size_t result = 0; +Block* frontBlock_ = frontBlock.load(); +Block* block = frontBlock_; +do { +fence(memory_order_acquire); +size_t blockFront = block->front.load(); +size_t blockTail = block->tail.load(); +result += (blockTail - blockFront) & block->sizeMask; +block = block->next.load(); +} while (block != frontBlock_); +return result; +} + +// Returns the total number of items that could be enqueued without incurring +// an allocation when this queue is empty. +// Safe to call from both the producer and consumer threads. +// +// NOTE: The actual capacity during usage may be different depending on the consumer. +// If the consumer is removing elements concurrently, the producer cannot add to +// the block the consumer is removing from until it's completely empty, except in +// the case where the producer was writing to the same block the consumer was +// reading from the whole time. +inline size_t max_capacity() const { + size_t result = 0; + Block* frontBlock_ = frontBlock.load(); + Block* block = frontBlock_; + do { + fence(memory_order_acquire); + result += block->sizeMask; + block = block->next.load(); + } while (block != frontBlock_); + return result; +} + + +private: +enum AllocationMode { CanAlloc, CannotAlloc }; + +#if MOODYCAMEL_HAS_EMPLACE +template +bool inner_enqueue(Args&&... args) AE_NO_TSAN +#else +template + bool inner_enqueue(U&& element) AE_NO_TSAN +#endif +{ +#ifndef NDEBUG +ReentrantGuard guard(this->enqueuing); +#endif + +// High-level pseudocode (assuming we're allowed to alloc a new block): +// If room in tail block, add to tail +// Else check next block +// If next block is not the head block, enqueue on next block +// Else create a new block and enqueue there +// Advance tail to the block we just enqueued to + +Block* tailBlock_ = tailBlock.load(); +size_t blockFront = tailBlock_->localFront; +size_t blockTail = tailBlock_->tail.load(); + +size_t nextBlockTail = (blockTail + 1) & tailBlock_->sizeMask; +if (nextBlockTail != blockFront || nextBlockTail != (tailBlock_->localFront = tailBlock_->front.load())) { +fence(memory_order_acquire); +// This block has room for at least one more element +char* location = tailBlock_->data + blockTail * sizeof(T); +#if MOODYCAMEL_HAS_EMPLACE +new (location) T(std::forward(args)...); +#else +new (location) T(std::forward(element)); +#endif + +fence(memory_order_release); +tailBlock_->tail = nextBlockTail; +} +else { +fence(memory_order_acquire); +if (tailBlock_->next.load() != frontBlock) { +// Note that the reason we can't advance to the frontBlock and start adding new entries there +// is because if we did, then dequeue would stay in that block, eventually reading the new values, +// instead of advancing to the next full block (whose values were enqueued first and so should be +// consumed first). + +fence(memory_order_acquire); // Ensure we get latest writes if we got the latest frontBlock + +// tailBlock is full, but there's a free block ahead, use it +Block* tailBlockNext = tailBlock_->next.load(); +size_t nextBlockFront = tailBlockNext->localFront = tailBlockNext->front.load(); +nextBlockTail = tailBlockNext->tail.load(); +fence(memory_order_acquire); + +// This block must be empty since it's not the head block and we +// go through the blocks in a circle +assert(nextBlockFront == nextBlockTail); +tailBlockNext->localFront = nextBlockFront; + +char* location = tailBlockNext->data + nextBlockTail * sizeof(T); +#if MOODYCAMEL_HAS_EMPLACE +new (location) T(std::forward(args)...); +#else +new (location) T(std::forward(element)); +#endif + +tailBlockNext->tail = (nextBlockTail + 1) & tailBlockNext->sizeMask; + +fence(memory_order_release); +tailBlock = tailBlockNext; +} +else if (canAlloc == CanAlloc) { +// tailBlock is full and there's no free block ahead; create a new block +auto newBlockSize = largestBlockSize >= MAX_BLOCK_SIZE ? largestBlockSize : largestBlockSize * 2; +auto newBlock = make_block(newBlockSize); +if (newBlock == nullptr) { +// Could not allocate a block! +return false; +} +largestBlockSize = newBlockSize; + +#if MOODYCAMEL_HAS_EMPLACE +new (newBlock->data) T(std::forward(args)...); +#else +new (newBlock->data) T(std::forward(element)); +#endif +assert(newBlock->front == 0); +newBlock->tail = newBlock->localTail = 1; + +newBlock->next = tailBlock_->next.load(); +tailBlock_->next = newBlock; + +// Might be possible for the dequeue thread to see the new tailBlock->next +// *without* seeing the new tailBlock value, but this is OK since it can't +// advance to the next block until tailBlock is set anyway (because the only +// case where it could try to read the next is if it's already at the tailBlock, +// and it won't advance past tailBlock in any circumstance). + +fence(memory_order_release); +tailBlock = newBlock; +} +else if (canAlloc == CannotAlloc) { +// Would have had to allocate a new block to enqueue, but not allowed +return false; +} +else { +assert(false && "Should be unreachable code"); +return false; +} +} + +return true; +} + + +// Disable copying +ReaderWriterQueue(ReaderWriterQueue const&) { } + +// Disable assignment +ReaderWriterQueue& operator=(ReaderWriterQueue const&) { } + + +AE_FORCEINLINE static size_t ceilToPow2(size_t x) +{ +// From http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 +--x; +x |= x >> 1; +x |= x >> 2; +x |= x >> 4; +for (size_t i = 1; i < sizeof(size_t); i <<= 1) { +x |= x >> (i << 3); +} +++x; +return x; +} + +template +static AE_FORCEINLINE char* align_for(char* ptr) AE_NO_TSAN +{ +const std::size_t alignment = std::alignment_of::value; +return ptr + (alignment - (reinterpret_cast(ptr) % alignment)) % alignment; +} +private: +#ifndef NDEBUG +struct ReentrantGuard +{ + AE_NO_TSAN ReentrantGuard(weak_atomic& _inSection) + : inSection(_inSection) + { + assert(!inSection && "Concurrent (or re-entrant) enqueue or dequeue operation detected (only one thread at a time may hold the producer or consumer role)"); + inSection = true; + } + + AE_NO_TSAN ~ReentrantGuard() { inSection = false; } + +private: + ReentrantGuard& operator=(ReentrantGuard const&); + +private: + weak_atomic& inSection; +}; +#endif + +struct Block +{ + // Avoid false-sharing by putting highly contended variables on their own cache lines + weak_atomic front; // (Atomic) Elements are read from here + size_t localTail; // An uncontended shadow copy of tail, owned by the consumer + + char cachelineFiller0[MOODYCAMEL_CACHE_LINE_SIZE - sizeof(weak_atomic) - sizeof(size_t)]; + weak_atomic tail; // (Atomic) Elements are enqueued here + size_t localFront; + + char cachelineFiller1[MOODYCAMEL_CACHE_LINE_SIZE - sizeof(weak_atomic) - sizeof(size_t)]; // next isn't very contended, but we don't want it on the same cache line as tail (which is) + weak_atomic next; // (Atomic) + + char* data; // Contents (on heap) are aligned to T's alignment + + const size_t sizeMask; + + + // size must be a power of two (and greater than 0) + AE_NO_TSAN Block(size_t const& _size, char* _rawThis, char* _data) + : front(0UL), localTail(0), tail(0UL), localFront(0), next(nullptr), data(_data), sizeMask(_size - 1), rawThis(_rawThis) + { + } + +private: + // C4512 - Assignment operator could not be generated + Block& operator=(Block const&); + +public: + char* rawThis; +}; + + +static Block* make_block(size_t capacity) AE_NO_TSAN +{ +// Allocate enough memory for the block itself, as well as all the elements it will contain +auto size = sizeof(Block) + std::alignment_of::value - 1; +size += sizeof(T) * capacity + std::alignment_of::value - 1; +auto newBlockRaw = static_cast(std::malloc(size)); +if (newBlockRaw == nullptr) { +return nullptr; +} + +auto newBlockAligned = align_for(newBlockRaw); +auto newBlockData = align_for(newBlockAligned + sizeof(Block)); +return new (newBlockAligned) Block(capacity, newBlockRaw, newBlockData); +} + +private: +weak_atomic frontBlock; // (Atomic) Elements are dequeued from this block + +char cachelineFiller[MOODYCAMEL_CACHE_LINE_SIZE - sizeof(weak_atomic)]; +weak_atomic tailBlock; // (Atomic) Elements are enqueued to this block + +size_t largestBlockSize; + +#ifndef NDEBUG +weak_atomic enqueuing; +mutable weak_atomic dequeuing; +#endif +}; + +// Like ReaderWriterQueue, but also providees blocking operations +template +class BlockingReaderWriterQueue +{ +private: + typedef ::moodycamel::ReaderWriterQueue ReaderWriterQueue; + +public: + explicit BlockingReaderWriterQueue(size_t size = 15) AE_NO_TSAN + : inner(size), sema(new spsc_sema::LightweightSemaphore()) + { } + + BlockingReaderWriterQueue(BlockingReaderWriterQueue&& other) AE_NO_TSAN + : inner(std::move(other.inner)), sema(std::move(other.sema)) + { } + + BlockingReaderWriterQueue& operator=(BlockingReaderWriterQueue&& other) AE_NO_TSAN + { + std::swap(sema, other.sema); + std::swap(inner, other.inner); + return *this; + } + + + // Enqueues a copy of element if there is room in the queue. + // Returns true if the element was enqueued, false otherwise. + // Does not allocate memory. + AE_FORCEINLINE bool try_enqueue(T const& element) AE_NO_TSAN + { + if (inner.try_enqueue(element)) { + sema->signal(); + return true; + } + return false; + } + + // Enqueues a moved copy of element if there is room in the queue. + // Returns true if the element was enqueued, false otherwise. + // Does not allocate memory. + AE_FORCEINLINE bool try_enqueue(T&& element) AE_NO_TSAN + { + if (inner.try_enqueue(std::forward(element))) { + sema->signal(); + return true; + } + return false; + } + +#if MOODYCAMEL_HAS_EMPLACE + // Like try_enqueue() but with emplace semantics (i.e. construct-in-place). + template + AE_FORCEINLINE bool try_emplace(Args&&... args) AE_NO_TSAN + { + if (inner.try_emplace(std::forward(args)...)) { + sema->signal(); + return true; + } + return false; + } +#endif + + + // Enqueues a copy of element on the queue. + // Allocates an additional block of memory if needed. + // Only fails (returns false) if memory allocation fails. + AE_FORCEINLINE bool enqueue(T const& element) AE_NO_TSAN + { + if (inner.enqueue(element)) { + sema->signal(); + return true; + } + return false; + } + + // Enqueues a moved copy of element on the queue. + // Allocates an additional block of memory if needed. + // Only fails (returns false) if memory allocation fails. + AE_FORCEINLINE bool enqueue(T&& element) AE_NO_TSAN + { + if (inner.enqueue(std::forward(element))) { + sema->signal(); + return true; + } + return false; + } + +#if MOODYCAMEL_HAS_EMPLACE + // Like enqueue() but with emplace semantics (i.e. construct-in-place). + template + AE_FORCEINLINE bool emplace(Args&&... args) AE_NO_TSAN + { + if (inner.emplace(std::forward(args)...)) { + sema->signal(); + return true; + } + return false; + } +#endif + + + // Attempts to dequeue an element; if the queue is empty, + // returns false instead. If the queue has at least one element, + // moves front to result using operator=, then returns true. + template + bool try_dequeue(U& result) AE_NO_TSAN + { + if (sema->tryWait()) { + bool success = inner.try_dequeue(result); + assert(success); + AE_UNUSED(success); + return true; + } + return false; + } + + + // Attempts to dequeue an element; if the queue is empty, + // waits until an element is available, then dequeues it. + template + void wait_dequeue(U& result) AE_NO_TSAN + { + while (!sema->wait()); + bool success = inner.try_dequeue(result); + AE_UNUSED(result); + assert(success); + AE_UNUSED(success); + } + + + // Attempts to dequeue an element; if the queue is empty, + // waits until an element is available up to the specified timeout, + // then dequeues it and returns true, or returns false if the timeout + // expires before an element can be dequeued. + // Using a negative timeout indicates an indefinite timeout, + // and is thus functionally equivalent to calling wait_dequeue. + template + bool wait_dequeue_timed(U& result, std::int64_t timeout_usecs) AE_NO_TSAN + { + if (!sema->wait(timeout_usecs)) { + return false; + } + bool success = inner.try_dequeue(result); + AE_UNUSED(result); + assert(success); + AE_UNUSED(success); + return true; + } + + +#if __cplusplus > 199711L || _MSC_VER >= 1700 + // Attempts to dequeue an element; if the queue is empty, + // waits until an element is available up to the specified timeout, + // then dequeues it and returns true, or returns false if the timeout + // expires before an element can be dequeued. + // Using a negative timeout indicates an indefinite timeout, + // and is thus functionally equivalent to calling wait_dequeue. + template + inline bool wait_dequeue_timed(U& result, std::chrono::duration const& timeout) AE_NO_TSAN + { + return wait_dequeue_timed(result, std::chrono::duration_cast(timeout).count()); + } +#endif + + + // Returns a pointer to the front element in the queue (the one that + // would be removed next by a call to `try_dequeue` or `pop`). If the + // queue appears empty at the time the method is called, nullptr is + // returned instead. + // Must be called only from the consumer thread. + AE_FORCEINLINE T* peek() const AE_NO_TSAN + { + return inner.peek(); + } + + // Removes the front element from the queue, if any, without returning it. + // Returns true on success, or false if the queue appeared empty at the time + // `pop` was called. + AE_FORCEINLINE bool pop() AE_NO_TSAN + { + if (sema->tryWait()) { + bool result = inner.pop(); + assert(result); + AE_UNUSED(result); + return true; + } + return false; + } + + // Returns the approximate number of items currently in the queue. + // Safe to call from both the producer and consumer threads. + AE_FORCEINLINE size_t size_approx() const AE_NO_TSAN + { + return sema->availableApprox(); + } + + // Returns the total number of items that could be enqueued without incurring + // an allocation when this queue is empty. + // Safe to call from both the producer and consumer threads. + // + // NOTE: The actual capacity during usage may be different depending on the consumer. + // If the consumer is removing elements concurrently, the producer cannot add to + // the block the consumer is removing from until it's completely empty, except in + // the case where the producer was writing to the same block the consumer was + // reading from the whole time. + AE_FORCEINLINE size_t max_capacity() const { + return inner.max_capacity(); + } + +private: + // Disable copying & assignment + BlockingReaderWriterQueue(BlockingReaderWriterQueue const&) { } + BlockingReaderWriterQueue& operator=(BlockingReaderWriterQueue const&) { } + +private: + ReaderWriterQueue inner; + std::unique_ptr sema; +}; + +} // end namespace moodycamel + +#ifdef AE_VCPP +#pragma warning(pop) +#endif \ No newline at end of file diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 7d1244b0..39fb50ea 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -42,7 +42,7 @@ void QueryCoordinator::allocate_core_resources(int core_idx, int num_queries, in res.topk_buffer_pool.resize(num_queries); for (int q = 0; q < num_queries; ++q) { res.topk_buffer_pool[q] = make_shared(k, metric_ == faiss::METRIC_INNER_PRODUCT); - res.job_queue = moodycamel::ConcurrentQueue(); + res.job_queue = moodycamel::BlockingReaderWriterQueue(); } } @@ -109,9 +109,10 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { auto job_wait_start = std::chrono::high_resolution_clock::now(); int64_t job_id; - while (!res.job_queue.try_dequeue(job_id)) { - std::this_thread::sleep_for(std::chrono::microseconds(5)); - } + res.job_queue.wait_dequeue(job_id); +// while (!res.job_queue.try_dequeue(job_id)) { +// std::this_thread::sleep_for(std::chrono::microseconds(5)); +// } auto job_wait_end = std::chrono::high_resolution_clock::now(); From 00bd8e14a4a18b9212916e1b008f26e832b01a48 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 12:46:58 -0500 Subject: [PATCH 120/323] minimize job enqueing time --- src/cpp/include/query_coordinator.h | 2 +- src/cpp/src/query_coordinator.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 23baabab..16759913 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -54,7 +54,7 @@ class QueryCoordinator { int core_id; ///< Logical identifier of the core. vector> topk_buffer_pool; ///< Preallocated Top‑K buffers. vector local_query_buffer; ///< Local aggregator for query results. - moodycamel::BlockingReaderWriterQueue job_queue; ///< Job queue for scan jobs. + moodycamel::ReaderWriterQueue job_queue; ///< Job queue for scan jobs. }; vector core_resources_; ///< Per‑core resources for worker threads. diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 39fb50ea..ab228087 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -42,7 +42,7 @@ void QueryCoordinator::allocate_core_resources(int core_idx, int num_queries, in res.topk_buffer_pool.resize(num_queries); for (int q = 0; q < num_queries; ++q) { res.topk_buffer_pool[q] = make_shared(k, metric_ == faiss::METRIC_INNER_PRODUCT); - res.job_queue = moodycamel::BlockingReaderWriterQueue(); + res.job_queue = moodycamel::ReaderWriterQueue(); } } @@ -109,10 +109,10 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { auto job_wait_start = std::chrono::high_resolution_clock::now(); int64_t job_id; - res.job_queue.wait_dequeue(job_id); -// while (!res.job_queue.try_dequeue(job_id)) { -// std::this_thread::sleep_for(std::chrono::microseconds(5)); -// } +// res.job_queue.wait_dequeue(job_id); + while (!res.job_queue.try_dequeue(job_id)) { + std::this_thread::sleep_for(std::chrono::microseconds(1)); + } auto job_wait_end = std::chrono::high_resolution_clock::now(); From 9fb76328cd3d73a5e1cb96877733290df4b54f56 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 12:53:54 -0500 Subject: [PATCH 121/323] minimize job enqueing time --- src/cpp/include/query_coordinator.h | 5 ++--- src/cpp/src/query_coordinator.cpp | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 16759913..317e3256 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -10,8 +10,7 @@ #include #include #include -//#include -#include +#include class QuakeIndex; class PartitionManager; @@ -54,7 +53,7 @@ class QueryCoordinator { int core_id; ///< Logical identifier of the core. vector> topk_buffer_pool; ///< Preallocated Top‑K buffers. vector local_query_buffer; ///< Local aggregator for query results. - moodycamel::ReaderWriterQueue job_queue; ///< Job queue for scan jobs. + moodycamel::ConcurrentQueue job_queue; ///< Job queue for scan jobs. }; vector core_resources_; ///< Per‑core resources for worker threads. diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index ab228087..a1ec9b0f 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -42,7 +42,7 @@ void QueryCoordinator::allocate_core_resources(int core_idx, int num_queries, in res.topk_buffer_pool.resize(num_queries); for (int q = 0; q < num_queries; ++q) { res.topk_buffer_pool[q] = make_shared(k, metric_ == faiss::METRIC_INNER_PRODUCT); - res.job_queue = moodycamel::ReaderWriterQueue(); + res.job_queue = moodycamel::ConcurrentQueue(); } } From 8abf36960483d6241049d1532793b4ffbc79ce95 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 13:53:08 -0500 Subject: [PATCH 122/323] track parent timing info --- src/cpp/include/atomicops.h | 772 -------------- src/cpp/include/list_scanning.h | 18 +- src/cpp/include/readerwritequeue.h | 979 ------------------ src/cpp/src/query_coordinator.cpp | 2 +- .../osdi2025/numa_single_query/run.py | 182 ++-- 5 files changed, 122 insertions(+), 1831 deletions(-) delete mode 100644 src/cpp/include/atomicops.h delete mode 100644 src/cpp/include/readerwritequeue.h diff --git a/src/cpp/include/atomicops.h b/src/cpp/include/atomicops.h deleted file mode 100644 index 1832dee8..00000000 --- a/src/cpp/include/atomicops.h +++ /dev/null @@ -1,772 +0,0 @@ -// ©2013-2016 Cameron Desrochers. -// Distributed under the simplified BSD license (see the license file that -// should have come with this header). -// Uses Jeff Preshing's semaphore implementation (under the terms of its -// separate zlib license, embedded below). - -#pragma once - -// Provides portable (VC++2010+, Intel ICC 13, GCC 4.7+, and anything C++11 compliant) implementation -// of low-level memory barriers, plus a few semi-portable utility macros (for inlining and alignment). -// Also has a basic atomic type (limited to hardware-supported atomics with no memory ordering guarantees). -// Uses the AE_* prefix for macros (historical reasons), and the "moodycamel" namespace for symbols. - -#include -#include -#include -#include -#include -#include - -// Platform detection -#if defined(__INTEL_COMPILER) -#define AE_ICC -#elif defined(_MSC_VER) -#define AE_VCPP -#elif defined(__GNUC__) -#define AE_GCC -#endif - -#if defined(_M_IA64) || defined(__ia64__) -#define AE_ARCH_IA64 -#elif defined(_WIN64) || defined(__amd64__) || defined(_M_X64) || defined(__x86_64__) -#define AE_ARCH_X64 -#elif defined(_M_IX86) || defined(__i386__) -#define AE_ARCH_X86 -#elif defined(_M_PPC) || defined(__powerpc__) -#define AE_ARCH_PPC -#else -#define AE_ARCH_UNKNOWN -#endif - - -// AE_UNUSED -#define AE_UNUSED(x) ((void)x) - -// AE_NO_TSAN/AE_TSAN_ANNOTATE_* -// For GCC -#if defined(__SANITIZE_THREAD__) -#define AE_TSAN_IS_ENABLED -#endif -// For clang -#if defined(__has_feature) -#if __has_feature(thread_sanitizer) && !defined(AE_TSAN_IS_ENABLED) -#define AE_TSAN_IS_ENABLED -#endif -#endif - -#ifdef AE_TSAN_IS_ENABLED -#if __cplusplus >= 201703L // inline variables require C++17 -namespace moodycamel { inline int ae_tsan_global; } -#define AE_TSAN_ANNOTATE_RELEASE() AnnotateHappensBefore(__FILE__, __LINE__, (void *)(&::moodycamel::ae_tsan_global)) -#define AE_TSAN_ANNOTATE_ACQUIRE() AnnotateHappensAfter(__FILE__, __LINE__, (void *)(&::moodycamel::ae_tsan_global)) -extern "C" void AnnotateHappensBefore(const char*, int, void*); -extern "C" void AnnotateHappensAfter(const char*, int, void*); -#else // when we can't work with tsan, attempt to disable its warnings -#define AE_NO_TSAN __attribute__((no_sanitize("thread"))) -#endif -#endif - -#ifndef AE_NO_TSAN -#define AE_NO_TSAN -#endif - -#ifndef AE_TSAN_ANNOTATE_RELEASE -#define AE_TSAN_ANNOTATE_RELEASE() -#define AE_TSAN_ANNOTATE_ACQUIRE() -#endif - - -// AE_FORCEINLINE -#if defined(AE_VCPP) || defined(AE_ICC) -#define AE_FORCEINLINE __forceinline -#elif defined(AE_GCC) -//#define AE_FORCEINLINE __attribute__((always_inline)) -#define AE_FORCEINLINE inline -#else -#define AE_FORCEINLINE inline -#endif - - -// AE_ALIGN -#if defined(AE_VCPP) || defined(AE_ICC) -#define AE_ALIGN(x) __declspec(align(x)) -#elif defined(AE_GCC) -#define AE_ALIGN(x) __attribute__((aligned(x))) -#else -// Assume GCC compliant syntax... -#define AE_ALIGN(x) __attribute__((aligned(x))) -#endif - - -// Portable atomic fences implemented below: - -namespace moodycamel { - - enum memory_order { - memory_order_relaxed, - memory_order_acquire, - memory_order_release, - memory_order_acq_rel, - memory_order_seq_cst, - - // memory_order_sync: Forces a full sync: - // #LoadLoad, #LoadStore, #StoreStore, and most significantly, #StoreLoad - memory_order_sync = memory_order_seq_cst - }; - -} // end namespace moodycamel - -#if (defined(AE_VCPP) && (_MSC_VER < 1700 || defined(__cplusplus_cli))) || (defined(AE_ICC) && __INTEL_COMPILER < 1600) -// VS2010 and ICC13 don't support std::atomic_*_fence, implement our own fences - -#include - -#if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) -#define AeFullSync _mm_mfence -#define AeLiteSync _mm_mfence -#elif defined(AE_ARCH_IA64) -#define AeFullSync __mf -#define AeLiteSync __mf -#elif defined(AE_ARCH_PPC) -#include -#define AeFullSync __sync -#define AeLiteSync __lwsync -#endif - - -#ifdef AE_VCPP -#pragma warning(push) -#pragma warning(disable: 4365) // Disable erroneous 'conversion from long to unsigned int, signed/unsigned mismatch' error when using `assert` -#ifdef __cplusplus_cli -#pragma managed(push, off) -#endif -#endif - -namespace moodycamel { - -AE_FORCEINLINE void compiler_fence(memory_order order) AE_NO_TSAN -{ - switch (order) { - case memory_order_relaxed: break; - case memory_order_acquire: _ReadBarrier(); break; - case memory_order_release: _WriteBarrier(); break; - case memory_order_acq_rel: _ReadWriteBarrier(); break; - case memory_order_seq_cst: _ReadWriteBarrier(); break; - default: assert(false); - } -} - -// x86/x64 have a strong memory model -- all loads and stores have -// acquire and release semantics automatically (so only need compiler -// barriers for those). -#if defined(AE_ARCH_X86) || defined(AE_ARCH_X64) -AE_FORCEINLINE void fence(memory_order order) AE_NO_TSAN -{ - switch (order) { - case memory_order_relaxed: break; - case memory_order_acquire: _ReadBarrier(); break; - case memory_order_release: _WriteBarrier(); break; - case memory_order_acq_rel: _ReadWriteBarrier(); break; - case memory_order_seq_cst: - _ReadWriteBarrier(); - AeFullSync(); - _ReadWriteBarrier(); - break; - default: assert(false); - } -} -#else -AE_FORCEINLINE void fence(memory_order order) AE_NO_TSAN -{ - // Non-specialized arch, use heavier memory barriers everywhere just in case :-( - switch (order) { - case memory_order_relaxed: - break; - case memory_order_acquire: - _ReadBarrier(); - AeLiteSync(); - _ReadBarrier(); - break; - case memory_order_release: - _WriteBarrier(); - AeLiteSync(); - _WriteBarrier(); - break; - case memory_order_acq_rel: - _ReadWriteBarrier(); - AeLiteSync(); - _ReadWriteBarrier(); - break; - case memory_order_seq_cst: - _ReadWriteBarrier(); - AeFullSync(); - _ReadWriteBarrier(); - break; - default: assert(false); - } -} -#endif -} // end namespace moodycamel -#else -// Use standard library of atomics -#include - -namespace moodycamel { - - AE_FORCEINLINE void compiler_fence(memory_order order) AE_NO_TSAN - { - switch (order) { - case memory_order_relaxed: break; - case memory_order_acquire: std::atomic_signal_fence(std::memory_order_acquire); break; - case memory_order_release: std::atomic_signal_fence(std::memory_order_release); break; - case memory_order_acq_rel: std::atomic_signal_fence(std::memory_order_acq_rel); break; - case memory_order_seq_cst: std::atomic_signal_fence(std::memory_order_seq_cst); break; - default: assert(false); - } - } - - AE_FORCEINLINE void fence(memory_order order) AE_NO_TSAN - { - switch (order) { - case memory_order_relaxed: break; - case memory_order_acquire: AE_TSAN_ANNOTATE_ACQUIRE(); std::atomic_thread_fence(std::memory_order_acquire); break; - case memory_order_release: AE_TSAN_ANNOTATE_RELEASE(); std::atomic_thread_fence(std::memory_order_release); break; - case memory_order_acq_rel: AE_TSAN_ANNOTATE_ACQUIRE(); AE_TSAN_ANNOTATE_RELEASE(); std::atomic_thread_fence(std::memory_order_acq_rel); break; - case memory_order_seq_cst: AE_TSAN_ANNOTATE_ACQUIRE(); AE_TSAN_ANNOTATE_RELEASE(); std::atomic_thread_fence(std::memory_order_seq_cst); break; - default: assert(false); - } - } - -} // end namespace moodycamel - -#endif - - -#if !defined(AE_VCPP) || (_MSC_VER >= 1700 && !defined(__cplusplus_cli)) -#define AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC -#endif - -#ifdef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC -#include -#endif -#include - -// WARNING: *NOT* A REPLACEMENT FOR std::atomic. READ CAREFULLY: -// Provides basic support for atomic variables -- no memory ordering guarantees are provided. -// The guarantee of atomicity is only made for types that already have atomic load and store guarantees -// at the hardware level -- on most platforms this generally means aligned pointers and integers (only). -namespace moodycamel { - template - class weak_atomic - { - public: - AE_NO_TSAN weak_atomic() : value() { } -#ifdef AE_VCPP - #pragma warning(push) -#pragma warning(disable: 4100) // Get rid of (erroneous) 'unreferenced formal parameter' warning -#endif - template AE_NO_TSAN weak_atomic(U&& x) : value(std::forward(x)) { } -#ifdef __cplusplus_cli - // Work around bug with universal reference/nullptr combination that only appears when /clr is on - AE_NO_TSAN weak_atomic(nullptr_t) : value(nullptr) { } -#endif - AE_NO_TSAN weak_atomic(weak_atomic const& other) : value(other.load()) { } - AE_NO_TSAN weak_atomic(weak_atomic&& other) : value(std::move(other.load())) { } -#ifdef AE_VCPP -#pragma warning(pop) -#endif - - AE_FORCEINLINE operator T() const AE_NO_TSAN { return load(); } - - -#ifndef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC - template AE_FORCEINLINE weak_atomic const& operator=(U&& x) AE_NO_TSAN { value = std::forward(x); return *this; } - AE_FORCEINLINE weak_atomic const& operator=(weak_atomic const& other) AE_NO_TSAN { value = other.value; return *this; } - - AE_FORCEINLINE T load() const AE_NO_TSAN { return value; } - - AE_FORCEINLINE T fetch_add_acquire(T increment) AE_NO_TSAN - { -#if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) - if (sizeof(T) == 4) return _InterlockedExchangeAdd((long volatile*)&value, (long)increment); -#if defined(_M_AMD64) - else if (sizeof(T) == 8) return _InterlockedExchangeAdd64((long long volatile*)&value, (long long)increment); -#endif -#else -#error Unsupported platform -#endif - assert(false && "T must be either a 32 or 64 bit type"); - return value; - } - - AE_FORCEINLINE T fetch_add_release(T increment) AE_NO_TSAN - { -#if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) - if (sizeof(T) == 4) return _InterlockedExchangeAdd((long volatile*)&value, (long)increment); -#if defined(_M_AMD64) - else if (sizeof(T) == 8) return _InterlockedExchangeAdd64((long long volatile*)&value, (long long)increment); -#endif -#else -#error Unsupported platform -#endif - assert(false && "T must be either a 32 or 64 bit type"); - return value; - } -#else - template - AE_FORCEINLINE weak_atomic const& operator=(U&& x) AE_NO_TSAN - { - value.store(std::forward(x), std::memory_order_relaxed); - return *this; - } - - AE_FORCEINLINE weak_atomic const& operator=(weak_atomic const& other) AE_NO_TSAN - { - value.store(other.value.load(std::memory_order_relaxed), std::memory_order_relaxed); - return *this; - } - - AE_FORCEINLINE T load() const AE_NO_TSAN { return value.load(std::memory_order_relaxed); } - - AE_FORCEINLINE T fetch_add_acquire(T increment) AE_NO_TSAN - { - return value.fetch_add(increment, std::memory_order_acquire); - } - - AE_FORCEINLINE T fetch_add_release(T increment) AE_NO_TSAN - { - return value.fetch_add(increment, std::memory_order_release); - } -#endif - - - private: -#ifndef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC - // No std::atomic support, but still need to circumvent compiler optimizations. - // `volatile` will make memory access slow, but is guaranteed to be reliable. - volatile T value; -#else - std::atomic value; -#endif - }; - -} // end namespace moodycamel - - - -// Portable single-producer, single-consumer semaphore below: - -#if defined(_WIN32) -// Avoid including windows.h in a header; we only need a handful of -// items, so we'll redeclare them here (this is relatively safe since -// the API generally has to remain stable between Windows versions). -// I know this is an ugly hack but it still beats polluting the global -// namespace with thousands of generic names or adding a .cpp for nothing. -extern "C" { - struct _SECURITY_ATTRIBUTES; - __declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES* lpSemaphoreAttributes, long lInitialCount, long lMaximumCount, const wchar_t* lpName); - __declspec(dllimport) int __stdcall CloseHandle(void* hObject); - __declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void* hHandle, unsigned long dwMilliseconds); - __declspec(dllimport) int __stdcall ReleaseSemaphore(void* hSemaphore, long lReleaseCount, long* lpPreviousCount); -} -#elif defined(__MACH__) -#include -#elif defined(__unix__) -#include -#elif defined(FREERTOS) -#include -#include -#include -#endif - -namespace moodycamel -{ - // Code in the spsc_sema namespace below is an adaptation of Jeff Preshing's - // portable + lightweight semaphore implementations, originally from - // https://github.com/preshing/cpp11-on-multicore/blob/master/common/sema.h - // LICENSE: - // Copyright (c) 2015 Jeff Preshing - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgement in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - namespace spsc_sema - { -#if defined(_WIN32) - class Semaphore - { - private: - void* m_hSema; - - Semaphore(const Semaphore& other); - Semaphore& operator=(const Semaphore& other); - - public: - AE_NO_TSAN Semaphore(int initialCount = 0) : m_hSema() - { - assert(initialCount >= 0); - const long maxLong = 0x7fffffff; - m_hSema = CreateSemaphoreW(nullptr, initialCount, maxLong, nullptr); - assert(m_hSema); - } - - AE_NO_TSAN ~Semaphore() - { - CloseHandle(m_hSema); - } - - bool wait() AE_NO_TSAN - { - const unsigned long infinite = 0xffffffff; - return WaitForSingleObject(m_hSema, infinite) == 0; - } - - bool try_wait() AE_NO_TSAN - { - return WaitForSingleObject(m_hSema, 0) == 0; - } - - bool timed_wait(std::uint64_t usecs) AE_NO_TSAN - { - return WaitForSingleObject(m_hSema, (unsigned long)(usecs / 1000)) == 0; - } - - void signal(int count = 1) AE_NO_TSAN - { - while (!ReleaseSemaphore(m_hSema, count, nullptr)); - } - }; -#elif defined(__MACH__) - //--------------------------------------------------------- - // Semaphore (Apple iOS and OSX) - // Can't use POSIX semaphores due to http://lists.apple.com/archives/darwin-kernel/2009/Apr/msg00010.html - //--------------------------------------------------------- - class Semaphore - { - private: - semaphore_t m_sema; - - Semaphore(const Semaphore& other); - Semaphore& operator=(const Semaphore& other); - - public: - AE_NO_TSAN Semaphore(int initialCount = 0) : m_sema() - { - assert(initialCount >= 0); - kern_return_t rc = semaphore_create(mach_task_self(), &m_sema, SYNC_POLICY_FIFO, initialCount); - assert(rc == KERN_SUCCESS); - AE_UNUSED(rc); - } - - AE_NO_TSAN ~Semaphore() - { - semaphore_destroy(mach_task_self(), m_sema); - } - - bool wait() AE_NO_TSAN - { - return semaphore_wait(m_sema) == KERN_SUCCESS; - } - - bool try_wait() AE_NO_TSAN - { - return timed_wait(0); - } - - bool timed_wait(std::uint64_t timeout_usecs) AE_NO_TSAN - { - mach_timespec_t ts; - ts.tv_sec = static_cast(timeout_usecs / 1000000); - ts.tv_nsec = static_cast((timeout_usecs % 1000000) * 1000); - - // added in OSX 10.10: https://developer.apple.com/library/prerelease/mac/documentation/General/Reference/APIDiffsMacOSX10_10SeedDiff/modules/Darwin.html - kern_return_t rc = semaphore_timedwait(m_sema, ts); - return rc == KERN_SUCCESS; - } - - void signal() AE_NO_TSAN - { - while (semaphore_signal(m_sema) != KERN_SUCCESS); - } - - void signal(int count) AE_NO_TSAN - { - while (count-- > 0) - { - while (semaphore_signal(m_sema) != KERN_SUCCESS); - } - } - }; -#elif defined(__unix__) - //--------------------------------------------------------- - // Semaphore (POSIX, Linux) - //--------------------------------------------------------- - class Semaphore - { - private: - sem_t m_sema; - - Semaphore(const Semaphore& other); - Semaphore& operator=(const Semaphore& other); - - public: - AE_NO_TSAN Semaphore(int initialCount = 0) : m_sema() - { - assert(initialCount >= 0); - int rc = sem_init(&m_sema, 0, static_cast(initialCount)); - assert(rc == 0); - AE_UNUSED(rc); - } - - AE_NO_TSAN ~Semaphore() - { - sem_destroy(&m_sema); - } - - bool wait() AE_NO_TSAN - { - // http://stackoverflow.com/questions/2013181/gdb-causes-sem-wait-to-fail-with-eintr-error - int rc; - do - { - rc = sem_wait(&m_sema); - } - while (rc == -1 && errno == EINTR); - return rc == 0; - } - - bool try_wait() AE_NO_TSAN - { - int rc; - do { - rc = sem_trywait(&m_sema); - } while (rc == -1 && errno == EINTR); - return rc == 0; - } - - bool timed_wait(std::uint64_t usecs) AE_NO_TSAN - { - struct timespec ts; - const int usecs_in_1_sec = 1000000; - const int nsecs_in_1_sec = 1000000000; - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += static_cast(usecs / usecs_in_1_sec); - ts.tv_nsec += static_cast(usecs % usecs_in_1_sec) * 1000; - // sem_timedwait bombs if you have more than 1e9 in tv_nsec - // so we have to clean things up before passing it in - if (ts.tv_nsec >= nsecs_in_1_sec) { - ts.tv_nsec -= nsecs_in_1_sec; - ++ts.tv_sec; - } - - int rc; - do { - rc = sem_timedwait(&m_sema, &ts); - } while (rc == -1 && errno == EINTR); - return rc == 0; - } - - void signal() AE_NO_TSAN - { - while (sem_post(&m_sema) == -1); - } - - void signal(int count) AE_NO_TSAN - { - while (count-- > 0) - { - while (sem_post(&m_sema) == -1); - } - } - }; -#elif defined(FREERTOS) - //--------------------------------------------------------- - // Semaphore (FreeRTOS) - //--------------------------------------------------------- - class Semaphore - { - private: - SemaphoreHandle_t m_sema; - - Semaphore(const Semaphore& other); - Semaphore& operator=(const Semaphore& other); - - public: - AE_NO_TSAN Semaphore(int initialCount = 0) : m_sema() - { - assert(initialCount >= 0); - m_sema = xSemaphoreCreateCounting(static_cast(~0ull), static_cast(initialCount)); - assert(m_sema); - } - - AE_NO_TSAN ~Semaphore() - { - vSemaphoreDelete(m_sema); - } - - bool wait() AE_NO_TSAN - { - return xSemaphoreTake(m_sema, portMAX_DELAY) == pdTRUE; - } - - bool try_wait() AE_NO_TSAN - { - // Note: In an ISR context, if this causes a task to unblock, - // the caller won't know about it - if (xPortIsInsideInterrupt()) - return xSemaphoreTakeFromISR(m_sema, NULL) == pdTRUE; - return xSemaphoreTake(m_sema, 0) == pdTRUE; - } - - bool timed_wait(std::uint64_t usecs) AE_NO_TSAN - { - std::uint64_t msecs = usecs / 1000; - TickType_t ticks = static_cast(msecs / portTICK_PERIOD_MS); - if (ticks == 0) - return try_wait(); - return xSemaphoreTake(m_sema, ticks) == pdTRUE; - } - - void signal() AE_NO_TSAN - { - // Note: In an ISR context, if this causes a task to unblock, - // the caller won't know about it - BaseType_t rc; - if (xPortIsInsideInterrupt()) - rc = xSemaphoreGiveFromISR(m_sema, NULL); - else - rc = xSemaphoreGive(m_sema); - assert(rc == pdTRUE); - AE_UNUSED(rc); - } - - void signal(int count) AE_NO_TSAN - { - while (count-- > 0) - signal(); - } - }; -#else -#error Unsupported platform! (No semaphore wrapper available) -#endif - - //--------------------------------------------------------- - // LightweightSemaphore - //--------------------------------------------------------- - class LightweightSemaphore - { - public: - typedef std::make_signed::type ssize_t; - - private: - weak_atomic m_count; - Semaphore m_sema; - - bool waitWithPartialSpinning(std::int64_t timeout_usecs = -1) AE_NO_TSAN - { - ssize_t oldCount; - // Is there a better way to set the initial spin count? - // If we lower it to 1000, testBenaphore becomes 15x slower on my Core i7-5930K Windows PC, - // as threads start hitting the kernel semaphore. - int spin = 1024; - while (--spin >= 0) - { - if (m_count.load() > 0) - { - m_count.fetch_add_acquire(-1); - return true; - } - compiler_fence(memory_order_acquire); // Prevent the compiler from collapsing the loop. - } - oldCount = m_count.fetch_add_acquire(-1); - if (oldCount > 0) - return true; - if (timeout_usecs < 0) - { - if (m_sema.wait()) - return true; - } - if (timeout_usecs > 0 && m_sema.timed_wait(static_cast(timeout_usecs))) - return true; - // At this point, we've timed out waiting for the semaphore, but the - // count is still decremented indicating we may still be waiting on - // it. So we have to re-adjust the count, but only if the semaphore - // wasn't signaled enough times for us too since then. If it was, we - // need to release the semaphore too. - while (true) - { - oldCount = m_count.fetch_add_release(1); - if (oldCount < 0) - return false; // successfully restored things to the way they were - // Oh, the producer thread just signaled the semaphore after all. Try again: - oldCount = m_count.fetch_add_acquire(-1); - if (oldCount > 0 && m_sema.try_wait()) - return true; - } - } - - public: - AE_NO_TSAN LightweightSemaphore(ssize_t initialCount = 0) : m_count(initialCount), m_sema() - { - assert(initialCount >= 0); - } - - bool tryWait() AE_NO_TSAN - { - if (m_count.load() > 0) - { - m_count.fetch_add_acquire(-1); - return true; - } - return false; - } - - bool wait() AE_NO_TSAN - { - return tryWait() || waitWithPartialSpinning(); - } - - bool wait(std::int64_t timeout_usecs) AE_NO_TSAN - { - return tryWait() || waitWithPartialSpinning(timeout_usecs); - } - - void signal(ssize_t count = 1) AE_NO_TSAN - { - assert(count >= 0); - ssize_t oldCount = m_count.fetch_add_release(count); - assert(oldCount >= -1); - if (oldCount < 0) - { - m_sema.signal(1); - } - } - - std::size_t availableApprox() const AE_NO_TSAN - { - ssize_t count = m_count.load(); - return count > 0 ? static_cast(count) : 0; - } - }; - } // end namespace spsc_sema -} // end namespace moodycamel - -#if defined(AE_VCPP) && (_MSC_VER < 1700 || defined(__cplusplus_cli)) -#pragma warning(pop) -#ifdef __cplusplus_cli -#pragma managed(pop) -#endif -#endif \ No newline at end of file diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index b8319e04..b41831ca 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -403,7 +403,9 @@ inline void batched_scan_list(const float *query_vecs, int list_size, int dim, vector> &topk_buffers, - MetricType metric = faiss::METRIC_L2) { + MetricType metric = faiss::METRIC_L2, + float *distances = nullptr, + int64_t *labels = nullptr) { if (list_size == 0 || list_vecs == nullptr) { // No list vectors to process; return; @@ -413,8 +415,12 @@ inline void batched_scan_list(const float *query_vecs, int k = topk_buffers[0]->k_; int k_max = std::min(k, list_size); - int64_t *labels = (int64_t *) malloc(num_queries * k_max * sizeof(int64_t)); - float *distances = (float *) malloc(num_queries * k_max * sizeof(float)); + bool alloc_results = false; + if (distances == nullptr) { + alloc_results = true; + (int64_t *) malloc(num_queries * k_max * sizeof(int64_t)); + (float *) malloc(num_queries * k_max * sizeof(float)); + } if (metric == faiss::METRIC_INNER_PRODUCT) { faiss::float_minheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; @@ -447,8 +453,10 @@ inline void batched_scan_list(const float *query_vecs, topk_buffers[i]->batch_add(distances + i * k_max, labels + i * k_max, k_max); } - free(labels); - free(distances); + if (alloc_results) { + free(distances); + free(labels); + } } // } diff --git a/src/cpp/include/readerwritequeue.h b/src/cpp/include/readerwritequeue.h deleted file mode 100644 index 098d47cf..00000000 --- a/src/cpp/include/readerwritequeue.h +++ /dev/null @@ -1,979 +0,0 @@ -// ©2013-2020 Cameron Desrochers. -// Distributed under the simplified BSD license (see the license file that -// should have come with this header). - -#pragma once - -#include "atomicops.h" -#include -#include -#include -#include -#include -#include -#include -#include // For malloc/free/abort & size_t -#include -#if __cplusplus > 199711L || _MSC_VER >= 1700 // C++11 or VS2012 -#include -#endif - - -// A lock-free queue for a single-consumer, single-producer architecture. -// The queue is also wait-free in the common path (except if more memory -// needs to be allocated, in which case malloc is called). -// Allocates memory sparingly, and only once if the original maximum size -// estimate is never exceeded. -// Tested on x86/x64 processors, but semantics should be correct for all -// architectures (given the right implementations in atomicops.h), provided -// that aligned integer and pointer accesses are naturally atomic. -// Note that there should only be one consumer thread and producer thread; -// Switching roles of the threads, or using multiple consecutive threads for -// one role, is not safe unless properly synchronized. -// Using the queue exclusively from one thread is fine, though a bit silly. - -#ifndef MOODYCAMEL_CACHE_LINE_SIZE -#define MOODYCAMEL_CACHE_LINE_SIZE 64 -#endif - -#ifndef MOODYCAMEL_EXCEPTIONS_ENABLED -#if (defined(_MSC_VER) && defined(_CPPUNWIND)) || (defined(__GNUC__) && defined(__EXCEPTIONS)) || (!defined(_MSC_VER) && !defined(__GNUC__)) -#define MOODYCAMEL_EXCEPTIONS_ENABLED -#endif -#endif - -#ifndef MOODYCAMEL_HAS_EMPLACE -#if !defined(_MSC_VER) || _MSC_VER >= 1800 // variadic templates: either a non-MS compiler or VS >= 2013 -#define MOODYCAMEL_HAS_EMPLACE 1 -#endif -#endif - -#ifndef MOODYCAMEL_MAYBE_ALIGN_TO_CACHELINE -#if defined (__APPLE__) && defined (__MACH__) && __cplusplus >= 201703L -// This is required to find out what deployment target we are using -#include -#if !defined(MAC_OS_X_VERSION_MIN_REQUIRED) || !defined(MAC_OS_X_VERSION_10_14) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_14 -// C++17 new(size_t, align_val_t) is not backwards-compatible with older versions of macOS, so we can't support over-alignment in this case -#define MOODYCAMEL_MAYBE_ALIGN_TO_CACHELINE -#endif -#endif -#endif - -#ifndef MOODYCAMEL_MAYBE_ALIGN_TO_CACHELINE -#define MOODYCAMEL_MAYBE_ALIGN_TO_CACHELINE AE_ALIGN(MOODYCAMEL_CACHE_LINE_SIZE) -#endif - -#ifdef AE_VCPP -#pragma warning(push) -#pragma warning(disable: 4324) // structure was padded due to __declspec(align()) -#pragma warning(disable: 4820) // padding was added -#pragma warning(disable: 4127) // conditional expression is constant -#endif - -namespace moodycamel { - - template - class MOODYCAMEL_MAYBE_ALIGN_TO_CACHELINE ReaderWriterQueue -{ - // Design: Based on a queue-of-queues. The low-level queues are just - // circular buffers with front and tail indices indicating where the - // next element to dequeue is and where the next element can be enqueued, - // respectively. Each low-level queue is called a "block". Each block - // wastes exactly one element's worth of space to keep the design simple - // (if front == tail then the queue is empty, and can't be full). - // The high-level queue is a circular linked list of blocks; again there - // is a front and tail, but this time they are pointers to the blocks. - // The front block is where the next element to be dequeued is, provided - // the block is not empty. The back block is where elements are to be - // enqueued, provided the block is not full. - // The producer thread owns all the tail indices/pointers. The consumer - // thread owns all the front indices/pointers. Both threads read each - // other's variables, but only the owning thread updates them. E.g. After - // the consumer reads the producer's tail, the tail may change before the - // consumer is done dequeuing an object, but the consumer knows the tail - // will never go backwards, only forwards. - // If there is no room to enqueue an object, an additional block (of - // equal size to the last block) is added. Blocks are never removed. - - public: - typedef T value_type; - - // Constructs a queue that can hold at least `size` elements without further - // allocations. If more than MAX_BLOCK_SIZE elements are requested, - // then several blocks of MAX_BLOCK_SIZE each are reserved (including - // at least one extra buffer block). - AE_NO_TSAN explicit ReaderWriterQueue(size_t size = 15) -#ifndef NDEBUG - : enqueuing(false) - ,dequeuing(false) -#endif -{ - assert(MAX_BLOCK_SIZE == ceilToPow2(MAX_BLOCK_SIZE) && "MAX_BLOCK_SIZE must be a power of 2"); - assert(MAX_BLOCK_SIZE >= 2 && "MAX_BLOCK_SIZE must be at least 2"); - - Block* firstBlock = nullptr; - - largestBlockSize = ceilToPow2(size + 1); // We need a spare slot to fit size elements in the block - if (largestBlockSize > MAX_BLOCK_SIZE * 2) { - // We need a spare block in case the producer is writing to a different block the consumer is reading from, and - // wants to enqueue the maximum number of elements. We also need a spare element in each block to avoid the ambiguity - // between front == tail meaning "empty" and "full". - // So the effective number of slots that are guaranteed to be usable at any time is the block size - 1 times the - // number of blocks - 1. Solving for size and applying a ceiling to the division gives us (after simplifying): - size_t initialBlockCount = (size + MAX_BLOCK_SIZE * 2 - 3) / (MAX_BLOCK_SIZE - 1); - largestBlockSize = MAX_BLOCK_SIZE; - Block* lastBlock = nullptr; - for (size_t i = 0; i != initialBlockCount; ++i) { - auto block = make_block(largestBlockSize); - if (block == nullptr) { -#ifdef MOODYCAMEL_EXCEPTIONS_ENABLED - throw std::bad_alloc(); -#else - abort(); -#endif -} -if (firstBlock == nullptr) { -firstBlock = block; -} -else { -lastBlock->next = block; -} -lastBlock = block; -block->next = firstBlock; -} -} -else { -firstBlock = make_block(largestBlockSize); -if (firstBlock == nullptr) { -#ifdef MOODYCAMEL_EXCEPTIONS_ENABLED -throw std::bad_alloc(); -#else -abort(); -#endif -} -firstBlock->next = firstBlock; -} -frontBlock = firstBlock; -tailBlock = firstBlock; - -// Make sure the reader/writer threads will have the initialized memory setup above: -fence(memory_order_sync); -} - -// Note: The queue should not be accessed concurrently while it's -// being moved. It's up to the user to synchronize this. -AE_NO_TSAN ReaderWriterQueue(ReaderWriterQueue&& other) -: frontBlock(other.frontBlock.load()), -tailBlock(other.tailBlock.load()), -largestBlockSize(other.largestBlockSize) -#ifndef NDEBUG -,enqueuing(false) -,dequeuing(false) -#endif -{ -other.largestBlockSize = 32; -Block* b = other.make_block(other.largestBlockSize); -if (b == nullptr) { -#ifdef MOODYCAMEL_EXCEPTIONS_ENABLED -throw std::bad_alloc(); -#else -abort(); -#endif -} -b->next = b; -other.frontBlock = b; -other.tailBlock = b; -} - -// Note: The queue should not be accessed concurrently while it's -// being moved. It's up to the user to synchronize this. -ReaderWriterQueue& operator=(ReaderWriterQueue&& other) AE_NO_TSAN -{ -Block* b = frontBlock.load(); -frontBlock = other.frontBlock.load(); -other.frontBlock = b; -b = tailBlock.load(); -tailBlock = other.tailBlock.load(); -other.tailBlock = b; -std::swap(largestBlockSize, other.largestBlockSize); -return *this; -} - -// Note: The queue should not be accessed concurrently while it's -// being deleted. It's up to the user to synchronize this. -AE_NO_TSAN ~ReaderWriterQueue() -{ - // Make sure we get the latest version of all variables from other CPUs: - fence(memory_order_sync); - - // Destroy any remaining objects in queue and free memory - Block* frontBlock_ = frontBlock; - Block* block = frontBlock_; - do { - Block* nextBlock = block->next; - size_t blockFront = block->front; - size_t blockTail = block->tail; - - for (size_t i = blockFront; i != blockTail; i = (i + 1) & block->sizeMask) { - auto element = reinterpret_cast(block->data + i * sizeof(T)); - element->~T(); - (void)element; - } - - auto rawBlock = block->rawThis; - block->~Block(); - std::free(rawBlock); - block = nextBlock; - } while (block != frontBlock_); -} - - -// Enqueues a copy of element if there is room in the queue. -// Returns true if the element was enqueued, false otherwise. -// Does not allocate memory. -AE_FORCEINLINE bool try_enqueue(T const& element) AE_NO_TSAN -{ -return inner_enqueue(element); -} - -// Enqueues a moved copy of element if there is room in the queue. -// Returns true if the element was enqueued, false otherwise. -// Does not allocate memory. -AE_FORCEINLINE bool try_enqueue(T&& element) AE_NO_TSAN -{ -return inner_enqueue(std::forward(element)); -} - -#if MOODYCAMEL_HAS_EMPLACE -// Like try_enqueue() but with emplace semantics (i.e. construct-in-place). -template -AE_FORCEINLINE bool try_emplace(Args&&... args) AE_NO_TSAN -{ -return inner_enqueue(std::forward(args)...); -} -#endif - -// Enqueues a copy of element on the queue. -// Allocates an additional block of memory if needed. -// Only fails (returns false) if memory allocation fails. -AE_FORCEINLINE bool enqueue(T const& element) AE_NO_TSAN -{ -return inner_enqueue(element); -} - -// Enqueues a moved copy of element on the queue. -// Allocates an additional block of memory if needed. -// Only fails (returns false) if memory allocation fails. -AE_FORCEINLINE bool enqueue(T&& element) AE_NO_TSAN -{ -return inner_enqueue(std::forward(element)); -} - -#if MOODYCAMEL_HAS_EMPLACE -// Like enqueue() but with emplace semantics (i.e. construct-in-place). -template -AE_FORCEINLINE bool emplace(Args&&... args) AE_NO_TSAN -{ -return inner_enqueue(std::forward(args)...); -} -#endif - -// Attempts to dequeue an element; if the queue is empty, -// returns false instead. If the queue has at least one element, -// moves front to result using operator=, then returns true. -template -bool try_dequeue(U& result) AE_NO_TSAN -{ -#ifndef NDEBUG -ReentrantGuard guard(this->dequeuing); -#endif - -// High-level pseudocode: -// Remember where the tail block is -// If the front block has an element in it, dequeue it -// Else -// If front block was the tail block when we entered the function, return false -// Else advance to next block and dequeue the item there - -// Note that we have to use the value of the tail block from before we check if the front -// block is full or not, in case the front block is empty and then, before we check if the -// tail block is at the front block or not, the producer fills up the front block *and -// moves on*, which would make us skip a filled block. Seems unlikely, but was consistently -// reproducible in practice. -// In order to avoid overhead in the common case, though, we do a double-checked pattern -// where we have the fast path if the front block is not empty, then read the tail block, -// then re-read the front block and check if it's not empty again, then check if the tail -// block has advanced. - -Block* frontBlock_ = frontBlock.load(); -size_t blockTail = frontBlock_->localTail; -size_t blockFront = frontBlock_->front.load(); - -if (blockFront != blockTail || blockFront != (frontBlock_->localTail = frontBlock_->tail.load())) { -fence(memory_order_acquire); - -non_empty_front_block: -// Front block not empty, dequeue from here -auto element = reinterpret_cast(frontBlock_->data + blockFront * sizeof(T)); -result = std::move(*element); -element->~T(); - -blockFront = (blockFront + 1) & frontBlock_->sizeMask; - -fence(memory_order_release); -frontBlock_->front = blockFront; -} -else if (frontBlock_ != tailBlock.load()) { -fence(memory_order_acquire); - -frontBlock_ = frontBlock.load(); -blockTail = frontBlock_->localTail = frontBlock_->tail.load(); -blockFront = frontBlock_->front.load(); -fence(memory_order_acquire); - -if (blockFront != blockTail) { -// Oh look, the front block isn't empty after all -goto non_empty_front_block; -} - -// Front block is empty but there's another block ahead, advance to it -Block* nextBlock = frontBlock_->next; -// Don't need an acquire fence here since next can only ever be set on the tailBlock, -// and we're not the tailBlock, and we did an acquire earlier after reading tailBlock which -// ensures next is up-to-date on this CPU in case we recently were at tailBlock. - -size_t nextBlockFront = nextBlock->front.load(); -size_t nextBlockTail = nextBlock->localTail = nextBlock->tail.load(); -fence(memory_order_acquire); - -// Since the tailBlock is only ever advanced after being written to, -// we know there's for sure an element to dequeue on it -assert(nextBlockFront != nextBlockTail); -AE_UNUSED(nextBlockTail); - -// We're done with this block, let the producer use it if it needs -fence(memory_order_release); // Expose possibly pending changes to frontBlock->front from last dequeue -frontBlock = frontBlock_ = nextBlock; - -compiler_fence(memory_order_release); // Not strictly needed - -auto element = reinterpret_cast(frontBlock_->data + nextBlockFront * sizeof(T)); - -result = std::move(*element); -element->~T(); - -nextBlockFront = (nextBlockFront + 1) & frontBlock_->sizeMask; - -fence(memory_order_release); -frontBlock_->front = nextBlockFront; -} -else { -// No elements in current block and no other block to advance to -return false; -} - -return true; -} - - -// Returns a pointer to the front element in the queue (the one that -// would be removed next by a call to `try_dequeue` or `pop`). If the -// queue appears empty at the time the method is called, nullptr is -// returned instead. -// Must be called only from the consumer thread. -T* peek() const AE_NO_TSAN -{ -#ifndef NDEBUG -ReentrantGuard guard(this->dequeuing); -#endif -// See try_dequeue() for reasoning - -Block* frontBlock_ = frontBlock.load(); -size_t blockTail = frontBlock_->localTail; -size_t blockFront = frontBlock_->front.load(); - -if (blockFront != blockTail || blockFront != (frontBlock_->localTail = frontBlock_->tail.load())) { -fence(memory_order_acquire); -non_empty_front_block: -return reinterpret_cast(frontBlock_->data + blockFront * sizeof(T)); -} -else if (frontBlock_ != tailBlock.load()) { -fence(memory_order_acquire); -frontBlock_ = frontBlock.load(); -blockTail = frontBlock_->localTail = frontBlock_->tail.load(); -blockFront = frontBlock_->front.load(); -fence(memory_order_acquire); - -if (blockFront != blockTail) { -goto non_empty_front_block; -} - -Block* nextBlock = frontBlock_->next; - -size_t nextBlockFront = nextBlock->front.load(); -fence(memory_order_acquire); - -assert(nextBlockFront != nextBlock->tail.load()); -return reinterpret_cast(nextBlock->data + nextBlockFront * sizeof(T)); -} - -return nullptr; -} - -// Removes the front element from the queue, if any, without returning it. -// Returns true on success, or false if the queue appeared empty at the time -// `pop` was called. -bool pop() AE_NO_TSAN -{ -#ifndef NDEBUG -ReentrantGuard guard(this->dequeuing); -#endif -// See try_dequeue() for reasoning - -Block* frontBlock_ = frontBlock.load(); -size_t blockTail = frontBlock_->localTail; -size_t blockFront = frontBlock_->front.load(); - -if (blockFront != blockTail || blockFront != (frontBlock_->localTail = frontBlock_->tail.load())) { -fence(memory_order_acquire); - -non_empty_front_block: -auto element = reinterpret_cast(frontBlock_->data + blockFront * sizeof(T)); -element->~T(); - -blockFront = (blockFront + 1) & frontBlock_->sizeMask; - -fence(memory_order_release); -frontBlock_->front = blockFront; -} -else if (frontBlock_ != tailBlock.load()) { -fence(memory_order_acquire); -frontBlock_ = frontBlock.load(); -blockTail = frontBlock_->localTail = frontBlock_->tail.load(); -blockFront = frontBlock_->front.load(); -fence(memory_order_acquire); - -if (blockFront != blockTail) { -goto non_empty_front_block; -} - -// Front block is empty but there's another block ahead, advance to it -Block* nextBlock = frontBlock_->next; - -size_t nextBlockFront = nextBlock->front.load(); -size_t nextBlockTail = nextBlock->localTail = nextBlock->tail.load(); -fence(memory_order_acquire); - -assert(nextBlockFront != nextBlockTail); -AE_UNUSED(nextBlockTail); - -fence(memory_order_release); -frontBlock = frontBlock_ = nextBlock; - -compiler_fence(memory_order_release); - -auto element = reinterpret_cast(frontBlock_->data + nextBlockFront * sizeof(T)); -element->~T(); - -nextBlockFront = (nextBlockFront + 1) & frontBlock_->sizeMask; - -fence(memory_order_release); -frontBlock_->front = nextBlockFront; -} -else { -// No elements in current block and no other block to advance to -return false; -} - -return true; -} - -// Returns the approximate number of items currently in the queue. -// Safe to call from both the producer and consumer threads. -inline size_t size_approx() const AE_NO_TSAN -{ -size_t result = 0; -Block* frontBlock_ = frontBlock.load(); -Block* block = frontBlock_; -do { -fence(memory_order_acquire); -size_t blockFront = block->front.load(); -size_t blockTail = block->tail.load(); -result += (blockTail - blockFront) & block->sizeMask; -block = block->next.load(); -} while (block != frontBlock_); -return result; -} - -// Returns the total number of items that could be enqueued without incurring -// an allocation when this queue is empty. -// Safe to call from both the producer and consumer threads. -// -// NOTE: The actual capacity during usage may be different depending on the consumer. -// If the consumer is removing elements concurrently, the producer cannot add to -// the block the consumer is removing from until it's completely empty, except in -// the case where the producer was writing to the same block the consumer was -// reading from the whole time. -inline size_t max_capacity() const { - size_t result = 0; - Block* frontBlock_ = frontBlock.load(); - Block* block = frontBlock_; - do { - fence(memory_order_acquire); - result += block->sizeMask; - block = block->next.load(); - } while (block != frontBlock_); - return result; -} - - -private: -enum AllocationMode { CanAlloc, CannotAlloc }; - -#if MOODYCAMEL_HAS_EMPLACE -template -bool inner_enqueue(Args&&... args) AE_NO_TSAN -#else -template - bool inner_enqueue(U&& element) AE_NO_TSAN -#endif -{ -#ifndef NDEBUG -ReentrantGuard guard(this->enqueuing); -#endif - -// High-level pseudocode (assuming we're allowed to alloc a new block): -// If room in tail block, add to tail -// Else check next block -// If next block is not the head block, enqueue on next block -// Else create a new block and enqueue there -// Advance tail to the block we just enqueued to - -Block* tailBlock_ = tailBlock.load(); -size_t blockFront = tailBlock_->localFront; -size_t blockTail = tailBlock_->tail.load(); - -size_t nextBlockTail = (blockTail + 1) & tailBlock_->sizeMask; -if (nextBlockTail != blockFront || nextBlockTail != (tailBlock_->localFront = tailBlock_->front.load())) { -fence(memory_order_acquire); -// This block has room for at least one more element -char* location = tailBlock_->data + blockTail * sizeof(T); -#if MOODYCAMEL_HAS_EMPLACE -new (location) T(std::forward(args)...); -#else -new (location) T(std::forward(element)); -#endif - -fence(memory_order_release); -tailBlock_->tail = nextBlockTail; -} -else { -fence(memory_order_acquire); -if (tailBlock_->next.load() != frontBlock) { -// Note that the reason we can't advance to the frontBlock and start adding new entries there -// is because if we did, then dequeue would stay in that block, eventually reading the new values, -// instead of advancing to the next full block (whose values were enqueued first and so should be -// consumed first). - -fence(memory_order_acquire); // Ensure we get latest writes if we got the latest frontBlock - -// tailBlock is full, but there's a free block ahead, use it -Block* tailBlockNext = tailBlock_->next.load(); -size_t nextBlockFront = tailBlockNext->localFront = tailBlockNext->front.load(); -nextBlockTail = tailBlockNext->tail.load(); -fence(memory_order_acquire); - -// This block must be empty since it's not the head block and we -// go through the blocks in a circle -assert(nextBlockFront == nextBlockTail); -tailBlockNext->localFront = nextBlockFront; - -char* location = tailBlockNext->data + nextBlockTail * sizeof(T); -#if MOODYCAMEL_HAS_EMPLACE -new (location) T(std::forward(args)...); -#else -new (location) T(std::forward(element)); -#endif - -tailBlockNext->tail = (nextBlockTail + 1) & tailBlockNext->sizeMask; - -fence(memory_order_release); -tailBlock = tailBlockNext; -} -else if (canAlloc == CanAlloc) { -// tailBlock is full and there's no free block ahead; create a new block -auto newBlockSize = largestBlockSize >= MAX_BLOCK_SIZE ? largestBlockSize : largestBlockSize * 2; -auto newBlock = make_block(newBlockSize); -if (newBlock == nullptr) { -// Could not allocate a block! -return false; -} -largestBlockSize = newBlockSize; - -#if MOODYCAMEL_HAS_EMPLACE -new (newBlock->data) T(std::forward(args)...); -#else -new (newBlock->data) T(std::forward(element)); -#endif -assert(newBlock->front == 0); -newBlock->tail = newBlock->localTail = 1; - -newBlock->next = tailBlock_->next.load(); -tailBlock_->next = newBlock; - -// Might be possible for the dequeue thread to see the new tailBlock->next -// *without* seeing the new tailBlock value, but this is OK since it can't -// advance to the next block until tailBlock is set anyway (because the only -// case where it could try to read the next is if it's already at the tailBlock, -// and it won't advance past tailBlock in any circumstance). - -fence(memory_order_release); -tailBlock = newBlock; -} -else if (canAlloc == CannotAlloc) { -// Would have had to allocate a new block to enqueue, but not allowed -return false; -} -else { -assert(false && "Should be unreachable code"); -return false; -} -} - -return true; -} - - -// Disable copying -ReaderWriterQueue(ReaderWriterQueue const&) { } - -// Disable assignment -ReaderWriterQueue& operator=(ReaderWriterQueue const&) { } - - -AE_FORCEINLINE static size_t ceilToPow2(size_t x) -{ -// From http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 ---x; -x |= x >> 1; -x |= x >> 2; -x |= x >> 4; -for (size_t i = 1; i < sizeof(size_t); i <<= 1) { -x |= x >> (i << 3); -} -++x; -return x; -} - -template -static AE_FORCEINLINE char* align_for(char* ptr) AE_NO_TSAN -{ -const std::size_t alignment = std::alignment_of::value; -return ptr + (alignment - (reinterpret_cast(ptr) % alignment)) % alignment; -} -private: -#ifndef NDEBUG -struct ReentrantGuard -{ - AE_NO_TSAN ReentrantGuard(weak_atomic& _inSection) - : inSection(_inSection) - { - assert(!inSection && "Concurrent (or re-entrant) enqueue or dequeue operation detected (only one thread at a time may hold the producer or consumer role)"); - inSection = true; - } - - AE_NO_TSAN ~ReentrantGuard() { inSection = false; } - -private: - ReentrantGuard& operator=(ReentrantGuard const&); - -private: - weak_atomic& inSection; -}; -#endif - -struct Block -{ - // Avoid false-sharing by putting highly contended variables on their own cache lines - weak_atomic front; // (Atomic) Elements are read from here - size_t localTail; // An uncontended shadow copy of tail, owned by the consumer - - char cachelineFiller0[MOODYCAMEL_CACHE_LINE_SIZE - sizeof(weak_atomic) - sizeof(size_t)]; - weak_atomic tail; // (Atomic) Elements are enqueued here - size_t localFront; - - char cachelineFiller1[MOODYCAMEL_CACHE_LINE_SIZE - sizeof(weak_atomic) - sizeof(size_t)]; // next isn't very contended, but we don't want it on the same cache line as tail (which is) - weak_atomic next; // (Atomic) - - char* data; // Contents (on heap) are aligned to T's alignment - - const size_t sizeMask; - - - // size must be a power of two (and greater than 0) - AE_NO_TSAN Block(size_t const& _size, char* _rawThis, char* _data) - : front(0UL), localTail(0), tail(0UL), localFront(0), next(nullptr), data(_data), sizeMask(_size - 1), rawThis(_rawThis) - { - } - -private: - // C4512 - Assignment operator could not be generated - Block& operator=(Block const&); - -public: - char* rawThis; -}; - - -static Block* make_block(size_t capacity) AE_NO_TSAN -{ -// Allocate enough memory for the block itself, as well as all the elements it will contain -auto size = sizeof(Block) + std::alignment_of::value - 1; -size += sizeof(T) * capacity + std::alignment_of::value - 1; -auto newBlockRaw = static_cast(std::malloc(size)); -if (newBlockRaw == nullptr) { -return nullptr; -} - -auto newBlockAligned = align_for(newBlockRaw); -auto newBlockData = align_for(newBlockAligned + sizeof(Block)); -return new (newBlockAligned) Block(capacity, newBlockRaw, newBlockData); -} - -private: -weak_atomic frontBlock; // (Atomic) Elements are dequeued from this block - -char cachelineFiller[MOODYCAMEL_CACHE_LINE_SIZE - sizeof(weak_atomic)]; -weak_atomic tailBlock; // (Atomic) Elements are enqueued to this block - -size_t largestBlockSize; - -#ifndef NDEBUG -weak_atomic enqueuing; -mutable weak_atomic dequeuing; -#endif -}; - -// Like ReaderWriterQueue, but also providees blocking operations -template -class BlockingReaderWriterQueue -{ -private: - typedef ::moodycamel::ReaderWriterQueue ReaderWriterQueue; - -public: - explicit BlockingReaderWriterQueue(size_t size = 15) AE_NO_TSAN - : inner(size), sema(new spsc_sema::LightweightSemaphore()) - { } - - BlockingReaderWriterQueue(BlockingReaderWriterQueue&& other) AE_NO_TSAN - : inner(std::move(other.inner)), sema(std::move(other.sema)) - { } - - BlockingReaderWriterQueue& operator=(BlockingReaderWriterQueue&& other) AE_NO_TSAN - { - std::swap(sema, other.sema); - std::swap(inner, other.inner); - return *this; - } - - - // Enqueues a copy of element if there is room in the queue. - // Returns true if the element was enqueued, false otherwise. - // Does not allocate memory. - AE_FORCEINLINE bool try_enqueue(T const& element) AE_NO_TSAN - { - if (inner.try_enqueue(element)) { - sema->signal(); - return true; - } - return false; - } - - // Enqueues a moved copy of element if there is room in the queue. - // Returns true if the element was enqueued, false otherwise. - // Does not allocate memory. - AE_FORCEINLINE bool try_enqueue(T&& element) AE_NO_TSAN - { - if (inner.try_enqueue(std::forward(element))) { - sema->signal(); - return true; - } - return false; - } - -#if MOODYCAMEL_HAS_EMPLACE - // Like try_enqueue() but with emplace semantics (i.e. construct-in-place). - template - AE_FORCEINLINE bool try_emplace(Args&&... args) AE_NO_TSAN - { - if (inner.try_emplace(std::forward(args)...)) { - sema->signal(); - return true; - } - return false; - } -#endif - - - // Enqueues a copy of element on the queue. - // Allocates an additional block of memory if needed. - // Only fails (returns false) if memory allocation fails. - AE_FORCEINLINE bool enqueue(T const& element) AE_NO_TSAN - { - if (inner.enqueue(element)) { - sema->signal(); - return true; - } - return false; - } - - // Enqueues a moved copy of element on the queue. - // Allocates an additional block of memory if needed. - // Only fails (returns false) if memory allocation fails. - AE_FORCEINLINE bool enqueue(T&& element) AE_NO_TSAN - { - if (inner.enqueue(std::forward(element))) { - sema->signal(); - return true; - } - return false; - } - -#if MOODYCAMEL_HAS_EMPLACE - // Like enqueue() but with emplace semantics (i.e. construct-in-place). - template - AE_FORCEINLINE bool emplace(Args&&... args) AE_NO_TSAN - { - if (inner.emplace(std::forward(args)...)) { - sema->signal(); - return true; - } - return false; - } -#endif - - - // Attempts to dequeue an element; if the queue is empty, - // returns false instead. If the queue has at least one element, - // moves front to result using operator=, then returns true. - template - bool try_dequeue(U& result) AE_NO_TSAN - { - if (sema->tryWait()) { - bool success = inner.try_dequeue(result); - assert(success); - AE_UNUSED(success); - return true; - } - return false; - } - - - // Attempts to dequeue an element; if the queue is empty, - // waits until an element is available, then dequeues it. - template - void wait_dequeue(U& result) AE_NO_TSAN - { - while (!sema->wait()); - bool success = inner.try_dequeue(result); - AE_UNUSED(result); - assert(success); - AE_UNUSED(success); - } - - - // Attempts to dequeue an element; if the queue is empty, - // waits until an element is available up to the specified timeout, - // then dequeues it and returns true, or returns false if the timeout - // expires before an element can be dequeued. - // Using a negative timeout indicates an indefinite timeout, - // and is thus functionally equivalent to calling wait_dequeue. - template - bool wait_dequeue_timed(U& result, std::int64_t timeout_usecs) AE_NO_TSAN - { - if (!sema->wait(timeout_usecs)) { - return false; - } - bool success = inner.try_dequeue(result); - AE_UNUSED(result); - assert(success); - AE_UNUSED(success); - return true; - } - - -#if __cplusplus > 199711L || _MSC_VER >= 1700 - // Attempts to dequeue an element; if the queue is empty, - // waits until an element is available up to the specified timeout, - // then dequeues it and returns true, or returns false if the timeout - // expires before an element can be dequeued. - // Using a negative timeout indicates an indefinite timeout, - // and is thus functionally equivalent to calling wait_dequeue. - template - inline bool wait_dequeue_timed(U& result, std::chrono::duration const& timeout) AE_NO_TSAN - { - return wait_dequeue_timed(result, std::chrono::duration_cast(timeout).count()); - } -#endif - - - // Returns a pointer to the front element in the queue (the one that - // would be removed next by a call to `try_dequeue` or `pop`). If the - // queue appears empty at the time the method is called, nullptr is - // returned instead. - // Must be called only from the consumer thread. - AE_FORCEINLINE T* peek() const AE_NO_TSAN - { - return inner.peek(); - } - - // Removes the front element from the queue, if any, without returning it. - // Returns true on success, or false if the queue appeared empty at the time - // `pop` was called. - AE_FORCEINLINE bool pop() AE_NO_TSAN - { - if (sema->tryWait()) { - bool result = inner.pop(); - assert(result); - AE_UNUSED(result); - return true; - } - return false; - } - - // Returns the approximate number of items currently in the queue. - // Safe to call from both the producer and consumer threads. - AE_FORCEINLINE size_t size_approx() const AE_NO_TSAN - { - return sema->availableApprox(); - } - - // Returns the total number of items that could be enqueued without incurring - // an allocation when this queue is empty. - // Safe to call from both the producer and consumer threads. - // - // NOTE: The actual capacity during usage may be different depending on the consumer. - // If the consumer is removing elements concurrently, the producer cannot add to - // the block the consumer is removing from until it's completely empty, except in - // the case where the producer was writing to the same block the consumer was - // reading from the whole time. - AE_FORCEINLINE size_t max_capacity() const { - return inner.max_capacity(); - } - -private: - // Disable copying & assignment - BlockingReaderWriterQueue(BlockingReaderWriterQueue const&) { } - BlockingReaderWriterQueue& operator=(BlockingReaderWriterQueue const&) { } - -private: - ReaderWriterQueue inner; - std::unique_ptr sema; -}; - -} // end namespace moodycamel - -#ifdef AE_VCPP -#pragma warning(pop) -#endif \ No newline at end of file diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index a1ec9b0f..d141b4c1 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -111,7 +111,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { int64_t job_id; // res.job_queue.wait_dequeue(job_id); while (!res.job_queue.try_dequeue(job_id)) { - std::this_thread::sleep_for(std::chrono::microseconds(1)); + std::this_thread::sleep_for(std::chrono::microseconds(5)); } auto job_wait_end = std::chrono::high_resolution_clock::now(); diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index f105cb3c..8f08bce2 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -1,16 +1,15 @@ -#!/usr/bin/env python3 """ -NUMA Single-Query Latency and Recall Benchmark (detailed timers, aggregated) +NUMA Single-Query Latency and Recall Benchmark (detailed timers + parent) -For each query we extract: +Tracks these phases, for both the worker_scan and its parent search: - buffer_init_time_ns - job_enqueue_time_ns - job_wait_time_ns - result_aggregate_time_ns - total_time_ns -We average each timer across queries in a trial, then average across trials, -and emit those means (in ms) alongside recall and latency. +Averages per‐query timers within each trial, then across trials, +and writes them (in ms) to the per‐index CSV. """ import sys from pathlib import Path @@ -48,13 +47,13 @@ } def build_and_save(index_cls, params, vecs, path): - """Builds and persists an index to disk.""" + """Build and persist an index.""" idx = index_cls() idx.build(vecs, **params) idx.save(str(path)) def extract_ids(res): - """Normalize the returned IDs array.""" + """Normalize returned IDs array.""" if hasattr(res, "ids"): arr = res.ids elif hasattr(res, "I"): @@ -81,20 +80,20 @@ def run_experiment(cfg_path: str, output_dir: str) -> None: out_dir = Path(output_dir).expanduser().absolute() out_dir.mkdir(parents=True, exist_ok=True) - # Load data + # Load dataset print(f"[INFO] loading dataset {ds_cfg['name']} …") base_vecs, queries, gt = load_dataset(ds_cfg["name"]) queries = queries[:q_n] gt = gt[:q_n] if gt is not None else None - # Build shared Quake base index if needed + # Build shared Quake base index once quake_base_params = None for c in idx_cfgs: if c["index"] == "Quake": - earthquake = dict(c.get("build_params", {})) - earthquake.pop("num_workers", None) - earthquake.pop("use_numa", None) - quake_base_params = earthquake + p = dict(c.get("build_params", {})) + p.pop("num_workers", None) + p.pop("use_numa", None) + quake_base_params = p break quake_base_path = out_dir / "Quake_base_index.bin" @@ -115,16 +114,14 @@ def run_experiment(cfg_path: str, output_dir: str) -> None: continue idx_csv = out_dir / f"{name}_results.csv" - idx_path = (quake_base_path if typ == "Quake" - else out_dir / f"{name}_index.bin") + idx_path = quake_base_path if typ == "Quake" else out_dir / f"{name}_index.bin" - # Skip if done if idx_csv.exists() and not overwrite: print(f"[SKIP] {name} – results exist.") results.append(pd.read_csv(idx_csv).iloc[0].to_dict()) continue - # Build non-Quake if missing + # Build non-Quake if needed if typ != "Quake" and not idx_path.exists(): print(f"[BUILD] {name} index …") build_and_save(cls, b_params, base_vecs, idx_path) @@ -132,16 +129,14 @@ def run_experiment(cfg_path: str, output_dir: str) -> None: # Load index if typ == "Quake": - load_kw = {k: b_params[k] - for k in ("use_numa", "num_workers") - if k in b_params} + load_kw = {k: b_params[k] for k in ("use_numa", "num_workers") if k in b_params} idx = QuakeWrapper(); idx.load(str(idx_path), **load_kw) elif typ == "DiskANN": idx = cls(); b_params.pop("metric", None); idx.load(str(idx_path), **b_params) else: idx = cls(); idx.load(str(idx_path)) - # Dispatch search params + # Dispatch search parameters if typ == "SCANN": search_kw = {"leaves_to_search": s_params.get("leaves_to_search", 100)} elif typ == "HNSW": @@ -157,72 +152,111 @@ def run_experiment(cfg_path: str, output_dir: str) -> None: for q in queries[:min(warmup_n, len(queries))]: idx.search(q.unsqueeze(0).float(), k, **search_kw) - # Collect per-trial means - all_trial_latencies = [] - all_trial_recalls = [] - # for each timer: list of trial-means - buf_init_trials = [] - enqueue_trials = [] - wait_trials = [] - agg_trials = [] - total_trials = [] + # Prepare accumulators + child_lat_trials = [] + parent_lat_trials = [] + child_buf_init_trials = [] + child_enq_trials = [] + child_wait_trials = [] + child_agg_trials = [] + child_total_trials = [] + parent_buf_init_trials = [] + parent_enq_trials = [] + parent_wait_trials = [] + parent_agg_trials = [] + parent_total_trials = [] + first_trial_recalls = [] for t in range(trials): - latencies = [] - recalls = [] - buf_init_q = [] - enq_q = [] - wait_q = [] - agg_q = [] - total_q = [] + # per-query lists + child_lats = [] + parent_lats = [] + child_buf_init = [] + child_enq = [] + child_wait = [] + child_agg = [] + child_total = [] + parent_buf_init = [] + parent_enq = [] + parent_wait = [] + parent_agg = [] + parent_total = [] + recalls = [] for qi, q in enumerate(queries): res = idx.search(q.unsqueeze(0).float(), k, **search_kw) ti = res.timing_info - # latency - if hasattr(ti, "total_time_ns"): - latencies.append(ti.total_time_ns / 1e6) + + # child latency + child_lats.append(ti.total_time_ns / 1e6) + child_buf_init.append(ti.buffer_init_time_ns) + child_enq.append( ti.job_enqueue_time_ns) + child_wait.append( ti.job_wait_time_ns) + child_agg.append( ti.result_aggregate_time_ns) + child_total.append( ti.total_time_ns) + + # parent latency (if exists) + pi = getattr(ti, "parent_info", None) + if pi and hasattr(pi, "total_time_ns"): + parent_lats.append(pi.total_time_ns / 1e6) + parent_buf_init.append(pi.buffer_init_time_ns) + parent_enq.append( pi.job_enqueue_time_ns) + parent_wait.append( pi.job_wait_time_ns) + parent_agg.append( pi.result_aggregate_time_ns) + parent_total.append( pi.total_time_ns) else: - raise RuntimeError("missing total_time_ns") + parent_lats.append(0.0) + parent_buf_init.append(0) + parent_enq.append(0) + parent_wait.append(0) + parent_agg.append(0) + parent_total.append(0) + # recall on first trial only if t == 0 and gt is not None: preds = extract_ids(res)[0] recalls.append(float(compute_recall(torch.tensor([preds]), gt[qi:qi+1], k).item())) - # collect timers (ns) - buf_init_q.append(ti.buffer_init_time_ns) - enq_q.append (ti.job_enqueue_time_ns) - wait_q.append (ti.job_wait_time_ns) - agg_q.append (ti.result_aggregate_time_ns) - total_q.append (ti.total_time_ns) - - # trial means in ms - all_trial_latencies.append(np.mean(latencies)) - buf_init_trials.append(np.mean(buf_init_q) / 1e6) - enqueue_trials .append(np.mean(enq_q) / 1e6) - wait_trials .append(np.mean(wait_q) / 1e6) - agg_trials .append(np.mean(agg_q) / 1e6) - total_trials .append(np.mean(total_q) / 1e6) + # compute trial means + child_lat_trials.append(np.mean(child_lats)) + parent_lat_trials.append(np.mean(parent_lats)) + child_buf_init_trials.append(np.mean(child_buf_init)/1e6) + child_enq_trials .append(np.mean(child_enq) /1e6) + child_wait_trials .append(np.mean(child_wait) /1e6) + child_agg_trials .append(np.mean(child_agg) /1e6) + child_total_trials .append(np.mean(child_total) /1e6) + parent_buf_init_trials.append(np.mean(parent_buf_init)/1e6) + parent_enq_trials .append(np.mean(parent_enq) /1e6) + parent_wait_trials .append(np.mean(parent_wait) /1e6) + parent_agg_trials .append(np.mean(parent_agg) /1e6) + parent_total_trials .append(np.mean(parent_total) /1e6) if t == 0 and recalls: - all_trial_recalls.append(np.mean(recalls)) + first_trial_recalls.append(np.mean(recalls)) print(f" [{name} trial {t+1}/{trials}] " - f"{all_trial_latencies[-1]:.2f} ms" - + (f" | R@{k} {all_trial_recalls[-1]:.4f}" if recalls else "")) + f"child {child_lat_trials[-1]:.2f} ms, " + f"parent {parent_lat_trials[-1]:.2f} ms" + + (f" | R@{k} {first_trial_recalls[-1]:.4f}" if recalls else "")) - # final averages across trials + # assemble final row row = { "index": name, "n_workers": b_params.get("num_workers", np.nan), - "mean_latency_ms": float(np.mean(all_trial_latencies)), - "std_latency_ms": float(np.std(all_trial_latencies)), - f"recall_at_{k}": (float(all_trial_recalls[0]) if all_trial_recalls else np.nan), - "buffer_init_ms": float(np.mean(buf_init_trials)), - "enqueue_ms": float(np.mean(enqueue_trials)), - "wait_ms": float(np.mean(wait_trials)), - "aggregate_ms": float(np.mean(agg_trials)), - "total_time_ms": float(np.mean(total_trials)), + "child_mean_latency_ms": float(np.mean(child_lat_trials)), + "child_std_latency_ms": float(np.std(child_lat_trials)), + f"recall_at_{k}": (float(first_trial_recalls[0]) if first_trial_recalls else np.nan), + "child_buffer_init_ms": float(np.mean(child_buf_init_trials)), + "child_enqueue_ms": float(np.mean(child_enq_trials)), + "child_wait_ms": float(np.mean(child_wait_trials)), + "child_aggregate_ms": float(np.mean(child_agg_trials)), + "child_total_time_ms": float(np.mean(child_total_trials)), + "parent_mean_latency_ms":float(np.mean(parent_lat_trials)), + "parent_buffer_init_ms": float(np.mean(parent_buf_init_trials)), + "parent_enqueue_ms": float(np.mean(parent_enq_trials)), + "parent_wait_ms": float(np.mean(parent_wait_trials)), + "parent_aggregate_ms": float(np.mean(parent_agg_trials)), + "parent_total_time_ms": float(np.mean(parent_total_trials)), } results.append(row) pd.DataFrame([row]).to_csv(idx_csv, index=False) @@ -233,7 +267,7 @@ def run_experiment(cfg_path: str, output_dir: str) -> None: df.to_csv(out_csv, index=False) print(f"\n[RESULT] aggregated CSV → {out_csv}") - # latency plot + # latency plot (child only for clarity) plt.figure() for nm in df["index"].unique(): sub = df[df["index"] == nm] @@ -241,16 +275,16 @@ def run_experiment(cfg_path: str, output_dir: str) -> None: else f"{nm} (nw={int(sub['n_workers'].iloc[0])})") plt.errorbar( sub["n_workers"] if "n_workers" in sub else sub.index, - sub["mean_latency_ms"], - yerr=sub["std_latency_ms"], + sub["child_mean_latency_ms"], + yerr=sub["child_std_latency_ms"], marker="o", capsize=5, label=lbl ) plt.xscale("symlog", base=2) - plt.xlabel("Num Workers"); plt.ylabel("Mean Latency (ms)") - plt.title("Single-Query Latency"); plt.legend(); plt.tight_layout() - lat_path = Path(output_dir) / f"{out_csv.stem}_latency.png" + plt.xlabel("Num Workers"); plt.ylabel("Mean Child Latency (ms)") + plt.title("Single-Query Child Latency"); plt.legend(); plt.tight_layout() + lat_path = Path(output_dir) / f"{out_csv.stem}_child_latency.png" plt.savefig(lat_path) - print(f"[PLOT] latency plot → {lat_path}") + print(f"[PLOT] child latency plot → {lat_path}") # recall plot if f"recall_at_{k}" in df.columns: From 6b7c586a6a166fb40ded1641b4d966acbc55e792 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 13:59:28 -0500 Subject: [PATCH 123/323] track parent timing info --- src/cpp/include/list_scanning.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index b41831ca..29aa898a 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -418,8 +418,8 @@ inline void batched_scan_list(const float *query_vecs, bool alloc_results = false; if (distances == nullptr) { alloc_results = true; - (int64_t *) malloc(num_queries * k_max * sizeof(int64_t)); - (float *) malloc(num_queries * k_max * sizeof(float)); + labels = (int64_t *) malloc(num_queries * k_max * sizeof(int64_t)); + distances = (float *) malloc(num_queries * k_max * sizeof(float)); } if (metric == faiss::METRIC_INNER_PRODUCT) { From ce7671fc2119d6c2a88ee7cee9715d6d3b96e499 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 14:04:02 -0500 Subject: [PATCH 124/323] track parent timing info --- src/cpp/src/query_coordinator.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index d141b4c1..a012121b 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -815,11 +815,6 @@ shared_ptr QueryCoordinator::search(Tensor x, shared_ptrrecompute_threshold = search_params->recompute_threshold; parent_search_params->initial_search_fraction = .5; parent_search_params->batched_scan = false; - - // check if parent is flat - if (parent_->parent_ == nullptr) { - parent_search_params->batched_scan = true; - } } else { parent_search_params = search_params->parent_params; } From ae70dfb608edcafa1f2365ce7c2a350be772ef66 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 14:28:26 -0500 Subject: [PATCH 125/323] track parent timing info --- src/cpp/src/quake_index.cpp | 8 +++++++- src/cpp/src/query_coordinator.cpp | 1 - 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/cpp/src/quake_index.cpp b/src/cpp/src/quake_index.cpp index 43bb6955..637f0036 100644 --- a/src/cpp/src/quake_index.cpp +++ b/src/cpp/src/quake_index.cpp @@ -281,7 +281,13 @@ void QuakeIndex::load(const std::string& dir_path, int n_workers, bool use_numa) std::string parent_dir = (fs::path(dir_path) / "parent").string(); if (fs::exists(parent_dir) && fs::is_directory(parent_dir)) { parent_ = std::make_shared(); - parent_->load(parent_dir, n_workers, use_numa); + int n_parts = partition_manager_->nlist(); + + // don't put too many parent workers. maximum of 1 worker per 500 partitions + int parent_n_workers = std::max(1, n_parts / 500); + parent_n_workers = std::min(parent_n_workers, n_workers); + + parent_->load(parent_dir, parent_n_workers, use_numa); partition_manager_->parent_ = parent_; } else { parent_ = nullptr; diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index a012121b..8fc70fc1 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -109,7 +109,6 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { auto job_wait_start = std::chrono::high_resolution_clock::now(); int64_t job_id; -// res.job_queue.wait_dequeue(job_id); while (!res.job_queue.try_dequeue(job_id)) { std::this_thread::sleep_for(std::chrono::microseconds(5)); } From 3104de9f108b3394cf77a8753f26d678d5b6aee7 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 14:55:19 -0500 Subject: [PATCH 126/323] reduce allocation cost of scan jobs --- src/cpp/include/query_coordinator.h | 2 +- src/cpp/src/query_coordinator.cpp | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 317e3256..c7ed1da6 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -24,7 +24,7 @@ struct ScanJob { int64_t partition_id; ///< The identifier of the partition to be scanned. int k; ///< The number of neighbors (Top-K) to return. const float* query_vector; ///< Pointer to the query vector. - vector query_ids; ///< Global query IDs; used in batched mode. + int *query_ids; ///< Global query IDs; used in batched mode. bool is_batched = false; ///< Indicates whether this is a batched query job. int64_t num_queries = 0; ///< The number of queries in batched mode. int rank = 0; ///< Rank of the partition diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 8fc70fc1..cb3d6af0 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -375,6 +375,8 @@ shared_ptr QueryCoordinator::worker_scan( duration_cast(end_time - start_time).count(); start_time = high_resolution_clock::now(); + vector all_query_ids = std::vector(x.size(0)); + std::iota(all_query_ids.begin(), all_query_ids.end(), 0); if (search_params->batched_scan) { auto partition_ids_accessor = partition_ids.accessor(); job_buffer_.resize(partition_manager_->nlist()); @@ -382,10 +384,6 @@ shared_ptr QueryCoordinator::worker_scan( auto pids_acc = pids.accessor(); if (pids.size(0) == partition_ids.size(1)) { - vector all_query_ids = std::vector(x.size(0)); - std::iota(all_query_ids.begin(), all_query_ids.end(), 0); - - for (int64_t i = 0; i < pids.size(0); i++) { ScanJob job; job.is_batched = true; @@ -393,7 +391,7 @@ shared_ptr QueryCoordinator::worker_scan( job.k = k; job.query_vector = x.data_ptr(); job.num_queries = x.size(0); - job.query_ids = all_query_ids; + job.query_ids = all_query_ids.data(); int core_id = partition_manager_->get_partition_core_id(pids_acc[i]); if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); @@ -404,7 +402,7 @@ shared_ptr QueryCoordinator::worker_scan( } } else { - std::unordered_map> per_partition_query_ids; + std::unordered_map> per_partition_query_ids; for (int64_t q = 0; q < num_queries; q++) { for (int64_t p = 0; p < partition_ids.size(1); p++) { int64_t pid = partition_ids_accessor[q][p]; @@ -419,7 +417,7 @@ shared_ptr QueryCoordinator::worker_scan( job.k = k; job.query_vector = x.data_ptr(); job.num_queries = kv.second.size(); - job.query_ids = kv.second; + job.query_ids = kv.second.data(); int core_id = partition_manager_->get_partition_core_id(kv.first); if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); @@ -440,7 +438,7 @@ shared_ptr QueryCoordinator::worker_scan( ScanJob job; job.is_batched = false; - job.query_ids = {q}; + job.query_ids = all_query_ids.data() + q; job.partition_id = pid; job.k = k; job.query_vector = x_ptr + q * dimension; From 3d2354b308e80aeac21a50b0eddf6a7b836583db Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 15:17:43 -0500 Subject: [PATCH 127/323] reduce allocation cost of scan jobs --- src/cpp/src/query_coordinator.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index cb3d6af0..ce5bc667 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -330,7 +330,6 @@ shared_ptr QueryCoordinator::worker_scan( auto partition_ids_accessor = partition_ids.accessor(); - job_buffer_.clear(); next_job_id_.store(0); job_flags_.clear(); @@ -376,6 +375,7 @@ shared_ptr QueryCoordinator::worker_scan( start_time = high_resolution_clock::now(); vector all_query_ids = std::vector(x.size(0)); + std::unordered_map> per_partition_query_ids; // for batched scan std::iota(all_query_ids.begin(), all_query_ids.end(), 0); if (search_params->batched_scan) { auto partition_ids_accessor = partition_ids.accessor(); @@ -402,7 +402,6 @@ shared_ptr QueryCoordinator::worker_scan( } } else { - std::unordered_map> per_partition_query_ids; for (int64_t q = 0; q < num_queries; q++) { for (int64_t p = 0; p < partition_ids.size(1); p++) { int64_t pid = partition_ids_accessor[q][p]; From 198f2429c875c540844bb9aea93056a6fcde8b04 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 15:37:20 -0500 Subject: [PATCH 128/323] reduce allocation cost of scan jobs --- src/cpp/include/query_coordinator.h | 3 +- src/cpp/src/query_coordinator.cpp | 49 ++++++++++++++++++----------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index c7ed1da6..e7898939 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -24,7 +24,8 @@ struct ScanJob { int64_t partition_id; ///< The identifier of the partition to be scanned. int k; ///< The number of neighbors (Top-K) to return. const float* query_vector; ///< Pointer to the query vector. - int *query_ids; ///< Global query IDs; used in batched mode. + std::shared_ptr> query_ids; ///< Global query IDs; used in batched mode. + int query_id; bool is_batched = false; ///< Indicates whether this is a batched query job. int64_t num_queries = 0; ///< The number of queries in batched mode. int rank = 0; ///< Rank of the partition diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index ce5bc667..593b1334 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -127,12 +127,12 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { ScanJob job = job_buffer_[job_id]; - // Ignore this job if the global buffer is not processing queries. - if (!global_topk_buffer_pool_[job.query_ids[0]]->currently_processing_query()) { - // decrement the job counter - global_topk_buffer_pool_[job.query_ids[0]]->record_empty_job(); - continue; - } +// // Ignore this job if the global buffer is not processing queries. +// if (!global_topk_buffer_pool_[job.query_ids[0]]->currently_processing_query()) { +// // decrement the job counter +// global_topk_buffer_pool_[job.query_ids[0]]->record_empty_job(); +// continue; +// } worker_job_counter_[core_index]++; @@ -153,10 +153,17 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { if (partition_size == 0) { std::cerr << "[QueryCoordinator::partition_scan_worker_fn] Partition " << job.partition_id << " is empty." << std::endl; // call dummy batch add to decrement topk_buffer jobs counter. #TODO remove jobs counter from topk_buffer - for (int64_t q = 0; q < job.num_queries; q++) { - int64_t global_q = job.query_ids[q]; - global_topk_buffer_pool_[global_q]->batch_add(nullptr, nullptr, 0); + + if (job.is_batched) { + for (int64_t q = 0; q < job.num_queries; q++) { + int global_q = job.query_ids->at(q); + global_topk_buffer_pool_[global_q]->batch_add(nullptr, nullptr, 0); + } + } else { + global_topk_buffer_pool_[job.query_id]->batch_add(nullptr, nullptr, 0); } + + continue; } @@ -196,8 +203,8 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { int64_t n_results = topk_indices.size(); // Merge local results into the global query buffer. - global_topk_buffer_pool_[job.query_ids[0]]->batch_add(topk.data(), topk_indices.data(), n_results); - job_flags_[job.query_ids[0]][job.rank] = true; + global_topk_buffer_pool_[job.query_id]->batch_add(topk.data(), topk_indices.data(), n_results); + job_flags_[job.query_id][job.rank] = true; auto s4 = std::chrono::high_resolution_clock::now(); @@ -225,7 +232,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { int64_t d = partition_manager_->d(); std::vector query_subset(job.num_queries * d); for (int i = 0; i < job.num_queries; i++) { - int64_t global_q = job.query_ids[i]; + int64_t global_q = job.query_ids->at(i); memcpy(&query_subset[i * d], job.query_vector + global_q * d, d * sizeof(float)); @@ -265,7 +272,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { auto s3 = std::chrono::high_resolution_clock::now(); for (int64_t q = 0; q < job.num_queries; q++) { - int64_t global_q = job.query_ids[q]; + int64_t global_q = job.query_ids->at(q); vector topk = res.topk_buffer_pool[q]->get_topk(); vector topk_indices = res.topk_buffer_pool[q]->get_topk_indices(); @@ -375,7 +382,8 @@ shared_ptr QueryCoordinator::worker_scan( start_time = high_resolution_clock::now(); vector all_query_ids = std::vector(x.size(0)); - std::unordered_map> per_partition_query_ids; // for batched scan + shared_ptr> all_query_ids_ptr = make_shared>(all_query_ids); + std::unordered_map>> per_partition_query_ids; // for batched scan std::iota(all_query_ids.begin(), all_query_ids.end(), 0); if (search_params->batched_scan) { auto partition_ids_accessor = partition_ids.accessor(); @@ -391,7 +399,7 @@ shared_ptr QueryCoordinator::worker_scan( job.k = k; job.query_vector = x.data_ptr(); job.num_queries = x.size(0); - job.query_ids = all_query_ids.data(); + job.query_ids = all_query_ids_ptr; int core_id = partition_manager_->get_partition_core_id(pids_acc[i]); if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); @@ -406,7 +414,10 @@ shared_ptr QueryCoordinator::worker_scan( for (int64_t p = 0; p < partition_ids.size(1); p++) { int64_t pid = partition_ids_accessor[q][p]; if (pid < 0) continue; - per_partition_query_ids[pid].push_back(q); + if (per_partition_query_ids[pid] == nullptr) { + per_partition_query_ids[pid] = make_shared>(); + } + per_partition_query_ids[pid]->push_back(q); } } for (auto &kv : per_partition_query_ids) { @@ -415,8 +426,8 @@ shared_ptr QueryCoordinator::worker_scan( job.partition_id = kv.first; job.k = k; job.query_vector = x.data_ptr(); - job.num_queries = kv.second.size(); - job.query_ids = kv.second.data(); + job.num_queries = kv.second->size(); + job.query_ids = kv.second; int core_id = partition_manager_->get_partition_core_id(kv.first); if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); @@ -437,7 +448,7 @@ shared_ptr QueryCoordinator::worker_scan( ScanJob job; job.is_batched = false; - job.query_ids = all_query_ids.data() + q; + job.query_id = q; job.partition_id = pid; job.k = k; job.query_vector = x_ptr + q * dimension; From aa60b9ca48cec2f1660b86383b811ca7a9eeea5b Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 15:45:16 -0500 Subject: [PATCH 129/323] reduce allocation cost of scan jobs --- src/cpp/src/query_coordinator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 593b1334..7924b607 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -337,7 +337,7 @@ shared_ptr QueryCoordinator::worker_scan( auto partition_ids_accessor = partition_ids.accessor(); - job_buffer_.clear(); +// job_buffer_.clear(); next_job_id_.store(0); job_flags_.clear(); job_flags_.resize(num_queries); From 698f6de539d8571e217cb07b9b5d83e4f72932d5 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 15:50:06 -0500 Subject: [PATCH 130/323] reduce allocation cost of scan jobs --- src/cpp/src/query_coordinator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 7924b607..25790a08 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -461,11 +461,12 @@ shared_ptr QueryCoordinator::worker_scan( } size_t jid = next_job_id_.fetch_add(1, std::memory_order_acq_rel); job_buffer_[jid] = job; + end_time = high_resolution_clock::now(); core_resources_[core_id].job_queue.enqueue((int64_t) jid); } } } - end_time = high_resolution_clock::now(); + timing_info->job_enqueue_time_ns = duration_cast(end_time - start_time).count(); auto last_flush_time = high_resolution_clock::now(); From 46f2627a33e601aaf7ce2c8df89f6953db2cb28f Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 15:56:11 -0500 Subject: [PATCH 131/323] reduce allocation cost of scan jobs --- src/cpp/src/query_coordinator.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 25790a08..76529279 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -381,10 +381,7 @@ shared_ptr QueryCoordinator::worker_scan( duration_cast(end_time - start_time).count(); start_time = high_resolution_clock::now(); - vector all_query_ids = std::vector(x.size(0)); - shared_ptr> all_query_ids_ptr = make_shared>(all_query_ids); - std::unordered_map>> per_partition_query_ids; // for batched scan - std::iota(all_query_ids.begin(), all_query_ids.end(), 0); + if (search_params->batched_scan) { auto partition_ids_accessor = partition_ids.accessor(); job_buffer_.resize(partition_manager_->nlist()); @@ -392,6 +389,9 @@ shared_ptr QueryCoordinator::worker_scan( auto pids_acc = pids.accessor(); if (pids.size(0) == partition_ids.size(1)) { + vector all_query_ids = std::vector(x.size(0)); + std::iota(all_query_ids.begin(), all_query_ids.end(), 0); + shared_ptr> all_query_ids_ptr = make_shared>(all_query_ids); for (int64_t i = 0; i < pids.size(0); i++) { ScanJob job; job.is_batched = true; @@ -410,6 +410,7 @@ shared_ptr QueryCoordinator::worker_scan( } } else { + std::unordered_map>> per_partition_query_ids; // for batched scan for (int64_t q = 0; q < num_queries; q++) { for (int64_t p = 0; p < partition_ids.size(1); p++) { int64_t pid = partition_ids_accessor[q][p]; @@ -441,6 +442,7 @@ shared_ptr QueryCoordinator::worker_scan( auto partition_ids_accessor = partition_ids.accessor(); job_buffer_.resize(num_queries * partition_ids.size(1)); + vector job_ids for (int q = 0; q < num_queries; q++) { for (int64_t p = 0; p < partition_ids.size(1); p++) { int64_t pid = partition_ids_accessor[q][p]; @@ -461,12 +463,11 @@ shared_ptr QueryCoordinator::worker_scan( } size_t jid = next_job_id_.fetch_add(1, std::memory_order_acq_rel); job_buffer_[jid] = job; - end_time = high_resolution_clock::now(); core_resources_[core_id].job_queue.enqueue((int64_t) jid); } } } - + end_time = high_resolution_clock::now(); timing_info->job_enqueue_time_ns = duration_cast(end_time - start_time).count(); auto last_flush_time = high_resolution_clock::now(); From c414bf59ecd6cdc0d4e8e5679d2d624faf468a9f Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 15:56:29 -0500 Subject: [PATCH 132/323] reduce allocation cost of scan jobs --- src/cpp/src/query_coordinator.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 76529279..5bed1991 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -442,7 +442,6 @@ shared_ptr QueryCoordinator::worker_scan( auto partition_ids_accessor = partition_ids.accessor(); job_buffer_.resize(num_queries * partition_ids.size(1)); - vector job_ids for (int q = 0; q < num_queries; q++) { for (int64_t p = 0; p < partition_ids.size(1); p++) { int64_t pid = partition_ids_accessor[q][p]; From a4a406114d3fe7c12db30908738d883557277ec1 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 16:01:29 -0500 Subject: [PATCH 133/323] reduce allocation cost of scan jobs --- src/cpp/src/query_coordinator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 5bed1991..86ceb4a8 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -461,8 +461,8 @@ shared_ptr QueryCoordinator::worker_scan( throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } size_t jid = next_job_id_.fetch_add(1, std::memory_order_acq_rel); - job_buffer_[jid] = job; - core_resources_[core_id].job_queue.enqueue((int64_t) jid); + job_buffer_[jid] = std::move(job); + core_resources_[core_id].job_queue.enqueue(jid); } } } From 67707da7f9dd02121efdc8b4a3ef6a70be2609b4 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 16:02:00 -0500 Subject: [PATCH 134/323] reduce allocation cost of scan jobs --- src/cpp/src/query_coordinator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 86ceb4a8..cb4e75eb 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -442,6 +442,7 @@ shared_ptr QueryCoordinator::worker_scan( auto partition_ids_accessor = partition_ids.accessor(); job_buffer_.resize(num_queries * partition_ids.size(1)); + int jid = 0; for (int q = 0; q < num_queries; q++) { for (int64_t p = 0; p < partition_ids.size(1); p++) { int64_t pid = partition_ids_accessor[q][p]; @@ -460,8 +461,8 @@ shared_ptr QueryCoordinator::worker_scan( if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } - size_t jid = next_job_id_.fetch_add(1, std::memory_order_acq_rel); job_buffer_[jid] = std::move(job); + jid++; core_resources_[core_id].job_queue.enqueue(jid); } } From b31bf25400dfe6a339eaec4a9caa5c1a476f734d Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 16:04:15 -0500 Subject: [PATCH 135/323] reduce allocation cost of scan jobs --- src/cpp/src/query_coordinator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index cb4e75eb..f1f3a4a0 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -462,8 +462,8 @@ shared_ptr QueryCoordinator::worker_scan( throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } job_buffer_[jid] = std::move(job); - jid++; core_resources_[core_id].job_queue.enqueue(jid); + jid++; } } } From 352417ceb5b0d55d95271cc920b3a2a661134b03 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 16:21:55 -0500 Subject: [PATCH 136/323] reduce allocation cost of scan jobs --- src/cpp/src/query_coordinator.cpp | 3 +- test/cpp/scan_benchmark.cpp | 469 ++++++++++++++++-------------- 2 files changed, 248 insertions(+), 224 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index f1f3a4a0..c1b6d46c 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -442,6 +442,7 @@ shared_ptr QueryCoordinator::worker_scan( auto partition_ids_accessor = partition_ids.accessor(); job_buffer_.resize(num_queries * partition_ids.size(1)); + auto partitions = partition_manager_->partition_store_->partitions_; int jid = 0; for (int q = 0; q < num_queries; q++) { for (int64_t p = 0; p < partition_ids.size(1); p++) { @@ -457,7 +458,7 @@ shared_ptr QueryCoordinator::worker_scan( job.num_queries = 1; job.rank = p; - int core_id = partition_manager_->get_partition_core_id(pid); + int core_id = partitions[pid]->core_id_; if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } diff --git a/test/cpp/scan_benchmark.cpp b/test/cpp/scan_benchmark.cpp index a029c0fa..df2b467c 100644 --- a/test/cpp/scan_benchmark.cpp +++ b/test/cpp/scan_benchmark.cpp @@ -1,241 +1,264 @@ -#include -// #include // OpenMP no longer used for the primary parallelization -#include +#include #include #include -#include +#include #include -#include -#include -#include -#include // For std::mutex and std::call_once -#include // For std::thread::hardware_concurrency -#include // For std::async, std::future (used by parallel.h) -#include -#include "faiss/utils/distances.h" -#include "parallel.h" // Include your custom parallel_for header - -// ------------------------------------------------------------------ -// Constants -// ------------------------------------------------------------------ -static constexpr int64_t LIST_SIZE = 1'000'000; -static constexpr int D = 128; -static constexpr int NQ = 100; // Number of queries - -// Forward declaration of the fixture -class ListScanBenchmarkF; - -// ------------------------------------------------------------------ -// Timing helper -// ------------------------------------------------------------------ -struct Timer { - using clk = std::chrono::steady_clock; - clk::time_point t0; - void start() { t0 = clk::now(); } - double stop() { return std::chrono::duration(clk::now()-t0).count(); } -}; - -// ------------------------------------------------------------------ -// Pretty printer -// ------------------------------------------------------------------ -// Takes requested threads (nth_req) and actual threads used by parallel_for (pfor_threads) -static void print_stats(const char* label, int nth_req, double sec) -{ - const double evaluations = static_cast(LIST_SIZE) * NQ; - const double bytes_scanned = evaluations * D * sizeof(float); - const double gb_scanned = bytes_scanned / (1ULL << 30); - const double gb_per_sec = gb_scanned / sec; - - std::cout << std::setw(24) << std::left << label - << " | " << std::setw(2) << nth_req - << " | " << std::fixed << std::setprecision(3) - << sec << " s" - << " | " << std::setprecision(2) - << gb_per_sec << " GB/s" - << std::endl; -} - -// ================================================================== -// Google‑test Test Fixture -// ================================================================== -class ListScanBenchmarkF : public ::testing::Test { -protected: - // Data members are static members of the fixture - static std::vector S_base_vectors_data; - static std::vector S_queries_data; - static std::vector S_seq_order_data; - static std::vector S_rnd_order_data; - - // Flags for std::call_once, also static members - static std::once_flag base_vectors_flag; - static std::once_flag queries_flag; - static std::once_flag seq_order_flag; - static std::once_flag rnd_order_flag; - - static void initialize_base_vectors() { - std::call_once(base_vectors_flag, []{ - S_base_vectors_data.resize(LIST_SIZE * D); - std::mt19937 rng(123); - std::normal_distribution nd(0.f, 1.f); - for (float& v : S_base_vectors_data) v = nd(rng); - }); - } +#include // For std::iota +#include // For std::fixed, std::setprecision +#include // For std::thread +#include // For std::atomic + +#include // Assuming torch is available +#include "concurrentqueue.h" // Assuming moodycamel's queue header is findable + +using namespace std::chrono; +using torch::Tensor; + +// Namespace for this specific microbenchmark's helpers +namespace JobEnqueueMicrobenchmarkWithContention { + +// --- Struct Definitions (ScanJob, CoreResources, MockPartitionManager - same as before) --- + struct ScanJob { + int64_t partition_id; + int k_val; + const float* query_vector; + int query_id; + bool is_batched = false; + int64_t num_queries_in_job = 0; + int rank = 0; + + ScanJob() = default; + ScanJob(ScanJob&& other) noexcept = default; + ScanJob& operator=(ScanJob&& other) noexcept = default; + ScanJob(const ScanJob&) = delete; + ScanJob& operator=(const ScanJob&) = delete; + }; + + struct CoreResources { + int core_id_val; + moodycamel::ConcurrentQueue job_queue; + // For worker thread to count its dequeued items: + std::atomic dequeued_items_by_worker{0}; + + + // Explicitly define constructors for clarity if needed, + // or rely on aggregate initialization / default members. + CoreResources() : core_id_val(-1), job_queue(), dequeued_items_by_worker(0) {} // Default + CoreResources(int id) : core_id_val(id), job_queue(), dequeued_items_by_worker(0) {} // With ID + + // Since moodycamel::ConcurrentQueue is not copyable, + // CoreResources becomes non-copyable. We need move semantics. + CoreResources(CoreResources&& other) noexcept + : core_id_val(other.core_id_val), + job_queue(std::move(other.job_queue)), // Moodycamel queue is movable + dequeued_items_by_worker(other.dequeued_items_by_worker.load()) + {} + + CoreResources& operator=(CoreResources&& other) noexcept { + if (this != &other) { + core_id_val = other.core_id_val; + job_queue = std::move(other.job_queue); + dequeued_items_by_worker.store(other.dequeued_items_by_worker.load()); + } + return *this; + } + // Delete copy operations + CoreResources(const CoreResources&) = delete; + CoreResources& operator=(const CoreResources&) = delete; + }; - static void initialize_queries() { - std::call_once(queries_flag, []{ - S_queries_data.resize(NQ * D); - std::mt19937 rng(321); - std::normal_distribution nd(0.f, 1.f); - for (float& v : S_queries_data) v = nd(rng); - }); - } - static void initialize_seq_order() { - std::call_once(seq_order_flag, []{ - S_seq_order_data.resize(LIST_SIZE); - std::iota(S_seq_order_data.begin(), S_seq_order_data.end(), 0); - }); + class MockPartitionManager { + public: + int num_cores_manager_ = 1; + MockPartitionManager(int cores) : num_cores_manager_(cores) { + if (cores <= 0) num_cores_manager_ = 1; + } + int get_partition_core_id(int64_t pid) const { + return static_cast(pid % num_cores_manager_); + } + }; + +// --- Parameters --- + static const int64_t BENCH_DIMENSION = 128; + static const int BENCH_K = 10; + static const int BENCH_NUM_CORES = 4; // Number of worker threads and queues + +// --- Worker Thread Function --- + void dequeuing_worker_function(CoreResources& core_res, std::atomic& stop_signal) { + long items_this_worker = 0; + int64_t job_id_val; // Renamed to avoid conflict + + while (!stop_signal.load(std::memory_order_acquire)) { + if (core_res.job_queue.try_dequeue(job_id_val)) { + items_this_worker++; + // Simulate minimal work with the job_id_val if needed + volatile int64_t sink = job_id_val; // "Use" job_id_val + (void)sink; + } else { + // Yield if the queue is often empty to reduce busy-waiting, + // though try_dequeue is quite efficient. + std::this_thread::yield(); + } + } + // After stop_signal is true, drain any remaining items from the queue + while (core_res.job_queue.try_dequeue(job_id_val)) { + items_this_worker++; + volatile int64_t sink = job_id_val; + (void)sink; + } + core_res.dequeued_items_by_worker.fetch_add(items_this_worker, std::memory_order_relaxed); } - static void initialize_rnd_order() { - std::call_once(rnd_order_flag, []{ - S_rnd_order_data.resize(LIST_SIZE); - std::iota(S_rnd_order_data.begin(), S_rnd_order_data.end(), 0); - std::mt19937 rng(999); - std::shuffle(S_rnd_order_data.begin(), S_rnd_order_data.end(), rng); - }); - } -public: - // Kernel now uses the custom parallel_for for the inner loop (scanning list_size) - // It returns the sum of minimum distances found for each query (for anti-optimization) - static float static_scan_kernel(const std::vector& order, int n_threads_requested) +// --- Function with the snippet to benchmark (Updated jid logic) --- + int run_job_creation_and_enqueue_snippet( + std::vector& job_buffer, + std::vector& core_resources_list, + const MockPartitionManager& partition_manager, + const Tensor& partition_ids_tensor, + const float* x_ptr, + long num_queries, + long num_partitions_per_query, + int k_param, + int dimension_param) { - const float* base_ptr = S_base_vectors_data.data(); - const float* query_ptr = S_queries_data.data(); + auto partition_ids_accessor = partition_ids_tensor.accessor(); + job_buffer.resize(num_queries * num_partitions_per_query); // Max possible + int jid = 0; // Current index for job_buffer, also basis for enqueued ID + + for (long q = 0; q < num_queries; q++) { + for (long p = 0; p < num_partitions_per_query; p++) { + int64_t pid_val = partition_ids_accessor[q][p]; + if (pid_val == -1) continue; + + ScanJob job_item; + job_item.is_batched = false; + job_item.query_id = static_cast(q); + job_item.partition_id = pid_val; + job_item.k_val = k_param; + job_item.query_vector = x_ptr + q * dimension_param; + job_item.num_queries_in_job = 1; + job_item.rank = static_cast(p); + + int core_id = partition_manager.get_partition_core_id(pid_val); + + // Original snippet logic: place job, THEN increment jid, THEN enqueue the NEW jid. + job_buffer[jid] = std::move(job_item); + jid++; // jid is now the 1-based count of jobs created, or index for the *next* job. + core_resources_list[core_id].job_queue.enqueue(jid); // Enqueue this 1-based count. + } + } + return jid; // Returns the total count of jobs created (which is the last enqueued jid value) + } - volatile float total_min_sum = 0.f; // Accumulates min distance for each query - // Determine the actual number of threads parallel_for will aim to use - int threads_for_pfor = n_threads_requested; - if (threads_for_pfor <= 0) { - threads_for_pfor = static_cast(std::thread::hardware_concurrency()); +// --- GTest TEST Case with Contention --- + TEST(JobEnqueueMicrobenchmark, SnippetPerformanceWithContention) { + long num_queries_test = 100; // Increase for more work: e.g., 1000 + long num_partitions_test = 1000; // Increase for more work: e.g., 1000 + int test_iterations = 5; + int warmup_iterations = 1; + + std::cout << std::endl << "[JobEnqueueMicrobenchmark::SnippetPerformanceWithContention]" << std::endl; + std::cout << " Config: Queries=" << num_queries_test + << ", Partitions/Query=" << num_partitions_test + << ", Iterations=" << test_iterations + << ", Worker Threads=" << BENCH_NUM_CORES << std::endl; + + // 1. Setup data structures + std::vector local_job_buffer; + std::vector local_core_resources; + local_core_resources.reserve(BENCH_NUM_CORES); + for (int i = 0; i < BENCH_NUM_CORES; ++i) { + local_core_resources.emplace_back(i); // Use constructor CoreResources(int id) } - if (threads_for_pfor == 0) { // Safety for hardware_concurrency returning 0 - threads_for_pfor = 1; + JobEnqueueMicrobenchmarkWithContention::MockPartitionManager local_partition_manager(BENCH_NUM_CORES); + + std::vector local_queries_data_storage(num_queries_test * BENCH_DIMENSION); + float* local_x_ptr = local_queries_data_storage.data(); + Tensor local_partition_ids_tensor = torch::empty({num_queries_test, num_partitions_test}, torch::TensorOptions().dtype(torch::kInt64)); + auto accessor = local_partition_ids_tensor.accessor(); + for (long i = 0; i < num_queries_test; ++i) { + for (long j = 0; j < num_partitions_test; ++j) { + accessor[i][j] = i * num_partitions_test + j; + } } - float distances[LIST_SIZE]; // Distances for the current query - - // Outer loop over queries (sequential) - for (int qi = 0; qi < NQ; ++qi) { - const float* current_query_vector = query_ptr + qi * D; - - // Inner loop (over base vectors for the current query) is parallelized - // The 'order' vector contains indices into 'S_base_vectors_data' - // 'k' will be an index from 0 to order.size()-1 - parallel_for(static_cast(0), static_cast(order.size()), - [&](int64_t k) { // k is the index in the range [0, order.size()) - int64_t base_vector_original_idx = order[k]; - const float* current_base_vector = base_ptr + base_vector_original_idx * D; - - distances[k] = faiss::fvec_L2sqr(current_query_vector, current_base_vector, static_cast(D)); - }, - threads_for_pfor // Pass the determined number of threads to parallel_for - ); + std::vector durations_ms; + durations_ms.reserve(test_iterations); + long total_jobs_actually_created = 0; + + + // 2. Run benchmark loop + for (int iter = 0; iter < test_iterations + warmup_iterations; ++iter) { + // Reset/drain queues and worker counts for each iteration + for (auto& cr : local_core_resources) { + int64_t dummy_val; + while (cr.job_queue.try_dequeue(dummy_val)); + cr.dequeued_items_by_worker.store(0, std::memory_order_relaxed); + } + local_job_buffer.clear(); + + std::atomic stop_worker_threads_signal{false}; + std::vector worker_threads; + worker_threads.reserve(BENCH_NUM_CORES); + + // Launch worker threads + for (int i = 0; i < BENCH_NUM_CORES; ++i) { + worker_threads.emplace_back(dequeuing_worker_function, std::ref(local_core_resources[i]), std::ref(stop_worker_threads_signal)); + } + + auto iter_start_time = high_resolution_clock::now(); + + // This is the timed operation (producer) + int jobs_created_this_iteration = run_job_creation_and_enqueue_snippet( + local_job_buffer, local_core_resources, local_partition_manager, + local_partition_ids_tensor, local_x_ptr, + num_queries_test, num_partitions_test, + BENCH_K, BENCH_DIMENSION); + + auto iter_end_time = high_resolution_clock::now(); + + // Signal workers to stop and wait for them to finish + stop_worker_threads_signal.store(true, std::memory_order_release); + for (auto& t : worker_threads) { + if (t.joinable()) { + t.join(); + } + } + + if (iter >= warmup_iterations) { + durations_ms.push_back(duration_cast(iter_end_time - iter_start_time).count() / 1000.0); + total_jobs_actually_created += jobs_created_this_iteration; + } + + // Sanity check: total dequeued items should match jobs created + long total_dequeued_this_iteration = 0; + for (const auto& cr : local_core_resources) { + total_dequeued_this_iteration += cr.dequeued_items_by_worker.load(); + } + ASSERT_EQ(total_dequeued_this_iteration, jobs_created_this_iteration) + << "Mismatch in created vs dequeued jobs for iteration " << iter; } - return total_min_sum; // Return sum for anti-optimization - } - // Wrappers call the kernel - static float static_sequential_scan(int nth = 1) { - return static_scan_kernel(S_seq_order_data, nth); - } - static float static_random_scan(int nth = 1) { - return static_scan_kernel(S_rnd_order_data, nth); - } - -protected: - static void SetUpTestSuite() { - std::cout << "Using custom parallel_for for inner loop parallelization." << std::endl; - unsigned int hw_threads = std::thread::hardware_concurrency(); - std::cout << "std::thread::hardware_concurrency(): " << hw_threads << std::endl; - - std::cout << "Initializing benchmark data (once)..." << std::endl; - auto overall_start_init = std::chrono::steady_clock::now(); - - initialize_base_vectors(); - initialize_queries(); - initialize_seq_order(); - initialize_rnd_order(); - - auto overall_end_init = std::chrono::steady_clock::now(); - std::chrono::duration init_duration = overall_end_init - overall_start_init; - std::cout << "VECTOR SCAN BENCHMARK" << std::endl; - std::cout << "--------------------------------------------------------------------------" << std::endl; - std::cout << "Benchmark data initialized in " << std::fixed << std::setprecision(3) - << init_duration.count() << " s." << std::endl; - std::cout << "Benchmark data size: " << LIST_SIZE << "vectors, " - << NQ << " queries, " << D << " dimensions." << std::endl; - std::cout << "Throughput averaged over all queries." << std::endl; - std::cout << "--------------------------------------------------------------------------" << std::endl; - std::cout << std::setw(24) << std::left << "Test Case" - << " | " << "N_Threads" // Requested threads - << " | " << "Time (s)" - << " | " << "Throughput" << std::endl; - std::cout << "--------------------------------------------------------------------------" << std::endl; - } - - static void TearDownTestSuite() { - std::cout << "--------------------------------------------------------------------------" << std::endl; - std::cout << "Benchmark suite finished." << std::endl; + // 3. Report results + double total_duration_ms = 0; + for (double d : durations_ms) total_duration_ms += d; + double avg_duration_ms = durations_ms.empty() ? 0 : total_duration_ms / durations_ms.size(); + + std::cout << " Average time for snippet iteration (with contention): " + << std::fixed << std::setprecision(3) << avg_duration_ms << " ms" << std::endl; + + if (test_iterations > 0 && total_jobs_actually_created > 0) { + long avg_jobs_per_iteration = total_jobs_actually_created / test_iterations; + if (avg_jobs_per_iteration > 0 && avg_duration_ms > 0) { + std::cout << " Average jobs created per iteration: " << avg_jobs_per_iteration << std::endl; + std::cout << " Average time per job (snippet part, with contention): " + << (avg_duration_ms * 1000.0 / avg_jobs_per_iteration) << " us" << std::endl; + } + } + ASSERT_GT(avg_duration_ms, -0.00001); } -}; - -// Static member definitions -std::vector ListScanBenchmarkF::S_base_vectors_data; -std::vector ListScanBenchmarkF::S_queries_data; -std::vector ListScanBenchmarkF::S_seq_order_data; -std::vector ListScanBenchmarkF::S_rnd_order_data; - -std::once_flag ListScanBenchmarkF::base_vectors_flag; -std::once_flag ListScanBenchmarkF::queries_flag; -std::once_flag ListScanBenchmarkF::seq_order_flag; -std::once_flag ListScanBenchmarkF::rnd_order_flag; - - -TEST_F(ListScanBenchmarkF, ParallelSequentialScan) -{ - for (int nth : {1, 2, 4, 8, 12}) { // Test with different numbers of threads - Timer t; - t.start(); - volatile float dummy_sum = static_sequential_scan(nth); - double elapsed_seconds = t.stop(); - (void)dummy_sum; - - int actual_pfor_threads = (nth <= 0) ? static_cast(std::thread::hardware_concurrency()) : nth; - if (actual_pfor_threads == 0) actual_pfor_threads = 1; - if (nth == 1) actual_pfor_threads = 1; // parallel_for handles num_threads == 1 specifically - - - print_stats("Parallel-Sequential", nth, elapsed_seconds); - } -} - -TEST_F(ListScanBenchmarkF, ParallelRandomScan) -{ - for (int nth : {1, 2, 4, 8, 12}) { // Test with different numbers of threads - Timer t; - t.start(); - volatile float dummy_sum = static_random_scan(nth); - double elapsed_seconds = t.stop(); - (void)dummy_sum; - - int actual_pfor_threads = (nth <= 0) ? static_cast(std::thread::hardware_concurrency()) : nth; - if (actual_pfor_threads == 0) actual_pfor_threads = 1; - if (nth == 1) actual_pfor_threads = 1; // parallel_for handles num_threads == 1 specifically - - print_stats("Parallel-Random", nth, elapsed_seconds); - } -} +} // namespace JobEnqueueMicrobenchmarkWithContention \ No newline at end of file From 72b6c8fa07c844c7bfe20d14761f9eea229a08f2 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 16:26:53 -0500 Subject: [PATCH 137/323] reduce allocation cost of scan jobs --- src/cpp/src/query_coordinator.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index c1b6d46c..f1f3a4a0 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -442,7 +442,6 @@ shared_ptr QueryCoordinator::worker_scan( auto partition_ids_accessor = partition_ids.accessor(); job_buffer_.resize(num_queries * partition_ids.size(1)); - auto partitions = partition_manager_->partition_store_->partitions_; int jid = 0; for (int q = 0; q < num_queries; q++) { for (int64_t p = 0; p < partition_ids.size(1); p++) { @@ -458,7 +457,7 @@ shared_ptr QueryCoordinator::worker_scan( job.num_queries = 1; job.rank = p; - int core_id = partitions[pid]->core_id_; + int core_id = partition_manager_->get_partition_core_id(pid); if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } From a452a85a952ac88f2b63a81a6bf0d0f316d99690 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 16:31:22 -0500 Subject: [PATCH 138/323] reduce allocation cost of scan jobs --- src/cpp/src/query_coordinator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index f1f3a4a0..cb0fdcca 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -457,7 +457,7 @@ shared_ptr QueryCoordinator::worker_scan( job.num_queries = 1; job.rank = p; - int core_id = partition_manager_->get_partition_core_id(pid); + int core_id = pid % num_workers_; if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } From 20a55ddce3bb9c90cc8fca11a3b0f1348dd873b6 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 16:35:50 -0500 Subject: [PATCH 139/323] reduce allocation cost of scan jobs --- src/cpp/src/query_coordinator.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index cb0fdcca..b555c9bf 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -457,8 +457,10 @@ shared_ptr QueryCoordinator::worker_scan( job.num_queries = 1; job.rank = p; - int core_id = pid % num_workers_; - if (core_id < 0) { + int core_id = partition_manager_->get_partition_core_id(pid); + + + if (core_id < 0 || pid % num_workers_ != core_id) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } job_buffer_[jid] = std::move(job); From 12ea88c0daa22a9f10f36166648c8bbe12754b14 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 16:38:53 -0500 Subject: [PATCH 140/323] reduce allocation cost of scan jobs --- src/cpp/src/partition_manager.cpp | 2 +- src/cpp/src/query_coordinator.cpp | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index 428c7ed4..de6b5a7f 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -621,7 +621,7 @@ void PartitionManager::distribute_partitions(int num_workers, bool use_numa) { Tensor partition_ids = get_partition_ids(); auto partition_ids_accessor = partition_ids.accessor(); for (int i = 0; i < partition_ids.size(0); i++) { - set_partition_core_id(partition_ids_accessor[i], i % num_workers, use_numa); + set_partition_core_id(partition_ids_accessor[i], partition_ids_accessor[i] % num_workers, use_numa); } } diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index b555c9bf..f9dddfc4 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -457,10 +457,9 @@ shared_ptr QueryCoordinator::worker_scan( job.num_queries = 1; job.rank = p; - int core_id = partition_manager_->get_partition_core_id(pid); + int core_id = pid % num_workers_ - - if (core_id < 0 || pid % num_workers_ != core_id) { + if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } job_buffer_[jid] = std::move(job); From 37b7b547b8a55ec050e84a0f70804152c8a77679 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 16:40:09 -0500 Subject: [PATCH 141/323] reduce allocation cost of scan jobs --- src/cpp/src/query_coordinator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index f9dddfc4..e1c18120 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -457,7 +457,7 @@ shared_ptr QueryCoordinator::worker_scan( job.num_queries = 1; job.rank = p; - int core_id = pid % num_workers_ + int core_id = pid % num_workers_; if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); From 947868697eda883a060d68146f9e2d22a3511fe8 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 16:49:33 -0500 Subject: [PATCH 142/323] reduce allocation cost of scan jobs --- src/cpp/src/query_coordinator.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index e1c18120..a69723b2 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -468,6 +468,12 @@ shared_ptr QueryCoordinator::worker_scan( } } } + auto topk_ids = torch::full({num_queries, k}, -1, torch::kInt64); + auto topk_dists = torch::full({num_queries, k}, + (metric_ == faiss::METRIC_INNER_PRODUCT) + ? -std::numeric_limits::infinity() + : std::numeric_limits::infinity(), + torch::kFloat32); end_time = high_resolution_clock::now(); timing_info->job_enqueue_time_ns = duration_cast(end_time - start_time).count(); @@ -548,12 +554,6 @@ shared_ptr QueryCoordinator::worker_scan( // Aggregate results. start_time = high_resolution_clock::now(); - auto topk_ids = torch::full({num_queries, k}, -1, torch::kInt64); - auto topk_dists = torch::full({num_queries, k}, - (metric_ == faiss::METRIC_INNER_PRODUCT) - ? -std::numeric_limits::infinity() - : std::numeric_limits::infinity(), - torch::kFloat32); auto ids_accessor = topk_ids.accessor(); auto dists_accessor = topk_dists.accessor(); { From 9161783a02957b58c2292cdaa447d19fae08dfe7 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 16:56:28 -0500 Subject: [PATCH 143/323] reduce allocation cost of scan jobs --- src/cpp/src/query_coordinator.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index a69723b2..425dfdc6 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -458,10 +458,6 @@ shared_ptr QueryCoordinator::worker_scan( job.rank = p; int core_id = pid % num_workers_; - - if (core_id < 0) { - throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); - } job_buffer_[jid] = std::move(job); core_resources_[core_id].job_queue.enqueue(jid); jid++; From 704ab4fc8cfdf9412f2709991011bbc70ab08c4c Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 17:05:00 -0500 Subject: [PATCH 144/323] reduce allocation cost of scan jobs --- src/cpp/src/query_coordinator.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 425dfdc6..ffce055e 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -70,6 +70,10 @@ void QueryCoordinator::initialize_workers(int num_cores, bool use_numa) { worker_job_counter_[i] = 0; } workers_initialized_ = true; + + // get num cores on machine + int num_cores_on_machine = std::thread::hardware_concurrency(); + set_thread_affinity(num_cores + 1 % num_cores_on_machine); } // Shutdown Worker Threads From eee6b9fe247a619f5966e42be7e1c5d5c5c26e48 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 17:09:56 -0500 Subject: [PATCH 145/323] reduce allocation cost of scan jobs --- src/cpp/src/query_coordinator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index ffce055e..97c96bc4 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -71,9 +71,9 @@ void QueryCoordinator::initialize_workers(int num_cores, bool use_numa) { } workers_initialized_ = true; - // get num cores on machine + // set main thread on separate thread from workers int num_cores_on_machine = std::thread::hardware_concurrency(); - set_thread_affinity(num_cores + 1 % num_cores_on_machine); + set_thread_affinity(num_cores % num_cores_on_machine); } // Shutdown Worker Threads From dea4112fc8ac669437d990832dfc6760062509b9 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 17:46:36 -0500 Subject: [PATCH 146/323] time scan function --- src/cpp/src/query_coordinator.cpp | 32 +++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 97c96bc4..acc5a764 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -96,6 +96,13 @@ void QueryCoordinator::shutdown_workers() { workers_initialized_ = false; } +void threadsafe_cout(std::string log_msg) +{ + static std::mutex lock; + std::lock_guard guard{ lock }; + std::cout << std::move(log_msg); +} + // Worker Thread Function void QueryCoordinator::partition_scan_worker_fn(int core_index) { @@ -106,6 +113,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { } int64_t total_pull_time = 0; + int64_t total_copy_time = 0; int64_t total_scan_time = 0; int64_t total_merge_time = 0; @@ -117,6 +125,8 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { std::this_thread::sleep_for(std::chrono::microseconds(5)); } + auto s0 = std::chrono::high_resolution_clock::now(); + auto job_wait_end = std::chrono::high_resolution_clock::now(); job_pull_time_ns += std::chrono::duration_cast(job_wait_end - job_wait_start).count(); @@ -213,11 +223,13 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { auto s4 = std::chrono::high_resolution_clock::now(); // print out timings for worker - auto wait_time = std::chrono::duration_cast(s2 - s1).count(); + auto pull_time = std::chrono::duration_cast(s1 - s0).count(); + auto copy_time = std::chrono::duration_cast(s2 - s1).count(); auto process_time = std::chrono::duration_cast(s3 - s2).count(); auto merge_time = std::chrono::duration_cast(s4 - s3).count(); - total_pull_time += wait_time; + total_pull_time += pull_time; + total_copy_time += copy_time; total_scan_time += process_time; total_merge_time += merge_time; } @@ -288,19 +300,27 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { auto s4 = std::chrono::high_resolution_clock::now(); // print out timings for worker - auto wait_time = std::chrono::duration_cast(s2 - s1).count(); + auto pull_time = std::chrono::duration_cast(s1 - s0).count(); + auto copy_time = std::chrono::duration_cast(s2 - s1).count(); auto process_time = std::chrono::duration_cast(s3 - s2).count(); auto merge_time = std::chrono::duration_cast(s4 - s3).count(); - total_pull_time += wait_time; + total_pull_time += pull_time; + total_copy_time += copy_time; total_scan_time += process_time; total_merge_time += merge_time; } auto job_process_end = std::chrono::high_resolution_clock::now(); job_process_time_ns += std::chrono::duration_cast(job_process_end - job_process_start).count(); } - -// std::cout << "Worker=" << core_index << ": total_pull_time=" << total_pull_time / 1000 << ", total_scan_time=" << total_scan_time / 1000 << ", merge_time=" << total_merge_time / 1000 << '\n'; + std::string log_message = + "[QueryCoordinator::partition_scan_worker_fn] Worker " + std::to_string(core_index) + + ": total_pull_time=" + std::to_string(total_pull_time / 1000) + + ", total_copy_time=" + std::to_string(total_copy_time / 1000) + + ", total_scan_time=" + std::to_string(total_scan_time / 1000) + + ", merge_time=" + std::to_string(total_merge_time / 1000) + '\n'; + + threadsafe_cout(log_message); } // Worker-Based Scan Implementation From d5b4ad8683db01d42b8b222305b35c04f5ea47d8 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 17:57:52 -0500 Subject: [PATCH 147/323] query buffer on numa node --- src/cpp/include/query_coordinator.h | 6 ++++- src/cpp/src/query_coordinator.cpp | 42 +++++++++++++++++------------ 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index e7898939..ff58327d 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -53,11 +53,15 @@ class QueryCoordinator { struct CoreResources { int core_id; ///< Logical identifier of the core. vector> topk_buffer_pool; ///< Preallocated Top‑K buffers. - vector local_query_buffer; ///< Local aggregator for query results. moodycamel::ConcurrentQueue job_queue; ///< Job queue for scan jobs. }; + struct NUMAResources { + float *local_query_buffer; + }; + vector core_resources_; ///< Per‑core resources for worker threads. + vector numa_resources_; bool workers_initialized_ = false; ///< Flag indicating if worker threads are initialized. int num_workers_; ///< Total number of worker threads. vector worker_threads_; ///< Container for worker threads. diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index acc5a764..ec6f0d7b 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -38,12 +38,27 @@ QueryCoordinator::~QueryCoordinator() { void QueryCoordinator::allocate_core_resources(int core_idx, int num_queries, int k, int d) { CoreResources &res = core_resources_[core_idx]; res.core_id = core_idx; - res.local_query_buffer.resize(num_queries * d * sizeof(float)); res.topk_buffer_pool.resize(num_queries); for (int q = 0; q < num_queries; ++q) { res.topk_buffer_pool[q] = make_shared(k, metric_ == faiss::METRIC_INNER_PRODUCT); res.job_queue = moodycamel::ConcurrentQueue(); } + + + int num_numa_nodes = 1; + #ifdef QUAKE_USE_NUMA + num_numa_nodes = numa_max_node(); + #endif + + for (int i = 0; i < num_numa_nodes; i++) { + NUMAResources &numa_res = numa_resources_[i]; + int64_t alloc_size = num_queries * d * sizeof(float); + #ifdef QUAKE_USE_NUMA + numa_res.local_query_buffer = (float *) numa_alloc_onnode(alloc_size, numa_node)); + #else + numa_res.local_query_buffer = (float *) std::malloc(alloc_size); + #endif + } } // Initialize Worker Threads @@ -108,6 +123,12 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { CoreResources &res = core_resources_[core_index]; + int numa_node = 1; + #ifdef QUAKE_USE_NUMA + numa_node = numa_node_of_cpu(core_index); + #endif + NUMAResources &numa_res = numa_resources_[numa_node]; + if (!set_thread_affinity(core_index)) { std::cout << "[QueryCoordinator::partition_scan_worker_fn] Failed to set thread affinity on core " << core_index << std::endl; } @@ -185,15 +206,6 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { if (!job.is_batched) { auto s1 = std::chrono::high_resolution_clock::now(); - // Allocate a thread-local query buffer if needed. - if (res.local_query_buffer.size() < partition_manager_->d() * sizeof(float)) { - res.local_query_buffer.resize(partition_manager_->d() * sizeof(float)); - } - - // Copy the contents of the query vector to the local buffer using memcpy. - if (memcpy(res.local_query_buffer.data(), job.query_vector, partition_manager_->d() * sizeof(float)) == nullptr) { - throw std::runtime_error("[partition_scan_worker_fn] memcpy failed."); - } if (local_topk_buffer == nullptr) { throw std::runtime_error("[partition_scan_worker_fn] local_topk_buffer is null."); @@ -203,7 +215,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { } auto s2 = std::chrono::high_resolution_clock::now(); // Perform the scan on the partition. - scan_list((float *) res.local_query_buffer.data(), + scan_list(numa_res.local_query_buffer, partition_codes, partition_ids, partition_size, @@ -239,10 +251,6 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { throw std::runtime_error("[partition_scan_worker_fn] Invalid batched job."); } - if (res.local_query_buffer.size() < partition_manager_->d() * sizeof(float) * job.num_queries) { - res.local_query_buffer.resize(partition_manager_->d() * sizeof(float) * job.num_queries); - } - auto s1 = std::chrono::high_resolution_clock::now(); int64_t d = partition_manager_->d(); @@ -254,7 +262,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { d * sizeof(float)); } - if(memcpy(res.local_query_buffer.data(), + if(memcpy(numa_res.local_query_buffer, query_subset.data(), query_subset.size() * sizeof(float)) == nullptr) { throw std::runtime_error("[partition_scan_worker_fn] memcpy failed."); @@ -276,7 +284,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { auto s2 = std::chrono::high_resolution_clock::now(); // Process the batched job. - batched_scan_list((float *) res.local_query_buffer.data(), + batched_scan_list(numa_res.local_query_buffer, partition_codes, partition_ids, job.num_queries, From 76ce5d99ec9d9f5fc140af1eac55c665aa0704dc Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 17:59:18 -0500 Subject: [PATCH 148/323] query buffer on numa node --- src/cpp/src/query_coordinator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index ec6f0d7b..38e3cd10 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -54,7 +54,7 @@ void QueryCoordinator::allocate_core_resources(int core_idx, int num_queries, in NUMAResources &numa_res = numa_resources_[i]; int64_t alloc_size = num_queries * d * sizeof(float); #ifdef QUAKE_USE_NUMA - numa_res.local_query_buffer = (float *) numa_alloc_onnode(alloc_size, numa_node)); + numa_res.local_query_buffer = (float *) numa_alloc_onnode(alloc_size, numa_node); #else numa_res.local_query_buffer = (float *) std::malloc(alloc_size); #endif From 40d25197cf81e8bcdbeb44f56a777ace6b3bf779 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 18:04:04 -0500 Subject: [PATCH 149/323] query buffer on numa node --- src/cpp/src/query_coordinator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 38e3cd10..45b6f1b3 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -54,7 +54,7 @@ void QueryCoordinator::allocate_core_resources(int core_idx, int num_queries, in NUMAResources &numa_res = numa_resources_[i]; int64_t alloc_size = num_queries * d * sizeof(float); #ifdef QUAKE_USE_NUMA - numa_res.local_query_buffer = (float *) numa_alloc_onnode(alloc_size, numa_node); + numa_res.local_query_buffer = (float *) numa_alloc_onnode(alloc_size, i); #else numa_res.local_query_buffer = (float *) std::malloc(alloc_size); #endif From d006f303a9deaf9124f2c8fefe9abf5783ba6241 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 18:12:25 -0500 Subject: [PATCH 150/323] query buffer on numa node --- src/cpp/src/quake_index.cpp | 2 +- src/cpp/src/query_coordinator.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cpp/src/quake_index.cpp b/src/cpp/src/quake_index.cpp index 637f0036..8419d64f 100644 --- a/src/cpp/src/quake_index.cpp +++ b/src/cpp/src/quake_index.cpp @@ -284,7 +284,7 @@ void QuakeIndex::load(const std::string& dir_path, int n_workers, bool use_numa) int n_parts = partition_manager_->nlist(); // don't put too many parent workers. maximum of 1 worker per 500 partitions - int parent_n_workers = std::max(1, n_parts / 500); + int parent_n_workers = std::max(1, n_parts / 1000); parent_n_workers = std::min(parent_n_workers, n_workers); parent_->load(parent_dir, parent_n_workers, use_numa); diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 45b6f1b3..3f6a3d15 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -49,6 +49,7 @@ void QueryCoordinator::allocate_core_resources(int core_idx, int num_queries, in #ifdef QUAKE_USE_NUMA num_numa_nodes = numa_max_node(); #endif + numa_resources_.resize(num_numa_nodes); for (int i = 0; i < num_numa_nodes; i++) { NUMAResources &numa_res = numa_resources_[i]; From b85a4e3260d6816bc76a92fc08a2807156fa47e6 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 18:15:26 -0500 Subject: [PATCH 151/323] query buffer on numa node --- src/cpp/src/query_coordinator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 3f6a3d15..16d68c6b 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -124,7 +124,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { CoreResources &res = core_resources_[core_index]; - int numa_node = 1; + int numa_node = 0; #ifdef QUAKE_USE_NUMA numa_node = numa_node_of_cpu(core_index); #endif From 227a548fc0111a3d8ac619fbafa785dd29c7d279 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 18:37:06 -0500 Subject: [PATCH 152/323] query buffer on numa node --- src/cpp/src/query_coordinator.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 16d68c6b..14d31dca 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -47,7 +47,7 @@ void QueryCoordinator::allocate_core_resources(int core_idx, int num_queries, in int num_numa_nodes = 1; #ifdef QUAKE_USE_NUMA - num_numa_nodes = numa_max_node(); + num_numa_nodes = numa_max_node() + 1; #endif numa_resources_.resize(num_numa_nodes); @@ -214,6 +214,13 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { local_topk_buffer->set_k(job.k); local_topk_buffer->reset(); } + + int d = partition_manager_->d(); + std::memcpy(numa_res.local_query_buffer, + job.query_vector, + size_t(d) * sizeof(float)); + + auto s2 = std::chrono::high_resolution_clock::now(); // Perform the scan on the partition. scan_list(numa_res.local_query_buffer, From d49a5d0af9447226a5582ed1cd89ceb1f3399f49 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 19 May 2025 18:39:22 -0500 Subject: [PATCH 153/323] query buffer on numa node --- src/cpp/src/query_coordinator.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 14d31dca..6a7f64d4 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -215,12 +215,6 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { local_topk_buffer->reset(); } - int d = partition_manager_->d(); - std::memcpy(numa_res.local_query_buffer, - job.query_vector, - size_t(d) * sizeof(float)); - - auto s2 = std::chrono::high_resolution_clock::now(); // Perform the scan on the partition. scan_list(numa_res.local_query_buffer, @@ -422,6 +416,12 @@ shared_ptr QueryCoordinator::worker_scan( start_time = high_resolution_clock::now(); + for (auto &nr : numa_resources_) { + std::memcpy(nr.local_query_buffer, + x_ptr, // q == 0 + size_t(dimension) * sizeof(float)); + } + if (search_params->batched_scan) { auto partition_ids_accessor = partition_ids.accessor(); job_buffer_.resize(partition_manager_->nlist()); From 5cd241ff16e7833a2f1b04e7e352017505f39907 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 02:09:29 -0500 Subject: [PATCH 154/323] NUMA allocation for topk buffer --- src/cpp/include/list_scanning.h | 319 +++---- src/cpp/include/parallel.h | 54 ++ src/cpp/include/query_coordinator.h | 80 +- src/cpp/src/maintenance_cost_estimator.cpp | 2 +- src/cpp/src/query_coordinator.cpp | 948 ++++++++++----------- test/cpp/benchmark.cpp | 2 +- test/cpp/latency_estimator.cpp | 2 +- test/cpp/list_scanning.cpp | 6 +- test/cpp/query_coordinator.cpp | 28 - test/cpp/topk_buffer.cpp | 2 +- 10 files changed, 754 insertions(+), 689 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 29aa898a..6aa4359d 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -13,6 +13,7 @@ #include "sorting/pdqsort.h" #include "sorting/floyd_rivest_select.h" #include "sorting/heap_select.h" +#include "parallel.h" inline Tensor calculate_recall(Tensor ids, Tensor gt_ids) { Tensor num_correct = torch::zeros(ids.size(0), torch::kInt64); @@ -39,206 +40,226 @@ inline Tensor calculate_recall(Tensor ids, Tensor gt_ids) { return recall; } -#define TOP_K_BUFFER_CAPACITY (16 * 1024) - -template +template class TypedTopKBuffer { public: - int k_; // Number of top elements to keep - int curr_offset_ = 0; // Current offset in the buffer - std::vector > topk_; // Buffer to store top-k elements - bool is_descending_; // Flag to indicate sorting order - std::recursive_mutex buffer_mutex_; - std::atomic processing_query_; - std::atomic jobs_left_; - std::atomic partitions_scanned_; - - TypedTopKBuffer(int k, bool is_descending, int buffer_capacity = TOP_K_BUFFER_CAPACITY) - : k_(k), is_descending_(is_descending), topk_(buffer_capacity), processing_query_(true), partitions_scanned_(0) { - assert(k <= buffer_capacity); // Ensure k is smaller than or equal to buffer size - - for (int i = 0; i < topk_.size(); i++) { - if (is_descending_) { - topk_[i] = {-std::numeric_limits::infinity(), -1}; - } else { - topk_[i] = {std::numeric_limits::max(), -1}; - } + T *vals_; // size = capacity + I *ids_; + int capacity_, head_, k_; + bool is_desc_; + int *ord_; + bool owns_memory_ = true; + TypedTopKBuffer(int k, bool desc, int cap, int node) + : capacity_(cap), head_(0), k_(k) { + vals_ = static_cast(quake_alloc(sizeof(T) * cap, node)); + ids_ = static_cast(quake_alloc(sizeof(I) * cap, node)); + ord_ = static_cast(quake_alloc(sizeof(int) * cap, node)); + + if (capacity_ < k_) { + throw std::invalid_argument("capacity must be greater than k"); } - } - ~TypedTopKBuffer() = default; - - void set_k(int new_k) { - std::lock_guard buffer_lock(buffer_mutex_); - assert(new_k <= topk_.size()); - k_ = new_k; - reset(); + if (desc) { + is_desc_ = true; + for (int i = 0; i < capacity_; i++) { + vals_[i] = -std::numeric_limits::infinity(); + ids_[i] = -1; + } + } else { + is_desc_ = false; + for (int i = 0; i < capacity_; i++) { + vals_[i] = std::numeric_limits::infinity(); + ids_[i] = -1; + } + } } - void set_processing_query(bool new_value) { - processing_query_.store(new_value, std::memory_order_relaxed); - } + // Create buffer but do not allocate memory (except for ord_) + TypedTopKBuffer(T *vals, I* ids, int cap, int k, bool desc, int node) { + capacity_ = cap; + head_ = 0; + k_ = k; + is_desc_ = desc; + vals_ = vals; + ids_ = ids; + ord_ = static_cast(quake_alloc(sizeof(int) * cap, node)); + owns_memory_ = false; + + if (capacity_ < k_) { + throw std::invalid_argument("capacity must be greater than k"); + } - inline bool currently_processing_query() { - return processing_query_.load(std::memory_order_relaxed); + if (desc) { + for (int i = 0; i < capacity_; i++) { + vals_[i] = -std::numeric_limits::infinity(); + ids_[i] = -1; + } + } else { + for (int i = 0; i < capacity_; i++) { + vals_[i] = std::numeric_limits::infinity(); + ids_[i] = -1; + } + } } - void set_jobs_left(int total_jobs) { - jobs_left_.store(total_jobs, std::memory_order_relaxed); - } + ~TypedTopKBuffer() { + if (owns_memory_) { + if (vals_) { + quake_free(vals_, sizeof(T) * capacity_); + } - void record_skipped_jobs(int skipped_jobs) { - jobs_left_.fetch_sub(skipped_jobs, std::memory_order_relaxed); - } + if (ids_) { + quake_free(ids_, sizeof(I) * capacity_); + } + } - void record_empty_job() { - jobs_left_.fetch_sub(1, std::memory_order_relaxed); - } + if (ord_) { + quake_free(ord_, sizeof(int) * capacity_); + } - inline bool finished_all_jobs() { - int curr_jobs_left = jobs_left_.load(std::memory_order_relaxed); - return jobs_left_.load(std::memory_order_relaxed) <= 0; + vals_ = nullptr; + ids_ = nullptr; + ord_ = nullptr; } - inline int get_num_partitions_scanned() { - return partitions_scanned_.load(std::memory_order_relaxed); + void set_k(int new_k) { + if (new_k > capacity_) { + throw std::invalid_argument("k must be less than the capacity"); + } + k_ = new_k; + reset(); } void reset() { - std::lock_guard buffer_lock(buffer_mutex_); - curr_offset_ = 0; + head_ = 0; for (int i = 0; i < k_; i++) { - if (is_descending_) { - topk_[i] = { -std::numeric_limits::infinity(), -1 }; + if (is_desc_) { + vals_[i] = -std::numeric_limits::infinity(); + ids_[i] = -1; } else { - topk_[i] = { std::numeric_limits::max(), -1 }; + vals_[i] = std::numeric_limits::infinity(); + ids_[i] = -1; } } - partitions_scanned_.store(0, std::memory_order_relaxed); } - void add(DistanceType distance, IdType index) { - if (curr_offset_ >= topk_.size()) { - flush(); // Flush the buffer if it is full - } - topk_[curr_offset_++] = {distance, index}; + inline void add(T dist, I idx) { + vals_[head_] = dist; + ids_[head_] = idx; + if (++head_ == capacity_) flush(); } - void batch_add(DistanceType *distances, const IdType *indices, int num_values) { - if (num_values == 0) { - jobs_left_.fetch_sub(1, std::memory_order_relaxed); - return; - } - if (!currently_processing_query()) { - jobs_left_.fetch_sub(1, std::memory_order_relaxed); - return; - } - std::lock_guard lock(buffer_mutex_); + void batch_add(T *distances, I *indices, int num_values) { int pos = 0; while (pos < num_values) { - int available = static_cast(topk_.size()) - curr_offset_; + int available = capacity_ - head_; if (available <= 0) { flush(); - available = static_cast(topk_.size()) - curr_offset_; + available = capacity_ - head_; } int to_copy = std::min(num_values - pos, available); for (int i = 0; i < to_copy; i++) { - topk_[curr_offset_++] = { distances[pos + i], indices[pos + i] }; + vals_[head_] = distances[pos + i]; + ids_[head_] = indices[pos + i]; + head_++; } pos += to_copy; } - jobs_left_.fetch_sub(1, std::memory_order_relaxed); - partitions_scanned_.fetch_add(1, std::memory_order_relaxed); } - DistanceType flush() { - std::lock_guard buffer_lock(buffer_mutex_); - if (curr_offset_ > k_) { - - // for k < 10 use heap select - if (k_ < 10) { - if (is_descending_) { - miniselect::heap_select(topk_.begin(), topk_.begin() + k_, - topk_.begin() + curr_offset_, - [](const auto &a, const auto &b) { return a.first > b.first; }); - } else { - miniselect::heap_select(topk_.begin(), topk_.begin() + k_, - topk_.begin() + curr_offset_, - [](const auto &a, const auto &b) { return a.first < b.first; }); - } - } else if (k_ < curr_offset_ * .001) { - if (is_descending_) { - miniselect::floyd_rivest_select(topk_.begin(), topk_.begin() + k_, - topk_.begin() + curr_offset_, - [](const auto &a, const auto &b) { return a.first > b.first; }); - } else { - miniselect::floyd_rivest_select(topk_.begin(), topk_.begin() + k_, - topk_.begin() + curr_offset_, - [](const auto &a, const auto &b) { return a.first < b.first; }); - } - } else { - if (is_descending_) { - miniselect::pdqpartial_sort_branchless(topk_.begin(), topk_.begin() + k_, - topk_.begin() + curr_offset_, - [](const auto &a, const auto &b) { return a.first > b.first; }); - } else { - miniselect::pdqpartial_sort_branchless(topk_.begin(), topk_.begin() + k_, - topk_.begin() + curr_offset_, - [](const auto &a, const auto &b) { return a.first < b.first; }); - } - } - curr_offset_ = k_; // After flush, retain only the top-k elements - } else { - if (is_descending_) { - miniselect::pdqsort_branchless(topk_.begin(), topk_.begin() + curr_offset_, - [](const auto &a, const auto &b) { return a.first > b.first; }); + T flush() { + int n = head_; + int m = std::min(n, k_); + + // 1) build identity permutation + for (int i = 0; i < n; ++i) { + ord_[i] = i; + } + // comparator by value + auto cmpIdx = [&](int a, int b) { + return is_desc_ ? (vals_[a] > vals_[b]) + : (vals_[a] < vals_[b]); + }; + + // 2) select top‐m indices into ord_[0..m) + if (n > m) { + if (m < 10) { + miniselect::heap_select(ord_, ord_ + m, ord_ + n, cmpIdx); + } else if (m < n * 0.001) { + miniselect::floyd_rivest_select(ord_, ord_ + m, ord_ + n, cmpIdx); } else { - miniselect::pdqsort_branchless(topk_.begin(), topk_.begin() + curr_offset_, - [](const auto &a, const auto &b) { return a.first < b.first; }); + miniselect::pdqpartial_sort_branchless(ord_, ord_ + m, ord_ + n, cmpIdx); } } - return topk_[std::min(curr_offset_, k_ - 1)].first; - } - - std::vector get_topk() { - std::lock_guard buffer_lock(buffer_mutex_); - flush(); // Ensure the buffer is properly flushed - - std::vector topk_distances(std::min(curr_offset_, k_)); - for (int i = 0; i < std::min(curr_offset_, k_); i++) { - topk_distances[i] = topk_[i].first; + // 3) sort the top‐m prefix + miniselect::pdqsort_branchless(ord_, ord_ + m, cmpIdx); + + // 4) copy the m winners back to front of vals_/ids_ + for (int i = 0; i < m; ++i) { + int idx = ord_[i]; + vals_[i] = vals_[idx]; + ids_[i] = ids_[idx]; } - return topk_distances; + // 5) clamp head_ and return the k-th value (or extreme if too few) + head_ = m; + if (head_ == 0) { + return is_desc_ + ? -std::numeric_limits::infinity() + : std::numeric_limits::infinity(); + } + int ret_i = std::min(k_ - 1, head_ - 1); + return vals_[ret_i]; } - DistanceType get_kth_distance() { - std::lock_guard buffer_lock(buffer_mutex_); - flush(); // Ensure the buffer is properly flushed - if (curr_offset_ < k_) { - return 0.0; + std::vector get_topk() { + flush(); + int n = head_; + std::vector out; + out.reserve(n); + for (int i = 0; i < n; ++i) { + out.push_back(vals_[i]); } - - return topk_[std::min(curr_offset_, k_ - 1)].first; + return out; } -// Get the current top-k indices (after final flush) - std::vector get_topk_indices() { - std::lock_guard buffer_lock(buffer_mutex_); - flush(); // Ensure the buffer is properly flushed + T get_kth_distance() { + flush(); + if (head_ < k_) { + // not enough elements: return the sentinel extreme + return is_desc_ + ? -std::numeric_limits::infinity() + : std::numeric_limits::infinity(); + } + return vals_[k_ - 1]; + } - std::vector topk_indices(std::min(curr_offset_, k_)); - for (int i = 0; i < std::min(curr_offset_, k_); i++) { - topk_indices[i] = topk_[i].second; + std::vector get_topk_indices() { + flush(); + int n = head_; + std::vector out; + out.reserve(n); + for (int i = 0; i < n; ++i) { + out.push_back(ids_[i]); } - return topk_indices; + return out; } }; // Type alias for convenience using TopkBuffer = TypedTopKBuffer; +inline vector> create_buffers(int batch_size, int k, bool is_desc) { + vector> buffers; + for (int i = 0; i < batch_size; i++) { + buffers.push_back(make_shared(k, is_desc, k*100, 0)); + } + return buffers; +} + +//vector> local_buffers = create_buffers(batch_size, k, (metric_ == faiss::METRIC_INNER_PRODUCT)); + inline std::tuple buffers_to_tensor(vector> buffers) { int n = buffers.size(); int k = buffers[0]->k_; @@ -263,14 +284,6 @@ inline std::tuple buffers_to_tensor(vector> create_buffers(int n, int k, bool is_descending) { - vector> buffers(n); - for (int i = 0; i < n; i++) { - buffers[i] = make_shared(k, is_descending, 10 * k); - } - return buffers; -} - inline void scan_list_no_ids_inner_product(const float *query_vec, const float *list_vecs, int list_size, @@ -460,4 +473,4 @@ inline void batched_scan_list(const float *query_vecs, } // } -#endif //LIST_SCANNING_H +#endif //LIST_SCANNING_H \ No newline at end of file diff --git a/src/cpp/include/parallel.h b/src/cpp/include/parallel.h index 5db90651..ac8ef8da 100644 --- a/src/cpp/include/parallel.h +++ b/src/cpp/include/parallel.h @@ -38,6 +38,60 @@ inline bool set_thread_affinity(int core_id) { #endif } + +#ifdef QUAKE_USE_NUMA +#include + #include + #include + + inline void* quake_alloc(size_t sz, int node) { + void* ptr = numa_alloc_onnode(sz, node); + if (ptr == nullptr || ptr == MAP_FAILED) { + throw std::bad_alloc(); + } + return ptr; + } + + inline void quake_free(void* ptr, size_t sz) noexcept { + if (ptr) { + numa_free(ptr, sz); + } + } + + inline int numa_node_of_cpu(int cpu) { + return numa_node_of_cpu(cpu); + } + + inline int get_num_numa_nodes() { + return numa_num_configured_nodes(); + } + +#else +#include +#include + +inline void* quake_alloc(size_t sz, int /*node*/) { + void* ptr = std::malloc(sz); + if (!ptr) { + throw std::bad_alloc(); + } + return ptr; +} + +inline void quake_free(void* ptr, size_t /*sz*/) noexcept { + std::free(ptr); +} + +inline int numa_node_of_cpu(int /*cpu*/) { + return 0; // Not applicable +} + +inline int get_num_numa_nodes() { + return 1; // Not applicable +} +#endif + + template void parallel_for(IndexType start, IndexType end, Function func, int num_threads = -1) { if (num_threads <= 0) { diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index ff58327d..56628210 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -21,14 +21,17 @@ class PartitionManager; * A ScanJob encapsulates all parameters required to perform a scan on a given index partition. */ struct ScanJob { - int64_t partition_id; ///< The identifier of the partition to be scanned. - int k; ///< The number of neighbors (Top-K) to return. - const float* query_vector; ///< Pointer to the query vector. - std::shared_ptr> query_ids; ///< Global query IDs; used in batched mode. - int query_id; - bool is_batched = false; ///< Indicates whether this is a batched query job. - int64_t num_queries = 0; ///< The number of queries in batched mode. - int rank = 0; ///< Rank of the partition + int64_t partition_id; ///< The identifier of the partition to be scanned. + int k; ///< The number of neighbors (Top-K) to return. + const float* query_vector; ///< Pointer to the query vector. + bool is_batched = false; ///< Indicates whether this is a batched query job. + int64_t num_queries = 0; + + int query_id; + int rank = 0; ///< Rank of the partition + + std::shared_ptr> query_ids; ///< Global query IDs; used in batched mode. + std::shared_ptr> ranks; ///< Rank of the partition for each query }; /** @@ -51,17 +54,33 @@ class QueryCoordinator { * Each core maintains its own pool of Top‑K buffers, a local query buffer, and a dedicated job queue. */ struct CoreResources { - int core_id; ///< Logical identifier of the core. - vector> topk_buffer_pool; ///< Preallocated Top‑K buffers. - moodycamel::ConcurrentQueue job_queue; ///< Job queue for scan jobs. + int core_id; + std::vector> topk_buffer_pool; + moodycamel::ConcurrentQueue job_queue; + + // Thread-local buffers for batched queries + float *batch_queries; ///< Thread-local buffer used for batched queries. + float *batch_distances; ///< Thread-Local buffer for result distances. + int64_t *batch_ids; ///< Thread-Local buffer for result IDs. }; struct NUMAResources { - float *local_query_buffer; + float* local_query_buffer = nullptr; + size_t buffer_size = 0; + }; + + struct ResultJob { + int query_id; + int rank; + std::vector distances; + std::vector indices; }; + vector core_resources_; ///< Per‑core resources for worker threads. vector numa_resources_; + moodycamel::ConcurrentQueue result_queue_; + bool workers_initialized_ = false; ///< Flag indicating if worker threads are initialized. int num_workers_; ///< Total number of worker threads. vector worker_threads_; ///< Container for worker threads. @@ -73,7 +92,7 @@ class QueryCoordinator { bool debug_ = false; ///< Debug mode flag. std::vector job_buffer_; - std::atomic next_job_id_{0}; + int next_job_id_{0}; vector>> job_flags_; ///< Flags to track job completion std::atomic job_pull_time_ns = 0; ///< Time spent pulling jobs from the queue. std::atomic job_process_time_ns = 0; ///< Time spent processing jobs. @@ -198,6 +217,41 @@ class QueryCoordinator { * @param d Dimensionality of the query vectors. */ void allocate_core_resources(int core_idx, int num_queries, int k, int d); + + int64_t pop_scan_job(CoreResources &res); + void process_scan_job(ScanJob job, CoreResources &res); + + // handles the non‐batched branch + void handle_nonbatched_job(const ScanJob &job, + CoreResources &res, + NUMAResources &nr); + + // handles the batched branch + void handle_batched_job(const ScanJob &job, + CoreResources &res, + NUMAResources &nr); + + // — Main‐thread helpers — + void init_global_buffers(int64_t nQ, int K, + Tensor &partition_ids, + shared_ptr params); + + void copy_query_to_numa(const float *xptr, int64_t nQ, int64_t D); + + void enqueue_scan_jobs(Tensor x, + Tensor partition_ids, + shared_ptr params); + + void drain_and_apply_aps(Tensor x, + Tensor partition_ids, + bool use_aps, + float recall_target, + float aps_flush_period_us, + shared_ptr timing); + + std::shared_ptr + aggregate_scan_results(int64_t nQ, int K, + shared_ptr timing); }; #endif //QUERY_COORDINATOR_H diff --git a/src/cpp/src/maintenance_cost_estimator.cpp b/src/cpp/src/maintenance_cost_estimator.cpp index 8fd2a9c1..d1f4d1ab 100644 --- a/src/cpp/src/maintenance_cost_estimator.cpp +++ b/src/cpp/src/maintenance_cost_estimator.cpp @@ -70,7 +70,7 @@ void ListScanLatencyEstimator::profile_scan_latency() { torch::Tensor curr_vectors = vectors.narrow(0, 0, n); torch::Tensor curr_ids = ids.narrow(0, 0, n); - auto topk_buffer = make_shared(k, false); + auto topk_buffer = make_shared(k, false, k * 100, 0); const float *query_ptr = query.data_ptr(); const float *curr_vectors_ptr = curr_vectors.data_ptr(); diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 6a7f64d4..15820c71 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -35,395 +35,309 @@ QueryCoordinator::~QueryCoordinator() { shutdown_workers(); } -void QueryCoordinator::allocate_core_resources(int core_idx, int num_queries, int k, int d) { - CoreResources &res = core_resources_[core_idx]; - res.core_id = core_idx; - res.topk_buffer_pool.resize(num_queries); - for (int q = 0; q < num_queries; ++q) { - res.topk_buffer_pool[q] = make_shared(k, metric_ == faiss::METRIC_INNER_PRODUCT); - res.job_queue = moodycamel::ConcurrentQueue(); - } - +void QueryCoordinator::allocate_core_resources(int core_idx, + int num_queries, + int k, + int d) +{ + auto& CR = core_resources_[core_idx]; + CR.core_id = core_idx; + CR.topk_buffer_pool.clear(); - int num_numa_nodes = 1; - #ifdef QUAKE_USE_NUMA - num_numa_nodes = numa_max_node() + 1; - #endif - numa_resources_.resize(num_numa_nodes); - - for (int i = 0; i < num_numa_nodes; i++) { - NUMAResources &numa_res = numa_resources_[i]; - int64_t alloc_size = num_queries * d * sizeof(float); - #ifdef QUAKE_USE_NUMA - numa_res.local_query_buffer = (float *) numa_alloc_onnode(alloc_size, i); - #else - numa_res.local_query_buffer = (float *) std::malloc(alloc_size); - #endif + int numa_node = 0; +#ifdef QUAKE_USE_NUMA + numa_node = numa_node_of_cpu(core_idx); +#endif + + // job queue remains default-constructed + numa_resources_.resize(get_num_numa_nodes()); + auto& numa_res = numa_resources_[numa_node]; + size_t bytes = size_t(num_queries) * d * sizeof(float); + if (numa_res.buffer_size != bytes) { + quake_free(numa_res.local_query_buffer, numa_res.buffer_size); + numa_res.local_query_buffer = static_cast(quake_alloc(bytes, numa_node)); + numa_res.buffer_size = bytes; } } -// Initialize Worker Threads -void QueryCoordinator::initialize_workers(int num_cores, bool use_numa) { - if (workers_initialized_) { - std::cerr << "[QueryCoordinator::initialize_workers] Workers already initialized." << std::endl; - return; +int64_t QueryCoordinator::pop_scan_job(CoreResources &res) { + int64_t jid; + while (!res.job_queue.try_dequeue(jid)) { + std::this_thread::sleep_for(std::chrono::microseconds(5)); } + return jid; +} - std::cout << "[QueryCoordinator::initialize_workers] Initializing " << num_cores << " worker threads with use_numa=" << use_numa << - std::endl; +void QueryCoordinator::partition_scan_worker_fn(int core_index) { + CoreResources &res = core_resources_[core_index]; + int numa_node = 0; +#ifdef QUAKE_USE_NUMA + numa_node = numa_node_of_cpu(core_index); +#endif + NUMAResources &nr = numa_resources_[numa_node]; - partition_manager_->distribute_partitions(num_cores, use_numa); + set_thread_affinity(core_index); - core_resources_.resize(num_cores); - worker_threads_.resize(num_cores); - worker_job_counter_.reserve(num_cores); - for (int i = 0; i < num_cores; i++) { - if (!set_thread_affinity(i)) { - std::cout << "[QueryCoordinator::initialize_workers] Failed to set thread affinity on core " << i << std::endl; - } - allocate_core_resources(i, 1, 10, partition_manager_->d()); - worker_threads_[i] = std::thread(&QueryCoordinator::partition_scan_worker_fn, this, i); - worker_job_counter_[i] = 0; + while (true) { + int64_t jid = pop_scan_job(res); + if (jid == -1) break; + process_scan_job(job_buffer_[jid], res); } - workers_initialized_ = true; - - // set main thread on separate thread from workers - int num_cores_on_machine = std::thread::hardware_concurrency(); - set_thread_affinity(num_cores % num_cores_on_machine); } -// Shutdown Worker Threads -void QueryCoordinator::shutdown_workers() { - if (!workers_initialized_) { +void QueryCoordinator::process_scan_job(ScanJob job, + CoreResources &res) { + int numa_node = 0; +#ifdef QUAKE_USE_NUMA + numa_node = numa_node_of_cpu(res.core_id); +#endif + NUMAResources &nr = numa_resources_[numa_node]; + + // fetch codes & ids + const float *codes = (float*)partition_manager_->partition_store_->get_codes(job.partition_id); + const int64_t *ids = (int64_t*)partition_manager_->partition_store_->get_ids(job.partition_id); + + int64_t part_size = 0; + try { + part_size = partition_manager_->partition_store_->list_size(job.partition_id); + } catch (...) { + std::cerr << "[partition_scan_worker_fn] Partition " << job.partition_id << " not found.\n"; return; } - stop_workers_.store(true); - // Enqueue a special shutdown job for each core. - for (auto &res : core_resources_) { - res.job_queue.enqueue(-1); - } - // Join all worker threads. - for (auto &thr : worker_threads_) { - if (thr.joinable()) - thr.join(); + if (part_size == 0) { + // empty => enqueue zero‐work per query + if (job.is_batched) { + for (int64_t q : *job.query_ids) { + result_queue_.enqueue(ResultJob{(int)q, 0, {}, {}}); + } + } else { + result_queue_.enqueue(ResultJob{job.query_id, job.rank, {}, {}}); + } + return; } - worker_threads_.clear(); - workers_initialized_ = false; -} - -void threadsafe_cout(std::string log_msg) -{ - static std::mutex lock; - std::lock_guard guard{ lock }; - std::cout << std::move(log_msg); -} - -// Worker Thread Function -void QueryCoordinator::partition_scan_worker_fn(int core_index) { - - CoreResources &res = core_resources_[core_index]; - int numa_node = 0; - #ifdef QUAKE_USE_NUMA - numa_node = numa_node_of_cpu(core_index); - #endif - NUMAResources &numa_res = numa_resources_[numa_node]; - - if (!set_thread_affinity(core_index)) { - std::cout << "[QueryCoordinator::partition_scan_worker_fn] Failed to set thread affinity on core " << core_index << std::endl; + if (!job.is_batched) { + handle_nonbatched_job(job, res, nr); + } else { + handle_batched_job(job, res, nr); } +} - int64_t total_pull_time = 0; - int64_t total_copy_time = 0; - int64_t total_scan_time = 0; - int64_t total_merge_time = 0; - - while (true) { - - auto job_wait_start = std::chrono::high_resolution_clock::now(); - int64_t job_id; - while (!res.job_queue.try_dequeue(job_id)) { - std::this_thread::sleep_for(std::chrono::microseconds(5)); +void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, + CoreResources &res, + NUMAResources &nr) { + + // ensure buffers + if (res.topk_buffer_pool.size() < 1) { + res.topk_buffer_pool.resize(1); + res.topk_buffer_pool[0] = std::make_shared( + job.k, + metric_ == faiss::METRIC_INNER_PRODUCT, + /*cap=*/100 * job.k, + /*node=*/numa_node_of_cpu(res.core_id) + ); + } else if (res.topk_buffer_pool[0]->k_ != job.k) { + // check capacity + if (res.topk_buffer_pool[0]->capacity_ < job.k) { + res.topk_buffer_pool[0] = std::make_shared( + job.k, + metric_ == faiss::METRIC_INNER_PRODUCT, + /*cap=*/100 * job.k, + /*node=*/numa_node_of_cpu(res.core_id) + ); } + res.topk_buffer_pool[0]->set_k(job.k); + } - auto s0 = std::chrono::high_resolution_clock::now(); - - auto job_wait_end = std::chrono::high_resolution_clock::now(); + auto buf = res.topk_buffer_pool[0]; + res.topk_buffer_pool[0]->reset(); - job_pull_time_ns += std::chrono::duration_cast(job_wait_end - job_wait_start).count(); + scan_list(nr.local_query_buffer, + (float*)partition_manager_->partition_store_->get_codes(job.partition_id), + (int64_t*)partition_manager_->partition_store_->get_ids(job.partition_id), + partition_manager_->partition_store_->list_size(job.partition_id), + partition_manager_->d(), + *buf, + metric_); - auto job_process_start = std::chrono::high_resolution_clock::now(); - shared_ptr local_topk_buffer = res.topk_buffer_pool[0]; + auto tv = buf->get_topk(); + auto ti = buf->get_topk_indices(); + result_queue_.enqueue(ResultJob{job.query_id, job.rank, + std::move(tv), + std::move(ti)}); +} - // Shutdown signal: -1 indicates the worker should exit. - if (job_id == -1) { - break; +void QueryCoordinator::handle_batched_job(const ScanJob &job, + CoreResources &res, + NUMAResources &nr) { + // ensure buffers + if (res.topk_buffer_pool.size() < (size_t)job.num_queries) { + res.topk_buffer_pool.resize(job.num_queries); + for (int64_t i = 0; i < job.num_queries; ++i) { + res.topk_buffer_pool[i] = std::make_shared( + job.k, + metric_ == faiss::METRIC_INNER_PRODUCT, + /*cap=*/num_workers_ * job.k, + /*node=*/numa_node_of_cpu(res.core_id) + ); } - ScanJob job = job_buffer_[job_id]; - -// // Ignore this job if the global buffer is not processing queries. -// if (!global_topk_buffer_pool_[job.query_ids[0]]->currently_processing_query()) { -// // decrement the job counter -// global_topk_buffer_pool_[job.query_ids[0]]->record_empty_job(); -// continue; -// } - - worker_job_counter_[core_index]++; - - // Retrieve partition data. - const float *partition_codes = (float *) partition_manager_->partition_store_->get_codes(job.partition_id); - const int64_t *partition_ids = (int64_t *) partition_manager_->partition_store_->get_ids(job.partition_id); - - // skip partition if it is not found (workaround) - int64_t partition_size = 0; - try { - partition_size = partition_manager_->partition_store_->list_size(job.partition_id); - } catch (const std::runtime_error &e) { - std::cerr << "[QueryCoordinator::partition_scan_worker_fn] Partition " << job.partition_id << " not found." << std::endl; - continue; + // realloc batch query buffer + if (res.batch_queries != nullptr) { + quake_free(res.batch_queries, + size_t(job.num_queries) * partition_manager_->d() * sizeof(float)); } - - // skip partition if it is empty - if (partition_size == 0) { - std::cerr << "[QueryCoordinator::partition_scan_worker_fn] Partition " << job.partition_id << " is empty." << std::endl; - // call dummy batch add to decrement topk_buffer jobs counter. #TODO remove jobs counter from topk_buffer - - if (job.is_batched) { - for (int64_t q = 0; q < job.num_queries; q++) { - int global_q = job.query_ids->at(q); - global_topk_buffer_pool_[global_q]->batch_add(nullptr, nullptr, 0); - } - } else { - global_topk_buffer_pool_[job.query_id]->batch_add(nullptr, nullptr, 0); - } - - - continue; + res.batch_queries = static_cast(quake_alloc( + size_t(job.num_queries) * partition_manager_->d() * sizeof(float), + numa_node_of_cpu(res.core_id))); + + // realloc batch distances and ids + if (res.batch_distances != nullptr) { + quake_free(res.batch_distances, + size_t(job.num_queries) * job.k * sizeof(float)); + } + if (res.batch_ids != nullptr) { + quake_free(res.batch_ids, + size_t(job.num_queries) * job.k * sizeof(int64_t)); + } + res.batch_distances = static_cast(quake_alloc( + size_t(job.num_queries) * job.k * sizeof(float), + numa_node_of_cpu(res.core_id))); + res.batch_ids = static_cast(quake_alloc( + size_t(job.num_queries) * job.k * sizeof(int64_t), + numa_node_of_cpu(res.core_id))); + } else { + for (int64_t i = 0; i < job.num_queries; ++i) { + res.topk_buffer_pool[i]->set_k(job.k); + res.topk_buffer_pool[i]->reset(); } - // Branch for non-batched jobs. - if (!job.is_batched) { - - auto s1 = std::chrono::high_resolution_clock::now(); + // set batch distances and ids to max/min and -1 + for (int64_t i = 0; i < job.num_queries * job.k; ++i) { + res.batch_distances[i] = metric_ == faiss::METRIC_INNER_PRODUCT ? + -std::numeric_limits::infinity() : + std::numeric_limits::infinity(); + res.batch_ids[i] = -1; + } + } - if (local_topk_buffer == nullptr) { - throw std::runtime_error("[partition_scan_worker_fn] local_topk_buffer is null."); - } else { - local_topk_buffer->set_k(job.k); - local_topk_buffer->reset(); - } + // gather queries + for (int64_t i = 0; i < job.num_queries; ++i) { + std::memcpy(res.batch_queries + i * partition_manager_->d(), + job.query_vector + job.query_ids->at(i) * partition_manager_->d(), + partition_manager_->d() * sizeof(float)); + } - auto s2 = std::chrono::high_resolution_clock::now(); - // Perform the scan on the partition. - scan_list(numa_res.local_query_buffer, - partition_codes, - partition_ids, - partition_size, + batched_scan_list(res.batch_queries, + (float*)partition_manager_->partition_store_->get_codes(job.partition_id), + (int64_t*)partition_manager_->partition_store_->get_ids(job.partition_id), + job.num_queries, + partition_manager_->partition_store_->list_size(job.partition_id), partition_manager_->d(), - *local_topk_buffer, - metric_); - auto s3 = std::chrono::high_resolution_clock::now(); - - vector topk = local_topk_buffer->get_topk(); - vector topk_indices = local_topk_buffer->get_topk_indices(); - int64_t n_results = topk_indices.size(); - - // Merge local results into the global query buffer. - global_topk_buffer_pool_[job.query_id]->batch_add(topk.data(), topk_indices.data(), n_results); - job_flags_[job.query_id][job.rank] = true; - - auto s4 = std::chrono::high_resolution_clock::now(); - - // print out timings for worker - auto pull_time = std::chrono::duration_cast(s1 - s0).count(); - auto copy_time = std::chrono::duration_cast(s2 - s1).count(); - auto process_time = std::chrono::duration_cast(s3 - s2).count(); - auto merge_time = std::chrono::duration_cast(s4 - s3).count(); + res.topk_buffer_pool, + metric_, + res.batch_distances, + res.batch_ids); + + vector results(job.num_queries); + for (int64_t i = 0; i < job.num_queries; ++i) { + int g = job.query_ids->at(i); + auto tv = res.topk_buffer_pool[i]->get_topk(); + auto ti = res.topk_buffer_pool[i]->get_topk_indices(); + results[i] = ResultJob{g, + job.ranks->at(i), + std::move(tv), + std::move(ti)}; + } + result_queue_.enqueue_bulk(results.begin(), + job.num_queries); +} - total_pull_time += pull_time; - total_copy_time += copy_time; - total_scan_time += process_time; - total_merge_time += merge_time; +// — Main‐thread: worker_scan — + +void QueryCoordinator::init_global_buffers(int64_t nQ, + int K, + Tensor &partition_ids, + shared_ptr params) { + std::lock_guard lg(global_mutex_); + // resize or reset + if (global_topk_buffer_pool_.size() < (size_t) nQ) { + size_t old = global_topk_buffer_pool_.size(); + global_topk_buffer_pool_.resize(nQ); + for (int64_t q = old; q < nQ; ++q) { + global_topk_buffer_pool_[q] = std::make_shared( + K, + metric_ == faiss::METRIC_INNER_PRODUCT, + /*cap=*/num_workers_ * K * 2, + /*node=*/0 + ); } - // Batched job branch. - else { - if (!job.query_vector || job.num_queries == 0) { - throw std::runtime_error("[partition_scan_worker_fn] Invalid batched job."); - } - - auto s1 = std::chrono::high_resolution_clock::now(); - - int64_t d = partition_manager_->d(); - std::vector query_subset(job.num_queries * d); - for (int i = 0; i < job.num_queries; i++) { - int64_t global_q = job.query_ids->at(i); - memcpy(&query_subset[i * d], - job.query_vector + global_q * d, - d * sizeof(float)); - } - - if(memcpy(numa_res.local_query_buffer, - query_subset.data(), - query_subset.size() * sizeof(float)) == nullptr) { - throw std::runtime_error("[partition_scan_worker_fn] memcpy failed."); - } - - // Use a thread_local vector to hold one buffer per query. - if (res.topk_buffer_pool.size() < static_cast(job.num_queries)) { - res.topk_buffer_pool.resize(job.num_queries); - for (int64_t q = 0; q < job.num_queries; ++q) { - res.topk_buffer_pool[q] = std::make_shared(job.k, metric_ == faiss::METRIC_INNER_PRODUCT); - } - } else { - for (int64_t q = 0; q < job.num_queries; ++q) { - res.topk_buffer_pool[q]->set_k(job.k); - res.topk_buffer_pool[q]->reset(); - } - } - - auto s2 = std::chrono::high_resolution_clock::now(); - - // Process the batched job. - batched_scan_list(numa_res.local_query_buffer, - partition_codes, - partition_ids, - job.num_queries, - partition_size, - partition_manager_->d(), - res.topk_buffer_pool, - metric_); - - auto s3 = std::chrono::high_resolution_clock::now(); - - for (int64_t q = 0; q < job.num_queries; q++) { - int64_t global_q = job.query_ids->at(q); - - vector topk = res.topk_buffer_pool[q]->get_topk(); - vector topk_indices = res.topk_buffer_pool[q]->get_topk_indices(); - int n_results = topk_indices.size(); - - global_topk_buffer_pool_[global_q]->batch_add(topk.data(), topk_indices.data(), n_results); - } - - auto s4 = std::chrono::high_resolution_clock::now(); - - // print out timings for worker - auto pull_time = std::chrono::duration_cast(s1 - s0).count(); - auto copy_time = std::chrono::duration_cast(s2 - s1).count(); - auto process_time = std::chrono::duration_cast(s3 - s2).count(); - auto merge_time = std::chrono::duration_cast(s4 - s3).count(); - - total_pull_time += pull_time; - total_copy_time += copy_time; - total_scan_time += process_time; - total_merge_time += merge_time; + } else { + for (int64_t q = 0; q < nQ; ++q) { + global_topk_buffer_pool_[q]->set_k(K); + global_topk_buffer_pool_[q]->reset(); } - auto job_process_end = std::chrono::high_resolution_clock::now(); - job_process_time_ns += std::chrono::duration_cast(job_process_end - job_process_start).count(); } - std::string log_message = - "[QueryCoordinator::partition_scan_worker_fn] Worker " + std::to_string(core_index) + - ": total_pull_time=" + std::to_string(total_pull_time / 1000) + - ", total_copy_time=" + std::to_string(total_copy_time / 1000) + - ", total_scan_time=" + std::to_string(total_scan_time / 1000) + - ", merge_time=" + std::to_string(total_merge_time / 1000) + '\n'; - - threadsafe_cout(log_message); } -// Worker-Based Scan Implementation -shared_ptr QueryCoordinator::worker_scan( - Tensor x, - Tensor partition_ids, - shared_ptr search_params) { - - auto start_time = high_resolution_clock::now(); - - if (!partition_manager_) { - throw std::runtime_error("[QueryCoordinator::worker_scan] partition_manager_ is null."); - } - - if (!x.defined() || x.size(0) == 0) { - auto empty_result = std::make_shared(); - empty_result->ids = torch::empty({0}, torch::kInt64); - empty_result->distances = torch::empty({0}, torch::kFloat32); - empty_result->timing_info = std::make_shared(); - return empty_result; - } - - int64_t num_queries = x.size(0); - int64_t dimension = x.size(1); - int k = search_params->k; - int64_t nlist = partition_manager_->nlist(); - bool use_aps = (search_params->recall_target > 0.0 && !search_params->batched_scan && parent_ != nullptr); - auto timing_info = make_shared(); - timing_info->n_queries = num_queries; - timing_info->n_clusters = nlist; - timing_info->search_params = search_params; +void QueryCoordinator::copy_query_to_numa(const float *xptr, int64_t nQ, int64_t D) { - float *x_ptr = x.data_ptr(); - - if (partition_ids.dim() == 1) { - partition_ids = partition_ids.unsqueeze(0).expand({num_queries, partition_ids.size(0)}); + for (int node = 0; node < get_num_numa_nodes(); ++node) { + auto &nr = numa_resources_[node]; + if (nr.buffer_size < size_t(nQ) * size_t(D) * sizeof(float)) { + quake_free(nr.local_query_buffer, nr.buffer_size); + nr.local_query_buffer = static_cast(quake_alloc( + size_t(nQ) * size_t(D) * sizeof(float), + node)); + nr.buffer_size = size_t(nQ) * size_t(D) * sizeof(float); + } + std::memcpy(nr.local_query_buffer, + xptr, + size_t(nQ) * size_t(D) * sizeof(float)); } +} - auto partition_ids_accessor = partition_ids.accessor(); +void QueryCoordinator::enqueue_scan_jobs(Tensor x, + Tensor partition_ids, + shared_ptr params) +{ + int64_t nQ = x.size(0), D = x.size(1); + float *xptr = x.data_ptr(); -// job_buffer_.clear(); - next_job_id_.store(0); + // flatten jobs + next_job_id_ = 0; job_flags_.clear(); - job_flags_.resize(num_queries); - for (int64_t q = 0; q < num_queries; q++) { + job_flags_.resize(nQ); + for (int64_t q = 0; q < nQ; ++q) { job_flags_[q] = vector>(partition_ids.size(1)); - for (int64_t p = 0; p < partition_ids.size(1); p++) { + for (int p = 0; p < partition_ids.size(1); ++p) { job_flags_[q][p] = false; } } + job_buffer_.clear(); - job_pull_time_ns = 0; - job_process_time_ns = 0; - - { - std::lock_guard lock(global_mutex_); - if (global_topk_buffer_pool_.size() < static_cast(num_queries)) { - std::cout << "Resizing query_topk_buffers_ from " << global_topk_buffer_pool_.size() - << " to " << num_queries << std::endl; - int old_size = global_topk_buffer_pool_.size(); - global_topk_buffer_pool_.resize(num_queries); - for (int64_t q = old_size; q < num_queries; q++) { - global_topk_buffer_pool_[q] = std::make_shared(k, metric_ == faiss::METRIC_INNER_PRODUCT); - } - } else { - for (int64_t q = 0; q < num_queries; q++) { - global_topk_buffer_pool_[q]->set_k(k); - global_topk_buffer_pool_[q]->reset(); - global_topk_buffer_pool_[q]->set_processing_query(true); + auto pid_acc = partition_ids.accessor(); + if (!params->batched_scan) { + // one job per (q,p) + for (int64_t q = 0; q < nQ; ++q) { + const float* qptr = xptr + q*D; + for (int p = 0; p < partition_ids.size(1); ++p) { + int64_t pid = pid_acc[q][p]; + if (pid < 0) continue; + ScanJob job; + job.is_batched = false; + job.query_id = (int)q; + job.partition_id = pid; + job.k = params->k; + job.query_vector = qptr; + job.rank = p; + size_t jid = next_job_id_++; + job_buffer_.push_back(job); + core_resources_[pid % num_workers_].job_queue.enqueue((int64_t)jid); } } - for (int64_t q = 0; q < num_queries; ++q) { - int valid = 0; - for (int64_t p = 0; p < partition_ids.size(1); ++p) - if (partition_ids_accessor[q][p] != -1) ++valid; - - global_topk_buffer_pool_[q]->set_jobs_left(valid); - } - } - auto end_time = high_resolution_clock::now(); - timing_info->buffer_init_time_ns = - duration_cast(end_time - start_time).count(); - - start_time = high_resolution_clock::now(); - - for (auto &nr : numa_resources_) { - std::memcpy(nr.local_query_buffer, - x_ptr, // q == 0 - size_t(dimension) * sizeof(float)); - } - - if (search_params->batched_scan) { - auto partition_ids_accessor = partition_ids.accessor(); + } else { job_buffer_.resize(partition_manager_->nlist()); auto pids = partition_manager_->get_partition_ids(); auto pids_acc = pids.accessor(); @@ -436,207 +350,256 @@ shared_ptr QueryCoordinator::worker_scan( ScanJob job; job.is_batched = true; job.partition_id = pids_acc[i]; - job.k = k; + job.k = params->k; job.query_vector = x.data_ptr(); job.num_queries = x.size(0); job.query_ids = all_query_ids_ptr; + job.ranks = make_shared>(x.size(0), i); int core_id = partition_manager_->get_partition_core_id(pids_acc[i]); if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } - size_t jid = next_job_id_.fetch_add(1, std::memory_order_acq_rel); + size_t jid = next_job_id_++; job_buffer_[jid] = job; core_resources_[core_id].job_queue.enqueue(jid); } } else { - std::unordered_map>> per_partition_query_ids; // for batched scan - for (int64_t q = 0; q < num_queries; q++) { + std::unordered_map>>> per_partition_query_ids; // for batched scan + for (int64_t q = 0; q < nQ; q++) { for (int64_t p = 0; p < partition_ids.size(1); p++) { - int64_t pid = partition_ids_accessor[q][p]; + int64_t pid = pid_acc[q][p]; if (pid < 0) continue; if (per_partition_query_ids[pid] == nullptr) { - per_partition_query_ids[pid] = make_shared>(); + per_partition_query_ids[pid] = make_shared>>(); } - per_partition_query_ids[pid]->push_back(q); + per_partition_query_ids[pid]->push_back({q, p}); } } for (auto &kv : per_partition_query_ids) { + + auto qids_and_ranks = kv.second; + vector qids(qids_and_ranks->size()); + vector ranks(qids_and_ranks->size()); + for (size_t i = 0; i < qids_and_ranks->size(); ++i) { + qids[i] = (*qids_and_ranks)[i].first; + ranks[i] = (*qids_and_ranks)[i].second; + } + ScanJob job; job.is_batched = true; job.partition_id = kv.first; - job.k = k; + job.k = params->k; job.query_vector = x.data_ptr(); job.num_queries = kv.second->size(); - job.query_ids = kv.second; + job.query_ids = make_shared>(qids); + job.ranks = make_shared>(ranks); int core_id = partition_manager_->get_partition_core_id(kv.first); if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } - size_t jid = next_job_id_.fetch_add(1, std::memory_order_acq_rel); + size_t jid = next_job_id_++; job_buffer_[jid] = job; core_resources_[core_id].job_queue.enqueue(jid); } } - } else { - auto partition_ids_accessor = partition_ids.accessor(); - - job_buffer_.resize(num_queries * partition_ids.size(1)); - int jid = 0; - for (int q = 0; q < num_queries; q++) { - for (int64_t p = 0; p < partition_ids.size(1); p++) { - int64_t pid = partition_ids_accessor[q][p]; - if (pid == -1) continue; - - ScanJob job; - job.is_batched = false; - job.query_id = q; - job.partition_id = pid; - job.k = k; - job.query_vector = x_ptr + q * dimension; - job.num_queries = 1; - job.rank = p; - - int core_id = pid % num_workers_; - job_buffer_[jid] = std::move(job); - core_resources_[core_id].job_queue.enqueue(jid); - jid++; - } - } } - auto topk_ids = torch::full({num_queries, k}, -1, torch::kInt64); - auto topk_dists = torch::full({num_queries, k}, - (metric_ == faiss::METRIC_INNER_PRODUCT) - ? -std::numeric_limits::infinity() - : std::numeric_limits::infinity(), - torch::kFloat32); - end_time = high_resolution_clock::now(); - timing_info->job_enqueue_time_ns = duration_cast(end_time - start_time).count(); - - auto last_flush_time = high_resolution_clock::now(); - vector> boundary_distances(num_queries); - if (use_aps && parent_) { - for (int64_t q = 0; q < num_queries; q++) { - vector partition_ids_to_scan_vec = vector(partition_ids[q].data_ptr(), - partition_ids[q].data_ptr() + partition_ids[q].size(0)); +} + +void QueryCoordinator::drain_and_apply_aps(Tensor x, + Tensor partition_ids, + bool use_aps, + float recall_target, + float aps_flush_period_us, + shared_ptr timing) +{ + // precompute boundary distances if needed + int nQ = x.size(0); + int D = x.size(1); + int nprobe = partition_ids.size(1); + vector> boundary_dist(nQ); + vector query_radius(nQ, 0.0f); + vector> probs(nQ); + if (use_aps) { + + for (int64_t q = 0; q < nQ; ++q) { + vector partition_ids_to_scan_vec = std::vector(partition_ids[q].data_ptr(), + partition_ids[q].data_ptr() + partition_ids[q].size(0)); vector cluster_centroids = parent_->partition_manager_->get_vectors(partition_ids_to_scan_vec); - boundary_distances[q] = compute_boundary_distances(x[q], - cluster_centroids, - metric_ == faiss::METRIC_L2); + boundary_dist[q] = compute_boundary_distances(x[q], cluster_centroids, metric_ == faiss::METRIC_L2); } + } - start_time = high_resolution_clock::now(); - last_flush_time = high_resolution_clock::now(); + auto last_flush = high_resolution_clock::now(); - vector query_radius(num_queries, 0.0f); - vector> probs(num_queries); while (true) { - // check if all jobs have been processed + // 1) drain all ready results + ResultJob rj; + while (result_queue_.try_dequeue(rj)) { + global_topk_buffer_pool_[rj.query_id] + ->batch_add(rj.distances.data(), + rj.indices.data(), + (int)rj.indices.size()); + + job_flags_[rj.query_id][rj.rank] = true; + } + // 2) check done bool all_done = true; - for (int64_t q = 0; q < num_queries; q++) { - if (global_topk_buffer_pool_[q]->jobs_left_ == 0) { - // flush the topk buffer (if needed) - global_topk_buffer_pool_[q]->flush(); - } else { - all_done = false; + for (int64_t q = 0; q < nQ; ++q) { + for (int64_t p = 0; p < nprobe; ++p) { + if (!job_flags_[q][p]) { + all_done = false; + break; + } } } - - if (all_done) { - break; - } - - // check if recall target has been reached - if (use_aps && duration_cast(high_resolution_clock::now() - last_flush_time).count() - > search_params->aps_flush_period_us) { - for (int64_t q = 0; q < num_queries; q++) { - auto curr_buffer = global_topk_buffer_pool_[q]; - int scanned = curr_buffer->get_num_partitions_scanned(); - if (curr_buffer->currently_processing_query() && - scanned > 0 && scanned < (int) boundary_distances[q].size()) { - float radius = curr_buffer->get_kth_distance(); - - if (query_radius[q] != radius) { - query_radius[q] = radius; - - // recompute recall profile if the radius has changed - probs[q] = compute_recall_profile(boundary_distances[q], - radius, - dimension, - {}, - search_params->use_precomputed, - metric_ == faiss::METRIC_L2); + if (all_done) break; + + // 3) APS early-stop + if (use_aps && duration_cast(high_resolution_clock::now() - last_flush).count() + > aps_flush_period_us) + { + for (int64_t q = 0; q < nQ; ++q) { + auto buf = global_topk_buffer_pool_[q]; + float r = buf->get_kth_distance(); + if (r != query_radius[q]) { + query_radius[q] = r; + probs[q] = compute_recall_profile( + boundary_dist[q], + r, + D, + {}, + true, + metric_==faiss::METRIC_L2 + ); } - - float cum = 0.0f; - for (int i = 0; i < partition_ids.size(1); i++) { - if (job_flags_[q][i]) { - cum += probs[q][i]; - } - } - if (cum > search_params->recall_target) { - curr_buffer->set_processing_query(false); + float cum=0; + for (int i=0; i<(int)job_flags_[q].size(); ++i) + if (job_flags_[q][i]) cum += probs[q][i]; + if (cum > recall_target) { + // set all jobs to done + for (int i=0; i<(int)job_flags_[q].size(); ++i) + job_flags_[q][i] = true; } } } - last_flush_time = high_resolution_clock::now(); - } - std::this_thread::sleep_for(microseconds(5)); + last_flush = high_resolution_clock::now(); + std::this_thread::sleep_for(std::chrono::microseconds(5)); } - end_time = high_resolution_clock::now(); - timing_info->job_wait_time_ns = - duration_cast(end_time - start_time).count(); - - // Aggregate results. - start_time = high_resolution_clock::now(); - auto ids_accessor = topk_ids.accessor(); - auto dists_accessor = topk_dists.accessor(); +} + +std::shared_ptr +QueryCoordinator::aggregate_scan_results(int64_t nQ, + int K, + shared_ptr timing) +{ + // build output tensors + auto out_ids = torch::full({nQ,K}, -1, torch::kInt64); + auto out_dists = torch::full({nQ,K}, + (metric_==faiss::METRIC_INNER_PRODUCT + ? -std::numeric_limits::infinity() + : std::numeric_limits::infinity()), + torch::kFloat32); + { - std::lock_guard lock(global_mutex_); - for (int64_t q = 0; q < num_queries; q++) { - auto topk = global_topk_buffer_pool_[q]->get_topk(); - auto ids = global_topk_buffer_pool_[q]->get_topk_indices(); - for (int i = 0; i < k; i++) { - if (i < (int) ids.size()) { - ids_accessor[q][i] = ids[i]; - dists_accessor[q][i] = topk[i]; - } else { - ids_accessor[q][i] = -1; - dists_accessor[q][i] = (metric_ == faiss::METRIC_INNER_PRODUCT) - ? -std::numeric_limits::infinity() - : std::numeric_limits::infinity(); - } + std::lock_guard lg(global_mutex_); + auto id_acc = out_ids.accessor(); + auto d_acc = out_dists.accessor(); + for (int64_t q = 0; q < nQ; ++q) { + auto tv = global_topk_buffer_pool_[q]->get_topk(); + auto ti = global_topk_buffer_pool_[q]->get_topk_indices(); + for (int i = 0; i < (int)ti.size() && i < K; ++i) { + id_acc[q][i] = ti[i]; + d_acc [q][i] = tv[i]; } - timing_info->partitions_scanned += global_topk_buffer_pool_[q]->get_num_partitions_scanned(); + } + } - if (search_params->track_hits && maintenance_policy_ != nullptr) { - vector partition_ids_vec; - for (int64_t p = 0; p < partition_ids.size(1); p++) { - if (job_flags_[q][p]) { - partition_ids_vec.push_back(partition_ids_accessor[q][p]); - } - } - maintenance_policy_->record_query_hits(partition_ids_vec); - } + auto res = std::make_shared(); + res->ids = out_ids; + res->distances = out_dists; + res->timing_info = timing; + return res; +} + +std::shared_ptr QueryCoordinator::worker_scan( + Tensor x, + Tensor partition_ids, + std::shared_ptr params) +{ + int64_t nQ = x.size(0), D = x.size(1); + int K = params->k; + bool use_aps = (params->recall_target>0 && !params->batched_scan && parent_); + + auto timing = std::make_shared(); + timing->n_queries = nQ; + timing->n_clusters = partition_manager_->nlist(); + timing->search_params = params; + + // 1) init global buffers & jobs_left + init_global_buffers(nQ, K, partition_ids, params); + + // 2) copy query vec to NUMA buffers + copy_query_to_numa(x.data_ptr(), nQ, D); + + // 3) enqueue jobs + enqueue_scan_jobs(x, partition_ids, params); + + // 4) drain results + APS + drain_and_apply_aps(x, partition_ids, use_aps, params->recall_target, + params->aps_flush_period_us, timing); + + // 5) aggregate & return + return aggregate_scan_results(nQ, K, timing); +} + +// Initialize Worker Threads +void QueryCoordinator::initialize_workers(int num_cores, bool use_numa) { + if (workers_initialized_) { + std::cerr << "[QueryCoordinator::initialize_workers] Workers already initialized." << std::endl; + return; + } + + std::cout << "[QueryCoordinator::initialize_workers] Initializing " << num_cores << " worker threads with use_numa=" << use_numa << + std::endl; + + partition_manager_->distribute_partitions(num_cores, use_numa); + + core_resources_.resize(num_cores); + worker_threads_.resize(num_cores); + for (int i = 0; i < num_cores; i++) { + if (!set_thread_affinity(i)) { + std::cout << "[QueryCoordinator::initialize_workers] Failed to set thread affinity on core " << i << std::endl; } + allocate_core_resources(i, 1, 10, partition_manager_->d()); + worker_threads_[i] = std::thread(&QueryCoordinator::partition_scan_worker_fn, this, i); } - end_time = high_resolution_clock::now(); - timing_info->result_aggregate_time_ns = duration_cast(end_time - start_time).count(); - auto search_result = std::make_shared(); - search_result->ids = topk_ids; - search_result->distances = topk_dists; - search_result->timing_info = timing_info; + workers_initialized_ = true; + + // set main thread on separate thread from workers + int num_cores_on_machine = std::thread::hardware_concurrency(); + set_thread_affinity(num_cores % num_cores_on_machine); +} -// // print out timing info -// std::cout << "[QueryCoordinator::worker_scan] Timing info: " << std::endl; -// std::cout << "Total time: " << timing_info->total_time_ns / 1e6 << " ms" << std::endl; -// std::cout << "Job enqueue time: " << timing_info->job_enqueue_time_ns / 1e6 << " ms" << std::endl; -// std::cout << "Job wait time: " << timing_info->job_wait_time_ns / 1e6 << " ms" << std::endl; -// std::cout << "Buffer init time: " << timing_info->buffer_init_time_ns / 1e6 << " ms" << std::endl; -// std::cout << "Result agg time: " << timing_info->result_aggregate_time_ns / 1e6 << " ms" << std::endl; +// Shutdown Worker Threads +void QueryCoordinator::shutdown_workers() { + if (!workers_initialized_) { + return; + } - return search_result; + stop_workers_.store(true); + // Enqueue a special shutdown job for each core. + for (auto &res : core_resources_) { + res.job_queue.enqueue(-1); + } + // Join all worker threads. + for (auto &thr : worker_threads_) { + if (thr.joinable()) + thr.join(); + } + worker_threads_.clear(); + workers_initialized_ = false; } shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partition_ids, @@ -688,7 +651,9 @@ shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partitio auto t1 = high_resolution_clock::now(); - auto topk_buf = std::make_shared(k, is_descending); + auto topk_buf = std::make_shared(k, is_descending, + /*cap=*/10 * k, + /*node=*/0); const float* query_vec = x_ptr + q * dimension; int num_parts = partition_ids.size(1); @@ -902,6 +867,13 @@ shared_ptr QueryCoordinator::search(Tensor x, shared_ptr QueryCoordinator::scan_partitions(Tensor x, Tensor partition_ids, shared_ptr search_params) { + + if (partition_ids.dim() == 0) { + throw std::runtime_error("[QueryCoordinator::scan_partitions] partition_ids is empty."); + } + if (partition_ids.dim() == 1) { + partition_ids = partition_ids.unsqueeze(0).expand({x.size(0), partition_ids.size(0)}); + } if (workers_initialized_) { if (debug_) std::cout << "[QueryCoordinator::scan_partitions] Using worker-based scan." << std::endl; return worker_scan(x, partition_ids, search_params); diff --git a/test/cpp/benchmark.cpp b/test/cpp/benchmark.cpp index 3357086a..f4b8d380 100644 --- a/test/cpp/benchmark.cpp +++ b/test/cpp/benchmark.cpp @@ -29,7 +29,7 @@ using torch::Tensor; static const int64_t DIM = 128; static const int64_t NUM_VECTORS = 100000; // number of database vectors static const int64_t N_LIST = 1000; // number of clusters for IVF -static const int64_t NUM_QUERIES = 1000; // number of queries for search benchmark +static const int64_t NUM_QUERIES = 10; // number of queries for search benchmark static const int64_t K = 10; // top-K neighbors static const int64_t N_PROBE = 20; // number of probes for IVF static const int64_t N_WORKERS = 12; // number of workers for parallel query coordinator diff --git a/test/cpp/latency_estimator.cpp b/test/cpp/latency_estimator.cpp index 80ed570a..495ec149 100644 --- a/test/cpp/latency_estimator.cpp +++ b/test/cpp/latency_estimator.cpp @@ -19,7 +19,7 @@ static float measure_actual_latency(const ListScanLatencyEstimator& estimator, torch::Tensor ids = torch::randperm(n); torch::Tensor query = torch::rand({estimator.d_}); - auto topk_buffer = make_shared(k, false); + auto topk_buffer = make_shared(k, false, k * 100, 0); const float* query_ptr = query.data_ptr(); const float* vectors_ptr = vectors.data_ptr(); diff --git a/test/cpp/list_scanning.cpp b/test/cpp/list_scanning.cpp index 5c5e82d8..518972e0 100644 --- a/test/cpp/list_scanning.cpp +++ b/test/cpp/list_scanning.cpp @@ -14,7 +14,7 @@ class ListScanningTest : public ::testing::Test { protected: // Helper function to create a TopkBuffer std::shared_ptr create_buffer(int k, bool is_descending) { - return std::make_shared>(k, is_descending); + return std::make_shared>(k, is_descending, k * 100, 0); } }; @@ -448,7 +448,7 @@ TEST_F(ListScanningTest, LargeListCorrectnessInnerProduct) { auto gt_dists_accessor = gt_dists.accessor(); // perform single query scan first - auto buffer = make_shared(k, true); + auto buffer = make_shared(k, true, k * 100, 0); for (int i = 0; i < num_queries; i++) { scan_list( query_vectors[i].data_ptr(), @@ -514,7 +514,7 @@ TEST_F(ListScanningTest, LargeListCorrectnessL2) { auto gt_dists_accessor = gt_dists.accessor(); // perform single query scan first - auto buffer = make_shared(k, false); + auto buffer = make_shared(k, false, k * 100, 0); for (int i = 0; i < num_queries; i++) { scan_list( query_vectors[i].data_ptr(), diff --git a/test/cpp/query_coordinator.cpp b/test/cpp/query_coordinator.cpp index d272f2d0..0ed914b2 100644 --- a/test/cpp/query_coordinator.cpp +++ b/test/cpp/query_coordinator.cpp @@ -169,34 +169,6 @@ TEST_F(QueryCoordinatorTest, WorkerInitializationTest) { ASSERT_TRUE(coordinator->workers_initialized_); } -TEST_F(QueryCoordinatorTest, FlatWorkerScan) { - int num_workers = 4; - - // create flat index - auto flat_index = std::make_shared(); - auto build_params = std::make_shared(); - build_params->nlist = 1; - build_params->metric = "l2"; - flat_index->build(torch::randn({20, dimension_}), torch::arange(20), build_params); - - // create coordinator with workers - auto coordinator = std::make_shared( - flat_index->parent_, - flat_index->partition_manager_, - nullptr, - faiss::METRIC_L2, - num_workers - ); - - auto search_params = std::make_shared(); - search_params->k = 2; - - auto result_worker = coordinator->search(queries_, search_params); - ASSERT_TRUE(result_worker != nullptr); - ASSERT_EQ(result_worker->ids.sizes(), (std::vector{queries_.size(0), search_params->k})); - ASSERT_EQ(result_worker->distances.sizes(), (std::vector{queries_.size(0), search_params->k})); -} - // Test that worker-based scan produces the same results as serial scan TEST_F(QueryCoordinatorTest, WorkerScanCorrectnessTest) { // Initialize QueryCoordinator with workers diff --git a/test/cpp/topk_buffer.cpp b/test/cpp/topk_buffer.cpp index c2afaaec..88225a65 100644 --- a/test/cpp/topk_buffer.cpp +++ b/test/cpp/topk_buffer.cpp @@ -13,7 +13,7 @@ class TypedTopKBufferTest : public ::testing::Test { protected: // Helper function to create a TopkBuffer std::shared_ptr create_buffer(int k, bool is_descending) { - return std::make_shared>(k, is_descending); + return std::make_shared>(k, is_descending, k* 100, 0); } }; From e4ba407202f5e7ed08b7812a8eb1a596b5b273ee Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 02:18:56 -0500 Subject: [PATCH 155/323] NUMA allocation for topk buffer --- src/cpp/src/query_coordinator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 15820c71..13a5f423 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -78,7 +78,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { set_thread_affinity(core_index); - while (true) { + while (!stop_workers_) { int64_t jid = pop_scan_job(res); if (jid == -1) break; process_scan_job(job_buffer_[jid], res); From 629f30b856fbc819228ab59954473e0bc8791204 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 02:25:51 -0500 Subject: [PATCH 156/323] NUMA allocation for topk buffer --- src/cpp/include/list_scanning.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 6aa4359d..3696d387 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -190,15 +190,19 @@ class TypedTopKBuffer { } else { miniselect::pdqpartial_sort_branchless(ord_, ord_ + m, ord_ + n, cmpIdx); } + + } else { + miniselect::pdqsort_branchless(ord_, ord_ + n, cmpIdx); } - // 3) sort the top‐m prefix + + // 4) fully sort the top-m indices so they are in strictly correct order miniselect::pdqsort_branchless(ord_, ord_ + m, cmpIdx); - // 4) copy the m winners back to front of vals_/ids_ + // 5) copy the winners back to vals_/ids_ and clamp head_ for (int i = 0; i < m; ++i) { int idx = ord_[i]; vals_[i] = vals_[idx]; - ids_[i] = ids_[idx]; + ids_ [i] = ids_ [idx]; } // 5) clamp head_ and return the k-th value (or extreme if too few) From 3e67865cfa3aa8bc9cf1a5263dfdf1afa7e774d3 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 02:33:41 -0500 Subject: [PATCH 157/323] NUMA allocation for topk buffer --- src/cpp/include/list_scanning.h | 4 ++-- src/cpp/src/query_coordinator.cpp | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 3696d387..c2a7d5c2 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -199,10 +199,10 @@ class TypedTopKBuffer { miniselect::pdqsort_branchless(ord_, ord_ + m, cmpIdx); // 5) copy the winners back to vals_/ids_ and clamp head_ - for (int i = 0; i < m; ++i) { + for (int i = m - 1; i >= 0; --i) { int idx = ord_[i]; vals_[i] = vals_[idx]; - ids_ [i] = ids_ [idx]; + ids_[i] = ids_[idx]; } // 5) clamp head_ and return the k-th value (or extreme if too few) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 13a5f423..b548990c 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -332,9 +332,9 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, job.k = params->k; job.query_vector = qptr; job.rank = p; - size_t jid = next_job_id_++; job_buffer_.push_back(job); - core_resources_[pid % num_workers_].job_queue.enqueue((int64_t)jid); + core_resources_[pid % num_workers_].job_queue.enqueue(next_job_id_); + next_job_id_++; } } } else { @@ -359,9 +359,9 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } - size_t jid = next_job_id_++; - job_buffer_[jid] = job; - core_resources_[core_id].job_queue.enqueue(jid); + job_buffer_[next_job_id_] = job; + core_resources_[core_id].job_queue.enqueue(next_job_id_); + next_job_id_++; } } else { @@ -398,9 +398,9 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, if (core_id < 0) { throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); } - size_t jid = next_job_id_++; - job_buffer_[jid] = job; - core_resources_[core_id].job_queue.enqueue(jid); + job_buffer_[next_job_id_] = job; + core_resources_[core_id].job_queue.enqueue(next_job_id_); + next_job_id_++; } } } From 3ba5d6f34d740c639cb0d3a82941cce2ff36fb36 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 02:38:33 -0500 Subject: [PATCH 158/323] NUMA allocation for topk buffer --- src/cpp/src/query_coordinator.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index b548990c..1a07a1f1 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -305,6 +305,8 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, int64_t nQ = x.size(0), D = x.size(1); float *xptr = x.data_ptr(); + auto partition_ids_acc = partition_ids.accessor(); + // flatten jobs next_job_id_ = 0; job_flags_.clear(); @@ -313,6 +315,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, job_flags_[q] = vector>(partition_ids.size(1)); for (int p = 0; p < partition_ids.size(1); ++p) { job_flags_[q][p] = false; + if (partition_ids_acc[q][p] < 0) job_flags_[q][p] = true; } } job_buffer_.clear(); From 1911d9b72ac08e7c72d5e132154e170d89d13ddc Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 03:07:31 -0500 Subject: [PATCH 159/323] NUMA allocation for topk buffer --- src/cpp/src/query_coordinator.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 1a07a1f1..771949f2 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -102,6 +102,7 @@ void QueryCoordinator::process_scan_job(ScanJob job, part_size = partition_manager_->partition_store_->list_size(job.partition_id); } catch (...) { std::cerr << "[partition_scan_worker_fn] Partition " << job.partition_id << " not found.\n"; + result_queue_.enqueue(ResultJob{job.query_id, job.rank, {}, {}}); return; } @@ -307,6 +308,8 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, auto partition_ids_acc = partition_ids.accessor(); + std::cout << "[QueryCoordinator::enqueue_scan_jobs] Enqueueing scan jobs...\n"; + // flatten jobs next_job_id_ = 0; job_flags_.clear(); From 3631109f068c1c280c35ba81fd821b8738aa41a3 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 03:28:04 -0500 Subject: [PATCH 160/323] NUMA allocation for topk buffer --- src/cpp/include/query_coordinator.h | 2 +- src/cpp/src/query_coordinator.cpp | 172 +++++++++++++++++++--------- 2 files changed, 120 insertions(+), 54 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 56628210..324a5bde 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -92,7 +92,7 @@ class QueryCoordinator { bool debug_ = false; ///< Debug mode flag. std::vector job_buffer_; - int next_job_id_{0}; + int next_job_id_ = 0; ///< ID for the next job to be processed. vector>> job_flags_; ///< Flags to track job completion std::atomic job_pull_time_ns = 0; ///< Time spent pulling jobs from the queue. std::atomic job_process_time_ns = 0; ///< Time spent processing jobs. diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 771949f2..fdb5001e 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -60,14 +60,6 @@ void QueryCoordinator::allocate_core_resources(int core_idx, } } -int64_t QueryCoordinator::pop_scan_job(CoreResources &res) { - int64_t jid; - while (!res.job_queue.try_dequeue(jid)) { - std::this_thread::sleep_for(std::chrono::microseconds(5)); - } - return jid; -} - void QueryCoordinator::partition_scan_worker_fn(int core_index) { CoreResources &res = core_resources_[core_index]; int numa_node = 0; @@ -78,9 +70,15 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { set_thread_affinity(core_index); + int64_t jid; while (!stop_workers_) { - int64_t jid = pop_scan_job(res); + + if (!res.job_queue.try_dequeue(jid)) { + std::this_thread::sleep_for(std::chrono::microseconds(5)); + continue; + } if (jid == -1) break; + process_scan_job(job_buffer_[jid], res); } } @@ -154,19 +152,47 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, auto buf = res.topk_buffer_pool[0]; res.topk_buffer_pool[0]->reset(); - scan_list(nr.local_query_buffer, - (float*)partition_manager_->partition_store_->get_codes(job.partition_id), - (int64_t*)partition_manager_->partition_store_->get_ids(job.partition_id), - partition_manager_->partition_store_->list_size(job.partition_id), - partition_manager_->d(), - *buf, - metric_); - - auto tv = buf->get_topk(); - auto ti = buf->get_topk_indices(); - result_queue_.enqueue(ResultJob{job.query_id, job.rank, - std::move(tv), - std::move(ti)}); + try { + // It's good practice to re-fetch or validate partition data here if it could + // have changed since process_scan_job's initial checks, especially with maintenance. + const float* codes = (float*)partition_manager_->partition_store_->get_codes(job.partition_id); + const int64_t* ids = (int64_t*)partition_manager_->partition_store_->get_ids(job.partition_id); + int64_t part_size = partition_manager_->partition_store_->list_size(job.partition_id); + int D = partition_manager_->d(); + + // Defensive check for partition validity right before scan + if (!codes || !ids || part_size <= 0) { + std::cerr << "[QueryCoordinator::handle_nonbatched_job] Partition " << job.partition_id + << " invalid or empty before scan for query " << job.query_id + << ". Enqueuing empty result.\n"; + result_queue_.enqueue(ResultJob{job.query_id, job.rank, {}, {}}); + return; // Important to return after enqueueing the placeholder + } + + scan_list(nr.local_query_buffer, // Or job.query_vector depending on NUMA strategy + codes, + ids, + part_size, + D, + *buf, + metric_); + + // If scan_list completes, enqueue its results + auto tv = buf->get_topk(); + auto ti = buf->get_topk_indices(); + result_queue_.enqueue(ResultJob{job.query_id, job.rank, std::move(tv), std::move(ti)}); + + } catch (const std::exception& e) { + std::cerr << "[QueryCoordinator::handle_nonbatched_job] Exception during scan for partition " + << job.partition_id << ", query " << job.query_id << ": " << e.what() + << ". Enqueuing empty result.\n"; + result_queue_.enqueue(ResultJob{job.query_id, job.rank, {}, {}}); // Enqueue empty result on error + } catch (...) { + std::cerr << "[QueryCoordinator::handle_nonbatched_job] Unknown exception during scan for partition " + << job.partition_id << ", query " << job.query_id + << ". Enqueuing empty result.\n"; + result_queue_.enqueue(ResultJob{job.query_id, job.rank, {}, {}}); // Enqueue empty result on error + } } void QueryCoordinator::handle_batched_job(const ScanJob &job, @@ -223,36 +249,77 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, } } - // gather queries - for (int64_t i = 0; i < job.num_queries; ++i) { - std::memcpy(res.batch_queries + i * partition_manager_->d(), - job.query_vector + job.query_ids->at(i) * partition_manager_->d(), - partition_manager_->d() * sizeof(float)); - } - - batched_scan_list(res.batch_queries, - (float*)partition_manager_->partition_store_->get_codes(job.partition_id), - (int64_t*)partition_manager_->partition_store_->get_ids(job.partition_id), - job.num_queries, - partition_manager_->partition_store_->list_size(job.partition_id), - partition_manager_->d(), - res.topk_buffer_pool, - metric_, - res.batch_distances, - res.batch_ids); - - vector results(job.num_queries); + bool scan_successful = false; + try { + const float* codes = (float*)partition_manager_->partition_store_->get_codes(job.partition_id); + const int64_t* ids = (int64_t*)partition_manager_->partition_store_->get_ids(job.partition_id); + int64_t part_size = partition_manager_->partition_store_->list_size(job.partition_id); + int D = partition_manager_->d(); + + if (!codes || !ids || part_size <= 0) { + std::cerr << "[QueryCoordinator::handle_batched_job] Partition " << job.partition_id + << " invalid or empty before batched scan. Enqueuing empty results for batch.\n"; + // Let success remain false, loop below will send empty results + throw std::runtime_error("Batched scan pre-check failed for partition data"); + } + + // Gather queries into res.batch_queries (as in your original code) + for (int64_t i = 0; i < job.num_queries; ++i) { + std::memcpy(res.batch_queries + i * D, + job.query_vector + job.query_ids->at(i) * D, + D * sizeof(float)); + } + + batched_scan_list(res.batch_queries, + codes, + ids, + job.num_queries, + part_size, + D, + res.topk_buffer_pool, // Vector of TopkBuffer shared_ptrs + metric_, + res.batch_distances, // Scratch space for distances + res.batch_ids); // Scratch space for IDs + scan_successful = true; + + } catch (const std::exception& e) { + std::cerr << "[QueryCoordinator::handle_batched_job] Exception during batched scan for partition " + << job.partition_id << ": " << e.what() + << ". Will enqueue empty results for affected queries.\n"; + // scan_successful remains false + } catch (...) { + std::cerr << "[QueryCoordinator::handle_batched_job] Unknown exception during batched scan for partition " + << job.partition_id + << ". Will enqueue empty results for affected queries.\n"; + // scan_successful remains false + } + + // Enqueue results (actual or empty) for every query in this batch job + std::vector results_batch; + results_batch.reserve(job.num_queries); for (int64_t i = 0; i < job.num_queries; ++i) { - int g = job.query_ids->at(i); - auto tv = res.topk_buffer_pool[i]->get_topk(); - auto ti = res.topk_buffer_pool[i]->get_topk_indices(); - results[i] = ResultJob{g, - job.ranks->at(i), - std::move(tv), - std::move(ti)}; - } - result_queue_.enqueue_bulk(results.begin(), - job.num_queries); + int global_query_id = job.query_ids->at(i); + int rank_for_this_query = job.ranks->at(i); // Rank of this partition scan for this specific query + + if (scan_successful) { + // Ensure buffer pool access is safe if it could have been resized or is smaller than expected + if (i < res.topk_buffer_pool.size() && res.topk_buffer_pool[i]) { + auto tv = res.topk_buffer_pool[i]->get_topk(); + auto ti = res.topk_buffer_pool[i]->get_topk_indices(); + results_batch.emplace_back(ResultJob{global_query_id, rank_for_this_query, std::move(tv), std::move(ti)}); + } else { + std::cerr << "[QueryCoordinator::handle_batched_job] Error accessing TopK buffer for successful scan, query " + << global_query_id << ", buffer index " << i << ". Sending empty result.\n"; + results_batch.emplace_back(ResultJob{global_query_id, rank_for_this_query, {}, {}}); + } + } else { + // Scan failed, enqueue an empty result for this query's part of the batch + results_batch.emplace_back(ResultJob{global_query_id, rank_for_this_query, {}, {}}); + } + } + if (!results_batch.empty()) { + result_queue_.enqueue_bulk(std::make_move_iterator(results_batch.begin()), results_batch.size()); + } } // — Main‐thread: worker_scan — @@ -308,8 +375,6 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, auto partition_ids_acc = partition_ids.accessor(); - std::cout << "[QueryCoordinator::enqueue_scan_jobs] Enqueueing scan jobs...\n"; - // flatten jobs next_job_id_ = 0; job_flags_.clear(); @@ -582,6 +647,7 @@ void QueryCoordinator::initialize_workers(int num_cores, bool use_numa) { worker_threads_[i] = std::thread(&QueryCoordinator::partition_scan_worker_fn, this, i); } workers_initialized_ = true; + stop_workers_.store(false); // set main thread on separate thread from workers int num_cores_on_machine = std::thread::hardware_concurrency(); From d29c6966623b7bb3fddc08297af5be77ae94ace2 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 03:42:19 -0500 Subject: [PATCH 161/323] NUMA allocation for topk buffer --- src/cpp/src/query_coordinator.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index fdb5001e..00a5722d 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -70,14 +70,13 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { set_thread_affinity(core_index); - int64_t jid; while (!stop_workers_) { + int64_t jid = 0; if (!res.job_queue.try_dequeue(jid)) { std::this_thread::sleep_for(std::chrono::microseconds(5)); continue; } - if (jid == -1) break; process_scan_job(job_buffer_[jid], res); } @@ -382,7 +381,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, for (int64_t q = 0; q < nQ; ++q) { job_flags_[q] = vector>(partition_ids.size(1)); for (int p = 0; p < partition_ids.size(1); ++p) { - job_flags_[q][p] = false; + job_flags_[q][p].store(false); if (partition_ids_acc[q][p] < 0) job_flags_[q][p] = true; } } @@ -639,6 +638,7 @@ void QueryCoordinator::initialize_workers(int num_cores, bool use_numa) { core_resources_.resize(num_cores); worker_threads_.resize(num_cores); + stop_workers_.store(false); for (int i = 0; i < num_cores; i++) { if (!set_thread_affinity(i)) { std::cout << "[QueryCoordinator::initialize_workers] Failed to set thread affinity on core " << i << std::endl; @@ -647,7 +647,6 @@ void QueryCoordinator::initialize_workers(int num_cores, bool use_numa) { worker_threads_[i] = std::thread(&QueryCoordinator::partition_scan_worker_fn, this, i); } workers_initialized_ = true; - stop_workers_.store(false); // set main thread on separate thread from workers int num_cores_on_machine = std::thread::hardware_concurrency(); From 13e8dcbdd1cab13dd7ffbe5c68b4941d3e6e4eee Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 03:45:21 -0500 Subject: [PATCH 162/323] NUMA allocation for topk buffer --- src/cpp/src/query_coordinator.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 00a5722d..4e9a7a35 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -70,6 +70,9 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { set_thread_affinity(core_index); + std::cout << "[QueryCoordinator::partition_scan_worker_fn] Worker " << core_index + << " started.\n"; + while (!stop_workers_) { int64_t jid = 0; @@ -77,9 +80,14 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { std::this_thread::sleep_for(std::chrono::microseconds(5)); continue; } + std::cout << "[QueryCoordinator::partition_scan_worker_fn] Worker " << core_index + << " processing job " << jid << "\n"; process_scan_job(job_buffer_[jid], res); } + + std::cout << "[QueryCoordinator::partition_scan_worker_fn] Worker " << core_index + << " exiting.\n"; } void QueryCoordinator::process_scan_job(ScanJob job, @@ -404,6 +412,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, job.rank = p; job_buffer_.push_back(job); core_resources_[pid % num_workers_].job_queue.enqueue(next_job_id_); + std::cout << "[QueryCoordinator::enqueue_scan_jobs] Enqueued job " << next_job_id_ << " for query " << q << ", partition " << pid << "\n"; next_job_id_++; } } From 669b39b75009ec0c31c42dd31150a9f71afd640f Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 03:47:24 -0500 Subject: [PATCH 163/323] NUMA allocation for topk buffer --- src/cpp/src/query_coordinator.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 4e9a7a35..fbb0159d 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -645,6 +645,8 @@ void QueryCoordinator::initialize_workers(int num_cores, bool use_numa) { partition_manager_->distribute_partitions(num_cores, use_numa); + std::cout << "[QueryCoordinator::initialize_workers] Partition manager distributed partitions." << std::endl; + core_resources_.resize(num_cores); worker_threads_.resize(num_cores); stop_workers_.store(false); @@ -655,6 +657,7 @@ void QueryCoordinator::initialize_workers(int num_cores, bool use_numa) { allocate_core_resources(i, 1, 10, partition_manager_->d()); worker_threads_[i] = std::thread(&QueryCoordinator::partition_scan_worker_fn, this, i); } + workers_initialized_ = true; // set main thread on separate thread from workers From f92d2efb2366b729af237e5001e75111b81bcc3c Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 03:48:35 -0500 Subject: [PATCH 164/323] NUMA allocation for topk buffer --- src/cpp/src/partition_manager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index de6b5a7f..770453f9 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -575,6 +575,8 @@ void PartitionManager::delete_partitions(const Tensor &partition_ids, bool reass void PartitionManager::distribute_partitions(int num_workers, bool use_numa) { + + debug_ = true; if (debug_) { std::cout << "[PartitionManager] distribute_partitions: Attempting to distribute partitions across " << num_workers << " workers." << std::endl; From 28a74d3ee5ec5808f66491d53427437412e1e9f1 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 03:50:24 -0500 Subject: [PATCH 165/323] NUMA allocation for topk buffer --- src/cpp/src/partition_manager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index 770453f9..93cd9ca2 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -625,6 +625,8 @@ void PartitionManager::distribute_partitions(int num_workers, bool use_numa) { for (int i = 0; i < partition_ids.size(0); i++) { set_partition_core_id(partition_ids_accessor[i], partition_ids_accessor[i] % num_workers, use_numa); } + + std::cout << "[PartitionManager] distribute_partitions: Distributed partitions to cores." << std::endl; } void PartitionManager::set_partition_core_id(int64_t partition_id, int core_id, bool use_numa) { From 33292dd19e072c7c658cde4231cf58f3ccf9baaf Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 03:52:29 -0500 Subject: [PATCH 166/323] NUMA allocation for topk buffer --- src/cpp/src/partition_manager.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index 93cd9ca2..7fd54ba7 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -623,6 +623,8 @@ void PartitionManager::distribute_partitions(int num_workers, bool use_numa) { Tensor partition_ids = get_partition_ids(); auto partition_ids_accessor = partition_ids.accessor(); for (int i = 0; i < partition_ids.size(0); i++) { + std::cout << "[PartitionManager] distribute_partitions: Partition " << partition_ids_accessor[i] + << " assigned to core " << partition_ids_accessor[i] % num_workers << std::endl; set_partition_core_id(partition_ids_accessor[i], partition_ids_accessor[i] % num_workers, use_numa); } @@ -631,10 +633,10 @@ void PartitionManager::distribute_partitions(int num_workers, bool use_numa) { void PartitionManager::set_partition_core_id(int64_t partition_id, int core_id, bool use_numa) { partition_store_->partitions_[partition_id]->set_core_id(core_id); + int node = numa_node_of_cpu(core_id); #ifdef QUAKE_USE_NUMA if (use_numa) { - int node = numa_node_of_cpu(core_id); partition_store_->partitions_[partition_id]->set_numa_node(node); } #endif From b8434d9eaf8229d07ba42d1d4e96ac20f85918b6 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 11:47:45 -0500 Subject: [PATCH 167/323] fix numa alloc --- src/cpp/src/partition_manager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index 7fd54ba7..161b20f2 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -635,9 +635,14 @@ void PartitionManager::set_partition_core_id(int64_t partition_id, int core_id, partition_store_->partitions_[partition_id]->set_core_id(core_id); int node = numa_node_of_cpu(core_id); + std::cout << "[PartitionManager] set_partition_core_id: Partition " << partition_id + << " assigned to core " << core_id << " on NUMA node " << node << std::endl; + #ifdef QUAKE_USE_NUMA if (use_numa) { + std::cout << "Before set\n"; partition_store_->partitions_[partition_id]->set_numa_node(node); + std::cout << "After set\n"; } #endif } From d398ceaa1884a81c60a0972363795eaaa87a2aa7 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 11:51:05 -0500 Subject: [PATCH 168/323] fix numa alloc --- src/cpp/include/parallel.h | 4 ++-- src/cpp/src/partition_manager.cpp | 10 +++++++++- src/cpp/src/query_coordinator.cpp | 18 +++++++++--------- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/cpp/include/parallel.h b/src/cpp/include/parallel.h index ac8ef8da..ab61f6c9 100644 --- a/src/cpp/include/parallel.h +++ b/src/cpp/include/parallel.h @@ -58,7 +58,7 @@ inline bool set_thread_affinity(int core_id) { } } - inline int numa_node_of_cpu(int cpu) { + inline int cpu_numa_node(int cpu) { return numa_node_of_cpu(cpu); } @@ -82,7 +82,7 @@ inline void quake_free(void* ptr, size_t /*sz*/) noexcept { std::free(ptr); } -inline int numa_node_of_cpu(int /*cpu*/) { +inline int cpu_numa_node(int /*cpu*/) { return 0; // Not applicable } diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index 161b20f2..56fbc48a 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -632,8 +632,16 @@ void PartitionManager::distribute_partitions(int num_workers, bool use_numa) { } void PartitionManager::set_partition_core_id(int64_t partition_id, int core_id, bool use_numa) { + + std::cout << "[PartitionManager] set_partition_core_id: Setting core ID for partition " << partition_id + << " to core " << core_id << std::endl; + partition_store_->partitions_[partition_id]->set_core_id(core_id); - int node = numa_node_of_cpu(core_id); + + std::cout << "[PartitionManager] set_partition_core_id: Partition " << partition_id + << " assigned to core " << core_id << std::endl; + + int node = cpu_numa_node(core_id); std::cout << "[PartitionManager] set_partition_core_id: Partition " << partition_id << " assigned to core " << core_id << " on NUMA node " << node << std::endl; diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index fbb0159d..9f787303 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -46,7 +46,7 @@ void QueryCoordinator::allocate_core_resources(int core_idx, int numa_node = 0; #ifdef QUAKE_USE_NUMA - numa_node = numa_node_of_cpu(core_idx); + numa_node = cpu_numa_node(core_idx); #endif // job queue remains default-constructed @@ -64,7 +64,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { CoreResources &res = core_resources_[core_index]; int numa_node = 0; #ifdef QUAKE_USE_NUMA - numa_node = numa_node_of_cpu(core_index); + numa_node = cpu_numa_node(core_index); #endif NUMAResources &nr = numa_resources_[numa_node]; @@ -94,7 +94,7 @@ void QueryCoordinator::process_scan_job(ScanJob job, CoreResources &res) { int numa_node = 0; #ifdef QUAKE_USE_NUMA - numa_node = numa_node_of_cpu(res.core_id); + numa_node = cpu_numa_node(res.core_id); #endif NUMAResources &nr = numa_resources_[numa_node]; @@ -141,7 +141,7 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, job.k, metric_ == faiss::METRIC_INNER_PRODUCT, /*cap=*/100 * job.k, - /*node=*/numa_node_of_cpu(res.core_id) + /*node=*/cpu_numa_node(res.core_id) ); } else if (res.topk_buffer_pool[0]->k_ != job.k) { // check capacity @@ -150,7 +150,7 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, job.k, metric_ == faiss::METRIC_INNER_PRODUCT, /*cap=*/100 * job.k, - /*node=*/numa_node_of_cpu(res.core_id) + /*node=*/cpu_numa_node(res.core_id) ); } res.topk_buffer_pool[0]->set_k(job.k); @@ -213,7 +213,7 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, job.k, metric_ == faiss::METRIC_INNER_PRODUCT, /*cap=*/num_workers_ * job.k, - /*node=*/numa_node_of_cpu(res.core_id) + /*node=*/cpu_numa_node(res.core_id) ); } @@ -224,7 +224,7 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, } res.batch_queries = static_cast(quake_alloc( size_t(job.num_queries) * partition_manager_->d() * sizeof(float), - numa_node_of_cpu(res.core_id))); + cpu_numa_node(res.core_id))); // realloc batch distances and ids if (res.batch_distances != nullptr) { @@ -237,10 +237,10 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, } res.batch_distances = static_cast(quake_alloc( size_t(job.num_queries) * job.k * sizeof(float), - numa_node_of_cpu(res.core_id))); + cpu_numa_node(res.core_id))); res.batch_ids = static_cast(quake_alloc( size_t(job.num_queries) * job.k * sizeof(int64_t), - numa_node_of_cpu(res.core_id))); + cpu_numa_node(res.core_id))); } else { for (int64_t i = 0; i < job.num_queries; ++i) { res.topk_buffer_pool[i]->set_k(job.k); From 69561bfb8a2bf5af55dbf507877b3bfe795b9b99 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 11:54:35 -0500 Subject: [PATCH 169/323] fix numa alloc --- src/cpp/src/partition_manager.cpp | 17 ----------------- src/cpp/src/query_coordinator.cpp | 13 ------------- 2 files changed, 30 deletions(-) diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index 56fbc48a..a1890f58 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -575,8 +575,6 @@ void PartitionManager::delete_partitions(const Tensor &partition_ids, bool reass void PartitionManager::distribute_partitions(int num_workers, bool use_numa) { - - debug_ = true; if (debug_) { std::cout << "[PartitionManager] distribute_partitions: Attempting to distribute partitions across " << num_workers << " workers." << std::endl; @@ -623,29 +621,14 @@ void PartitionManager::distribute_partitions(int num_workers, bool use_numa) { Tensor partition_ids = get_partition_ids(); auto partition_ids_accessor = partition_ids.accessor(); for (int i = 0; i < partition_ids.size(0); i++) { - std::cout << "[PartitionManager] distribute_partitions: Partition " << partition_ids_accessor[i] - << " assigned to core " << partition_ids_accessor[i] % num_workers << std::endl; set_partition_core_id(partition_ids_accessor[i], partition_ids_accessor[i] % num_workers, use_numa); } - - std::cout << "[PartitionManager] distribute_partitions: Distributed partitions to cores." << std::endl; } void PartitionManager::set_partition_core_id(int64_t partition_id, int core_id, bool use_numa) { - - std::cout << "[PartitionManager] set_partition_core_id: Setting core ID for partition " << partition_id - << " to core " << core_id << std::endl; - partition_store_->partitions_[partition_id]->set_core_id(core_id); - - std::cout << "[PartitionManager] set_partition_core_id: Partition " << partition_id - << " assigned to core " << core_id << std::endl; - int node = cpu_numa_node(core_id); - std::cout << "[PartitionManager] set_partition_core_id: Partition " << partition_id - << " assigned to core " << core_id << " on NUMA node " << node << std::endl; - #ifdef QUAKE_USE_NUMA if (use_numa) { std::cout << "Before set\n"; diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 9f787303..f4a23218 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -70,24 +70,15 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { set_thread_affinity(core_index); - std::cout << "[QueryCoordinator::partition_scan_worker_fn] Worker " << core_index - << " started.\n"; - while (!stop_workers_) { - int64_t jid = 0; if (!res.job_queue.try_dequeue(jid)) { std::this_thread::sleep_for(std::chrono::microseconds(5)); continue; } - std::cout << "[QueryCoordinator::partition_scan_worker_fn] Worker " << core_index - << " processing job " << jid << "\n"; process_scan_job(job_buffer_[jid], res); } - - std::cout << "[QueryCoordinator::partition_scan_worker_fn] Worker " << core_index - << " exiting.\n"; } void QueryCoordinator::process_scan_job(ScanJob job, @@ -412,7 +403,6 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, job.rank = p; job_buffer_.push_back(job); core_resources_[pid % num_workers_].job_queue.enqueue(next_job_id_); - std::cout << "[QueryCoordinator::enqueue_scan_jobs] Enqueued job " << next_job_id_ << " for query " << q << ", partition " << pid << "\n"; next_job_id_++; } } @@ -644,9 +634,6 @@ void QueryCoordinator::initialize_workers(int num_cores, bool use_numa) { std::endl; partition_manager_->distribute_partitions(num_cores, use_numa); - - std::cout << "[QueryCoordinator::initialize_workers] Partition manager distributed partitions." << std::endl; - core_resources_.resize(num_cores); worker_threads_.resize(num_cores); stop_workers_.store(false); From 68343b005b97cd8fe47236506ae0ee5bf124ec69 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 11:56:17 -0500 Subject: [PATCH 170/323] fix numa alloc --- src/cpp/src/partition_manager.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index a1890f58..fa068200 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -631,9 +631,7 @@ void PartitionManager::set_partition_core_id(int64_t partition_id, int core_id, #ifdef QUAKE_USE_NUMA if (use_numa) { - std::cout << "Before set\n"; partition_store_->partitions_[partition_id]->set_numa_node(node); - std::cout << "After set\n"; } #endif } From db25afd91d2deba441867ad4f99e5625b14bbf43 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 12:13:52 -0500 Subject: [PATCH 171/323] fix numa alloc --- src/cpp/src/query_coordinator.cpp | 30 +++++- .../numa_single_query/configs/sift1m.yaml | 102 +++++++++--------- 2 files changed, 77 insertions(+), 55 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index f4a23218..81716059 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -320,8 +320,6 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, } } -// — Main‐thread: worker_scan — - void QueryCoordinator::init_global_buffers(int64_t nQ, int K, Tensor &partition_ids, @@ -606,21 +604,45 @@ std::shared_ptr QueryCoordinator::worker_scan( timing->n_clusters = partition_manager_->nlist(); timing->search_params = params; + auto s1 = high_resolution_clock::now(); + // 1) init global buffers & jobs_left init_global_buffers(nQ, K, partition_ids, params); + auto s2 = high_resolution_clock::now(); + // 2) copy query vec to NUMA buffers copy_query_to_numa(x.data_ptr(), nQ, D); + auto s3 = high_resolution_clock::now(); + // 3) enqueue jobs enqueue_scan_jobs(x, partition_ids, params); + auto s4 = high_resolution_clock::now(); + // 4) drain results + APS drain_and_apply_aps(x, partition_ids, use_aps, params->recall_target, params->aps_flush_period_us, timing); - // 5) aggregate & return - return aggregate_scan_results(nQ, K, timing); + auto s5 = high_resolution_clock::now(); + + auto res = aggregate_scan_results(nQ, K, timing); + + auto s6 = high_resolution_clock::now(); + + res->timing_info->buffer_init_time_ns = + duration_cast(s2 - s1).count(); +// res->timing_info->copy_query_time_ns = +// duration_cast(s3 - s2).count(); + res->timing_info->job_enqueue_time_ns = + duration_cast(s4 - s3).count(); + res->timing_info->job_wait_time_ns = + duration_cast(s5 - s4).count(); + res->timing_info->result_aggregate_time_ns = + duration_cast(s6 - s5).count(); + + return res; } // Initialize Worker Threads diff --git a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml index 3682722b..d8eb082f 100644 --- a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml @@ -6,7 +6,7 @@ dataset: trials: 5 warmup: 10 -overwrite: false # Set to true to force all indexes to rerun +overwrite: true # Set to true to force all indexes to rerun indexes: - name: Quake_0 @@ -14,7 +14,7 @@ indexes: build_params: nc: 1000 metric: l2 - num_workers: 1 + num_workers: 0 use_numa: false search_params: nprobe: 20 @@ -29,55 +29,55 @@ indexes: search_params: nprobe: 20 - - name: Quake_4 - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 4 - use_numa: false - search_params: - nprobe: 20 - - - name: Quake_16 - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 16 - use_numa: false - search_params: - nprobe: 20 - - - name: Quake_1_numa - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 1 - use_numa: true - search_params: - nprobe: 20 - - - name: Quake_4_numa - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 4 - use_numa: true - search_params: - nprobe: 20 - - - name: Quake_16_numa - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 16 - use_numa: true - search_params: - nprobe: 20 +# - name: Quake_4 +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 4 +# use_numa: false +# search_params: +# nprobe: 20 +# +# - name: Quake_16 +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 16 +# use_numa: false +# search_params: +# nprobe: 20 +# +# - name: Quake_1_numa +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 1 +# use_numa: true +# search_params: +# nprobe: 20 +# +# - name: Quake_4_numa +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 4 +# use_numa: true +# search_params: +# nprobe: 20 +# +# - name: Quake_16_numa +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 16 +# use_numa: true +# search_params: +# nprobe: 20 # - name: FaissIVF # index: IVF From 7e5a3c2e3a7c3cace6b082f3a4330384f3c87a7f Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 13:12:33 -0500 Subject: [PATCH 172/323] fix recall bug --- src/cpp/include/list_scanning.h | 20 +++++++++++++++---- src/cpp/src/query_coordinator.cpp | 10 ++++++++-- .../numa_single_query/configs/sift1m.yaml | 12 +++++------ 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index c2a7d5c2..de7fa263 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -168,6 +168,8 @@ class TypedTopKBuffer { } T flush() { + + int n = head_; int m = std::min(n, k_); @@ -199,10 +201,20 @@ class TypedTopKBuffer { miniselect::pdqsort_branchless(ord_, ord_ + m, cmpIdx); // 5) copy the winners back to vals_/ids_ and clamp head_ - for (int i = m - 1; i >= 0; --i) { - int idx = ord_[i]; - vals_[i] = vals_[idx]; - ids_[i] = ids_[idx]; + std::vector temp_v(m); + std::vector temp_i(m); + + for (int i = 0; i < m; ++i) { + int original_slot_idx = ord_[i]; // ord_[i] is the original index of the i-th best item + // (e.g. ord_[0] is index of best, ord_[1] of 2nd best) + temp_v[i] = vals_[original_slot_idx]; + temp_i[i] = ids_[original_slot_idx]; + } + + // Now copy from temporary buffers to the main buffers + for (int i = 0; i < m; ++i) { + vals_[i] = temp_v[i]; + ids_[i] = temp_i[i]; } // 5) clamp head_ and return the k-th value (or extreme if too few) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 81716059..3c13350a 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -70,6 +70,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { set_thread_affinity(core_index); + int i = 0; while (!stop_workers_) { int64_t jid = 0; if (!res.job_queue.try_dequeue(jid)) { @@ -78,6 +79,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { } process_scan_job(job_buffer_[jid], res); + i++; } } @@ -167,7 +169,7 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, return; // Important to return after enqueueing the placeholder } - scan_list(nr.local_query_buffer, // Or job.query_vector depending on NUMA strategy + scan_list(nr.local_query_buffer + (job.query_id * D), codes, ids, part_size, @@ -333,7 +335,7 @@ void QueryCoordinator::init_global_buffers(int64_t nQ, global_topk_buffer_pool_[q] = std::make_shared( K, metric_ == faiss::METRIC_INNER_PRODUCT, - /*cap=*/num_workers_ * K * 2, + /*cap=*/num_workers_ * K * 1000, /*node=*/0 ); } @@ -500,10 +502,12 @@ void QueryCoordinator::drain_and_apply_aps(Tensor x, auto last_flush = high_resolution_clock::now(); + int64_t jobsReceived = 0; while (true) { // 1) drain all ready results ResultJob rj; while (result_queue_.try_dequeue(rj)) { + ++jobsReceived; global_topk_buffer_pool_[rj.query_id] ->batch_add(rj.distances.data(), rj.indices.data(), @@ -599,6 +603,8 @@ std::shared_ptr QueryCoordinator::worker_scan( int K = params->k; bool use_aps = (params->recall_target>0 && !params->batched_scan && parent_); + int64_t nJobsExpected = 0; + auto timing = std::make_shared(); timing->n_queries = nQ; timing->n_clusters = partition_manager_->nlist(); diff --git a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml index d8eb082f..f8a101e1 100644 --- a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml @@ -1,11 +1,11 @@ # numa_latency_experiment.yaml dataset: name: sift1m - num_queries: 100 - k: 100 + num_queries: 1 + k: 50 -trials: 5 -warmup: 10 +trials: 1 +warmup: 0 overwrite: true # Set to true to force all indexes to rerun indexes: @@ -17,7 +17,7 @@ indexes: num_workers: 0 use_numa: false search_params: - nprobe: 20 + nprobe: 1 - name: Quake_1 index: Quake @@ -27,7 +27,7 @@ indexes: num_workers: 1 use_numa: false search_params: - nprobe: 20 + nprobe: 1 # - name: Quake_4 # index: Quake From 899271dfb91a363909aeda2894c08903080fef99 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 13:55:09 -0500 Subject: [PATCH 173/323] reduce buffer allocs --- src/cpp/src/query_coordinator.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 3c13350a..3d7e5994 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -133,7 +133,7 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, res.topk_buffer_pool[0] = std::make_shared( job.k, metric_ == faiss::METRIC_INNER_PRODUCT, - /*cap=*/100 * job.k, + /*cap=*/std::max(100 * job.k, 10000), /*node=*/cpu_numa_node(res.core_id) ); } else if (res.topk_buffer_pool[0]->k_ != job.k) { @@ -142,7 +142,7 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, res.topk_buffer_pool[0] = std::make_shared( job.k, metric_ == faiss::METRIC_INNER_PRODUCT, - /*cap=*/100 * job.k, + /*cap=*/std::max(100 * job.k, 10000), /*node=*/cpu_numa_node(res.core_id) ); } @@ -205,7 +205,7 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, res.topk_buffer_pool[i] = std::make_shared( job.k, metric_ == faiss::METRIC_INNER_PRODUCT, - /*cap=*/num_workers_ * job.k, + /*cap=*/std::max(100 * job.k, 10000), /*node=*/cpu_numa_node(res.core_id) ); } @@ -335,7 +335,7 @@ void QueryCoordinator::init_global_buffers(int64_t nQ, global_topk_buffer_pool_[q] = std::make_shared( K, metric_ == faiss::METRIC_INNER_PRODUCT, - /*cap=*/num_workers_ * K * 1000, + /*cap=*/num_workers_ * K * 2, /*node=*/0 ); } From 71270c402cd862cfb7f2441ca51ad103a29aaf70 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 14:01:33 -0500 Subject: [PATCH 174/323] reduce buffer allocs --- src/cpp/src/query_coordinator.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 3d7e5994..70dfe539 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -78,6 +78,10 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { continue; } + if (jid == -1) { + break; + } + process_scan_job(job_buffer_[jid], res); i++; } From ea622431d49c6ef184f999c23515ac5236a33500 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 14:39:23 -0500 Subject: [PATCH 175/323] reduce buffer allocs --- src/cpp/src/query_coordinator.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 70dfe539..e4588759 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -95,6 +95,9 @@ void QueryCoordinator::process_scan_job(ScanJob job, #endif NUMAResources &nr = numa_resources_[numa_node]; + // print out job details for debugging purposes + std::cout << "Core: " << res.core_id << " Processing partition_id=" << job.partition_id << '\n'; + // fetch codes & ids const float *codes = (float*)partition_manager_->partition_store_->get_codes(job.partition_id); const int64_t *ids = (int64_t*)partition_manager_->partition_store_->get_ids(job.partition_id); From 765fef2a09540c7bf0c1a8ec92663c010334d568 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 14:47:01 -0500 Subject: [PATCH 176/323] reduce buffer allocs --- src/cpp/include/query_coordinator.h | 6 +++--- src/cpp/src/query_coordinator.cpp | 3 --- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 324a5bde..661ef0fa 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -59,9 +59,9 @@ class QueryCoordinator { moodycamel::ConcurrentQueue job_queue; // Thread-local buffers for batched queries - float *batch_queries; ///< Thread-local buffer used for batched queries. - float *batch_distances; ///< Thread-Local buffer for result distances. - int64_t *batch_ids; ///< Thread-Local buffer for result IDs. + float* batch_queries = nullptr; + float* batch_distances = nullptr; + int64_t* batch_ids = nullptr; }; struct NUMAResources { diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index e4588759..70dfe539 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -95,9 +95,6 @@ void QueryCoordinator::process_scan_job(ScanJob job, #endif NUMAResources &nr = numa_resources_[numa_node]; - // print out job details for debugging purposes - std::cout << "Core: " << res.core_id << " Processing partition_id=" << job.partition_id << '\n'; - // fetch codes & ids const float *codes = (float*)partition_manager_->partition_store_->get_codes(job.partition_id); const int64_t *ids = (int64_t*)partition_manager_->partition_store_->get_ids(job.partition_id); From 834874d93164d207fe269097bb5a053cad04940a Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 15:10:41 -0500 Subject: [PATCH 177/323] reduce buffer allocs --- src/cpp/include/query_coordinator.h | 6 +++--- src/cpp/src/query_coordinator.cpp | 7 ++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 661ef0fa..8b2eb8b6 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -59,9 +59,9 @@ class QueryCoordinator { moodycamel::ConcurrentQueue job_queue; // Thread-local buffers for batched queries - float* batch_queries = nullptr; - float* batch_distances = nullptr; - int64_t* batch_ids = nullptr; + float* batch_queries = nullptr; // batched query buffer (NUMA-allocated) + float* batch_distances = nullptr; // scratch space for distances + int64_t* batch_ids = nullptr; // scratch space for ids }; struct NUMAResources { diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 70dfe539..d18cdae7 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -44,12 +44,17 @@ void QueryCoordinator::allocate_core_resources(int core_idx, CR.core_id = core_idx; CR.topk_buffer_pool.clear(); + // --- ZERO‐INITIALIZE our batched‐query buffers so we never free garbage pointers --- + CR.batch_queries = nullptr; + CR.batch_distances = nullptr; + CR.batch_ids = nullptr; + int numa_node = 0; #ifdef QUAKE_USE_NUMA numa_node = cpu_numa_node(core_idx); #endif - // job queue remains default-constructed + // job queue remains default‐constructed numa_resources_.resize(get_num_numa_nodes()); auto& numa_res = numa_resources_[numa_node]; size_t bytes = size_t(num_queries) * d * sizeof(float); From fb7d51d9d17c2afbc09e6be11c29df821f3af0ea Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 15:27:21 -0500 Subject: [PATCH 178/323] reduce buffer allocs --- src/cpp/include/query_coordinator.h | 8 ++- src/cpp/src/query_coordinator.cpp | 86 +++++++++++++++++------------ 2 files changed, 55 insertions(+), 39 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 8b2eb8b6..2a78379a 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -59,9 +59,11 @@ class QueryCoordinator { moodycamel::ConcurrentQueue job_queue; // Thread-local buffers for batched queries - float* batch_queries = nullptr; // batched query buffer (NUMA-allocated) - float* batch_distances = nullptr; // scratch space for distances - int64_t* batch_ids = nullptr; // scratch space for ids + float* batch_queries = nullptr; // batched query buffer (NUMA-allocated) + float* batch_distances = nullptr; // scratch space for distances + int64_t* batch_ids = nullptr; // scratch space for ids + size_t batch_q_capacity = 0; // number of floats in batch_queries + size_t batch_res_capacity = 0; // number of (k×Q) slots in distances & ids }; struct NUMAResources { diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index d18cdae7..33e472d8 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -207,55 +207,69 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, void QueryCoordinator::handle_batched_job(const ScanJob &job, CoreResources &res, NUMAResources &nr) { - // ensure buffers - if (res.topk_buffer_pool.size() < (size_t)job.num_queries) { - res.topk_buffer_pool.resize(job.num_queries); - for (int64_t i = 0; i < job.num_queries; ++i) { + // Number of queries in this batch, top-k, vector dimension, and NUMA node + int64_t Q = job.num_queries; + int K = job.k; + int D = partition_manager_->d(); + int node = cpu_numa_node(res.core_id); + + // Ensure we have exactly Q TopK buffers, each with capacity = max(100*K, 10000) + size_t cap = std::max(100 * K, 10000); + if (res.topk_buffer_pool.size() < (size_t)Q) { + res.topk_buffer_pool.resize(Q); + for (int64_t i = 0; i < Q; ++i) { res.topk_buffer_pool[i] = std::make_shared( - job.k, + K, metric_ == faiss::METRIC_INNER_PRODUCT, - /*cap=*/std::max(100 * job.k, 10000), - /*node=*/cpu_numa_node(res.core_id) + /*cap=*/cap, + /*node=*/node ); } + } else { + for (int64_t i = 0; i < Q; ++i) { + auto &buf = res.topk_buffer_pool[i]; + buf->set_k(K); + buf->reset(); + } + } - // realloc batch query buffer - if (res.batch_queries != nullptr) { + // Allocate or grow the per-batch query buffer (size Q × D floats) + size_t need_q = size_t(Q) * D; + if (res.batch_q_capacity < need_q) { + if (res.batch_queries) { quake_free(res.batch_queries, - size_t(job.num_queries) * partition_manager_->d() * sizeof(float)); + res.batch_q_capacity * sizeof(float)); } - res.batch_queries = static_cast(quake_alloc( - size_t(job.num_queries) * partition_manager_->d() * sizeof(float), - cpu_numa_node(res.core_id))); + res.batch_queries = static_cast(quake_alloc( + need_q * sizeof(float), node)); + res.batch_q_capacity = need_q; + } - // realloc batch distances and ids - if (res.batch_distances != nullptr) { + // Allocate or grow the per-batch result buffers (size Q × K entries) + size_t need_r = size_t(Q) * size_t(K); + if (res.batch_res_capacity < need_r) { + if (res.batch_distances) { quake_free(res.batch_distances, - size_t(job.num_queries) * job.k * sizeof(float)); + res.batch_res_capacity * sizeof(float)); } - if (res.batch_ids != nullptr) { + if (res.batch_ids) { quake_free(res.batch_ids, - size_t(job.num_queries) * job.k * sizeof(int64_t)); - } - res.batch_distances = static_cast(quake_alloc( - size_t(job.num_queries) * job.k * sizeof(float), - cpu_numa_node(res.core_id))); - res.batch_ids = static_cast(quake_alloc( - size_t(job.num_queries) * job.k * sizeof(int64_t), - cpu_numa_node(res.core_id))); - } else { - for (int64_t i = 0; i < job.num_queries; ++i) { - res.topk_buffer_pool[i]->set_k(job.k); - res.topk_buffer_pool[i]->reset(); + res.batch_res_capacity * sizeof(int64_t)); } + res.batch_distances = static_cast( + quake_alloc(need_r * sizeof(float), node)); + res.batch_ids = static_cast( + quake_alloc(need_r * sizeof(int64_t), node)); + res.batch_res_capacity = need_r; + } - // set batch distances and ids to max/min and -1 - for (int64_t i = 0; i < job.num_queries * job.k; ++i) { - res.batch_distances[i] = metric_ == faiss::METRIC_INNER_PRODUCT ? - -std::numeric_limits::infinity() : - std::numeric_limits::infinity(); - res.batch_ids[i] = -1; - } + // Initialize the result buffers to infinity (or –infinity) and –1 + float dist_init = (metric_ == faiss::METRIC_INNER_PRODUCT) + ? -std::numeric_limits::infinity() + : std::numeric_limits::infinity(); + for (size_t idx = 0; idx < need_r; ++idx) { + res.batch_distances[idx] = dist_init; + res.batch_ids [idx] = -1; } bool scan_successful = false; From 7aa34db22af7f614b6ac3391bc9a2529e95b9594 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 15:34:35 -0500 Subject: [PATCH 179/323] reduce buffer allocs --- src/cpp/src/dynamic_inverted_list.cpp | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/cpp/src/dynamic_inverted_list.cpp b/src/cpp/src/dynamic_inverted_list.cpp index 2e82ca97..4364c53a 100644 --- a/src/cpp/src/dynamic_inverted_list.cpp +++ b/src/cpp/src/dynamic_inverted_list.cpp @@ -77,7 +77,8 @@ namespace faiss { const uint8_t *DynamicInvertedLists::get_codes(size_t list_no) const { auto it = partitions_.find(list_no); if (it == partitions_.end()) { - throw std::runtime_error("List does not exist in get_codes"); + string err_message = "List " + std::to_string(list_no) + " does not exist in get_codes"; + throw std::runtime_error(err_message); } return it->second->codes_; } @@ -85,7 +86,8 @@ namespace faiss { const idx_t *DynamicInvertedLists::get_ids(size_t list_no) const { auto it = partitions_.find(list_no); if (it == partitions_.end()) { - throw std::runtime_error("List does not exist in get_ids"); + string err_message = "List " + std::to_string(list_no) + " does not exist in get_ids"; + throw std::runtime_error(err_message); } return it->second->ids_; } @@ -100,8 +102,10 @@ namespace faiss { void DynamicInvertedLists::remove_entry(size_t list_no, idx_t id) { auto it = partitions_.find(list_no); - if (it == partitions_.end()) - throw std::runtime_error("List does not exist in remove_entry"); + if (it == partitions_.end()) { + string err_message = "List " + std::to_string(list_no) + " does not exist in remove_entry"; + throw std::runtime_error(err_message); + } auto& part = it->second; if (part->num_vectors_ == 0) return; @@ -121,7 +125,8 @@ namespace faiss { void DynamicInvertedLists::remove_entries_from_partition(size_t list_no, vector vectors_to_remove) { auto it = partitions_.find(list_no); if (it == partitions_.end()) { - throw std::runtime_error("List does not exist in remove_entries_from_partition"); + string err_message = "List " + std::to_string(list_no) + " does not exist in remove_entries_from_partition"; + throw std::runtime_error(err_message); } shared_ptr part = it->second; @@ -180,8 +185,10 @@ namespace faiss { if (n_entry == 0) return 0; auto it = partitions_.find(list_no); - if (it == partitions_.end()) - throw std::runtime_error("List does not exist in add_entries"); + if (it == partitions_.end()) { + string err_message = "List " + std::to_string(list_no) + " does not exist in add_entries"; + throw std::runtime_error(err_message); + } auto& part = it->second; if (part->code_size_ != static_cast(code_size)) @@ -204,7 +211,8 @@ namespace faiss { const uint8_t *codes) { auto it = partitions_.find(list_no); if (it == partitions_.end()) { - throw std::runtime_error("List does not exist in update_entries"); + string err_message = "List " + std::to_string(list_no) + " does not exist in update_entries"; + throw std::runtime_error(err_message); } shared_ptr part = it->second; @@ -291,7 +299,8 @@ void DynamicInvertedLists::batch_update_entries( void DynamicInvertedLists::add_list(size_t list_no) { if (partitions_.find(list_no) != partitions_.end()) { - throw std::runtime_error("List already exists in add_list"); + string err_message = "List " + std::to_string(list_no) + " already exists in add_list"; + throw std::runtime_error(err_message); } shared_ptr ip = std::make_shared(); ip->set_code_size((int64_t) code_size); From aa6c549bbbce14e1b016382e079cf4c2b46ef8e9 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 15:38:34 -0500 Subject: [PATCH 180/323] reduce buffer allocs --- src/cpp/src/query_coordinator.cpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 33e472d8..fd36036e 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -100,16 +100,24 @@ void QueryCoordinator::process_scan_job(ScanJob job, #endif NUMAResources &nr = numa_resources_[numa_node]; - // fetch codes & ids - const float *codes = (float*)partition_manager_->partition_store_->get_codes(job.partition_id); - const int64_t *ids = (int64_t*)partition_manager_->partition_store_->get_ids(job.partition_id); - - int64_t part_size = 0; + // Attempt to fetch partition data; if the list doesn't exist, catch and enqueue empty results. + const float *codes = nullptr; + const int64_t *ids = nullptr; + int64_t part_size = 0; try { + codes = (float *)(partition_manager_->partition_store_->get_codes(job.partition_id)); + ids = (int64_t *) partition_manager_->partition_store_->get_ids(job.partition_id); part_size = partition_manager_->partition_store_->list_size(job.partition_id); - } catch (...) { - std::cerr << "[partition_scan_worker_fn] Partition " << job.partition_id << " not found.\n"; - result_queue_.enqueue(ResultJob{job.query_id, job.rank, {}, {}}); + } catch (const std::exception &e) { + std::cerr << "[process_scan_job] Partition " << job.partition_id + << " invalid: " << e.what() << ". Returning empty result(s).\n"; + if (job.is_batched) { + for (int64_t q : *job.query_ids) { + result_queue_.enqueue(ResultJob{(int)q, 0, {}, {}}); + } + } else { + result_queue_.enqueue(ResultJob{job.query_id, job.rank, {}, {}}); + } return; } From 8570e86e6e4cbf23be4a00b8dac7b315a837a8c9 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 16:54:45 -0500 Subject: [PATCH 181/323] update multi-experiment to track detailed timers --- .../osdi2025/numa_multi_query/run.py | 401 ++++++++++-------- 1 file changed, 220 insertions(+), 181 deletions(-) diff --git a/test/experiments/osdi2025/numa_multi_query/run.py b/test/experiments/osdi2025/numa_multi_query/run.py index e9d7a735..25c89fdc 100644 --- a/test/experiments/osdi2025/numa_multi_query/run.py +++ b/test/experiments/osdi2025/numa_multi_query/run.py @@ -1,59 +1,64 @@ #!/usr/bin/env python3 """ -NUMA Batch-Query Latency and Recall Benchmark +NUMA Batch-Query Latency and Recall Benchmark (detailed timers) Benchmarks a suite of ANN indexes (Quake, Faiss-IVF, SCANN, HNSW, DiskANN, SVS, etc.) -for batch-query latency and recall@k under configurable build and search parameters. +for per-query latency breakdown and recall@k under configurable build and search parameters. Results are cached and only recomputed if the 'overwrite' flag is set in the configuration. -Outputs a unified CSV and a latency plot per index. +Outputs per-index CSVs with detailed timing info and unified CSV + plots. Usage: python numa_latency_batch_experiment.py numa_latency_experiment.yaml output_dir """ - +import sys +from pathlib import Path +ing = yaml = None import yaml import numpy as np +torch = None import torch import pandas as pd import matplotlib.pyplot as plt -from pathlib import Path -from time import time -from quake.utils import compute_recall +from quake.utils import compute_recall from quake.datasets.ann_datasets import load_dataset from quake.index_wrappers.faiss_ivf import FaissIVF from quake.index_wrappers.faiss_hnsw import FaissHNSW from quake.index_wrappers.quake import QuakeWrapper -# try: -# from quake.index_wrappers.scann import Scann -# except ImportError: -# raise ImportError("SCANN wrapper not available. Please install the required package.") -# try: -# from quake.index_wrappers.diskann import DiskANNDynamic -# except ImportError: -# raise ImportError("DiskANN wrapper not available. Please install the required package.") -# try: -# from quake.index_wrappers.vamana import Vamana -# except ImportError: -# raise ImportError("SVS wrapper not available. Please install the required package.") +# Optional wrappers +try: + from quake.index_wrappers.scann import Scann +except ImportError: + Scann = None +try: + from quake.index_wrappers.diskann import DiskANNDynamic +except ImportError: + DiskANNDynamic = None +try: + from quake.index_wrappers.vamana import Vamana +except ImportError: + Vamana = None INDEX_CLASSES = { - "Quake": QuakeWrapper, - "IVF": FaissIVF, - # "SCANN": Scann, - "HNSW": FaissHNSW, - # "DiskANN": DiskANNDynamic, - # "SVS": Vamana, + "Quake": QuakeWrapper, + "IVF": FaissIVF, + "SCANN": Scann, + "HNSW": FaissHNSW, + "DiskANN": DiskANNDynamic, + "SVS": Vamana, } -def build_and_save_index(index_class, build_params, base_vecs, index_file): - idx = index_class() - params = dict(build_params) - idx.build(base_vecs, **params) - idx.save(str(index_file)) + +def build_and_save(index_cls, params, vecs, path): + """Build an index and save it to disk.""" + idx = index_cls() + idx.build(vecs, **params) + idx.save(str(path)) + def extract_ids(res): + """Normalize returned IDs array.""" if hasattr(res, "ids"): arr = res.ids elif hasattr(res, "I"): @@ -61,186 +66,220 @@ def extract_ids(res): elif hasattr(res, "indices"): arr = res.indices else: - raise RuntimeError("Cannot extract predicted indices from search result.") + raise RuntimeError("Search result has no id field.") if isinstance(arr, torch.Tensor): arr = arr.cpu().numpy() - elif not isinstance(arr, np.ndarray): - arr = np.asarray(arr) - return arr - -def run_experiment(cfg_path: str, output_dir: str): - cfg = yaml.safe_load(Path(cfg_path).read_text()) - ds = cfg["dataset"] - queries_n = ds["num_queries"] - k = ds["k"] - trials = cfg.get("trials", 5) - warmup = cfg.get("warmup", 10) - indexes_cfg = cfg["indexes"] - csv_name = cfg.get("output", {}).get("results_csv", "numa_results.csv") - overwrite = cfg.get("overwrite", False) - - out_dir = Path(output_dir) + return np.asarray(arr, dtype=np.int64) + + +def run_experiment(cfg_path: str, output_dir: str) -> None: + # Load config + cfg = yaml.safe_load(Path(cfg_path).read_text()) + ds_cfg = cfg["dataset"] + k = ds_cfg["k"] + q_n = ds_cfg["num_queries"] + trials = cfg.get("trials", 5) + warmup_n = cfg.get("warmup", 10) + idx_cfgs = cfg["indexes"] + csv_name = cfg.get("output", {}).get("results_csv", "numa_results.csv") + overwrite = cfg.get("overwrite", False) + + out_dir = Path(output_dir).expanduser().absolute() out_dir.mkdir(parents=True, exist_ok=True) - print(f"[INFO] Loading dataset '{ds['name']}'...") - base_vecs, queries, gt = load_dataset(ds["name"]) - queries = queries[:queries_n] - gt = gt[:queries_n] if gt is not None else None + # Load dataset + print(f"[INFO] Loading dataset {ds_cfg['name']}...") + base_vecs, queries, gt = load_dataset(ds_cfg["name"]) + queries = queries[:q_n] + gt = gt[:q_n] if gt is not None else None - # --- Build the Quake base index ONCE --- + # Build shared Quake base index once quake_base_params = None - quake_base_index_file = out_dir / "Quake_base_index.bin" - # Find the build params for the first Quake config for base index - for idx_cfg in indexes_cfg: - if idx_cfg["index"] == "Quake": - quake_base_params = dict(idx_cfg.get("build_params", {})) - # Remove any runtime/load-only params - quake_base_params.pop("num_workers", None) - quake_base_params.pop("use_numa", None) + for c in idx_cfgs: + if c["index"] == "Quake": + p = dict(c.get("build_params", {})) + p.pop("num_workers", None) + p.pop("use_numa", None) + quake_base_params = p break - if quake_base_params is not None: - if not quake_base_index_file.exists(): - print(f"[BUILD] Quake (shared) base index ...") - build_and_save_index(QuakeWrapper, quake_base_params, base_vecs, quake_base_index_file) - print(f"[SAVE] Quake base index saved at {quake_base_index_file}") - all_rows = [] + quake_base_path = out_dir / "Quake_base_index.bin" + if quake_base_params and not quake_base_path.exists(): + print("[BUILD] Quake (shared) base index...") + build_and_save(QuakeWrapper, quake_base_params, base_vecs, quake_base_path) + print(f"[SAVE] Quake base index → {quake_base_path}") - for idx_cfg in indexes_cfg: - idx_name = idx_cfg["name"] - idx_type = idx_cfg["index"] - build_params = dict(idx_cfg.get("build_params", {})) - search_params = idx_cfg.get("search_params", {}) - IndexClass = INDEX_CLASSES.get(idx_type) - if IndexClass is None: - print(f"[WARN] Unknown index type: {idx_type}. Skipping.") + # Collect results per-index + all_rows = [] + for cfg_i in idx_cfgs: + name = cfg_i["name"] + typ = cfg_i["index"] + b_params = dict(cfg_i.get("build_params", {})) + s_params = dict(cfg_i.get("search_params", {})) + cls = INDEX_CLASSES.get(typ) + if cls is None: + print(f"[WARN] Unknown index type '{typ}', skipping.") continue - idx_csv = out_dir / f"{idx_name}_results.csv" - # Quake uses the shared base index; others get their own file - if idx_type == "Quake": - idx_file = quake_base_index_file - else: - idx_file = out_dir / f"{idx_name}_index.bin" + idx_csv = out_dir / f"{name}_results.csv" + idx_path = quake_base_path if typ == "Quake" else out_dir / f"{name}_index.bin" + # Skip if exists if idx_csv.exists() and not overwrite: - print(f"[SKIP] {idx_name}: Results exist. Use overwrite: true to rerun.") - df_idx = pd.read_csv(idx_csv) - all_rows.append(df_idx.iloc[0].to_dict()) + print(f"[SKIP] {name} – results exist.") + all_rows.append(pd.read_csv(idx_csv).iloc[0].to_dict()) continue - if idx_type != "Quake" and not idx_file.exists(): - print(f"[BUILD] {idx_name} index...") - build_and_save_index(IndexClass, build_params, base_vecs, idx_file) - print(f"[SAVE] Index saved at {idx_file}") - - print(f"[RUN] {idx_name} ...") - - if idx_type == "Quake": - # Only use load-time params for Quake - load_kwargs = {} - if "use_numa" in build_params: - load_kwargs["use_numa"] = build_params["use_numa"] - if "num_workers" in build_params: - load_kwargs["num_workers"] = build_params["num_workers"] - idx = QuakeWrapper() - idx.load(str(idx_file), **load_kwargs) - elif idx_type == "DiskANN": - idx = IndexClass() - build_params.pop("metric", None) - idx.load(str(idx_file), **build_params) + # Build if needed + if typ != "Quake" and not idx_path.exists(): + print(f"[BUILD] {name} index...") + build_and_save(cls, b_params, base_vecs, idx_path) + print(f"[SAVE] Index → {idx_path}") + + # Load index with params + if typ == "Quake": + load_kw = {k: b_params[k] for k in ("use_numa", "num_workers") if k in b_params} + idx = QuakeWrapper(); idx.load(str(idx_path), **load_kw) + elif typ == "DiskANN": + idx = cls(); b_params.pop("metric", None); idx.load(str(idx_path), **b_params) else: - idx = IndexClass() - idx.load(str(idx_file)) + idx = cls(); idx.load(str(idx_path)) - print(search_params) + # Warm-up runs + for _ in range(min(warmup_n, len(queries))): + for q in queries: + idx.search(q.unsqueeze(0).float(), k, **s_params) - # Warmup (single batch, no timing) - for i in range(min(warmup, 1)): - idx.search(queries, k, **search_params) + # Prepare accumulators for detailed timers + child_buf_init_trials = [] + child_enq_trials = [] + child_wait_trials = [] + child_agg_trials = [] + child_total_trials = [] + parent_buf_init_trials = [] + parent_enq_trials = [] + parent_wait_trials = [] + parent_agg_trials = [] + parent_total_trials = [] + recall_trials = [] - # Benchmark Trials (latency and recall) - trial_means = [] - trial_recalls = [] + # Benchmark trials for t in range(trials): - t0 = time() - res = idx.search(queries, k, **search_params) - t1 = time() - mean_t = ((t1 - t0) * 1e3) / queries.shape[0] # ms per query - trial_means.append(mean_t) - - preds_arr = extract_ids(res) - if preds_arr.shape[0] != queries.shape[0]: - raise RuntimeError(f"Pred shape {preds_arr.shape} doesn't match queries {queries.shape}") - - if gt is not None: - recall = float(compute_recall(preds_arr, gt, k).mean()) - trial_recalls.append(recall) - print(f" [trial {t+1}/{trials}] {mean_t:.2f} ms | recall@{k}: {recall:.4f}") - else: - print(f" [trial {t+1}/{trials}] {mean_t:.2f} ms") - - mean_lat = float(np.mean(trial_means)) - std_lat = float(np.std(trial_means)) - mean_recall = float(np.mean(trial_recalls)) if trial_recalls else np.nan - n_workers_val = build_params.get("num_workers", None) + # per-trial lists + buf_init = [] + enq = [] + wait = [] + agg = [] + tot = [] + p_buf = [] + p_enq = [] + p_wait = [] + p_agg = [] + p_tot = [] + recs = [] + + for qi, q in enumerate(queries): + res = idx.search(q.unsqueeze(0).float(), k, **s_params) + ti = res.timing_info + + # child (worker_scan) timers + buf_init.append(ti.buffer_init_time_ns) + enq.append(ti.job_enqueue_time_ns) + wait.append(ti.job_wait_time_ns) + agg.append(ti.result_aggregate_time_ns) + tot.append(ti.total_time_ns) + + # parent timers if present + pi = getattr(ti, "parent_info", None) + if pi: + p_buf.append(pi.buffer_init_time_ns) + p_enq.append(pi.job_enqueue_time_ns) + p_wait.append(pi.job_wait_time_ns) + p_agg.append(pi.result_aggregate_time_ns) + p_tot.append(pi.total_time_ns) + else: + p_buf.append(0) + p_enq.append(0) + p_wait.append(0) + p_agg.append(0) + p_tot.append(0) + + # recall on first trial + if gt is not None and t == 0: + preds = extract_ids(res)[0] + recs.append(float(compute_recall(torch.tensor([preds]), gt[qi:qi+1], k).item())) + + # compute per-trial means (convert ns to ms where appropriate) + child_buf_init_trials.append(np.mean(buf_init)/1e6) + child_enq_trials .append(np.mean(enq) /1e6) + child_wait_trials .append(np.mean(wait) /1e6) + child_agg_trials .append(np.mean(agg) /1e6) + child_total_trials .append(np.mean(tot) /1e6) + parent_buf_init_trials.append(np.mean(p_buf)/1e6) + parent_enq_trials .append(np.mean(p_enq)/1e6) + parent_wait_trials .append(np.mean(p_wait)/1e6) + parent_agg_trials .append(np.mean(p_agg)/1e6) + parent_total_trials .append(np.mean(p_tot)/1e6) + recall_trials.append(np.mean(recs) if recs else np.nan) + + print(f" [{name} trial {t+1}/{trials}] " + f"child_tot={child_total_trials[-1]:.2f}ms, " + f"parent_tot={parent_total_trials[-1]:.2f}ms, " + f"R@{k}={recall_trials[-1]:.4f}") + + # assemble result row row = { - "index": idx_name, - "n_workers": n_workers_val, - "mean_latency_ms": mean_lat, - "std_latency_ms": std_lat, - f"recall_at_{k}": mean_recall, + "index": name, + "n_workers": b_params.get("num_workers", np.nan), + "recall_at_%d"%k: float(np.mean(recall_trials)), + "child_buffer_init_ms": float(np.mean(child_buf_init_trials)), + "child_enqueue_ms": float(np.mean(child_enq_trials)), + "child_wait_ms": float(np.mean(child_wait_trials)), + "child_aggregate_ms": float(np.mean(child_agg_trials)), + "child_total_ms": float(np.mean(child_total_trials)), + "parent_buffer_init_ms":float(np.mean(parent_buf_init_trials)), + "parent_enqueue_ms": float(np.mean(parent_enq_trials)), + "parent_wait_ms": float(np.mean(parent_wait_trials)), + "parent_aggregate_ms": float(np.mean(parent_agg_trials)), + "parent_total_ms": float(np.mean(parent_total_trials)), } all_rows.append(row) pd.DataFrame([row]).to_csv(idx_csv, index=False) - # Save Unified CSV + # write unified CSV df = pd.DataFrame(all_rows) out_csv = out_dir / csv_name df.to_csv(out_csv, index=False) - print(f"\n[RESULT] Results written to {out_csv}") + print(f"\n[RESULT] Unified results → {out_csv}") + + # Plot child total latency + plt.figure() + for nm in df["index"].unique(): + sub = df[df["index"]==nm] + lbl = (nm if sub["n_workers"].isnull().all() + else f"{nm} (nw={int(sub['n_workers'].iloc[0])})") + plt.errorbar(sub["n_workers"], sub["child_total_ms"], + yerr=df[df['index']==nm]["child_total_ms"].std(), + marker="o", capsize=5, label=lbl) + plt.xscale("symlog", base=2) + plt.xlabel("Num Workers") + plt.ylabel("Mean Child Total Latency (ms)") + plt.title("Child Latency Breakdown (per-index)") + plt.legend(); plt.tight_layout() + plt.savefig(out_dir/ f"{out_csv.stem}_child_breakdown.png") + print(f"[PLOT] Child breakdown → {out_dir/ f'{out_csv.stem}_child_breakdown.png'}") - # Plot Latency + # Plot recall plt.figure() - for idx_name in df["index"].unique(): - subset = df[df["index"] == idx_name] - label = f"{idx_name}" if subset["n_workers"].isnull().all() else f"{idx_name} (n_workers={subset['n_workers'].iloc[0]})" - plt.errorbar( - subset["n_workers"] if "n_workers" in subset else subset.index, - subset["mean_latency_ms"], - yerr=subset["std_latency_ms"], - marker="o", - capsize=5, - label=label - ) + for nm in df["index"].unique(): + sub = df[df["index"]==nm] + lbl = (nm if sub["n_workers"].isnull().all() + else f"{nm} (nw={int(sub['n_workers'].iloc[0])})") + plt.plot(sub["n_workers"], sub[f"recall_at_{k}"], marker="o", label=lbl) plt.xscale("symlog", base=2) plt.xlabel("Num Workers") - plt.ylabel("Mean Latency (ms)") - plt.title("Batch Query Latency (per-index)") - plt.legend() - plot_file = out_dir / f"{out_csv.stem}_latency.png" - plt.tight_layout() - plt.savefig(plot_file) - print(f"[PLOT] Saved to {plot_file}") - - # Plot Recall - if f"recall_at_{k}" in df.columns: - plt.figure() - for idx_name in df["index"].unique(): - subset = df[df["index"] == idx_name] - label = f"{idx_name}" if subset["n_workers"].isnull().all() else f"{idx_name} (n_workers={subset['n_workers'].iloc[0]})" - plt.plot( - subset["n_workers"] if "n_workers" in subset else subset.index, - subset[f"recall_at_{k}"], - marker="o", - label=label - ) - plt.xscale("symlog", base=2) - plt.xlabel("Num Workers") - plt.ylabel(f"Recall@{k}") - plt.title(f"Recall@{k} (per-index)") - plt.legend() - plot_file = out_dir / f"{out_csv.stem}_recall.png" - plt.tight_layout() - plt.savefig(plot_file) - print(f"[PLOT] Recall plot saved to {plot_file}") \ No newline at end of file + plt.ylabel(f"Recall@{k}") + plt.title(f"Recall@{k} (per-index)") + plt.legend(); plt.tight_layout() + plt.savefig(out_dir/ f"{out_csv.stem}_recall.png") + print(f"[PLOT] Recall plot → {out_dir/ f'{out_csv.stem}_recall.png'}") \ No newline at end of file From adf7bd4ebc1104b6b5bdc7790cc1f6776ac26681 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 16:57:42 -0500 Subject: [PATCH 182/323] update multi-experiment to track detailed timers --- .../osdi2025/numa_multi_query/run.py | 342 ++++++++---------- 1 file changed, 158 insertions(+), 184 deletions(-) diff --git a/test/experiments/osdi2025/numa_multi_query/run.py b/test/experiments/osdi2025/numa_multi_query/run.py index 25c89fdc..6c826178 100644 --- a/test/experiments/osdi2025/numa_multi_query/run.py +++ b/test/experiments/osdi2025/numa_multi_query/run.py @@ -1,24 +1,24 @@ #!/usr/bin/env python3 """ -NUMA Batch-Query Latency and Recall Benchmark (detailed timers) +NUMA Batch-Query Latency and Recall Benchmark (with detailed child/parent timers) Benchmarks a suite of ANN indexes (Quake, Faiss-IVF, SCANN, HNSW, DiskANN, SVS, etc.) -for per-query latency breakdown and recall@k under configurable build and search parameters. -Results are cached and only recomputed if the 'overwrite' flag is set in the configuration. -Outputs per-index CSVs with detailed timing info and unified CSV + plots. +for batch-query latency, per-phase breakdown, and recall@k under configurable parameters. +Results are cached and only recomputed if 'overwrite' is set. +Outputs per-index CSVs with detailed timers, a unified CSV, and plots. Usage: - python numa_latency_batch_experiment.py numa_latency_experiment.yaml output_dir + python numa_latency_batch_experiment.py nna_latency_experiment.yaml output_dir """ import sys from pathlib import Path -ing = yaml = None import yaml import numpy as np torch = None import torch import pandas as pd import matplotlib.pyplot as plt +from time import time from quake.utils import compute_recall from quake.datasets.ann_datasets import load_dataset @@ -50,15 +50,15 @@ } -def build_and_save(index_cls, params, vecs, path): - """Build an index and save it to disk.""" - idx = index_cls() - idx.build(vecs, **params) - idx.save(str(path)) +def build_and_save_index(index_class, build_params, base_vecs, index_file): + """Build and save an index to disk.""" + idx = index_class() + idx.build(base_vecs, **build_params) + idx.save(str(index_file)) def extract_ids(res): - """Normalize returned IDs array.""" + """Normalize returned prediction IDs to a NumPy array.""" if hasattr(res, "ids"): arr = res.ids elif hasattr(res, "I"): @@ -66,220 +66,194 @@ def extract_ids(res): elif hasattr(res, "indices"): arr = res.indices else: - raise RuntimeError("Search result has no id field.") + raise RuntimeError("Cannot extract predicted indices from search result.") if isinstance(arr, torch.Tensor): arr = arr.cpu().numpy() - return np.asarray(arr, dtype=np.int64) - - -def run_experiment(cfg_path: str, output_dir: str) -> None: - # Load config - cfg = yaml.safe_load(Path(cfg_path).read_text()) - ds_cfg = cfg["dataset"] - k = ds_cfg["k"] - q_n = ds_cfg["num_queries"] - trials = cfg.get("trials", 5) - warmup_n = cfg.get("warmup", 10) - idx_cfgs = cfg["indexes"] - csv_name = cfg.get("output", {}).get("results_csv", "numa_results.csv") + return np.asarray(arr) + + +def run_experiment(cfg_path: str, output_dir: str): + cfg = yaml.safe_load(Path(cfg_path).read_text()) + ds = cfg["dataset"] + queries_n = ds["num_queries"] + k = ds["k"] + trials = cfg.get("trials", 5) + warmup = cfg.get("warmup", 10) + indexes_cfg = cfg["indexes"] + csv_name = cfg.get("output", {}).get("results_csv", "numa_results.csv") overwrite = cfg.get("overwrite", False) - out_dir = Path(output_dir).expanduser().absolute() + out_dir = Path(output_dir) out_dir.mkdir(parents=True, exist_ok=True) - # Load dataset - print(f"[INFO] Loading dataset {ds_cfg['name']}...") - base_vecs, queries, gt = load_dataset(ds_cfg["name"]) - queries = queries[:q_n] - gt = gt[:q_n] if gt is not None else None + print(f"[INFO] Loading dataset '{ds['name']}'...") + base_vecs, queries, gt = load_dataset(ds["name"]) + queries = queries[:queries_n] + gt = gt[:queries_n] if gt is not None else None - # Build shared Quake base index once + # --- Build shared Quake base index once --- quake_base_params = None - for c in idx_cfgs: - if c["index"] == "Quake": - p = dict(c.get("build_params", {})) - p.pop("num_workers", None) - p.pop("use_numa", None) - quake_base_params = p + quake_base_index_file = out_dir / "Quake_base_index.bin" + for idx_cfg in indexes_cfg: + if idx_cfg["index"] == "Quake": + quake_base_params = dict(idx_cfg.get("build_params", {})) + quake_base_params.pop("num_workers", None) + quake_base_params.pop("use_numa", None) break + if quake_base_params and not quake_base_index_file.exists(): + print(f"[BUILD] Quake (shared) base index ...") + build_and_save_index(QuakeWrapper, quake_base_params, base_vecs, quake_base_index_file) + print(f"[SAVE] Quake base index saved at {quake_base_index_file}") - quake_base_path = out_dir / "Quake_base_index.bin" - if quake_base_params and not quake_base_path.exists(): - print("[BUILD] Quake (shared) base index...") - build_and_save(QuakeWrapper, quake_base_params, base_vecs, quake_base_path) - print(f"[SAVE] Quake base index → {quake_base_path}") - - # Collect results per-index all_rows = [] - for cfg_i in idx_cfgs: - name = cfg_i["name"] - typ = cfg_i["index"] - b_params = dict(cfg_i.get("build_params", {})) - s_params = dict(cfg_i.get("search_params", {})) - cls = INDEX_CLASSES.get(typ) - if cls is None: - print(f"[WARN] Unknown index type '{typ}', skipping.") + + for idx_cfg in indexes_cfg: + name = idx_cfg["name"] + idx_type = idx_cfg["index"] + build_params = dict(idx_cfg.get("build_params", {})) + search_params= dict(idx_cfg.get("search_params", {})) + IndexClass = INDEX_CLASSES.get(idx_type) + if IndexClass is None: + print(f"[WARN] Unknown index type: {idx_type}. Skipping.") continue - idx_csv = out_dir / f"{name}_results.csv" - idx_path = quake_base_path if typ == "Quake" else out_dir / f"{name}_index.bin" + idx_csv = out_dir / f"{name}_results.csv" + idx_file = quake_base_index_file if idx_type == "Quake" else out_dir / f"{name}_index.bin" - # Skip if exists if idx_csv.exists() and not overwrite: - print(f"[SKIP] {name} – results exist.") + print(f"[SKIP] {name}: Results exist. Use overwrite: true to rerun.") all_rows.append(pd.read_csv(idx_csv).iloc[0].to_dict()) continue - # Build if needed - if typ != "Quake" and not idx_path.exists(): + # Build non-Quake if necessary + if idx_type != "Quake" and not idx_file.exists(): print(f"[BUILD] {name} index...") - build_and_save(cls, b_params, base_vecs, idx_path) - print(f"[SAVE] Index → {idx_path}") - - # Load index with params - if typ == "Quake": - load_kw = {k: b_params[k] for k in ("use_numa", "num_workers") if k in b_params} - idx = QuakeWrapper(); idx.load(str(idx_path), **load_kw) - elif typ == "DiskANN": - idx = cls(); b_params.pop("metric", None); idx.load(str(idx_path), **b_params) + build_and_save_index(IndexClass, build_params, base_vecs, idx_file) + print(f"[SAVE] Index saved at {idx_file}") + + # Load index + if idx_type == "Quake": + load_kwargs = {k: build_params[k] for k in ("use_numa","num_workers") if k in build_params} + idx = QuakeWrapper(); idx.load(str(idx_file), **load_kwargs) + elif idx_type == "DiskANN": + idx = IndexClass(); build_params.pop("metric", None); idx.load(str(idx_file), **build_params) else: - idx = cls(); idx.load(str(idx_path)) + idx = IndexClass(); idx.load(str(idx_file)) - # Warm-up runs - for _ in range(min(warmup_n, len(queries))): - for q in queries: - idx.search(q.unsqueeze(0).float(), k, **s_params) + # Warmup (batch) + for _ in range(min(warmup,1)): + idx.search(queries, k, **search_params) - # Prepare accumulators for detailed timers + # Prepare per-phase accumulators child_buf_init_trials = [] - child_enq_trials = [] + child_enqueue_trials = [] child_wait_trials = [] child_agg_trials = [] child_total_trials = [] - parent_buf_init_trials = [] - parent_enq_trials = [] - parent_wait_trials = [] - parent_agg_trials = [] - parent_total_trials = [] - recall_trials = [] - - # Benchmark trials + parent_buf_init_trials= [] + parent_enqueue_trials = [] + parent_wait_trials = [] + parent_agg_trials = [] + parent_total_trials = [] + recall_trials = [] + + # Benchmark Trials (batch) for t in range(trials): - # per-trial lists - buf_init = [] - enq = [] - wait = [] - agg = [] - tot = [] - p_buf = [] - p_enq = [] - p_wait = [] - p_agg = [] - p_tot = [] - recs = [] - - for qi, q in enumerate(queries): - res = idx.search(q.unsqueeze(0).float(), k, **s_params) - ti = res.timing_info - - # child (worker_scan) timers - buf_init.append(ti.buffer_init_time_ns) - enq.append(ti.job_enqueue_time_ns) - wait.append(ti.job_wait_time_ns) - agg.append(ti.result_aggregate_time_ns) - tot.append(ti.total_time_ns) + res = idx.search(queries, k, **search_params) + ti = res.timing_info + + # Child (worker_scan) timings + child_buf_init_trials.append(ti.buffer_init_time_ns / 1e6) + child_enqueue_trials .append(ti.job_enqueue_time_ns / 1e6) + child_wait_trials .append(ti.job_wait_time_ns / 1e6) + child_agg_trials .append(ti.result_aggregate_time_ns / 1e6) + child_total_trials .append(ti.total_time_ns / 1e6) + + # Parent timings + pi = getattr(ti, "parent_info", None) + if pi: + parent_buf_init_trials.append(pi.buffer_init_time_ns / 1e6) + parent_enqueue_trials .append(pi.job_enqueue_time_ns / 1e6) + parent_wait_trials .append(pi.job_wait_time_ns / 1e6) + parent_agg_trials .append(pi.result_aggregate_time_ns / 1e6) + parent_total_trials .append(pi.total_time_ns / 1e6) + else: + parent_buf_init_trials.append(0.0) + parent_enqueue_trials .append(0.0) + parent_wait_trials .append(0.0) + parent_agg_trials .append(0.0) + parent_total_trials .append(0.0) + + # Recall for this trial + if gt is not None: + preds_arr = extract_ids(res) + recall = float(compute_recall(preds_arr, gt, k).mean()) + recall_trials.append(recall) + print(f" [{name} trial {t+1}/{trials}] child_total={child_total_trials[-1]:.2f} ms, parent_total={parent_total_trials[-1]:.2f} ms | recall@{k} {recall:.4f}") + else: + print(f" [{name} trial {t+1}/{trials}] child_total={child_total_trials[-1]:.2f} ms, parent_total={parent_total_trials[-1]:.2f} ms") + + # Aggregate metrics + mean_lat = float(np.mean(child_total_trials)) + std_lat = float(np.std(child_total_trials)) + mean_recall= float(np.mean(recall_trials)) if recall_trials else np.nan + n_workers = build_params.get("num_workers", None) - # parent timers if present - pi = getattr(ti, "parent_info", None) - if pi: - p_buf.append(pi.buffer_init_time_ns) - p_enq.append(pi.job_enqueue_time_ns) - p_wait.append(pi.job_wait_time_ns) - p_agg.append(pi.result_aggregate_time_ns) - p_tot.append(pi.total_time_ns) - else: - p_buf.append(0) - p_enq.append(0) - p_wait.append(0) - p_agg.append(0) - p_tot.append(0) - - # recall on first trial - if gt is not None and t == 0: - preds = extract_ids(res)[0] - recs.append(float(compute_recall(torch.tensor([preds]), gt[qi:qi+1], k).item())) - - # compute per-trial means (convert ns to ms where appropriate) - child_buf_init_trials.append(np.mean(buf_init)/1e6) - child_enq_trials .append(np.mean(enq) /1e6) - child_wait_trials .append(np.mean(wait) /1e6) - child_agg_trials .append(np.mean(agg) /1e6) - child_total_trials .append(np.mean(tot) /1e6) - parent_buf_init_trials.append(np.mean(p_buf)/1e6) - parent_enq_trials .append(np.mean(p_enq)/1e6) - parent_wait_trials .append(np.mean(p_wait)/1e6) - parent_agg_trials .append(np.mean(p_agg)/1e6) - parent_total_trials .append(np.mean(p_tot)/1e6) - recall_trials.append(np.mean(recs) if recs else np.nan) - - print(f" [{name} trial {t+1}/{trials}] " - f"child_tot={child_total_trials[-1]:.2f}ms, " - f"parent_tot={parent_total_trials[-1]:.2f}ms, " - f"R@{k}={recall_trials[-1]:.4f}") - - # assemble result row row = { "index": name, - "n_workers": b_params.get("num_workers", np.nan), - "recall_at_%d"%k: float(np.mean(recall_trials)), - "child_buffer_init_ms": float(np.mean(child_buf_init_trials)), - "child_enqueue_ms": float(np.mean(child_enq_trials)), - "child_wait_ms": float(np.mean(child_wait_trials)), - "child_aggregate_ms": float(np.mean(child_agg_trials)), - "child_total_ms": float(np.mean(child_total_trials)), + "n_workers": n_workers, + f"recall_at_{k}": mean_recall, + "mean_latency_ms": mean_lat, + "std_latency_ms": std_lat, + "child_buffer_init_ms":float(np.mean(child_buf_init_trials)), + "child_enqueue_ms": float(np.mean(child_enqueue_trials)), + "child_wait_ms": float(np.mean(child_wait_trials)), + "child_aggregate_ms": float(np.mean(child_agg_trials)), + "child_total_ms": float(np.mean(child_total_trials)), "parent_buffer_init_ms":float(np.mean(parent_buf_init_trials)), - "parent_enqueue_ms": float(np.mean(parent_enq_trials)), - "parent_wait_ms": float(np.mean(parent_wait_trials)), - "parent_aggregate_ms": float(np.mean(parent_agg_trials)), - "parent_total_ms": float(np.mean(parent_total_trials)), + "parent_enqueue_ms": float(np.mean(parent_enqueue_trials)), + "parent_wait_ms": float(np.mean(parent_wait_trials)), + "parent_aggregate_ms": float(np.mean(parent_agg_trials)), + "parent_total_ms": float(np.mean(parent_total_trials)), } all_rows.append(row) pd.DataFrame([row]).to_csv(idx_csv, index=False) - # write unified CSV + # Save unified CSV df = pd.DataFrame(all_rows) out_csv = out_dir / csv_name df.to_csv(out_csv, index=False) - print(f"\n[RESULT] Unified results → {out_csv}") + print(f"\n[RESULT] Results written to {out_csv}") - # Plot child total latency + # Plot batch total latency (child only) plt.figure() - for nm in df["index"].unique(): - sub = df[df["index"]==nm] - lbl = (nm if sub["n_workers"].isnull().all() - else f"{nm} (nw={int(sub['n_workers'].iloc[0])})") - plt.errorbar(sub["n_workers"], sub["child_total_ms"], - yerr=df[df['index']==nm]["child_total_ms"].std(), - marker="o", capsize=5, label=lbl) + for idx_name in df["index"].unique(): + sub = df[df["index"]==idx_name] + label = f"{idx_name}" if pd.isna(sub["n_workers"]).all() else f"{idx_name} (n_workers={int(sub['n_workers'].iloc[0])})" + plt.errorbar( + sub["n_workers"], sub["child_total_ms"], + yerr=sub["child_total_ms"].std(), + marker="o", capsize=5, label=label + ) plt.xscale("symlog", base=2) plt.xlabel("Num Workers") - plt.ylabel("Mean Child Total Latency (ms)") - plt.title("Child Latency Breakdown (per-index)") + plt.ylabel("Mean Child Batch Latency (ms)") + plt.title("Batch Query Child Total Latency") plt.legend(); plt.tight_layout() - plt.savefig(out_dir/ f"{out_csv.stem}_child_breakdown.png") - print(f"[PLOT] Child breakdown → {out_dir/ f'{out_csv.stem}_child_breakdown.png'}") + plt.savefig(out_dir / f"{out_csv.stem}_batch_latency.png") + print(f"[PLOT] Saved to {out_dir / f'{out_csv.stem}_batch_latency.png'}") # Plot recall - plt.figure() - for nm in df["index"].unique(): - sub = df[df["index"]==nm] - lbl = (nm if sub["n_workers"].isnull().all() - else f"{nm} (nw={int(sub['n_workers'].iloc[0])})") - plt.plot(sub["n_workers"], sub[f"recall_at_{k}"], marker="o", label=lbl) - plt.xscale("symlog", base=2) - plt.xlabel("Num Workers") - plt.ylabel(f"Recall@{k}") - plt.title(f"Recall@{k} (per-index)") - plt.legend(); plt.tight_layout() - plt.savefig(out_dir/ f"{out_csv.stem}_recall.png") - print(f"[PLOT] Recall plot → {out_dir/ f'{out_csv.stem}_recall.png'}") \ No newline at end of file + if f"recall_at_{k}" in df.columns: + plt.figure() + for idx_name in df["index"].unique(): + sub = df[df["index"]==idx_name] + label = f"{idx_name}" if pd.isna(sub["n_workers"]).all() else f"{idx_name} (n_workers={int(sub['n_workers'].iloc[0])})" + plt.plot(sub["n_workers"], sub[f"recall_at_{k}"], marker="o", label=label) + plt.xscale("symlog", base=2) + plt.xlabel("Num Workers") + plt.ylabel(f"Recall@{k}") + plt.title(f"Recall@{k} (batch)") + plt.legend(); plt.tight_layout() + plt.savefig(out_dir / f"{out_csv.stem}_batch_recall.png") + print(f"[PLOT] Recall plot saved to {out_dir / f'{out_csv.stem}_batch_recall.png'}") \ No newline at end of file From 37d3e67bd71d5f3f1ba069d374ef3638c9a65e30 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 17:02:00 -0500 Subject: [PATCH 183/323] update multi-experiment to track detailed timers --- src/cpp/bindings/wrap.cpp | 2 ++ src/cpp/include/common.h | 1 + src/cpp/src/query_coordinator.cpp | 4 ++-- test/experiments/osdi2025/numa_multi_query/run.py | 7 +++++++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/cpp/bindings/wrap.cpp b/src/cpp/bindings/wrap.cpp index 35c98e3d..d4aa0d87 100644 --- a/src/cpp/bindings/wrap.cpp +++ b/src/cpp/bindings/wrap.cpp @@ -324,6 +324,8 @@ PYBIND11_MODULE(_bindings, m) { "Total time taken for the search operation in nanoseconds.") .def_readwrite("buffer_init_time_ns", &SearchTimingInfo::buffer_init_time_ns, "Time spent on initializing buffers in nanoseconds.") + .def_readwrite("copy_query_time_ns", &SearchTimingInfo::copy_query_time_ns, + "Time spent on copying query vectors to NUMA buffers in nanoseconds.") .def_readwrite("job_enqueue_time_ns", &SearchTimingInfo::job_enqueue_time_ns, "Time spent on creating jobs in nanoseconds.") .def_readwrite("boundary_distance_time_ns", &SearchTimingInfo::boundary_distance_time_ns, diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index aa102738..b165ac5f 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -238,6 +238,7 @@ struct SearchTimingInfo { // main thread counters for worker scan int64_t buffer_init_time_ns; ///< Time spent on initializing buffers in nanoseconds. + int64_t copy_query_time_ns; int64_t job_enqueue_time_ns; ///< Time spent on creating jobs in nanoseconds. int64_t boundary_distance_time_ns; ///< Time spent on computing boundary distances in nanoseconds. int64_t aps_time_ns; ///< Time spent on APS in nanoseconds. diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index fd36036e..8c00c512 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -670,8 +670,8 @@ std::shared_ptr QueryCoordinator::worker_scan( res->timing_info->buffer_init_time_ns = duration_cast(s2 - s1).count(); -// res->timing_info->copy_query_time_ns = -// duration_cast(s3 - s2).count(); + res->timing_info->copy_query_time_ns = + duration_cast(s3 - s2).count(); res->timing_info->job_enqueue_time_ns = duration_cast(s4 - s3).count(); res->timing_info->job_wait_time_ns = diff --git a/test/experiments/osdi2025/numa_multi_query/run.py b/test/experiments/osdi2025/numa_multi_query/run.py index 6c826178..10eb5fbb 100644 --- a/test/experiments/osdi2025/numa_multi_query/run.py +++ b/test/experiments/osdi2025/numa_multi_query/run.py @@ -146,11 +146,13 @@ def run_experiment(cfg_path: str, output_dir: str): # Prepare per-phase accumulators child_buf_init_trials = [] + child_copy_query_trials = [] child_enqueue_trials = [] child_wait_trials = [] child_agg_trials = [] child_total_trials = [] parent_buf_init_trials= [] + parent_copy_query_trials = [] parent_enqueue_trials = [] parent_wait_trials = [] parent_agg_trials = [] @@ -164,6 +166,7 @@ def run_experiment(cfg_path: str, output_dir: str): # Child (worker_scan) timings child_buf_init_trials.append(ti.buffer_init_time_ns / 1e6) + child_copy_query_trials.append(ti.copy_query_time_ns / 1e6) child_enqueue_trials .append(ti.job_enqueue_time_ns / 1e6) child_wait_trials .append(ti.job_wait_time_ns / 1e6) child_agg_trials .append(ti.result_aggregate_time_ns / 1e6) @@ -173,12 +176,14 @@ def run_experiment(cfg_path: str, output_dir: str): pi = getattr(ti, "parent_info", None) if pi: parent_buf_init_trials.append(pi.buffer_init_time_ns / 1e6) + parent_copy_query_trials.append(pi.copy_query_time_ns / 1e6) parent_enqueue_trials .append(pi.job_enqueue_time_ns / 1e6) parent_wait_trials .append(pi.job_wait_time_ns / 1e6) parent_agg_trials .append(pi.result_aggregate_time_ns / 1e6) parent_total_trials .append(pi.total_time_ns / 1e6) else: parent_buf_init_trials.append(0.0) + parent_copy_query_trials.append(0.0) parent_enqueue_trials .append(0.0) parent_wait_trials .append(0.0) parent_agg_trials .append(0.0) @@ -206,11 +211,13 @@ def run_experiment(cfg_path: str, output_dir: str): "mean_latency_ms": mean_lat, "std_latency_ms": std_lat, "child_buffer_init_ms":float(np.mean(child_buf_init_trials)), + "child_copy_query_ms": float(np.mean(child_copy_query_trials)), "child_enqueue_ms": float(np.mean(child_enqueue_trials)), "child_wait_ms": float(np.mean(child_wait_trials)), "child_aggregate_ms": float(np.mean(child_agg_trials)), "child_total_ms": float(np.mean(child_total_trials)), "parent_buffer_init_ms":float(np.mean(parent_buf_init_trials)), + "parent_copy_query_ms": float(np.mean(parent_copy_query_trials)), "parent_enqueue_ms": float(np.mean(parent_enqueue_trials)), "parent_wait_ms": float(np.mean(parent_wait_trials)), "parent_aggregate_ms": float(np.mean(parent_agg_trials)), From 3b08e4684ec0490259cd3405f5e417123ccb6086 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 17:15:35 -0500 Subject: [PATCH 184/323] configure num parent workers --- src/cpp/include/quake_index.h | 2 +- src/cpp/src/quake_index.cpp | 7 +------ src/python/index_wrappers/quake.py | 10 +++------- test/experiments/osdi2025/numa_multi_query/run.py | 2 +- test/experiments/osdi2025/numa_single_query/run.py | 2 +- 5 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/cpp/include/quake_index.h b/src/cpp/include/quake_index.h index d2377aaa..0358aec9 100644 --- a/src/cpp/include/quake_index.h +++ b/src/cpp/include/quake_index.h @@ -122,7 +122,7 @@ class QuakeIndex { * @param path Path to load the index. * @param n_workers Number of workers to use for query processing. */ - void load(const std::string &path, int n_workers = 0, bool use_numa=false); + void load(const std::string &path, int n_workers = 0, bool use_numa=false, int parent_n_workers=0); /** * @brief Get the total number of vectors in the index. diff --git a/src/cpp/src/quake_index.cpp b/src/cpp/src/quake_index.cpp index 8419d64f..36f04661 100644 --- a/src/cpp/src/quake_index.cpp +++ b/src/cpp/src/quake_index.cpp @@ -236,7 +236,7 @@ void QuakeIndex::save(const std::string& dir_path) { std::cout << "[QuakeIndex::save] Index saved to directory: " << dir_path << "\n"; } -void QuakeIndex::load(const std::string& dir_path, int n_workers, bool use_numa) { +void QuakeIndex::load(const std::string& dir_path, int n_workers, bool use_numa, int parent_n_workers) { namespace fs = std::filesystem; if (!fs::exists(dir_path) || !fs::is_directory(dir_path)) { @@ -282,11 +282,6 @@ void QuakeIndex::load(const std::string& dir_path, int n_workers, bool use_numa) if (fs::exists(parent_dir) && fs::is_directory(parent_dir)) { parent_ = std::make_shared(); int n_parts = partition_manager_->nlist(); - - // don't put too many parent workers. maximum of 1 worker per 500 partitions - int parent_n_workers = std::max(1, n_parts / 1000); - parent_n_workers = std::min(parent_n_workers, n_workers); - parent_->load(parent_dir, parent_n_workers, use_numa); partition_manager_->parent_ = parent_; } else { diff --git a/src/python/index_wrappers/quake.py b/src/python/index_wrappers/quake.py index 033abdba..982165ca 100644 --- a/src/python/index_wrappers/quake.py +++ b/src/python/index_wrappers/quake.py @@ -203,12 +203,9 @@ def load( self, filename: str, num_workers: int = 0, + parent_num_workers: int = 0, use_numa: bool = False, verbose: bool = False, - verify_numa: bool = False, - same_core: bool = True, - use_centroid_workers: bool = False, - use_adaptive_n_probe: bool = False, ): """ Load the index from a file. @@ -216,11 +213,10 @@ def load( :param filename: The name of the file to load the index from. """ print( - f"Loading index from {filename}, with {num_workers} workers, use_numa={use_numa}, verbose={verbose}, " - f"verify_numa={verify_numa}, same_core={same_core}, use_centroid_workers={use_centroid_workers}" + f"Loading index from {filename}, with {num_workers} workers, use_numa={use_numa}, parent_num_workers={parent_num_workers}" ) self.index = QuakeIndex() - self.index.load(str(filename), num_workers, use_numa) + self.index.load(str(filename), num_workers, use_numa, parent_num_workers) def centroids(self) -> torch.Tensor: """ diff --git a/test/experiments/osdi2025/numa_multi_query/run.py b/test/experiments/osdi2025/numa_multi_query/run.py index 10eb5fbb..9c798d36 100644 --- a/test/experiments/osdi2025/numa_multi_query/run.py +++ b/test/experiments/osdi2025/numa_multi_query/run.py @@ -133,7 +133,7 @@ def run_experiment(cfg_path: str, output_dir: str): # Load index if idx_type == "Quake": - load_kwargs = {k: build_params[k] for k in ("use_numa","num_workers") if k in build_params} + load_kwargs = {k: build_params[k] for k in ("use_numa","num_workers", "parent_num_workers") if k in build_params} idx = QuakeWrapper(); idx.load(str(idx_file), **load_kwargs) elif idx_type == "DiskANN": idx = IndexClass(); build_params.pop("metric", None); idx.load(str(idx_file), **build_params) diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index 8f08bce2..a787c0d2 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -129,7 +129,7 @@ def run_experiment(cfg_path: str, output_dir: str) -> None: # Load index if typ == "Quake": - load_kw = {k: b_params[k] for k in ("use_numa", "num_workers") if k in b_params} + load_kw = {k: b_params[k] for k in ("use_numa", "num_workers", "parent_num_workers") if k in b_params} idx = QuakeWrapper(); idx.load(str(idx_path), **load_kw) elif typ == "DiskANN": idx = cls(); b_params.pop("metric", None); idx.load(str(idx_path), **b_params) From d5857154947626c02221f5c8a3dc3c2073332655 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 17:29:18 -0500 Subject: [PATCH 185/323] configure num parent workers --- src/cpp/src/query_coordinator.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 8c00c512..aa51a433 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -950,11 +950,16 @@ shared_ptr QueryCoordinator::search(Tensor x, shared_ptr(); if (search_params->parent_params == nullptr) { - parent_search_params->recall_target = .99; +// parent_search_params->recall_target = .99; parent_search_params->use_precomputed = search_params->use_precomputed; parent_search_params->recompute_threshold = search_params->recompute_threshold; - parent_search_params->initial_search_fraction = .5; +// parent_search_params->initial_search_fraction = .5; parent_search_params->batched_scan = false; + + if (x.size(0) > 10) { + parent_search_params->batched_scan = true; + } + } else { parent_search_params = search_params->parent_params; } From 2ec93f1851a7b699e73775c1095b0b48c4ef24ae Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 17:35:05 -0500 Subject: [PATCH 186/323] configure num parent workers --- src/cpp/include/query_coordinator.h | 1 + src/cpp/src/query_coordinator.cpp | 45 +++++++++++++++++++---------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 2a78379a..60f8bd33 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -32,6 +32,7 @@ struct ScanJob { std::shared_ptr> query_ids; ///< Global query IDs; used in batched mode. std::shared_ptr> ranks; ///< Rank of the partition for each query + bool scan_all = false; }; /** diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index aa51a433..cd4d9a7a 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -295,22 +295,37 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, } // Gather queries into res.batch_queries (as in your original code) - for (int64_t i = 0; i < job.num_queries; ++i) { - std::memcpy(res.batch_queries + i * D, - job.query_vector + job.query_ids->at(i) * D, - D * sizeof(float)); + + if (job.scan_all) { + batched_scan_list(nr.local_query_buffer, + codes, + ids, + job.num_queries, + part_size, + D, + res.topk_buffer_pool, // Vector of TopkBuffer shared_ptrs + metric_, + res.batch_distances, // Scratch space for distances + res.batch_ids); // Scratch space for IDs + } else { + for (int64_t i = 0; i < job.num_queries; ++i) { + std::memcpy(res.batch_queries + i * D, + nr.local_query_buffer + job.query_ids->at(i) * D, + D * sizeof(float)); + } + + batched_scan_list(res.batch_queries, + codes, + ids, + job.num_queries, + part_size, + D, + res.topk_buffer_pool, // Vector of TopkBuffer shared_ptrs + metric_, + res.batch_distances, // Scratch space for distances + res.batch_ids); // Scratch space for IDs } - batched_scan_list(res.batch_queries, - codes, - ids, - job.num_queries, - part_size, - D, - res.topk_buffer_pool, // Vector of TopkBuffer shared_ptrs - metric_, - res.batch_distances, // Scratch space for distances - res.batch_ids); // Scratch space for IDs scan_successful = true; } catch (const std::exception& e) { @@ -453,7 +468,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, job.k = params->k; job.query_vector = x.data_ptr(); job.num_queries = x.size(0); - job.query_ids = all_query_ids_ptr; + job.scan_all = true; job.ranks = make_shared>(x.size(0), i); int core_id = partition_manager_->get_partition_core_id(pids_acc[i]); if (core_id < 0) { From f5bc2246e6d658033441e350f52a693738b76d8a Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 17:42:21 -0500 Subject: [PATCH 187/323] configure num parent workers --- src/cpp/src/query_coordinator.cpp | 219 +++++++++++++----------------- 1 file changed, 93 insertions(+), 126 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index cd4d9a7a..40ab9733 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -215,157 +215,124 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, void QueryCoordinator::handle_batched_job(const ScanJob &job, CoreResources &res, NUMAResources &nr) { - // Number of queries in this batch, top-k, vector dimension, and NUMA node + // Total queries in this batch, Top-K, vector dim, and NUMA node int64_t Q = job.num_queries; int K = job.k; int D = partition_manager_->d(); int node = cpu_numa_node(res.core_id); - // Ensure we have exactly Q TopK buffers, each with capacity = max(100*K, 10000) - size_t cap = std::max(100 * K, 10000); - if (res.topk_buffer_pool.size() < (size_t)Q) { - res.topk_buffer_pool.resize(Q); - for (int64_t i = 0; i < Q; ++i) { - res.topk_buffer_pool[i] = std::make_shared( - K, - metric_ == faiss::METRIC_INNER_PRODUCT, - /*cap=*/cap, - /*node=*/node - ); + // Retrieve partition data once + const float *codes = (float*)partition_manager_->partition_store_->get_codes(job.partition_id); + const int64_t *ids = (int64_t*)partition_manager_->partition_store_->get_ids(job.partition_id); + int64_t part_size = partition_manager_->partition_store_->list_size(job.partition_id); + if (!codes || !ids || part_size <= 0) { + // Empty or invalid partition: enqueue empty results + for (int64_t q : *job.query_ids) { + result_queue_.enqueue(ResultJob{(int)q, 0, {}, {}}); } - } else { - for (int64_t i = 0; i < Q; ++i) { + return; + } + + // Maximum sub-batch size to bound memory + static constexpr int64_t MAX_SUBBATCH = 128; + + // Process queries in chunks of at most MAX_SUBBATCH + for (int64_t offset = 0; offset < Q; offset += MAX_SUBBATCH) { + int64_t chunk = std::min(Q - offset, MAX_SUBBATCH); + + // 1) Prepare TopK buffers for this sub-batch + size_t cap = std::max(100 * K, 10000); + if (res.topk_buffer_pool.size() < (size_t)chunk) { + // grow pool to at least 'chunk' + size_t old = res.topk_buffer_pool.size(); + res.topk_buffer_pool.resize(chunk); + for (size_t i = old; i < (size_t)chunk; ++i) { + res.topk_buffer_pool[i] = std::make_shared( + K, + metric_ == faiss::METRIC_INNER_PRODUCT, + /*cap=*/cap, + /*node=*/node + ); + } + } + // reset first 'chunk' buffers + for (int64_t i = 0; i < chunk; ++i) { auto &buf = res.topk_buffer_pool[i]; buf->set_k(K); buf->reset(); } - } - // Allocate or grow the per-batch query buffer (size Q × D floats) - size_t need_q = size_t(Q) * D; - if (res.batch_q_capacity < need_q) { - if (res.batch_queries) { - quake_free(res.batch_queries, - res.batch_q_capacity * sizeof(float)); + // 2) Allocate or grow query gather buffer (chunk × D floats) + size_t need_q = size_t(chunk) * D; + if (res.batch_q_capacity < need_q) { + if (res.batch_queries) { + quake_free(res.batch_queries, + res.batch_q_capacity * sizeof(float)); + } + res.batch_queries = static_cast( + quake_alloc(need_q * sizeof(float), node)); + res.batch_q_capacity = need_q; } - res.batch_queries = static_cast(quake_alloc( - need_q * sizeof(float), node)); - res.batch_q_capacity = need_q; - } - // Allocate or grow the per-batch result buffers (size Q × K entries) - size_t need_r = size_t(Q) * size_t(K); - if (res.batch_res_capacity < need_r) { - if (res.batch_distances) { - quake_free(res.batch_distances, - res.batch_res_capacity * sizeof(float)); - } - if (res.batch_ids) { - quake_free(res.batch_ids, - res.batch_res_capacity * sizeof(int64_t)); + // 3) Allocate or grow result scratch buffers (chunk × K entries) + size_t need_r = size_t(chunk) * size_t(K); + if (res.batch_res_capacity < need_r) { + if (res.batch_distances) { + quake_free(res.batch_distances, + res.batch_res_capacity * sizeof(float)); + } + if (res.batch_ids) { + quake_free(res.batch_ids, + res.batch_res_capacity * sizeof(int64_t)); + } + res.batch_distances = static_cast( + quake_alloc(need_r * sizeof(float), node)); + res.batch_ids = static_cast( + quake_alloc(need_r * sizeof(int64_t), node)); + res.batch_res_capacity = need_r; } - res.batch_distances = static_cast( - quake_alloc(need_r * sizeof(float), node)); - res.batch_ids = static_cast( - quake_alloc(need_r * sizeof(int64_t), node)); - res.batch_res_capacity = need_r; - } - - // Initialize the result buffers to infinity (or –infinity) and –1 - float dist_init = (metric_ == faiss::METRIC_INNER_PRODUCT) - ? -std::numeric_limits::infinity() - : std::numeric_limits::infinity(); - for (size_t idx = 0; idx < need_r; ++idx) { - res.batch_distances[idx] = dist_init; - res.batch_ids [idx] = -1; - } - bool scan_successful = false; - try { - const float* codes = (float*)partition_manager_->partition_store_->get_codes(job.partition_id); - const int64_t* ids = (int64_t*)partition_manager_->partition_store_->get_ids(job.partition_id); - int64_t part_size = partition_manager_->partition_store_->list_size(job.partition_id); - int D = partition_manager_->d(); - - if (!codes || !ids || part_size <= 0) { - std::cerr << "[QueryCoordinator::handle_batched_job] Partition " << job.partition_id - << " invalid or empty before batched scan. Enqueuing empty results for batch.\n"; - // Let success remain false, loop below will send empty results - throw std::runtime_error("Batched scan pre-check failed for partition data"); + // 4) Initialize result scratch + float init_val = (metric_ == faiss::METRIC_INNER_PRODUCT) + ? -std::numeric_limits::infinity() + : std::numeric_limits::infinity(); + for (size_t i = 0; i < need_r; ++i) { + res.batch_distances[i] = init_val; + res.batch_ids [i] = -1; } - // Gather queries into res.batch_queries (as in your original code) - + // 5) Gather this sub-batch of query vectors if (job.scan_all) { - batched_scan_list(nr.local_query_buffer, - codes, - ids, - job.num_queries, - part_size, - D, - res.topk_buffer_pool, // Vector of TopkBuffer shared_ptrs - metric_, - res.batch_distances, // Scratch space for distances - res.batch_ids); // Scratch space for IDs + // use pre-copied NUMA buffer } else { - for (int64_t i = 0; i < job.num_queries; ++i) { - std::memcpy(res.batch_queries + i * D, - nr.local_query_buffer + job.query_ids->at(i) * D, - D * sizeof(float)); + for (int64_t i = 0; i < chunk; ++i) { + int qid = (*job.query_ids)[offset + i]; + float *dst = res.batch_queries + size_t(i) * D; + const float *src = nr.local_query_buffer + size_t(qid) * D; + std::memcpy(dst, src, D * sizeof(float)); } - - batched_scan_list(res.batch_queries, - codes, - ids, - job.num_queries, - part_size, - D, - res.topk_buffer_pool, // Vector of TopkBuffer shared_ptrs - metric_, - res.batch_distances, // Scratch space for distances - res.batch_ids); // Scratch space for IDs } - scan_successful = true; - - } catch (const std::exception& e) { - std::cerr << "[QueryCoordinator::handle_batched_job] Exception during batched scan for partition " - << job.partition_id << ": " << e.what() - << ". Will enqueue empty results for affected queries.\n"; - // scan_successful remains false - } catch (...) { - std::cerr << "[QueryCoordinator::handle_batched_job] Unknown exception during batched scan for partition " - << job.partition_id - << ". Will enqueue empty results for affected queries.\n"; - // scan_successful remains false - } + // 6) Perform the batched scan for this sub-batch + batched_scan_list( + job.scan_all ? nr.local_query_buffer : res.batch_queries, + codes, ids, + chunk, part_size, D, + res.topk_buffer_pool, + metric_, + res.batch_distances, + res.batch_ids + ); - // Enqueue results (actual or empty) for every query in this batch job - std::vector results_batch; - results_batch.reserve(job.num_queries); - for (int64_t i = 0; i < job.num_queries; ++i) { - int global_query_id = job.query_ids->at(i); - int rank_for_this_query = job.ranks->at(i); // Rank of this partition scan for this specific query - - if (scan_successful) { - // Ensure buffer pool access is safe if it could have been resized or is smaller than expected - if (i < res.topk_buffer_pool.size() && res.topk_buffer_pool[i]) { - auto tv = res.topk_buffer_pool[i]->get_topk(); - auto ti = res.topk_buffer_pool[i]->get_topk_indices(); - results_batch.emplace_back(ResultJob{global_query_id, rank_for_this_query, std::move(tv), std::move(ti)}); - } else { - std::cerr << "[QueryCoordinator::handle_batched_job] Error accessing TopK buffer for successful scan, query " - << global_query_id << ", buffer index " << i << ". Sending empty result.\n"; - results_batch.emplace_back(ResultJob{global_query_id, rank_for_this_query, {}, {}}); - } - } else { - // Scan failed, enqueue an empty result for this query's part of the batch - results_batch.emplace_back(ResultJob{global_query_id, rank_for_this_query, {}, {}}); + // 7) Enqueue each result immediately + for (int64_t i = 0; i < chunk; ++i) { + int global_q = (*job.query_ids)[offset + i]; + int rank_q = (*job.ranks) [offset + i]; + auto tv = res.topk_buffer_pool[i]->get_topk(); + auto ti = res.topk_buffer_pool[i]->get_topk_indices(); + result_queue_.enqueue(ResultJob{global_q, rank_q, std::move(tv), std::move(ti)}); } } - if (!results_batch.empty()) { - result_queue_.enqueue_bulk(std::make_move_iterator(results_batch.begin()), results_batch.size()); - } } void QueryCoordinator::init_global_buffers(int64_t nQ, From f0384cd1154ac53e7019c712d7a8df21cdbfb816 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 17:57:42 -0500 Subject: [PATCH 188/323] configure num parent workers --- src/cpp/src/query_coordinator.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 40ab9733..0f811f71 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -436,6 +436,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, job.query_vector = x.data_ptr(); job.num_queries = x.size(0); job.scan_all = true; + job.query_ids = all_query_ids_ptr; job.ranks = make_shared>(x.size(0), i); int core_id = partition_manager_->get_partition_core_id(pids_acc[i]); if (core_id < 0) { From 3a61c4ddbfc24fbcf48c7e76b6dc28cab477ce3f Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 18:05:17 -0500 Subject: [PATCH 189/323] configure num parent workers --- src/cpp/src/query_coordinator.cpp | 10 +++++++--- .../osdi2025/numa_multi_query/configs/sift1m.yaml | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 0f811f71..590b5fe3 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -302,20 +302,24 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, } // 5) Gather this sub-batch of query vectors + float* qptr = nullptr; if (job.scan_all) { - // use pre-copied NUMA buffer + // point at the sub-batch slice inside the big NUMA buffer + qptr = nr.local_query_buffer + offset * D; } else { + // copy into our contiguous temp buffer for (int64_t i = 0; i < chunk; ++i) { int qid = (*job.query_ids)[offset + i]; - float *dst = res.batch_queries + size_t(i) * D; const float *src = nr.local_query_buffer + size_t(qid) * D; + float *dst = res.batch_queries + size_t(i ) * D; std::memcpy(dst, src, D * sizeof(float)); } + qptr = res.batch_queries; } // 6) Perform the batched scan for this sub-batch batched_scan_list( - job.scan_all ? nr.local_query_buffer : res.batch_queries, + qptr, codes, ids, chunk, part_size, D, res.topk_buffer_pool, diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index d5881277..96886fc5 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -26,6 +26,7 @@ indexes: nc: 1000 metric: l2 num_workers: 1 + parent_num_workers: 1 use_numa: false search_params: nprobe: 20 From 315e70611b5b376d7f3e64ab763190c27ae7c94a Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 18:25:58 -0500 Subject: [PATCH 190/323] optim batch scan --- src/cpp/src/query_coordinator.cpp | 126 ++++++++++++++---------------- 1 file changed, 58 insertions(+), 68 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 590b5fe3..28e08e6e 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -215,109 +215,91 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, void QueryCoordinator::handle_batched_job(const ScanJob &job, CoreResources &res, NUMAResources &nr) { - // Total queries in this batch, Top-K, vector dim, and NUMA node + // Total queries, Top-K, dimension, NUMA node int64_t Q = job.num_queries; int K = job.k; int D = partition_manager_->d(); int node = cpu_numa_node(res.core_id); - // Retrieve partition data once - const float *codes = (float*)partition_manager_->partition_store_->get_codes(job.partition_id); - const int64_t *ids = (int64_t*)partition_manager_->partition_store_->get_ids(job.partition_id); + // Fetch partition data + const float *codes = (float *) partition_manager_->partition_store_->get_codes(job.partition_id); + const int64_t *ids = partition_manager_->partition_store_->get_ids(job.partition_id); int64_t part_size = partition_manager_->partition_store_->list_size(job.partition_id); if (!codes || !ids || part_size <= 0) { - // Empty or invalid partition: enqueue empty results for (int64_t q : *job.query_ids) { result_queue_.enqueue(ResultJob{(int)q, 0, {}, {}}); } return; } - // Maximum sub-batch size to bound memory + // Sub-batching static constexpr int64_t MAX_SUBBATCH = 128; - // Process queries in chunks of at most MAX_SUBBATCH + // 1) Prepare per-thread buffers *once* up to MAX_SUBBATCH + size_t cap = std::max(100 * K, 10000); + int64_t queries_req = std::max(Q, MAX_SUBBATCH); + + + if (res.topk_buffer_pool.size() < (size_t)queries_req) { + res.topk_buffer_pool.resize(queries_req); + for (size_t i = 0; i < (size_t)queries_req; ++i) { + res.topk_buffer_pool[i] = + std::make_shared(K, + metric_ == faiss::METRIC_INNER_PRODUCT, + cap, + node); + } + } + + size_t max_q = size_t(queries_req) * D; + if (res.batch_q_capacity < max_q) { + quake_free(res.batch_queries, res.batch_q_capacity * sizeof(float)); + res.batch_queries = static_cast(quake_alloc(max_q * sizeof(float), node)); + res.batch_q_capacity = max_q; + } + + size_t max_r = size_t(queries_req) * K; + if (res.batch_res_capacity < max_r) { + quake_free(res.batch_distances, res.batch_res_capacity * sizeof(float)); + quake_free(res.batch_ids, res.batch_res_capacity * sizeof(int64_t)); + res.batch_distances = static_cast (quake_alloc(max_r * sizeof(float), node)); + res.batch_ids = static_cast(quake_alloc(max_r * sizeof(int64_t), node)); + res.batch_res_capacity = max_r; + } + + // 2) Process in sub-batches for (int64_t offset = 0; offset < Q; offset += MAX_SUBBATCH) { int64_t chunk = std::min(Q - offset, MAX_SUBBATCH); - // 1) Prepare TopK buffers for this sub-batch - size_t cap = std::max(100 * K, 10000); - if (res.topk_buffer_pool.size() < (size_t)chunk) { - // grow pool to at least 'chunk' - size_t old = res.topk_buffer_pool.size(); - res.topk_buffer_pool.resize(chunk); - for (size_t i = old; i < (size_t)chunk; ++i) { - res.topk_buffer_pool[i] = std::make_shared( - K, - metric_ == faiss::METRIC_INNER_PRODUCT, - /*cap=*/cap, - /*node=*/node - ); - } - } - // reset first 'chunk' buffers + // reset only the first 'chunk' TopK buffers for (int64_t i = 0; i < chunk; ++i) { auto &buf = res.topk_buffer_pool[i]; buf->set_k(K); buf->reset(); } - // 2) Allocate or grow query gather buffer (chunk × D floats) - size_t need_q = size_t(chunk) * D; - if (res.batch_q_capacity < need_q) { - if (res.batch_queries) { - quake_free(res.batch_queries, - res.batch_q_capacity * sizeof(float)); - } - res.batch_queries = static_cast( - quake_alloc(need_q * sizeof(float), node)); - res.batch_q_capacity = need_q; - } - - // 3) Allocate or grow result scratch buffers (chunk × K entries) - size_t need_r = size_t(chunk) * size_t(K); - if (res.batch_res_capacity < need_r) { - if (res.batch_distances) { - quake_free(res.batch_distances, - res.batch_res_capacity * sizeof(float)); - } - if (res.batch_ids) { - quake_free(res.batch_ids, - res.batch_res_capacity * sizeof(int64_t)); - } - res.batch_distances = static_cast( - quake_alloc(need_r * sizeof(float), node)); - res.batch_ids = static_cast( - quake_alloc(need_r * sizeof(int64_t), node)); - res.batch_res_capacity = need_r; - } - - // 4) Initialize result scratch + // init only the first chunk*K slots in scratch float init_val = (metric_ == faiss::METRIC_INNER_PRODUCT) ? -std::numeric_limits::infinity() : std::numeric_limits::infinity(); - for (size_t i = 0; i < need_r; ++i) { - res.batch_distances[i] = init_val; - res.batch_ids [i] = -1; - } + std::fill_n(res.batch_distances, chunk * K, init_val); + std::fill_n(res.batch_ids, chunk * K, -1LL); - // 5) Gather this sub-batch of query vectors - float* qptr = nullptr; + // gather queries + float *qptr = nullptr; if (job.scan_all) { - // point at the sub-batch slice inside the big NUMA buffer qptr = nr.local_query_buffer + offset * D; } else { - // copy into our contiguous temp buffer + float *dst = res.batch_queries; for (int64_t i = 0; i < chunk; ++i) { int qid = (*job.query_ids)[offset + i]; const float *src = nr.local_query_buffer + size_t(qid) * D; - float *dst = res.batch_queries + size_t(i ) * D; - std::memcpy(dst, src, D * sizeof(float)); + std::memcpy(dst + i * D, src, D * sizeof(float)); } - qptr = res.batch_queries; + qptr = dst; } - // 6) Perform the batched scan for this sub-batch + // run the scan on this chunk batched_scan_list( qptr, codes, ids, @@ -328,14 +310,22 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, res.batch_ids ); - // 7) Enqueue each result immediately + // collect results for this chunk + std::vector results_batch; + results_batch.reserve(chunk); for (int64_t i = 0; i < chunk; ++i) { int global_q = (*job.query_ids)[offset + i]; int rank_q = (*job.ranks) [offset + i]; auto tv = res.topk_buffer_pool[i]->get_topk(); auto ti = res.topk_buffer_pool[i]->get_topk_indices(); - result_queue_.enqueue(ResultJob{global_q, rank_q, std::move(tv), std::move(ti)}); + results_batch.emplace_back(ResultJob{global_q, rank_q, std::move(tv), std::move(ti)}); } + + // enqueue this sub-batch in bulk + result_queue_.enqueue_bulk( + std::make_move_iterator(results_batch.begin()), + results_batch.size() + ); } } From 573c5a64f88d99957ff19c253409c6df116bb8fe Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 18:29:21 -0500 Subject: [PATCH 191/323] optim batch scan --- src/cpp/src/query_coordinator.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 28e08e6e..41bf283e 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -237,7 +237,7 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, // 1) Prepare per-thread buffers *once* up to MAX_SUBBATCH size_t cap = std::max(100 * K, 10000); - int64_t queries_req = std::max(Q, MAX_SUBBATCH); + int64_t queries_req = std::min(Q, MAX_SUBBATCH); if (res.topk_buffer_pool.size() < (size_t)queries_req) { @@ -299,6 +299,13 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, qptr = dst; } + for (int64_t i = 0; i < chunk; i += 4) { + __builtin_prefetch(qptr + i * D, /* rw = */ 0, /* locality = */ 3); + } + // PREFETCH: warm up the partition codes and ids + __builtin_prefetch(codes, 0, 3); + __builtin_prefetch(ids, 0, 3); + // run the scan on this chunk batched_scan_list( qptr, From 2c84df37b37a0e3539433cf3269b019d0266bc6b Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 18:59:02 -0500 Subject: [PATCH 192/323] optim batch scan --- src/cpp/src/query_coordinator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 41bf283e..e943bf25 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -79,7 +79,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { while (!stop_workers_) { int64_t jid = 0; if (!res.job_queue.try_dequeue(jid)) { - std::this_thread::sleep_for(std::chrono::microseconds(5)); + std::this_thread::sleep_for(std::chrono::microseconds(20)); continue; } @@ -236,7 +236,7 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, static constexpr int64_t MAX_SUBBATCH = 128; // 1) Prepare per-thread buffers *once* up to MAX_SUBBATCH - size_t cap = std::max(100 * K, 10000); + size_t cap = std::min(100 * K, 10000); int64_t queries_req = std::min(Q, MAX_SUBBATCH); From ab992bfbd3646b68e7434531c233e28aea0b120f Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 20 May 2025 22:04:21 -0500 Subject: [PATCH 193/323] optim batch scan --- src/cpp/src/query_coordinator.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index e943bf25..d7e3835a 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -150,7 +150,7 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, res.topk_buffer_pool[0] = std::make_shared( job.k, metric_ == faiss::METRIC_INNER_PRODUCT, - /*cap=*/std::max(100 * job.k, 10000), + /*cap=*/std::min(100 * job.k, 10000), /*node=*/cpu_numa_node(res.core_id) ); } else if (res.topk_buffer_pool[0]->k_ != job.k) { @@ -159,7 +159,7 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, res.topk_buffer_pool[0] = std::make_shared( job.k, metric_ == faiss::METRIC_INNER_PRODUCT, - /*cap=*/std::max(100 * job.k, 10000), + /*cap=*/std::min(100 * job.k, 10000), /*node=*/cpu_numa_node(res.core_id) ); } @@ -342,6 +342,8 @@ void QueryCoordinator::init_global_buffers(int64_t nQ, shared_ptr params) { std::lock_guard lg(global_mutex_); // resize or reset + + size_t cap = std::min(100 * K, 10000); if (global_topk_buffer_pool_.size() < (size_t) nQ) { size_t old = global_topk_buffer_pool_.size(); global_topk_buffer_pool_.resize(nQ); @@ -349,7 +351,7 @@ void QueryCoordinator::init_global_buffers(int64_t nQ, global_topk_buffer_pool_[q] = std::make_shared( K, metric_ == faiss::METRIC_INNER_PRODUCT, - /*cap=*/num_workers_ * K * 2, + /*cap=*/cap, /*node=*/0 ); } From 7dfca1abe2238ec650f8e5cf342d82b598fd8737 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 00:18:45 -0500 Subject: [PATCH 194/323] update aps experiment --- src/cpp/src/query_coordinator.cpp | 21 +- .../adaptive_partition_scanning/aps.py | 698 ------------------ .../adaptive_partition_scanning/run.py | 119 +++ test/experiments/osdi2025/README.md | 134 +++- .../osdi2025/aps_recall_targets/run.py | 237 +++--- test/experiments/osdi2025/experiment_utils.py | 126 ++++ 6 files changed, 452 insertions(+), 883 deletions(-) delete mode 100644 test/experiments/adaptive_partition_scanning/aps.py create mode 100644 test/experiments/adaptive_partition_scanning/run.py create mode 100644 test/experiments/osdi2025/experiment_utils.py diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index d7e3835a..7f3c0611 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -10,6 +10,7 @@ #include #include #include +//#include "parallel_hashmap/btree.h" // Constructor QueryCoordinator::QueryCoordinator(shared_ptr parent, @@ -451,25 +452,25 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, } } else { - std::unordered_map>>> per_partition_query_ids; // for batched scan + std::unordered_map>> per_partition_query_ids; // for batched scan +// ska::flat_hash_map> per_partition_query_ids_map; + for (int64_t q = 0; q < nQ; q++) { for (int64_t p = 0; p < partition_ids.size(1); p++) { int64_t pid = pid_acc[q][p]; if (pid < 0) continue; if (per_partition_query_ids[pid] == nullptr) { - per_partition_query_ids[pid] = make_shared>>(); + per_partition_query_ids[pid] = make_shared>(); } - per_partition_query_ids[pid]->push_back({q, p}); + per_partition_query_ids[pid]->push_back(q); } } for (auto &kv : per_partition_query_ids) { - auto qids_and_ranks = kv.second; - vector qids(qids_and_ranks->size()); - vector ranks(qids_and_ranks->size()); - for (size_t i = 0; i < qids_and_ranks->size(); ++i) { - qids[i] = (*qids_and_ranks)[i].first; - ranks[i] = (*qids_and_ranks)[i].second; + auto qids = kv.second; + vector ranks(qids->size()); + for (size_t i = 0; i < qids->size(); ++i) { + ranks[i] = i; } ScanJob job; @@ -478,7 +479,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, job.k = params->k; job.query_vector = x.data_ptr(); job.num_queries = kv.second->size(); - job.query_ids = make_shared>(qids); + job.query_ids = qids; job.ranks = make_shared>(ranks); int core_id = partition_manager_->get_partition_core_id(kv.first); if (core_id < 0) { diff --git a/test/experiments/adaptive_partition_scanning/aps.py b/test/experiments/adaptive_partition_scanning/aps.py deleted file mode 100644 index 78ee9e7f..00000000 --- a/test/experiments/adaptive_partition_scanning/aps.py +++ /dev/null @@ -1,698 +0,0 @@ -import logging -from pathlib import Path - -import hydra -import matplotlib.pyplot as plt -import numpy as np -import pandas as pd -import seaborn as sns -import torch -from hydra.utils import get_original_cwd -from omegaconf import DictConfig - -from quake import IndexBuildParams, QuakeIndex, SearchParams -from quake.datasets.ann_datasets import load_dataset -from quake.utils import compute_recall, to_path - -# Set up logging -log = logging.getLogger(__name__) - -# Constants -MIN_FANOUT = 8 - - -# Dataset Management -def get_dataset(cfg): - dataset_path = get_original_cwd() / to_path(cfg.dataset.path) - vectors, queries, gt = load_dataset(cfg.dataset.name, dataset_path) - return vectors, queries[: cfg.experiment.nq], gt[: cfg.experiment.nq] - - -# Index Management -def build_or_load_index(cfg, num_workers): - index_dir = get_original_cwd() / to_path(cfg.paths.index_dir) - index_path = index_dir / f"{cfg.dataset.name}_dynamic_ivf{cfg.index.nc}.index" - if not index_path.exists() or cfg.overwrite.index: - # Build and save index - vectors, _, _ = get_dataset(cfg) - build_index = QuakeIndex() - build_params = IndexBuildParams() - build_params.nlist = cfg.index.nc - build_params.metric = cfg.index.metric - build_index.build(vectors, torch.arange(vectors.size(0)), build_params) - build_index.save(str(index_path.absolute())) - log.info(f"Index built and saved to {index_path}") - - # Load existing index - index = QuakeIndex() - index.load(str(index_path.absolute()), num_workers) - - log.info(f"Index loaded from {index_path} with {num_workers} workers") - - return index - - -# Experiment Execution -def run_single_experiment(args): - method, recall_target, recompute_ratio, use_precompute, cfg, action, n_workers = args - index = build_or_load_index(cfg, n_workers) - _, queries, gt = get_dataset(cfg) - k = cfg.experiment.k - - result_dir = get_original_cwd() / cfg.paths.results_dir / method - result_dir.mkdir(parents=True, exist_ok=True) - - print(f"Running experiment for {method} at recall {recall_target} with action {action}") - - if method == "Oracle": - result_path = result_dir / f"recall_{recall_target:.2f}.csv" - - data_df = run_experiment_for_configuration( - index=index, - queries=queries, - gt=gt, - k=k, - recall_target=recall_target, - oracle=True, - ) - # Save per-query data - data_df.to_csv(result_path, index=False) - log.info(f"Results saved to {result_path}") - elif method == "FixedNProbe": - result_path = result_dir / f"recall_{recall_target:.2f}.csv" - if result_path.exists() and not cfg.overwrite.results: - log.info(f"Results for {method} at recall {recall_target} already exist. Skipping.") - return - - data_df = run_experiment_for_configuration( - index=index, - queries=queries, - gt=gt, - k=k, - recall_target=recall_target, - fixed_nprobe=True, - ) - # Save per-query data - data_df.to_csv(result_path, index=False) - log.info(f"Results saved to {result_path}") - elif method.startswith("APS"): - result_path = result_dir / f"recall_{recall_target:.2f}.csv" - if result_path.exists() and not cfg.overwrite.results: - log.info(f"Results for {method} at recall {recall_target} already exist. Skipping.") - return - - data_df = run_experiment_for_configuration( - index=index, - queries=queries, - gt=gt, - k=k, - recall_target=recall_target, - recompute_ratio=recompute_ratio, - use_precompute=use_precompute, - ) - # Save per-query data - data_df.to_csv(result_path, index=False) - log.info(f"Results saved to {result_path}") - else: - raise ValueError(f"Unknown method: {method}") - - -# Results Management and Plotting -def collect_and_plot_results(cfg): - methods = cfg.methods - recall_targets = cfg.experiment.recall_targets - all_data = [] - - for method in methods: - for recall_target in recall_targets: - result_dir = cfg.paths.results_dir / method - result_path = result_dir / f"recall_{recall_target:.2f}.csv" - if not result_path.exists(): - log.warning(f"Result file {result_path} does not exist. Skipping.") - continue - data_df = pd.read_csv(result_path) - data_df["Recall Target"] = recall_target - - complete_name = method - data_df["Method"] = complete_name - all_data.append(data_df) - - if not all_data: - log.error("No data available for plotting.") - return - - df_plot = pd.concat(all_data, ignore_index=True) - - # Clean data - df_plot = df_plot.dropna(subset=["total_time_ms", "nprobe", "recall"]) - df_plot = df_plot[(df_plot["total_time_ms"] >= 0) & (df_plot["nprobe"] >= 0) & (df_plot["recall"] >= 0)] - - df_plot["Query Time (ms)"] = df_plot["total_time_ms"] - df_plot["Recall"] = df_plot["recall"] - - # Compute stats - grouped = df_plot.groupby(["Recall Target", "Method"]) - stats = grouped.agg( - { - "Query Time (ms)": ["min", "mean", "max"], - "nprobe": ["min", "mean", "max"], - "Recall": ["min", "mean", "max"], - "buffer_init_time_ms": ["min", "mean", "max"], - "job_enqueue_time_ms": ["min", "mean", "max"], - "boundary_distance_time_ms": ["min", "mean", "max"], - "job_wait_time_ms": ["min", "mean", "max"], - "result_aggregate_time_ms": ["min", "mean", "max"], - } - ).reset_index() - stats.columns = [" ".join(col).strip() for col in stats.columns.values] - - # Compute 'other_time_ms' and include in stats - df_plot["other_time_ms"] = df_plot["total_time_ms"] - ( - df_plot["buffer_init_time_ms"] - + df_plot["job_enqueue_time_ms"] - + df_plot["boundary_distance_time_ms"] - + df_plot["job_wait_time_ms"] - + df_plot["result_aggregate_time_ms"] - ) - df_plot["other_time_ms"] = df_plot["other_time_ms"].apply(lambda x: x if x >= 0 else 0) - other_time_stats = grouped["other_time_ms"].agg(["min", "mean", "max"]).reset_index() - other_time_stats.columns = [ - "Recall Target", - "Method", - "other_time_ms min", - "other_time_ms mean", - "other_time_ms max", - ] - stats = pd.merge(stats, other_time_stats, on=["Recall Target", "Method"]) - - # Compute p99 for 'Query Time (ms)' and 'Recall' - p95_latency = grouped["Query Time (ms)"].quantile(0.95).reset_index() - p95_recall = grouped["Recall"].quantile(0.05).reset_index() - p95_latency.rename(columns={"Query Time (ms)": "Query Time (ms) p95"}, inplace=True) - p95_recall.rename(columns={"Recall": "Recall p95"}, inplace=True) - stats = stats.merge(p95_latency, on=["Recall Target", "Method"]) - stats = stats.merge(p95_recall, on=["Recall Target", "Method"]) - - # Save this as intermediate results - stats_save_path = cfg.paths.plot_dir / "all_intermediate_stats.csv" - stats.to_csv(stats_save_path, index=False) - - # Plotting - plot_recall_only(df_plot, stats, cfg.paths.plot_dir) - plot_mean_line_plots(df_plot, stats, cfg.paths.plot_dir) - plot_query_overheads(stats, cfg.paths.plot_dir) - - -palette = {"Oracle": "C0", "APS": "C1"} - - -def plot_recall_only(df_plot, stats, plot_dir): - sns.set_style("whitegrid") - sns.set_context("talk", font_scale=0.8) - plt.rcParams["font.weight"] = "bold" - plt.rcParams["axes.labelweight"] = "bold" - - fig, ax = plt.subplots(figsize=(6, 4)) - stats["Method"] = stats["Method"].replace("Adaptive nprobe", "APS") - - # Shared x-axis range - x_min = stats["Recall Target"].min() - x_max = stats["Recall Target"].max() - - # Generate detailed x-axis ticks - x_ticks = [0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0] - - ax.set_title("Sift1M: Measured Recall vs. Recall Target", fontsize=14, fontweight="bold") - - for method in stats["Method"].unique(): - method_stats = stats[stats["Method"] == method].sort_values("Recall Target") - ax.plot( - method_stats["Recall Target"], - method_stats["Recall mean"], - label=method, - color=palette[method], - linewidth=4, - marker="o", - markersize=10, - ) - - # plot p95 recall - # p95_recall = method_stats['Recall p95'] - # ax.plot(method_stats['Recall Target'], p95_recall, color=palette[method], linestyle='--', linewidth=8) - - x_vals = np.linspace(x_min, x_max, 100) - ax.plot(x_vals, x_vals, color="black", linestyle="--", linewidth=4, label="Recall Target") - - ax.set_ylabel("Recall", fontsize=16, fontweight="bold") - ax.tick_params(axis="both", which="major", labelsize=16) - ax.set_yticks([0.7, 0.8, 0.9, 1.0]) # Custom y-axis ticks - ax.set_xticks(x_ticks) - ax.legend(fontsize=8, prop={"weight": "bold"}, loc="lower right") # Legend moved to top-left - ax.grid(True) - - plt.tight_layout() - plot_path = plot_dir / "recall_plot.pdf" - plt.savefig(plot_path, bbox_inches="tight") - log.info(f"Plot saved to {plot_path}") - plt.show() - - -# Plotting Functions -def plot_mean_line_plots(df_plot, stats, plot_dir): - sns.set_style("whitegrid") - sns.set_context("talk", font_scale=0.8) - plt.rcParams["font.weight"] = "bold" - plt.rcParams["axes.labelweight"] = "bold" - - # Create a vertically stacked layout with shared x-axis - fig, axes = plt.subplots(3, 1, figsize=(8, 6), sharex=True) # Stacked plots with shared x-axis - - stats["Method"] = stats["Method"].replace("Adaptive nprobe", "APS") - - # Shared x-axis range - x_min = stats["Recall Target"].min() - x_max = stats["Recall Target"].max() - - # Generate detailed x-axis ticks - x_ticks = [0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0] - - axes[0].set_title("Sift1M: Recall, Query Latency, and Nprobe vs. Recall Target", fontsize=20, fontweight="bold") - - # Plot 1: Recall - for method in stats["Method"].unique(): - method_stats = stats[stats["Method"] == method].sort_values("Recall Target") - axes[0].plot( - method_stats["Recall Target"], - method_stats["Recall mean"], - label=method, - color=palette[method], - linewidth=8, - marker="o", - markersize=10, - ) - # plot p95 recall - # p95_recall = method_stats['Recall p95'] - # axes[0].plot(method_stats['Recall Target'], p95_recall, color=palette[method], linestyle='--', linewidth=8) - - # Diagonal reference line - x_vals = np.linspace(x_min, x_max, 100) - axes[0].plot(x_vals, x_vals, color="black", linestyle="--", linewidth=8, label="Recall Target") - - axes[0].set_ylabel("Recall", fontsize=16, fontweight="bold") - axes[0].tick_params(axis="both", which="major", labelsize=16) - axes[0].set_yticks([0.7, 0.8, 0.9, 1.0]) # Custom y-axis ticks - axes[0].set_xticks(x_ticks) - axes[0].legend(fontsize=8, prop={"weight": "bold"}, loc="lower right") # Legend moved to top-left - axes[0].grid(True) - - # Plot 2: Query Time - for method in stats["Method"].unique(): - method_stats = stats[stats["Method"] == method].sort_values("Recall Target") - axes[1].plot( - method_stats["Recall Target"], - method_stats["Query Time (ms) mean"], - label=method, - color=palette[method], - linewidth=8, - marker="o", - markersize=10, - ) - - # plot p95 query time - p95_query_time = method_stats["Query Time (ms) p95"] - axes[1].plot(method_stats["Recall Target"], p95_query_time, color=palette[method], linestyle="--", linewidth=8) - - # axes[1].set_ylabel('Query Time (ms)', fontsize=20, fontweight='bold') - axes[1].set_yscale("log") - axes[1].tick_params(axis="both", which="major", labelsize=16) - axes[1].set_yticks([0.2, 0.4, 0.8, 1.6, 3.2]) # Custom y-axis ticks - axes[1].set_yticklabels(["0.2ms", "0.4ms", "0.8ms", "1.6ms", "3.2ms"]) # Add units to tick labels - axes[1].set_xticks(x_ticks) - # axes[1].legend(fontsize=16, prop={'weight': 'bold'}, loc='upper left') # Legend moved to top-left - axes[1].grid(True) - # - # # Plot 3: nprobe - for method in stats["Method"].unique(): - method_stats = stats[stats["Method"] == method].sort_values("Recall Target") - axes[2].plot( - method_stats["Recall Target"], - method_stats["nprobe mean"], - label=method, - color=palette[method], - linewidth=8, - marker="o", - markersize=10, - ) - - axes[2].set_xlabel("Recall Target", fontsize=16, fontweight="bold") # Shared x-axis - axes[2].set_ylabel("nprobe", fontsize=16, fontweight="bold") - axes[2].set_yscale("log") - axes[2].tick_params(axis="both", which="major", labelsize=16) - axes[2].set_yticks([4, 8, 16, 32, 64]) # Custom y-axis ticks - axes[2].set_yticklabels(["4", "8", "16", "32", "64"]) # Add units to tick labels - axes[2].set_xticks(x_ticks) - # axes[2].legend(fontsize=16, prop={'weight': 'bold'}, loc='upper left') # Legend moved to top-left - axes[2].grid(True) - - plt.tight_layout() - plot_path = plot_dir / "mean_line_plots_stacked.pdf" - plt.savefig(plot_path, bbox_inches="tight") - log.info(f"Plot saved to {plot_path}") - plt.show() - - -def plot_query_overheads(stats, plot_dir): - """ - Plot stacked bar charts showing the mean time taken by each component for each method and recall target, - including an 'Other' category representing the remaining time. - """ - import matplotlib.pyplot as plt - import numpy as np - from matplotlib.patches import Patch - - # Define the components and their labels - components = [ - "buffer_init_time_ms", - "job_enqueue_time_ms", - "boundary_distance_time_ms", - "job_wait_time_ms", - "result_aggregate_time_ms", - "other_time_ms", # Added 'Other' category - ] - component_labels = [ - "Buffer Init", - "Job Enqueue", - "Boundary Distance", - "Job Wait", - "Result Aggregate", - "Other", # Label for 'Other' - ] - # Blue, Orange, Green, Red, Purple, Gray] - component_colors = ["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#8c564b", "#7f7f7f"] - - # remap the method names: Adaptive nprobe -> Adaptive Partition Scanning - # stats[methods == 'Adaptive nprobe'] = 'Adaptive Partition Scanning' - stats["Method"] = stats["Method"].replace("Adaptive nprobe", "APS") - - # Define methods and their hatching patterns - methods = stats["Method"].unique() - - method_hatches = {method: "" if method == "Oracle" else "//" for method in methods} - - # Prepare data for plotting - recall_targets = sorted(stats["Recall Target"].unique()) - - # Initialize plotting - fig, ax = plt.subplots(figsize=(14, 8)) - - bar_width = 0.1 - opacity = 0.8 - - n_groups = len(recall_targets) - index = np.arange(n_groups) - - # Set positions for each method's bars - # method_offsets = np.linspace(-bar_width/2, bar_width/2, len(methods)) - positions = {} - positions["Oracle"] = index - 3 * bar_width / 2 - positions["APS"] = index - bar_width / 2 - positions["APS-R"] = index + bar_width / 2 - positions["APS-RP"] = index + 3 * bar_width / 2 - positions["FixedNProbe"] = index + 5 * bar_width / 2 - - # Initialize cumulative bottoms for stacking - cumulative_bottoms = {method: np.zeros(n_groups) for method in methods} - - # Plot each component - for comp, comp_label, comp_color in zip(components, component_labels, component_colors): - for method in methods: - print(f"Plotting {comp} for {method}") - - comp_means = [] - for rt in recall_targets: - row = stats[(stats["Recall Target"] == rt) & (stats["Method"] == method)] - if not row.empty: - comp_time = row[f"{comp} mean"].values[0] - else: - comp_time = 0 - comp_means.append(comp_time) - print(f"Component means: {comp_means}") - - method_lookup = method.split("+")[0].strip() - pos = positions[method_lookup] - ax.bar( - pos, - comp_means, - bar_width, - bottom=cumulative_bottoms[method], - color=comp_color, - alpha=opacity, - hatch=method_hatches[method], - edgecolor="black", - label=comp_label if (method == methods[0]) else "", - ) - cumulative_bottoms[method] += comp_means - - # Set x-axis labels and ticks - ax.set_xlabel("Recall Target", fontsize=14, weight="bold") - ax.set_ylabel("Time (ms)", fontsize=14, weight="bold") - ax.set_title("Query Overheads by Method and Recall Target", fontsize=16, weight="bold") - ax.set_xticks(index) - ax.set_xticklabels([f"{rt:.2f}" for rt in recall_targets], fontsize=12) - ax.tick_params(axis="y", labelsize=12) - - # Create custom legend for components - component_handles = [Patch(facecolor=color, edgecolor="black") for color in component_colors] - component_legend = ax.legend( - component_handles, component_labels, title="Components", title_fontsize=14, fontsize=12, loc="upper left" - ) - - # Create custom legend for methods - method_handles = [ - Patch(facecolor="white", edgecolor="black", hatch=method_hatches[method], label=method) for method in methods - ] - ax.legend(method_handles, methods, title="Method", title_fontsize=14, fontsize=12, loc="upper right") - - # Add the component legend back to the plot - ax.add_artist(component_legend) - - # Add grid for better readability - ax.yaxis.grid(True, linestyle="--", which="major", color="grey", alpha=0.5) - - # set ylimit - ax.set_ylim(0, 2.5) - - plt.tight_layout() - plot_path = plot_dir / "query_overheads.png" - plt.savefig(plot_path) - log.info(f"Overhead plot saved to {plot_path}") - plt.show() - - -# Helper Functions -def run_experiment_for_configuration( - index, queries, gt, k, recall_target, oracle=False, recompute_ratio=0.05, use_precompute=True, fixed_nprobe=False -): - - timing_infos = [] - - if oracle: - nprobes = [] - for i, query in enumerate(queries): - max_nprobe = index.nlist() - min_nprobe = 1 - best_nprobe = max_nprobe - - # find minimum nprobe that achieves recall_target - while min_nprobe <= max_nprobe: - curr_nprobe = (min_nprobe + max_nprobe) // 2 - - search_params = SearchParams() - search_params.nprobe = curr_nprobe - search_params.k = k - search_params.recall_target = -1 - - search_result = index.search(query.unsqueeze(0), search_params) - ids, dist, timing_info = search_result.ids, search_result.distances, search_result.timing_info - recall = compute_recall(ids, gt[i].unsqueeze(0), k) - - if float(recall) >= recall_target: - max_nprobe = curr_nprobe - 1 - best_nprobe = curr_nprobe - else: - min_nprobe = curr_nprobe + 1 - - nprobes.append(best_nprobe) - - # Second run to execute queries - all_ids = [] - all_dists = [] - - for query, nprobe in zip(queries, nprobes): - - search_params = SearchParams() - search_params.nprobe = nprobe - search_params.k = k - search_params.recall_target = -1 - - search_result = index.search(query.unsqueeze(0), search_params) - - ids, dist, timing_info = search_result.ids, search_result.distances, search_result.timing_info - all_ids.append(ids) - all_dists.append(dist) - timing_infos.append(timing_info) - recalls = compute_recall(torch.cat(all_ids, dim=0), gt, k) - elif fixed_nprobe: - print("FIXED NPROBE") - # compute nprobe for recall target for all queries, rather than per-query - - # first use binary search to find the nprobe that achieves the recall target - max_nprobe = index.nlist() - min_nprobe = 1 - best_nprobe = max_nprobe - - while min_nprobe <= max_nprobe: - curr_nprobe = (min_nprobe + max_nprobe) // 2 - all_ids = [] - all_dists = [] - - search_params = SearchParams() - search_params.nprobe = curr_nprobe - search_params.k = k - search_params.recall_target = -1 - - for i, query in enumerate(queries): - search_result = index.search(query.unsqueeze(0), search_params) - ids, dist, timing_info = search_result.ids, search_result.distances, search_result.timing_info - all_ids.append(ids) - all_dists.append(dist) - recalls = compute_recall(torch.cat(all_ids, dim=0), gt, k) - avg_recall = recalls.mean().item() - if avg_recall >= recall_target: - max_nprobe = curr_nprobe - 1 - best_nprobe = curr_nprobe - else: - min_nprobe = curr_nprobe + 1 - - # Second run to execute queries - all_ids = [] - all_dists = [] - - search_params = SearchParams() - search_params.nprobe = best_nprobe - search_params.k = k - search_params.recall_target = -1 - - for query in queries: - search_result = index.search(query.unsqueeze(0), search_params) - ids, dist, timing_info = search_result.ids, search_result.distances, search_result.timing_info - all_ids.append(ids) - all_dists.append(dist) - timing_infos.append(timing_info) - recalls = compute_recall(torch.cat(all_ids, dim=0), gt, k) - else: - all_ids = [] - all_dists = [] - - search_params = SearchParams() - search_params.nprobe = -1 - search_params.k = k - search_params.initial_search_fraction = 0.1 - search_params.recall_target = recall_target - search_params.recompute_threshold = 0.01 - search_params.use_precomputed = use_precompute - search_params.num_threads = 1 - - # debug print search params - print( - f"Search Params: {search_params.nprobe}, {search_params.k}, {search_params.recall_target}, " - f"{search_params.recompute_threshold}, {search_params.use_precomputed}" - ) - - for query in queries: - search_result = index.search(query.unsqueeze(0), search_params) - ids, dist, timing_info = search_result.ids, search_result.distances, search_result.timing_info - all_ids.append(ids) - all_dists.append(dist) - timing_infos.append(timing_info) - - ids = torch.cat(all_ids, dim=0) - # dists = torch.cat(all_dists, dim=0) - recalls = compute_recall(ids, gt, k) - - per_query_data = [] - for i, timing_info in enumerate(timing_infos): - per_query_nprobe = timing_info.partitions_scanned - buffer_init_time_ms = timing_info.buffer_init_time_ns / 1e6 - job_enqueue_time_ms = timing_info.job_enqueue_time_ns / 1e6 - boundary_distance_time_ms = timing_info.boundary_distance_time_ns / 1e6 - job_wait_time_ms = timing_info.job_wait_time_ns / 1e6 - result_aggregate_time_ms = timing_info.result_aggregate_time_ns / 1e6 - total_time_ms = timing_info.total_time_ns / 1e6 - - per_query_recall = float(recalls[i]) - per_query_data.append( - { - "nprobe": per_query_nprobe, - "recall": per_query_recall, - "buffer_init_time_ms": buffer_init_time_ms, - "job_enqueue_time_ms": job_enqueue_time_ms, - "boundary_distance_time_ms": boundary_distance_time_ms, - "job_wait_time_ms": job_wait_time_ms, - "result_aggregate_time_ms": result_aggregate_time_ms, - "total_time_ms": total_time_ms, - } - ) - - per_query_data_df = pd.DataFrame(per_query_data) - # per_query_data_df = per_query_data_df[1:] # Skip the first query - return per_query_data_df - - -def get_nprobe_for_recall_target(recall_target, nlist): - nprobe = int(nlist * recall_target / 2) - nprobe = max(1, min(nprobe, nlist)) - return nprobe - - -@hydra.main(config_path="configs", config_name="sift1m") -def main(cfg: DictConfig): - # Set up directories - base_dir = get_original_cwd() / Path(cfg.base_dir) - - cfg.paths.index_dir = Path(cfg.paths.index_dir) - cfg.paths.index_dir.mkdir(parents=True, exist_ok=True) - cfg.paths.results_dir = base_dir / cfg.paths.results_dir - cfg.paths.results_dir.mkdir(parents=True, exist_ok=True) - cfg.paths.plot_dir = base_dir / cfg.paths.plot_dir - cfg.paths.plot_dir.mkdir(parents=True, exist_ok=True) - - if cfg.mode == "run": - # Prepare experiment parameters - methods = cfg.methods - recall_targets = cfg.experiment.recall_targets - n_workers = cfg.experiment.n_workers - experiment_args = [] - for method in methods: - for recall_target in recall_targets: - if method == "Oracle": - experiment_args.append((method, recall_target, 0.05, True, cfg, "execute_queries", n_workers)) - elif method == "APS": - experiment_args.append((method, recall_target, 0.0, True, cfg, "execute_queries", n_workers)) - elif method == "APS-R": - experiment_args.append((method, recall_target, -1, True, cfg, "execute_queries", n_workers)) - elif method == "APS-RP": - experiment_args.append((method, recall_target, -1, False, cfg, "execute_queries", n_workers)) - elif method == "FixedNProbe": - experiment_args.append((method, recall_target, -1, True, cfg, "execute_queries", n_workers)) - - # Run experiments - for args in experiment_args: - run_single_experiment(args) - - elif cfg.mode == "plot": - collect_and_plot_results(cfg) - - -if __name__ == "__main__": - main() diff --git a/test/experiments/adaptive_partition_scanning/run.py b/test/experiments/adaptive_partition_scanning/run.py new file mode 100644 index 00000000..dc5a74e5 --- /dev/null +++ b/test/experiments/adaptive_partition_scanning/run.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +""" +Adaptive‐Partition‐Scanning Recall‐Target Runner (Simplified) +Supports: Oracle, FixedNProbe, APS +""" +import logging +from pathlib import Path +import numpy as np +import torch +import pandas as pd + +from test.experiments.osdi2025 import experiment_utils as common_utils +from quake import SearchParams # Keep direct import for clarity if used extensively + +logger = logging.getLogger(__name__) +logging.basicConfig(level=logging.INFO, format="%(asctime)s | %(levelname)s | %(message)s") + +def run_experiment(cfg_path: str, output_dir_str: str): + cfg = common_utils.load_config(cfg_path) + out_dir = Path(output_dir_str) + + dataset_cfg = cfg["dataset"] + exp_cfg = cfg["experiment"] + idx_build_cfg = cfg["index"] + paths_cfg = cfg["paths"] + + vecs, queries, gt = common_utils.load_data( + dataset_cfg["name"], dataset_cfg.get("path", ""), exp_cfg["nq"] + ) + + idx_path = Path(paths_cfg["index_dir"]) / f"{dataset_cfg['name']}_ivf{idx_build_cfg['nlist']}.index" + quake_idx = common_utils.prepare_quake_index( + vecs, + {"nlist": idx_build_cfg["nlist"], "metric": idx_build_cfg["metric"], "num_workers": exp_cfg["n_workers"]}, + idx_path, + force_rebuild=cfg["overwrite"].get("index", False) + ) + logger.info(f"Index ready (workers={exp_cfg['n_workers']})") + + records = [] + k = exp_cfg["k"] + max_nlist_val = quake_idx.nlist() + + for method in cfg["methods"]: + for rt in exp_cfg["recall_targets"]: + logger.info(f"Method={method} RecallTarget={rt}") + per_query_stats = [] # (nprobe, recall, time_ms) + + if method == "Oracle": + for i, q_vec in enumerate(queries): + lo, hi, best_np = 1, max_nlist_val, max_nlist_val + while lo <= hi: + mid = (lo + hi) // 2 + sp = common_utils.create_search_params(nprobe=mid, k=k, recall_target=-1) + _, rec, _ = common_utils.run_search_trial(quake_idx, q_vec, gt[i], k, sp) + if rec >= rt: + best_np, hi = mid, mid - 1 + else: + lo = mid + 1 + sp_final = common_utils.create_search_params(nprobe=best_np, k=k, recall_target=-1) + _, final_rec, final_time_ms = common_utils.run_search_trial(quake_idx, q_vec, gt[i], k, sp_final) + per_query_stats.append((best_np, final_rec, final_time_ms)) + + elif method == "FixedNProbe": + lo, hi, best_global_np = 1, max_nlist_val, max_nlist_val + while lo <= hi: + mid = (lo + hi) // 2 + sp = common_utils.create_search_params(nprobe=mid, k=k, recall_target=-1) + current_ids = [] + for q_vec_fixed in queries: # Use all queries for tuning this + res_ids = quake_idx.search(q_vec_fixed.unsqueeze(0), sp).ids + current_ids.append(res_ids) + avg_rec = common_utils.quake_compute_recall(torch.cat(current_ids,0), gt, k).mean().item() + if avg_rec >= rt: + best_global_np, hi = mid, mid - 1 + else: + lo = mid + 1 + + sp_final = common_utils.create_search_params(nprobe=best_global_np, k=k, recall_target=-1) + for i, q_vec in enumerate(queries): + _, final_rec, final_time_ms = common_utils.run_search_trial(quake_idx, q_vec, gt[i], k, sp_final) + per_query_stats.append((best_global_np, final_rec, final_time_ms)) + + elif method == "APS": + for i, q_vec in enumerate(queries): + sp = common_utils.create_search_params( + nprobe=-1, k=k, recall_target=rt, + recompute_threshold=exp_cfg["recompute_ratio"], + use_precomputed=exp_cfg["use_precompute"], + initial_search_fraction=exp_cfg["initial_search_fraction"] + ) + nprobe_scan, final_rec, final_time_ms = common_utils.run_search_trial(quake_idx, q_vec, gt[i], k, sp) + logger.debug(f"APS recall: {final_rec:.4f} (target={rt}), nprobe_scanned={nprobe_scan}") + per_query_stats.append((nprobe_scan, final_rec, final_time_ms)) + else: + raise ValueError(f"Unknown method: {method}") + + arr = np.array(per_query_stats, dtype=float) + records.append({ + "Method": method, "RecallTarget": rt, + "mean_nprobe": arr[:,0].mean(), "std_nprobe": arr[:,0].std(), + "mean_recall": arr[:,1].mean(), "std_recall": arr[:,1].std(), + "mean_time_ms": arr[:,2].mean(), "std_time_ms": arr[:,2].std(), + }) + + results_df = pd.DataFrame(records) + common_utils.save_results_csv(results_df, out_dir / "aps_recall_targets_summary.csv") + + plot_path = out_dir / "aps_recall_vs_metrics.png" + common_utils.plot_recall_performance( + results_df, + x_metric="RecallTarget", + y_metrics=["mean_time_ms", "mean_recall", "mean_nprobe"], + y_labels=["Mean Query Time (ms)", "Mean Recall Achieved", "Mean NProbe"], + y_scales=["linear", "linear", "log"], + plot_title_prefix=f"{dataset_cfg['name']} APS Experiment", + output_path=plot_path, + recall_targets_for_line=exp_cfg["recall_targets"] + ) \ No newline at end of file diff --git a/test/experiments/osdi2025/README.md b/test/experiments/osdi2025/README.md index 1df6e158..465429df 100644 --- a/test/experiments/osdi2025/README.md +++ b/test/experiments/osdi2025/README.md @@ -1,57 +1,131 @@ -# OSDI 2025 Artifact -This directory contains the experiments for Quake's OSDI 2025 submission. +# Quake OSDI 2025 Artifact Evaluation +This artifact provides the experimental setup for the Quake vector search system, as described in the OSDI 2025 submission. +## Structure +The experiments are organized as follows: -### Installation + + +```plaintext +./test/experiments/osdi2025/ +├── common/ \# Shared utilities for experiments +│ └── experiment\_utils.py +├── experiment\_runner.py \# Main script to run any experiment +├── README.md \# This file +├── \/ \# Directory for each specific experiment +│ ├── configs/ \# YAML configuration files for the experiment +│ │ └── \.yaml +│ └── run.py \# Python script to execute the experiment logic +└── ... \# Other experiment directories +``` + +Each experiment directory (e.g., `aps_recall_targets`, `early_termination`) contains its specific logic in `run.py` and configurations in its `configs/` subdirectory. The `common/experiment_utils.py` module provides shared functionality for loading data, configurations, preparing indexes, and plotting, aiming to simplify individual experiment scripts. + +## Installation **Requirements:** - Python 3.9 or later -- Linux (Tested on Ubuntu 22.04) +- Linux (Tested on Ubuntu 22.04) +- Conda package manager -1. **Clone the Repository:** +1. **Clone the Repository:** + ```bash + git clone [https://github.com/marius-team/quake.git](https://github.com/marius-team/quake.git) + cd quake + git submodule update --init --recursive + ``` -```bash -git clone https://github.com/marius-team/quake.git -cd quake -git submodule update --init --recursive -``` +2. **Set Up the Conda Environment:** + Create and activate the environment using the provided YAML file: + ```bash + conda env create -f environments/ubuntu-latest/conda.yaml + conda activate quake-env + ``` -2. **Set Up the Conda Environment:** +3. **Install Quake:** + Ensure you are in the `quake` repository root. + ```bash + pip install --no-use-pep517 . + ``` - Create and activate the environment using the provided YAML file: +## Running Experiments -```bash -conda env create -f environments/ubuntu-latest/conda.yaml -conda activate quake-env -``` +All experiments are launched using the central `experiment_runner.py` script located in the `test/experiments/osdi2025/` directory. -3. **Install Quake:** +**General Command Structure:** +Make sure to run all commands from the **repository root directory (`quake/`)**. ```bash -pip install --no-use-pep517 . -``` +OMP_NUM_THREADS=1 python3 -m test.experiments.osdi2025.experiment_runner \ + --experiment \ + --config \ + --output-dir # Optional +```` -### Kick the tires +**Explanation:** -To make sure Quake and the experiment environment are set up correctly, you can run the following commands: +* `OMP_NUM_THREADS=1`: Recommended for consistent performance measurement as OMP interferes with our custom parallelism. Adjust as needed based on specific experiment guidelines if any. +* `--experiment `: Specifies which experiment to run (e.g., `kick_the_tires`, `aps_recall_targets`). +* `--config `: Specifies the configuration file from `test/experiments/osdi2025//configs/`. For `sift1m.yaml`, use `sift1m`. +* `--output-dir ` (Optional): If provided, results (CSVs, plots) will be saved here. Default is `test/experiments/osdi2025//results//`. -**Make sure to run all commands in the repository root directory** +### Kick the Tires (Quick Verification) -1. **Run the quickstart example:** +1. **Run the Quickstart Example:** + Tests Quake's core operations. -This is a basic test that the main operations of Quake are working. + ```bash + python3 examples/quickstart.py + ``` -```bash -python3 examples/quickstart.py -``` +2. **Run the `kick_the_tires` Benchmark:** + Tests basic system functionality and performance with a dynamic workload. + + ```bash + OMP_NUM_THREADS=1 python3 -m test.experiments.osdi2025.experiment_runner \ + --experiment kick_the_tires \ + --config sift1m + ``` + + Outputs will be in `test/experiments/osdi2025/kick_the_tires/results/sift1m/`. + +## Experiment Summaries and Outputs + +The following table summarizes each experiment and its primary outputs. Output files are typically generated within the experiment's specific output directory (refer to the `--output-dir` option or its default value). + +| Experiment Name | Description | Key Outputs (Illustrative Filenames) | +|------------------------|--------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `aps_recall_targets` | Evaluates Quake's Adaptive Partition Scanning (APS) against baselines for various recall targets. | `aps_recall_targets_summary.csv`, `aps_recall_vs_metrics.png` | +| `early_termination` | Compares APS with early termination strategies like LAET and Auncel. | `aps_et_results_.csv`, `latency_plot_.png`, Markdown table (printed to console) | +| `kick_the_tires` | Basic dynamic workload stress test focusing on latency, recall, and system state over operations. | Per-index `results.csv` (e.g., `Quake10000/results.csv`), main `unified_plot.png` | +| `maintenance_ablation` | Evaluates the impact of Quake's maintenance operations under a dynamic workload, extending `kick_the_tires`. | Per-index `results.csv`, main `summary_table.csv`, `summary_table.md`, `unified_plot.png`, `time_breakdown.png` | +| `measure_skew_and_perf` | Measures data skew characteristics and their performance impact on a dataset. | Script-specific CSVs/plots detailing skew metrics and performance correlations. | +| `multi_level` | Benchmarks Quake with multiple index levels against single-level configurations, varying `nprobe`. | Per-index `results.csv` (e.g., `Quake5000/results.csv`), main `recall_vs_qps.png` | +| `numa_multi_query` | Tests Quake's multi-query batch performance under different NUMA and worker configurations. | Per-index `results.csv`, main `.csv` (aggregate), `_batch_latency.png`, `_batch_recall.png` | +| `numa_single_query` | Tests Quake's single-query performance under different NUMA and worker configurations. | Per-index `results.csv`, main `.csv` (aggregate), `_child_latency.png`, `_recall.png` | +| `vary_levels` | Evaluates Quake with varying numbers of centroids in parent index levels. | Per-level `results.csv` (e.g., `L/results.csv`), main `recall_vs_qps.png` | +| `workload_comparison` | Compares Quake's performance across different types of synthetic or real-world workloads. | Script-specific CSVs/plots comparing workloads. | -2. **Run the Benchmark:** +**To run any of these, replace `` and `` in the general command structure.** For example, to run the `aps_recall_targets` experiment with its `sift1m` configuration: ```bash -OMP_NUM_THREADS=1 python3 -m test.experiments.osdi2025.experiment_runner --experiment kick_the_tires --config sift1m +OMP_NUM_THREADS=1 python3 -m test.experiments.osdi2025.experiment_runner \ + --experiment aps_recall_targets \ + --config sift1m ``` ---- \ No newline at end of file +Results, including CSV files and plots as detailed above, will be saved to the specified (or default) output directory. Check the terminal output for the exact location. + +## Notes + +* **Dataset Downloads:** The `quake.datasets.ann_datasets.load_dataset` utility will attempt to download datasets if they are not found locally (typically in a `data/` directory in the repository root). An internet connection is required for initial downloads. +* **Disk Space:** Some datasets (e.g., SIFT1B, MSTuring100M) are large and require significant disk space. +* **Execution Time:** Full experimental runs can be time-consuming, ranging from minutes for small configurations to many hours for large-scale evaluations. The `kick_the_tires` experiment with `sift1m` is designed for relatively quick verification. + + + +``` +``` \ No newline at end of file diff --git a/test/experiments/osdi2025/aps_recall_targets/run.py b/test/experiments/osdi2025/aps_recall_targets/run.py index 1e9510fe..499dfd8a 100644 --- a/test/experiments/osdi2025/aps_recall_targets/run.py +++ b/test/experiments/osdi2025/aps_recall_targets/run.py @@ -1,182 +1,129 @@ #!/usr/bin/env python3 """ -Adaptive‐Partition‐Scanning Recall‐Target Runner -Supports three methods: Oracle, FixedNProbe, APS +Adaptive‐Partition‐Scanning Recall‐Target Runner (Simplified) +Supports: Oracle, FixedNProbe, APS """ - -import time -import yaml import logging from pathlib import Path - +import numpy as np import torch import pandas as pd -import numpy as np -import matplotlib.pyplot as plt -from quake import QuakeIndex, IndexBuildParams, SearchParams -from quake.datasets.ann_datasets import load_dataset -from quake.utils import compute_recall +from test.experiments.osdi2025 import experiment_utils as common_utils +from quake import SearchParams # Keep direct import for clarity if used extensively logger = logging.getLogger(__name__) +logging.basicConfig(level=logging.INFO, format="%(asctime)s | %(levelname)s | %(message)s") + +def run_experiment(cfg_path: str, output_dir_str: str): + cfg = common_utils.load_config(cfg_path) + out_dir = Path(output_dir_str) + + dataset_cfg = cfg["dataset"] + exp_cfg = cfg["experiment"] + idx_build_cfg = cfg["index"] + paths_cfg = cfg["paths"] + + vecs, queries, gt = common_utils.load_data( + dataset_cfg["name"], dataset_cfg.get("path", ""), exp_cfg["nq"] + ) + + idx_path = Path(paths_cfg["index_dir"]) / f"{dataset_cfg['name']}_ivf{idx_build_cfg['nlist']}.index" + quake_idx = common_utils.prepare_quake_index( + vecs, + {"nlist": idx_build_cfg["nlist"], "metric": idx_build_cfg["metric"], "num_workers": exp_cfg["n_workers"]}, + idx_path, + force_rebuild=cfg["overwrite"].get("index", False) + ) + logger.info(f"Index ready (workers={exp_cfg['n_workers']})") -def run_experiment(cfg_path: str, output_dir: str): - # 1) Load config + setup output dir - cfg = yaml.safe_load(Path(cfg_path).read_text()) - out = Path(output_dir); out.mkdir(parents=True, exist_ok=True) - - # 2) Load data - data_dir = cfg["dataset"].get("path", "") - vecs, queries, gt = load_dataset(cfg["dataset"]["name"], data_dir) - - - nq = cfg["experiment"]["nq"] - queries, gt = queries[:nq], gt[:nq] - - # 3) Build or load index - build_params = IndexBuildParams() - build_params.nlist = cfg["index"]["nlist"] - build_params.metric = cfg["index"]["metric"] - build_params.num_workers = cfg["experiment"]["n_workers"] - - idx_dir = Path(cfg["paths"]["index_dir"]); idx_dir.mkdir(parents=True, exist_ok=True) - idx_path = idx_dir / f"{cfg['dataset']['name']}_ivf{build_params.nlist}.index" - - idx = QuakeIndex() - idx.build(vecs, torch.arange(len(vecs)), build_params) - logger.info(f"Loaded index → {idx_path} (workers={cfg['experiment']['n_workers']})") - - # 4) Run each method × recall_target records = [] - k = cfg["experiment"]["k"] - max_nlist = build_params.nlist + k = exp_cfg["k"] + max_nlist_val = quake_idx.nlist() for method in cfg["methods"]: - for rt in cfg["experiment"]["recall_targets"]: - logger.info(f"Method={method} RecallTarget={rt}") - per_query = [] # collect (nprobe, recall, time_ms) tuples + for rt in exp_cfg["recall_targets"]: + per_query_stats = [] # (nprobe, recall, time_ms) if method == "Oracle": - # per‐query binary search - for i, q in enumerate(queries): - lo, hi, best = 1, max_nlist, max_nlist + for i, q_vec in enumerate(queries): + lo, hi, best_np = 1, max_nlist_val, max_nlist_val while lo <= hi: mid = (lo + hi) // 2 - sp = SearchParams() - sp.nprobe = mid - sp.k = k - sp.recall_target = -1 - res = idx.search(q.unsqueeze(0), sp) - rec = compute_recall(res.ids, gt[i].unsqueeze(0), k).item() + sp = common_utils.create_search_params(nprobe=mid, k=k, recall_target=-1) + _, rec, _ = common_utils.run_search_trial(quake_idx, q_vec, gt[i], k, sp) if rec >= rt: - best = mid - hi = mid - 1 + best_np, hi = mid, mid - 1 else: lo = mid + 1 - - # time at best - t0 = time.time() - sp = SearchParams() - sp.nprobe = best - sp.k = k - sp.recall_target = -1 - res = idx.search(q.unsqueeze(0), sp) - rec = compute_recall(res.ids, gt[i].unsqueeze(0), k).item() - elapsed = (time.time() - t0) * 1000.0 - per_query.append((best, rec, elapsed)) + sp_final = common_utils.create_search_params(nprobe=best_np, k=k, recall_target=-1) + _, final_rec, final_time_ms = common_utils.run_search_trial(quake_idx, q_vec, gt[i], k, sp_final) + per_query_stats.append((best_np, final_rec, final_time_ms)) elif method == "FixedNProbe": - # find one global nprobe - lo, hi, best = 1, max_nlist, max_nlist + lo, hi, best_global_np = 1, max_nlist_val, max_nlist_val while lo <= hi: mid = (lo + hi) // 2 - sp = SearchParams(nprobe=mid, k=k, recall_target=-1) - ids = [] - for q in queries: - ids.append(idx.search(q.unsqueeze(0), sp).ids) - avg_rec = compute_recall(torch.cat(ids,0), gt, k).mean().item() + sp = common_utils.create_search_params(nprobe=mid, k=k, recall_target=-1) + current_ids = [] + for q_vec_fixed in queries: # Use all queries for tuning this + res_ids = quake_idx.search(q_vec_fixed.unsqueeze(0), sp).ids + current_ids.append(res_ids) + avg_rec = common_utils.quake_compute_recall(torch.cat(current_ids,0), gt, k).mean().item() if avg_rec >= rt: - best = mid - hi = mid - 1 + best_global_np, hi = mid, mid - 1 else: lo = mid + 1 - # then time each query at best - for q in queries: - t0 = time.time() - sp = SearchParams(nprobe=best, k=k, recall_target=-1) - res = idx.search(q.unsqueeze(0), sp) - elapsed = (time.time() - t0) * 1000.0 - rec = compute_recall(res.ids, gt[0:1], k).item() # single recall - per_query.append((best, rec, elapsed)) + sp_final = common_utils.create_search_params(nprobe=best_global_np, k=k, recall_target=-1) + for i, q_vec in enumerate(queries): + _, final_rec, final_time_ms = common_utils.run_search_trial(quake_idx, q_vec, gt[i], k, sp_final) + per_query_stats.append((best_global_np, final_rec, final_time_ms)) elif method == "APS": - # one‐shot APS per query - for q, true in zip(queries, gt): - sp = SearchParams() - sp.nprobe = -1 - sp.k = k - sp.recall_target = rt - sp.recompute_threshold = cfg["experiment"]["recompute_ratio"] - sp.use_precomputed = cfg["experiment"]["use_precompute"] - sp.initial_search_fraction = cfg["experiment"]["initial_search_fraction"] - t0 = time.time() - res = idx.search(q.unsqueeze(0), sp) - elapsed = (time.time() - t0) * 1000.0 - rec = compute_recall(res.ids, true.unsqueeze(0), k).item() - print(f"recall: {rec:.4f} (target={rt})") - per_query.append((res.timing_info.partitions_scanned, rec, elapsed)) + for i, q_vec in enumerate(queries): + sp = common_utils.create_search_params( + nprobe=-1, k=k, recall_target=rt, + recompute_threshold=exp_cfg["recompute_ratio"], + use_precomputed=exp_cfg["use_precompute"], + initial_search_fraction=exp_cfg["initial_search_fraction"] + ) + nprobe_scan, final_rec, final_time_ms = common_utils.run_search_trial(quake_idx, q_vec, gt[i], k, sp) + logger.debug(f"APS recall: {final_rec:.4f} (target={rt}), nprobe_scanned={nprobe_scan}") + per_query_stats.append((nprobe_scan, final_rec, final_time_ms)) else: raise ValueError(f"Unknown method: {method}") - # 5) Aggregate - arr = np.array(per_query, dtype=float) # shape (nq,3) + + arr = np.array(per_query_stats, dtype=float) + mean_nprobe = arr[:,0].mean() + std_nprobe = arr[:,0].std() + mean_recall = arr[:,1].mean() + std_recall = arr[:,1].std() + mean_time_ms = arr[:,2].mean() + std_time_ms = arr[:,2].std() + + logger.info(f"Method={method} RecallTarget={rt}, Recall={mean_recall:.4f} (std={std_recall:.4f}), " + f"Time={mean_time_ms:.2f}ms (std={std_time_ms:.2f}ms), NProbe={mean_nprobe:.1f} (std={std_nprobe:.1f})") + records.append({ - "Method": method, - "RecallTarget": rt, - "mean_nprobe": arr[:,0].mean(), - "std_nprobe": arr[:,0].std(), - "mean_recall": arr[:,1].mean(), - "std_recall": arr[:,1].std(), - "mean_time_ms": arr[:,2].mean(), - "std_time_ms": arr[:,2].std(), + "Method": method, "RecallTarget": rt, + "mean_nprobe": mean_nprobe, "std_nprobe": std_nprobe, + "mean_recall": mean_recall, "std_recall": std_recall, + "mean_time_ms": mean_time_ms, "std_time_ms": std_time_ms, }) - # 6) Save CSV - df = pd.DataFrame(records) - out_csv = out / "aps_recall_targets_summary.csv" - df.to_csv(out_csv, index=False) - logger.info(f"Summary → {out_csv}") - - # 7) Plot: recall-target vs time, one line per method - fig, axes = plt.subplots(3, 1, figsize=(6,8), sharex=True) - for m in df["Method"].unique(): - grp = df[df["Method"]==m] - axes[0].errorbar(grp["RecallTarget"], grp["mean_time_ms"], - yerr=grp["std_time_ms"], marker="o", capsize=4, label=m) - axes[1].errorbar(grp["RecallTarget"], grp["mean_recall"], - yerr=grp["std_recall"], marker="o", capsize=4, label=m) - axes[2].errorbar(grp["RecallTarget"], grp["mean_nprobe"], - yerr=grp["std_nprobe"], marker="o", capsize=4, label=m) - axes[0].set_xlabel("Recall Target") - axes[0].set_xlabel("Mean Query Time (ms)") - axes[0].set_title("APS‑Experiment: Recall Target vs Time") - axes[0].legend() - - recall_targets = cfg["experiment"]["recall_targets"] - - axes[1].plot(recall_targets, recall_targets, "k--", label="Target") - axes[1].set_xlabel("Recall Target") - axes[1].set_ylabel("Mean Recall") - axes[1].set_title("APS‑Experiment: Recall Target vs Recall") - - axes[2].set_xlabel("Recall Target") - axes[2].set_ylabel("Mean NProbe") - axes[2].set_yscale("log") - axes[2].set_title("APS‑Experiment: Recall Target vs NProbe") - - plt.grid(True, which="both", ls=":") - plt.tight_layout() - plot_path = out / "aps_recall_vs_time.png" - plt.savefig(plot_path) - logger.info(f"Plot → {plot_path}") \ No newline at end of file + results_df = pd.DataFrame(records) + common_utils.save_results_csv(results_df, out_dir / "aps_recall_targets_summary.csv") + + plot_path = out_dir / "aps_recall_vs_metrics.png" + common_utils.plot_recall_performance( + results_df, + x_metric="RecallTarget", + y_metrics=["mean_time_ms", "mean_recall", "mean_nprobe"], + y_labels=["Mean Query Time (ms)", "Mean Recall Achieved", "Mean NProbe"], + y_scales=["linear", "linear", "log"], + plot_title_prefix=f"{dataset_cfg['name']} APS Experiment", + output_path=plot_path, + recall_targets_for_line=exp_cfg["recall_targets"] + ) \ No newline at end of file diff --git a/test/experiments/osdi2025/experiment_utils.py b/test/experiments/osdi2025/experiment_utils.py new file mode 100644 index 00000000..b9091483 --- /dev/null +++ b/test/experiments/osdi2025/experiment_utils.py @@ -0,0 +1,126 @@ +# File: test/experiments/osdi2025/common/experiment_utils.py +import time +import yaml +import logging +from pathlib import Path + +import torch +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt + +from quake import QuakeIndex, IndexBuildParams, SearchParams +from quake.datasets.ann_datasets import load_dataset as quake_load_dataset +from quake.utils import compute_recall as quake_compute_recall + +logger = logging.getLogger(__name__) + +def load_config(cfg_path: str) -> dict: + return yaml.safe_load(Path(cfg_path).read_text()) + +def load_data(dataset_name: str, dataset_path: str, nq_override: int = None): + vecs, queries, gt = quake_load_dataset(dataset_name, dataset_path) + if nq_override is not None and nq_override > 0 and nq_override < len(queries): + queries = queries[:nq_override] + if gt is not None: + gt = gt[:nq_override] + return vecs, queries, gt + +def prepare_quake_index( + vecs: torch.Tensor, + build_params_dict: dict, + index_file_path: Path, + force_rebuild: bool = False, + num_workers_load: int = 0, + num_parent_workers_load: int = 0, + use_numa: bool = False +) -> QuakeIndex: + idx = QuakeIndex() + if index_file_path.exists() and not force_rebuild: + logger.info(f"Loading index from {index_file_path}") + idx.load(str(index_file_path), num_workers_load, use_numa, num_parent_workers_load) + else: + logger.info(f"Building index -> {index_file_path}") + bp = IndexBuildParams() + for key, value in build_params_dict.items(): + if hasattr(bp, key): + setattr(bp, key, value) + idx.build(vecs, torch.arange(len(vecs)), bp) + index_file_path.parent.mkdir(parents=True, exist_ok=True) + idx.save(str(index_file_path)) + logger.info(f"Index saved to {index_file_path}") + return idx + +def create_search_params(**attrs) -> SearchParams: + sp = SearchParams() + for k, v in attrs.items(): + if hasattr(sp, k): + setattr(sp, k, v) + return sp + +def run_search_trial( + idx: QuakeIndex, + query: torch.Tensor, + gt_vector: torch.Tensor, # Ground truth for this single query + k_val: int, + search_params: SearchParams +) -> tuple: + t0 = time.perf_counter_ns() + res = idx.search(query.unsqueeze(0), search_params) + elapsed_ns = time.perf_counter_ns() - t0 + rec = quake_compute_recall(res.ids, gt_vector.unsqueeze(0), k_val).item() + partitions_scanned = getattr(res.timing_info, "partitions_scanned", np.nan) + return partitions_scanned, rec, elapsed_ns / 1e6 # nprobe, recall, time_ms + +def save_results_csv(records: list, output_path: Path): + df = pd.DataFrame(records) + output_path.parent.mkdir(parents=True, exist_ok=True) + df.to_csv(output_path, index=False) + logger.info(f"Results saved to {output_path}") + +def plot_recall_performance( + df: pd.DataFrame, + x_metric: str, # e.g., "RecallTarget" + y_metrics: list, # e.g., ["mean_time_ms", "mean_recall", "mean_nprobe"] + y_labels: list, + y_scales: list = None, # e.g., ["linear", "linear", "log"] + plot_title_prefix: str = "", + output_path: Path = None, + recall_targets_for_line: list = None +): + num_plots = len(y_metrics) + fig, axes = plt.subplots(num_plots, 1, figsize=(6, 3 * num_plots + 1), sharex=True) + if num_plots == 1: + axes = [axes] + + for m_idx, method_name in enumerate(df["Method"].unique()): + grp = df[df["Method"] == method_name] + for i, y_col in enumerate(y_metrics): + y_err_col = df.columns[df.columns.get_loc(y_col) + 1] if f"std_{y_col.split('_')[1]}" in df.columns else None + yerr_values = grp[y_err_col] if y_err_col and y_err_col in grp.columns else None + axes[i].errorbar( + grp[x_metric], grp[y_col], + yerr=yerr_values, + marker="o", capsize=4, label=method_name, + linestyle='-' if m_idx == 0 else '--' # Differentiate methods + ) + + for i, y_col in enumerate(y_metrics): + axes[i].set_ylabel(y_labels[i]) + if y_scales and y_scales[i]: + axes[i].set_yscale(y_scales[i]) + if y_col == "mean_recall" and recall_targets_for_line: + axes[i].plot(recall_targets_for_line, recall_targets_for_line, "k--", label="Target") + axes[i].legend() + axes[i].grid(True, which="both", ls=":") + axes[i].set_title(f"{plot_title_prefix}: {x_metric} vs {y_labels[i]}") + + axes[-1].set_xlabel(x_metric) + plt.tight_layout(rect=[0, 0, 1, 0.97]) # Adjust for suptitle + fig.suptitle(f"{plot_title_prefix} Performance", fontsize=14) + + if output_path: + output_path.parent.mkdir(parents=True, exist_ok=True) + plt.savefig(output_path) + logger.info(f"Plot saved to {output_path}") + plt.close(fig) \ No newline at end of file From 3f09148e283154d15f10c2272d7c0ce4ffe3580e Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 00:19:10 -0500 Subject: [PATCH 195/323] update aps experiment --- .../configs/sift1m.yaml | 25 ---- .../adaptive_partition_scanning/run.py | 119 ------------------ 2 files changed, 144 deletions(-) delete mode 100644 test/experiments/adaptive_partition_scanning/configs/sift1m.yaml delete mode 100644 test/experiments/adaptive_partition_scanning/run.py diff --git a/test/experiments/adaptive_partition_scanning/configs/sift1m.yaml b/test/experiments/adaptive_partition_scanning/configs/sift1m.yaml deleted file mode 100644 index 51e8f982..00000000 --- a/test/experiments/adaptive_partition_scanning/configs/sift1m.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# configs/experiment.yaml -mode: run # options: build, run, plot -base_dir: data/aps -dataset: - name: sift1m - path: data -experiment: - nq: 100 - k: 100 - n_workers: 0 - recall_targets: [0.7, 0.75, 0.8, 0.85, 0.9, 0.95, .99] -index: - metric: l2 - nc: 1000 -overwrite: - index: false - results: true -methods: ['Oracle', 'APS'] -#methods: ['APS'] -#methods: ['Oracle'] - -paths: - index_dir: data/sift/indexes - results_dir: data/sift/results - plot_dir: data/sift/plots \ No newline at end of file diff --git a/test/experiments/adaptive_partition_scanning/run.py b/test/experiments/adaptive_partition_scanning/run.py deleted file mode 100644 index dc5a74e5..00000000 --- a/test/experiments/adaptive_partition_scanning/run.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python3 -""" -Adaptive‐Partition‐Scanning Recall‐Target Runner (Simplified) -Supports: Oracle, FixedNProbe, APS -""" -import logging -from pathlib import Path -import numpy as np -import torch -import pandas as pd - -from test.experiments.osdi2025 import experiment_utils as common_utils -from quake import SearchParams # Keep direct import for clarity if used extensively - -logger = logging.getLogger(__name__) -logging.basicConfig(level=logging.INFO, format="%(asctime)s | %(levelname)s | %(message)s") - -def run_experiment(cfg_path: str, output_dir_str: str): - cfg = common_utils.load_config(cfg_path) - out_dir = Path(output_dir_str) - - dataset_cfg = cfg["dataset"] - exp_cfg = cfg["experiment"] - idx_build_cfg = cfg["index"] - paths_cfg = cfg["paths"] - - vecs, queries, gt = common_utils.load_data( - dataset_cfg["name"], dataset_cfg.get("path", ""), exp_cfg["nq"] - ) - - idx_path = Path(paths_cfg["index_dir"]) / f"{dataset_cfg['name']}_ivf{idx_build_cfg['nlist']}.index" - quake_idx = common_utils.prepare_quake_index( - vecs, - {"nlist": idx_build_cfg["nlist"], "metric": idx_build_cfg["metric"], "num_workers": exp_cfg["n_workers"]}, - idx_path, - force_rebuild=cfg["overwrite"].get("index", False) - ) - logger.info(f"Index ready (workers={exp_cfg['n_workers']})") - - records = [] - k = exp_cfg["k"] - max_nlist_val = quake_idx.nlist() - - for method in cfg["methods"]: - for rt in exp_cfg["recall_targets"]: - logger.info(f"Method={method} RecallTarget={rt}") - per_query_stats = [] # (nprobe, recall, time_ms) - - if method == "Oracle": - for i, q_vec in enumerate(queries): - lo, hi, best_np = 1, max_nlist_val, max_nlist_val - while lo <= hi: - mid = (lo + hi) // 2 - sp = common_utils.create_search_params(nprobe=mid, k=k, recall_target=-1) - _, rec, _ = common_utils.run_search_trial(quake_idx, q_vec, gt[i], k, sp) - if rec >= rt: - best_np, hi = mid, mid - 1 - else: - lo = mid + 1 - sp_final = common_utils.create_search_params(nprobe=best_np, k=k, recall_target=-1) - _, final_rec, final_time_ms = common_utils.run_search_trial(quake_idx, q_vec, gt[i], k, sp_final) - per_query_stats.append((best_np, final_rec, final_time_ms)) - - elif method == "FixedNProbe": - lo, hi, best_global_np = 1, max_nlist_val, max_nlist_val - while lo <= hi: - mid = (lo + hi) // 2 - sp = common_utils.create_search_params(nprobe=mid, k=k, recall_target=-1) - current_ids = [] - for q_vec_fixed in queries: # Use all queries for tuning this - res_ids = quake_idx.search(q_vec_fixed.unsqueeze(0), sp).ids - current_ids.append(res_ids) - avg_rec = common_utils.quake_compute_recall(torch.cat(current_ids,0), gt, k).mean().item() - if avg_rec >= rt: - best_global_np, hi = mid, mid - 1 - else: - lo = mid + 1 - - sp_final = common_utils.create_search_params(nprobe=best_global_np, k=k, recall_target=-1) - for i, q_vec in enumerate(queries): - _, final_rec, final_time_ms = common_utils.run_search_trial(quake_idx, q_vec, gt[i], k, sp_final) - per_query_stats.append((best_global_np, final_rec, final_time_ms)) - - elif method == "APS": - for i, q_vec in enumerate(queries): - sp = common_utils.create_search_params( - nprobe=-1, k=k, recall_target=rt, - recompute_threshold=exp_cfg["recompute_ratio"], - use_precomputed=exp_cfg["use_precompute"], - initial_search_fraction=exp_cfg["initial_search_fraction"] - ) - nprobe_scan, final_rec, final_time_ms = common_utils.run_search_trial(quake_idx, q_vec, gt[i], k, sp) - logger.debug(f"APS recall: {final_rec:.4f} (target={rt}), nprobe_scanned={nprobe_scan}") - per_query_stats.append((nprobe_scan, final_rec, final_time_ms)) - else: - raise ValueError(f"Unknown method: {method}") - - arr = np.array(per_query_stats, dtype=float) - records.append({ - "Method": method, "RecallTarget": rt, - "mean_nprobe": arr[:,0].mean(), "std_nprobe": arr[:,0].std(), - "mean_recall": arr[:,1].mean(), "std_recall": arr[:,1].std(), - "mean_time_ms": arr[:,2].mean(), "std_time_ms": arr[:,2].std(), - }) - - results_df = pd.DataFrame(records) - common_utils.save_results_csv(results_df, out_dir / "aps_recall_targets_summary.csv") - - plot_path = out_dir / "aps_recall_vs_metrics.png" - common_utils.plot_recall_performance( - results_df, - x_metric="RecallTarget", - y_metrics=["mean_time_ms", "mean_recall", "mean_nprobe"], - y_labels=["Mean Query Time (ms)", "Mean Recall Achieved", "Mean NProbe"], - y_scales=["linear", "linear", "log"], - plot_title_prefix=f"{dataset_cfg['name']} APS Experiment", - output_path=plot_path, - recall_targets_for_line=exp_cfg["recall_targets"] - ) \ No newline at end of file From e9d18d1e437f03a7491c8802389ba3f95c96b0bc Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 00:51:02 -0500 Subject: [PATCH 196/323] update early termination experiment --- .../early_termination/configs/sift1m.yaml | 4 +- .../osdi2025/early_termination/run.py | 528 ++++++++---------- 2 files changed, 236 insertions(+), 296 deletions(-) diff --git a/test/experiments/osdi2025/early_termination/configs/sift1m.yaml b/test/experiments/osdi2025/early_termination/configs/sift1m.yaml index 9d53f80f..df1c96a1 100644 --- a/test/experiments/osdi2025/early_termination/configs/sift1m.yaml +++ b/test/experiments/osdi2025/early_termination/configs/sift1m.yaml @@ -18,8 +18,8 @@ index: overwrite: index: false results: true -#methods: ['LAET', 'Auncel', 'Oracle', 'FixedNProbe', 'APS', 'SPANN'] -methods: ['Auncel'] +methods: ['LAET', 'Auncel', 'Oracle', 'FixedNProbe', 'APS', 'SPANN'] +#methods: ['Auncel'] paths: index_dir: data/sift1m/indexes diff --git a/test/experiments/osdi2025/early_termination/run.py b/test/experiments/osdi2025/early_termination/run.py index ce8c2dbc..c6538b95 100644 --- a/test/experiments/osdi2025/early_termination/run.py +++ b/test/experiments/osdi2025/early_termination/run.py @@ -1,13 +1,11 @@ #!/usr/bin/env python3 """ -APS vs. early-termination baselines +APS vs. early-termination baselines (Simplified) Generates CSV + Markdown table with: RecallAchieved | nprobe | QueryLatencyMs | TuningTimeMs for recall targets 0.80, 0.90, 0.99 """ - from __future__ import annotations -import argparse import logging import time from pathlib import Path @@ -16,22 +14,14 @@ import numpy as np import pandas as pd import torch -import yaml - -# ── optional plotting ───────────────────────────────────────────────────────── -try: - import matplotlib.pyplot as plt +import matplotlib.pyplot as plt - _HAVE_MPL = True -except ImportError: - _HAVE_MPL = False +import test.experiments.osdi2025.experiment_utils as common_utils -# ── Quake bindings ──────────────────────────────────────────────────────────── -from quake import QuakeIndex, IndexBuildParams, SearchParams -from quake.datasets.ann_datasets import load_dataset +from quake import QuakeIndex, SearchParams, IndexBuildParams from quake.utils import compute_recall -# ── LAET (mandatory) ────────────────────────────────────────────────────────── +# LAET (mandatory for this experiment) try: from .laet import LAETPipeline except ImportError as e: @@ -40,24 +30,11 @@ "Install the laet package or fix PYTHONPATH." ) from e -# ── logging ─────────────────────────────────────────────────────────────────── logging.basicConfig( level=logging.INFO, format="%(asctime)s | %(levelname)7s | %(message)s", datefmt="%H:%M:%S" ) logger = logging.getLogger("experiment") - -# ----------------------------------------------------------------------------- # -# Helpers -# ----------------------------------------------------------------------------- # -def make_sp(**attrs) -> SearchParams: - """Create SearchParams then set attributes (bindings have no kwargs ctor).""" - sp = SearchParams() - for k, v in attrs.items(): - setattr(sp, k, v) - return sp - - def tune_auncel_a( idx: QuakeIndex, queries: torch.Tensor, @@ -70,331 +47,294 @@ def tune_auncel_a( a_min: float = 1e-5, a_max: float = .5, ) -> tuple[float, list[tuple[float, float, float]]]: - """ - Binary-search the smallest 'a' that still meets the recall target. - Returns (best_a, per_query_stats) where the stats are - (nprobe, recall, latency_ms) for the final run. - """ best_a = a_max lo, hi = a_min, a_max best_stats: list[tuple[float, float, float]] = [] for _ in range(max_iters): mid = (lo + hi) / 2.0 - per_query: list[tuple[float, float, float]] = [] - - for q, g in zip(queries, gt): - sp = make_sp( - nprobe=-1, - k=k, - recall_target=target_recall, - use_auncel=True, - auncel_a=mid, - auncel_b=.5, - recompute_threshold=recompute_thr, - initial_search_fraction=init_frac, + current_per_query_stats: list[tuple[float, float, float]] = [] + + for i_q, q_vec in enumerate(queries): + sp = common_utils.create_search_params( + nprobe=-1, k=k, recall_target=target_recall, + use_auncel=True, auncel_a=mid, auncel_b=.5, + recompute_threshold=recompute_thr, initial_search_fraction=init_frac, ) - t0 = time.perf_counter_ns() - res = idx.search(q.unsqueeze(0), sp) - per_query.append( - ( - getattr(res.timing_info, "partitions_scanned", np.nan), - compute_recall(res.ids, g.unsqueeze(0), k).item(), - (time.perf_counter_ns() - t0) / 1e6, - ) + partitions_scanned, rec, time_ms = common_utils.run_search_trial( + idx, q_vec, gt[i_q], k, sp ) + current_per_query_stats.append((partitions_scanned, rec, time_ms)) - mean_recall = np.mean([r for _, r, _ in per_query]) + mean_recall = np.mean([r for _, r, _ in current_per_query_stats]) if mean_recall >= target_recall: - # feasible → try smaller a - best_a, best_stats = mid, per_query + best_a, best_stats = mid, current_per_query_stats hi = mid * 0.5 else: - # not enough recall → increase a lo = mid * 1.5 - if hi - lo < 1e-3: + if abs(hi - lo) < 1e-4 or hi < lo : # Added small tolerance and check break - return best_a, best_stats def binary_search_best_nprobe( idx: QuakeIndex, - queries: torch.Tensor, - gt: torch.Tensor, - k: int, - target_recall: float, - max_nprobe: int, - use_spann: bool = False, - spann_eps: float = 1.5, + queries_tensor: torch.Tensor, # Can be single or multiple queries + gt_tensor: torch.Tensor, # Corresponding ground truth + k_val: int, + target_recall_val: float, + max_nprobe_val: int, + use_spann_flag: bool = False, + spann_eps_val: float = 1.5, ) -> int: - """Return smallest nprobe reaching `target_recall` on the supplied queries.""" - lo, hi, best = 1, max_nprobe, max_nprobe + lo, hi, best = 1, max_nprobe_val, max_nprobe_val + is_single_query = queries_tensor.shape[0] == 1 + while lo <= hi: mid = (lo + hi) // 2 - sp = make_sp(k=k, nprobe=mid, use_spann=use_spann, spann_eps=spann_eps if use_spann else 0.0) - ids_all = [ - idx.search(q.unsqueeze(0), sp).ids - for q in queries - if idx.search(q.unsqueeze(0), sp).ids.numel() - ] - mean_rec = ( - compute_recall(torch.cat(ids_all, 0), gt, k).mean().item() if ids_all else 0.0 + sp = common_utils.create_search_params( + k=k_val, nprobe=mid, use_spann=use_spann_flag, + spann_eps=spann_eps_val if use_spann_flag else 0.0 ) - if mean_rec >= target_recall: + + if is_single_query: + # For single query, run_search_trial is fine for recall check + _, rec, _ = common_utils.run_search_trial(idx, queries_tensor[0], gt_tensor[0], k_val, sp) + mean_rec_val = rec + else: + # For multiple queries, need to aggregate recall + ids_all_list = [] + for i_q in range(queries_tensor.shape[0]): + # Directly call idx.search for id extraction for compute_recall over batch + res_search = idx.search(queries_tensor[i_q].unsqueeze(0), sp) + if res_search.ids.numel(): + ids_all_list.append(res_search.ids) + if not ids_all_list: + mean_rec_val = 0.0 + else: + mean_rec_val = compute_recall(torch.cat(ids_all_list, 0), gt_tensor, k_val).mean().item() + + if mean_rec_val >= target_recall_val: best, hi = mid, mid - 1 else: lo = mid + 1 return best - def print_markdown(df: pd.DataFrame) -> None: print("\n" + "-" * 80) print(df.to_markdown(index=False, floatfmt=".4f")) print("-" * 80 + "\n") -# ----------------------------------------------------------------------------- # -# Core experiment -# ----------------------------------------------------------------------------- # -def run_experiment(cfg_path: str, output_dir: str) -> None: - # 1) ---------------------------------------------------------------- config - cfg = yaml.safe_load(Path(cfg_path).read_text()) - out_dir = Path(output_dir).expanduser() +def run_experiment(cfg_path_str: str, output_dir_str: str) -> None: + cfg = common_utils.load_config(cfg_path_str) + out_dir = Path(output_dir_str) out_dir.mkdir(parents=True, exist_ok=True) - k = cfg["experiment"]["k"] - recall_targets: List[float] = cfg["experiment"]["recall_targets"] - table_targets = {0.80, 0.90, 0.99} - - # 2) ---------------------------------------------------------------- data - vecs, queries, gt = load_dataset(cfg["dataset"]["name"], cfg["dataset"].get("path", "")) - nq = min(cfg["experiment"].get("nq", queries.shape[0]), queries.shape[0]) - queries, gt = queries[:nq], gt[:nq] - logger.info(f"Dataset loaded – {len(vecs):,} base vecs, {nq} queries.") - - # 3) ---------------------------------------------------------------- index - idx = QuakeIndex() - bp = IndexBuildParams() - bp.nlist = cfg["index"]["nlist"] - bp.metric = cfg["index"]["metric"] - bp.num_workers = cfg["experiment"].get("n_workers", 0) - - idx_file = Path(cfg["paths"]["index_dir"]) / f"{cfg['dataset']['name']}_quake_ivf{bp.nlist}.index" - idx_file.parent.mkdir(parents=True, exist_ok=True) - if idx_file.exists() and not cfg["overwrite"].get("index", False): - idx.load(str(idx_file), 0) - logger.info("Index loaded from disk.") - else: - logger.info("Building index …") - idx.build(vecs, torch.arange(len(vecs)), bp) - idx.save(str(idx_file)) - logger.info(f"Index saved to {idx_file}") - - max_nprobe = idx.nlist() if callable(getattr(idx, "nlist", None)) else bp.nlist - - # 4) ---------------------------------------------------------------- LAET (train / load) - laet_cfg = cfg["laet_config"] - - # required dicts for get_or_train_model - data_paths_cfg = { - "base_vectors": laet_cfg["base_vectors_path_for_laet_train"], - "train_query_vectors": laet_cfg["train_query_vectors_path_for_laet_train"], - "gt_train": laet_cfg["gt_train_path_for_laet_train"], - "gt_format": laet_cfg.get("gt_format_for_laet_train", "ivecs"), - "training_vectors_for_faiss_index": laet_cfg["faiss_training_vectors_path_for_laet_train"], + exp_cfg = cfg["experiment"] + dataset_cfg = cfg["dataset"] + idx_build_cfg = cfg["index"] + paths_cfg = cfg["paths"] + + k_val = exp_cfg["k"] + recall_targets_list: List[float] = exp_cfg["recall_targets"] + table_targets_set = {0.80, 0.90, 0.99} + + vecs, queries_all, gt_all = common_utils.load_data( + dataset_cfg["name"], dataset_cfg.get("path", ""), exp_cfg.get("nq") + ) + logger.info(f"Dataset loaded – {len(vecs):,} base vecs, {len(queries_all)} queries.") + + idx_file_path = Path(paths_cfg["index_dir"]) / f"{dataset_cfg['name']}_quake_ivf{idx_build_cfg['nlist']}.index" + quake_idx_instance = common_utils.prepare_quake_index( + vecs, + {"nlist": idx_build_cfg["nlist"], "metric": idx_build_cfg["metric"], "num_workers": exp_cfg.get("n_workers", 0)}, + idx_file_path, + force_rebuild=cfg["overwrite"].get("index", False), + num_workers_load=exp_cfg.get("n_workers",0) # Pass num_workers for loading context + ) + max_nprobe_val = quake_idx_instance.nlist() + + # LAET SPECIFIC CONFIG + laet_cfg_dict = cfg["laet_config"] + data_paths_cfg_laet = { + "base_vectors": laet_cfg_dict["base_vectors_path_for_laet_train"], + "train_query_vectors": laet_cfg_dict["train_query_vectors_path_for_laet_train"], + "gt_train": laet_cfg_dict["gt_train_path_for_laet_train"], + "gt_format": laet_cfg_dict.get("gt_format_for_laet_train", "ivecs"), + "training_vectors_for_faiss_index": laet_cfg_dict["faiss_training_vectors_path_for_laet_train"], } - generation_params_cfg = { - "num_train_queries_to_process": laet_cfg.get("num_laet_training_samples", 10000), - "k_gt_load_for_target": laet_cfg.get("laet_train_k_gt_load", 1), - "k_search_for_target": laet_cfg.get("laet_train_k_search", 10), - "max_nprobe_scan": laet_cfg.get("laet_train_max_nprobe", 128), - "max_efsearch_scan": laet_cfg.get("laet_train_max_efsearch", 256), - "param_scan_step": laet_cfg.get("laet_train_param_scan_step", 1), + generation_params_cfg_laet = { + "num_train_queries_to_process": laet_cfg_dict.get("num_laet_training_samples", 10000), + "k_gt_load_for_target": laet_cfg_dict.get("laet_train_k_gt_load", 1), + "k_search_for_target": laet_cfg_dict.get("laet_train_k_search", 10), + "max_nprobe_scan": laet_cfg_dict.get("laet_train_max_nprobe", 128), + "param_scan_step": laet_cfg_dict.get("laet_train_param_scan_step", 1), } - faiss_params_cfg = { - "faiss_index_key_for_gen": laet_cfg.get("faiss_index_key_for_laet_train_gen", f"IVF{max_nprobe},Flat") + faiss_params_cfg_laet = { + "faiss_index_key_for_gen": laet_cfg_dict.get("faiss_index_key_for_laet_train_gen", f"IVF{max_nprobe_val},Flat") } - training_params_cfg = { - "log_target_training": laet_cfg.get("train_log_target", False), - "test_size": laet_cfg.get("train_gbdt_test_size", 0.1), - "num_leaves": laet_cfg.get("train_gbdt_num_leaves", 31), - "learning_rate": laet_cfg.get("train_gbdt_lr", 0.05), - "n_estimators": laet_cfg.get("train_gbdt_n_estimators", 100), - "feature_fraction": laet_cfg.get("train_gbdt_feature_fraction", 0.9), - "bagging_fraction": laet_cfg.get("train_gbdt_bagging_fraction", 0.8), - "bagging_freq": laet_cfg.get("train_gbdt_bagging_freq", 5), + training_params_cfg_laet = { + "log_target_training": laet_cfg_dict.get("train_log_target", False), + "test_size": laet_cfg_dict.get("train_gbdt_test_size", 0.1), + # ... other GBDT params from the LAET repo + "num_leaves": laet_cfg_dict.get("train_gbdt_num_leaves", 31), + "learning_rate": laet_cfg_dict.get("train_gbdt_lr", 0.05), + "n_estimators": laet_cfg_dict.get("train_gbdt_n_estimators", 100), } - laet = LAETPipeline( - vector_dim=queries.shape[1], + laet_pipeline_instance = LAETPipeline( + vector_dim=queries_all.shape[1], laet_artifacts_config={ - "base_dir": cfg["paths"]["laet_artifacts_base_dir"], - "dataset_name_for_files": laet_cfg.get( - "dataset_name_for_files", cfg["dataset"]["name"].upper() - ), - "index_key_for_files": laet_cfg.get("index_key_for_files", f"IVF{max_nprobe}_Flat"), - "model_subdir": laet_cfg.get("model_subdir", "laet_gbdt_models"), + "base_dir": paths_cfg["laet_artifacts_base_dir"], + "dataset_name_for_files": laet_cfg_dict.get("dataset_name_for_files", dataset_cfg["name"].upper()), + "index_key_for_files": laet_cfg_dict.get("index_key_for_files", f"IVF{max_nprobe_val}_Flat"), + "model_subdir": laet_cfg_dict.get("model_subdir", "laet_gbdt_models"), }, ) - - t_train0 = time.perf_counter_ns() - laet.get_or_train_model( - overwrite_model=False, - data_paths_config=data_paths_cfg, - generation_params_config=generation_params_cfg, - faiss_params_config=faiss_params_cfg, - training_params_config=training_params_cfg, + t_laet_train_start_ns = time.perf_counter_ns() + laet_pipeline_instance.get_or_train_model( + overwrite_model=False, # Or cfg["overwrite"].get("laet_model", False) + data_paths_config=data_paths_cfg_laet, + generation_params_config=generation_params_cfg_laet, + faiss_params_config=faiss_params_cfg_laet, + training_params_config=training_params_cfg_laet, ) - laet_training_ns = time.perf_counter_ns() - t_train0 - logger.info(f"LAET model ready (train/load time: {laet_training_ns/1e6:.1f} ms).") - - # 5) --------------------------------------------------------------- run methods - records: List[Dict] = [] - - for method in cfg["methods"]: - for rt in recall_targets: - logger.info(f"{method:>10s} | target recall {rt:.2f}") - per_query = [] # tuples of (nprobe, recall, q_ms) - tuning_ns = 0 - - # ---------------------------------------------------------------- # - if method == "Oracle": - for q, g in zip(queries, gt): - t0 = time.perf_counter_ns() - best_np = binary_search_best_nprobe( - idx, q.unsqueeze(0), g.unsqueeze(0), k, rt, max_nprobe + laet_training_total_ns = time.perf_counter_ns() - t_laet_train_start_ns + logger.info(f"LAET model ready (train/load time: {laet_training_total_ns/1e6:.1f} ms).") + + experiment_records: List[Dict] = [] + + for method_name in cfg["methods"]: + for recall_target_val in recall_targets_list: + query_results_list = [] # list of (nprobe_val, recall_val, query_time_ms) + current_tuning_ns = 0 + + if method_name == "Oracle": + for i_q, q_vec in enumerate(queries_all): + gt_vec = gt_all[i_q] + t_tune_start_ns = time.perf_counter_ns() + # Pass single query and gt for Oracle's per-query tuning + best_np_val = binary_search_best_nprobe( + quake_idx_instance, q_vec.unsqueeze(0), gt_vec.unsqueeze(0), k_val, recall_target_val, max_nprobe_val ) - tuning_ns += time.perf_counter_ns() - t0 - sp = make_sp(k=k, nprobe=best_np) - t1 = time.perf_counter_ns() - res = idx.search(q.unsqueeze(0), sp) - per_query.append( - ( - best_np, - compute_recall(res.ids, g.unsqueeze(0), k).item(), - (time.perf_counter_ns() - t1) / 1e6, - ) + current_tuning_ns += (time.perf_counter_ns() - t_tune_start_ns) + + sp_final = common_utils.create_search_params(k=k_val, nprobe=best_np_val) + _, rec_val, time_ms_val = common_utils.run_search_trial( + quake_idx_instance, q_vec, gt_vec, k_val, sp_final ) + query_results_list.append((best_np_val, rec_val, time_ms_val)) - elif method in ("FixedNProbe", "SPANN"): - t0 = time.perf_counter_ns() - best_np = binary_search_best_nprobe( - idx, - queries, - gt, - k, - rt, - max_nprobe, - use_spann=(method == "SPANN"), - spann_eps=1.5, + elif method_name in ("FixedNProbe", "SPANN"): + t_tune_start_ns = time.perf_counter_ns() + best_np_val = binary_search_best_nprobe( + quake_idx_instance, queries_all, gt_all, k_val, recall_target_val, max_nprobe_val, + use_spann_flag=(method_name == "SPANN"), spann_eps_val=1.5 ) - tuning_ns = time.perf_counter_ns() - t0 - for q, g in zip(queries, gt): - sp = make_sp( - k=k, - nprobe=best_np, - use_spann=(method == "SPANN"), - spann_eps=1.5 if method == "SPANN" else 0.0, + current_tuning_ns = time.perf_counter_ns() - t_tune_start_ns + + for i_q, q_vec in enumerate(queries_all): + sp_final = common_utils.create_search_params( + k=k_val, nprobe=best_np_val, + use_spann=(method_name == "SPANN"), + spann_eps=1.5 if method_name == "SPANN" else 0.0 ) - t1 = time.perf_counter_ns() - res = idx.search(q.unsqueeze(0), sp) - per_query.append( - ( - best_np, - compute_recall(res.ids, g.unsqueeze(0), k).item(), - (time.perf_counter_ns() - t1) / 1e6, - ) + _, rec_val, time_ms_val = common_utils.run_search_trial( + quake_idx_instance, q_vec, gt_all[i_q], k_val, sp_final ) - - elif method == "APS": - for q, g in zip(queries, gt): - sp = make_sp( - nprobe=-1, - k=k, - recall_target=rt, - recompute_threshold=cfg["experiment"]["recompute_ratio"], - use_precomputed=cfg["experiment"]["use_precompute"], - initial_search_fraction=cfg["experiment"]["initial_search_fraction"], + query_results_list.append((best_np_val, rec_val, time_ms_val)) + + elif method_name == "APS": + for i_q, q_vec in enumerate(queries_all): + sp_aps = common_utils.create_search_params( + nprobe=-1, k=k_val, recall_target=recall_target_val, + recompute_threshold=exp_cfg["recompute_ratio"], + use_precomputed=exp_cfg["use_precompute"], + initial_search_fraction=exp_cfg["initial_search_fraction"] ) - t1 = time.perf_counter_ns() - res = idx.search(q.unsqueeze(0), sp) - per_query.append( - ( - getattr(res.timing_info, "partitions_scanned", np.nan), - compute_recall(res.ids, g.unsqueeze(0), k).item(), - (time.perf_counter_ns() - t1) / 1e6, - ) + nprobe_scanned, rec_val, time_ms_val = common_utils.run_search_trial( + quake_idx_instance, q_vec, gt_all[i_q], k_val, sp_aps ) - - elif method == "Auncel": - t0 = time.perf_counter_ns() - best_a, per_query = tune_auncel_a( - idx, - queries, - gt, - k, - rt, - recompute_thr=cfg["experiment"]["recompute_ratio"], - init_frac=cfg["experiment"]["initial_search_fraction"], + query_results_list.append((nprobe_scanned, rec_val, time_ms_val)) + + elif method_name == "Auncel": + t_tune_start_ns = time.perf_counter_ns() + best_a_val, query_results_list = tune_auncel_a( # tune_auncel_a returns the list directly + quake_idx_instance, queries_all, gt_all, k_val, recall_target_val, + recompute_thr=exp_cfg["recompute_ratio"], + init_frac=exp_cfg["initial_search_fraction"] ) - tuning_ns = time.perf_counter_ns() - t0 - logger.info(f"Auncel @ RT={rt:.2f} → selected a = {best_a:.4f}") - - elif method == "LAET": - t0 = time.perf_counter_ns() - mean_np, mean_rec, mean_ms = laet.run_inference_for_quake_experiment( - quake_idx=idx, - queries_torch=queries, - gt_torch=gt, - target_recall=rt, - k_search=k, - base_quake_sp=make_sp(k=k), + current_tuning_ns = time.perf_counter_ns() - t_tune_start_ns + logger.info(f"Auncel @ RT={recall_target_val:.2f} → selected a = {best_a_val:.4f}") + + elif method_name == "LAET": + t_infer_start_ns = time.perf_counter_ns() + mean_np, mean_rec, mean_ms = laet_pipeline_instance.run_inference_for_quake_experiment( + quake_idx=quake_idx_instance, + queries_torch=queries_all, + gt_torch=gt_all, + target_recall=recall_target_val, + k_search=k_val, + base_quake_sp=common_utils.create_search_params(k=k_val), # Pass k here ) - tuning_ns = laet_training_ns + (time.perf_counter_ns() - t0) - per_query.append((mean_np, mean_rec, mean_ms)) + # For LAET, tuning_ns includes GBDT training + multiplier search + current_tuning_ns = laet_training_total_ns + (time.perf_counter_ns() - t_infer_start_ns) + query_results_list.append((mean_np, mean_rec, mean_ms)) # Store averages else: - logger.warning(f"Unknown method '{method}' – skipping.") + logger.warning(f"Unknown method '{method_name}' – skipping.") continue - # ---------------------------------------------------------------- # - if not per_query: - continue - arr = np.asarray(per_query, dtype=float) - mean_np, mean_rec, mean_q_ms = np.nanmean(arr, axis=0) - - records.append( - dict( - Method=method, - RecallTarget=rt, - RecallAchieved=mean_rec, - nprobe=mean_np, - QueryLatencyMs=mean_q_ms, - TuningTimeMs=tuning_ns / 1e6, - ) - ) + if not query_results_list: continue - # 6) ------------------------------------------------------------- results - df = pd.DataFrame(records) - df_out = df[df["RecallTarget"].isin(table_targets)].copy().sort_values( + # logger.info(f"Method={method} RecallTarget={rt}, Recall={mean_recall:.4f} (std={std_recall:.4f}), " + # f"Time={mean_time_ms:.2f}ms (std={std_time_ms:.2f}ms), NProbe={mean_nprobe:.1f} (std={std_nprobe:.1f})") + + logger.info(f"Method={method_name} RecallTarget={recall_target_val:.2f}, " + f"Recall={np.mean([r for _, r, _ in query_results_list]):.4f}, " + f"Query Latency={np.mean([t for _, _, t in query_results_list]):.2f}ms, " + f"NProbe={np.mean([n for n, _, _ in query_results_list]):.1f}, " + f"Tuning Time={current_tuning_ns / 1e6:.1f}ms") + + arr = np.asarray(query_results_list, dtype=float) + if arr.shape[0] == 1 and method_name == "LAET": # LAET already returns mean values + mean_nprobe_val, mean_recall_val, mean_q_ms_val = arr[0,0], arr[0,1], arr[0,2] + std_nprobe_val, std_recall_val, std_q_ms_val = np.nan, np.nan, np.nan # Stdev not applicable for pre-averaged + else: + mean_nprobe_val = np.nanmean(arr[:,0]) + std_nprobe_val = np.nanstd(arr[:,0]) + mean_recall_val = np.nanmean(arr[:,1]) + std_recall_val = np.nanstd(arr[:,1]) + mean_q_ms_val = np.nanmean(arr[:,2]) + std_q_ms_val = np.nanstd(arr[:,2]) + + + experiment_records.append(dict( + Method=method_name, RecallTarget=recall_target_val, + RecallAchieved=mean_recall_val, nprobe=mean_nprobe_val, + QueryLatencyMs=mean_q_ms_val, TuningTimeMs=current_tuning_ns / 1e6, + StdRecall=std_recall_val, StdNprobe=std_nprobe_val, StdQueryLatencyMs=std_q_ms_val + )) + + df_results = pd.DataFrame(experiment_records) + df_output_final = df_results[df_results["RecallTarget"].isin(table_targets_set)].copy().sort_values( ["Method", "RecallTarget"] ) - csv_path = out_dir / f"aps_et_results_{cfg['dataset']['name']}.csv" - df_out.to_csv(csv_path, index=False, float_format="%.4f") - logger.info(f"Results written to {csv_path}") - print_markdown(df_out) - - # 7) ------------------------------------------------------------- plot - if cfg.get("plot", {}).get("enable", False) and _HAVE_MPL: - plt.figure(figsize=(6, 4)) - for m in df["Method"].unique(): - d = df[df["Method"] == m] - plt.plot(d["RecallTarget"], d["QueryLatencyMs"], marker="o", label=m, alpha=0.7) - plt.yscale("log") - plt.xlabel("Recall target") - plt.ylabel("Mean query latency (ms)") - plt.title(cfg["dataset"]["name"]) - plt.legend() - plt.tight_layout() - plt.savefig(out_dir / f"latency_plot_{cfg['dataset']['name']}.png", dpi=200) \ No newline at end of file + + csv_output_path = out_dir / f"aps_et_results_{dataset_cfg['name']}.csv" + common_utils.save_results_csv(df_output_final, csv_output_path) # Use common save + print_markdown(df_output_final) + + if cfg.get("plot", {}).get("enable", False): + plot_path = out_dir / f"et_latency_recall_plot_{dataset_cfg['name']}.png" + common_utils.plot_recall_performance( + df_results, # Plot all results, not just table_targets + x_metric="RecallTarget", + y_metrics=["QueryLatencyMs", "RecallAchieved", "nprobe"], + y_labels=["Mean Query Latency (ms)", "Mean Recall Achieved", "Mean NProbe"], + y_scales=["log", "linear", "log"], # nprobe often benefits from log scale + plot_title_prefix=f"{dataset_cfg['name']} Early Termination", + output_path=plot_path, + recall_targets_for_line=recall_targets_list + ) \ No newline at end of file From 4dab300eb7550388732226941e37b94175f914a4 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 00:51:25 -0500 Subject: [PATCH 197/323] update maintenance ablation --- test/experiments/osdi2025/experiment_utils.py | 98 ++++ .../osdi2025/maintenance_ablation/run.py | 534 +++++++++--------- 2 files changed, 367 insertions(+), 265 deletions(-) diff --git a/test/experiments/osdi2025/experiment_utils.py b/test/experiments/osdi2025/experiment_utils.py index b9091483..0663391a 100644 --- a/test/experiments/osdi2025/experiment_utils.py +++ b/test/experiments/osdi2025/experiment_utils.py @@ -3,6 +3,7 @@ import yaml import logging from pathlib import Path +from typing import Dict, Any import torch import pandas as pd @@ -12,6 +13,7 @@ from quake import QuakeIndex, IndexBuildParams, SearchParams from quake.datasets.ann_datasets import load_dataset as quake_load_dataset from quake.utils import compute_recall as quake_compute_recall +from quake.workload_generator import DynamicWorkloadGenerator, WorkloadEvaluator logger = logging.getLogger(__name__) @@ -72,6 +74,102 @@ def run_search_trial( partitions_scanned = getattr(res.timing_info, "partitions_scanned", np.nan) return partitions_scanned, rec, elapsed_ns / 1e6 # nprobe, recall, time_ms +def generate_dynamic_workload( + dataset_main_cfg: Dict[str, Any], + workload_generator_cfg: Dict[str, Any], + global_output_dir: Path, + overwrite_workload: bool +) -> Path: + """ + Loads dataset and generates the dynamic workload. + Returns the path to the workload directory (which is the global_output_dir). + """ + log = logger # Use the logger defined in common_utils + + log.info(f"Preparing dataset '{dataset_main_cfg['name']}' for dynamic workload.") + # Assuming common_utils.load_data is defined elsewhere in experiment_utils.py + base_vectors, query_vectors, _ = load_data( + dataset_main_cfg["name"], dataset_main_cfg.get("path", "") + ) + + log.info("Setting up DynamicWorkloadGenerator.") + generator = DynamicWorkloadGenerator( + workload_dir=global_output_dir, + base_vectors=base_vectors, + metric=dataset_main_cfg["metric"], + insert_ratio=workload_generator_cfg["insert_ratio"], + delete_ratio=workload_generator_cfg["delete_ratio"], + query_ratio=workload_generator_cfg["query_ratio"], + update_batch_size=workload_generator_cfg["update_batch_size"], + query_batch_size=workload_generator_cfg["query_batch_size"], + number_of_operations=workload_generator_cfg["number_of_operations"], + initial_size=workload_generator_cfg["initial_size"], + cluster_size=workload_generator_cfg["cluster_size"], + cluster_sample_distribution=workload_generator_cfg["cluster_sample_distribution"], + queries=query_vectors, + query_cluster_sample_distribution=workload_generator_cfg["query_cluster_sample_distribution"], + seed=workload_generator_cfg["seed"] + ) + + if not generator.workload_exists() or overwrite_workload: + log.info(f"Generating workload in {global_output_dir}...") + generator.generate_workload() + else: + log.info(f"Existing workload found in {global_output_dir} – generation skipped.") + return global_output_dir + + +def evaluate_index_on_dynamic_workload( + index_config: Dict[str, Any], # Single entry from the 'indexes' list in YAML + index_class_mapping: Dict[str, type], # Maps index type string to class (e.g., {"Quake": QuakeWrapper}) + workload_data_dir: Path, # Path where DynamicWorkloadGenerator output (operations, groundtruth) is stored + experiment_main_output_dir: Path, # Base output dir for the whole experiment (e.g., .../maintenance_ablation/results/sift1m/) + overwrite_idx_results: bool, + do_maintenance_flag: bool = False # Specific to experiments that test maintenance +): + """ + Evaluates a single index configuration against a pre-generated dynamic workload. + Results are saved by WorkloadEvaluator in a subdirectory named after the index. + """ + log = logger # Use the logger defined in common_utils + idx_name = index_config["name"] + index_type_str = index_config["index"] + + # Determine the directory for this specific index's results + idx_specific_output_dir = experiment_main_output_dir / idx_name + idx_specific_output_dir.mkdir(parents=True, exist_ok=True) + + per_index_results_csv = idx_specific_output_dir / "results.csv" + + if per_index_results_csv.exists() and not overwrite_idx_results: + log.info(f"Results for {idx_name} exist at {per_index_results_csv} – skipping evaluation.") + return + + log.info(f"Evaluating index configuration: {idx_name} (Type: {index_type_str})") + + index_class_constructor = index_class_mapping.get(index_type_str) + if not index_class_constructor: + log.error(f"Unknown index type '{index_type_str}' in mapping for index '{idx_name}'. Skipping.") + return + + index_instance = index_class_constructor() + + evaluator = WorkloadEvaluator( + workload_dir=workload_data_dir, # Where operation files are located + output_dir=idx_specific_output_dir # Where this index's results.csv will be saved + ) + + evaluator.evaluate_workload( + name=idx_name, + index=index_instance, + build_params=index_config.get("build_params", {}), + search_params=index_config.get("search_params", {}), + m_params=index_config.get("maintenance_params", {}), # Pass maintenance_params + do_maintenance=do_maintenance_flag, + ) + log.info(f"Finished evaluating {idx_name}. Results should be in {idx_specific_output_dir}") + + def save_results_csv(records: list, output_path: Path): df = pd.DataFrame(records) output_path.parent.mkdir(parents=True, exist_ok=True) diff --git a/test/experiments/osdi2025/maintenance_ablation/run.py b/test/experiments/osdi2025/maintenance_ablation/run.py index 0173457b..af274dfb 100644 --- a/test/experiments/osdi2025/maintenance_ablation/run.py +++ b/test/experiments/osdi2025/maintenance_ablation/run.py @@ -1,335 +1,339 @@ #!/usr/bin/env python3 """ -Quake maintenance–ablation runner -───────────────────────────────── -Extends the original “kick-the-tires” driver with: - -1. *summary_table.csv* – cumulative times + final partition count -2. *summary_table.md* – Markdown, via **tabulate** -3. *time_breakdown.png* – stacked bars (unchanged) -4. *unified_plot.png* – nine-panel diagnostic (unchanged) - -Per-index artefacts (under //): - results.csv – per-operation log - time_breakdown.png – per-index stacked bars +Quake Maintenance Policy Ablation Study Runner +─────────────────────────────────────────────── +This experiment evaluates different maintenance policy configurations within Quake +under a dynamic workload involving inserts, deletes, and queries. +It generates detailed reports including: +1. Per-index CSV logs of operations. +2. A 9-panel unified plot comparing various metrics across configurations. +3. A stacked bar chart breaking down cumulative time per operation type. +4. A summary table (CSV and Markdown) of key performance indicators. """ from __future__ import annotations -import argparse import logging from pathlib import Path -from typing import Dict, List +from typing import Dict, List, Any # Added Any for type hinting import matplotlib.pyplot as plt import numpy as np import pandas as pd -import yaml from tabulate import tabulate from matplotlib.cm import get_cmap from matplotlib.lines import Line2D -# ── quake wrappers ------------------------------------------------------------ -from quake.datasets.ann_datasets import load_dataset -from quake.index_wrappers.faiss_ivf import FaissIVF -from quake.index_wrappers.quake import QuakeWrapper -from quake.workload_generator import DynamicWorkloadGenerator, WorkloadEvaluator +# Common utilities +import test.experiments.osdi2025.experiment_utils as common_utils + +# Quake specific imports +from quake.index_wrappers.quake import QuakeWrapper # This experiment only uses QuakeWrapper +# DynamicWorkloadGenerator and WorkloadEvaluator are now used within common_utils helpers primarily logging.basicConfig(level=logging.INFO, format="%(asctime)s | %(levelname)s | %(message)s") log = logging.getLogger(__name__) -# ── constants ----------------------------------------------------------------- +# Constants for plotting remain specific to this experiment's visualization OP_STYLE = { "query": dict(ls="-", marker="o", mfc="none", ms=4, lw=1.2), "insert": dict(ls="-", marker="s", mfc="none", ms=4, lw=1.2), "delete": dict(ls="-", marker="^", mfc="none", ms=4, lw=1.2), "maintain": dict(ls="None", marker="X", mfc="black", ms=5), } - LAT_OPS = ["query", "insert", "delete", "maintain"] IDX_LAT_Q, IDX_LAT_I, IDX_LAT_D, IDX_LAT_M = 0, 1, 2, 3 IDX_PART, IDX_RES, IDX_REC, IDX_TOT, IDX_SPL = 4, 5, 6, 7, 8 -# ══════════════════════════════════════════════════════════════════════════════ -# Plot: unified nine-panel diagnostic -# ══════════════════════════════════════════════════════════════════════════════ -def unified_plot(cfg: Dict, out_dir: Path) -> None: + +def unified_plot(cfg: Dict[str, Any], out_dir: Path) -> None: styles = cfg["plot"].get("styles", {}) fig, axs2d = plt.subplots(3, 3, figsize=(18, 12), sharex="col") axs = axs2d.flatten() - # legend handles ----------------------------------------------------------- idx_handles: List[Line2D] = [] - for j, idx in enumerate(cfg["indexes"]): - nm, st = idx["name"], styles.get(idx["name"], {}) + for j, idx_cfg in enumerate(cfg.get("indexes", [])): # Added .get for safety + nm, st = idx_cfg["name"], styles.get(idx_cfg["name"], {}) idx_handles.append(Line2D([0], [0], - color=st.get("color", f"C{j}"), + color=st.get("color", f"C{j % 10}"), marker=st.get("marker", "o"), ls="", markersize=6, label=nm)) - # traces ------------------------------------------------------------------- - for j, idx in enumerate(cfg["indexes"]): - name = idx["name"] + max_ops_overall = 0 + + for j, idx_cfg in enumerate(cfg.get("indexes", [])): + name = idx_cfg["name"] st = styles.get(name, {}) - colour = st.get("color", f"C{j}") + colour = st.get("color", f"C{j % 10}") marker = st.get("marker", "o") - csv = out_dir / name / "results.csv" - if not csv.exists(): - log.warning("[unified_plot] %s missing – skipped.", csv) + csv_path = out_dir / name / "results.csv" + if not csv_path.exists(): + log.warning("[unified_plot] Results CSV %s missing – skipped for this index.", csv_path) + continue + try: + df = pd.read_csv(csv_path) + if df.empty: + log.warning(f"[unified_plot] Empty CSV: {csv_path}") + continue + if 'operation_number' in df.columns and not df['operation_number'].empty: + max_ops_overall = max(max_ops_overall, df.operation_number.max()) + except pd.errors.EmptyDataError: + log.warning(f"[unified_plot] Could not read or empty CSV: {csv_path}") continue - df = pd.read_csv(csv) - # latency -------------------------------------------------------------- - for op, ax_idx in zip(LAT_OPS, [IDX_LAT_Q, IDX_LAT_I, IDX_LAT_D, IDX_LAT_M]): - ax = axs[ax_idx] + # Latency plots + for op, ax_idx_val in zip(LAT_OPS, [IDX_LAT_Q, IDX_LAT_I, IDX_LAT_D, IDX_LAT_M]): + ax = axs[ax_idx_val] + y_val_series = None if op == "maintain": - sub = df[df.maintenance_time_ms.fillna(0) > 0] - y = sub.maintenance_time_ms - else: + if 'maintenance_time_ms' in df.columns: + sub = df[df.maintenance_time_ms.fillna(0) > 0] + y_val_series = sub.maintenance_time_ms + elif 'operation_type' in df.columns and 'latency_ms' in df.columns: sub = df[df.operation_type == op] - y = sub.latency_ms - if not sub.empty: - ax.plot(sub.operation_number, y, color=colour, **OP_STYLE[op]) - - # partitions ----------------------------------------------------------- - ax = axs[IDX_PART] - sub = df[df.n_list.notna()] - if not sub.empty: - ax.plot(sub.operation_number, sub.n_list, - color=colour, marker=marker, lw=1.2) - - # resident vectors ----------------------------------------------------- - ax = axs[IDX_RES] - sub = df[df.n_resident.notna()] - if not sub.empty: - ax.plot(sub.operation_number, sub.n_resident, - color=colour, marker=marker, lw=1.2) - - # recall --------------------------------------------------------------- - ax = axs[IDX_REC] - sub = df[(df.operation_type == "query") & df.recall.notna()] - if not sub.empty: - ax.plot(sub.operation_number, sub.recall, - color=colour, marker=marker, lw=1.2) - - # running total time --------------------------------------------------- - ax = axs[IDX_TOT] - total_ms = df.latency_ms.fillna(0) + df.maintenance_time_ms.fillna(0) - ax.plot(df.operation_number, np.cumsum(total_ms), - color=colour, marker=marker, lw=1.2) - - # cumulative splits / deletes ----------------------------------------- - ax = axs[IDX_SPL] - spl, dlt = df.n_splits.fillna(0), df.n_deletes.fillna(0) - if (spl > 0).any(): - ax.step(df.operation_number, np.cumsum(spl), - where="post", color=colour, ls="--", lw=1.2) - if (dlt > 0).any(): - ax.step(df.operation_number, np.cumsum(dlt), - where="post", color=colour, ls=":", lw=1.2) - - # titles / grids ----------------------------------------------------------- + y_val_series = sub.latency_ms + + if y_val_series is not None and not y_val_series.empty: + ax.plot(sub.operation_number, y_val_series, color=colour, **OP_STYLE[op]) + + # Other metric plots + plot_specs = [ + (IDX_PART, 'n_list'), (IDX_RES, 'n_resident'), + (IDX_REC, 'recall', lambda d: (d.operation_type == "query") & d.recall.notna()), + (IDX_TOT, 'total_cumulative_time', + lambda d: pd.Series(np.cumsum(d.latency_ms.fillna(0) + d.maintenance_time_ms.fillna(0)), name='total_cumulative_time')), + (IDX_SPL, ['n_splits', 'n_deletes']) # Special handling for splits/deletes + ] + + for spec_item in plot_specs: + ax_idx_val = spec_item[0] + metric_name_or_list = spec_item[1] + condition_func = spec_item[2] if len(spec_item) > 2 else lambda d: d[metric_name_or_list].notna() + + ax = axs[ax_idx_val] + + if ax_idx_val == IDX_TOT: # Cumulative time calculation + if 'latency_ms' in df.columns and 'maintenance_time_ms' in df.columns: + total_ms_series = np.cumsum(df.latency_ms.fillna(0) + df.maintenance_time_ms.fillna(0)) + if not total_ms_series.empty: + ax.plot(df.operation_number, total_ms_series, color=colour, marker=marker, lw=1.2) + continue + + if ax_idx_val == IDX_SPL: # Splits and deletes + if 'operation_number' in df.columns: + spl_series = df.n_splits.fillna(0) if 'n_splits' in df.columns else pd.Series(0, index=df.index) + del_series = df.n_deletes.fillna(0) if 'n_deletes' in df.columns else pd.Series(0, index=df.index) + if not df.empty: + if (spl_series > 0).any(): ax.step(df.operation_number, np.cumsum(spl_series), where="post", color=colour, ls="--", lw=1.2) + if (del_series > 0).any(): ax.step(df.operation_number, np.cumsum(del_series), where="post", color=colour, ls=":", lw=1.2) + continue + + # General case for other plots + if isinstance(metric_name_or_list, str) and metric_name_or_list in df.columns: + sub_df = df[condition_func(df)] + if not sub_df.empty: + ax.plot(sub_df.operation_number, sub_df[metric_name_or_list], color=colour, marker=marker, lw=1.2) + titles = { - IDX_LAT_Q: "Latency – Query", - IDX_LAT_I: "Latency – Insert", - IDX_LAT_D: "Latency – Delete", - IDX_LAT_M: "Latency – Maintain", - IDX_PART: "# Partitions", - IDX_RES: "Resident Vectors", - IDX_REC: "Recall", - IDX_TOT: "Running Total Time", + IDX_LAT_Q: "Latency – Query", IDX_LAT_I: "Latency – Insert", + IDX_LAT_D: "Latency – Delete", IDX_LAT_M: "Latency – Maintain", + IDX_PART: "# Partitions", IDX_RES: "Resident Vectors", + IDX_REC: "Recall", IDX_TOT: "Running Total Time (ms)", IDX_SPL: "Cumulative Splits / Deletes", } - for i, ax in enumerate(axs): - ax.set_title(titles[i], fontsize=11) - ax.grid(alpha=0.25, zorder=0) - ax.set_axisbelow(True) - - axs[IDX_PART].set_ylabel("count") - axs[IDX_RES].set_ylabel("# vectors") - axs[IDX_REC].set_ylabel("recall") - axs[IDX_TOT].set_ylabel("ms") - axs[IDX_SPL].set_ylabel("count") - - for idx in [IDX_PART, IDX_RES, IDX_REC, IDX_TOT, IDX_SPL]: - axs[idx].set_xlabel("Operation #") - - all_ops = max((pd.read_csv(out_dir / idx["name"] / "results.csv").operation_number.max() - for idx in cfg["indexes"] - if (out_dir / idx["name"] / "results.csv").exists()), - default=None) - if all_ops is not None: - for ax in axs: - ax.set_xlim(left=0, right=all_ops) - - fig.legend(idx_handles, - [h.get_label() for h in idx_handles], - loc="upper center", bbox_to_anchor=(0.5, 1.03), + y_labels_map = { + IDX_PART: "Count", IDX_RES: "# Vectors", IDX_REC: "Recall", + IDX_TOT: "Cumulative Time (ms)", IDX_SPL: "Count" + } + for i, ax_val in enumerate(axs): + ax_val.set_title(titles[i], fontsize=11) + ax_val.grid(True, which="both", ls=":", alpha=0.7) + ax_val.set_axisbelow(True) + if i in y_labels_map: ax_val.set_ylabel(y_labels_map[i]) + # Set x-label only for the bottom row of plots + if i // 3 == 2 : ax_val.set_xlabel("Operation #") + + is_latency_plot = i in [IDX_LAT_Q, IDX_LAT_I, IDX_LAT_D, IDX_LAT_M] + if is_latency_plot: ax_val.set_ylabel("Latency (ms)") + + + if max_ops_overall > 0: + for ax_val in axs: + ax_val.set_xlim(left=0, right=max_ops_overall) + + fig.legend(idx_handles, [h.get_label() for h in idx_handles], + loc="upper center", bbox_to_anchor=(0.5, 1.035), ncol=min(4, len(idx_handles)), - fontsize=9, title="Index", frameon=False) - - plt.tight_layout(rect=[0, 0, 1, 0.97]) - out_path = out_dir / "unified_plot.png" - plt.savefig(out_path, dpi=150) - log.info("[unified_plot] → %s", out_path) - plt.close() - -# ══════════════════════════════════════════════════════════════════════════════ -# Plot: stacked-bar time breakdown -# ══════════════════════════════════════════════════════════════════════════════ -def make_time_breakdown(cfg: Dict, out_dir: Path) -> None: + fontsize=9, title="Index Configuration", frameon=False) + + plt.tight_layout(rect=[0, 0.03, 1, 0.97]) + out_plot_path = out_dir / "unified_plot.png" + plt.savefig(out_plot_path, dpi=150) + log.info("Unified plot saved to %s", out_plot_path) + plt.close(fig) + + +def make_time_breakdown(cfg: Dict[str, Any], out_dir: Path) -> None: categories = ["Search", "Insert", "Delete", "Maintain", "Total"] - idx_names = [idx["name"] for idx in cfg["indexes"]] - totals, recalls = {}, {} + totals_data, recall_data = {}, {} cmap = get_cmap("tab10") - for j, idx in enumerate(cfg["indexes"]): - name = idx["name"]; csv_path = out_dir / name / "results.csv" + for j, idx_cfg in enumerate(cfg.get("indexes", [])): + name = idx_cfg["name"] + csv_path = out_dir / name / "results.csv" if not csv_path.exists(): - log.warning("[time_breakdown] missing %s – skipped", csv_path) + log.warning("[time_breakdown] %s missing – skipped", csv_path) + continue + try: + df = pd.read_csv(csv_path) + if df.empty: raise pd.errors.EmptyDataError + except pd.errors.EmptyDataError: + log.warning(f"[time_breakdown] Empty or unreadable CSV: {csv_path}") continue - df = pd.read_csv(csv_path) - totals[name] = [ - df[df.operation_type == "query"].latency_ms.sum(), - df[df.operation_type == "insert"].latency_ms.sum(), - df[df.operation_type == "delete"].latency_ms.sum(), - df.maintenance_time_ms.fillna(0).sum(), + + totals_data[name] = [ + df[df.operation_type == "query"].latency_ms.sum() if 'operation_type' in df.columns else 0, + df[df.operation_type == "insert"].latency_ms.sum() if 'operation_type' in df.columns else 0, + df[df.operation_type == "delete"].latency_ms.sum() if 'operation_type' in df.columns else 0, + df.maintenance_time_ms.fillna(0).sum() if 'maintenance_time_ms' in df.columns else 0, ] - totals[name].append(sum(totals[name])) - recalls[name] = df[df.operation_type == "query"].recall.mean() - - n_idx, n_cats = len(totals), len(categories) - x = np.arange(n_cats); width = 0.8 / max(1, n_idx) - - fig, ax = plt.subplots(figsize=(10, 6)) - for j, (name, values) in enumerate(totals.items()): - style = cfg["plot"].get("styles", {}).get(name, {}) - color = style.get("color", cmap(j % 10)) - x_off = x + (j - (n_idx - 1) / 2) * width - ax.bar(x_off, values, width=width, label=name, - color=color, edgecolor="black") - ax.text(x_off[0], values[0] * 1.01, - f"R={recalls[name]:.3f}", ha="center", - va="bottom", fontsize=7, rotation=90, color=color) - - ax.set_xticks(x); ax.set_xticklabels(categories) - ax.set_ylabel("Cumulative Time (ms)") - ax.set_title("Time Breakdown per Index") - ax.legend(title="Index", frameon=False) + totals_data[name].append(sum(totals_data[name])) + + query_df = df[df.operation_type == "query"] if 'operation_type' in df.columns else pd.DataFrame() + recall_data[name] = query_df.recall.mean() if not query_df.empty and 'recall' in query_df else np.nan + + + if not totals_data: + log.info("[time_breakdown] No data available for time breakdown plot.") + return + + n_idx, n_cats = len(totals_data), len(categories) + x_indices = np.arange(n_cats) + bar_width = 0.8 / max(1, n_idx) + + fig, ax = plt.subplots(figsize=(max(10, n_idx * 1.5 + 2), 6)) + for j, (name, values) in enumerate(totals_data.items()): + style = cfg.get("plot", {}).get("styles", {}).get(name, {}) + color = style.get("color", cmap(j % cmap.N)) + x_offset = x_indices + (j - (n_idx - 1) / 2) * bar_width + ax.bar(x_offset, values, width=bar_width, label=name, color=color, edgecolor="black") + current_recall = recall_data.get(name) + if pd.notna(current_recall) and values[0] > 0: + ax.text(x_offset[0], values[0] * 1.01, f"R={current_recall:.3f}", + ha="center", va="bottom", fontsize=8, rotation=90, color='dimgrey') # Standard color for text + + ax.set_xticks(x_indices) + ax.set_xticklabels(categories, fontsize=10) + ax.set_ylabel("Cumulative Time (ms)", fontsize=10) + ax.set_title("Time Breakdown per Index Configuration", fontsize=12) + ax.legend(title="Index Configuration", frameon=False, fontsize=9) + ax.grid(True, axis='y', linestyle=':', alpha=0.7) plt.tight_layout() - out_path = out_dir / "time_breakdown.png" - plt.savefig(out_path, dpi=150) - log.info("[time_breakdown] → %s", out_path) - plt.close() - -# ══════════════════════════════════════════════════════════════════════════════ -# Summary table (CSV + Markdown) -# ══════════════════════════════════════════════════════════════════════════════ -def produce_summary_table(cfg: Dict, out_dir: Path) -> None: - """ - Write summary_table.csv and summary_table.md with columns: - Index | Search | Insert | Delete | Maintain | Total | Recall | Partitions - Times are cumulative milliseconds; Recall is mean over all queries. - """ + out_plot_path = out_dir / "time_breakdown.png" + plt.savefig(out_plot_path, dpi=150) + log.info("Time breakdown plot saved to %s", out_plot_path) + plt.close(fig) + + +def produce_summary_table(cfg: Dict[str, Any], out_dir: Path) -> None: rows = [] - for idx in cfg["indexes"]: - name = idx["name"] + for idx_cfg in cfg.get("indexes", []): + name = idx_cfg["name"] csv_path = out_dir / name / "results.csv" if not csv_path.exists(): log.warning("[summary_table] %s missing – skipped", csv_path) continue + try: + df = pd.read_csv(csv_path) + if df.empty: raise pd.errors.EmptyDataError + except pd.errors.EmptyDataError: + log.warning(f"[summary_table] Empty or unreadable CSV: {csv_path}") + continue + + search_time = df[df.operation_type == "query"].latency_ms.sum() if 'operation_type' in df.columns else 0 + insert_time = df[df.operation_type == "insert"].latency_ms.sum() if 'operation_type' in df.columns else 0 + delete_time = df[df.operation_type == "delete"].latency_ms.sum() if 'operation_type' in df.columns else 0 + maintain_time = df.maintenance_time_ms.fillna(0).sum() if 'maintenance_time_ms' in df.columns else 0 + total_time = search_time + insert_time + delete_time + maintain_time + + query_df = df[df.operation_type == "query"] if 'operation_type' in df.columns else pd.DataFrame() + recall_val = query_df.recall.mean() if not query_df.empty and 'recall' in query_df else np.nan - df = pd.read_csv(csv_path) - search = df[df.operation_type == "query" ].latency_ms.sum() - insert = df[df.operation_type == "insert"].latency_ms.sum() - delete = df[df.operation_type == "delete"].latency_ms.sum() - maintain = df.maintenance_time_ms.fillna(0).sum() - total = search + insert + delete + maintain - recall = df[df.operation_type == "query"].recall.mean() # ← NEW - n_part = (df.n_list.dropna().iloc[-1] - if not df.n_list.dropna().empty else None) - - rows.append(dict(Index=name, - Search=int(search), - Insert=int(insert), - Delete=int(delete), - Maintain=int(maintain), - Total=int(total), - Recall=f"{recall:.4f}" if pd.notna(recall) else "—", - Partitions=n_part)) + n_list_series = df.n_list.dropna() if 'n_list' in df.columns else pd.Series(dtype=float) # ensure series exists + n_partitions_val = n_list_series.iloc[-1] if not n_list_series.empty else np.nan + + rows.append(dict( + Index=name, Search=int(search_time), Insert=int(insert_time), + Delete=int(delete_time), Maintain=int(maintain_time), Total=int(total_time), + Recall=f"{recall_val:.4f}" if pd.notna(recall_val) else "—", + Partitions=int(n_partitions_val) if pd.notna(n_partitions_val) else "—" + )) if not rows: - log.warning("[summary_table] no data – nothing written") + log.info("[summary_table] No data for summary table.") return - df = pd.DataFrame(rows).sort_values("Index") - - csv_path = out_dir / "summary_table.csv" - df.to_csv(csv_path, index=False) - log.info("[summary_table] → %s", csv_path) - - md_path = out_dir / "summary_table.md" - md = tabulate(df, headers="keys", tablefmt="github", showindex=False) - md_path.write_text(md + "\n") - log.info("[summary_table] → %s", md_path) - log.info("\n%s", md) -# ══════════════════════════════════════════════════════════════════════════════ -# Main orchestration -# ══════════════════════════════════════════════════════════════════════════════ -def run_experiment(cfg_path: str, output_dir: str) -> None: - cfg = yaml.safe_load(Path(cfg_path).read_text()) - out = Path(output_dir).expanduser(); out.mkdir(parents=True, exist_ok=True) - - # 1. dataset & workload ---------------------------------------------------- - if cfg["mode"] in {"build", "run"}: - ds = cfg["dataset"] - vecs, queries, _ = load_dataset(ds["name"], ds.get("path", "")) - gen = DynamicWorkloadGenerator( - workload_dir = out, - base_vectors = vecs, - metric = ds["metric"], - insert_ratio = cfg["workload_generator"]["insert_ratio"], - delete_ratio = cfg["workload_generator"]["delete_ratio"], - query_ratio = cfg["workload_generator"]["query_ratio"], - update_batch_size = cfg["workload_generator"]["update_batch_size"], - query_batch_size = cfg["workload_generator"]["query_batch_size"], - number_of_operations = cfg["workload_generator"]["number_of_operations"], - initial_size = cfg["workload_generator"]["initial_size"], - cluster_size = cfg["workload_generator"]["cluster_size"], - cluster_sample_distribution= cfg["workload_generator"]["cluster_sample_distribution"], - queries = queries, - query_cluster_sample_distribution=cfg["workload_generator"]["query_cluster_sample_distribution"], - seed = cfg["workload_generator"]["seed"]) - if not gen.workload_exists() or cfg["overwrite"].get("workload", False): - log.info("Generating workload …") - gen.generate_workload() - else: - log.info("Existing workload found – generation skipped.") - - # 2. evaluate -------------------------------------------------------------- - if cfg["mode"] == "run": - for idx in cfg["indexes"]: - name, res = idx["name"], out / idx["name"] - res.mkdir(parents=True, exist_ok=True) - csv = res / "results.csv" - if csv.exists() and not cfg["overwrite"].get("results", False): - log.info("%s: cached results – skipped.", name); continue - - eval = WorkloadEvaluator(workload_dir=out, output_dir=res) - cls = {"Quake": QuakeWrapper, "IVF": FaissIVF}[idx["index"]] - eval.evaluate_workload( - name = name, - index = cls(), - build_params = idx.get("build_params", {}), - search_params = idx.get("search_params", {}), - m_params = idx.get("maintenance_params", {}), - do_maintenance=True, + summary_df = pd.DataFrame(rows).sort_values("Index") + summary_csv_path = out_dir / "summary_table.csv" + common_utils.save_results_csv(summary_df, summary_csv_path) # Use common util + + summary_md_path = out_dir / "summary_table.md" + md_content = tabulate(summary_df, headers="keys", tablefmt="github", showindex=False) + summary_md_path.write_text(md_content + "\n") + log.info("Summary table (Markdown) saved to %s", summary_md_path) + log.info("\n%s", md_content) + + +def run_experiment(cfg_path_str: str, output_dir_str: str) -> None: + cfg = common_utils.load_config(cfg_path_str) + main_output_dir = Path(output_dir_str).expanduser() + main_output_dir.mkdir(parents=True, exist_ok=True) + + current_mode = cfg.get("mode", "run") + log.info(f"Running Maintenance Ablation experiment in mode: {current_mode}") + + workload_actual_dir = main_output_dir # Workload files are stored at the top level of main_output_dir + + # --- Phase 1: Dataset and Workload Generation --- + if current_mode in {"build", "run"}: + workload_actual_dir = common_utils.generate_dynamic_workload( + dataset_main_cfg=cfg["dataset"], + workload_generator_cfg=cfg["workload_generator"], + global_output_dir=main_output_dir, # Pass main_output_dir as the place to store workload files + overwrite_workload=cfg["overwrite"].get("workload", False) + ) + + # --- Phase 2: Index Evaluation --- + if current_mode == "run": + log.info("Starting index evaluation phase...") + # For this specific experiment, the index class is always QuakeWrapper + index_class_map = {"Quake": QuakeWrapper} + + for index_conf in cfg.get("indexes", []): + common_utils.evaluate_index_on_dynamic_workload( + index_config=index_conf, + index_class_mapping=index_class_map, + workload_data_dir=workload_actual_dir, # Use the returned/set workload_actual_dir + experiment_main_output_dir=main_output_dir, + overwrite_idx_results=cfg["overwrite"].get("results", False), + do_maintenance_flag=True # This experiment always does maintenance ) - # 3. global artefacts ------------------------------------------------------ - if cfg["mode"] in {"run", "plot"}: - unified_plot(cfg, out) - make_time_breakdown(cfg, out) - produce_summary_table(cfg, out) \ No newline at end of file + # --- Phase 3: Global Artifact Generation --- + if current_mode in {"run", "plot"}: + log.info("Generating global plots and summary tables...") + any_results_exist = any( + (main_output_dir / index_conf["name"] / "results.csv").exists() + for index_conf in cfg.get("indexes", []) + ) + + if any_results_exist: + unified_plot(cfg, main_output_dir) + make_time_breakdown(cfg, main_output_dir) + produce_summary_table(cfg, main_output_dir) + else: + log.warning("No results found to generate plots or summary tables. Skipping this step.") + + log.info("Maintenance Ablation experiment finished for mode: %s", current_mode) \ No newline at end of file From 024f846eac952a5861bb730456ab59e6b2f782c7 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 01:15:33 -0500 Subject: [PATCH 198/323] update maintenance ablation --- .../maintenance_ablation/configs/sift1m.yaml | 106 ++++++++++++++++++ .../osdi2025/maintenance_ablation/run.py | 2 - 2 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 test/experiments/osdi2025/maintenance_ablation/configs/sift1m.yaml diff --git a/test/experiments/osdi2025/maintenance_ablation/configs/sift1m.yaml b/test/experiments/osdi2025/maintenance_ablation/configs/sift1m.yaml new file mode 100644 index 00000000..9e6365a4 --- /dev/null +++ b/test/experiments/osdi2025/maintenance_ablation/configs/sift1m.yaml @@ -0,0 +1,106 @@ +# Ablation experiment on Quake maintenance policy +# ─────────────────────────────────────────────── +mode: run # {build, run, plot} +dataset: + name: sift1m + metric: l2 + path: data + +workload_generator: + recall_target: 0.9 + insert_ratio: 0.3 + delete_ratio: 0.2 + query_ratio: 0.5 + number_of_operations: 1000 + initial_size: 100000 + cluster_size: 1000 + update_batch_size: 10000 + query_batch_size: 1000 + cluster_sample_distribution: skewed + query_cluster_sample_distribution: uniform + seed: 9299 + +# ── six index configurations ───────────────────────────────────────────────── +indexes: + - name: Quake + index: Quake + build_params: {nc: 1000, num_workers: 0} + search_params: {k: 10, recall_target: .9} + maintenance_params: + split_threshold_ns: 50 + delete_threshold_ns: 50 + + - name: Quake-NoReject + index: Quake + build_params: {nc: 1000, num_workers: 0} + search_params: {k: 10, recall_target: .9} + maintenance_params: + enable_split_rejection: false + enable_delete_rejection: false + split_threshold_ns: 50 + delete_threshold_ns: 50 + + - name: Quake-NoRefine + index: Quake + build_params: {nc: 1000, num_workers: 0} + search_params: {k: 10, recall_target: .9} + maintenance_params: + refinement_radius: 0 + split_threshold_ns: 50 + delete_threshold_ns: 50 + + - name: Quake-NoRefineNoReject + index: Quake + build_params: {nc: 1000, num_workers: 0} + search_params: {k: 10, recall_target: .9} + maintenance_params: + refinement_radius: 0 + enable_split_rejection: false + enable_delete_rejection: false + split_threshold_ns: 50 + delete_threshold_ns: 50 + + - name: Quake-NoCost + index: Quake + build_params: {nc: 1000, num_workers: 0} + search_params: {k: 10, recall_target: .9} + maintenance_params: + max_partition_size: 2000 + + - name: Quake-NoCostNoRefine + index: Quake + build_params: {nc: 1000, num_workers: 0} + search_params: {k: 10, recall_target: .9} + maintenance_params: + refinement_radius: 0 + max_partition_size: 2000 + + - name: LIRE + index: Quake + build_params: {nc: 1000, num_workers: 0} + search_params: {k: 10, recall_target: .9} + maintenance_params: + refinement_iterations: 0 + max_partition_size: 2000 + +plot: + x_axis: operation_number + metrics: [latency_ms, recall] + styles: + Quake: {color: "#1f77b4", linestyle: "-", marker: "o"} + Quake-NoReject: {color: "#2ca02c", linestyle: "-", marker: "v"} + Quake-NoRefine: {color: "#9467bd", linestyle: "-", marker: "^"} + Quake-NoRefineNoReject: {color: "#8c564b", linestyle: "-", marker: "s"} + Quake-NoCost: {color: "#d627bb", linestyle: "-", marker: "D"} + Quake-NoCostNoRefine: {color: "#ff7f0e", linestyle: "-", marker: "+"} + Quake-NoRejectSplit: {color: "#7f7f7f", linestyle: "-", marker: "H"} + Quake-NoRejectDelete: {color: "#bcbd22", linestyle: "-", marker: "h"} + Quake-NoRejectNoDelete: {color: "#ffbb78", linestyle: "-", marker: "P"} + Quake-NoRejectNoSplit: {color: "#ffbb78", linestyle: "-", marker: "P"} + + LIRE: {color: "#ffbb78", linestyle: "-", marker: "P"} + +overwrite: + workload: true + index: true + results: true \ No newline at end of file diff --git a/test/experiments/osdi2025/maintenance_ablation/run.py b/test/experiments/osdi2025/maintenance_ablation/run.py index af274dfb..4667d458 100644 --- a/test/experiments/osdi2025/maintenance_ablation/run.py +++ b/test/experiments/osdi2025/maintenance_ablation/run.py @@ -28,13 +28,11 @@ # Quake specific imports from quake.index_wrappers.quake import QuakeWrapper # This experiment only uses QuakeWrapper -# DynamicWorkloadGenerator and WorkloadEvaluator are now used within common_utils helpers primarily logging.basicConfig(level=logging.INFO, format="%(asctime)s | %(levelname)s | %(message)s") log = logging.getLogger(__name__) -# Constants for plotting remain specific to this experiment's visualization OP_STYLE = { "query": dict(ls="-", marker="o", mfc="none", ms=4, lw=1.2), "insert": dict(ls="-", marker="s", mfc="none", ms=4, lw=1.2), From 2a4191a5670dd84986e76ec0d0069c03bc93410f Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 02:06:31 -0500 Subject: [PATCH 199/323] update multi_query experiment --- src/cpp/src/query_coordinator.cpp | 20 +- .../numa_multi_query/configs/sift1m.yaml | 7 +- .../osdi2025/numa_multi_query/run.py | 456 +++++++++--------- 3 files changed, 248 insertions(+), 235 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 7f3c0611..c831e108 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -452,25 +452,25 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, } } else { - std::unordered_map>> per_partition_query_ids; // for batched scan -// ska::flat_hash_map> per_partition_query_ids_map; - + std::unordered_map>>> per_partition_query_ids; // for batched scan for (int64_t q = 0; q < nQ; q++) { for (int64_t p = 0; p < partition_ids.size(1); p++) { int64_t pid = pid_acc[q][p]; if (pid < 0) continue; if (per_partition_query_ids[pid] == nullptr) { - per_partition_query_ids[pid] = make_shared>(); + per_partition_query_ids[pid] = make_shared>>(); } - per_partition_query_ids[pid]->push_back(q); + per_partition_query_ids[pid]->push_back({q, p}); } } for (auto &kv : per_partition_query_ids) { - auto qids = kv.second; - vector ranks(qids->size()); - for (size_t i = 0; i < qids->size(); ++i) { - ranks[i] = i; + auto qids_and_ranks = kv.second; + vector qids(qids_and_ranks->size()); + vector ranks(qids_and_ranks->size()); + for (size_t i = 0; i < qids_and_ranks->size(); ++i) { + qids[i] = (*qids_and_ranks)[i].first; + ranks[i] = (*qids_and_ranks)[i].second; } ScanJob job; @@ -479,7 +479,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, job.k = params->k; job.query_vector = x.data_ptr(); job.num_queries = kv.second->size(); - job.query_ids = qids; + job.query_ids = make_shared>(qids); job.ranks = make_shared>(ranks); int core_id = partition_manager_->get_partition_core_id(kv.first); if (core_id < 0) { diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index 96886fc5..60c0c558 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -1,12 +1,13 @@ # numa_latency_experiment.yaml dataset: name: sift1m - num_queries: 10000 + num_queries: 1000 k: 100 trials: 3 warmup: 1 -overwrite: true # Set to true to force all indexes to rerun +overwrite: false # Set to true to force all indexes to rerun +force_rebuild: false # Set to true to force all indexes to rebuild indexes: - name: Quake_0 @@ -26,7 +27,7 @@ indexes: nc: 1000 metric: l2 num_workers: 1 - parent_num_workers: 1 + parent_num_workers: 0 use_numa: false search_params: nprobe: 20 diff --git a/test/experiments/osdi2025/numa_multi_query/run.py b/test/experiments/osdi2025/numa_multi_query/run.py index 9c798d36..c447c066 100644 --- a/test/experiments/osdi2025/numa_multi_query/run.py +++ b/test/experiments/osdi2025/numa_multi_query/run.py @@ -1,27 +1,28 @@ #!/usr/bin/env python3 """ -NUMA Batch-Query Latency and Recall Benchmark (with detailed child/parent timers) +NUMA Multi-Query Batch Performance Benchmark +─────────────────────────────────────────── +Benchmarks Quake (with varying NUMA/worker settings) and other ANN indexes +for batch-query latency, per-phase breakdown (for Quake), and recall@k. +Results are cached. Outputs per-index CSVs, a unified CSV, and plots. -Benchmarks a suite of ANN indexes (Quake, Faiss-IVF, SCANN, HNSW, DiskANN, SVS, etc.) -for batch-query latency, per-phase breakdown, and recall@k under configurable parameters. -Results are cached and only recomputed if 'overwrite' is set. -Outputs per-index CSVs with detailed timers, a unified CSV, and plots. - -Usage: - python numa_latency_batch_experiment.py nna_latency_experiment.yaml output_dir +This script tests how different configurations handle batches of queries, +focusing on Quake's behavior with NUMA-awareness and threading for parallel +processing of queries or internal operations. """ -import sys +import logging # Standard library logging from pathlib import Path -import yaml import numpy as np -torch = None import torch import pandas as pd import matplotlib.pyplot as plt -from time import time +# time.time() is still used for the benchmark loop due to its specificity. + +# Common utilities +import test.experiments.osdi2025.experiment_utils as common_utils -from quake.utils import compute_recall -from quake.datasets.ann_datasets import load_dataset +# Quake specific imports +from quake.utils import compute_recall # compute_recall remains useful from quake.index_wrappers.faiss_ivf import FaissIVF from quake.index_wrappers.faiss_hnsw import FaissHNSW from quake.index_wrappers.quake import QuakeWrapper @@ -46,221 +47,232 @@ "SCANN": Scann, "HNSW": FaissHNSW, "DiskANN": DiskANNDynamic, - "SVS": Vamana, + "SVS": Vamana, # Assuming Vamana is the class for "SVS" } +# Setup logging (can be centralized in common_utils or main runner if preferred) +logging.basicConfig(level=logging.INFO, + format="%(asctime)s | %(levelname)7s | %(name)s | %(message)s", + datefmt="%H:%M:%S") +logger = logging.getLogger("numa_multi_query_exp") + + +def run_experiment(cfg_path_str: str, output_dir_str: str): + cfg = common_utils.load_config(cfg_path_str) + + dataset_cfg = cfg["dataset"] + num_queries_to_use = dataset_cfg["num_queries"] + k_val = dataset_cfg["k"] + + num_trials = cfg.get("trials", 5) + num_warmup = cfg.get("warmup", 1) # Reduced default warmup, can be configured + indexes_config_list = cfg["indexes"] + output_csv_name = cfg.get("output", {}).get("results_csv", "numa_multi_query_results.csv") + force_overwrite = cfg.get("overwrite", False) + force_rebuild = cfg.get("force_rebuild", False) + + main_output_dir = Path(output_dir_str) + main_output_dir.mkdir(parents=True, exist_ok=True) + + logger.info(f"Loading dataset '{dataset_cfg['name']}'...") + # Use common_utils.load_data, pass num_queries_to_use for slicing + base_vectors, query_vectors, gt_vectors = common_utils.load_data( + dataset_cfg["name"], + dataset_path="", # Assuming load_data handles default path or it's in dataset_cfg + nq_override=num_queries_to_use + ) + + # --- Build shared Quake base index once (specific to this experiment script) --- + quake_base_build_params = None + shared_quake_index_file = main_output_dir / "Quake_shared_base_index.bin" # More descriptive name -def build_and_save_index(index_class, build_params, base_vecs, index_file): - """Build and save an index to disk.""" - idx = index_class() - idx.build(base_vecs, **build_params) - idx.save(str(index_file)) - - -def extract_ids(res): - """Normalize returned prediction IDs to a NumPy array.""" - if hasattr(res, "ids"): - arr = res.ids - elif hasattr(res, "I"): - arr = res.I - elif hasattr(res, "indices"): - arr = res.indices - else: - raise RuntimeError("Cannot extract predicted indices from search result.") - if isinstance(arr, torch.Tensor): - arr = arr.cpu().numpy() - return np.asarray(arr) - - -def run_experiment(cfg_path: str, output_dir: str): - cfg = yaml.safe_load(Path(cfg_path).read_text()) - ds = cfg["dataset"] - queries_n = ds["num_queries"] - k = ds["k"] - trials = cfg.get("trials", 5) - warmup = cfg.get("warmup", 10) - indexes_cfg = cfg["indexes"] - csv_name = cfg.get("output", {}).get("results_csv", "numa_results.csv") - overwrite = cfg.get("overwrite", False) - - out_dir = Path(output_dir) - out_dir.mkdir(parents=True, exist_ok=True) - - print(f"[INFO] Loading dataset '{ds['name']}'...") - base_vecs, queries, gt = load_dataset(ds["name"]) - queries = queries[:queries_n] - gt = gt[:queries_n] if gt is not None else None - - # --- Build shared Quake base index once --- - quake_base_params = None - quake_base_index_file = out_dir / "Quake_base_index.bin" - for idx_cfg in indexes_cfg: - if idx_cfg["index"] == "Quake": - quake_base_params = dict(idx_cfg.get("build_params", {})) - quake_base_params.pop("num_workers", None) - quake_base_params.pop("use_numa", None) + for idx_c in indexes_config_list: + if idx_c["index"] == "Quake": + # These are params for the *base* index, stripped of worker/NUMA specifics + quake_base_build_params = {k: v for k, v in idx_c.get("build_params", {}).items() + if k not in ["num_workers", "use_numa", "parent_num_workers"]} break - if quake_base_params and not quake_base_index_file.exists(): - print(f"[BUILD] Quake (shared) base index ...") - build_and_save_index(QuakeWrapper, quake_base_params, base_vecs, quake_base_index_file) - print(f"[SAVE] Quake base index saved at {quake_base_index_file}") - - all_rows = [] - - for idx_cfg in indexes_cfg: - name = idx_cfg["name"] - idx_type = idx_cfg["index"] - build_params = dict(idx_cfg.get("build_params", {})) - search_params= dict(idx_cfg.get("search_params", {})) - IndexClass = INDEX_CLASSES.get(idx_type) - if IndexClass is None: - print(f"[WARN] Unknown index type: {idx_type}. Skipping.") + + if quake_base_build_params: + if not shared_quake_index_file.exists() or force_rebuild: # Respect overwrite for base index too + logger.info(f"Building shared Quake base index at {shared_quake_index_file}...") + # Using common_utils.prepare_index for this specialized build. + # It requires IndexClass, build_params, base_vectors, path, force_rebuild. + common_utils.prepare_index( + IndexClass=QuakeWrapper, + index_build_params=quake_base_build_params, + base_vectors=base_vectors, + index_file_path=shared_quake_index_file, + force_rebuild=force_rebuild, # Force rebuild if top-level overwrite is true + save_after_build=True + ) + logger.info(f"Shared Quake base index saved at {shared_quake_index_file}") + else: + logger.info(f"Using existing shared Quake base index from {shared_quake_index_file}") + + all_experiment_rows = [] + + for idx_conf in indexes_config_list: + index_name = idx_conf["name"] + index_type_str = idx_conf["index"] + current_build_params = dict(idx_conf.get("build_params", {})) + current_search_params = dict(idx_conf.get("search_params", {})) + + IndexCls = INDEX_CLASSES.get(index_type_str) + if IndexCls is None or (IndexCls == Scann and Scann is None): # Handle optional Scann + logger.warning(f"Index type '{index_type_str}' for '{index_name}' is not available or unknown. Skipping.") continue - idx_csv = out_dir / f"{name}_results.csv" - idx_file = quake_base_index_file if idx_type == "Quake" else out_dir / f"{name}_index.bin" + per_index_csv_path = main_output_dir / f"{index_name}_results.csv" - if idx_csv.exists() and not overwrite: - print(f"[SKIP] {name}: Results exist. Use overwrite: true to rerun.") - all_rows.append(pd.read_csv(idx_csv).iloc[0].to_dict()) + # Determine actual index file path (shared for Quake, specific for others) + actual_index_file_path = shared_quake_index_file if index_type_str == "Quake" else main_output_dir / f"{index_name}_index.bin" + + if per_index_csv_path.exists() and not force_overwrite: + logger.info(f"Results for {index_name} exist. Use overwrite:true to rerun. Loading cached.") + try: + # Ensure only one row is taken if multiple exist from partial runs. + cached_df = pd.read_csv(per_index_csv_path) + if not cached_df.empty: + all_experiment_rows.append(cached_df.iloc[0].to_dict()) + except Exception as e: + logger.error(f"Could not load cached results for {index_name} from {per_index_csv_path}: {e}") continue - # Build non-Quake if necessary - if idx_type != "Quake" and not idx_file.exists(): - print(f"[BUILD] {name} index...") - build_and_save_index(IndexClass, build_params, base_vecs, idx_file) - print(f"[SAVE] Index saved at {idx_file}") - - # Load index - if idx_type == "Quake": - load_kwargs = {k: build_params[k] for k in ("use_numa","num_workers", "parent_num_workers") if k in build_params} - idx = QuakeWrapper(); idx.load(str(idx_file), **load_kwargs) - elif idx_type == "DiskANN": - idx = IndexClass(); build_params.pop("metric", None); idx.load(str(idx_file), **build_params) - else: - idx = IndexClass(); idx.load(str(idx_file)) - - # Warmup (batch) - for _ in range(min(warmup,1)): - idx.search(queries, k, **search_params) - - # Prepare per-phase accumulators - child_buf_init_trials = [] - child_copy_query_trials = [] - child_enqueue_trials = [] - child_wait_trials = [] - child_agg_trials = [] - child_total_trials = [] - parent_buf_init_trials= [] - parent_copy_query_trials = [] - parent_enqueue_trials = [] - parent_wait_trials = [] - parent_agg_trials = [] - parent_total_trials = [] - recall_trials = [] - - # Benchmark Trials (batch) - for t in range(trials): - res = idx.search(queries, k, **search_params) - ti = res.timing_info - - # Child (worker_scan) timings - child_buf_init_trials.append(ti.buffer_init_time_ns / 1e6) - child_copy_query_trials.append(ti.copy_query_time_ns / 1e6) - child_enqueue_trials .append(ti.job_enqueue_time_ns / 1e6) - child_wait_trials .append(ti.job_wait_time_ns / 1e6) - child_agg_trials .append(ti.result_aggregate_time_ns / 1e6) - child_total_trials .append(ti.total_time_ns / 1e6) - - # Parent timings - pi = getattr(ti, "parent_info", None) - if pi: - parent_buf_init_trials.append(pi.buffer_init_time_ns / 1e6) - parent_copy_query_trials.append(pi.copy_query_time_ns / 1e6) - parent_enqueue_trials .append(pi.job_enqueue_time_ns / 1e6) - parent_wait_trials .append(pi.job_wait_time_ns / 1e6) - parent_agg_trials .append(pi.result_aggregate_time_ns / 1e6) - parent_total_trials .append(pi.total_time_ns / 1e6) - else: - parent_buf_init_trials.append(0.0) - parent_copy_query_trials.append(0.0) - parent_enqueue_trials .append(0.0) - parent_wait_trials .append(0.0) - parent_agg_trials .append(0.0) - parent_total_trials .append(0.0) - - # Recall for this trial - if gt is not None: - preds_arr = extract_ids(res) - recall = float(compute_recall(preds_arr, gt, k).mean()) - recall_trials.append(recall) - print(f" [{name} trial {t+1}/{trials}] child_total={child_total_trials[-1]:.2f} ms, parent_total={parent_total_trials[-1]:.2f} ms | recall@{k} {recall:.4f}") - else: - print(f" [{name} trial {t+1}/{trials}] child_total={child_total_trials[-1]:.2f} ms, parent_total={parent_total_trials[-1]:.2f} ms") - - # Aggregate metrics - mean_lat = float(np.mean(child_total_trials)) - std_lat = float(np.std(child_total_trials)) - mean_recall= float(np.mean(recall_trials)) if recall_trials else np.nan - n_workers = build_params.get("num_workers", None) - - row = { - "index": name, - "n_workers": n_workers, - f"recall_at_{k}": mean_recall, - "mean_latency_ms": mean_lat, - "std_latency_ms": std_lat, - "child_buffer_init_ms":float(np.mean(child_buf_init_trials)), - "child_copy_query_ms": float(np.mean(child_copy_query_trials)), - "child_enqueue_ms": float(np.mean(child_enqueue_trials)), - "child_wait_ms": float(np.mean(child_wait_trials)), - "child_aggregate_ms": float(np.mean(child_agg_trials)), - "child_total_ms": float(np.mean(child_total_trials)), - "parent_buffer_init_ms":float(np.mean(parent_buf_init_trials)), - "parent_copy_query_ms": float(np.mean(parent_copy_query_trials)), - "parent_enqueue_ms": float(np.mean(parent_enqueue_trials)), - "parent_wait_ms": float(np.mean(parent_wait_trials)), - "parent_aggregate_ms": float(np.mean(parent_agg_trials)), - "parent_total_ms": float(np.mean(parent_total_trials)), + logger.info(f"Processing index: {index_name} (Type: {index_type_str})") + + # Load or build index + idx_instance = None + if index_type_str == "Quake": + if not shared_quake_index_file.exists(): + logger.error(f"Shared Quake base index {shared_quake_index_file} not found for {index_name}. Skipping.") + continue + idx_instance = QuakeWrapper() + # These are load-time parameters for Quake specified in each config entry + quake_load_kwargs = { + k: current_build_params[k] for k in + ("use_numa", "num_workers", "parent_num_workers") if k in current_build_params + } + logger.info(f"Loading Quake index {index_name} from shared base with params: {quake_load_kwargs}") + idx_instance.load(str(shared_quake_index_file), **quake_load_kwargs) + else: # For non-Quake indexes + # DiskANN needs metric popped from build_params before load, if present during build + diskann_load_params = current_build_params.copy() + if index_type_str == "DiskANN": diskann_load_params.pop("metric", None) + + idx_instance = common_utils.prepare_index( + IndexClass=IndexCls, + index_build_params=current_build_params, + base_vectors=base_vectors, # Needed if building + index_file_path=actual_index_file_path, + force_rebuild=force_rebuild, # Rebuild this specific non-Quake index if needed + load_kwargs=diskann_load_params if index_type_str == "DiskANN" else None, + save_after_build=True + ) + + if idx_instance is None: # Should not happen if logic is correct + logger.error(f"Failed to load or build index {index_name}. Skipping.") + continue + + logger.info(f"Warmup for {index_name} ({num_warmup} iterations)...") + for _ in range(num_warmup): # Batched search for warmup + _ = idx_instance.search(query_vectors, k_val, **current_search_params) + + # Benchmark Trials (batch search) + trial_timings = { + "child_total_ms": [], "parent_total_ms": [], "recall": [], + "child_buffer_init_ms": [], "child_copy_query_ms": [], "child_enqueue_ms": [], + "child_wait_ms": [], "child_aggregate_ms": [], + "parent_buffer_init_ms": [], "parent_copy_query_ms": [], "parent_enqueue_ms": [], + "parent_wait_ms": [], "parent_aggregate_ms": [] } - all_rows.append(row) - pd.DataFrame([row]).to_csv(idx_csv, index=False) - - # Save unified CSV - df = pd.DataFrame(all_rows) - out_csv = out_dir / csv_name - df.to_csv(out_csv, index=False) - print(f"\n[RESULT] Results written to {out_csv}") - - # Plot batch total latency (child only) - plt.figure() - for idx_name in df["index"].unique(): - sub = df[df["index"]==idx_name] - label = f"{idx_name}" if pd.isna(sub["n_workers"]).all() else f"{idx_name} (n_workers={int(sub['n_workers'].iloc[0])})" - plt.errorbar( - sub["n_workers"], sub["child_total_ms"], - yerr=sub["child_total_ms"].std(), - marker="o", capsize=5, label=label - ) - plt.xscale("symlog", base=2) - plt.xlabel("Num Workers") - plt.ylabel("Mean Child Batch Latency (ms)") - plt.title("Batch Query Child Total Latency") - plt.legend(); plt.tight_layout() - plt.savefig(out_dir / f"{out_csv.stem}_batch_latency.png") - print(f"[PLOT] Saved to {out_dir / f'{out_csv.stem}_batch_latency.png'}") - - # Plot recall - if f"recall_at_{k}" in df.columns: - plt.figure() - for idx_name in df["index"].unique(): - sub = df[df["index"]==idx_name] - label = f"{idx_name}" if pd.isna(sub["n_workers"]).all() else f"{idx_name} (n_workers={int(sub['n_workers'].iloc[0])})" - plt.plot(sub["n_workers"], sub[f"recall_at_{k}"], marker="o", label=label) - plt.xscale("symlog", base=2) - plt.xlabel("Num Workers") - plt.ylabel(f"Recall@{k}") - plt.title(f"Recall@{k} (batch)") - plt.legend(); plt.tight_layout() - plt.savefig(out_dir / f"{out_csv.stem}_batch_recall.png") - print(f"[PLOT] Recall plot saved to {out_dir / f'{out_csv.stem}_batch_recall.png'}") \ No newline at end of file + + logger.info(f"Running benchmark for {index_name} ({num_trials} trials)...") + for t_idx in range(num_trials): + search_result = idx_instance.search(query_vectors, k_val, **current_search_params) + timing_info = search_result.timing_info # Assuming this is always present for Quake + + # Collect detailed timings if available (primarily for Quake) + for key in trial_timings: + if key.startswith("child_") and hasattr(timing_info, key.replace("_ms", "_time_ns").replace("child_", "")): + trial_timings[key].append(getattr(timing_info, key.replace("_ms", "_time_ns").replace("child_", "")) / 1e6) + elif key.startswith("parent_") and hasattr(timing_info, "parent_info") and timing_info.parent_info: + parent_attr_name = key.replace("_ms", "_time_ns").replace("parent_", "") + if hasattr(timing_info.parent_info, parent_attr_name): + trial_timings[key].append(getattr(timing_info.parent_info, parent_attr_name) / 1e6) + else: + trial_timings[key].append(0.0) # Parent info might not have all fields + elif key == "recall" and gt_vectors is not None: + pred_ids = search_result.ids + current_recall = float(compute_recall(pred_ids, gt_vectors, k_val).mean()) + trial_timings["recall"].append(current_recall) + + log_msg_trial = f" [{index_name} trial {t_idx+1}/{num_trials}] " + if trial_timings["child_total_ms"]: log_msg_trial += f"child_total={trial_timings['child_total_ms'][-1]:.2f}ms " + if trial_timings["parent_total_ms"] and trial_timings['parent_total_ms'][-1] > 0: log_msg_trial += f"parent_total={trial_timings['parent_total_ms'][-1]:.2f}ms " + if trial_timings["recall"]: log_msg_trial += f"| recall@{k_val}={trial_timings['recall'][-1]:.4f}" + logger.info(log_msg_trial) + + + # Aggregate metrics from trials + final_row = {"index": index_name, "n_workers": current_build_params.get("num_workers")} + for key, values in trial_timings.items(): + if values: + final_row[f"mean_{key}"] = float(np.mean(values)) + final_row[f"std_{key}"] = float(np.std(values)) + else: # Handle cases where timings might not be available (e.g. non-Quake, or no GT) + final_row[f"mean_{key}"] = np.nan + final_row[f"std_{key}"] = np.nan + + # Rename for CSV consistency if needed, e.g., mean_child_total_ms to mean_latency_ms + if "mean_child_total_ms" in final_row: + final_row["mean_latency_ms"] = final_row.pop("mean_child_total_ms") + if "std_child_total_ms" in final_row: + final_row["std_latency_ms"] = final_row.pop("std_child_total_ms") + if f"mean_recall" in final_row: # Ensure recall key matches expected format + final_row[f"recall_at_{k_val}"] = final_row.pop(f"mean_recall") + if f"std_recall" in final_row: # std for recall might not be needed in final summary + final_row.pop(f"std_recall") + + + all_experiment_rows.append(final_row) + common_utils.save_results_csv(pd.DataFrame([final_row]), per_index_csv_path) # Save per-index + + # Save unified CSV for all indexes + if not all_experiment_rows: + logger.warning("No results collected. Skipping final CSV and plots.") + return + + final_df = pd.DataFrame(all_experiment_rows) + unified_csv_path = main_output_dir / output_csv_name + common_utils.save_results_csv(final_df, unified_csv_path) + logger.info(f"Unified results written to {unified_csv_path}") + + # Plotting (remains specific to this experiment's needs) + plot_suffix = Path(output_csv_name).stem + + # Plot 1: Batch total latency (child_total_ms) vs. Num Workers + if "mean_latency_ms" in final_df.columns and "n_workers" in final_df.columns: + plt.figure(figsize=(8,6)) + for idx_name_plot in final_df["index"].unique(): + subset = final_df[final_df["index"] == idx_name_plot].sort_values(by="n_workers") + label = idx_name_plot # Simplified label + yerr_values = subset["std_latency_ms"] if "std_latency_ms" in subset else None + plt.errorbar( + subset["n_workers"].astype(int), + subset["mean_latency_ms"], + yerr=yerr_values, + marker="o", capsize=4, label=label, alpha=0.8, linestyle='-' + ) + # plt.xscale("symlog", base=2) # May not be ideal if n_workers are not powers of 2 or include 0 + plt.xlabel("Num Workers (Configuration)") + plt.ylabel(f"Mean Batch Query Latency (ms) - Child Total") + plt.title(f"NUMA Multi-Query: Latency vs. Num Workers ({dataset_cfg['name']})") + plt.legend(title="Index Configuration", bbox_to_anchor=(1.05, 1), loc='upper left') + plt.grid(True, linestyle=':', alpha=0.7) + plt.tight_layout(rect=[0,0,0.8,1]) # Adjust for legend + plt.savefig(main_output_dir / f"{plot_suffix}_batch_latency.png", dpi=150) + logger.info(f"Latency plot saved to {main_output_dir / f'{plot_suffix}_batch_latency.png'}") + plt.close() + + logger.info("NUMA Multi-Query experiment finished.") \ No newline at end of file From 1c939845e2fe411a3550a17afaf110aacdf96c77 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 10:14:36 -0500 Subject: [PATCH 200/323] update vary_levels --- src/cpp/include/list_scanning.h | 39 +- test/experiments/osdi2025/experiment_utils.py | 18 +- .../osdi2025/vary_levels/configs/sift10m.yaml | 144 ++-- test/experiments/osdi2025/vary_levels/run.py | 626 ++++++++++++------ 4 files changed, 542 insertions(+), 285 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index de7fa263..37dfafe4 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -49,14 +49,17 @@ class TypedTopKBuffer { bool is_desc_; int *ord_; bool owns_memory_ = true; + int node_; TypedTopKBuffer(int k, bool desc, int cap, int node) : capacity_(cap), head_(0), k_(k) { - vals_ = static_cast(quake_alloc(sizeof(T) * cap, node)); - ids_ = static_cast(quake_alloc(sizeof(I) * cap, node)); - ord_ = static_cast(quake_alloc(sizeof(int) * cap, node)); + node_ = node; + + alloc(); if (capacity_ < k_) { - throw std::invalid_argument("capacity must be greater than k"); + string err_msg = "capacity= " + std::to_string(capacity_) + + " must be greater than k= " + std::to_string(k_); + throw std::invalid_argument(err_msg); } if (desc) { @@ -103,6 +106,26 @@ class TypedTopKBuffer { } ~TypedTopKBuffer() { + clear(); + } + + void set_k(int new_k) { + if (new_k > capacity_) { + clear(); + capacity_ = std::min(new_k * 100, 10000); + alloc(); + } + k_ = new_k; + reset(); + } + + void alloc() { + vals_ = static_cast(quake_alloc(sizeof(T) * capacity_, node_)); + ids_ = static_cast(quake_alloc(sizeof(I) * capacity_, node_)); + ord_ = static_cast(quake_alloc(sizeof(int) * capacity_, node_)); + } + + void clear() { if (owns_memory_) { if (vals_) { quake_free(vals_, sizeof(T) * capacity_); @@ -122,14 +145,6 @@ class TypedTopKBuffer { ord_ = nullptr; } - void set_k(int new_k) { - if (new_k > capacity_) { - throw std::invalid_argument("k must be less than the capacity"); - } - k_ = new_k; - reset(); - } - void reset() { head_ = 0; for (int i = 0; i < k_; i++) { diff --git a/test/experiments/osdi2025/experiment_utils.py b/test/experiments/osdi2025/experiment_utils.py index 0663391a..f18a75b1 100644 --- a/test/experiments/osdi2025/experiment_utils.py +++ b/test/experiments/osdi2025/experiment_utils.py @@ -3,7 +3,7 @@ import yaml import logging from pathlib import Path -from typing import Dict, Any +from typing import Dict, Any, List import torch import pandas as pd @@ -221,4 +221,18 @@ def plot_recall_performance( output_path.parent.mkdir(parents=True, exist_ok=True) plt.savefig(output_path) logger.info(f"Plot saved to {output_path}") - plt.close(fig) \ No newline at end of file + plt.close(fig) + +def expand_search_sweep(sweep_config: Dict[str, Any]) -> List[Dict[str, Any]]: + """Expands nprobes or recall_targets from sweep_config into individual search dicts.""" + base_params = {k: v for k, v in sweep_config.items() if k not in ["nprobes", "recall_targets"]} + expanded_list = [] + if "nprobes" in sweep_config: + for nprobe_val in sweep_config["nprobes"]: + expanded_list.append({**base_params, "nprobe": nprobe_val}) + elif "recall_targets" in sweep_config: + for rt_val in sweep_config["recall_targets"]: + expanded_list.append({**base_params, "recall_target": rt_val}) + else: # No sweep, just use base_params + expanded_list.append(base_params) + return expanded_list \ No newline at end of file diff --git a/test/experiments/osdi2025/vary_levels/configs/sift10m.yaml b/test/experiments/osdi2025/vary_levels/configs/sift10m.yaml index 76fe00c3..728a35a7 100644 --- a/test/experiments/osdi2025/vary_levels/configs/sift10m.yaml +++ b/test/experiments/osdi2025/vary_levels/configs/sift10m.yaml @@ -1,101 +1,77 @@ # ─── top-level controls ─────────────────────────────────── -mode: run # ignored by new script – kept for compatibility overwrite: - index: false - results: true + index: false # Force rebuild of the base child index (L0) + results: true # Force rerun of searches for all experiment setups # ─── dataset ─────────────────────────────────────────────── dataset: name: sift10m metric: l2 - path: data - nq: 100 + path: data # Path to dataset if not packaged locally + nq: 100 # Number of queries to use for benchmarking -# ─── base index (built once) ─────────────────────────────── -index: - type: Quake +# ─── base child index (L0 - innermost data layer) ────────── +# This index is built once and used as the foundation for all experiment_setups. +child_index_config: + type: Quake # Index type, currently supports Quake build_params: - nc: 40_000 # child level - num_workers: 8 - search_params: - k: 1 + nc: 40000 # Number of centroids for the L0 index + metric: l2 # Metric for L0 (inherited by parents unless overridden, though Quake parents don't typically change metric) + num_workers: 8 # Build workers for L0 index -# ─── parent levels to test ───────────────────────────────── -levels: - - nc: 0 - search_params: - nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -# batched_scan: true -# recall_targets: [.5, .6, .7, .8, .85, .9, .95, .99] -# initial_search_fraction: 0.01 -# aps_flush_period_us: 1 - batch_size: 1 +# ─── global innermost search sweep (applies to L0 search phase) ─── +# Define EITHER nprobes OR recall_targets for the L0 search sweep. +# These parameters are applied to the SearchParams of the L0 layer. +global_innermost_search_sweep: + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] # Option 1: nprobe sweep for L0 +# recall_targets: [0.5, 0.6, 0.7, 0.8, 0.85, 0.9, 0.95, 0.99] # Option 2: recall_target sweep for L0 +# initial_search_fraction: 0.01 # Required if using recall_targets for L0 + k: 1 # k for the L0 search + batch_size: 1 # Query batch size for L0 search + # Other common SearchParams for L0 can be added here. +# ─── experiment setups (different hierarchical configurations) ───── +experiment_setups: + - name: "ChildOnly_L0" + # This setup uses only the base child_index_config. + # additional_levels is empty or omitted. + # Search on L0 is governed by global_innermost_search_sweep. -# - nc: 100 # baseline (keep the index single-level) -# search_params: # ← optional override for the CHILD search -# # nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -# recall_targets: [.5, .6, .7, .8, .85, .9, .95, .99] -# initial_search_fraction: 0.002 -## nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256] -# batch_size: 1 -# parent_search_params: # ← optional params passed to *parent* search -## nprobe: 10 -# recall_target: .999 -# initial_search_fraction: 0.05 -# -# - nc: 500 # 500-centroid parent layer -# search_params: -# # nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -# recall_targets: [.5, .6, .7, .8, .85, .9, .95, .99] -# initial_search_fraction: 0.002 -# batch_size: 1 -# parent_search_params: # ← optional params passed to *parent* search -## nprobe: 15 -# recall_target: .999 -# initial_search_fraction: 0.05 + - name: "L0_plus_L1_Parent1k_PScan50" + additional_levels: # Levels added ON TOP of the base child_index (L0) + - type: Quake # Describes L1 (parent of L0) + build_params: # How to build this L1 layer + nc: 1000 + num_workers: 4 # Build workers for this L1 layer + search_params: # How to search this L1 layer (when it's acting as parent of L0) + nprobe: 50 + num_workers: 4 # Search workers for this L1 layer's scan + use_numa: true # NUMA setting for this L1 layer's scan - - nc: 1_000 - search_params: - nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -# batched_scan: true -# recall_targets: [.5, .6, .7, .8, .85, .9, .95, .99] -# initial_search_fraction: 0.01 - batch_size: 1 - parent_search_params: # ← optional params passed to *parent* search - nprobe: 50 -# batched_scan: true -# recall_target: .999 -# initial_search_fraction: 0.05 + - name: "L0_plus_L1_Parent5k_PScan100" + additional_levels: + - type: Quake # L1 + build_params: {nc: 5000, num_workers: 8} + search_params: {nprobe: 100, num_workers: 8, use_numa: false} -# - nc: 2_000 -# search_params: -# # nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -# recall_targets: [.5, .6, .7, .8, .85, .9, .95, .99] -# initial_search_fraction: 0.01 -# batch_size: 1 -# parent_search_params: # ← optional params passed to *parent* search -# nprobe: 50 -## -# - nc: 4_000 -# search_params: -# nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -## recall_targets: [.5, .6, .7, .8, .85, .9, .95, .99] -## initial_search_fraction: 0.01 -## aps_flush_period_us: 1 -# batch_size: 1 -# parent_search_params: # ← optional params passed to *parent* search -# nprobe: 200 -# recall_target: .999 -# aps_flush_period_us: 1 -# initial_search_fraction: 0.05 + - name: "L0_L1_Parent1k_L2_Parent100_PScan10" + additional_levels: + - type: Quake # L1 (parent of L0) + build_params: {nc: 1000, num_workers: 4} + search_params: {nprobe: 50, num_workers: 4} # Search params for L1 when it's parent of L0 + - type: Quake # L2 (parent of L1) + build_params: {nc: 100, num_workers: 2} + search_params: {nprobe: 10, num_workers: 2} # Search params for L2 when it's parent of L1 + +# ─── common experiment parameters ────────────────────────── +experiment_params: + trials: 3 # Number of timed trials for each search configuration + warmup: 1 # Number of warmup runs before timed trials # ─── plotting (optional) ────────────────────────────────── plot: - styles: - L0: {color: "#1f77b4"} - L100: {color: "#ff7f0e"} - L500: {color: "#ffbb78"} - L1000: {color: "#2ca02c"} - L2000: {color: "#d62728"} - L4000: {color: "#9467bd"} \ No newline at end of file + styles: # Keyed by experiment_setups.name + ChildOnly_L0: {color: "#1f77b4", marker: "o", linestyle: "-"} + L0_plus_L1_Parent1k_PScan50: {color: "#ff7f0e", marker: "s", linestyle: "--"} + L0_plus_L1_Parent5k_PScan100: {color: "#2ca02c", marker: "D", linestyle: "-."} + L0_L1_Parent1k_L2_Parent100_PScan10: {color: "#d62728", marker: "^", linestyle: ":"} diff --git a/test/experiments/osdi2025/vary_levels/run.py b/test/experiments/osdi2025/vary_levels/run.py index 01c0ccd1..dcc3f3ce 100644 --- a/test/experiments/osdi2025/vary_levels/run.py +++ b/test/experiments/osdi2025/vary_levels/run.py @@ -1,216 +1,468 @@ #!/usr/bin/env python3 """ -experiment_levels.py – benchmark a single Quake/IVF index with optional -parent levels, each level having its own search parameters. - -* Build the **child** index once (saved as base_index.bin). -* For every level described in `levels:`: - – Reload the base index from disk. - – Optionally add a parent layer with `nc` centroids. - – Run searches using the per-level overrides. -* Results for each level go to ./OUT_DIR/L/results.csv -* A combined QPS-vs-Recall plot is written to OUT_DIR/recall_vs_qps.png +vary_levels.py - Benchmarks Quake with varying hierarchical structures. + +This script evaluates Quake's performance with an arbitrary number of index levels. +It builds a base child index (L0) once. Then, for each defined 'experiment_setup', +it loads the base index and adds any specified additional parent levels (L1, L2, etc.) +on top. + +Each complete multi-level index is then benchmarked against a sweep of search +parameters applied to the innermost (L0) level. Search parameters for higher +levels (L1, L2, ...) are fixed for each experiment_setup. + +Key metrics, including overall QPS, latency, recall, and per-level scan times +and statistics (e.g., partitions scanned), are recorded. """ from __future__ import annotations -import argparse, logging, time +import logging +import time from pathlib import Path -from typing import Dict, List, Tuple +from typing import Dict, List, Any, Tuple import matplotlib.pyplot as plt import numpy as np import pandas as pd -import quake -import torch, yaml +import torch +import yaml -from quake.datasets.ann_datasets import load_dataset -from quake.index_wrappers.faiss_ivf import FaissIVF -from quake.index_wrappers.quake import QuakeWrapper -from quake.utils import compute_recall +from quake import QuakeIndex, IndexBuildParams, SearchParams, SearchTimingInfo +from test.experiments.osdi2025 import experiment_utils as common_utils -logger = logging.getLogger("experiment") +logger = logging.getLogger("vary_levels_exp") logging.basicConfig( - format="%(asctime)s | %(levelname)s | %(message)s", + format="%(asctime)s | %(levelname)s | %(name)s | %(message)s", datefmt="%H:%M:%S", level=logging.INFO, ) -# ───────────────────── helper routines ───────────────────── -def _prepare_index(idx_cls, vecs, metric, build_params, - path: Path, rebuild: bool) -> Tuple[object, float]: - """Build or load the *child* index; return (index, build_time_s).""" - idx = idx_cls() - if path.exists() and not rebuild: - t0 = time.time() - idx.load(str(path), num_workers=build_params["num_workers"]) - return idx, 0.0 - logger.info("Building index → %s …", path) - t0 = time.time() - idx.build(vecs, metric=metric, **build_params) - t_build = time.time() - t0 - idx.save(str(path)) - logger.info("Index saved (%.1fs).", t_build) - return idx, t_build - - -def _benchmark_index(idx, queries, ground, search_params, - trials: int, warmup: int) -> Dict: - """Run `trials` timed searches; return stats dict.""" - sp = search_params.copy() # don’t modify caller’s dict - bs = sp.pop("batch_size", None) - k = sp["k"] - - # warm-up - for _ in range(warmup): - if bs is None: - idx.search(queries, **sp) - else: - for i in range(0, len(queries), bs): - idx.search(queries[i:i+bs], **sp) - - qps, lat_ms = [], [] - for _ in range(trials): - t0 = time.time() - if bs is None: - I = idx.search(queries, **sp).ids - else: - I = np.concatenate([ - idx.search(queries[i:i+bs], **sp).ids - for i in range(0, len(queries), bs) - ]) - dt = time.time() - t0 - qps.append(len(queries) / dt) - lat_ms.append(dt * 1e3) - - recall = compute_recall(I, ground[:, :k], k) - recall = 0.0 if recall is None else recall.mean().item() - - return dict( - recall = float(recall), - qps_mean = float(np.mean(qps)), - qps_std = float(np.std(qps)), - latency_ms = float(np.mean(lat_ms)), - trials = trials, - warmup = warmup, - batch_size = bs or len(queries), +def build_hierarchical_index( + base_vectors: torch.Tensor, + child_index_config: Dict[str, Any], + additional_levels_config: List[Dict[str, Any]], + base_child_index_path: Path, + force_rebuild_base: bool, + exp_setup_name: str +) -> Tuple[QuakeIndex | None, float]: + """ + Builds or loads the base child index (L0), then adds additional levels on top. + Returns the fully constructed QuakeIndex instance and total build time for L0. + Build time for additional levels is not explicitly tracked here but happens during add_level. + """ + # Prepare L0 (base child index) + # Note: build_params_dict for prepare_quake_index should be flat, matching IndexBuildParams attributes + l0_build_params_dict = child_index_config.get("build_params", {}) + + # Ensure metric is in the build_params_dict for prepare_quake_index if it expects it + if 'metric' not in l0_build_params_dict and 'metric' in child_index_config: + l0_build_params_dict['metric'] = child_index_config['metric'] + if 'metric' not in l0_build_params_dict and 'metric' in dataset_cfg: # Fallback to dataset metric + l0_build_params_dict['metric'] = dataset_cfg['metric'] + + + # Use common_utils to prepare the base L0 index + # This function handles building if not exists or force_rebuild is true, and saving. + # It returns the loaded/built index instance. + idx = common_utils.prepare_quake_index( + vecs=base_vectors, + build_params_dict=l0_build_params_dict, + index_file_path=base_child_index_path, + force_rebuild=force_rebuild_base, + # Pass load-time worker/NUMA settings for L0 if they were part of its build_params + # For Quake, these are typically search-time. If prepare_quake_index needs them for load: + num_workers_load=l0_build_params_dict.get("num_workers", 0), # Assuming build num_workers is also load num_workers + use_numa=l0_build_params_dict.get("use_numa", False) # Assuming build use_numa is also load use_numa ) + # Build time for L0 is implicitly handled by prepare_quake_index if it were to return it. + # For now, we'll assume build_time_l0 is primarily for the initial creation. + # If the file existed, build_time_l0 would be 0. + build_time_l0 = 0.0 # Placeholder, as prepare_quake_index doesn't return build time directly. + + if idx is None: + logger.error(f"Failed to prepare base child index for {exp_setup_name}.") + return None, build_time_l0 + # Add additional levels (L1, L2, ...) + for i, level_cfg in enumerate(additional_levels_config): + level_num = i + 1 # L1, L2, ... + logger.info(f"For '{exp_setup_name}', adding L{level_num}...") -def _expand_targets(sp: Dict) -> List[Dict]: - """Yield one search-param dict per recall_target OR per nprobe value.""" - if "recall_targets" in sp: - tgs = sp.pop("recall_targets") - if not isinstance(tgs, (list, tuple)): tgs = [tgs] - return [{**sp, "recall_target": t} for t in tgs] - if "nprobes" in sp: - tgs = sp.pop("nprobes") - if not isinstance(tgs, (list, tuple)): tgs = [tgs] - return [{**sp, "nprobe": t} for t in tgs] - return [sp] - - -def _plot(cfg: Dict, root: Path) -> None: - """Generate combined QPS-vs-Recall plot.""" - fig, ax = plt.subplots(figsize=(6, 4)) - styles = cfg.get("plot", {}).get("styles", {}) - for lv in cfg["levels"]: - nc = lv["nc"] - name = f"L{nc}" - csv = root / name / "results.csv" - if not csv.exists(): - logger.warning("No results for level %s – skipped.", nc) + add_level_build_params_dict = level_cfg.get("build_params", {}) + if not add_level_build_params_dict.get("nc"): + logger.warning(f"Skipping L{level_num} for '{exp_setup_name}' due to missing 'nc' in build_params.") continue - df = pd.read_csv(csv).sort_values("recall") - sty = styles.get(name, {}) - ax.plot( - df["qps_mean"], df["recall"], - label = f"{nc:,} centroids" if nc else "single-level", - marker = sty.get("marker", "o"), - linestyle = sty.get("linestyle", "-"), - linewidth = 1.4, - markersize = 6, - color = sty.get("color", None), - ) - # ax.set_xscale("log", base=10) - ax.set_xlabel("Queries per second (log)") - ax.set_ylabel("Recall@k") - ax.set_title("QPS vs Recall for different parent levels") - ax.grid(True, which="both", ls=":") - ax.legend() - fig.tight_layout() - fig.savefig(root / "recall_vs_qps.png", dpi=180) - logger.info("Plot written to %s", root / "recall_vs_qps.png") - -# ─────────────────────────── main ────────────────────────── -def run_experiment(cfg_path: str, output_dir: str) -> None: - cfg = yaml.safe_load(Path(cfg_path).read_text()) - out = Path(output_dir) - out.mkdir(parents=True, exist_ok=True) - - # dataset --------------------------------------------------------------- - ds = cfg["dataset"] - logger.info("Loading dataset %s …", ds["name"]) - vecs, queries, ground = load_dataset(ds["name"], ds.get("path", "")) - nq = ds["nq"] - queries, ground = queries[:nq], ground[:nq] - metric = ds["metric"] - - # build child index once ----------------------------------------------- - icfg = cfg["index"] - idx_cls = {"Quake": QuakeWrapper, "IVF": FaissIVF}[icfg["type"]] - base_bin = out / "base_index.bin" - base_idx, build_t = _prepare_index( - idx_cls, vecs, metric, - icfg["build_params"], - base_bin, - rebuild=cfg["overwrite"].get("index", False), + + # Create IndexBuildParams for adding the level + # The metric for parent levels is typically inherited or fixed by Quake internally. + # We primarily need to set 'nc' and 'num_workers' for building this parent level. + parent_bp = IndexBuildParams() + parent_bp.nlist = add_level_build_params_dict["nc"] + parent_bp.num_workers = add_level_build_params_dict.get("num_workers", 0) + parent_bp.metric = l0_build_params_dict.get("metric", "l2") # Parent inherits metric + + try: + idx.add_level(parent_bp) # Assumes QuakeIndex has .index attribute pointing to C++ object + logger.info(f"L{level_num} (NC={parent_bp.nlist}) added successfully for '{exp_setup_name}'.") + except Exception as e: + logger.error(f"Failed to add L{level_num} for '{exp_setup_name}': {e}") + return None, build_time_l0 + + return idx, build_time_l0 + + +def construct_hierarchical_search_params( + innermost_level_sp_item: Dict[str, Any], + additional_levels_config: List[Dict[str, Any]] +) -> SearchParams: + """ + Constructs a nested SearchParams object for the entire hierarchy. + """ + # Innermost level (L0) search parameters + l0_sp = common_utils.create_search_params(**innermost_level_sp_item) + + current_parent_sp = l0_sp + for level_cfg in additional_levels_config: # L1, L2, ... + level_search_params_dict = level_cfg.get("search_params", {}) + if not level_search_params_dict: # If no specific search params, create default + level_search_params_dict = {"nprobe": 1} # Minimal valid SearchParams + + # These are search-time worker/NUMA settings for this specific parent level's scan + # common_utils.create_search_params will set these if present in level_search_params_dict + higher_level_sp = common_utils.create_search_params(**level_search_params_dict) + + current_parent_sp.parent_params = higher_level_sp + current_parent_sp = higher_level_sp + + return l0_sp + + +def _extract_recursive_timings(innermost_timing_info: SearchTimingInfo | None, num_levels: int) -> Dict[str, Any]: + """ + Extracts scan time and other stats for each level from the TimingInfo hierarchy. + The innermost_timing_info is for L0. Its .parent_info is for L1, and so on. + """ + timings = {} + current_ti = innermost_timing_info + + for i in range(num_levels): + level_prefix = f"level_{i}" + if current_ti: + timings[f"{level_prefix}_scan_time_ms"] = current_ti.total_time_ns / 1e6 + timings[f"{level_prefix}_buffer_init_ms"] = current_ti.buffer_init_time_ns / 1e6 + timings[f"{level_prefix}_enqueue_ms"] = current_ti.job_enqueue_time_ns / 1e6 + timings[f"{level_prefix}_wait_ms"] = current_ti.job_wait_time_ns / 1e6 + timings[f"{level_prefix}_aggregate_ms"] = current_ti.result_aggregate_time_ns / 1e6 + timings[f"{level_prefix}_partitions_scanned"] = getattr(current_ti, "partitions_scanned", np.nan) + current_ti = current_ti.parent_info + else: + timings[f"{level_prefix}_scan_time_ms"] = np.nan + timings[f"{level_prefix}_buffer_init_ms"] = np.nan + timings[f"{level_prefix}_enqueue_ms"] = np.nan + timings[f"{level_prefix}_wait_ms"] = np.nan + timings[f"{level_prefix}_aggregate_ms"] = np.nan + timings[f"{level_prefix}_partitions_scanned"] = np.nan + return timings + + +def benchmark_search_config( + idx: QuakeIndex, + queries: torch.Tensor, + ground_truth: np.ndarray | None, + hierarchical_sp: SearchParams, + num_levels_in_hierarchy: int, + num_trials: int, + warmup_trials: int +) -> Dict[str, Any]: + """ + Benchmarks a specific hierarchical search configuration. + Returns aggregated metrics including per-level timings. + """ + k_val = hierarchical_sp.k # k from the L0 SearchParams + + # Warm-up + for _ in range(warmup_trials): + idx.search(queries, hierarchical_sp) + + trial_metrics_list = [] + for _ in range(num_trials): + t_start_ns = time.perf_counter_ns() + search_result = idx.search(queries, hierarchical_sp) + t_elapsed_ns = time.perf_counter_ns() - t_start_ns + + current_recall = np.nan + if ground_truth is not None and search_result.ids is not None: + # Ensure k_val does not exceed columns in ground_truth or search_result.ids + max_k_recall = min(k_val, ground_truth.shape[1], search_result.ids.shape[1]) + if max_k_recall > 0 : + current_recall = common_utils.quake_compute_recall( + search_result.ids[:, :max_k_recall], + ground_truth[:, :max_k_recall], + max_k_recall + ).mean().item() + + + per_level_timings = _extract_recursive_timings(search_result.timing_info, num_levels_in_hierarchy) + + trial_metrics_list.append({ + "overall_latency_ns": t_elapsed_ns, + "recall": current_recall, + **per_level_timings + }) + + # Aggregate results from trials + num_queries_total = len(queries) + aggregated_results = { + "qps_mean": np.mean([num_queries_total / (m["overall_latency_ns"] / 1e9) for m in trial_metrics_list]), + "overall_latency_ms_mean": np.mean([m["overall_latency_ns"] / 1e6 for m in trial_metrics_list]), + "recall_mean": np.nanmean([m["recall"] for m in trial_metrics_list]), + } + + # Aggregate per-level timings and stats + for i in range(num_levels_in_hierarchy): + level_prefix = f"level_{i}" + for metric_suffix in ["scan_time_ms", "buffer_init_ms", "enqueue_ms", "wait_ms", "aggregate_ms", "partitions_scanned"]: + key = f"{level_prefix}_{metric_suffix}" + valid_values = [m[key] for m in trial_metrics_list if key in m and pd.notna(m[key])] + if valid_values: + aggregated_results[f"{key}_mean"] = np.mean(valid_values) + else: + aggregated_results[f"{key}_mean"] = np.nan + + return aggregated_results + + +def run_experiment(config_path_str: str, output_dir_str: str) -> None: + global dataset_cfg # Make dataset_cfg accessible to build_hierarchical_index if needed for metric fallback + config = common_utils.load_config(config_path_str) + output_dir = Path(output_dir_str) + output_dir.mkdir(parents=True, exist_ok=True) + + dataset_cfg = config["dataset"] + child_index_cfg = config["child_index_config"] # L0 build config + innermost_search_sweep_cfg = config["global_innermost_search_sweep"] # L0 search sweep + experiment_setups_cfg = config["experiment_setups"] + exp_params_cfg = config["experiment_params"] + overwrite_cfg = config["overwrite"] + + logger.info(f"Loading dataset: {dataset_cfg['name']}") + base_vecs, queries, gt_numpy = common_utils.load_data( + dataset_cfg["name"], dataset_cfg.get("path", ""), nq_override=dataset_cfg.get("nq") + ) + + # Path for the L0 index binary + base_child_index_path = output_dir / "base_index.bin" + + l0_build_params_dict = child_index_cfg.get("build_params", {}) + if 'metric' not in l0_build_params_dict: # Ensure metric is set for L0 build + l0_build_params_dict['metric'] = dataset_cfg.get('metric', 'l2') + + _ = common_utils.prepare_quake_index( # Build L0 and save it + vecs=base_vecs, + build_params_dict=l0_build_params_dict, + index_file_path=base_child_index_path, + force_rebuild=overwrite_cfg.get("index", False) ) + logger.info(f"Base L0 index prepared at {base_child_index_path}") + + all_experiment_run_records = [] + innermost_sweep_list = common_utils.expand_search_sweep(innermost_search_sweep_cfg) # Adapted from common_utils or defined here - # iterate over parent levels ------------------------------------------- - for lv in cfg["levels"]: - nc = lv["nc"] - name = f"L{nc}" - res_dir = out / name - res_dir.mkdir(parents=True, exist_ok=True) - csv_file = res_dir / "results.csv" + for exp_setup_item in experiment_setups_cfg: + exp_setup_name = exp_setup_item["name"] + additional_levels_config = exp_setup_item.get("additional_levels", []) + num_actual_levels = 1 + len(additional_levels_config) # L0 + additional levels - if csv_file.exists() and not cfg["overwrite"].get("results", False): - logger.info("[%s] results cached – skipping.", name) + exp_setup_results_path = output_dir / f"{exp_setup_name}_results.csv" + if exp_setup_results_path.exists() and not overwrite_cfg.get("results", True): + logger.info(f"Results for setup '{exp_setup_name}' exist, loading cached.") + try: + cached_df = pd.read_csv(exp_setup_results_path) + all_experiment_run_records.extend(cached_df.to_dict('records')) + except Exception as e: + logger.error(f"Could not load cached results for {exp_setup_name}: {e}") continue - # fresh load of the base index for this level - idx = idx_cls() - idx.load(str(base_bin), num_workers=icfg["build_params"].get("num_workers", 1)) - if nc: # add parent layer when nc > 0 - build_params = quake.IndexBuildParams() - build_params.nlist = nc - idx.index.add_level(build_params) - - # child search params (base defaults + per-level overrides) - child_sp = icfg["search_params"].copy() - child_sp.update(lv.get("search_params", {})) - - # optional parent search params - parent_sp = lv.get("parent_search_params", None) - - df = pd.DataFrame() - for sp in _expand_targets(child_sp.copy()): - if parent_sp: # attach parent section if any - sp["parent"] = parent_sp - stats = _benchmark_index( - idx, queries, ground, sp, - trials = cfg.get("trials", 5), - warmup = cfg.get("warmup", 1), - ) - stats.update( - build_time_s = build_t if nc == 0 else 0.0, - parent_nc = nc, - recall_target= sp.get("recall_target", sp.get("nprobe", np.nan)), + logger.info(f"--- Processing Experiment Setup: {exp_setup_name} ({num_actual_levels} levels) ---") + + # Assemble the full hierarchical index for this setup + # This loads L0 and adds L1, L2... on top. + current_hier_idx, _ = build_hierarchical_index( + base_vecs, child_index_cfg, additional_levels_config, + base_child_index_path, False, # False: don't force rebuild L0 if already done + exp_setup_name + ) + if not current_hier_idx: + logger.error(f"Failed to build index for setup '{exp_setup_name}'. Skipping.") + continue + + setup_specific_records = [] + for l0_sp_item in innermost_sweep_list: # Iterate L0 search params (nprobe/recall_target) + param_key = "nprobe" if "nprobe" in l0_sp_item else "recall_target" + param_val = l0_sp_item.get(param_key, "N/A") + logger.info(f"Benchmarking '{exp_setup_name}' with L0 {param_key}={param_val}...") + + # Construct the full stack of SearchParams for this run + hierarchical_sp = construct_hierarchical_search_params(l0_sp_item, additional_levels_config) + + benchmark_stats = benchmark_search_config( + current_hier_idx, queries, gt_numpy, hierarchical_sp, + num_levels_in_hierarchy=num_actual_levels, + num_trials=exp_params_cfg.get("trials", 3), + warmup_trials=exp_params_cfg.get("warmup", 1) ) - df = pd.concat([df, pd.DataFrame([stats])], ignore_index=True) - logger.info("[%s] target %.3g done.", name, stats["recall_target"]) - df.to_csv(csv_file, index=False) - logger.info("[%s] results written to %s", name, csv_file) + # Record configuration and results + record = {"exp_setup_name": exp_setup_name} + record[f"L0_{param_key}"] = param_val # L0 sweep parameter + record["L0_k"] = l0_sp_item.get("k") + record["L0_batch_size"] = l0_sp_item.get("batch_size") + record["L0_nc"] = child_index_cfg.get("build_params", {}).get("nc") + + + for i, add_level_cfg in enumerate(additional_levels_config): + level_num = i + 1 # L1, L2... + record[f"L{level_num}_nc"] = add_level_cfg.get("build_params",{}).get("nc") + record[f"L{level_num}_build_workers"] = add_level_cfg.get("build_params",{}).get("num_workers") + record[f"L{level_num}_search_nprobe"] = add_level_cfg.get("search_params",{}).get("nprobe") + record[f"L{level_num}_search_recall_target"] = add_level_cfg.get("search_params",{}).get("recall_target") + record[f"L{level_num}_search_workers"] = add_level_cfg.get("search_params",{}).get("num_workers") + record[f"L{level_num}_search_use_numa"] = add_level_cfg.get("search_params",{}).get("use_numa") + + record.update(benchmark_stats) + setup_specific_records.append(record) + all_experiment_run_records.append(record) + + if setup_specific_records: + setup_df = pd.DataFrame(setup_specific_records) + setup_df.to_csv(exp_setup_results_path, index=False) + logger.info(f"Results for setup '{exp_setup_name}' saved to {exp_setup_results_path}") + + if all_experiment_run_records: + final_df = pd.DataFrame(all_experiment_run_records) + unified_csv_path = output_dir / f"{dataset_cfg['name']}_vary_levels_all_setups_summary.csv" + final_df.to_csv(unified_csv_path, index=False) + logger.info(f"Unified results for all setups saved to {unified_csv_path}") + + + if not final_df.empty: + plot_metric_vs_l0_param(final_df, config, output_dir, metric_to_plot="recall_mean", ylabel="Mean Recall") + plot_metric_vs_l0_param(final_df, config, output_dir, metric_to_plot="overall_latency_ms_mean", ylabel="Mean Overall Latency (ms)") + plot_level_scan_times(final_df, config, output_dir) + + else: + logger.info("No results generated across all setups.") + + logger.info("Vary Levels (Generalized) experiment finished.") + +def plot_metric_vs_l0_param(results_df: pd.DataFrame, config: Dict[str, Any], output_dir: Path, metric_to_plot: str, ylabel: str): + """Plots a given metric against the L0 sweep parameter for different experiment setups.""" + if results_df.empty or metric_to_plot not in results_df.columns: + logger.warning(f"Cannot plot '{metric_to_plot}': Data missing or empty.") + return + + fig, ax = plt.subplots(figsize=(10, 7)) + plot_styles = config.get("plot", {}).get("styles", {}) + + # Determine L0 sweep key (nprobe or recall_target) + l0_sweep_key = None + if "L0_nprobe" in results_df.columns and results_df["L0_nprobe"].notna().any(): + l0_sweep_key = "L0_nprobe" + elif "L0_recall_target" in results_df.columns and results_df["L0_recall_target"].notna().any(): + l0_sweep_key = "L0_recall_target" + + if not l0_sweep_key: + logger.warning("L0 sweep parameter (nprobe/recall_target) not found in results. Skipping plot.") + plt.close(fig) + return + + for exp_name, group in results_df.groupby("exp_setup_name"): + style = plot_styles.get(exp_name, {}) + sorted_group = group.sort_values(by=l0_sweep_key) + ax.plot( + sorted_group[l0_sweep_key], + sorted_group[metric_to_plot], + label=exp_name, + marker=style.get("marker", "o"), + color=style.get("color"), + linestyle=style.get("linestyle", "-") + ) + + ax.set_xlabel(f"Innermost Level (L0) Search: {l0_sweep_key.replace('_', ' ').title()}") + ax.set_ylabel(ylabel) + ax.set_title(f"{config['dataset']['name']}: {ylabel} vs. L0 Search Parameter") + ax.legend(title="Experiment Setup", bbox_to_anchor=(1.05, 1), loc='upper left') + ax.grid(True, which="both", ls=":", alpha=0.7) + plt.tight_layout(rect=[0, 0, 0.78, 1]) # Adjust for legend + + plot_filename = f"{config['dataset']['name']}_vary_levels_{metric_to_plot}_vs_L0param.png" + plt.savefig(output_dir / plot_filename, dpi=150) + logger.info(f"Plot saved: {output_dir / plot_filename}") + plt.close(fig) + + +def plot_level_scan_times(results_df: pd.DataFrame, config: Dict[str, Any], output_dir: Path): + """Plots the breakdown of scan times per level for each experiment setup, at a chosen L0 parameter value.""" + if results_df.empty: + logger.warning("Cannot plot level scan times: Data missing or empty.") + return + + l0_sweep_key = None + if "L0_nprobe" in results_df.columns and results_df["L0_nprobe"].notna().any(): + l0_sweep_key = "L0_nprobe" + elif "L0_recall_target" in results_df.columns and results_df["L0_recall_target"].notna().any(): + l0_sweep_key = "L0_recall_target" + if not l0_sweep_key: return + + + # Select a representative L0 parameter value for the bar chart (e.g., median or a common high-recall point) + if results_df[l0_sweep_key].nunique() > 1: + target_l0_val = np.percentile(results_df[l0_sweep_key].dropna(), 75) # Example: 75th percentile + # Find closest available value in the df + available_l0_vals = results_df[l0_sweep_key].dropna().unique() + closest_l0_val = available_l0_vals[np.abs(available_l0_vals - target_l0_val).argmin()] + + df_subset = results_df[results_df[l0_sweep_key] == closest_l0_val].copy() + plot_title_suffix = f"(at L0 {l0_sweep_key.split('_')[-1]} ≈ {closest_l0_val:.2f})" + else: + df_subset = results_df.copy() + plot_title_suffix = f"(at L0 {l0_sweep_key.split('_')[-1]} = {df_subset[l0_sweep_key].iloc[0]:.2f})" + + + if df_subset.empty: + logger.warning("No data for selected L0 parameter for level scan time plot.") + return + + level_time_cols = sorted([col for col in df_subset.columns if col.startswith("level_") and col.endswith("_scan_time_ms_mean")]) + if not level_time_cols: + logger.warning("No per-level scan time columns found for plotting.") + return + + max_level_idx = max([int(c.split('_')[1]) for c in level_time_cols]) + num_levels_to_plot = max_level_idx + 1 + + plot_data = df_subset.set_index("exp_setup_name")[level_time_cols] + + # Ensure all level columns up to max_level_idx are present, fill with 0 if not (for consistent plotting) + for i in range(num_levels_to_plot): + col_name = f"level_{i}_scan_time_ms_mean" + if col_name not in plot_data.columns: + plot_data[col_name] = 0 + # Reorder columns for stacked bar plot + ordered_level_time_cols = [f"level_{i}_scan_time_ms_mean" for i in range(num_levels_to_plot)] + plot_data = plot_data[ordered_level_time_cols] + + + plot_data.plot(kind='bar', stacked=True, figsize=(12, 8), colormap='viridis') + + plt.xlabel("Experiment Setup") + plt.ylabel("Mean Scan Time per Level (ms)") + plt.title(f"{config['dataset']['name']}: Scan Time Breakdown by Level {plot_title_suffix}") + plt.xticks(rotation=30, ha='right') + plt.legend(title="Index Level (L0=innermost)", bbox_to_anchor=(1.05, 1), loc='upper left') + plt.tight_layout(rect=[0, 0, 0.8, 1]) # Adjust for legend - _plot(cfg, out) + plot_filename = f"{config['dataset']['name']}_vary_levels_scan_time_breakdown.png" + plt.savefig(output_dir / plot_filename, dpi=150) + logger.info(f"Plot saved: {output_dir / plot_filename}") + plt.close() \ No newline at end of file From 66ed970da103d99017407b890ca4b3ff431815fc Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 10:35:05 -0500 Subject: [PATCH 201/323] update readme and install script --- test/experiments/osdi2025/README.md | 32 ++-- test/experiments/osdi2025/install.sh | 247 +++++++++++++++++++++++++++ 2 files changed, 259 insertions(+), 20 deletions(-) create mode 100644 test/experiments/osdi2025/install.sh diff --git a/test/experiments/osdi2025/README.md b/test/experiments/osdi2025/README.md index 465429df..b62a81fe 100644 --- a/test/experiments/osdi2025/README.md +++ b/test/experiments/osdi2025/README.md @@ -41,7 +41,7 @@ Each experiment directory (e.g., `aps_recall_targets`, `early_termination`) cont 2. **Set Up the Conda Environment:** Create and activate the environment using the provided YAML file: ```bash - conda env create -f environments/ubuntu-latest/conda.yaml + conda env create -f environments/ubuntu-cpu/conda.yaml conda activate quake-env ``` @@ -67,7 +67,7 @@ OMP_NUM_THREADS=1 python3 -m test.experiments.osdi2025.experiment_runner \ **Explanation:** -* `OMP_NUM_THREADS=1`: Recommended for consistent performance measurement as OMP interferes with our custom parallelism. Adjust as needed based on specific experiment guidelines if any. +* `OMP_NUM_THREADS=1`: Recommended for consistent performance measurement as OMP interferes with our custom parallelism. * `--experiment `: Specifies which experiment to run (e.g., `kick_the_tires`, `aps_recall_targets`). * `--config `: Specifies the configuration file from `test/experiments/osdi2025//configs/`. For `sift1m.yaml`, use `sift1m`. * `--output-dir ` (Optional): If provided, results (CSVs, plots) will be saved here. Default is `test/experiments/osdi2025//results//`. @@ -94,20 +94,16 @@ OMP_NUM_THREADS=1 python3 -m test.experiments.osdi2025.experiment_runner \ ## Experiment Summaries and Outputs -The following table summarizes each experiment and its primary outputs. Output files are typically generated within the experiment's specific output directory (refer to the `--output-dir` option or its default value). - -| Experiment Name | Description | Key Outputs (Illustrative Filenames) | -|------------------------|--------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `aps_recall_targets` | Evaluates Quake's Adaptive Partition Scanning (APS) against baselines for various recall targets. | `aps_recall_targets_summary.csv`, `aps_recall_vs_metrics.png` | -| `early_termination` | Compares APS with early termination strategies like LAET and Auncel. | `aps_et_results_.csv`, `latency_plot_.png`, Markdown table (printed to console) | -| `kick_the_tires` | Basic dynamic workload stress test focusing on latency, recall, and system state over operations. | Per-index `results.csv` (e.g., `Quake10000/results.csv`), main `unified_plot.png` | -| `maintenance_ablation` | Evaluates the impact of Quake's maintenance operations under a dynamic workload, extending `kick_the_tires`. | Per-index `results.csv`, main `summary_table.csv`, `summary_table.md`, `unified_plot.png`, `time_breakdown.png` | -| `measure_skew_and_perf` | Measures data skew characteristics and their performance impact on a dataset. | Script-specific CSVs/plots detailing skew metrics and performance correlations. | -| `multi_level` | Benchmarks Quake with multiple index levels against single-level configurations, varying `nprobe`. | Per-index `results.csv` (e.g., `Quake5000/results.csv`), main `recall_vs_qps.png` | -| `numa_multi_query` | Tests Quake's multi-query batch performance under different NUMA and worker configurations. | Per-index `results.csv`, main `.csv` (aggregate), `_batch_latency.png`, `_batch_recall.png` | -| `numa_single_query` | Tests Quake's single-query performance under different NUMA and worker configurations. | Per-index `results.csv`, main `.csv` (aggregate), `_child_latency.png`, `_recall.png` | -| `vary_levels` | Evaluates Quake with varying numbers of centroids in parent index levels. | Per-level `results.csv` (e.g., `L/results.csv`), main `recall_vs_qps.png` | -| `workload_comparison` | Compares Quake's performance across different types of synthetic or real-world workloads. | Script-specific CSVs/plots comparing workloads. | +The following table summarizes each experiment and its primary outputs. Output files are generated within the experiment's specific output directory (refer to the `--output-dir` option or its default value). + +| Experiment Name | Description | Reproduces in Paper | +|------------------------|--------------------------------------------------------------------------------------------------------------|-------------------------------| +| `aps_recall_targets` | Evaluates Quake's Adaptive Partition Scanning (APS) against baselines for various recall targets. | Figure 6 | +| `early_termination` | Compares APS with early termination strategies like LAET and Auncel. | Revision Experiment (Table 5) | +| `kick_the_tires` | Basic dynamic workload stress test focusing on latency, recall, and system state over operations. | | +| `maintenance_ablation` | Evaluates the impact of Quake's maintenance operations under a dynamic workload, extending `kick_the_tires`. | Revision Experiment (Table 6) | +| `numa_multi_query` | Tests Quake's multi-query batch performance under different NUMA and worker configurations. | | +| `numa_single_query` | Tests Quake's single-query performance under different NUMA and worker configurations. | Figure 5 | **To run any of these, replace `` and `` in the general command structure.** For example, to run the `aps_recall_targets` experiment with its `sift1m` configuration: @@ -122,10 +118,6 @@ Results, including CSV files and plots as detailed above, will be saved to the s ## Notes * **Dataset Downloads:** The `quake.datasets.ann_datasets.load_dataset` utility will attempt to download datasets if they are not found locally (typically in a `data/` directory in the repository root). An internet connection is required for initial downloads. -* **Disk Space:** Some datasets (e.g., SIFT1B, MSTuring100M) are large and require significant disk space. * **Execution Time:** Full experimental runs can be time-consuming, ranging from minutes for small configurations to many hours for large-scale evaluations. The `kick_the_tires` experiment with `sift1m` is designed for relatively quick verification. - -``` -``` \ No newline at end of file diff --git a/test/experiments/osdi2025/install.sh b/test/experiments/osdi2025/install.sh new file mode 100644 index 00000000..9cb705c1 --- /dev/null +++ b/test/experiments/osdi2025/install.sh @@ -0,0 +1,247 @@ +#!/bin/bash +set -e # Exit immediately if a command exits with a non-zero status. +# set -x # Uncomment for debugging (print each command before execution) + +echo "Starting QUAKE Artifact and Baselines Setup Script." +echo "This script should be run with sudo (e.g., 'sudo ./install.sh')." +echo "Targeting Ubuntu 22.04 (Jammy) based system." + +# ----------------------------- +# Environment Variables +# ----------------------------- +export CONDA_DIR_PATH="/opt/miniconda" +# Ensure Miniconda's bin is in PATH for the root user running the script +export PATH="${CONDA_DIR_PATH}/bin:${PATH}" +export DEBIAN_FRONTEND=noninteractive + +# ----------------------------- +# Update System and Install Base APT Packages +# ----------------------------- +echo ">>> Updating system and installing base APT packages..." +apt-get update + +apt-get install -y --no-install-recommends \ + wget \ + curl \ + build-essential \ + ca-certificates \ + swig \ + git \ + libomp-dev \ + graphviz \ + numactl \ + libnuma-dev \ + htop \ + software-properties-common + +# ----------------------------- +# Install/Ensure GCC 11 and G++ 11 +# ----------------------------- +echo ">>> Ensuring GCC 11 and G++ 11 are set up correctly..." +add-apt-repository -y ppa:ubuntu-toolchain-r/test +apt-get update +apt-get install -y gcc-11 g++-11 + +echo ">>> Setting up GCC and G++ alternatives to point to version 11..." +update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 110 \ + --slave /usr/bin/gcov gcc-gcov /usr/bin/gcov-11 \ + --slave /usr/bin/gcc-ar gcc-ar /usr/bin/gcc-ar-11 \ + --slave /usr/bin/gcc-nm gcc-nm /usr/bin/gcc-nm-11 \ + --slave /usr/bin/gcc-ranlib gcc-ranlib /usr/bin/gcc-ranlib-11 +update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-11 110 +update-alternatives --set gcc /usr/bin/gcc-11 +update-alternatives --set g++ /usr/bin/g++-11 + +echo "Verifying GCC version after update-alternatives:" +gcc --version +echo "Verifying G++ version after update-alternatives:" +g++ --version + +# ----------------------------- +# Install CMake 3.24.2 +# ----------------------------- +CMAKE_VERSION_EXPECTED="3.24.2" +CMAKE_INSTALL_PATH="/usr/local/bin/cmake" +echo ">>> Installing CMake ${CMAKE_VERSION_EXPECTED}..." +if command -v cmake &> /dev/null && [[ "$(cmake --version)" == *"cmake version ${CMAKE_VERSION_EXPECTED}"* ]]; then + echo "CMake version ${CMAKE_VERSION_EXPECTED} already installed at $(command -v cmake). Skipping." +else + echo "Installing CMake ${CMAKE_VERSION_EXPECTED}..." + cd /tmp + wget -qO cmake.sh https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION_EXPECTED}/cmake-${CMAKE_VERSION_EXPECTED}-linux-x86_64.sh + chmod +x cmake.sh + ./cmake.sh --skip-license --prefix=/usr/local # Runs as root + rm cmake.sh + cd - +fi +echo "Verifying CMake version:" +cmake --version + +# ----------------------------- +# Install Miniconda +# ----------------------------- +echo ">>> Installing Miniconda to ${CONDA_DIR_PATH}..." +if [ -x "${CONDA_DIR_PATH}/bin/conda" ]; then + echo "Miniconda already found in ${CONDA_DIR_PATH}. Skipping installation." +else + cd /tmp + wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh + bash miniconda.sh -b -p "${CONDA_DIR_PATH}" # Runs as root, installs to /opt/miniconda + rm miniconda.sh + cd - + echo ">>> Initializing Conda for bash (modifies /root/.bashrc as script runs with sudo)..." + "${CONDA_DIR_PATH}/bin/conda" init bash +fi + +# Source conda's profile script to make conda command available in this script session +echo ">>> Sourcing Conda profile script for current root session..." +if [ -f "${CONDA_DIR_PATH}/etc/profile.d/conda.sh" ]; then + source "${CONDA_DIR_PATH}/etc/profile.d/conda.sh" +else + echo "ERROR: Conda profile script not found at ${CONDA_DIR_PATH}/etc/profile.d/conda.sh after installation attempt." + echo "Conda commands might not be available. Exiting." + exit 1 +fi + +# ----------------------------- +# Create Conda Environment 'quake-env' and Install Dependencies +# ----------------------------- +CONDA_ENV_NAME="quake-env" +echo ">>> Setting up conda environment '${CONDA_ENV_NAME}'..." + +echo ">>> Creating conda.yaml file at /tmp/conda.yaml..." +# Ensure the file is removed first to prevent issues with existing file/permissions +rm -f /tmp/conda.yaml +cat > /tmp/conda.yaml << EOF +name: ${CONDA_ENV_NAME} +channels: + - pytorch + - defaults + - conda-forge +dependencies: + - python=3.11 + - numpy + - pandas + - faiss-cpu + - matplotlib + - pytest + - pip + - pip: + - sphinx + - sphinx_rtd_theme + - sphinxcontrib-mermaid + - graphviz + - pyyaml +EOF + +# If environment exists, remove it for a clean setup +if conda env list | grep -E "^${CONDA_ENV_NAME}\s+"; then + echo "Conda environment '${CONDA_ENV_NAME}' already exists. Removing for a clean setup..." + conda env remove -n "${CONDA_ENV_NAME}" --all -y +fi +echo ">>> Creating conda environment '${CONDA_ENV_NAME}' from /tmp/conda.yaml..." +conda env create -f /tmp/conda.yaml +rm /tmp/conda.yaml # Clean up +conda clean -afy + +echo ">>> Installing specific PyTorch (CPU) and other Python packages into '${CONDA_ENV_NAME}'..." +conda run -n "${CONDA_ENV_NAME}" pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu + +conda run -n "${CONDA_ENV_NAME}" pip install \ + lightgbm \ + scikit-learn \ + scann==1.4.0 + +# Force numpy 1.25.0 for diskannpy compatibility +conda run -n "${CONDA_ENV_NAME}" pip install numpy==1.25.0 --force-reinstall +conda run -n "${CONDA_ENV_NAME}" pip install diskannpy==0.7.0 + +echo ">>> Verifying '${CONDA_ENV_NAME}'..." +conda env list +conda run -n "${CONDA_ENV_NAME}" python -c "import sys; print(f'OK in {sys.prefix}; python:', sys.executable); import torch; print('PyTorch version:', torch.__version__); import numpy; print('Numpy version:', numpy.__version__)" + +# ----------------------------- +# Install Intel oneAPI Base Toolkit +# ----------------------------- +ONEAPI_INSTALL_PATH="/opt/intel/oneapi" +echo ">>> Installing Intel oneAPI Base Toolkit to ${ONEAPI_INSTALL_PATH}..." +if [ -f "${ONEAPI_INSTALL_PATH}/setvars.sh" ]; then + echo "Intel oneAPI already found in ${ONEAPI_INSTALL_PATH}. Skipping installation." +else + cd /tmp + wget -O intel-oneapi-base-toolkit-offline.sh https://registrationcenter-download.intel.com/akdlm/IRC_NAS/6bfca885-4156-491e-849b-1cd7da9cc760/intel-oneapi-base-toolkit-2025.1.1.36_offline.sh + chmod +x intel-oneapi-base-toolkit-offline.sh + ./intel-oneapi-base-toolkit-offline.sh -a --silent --cli --eula accept --install-dir "${ONEAPI_INSTALL_PATH}" # sudo implied + rm intel-oneapi-base-toolkit-offline.sh + cd - +fi +# Source oneAPI environment variables for the current session. +echo ">>> Sourcing Intel oneAPI setvars.sh for current root session (needed for SVS build)..." +if [ -f "${ONEAPI_INSTALL_PATH}/setvars.sh" ]; then + source "${ONEAPI_INSTALL_PATH}/setvars.sh" +else + echo "WARNING: oneAPI setvars.sh not found at ${ONEAPI_INSTALL_PATH}/setvars.sh. SVS build might fail." +fi + +# ----------------------------- +# Clone and Install QUAKE Repository +# ----------------------------- +QUAKE_DIR_BASE="/opt" +QUAKE_REPO_NAME="quake" +QUAKE_FULL_PATH="${QUAKE_DIR_BASE}/${QUAKE_REPO_NAME}" + +echo ">>> Cloning/Updating and installing QUAKE repository in ${QUAKE_FULL_PATH}..." +if [ -d "${QUAKE_FULL_PATH}" ]; then + echo "QUAKE directory ${QUAKE_FULL_PATH} already exists. Updating..." + cd "${QUAKE_FULL_PATH}" + git pull +else + git clone https://github.com/marius-team/quake.git "${QUAKE_FULL_PATH}" + cd "${QUAKE_FULL_PATH}" +fi +git checkout osdi2025_debug + +git config --global --add safe.directory "${QUAKE_FULL_PATH}" # For root's global config +SUBMODULE_PATHS=("src/cpp/third_party/concurrentqueue" "src/cpp/third_party/faiss" "src/cpp/third_party/pybind11") +for SUBMODULE_PATH in "${SUBMODULE_PATHS[@]}"; do + git config --global --add safe.directory "${QUAKE_FULL_PATH}/${SUBMODULE_PATH}" +done +git submodule update --init --recursive + +echo ">>> Building and installing QUAKE Python package..." +conda run -n "${CONDA_ENV_NAME}" pip install . --no-use-pep517 +cd / + +# ----------------------------- +# Clone and Install ScalableVectorSearch (SVS) +# ----------------------------- +SVS_DIR_BASE="/opt" +SVS_REPO_NAME="ScalableVectorSearch" +SVS_FULL_PATH="${SVS_DIR_BASE}/${SVS_REPO_NAME}" + +echo ">>> Cloning/Updating ScalableVectorSearch repository in ${SVS_FULL_PATH}..." +if [ -d "${SVS_FULL_PATH}" ]; then + echo "ScalableVectorSearch directory ${SVS_FULL_PATH} already exists. Updating..." + cd "${SVS_FULL_PATH}" + git pull +else + git clone https://github.com/intel/ScalableVectorSearch.git "${SVS_FULL_PATH}" + cd "${SVS_FULL_PATH}" +fi +git config --global --add safe.directory "${SVS_FULL_PATH}" + +echo ">>> Attempting to build and install SVS Python bindings..." +echo "This step requires GCC/G++ 11 and Intel oneAPI tools (which should be sourced)." +echo "Current compilers: GCC=$(which gcc || echo not_found), G++=$(which g++ || echo not_found)" +# The oneAPI setvars.sh should have configured the environment for Intel compilers if available and preferred by SVS build. +# Otherwise, it should use the g++-11 from update-alternatives. +conda run -n "${CONDA_ENV_NAME}" pip install ./bindings/python +cd / + +echo "--------------------------------------------------------------------" +echo "Setup script finished successfully." +echo "To activate the conda environment (in a new shell, as root or user depending on .bashrc): conda activate ${CONDA_ENV_NAME}" +echo "QUAKE repository is in ${QUAKE_FULL_PATH}" +echo "Intel oneAPI (if installed) is in ${ONEAPI_INSTALL_PATH}. Source with: source ${ONEAPI_INSTALL_PATH}/setvars.sh" +echo "SVS repository (if cloned) is in ${SVS_FULL_PATH}" +echo "--------------------------------------------------------------------" From 250b91a3a75d5686d5ea74c26d0d80948d74fe26 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 10:39:11 -0500 Subject: [PATCH 202/323] update vary_levels --- test/experiments/osdi2025/experiment_utils.py | 5 +++-- test/experiments/osdi2025/vary_levels/run.py | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/test/experiments/osdi2025/experiment_utils.py b/test/experiments/osdi2025/experiment_utils.py index f18a75b1..14aef786 100644 --- a/test/experiments/osdi2025/experiment_utils.py +++ b/test/experiments/osdi2025/experiment_utils.py @@ -35,10 +35,11 @@ def prepare_quake_index( force_rebuild: bool = False, num_workers_load: int = 0, num_parent_workers_load: int = 0, - use_numa: bool = False + use_numa: bool = False, + load: bool = True ) -> QuakeIndex: idx = QuakeIndex() - if index_file_path.exists() and not force_rebuild: + if index_file_path.exists() and not force_rebuild and load: logger.info(f"Loading index from {index_file_path}") idx.load(str(index_file_path), num_workers_load, use_numa, num_parent_workers_load) else: diff --git a/test/experiments/osdi2025/vary_levels/run.py b/test/experiments/osdi2025/vary_levels/run.py index dcc3f3ce..5c63ba47 100644 --- a/test/experiments/osdi2025/vary_levels/run.py +++ b/test/experiments/osdi2025/vary_levels/run.py @@ -261,7 +261,8 @@ def run_experiment(config_path_str: str, output_dir_str: str) -> None: vecs=base_vecs, build_params_dict=l0_build_params_dict, index_file_path=base_child_index_path, - force_rebuild=overwrite_cfg.get("index", False) + force_rebuild=overwrite_cfg.get("index", False), + load=False ) logger.info(f"Base L0 index prepared at {base_child_index_path}") From 9bcc9426a35e886764f2b80d7812e52619ac0f01 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 10:53:38 -0500 Subject: [PATCH 203/323] update numa_single_query --- .../numa_single_query/configs/sift1m.yaml | 237 ++++--- .../osdi2025/numa_single_query/run.py | 603 ++++++++++-------- 2 files changed, 470 insertions(+), 370 deletions(-) diff --git a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml index f8a101e1..54c1711f 100644 --- a/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_single_query/configs/sift1m.yaml @@ -1,25 +1,84 @@ -# numa_latency_experiment.yaml dataset: name: sift1m - num_queries: 1 - k: 50 + num_queries: 100 + k: 1 -trials: 1 -warmup: 0 -overwrite: true # Set to true to force all indexes to rerun +trials: 3 +warmup: 1 +overwrite: true indexes: - - name: Quake_0 + - name: Quake_1_NUMA index: Quake build_params: nc: 1000 metric: l2 - num_workers: 0 - use_numa: false + num_workers: 1 + use_numa: true + search_params: + nprobe: 20 + + - name: Quake_2_NUMA + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 2 + use_numa: true + search_params: + nprobe: 20 + + - name: Quake_4_NUMA + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 4 + use_numa: true + search_params: + nprobe: 20 + + - name: Quake_8_NUMA + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 8 + use_numa: true search_params: - nprobe: 1 + nprobe: 20 - - name: Quake_1 + - name: Quake_16_NUMA + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 16 + use_numa: true + search_params: + nprobe: 20 + + - name: Quake_32_NUMA + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 32 + use_numa: true + search_params: + nprobe: 20 + + - name: Quake_64_NUMA + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 64 + use_numa: true + search_params: + nprobe: 20 + + - name: Quake_1_NONUMA index: Quake build_params: nc: 1000 @@ -27,101 +86,67 @@ indexes: num_workers: 1 use_numa: false search_params: - nprobe: 1 - -# - name: Quake_4 -# index: Quake -# build_params: -# nc: 1000 -# metric: l2 -# num_workers: 4 -# use_numa: false -# search_params: -# nprobe: 20 -# -# - name: Quake_16 -# index: Quake -# build_params: -# nc: 1000 -# metric: l2 -# num_workers: 16 -# use_numa: false -# search_params: -# nprobe: 20 -# -# - name: Quake_1_numa -# index: Quake -# build_params: -# nc: 1000 -# metric: l2 -# num_workers: 1 -# use_numa: true -# search_params: -# nprobe: 20 -# -# - name: Quake_4_numa -# index: Quake -# build_params: -# nc: 1000 -# metric: l2 -# num_workers: 4 -# use_numa: true -# search_params: -# nprobe: 20 -# -# - name: Quake_16_numa -# index: Quake -# build_params: -# nc: 1000 -# metric: l2 -# num_workers: 16 -# use_numa: true -# search_params: -# nprobe: 20 - -# - name: FaissIVF -# index: IVF -# build_params: -# nc: 1000 -# metric: l2 -# search_params: -# nprobe: 1000 -# -# - name: SCANN -# index: SCANN -# build_params: -# num_leaves: 1000 -# metric: squared_l2 -# search_params: -# leaves_to_search: 1000 -# -# - name: FaissHNSW -# index: HNSW -# build_params: -# m: 64 -# ef_construction: 128 -# metric: l2 -# search_params: -# ef_search: 32 -# -# - name: DiskANN -# index: DiskANN -# build_params: -# complexity: 128 -# graph_degree: 64 -# metric: l2 -# search_params: -# complexity: 32 -# -# - name: SVS -# index: SVS -# build_params: -# graph_max_degree: 64 -# alpha: 1.1 -# window_size: 128 -# metric: l2 -# search_params: -# search_window_size: 32 + nprobe: 20 + + - name: Quake_2_NONUMA + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 2 + use_numa: false + search_params: + nprobe: 20 + + - name: Quake_4_NONUMA + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 4 + use_numa: false + search_params: + nprobe: 20 + + - name: Quake_8_NONUMA + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 8 + use_numa: false + search_params: + nprobe: 20 + + - name: Quake_16_NONUMA + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 16 + use_numa: false + search_params: + nprobe: 20 + + - name: Quake_32_NONUMA + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 32 + use_numa: false + search_params: + nprobe: 20 + + - name: Quake_64_NONUMA + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 64 + use_numa: false + search_params: + nprobe: 20 output: results_csv: numa_single_query_results.csv \ No newline at end of file diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index a787c0d2..53b72969 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -1,26 +1,15 @@ -""" -NUMA Single-Query Latency and Recall Benchmark (detailed timers + parent) - -Tracks these phases, for both the worker_scan and its parent search: - - buffer_init_time_ns - - job_enqueue_time_ns - - job_wait_time_ns - - result_aggregate_time_ns - - total_time_ns - -Averages per‐query timers within each trial, then across trials, -and writes them (in ms) to the per‐index CSV. -""" import sys from pathlib import Path +import logging import yaml import numpy as np import torch import pandas as pd import matplotlib.pyplot as plt -from quake.utils import compute_recall -from quake.datasets.ann_datasets import load_dataset +from quake import SearchParams, SearchTimingInfo # Quake specific +from test.experiments.osdi2025 import experiment_utils as common_utils + from quake.index_wrappers.faiss_ivf import FaissIVF from quake.index_wrappers.faiss_hnsw import FaissHNSW from quake.index_wrappers.quake import QuakeWrapper @@ -46,260 +35,346 @@ "SVS": Vamana, } -def build_and_save(index_cls, params, vecs, path): - """Build and persist an index.""" - idx = index_cls() - idx.build(vecs, **params) - idx.save(str(path)) - -def extract_ids(res): - """Normalize returned IDs array.""" - if hasattr(res, "ids"): - arr = res.ids - elif hasattr(res, "I"): - arr = res.I - elif hasattr(res, "indices"): - arr = res.indices - else: - raise RuntimeError("Search result has no id field.") - if isinstance(arr, torch.Tensor): - arr = arr.cpu().numpy() - return np.asarray(arr, dtype=np.int64) - -def run_experiment(cfg_path: str, output_dir: str) -> None: - cfg = yaml.safe_load(Path(cfg_path).read_text()) - ds_cfg = cfg["dataset"] - k = ds_cfg["k"] - q_n = ds_cfg["num_queries"] - trials = cfg.get("trials", 5) - warmup_n = cfg.get("warmup", 10) - idx_cfgs = cfg["indexes"] - csv_name = cfg.get("output", {}).get("results_csv", "numa_results.csv") - overwrite = cfg.get("overwrite", False) - - out_dir = Path(output_dir).expanduser().absolute() - out_dir.mkdir(parents=True, exist_ok=True) - - # Load dataset - print(f"[INFO] loading dataset {ds_cfg['name']} …") - base_vecs, queries, gt = load_dataset(ds_cfg["name"]) - queries = queries[:q_n] - gt = gt[:q_n] if gt is not None else None - - # Build shared Quake base index once - quake_base_params = None - for c in idx_cfgs: - if c["index"] == "Quake": - p = dict(c.get("build_params", {})) - p.pop("num_workers", None) - p.pop("use_numa", None) - quake_base_params = p - break - - quake_base_path = out_dir / "Quake_base_index.bin" - if quake_base_params and not quake_base_path.exists(): - print("[BUILD] Quake (shared) base index …") - build_and_save(QuakeWrapper, quake_base_params, base_vecs, quake_base_path) - print(f"[SAVE] Quake base index → {quake_base_path}") - - results = [] - for cfg_i in idx_cfgs: - name = cfg_i["name"] - typ = cfg_i["index"] - b_params = dict(cfg_i.get("build_params", {})) - s_params = dict(cfg_i.get("search_params", {})) - cls = INDEX_CLASSES.get(typ) - if cls is None: - print(f"[WARN] unknown index type '{typ}' – skipping.") - continue +logging.basicConfig(level=logging.INFO, + format="%(asctime)s | %(levelname)7s | %(name)s | %(message)s", + datefmt="%H:%M:%S") +logger = logging.getLogger("numa_single_query_exp") - idx_csv = out_dir / f"{name}_results.csv" - idx_path = quake_base_path if typ == "Quake" else out_dir / f"{name}_index.bin" - if idx_csv.exists() and not overwrite: - print(f"[SKIP] {name} – results exist.") - results.append(pd.read_csv(idx_csv).iloc[0].to_dict()) - continue +def build_and_save_generic_index(index_cls, build_params_dict, base_vectors, index_file_path: Path): + if index_file_path.exists(): + logger.info(f"Index {index_file_path} already exists. Skipping build.") + return + logger.info(f"Building index {index_file_path}...") + idx_instance = index_cls() + # FaissIVF and FaissHNSW expect metric at build, not in build_params dict necessarily + metric = build_params_dict.pop("metric", "l2") + idx_instance.build(base_vectors, metric=metric, **build_params_dict) + index_file_path.parent.mkdir(parents=True, exist_ok=True) + idx_instance.save(str(index_file_path)) + logger.info(f"Index saved to {index_file_path}") + +def get_timing_details(timing_info_obj: SearchTimingInfo | None, is_parent: bool = False) -> dict: + prefix = "parent_" if is_parent else "child_" + details = { + f"{prefix}buffer_init_ns": np.nan, + f"{prefix}enqueue_ns": np.nan, + f"{prefix}wait_ns": np.nan, + f"{prefix}aggregate_ns": np.nan, + f"{prefix}total_time_ns": np.nan, + } + if timing_info_obj: + details[f"{prefix}buffer_init_ns"] = getattr(timing_info_obj, "buffer_init_time_ns", 0) + details[f"{prefix}enqueue_ns"] = getattr(timing_info_obj, "job_enqueue_time_ns", 0) + details[f"{prefix}wait_ns"] = getattr(timing_info_obj, "job_wait_time_ns", 0) + details[f"{prefix}aggregate_ns"] = getattr(timing_info_obj, "result_aggregate_time_ns", 0) + details[f"{prefix}total_time_ns"] = getattr(timing_info_obj, "total_time_ns", 0) + return details + + +def benchmark_single_query_detailed( + idx, + queries_tensor: torch.Tensor, + gt_tensor: torch.Tensor | None, + k_val: int, + search_params_dict: dict, + index_type: str, + num_trials: int, + warmup_runs: int +) -> dict: + + search_kwargs_final = {} + if index_type == "Quake": + # For Quake, convert dict to SearchParams object + # And pop non-SearchParams like 'nprobe' if they are handled differently + # For single query, SearchParams is directly constructed. + pass # SearchParams will be constructed per query for Quake + elif index_type == "SCANN": + search_kwargs_final = {"leaves_to_search": search_params_dict.get("leaves_to_search", 100)} + elif index_type == "HNSW": + search_kwargs_final = {"ef_search": search_params_dict.get("ef_search", 32)} + elif index_type == "DiskANN": + search_kwargs_final = {"complexity": search_params_dict.get("complexity", 32)} + elif index_type == "SVS": + search_kwargs_final = {"search_window_size": search_params_dict.get("search_window_size", 32)} + else: # IVF or other Faiss based that might use nprobe directly + search_kwargs_final = {"nprobe": search_params_dict.get("nprobe", 100)} - # Build non-Quake if needed - if typ != "Quake" and not idx_path.exists(): - print(f"[BUILD] {name} index …") - build_and_save(cls, b_params, base_vecs, idx_path) - print(f"[SAVE] index → {idx_path}") - - # Load index - if typ == "Quake": - load_kw = {k: b_params[k] for k in ("use_numa", "num_workers", "parent_num_workers") if k in b_params} - idx = QuakeWrapper(); idx.load(str(idx_path), **load_kw) - elif typ == "DiskANN": - idx = cls(); b_params.pop("metric", None); idx.load(str(idx_path), **b_params) + + logger.info(f"Warmup ({warmup_runs} queries)...") + for i in range(min(warmup_runs, len(queries_tensor))): + q_vec = queries_tensor[i].unsqueeze(0).float() + if index_type == "Quake": + idx.search(q_vec, k_val, **search_params_dict) else: - idx = cls(); idx.load(str(idx_path)) - - # Dispatch search parameters - if typ == "SCANN": - search_kw = {"leaves_to_search": s_params.get("leaves_to_search", 100)} - elif typ == "HNSW": - search_kw = {"ef_search": s_params.get("ef_search", 32)} - elif typ == "DiskANN": - search_kw = {"complexity": s_params.get("complexity", 32)} - elif typ == "SVS": - search_kw = {"search_window_size": s_params.get("search_window_size", 32)} + idx.search(q_vec, k_val, **search_kwargs_final) + + trial_aggregated_metrics = [] + + for t_idx in range(num_trials): + per_query_timings_in_trial = [] + recalls_in_trial = [] + + for q_idx, q_vec_single in enumerate(queries_tensor): + q_vec_single = q_vec_single.unsqueeze(0).float() + + search_result = None + if index_type == "Quake": + search_result = idx.search(q_vec_single, k_val, **search_params_dict) + else: + search_result = idx.search(q_vec_single, k_val, **search_kwargs_final) + + timing_info_child = getattr(search_result, "timing_info", None) + query_metrics = get_timing_details(timing_info_child, is_parent=False) + + if index_type == "Quake" and timing_info_child: # Quake specific parent info + timing_info_parent = getattr(timing_info_child, "parent_info", None) + query_metrics.update(get_timing_details(timing_info_parent, is_parent=True)) + else: # For non-Quake or if no parent_info + query_metrics.update(get_timing_details(None, is_parent=True)) + + + if gt_tensor is not None: + ids_this_query = search_result.ids + if ids_this_query.ndim == 2 and ids_this_query.shape[0] == 1: # Ensure it's [1, k_found] + recall_val = common_utils.quake_compute_recall( + ids_this_query, + gt_tensor[q_idx].unsqueeze(0), + k_val + ).item() + recalls_in_trial.append(recall_val) + + per_query_timings_in_trial.append(query_metrics) + + # Aggregate for this trial + trial_df = pd.DataFrame(per_query_timings_in_trial) + mean_metrics_for_trial = trial_df.mean().to_dict() + if recalls_in_trial: + mean_metrics_for_trial["recall"] = np.mean(recalls_in_trial) + + trial_aggregated_metrics.append(mean_metrics_for_trial) + logger.info(f" Trial {t_idx+1}/{num_trials}: " + f"child_total_ms={mean_metrics_for_trial.get('child_total_time_ns', np.nan)/1e6:.2f}, " + f"parent_total_ms={mean_metrics_for_trial.get('parent_total_time_ns', np.nan)/1e6:.2f}" + f"recall@{k_val}={mean_metrics_for_trial.get('recall', np.nan):.4f}") + + + # Aggregate across trials + final_metrics_df = pd.DataFrame(trial_aggregated_metrics) + results_summary = {} + for col in final_metrics_df.columns: + # Convert times from ns to ms for mean, keep std in ns then convert if needed, or just report mean in ms. + if col.endswith("_ns"): + results_summary[f"{col.replace('_ns', '_ms')}_mean"] = final_metrics_df[col].mean() / 1e6 + results_summary[f"{col.replace('_ns', '_ms')}_std"] = final_metrics_df[col].std() / 1e6 + elif col == "recall": + results_summary[f"recall_at_{k_val}_mean"] = final_metrics_df[col].mean() + results_summary[f"recall_at_{k_val}_std"] = final_metrics_df[col].std() + else: # other metrics if any + results_summary[f"{col}_mean"] = final_metrics_df[col].mean() + results_summary[f"{col}_std"] = final_metrics_df[col].std() + + return results_summary + + +def run_experiment(cfg_path_str: str, output_dir_str: str) -> None: + config = common_utils.load_config(cfg_path_str) + dataset_cfg = config["dataset"] + k_val = dataset_cfg["k"] + num_queries = dataset_cfg["num_queries"] + + exp_params_cfg = config # Top level items like trials, warmup + num_trials = exp_params_cfg.get("trials", 5) + warmup_runs = exp_params_cfg.get("warmup", 10) + + indexes_config_list = config["indexes"] + output_csv_name = config.get("output", {}).get("results_csv", "numa_single_query_summary.csv") + force_overwrite_results = config.get("overwrite", False) + # force_rebuild_indexes = config.get("force_rebuild", False) # If we add a global force_rebuild + + main_output_dir = Path(output_dir_str).expanduser().absolute() + main_output_dir.mkdir(parents=True, exist_ok=True) + + logger.info(f"Loading dataset '{dataset_cfg['name']}' for {num_queries} queries.") + base_vectors, query_vectors, gt_vectors = common_utils.load_data( + dataset_cfg["name"], + dataset_cfg.get("path", ""), # Allow path in dataset_cfg + nq_override=num_queries + ) + + # Shared Quake base index build logic (specific to this experiment script) + quake_base_build_params_shared = None + quake_base_index_file = main_output_dir / "Quake_base_index_single_query.bin" # Distinct name + + for idx_c in indexes_config_list: + if idx_c["index"] == "Quake": + temp_params = dict(idx_c.get("build_params", {})) + # These are stripped for the *base shared* build + temp_params.pop("num_workers", None) + temp_params.pop("use_numa", None) + temp_params.pop("parent_num_workers", None) # Not relevant for single level base + quake_base_build_params_shared = temp_params + break # Assume all Quake configs share the same base parameters for nc, metric etc. + + if quake_base_build_params_shared: + # Check if force_rebuild_indexes is globally set, or if file doesn't exist + # For now, let's assume force_rebuild_indexes comes from a potential global config key + # if 'force_rebuild_indexes' not in config: config['force_rebuild_indexes'] = False # Default + needs_shared_build = not quake_base_index_file.exists() # or config['force_rebuild_indexes'] + if needs_shared_build: + logger.info(f"Building shared Quake base index at {quake_base_index_file}...") + # For Quake, build_params_dict for prepare_quake_index needs 'metric' and 'nlist' (nc) + # Ensure these are present in quake_base_build_params_shared + if 'metric' not in quake_base_build_params_shared: + quake_base_build_params_shared['metric'] = dataset_cfg.get('metric', 'l2') + if 'nc' not in quake_base_build_params_shared and 'nlist' not in quake_base_build_params_shared : # common mistake + logger.error("Missing 'nc' (nlist) in Quake base build_params.") + # Fallback or error, for now assume it is there if this block is reached + else: + if 'nc' in quake_base_build_params_shared and 'nlist' not in quake_base_build_params_shared: + quake_base_build_params_shared['nlist'] = quake_base_build_params_shared.pop('nc') + + common_utils.prepare_quake_index( + vecs=base_vectors, + build_params_dict=quake_base_build_params_shared, + index_file_path=quake_base_index_file, + force_rebuild=needs_shared_build, # force if it doesn't exist + load=False + ) + logger.info(f"Shared Quake base index preparation complete at {quake_base_index_file}") else: - search_kw = {"nprobe": s_params.get("nprobe", 100)} - - # Warm-up - for q in queries[:min(warmup_n, len(queries))]: - idx.search(q.unsqueeze(0).float(), k, **search_kw) - - # Prepare accumulators - child_lat_trials = [] - parent_lat_trials = [] - child_buf_init_trials = [] - child_enq_trials = [] - child_wait_trials = [] - child_agg_trials = [] - child_total_trials = [] - parent_buf_init_trials = [] - parent_enq_trials = [] - parent_wait_trials = [] - parent_agg_trials = [] - parent_total_trials = [] - first_trial_recalls = [] - - for t in range(trials): - # per-query lists - child_lats = [] - parent_lats = [] - child_buf_init = [] - child_enq = [] - child_wait = [] - child_agg = [] - child_total = [] - parent_buf_init = [] - parent_enq = [] - parent_wait = [] - parent_agg = [] - parent_total = [] - recalls = [] - - for qi, q in enumerate(queries): - res = idx.search(q.unsqueeze(0).float(), k, **search_kw) - ti = res.timing_info - - # child latency - child_lats.append(ti.total_time_ns / 1e6) - child_buf_init.append(ti.buffer_init_time_ns) - child_enq.append( ti.job_enqueue_time_ns) - child_wait.append( ti.job_wait_time_ns) - child_agg.append( ti.result_aggregate_time_ns) - child_total.append( ti.total_time_ns) - - # parent latency (if exists) - pi = getattr(ti, "parent_info", None) - if pi and hasattr(pi, "total_time_ns"): - parent_lats.append(pi.total_time_ns / 1e6) - parent_buf_init.append(pi.buffer_init_time_ns) - parent_enq.append( pi.job_enqueue_time_ns) - parent_wait.append( pi.job_wait_time_ns) - parent_agg.append( pi.result_aggregate_time_ns) - parent_total.append( pi.total_time_ns) - else: - parent_lats.append(0.0) - parent_buf_init.append(0) - parent_enq.append(0) - parent_wait.append(0) - parent_agg.append(0) - parent_total.append(0) - - # recall on first trial only - if t == 0 and gt is not None: - preds = extract_ids(res)[0] - recalls.append(float(compute_recall(torch.tensor([preds]), gt[qi:qi+1], k).item())) - - # compute trial means - child_lat_trials.append(np.mean(child_lats)) - parent_lat_trials.append(np.mean(parent_lats)) - child_buf_init_trials.append(np.mean(child_buf_init)/1e6) - child_enq_trials .append(np.mean(child_enq) /1e6) - child_wait_trials .append(np.mean(child_wait) /1e6) - child_agg_trials .append(np.mean(child_agg) /1e6) - child_total_trials .append(np.mean(child_total) /1e6) - parent_buf_init_trials.append(np.mean(parent_buf_init)/1e6) - parent_enq_trials .append(np.mean(parent_enq) /1e6) - parent_wait_trials .append(np.mean(parent_wait) /1e6) - parent_agg_trials .append(np.mean(parent_agg) /1e6) - parent_total_trials .append(np.mean(parent_total) /1e6) - - if t == 0 and recalls: - first_trial_recalls.append(np.mean(recalls)) - - print(f" [{name} trial {t+1}/{trials}] " - f"child {child_lat_trials[-1]:.2f} ms, " - f"parent {parent_lat_trials[-1]:.2f} ms" - + (f" | R@{k} {first_trial_recalls[-1]:.4f}" if recalls else "")) - - # assemble final row - row = { - "index": name, - "n_workers": b_params.get("num_workers", np.nan), - "child_mean_latency_ms": float(np.mean(child_lat_trials)), - "child_std_latency_ms": float(np.std(child_lat_trials)), - f"recall_at_{k}": (float(first_trial_recalls[0]) if first_trial_recalls else np.nan), - "child_buffer_init_ms": float(np.mean(child_buf_init_trials)), - "child_enqueue_ms": float(np.mean(child_enq_trials)), - "child_wait_ms": float(np.mean(child_wait_trials)), - "child_aggregate_ms": float(np.mean(child_agg_trials)), - "child_total_time_ms": float(np.mean(child_total_trials)), - "parent_mean_latency_ms":float(np.mean(parent_lat_trials)), - "parent_buffer_init_ms": float(np.mean(parent_buf_init_trials)), - "parent_enqueue_ms": float(np.mean(parent_enq_trials)), - "parent_wait_ms": float(np.mean(parent_wait_trials)), - "parent_aggregate_ms": float(np.mean(parent_agg_trials)), - "parent_total_time_ms": float(np.mean(parent_total_trials)), - } - results.append(row) - pd.DataFrame([row]).to_csv(idx_csv, index=False) - - # write aggregate CSV + plots - df = pd.DataFrame(results) - out_csv = Path(output_dir) / csv_name - df.to_csv(out_csv, index=False) - print(f"\n[RESULT] aggregated CSV → {out_csv}") - - # latency plot (child only for clarity) - plt.figure() - for nm in df["index"].unique(): - sub = df[df["index"] == nm] - lbl = (nm if sub["n_workers"].isnull().all() - else f"{nm} (nw={int(sub['n_workers'].iloc[0])})") - plt.errorbar( - sub["n_workers"] if "n_workers" in sub else sub.index, - sub["child_mean_latency_ms"], - yerr=sub["child_std_latency_ms"], - marker="o", capsize=5, label=lbl + logger.info(f"Using existing shared Quake base index from {quake_base_index_file}") + + + all_experiment_rows = [] + + for idx_conf in indexes_config_list: + index_name = idx_conf["name"] + index_type_str = idx_conf["index"] + current_build_params = dict(idx_conf.get("build_params", {})) # Copy for modification + current_search_params = dict(idx_conf.get("search_params", {})) + + IndexCls = INDEX_CLASSES.get(index_type_str) + if IndexCls is None or (IndexCls == Scann and Scann is None): + logger.warning(f"Index type '{index_type_str}' for '{index_name}' is unavailable. Skipping.") + continue + + per_index_csv_path = main_output_dir / f"{index_name}_detailed_results.csv" + + if per_index_csv_path.exists() and not force_overwrite_results: + logger.info(f"Results for {index_name} exist at {per_index_csv_path}. Loading cached.") + try: + # Assuming one row per config in these detailed CSVs + cached_df = pd.read_csv(per_index_csv_path) + if not cached_df.empty: + all_experiment_rows.append(cached_df.iloc[0].to_dict()) + except Exception as e: + logger.error(f"Could not load cached results for {index_name}: {e}") + continue + + logger.info(f"--- Processing index: {index_name} (Type: {index_type_str}) ---") + + idx_instance = None + if index_type_str == "Quake": + if not quake_base_index_file.exists(): + logger.error(f"Shared Quake base index {quake_base_index_file} not found for {index_name}. Skipping.") + continue + idx_instance = QuakeWrapper() + # Load-time parameters for this specific Quake configuration + load_time_workers = current_build_params.get("num_workers", 0) + load_time_use_numa = current_build_params.get("use_numa", False) + load_time_parent_workers = current_build_params.get("parent_num_workers", 0) # If applicable + logger.info(f"Loading Quake index '{index_name}' from shared base with: " + f"workers={load_time_workers}, numa={load_time_use_numa}, parent_workers={load_time_parent_workers}") + idx_instance.load(str(quake_base_index_file), + num_workers=load_time_workers, + use_numa=load_time_use_numa, + parent_num_workers=load_time_parent_workers) + else: # For non-Quake indexes + generic_idx_file_path = main_output_dir / f"{index_name}_index.bin" + # Assume force_rebuild_indexes applies here too, or build if not exists + # build_if_needed_flag = not generic_idx_file_path.exists() # or config['force_rebuild_indexes'] + # if build_if_needed_flag: + build_and_save_generic_index(IndexCls, current_build_params.copy(), base_vectors, generic_idx_file_path) + + idx_instance = IndexCls() + load_params_non_quake = current_build_params.copy() + if index_type_str == "DiskANN": load_params_non_quake.pop("metric", None) # DiskANN doesn't take metric at load + idx_instance.load(str(generic_idx_file_path), **load_params_non_quake) + + + if idx_instance is None: + logger.error(f"Failed to load or build index {index_name}. Skipping.") + continue + + benchmark_results = benchmark_single_query_detailed( + idx_instance, query_vectors, gt_vectors, k_val, + current_search_params, index_type_str, num_trials, warmup_runs ) - plt.xscale("symlog", base=2) - plt.xlabel("Num Workers"); plt.ylabel("Mean Child Latency (ms)") - plt.title("Single-Query Child Latency"); plt.legend(); plt.tight_layout() - lat_path = Path(output_dir) / f"{out_csv.stem}_child_latency.png" - plt.savefig(lat_path) - print(f"[PLOT] child latency plot → {lat_path}") - - # recall plot - if f"recall_at_{k}" in df.columns: - plt.figure() - for nm in df["index"].unique(): - sub = df[df["index"] == nm] - lbl = (nm if sub["n_workers"].isnull().all() - else f"{nm} (nw={int(sub['n_workers'].iloc[0])})") + + # Combine config with results + final_row_data = {"index_name": index_name, "index_type": index_type_str} + final_row_data.update({f"build_{k}": v for k,v in current_build_params.items()}) + final_row_data.update({f"search_{k}": v for k,v in current_search_params.items()}) + final_row_data.update(benchmark_results) + + all_experiment_rows.append(final_row_data) + common_utils.save_results_csv(pd.DataFrame([final_row_data]), per_index_csv_path) + + if not all_experiment_rows: + logger.warning("No results collected. Skipping final CSV and plots.") + return + + final_summary_df = pd.DataFrame(all_experiment_rows) + unified_csv_path = main_output_dir / output_csv_name + common_utils.save_results_csv(final_summary_df, unified_csv_path) + logger.info(f"Unified results for NUMA single-query written to {unified_csv_path}") + + # Plotting (using the structure from the original script) + plot_suffix = Path(output_csv_name).stem + + # Mean Latency (child_total_time_ms_mean) vs. build_num_workers + if "child_total_time_ms_mean" in final_summary_df.columns and "build_num_workers" in final_summary_df.columns: + plt.figure(figsize=(10, 6)) + for name_plot, group_data in final_summary_df.groupby("index_name"): + sorted_group = group_data.sort_values(by="build_num_workers") + yerr_val = sorted_group["child_total_time_ms_std"] if "child_total_time_ms_std" in sorted_group else None + plt.errorbar( + sorted_group["build_num_workers"], # Treat as categorical for distinct points + sorted_group["child_total_time_ms_mean"], + yerr=yerr_val, + marker="o", capsize=5, label=name_plot, linestyle='-' + ) + # plt.xscale("symlog", base=2) # May not be ideal if num_workers are not powers of 2 or include 0 + plt.xlabel("Build Param: Num Workers (Configuration)") + plt.ylabel("Mean Single-Query Latency (ms) - Child Total") + plt.title(f"NUMA Single-Query: Latency vs. Num Workers ({dataset_cfg['name']})") + plt.legend(title="Index Configuration", bbox_to_anchor=(1.05, 1), loc='upper left') + plt.grid(True, linestyle=':', alpha=0.7) + plt.tight_layout(rect=[0,0,0.8,1]) # Adjust for legend + plt.savefig(main_output_dir / f"{plot_suffix}_latency_vs_workers.png", dpi=150) + logger.info(f"Latency plot saved to {main_output_dir / f'{plot_suffix}_latency_vs_workers.png'}") + plt.close() + + recall_col_name = f"recall_at_{k_val}_mean" + if recall_col_name in final_summary_df.columns and "build_num_workers" in final_summary_df.columns: + plt.figure(figsize=(10, 6)) + for name_plot, group_data in final_summary_df.groupby("index_name"): + sorted_group = group_data.sort_values(by="build_num_workers") plt.plot( - sub["n_workers"] if "n_workers" in sub else sub.index, - sub[f"recall_at_{k}"], marker="o", label=lbl + sorted_group["build_num_workers"], + sorted_group[recall_col_name], + marker="o", label=name_plot, linestyle='-' ) - plt.xscale("symlog", base=2) - plt.xlabel("Num Workers"); plt.ylabel(f"Recall@{k}") - plt.title(f"Recall@{k}"); plt.legend(); plt.tight_layout() - rec_path = Path(output_dir) / f"{out_csv.stem}_recall.png" - plt.savefig(rec_path) - print(f"[PLOT] recall plot → {rec_path}") \ No newline at end of file + plt.xlabel("Build Param: Num Workers (Configuration)") + plt.ylabel(f"Mean Recall@{k_val}") + plt.title(f"NUMA Single-Query: Recall vs. Num Workers ({dataset_cfg['name']})") + plt.legend(title="Index Configuration", bbox_to_anchor=(1.05, 1), loc='upper left') + plt.grid(True, linestyle=':', alpha=0.7) + plt.ylim(0, 1.05) # Typical recall range + plt.tight_layout(rect=[0,0,0.8,1]) + plt.savefig(main_output_dir / f"{plot_suffix}_recall_vs_workers.png", dpi=150) + logger.info(f"Recall plot saved to {main_output_dir / f'{plot_suffix}_recall_vs_workers.png'}") + plt.close() + + logger.info("NUMA Single-Query experiment finished.") \ No newline at end of file From be446efe76ad4fd0382bae203585ca106e5df322 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 11:04:42 -0500 Subject: [PATCH 204/323] update numa_single_query --- src/python/datasets/ann_datasets.py | 4 +- test/experiments/osdi2025/README.md | 13 ++ .../configs/msturing10m.yaml | 153 +++++++++++++++++- 3 files changed, 160 insertions(+), 10 deletions(-) diff --git a/src/python/datasets/ann_datasets.py b/src/python/datasets/ann_datasets.py index a2ba8797..a7ba1459 100644 --- a/src/python/datasets/ann_datasets.py +++ b/src/python/datasets/ann_datasets.py @@ -183,7 +183,7 @@ def download(self, overwrite: bool = False): pass def load_vectors(self) -> Union[np.ndarray, torch.Tensor]: - fname = self.data_dir / "base1b.fbin.crop_nb_10000000" + fname = self.data_dir / "base1b.fbin.crop_nb_100000000" n, d = map(int, np.fromfile(fname, dtype="uint32", count=2)) # return to_torch(np.fromfile(fname, dtype=np.float32, offset=8).reshape((n, d))) return torch.from_numpy(np.fromfile(fname, dtype=np.float32, offset=8).reshape((n, d))) @@ -195,7 +195,7 @@ def load_queries(self) -> Union[np.ndarray, torch.Tensor]: return torch.from_numpy(np.fromfile(fname, dtype=np.float32, offset=8).reshape((n, d))) def load_ground_truth(self) -> Union[np.ndarray, torch.Tensor]: - fname = self.data_dir / "msturing-gt-10M" + fname = self.data_dir / "msturing-gt-100M" n, d = map(int, np.fromfile(fname, dtype="uint32", count=2)) assert os.stat(fname).st_size == 8 + n * d * (4 + 4) f = open(fname, "rb") diff --git a/test/experiments/osdi2025/README.md b/test/experiments/osdi2025/README.md index b62a81fe..fdd42c91 100644 --- a/test/experiments/osdi2025/README.md +++ b/test/experiments/osdi2025/README.md @@ -31,6 +31,19 @@ Each experiment directory (e.g., `aps_recall_targets`, `early_termination`) cont - Linux (Tested on Ubuntu 22.04) - Conda package manager +### Install from Scratch + +This will install Quake, the baselines and all necessary dependencies. + +Run `sudo install.sh` + +This will install: +- C + +### Quake Installation Only (No Baselines) + +To just evaluate Quake use this. + 1. **Clone the Repository:** ```bash git clone [https://github.com/marius-team/quake.git](https://github.com/marius-team/quake.git) diff --git a/test/experiments/osdi2025/numa_single_query/configs/msturing10m.yaml b/test/experiments/osdi2025/numa_single_query/configs/msturing10m.yaml index 327e20ba..8c671df9 100644 --- a/test/experiments/osdi2025/numa_single_query/configs/msturing10m.yaml +++ b/test/experiments/osdi2025/numa_single_query/configs/msturing10m.yaml @@ -1,15 +1,152 @@ -# existing keys... dataset: - name: sift1m + name: msturing10m num_queries: 100 - k: 10 - nprobe: 100 + k: 1 -n_workers: [0,1,2,4,8,16] +trials: 2 +warmup: 1 +overwrite: true # Set to true to force all indexes to rerun -# new keys: -trials: 5 -warmup: 10 +indexes: + - name: Quake_1_NUMA + index: Quake + build_params: + nc: 10000 + metric: l2 + num_workers: 1 + use_numa: true + search_params: + nprobe: 2000 + + - name: Quake_2_NUMA + index: Quake + build_params: + nc: 10000 + metric: l2 + num_workers: 2 + use_numa: true + search_params: + nprobe: 2000 + + - name: Quake_4_NUMA + index: Quake + build_params: + nc: 10000 + metric: l2 + num_workers: 4 + use_numa: true + search_params: + nprobe: 2000 + + - name: Quake_8_NUMA + index: Quake + build_params: + nc: 10000 + metric: l2 + num_workers: 8 + use_numa: true + search_params: + nprobe: 2000 + + - name: Quake_16_NUMA + index: Quake + build_params: + nc: 10000 + metric: l2 + num_workers: 16 + use_numa: true + search_params: + nprobe: 2000 + + - name: Quake_32_NUMA + index: Quake + build_params: + nc: 10000 + metric: l2 + num_workers: 32 + use_numa: true + search_params: + nprobe: 2000 + + - name: Quake_64_NUMA + index: Quake + build_params: + nc: 10000 + metric: l2 + num_workers: 63 + use_numa: true + search_params: + nprobe: 2000 + + - name: Quake_1_NONUMA + index: Quake + build_params: + nc: 10000 + metric: l2 + num_workers: 1 + use_numa: false + search_params: + nprobe: 2000 + + - name: Quake_2_NONUMA + index: Quake + build_params: + nc: 10000 + metric: l2 + num_workers: 2 + use_numa: false + search_params: + nprobe: 2000 + + - name: Quake_4_NONUMA + index: Quake + build_params: + nc: 10000 + metric: l2 + num_workers: 4 + use_numa: false + search_params: + nprobe: 2000 + + - name: Quake_8_NONUMA + index: Quake + build_params: + nc: 10000 + metric: l2 + num_workers: 8 + use_numa: false + search_params: + nprobe: 2000 + + - name: Quake_16_NONUMA + index: Quake + build_params: + nc: 10000 + metric: l2 + num_workers: 16 + use_numa: false + search_params: + nprobe: 2000 + + - name: Quake_32_NONUMA + index: Quake + build_params: + nc: 10000 + metric: l2 + num_workers: 32 + use_numa: false + search_params: + nprobe: 2000 + + - name: Quake_64_NONUMA + index: Quake + build_params: + nc: 10000 + metric: l2 + num_workers: 64 + use_numa: false + search_params: + nprobe: 2000 output: results_csv: numa_single_query_results.csv \ No newline at end of file From 66859899ea186001a24f1b4d4c54b42d0b7720f6 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 11:08:57 -0500 Subject: [PATCH 205/323] update numa_single_query --- test/experiments/osdi2025/experiment_utils.py | 2 +- test/experiments/osdi2025/numa_single_query/run.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/test/experiments/osdi2025/experiment_utils.py b/test/experiments/osdi2025/experiment_utils.py index 14aef786..3dafc5cf 100644 --- a/test/experiments/osdi2025/experiment_utils.py +++ b/test/experiments/osdi2025/experiment_utils.py @@ -20,7 +20,7 @@ def load_config(cfg_path: str) -> dict: return yaml.safe_load(Path(cfg_path).read_text()) -def load_data(dataset_name: str, dataset_path: str, nq_override: int = None): +def load_data(dataset_name: str, dataset_path: str = "data/", nq_override: int = None): vecs, queries, gt = quake_load_dataset(dataset_name, dataset_path) if nq_override is not None and nq_override > 0 and nq_override < len(queries): queries = queries[:nq_override] diff --git a/test/experiments/osdi2025/numa_single_query/run.py b/test/experiments/osdi2025/numa_single_query/run.py index 53b72969..5682f89c 100644 --- a/test/experiments/osdi2025/numa_single_query/run.py +++ b/test/experiments/osdi2025/numa_single_query/run.py @@ -198,7 +198,6 @@ def run_experiment(cfg_path_str: str, output_dir_str: str) -> None: logger.info(f"Loading dataset '{dataset_cfg['name']}' for {num_queries} queries.") base_vectors, query_vectors, gt_vectors = common_utils.load_data( dataset_cfg["name"], - dataset_cfg.get("path", ""), # Allow path in dataset_cfg nq_override=num_queries ) From 6db547b2c99e195cffb76f066cc0caabde06fdd0 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 11:26:46 -0500 Subject: [PATCH 206/323] update readme and add paper --- test/experiments/osdi2025/README.md | 65 ++++++++++++++---- .../osdi2025/paper/Quake-Revision.pdf | Bin 0 -> 1081872 bytes test/experiments/osdi2025/paper/Quake.pdf | Bin 0 -> 1096475 bytes 3 files changed, 53 insertions(+), 12 deletions(-) create mode 100644 test/experiments/osdi2025/paper/Quake-Revision.pdf create mode 100644 test/experiments/osdi2025/paper/Quake.pdf diff --git a/test/experiments/osdi2025/README.md b/test/experiments/osdi2025/README.md index fdd42c91..3f717c6e 100644 --- a/test/experiments/osdi2025/README.md +++ b/test/experiments/osdi2025/README.md @@ -37,8 +37,11 @@ This will install Quake, the baselines and all necessary dependencies. Run `sudo install.sh` -This will install: -- C +This will: +- Install required system packages (GCC/G++ 11, CMake, Miniconda, Intel oneAPI, etc.) +- Set up a Conda environment (quake-env) with all Python dependencies +- Build and install the Quake library and baselines (Faiss, SCANN, DiskANN, SVS) +- Automatically clone, build, and install all required repositories ### Quake Installation Only (No Baselines) @@ -102,21 +105,59 @@ OMP_NUM_THREADS=1 python3 -m test.experiments.osdi2025.experiment_runner \ --experiment kick_the_tires \ --config sift1m ``` - Outputs will be in `test/experiments/osdi2025/kick_the_tires/results/sift1m/`. +### Quick Reproduction + +These experiments should take less than 10 minutes to run in total. + +1. Reproduction of APS (Figure 6 in `paper/Quake.pdf`) + + This compares an Oracle against APS at various recall targets. + + ```bash + OMP_NUM_THREADS=1 python3 -m test.experiments.osdi2025.experiment_runner \ + --experiment aps_recall_targets \ + --config sift1m + ``` + +2. Reproduction of NUMA-aware searching (Figure 5 in `paper/Quake.pdf`) + + This measures query latency and varies the number of workers used in searching and whether partitions are pinned to NUMA regions. + + ```bash + OMP_NUM_THREADS=1 python3 -m test.experiments.osdi2025.experiment_runner \ + --experiment numa_single_query \ + --config msturing10m + ``` + +3. Maintenance Ablation Study (Table 6 in `paper/Quake-Revision.pdf`) + + This removes critical pieces of the Quake maintenance policy and measure its effect on workload performance. + + ```bash + OMP_NUM_THREADS=1 python3 -m test.experiments.osdi2025.experiment_runner \ + --experiment maintenance_ablation \ + --config sift1m + ``` + + +### Full Reproduction (In progress) + ## Experiment Summaries and Outputs -The following table summarizes each experiment and its primary outputs. Output files are generated within the experiment's specific output directory (refer to the `--output-dir` option or its default value). +The following table summarizes each experiment and their figure/table in paper. Output files are generated within the experiment's specific output directory (refer to the `--output-dir` option or its default value). + +Some experiments are added as revisions for the camera ready. See `paper/Quake.pdf` for the initial submission and `paper/Quake-Revision.pdf` for the revised version -| Experiment Name | Description | Reproduces in Paper | -|------------------------|--------------------------------------------------------------------------------------------------------------|-------------------------------| -| `aps_recall_targets` | Evaluates Quake's Adaptive Partition Scanning (APS) against baselines for various recall targets. | Figure 6 | -| `early_termination` | Compares APS with early termination strategies like LAET and Auncel. | Revision Experiment (Table 5) | -| `kick_the_tires` | Basic dynamic workload stress test focusing on latency, recall, and system state over operations. | | -| `maintenance_ablation` | Evaluates the impact of Quake's maintenance operations under a dynamic workload, extending `kick_the_tires`. | Revision Experiment (Table 6) | -| `numa_multi_query` | Tests Quake's multi-query batch performance under different NUMA and worker configurations. | | -| `numa_single_query` | Tests Quake's single-query performance under different NUMA and worker configurations. | Figure 5 | +| Experiment Name | Description | Reproduces in Paper | +|------------------------|----------------------------------------------------------------------------------------------------|---------------------------| +| `aps_recall_targets` | Evaluates Quake's Adaptive Partition Scanning (APS) against baselines for various recall targets. | Figure 6 in Quake | +| `early_termination` | Compares APS with early termination strategies like LAET and Auncel. | Table 5 in Quake-Revision | +| `kick_the_tires` | Basic dynamic workload stress test focusing on latency, recall, and system state over operations. | | +| `maintenance_ablation` | Evaluates the impact of Quake's maintenance operations under a dynamic workload. | Table 6 in Quake-Revision | +| `numa_multi_query` | Tests Quake's multi-query batch performance under different NUMA and worker configurations. | Revision Experiment | +| `numa_single_query` | Tests Quake's single-query performance under different NUMA and worker configurations. | Figure 5 in Quake | **To run any of these, replace `` and `` in the general command structure.** For example, to run the `aps_recall_targets` experiment with its `sift1m` configuration: diff --git a/test/experiments/osdi2025/paper/Quake-Revision.pdf b/test/experiments/osdi2025/paper/Quake-Revision.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2adb688397192b00c1492a3a4afcb711aa370b5b GIT binary patch literal 1081872 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 z,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

;U^tlya~=3MAO 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 z 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 _YP>Y2 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%0DicH=Yg{tTj?&I5JlxPu*>Q#<`X6_G>f^iQ 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%0A-h;mjL!8N8-k*#1a!kgXAr zM|w$}>|v1IQ@48PagMyw5dD%zBSH*)Z59A*M7jo-j0_y2H>DKKoVM51sX7JxqAs~7 zV+)-NAO4;m1IL7*AYCwv^Dt;xWI~Mv)Qx#WN@RrNNAQ(odQu?1dP7}id}a9#xss$L z+i68)_TiFb2ieyP%rblpytuYJ2O?fV-{htpJexmbx$J5|w!0l-0rE`X7UbJWDX_fa zM@ga=|E=#(&t{5$e>B|7@{bRSdYz$>&8ZbTjG0T;y%jM_Zj{5OXdS}iWSfwe0!e%7 zI`g^Bxf8}F*}RqmUslZZ3#uHDpy^d) zL$VJR&3IUI-DtNXcBtsCp66tQE{3?_vr3+p8>5+<8qRxIN1=tyj^fd*MN36a@`9o{ z23yq-7+QMoRfC936MaUU%J=^F-w|%PKs4I_s3B+)w<)ofS?G!pvgfqEjf0-8(ykGMsZylGW;UU;fJCWnPjdV)b_L-kKtF+iDjb*zc zSj`5gGDZ!|loYX7Q@7GDx1ufH?0E=SD1yQ*EfP+J*5;g*9$>4SpZHZi$q~dLmw-<3 ztApU~$hD4VET>l^-PLqWQkLK5vKhRs9wBea8Yl#xHs@dFXna2Ngum}VV!ecejq2tP zy*u^Ty2s|msr?Es1bum%HabQsO?JfVhDp0L=PHNsFbNt!v`P-R7wVQCiD|S`g^CET zbqt(H+Q&o7*OLO2-zfQ>r-n7&$@`?J}d5LCBB9gr=- zP^lufvcMIcEGBt~;+*r0jaHq!=LR;Zxu`~Z=b504^BpJ)ZhtVeb)1w>1!lStx^%kV0upv%#grV3`#t^e zx~d6N3EKLF{%M6!hwdU*b?t1+bgYSeJQQ=oX0v|D>_NnfO>;n5y6uoMF>><)F@3WC z9Zd#0dvQ-ksb(wkDwn~;vofUQsp&!tgY~H3)kP|l!jG$AZE{1Ak71vi={G-D$!Fm^ z;?TYX(D=;2BDgvxGhCpFUx-3}V#c@nuW%>PUI)TD$22raJmw}(=$i48hUozi6I?=WpA|m6Jc%CK}ZqGiTivJ@HR2*KLe41kxUlEF+W)PkvpfGJd2s z*T@V=QjYzDCj9W^;Ke1#qO@Ov0-m3^a=D+>^@u*FX48UHM0sUEjW#k;`V4J5s{^%I zrDS`_Zm})>lH%|bj!LefF0^i`nPKF==zkI_V@7yRy^a_FPe8E0SjHJDEre*+0o9=v?gSQY! zIx*-HNg>@e0US@DVWZC_WGN8}0mVLX7-XAzYA7T};h^oDsCEmIsQg?}#b!>Az=>(D zaDL?LLRN|u1rY9x&9-WIuIVu!aa25&8A=h{{az#b;4N=-LLcGfy(eSaEt~g$%#(q> zeqg(yUQF^+FJ=Y8{6{@|bz6_hMrJEtgQ-ycG{}Lsp4QcM^Iw#{@*(ss=^R_b^@R3m zgSap|l@JUH_K%BoL-k~Vj$=71A=-ZaiW*R~yHhB>^$chyr4(rBcH)8EDQTo^ATn%p zitt(Tp&fMS>XV2=-)VdAU#4LzjPKW~SzEa;zAX0Bpz>4^DSTO(nON^6=HNRYojFOV z_rZvJ*1;$S&!V(})-qeoPWh4P0S9A8>wFla_C|-xjks=42w9v|M__v_-hzU}Qt|?G zB^b(!3)Vn@GVyCDk;r4qZzcN+MP=V77klbQ4XP(?b2#ddQz!qJ=6k$`4)n-|E-5{S zz8Q9!SR|rYcizTBvcc@Ng^y~~8o01xEk=sdG!+K&3Jx1exmTu!N;XQf2F!?OG^fgy zpXumJUxULRR}DiY(%m{6LS(z-E9Y3%aa00jW8iUdph!3+=a7wzV(v9 zoCAzsP7F9nT8d~F1esRlnZ$R)4FW;=bEKN7UdW?j;ZEhBL1z$M9#pL(vh@SGh; zBsMb3DBn#S7Ge30=MhHS!k>P6A?uk~lX=u8mcWl{ALOxQAk0w6*VX>Us7s__eR;Gn zLJ8fsO6pa~Dev+_v9A?u?#FM$-18N!lxdgo^BvGO`+BE?D^-~KpWk1j<|YB;tQlr} zfdDU15vvuA2PywDHvu$5vtD;^Y1gqC9)g~^SW&CcusmhJ-*jw&BdAbp?g(AlEeBr2 ze1%g@J3-_#!7cXPS;>fA7H?mhH>!7>|k6coZ6*FG{Cj_qAsb~#rN z`(prC0uUH4iN%)jcNlz|NT*y;d18%5mhj;$I1IU2wTLkQx@Qb^PpcZwlIX@b&eH83 z9_@5T-(ft%c)}*IODl-%C`0cyv@VyLKw}Wtq_L^gK1kUyFpdmXVN}u^&nxqlL5G6auH$vvyBUmg<((c z_*%v}6%2kHP*=~wTe)?CIr9uJ%_NqTJ!?OLRzvPQxRH5`G$M;qt?jLk1UCvqc&rhQ z4q_|?`Ce$8Nb*iOF}5wFF6NID(NAj+CF~II;(#aFXnX1P{{f@!T4>uk@Zo|;{3_x})MK6PG z+_%XgB%bCe{Z&J8sx1JVZ|TDgcnYd*q9!kPmDsw9&i-+JS(W_$d|)W5p)<2?wzKb@ zrY=IgT3!i$r2}$}st+s6tj9jUC}nsXQ5E&ibwQt;{W@v{ z?_;14?~n6&sa2yCv80x5e`y73uCw{fiUyAafI)SV*;9ZDVAibzMIlnD6pgCSH>B3q za1l-8TH}abnWTfm*pStbs1$2LtQM5NM_yXQlKHf%L*_YJy!FA5dDjq-_$Pv|7F}W; znesdD5iPqi7eKeEAn5B58cq1pp1#Gj9+r?u&n_X7=s}uk-qU^}2d;`BXF->?dw#(3 zO8IGSm0LtAho>DI76U@}<^3;*Yj;w7uSkrd13G$MnQD!Ud-jL3zIN}|(hq$b=zi6$ z(euwu5mDa47&3Q`FV`MeRh&jz4kXFRho=jQ!Rc`shHkW4B7x= zy`_CgdEJ=ZuZsp#`6e zl-xX`JJeWTs#lHRS#9gF!2js%uRV})8Z{^|B4^}~3cvMq_@JS+&qXPy!*9)TsHPC@ zg?xEFzf02EXKlVK<5e+|L>qazt_c60S8+5|=e&yTozBap>(btWMK}7|_2~;h2N3Jd zycNg9Td`S&C?2Px?z@t`(xbiC0&d8wycJSq;v5O*py7?l!^cD9%wDeP5J_Bl<$VI`Fj)B$J*pLAE|3AdZ_)o;BvO3afD) z4ne8NjoxmlHlZF?1@xOoDx*LjN^>wP0{h7kTn7=6k+^hYe?FXkDiJ@J zxyO6;k3Y8Y(codtQINIj(w|^2%?$*?$$8YQEwtvU<(qXh@C*MZU^RnY*2kQY$-mH` zB9zcJII(-!z#5`<6rs^yq0Z%%j(SXU!{q_4CUQK-@9?1l9qNJAbu#+3<-xrPScZI8 zy^-g6ssip?L4%&3UT<9V%~GLRL-FIoPsCn*e)lgc{4A~q36)L&i&T7!l*h+7R$YCj zgh^n6K7l|UHSe;){`|dHIqKX<=Z7zIq~RJ`-GwK{xuN{HWshN(vZ=j!97~7pWVeA2 z>U%OnKvkk*%WKD`+;3b&nW0$npdZ|T$E_5rK20n@>PxHRTdVD4vv}*#Gir zuf>J3BZ^(Avkbjfb2Ad5S4w5}`bim6E^h?@S$c~K-R*0hw1&UEaJ&cyfuaQyToG*4 z6bZpsHf(^y-+bnQxB&zhGN$F|yaJ2Cmdc?ZJ)24tr6yUdheP`%^udlUN)?Z@N1wo* zm=OZH#l!ckCZym^oFg>x2fZ}_nz>}uZ4K5J&Z`*kz#EF{%Scptn}0r{X8m6#;2<@v z&!^3Cd^O8nw#}Z}Pr=SN8qq?I3M#ZYY)D12^X=eF94%*`<24=fQM}CdbBQGG`Lq~x zrA(0J#ht6Ltvt-!D{M88J}%1D9T=cDqX*|c=9asEXUeU{07c2KM%Pa-_G8~ zs8z0K$W07Cn_6YO_Tp5g>DV+9{=2Vr_TcDiiWchQf8j+{xQm>*3@N_X?{4rW*4v|( zf5ZFDJQ4%9w8r&+CJ-?_=6w9RCj&e7ucoipMiNrGk8LSt|)cm;!p&J!bV zRub!eC|}2^eZZPa3r(F{2F>j_`J{8n9$TYpOWoK}%1W!DjF?FA9s-_Zcsi9e@jU!S z@Wb0eBm)Z^FqmGuMc}kF0XE0^>3E8>AijB24-Ka?ldppxglWOb()dyCRq?Yn0tB)pe>;m=%@f!okum zFx#Yx4v;JeBzC~_x^H3RTR|}2i`QcEU5-)2--xJExOlG0>$FtdKpDlN8u}+sm#@NG zl8xFHhCEiL0l%^pUpf+rFim_C?xmG@jYKD)v8`TUK14vyu>*bih-Q__MKg7{29%nwxE0?3^gXW1VqvcU~p*rlBunAAsR>mo7F20W7Au6S1i zt)V#H?IsHYe$0E_*pgGEFvVcd}#_s>d*e`3@u5;f20zSh4E-1ty3ogYp@i9KTxqN zF97DVA1x-iJeJ?JWkA3z;*I|WjL2-|{yGMp`r}}Bd)8?r{8jDj;ZJpj_ILzffdGVi z8DO=VU3|G~FHdfZION1h>+u}c1_D9(NBjIMr3i{sx2$UU&M${^o@#OznoF=~|_iJR8Q1fG@=y)vHNMNIOfesUP zH@iI0wVK@02eN9?$U&fvb|B60NgU7ukj53BoIlWNn_8(wuT=ApzFn-S&OiR}W4L_ zSfM0pE*}mTEyfc|#ezLEJRmIN_6u_V2_+t+6!t;xyiaJ zeP4O%SWp*)prvo~j7ioM<2oA-?Ghl;<~q%QWXRGJ$tfd>lpJg8u_?)Hg?++-0(U{Q zgwjnh9Qm(0DE`!lU^Znr8%92Ay%`b=IpX;va95+w9S=QCFG)int1)NlJB_|Z#x8>5 zgmPGOfR}u$f1{m^mlsG#85;CgF2|jtpe{Ogxx;3m{U0b)7=Ew}W~su2~+Rz=;Q;&G^5{ika94E1YDUotXx@!ZG+XbPm-&k8F}tF&W4ktmBzPL zT_;M=U2N5aJ^(7bgYNy)cPRDY5-gNj?t5=Y*0Rt4m^nX@q2Q-oAs#0&B6ML1HJT2A z1yWv#5&Qj-y|zi6kX}UnUYD%~|FO0yt)Op7*6~;X8$jg0ej2`4pohVLmYTA~W_kR1 znqiMkt(+_=d%;ZoQxXUQBG+(zUSKeJZ3yBNI>vM8Fkw|YD6rn;&iEFGs`hwVWuzph zQ;rBUlzQR5PEeViE(+%c#gYNmN+o(loU*+pM&X13~@=#2{m<9+CuLhI;A9 z2^y27-ZqT*im@pI5oOsr^nH%@c{Z;2iMxaGI}u7q0s*ZDitAqeYJ95OcVNo6O`C%L zy?mHESd~9O)pK#?1>%PSW7Cd;UntR|^({#epG>Ve`NdstNmyfJ)0B#$Eg>|?0DhmE z&k$Y8PgXRQhm(5wM7udRfxF8mD=#1kug2?}j~se0?1{hRz8v^QKRaMBRcJaPuG6lN zO`j7_Wd1)(u%m|+>#$;(V9rJ7i|r)#zeZ7c(FCo@Pv6|U9r1nW4@|-_&*d5SI(irs zkIzg_TnWn=$v`r|3EV+T_&9I!$~n4OIEx!OMa62&F|UGU?E#Fzp)l?~E%NWzXFao_ z&MP}KsD`YM#l*^`V=LNzmjo=snjJ&Q6WEX zD6A#1Opik*oF>2CeUN*%dgK<&w~0%x3+eZ`8W`={9vPb|tcjCmuxTVZXnpvxFZU*Y z7lQ2AhehaO4eis#|2iTXZc$2Y94}(1NJ<6NtFZyw-ZwFTDOvvm0!euNpP1B@oBb5x z%B$HUZGdLh9_2bux0`08r@XNNS{F$88V`l9mRERO^3u!LR-~gg#e;%<4r4EuHMHLP z+?>|0XIBDC&r&?hWyza$N!dw--KHx7b8{5)dnZ7oV#h04F~=j`h7<}WF)Z18`bN{vm7j!@GhM%imb_TCR1T@dB$`>xTY7;85)}0z+jDxl=a6Q%&X$kGg^6D{P98sKKS-NS#>I`U|w7+LC@cZ`K)$LI&aj|ILt`;4m`ME{i^f2M`< z{Ho)K+__i=mgv2_Y5fJj!RxMwmAa2AByPh>j&)Z{9F>_vbiz<$)eaoENIYUBj$2@DHz02nL<`L@pJ8 zG-%VA25dI~FvLb}eTP|M5$*vY`LW)G>pF7JIsWAmTz4?@)MIevAE>)^9*NDb(69|f zbGF-U_M*0axNczGumx)`T9qeW&qnr>TlhM78~YvmS;?!r<`U#K-`TA*p__m?T#gc; zSGX;>rb98^z$_F+{Y8V^KS9M8p8o$~Os}XG3rHjpwpuiY0!I|nuK#~m%YZSX;aDuVE2^57FouL-%mcq0KGoJg!{GcUQo;7GJHo2-7(Fk-yrG}^Qjs%y)x@_@i_)Lmu7430F7ebRfPE>a zy}~!G`+j>w%JvYCbZz^flMhnk2bE`%?sYR@+Wa}W>CVX@ankI@4EL3TXCHpG6+45Y2i9I=voQV zE&&+DNG$dA@_}cK1lT#jRJ_t)rirg_bKlR2g%>)oQFSUy6%UD~aQyV{Vlpy>!aA3I z#VV0@WN-1vrifVn)|Mp~ZeN%v6C;ws{)=37(xpa#n;6mFUkEabtya-L)5Cbi&HOyB zmI;NV>oE!R-dRrBm2xEpRTrgGee^WL*)p_T;h$){XUoMUeC&!tMlc{vBXBz;-e$YS3U05J?eZIU)6JjYF_V>Q3;)2=ZI`D;`< za&!{K+L^hCu$#d~ZG_h?#`^nWQ)*&MUAr1wg3EX5&oywG8;Ep90F}9d%7vtp|I`di z1G2de-9Hmn9a6hNe(BGB_V1Kha#XsU9aO%xO ziGN4Nrn3ZsN=3St7&JMgCpR4EX0xOIQLU_Gdd0JOLDiLodzVFDN6AR$antVrvgFeP zR+(91c@O%z z&WMO9mxKd07NvIQ2-&*zt)a0Rd%vt@tRHb<6;QucxUE&Ld{|@$ zJ7{F?beI(EAr{>MMeteHk6;sz``4qbSPshF1_EbXnECi>8{Z3~oQa-_E!&dvD8t|f!Bo_+irAz({D9LWR7Ghwg(svq(Bd?+Oq4t^8iY^;z9dYl z3MzE=X85T08kH^YkS-;sUEmMYCyRHCqb5v7?yk%EE}2H9@*k4+@QuIAC{HgX@|@OQ z=}z29A+^W0;tguy@9ni8uEvlrLMUKjF%3Arwofi)X1s+8shVdW-!B;pEq?vR{0_Lb zS(TqSnzOz5F*mNWfCVZ+OIZ~nNiw|H-Fy$Ls=25qjY>)O_fLuKzX>D*Utyp>udmUf zF~_agS6f}m-Ho%(4S2wJnW@<+Ngv1m}%_1trNJB($_G?+o=v zTCq=@z|f}qQs9RoV*~Y4AQBaqFHf@0NvM3qce8|!s=>@eN$2jHV%zXRG*HwiO>OOR zgM-@quq_tLnfb(5HVI#U+eF#&Q4!_WsXiEbqxPdF{5s4CX*R_{|6^T&>zhJ`kcx@OP+Od)oFk8;#s>X$ z)n<_QT}nTk%;W8vn6#rx@So%S)_|rJU+yRn^UYml4nE_UBV~QX-)jaH2Xu^KA##`0 z+;SYi_sWW3a_BD*Y~Eoj7IfkB(NNMnR#x&tk^y3YQ3TB#Z`UALk+1%6rJOyI#iqEA zcKQ4@HGZ1k9UY5UrH}Tds!w3OXe3CLU>Q->tar^(P2$Q}X@-apnrf z+m36cyT z7r`ESRoVLPTf&_A$IgSAsx<{I`mfphge*>*HUS>Kzxz5O0Oi^~d2aq8P9j7#lzf@Z zUnv=PQIiBY?X8ga+a}wJCUts4N%uT^CS)mMp+wRZ;H+J<->%B+gjZ$aW%lA?Vy5B{ z+nJS~aJsT^)HqED9O3-d0?^scTp-UYta=-3V4Bx3{`Q@n*{J(tp;6L%s|Dze1G)K7 zuSs0P{Uc^XgbQ)d!rIlm4$I^uL6^5pRXg4cKanbIYBpRk?|*(p7!Eb8XAl9kR6Ds8 zx9td8xPmMD+6W+{*rotR#hD+q)KyfMT){%(7rQSHxOuoJiqmK2Vnj&s{K~@v-|i;Z8-Io#l9_~1%Sw=pA`JMT^D24QY{fyaP^EX zm=^lR?~dUVc&Yf}hHI{GBZ-HU?QUm`=5Q0CQlcC*K7~scxE^{qmAQmI3T@*NMzTza zu_-2~9P~t5J@Q$@_%5YakE3AoamuVZ-I^p&m{ zt)0?Yh^?#t!zmyH{Rx31NVfR}g-TE6`huu6GV2q&OvpOkACvx={!YDU;S@3erAXpY zvXl9(@~J=tczmEVSBZYHjS)QR372R+R<*Yw*F>3{8`cpzoocic2h58ABLZxJC~BgR z>*{=)*J_VbRN*{%WK8EthI_rrzJ1~vqPT9{$WuQu8-lMml82(V*$?}RMdgE9zo1>g zLu3&x=}lHf!rs&^GY|K*9D)5wm&6vxQ++k+&mAYA**Us=mL}tVhb2n*XW|e59!Ao0 zGE0o?+zS-8dxK0Zyiv3*&D+@a5LnLW?aV@tfO@lvOOhdreXalqB~T+G#V5hZLp z>e8!`bTQWB$zZ@MPLbodHL|*T`oagAMD14gzM>iEE6A%gy)(QHuhCeALxn&PI{EzY7@MV#Hh;L*OEHX`taX2^m7(bN_ zuv5E!-Y&d2LBu!1%CFB7*HIT#U2d^W=twQ|Te-bS1z`EMw;8CVbxMvy_$QiPJ+OQy zAdjY5XS-(mMIl}U|AeQde&_L%ulEzM5Hs5PQ6->5EU@6Axae4nlt#o_%1Ip4->sB- znMAe)0`3xgF6?g3`8__>|q%Fpuro;=v})vv1~Zl4um8pv+WFS_*Ni| z^qs$XKu>01D%m?`-da7A&^=6=GZV)zc=!9rqXvk!Bfm;bJV2A0I{E&3C%}x7 zyCaO06T4n5J=MjJYoHo%$n6fP_$jRG6^#>Nc&ly^@oNw{VnC>rkoCxA1WkWf1hGWi zc!u|HSX3-1D}N@<4<$@o^pMI_r)`Qm;zQ^UbvN#5^sn=x*@DU6p%Uen-JsO^Bs^o3 z&5S{ucTp>nTF!=HuW%jcpTZ`*h1k{y$Q85WUwX7vGDyB2+=poFeEC$_d3u|9676yN4V!l^rAu}X>JcU3F+UVZpP$Urz# z0__BiygeA891Q#71_x$O(LY^d^T2W~>^fH9d?T$fl63Ov&<@JP5wUaFE3&*&gE(#3 ze=&Ho`t2N-(ZtS!!{rZ5Xc-G1PU~v%z1jPW!NPA*EH0(nNG;m_bnH_V+Q+(4=AU1W z4l_q1pTVDCuP|XhbyK(%$SbrHuO7`ur*=I&zR-)F=*_bG{OVloPV-^|rs{brz=eQl z>ngzltx0lI+t_3Y=(btY;+!^2_x3%5|K=WO~*L0&S>7QF1G${;;r>E{y z_JCglB*_e%c1ylnP6g7nqkFr%Lrb%Vdw>LwxZ^bLxUO7vw1+q8NOcdJsw=c;N z;4PbmmoM;t5OS_;wG%fe2+2Bnd}5tQPTP|nPMnfH1?e5p5lbgn{ePZ?&xCr~)lwai z#k)$w+PXLSQ%4`v)27MY41xf;f`6h#$@0)y-{>nqU3lTN9L0tr+urcNn8@h zj-Bbgqp_eW=yiCJI@EhlZ;-%aEapk=s}Je zYbJI7D|4BOrf$Rf!84wDL$$C=91kZ!a4$WcgLULaG&W*T=u6x+7LwT=4K%m!zKP59 zg*={6(bt40EUs7<3myiVvlqW-ZMzuK=QjGi6UI7SUklR2*g^R|fQ^qX;T+c9xa~$3 z1VWiE-n~aVlgsH0ouR;j6aCmQGXp4AFIDGM)n1!TKwnAO_ebRlN<+05oL;!oq-H7x zj@0dR0Ww(H`C$8NL`1Y8I%+YrVJvzuIc<@q7=Q7Gy`%T*4mo-(;oY7XC`T z-LaL#mEPyD=&!_!mZT&U*J;OiH+JzI<`P=9KiAYiyALqv^#hn`AoaHkWA64OIkKNS zT^wrsGyI(fE+*)PN$AI4k|wK=(pELOwCgxEBZ{OUWpZ^MDC;A^$@jQerh;UlIrdJq zQoQ2x&NEwL8sf7)rHz&G85^$UOaUP=K%O#3P32vy{q+6UP{w|9K`OCY94vX7Z>t($ zj&O87+%LfjDLAFNmp=qQM}xvSvbYd$1JY8ifPd+UTVS`ui(==W#0oiMEksDj9vu`r zJ;^0-5mQ*x`tV$xo)@izaM%7-FQwbiHl(0m-Z0e#Jy(KYzs}bO#HSCmb20e|W%Pl; zR3_w`7<#NWYeK8OoQ4S!KN+3vV(FDE-Bq+RX6AM;k)^P%+WU{-|8joXBc9ZR+41iM zcLbFy-nt!O@C6?V^L@sn_MCyb4Qnz}jL^zNnvgmr;9h4kfo61u{> zm(k0)l|l)=RJobUc*)BB%Vf;WDcWL=P=;hV07HUtDR3QlEq7z+0NywZ^hG{Lfd(Qv zkGs5$H+trcaXc{QPpBHcKj`YuwWz4*8mV+)jhEqD2@dR-u1PVuA@uWd#D!BGOr64* z-KA?*n*a-I;v0qW>f326%M8$J^6dMp$~AO&VVrxJl9vE`tv9K29T~LIoI8$78ah}| znNTewUb8K9nv}Szevg%;_w8ClE7D@rmQL1&?b#NcUxu4rWq|sDYHPulX!^q1qQ#*N z-17d~upb61&RDAk3)i4SICshI2cKUi0tR)Q}KW@V#F(l8b`YiA*!i zbO2nYV8e=W?=jbhRj2(K#cSdcnZu z_&sr{0UgS6t>u7=Dg~s5y?mN{zA0+9kfx51#O zG@Fw}3YU;6Ilcw7%)k}g#dK&cp1UliEY-c(5s z>6|FplL`qB9?!$bkB?|e3{%GoxxQwa!K{Hd0ot0n%RqxI)vKe_vodHUyfXX7v}+s6 zQj^ckgU8L7=mc>RLGXD97fKGUDJwou}wlDE#sbO1Fk7_1eUlh`fukeCG z+a$$1^epP`)3n%k%Xg;nLdoDeB=&WM7^^SC(J0y5^TN!(D-irt&|+xUig_jhaIfS|4|I1s44RXestP8UJa=^ecfyYVoihmqgzRSHPH{b!^dN8|M9; z$daktgmWXGV_!ME!HLu_tW(IPnxjwrIukK3N#81YxNLin8*0^TGBk%CdZ~2o2~q(_ zich-FXvyA?Ng1n>G)6~>Y+S#kLN~{6eczm?IVgo*r6KOa1Sr@{z?G&iCE0kR?Mi}T z6l0~%H9>qFHbBFo1Cq)uL7i=B?)WOW zlr{dEjgr$n;>f;n#9z<^1`>mP&Rx8(`G9G>7sj>j{cg#7Kn$6YSEkdvcw;Bf#$Fw! z-MDUghVB@l8%!ZKX)aQexzRT)Y#Y6ZB0%b)stw?DT;+h!jzoh}3J{uxFzd@>J_SA zFlZ4wA9NtBbw_iKsHgsKX@Zod{;OOO2=3e5rpPNo5SD`774v8P&g{@`12AtnOyeITgbYf_s^|_-y9*139>!o^gb{ydm**_|Xxq%l=y^4gPkru*GAdh1hG`?PB}g z*@ckgMiI;PEJKOdO1$ASj8{R`s>Q2BCtnhFqbXJ!Mng*6y@OfnB(@$6WY6ViNzaAl_l^;@RaO- zbcttvX+q`Gv$pm_vRobnCXL+{kO@pI4z}=#BY!vt1Qjky&AH9_C(*zul=3KeSDMC$ z-GSC9jP@*Cx^xy}a0MfT7gPy#5lEhbq4^ zv7g++o7*UeJ&GPp$5pZO^7aLRSwV@|(CZqcqVP`mwx-Wp4_LyevFx-W%59P$2sKCZ z26`_nh+4?5rjQZO_2>OA`Wq|~qw<&PJnk470p(-dNiNknDKSAm_UONM2yAdd-FyjV zQh!RCFjO)LObJOp^&CtUZXd@&Sz2R>0!( zD5eT$do-H`tSs;_qyrn6O7dxFYR-$p#1hw9EgQ8zmJ$`$^UL?;ywL ztJTHa+#nveZiL{NwYfI^^!oZ@l1tvjvjdu-D`@DyB#mKD*hHve4XMu~t7OF9t?EYX zosV8#t0Nqq{pcLUqgE4EHY@|8mX+c-FFHHB`*n*|Ub?P$w?5Hr0U8adrTWV8DJiXN z>@=*VMuj!8iq5uV-hByKk;V*9%xUPwbmtt7JXI8`b7OLK3@)0L!MQnKuU7Z7k7sc9 zW3fCQnpYNw@tzx~%xkbmPicjPORFN<`g>6Ir%1P?`bF?J1laBCdLCCzqK;c~sZFAVpRsWuPD#gRSj=rAR}OaSq!cB2@Y`10a%1M?ydD3%Uc zS3G#20<)krHMf<0!EUPr;k?wZH}95B1>rY~5%#EHd_j|g)8P;!f$M;tK4<~eKyOcz zo0$C+=xI4IqkJ#)hOJ~STxy^6NvGv=7c=&uC{;jk7?Irm439_Cta@pX3*L!}#FJ>) z#hm1CIK9Nkh9aG1v>{AmNZ0Bn((V`AF08ZdDm+Syg5R$X*M{+P64)HSa=N@Bfa;Oy zn_veC&;h~3VX~Y*yll!BQb$ZOckwmshryvW0{lFvQ}qUDpKbH~2pcyi@o}xdF&EHtKD` z{69%B>B398j74^_7>S=*P<$XzpNeuyhC9S7`DJI4yOUT8S@rtEwUPT2(9<0=fwbz3 z3f`s$JIEM&yr=KL{GK-^o|%Ptxqo4Y{co*N06(yu=Yed0DlaeZAZ|kw7DSpJf5_YQ z5ztDz;9sXq-4bE$&X`+QM8UgFW6*aqTJhpQ_w3hGv!G6luUZzeM;Tf!CXK zMKgvcEwK9sxjTUJ>{?^$=W*+CP&^CFqq_93dpxRXDeWF6dKFWdHojuuz_+Fq{h#kg zylk!P^@IZ%-`$J-YPe>zHV2|KEu?S)g2ohCg`GCuRMK;P(4WZ5;4&op7gLi z&NCJx3uqf{xK3j+gMx@i(E!z=PJ2O0+r&w=@cIU%DaeGNF|i}|XHZeVHI8T0W2%_4 zSYgT;Mj|koy_JUWama@ZVQ$_AHe0Ieoo%pj`jkKU2PDG&pU&~lvDyiywy&#V++fs0 z)jT3deZU=)2RFdAU0pDu28z0QJHe?RA!b`%!hc^n8bFqhZqv(cN!v|O1Om4c z3z}y4&D%?{eN3{u@2;hy>QA|kea^R55&nr7HW$|>I}pn1(6{YN!^d)qTzgA)0eI-C z;QTIJwBWY>?xk%PkMe6CEgcv*-H>Ir*J6S0=zr+B&LRQhow~YN1=nZL}IwZPT%e4E|yg$i+pABkrwxn!#X6-qvBVC48mX|+BN;6hD)R{n15SvQdxjrptCh}uWOCYvt05Q;dMR3a*J3sCBqV#kHV*I07)^_DQ6KbL~8Vn z9YpW~%f+HZ%@x_{3aCl{@@O8OjT-hWWU}-oM~EUI zKTt+7{I_(g`cvw4u@OQiWxzpV)=(Myub(8oPXbrmK2p=24>X|Fe3-2++9=fk6}mm1 z!m!9}qF6qNz%__zTxyb5!g}F)SL>TzLY$KF|H%NwMyh z%5oJq9e-MKK=7)3uatVE&oX^*M7>z_kSK%ZgR#QJD_ji(MRLmo$$A!>)DIHDPDf~?OS{)A=$0`8Jn{ z1Fv4s!V6{$>8WI75XeOzrHkXu^JasLHt)(Y?rJD-z?Wn-lF<*HMoz5osZF*9mJ|gS z4l2z=7`=mx8R)t+SKZ|K@Ym(jfPSDpd#75YLl=rAe(}oW#E)~xfV)w{vxht@{hMQ` zkF+r!!=y9{OVhmosg0hsP9>>Zc&%lV`UN3-ZIyMzeUQrz7R_`{Ft>I3k{tFSbc?U+1OUh1%Vjh8ja50{-sRlZs7bTPz)rTY&Msp2P zj{l~-k&&(voAFmX<{z)-qn(%AQsl+{F?MI0TSUpaSp;;|S>mZb^inuaRrOWUCqe=O zsg)C@pb=-#I(BMMT#`T@aI3~_hujSkIyE=6o;Zq?IktqaqzhzVF6ehdW(@!J`(Q*# z3*ufLo$$cK3Kyr3lib4Iyne=)>&_h)n!pzUNH@@!F#b}LVk=MA*e;9?z-v`4 zmlNOKu9mfFQwfRyyLAw+>p76*NE?=LnU`MnA#DlFFM;N$HqZ-A(%EMu^TjG?9(SD? zGe=;Z!dc{1yLt5Z^3`p@P*W1rzKFKUzz_ns;#`=2F;iTvGs6`F?BnW1LP$~yslrc{ zb5SY5YxsU?ebCh?62M}f)3MKS#qR;C5a|&6$!77?t6VEs{n+W8j<(*+TYd=6%eB}h z@Zgdya{Pe}_t%S3D-s-C@Uu@o1Z49w`@~K8O4b|T-N@UfxC6LdmiA&L+yrX+Q(i)n z;IsFMNF~wKm>HEyQW5E%@)8fQjS+6OIg^cMQR+IS^4M(nqp(8k2$Z3{!Xw)KFYf3A zsj%5KSR!!5v#u?i5cX@PkhxYCU$xoPc0Z0ETX)K$5FP+ZCO^X{V<{B(c9h*<7hX7R zll?*5csf%O0!i)E>-PXO2rTjiky!JHhG*+Q=W;RLMh3bAT_6Q$zzASm@a-hNpVIju0fEE<0nPCprYrP; zZ@caj)QRD%vz@DACQ!(uA77x#A(%G?B+y2+tV@d<3ki$+YwX1(LJdX1Dtg4Ddmo>M z)fyAQJAv%iF$~QkildNuD}6}{LhL+_Vx1i>+LfC9;0&dzvB-mFCKyuA=Vfg0t+?+k z{A1K?Q-uN0n1;wE8{VQ}!Al+0^NLhPOHy!H`ot#hu^e;n%3VRm+7u(~e{A}Qa1MRS zyqDz5rggmQ&g-rV*_h3PFa<8Y{}8w3xIBq0=?-2}E)9hl{CmV7WCgIB&rly-A=w?Q z))_<`c^tWHvQ`xI*)E2v%m0TXWttbIFM*a;2a%@>BXCi;@7L$Ur)5p-352|WKan-c z!nKkiiJB#e4p6*bH(AF$tiVsQtG-4CNXCWf7CCNvKgs0M!(k5h+Ol11nyWF7e1%&K zP~8Li6@`WYDocx}Rsj59JmjnO_e{=%=a4VocGsG8E1?N)eY7;QtX>S3IYU_l1G27N zH#C=6u)3P>j`#ziCb;kbaQ@R0XxDe)lF+Tb!=l^$+RbBYS4RgNNVn`Nk4Oq1I3>_Br*jhFxGN(`2LrWSl^|S4U7V{mNgFH6_q5QD;$5;p!{78>@*jd{1E-l$l0t zD_!pPy{;hL_^7{)KE{YSr=GMe*+fGA6`N%$we(bDFFOI8m(V|@*;poIPs)r&+AJ^YbDNdh=74B^sD*!c%G>&+oLH5(}iu|)NdbXtB+34hN|t4ynionOl*2*tax zOC&81YA&2&WgU!eHm;md$M9R#<3K66w2r@kM2@zR!Fr~ePk3k|!?PcU!dNXxzNYA3 zk@K;&s=lo3#C@~CH*OZ!h(df(YC$=NunuXyZ89fJSnQy$Al$nNtadwcnM$*zZBc-C z`25lbF$5$}PnR5jVoGX5gNmTP zw_c^U2N#zOB~ED}zU_b|2856QdG}t@Zc$H#vyy4v2y%aATeFFK?D6W)p)ATL8zy={ z$*X3F>ad2xFFBSH@(=wG;JR-?Wj0S$W*Re0e>vtP$`lLaw!j$(fX#=z%OOd?Y4 zoBh$cpxUcEqT4l_Su0_C5%*mz26|8L=f-3r838P$a!mH-LeB4dg_yw8+Zj=}ACd!d zdzc4LWt&yX=7ZSjy@?tQrVWFy^tXr|Dn1AC3vg`b@PEQ2+r63`7 z#hsJGMLTY58GV5PC=y<9oy|N(_Ogpw&pPmMp-44aU(t;*G_Nb=waT!z%qMfmm&&g-}*`_BV2-He>yHg!;Wa zKwHUS9Pdv%G^sFJ623r3%JM5(pagW^dg%u+m^vQ#kyR2rHn^<{)`^S`o`KaHzS>Ky ztljMls_#550(b#8zM!t;itnrNK*}PeixVgZq1^d<$pW?f!=fqH{`6J^E(5MTFI?W zhwlZN3aYt81vE)>YaVu;OpR{GiF;+}Lg<$7XjyuO8LD86ck-S#=j^}%(qABl@==>F z>?-B}0KTd{VTiJHD!``HYQK$S^Jiwvr3IRWzS8r|y7Q%F^aEB1&g`v|hsjzU2n`8p z%i!mX^uzf-TI`RFN*x;^C|O|g>Bz2X1*gt!C2U+7m|kx@UP&+L23ID91~a*K7?DZi zwFdiS*+sPhsrbRZ@BzsE7Bu9u&CF1=$-`kuoJ2MWab(~O7JBW}m*W}Hy1R7(M zyeq+#x~(47*zxa9+&gIQ*x^_CJ+=6m%!LrgZ_&WVZC?l813fP0EGxPi9C1j`a(nJP zX1twA4Y0go+x;U&Wt?*&&dbRgLLtcR>EG`^-`5rsYG*IXVtV8GP&zFXHwWfcDAZCP z?IcR#5-hV&KDTGjSX~exaNdS)v2yru!2zXwBC~6#KFv}>wbNl`kij%>h*EoDabd(( z2Zw7&Oko;r@b9d(--71}G$Chq)x1-py>r*`V1+I=83?z)*{liXsHyV( z#N--w;+}4CWG&gL2FQa^!%PqqeyD(XnLyD#;}~!jn5G{(H%d!O(Q$AqnpWS7Df~pM zGRS(4N0_w_#vu>y-~D=e0RZ+2_(5%ZRx~|qVga@K{=c6>_Behs^d|+wBt(ZRR#Pj) zBiad`9W2BMp5fiT3!Y~x7iGd;=)b71#$kRnlOYr+1X}?B#pJF6C>FQS_A~F{yQzgeq;1yY}LdD!XYckH0J8@{7G}xB+_5(bR0(>Hl+c`pP-|;wDD7Fjq6x zN6=re`W{Y)FOtXewcU`bA@6U9#V<=wezV^EiY|#HCbz?+a z5t@6Sv_Vp3ft1K+*VtjdrSW}m(y}i(Ve&BL$YRCTdi&xh8^+v@2tbB7uRjnCK0)9l z*e(D{w1HOCy3O>D`Ao^msewKImZk1;fXEC?!zF*0<7)8^CjpM+o=%vHzKMyU#;I;I z=Z7Gg?qyKWn|7+gA#JjHkHRYe(>9MZ6YIyp~{H{0+|PBNI<7aZhE#bQmkA7u#56TjVbMKr%##O2KA zd3agMEqkJ?trqnis-M9~1+=d;qp-oj9){;m>~V>bBXCX}c>YWeUh~#8mYf&dNHP#WEQA&j+atWan& zUfE$eOOe(+s?F4g!g($O3y4ZS`@O<&%*wPpUMD}d>r9YaeVka_3=P0T%3f1HiTp`g zA5`eUt2G#{OTW&;{YfgYl3_{4DF-j+P;x6|l}z;Hz0+b|jpdT8C+bp2i@$=?@^pzs zZE$y3LfY(-o0244fI7;dX5j`sV17zt)D{e}+gT8|#&Qsn{#pJML;9=ukrP!111_&O zldu#0UL^a7b<-zG9)~f>%u=9D`EzFXHxPzlmS@$v(8y{DIc^$1NgEE9MRdSS?%S?$ zeVLyyP+_Cvu+{2T(~G#@(Im??wnw!!F@Ozz?ugUDgT0%!|_KIUIqOl!GAYeKb0bdkbUhA$thw2^h^M}mVpDFHbcdo)zSIpeUSw&w^G ziyuU_KJL0Z!uGrtnqnM&o-q@gNXS1&q#~?8{F%T?;CQ2J_7HB@QBYr#0^+LWiK_Po zNQQ!^Vsw!|i#m&IJpE02`nGn>G$c>mt|+6Bg(F`}UQmn5>+6lRZx(?71AW9UjVY`&>VH zGinz?NkUBFQNa>00=~e^a=ZS79kNYk4>s_>POW-gQ<=7?osxmnpdMs5uk87db5_wS zvBhXt10m9xHT+4rH^F26*L0WRK(x-}EkDrRxHuJMyJ3I)1DvME#&80q{ncQL zWXGYV_W^4)OqQW4#vM{SZO}hn-*#rSp)7y?JU8$b%^u9@DVV(4>69IE@<{(3K#iYl2 z{e7~?^=POR_|+svIf*4c(Q6(_XeQA{P~2px+0UG#o2;55Z`pp_01|QguqP9Ee6&Af zmck0!m-K#+`s|+ag|Zk!mD5K0aJWtIY}i)kmoLn<5G3M?t{4@}MviL4-eRPvD1e^n~Y{Bj~iJPHwCu!ZBBL#cQ?n$OKb=pxI z5}7WH5%PhBO&gDfc4oRw2s@X?3wz-nihR@o!IqW3^#H!^Eu{hf(WTlyyKS3+b2#ee zxV758i#~yC%Hy8hy8xL6Kd#R@+@a0QiHbsOQ|n|b%nkZAfoXH z2DR=lK;h>CFY}&$#DRVls!?|O0y6dkJvIK#fuM+Wa_BPxP+CM3XmT(l*Jx@YfYYME|PTSQg{a@1$ZbJ@;0Wo*+R{r>jNnd)5gp zAYg252?bzl25N06R!_x?``UL!gP7mOcFMAv)7y7qXH}X+hIj^1sclS8A?4@u6IhHr zE^K=Irg_akF$&qlG%ghja0U$P{YZLI-Rj#1w z%PVc3*hj4hHIBc2on#$Dl1^i$)c+LxJa;wyTW(8&L6o@+k2!Ph`qWP&)YCQM*K!pv z-dx3G`~HrZ2z)Whc+HtaGX$TC%K7axe^VOT(~+1-OBPHDL3LqCv!nn5S|O@Oo3&xN zvYWx+DnwtDJv$@KrrYOc9Ls^c!Tf(2ja3V&bDsEaE&hd7Uh)sAp#XxyAdZ{%LJ;d3 z&rhX};G~oXhJPo%Gq?a|)g)l`fY5k>MqZL#Rn&fw- z`=?J0WrYE(Vm3qp&OdiDCSOrDo+0_sZF)vw_InJuaV@;wZv4RoX>h&)She$1%)LIyeR z5B|$WsuTOc$}(`TAsCKpYDp=%h2pJm4D&V$-KVad9C@P++Jr3oNJ{k>NWnB(D_2-NvM)P>Y#W$kw8G`vHYKb#!? zMCFZ=(ga&E=1)@-h*7dYeEft|M?#8Tze1{>glAxTXF0&N1eabla5qfJK| zgEh#KaiRS9M2f=L92JQzk$>j21Ve=8BwCUG>rqj3K?V8e^rrcmp@z;MKnpEhqsqD! zZLvYZNQ%jo=>*FmodP>sFf!f^GBH<6D$pq47i5Elt$ZRTEHs|}+6vDrBNf~02fBye zTy1h*dJ#FJ_kfW@Ieyp}m~M~!s8vNV9ij;v7kuTd$a+#2QM|e-E9`eC7cz@Fn@m9$ zD(*lY5+{w(tf_&2-Zw?_DOTF7+mMSkImEk513WvW?tW(T3r&owKV=z zuPq{@F#Jqz$LSoR8(bC5ES^~-g!{f^VZ=6~n!+47$Ysi(N;;(Mubegg3X=vc)&z-W zYc8K}5+rLZ+c?W32E0LOc3AtlWEks(gDVvyXcsAg_nm!igbG|wmpZt5X8jge`r&Wl zis$Axf5j%c_vSyT%FDc7q*%LJ3a@El56>&>W(fhFdo@y8Ifu}GsLb8!H4utd$0W?u zP(h=P{RBYx{qh6zno<)iIhed}88A&<_7MTn``RIUiVq$7S#T+`1?-*g0CRqTrbavW zghkktl}(@FrChvV58a+ZvO~Mw7IY*|g%jgOcVRnKw(c@jg>{+=%Hh5Y0<|9{qt@G5 zC%>I&NVR&n0caX0ZS~ANs2H4cS%$s6X+3jz`5c^Wt^wX0Ucf`zpUB;pjeufqWV;Ux z>znJ&o}akd2*ofeF~%(D7>8<_BRnBzKid-=h12@v_Rq1E0D2Eb@46c_&6JzI>G&UO zKvLX>u1*BifGii9V(2r? zRCQ_eJe!I3=vMv`b3V|^6W7hLahRVrPwG#&ObGS17r=fH()3?*? zb>R#p&73AckO93NKMTSDW9GOFh~o~fIuWi<`hckr4-)ky3{VW*Oom&nr5Gb`Xu9s7 zd?F8}%K&R_cwH=rP#G~6FOR{*5(1^Mp{owmOtmJ6DJNdBO_l%QU>Kzpe%I~BD&KoU z?sn|Om}HrJi%)Jx8gtQX9U+{jCN0%v2Dii$s?rCJI0~aFZE>~WbF@IEl^Y6Kgfa{< zg90ZFJWfuL$Q!%W2(zU%qntWAQ`0b_cRqj{lVE{~Qdemvj*sap=ae%f8Lz-%p3K6z zPwC!`%t%nHdvVjuO3MdAsu4q$D@vTbYQwXGuKSK(Mx~8xeBf%4N^l$LHrF+i&~8MG zNp5L_RKb8{tTcO)kT0#mx>JqC8JkunHlCl@31QYzI4hzU{>H1+h>~4k4a?Z%E-+Q` z{FEIVivvkA_l??6$1TZ-AjS9HVWpBp-ew<($pB0YJD5r2`+2zlcv(yO3%beLhyrG$ zq{=g)G|n|6SdtCj4EL>12i8@}FU&_a>4@xRv&x>}@bJbeID2GjIO@xRhm|HR^kkw$ zNSBaKGLsTyIejEY|5C+l5~RRb&KRu?QV3W!D&(HWT_6o-@dE1xrK83ePQe$KXjQ4x zC?H`-@kZ^%o>;f1BA53kET?DD#0KT~b*1q>1=^T6R@7HgHE(v+c@x!!KL%wQPO@w< zzg4!;VWGoK>OL-i-awzR$*5d|FKE;Q)C8*2p*+U>3B>|=N0L567(0;~)FbPf1r>G8 zN$^P(e68&>UPYlA|C&04kbLN%xhZ>GJ?Jti2%~v0F8i#@ejW!Io-@44R)AZU+=uz`cg+PlPJDZKtiO#y6h*RZ{0JS-Ups`w!?`UR?;K!XBLAq-k!H)U{ zQ2)|6+OT(hyt-SzDHw)&ieRxH2C0ghLET+x_x=PcmD5~6o5ACyY6e=DEDA$=8~MrZ zN9SRfKSXq)n7@guM$xJ|t-}S~UGRj5FD=(5&q*TPFehXfm##n>C$+<}e4mquDTlF+ zg56(D$zs5=M}LAA+1Hb>nklwCx-mLQNXa7CbdBz8;*>Z8+#V*v__P%fD=&7?C#+s8 z0?!XXT35ehJ%T)7gx#o=O3H9y)E~hWR(Y~J0?S>AG^kN`_g#+f*s|QtDb%K=U3-c= zF0BhE%qN|r&;G(^!=oci^r^JlO~>&_-8*~sDE;K>@J>b8qB<<^&!?7D#gfoe}^#q{r(bogbJxj={d-@Dz?puAwfp zZzMf7mq1f|*`q&tov*6}S_GqMj;z+M|+;|y4RM^Z;( zU_W~gz|LZS|q5h6}rE%W8(7lhGk#$Cu(sL3OONbEsjH8C7htsZ-Y3hnW^4 zBp?5!xld-L@a%_?f+-t?ACl&>nTEL{lz^b-L2w%!sj)s^w(MtRCP!TC!l1XX@zS>V0&Eqfy|W2&rb18!4LP7gd5 z5jFx3`Uz7p=cSXDI@D%ysBl`PW&QybpM)IL>{)l1wT28wwvha;W^mmtQ)DtP&EawA zgLyBHhS#|e^3PEbIP>~M?3Q>E1UVM9S7qd{*t)G7y*Y^}%#ViVja>O6QV$$L(3gO& z>uVbrUkkoOo#(e}TU8fTA8*uehARl=Flj6(_)Al-BjwC9YlIQ~h0|T=V?I6@-EycF z&MOuUpi=y1ye1^xqI7#psL_Y?V}+LDtu%pie_l4daW(WM{fl@dN^>Q9WQ#`AvUCKd zgnBPJ?eb&mnB4P1pJs{mH?C5q%lOp%fXImrAX^^avC)C7C-z&NxDEBB4Qx(TD%_=` zyxP$~M3?f;Fg&ZHnqGYkbVM7#xqnqSqr$RQQ3$uoKyPER&X6@)!KE{1647Z!6h(r; z8>f3BC|1);N4KeFi4DUykbd2AVL6}oL>u{qUr%KR&9CZI@Fcf1K9O3*IKb%H`H`1$ z*((O{0U_&QSuW5q6dc_1i&GOdc&gRF;g5G-$x^5+rNFEqyC`jR#Z#Z$HjUenh_wrf zB+p?K90rx(B}G<1yzN>z3^Ab8t%|Ej6LRshWt~$NRk2Vts(7?9Ut>HHP+yF9kzo2J z2Fsk|pL4%;va?(Au1a^3=-DG#}822DYtKgRNO7zS$9`EJ|Y zjaw9?f)Mcq%yNk9e5f@=iYhumS+OMrOOD`VaJuE|CCD7qGD7J{Ki=YTiI-b47pRH` z*7>dD)+4J;AAL7B{N5Htd<_y)2y*2)msn*TeG;sGW@+S6z4h2JsaM^+-86Cz7UnM& z4T*p{XY)NwD>{TJcjw)JE0VwGbxyeljSLL#nO*UqWB6QL!ZrYiEQ(rclxKs-60y=X zCyI0}jR5d#V@)d7GUCx^7gEk;DT4z0%+>@vq9DmFI_1K(28E*(ujG8t0h!kAx2ad# zO$C}dgoJDOTN}d$mFE%2Zot%4$jI6+sDVe`w~L^E`v*o2HPio<_N0~1{hO@8F~Jpn z+(3JUs=}z~t|7J|zV?MZ3Q==nS!(UrmHNR;P$r}N4WpvKk0~L}UbET>F;rS!QX1Bo z@B8lCOLuS?_f=Bx0E}A0Dh|npPAlI@$g>$#`tbOSG}6N2UA_JL$uY&j);baCN3BZY zFRwzhTN)Qlm=7#TP8ugd;uCR6Z>{Too#^kvdVK-l1JvzplbBt>l^18L{lEB#dJ5%b zH`n+)v0y-(o+O4fBERM%Cbp_@b2}AO`6gH8ntfS29O&9Fg1Nkeby=iyFcp5)mz@3F ze?_9SZDLW~@Rkdk?7|n)9qr>b-TZv@qIxjzwcEkK_6lupj0$YRhqp?waaZiaT75kk z)g(x!rIyP@b+-lw8_8`hXA60NWQ{6Hq7DVp-j{i`tv$WB^(A%*#jorKtSi!MIJ#LLQ>m9VdRt<$4` zzqzF72-3lWeo#m z4l$nnQ>VK8vBCQ8i`j*Dd)+j;CF2NCx#>%`J2={uNBDiM4Gml}!v@I^H*|1%6?*^R zJc+V}jygBpt`ucLW)+>HlbB4Vo$Hct0{gz&?Uq}^_>=TdgDhMc0f4o1WcZnJ-p4M* zr=A(B%hj{f-lNDhV4tI~av#%VZ!Wyve46C&o`iDJSjSLOHK^&&2mhg$Q9`LFc}8_< zE6Xce^}pFQ`dR$Dmhy97-6Vl5 zl=RJvS*(?uRzSVmB{OM6+x=c41vJ-5aNrC)ezp5gJ^Uwt&$cy)btE64YWHWS;UBBPkfMG7x7*}*4=LA?o`_xj95#3T3{~$Q_6KiyU48W_JiKsarqEDhVXXp0 z_lPzEuFOsWttte>oPq<;t?B|s&m|b&;&&+2Lq8A3(j1W#QowFBKUYqt?j+RZnAt1D z`^6Y$(dEc?U{Cgrrs{X`)~sd?*I9zUC!?iAsHmcZNgmv2&DTl*+wU#>b9-H7>danP zxF(!a?xRzjFB&{a<+xc?F71voP^5=Bk`nF%KX{*AYpUf~oe3{{wJtdAIr?ih&v0{lR@HAB?XTQ-ETdIebAbect==k&Y$RP%q zZ!^k12w5ULN;Zkiu8T6I8Za0oeIrE&sb!GBfqi%YO2t99?b{SKaG^8M0);Kj7N^L+ zQ6Qi7Q_6*TDHrs8Z+YRdOm^zP*w zfm~Zul>Sz=RxMq2=I?A@+QEt4O1-%$dYOZi9Mf54D`$I8mU*B;lW0JE{zV^8vGP(| z9>R@qx@G=hFVY6h#=hH6-Bybg=7tam2Lc}p3due~Fh1m44V*T;h(RuGAkOm%rqW4{ z37O(o8rO#WHG&gk?338l0ruHFB^F2X^8CfgUUq(HEp|URB_SBcndHb8=ecFyQ`0_R z@+x0rnS54Yq8rn7w3JTbP&Z8r)DYa!a**ByS!w~>#Rq2JRB<@3iKr$e*4^(%h}GYb zQS^k*mbaUNSe(DN7Z&+5byu^m3g-B|DawT>Viw5o0M)#j7S8MgNYr)=O_=rr818u1J@Jcxf+9=@y-#GX zW7rxjy~Ox|Z6q)IoZ+gCPy9@jbSo%Idn*F86mJ(w_LI{+4Z7?Qqmdz()zo_ znj=#-Syn;-Q`}l5&;$u-jo-5OBYu0?&mfpuSkC({^tX-)rTlr0x0+|x#&IV5dx4puF5L3 zVXG*>(=j?G=K-nTAmvOYFq`Q-jOf&WvMK@dJa60QtU<*Q`f_?6z=;l@H+S0}*J9nx zDY8Jv34$zmfYi|1smIw>C5T`^?#`{#pl;rH-*CrqeZoHS@*!XYWOZvhn{@-=y zw$`mvW|7pks5h|!an|sNzlXH7$j-lMh_5!OGeAxLf+We@)uYl$=A;V)>1{|}#Im9> z*46cFv_BXSaj&@pj7ixfc^dwL-jH>h+gZm{TNZ9v zao{uSSu|@BU-dmd+uw=_aS+EECh+|o`T_$n@%T@eVz~Y{XCbQ_2Fy^bEnr0VRW(u796e@ z-r_Ip^r)aVl8z$Qu)(bJy0@^%(*@;pcjx3bPTrOI!{4}5wfkuA4Gc;cfQZk-^+_5M zfBOaru4e07DqQSyJIhX=AUxE$PhiZu_p-a6Vg$ks)1guS*`bl0{}FE?Ap0|w8`Fgp zpN7|LfY$#6JzXH9kX-mcYxT^E@NlO|BrP~zNU`T6wH1|{pbr-~3?XX}_V=G$r!Yb4 z1`S`t+#}q1Nx!+<@R05?!epMzt84Mz_BYeitK2iNVY|j#(8-ct?C$M+Y+wXGELCt> z|9IRfrG*Rq5_ZOZJeR@t9U#%6G(l-dL36`*s>b@RjNTY$_tWQ(!A*B{?i^UxS@(Xq!RMGCH5JxFjeoU669sEAbbLo96dvMEhGH>yJ&Fnx(3`-%IU#@TSw*US9IB2HyFLKJiB zL|Tqb4W0#3S?3-Up7IutsE?AOwYS4~oNSQppG4!Iv^A?-%8<+;C1&V#PkeyKa>NVR-uyuqh{{kEw7 zmvtGJzzb0jM_ImROj6R=qjYr}D>q)i)_k(Cn{+&L3F%h@CRP8LITx-=&Y~fPN4OL< zAl_!ou^_ez?}uZp3g7Kxahgn{&0pD>OmaKojL_5@Z<3+XKRDP{Dzvs#tK{|U)MAnI zak`BM^-W$L$#D*6Afw!|4bZr%K9BYxS{gs9E#fbTS^YuG$pm`5%?k4rQ+#!cGl#a^(o#mrw~ASx;8@kQ4uew~Z%a>}|( z<8;25!{lwcC3{(|9+br~rL%*JqUcxEpLM7~=x53_%z<{o)&$O`#xt!HZa&pxR*XR| zs+xvSmyQ~C9n#QCh+4KI8&5nS;aD|A620H9M8za~AVs96g{0+Dk>W38lri95hSXiY z?add`IFn>=YckxpT1;spuuPg0Xvar>LX#n=6gr5GI^2JTm8df~mNgwP53>>ea2wFm zHC)ojBPB=dgI)OhuP+p=DXYq+u(oy*`+D&472dCfa~V&`ZjN8XcssT@*R>rBQ(N50a*Qw9~O@BjGeCMHWbz8 zjWpE{h&4xf+bJdy#_(QMIJ`T^ptbDI@JVEzz~dD7WiCvmcTZne-)$<&+>oL2A0c%o zeQqK0#1*HqZuB^u3)fjX|89P%P)`PH2aFBKm~t?o(D`j^l4B>ks?g-_Ivrd17I$?M zSRtYo(G1<(pq0(1=~hqy{hw?>BtZzx$0s((khu?z?M0geXQ)77nC0d7PU_hkFQvS0 zo}G<3(RV&o68=VGy!+JcCry%!r7yBF$#EFNAR9n@qB&Zncz&9hg&#}KCDu1u&>cb* z-Yw=_>FwUjvGK^~5JykMj>i2 zb0ZIzRp&ZmnO;re4hH>^RtdXi>6@0A4M^jJdVdw%8vh-Q{%?hKleF9h88(@=txst- z$cr^;6@npsL{(1IT)<&;4I~KU6s&-Lk6`?@Rw+PA^Ro7^@0(a^Cm7syks&lqmXKgQ zU$y>)<$_I<26%vsx*4}>oEy(=CM5Rv-&CMV*3RhovVR02V7AyeEXu0-~Q$lp&$X_~fT{!at0;NmM#p)V2r>#C10 zRsH7aUD?QDFCZ8j)J8X%eJkmGjWC51KOoLPF_2dZwa~&DvnsCyy@)S2agowg^Rb&Q z+0auuH27)x;SzXN&+U6}q2$gSQy`vhf`{M48ciZ+N52tzurTV40vlND0glaAjxArk*QS)>9k3-QE(;XpDk&&euz7y$L3FSi#nm-kF#Q#+HKQ3z7;c->k_? z@y_uYtVPbyQqE75RuK4S93*S;N+y#qRF-5~y6x9Z64uCjBNI|bEWHIbjN6cbCWNPh}1h?KK8!CO*Tt9DSE7(!I<_}Jc_GruA zSk5RST4A|7x~$tg9gUN&_@Ab{=CYQThZgLRbLM$52_^=!w8)+QB`!2eM*~Ml|Dg^) zT(OJV{-%{mlW$`8o}Lto8UW$DC)D}ba^E z2SssGoUeDanUm|aFt%KqXDZ7Q#*9*n0$h3Dl)=!|Q_2%dz(R2>7+G7x=`M#?wW`qY ztt}iwKGY;jj+8Xb^Wam&Q{3t)*9Lm;_~*hNvTv&dtG$AdU#QbiRc&vCa)~;AF2%%r z|HQlXdq_9m4IKG zi&Zl^28!vYj2@Z@QFJ=KJjiohrW=khGf^|yv&39z=#Ps+-hcmfh+nX>Vwiy6Z!NsW zV~aVhiywQh<*#@s9FM4Y2#bl=1~nMfCGuJmD;qANwYtYK&UK#E0Lu;U9Et6pdT!6W z`nwmT3iypTHI(RQ?UJ5*ux7?7P+V+Ji9DWD?akIgX8SS*6K%Z4ik9(bK&@=`5s@-d z9r)W?qAfjsbU=NrA{Nasy!{YGC*0R&%}|(WFfzw-tNcc~uIXaEmtZW%ION|MPM*WV%pxlGA6qck z6!Dh+DrWie(;|dtWm9N$g~nu0Z!V-g3scKGOxeqP*mx0E`_$^sYB_lx11Zk{vk?z= z`#y&}C?$eP3b=$wh$r)%tpJH9v$VRu=dXdTr)6ankAhs&o$2c&aVz82SFrZhxl8DI zwF4z-!ikv~i1cD({Q05k$n^Zay1OUD^i*Y*LV+~#ID~~bNEs9{6n>Wbigpp$C&axY zjl!Ws36NQxwvp4v)pfA)7b~x(8EvuWGX|_V{qHa)NmSy1Itb}=42$;yQb%E*)=3Bi z2&R5d#I=y0FA*Y9*`j|QrobI7kT~}#LM1Nmh8h)t{We{g27Jn2#1Zig_m+>R+eD5M zV^|1KPNeJ?CCbMj)C(<-1PJGy3J%x{q+7SChq(H8G_%Y^Q#9=phSI2XrtU9hms^&* z$xu57SfLFuq!>vN05}Aq*!;-ba$xn1j`2Pjv>El7b~3JLo7!5)k5L<8_&4M+uwgqQ z#8flFOP*IvZbL#6HQw`FD<|LJkFL$6YgW^Ma>@jifpzCB#8nt;8W11)dpegUycpM2 zKfX6TUiv$+Qn&8)MhW#J2L6}{W$44|1Gwx?FJ+q!61BGJOyBwcoQD`NPV#2H#h=4q z;dzCemT{N?#{91Ra(LWJ^E*5P#_JQ_n*`ygZR4d&Qu%PXSvb-3L$$*iIweuc1j*G) z0g0!Ych(ynchW#SHl`yh`<$IpzenXO48{<)C!Tt#WYj`tP-)=OPO|CqZ{SX!CDW zlf-Y$mssMF*H+X@ma4P8V;A`HQjv>NB?k0Kq>bwwVo94-dq?bktxfbhE~oehZwqaN zYixh{FdqT4ac!_^m2%G3DQ1~Jc=Ct~3VoB+n3@f(S>-lku2*6YSoaTLMzXb+oq!B6 zOu4%eC$ULuFfxp3<>*xj1vUVvxycs@hX>(Fbjq-noSbd;%YT5Pu?+8a+>I3YCk1Y`_Nztp8ANcS~M!>yodf4h}aKK2pC)myd7PR(mUt`i5| zbxg#3&|+&$p}4`5YX-s1f-02jY64tCV=CC``m~MvWx|S5b;V?E8CAA zLDKDu*h7G2EJL!?Dxo(i+933;Io+MXh1SAO@Zh+#!p6(>Q_R3MC*|bHA8%MP3{^#H zs8clT1Di8vf|12a7G%T;{znNR!=r(8hvby*W1*4bN*fJ?kCeKZq6{?W;As&*WlJn! z+GV=Ir3>4N4G#S@yg&ij# z-Tl>8%g4QKG5vcX?OS_-n^Ah{hS@6R+ic#Cg2yNXG1I=m;gND6?lz_b%xZC)3yL~s zKft_EDb%XseKU9=p`~0Omk||(C%E9uY$KeQ=4KWw|1~|kp``9K@Y?*v61Lb}|3>x` zt!kLS62m1foMQ!d>EY>qbZiyiC$B_wd45W0QH^^D zpfhm0VE3sTVXR=_pFtl!jgoY+D;p92_e=ePZx5I~ZhZqH1!mYKu?G6#3e|qXQJz0| z;w|EikW}OUhZu*e=jFp*hI*?A!H7^{%F!NX2W{LKOJTu+PKvA$<63#(8x(6<%s)s8 z=Ike1HjlKvkpt8%0jNF-XPK_prXMDOjl8}u;{!uAK$wZAwSt5qvJ zc}0dNCz5n%f%@&iiUGhK{=?Cclo8~>WBd~{M~ldBHPSt(Ln78?-(0rR%A8jla)_&2 zLaQKspOrod9ab3e313h}S*stoFd@qBN`)_Gj~tL9)4v#Ys;w04-yMNEQlQKgo$XBv zNm%JM4S%1PR(AXdN~p3ejhB|5Qn3Pby&ZTcNuM?Z@r!N0O~u+k)Ad71zfLSul>a^u7*QKWR*ljh!_!hLMwcAv(n_`F- z2-!>4mWOb&s^u5rBb!<>O&9oFDH?)IXsFY`-NZM!$~WP^{cRRdMB9P3ig5e^yu0LR zz=#RD&URK5(Of2JhBR4Mm$7pN(W66s&tEzNEJ=v8>Rz|%)9BS91m}`JR%Ux`M!NSEVUK=jsF~XFUg7K~DVJ?=jNG5X&G@~I z=mkYW;cQ$XM2cwQPlrvX*xQpseyMES@Li?GFAbM~bYigLJxI5eVc02=ahM=E({HR8 z;~K#=>B~P02~No@8l6uUC-610`g?6wMQziFJ9pS$pJw@eEg44(6S_OmE?_huxf?|M z0@4zPQNBJLTXv9SV=qgt+1+<%!vvv&$dmdowxGYY&7Q3rf*1?OJQSSTP4(z4qxJiR zETwt+PQA*5DS>~>@C1NlV7|^CDQ&_Zgv72dxL7!=xdi-8+#<#OBlA|b1}Qu=;A(r) zY@cZLVB`R>(%Zixe&dTm%$+D9o6+5fK`}8TU5b5;PmN>H5W@A>=Dfka%)$Q0#|@K`+$hLOt5+kX!E(5-k{|EY{2QlH(10H&-y zPxoLB3ynel15)+tXJ?9i07gK$zs~7_Xm-O@#ny}!V8Bjd1+kav{Ea4Ag=hir=s(IZ zhqqx?GRO*X2ND z1UbRSYwytiwG~~MqFJnCWZR8ATb9V;YcgGW6Uq!!#w5)CfPjC9_n{JCI=TF?YjZ*2 zHz3ocMDFV2j$J2=Tj1pG3R0-MlO=%x3iuP}#2@l18-KPB1k=U(h3LnNV`S}x!RHX6 z3t$4lOjl^^6DvYSlc9>hp@aV?&s(9XlT;N_v@A?4(MRin5DkG>cOuD2F6Ge6UG{hX z>b%|>35kDXYZg*p+bieaz4%!)aCf)}! z1N8e~1fT@bF7@~%ANTvB`%GgSzrl>dIkx^rY`4i?;SzANiMoUtw-nfPG^lsx!$Nn? z9t<3-$t!<2!@vCLWvB*gTF)fKC9&xEjX#vhm5Jl)!ce`XoHO%0edK!XyTW<+Yv zQ%pv@h{sM9nX0S=v23|(@Ytx{%PjGN2KY-`%Y2anZ+g}e zCmzAMFk(R$D>B@a#3H$2s^q&uWe1)ePh2YZ5y}Mr1ZlcAmp3|5=sdp3N)TZkFyf@h z+#_BRk*zm~;9=xlbW#>Kx4UNJw`Inp=7NM23B|gmm#~{ZD*ZQ>%&GcWv(0I6g-hzn zrRdxiXb#vtxOz_9BA04^?RgKHWMl^ z8?xZk2XB>3iY+>_SYYzR-lG*n+5HThS&c-%>m!5b6R&y#9{x%RC1nncojHlp!Xlf}2tle9UC|1@p<}3-A}k^1KjCm|B044bvRGzA#`ey^Z7Pp_9|$FFl%ThX%-I9zUp~xP<7o(o|#%M}fsOI~8dy7ilyMxb4+_ zBg>%C2Bz&0D;l6ir%wv-4{~Re% z)*yq~7_#XPl{6gR-Ba+&W(MeZolLJPM@|$L?a%GT*Ea&+B2pG7KU}eC*i~#a{g}V- zweawjbQ>H0XBs8s~ z9?!Hm@0SI02HrA6jUVh>6=dO4MG0Y503jz7&uYOgmTW>^Fv8=VC~3a%6A(;DRAdVX zR^M|<15BL%ZIZ4JuXvR8F*`}_g6BiH^U(Jg8x}F-UDok7lZ^CtD>dizz7}^5YcgJ{ zi`Jp$^8B&(Q4x(eX-EPkIkd}t^vZ|Lmi2VdBoN{urP$e(T!F3e+=}tf4tpk>(Y_bC;OhV4v?cB+T+trHeKR%q_=V{iJjRw~ zh|Z5OMu=uoHn+?>EfYUUN&eni9v(|Repsv<9}vGY;KZp z^v3cf3eL!s%vw5PXI&jc^&oJxfFPW*`=gxM3@081=UzV+)DyDz8rIyQgcMp`&+VR% z1RV<^;FVFG_Y4&knD@J~y<63=>C+~@fJ2lK#|!vCy#d#j%nBoh zmog%X*JQsKSW4em(BO$lB8P!_olaKUxWldd3Z-kt4qAd!EY|+>F>^L0!(4RKxzk3c3sr^&_p8u?+;b4{>|C(Qi}(mv@UYJq6oss0 zx3SvLTxmBhffD__YkmwdBKQ*I>~D)K{yla%rIjMje{p~NHkt_vsHy2IC1mVza=N_PGS6?E#4V~2 zYZ*X=FvY^j3g?&x9&q(<8>fHu-9~pH5smKY%V%yvR}nen-HDAvNK@>eQ`UMDu4C%) zGgFh3>_q)SdT6tiu%zs%gGhEK8703KX$-Di_gzE!CO;M^GhC>8<-jhi4uW^`bFi7m zYtx-v7hjk=cpK_D%InHLbcZDFIBK4XSeZ+`v6UZvnzltmeu0a|Vqd>tz24Wn$x0Am zs&I0SCcumzWNch@Rn9{ouPrE)j<};@&4(>R@z+SkiXTOv*&Gk4M14^{GjGb3jULx4 zwA->(uqx=)HLleoS)V(*svu>qH~v*H9`chiId zN{Ew+W8R~sk*|3TB7$D&jW=bsV1R+ic{&Y2zZrH1QrtF$y;o+|)yO+w_t8Fd9g&|_I1 zv1!Rz=|ha*R})0U{i_?UZ3k<2c6_2tNF_1zUhP$UVVop!m(W#buV~==DXx;CK}(xD{TV zH7CL1ycW?)PgU5se?(1!v!sB($aE@-WYw?<9nVWq1n9chQscIQjOm{rE*p1^(MY1* z{46MyoQ$f-cBCh~_pu%DTMaxQUQb+;D8r28T!cC`;?(LM_tP8G(}Zm-#aehTr@jKe&M?LPBIutyp#m%m#3X7dMnOQiyLcZ)7u}%|6Aq+i5KS|o^E7oi0%)c5phf&m&<-wK^ zPlk?uS%3KU8^0e&7)v4t_mm#bx)zDNZe2oO=J5APhILk|HX*TPGP%aFNk$VMTMn z$Z`mOC;m*vfl-}XMZRDk_!paa(6dA+))5Ea)mGz&qKq4Q3+a#fTJhmmGaHXW3i+{< zyH%4`5($FaAs8E=y8Wx4vadt7`jfB;(C%h<5_-trvk!FJ&{$&AG6GC^M*0Res8yYAL6}iS=DWu>mXhN3mq6T zWAWe9%5wui1ocPIw&o9NQfirjg%F+R#LRPrS(I>}FW1nqVnx~F*dgHZ5XVvhWpH?+ zPf%E=*EvhNx@#YT)a3}(x0K86%sk;KSf7ydHa^~S$=%ti_8T3I@WF_Nq&st(;G~Ee z@6_8*IuP^lSvxF1Zt;Zh4e3<-EaH{U)pl^eWwDgv|2S~nBcb!KpD;?(S$?Q={PPV> zK;qb+Pz*RY?6k|}c3V{%$mc$Lp$ao65I0S&p@W%}GPBQOmUPFTiSkh^zqnX?#@?9C zal-Cv|EhoFx}KzpL8D#C4ey5r&M|r+Lik@sqU6Q-FV|=91K*dUK@~=J=D}_x&T{aEq6yfC2k)ehPxqsncAhhB6z&q-oeli zq~$4UXKDMcghPP-Xyh0tuW+0d=+DQ3w+BYE6VNiahFQpI14^dY_PufjPUv2J1r)@a zG6X+sOl_$8E}HcO8+15HJnz99FgJ=3G}95s^ueua?@b=eWmYs*S>Fp5E|&zXjc!0n zlAu`_hgDFY97DmBDg)I(#nx7yt8PTtyapf*I^Pi*{%zh3A06;WRcEqb1E>Ju`qMBe z9KIa_P|uF1Od4qgzo>}tjJ_?1TnA+uR2C(Ql<$ycyHH2Y#HaC`u`3`hA9?GSiV4Qu zhbarr=pfqx5{E`S4d@VYgo!k{p`C8g9xWsF4DO7d)}^bEr~}1WpT#A3Tmo6*L1gWn zuAXJg@Z&)ZGlpk5#BA29WM62Yix~LE1L@&}jQ{cVF_s#a7G0zPM~mkZR2SCf6pe=J zwF)JrsA>6CmD?;)Ym?yHd;qEtDpGN)xshaUeLE`^)%}$$i-4swN2gt(+R6F#TEQCP zLp};wzt};_hu2&2*yXPOu_;#VkD3jS!l0c2at!TwchkPM;(;bm-yHT^y}pC(OFBzd zUP-Zre2W3AFConH5!QlQ3Bj1@{}wV4%W@mY+sCt#rM&r-X_UT`5_A;0izFGBu4d8k zOAOL;uuY?OS*qu|d}u@Fc;`n78S!r+QW5w@%L4zT0AmQ#ik(?G5Bj}abK-gKXY_sk ziR30537XxET^`IrTj;!E1Y6O5|AR~}pf1_#VWPLbDR}AQb*w54@8ftlcFfzD>I~F`O^%9=3;-%rQ7$xg?nA=9F#pJl1i30+h-rx*SH` zFpz|vbqrz-f_ve2=J5giQQ{F!5EyNIKZWv{> z@5989xBIAM^W^A|0QMLAFEM4YGW2OHuyLI358~lgGDW7ZkG4C!CNUzL4YN7>M1!I# zd*9ovXg^>?L9`14v0sLR2op*^kcXosIGJ=Q5IdUxyB(z~A$;!MBlVQb zc~P|BJbjF6*99R(8P`->Eh82mix(vc_b6Z!1<`pfgkXM)#Az33zl5hQ=Tv8HNc~Eo z$t*D^`dr^iGz|EqO!LsUaQA*u90+l;UHT$BcM%P#N#B6P2UsXI=JJJ>;8BkEkY;j) zmADn>PCmOmnwo^l3@*-^R~3h8I4hyjZ1q6QX{pyEp8dfU8jlVx^L|MV!?hWj7+@UY z#toJc9l{Z%^w@<)h$2E%nvc9{|CyHbKLE~{O2MT#1O4ye$rwAGUs=vX=|(vz6hIVTx#i$rjtev(!vk=mPzS=Fb`xsB5X z=%)OX%CrUAw$Z@-N^qxw3OszY%LbT5I%7(yUc!6c4LI!%vpM^pj8R1L6KBc2Bn`-- z%emW-my@9cEFNw(WKGsRJ`8Mnx*7gMi=tIWKeJb%tM> z`ETVJQIweftdvha$hXK|eLew0D0-JxOUewhA;R|U`HIr&-iwne{_Crd%O#Jzkat5; zJ`diS9vV8a2(`=9uoBwvs-ORj%Px!NDSGTf0 z&84F+Z7CGV8?0OMJ0zkqioPPr<<=b{Q@t2whxn8xF^7 zV(?6P;EF;Kd*Dl>8`|RnP86C+03}mk1O3bnqK5xHq`q2=lxKzOy>W^wv#X z>gxZV6Y1sZXc<<#4@xkp>IVpyTJm!+Lote-{uY=yFZ`eQf(eK#k1gj=d31#N4` z@k+yV==V%;F0TLxZU*@p^afX+J>2HZpD3oD8YfRCet0n036=^qcXXyU-d%H|YPwYd zb3JO#jVg;GvKzYA+0?1sOZ}O+_B5sLzBDfh=Vqe`Mc!a+ zjy)*ASo;d%Dnjh8^hyy-F$HPYu}b@N@x;p$Gpqh1+<>`c7}4)=8rk-?hQy~v!*kCK zaEnFEfFz3o2Mtd|k4+jm>NSNM_3rz(;4uXR?gMqiWm&%4001f4&!z^w&dYY?T70b}R0*)?#zB9i zCfvRStV&9O>yO{6@*#HwB**f%1>)gEJIcZuUu?)_T(CHsqS)h&f|B^4Tv4)aQaJjA zZX3AZ4J5WnrLHoq@saW>4g2#X0r9_{YMy6P_Ou~6ch0V~#c5gEPMYm|DrXZf%IvS9 zu2O2E9?S(5jjo3p918UfKY_xt6p(lUu^IpbEZ&WHB@gp$%+8JL*bdD%Te5sw#le^E1a-wLC1ykq(CPF0|BOFttf-DLeW36h|LU;HW01=gCw4h> zHyM1>i?{}F2{f%Uup6nB(T+IFYW9#Xu5IuTAk2$RV~PknROEnalBK63oFD<KbbI#-6? zrHJL=zssFc#VSO%97NhL)uS`#t0^WrcZrf%&V0`aew=JN^(9&>zZ0Rc6>#_ve2Io! zgFM=!Qdx|)Sx@glLUxK9nbF%oo+^#>zb3HW#tfUK+qX~R&MzB$y9?=^wCGZdHJWMC zr4M;3r1SnF0&ng#HHe3kD(Zg{gPmXD2RAuT_*m~+;xwi|-aFT?RQH%aUUQGv?-&DE zsizwi->qgdQ2Pu3aAwKH6yG^hti9$QL{YM5*OL$)6k88!xh9@2O3(~@qd4!BPkaja ztdOR5;gBIa_+OrH>Ys<-_!S}717A(H=tk;mHv&UB^!Q*v={+5eXX|g6;?LKgUi5jq zO@XaF`wU9IcwX~Lr0bcA;Yw!y=S~YTCzCm)IcwNGMCr%e@)J;-JfKNKy9ZlTarfDa zIg*MO)f3Do4k}ev&yuz_t#E6IKfc|3po#5q*(XDJ-4Oe?4+=0BuMFa~JqARJha;3KSVnWEk|8D85q4(hauKxBiz*B&Q{ABrrIk z<%k`DAN>sOTf;BQ90WNg5x&f$)I>#lejwRGTA{jKzD)I6F@J{LrKNyHO=o?t1@^Qx zb__t&&gsPtQ1}E2Z~e*ghqAx=D)qj2fu!^WwbXGvH3wR>uPJu?4VI#SbFG~J-F;QF zh=gskqG$s;t#ugk;SlB2;F{L1IR7^N`{@5VFrBV=0H6^QOHMQ)(5P6N^Yh$22 zcs638fuIe{o(`Xa(HR*X-Svo8HR}|06xEBVE~euxE(|f51A*=OF8!oduoxUO8Vr*o zCCyWDOCHn<%G~yZudL-hrL?|y{Wyn z9mG5=69iZTXC}zq^{LNOD?U%(8MZ@12}03_Yo+yan&J<*T$nK_qlc$K4K@2|G&g8d zSmJq(ZjEnD{lUVxFn*JXAK|4;HOnI!MZp@&9L$yYZm^PN2INM#J8Su5Xp+W3*#CP+ ziW={RDyS#$LL5G0p%qTr&U|#r1HUyE{V)+;&)2Y6P&Rgw+CO`pn|a^DCF60KN^0s) z-;Wka`vE|d|JO@@uKmR=R&}S|QBxWa6SH}$YQcKvL4^ajTz5<`>pqHY-jU-{MiD+y zwF(rPmSBD4%xk`HdM_89)qT(cPVb&vx~|*jrJ)EIbflK1gfvr7e@mQT*?wZqW;YLy zQi^J;5**Z1Wyzl7-(<%S-2ac8q_kfs@gImwV}&b+FUF`Tfr?)M`oqe+p_RnU#3t2L zdD>qswu}4oR3gUYmtlP6q3SPL;qulk-cLAD)LxAYfFQZIe+N#!%Kz{(1x_Yehd_n) z3dTqkiz!*r z*qgr71rS(uDVKz4V^k8m6RU2EDmI1YVTb~lTnx%)kus4-ZDC)SrMwlA%CP&BqfDsc z@H;JLYPHjUZ;Vos^Uf6k@@;{lLv;|1?`v_T{Fl{Sv26l-QtU%W+x&(hn zQEldkGDyVcn_ne)g172%I*EYC#s-Zom6?#T4?4A1Jf@G?16oCZ0`TN3G*#EJm-$6P z-U!R}aY9=0)EZe@M%ri$SOPBfoV*wUSb-6Z%q)Xu|DBOZY5o7?@6tr(&qw z?f_)EsvG9JdLi?nQZM_s6^ZrhIThKT?Y4R*;uC$2CC8X~nF0 ztS~b#;H%{QTm;WhU-f+FuqX-C1*2o)`Eg&(54HO9O@+HllI?w=-1cA^v^aj7cUIy> z8R}RgO6CyZzea+qcif)7XS^N1;$h|Z`U%mi6!oU=fCUp~+OZv6*c@6n@jJ*H&ND77 zh#?h>$3iMcY1b1a>5l3~joQU;<>Xn|Y~qUB0i20ezI%b3rWPI`Rn&YkK!s3Xcpmrp z4)k(`lj)9{Z@yj5C$5QV;IS(xu`vSCeqBOlk_ECrRstaVB&HBXljGGW74-MfvA@Vt zMFv3#a35;Zg|UF>v;O13vch?Snx%k2=zk}E?}OfV7GTvKq!YITQTAjc6h)Y*9WPN6 zIqC*A2KQNHs(Wse*j_-pClK@A6L1BmYcPn*@Xv3OHrD~hlqB47;gm&1NMuKEeHNw^ zKFp+E(zawOZYk$#Aq_S{8IHDLH3wB-qM07FZpu$$q26H>J>i7r>VF1LyIg(n&=_W3ksPLgoN$szXPx9PflLI$080fUThcGoY!Fm>$Vux;qpZ4Vigo9`VVd`Asdk^T#_N&aR zDd~BHvmCe0fNgCdPuNg1STVPY(Ar2Zeg)i#GZ540BakHby)5WB!RM@{)E9Py_5K#n zl-e$z2u>}-m$l3ti+KPTb3UZmkiv_B>r399dQ`~}lbCai;|8WObLO`#7xI!_&(i{4 z8b@4U*t9XJCTUYKF~nf07uqe9X-w5#@rGq%tzD*L0EUSC(b1rMZ(6w?`d#ruQhGkZ&~_Usga}`9w#r# zq}C3RY_Z7VBbvQc9fRA;PbzwZkX^lLq$jh$t=CJMq`cm((h8VuLmXW>AxisqVpW-F zwzGCmq9oav==UBEQHEKMhg>U%UEj>sEui`4lddLf{Mz3`@}Hg9Ghrc4zgUFRKopLQ z%V^iCf9y9kAWpoB7l7_~=8k1}kNQM|lz-rW}c0bJ;%|B72 z%k2H>7nyjM0ENU){qR_j9 zI|v7K8cu$XepBeCL}P?oUDx>oWV6E{BOX6Rf-_@lJ3yH(I<+hG&amJuFENV!f9i4@ zd%2M_Wkjz;nr*?xiA3cWcfpX`Va)b(zOJ|gy*N40+KdRB@$8U6A`J|T&~b*{hC&p? zXLmaN_ez&2|Ls{{iO)^rFOUDormUmi2 zR+OLE!8i!N63SiMjOl1Az)SEzU=xpAseX^+(kuE>kQ>Y321k{@2eO!ZsC=@Y1uZTpfj^0?5t$l?vEz)AJsGS|{o-_NE&e zQrjG>@Hk5-2u&0N!DEcEsStyEC3wS*qBZfFXaxCP>l%kplK+ly1Hw|Lr7t@=(RpF| zYHrvv5|@?TmvSTQkFSUHmYbdv7FKM}P)`v`{-KYX0-I+V;e1d;7=yvziusWv`G|2M z9Mq~`o!{UzRV*%0fCEq!a(Ga*1|9=r7mPPL3E~QdyW!$AWbyL@X9^$7#Z6}b$?M-b zCgx@gQg7#vjf86RVr;SP;3K;(cED7R79|<}I{TzWIpRG^e|(#dsr_cmk;b{5!px?9 z5#z`vR*!g{nraIcHFaH-~4-oss#U|7!7T1h9y{eLA`#y~^ zFk{qA1Tm6HjhC3@fXK?Rl1K_bj!3jvy7F9{#HbAEhI%l3NA3KN^tNGuztOKrc^o^2 zGTjyip75fV7DOZIOEy>I0x2RGm3S@<5^mm|v+pI_uX!zNibo`SosaQbg$wXm2hPIr zk=QKjzMU5C(%fn$;NNUfsu1?njRta@NsVAzR`_z*VX) zv}h~?F?W4`lCbkyyYze+d5!4UD&F2O3!|@H`XW~@Ym&${5`*hu8#$qrNiUVBQG7tU zQff8zyx{yXJd&NAOSP-MG*s)6t?v#*L4Ns~vey5KbkzUA8uExa_0=!q+e*llLE$sr z?9kKj2#>(TSEyXR&4D;zmD1#!Ab2@GM>9X`)Cb+_)F?bXX&GBM+`W>EV-B1q3R9u2 z-4DSgc=uv1onqkNir9wA?$OCA5$I91e#jD>z#g#}~W}OsoQQ2UBo02`~~cY`Zz~B!ZVwT)DV&U1`a%14m$T=3%GZfONW7b!_9V!1Z*Fka!Oo z-%ZAcN+B?BCpgUbw{g}hbntelE2QXzP#(C*_$&1aEO}ktfKu7il8kj286{ye9GK^n zHC$QeFSzkMqKn)C@gKwrRoqPy2R#G_RH&4d^~2Y@3#yKVg6!E`oL4~byHXW+-^Nf| z9F|$}vMXv@Jl>VU6uXg=5zQIz_vn4%epGNbO$>ZI%3(#jCc7G;EJQz0P~Hl4B*wv} zh>6MH&GL!j?%+Plp=7x(GF_31sI5Mh7zKr(O_Fu6*dPU( zTTu-fn1`F`S8f0_IyeUsdbl=w_It)aw)IXKbAd{JZRDroJfogkw)}*EG+}w>H|d~~ zr}dK`2D)99BQ=D3c=1cxNvaa*JfxyNL?fs>-sFH#3H0tohOJ$hqqbv2&U!?6R$MFT7y~&z~#%j_`M%IE7oQ}G+O*J+xSw_K}KsD*>J#Kj82#vm1WCv7B3|Du{{X{9tKMP!b(QDjwzNNvaHy-2iKTg`8z$ z0Z9q6HWe@JOob&-)gP`O)Z}iorgp5wk3gZ&6sce#qMeu02Lz!(7h{t=me0E>GG!ay z%Dv+&L(a3$eWzKS6pOXh)!u$Zmvt#n0fc@#FsrI@H)oN#wsaY_*kXJ?V}<(4tA)?g z&u`$@E?#m@)|Qd7QfcPPl*{in6d!9x%S&d=A-C?I5DJ*U*~|k#Oi{aYS*y|r2vFnA zN%WWQF#9RM|4>HXiwnju%GRjB zKFyxiq-oZbWpBK+6(n7V_?}6Hng|v{CTEbVxS!JCW`_YlOO`T|$kQcZ#~zk4u6$*0 zU_Y2Z)t1jr4az&!PM-@k)cgA&+Nd7x^1*isydGA~FP02SUvSz>7kLF#M5 zx(@%o)SB)1{WOVi=?a)9ooco;sGH&wY-xwhEO^G_!Jbq^dv1r<(**gXM}bo$-)V{z zIi202xFBJh2h)k5gr5}1V`kUkAv)+iSk;W;N|HZmG+2X;)c7_T2>%zN-RuEamv9L! zIb^G?%rhl8T!9=NRdZzJwhOK#Rud|Jxku0!J0>%1=gbiYuc7E(rn2eQYVR&Sp~t7t z*i=tK=;7w1sXGL-iLTI)jSVI`LI!3y#su^;pkTzR zurV{lDeF+dmH>J29aheA_Fb{OC6DK#Pvw+Y z6bZwK;jYH~E`b#^w5$n^%UA~5@zD=SMptS@Y;S&ho79Yss;oKzQeqY|5-C90xN2VU zkLNUo-`w_TIW9M*KyNm;Hy>Z6#3{eo{Rz{os$!KY9!Mlp3zmSo?LWmm_LsU5vs|8O z@p2R60zok*L&JZ{a|ZEP7E+q#_71~PmgMmE~7i4rr7FfpN|o~Rs!kfyS!*TdEoT|SLoO_J#Ytc0R^Qx zPI9hF1e4M#w=?ErGYnrft$^M2t^Ks`>ht8V6HlEcWp9q_^DN};foR=1YaYvV!i0dU z#cDY6FT$a<=~)aj*qy+|(^~{Qj_wmpWbbwh8f5oPiLLT6hus;kV9=LIY|jo_4}>sRps~AG?4MHQl{mYuBN3Cl|+LR�!h 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%0DF7qM#!h}uEBjo zmO^1f9j$8`Er`?QHv9)8JBP`|0k7@0HUlA;#eo@=Y*dN=&BJ>=N8Qc@@RiCD=>`}O zUo;F;%4;J�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 z%0A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

jTGYevpjLDOHM@%oG4)!=>7(IFZ#Km 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�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⋙OOB- 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 T{l__nVq{>2A|Vlx6NUO;Blzw* literal 0 HcmV?d00001 diff --git a/test/experiments/osdi2025/paper/Quake.pdf b/test/experiments/osdi2025/paper/Quake.pdf new file mode 100644 index 0000000000000000000000000000000000000000..de92f349f1a584dc171ecc4d9a01935f886cb36a GIT binary patch literal 1096475 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

HW!_vXhcz2~$JVzl7>Gj=)I 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

ypxtNZ>W!ydapE=-BNfC6LGeydTP}lZ*6Vn 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≦%EAyY;G3a+NfO=1>LJ7 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%0Af9BRXucR`r^MUY$Pbczjz9<^#P?*U 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

ZG%|gmbM>O=D*$@=ID=6{ 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 GeXT)2BNn)v@u3Xd zVBkq3W)v4vs9h_W`#}O51w;}>Jq9L`o{#bm`1E%~!FP#3Fd7E_>-LxCnZ`{Xz>!~+ zLHz7|qSh14DzaxRS|L@?IWMkD%37~MNA?NfRIqoyic)dl(iAV8y273aCBP@EE3g^h z9+9D>)l>)_%*qC!g=S|!BMy)ezaHdnbgS&G{-lucQJBl6_Bg{XF37LwOX5&B+8$bp zgePM)0>e4l7tLG}^Fk!y%};29?K)2GmF$+)I3`Ao9PXlc#nj1Q0Z(D1$Q|bf3_0W7 zHXRM?zltO&VD)zG*S3M?8EgjNeL}fztRv>R%B5AYDe0X~C=t=$8S|uC*|M6~oL<$H z>ZhEAvl03{2LHs$o@m-90H@MZ*G~pi_kGEliGa$*pXVi$Z7?4$c8IBT?#?z3U)bcX z%9%UuMx*P9W#k>6u!Oy~xp%5Fy)7{=OZ@HEi5bTlaxiI8+R*9;bFIK9GaKBNL#2$2a)EFPC2llm5h z?#Rw9U)(IoOM!Nx$}{%vcVY^gfeL8;_P*#r?Fy9@I<1);vxj81!<7z$b)=10bNtGh z#~)7{O>7VF+)w(<$spUu*otETBgWOb7L*C4lV-(XUL8;eojN zG71Af_ACb}zhPIlOsS*+4_c~oYhkix!-JUn13>2!vxyf6EAkRzbQO_^igC?R)pfON zEm|OS-a0vjxF9^^1340xN3m$k7$VrqPAir!62DL4>cZm&rKQE`@cN2F!P?r^bobv! zmzK5M^5<`nn9m959x#+?8wi+|cax?e1iqG|=_Q6mqL-y+H@Mma=CD03$H3T@*K?b8 zd5~96E56Blm_N)oAVg+wnCfZLx=qWj$-PnPc1Nt^PI&fI60KDwcOy3f37Ey}ngY?i zRUrA6mH*uPSxPsUWirU%?+GE`<{Z2PTt%^I`brmPf??CSnfxfY}0w77kpW^qp3 zwzV)ksH|@KEoyd@d^6>?G)@x@&?HYM6Z3yxZL4)sgXV$1_ry~DAqFhu;@xb>GoXo#`Q_%J=>ghW8sUr^K|NV>0FZ+_sz|#Z#Dq> z6%1I%1~X7uYvxESbLFQu4Z$R#XA3MQ?0Xnrv0A`^H=j-@jI3eBYo#FhGH?mKkeTE8Y zV2b&cKezurA@9+Yfb65N?9mX;bUW=Tz&`~2Vl+2{XHZa&y&SBUbZm;kcZ7T&2VB!K z)&8haH+L&c3Ln0I9bQI@(@M%}7=J&`^ff>0poGGuuyFq#@q|_Zn3{FHujEyZKg~Xtsf&Ycl!t9sKvHJ0!8_fwf{`mG(8FjVR&Dti=z6++&3S0fE)aXZk!}tOt z$h=eCy+a_YJwC*H-`-O&-XbzO#A{8RC1?uv$JD;CKvFy_!WpA-tbO5*xWUv-)EKAj za_y0EZv&`nwH_W$CvRnfFR3w4n3nvq&yM)2g9Pi+LO@&U39h$C`?@AiD)P@EhiDev zI_eg*d8#Fs>YcHa!9k$>$N<&&Y6=-@S|4u?`YNn}<~AO((l7=^f>xlOCo){$r*pm? zFK@xI1ywMP*<&v9i%IWO$uGDR9Rz?6XMR_wef=aPJHGv>;nVdK3%t%-p4Q|1U%pFX z7|Br4EAMd(X+KgfjQ1H;-7#{7;2Z^)hSA5(U(rUpuD&}63s0%EgG2j1;0gi$Wm6tfUJnWc zYjf7DU9cz!$XDei8GF|VfN4yIX$gse_xJ30|3wNLI!-((e!OFzoON1MI;Ki*<{jIs zEVJG78;(vUFk6H+t@KTpz9=Q=d&yxicRGK7(A7>wXjw6ntGlZ@0C}Z>3YXEvucOfwk1Yd7Z%@6G6DOOkqY49mE$#~`Lj~NLiY;# z?jG=eTJxv%dJz_RwNi!|Ena*{tw_X|fa0m9?a;@!N2=ZQN(gL|UMOwcJY>s;hG9TM zpq7&l<6t|^>>X)lr<`l1%)Y=YB!P>lO%E-XZO{5hVbGG&`D!r=Zzfc$@4^97)1z4D;eEqL*RW8LcYvs}s55m2B65vakT@u+!9<3Ci|9Wt zdqnH6j{)E|_q8851ZE99@Y$u8>bzG)<2d6Hox!Bsydso0KeRsY3-19I6c|u-k)LKh zFq&2@8n`BPEjj&2?rp5*sXd;05pFH|?1&j~a}kc8xNyt&6L_`}3-N4(gXc;}I5n`- z&{v8E-kFY53f6`U{DFzx=3YNbqz8986TTT}0T-7*J-Pi3H*@6cel7yxk9j*$_q81J65 ziFla8(3eaA^N*D^tj99HsfAV9)%r#cufQWS?%f`v5Fw~)fAG^R#*>De_n8pe>xQ9oLrj8^@|>2SP}L(&*Lj%JuP{NWp(L z1Q&xzE4=f~i)8_zAST?P+|WP`J==(Nm)K!2s?x%Qeu zp*#4|;ZoaiS*Wgf;vPLSQ#fGfI2!tF0fiP6M!Wl-`!sotvm({1x^OYCLCMY%-qtcb zKbIj9wF`=I2C^>KY_^GNlX35<0l~Dn`xS8%3#PDO1lqwZ5n@{b2`1Cs2JMcsUV&C< z6o;yDXZXVALQH@u#>~`!%WZN?y^u0s=Pd(dn8gz;)7?g84$kj+30QMgZ9Xo}a31Bx zMUKB4>@K6_@B@K;axAS4TFS?R&L`B30y+BE*E!9 z^Xij!-9iAghzq~ALEnl-)Yt$*z?va)+3*{q$h~5KHSdHC}sQg0b-F>lIKQN->(FwXSnt4f)qUu^e6vu%syUdYJ1$`dr5mEdRvE*B7{X(qVXUf zEc~am)UjJZ=D%$2AH=dM8pr!yP4x|sm^LC|mBeJGAiiBxQw+KTm$H-o2ZyE%zc*Ftm$5k*mS>493UCU_8_BrBQP^S7aOR<9!`Q zT0MM%sk%z>iWpWprvN!XdZIrv-9(YVbRWFyvK zIt2uTo@aL>=U>Gk{uP6u$|ASY<=;n^;wfcuMDy{eYulU3Xlqy159ctfJ(e>JBQ*bQ zKB(B%y0Bo;PV%+&2ROvc_=%f;FbmP(5!gGktO>r-3UpZH+;>Sf&BTW$53K%+Wbem? z5d92nqzTysj@bua_~p<8HaL8HE(nhiV|>cv+&yd>1@z#1c~H?6mgNyTanv>X-6%e! z@CFo{MuUYUO0qot=7tr-e0$9ShL-kN(D3NqFS7q zwp57M7UH5e_%h$)h(?_h9_Bd<9P5O9k-YJ66)({nQ3cXv_xc4R&MIzRAdP88(4LfX zKSn+@y~6k;zTghg@P*M4taNBBMrYmnKHFO0 z50!jBi1jT0=I848UR#-|9K_Lw>o=KymhvLmstDD+c4k4=}e#<1JU)2=$_1x z9^zSkXGTuEq^{V}10TPceb66YEffXY6Gvqppa4Y7;MhIc=C_nPbn5T}4nx1XYgC9D z6<7_vgYq8Daip}l?mO!_{q#5!dZnScY8JTB6!q;RaC_Q|xcQsg zo>D#lbda)221BjumX{J56ilJpeAH4YyJEA@bxuy=KI9}Zb*B?#APVF3V7vBq-#Vx4 z?&+GKuAm=daZHc@;O&$aluN#&7kB1yHxgZYD9(k#Bv%K4Mbyb2$X$>PCMUTVG0D?J=z0e9Rp^NPfEu{%oQvC zW7kP?)|buruuEc{2wH!K+sO{BMo}Z!?f>ZKt&mc4uhem>u(U!#mmIwCULe(W44F@! zlzrWvo|bM2^lZ{>|v~GjOHL`QNHE`uwpi zyM;9LDe!B8<6xY5jwEkjEoBdYtHJ@s!Fw34NcqAR6p|OYpyr%540Z!JFfV~l}~ zv>KGhhF+p&U$x7S%Wt0TWCU)EHW%Uce5`&8ZbepNf$ ztG#{1m+MwI=ZI5cW~7ify?*Etyj~}+8Jo4TB@mwnLOComJ163os2_5&517zj%R|ce z_z&i{Z=Nt-?k+m%+TITw5~h>d)IltxG`RkJI%Iyv75LjH7aU6_^32{W3T?c1^go^u z+&jRfHm7()l+_70g?dt71?#nlXdTrg>v>ghe*aCJfvhF1HOpzT;=H3WNroJey3eDU1SDqMmGZD$AYY_T>= zPS1`Z{-6beT+Jg0uf8Mr$*(z_ID>Adx{N_*~6yCFgd;g{8=#>Fr|L#z2v#1q8eAnGgaW zPco_rD#&{!Tl&-e;5(L(s)v(Ssv42vOG9oOKih$-fh$l9jNRG6N4;-w@=RPl$X7*T znx|;NpzV>DuXo-@R4_Mq7OmY}P%VG9|5%no0kB6$EHR@1E?@nLWJD8! zC<2uv;BhIaOJGq)HF*^w#^<1ldneJF#~kg|T3#Vq2<=Cjrfk97fbZY&%=*ITQIu$n ze)sMDagyo%L^9E=yfE#yNgfzj8uERzbpiG+g3Bak2(Xh%$ejln<(y1_xB<$VL6ufzD+EwEs!L*)`uLfo=@&Wju}nY$W7_mVOsgESXgw1f&?JC4Gh*M_ley zEMN0b{CQFJPB7fh!`5s&nKJ^&Vu>a!;c#`YY|z)owH<881_)pZ=0EU!-J+oi#js5# z@9P3S7R}(*NeNQ-*^T$BLQwfd!WUQ!@$Bo}dZ*~vNJ5^o&op>=`FKk7uKedgqp{A# zmQ{);I#vxuyyLJ3eL#1Ltz|5tFj|0%yaFBKZ2$~TQk2Q&0D9Cx zxv>P-Ef|28XyiXvZ*wmv?bOvm%A<3~Whi`X^qZusI{Znk7Pty(&yo z!1T7KLwf!+t7siw@sj8t=WscCC3TntdfJcJv`Y_fev*AS$bV-&4;@&7Uw=Fi{Qg74 z&%)Z933IumzcTK^LHR~A8YS?5lA`UvbM&Eys?M)^b`2ICuuYtE69=}YW^Mlz{KLw_ zBQ+zDtl47F`!g_MG<_uBz?iYvUHQXY79E&{1WPDpMVlDfC|2cGTIdzE;W_;hTf^tR zx;jy7XU>Lah^H4J0|t&Z`1OR)OhgIasZ|ti^(I%&{~Sq2wvz}1TFe!}p)StwDcjK{ zcwdM2P&B?_`{j7=Iu|FM0dDsUm|H5>H^G!?xKtxAZ6B~YxPKv@72 zQgGk(i{bi}VbzSNG6}P4jR&lEPT4ELjwgIf4 zR|^*%)ZOI8h4WvGssI$1^bnN_W%~CF3rHSdZr+0j>?T!Jprr`wLAmDC*j9U4VF$ z_Ntp3O45DwEZdQ5L2eu(wK-cqf~@?^r#oXlig)9dFWu3JIbgoZ3|7PEr{_ot=YiPM zzmC4i>hc20@=1^735H}rVX{i6eR;Naq-N_-N7|7&Yav}IJu#UplWA#bCQBGpm;p4C zC?3xZK4`7_UN|*RvP2@)brdZkT8%z9@ zF9&yR<&f0r+a&Jn{xdw$Dr=dUlmqqunY#soZT@$?kk>(y2hd>x2Kpw++RGijP%I&m zRavCJ0$Uw%5cmpjF^FuU0f=W2{pC9fT*giP0VUJ2xaOp&F``G(xH9l`i0 z!AihW)#BfYRRz~Y9^VX~)VOJrFBT1%D;JR%IuMkF+u%GlnQ~!}D!X&r)<&i@cgIZq-xk?aC|+@g z5CcB70z<2V#7wZyE)gXJy>27KtzQmOeZc~ z;OU?pbp_4-M#JveWuKP`EJ^6EqD#kziaS{=%R0Z`7UQtBa$5<~p-y4V1OE!qk1+~R zY$R7d#FIBVSf+9L)I~In4^J=_pr4%UW7`_gg=AQ=Q3!WCS^bV{^Y231Qy{%ZLlBqI zRuqNX7r(OHFt-Sbe%<%Rsqa4ts6Bj+lp#yyE_L3KWiZ+ctuB0RYsJm>rl5o5m0s4J z9}Ui;_K?u=)gvTly^c$hd_TFGfNPL2Du&dYZhDwQj>B1lkCz=D1CcbbL+*>sLsjWp zf?$2`dNkRoC{KP}?_J%v${Xl3a?e~o8GEux1v|kGeOQ?Y5MGrUjVxP|)2Zu;7;$N> z*KUQKvQc$5U!Ptts|_Djiy*%)Rp?pqe89Jn7BL2x-vF$oGx!mC?+R>EBG)aA$b_DU zINFhyVeBg$7l#JdrFmRaaTW`^U&JASBHymPUEWVJ%kyLHj^OK>Glg_J>@ZAslANws zj2Rz@Qd??a7V(CWkTBAh3RUk zl-46gTA&|JRzZY*1PY8E@BtM+dt6Y;h{@Fv@*Pu$A#!KPQzBCw*FHcN=TNM_H$F(} z6@vI|#OL9j85+9=2SLgj{Zmo6>3;SX_^q1+ZQX-v0dvL^)l~1)a0%PT4Wkc-Htn74 zir@P94?me*r&ESGB)3#}WzhR+QKD()ng8Bkz0^qm)B3*cJ;*yve%g>I87pRS!~o1H z1`66r5GcB`%&y^-Ow~yy;3H6PL%-XA(rk?iEhE#;_l&?crARKBxTh5qpcFAhgkV(I zL_3cLJ*-OZpuMNb)k*%@I?Z$fSOH7w4!A=lfNX1T&!^Ooj-GBO*bP|h^A)mAshw9O zZcj|aufW2x!vgh5e>Y1W+nm_&!ToDqdaqwtS+@aGM!Y5~L>0L=u9tA;Tn(8CeaI@vP; z*Zn`FMw#FkQ3iK&w@oohF4@|m(DrI)6a8?5VUGDZM-bk`K=Guo)8g>90qg^Vb>*mq zaiY9Ikv!)NjhPBd2_1JXp#r+!3mccFsZcel69#K_5c_AP8^Sth0jSh^nRRdnpvcOp zYlr2`hX74LvcIjMtsBFtbDiY{WdOJzAQ5U-lKZwQta;VP_6oOiR3@0_7XY{Ap7~M?S8>yZ*yctlOd1t%} z;D+@~Xt_kP7-d}1g8V753}1$e$4CWFhDZ9%qpp?WZox5}ihb7!qw)3tEw;bw-Yam> zsS@yPIr4Zzyk74~3$Sl!9nwP)FCX*K^9R3#qQn;CJgAejU(3<0>Y&AR{(``8^r;_T zxQ+SKu8E2nSL)xK_kNLejRCQ1o^>96CW8YmbVDnDX0he{ zz28C7*6eOkVM1ls8+$emuTy35%@v?UF{IR3(&|Q2c;C4kd3HlY6U|$VRFHjZdr|5Y zicArz5$@k1;nhX%99#=H-O%_f7Tt&{y?!j;+*SM7f^)Da`-MKH03t1UFrsz7oQJ&x|f9c{_eYqNW_31HKDzh4%n7dn={?#+6|Rr+~t{3r-bz*fawRq!pRYrMqUVMIK-lkenG#&d)R~WaDOby(|vU= z?>gMqSh=>Vd7Rme_TQgjGW^N)hnMLQ6V$>#Gb#5L1}1upUk(CKKcM5& z61OL@rWaaoYk+a%;m@C=r%I?<8~t<=wEEuTH+z5Z#R=@tnL%n{zNa4IP=JN^ z1SWoSuF)>l!;KVbTypt-!Pz^G{LOz^2DqCgflN+RCMCdcy)o#F? z3i%FpIrcP`q=lE-W*B*no7N!j+4?eK+n^z$ic`T?5R~lWm;1fx=q^Py7>ZZ*Q=-A% zSmKwI6Vxi~hf+ZTk?+y;>ggx+0w&cQIA!y97`mK7m0I0J#}FyABOQDsi0B z4gJ!iqq&A`@BMGLCx&kN0vg<8%_#|_fVed)QqInQ1Zv6pXHDB=J~#&uVDL$YD4OpPeE?Ag$>FwRO#If52#~ibvVD&y5c|hOImNr5y@j{w={=x#sD< zV)G@)x6odQaCLaBU1kh9Hd~(EaZ=sj1AR0{)<+@+j&8CBI|e;2WeXyOjgFixJwP$< z)HzAyB$qKqCB0rfTTCBPuK*HhAk(VHa~>*d671|@c2i8Y#E|CeJm)hHe+{Q-)VrGoN#yt&agU0!JrU^a0hFDkmxB)sehz`M&3x?0fv+f*c{@|X3wWV0R3+a8RfO#EG157>~TeBfLci1cq z$;WYQ27ZysLreOwIt78s3}Dzok1gL0A1%BsrIP()8f#vxG0&3O<}G>l76y>8kNegL z<|(2aRFVJc{yE4{2nf2L!~pB}TZ0)aK(1H>v+-6jc<30_&+@H2dX>GGtoO+v(}I++ zcrqg;r{UIfn(a zxs3~r*X*4?`zF7Fj*=_vp{vcevOAB;+X*(AY3LM^cK%`kam>F=;p~&zp@~}HZ{CG! zyQ{EYa`c;La2G1{BFpxg4?!2J%n!WgU0`x!(8nPTfNi(T4q#%oFz5#{S+l8qD`KG=IGI38^SsbN4F}Z&RyKKGXM+sXX8$$q{$MwZV^4Uda{AQf<)8o0YGz=4 zb6ST*Z!pVz{RRoGQCp%#dcm(aJTgMQOl`k-TJ>${F->^0xNd9x1q9lq4mzVQBxM`V z>tT}9V9y+~V$;A~Gj%LPAS+}O=un`V1xD>0>^)MP;z?=FQf>ajoVZV4;L+*I+qM#f zyn8_4#j!uh!T{&8Y;qJ^z4bDi3D-XnUmoF-SJ{XWby(|BG+&1nDObcawod9($_T8CcKKw zo=|$-d^C~Nj(f)=&i;>g9|{nrlUWCK+I*up$^JHPqL%tKwUv9~GHEtrRxI~!qCHAT zcf#h4ej3^gy_(7AhEYXmPLK3`R1w-$0L?d^Ksp^`qaV*n(ZuUNLTL#SxQ}dqfSEw8 z@GCSsK(vJyH?n9@=(MPz@x1oCXcn>x%y;JorY;aIqscC&ug0Ya8rOoHAz;Qoa|)I% zCH3pb8Ng$+fj8`?o~f~-I0FLiER;~)e<^!LSDZ8-=Nc90T)}{A zTn`e_f+g=HV^R(zNZ}B2P(_p|S5-}tqFkxA z|9Mq6iZH52ahaVdO$lW)nx7>rty{0895o|RT?@S)H6pFtB-5%~uOd3G+6s8Kyajr= zFLEY2+Ev@BtJa7_deh>&pNNb=Z7R3?5MaP>x~5zLSb6YLv=l{T#2rT2Mb?r6Yk6Wm z_bJTKHW9*5CYD^{pIy54Vu)O-V%@jKJf;85#^C3PS`A;Hx;Kj3N&Wc~i%?^A$Y4?* zGD=;SF(2YXD^LWq!NnJKq(3Z7sxKJDP-Ru~yVDT7435%UE%GDC{u|@RN%R$Z%~rc} zuv6O85U-n2iXPt;B2Ru03D1Kc1hN~!5D>-EQ0jr!aEoSmy3%)`7|J zRKibPgQA8(dK&++gzw`Q0vQmWCM(ah_&F|k#qUz9AFjvLwAmGxi*Pyh^6dw~Ye+9S z7&4O!d!qnQK1kQj7Nx$lX4+XU{@v`Kb%qkf;Zt?xMr!66MSq{Huy&*{BhH>$Ik{VI zr#gce`DBP;4cSx&?Dszv56yG*8+aBtVS0;_n89Hf=?0DYUWR$#`pXEg5y#xEc8S!# zUW=LIB$d$64IejnR z)lhxOyv*y>;eCvSaUnN4&@2|^;ui>^iu&|z3}p`FC5Td~UTJP>a>Mpw33l{88_Vpi z(g{(Hh~R#^vp%U2-hq!R zOF+ReXw!|n7niutX)m0OCcq-#HRck%_hb6oWz}F>K9(efjR?fkYu1u+r!1mD5|6qI3rqhyS|@kkHox9 zrE*|bGo28!ft6I;bge(25PQ)sIj_%DlffH6M(v`8MHFvF*Ajo#tH%8oFKH9!Xo;jv zI(YI(kyBe_&%_QF`|#fR4h+x}dTSz2KBok}qdOgVTcyH8kQ1R?7L{wdbWu&bQ_5Gl zHkCvktF~t88TbI`A|>P%owEYC8QhGuQ@MQEkc4j#y}&jpm_q^`j0C5slDMfRrjH%D zW4Kl5bG>$-8dAHFxXs=Ag`#suMGQ6p(>#&KJg(5WJUbwmx(q1{ZO>z{#T|Q|*@QU1 z4!(}Sr_9*rBPDEJP_h7mfBu)n`q8+2N@#1e4qV>V7?Mm>qrBbl#)bW!b9woAF%^#9 zzH^t*^l#sgy1L4`7T_D^iWJU6m;vHP^u6k|pypyy?1OVVn z5uk{&ua)9=7O+%hes8#npYKtet&I!@xxA$5*7s`QvQ8wpPA^X+RN0KX8DjrzzQubv z=0Ti8cEC~$onTAK_RPVncD>hfOp>XAkFY)hP`NrdB)S8R&=y8Ku`s3=yxJJEl<@%j38Br0l6p zV?TUcB|SzU0W$T`un)g{zVGwXFbQ9^$6p+KlOf+PN}PBL&?<4t-QCpEi^n3S{fUC8 zBwyemR;*NzKTZ6uA#gCpQGdVA)w*Cibfc3E`>Okw0C&X)gx8ODLX7F4k+0)=@sx)V zgE+AJt5~+aw@CWZY9eec1XX*GO1A@4#b2#CQm%O0cw!-fVD7PgmaY~qx;1F3B41b_ zqg4&}0?Uic*ZRQ7KhR2ej{2$)*PY0fX8_aN7>}b;M654kv;jFhBfA21L-_L`G@{5Y zq2;$7izlROw**o9Q_XeXf3Z*kv0|&+#JT_$20rO?O5%50{}yg$u9J%(O<~!scrb1G zY2k20w9>1+*56GlXHc1Q1Z1Be{K#^A7=|&pyQModmam>BLdO9XhsXFdezNa05=)JJ zcEv_C7xRhFhsok#q3jA~hKJUz_>mf2mk?19SZgC&bNp{``I#t}ogN!gdj+6Ao+=VF zaGr@3>we~bVVuYrE;GDT_yZM=mh+uM-%zx9gq_ z@22|7?*3#I-kC3e$WdvaavHfG{=2=}kBG1@YHf^w<3+WKo1U5Cqr(WVh_`x}{Q(gk zek#H6(o-}OdhpwAzyc%>J~$|=%LroK>@3qSq^2M5+kqzW4rp+vSY$a3klv)|g%|+e z|4pov`I8#VCtb?p9=O;QpgTsOdq3UW!ou$(S_NnOtI-~(lxof zxk!s=Hmk|GCA1u!VuhOzl(4&b(rw&QmQixIEW-T^I!OiUj3Kco%KW(ANPy5wm%|Au zYfa}ADnNrJtrkTtMs=pwq|XEWxHRFXhLa{WHtA;UR>P4~Gz@R0dOp?CTvJ$@?Q_i! z{&cV_>~d)m^t_PAW_)>xr`#_-FgLy1 zhMAx)4yZX4w28bgas6E;5gun3$~uZ#ehX>hO$%RPVjT&RnXBNd>#GDL4;?B|22?E7 zIb8+kha@!`y!NduaEBMf15O2J@tW$O3pr5OT(IaEFE7HL&a^fJ*y)SZHk+J&M9rWx zm5-d>KK#oAqt#Ujy{{A{S1;bB&&C(LAfCs?9)_BO2N+x)3k5XKA1Wz!oVA6yv5p#5 zauu=8?P>Y4ma2vHLTK?>!H4Sf-?v)gyaHLY~aG>z$z{<{cX zJHFXMM;>sHzw>rH_5PAJC~H9&@^R*~OUo z#!xf$9^rrXcRfPq)obb*3t95KP243#e?eSLE< zSU+WR3KX?r6BsJ8_oT3#d7fBu@5)A-mDdT&TJB+)#tS#I*wv+;g6ZTY>XAn5#uP$# zDTcE&e`=Mq&f61>q2Q@Gq>tqqI$al5+`knS{2KShpqTZ1IRy!ckz9mmme>V|``l3s z+f(BIf-HTw@r}L2rSoG*IQa#K8S7v*nR>l1q%$|r!9``8-3XV|`4FpDx8Mf(D9Fx6 zM@4zijlHTSTgH8sK68wWymLX+1B1QQR)xWjsw2Q}uM)+LPi6>xt-#dC~ zt-E0GOq0mLrdk6P83C&(vjfX4TXpS4B_#G304Q;7e84dG!?w?iU6K$#WQm*%Njx&I zX#qGTdOl%g5avp%Uz;Zk3#bR$**y?rYlEQ|h%Y^4W+-IYHPE%Ccj>HzM5`gVAjzG( z@-7X{QRq>{a~6~tTD9Fw;(w4r{ErcjTZis5% zcbKBw@Acm9Z{UO2%vT+1i9?xMkmZt>)PS%^+xrtzX_?KEN{)0F zy{-A_&S}T7hvuiPIVK6gBpvLRP;?B|d3U&3?{EjfE(v3xg@GxUVWx!(CLcbvqn9*nc>i0azUW<``)6rBE4s0ijxJ zg;0=-L;T|A>L6?gc@#b2UX7K`;J`4ysb=D<}7<7f^6(>7OmN(!`;?99q=DXJb~uKYUk7Wx1!a;XfrhNO_si zHoS=~_#$63 zjd#f0Q`h}+GYB%fZ>imLN>u_(XrNxshH6nkjjNtmW3&77d$c(=4>YvGqDp>b#VVb-y2_yOy90hX(AiyZG4S~n;e6Yj3WWyC0IW_Nxz zi%u*0jQ(K`NCq1$TQVI^1y^*>IPQ=Fw>qWDc(rD{bg~jfS?J2#q6DhX31_( z2?YIoN3->a5!ygKL=5-0ooLoOFbN<8ZXKgmxI~gOkKpR~;EUpNeMLu_8hWjbtpnrs z@TD7_T=VA;l`6}tx3fhdbrDK(vqa{O!GHv0X~~JX*egOvTMrhTc!z2}jl=0>Ipy$c zZOdv`40tA!Y^2twdxwY><|{&1{lj!HlILu7E|Y`-p=bvVp&Ayo^7C9@!zm;Fg|TiX z+10<;5d~!JPGwr}wr=WS(ML=LvvO|rB-cH6?1%X)Z@g>aLPCb-K1g`OvzHFgtBLxqx<&f+Z{w@q{X78WSuPGXTC z!M}x*J!4w7QeieGdRu^7J9+36h!nZ+EYPc(D6%)K*GkOvJhfqx22*LDNvHQBQ!6Oc zsXtFUD$(`lO1AZveWoN9c$Woi?WDX{TNZvFPk}>^7BWFXQeE`#bEiA3g?hx?l<1f> zotm?nbB-~@2DO8wqDgUJY3o=?~73AE~b{kH|P7>cqL8%ggPyG#8z|Zj#)K z%5lU`Y)6|f?1s@5^e$X>&|GnK!O7XtGhVS0l&L|w)f}hH3=+;1h5dk06|5|?9Nf0Ph({^SM2SdtesA*4xSq<_wDQKk<6$PE&VRtkfNEVTirtsX^2#Z>(+N%^ zR<5&Nyjc*v5-gRQrz4=E2R250=P>yMO`AuoF`A6|EucViua!A`wpQ7A9An!t$)>Se z&f`B2>b=3caMLZR+`{wjq32T-eb$B`;jZJK(Io;6X4=FyK_QLynGBZ1#W)1__H7IP zstq-RdWU@lqDHL+umtH6s4Mt;n_|pGudDhvNMot9JxIDE-?(H-Dd9tFd`5=08?n?N zOM)taXuq=2z1cQnV3j~&b7a*}YN*1|bV=4eeArL{DtY}Ak|wI0gl1#a$X$!W-z?NPQq{HLfXO=T{>_(PzbR(E_6cMhezgf z;BQy~_ol4x({tao|EFd48s{t%345sv9=*nicFSqU(qzwCxU_)Ro{FKUG1k3pvhvNl zU!0_Y*F$Bm3223R-&a|`-SC!pX*Hs@M5P>Pwx3Gww11g$^k8Bu5=K>b(O|N$*$Pp-M z*DP;07M0Tmk%HJqBdsaB4cb3HX1Iorgf@J1_r*=upOJB$4IW?bR||Qpa<6RnzNrSxs7HVK!(UsqEJ-Wa)HhK}{0R%YODJ$KT|j}orJLdCvO|B< zRine!N!3>0z5CX}gyaW69Q0q*S*h{Av2?GM+X2~yb2LN7=+>y0ra#+nJGUqQs~*k< zDBwRMND1+z_P)~q^7!CMmGg7Y@>#Xeua9QUFQ__g>_c^EAp5Dy;O%k0KjQxfwt=l4 z@*FA?KS!3g4h-QU#t0Y)CrTVh- zo2quRe&Igt(Bn`x?l1rH)$9*V2NBK}C9W_7m6OJqLGQop34*6}*}y|wVx2AMCTfP1 zFypt0XD%JXc`)FqQq^$@Rr?MC*4MTI1)`Wjq-aTaj^Y#OD_(qIV_OkR$c|`lAJh6! zSsC29{-ACAjA7Pwa;4w4GhHF0AMgnzHT#VW2edRLhwOS3_Z9DT2&bfX-qv6St)b>? z+MJdM=B&qN^@lfm4%5XE2mv?yrxG^sw_ zWeP9~@fQ*0uNAvzWVHeN;ylX|*Im;dUR9PXKFnZXEcVr=P9Z&k&6`>5eDrh89=@&= zwO}8+S_ZaCs9N7Uyjhzx=mn2coJrY-Z9bx^uXpAV@bNu*v{!M9`Vfq2oaPl(bOdNI zl(zK0#KD^yT@^Q@`C<-vt1evl?Y`5;?gGj;HsFYsLLQ@|?02vdb#Rs%CsQP+7ScG~y|6Kymi+;kPIRBY18i5|9+ z5~rcsIK|f;bJ;L7&j1VGQss}&BP|-PNh!$IH#RXN*|_zT@=64O?@g7J)%g3L(60k& z`PUC;a`ENwfg9?tt9OuD-0!%AGoM&+i#}kuB)p z-x{Z$4no^QxQ#$aX?t4|$J;`2Nf#6Ipe>;}m29N@<==T!0+N{lYxjS8q z{xU##_r4z^dI>U*6d^cF)iQwwXd%8rj-DBP_Z~+f*I1D$0~T?Ri3cyptp(DlM7St; za{G;H`t2s{*@fkPeGk5)mXA~MJ;U;**7!iN^?i*?iVLDYQbTCqy-Ya4X@~40|H3pw z(bWB{)Ip>v@Roj6OT-ewR^?FRP4y2P_3{(0kuH6CQC3i-plk3a1>h~Rr;%5i_vQ&n^sgPyCScNFD{Zp@Bu(RHXVzdh7RF{CB)2*f%KC|-`jty`Yv(2$&R z4Y?OHc~ksj8)dXSX-(^T!JM>F4ay1C(2i~LC4g)@wh+P!!y+@5J>iX%Ypjnk9wvkj z>N_#7kZ;$tCy;h6n8Zn)cC^UbTT|x>rgjiW z)V?fR7NAOgy_}ifVd-wJ%o$@12Ood_oz8r%BwVaLZwi}vA<0)JEj=4-;h*~5RY`7x ztr|n#3@_g3ee!X9Cni7cq74B%>1f?Wqfwv3jXTOrnQ?kNWdFBtLVKJdT`56SZP}AD z+BF&Pu}jiDUrzv?Y>0u*YbJjHH!f+Vwbx~Ri-8}>g!G>9EPi5%kK2Sjw!vpMHE+9m z^D~@+EW>}R!5t=j_WaDn71Nn1<=LTV;2o6IXe}5*p9*Z@buH1bJ^5|iLh~R$q4$f7 zh#|WnAd!BG_6ZSWi>`bV z1&>f+v$P%f1v-}@rV9t z>EAbsT(FM-Gd3++>cH?mI!TrCJ;`f7r%RLtMcTxkZ#wgxu!Ix~9(T6d1?RCCXIEpsK}(M$fgWQt@0+xBgV}+_u!27dE&ZfvPE`)`%Twn zKf^wL%->mY7|ma*!HgOd8#R*pvDBs6|I07{{=>B)YcOdV+<=cDEDU9EtPryKNp!ZE zaHn$`6NI7l8??EYn9GTuJmqXB3mZk>F8s415s)-5H9f6i!5UH<@`+pld|rZ`%9w$hzI?&gZY z@XN=Ccw4(e>)BH_m9O#R{=`DMBx%Z%K;UrApo9yZ1q3AszBG-P?CwXtL?Jf|Mno1V z(8QwEh?{VlK3wa#Z-h1xuMQs8e#6r&S{|T=f)Sgn1{CBhp^&Nc;N zD=)IkzrGG4p#_Fpt~Qu2aqfdjaax$)m9~;?dCLAUleqZ8)!zh3CG1b1>7oGFRFh|W zJ25=GRQkfprEo#w4`vrZ>U6}5vGqSFv?)c`8JF=Mp=oZNOc6}CXB8pH(J^*G)Sq7c z9SJu;6|&R-h1T=svl8XvZky_^}1H)N4Qf8*?g;U_|hb%hr&_}zf>b>MRmww zpxBv>AJ5N>{L43CuX0Py`upbg@dO03|5EqYlTZX_-d2NbBJzZJ#DuSM#^Gg*x;zul zxvG1G<`Pt-5AynBRNByq{8K%*l$&;({K+U$LuD-EN&=eWxj9Rj86(wP zKF(JdL`!{dNEZZ30~ROCO_T*iC6zDKVt&kI`$6Cbj(WiV&6Zr{G1M0)=>)<+FB=yL z4lk`P)VXY2BuibEYB9$Gb0u{|A zR0(+3EWeN5gF&5q%7GO}g!rL;A)&SxllwmKsPy7hb@M$PK(nZs8isK!7Qw7xl>pJ> zr=hD*>Cxb%axIm{pN2HaJx=9=;B=PfEX`q8$D_|sV<7Wywk(@&iKPUGS)`;g0rt>6 zf-DOnelZ`4FlI*8y2k8)rXFj2r&A~;-y!!yYUOIcNoY2G{}z!L&dMnE88gfUb@ zdxXycq5u_3r?-*t)9u?Kgxts#vNwo|w#5LmsH1Z1QM>=0%No+9osl^JvjlX-8sI0+ z82!p4H3u)umMqWXP7E_%qZoKBQjEP!>xdlq$&~uIQ}9l%Taf-s$qZaV3lLM;SBpo z{b;1?3W_^V5yL0wsdJVMLouCvsb-~SCc_VdHUw`3yTAQ5m!E?BQ{)_`YPiWE30#VWEF zb=g6!CUhFm0BI80C7iCt&`J4~nN1-YrMd%wbN@}kUelnwC$r~K9y?#*ZnZqkmY3Xb zv=HXR`TRVn`t^zV{Kj@aN7vOkp3?j%>D@oV0os@#L0SIscC4C#TPj#CfO8=}J=7Wm z0`0EODo`|9Ki>t#=llu~V_!#Q0EIW3Ga_;(UkU1mm=woraqKoqTCMFE4cnuS!_Vff z)M+`%hD7zvx4hWda5o{#(SJI&iOZ-G!v>v#elS^~6(0oI?D54?^Ep_6n3Aqj@E{^> zy3Om2#Mo;AC=ei2FCb4<&B`Z%JpvC5w+x%|on(kn&cD}TM1_nJsW@DcXGTF*yxef1 zD~4;?Tkty8BWMx)-Ko)af!h46OR)Yq&IY@bQgTJb_ za!8*6j@=ESmO3F3-pv00Va7pwJJBXH19D{gzg(+frMUDi%?JRvJ893{+w z$QfGJYcjF)v)6;AjQOMVa96&wIF9w70?a%b0p?|wr$wk?-brooU#!u6U;MpwSZ7;I zR2ERBTw_Fb7*$>7{X~>sy_Y*z_r&XpyU@T&N(&Q>AjNr@F|H{6DKnKIr&RA(PezxqBrIP7SSVE;MrW&=rH;{u>r zMgqOAsI>o3nE*?@wPgV4p}vrJ)h{vJ8oBHofp7X}SdpJA-9pO<5zwLR)+`JK4;9-0 z?}b#Yn_juj(!s7qTuclxzV7kE=&nVXRmSM^21Vt>1p zeFm^7VOC=1ma66>r^aRP!}-A-8cV~D{fsM+--f3#Nnn2!8V(sj{O-9616rh2 zwpuf(UeI5^+1)kZt)ZK?=M>f?8$Vv*CQ+ke`189y=7&wfuY)_pZSB-5NBJEK z82s%YQaICg{bL%im&f72*9+szu&5;y+~C`Ce|fXUN>tE5l6fkeix%yJijwFG|M3G4#8}#vQMxC#6mVYzX)K2PO&OuL_eT zKENh%RmiT+7kt%Z>VWhx`1=>anXHf7KfAO%YaSt7KD~p)Dpi@nxzcQTVHMu2 z<3zkZzDC#n`DGxqHnQW?AF5rO_jXVt1QYiYX{&70Qll0pSlb5YbD|xbES#NnRSc*VrQ z7`&J31tZ}xSK0onpn+z>y~Kxyf-$`c6t?BkhP~`Iyl%hT4(7o#RTZru zpUh=JZ?yXd0ZH>m?ct*KkMD{Vvh<|r2FaEiwNbXFk4*`Gcaa%NmlICXBH+%jAd{Uf6a8R|=P+jz z1N@?XT(E+h8bccH2kP`tUenP|2Pl#62s0g)K|+k~Hv~FwssHL<@-b<@A*ek^Jfv_N z8J#>q=3FIT!^b)GLsaIDRdzY(TxHl9V*^;kfmu}se(E1LsjQtW8Cp_fRl_g**BVc> zn0YKO9m8l5MMlK|`N`+(dGZ%66-=|I8Wn*|6#m8E7w)?ZQVBkT(|36#X^$HIYq~iZ zjKY_e=SAk0uXVFcIplotFg`SHHheYCwZBa|c74_o?xBvF!;3zJsbCYr>wjuI=ucL2 z{^h10Iee?^487(_IrX)C9@i8*!U~D4(EQRdY7N$DnqM-mSk2&)eWpKzsW(J&-}N$_ zoL?K|{P!@N(ap$L+jpnl*UHoFcUr}%ykKpwa^{4{!7&FDrIUJFs*Yyegs-Y280GfrvKUQuhPb96f1rvEG-F-63QjO>mVUeKmNfXFuTOm(XTyLr4 zG>!IF+yyXDkhPuAcldlWRds!+hg@M+V{*{Dk7t^`jXY3(C4#OJ|ppDAW^l{lB zw;~WcAb)PB;7-Vsxhhq&b1mL~4wZw-;VT;5x%Dqk`^{gS(5gJx7#nUs%f3@~KWX(D zLlS13kg&BlcJE7X!#_axpMR=#k09WN(Xf8@(juA4t}J*AD_XI67T{Tt!sGZd&npwu z1#S9kh=Qg(feY`%L(9+JOBgI5WG(=DBqvZwL#L%eS z7roN7KM73+<&`%Ot0)GrhZk=gB%Get*4h{!$|IgedTsu|2^6B5HONy6V_57dh0+(t zX1g8%#fRn~TLI(}L2R;=>5{SKhbno+NuMCgCS6dYif&p6Vmt5tj`nE2SI`w05Y~36 zF_p%Pfx)h9#0j8=@0vn`StIIK!o0mHd46ebp=+e%;Cl_J{@Rr};8 z56Jdk=SZKB`#BdFi|-;?AyvXbRL^RO+6{33Xw#)#TL2SLrdC1ODaox?$1hYgzwc?!SzwQ*s3OS^TxGXru9bL01d|JEHLY&oMInOmjX0UQ9e`Nns)RBBm9N zJT|POwkEx0X%eq>)l1pb7!=^-TXCnh5Ba6$J0N_?v~+*;=5?$)#yYG?NIfjY3^U@Q z>WkHx9rR2Thj@-aSoW$QpoUyF)msIA;V2W=8tq2?m~FwjnA6LIZH$g5G(-4Brcm0Z zU0u%jRw3^$1SxBXbOsdLULp&GZBQO9%<-n-HauQ+N>10GO$noG5EyEO2n~gnSCUH5%y&thiK`Tm$a(l#sas>K+xuu zv@zW05XT(`14E`deH!_c^?oR`DC521L~MOmL*Q$+|1%20CLBEBvKYNTRFQK?1=b~uCKQWKO?J7Y`Dp!tD4z`42`5X9 z?3MTV+-@Fr+Nb^DHEu9zE!yB-vKAL)` zIv>O9P0SHrroWz=qSsPp`tMB(K9g3+K_Mc+8mdR3!^8PxGbQ@$fn!{TA>;5L_5?0l zW4$Bejt-Y|QC%ABoU9hgMBarq*Ojq0?0vVa*+C7nCJ#IkB>vo1-ZB2qjkYY*IW*0K z0g99q0}E$@7OJVt)(^%OA&5R31z_tU(@o5r@^vP_HyHHC*B>H;UxJadTG~gUhk(I~ z4Tl5dUco@u{kD0;8Sncv+eappc!LIw68xLveie1s^1N{UVB?r*th~=*6nE#pwLL`K9p};<)XuSpX8(Xw3_qRUms=bIIxJ8|Bvc|0r=+Mr8b@7q?Xlk(#=CI z+FC_1jH~6E1^cKKJjCetT5r8UUB~b>IF{COw``5Xpo7bCZT|B85r4A?3m?jzqIL>xPUl(PYA)NiiidVdqe>WgNSi3^}4 zL(ihDV#REd1%nXZ_Y}tN<4CM@n0uSZn)=rDx7~K_j$>qYWPrT1b`lmi5>m)a% z(0rmA@E=c)$)o0bYb@Y#8!YzpDER6DDKS60q1!$^7vBk#iHb2Tr4t8bfpd0!W?@9h zC@Tz~ws0!TEW_(LfJ-1etpL1bZ}LmSIxZhanWKGo{YtYTd_oACHbB3eSc58c;FdN= zTz4w(-Ez>(DjI=DZvY1YV9z=muJQ!Xm7Hv)QWlzzYOl^od?WQ?ld~r! zdZv-*t;Z`YjeU!{UI1<7mND-y=o9rT*kpR3N68>)mo{QpspQUpXDr&h>$)5!cp1jh zjDJ=XbG>*G&ZM;S{r*bS2(3&mx$PgMK|WijRpR@kXZt^py>6lz1=5h3c19}rfdx(S z8p9LDs`CwIXlAF<1)(c1zU#Cbrq^QjA~N+qP^~yNt8{-KKCg(HeYblO6Az3z4}=@2 z@S;UA_Z2%mh@_>{X~-rB^pE$1i!^X4+gTPY zmnN|q?na3aA0-VPD6}b`;Uy^Z$GiNDu)L?|u&_*#KfdHAyGh+LHqkmltU4Ki>V(I6 zV%~?iz|*1k&yq42`oxdVKKHXNWA^{{^%WX4yaF9sxnR0TkLXVi44H_a(Yc3t-R_oP z_tMXna(fO(r{ z3}4F@L%;8FQUrMp7{YnmLD2zUcD1G;a&bbZDWnk0Lej* zu!blC*$#H#=t@_}M2QctJ!P)C`aqEU*+$;xzX7G5%E=~J(wcl$q2t2|-EuN8Y8oRh zR#5a_2Y{;BF!cm>KC8lpOhx_WDx0`B1|G~#K8#Qv>e9~_MgPlAb^}>T?V5l-`Zuho z*}x!Y@A!IiNn=gz66Ui)Ku2&Y=9DBReqv64vT)cDf=$gknjKc3yv?)zI6FxxhERTe z$|)c3poVX|W;4Cg?oG>I#^4jSoaoq)nr!gHI^Gjo@(3Sdcf)K-dH)%PXwXU(v$S}`w>GR^y?em z=rp7AjMg=5xGa7xm&|W-^206)Ki7cd*u}!WF7jw%#9_vC)3-8mYTm<+KGX063Jc+Z zmtKf8rQu!SoQ91f-CACq1x9BsAnTL>%q6~G)=xrc+bV_+G90UKM6j8SA ztP6{mr&CcuGyP_hB*+z0{$CKgdEhO>=un1#wg=zJUoT_?P``lsf9K<3vKUsk6e=Qd z@|rN+()j?>*8i_-wWO<7Ub*sDmnr_jyas{g_!m6Q>O3qy`r20NaMx~p356X!z!yuM zv``(<8gUZVEd{8p1%=4wzsY(}vcjhB_P71F-nR<>1l-o1odon~CdZ9D`6Z%@t(=6~ zH?>`@{%rKwm}A=<2qZQAj`iop-Z_!hP#=a_UW!jx zEc<}Zd*zurd(G1GyJ$H5KAKm`bWcBYv1we(gAuVGC&AqgMk?e0RY0o09MU44h+}Ci zE#4rLgKci=0s=nEc&CnL)RZJzR zR&A$du`Lp4gxJ|j7pB5&w8*W|WDMbHL0i&OsxCRtlp@|stIYE&5K;b_6-h$HaIv2$ zefhc5HLCSZD!&w8Osx+&)tgiRw5U!WRF92F;)KMLfO$>-3ti97p_2wp z)7?>ThB4ONLqdaF>tR9!T^%gLJiZRsComNDbY1==AeX**b39K)dIH&pSw_ z4WTo!`aGeqKE;WK6LPCg%eJ9{iAl%*xCkCPL8b=}u}?M(C#5=xVGKuxcFLcB1e>oQ zUE5pqn{0r%-(M~B7CA7eB&1R0V43ttg+FEDsP^SzHMEI@gQhZ@djf>d9;xd57$|a= zjBjHf?UePfZQ7JctzzF7!*Wtw$foY&OpY6tVYNVN2^5IDVcx$9-|S) zFqY@BHy=!&e8-_D#;L_+D?g)v)rkSDTAp)042r!v)@bCzjma~j71`x;2$Qb3ATPM#TN?SuH)SeuPeCxxQ5WMI;)nfP=q;4h^+X`)YLP8kzQ6{b%e zk+9|!6?rNw)6kLXWImS&WX9Od2ufO`0KaG0y;ry42lN2XE5k6yDDBsMOXlVgY(U*N z4;s&WD8P|E{17bd9Y(wRFoUJ--q8G3zo%w+x_?JFZwmo=#>pYj^MUu=J1f+eniv!Z z?E)+awgi4oAiD@j$<;vdqfH__GIm?&9J3(%150+)lotqV-y-8c8Y2dj7FS5EvPILw zE9>kKB+%W5^?DLJhdrCS4V$!-c-I@%_X@(5*gfGQksC{PP;NXwDtle0@L%Fv;6_iI z`zfI}47_$tr?!K&bg=q8y~7W?5dq!P2hsK>&O^6tH!6UTIM8@Kz1wi6|6UgtZ0@!V ztC&Sm^SrZ=K!io~%%UFLYG^{QEfzc%V$SqjRAfS1gN^_K4upZ8>Kpb|UWF=7z zirNHwsJd47TDh>XVE8n1_nW2-zxhCm1Yu(o?9i*BJfBr0kmyll&Bhzq)FCk6z=l~~ z!5@^HRIVnD=PRi5H*K`z{KnXr(?~I4HgHlz3t?v>rYw;Q_$60h1P49AO4={)elMP1S{IbP zNvsgRlo}bct|!xxw$n4c7!Ih6apN8{;J70p`65NFPbpzUU^{djmyXN+7DdPe!^Cvd z6$DsD@mr~Wt*wz0eRHl?dBuzR!4#N~+K%gr=B@uSVGb$*ZDW(y1m&hG;A%sef=C`; z+uEw2x@o2@_j-lqtwskh2^QchDm4}u+-yz5*M@)WAaaP%sh<#(zjSqkNf(6L4)x)1 z9$0zmqos_T69$3khDni4YtlDk$yA3{qQ*OaX3e`9yk!awc0w>?qBefHmX2SU zVG|hf9FU0f4KjOdjb2qz%|$&3^e3JP&?SlPgE5d$pod zS`yC!?x3bI9r9w?Z|BCV>OLwJQ;S)LAv|r%CubXY6*jT20n)0D&ng_YW^dmFvhc=Q zmc0d8G`~S^k7STb#5Ezp&DXZ)wibXIGt~ z%Hr=`5@(c39l2BYkk$i0QD>GI3j4`y4Rb+}Bg~kryb-)D8EvBitsv2OvYo3nfBlgv zC*3KPEcF+bT+ZwuY6RXxIi6~Kc#9#0r#mS|CGwsiNj3MS7x-p1fUt2kpP;O`sp1Ab zm1;+;PxXaWEy_LVnsIMYy@ro{CN|T&L3&+&azfD{wWN>F`r2SAf6?*MQiD+kJcomM*ir21SlGO$xU{nPA+U1wTFhI87%Wz-SgxZi|W1TLKLK*Bn;E;o*B zUZ2)#`QtiarZsMR6Ub)5rGKA>+K~*p(*W}1`7(0SroS%JLJkw0R*k#fBv%Bni^`&j^T&MIIMDKJHjzo?wJd z$G5^w=Hd8#Hu*Z>XaGmc0$Fd(sY@T5$E~~awVMBvmWaV4GW~12=xQr8s{ADDi^Cb* zxk0;UM$p(NLLoR?guZnKJBAC`I4na_a~2Eyyv4hE)zWmVRsdWi#^7JKd31JI8+H@J z|7+$oO+4mbuN6ud!JV_xZE?!oqpBHhz$awyorZ=S1W|a;$p(Yb+1BYTrBd4*7 zeGu@Z9}L)-9m2C$RUxCwRO(ZB53hmyjcoNI zGd7v7oekYOR*DkrZ&AJ6p>2iw<18<^}-rA|CJ-r4%ReM8F+F58l=P8g-Q)-{B?A(Ey}gZY5ge-`B^H7L%Ye?1Y8fwWt7Tgdqp0UjOv+tO+kM zL{0#|tjnX1rdAH9OpZx>j&JdC@`e%;iyj*MFFNHbMBCel&zLpaaU7y%m8Mc1m@(kX z|NX>22m;Nd1EbECJhknNlKT`0H=HSKzP=B(>i3i3LwFXmmJUyzM!?x9ear>r@AhBm zUL4^*K6_1e-QUpifv$fh*X2smeb(Wx{qva2V*bfSh`OlQc^=Wc8fH4U#T~L*-Iqv= zKVcir05Z$j+@DH9~bL!gt@=|7I_!&yt3d2>=ruefHA*|7xfmq8r^&*IazY_?mE zeKlO!|&*;h1qXGvmE6VuH@x5 z6Q87cz*>)`xMO;^;9S~N+$an5z~Zi4>6K)Nx@2$2E80Sm7 zAxU_$=AT@T6c_AMf%zmvNe`&rPkY|2n+9di(oAlG4|R!EyvhPYJKN4)k(-|Ek2R5V zUKQ^6`JFqbJ_uRp+Qq(Q_Y7E}K$nIC6DmsXfeuIQzqDuIuZd-KFqON3j@U%+>wE>@ z^}g130XhS5s~RfY;k)VAWcMg+BaVX-+sk@C=il#n?_hT!t!L3%Ns(kvu5-*ouSj63 zIz(A&P42Kx8+xUpL|Se_lxhQM9M9U0qoZH^4v4L(6&%#l*5wZwKl~6$t@_WK3V73< zy`GkDlqO3ho+M5DP5s;RtX0H2_j21(SVu)QZR#`*N%bF9y>kBlnpb{-o_1(N021<; z`P-Zq2)G(-4Q$@qm@WDPUn0W?+Dkuy(-o(RMf@#qoQQp`jQ7@feb_MqV`lunJUg}) z;GGSPAET()3@@RwMZU@sQ!e+MLR8>4# zeiPHZb?+6-CBES&ns9a{YceLb@$@! z+d?-|h<#Q0g_0k5sr}WUz6^C@ZM*o39ChW$;2WVKrfhcI-?KHF&sNv>^`QgITH35Z zE4b2sLSC@WP)&*a1b?|T9!0bbP)r~DQq|QbPQ*sVUjmE|@YDRODISsn;u#R4*v}#K zB`jbMH?QPCyKUM^bbuwQ4!zsw^vG_+8pk9O2efy`8t#S5iz%BFNSe6XTu#60lenq96 z3o>h!H+@1pOmeq_|EHAe*5dBq_ZsRedINK9(WfPvNnJxqGT@HMZ&Av+N+^RtlU24k zV3{bq6U|lrJ8*fme-iAaBMpLQ+nwD8R3ELD*)fpi9$F-zIxRX*z25f5EraH9YGMkr z+f|{VRmCB&F#_izqjD+tDA<^rHsi+Us4Dt5uT$2T0w2Yl;!eEJwo|y*byO~8rEzt`81&aCu`y66iZ$5@7EbxpioXXk z0=tn#{=gcr)M;Ig#oEGu=4^+E*`U-d&x zY*^caTiX+vzliLFw`~GPnSSIm9t$U8kbM5Dk&Z?E=y@bOzSl$AshPW!DxolNWo<14 zzl`{Lcpa;JDfrtzWAAc^xix4PKEV}E7G4y_7#Dm-X&*D))!iIduWxtrXeR>#WW&FY z62QxA%od;MvGu|`VDCBLHaD7UdQ**ONmRl)h&9a43vbYit2(gsb)?M~PT4>2K^*#c zba;%$Q3IQcSTwS#1g@0&F%viKURLu6qhl5TQxqj^m+=wQng*}(>N|N`3WvKoRbI(%W@4XUTY zf~C?I8fpw=Cac9$We(H&i0v=VtI(md%zh;6pgT3!3KenzsLNjV+dIG1mQw?at|-$3 zxiz;-x`y4o4gs+PpzV1(I5->UdO8vam>aTpO@;L{XDGWPXZi7)ifqa((FVNOji&8y zA*f7L#9PL?I#Z;W3BR4Hc&>SM?^vpZO~hixVd5dOH$*5GPV%t?H#i<^9SDK%;z3uc zfkb}4|3r2ZKeY=>wdULp5lONDTgG}V?l!7s0@bC z5Wxe)GrW^~FQP03x1S>fI!I6KwyW9Fb*pC*=Ma7k{X~Po*F-!tn;xeSits$kjmX9Q;$ z%8;;nWMqZZ?ki@+uD?$?d)O8sIi^W`bRA19dOW~>GR+-w$Q5&mPf^hunEFv1@WGHF zfyj^zfAtR(EmDZgKEB7;o7#9wJqJZS)b^GI*V8#32OqV}C=ly|ibKDkzTmGW3;9#| zo55KzHN#FK1HG|eBV(z=mC`nrqn@GT15=4TkwU($50@~-qutjGdOC7^TQsHN-KYj^ zGrJXaNOd5YeXbs^zXCEw+UP+qb@Hq%+l4A3xLB3 zzk}_W(GIjaz|$MlyN#2~D*4{Glh*kCPY^1I&un#~_*~)1XgDK7K zztx*LNIaOyzt&**!t$nH4eO*p)R2({Y&_}9Mp>ix?wuxuKk?T9J5ayGY3 zDTK(hWD|CJJYB8@Xf~X(UlFZ_>y|4ZDTw1>j>NJbuCq)as0o)s4HD!}3h!-sAM-hQ zU7_8_w^I!_x{rp37MVR*yKCP80l+olw6ljCJ zkTNa?8y>~044y0`Pl9KZBB)U0LuTs4lu=^o7s0C823qpBM0Jop_0mww8Xi-V*{3YG zCDPf&_W%L83NzE@6#s)p|8X}Z_2MYpR-}Ei6Jx%vYYl>T^7Mo0&?%seuB^j;r+;UwoNeHEpRhq`zP*sgh|QQI5!)1`QdN26dG{Q zsr^BZz?1rJN|%8#-)sBW`85Vt!ot)=v$;m2X4UF#-Jo&5-0)%48GFVkpl>5)2FsXLtp)JgFD zqKknv`n6-)-FuQN_E?EM385DMvu`S+{Pmz!daQ*xYxxA_1W`Ytl`$I$+AckyAFzQ- zG8OHIz(3EwAm_s}_lIhGVLYuY{8e=;S ze3@wnmM_t6NuqFK?U!CS^Y#Gi_G<>#1oBVN>vsnw1&QJjP-*-!>P9dk_V%{FM5ISD zwH%rcc3Ry0RR z0PM}}nMW}tO$)eMoSSi#1M%yE$=L{n+6|4F)N8*v0tr(N$>f1u4r9r5H;3LFLpN*c z85zcqg|WfN!(tcW6BIf}sEckmL!;d@WX$j?4_V0#I7>yP?r}*)e8j4bnToo~!u+NC6J)>@hbo_0|W-%U0$$Zy)7U?^Hlp~I*u9jo^*N23lQZsc^$ zUB620Fqx!||I=)E_`;v`DIPn}(}H`m>+NFem2t1xG1;`lfhZ!BXJR06n zmu&|P&lz-BtiU2D#%Yw$-7V2vXazXeC4K&$`chEOIGp)#qR@VLy6>P7gr;~R#o|x# zt!t>U^)7lqG$6qtqO_$&3>P71+6oH2MmV<22t>FYFMyW5GKdQe9iJs~_w6ozlcwrI zzk2fD@5Lv0gyipHKR#?d>g7gm5JxBwwSCKIlf39iOp9cJ&Oem>=9bmo{Gft!u(fO$ z3VU!IuBFNYy1r$@TB!tB_NW)F0gi@3R3dy*P_s8no~gI{=Yx(O+I==nTu2bIkMw10 ztzADe9$Q~sLznSW4Kqcjg=a};JCD*an4~G#qxl*q#bdquJV47Q0OXY&E+|fRt^!1o z-;{E-z=77KCz6R&(k~Wo%Y!jv01$_w;=Te`Ez)w`E(qp~HY{Q5iCl~CihP^;<0B-~ z53q{~;MUfDGhApxZkn9&^n$1gdhHaq@9>Ued^z1lwh_+9nZuF%{>01trKDi(D9V{C z)uj_~=i-nE@`tj)q{)tEQE?24ttK|a zHgUnkOy*(}YL=xV+_`;z1L|IyBOoty+VI{Al_y+uTnlwJ1y65*Y7cJCyu;J#rTV-k zGRFC6UTar!QbE|lEdYZ!;5@mvH4nU$@>w-f`G$PtEoUY0^pdVnV;lxbXqiX24+d`1 z4)QQJR`pXCl}Xpu19^?rq5C%GhQ&=@r7C|ATL4;fa_dx~yly9tr+zkO<=^U9Zu^^w z8xItKy{%T1=cKm_-bJGL?wCZEg|-7h@6dRsW|95t;jD^eE5HlHevv|cPiTe0jdn_p zBF~D^Z&YZ-njrZUXJKS7)7msZi}77^qFC-ki(Aq?p>;dpRgVU^Ad81cGZ*xk)d1^) zwcTI=?=FbZ&li;7g_mC_Jt@kl`DQ=rXZoUQxLSyd zf?!Y7bM3$GZzT2gjswoS^_q1~*?RxyUI6{oluDV)Q&;y@K6t{?C`Lb2qB73qFLR85 zFjL8^_(q28c0bhE(?Ur?zctFCiqICCgDCCF5+a{?dOpVk~W*1Xi0-C4r>oc=jf~Wt_ z4#jPHJ;!r;Q_{<8X9~)`tpE9*7*V#(^*0vd9{qP5d6$2W(77D}091VA{t`BoCwPC&|hDqJ*aw0Uex}tp-w- z2BY1TdZwFQfke;)D}^+L&zWEK?em?^P{dd!14XVPjDFuXPKg8CK41|@Yox!9yA7=* zmG*@!nY#S(r-RmE4)81z`2(O{_!nx^;eqEQ&Wai|CN18HgiC9 zt^zOuzNemg5PP-a;;j3|RSbB_d7=n3e|c{3mV;-fX5jcdyvavDPh1tmbFfhEr+CZt zhcy~)vE`x7eFhFzITsm7DsWB6O#k83?09JiSao9lNA;^2 zkAZp8-tvE=9Iux`I2DJjgu>#0Z(6N=U8wIBwxIO%nbLBFS+{?@wz7kp@|uC_43~2u zRQIbOiiUX8#k!M;l>>rD`S0}#C>D&ou>?eBBf(xrhlK#Mn`EExh5qgpV2a&0+m`40 zeMP&h1`B8$0MFECfI*|7oeV^ZR-11HO@^&=C zP>Gut{Nd)7Cb+NFbvf{^%0Zx3xQga>H}M>MNN4#K!4IFGsN_tROR9O#np~8zLXMbA z%t|tot)(4XYzCu*)7-^;RDa6V#DyE`Gg7dW(_fS+{?@QiP=}Hm&Wo8F&mu%PaW<*H zM8ggn`_0-C*|SU%WIkab=Lei-44lQ4|MS{%_McqIDqvyL3rHsRR-m!#Fj|jJh0bSh zxUCVd%f+*!$9<&eRJLfc4ZJL$ikHC7$3*BPWn{T!46FU&6B|`)zSUoPnBqsro<9K z1M>Fi;T-T;NgZ<0hoX%Acn2t4ICKDVoecSexqv$_GwYqyHhJdUi9 zlcI=^U_t}lTLTqO5DnQZhdU1h4G6bn(6sl}gsOdc1h^zwDM-G>JLg$5Gz3-c-)zx* z0t&UG`K$Sv1wpK@==CA;)(oag!N3XK`UlsnyLl@Aq9pB$v~!5DA^P!8T#=jV_s8~d zJv-`JQUTT8LO$1~J53I-r&6_sY zn`3a>;At}=<{kE0KKw|dA;|L}Iri`Rx2_`9t0}Z3yD(gA_94=*j`rFSAIQDd%uh)d z_78etubprQvDub4D^d9V2f2kky5*Q5)$1RL^%LxrF)`b?3_B(7jBAhBbI^$DKS_(a zac4|Hnh6iHSWYP-}9vqp3 z$D9~Ax{oWwFzR1jns~+TW`>c}m7+348BRia{GI&(R>^0jYsE3_Wr3fCaI7d%vRbCy zWC2M5cpF;!S5Y_86Te9+hD-OxJ0$|^kwW_96gH?zh6;+*7X%dTkvb>?Px3^%GP%O` zR9jhvegI*!$^Bf58Es7n=q+)vCA4SYE2kjhP_FJr8ct#3gZ)vdi3=dG^8~^X`DFYV z*LTrJ>KJ|woXZ3e)ZlKybQCCpzN+XEhwkg}Vq2L)B%z!1F+09Y7rd%3g`TPWms@zb z{X)v@{#ev#74ENvFSR5THIRVv=ppE<`dKQWK(dqph(84)a4vgUV&twpc0QsiDt03U zVduyd<;=HU+5@BvzlU(%IJETq2#!tOSanQhwn~MffY1k^V(^IF!(%r<=8OIl*2sit zM>^t=iB}hqI)N*rRi3RRt_%wBg>UQvrA1n2=x#PU^`krv7cHSlT0liG>WDx{6As4a zyw@`6PVNoZzcS$fQbEPf*I8+n*HT@X>n@ED)Y>AGkuHi6QIL_%tD;uLy>Z%5A;Wjz78j?rbh8!#UA~B8G|feFHkqVqLe3N5BwRDakJn_6OpnYM$eYiK#&$0L|=Qo zyry&v`BzK@l@rC2uo|nBA6&8#P>Vj`GjV?z!*?sD_j$|t|KN9GtfIsbW*NaIuhb-? zFqd%uJ9+{wr-{Xq;q$!}Rd0i70!^(wCAHF3uoia74M*y~i>Co)CU6#qVz+X~!G z?E(oAMJk6;5Y&6HEQiqfy)f`4F&*YA>4~W6F%z!}^ik8GQ;!20{~MVx$#DaRpp1cy z*3{p+&xHLY=`#GL(1$1#VCcTC3rG*@_JCPcCEk1_knHLK`~qfv5K@N@KSX`DgzPBv zmP4K?#qFS#H{+RScW;2Ggn($8CrnFYhwV zSf2>jK3idni##D^;-K@NduFaUYGf&m)5(Nl^0mR`O+=gfrxB`` zk&)JX$zk;RWSiOfSg*viT&Q)=N=|v%Gc0>9D`q`a+6u*_zXO)$11)YAX zeU;XUE8^UCB8Lv!BtqlF9pIx+VADd{IOu(3;Y5wAIZcHdj-14>wuVu(6y5Y~rrM*-R4ibVu5#B=B*8zxdyoU-ZZpEMp;lp;OSO<#H(mCJGv6D4BhAKF zU&JXkf(!U~pbA7n)X(*9cadj3d8>vVdS8e`T;3#h&q)ds!oNn;XZ#mE_5qIXg^{i= zOsuO(;f0eDALfZLVa|fW6;OO+@W)#QpU8nmQixSCW3=4;URUVucp!~0mM#_28ZIZJ zrUgc&3@X#?a}NXR;sKp4Jh=-fX-P@YN7!}&twGqjeYSRhLU=k2BlG#E1bzBwC1M@{ z^jyqvpA`KX#R#RS9!e{95iaj*+t7JvFpK6@c?M|yXn%*-rfPi8wW)FBZZS4hoG86?Y@oLkX*rUD2Az~(HQ(ou!2 zKaU=HJq8n*!hU@ukbJ?ML1VC9I@0s~Et&yk4FL*EnQAu`q!%@OsljhoDUqs)S_{*8 zDkBPlq#Lb+T=d`lkIs`3-`PlLqWNyN44irh@?PH)SZ`I*BJ@nrX2N2Tpn@_r-pqg* zbFi+Y13J~5$i>%ndtImJp}%OETeL`}oA0=-7_Z|HBhRQt7)|U0!EwADmHhsM z$Oa=KF~Sz`Kz^T;m9!Wcow!;rfBE1N;5E=P5E)8r5z&BzeANgdns$vc;mjl!or9BZ zMS}tFH0UeTpA<=$bh*!2v(Ta8J<^1B4qzXc#dJKrMcFq`XYt;Nq#j@nO{1`tVr-~g zeGLO6p2|aaT_wXvSJvLo%ubF`v?J4|!y7W(58lELKqK(CGD$~^GRrQ*GFM~6w%38Qb zCSFE7YGp`vYvA+OXLd=Q@yIsLXC`U%!}*A_%AM_}-?Q*pSt(NeaS9&V%_zG{5A&-0 z?DI?tl6RJ;plIXO;7&NL^GePmF$4l8^Q@I)aCA+v6c1IP9^_$XovnSDQ+<@ph|U*^ zw;CFY?Gd{ra+A>lagV6zo;#^X(AO3wMV=E-_7kyG5-%#73KM{2YaUb1iA*G#+;Rvy zwXI6`2d_@=`L#ky2F|Q^(`Y|EvBugsHqeb)AE<}G$`Jsq(J7`YooWvS9=BWKPW>L;L#9k z{-R%`RrAt2{CJn3;E=GLJe(~d-6!v35xYOUH^N@X;SSg=W*AOa+aw4qNNa7IpCVxn z>g0_0njujv*1$0jy*wlT6tmRDJ3;=G6^6Z#`M_8t?UR=Iv7F`#k$B}v+L)=S8qmX> z%1@A}1e5PMN&C!bkX8$)ITVne#@WV}Y{u+2!-$0nFd5``th?Pf#s(}FRyV&?K(NHt z{d);X`5MXk=?B!?I;#9inGW34#k_|hsU1G`Ghm#QE`r!oE26M{z z`ue*uYF;=&HqZhnuv|B0O%lw`e~5dSo&4rB)-sj6;Dp*!=^+7_xjqSQhhs8zV z;=wWzkytR7N~S9dEbv)b7+!3(@%aK}>CPQa3gAm%QTNe8qsGYI^6S$1YP;;e!4MpE zD}J~ZwLL4csqvdXtTV2wa9$gYfacRh+Dj;N>IO}MQ|@riqZKP7pMUR{q=y5QJ6qMv z5|vS2%vg05!4mc{k2Ycj40soXtK=u*h`+Sve4wo4=W%wqne173k#rWujhVg`((BUo zq0>+XDfeZqBDCyr7Icrt_2EZ>$0hYva`T|?$E!TEa%MfKW!L1ww0R{Z3{8L^QL|t8 zc-v0+>qiaCB}2!vHBSUor(Jpx+Sl5h-v07GGdR&-W$puLvdfTL$1fUE-(EiN(fPx@ zh1wMRclrg!QlB=99o+W~$owOlVaR>A7ad9$2@x`xs#hIU?X=V9#=z{sP~?Q} z7AAmDiZjIM84SY}Y780BkIbW<8g19#!5h;jL1;iRIX3so8RmUgc$8gV6Or#TkHgy>Blvb?du zW#^2hu25*qjBJcX*(t%%i@vrnImzee+Mtk3y&nkhNUH#nMla zTK03vdi!TTZ+eK^d&5P#P>5d!h3j)m-7BPDSHEFQZv$%IlyKGQJ7TpX^^Y_MyyUsM z{j%LijH)O|dX z(^$R4gGU{A7K3V*6bC|jdu1<#NVa}1<+WRy?zeW>Us~SWrU)EtY(^K6v+|WK%|nL| zY5%pesaoUWe5U43^p9-}(5$BX8o_gq;^*V#UVPH$yok_2%&pUp1^X5SYQJP{nU8{O~nFqz&T+(ClwPGJjR4&i{?Df=HnkPHt91|C)xiDb!cWz$C`d-N zW#tlpG`-$8B{e4wiO5y)s%kkYJ+s6>0-18HiMPk`e3+L=wq#$?AI6X5YzX>F4rv;EGl6r#ix2Ur+?2 z9oHC}{W*rh&^m(q!g>xr?sWi@xTuuHRex#Wg>gsn$9zz33n^0B>8CDacTf@3Kj1*w9J`}wWw{i}28*rc@Z#rXHVjIW|Q>Qe;7{^l)?!6>PW}A%@J33x7 zBg7e5@I%)qRcpCi^sMq8-LY)^>*>B{ zV+*99J=m3EBvj zc)`G%pa8Q!fYVc(adVEbEvw55w$B)KzR^JQ9PQ*#i7 z<=u6KD`4ILW2!|hbIW<1?4=O<+a)S7>MLbZqAu3rZhX-D;G)?b+^ME^%S}|NU^p-4 zR3AwgC<+)6N@wcv@y8JE+lC zJem6H`beO^N5A&l$Qr?&gNZF0g!M*Wo^O)gKmEpxfN2bl;z!}zQ!yr})R%tDs)RCr za2^)Yi;&dDA7n2urQ3w#`DN&(%DReC-`^4K@JKK&{?D++pxgnFVKaR2J1y}#p!hHP zBx4hp_IqS0cE*3~ynZB3x}sEqk^aNgWTGg`0~oQXuz+1QhGq88Y;m?BcU5!bH-~Af z%5*pj!Z)sUx#{x`v>yd<1kHtIvRgQc;$Ro)`bT9Vo*%5Pd z>uLH$X@>G6EnS=dbFt?pf7F93mB4BH^_Hw*md@Qrq&fxVneX3Bv19~|e$gQx#p?_VH@ zjJ8UluDg?Ic`Fsp4lVnJ?{~`^UxJ653+*e$nb`-Ww;BVGHo`wyx~;d8Dg6q7ut&N~*i=MY7p z{rj7|fzg0DF@Jet-Ys!s@FllJt+Dx9>(q0e#qNAc0lPONDXrEo6N5&K7h-cmYa;Yd zPunmKb~Lin3(bI=V0k8YnHdO-bc*dB$XD9`WJIqvQD^3X83+j-Uamsa+X$UHRW!?% za;iMQHRTBwe}T@W11Uj(@3M`hkm#d$1puWsQD+ah;u&9^v9DWs(&OO^Irq(!Lp$rj zGBGFF@(Nw4rdDqH#_&F3&AJ#49dj9*b*!jmu|*z>4r(fMZZ@NOLnFc}@_UJv3N-*A zKpA$tai4PG5Gjajk3Vsd%XFg};<;w4ZcNxk`3_8mE>BZTz70dn-}81c>pK;BlHdRY zjz0e(MFz|`gJ1ZPyDF!l`kDqA%X5b$+foP1K}+s|p0s3N|FSmNZwj=gr*VGO-yitZ zyz6w{K|1ZT#0#8N47MC}kHKE#WIe*(Be^u{aS1DQD(X} zd**GN;u%#;T0q}$2YuLh^TOH`1as(!QpMH+>%y{Msiv zM{I|G`D@(qsx7FCD|r2Aon6V11*XU+nD=37s(@B;2p|qX;C$Vvrm#eYQ~va~?e7-H z0@nylp7cBtML6i^2IsOPRTEhbZZ|91HJH7LM8&i7hQ2}dRnmS-L4NZ1%=_xfDbFdy zgL2bYDIhhQ{B8gpgFO ztJq<&*8cpmH)qs_5gCrn~uRO@Y5%AjHQSwR^obuxsyx{^v1yCw5mS@vc-o*5WG;fbvNv77@*H{#33n($ADxO8fM}rLkCRi% zKPv}d)DE7}?J-ne&ES$MJe1&U>0urlR_%cnl;vQVFJs@x&n zl)LgOTuucn?EibxUFZSm?3S29V~c0#BTb(PtjEItQTJkyH3`?2T=GuFD+r>l!f7f0 zK8=KhgK;ilPWIg^P?n8NsWQ9KSOGsA4#-ru3IH)c&cD3oHDuNuUelB!NBDPyJjUxg zk1icBu)}uf?M9mrHnbeTJeg1!NCdSAVT+lzEJw1FnhvofufN#j8y~LtGKbNs>>yeS znn=ZD{bWn=pz5CTp8o29Kn z=Eqrd3f(Y2pq=LtRPX=RSn+6LPq^1b?F%5fD_?|gRbyJW0yi-Y+fD~fWVJ1z{sANx zp*j{wAiIOe(_nDYvNrg3zTg|ku`h>#aMrWs3Voz0Xmx~hJ1^5Sr))TSUQFn$$<08Y zSWCO#9F(-oB#ws8GySGOm@Z|Uio{RZ4tpz{BF~xTEte5CF@9IHZ|TF7ZDeZg|1X*Z zI;vQKcz4QfKBGCwiePLlEN6vRAk=s8zvKuUtsoGseBkuY1O|P^ytx3$K*QAVaq|8o zD;5+=qzUN8SJ(hi*v7br-3%(25#mZK44}HOXS12d0Su&_EIqgRYSj3L$|-CMBoQ#d zUNv}Ld~j<&HbS(sbQTz?JSP5fAjt0%<%p)dDu-#$8Y1|x!R7ydLAh3~Eb|jp zhX6KK^dId(;FsD$hdVd6=d*x*&!ijL(d1ykxWHU&tkBY%NB;P*x4FvT7U!G@kjMpK zr~Im(qK{)zf+Q3cmu38@pu6v=*xxQrO}%mgVvTFueSQ~S$YMqK2rDS)aE%@%S1<{X zQ4<@|b5Q->(KRFsp_?kM64}fD54e{&{i5*xRl?e_C5bf{7IkXsSdhhQGS6?E#4Yu=cDx$7rWp}%y9K&`+BqBc0mC79n*8|#8`V}&V7%_F zC+Svp8^?UoVyJ};5i&ln@5Ep$kG6*=Rb)q@RaWvL7T$(cUA7lcc$G5bL+eO~trBE` ze5erR-~44Y98DId;wHRTC+O?Z33gTKOTz+Scl-P^fX1k|EzX8u^Q-%zd#{0|09yu4 zaadn(CjqV{Bb&Gz9OYf{U+%`^g&B7_^<#zWk+tos{rf2?jfl`Pglkmmal8eHNW8GS z$+zY*xuCyf@_0#&OKWqBSUNjR6pO+Y^NQKa;)$H;K$<;@X*sRb*=9o0r>iNN=0C)> z`5@BU)JgA1#G97W%)rjQfs?Kk*@xSfk@O`=I(#>{E6AjOTu?yW_@;uTEBC4$d(90S zZQF8%pj*jbq0vwzG1S95^7o+ejbhzq4gDnZWe!8NW+NABp?5d&@j0_{cqFR=pqy)-Ku3a9-d%UznrJ;@H zlrLo_o#uz_7Z46g{W}0^xY8X63SUS5$*`VcsQlI}^}_5`(o{LSr`Y*!Z_^qa=w8>2QA?Wp97?_|F!WW^gHp*>xVr3CA|JFS+WG78`FGPX z!d4m=Nq}mkp2^M&RuVQN@#`LtS2V*k_<&QW^fZ=P81-|2=jVkLZA@N$W;y9*0@u zEwIl*WM)ypdwT-T5^PYCiHGYavKFcir{^?E@gr;GgyTSaXo27Ee`vPoHr$c(6*8S^ zDD*XoaX~G~4DXe3F4KjY`g+tH}lh;M^ZMl2Z0ri#SRWl|J%YQZN`of%H`I~+4HS;)Qh3+Aboi@-RT6rA(q!a zr#4R4g2UM0$qaSK4-*puN-jNr!=lVPPGIow2Jx`Rg*Mjcs5M{N`Dam)ixuC=bf`w$W&KR(#gzL$SV~XppVKxxnPRf!P{;3So{72v@=yp7 zE04q_X+ZcXo;C}BSlJN(XZf%HJ}BWVuIgvTG@fl_>_i9*I6%fQqiUG(RVHzrcwdY? zIN5OQUrmV7LJ{=w>%CJFCJPW+Qs2tWI#{N2Zbw7L_C})+PMG|8_s83U6sBSbJYX>;D=&hVJs+q1r5QFEPS}HVgChAHf5=o5zRv5X&BxC&s6prW4f5#GxQ}K95Fh34hXl@^{4KfUnP4 zACBA>Q@X-$Mu@ntBrg7WIj0q#x~}qORj6Zm$Ab}##GhblDo)FL4y@|Zd_%KLsfzS( zPTf%CcJ_G#L$Mq0hy3q`67jY4{QK{vG@RVTEBHxl3a}lXKH|YQgQY{AB^+zYrq=wz zRvIv9UG}it1AG7BNPkCwxo{tL|LkKis#onD$cDFebL0)2=dLhdYCJRXAuNABM#h{E zdGk@P29ML>Pk>q2@G>&3EEc>=SS^wwv=!Huw{l5Y#q`9)JcM&?Bt_z$*r_Yx5Yt!n zfd=bG+2cQanSg;Y4VEj!s9CNJEsfSVMy#ZV#nkwEiWD0;6$s*{jg2+g)X8Wf z%O@M!*5;nUSWRM$-==IMMSJnhCi1OXK*O9kaJ|GQo$+zt%ra8dqIyk^94v9b55`Uyn)R^LfCI7`LwLCZ89#w|g%g>QWQcOo~x zVsFWLfp-yDPlEd*0lmt+nTV7bLb2x6uIf{=d9kTBorNP7nPdpbE|#7$Aqnw+hWC-4 z{kzT88(0|;Z994Cujl*;N}uv)Nb`LqljyB6rPP5Q~7WJG*u&Blj3TTzAhH--6-h&m4QM>^Clq zxpx`UZkCmS{!~C=r-8|vkR$&sPm32LkKVLn&<+-JKpa#DZkAB#F@@ort0dhKKA0gP^$GIa{8LZ}UHHTBk_){5kY^0zms6;OVGwcZ;Z7Db0T*^Kol5u!!03h!BQ>9WscDI*Ht=)UBH`pFvIzWN zsMAS(AJRSwme&5qI#y|C;>ktfiwxypYV5tW!Mv6-t9cgGXrKMWLmM;wp-%1pqs)T* zJI^B@%Zw)B6qjgk(>W^0`!M2Oa zEvPeMvu|d_H!qeMx{jaB3i|(N!!Oig4rTQHcMfTyG(=*otn1vm9m>cQF_N{w(ucbL z#@{uMGjya@q6_{tl)M{~y`aoA@~oJqciy8+)SlYTpms%N$nYl6Chf74r&2?E`=vNh z#JVh=7##lm)H`qZeZGy_|7%SHJ6dY{pdyRP<4m!3h)KkxpjKgaPNz=6bt2}+r(Kz= zbpI5_E9)qdg2v8BSVdi-a}N{9rLD8<#m9%_G(?}RbIn#BV7xCtT1|HYrd6WGe;bjB zq0I^ppNZ)KHz}^%AW@%ynIxw3SMO!vR@@9M{nROxwS$9W5yVJsQtmI+p|pX7)osit zWDwBoLyUs+t-zGcb5P*PrEaL?V8cqpsksbOqO>0ZdIrjr<%cF@`l>hI5$P_wxi25~ zDL2geZ`BMZSsma$0g|`j20XX%BaBB64}l7WinWc(m=DW>xsWb5zyfy)Jm>3yxk5%X zC@%qv0U!&8%?robjz74LcpCYlWuehJM0Z9bC%vCLP|B+5?4+2mHhoT};0JoJ&KK+{$?<&uA$-J}(+U z8!Ys4%y|Cv&NwcVF(LY5XLKi!>pish0pH3sU_q=gyArlQq`_=NY!kJh)qNBW9&s5zwoa;8nO6-Owm-Joxu;=#{T`f0m1xhR2 zPe>qCsFcnF*8}Fm5x04#? z=%4FjQp`oeYKgaahz{Y8un{tYtF=T~{z;@0YoQk!Vo5ndv!c#}U1OZ^Xn=dx3=5OO zpoD&ooVJhaJ9btI^;7Ikln~@`WPL2`INT3Qc@uks7=?LrD2H3TD<8t}V&VodS;Gt`L@2 z7jqY8o6y=9j=qN>%^|B=Wbx09%uNry7`iOh#!n}tMBzvUEekskl6&9M1PF7P)tA-@m zfzxdEP^9Yh?NIfV+=Z1B3Per4)O(2%tkZp`D4XKH7!ZbxEGt4p0RMfdcZn=8PqZIQumU=?&`SJyur9NRw;Gf4up3rNS*aI|w-X1g#^MkrCTq-3yR;$JXxrtvv%kp87L!j@?gCk`l^pC;YywRuMDQbnw}-s zw27nZD}yJRWzwst4x%%vfOi(PKc^7A^uOV*h{AZtkub$C^EmH^O>dtq$Sqf>JTW>q zQujki{t7^hxPb+VqHgU};rS2pn^0c8>=E(M;dW3a$M#_}5Z^ECB=}t+nM@716flx3 z3+D@;<=cc%E}w2KaL$r4jK<6YW4_THnaFtJ0(J_60~vsv@*_ZSyqg0}vf?jOoiDU- zq{bDC9VPG*w*M1tj|+)fg5ojpCaQd`R{;BfCV`~PbukSs5CSJ2Uq_A-Pn0qy(KVj^l40$pfXt_4gbPMszW~y$%6+j+ zPJuzAJJ**cUD%EJ0eQ%MztNYD&5KpOp0)n)uV3n77`jLosl37k{T#6(VMkfcR;^RK zfT_YXou^y~r2>{2Z}nra%kBbI`Rp+d!g^|=+(K{0R2f1)(bVp0^Y6*aSBR7hZ|U%L z^4H0o1J^|PaUY(-zB;Xip%A5+;JA{IdivAdy?+s~V`$euXTjxKuGC==wfL4v_!WcsPsefBh=bbwPejR;nwR zt40m>&75+t-@IV94UqJm$S77L@}MH4-Sn6!UjcGgUDy!t(bf`h zgSL)Fo6S{DJm|;DRyQ0#8`7t*rq!+J0FwG=KAPYb176N7dsgzG+rLW4xd_#=d z_F~V}N-KDNgIk*LnTTV@w`_v9yck@5YV5bmL<GEt|(68Ikzs zBEgHBJf_C;1rfym$+bg~g!t0qz_n>!9(s3W83&28&wrQ)AA3JEMx%QYVU)Q2Q7NLf zNM^a8uP+j^&3?k^U#jD7Pn}*47s2=fG9c^zYsd4Vef*hiO^GqOK!hE9vEjW9U11E5U2 zf|{6C7{8k5j>UP=pahVW=lQBmtwwQVKj~q_)hEMi^i$P4e zy(4PuH0!$|^!mL~v{=atH3L6$RGm^?VzNgTEQkQJv~3e8Hra1e&0b1#B6S zvAD7%P5O|ckKEi}y{3L)2(Q@k1+tbm;Ee86rE|%T8Lk!0)Z4_$*9`Mi$X1hEnJ^t) zwF$lgSK)Atm^DgG^}lEmS;t8eq7jruxX>Q9fdi!VaQBrU1sHE`selgVYIcd%gp}mu zS)$txI`_5=@!W%lu8VoNcXJJbDFWHKA_7va$hsMbV-aNV-wcOETEBoDDAni}`?L6d z4nUTKXh-m;BN9dXlmD&747}zP1X&}rsHFID`h1>rBQON4Haihex?M&|xdT#j!4(r8 zw;Ecp+_^dP#QifD6XR#>XvkV`&p#1o}N>Nl8+e1a} zpn@TQxkgiGJIe%pbK3D|o??}pGYJ=)R`JL|=`CV})GB#fZ{O%n7}o&g)G^!o*PCZ} zWWX=^maU3aZgVZX&WO{lADZ70z>8pocx!3n_By~AYk)g`}6;HS22-vQH&CR88Z;H~K>Pc=uga?m=u723wo7YO?+>O8@z zcpMr{C6ZsF1OWTpJdUeq)^(1;PCZgZXQcauHd#m*d1_x@R=rM)k!)fV`yQB;W*m|- z)BAh2m;fgU;#C?wBV!jjo>u!E7P~+K9pf8KkHZ(n34ua&5}qP64e5&x;+|;2e%DR3 zGuEQPX~3ABW5uX=pdI(i&!@|4H5e)42x#DVn5+qDH-GiKf+ALXJy$+G|Djs25%Pu~ zjXPkI$Sd*-<6A4LTj;He8@y^@C!FTN*Qf70&2<$|sUb_dAs;m^`O2ym187tlWH~&_ zgiBMSE9Lpm2N>@S9b<DXpeBdUQhlEvlD#ka$eN*sCzd3S0^^0i55NA8TXFYyW`vcu`45_MXIS%Rp6 zg-2iT6ou2DjS#hXg)H0dT09v1YWiRZ{{7}%f9N!_lb5Zg1Cpo8osn0wlfOtp^l<&a zCTk`@?#YH90mP$@65=UfxaVZj=5OLtWmCIg3P(X!W9Sz2c>|+b=r*{3ggFd}p4OLP zDRWu$f^d{<179rtK3EJ8_ZqK-Lvm9oBnldCt^%<=hX!NO6_n z!eDfQZQ~SP?wApeYtvj7AN#^mH(gx=X8@)gv}SP|@4Jk4e%dRBn$hOBR#2Ni+Tf?P z#nD|Xq;zzr_RJ7YyMal|)$k<}KpB>fc1g;U6jmz~@!vYSqXhIdbe(3AQgz}}w&W3& z@m{VmC?vo={bK`5sPV2#VaFq0lwt~}9cvQ4X*Dl8b(h4Ul z!q&W+b!pXYNN{7)Vaa!kncY=jz~{{JWR$Si>L21Z$#-=Gy61vr;fMur9)mV33Td6I%&FKa*ny(()e4u9Ln?u)u|uS3ThRhP2!qI8Y_nN$UZlI@m()YXpDEr zMt|)XsjiG_~= z=P%#&Mzd;IZsQeAs(#sLApQ#s$cp%^Tp(8J+J-#6O(pZ5m=3Eu664~7yLW^HbKi_3 z`w19ZFzIQvZCS0)g|`4l3+KJ0aAeSvvQ4obH0Um;wKnI~y_1B#fS0cR>kDOkd(mVg;}!A{d0dIKB}Z@R@(tGIb3LY^=cR0uLs|zHc*$F*i(Hjy7XaE zYfd*}k?JyLXYn6;GL$pRxSAEW*i?y%Seg}`A8Dq0&)>4QtolhNbV{_mctX}tKudIb|3{0L2+CGzWw3lD zpMjd!h*Wa0M-E)zfs6mVRT=wP-=6vB3jQRhw=QZ7rHmtnTKF;)#K*!rm;XwS*k_NH z2SS59C!53TZlQmJtsXq#n__nqH0ExA@`P?(#$*PhfGz$pwQ+9zMZ0!NbFGbRNzph; zcO?+@Q6Es?K${5h21D}EGpBoBVluj*a6VaFlYmY1uaiPv;>Y!xM6aC~vMSVH!Ce)8ijn4(CI=njXuWx9u|sZ$bz9kP zYEi=LbiPFIpxlpvVk9k?rs@CHN{`i~U#R#bLzE~g+(6Q?mY6$V9e(%kcWt*)6Rs+c zoJ1>PO!0G4$gz1$5@qXQ`XbYg28;H1g&ski!E+B_^U8Pi6V4>Z+3abNAK?nFg&2(h11(Vo*s8#e$c|r zF4J?QFJkVPxg>g%=$~zWWMPWeV~|1@!%Od}cMrJAGIB@!VODbLOGKN55f~X3|DSlA z(4Rzv(`ZnmRGaz)?YGoMj>C{CMBX>_nnrSsz!I5{%Jk2Sb%ggqv7xxHpoY99_s6Hs zfOl~}ZN78g`V1cnLM^9uqSqeVob8zhAOLq71vNA+UWHZ$bxsECR|n+b`rbaH_rjEWe9hnid$ z#3HfDE@@GShY14<68pJA`z#%9k#)?E`v{2B`FQGrq_v6qI=&?RTskSjcj&F}4d77;;;2{Q5;uvZgVB{c7aS^4cmE@Z z7T@R21$A3{3=NzXCzFh2K+#n@U));s92NqF+E`u;uypsN9o;h92`iYRK5v?#S-2vP zDocZjP1C2Z&5ZYjB=Qz;n#yE*S1VdM)w?=gxhr6}Z^uf>YnepZnu`J5Wvg6k$IfW)tWB1zLg<`NhV7) z&hCuiDU@T$S)-LMZ`1h!!eB88putxgYrm(g=7ldBpoMgu7UaGH*pe4hgB3aj5+v#! zdoU7VM8%4Vgql5Ag7+KMoDVC1K;HXWMK8h4Qf4@QrmJM@ifN8_cd_U<{Z}>03fe3c zpRCp1iL8M4@AWW5#P^*E#Wnmk+`H2w;kUU4`w3)mssY-nz+td8Pbk6!wn%|q4wYv0 zP!w`JYa*`EO4BUM&@BhyC9Mb@-bVOgjG`G>Pym}yxgr#hy4baO=*CyzdHmP2=VOfeazI$-iMdTBjA&DvvQSdl>_Xj&yOJ1!wXHpNeN*RHcvh4 z$a^>d(<3#m@1XkVAaJjz;CcbeD;PldOI~6JlOFAdJ37eLGGl&qBJJNwrHiN%E9e(6 zK~%}H$S6wudEH+-1XR}QC9EG3ImCD%?97KDLt5#~=yKq!iT~^|1j}*DxvWvUnnKYT?4~iu}Vk8=Df@{3KOJoh8X^k+vuUt^?uJ@>}qlR5<#@5ZA>KzIK(Cq z%?Q|s{i9b_0dJOuWT8uMp|wI3FaK=%SMC7fO=&!`(3q(3M?C>%4~F<-c<2e<|8PNW51=ya$*1%^)^?YkytZVjqO z`&|8+{*6?KX5=I^7gm1)R}`L%fe9|IXE%bD*+A>x!Qd`~B>$(A66ru^LxWD@S`BE~ zjn1XZf}NrN|LA=ydBI#YX*>gUxi4j`qzc$s9oSL{#VWF@2&t#CuNF*FyPfMG*r3`h{6WuyEDN=H~-D(*Pv0yGJ9 z7jYG>5YG!o@waa3s{OcZjv?QT+Vt0RiT^Lr_7kfh`rRBQU=2~-V0*JHgU2C++udxN zrl&EjO%-9l99n!bA1^&^{p@6wTpDLI>1bi|t8ypye8H{}FH!!JkljPB-qkV;ihcHu(N$eNKRpds6``1uShng0HWcLacp6k@A2STS=ke*!0Z3CmHAs7(NV(CFBi@ zA$Tm4rM(=Rg|6*5ZbGlY)0Lef`A-$JOcLUJ8NRIumQV=J8oVnvLFW+n`2J>|nhP34G2^=sZ7klk6<%f3_k386@%Am))R@_=x-xS!z8wle^9ObCi~vS3AD$slqk} zR0V@~?YbbkAjGdiYSb{09lN#4xYW8c>mFsugU~rIZkVrey-iHJlOT9*f-g%E7>fg?$HnKLFHV&tj zHmZZPm_osh$Zz=Nk@V9_AonD%g~vh>s$T=DVUiF&<58FDuIfGcb443qUq}yXA^4N@ zU;}F;$GZDq<^ZaohI_(?igJLS4kD5dx#ijg4)p_}ORdDCJmrW-D<4D|(UMDDPRl2k za)y|U;ejSUuLNH=HzktN*suHGR3>Kg+N^JQ2Q|3hG*UsiZkO?u{&YK9ru&!s@?iN8 z+dIxgq*y+3GieaAxvL`5y&=aT$?kFz2!9+s2@&Z3YZw{j)dNSX*e#hRlx zpz()RcRK}To7VZg+MBnzoGhwSs1Bi%_294}EubU+C!2EoS`5@A3Qp*y_}wZ>sV5zM zja4*k3X}9ZJJduLUZc6}FGhr_=Q8EDCBV&{CKYrc9Cz;1?-PIwgz~UB>i3~3qi;Y^ zG~+OcjNlhkb^>RnWN_1=A@kU+y>%FuXI{z|3#{5DhnT(ye_)9Aw7JoR$>4t?mb-0Q z#U%P>hn(Xf(LC<e7z>c@)@(;!V-IW?y1qNiLBgO# z`Oht1(z6em&2E|k)?b=EvwBpw(D6Un-;7`5L5ZCojxx4oP009l-5OW|*qw*NwGBM= z3)OuwloZJS@@o!M04G8V3iTYEuq7YjGO40b6wWa=nlq&ql&NF@C?Dx{@U%S7C0XPV zUeVRPRs?M;)jCJI*AcozwfNjR`RRv(7j(%FoWXudNeA0|F`(2ld9r6{eG)2eply&L zwz;<)_Xa$)cIN#f_8cXTWsnEK4*A+%tzp?IkULEUdqGzhet_q`;GP>D_TbvFuvZUVeRp=ezF2C?TI!TISPT1{kb3gQwZzU-vDHIIN_d#Z01NUud9Gp!@nk4F{klI0!uQy^Z91AV6oFbObay_kehePOjnslDg{*=(Kbb9@>AGWy*}g3v}3RGtpU? z#cCCk+PXF^y3IPkKuV`WO-_d$^XFG2&SmifIyT%mIec(5)ghQI6RVRGzgx_gp0bgl zKvC=AMU#Htejyh5fYGk6AmZt-o`7YtX_B0O(Bkt1#Pv2u6P9>;oAeXJOHZ0;@`2nv zWZ1o?bZ6(iNQeLk?eEQD@C&Kl393J;oEFznnSP0ab>aqH<^N>(V@`I?v^jKV2mdm| zf%SINU1>Z7D0zorLxZ^%c2{clo9-gj-E)CQ$~8tkbIvn9rj-2axDZFoA}vR#4^fc_ z%=f9d4}zj^gO+6n#Rer0?cxAnMC(9RNSA4pick6imX)MhTc4PtTu_uNwqQ+g&>4OJ zG;d-kUb4JNJPfmS&4~`e-4T4f@=>jZTv@76;n&eKt%!n>@-ZhCT%+A&S}kbG8n(i95T2si;%pV&Cm^ z@~jR+t{V}u@)UWnTRN8GUMGG_A$?8~n4~@Kd3|`b3(q%+Q13><^LA2Oe-jAl{r?W& zFs3Rox!C(O*s3=o$`AWc?N`I3Y+g9lwq53+Dti_)&nU@Gcr^$2X^~4N6X!I5;RK@R zJ{0cQE871yoh@%0fsVN4%VpwW1jWCUC*#%wM{P#$nMhd-0eJ@F=GYZ;AAB(FN#@Yl z=9XYyk!+&1J$GM7e9p}M{>;YMZfhbCDK_*>dW(1!^`F$S~We!Av*E85I zYaiO;+LtJ%GaBVg|Mgp1xNWK9VVZ&9RCHTm5fkLn@QQNN9i?Mqxrp=-43?}QD1k^Tnty(A+|#rM;=9v_HrD^{vWs@bGtyqN}0 zvi&-7G1sl;-f8d78Rmwi0R?uQ1TrsjfNui!C^!BM>K<;jmryi2$Cr*bpC3zPuBvFh(yHW9a>(N-q2P}##vsQ)Sd00_#FzR{ z^5%LH=rR&vklRSKe2KX%l5WFfZb;=uP#XY@R^!&~&+g?{KpXi{Cc`(-L{t)U9WtWM} zR`QA8QqD7&PG_HY_Abw}gpDYqr8w9^F!zHO5@lVd%#@JZB>_a#r{_6kM)*zU7{;h8 zUbfOpzs=wbL1mnyRX#@p%x@|B+Vi)D8B2dx#KLms$u54N{f_4J62#T*%#TkfP#ed| z*?>_RX9YH2#%fSIwP{!1<(`8y95!v2pp5%{Q^F~fjZa6IXY*5ICFq(o&a4E-&Mq8X zmlRVYx|_gu?j12$iWRT2#u{C(k^nlZ#9>w& zk#(n}^X}iE$^STWeK8;=yL-8sjv=>8nHD$r!TO3~bZubynpA59iLUZTWwF9YuBBt5 zFsk&sER>ZMamf{Lm}kH8#oH_-%jd{;1(d36CYpkHMFk!2z9g&YIj}*InAEte#NOtf zHY2Z1Asi7NtMaos4#JRbrY>xL$z8{~xje2d!h#^ZhAsP6a?_eWC+Dchj>F5#2fK5( z@1zx4HEN>*Nbb>=+In9S+Yvgy8QL2@pWikA+i-lZ3y-Q3D!@9F zbs}$TFfQrPO@E0^`~hf33Sh20J%v7!GE|ilJntq`t{=^~(!(;LJVwE{rzyUY&mT{u zMh?dZw`SP#e9E9A1_`bzNj0{Mw3!pk|T&6`N9@C!U9k4bakepod)VKtQ*{7ox%MXJ20I@v0 zE$h2Nbn?Q1{R*C5{o-!0k;xrLOKWnn!nl_h?jZ2F!Vgm3XnC4;%Qb?@1``DGB7*2a#ABy(X zl@Ri$dH-HNJ1m=ggJByw(RdQ%Ykk^N(Wy!_szEDP(Cmgq=xIx+*TPn7e~A;c>5O+u zmbCCa50L5WM^olgX|+^3qGTt>3+NTz|cZ<|8bwtD}9FFU6v zHAWteoZ_t^=5Rq;ug{Cl73nj0vTEzkT~VY0H?))#H!fj>^gGl1%>J=jwLt`cm=VH7 z<;<(@zpY)iT20FsU}6Y+sD0Nf|6=i)4Lg1&|7{lvD+-w#mE-8>SxlI+pM3|>ioF-a+{YLvyO3LD|E*6Ju0f=~v1^)8t`fGw~< z;NHZAYPW~2ZpXZm9r_BVxS6Wx<>FU_9gdtc~8a&Oaimc&XB)x1xWZd@7|JCQsOO zk+T5l0r`)e^&GbP9}%rV>HQ5d^i~!I^4oXO4nnIKDomI)5(QZVC63HMf(k|9|A3 z`rNqk@@OkH=i)XFg%#Xv3sTwM3&KkHUXC+YW1x7L&RZ&vJq#0)sj%H_3v>-wR(4D6 z!X#n%3E*@peRRaj>7*9w`C!EXf9*WEe-Hvg;X-Y#M`A;6)$#Y13Ekadb2ng@o(Z zT{d;jo7EZh`7C^!QM6GEx?Axu&cTN(pH7O~0pJt^-d_FZ+dMwTB<6>v?7wUDJ?c2F z!w*Y{-vv_=7Pti06h=LzLDBiv<2}p--pMwvSH9)e^VW=FnY4MNKu$?ujtS$jd+yB~ zNWc9Gr%iJHc!Tx+y*A4ao%ol*z-ACR`b2Z=pxoNry^8g!KTBh`FCIM3IFAl%xa6a; zJ0IzdBGg}Gu9KWRQU$>%nqrX_GR)nkwyA91oiX!4QaDYIhAmxT-o&n0$*{L>`$y%G z*s2%qz;p|$;Ii+U4>0m)3?^dn*I{nbL*}S7^3#7>LrzlzCuk7lcw9VDSK6fP=3cIL zB}hcPdlM7V0N~HIa*3A&DYryy@3kJRl5!T~9cmM1tGx5Vy>l09 zTD>+1zONuNi~@P8t|azz`|=~_1~SYg4dGFru(ohrlgO8eXO0VTVK*vr`-c|Ml$WYr z0=13)DT&zK+&DDqVBwE%%Ii5wi64Xcgl%jO=&9F5i1VzD7b@phkF31rz=?+Znh0Va z7tnt+rFAbxGo!28uk16(o8Z{6WsA_lC%|g>J|KSFZpvm8SYViV?!Xb8>0RAf3MzFXjpdeL#(5ulv__-e+XG&^OsQ3qh9`!j(K7Yp>R}KdkTy->62F&O$#45!HuBXx+(o4T_MT&IJRK zdgnR>)T(_&2A2ld=Q?ZxX!4BW`mMeXmJ4*l`%_`K*9-Yhd<&y3OF8?68g@wzaZ^ip zVP8R%pCb(!r#d+ferMyTcI;JI#6}^(N&0}?HrVcv;V*s7i2O$UcWf|O5=*c6N$cAq zpcg+uSED5x{c?N7-g#=u5IWtDE&3pcx~MzOHqsPa{GqV;>PKm*Zrn-ieqS+7L6;@J zDB0l=z-qQxqB=u8JyuqPlvU@=5&WXPS=~qQao95-e#~J9=+1*S9DH|Z-Q16WaV8-$ zOSDTNKqokrsKUAxE8qFitY z#E8>0KWK+`i_*}(oZg~Q(e5XbW7@)oiHCQ5d}C!=Vlaj(Lr2+#o`V8t!tv)SPo%H( zk0V-7Dod>8xdNw`a2X#c3Pd`h76QabUNm^%)%=k3nA^&G&WA6)^>#yIq99y_aaWz( z@@j9tN89Z3(__60Ho0ytAFoSyneYJU<2sN+shIEVx5aao?Rpy2%BLSgV9roZ59tpz zUiO8+|2^F3G&f%KqRzL9nbt(BkV+?cMx@L`oVii2MF!ibZUo8_G)+lWkFv7rtJ zJ`W8nh(kG^-f4pwmX3su3n}+`km||z_{qss89C~D-z4) z2hPfg^Rt~$<-S1N0NbJ=h<6}RNAZ_aa8sL#NJHX6Jag-|Bwm@I`D=`!=44^wAe7R; z)-7icc9nI;fpgkRL+y5Gd%?DwTcOQbrMrrdOf)~UXwDstHSo2+@LbrY_U?L>f|{lQ zs9E?FDnp%ZD{4%nZT6OH zPX_Cs&{qadK1^Fn*VB7nDAR}zh28Mp-HhRd?f@P)!s7oLw44=+)#DmHO8OxS;Cx$b z#+bR4BIEcdQ|-GGB+*Hnbf<9Che`d?@4|YhN@MQhA77wf^F@KRGZ@nou)^8q^2eQs zro4nvH_5!ntZ~e?_d)b!&1<){k7|Jf^2>XS0KC1@xr4d3%#&p5U$<%eq`FXV%28na z#<1FbpFvdZE)Kbi&&rZ!c+`cr4D0e4ZSL*`Y~r0tqHsZ0k`0W=*op6a+)K=x$H<6G z7Lw4c2z318alhOdUXbYM*kPg6o?oBc;;lFf2Zxgwaxxp$N1e*Cw@1Vl*}-%J3}Ue& zIR_k-?6N$2-d1*XF`syJJ@uO(Sb&mpTJ!90TzAK4V@Fr+PZ;T)A~5mOWJ5#Khzd=C z3q}E{qd^6&aV{*oSVK$>2QE%?9P{|~XNRV-n6ciSI4!3*y8ccweaoNyLK0j?Llje& z%&(DuDVs>t5%OTMpdQ!)nt-#H>7#GSNsAj~^P9H|J1~?5^msx;pGyRMv1PmIt|Qu> zbK)e0DOZAq8kF&npnKw6&cUP&L;X0#?P#U6f@hAFSuD#zG!}BtrUi|1(oQ8LT&#CY zG|Tk607IW1*Y;wX)1~C6ef=hoUl~=mj7VkQ1t;SY$$b|M{FVjxe(xFVJ0^}WHFEF) z0KIQ~tP8UAEgom~nS#|k_u1rhP`J!v3;TjxSrG^5>)ag``5D=fz!cU{^O29Ah6nP!;9d#VxPYm5k~ zC`U9%#itQ~X8bJ2#RQ|e!7pZz;+p7x(Xgk&HZTzs1{;8_2k~TKZ#zu$)xW;Kn ziDL}O{)VPGw@$+xtLwhbB@=AWH$ifDoO|29Is(AJq!Q%b$q4M0Mw3%2D}CAFWwx*q zo7C_JesH`ENlbkmkg-`r%KQ2oc|~_OPB*ns!?U3pxQp9hx8bT-2bM~(w!wluuMqi? zgH&0VLK~_(=Lu7KMgG!J(!bEcdl20UU+C%?I}90*fGQDKPT(ExyVR+&cd`zk06GaF zPfA}$HqOGF=aCSB@QGon5_XkYziU(zP@f>%;!de|qBM%gQbzLY8}S`fnC8!q&fE|) zv&W3JyYLuj4Uzs9?V0^}&s6HRXk;=L&T7b%i#`BQHu&j4`p{n_e8tY@~z99o2E$At9`pnp%v6(K`tLXE4xDW1!R z?4ux1sAP}n*n^vtd24}f79Y!@`49EI$`QDcYPyqG2XL(8+Ie2>9v$JSOBRu3q4 z)8$!hBb;Z2sr^n*a{L@nHg2Nr8gZ#VuzF2+51EW1GnTX4d5mIx;&L(%@^g~Z!DLCn zs<3$B;*@kWuMB{ve`_P2$J!`=fpzwmb`F#Slobt#-Y~h6G%R~ZovU? zt59hT-k&qa4Rh~ObXeiEgh3U&JU{x+qQmoOUOqy8T}+bT~W{02X-d;1O>hp z?!05(Ez;G;$LfiH5b=~7c*6Ex3;KgimpuR&>oMh}>g@A<$1S5tU`TN605`{5FSAA; z-@*W1e!|mO>04IWS}|6=2R~Ik|NpOGCI>4zWxpz!0_SCse94;Bc%DMNCl`o;`Wc7QHm_k9^L2<+ai_n{}v%9-z5k% zRzgt&5-sUiY!(a|9om`+bxRbJiQE7JFth)4xHX0dG zD31e61f;1-&*AN<9?w;6Qc34SLio%>p;IUtB|devB8zB9VXrgU6~;h0-o$LXD}NGh zJ8v*CkPW!q-UF^VcvJM58fGxJ0wH17s$%oO@Fn$X@`Unp9RfOWk!%)zv-@2pvK$cy;tGD3TAbTIe-hxxhuRVcN{*REbg z_p?Q%EoIh2bkLf$Es^*SK#eNe2TLi%DlX2N!~Dk9s*9w&w*}om_O4RmcbPa5`=074 zo^%dz-8G!pD^&1a^pTkjOIl#fY|RlYe(4@KP|YnaAv#nfV%l>$2rOn4D|Mej`?yf- zT=C320v*~Zj0&}jKV3N0O*fA!cSD4aBVy$|))#W3w-j5X6+KIl-WRBal9keH%_!s= zs%~mV+scF7EWIG((O7lvPY#E6Kc_@&j(T+9kpa**LA~pYX8`;uQ=L1mn>EsIyaSSi z)R(`6?$30p2u$8YYj|WfbiQ}7jSF}-0+!0T#`=0f*KN8jp>~3W$gD^N{(b8N_!1IJ z_d^(|q{-P1j%XqCs=X%Oee9hj>Dffw{|nX?znj^vh-b=wGoG4@fW)!|N4bKwzS3MbMCrcsp$~_mn3l@)5{1$v+W7!Q zHa8h6*{nida8Rs-59B;-LtEZ!s#2ly#*U7aqTc;buqXhtGpQc#^rulbe+{(8hYe`8`S#$2C8(NdGS<7X-nXhBgx z#O0D2BMWb6GrO(w>yFv1n3!j`{Lyrf)Cw;?)aPCAoO~rBH0ecUnp<5eU}d#`NPzUB zMQVo??oUk~?tr5}woy=k2^#7uBH)s7XG>3!3lZ1?EH)56Q&h&8 z$aN59cMCf?MJBnv?wHHX#_H;1KTdlzeE^lwRs(Wp<9YQ#!dd{~A6kUb#Lgyt;Y$8B z`|z`{N2VPX)ak`!#HU;L19QUv-0R;+?#(8=t84OSdCw;m6vSv%q9`AmkB)C)+arIn z`Tz0FlPCO)GURlcW!snt*$zU~UzOOu?nlNX+uHa4sb;$SU3w3Ls&P&4hRml}YA#!m zF*jp#H@)&5zGAJG28ExWua;GYYE`xSLb7i&e%USx>V8N)%rNI}i-(xd8oc5$TtsuU z0aj=TrJD8RNkVan6-lR_QvwQqfU}%qY0=&{_^1h7P$ADbO(1c_fcVSdb$Z~4)8l+# zqQM=7@xu>A-X!_(S8#?&-wgWKYz)S19%=!$IO$ap`#bm$=q*U{l2F8!VtEzydvaVc9i3rw!$8b%aKhFl zf`@t#>S~LVX|l&p-a>6agWSX9L2I*?x+&?1r)(5hv(1%i9LPd{Dj$%`&xJG2&6$bl z%|19N5i~>R__|CxW{O7|hu411ZEE7778VK6!dOgNe)w0ZPMcin9lsV{40B>gPvSy8c0g;8sqU^OQH$ z08&%ZWWU^w^tsyH0klqgF~j@=XuD$okguB$FDU+W`_sPAN4RGGsAnP!BjNhr(sbd* z*uJfyEcNhd?POI!F2Qzdx%Kk(CTdv?csZR74WRVqILZFQ9{%A2`s4ZNjF>)+Lhb@_MnhJ`a z5b)F-SA(UF?(%7?F-;0EFXon(fgL0acA;@wq^$t#iIS=uI+%^mKZ~B3_z-)>b5gXD z|4l}*hzO`^d<9mOf(ofJY}LV23B9A1-=at<9n;$tN-BR_CSA&G+h2%vld#X1HI&%U z4xDcrZ9g*8N$QY_hTNMfd>F1DgMlb0e(~?Z=?-~NykdJnAj#5E=ac`R`4b4^BzZ1wqEek7@W0>yUN8e%gAeV zK=+(Gh2c|z>HE_)U$Q8L{^94{0M)_W54Up1&fB8Jw6*?SX_5IfJyfxn+C_FT%DsRC z_`9`Nz0WFI<6B&)J$sFyad7T>6Bm%LrnfpALMug!f91Nxzlrpi7_(2DlX!`j*_8kW zK>5FIg*6Pi33PqGL(ljzeQP4Lb0rR;l8|A@rm?S+OQ2{L55sf~T6!8$e|o4gG+y2E zta-FUKJi@Vj++cJiq=g?%g3TewHwiT3=v05l~I^%P zXC(_t=Dhf7Je2zckIPc3gbvo;uW!Q&&v1!+`E7!=ilJSN1Gij3G=b_wR{H z%VUZuEQkqQtO86H!ND?)frfdNkO%xi*tXoyj(H@p1Ws=i#}Z#{CLHV~)neCMY;T zSKxU|XJXJg^hz{hV=S2|h2@#Q zIVT@Mdix*}rh41MqZujn8{x#}TqAmVis%!8%}K*QhNWFGuQ!Z4Y-n|WF8{MS@w__z zl>N#vTXP_YSW?&~1{p^m#m9-8ia9?N%2fj-TdSwLG=k;;flApy?ekF+g4-@yiDc=p!8H+n5_&GE8f)L8q z*nkx5TrErli%v2G@ErI{WAO%4E2G6n?VXw$Un3vvZ-sp6QY8+~<$mBW{X_%+k3^6x z%53xzUxxe)B%j%NSC5Q8jj+I*=LcK~om&|**b{=%!}9{-M^e5Fb@if-u|O-^+kk=huO zXOG1bLk2vvp-AN(?s?{aH<|5Hv!;SUdgj4tg%w)A;@ZTv55@f{ANeRXg`qfNZ+kq1 z-dDfZJ1;ASP{hTR6+BCA>hvyXiwYbzU|GHnK369(GzAp0c|6%C-YPC)te>AaN)~7T zg7CNHvyB(|5z0MN@;Qb=8&4ThXEo~s;xr4zj*q@YqgM|dt<&Oy|OOC5(dkGs9Dols7vg0uO zK>;Vj;kov#fX$D>JGxP)7G#PA^IGxR%TW;mwRh3vtf5`Dk{h z=$#gm+fn*e;g|YXsP86+bNV}y7eko`L?Nv!m%R;72G%&}O(;F;7Fd}I*Z(b|=yYK% z{bX1SXQ_AmURn?oR{C_^N^0HPPH>amc^2X}T<9TnAJKPjb7r%2&KlnbO$`50vIgkj zn(iU+B`GIj(4W-(X1*c+?c(ofkWOC49#CJQ4QFlS3-V5ZOEG>=Rv{jAizP>9&p%d> zJ8n7GxHoZDduxLY>Np>P^?U~7KRqGv5^f*I*8=XdKx!{P18=vSUE#`8YdSAliN^ic z9LY+?zG#-=auc^#rkQux@=TQsj=kv^DO7{T#RvRrimX?Vx#O?{#L>ld^3O2lapj63 zWK-v@dS?0E{AAjGhHEl`rDR|3j2ip2dHo8>lt}rxLpt(1(YXG^0Y z_z{q^Z&ihgBVlL-koWBNYA<^ccpse|_?bg4IIbfei-qrJ*;0GSTqnh5Q+5Dnu~p;9 zF#RMk6=eZ*Pvj+1envOXaIAZ5SSo>)CpWDc&2su3`|nZ_pN*A2g$GpPg2EP%B)a9& zH{4V+gR+nvoEw)-(O$U&n{505Ml)^fXIbJD-;%&uOacEmQ9BY~gi>5GRD2U&(~5g7 zV}6YP>SNJIE=7CCM%Q<}-Q-G%sx@|h!xeUmb6cs$KepswW0tO9Jw~0Rv@kkwIS+?} zB;Hsbp>S_I=AbtC(JgAEAYrIRkIYMBwNG?;@kV0ZA3>eOd@HnnGdT9MmWW4q0C8B( zC#0e{8t)cmccc-@ocSiF>UdvCNNR|7GYj2s3wbLVC$ z!t@@mzRo^4uCU58_sqBwIV=G9KJCvrRTgwmSbG`0xiM$YyvDzo!o#UCU>iT`_g2%J zLene}Lr|puY($C)?V2apFFs18ltRB!cak_>_|RJR;8-rTCviQcP`}&yN~vGw}?jKOB^;u+FF?yQ~{$DVKLOTmFEypWgb!lT-l)fT-^ zWUph`MYY4)%k5Z+^iuUcQjbEd>(k#~#KG1nP3$0f6}z2e&1JKk#dN9k$R>)xrP z?#0Ymfb@Dp910ze>g=D>!c7oL6GonwC8rvi{l&f2d{7mb7^CT6X?#1A%87S3_myXv zvPEz)s4lSh#Ra&ORM~q!s0^Lxxbg^=7Lg;4ttX|SvG^N0Z2PQMAL^D)kS?{ul@PyK zde>UTPEuyCljHrvmbTV|pM06Q$F$uhSwfO!?B4+fV6tlELaOj+@+}G+@t{Cx28kN_ z==%)oZcYOb-|W>~`b%!Vzgs8`;3*zy2(g#;u7=}kZ9ll%^mnuoq2c*j+1rF};2jFg z@yZJ81_f-7o#p^jgc_pC4}^0j_Ms||8aI&2EGjHj_5u!~E5l~+-G5}mKUr>ra*1Z> z5mU_wLNEOsRIefj7OL^^nlDK+fpUw*G56{rYw!~`!mQtWAvAx*OLH>4Y3kKo>09*L}X z;7S8QmD)g{E!nTw#Ju+PMD22p!NjD1_oo(%LMv?Kfq&TU6Ime{+CNpM%ZCBNy~^kr z!I-b$`y>xw#+ID=DxMSga`Xk_)iIW)bhmtO54iHU0L*Nuhsn6~UC0U;RkBnMNhE6Lz z%S2~By@$^ug=kuK>kp_#Jmb?T0=HnH88 zrAwAUO*;*EObk5FtYmAT3M9HXHn+9G!*35rk~?aJd{7&ks6^L1WkZ@nMY6LSJvG(| z<4nrUmy0DjjP62dq!-1jz&pNW;0|PHj#WUi0~k0Ld2 zs5Q|4`U%RW34`GCwqpU{EPq>18#ESSKNvBl$!npNSH@$Z~t!$+B^e zA0{-Os4s3YweHFdV7>eOsL`vb;k7)kB8$JR#_xv$GD>k4hh|I9a8h zWa&Mz^N@#Osj8Ejow%0245*9>Qj6(AlQlYDK&TJvOQoWL4H$aU(gr2#;T>K^|AjKP zQ)PZe(!Sx+B*tKY9M37VXin7PSE3fs(_4 z<_o#QmluszU=j`CFTSw9t+V6dyd4AvY(~r8?{Z4E=TAOP`Vy4RJZ8r^C0|OFHl_9| znh0B!R9Htf#U``Pl9m?cQD{vsf`Vye@rU8@X+0MOjp$*tq@F~GGZ(pJmz?i%$DTZ{ zy}8#aeOzlcwu+lr<77ik)isn2ggWJ4<4o7zWOJncwY<~AYwx{PK?=TGR%3!9p14HW zaLK-Dt7!2PloIQse?E0AG3i{qtBUaKWA~@2U0xfH>kSvzJi;#Zq6m~ISe&3qm4&e~ zGmQ7ffG^Q5PZC?Te}uAHVw+^rG+`Y#9|^~fAhQrtAgLB{mb#sK@%LKJ?v zZI^grlGJaOg}%uc{zwe)8)#oSVyZm}MeAGBMT5CtQ`kmrVa{~gDjARm2{LnOp6Ax5 z58>G>Qycjq>?qH5#Wr&G64#6d%2bqmJGBseju*c5b;N!#eJg^yz)Cc4b#3pTa1o~b z96E8anvR+u85*Hgv|QSx)nVWc<<19|IVBb1o>Q5%Hr(4yS3lxs#sY|WZow^vn`;XL zQ6muWdqbBE1prC#Uq5WY+nuC7skV0~$29);tAi(u<~SxDUj@vSQ1t8@-vC=416epl#-ws=zSyM@5%Pw2D4Y!|NrQ` zF~SLd@OX&}ji06C+#25#uETc;4MDf-Gdd9v>~si%1f*K6lWR^EzZ83Z-O_ug-%V3Ka>SO<6vw~15-;Y&|U0F4lRpkbsUHA*FZ!O3*SwF5d}>e=Xt{os1gJ*7J!p{XbZSfz zhT68qhV2!q2|yc4N#@CEH*ah2ckio&1LBS0)+6)6)UCQbi%G{>_HlsaN`^D%iShNl z)(%7V1kE2>qBU>~jayftuu(TafzGYzlBRHPEF>DeV=e2AEm34!>5gf4Rlbc=D=~2{@ zTk>k%X~NnYMHb}gyq@NG#RJpdq0sg~@}-B*6REFgST5mOvp84)04Txo^Cj0u(pJ?i zSUxeo9kSakPCb*inpxi8IPcs=v{vzmWe!?|Kw3`yTidvQy*xM*dLJwPADj&U{MLS0 z^}R5Op;t~8XPG)dCtRu^DqzdZP;^uc8LjVHJpm@Qme%B?ps9y7p4Cy3Z1b88Si<@j zQaqRhGFz99qzou~ER-y7X!dq}%Tf zi7SZ)TMIr+5ODCWMhI(AK3*(h>mWR<2^&jtmCjgB0{3<`gNXSC1hio!{G8LQ@M(K8 z8m;rJTk)oXDtn2DRO1bI{53$}VvhgK7pEq3J{0J;mc-xIZP`Bs!%6cqpy-TXrT&hX z!8x~S!4j4B_(0PO9bL2~h$QqGjY`J5?obxdy~P#EQ3%XeH4aO(@f>$KSmlS%XZ<4J zVp%%lOT!?!iAU26G=pv6*6F`s1&<7}KWOfs;LWsGW)I}1XzG19a=ie>gH700xjMwE zT5g!J=auAxZ98%dk~1rM2uH$|edNNC3lgbwl*u79GPvdJ zqVjhXW0|K#e@7N*g(ooHY;h|`cN|dCjm^0@T3*8?)r(m2=}3T7V_th`kwV@&6A-p% zaaq(*oMKA@h=t4jBz?6sR8>{Gd%7A}8@CvB#@xFG2c-6_Czjr|r>lo(ZRqZbwTsX( zDKqhD{NOtI(pDK?@716Yf|D4$;k@Fen$Nkxqag{9y!Dn3@nr;jn%Th=WHyZTyMFIW zBYF$I=x*+`=0%pSQc8!mU=ia1khH<-(@O!67r4J3CPPiwINvc5;}tTR9e$F@#}s|B zMLj>B_mnHx?oJX_M&S)W@`kP8(I?y%ggeBBTpcrR)?|(;7v{=-I5>7N5Zc~Dh#7o|Ol++5C#5HP zWh*n4L~(95`wTFDBI!7GSynI>qb#{S5hX9p;3+LYp@2U_S)Av-*XfkAY2`lC9p0ab zBN!0wX-u!!E)*jgugI|aSi>T+iEJ&ht>*KP(?b@OiQp;ByfT$xRo_f0f`rDbAL)FW zOe=k8@f(WCiC_VVLj`CT)Z1EoRCNz)3@H}HXMfzR97ZgZ>7LgyVmO4Hi0A{Inh`55WmDf zjNe3oz`c`z*60KN9mWGZkMAE)hn+*=8VDzt6-3yVxO%WWgskr~l7?%ZNof5VS07{2>1=Ss*4%1<$4t{-Gi*Qs*7B`aS`bJn zIZHard`21|ag}=sU}AUtwuomsDXk)72i3d35`f@4QqmpGT|TPC7isEo82rF$*$!n0HPY0z7baW|DUhtZl^hT@myWm>xA zCfyt(sK0pv<3K$VOY{5-o<@+af{WbSkfxy6_>0s7&j9AL!e#p{23rz)Vya~gGClB$ z6!q&?fW*Jt4o?HGQ+he~yV(bhtYA?X5n#jJE~;-<_*k>)dPz!zh;alz7tJtJwtY(3k|oN4i1AsH_zrGk@C8q; znryPK^(T&#PJ_Tbo=ra$2gnFr6wLu)x*a{^>M>ugDADIGMFnKL%=>U~U!Ey^h=@>n z=Yl~$#MNFHh@U(^#4YkzM|XPuNeCgO?0aBzU`JA-Fls0YuPS>&*pBWQ>%ct|{?4*P zY0)D91_Q|cqBLLd(XM0|+;Y@B@Xx?U?({Kdi!U^QvXqQ=XAEB5BAjPPk6u?duHkuk z9PrRn8Xdk5g`Gs>TEJVK<-iW5CKLMIV9hO|h+842Gt`W2jImDaMJU~iJkf z2zKV;io>g&a-s^3DX$U1Xj#`Fl? zuY>2KOPFr^khm6JEpmqNF%5OWqyWi@Ll22!DHUaQ_k}TV;+uaHU7dsai#b6~ThY%G z#w(NovOW5p_XdiW)uU^-m#-bxZXTG$w;B9aKC}#l6t&qL@KG03qWOz$1RNZML3@?H z5EevA5Zl5E3Kq=CH(8Btil#Q$w9y>xYOoOn4X*D?cd7#iVsskxw_C7Ux?e@H^OtZJ z0#+!#uPx=8`~(RmZjXkBF@9WIc%5qkt_Zqb0<)^-+jLX$6^!O(Er&WaC=S;)#?00? zlnbptfq9<~k@Gq9zu}%?c4mXoVTD)E3{~9RzH-HF5NmI%Nq5$J-*&elE}g@Keg-mh9FPW%`CAD>PzfGSYB(veK3oD+*I?D%H} zDHN;qoi&d;XQm&l1U?w!D%>d+Ox*WT|P~&EnQfWUsVJ+os{S*AV2POKrCX4(<1^8@^ATjc`Uy1j zeS{@ZPF#k18RTWuC@>lw{3B;f2plQ+WfX=CJDY-LFpQ_9^0eHmaM37u_ZDmN+Ki_3 zES_td`p{hxn0JroN+`JR1*W`<%^2OJ&=E{l>wq#L@6aN%Npfq+VMe_6y89UWcDWVv zki1?I)^ALmL4eZg0$e<=UKQ&^Ljm!(<J`*pVi_LM{q8b=Q122r^+?(khoSV_o)~)fE5%?EID~uBC?G_; zSL!v6st$Qqxe`5~3Z*pk-=gV7z(@j-4dM!$X! z>Gd1l@kTmratoQdg79P2|8oA)P&58WirSBnC2byhQScyGwgpd_QC8!m2ebbg`YLhk7e~+L*QAp}V z;43}D(Yx}Evohg~{BTq`!~B#y zD&a7KKr>hCTZ@SyaHt2=y@bxP2eErmd&5P8?t{h8&3E{{J!Hz^>A}`Depx%1@g_U* zz&K+q10a!fwz!cRVDi&uTw{n)j>L&6Q|jM~AzFR$8q+(qYb_bH`&sRY z)pcLnh!`Q$A==WYm5{crUg<;<#BEB3n*|&cD`=sxfe*Sf{io#!-qrKA?@EB1db35F zP|pj`M~Bcj)#5FBDJF|YSsN|L@;x8ala=P>2g$TsdPDlf05;*X`Uz+K{2{xt6V_70 zjg0RwQHM{p3%0e072e|F+T5DIZ$XRe@Tymbf?5}ojcyBoO?#5E`A)^sQK)?RAkKM41j zay)+$Ba{Qwicj=M1K0`8TA8Ty7{pP4wki`w27t=UInx?VOt3S|jHDQwF#X`-En_%MR`Fz8| z0$ATJ$a~;VoLt*}Q-(pIlid($vN=0h(RPm~QVcW&(_W(h>#sJ!HRhR-%6hg~PPuDb zh{DfOLGSvj*xwsqABfIXop@#D=?SQfrz@$G=vx>7!7(HDxINes8Z-B5BP5vx+!O#1 zlkIy-ALH7MjBT=)_cr>P5XL}lG1b99qAL}v_K5@LOSSwIzQ!Hv`RY>E1-MnD%*?;; zofzFjIHr#$B#Jc{`BX8R!Y1H?HZajLQCQNGv4f-&lWXR-Rgp;sPsFcr>!JxDDl7R1 zGshnzl`!ugQ(?jr+i z&<6Yv0s63nzg?m-by_3kBMRtn8&fnKn!qlbE4Za-3?Ws25XueD$T}u|_Txz{md61m z{4~}B;$UMIg?5sp&0$bmk`cZ+CaliRuWqYlE#0zrB#1!MU?-E)8zZb4 zp`5Ld#7WP#b8rMbc0H(#OM@v?N}ApgWClxuSu&!|m@=U<8z2QW5dCaD3hAWF#3fF4 z+ZLM#;&}*))`u}(QGWcC8`5`lWGo`GEB`4sXcAb= z?-tZdBzJAL%uDKVx_{JoR;;^oGhUCpWazL`b({y>(3tB?J$edJ{uFMH3Wig#s-H}i@s zaj3A99Qs|oY-I2DG^^Ykr9M{9Le6)?!f@wMyA)fiGfs`=Pvu-0Xza74izWUc;+FTJ z>~1^sdzG&aY2ImYE9wJ3N?W6;ubMyErWXH3HOR5TJgyek_m;A`P%#KB2&^fi{&^1; zY}{EBr=5fYTT&aCr5Enn5*uIkb7z6h$Yw`I)QY<$W-Agd2c4XM&-gsGPv{sWsw+w> zY~jtTdw3jOv|$7;cmD3he``!4)=p-`rFkg^~kMnmU zt4zy-`XqRnPo@2B$QrpBLZk9SnxIEyd$d3H;V+f7Bcyy!m`z_&2Qt`meag_nWDJv?hN54f(}FkO~PNdQ-8z05>nHJ7j9z^l)) zh#Z@~Z%6w*Hof4z zARTmd%>G*JO|?9084yIo5>QC6O%4xe!)ZUW9^n}nTArNSQO%gbovg1uloXt9tIYl0 zgNN78;&Qya@CwbJLUk;bBJ~WX`*)b74RK)7pJAZahNEX+nv@H3J!>#XL|VS?XV7gcLA<$%ESGj_=^^l62OZPn&+tIAotZfLSJN*R zw@>~HTF^4&+(p0SL3XCV(UKd*c5F@&&LnM?0}Uy`Vjt?_RwKuHiFy+DGz9S-&7Fa> z#mI9At6j7cx3d%P&?7G_4k`*7XElX1xuo<2aZ;`Jc&Y0MP_iRk)8K7C*`42%krJD? zyBj5d(@P4oyKqAo4~z~=Lg0Fg)PsIUCJ;u2BU`3%Kw&e>y> zZZmEyWj*wc$d&m0uRxD9!5h<*T0~lVknGJ|?{V=$?PdZK+O1}f25p2;4k+-|74nJ) z`tDC9d#bhWYJ8?^ZW43Hnv;`j+Ku(5tktVKX$LTpFn=spNDB`?7Ksz}F+(G;v?^-o zR>x~={(t${oN6zI$`@Q~PUT^jGd#{_RHGBGLnUMf=uWnYn(eRiIZz$joS5sH#6#fQus$iNO8bhEz)4o z>B;F)k&dBz&akwY3m7v^zz&Remk6Q7lBeYi z$4!FQF%`?xO zDD@#s>%Y+p)_=Z|s(jivy4(uuKQcv@xY8J2O(Sx9-f!qFSoxO~X)8@Gxk8TD`w7W7 z%0GS*)h4e<`B1c4G>!8=`t~9Z2e0O^Mw6`kU|c!=J#L|d<`@kDo2wW|d_zbDbZL1Q z!MaC0C(^}X@r9dO7P&M8iYgzM8=6&$^RgwrFCs_gq?j0x8b}2r$$+bf$E!b8P8M=ODl{W6LRd3@m_C8mQW$#rLU~2 z^xy)Y3jjVq!M{d)A6dCII)v27P5TA8D7ZW^Gg^ed7xLb%|4_x-#*q*~mAOi<481iM zbG%detB4v;2uhd5jqPEqndfRh)*GQJz4gX(7&pE7nVS~^ODk*LaJ--$;HvI>O82#9 z&ED)z$ZkO)R>Nk-7GC+^p(Gl`f7`!%xa*&_ zOu3_v=d%{KMJipE0dQ3K^(3;Uf1pye3>A|sI2wNN_T80>@WJOC&j$N$bp z&`3a>Aqf__V&bx8alq~T?cKE&(K$(5-fHx^W<#?<`-B>#J8gSQEG<~7EfdImV{$&F zEe9$>l=g>~=uQAOEL)vN_2|D*ow8~M(axq}G6vyPe~eJR`v)Sk^A#D4GYPF8&1G2l z!=?;)F{P#6?;i=dg8<)`|0A%1c)#mxX-9v>N7sn2DT7D43`lM^v=%-O#@4>S?sb68 zBG-%YhxC7{rhL^(6Mb*HRg{P1`t(X;HlCJLr{wl)c8l|@<*1gS7LH^ zB7)~KUXu#51!p|zxc=zm`cu@=}XB|3Xum_-05ne+M|brYK;(p`fCZChiH#T zrX=+Vd1wi|qmRM&yEUerTesyMk`$!LwE@l*CX>blOwZ9Pd`0dqHzT9JnR~LaU-cwF zU3oKNgEg*~aJ+JN=Gqxj(-5vt?i1DTdgSeSrqKICmPQnpFU^L9*Wdu}&7RSSP^`BA zSt`hIwn4SU_h<6q=b22NbEQmMtCkn~shd$+;#nSi%Qz}x zT5ztSMChcq8X4^tnDs?%{rh4TSqx-Mi>kvUNvrW!kuiZSRcy zU?~Gnn!~jentg6W_Jr#HT^kW?Gs|a#p>qPREc`_Q~H?7#b-?#kdi&2i{C_DxW($SIV3^F zwl{Iz{fP(3p_T#`bUqcy0-A`&!dzSV%y_4oo7dBA*y-N2_@U`P@cCa(h=I+?U!!5< zuK$w+f58A2!T|==hKlh0^+~wnkAPV%O4`+^*TWtOy}4<|%ZiVlFBPn64nJFDdu^h)6!4m1Pl^ z(A=`vQ#%j}#yTaK!wkem<5F)k1~7~uFLN}WCeOWK-2MpVvB@#@-<5vv#TFMqIq$qm z=ZPxmX0zL9ME%Y!VAAvA!(+L{yp688eH&EclJ9IYo&pjWpoXlq4x&XcR#l4x3M$l@ zU_2EM^4^bkq`ENo4$!duBgl(0tdXjpFEj43qTX*H+3O?wj-vNrZAb49$qwj4|A=P7 zxA#SDMry1nyxEO_iYYgOAo#`Z{R5>3iGU}Qt{cB zMGt{kSxD;XlzU|ZDN5@K%)^5s@62^#gF*#qoZ37hc)}c4KgfG8tUrj`D{mELAVaPd z)HGlN@tp>Z<9=c(`v?@?yOK5)yV)k}S!ecj=xor`);pfR97{D8xbp z8QkX%S}ER9_8ZNU(kYhWLfVh-~ zxuKiD)hY#>Ut!I&`+`2cm>P(Q_yHRKe;`2p?Es(oh)2uiqk z!-bnMe->)PX4lb#OG7(bpqNdS+e}ffCOTsMcO*nF6)lXV|9vrY`lc<0zin(t)?qU) zG)BjA+|r3sdwwBgU60{WhE41&3P5qTs_2t}5JbknW6qn*ob@eo^sk*Xm!oKNa1;L9 z4O|};Ow&P96e5lpVu*c!1^50*Dcj8jdKR-rCe2Seak}_ygQldniycyF@ei)#YA;;cW>!yyi!DrL3<&spNbO;|t&tMDxkCjoOo+8T_;=4A|F z_##}~-d~U)oXm9V;F==s8F21_Li4an5i#Yu*3+&-zkP4*VXAQ_l%%(8pSc5Y&wqA> zK}sZn)Qzh{SOzyn&f{nDTM`gAzjtjr;#@3bD}G!<$;O|*hlxc;}?F4kFG(hL(?OhOG9|Y ziwDyOI8Tm2O*=$ipXnqt0&D$2lwy}Rx!oibdu3|IN8F$hFZ+O2I#thI^Fv%xnLW^ z034at+Z+&+N~6Zyb-W94cxgK%4^~=|WQ*3_TGFGq8mTfSxpBD8C2lnD4fIT^`@$~| zW5W@Uyj_behiUKNyioWcn0)xEMoMXYTJfUfA&Jt6e7NKcg~tmuw{KrDG7}+f<3YZg zMN*@8H&JIgDa9P*EXLk+X&CklXlEh!iOtvMu3bW6X4?XbKbUdW+Uiv<4UuV8x@I(* z4KXABOTi7hCxOa~r|BPHuX!7^1m%qWHl^~$3Tns00xM@5M$YTK@EMQEOw+rEDD!+Y zcuwGiy4#q58?frPNYDi^oFN$5^BXXN5cG5I$i)-+xuk9MHc+JiN}gD@2ZQ0;b12qIj?{sWdiS{jnEzHWUubbbCy9{ z%(Op%NED;l|Di*{z*3nm=D-F6kjTFHae#>qs~|hcrz8lGbB>G4d1=@dukSk}(n#Tg zk;*{4SJV-*^1m@-+IPcmx*zSA0jCMi*M?q&>RS(i?6SqtQRZQg5t8bVh2VBBb9U^q zH1bu4cuqHhmi1o|Fm2qqJZ;@c$JUwhF{@__ZS5#w*508Ik~ILo5}*C^V1!xiBOB?(26jsXe?AU-W&&;TKx95p6Jac>qC%MLc!`bfV~cS6uhXld!CRsYhMl_9e+M@jA0>i z;U+qqaladI*1D0il3Fu|%*^g&Z&^e$3cF3!4y|lx-rM2vNNAYL1$KbM4Ijahh~Ww| zDHBi9MkPve)(v#?qv#yE2p~4n_!g;%_}2&|yPUBp4BG9prO@@^*JM$4gp$^Ll*Xsv zXuPB5+)usA=G7aAG(9S9XB(71>FA3X-IC4l)&idE-*|O?(2Xg&2 znDP;B%Cd>aFd2IOLznxu6D({E6=)0=v0qLw4#zVTq7eEv{S2gxnWHeks18>qn;dQ~ zJLonc!t&4yvZrSQ6g2w?A!gX)hZrHrm1jqvPz~C;Tl&GeYoM$&l~U_n{*1~Qm*pQI(6--&IJ^z$NXPOgF@WQ)hKRL zfB+);=#rQgPI^|H+S$nyL)a1=k1)c0=D?qCRIJ|tl2XQ6d3PT;%%O#0U_Xe9qYNih z?ox?VtrS<0CF7C2HmcDXsClP1gxbKYdnwcrtUM$Hk#0?_IQXHV-oQx;_Ztm^kDC1v z-ms>fR10cPE@%$7dfITX19rPh_IwX(F}l)q@t*83fbt!fwBIOoHp|U`_f>p|Nxn#b zE}#!BPoxKgxMFyGVg2@QJ+47pkvR@gPkdo6cA?tee0C@9&xAD0rP$8WhXn$Yw{7?O zX&YhyLpQ?%iW&=#>2gE z=Pg^9G9y5Ag4HnF?%s1(OU6{TC~N0X!AI4oUOU>G1QWRD$sGWDS@aqnpP>c~Z;Irg zy*dv4r&J`TGaUB-n&xf!uR!oRobFwYW;nL#VV@!v=)d*TMrAVnD*Zidms!p>Fgj|2 zYorsh!2!0ViZ=>0Z;3XkckBh7Ij&Z>XX!S#k7cM(_K7;B!-qyi<`YyjOH!DI)*?!F zMu1#A>S=%$r6D~e1+7O^K~q$zDds9M_R+*EPwa4#bm+j%ZI&I7>l?)keSQr2nrufS zwMcfiN9mH&QB4(xM19|+ro!IkrjW!q&wmV*xNE8TH_K57%;L1CWP~nSWHET1F=sD%~f%oqE#SFRePnrC?+_4Y_FNXM0VXoYoMBr#>xN4$%XH4h5Ud# zQc$#}e+ixP=cSWe_%3=Hp*~V}jF0ABP8*+A+Br&Kfx_v23Q?U}mU_(91O_p;htk2C z;l&qG!UJnAhnP+Dfk!6PnO)4O)c=7+;>2ok@GUI1*nC?(2WfSf)pNl9fp#-{xCNtn zS?75L;clrRaE6r-50<#zovPc~T9YYf=_}sixt|}h1dEQORw}D4f~3FcVV49)#nWP@ z_yzBnSR~r*6_B(*m;x8;Q(yoOK=8k=1!1(J$iFW9AJf^BG+a>HRYUWm&5vA#s?(VG z3^tpYnT$mvz-r@KGnfs;j3Sn7;tA!pS_D&72r}oe{P1sfu^$~30f}>RL}4Iflc91e zFtMARXl`wmmZVpKJ+|1jy>k^tor9(M{O;DHeul&?@tCR9y|y7TpPEomEw^zajq<9F zFJHXqtu4eYDZ8D9cP*eMvQX;dXDw9;lY6?Mu|hiY?&jbTEh9PSG?&y}XMfks_yq_S zE*8Q6OXOvovcMh*S~{fJAX1d_c-6x-)RsU6c4igOS{X<@8`mFhqm8R7JGH+y5k{b` z7}9mF@cj(kN(rdFV3nVt^lwfuVk{NEB9^8N?`4Sc;7+wx1szfMEd1R42tn?1x+7UBUoLXeVORcx#TZRHtFgRLV& zPX4)tMJ1SK%Am&?^t{Xsd%`))gBq0#Ji$G3UEvr4?dz(uhugXHCeu`jfFw8cWso3i zB0-ey_`kCHtmPXfDYK&t13X&jB=}R{6F$6BjTu~5ToihhEUMAls4hnIA0c~%Vk3UQ zVr|Fy$50wUV6Anu#&s=Qu zc^c<5VBIeu7DAmpoJldyeBx7cu_7Cnz3S>L830=mI(U<->mS+7w?forpYSPSqg$R( zcC{w|jIm|bP}!3Y)9Q1{HeGxZabs^kiyflN^%vg)vMTaLVByXIPQO836>3XbBb98b zJT}`nLg(wxf72n}>ql?pS?<5vc*?zO$f#U(IFJKkb%KBpSD=JmRt25=p#y&1j^6}^ zT`dzXWH-LZul#7#zhos@1;(=1Rps;q1o(Rgz*eh|9$h(rDe!#E?9S zxg~g*mN=t}3ZXSqa+SFpINPK5f5skUnL|$h0Kx86wa2F31iApsIqDYujdNIQ-P@r7 zG@VA~1ZX^J%z@`BXqzWSPQnYbYYv(9#vU9Bi_Sri&vlRDqjFrRE^>hNd(yj0l_(=6 z_TW%Rjd!v;MT;MJK5?j2fH$^nh$6A}n4jIIwXr7x*7Pq)0K68h8L2jsu18ID;i@OP zo+7D0U;Cvh53BGdnACLQN;yhK7G5*aYYxw;0+sU0^@8mH7tr)dxQzSi^;(#!#HC+@ zbYGA&0L0EhotyQ_J(KnCj(%R5vTpm(9j8M{bDtx8JgHMO_cT_;3)pCc;XQc=#AQ=F2rY(1xaWdlIE^TwUGZ8FYGaE_d@o9%m{TtHNpMMsgB+O zbKlhGOx!u^mLDhIM>V(lm?Xkn6Bjv@@!fimvMDI@HTlzU)VbJ#v;-vncPfkC7o&^M zj-ItK%&_hagwWs!Or{_pqs88Pvc>^$+5a}D@8P1^uz=nqkJrcrc^BlrPy<_@^fVdx zQpnK{D75_+7oSM2Tt@u~57y@kcnL~z&K7cjQhyRy=$OC?WRY;Jy^_(LwqX1d4|mqR zJ7qfN!xX(|2M8nR`@uTiCi2>?jOkP(7_QO?JVejUeoEl~TiW+tI45#|>r3;7jiTKG zD`kfv$r1T6nDo_ygU3N539m1p9oLJyoR(SmI#AL+L!fDr3+i_euRTGdXbu+9GBHxC5LDRcWscO;?UR*7O{{9P__@#$R(`>n?z z4-u=}*UgMxug}$A`O}4Zo`q-qZ5{LcTM8#15_)#R)PCs9)@OJ&0Vd_%YS(ypXupoL zB!dQ>zfMC@J)Z^zz*z5ynUPYqx{%s{;qqE?N#K?j87P1cO{q(FNN{7$*a?i+R}A0V z1RI~-8utLfR*5{Y^X<`8#Na#Peo1@3edFT6=W{@bo>xt7Lqbifov=^we9|piae0eQ zpR8x)VE+21sx^Hv8a!-m_F&?cZWJ?7NB$=MmuYaLLC0xX)RbX}PH>M+710(`YOH5xIAj!i z2b5u%4h~JvF!cBka%4;ER;Eq6v+}hVV4MM4=W(;RTBH|6vekl=U_WNQ>8T&O=LJnb zo*yWLd+Y26wl1BJxDmsSeOPt(j>8R%((Tn`dVKYFEdl)1#8+$h6_Zj$n(g9uQtuBh zydk9S$jMa|K#nXT>ySGbfPFau`ajg0OgSqX6JM1a_s;J4wOn_B`E_&YRrNx`_&*@D zBg|#89jfAES<7OYfjxlAu$e?@hA!h+2Yas3)Gl?s)1sA{(aY7zecydiW0OSYg>Ede zKk+E=v3}c0TBr3oKFtx*e`_{Gp)WIsDz2;Ga|@w=VxD{j-~eeEA~eV1wT@d?uUu?c ztMh`Skq}8S5l?G5kr9!=hqZ+slsq;E;+y>Ah>G*~Z`R!w=W{S>|EmRo;ZZi4H>v== za7y%QSuz;Fq}7;#&U)3^s?H4<4AH6>!sxh4%srdY3^+8{elMkh#ND<(bwwU{J`b@|pCK4|s8M)Xk|c6Mit8LHVa{W< zznue;c7gkX>GszQh>48Zkl7H?WF7$e;%!|wgfyI!DA%soiu6ApJwuTagl7r<)!0GD z9HdkDxHy*CNvq)*tbWgyWwQ&gq|Gb%wKL>)xsbOg{O|*k<3soe68Ts{-o(g`8B=ZJzn04ltb zkeHNwNDZ#x*x>lJw3L=)2`t9TzD@Gcpc0bS)D;?l9*?w$p~sXG+p1+GHcQ|9B$^ZN zB!(Cm6_?P**4{pH(H>1fD_9g%duUSBa;r&G<}X|W*Z*z7v|5H{{yPXS)L#C z=Nwz4hHb9FNI365eW zh8dBxzpyX9N*EXU0O2jB${OY6M#W*->q=SxLI+?uMokGIQ9kiEYp%EBcF9_sX>T?2 zYpuE2Bs=sFtukIbvP>P0H^#CaL_HG5LQzfGq1OG=p$?~P= zUT-N)XY-7A4}sf51_e!)oYp8m7lLY*$98#*q(|}CPI8{pMG#y&WspB7;Trm~F~4#N ziYH`lON`5~&t&z?^7!*43>Eu2VT@t`Nvi23-T3p;!9;RDzCUIiOmhwFf6LdH{ilTp&6%s7q>H+}sQS54bz4MJ06?$*b>_4s}FtsodyZz&Ydvo9xA zZb-O$&C;2M!x;y)le3BrYY!cbPc+-h&_?x)>pU~`cO%1*%#A%3I2e=c#^0j`-x-#? z;yx_v*U*|Gto50ZBhK;{c)4W}<)E}Lro`L#^Y%QVbsFRLcbC*Lt6F&etbxR z?1%yZlzDCh6wZMpBGAHcIN28naoFK2!8%uTl>H-jZGNg<-ZwJ$UML7=)Qaaj`ndJp%WCaSZ$CJ;KpdwV%yf853(3W$H zdWK<-z|WIEeK2o4pqx@h)%qf$1*x$1e_{vAHkfV2BoEBm%xU z;tI@CtG>iUj;2EuzD8pdAvpZ%__{8Oz!=HMU#{xH(M?wJ>n1dmx3a&x#1uGPQZ)~s zlraWc&V_An1wFQNcZw_IJ4x1!U8y^iK|l>&jK;1yP!rS5AJSA#mI)Lv?^Ehs8joI~ zI?T%7n=Zoe`(v4%`_wbKDfYd=9$HZn_)xEDB@z^AF32kqNd<(a?=Po_3HI4CS!$W4POGQN z6;!W(MB3T3;|g$Rz6(Gpb+Zi;_6|)F?W|P`NV_w=2N%3$F&2c-8Koq=0(MzW@F@7I z!68}Dfm4KPCi;n*io;f7`n@<3H`VVqkZ>gb6N4=z61=-2A&rWxL4Jfm0^5Mw*EiO^ z2v)>)sfw*Dub`iZweV{?8CwSWaD$xC!3@f8BS?hwLjs0BAk>D8=B)wEA5Z!ZvSfS) zKQAbt;I#IUG(C5O?i0A)`<5TgZzdwAMpyDA94+9oRP5v|e7{$3%ffp_Tw-4qarFVO zIfhFQ{bz{>Y&#q^+&Fu>=k2BkKmq|3gSz)!4WlWkV}gnT1gGjL;k|iSFtbwj@OC`p zD#%wo6(&qj;Jq4VIi>Gw7c=2uw6OUcwEeGp8BLwCsEA9Fs%cz7@<9k0xB7L~eZt&_9l7}9FLC++BtPe~e1GjUK7 z=(Y`HH2{MsI;b`^{^n}p0^OW*AqC?51_|sXL_0{A<=W}L&yL1kH}1ZFpSGO5zQLVO zJDqwBNhb-VPc9-orN?YL0hZCRsEjbzw0MdEKXlMYhbN)b5eyjK>#lfebF_Sz&HNV+GmR42sWm%u(Y~zTvCm07%0``X9sCM+ z`j8B^(g4g4#tb&CpZZH}?A>lf@q(u<5abPPiZ@9obHoh!y@T+DMHn2;mV^y_X9-<4W*@S{A-p$O*ptP?m+eBA2!b=G zd-TMHcTh|jKu~UpQ1Ro~)ro#)Tw zm%6U3aeg8fjnggX(HvN02`a60LUmCAL+_&|w%}!L18ae#+umc7%gI8WudmC4K^QR# z7$Lfo`h|ax6&4_0+(fzfGMjVU`SuprIdK5%Y7@_zAHvh6`A3_bGBnXPf=7ZFi^g{Z zY|H3v1g#RL2+@k7(tBlrH!!D8_ey;_N1hQ=FC^VK;riWYprfyP>9D}%GcviN^|$Ui z%tv9A2|kz?02ccHm4uL{n39wzaoFYP5Arm#A0X-O+JB<34F~7xkeDA3vLnWbC^p@{ zHw|dvEmy3OtVR}LR8*5Yhd)=lcwOIekiEp2)yR^ooYG9~GZk)_^YWQ~ND|*ghjI;zP9dgGgvy)_&D%p1^Ns^;t3OGLZgq_8Nj5lKed}N&A=W{% zy@pt6YL}oNhjp{v19ZMr|49P>H9&hdzZ^Q9)(csij-DykT7ugVd3Nsyh-q7y9ck-f z)|!R)pkp^{i)N}4xVyQQ8au$<={|elZU;(ezne+-gjl27M74;ftRa$YEMMoJr?a|b zmH_Ith_rOPjqcGcJS*MX6K~!e8O!>Y{?3ec%i^N}dKBM&W%I|3`&%?{Nkw+Oz^^KEVadzh_ z0y*^phuC1b2R7@-e=R*emzYc1fm|()_z3@^lF^kHsZZIa79!fb$b6@?HSM8?NUxhS z8jsjTWSzlztjHePMebWJ!$eZzH3oOJjEQXuRyA%@nWpSpisWOZ=n=v{nzj;522n>G zh|Yr#Y1ZeXX$HEGqyapkGX&`2w>D@5 zhDA$OQ(@Dn)h_tNuZU}b+b0365Tbu+l4}9oFG9uaATIH0_UeZ~xygsvwnwoiI~l%5 z8tagc76$n2$!0$I5y9*%HW2nT?pW0&>dy`MP=4TgjOX6XA6*~aCBKTY#wIEBXIr_a zsp8#nvW<;SqgBUKHtKm|o2}sYdG*u~V^`+V6^N%ixQ_G2NNEPX*cWbw^qE*J5lU>j z+@l^=au;ox1ugX!6-V1>5kqLL7*Fz<;DzwME=#3B5rG!SiIB>w+|MI*gaCZZ z^e;+o^ddJ+f|7{dM{AKC=L-X0ISUFDi$YY=4?GPtM|gP^kbdV6s{B7BO`$pAoDsJN zF`lL%)sOi*)*6!F?gK_wy``#1k^!+hNHuE5=wD#=t#MixCh{w^U^9GBlwRsdVyXvG z;;^bk)+e^^cQ+Yg6O${@I5Fv88v)%g@!Fx_Mdd5@6vD3sRE)7K{EoGX0q6V(*SxBD ztY0Rjz+n2$%I?Etecg!MK-O;7XI9Xg!RNVqvZD=!(*~=X@|LmeJtikCE8^!An#88_ zvuiw-Qjn4XAjdlp#v+#B&^IylD)LTUb_ZmO_QFauo#pRp#+rYNQGv)6H zU2@b}i-grNh{8@L?-UE}5O&U{Lm6Dj1;c?|1tT(;5sw)OoaBD`Z?W#C5?~pU4gGm= zPd)FB7rMjXU*)qqN^C?N2okdFbVyx1#KZg$)dWEL(7xEn6t&HWSk$7Vb^$H9B1?aM z+9K<6uG}w{=-p`i>4Mzn3G7dOVjl$cy%o%xUEU{xUn)l&WPDSf;rJZ+#t&a!(jo`u zO-zey^WohSrg7$(Re|R|(!!c#PcJsMbSnQHxd)v>y$hK=k;A+rscU#b&?!Mpc6&rO zruR2-jg1C1?c{T{Kl1Qykn(FdjW`NoKw&VC2 z+*aa#B1YqSY5*vEPm;rk3YB>Ul-Vv|W%vsPhatUQ&Jg#jXU|y_-`NNRmS~J{#nG~q zvLR4)pSS*bC25C1h_#oEKlLuF!wlRq@$=UlaoM@mrEQ*eJa`di2$FbS`!yG!FLrYBDn2q=tf^N#K;FC@pMxfKX-~iRX5|g zBAQ|ye22w}7MHc>zegEG*8sziX1(Xiy$QPdX>gu0BN;NRtJM3v=x^w)UBAnCzsCys zXC+sYe0C3?q_kwrxTw49n3F`VKNX)CVvb%zvlQa>HUhN14_OY+j>8@}Up1&!Asy?)p6VCtiH=ESel9W<36UmXK^LhmaXyo-38=YcX#!Z4)Iz2U>WZFqvJA7yO_j`0>V}4+ERio}7jlF{5#DPC0(lAxqkOmmZw^Ry|mHl+1Nu!+^nuOj-;r0K!NZ$zGYvceOYXQ$5on zS!)aO>fCPhEUO9RM+FD%uB6ueFhwo^2cX&-zSf6VID(GhrW3b}r$wfRzR_?tWc3sq zIKhm>W@(%PR(bF%K;zm}Z>XfVTfPJ1zA zEh!4%jFs`>*I?z$gsz#le-PPVA0{3kNb{jrw^{~(i1%G1!{3$wU6;H^dizcENsUPj z!n$PNxDe4HLk%KMevF_TdoKmXs7Ahk+@&DB>l}yR;qg0AeEO<*k_IE#p5V?0=tqWu zy%*;(=z)m=qLNu}cd+Zz`xIIDa-uS7f*%Ib?PziyI@%ue(No(*S&IcDwx4%hk!MaW zKgVJi$iM=m{)?*-SX|WR={mXyXb@EO{(7TQf zC|3>#t=$Ox(`*)*{WQobh;qV_hEhYW>|LdKXG&8-g3WOYsT393gt+_eSZleH~6*(-2@kyps|$be2eX zy2Z0YonB!(E>L!~Tqqi-#wq=?{48-@SF;E@Qm`(+Q3V4>8tgy~9DT(vu9d-u%TQ5X=L4GSsrPJ<9PWD8+q^|!izZQ5o)bB?B&5^ zYfu}eVcOM0R07201W~;ABli;95d)M37y5Fy-rZOWBmeTpD zHG)4rSNI-=rsq^D4zWO_>iv#lt@0N&gcHaB_Q5gUPkf8@Tcpgwlxh83ZaSCT>JDa4nD~?+wB7kO_WxkQo+Qo8ZOwaR3_qOJ8 zP5kd~pHUD+sz;PyQh<(KlZVrwP);c_FR~HA`j?7QJ0C{0IhKG48Ftyhaq=fY58w%Z z)G(wNEB!9sQ4O}hfkd>6>*ixM_g;DD6Dr}xK6wor66E%<{d|kOc^WhSz5MH#Y;K_P zC8WCQil{W^!hse|=!6J_3G^}Y5M!2y`Iz{jl-thK4~1(nlA}Le&(&_wn)Z@3bIWYN zVq)@(s-vyQVHNV6pX_0h>F*0I7^_c)GARpzfaQ>y__5D!*{TN+`Pwk3;8yWJGRBE@ z7$BHjvGT$JB`{zjM?4~(TH*OyVg(if{6p+7!%;*6dr)fki#G~`M9EpQ))EC#g2mN& zmV7>g>}T5=FIZ1t0@D8Oia@_Q`QNaz!sh72!ao2G5Z;=i{>%hhE7CWy9OP~FGWo{5 zY-Vb^^1{j$T%YY1O$a-;X>)v8W&%3a}) zjlhJo%{GijMU1l~miD$%wPd*cv`2aU6ZWfbyQa$p#Dx_aTrryhqL5S)h7y$t=MZMq z_MIlU3u*wnSHK98z1IB@%p9`pVx>89vV{d1>@XIaVY=x@8kzvN!AqZw=>gF7?mP6= zbag5HNP%zwbJ#L(Xcm0Wh56oF;dQeAHqh{9nJnEZuN~f?lRCjm^WyJwnPL_7)RB)(%Yf^wN3?(K?K!~5E*^^KD9D&SEYMKn+9U% z4>zgFPvHsK`(6MUAj2at-tbZKAufZm+CLa++kiZZ44PN4$CME!_3CDJ;~I`HO0@FqjWN(`j}?p6!6 zhePPyjh~*q4&b&eEBv&!VNsVu4G5C)Y?jKd9tqi8WT@U7-wDq>A+1Ci;?yp4zkrh7 zTI-1UFAds@kzHJZRr>g;y#@_`BXpTHk=;xKF4GqE`0<}+D{}9HYVfu)t|oEaq;cN| zF@x*#r>X$_ZB8fzL<83*&jj{x<4}>slNj#+ZtJ0H-X?4g%F(aE7oc&H#HlC7iuUM( z!1n>&fN!FAM)biYed$nPcPs|-n8fF(L@Pzr1RJt^17k5~h3`?v3tFOAZzt=-;Pi(Z zXOKY|DSZ#Cm){P!UqS1t{G37OF|*G(N}6S!0+tVaI%1zFY?Iw_U3pNCV1;n6880aX zQ*Q9xuOY+!yW)CCL`g6}sE)nYXFWiVtxRoo^1DrGRT|Go$7jWYhV?54*r#k82yqqv z{fKIpTHy@0VB2Vvou}o2ce1QIguQWoFP}ezAf(qDq)8L;u-8PpP&~^~993!b5F5RB zx5xZ%p-N6i@Gn+4uD5_Od65BsK#sN|gk!b$Zg5i-@P;$_@Vk_&GbvFOnvB?zx+5Hu z9O^OlqUK$f9~xyR6yYtTej-;`zp3xItoHye>xawXdQrPhW!`zvR(vKsAnmHzYdlM{ z4}Ts})^oL&Gt_LGZi9zq3dMlSIsk`XT8@iswLq!#j1u?CnJ2tl+o!eRmM{35`9zy} z>mR}|*QY!nUFR#t)dgk*QN0=kb`oi(Ov5!B#DesCmePo>$z|E1UqHg+A51a5Nwy=n zT9>I>k_kNix7voeD_o8I3)PA>0p3GH=y?viEgHwJi3L8y&aFccUT4)!>JB&OQ0GlJ z)gEy*XBU{z7j!#&`)CJ>`o4K!_1(0iqBIHaIrP$leOh?bii)4W@*^{T8f&4|C>`M` zPELVyz|v=w{LPK#EXH3#E`1k3fb#FQYqDXeeCSVWfP4&`?j8Xb7j+Np{EuWB@ zayhorDudE-k-p!1o#r22X>~;1hgzn_QGtbV6GI%FkYgmxLjN_D z81aqWc`p~miVqz92rsFj@KV_mxpmYBhN7_zN@=80n7&mvt!`dK9!(rBiJd{eX8>0r%d#(1(&_sO zPxW|wFGwDb^}xrV$ox@WCmr1(f@Rr=)G`V!W%fqiBO?w!R#zLSC%B%WXAI)o9w`)* zn@W-^xGc_vx_K*i-K8jm>IT|;AHfmKP!i;!QGQ%{hkmlhP5wv2f(NfNNMpj^P1GU4 zzxBFqdXf$Wx(a%==ZByBCO3*uT5vDDc@lR^@5rY>5{W?jS;#t-2*X4+cNn2{nLce= z46s~}r&6z7Dl7;s`Vurtfe6Zc4n?*9hVNJWrYa^$i)JdgRNmkeqLb#oGWb3TMTNt> zHW9I!nEMp8@k78$q!r@-Tni#g?%F$jL9x!=^;Qt^Bh|$V?4H~s{TDBq_41vk8=1k1 zuB|aUo&Dmgy*Xk!7{jPitr;9xrs!aH7jxJgYs#ImFe z%@(8XXturGKiVjtVE61J_#|ZgLj^-O{gfiB(*j6SQNn|zXTkf10E06;*$zj;bqbTu54<8)CRLy8zD55c=?H`XO7 z!V`DLSa4EK5H5BNjhJNH(e|%oYdCK~RCmN&$I8=AOExDh<$;D)+urXlY^q1rCLCv< z^-&XrC7*zs{+(ws&rm=SkP{jB#Em=x$WX%8a{-_o=x&<;JfY(;V3A>`mF90gBQjrg zlX|tUIb*xo!aE-FVn0Y{aQh7zHYD$iB8V%jM<^)~aM~bXNf{jrKn;!B^LT@* zR3Ie66ow%!kJ&BqHZ%HJb;t(d{T<*508Ik~MLYzz=m1{1n-&XQ`LwZbQx4TUjPqe_t@BVGhnhF>eTU z9{_YS%8ar5t@N!uaWJm9&_=t;SKq{*#pXbNFpPclp+GX*o;^9WV4g~~L`&=IxUOV! zFLGL^kB`;XJ9!JaQe|D`ee@>w{~E$DDIW^`1`spB&8mnk%R^D$Jv1a58xaMB*QU&A z=0Ly%<=gU{{$x(v z$3jW*;1UDkYh)i-0SgO);K{L*ILni86sk;%nfi1S4jNp2Pa6xzA$`m%ihz*=tkq1R*Pawm8Xn% zt3LP%DbBLMkMCtnY(4jElT!Tqg^D+ArCDB*T-KkHmulVYFHPR`b1yyh6(yA^0@1Us zP@uY&Way5wx@od+4#Rn*7fL9eeF6f)s!~I0DS=6V20l|9LpRwIs(_d9?roTjN|~2v z7&=>liA}XytmT!_HiXC{bdIxTAx_~kror~cxrds@o(QKdcElYue;lfmD7ovQY>fag zD%umg@Sp2Ql$=J(ZEN_%ty?&TcMBc0Z;p^fgswtNuOuhRs^fXo;O;52?jYC|aEZzb z21MEyHU{(uP0cTTG%+g zR{zPS_F1^xYC?XEr3TwFRejr_{S`RD!GcJ_bbs?26T&h3ES+2$YB9cT%rThIf-uaV zzsv5iyl|r*4c(v;5=VDkoW+p^)8VxtXy`T7MKr|6pbwRy2kWd>xA(QuoKg|I-gj>0 zvU4ZtXRyUCT)}4KROwL)75;#Or#%pGLj*=rU+O-mY)NE)HP?FB+bO^mn~17^;P!7N z_&8vS^j>+v7^3OSWqAeHo>J*;WT-uoUP<&hE4NGj(^PsE>ozOKaH?VrB3T2RyN8e% z(v;6e?6?NU7N<(t;b=gm{4)kVeRM(f0KN#R;|^3iMMotKu#xShbHLwAagUlTeXWB7Vjp9BzhAA8VmQfoi_xqD>S90M9^J$esIqu1_VG(ZT!i6H*)9dAi zOH+ZryDYkk_6E161*@cix?L}C-8>FK%*uwKnFw{H@rrxN;l;hlGWXG3W6CjD9 z)?H-F#>9K#Kb18gHj;dAl?|QRT?O*`dS2x(>q26Q)=V6v5bAa@&+r$?(&-TZH4F0v zbjMr5r64DVkM&#r=r~l<} z1cqVmkNnSTj-H_%zM_ypkZ?`o{8t`I^N3#2jlqh?_HsMZD8_9>sVqyZE-V)^0;OYZ z3AXqANDpyxDfimQANWSqn-VY^`p-;{G<56k^d!%wfsQrb%l_@P0OAoq152b2kw)Y| zX&dxGQtp?xw2C|y^!=F{n40Ymoe>_&2%vBtcfvu^sp0x!%w)^vatrcwWbmA_wcClP zYs}z*?1g~1XV3~h`=Dv|O{Wno5Q6gG+B^op=+5o>B&}(PBy2@+a)1fHG)4_n%LwM=_w zf@)dI1;nJ8>W|?DcMLHt!V~Jp=YU{R!2n939uz`%OgD(a^47>ni2~!R+Z3MKQ~z=0 zd|ql7imy&qx^1nvmmz-r`@reF3=aWJBCR(<@#TdZa0)uxyx)vaEoiE{@Y5p|NIaj% zfGClc!3J%PUqqz$-RN&PcVb~bgfw$F3Sp;C84#A?m14{n?!5?B|P=1t^J_I39%K#6Nr)iV2#oz&SAOlpl2yN2u-Vk zPsEL(F!uhhlJpq}ilT3}`)Xh)yZwHfaWp*_uSUcIxE+-VZS-OYhIHYhz_BlXEKNeY z<7ICVrbRAj=X328cDR@odROJ>QwIy6f8Gn?f~c{+WSM56(O5$a{{XhwVfT4ra_6{vNC-*mRC>y9E3WnH=+x;X^2$Hc zX@;>oc0#_1VE(XpwOEy@MIPxYI4}d?Cv*c|8Gax#8)gGqh{py9-6~GD1vc@xN_?qf zYwsRqCE1q})^odLvH9PW<+ALCq0PUq81?TgwWnQ*9gd zwPldyUgHcBHZH}OSoWfNj(bxE{X_cij63g)eM6QrvP4+x>M*7l!T@>=g zPx=ueJAR1a@XM&g-WgxcGZRy|16ku7CJ_U2L`E0)BbpDwKv$#z2T%;`nQL4Ep48q8 z6uNAT)!}j2n{jA?$*!FSwjDP|iE>X_0O8OrrRy-*Yfe8@2f0Q7g5(_oz+2D~dR-^D$~M0g>&&_#@w|vb7{Q`p;D(+aSXXxjs2<@d<%`f2_~oeE z;nnsFJPXXGc#7SK_%xtKP=t`Qo?dhOH#@Ya-KCJebuES?CwP<{DafT4k`Jn^>1FSp!bFvN%S_ijz-&TRpO=U|NbWKw*EG{Nr)jr_hRIV_pI7UCwX-7!Tsjy=#wPOBfNB&Zx}iPG4L$tb z1F;2u)8CbUUMM~dbG9pu%y;7&tC+*Of2vnSGM#D8?X=wn^iA_hxT3Brj~Yz7sK^6` zxH)^_UIq9b9&8K$)B-Slf`nzn)M%A?dL}NA(aTU~A(VBs4UiMs z*rgrY#tjrWT@z;V%T==Pk#hy(6v`}s&YuIgxmlEqtg91IazGs9HS56Fh{Gq3t>T$U z=QPeV)3LcIu7-gMu%0J}v9k66XXm$O)QxpjthY z^l&726EKnF-Kh5WA4c*+G~<`HsI(VoAQWtyFd+F|80UKo0B-6K1xh5)8pCcM@P9e? zVTRyQuuSlnBauHS5sstbn&tBTSB&}UmyBbB#5o*aT62S9QxqNEzqZ05(Iq0y7$2IX z>s#r;0@hw8t%iq3h06Lj=d-9@mA@kGDj168pK}Lkp5R~tIl(Nh3@H595m%$);V=O?IdSd z-`ZXiVHe?KX<-1T`2GRSvaTcB8{=q_fK}tD2&X1@maAaPMuX#VK z+)@QTJq*?N1E^zN#uB;qd9A2+=76FevA~rtCE1GGPONV*O$k5nr{f~y(V_9hr>8Fz zbW9IVnm^pv+*7Vrs4q-52RCdB{C8|YXP%L>0!QkVNNKa1e|D&wgI;l*n3}4%c0IPN z91nE+8{^UZ5qoIB&uJ~wjeb-)6vrQ}gLi>)1HfJ7_K^P-IwXn?7>2MWYck@9jpMfT z)w7HEan;p}@i$UbiwIQBM`00wvG2J{t%{jyzCa@DtmRgs2-fv z=pfGA>I>7gc9D|fPYPjIxN;JoFF}CS+Y(<)(A429iiN8P>L-oB-OBZwXSxX@j|DBX zs-ZL#1n?%sN%AB)c+uC@UH^0CTkC-GpKgt6!mf@{<{wR88fDc8-F7u1G|vX6HM^|ct=Y#0WVIbRwJ)!c}sJnApYxe zGG#Q8_pafrOnN*)Y}-t%oZ9F5n$)ueYQTqns>+xLL4FbIjHvCU zGvR7k+nZS@Nzr8{iK*#8gNSC!0R@4wSc^yX>UVrvHC}T70T-Sj%=ecMj%vUF5J2z0 zRuxojxKp8Sm?CiCDbwpEzMcLh4SK3SW~HN;ZSuXReSfSqB7t4z3;D`}!P67 zikF-6^b~*g%<*D;L`u|R#!?%=-&NbhXrzI(Xg6xDPQmPZAw=R6eR$y6disc6i-g%7 zhC5T<4#RD(x0jTgAfeaL`ajCM$G*vhy0>$!!WiTJ=!ODBwYk@-0G5%mkK(1Y;TDN# z{0G<`)n0sOA3i+WA+ENm*JsQh3Y3eIz-N}}LdcH#XBeO?qFG2W_&D!wjOWpu-e!X! zF5i>POato#tIt*4e%Vgckis1X4|cT&#`=k z4c|r!L3v>A37k+}U+u9Jo^#9@>OlkSZ))Wt=U?Q6;sc64LUsuj0(98VDcYeVBpov0 zWaA!rK}!_wDd1D-&M=Eo%hrnzJRqdvAh@@(Ehwo$`?mT1l5F~UH;2rW>LHly4&qmqLj>^of$rYyHTtwXOY?}};$)G>7fqLKwlHHH*UHyBG zEk<~NiOZab?5R20WX(taBqVB3Cas)oxOHbCPc&ObfJ(*l)1Z<%v&WFw)#DLknNN#G zb*h$@e2p0lerwOyM3FfYeGL3hNI6~HP^BUltq(LXOUxOWOt9ZJ=|Va$mHT;sNU#)@ ziZ2&QgLxa5bKRxCbxM@dDIt6nAvGaheR*#X1Po(ox{H{T(vfr=Trux$`_&{OzN)8^ zy-T&EZ3-v40Hdc)Aa5ikEHsm*GR!{&-l@T4$?4_T@=>;t2_M3#xK#Q#iYiwIA9;c% zB*gZ_aF%FyqzHF9_|W*@?vle4$>)L88>k1^IydRJNeu&D7hxI=MvGLLHs&R!$unqj zUP_gtM9Y#>XuS@2vFc;+vSsHGEYS-{_VQ0E`M$oubZ~??$RQ9|!w*4$H)5kf zRVv_6m|G@z3Y|9g6@W@I$Tt@|M`rC#Zd=$pg9UhSwg}yG0M6=T^FR2tZcZAXqi4gK z$r8zcm*#ZpkpHkw8F&t0*M+FIOXUfzve#1i4VlX8f~Pv!6Q2^(W zoXaGgi|G`|a&488d3{Fd@O;gfUG+tbdmU3SapSFN3nc3L(`k6i*}FnLR^GCTAXi8` zcaS0nIY}xwd47aXJTO&nNP$xxhi-N)m$&SeR|Y8-aa2P5=)oiW%mD)SO!(5~oYMQu z29U$;mT8zDtklXsuK94j+g$hMY@(hnxbOkTMc$L5sc*R#x1K2Y*&QxfxJCTyqoivA zqcN`UX704plf2vYI+{*F!3PB819pIvLjhJ{NQEGDxe%|EDEddp(soIT!JcAxJ{=TA z6TrdOpaLSJG#8*hG>K!yEB^040Zf_V^2xT(C@uHnN=(WTwCdg2Oh(=xElj!5??NAUtg< z3L9R62L>{W5MMzUaSmgXpfBmaB|J?CPZoMP1lASYJ!d5eaHC3`Qh^8JpWkaP-~To3 zVD_k`K7RGCee;oAdEQNPwZGu43u!A(b!Uf4TZ zo|}=x7|N_9qvTAw>*>t)I6rrm1XB9qJ*0-zCtQ-n$*}ZHMrD{~OsSdl8bM^@Q^;~| zy8%y>=FG*WXXsa$(+Ox&WqUVjm|@m`Ad=PRtQe}N;TDGj%iH*S0Pz@I?mRWlxZ5Bd zrktU#^Vy;zi4;2S*6w(?li9k7OTX>1-c^L6N(%-RVx_Rrsq@LQ!u=E_MlsfYbqH*?#Q$x_;FqMaUzouH zNX(*qK0WEL6ae^eb2{@a&R5=340rZauw9zdE+yGhRs5NI{#DLU@eg^2L(sa-pkWE9 zZ@Rc_RN~*0bA$&?C}IpZ2AABaVBknnU(=UvjM-9Bzqh`Oe=`b21G;Ud{X`D0RwVj% ze#;;zt{K*ilUQUrl>kzyBbtj_1pk05&r-Z7YCs~wF}_;a{lRxAd_Sm?zNguAdG zaCnsKaBy;c_Rn9E!cOZfOC-vS_{Kj+d;~LS#y`U|h^`DEF2Fkg`Iu;Kur&T{rzrY9 z`vF`)5+2i~(%F`mE!R3hD44UvDw*Pxzb!+W_4%TkX% z`j|KX6T~f<4Hw?pG@99h@xF&~lpCpSIt4Dgv{xvZw}QkNwaSWV`xM zv`Gs3^NHRj?*Cr+dhW6$nNcS^f};ikT~yDlFkHcRGg#AbA-CQd?oBVxKT3!Z^8CXs z-Arc0Diez9CJGp@ETuR>*bNh-pS(-{iDwYaPbeNilfS1IX{`{jK@ivd7w1&ca<}`x z7B45fEyAd{eIC@Tz)oK%OE}^hOV4Utl{t5nFg3@5b~Eem%9l~D?Mx|d68SGj`|BTk zm6Ly47XxhXieU_LsZr*iT`#0d}96`cjN-uMev-mw zBt!AJ%Qe0$&Fry0i+$sP@ZvSm2BmeHsjK2SrF?TX$_2vO`)|aUu!R}sLQj}aE~nzi zI?n~8;~n(i&x3t|dO2Vy&UH%L@!wQ~G`pc{Uq1OoteupmEf9MWeIq4x=5j`NqDu`n zCZ6LuJVIE88dw?-?+{0LsI`mwj|2#;gkMyPo>koot!;7FRjdi}3I6};6cO-J)-HYh zTae;La{wRs)3}d3hmxYJIb~@c1?Boz`D!%`f1tG(#5h7%sFq?v5}pyqvUR#2qU82Mg1FJR=F9^w_G8?9!(c5LZznaOk%?JO_6$8ycR;!3%yxnaPya0#W1L1ZLG&ZN2 z^2}&D^OZl?W7LdAG0gMmbnGJ-32J!| zpf9t70^E0W)8)`V`2>vKQFc9qwOg93u?fY3&xkSZLa{N4Czk$BpKjoB{y>{NkA|XX z;@rOQ5;9p4M2fUy)IzKI|UBAtj8_7R1F{{`v zFF(V)UdiFnx<6lioFo=94Y_VDtuuQwIU7_wI~BzFP_H(|*t@-V%5N4bG`B1h0F%-^_Ec!HkT5bv@IxLK&V ze$ib7j7#?RK2q#t3S1{_+h`G2GzVW13tG*6DQE?@D%{7?l!txoiiN3uE2s06dSZxC z{wM6Ml1w=Qo}`mIZ@PlPRbCGSbJe(`FS0Xdr<|N8oKs5XGETX5snCn-ZLer$;H+fS zdif>`(`x-8bE5@%^FGhmVtwA(=Ezpw?PTVC?Ldt(dY znOQ_CUU7$GnEQ=0w@!a?T6Y6L#Jiy(xHh1}o_NCBgpL5^Q*slM1+|-?`10%5Lf7Ls zL=8cf6A5U7L6#;P&iIa9a-I`Mw%`f1@ecC-URb5+&8|R7|IY63Uqmx4Gv^3gRaD-O zgPXZZiWC1NW4&kDL1f3k#P)cF2Kuapz!vg8^6yWIXQanSvyO}6gpvfmxOfO|$W3^E zz6R4v`AoxTeqX&*$6&Pj5<6Kb8CLwwz2@>I0dO6#q-VWzwxHuD3xR;;0=V+!)4Q(+ zY5SBGG=Vyz9uofv{@M0xFr^B^w{&!>ES$InCWMFUrt!2!880Oc47MI8tl9?^ZSwT4 zg7tje(;hv@LeQ70RogKCQGfv>n?Do3{(9YlrM#KPKtp^17q*{a6=V4w# zyr^Z(Ho!Ah#N{GvX~^6+f!)XH4b+d=2mhp&1yIr=cnzhA5V7i!6WnUfMG{M2r*ch#b z5-f5Db+a(tR_z+>wU%g+5X{irnY9?1jy2*@^2!+pav)3Y6nTgsFLXtLTvo(~{W8#g z`%lgPecxDoF2L-|Vg2%VBMo2$7??a0A9T7Kyg^Hx*E$GWow{tuD!X&|*J!lfub5uo zt-g&lF_0M0ulDt+A3oh=dfW&pwh1d;*<_ssLuWJE({AcVGh;zl&S<6Ug8YX80~Dp0 z`#ODN+v87g9s;;f_BWwxSbXz~&*c$-h8Yc9r9qEKp0{@k=X)c^ZJ1Re8k-Q!N#IHC zg37K)Vo)D(BclzQbA@mIU@yGsam&c7f?#y6I3)J)%a@I7NEp`W~{F*vB0K}5gAXjWBtLUF_``&v> zse>XREN}}2B+W()Qu6C$PXVMB^;@=5cV728M)$hCqotprewaUJQssMVvp#f5j8Sz0 z?Qz^R$(gF zfNYtKuB|ak%B+%sIc;IIa#q+2adz5paR$NgS=XQy+pS|AK z+J86j1xWz_^jrz6s#)j(8L$@UL~JY&dZ-^$kvbW!K;Z5ViyY1PJZ@J!3KasKJaE=r zR`ACHrVFkF%mIj)f*VTAByd{Jfe+UnzfUTIZo%ecrQW+LX&5mqe2c>A# zM1i~uNr5G_>jQvTR5Nim%}cn)xcM{h<>wiJ0CEegk3$^0Xdv2P)yc(}QyM=>3t2ri zE=k${WWWb>GJTnPZ22HjTws|4JFjZB4|wh@TM)qC+WQ)=VeVaD_9~%-keLm!)hRbIe zE&HvXLjbL84(te)-oHR3#HZ;XaOjBYv@7gLj2oGIZ060XO(pI)bA_C@u5>4?EUWp@ z=*<h zI@9&T2=k?nZe(`Yw3M**DYTfsR-OFaG1nPnWaE(G=3Z+&l_6Inzl^6Daq*kc>uYiX z^T?5O4I4Xxt~2eUIXGjvAltWt5S@xs4N%GC)+>uBWE2T_lC*?OOhTS_L5w+V%gX5y zTYa8Kr8e2f&CP#B>y8t?SZ;0@n}f}r5-{#v|GeRdP<27lc~M&(VeQ{PP*@P@{CDlX zh>7EU4qaPz4BLYf;~!G-XTBu)X1P#PqiH%$YhawOa_kAdtTPr*sn?Mkn(eWnUXiZg z*>jM|ohJAFc;E3=1FY~m`s-?M>06+Ko#3oZcf^6jv$0N?Pb$9BQ+0^n1L^b8S@eh2 zCqY;s*m`9>HN@^j&KJ0W6v~9YfI|uSek1MMqt$+Q(R-f%FH%qHffNZ4Ve}vnTTr+K z1NN>@EHOG?=&EXx!@B^)+2C?4Z1y(e8bE7LT8_-;8;I67<;hIDrZ6@BW5!>DX2xY9 z{b(7`5S8V+TL#gFS~sZj#Za`2$uFkqiKcg!&UP@(_m>Pa2GFEDjBJWL6w+%)YC+tA`x2ye0HPG!AJT zNj>yR!+xfGsN=jmJR#=!J{zWW1JIQD?(_RIUY(D|Meke3Hwpo{St$Ogn%3ozXPztn z6A^}E%jmrF`7&?H)IN+m&G5KKmtVa}Ei%9vBhhy~+sQ?$^uS6{Z%<$5yOzP(HnBBWZqdO-|ItYIvQ~pqCoN{Hv&!| zNWjt3SA|yIOJ(JY`8=iviK0oE=9=8o!xn+6UhEQPKO>V4$4Tr_dyjxSpjnV2cM7pX zLvIc5_=xSd_6M7G^&QOdE{$3U6B8d9gK5Ewkicar9+)R4^bf@U>9Ti2f3wmFJUF6w zR7>iR;UJ*Yx~I0?UOW~j=5Lfwaojr6J-)D1KlV~X$r7sUt9(T_E67(*6h#PD#b=F0 z;HDf$BZgK`CJ@1AeV*Tk4}0`iH3wcoJXa2&l!Il~OjW|e?>!3c?W~&`O4(6~5AG=P z6t{mVx?bbCe5CZ?5O5sdK3X1S7AHzLK59Qd7DRyt1f-@^4pVMxUo>(ho1YwyI~#WW z{n+J6s-s;4@(q28E}AxwHOQaR{Vm#|zKlSPt04Se!j17{5h{rU&!1X(AMxlL_}_D~ z%m}hj{;-_xjLYt{32v}P5pez2s|7$Z#<=J}6hwv4Qdz@N#Mog>PH~cxre8fPA6p=aqIc6MC1mi+Un<}*@PMejy4KN}u zjYEGwg|6sn#awB(>}u+G)neG;5MgO2zX~?5;KC1OO~NT_=QusiDsX1VZ$V37a9i#ww+SOmhuPm zp&)%6-AFWTY)R|5Vk(x zRoMFA?Ws%DzJ{}~=P{cFLMxzUwi}G;W`w`RJQ~3a|5r$_qF;d9_)wi`Pi{x(vB>xw z3Vf~{siZx)<7L%mLeKZ_Xcn3wBs$}83fQMWb%-En9`je+1mR^|bQXQa%~H;Iw+;<# zLEG8SKjwL$Ut@tG9|}Q)bOmGC)e;Q#I`{R#EE)Dq5GXTQ8mbLQ9Xqvg0f2By6oTA4 z50rnS8_Z)MizMmmQRj5w+F?|-G%=X++2ZU9sWhAez!M{Jbzi0xudY8swu>PSh9p$f zwK}!#$y>|>qgJ(?bZ`LIDb6(r+Qy8PS#RMfnw&(r& ziF6YSU2Su`r&6G_=G_rpW!fLo9TY>5Hk+JAXrMRP!93F>W{LmR&ebrJyXDYZ`gc-K zp|HUeUjkX@fR7-~XFb{elEpazPSCM&t<&3oODM0!^Mk50`sv>vO2qfr)g?BZYDiRl| z09hMv#ii47R)d!oPSa)xp2E_o3VN#^%f1aJv|DMe&AoRR&k#CG+FbFQyLm*94uq?H z;7GIk<$YiU>hJhxut6u>S-ggIJ@qnzt*9~IiHpu##?aLK9Tig1_I1p$h=$iSh5d2!sV*4DNoV0}2^i28ZUNCyq0Og9s($isG?bRlMu zs%3P=Mg+xMIPgSh?@AaiOx9-AYh}&YA5WNje)`4zOq%R1KkGS{_$`B&(w zvRGX-x?9DI>BCkwwVgR<^b*DN3S`i#0ETV4X&;F4<{(Oht7M-XfJ4!F=G#*Sf-hJ^ zdfMzaA(8L$jT6<2EZ8wlrxX^0D_MfcUj{g!bqZVd?KSfQ+JlNElH@@ZdanQ)Jw59g zYo7ttZncX@qL8Phdq`Mc17tY36Cq-tb2T4!sgm)0#Fdej-6pKJDzl5Fq(J@JB|ok} z))Ln-4;p>@{+(@f7{+%=Dtxxn7H82>vS>ZG={Wd}Cc7h4dM@{;J)eRB}l-esZ>Gqr6Ws{%#`^UKsDeO4pR3;vUT;pv4xlJvt0$RC{ZF7qJNUO zZF7^XT+hI`Cyd&@=jN~o1rk%UL_A}$b{SDy7Jmi31`uaYo1x>y@lhxM9)?e6^D2w^g_v^9;dKQbd#7vKDvTT(>UWSo~w2**St#>wBOh5H> z+Yn{0`0L&SG-PgJEG~b$8VHCObAiuG%Xvk##JT95WUQJSck=I_+5K9_%O$(q zL1rD_DPQG`eA6$M)8*|?chmF)T)=U@u?iBp+t>_st=^WWQ|X{Gemh-T>K$;8po|Xi zz*Z3{hmf(oqC8&T1@wPzWUP~+qA+eX6l8(|!5Howal%gai#aUby2c+O2@>Q!--?M) zu4U<*?El#o*18E%%Cn2WJ6b0>pG1eBTfM1G$ykqv=`Qo}Ft|Uu#3iKn*oWC^<~w(5 z(?|`1!VS8^7@FCjJIFVo81>UP%_NBA_G1MI**;>I2-&CS+Werrl!{j*Aw+ZUtm@@d zTf1setd!g;=q>U3(j2AM2JZwIv430ZE-?~e3B;0P%@H@eV`-fRY>LeN@*Pe95cqI| z(mud9H_Y|@s8qU>D&DZ!K^?4W+9mT3o46KW7}HX^&4ns@SgPkr4DyLm zA}G~L<08~ns)iT;6DN&`N=il=+3m(AYu#!9%hQ2#A{q=hhT@NTE0{djS zizX?7cQ{!%L6@<45gkhUh8E?zOwk36AM(hWx=PmU!Vh&1{KvtJ7IY@;;WEG=K9Pk& z+zaVb^WOX>EwBjhDAKBB{kkjdg%{!Z1?&v>+2PRZ$%Ks9TLU5xFMPHpaF%oKM9-+t-L{3Ol$Lpb*`$UE}y} zK{~I!->n?S?fiS~jlcMpd);v4OY6M!gsK&|CjbzxE={b@QyBif-9Le3O=lRlO}{uOVVgLY%qDUxE&e8V0=(nGMqnC z{_h~KG+SJ>fGMdSl7YSEpL4#g4TmbYkP9<`*#3<9&34%LcR0M9suIq3Ic z(h}O@p~jTsLOD&uMh8Vx2?pe89*cx3THhwZTC~pBTOXn_Mf47Xl>7l;iXd|H zq=#H`vpU!*v%sWII#jae5$~u2hA@IOw}-R;Ok*^(U`}w>Cyre84m~2O^2h$v0Qdq% z_3aQrKAb3Nd5CA%f|dgAV>!N8ZR}BseSA?N%rhjsvw6$l6V`*6vf8Nil9Z{=h*Zpx z0QW2eHWQ<<@rsU$SXZbqr*1IJSYiUDo2_mcg9)Fkfs_N3Q^sOr0NPnhE$|j~E$Hc! z9X)dKpm9=es*>r2`fB|aE%uuCM(mEP1xJe#aiId&UyHn~hqz%>a$=rw2`w-meDQyc z)!C@4xq@y(&kRV+H#eZ+kJ5+^ca``a#X-}~@9de~DAnKVWOS z=y9}p(#^{j0475ZQvGwj@)sxupF}x$i{_wk|GShrGi;ktIpAwG<(BoFDX~YjIT}+; z{r7<_20I=kkHqTv#D*Z3ljNmJzamE9>-`5@ucZu-pnU+<%ndRhn@8QsxLE;+LtoOo z<#QM{DM8W9|Fvgj0rI2OE|W;(LQk^}2;?8cWWu6a(qXLn7s}~T&GX(VE~)9P>(SC^ z-S2Tlt75Gx_1n7X|0kPtuSqG=g3ft~WDF4gu2W3X#I3D9+9}orF(8)P)lEe^8p<5S zU^U&Ng&FaIo!)b~%L8Z5+KAm%Z?7Zw=}h0|_{(NI@QtKu9%W75e*{lrErRmM;H@E7 zc@~{;$CH#KM&M!MRRFuEtU_|q<*Iqy4g1Ttep|_C4>Iu+bN4aS0|9Bno}A^!4wS1 z$e*@uwR`mRN0$tQ&NIx4#PErUmpzABAf2l*~$0QUFu#ow$ z&pZ4h1Sx#rE^2>F_j}_iZK9U7g6K%fph;JNtUz~|@+V0)X=&+yFJsZt6()n!ZYA{_ zA$up(MstFxw>0F;-3G!IT$f??hK^Hc;-5$runbPa=e?{I^yH5w_etOP+*H=;BrR=w z0K8Far@6J2r|e?cRZ(mD@qdbxAd5uA!UkJCc0=S$A5noeUC;U!6Yz!wW1j-yT4AFW z=jy{Eh}9)2Nq5ghhN>sH%_zu8K>M0(x0n~{MqAGjW}$)bA@ltjr0{>f3==$=&K6Scpa`nhL9kI9%GFGaTkj%z+UBNVbu_ zAg-WY=v{{5^d=AnBVvz;Ua%)b$g~&4c7_&_>1Nw19M&FA6RKl{Z4s(cqEoAXa!$fK z16{^_Kv_K9<;_U^LpSiwvVGREAukY)xccZgk@ll(Z+4egS%q#}Fa-Ai&myfKu!&!RLo zy#4V#Vi>x08GTwS3uo{j4v4pv%XPXM5IH+>rSJL~C7Jbhsb!4~2&AnFqmtE-^LRo) z|7?ab`as{7G+*pM=R1t2m*ACw&vkI+YUfaku1Q@4P{5Fz8{h*YBP;erCQZQZ4Pe1; zPKabs`i`(0sEFueB<_p(>igkC!X7Y+S*)4u_5a&#bpQg9PngFvSBRM;k5iFSY92(7 z8=Ga;yGHG?`n^I6trCA`aZ0SJ4@f2JkaNO<5J`DdN!yZ@v?6`8g3^3c0su%rx4%Xj z91e8*tGijWos(USdt2tRQ1xc>m$28f9N!=YHRK?fCIovlgxRNJ1%?1;*s@zNFN@^T z+c=Tu$|-8*WpuN@h6HL4e$sW)%oo{Evg~6BwJ{kjvr@1E4?IbQuN{ofp@lb4-2;`6 zDnt~;|AFJR$czcMUSPn2KOR|rzR>QAvnX|yz@*`sYf zCYS!K-#My=aBO3;NyL_5?&$Fdl0l}$cdSfb@nO?mfNW|h8ZLIy3j=RrvSh6`>GlJg zXmI|xtJHAy#gnThDC=zu(IbU(qeIV`RF?`CAj$3W{(~HiZoz#8s2-U7>yNRG#H`9t8#7N;EoPiIIz?wUKyd%3Xa9*n#Je zY5-{cgajty^GXy}T~^oYsqK=-I?XA_Q57NoYO!th1|QSTeL_nYSl#@Aj~~Sc6@5HD z-G}n!Gc;EhujU3+GpD`0^p-YCsuf7PMzN2)5L}+-J2odFi0NxS1k-mrM&P#>hPDL; zzS%G2ZBnJQbeH0u5UOcwmPUJNY?IZf+A#3;Qc0Bz_gy1t(>gcmIlO~?=_A6a04=IS zD1m;a2P_7Jy8nYF^h2V)X#;aq(G-TZAb`sICq0~v<2G62>Ucm(pI#^Gq_IdSfs>r6 zevLc^G;GYICbK+eUjyH~?}pWTgQ&1n55Gu)f}$)pcaA;5T9vtMP$Zia7s&l#yiWoo zE_|SJ&Hz^_TZ|p$5_w!ao?i2;`O)Kk zz1B14m5fpc^MMr)O-|-M%vh_x+OXu}e+?MJ=&t=3LZ8)C@ULg|cBz)x!PlGuZhyT) zi8z#)g?~Ze@Iijtf5?%eax-zA7$H6tV#oo^BhUP{lF9-Rv3h5~ocNL?1-b!=!4^}lBU+f(&b zJ@2#%w2?cstS+t0`W;8-k??k|_a_GW2ca#Dq|_-WbCdLIU1`90P9cl=@4is$Y$f`4 zXj|{iuxNW=y69JEhi#&H7HLGT!ttnEE#^?6X)(cmfdNM+)Ozh=0gT$Bdl+z$?tfxUph4m`xUQIDN9{fMG z7at^yurpDV$W-lTwDg!-zazZ093uEltBMiYR^*)Id_$WMN8=&a(Zuj7likOU9o8mC z#eOY{*K(TsX|d7D)1bTPUv(+(*(G>OZQ4w~id8RPAH>?Xh`6`F`P!-|Xr(8IVaKN6 zc3?I4=y5Q_x37;PZ##TWuZ;1kBAD`^q>=tjX7Ki>AzbYPMR_n%<|UHcrQSIoU)pdgZt zoola$y!yvu9)blzSaF5GxHB<&wecqM;xq!Le22?lTHZ@f7rY89Z{T^JHDSA3WRR2W zvMt0}>%(SN>Okq&`@R`!Cj_P8hg;c%l6cdzIWyoZ9rE4~)i!Z}lC+D6*i#0-5)tt@ zNlK*0VIE7gdopVu-T+jTdq~xOUP~IFPZd*-YHhPuG4Lh zFr-U4O68DyCY%87G)UyNI|zaA*rC=o;HNLF8bzk#!kI~tiKgP)&qU-~w|_vM;62jg zxy?RY*A{&%rM;^f=O+{aV*o|qeS)o@wESSxC>3jGe<_}CB=)Gfd=6KGkM3CJ1Xa;K z?y%`?&Oy;#7Yp7}4&(?VeE@TZ#?hO{tUZXchw7fUC-N_kAanqYxAH$maAA6jV05E< z4oIQNWVwc*-^z~nK-hv}-o48tZxvc0hldFmIJ^uCbLn&&h`&GG$KZak<;2^5@ROCX)e+ zOo@kKE`ys382}6FK$j}}ggTGI!|(^RN3pk^(dp&}M(ZIBoWSXuyA;l%dGiI`J1$@CYTACzaDZ8X?K=6MHe(B>LwQf2d|tvWZ!v8m2K3Cq+fL2EJ%D zlE2X~tckvN>Be9;=(oE8$=hDiQWjP>@GjylmxKkI!*F4EjA53z!d24-3}vs+1YPG) zU)FFu4JR;)Z{~ZYp1b#lzaV``M;Yc7GT%qx3NTcIy-*}B(h_1J82n+d)oofdL)t^! zhr923&s1-sdEliW-_d3{k&-fTpYn5oa(L{1g}IbW2)f_@@Y>dOsZrvo)?@LdHK-Jc z!<8N~Z@(z#hhH&$(s;Ba2#^G3y$l2B`Phm%mwBGm7G{#jW&#bvPYRQTLLjPE2Yk3U!Eod2B@p1(604?^_Wu!2mi;ttwtb;FDjJ{V83i**V$z;J$Y1XZ zfC2N`>8W9uF$!-|BETJlL*#Eqsq{G~;nm;5vdazmkS6=ctJ-K}QUwBe8c$Yqj1K`$JH{IzQz&Xk7y`wH)nWVh3Z8R@mVPl&SI6n2!y~jeQ&x zD97h29Cn9qV)2%l_67>}z+8p5wJrHP{O@|G7JDW$TWyJp!j@z|vif>>`X#ZBsPvsH zYj=q}VKYh$Z`O~E5pKZQYm-A^5;a~a@sqS+!(9C}lS4r9=pgQ|5J`m(z9k>5#n?e} zeik)VlYPYhLyMA(Sj_^O|3j*8Rssa}!&5OuJuVGmq4T2Pt@%)Xr(e-7{V;Tw(TNBG z{@e+oMPeO!UOwOI{%zcL6dOM-0e=(*zg^N>dFEWyy- zlyi%;zw*J~N!a>VB7R{B!-aNQA}kYM!ACG| z^$!NTb+SxXr-c&vwXb(lK%7}%r;|{)CSEGmgUW4AOWfHO82ao%K$B^+= zX^^yGv|&LCZ2kcDYudozhUjw*DC|e}_lRe23GuS#$;FDc85PHmW`{srXYs6!p=lDU z2puKcW6%Ts{5}P68EQ{n8*)@HVa%1xEE2-ju;!2729%Zs9uy8KPRll%*T4rKeX}#O*APmO-Qy^FwkF1 zQCc9wQI+qh$e?+4f>T8+SZyyS%sMfYfh{z#41meEJB`z<;)}CXx;t*STsG=48AJ)z z-2?IM&$pk7S!ye*z9yRh zFlpfhR)k=h@(-;=DkgMxRnYNOu+wW8_^e545{SRYIkMy-bo!5rCAeh?*C!-qc=y^r z;UMS_S$ZzE&JnK0k-s<2sDAXt*zDkn!DI}9u@H^?(DjERG4DJJQ{$IFuxRRcvvFS$ z)9niw+McdtL4>4F@ID9~U|zcJ=XHAy_{wOy8W&o#azZb_S z=g20hFk3!u>vKlc-(y@O+g}BE3#Md*APVO9?CeE~ftp4i_wNjX%HFS8rYESM@TXl% zxh;`AMQkTP4p@s1l76ZZ`nVlLgv%&4{1)Np;CDb>N!tG9a)m;YZ=Q%BP&x2R0&Fim zO0+E_$Y1<8m%tEG$k0KQrFjPsUn0@cu5s@K=HB({y7UjwyTlO71oIYPDl+H9%)ups zLoyUEC|u3;!%Fidzf^Z&XMSsIRL3vTDOp6GY)0Lrr(G^4I)5mXDierma-zw|{a^;d zr2#ga5BF2bWkU)<1qzO;ph)c!+3$Pk+azBp$pX^2?H&n6f1C+7&gZY`i;bIyEs-F> z2r31_Om8Q39nk?2)zn~bEA2GDz!}8)Gh2qG&_uR#P0yK8?YpCqr>hIq#T%@9WY<21 z3RHg=X*a=2FE!`kQMHedgYn zcuA9d$Rx{95qK=W@-}@NnKy44Pdo2%)~*KB5%RISYMV@1u0*ZCPsna8TLn-TbBHG1 z3UsrDV?j49Iy&I(xMup~Ip_VH+J7@Va09WYrjMqnCSrivXX}|>Tq$CMi$-u<9idm; zVl!!O?^{vv=QS_<9?dDMzcDQSCmc3@fHAILNR~#5_&nTc>}K^I#rOkEaN1&FT>soB z3G;vZ>W$p5kkGd|d0!i6NWSf~t-}OQ~f{ z7BZB0nuU86dUSn$kFs{f>aLuFQS|x~_`KtR&X?a&p{18IX_!?8eU+L)da){SDSTu{#JAwxSqXoeO|m0 z!WOr{*@2Gs@D_C~=;@OkJ#vN&P#$RtD3D-PYHKah_{h(Jw4NQa?PJKWUnpItS$3CKqt6HL!!Eng2 zGu+8CjFx~+8KV6^;NszcbitH10&#=M!&R@iK9s9hYb~waGFYSZUB@ySQeH-wn6BqS zN$t-}KRqNO@(5dL{EszGHlE08$9RcT!~hUL@4x$VoUWUCXCgdx3~k1b;2l)`EH_j* z#NqV)xz~J(zoyWqc-HSF|EzbkZ3x&L-j0qrdS`u&QM35dI5BK$zUSk4<|3DC~A1gwNfl5 z6a+tbU512PMyCqyz^#0615@wINjbfG^g-qI<9;cCLc9fi^LPj#D;H=xM^Uqq1Xaqi z@Wb_sKI#SJ2=yBk$^lUfM_coh4=^LQ2O$Q+rA_|Q^ue`1!^ThLilhhVhh5r>&ia+b zTj7kE>GQT&yuGxak?6lavhc@=EC<7a>n!zKqT$UY+f#-(-%?v|5S5GMwE^-=K9w#gz^#Wye$H8=n^`Djp{5m; z3OFxi`0Q+TiSq57ptDklGOn*CVMZx#U)qD9pgmri8s`NX-N5O$x+JJGSj5v<+pXQz zH6_5|)!{yuWc0L{(8}wJtdLZT+)+{)4TsgM>OV#-J7EF6e72VzcnJ?F{l8R!ftSbx z8b^w-K>R0Mdn5q;AhJ#w z{&4V55xg-Npj@|YQ-b~{uKEiiaB}Up{*=;PAXin?#pF8-0$NP%LANz&bM_`hZ_D3* z=?5FLVRp$&l7giNX=6+E(>#{=x7Bj6 z=xGF|2v<|Ui{9<9s-DSJh`z9P7g>tJv}V6JzPHi@a4`I&V&;I66rcXc%iZB=Wkvbd zIAK#6`<7r#d1QIjYw8n617ZtPxLA9Nfj5n$gKY;1$r^o(e#bm6o*zTmPjU~YdX^1t zJ74=kP?G)6?oIIg7MM*8;`Cwe{;0Sh0#a1;FfGV1qw`^rP@oxbf5%#ux`bDOQ!2v| zqQuO99+Q01X@=2zCilHzhs}PnYm3pOV$2%vVF6SYS#~i%z+851b$JHYrd-~aH%*Mv zt0#$`n)>D;@pmko&0fCvDKw-(+HKUnSNww_M<=T^vE^l7#&sEvH1@jP$sfKWz|*+K z(FE2Y#i!oz>4sJyuMFgXStR(+4WmPJXV(*mtJ*+TLLvV@%S)n8tvv`^%frNsMxXUP z6B;X0z0C9ts`o`FjLN*yX7MO%-Ld%ggnzG`8 zKUEYB10sLNQ)2Uz^fk;OWi5Eb_%y!c>o zLc}8OK`!yJhR*tW3^++*kMhuAAfav>hGfQ_?u^N_l7QrQhvsvzu&b5@9M-3_i`cl7 zIR7y)b=Y4n6AZC)7BNxl!R(dW2c~bIn~08;VXG`LFI_M}c9&m-%?}gvUM!#|ob}1z zx9Mq&;<&oAdL`Frnz;zA&UM<;IHxm9mO4saRx3dPnpQJCBt4ziHtZt{`JM{vh0rm%RZ>-`I$>SEe9>{6Mj4_wW(^A zzhi`U{Z=m6_uS(@vUeL{JN}n)k|G2m-4CHKnD2i8ne>pF}Wy>wRd`l|a$ zS3_$(v=$mhm@C9Q7)>Ypg_8-uG=t#Y%)HZoh5T-=ZjqtOVwR3iFIFzS7S=#9Gv>a0 z=^NjgmymBUTOxI+0yVz1X=BLWkn8vY=T~|jwv1%qsKU)zWO8csDV;`*Md5OS*Kul7 zK7{Dbq66?1&7rkB@{CvS08Y|%^vwqla34u!z~|P10YVA7eIqiZBInBrMMd{j zL_|tmN5%&OeNRUC(7dq634_LdQ{%hd6>Evt?tR~Pj$i~+vR@OH9d z*-tF%?U`e6N#$ZOL_?M1!r5W(I{z-OqddFc8tuuSsvYN>5PWyriH_k8#I$9=dgMbER zjPYnb=|H@g)~aja0R{K=IYi^QU@sak4e9axUO82?<_mvDvlpeSfnd9AIZTBQ^s z>zE=|`)wYh5mIJ%>q#>EQ7Wb>$8P#d4l0}ETLm?$g%!JaqCqZoUCOu(xx%(KFMo1y zCnUSnr7>1rWZ+lu9^{*WtJm*=S9W<}5D0C(qKr!Z$ev$p4=h3c1)qy5amq&?{tm00 zKyprH&$k#dP3Kv?3322V9LPpRO=5eL2sM=+(LW1%&v2E&qU0cB@l`Qa&WhmlI&aE% zG!usqpDG$KuhK+i;LOy*L7-dud)FdckfSuh-pzdjjzw(!9AOiS@_Q(u-MZ6PDD<$= zXKt=KRyzG)m@4z&<=lR;R=R|^4LSoe@IHtU-+}yR;#4ya^J4R|_avP*DT#w*+q7pr zR?^C3F-ND}veo0e5Y;5KG#^32QawaOyxIIUnCyVAdRBwypFzoBuG)&5@|e_>Lf}BOf90f*V!vc?nGdu^Ctzyk+UA^l$ySZl5?>p~b?W z`eHbB+atbS<4In=CAmfML--5v;iBCDYE^)~&ImJx6a9 zM$enAs^(@~`I%|94hB8%nlJ(%;CqovB9ZdB%2sh9e0z~=_>JgRpQj)&jZ0}sZ;Bq@msyu z-!lfabC!d@8yGfR*RchqsDEt^II$+tr3XG(1p}J2((_xCb;G&2i=|x-(kRk9+%RtN zGDZ`vD066vDTk}?axYsE!Bw!qABVyvHZS6Fu$NtDq-B$ zhyrlsK`dGBUQ4T~DV-H>HC}z@hg`sw_WCwGV4(@4YUh$U;Y_@j_h;z|+3EU1Z7Nt( zKR1`AMa~CUq%}WHqP$1m#GwiH;kzm}5=Os>z>&Jxf&$>=GL*RPq_gZeAI9t`lD6b; zlz*o^&tmqo=vnnvDSbTY>5PL>kBh$AR4^LTvu=+=^T9E+HPS*((EEs?R(8$X`Qe9p&2t3G(%IA^cT(?K)Aq;>)E>OKQ4 zo2my@?uMbl$7EB!#dUAglRQAjf=YhCiLBlKYTm>8FIuS?yJ|}2X^*YssIp$+dc3^E zw}%_}AYPK`zLH_iH(2f4Mt`c-uamgQ2YW{AoVB*!ig@l)=^K#ohG!V;pO=ZVJ_p;+{sUE9m?rJvbL>7~>q;kRUz00d-otYG*eX{JqqCyAhCYQ0Oa8~8(sbV{Z_X;htYVu_!o_?vH?gveH#_b zMFuE`7{PD|W|DLBMGJB2Df5WoU`P24yI0MMyX&z-MkGkT&o-gqj5cV7zCZ)!9eBx$ zw6b>4E0r9(o3y^{Ba9z^yr;>fnPo zcHdVFwW3SGR z8BAy16>81?jaiFr1Lx*QYa3sNzt740(DZ5CNESR3*4A$ClM|%Ybcq3AcbL#94UX{v z?BbwT^NFX2#Di*A?Xnjf(oIzmmF~Kst*rSa!sMGQof;@qwQ#%A>bb!KU?Kof_Z0}98Tf;oWr1ZpSLF*Pp{E>BTdw< z#^eil#!L;DQ`j1An_W$WSo9X)Mh$j4jTv0&Ss7UkPw}> z>w^Pqvy)khk^r4q*o`f=acA!Be8gf~7-}oiJ!=~D=Q@zmDfeBMwhVAULKbNNf-ftN zE0azAef~xCuB%+>ST|xYzC&P|tizU);B!A}ni9eQd)~vKLiBC6J3`)5U)coO(^F}0 zE-pycl=&D38<)L?9(&G9u^E>G6JdJzZRuZlDjp7eX?S)-AUc+5C(m*5`5wi{hGo;s zVld&F8Y>VKMCUJHJBlalojCU1jk}!Fr-0_&MDbSned)rfggWs+-Cic7%DlI!V^#kNxoH8;BWepAPBj&=2C9e^4N&sN`z-)r0`dyEq z?ts@-{VT{W^1yl&t6)P;^5Li!A8bSNq~M@e0vZt4hvfxw2j%G<57X7z|k-ORSTFf!tIlrbf|nbS|ZMU9c}-QU$PpCeaNsbfb5B!gH}Hq5bj zxl7I5?YVlzSMJW>RI5?YkTeQ{hn3e+CpWB2)u&V-I>kgz8uDJlmW_;vDnLlKXSmy? z1xUQld!`|DReKO7>1!$o95d0-eQ9x=gb6X_9*A9sS$Xn9YXjf6N3c@jY?XCH@<5}~ zNpUnBN6NTb{yvw=;~ z(xHMEn2stnKLke{B}A2y!~P6I$K))YTN!eQnSFj$PkYeoVCtsa(`KIR;sz`{`;(D+ zfv>fRYAD-)E&pU$g?_T=) zzoE0KD(d8=ZMXjBi5x|Lz|De1HCvzcs zZDKfn?<;c7IX|nlS*7}yEF7pB;8h@FX|mAC-Th%|8zVcst(VS#K6T(|hn$w)hK3lv z?QQ#UDTR*@%E3n#?M-m?KP%Ljj*Z*j^TRUlj7+@;*x13E#7Zu2@hH2ZI>r_F66F%O2i69GDqKS7E? z*Qp&s6r*;zM*tZSOVuVgcHnRKlW%v$kBDEkr36Yemp;_vKItjey9jufXV#ojBXYS- zd_ZQCSl)7OEg7*VYNhCb;dvdRUD&lGP~_Q4rHxmTeNP%#GMpg~Ex4r;u&F9My~GeA zfMT%H{p@2Xb)Hl}$B>mOir9tr<$(_`foE4313 zcW1zgRASKRMp2p=quhMt8z>Xxk$7{-l4uHMy=laY0V?&)MnCo|`;!r$B`EeC}s6aP*{=D~4+6;;(;=v=jsz z?jXR#&?O?+nvoe5F%)Om91AVu76XHNvN4zLHVUn5p-&d8ji&1$0t;YsFkunV&XX+a zBdyB^^y5%>hN-=|S0h?T&{KYcmE79kS?IlpOmUCA!y~7oU()U2W@f zM|zxJf?gbk?{kol$5glNmG+r=j*}q{Or}ybm@g)L6cbefl2BggbDa|6RMe6B*X@tR zjk{&eN~!1|Xy-_n z8|qc%o47)XH}#Qk$71}#15uzYI=daQgvRDzl9PK<$~&_#C)L(EX*$fDaLe$yfa7J8 z!g7*S^Rmx0ta-!s{-Hfe>)=m+>UfM=g*>x~vQ#^OL5R<}TH>PIiuB!jW3_X;g{_sa z$WN)4cy*bO2PV#|J;Om{i~mBHOJ?O?_iQCZN>(&XRd(YSuN9OaA#Z(LY**; zFrb*WJxIO1m8O@9k6(^IV9k_e!sz{4-ZdXL*_^?xnke8Q-1HCn_1^_K1QFDfBYV@Tl=e*}y1nFstN-Bz>95=UK zI?p?<$3oM$pJFo0m9&WG%iQwvpLloHq0DAdr}Y z8xkr*#NrzYx=#+m)9;A&UABs7&?Ize9kr6Ba(aTtO zpbNB@W&&Vh9Fe2#tukY`x1xGlS8n~{W&Hyu2`1`69t1wgQ5kH*U5qae(h;l8&@#83kja)rS%$)XoWpq7cFGXTv%xJ*m59Ph<;Ra%bH2Cwr=E6=Bo@~_Z| zc97-4QOKLw3sse7$iNe=Vn@8YA?0f-k((yrllTt~?X8YF>~hVmN$0$2g*j3BCD$T&eg4x?r%;mjaRw=2PhSzQn8x+a`0oVAAO0?qhWAqPn)PK)JF~vF zfKNMviZesIY`4@>Tv1_am7XF20c(|+eE{34z7{lHE5y@OpPoy%Xf$8Hr-eb{X*2+~ zv*gYUXlciUsJWeTjgcJ{3MYe&!M!UVWI7i1K*~d$2@rjV>S=y^eTRUv>%!bOdqhW+ zEwV;2TIw__TJj=@_>uhLqY=~O@801yat;`(Cjl}mhi@P&L`Ui&> z8~am4uSipL|E45b-xg}xLZInrM7lE*$6_4H%^jHD%o3TGNpZW!O%5km{1E#VLEAWI zi5Zqs)>j)6(O|HNHym$XsveogS+ z2u-m+>Fbznc9+RQNB|?0>BJtl>BNH@LhWkMt1>a>3yyX+r@6h*l|-PX6PU=1FSaQP z*&a%^1(bNMfYdSl>Pvp4>XO@-vf$UwNZkeW-2-`~7dPL$KoNQnnzz%PJ&7s@M9<7N zD}8QJWZ&MC*Nk$QvMbM$(#4v8YCW*@M_W-rL-U9e^31O=3=p>$x*8ZrmjKZzb`s8b zbncgfOpd#+43Mhh$9AG6DaGa{iU7i$fjr^nx%q6Re*-tLEYlR{>X4kU%Tkmb(Ye6u z9-Mk8EwXkjaw_zK^rmJrV=CliVypp6h>7wR3mFgPY7p+PA0pvWyTta!-?7)e^lJ0a z+MioMb7JX*^HYnO{60x@=J)MEp=RlrHvBL&F!4?MR5wA8j|>Y9OKKt3qCRoIs*3&V z`W`x3f`$E%wr%GEy+tn&*LUYrlENmTWVQ>xe4qVu)EpV2<-dFMpY}KcSH?syrlTJg zR*_5gh0GzBKY66?9EzJ$QgrPH<(tGMvnYSA4P>8VIPCLv7>|T3!N~H;7Q3sqbfdR* zfjT8LX(+l3bWko2^@wrqsUewo{-9gA1>h+De*M{J)M4CG&HT<2esg6d0Xo|X7eerF znpnHArG1N&Gp}9)(Z>TF7e42pB8C85S?jN`);~0wij+WqFvwh0o}*KCDyK=UwqCvK z<~McBAI#MN9RO3+t2rc3dQTu0on8axN<*CZPoRV^xTqVDj%M@ zc4!lQfz_-~$4$bs>ayFyc=;48r5qwNfNCzP0cj{LhrB6m(>U|zTl?&Z3>7Q4KLtE5 zt%M36W&{cV79y{1GWnbL&bn-&d4TJXGYuE`K7U^gR)w=|2e#>xyGAG>$3bVT>=H(< zvt}h5s3!SWt0o#uCDC{XUtCAcH?h0~PXYUnV_EAEuuazR>?sGcq(b1RrhbjP>zfc- z5Ae^k5UB_*8f#Nitc=RfRp#^S>d<0cwq9abV8EIp|0NQV zeWer^Rz7)|(dEz`BL)uKF~jot*K4W+Ew`8T<29!R7*+7CgWpB}wbhDx?VAcHr`!9n zyMx~1k_A%vJ^{<~WnJ@-+HXA&IJ=(3f32??MkkPgd4GBc%S=wG3FnL(?BLMYLwhs? z&mkc-Zbi=^Y|npbAuYqQ;D30Z0B=(+(lE^EPi9C&EjU~{yryI_R&D-$6()HqwC_Qh0BVA?VPYNtoH9G| zz*@2)23_cBIB&11O?ZV`CXUJeNX;p#6+ZJKHI%fT*+^;wEdZddg@xN;y$FxqM%=qP zOxkJAp$eZnLS!Zy?hz8+cEBh|J;XbEa<4f5{h7efbA1W9hmn9M{PXKt1vaWYS6+ zgNbYN#4#WDSIU8ecE>w8F;#9_UNu}IP5|C}e-fshz~s5f3&SW>ZkEpe#4`ZHiWzLX z4%)bO#sfg!t{WsgcKI9YB^2C)JrQgMFSjZQ2BiHQJ^h2Uy>61VB~%~NNg;{*L0)*e zR`PhfNJA|0rmkMEvKNy<c> zBIoqKVH1sW#Q4DCQxfv6o~h%EdbxJ-XrUKR0h>BUVk#jGNs9o@r+kaOggbp={u5c~`8s7BZyLr*5%amS z(Ts_h44zh787C@iT~&MzVzx|=)7qh3z=>T5Cc)Ssj!@0`49ik)QZ(i;i^@t{5 zYT90@-1NH@A;SgNAAEpLAW)BVefQwAye@jR17SXJlJ9$JUGSlT7VNIl8??-*B1;Hl z(!$(R{L!R9?G7XNl%YbLW3RQ&Y_u}qZ(hr9`^Y#%vTJ(Cj!FUovQHN_#lW!ynpINC zcE~o#Kvw-54G|KY&6GK_+8E_aXwfeC^g+-n;l=k2y`#y zQUT)-;c0#O5XzRJhY_9toO38@%Su2}g=F8+6pzVdF!**Q)59NQrpelR?%?}j2Aw~R zB-TD{_Hnkosk(o7&AezAsg~o@wf2Ey2FKm$rf#H@;277;>htP+(D8&^tH5*0fLiUU z2eccz=)d2*W5IHp)*79FV+mJaV1hDef;I=dXM?s@iNzhv>yq0a)@GwuUzqu}-S6@lS0eD+EB4oOgaO|o{E-Me%P9e^7pR~| zB@(SjM(Kw&+`9Vi_IAglnXKnD*xoexyKmMmW_0M=o>cA5;O?%n!NzxVJy&{tJ0Pc& z93=()NXsOTmztjzN93X$0}(B${KWSBnd_U%*)NIT0MyAg(oD&tftd6{nvA8W7g51Z zTuJVFdVuZakTaM+T2TkHlkzm1C#s@&q?atQNFGj*{@Uh1xxXUO9OT{a$wF^BdFn;r zmFyOW5zfn)vkjE^SPA5>t(#;i5~_-uN1S3!Uq5tBGeCKMMTz$&!=Ev2JN>IJ+!NU< zU@8AF0B`&mk2bekmN?%2eeX+Ix8?=E)l;v<cAi1VHmWdT*mK&TK(N zuZ)PMo#E9@v~5*_B%DXqK(5Xl8e?LU4H?v<^lw#ug5xhG4!U=3ERd@Zg5Cx==ILa_2DRtn6x=Ez}CL(&}rYl54<%ic^uABCHys`eBc-<(|Zeg8jq#5(}N8br|hGn%y1! zLY2VE5&ma}(Cmp*@;7)rl5$Ni%JLVGIF|G5)gmRyxt?478ai!+RC|R&*hYNuZl4CP zeXuS?)-KH@>*Jw`4m~$YPd}0QETgi&zBtD%xAlM(W*;w0<61ftl*_DygnU0FKkc?{ z)o3hFE>OvCQeU_Z7-Q6|3Y>Kx_lZQ(3~K^wUWlIX8+I6vZ3UWB!u!tMFG_cZoa~{? zPCwdm%XwyB9O!Pn#Mf;uUhvJ`UM4yHn(TkwMLXW!6p-xbf zx@Aj&J&tLgn3VN1Nt1gqvJU};^fvVPt#?w%@(tbl~Js2oXw z)3D1K!&fDN1a?dYnuhloK~WSSQIC=f8??w@&V%dAd+4dJi<{GYR-o%@R4Q*)dI$7p zP_4e~_gsAjDU#Wj)*Omj)UKgJ#& zTPYx8)+b=7Tbx}a8518`2q;;>6OYv%t2%xGcDo(TXd&TE65j8G4Q)NzC_m|teBhyZ z2!%j%1RMAc|7`06YGO)ipLUH(eSIA(cGHEd{{ECA`&?NTbS*h7oi`bteLX9RZ@-iV zIth1H2bju(g^oqve0h)ixQ$hfdT0YBcM-(wbbrHJeTm=i<7l`s%>WJNWmj6>Ahu#&A)8snbdk<{<7VJbD-Yo)WT+CgWfFT~Vr*Bl*gznj=*2jE zDN-aonEWpd81_7?Oh-75jz&iL5(8a_cJP@%G%^uVlT`F%M7mbUss@CMi$J^jsa{e5 z$Y8rHTXoDWdw9ydb)a?%{s4@1csjS*@2Osithn&>6>isS4#a%CUGs!&Vn2lD7s>N& zlxEN6pweJPTIpsXqe6qHCtfhM>LT*NiKZeBX&HM5(kFWQ9wYoEHFN_nvUo|}J0H~> zYYP5EH`i?d(ovBd1N23taj0tL4eA2P`8go zg=rNOY45)PTNAOq3Hsx8>@GShw-sJD{`Xk)0sEkuJfWKgctj&}UKEy95K|x1K!;*! z70fXFZ8ao>;ByPdJP^|3nI&M+T;2dPK+L~2;}(AWWjSe$r>A4|3eOuAJBTP57H!0h zyQV4oi&&kb*XThFV%acoAR4E^lUYpwY)=$$8F4T89WLY-5Ir*60mL|VP48v$^EvHn z7yYl?Kt#v4MW!%4eP48A{M-#@O6y(updqI(DIvl{>4ci6b9hQ*e5Qn-I=PaO-j94G z2sM#*I(5(rq~|E!F$#of8+ce!JB~ACA~;D)Q1xZth3gGxi~ox_JX533)hHCoguZ}7 z3Hg2^I?3$DVxHs4qVAT%43w$-<%qPZ?o~sYBK8Uj#Ksxh;c`9GnPn~IfbS+UK{#vI z)ROgwkH*c=OQ8brmN`cAnV0(=4@CBe&vp#=OV3fIa{%8)s7p7eIb3|H!tLamP5Bv| zP=*bGpF3E_GKv#``(g9FHDjztCbX zTUq{l)xN_zt?L`6JOo}ntEYQi{9y_kTp4fwjuP36q6yWg~M#Y;vr-Zx^bu4 z63fIb-!uIM6bn*keft|DuRMfFY0}=8XH?y@t?Pz=oZq~JgzIW{AL0;Wz%kwmDnN2o zD(S8U*%woYM(==rdNBF=2NoUQk}b4V=~~<4iW3g?`9{^3hfIlgDuqS`Z;_~ zU~6p!;iRBbpb*^&7ye|7u!PZ~w1^rMtzUtHOP4YdNbn;e|7tjzG7|Vd{|tKP%*wk9 z*P@X`NccK3Zn9|gLbN{0@eB!kIJ}B-fv_+77G`h7a-g_Y_h(HhEaS)jF}Q~@tZ=#; z)84uI$>)xrj{#3H-3dxV#8={$R}pD_Zx3vHpQd}3U8Qn4{3HShBT<&dHmwIn^$+oB!JD&JlaKa z2z;WV6G;RJH&PX?O3G+3`djn7&+0+=4s(rBX|neD%A?0_bqvjdCn)FrF)RL=B^qye z)9nxbo!{7;zJAhAzHSM|&XVaf7KZvwn`EPOss4qG_AeQ4%61W&`_y=)9C<~Pbpq7T zai2ZJtv`Ft0s?9RyV>ogk(I6&7(-W(4oBdDV|)-rnHq^hn{``DuMCq;Oz`q16Le~{ zF)5NdZi%qe*P=f^vf}*;(w?41T&NG){*EqbhI1c7E`=w$z{`D*;^MFjQ|J$h>~)vs z(eaCDhL-kZUAkaq%dOiAc`ITSn?~WL8!dZkbOI$%wx62mQaa*mWRkh`f-4E# zi&o$jl$>TBC9~?*j#;q>xqzI`aPbeA&Y^5?b6&=-d&Ch_C?tRiFA#fQnx;MP(?v>0S7=R9%^^(%^Q*1(qVP(F ziOd)4pO1}Z6p;V$k*aI=u|IE!bm<3_<;1(dkatJDG!j5ulmk8P5juc74cXp9T$t-d z+&wFy#J#_sbqrY_99;2azc0~)hOJsnnT;fokXe5xzLnmL6DE-XP`W^4S6kJC@ zuI%rN{CBkk21;fd*fmeT^de-hRXXJ(8WhxR1T_f)!K;k90whK8+spuOHKR1JfP>bf z1Kz@dKO_wM{}+{1w;5xhx{NQcDoB7L!{`OECnfe|;Qny{#)2k&7#@JDBLs`kH*bq* z9@|4)bq2-eDp$|hHVBY_xzWWoK`(5!7z8sR$-od5I{!bOf0=?fOQB4MtfAKZShwz7 z%MZqWzmtb1uD9zOqnlzQOt~P9xHh+zq2a{SG_ezad^uh@m4b{p}-SARAe?trvEOWgDfnd2b!~GBQ8~h7oWq`-hPt3;b9wW z!PDW0j9hpH>f9r04`x1(_~;Nhphk`XW$Ip4bwD-wd;fYgl;K}w5KSpBJi~$Xw&YY> z(;tpr8N{WXgS(n{?oM7)zS&_=%h8X@c`{CoUc@5`h)idGfu3ZQ98JhE<)r`(sbQVC zvGa63LjjszY{gjy_eNTkYz`LS0r$QUCo*rVHf&We`$Wc@zF!Fox&-jA;yWN+?&@{m zM=jx~JJ(blZ_QWb2 z-Ng7NS*@_xpzeD(O>!@cUyy1r1@;xRI{3-EHe~qDkbj<|(c<7R_2&fDgWEorU@*~3 zRS%l`aY&g>&9rt1#A@yZkfUe)L}C34BYo>E?9u5K>qB{Ecl?dHB5Ox%iy{q~*?a;W zWdSQDa?GFSs{&EdUfgjceeV&={aa*#>)S+xm z>GAC%*>lH&u8wTzOMFmoF%NZ*kVP&fmMo9k2pLc1R=5U2xY&9u5q_u`1Z zswCTp6T%x(+}XWG&|@GLo(J-$R3hZg8%TaE-eM#iJ@NNIbUz0&ov0q2Hhraf$2Dd{ z3wxj5%FY(o%%92Q&vce@QkPJ)AmA6Ab<4dMbT+BAk4!gD0f=eV*n#h$34*kM`olf6 z-T9-*Lg`E8(E;W(>F>`VlhGPE<%C+(XS-ft0r|teVuJcmP7GdLD;HnRTCNwfQ3v;) zM24#fjx!im<{m$0KvU}wHn@gC;Lvqv2pXI4z4e(j%O$ib?ldM&MSdRUHbEV>WwO@o zyMdBzIxIwA^tSyw!}&NdzI_^(-vFi2m0I%e{dUOTZQq(80gc+eyJPk8FI$r+m{GTR zbIAFA6KBe5PwEYY9T4TbYBVUm6M1sX&1e}>%-41D)#BJ z*3s8p{UFw|VZ%j)JTKAQwm@Zyec zo0A+jD=}p@*{$hJSHV=1+eL@uyxRu7Kd~(XVcM zN;P=^}9%xk|-?pPcW9X7wUXK8t%hF+301e2Ps)Y9+ZaEbQ&&-88h)7&sU>G_ z5MT_@e>wf4*fn$W%o7p{-G%8I#1%ur%jMPuM8hREKU{e)B>mH&&iG$mJ5}hAXeP+p zBPoapN4d_}>ci0gBC}pK7uPR`o5L8%R{u@zE_(sozosde0gn-w2fv#kDzumj=G3Ub zDyIkq=hX&97qW9nGbrDlV$n?BnpD^<7*lh!>dd=j)1_xMrH67Dm@)nB^^pe%jlqWn zba%e_kf`t$l{S9~ki337+yW6k+h(fiit?%#zaTRGq1-PNGiUbn9CcQd2P-Ut{OYl5 zml?br9#h7^yDQ2OO)42>N*+6y z$ySAkp}M-lr_)s5wx;{h1NVaZN$UK{MZk`gArJ_a{cRE71Y2(B%ShV(WjH)77m?Aa z0Renq25cIVu_ErsS4}&xNu5{;SKCtQ4lOL?bpw{3)uKZWa9s<671f=%@?Zm1@0 zqM;MB|L$})buF4-(`cdBwbq!;^+=<<#lT{=E|{`J(b2(WsHOo`vpmV8sHGV;#WMwJ z@>y#QydNh3+k0J~sg1&{osWpBSvW!uWn$pb)4mIB&l#(_@!1gaC!PIm_g+sE6peLQK0w;cW2c zMB?VoD{xtOclx5>dCDvMl2y2r5n8li_E?>%7$AGBb%Q0TVZ=WAP|B@?Yx5Ot&r@B{ zk$17~V92x)g*!SM-t}Ea1e?)ll`TQmxh{&I>`=K_h|Pa*YO>39h67mNCOUbALxY?@ zj^xnSTBpAUHoK^G=r0B~vG!btuvK3S;D*Rw4mSW`AUi0q=S{6%B1^xbI0nj1k-#N37X%EKz2R;|BWXiA zetd3h-ONox7yoO$oahxk|LB%i0H{l|JPRs#K*Z7gA?L%_Sjif<@}{OJW>iKKg4!Gd zM|rijSi=pSXaT{bfyYK^&ExuLi$?_Y+&`(G@xYj|&m$+`>`W76D65Zl`Dp9_aLcd5 zdE_+$ZFxk-v!n?ZLKa+0A_PK8oH6MO_KZM}@Sn(tUY3YBBx^&f%lCtBC*b!e&I^#* zQMrnX?M75ds2$6!l`h;vczG=9NX|`6=Y3)i>fA;8}ZEjm(F%=gTb+?*Z9f}W#x** z`n4l>U0ahNK9UVy3+M+VKzMfC;Qxh$_{eqT-$MdGh-_$)CRJ!ebrjZu14sxxH(1?L zI_)6d4inyal>pWcZ9oR0I963TE`P6IbQxgHMHFFmu>d?4_OhfGOs9EqRJ+9XbQWhZ zsr9K$D(RwNfGY&8^d`P{4bhuE_!ur)(^d`r(_4M*p)XIyf!p7QyCNO+gb|$b{~ZE< z{VB!QH$mw5BAm5UUsBH#?xiAmdLEv+D#VXhDD&Reg3M0A{?m*w{)|i^$Es^^Y|Z7$ zqpFd1(vFLr$iiIs-qvCZbi|(0o#)v!dKHp8S9+LF%a>W_qW?-?a5CAGi zaBb|c_eL*-NIWGL)0wGWO`mugEgrgwBL?kYh1mG`kyDLk=vHa}4j(N9`|NFZdP3Bx z9Y9YEHofGb`{bL*OfZFQaJSg@R3D66ljK$lQ(7+~uYZ4%34)-lf`%L$gi?i?bo@{QWTfA2ZqMZ3#~`d~=*@ET*5U?Q+NI-!14mo8nacDW8Qz4nqXihft?DxFYojD5p>(OG784j(A@G|pD z%TGPoL9_*scG03-k3z$W*akS4^vS1V#U&tXDsWP{Q=aJuXfi?vF^9vuk0|~f^$kA) zFCC{0wTlVj>NR4J7=H4yO#{F0J1W~jbQ0qPWVgDU&Q;&v892X z_;{miM?UZ4%RT=8_yOZVi?+B{LQ)Si;#Ag6gk!6|N=K9@1-B{xir9I(4&r!f7&X*t zBh7Y< zcM5PFFn0j>e&qG!vS*N~cthyCz+%C#mdjb;nwP#p3jJmpEN2PRBp*}9i4`fjU5ZSom=mD}G2~bTzX$2D zB3wJ#UxntHHPKT%qfUchE?R}1GE_I0)@^s}+miw>S${*ZLvw1%5ITfR$`z**Kfl#y zsV2VLaC;2U~Fi=;+Xc&|Gh+9XThYgWvlz4Vn+lF#!n- zg=H@uSq%E=Jts0>(Xb93al6?L&HV z)Qvff4Fu-aR}H(yv>liTy?>v$j_40-bS)y3!Hx`!zG<}K2i~4SD{xm3Y*re(RV@a) zfu!RgjKAX8r0r)ig*a{m_-W;STy9VFXk4+F+6nU&&a~#c81s-ZvxQ6R+boKxOPH=O zd{VhS`pJnKr>xc+>YxTrpkNnvb%G9|Xi}T{4N%%8!*&;4qciJs%t6UNDf_LRq~>XAMWQf+kT}o;myV4qj+hPm zGMr}9>0BR28Itobm14<%sUNWVFHl*PI67X_LBUwaQXEUEklBnXrR}LYzts(O0Xf1x zH0Tu5%X&fnlBc8zzg%k0N8P}Jg>3@)cpMH9lsdIrCHA^O?%Hqk+@*&~m;^1_^(Aud zbAJOIhV1I_{1u;RANQ|8e+|8JW7riXe%6#j9&YKUsF-C5$ytKa)@>+Xr}W|uExJ<; zRFtEx3I!wfbMP`2V*&z6MPd&$AAV}_<%HlgE|aZ<1y4`s;n0u2oH3Z>rj?E za(f@!vjOTPg_!(ZK4=`dwR@ID?m$HA3AB+30JI2+$oaR*vfJ*trz@CXyCGFWe6KDB zCcQbIlTOpUsG}<>nyW^C>5^UPw5q%!Z7(@=n`Nx;K;Fk!Ye?P<1n<7&2@-*@*GuOx z<7n7QjnnclhZ-Wto=Tc$t&WQ4_McE&*K5rlw?r)PWvd$i?4P~+|w^4j8_$73!#{R}*C zHtSD!;v5Q2swf^qosC_>H1D`Y5TV^q;NQvazHr0Uq&SA{y3nA8`@!YyYbn@?R+q*g zO4HfOsLo)X?T#(|k_5BO6F2sNB4A8Jdr*Yw*&@D)=3Uw6NZ9zoS;ij4c_83mu1Xj9 zYqy+2vO77k0e3?Lb)j|m{CwdEvSxIDeQG%+VKo8LMT3T9?_?f3j;SG{?XOQgfZdQ_ zB$0YPA9E0(`?(-(SxsWj>I-6|CmHhFjAQ4g)~J`2gUUoo!Ko1Xy43>VBbEpIMpx%X z<`qfO$Wmi_YQMVSI<2hCZ0FQm81YVer(&!E*|xs=xJXEVA(&~zH^^4c8@JA^(wO)* zz4o=LCYtE!ylww=O1@;y_DQee>~Mw!d5uEuJ=6LMrXG!a76|wEZ}Jsrf2%%WmcjG~oyY=?m;}eD zM6PjohsKtGbKvU6(yKMN5*aB>;gS`Q?G1L17f!!Sz}GYLZmO)Cw#}@61!2u*RwvA; zaR>J|puK|Hdwq>KiF;ia7x{s8#Y$do>G`w2q-e_~NQ%?+4d8+j+dm>9)Nh|acmsn5 zL+Sv!*`t;QPx(9vSD`AK7z4rDmb2wUk`3_}N4*TAe8#UXwjT!Txp;FL3Q7r@eetqa zE*)T-8Kg#&Mp)(D;xO)g;Ri#ek4uEu&SLAeIDmQ>CVGuE$aP(q<0+OeUdrCE+)Oa8 z(DfCdWr3H39RbhA`Zds_-nz^sv1bl#Z$H2*8LOsYg+`2g2h7!|^j?HHR2t;7q7E5u zUz04T_qdyao9%ld*Fz@B;hU>8VNH*-b#^?)CFlUN#IW1_$4?BZm@nZiYX(X~xg=;< zfK9KN(SU1@E9O$4Y8(VJk9sunl7}vbj5DWvPfE)f zJt+<5gs7u}moC#|fT`omn2!@shhEYPCbeL}KUE_*q%F;905t8}0%}7bX-g)n=j;b) z2vW7E)NgBSUa=doDWkq`wv(esD4T~JQG()8Z)RjT@Eu{1a+jCn)wRr&CL^8fq$+*( zGuQB_Z~G45yM`hd@~an4`*kM{@9fi@w8Z=KMkW8W z<(G?*|+Py;DxwPv2`md9c5#El;cRN%_Ry_`RBlf0E{e_6J z>d`b`%VakrEkC}#3`H0DSYOUYl6~nFDHoLFtUBK*+!8Dbzul@YR%P1DS!0?1{q?_{$a57tqc?=zzin#Cur!zJfW}8iBA;;@UNFIF0W>?Gs*21=6pGABXhv zU{*A3ehAw?O5qhB`2sZsDU9|p$k4pme}rw<;?zA(OaX43 zadHKayck3CZMKY19|{441jRL|r@WN}9-!~FVKo=OlX<`F+rxb&HK=;UK2ep}R;TT) znvlpf2^p)=0F>= zZ`r`K^V!1ioq6rWK@FtyXX%i_Vx~reHBYl?h6%-X&8CAE8Tv2(C{9lyg^I~DTcQqL(;`Z=V|nQ1bUW16sJRvJ+YHQ3kReZ)&Sumj0;kGuYv*v z?;$oUM8InROHT}*?O>P9v%SF|(1oOV7d%}zZszV5hL48BkeQIQ6=rVnZjw6-Fgzy- z3pX`uCEL{0XtEK>TH3u>@pCX=;iSQ*h*Tae&oj_bWvY$ zUyM;fNw|uYeLX74=uJ!>)q7c7G~xaxEwt&w#eVVASEB;5nlC;*0k}%XzBOSi|1R^I zL5};7cWnW&KdL`M(|M>0`7d3Sr6qzioz2R_kQ_B)E-|h7EK|osHqVA~*cML}S*cR8 z0g?D*mPXrj34bj%`scJ=?(VbGm4aS6cEAvDxLS$ z*$Dn=VAI{(gE=7~d}*m*X-1?EkM?P|m%V;`e&+kmC8kV;Lt(H;^J4rnu;@rxkq5KU z*c|m6v1J*e3-5PRkhwwacQ7_kbMbb?N$hwNCd>|ic-0u*urk6eLf6d-yarFuwG4{c z`m}KMBv7^1w!Ig!J*&~E$f`H;i^AkJ^zboq;8IJ8-y2Sv81MmWn-hhu>#F>mLFaBx z7nb`^bt;J?r|Zg6FMxCW?z3vkAe@T1Q^t+uSSu9AoT$29pgsSTlQtD`S7<=QVrgs( z2T&{ug7qL~14r7OPn8HEnv+W{T(K@7BPw_Z%f`G>8@BfI_2w?8oOE%*@UCN`iy00vc{|3$kh}X)&Q-bl)#cR1A zs_}T_zQpYQVQwr?^P!U6^JCte|6XP$qPD9mjg3xKLR`F%&rQZPHKfHuq*zG0gdlR$ z3|QtZLRM_qTLl6dwPM8_zP;owXDqAE0;5SKZZ#a{Hz}vBu<08hxL&&QHDt)$IZgW3 z_m>b8am}ai&?28$w!?%Z=eR(*&js7(%I1L%h+1U8R=88po@jilRC~f{WLm87M*xgT zhM`0ciXxEbXHcnC@hWw=hh$So{mCh#3go6WBz1?iRWlxq<22yIKS^2QJ+ZI5VOdP_ zOAj^avt2kq;9E22xeR*+>ZqAchIG=JvhoW3cJ{u)b!t9ko==7bD;9zf5!;p?f|1)i z9Q++MfXvY4rX&fsB$siVK8(D8S{jkNl-3o7Zv^-iMLez>vucCbKbKip`?1+09q=}a ztURw-En0ME<7VW7cW8u3F#Nb5-8NhXKX7GzWVAl1|7lDWqlu$nknro|Jzo>xt7LqZZYtCp6}!n=mqJ%S18OjKI&7%y`7 z$2=j)#ueZ$sm7Hny!=b!j6;B;*RV5=bK6k70o=cimC)F(Z&(jqYl~UjpG|+%z~NMmasoXf@QymP%|ES(hIL>U*7u&aj}^Kt zFNZH2*Ops2jlqi2>Rg}m#Vag|TsR3-Nm{JF+k+L*{CbcwC zQj+WQUvBDnqML;?woGZ+ECG62GM(xoLThx;V{NAu-3tHh1jVugGJ0TgnxLS{UEkVG z>9~$}6DvoFz?@zL8x57LIO>TP*BSN6yqOKa-t5N(O4cEi;?*e?!NpL7#=_-lj!ES%L3Zg5n*;m7kQbWz$L zdV#onNz6eHZvzf|O=8iMg`WNby;Og&sI!YV5c0_dYSNxFULTFqG9gpUSk-mt{n-C% zbOnsXfe6xowt|<1{_de+LM(PJ07n+W8C%OsM}@(O61*;p1&OTe74_TP9j>XF@+1MW zEkK}ZLmlgT)?0ubZp6fy*ky)2k@=U;Dt>q| zL~q%KM@G6tU-`S*WVn^=D|m`n@i}#y6j~EYqNcea&&5vx`P>sgx@0zrbpoj4@|^gx zX-O#a2vk3_!`(GqlQVc;gb}rl&DS}!dB;Rg62R~~0_b{+e!{L#W4*oV{F5uN@Obw! zk4fYs7Jyq!lJ4_WV__{uN<2P-{#Y#I+3)TZOjYF>SouMceF|!1ZVof*=uXWHq^{7tA@r_}E8_DgDYIB0>i64eq@eBSix89Qs(!9h zo44S)SWj#vC3}UxRw%p9M3PM zMaPINgv}Hx7n>39@Df6)>G7gzs;lQAx6~-|_;5@_Ax7!usRKi_pB?j2T)+{a^~Rv# zdm><|ciJ=kB_m~kiRgRRVvR{r)9xcdvB(ogU(qp@X%M6~!ygvDwYR+`^`u!4JGK_#335}K2XhKr6@%1imAGhCgp#$8=*N2G6TM8aYZFCWTO@Zq({ z2Q%%=Mh~AhwRmm-meH;hpmyE3imudbrj5#e1z!GMh)&LtERw3$mhhZRxMic0lYCT4 zINdMVzE9n#{D~Ae;}hN{xq_I=l9Mt#-yLlN0-#tmCou;4tcCKqk4Xy3YTS||>1mbo zmDwn*8r{KmBbEd5tP8y%?85dzB>O+WIoPlk4|uQ-!}>~42C zv5`n(KUKFLwANwhGv?Q@=E(67_G11F1x!k8%0aej0}#uB*m_Qb@BW%?VC;xi%kc7d z>WfT56e~P&XzFjJqlrfePi4<@U;my0$>fBtoaJcUge_n}lghs*`S)lW#3A3^!&Bhs z;YRz01wDSx%kbDNk}(ShG7d)e!tMnu7My=?U&lbyn7PpY0`TmFQt$><(oXG_a-nk| zXYI~Zw~YmKR3jOkQ^&;j4@~{BO=v&oI3|rPKjv~POUgT$$Y_Fve8CT7I`bS=lcGDh zB5ATrM6IB)&k}Xr3v>|h5Lem6G+(M@nTt1@O;Cs$H>}rfo?8mr$xxr|yF)Nd*)_o7 zi1!0M)cKnOSM+uRH!16B{oM=R`(w9r7*}z$$mJkXh--U(`UM50+iHSVEE8T{_SB`$ z(XsJg;esNi$R92IE+6n7FUVEjMX(s>B^5>}F~h~l7cOJlQ@{_Zq=O{D5Q_XjW5j8qVI(#40Aq%e7;wd<65^84A=|4s;M2 znp@t0y{a1-v&-gh(P=>omU^W%+GB{FM}6#1d;b;yrh9JkUIC&$Yg-?CM^|n1(tqdP z`<4$qq_KAnVZN_CVKgqTfW9dD|^=`n2)+hOt^M&XU zq$_PxUR7dWWQFB?Rh9$dEw91{os*dDxoB}$1M_Eu*PmUFY|LMFxAG~J=ljlBP+5|Y zqXl80z)*4+9rh^Fpi-gfe13b!@1|Pd$8{4S4499*s5YQ8vqg5dRr8{AF#O_chiC?> zI||Y_(b!c+^nZ_ZI4C>2DcoMAYbi-R0Or)-B0F}AMSC;QdbGT#+-fS*be+zZLt{%= zErM~Qa+4E4uHY0`f@Mu8MiqE^JUF(o z>_%)ZxsduEoQhz7sj2d)<`mSDar*`yji9X~{fzk6jr%m2!!aC~)o{1?8)787h*f{fb-x~LN+A&5lF!FGdurYsCG@H>d{nPLkv0_J92p|V!?W~Pnob zWya+;d`Y1AuG%08E$$MKMUPmsUW+Gty$jAcr&fn&h)6O_Ran5iZzv}N4vcZqESF5r z&f)ltu^8l~8GEdrhm`SKAhoeR5{uho{5Y~g?}|Sff#~n2hvfqk^1)o}epoPfhYC)V zoi+&-#L@6)A=XP;JUULT;w92pfR0Bi;fJU^H=gVd_zz3DiV{Tw3f47_xr9K z$BImvL_HiIb*|%mP%q6<@hgY{=W7BzLO-vbN#dOMb1%ROjgG0=>uz@+G|3ne3tB#v z9`gOJCYr;ACq*o8gldTim|E5c8qh7-M)UX}BARI%&ie>lhfaFHigvpBe%>MN(#&_} z_gX;$pcObx$MUqWjz0qBU_!?#dA)#ozS`sx@O;YZefqs)-t@UVZos(9q^~OS3FVfG z#e$a{W@BwelVx_gt>}igbld%G>Q1>g-kY1)xzH!c$Q-!M1Rjk#L*v%Sx~jRuvt4e~ zt6(Z%@t7z|Oh2mag-Y$`TSA&}ZrVbDn!Lz!2DK9SQm9KnM?L6A*)z^u`^&X@p*z<7`q79FkiO^V3H89F!DBQJ!9c-oI4PK-X0jY}5bm5*)@j z4yDA%4FIlNwAb=BVSf8h&HsJhSbQ&lnok6+TqkdZl`+KfWgL2s%|;^y>$~&jDL#1q zvLh?uU*d^Bp%MK^pRTksXLhniQp}9be|6eK{xdCmd`6{TDm!OMuoqP^^xP}!&t z&njFJe*j;P@DT`lB^wD_O(NxUy_Lb$#76gO%zRO=^AS)Odx{7@Pbty;4Vh6^cm81+ z7qyldr4+YMoSgV~V{zOLveN}RC#S>q4I+exFmcS{)olH~sa~e2nc2?1d}AxTHcBdQ z)UbL@hzPM2Bm>Y{b;BPD37B4)tb}0bXK$$rh5fSBG9F!~@EaC`$WXwMzCpR9`7s$@ zB+Ffox1CUNu&3n#0iH zi)DS|^=I=2c-&&y7&lvfSoc0R8xm_yEG?1_eQEfC=Mf{5ysiUpEtHKB9~;aB01(Nn zfcVapF{q}MkHpP*uWi?Yt~5vVo0!ROE;oPG#Qvlh$~!zICj(0uS`5Caxy{X}>p@jl zsg)rPfByOD)J?B}bYp+APN5dHa!b+2Vy9_@wermU~^{^IV7%%r3Ah&!L4MB8-ZMcMz$`wOArW841-UnKGN;{=$Cx2yRGL{M?Ufx?k~-anweE`WPA zBGO>5$qtBf<;_gqZIxOrnS05M14NKqy`6LZK1nXxO1szFMl0oFHkE4oZbH*$@A~}2 zl^Big5e4%C(ZzAM95BDh;adb9Tr?PC?q*TbwXsjOUbT`5<_8LBWGt)-UC=!vAvX{63syiDNJ$Y(EAiSwU>aUo4Gl&bi3dGh$!3 zwlOcOeG+hpnu5H|8f(6{W6be*NqQq1} zSDfEtaslKoZA}_~<|UZ)DbylZPk$yJ;7m|QfdPtojyI?w>O_uyo~tl4R5ryG$E#Mq_$CW2taWKA-oV3t~o_Ctg=jkTyX3x__|w6Ufr{n=6(uz zZ|>-ID7^W_#%Q ztAHXOb{L{S`}tR9Jfye2W=b1n-g>`97510aD={LgpE+nH`_CC?gB32hH$5Zk~) zpH~4EO*C@xY=`+)*Cd(0<)Y`su!p6Av)8I!o7{4OQBC|~A>+8^e-o4RRcPiIwOLT& zNXOOu=6*eOEbm)j(KUp?V%BQT6Ii0+-xqy0O%3PvCdEIO%4-qxEm;${Ok^;lRzjfG z8Ae30$VUQWC}zC}&hTqF%}1!z0v9{)AGvj9Oyh}N=PGZTVpO=#3t-)n47L_BiV>-m zU*@q}#OiW!dp}a|=kQr%3Z*7zhZ8v$hwEhn7+ouY1hEtyjEqI*2QD@K6M8kHJ!AAh z-XL<1FuVL#PCJC0{A-p(s4k({{V;lNo}iM4Xp1jXTy`l%?QaBZ@R^x8`z7I6zkvR# zRm`jU8WNYLib@%AbD8J9-=CoVN`}owcEZeYLL%OUPC>9{=sv)IMWYRg0eg&MRj(yr zxRa2-Ot)KeQo^L$Ysmu;1yC6D%2A{ncz8JY0vFpRz~ic5cIF*H`HKWbyzY1o?vt`{ zY=rP_@d&v93Cx~^jdpprG35=R1{~OBr!!GC>>184#p@21-VK1TLN5TV(^{wR613d> z#tW0MnL4bQXk%Y~c(Sm5czItO$nC%+$P@i7(Lq67zV;zRWqzt7(O3BJ&;?GhpTfvM z&lz`pWiJI4{Q1keRSB-L-lq8l`?9DDY$|hw&x6(?HK;tZA!P>5ak&rrBH$Yql3e#l z#ctQ`Ly7WjYL4|wMF9(0GA`#;Q$^MxhZ~FKIjbas#%^{-iMuTOx#s>UZK`FWT6Orf zv3CX@c3gp__C36-2j0H=X|-;}Hy5f?E=p6npc@rmWMn}qqdMskjF!K|mpb)JdBREMc4R^*IY57s@l22t0(pl>BG1TQ7MKW1m$*I-JXyJgrYI z;%m{MnL2#uEqX5MA~B8I1V;#w4m`wx@cvfA`(7;U85nZoC~hMV!2@wqx4l3EF^wtj;rNHr;9fj% z_@rR%<>5WeL}Gc*S^m)OjR4g-sM`fZ3yNj}GBqGFUoEPWT z5@MEfaYl+gY8=r1*#_~z*el_%RBPaS0!3mAcxPF#B=MkRXjQ9ymv`12Y`b*Wrxkxh zlsjZ_k-0Xz19+T?f~2qHa6oW#GUdFroAYB+9;m(4Xo2B#B2|*rg763HCyNkEAhQ;+ zTE&mhaUYV6X)g){YB0BWB@FiWJLrkqkF(Q802DIllo6K4nTm?|jgFXE-%qfw#Lmv>;HJTz z7lmYtFW^(M4nj+uGJA?yo5a25f%0CdNO5w#t5(BQXaF4fm`}VH_o0 z5zQd;a*B;ktEQMmz^M}`0AkVCcr|ufZ=7eS{x3WAhZTb5sOF%*_UCEiw+R#flr8&* zB6_%v31sH|j1;67y;7tKrGSfRjq(wHDdM~8HRn8;XRaIao9G3EIgx9gfuFzhTSWb~ zWmq!!XDUzZ+>%4v9h|+Dv~heca+Soz{PN>JyGRyts}WwTh)*glh}fM*US8xX*3r<> zUd{EUlcH6i29_|&0N#`vdSm5~`9z*j=8*-AzvkakPC_%8+sg>Blr}EwI&ad@Z@Wfi zHf0qg4^vK!jTuFY&V8=f(ZKV=ICox`|A+bqVD$!th|;cg+-?I$W+ye0C@0F3p}HB@ zHzB+ArJURtofGB7mj;{bx~x)jxn`CX9^zbX;(iCi6fYACxUDR zHDv{VUWse4RIHJM^=*^=VCS)~uNuhiz|zG(82k1A{}8W}=NV{8Fg(ZMsHN$E81XnX zIzGEWGfS+kc0@1Bv{=>#i#RWe#43Tryqx*z&Og~PAuuKlYa$Z+@Pk%sO)FZ=OYo(z}!MT_=DlGi(wBWsT?cpcI@Fz>r@Qv;aq#9qmjc+7VN zZt^SmE1ipq4h>}uqE6{KWb_LZnI-vSzQv6nVW`RZ@9xveD?L7lFPJzF#8vbYL~F@- zar9I^;rpiGNg$|+)Vk=RjaWJF7FHMYuDE*~T9}SEZJE(;7;W60a*W@t_| zev~7kR;=1smTY1%cPqa+!~*pjnmvUD{`dGRHbytp9wKe~4MBk5)6`i+i}L;*|crbQ!f*(9AQ^FqCqnDfZ(p++5?OXb7t zL&Ut>4E**Xm!Wq#+!poaY+t{K06e!D6OP*SiG`)!*@}75^TCqsv@4J%ds6t0}5~Mt=Az8GXa1ia^hVl&3OrxoI;8v`UXRT zzy&^=1~KJpCbRF;ISUa>dc)Dt3khX7Rc2_gAulBof>%m&|>(@B9o~EN!YT-01s+w0g!SAw7TAyn~@H zCCJP9=eCovr)~=+`Wg#`#tgL#QZM!u*k_8e2rg3tA|WF)YA>dRY~#&mQ{>Xq0LsGK zIKtlCQ4F#aaFu=PTeDhn<-SnTNV8<~VQqY4DTOB2W)n7MG`OP>BcrY~)2!ekGOf~1 zBpaOY70PJp{u;Ml(7CVuCe1{d^$K;_R7IoMD=k}*pymIcq}={*K3e!5mWm`z`Be77 zCo<8sWQL(%U;}(k-&*7=d9%F*k+ zqBR4?ipmnh9U~*qFP#%GCyMS)nc*kwiBu~q6lMV&5jLVjEZ{7BE`Vjd4Ga1ZJU)+0 zF{tQn9nN6*Ci2v5s$O${uhV4n?bs#__7ZMb_$I6Qvt~|Z~9E5aA9jvCB=uL>3 zWyVJO;kSR7gz)JBvgI`>WTzx4Hr^DWCM)q;qO82NJLeZ!^!Uqiesg~M{O61Hh8>n^A+x8QREG8B;1b$Xk7T{SD zgYKOWdlAm4yTtum9m`YGe&c`aq-mFY-^P_5cO~` z;g$|+5+}6-Ez()m9i~GlMAuuHYIktEm7E=>*6j=r!B8Yb z`>@Q=^5t5k3gxFi-OEnK{32o09mRqW;njP{;+0;xh{Xf^_L~*ej6u4-O2JL7)F?=} zliKaO_2z+JMeaGpfC4GzXB`cT{rPUdZw0>q#>2u&K$M707J-^ML zAwqIiHorX%W@>Vw5NDPF4Oyu74_2iJ?$mSy$M}`G1^_w*65)O(i8xMDcBzIM$%U>( zJmZJp)97a%lqXF8b=OS>EqhH7fX7rGTX1N1G`64UZ;i(Zw-)v z=w%8$DnsR{W-0|}>C=0#La74XWZQFH{?KsbAZ22wpU3|DLxiH2(1EKioc9!Y{m0u$ zfRR6}5&b~ab6RDv_U5G&gQi$lG`UFI2hCM5K@BG~tqp;tX@6X(7zw6(m%T5}y`P;a zY=lUS#76FqdWHV!BTGxVD&NX($MH$Yy6zG(<%DPL(oiM#`<4*ZuXs5H&=ZJ#hHAAn zXrdPzSlh{ktZL3m>o4TyXV0IlNS$J-*SXi1LZZ;!R%AH z-J@j;fJmrn8@(`1RMU3@e<7^!)j5U2M~#y;@}*1fyd2|b^~!&wbsPUK#k-QbdO=^c zw8!jU?oBL zLrb7%EPO?wr=9L!XNYx@Aq8U@4RIhB=v-Dz*(jw>fg+s3jML#N5hP~fIIXz+&L@%q z2PV`J$0Fwqbr52+M1L6Gon^q?<`yJ34&wWT_p%J}RuS*L+=i=%9jV56iy{(pu2>;i zAPJ#+bugOv1&H%ZplB4u`a$XWbZ|LRNzi10^tf)#YuVWN!e zJa099J|TD5v~I~By=mz6(rjCmevCSLZSCh88$vs~nr?e4;Y!)tQ+YQ z^3k9$M}i=T6W=$uo2So5c{GTpFuw+X71K04`K-s^}+Npu`s zwko^A&&-0JTcwn!e$R8YIDg=6;|Sm_?+>GImu{J(R_l`beD{skqN7LGvH~~5c@!hJ zZy8A(Vvp)KtC#)Kxy|CSb~s9OiTmAl0LWgc@NWNm?AWNcp8EBu)OCk}>icy=Iaa+w zF7o87t4G7V9@(5oZI1EgG>jLGZNXj5 zFYl5RjRk12!!A_|$)l;=;4C6iu7I!4AE26EbDCbrW3xP6USDcxMIy_&Q$0s<#x(DH zrLitnQ!>s4s;qyZ6`SeXVh3!_{k7sbg@*%wa>(TIb34cP97eRXmjfFb_00@Sp6w(u z&LrIBH9D?COwAc^U9lODIF!@t>`}E)$=sK2k-ck6T3Qf)A7X9cU^u>_@=9|oJnP|9o7aeGJmqSmHf2%MQobMum zsp=bT!0bw&n%TME5hbm4hb08>kPKl)!0Y`gi$i^0Q1t@g16FCClVoHQwkJK+!7WR0 z=-%0eqmh1>sb3~1__XH==w-;O?aV;z zJAsmIBuzMc>v>2gI}EXoCpoELjjjx01;UyZ+A^5G%ScwFd8Atk)xG z^}Q#@cgI!cPA4;!y!6`Y=~3Hm95w(84QW;ltamt;wUI3Mo%4~+H*nbSg3mEF*Y^!o zIvV`nE*N)Xo6tsk5O)*#MLO!j8^iuB>^&ax)i^7nx7~&~5QyzQ5nHlnd}o;1Sqt~= zV2|~_=#OR3lVbL@_6DcGf*_w&~f@t6;DwdY?cqL97xUFdl4KVO8_CO}1c zq7|GS6qk(yv_ammP+{9}@;FaL`hHHa$3Dwbs_uGQIq!{f!m=l|!}69p&NdZuez)a3 zJa51NH}D4LK}amdxW*I?vf@jU!15elvW6DLA6XwYAlou!$tMg9TtPI_+vg}7i5$N~ zXpn}wg=U~!JB-Jtob71IH#Z4wt@Nit8x8p_r-xX$%c^S7^`0MCkSeb5I#T(dHNnv< ztF0w6K5jxGGV0Y!B(RGRGm79r@xbH^$zthE(r?~mU=v0mL=Fb^OT9*`VxF_eG>d5l zMwDy7B%_%GtWNmPnW1FHpyW zKPMT=9er&`a5-M74Yo))JY%LgNo`Y}38w#dH3oFPu)WgG*#Zl-_XKX(ccFwAFi|CX z!0BWy%#?#A9DTrSdc;2F@f85yJfUpz$R{x^NecnRD;KJBq3$`}{Ly^tgvpxwk0GWK zbI^u-e2lKQv|MBg2D$${lmyTom4g;2-;>%>3Cz85C!>cQ|3eoJa60Qfi7uRSy>a-A z_8QqQEL5t#qgjc?Or-P9>FvVp?kQhvibCl$+{rJM%yuGjRen`8_!)=FLmK;WN{m25 zFo)ocYLNDP)N`rrgRtyK>DQGn#Z*)>n*~Ld(5I~$w0J^!jwVOFLd*JyQvw;!no~}# z^@cu;rdU2E9Kp41)Yw0R_Pt#?s7=43%oWo<&eT>>uf=Fg&&Ys1yBt*aNheud_`@3) z0EmeMsb7VOKFaU#b)o(0BoYneMq>5BpF*NxhRVq0s#>*!JD56faG9A>zSUi25y8hm z(1P^*MHJ76NS?A8Qzwx@2avc2JKfz4vClXalgNDPK~xtMSE&fK8`Oq7{Jo=~nY^Nh zU{e5poI1mjkM{mpykf0UY19UK=ocurTwjNIvM~y^U9f)JZa5J)y3Ahh!6bN`#a3v8 zzf=pt4x*kLgavJ{htWdBL962(;2I_7*Mjw3KzqwYRa!% zeGf4%sv8KF*L^rlaqVuvo%K^mO2)g#RX2wDi6t5tuY+`v68fMr8x^_qf|_9xz?Zau z_!hI?N^j!<)_}BO_yNkKF;`=FFs*rB5TO?=An54Tz!rS<P8_BZ=eY2oymkp8hNvD%n&sXEK? zoy)Hu+Rr+olEpUg9PEpGSJBL5`f~8XfMK}v28~u+u#?&Ccl?$LU0Gb`U8P{%v(hkT zgGFXkR&kM=+J&$R#*Sl%h*Us6AmW^T{T#~PQ-o@KaARONR#CdJnkpS zlEXW{EEn$k0PZ_!&?3P6W@-I#e*E7%L%2y?JCxVB-beEl4sGYFq3K#NSOENm!{^ z6W3rc)Jaig^BK<3ECA5nfsMf3a-|?UmsZYh&<0fW8qbD@@0M9(X<@QRm%bmhpB_z7C(t zoW#AAr{aQEMon2fV+m`DDE{z7-Valo+#@=Z%j(vZJ!Gc&9vc=eDRIw6Q&z99ol5q0b+>gt8+2NJQV5t)Slq03 zIX;T?UKR~CCbiAJ_&mT_r%NCu=#)os8!b4tAoleGVV#CEI{dPSvB7dEt~_z@LQ2>Z zMt~Wg9Ku!acYBwKpuHXz9Oo;?-2-$D~W{JJAs&Tk&vszAwCo!eH{Hi%6=>U_VE zo#O=IT)Go31y(p;;w*KO$pRyessOz)CQ{{WO&a6nX|nZkgRLP7XfmWFWoEmGiDtwz zjC3qXUvhgsr-@(efd8H%z073XNIQD-Z@tmDMO34%fG1-l{o_l9d##j| z>w%+e5&o`1Zr@vY%HE1316}=H-_fWtMo5q3G}F%KUGsqm?|V^lpx|nq+ZZ6)sFcFu z;wkx6_!&{yb6TurH`2rRCu7H|%rosG^>Q#Ekytlj)bp_~Zjnt`afB7L8mx|IGI$E3 z;m#}oOdJ8GgkLCsgzNs3UpiO{7TZ2Y12JAZU>egO4 zqq8ODJryeh8!U4@U_4+#Ke;iHm5OTowSin*zdZB6R{Keh-_O{fbztby1X-IigN3@d z=Zzp*#QZ)dTraTq<=loT1S~G>H#xt2&IV43NW719$NHG}WRAu6T`8OdH7f`RV?zXi z-IVE)LD`KUm}&PuN13nhf9J+*i*Q|LhZ52aSH1g6?yp<5qO^mt{)T{~KUqxq1eEz` z$n1t-(4Q8AyblKyQawLL96#-uI&%>90!#q5{-icDz9jbAQnojvl`y7_(9#kAS$Sn8!LR$0mF=`{uk;G?+29poz+;d@x zG$N@SjL>sUSiMMnO~RlvtCgNAWG;6f@nlBYJr;hceHDyD1MCNf*1If`UthBj z_xUIKYK_jm6n}LRo$Z&$By*(VY8FUAJvA_+X%+vr)m{^a zCjVi!ipHV9T$YdbZJQ%t>0f=>Mb{B7GHfFz`@&&3!e!}WZD$2y%e6wH4cR={moHMW z9JRA-AJ89~O(slODBcPqHv zl6e4rsCDkps-k()p1^jeZDb0+Jo-Twx1)m{!e50UB{D)CEr42kiKd2AvaGf6-QDnQ zTTw`4RAn-`Et$z-AxW}qoqsr^ow$h*nD!~DdJYvqEv-?gHQAT9)BrW@&)T-nC_I(2 zahyk*1&lV)w^+Y+L3r#}59RJl>J$WlWBm7{&!c7_5p-u^Zr^(i>BE- zjewM&9wt88QrZcfJV;|3BS$9(V}0v?G+P4;NOmSXI=p`rE-pM;ej6KGCr3O@JSGO# zzs(AGOw0`bO2&WXKj#0mGyf}D{+0i2&-U*<`+rGoJX%3p8z*C%zh2q@(}h;r*vMR8 zz}D^WFm!(}7J3FeR(1xwzov5f4u382SlIqED6N9Aqph=pp|K+#6U#rQ3V5_i?smri z7@8X6@$mf582<76-!X`oTR9m!;L(a$={p$<85`Of{p}!SY-8$VhR4D}$M8?Te_w%H z))1F;>PEAR=TF4iW0K>!ezge zL;}~{p)+v;fnVgumoSp*i|Wvlt}fE|%f$=r_mgJHl5%=##zp0et11<3#P4san$_e4 z)evNN{K=({t0mdB%AJt*t4wWA?}6g65bQ4>Uam!KZ68%Q?Z)$3-p(J}wAE2WM8-mg zN@@O*9@mbg{1M5_U}0Tsl}rTh5wlh3iZ`tXJGzh>$icOgpu$p&rba@C7`62#QLW>5K>QNMdegnf|w(ZwL9;IA4@qrV%w3p1se_It!fAm?(Ell=t%@yJk6#ECoY` zft1*Y@YgQZ*$Yb_;4h;_FHbRaLNogL?HjI7axjAhx6o`0x=(OZTeGnMb-#d=5BWxa z;X}el@G|Uz;&5qIUfS!re&M8bk$|$OzqMeY5ra@w@)4ywUoeHu`3Z5Fcu3rF7bL%G8i_$sjk~z?PeU`l80XnK#0PaT% zDXrKs#Zn2G7U`IbZ>j2;#g9Z37l0pe=0Ad*%2f4zVkyM=wSwE;VF^~K`hApZcZMo# zvpJ4kM(F$YTuZB`UvlPKTe>?2Uex_-F%;d#HPl5L@Pj%GW2H^bssvmF5^JG~$^pWI z5dEc2h~X^Ee!xLpqCnkIUsMY#F-zEQvi_mPa;R36A?^t zSP>xj_VPe!`|}MxDAsQRXu9;sc}04$atgf^8-vJzMR*-}ggpaYXFbWmG0Ku;oLC`R9=wjKWx&()m$w>tDVI0)X7N&SOA`9@S!@`uZe z@jXsbhbj7wWUWBb-e@e+k_GTrTLZ&#BY^U-*ydO$Ot8C_TC3c+6}mO*@k?I;SmZET zg;gt-tw?dz<}ct$@d9tkd+K>I@&)(HI_{p^iW6e`ct69FC~t0niBe}-z`7)XeC~A# zoX+5N(7o1^0R~Te0RsAKkkOHu8c9$M1O7`)tM^9h`s!{$2t-^Ft%p~jas26r!AKK$ zgpmxOY@j~Q7?1!qa2p%#nsN{l?tWXd2__(OQSg6D|^*9oeVyZJ~um|E&U<;{we>Ldo3fWko>n^&#pc^>zPu^@K5#ne;4 z*qbZiS~uIp?3AJ2>41o}dvVN%q=UOn#7KGzF%FMG&$LzZgVtHSog403SkRbE*LP|{t+4j+EibZ#H;cB zsD`wkxLsg&u!_r?hOlBFr)6)iRBbnryn2HGz@NTWtY%mbu&SQaVcQgwknmy{+gEW> zL%@}3wcSR;4?1ZBf24p=bsu#*?NV3UG%#;#iB^E5%7kGrUo@JCbU8j4bQO1BYrytZ zA)-@;-R|LAs>_Y2wDhW8uTn-mX!u$^8_Y7iHZj+}X9rH~UyVL`aJNfD0>8rvrCG!es8u{vx7N=@NePX{7_%Ld+Dq!EzK^v9ZkrGVP zVo}k+;Far=bO#lS4mXa;EM$tDA@ft~v>fF63OOABt2Z-44IoPOgsa*kw(r}2bMxI4 z!qA%9f9v0@>O;^0bI3IcogY)C>^7zB!DKo1p;Tn8-DO{Mk>edtN!loCj1p=P70H;} zhYGZ7{>g!UVPpXHD9;td35#)a7s?STVRmCX=$x9LpJ$iZi$?SUpt3|=-Tk|LU$6Ky zj;7?rw%Qfd4R9Dv^*M|inDczmmZZwp)KcTtJh%vI@2Z`v*qd&bE>%f>Oc_xU+6G8l8 z$FQi6S#bS+vv872xcu9C#d_>PjSoXeD!6GT_)kzH*^aK95&_kOPspqh1lTmT;wL(t z7vSD_sUxdUSw)(Ci#KFBkZWQ%JGK|!<1ne>tqX+Vc*oZ6-AB~!UzLOvjC$*J8C5R| zSymK1Xf`Vo$@r)~y@6Ez*p+x++CO2AkoQY#R2cI{m5P9Mmnlu4-7Kj0u?@@S z6C3sQP@-;PvzF8>S46V!w*p0tp~Ck_0HXeZv@YbUY5Ad%D+w(C>zrmPbP>5$0~t&{ z&7j=ou@%G7&AD_JB)_l4{hU}CJ;uA$P5@~IJk=@NkZy_^SgiIs}WXIbUNQ;7J5hvO0$}!EZh6)z(B`brcAmBOMxc-!#Y!+b0331e>Nd&0bc3 zF+?le4Ym?d&w7ut^$)q+pxxZ^OZyfvQP9cJCn;4NVod3R)DB|ha>rupsxXtRa8{Slp>w%=j3957Fn+voj6pc#4v4|3XQb|4)Ww!Q|(NRc)3y1r!V0bxyK=1*qFkfS3IJ+jV6@q2`;4rP-?UR3&HED~~L9Y3H5Smb%F~o&mO#CoSVdY^B_*95M%(&#SF>_% z_Lk!9)rg@8X$7WExX<^+GdX3awEY%?veDugVA%LYmSR$O(f{r7CB%D1{11K|-sl@^)+<2~N4rrGG z>jCS}3HwWNGMf87&x05Q1_GcP|4uo$x>e^$_9^GfhEMW>b9s*zl5l}X6y+sQhY28z zMNTQeyM$sH8mq@iED%M?t|9F7{hp!TM8GupLMtSa^OAK+T=ZuP9Ix~p7K-1zuhcIz zTUTNlOnMH5ZgcE!7q(t7mRJn~hH$VdnP*>VmW+Fan{6?j9BtUb*<)2AjUj&2|ykEVs}kJl$5$ zvdSmP_k_cR1Xt_68&!%~hZbBf+p0nUmeGJX_yR2rAXA1lnvhNJS_P9G7VR6zS!4cr zK;V}xwA+pkT?Fu@W4RZoxU^R7R83l$X^R6DEk`aZduco->gmq%t;L2xl(z_-9?n0N z<-4Ba3ykdGQ^?C++$0$#uEI8NXw$(G16~3aZjZEI%|b$Q7Z#I`pC94ulSu>Eji+}= zkJ6)SAZ=739|32L{cmm*XvvfVHP9?j5ozxD3HFY0;!MvgLh`f&toStjiFjrk4C)v@i6X`SrQ?KWypPmO6gfPs)e!itTR#!&L z-sawXNdiC##H^zy#u7_^zer2$P{Bawq;Btls@ZOL=Z6-0x#!M#_Flui%&mslv~)OM zeQnPwLCb2V4gz_=6BXhiWn3sG?a$f=s1jm;kcG*wR-P@jN}sDi)_bE6ei+p&7L?_R zA`PWR67-NoyeE*|lZF-S@4l6xi)(RqljxwWMNFCf;?FY9sV3kF*G%8Xx#=Y`Bjrx) zJyM{Ys=6D63UlDHW0VyGF+-ZDo~LIrBv#eZL(-S9`&Q!^`Qa=~lZ?8Lon1pHAb#dk z&o&qX*ZnpmO~2(wQk3?>BjJI!w>QLBlf$wajG~C7d4n-g*=3$I3GCSG@%1X>Voeb3 z=28DiBLT7vzN2sC7H&HUShfLd!XSd|Fdt6+ZUAvP(<+n`doR6Echtr$B46@43w0FV zRw3JKSbKHGQ#4I%S*_RM5EfY52o^`9`_=1fl0e{uG>E=Sqz;>-sRId`sQ&>5MU6`x zBJ>hk0~w>#4mT$8H?2Y;UeOX{je~XuQcz1_UsiQhFKzvPy2`R}4U?p*4>*nQtlJMF zJGy9|A0of*2@iUbu|~%I=|nmy14z*5D(06k8#;QyY#k>pb{V$}W1k}xrF(j$K{J)h zb&kHjsrri93SdS}Wot{=7kUG)`?uK;lK0ld$Z2a8lH(h6;psHU_QPGa(-()xM1?q z`4GA!Ll^K!rIjpqBxcK>%bH4F9IdGwN9^JW?*dRp_>)So2BcRAqlSB8J7sx3BNCIq zbL*u)I91z>m9ZUbT3}Ezx@WV!Px`{u@Cv4(&DHeuI&aiLjMXh*=qqn-#1^6>WNiC%YrM4Be8h1WLd6Y=o|b}5I%-t}IRXrBiXT+O zP_!-Kaas)=1K-q=+TQ%xoi@kezjX*DaJ!_kqb@7#K_gA2i5?7ghQdn z=2=ye+~}sxcPTjS9$IjFKF&)7s^t1eI=OI=ltU!qQvK#bXWZnFfLh9g=BDiS&;;oG zZ<;|ksw`M|u3>Y*VmEZCCiBc9*C2z()YSl4{U1&*c`Ne^Dp}oRW>T2oG@unq)_uiq za=Prz*XyFO0h0o06h#9=T+WC+ZmQ#7f0h72<5$EH4z zeZ0Stxo+d_h{S-o-K@W=@$9q@{poy+2yLK+3LvinxM4l4xZ5q|G(BzWd$3W_)^@*@ z8l~wIzT(;J5Hw_KGN04^^V-B|a)pxewOB>I5u*b%An2e65a-n&lLKhXmz0Sh$r4EM;T)HZIAVjCd9>nsW zya$^C0xo!{!LDtluM{DJ$-u2;XSQ-{yB z;;d<&3yjzjIXlw16}1Gf1P|?WWlI-Qgb4s2!)*Ut706vKB(JJP6Q2ez6co{EfqZ ztFt>_8xhoJtr>!can??VXw1t~08Zzk1{=Zyoujw8Y*pb{--_^Ib~>Go&;%1=k4FQ6 z)4QdVx!AUEQHQrZ;pN|riC1*RW_>zi%a|4=PJHfQUZMe~ni43mYoZ&l7z-&a3{m;s zSkcFOHag0XadlO*C|_u+9s=t!uo>h{r@~h-FPYbm8M!C+wxQfz_o$$Bx7Kn*`eWw_0Zo5yH)IVUx{8vxo;Q_ZNc9ss^VoK<;HA z?{1bliX(!IoUN@)JO-b_-eMqk95@(v`-8{=4@-0@H~tkoY?zuR2b*B%vaU82rzTwt z2XnhFJSXw!GBBR$L4Tkg{mH8d{1qyRQ>liFDi6q8WS zxeU1{*VDjg{TU)BVJCb+{(S>#1B{NJT!HFRQV?D)`@82=_O{`IUu}>dxRijjdmt!i zBs!&`w2@W)*vuOQEP7PNhgPrdT#unDhln9AoHQ%Tp)|OC-^Rv(iJ2H{cp7Mo$0HDt z#F5INbv@Zge2|~CbE$oS(}KMPj75o+^p7%p;dUtSHJ8s;x~H`R3)ZqEAek!$W_zg& z?tq;s1W@RV0W3**o8NT6U5J1Tc$*AXMT}eaq=AgD&llP&jwh;ka}s!JO<-lLC@`)_ zd?vVul%58o+x>T%DW-u+oWTtGZPelp^E-eHaDU-y%y>EA6lMi%Ru=xJFs!Vf!EyJ& ziL~*l1zrwB;;USJ6vnT;a>TxY6dQv2Le(+E=ET(C=ta6Y`@C>&zEx(mAXtc#Fl~#g z2RTt|HyLVQXKO&m#kPY?9&bBRJSDFu%-KHHAv6?*-wC1Z>utwyD!m>AI&{t48PohZ zW?YGrtsOVr4^w@nKrilpaMJo>NYBQ|kd<+=i@;;Ig=Z%pRn15?qSWQn*mx{sJ%Y8<^!^q|Ksof;9UQC^#8}X*#4iK>mSem9n=4lb20oyX#YFss@Bp@%@j-UeyN?6 z%oR43kn)N5+u<^ljWu1~x~@6D%URfhOA=D1PsxKGUE0>|K|oK32#+gU-y+2a5jQd# zjK+-jUp@C3QrYP-cz&Q|t^NLF&8bkvIng*>n%asOk?OUz8d43{D9##^DyhsIIA1w! zJ{{lkAXLC+X7(}>e>_ra-noqvwthQOYdXrW`hcA&D=WKN>Szemy-aQ1MEUTB)^$MN z;!1L&hI#y$;#HxVcH|Mud!RB&$AiGxFwu0;R^A!VhKQ~3s8)M)rgmGr?5T18os9kE zu<;1z^!VqP%3^)yRleCRM)*rm6NS^$yoLIF9j?umkBh^LYQ1|MEq@runB%y=qNp~b zy^!9#*^Li3w4h={w(!7u;ZH{ejmHPyXHyX{XB!&s>-pAHC2j4nth74Sp@pa0)5VQd zQ{X~bIg_la>~X<>1R0n^-=2^2*LmsK?+c?pgL!+C(Nu=juM(DQsU%FLtREjG)$gIe z=KOhFij?Rued#fbDZz%Hw-cePnXDID@$Zq%MSVU2#yStDnBE^~RHTtP6dFt@U2Dj( z-c2YFR5UB{?hU^vL^+vf-oq|pB!eUQTXa)D94xyFXtF6}oGP5MBD^Y;AQUy_&chuT zXQNcg(6Lm{+2-;}vBh4xeYl=$f!W2<2dD{CCxo*44!(Y|_2iC@5TTYqBlk^aEYn0x z4`V!t|q@8@`^=>mR?>bAO)1Gg%e@j9@vF~ zS;nJp=kF68RKmm>mx!4!1=Iyps+}`oWmbtc48GnrcyWZ%liYvRZJY5y*)0pjElCF> zn;og+UG=0EO$lekUIi#wN_n(G4kAE4(k7@eLecVKRt1TVZRUx+%wD=aGNsSdaIMNF zga$r3F2vc>IMYSura}wdvGu7(jdTkHSMp5@Hd4NzPBDV-EOB9-4kW-L7&mx5pW#k4 z_Y*T}SnMiRnn9I~7hajZmZU|qrv^E!gAdG86z zq20IDS_5-}FY@m^u`gdA^7&hxkDu>J_OutGqr(t*DXjP1Wq=hPFaR{jv-X&Y)~IY4=f^J~r&=)jl`jE^5>)0#GiGX2m?4%nh8;e9v|5 z4Xo2L;M7eXH($U#f2qP|+71A-Ku2s3zt&4YyYgwSs?K2d=A|o*y3^HE$3_s0B)HuM zF3BMMtN_!6-p~m_LkCc$TWoIv=|2D<@`W8-Q$&%)@Gcq4?MIR&?xA#Bt4Mlb;C)nh zowtj$CsAICQ$%_ZzQyEze^O~v%1cDyFL8%h(W)FfI z3oxa`(WK+q6#6#gNg_L*VVkCW1LY$$g4q{HJ~?Q|0Ne(gBL!jI{TL3Gw;K(DT^tjD zgWTaCYtvE-qEyZnJQ-vCQr*-3I#R|DC|t3Z;^H?n?Wvgpt5p75{`z=O)*ijfo`%2%Og%>&LF75TYmkTc zb$o70u;W-gXsIxLjrbPe_$Xt7P{g2*C@pLD@RL}&pnByp= zhhdSu8-CB;9`k$3xt9xjs#uBaXonOoqwt;RrJc)iF`LJmE zz_*y1bKLRw1_LIxyj{dDDtPxQZu8pI9yO&bY6pNoRd!x=9e^z0<*ftbe|VX z`xD}9-vP#7a6YwE@sCEq5}*cmB4J2E+vPe~b@n_B%${kkDMJq!=IU zDpI1XxTTrDfA{w~7EUazw)S3?BUgtn#l%`%1oL8Fd@7VA&P@2ofy(Mp9JQXoPo;1d z{F*w3CEoA>0|4*QJZjR@#KE*^fqV?BB&sP%av-A}4#1t0LR{c4=L~n9{h>Tl5?~!F z6gPXe@{99sn&U`|Uf3qq9lWkP%!46o$Hz>B(Sux?i^DYpkM;{nW)O6~_LG};8ms() zxV&HFjcZpAuD)E?k?U5X-8fE+J&8Goaa>_`tuM^cjL?#aru5s(`&ehUCpWs)KEaZp zSF0ay8@G85E9Sl4mH}by-ClpJ;e|CrD!I39Q_&F93F6(j43QhLi7?3Q2nIU7o+S{5 zpVt6e`P|Z?Zauo<+w!&%${AOJ2oSjig8RrtfNMjl%}Yod-y85Ec7f)T!^xCI2`&R5 zIj)5%%wGr?3tx6fGrLsivs})n)L?(z53Y<8BPvnOG*t^rrmSiFVgG}TXeX&DaEnY) zP_<5^YquaL9zFmA|KY`_yQ#xq=Zk0?H_wPyBlII>zp39_1y|%YvZflxP_njqa*>Jg83Y{Ym0ENQMc?(k5wXJG z-;@cOCBURwoqD7DX?llsWFwdTT~R3wK~z#3xM7!3`QAbvG$%)Ml#Jy<8ko( zRt3LXh7_Nj&pvph#udWCD?Vr=G3Z5ddbTI!OO#zMuimQisN#MbKq@g%SM_te(nbFD zYGh`$MiA4@Np@%eVj;*4H>6?fLJ7&iShSs!EF=6?S!ygi@LUNno4^LIdVj+W@%?uy z=ts%kFnMc)JRx9z$87T%I!owNcQ%HChDDU*U?_%HqLrTzS$C!`jOI!jCL6-aUhf$G z9#1BMasc?~x|dE*o#S!1VFb|mBmqabycP-wMtNjIc(UFbIdSil({Rr z0etGaaA!s^*~X8(Zd&>>7^ID>JG)I(9yBMH%Ke!4&t-9kfCWdDDjkaFp{TEW=y+fUZxzPMbxpSC0sT43*R+- zxH?LCr+g<1ceAQ8bqPXEgLC5+Wt>*F6Cmf8ZvGnC{WqrC#P2Si7HoWcdROOjI zfNTA5;>A5-Pciv>(0b;0b#!qgdn55H20!UQs0|lmQ({6nXAsuF7N;U6s~GKta{>DH zl2FXXjKGKT;(9eD`+;|00_;Sp@EX&|5uC$?@tJ6TaoUO@)gLeXDW_z6BPXkW`rK}F zoy2OFPWV+5rtHXX=SrUNTl$gS<`J_8#SXa)LzlKLzMI3Zm+h{0TT)`7Iu==!zr&^*g{Zv*ZIF4mJVI-aqM`lDdo)ii4a zu9T`0VmMHVFtTby$;Rs3NU|U|X2=wE?bh|9^N~W|>YQI?byqmtTRE}VYy%Sf^IF!o z0C+x^!G@n>C;1tbAt!d{9XumHX4}h47Tgt zfQYMuL&@xp##Gc?ScDPT{gE{>N+p~7i;`MjN+n7e&eN;{N1mnH?K36^meA|drEwZB z)FxVbz!4Q}|Ls%k+870Gubo4y=jZlW-C=H9lP=43^z6Qv;&>W&v<0cv%f5s5>@~mL zcNM@pB$%yr5@S_V9`$9|iOe=Xt#C4vezRiP_}RulM4t#|wsYJjS* zCv(@U8dOMyEm2r=yuncUhUu$(MpY!(bWF&E41wp9M92h+(8`>MuC-)%ylYj4rj@c} z`#6*OrV!{~?|-J_ovtv?jp#caftpu6XdNrZKK=)1?-(B0(?I*iwr$(y#I|j_<4GoV zGO;GMZQHiZi6@*SlidE}J?Gqe-*Y~kPrLV1t5%`Yd3yJ+YE^?|Fxiw0p}8mmg(wWL`VBCV}p34P%^3f?;C#5irXV}~{K_X4H##Mba#K!0j0O=owX^qjPQ9Z(Ld9eG#2XR8x1r%ADAEqxCM15+`%+-W&gn(XE&K z_MR!p`)12IUq`|YYfz=fF4vAxQn@}tfP&snL+o%{{=-N!-D0Ww;2CuB0CMnEc715^ zU6CHq-ksLr!(b^^PH%yu&3aR=gz~9qxA^NMq8e+P*j-4wNJ<##mmuHvYOq_kZ#GKHqT--34`hO(Wr)UBRtkq6!;T8GE0w9kF`Vq1TwI_*<+2N-H zCg4JcZ+btS|G>JfCSjkw!VbRdx##Y_-wt9jX2+7#b$qOHX6Khcx>>)8&GU{% z7XpZ^`gns(9=mKgzlGU`_R=J=52hDdovrj1PowqeV@_a~apn6wKs02xs9NGhowdkC zE|v);%rUaRG4@|xBBW-HYUj)8?Brx8WO?c}GFf}Z^|RK^jEeHdPDNWeUH%lpZp!mH5+D0ADmCk6HiAhtW4{R8cHP2F+z$A=4KM?dHhV0{HM`-Q`j2BQZaaLMN z3J+ncIh@wTxbvz_b0RnXEw>LZKh01A1|6!y#1k=hIRP@xF&i{&-ik!Il%yRtdZ>>V z8^(KBnRrqofk(GGy07#4^-EpHTwQN=3kG!7ZT6Z{0bj;FQ%?{P_ZZC;0IpIA6~F9N zI|U)!!jCO$3W}v#ST2;>0Q+xCDI!%ZWs@uJy-ye!TO<>CU=HwG*^i zWR8~4C5`AZ?xYu8GsKpHPb%O{<(l`0*? z_tY+;(JkO6q-krbe$x1K*yDeYnWBORUgy4R11SlrgO%{gI?jK{iuP4#(c@<- zDeY`Ln8i86NjuEVo*OAOH|Fr^C|pM1sx4uhKpdv`btmnM$cVbRl7NX@?fN45ggGCf zwrn<15P#E;41qoE>jm?p-Zxh<4bO>@=0A49E#!|IiB2ftm^@f*ek{p+Vv2@nA}N+7 z+4MMGRTyIeU5o}@oZb`YE}b%_rPCE=wnR8D-Gyyu3Ge}001 ziU_rZf`|;SS3xhNnv?XU=_Tmz1joV)qzU;HMmu@sh_|4GR*tgEltU>g1l364#_K5L zSS7qMoIP!q{j%yqR>CVi#BJ`{D>Ej3i_FLf5$Xzn6WB=0DQ+}<7$TNrjrZfs# z+}Nq>IlWS9YI8IJ4i5il5k7TC?Z&nzO$TSUp@_z4mLStA8rpA``7;i5R;3!=z|zt9 zQW&L22l7A}g&!M>bFwdZfb|k<2;)iM_4Nf@Mws##rml}r-(-6I3W@FK{->@7wTSU? zTDy1qw!mhXPFV~8BA?A!@C1+el zNSI`tPUJcn^>VE{n(B2ke(;l$(j@ZV9YQ%kLr{!!>=tc}FY@So^c>}WoWX-)!^G8# z+1_aL?6j>}>-LQ%8W(vU&(>_DwCD^w97q>JZ7v<))9u@@3tSWOw>&=}D_ALs5`0|# z=G;%|q%L9RMn0W*3o=>mqoZcY*As)fre`5|_*2FYTUOsf>PMjQ2Vu=P1h|C9`HthA zKlC@p@zMOBd#X{l_g%Egrh}SN9%|AYIXK&+t!&D>ll-uI;baF`9IXY77N2}YnIje` zLeCPAU?~l5^c*VX{=itucIFnj9*hAAtkcBsXV4xalK~rB_rj+V9Gi@|9YSMN$H{Ek z_c;mipL>0py0nRd6@G=P@NGN}I-M4|Rs7Ior3N|}pTc|Kf5adt(B=F`XVg2(YfO>m z6|$PFzrAD*X@NuC9)=fG$89&}P#)RPUl!wY5xi^UIBujrQ&&|YdN1iiV!W|8(T_o4 zDmQ36aN>i!KD9yG>M4>B&QpR5!Iu5put1DIz24&*4Sj3bcr6hyQikrEz<8n><4N(a zT`!q9j0sxksws#gs$2w(*_YGswAkD@%8rE?iGAh11HfkU~;5bl0;rvTmN2d~!=CX8|q7-q=fc;rZxec9X!NH z{kp~5Y~|D7dn@LqVr#Jz6t!sWwb7DdgADv!qxm6VTrwL@SSa=J4ZMb_5=gv0lCwhbtM13Rj zCig~^PBGM&9v#7QQ;TS$iHfV6QQr_JAr-aJSME~=dQ31N@Ee_^ zP02+6=i0NhSWxmzmY*V^b0b1yEl2a0V{z`!8~Cg_(DCBjtYolAAQjcWAAjg%Xq17? z+Y;ZCph|&`O-vk47V>p^ca1yt{2@Est-bDj`BhExppc>|nF-vBfS+KAc5T6ZK()#p zI<_E>$^AU~qnFZ%c;nu-I$80f<@N24QP0@IK-}fN#n+d?R---<$}^#FkTvgwIg5NY zN-uhp&3_p8-Z%F_^#ITq@P^w3OqqEqiin>)Ys? zcai8H$LN1C=RwVP^CN$ovov8wsKyv-+T-#yFsDXITzyJGEmK|kgi3kwp^&il%8N&N zyoQ&z{$hok<1?0$!<8sBzLcb>T;U7hMl@Mi)0TyitWd(@6(7X?kNXUGT5D#VKj_W@NE( zf(<6wHVXUGYb#}AvAC&{Xd8doKt|)u!SnUhzWKl}z|m7D)^8)V0tTaS-nmHF2!);^ zr(uOxv;Ak-etVr?Ob3QbI(eStWooBs>Ckb^KF+hliL)#Hy#GDt_}jo)$m8oD@o4r& zJb;_lcTPFtEFJhbXyW)dsFYvm20ViV-=}>V_a6NO$0J3mtZqT!>Lq=EkDw88YGEsH zN!feKjBw`glI!Yn`pO|8Ffj=K4&^EyXYlu}wH0U~lP76_yJXUoUQ38v%7r@CRC+6q z&ZHZP&?iq6jBl#*zKlP`52Q9+CJucm6{0gF7H{K{LS`3#xT+(%9r1lmWU&Z(%Rn%yDqJ0@2&f+E_vGg9VYM%BGuEn za(J@o3eT&)X_qtn{-DHXx?hS|w=*Pds!CjiAe~9e=?_s;7YEx{)fpmjS)U9EH&kS_ zh4s41z~X6$rklpJ8|Wj;Ysgx~?@N4z^%<-xn0p|>yV z;f<|G`jYpXrcZ~89NB2HPI+I_ZXHC7o5E^KB+UQDi1dn~!MTB1N_Akb+v4#a%5y+7 z`;sAm4KtRbwkTixg*C0>Qh1Ek4Fkm9;~EYrq?4akQS_Q1L&wJ)kvvNsduF(xaJMPk zL!6a~E$d3a(jo|BjaG&2`_t_m`0Q`xXL^;OQbXj;4FiCDkV6IFHti?`lNDGph)P)iGPQ&b{2>m*cT-P1+eN*mqRJWOF4Q`}#ORc_do}~| zH;6Aj21UrLixVmDA(_1NC?6ZDI~u<93jjdtv1SXUPnW7q40V2;V559K!H7yu*Dq&t zHcg(;PJz<&$?LM!WE&33X+C!~5R79*PNFOUd?1uS6Y#U^X8Kh!=5Jbp$9|>ej5S_v z*1k|8!-J@TPAv$`nz>z8wP6i(FRKSAFbm?&-h4d&vHQi>jYvVHbGJWmq$u+Q|3wRO zgkgyA))0%KAHRRt2N6aFG(H91a-!A9&!$~PQT?25J%B=}xzi1 zd>SSz21Qex4q6JbQgX9um%x58UPp8X`?i44g1aiz`6`a!Vzmk`<#9y;rg{QG~wQzg+{0C|GDF7JJTh zE~vJpFfZS*vYTdq=;B$DeK5uqUc~#(u$gSlgpu@ zNPrDQD5dO;$k~)D+cw~^Y?y|g48byZVY?ZS?(}a>tvOe*V^htQEkKSCOr6l75MWZ@ zA`D|kiDqZ|;X;_(t%6_Mzj%AJFeT0Za!B6NF=nV>tJXK}DsLqQAu-UmT^L4co1!+1 z*k5GfO1}UZeK6H2>;Qv|ZXfe17LQDT4lb+B^61rVQ0NafPFFRlc(G~qC}8VLI$W>e z&wZEPd0NS0OyMj(7FBQ?s@Xp@AphtG+*8>(t z<&9G?N5sJ88|1doAe^CLqFs*N2Ndou4C~;TBi+&OJ$34qHs!7;qpN-D1{)l1yFBuU zIJ{h1c-iA?di;oBNITNOu)7AO_1jfNAQ$6soK4@0D1ru!06qS+?Xt5IC^$^*!e|tgO%C(*z=xXYA-Dln7-Db!CRUx7*27RxRir~w3hN^NbPH6 zAV>{3VnTthw9`aHeGNj$v1dJY2Vj2BVA(jRio|+WqDL`FZ4i4tYv6m4v1;qic=L?d zdOS#`;fi_we7z3mW==nA2-(w?Qu^Zo{VOW#>TL`fjGFO!bA5;+$2A>Md#6T#B)s!p zFQUSJ4^(I;p_7GPYXcEteFBcpLj;~{OfBpvufa8-RB!6{%T%u`Yb%;)sP3^Lf-zi= zGK!)L+ex_+6m1p$Pqu5uvUVK!jX}$Z{W&pD9zYAyfoTaMG)=gp9Vw-L5RQe2LxZTD zY-{OP37LkrIEZ-_)Mr>{3E@TrL`t-Hja`*553TSP8mYYoG=hO7#u?xjo|~_oH-_hF7U<*65Ov04;XzyY;O!nYiBIh8Lda&n5q1a!NkG_VDMva=sqX~N8{PDENA zEyAR&Ggyr8$mU}?`+}2-C+RDmPM*vmy}{x`o%no7o2~LQEFNedT2wDWNy!*WZ8$v z{w0a45BC7QC>AtoncIk9D(d%9vV1TcX-&$aeWhw%2WWi#>aI%&r~V919fBjEZK(r} z&vs7M>m7``)G;c!Hblg-oFPNaeoGZj{Q5a9FgOJo_;;msTh|aJO5SgD{6?%F`50-I ze!b>e8IZfp{v{)&+%%(!-f?&uQd4{50t!n$3UmXs=ZRP4y}7v+@-RsY&L5ZV>mm}d zVXwWvd6Dvk4dKKG;5nW!KvoJ(ASw{V~5!k{K$S3O%y(a#mv?aEQY|m zHtP&pbXjtVED*+^&|u%IF)z=b9;mtDc=GyT%GO96b)<8xh4lys)2F}Y;2w7RCkwM`!W5bAxmXdd##o1sj2>&T{jZlx4& zo(M_r6=g3F&GgV_P8drXsn=rr_bIs}qlT?G<{fzq38S5Z?n5TgsG9v$nfXK1=^6{` zJ@PM7qrJg5kes*>Yv-9YYJlEmcXJg1kJSF_$k$5UxmxySJJ;e)3%9ez`$i88 zC^RaUk}2dSV+Th>2mh;7-P4`Lq)PU{vu9wSUZ$=&W1)iZwaOm~pp;U!h^UkhrCcEO%RR3w zUa}h+aY^pXUo7;x+KK4jDjmkF)(-2c7y-r)_EY8 zT@(%@XPN_!RWsl9B|r@3%`wASI|-O ze^UU5LdkMNa|8!Dh%duzbCoX1j7LZl#fjLux$+Obc5U|UPf(_-BT&SMyGV51;^n)B(oB1cXT8MVuj3_jtcrcDOY zXH&Tk(kE;R-jV}4@CVAEs>Fwdo7(!jjdFZx2tHnNds=MJ%`Eq96}3Uwae+0O)F97Bfb{x*Lzf9bz-JR9FiT`*|w5jP0r_qwSEjl;Y6ktzXh>l+gEKv zT}CdupJ}d)h3n=6Y-Se{!P$kH0yF-sbeTn&=K5{fwAS(>!4bwPP-oTnbZo1Go~0~s z60{m?(+;WanTwH9h*#6e@2f3fwR-9>p3dl!dl7$6Fzmm2scRPrOfU!a3L_#dDPV`C zCHtW*Pz4S=TnK^P}$A^J;;++{iHY!>|=dWK~7^!R3#l6gHD!^0wd* zyhMg*pN(TlE|eQoslAM{cQ9^yTK&Kgr@q#OGq(0DuE+iMlthcbf#VIK*4S*sE|W02 z0Y;Z%*FOnFn4s$A^6zZWB@z%Nm8v}3230oUs1p8Nx=PuV>e7VY#@$I%8oPxv_Y!4y zbcU>aZ$^8FO1kk(v53K8nsRJ5$o4OKu&f=CuUy!xwj5IDLfGL1tM}5 zeiP^Txf7f`*vR{e8e{s|t|FXzJVdxSCkGu3Qv9h=u*LY+SHyCv=SOKT%IOO0MppuZ zguqCHUMzBpgB#mBI`Xq_j{(8ZwP(%{K&eJ#-g+KiC^$a?X7^sWl8i7g^Hnm4rsk0} z+)Mn3j0lIWpIvRS&5nL6J7Uw0aYo#(f-r{QEQTI$1^Dk^Wte(~@PM#Me1{AB_2*lg z7kd#U=?l6AMZ0MI(7I3vS&POh*}`&HlJT*u!`2W4l^^z{{v9meO(ElG?tX;GCv#8; zX=*F?G)qke_EWd)n2vWL9qz$8qAsdPcq3|zb;?u#;?9@`+IP8Rs$w>AAJWu5od zrojG2r(z6F$j7L$=1TJxS}}O%Q;qjHS5_^wx#++(Hxw#_($I93XXE}Q5#!A#hju9D z-cNg+x9f+oPTG`NP$m-%m3=IB!?hV-&$NV$o18wva+6O&qpY8_#($9P{D0QD?YV6j zI@d_$WzjRZ#D**kfO)?1Xf!*MA9f)+=KlHE%Gx0m-Ey&-)-8JmctdfE2Szqvp`uwQ zY;N-GY4>8U8ur>UxabGg?Y7y%JFUe&Us^OSsDpfdGzIMi&*$%M8MhKl;R#upCR6ZJa&1xK|DJ5tw*!@qsAtdIrv;Ncq$rp7LUfyB* zQl4=rT)a;XFi#cRLvD3q=J5K*ACjUUZT88~0XKI`amM6l03PM4dFKUA>nfxlxP%J0 z?>KIVOl0?8mnX_Cza91e&U^}}7Eb4M@utK!tr%6EwCE$sG8@x~uH>s}Mfk?!*^+_L`a%gbQ z7pHPA*mwRu(2MUM?U4;oxCqVqxLn1m>}^ zGjVaVv;LKm_Fut)q?4<|-`Qxaz;rZq32i2z%0kh^!GeT_iP_D<3}EBr=*DbmW99B@ z;l}I+Ffp^UFgN-uBF)jv+sM_z%*5W_$l1gdVDq<<$=TeJ_FpF%M@uJh8#4e2C+ELA zTmEj~uM9RtcL!5o)*7%))&CLI_E(Oagcm?c4FEJJ`8!pP_3w+AD3E^qJ01U1z-(p$ ztS=-444-5Bj|}MdPtMzam9hUv#=^w&--Uk_03H7_l?0~G{jHZ|1@`|R2*fPO27LVw z<@rmaYyto##yS2a`}@|_$xO`x0F0+&Ru-28wqW4}AYqnq0FL*|zgMw;uQGqVA8OVn z<~EL2|EaF6WNHhX?|*OqGE{Rn1^gXb_t%^BpC125_Md1vUN$xsVDtY=G+p*&g9Ud& z*y$0)!F=Yx~7G|F@6Nspew!96k&Ds6J5@4IN!w zT~)e!HM-*a{#nD%8|+%c&tHYePM;5zrN~dahJN=LPT%@!cee+wkY66R8Fz#RYIg-8 z->)i5H}L&GRsETH_koLY{yZxwgf`v9OkFrm=&bZT9&E&Aj}Ld*^j(=A(PGV>2BrnIX~^J;@Q1F^iv`h8eX|+gw)!R zo;@fJ^{pshb`^3So0W1^c-EDLKm2+WpZh&o^_skO<7=AE@81#UM+-OgEt>ScVTO$}?VHfTO06_W6lX=Rk5}DBU!SfngnM3lH=TCge*W0)`uw;OcFOgyN;;iw zl}cjz(Zpauwk!=8(wG`SvMaN9B(wn=m}xsw7*E zUxG^^G9e51L{_H7DBSYfTT;mjtgD*k80d)OEUjuoppupmIEyTgF!ZyyxN}E+yzFm& zL#$*zlx8^l+~k<70}IO$;gg()cWG3vW!xim)XCqi<+7S12tGVc0#mKNDkHf^@u;@j zDZH*kjF_ji`u@a8pgLylu!!&)(1{~mHpZ}(SJ;80U&afA5R5-pVl`JqoMQLk!Q^Cj z3qdUpK~;dSTSWDXXFqYOGWaQ#pJSJ8@KaPNyyV!#Rqd4KB!-BoIhs4h*^o63wtJFt zPlM12#ap5_6iPP#M#A%m;xXB~mej&QF_)Es){xzYZkDy^70dyvC-CRiUA4j%#rv`~ zr<*((O5PKa8l?9K&ytXY{x$3(31z)0Z)}ZOGm03TSwxYOPuHN5g#esGz+f2c8CmU_ zQ=4Gw=$qAPnTimrSGrHz|NqVNTHYTWxIfHmGLL{AB8<^=6cw|c) zn?F|mlJMQvAt{QXv3qs=CprhpjF0jSsZySNwa~!Ls(SG|2%`G(6a;37Z-kmrG!ap( zSz=xgF6F-UT6Q}7nO=g}_dK4I?En`T4*O&?E_eB54v8H%Ew}J`saBJLLVRhT!e-h7 zQ05Fe&fH-$Je?l6YeWxPm3w?%vxj(b!yCZB(tGNi4(ZQR(+JZW#>m5<^&2*tI-GP! z_I!EA^m5kuG3A{(8wN_(E+LF_Nbr1z9jVN8MY35>T^TxmGbz!^;vC5-o4}9nQ3&v) zwV_A@4P12o;X3IOhm?ub(H-a#!{oDI$EW(X#S^(k? zhF>Fma>}jz@C+5|!YAFxQ!o#H;dF;~>PVO&rhp0|L(I8nQ&x0!7OofYE>Gj17S^zv zN&9QY{Cg-Q;fRh4^~vCCbOMrzztY*%gy_W}^Y@l+1IMAO&?-T?yASoq5OWxLJ%Z}owDg&5F* z5-Mf-c?Ql(>b}kp50HG)?K%Z{ttJZ%+U6NaxC+)}qg8Nhg7d{Vtw?gnx_yOpDyD4Z zmy8RbB5}w!=`s>Ww-Br+6vOky>CYHqpkmVKK1yfl?ieoF>dXjUhlxqY@RsQl^TFx2 z+8Y=Mu7koA1czA0?ea@;X++=BT{3t1d{fF^;dufcj58}jluz^4Mlp;ECV zlF?H|>pTE>27DCww3O72-t4bt3VLll9t3a3sW8pKmVO^oB5BU<{8w66Z4#U%(qU*# zcQ$_3WFVYmoS@DpjXX!nIr?O2eCN&J^WfxUZMP%@v|GA$y&J}rVqLDPfqYUK(VOg%r|DZhrH-h7% zH6lVSKGmXP#!O};r#&I30G3DN4edlhBP47)Rp4J6QJABq3;S$fg*j+Q#~_8VK$n+@ z5>x>rzuXO}T}$>DAe0=C$tE)@@s zO*9`!zM7T(d443h1ZJ4eD%{SxV6?nK$R!CyD*3o3Edo_V6NO`MjxSevV8y^yfcLUQ zV`N*;x*+VlykD14ja#QXZbJSu@C#Kv92Wlk0iLmY=AdL51gieLompYkZnzhvTr5gq zaAmr-T&&jx!TC=Uu~=nil5#xA=vao?VH=@3R8^djctNg%>RTk0lE`66F0?R%w?1Q_ zDN>YH!xD`_a1UJ^-h4_xF73>;D)~_s{InW*7>lS8^Y0Q#Bok0O1*ur|)IJmECFx(} zVoOPQ<;vMDlPYFM9h5Q31e^!oLH*0Mq+%D~Z_RS>Xmgz#=T*$i`|>XI8<)mjBc*fj zY`Wl5;igTMapsu$ri$0271HEm@HxE0I-u(T=#3M$T1wtp}qkc#9`n; zY+1ry`lNF#s1~aV)yG+7@f+1BRtZkTDq)f?caxJ%LbT|_Yw%z(5X7v7ioPV zrirq*$AAW1WOjiGj$I(gYpL=^*`$iDx)2Qj&G5wgdita zpWqrGmyLukfm?T=fwZ+ovxucA9%*koSV&{=$ ztavK^gIPGKZ$}>LxBeo=n5RB0g3n)?=^@~K71-(?1Lpaa;cB?l@&!)dCAomIK$)=X zyBkw)1O+w-?vC(r`O3(!YzCPnS&7(8i*bZOP`i8x^Wb=|=`-w3ob;?J7rtb97Sa?u zrqRSmdZo6@Gh;TFOd!WIi+?9i9Vke{q9P?e|HY0)m1G}?F`G#7*k_$*CSwgML~DyP zTSrk5ZhLeo7GFg~Bzm#SAhU@4t?74X}^1kDfjw9rI*F!9oKE+wwjL}m5?7L zz%@ExzW<@8)xya#PCDdiG}mU5=o)`}%Ob<;qcPPQDD(8iTE(&_R0c^SWb>X>+Qwf6 zm@1t3Sd_{kZ(*GH4Ph$^z%ov$H8qhFM!61eldMZ97ll5Fy@Z=;&R)M4kweK!w`H&P z#KAzDiSW%xDK#Vz8ul4DE^C(7@56?=sp8&V=d}0J4HTXxGBoq`6e-XZhLhuoGM-~Y zoO-G9F?1p26!zL|GGALLh=Y%&Mi3TuSUJW|sQqgPWjKiW&{AX&6%V?b2fGkQlVtcO z<|&FmhtR_cWmX1Mo;YB6J2;J!+pQC0Z$#7BQ>j!4&^657QmII(*M?54*<4IlneeP_ z5@$LGA`qmKaL}j1DtW`Gl1SQ^WEd6MmOw1V7WXNd)2648s7Xg3BJl({c*eEzHR zz(y!h@+`aYCYQZ%+$-SInYth$Z4wc5qhhaI<|M zJSe(ek&qw^PP$YKP`sd4bZzP@qUFswvNMU7brYa1ObNFh>`zMaMzoP1O`6la7I|Vv zpdAj^7L86SBS1fe%h%1ydN)(sYUJS^G7u<~iC7FyU{o+Y@NiV)%`{()e*#XGV$c`j zQ|m-A`03g8d5Ulf*XnK?wr!!6DmobhzVqu)^YYVn<+2MMsAVmtU^okZuV2e5+IC)I ze#Gw_c2CQr@=$}dH%IIooR^U{*!+XRu+Sh(F%&1po#G*cd}!oBp@$Whr0Jy~l>wWT z)a0gB1||~`duUE2rnb~ch%1vCw-Zgultw}>0#W#m^~7%kV6Vgtx) z?mw|#{k@0PTaa^$8w_OZsglYkxpv0%b&N9Pji;sfhRJPgO4Z&cFPy%8mhSqS-P7Py z`&09xC@CwYPmG2m?tNQ!AEh0bAQ3_rbss2Z?)7il|9vXyqu4k%a8TTR<@W9A)ynAG z-S0PUC^4M0>Gzwboz|x}-c5hN(9Tz@a74vxG3NEVVmYeZ*So8`cHupC{3VX=D}LeM zlUAR9K4L3r$EAI59`8Z@vE}6Mm+QQ)-YpXdjK0czbmSi&`AuSf9z@sfS}7(Vl_Oo; zEo+69Pb(uLvo~GgNF&xnx|~={#hfL$WVYdMnEbZMc^V9V89mA&a%w)9itp}OKgl6F zj(uQoTzmD}13tjw0QiV_k50))xO1|tj!(%;I_txNrLHpx+ZH%uUlh(W0SSHUHJSa7 zCTAIelnjEq1!QH5bRkNF#}n43xXH6EICsyjp_MiAV*$sZNniE!M)Wqp*drh*=ijX- zu|5M@0?74_6-%qK4ISZ)FUJbmd41Ny>d~H!ez;K2Hs1UHeqFXQ^0%?`B|_ZPB`f#; zoa^dZ0@)#ba6LJu#91R672wvQg+xj99~opxsFVHSmeX0uKxmeU=C}dM8WpI5r@f0> zzm#XOd{ZrJBHy`xU{VhJu#)TCpdu$7@SYK6L`KwyhDP}DgPB%^ZXRkO?ZQRW^Jw08 zsB(d_mX}BvG-d|i9BX65?Ir#~qX~z#9G4hsYheads(!{r)C&+e#&$$^keS+3ujrR| zZfp2om(djbk`j+urmivK{Ou?)RJ2I4GPe4cc12YK>zayeWOhQqlS5u4W(B=l_aq^C zwB>NK;%OQwqTV&V#N(=Vhk3WTpfXP>;R$A1{^f1C!lpgOC-hwr%Z>a1OE*sLM2*ioUtuS zfYwlo$Am#jpFhEdXkY9z}L2zeAoyT>@PQ&G&W$s zK5oUj^Lj7fO?4e{Y2``9fv0G6&tTh2J?i-g;_r;GuK)VO{$=()A5A#_E{d7^wnkiEspBFCh>>p+|_i9;tE0IiAbQ zU$^_QU9>7WFVYAb9!c=Cy0e>~fa<>8aC&Q=%p-7@Hi%Rd>7-v!~k|V4w*o5sw6r7d{Ys7X=T08xWT|$+_13jE&aohe0s?D2 z%L@498esAf70%2i2LZ>?DaDn8-sXxQhpPFZ0%`?f@W@Pt5pP>}o@Ii1si&=5!vpWZ z*A~N0YEZi;=>|{>kQiJe8hLrF^xy!7SJgRW4zvcDEWBrO!aR>uFZV)GeXb-6_~iFB zRbJ;ML}R^#9+aW(vdFs8dIzDJ0bKmT@Km_tsbp>BVg(LCf8tVeE)cU-e8k|l8)b65 z^}Cu8W)gdvnq8q?F>ad_nok`XZAsGYM#atP-v#4G5_2HL;nS-Po~TQ*ZbkUCk*bxR zj`XQvJ|2h-#v+`g%?olD5OuXieXrXZ>tU!fTz4TqN_SQ30)COxOv?K)47@e|$SY-M z;BFY^q#4k03?WLUKi>)@r<%Bw(#;V8eGo6kA`m5(AM~*CE`Y`H{X+vES0$)GUp;~hgi44BPgVpamgj_X}>Knuf{$R}|#@M@0dtx$l;#V!3o z$-OF89reyD>o_D>aA-7$^uQuKrypEa433-I0bEJwx*`b3md*?&lG{1`IWQE9Yo0s_ zy5_@k76095LWD$!%YC8s2t}wOu!0h8B{h)`yN}DyHhI30(|S3kC@03co=2`144Way zI{*es&@_p_3-|76@SqDQQjt@0Lq`ULEQTl=zRJ7^>&=n`+e&;L!U$D*Tz1z8Pv>S8e5xiI%qaQUMmOupXNf@x-Q^bR$c5nv z3%bnK67Xh@oWkRZ1Zw&lrKC8BPb6Ua3dn`Ig~m4W$U9?4xwaH5#_m%Z-0IBCO>;T` zgK_F#OO*Km;x=CCq$@KGW|%X~t9Re0Y9`odc zCgV&2uAZA^1>w{(~+ea^o>vuPasZu{+?&+j{A}X=@Phzb5 z{5pb>=fnG=6GnZ<3Ibsug_CnB&EJaH13!U1_o5ipcoKe$Aj8C0UCveIaJ}84igl^6uZ|&R=kH^v*H8`F~ zS;^Vf*v}vgrZc*4ZVAWcJG5^e_5=bh=gN~|Be3aCWxhz!4qrPNM|FGv{-Ef|5g9pT zZFZ+3-G$lshtJ*48jY9@23^XK=w#MF-H|Wzi2IQU*bmSj<4f$&Nv<{Rwndu*6mImE zE94qjR2h1pPYgs<=;2rbJcRNE0t}(TxD3Om%@g$uP`>69o7Id)gJ@nd6cV36Wd432^rX0z9-Tc235|LWV2SOts_8cOYhoC`S_#+Br1X z+Zm-Lb7D{WeWVgqboIB(jpeWT4MO4~K*w3iBMrb+p(woh*iKQS!N*A=FI-B{DM+E% z?bO$TC@?t;$^)<{f(eMCeP&hzDBAK)?2au((Xi4_e?R8cg32uIHs-uG5JcLh*I;bH zBKKhRkl3NjI-8dzT2++;!pKQS@kpN!M9?1lF3gX0!4m-(>EP3Z2#SHD@3@Z6B)API zVs6mEHqc)BYq_@p=mm@R6BqCl{czSUc-zHCDsf2dWPLvH)nLg0s7wB3S@k1eih112UW0w`7vJ&9~J7dA;? znTL-Z<4)U+HHkYU84#ozJVs1P_;*FU4_s1RT`4L-2U1iNoeHv(oq<9w+(lR|%!)xZ;(foUNH7r5Gp{PJ zZNEeC?a&WY=1?g?cL_kcA8da-{Jz@V?M)bk#`2}S^ACR(dVAeu=Hc)4_EpT<`0>q} zj-Z->XBjfTWoaZ2=^Rc}=R8h?Z~-%buZSMRqL}If5T*5gjv+jt6b_KeRlI`}%09sK zh60|k892U2tA@z?3V0@6~kE^@_EFUTy#I|;II z=kOmu0XNXW0qC#>bf^M4Ciz3zdM@SwL$JV1e-ha6xpD zT9>H|ureL?-gSHvF#v;_gy1Oe8(D+Er8 zRH>K5cVJB-U`>GrQ*?e{Z2%yOIH6FigB(~08K-y`g%4ce!o@fIy=VaUB+t0sYe?j>#f z(@z5G+-qNcj^sg-FAV*Gs0R@cJE8xu5`YMpa${~>y>BronKM(>@SK&hdmbl$zOFG* zg?t7d0R>FuS1Sa^LY-wo?H0-@+L`lAiFle3sHw3oCUzbMucn7>y=#(D{~=({6<8gI zHRv3>CCFBpAzw;5rLpu0?c52LslpuT+rB1kuU^fD`Eg1??`o}Ew9gA#y%63>jbs{- zbd7?WQ;0K|ZNP`eF2c%kz9ww`%NE{eJ7J&qr0mNZ!3^tZ6ChR)Kg%qNdS`CCc>v{5 z?9Ev(T;2`ReB83Pznw|$wNjXC#{C+#=z^#>)@@2R^dkED0gOGsq$r%f3xu^~*S&dT zfY*}HEv?@GLF&#uW?)Xg6kfFUB0sQt3iE{oJX zSo3Ok7or;>d)?55$1$Rt!F6lYZ+V{Jrh5+{{?R{`Sk_63M4Y;FHQJfGWV$}fhQ^U~ zAGgfLjvG!iXuuuf;Q2`ZQaVoCA!Te_b3YJR@;r-^Ug#U1;u2{Y&t)i|u9Rv9k@<#j zdQEaV4zV+pbo~EN_m)9nZQYhA65JhvySux)yF0-lxVyW%yA#~q-GWPy;O-UzH2J#k z?UPe<7w`Rg@7D%4ReP;DmyD^y#X4#K(^_PYHcMUJx?;QfH%8IA#jPk(zVUF>@U~x8 z(+Bate!z3>5Qt1D(~+_6EL@z>x?u`_6B>ivbs4b7Y-#nV z#jjv^KJA8YV#+6aOVZh9(Lh&)d=Y8sF%)3<0h=KB)f^|H8NFjN@iE$P88w2>^YfL#diQFohXaTsG*MU(-9+) z&ZwL$>y9mtQdQy0K8wrI;%{BRecn0;k?bE)Z^FQWNb&IiMz8Ql%+H2lUKAPGA0ec} zxHz2mhdTk`(4xYj+b7eoq{eIAir@mftlb5-*m(>|ej*Uv0L;>&iSb`&{sJ${gRjkt zWk`tQ7UDWP!icjweiIFQMV6g=h&K`@M)B1-Re?AJTtdLZf2kkf>KF>M&# z3w%TqjL$uaX)!F=^3MskO)HpD-ZiQ*pj za07eS<3NNJnQ5lKkOiwBMZFMwg$r6;m}`jiPUr(L>JD4)GKoE!y_Gt z+$5_7>d>|}S#1sn9l8MP$P@q99^aXP{wIf6Gd{X2ie9f&OhLbdzI5XW`BgIXz$$}w zFQR@wetL#F7FmCJ1$@!z^chrGkrrm_qr~zcFv72qeH3_Xcm?g(L+Q;>YX(X6&y=B- zg!sGhOkA=g1rz>gGY*QtfopZ!>cMATVV`!ddw~T5>Foy?HJrgz%sA<>Z^6tl==w)t zsw!0to=N(KvuFKjGS6OERx~)$jvaao1V?Me7Y*$|VZVSOY-3?zi@a=NKR>$E%V_Pc@KxWD{%dA@S>@X{!+bK(@Q>p~T3?(8p+7EtV?S zaKH74-0L6PBImr$lnrF9+ilqTffL zLM154kH=lEzI4(u9!V{)z;!8YkjlQotw*CFyqCQ8r@Z{X(#GCR1p8l1mv4pe%zvd5 zy>$RiUmdLMeCq%#oh`Uqqc%y(&aHZAyT&Gq&3f6`BIe$c*o+u`TZ3O{`9oJ%&nGts zS+&jLngErZ$b=7CXA`7bnniP}c3D^Fi~q)k4#dNRv4Qao6&ejS1HI;%&hxJ-%SOLT zTx0bzEqeD0=Tl>m5+$S0QB8HxRbHRDvQbLsk5;a2Op-XZA1-+}+J9|p>Q7XNWj44u z*|RdzIJyGbFDqfvx2aEfNw2F8P3SYfE>6Hzb+&~rAmc?U4=_PNRqB5M)_^ZntiPbO zmnXU{{?(~5zbi0&pUfZz;zz+A3H`lHNpmKCtIxB+yNPm9xeeZ22ms`B{C62bpIVZ{ z)FX(Cm+gtQk)64@r-tEmTCc2fsz)305Ks^b`baE}DTVmZa=Z4Y7X?s5`>)xwXa;L# zH@EEdJ)zRi1se{&GaTxo)x2@mF_L6v_jvEuI`_dT`M+) z)MMLekDuv1*H%blCC%ga)(tu}z5)1&?TK;paemeGsC2m~} zY-<0f{3WNBOwA>FM*X2At)jXR5PN!`+!hWBS-1TgO`Lyuc`iq0XPHdAaUk2VB6I}c z#ceaQ1D#jR0~#GN!>b+oK3`%*I_RKltVDb~$NFTT_-LyY+WE`n9b`hWnywh2+~gAw z`o-58Pc%qrovdIYK6Z7joQJPjVx23yAuVb+j>)M&|-LMJ-Q_5f=HtH$y9oJ zpsS)7pjeXv%#f|YyGgFf99U&q)KegoM^&FugX*p{Pi|bLZav6-G1{+XtkRy&?Lfuk zDrcL>v@nyC12590xkK^lc@E}TQQnHfOIs94HDdFH%ON;(cJPP=E*zuM_ys`esDn3w zTH|OMP_8hliWNV$D0Eg^ncVG=@J~==gDcU-Tzui>dXovEw;Np9NpXc!=u2nfm~IxG zdA*%MbQGy5KiNUg>Z+zFdD@$``B&D&K=4LZkq4Yypg@_4Tz&z20D2n98eBvcaC!&} z^Z@NFQqxR_M&IssOOU#DK}!Tv+XMYPir35)S&b&?>Kg;?a6JI-uT^ZLYPflg5LBP1 zr}Av8{_?Pm5+Yq=jn?xsP&gajZQq2@nGDJ^6HW$SJ-9r}h=ZDD&F-b%2s@=HhHAPe zOHZ$Ks@PvqY$mW$4Z2kHp>|Z44@{S81qAivZBZGDx6YM>#!+3+2eymVcD`P2)2i|@ z2LfQ17(hr($t^paLcRTJ6vJ9Dy3}ce3}*M59xC5=dchb756D{s&DSw^eaRSzjO}GW z?~|x&8AmVsRRJs;P0~sK<%p6Z5-88ZHj$DCms_tdt>LQ3n%C2v8CklIklumh>GB-K69!|P(P=U1x)=>0A}I^1~IC~ z=^zK59*Dwps1^Z0t2qbeaTXlWzidYC2$3VLk$#F_kA8h{0TEQJSotD#S(~F|+tU!} z4oZ2T#}sIZ9bvG%*_=#nrbuLF4N0p^Gp`KonX8mPvC*ld=e2mW95Z6NcnkIoz!I{< z@lnxR_H;MP_>4HP3vJ8^5RpX+Q7dvwVpt|j*tI6nDS z4G*VE%-OC56qqM8KR>NrshuX<=f+Pl*>FuuODlip<|96oP^2C^O$vf_zDaLgbg)%T zd|G!SJ=1_itKrxZ9qoAiX^2X`vcodK16Ag0(vLluWzsN|T;NNWeJRifP~r;v`Gt9RL-`S#OYeFh_gZr2`5JQ#^PjL?i>D=rB-GbZC#?cU0EJBr4tTN+sDO5-<{RV-_XS6h})K`^rMFlZd2SJBs-6>$&A z3PZn3U1_NRLL&PR-yeR&Pi|MQIo+=7 zo5mcVX}MP7y=a%K3-!7!mnhO*7a0*wH3mg|Uxz4NzUPV=DPk_XnNGFc%XxKM<^4P) zXBFa2D?CIR%;y#xipR_I^Dga#2Lm{J{J8I3Hbw2Z)=l$`*3MOzltEZo7i9hx*~jK> zKeyw&mhfw+Xll8vu!$tMi;AbA29l1TjhGr=BMM?bi%q~PwmiRpn|gB$wO?Z+_SQl< z5BmWb%Cg|=Cs|gjNf>y_l7%^Sq#lpAaTEGal=y<2A5d63O0Eml7%J#lXIA!i@(cQD z?zAi3&)0%xy34?G+%^Sp2KK42=bpw+t5JAlvDfrpjXaGGEm*)s3DvI^Ye=73SI)_sztQACaRY=7 z2jd|O?{|X@)rE@k5oEz3ZpHwI3d2SWudEAje$`2pQJIHzIu5B>(JT>SRmM3)`F#h7 zy$8>c2a#j0HbA1RB%0Ab1^r~7>j<#bN`B7jAhuvVv$7mXNmszG0f_A{2S$sCMGM#V z6h>7J^@V^e&M?&uH6n=rL0^{ba(dx1IRd&oSb7)D!06GRac9fuN6fV;gt7C4z9W_5YVUWK(_C75+I;F4nG1(mpV*v>PFF;t&2tXY`iueqF%An z1q%aT_hvVGCVAc1-?CVcYH6*)K9dVP4uhHA-Hs9n^hj2qHYtbWYw!9t`?~|J*pZOC z7Vtu)s)tae#|iR_^U4Ma;L|aMybwhX^pfhYANFPv>XViM1X1AU9#Y??6|5v?gKyZZ zJ^583DG6Z30JC>3VLRG=&f@1~0j_QvcOgsR8-&oXftfX&hD{LjXua0q>a2Kf(@oMV~qnw1BQt?y4DA00#VZq;| z=Mccnn*igDMH&M8P0n<6GVW~-z zhE`-vo9TcFP1+9`Fa2!?aY$}I@wyTJb_m?)=UvNK$T!ZbQv!o)C}LW_O#8MUskIY8 z7JKVTk=5;V@7lIp9zZffaq-caj~~|b+qB}=L5lrS#0+6sytacl#*gHGx-U&>@UQp| znpH`dl?f%M*s)9AZJYuWTf0e7vw(a1kttMYRm(!KOV83h;|rI{S|;03eOZO-egTx!sVW-uZecXpG1^JLN}j%v7EGoA{W0ybLE1 zT#Pe*4<@la=Q$=A_(7M1d`}Hd&qJO2?UVXHf+493He;rqvXwz}95BNG$JX0WezdXw zT93hj<~YX$s5X|8|NZ^<84N;DkU(LGw(YFT>!c^xc515TbyBahwuO6b3d({*#Hj3?{9fI|r6<}G_ z1#QE{i_-fe`DB^^V9;mB6;?F9yf)}+^VDeHwmyx(W6Klv{~~J)e2wC2-{R!Xs0p|2 z=ly{tFNKp>9z*5%)D#`TG{+cq!v?OyPa23-e7!;bC7h?H8Bi$OpE~g3 z>BmG%c}TW3A3-EcPsK&H&F?#kc~IWY0nR)@Z*s0CxdUg^yr+x9=yNCIySjBVujqv$p=&zyvZyqH!V| z@|{2~dw{^=$PY~stPJ&CTHw0_802YzKH<-k;hf1j`6UtCU5fp-z!YJ#_H-g{Mxa3A zzbz`;ub+uQoB}vFVe)}v9Pg6>Ujh;e0j>B-4eJY;aKcT7+0eMXafRR?mNTH0XWXVv z>zZG$U6M-{xmO>)(_Igh44@803_TeEm&dXjg_nT~`8K0!!bt<#^#Q|7@&)tu33Vxi zH#9*mUOit&?sM2Qb7S#1YR|`kO~E1)j04|WtcJlg7eR=2bgnldpj9a}g+Z;R|HKul{&9P&fb0tSg?Be+42<7ez@!NyfQqIJvwrSH7=EggDi z{9L;VC>~!GeThYkijJf8?BKq+PoI{wK)!XU=BnkrkZbw%syH@;1#IxJU-85Rn_$a{ zFGhN;6yA<58A8+pY~Cv*eI&!u{`n?^bYCXn&^ZqXDy#`rk(Rug zvwIXu9cIV3*m$Z44nGx~p}CZB0jT+Pe1xEp#h^$ZXx2q?@SKN*bg<~RovudH*GfEIIz}fJNft+CLG$gj&~6A zS-vRwJ;*p!yb}kA%^lR4yKOm6g~v_G{n;AR%iPsMmZ+FLTvfVcsJhp zWqGW<{b%0t>iu7(WT2=`;% zq(i9Ac;{1Ka_KZ4U-Lh;$mY26c{U|H8uU%J;U(&4DeHgnb$2@%MowO=8FTKcj9#O+ zB-@$5FJUdWnzvJ&ezL#GN-rxviU#13QIQllsBa#!cxiS+% z)$a8r;aU>LIbxb7!p6MK9)^Bm8F`F&tuRMn_sUS8VpB3DfU zZcQ#WB80S9rqiq@w9_H1i&f9}XF<}>1cZ*>E^#*Fg!}&9eR)Gc*e=|-3Qz>rvwUl~ z`TC;;)%!tg*Njmo6uB>K9dh4qENsL|^P=OLMFDam5M}xxNCQN=Az8+sVUFp)&G+2}_+eDo|# ze>wQLV|ow-@xg`8RceTReE7IWjO-q|UM=|IwT!U!?n^m+W8{Mw`%He0_|Mib*?dKb zumGeglm&~d&H+p5!Tm`G$@*+3K*qoe>##6wgY5gK~I{!o||1WL-TilF%tESbGR7-6&g2xB`^{At6vSNqn@@7Fp2;whSAO{CtA3K zF=|&DNh#8IBHMMLTuy0;Ot|{l)y=?t;M+s&llO-BPddB*o8y;(`ES23v%I9W5Iy+n zKC+fx0pA1BeyaJLu=}f()%PX{R9wUO6=Fq#-NMGgB#D-hVbWw?ctbLpyP!Km6+Bxq6H%K*g-xCoTQz%>@SA z{6Zv``4KW&YQ+R{lV^8ou5dO8QH7|R4f42OBQ9?FhL$7~hudQfUGrT-Fuak_%IA>8CBRksZ~l{5hsQzKEV6%!lowkiqmq+ z*mzSTFFABKVSgIM;4IH$d0a$Wopj(Rz?h@yK%N~9j77REyPT@<2aOBtB1x9!9RhFr zbPmoOGYtf*gKGX4awfyFC-3j>zatnn&84(070TUlxpah-4-UXYLkSF%(e}6bAr2*a zO*KLiorQt<&#vl6-676a*Ug7(!AesmImwNyj~x_ftkHt;afYu-E_U;mECi+=sws(Y z#Fl~>?MTl|2lwWNf5yD5M}Crw{$`4Qy;)_wK%>{L$RTWCBx6@$7OpIFFNZwa($@hE ze`_f$NNyiHf27+t31yLFiRvQp3j`q<^q3Y7707mC6$n{+IVPH z!wAoKQ&DQ5>#iOSsqB6ehae#wNVefz~mNYB;{BD)XiQNnK z7>XqlA7%f6!p)DxKkvl#9O$zh|Euh}cp(T>3kOzeLNj9ZQ~N(dkNm_3m8 zg6N9S21lfv+W36q8*m!AoRn81BhfU1uP8KqLe(~LWzIL>u5f`%>z~K|y?Et<3V4%l za3KySMJ%yM9M~C*y!xz$QQgAypc#h_MciN{>`%Rr0rr?*PE^E5L(2%Fju@lJvnbrN zT~Mh`hgmd9{hq8c4N3I;4+#{J$ z&?>ZHYh-#kA}0Po-$zGGHu1*TFnWCidkNMcct?cve;PY{WX&xF5 z&&iqd{UUwJRYCbj`_oqoL4{I^_E7pkI?vIVmR(70MBBiTCY^7ZTtyxSc6C?y4Q+3LL;@@L2Q3?SxTBMPAmv2GyhK?JPC`hkx40EA8w zlqzGQOo))WP=1&gVCn78)B=9PP!dXVKN$)soh*rH7wYGcmHtJRBt@+;c8mBZW>B0)D`iL{kPb|{(>cb5Qp``Rp>4*;{XHVq@EZAmgY$ZU);n68>#wZui;zS7l&1i3CDIj@I1aXnwZk(NTM*Q%5u`U52t|fj+H-e&T97&)U|;A%>a{%2T*$3u zWTe3NTWJk4Kjw3)>%6vU%;sf0$g_G+sejsbe?+PDjDI)MmX79!1*QiFK6eew=ELK2 znNm@PTYc4)TymO)!Wr?gln3=C4t5E~+?rX1+Yn|!G1<=0RUkLOPm#6Brc=aLgMGYmeXc_m&;0xw~o+9eF zZB{t+Y#{q5 zh^n~wq!cwMIQjrwD(;6^e0$bsOs~A%HveF8=K2Za(E0|D(2%&A<23+`MC zMD?1EOLnUKRQpaa+`#5fjJbe@p5hEGC3}hZNHWllSg;xez0DQ|eLpp3xFXlApG1tm zkOaU)8wsqT`-I>f1J$BaC9tp{F{n=hpTdm5Xy`4LV#Rddk|fL#SQ@mnk7JrRBsI9Nf@rlMe}uR*-?+Ifxy|2daq0?WhBiyo5hMNldlyZy1v4iki?X@ z&KPFiLm561a=kaqk7C|`BYfeQAzP3)1ae*mL`>%cd0R1b4R`!f6?8Mp?}jb_Z6MoQ zt)*(K@6Z?BM9m1}EsAkA_=~}?eO?WZ^Z*z-Hne=E;Fr??M%m5Iyur8pJS|!d0>tsS z?Q%Xs502WQ_{K)YX9peJ6Z~_eR|<-KYkfePvNOI%1>DQI=w&hQH{@kzn6f*-&`6{<-M#Sp^I0E`{mlmG@GUPXO} zZ-Acuqez;K@vi}KkFz8C(1C+YXDR+B3>YT3x5Wx~c~zmC0mUhI%fV;!Z|$kv(i?4c zKss04o*&FWgeY;5kWOlaa+|B~oa;2*Y&+hQoDb!lm_o~hYs1F)@t&|g3Qig5|8%(d z-_2sU(Clx8209ryC^!1xvbhb`7CQsj`AaZOR>>l&0+Vhn? zOqF6ZX{`0v&YwCNrLe#VSaE6XgxYE~G>8ah%>2?*-5S(BZB05anDvCM(0q5H{kCZe zQMp|fHic8PyQGRs@5$(+81i5G6OL&6W2_0e7wLWSBDv#{Pv~9mf`KQtZYKS~t%VJd zN^Z^ACkUDaO%wA+#2c;z{7nOOEuRq^;^eOVTNa6Y%E+Olr;%Cq?AdtXkY#j|^Vq$?@_8oqtVp@Lp6=MxOzg|nh7DV$7ftavbQKd)S zkWG0GYeaHer!5YsB;tg6P~))WiVZ_J$;70@4CBNaar_C>)atZTQk5v`6t?Qk270@e zHRgwfB5fjnhaQ3|{gyq_O1O~ruZpApg|5`j=^r8fpd-AdL4W!pL|21x2k}*y1SBA| zrgXV;N-t>q9&(Xw=o&`KkM;PynSS*0XJq{Qpr=-lv>U*KUbTnR&S882+u=HNXm#m$ zZH$W-7J=2fq2CP(mGDr^{Y6_M2O^6lYmMHI}8Uy$*@4hDi&@TmPVuyKhSf3T;5h zfh~-a_FH7LDkAl$PAp>PT9#jmQ|k zbFjlywk^&YXHE}qViY$%?i8y@?RC{=t9yY~G;VMuowCcDD+NEVF_D~}X8)Gek)&?w zkdD+|5HK|;BP-LX%6N>=jsj6?prP7hhMZ~uv5KgxD6g32hVk-rb#}?=^#Vv`?_vL* zUOoz882{Dkiuny`gS`1DrpTN53NK_Qugl89JKvBtQU{6@o!&M%t@?M#&N<@M!oD3% z+ZxNJ@sfqp*wQiw zfCHlg;yK#lk2$F+5<+pw$DTC;H$mNTTs)%mBR(fAp;mbyB>Omp#N++Q9MwZW?Z#>I z$_IMAIKku*s!(+$IF?tMNQnj5mD?E0bn9buiUzq`)gW_w24DQncDI?UdP7d-BJM2l+>Va(XNL%Oqc*amd2k=S9oLku(1sGto^Ns8T~Lc6E4 z>I(G-hj27*ui=yqJ%ZoU#7B`3J>%b(oN%-x?58&;;(bP5RQC|>zAeLHp#AHqPo_1J zA$OpXZ;M|pH;n~wCJHV-M&o5uX;PH1I**c@f(qQoW^l#e82(xg)rFrpMG(GRc*^Hk z>Mzz!KC3J+wY7ro+pXBcg$r%#dEuSj1%UJr z?@i~Uh>7uy*5{wsBC`U!_1m?0{0!-d=VQHkzKkap`@0LK^ewsB)BqO{)5j+lV{b&nqEm}-O(-q8I%juLuw!jm_OJ~!|rokscS() zI#QFuAhA_KQN8#tb3`LO@6eUh@Mcc2#BCx%@;|RxpLv z_~#=i(wR_NmX{d)oOZ!ejW?tw${{ zZU@W{-Zn*f6JT7tVVF!Ayz{yUJ_-g36VB(L@iQkP8;?r0eK)q;v~Pov-fsgW*o$(} zN^OTv2~XTmjyc!q((MLk$u@kfPC6VBOrZ0Hev9Rb26jbw69f-P+g2 zZ@5VAPomClyHAW<^(yHNq%T_YvCRM6Xb;(bim2M(fBX%stEU* z#9;;T-`tWJy=Wx?jNSWOU1hDN=UtV8V2-}OckpbuxTbB1XdH|VBBChMv9`PG@C<*> zu)U5n^Yqj6|Hz|OOLiJs9!IqAWuOOY6d76O%Ik(3(gH^`O2+N%#v{;C)DYt2m^sOqm5z-&>ar1u2$QMk+UFZ+p+e*qikv9pOV2!|`bhK+L~kzuRHg=8H`sAi$O&{MmcM_$abv{oCKd{bpPH@PPxr zD#aqg3$=S;4S_AbE((J3j(~#NmHE>fg`R^Z`D#*>hvfh=#uWScLb31@IpqnV(y z7J8%1Wc%Z^>JDF`y}mOj#*ac?2Kv7@4fC71^ybSSR|dhP>(*U!TcD${eLb`-am0)D z*;58VQq-lTr!Zdmc9XRGIU(alJIS3zF`taIBOs6e{(E!UNWs~TS5e`1A#0^HU&+~) zm~a=L@EUkop2S5@dvfw5YMOsYNiY&xG^7HbhQN1X}SaGnbZfomZ>GfQlS7fQ1-vGd9JO%Gf_oMjp z-_ZqbIdQwbHy7FyiU-huvRgD~Cf3@kE)-oVmTC7-&}vQLU38vIaL%hbnkm9uV(;W^ zZYt;+Eduz)-OfB@ZxZ>E%Fj~sBR=d$afFCWWX zzAd(EC?cf(v|@sjV=8;{P;-DC1EA^CN?cJ=!BMCw%%PC&vR#V-F^A+v;PYqX9ww@H z6Z|UwRpJ{eT&wtl-4N7T8#Nm+1tZA(oce-+t#Pp#VIQHQlNX)&$Vxc$EOcET5I4&t zH57N}Ok_F-@&)MG*Y+;etw66=z#T)C&G!WMQJBd1<}~>yu6m1wMeWeNT{`T6G}At} zb=%iU`SjswPha6j7 zh1XEmJyt!cz*LWfWeBf_8`ft0?VxFz(olu2ib-kZ*Z@P=LA* z@=NatBY3QLd2B3ZOEP>1J_`e7pZC0QO1zdEvzwWsIIxnpX`;QUaGgX@2h&aNQ;99s zOdGV|OipXE-oJs+gC+gUK0cQrG9zMWAyP*+0{Yp#+XmZ1iOlUm{Poq8G3mv?V;$;8 zTDBC;S)5I2Z+sh^ohEW7^h$a2Jhh3VX4R8JoBx5HjWs!mDaCrSV9PGzZ2D1m^4T`= zvh|ww({HSw)B&vPloT1}caB#uEoO0;XG08Hv9XyuJ8^%?`h$q=$7HF5%fQ` zAT0mi=vEKlxc)f{0+pQQ^{b#cshDtY9GQZS2E&(Nts@1=FY^hs*qsWzKe^Wy_rGMFReNS(l+RKm z6)T5kb5B&KVmtJvMzfYpQ!5|7&`xo8x>K0rr(5lC6gwATwECuWdsvMG44K8*$Zqtz z?`Tcb%K2`jHIHzVDDk1axQI-d*AIL$YHg|(jE!VeM)n8SlD~Gd_GpkiBhHVeTwQWC zNR@oj@eEm)V%X)rh=#ks+<1PON_mX@U8Sq5q}~3W_&y9j8UGIG{)vqLu{!sWJGS94oCH0m_m!vbUn&4Z|R&dsUO6+*SNK(^*^^9HoC)_<+5fmZS@a5W3EM&Nb%F96fG%F6GF?W2J6->9AYzgL}?9^ijgogZ@D+p05*s}vJs5T0paAz8aX z6kHM7=}(TxYXv$FHrvE0yV3_-hP{P=@HZA1w}IgXLI@L{LJIbcz;CoP!we8 zBmk2aTpoI|=OCt1jQ-^uK|D1u$A4!`yp7llvkI8A{8ZD3P`h6dLFRkJv~^N2^J<1_ zF@JIcY{auN|6IMj@O`CW$mo<85bBNv!a{5-LNEW33cs~xZfGl^Mdv3_MR;3YcJ1G zU(+=y-V@?S(d#>5C`4d<@K5LMexv|?&F9NX=5TwjixFwe?zXL1g`a7Adfhf{oF^%M zE3{rRmb%##|8$LCE+FtlZUk0OkgWw3u#j$%n1o)71Py@5Y#;W=s(P|~B@#<)wP&_j ztA2?-Gy;@s!YCU)ci6UftFFoQvJh>kUto_Rj zVPv6Kd4rpDfQTYRN&hEzJ(HRltduaUDrgAAcTjm~1AgRmj5NWy9t`*v=xFW-NUM)fm5vmp%eJNo?(OYlcN&A|4zLswWq zJnqe>`i3ap@?-Y7xtSCD#$T%toQmzmBtb;Lhto!x$U(C0@UO*rE!3zL?0?~Q2Go7~)g{;6fd8wJ3xDM> zTFk!4AWjURMH9u{rtJ@@xg51s{(CN12OKcJN+(|14(yP%*wR(N;tkj(drrOIEBxEG z(-oY>9^FiQ94}vv(zkFl06hu)CBClrx7E?EA-47Yc(NOH+E932Q-DI~<5riSwNJ_Y zOhZjaeE0k~rM1oMwb9~f`(8BcKLpGl5i$M0lCOkgB>#x`Pd-kR5C4OGmQ0~BeakBg z!z1-cv4Ax*U0YvuiN&YbKAYpy;gIh9gsm?6#pIEui}5B%d%9wtyp#|JEju83m>rP{ zc$BuWP>3{&PQHe29)|^6DG0B1^%i>3OLK%L{>U7lH2JYrb4sV8tm z6c?`Ol=V|QyCRPHn~-8SWhMYkXNeC+z|!387}`PAa12=nB_i{kLhsCj-agz=J|x!G zT^<1_Ws6~%h^^4ybb(TKbP@z9>AfeOk3v<3w*~djQ$RR|^N$Nq&^_A^O|ARa3eVK1 zaOCBuCIn`r0s=tsow{TqlE&>qd;DZPyPuLlgFPG%^@m$i51JNeGJS_#*OpB%Ua*!6 zQYglSjW#f2k>G){r#Sb^ZjmKwt;1<4_$IyOub&SS%V#W6m&+vC$w}S)F$s#lGGM6S z8|dwoCs5B>R3}GaRhiPMz$?K_bX>Im{=Ctr(jC6XSn+V!d^BI!w(cyJt4`A~Rl!!; zy0jn@-pFDkxgqwTNS3Bo7E|oDLxOB2YHaQDJmR_S?i7~2Tw3`2)(WN5Q==C9x@( z;3sL`nY~b73^p~4w9uPCG{v#irrTghTFpAqJ1$ z;iTYUrX-grqB0H@QJ9$*;^S*B)z4Y$k;cu1{v0AUpiV#6n}M+~7m!e$iWmbjtYDA{ z?XbmL6Gd?Hp!lj8DodmYV%4!?}apMwOn@Cx^7T5#A$`n1Fa2g?(&z* z0aBNICX@oBB-ks@UcFS^8}`9Yt?1_7o8U*$8vPr`$v<@{EXV%`XtX^+X8FV&{K`6Y za9etLUFmL|^(P6C;;ZRfgFWbV+IDciNn*OwKMw-&pY66fVBmKQ&V(UMR7Uxgf4um#1wl0^zo5+k+S1^ zMIW6Kt3-K7L0IBY(lW;V%8LH&7tp=NF5Tvpa&F$QR%}%7&GVyxijnDWi?OQD2TgdZ)oH9M$l=;#E5=eU4CT!0ePpx_F^B=GG>%x$TOpy>K(NXc z5(832P(R9S$v(T#YFAg*$1o@N;_F?C3dvVkjw-4Qjv82FSy-;q7hN{ACoCbVuL%z$ zAwnr1y)ZD-w_EOOCC>j<*C}Du(pzc~7ecK`tQNG;G-Hq}KKR`t^tKrK7R5rjoN?%I zeB!(Bn1UuQAs`eeiOh?4uZc(WJ?%od*XQ?i^ihxGzj729S!(3yeEN_D-=H222Jm}E z$y*ZR2V>Zbe|tNH-_pANB){Kh_z{8|%v>)qX)ir}Y)BA|F? z%D#*ie(X!?+vj`WVsjd5!)7^?=$an09yrX`VI_xBIVQtQf|3!9KmM88RI(EQLdmHo zD06aIz~B~#5#*d=)!728AkItGS~HX?`)w4}p;lU0{J@TGm&9q}q2i}OCfR8Z6+#1v z2ug|dHRn9q?=?<7U7RwC2BsZNT2#kRwYlRHOGwqw} z_n8dEOn>B-ucyxZ(m>n|cS$+r6kM4xfK7fa7p9GrlF)-c80U6^L=|J9qM?rQjbCgB z0!ijrq8;)Y3jcn@A z>$fM%pJV*b^UpE&=lN$VDf}Uk5`5#S`eN;1k4Mk^KmX_d9qAa$pADq&UmR0^D7yaK z24Ad={w%{k_xt}A{r@5zW2IqZV_>D zzIRIw{-2SK{TJDolfACBqm{1nS38R@cJ}WxjlEfy|Cz`CUzx^O{{WIVJ^W!Bdy9zt z`T74dOk?!__UH_xNGlSu!UvuILgDBIRImJsjgPBj^`!|isgk>zy?XFO)UwfsNa@8> zXJU!a3}9;nUoi1BRpdJASM1!6??3nFH#U;WuV;~7X5AZyoyWjLesl8ZHt%d)y6*JL zUOx5`ov}y-`fNDfr}J1WJ#AD){HPwFPvglMAitJqHf^ctZN1647qB{CSZ#Z8@33fX zJ54xqAr~-hF$m#GJI0UsY~J0m&fyiLFRb)Smex`p6>XS zMLq(NL%+|hsnl)j)%Pb68>c$N{6*f{-N&0IwM>o?hzu>`GCsGlKejZl2q92#h43)) zX9Aow!Va*0b*xp#Lv=nRvWa`y&iZyW8z=wvf!&%Lz`Pp+;XLNJ<;5ew2wiH1hv^N-$w&r;x!*+I+eG&3_7Fv@b6#c&Ra7kPfuN^i+t6olwgi00?<_u zJEk?@gmgk7eKO$$a!Ql`dWkHM;H08{4D|V|?nViv0J1Wq5C;Ozkb-i%F2t`8)%AXH z@A@d~wRsB{j$I*&G~aKaX%CF|?3Hb2RG)dNG8MPt4A&Sv%UHi(oCgCV-X4-g8;E(wwRG5aR-T9>RgFZ{t?XzJHw1dnIjdA%tT~;Zn4na z12CmGIh0G7LzOSM2|&ft6`)Dv7QiUP3Xqw8S#VWPRiZ@~ckMwbGOLg%#V(gPCRQ25 z8zZ>WQzbTJY?&ORAk&YSUocWxW{OlMZ!lCg>*$Bnlr-_XL~u<_dvsJ$3Bx*a+|PT< z$tV)9peUs-*Elvy5?wAn5yTi2I!c67g$`eP_YAA^z z1=9Gm3n-oR0Y`dsJ!HaLm+W&?n2_70`{b3Dre_bih@_A6vK%x59Ap%Xewi`OI$VFZ zi4f%_b^S~{GC5RN^JzOH5^I|*wcP){a&>6bJqx4AwkLMCz1 z_#jS{&%IJABBeO$@(smDs*gEYN&IF6J1E~Pm_@-7r^(BwCJxk)UcD++DnDhrdf8Sy z1!nA-Ym7&0t3DyAi=c9Xug+^ph$2{Oq=^fYB=*EbX^N|5zCbeG>6NDPV<{XinbJ)+ z_QY9HXRf<7kNpq!-U6zwZA;h1A-H=8Zb29BPH=a3cXzj7!8N!C2p$|l@Zc`N-GaNm zm3>at&EA!JFRxymQ*YPVEs(a77095^Imh@%AAkS4#-_2&oGyLop))x=4OpbAOqzD7 z5%xU1MWV7zceVM>Y7;9`Wum_1N^k%{6e5@+#jB#p7! zTx`=utUk7p)2lzjxetDP3e*AJWZB!z)2p_r^|nPvJDKPt7-P|8Kv=(4Jh@JHPKQfn zo@>OTg09}ytDCDVWR~wC+;e7`AoJR_=MmDFj~4n@3--^O;(uQXSy&kWKyx^7DP&=0 zW(54U6arX*Iu^hNTql{?*#C=`LMJl^TW3=7^M689Dxa*?o2oPDWOS-=DB`t4lk6V?}N~Q(ZB81#gJ8{HEEQCqC7v@GTby zDGzBiD#gVcD~gNdBX9xKY@=8Ot~zd#v1TyLW~7KvNVj`~o2!}b)1kSN>rHD%t^95w zp*1{S-5}KEV|R4Y;p3ZeO0gM)P`_>EJE^SKJ7;Ir=DcjZ6lS-6n5NRB09eBU=aTfR zIIi6f@w1lwPzK)|Vl=p1bN6KAC23Pyodg!>ySeO1qGj0;g!{$KSGVpiON{hhKL&wg zMa9ukhs)gPA$PKW?PJ)gWeSWCVQLs}vG&1oeNcnV-Z%m45egG$GViNYqFUNQ594KZ zy;fNh>yQW=r`~SKo0NHtlM%QcvA=b$h5sZPkih=5VBq63)`A7?6jnT}%i5mF)?P33 zFmjFTzME&j7NpF~waR2{#>6Wu%Be8TgjY}x8kU7e$o?vqNE1>;sab&8+yadBWdVhu z)@aW$D`Dz3RKGippTqJaI)d$~nS7HZ|)KsacD8t8*YHELU-z?SvXZXWE^FLeDQl%Yp`jyeX%TIXo;cCrG0iZlOenAhQaSfg5{M8L`gsuMYeWShz$Whd= z=|*cfL7-n#LV^|^8LH$}Vrs|f!kiYF2)&P}xXTh{hE{T}dI{|mLcSDbG{6x9zp{VS z7d9T`Ln?`KJs+{Yg94Vu_pX-=IPkS836J}pJbV7N^-NW@j)URWKE5&7fkW;5aoyU4 zy9h>NA&==qjC$!DHpb0-QZYK{M@%e@!0Zq-JoxafQ5y`aJg~7x(=Y=7kKx?NSu&ILf zb5DGnXocU3F}uG4RdGg(n^j9U^VYDKTFnBpP=C)+-NwloFUlyxyXUm6_7W4c9*Lh^ zTGW|$TrC&YnS;#Pnf&v|V*5h-gl!$79{g|KX*azBJ0{F8ydypEi)v7~*4H%f+ZEQj zzmLAB^_nK)^y(!w50zJkj6N%ms(tY~s-0mOR|=y=A)LqMc5XVwz&158aJ#1bg^wo& zzTEWLr@C|Y3gM&KQLA;5o(=PS=)!y#BUJzcEe7^#{s1%KshjPvicLo;jk64xZutTfuhFGZhBpRm@>L2H#$C~t zaftYnA8FuVlwoM(RxM&utmVHrsANXw=0_K=)LPHD5m06zR`oVXur#D|nJzG9ET!uS z8`H-riE>m=jgA)72oJV;Qgn#;b$U{KFe6SjYifv~zUXN~rV_@jn=JMNgP$U=Vy zHEAZ`>win-FauxzE#*Tm%>sP=x3mv%kk6JT%!~}bKb+}K*Q~+sM(AC>QXC{v5@@F1 z(_A7X{g^9=YN)zN)E(%^j!cOcAf0{s{Ve_xz~gv%kl75X*z8~{EBTOop4_xOhn3v^ zU}t}GaW+!K*S5f&-mcxU9JKr9(Tnc}`1?I?@GggM+p=3*>*B_e)>n?R&7pe{K^I!qoJ+lp_-BF6VDL7Wh)7nj^vc0*?2g43#<&l8!S?~Zd)jOi>dDSfG?f!frA8R z15QS#$QG$VvAl^TaN{c8Hnd;Q4;^lM&nM0gYKlwYCX(-O>|yC_eX?3CcUo%0d1Z`R z&jX#*hPO7iy3Yv*<|^OsUONcB7*ueS9DqbPEz(htTGIfwk=~4hx^WQiXH#9nNFQFC zI>yWhDy2p`-9#eA!s?s?{>x1yhtuJ^*Kldwvex7JmwR1BO6y;B5!X7yUE)2l05VqD zpXP3Ey(kv%0|M`M6-RV)G~*VT0$$fK!^c~u(=FNX`m*rcIi?(MsxGJAwcom&jqH*f z?e$KuO_b8J`Fhm3pCp)wF*XxeMoKcluid2+i5%r#k-55Xzh@S@lQZdCBZY1k>?HI7 zVG?s>k+^JiYRd!&J;|ATKJiR!6YZn{zM&L#OuM;sa}n zONE~7DYK}=$2d2Wj8(DR;to+GW1aV6k!yFTh~UJj?V4sWRL3j5O-IvH%pUY*b8UkJ z6H4dZL7vGy<8;xQ1yxmvSJdu9+X z!b(oK5&RC|TWO{EF(fja5mi13%x;#m7 za$fH^UOD(wHYf-}P`6FiQXjC z(1}IpKHwbrU8Lx17Y{zpCQQYF)=B1%xB9WsrZrgwiDBlms|uIzC_?8d{N?x%Znq{c z3^nrzoY<07XNoH*F(u4jPoBL^w9U}x=V9uR8Afs|*Sw%CLmbw)W zA7_9qKF4}85cbcxcog0o>Sc63ju+lZXi;Yr>%-&r9saFcXG=*m6JHS13e3dOM#8MN zJO-|Kx9qY7j|=S%mKBBHMr_PfO+hlqsGlz)r)xTD6vbMLS`FA>)3m?Sk_-DV_JEr~HiWrb3Y-5dNDhg!0>< zZ5XmI$Vcc{V$04}R@dq$BwcZhSvK?ZFRL#G`J*MP?w0IuC`HZnK5q=6fa%dEsTiz1 znS{h?mA%am z(`Ch*C6EmI?v(+9eD}S2i+UCU!*S(>48YY@h(qr^28Y#QMTW8Px(rE@aC@K{h4GPAn5DB;lmF zaBDr0>}K`w{b~AIWa%vzYWJ*;Ur_M`z=ZW}?#peNEGl=1kl|rC`!S%)$$L?5QkbWz z?`V${%Gcl=!mZ-h>xpiu zJIom?5rJtfltRj<5Vq5k2<$`f!R4Kw7Q0&4vrK{muH?s|3RlHxfq#HR#pfy|CC9-R zSN$Xvo=J!6@B)m+Z?mY>>Osz;Q02H(#xK>W;~*FtGfb$9om>Q7!m^^!vR4NCb!iGb zITYtC(p!J)-WBpAf~$qE;)!nRss*zd;hwDVhRA}=(z3WjnmFjkUd-~LX_Hb6<5qIW zQBpx)$D^FdXphUM37z<7im_tR`0T9%16I1a9x$CU^R?Qs(MN|cP{sDhDF!@&e-Blr z9zIO+)h1p5)M!<`F0R~%;Fd@#C%8msOQwG+)x0YH&E!o901S9qJlTxXbJsJ1s7(xuSn6@DI>o9g) z)IPRrj8BljF2Jx=26D)5l$Id3qRNcYY?Lc*G<4V5XE6s1@dEy*5ERp5k?)12s>Y>d zwg_p^=3)%_#A0Zn3p*mau+Utq8}NHapRP$S^sQU^hk zcN#TX!|b~%W9pDYWm!ok4-}awE1?^dRiphPS2S}4h|nHWt1Y)iZ&5i7<L?f=TJM!KF&y z$IEPgeG_T<0k`e8v)0<*3($IfwAuV5?d$%qzbT9Lbms=9#DE`pGe$A7pVgM}c$?+Q z_q6YD`@QwsgMr7zi3!2^?c!B(yAQW_&D@oIrgze(7B|l}Mwis{$j)2{yS^UX{SJd5 zN9VKPlm{%@N!7JT!|n3c1o*qxg5z?GtKBBZmP@KGO&PA3Yy~vbnXd|0KPF|^wO0zb zFz*ji3c83Qf4^PXRx?2Ng#bC$YfI6Owp!4-`F}EYO>**h;CFU zix}roj93vT?UkF~2<=WtR9b(%d4sVVc=5KU=xYP!4ha!C%|_g0MwyxFA-|NA#uS;f zqLQxW7V@V>vcgf~fm_(G_$?^);swpUEYRDdsNOLzl@=a-Ub7ewHcG80T(e7|hJ144 z6%Pd|?iZm*QI$MJvT_(5t1)pOwXzLXFJz*`3Pl=lu$rvYO;~t$CKzULP*A2SU}sJm z*P!Ou@5=)uL#6ZgzoY)#KVft~c zV#1_0sBeMPAEL0@M0q}|eg}*YK!g?B6{kSWm0j;xijx!ovh5{43);WD9iJ)N323VD zMsQx4Q%Gt{f*L~PQs^NY48!jo-g&v5k<+HteSqDWwywOnCjYw2@G`9kpO%YWuL|MJ zqL(L~CE`sPGW6?(@tNFDoaaTR-rsGHbaY!9@fW4FzmrRUnk%m@S*5LywqcQcQ;%D) zr{XzZFtWh2+u||bPz~X$(h43wj%Y^QZv4PD>|~L)tAxFqpo4YdN$pG+@2?Kx8`G2> zAL!O{fD#eV9vElda99;HAN)?l(kXL5W}09t`(zYJo07p*yqB!J0-XD6K*(8WcU;c^ zp=?`mj`SzBNw=3qb;UPYMkf)gynVOOj@$Y-5vvk?dla4eU)Lzs3u2~Zw;XKV&fci> z#p7M6@H*Ak*eIpd=184nrDp;%+HO&n+uAR+ZeyiK;g}^1pT;3-u64+FCO+r1gB}W9r@-3L8BIT5Mpik`W2~*r= z_XgFefAf;zUV^cp@}4^)H{|ChIxhW2g>ovq5Ls$?3$tx9{=H;5hOcZptG-C@ojZr| zr;yqQggCb~qi?(NYA@my@>fokM(9k)!t|zh!97hr5x%o6kge?e}S-;PBck%SFbF>OhS;0eeAMuhPz= zP4Gg)(nVA`xfm%UuDiFP>3y|x$l}`tuybyfy~Ix#dwB%?Z*1RagYU&JdF&JM`N*!M zyvCOjhO7fu=7gkPhzGcRv*lz`lN?egS-BwHU0BJ_D492yMk{a(ES0=&mU{^HaAEkC zvk+CSU9qP7vbCwOfFcz;9~o^TcI>sRn8*7g$rJag11wk0HMPpw^}5Bin04Ig=En|e z^;2uKy;Y15de_9mDr&ZUroFhd@5YAS1Jt#)INmt>--6FAyqmLjl8yjYSB8$(`dk(6 zm&x`-uB2!J={QugjeU=Y`~CYHj~c8emElN44l3S}=~t>c6%gXnj^9j9HcX)UWR3iY zum+*9(YhWGkcCt!FXjWumhf=0c`(4X^4a$JNWVbKz522{VLiH>X>k@h$xF#st8!S; zs$Dw5_pQN_oh2)x*T`Du$@aWkP9e^m966EtTB8OS+PYb^(N4&g)KUi+>%EH z4!a-umswJ;Jp}jnbvr#s%ejnOmXvf@iA{Gi@`@Ye*C&`JU^MIP09^to!e7LE_c0|!EaFJbD`*B=1NN)-&4701{)DD@bwBCA!&Lda{b1`yS3={R+ zhv1?a88T1xR`a|Ha`adCx6_u>-&R@rBxp;1HmEht^s_kO&Hz2^putcLHP+o-_k<6wQ5~OkD;n*y@WRR2FFMKVJ3@B+ayZ*=%MIuj~9NY zf_vRxt)m=TeRJyzR4Cu|>%a^S?3WR-sK)QSMtPNMT3;_~9$JrnMs;vEn%l--b##=0 z9VtRh#JCfoWeRONqj*kR*L38afxUpUAaVKm=|1g3yT4GaMit>BaEo<7I28ov4gT>} zx+kPB2%Yqi&y4pO=W?qt8`}JO>j#ncL+m^4cWoTXyqBL9nc8RXU)>6j0)CZT`jK;Z zj_C+^!1a6AQMsn3<3dlB&rHQ^vQnioIkPJWhivsrG6{7~@jgR7c6Sh0BGdxNN~p@h zOv6U?~^k%pLK!Q+Qd+mWvL5(TTU=^TUABq>wIMKaP-uu0pq<$B8#uzgz7?j;bM<7 z$4SLx_2b_ub7bDa%FGCo8xM@ID06%UJe>+#=EOB|BsIrk#)@m~Y!sE##oa1;mt8u$ z%S6Z|PT_5bPi_vrELrL-6(vU!lb-SAbRv77kAd%(jvE0#$g@a87Q0oc{q9TdfUjrj zD!B_;A89b{d&nk!D2$iPN?wdh$s`#Nk%15Um(eyYH`^@Q3(1{iKJzp~%x7nE@76)t zltebdlG507S!yKVkiDmX(J=zEP_An(ul?+1ike`6sLMV|$7H_l*&OFe?Rw>0r%Zl> zvAjVtz@PPg%+xB)m}6qbIuUX!AfUmGK^z~Gx<&jhCoO%D>E%(SO_LFJ2aJnT4bSDG zwOU0F3VYIcM*9R~&4Y&$WJUHg(>d6yIvK};w=%Ohx_5O;d5<|A2p8I#Pj6r#@v)II zSBTA<+HydAY*e8*OtA>u&exx(*U917Lm*cX3C30adQ7)u7e#M98z8aW^JD9$zVRpH$6UAW19i&Hzf$$qu0l}pJ~!hj=RYlm+7sK26o+i3%G4tnqO zNsss%B~aLdEgmwoz~4IX%9ySZQr;g-Wk*WDaCur@fAc+Sk%ByBZaL(%%=8YsaO1K4 zc^=h1<_={CV9vz5?_@am71hnv0@mobVCd(B2plq%d<9b`jB1M#w&4k5BJ4?NZ%R)O zqXV;87So$(T|%;$eod{{`}z$YSL@%Nay+k;M=C@x8qs;mh80tp(rsSDY$@9*Rc_lF z>ar*wyEr>)5`68q|1NuQAEv;#d;K}>a~pw5z;4$YLBH1UVO!AzhY|&K7@W;aott-+ z0m7hsOVh3~klZf=W7(>;p!H`(#|fHGnPdFF1e#4cA7A=k1-^4_`0|lpS}e!aaOSMD zm;#Iawe$x7&Pz94?{iHvc?fGFdg^XYh&+?m$qNfJ;5<(!lk12Hi&Degniws-HbfjL zO16h>K@uG%v#=kuS>Umg?}3xky*XTW*7BUM%|K76X0z1WmUsSjuCx!q3HGk++Tr+x z$R#d=A)vL#c&7{)>@eqw#2nL!eAv7TubF9v6s6PQlQwfQz+yvEcZIS5AuPB?f26IiseN5028VICQLm%BQ z&V0K~koJpLaJ9MveLwhf6Ujo7o)|dJYPH|a?0Ku__skY8g;I1FSanqNp3;Oabl~V_ z3gm*!mCD0bTS>e3xN1i%y~3A^oRVBKhEjenPcP&@=p61jMAZOQWkrUrOOy7h#f&#g zF#!InPB>N!A=r!83XeQY@%#2!nG+zJsaWGP6L#b>Fm=9KFCi8N&niqn^W(Pn2#r55 zy}?iMe2u7RD;pa4j_F-#kEC2)kW@jeq=Q1~90!8zPGhZ1ES> zSM8|ANn3I?Px8v6!QhZd^m(v?{9CEIO2MHs?{Vz=-PJL4f^f;4J~+0LQq<{A2PJdx zn0;Au$~nMdS>1of7oYEadr`zfRG-~+E5a<-2%Z;?YB?H!l``2 zq_j#VgY==2{nh&~z}Kbk_|VAWPD7PJOVw|TyxiNU{kZE!byb3AWIaQY3ExiX%fyDH z9pUU9qZYk!PRV-W9yy-st>`M5&@uu3*nW1Vy5!oU!-c_(@9Bh{-QF3`?we9}OCtA3 zFcuBWD)9(W>8za>qo17#%x(=xoJ{p*y_lMK#F-|9-KY?~+C`Jj%t1n?V;NVhyYc(axYA zl#-e8Q>s2Ph6G1(j_i>2)EhHvC^K`Zr3L)3a~N-3Mmmu8B}SVkngpm!u63-nbI^iy zphLh^!y25smu0W4$dARs&(SphwHQ{uo)4f+6=Z;vg%u`euX$qe;iLxBzL z`{i~U6GpwlxYPOPE&dG;kq9OueFpa>(W|OcXy+x^p zx8w{8Bb-Q;8^Jj>5QxVCqy5leKK8&*mg>>Kr^;___yaj>o08wjEMiNf3RV~zM93kW z7t(I+ic6-plY- z_*uFD;^KfrKnx$i6ij3HrQuP(z($0={m^M|#3##&6r$tT*p+95$ zl*_>Boh|CrOK)b$GmC9zJ6r5}n6uzhbHrXxLbmZ2Fl zU$6@?X}&A92XVHZv*fuCg{g1^$^IQ7AB5t|huA;{in^U6M#_o!6=*{E`*2DRSHh(O z@sCSF=QD*leO>Tp&{6sa(OK-GEa;4Kvst~}kRugU=8d~lxTEy)AP1wW zLRSwoKg#JMHyhfz)i4OG@=?oLSb1q%F%RL=RAt76 zW!t>3EMX>axY@)AqQ;->fHp~fRB`(byR486A7dboae1q~&bsU>M=4#P;FTuZnD){! z2X|5yIE}s7O#WqPNA-lkYE4b>}f$&rrRe3z)BrCJWTM=Ju zO(9jgH?rmAZFG<<=}P+vX}c^UvAE=}x(K}<8_bzahft=jF1&k=XG?mZN}jKvrc95E z<Iu>&NxPuo_wjYzkx^BTlpuM?)Q( z$!0qBR@t~shQoO>3-jUM70eC8X?>-+enBj*i_0c(5*7mzI1sG>aUvif&*rbv-JeoT z!)ENYHU3?e>s8?%Sk<4kFClZ3Do z8Zin_h@G%N+qqiX=sb`tcT48WDN@lDd{Qr&ljCw!UyVX)`!YYPBP$I;n?feLW(#l* ztG)NeuPW-+dxAoqCc4za##^Ir7{*7U*4U$d)Jztx=-y~0{U7RSc) zdC9*2upE<|9bSE?)9&d>vU~=9FX2rR(P;1FJA}?fGWG?Xut73?@xjn_19~y#N*Sy7}N4!9nQV zAvoFHD_FAB!)x_x@T{2BE2gq!;3L`S+(`&*ODAWJP92OcIdONlbYG;9iLoMM)nn(0 z(=F-V&EM*^rd2~qs=42r53_!5k#}58o5c7YTG&_AIvqIYkDq+Aw-ApeQsyl%$3HYO zFPqAnKIn?oEnX+Wb6iymod~}=*2E(e1&%Wv@Ysx;`JfV;2YVXMxkq*ntC*{|?3Gmu zrc%-FdA1seq!3-F9#T(kt)e(Z9f2W3zK+cmV%0oNp6C5;dE$nAWsQ#NY7-?sW~Cbu z{_)0N__{au^X~kyGjFCFW`}9l4o~{jgUfsym2W5EE5#R8CRs`5NsSCC17!OUs^|o% zFR~+ExqV+ZWJJegDkClMl%FgGV|@Rbh*1@EeGew0VSiwqC)yFSrXnhSA~l)pp$O&L z{$agtgw6Q$3TcMV8o1$>9f3kPvP64Z5T_q~pB3$yDIaW2$i#lkYgC<(`?04WHTz2;=-dm!+L=zr>kS%r z6HCutPz!bz={Z^RI#{!2*t4VAC(idK*Oqo?iqv)0j~tJc*CTQ`nICl(95#^m&`r0nT z>T*ny0TJRs5G`dRf`1?0zh_ACd;|4hecff-U(ePZMQjeaFO~@VWq?bD*3;VbP3x0= z2-ip*&PV*CHP@7BmtI|iI1ES7hy|+RZA&_h863`~c&6Ts!n=^+M!n?bK&hh}zUh(M zM{oivliOcRg}~-b&x_@M1F{>4O?=+i{(?#WQ(@AqKi8`MvielY*v8b!jPNg*^gkFT z4eT@byeH&8)cXUW_J6PUf4K#&@T-a8XD9Uk@gn~PcK+vsoqwxVf6h_j9}9~A0z3cK zv*@>)``=3apA$rm-*bz2A_WkCG^IHLl3TK2h@Z@HkM?w-s{O|@hJS+>JS$Yc2fgt`SN-Vh0r8`=#~>cs<=b5J;YaI8!=lx9LNLUU!9q1K zvn&1q__wyoHHH^7*15CqiASbtCpI!9a(v_!PD{q&{u zRR{|BBBG}hLZ{&`-ezc{MYuW=^*r%HWdX1kM%E*U=3XA^k**ij_2slQK8B}g+U6@k zx;Z79MmKtsn!HKI*O1AQFyfhBZ=q}*)nZ|5*ETDpTpDaKtH;?pqQB?%&Ek6k<+Szv z74ihw+US`p=pXP@EV2SX0v8Ohx7XumQU-C{rHPVx{ktb;{`tV*O^9zaWDqhflXh}o z(emdC%~-2`G|*#F@D_>hC4l1gT5+*! zyiTnQ-Wui&s!nHhQQpqTg%frs9cUkj3MolkI7I5S@U93wVWEFgSGxN4%H1tw#g|3< zmKh5SaN!=UN%%wP$?+woyXn(HV5jEwppl)I%R@-XpS7J3jsc+jZsjb+ugTzk2{ zbsscTXTDbv+ky~paGc!{)M$!(Yz(b`@B&fy)@uFLocUaB_{UAaU!3TlZocQ{JpVMD zX!hp{Va7k~YeZrMe)L)ZKk|Ug@3v5=%VhN z!KWnwYkz}75ZK5k_4wkcm;u^xmn8hHST8LF@&Lb1*vs5$o!+;QY2m(&I*soT6-z5(t`H)d zlUd0LxMQg5i>3riB#EDto5kh1#+&q|S<2Y!B{bc1cX@nzuFy=IMSrz-0)n5Pr|p1T zx1XmKCPrpuV9P%ic?JNpDg!H%5(8_Uk{II#Sh$~BqZUIIJ_B4nbtv2iZslgvVAVPSND;^R0V{u6l+JH)mNo!0#ZTcbb)E>bCqwN@t z32lN%ybIMq;T>_=yNbY>3;YFLw%vPNoL5d(avqX#rP)fIZ4R}lTuFP{fd_$w>EnA$ z6CV%!3Qj`GCi7){UtYA6(0s{X5)*+Y!fc-ycv(%8k3adX(Fc50`+IA1=Zdx;sI8wPDlIQ=)Ad_-$NSG9NoC#cvf%-PU9kpAr)TM&l8?*RxVj45TV<$Yo=3zok zUkUwr*@&Qp&7*aK^V=^wovoRh>sV_jJ_Nog3_2CB!A+Z>GU>A_?zN^?0l>0-hz!3| z64gLDWgQ0i#jgheG-O@M$aC)}DUxHb(Coj^adBZ9puypV*1k&Qt-ANxAG%IAFE5C( z7a(TtE?72g>D_jF0!ftBBL7tYpDPKO{xYQgSq!NFhUd!QzYMAW8$&99;kgR?4~Lf` zz}Ch;92!qb0xw`;=Vi&`Loc7AkO5wL+lYrjkZ_;eMPETClIvioK}#4e$i3rlU3H-C zUw}liqwt*{ReGN^;c6Z$u1vL%kLvz}Xi6Sa>^^3gaRq01NAinCX#j@j=K22lCQ1O1 zP53+o1Nei2k(TSX26pGVYldZE_`HMPOaL9hUH#xI^z}ttvYF&s&S`>X(pTdv5)Rw` zrcI$xnMCtbo6(_)s>eKdFqbDeCFF9lDv3d@ahob;ar(JV_NZjby6Ei^&mi?Yx8wEM z2`c|x9zcglO)CdODbFxsj7&pM#oh#0A}RRWrkFFq0@!_mNwQpE=g|~}3>n%@?BuK+ zPp@bYp6;cng|XfNtVq#1+Tt;bM0O+wG{vz*`_fqd1T-ii(>JQja0Pu|Jp@_4L~-P# zwszX-fe+LK+LS?tp2}bFMQ>1Vn>;S*DDzm(_xlB=>pL5Qmo;t7`FIh19 zQd(vQwEJtfc(%6qO?GOEgm7H)zIT=2dC2EDZr(SH{eB0mZ>@77$+rm#$OgO6IV*d? zT1?WWly~&L5QI`is>0P26Ih*Uq9x|PEMLc&V^|tsP&CL{t%RK1GB6G}++6?1x=#TN z&ra$7{@9j@_5bER1u#5Uqci>GKK-Y=PXP?i*86|RVE*Mk{r7`s0I;3Y^X9QXoYMXi z-KPM?XG>VN-`f{?VkP5%?l|EqPRKXNYb5prMG7@`hwT|Q@4tS@l@uKUccDvF;6~ln zA)|lkqP0-(6;fK~0C(bth%u62d3>&Y9iv%fNVENlx?(tj`++?A6iF*L25II!by=rd zl(R``Gsf#BzHrZbgi@*|#J6?|?)k;BM8bw+FNecD7*WRH*DZ2Y{1IcS(m0Hij}f$_ z#?bJkCDlSth;lu`)J`7dV<-WfcT5g~-$`EJM$qCMYdFcaXc_ZpOdqlD$`q)?t?*Da z7CIqS*|+=iR-r&&b{SV}6D&V~fP?#>`f@)skZuhc(RTyZz*rvv|eFQEV3b3wgo#TxkmcQpbPZGmFSKTMPeaDhr7Plihyc zP6wl)b!jVfgQ1E|YNUv|YYi&^+cr5i#vNj-EyQ$OuL1F~Sjj9~c-5^OUxZ}1?Mqn8 zwT6vPs(L3xT5zlSvUny_Um=sHiqtCst8O|YE?p}n%Kfc?B!qfLHdqVjH>=4*P~WYb z!K|5bz49)yFU=y9iL%o5`|FRCy<@tY&^#x*yg!mq@3JIv$-R77v4o^RbWD@FwIk|D zVet?nH$aJ8>FAwd$a`H%0gDx=FyLnp;B;+XJf@xz@xJC&5`ZnbmN1$;P`p|a0J&+p zVYU;>W+W`-_djqW*tgZE{Kt5M||Dj3oKhK&B0G{MM?@|9J zT9W}l#Mtu&^_MmIzr~siV0^C71=eHzJV7wkFem`+E06|Ej*gIyB$C1CLUf7@B*}2( z3E(EF8Y$rF2A_a{Wvxk1-<}=CIUXTAi)+mEQWK_iC$+|r!9@EVY zUvgtGX7bXw(_;Q5ueI^)`(B?LWyd-3J4X!Df%2Z(h5ICt+1|vuC|UZih7lX<;r3y? z0|u#gmEP>yD^BLu?&xds0K(PHPiwmedya{+%p&CU#Hzxmj6~uiyWfqsP_ed5vIVs3 zV9H8u`Qz^^NEl~p3zKhxK*m;L`o6r*PTv<6T;dUIi;qpTK1{H9OR$i&{ zvsIvqjHfqbP8R5;AA^+xmb+T@33;pW;rDsdR?SrHm#&AkD6=LSyH9OQ!nCUxVe9Z7 z__kfIu&Gt4Ok>tan_041}}Mjt`dkOf{ucs z2YV^9FrFwEHHA~~rpl!mGH2H2&b-X`-I}tB=;g%q2{~pXM(M)S`I&%imM>@=Tj2Vy zZn@`b-~Ztrb^zeH;`<-uVFv)7D~|tZ9(DlWxkC7#?qLT2o~sW3%RTG>re`ZFU|qz| z+XE2=@i=fsnC3eS?hcb}9v+s&&cUY&6qh1LF-b^Kn7*{H%v6wB4n$|-e3ojo3XZq0 z+Jb7y8`0+g4$$GFEG?g{
    1Qt&EbzoZ)z=OTxMNQ)LuijNg)?nXvcPo+uU;>Dg2 z7V(r(0^Um6N=-7O?GSL&8}Z;=zcY#xme$MsPFN;}wM0$)9({n#fS|>C3)3yf(?G!1 z$W5TU4=ZL{w1*%D)UuxXa>ag8YBF2xo4^$}q7wmhK)DN_ee27xh1imBphe4wvyNPP z_wxel_M>H7MP8qo`8gkr_tIAhG(f#c0wrvhx|(a~7f_qOEdD1w>;Ry->3QPyf3}Am z0Q56HFAhI4Uq9b!EOLzqKnK-6PcSBo-d>GuCR_mXTzeEHMYlh9dal^E4xn3_fI-~# z?fcWN%3K?wEPbZ5U23H;(J*cDt5MFnGCbPJz^2>6r$RY@9#5#87AmY_IBigvE94`6 z&2)EfrG{0ub$^$WNf+w_9-{>*$auRgqdd5Y@xrl2ma&tG3BR@a>Dfhc8( z;hT!hGoH6Yy>4wI4pGwk#p1>ET)hNf{=<_P!({_Jau@Q<3cynPd^^uO0ug~ecUOv#p5=*9YxBbkj9>E9EYFY}zq~Mbs z!ax*Eu3xVP^4K6pw|-+{I-V)qjT}A&^=d}{b}w00H$Y4n?Iz}{v`H)0MoN2%kN9fm_7lsmU0Zt3}A7hTbQsR zm`SiyAzFl>$V|Z0WeT_n4v2Z!8h%3>{zv$a%pm*L2y?%>fu1W@{@k?(KPsW0HwFJy zd+^^?d+@_h^}K8J|GM@70CYV(^IQK3Y7c%agU|bE{*`JE0L;%-S-?V+pG6i=Z=Gn2Y zHN@NMwB~Q-70w@aUY3;{>db@6uA=A&Eb0`}T#)dmg1Pg9LUzF=TUAq2-5W&u53;yz zH;$j`WGLF+yAHU6&_QiDplOvwsk+;Ae66uNs5riXUKw=I>XpjvvH8@F%Gbm=1o_%aRYg;}7j*wI7h} zzRZHJsIVBBxbg%MT~Xy&WP;0dbtiT#AVk0SdMY0z2V_iTN3j|`(koutm(H> zwx^>!RHga8bZ#q;AhgQ(w!a$Qb5#hC;`F=WMRxp9A-|Pi_(2!|RS3!D69$Y=gE925 zNX#fpNJ)0hYPZ~7daQx}u^BG2eDqxH;#0$0;)`>Mw|FeJ5{g4`1Py%Q-dIk*8r8E? zEPrs%vB)=Cg9yM3*2Cgfb|GnwXe6OsWqI(sFz0FNWtLhPIOHLrP+L-4-zEgoW6JOe zX~lnTjes2tUuu+)7bO1N}z`kt>~-wHp`F zDZEnvNIVz(p>HZd9=K0nGV$KdP|K;Dp;S7if~}7(J=T@u4X(m>BTRE`KA@WyI#j<3 zOO|AhJdk=p+G`ijVLIdsXv?0dsTAM<++y0gZMS2gH6-i{qPZL^Db%PMdi9^NT$4ENqT=;^loPhmh>Xr^2`kC zScfHaj&+FHp#Thx-~?ik*1PKty8Z0|?FDRzA?0d{NOJvJ;R=A4VGNN6Y@aj`8NR}7S>(KIbZ zTVq!;dn6ESQoa=%^M-o*d4L`zwG}18kZA#!-fTQqcX4dLzX_Vzn>{2g%pZ|-3DcV(pG3Nxmv2MGP!Z*4sFGYIMw9BfkfmwB^OqVr@sscRyUGDNNjO%oWc;(MBC7{@3tY!F#8_=JGMSv5nh+wjHeaq>HN1mJqA5h|8rpELLXR?dnZ8lrP-% z<4F@vd*kX1=O(>+cs4w;qY;gmsM$_`J-HT2c7qA`8tJdvDcIT{yv<5*0J)J^yYR|N z`_4obK6Hm=uo6~HUJ9jhRUdju~d&jJW|y_a=&HC({Pi(@|L5H75s z$S{vn$(MYSb8J*4cgqGvx27*Nn&({@E0&dkb1H5Uvl9y`iwN6Tlb_-l0Axq*6yVd+DFl77} zGNg_hEXSsY5jw{KL#D&0S=z$rzR>f2Q|Zuu{*KmL9yXitv8goghF6UPMzQaf@zw)f z7RDK&vTM(4hA5}Us+PJlR+^2n`_1TIRU>9+`G1^^$FnaFUEk5@MF{2(wKSuxakDQl zqOyNR7oNU~y59rrG_wz^&xai?C>_;14W{__2f+}RAg1>&7E%K2s9B}VDEOR4%fUz7 zt>!$enk+t99L{^H0Wn?n2^5RJnziY-HZT>}uXM+R$b>{Mo7)i#%u7mRbV)g^d=m~K zslXrW;g94b*ErO6m6j9S>%~IA0_^cEA5vx6QIU}qSZgpc)s&Sd=k1-j-r|Wpp-dMr zbw@Ej7t)5DLJ9NXrAyg48Wsa{!Y*X2kvwwwU{N4kK^ziy)P7D-Z-YndI!We`;1mvS zzK5Hfe10eV{5-+xAuN={#JR){r?D-F_`}BxX?e`@Wcr3;BHgTxgA$`5IhHgc!7_wQ zUW$JtDIC&AndreSFe2n#pyVqF)o^Z=pGA!(~DPwzTz>*|-O)QmnJg#b@;-uzo&`>j~NoVcny6rbwnyF$LT=ibt zUEsXt*tlA)N6icb3}N%`l#wytQ+wkC$0qnKNAHF(Km+SkBbEg0vJqeJ0AabF`NQXH zx`pR2v~Vgszq8t(;{LzL-oIOoT29hhhyZ5U0b1uf(&MLnH>Fu&kN4As5vmv>{S!7t zX40ukqaf(aP#dh>(1Wh`5HAF?2ZMr^Kvmy`9`yk;*Pth}KwC5RmziD@*X3tYzX+&? z`(={_y;WoelgtEyz8DWUk%V z^5N5pNzq$N=A>VVf@$1H(dohk070Z<=?ce}24C1AYD%he(?!@#0h0{t>P6)!u7e?g zd-^JV`X&@nS@V`+(jG40X!fSw;U$I*WwD-F&*oM%375xD7acr!w-M`?*Pj@7lmdQd zxjzm`{+V87WMNUJldY@;LK5jKgf0yFPkxE7y(%zAfF=YOX=u|=TtF3n5Id#h;{cf4hQhD-t$ssdIu!vuQRNBiym|I=WE{-bi`@1A6qX8()KJb4X!1d5BKPr0|O zmEeC{H^xu5W^%!S5{5wu4=wr7=b(+xg7DfIFZcK4;WMisx30t>pR^4%%7s~iNM+ZZ zT(qbnSw}vjbMQ+VxLa=BDXXy*Khq4Ps8e)LJuhmiZaS4zq)g|2*jS=XY}!AGYgp0w z3?L)=on`+x8u-_p%q+_u^W66N?3Cp~)KnQ| zIUTpH5f>R6Lwm+iIQN$!%4m_OdPyZ#CC`3M?7KGznqSIWzq8t(1_l2f^uYZw{se>{ zvi1J!5lF16hugT2GTipNjsjh^3_fUGEIWa1cQmCu{1jLRhbM+3=^D{4U$<>ETbMz} z;Q*g%7fZ#aN9P7Xq~3Ciw&3{m55NKVzJ(oj03)r$suop^EVKZYD$5wZp_K)w`~dON zl%==|ZqEsgp`E{pxY^+-9Xs>VV$Xh?bjobxl#&xGXE2S#BEJh0A6y-hK8cD%(sn|2 znE+4fEDHYRs@qqqY!3;kY@w~2_!Z_iblClwJL9Ywq#I7P!PAINnOZydS-wq|!j%Y7 zajs1IiY2;D96Ua}MC|wp)XcOB%dF#J*Z9|4cv>vg(BGNxPk}tsN8j8(ZlO5IF>HQF z|9dZJ8iXINGsj%W!iyuX4Uba$$s!<>zZMGjHCf75yxkTY8&2oFpSLYkvy9gJ^U8vj z+msQVr%Ix{vg*p67h73G9S6451{doa${ihOH7qXAkS%rf70*L5ad>6sT9|E|Md|Oy zW||}A_nA!l*QOS~Jp|1b8i3UnQobaIfBosW;}s|iZ>t27;vn`dWjm5b zk>I)uNcKV8Ez}{>s6S5o5p6#*n{1*~>JBhtb2nUSL4p%P}4m8Lg*rMFa#88(SD?vX1Gk|r@sX|kRANavruql5nLN7%<3wOD`6v|ox=lp8n+cLguq_j^STfy{ zBYV5zE>cn?nr4{}-$XLzkG3h{s=C!$-JQz9>G0PwWCO6`U;6xT9-QUL-;*c!|Z^S_Z z%WP_G=&~{dIcHy?H95C?;P(?uDY&M+QXZ`oB6SZBOUftd*}$vgE~xz4pxw}=W9b^? zn+Z4m?=JUGVfSD4RDa*o06ES$!H>)RXxFJ^d`v%l=2y~jhBU#N;7r5uSQYOo zbCT&7JmXNRA7ikFSlMbqJe>FZaMf#6URg_;QB1uhsWBzo=2AIDA}G_O;TCj7$(PQu zV*BmrroE5ACXq2Y=-MMGzS?=B^Q#+t(1)SpWUJdYT-xS_O18hV*q??5|C)j%{5P$N z>sz;MO`5VSfiCF@Eq=4kKbD$d{8v$|u>7!AYAkBbcDt-EELF8|{m81UgZ+ zDB&o@tLs~{HIYa8Ef8VUD~(d@=w9a~Rq3KgggXlf#cE51aHViy#hkX1 zj{c*&DJ?r31y!MzIb<+{ncnrt6CP&bAxo2WgtA(V{9q7W$F_a;*NG;Izf?<^(xW>{ zA(3XZua|<|^qTTWr_!1a{FEp+gA(NgrW2A4sd+dx%MaMYr6Y%z$JmB(9kjwo)8F~; zPoejRe9zx+Oh$%=zbceiKOu>LC;d-E%-8-Su;Bj%AU{ARov`iy2O#fP(8PbYo<9Y& z|E?PT-Fp5f4bhp8|Iy%*qI0pltBnn^t-?QQ|!v{uPOs(d3xtwI>?VGBuWTTl{BvfTbTLQ=USNn0Tp{i3DLeBzSg5sQIeB~@mBg=lf% zkYkxrDuLcpmFk9mIl79xB`meIsBr2KICm0Yz@VSKFLe{9beCrl%uE0}-o_bs|(;CFN&0+l$Ip(zm7O{U=h)(-j>dUfboP58&TWxJU49 zYE8jLjpOdRUW2?V&V8Qmo!Eb8?mq?C^z8rSVgR!Ae-&we5SHA)M3wXB;-n73XYW>^ z>4acOeFEriqfp%yME+u!Sq>=7FVU4Go~%zpw0SZCh$FDLv!uBGCVumBO^Oin{HDzb zQUO?EtFCL_n+A<5y`HqU+O_}~i@;=K&eo>}j(mnZlu_b>lqYx_LysQwW$Edd>yQzL z*GkAQ*U%PA;z~Id%UwfuH5ZXLeEGv#wEc6D_WhIf5^058%LRrc@GG)7<24L zqD}1wr-!`W(H)mhKtz3F9ltZkpJL~K>;5pu4##TIe@vKQg+{VXe2@s+Zz^oP*y+dw znO_S*69Y^eCQ;eN>zKzi8y+XFKM92?58mfJhh&lX;Bix?jh%)yhf`NlKXMgnI9k!~ z&&yYFA^*t0+@UKCYDCU^cdaYS_4d?~fj5I29Tw1LT=+P`e$PfEV(23~_YoL&kxl7x`r~#B) z>TDKYd*Ny5zVD`3*pW`Xw>w)T*!s0jiy0qTe%AANedqGA4YMF=F-`dFrpTyYjJ$qO z$2Wn=N%`^5v9JqXjGr&RC~NPYh1nZ7lv10qT;5vA+L#l)XUp+0s)diPL8Y$2hIu&~ zNG%U2?FUZJH#F4il8jC`e1CZ7;$EJI2Q_y7T>;CV3)e9Hb6YaY4n}^&ea}VEEOg%} z235E*sP1ZBeUcrGzkw1`g$9F%2AR7;-7HSlY>rCO(v!Zy#Q91a;-!SHVBObomO%Ci zjehDEIn5ENG;<|jvZ}DWo_QX+tyGy8`uf`UL;AcPL6p}a6Vv|;((Z=>R(>rp&jgy)Ns9u5LDCS?aS_}(dV%$RsG|D$PAyhV!kN+Blu`LM zC4@XnHL}dYa*aWQag|4n_chz{IPX_sO{d>&3OSUdAU!zD zI3ziBHowoD3`uWIu#BC|3WG{(_fQHFe5g0wsG`T|-{6xoUZ}ry&bhVGB93CQLKT^^Nhs z1JBF7hV#hUpmG!t_o9t@7I7AVbQ8Bm$1{ql?pFvN`3weDnXNFTFx}RS#9CFeH zhK3JofH5NAjsBk881o{Ljw6?nszfBzV?io_z0BB={uZVY;+3vKV46|AHB;>3NZZ~| zt>G*gY}kLc#aqHi3uP~J#@X~%U00cHSPr7;oiH($&&Jr>YKCHYQ~QcJOUFfxLGU+* z{bL0e#(&KnrjBd*E6p!-UG4`?b-Ap=ZK4Ku@}|JcCfaRB2h%;)B-AU&Gh%oYi$R&q zGN6k4h*K|Rsr5*(w4-UMLk~f_?#R_`H3Ya+WY_TY=wuXd0YjuC$1N8 z)E+70MIB904bOoyhu*^D_QyklIBzgHMSKv62%IAREX1TRsc^48Rz6+Bc8BZ5T<1zD(JO{hCI73K^#AU z=Iz15EYd)G8Q#oy5+>q&^=e$}cs`e)yp{;@0~@GFzOHKF7+x;Zc>nl-0?(r+e4cHK zJVNM85u6Q}Qa2PMsj~0qlPtsVW)p6x`B~L3ZX%)&2{Vk8ZX{|nB#&u%uL(zpD05zA zLmKC9;-;`%T#;thT(k{Zo!(KsTVl_V#Tw)&9Ds%&NN7eJyc=(hUv=6htSaKxl@xG4E5{r}y25x{Ht7_Yu3@HGn0ljYD zy9D{=MW^0Bum_K*KA>|7A^jkbE%ceeKn7I`&Yq;!{-T{JTTC3$NS0*pY-ma^M!{A( z7WraVYZLkm4&ZBITLKqHWVtslHBr-ed01xVEt%)$`mju>)*ck{cEFqS%a^ zHlk}~z+%%wA=$FA3>_nDCI9SV4UzQ>PJQwBRqr)dEE5MCNxW;!=e0M(HJp+YhI9|! zao51#`QndZ@jnl-{{&?Jtz(VL0iyD|pZ-&TN&m0k@eIcB zjOz^YT1|2Keo5tf?((7Kpv-G@6g0X!0EeSQ8gP@7Y$>{~&4?aXxEsfOD@Ia<|nmySte1h zXPJIXSe14-HR0U|g^WvKk1>57Z0>imw2{+mP;geE>L?*`EqP6Ljj*8?&4n;LM}-}E z*VT%`2A9Gque-A{?UM@gl$w44Q8u6II#G*WWW%9XydvouU5`%hJhDi6-fg*szNKkC zqmwn^uVT)Yto!Z}ZgA%BW`*J`D4Ii{r}e9;SaF$%H;WjbZ44ccxrK!Hviw8mBqhtk z9j=>Z+egN)pI=@;`se+;e&?t^1(6K@n)&p975#WRn@{hh5b_sZI$#Tc-z>HwF9c30ZMC*3_u`YCcI| zcq}A}K+jq6A}VNfJ0z?1@+fhRIM3`9`8_(OO8lg-Y)r!EqZ>`~48! z4PV+yf6OTxh0J9SG%eacsadwmV1>&w8;(__vu0hJo|a=v;HBI^F@jP5Nn#cLC}Kyz zKN}%ihS#%4lKsy5T9$qL3L(p?jr%);{xQb=nAZJwR4yDN8P&rF`Bw>x&UX@++ifnh zNaNV1cV{W#a&2N&@KjL%Qc$X^ctk~XD659az&odt)e3dB0lGk5J7N`o|7;hUHn7e% zaU)WR_NWzZ?-A(2mnfOtXCcy^6R^6Ug?QA^{?Ns7q#C)lXUKO-?WcLQs{r!p%`)m5 zWd&*U6^nfi*_nKfJR&11La#W#D*eag=)YTpIg%f)=c6$9ytPXP2*k`) zrqmpM@m(if@vw7h08Pr+pHPJ`M!8YSls>#;M+2s+7!Uz6qUuOoRwulw*XI9Kq7sFv zm!b@aUBThf&!Tm{DB$Vs!7RA(-VA4%XNT+_gslV@@;3|qb2Xt4_1b?dIQjzvepDen zr~7?IpV&7Pzb1y1Cw^|o8B6ZE0QmurT16m66)&>lH_=z5{rKy=U=#jTGYJZoz-_+t zl~p!8fV*&2^)UuBDeTu{Qd)Nj)Y`*FEuqM-JJJ)s-UNlhLjyGC^fBYv2s*j6H10+W zDoLR0{Qj$E! z-`m^YfO^2W)qZ#3f67ua{Ht!~ulVdk$MNJ9+FKWREpBaFxN`KZV-zM+5j$l@v%*|X zJQATU2OVZMpopK97+ukt!&%YyJoj>H~VXedMHpXGq!%L^wjrOj&MU)xbwg9FRWn zp}x3{o|%3!G8SC|=<+7Wf5g+i=S=2hW4D| zq`aQV5AXXb>)fwd1?F99nRXRFLt?c#7|~xNlv`no0Or_E9vv>wosOWl?AKwOElIw1gyH5xx6IKS^)p>NZM| zTE_iQHR>fEHOvt6d_bb*VpTFqd&*BwOf2NDEY>Vv+QX}%^3ahzrjXEBz1>_}p{eLj z;nb?H2`o*e9y$sDr_;0R5?w9ilD-;o(l~rl=IvIoM{S!vo-1qiu?zAT=`T~OaI|rU z35PbEY1lnsEEL-HOo_8_@Q|OYJGY#Pm(VADfzUR9{W4try3%X(W03-u}NIpaFyX#Wi8k7T}EE>gTgQGIu!j0g0e7g0sl zbIRnkystSv?@VO;Q0ytYSl={$L%hyw=jN5~`C(YG`o-OtQlU#Mj*FvB>$rYa6&o-d zXEX`M7hOsishw(G@w1b_K_gLQe|5`R{a4{?OLAem7HAB~VzFfB7LyFO7S+Y#Ovp%H zX`uBUK$4i?Gp~u#Ee0Bb**m1WV;y=p#c^K;+vvrBIT$ttAF6?@+D$z$h|)b-KN=!( zBGmilZmZ^P5L#C%Vj3#plLu@Zla3_S_iZ?ud`7k?vX=H)#k!t`=KTghjDb}q)KVZJ ze5_5?%bcrgpF!xJLhNR@2J*`{uXBuKsNz^M`KNXlE*L>% zi2~DEKSKkD=M(`%f7)d*rKgW7G_Gj&uPgZDNrg7&gYN?eZcrm5XvgC+*o-;}ULADV z94kg{j&o%l<~rBUwZF_=KC4Tjy|z;BhyMsW8-6yU%q0_jkTfmR;41XN z@S4evY_X42se6=A9SkiVQ+Jr=%{yXxn$VPSLn_bo*y6jMQv9XiBXdvK>^S3Y2=gOC zc&o!pYaFLxcQU;2tWJycL2r2(nKfnlw)~g^w#S7q6t6N)NKzG`iqbrY!V3!d!<8!G zeUI08RVSJ-=w#V~+%*Grt>rBsQ~~`sJg_44byFuxV?klFUwHAMOQj(7W4q3qfr}K| zc&&nIKP>+WQ&bnS8LbTRz_}(K^G|cF`UdOGkcG6Cc8lzCi+J{S+~q91;boBps&2Z{ zd#)SVb1!`lV%OS7cY@AMjbcB|-7_tuUw!?Z(mQi60<-FhB9cb$?7RppT6(?BW3TcO zdI*d-&n9H#y{CU9Lc?eyARl3EK~9j6!^!;My9tUg<`;fb(6$7=2^jrQ>-yfQ-5`VZ zy1hqWlH{nT@oH7j!zy~|rwQE*N3Sp&V4?TU{Q8QW;M@7$FKK>LyaHmK_RlVL8W5^i z7OV=a5M`p@-xYiH4s}?=n=K%%4Ka9QyvK4iv|4tt5J_&%!JKqz_o;axD3Q8aE z?Aoi%S!l@-M zEH|D(i1yQfW+eATQSEpz7jNm<7&_;rcSO_oy(@z1B`qRlr9#W#*=|D$HfJrpz&W}T z)!>w+T_wU@dLzm&jpFNr>bdUZRI>w|QfION=GcDYsb=DJn}k&$B&DC|t{Z{C%Vve|DbV?g=G|u%Ck|99 zce_n%nsFaj2j@Lp_FxlJ3r;X2C!icn02?@64~H!YigegaP`n{rmxOiJ-~nKDMakXU zLO8yZgK@Pi=b5&-t}kBbeb)j(vhiz7ja^1#5gLo&CRp_Kr7m2FQiLHgUF_JMYmmu1 z@{;(4;WtKsD8vk333G$wR@Ey&G?+!&McFc%@s_6o1V z;W@rJiNQ^gqerV!!CsjQ?sh0i-QXsFNghyu2?E_XrjMv?D_%vMPt0yPBa(tQe1#dcqdOB_G*fxScC>VqJ) z*$GX|1rSE#udJowj+t*d8Co?L+N39v0HIi#Y48HE-~uT#TwgJhoA}j|K-%^6)GzC$ zh;=?l3$_&MsX4*FlGhycV{0ccV(x#cIzmsI9QNkkCuHUliJlOd;;vF6f?GE+Wz`^Y2t?VX^;>@laoN->R@yCf zS)AzigkPjCHLNH-HC*=!m7SDN-kiF(QwFFw88&*T<3OdKU7Vo5f2zkS%Z;ek9i&l> zj|I^W>lJuNeJ~4{OTZI7ov4=9BCm~)VA?_sk23E6{zDSgk9r`Km1oAq* ztWuo1F5C;{0)n7@^a!R8c)flak(y1PSY~x5@*8>mN~T~Q?v`gCqiMqi7VVn%MbLFc zjvo8lLcV(j`(pmi<8Fb%G&#WN69X0QA#z`nxO#SMZh6Xwmx3Nhrj;C2(z}w4>b!|E1fs-EBL_vtcJ8k>IH5IE93~Wv2 zYR(1?Pnz@DLj|9IZnzDjp-+0*xY&G$G}GCpQ?(qI*S+(?hVnSZ(c0C(qHJ^~P%O+P z*`m5iZn}ESv!5M7+=_#V$V_890*7$?rmet!lo26hjWJjS{22}Tg0C>}j85dhRzjqPOP3^+`@=K;OTz`c z3?tmYV+B;$I(q=B-MTa*#@LsjZe6CRsp955-Xvtft}t`b%Z>h_w~{*FXu z_|>n)j*4eD-fvgC!v>}b30Qk;6!+yM-kY zrhr&UuBAGv0itY2Z-dlE!?{!n6(YaQ57`60g4{j6ryxwVRkOQavA?w1=1av`_tPDA z0WJSvCJ=6|8Ks2UMu)C9;f*^r(fRk)E><) zQbjkCU?f>T>fBA0M@KA+BohJ29FO5+gOf~&XXXa?4FVPrcPvyo6m--(?8q9q)oO9y z1CaeYYh z-hJ;#z+5{bIL4mgQNOtk0Jl-9uC;jA5~$X+l%wXN@k9i{0&gE-7!;+HyG14A z!nu}geKT}t@4G_AfLxW}-K>pliUoN{CrySCYMxx`^ppGcl_3y<5eN1Th}rVqFKIg> zd{vukg%4KfOKM)YK!LQ!?nu!FElZ2a_9H-z>NCA1!};Y5yL;XC7R^T9 zHY>gbSqjn)5LT zzu_=6`*j^Ajbp3DC2u1TngV5Q=jRulQ*Ac5)A}YFmjTM$X@}dXnq22=yeC5k!-h50aM5$lbrb6Jd zr3`HV)hKVpK}y_MI!!^Fu_waKbl)3oQn5vES1S8G)F2&oDvc)-->)#JF}KM!%+!ok z8muW0>)vMezI&76V2EZ^I-5mL9%j3c=Dl|(KF`npZTj>SdcT*EB7}o+cZ_7Rlfgr| zf7Tt%f;U(Kg-@8*?(%g!xu|_5HF+4^5l7M2zlVSW0eeyrp@vm2eEuDZ{FmDv>Jw!;Xd!nd&%(!H?MA<2=yT+bUzl)+!|3AZ@grv zVf#0YOJ`dz_mA4a)Opq}IDyn@h{J~gd#bdiP&mcJ@sgn;%1uR3j9t}ACSYh(4~+b zKp7D4rGXVop5`{56gZmFQ;;nbC+zaJeX)?4`aE}bbIbn>%-f^3rv!te3@!m53>0$g zMjCCBrfAKbv^2z6Wf{$_nDLcfAO7uE#V(z60Sg2xFU=gl!Uc!%aFYUg$+0>;mHc@j zpn837vq_dT_e+6VnIs3f2pKnH2Qbo!f*=ecp9ZWp>^p@Waz6zm(01vXFHfh-Gl78TT2I_!Lc1gO-q{&c3ghh0j}sBEImN4$8yt%&AtHBsVBW?M#F7y^g_iV zZr|o=S|ztA9(N%m8w$l{if_e6OzMK$-tMf+JBUq1-YbY&13nG zuKWL+&HK}YA~WO1AjrQH(uo?2&dYt(Uc5RvMIN0_ROsA#6X})|^<4e-NZIi_z=Q-< zLUS{A7p|I9 zl6NBc*dCt~;@vCwv2DekiYv$EgDIY?5YbH(n|>&GwIm#z8kprHISS+Ap8QGA_e7ZO zf%132+T2Yi1Jv65aWmzC#o3oCrmqQh7ftOHn9mQ(goA#qR4_XgpXWE6 zRPYHuhe5X$(~-&P3W%_Ui`<_M=CBK+^rb$ZxbWE+@qHzRXK`C@PECPC@e@*|)7_(BV#F=9=KxYzU2;Y? zh;b`s=oG{#HOoFO+Cvm4x1)@g?$FHgX?%EEP=va}+@d>lx}H%K$Am_e;nZ5Qsdp;% z$YA^ux@h$D+DKhi=Bzv%f=<1>E!dCUtG9)!u3~9x$feh*HhF}FNq2cfALSoDT2I9y zn~vV>oJbrU?MZE7M~;y$UE^XPD!H8z_-P{D@yXTA`Eo%>K1gDObg89$I}`=}vTj;B zBi4PfD6Ws&0JV@R>yF8t9Jc-uFgeCda9Zb=1~4NxFAKoGEik;ZoKUl@sF4-Gi5v@K z{8_tGF_o5C(nYHRN0#2Ky-Irxkju(wEh{xzXJYHle$J(JMyWr<4wrQeY&dJS^0<0= zj69oro&97^q&b(q&!nlK;y1WItT$lO9RtCmC);A43^TH;BMw~LqNI5=y4&l)aPbMt zQx{NqBkKj^T{HAGQ)N6@dwSLW`dcnJ+%!rHyZ8PjZWx2cOk+0|Wap@rbpVXWqko}) zgwTc3zS9pab_aDH22aqV>i0|8+jRQe*+`2E2C|$jF4z5F_dNI`Q84O$B9|T?GyPBc z8(g=HoCs819P^4Kqt%*KiKbb4R=rad;9l=7eMDCDOwXy-HZr`P5BDALsSv2bd@0MJ zTFNAhbfBKpLYohiHsOiXE!e6Pzcw$jnN!qkC+E_e7yV!s(a!lRCmh~C8KwnsIjp}A zVd8-ay2zD7r#(Wb@t!rIff533r9W@i7pt$DRmZwCw=|TGl~&kAk7=@G;_NQ+K*fq< zceyV%@ka1~2K~gyS3@7e0FKrvujAVEL$@X-vc`ICw|svQy^7Ba1?3s6O`$?m14gi>i*`WarY*Z`8UpJkmB3V#mEzE+zD_u%NGIt*L zyC#BKO=oaHDQajY5Ts?m!~{K{MKC-O%IN8AA_K=o{$vjV7dZO3w!{MfmJ5nh+YP2l z3MiLugW(WN@YBU8%={*QP%T7(QLPAi%bZBL@!d3}MS^K{9AAX7iV7}IRjTM|hAJQC z$ViUO{F=@a+wr&y&32MXHy}9ET{oU#MAw`+#B8tk&XM3_K7+?FI4!Mq8#iaocr&5C z)rh6`5@GS;aaV+v;&4}z8f6-IgVJl8X61L)RjO~RZ84EkbP6M5EmNn}q@tS@bebr# zjy$p`Wqin|(;`?y4dVzRmEIKDu?`mZBSgbxPW}d+5Z8Ti>~otI-<+$Oyd<-QTEuE( zU28m={jd#2#WCZjfMX;_e(?Ef3*`BhAv{cNyr3QJQl2MGgcNG?V{gzLRgl8Q=0h>* zuJUqzw-NTMb6-CY20W?74iO*fnh7~D7d*a&v;q}lOo7F8V9ozJp^HInJxuR%_ED)_ z%Z$tfR|`Vx&307E;f?6Qhp^nE>CT2V+KQ^}-OFa{&!^?|YW<;t%Msx9%tYt#><;Vm z9UpMe+NYtS$q5hM^+5M*X-^_xS(UjWZn@tB7c#>6+`=ptBx5P%;;ecD?hXUNDOYnT zelsICj;gPDu=V$i{dtxe~@GhNnFUl&})hUij^ z*D6l%bMK#)dzn=cl(sv*sqKJ{A=LPLMyJz-J-=MFGa?dMx^O|-sO^9C2d~DfH;+F) za#i@Iw7MK-q;;2m)OczRxvQW@kj5~&;AkG#i(bve%YUwbQ}#KIAWeV**vtv z(;C;1q{IsM2qXaRDwSB%%Lg}YI6ur`y;a=1e)*8gtPCm|B|vK z$Qq&6`_wFg7393{m(-KKyyho^M181#O zRHv3$Z3f%Iwl{zu6eI_w20G6{q`D~^zVXz7LOs2vQdff7C?r&LdW_hYepPuU)md9A zN;X^MJN08C^=-Q_XlJ^&AMi zN*k*VYRmzOl#zGVR^q+XG;YoyI0_T^8!Ry~ij{BYBoX8jbHm<%J6?jW^z~)iTC-`L zRPtJ1Q)^67ARKz5viq3JVDCV(J$z^|*L2R;_at3#PMgUF3w{v z8g;BUeo$GPxyO>p&0mftVe|?)DucY8<`tXVt9wej3wJ-ZM~uDWpF7ht(*)LrNur7! z-qJ#2d3yxOv*q1_&nJ?LK6$5Kl?ChG`2&$snc))wZBqX7hBQZ7pEGy;(<5AyT_$1Uud9pwID+mGpShP$XH^1UWsM&WaNWGCgM$?q3Q99j7J=C$#SX@hy`w z%k|pko{I^-FcvJD^JJ2xMhChtO}4eC%v5z>pMin~7~yYpXk_sG2p9PaGJ+VCaJQm+ zUV_0QiT1MRnrAe`XowVyBKRmb&DBpZASg&=spcOAaSnBlKc{l7skK>Itlv8P>@dTE z^qigNl#A0t^uw6Mtq~Ir*rWwiJ#s$3C4IuZD8L+|!lFqBO?Fyi`=(`CKT2M5Wcjlq zNw*Lh(m=w7qPas$r!(-REZ~u7PuAL`}^zo@@_ZSNG1P>I(NZ`haV?4MkRK%>m zqqt)5m>F@HJu8JHEHY5i7&v-P2Q`E|)a1(Hd4{67g!@QwqzbH0l7YK>uHAA(Gqu>R zXOyfdQCv@`hPYu^yy$6j#?^*bG+nWNj?CsCnir4gSplY_7Ve_>x$` zZo0vsW#?t4%`Q4PN(0M(%{HLdx>P!yz9n5UEf|%J%H6Pem18>O6B zS@Ju@$t6=}#j2AR6^)yul1Uq%Q2Uxe!N^!<6toUCKQkt+s4{zma6ggV?FG0T^tHtWCtZ&4c ztI)fZw=)`grD5Ej6AnYBu9#AGy`qVD^j>RUDqWHmfybm{f*)vRA!ZLj4%~7i{lEk7JA{;)JPLGRfDVBw z=K#RFEAb}jO%J3w#xak~Ek%FsvGvIv1sqmL9@QxrPPllkHW4t?xo>ELNR~{YXCZY# zZ?5U;&3*jV*a9l%2hX3Lm?drw<}*&gI|ox?*&u)`dRmgkILqhkoqwzEzJ}5|zc%PN zqkft22s-ytZ&teOe%hwwOpuLdDZ$0n;WQcs6R|M}@F_@s8uqy$jJ%rRD=DE80c7d{9v8Sy)lBpE9cN=fjf_o8BVLhB;C>KOUcwe>wN>bTHk4*jJP^txFi2 zE?>D;rTP@AV2V2yv{o(}JzOs|C*u&41=bSsdK{R0Nqr4je(YltD1CbX?%L2O7-T4G-$nd(Z z68BVJ?qwTN4pzHa4S68C;-8)vF?5Wj?>-rhlClBZY^6a5xsh%E9 z2&_E)G=92_C?K_TDNf!Ceqhyx4q5JKkUq7q4}Z5I1OJ#KQd7OO4J7rm+J6-%$|Y&& zaK3dIKOU04lDd~ib>m4$g zCxcPaG5G#3O=B6`y+5)sSw_Y-OGS9eSIAGZB$CrO*?93AkzN?T8Y8A^y4Lo)F=`58 z;j_Ou6TJQh0X;hS@0W1MS0c6t5#w5l2piEK?n3F&=~P(>kP_-vVMb0%m!D((UvMc( znu-5pTmA20ga6+UDQ{$@>|#qmFJo$F?qWf}#KOi-K>r_&ka7f^Z2$Gj$=QW~gXRDA z^Nwm+J8zDme(&fv?pn!@Px8vI#*}*E;lYB;wHNStL8a3W4htGZZv%K^}VMhpLKc1gqSc9vgnh*aED_8!vv-VSxXC!1&pK(%%HJu zWNIrkFaT-G+GiWMB+5rL|A3|z7h=@tG?v?{i7|?KXC4C#RUYaHb;$wjMs&wTEpv1^ z3z>|BA1LR^2W4VESWY{lF{QmI07YoHap*|3lps8t6G*_aJMhnZUjsvy`{*&{y$=)` zj*SkybEnt=lc*iBYC0#5860B|O4>ujFz+df2u9pfwiP@|;4lWMk8m)CJ(o$)qnr~t zOM$iIDJ#K`h!Kvg3No`(*Er!OlF4+L{6Tcgsh!iYf3|EGsLIsx4B%#te zBSj+5^QQN(w`oSKq~K%1NO2Gj3NEvGB|5Z-0Rj^+8?>21(G`=5d@n#mNgaVdB$d*m ztdVKtIIo}<$BY&{f=SLa4F?<#IItAfv``X>(eYJo--p<1exNTjT&fqfbLsyBB|30X zBNM=r7b|uU`}VRa>vG2k8P_YtGyv5-e-OIhAW#TxNRV*`m+Kv6!Q){*5(AGF$rjCH%Rqsok3M@K~8V(LoE7 z!;ltgfVQ;dh9H;b9wTCCNJf4)h>&)x%?EiLrqfrk(PlUHHsDkDT9o-TXT`MQeSZa_ za0yS#>GA#e-akRp@9PzcYbfXE6*}LjW83^nn8#G*yDE$>SH5;-o(p%6G`Vw>OYH(B zhRFUt=VcNxCT-V}TNEM5RE5it&WD)9VhO%VS~~=q^`7$!L)Of1RUG534qLvoaMx3r z6%WpVLL@Whhks{T2FjuX?hh{}8J=_G_oIT4r!LESqd&XTkGmXf_EzT$-Lb7>4J{Hv zaHYscJWW(OSt$}w(B#r^&Wqre(VMH+Z+&roJUEYVmw_t*@4OTtiRT$XE@b24O;G*w z$W2%&OaKV-Vvq0nJdFy?k^gTzLi@M+&sCWz3@Xw!9lIu_(eN?b+QDD-cynXO>8l?* z93G_1KtbvUaAl%j#Zt^+3K=c^w4-v)gdImu4=9b!q;&-bbT4R^>(PJkyk1hML zV&NjuGrWq}fa`e#i@1(7Ef0*z0}^lx*-$$x&OQ;$PvAMvM;!W0!-&AShZ|T(*Nm4S zcTL(sU$hI7A<+Z_q(}FO8WQm}Ou*DU^wlMI)#yy>4h)BFZ$R43-vRD^P(d2=24*DG zhrC3HfWO5b6N>Ro9x+x3Cxq94KLY-gAcB*y*WkUJ?9Y$ zFUuix<~sBHh5nKeWn#vF2eaUecjONel|!2aB4HBam5tO)9tsqm+N6Frk-6-jv|Zoo zJ6qanThtdReQWQ`ZXt_(2s-;K<-9j-6t%7VrbuGi`>(Spkj7e_IfwnF1sZ@l$F9s z1kp@@hH4!6r3ZjOlOW)@T+8b3JDT%IiX0${18skbfl>Uj%E_MW^BOQ<7hG-deHSRA z3A!~Nq*(+JUB8`TX|La}6W`eu%!wa$h0Mq>nFLdGYeo|Wl*tRH1nr8c{ zUd+9{-Urz&Mu_t-;~Un>i1}r~xb=c|V@`kE<%_GU{+=@5OK;2EGuk90WtO~MFD%$_ zUz`#DDQs@2uG)&X>hU;--0c`S_^FUIuFX zeaap}D35Y}%6rH!?(eA(+jHRYbYdAS_nI63o&YGNxl{j6Pp-D|VRmM+DZ9QmT^TSv zrF*H#d&%Bs#=;>3Dc^B){r2VU>97%Hz#A;g~=bY=V|Stu@^0FO9? zq^=?_Rhq59Y?&=x5{ydTuV5>}STKVB&~{a|cWzy3!-D;kA4k8_7cKqg${25glbGH3 zxImxXJv&O1@~%g(NF?D$(1wG%8zFs>McLeNOs(xntaatyo>UKccR!u-Ie*ypQW@n5 zH!YuG5`L)oG0^?H-*oMv@znZ=xJ9r*BV#wWaW|X!+XiED91dt8Xw_@!-Y@$H*&VH3 z;!{DQ-mVTi?Kx09rW>MFFtFsU8^`7jd(K8Z&Ga`={E{2e)}a)*;qY^HavFc~jKp~3 zIXK*Dqy4KS`j=X zHqE%}Z(%3#x`hfj5gx@(;@K~N-cID^e;Nk=d!X?@4uj0B42=JqVeo$dysx!2oj1jh z{C4#j?XCL(obk0O)hE=|vW4YrPB%J~5FnKz1Oo;QwSS&JSplNLDU*qkCiyCS48km) zo}TVq;mry<&2udO#m!})XM09P83=Lfk|4<)Rb`+qtjTDf1+6OWGY22BUSrCt&BvBl z8K?&poy>B_R2jtQBqnl3EtDAND(f@Zm)T_;;Kml22w_MD&V&SEXnB#hHTJ+Y9i$yu zYJ`B5yx?A-jJ%NaDOrFpsAfbIL||qIgWrgUL#H$Uq}op=78IiaD_oM6CnE z20>axhz)39VH4i8mRwlAg(1OE!3 z;xW&QF{0yuFe`)+gcUp{ErW@AET*!-c{wfLO}k44IP5HGD46e+Fj8wI#K912Dm3JT z#RUO*+p=N-!qgfDsub0V4nNLD4bB&=7Vn>>4+Ign79jI1a0sp{E(iVdT`9nXAnGKN zAgDNW72|3yBqcEj4&qkgA|vx8^x?ozf@tE-LCc`%4Cq2AHG$P4p!pT`mY|VU^%kiS zaK#YfOc(bSqB*`CQRRs}#%UcP=8Zv^NXZ+6Gzk_k0&$8G)Ss|?6I6;i2it~TwZMHB zh+;ut2unSz1u&Kn%>o)r5TDbHC7?kqC&);^e_~{4{Mn<#0(qyMw%wZ*O4P=TV?<&3 zj;HT4xL1DB*FYzH<&F0Lct~Fk=l?rD&6*g+*D7EK7E2j^iRi6p*emQy*`_y zFn{Jx`KjpwLyp?Fcxk@K>y1fUYJK6U%QrQzh**f%E1z_^ zL4k35;$bOX`77*@y^%aDguyX1Jud|6h$13|FP=k#2WiO_pFA$`j6;+U;Ha%cCxFSD z$39~p;&?0*rg>t?ChI1qh?1WPqx70zrtei(H6I-{WtO0`J)e(YdJ%CNu0Jye&S?Jm za(|`)O8*RI$Bv}VgPQ@VV3`&$$RE*fPMvsVHoaZectFRWZJ3KHvgQ9_ojS2?CCtDk z#3;k34C1UM3N;~$jY9$F*r!V5xFK67v0kK@BSH63LQAfZi${ueAG(ez+mpqsl$XTE zoJ70>hQCs#5(zmjk4P&^kd04=b-+_Z1vZHUIgp@2btNdW9ZA%UPrCkvZAl;wWX>1T z_{u4of8;*Y{8}14zAa%$`tcDQU5^^Kg@hc9-h$TOoPf~e5Q5^7i8#Vk^nLOi0))?D zQ5-0NNASikR1m;(L;NK{-X6jNJ)`Bc%Wf5jYn5><$lw%-ZQ^XwwLCBWe(MmeA*wo8 z2nUXItISui6f$^7;kg}L@-J)=U5FzBLTzd3cleS2^5vLMMfJW@^@5czL-;7m!SjN; zVYDTWs0EKUak@|XPEcb713nYsLb_T5kKd%pH^Q4MS?=dE*=?0v@iB2ICBO51L-OdE z%)$xop~JG0!B0AJXn!P^$0K*;GVObPVc&N7Fwh=X;*rD<7Ys_kBJ0TqS||326WX$1 z&z@PNq9wDGl_1sBad*Ti$0ze_GPuX5ZDH=6*3@Zk+T+tWs(*H-$ztTjy@MyaN7_-d$L-ZXY-S3fV_>)2V@VZqu%?1kM0LT8`9VKqK&5CL#6qF z3)l#}qekmDyN9RwLEM=<$k+UWj;60Rd0?~kV$~_)owk1a79&rl$u?Oj3EkKPLeP_+ zq$0&c&LVnpj(it*Pr!Q|gSChm#f{>=~zJD zZZX~Z!>Pa?{KKulp8b52^_wMgZlbmfA;YIN9_ituCtEYtX3=w#bdUPFI5?#_MDTtO zDA6S|SUz=@*$Zj_KwVD{9?h!CB#SQTg0`{=*}~WgqJO7zZm$bHxZZS>hPvsbE51Wi zP2sO1g$?-7e0Ld#R!gpiY}%3X07!@(VrlQ+DL6>Un-~vv6Lg;NN#ihyOJVq2P@T$| z?wwJh+~EYsZ448w(XAFA{ThUF`_p5dY!c2D48}4kTMwS9m>3|J$OV3wBtF?kFq>0= z9Uk2j;e>4$aNknTJX-E+m^(MNzqdBWZPnB&YDxa6OL8MFjJP7#h7IQZ7qDC1H)FZ` zrGbUM}6QICsj7y1ALoL`{voX&4ZnJwWYpn6gNH{u6>gJeP!JEXLMj)(X|o! zbd;PrFf8@pS!>xW_2JpdO_sXGW7+QD&V;b)x+tpW0@*Sj3fKT9q4?^yjPg}(iR8Az z3vnh7X-tH?-zQ|^XviTvdDuzBq(^lYt-`(SWd*N#zLJ@$u8&7h2v|b;2Yj-ZlBu+n zT@8K(A6%FbXT2L;MP-JgR!?>%Z{s!_I*N2<=vF>&!ncZUzcxQ&E%rCcAHGuk^5?IV z-+ZOJ5FOz5@Q0}mcCj_=m=9_&#cQ$Io{p(h z{P4Eie|@~k{*DMBj>vH#3D#2A{u;`+tFWR1}NjCmI z?`2e@>>k(6}}B838AV{gE>mP1wMJ~kcl%;sWBS8s-w12u; zzUI(&`KG(=3X&ia6~-O)=*RF@+Q|4w3vw?8@QZH#0rQ2&5IM7uz`F55D}m0nT=$c) zd~{7Sam_Wa2(P|mbOa6w1J|Z6wBX8@;4XHU0N8UQmxRbvc#x?ZgAf&;dOj)2R;yp}N2&sb`!y#NQqA53yDK9|Z*we?AE!>hXJ;{wLvx$D<^UjV{ zLQ*Amp+G|u1|ufbB(8t%d8n;7829xU_9uRZy?J>RH)GF@l=dSM4;GD*s&u4q0{Ed z_Ua0m=#gza>Kh44+@qllDVVoZ{6JX%4lzOlF)+mwH?UVKk z4jD%+Xy3z3f{jABRNU^QljjWFii$=omrx^J!VDunomwgxI`G(0kyM;pjEY)v*W4z1 z2ZEmPiP7c)pGSq+2-agQZiTl}4*xoj;~jrPS5xsnj@+7Q{?o25l`VpSuVM4Pb77pV zfC<`rLtE(vu|I#Xr)fzvf|beV#vwrg8zhKFSbRiv;I~`2jVolxktQIXclsm4*m+vg zft1)Pjz_%)L0bwx(aoh62MWV)QMt131#SIKY|5vg;@0S$Ig_lY5tE7(gKrfg(*I&_EIaRHXc&wAmVl5CF3{r-*eDiUB zuK>c9_){gk+Jb}QM+g{YKHp{I-Sg5aLpo&A%2Ac?=O#<8+IkIUtr!&ON0PMT^6=9; z-0~zLbt=d~$-~iHvtxl5NzEh@(#m|h3dy>p=|m5$fAQ-zXOeI5G=Ce1;sE>y$8-@M zWY*3KWXeqo$PvVTcVDx1f5-u$-}Av$_9Mi=L0}=D1-n@MqTbtJ8j8*&OD_dXP#2gJ&(x%oP!1;kr!v8B$;DTm@DuPuF*I| z0C4~`O2M=hq<~RwEyzj+$!b=BVLmW{6abpC$W1gB>FafHWcCs*;AY1W;Ayxg%@}Im z0b=0k#AR&IIv0;^i$WEU-55kEV*zU#fLV}3O5*i#U;p!6n_;8Y>c zS$G~*!UI?6F*gCTT0|{MAhZBrp*zvbICma^9;-lIZFE2ph-TtBZbO(qEpkExSHYB- z88-l;PiI##4wJ?T=Aq0-gjwYgwU0yGJneK4_yjyguZg(}K_qbWq6)ZN#%+R_JAros zyZ{pLDS!cQ9H^ItdWjx9AQhE_77JzEiU5o|Pxyl zu)rXU0U*a>kV~fA{Nygj}iu z)28XlmG6t+mh#(PmKNCww7u6Y+H0Gyx~zM3ZGisvmom3l#)53J!sT>zmZy|CUWny{ z0+^~6AFw&8ZY^%Ukxlw~OHbDY+q6BiS+ij8vMSnVZ@1>Z=k_Vc@0L2q*L=LLAu%sQ z=Rx*4>vXTNd1EXrne4AmxuY>J3#2ySvF@9morA8}g`b~KE(!6Snn^1l6rJ$$()PxV zitJV{*R-m`+b?E(7NvxtzO7pCf6r{i4zaui>vp774ZE}k;eM+^27x^;z^Nvdw@n+D=jX}dKmj3#o zTn|49pWyqWT`Mp2Vd2+1s5{FC{YXo(3jqBctU$&H@`b05SHq_pEBZEL`jl*`NB%Nk z%dT%rCg;{5v(~oVi!*54gOXm^4if0u#<2Aw+85ZzvKKx&yFT`4#K4b5H#T5cdcU{e z`gXu3!>Y(A3NFU>P<8Rf0zCzy69-nmAhy(rjVn7m@o;I(nl_J3^hPARjAtE+NtOl2 z2bCkB0k+W(gfn zs>`PSh}HkAS+H`Pep*FQeZ+`^aSA;-?vR*U{fDKy^8@(cWu1@^TrWng`rat4P&ynv z`u%=C1KCcW$16rMX1Ct0oB8gmXT!{%-G{hbXX$!Der$d|cxx^)D1YA_Ba@c9X*o7> zvo}1}w{aMctR1oOB&XDO)u?^5q+qRYX<~C~RN(uGb~*kMpfN&SL8u0*22PBXYJMTI zT^scU%|sIVI$RwV)LN{>Dp> z|ME1t{rzI|`vjSuj;eY6U64I_`nW=p_i6FrY52j6M=tVvdj~@hK&_q8vJRRLwGja?oTGL>dqL~|mR$OwyX0SQEKA+cPxA>ud z%#IFToSC%DsZC44pEOFkIWH#ey!?T|KV7_>yrXcO+<5d$azq=^_eM28Cn+Z=bMTpJFpxr!J^zrD)&{Aohk$$cMlhKg+H(7O4&@WI!-McZ93K1Wo zpVwzTJ*hL_QKX$+O1Y&E+eap@Z8Dk(Jp^neFVETK@c2CV1>OD(;bb+Da=R2qDb;+Fg7xuwHEoplzh6eWyy!&&FxE!;ht<> z`6UxLxDEJqW2g2WzfxPkrq=zp=fLm&!fy+{3uT0Sz|U+A+kihL?uKT8zGr(5nkOtu z&ANWGKUgQUy8Gx2zkIR2>k-9mDbqI+5(ZKrxcg^bG@9c&%wVrJGFal-S;fl6fglGD zVH4U20ielsK5+FTl4RSeLz1`ip+50zESN}0k0u0DF<=gSRFhp+n#=Tu3r5>%2| z^Xr21K2xCzz}nDgQ)xIA8Z$GrM0Qw(c`jV9$Y?!ocP+q=CV9}zOs~6K&-l@p z<<}ge0Ugw3`%aoWc0_L2npI=%1*@^`wERN5f(#lG^5#ms^?K&dsAB z7Yh{B4rbWsp)ocrnw3R1o+yWEoYedFiF3@g5EqIfYZM?%TUX>IMzD1Tg-%&D`RYvs zGC>W4(bUcx6_N+ENnDrVB~*O^&zI<`_;= zs@(1Njy~SVp6Yf+uxdkQ&R*`@vVBzFxSs5=p`Ww|yVj>h{Rc8Xm7&;kkggDhkGpL? z`L3E}6TfSh%=r8qI%sxtu2;$QK}m}_KAoJ{#vIxi&HTS1pYgeHVldtYpXeTD1m3jK zZQM(oGNs>Do-GbjHK(=@7KXIXnks7_hJ90E|Bjw0H>+*#q9&_r_tATY;A|C{g!H^p zt@DKT%7NIV_Vd^W9j|M8UYE4|c4_&K^`bI7NbtN?zC&TXe8*q%TA#+Ua315V!TyrN zRmd;6f}3QuohM0Z`_Gb8cVEq7FE(R5x$8%D(?he`BD)b&^i)^)Av=vWkX5>%n`WKC zCpZ4Td{d}(QP_j}(zc-t9jZ#&`&HA3^^-V?b=OGuRr83h`5RT?-F$Zg&$?EZbgi!G z8(q@2-|FRUeIgNc{>tLU7hsQ^LM|iN*MJ;!8|0N$`LpsqV-CGH3H?qTctZ~LUmXs- zKa2Zbyf+EMFL~d0>S2T4pC4g+y}sStZo6(UVA5UR@64gME3xlL``$X#_qYl3GSkR- z(Wt|ZG>mXTUMnk0v^uy|)uWS`_|L~us_-i`p;h5l9U&^bYRRDW7YkWE2P(XJ!>Scs zchFu|?tFa=fjy;b0#@JqXL^J@zFE5li|W~-eQy8mFU_@8Xb(`u1y-E4g8YfL?b)AwWY-NZFtK~| z=l<$E&{s0QF%Puzyyyz;(GfbNBXmeZe8rQ1aK-zMOy2mJ+b1J*M7@C9>*nM{6))V& zLmWVd(K3D|pT_%p+z;R4(U28eGKJ0Q)sH5!I(O^iMEI zHAn7q;K`qDM~!~O*KVQrq+tQi>pqzI{yi)5eT{rJ@>4kI6Qil=YN>c|%(K2f*+ZEw zAIa7ZZB=jR)XN_&!?u0`i>LzY-z0-~_^X~z z*S-*>ZXs7D9~D2&WS&E;wmG3SRyLf~2vn=*?wGBPF?U32xy)e|>-hJpw;CR5|La)Q zg3+ngt_;{$wPsQN&NjKHS=E}2(RZLEcvV<+g4HS0u9XyYquJ0U1$Uhgy!ROu3F$K` zwi+a->V^u==!Ujtbyt;Q%e1E1NtNg|TT?34pHp(EwK_b;?dDdBqN^g~TH;o9Ji9RR z1P6|b96zhDv6b{43lNw}hQ*ziH zt}f@EHm|(b<{EtZ{tRgEaaOMOh$v+fK(h`Rv^cJZPsDUM0bll(B?dOa>1 zp94$q(YETsxVhepk+4Nqb}VpkLrVl6Q(U(vnF{ zKk~m&KT`NKMK>Gh$N_Tvxd@lPFVjIb7E;8)*HtK={nkds$4myJx9~2rfruShb@y@d zfz};-dVQ0`@>={#QmLom@;9@jcw0W}Q5;M%&ecZ!+m=?YMapfFUFiCYv>%(s!F$EL z+*E|w-NJ@asb@UhIo zKw=&Ph|U2&MwA2vhO4nMP_bRa1_Xz|@DwTl5=ejui9iw3*B1bwpWl6dBt!{_0OS>H zGq?pXAQlA2a&m$!;{Hu|2q#ye-NV;6)LwuCkifw~5l{a%;Den42@FseaLXVCdBvuz z7{p&xgNT5E0*ZeBki7&ap~5ZFw>KXjpMZblC<35!is1?1yTHO605Ao4ibZTI__q}% z0q`rZ?u=FLz^_gm00@W=^$z}>exSj<{@g(Xh@lx=nAhMzTtGMmbqWD>QRs*V(R+XahfjTx zhHCPIG5jmou+E@sJBWU1aA1|AXTZH|xZkH!NWq~k#XJG|jLUkwcfZiiPBYVvUZSBH zSSWE%q@OBz$gmJ0yPNI!+c^i_JqUb`kK1Hm7`xlMYFKZ2cRpi|>0#)qx~FhwW1_G2 z8N?_ch{tH?h^PpF0z7~U`jN<6bs%DX_cMEhrzxK$VS)|ZeK>~>OJFPr=YX9r#3J6o z9R&cWb5K~3U-G*-WI_m#hHyaz0PYH67`eCGGj_9zVg1wWcVfdn0O=p>_dtNJe!pL@ z=03#?UZ9(cSNo4!#7E7u$}Ea1$6w2L{emE%A@qO~R0NdD`#r{6k>(W#YZ_St*%{olbsI|lWB{uu0YuR^<30c^)+n7iMyETP{G zUE2!Y>8a~}#eZyYGu)&7xVqmiiHvfnX>_Z4aAComAEjx1w?qBz6R2R}XN0^4eSLHQ z`iT7B{)TMO;EpXHK^}XPckG~@t2usUs$oKiPyJ{z0vaFy;zR@fp=`$8oDe{Z`5Cbd zVPAh}%mMHaVg+`(fb16_KsX4J{rb$H5dfbX_FcdZ>SaJvaA%h<(BIIAUqQdQJNhdYV{ebh#0ylVpF7X$3+-L)mvi6c<*pyG)(El% z(RB{{BF7-rvuMaRpza(=E;Jq#`e9nSDB#^qWb$%+$_G9jW=oy}GMFt{6dFNo8fcPS z*$;XZ3`h^Rh28S@0^s4RVZMn^KK}JpBBTUSF#9g@T#OjQE@&`Zg+Vql-6t3`&&bC-UcRip=K}j zgbrAMjk}akQEiprG^mKqVGvqxX`=inGKiOxc?q7oMal*>4dVHLBxKZh9nbv!{em}~ zVA86Ex2`Uc&E2YLX<{gHs`Px zIpqaDx-Z19!$<10tAZ%{j>=6w`Ce+iS9uYA#b7M=x}BQ}V*`Y4%Z$z~LWe=gqO7e8 zR4_&AW3n-t#b-^pOrkAab$q8Q-_#PkS4izdrru@NY;t0XQb%}3f2fFoPmx3AdH!Ca zR}Ac=_axn1FB|%6b8^wb-Rk)by?+Jo^v^_2?@x?A;v;m}Kaf1eyqT%jL2=5`^<7c{ zWGAiL(Am0NmogoYb0c%NDX&ADxwPaJD;H!JvP7-Qxz{67VXpt0ycEdMpf2S({cMKR zq;T@?+d|p2E)XlwoZZ5|62=+{zp^^6>={-Y2l@US(a;N9l?Ji9@|4{C>e4=##_oPk z4}D7L9E5c@3-oE}pBgd_+Aw`3%YRZc?f)>jvu)T%`>$bopUiN(AL+JCdm5Ukl#Gnd zSJk0rtQ|SlpE#eBbMIRIs}+XPD+#=&RE2LN5pyfittH2F&yOJ_(d)H}*r8MN!_kNQ zd@`D2()=+T3!hR>%J7?#>D#=V1RGAeg@bKFB3+Wu{1D;r(qFaSNmVt$OG|WdIk?Io zQ3GZ7Cq)Rq>^IRmOM*%+-sXsy+%GUm${LQ5obJOOz#YZps9a-5ktMy`Gp*${4hzRV zGKzFn&0VgnvurlkJw~bWo5eQPh#yYimc|(b(f@ql1JDIBjB>ntltVeF=kjkhzOKcl z_3l8h7rZBQQwUe}?T^A;lJeOx-|Hb)s)yR-ecwd2i@tW_u5m&SHo9=sfw-it5d%IEO*R3y(Cg`Y}Y;l!IQx61DF>gpXjYY{Z%jaSd zIbTY}R!a~?a*434f|H$<>#}g*C)7z_T2`7^&_b0gMfOE+`UTHpt(7~cAfx9#I zSJ$RtdGZx~Rra>mxw>rYj<)YM{RkexT%9>rx;;CKBXif!z#+8G1P$VcWw&jjuQ(XR z5Tio2O?uj$vJJ94+nck^%ewj`iY&hE@;G-t759a%6T?dZ|2fKlIO|D3+nJDb4GX^gC92Jy;AStOSUliSt-x@SRn1VU( zOp}~bMKbsq`!CEf-oKM--!owRbc;8dNQfr`)8&pB3 zz-@Tm$bR~Up1U?K(OeE9?G=31)=chDYYrZEOPmt0RFAt>s*jp2e-j;TJnr2zVCzG~ z@JC9J>1TWBD8)$F+n+>;j)X^pZFfxIN*(-u)WJ)^;pn1Z-c-^GJykIu`<@`7uNM0h zx61~t#OWgq1Vi#l=np6==&5~*=8%x1FI=NHg=N~Rjff1_k+BrDrd;s-n@Y=;ipjsx zni^CX&geBrAgav-(jL`$^_}gslLpFphzmQZS9_!`2V#nA%n_D>vtdSeK0B*9FIJ_P zHGPjwuR&s4B&<4|-Sn`SA|oJlk!Uijeh1Evk1O`(MoIO#wTe!KfM!rs;Ms-j}Pg$80;f8Wu z-XT>17wlU9jjS}7;|yfrBHQ2gMT3!==+<63L0>(VYIJt)bYy};o{+DRh_!e`gOrH5m@04U%X?FXcTz2dep>eIjg2mW zuU{P{O0f5ILp{wdv91m`5o1X$H{cESDH|hpgO0D=c=Ny>Sl+Q!T(LAR8sc0_M0Fz` zjh$^YBz#4iDb5#xv?y}?1E0z|%~K|(Ae6&PEEB^hliYpneVx&z*BX@ZYm)oaJ7|9l zJTkaOdqbR_v0QvF_h;BSHcIH&+oTMG$`L<-X`o|}1W?h{2P%%%4bB-mE%-59A7zap zc0EG`WCM{}fTh!U11`ulLqb}y?HK;wnG-I8(wkbs#-W>CP;QJ8o*VzqX1h2BxO#$i zWgG#Ck;#;&u6GR13#%?siAmB*Fce=moM{;3t>pgKKqz?v`HLn#V$_Y_b4!gs4mM36T1OZY zQ^%GUAtA2TJYk$&S$23fsrI|1R?ARkO658;k}6EgFu|{thOaxkUC3*q^oey+rvH)( zm}tpf}onsvRlL=481r11<{*d=yfl!m+SU1^vbHM!Vqz3RLg*R`R> zB2PJaM7>Ke;s%ez1ioDv)fo{y1;veM4Ia>RqQ$IDG6l0?X_ za9(|UT=^%wTaD$aWSEGiSA$cW1LaJzs_u&$viGH z#Biwov8_(-oHfd}+?y1J2*x-X;B99u_W2FgH!VnCs3sdvJ&!8c)h`ClJLu7I!%C~F z&;66+Fq+yHR%8q`-tGvlO?XnnCkz$|P210<-eXnWR$KvLn!`pvOC3)VN=81^rN4!P z<1Y`GUv(I+xQk|ex)#A}`v-g|%Fp>(=ay00#i}LeT_pr+KTSXP|L9Mx!$4rLLggPmp`JA>L z6p}i&H=ud1tSkT3IR|!ZRqSi#c3yb)A`wB2e!f|M8X4cXVgKilPn9pNoe`z%$Rm{{ z9Dc3`m@fNx#3xSZB{waP%b0rEIEc~3-*@lOdcFXF#eGd`$fF%!r-c+tv8QZ#JJ5GgvoKqb@Ufm+=}99{>Wpk*#o~PoOvjpAiTzQ0ZS0X#^(1^$xf3!-!8HskYJbV zM-@5ld)DK;+PR)-JzXAvO5gK)9#@@0AQZ2xtX11+m517-HAmxC%hiBdjyX;ok~8G| zQ&zG0G%5OyxcmZ7>FqnYGh#S1gr(mJ2t|4?4-#>%VdC8mS!-)+WvQnHaCSHPguz(b zCKl)0l;;?>1C4HuJV##soo0(~NP)y7XrD%bjgdOgn^nzfpjUOjUzm?`X5)~Y0@*OU zAHr7G?aT;OTkKA~d#JeItUqNGk!@h0h}=v3IhOgBDQWQ6G7MlpjJnV+xEeP+s`GCH z)%#rO25%vj0X^h$!V{WUu4|==tu9q+F3!idz`x#8vU!FulL0|8zy;ST)n#>pq>1*s zQs&z7bS3p#D5`!XoY*CQo*^l+{hofgzXVb$i=>MlpLy?EYiGj1_FyK%X*71gwX^Y* z$&SyBn*Iuh&b#59UJu&D$!pSrsM!2Ytj-w@y$Y3KYw1D zW$WVwSzsh>rjLbmoLlvi=;!Ka6Mu4n)v`oS5vOXcxV${@P#P(Zu;Pk6gboM2wWmbS znA1Y&HMrX0?$KHLW@iA};rjQD@af~3Dv4<1zbSgH@c~zyVKzIIKSn1ia>Zk?Tdq2d zvGBP)N?T!5dtjZG=qp?euI^QMm+>00kGI$u&^0`%m5<2{@Tp@TxqL$UR^Hq`2;~4> z?9ERODlmmAgWpLwK|3zf&1+9nM5>utwfMk_d~OjJA6GM*Iy0h>8j@cNPnbfu#gP)Jm^&j1UmLB1C8C%EEA0mP>@G>deA~*hGJ@yU< z(WI63gF&zXzO@I!&W^lgZU_c{7u%yl!4+5LZvy5k(lQnLN*qa5& zg#8hV2f7uC#UYI?9ru^Q!)DQnPhZL>{(`i}C6@UzfwzE!v>wFb*A1^f*I*3})q<-B zE-tWK^JneYyLzJ3nAD+ys&mH(8Gp8=Hs~dz0p_#dUV=|^Qc{NOxs6ZioWlph6D;?c zoY)j^Usw-=oM$A%yN7;o?V{*|N)=mw4ayF6C#*xp)Re(DW*-P) z5!1+9B0_nl!1DJQc~RQF3E%92YZ!x_o>{2s!VF9-TCb#8#^J;XJpatKfs;kI1rZP= z^fZ^3_y<1sP|Qx|Cen^)vKne@f`__uwyILi13vQe zq$w!Y9%aBN%qub4K9v>e^bI|TV;FIJ3zh6bpi`r~gD_fU^c7dGrY3c&r`JCCzE6VqO_DJIxbok-?UrXqijf3vQx85E_`TzMDo8+;gJTC zv6wQ|Qz)ixMLH9H8f)1xtg-eq+P0t?_006&t3AkHy1ZShwhRv-5_9$!(td-y!kEt* z{|1DBMm&DMozTWrGHbfU8f6;ft2%DlKbehYw!rbw)ga>LQ%I1_b$kG@tE6U0Sx^u7 zJ`Xn_ak*9FoCBGt)#3BYBOo2TdfppydRF0dNAJ!_TP6n`8KT{l!l$QWc40m0u`hYt zzs?LsFcfB5rvLi6N9*otqx=jn@(hQ+w8v4;Vqx99o3PNh$L-k!*jE*y?>$sZ|er=qsJ(zwub--2$Qj~mdfM@{GWBBq*X0I|}4RG6)Nwj0jR zJOJ@2Gpl25Rh!IHUD!F7J3$$$R|}hYM$1-t39P@jG=bvI6y^87AhH z&J1G|ie6>gbq}0pQMIzYfmo$wg|GUMDM;{D3^E#7tqq8WD3P*&7CEpaUcR54SbqO2 z&ym`^B%?=eGKe*g=aifGMC>);f+bV+Ak;)XRvztb13RnQF^QiklgxzQz|C193JY$b z3L;gv4lj;p4uyA+$ldKC$;t(KSY0kP80sONiA17rS-1667Hd!NF$bdV<Gaobdx$ETPum>Q>{})gH-{C%GV)E98-aX%iEP{T2gxYDelNPMy$jC-uGV)6IPvFC!PO$Kq=h> zT5VqKwQ%qpY&5PiZuQgT35`FQ-a%Zp&mJ1eE4FqPOMRn!xT+hE0i``mAf_moX0@!# zyLS_uc-uM6$Q5B9JQ>Ps>f6x`3ul-lSn2v`*h26`hnh#_{XJUmGis4p!4J-R$FOO? z(aS}xTAPk;d49%E9$}2O6uzDJ|0s{AFU{5*Z}+^bXu^w&yuL^1>yO-_{Sh8 zi5`H29yWr>nA<-fS%WX2zQT*iTbUg7u?*UGv(TQSb7pJqRqBx3rm=&>H>ALYz9#Xv z`gRLJN6gR2i&d-ov$_e<%yBE(?`rdvk!HED& zP5D#tCeg;Den>6>$m?gM)~V?kPO;*{wcit+laJ?L*0YJ)h+5bEXmF(>YQ$QN&n0la zG$g$gXwr@2u2;v!84&5W{NCi2NXvC~tQg-e#FEEcWfQ0+QYY3(xii=mu%(4*Suxo#GZ4gV0;#$?prfxWAV6?>Q>Fb-tUTI z7CP2R%P^sf!KsV z(2LprM?)-5xB?kuyDkqRr+3wnfwv@;%@MxSGmgxNS6G(Hku71=_eURU=9EjTcjE3u|BJ3`~h=-}lpjkAT5c zO^BbUa^dh{1V5c6bI^ecs~DjtCakJL%+Hisy@nACyrz{QUR(XH_sy~o74epI>bSpX zN|5p~?61iyo12qI=6&?mHsVm0dnI4}lHWqw<44UyIvjHH+&L!3xkImFsLhQoc2jOr z13=d`+!h7T504z@2QVE|S19$!?lyP)IC~)mb+o;aJ1tsVxJp0$S;y_tb^W~j?NG%& zC@jg@r-*|VZFn_WumvaM*Z|{cOgrkXF_CEp0UZkIrqrV6cDV*dG8iNi*0syA_WCI^ zVF4IjR;O{UL!bQmI#ew9hAN`Ydb1{qedGekb@sUzDL>#-(G_3+Una=>Ymj6hu>Tdl z@$mfrTrU5g{geOA1lc+MU-b9O1X+Gfi~kP@{BKN<`PVe}U-zS9oIzCr=JTArjk{j9U%r2=eReXM zeVwKo4=ztG&GF&XfQ@}c$%BDKV1J=t5Qx7LfT=Dq0s;UC6f{79&>#*DnF0#TJviAh zLl6OPK1AE19|r|7p#ch*GGHNtZ^thZoPY)cfCLsWQX+7mBtRel0g?K?3Kx(9RQb29 zK<-}yAOH;*=8ohr-vt(J2Z|=hK`3G$guG2+ z5P-h~dz+H+PXjjChkE*q!6wd96-~#Y*gZON1 zoVEw&`+h=g)af3C6mJ>(P^$F%)eQF z(@*g#vQ13D_)lHh&10ET9BkozCfg8+hn z96%wEfCi_afLVwV`?#!H{1@P7YL8pbXz$@-jf?xRPbM~R0{x@}v{QdQgiC}bLS zz-*RP5k;2BvDvb~^;Su-V5`{>edtzIyjR9V21o4+>d@TJ5G~N&5lZ1cg3!cc z!%_!jgLuY~bKzWe+_F#8dq(e62bvujZ4;p%8T`5|vs_Lu6k~P5CK*?6YMErP(ldqBOs?fv|Ha(2t}XMIB(1 zaT8^8JG%PlQjk;$KN0$y<}RyPR@_aN&p&rT51I~dJFWjwq!(Y9N!VKd^GF`ixf!AR zJ{U!RBJXC!Pt^{Z)Sqx0XYP3Qzb^048k(GzC}!^dCtUb$-;^fIQf_xA`>Pml`v)vO z3c|Ck&SeZhiwY3%LVCMi|AFBq;so@P3zDpMbH+*^yPf0zrmz~U8y0b<%kAx6->NQf zLsey!i#V2@S+oAGe(epEn(s_nHDc7QS zn_ORJaKP!uiVbSa?ru?DRXw`Fo3GDySETG47iiKp&!DJp77O+wLDuL-GmT+BOHQzRTcmFDMyKj|M>q$+IzRHz zaF^gZ3+k$dc{@LSI+$a_7^m1ecbU^R2ksOEYfZE0sESf1Lerh_c>xX9RMss0ihZ_~ ztD#E4p-ipABOrHW+~jdBU=1w_7Bq7&e~xeEdZ_)*e6ygdAlgjh11w{=M0jJ+DE@7g z%s+RA%E&$`yN&iZQ+OJ_xRDHhF*Wer1%;SQeonh($e1BCa3s<^X%}vnY+Eaiotcb# zR$T1)$i4F)tsx9uo;F&~?zwKu{0JA zP3DctU77_YZ0Tp!_a0c3O=);6uw;|LDw-TENKQxNVm&_36Ns6^o&rbg!d-m6GQxYp z*(+5$w(8A%wl}uij?fo%tz+w9{(+Vx0_#>QZ`nxiX7+&G0Mvtam>(>YU-@H?+Qey;&^rTY>u*Cf`t(o3kP^Grvv!*@>Pzj+|mYIpjG*imf_M zso(W^=rr=;#L+WWBCmX}MeG%ul+)~J>)H3O>3i8+|2`gn{lN(B!UF&qYeT^wF5I@Vy8w7|#-HQSje8oG zpCqC&d*=pT9ZBjGMfcfrb=oXmn-1-rO)eCx z$q^#yGbpJoGh7aTW%|48?6p!`BNAL%u{=vx z5z4u7&B!z;Cc=E`hHTNXfi~}R&8z>i+1(P$rrm{ ziUw*8PUI|kNiia>m$swVW+Y=n^q@Vr)rJO5IaXe0%LP{0paFsUD45wEn66>Jdn1-x}m4QRMs&rz4J{X;C4~ zY+zExlc}|y-}8_RQ#8HD-*=hlZ>^$Gfk_spO(ic=KdJVzmaAfbtnHnQ_SGQC%HF4` zQKRN5G6wr(aTTl6x?vlOZ)~$GFmDRe^Vs{u5v9f;g2+e94Pu^%&vV}Vp>0sb6RVTlv7nrM;l3J3EX2O zv!=uR(KI@T%p^RwR1}4vZ11~(Sf+)`LSC=HPecLHmiW!+;qIHE2HuJ1Q^e7^2Ov{~BOFO`Z7S-A!ek^%JqNc7 zAbfpKs0mURqYX~QrH1dd7!xa~VVlmi4wR?!19~rg;kI;CNki7Z!rTNOnvnDX!t~qO zN0cp%!klNkJqAD96@+j`BEoM%vGj8Ax5Xz18wb3PD8~e>J2Tvc*z{-sbn12ycS}8H zzWf!X_VA_+YnxAgA}{;RoiBpanq` zBmu0i3iMViY9F+&)8Wp(6RmS58fEL4?0jP;S=)w_)HY{B^dWNU_UqHF^+{6px-^^C z(Ftds$sgYBNlaNtF$Zh+Qc5LSya6(rOMLy8);SkO%J$&k&4%~>T7><1<;Iq$t{M#7 z@0Q3L@pXR=>H`jg50}5(<;N&&=su2=%o=D9o8HR*Za4N<hjRSYH+j9e4gs=5s>S)qYQeTY0Ord9Q7tDbd;)Z1Z`$$R~FK2$QEHo(iHh zh<{{meyo^~@K8>XphjorjU`P?N2_`SC9hhoo1xMCgJH|C2lo34ajKgeK9^mIU&~*1A*xLREhnd`WQN_bxQ&g^(V5zxWIW!VcB*B$-1tbgifX4*?rx*GJ-kzaX0kK zi;=#Sa8D)$XJrFv#J7pd%=EefB^t4-BsL?}^eHoYFB6^xt53As%?h}!__1g`7p|C8 zi;S3*!D^W7j+-kda!R^VazRJ!gai7rt67<=F$6^}%il!x9Y{JZbZ-TO`c=;42`m=- z9~*P!kcBM9BJge|I}62;*xLGA&+IPvVoim036xD{G6vJJwps?rQaZts&4!O2&|Fws zViN1+UJWtI^S!%^_&#ML{n3N9sfE>b(aAOiQdR!(f-|Z3*j962?l#?`Y82L9aZa-%x% zXRJD?&Q2@HOK2l(y}^SZ_f0c0(?P~8N>b=ID=~kg+=nv3d`>Sl?0@uvGnw22UCE>+)}usI*1Y?WSV&vM}n zgAmiCnUtjuqKmDtwxZ>(IIxuz5+mopdvt5GV!0VUx7I;^e&#o<=k~#;?nYGQ{DY9y zR-}57?bXP%X!cCU_<;hL;T=SaR)FD&Aa+_I!;9H?G zWH6F8TFVg3>6%RUA_&BXRC)Zgh4~R7*k<}K2-9m%U=`NBgz3YRPF7>u^wtRU!fHwM zIu0?YB~BY~=KfZ7LjQUkt}W=dwI)Qa%l?GFziPgGSw!ENo0X6v<^DF+Kn$;R443PL z$PLcv+4KSfn!PyioGwMFZPDM+SoaK|ae{V!)_6QO-WUVxRI(L8$e;EtXrsSvX@fhmN6*+JB zoL$dO+43|q@J+XFHiCTN@OMZNL)}+>{p`7U{n@9zBeg8sldDhi3FUN&lT(Vp?(d-$ zV~@RMoV(&-EtCQ!&-%5FDBUP-uGWmUEhVHEPO~<3=ywzj#3TyryS9XyrlF#cE9P*V>9q317oV5MD z*B3)&F?LVA8&Ai;{nsDXcI6su{7s}KkCv`A2ol0+z4M=f%=Krkvk^ zH04tsu=Nx>1DcJQ2M@kfw@WE8@mm@8sznaLh6!l1Z_y|lF)w7VnD4MD9lE}RFnfc| z-Uxbeq||$gAJRyMAKYxfx4TxJ8n=Hiv>4g|V%{N~deRTVJM|y1qzuIK_U_!S{F8&< zh_#4$Dc#dz{f!q#;DU;G^ma&!;Co~CZ^|+4^ULUGVD$u_(&*^dZ{4D~`Q{SJ;dMXb z;M#n31n{gXievjs>A~%U@5wuN|FoTp)nQXj|J{))!s~1KdMBNb6XXPPBV+vF?T!{0 zL*aYgOsQD-Gn+rbp6Yu$o>Z!*YQ-sB&UEz`&D__i`IJ3~efpYp`_zH611+Hyp~2FN zN~tJeIX9KhA>M3*>ogx&P{pi^WsA>S#8W5jFAD`->(GMgpR@`478o3tcNJ(&_5|P{Q5Z$N^;!|3R|Apj+NrO8|cd^ zeXcEDTFk@y?Aj%?=@XEc?65qIdID zNFP6B%ZyrG{}27?3GGl&xHdU~k+(^g?Dzi?Hp#SeD!bnCuK*JwaX88l+j5Z)>({q! zk*MsXeDyl%nZ0+v>dJx{76BM0!j)V`dYg$TFw}9tm>#-Pw%TlXaRp@AzE*#)N@z>R5Q=)W>#vd5?Ykj^@g&Rc#~q zACtU;2;x+0)v^=#Qjz`LnFE@GqEM7^74;*GHY+@f*hepXL(^!cge|p9#npVxg>Di8 zhIZ35AhpT%ElV3+M%+OdTLi~SdHG@+*(8Ka4|98;v2`^2;0zAn3uMP3aYRq8dZiR^ zS@c);XWC#Q$uoRf2AZy|p(+tfiU(O{%Dp ziNZ0T3$ zvsbs;B2$*bdkGYgF9r>Y&!M6Z7Omj-Ykw2N!DLve%}fZ>F>>=r*c1~wznOpGBZ6$G=b_P;3|mt_}Mf4-dTcPk3>5R-IJFtyP_>C zLr{pX56&<>#J7oKhoA~quuDR$@H;L)NF7gr??^S z%-g7M>VfyYZ+Eh6ZWTrbN$JH`mCovkq&H~4piQBOIV}_Di%_#!l5bX_#lpZ4ANTk+XOE`6R)X`yUcm9!6W5;H?8SQct zpLz9os}?yZ;9vfA-PgBZ>%#2`{F_1-vFsa1Ka7rrj#^)>23aS$vX7|bHrDULHOFL^$0)^Wx2$qYFmgU=+4^ zm$D4>mW=zt<;+=|3NQN>@W7dDfhETl!(vR{f-w;?YN?m&APq8jE^aJkXQ486_yRSA zrTz8!fV!Kch>HEhnsf_tjt*~DBGk%r+lo7Aq+1JSnVg*yC%GugEXWy%qI(%oKM;t2 z-N|Zkza|U`)@I{YYtDo>lc zjiBR}p3&fW^}mb!hoB2}%#|)Fduxw{6{|)ZDBeX{ZHSjVmNHUYeH&s~;F|`J1h@G2BWFAu@e4;l zW2lTe*&{l!h_F4Sz!R}C4*1M%<~x;5cDe|;LDNx>Wg0;bSa_vBU{a|{oDh?TmFG5d z3`J4mj=M_;i^WOM)P1rz%5o{QbbHrI2yal2AIYOuB5u(p)f5z?{$! zHl6eyNM+nf3>OoE7{_!|qH%LKKN46cSGo60f4PEG48F$(?fUeC?CtmFtmX|9$iE zz5VqvZr|FZMm%evK8s=IxWpjQ#3sc8^@;lUk06<|>E zyn_&G6W@<|9!;^yNiYfW{D1)f25!L8#Ms$9X8{l;X6*ysZ)5u}d>?iW010Uoo>>r1 zXdA%{ay34aTOIrL4g{rK3P4QSy7jz^Ti_OC4I#N7L;|IT`;>B0qL=}|It?m7r;nZx z#bv8qCxs2_=-?oz$lWoXVZ$~qk!ly%VGEFH6mV^u05;7UlcCf-Fshmm@!mg%dr*@> zW5BrvJ_Hs>2o$&=P$qUZWTYs-Mj#EhZrdD8qfX!$Xw?QV4~hm3{2u`$e?P6~3}|55 z!!!yN>a&Sr8c_Hd*eoF!ga$??VY_z?m4M;=u|EnJING~%7bQZ_J{8DhsvKZ6q#A(e z>YkAw4i&bM1E&PsVA=&DE4mnm8BvlMgqLTa3>`S5dM@H1Sb2Xtv_jOxlR-b9Oz#a6 zuF?FdlkKcK&0kvN`~85AXf#G4)cw+F*h3(97P!LV2v7lffJ5aiMJGrb5Sl;R;pxiI zUJ$p&eKh`bHo!3cr+K&Vdn5VoK>(>!z`&p1cCV^J1`GhO1&)B~v#>@)zGCPVg71Me zoBY`Oz;YIZUkm`A*DnVy5~B=QlO_pNqHd0--;1-bhfW5=@MFLSSpHpu5NpQfO=;Nr?t#%Z@D5r=Ay$qV8+`uZ2+(E+(XDl5NHS@c)%t<$OiCqI5dz& zf;=;RS}zWi{n!KyTNwPq;11D*d=ibpZ7MII8Iu=+gdcuSq)g=uw%0Os?y&y-X38KC zP4Ungd;Omb{aytDpB`916eP&UP`UtUao7N}hHOT5q(V6bqfQl|kl=Y$C&l`S3LZ8s zw`#{P6ji&OJbq~equ}M?v84>E!-H2l2<#p&nxNR{ zaedbf8xcwaD2~lG0JJT9J*~dx0=P5dM&%R7ZFCH!>)M$ ze6$oo$4WXS;n9(;yhUHxs;!ruv);EnZTd%C*X(!Et8a!4p+s&Is?%CWN1`OnEe=*| zp()96sOOmfiJ9G0s<$UUS=b(a`PHrfCq=yA8Qj%c=jf{GLb;IJ;o;~^aWS~s{h3+& zmV#Xarjr$D{LGXpn0&Mx+O2PhKZvZ!0<-2#g4YXa{ix(}uU4KK>Gss&W->Dgq>shl z?0t`XQ*+`y%HI% z`*u8Ts|p7@#5QA#zM15jCkZTjWVnLppo6Hzp`E#=tG+7h!S8&^2y_?-ibklJPuGhQ zSTLvO-{=hgvnT6Dmer_)K^wL!rM_`MQe7W~6>~G+bRl_*moJ8u< zP#z&l{Cc(-V04E)DllSuU}!(`MZdO)4YuTL>b)6x({8ytf|GSWCnm>znnj9lqvPSm zb;>9>jW|v7V@uxS5z$s-C)5{wHs-Wl{^_?BIqcCsfPQy$4apqV0i|Sj8<_m(#XHt7fT-Pc^l;_$}6ZbZv$_B@-d4@fTyJL+spN}$ky%h>IWr3T!9?u}* zMoKMo`GOD9M}N*~$?oZa0#QXQI6`Kz&F-YHkG0aWRQ5ppLGQ(mvYG&RHJi-?s=E09%fwgVp2=Sw2)e`gV7e{o6cVcU`$~os{ z{m~)VCJJxM$NT3=eGIm(dYy0Y@@ZftADf?PcgBFLYwRNV1Y7$qxWyg(vhp&CUa)Wwn^uu%up!(onNvzF%B9!6j`v=+ zEV%3WW*Og5Cb*UM9Q&`9@sJ-7Z*{3!u(0d^f88I`sN5F z`)RIh11a%erzc%9l+th*YQwIN%te3U1OotlxIvp_GM`Wf=Bd_)V+lvP{2WQMbzn;jr z7owI8R>Zo-N--BLz^*oHqVM)wIfJWT6NTGq9t{?QE4YaJWxJGL&VrJn$C@ubF^9&* zZ>**5W11);uWoccjN%HaRTe7uOgE9<;UpS~-FP-FWxO7f*Hym5Pk`U|+~7#A8sU7$ z{bTL2envnf2ReUBWh)P zfa#|3r7jjwh6=odkSkQ_?%d$lHv9?met-9AbPmF_*^?!93J$)Xj>loglCbK)c$sRK zTh6WTd4C&vRt%Lq8*)YtN%8_aM3ihMZY~~H&9_9y6^0&TS4`KW;g0>ip`TW_xWu;= zJu3^xi?Zf$^4N+euJ;MTI~L*8E_@ztaF?A=u-!=^7OK;o{z7Gx0~?eJs3PFJozCAR z{7#0qDmeQsscWv;3=mdYX-b|{cs~@sYk`p#X286G%Q_5mRvg?N>UbAs3a#DNXH=v^ zZ!UNGd04R=o4x5>Uz?d7&RtHFDkaYRsuilLk~f`^b6&1_D0;qjw{f$x`RPH^Pg8|>n? zmda~;wffg5R(;E7N+|6jj}hRiD0X-La>AEjg>>6Bxk@{^@!uJCr-ixIYV%tTnY@MY zBe$fKzmmBe|MifO?oinz(z;Dt9+HHmW^_B%4c9ewC}i~QG~TjraeQp!pZ0MPtEy_Y`9f#PLxIwy% ziua29=#^@csx+D)YAi`GmsUh1TE`C?EJg_hT0Z5V#8q_?3DB7LZN$!4Z62yrExFZ_ zkCrM(l$yM`fed{0?pN*xc2-YfWhQpj3qvKt+9i3_p6byxdikB1qnX;eplDS#{NBMD zB(GUEnm&B;3O0XHz>NIv{I!L=7hEPhzPpRxTHVWwL073h4|~xJ`{NwfM=F_{3<2|W zRZVz9;Uu^7Tw}LBWXCC;L%#k!))nL3OM7Q{`nH_y5k8Ft^l)&?L|@g;yCL4`pg@n{AJ2m`jO@6PcLUHtKMhLff`L z%WrRK$mX(5^51_M3u+4+KDh0SZ9C1fj{!;5;01Os^fCbhN zPS9nf1a1&77k~lt$PU2hPrwxr=}!WX4~UQ~VV0-{CGZq*>aT#1CMV2GQ3ea@RKkb= zmH^iW;cw>B((tWCjwB7l&!oAdi9KdEB|@3G%bt3kW7@K&{ZSQqOM@ zfDk4gr;M_yIObSH5(XfMpn}276x60XfJFfMLsj0Wzjp&J=y3_K{Idn2!U7irDMkto zSmO6-X7sRvjX+d>0jg8Iaf`hH^SvRny&=;-ag#TYZ)~2)KW9w6BlTv9V_uLbf7f?* zKmmL(fGkYFc5m@}K%hk6J}S3A`f88b{RL&10=~P~&u#5so z%pnNDfCE67xYAU+v6DgO#}H6OAa$~F^YW{0U$duJF^EDH)XA!&v{?gG=3j90vZ|Kj z>g!vZ8XQ$VT1WmY4PhQ(I=}|aRrp>EB#6BWYXH{O<<-8UgBAOlVXu4f}m~Cwcb-t;v$kOHfzlSBC*ZICBxoU`&Ncc?txh zb*zxYH#=hY0f;3@3C|(`m=P&bvy*l??r{JE7=tDv_D6cE2GIeB3WNsrS~k^{A*TyK z5`0OP7DF4H_BHXNbXZ^n$rynAYX;RQ}-jMGgXD1poU)izo;SdaPCWS;k3_ zEG^XTdB@3j{-UeZBZX)XDEOlfA7kNtY2bOxS!CjL-R(+U8_Grd?KQF&=(sY0&Z%zM zeEHaBIAHXnUyHj^+LgbnqcBD&x!z1Bvs`a7(|}V&`N(^XFo{8s6?~7L=T?(y;}vRra>KiN^_6}Fboigg-)OL48r9SWlclsc-nFlF9+!~=1P%Yq0 znV4miPP|SnA&1bSshe}R55-yPZ(Gvcii6jc?JYuSB&aP37AOtmm}aFZUwndxYI9fO zHk7>`D(WRvj*I{Lxq)24K)-x?I*sOFWK(> zo0oD2x7EciZPY@W-Zv;YG_tlypFwDKymzJ&VOR)$PmqFck=!Su}`RRy=~IHXU&(NE3}M@c_uO zKzELr5mC5#A+D$uOTOE2|ER8nU*7YD_7+pRGfcR~9M;;AiHfN4O?B9$m1YSYJ4CG1 zR>qY*vXiISYkFLzFScmCkvc^t13*{wGf+o5|3pQwX1u9zM4Lb`-rkFUsNtHq#5 zj3&)``YgNMcl3-09j$%yxv%Z@*o9d;4*45bt=qBnG-qOIj4(k+QS8cE6&XA1zP+!+ zHjY+)wngO(Kg01jV%D~O-i5)WMz1Af`84Mtm_3izR}4o%x-f@~|I!(yKpIj^lU3qW zqK%*VvbQ#G+pEDH!xi_AkTs01sgGepQsy=sWji7e`|L3wm`~(NyT5UIWm@O<%F6^@ z)IAl^o#D5xCo47I*fz$`p;=S0 zw2jhHewu0S#`xn3FCS^;3#2;aUJ6>!LCq@_2o7A1713CBm^+0vJHwjvPh_4?M&}qP z5=F}^dbN#&XEB=X`p2Odw@zNB>a2`*7>$NgFrGRJ6?ZC2N2Ummtjx{`)*h4$6@|lF zkLRg-JN_+toy0&*l_YgO6>`Oeb`E+8;SJHw8&b10udSTMgdzAHdZvQy^*kQ!?HD)w3d(d9 z!eqnuj4$xBl_42Fq|qBzulF&YN&+NwN|2q7_H6p#`~)-lKd!%fG>$b{RV0lIOf-h{ z$Ep%~R~v3T4ux57jrCuxqTAKlc32!GpR>GVH$lXmtAf4vxmwmq#a34QJV%SVaW&j8 z&Ie|)%X@;3SEJVPQ80C^k5+7r_^1h-%g*g4z9_3SL$)b`fO@V69eEmkT6pAKQ(OX+o;L*ZvG zAL2|Wu9?m+?RA*;x;5OZ@J?}XjW%2>i#6d#y(QZ&cN4tHw%FUXO7vT#^XetK%#?+* z?bhKon{gEvwgg-cW2pkZt7S*59z>?-96oxT5s!>Ql#t`gIN&eL+3(be=rQmtUhKBo zCnInV0$6nh#Vy{9IL<;PyR^aaE7PCg6Ufzn?eL3c+jI-O-5wOkCm`y7TUc-QliSPl zWBbT`8(!NRoH%sICZ5p`+Cj7?WX6Y4M)Y95ws7VHV&n7gt zXK+_|x%54RuL0eiCn>!)I~7@pM4ze93!*#KQ4frcWlnv(T6n9l&ZHNWXxv{9j4H>c zY;ABuzthOk0;oSoWFDjdf-dhk9$Ko#Pu$khw)a?HYiw!|N@l%6H5eu8PpS zy{@jauy1+JU_H)KB}j^mV13#or4@C0o0S7(;7wi8{~Ps=XVF>Y6xt%<1&6 zu`jAjn*>FEe84;MKHSigKonuXrWrI&*TsM(y9Ou`VkchX^*!>fn$q*@4OnGo++4lW zXkWRNGn-m247aLrHX(=;N_-)vj+i6I#jA(zI+kkpWMK_?Bt0k$Jk!9zu{3fav0uZ<$Si96E!s*ucUov_*7QZ$ddj((PJ_AOx%AGn8dm#L z9u3dd_OiSOm-1~vUx33>;=RG_SM$EvXF#9qvme8Z9V%Dh*_I5YoAe%c`_+yd6q>djpq-_+ zK#Pw{GdrBSaGd(zq3Lf9Kg*oyM7^C4^aF!G$&$lxX2(U#<1p`hI+|zs6dg8wk^c!G zmX2s!SoEU1V=7dcsvcblRU`Ox*Ymy-0P3r?`{{#8!ivk&XeFA_m~z?VDqWRXYETa| z0>9|iZj-GoxiQoA&1)ogSS;Z7wV;P4D3-!L`h(!cPYnwe*H$L6=W zcHFPYed9bx>a5qHz0Ce7k2;iZr(@OV`tb_g4nP-AbftgzAZ3$Cqgtb_@i=Pnk+-Wl zzO7#A4CVC!gIRw1gmzTLl>bjD?0?tN{%6fLHs=4!UYH12m^pt%-~Xre_FtQAtV|4? z|2>7Nm}@9sHGtBnoGGc8EN}w z3UWnKC?%6UfpzV?O&{>~PJj85%;ab?TbpgO-cbJoW=)+HGO!Eu#9$E=(n2bL(a@`3 zb_mViBbc6$=*JKtphq^K@CO-NfPgsN6~F+D5WMJz$YU~qB?8bzfEyhJn3s~0Vgd4p z1G@+j=Hf&KFhq(APfL5<$r(V{Em_frphS*y76J||f_Fm*>FWrz0E*b}m16-H^xuU6 zij_ctI876>rOP}8?tdps@#hN%b0{Lr8_c92!C?^U7i7Uh0mNbC0C@UURb#LKd2nFq zB@PzTP*e!q!oriFl!-V(5eAANp8VVoQg?3?!hbjXmshZR5*6~cr*#i?? zcPWVquZJfU3j?3-$~lE1o=cnq@f9@^8YY`!vuaKjS&-;b4SghBB~3J_k2rdXXe-vV zu!9E~+BO>vK3LG#l{Yk~*VC2TdmQ#<`G%1ebJr;$k}K>9fF${uK$J^*N^&^Hyc;%u zNlubAa%QtxOPt35%xus`z%S(WivzTs1T?8fBg?mZay=M$oLxvFK?xixGbG~nIz|Rhl(Q!T7+XixS{hRZhkP7abPY`c>0u6 zvG|X4lQ77^!ns0mwGxHW(s8~ozUrJLoAd`F2s_>)L^ziw&!lxxKa;DO+3OkEFrUZe zPZVhrYT+QhFwnxh*brM7!f)yJ6UW!H_oH3J#v~;|k{Trt<>MB)eo}}_x_w1bjSk6w zuaDG+z?(v=3X~KkngTm~uUubGdL?AVnzV)g7_=CHWn}fMwRyM4>$d%dC=vH~0851M zmh4&kNOS<(Z6+SXXq&j98A>G;fO$y zcy_!Oq#z@)oHq9~ix!zR9`+$|hN!<94-Y|B?@loU)?{=<*-^vqnV;junL!toC^*ULt4u?O-AmV z+t)QCJ`a^iNqaYDAP;7IOwsNxYbLe&VkI?7Qj0yq;-bBdV3qx|ymhcyfefqAuq#BT zH0qKSz0HQMmVuU^4x8!7{g!&d^?vS)@&?^lP7%Aa;lR$Cb?B$|YOCu+f9b~cPhDb- zzTE|sQFFlsP~{C16ExS;a;bw9-0u5}Yb{t%m`%NZD2YNV?8{hNR`TNUUDGccrN+Q| zZr<`=29{?S#0>%3SS{nh&8Iz~PT+?(?dK0YW*UCvE0}>Y4JE(0zx=3B?|YF3c=22c zRudf0)<0U~IjaY1Y>H?kMJ>M~9>i^f(<{2G9il$37H!2cJ{FLt$vk(h5q@7MZl>p$+5FkTA6AfD8oxfo^;te~#+K!iPM1!12tGoX7 zUH;J1;a1*)zRzd~;xI=X00IgSgr`b_j^)Rx6(x%mVk8<6)d^r}(BhxNLh}?|qG#c< z<5B%k*nV;L1~nAUZJA7SMP~#()JI*Bd}|WxQ4(VkX#3Joi6cJL)3j^_E0!CVe$=U9S6C)5cce@UX0KX0%&28>3`r z>r`WW>TYAdl|LfZaokFDfq^i@;UwMcB3&E!rB?s4N(l4&NVuMhGONM4OJ|(AS9K!c zFn;|3A_lVF`pmYA=TMiG2b;wRO}2JiJu}8By>_2__OSrnU5M1hP?S0Eb9NQNxlG2B z+hVx`(kWwjA3vsuF`%ImOIroV!OkK%t9&^(SCe1!Rmi;c55XFhf!fK-BS^*KxkUef zAUV{TkQf8ym0qrY_o!#^fq{zN>*y2~{PQLIpPiyGKA63&-m9%Bua54coq_|8e&yu& z9-J_>?(<9qk=Y@-fIF9duPq=xQq%T&KVAP^xdacrfWl-0_4%bv#8P?#tk5b2_B24# zg0l<~+ZY#Ee}dX*YDypik}1^Yt>>;{9pyRSHLI^%`U-FyGdv1p$vo2~ql_`L|GFcm z+mH6T;X8LGwH#_}MR-lVT!U6NUX3SSs`Sms^(H{sJBlSBquCE6=Ha+3ky$WV)x^IN zGm@7#-KbnrefoUtvlY7vu(ta}LD0su?FlT{^kRo*NM+oy1fpxyZkF08Uex*d(X=I; z3oAZiAM7=)eEeH4x_kwYotvZ;8@qI?Qpw=!ag)>x;0Fztv7yOvjIbt=hq(^VQ~#lQ zM9RcX-q)p?EtM^y!Y`2%F?ykFBwgt%N?}bgp%E9D6YffB7*SBBBsjtuCHXexO07Nr z>}V}HR!o!KA+NIz$-I5m`P1)G3TE+yqJBd+5kuom1CYO?v1?<^cuK|K_?3Em^(Tg* z2EM}c6R9|xS-D0Y+QulEq_+2y2ucsvVNKdx4*ThEb6XuC7hpL>m#gwj?rRHLW&{%b z#zv4TR}+pGxpLrZ6bwkbErMoUXTF*4I787Uvk|jrA&jQNcPdZ^?WT`jic_vfBaTn3ay15^=6N0HR&kTbk13S448I>3#8>c{ zFxz!Zf%rzn+@t7z>}i%rMKWzv(G} zPs9N87EDZAs~TIkQj_O2t}bA)7Mxm(F0$O~N=t<|sV{kBuX?>!Ujo*|>1=C=tBMUN{P`Fd6J1G+EiO!? zsvinCo*vY&a-j++E-Uutd3Y|p4zjdXt1^f7jEEazd=zj;zvt8?yoH(AoWoDkrFr#? z9CKKjm4euyF_K~^CKap`6;978mtmFNCxDEt+fF~%VfIV2sAF){2Z3vO3Hj3|?Muu) zwn&Yc3p#H0@)yaGR6n^GpbWSuhnbf+e8Uv*>=lj5HD=g;=3PYDATk<46+bY&?Ryu) zP2YnuOmS^s$IB25W#kmASmF|3_oieq_d&@isT%RLdqyn}mj$VR*g4j>tt40Q0FQ!F z9liCBH*O?pFzS6r)jhjBT?~5ZVhh;nrg_YcdC`jEWIq8KhLqHD>a6Kq@N0k;Yot}( zp$#%Xt?v2>K|myEUc1p-QA$(u5Mkg5;+Q6y7V|td6*e!zWIsNwv_x!iZrfnKoFFW~ z9_!pG9Z97yXFU1FaI475Y_oC%b~tpb+?M)s3^&dqj}ueO^;#3*2c`g&WQCZC<_0*$eP__6p|R;P6o3aNu2WZG17 zIE0cgfnO)vuR`{^DBw_wX~8#U{2k;7YPF!%A17WyM z={R9%^D|s0V-StA6`2iz^!)2Nk~%nRr2-a18_~K_Jj%R)OK;0W#p7mt{%c) zWk-A$9D5_p)S`;a*QN)Tl~=i6#*5{6ND^Ne-qdUs#|zY}6PzFU&&qa`U9?^9XUtlz z2jmwFKZoJ_yx7EUyCP6LE#K8s=z4z->ncE{F`v2XOied(k+&DM*n<;gsxw4Pv#;q zEvds!=v<}!T3=*2IPmcl%x`sPN4 z{PNgkmPoQ%Gp-$7Seg=Hp)EsNAy7hg2d?EnoZrj5nsF|yCx`$Y?& z%<9R%OOogv1uELfsPj`S|jLYVHOt=WVH=ORuy@nUi#!`giKWR4wF0`_ruy>B3#2#C_Wr?@e ztZU=tNN*wKARBWV?5^ZqvDVSnsOpN=lq=HQ=g?LEih|LQ2B>VXlFQqV&R#p9} zL11Gssd$z4)mZ_Eo>ZOkU1K9<2RdY{ArpAiuek*uS)$ME?}p>$yjmnz9?z>NfFAJO zq|`6T?|v=?BaEIkX~0~Y885Bom7n=$>xUJ>i8X>121ly`c&FPp&3je})@$MX!yqUg z<=v*pP+2QrvX*}3`f{k8nPO7W7;@77lJ^T^v?g-0MkM8VAM4R{vSRxe-7uYmMK+W~ z2ekBa#a=tjw(#p_J?snRE@aeDj|qPFsES;}M$o zxI0j!?IB-3{lcutu`IOVZN=^S6rV*^QcOe7mT)|NM<@Rj(#(GR$Ej0fa4m=%E4UD% za>-?|7t@={UAA`YhlQXv?3m5^VbJ{PsGR{#h*|q}L)lJ{W|6(ChYlu*KYS zg?|7W-#yIOCDkU4E~grxL~iOyKl`0ChB97gHkXnjrquR!TCdO{$^Ck(Almh9$AcL& zEu*^d_x;QBR^n@kh&XN>tp+I?xOO!omew6*Hy-<|D1dlmf24O=@QT%9Xf+2 zQ8St4T1@Y?4Zh|}2o0>KPioZ|F9k)U+W4Mkj2_)QZu6x3Kkv!4zm?`D7d$0@nFV#s z8KjU(raa9Ec?yt_5dSsy@2lZQT0uki>i&uKFWtp(&Y)O)*EF`^JQf7w0qH z8QsE_mr?w0{}@~|YPJMZjv@;vsWC?~fsOL2k_`cp8=TR3ENr07cdKm{Ywm^sOoOy~ z?kuek#W49jX2ZP(hn(A&U)~yn_ZvSsHD{wE{lL$s0*)hdp9qs^$k%0u;H$~TMCADE zJa~uQz8T~wW=!?RDh`kP=)ACDuV>n$4EIb$s_7WoG0`eQuOSkf z_`bxK`R(fWyHiv$Jj?5WU&fOx2O>tu%u}x3&KXA?q=+^wos7K?6~pyViXN0~yprVV zYGIBaIrS>^|B6pR_A8`{X+B;LT%YdV(m z`xvi&iQDn-v(M;5t@eapQ(dBnQ4$N`DVjQXDw6Q_rN2~S37NTpkr=dgN26!c=ImY3 z^#Ld{Xk0_+0g<(+u6R_#B0r&;e|^hp1`TA|V#_q>$*>}pR@i+ICUutnj-d+0E+l-% zWN(t;*d#MyWTO6Uw->1Uxm4VREOYOdr*jqZ-DhgGfYAfR5qtz`ktHI17HkiQC@34z z?+E)bwbp#N*vfzwlW(*>6*s&?M04cHn@||{rg8%7hHK_6;ZQpQK7PVGm z!JwAqdc}2H3e22^C}AuqPE6DqnKGOVcQ)0Z(C-EA)JxX?T`80GKPzPtv2wBgtwd=R zFKd&>h#YkO0(VZVht&mGA6+X=JO{F6n*tMQt&<{62NNo{)E-pFoL~Qgz7Azy|6bQ zvtf;ns*6+yYjDkScBeqYS{+6;{VvlpEps50z)8SaE2BY4!m6#ky!zt3Z{M@#vQXXh z{*sI`rpJQOa%$T3!w#g4xG&Xhpscq>O|j=XD?ku8!d<-|J>5!z=l%HiXH4Go%L=X) z9KBec;2oJcxTQVHF1%aF)`aVb0G8!O^n0VSCH(<*%GqE zpr0C%O(@!q-)%P+tW>+Kw;0h|_i0*#rB8hg zcu0NWh!#OLlw zt=3AHl&g?hyji@-`-;&#ss#W8IVBW$D-GtH8e=ZgBXbL~kxgVBvhx7h*WO-|{T0kP zr&M+d*8~4UG3d0YKZvT@&R9&ANM^nFl>Tut_rPo^|oB z6P}!bNL@EgG_ru%^OHC6)QrW<wQlrDdI$F+hGlIX+Zky7Q zMf;M?=J*5$uw6u4;Be;RbJ~7ixNSN)nG-HVpSmSQvx`9LFD7JQ9DCvHbA1gJu)kWy zaqR{n6ORdZ`tuDzsG(v#1zdOD!Y_bginlqDnEihU&1c&Ve#>e8oH?yAV7KPF$LR=d z;fgYr7P6rmQ@L_EqKgVue4uOtsCC&?#bE6h!Tz&Am+%X`C+gJUnUdX9=(S4szPMBtF2)CWV(NHg zn1{8>i9;T07H)xuH9AmCD7x9z!Y|K# z1)BOj9xvySd9$)F#o&=y`>|tbU#jq9=^8X;kwua5%v-RsPldrRUwi|SHks#f=g!wvrfY-T^Zop*u zlZEB)SyolnW{VNIZ6Dx@l(+;Qej3230y8ugJk#T4s#$&q7rGp&f{MN|;oafI63|%! z9rMb2{bKxbvf}yp$Xg@Zaa;3Hir(>(BY;qswY$##d~jBAa6CQcGH|}e(T)v3ir(6v zm>++mJi9L3Dz=D5B7P_?U6+p}%;QJ0e=9%zg?vJCru&k$cviJa#kHKdbZ@vkO6sS( zwCxV_ffakrYMpj(jeiL!nO%?$#Xy9UD^^-+Svz%64ktcs_OBe%c!@- z@4bZ6W2Z8eP5EP1O=v;z5LiZ3!OwbKC}ck9KEytKv zojD;r&5&TWMP%SIV3`(h-5nnun zSz^V_wkRAw`ioriLfyU37e6EY=ZWA^T=5Vh)tH>DbJ5DKaybT?_6W4b3e9Qw>)=26>4TbqpoZEMmQ-le!5jOuEPGA z`HAFe7d6c^E4fGcJ7A~{cO2? zH-0n~|2~u5RD0N?j5Ad2zzJ$-kEB|3Kz%|vUVZ?RneqvneZbV9ECQ&?4_k>{T=>$m zHl<9GUmHE3hW#jX69>Zpe*SA7W)B-V`p3rDrcZ%01AK7)I%CkOYh|h{CAoH9uH29d%r0oMD1o$=4Cqi~u1H<2dR6HIC zOX=)<|95_6?F4|@gI<&BNkxU1tvHAGtA|>e{yX~IA|UYvZr~Mk*0c25##3f({n9Sb z5qNmR7eEZ3TsUAeG!9x92vD{^K6`y-&1@Ile=hdsL)zTBZHh-=*uKg7az)w@y}5q7 z`M_V9HMV_hmOckp5xsrL*6eY`8meHAK!$oDpAx<8^^}yao2Z0hTG(~EuFz>$r!GpG z7GAb*hqEUpbp@easzTATkdI!FbKYi_0w@RL-d%1bZ+7aH)P&yh7 zg1P2wBW;-P-trH=-n_se`leXg(qaTN9?LNI>UobDH%c+<>B`$qD4e_NE-m}&1vAi7 zfpl%{23uPGG0|IpeD*^h=k5M`GCasl$Aito2}d9y%ozd>jLi45AVM~=0(cb|-ls3w zks#&oh=Fwxl>lLpC}<1)gh#96LzXLC>_9Vs<^;nlA^#Q zWnzAi))AEpYB2Ts)(T7RikU$kLT&zvCt#&q|Mo$p@B>VR;4m+k9#XJTj81zs3B^{m zHp5YBfL{y@DI>-_FbZVrYJUI+Hs$u~mdI-IqMn2*zzK|-MlhHbUzqz>B)hRYw!ySk z(9-+bs2#!2VqiMN@`b*`4>5P2!W zE}E^u#Q9pX`kYAqU2)6kLrf~W+R}}g$c-Jx3FVMI75@%3&fnIMT#>zTH7JBMby!8e zZF9MLw$QbF9vGI&H=v%rRM`5?Qel{UYBf4Vd>R%*dXSkj1!@-$gdyFk&8X3{!6991 z{C;FsGc8hU349ByKcEP09I#eW9M0G74w*Ce+Tzp;e!`yUwxaS2W{Fo z97anZoyK9k{wBLe0G02kYFHlnAN8)=116!54?ft&7*cOmF3W~{<@)3%O$yEO1nBb+ z2nP6)+ni=d+|Mxi3}o7x#p$BX73tn)l=E~3R!eghFJDV?Mz3Gv4Cf1X5~hWm1+i~d zu3y^GEL;ssrLCu`Yj@N( zEhCVg$4P1zj=T;#{0GciMWw?a10i_;vV8Kij2z91Vxz18ea9Q`_@zz)4S=3k%V`^( z-+H&_&4=4ExH8nw2( zwWdBz?}>57+H?uvl3vZUO(ncq3#y|09b{ra1zL=5g55phA}}^if+#~th9CLzIig@8{|2VV zNL(=Fj(FZI3|3HF3r-JK628yDIvMS=D;@L>}}-hI|Q=Oqi)y)x0UQNBiv!7z;5N9HJgsk6>^t`|HXEDjWx2j9~1i zZwpY_0s|lVO;mVqvPuO!A8hT~JXWA*L0=C_Hh4m8K6$*$9`jcew;wC^dAG0k%b=GA zGe3X}xjQERyD<1ybzc>bEs%&o-oRYh(dvJinTR+T+5Z=gZ#g2SkDe!SGkXWe51#M8 zKT-pK$lA;Z!na-1>`BHhM0FUW79SOJAVYKJmPj{z`gVZXy!<}Sc}yQlp)bGYX}CB( zP9U!oK^%lmEI5rG?rTq<32lZz1JaOtaNPzU)5 z=Ib!%GdzsoE;OX5LI60b^ds>n>{%{Ibkj90?ZDyao^9KO;L6R@_H}}w!qpZ8R;+mM z5UfphEw3Yj=cUM{UkNv$u==oiL^`IB3IEG)7ezzxkYZhVMF&jXR*mgC+fl5$a(00& z%}lOmgOGh;F_ao8)UzzArlpiTDrUCa@|k+#{FN~P4mnj+y5f;ok-Gc@z7jIFoyq(n zn~bTAq_OxcS%hmG&}@16Al7OC-yd$aOfm^4jOg6lb~hmLHT^>I zH8gGU4<)|C@>TpK%7Ao-VPgooVf zl2)aegAoOa5kukZKydsswc!|5sL(oibzqFzFe7SwBfp+9pbaDV>T&Me64&s4J*D1*iKfmqS88cvSZ^Y*{B8V> zdkj@p`1%IJSBpaWt}o^Umv|B2>m`9tmzKyK``lmrqewoHR)u{z#R^OKnXG|Pk-nAA z*Qk_Zv01hr9FkzzRp^5u&N_(1=^2^FS)CA}ANax}HEC!(YxVi2(h z>N}d*Sc~dA0*NR^xtST6S(!eV8JL+^*jTwV{^y9lj{dH%0#qY%F>^E}GX01(dwZbq z$Fd9%uJ3R|M+lN;Q_BKXNhJRh;zm5NojgKW|Cj)b!q2qt~t77J8`SGO&*98#+fJl>wiHPN6)BbSL z%nkSi5xJCHT}$KTz@ zcQ-}jxc4`w%}-x7-96_u+zHQb_QlvET-v9bi)dR4zt2%C?@H_TnWrg@b&A+BlE^nj1QkXXMN|GnQ0enDGkX~_0x z8f6g>fH%c;-c>&$(K$ry?ShVr!HoMOXwVv(AeSpwDt|bwBDD&<-Izj}@3C=BT6S_q zPWq^M36f#41NEH_I79_J!~|}dxit`YlQ6kZ1%EesCkKKwCsH_k+eO|n@4na>l`#Xh zcW9?ZuCXlpy#ZW}tVU|qAg^yY6mW@nERieR-K6<6mKo)nz0Icfdz&ENS6bH{X>?zD zNi;ls%Le>s5|pCQllkT$j>iqnZW_gdIutneC|J|uB_U}7dsO1 zEMMAvPcOhN1LwLZ7{&0EJyYA!r!3GD%YvTOfYF8IQ9mC77i9TVT>7F_cz7E4M>>k{ z=vZ52A#x< zvY*CppzvC3fZyTuvuoc;FT2lz5sG`Y6rNX|wtx2pT&|OAh_E8z>f5QP9&gL4;hK|G zE*N??At8zLu{q6epz@NHt$lRMkK6OMs`&rd1Zc*soV|f3iUI#@@%+hYHSEEpfky5K zfsc<45g$Nn&4PVXwg=InwH}4qX{*Ln4xjA0!~v5!M9d!Vxr`p)nRx`%-(bJIKfSzs z4pPa({eN>C(Lb+$5cmgye-QWwfqxMA2Z4VO_y>W15cmgy|4$Ksb8ytRcXa(IF2FG} NvBQy(iOGw@{U5Vq)s_GN literal 0 HcmV?d00001 From 4a7c1d4a384c30eb2deed56619bc377027dcdc13 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 11:28:52 -0500 Subject: [PATCH 207/323] update readme and add paper --- test/experiments/osdi2025/README.md | 2 ++ test/experiments/osdi2025/install.sh | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/test/experiments/osdi2025/README.md b/test/experiments/osdi2025/README.md index 3f717c6e..3436608b 100644 --- a/test/experiments/osdi2025/README.md +++ b/test/experiments/osdi2025/README.md @@ -51,7 +51,9 @@ To just evaluate Quake use this. ```bash git clone [https://github.com/marius-team/quake.git](https://github.com/marius-team/quake.git) cd quake + git checkout osdi2025 git submodule update --init --recursive + ``` 2. **Set Up the Conda Environment:** diff --git a/test/experiments/osdi2025/install.sh b/test/experiments/osdi2025/install.sh index 9cb705c1..b114186b 100644 --- a/test/experiments/osdi2025/install.sh +++ b/test/experiments/osdi2025/install.sh @@ -199,7 +199,7 @@ else git clone https://github.com/marius-team/quake.git "${QUAKE_FULL_PATH}" cd "${QUAKE_FULL_PATH}" fi -git checkout osdi2025_debug +git checkout osdi2025 git config --global --add safe.directory "${QUAKE_FULL_PATH}" # For root's global config SUBMODULE_PATHS=("src/cpp/third_party/concurrentqueue" "src/cpp/third_party/faiss" "src/cpp/third_party/pybind11") From e44c75db61a9451ce2a44abe4f75f6ce58156a80 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 11:33:07 -0500 Subject: [PATCH 208/323] update readme --- test/experiments/osdi2025/README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/test/experiments/osdi2025/README.md b/test/experiments/osdi2025/README.md index 3436608b..709d909a 100644 --- a/test/experiments/osdi2025/README.md +++ b/test/experiments/osdi2025/README.md @@ -10,19 +10,21 @@ The experiments are organized as follows: ```plaintext -./test/experiments/osdi2025/ -├── common/ \# Shared utilities for experiments -│ └── experiment\_utils.py -├── experiment\_runner.py \# Main script to run any experiment +quake/test/experiments/osdi2025/ +├── experiment_runner.py \# Main script to run any experiment +├── experiment_utils.py \# Shared functionality across experiments ├── README.md \# This file -├── \/ \# Directory for each specific experiment +├── paper/ \# PDF of the paper +│ ├── Quake.pdf \# Original Submission +│ ├── Quake-Revision.pdf \# Revised Version +├── / \# Directory for each specific experiment │ ├── configs/ \# YAML configuration files for the experiment -│ │ └── \.yaml +│ │ └── .yaml │ └── run.py \# Python script to execute the experiment logic └── ... \# Other experiment directories ``` -Each experiment directory (e.g., `aps_recall_targets`, `early_termination`) contains its specific logic in `run.py` and configurations in its `configs/` subdirectory. The `common/experiment_utils.py` module provides shared functionality for loading data, configurations, preparing indexes, and plotting, aiming to simplify individual experiment scripts. +Each experiment directory (e.g., `aps_recall_targets`, `early_termination`) contains its specific logic in `run.py` and configurations in its `configs/` subdirectory. The `experiment_utils.py` module provides shared functionality for loading data, configurations, preparing indexes, and plotting, aiming to simplify individual experiment scripts. ## Installation From 31f68ddf15d57648d46902786d4ef5dde81fe655 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 11:36:13 -0500 Subject: [PATCH 209/323] update readme --- test/experiments/osdi2025/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/experiments/osdi2025/README.md b/test/experiments/osdi2025/README.md index 709d909a..fdd3c697 100644 --- a/test/experiments/osdi2025/README.md +++ b/test/experiments/osdi2025/README.md @@ -113,7 +113,7 @@ OMP_NUM_THREADS=1 python3 -m test.experiments.osdi2025.experiment_runner \ ### Quick Reproduction -These experiments should take less than 10 minutes to run in total. +These experiments should take less than 10 minutes to run in total if the datasets/indexes have been prepared ahead of time. Otherwise it will take 30-60 minutes on the first run. 1. Reproduction of APS (Figure 6 in `paper/Quake.pdf`) From 488640578661d4b064c35c39a1d172491de0c1a6 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 12:32:53 -0500 Subject: [PATCH 210/323] dont overwrite workload --- .../osdi2025/maintenance_ablation/configs/sift1m.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/experiments/osdi2025/maintenance_ablation/configs/sift1m.yaml b/test/experiments/osdi2025/maintenance_ablation/configs/sift1m.yaml index 9e6365a4..a932cbb8 100644 --- a/test/experiments/osdi2025/maintenance_ablation/configs/sift1m.yaml +++ b/test/experiments/osdi2025/maintenance_ablation/configs/sift1m.yaml @@ -101,6 +101,6 @@ plot: LIRE: {color: "#ffbb78", linestyle: "-", marker: "P"} overwrite: - workload: true + workload: false index: true results: true \ No newline at end of file From 9313075a8d1112bbd25b383f0c1cf4034353a2ce Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 13:08:57 -0500 Subject: [PATCH 211/323] dont overwrite index if load=false --- test/experiments/osdi2025/experiment_utils.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/experiments/osdi2025/experiment_utils.py b/test/experiments/osdi2025/experiment_utils.py index 3dafc5cf..1d397168 100644 --- a/test/experiments/osdi2025/experiment_utils.py +++ b/test/experiments/osdi2025/experiment_utils.py @@ -39,9 +39,10 @@ def prepare_quake_index( load: bool = True ) -> QuakeIndex: idx = QuakeIndex() - if index_file_path.exists() and not force_rebuild and load: - logger.info(f"Loading index from {index_file_path}") - idx.load(str(index_file_path), num_workers_load, use_numa, num_parent_workers_load) + if index_file_path.exists() and not force_rebuild: + if load: + logger.info(f"Loading index from {index_file_path}") + idx.load(str(index_file_path), num_workers_load, use_numa, num_parent_workers_load) else: logger.info(f"Building index -> {index_file_path}") bp = IndexBuildParams() From 419953fffea88648e4d017e41b0f1bcdf812dd0a Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 13:10:58 -0500 Subject: [PATCH 212/323] update readme --- test/experiments/osdi2025/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/experiments/osdi2025/README.md b/test/experiments/osdi2025/README.md index fdd3c697..40cec97b 100644 --- a/test/experiments/osdi2025/README.md +++ b/test/experiments/osdi2025/README.md @@ -51,7 +51,7 @@ To just evaluate Quake use this. 1. **Clone the Repository:** ```bash - git clone [https://github.com/marius-team/quake.git](https://github.com/marius-team/quake.git) + git clone https://github.com/marius-team/quake.git cd quake git checkout osdi2025 git submodule update --init --recursive From 8d247a3bb67a081e30246ba12946e8f68470de35 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 13:45:32 -0500 Subject: [PATCH 213/323] update readme --- test/experiments/osdi2025/README.md | 6 +++--- .../osdi2025/maintenance_ablation/configs/sift1m.yaml | 4 ---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/test/experiments/osdi2025/README.md b/test/experiments/osdi2025/README.md index 40cec97b..a3759705 100644 --- a/test/experiments/osdi2025/README.md +++ b/test/experiments/osdi2025/README.md @@ -111,9 +111,9 @@ OMP_NUM_THREADS=1 python3 -m test.experiments.osdi2025.experiment_runner \ ``` Outputs will be in `test/experiments/osdi2025/kick_the_tires/results/sift1m/`. -### Quick Reproduction +### Reproduction of Main Quake Components -These experiments should take less than 10 minutes to run in total if the datasets/indexes have been prepared ahead of time. Otherwise it will take 30-60 minutes on the first run. +These experiments should take less than hour (mostly in maintenance_ablation) to run in total if the datasets/indexes have been prepared ahead of time. Otherwise it will take 2 hours on the first run. 1. Reproduction of APS (Figure 6 in `paper/Quake.pdf`) @@ -135,7 +135,7 @@ These experiments should take less than 10 minutes to run in total if the datase --config msturing10m ``` -3. Maintenance Ablation Study (Table 6 in `paper/Quake-Revision.pdf`) +3. Maintenance Ablation Study (Table 6 in `paper/Quake-Revision.pdf`) This removes critical pieces of the Quake maintenance policy and measure its effect on workload performance. diff --git a/test/experiments/osdi2025/maintenance_ablation/configs/sift1m.yaml b/test/experiments/osdi2025/maintenance_ablation/configs/sift1m.yaml index a932cbb8..8b4895eb 100644 --- a/test/experiments/osdi2025/maintenance_ablation/configs/sift1m.yaml +++ b/test/experiments/osdi2025/maintenance_ablation/configs/sift1m.yaml @@ -93,10 +93,6 @@ plot: Quake-NoRefineNoReject: {color: "#8c564b", linestyle: "-", marker: "s"} Quake-NoCost: {color: "#d627bb", linestyle: "-", marker: "D"} Quake-NoCostNoRefine: {color: "#ff7f0e", linestyle: "-", marker: "+"} - Quake-NoRejectSplit: {color: "#7f7f7f", linestyle: "-", marker: "H"} - Quake-NoRejectDelete: {color: "#bcbd22", linestyle: "-", marker: "h"} - Quake-NoRejectNoDelete: {color: "#ffbb78", linestyle: "-", marker: "P"} - Quake-NoRejectNoSplit: {color: "#ffbb78", linestyle: "-", marker: "P"} LIRE: {color: "#ffbb78", linestyle: "-", marker: "P"} From d03f74b315abb4927923bc1519b77e2798530d68 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 21 May 2025 17:20:11 -0500 Subject: [PATCH 214/323] update multi-level experiment --- test/experiments/osdi2025/experiment_utils.py | 65 +- .../osdi2025/multi_level/configs/sift10m.yaml | 189 ++---- .../osdi2025/multi_level/configs/sift1m.yaml | 61 ++ test/experiments/osdi2025/multi_level/run.py | 603 +++++++++++------- 4 files changed, 561 insertions(+), 357 deletions(-) create mode 100644 test/experiments/osdi2025/multi_level/configs/sift1m.yaml diff --git a/test/experiments/osdi2025/experiment_utils.py b/test/experiments/osdi2025/experiment_utils.py index 1d397168..9f935028 100644 --- a/test/experiments/osdi2025/experiment_utils.py +++ b/test/experiments/osdi2025/experiment_utils.py @@ -3,7 +3,10 @@ import yaml import logging from pathlib import Path +import contextlib +import sys from typing import Dict, Any, List +import os import torch import pandas as pd @@ -14,7 +17,6 @@ from quake.datasets.ann_datasets import load_dataset as quake_load_dataset from quake.utils import compute_recall as quake_compute_recall from quake.workload_generator import DynamicWorkloadGenerator, WorkloadEvaluator - logger = logging.getLogger(__name__) def load_config(cfg_path: str) -> dict: @@ -47,8 +49,8 @@ def prepare_quake_index( logger.info(f"Building index -> {index_file_path}") bp = IndexBuildParams() for key, value in build_params_dict.items(): - if hasattr(bp, key): - setattr(bp, key, value) + setattr(bp, key, value) + idx.build(vecs, torch.arange(len(vecs)), bp) index_file_path.parent.mkdir(parents=True, exist_ok=True) idx.save(str(index_file_path)) @@ -237,4 +239,59 @@ def expand_search_sweep(sweep_config: Dict[str, Any]) -> List[Dict[str, Any]]: expanded_list.append({**base_params, "recall_target": rt_val}) else: # No sweep, just use base_params expanded_list.append(base_params) - return expanded_list \ No newline at end of file + return expanded_list + +def create_index_build_params(**attrs) -> IndexBuildParams: + """Creates a Quake IndexBuildParams object from dictionary attributes.""" + bp = IndexBuildParams() + if 'nc' in attrs and 'nlist' not in attrs: # Allow 'nc' as an alias for 'nlist' + attrs['nlist'] = attrs.pop('nc') + + for k, v in attrs.items(): + if hasattr(bp, k): + setattr(bp, k, v) + else: + logger.warning(f"Attribute '{k}' not found in IndexBuildParams. Ignoring.") + return bp + +def save_results_df(records: list, output_path: Path): + df = pd.DataFrame(records) + output_path.parent.mkdir(parents=True, exist_ok=True) + df.to_csv(output_path, index=False) + logger.info(f"Results saved to {output_path}") # Already logs + +@contextlib.contextmanager +def redirect_all_stdout_to_file(filepath: Path | str, mode: str = 'a'): + original_python_stdout = sys.stdout + original_c_stdout_fd = -1 + saved_c_stdout_fd = -1 + target_file = None + + try: + original_c_stdout_fd = sys.stdout.fileno() + saved_c_stdout_fd = os.dup(original_c_stdout_fd) + + target_file = open(filepath, mode) + target_file_fd = target_file.fileno() + + os.dup2(target_file_fd, original_c_stdout_fd) + sys.stdout = target_file + + yield + + except Exception: + # util_logger.error(f"Exception during stdout redirection: {e}", exc_info=False) # Removed for brevity + raise # Re-raise the exception + finally: + if sys.stdout == target_file : + sys.stdout.flush() + + if original_c_stdout_fd != -1 and saved_c_stdout_fd != -1: + os.dup2(saved_c_stdout_fd, original_c_stdout_fd) + + sys.stdout = original_python_stdout + + if target_file: + target_file.close() + if saved_c_stdout_fd != -1: + os.close(saved_c_stdout_fd) \ No newline at end of file diff --git a/test/experiments/osdi2025/multi_level/configs/sift10m.yaml b/test/experiments/osdi2025/multi_level/configs/sift10m.yaml index df7ef1f1..384ffd13 100644 --- a/test/experiments/osdi2025/multi_level/configs/sift10m.yaml +++ b/test/experiments/osdi2025/multi_level/configs/sift10m.yaml @@ -1,136 +1,75 @@ -# ─── top-level controls ─────────────────────────────────────────────────────── -mode: run # build | run | plot +# General settings overwrite: - index: false # force rebuild of every index - results: true # force rerun of every search + index_files: false # If true, rebuilds all L0 index files + results_csv: true # If true, re-runs searches and overwrites result CSVs -# ─── dataset ────────────────────────────────────────────────────────────────── dataset: - name: sift10m # built-in quake dataset + name: sift10m metric: l2 - path: data # ignored for packaged datasets - nq: 100 # number of queries to use + nq: 100 -# ─── indexes / workloads ────────────────────────────────────────────────────── -indexes: - - name: Quake5000 - index: Quake +# --- L0 (Base Level) Definitions --- +l0_definitions: + "L0_40k_config": # Unique reference name for this L0 build configuration + type: Quake build_params: - nc: 5000 - num_workers: 8 - search_params: - k: 1 -# recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] - nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -# initial_search_fraction: 0.01 -# batched_scan: true - batch_size: 1 - - - name: Quake10000 - index: Quake + nlist: 40000 + num_workers: 4 + "L0_10k_config": + type: Quake build_params: - nc: 10000 - num_workers: 8 - search_params: - k: 1 -# recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] - nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -# initial_search_fraction: 0.01 -# batched_scan: true - batch_size: 1 + nlist: 10000 + num_workers: 4 - - name: Quake20000 - index: Quake - build_params: - nc: 20000 - num_workers: 8 - search_params: - k: 1 -# recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] - nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -# initial_search_fraction: 0.01 -# batched_scan: true - batch_size: 1 +# --- Global L0 Search Sweep --- +global_l0_search_sweep: + nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256] # List of nprobe values for L0 + # recall_targets: [0.5, 0.6, 0.7, 0.8, 0.85, 0.9, 0.95, 0.99] # Alternative L0 sweep + # initial_search_fraction: 0.01 # Required if using recall_targets + k: 1 # k for L0 search (and overall recall calculation) + batch_size: 1 # Query batch_size for L0 search - - name: Quake40000 - index: Quake - build_params: - nc: 40000 - num_workers: 8 - search_params: - k: 1 -# recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] - nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -# initial_search_fraction: 0.01 -# batched_scan: true - batch_size: 1 +# --- Index Hierarchy Definitions --- +index_hierarchies: + - name: "Flat_L0_40k" # Unique name for this specific hierarchy/curve + l0_ref: "L0_40k_config" # Referenlistes an L0 from 'l0_definitions' + # parent_levels: (empty or omitted) -> This is a flat index using the referenlisted L0. - - name: Quake80000 - index: Quake - build_params: - nc: 80000 - num_workers: 8 - search_params: - k: 1 -# recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] - nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -# initial_search_fraction: 0.01 -# batched_scan: true - batch_size: 1 -# - - name: Quake160000 - index: Quake - build_params: - nc: 160000 - num_workers: 8 - search_params: - k: 1 -# recall_targets: [0.50, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 0.99] - nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] - initial_search_fraction: 0.005 -# batched_scan: true - batch_size: 1 -# -# - name: Quake20000_500 # two-level Quake index -# index: Quake -# build_params: -# nc: 20000 -# num_workers: 0 -# parent: -# nc: 500 -# num_workers: 0 -# search_params: -# k: 1 -# nprobes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -## initial_search_fraction: 0.05 -# batch_size: 1 -# parent: -# nprobe: 50 -# # child-internal search; leave single high target here -## recall_target: 0.999 -## initial_search_fraction: 0.2 + - name: "Flat_L0_10k" # Unique name for this specific hierarchy/curve + l0_ref: "L0_10k_config" # Referenlistes an L0 from 'l0_definitions' + # parent_levels: (empty or omitted) -> This is a flat index using the referenlisted L0. + + + - name: "Hier_L0_40k_L1_1k_P50" # Name implies: L0 is 40k, L1 is 1k centroids, L1 nprobe is 50 + l0_ref: "L0_40k_config" + parent_levels: # List of parent levels (L1, L2, ...) built on top of L0 + - type: Quake # L1 configuration + build_params: {nlist: 1000, num_workers: 8} + search_params: {nprobe: 50} # Fixed search parameters for this L1 scan + + - name: "Hier_L0_10k_L1_0.5k_P20" + l0_ref: "L0_10k_config" + parent_levels: + - type: Quake # L1 + build_params: {nlist: 500, num_workers: 8} + search_params: {nprobe: 20} + + - name: "Custom_Flat_L0_5k" # Defines its L0 ad-hoc (not from l0_definitions) + custom_l0: # L0 definition specific to this hierarchy + type: Quake + build_params: {nlist: 5000, num_workers: 8} + # parent_levels: (empty or omitted) -> This is a custom flat L0. + +# --- General Run Settings --- +run_settings: + trials: 3 + warmup: 1 + default_batch_size: 1 + omp_threads_build: "16" # Or "MAX" as a placeholder for max available + omp_threads_search: "1" -# ─── plotting ──────────────────────────────────────────────────────────────── -plot: - styles: # one entry per *name* above - Quake5000: - color: "#1f77b4" - marker: "o" - Quake10000: - color: "#ff7f0e" - marker: "o" - Quake20000: - color: "#2ca02c" - marker: "o" - Quake40000: - color: "#9467bd" - marker: "o" - Quake80000: - color: "#8c564b" - marker: "o" - Quake160000: - color: "#e377c2" - marker: "o" - Quake20000_500: - color: "#d62728" - marker: "o" \ No newline at end of file +plot_styles: + "Flat_L0_40k": {color: "#1f77b4", marker: "o"} + "Hier_L0_40k_L1_1k_P50": {color: "#ff7f0e", marker: "s"} + "Hier_L0_10k_L1_0.5k_P20": {color: "#2ca02c", marker: "D"} + "Custom_Flat_L0_5k": {color: "#d62728", marker: "^"} \ No newline at end of file diff --git a/test/experiments/osdi2025/multi_level/configs/sift1m.yaml b/test/experiments/osdi2025/multi_level/configs/sift1m.yaml new file mode 100644 index 00000000..2cdda0aa --- /dev/null +++ b/test/experiments/osdi2025/multi_level/configs/sift1m.yaml @@ -0,0 +1,61 @@ +# General settings +overwrite: + index_files: false # Set to true to force rebuild L0s on first run of this config + results_csv: true # Re-runs searches and overwrites this config's output CSVs + +dataset: + name: sift1m # Using sift1m for a quicker test + metric: l2 + nq: 100 # Reduced number of queries for faster testing + +# --- L0 (Base Level) Definitions --- +l0_definitions: + "L0_1k_config": # L0 with 1000 centroids, suitable for sift1m + type: Quake + build_params: + nlist: 1000 + num_workers: 0 # Adjust based on your test machine + "L0_0.5k_config": # A smaller L0 + type: Quake + build_params: + nlist: 500 + num_workers: 0 + +# --- Global L0 Search Sweep --- +# Applies to the L0 of ALL index_hierarchies +global_l0_search_sweep: + nprobes: [1, 5, 10, 20] # Reduced list of nprobes for L0 + k: 10 + batch_size: 1 + +# --- Index Hierarchy Definitions --- +index_hierarchies: +# - name: "SingleLevel_L0_1k" # A single-level index using the 1k L0 +# l0_ref: "L0_1k_config" +# # No parent_levels + + - name: "Hier_L0_1k_L1_30_P5" # L0=1k, L1 groups L0's centroids, L1 nprobe=5 + l0_ref: "L0_1k_config" + parent_levels: + - type: Quake # L1 configuration + build_params: {nlist: 30, num_workers: 0} # L1 nc groups centroids of L0 + search_params: {nprobe: 5} # Fixed search params for L1 scan + + - name: "Custom_SingleLevel_L0_0.5k" # Ad-hoc custom L0, used as single-level + custom_l0: + type: Quake + build_params: {nlist: 500, num_workers: 0} # nc should be custom_l0.build_params.nc + +# --- General Run Settings --- +run_settings: + trials: 1 # Reduced trials for speed + warmup: 0 # No warmup for a quick test + default_batch_size: 1 + omp_threads_build: "16" # Adjust as needed + omp_threads_search: "1" + +# --- Plotting Styles --- +plot_styles: + "SingleLevel_L0_1k": {color: "#1f77b4", marker: "o"} + "Hier_L0_1k_L1_30_P5": {color: "#ff7f0e", marker: "s"} + "Custom_SingleLevel_L0_0.5k": {color: "#2ca02c", marker: "D"} \ No newline at end of file diff --git a/test/experiments/osdi2025/multi_level/run.py b/test/experiments/osdi2025/multi_level/run.py index a3abbbed..2788889b 100644 --- a/test/experiments/osdi2025/multi_level/run.py +++ b/test/experiments/osdi2025/multi_level/run.py @@ -1,252 +1,399 @@ +#!/usr/bin/env python3 from __future__ import annotations - -import argparse import logging import time from pathlib import Path -from typing import Dict, List, Tuple - +from typing import Dict, List, Any, Tuple +import copy import matplotlib.pyplot as plt import numpy as np import pandas as pd import torch +import os +import sys import yaml +from quake import QuakeIndex, IndexBuildParams, SearchParams, SearchTimingInfo +from test.experiments.osdi2025 import experiment_utils as common_utils +from quake.utils import compute_recall -# ── quake imports ────────────────────────────────────────────────────────────── -from quake.datasets.ann_datasets import load_dataset -from quake.index_wrappers.faiss_ivf import FaissIVF -from quake.index_wrappers.quake import QuakeWrapper -from quake.utils import compute_recall # recall@k - -logger = logging.getLogger("experiment") +logger = logging.getLogger("multi_level_debug_exp") logging.basicConfig( - format="%(asctime)s | %(levelname)s | %(message)s", - datefmt="%H:%M:%S", level=logging.INFO, + format="%(asctime)s | %(levelname)-8s | %(name)-25s | %(message)s", + datefmt="%H:%M:%S", + handlers=[logging.StreamHandler(sys.stdout)] ) -# ─────────────────────────────────────────────────────────────────────────────── -# helpers -# ─────────────────────────────────────────────────────────────────────────────── -def _prepare_index( - idx_cls, - vecs: torch.Tensor, - metric: str, - build_params: Dict, - index_path: Path, - rebuild: bool, -) -> Tuple[object, float]: - """ - Build–or–load an index and return (index, build_time_seconds). - build_time_seconds == 0 when loaded. - """ - idx = idx_cls() - if index_path.exists() and not rebuild: - t0 = time.time() - idx.load(str(index_path), num_workers=build_params["num_workers"]) - return idx, 0.0 - - logger.info("Building index → %s …", index_path) - t0 = time.time() - idx.build(vecs, metric=metric, **build_params) - t_build = time.time() - t0 - idx.save(str(index_path)) - logger.info("Index saved (%.1fs).", t_build) - return idx, t_build - - -def _dist_ids(res): - """Handle `(D, I)` tuples OR Quake SearchResult objects.""" - if isinstance(res, tuple) and len(res) == 2: - return res - if hasattr(res, "distances") and hasattr(res, "indices"): - return res.distances, res.indices - raise TypeError(f"Unknown search result type: {type(res).__name__}") - - -def _benchmark_index( - idx, +def build_or_verify_l0( + l0_key_name: str, + l0_build_config: Dict[str, Any], + base_vectors: torch.Tensor, + dataset_metric: str, + output_dir: Path, + force_rebuild: bool, + quake_verbose_log_path: Path # Added for redirection +) -> Path: + index_file_path = output_dir / f"l0_index_{l0_key_name}.bin" + l0_type = l0_build_config.get("type", "Quake") + if l0_type != "Quake": + raise NotImplementedError(f"L0 index type '{l0_type}' not yet supported.") + + build_params_dict = copy.deepcopy(l0_build_config.get("build_params", {})) + if 'metric' not in build_params_dict: + build_params_dict['metric'] = dataset_metric + + if not index_file_path.exists() or force_rebuild: + logger.info(f"Building L0 '{l0_key_name}' (nlist={build_params_dict.get('nlist')}) -> {index_file_path}") + with common_utils.redirect_all_stdout_to_file(quake_verbose_log_path, mode='a'): + _ = common_utils.prepare_quake_index( + vecs=base_vectors, + build_params_dict=build_params_dict, + index_file_path=index_file_path, + force_rebuild=True, + load=False + ) + else: + logger.info(f"Using existing L0 '{l0_key_name}' from {index_file_path}") + return index_file_path + +def construct_full_search_params( + l0_variant_params: Dict[str, Any], + parent_levels_config: List[Dict[str, Any]] +) -> SearchParams: + current_sp = common_utils.create_search_params(**l0_variant_params) + previous_level_sp = current_sp + for parent_cfg in parent_levels_config: + parent_search_dict = parent_cfg.get("search_params", {"nprobe": 1}) + parent_level_sp = common_utils.create_search_params(**parent_search_dict) + previous_level_sp.parent_params = parent_level_sp + previous_level_sp = parent_level_sp + return current_sp + +def extract_recursive_timing_stats( + timing_info: SearchTimingInfo | None, max_levels: int +) -> Dict[str, Any]: + stats = {} + current_ti = timing_info + for i in range(max_levels): + level_prefix = f"L{i}" + if current_ti: + stats[f"{level_prefix}_total_scan_ms"] = current_ti.total_time_ns / 1e6 + stats[f"{level_prefix}_partitions_scanned"] = getattr(current_ti, "partitions_scanned", np.nan) + current_ti = current_ti.parent_info + else: + stats[f"{level_prefix}_total_scan_ms"] = np.nan + stats[f"{level_prefix}_partitions_scanned"] = np.nan + return stats + +def benchmark_hierarchy_search_point( + index_instance: QuakeIndex, queries: torch.Tensor, - ground: np.ndarray, - search_params: Dict, + ground_truth: np.ndarray | None, + full_hierarchical_sp: SearchParams, + num_actual_levels: int, trials: int, warmup: int, -) -> Dict: - bs = search_params.pop("batch_size", None) - k = search_params["k"] - - # warm-up - for _ in range(warmup): - if bs is None: - idx.search(queries, **search_params) - else: - for i in range(0, len(queries), bs): - idx.search(queries[i : i + bs], **search_params) - - qps_vals: List[float] = [] - lat_ms: List[float] = [] + quake_verbose_log_path: Path # Added for redirection +) -> Dict[str, Any]: + trial_latencies_ns = [] + trial_recalls = [] + trial_per_level_stats_list = [] + k_val_for_recall = full_hierarchical_sp.k + + with common_utils.redirect_all_stdout_to_file(quake_verbose_log_path, mode='a'): + for _ in range(warmup): + index_instance.search(queries, full_hierarchical_sp) + for _ in range(trials): + t_start_ns = time.perf_counter_ns() + search_result = index_instance.search(queries, full_hierarchical_sp) + t_elapsed_ns = time.perf_counter_ns() - t_start_ns + trial_latencies_ns.append(t_elapsed_ns) + + if ground_truth is not None and search_result.ids is not None: + max_k_recall = min(k_val_for_recall, ground_truth.shape[1], search_result.ids.shape[1]) + recall_val = compute_recall( + search_result.ids[:, :max_k_recall], + ground_truth[:, :max_k_recall],max_k_recall + ).mean().item() if max_k_recall > 0 else np.nan + trial_recalls.append(recall_val) + else: + trial_recalls.append(np.nan) + trial_per_level_stats_list.append( + extract_recursive_timing_stats(search_result.timing_info, num_actual_levels) + ) - for _ in range(trials): - t0 = time.time() - if bs is None: - res = idx.search(queries, **search_params) - D, I = res.distances, res.ids - else: - all_I, all_D = [], [] - for i in range(0, len(queries), bs): - res = idx.search(queries[i : i + bs], **search_params) - D_, I_ = res.distances, res.ids - all_I.append(I_); all_D.append(D_) - I = np.concatenate(all_I); D = np.concatenate(all_D) - dt = time.time() - t0 - qps_vals.append(len(queries) / dt) - lat_ms.append(dt * 1e3) - - recall = compute_recall(I, ground[:, :k], k) - recall = 0.0 if recall is None else recall.mean().item() - - return dict( - recall = float(recall), - qps_mean = float(np.mean(qps_vals)), - qps_std = float(np.std(qps_vals)), - latency_mean_ms = float(np.mean(lat_ms)), - trials = trials, - warmup = warmup, - batch_size = bs or len(queries), + mean_latency_ms = np.mean(trial_latencies_ns) / 1e6 if trial_latencies_ns else np.nan + qps_mean = len(queries) / (mean_latency_ms / 1000) if mean_latency_ms > 0 else np.inf + results = { + "qps_mean": qps_mean, + "recall_mean": np.nanmean(trial_recalls) if trial_recalls else np.nan, + "overall_latency_ms_mean": mean_latency_ms, + } + if trial_per_level_stats_list: + df_level_stats = pd.DataFrame(trial_per_level_stats_list) + for col in df_level_stats.columns: + results[f"{col}_mean"] = df_level_stats[col].mean() + return results + +def run_experiment(config_path_str: str, output_dir_str: str): + config = common_utils.load_config(config_path_str) + output_dir = Path(output_dir_str) + output_dir.mkdir(parents=True, exist_ok=True) + + quake_verbose_log = output_dir / "quake_internal_details.log" + if quake_verbose_log.exists(): quake_verbose_log.unlink() # Clear log at start of run + + logger.info(f"Loaded configuration from: {config_path_str}") + dataset_cfg = config["dataset"] + overwrite_cfg = config["overwrite"] + l0_definitions = config.get("l0_definitions", {}) + global_l0_sweep_cfg = config["global_l0_search_sweep"] + index_hierarchies_cfg = config["index_hierarchies"] + run_settings = config["run_settings"] + original_omp_threads = os.environ.get("OMP_NUM_THREADS") + plot_styles = config.get("plot_styles", {}) + + logger.info(f"Dataset: {dataset_cfg['name']}, Metric: {dataset_cfg['metric']}, NQ: {dataset_cfg['nq']}") + logger.info(f"Overwrite index_files: {overwrite_cfg['index_files']}, Overwrite results_csv: {overwrite_cfg['results_csv']}") + logger.info(f"Verbose Quake output will be logged to: {quake_verbose_log}") + + + base_vectors, queries, gt_numpy = common_utils.load_data( + dataset_cfg["name"], dataset_cfg.get("path", "data/"), nq_override=dataset_cfg.get("nq") ) + logger.info(f"Loaded data: Base vectors {base_vectors.shape}, Queries {queries.shape}, GT {gt_numpy.shape if gt_numpy is not None else 'None'}") + + built_l0_files = {} + all_experiment_records = [] + + omp_build_threads = str(run_settings.get("omp_threads_build", os.cpu_count())) + os.environ["OMP_NUM_THREADS"] = omp_build_threads + logger.info(f"BUILD PHASE: Set OMP_NUM_THREADS={os.environ['OMP_NUM_THREADS']}") + unique_l0s_to_process = {} + for l0_ref_name, l0_conf in l0_definitions.items(): + unique_l0s_to_process[l0_ref_name] = l0_conf + for hierarchy_cfg in index_hierarchies_cfg: + if "custom_l0" in hierarchy_cfg: + unique_l0s_to_process[f"custom_for_{hierarchy_cfg['name']}"] = hierarchy_cfg["custom_l0"] + logger.info(f"Found {len(unique_l0s_to_process)} unique L0 configurations.") + for l0_key, l0_build_conf in unique_l0s_to_process.items(): + built_l0_files[l0_key] = build_or_verify_l0( + l0_key, l0_build_conf, base_vectors, dataset_cfg["metric"], + output_dir, overwrite_cfg["index_files"], quake_verbose_log # Pass log path + ) - -def _expand_targets(sp: Dict) -> List[Dict]: - """ - Produce one search-parameter dict per recall_target value. - - If `recall_targets` is absent (or a single float) we fall back to a list - containing exactly one dict, preserving the original behaviour. - """ - if "recall_targets" in sp: - tgs = sp.pop("recall_targets") - if not isinstance(tgs, (list, tuple)): - tgs = [tgs] - return [{**sp, "recall_target": t} for t in tgs] - elif "nprobes" in sp: - tgs = sp.pop("nprobes") - if not isinstance(tgs, (list, tuple)): - tgs = [tgs] - return [{**sp, "nprobe": t} for t in tgs] - else: - return [sp] - - -def _plot_unified(cfg: Dict, root: Path) -> None: - styles = cfg["plot"]["styles"] - fig, ax = plt.subplots(figsize=(6, 4)) - - for icfg in cfg["indexes"]: - name = icfg["name"] - csv = root / name / "results.csv" - if not csv.exists(): - logger.warning("No results for %s – skipped in plot.", name) + l0_search_variants = common_utils.expand_search_sweep(global_l0_sweep_cfg) + global_k_val = global_l0_sweep_cfg["k"] + global_batch_size = global_l0_sweep_cfg.get("batch_size", run_settings.get("default_batch_size", 1)) + for variant in l0_search_variants: + if "k" not in variant: variant["k"] = global_k_val + if "batch_size" not in variant: variant["batch_size"] = global_batch_size + logger.info(f"Global L0 search sweep: {len(l0_search_variants)} variants. k={global_k_val}, batch_size={global_batch_size}.") + + omp_search_threads = str(run_settings.get("omp_threads_search", "1")) + os.environ["OMP_NUM_THREADS"] = omp_search_threads + logger.info(f"SEARCH PHASE: Set OMP_NUM_THREADS={os.environ['OMP_NUM_THREADS']}") + + for hierarchy_cfg in index_hierarchies_cfg: + hierarchy_name = hierarchy_cfg["name"] + logger.info(f"===== Processing Hierarchy: {hierarchy_name} =====") + l0_file_to_load, l0_build_details_for_reporting, l0_load_params_dict = None, {}, {} + + if "l0_ref" in hierarchy_cfg: + ref_name = hierarchy_cfg["l0_ref"] + l0_file_to_load = built_l0_files.get(ref_name) + l0_build_details_for_reporting = l0_definitions.get(ref_name, {}).get("build_params", {}) + elif "custom_l0" in hierarchy_cfg: + custom_l0_key = f"custom_for_{hierarchy_name}" + l0_file_to_load = built_l0_files.get(custom_l0_key) + l0_build_details_for_reporting = hierarchy_cfg["custom_l0"].get("build_params", {}) + if not l0_file_to_load: + logger.error(f"L0 file path not found for {hierarchy_name}. Skipping.") continue - df = pd.read_csv(csv).sort_values("recall") - sty = styles.get(name, {}) - ax.plot( - df["qps_mean"], df["recall"], - label = name, - marker = sty.get("marker", "o"), - linestyle = sty.get("linestyle", "-"), - linewidth = 1.4, - markersize= 6, - color = sty.get("color", None), - ) - - # ax.set_xscale("log", base=10) - ax.set_xlabel("Queries per second (log)") - ax.set_ylabel("Recall@k") - ax.set_title("Recall curves over varied recall_target") - ax.grid(True, which="both", ls=":") - ax.legend() - fig.tight_layout() - out_png = root / "recall_vs_qps.png" - fig.savefig(out_png, dpi=180) - logger.info("Plot written to %s", out_png) - - -# ─────────────────────────────────────────────────────────────────────────────── -# main -# ─────────────────────────────────────────────────────────────────────────────── -def run_experiment(cfg_path: str, output_dir: str) -> None: - cfg = yaml.safe_load(Path(cfg_path).read_text()) - out = Path(output_dir); out.mkdir(parents=True, exist_ok=True) - - mode = cfg.get("mode", "run") # build | run | plot - overwrite = cfg.get("overwrite", {}) - rebuild_index = bool(overwrite.get("index", False)) - rewrite_csv = bool(overwrite.get("results", False)) - - # dataset ------------------------------------------------------------------ - ds = cfg["dataset"] - logger.info("Loading dataset %s …", ds["name"]) - vecs, queries, ground = load_dataset(ds["name"], ds.get("path", "")) - metric = ds["metric"] - nq = ds["nq"] - ground = ground[:nq] - queries = queries[:nq] - - idx_map = {"Quake": QuakeWrapper, "IVF": FaissIVF} - - # build / run -------------------------------------------------------------- - if mode in {"build", "run"}: - for icfg in cfg["indexes"]: - name = icfg["name"] - res_dir = out / name; res_dir.mkdir(exist_ok=True, parents=True) - idx_bin = res_dir / "index.bin" - csv_file = res_dir / "results.csv" - idx_cls = idx_map[icfg["index"]] - - # BUILD once ======================================================= - idx, build_t = _prepare_index( - idx_cls, vecs, metric, icfg["build_params"], idx_bin, rebuild_index + l0_load_params_dict = { + "num_workers": l0_build_details_for_reporting.get("num_workers",0), + "use_numa": l0_build_details_for_reporting.get("use_numa",False), + "parent_num_workers": 0 # For L0 load itself + } + + num_actual_levels = 1 + len(hierarchy_cfg.get("parent_levels", [])) + + current_index = QuakeIndex() + with common_utils.redirect_all_stdout_to_file(quake_verbose_log, mode='a'): + current_index.load(str(l0_file_to_load), l0_load_params_dict["num_workers"], l0_load_params_dict["use_numa"], l0_load_params_dict["parent_num_workers"]) + + parent_levels_config_for_sp = [] + for i, parent_cfg in enumerate(hierarchy_cfg.get("parent_levels", [])): + parent_bp = common_utils.create_index_build_params(**parent_cfg["build_params"]) + if not parent_bp.metric: parent_bp.metric = dataset_cfg["metric"] + with common_utils.redirect_all_stdout_to_file(quake_verbose_log, mode='a'): + current_index.add_level(parent_bp) + parent_levels_config_for_sp.append(parent_cfg) + + for l0_variant in l0_search_variants: + l0_nprobe_val = l0_variant.get("nprobe") + l0_rt_val = l0_variant.get("recall_target") + sweep_param_log = f"nprobe={l0_nprobe_val}" if l0_nprobe_val is not None else f"RT={l0_rt_val}" + logger.info(f" Testing L0 Sweep: {sweep_param_log} for '{hierarchy_name}'") + + full_sp = construct_full_search_params(l0_variant, parent_levels_config_for_sp) + metrics = benchmark_hierarchy_search_point( + current_index, queries, gt_numpy, full_sp, + num_actual_levels, run_settings["trials"], run_settings["warmup"], + quake_verbose_log ) - if mode == "build": - continue # build-only mode stops here - - # RUN for every recall_target ====================================== - if csv_file.exists() and not rewrite_csv: - existing_df = pd.read_csv(csv_file) - else: - existing_df = pd.DataFrame() - - for sp in _expand_targets(icfg["search_params"].copy()): - tgt = sp.get("recall_target", None) - if tgt is None: - tgt = sp.get("nprobe") - # if ( - # not rewrite_csv - # and "recall_target" in existing_df.columns - # and ((existing_df.recall_target - tgt).abs() < 1e-9).any() - # ): - # logger.info("[%s] target %.3g cached – skipping run.", name, tgt) - # continue - - stats = _benchmark_index( - idx = idx, - queries = queries, - ground = ground, - search_params = sp, - trials = cfg.get("trials", 5), - warmup = cfg.get("warmup", 1), - ) - stats.update(build_time_s = build_t, recall_target = tgt) - existing_df = pd.concat( - [existing_df, pd.DataFrame([stats])], ignore_index=True - ) - logger.info("[%s] target %.3g done.", name, tgt) - - existing_df.to_csv(csv_file, index=False) - logger.info("[%s] results written to %s", name, csv_file) - - # plot --------------------------------------------------------------------- - if mode in {"run", "plot"}: - _plot_unified(cfg, out) + record = { + "hierarchy_name": hierarchy_name, + "L0_nlist": l0_build_details_for_reporting.get("nlist"), + "L0_nprobe": l0_nprobe_val, "L0_recall_target": l0_rt_val, + "L0_k": l0_variant["k"], "L0_batch_size": l0_variant["batch_size"], + } + for i, p_cfg in enumerate(hierarchy_cfg.get("parent_levels", [])): + level_num = i + 1 + record[f"L{level_num}_nlist"] = p_cfg.get("build_params", {}).get("nlist") + record[f"L{level_num}_search_nprobe"] = p_cfg.get("search_params", {}).get("nprobe") + record.update(metrics) + all_experiment_records.append(record) + logger.info(f" Done: Recall={metrics.get('recall_mean',0):.4f}, QPS={metrics.get('qps_mean',0):.1f}, Latency={metrics.get('overall_latency_ms_mean',0):.2f}ms") + del current_index + + if original_omp_threads is not None: os.environ["OMP_NUM_THREADS"] = original_omp_threads + elif "OMP_NUM_THREADS" in os.environ: del os.environ["OMP_NUM_THREADS"] + logger.info(f"OMP_NUM_THREADS settings reverted.") + + if not all_experiment_records: + logger.warning("No results collected.") + return + + final_df = pd.DataFrame(all_experiment_records) + unified_csv_path = output_dir / f"{dataset_cfg['name']}_summary.csv" # Simplified name + common_utils.save_results_df(final_df, unified_csv_path) + + plot_qps_vs_recall(final_df, plot_styles, dataset_cfg, output_dir) + plot_level_scan_time_breakdown(final_df, plot_styles, dataset_cfg, global_l0_sweep_cfg, output_dir) + + logger.info(f"===== Experiment Finished: {config_path_str} =====") + logger.info(f"Output directory: {output_dir.resolve()}") + + logger.info("\n--- Per-Hierarchy Per-L0-Parameter Summary ---") + for name, group in final_df.groupby('hierarchy_name'): + logger.info(f"\nResults for Hierarchy: {name}") + sweep_param = "L0_nprobe" if "L0_nprobe" in group.columns and group["L0_nprobe"].notna().any() else "L0_recall_target" + summary_cols = [sweep_param, 'recall_mean', 'overall_latency_ms_mean', 'qps_mean'] + # Filter out columns that might be all NaN if a sweep param wasn't used + summary_cols = [col for col in summary_cols if col in group.columns and group[col].notna().any()] + if not summary_cols or sweep_param not in summary_cols : # if sweep_param is all NaN + logger.info(group[['recall_mean', 'overall_latency_ms_mean', 'qps_mean']].to_string(float_format="%.4f")) + else: + logger.info(group[summary_cols].sort_values(by=sweep_param).to_string(float_format="%.4f")) + logger.info("-----------------------------------------------\n") + + +def plot_qps_vs_recall(results_df: pd.DataFrame, plot_styles: Dict[str, Any], dataset_cfg: dict, output_dir: Path): + if results_df.empty: return + plt.figure(figsize=(10, 6)) + for hierarchy_name, group in results_df.groupby("hierarchy_name"): + style = plot_styles.get(hierarchy_name, {}) + sorted_group = group.sort_values(by="recall_mean").dropna(subset=["qps_mean", "recall_mean"]) + if sorted_group.empty: continue + plt.plot( + sorted_group["recall_mean"], sorted_group["qps_mean"], label=hierarchy_name, + marker=style.get("marker", "o"), color=style.get("color"), linestyle=style.get("linestyle", "-") + ) + plt.xlabel(f"Mean Recall@{results_df['L0_k'].iloc[0] if 'L0_k' in results_df.columns and results_df['L0_k'].notna().any() else 'k'}") + plt.ylabel("Mean QPS") + plt.title(f"{dataset_cfg['name']}: QPS vs. Recall") + plt.legend(title="Hierarchy Config", bbox_to_anchor=(1.05, 1), loc='upper left') + plt.grid(True, which="both", ls=":", alpha=0.7) + plt.xlim(left=max(0.0, results_df["recall_mean"].min() - 0.05 if results_df["recall_mean"].notna().any() else 0.0), right=1.05) + if results_df["qps_mean"].notna().any() and results_df["qps_mean"].max() > 10 * results_df["qps_mean"].min() and results_df["qps_mean"].min() > 0: + plt.yscale("log") + plt.tight_layout(rect=[0, 0, 0.82, 1]) + plt.savefig(output_dir / f"{dataset_cfg['name']}_qps_vs_recall.png", dpi=150) + plt.close() + + +def find_best_op_point_for_recall_plot( + hierarchy_data: pd.DataFrame, + target_recall: float, + l0_sweep_key: str +): + # Find points meeting or exceeding target recall + valid_points = hierarchy_data[hierarchy_data['recall_mean'] >= target_recall] + + if valid_points.empty: + # If none meet, pick the one with highest recall + if not hierarchy_data.empty: + best_effort_point = hierarchy_data.loc[hierarchy_data['recall_mean'].idxmax()] + logger.warning( + f"For breakdown plot of '{best_effort_point['hierarchy_name']}', no L0 param met target recall {target_recall:.3f}. " + f"Using best achieved: R={best_effort_point['recall_mean']:.3f} " + f"(L0 {l0_sweep_key.split('_')[-1]}={best_effort_point[l0_sweep_key]})" + ) + return best_effort_point + return None + + # Among valid points, pick one with highest QPS, then lowest latency + best_point = valid_points.sort_values(by=['qps_mean', 'overall_latency_ms_mean'], ascending=[False, True]).iloc[0] + return best_point + +def plot_level_scan_time_breakdown( + results_df: pd.DataFrame, + plot_styles: Dict[str, Any], + dataset_cfg: dict, + l0_sweep_cfg: Dict[str, Any], + output_dir: Path, + target_recall_for_plot: float = 0.9 # New parameter +): + if results_df.empty: + logger.warning("Level scan time breakdown plot: No data.") + return + + l0_sweep_key = "L0_nprobe" if "nprobes" in l0_sweep_cfg else "L0_recall_target" + + points_for_plot = [] + for hierarchy_name, group in results_df.groupby("hierarchy_name"): + op_point = find_best_op_point_for_recall_plot(group, target_recall_for_plot, l0_sweep_key) + if op_point is not None: + points_for_plot.append(op_point) + + if not points_for_plot: + logger.warning(f"No suitable data points found for any hierarchy at target recall ~{target_recall_for_plot} for breakdown plot.") + return + + df_subset = pd.DataFrame(points_for_plot) + plot_title_suffix = f"(at or above R≈{target_recall_for_plot:.2f})" + + max_level = max([-1] + [int(c.split('_')[0][1:]) for c in df_subset.columns if c.startswith("L") and "_total_scan_ms_mean" in c]) + if max_level == -1: + logger.warning("No per-level scan time columns found for breakdown plot.") + return + + level_cols = [f"L{i}_total_scan_ms_mean" for i in range(max_level + 1)] + for col in level_cols: + if col not in df_subset.columns: df_subset[col] = 0.0 + + plot_data = df_subset.set_index("hierarchy_name")[level_cols].fillna(0) + plot_data.columns = [f"L{i} Scan (ms)" for i in range(max_level + 1)] + + ax = plot_data.plot(kind='bar', stacked=True, figsize=(12, 7), colormap='viridis_r') + + # Add text for achieved recall on top of each bar + for i, hierarchy_name in enumerate(df_subset["hierarchy_name"]): + row_data = df_subset.iloc[i] + total_height = plot_data.loc[hierarchy_name].sum() + actual_recall = row_data.get('recall_mean', np.nan) + if pd.notna(actual_recall): + ax.text(i, total_height * 1.01, f"R={actual_recall:.3f}", ha='center', va='bottom', fontsize=8, color='dimgrey') + + plt.xlabel("Hierarchy Configuration") + plt.ylabel("Mean Scan Time per Level (ms)") + plt.title(f"{dataset_cfg['name']}: Scan Time Breakdown {plot_title_suffix}") + plt.xticks(rotation=25, ha='right') + plt.legend(title="Level", bbox_to_anchor=(1.05, 1), loc='upper left') + plt.tight_layout(rect=[0, 0, 0.82, 1]) + plt.savefig(output_dir / f"{dataset_cfg['name']}_level_scan_breakdown_at_recall_target.png", dpi=150) + plt.close() + logger.info(f"Level scan time breakdown (at R~{target_recall_for_plot:.2f}) plot saved.") \ No newline at end of file From 1c8ef7833958ab9c9bbd2ac57e507a1ed68f1a6f Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 22 May 2025 12:34:48 -0500 Subject: [PATCH 215/323] fix path --- test/experiments/osdi2025/numa_multi_query/run.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/experiments/osdi2025/numa_multi_query/run.py b/test/experiments/osdi2025/numa_multi_query/run.py index c447c066..d607dd3b 100644 --- a/test/experiments/osdi2025/numa_multi_query/run.py +++ b/test/experiments/osdi2025/numa_multi_query/run.py @@ -78,7 +78,6 @@ def run_experiment(cfg_path_str: str, output_dir_str: str): # Use common_utils.load_data, pass num_queries_to_use for slicing base_vectors, query_vectors, gt_vectors = common_utils.load_data( dataset_cfg["name"], - dataset_path="", # Assuming load_data handles default path or it's in dataset_cfg nq_override=num_queries_to_use ) From 70ba50dbaa823349f8146f66ebe10dbe967a8ddc Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 22 May 2025 14:36:55 -0500 Subject: [PATCH 216/323] fix index wrapper build --- test/experiments/osdi2025/experiment_utils.py | 45 +++++++++++++++++++ .../numa_multi_query/configs/sift1m.yaml | 2 +- .../osdi2025/numa_multi_query/run.py | 9 ++-- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/test/experiments/osdi2025/experiment_utils.py b/test/experiments/osdi2025/experiment_utils.py index 9f935028..a4eff0b3 100644 --- a/test/experiments/osdi2025/experiment_utils.py +++ b/test/experiments/osdi2025/experiment_utils.py @@ -57,6 +57,51 @@ def prepare_quake_index( logger.info(f"Index saved to {index_file_path}") return idx + +def prepare_wrapper_index( + IndexClass: type, + index_file_path: Path, + base_vectors: torch.Tensor, + build_params: Dict[str, Any], + force_rebuild: bool = False, + load: bool = True +) -> object: # Returns an instance of the IndexClass + + idx_instance = IndexClass() + index_file_path.parent.mkdir(parents=True, exist_ok=True) + build_params_copy = build_params.copy() + + if index_file_path.exists() and not force_rebuild: + logger.info(f"Index file {index_file_path} exists and force_rebuild is False.") + if load: + logger.info(f"Loading index from {index_file_path}") + load_kwargs = {} + if "num_workers" in build_params_copy: + load_kwargs["num_workers"] = build_params_copy.get("num_workers") + if "use_numa" in build_params_copy: + load_kwargs["use_numa"] = build_params_copy.get("use_numa") + if "parent_num_workers" in build_params_copy: + load_kwargs["parent_num_workers"] = build_params_copy.get("parent_num_workers") + + idx_instance.load(str(index_file_path), **load_kwargs) + logger.info(f"Loaded index from {index_file_path} with load_kwargs: {load_kwargs}") + else: + logger.info(f"Index file {index_file_path} exists, but load=False. Returning new, non-loaded instance.") + else: + if force_rebuild and index_file_path.exists(): + logger.info(f"Force rebuilding index at {index_file_path}") + else: + logger.info(f"Building index at {index_file_path} (file did not exist).") + + idx_instance.build(base_vectors, **build_params_copy) + idx_instance.save(str(index_file_path)) + logger.info(f"Built and saved index to {index_file_path}") + + if load: + logger.info(f"Index built. Instance is considered ready as per build_params (load=True).") + + return idx_instance + def create_search_params(**attrs) -> SearchParams: sp = SearchParams() for k, v in attrs.items(): diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index 60c0c558..f79e5ab8 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -6,7 +6,7 @@ dataset: trials: 3 warmup: 1 -overwrite: false # Set to true to force all indexes to rerun +overwrite: true # Set to true to force all indexes to rerun force_rebuild: false # Set to true to force all indexes to rebuild indexes: diff --git a/test/experiments/osdi2025/numa_multi_query/run.py b/test/experiments/osdi2025/numa_multi_query/run.py index d607dd3b..52cdca8a 100644 --- a/test/experiments/osdi2025/numa_multi_query/run.py +++ b/test/experiments/osdi2025/numa_multi_query/run.py @@ -95,15 +95,12 @@ def run_experiment(cfg_path_str: str, output_dir_str: str): if quake_base_build_params: if not shared_quake_index_file.exists() or force_rebuild: # Respect overwrite for base index too logger.info(f"Building shared Quake base index at {shared_quake_index_file}...") - # Using common_utils.prepare_index for this specialized build. - # It requires IndexClass, build_params, base_vectors, path, force_rebuild. - common_utils.prepare_index( + common_utils.prepare_wrapper_index( IndexClass=QuakeWrapper, - index_build_params=quake_base_build_params, - base_vectors=base_vectors, index_file_path=shared_quake_index_file, + build_params=quake_base_build_params, + base_vectors=base_vectors, force_rebuild=force_rebuild, # Force rebuild if top-level overwrite is true - save_after_build=True ) logger.info(f"Shared Quake base index saved at {shared_quake_index_file}") else: From e27121bf14c65261fb2854d0debf1cae5ad1c3f7 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 22 May 2025 14:39:06 -0500 Subject: [PATCH 217/323] fix index wrapper build --- .../numa_multi_query/configs/sift1m.yaml | 59 ++++++++++++++++--- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index f79e5ab8..2b46bac1 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -55,19 +55,40 @@ indexes: nprobe: 20 batched_scan: true - - name: Quake_0_numa + - name: Quake_1_numa index: Quake build_params: nc: 1000 metric: l2 - num_workers: 0 + num_workers: 1 use_numa: true search_params: nprobe: 20 - batched_scan: false - n_threads: 16 + batched_scan: true - - name: Quake_1_numa + - name: Quake_4_numa + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 4 + use_numa: true + search_params: + nprobe: 20 + batched_scan: true + + - name: Quake_16_numa + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 16 + use_numa: true + search_params: + nprobe: 20 + batched_scan: true + + - name: Quake_1_numa_no_batch index: Quake build_params: nc: 1000 @@ -78,7 +99,18 @@ indexes: nprobe: 20 batched_scan: false - - name: Quake_4_numa + - name: Quake_2_numa_no_batch + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 2 + use_numa: true + search_params: + nprobe: 20 + batched_scan: false + + - name: Quake_4_numa_no_batch index: Quake build_params: nc: 1000 @@ -89,7 +121,19 @@ indexes: nprobe: 20 batched_scan: false - - name: Quake_16_numa + - name: Quake_8_numa_no_batch + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 8 + use_numa: true + search_params: + nprobe: 20 + batched_scan: false + + + - name: Quake_16_numa_no_batch index: Quake build_params: nc: 1000 @@ -100,6 +144,7 @@ indexes: nprobe: 20 batched_scan: false + # - name: FaissIVF # index: IVF # build_params: From 27fa3082696418ee0ab92a9f84b79e728bf928a4 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 22 May 2025 14:40:09 -0500 Subject: [PATCH 218/323] fix index wrapper build --- test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index 2b46bac1..ecc1bb8d 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -1,7 +1,7 @@ # numa_latency_experiment.yaml dataset: name: sift1m - num_queries: 1000 + num_queries: 10000 k: 100 trials: 3 From b696548bc6deef9ff53b86e856304a9629362574 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 22 May 2025 15:39:27 -0500 Subject: [PATCH 219/323] update multi_query --- test/experiments/osdi2025/experiment_utils.py | 229 ++++++++- .../numa_multi_query/configs/sift1m.yaml | 271 +++++----- .../osdi2025/numa_multi_query/run.py | 486 +++++++++--------- 3 files changed, 589 insertions(+), 397 deletions(-) diff --git a/test/experiments/osdi2025/experiment_utils.py b/test/experiments/osdi2025/experiment_utils.py index a4eff0b3..59822c44 100644 --- a/test/experiments/osdi2025/experiment_utils.py +++ b/test/experiments/osdi2025/experiment_utils.py @@ -5,8 +5,15 @@ from pathlib import Path import contextlib import sys -from typing import Dict, Any, List +from typing import Dict, Any, List, Callable, Union, Optional, Tuple import os +import multiprocessing +import subprocess +import threading +import json +import traceback +import signal +from datetime import datetime, timezone # For Glances metrics collection import torch import pandas as pd @@ -80,8 +87,6 @@ def prepare_wrapper_index( load_kwargs["num_workers"] = build_params_copy.get("num_workers") if "use_numa" in build_params_copy: load_kwargs["use_numa"] = build_params_copy.get("use_numa") - if "parent_num_workers" in build_params_copy: - load_kwargs["parent_num_workers"] = build_params_copy.get("parent_num_workers") idx_instance.load(str(index_file_path), **load_kwargs) logger.info(f"Loaded index from {index_file_path} with load_kwargs: {load_kwargs}") @@ -306,37 +311,221 @@ def save_results_df(records: list, output_path: Path): logger.info(f"Results saved to {output_path}") # Already logs @contextlib.contextmanager -def redirect_all_stdout_to_file(filepath: Path | str, mode: str = 'a'): +def redirect_all_stdout_to_file(filepath: Union[Path, str], mode: str = 'a'): original_python_stdout = sys.stdout original_c_stdout_fd = -1 saved_c_stdout_fd = -1 target_file = None + can_redirect_c_stdout = hasattr(sys.stdout, 'fileno') try: - original_c_stdout_fd = sys.stdout.fileno() - saved_c_stdout_fd = os.dup(original_c_stdout_fd) - + if can_redirect_c_stdout: + original_c_stdout_fd = sys.stdout.fileno() + saved_c_stdout_fd = os.dup(original_c_stdout_fd) target_file = open(filepath, mode) - target_file_fd = target_file.fileno() - - os.dup2(target_file_fd, original_c_stdout_fd) + if can_redirect_c_stdout: + os.dup2(target_file.fileno(), original_c_stdout_fd) sys.stdout = target_file - yield - except Exception: - # util_logger.error(f"Exception during stdout redirection: {e}", exc_info=False) # Removed for brevity - raise # Re-raise the exception + raise finally: - if sys.stdout == target_file : + if sys.stdout == target_file and target_file: sys.stdout.flush() - - if original_c_stdout_fd != -1 and saved_c_stdout_fd != -1: + if can_redirect_c_stdout and original_c_stdout_fd != -1 and saved_c_stdout_fd != -1: os.dup2(saved_c_stdout_fd, original_c_stdout_fd) - sys.stdout = original_python_stdout - if target_file: target_file.close() if saved_c_stdout_fd != -1: - os.close(saved_c_stdout_fd) \ No newline at end of file + os.close(saved_c_stdout_fd) + +_GLANCES_REFRESH_SEC = 1 +_GLANCES_MB = 1_048_576.0 + +def start_glances_minimal(tmp_json_path: Path) -> subprocess.Popen: + cmd = [ + "glances", "-q", f"-t{_GLANCES_REFRESH_SEC}", "--export", "json", + "--export-json-file", str(tmp_json_path), "--disable-plugin", "all", + "--enable-plugin", "cpu,mem,diskio,gpu", + # Consider adding process monitoring if useful: "--enable-plugin", "processcount,processlist" + # and then filter by PID if possible with glances export, though might be complex. + # For now, system-wide A,B,C,D metrics. + ] + # print(f"Starting Glances: {' '.join(cmd)}") # Goes to main process stdout if called from there + # If called from child, it'll go to child's log via redirection. + # Use preexec_fn=os.setsid to create a new process group for Glances + glances_process = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, text=True, preexec_fn=os.setsid) + time.sleep(2) # Allow Glances to start and write initial JSON + if glances_process.poll() is not None: # Check if Glances started successfully + stderr_output = glances_process.stderr.read() if glances_process.stderr else "No stderr." + raise RuntimeError(f"Glances failed to start. Exit code: {glances_process.returncode}. Stderr: {stderr_output}") + return glances_process + +def stop_glances_minimal(glances_process: Optional[subprocess.Popen]): + if glances_process and glances_process.poll() is None: + try: + os.killpg(os.getpgid(glances_process.pid), signal.SIGTERM) # Send SIGTERM to the entire process group + glances_process.wait(timeout=3) + except ProcessLookupError: pass # Process already dead + except subprocess.TimeoutExpired: + try: + os.killpg(os.getpgid(glances_process.pid), signal.SIGKILL) # Force kill + glances_process.wait(timeout=1) + except Exception: pass # Best effort + except Exception: pass # Other errors during stop + +def read_glances_json_minimal(tmp_json_path: Path) -> List[dict]: + if not tmp_json_path.exists(): return [] + text = tmp_json_path.read_text(encoding="utf-8").strip() + if not text: return [] + try: # Glances typically writes a list of JSON objects, or one object per file if snapshotting fast + data = json.loads(text) + return data if isinstance(data, list) else [data] # Ensure it's a list + except json.JSONDecodeError: # Handle cases where file might not be complete JSON list + records = [] + for line in text.splitlines(): # Try parsing line by line if not a single JSON doc + try: records.append(json.loads(line)) + except json.JSONDecodeError: pass # Ignore malformed lines + return records + +def extract_metrics_minimal(glances_record: Dict[str, Any]) -> Dict[str, Any]: + # Simplified extraction for A, B, C, D + cpu = glances_record.get("cpu", {}) + mem = glances_record.get("mem", {}) + diskio_list = glances_record.get("diskio", []) + gpu_list = glances_record.get("gpu", []) + + read_bytes = sum(d.get("read_bytes", 0) for d in diskio_list if isinstance(d, dict)) + write_bytes = sum(d.get("write_bytes", 0) for d in diskio_list if isinstance(d, dict)) + + # Assuming first GPU, if any. User script used 'proc' or 'utilization'. + gpu_util = np.nan + if gpu_list and isinstance(gpu_list[0], dict): + gpu_info = gpu_list[0] + gpu_util = gpu_info.get("proc", gpu_info.get("utilization", np.nan)) + + return { + "cpu_percent": cpu.get("total", cpu.get("user", 0) + cpu.get("system", 0)), # 'total' is often available + "mem_percent": mem.get("percent", np.nan), + "disk_read_mb_per_s": read_bytes / _GLANCES_MB / _GLANCES_REFRESH_SEC, # Approximate rate + "disk_write_mb_per_s": write_bytes / _GLANCES_MB / _GLANCES_REFRESH_SEC, # Approximate rate + "gpu_percent": gpu_util, + } +# --- End Glances Helpers --- + +def _glances_metric_collector_thread( + glances_tmp_json_path: Path, + metrics_output_ndjson_path: Path, + stop_event: threading.Event +): + # print(f"Glances metrics collector thread started. Output: {metrics_output_ndjson_path}") # Debug + with open(metrics_output_ndjson_path, "w") as mof: + while not stop_event.wait(timeout=_GLANCES_REFRESH_SEC): # Check event periodically + try: + glances_data_list = read_glances_json_minimal(glances_tmp_json_path) + # Glances --export-json-file overwrites the file. So we read the whole content. + # If it's a list, it might be multiple snapshots if glances is very fast relative to our read. + # Usually, it's one snapshot. + for record in glances_data_list: # Process each snapshot found + extracted = extract_metrics_minimal(record) + ts = datetime.now(timezone.utc).isoformat() + mof.write(json.dumps({"timestamp": ts, **extracted}) + "\n") + mof.flush() + except Exception as e: + # This print will go to the main process log for the child process + print(f"Glances metrics collector thread error: {e}", file=sys.stderr) # Use stderr + # print(f"Glances metrics collector thread stopped for {metrics_output_ndjson_path}") # Debug + +def _process_target_wrapper( + target_func: Callable, log_file_path: Path, env_vars: Optional[Dict[str, str]], + result_queue: multiprocessing.Queue, process_name_for_log: str, + enable_glances_monitoring: bool, args: Tuple, kwargs: Dict[str, Any] +): + current_process_name = multiprocessing.current_process().name + glances_proc: Optional[subprocess.Popen] = None + glances_tmp_json_file = log_file_path.with_suffix(".glances-temp.json") + metrics_output_file = log_file_path.with_suffix(".glances.ndjson") + metrics_thread: Optional[threading.Thread] = None + stop_glances_collection_event = threading.Event() + + try: + if env_vars: # Set environment variables first + for k, v in env_vars.items(): os.environ[str(k)] = str(v) + + if enable_glances_monitoring: + try: + print(f"[{current_process_name}] Starting Glances monitoring... Temp JSON: {glances_tmp_json_file}") + glances_proc = start_glances_minimal(glances_tmp_json_file) + metrics_thread = threading.Thread( + target=_glances_metric_collector_thread, + args=(glances_tmp_json_file, metrics_output_file, stop_glances_collection_event), + daemon=True + ) + metrics_thread.start() + print(f"[{current_process_name}] Glances monitoring and metrics collector thread started.") + except Exception as ge: + print(f"[{current_process_name}] WARNING: Failed to start Glances: {ge}", file=sys.stderr) + glances_proc = None # Ensure it's None if start failed + metrics_thread = None + + # with redirect_all_stdout_to_file(log_file_path): + print(f"--- Process {current_process_name} started. Main log: {log_file_path} ---") + if enable_glances_monitoring and glances_proc: + print(f"--- Glances metrics being collected to: {metrics_output_file} ---") + + result_data = target_func(*args, **kwargs) + result_queue.put({"status": "success", "data": result_data, "log_file": str(log_file_path), "metrics_file": str(metrics_output_file) if glances_proc else None}) + print(f"--- Process {current_process_name} finished successfully. ---") + + except Exception as e: + tb_str = traceback.format_exc() + error_message = f"Process {current_process_name} Exception: {e}\n{tb_str}" + try: + with open(log_file_path, 'a') as f_err: + f_err.write(f"\n--- PROCESS ERROR ({current_process_name}) ---\n{error_message}\n") + except: pass + result_queue.put({"status": "error", "message": str(e), "traceback": tb_str, "log_file": str(log_file_path), "metrics_file": str(metrics_output_file) if glances_proc else None}) + finally: + if metrics_thread and metrics_thread.is_alive(): + stop_glances_collection_event.set() + metrics_thread.join(timeout=5) # Wait for thread to finish + if glances_proc: + stop_glances_minimal(glances_proc) + if enable_glances_monitoring and glances_tmp_json_file.exists(): # Cleanup temp file + try: glances_tmp_json_file.unlink() + except OSError: pass + + +def run_operation_in_process( + target_func: Callable, args_tuple: Tuple = (), kwargs_dict: Optional[Dict[str, Any]] = None, + env_vars: Optional[Dict[str, str]] = None, log_file_path: Union[Path, str] = None, + process_name: Optional[str] = None, timeout_seconds: Optional[float] = None, + enable_glances: bool = False # New flag to control Glances +) -> Dict[str, Any]: + if kwargs_dict is None: kwargs_dict = {} + effective_process_name = process_name or target_func.__name__ + + if log_file_path is None: + log_file_path = Path(f"./{effective_process_name}_{os.getpid()}_process.log") + log_file_path = Path(log_file_path); log_file_path.parent.mkdir(parents=True, exist_ok=True) + + result_queue = multiprocessing.Queue(1) + process = multiprocessing.Process( + target=_process_target_wrapper, + args=(target_func, log_file_path, env_vars, result_queue, effective_process_name, enable_glances, args_tuple, kwargs_dict), + name=effective_process_name + ) + process.start() + result = None + try: + result = result_queue.get(timeout=timeout_seconds) + except multiprocessing.queues.Empty: # type: ignore + result = {"status": "error", "message": "Process timed out", "log_file": str(log_file_path)} + if process.is_alive(): + process.terminate(); process.join(5) + if process.is_alive(): process.kill() # type: ignore + except Exception as q_e: + result = {"status": "error", "message": f"Queue error: {q_e}", "log_file": str(log_file_path)} + process.join() + return result if result is not None else {"status": "error", "message": "Process ended without result", "log_file": str(log_file_path)} diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index ecc1bb8d..9216049d 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -1,7 +1,7 @@ # numa_latency_experiment.yaml dataset: name: sift1m - num_queries: 10000 + num_queries: 100 k: 100 trials: 3 @@ -10,148 +10,148 @@ overwrite: true # Set to true to force all indexes to rerun force_rebuild: false # Set to true to force all indexes to rebuild indexes: - - name: Quake_0 - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 0 - use_numa: false - search_params: - nprobe: 20 - batched_scan: true - - - name: Quake_1 - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 1 - parent_num_workers: 0 - use_numa: false - search_params: - nprobe: 20 - batched_scan: true - - - name: Quake_4 - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 4 - use_numa: false - search_params: - nprobe: 20 - batched_scan: true - - - name: Quake_16 - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 16 - use_numa: false - search_params: - nprobe: 20 - batched_scan: true - - - name: Quake_1_numa - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 1 - use_numa: true - search_params: - nprobe: 20 - batched_scan: true - - - name: Quake_4_numa - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 4 - use_numa: true - search_params: - nprobe: 20 - batched_scan: true - - - name: Quake_16_numa - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 16 - use_numa: true - search_params: - nprobe: 20 - batched_scan: true - - - name: Quake_1_numa_no_batch - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 1 - use_numa: true - search_params: - nprobe: 20 - batched_scan: false - - - name: Quake_2_numa_no_batch - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 2 - use_numa: true - search_params: - nprobe: 20 - batched_scan: false - - - name: Quake_4_numa_no_batch - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 4 - use_numa: true - search_params: - nprobe: 20 - batched_scan: false +# - name: Quake_0 +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 0 +# use_numa: false +# search_params: +# nprobe: 20 +# batched_scan: true +# +# - name: Quake_1 +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 1 +# use_numa: false +# search_params: +# nprobe: 20 +# batched_scan: true +# +# - name: Quake_4 +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 4 +# use_numa: false +# search_params: +# nprobe: 20 +# batched_scan: true +# +# - name: Quake_16 +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 16 +# use_numa: false +# search_params: +# nprobe: 20 +# batched_scan: true - - name: Quake_8_numa_no_batch - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 8 - use_numa: true - search_params: - nprobe: 20 - batched_scan: false +# - name: Quake_1_numa +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 1 +# use_numa: true +# search_params: +# nprobe: 20 +# batched_scan: true +# +# - name: Quake_4_numa +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 4 +# use_numa: true +# search_params: +# nprobe: 20 +# batched_scan: true +# +# - name: Quake_16_numa +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 16 +# use_numa: true +# search_params: +# nprobe: 20 +# batched_scan: true +# +# - name: Quake_1_numa_no_batch +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 1 +# use_numa: true +# search_params: +# nprobe: 20 +# batched_scan: false +# +# - name: Quake_2_numa_no_batch +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 2 +# use_numa: true +# search_params: +# nprobe: 20 +# batched_scan: false +# +# - name: Quake_4_numa_no_batch +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 4 +# use_numa: true +# search_params: +# nprobe: 20 +# batched_scan: false +# +# - name: Quake_8_numa_no_batch +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 8 +# use_numa: true +# search_params: +# nprobe: 20 +# batched_scan: false +# +# +# - name: Quake_16_numa_no_batch +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 16 +# use_numa: true +# search_params: +# nprobe: 20 +# batched_scan: false - - name: Quake_16_numa_no_batch - index: Quake + - name: FaissIVF + index: IVF build_params: nc: 1000 metric: l2 - num_workers: 16 - use_numa: true search_params: nprobe: 20 - batched_scan: false - - -# - name: FaissIVF -# index: IVF -# build_params: -# nc: 1000 -# metric: l2 -# search_params: -# nprobe: 15 + omp_num_threads_search: 1 # # - name: SCANN # index: SCANN @@ -167,6 +167,7 @@ indexes: # m: 64 # ef_construction: 128 # metric: l2 +## omp_num_threads_build: 16 # search_params: # ef_search: 24 # diff --git a/test/experiments/osdi2025/numa_multi_query/run.py b/test/experiments/osdi2025/numa_multi_query/run.py index 52cdca8a..dd8efb29 100644 --- a/test/experiments/osdi2025/numa_multi_query/run.py +++ b/test/experiments/osdi2025/numa_multi_query/run.py @@ -1,274 +1,276 @@ -#!/usr/bin/env python3 -""" -NUMA Multi-Query Batch Performance Benchmark -─────────────────────────────────────────── -Benchmarks Quake (with varying NUMA/worker settings) and other ANN indexes -for batch-query latency, per-phase breakdown (for Quake), and recall@k. -Results are cached. Outputs per-index CSVs, a unified CSV, and plots. - -This script tests how different configurations handle batches of queries, -focusing on Quake's behavior with NUMA-awareness and threading for parallel -processing of queries or internal operations. -""" -import logging # Standard library logging +# test/experiments/osdi2025/numa_multi_query/run.py + +import logging from pathlib import Path import numpy as np -import torch import pandas as pd import matplotlib.pyplot as plt -# time.time() is still used for the benchmark loop due to its specificity. +import torch +import os -# Common utilities import test.experiments.osdi2025.experiment_utils as common_utils - -# Quake specific imports -from quake.utils import compute_recall # compute_recall remains useful +from quake.utils import compute_recall from quake.index_wrappers.faiss_ivf import FaissIVF from quake.index_wrappers.faiss_hnsw import FaissHNSW -from quake.index_wrappers.quake import QuakeWrapper - -# Optional wrappers -try: - from quake.index_wrappers.scann import Scann -except ImportError: - Scann = None -try: - from quake.index_wrappers.diskann import DiskANNDynamic -except ImportError: - DiskANNDynamic = None -try: - from quake.index_wrappers.vamana import Vamana -except ImportError: - Vamana = None +from quake.index_wrappers.quake import QuakeWrapper # type: ignore + +try: from quake.index_wrappers.scann import Scann # type: ignore +except ImportError: Scann = None +try: from quake.index_wrappers.diskann import DiskANNDynamic # type: ignore +except ImportError: DiskANNDynamic = None +try: from quake.index_wrappers.vamana import Vamana # type: ignore +except ImportError: Vamana = None INDEX_CLASSES = { - "Quake": QuakeWrapper, - "IVF": FaissIVF, - "SCANN": Scann, - "HNSW": FaissHNSW, - "DiskANN": DiskANNDynamic, - "SVS": Vamana, # Assuming Vamana is the class for "SVS" + "Quake": QuakeWrapper, "IVF": FaissIVF, "SCANN": Scann, + "HNSW": FaissHNSW, "DiskANN": DiskANNDynamic, "SVS": Vamana, } - -# Setup logging (can be centralized in common_utils or main runner if preferred) -logging.basicConfig(level=logging.INFO, - format="%(asctime)s | %(levelname)7s | %(name)s | %(message)s", - datefmt="%H:%M:%S") -logger = logging.getLogger("numa_multi_query_exp") - +logger = logging.getLogger("numa_multi_query_orchestrator") + +def task_build_index( + index_config: dict, dataset_cfg: dict, global_run_params: dict, + index_file_path: Path +): + index_name = index_config["name"] + index_type_str = index_config["index"] + original_omp_threads = os.environ.get("OMP_NUM_THREADS") + + print(f"[{index_name} BUILD_TASK] Process ID: {os.getpid()}. Target file: {index_file_path}") + # Make a copy to safely pop omp_threads param + current_build_params = dict(index_config.get("build_params", {})) + omp_build_threads = str(current_build_params.pop("omp_num_threads_build", "1")) # Pop the param + os.environ["OMP_NUM_THREADS"] = omp_build_threads + print(f"[{index_name} BUILD_TASK] Set OMP_NUM_THREADS={omp_build_threads}.") + + base_vectors, _, _ = common_utils.load_data( + dataset_cfg["name"], nq_override=1) + + IndexCls = INDEX_CLASSES.get(index_type_str) + if IndexCls is None or (IndexCls == Scann and Scann is None): # type: ignore + if original_omp_threads is not None: os.environ["OMP_NUM_THREADS"] = original_omp_threads + else: os.environ.pop("OMP_NUM_THREADS", None) + return {"error": f"Index type '{index_type_str}' unavailable.", "index_file_path": str(index_file_path)} + + print(f"[{index_name} BUILD_TASK] Calling prepare_wrapper_index (build phase)...") + # current_build_params now does NOT contain omp_num_threads_build + idx_instance_for_build = common_utils.prepare_wrapper_index( + IndexCls, index_file_path, base_vectors, current_build_params, + global_run_params["force_rebuild_indices"], load=False + ) + del base_vectors + + if original_omp_threads is not None: os.environ["OMP_NUM_THREADS"] = original_omp_threads + else: os.environ.pop("OMP_NUM_THREADS", None) + + if idx_instance_for_build is None : + return {"error": f"Index build failed for {index_name}.", "index_file_path": str(index_file_path)} + + print(f"[{index_name} BUILD_TASK] Build/Save completed for {index_file_path}.") + return {"status": "success", "index_file_path": str(index_file_path)} + + +def task_search_index( + index_config: dict, dataset_cfg: dict, global_run_params: dict, + index_file_path: Path +): + index_name = index_config["name"] + index_type_str = index_config["index"] + original_omp_threads = os.environ.get("OMP_NUM_THREADS") + + print(f"[{index_name} SEARCH_TASK] Process ID: {os.getpid()}. Loading index from: {index_file_path}") + # These params are for loading the index instance, or for search + current_build_params_for_load = dict(index_config.get("build_params", {})) + current_search_params = dict(index_config.get("search_params", {})) + + # Pop omp_num_threads_search before passing current_search_params to idx_instance.search + omp_search_threads = str(current_search_params.pop("omp_num_threads_search", "1")) + os.environ["OMP_NUM_THREADS"] = omp_search_threads + print(f"[{index_name} SEARCH_TASK] Set OMP_NUM_THREADS={omp_search_threads}.") + + _, query_vectors, gt_vectors = common_utils.load_data( + dataset_cfg["name"], nq_override=dataset_cfg.get("num_queries")) + + IndexCls = INDEX_CLASSES.get(index_type_str) + if IndexCls is None or (IndexCls == Scann and Scann is None): # type: ignore + if original_omp_threads is not None: os.environ["OMP_NUM_THREADS"] = original_omp_threads + else: os.environ.pop("OMP_NUM_THREADS", None) + return {"error": f"Index type '{index_type_str}' unavailable for search."} + + if not Path(index_file_path).exists(): # Ensure Path object for exists() + if original_omp_threads is not None: os.environ["OMP_NUM_THREADS"] = original_omp_threads + else: os.environ.pop("OMP_NUM_THREADS", None) + return {"error": f"Index file {index_file_path} not found for search."} + + idx_instance = IndexCls() + load_kwargs = {} + # Params like num_workers for Quake load are typically in "build_params" section of YAML + if "num_workers" in current_build_params_for_load: load_kwargs["num_workers"] = current_build_params_for_load.get("num_workers") + if "use_numa" in current_build_params_for_load: load_kwargs["use_numa"] = current_build_params_for_load.get("use_numa") + if "parent_num_workers" in current_build_params_for_load: load_kwargs["parent_num_workers"] = current_build_params_for_load.get("parent_num_workers") + + print(f"[{index_name} SEARCH_TASK] Loading index with kwargs: {load_kwargs}") + idx_instance.load(str(index_file_path), **load_kwargs) + + k_val = global_run_params["k_val"] + print(f"[{index_name} SEARCH_TASK] Warmup ({global_run_params['num_warmup']} iterations)...") + # current_search_params now does NOT contain omp_num_threads_search + for _ in range(global_run_params['num_warmup']): + _ = idx_instance.search(query_vectors, k_val, **current_search_params) + + trial_latencies_ms = [] + trial_recalls = [] + print(f"[{index_name} SEARCH_TASK] Benchmarking ({global_run_params['num_trials']} trials)...") + for i in range(global_run_params['num_trials']): + # current_search_params now does NOT contain omp_num_threads_search + search_result = idx_instance.search(query_vectors, k_val, **current_search_params) + latency_ms = np.nan + timing_info = getattr(search_result, "timing_info", None) + if timing_info and hasattr(timing_info, "total_time_ns"): latency_ms = getattr(timing_info, "total_time_ns") / 1e6 + elif timing_info and hasattr(timing_info, "child_total_time_ns"): latency_ms = getattr(timing_info, "child_total_time_ns") / 1e6 + trial_latencies_ms.append(latency_ms) + + recall_val = np.nan + if gt_vectors is not None and hasattr(search_result, "ids"): + try: recall_val = float(compute_recall(search_result.ids, gt_vectors, k_val).mean()) + except Exception: pass + trial_recalls.append(recall_val) + + if original_omp_threads is not None: os.environ["OMP_NUM_THREADS"] = original_omp_threads + else: os.environ.pop("OMP_NUM_THREADS", None) + + print(f"[{index_name} SEARCH_TASK] Individual trial results (Latency, Recall@K={k_val}):") + for i in range(len(trial_latencies_ms)): + lat_str = f"{trial_latencies_ms[i]:.3f}ms" if not np.isnan(trial_latencies_ms[i]) else "N/A" + rec_str = f"{trial_recalls[i]:.4f}" if not np.isnan(trial_recalls[i]) else "N/A" + print(f" Trial {i+1}: Latency={lat_str}, Recall={rec_str}") + + final_row = {"index_name_from_process": index_name} + valid_latencies = [l for l in trial_latencies_ms if not np.isnan(l)] + valid_recalls = [r for r in trial_recalls if not np.isnan(r)] + final_row["mean_latency_ms"] = float(np.mean(valid_latencies)) if valid_latencies else np.nan + final_row["std_latency_ms"] = float(np.std(valid_latencies)) if valid_latencies else np.nan + final_row[f"mean_recall_at_{k_val}"] = float(np.mean(valid_recalls)) if valid_recalls else np.nan + final_row[f"std_recall_at_{k_val}"] = float(np.std(valid_recalls)) if valid_recalls else np.nan + + n_threads_or_workers = int(omp_search_threads) + if index_type_str == "Quake" and "num_workers" in current_build_params_for_load : + n_threads_or_workers = current_build_params_for_load.get("num_workers", n_threads_or_workers) + final_row["n_config_concurrency"] = n_threads_or_workers + + print(f"[{index_name} SEARCH_TASK] Benchmark task finished.") + return final_row def run_experiment(cfg_path_str: str, output_dir_str: str): + logging.basicConfig(level=logging.INFO, format="%(asctime)s|%(levelname)7s|%(name)s| %(message)s", datefmt="%H:%M:%S") + logger.info(f"Orchestrator: Config: {cfg_path_str}, Output: {output_dir_str}") + cfg = common_utils.load_config(cfg_path_str) + main_output_dir = Path(output_dir_str); main_output_dir.mkdir(parents=True, exist_ok=True) + process_logs_dir = main_output_dir / "process_logs"; process_logs_dir.mkdir(parents=True, exist_ok=True) + individual_index_files_dir = main_output_dir / "individual_indices"; + individual_index_files_dir.mkdir(parents=True, exist_ok=True) dataset_cfg = cfg["dataset"] - num_queries_to_use = dataset_cfg["num_queries"] - k_val = dataset_cfg["k"] - - num_trials = cfg.get("trials", 5) - num_warmup = cfg.get("warmup", 1) # Reduced default warmup, can be configured + global_run_params = { + "num_trials": cfg.get("trials", 3), "num_warmup": cfg.get("warmup", 1), "k_val": dataset_cfg["k"], + "force_overwrite_results": cfg.get("overwrite", False), + "force_rebuild_indices": cfg.get("force_rebuild", False), + "enable_glances": cfg.get("enable_glances_monitoring", False) + } indexes_config_list = cfg["indexes"] - output_csv_name = cfg.get("output", {}).get("results_csv", "numa_multi_query_results.csv") - force_overwrite = cfg.get("overwrite", False) - force_rebuild = cfg.get("force_rebuild", False) - - main_output_dir = Path(output_dir_str) - main_output_dir.mkdir(parents=True, exist_ok=True) - - logger.info(f"Loading dataset '{dataset_cfg['name']}'...") - # Use common_utils.load_data, pass num_queries_to_use for slicing - base_vectors, query_vectors, gt_vectors = common_utils.load_data( - dataset_cfg["name"], - nq_override=num_queries_to_use - ) - - # --- Build shared Quake base index once (specific to this experiment script) --- - quake_base_build_params = None - shared_quake_index_file = main_output_dir / "Quake_shared_base_index.bin" # More descriptive name - - for idx_c in indexes_config_list: - if idx_c["index"] == "Quake": - # These are params for the *base* index, stripped of worker/NUMA specifics - quake_base_build_params = {k: v for k, v in idx_c.get("build_params", {}).items() - if k not in ["num_workers", "use_numa", "parent_num_workers"]} - break - - if quake_base_build_params: - if not shared_quake_index_file.exists() or force_rebuild: # Respect overwrite for base index too - logger.info(f"Building shared Quake base index at {shared_quake_index_file}...") - common_utils.prepare_wrapper_index( - IndexClass=QuakeWrapper, - index_file_path=shared_quake_index_file, - build_params=quake_base_build_params, - base_vectors=base_vectors, - force_rebuild=force_rebuild, # Force rebuild if top-level overwrite is true - ) - logger.info(f"Shared Quake base index saved at {shared_quake_index_file}") - else: - logger.info(f"Using existing shared Quake base index from {shared_quake_index_file}") + output_csv_name = cfg.get("output", {}).get("results_csv", "numa_multi_query_results.csv") # Changed from single_query all_experiment_rows = [] - for idx_conf in indexes_config_list: index_name = idx_conf["name"] - index_type_str = idx_conf["index"] - current_build_params = dict(idx_conf.get("build_params", {})) - current_search_params = dict(idx_conf.get("search_params", {})) + index_file_path = individual_index_files_dir / f"{index_name}_index.bin" + per_index_final_results_csv = main_output_dir / f"{index_name}_final_results.csv" - IndexCls = INDEX_CLASSES.get(index_type_str) - if IndexCls is None or (IndexCls == Scann and Scann is None): # Handle optional Scann - logger.warning(f"Index type '{index_type_str}' for '{index_name}' is not available or unknown. Skipping.") - continue - - per_index_csv_path = main_output_dir / f"{index_name}_results.csv" - - # Determine actual index file path (shared for Quake, specific for others) - actual_index_file_path = shared_quake_index_file if index_type_str == "Quake" else main_output_dir / f"{index_name}_index.bin" - - if per_index_csv_path.exists() and not force_overwrite: - logger.info(f"Results for {index_name} exist. Use overwrite:true to rerun. Loading cached.") + if per_index_final_results_csv.exists() and not global_run_params["force_overwrite_results"]: try: - # Ensure only one row is taken if multiple exist from partial runs. - cached_df = pd.read_csv(per_index_csv_path) - if not cached_df.empty: - all_experiment_rows.append(cached_df.iloc[0].to_dict()) - except Exception as e: - logger.error(f"Could not load cached results for {index_name} from {per_index_csv_path}: {e}") + all_experiment_rows.append(pd.read_csv(per_index_final_results_csv).iloc[0].to_dict()) + logger.info(f"Loaded cached final results for {index_name}.") + continue + except Exception as e: logger.warning(f"Could not load cached final results for {index_name}: {e}. Re-running.") + + logger.info(f"Orchestrator: Submitting BUILD task for index: {index_name}") + build_log_file = process_logs_dir / f"{index_name}_build_process.log" + build_env_vars = idx_conf.get("build_env_vars", {}) + process_timeout = idx_conf.get("process_timeout", cfg.get("default_process_timeout", 7200)) + + build_result = common_utils.run_operation_in_process( + task_build_index, (idx_conf, dataset_cfg, global_run_params, index_file_path), + env_vars=build_env_vars, log_file_path=build_log_file, process_name=f"BuildTask_{index_name}", + timeout_seconds=process_timeout, enable_glances=global_run_params["enable_glances"] + ) + + if not (build_result["status"] == "success" and build_result.get("data", {}).get("status") == "success"): + err_msg = build_result.get('message', build_result.get('data', {}).get('error', 'Build task failed')) + logger.error(f"BUILD task for {index_name} failed. Log: {build_result.get('log_file')}. Error: {err_msg}") + all_experiment_rows.append({"index": index_name, "error": f"Build Failed: {err_msg}", "mean_latency_ms": np.nan, f"mean_recall_at_{global_run_params['k_val']}": np.nan}) continue - logger.info(f"Processing index: {index_name} (Type: {index_type_str})") + logger.info(f"BUILD task for {index_name} succeeded. Index file: {build_result.get('data',{}).get('index_file_path')}") + built_index_file_path = Path(build_result.get("data",{}).get("index_file_path", index_file_path)) # Use confirmed path - # Load or build index - idx_instance = None - if index_type_str == "Quake": - if not shared_quake_index_file.exists(): - logger.error(f"Shared Quake base index {shared_quake_index_file} not found for {index_name}. Skipping.") - continue - idx_instance = QuakeWrapper() - # These are load-time parameters for Quake specified in each config entry - quake_load_kwargs = { - k: current_build_params[k] for k in - ("use_numa", "num_workers", "parent_num_workers") if k in current_build_params - } - logger.info(f"Loading Quake index {index_name} from shared base with params: {quake_load_kwargs}") - idx_instance.load(str(shared_quake_index_file), **quake_load_kwargs) - else: # For non-Quake indexes - # DiskANN needs metric popped from build_params before load, if present during build - diskann_load_params = current_build_params.copy() - if index_type_str == "DiskANN": diskann_load_params.pop("metric", None) - - idx_instance = common_utils.prepare_index( - IndexClass=IndexCls, - index_build_params=current_build_params, - base_vectors=base_vectors, # Needed if building - index_file_path=actual_index_file_path, - force_rebuild=force_rebuild, # Rebuild this specific non-Quake index if needed - load_kwargs=diskann_load_params if index_type_str == "DiskANN" else None, - save_after_build=True - ) - - if idx_instance is None: # Should not happen if logic is correct - logger.error(f"Failed to load or build index {index_name}. Skipping.") - continue + logger.info(f"Orchestrator: Submitting SEARCH task for index: {index_name}") + search_log_file = process_logs_dir / f"{index_name}_search_process.log" + search_env_vars = idx_conf.get("search_env_vars", {}) - logger.info(f"Warmup for {index_name} ({num_warmup} iterations)...") - for _ in range(num_warmup): # Batched search for warmup - _ = idx_instance.search(query_vectors, k_val, **current_search_params) - - # Benchmark Trials (batch search) - trial_timings = { - "child_total_ms": [], "parent_total_ms": [], "recall": [], - "child_buffer_init_ms": [], "child_copy_query_ms": [], "child_enqueue_ms": [], - "child_wait_ms": [], "child_aggregate_ms": [], - "parent_buffer_init_ms": [], "parent_copy_query_ms": [], "parent_enqueue_ms": [], - "parent_wait_ms": [], "parent_aggregate_ms": [] - } - - logger.info(f"Running benchmark for {index_name} ({num_trials} trials)...") - for t_idx in range(num_trials): - search_result = idx_instance.search(query_vectors, k_val, **current_search_params) - timing_info = search_result.timing_info # Assuming this is always present for Quake - - # Collect detailed timings if available (primarily for Quake) - for key in trial_timings: - if key.startswith("child_") and hasattr(timing_info, key.replace("_ms", "_time_ns").replace("child_", "")): - trial_timings[key].append(getattr(timing_info, key.replace("_ms", "_time_ns").replace("child_", "")) / 1e6) - elif key.startswith("parent_") and hasattr(timing_info, "parent_info") and timing_info.parent_info: - parent_attr_name = key.replace("_ms", "_time_ns").replace("parent_", "") - if hasattr(timing_info.parent_info, parent_attr_name): - trial_timings[key].append(getattr(timing_info.parent_info, parent_attr_name) / 1e6) - else: - trial_timings[key].append(0.0) # Parent info might not have all fields - elif key == "recall" and gt_vectors is not None: - pred_ids = search_result.ids - current_recall = float(compute_recall(pred_ids, gt_vectors, k_val).mean()) - trial_timings["recall"].append(current_recall) - - log_msg_trial = f" [{index_name} trial {t_idx+1}/{num_trials}] " - if trial_timings["child_total_ms"]: log_msg_trial += f"child_total={trial_timings['child_total_ms'][-1]:.2f}ms " - if trial_timings["parent_total_ms"] and trial_timings['parent_total_ms'][-1] > 0: log_msg_trial += f"parent_total={trial_timings['parent_total_ms'][-1]:.2f}ms " - if trial_timings["recall"]: log_msg_trial += f"| recall@{k_val}={trial_timings['recall'][-1]:.4f}" - logger.info(log_msg_trial) - - - # Aggregate metrics from trials - final_row = {"index": index_name, "n_workers": current_build_params.get("num_workers")} - for key, values in trial_timings.items(): - if values: - final_row[f"mean_{key}"] = float(np.mean(values)) - final_row[f"std_{key}"] = float(np.std(values)) - else: # Handle cases where timings might not be available (e.g. non-Quake, or no GT) - final_row[f"mean_{key}"] = np.nan - final_row[f"std_{key}"] = np.nan - - # Rename for CSV consistency if needed, e.g., mean_child_total_ms to mean_latency_ms - if "mean_child_total_ms" in final_row: - final_row["mean_latency_ms"] = final_row.pop("mean_child_total_ms") - if "std_child_total_ms" in final_row: - final_row["std_latency_ms"] = final_row.pop("std_child_total_ms") - if f"mean_recall" in final_row: # Ensure recall key matches expected format - final_row[f"recall_at_{k_val}"] = final_row.pop(f"mean_recall") - if f"std_recall" in final_row: # std for recall might not be needed in final summary - final_row.pop(f"std_recall") - - - all_experiment_rows.append(final_row) - common_utils.save_results_csv(pd.DataFrame([final_row]), per_index_csv_path) # Save per-index - - # Save unified CSV for all indexes - if not all_experiment_rows: - logger.warning("No results collected. Skipping final CSV and plots.") - return + search_process_result = common_utils.run_operation_in_process( + task_search_index, (idx_conf, dataset_cfg, global_run_params, built_index_file_path), + env_vars=search_env_vars, log_file_path=search_log_file, process_name=f"SearchTask_{index_name}", + timeout_seconds=process_timeout, enable_glances=global_run_params["enable_glances"] + ) + if search_process_result["status"] == "success" and isinstance(search_process_result["data"], dict) and "error" not in search_process_result["data"]: + logger.info(f"Search task {index_name} succeeded. Log: {search_process_result.get('log_file')}. Metrics: {search_process_result.get('metrics_file')}") + result_data_row = search_process_result["data"]; result_data_row["index"] = index_name + all_experiment_rows.append(result_data_row) + common_utils.save_results_csv(pd.DataFrame([result_data_row]), per_index_final_results_csv) + else: + err_msg = search_process_result.get('message', search_process_result.get('data', {}).get('error','Search task failed')) + logger.error(f"Search task {index_name} failed. Log: {search_process_result.get('log_file')}. Metrics: {search_process_result.get('metrics_file')}. Error: {err_msg}") + all_experiment_rows.append({"index": index_name, "error": f"Search Failed: {err_msg}", "mean_latency_ms": np.nan, f"mean_recall_at_{global_run_params['k_val']}": np.nan}) + + if not all_experiment_rows: logger.warning("No results. Skipping CSV/plots."); return final_df = pd.DataFrame(all_experiment_rows) + if 'index' not in final_df.columns and 'index_name_from_process' in final_df.columns: + final_df.rename(columns={'index_name_from_process': 'index'}, inplace=True) + final_df['index'] = final_df['index'].fillna(final_df.get('index_name_from_process', "unknown_index")) + unified_csv_path = main_output_dir / output_csv_name - common_utils.save_results_csv(final_df, unified_csv_path) - logger.info(f"Unified results written to {unified_csv_path}") + common_utils.save_results_csv(final_df, unified_csv_path); logger.info(f"Unified results: {unified_csv_path}") - # Plotting (remains specific to this experiment's needs) plot_suffix = Path(output_csv_name).stem - - # Plot 1: Batch total latency (child_total_ms) vs. Num Workers - if "mean_latency_ms" in final_df.columns and "n_workers" in final_df.columns: - plt.figure(figsize=(8,6)) - for idx_name_plot in final_df["index"].unique(): - subset = final_df[final_df["index"] == idx_name_plot].sort_values(by="n_workers") - label = idx_name_plot # Simplified label - yerr_values = subset["std_latency_ms"] if "std_latency_ms" in subset else None - plt.errorbar( - subset["n_workers"].astype(int), - subset["mean_latency_ms"], - yerr=yerr_values, - marker="o", capsize=4, label=label, alpha=0.8, linestyle='-' - ) - # plt.xscale("symlog", base=2) # May not be ideal if n_workers are not powers of 2 or include 0 - plt.xlabel("Num Workers (Configuration)") - plt.ylabel(f"Mean Batch Query Latency (ms) - Child Total") - plt.title(f"NUMA Multi-Query: Latency vs. Num Workers ({dataset_cfg['name']})") - plt.legend(title="Index Configuration", bbox_to_anchor=(1.05, 1), loc='upper left') - plt.grid(True, linestyle=':', alpha=0.7) - plt.tight_layout(rect=[0,0,0.8,1]) # Adjust for legend - plt.savefig(main_output_dir / f"{plot_suffix}_batch_latency.png", dpi=150) - logger.info(f"Latency plot saved to {main_output_dir / f'{plot_suffix}_batch_latency.png'}") - plt.close() - - logger.info("NUMA Multi-Query experiment finished.") \ No newline at end of file + plot_x_param = "n_config_concurrency" + # Ensure 'index' column is valid before attempting groupby for plotting + plot_df = final_df.dropna(subset=['index', plot_x_param]).copy() + if not plot_df.empty: + plot_df.loc[:, plot_x_param] = pd.to_numeric(plot_df[plot_x_param], errors='coerce').fillna(-1).astype(int) + k_val_plot = global_run_params['k_val'] + + if "mean_latency_ms" in plot_df.columns: + try: + plt.figure(figsize=(8,6)); + for name, group in plot_df.groupby("index"): + group = group.sort_values(by=plot_x_param) + plt.errorbar(group[plot_x_param], group["mean_latency_ms"], yerr=group.get("std_latency_ms"), marker="o", label=name) + plt.xlabel("Configured Concurrency"); plt.ylabel("Mean Latency (ms)"); plt.title(f"Latency ({dataset_cfg['name']})") + plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left'); plt.grid(True); plt.tight_layout(rect=[0,0,0.8,1]) + plt.savefig(main_output_dir / f"{plot_suffix}_latency.png"); plt.close(); logger.info(f"Latency plot saved.") + except Exception as e: logger.error(f"Latency plot error: {e}") + + recall_col = f"mean_recall_at_{k_val_plot}" + if recall_col in plot_df.columns: + try: + plt.figure(figsize=(8,6)); + for name, group in plot_df.groupby("index"): + group = group.sort_values(by=plot_x_param) + plt.errorbar(group[plot_x_param], group[recall_col], yerr=group.get(f"std_recall_at_{k_val_plot}"), marker="o", label=name) + plt.xlabel("Configured Concurrency"); plt.ylabel(f"Mean Recall@{k_val_plot}"); plt.title(f"Recall ({dataset_cfg['name']})") + plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left'); plt.grid(True); plt.tight_layout(rect=[0,0,0.8,1]); plt.ylim(0, 1.05) + plt.savefig(main_output_dir / f"{plot_suffix}_recall.png"); plt.close(); logger.info(f"Recall plot saved.") + except Exception as e: logger.error(f"Recall plot error: {e}") + else: logger.warning("Not enough data for plotting after filtering.") + logger.info("Experiment orchestration finished.") \ No newline at end of file From a81a9718f93cc91889b76a163c2f2e2e31084bf7 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 22 May 2025 15:45:21 -0500 Subject: [PATCH 220/323] update multi_query --- .../numa_multi_query/configs/sift1m.yaml | 264 +++++++++--------- 1 file changed, 132 insertions(+), 132 deletions(-) diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index 9216049d..d8572fed 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -1,7 +1,7 @@ # numa_latency_experiment.yaml dataset: name: sift1m - num_queries: 100 + num_queries: 1000 k: 100 trials: 3 @@ -10,138 +10,138 @@ overwrite: true # Set to true to force all indexes to rerun force_rebuild: false # Set to true to force all indexes to rebuild indexes: -# - name: Quake_0 -# index: Quake -# build_params: -# nc: 1000 -# metric: l2 -# num_workers: 0 -# use_numa: false -# search_params: -# nprobe: 20 -# batched_scan: true -# -# - name: Quake_1 -# index: Quake -# build_params: -# nc: 1000 -# metric: l2 -# num_workers: 1 -# use_numa: false -# search_params: -# nprobe: 20 -# batched_scan: true -# -# - name: Quake_4 -# index: Quake -# build_params: -# nc: 1000 -# metric: l2 -# num_workers: 4 -# use_numa: false -# search_params: -# nprobe: 20 -# batched_scan: true -# -# - name: Quake_16 -# index: Quake -# build_params: -# nc: 1000 -# metric: l2 -# num_workers: 16 -# use_numa: false -# search_params: -# nprobe: 20 -# batched_scan: true + - name: Quake_0 + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 0 + use_numa: false + search_params: + nprobe: 20 + batched_scan: true -# - name: Quake_1_numa -# index: Quake -# build_params: -# nc: 1000 -# metric: l2 -# num_workers: 1 -# use_numa: true -# search_params: -# nprobe: 20 -# batched_scan: true -# -# - name: Quake_4_numa -# index: Quake -# build_params: -# nc: 1000 -# metric: l2 -# num_workers: 4 -# use_numa: true -# search_params: -# nprobe: 20 -# batched_scan: true -# -# - name: Quake_16_numa -# index: Quake -# build_params: -# nc: 1000 -# metric: l2 -# num_workers: 16 -# use_numa: true -# search_params: -# nprobe: 20 -# batched_scan: true -# -# - name: Quake_1_numa_no_batch -# index: Quake -# build_params: -# nc: 1000 -# metric: l2 -# num_workers: 1 -# use_numa: true -# search_params: -# nprobe: 20 -# batched_scan: false -# -# - name: Quake_2_numa_no_batch -# index: Quake -# build_params: -# nc: 1000 -# metric: l2 -# num_workers: 2 -# use_numa: true -# search_params: -# nprobe: 20 -# batched_scan: false -# -# - name: Quake_4_numa_no_batch -# index: Quake -# build_params: -# nc: 1000 -# metric: l2 -# num_workers: 4 -# use_numa: true -# search_params: -# nprobe: 20 -# batched_scan: false -# -# - name: Quake_8_numa_no_batch -# index: Quake -# build_params: -# nc: 1000 -# metric: l2 -# num_workers: 8 -# use_numa: true -# search_params: -# nprobe: 20 -# batched_scan: false -# -# -# - name: Quake_16_numa_no_batch -# index: Quake -# build_params: -# nc: 1000 -# metric: l2 -# num_workers: 16 -# use_numa: true -# search_params: -# nprobe: 20 -# batched_scan: false + - name: Quake_1 + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 1 + use_numa: false + search_params: + nprobe: 20 + batched_scan: true + + - name: Quake_4 + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 4 + use_numa: false + search_params: + nprobe: 20 + batched_scan: true + + - name: Quake_16 + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 16 + use_numa: false + search_params: + nprobe: 20 + batched_scan: true + + - name: Quake_1_numa + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 1 + use_numa: true + search_params: + nprobe: 20 + batched_scan: true + + - name: Quake_4_numa + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 4 + use_numa: true + search_params: + nprobe: 20 + batched_scan: true + + - name: Quake_16_numa + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 16 + use_numa: true + search_params: + nprobe: 20 + batched_scan: true + + - name: Quake_1_numa_no_batch + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 1 + use_numa: true + search_params: + nprobe: 20 + batched_scan: false + + - name: Quake_2_numa_no_batch + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 2 + use_numa: true + search_params: + nprobe: 20 + batched_scan: false + + - name: Quake_4_numa_no_batch + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 4 + use_numa: true + search_params: + nprobe: 20 + batched_scan: false + + - name: Quake_8_numa_no_batch + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 8 + use_numa: true + search_params: + nprobe: 20 + batched_scan: false + + + - name: Quake_16_numa_no_batch + index: Quake + build_params: + nc: 1000 + metric: l2 + num_workers: 16 + use_numa: true + search_params: + nprobe: 20 + batched_scan: false - name: FaissIVF From ba3963bec8cefa83a0b2857789ad1cdf618d6ed5 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 22 May 2025 20:16:52 -0500 Subject: [PATCH 221/323] update multi_query --- .../numa_multi_query/configs/sift1m.yaml | 103 +----------------- .../osdi2025/numa_multi_query/run.py | 70 +++++------- 2 files changed, 28 insertions(+), 145 deletions(-) diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index d8572fed..70a20c64 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -10,39 +10,6 @@ overwrite: true # Set to true to force all indexes to rerun force_rebuild: false # Set to true to force all indexes to rebuild indexes: - - name: Quake_0 - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 0 - use_numa: false - search_params: - nprobe: 20 - batched_scan: true - - - name: Quake_1 - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 1 - use_numa: false - search_params: - nprobe: 20 - batched_scan: true - - - name: Quake_4 - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 4 - use_numa: false - search_params: - nprobe: 20 - batched_scan: true - - name: Quake_16 index: Quake build_params: @@ -54,28 +21,6 @@ indexes: nprobe: 20 batched_scan: true - - name: Quake_1_numa - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 1 - use_numa: true - search_params: - nprobe: 20 - batched_scan: true - - - name: Quake_4_numa - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 4 - use_numa: true - search_params: - nprobe: 20 - batched_scan: true - - name: Quake_16_numa index: Quake build_params: @@ -87,51 +32,6 @@ indexes: nprobe: 20 batched_scan: true - - name: Quake_1_numa_no_batch - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 1 - use_numa: true - search_params: - nprobe: 20 - batched_scan: false - - - name: Quake_2_numa_no_batch - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 2 - use_numa: true - search_params: - nprobe: 20 - batched_scan: false - - - name: Quake_4_numa_no_batch - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 4 - use_numa: true - search_params: - nprobe: 20 - batched_scan: false - - - name: Quake_8_numa_no_batch - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 8 - use_numa: true - search_params: - nprobe: 20 - batched_scan: false - - - name: Quake_16_numa_no_batch index: Quake build_params: @@ -143,7 +43,6 @@ indexes: nprobe: 20 batched_scan: false - - name: FaissIVF index: IVF build_params: @@ -151,7 +50,7 @@ indexes: metric: l2 search_params: nprobe: 20 - omp_num_threads_search: 1 + omp_num_threads_search: 16 # # - name: SCANN # index: SCANN diff --git a/test/experiments/osdi2025/numa_multi_query/run.py b/test/experiments/osdi2025/numa_multi_query/run.py index dd8efb29..603610eb 100644 --- a/test/experiments/osdi2025/numa_multi_query/run.py +++ b/test/experiments/osdi2025/numa_multi_query/run.py @@ -7,6 +7,7 @@ import matplotlib.pyplot as plt import torch import os +import faiss # Import faiss at the top level as it's now a hard dependency for thread setting import test.experiments.osdi2025.experiment_utils as common_utils from quake.utils import compute_recall @@ -27,41 +28,37 @@ } logger = logging.getLogger("numa_multi_query_orchestrator") +def _apply_faiss_thread_settings(config_threads_str: str, task_name_info: str): + num_threads = int(config_threads_str) + faiss.omp_set_num_threads(num_threads) + print(f"[{task_name_info}] Called faiss.omp_set_num_threads({num_threads}).") + + def task_build_index( index_config: dict, dataset_cfg: dict, global_run_params: dict, index_file_path: Path ): index_name = index_config["name"] - index_type_str = index_config["index"] - original_omp_threads = os.environ.get("OMP_NUM_THREADS") print(f"[{index_name} BUILD_TASK] Process ID: {os.getpid()}. Target file: {index_file_path}") - # Make a copy to safely pop omp_threads param current_build_params = dict(index_config.get("build_params", {})) - omp_build_threads = str(current_build_params.pop("omp_num_threads_build", "1")) # Pop the param - os.environ["OMP_NUM_THREADS"] = omp_build_threads - print(f"[{index_name} BUILD_TASK] Set OMP_NUM_THREADS={omp_build_threads}.") + omp_build_threads_config_val = str(current_build_params.pop("omp_num_threads_build", "1")) + + _apply_faiss_thread_settings(omp_build_threads_config_val, f"{index_name} BUILD_TASK") base_vectors, _, _ = common_utils.load_data( dataset_cfg["name"], nq_override=1) - IndexCls = INDEX_CLASSES.get(index_type_str) + IndexCls = INDEX_CLASSES.get(index_config["index"]) if IndexCls is None or (IndexCls == Scann and Scann is None): # type: ignore - if original_omp_threads is not None: os.environ["OMP_NUM_THREADS"] = original_omp_threads - else: os.environ.pop("OMP_NUM_THREADS", None) - return {"error": f"Index type '{index_type_str}' unavailable.", "index_file_path": str(index_file_path)} + return {"error": f"Index type '{index_config['index']}' unavailable.", "index_file_path": str(index_file_path)} - print(f"[{index_name} BUILD_TASK] Calling prepare_wrapper_index (build phase)...") - # current_build_params now does NOT contain omp_num_threads_build idx_instance_for_build = common_utils.prepare_wrapper_index( IndexCls, index_file_path, base_vectors, current_build_params, global_run_params["force_rebuild_indices"], load=False ) del base_vectors - if original_omp_threads is not None: os.environ["OMP_NUM_THREADS"] = original_omp_threads - else: os.environ.pop("OMP_NUM_THREADS", None) - if idx_instance_for_build is None : return {"error": f"Index build failed for {index_name}.", "index_file_path": str(index_file_path)} @@ -75,54 +72,43 @@ def task_search_index( ): index_name = index_config["name"] index_type_str = index_config["index"] - original_omp_threads = os.environ.get("OMP_NUM_THREADS") print(f"[{index_name} SEARCH_TASK] Process ID: {os.getpid()}. Loading index from: {index_file_path}") - # These params are for loading the index instance, or for search current_build_params_for_load = dict(index_config.get("build_params", {})) - current_search_params = dict(index_config.get("search_params", {})) + current_search_params_for_method = dict(index_config.get("search_params", {})) - # Pop omp_num_threads_search before passing current_search_params to idx_instance.search - omp_search_threads = str(current_search_params.pop("omp_num_threads_search", "1")) - os.environ["OMP_NUM_THREADS"] = omp_search_threads - print(f"[{index_name} SEARCH_TASK] Set OMP_NUM_THREADS={omp_search_threads}.") + omp_search_threads_config_val = str(current_search_params_for_method.pop("omp_num_threads_search", "1")) + _apply_faiss_thread_settings(omp_search_threads_config_val, f"{index_name} SEARCH_TASK") _, query_vectors, gt_vectors = common_utils.load_data( dataset_cfg["name"], nq_override=dataset_cfg.get("num_queries")) IndexCls = INDEX_CLASSES.get(index_type_str) if IndexCls is None or (IndexCls == Scann and Scann is None): # type: ignore - if original_omp_threads is not None: os.environ["OMP_NUM_THREADS"] = original_omp_threads - else: os.environ.pop("OMP_NUM_THREADS", None) return {"error": f"Index type '{index_type_str}' unavailable for search."} - if not Path(index_file_path).exists(): # Ensure Path object for exists() - if original_omp_threads is not None: os.environ["OMP_NUM_THREADS"] = original_omp_threads - else: os.environ.pop("OMP_NUM_THREADS", None) + if not Path(index_file_path).exists(): return {"error": f"Index file {index_file_path} not found for search."} idx_instance = IndexCls() load_kwargs = {} - # Params like num_workers for Quake load are typically in "build_params" section of YAML if "num_workers" in current_build_params_for_load: load_kwargs["num_workers"] = current_build_params_for_load.get("num_workers") if "use_numa" in current_build_params_for_load: load_kwargs["use_numa"] = current_build_params_for_load.get("use_numa") if "parent_num_workers" in current_build_params_for_load: load_kwargs["parent_num_workers"] = current_build_params_for_load.get("parent_num_workers") - print(f"[{index_name} SEARCH_TASK] Loading index with kwargs: {load_kwargs}") idx_instance.load(str(index_file_path), **load_kwargs) + print(f"[{index_name} SEARCH_TASK] Index loaded with kwargs: {load_kwargs}") k_val = global_run_params["k_val"] print(f"[{index_name} SEARCH_TASK] Warmup ({global_run_params['num_warmup']} iterations)...") - # current_search_params now does NOT contain omp_num_threads_search for _ in range(global_run_params['num_warmup']): - _ = idx_instance.search(query_vectors, k_val, **current_search_params) + _ = idx_instance.search(query_vectors, k_val, **current_search_params_for_method) trial_latencies_ms = [] trial_recalls = [] print(f"[{index_name} SEARCH_TASK] Benchmarking ({global_run_params['num_trials']} trials)...") for i in range(global_run_params['num_trials']): - # current_search_params now does NOT contain omp_num_threads_search - search_result = idx_instance.search(query_vectors, k_val, **current_search_params) + search_result = idx_instance.search(query_vectors, k_val, **current_search_params_for_method) latency_ms = np.nan timing_info = getattr(search_result, "timing_info", None) if timing_info and hasattr(timing_info, "total_time_ns"): latency_ms = getattr(timing_info, "total_time_ns") / 1e6 @@ -135,9 +121,6 @@ def task_search_index( except Exception: pass trial_recalls.append(recall_val) - if original_omp_threads is not None: os.environ["OMP_NUM_THREADS"] = original_omp_threads - else: os.environ.pop("OMP_NUM_THREADS", None) - print(f"[{index_name} SEARCH_TASK] Individual trial results (Latency, Recall@K={k_val}):") for i in range(len(trial_latencies_ms)): lat_str = f"{trial_latencies_ms[i]:.3f}ms" if not np.isnan(trial_latencies_ms[i]) else "N/A" @@ -152,10 +135,10 @@ def task_search_index( final_row[f"mean_recall_at_{k_val}"] = float(np.mean(valid_recalls)) if valid_recalls else np.nan final_row[f"std_recall_at_{k_val}"] = float(np.std(valid_recalls)) if valid_recalls else np.nan - n_threads_or_workers = int(omp_search_threads) - if index_type_str == "Quake" and "num_workers" in current_build_params_for_load : - n_threads_or_workers = current_build_params_for_load.get("num_workers", n_threads_or_workers) - final_row["n_config_concurrency"] = n_threads_or_workers + n_concurrency_param = int(omp_search_threads_config_val) + if index_type_str == "Quake" and "num_workers" in current_build_params_for_load : # type: ignore + n_concurrency_param = current_build_params_for_load.get("num_workers", n_concurrency_param) # type: ignore + final_row["n_config_concurrency"] = n_concurrency_param print(f"[{index_name} SEARCH_TASK] Benchmark task finished.") return final_row @@ -178,7 +161,7 @@ def run_experiment(cfg_path_str: str, output_dir_str: str): "enable_glances": cfg.get("enable_glances_monitoring", False) } indexes_config_list = cfg["indexes"] - output_csv_name = cfg.get("output", {}).get("results_csv", "numa_multi_query_results.csv") # Changed from single_query + output_csv_name = cfg.get("output", {}).get("results_csv", "numa_multi_query_results.csv") all_experiment_rows = [] for idx_conf in indexes_config_list: @@ -195,6 +178,8 @@ def run_experiment(cfg_path_str: str, output_dir_str: str): logger.info(f"Orchestrator: Submitting BUILD task for index: {index_name}") build_log_file = process_logs_dir / f"{index_name}_build_process.log" + # OMP settings are now handled inside the tasks by _apply_faiss_thread_settings + # Other env_vars can still be passed if needed. build_env_vars = idx_conf.get("build_env_vars", {}) process_timeout = idx_conf.get("process_timeout", cfg.get("default_process_timeout", 7200)) @@ -211,7 +196,7 @@ def run_experiment(cfg_path_str: str, output_dir_str: str): continue logger.info(f"BUILD task for {index_name} succeeded. Index file: {build_result.get('data',{}).get('index_file_path')}") - built_index_file_path = Path(build_result.get("data",{}).get("index_file_path", index_file_path)) # Use confirmed path + built_index_file_path = Path(build_result.get("data",{}).get("index_file_path", index_file_path)) logger.info(f"Orchestrator: Submitting SEARCH task for index: {index_name}") search_log_file = process_logs_dir / f"{index_name}_search_process.log" @@ -244,7 +229,6 @@ def run_experiment(cfg_path_str: str, output_dir_str: str): plot_suffix = Path(output_csv_name).stem plot_x_param = "n_config_concurrency" - # Ensure 'index' column is valid before attempting groupby for plotting plot_df = final_df.dropna(subset=['index', plot_x_param]).copy() if not plot_df.empty: plot_df.loc[:, plot_x_param] = pd.to_numeric(plot_df[plot_x_param], errors='coerce').fillna(-1).astype(int) From ffc0da880a387f8a2776823c833f0a21322ff47d Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 22 May 2025 23:12:33 -0500 Subject: [PATCH 222/323] limit busy waiting --- src/cpp/include/query_coordinator.h | 9 +- src/cpp/src/query_coordinator.cpp | 156 ++++++++++-------- test/cpp/benchmark.cpp | 9 +- .../numa_multi_query/configs/sift1m.yaml | 16 ++ 4 files changed, 113 insertions(+), 77 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 60f8bd33..8e6ee53d 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -10,7 +10,9 @@ #include #include #include +#include #include +#include "blockingconcurrentqueue.h" class QuakeIndex; class PartitionManager; @@ -57,7 +59,8 @@ class QueryCoordinator { struct CoreResources { int core_id; std::vector> topk_buffer_pool; - moodycamel::ConcurrentQueue job_queue; +// moodycamel::ConcurrentQueue job_queue; + moodycamel::BlockingReaderWriterQueue job_queue; // Thread-local buffers for batched queries float* batch_queries = nullptr; // batched query buffer (NUMA-allocated) @@ -79,10 +82,10 @@ class QueryCoordinator { std::vector indices; }; - vector core_resources_; ///< Per‑core resources for worker threads. vector numa_resources_; - moodycamel::ConcurrentQueue result_queue_; + moodycamel::BlockingConcurrentQueue result_queue_; +// moodycamel::ConcurrentQueue result_queue_; bool workers_initialized_ = false; ///< Flag indicating if worker threads are initialized. int num_workers_; ///< Total number of worker threads. diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index c831e108..6c6f6e8f 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -66,6 +66,9 @@ void QueryCoordinator::allocate_core_resources(int core_idx, } } + + + void QueryCoordinator::partition_scan_worker_fn(int core_index) { CoreResources &res = core_resources_[core_index]; int numa_node = 0; @@ -79,10 +82,8 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { int i = 0; while (!stop_workers_) { int64_t jid = 0; - if (!res.job_queue.try_dequeue(jid)) { - std::this_thread::sleep_for(std::chrono::microseconds(20)); - continue; - } + + res.job_queue.wait_dequeue(jid); if (jid == -1) { break; @@ -493,88 +494,99 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, } } -void QueryCoordinator::drain_and_apply_aps(Tensor x, - Tensor partition_ids, - bool use_aps, - float recall_target, - float aps_flush_period_us, - shared_ptr timing) + +void QueryCoordinator::drain_and_apply_aps(Tensor x, + Tensor partition_ids, + bool use_aps, + float recall_target, + float aps_flush_period_us, + std::shared_ptr timing) { - // precompute boundary distances if needed - int nQ = x.size(0); - int D = x.size(1); - int nprobe = partition_ids.size(1); - vector> boundary_dist(nQ); - vector query_radius(nQ, 0.0f); - vector> probs(nQ); - if (use_aps) { + const int64_t nQ = x.size(0); + const int64_t D = x.size(1); + const int64_t nprobe = partition_ids.size(1); + const auto aps_dur = std::chrono::microseconds( + static_cast(aps_flush_period_us)); + + /* ------------------------------------------------------------------------ */ + /* Book-keeping */ + /* ------------------------------------------------------------------------ */ + std::vector parts_left(nQ, 0); + std::atomic total_left{0}; + for (int64_t q = 0; q < nQ; ++q) { + for (int64_t p = 0; p < nprobe; ++p) + if (!job_flags_[q][p]) { ++parts_left[q]; ++total_left; } + } + + /* APS pre-computations -------------------------------------------------- */ + std::vector query_radius(nQ, 0.0f); + std::vector> boundary_dist(nQ); + std::vector> probs(nQ); + if (use_aps) { + query_radius.resize(nQ); + boundary_dist.resize(nQ); + probs.resize(nQ); for (int64_t q = 0; q < nQ; ++q) { - vector partition_ids_to_scan_vec = std::vector(partition_ids[q].data_ptr(), - partition_ids[q].data_ptr() + partition_ids[q].size(0)); - vector cluster_centroids = parent_->partition_manager_->get_vectors(partition_ids_to_scan_vec); - boundary_dist[q] = compute_boundary_distances(x[q], cluster_centroids, metric_ == faiss::METRIC_L2); + std::vector pids(partition_ids[q].data_ptr(), + partition_ids[q].data_ptr()+nprobe); + auto centroids = parent_->partition_manager_->get_vectors(pids); + centroids.erase(std::remove(centroids.begin(), centroids.end(), nullptr), + centroids.end()); + boundary_dist[q] = + compute_boundary_distances(x[q], centroids, metric_==faiss::METRIC_L2); } - } - auto last_flush = high_resolution_clock::now(); + ResultJob rj; + while (total_left.load(std::memory_order_relaxed) > 0) { - int64_t jobsReceived = 0; - while (true) { - // 1) drain all ready results - ResultJob rj; - while (result_queue_.try_dequeue(rj)) { - ++jobsReceived; - global_topk_buffer_pool_[rj.query_id] - ->batch_add(rj.distances.data(), - rj.indices.data(), - (int)rj.indices.size()); + /* -- Wait for result or APS timeout -- */ + bool got_result = result_queue_.wait_dequeue_timed(rj, aps_dur); - job_flags_[rj.query_id][rj.rank] = true; - } - // 2) check done - bool all_done = true; - for (int64_t q = 0; q < nQ; ++q) { - for (int64_t p = 0; p < nprobe; ++p) { - if (!job_flags_[q][p]) { - all_done = false; - break; + if (got_result) { + do { // Drain *all* currently available results. + auto &buf = global_topk_buffer_pool_[rj.query_id]; + buf->batch_add(rj.distances.data(), rj.indices.data(), + static_cast(rj.indices.size())); + + if (!job_flags_[rj.query_id][rj.rank]) { + job_flags_[rj.query_id][rj.rank] = true; + --parts_left[rj.query_id]; + --total_left; } - } + } while (result_queue_.try_dequeue(rj)); + + continue; // Skip APS; we just did useful work. } - if (all_done) break; - // 3) APS early-stop - if (use_aps && duration_cast(high_resolution_clock::now() - last_flush).count() - > aps_flush_period_us) - { + /* (b) Timeout fired → run APS once. */ + if (use_aps) { for (int64_t q = 0; q < nQ; ++q) { - auto buf = global_topk_buffer_pool_[q]; - float r = buf->get_kth_distance(); - if (r != query_radius[q]) { - query_radius[q] = r; - probs[q] = compute_recall_profile( - boundary_dist[q], - r, - D, - {}, - true, - metric_==faiss::METRIC_L2 - ); - } - float cum=0; - for (int i=0; i<(int)job_flags_[q].size(); ++i) - if (job_flags_[q][i]) cum += probs[q][i]; - if (cum > recall_target) { - // set all jobs to done - for (int i=0; i<(int)job_flags_[q].size(); ++i) - job_flags_[q][i] = true; - } + if (parts_left[q] == 0) continue; + + auto &buf = global_topk_buffer_pool_[q]; + const float r = buf->get_kth_distance(); + if (r != query_radius[q]) { + query_radius[q] = r; + probs[q] = compute_recall_profile( + boundary_dist[q], r, D, {}, true, metric_==faiss::METRIC_L2); + } + + float cum = 0.0f; + for (int64_t p = 0; p < nprobe; ++p) + if (job_flags_[q][p]) cum += probs[q][p]; + + if (cum >= recall_target) { + for (int64_t p = 0; p < nprobe; ++p) + if (!job_flags_[q][p]) { + job_flags_[q][p] = true; + --parts_left[q]; + --total_left; + } } } - last_flush = high_resolution_clock::now(); - std::this_thread::sleep_for(std::chrono::microseconds(5)); + } } } diff --git a/test/cpp/benchmark.cpp b/test/cpp/benchmark.cpp index f4b8d380..e9a836c3 100644 --- a/test/cpp/benchmark.cpp +++ b/test/cpp/benchmark.cpp @@ -29,10 +29,11 @@ using torch::Tensor; static const int64_t DIM = 128; static const int64_t NUM_VECTORS = 100000; // number of database vectors static const int64_t N_LIST = 1000; // number of clusters for IVF -static const int64_t NUM_QUERIES = 10; // number of queries for search benchmark -static const int64_t K = 10; // top-K neighbors +static const int64_t NUM_QUERIES = 10000; // number of queries for search benchmark +static const int64_t K = 1; // top-K neighbors static const int64_t N_PROBE = 20; // number of probes for IVF static const int64_t N_WORKERS = 12; // number of workers for parallel query coordinator +static const int64_t N_PARENT_WORKERS = 12; // Helper functions to generate random data and sequential IDs static Tensor generate_data(int64_t num, int64_t dim) { @@ -117,6 +118,8 @@ class QuakeWorkerIVFBenchmark : public ::testing::Test { build_params->metric = "l2"; build_params->niter = 3; build_params->num_workers = N_WORKERS; + build_params->parent_params = std::make_shared(); + build_params->parent_params->num_workers = N_PARENT_WORKERS; index_->build(data_, ids_, build_params); } }; @@ -305,6 +308,8 @@ TEST_F(QuakeWorkerIVFBenchmark, SearchBatch) { search_params->k = K; search_params->nprobe = N_PROBE; search_params->batched_scan = true; + search_params->parent_params = std::make_shared(); + search_params->parent_params->batched_scan = true; index_->search(queries, search_params); diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index 70a20c64..81e203a6 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -17,6 +17,7 @@ indexes: metric: l2 num_workers: 16 use_numa: false + parent_num_workers: 4 search_params: nprobe: 20 batched_scan: true @@ -28,6 +29,7 @@ indexes: metric: l2 num_workers: 16 use_numa: true + parent_num_workers: 4 search_params: nprobe: 20 batched_scan: true @@ -39,6 +41,7 @@ indexes: metric: l2 num_workers: 16 use_numa: true + parent_num_workers: 4 search_params: nprobe: 20 batched_scan: false @@ -51,6 +54,19 @@ indexes: search_params: nprobe: 20 omp_num_threads_search: 16 + + + - name: FaissHNSW + index: HNSW + build_params: + m: 64 + ef_construction: 128 + metric: l2 + omp_num_threads_build: 32 + search_params: + ef_search: 128 + omp_num_threads_search: 32 + # # - name: SCANN # index: SCANN From 374118a8a2f545ca62573c3e8ebfda7de8086d9f Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 22 May 2025 23:14:16 -0500 Subject: [PATCH 223/323] limit busy waiting --- src/cpp/include/sorting/atomicops.h | 772 +++++++++++++++ src/cpp/include/sorting/readerwriterqueue.h | 979 ++++++++++++++++++++ 2 files changed, 1751 insertions(+) create mode 100644 src/cpp/include/sorting/atomicops.h create mode 100644 src/cpp/include/sorting/readerwriterqueue.h diff --git a/src/cpp/include/sorting/atomicops.h b/src/cpp/include/sorting/atomicops.h new file mode 100644 index 00000000..1832dee8 --- /dev/null +++ b/src/cpp/include/sorting/atomicops.h @@ -0,0 +1,772 @@ +// ©2013-2016 Cameron Desrochers. +// Distributed under the simplified BSD license (see the license file that +// should have come with this header). +// Uses Jeff Preshing's semaphore implementation (under the terms of its +// separate zlib license, embedded below). + +#pragma once + +// Provides portable (VC++2010+, Intel ICC 13, GCC 4.7+, and anything C++11 compliant) implementation +// of low-level memory barriers, plus a few semi-portable utility macros (for inlining and alignment). +// Also has a basic atomic type (limited to hardware-supported atomics with no memory ordering guarantees). +// Uses the AE_* prefix for macros (historical reasons), and the "moodycamel" namespace for symbols. + +#include +#include +#include +#include +#include +#include + +// Platform detection +#if defined(__INTEL_COMPILER) +#define AE_ICC +#elif defined(_MSC_VER) +#define AE_VCPP +#elif defined(__GNUC__) +#define AE_GCC +#endif + +#if defined(_M_IA64) || defined(__ia64__) +#define AE_ARCH_IA64 +#elif defined(_WIN64) || defined(__amd64__) || defined(_M_X64) || defined(__x86_64__) +#define AE_ARCH_X64 +#elif defined(_M_IX86) || defined(__i386__) +#define AE_ARCH_X86 +#elif defined(_M_PPC) || defined(__powerpc__) +#define AE_ARCH_PPC +#else +#define AE_ARCH_UNKNOWN +#endif + + +// AE_UNUSED +#define AE_UNUSED(x) ((void)x) + +// AE_NO_TSAN/AE_TSAN_ANNOTATE_* +// For GCC +#if defined(__SANITIZE_THREAD__) +#define AE_TSAN_IS_ENABLED +#endif +// For clang +#if defined(__has_feature) +#if __has_feature(thread_sanitizer) && !defined(AE_TSAN_IS_ENABLED) +#define AE_TSAN_IS_ENABLED +#endif +#endif + +#ifdef AE_TSAN_IS_ENABLED +#if __cplusplus >= 201703L // inline variables require C++17 +namespace moodycamel { inline int ae_tsan_global; } +#define AE_TSAN_ANNOTATE_RELEASE() AnnotateHappensBefore(__FILE__, __LINE__, (void *)(&::moodycamel::ae_tsan_global)) +#define AE_TSAN_ANNOTATE_ACQUIRE() AnnotateHappensAfter(__FILE__, __LINE__, (void *)(&::moodycamel::ae_tsan_global)) +extern "C" void AnnotateHappensBefore(const char*, int, void*); +extern "C" void AnnotateHappensAfter(const char*, int, void*); +#else // when we can't work with tsan, attempt to disable its warnings +#define AE_NO_TSAN __attribute__((no_sanitize("thread"))) +#endif +#endif + +#ifndef AE_NO_TSAN +#define AE_NO_TSAN +#endif + +#ifndef AE_TSAN_ANNOTATE_RELEASE +#define AE_TSAN_ANNOTATE_RELEASE() +#define AE_TSAN_ANNOTATE_ACQUIRE() +#endif + + +// AE_FORCEINLINE +#if defined(AE_VCPP) || defined(AE_ICC) +#define AE_FORCEINLINE __forceinline +#elif defined(AE_GCC) +//#define AE_FORCEINLINE __attribute__((always_inline)) +#define AE_FORCEINLINE inline +#else +#define AE_FORCEINLINE inline +#endif + + +// AE_ALIGN +#if defined(AE_VCPP) || defined(AE_ICC) +#define AE_ALIGN(x) __declspec(align(x)) +#elif defined(AE_GCC) +#define AE_ALIGN(x) __attribute__((aligned(x))) +#else +// Assume GCC compliant syntax... +#define AE_ALIGN(x) __attribute__((aligned(x))) +#endif + + +// Portable atomic fences implemented below: + +namespace moodycamel { + + enum memory_order { + memory_order_relaxed, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst, + + // memory_order_sync: Forces a full sync: + // #LoadLoad, #LoadStore, #StoreStore, and most significantly, #StoreLoad + memory_order_sync = memory_order_seq_cst + }; + +} // end namespace moodycamel + +#if (defined(AE_VCPP) && (_MSC_VER < 1700 || defined(__cplusplus_cli))) || (defined(AE_ICC) && __INTEL_COMPILER < 1600) +// VS2010 and ICC13 don't support std::atomic_*_fence, implement our own fences + +#include + +#if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) +#define AeFullSync _mm_mfence +#define AeLiteSync _mm_mfence +#elif defined(AE_ARCH_IA64) +#define AeFullSync __mf +#define AeLiteSync __mf +#elif defined(AE_ARCH_PPC) +#include +#define AeFullSync __sync +#define AeLiteSync __lwsync +#endif + + +#ifdef AE_VCPP +#pragma warning(push) +#pragma warning(disable: 4365) // Disable erroneous 'conversion from long to unsigned int, signed/unsigned mismatch' error when using `assert` +#ifdef __cplusplus_cli +#pragma managed(push, off) +#endif +#endif + +namespace moodycamel { + +AE_FORCEINLINE void compiler_fence(memory_order order) AE_NO_TSAN +{ + switch (order) { + case memory_order_relaxed: break; + case memory_order_acquire: _ReadBarrier(); break; + case memory_order_release: _WriteBarrier(); break; + case memory_order_acq_rel: _ReadWriteBarrier(); break; + case memory_order_seq_cst: _ReadWriteBarrier(); break; + default: assert(false); + } +} + +// x86/x64 have a strong memory model -- all loads and stores have +// acquire and release semantics automatically (so only need compiler +// barriers for those). +#if defined(AE_ARCH_X86) || defined(AE_ARCH_X64) +AE_FORCEINLINE void fence(memory_order order) AE_NO_TSAN +{ + switch (order) { + case memory_order_relaxed: break; + case memory_order_acquire: _ReadBarrier(); break; + case memory_order_release: _WriteBarrier(); break; + case memory_order_acq_rel: _ReadWriteBarrier(); break; + case memory_order_seq_cst: + _ReadWriteBarrier(); + AeFullSync(); + _ReadWriteBarrier(); + break; + default: assert(false); + } +} +#else +AE_FORCEINLINE void fence(memory_order order) AE_NO_TSAN +{ + // Non-specialized arch, use heavier memory barriers everywhere just in case :-( + switch (order) { + case memory_order_relaxed: + break; + case memory_order_acquire: + _ReadBarrier(); + AeLiteSync(); + _ReadBarrier(); + break; + case memory_order_release: + _WriteBarrier(); + AeLiteSync(); + _WriteBarrier(); + break; + case memory_order_acq_rel: + _ReadWriteBarrier(); + AeLiteSync(); + _ReadWriteBarrier(); + break; + case memory_order_seq_cst: + _ReadWriteBarrier(); + AeFullSync(); + _ReadWriteBarrier(); + break; + default: assert(false); + } +} +#endif +} // end namespace moodycamel +#else +// Use standard library of atomics +#include + +namespace moodycamel { + + AE_FORCEINLINE void compiler_fence(memory_order order) AE_NO_TSAN + { + switch (order) { + case memory_order_relaxed: break; + case memory_order_acquire: std::atomic_signal_fence(std::memory_order_acquire); break; + case memory_order_release: std::atomic_signal_fence(std::memory_order_release); break; + case memory_order_acq_rel: std::atomic_signal_fence(std::memory_order_acq_rel); break; + case memory_order_seq_cst: std::atomic_signal_fence(std::memory_order_seq_cst); break; + default: assert(false); + } + } + + AE_FORCEINLINE void fence(memory_order order) AE_NO_TSAN + { + switch (order) { + case memory_order_relaxed: break; + case memory_order_acquire: AE_TSAN_ANNOTATE_ACQUIRE(); std::atomic_thread_fence(std::memory_order_acquire); break; + case memory_order_release: AE_TSAN_ANNOTATE_RELEASE(); std::atomic_thread_fence(std::memory_order_release); break; + case memory_order_acq_rel: AE_TSAN_ANNOTATE_ACQUIRE(); AE_TSAN_ANNOTATE_RELEASE(); std::atomic_thread_fence(std::memory_order_acq_rel); break; + case memory_order_seq_cst: AE_TSAN_ANNOTATE_ACQUIRE(); AE_TSAN_ANNOTATE_RELEASE(); std::atomic_thread_fence(std::memory_order_seq_cst); break; + default: assert(false); + } + } + +} // end namespace moodycamel + +#endif + + +#if !defined(AE_VCPP) || (_MSC_VER >= 1700 && !defined(__cplusplus_cli)) +#define AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC +#endif + +#ifdef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC +#include +#endif +#include + +// WARNING: *NOT* A REPLACEMENT FOR std::atomic. READ CAREFULLY: +// Provides basic support for atomic variables -- no memory ordering guarantees are provided. +// The guarantee of atomicity is only made for types that already have atomic load and store guarantees +// at the hardware level -- on most platforms this generally means aligned pointers and integers (only). +namespace moodycamel { + template + class weak_atomic + { + public: + AE_NO_TSAN weak_atomic() : value() { } +#ifdef AE_VCPP + #pragma warning(push) +#pragma warning(disable: 4100) // Get rid of (erroneous) 'unreferenced formal parameter' warning +#endif + template AE_NO_TSAN weak_atomic(U&& x) : value(std::forward(x)) { } +#ifdef __cplusplus_cli + // Work around bug with universal reference/nullptr combination that only appears when /clr is on + AE_NO_TSAN weak_atomic(nullptr_t) : value(nullptr) { } +#endif + AE_NO_TSAN weak_atomic(weak_atomic const& other) : value(other.load()) { } + AE_NO_TSAN weak_atomic(weak_atomic&& other) : value(std::move(other.load())) { } +#ifdef AE_VCPP +#pragma warning(pop) +#endif + + AE_FORCEINLINE operator T() const AE_NO_TSAN { return load(); } + + +#ifndef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC + template AE_FORCEINLINE weak_atomic const& operator=(U&& x) AE_NO_TSAN { value = std::forward(x); return *this; } + AE_FORCEINLINE weak_atomic const& operator=(weak_atomic const& other) AE_NO_TSAN { value = other.value; return *this; } + + AE_FORCEINLINE T load() const AE_NO_TSAN { return value; } + + AE_FORCEINLINE T fetch_add_acquire(T increment) AE_NO_TSAN + { +#if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) + if (sizeof(T) == 4) return _InterlockedExchangeAdd((long volatile*)&value, (long)increment); +#if defined(_M_AMD64) + else if (sizeof(T) == 8) return _InterlockedExchangeAdd64((long long volatile*)&value, (long long)increment); +#endif +#else +#error Unsupported platform +#endif + assert(false && "T must be either a 32 or 64 bit type"); + return value; + } + + AE_FORCEINLINE T fetch_add_release(T increment) AE_NO_TSAN + { +#if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) + if (sizeof(T) == 4) return _InterlockedExchangeAdd((long volatile*)&value, (long)increment); +#if defined(_M_AMD64) + else if (sizeof(T) == 8) return _InterlockedExchangeAdd64((long long volatile*)&value, (long long)increment); +#endif +#else +#error Unsupported platform +#endif + assert(false && "T must be either a 32 or 64 bit type"); + return value; + } +#else + template + AE_FORCEINLINE weak_atomic const& operator=(U&& x) AE_NO_TSAN + { + value.store(std::forward(x), std::memory_order_relaxed); + return *this; + } + + AE_FORCEINLINE weak_atomic const& operator=(weak_atomic const& other) AE_NO_TSAN + { + value.store(other.value.load(std::memory_order_relaxed), std::memory_order_relaxed); + return *this; + } + + AE_FORCEINLINE T load() const AE_NO_TSAN { return value.load(std::memory_order_relaxed); } + + AE_FORCEINLINE T fetch_add_acquire(T increment) AE_NO_TSAN + { + return value.fetch_add(increment, std::memory_order_acquire); + } + + AE_FORCEINLINE T fetch_add_release(T increment) AE_NO_TSAN + { + return value.fetch_add(increment, std::memory_order_release); + } +#endif + + + private: +#ifndef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC + // No std::atomic support, but still need to circumvent compiler optimizations. + // `volatile` will make memory access slow, but is guaranteed to be reliable. + volatile T value; +#else + std::atomic value; +#endif + }; + +} // end namespace moodycamel + + + +// Portable single-producer, single-consumer semaphore below: + +#if defined(_WIN32) +// Avoid including windows.h in a header; we only need a handful of +// items, so we'll redeclare them here (this is relatively safe since +// the API generally has to remain stable between Windows versions). +// I know this is an ugly hack but it still beats polluting the global +// namespace with thousands of generic names or adding a .cpp for nothing. +extern "C" { + struct _SECURITY_ATTRIBUTES; + __declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES* lpSemaphoreAttributes, long lInitialCount, long lMaximumCount, const wchar_t* lpName); + __declspec(dllimport) int __stdcall CloseHandle(void* hObject); + __declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void* hHandle, unsigned long dwMilliseconds); + __declspec(dllimport) int __stdcall ReleaseSemaphore(void* hSemaphore, long lReleaseCount, long* lpPreviousCount); +} +#elif defined(__MACH__) +#include +#elif defined(__unix__) +#include +#elif defined(FREERTOS) +#include +#include +#include +#endif + +namespace moodycamel +{ + // Code in the spsc_sema namespace below is an adaptation of Jeff Preshing's + // portable + lightweight semaphore implementations, originally from + // https://github.com/preshing/cpp11-on-multicore/blob/master/common/sema.h + // LICENSE: + // Copyright (c) 2015 Jeff Preshing + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgement in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + namespace spsc_sema + { +#if defined(_WIN32) + class Semaphore + { + private: + void* m_hSema; + + Semaphore(const Semaphore& other); + Semaphore& operator=(const Semaphore& other); + + public: + AE_NO_TSAN Semaphore(int initialCount = 0) : m_hSema() + { + assert(initialCount >= 0); + const long maxLong = 0x7fffffff; + m_hSema = CreateSemaphoreW(nullptr, initialCount, maxLong, nullptr); + assert(m_hSema); + } + + AE_NO_TSAN ~Semaphore() + { + CloseHandle(m_hSema); + } + + bool wait() AE_NO_TSAN + { + const unsigned long infinite = 0xffffffff; + return WaitForSingleObject(m_hSema, infinite) == 0; + } + + bool try_wait() AE_NO_TSAN + { + return WaitForSingleObject(m_hSema, 0) == 0; + } + + bool timed_wait(std::uint64_t usecs) AE_NO_TSAN + { + return WaitForSingleObject(m_hSema, (unsigned long)(usecs / 1000)) == 0; + } + + void signal(int count = 1) AE_NO_TSAN + { + while (!ReleaseSemaphore(m_hSema, count, nullptr)); + } + }; +#elif defined(__MACH__) + //--------------------------------------------------------- + // Semaphore (Apple iOS and OSX) + // Can't use POSIX semaphores due to http://lists.apple.com/archives/darwin-kernel/2009/Apr/msg00010.html + //--------------------------------------------------------- + class Semaphore + { + private: + semaphore_t m_sema; + + Semaphore(const Semaphore& other); + Semaphore& operator=(const Semaphore& other); + + public: + AE_NO_TSAN Semaphore(int initialCount = 0) : m_sema() + { + assert(initialCount >= 0); + kern_return_t rc = semaphore_create(mach_task_self(), &m_sema, SYNC_POLICY_FIFO, initialCount); + assert(rc == KERN_SUCCESS); + AE_UNUSED(rc); + } + + AE_NO_TSAN ~Semaphore() + { + semaphore_destroy(mach_task_self(), m_sema); + } + + bool wait() AE_NO_TSAN + { + return semaphore_wait(m_sema) == KERN_SUCCESS; + } + + bool try_wait() AE_NO_TSAN + { + return timed_wait(0); + } + + bool timed_wait(std::uint64_t timeout_usecs) AE_NO_TSAN + { + mach_timespec_t ts; + ts.tv_sec = static_cast(timeout_usecs / 1000000); + ts.tv_nsec = static_cast((timeout_usecs % 1000000) * 1000); + + // added in OSX 10.10: https://developer.apple.com/library/prerelease/mac/documentation/General/Reference/APIDiffsMacOSX10_10SeedDiff/modules/Darwin.html + kern_return_t rc = semaphore_timedwait(m_sema, ts); + return rc == KERN_SUCCESS; + } + + void signal() AE_NO_TSAN + { + while (semaphore_signal(m_sema) != KERN_SUCCESS); + } + + void signal(int count) AE_NO_TSAN + { + while (count-- > 0) + { + while (semaphore_signal(m_sema) != KERN_SUCCESS); + } + } + }; +#elif defined(__unix__) + //--------------------------------------------------------- + // Semaphore (POSIX, Linux) + //--------------------------------------------------------- + class Semaphore + { + private: + sem_t m_sema; + + Semaphore(const Semaphore& other); + Semaphore& operator=(const Semaphore& other); + + public: + AE_NO_TSAN Semaphore(int initialCount = 0) : m_sema() + { + assert(initialCount >= 0); + int rc = sem_init(&m_sema, 0, static_cast(initialCount)); + assert(rc == 0); + AE_UNUSED(rc); + } + + AE_NO_TSAN ~Semaphore() + { + sem_destroy(&m_sema); + } + + bool wait() AE_NO_TSAN + { + // http://stackoverflow.com/questions/2013181/gdb-causes-sem-wait-to-fail-with-eintr-error + int rc; + do + { + rc = sem_wait(&m_sema); + } + while (rc == -1 && errno == EINTR); + return rc == 0; + } + + bool try_wait() AE_NO_TSAN + { + int rc; + do { + rc = sem_trywait(&m_sema); + } while (rc == -1 && errno == EINTR); + return rc == 0; + } + + bool timed_wait(std::uint64_t usecs) AE_NO_TSAN + { + struct timespec ts; + const int usecs_in_1_sec = 1000000; + const int nsecs_in_1_sec = 1000000000; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += static_cast(usecs / usecs_in_1_sec); + ts.tv_nsec += static_cast(usecs % usecs_in_1_sec) * 1000; + // sem_timedwait bombs if you have more than 1e9 in tv_nsec + // so we have to clean things up before passing it in + if (ts.tv_nsec >= nsecs_in_1_sec) { + ts.tv_nsec -= nsecs_in_1_sec; + ++ts.tv_sec; + } + + int rc; + do { + rc = sem_timedwait(&m_sema, &ts); + } while (rc == -1 && errno == EINTR); + return rc == 0; + } + + void signal() AE_NO_TSAN + { + while (sem_post(&m_sema) == -1); + } + + void signal(int count) AE_NO_TSAN + { + while (count-- > 0) + { + while (sem_post(&m_sema) == -1); + } + } + }; +#elif defined(FREERTOS) + //--------------------------------------------------------- + // Semaphore (FreeRTOS) + //--------------------------------------------------------- + class Semaphore + { + private: + SemaphoreHandle_t m_sema; + + Semaphore(const Semaphore& other); + Semaphore& operator=(const Semaphore& other); + + public: + AE_NO_TSAN Semaphore(int initialCount = 0) : m_sema() + { + assert(initialCount >= 0); + m_sema = xSemaphoreCreateCounting(static_cast(~0ull), static_cast(initialCount)); + assert(m_sema); + } + + AE_NO_TSAN ~Semaphore() + { + vSemaphoreDelete(m_sema); + } + + bool wait() AE_NO_TSAN + { + return xSemaphoreTake(m_sema, portMAX_DELAY) == pdTRUE; + } + + bool try_wait() AE_NO_TSAN + { + // Note: In an ISR context, if this causes a task to unblock, + // the caller won't know about it + if (xPortIsInsideInterrupt()) + return xSemaphoreTakeFromISR(m_sema, NULL) == pdTRUE; + return xSemaphoreTake(m_sema, 0) == pdTRUE; + } + + bool timed_wait(std::uint64_t usecs) AE_NO_TSAN + { + std::uint64_t msecs = usecs / 1000; + TickType_t ticks = static_cast(msecs / portTICK_PERIOD_MS); + if (ticks == 0) + return try_wait(); + return xSemaphoreTake(m_sema, ticks) == pdTRUE; + } + + void signal() AE_NO_TSAN + { + // Note: In an ISR context, if this causes a task to unblock, + // the caller won't know about it + BaseType_t rc; + if (xPortIsInsideInterrupt()) + rc = xSemaphoreGiveFromISR(m_sema, NULL); + else + rc = xSemaphoreGive(m_sema); + assert(rc == pdTRUE); + AE_UNUSED(rc); + } + + void signal(int count) AE_NO_TSAN + { + while (count-- > 0) + signal(); + } + }; +#else +#error Unsupported platform! (No semaphore wrapper available) +#endif + + //--------------------------------------------------------- + // LightweightSemaphore + //--------------------------------------------------------- + class LightweightSemaphore + { + public: + typedef std::make_signed::type ssize_t; + + private: + weak_atomic m_count; + Semaphore m_sema; + + bool waitWithPartialSpinning(std::int64_t timeout_usecs = -1) AE_NO_TSAN + { + ssize_t oldCount; + // Is there a better way to set the initial spin count? + // If we lower it to 1000, testBenaphore becomes 15x slower on my Core i7-5930K Windows PC, + // as threads start hitting the kernel semaphore. + int spin = 1024; + while (--spin >= 0) + { + if (m_count.load() > 0) + { + m_count.fetch_add_acquire(-1); + return true; + } + compiler_fence(memory_order_acquire); // Prevent the compiler from collapsing the loop. + } + oldCount = m_count.fetch_add_acquire(-1); + if (oldCount > 0) + return true; + if (timeout_usecs < 0) + { + if (m_sema.wait()) + return true; + } + if (timeout_usecs > 0 && m_sema.timed_wait(static_cast(timeout_usecs))) + return true; + // At this point, we've timed out waiting for the semaphore, but the + // count is still decremented indicating we may still be waiting on + // it. So we have to re-adjust the count, but only if the semaphore + // wasn't signaled enough times for us too since then. If it was, we + // need to release the semaphore too. + while (true) + { + oldCount = m_count.fetch_add_release(1); + if (oldCount < 0) + return false; // successfully restored things to the way they were + // Oh, the producer thread just signaled the semaphore after all. Try again: + oldCount = m_count.fetch_add_acquire(-1); + if (oldCount > 0 && m_sema.try_wait()) + return true; + } + } + + public: + AE_NO_TSAN LightweightSemaphore(ssize_t initialCount = 0) : m_count(initialCount), m_sema() + { + assert(initialCount >= 0); + } + + bool tryWait() AE_NO_TSAN + { + if (m_count.load() > 0) + { + m_count.fetch_add_acquire(-1); + return true; + } + return false; + } + + bool wait() AE_NO_TSAN + { + return tryWait() || waitWithPartialSpinning(); + } + + bool wait(std::int64_t timeout_usecs) AE_NO_TSAN + { + return tryWait() || waitWithPartialSpinning(timeout_usecs); + } + + void signal(ssize_t count = 1) AE_NO_TSAN + { + assert(count >= 0); + ssize_t oldCount = m_count.fetch_add_release(count); + assert(oldCount >= -1); + if (oldCount < 0) + { + m_sema.signal(1); + } + } + + std::size_t availableApprox() const AE_NO_TSAN + { + ssize_t count = m_count.load(); + return count > 0 ? static_cast(count) : 0; + } + }; + } // end namespace spsc_sema +} // end namespace moodycamel + +#if defined(AE_VCPP) && (_MSC_VER < 1700 || defined(__cplusplus_cli)) +#pragma warning(pop) +#ifdef __cplusplus_cli +#pragma managed(pop) +#endif +#endif \ No newline at end of file diff --git a/src/cpp/include/sorting/readerwriterqueue.h b/src/cpp/include/sorting/readerwriterqueue.h new file mode 100644 index 00000000..098d47cf --- /dev/null +++ b/src/cpp/include/sorting/readerwriterqueue.h @@ -0,0 +1,979 @@ +// ©2013-2020 Cameron Desrochers. +// Distributed under the simplified BSD license (see the license file that +// should have come with this header). + +#pragma once + +#include "atomicops.h" +#include +#include +#include +#include +#include +#include +#include +#include // For malloc/free/abort & size_t +#include +#if __cplusplus > 199711L || _MSC_VER >= 1700 // C++11 or VS2012 +#include +#endif + + +// A lock-free queue for a single-consumer, single-producer architecture. +// The queue is also wait-free in the common path (except if more memory +// needs to be allocated, in which case malloc is called). +// Allocates memory sparingly, and only once if the original maximum size +// estimate is never exceeded. +// Tested on x86/x64 processors, but semantics should be correct for all +// architectures (given the right implementations in atomicops.h), provided +// that aligned integer and pointer accesses are naturally atomic. +// Note that there should only be one consumer thread and producer thread; +// Switching roles of the threads, or using multiple consecutive threads for +// one role, is not safe unless properly synchronized. +// Using the queue exclusively from one thread is fine, though a bit silly. + +#ifndef MOODYCAMEL_CACHE_LINE_SIZE +#define MOODYCAMEL_CACHE_LINE_SIZE 64 +#endif + +#ifndef MOODYCAMEL_EXCEPTIONS_ENABLED +#if (defined(_MSC_VER) && defined(_CPPUNWIND)) || (defined(__GNUC__) && defined(__EXCEPTIONS)) || (!defined(_MSC_VER) && !defined(__GNUC__)) +#define MOODYCAMEL_EXCEPTIONS_ENABLED +#endif +#endif + +#ifndef MOODYCAMEL_HAS_EMPLACE +#if !defined(_MSC_VER) || _MSC_VER >= 1800 // variadic templates: either a non-MS compiler or VS >= 2013 +#define MOODYCAMEL_HAS_EMPLACE 1 +#endif +#endif + +#ifndef MOODYCAMEL_MAYBE_ALIGN_TO_CACHELINE +#if defined (__APPLE__) && defined (__MACH__) && __cplusplus >= 201703L +// This is required to find out what deployment target we are using +#include +#if !defined(MAC_OS_X_VERSION_MIN_REQUIRED) || !defined(MAC_OS_X_VERSION_10_14) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_14 +// C++17 new(size_t, align_val_t) is not backwards-compatible with older versions of macOS, so we can't support over-alignment in this case +#define MOODYCAMEL_MAYBE_ALIGN_TO_CACHELINE +#endif +#endif +#endif + +#ifndef MOODYCAMEL_MAYBE_ALIGN_TO_CACHELINE +#define MOODYCAMEL_MAYBE_ALIGN_TO_CACHELINE AE_ALIGN(MOODYCAMEL_CACHE_LINE_SIZE) +#endif + +#ifdef AE_VCPP +#pragma warning(push) +#pragma warning(disable: 4324) // structure was padded due to __declspec(align()) +#pragma warning(disable: 4820) // padding was added +#pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace moodycamel { + + template + class MOODYCAMEL_MAYBE_ALIGN_TO_CACHELINE ReaderWriterQueue +{ + // Design: Based on a queue-of-queues. The low-level queues are just + // circular buffers with front and tail indices indicating where the + // next element to dequeue is and where the next element can be enqueued, + // respectively. Each low-level queue is called a "block". Each block + // wastes exactly one element's worth of space to keep the design simple + // (if front == tail then the queue is empty, and can't be full). + // The high-level queue is a circular linked list of blocks; again there + // is a front and tail, but this time they are pointers to the blocks. + // The front block is where the next element to be dequeued is, provided + // the block is not empty. The back block is where elements are to be + // enqueued, provided the block is not full. + // The producer thread owns all the tail indices/pointers. The consumer + // thread owns all the front indices/pointers. Both threads read each + // other's variables, but only the owning thread updates them. E.g. After + // the consumer reads the producer's tail, the tail may change before the + // consumer is done dequeuing an object, but the consumer knows the tail + // will never go backwards, only forwards. + // If there is no room to enqueue an object, an additional block (of + // equal size to the last block) is added. Blocks are never removed. + + public: + typedef T value_type; + + // Constructs a queue that can hold at least `size` elements without further + // allocations. If more than MAX_BLOCK_SIZE elements are requested, + // then several blocks of MAX_BLOCK_SIZE each are reserved (including + // at least one extra buffer block). + AE_NO_TSAN explicit ReaderWriterQueue(size_t size = 15) +#ifndef NDEBUG + : enqueuing(false) + ,dequeuing(false) +#endif +{ + assert(MAX_BLOCK_SIZE == ceilToPow2(MAX_BLOCK_SIZE) && "MAX_BLOCK_SIZE must be a power of 2"); + assert(MAX_BLOCK_SIZE >= 2 && "MAX_BLOCK_SIZE must be at least 2"); + + Block* firstBlock = nullptr; + + largestBlockSize = ceilToPow2(size + 1); // We need a spare slot to fit size elements in the block + if (largestBlockSize > MAX_BLOCK_SIZE * 2) { + // We need a spare block in case the producer is writing to a different block the consumer is reading from, and + // wants to enqueue the maximum number of elements. We also need a spare element in each block to avoid the ambiguity + // between front == tail meaning "empty" and "full". + // So the effective number of slots that are guaranteed to be usable at any time is the block size - 1 times the + // number of blocks - 1. Solving for size and applying a ceiling to the division gives us (after simplifying): + size_t initialBlockCount = (size + MAX_BLOCK_SIZE * 2 - 3) / (MAX_BLOCK_SIZE - 1); + largestBlockSize = MAX_BLOCK_SIZE; + Block* lastBlock = nullptr; + for (size_t i = 0; i != initialBlockCount; ++i) { + auto block = make_block(largestBlockSize); + if (block == nullptr) { +#ifdef MOODYCAMEL_EXCEPTIONS_ENABLED + throw std::bad_alloc(); +#else + abort(); +#endif +} +if (firstBlock == nullptr) { +firstBlock = block; +} +else { +lastBlock->next = block; +} +lastBlock = block; +block->next = firstBlock; +} +} +else { +firstBlock = make_block(largestBlockSize); +if (firstBlock == nullptr) { +#ifdef MOODYCAMEL_EXCEPTIONS_ENABLED +throw std::bad_alloc(); +#else +abort(); +#endif +} +firstBlock->next = firstBlock; +} +frontBlock = firstBlock; +tailBlock = firstBlock; + +// Make sure the reader/writer threads will have the initialized memory setup above: +fence(memory_order_sync); +} + +// Note: The queue should not be accessed concurrently while it's +// being moved. It's up to the user to synchronize this. +AE_NO_TSAN ReaderWriterQueue(ReaderWriterQueue&& other) +: frontBlock(other.frontBlock.load()), +tailBlock(other.tailBlock.load()), +largestBlockSize(other.largestBlockSize) +#ifndef NDEBUG +,enqueuing(false) +,dequeuing(false) +#endif +{ +other.largestBlockSize = 32; +Block* b = other.make_block(other.largestBlockSize); +if (b == nullptr) { +#ifdef MOODYCAMEL_EXCEPTIONS_ENABLED +throw std::bad_alloc(); +#else +abort(); +#endif +} +b->next = b; +other.frontBlock = b; +other.tailBlock = b; +} + +// Note: The queue should not be accessed concurrently while it's +// being moved. It's up to the user to synchronize this. +ReaderWriterQueue& operator=(ReaderWriterQueue&& other) AE_NO_TSAN +{ +Block* b = frontBlock.load(); +frontBlock = other.frontBlock.load(); +other.frontBlock = b; +b = tailBlock.load(); +tailBlock = other.tailBlock.load(); +other.tailBlock = b; +std::swap(largestBlockSize, other.largestBlockSize); +return *this; +} + +// Note: The queue should not be accessed concurrently while it's +// being deleted. It's up to the user to synchronize this. +AE_NO_TSAN ~ReaderWriterQueue() +{ + // Make sure we get the latest version of all variables from other CPUs: + fence(memory_order_sync); + + // Destroy any remaining objects in queue and free memory + Block* frontBlock_ = frontBlock; + Block* block = frontBlock_; + do { + Block* nextBlock = block->next; + size_t blockFront = block->front; + size_t blockTail = block->tail; + + for (size_t i = blockFront; i != blockTail; i = (i + 1) & block->sizeMask) { + auto element = reinterpret_cast(block->data + i * sizeof(T)); + element->~T(); + (void)element; + } + + auto rawBlock = block->rawThis; + block->~Block(); + std::free(rawBlock); + block = nextBlock; + } while (block != frontBlock_); +} + + +// Enqueues a copy of element if there is room in the queue. +// Returns true if the element was enqueued, false otherwise. +// Does not allocate memory. +AE_FORCEINLINE bool try_enqueue(T const& element) AE_NO_TSAN +{ +return inner_enqueue(element); +} + +// Enqueues a moved copy of element if there is room in the queue. +// Returns true if the element was enqueued, false otherwise. +// Does not allocate memory. +AE_FORCEINLINE bool try_enqueue(T&& element) AE_NO_TSAN +{ +return inner_enqueue(std::forward(element)); +} + +#if MOODYCAMEL_HAS_EMPLACE +// Like try_enqueue() but with emplace semantics (i.e. construct-in-place). +template +AE_FORCEINLINE bool try_emplace(Args&&... args) AE_NO_TSAN +{ +return inner_enqueue(std::forward(args)...); +} +#endif + +// Enqueues a copy of element on the queue. +// Allocates an additional block of memory if needed. +// Only fails (returns false) if memory allocation fails. +AE_FORCEINLINE bool enqueue(T const& element) AE_NO_TSAN +{ +return inner_enqueue(element); +} + +// Enqueues a moved copy of element on the queue. +// Allocates an additional block of memory if needed. +// Only fails (returns false) if memory allocation fails. +AE_FORCEINLINE bool enqueue(T&& element) AE_NO_TSAN +{ +return inner_enqueue(std::forward(element)); +} + +#if MOODYCAMEL_HAS_EMPLACE +// Like enqueue() but with emplace semantics (i.e. construct-in-place). +template +AE_FORCEINLINE bool emplace(Args&&... args) AE_NO_TSAN +{ +return inner_enqueue(std::forward(args)...); +} +#endif + +// Attempts to dequeue an element; if the queue is empty, +// returns false instead. If the queue has at least one element, +// moves front to result using operator=, then returns true. +template +bool try_dequeue(U& result) AE_NO_TSAN +{ +#ifndef NDEBUG +ReentrantGuard guard(this->dequeuing); +#endif + +// High-level pseudocode: +// Remember where the tail block is +// If the front block has an element in it, dequeue it +// Else +// If front block was the tail block when we entered the function, return false +// Else advance to next block and dequeue the item there + +// Note that we have to use the value of the tail block from before we check if the front +// block is full or not, in case the front block is empty and then, before we check if the +// tail block is at the front block or not, the producer fills up the front block *and +// moves on*, which would make us skip a filled block. Seems unlikely, but was consistently +// reproducible in practice. +// In order to avoid overhead in the common case, though, we do a double-checked pattern +// where we have the fast path if the front block is not empty, then read the tail block, +// then re-read the front block and check if it's not empty again, then check if the tail +// block has advanced. + +Block* frontBlock_ = frontBlock.load(); +size_t blockTail = frontBlock_->localTail; +size_t blockFront = frontBlock_->front.load(); + +if (blockFront != blockTail || blockFront != (frontBlock_->localTail = frontBlock_->tail.load())) { +fence(memory_order_acquire); + +non_empty_front_block: +// Front block not empty, dequeue from here +auto element = reinterpret_cast(frontBlock_->data + blockFront * sizeof(T)); +result = std::move(*element); +element->~T(); + +blockFront = (blockFront + 1) & frontBlock_->sizeMask; + +fence(memory_order_release); +frontBlock_->front = blockFront; +} +else if (frontBlock_ != tailBlock.load()) { +fence(memory_order_acquire); + +frontBlock_ = frontBlock.load(); +blockTail = frontBlock_->localTail = frontBlock_->tail.load(); +blockFront = frontBlock_->front.load(); +fence(memory_order_acquire); + +if (blockFront != blockTail) { +// Oh look, the front block isn't empty after all +goto non_empty_front_block; +} + +// Front block is empty but there's another block ahead, advance to it +Block* nextBlock = frontBlock_->next; +// Don't need an acquire fence here since next can only ever be set on the tailBlock, +// and we're not the tailBlock, and we did an acquire earlier after reading tailBlock which +// ensures next is up-to-date on this CPU in case we recently were at tailBlock. + +size_t nextBlockFront = nextBlock->front.load(); +size_t nextBlockTail = nextBlock->localTail = nextBlock->tail.load(); +fence(memory_order_acquire); + +// Since the tailBlock is only ever advanced after being written to, +// we know there's for sure an element to dequeue on it +assert(nextBlockFront != nextBlockTail); +AE_UNUSED(nextBlockTail); + +// We're done with this block, let the producer use it if it needs +fence(memory_order_release); // Expose possibly pending changes to frontBlock->front from last dequeue +frontBlock = frontBlock_ = nextBlock; + +compiler_fence(memory_order_release); // Not strictly needed + +auto element = reinterpret_cast(frontBlock_->data + nextBlockFront * sizeof(T)); + +result = std::move(*element); +element->~T(); + +nextBlockFront = (nextBlockFront + 1) & frontBlock_->sizeMask; + +fence(memory_order_release); +frontBlock_->front = nextBlockFront; +} +else { +// No elements in current block and no other block to advance to +return false; +} + +return true; +} + + +// Returns a pointer to the front element in the queue (the one that +// would be removed next by a call to `try_dequeue` or `pop`). If the +// queue appears empty at the time the method is called, nullptr is +// returned instead. +// Must be called only from the consumer thread. +T* peek() const AE_NO_TSAN +{ +#ifndef NDEBUG +ReentrantGuard guard(this->dequeuing); +#endif +// See try_dequeue() for reasoning + +Block* frontBlock_ = frontBlock.load(); +size_t blockTail = frontBlock_->localTail; +size_t blockFront = frontBlock_->front.load(); + +if (blockFront != blockTail || blockFront != (frontBlock_->localTail = frontBlock_->tail.load())) { +fence(memory_order_acquire); +non_empty_front_block: +return reinterpret_cast(frontBlock_->data + blockFront * sizeof(T)); +} +else if (frontBlock_ != tailBlock.load()) { +fence(memory_order_acquire); +frontBlock_ = frontBlock.load(); +blockTail = frontBlock_->localTail = frontBlock_->tail.load(); +blockFront = frontBlock_->front.load(); +fence(memory_order_acquire); + +if (blockFront != blockTail) { +goto non_empty_front_block; +} + +Block* nextBlock = frontBlock_->next; + +size_t nextBlockFront = nextBlock->front.load(); +fence(memory_order_acquire); + +assert(nextBlockFront != nextBlock->tail.load()); +return reinterpret_cast(nextBlock->data + nextBlockFront * sizeof(T)); +} + +return nullptr; +} + +// Removes the front element from the queue, if any, without returning it. +// Returns true on success, or false if the queue appeared empty at the time +// `pop` was called. +bool pop() AE_NO_TSAN +{ +#ifndef NDEBUG +ReentrantGuard guard(this->dequeuing); +#endif +// See try_dequeue() for reasoning + +Block* frontBlock_ = frontBlock.load(); +size_t blockTail = frontBlock_->localTail; +size_t blockFront = frontBlock_->front.load(); + +if (blockFront != blockTail || blockFront != (frontBlock_->localTail = frontBlock_->tail.load())) { +fence(memory_order_acquire); + +non_empty_front_block: +auto element = reinterpret_cast(frontBlock_->data + blockFront * sizeof(T)); +element->~T(); + +blockFront = (blockFront + 1) & frontBlock_->sizeMask; + +fence(memory_order_release); +frontBlock_->front = blockFront; +} +else if (frontBlock_ != tailBlock.load()) { +fence(memory_order_acquire); +frontBlock_ = frontBlock.load(); +blockTail = frontBlock_->localTail = frontBlock_->tail.load(); +blockFront = frontBlock_->front.load(); +fence(memory_order_acquire); + +if (blockFront != blockTail) { +goto non_empty_front_block; +} + +// Front block is empty but there's another block ahead, advance to it +Block* nextBlock = frontBlock_->next; + +size_t nextBlockFront = nextBlock->front.load(); +size_t nextBlockTail = nextBlock->localTail = nextBlock->tail.load(); +fence(memory_order_acquire); + +assert(nextBlockFront != nextBlockTail); +AE_UNUSED(nextBlockTail); + +fence(memory_order_release); +frontBlock = frontBlock_ = nextBlock; + +compiler_fence(memory_order_release); + +auto element = reinterpret_cast(frontBlock_->data + nextBlockFront * sizeof(T)); +element->~T(); + +nextBlockFront = (nextBlockFront + 1) & frontBlock_->sizeMask; + +fence(memory_order_release); +frontBlock_->front = nextBlockFront; +} +else { +// No elements in current block and no other block to advance to +return false; +} + +return true; +} + +// Returns the approximate number of items currently in the queue. +// Safe to call from both the producer and consumer threads. +inline size_t size_approx() const AE_NO_TSAN +{ +size_t result = 0; +Block* frontBlock_ = frontBlock.load(); +Block* block = frontBlock_; +do { +fence(memory_order_acquire); +size_t blockFront = block->front.load(); +size_t blockTail = block->tail.load(); +result += (blockTail - blockFront) & block->sizeMask; +block = block->next.load(); +} while (block != frontBlock_); +return result; +} + +// Returns the total number of items that could be enqueued without incurring +// an allocation when this queue is empty. +// Safe to call from both the producer and consumer threads. +// +// NOTE: The actual capacity during usage may be different depending on the consumer. +// If the consumer is removing elements concurrently, the producer cannot add to +// the block the consumer is removing from until it's completely empty, except in +// the case where the producer was writing to the same block the consumer was +// reading from the whole time. +inline size_t max_capacity() const { + size_t result = 0; + Block* frontBlock_ = frontBlock.load(); + Block* block = frontBlock_; + do { + fence(memory_order_acquire); + result += block->sizeMask; + block = block->next.load(); + } while (block != frontBlock_); + return result; +} + + +private: +enum AllocationMode { CanAlloc, CannotAlloc }; + +#if MOODYCAMEL_HAS_EMPLACE +template +bool inner_enqueue(Args&&... args) AE_NO_TSAN +#else +template + bool inner_enqueue(U&& element) AE_NO_TSAN +#endif +{ +#ifndef NDEBUG +ReentrantGuard guard(this->enqueuing); +#endif + +// High-level pseudocode (assuming we're allowed to alloc a new block): +// If room in tail block, add to tail +// Else check next block +// If next block is not the head block, enqueue on next block +// Else create a new block and enqueue there +// Advance tail to the block we just enqueued to + +Block* tailBlock_ = tailBlock.load(); +size_t blockFront = tailBlock_->localFront; +size_t blockTail = tailBlock_->tail.load(); + +size_t nextBlockTail = (blockTail + 1) & tailBlock_->sizeMask; +if (nextBlockTail != blockFront || nextBlockTail != (tailBlock_->localFront = tailBlock_->front.load())) { +fence(memory_order_acquire); +// This block has room for at least one more element +char* location = tailBlock_->data + blockTail * sizeof(T); +#if MOODYCAMEL_HAS_EMPLACE +new (location) T(std::forward(args)...); +#else +new (location) T(std::forward(element)); +#endif + +fence(memory_order_release); +tailBlock_->tail = nextBlockTail; +} +else { +fence(memory_order_acquire); +if (tailBlock_->next.load() != frontBlock) { +// Note that the reason we can't advance to the frontBlock and start adding new entries there +// is because if we did, then dequeue would stay in that block, eventually reading the new values, +// instead of advancing to the next full block (whose values were enqueued first and so should be +// consumed first). + +fence(memory_order_acquire); // Ensure we get latest writes if we got the latest frontBlock + +// tailBlock is full, but there's a free block ahead, use it +Block* tailBlockNext = tailBlock_->next.load(); +size_t nextBlockFront = tailBlockNext->localFront = tailBlockNext->front.load(); +nextBlockTail = tailBlockNext->tail.load(); +fence(memory_order_acquire); + +// This block must be empty since it's not the head block and we +// go through the blocks in a circle +assert(nextBlockFront == nextBlockTail); +tailBlockNext->localFront = nextBlockFront; + +char* location = tailBlockNext->data + nextBlockTail * sizeof(T); +#if MOODYCAMEL_HAS_EMPLACE +new (location) T(std::forward(args)...); +#else +new (location) T(std::forward(element)); +#endif + +tailBlockNext->tail = (nextBlockTail + 1) & tailBlockNext->sizeMask; + +fence(memory_order_release); +tailBlock = tailBlockNext; +} +else if (canAlloc == CanAlloc) { +// tailBlock is full and there's no free block ahead; create a new block +auto newBlockSize = largestBlockSize >= MAX_BLOCK_SIZE ? largestBlockSize : largestBlockSize * 2; +auto newBlock = make_block(newBlockSize); +if (newBlock == nullptr) { +// Could not allocate a block! +return false; +} +largestBlockSize = newBlockSize; + +#if MOODYCAMEL_HAS_EMPLACE +new (newBlock->data) T(std::forward(args)...); +#else +new (newBlock->data) T(std::forward(element)); +#endif +assert(newBlock->front == 0); +newBlock->tail = newBlock->localTail = 1; + +newBlock->next = tailBlock_->next.load(); +tailBlock_->next = newBlock; + +// Might be possible for the dequeue thread to see the new tailBlock->next +// *without* seeing the new tailBlock value, but this is OK since it can't +// advance to the next block until tailBlock is set anyway (because the only +// case where it could try to read the next is if it's already at the tailBlock, +// and it won't advance past tailBlock in any circumstance). + +fence(memory_order_release); +tailBlock = newBlock; +} +else if (canAlloc == CannotAlloc) { +// Would have had to allocate a new block to enqueue, but not allowed +return false; +} +else { +assert(false && "Should be unreachable code"); +return false; +} +} + +return true; +} + + +// Disable copying +ReaderWriterQueue(ReaderWriterQueue const&) { } + +// Disable assignment +ReaderWriterQueue& operator=(ReaderWriterQueue const&) { } + + +AE_FORCEINLINE static size_t ceilToPow2(size_t x) +{ +// From http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 +--x; +x |= x >> 1; +x |= x >> 2; +x |= x >> 4; +for (size_t i = 1; i < sizeof(size_t); i <<= 1) { +x |= x >> (i << 3); +} +++x; +return x; +} + +template +static AE_FORCEINLINE char* align_for(char* ptr) AE_NO_TSAN +{ +const std::size_t alignment = std::alignment_of::value; +return ptr + (alignment - (reinterpret_cast(ptr) % alignment)) % alignment; +} +private: +#ifndef NDEBUG +struct ReentrantGuard +{ + AE_NO_TSAN ReentrantGuard(weak_atomic& _inSection) + : inSection(_inSection) + { + assert(!inSection && "Concurrent (or re-entrant) enqueue or dequeue operation detected (only one thread at a time may hold the producer or consumer role)"); + inSection = true; + } + + AE_NO_TSAN ~ReentrantGuard() { inSection = false; } + +private: + ReentrantGuard& operator=(ReentrantGuard const&); + +private: + weak_atomic& inSection; +}; +#endif + +struct Block +{ + // Avoid false-sharing by putting highly contended variables on their own cache lines + weak_atomic front; // (Atomic) Elements are read from here + size_t localTail; // An uncontended shadow copy of tail, owned by the consumer + + char cachelineFiller0[MOODYCAMEL_CACHE_LINE_SIZE - sizeof(weak_atomic) - sizeof(size_t)]; + weak_atomic tail; // (Atomic) Elements are enqueued here + size_t localFront; + + char cachelineFiller1[MOODYCAMEL_CACHE_LINE_SIZE - sizeof(weak_atomic) - sizeof(size_t)]; // next isn't very contended, but we don't want it on the same cache line as tail (which is) + weak_atomic next; // (Atomic) + + char* data; // Contents (on heap) are aligned to T's alignment + + const size_t sizeMask; + + + // size must be a power of two (and greater than 0) + AE_NO_TSAN Block(size_t const& _size, char* _rawThis, char* _data) + : front(0UL), localTail(0), tail(0UL), localFront(0), next(nullptr), data(_data), sizeMask(_size - 1), rawThis(_rawThis) + { + } + +private: + // C4512 - Assignment operator could not be generated + Block& operator=(Block const&); + +public: + char* rawThis; +}; + + +static Block* make_block(size_t capacity) AE_NO_TSAN +{ +// Allocate enough memory for the block itself, as well as all the elements it will contain +auto size = sizeof(Block) + std::alignment_of::value - 1; +size += sizeof(T) * capacity + std::alignment_of::value - 1; +auto newBlockRaw = static_cast(std::malloc(size)); +if (newBlockRaw == nullptr) { +return nullptr; +} + +auto newBlockAligned = align_for(newBlockRaw); +auto newBlockData = align_for(newBlockAligned + sizeof(Block)); +return new (newBlockAligned) Block(capacity, newBlockRaw, newBlockData); +} + +private: +weak_atomic frontBlock; // (Atomic) Elements are dequeued from this block + +char cachelineFiller[MOODYCAMEL_CACHE_LINE_SIZE - sizeof(weak_atomic)]; +weak_atomic tailBlock; // (Atomic) Elements are enqueued to this block + +size_t largestBlockSize; + +#ifndef NDEBUG +weak_atomic enqueuing; +mutable weak_atomic dequeuing; +#endif +}; + +// Like ReaderWriterQueue, but also providees blocking operations +template +class BlockingReaderWriterQueue +{ +private: + typedef ::moodycamel::ReaderWriterQueue ReaderWriterQueue; + +public: + explicit BlockingReaderWriterQueue(size_t size = 15) AE_NO_TSAN + : inner(size), sema(new spsc_sema::LightweightSemaphore()) + { } + + BlockingReaderWriterQueue(BlockingReaderWriterQueue&& other) AE_NO_TSAN + : inner(std::move(other.inner)), sema(std::move(other.sema)) + { } + + BlockingReaderWriterQueue& operator=(BlockingReaderWriterQueue&& other) AE_NO_TSAN + { + std::swap(sema, other.sema); + std::swap(inner, other.inner); + return *this; + } + + + // Enqueues a copy of element if there is room in the queue. + // Returns true if the element was enqueued, false otherwise. + // Does not allocate memory. + AE_FORCEINLINE bool try_enqueue(T const& element) AE_NO_TSAN + { + if (inner.try_enqueue(element)) { + sema->signal(); + return true; + } + return false; + } + + // Enqueues a moved copy of element if there is room in the queue. + // Returns true if the element was enqueued, false otherwise. + // Does not allocate memory. + AE_FORCEINLINE bool try_enqueue(T&& element) AE_NO_TSAN + { + if (inner.try_enqueue(std::forward(element))) { + sema->signal(); + return true; + } + return false; + } + +#if MOODYCAMEL_HAS_EMPLACE + // Like try_enqueue() but with emplace semantics (i.e. construct-in-place). + template + AE_FORCEINLINE bool try_emplace(Args&&... args) AE_NO_TSAN + { + if (inner.try_emplace(std::forward(args)...)) { + sema->signal(); + return true; + } + return false; + } +#endif + + + // Enqueues a copy of element on the queue. + // Allocates an additional block of memory if needed. + // Only fails (returns false) if memory allocation fails. + AE_FORCEINLINE bool enqueue(T const& element) AE_NO_TSAN + { + if (inner.enqueue(element)) { + sema->signal(); + return true; + } + return false; + } + + // Enqueues a moved copy of element on the queue. + // Allocates an additional block of memory if needed. + // Only fails (returns false) if memory allocation fails. + AE_FORCEINLINE bool enqueue(T&& element) AE_NO_TSAN + { + if (inner.enqueue(std::forward(element))) { + sema->signal(); + return true; + } + return false; + } + +#if MOODYCAMEL_HAS_EMPLACE + // Like enqueue() but with emplace semantics (i.e. construct-in-place). + template + AE_FORCEINLINE bool emplace(Args&&... args) AE_NO_TSAN + { + if (inner.emplace(std::forward(args)...)) { + sema->signal(); + return true; + } + return false; + } +#endif + + + // Attempts to dequeue an element; if the queue is empty, + // returns false instead. If the queue has at least one element, + // moves front to result using operator=, then returns true. + template + bool try_dequeue(U& result) AE_NO_TSAN + { + if (sema->tryWait()) { + bool success = inner.try_dequeue(result); + assert(success); + AE_UNUSED(success); + return true; + } + return false; + } + + + // Attempts to dequeue an element; if the queue is empty, + // waits until an element is available, then dequeues it. + template + void wait_dequeue(U& result) AE_NO_TSAN + { + while (!sema->wait()); + bool success = inner.try_dequeue(result); + AE_UNUSED(result); + assert(success); + AE_UNUSED(success); + } + + + // Attempts to dequeue an element; if the queue is empty, + // waits until an element is available up to the specified timeout, + // then dequeues it and returns true, or returns false if the timeout + // expires before an element can be dequeued. + // Using a negative timeout indicates an indefinite timeout, + // and is thus functionally equivalent to calling wait_dequeue. + template + bool wait_dequeue_timed(U& result, std::int64_t timeout_usecs) AE_NO_TSAN + { + if (!sema->wait(timeout_usecs)) { + return false; + } + bool success = inner.try_dequeue(result); + AE_UNUSED(result); + assert(success); + AE_UNUSED(success); + return true; + } + + +#if __cplusplus > 199711L || _MSC_VER >= 1700 + // Attempts to dequeue an element; if the queue is empty, + // waits until an element is available up to the specified timeout, + // then dequeues it and returns true, or returns false if the timeout + // expires before an element can be dequeued. + // Using a negative timeout indicates an indefinite timeout, + // and is thus functionally equivalent to calling wait_dequeue. + template + inline bool wait_dequeue_timed(U& result, std::chrono::duration const& timeout) AE_NO_TSAN + { + return wait_dequeue_timed(result, std::chrono::duration_cast(timeout).count()); + } +#endif + + + // Returns a pointer to the front element in the queue (the one that + // would be removed next by a call to `try_dequeue` or `pop`). If the + // queue appears empty at the time the method is called, nullptr is + // returned instead. + // Must be called only from the consumer thread. + AE_FORCEINLINE T* peek() const AE_NO_TSAN + { + return inner.peek(); + } + + // Removes the front element from the queue, if any, without returning it. + // Returns true on success, or false if the queue appeared empty at the time + // `pop` was called. + AE_FORCEINLINE bool pop() AE_NO_TSAN + { + if (sema->tryWait()) { + bool result = inner.pop(); + assert(result); + AE_UNUSED(result); + return true; + } + return false; + } + + // Returns the approximate number of items currently in the queue. + // Safe to call from both the producer and consumer threads. + AE_FORCEINLINE size_t size_approx() const AE_NO_TSAN + { + return sema->availableApprox(); + } + + // Returns the total number of items that could be enqueued without incurring + // an allocation when this queue is empty. + // Safe to call from both the producer and consumer threads. + // + // NOTE: The actual capacity during usage may be different depending on the consumer. + // If the consumer is removing elements concurrently, the producer cannot add to + // the block the consumer is removing from until it's completely empty, except in + // the case where the producer was writing to the same block the consumer was + // reading from the whole time. + AE_FORCEINLINE size_t max_capacity() const { + return inner.max_capacity(); + } + +private: + // Disable copying & assignment + BlockingReaderWriterQueue(BlockingReaderWriterQueue const&) { } + BlockingReaderWriterQueue& operator=(BlockingReaderWriterQueue const&) { } + +private: + ReaderWriterQueue inner; + std::unique_ptr sema; +}; + +} // end namespace moodycamel + +#ifdef AE_VCPP +#pragma warning(pop) +#endif \ No newline at end of file From 0c4528a5edc3fd5b9a39c147746894158c2ce7e8 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 23 May 2025 00:32:49 -0500 Subject: [PATCH 224/323] limit busy waiting --- src/cpp/include/common.h | 1 + src/cpp/include/query_coordinator.h | 11 +- src/cpp/src/query_coordinator.cpp | 173 +++++++++++------- .../numa_multi_query/configs/sift1m.yaml | 94 +++++----- 4 files changed, 166 insertions(+), 113 deletions(-) diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index b165ac5f..88173e28 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -75,6 +75,7 @@ constexpr bool DEFAULT_PRECOMPUTED = true; ///< Default flag to us constexpr float DEFAULT_INITIAL_SEARCH_FRACTION = 0.1f; ///< Default initial fraction of partitions to search. constexpr float DEFAULT_RECOMPUTE_THRESHOLD = 0.001f; ///< Default threshold to trigger recomputation of search parameters. constexpr int DEFAULT_APS_FLUSH_PERIOD_US = 5; ///< Default period (in microseconds) for flushing the APS buffer. +constexpr int MAX_SUBBATCH = 128; // Default constants for maintenance policy parameters constexpr const char* DEFAULT_MAINTENANCE_POLICY = "query_cost"; ///< Default maintenance policy type. diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 8e6ee53d..eb47faba 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -59,8 +59,6 @@ class QueryCoordinator { struct CoreResources { int core_id; std::vector> topk_buffer_pool; -// moodycamel::ConcurrentQueue job_queue; - moodycamel::BlockingReaderWriterQueue job_queue; // Thread-local buffers for batched queries float* batch_queries = nullptr; // batched query buffer (NUMA-allocated) @@ -68,11 +66,19 @@ class QueryCoordinator { int64_t* batch_ids = nullptr; // scratch space for ids size_t batch_q_capacity = 0; // number of floats in batch_queries size_t batch_res_capacity = 0; // number of (k×Q) slots in distances & ids + + int64_t job_counter = 0; ///< Job counter for this core. + int64_t queries_counter = 0; ///< Number of queries processed by this core. + int64_t wait_time_ns = 0; ///< Time spent waiting for jobs. + int64_t process_time_ns = 0; ///< Time spent scanning. + int64_t enqueue_time_ns = 0; ///< Time spent enqueuing. + int64_t job_time_ns = 0; ///< Time spent on job processing (excluding waiting). }; struct NUMAResources { float* local_query_buffer = nullptr; size_t buffer_size = 0; + moodycamel::BlockingConcurrentQueue job_queue; }; struct ResultJob { @@ -103,7 +109,6 @@ class QueryCoordinator { std::atomic job_pull_time_ns = 0; ///< Time spent pulling jobs from the queue. std::atomic job_process_time_ns = 0; ///< Time spent processing jobs. - /** * @brief Constructs a QueryCoordinator. * diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 6c6f6e8f..d33ed6e2 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -80,17 +80,30 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { set_thread_affinity(core_index); int i = 0; + res.wait_time_ns = 0; + res.process_time_ns = 0; + res.enqueue_time_ns = 0; + res.job_time_ns = 0; + while (!stop_workers_) { int64_t jid = 0; - res.job_queue.wait_dequeue(jid); + auto start = std::chrono::high_resolution_clock::now(); + nr.job_queue.wait_dequeue(jid); + auto end = std::chrono::high_resolution_clock::now(); + + res.wait_time_ns += std::chrono::duration_cast(end - start).count(); if (jid == -1) { break; } + process_scan_job(job_buffer_[jid], res); i++; + end = std::chrono::high_resolution_clock::now(); + + res.job_time_ns += std::chrono::duration_cast(end - start).count(); } } @@ -140,6 +153,8 @@ void QueryCoordinator::process_scan_job(ScanJob job, } else { handle_batched_job(job, res, nr); } + res.queries_counter += job.num_queries; + res.job_counter++; } void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, @@ -217,6 +232,7 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, void QueryCoordinator::handle_batched_job(const ScanJob &job, CoreResources &res, NUMAResources &nr) { + // Total queries, Top-K, dimension, NUMA node int64_t Q = job.num_queries; int K = job.k; @@ -308,6 +324,7 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, __builtin_prefetch(codes, 0, 3); __builtin_prefetch(ids, 0, 3); + auto start = std::chrono::high_resolution_clock::now(); // run the scan on this chunk batched_scan_list( qptr, @@ -318,6 +335,8 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, res.batch_distances, res.batch_ids ); + auto end = std::chrono::high_resolution_clock::now(); + res.process_time_ns += std::chrono::duration_cast(end - start).count(); // collect results for this chunk std::vector results_batch; @@ -329,12 +348,14 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, auto ti = res.topk_buffer_pool[i]->get_topk_indices(); results_batch.emplace_back(ResultJob{global_q, rank_q, std::move(tv), std::move(ti)}); } - + start = std::chrono::high_resolution_clock::now(); // enqueue this sub-batch in bulk result_queue_.enqueue_bulk( std::make_move_iterator(results_batch.begin()), results_batch.size() ); + end = std::chrono::high_resolution_clock::now(); + res.enqueue_time_ns += std::chrono::duration_cast(end - start).count(); } } @@ -391,6 +412,11 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, auto partition_ids_acc = partition_ids.accessor(); + vector core_to_numa(num_workers_); + for (int i = 0; i < num_workers_; ++i) { + core_to_numa[i] = cpu_numa_node(i); + } + // flatten jobs next_job_id_ = 0; job_flags_.clear(); @@ -420,74 +446,54 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, job.query_vector = qptr; job.rank = p; job_buffer_.push_back(job); - core_resources_[pid % num_workers_].job_queue.enqueue(next_job_id_); + numa_resources_[core_to_numa[pid % num_workers_]].job_queue.enqueue(next_job_id_); next_job_id_++; } } } else { - job_buffer_.resize(partition_manager_->nlist()); - auto pids = partition_manager_->get_partition_ids(); - auto pids_acc = pids.accessor(); - - if (pids.size(0) == partition_ids.size(1)) { - vector all_query_ids = std::vector(x.size(0)); - std::iota(all_query_ids.begin(), all_query_ids.end(), 0); - shared_ptr> all_query_ids_ptr = make_shared>(all_query_ids); - for (int64_t i = 0; i < pids.size(0); i++) { - ScanJob job; - job.is_batched = true; - job.partition_id = pids_acc[i]; - job.k = params->k; - job.query_vector = x.data_ptr(); - job.num_queries = x.size(0); - job.scan_all = true; - job.query_ids = all_query_ids_ptr; - job.ranks = make_shared>(x.size(0), i); - int core_id = partition_manager_->get_partition_core_id(pids_acc[i]); - if (core_id < 0) { - throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); - } - job_buffer_[next_job_id_] = job; - core_resources_[core_id].job_queue.enqueue(next_job_id_); - next_job_id_++; + /* Build per-partition query lists -------------------------------------- */ + std::vector>> qlist(partition_manager_->nlist()); + for (int64_t q = 0; q < nQ; ++q) { + for (int p = 0; p < partition_ids.size(1); ++p) { + int64_t pid = pid_acc[q][p]; + if (pid >= 0) qlist[pid].emplace_back(q, p); } + } - } else { - std::unordered_map>>> per_partition_query_ids; // for batched scan - for (int64_t q = 0; q < nQ; q++) { - for (int64_t p = 0; p < partition_ids.size(1); p++) { - int64_t pid = pid_acc[q][p]; - if (pid < 0) continue; - if (per_partition_query_ids[pid] == nullptr) { - per_partition_query_ids[pid] = make_shared>>(); - } - per_partition_query_ids[pid]->push_back({q, p}); - } - } - for (auto &kv : per_partition_query_ids) { - - auto qids_and_ranks = kv.second; - vector qids(qids_and_ranks->size()); - vector ranks(qids_and_ranks->size()); - for (size_t i = 0; i < qids_and_ranks->size(); ++i) { - qids[i] = (*qids_and_ranks)[i].first; - ranks[i] = (*qids_and_ranks)[i].second; + /* Emit ScanJobs, already split into ≤ MAX_SUBBATCH chunks -------------- */ + for (int64_t pid = 0; pid < (int64_t)qlist.size(); ++pid) { + auto &pairs = qlist[pid]; + if (pairs.empty()) continue; + + for (size_t off = 0; off < pairs.size(); off += MAX_SUBBATCH) { + size_t chunk = std::min(MAX_SUBBATCH, pairs.size() - off); + + // Split query / rank vectors for this chunk. + auto qids = std::make_shared>(); + auto ranks = std::make_shared>(); + qids ->reserve(chunk); + ranks->reserve(chunk); + for (size_t i = 0; i < chunk; ++i) { + qids ->push_back(pairs[off + i].first); + ranks->push_back(pairs[off + i].second); } ScanJob job; - job.is_batched = true; - job.partition_id = kv.first; - job.k = params->k; - job.query_vector = x.data_ptr(); - job.num_queries = kv.second->size(); - job.query_ids = make_shared>(qids); - job.ranks = make_shared>(ranks); - int core_id = partition_manager_->get_partition_core_id(kv.first); - if (core_id < 0) { - throw std::runtime_error("[QueryCoordinator::worker_scan] Invalid core ID."); - } - job_buffer_[next_job_id_] = job; - core_resources_[core_id].job_queue.enqueue(next_job_id_); + job.is_batched = true; + job.partition_id = pid; + job.k = params->k; + job.num_queries = static_cast(chunk); + job.query_vector = xptr; // whole matrix; we gather later + job.query_ids = qids; + job.ranks = ranks; + job.scan_all = (chunk == static_cast(nQ)); // true only if every query in this chunk + + job_buffer_.push_back(job); + + // Choose NUMA queue by partition-to-core mapping. + int core = pid % num_workers_; + int node = core_to_numa[core]; + numa_resources_[node].job_queue.enqueue(next_job_id_); next_job_id_++; } } @@ -640,6 +646,19 @@ std::shared_ptr QueryCoordinator::worker_scan( timing->n_clusters = partition_manager_->nlist(); timing->search_params = params; + + // get initial values of the per-core resource timers; + vector core_wait_time_ns(num_workers_, 0); + vector core_process_time_ns(num_workers_, 0); + vector core_enqueue_time_ns(num_workers_, 0); + vector core_job_time_ns(num_workers_, 0); + for (int i = 0; i < num_workers_; ++i) { + core_wait_time_ns[i] = core_resources_[i].wait_time_ns; + core_process_time_ns[i] = core_resources_[i].process_time_ns; + core_enqueue_time_ns[i] = core_resources_[i].enqueue_time_ns; + core_job_time_ns[i] = core_resources_[i].job_time_ns; + } + auto s1 = high_resolution_clock::now(); // 1) init global buffers & jobs_left @@ -678,6 +697,33 @@ std::shared_ptr QueryCoordinator::worker_scan( res->timing_info->result_aggregate_time_ns = duration_cast(s6 - s5).count(); + // retrieve the final values of the per-core resource timers; + for (int i = 0; i < num_workers_; ++i) { + core_wait_time_ns[i] = core_resources_[i].wait_time_ns - core_wait_time_ns[i]; + core_process_time_ns[i] = core_resources_[i].process_time_ns - core_process_time_ns[i]; + core_enqueue_time_ns[i] = core_resources_[i].enqueue_time_ns - core_enqueue_time_ns[i]; + core_job_time_ns[i] = core_resources_[i].job_time_ns - core_job_time_ns[i]; + } + + + // print out the per-core resource timers; + for (int i = 0; i < num_workers_; ++i) { + std::cout << "[QueryCoordinator::worker_scan] Core " << i << ": " + << "wait_time_ms=" << (float) core_wait_time_ns[i] / 1e6 << " " + << "process_time_ms=" << (float) core_process_time_ns[i] / 1e6 << " " + << "enqueue_time_ms=" << (float) core_enqueue_time_ns[i] / 1e6 << " " + << "job_time_ms=" << (float) core_job_time_ns[i] / 1e6 << std::endl; + } + + // print out the main thread timers; + std::cout << "[QueryCoordinator::worker_scan] Main thread: " + << "buffer_init_time_ms=" << (float) res->timing_info->buffer_init_time_ns / 1e6 << " " + << "copy_query_time_ms=" << (float) res->timing_info->copy_query_time_ns / 1e6 << " " + << "job_enqueue_time_ms=" << (float) res->timing_info->job_enqueue_time_ns / 1e6 << " " + << "job_wait_time_ms=" << (float) res->timing_info->job_wait_time_ns / 1e6 << " " + << "result_aggregate_time_ms=" << (float) res->timing_info->result_aggregate_time_ns / 1e6 + << std::endl; + return res; } @@ -718,8 +764,9 @@ void QueryCoordinator::shutdown_workers() { stop_workers_.store(true); // Enqueue a special shutdown job for each core. - for (auto &res : core_resources_) { - res.job_queue.enqueue(-1); + for (auto &res : numa_resources_) { + for (int i = 0; i < num_workers_; ++i) + res.job_queue.enqueue(-1); } // Join all worker threads. for (auto &thr : worker_threads_) { diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index 81e203a6..44a4acd3 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -15,57 +15,57 @@ indexes: build_params: nc: 1000 metric: l2 - num_workers: 16 + num_workers: 12 use_numa: false - parent_num_workers: 4 + parent_num_workers: 1 search_params: - nprobe: 20 + nprobe: 200 batched_scan: true +# +# - name: Quake_16_numa +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 16 +# use_numa: true +# parent_num_workers: 4 +# search_params: +# nprobe: 20 +# batched_scan: true +# +# - name: Quake_16_numa_no_batch +# index: Quake +# build_params: +# nc: 1000 +# metric: l2 +# num_workers: 16 +# use_numa: true +# parent_num_workers: 4 +# search_params: +# nprobe: 20 +# batched_scan: false - - name: Quake_16_numa - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 16 - use_numa: true - parent_num_workers: 4 - search_params: - nprobe: 20 - batched_scan: true - - - name: Quake_16_numa_no_batch - index: Quake - build_params: - nc: 1000 - metric: l2 - num_workers: 16 - use_numa: true - parent_num_workers: 4 - search_params: - nprobe: 20 - batched_scan: false - - - name: FaissIVF - index: IVF - build_params: - nc: 1000 - metric: l2 - search_params: - nprobe: 20 - omp_num_threads_search: 16 - - - - name: FaissHNSW - index: HNSW - build_params: - m: 64 - ef_construction: 128 - metric: l2 - omp_num_threads_build: 32 - search_params: - ef_search: 128 - omp_num_threads_search: 32 +# - name: FaissIVF +# index: IVF +# build_params: +# nc: 1000 +# metric: l2 +# search_params: +# nprobe: 20 +# omp_num_threads_search: 16 +# +# +# - name: FaissHNSW +# index: HNSW +# build_params: +# m: 64 +# ef_construction: 128 +# metric: l2 +# omp_num_threads_build: 32 +# search_params: +# ef_search: 128 +# omp_num_threads_search: 32 # # - name: SCANN From 0e34285e18bd607145991f84f19dbfd61ba3df04 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 23 May 2025 00:44:24 -0500 Subject: [PATCH 225/323] limit busy waiting --- src/cpp/src/query_coordinator.cpp | 2 +- .../osdi2025/numa_multi_query/configs/sift1m.yaml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index d33ed6e2..45b607ab 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -765,7 +765,7 @@ void QueryCoordinator::shutdown_workers() { stop_workers_.store(true); // Enqueue a special shutdown job for each core. for (auto &res : numa_resources_) { - for (int i = 0; i < num_workers_; ++i) + for (int i = 0; i < num_workers_ * 5; ++i) res.job_queue.enqueue(-1); } // Join all worker threads. diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index 44a4acd3..c4226c70 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -1,8 +1,8 @@ # numa_latency_experiment.yaml dataset: name: sift1m - num_queries: 1000 - k: 100 + num_queries: 10000 + k: 1 trials: 3 warmup: 1 @@ -19,7 +19,7 @@ indexes: use_numa: false parent_num_workers: 1 search_params: - nprobe: 200 + nprobe: 20 batched_scan: true # # - name: Quake_16_numa From 2fa48301944e6b22bc1945d50a68e87eefbd5af2 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 23 May 2025 00:55:17 -0500 Subject: [PATCH 226/323] limit busy waiting --- src/cpp/src/query_coordinator.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 45b607ab..5521a2da 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -115,6 +115,14 @@ void QueryCoordinator::process_scan_job(ScanJob job, #endif NUMAResources &nr = numa_resources_[numa_node]; + auto enqueue_empty_batch = [&](const ScanJob& j) { + const auto& qids = *j.query_ids; + const auto& ranks = *j.ranks; // same length as qids + for (size_t idx = 0; idx < qids.size(); ++idx) { + result_queue_.enqueue(ResultJob{qids[idx], ranks[idx], {}, {}}); + } + }; + // Attempt to fetch partition data; if the list doesn't exist, catch and enqueue empty results. const float *codes = nullptr; const int64_t *ids = nullptr; @@ -127,9 +135,7 @@ void QueryCoordinator::process_scan_job(ScanJob job, std::cerr << "[process_scan_job] Partition " << job.partition_id << " invalid: " << e.what() << ". Returning empty result(s).\n"; if (job.is_batched) { - for (int64_t q : *job.query_ids) { - result_queue_.enqueue(ResultJob{(int)q, 0, {}, {}}); - } + enqueue_empty_batch(job); } else { result_queue_.enqueue(ResultJob{job.query_id, job.rank, {}, {}}); } @@ -139,9 +145,7 @@ void QueryCoordinator::process_scan_job(ScanJob job, if (part_size == 0) { // empty => enqueue zero‐work per query if (job.is_batched) { - for (int64_t q : *job.query_ids) { - result_queue_.enqueue(ResultJob{(int)q, 0, {}, {}}); - } + enqueue_empty_batch(job); } else { result_queue_.enqueue(ResultJob{job.query_id, job.rank, {}, {}}); } @@ -765,7 +769,7 @@ void QueryCoordinator::shutdown_workers() { stop_workers_.store(true); // Enqueue a special shutdown job for each core. for (auto &res : numa_resources_) { - for (int i = 0; i < num_workers_ * 5; ++i) + for (int i = 0; i < num_workers_; ++i) res.job_queue.enqueue(-1); } // Join all worker threads. From 23983f3905aa2bf37941b876359f7c3f5a03fdff Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 23 May 2025 01:15:23 -0500 Subject: [PATCH 227/323] limit busy waiting --- src/cpp/src/query_coordinator.cpp | 16 ++++++++++++---- .../numa_multi_query/configs/sift1m.yaml | 2 +- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 5521a2da..511b1bf7 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -243,14 +243,20 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, int D = partition_manager_->d(); int node = cpu_numa_node(res.core_id); + auto enqueue_empty_batch = [&](const ScanJob& j) { + const auto& qids = *j.query_ids; + const auto& ranks = *j.ranks; // same length as qids + for (size_t idx = 0; idx < qids.size(); ++idx) { + result_queue_.enqueue(ResultJob{qids[idx], ranks[idx], {}, {}}); + } + }; + // Fetch partition data const float *codes = (float *) partition_manager_->partition_store_->get_codes(job.partition_id); const int64_t *ids = partition_manager_->partition_store_->get_ids(job.partition_id); int64_t part_size = partition_manager_->partition_store_->list_size(job.partition_id); if (!codes || !ids || part_size <= 0) { - for (int64_t q : *job.query_ids) { - result_queue_.enqueue(ResultJob{(int)q, 0, {}, {}}); - } + enqueue_empty_batch(job); return; } @@ -464,6 +470,8 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, } } + bool scan_all = partition_ids.size(1) == partition_manager_->nlist(); + /* Emit ScanJobs, already split into ≤ MAX_SUBBATCH chunks -------------- */ for (int64_t pid = 0; pid < (int64_t)qlist.size(); ++pid) { auto &pairs = qlist[pid]; @@ -490,7 +498,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, job.query_vector = xptr; // whole matrix; we gather later job.query_ids = qids; job.ranks = ranks; - job.scan_all = (chunk == static_cast(nQ)); // true only if every query in this chunk + job.scan_all = scan_all; job_buffer_.push_back(job); diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index c4226c70..882c739a 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -17,7 +17,7 @@ indexes: metric: l2 num_workers: 12 use_numa: false - parent_num_workers: 1 + parent_num_workers: 8 search_params: nprobe: 20 batched_scan: true From 7437ee3019bac4e6a91184c993a8ac19bb7b4264 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 23 May 2025 01:38:32 -0500 Subject: [PATCH 228/323] limit busy waiting --- src/cpp/include/query_coordinator.h | 2 ++ src/cpp/src/query_coordinator.cpp | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index eb47faba..e0e6e7f9 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -23,6 +23,7 @@ class PartitionManager; * A ScanJob encapsulates all parameters required to perform a scan on a given index partition. */ struct ScanJob { + int64_t job_id; ///< Unique identifier for the job. int64_t partition_id; ///< The identifier of the partition to be scanned. int k; ///< The number of neighbors (Top-K) to return. const float* query_vector; ///< Pointer to the query vector. @@ -101,6 +102,7 @@ class QueryCoordinator { std::mutex global_mutex_; ///< Mutex for global synchronization. std::condition_variable global_cv_; ///< Condition variable for thread coordination. std::atomic stop_workers_; ///< Flag to signal workers to terminate. + std::atomic jobs_in_flight_; ///< Number of jobs in flight. bool debug_ = false; ///< Debug mode flag. std::vector job_buffer_; diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 511b1bf7..13b1c841 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -159,6 +159,7 @@ void QueryCoordinator::process_scan_job(ScanJob job, } res.queries_counter += job.num_queries; res.job_counter++; + jobs_in_flight_--; } void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, @@ -439,6 +440,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, } } job_buffer_.clear(); + job_buffer_.reserve(nQ * partition_ids.size(1)); auto pid_acc = partition_ids.accessor(); if (!params->batched_scan) { @@ -449,6 +451,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, int64_t pid = pid_acc[q][p]; if (pid < 0) continue; ScanJob job; + job.job_id = next_job_id_; job.is_batched = false; job.query_id = (int)q; job.partition_id = pid; @@ -458,6 +461,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, job_buffer_.push_back(job); numa_resources_[core_to_numa[pid % num_workers_]].job_queue.enqueue(next_job_id_); next_job_id_++; + jobs_in_flight_++; } } } else { @@ -492,6 +496,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, ScanJob job; job.is_batched = true; + job.job_id = next_job_id_; job.partition_id = pid; job.k = params->k; job.num_queries = static_cast(chunk); @@ -507,6 +512,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, int node = core_to_numa[core]; numa_resources_[node].job_queue.enqueue(next_job_id_); next_job_id_++; + jobs_in_flight_++; } } } From c7cc40b76b3205c09d916e9765afe937ae77dda0 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 23 May 2025 01:46:26 -0500 Subject: [PATCH 229/323] empty result queues --- src/cpp/src/query_coordinator.cpp | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 13b1c841..b8038764 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -115,14 +115,6 @@ void QueryCoordinator::process_scan_job(ScanJob job, #endif NUMAResources &nr = numa_resources_[numa_node]; - auto enqueue_empty_batch = [&](const ScanJob& j) { - const auto& qids = *j.query_ids; - const auto& ranks = *j.ranks; // same length as qids - for (size_t idx = 0; idx < qids.size(); ++idx) { - result_queue_.enqueue(ResultJob{qids[idx], ranks[idx], {}, {}}); - } - }; - // Attempt to fetch partition data; if the list doesn't exist, catch and enqueue empty results. const float *codes = nullptr; const int64_t *ids = nullptr; @@ -135,7 +127,9 @@ void QueryCoordinator::process_scan_job(ScanJob job, std::cerr << "[process_scan_job] Partition " << job.partition_id << " invalid: " << e.what() << ". Returning empty result(s).\n"; if (job.is_batched) { - enqueue_empty_batch(job); + for (int64_t i = 0; i < job.num_queries; ++i) { + result_queue_.enqueue(ResultJob{(*job.query_ids)[i], (*job.ranks)[i], {}, {}}); + } } else { result_queue_.enqueue(ResultJob{job.query_id, job.rank, {}, {}}); } @@ -145,7 +139,9 @@ void QueryCoordinator::process_scan_job(ScanJob job, if (part_size == 0) { // empty => enqueue zero‐work per query if (job.is_batched) { - enqueue_empty_batch(job); + for (int64_t i = 0; i < job.num_queries; ++i) { + result_queue_.enqueue(ResultJob{(*job.query_ids)[i], (*job.ranks)[i], {}, {}}); + } } else { result_queue_.enqueue(ResultJob{job.query_id, job.rank, {}, {}}); } @@ -244,20 +240,14 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, int D = partition_manager_->d(); int node = cpu_numa_node(res.core_id); - auto enqueue_empty_batch = [&](const ScanJob& j) { - const auto& qids = *j.query_ids; - const auto& ranks = *j.ranks; // same length as qids - for (size_t idx = 0; idx < qids.size(); ++idx) { - result_queue_.enqueue(ResultJob{qids[idx], ranks[idx], {}, {}}); - } - }; - // Fetch partition data const float *codes = (float *) partition_manager_->partition_store_->get_codes(job.partition_id); const int64_t *ids = partition_manager_->partition_store_->get_ids(job.partition_id); int64_t part_size = partition_manager_->partition_store_->list_size(job.partition_id); if (!codes || !ids || part_size <= 0) { - enqueue_empty_batch(job); + for (int64_t i = 0; i < Q; ++i) { + result_queue_.enqueue(ResultJob{(*job.query_ids)[i], (*job.ranks)[i], {}, {}}); + } return; } From 6a1baae919dca3b1ece12fc92caf7a6258b8cca1 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 23 May 2025 01:56:25 -0500 Subject: [PATCH 230/323] empty result queues --- src/cpp/src/query_coordinator.cpp | 6 +++++- .../osdi2025/numa_multi_query/configs/sift1m.yaml | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index b8038764..6159806b 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -464,7 +464,11 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, } } - bool scan_all = partition_ids.size(1) == partition_manager_->nlist(); + int nlist = partition_manager_->nlist(); + bool scan_all = false; + if (nlist == 1) { + scan_all = true; + } /* Emit ScanJobs, already split into ≤ MAX_SUBBATCH chunks -------------- */ for (int64_t pid = 0; pid < (int64_t)qlist.size(); ++pid) { diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index 882c739a..13d010c8 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -17,10 +17,10 @@ indexes: metric: l2 num_workers: 12 use_numa: false - parent_num_workers: 8 + parent_num_workers: 12 search_params: nprobe: 20 - batched_scan: true + batched_scan: false # # - name: Quake_16_numa # index: Quake From 3791a4485ed98c8552743632f340cc9609881610 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 23 May 2025 02:15:08 -0500 Subject: [PATCH 231/323] empty result queues --- .../numa_multi_query/configs/sift1m.yaml | 24 +++++++++---------- .../osdi2025/numa_multi_query/run.py | 2 ++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index 13d010c8..0ec92f83 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -16,11 +16,11 @@ indexes: nc: 1000 metric: l2 num_workers: 12 - use_numa: false + use_numa: true parent_num_workers: 12 search_params: nprobe: 20 - batched_scan: false + batched_scan: true # # - name: Quake_16_numa # index: Quake @@ -56,16 +56,16 @@ indexes: # omp_num_threads_search: 16 # # -# - name: FaissHNSW -# index: HNSW -# build_params: -# m: 64 -# ef_construction: 128 -# metric: l2 -# omp_num_threads_build: 32 -# search_params: -# ef_search: 128 -# omp_num_threads_search: 32 + - name: FaissHNSW + index: HNSW + build_params: + m: 64 + ef_construction: 128 + metric: l2 + omp_num_threads_build: 16 + search_params: + ef_search: 128 + omp_num_threads_search: 16 # # - name: SCANN diff --git a/test/experiments/osdi2025/numa_multi_query/run.py b/test/experiments/osdi2025/numa_multi_query/run.py index 603610eb..6d679069 100644 --- a/test/experiments/osdi2025/numa_multi_query/run.py +++ b/test/experiments/osdi2025/numa_multi_query/run.py @@ -53,6 +53,8 @@ def task_build_index( if IndexCls is None or (IndexCls == Scann and Scann is None): # type: ignore return {"error": f"Index type '{index_config['index']}' unavailable.", "index_file_path": str(index_file_path)} + current_build_params.pop("num_parent_workers", None) + idx_instance_for_build = common_utils.prepare_wrapper_index( IndexCls, index_file_path, base_vectors, current_build_params, global_run_params["force_rebuild_indices"], load=False From 7ebbba2dd567370df4e3b2f9a9506783eed163db Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 23 May 2025 16:03:29 -0500 Subject: [PATCH 232/323] update queue waiting --- src/cpp/include/common.h | 1 + src/cpp/include/list_scanning.h | 206 ++++++++++++++-------------- src/cpp/include/query_coordinator.h | 2 +- src/cpp/src/query_coordinator.cpp | 70 +++++++--- 4 files changed, 155 insertions(+), 124 deletions(-) diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index 88173e28..73dae02d 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -76,6 +76,7 @@ constexpr float DEFAULT_INITIAL_SEARCH_FRACTION = 0.1f; ///< Default initial fra constexpr float DEFAULT_RECOMPUTE_THRESHOLD = 0.001f; ///< Default threshold to trigger recomputation of search parameters. constexpr int DEFAULT_APS_FLUSH_PERIOD_US = 5; ///< Default period (in microseconds) for flushing the APS buffer. constexpr int MAX_SUBBATCH = 128; +constexpr int MIN_BATCH_SCAN_SIZE = 5; ///< Minimum batch size for scanning partitions. // Default constants for maintenance policy parameters constexpr const char* DEFAULT_MAINTENANCE_POLICY = "query_cost"; ///< Default maintenance policy type. diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 37dfafe4..89ece74e 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -281,10 +281,10 @@ class TypedTopKBuffer { // Type alias for convenience using TopkBuffer = TypedTopKBuffer; -inline vector> create_buffers(int batch_size, int k, bool is_desc) { +inline vector> create_buffers(int batch_size, int k, bool is_desc, int cap=10000) { vector> buffers; for (int i = 0; i < batch_size; i++) { - buffers.push_back(make_shared(k, is_desc, k*100, 0)); + buffers.push_back(make_shared(k, is_desc, cap, 0)); } return buffers; } @@ -387,121 +387,123 @@ inline void scan_list(const float *query_vec, } } -//inline void batched_scan_list( -// const float *query_vecs, -// const float *list_vecs, -// const int64_t *list_ids, -// int num_queries, -// int list_size, -// int dim, -// vector> &topk_buffers, -// MetricType metric = faiss::METRIC_L2) -//{ -// if (list_size == 0 || list_vecs == nullptr) { -// return; -// } -// -// // Wrap raw arrays in torch Tensors, no copy -// Tensor query = torch::from_blob((void*)query_vecs, {num_queries, dim}, torch::kFloat32); -// Tensor list = torch::from_blob((void*)list_vecs, {list_size, dim}, torch::kFloat32); -// -// torch::Tensor distances; -// if (metric == faiss::METRIC_L2) { -// // Returns [num_queries, list_size], each entry is the Euclidean distance -// distances = torch::cdist(query, list, 2.0); -// } else if (metric == faiss::METRIC_INNER_PRODUCT) { -// // [num_queries, list_size], each entry is dot product -// distances = torch::matmul(query, list.t()); -// } else { -// throw std::runtime_error("Metric type not supported"); -// } -// -// // For each query, push all list vectors and their distances into TopkBuffer -// auto distances_acc = distances.accessor(); -// for (int i = 0; i < num_queries; ++i) { -// std::vector dists(list_size); -// std::vector ids(list_size); -// -// for (int j = 0; j < list_size; ++j) { -// dists[j] = distances_acc[i][j]; -// } -// -// if (list_ids) { -// for (int j = 0; j < list_size; ++j) { -// ids[j] = list_ids[j]; -// } -// } else { -// for (int j = 0; j < list_size; ++j) { -// ids[j] = j; -// } -// } -// -// topk_buffers[i]->batch_add(dists.data(), ids.data(), list_size); -// } -//} - -inline void batched_scan_list(const float *query_vecs, - const float *list_vecs, - const int64_t *list_ids, - int num_queries, - int list_size, - int dim, - vector> &topk_buffers, - MetricType metric = faiss::METRIC_L2, - float *distances = nullptr, - int64_t *labels = nullptr) { +inline void batched_scan_list( + const float *query_vecs, + const float *list_vecs, + const int64_t *list_ids, + int num_queries, + int list_size, + int dim, + vector> &topk_buffers, + MetricType metric = faiss::METRIC_L2, + float *dist = nullptr, + int64_t *labels = nullptr) // Optional output for distances and labels +{ if (list_size == 0 || list_vecs == nullptr) { - // No list vectors to process; return; } - // Ensure k does not exceed list_size - int k = topk_buffers[0]->k_; - int k_max = std::min(k, list_size); - - bool alloc_results = false; - if (distances == nullptr) { - alloc_results = true; - labels = (int64_t *) malloc(num_queries * k_max * sizeof(int64_t)); - distances = (float *) malloc(num_queries * k_max * sizeof(float)); - } + // Wrap raw arrays in torch Tensors, no copy + Tensor query = torch::from_blob((void*)query_vecs, {num_queries, dim}, torch::kFloat32); + Tensor list = torch::from_blob((void*)list_vecs, {list_size, dim}, torch::kFloat32); - if (metric == faiss::METRIC_INNER_PRODUCT) { - faiss::float_minheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; - faiss::knn_inner_product(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr); - } else if (metric == faiss::METRIC_L2) { - faiss::float_maxheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; - faiss::knn_L2sqr(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr, nullptr); + torch::Tensor distances; + if (metric == faiss::METRIC_L2) { + // Returns [num_queries, list_size], each entry is the Euclidean distance + distances = torch::cdist(query, list, 2.0); + } else if (metric == faiss::METRIC_INNER_PRODUCT) { + // [num_queries, list_size], each entry is dot product + distances = torch::matmul(query, list.t()); } else { throw std::runtime_error("Metric type not supported"); } - // map the labels to the actual list_ids - if (list_ids != nullptr) { - for (int i = 0; i < num_queries; i++) { - for (int j = 0; j < k_max; j++) { - labels[i * k_max + j] = list_ids[labels[i * k_max + j]]; - } - } - } + // For each query, push all list vectors and their distances into TopkBuffer + auto distances_acc = distances.accessor(); + for (int i = 0; i < num_queries; ++i) { + std::vector dists(list_size); + std::vector ids(list_size); - // if the metric is l2, convert the distances to sqrt - if (metric == faiss::METRIC_L2) { - for (int i = 0; i < num_queries * k_max; i++) { - distances[i] = sqrt(distances[i]); + for (int j = 0; j < list_size; ++j) { + dists[j] = distances_acc[i][j]; } - } - // add distances to the topk buffers - for (int i = 0; i < num_queries; i++) { - topk_buffers[i]->batch_add(distances + i * k_max, labels + i * k_max, k_max); - } + if (list_ids) { + for (int j = 0; j < list_size; ++j) { + ids[j] = list_ids[j]; + } + } else { + for (int j = 0; j < list_size; ++j) { + ids[j] = j; + } + } - if (alloc_results) { - free(distances); - free(labels); + topk_buffers[i]->batch_add(dists.data(), ids.data(), list_size); } } +// inline void batched_scan_list(const float *query_vecs, +// const float *list_vecs, +// const int64_t *list_ids, +// int num_queries, +// int list_size, +// int dim, +// vector> &topk_buffers, +// MetricType metric = faiss::METRIC_L2, +// float *distances = nullptr, +// int64_t *labels = nullptr) { +// if (list_size == 0 || list_vecs == nullptr) { +// // No list vectors to process; +// return; +// } +// +// // Ensure k does not exceed list_size +// int k = topk_buffers[0]->k_; +// int k_max = std::min(k, list_size); +// +// bool alloc_results = false; +// if (distances == nullptr) { +// alloc_results = true; +// labels = (int64_t *) malloc(num_queries * k_max * sizeof(int64_t)); +// distances = (float *) malloc(num_queries * k_max * sizeof(float)); +// } +// +// if (metric == faiss::METRIC_INNER_PRODUCT) { +// faiss::float_minheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; +// faiss::knn_inner_product(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr); +// } else if (metric == faiss::METRIC_L2) { +// faiss::float_maxheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; +// faiss::knn_L2sqr(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr, nullptr); +// } else { +// throw std::runtime_error("Metric type not supported"); +// } +// +// // map the labels to the actual list_ids +// if (list_ids != nullptr) { +// for (int i = 0; i < num_queries; i++) { +// for (int j = 0; j < k_max; j++) { +// labels[i * k_max + j] = list_ids[labels[i * k_max + j]]; +// } +// } +// } +// +// // if the metric is l2, convert the distances to sqrt +// if (metric == faiss::METRIC_L2) { +// for (int i = 0; i < num_queries * k_max; i++) { +// distances[i] = sqrt(distances[i]); +// } +// } +// +// // add distances to the topk buffers +// for (int i = 0; i < num_queries; i++) { +// topk_buffers[i]->batch_add(distances + i * k_max, labels + i * k_max, k_max); +// } +// +// if (alloc_results) { +// free(distances); +// free(labels); +// } +// } + // } #endif //LIST_SCANNING_H \ No newline at end of file diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index e0e6e7f9..fd5b042e 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -79,7 +79,7 @@ class QueryCoordinator { struct NUMAResources { float* local_query_buffer = nullptr; size_t buffer_size = 0; - moodycamel::BlockingConcurrentQueue job_queue; + moodycamel::ConcurrentQueue job_queue; }; struct ResultJob { diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 6159806b..70b80100 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -89,7 +89,19 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { int64_t jid = 0; auto start = std::chrono::high_resolution_clock::now(); - nr.job_queue.wait_dequeue(jid); + + bool success = nr.job_queue.try_dequeue(jid); + if (!success) { + if (jobs_in_flight_ == 0) { + std::this_thread::yield(); + continue; + } else { + std::this_thread::sleep_for(std::chrono::microseconds(1)); + continue; + } + } + + // nr.job_queue.wait_dequeue(jid); auto end = std::chrono::high_resolution_clock::now(); res.wait_time_ns += std::chrono::duration_cast(end - start).count(); @@ -446,7 +458,6 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, job.query_id = (int)q; job.partition_id = pid; job.k = params->k; - job.query_vector = qptr; job.rank = p; job_buffer_.push_back(job); numa_resources_[core_to_numa[pid % num_workers_]].job_queue.enqueue(next_job_id_); @@ -488,25 +499,42 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, ranks->push_back(pairs[off + i].second); } - ScanJob job; - job.is_batched = true; - job.job_id = next_job_id_; - job.partition_id = pid; - job.k = params->k; - job.num_queries = static_cast(chunk); - job.query_vector = xptr; // whole matrix; we gather later - job.query_ids = qids; - job.ranks = ranks; - job.scan_all = scan_all; - - job_buffer_.push_back(job); - - // Choose NUMA queue by partition-to-core mapping. - int core = pid % num_workers_; - int node = core_to_numa[core]; - numa_resources_[node].job_queue.enqueue(next_job_id_); - next_job_id_++; - jobs_in_flight_++; + if (chunk < MIN_BATCH_SCAN_SIZE) { + for (size_t i = 0; i < chunk; ++i) { + int qid = qids->at(i); + int rank = ranks->at(i); + ScanJob job; + job.is_batched = false; + job.job_id = next_job_id_; + job.partition_id = pid; + job.k = params->k; + job.rank = rank; + job.query_id = qid; + job_buffer_.push_back(job); + numa_resources_[core_to_numa[pid % num_workers_]].job_queue.enqueue(next_job_id_); + next_job_id_++; + jobs_in_flight_++; + } + } else { + ScanJob job; + job.is_batched = true; + job.job_id = next_job_id_; + job.partition_id = pid; + job.k = params->k; + job.num_queries = static_cast(chunk); + job.query_ids = qids; + job.ranks = ranks; + job.scan_all = scan_all; + + job_buffer_.push_back(job); + + // Choose NUMA queue by partition-to-core mapping. + int core = pid % num_workers_; + int node = core_to_numa[core]; + numa_resources_[node].job_queue.enqueue(next_job_id_); + next_job_id_++; + jobs_in_flight_++; + } } } } From 32185a2340240b7f0565e48e4c8998e229d956c2 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 23 May 2025 16:04:10 -0500 Subject: [PATCH 233/323] update queue waiting --- src/cpp/include/list_scanning.h | 204 ++++++++++++++++---------------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 89ece74e..2e5d5aeb 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -387,123 +387,123 @@ inline void scan_list(const float *query_vec, } } -inline void batched_scan_list( - const float *query_vecs, - const float *list_vecs, - const int64_t *list_ids, - int num_queries, - int list_size, - int dim, - vector> &topk_buffers, - MetricType metric = faiss::METRIC_L2, - float *dist = nullptr, - int64_t *labels = nullptr) // Optional output for distances and labels -{ - if (list_size == 0 || list_vecs == nullptr) { - return; - } - - // Wrap raw arrays in torch Tensors, no copy - Tensor query = torch::from_blob((void*)query_vecs, {num_queries, dim}, torch::kFloat32); - Tensor list = torch::from_blob((void*)list_vecs, {list_size, dim}, torch::kFloat32); - - torch::Tensor distances; - if (metric == faiss::METRIC_L2) { - // Returns [num_queries, list_size], each entry is the Euclidean distance - distances = torch::cdist(query, list, 2.0); - } else if (metric == faiss::METRIC_INNER_PRODUCT) { - // [num_queries, list_size], each entry is dot product - distances = torch::matmul(query, list.t()); - } else { - throw std::runtime_error("Metric type not supported"); - } - - // For each query, push all list vectors and their distances into TopkBuffer - auto distances_acc = distances.accessor(); - for (int i = 0; i < num_queries; ++i) { - std::vector dists(list_size); - std::vector ids(list_size); - - for (int j = 0; j < list_size; ++j) { - dists[j] = distances_acc[i][j]; - } - - if (list_ids) { - for (int j = 0; j < list_size; ++j) { - ids[j] = list_ids[j]; - } - } else { - for (int j = 0; j < list_size; ++j) { - ids[j] = j; - } - } - - topk_buffers[i]->batch_add(dists.data(), ids.data(), list_size); - } -} - -// inline void batched_scan_list(const float *query_vecs, -// const float *list_vecs, -// const int64_t *list_ids, -// int num_queries, -// int list_size, -// int dim, -// vector> &topk_buffers, -// MetricType metric = faiss::METRIC_L2, -// float *distances = nullptr, -// int64_t *labels = nullptr) { +// inline void batched_scan_list( +// const float *query_vecs, +// const float *list_vecs, +// const int64_t *list_ids, +// int num_queries, +// int list_size, +// int dim, +// vector> &topk_buffers, +// MetricType metric = faiss::METRIC_L2, +// float *dist = nullptr, +// int64_t *labels = nullptr) // Optional output for distances and labels +// { // if (list_size == 0 || list_vecs == nullptr) { -// // No list vectors to process; // return; // } // -// // Ensure k does not exceed list_size -// int k = topk_buffers[0]->k_; -// int k_max = std::min(k, list_size); -// -// bool alloc_results = false; -// if (distances == nullptr) { -// alloc_results = true; -// labels = (int64_t *) malloc(num_queries * k_max * sizeof(int64_t)); -// distances = (float *) malloc(num_queries * k_max * sizeof(float)); -// } +// // Wrap raw arrays in torch Tensors, no copy +// Tensor query = torch::from_blob((void*)query_vecs, {num_queries, dim}, torch::kFloat32); +// Tensor list = torch::from_blob((void*)list_vecs, {list_size, dim}, torch::kFloat32); // -// if (metric == faiss::METRIC_INNER_PRODUCT) { -// faiss::float_minheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; -// faiss::knn_inner_product(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr); -// } else if (metric == faiss::METRIC_L2) { -// faiss::float_maxheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; -// faiss::knn_L2sqr(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr, nullptr); +// torch::Tensor distances; +// if (metric == faiss::METRIC_L2) { +// // Returns [num_queries, list_size], each entry is the Euclidean distance +// distances = torch::cdist(query, list, 2.0); +// } else if (metric == faiss::METRIC_INNER_PRODUCT) { +// // [num_queries, list_size], each entry is dot product +// distances = torch::matmul(query, list.t()); // } else { // throw std::runtime_error("Metric type not supported"); // } // -// // map the labels to the actual list_ids -// if (list_ids != nullptr) { -// for (int i = 0; i < num_queries; i++) { -// for (int j = 0; j < k_max; j++) { -// labels[i * k_max + j] = list_ids[labels[i * k_max + j]]; -// } -// } -// } +// // For each query, push all list vectors and their distances into TopkBuffer +// auto distances_acc = distances.accessor(); +// for (int i = 0; i < num_queries; ++i) { +// std::vector dists(list_size); +// std::vector ids(list_size); // -// // if the metric is l2, convert the distances to sqrt -// if (metric == faiss::METRIC_L2) { -// for (int i = 0; i < num_queries * k_max; i++) { -// distances[i] = sqrt(distances[i]); +// for (int j = 0; j < list_size; ++j) { +// dists[j] = distances_acc[i][j]; // } -// } // -// // add distances to the topk buffers -// for (int i = 0; i < num_queries; i++) { -// topk_buffers[i]->batch_add(distances + i * k_max, labels + i * k_max, k_max); -// } +// if (list_ids) { +// for (int j = 0; j < list_size; ++j) { +// ids[j] = list_ids[j]; +// } +// } else { +// for (int j = 0; j < list_size; ++j) { +// ids[j] = j; +// } +// } // -// if (alloc_results) { -// free(distances); -// free(labels); +// topk_buffers[i]->batch_add(dists.data(), ids.data(), list_size); // } // } +inline void batched_scan_list(const float *query_vecs, + const float *list_vecs, + const int64_t *list_ids, + int num_queries, + int list_size, + int dim, + vector> &topk_buffers, + MetricType metric = faiss::METRIC_L2, + float *distances = nullptr, + int64_t *labels = nullptr) { + if (list_size == 0 || list_vecs == nullptr) { + // No list vectors to process; + return; + } + + // Ensure k does not exceed list_size + int k = topk_buffers[0]->k_; + int k_max = std::min(k, list_size); + + bool alloc_results = false; + if (distances == nullptr) { + alloc_results = true; + labels = (int64_t *) malloc(num_queries * k_max * sizeof(int64_t)); + distances = (float *) malloc(num_queries * k_max * sizeof(float)); + } + + if (metric == faiss::METRIC_INNER_PRODUCT) { + faiss::float_minheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; + faiss::knn_inner_product(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr); + } else if (metric == faiss::METRIC_L2) { + faiss::float_maxheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; + faiss::knn_L2sqr(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr, nullptr); + } else { + throw std::runtime_error("Metric type not supported"); + } + + // map the labels to the actual list_ids + if (list_ids != nullptr) { + for (int i = 0; i < num_queries; i++) { + for (int j = 0; j < k_max; j++) { + labels[i * k_max + j] = list_ids[labels[i * k_max + j]]; + } + } + } + + // if the metric is l2, convert the distances to sqrt + if (metric == faiss::METRIC_L2) { + for (int i = 0; i < num_queries * k_max; i++) { + distances[i] = sqrt(distances[i]); + } + } + + // add distances to the topk buffers + for (int i = 0; i < num_queries; i++) { + topk_buffers[i]->batch_add(distances + i * k_max, labels + i * k_max, k_max); + } + + if (alloc_results) { + free(distances); + free(labels); + } +} + // } #endif //LIST_SCANNING_H \ No newline at end of file From 8fc75ba8d6b95e44a494b3595e0f48a5551aa096 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 23 May 2025 16:07:12 -0500 Subject: [PATCH 234/323] update queue waiting --- src/cpp/src/query_coordinator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 70b80100..01839a6e 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -96,7 +96,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { std::this_thread::yield(); continue; } else { - std::this_thread::sleep_for(std::chrono::microseconds(1)); + std::this_thread::sleep_for(std::chrono::microseconds(5)); continue; } } From be6f966e99f1a238dc60dcd57db3b57500a9140e Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 23 May 2025 16:18:31 -0500 Subject: [PATCH 235/323] update queue waiting --- src/cpp/include/query_coordinator.h | 3 +++ src/cpp/src/query_coordinator.cpp | 34 ++++++++++++++++++++++------- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index fd5b042e..001d2208 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -104,6 +104,9 @@ class QueryCoordinator { std::atomic stop_workers_; ///< Flag to signal workers to terminate. std::atomic jobs_in_flight_; ///< Number of jobs in flight. bool debug_ = false; ///< Debug mode flag. + std::condition_variable_any jobs_cv_; // parks idle workers + std::mutex jobs_mu_; // only for the CV + std::vector job_buffer_; int next_job_id_ = 0; ///< ID for the next job to be processed. diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 01839a6e..4b879cf1 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -90,17 +90,34 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { auto start = std::chrono::high_resolution_clock::now(); - bool success = nr.job_queue.try_dequeue(jid); - if (!success) { - if (jobs_in_flight_ == 0) { - std::this_thread::yield(); - continue; - } else { - std::this_thread::sleep_for(std::chrono::microseconds(5)); - continue; + + if (nr.job_queue.try_dequeue(jid)) // fast-path + { + if (jid == -1) break; // poison → shutdown + process_scan_job(job_buffer_[jid], res); + if (jobs_in_flight_.fetch_sub(1, std::memory_order_acq_rel) == 1) { + /* this was the last job in the batch – nothing to do; + main thread will reset jobs_in_flight_ to 0 before the + next batch anyway */ } + continue; + } + + /* queue empty → check global counter */ + if (jobs_in_flight_.load(std::memory_order_acquire) != 0) { + /* other workers are still draining → yield to avoid thrashing + the same empty queue */ + std::this_thread::yield(); + continue; } + /* REALLY nothing left – park this thread until a producer wakes us */ + std::unique_lock lk(jobs_mu_); + jobs_cv_.wait(lk, [&]{ + return stop_workers_.load(std::memory_order_relaxed) || + jobs_in_flight_.load(std::memory_order_relaxed) != 0; + }); + // nr.job_queue.wait_dequeue(jid); auto end = std::chrono::high_resolution_clock::now(); @@ -713,6 +730,7 @@ std::shared_ptr QueryCoordinator::worker_scan( // 3) enqueue jobs enqueue_scan_jobs(x, partition_ids, params); + jobs_cv_.notify_all(); auto s4 = high_resolution_clock::now(); From ac62261c0ea82f8c1d8c06a5e7ce6e663f11e8fa Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 23 May 2025 16:23:54 -0500 Subject: [PATCH 236/323] update queue waiting --- src/cpp/include/query_coordinator.h | 5 +---- src/cpp/src/query_coordinator.cpp | 32 +---------------------------- 2 files changed, 2 insertions(+), 35 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 001d2208..e0e6e7f9 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -79,7 +79,7 @@ class QueryCoordinator { struct NUMAResources { float* local_query_buffer = nullptr; size_t buffer_size = 0; - moodycamel::ConcurrentQueue job_queue; + moodycamel::BlockingConcurrentQueue job_queue; }; struct ResultJob { @@ -104,9 +104,6 @@ class QueryCoordinator { std::atomic stop_workers_; ///< Flag to signal workers to terminate. std::atomic jobs_in_flight_; ///< Number of jobs in flight. bool debug_ = false; ///< Debug mode flag. - std::condition_variable_any jobs_cv_; // parks idle workers - std::mutex jobs_mu_; // only for the CV - std::vector job_buffer_; int next_job_id_ = 0; ///< ID for the next job to be processed. diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 4b879cf1..73418614 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -89,36 +89,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { int64_t jid = 0; auto start = std::chrono::high_resolution_clock::now(); - - - if (nr.job_queue.try_dequeue(jid)) // fast-path - { - if (jid == -1) break; // poison → shutdown - process_scan_job(job_buffer_[jid], res); - if (jobs_in_flight_.fetch_sub(1, std::memory_order_acq_rel) == 1) { - /* this was the last job in the batch – nothing to do; - main thread will reset jobs_in_flight_ to 0 before the - next batch anyway */ - } - continue; - } - - /* queue empty → check global counter */ - if (jobs_in_flight_.load(std::memory_order_acquire) != 0) { - /* other workers are still draining → yield to avoid thrashing - the same empty queue */ - std::this_thread::yield(); - continue; - } - - /* REALLY nothing left – park this thread until a producer wakes us */ - std::unique_lock lk(jobs_mu_); - jobs_cv_.wait(lk, [&]{ - return stop_workers_.load(std::memory_order_relaxed) || - jobs_in_flight_.load(std::memory_order_relaxed) != 0; - }); - - // nr.job_queue.wait_dequeue(jid); + nr.job_queue.wait_dequeue(jid); auto end = std::chrono::high_resolution_clock::now(); res.wait_time_ns += std::chrono::duration_cast(end - start).count(); @@ -730,7 +701,6 @@ std::shared_ptr QueryCoordinator::worker_scan( // 3) enqueue jobs enqueue_scan_jobs(x, partition_ids, params); - jobs_cv_.notify_all(); auto s4 = high_resolution_clock::now(); From 70d4c244a4b9d4b55f72b2ef0c8a676bc36a0e7c Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 23 May 2025 17:01:46 -0500 Subject: [PATCH 237/323] update queue waiting --- src/cpp/include/list_scanning.h | 16 +++++++++ src/cpp/include/query_coordinator.h | 5 ++- src/cpp/src/clustering.cpp | 6 ++++ src/cpp/src/query_coordinator.cpp | 50 ++++++++++++++++++++++------- 4 files changed, 65 insertions(+), 12 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 2e5d5aeb..7b52755b 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -449,6 +449,9 @@ inline void batched_scan_list(const float *query_vecs, int list_size, int dim, vector> &topk_buffers, + int64_t *setup_time, + int64_t *scan_time, + int64_t *push_time, MetricType metric = faiss::METRIC_L2, float *distances = nullptr, int64_t *labels = nullptr) { @@ -457,6 +460,8 @@ inline void batched_scan_list(const float *query_vecs, return; } + auto s1 = high_resolution_clock::now(); + // Ensure k does not exceed list_size int k = topk_buffers[0]->k_; int k_max = std::min(k, list_size); @@ -468,6 +473,8 @@ inline void batched_scan_list(const float *query_vecs, distances = (float *) malloc(num_queries * k_max * sizeof(float)); } + auto s2 = high_resolution_clock::now(); + if (metric == faiss::METRIC_INNER_PRODUCT) { faiss::float_minheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; faiss::knn_inner_product(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr); @@ -478,6 +485,9 @@ inline void batched_scan_list(const float *query_vecs, throw std::runtime_error("Metric type not supported"); } + auto s3 = high_resolution_clock::now(); + + // map the labels to the actual list_ids if (list_ids != nullptr) { for (int i = 0; i < num_queries; i++) { @@ -503,6 +513,12 @@ inline void batched_scan_list(const float *query_vecs, free(distances); free(labels); } + + auto s4 = high_resolution_clock::now(); + + *setup_time = duration_cast(s2 - s1).count(); + *scan_time = duration_cast(s3 - s2).count(); + *push_time = duration_cast(s4 - s3).count(); } // } diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index e0e6e7f9..db0a7a65 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -71,7 +71,10 @@ class QueryCoordinator { int64_t job_counter = 0; ///< Job counter for this core. int64_t queries_counter = 0; ///< Number of queries processed by this core. int64_t wait_time_ns = 0; ///< Time spent waiting for jobs. - int64_t process_time_ns = 0; ///< Time spent scanning. + int64_t process_time_ns = 0; ///< Time spent processing jobs. + int64_t scan_setup_time_ns = 0; ///< Time spent on scan setup. + int64_t scan_time_ns = 0; ///< Time spent on scanning. + int64_t scan_push_time_ns = 0; ///< Time spent pushing results. int64_t enqueue_time_ns = 0; ///< Time spent enqueuing. int64_t job_time_ns = 0; ///< Time spent on job processing (excluding waiting). }; diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index 552228be..4e60c0b8 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -280,6 +280,9 @@ tuple >> kmeans_refine_partitions( vector > buffers = create_buffers(nvec, 1, false); // Use batched_scan_list to get nearest centroid for each vector. + int64_t scan_setup_time = 0; + int64_t scan_time = 0; + int64_t scan_push_time = 0; batched_scan_list(part_vecs, centroids_ptr, nullptr, @@ -287,6 +290,9 @@ tuple >> kmeans_refine_partitions( n_clusters, d, buffers, + &scan_setup_time, + &scan_time, + &scan_push_time, metric); // For each vector in this partition, determine its assignment. diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 73418614..edcec828 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -234,6 +234,8 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, CoreResources &res, NUMAResources &nr) { + auto start = std::chrono::high_resolution_clock::now(); + // Total queries, Top-K, dimension, NUMA node int64_t Q = job.num_queries; int K = job.k; @@ -317,27 +319,27 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, } qptr = dst; } - - for (int64_t i = 0; i < chunk; i += 4) { - __builtin_prefetch(qptr + i * D, /* rw = */ 0, /* locality = */ 3); - } - // PREFETCH: warm up the partition codes and ids - __builtin_prefetch(codes, 0, 3); - __builtin_prefetch(ids, 0, 3); - - auto start = std::chrono::high_resolution_clock::now(); // run the scan on this chunk + + int64_t scan_setup_time = 0; + int64_t scan_time = 0; + int64_t scan_push_time = 0; batched_scan_list( qptr, codes, ids, chunk, part_size, D, res.topk_buffer_pool, + &scan_setup_time, + &scan_time, + &scan_push_time, metric_, res.batch_distances, res.batch_ids ); - auto end = std::chrono::high_resolution_clock::now(); - res.process_time_ns += std::chrono::duration_cast(end - start).count(); + + res.scan_setup_time_ns += scan_setup_time; + res.scan_time_ns += scan_time; + res.scan_push_time_ns += scan_push_time; // collect results for this chunk std::vector results_batch; @@ -349,6 +351,10 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, auto ti = res.topk_buffer_pool[i]->get_topk_indices(); results_batch.emplace_back(ResultJob{global_q, rank_q, std::move(tv), std::move(ti)}); } + + auto end = std::chrono::high_resolution_clock::now(); + res.process_time_ns += std::chrono::duration_cast(end - start).count(); + start = std::chrono::high_resolution_clock::now(); // enqueue this sub-batch in bulk result_queue_.enqueue_bulk( @@ -680,11 +686,17 @@ std::shared_ptr QueryCoordinator::worker_scan( vector core_process_time_ns(num_workers_, 0); vector core_enqueue_time_ns(num_workers_, 0); vector core_job_time_ns(num_workers_, 0); + vector core_scan_setup_time_ns(num_workers_, 0); + vector core_scan_time_ns(num_workers_, 0); + vector core_scan_push_time_ns(num_workers_, 0); for (int i = 0; i < num_workers_; ++i) { core_wait_time_ns[i] = core_resources_[i].wait_time_ns; core_process_time_ns[i] = core_resources_[i].process_time_ns; core_enqueue_time_ns[i] = core_resources_[i].enqueue_time_ns; core_job_time_ns[i] = core_resources_[i].job_time_ns; + core_scan_setup_time_ns[i] = core_resources_[i].scan_setup_time_ns; + core_scan_time_ns[i] = core_resources_[i].scan_time_ns; + core_scan_push_time_ns[i] = core_resources_[i].scan_push_time_ns; } auto s1 = high_resolution_clock::now(); @@ -731,13 +743,21 @@ std::shared_ptr QueryCoordinator::worker_scan( core_process_time_ns[i] = core_resources_[i].process_time_ns - core_process_time_ns[i]; core_enqueue_time_ns[i] = core_resources_[i].enqueue_time_ns - core_enqueue_time_ns[i]; core_job_time_ns[i] = core_resources_[i].job_time_ns - core_job_time_ns[i]; + core_scan_setup_time_ns[i] = core_resources_[i].scan_setup_time_ns - core_scan_setup_time_ns[i]; + core_scan_time_ns[i] = core_resources_[i].scan_time_ns - core_scan_time_ns[i]; + core_scan_push_time_ns[i] = core_resources_[i].scan_push_time_ns - core_scan_push_time_ns[i]; } // print out the per-core resource timers; for (int i = 0; i < num_workers_; ++i) { std::cout << "[QueryCoordinator::worker_scan] Core " << i << ": " + << "job_counter=" << core_resources_[i].job_counter << " " + << "queries_counter=" << core_resources_[i].queries_counter << " " << "wait_time_ms=" << (float) core_wait_time_ns[i] / 1e6 << " " + << "scan_setup_time_ms=" << (float) core_scan_setup_time_ns[i] / 1e6 << " " + << "scan_time_ms=" << (float) core_scan_time_ns[i] / 1e6 << " " + << "scan_push_time_ms=" << (float) core_scan_push_time_ns[i] / 1e6 << " " << "process_time_ms=" << (float) core_process_time_ns[i] / 1e6 << " " << "enqueue_time_ms=" << (float) core_enqueue_time_ns[i] / 1e6 << " " << "job_time_ms=" << (float) core_job_time_ns[i] / 1e6 << std::endl; @@ -1163,6 +1183,11 @@ shared_ptr QueryCoordinator::batched_serial_scan( vector> local_buffers = create_buffers(batch_size, k, (metric_ == faiss::METRIC_INNER_PRODUCT)); // Perform a single batched scan on the partition. + + int64_t scan_setup_time = 0; + int64_t scan_time = 0; + int64_t scan_push_time = 0; + batched_scan_list(x_subset.data_ptr(), list_codes, list_ids, @@ -1170,6 +1195,9 @@ shared_ptr QueryCoordinator::batched_serial_scan( list_size, d, local_buffers, + &scan_setup_time, + &scan_time, + &scan_push_time, metric_); // Merge the local results into the corresponding global buffers. From 059596ff1530537af4c532c6a0114e73053602c9 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 23 May 2025 17:13:14 -0500 Subject: [PATCH 238/323] update queue waiting --- src/cpp/src/query_coordinator.cpp | 34 +++++++++++-------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index edcec828..8aab3d31 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -253,13 +253,9 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, return; } - // Sub-batching - static constexpr int64_t MAX_SUBBATCH = 128; - // 1) Prepare per-thread buffers *once* up to MAX_SUBBATCH size_t cap = std::min(100 * K, 10000); - int64_t queries_req = std::min(Q, MAX_SUBBATCH); - + int64_t queries_req = Q; if (res.topk_buffer_pool.size() < (size_t)queries_req) { res.topk_buffer_pool.resize(queries_req); @@ -288,12 +284,8 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, res.batch_res_capacity = max_r; } - // 2) Process in sub-batches - for (int64_t offset = 0; offset < Q; offset += MAX_SUBBATCH) { - int64_t chunk = std::min(Q - offset, MAX_SUBBATCH); - // reset only the first 'chunk' TopK buffers - for (int64_t i = 0; i < chunk; ++i) { + for (int64_t i = 0; i < Q; ++i) { auto &buf = res.topk_buffer_pool[i]; buf->set_k(K); buf->reset(); @@ -303,31 +295,30 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, float init_val = (metric_ == faiss::METRIC_INNER_PRODUCT) ? -std::numeric_limits::infinity() : std::numeric_limits::infinity(); - std::fill_n(res.batch_distances, chunk * K, init_val); - std::fill_n(res.batch_ids, chunk * K, -1LL); + std::fill_n(res.batch_distances, Q * K, init_val); + std::fill_n(res.batch_ids, Q * K, -1LL); // gather queries float *qptr = nullptr; if (job.scan_all) { - qptr = nr.local_query_buffer + offset * D; + qptr = nr.local_query_buffer; } else { float *dst = res.batch_queries; - for (int64_t i = 0; i < chunk; ++i) { - int qid = (*job.query_ids)[offset + i]; + for (int64_t i = 0; i < Q; ++i) { + int qid = (*job.query_ids)[i]; const float *src = nr.local_query_buffer + size_t(qid) * D; std::memcpy(dst + i * D, src, D * sizeof(float)); } qptr = dst; } // run the scan on this chunk - int64_t scan_setup_time = 0; int64_t scan_time = 0; int64_t scan_push_time = 0; batched_scan_list( qptr, codes, ids, - chunk, part_size, D, + Q, part_size, D, res.topk_buffer_pool, &scan_setup_time, &scan_time, @@ -343,10 +334,10 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, // collect results for this chunk std::vector results_batch; - results_batch.reserve(chunk); - for (int64_t i = 0; i < chunk; ++i) { - int global_q = (*job.query_ids)[offset + i]; - int rank_q = (*job.ranks) [offset + i]; + results_batch.reserve(Q); + for (int64_t i = 0; i < Q; ++i) { + int global_q = (*job.query_ids)[i]; + int rank_q = (*job.ranks) [i]; auto tv = res.topk_buffer_pool[i]->get_topk(); auto ti = res.topk_buffer_pool[i]->get_topk_indices(); results_batch.emplace_back(ResultJob{global_q, rank_q, std::move(tv), std::move(ti)}); @@ -363,7 +354,6 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, ); end = std::chrono::high_resolution_clock::now(); res.enqueue_time_ns += std::chrono::duration_cast(end - start).count(); - } } void QueryCoordinator::init_global_buffers(int64_t nQ, From f44e1941b9b517db3e7accb8567e4c05dfb77182 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 23 May 2025 19:07:37 -0500 Subject: [PATCH 239/323] update queue waiting --- src/cpp/bindings/wrap.cpp | 2 ++ src/cpp/include/common.h | 1 + src/cpp/src/query_coordinator.cpp | 17 ++++++++--------- src/python/index_wrappers/quake.py | 8 +++++++- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/cpp/bindings/wrap.cpp b/src/cpp/bindings/wrap.cpp index d4aa0d87..5e5b1563 100644 --- a/src/cpp/bindings/wrap.cpp +++ b/src/cpp/bindings/wrap.cpp @@ -189,6 +189,8 @@ PYBIND11_MODULE(_bindings, m) { (std::string("Threshold to trigger recomputation of APS. default = ") + std::to_string(DEFAULT_RECOMPUTE_THRESHOLD)).c_str()) .def_readwrite("aps_flush_period_us", &SearchParams::aps_flush_period_us, (std::string("APS flush period in microseconds. default = ") + std::to_string(DEFAULT_APS_FLUSH_PERIOD_US)).c_str()) + .def_readwrite("batch_size", &SearchParams::batch_size, + (std::string("Batch size for batched scan. default = ") + std::to_string(MAX_SUBBATCH)).c_str()) .def_readwrite("k_factor", &SearchParams::k_factor, "Factor to adjust the number of neighbors to return.") .def_readwrite("track_hits", &SearchParams::track_hits, diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index 73dae02d..7133b37e 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -178,6 +178,7 @@ struct SearchParams { int num_threads = 1; // number of threads to use for search within a single worker float k_factor = 1.0f; bool batched_scan = DEFAULT_BATCHED_SCAN; + int batch_size = MAX_SUBBATCH; bool track_hits = true; diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 8aab3d31..7cb70de7 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -100,6 +100,7 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { process_scan_job(job_buffer_[jid], res); + jobs_in_flight_.fetch_sub(1, std::memory_order_relaxed); i++; end = std::chrono::high_resolution_clock::now(); @@ -155,7 +156,6 @@ void QueryCoordinator::process_scan_job(ScanJob job, } res.queries_counter += job.num_queries; res.job_counter++; - jobs_in_flight_--; } void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, @@ -253,7 +253,7 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, return; } - // 1) Prepare per-thread buffers *once* up to MAX_SUBBATCH + // 1) Prepare per-thread buffers *once* size_t cap = std::min(100 * K, 10000); int64_t queries_req = Q; @@ -446,7 +446,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, job_buffer_.push_back(job); numa_resources_[core_to_numa[pid % num_workers_]].job_queue.enqueue(next_job_id_); next_job_id_++; - jobs_in_flight_++; + jobs_in_flight_.fetch_add(1, std::memory_order_relaxed); } } } else { @@ -465,13 +465,13 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, scan_all = true; } - /* Emit ScanJobs, already split into ≤ MAX_SUBBATCH chunks -------------- */ + /* Emit ScanJobs, already split into ≤ params->batch_size chunks -------------- */ for (int64_t pid = 0; pid < (int64_t)qlist.size(); ++pid) { auto &pairs = qlist[pid]; if (pairs.empty()) continue; - for (size_t off = 0; off < pairs.size(); off += MAX_SUBBATCH) { - size_t chunk = std::min(MAX_SUBBATCH, pairs.size() - off); + for (size_t off = 0; off < pairs.size(); off += params->batch_size) { + size_t chunk = std::min(params->batch_size, pairs.size() - off); // Split query / rank vectors for this chunk. auto qids = std::make_shared>(); @@ -497,7 +497,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, job_buffer_.push_back(job); numa_resources_[core_to_numa[pid % num_workers_]].job_queue.enqueue(next_job_id_); next_job_id_++; - jobs_in_flight_++; + jobs_in_flight_.fetch_add(1, std::memory_order_relaxed); } } else { ScanJob job; @@ -517,7 +517,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, int node = core_to_numa[core]; numa_resources_[node].job_queue.enqueue(next_job_id_); next_job_id_++; - jobs_in_flight_++; + jobs_in_flight_.fetch_add(1, std::memory_order_relaxed); } } } @@ -1043,7 +1043,6 @@ shared_ptr QueryCoordinator::search(Tensor x, shared_ptr 10) { parent_search_params->batched_scan = true; } - } else { parent_search_params = search_params->parent_params; } diff --git a/src/python/index_wrappers/quake.py b/src/python/index_wrappers/quake.py index 982165ca..99ea9846 100644 --- a/src/python/index_wrappers/quake.py +++ b/src/python/index_wrappers/quake.py @@ -152,7 +152,8 @@ def search( n_threads=1, parent=None, sample_prefix=0, - sample_stride=5 + sample_stride=5, + batch_size=128, ) -> Tuple[torch.Tensor, torch.Tensor]: """ Find the k-nearest neighbors of the query vectors. @@ -175,12 +176,17 @@ def search( search_params.num_threads = n_threads search_params.sample_prefix = sample_prefix search_params.sample_stride = sample_stride + search_params.batch_size = batch_size + + print(parent) if parent is not None: search_params.parent_params = quake.SearchParams() search_params.parent_params.nprobe = parent.get("nprobe", 1) search_params.parent_params.recall_target = parent.get("recall_target", -1) search_params.parent_params.initial_search_fraction = parent.get("initial_search_fraction", 0.05) + search_params.parent_params.batch_size = parent.get("batch_size", 128) + search_params.parent_params.batched_scan = parent.get("batched_scan", search_params.batched_scan) return self.index.search(query, search_params) From f285ee54065b7a1efaf16c8cff172f0f0d043c6e Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 23 May 2025 23:07:42 -0500 Subject: [PATCH 240/323] blas buffer preallocation --- src/cpp/include/blas_dist.h | 138 ++++++++++++++++++++++++++++ src/cpp/include/common.h | 1 + src/cpp/include/list_scanning.h | 47 +++++++++- src/cpp/include/query_coordinator.h | 9 ++ src/cpp/src/clustering.cpp | 39 +++++++- src/cpp/src/query_coordinator.cpp | 67 +++++++++++--- 6 files changed, 280 insertions(+), 21 deletions(-) create mode 100644 src/cpp/include/blas_dist.h diff --git a/src/cpp/include/blas_dist.h b/src/cpp/include/blas_dist.h new file mode 100644 index 00000000..da49c87c --- /dev/null +++ b/src/cpp/include/blas_dist.h @@ -0,0 +1,138 @@ +/***************************************************************************************** + * faiss_exhaustive_L2sqr_buf.h + * + * Header-only replacement for Faiss’ exhaustive_L2sqr_blas()/knn_L2sqr(). + * ─────────────────────────────────────────────────────────────────────── + * • No dynamic allocations on the critical path. + * • Supersedes Faiss’ originals *without* touching any public headers. + * • Thread-safe, preserves numerical behaviour and ResultHandler contract. + * + * Jason — MIT / Quake project, 2025-05-23 + *****************************************************************************************/ +#ifndef FAISS_EXHAUSTIVE_L2SQR_BUF_H +#define FAISS_EXHAUSTIVE_L2SQR_BUF_H + +#include +#include + +#ifndef FINTEGER +#define FINTEGER long +#endif + +extern "C" { +int sgemm_(const char*, const char*, FINTEGER*, FINTEGER*, FINTEGER*, + const float*, const float*, FINTEGER*, + const float*, FINTEGER*, float*, float*, FINTEGER*); +} + +namespace faiss { + +template +void exhaustive_L2sqr_blas_buf( + const float* __restrict x, + const float* __restrict y, + size_t d, + size_t nx, + size_t ny, + size_t db_blas_bs, // = bs_y + BlockResultHandler& res, + float* __restrict ip_block, // bs_x * bs_y + float* __restrict norms_x, // bs_x + float* __restrict norms_y) // bs_y +{ + if (nx == 0 || ny == 0) return; + + constexpr size_t bs_x = 256; + const size_t bs_y = db_blas_bs; + + for (size_t i0 = 0; i0 < nx; i0 += bs_x) { + const size_t i1 = std::min(i0 + bs_x, nx); + const size_t q_chunk = i1 - i0; + + /* ‖x‖² for this query block */ + fvec_norms_L2sqr(norms_x, x + i0 * d, d, q_chunk); + + res.begin_multiple(i0, i1); + + for (size_t j0 = 0; j0 < ny; j0 += bs_y) { + const size_t j1 = std::min(j0 + bs_y, ny); + const size_t db_chunk = j1 - j0; + + /* ‖y‖² for this database block */ + fvec_norms_L2sqr(norms_y, y + j0 * d, d, db_chunk); + + /* SGEMM */ + { + const float one = 1.f; + float zero = 0.f; + FINTEGER nyi = FINTEGER(db_chunk); + FINTEGER nxi = FINTEGER(q_chunk); + FINTEGER di = FINTEGER(d); + sgemm_("Transpose","Not transpose", + &nyi,&nxi,&di, + &one, + y + j0 * d, &di, + x + i0 * d, &di, + &zero, + ip_block, &nyi); + } + + /* IP → L2² */ +#pragma omp parallel for if ((q_chunk*db_chunk) > 16384) + for (int64_t qi = 0; qi < (int64_t)q_chunk; ++qi) { + float* line = ip_block + qi * db_chunk; + const float xn = norms_x[qi]; + for (size_t pj = 0; pj < db_chunk; ++pj, ++line) { + float d2 = xn + norms_y[pj] - 2.f * (*line); + *line = (d2 < 0.f || !std::isfinite(d2)) ? 0.f : d2; + } + } + res.add_results(j0, j1, ip_block); + } + res.end_multiple(); + InterruptCallback::check(); + } +} +/* ---------------------------------------------------------------------- */ +/* 2. Public convenience wrapper (mirrors knn_L2sqr()) */ +/* ---------------------------------------------------------------------- */ +inline void knn_L2sqr_buf( + const float* x, + const float* y, + size_t d, + size_t nx, + size_t ny, + size_t k, + float* vals, // (nx × k) + int64_t* ids, // (nx × k) + float* ip_block, + float* norms_x, + float* norms_y_buf, + size_t db_blas_bs = distance_compute_blas_database_bs, + const float* y_norms = nullptr, + const IDSelector* sel = nullptr) +{ + /* selector path falls back to stock Faiss (rare in hot loop) -------- */ + if (sel) { + knn_L2sqr(x, y, d, nx, ny, k, vals, ids, y_norms, sel); + return; + } + + /* choose the same handlers Faiss uses --------------------------------*/ + if (k == 1) { + Top1BlockResultHandler> rh(nx, vals, ids); + exhaustive_L2sqr_blas_buf(x,y,d,nx,ny,db_blas_bs, + rh,ip_block,norms_x,norms_y_buf); + } else if (k < distance_compute_min_k_reservoir) { + HeapBlockResultHandler> rh(nx, vals, ids, k); + exhaustive_L2sqr_blas_buf(x,y,d,nx,ny,db_blas_bs, + rh,ip_block,norms_x,norms_y_buf); + } else { + ReservoirBlockResultHandler> rh(nx, vals, ids, k); + exhaustive_L2sqr_blas_buf(x,y,d,nx,ny,db_blas_bs, + rh,ip_block,norms_x,norms_y_buf); + } +} + +} // namespace faiss +#endif /* FAISS_EXHAUSTIVE_L2SQR_BUF_H */ \ No newline at end of file diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index 7133b37e..f9120e58 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -77,6 +77,7 @@ constexpr float DEFAULT_RECOMPUTE_THRESHOLD = 0.001f; ///< Default threshold constexpr int DEFAULT_APS_FLUSH_PERIOD_US = 5; ///< Default period (in microseconds) for flushing the APS buffer. constexpr int MAX_SUBBATCH = 128; constexpr int MIN_BATCH_SCAN_SIZE = 5; ///< Minimum batch size for scanning partitions. +constexpr int BLAS_DB_BS = 1024 * 16;; // Default constants for maintenance policy parameters constexpr const char* DEFAULT_MAINTENANCE_POLICY = "query_cost"; ///< Default maintenance policy type. diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 7b52755b..9649997a 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -14,6 +14,7 @@ #include "sorting/floyd_rivest_select.h" #include "sorting/heap_select.h" #include "parallel.h" +#include "blas_dist.h" inline Tensor calculate_recall(Tensor ids, Tensor gt_ids) { Tensor num_correct = torch::zeros(ids.size(0), torch::kInt64); @@ -452,9 +453,13 @@ inline void batched_scan_list(const float *query_vecs, int64_t *setup_time, int64_t *scan_time, int64_t *push_time, - MetricType metric = faiss::METRIC_L2, - float *distances = nullptr, - int64_t *labels = nullptr) { + MetricType metric, + float *distances, + int64_t *labels, + float *ip_block, + float *norms_x, + float *norms_y_buf, + int blas_db_bs = BLAS_DB_BS) { if (list_size == 0 || list_vecs == nullptr) { // No list vectors to process; return; @@ -475,12 +480,43 @@ inline void batched_scan_list(const float *query_vecs, auto s2 = high_resolution_clock::now(); + // inline void knn_L2sqr_buf( + // const float* x, + // const float* y, + // size_t d, + // size_t nx, + // size_t ny, + // size_t k, + // float* vals, + // int64_t* ids, + // float* ip_block, + // float* norms_x, + // float* norms_y_buf, + // size_t db_blas_bs = distance_compute_blas_database_bs, + // const float* y_norms = nullptr, + // const IDSelector* sel = nullptr) + // { + if (metric == faiss::METRIC_INNER_PRODUCT) { faiss::float_minheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; faiss::knn_inner_product(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr); } else if (metric == faiss::METRIC_L2) { - faiss::float_maxheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; - faiss::knn_L2sqr(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr, nullptr); + // faiss::float_maxheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; + faiss::knn_L2sqr_buf( + query_vecs, + list_vecs, + dim, + num_queries, + list_size, + k_max, + distances, + labels, + ip_block, + norms_x, + norms_y_buf, + blas_db_bs + ); + // faiss::knn_L2sqr(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr, nullptr); } else { throw std::runtime_error("Metric type not supported"); } @@ -521,5 +557,6 @@ inline void batched_scan_list(const float *query_vecs, *push_time = duration_cast(s4 - s3).count(); } + // } #endif //LIST_SCANNING_H \ No newline at end of file diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index db0a7a65..9c66da60 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -68,6 +68,15 @@ class QueryCoordinator { size_t batch_q_capacity = 0; // number of floats in batch_queries size_t batch_res_capacity = 0; // number of (k×Q) slots in distances & ids + float* blas_ip_block = nullptr; // capacity: db_blas_bs * max_Q + size_t blas_ip_capacity = 0; // # floats + + float* blas_norms_x = nullptr; // capacity: max_Q + size_t blas_norms_x_cap = 0; + + float* blas_norms_y = nullptr; // capacity: db_blas_bs (re-used per chunk) + size_t blas_norms_y_cap = 0; + int64_t job_counter = 0; ///< Job counter for this core. int64_t queries_counter = 0; ///< Number of queries processed by this core. int64_t wait_time_ns = 0; ///< Time spent waiting for jobs. diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index 4e60c0b8..99344635 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -9,6 +9,7 @@ #include "faiss/Clustering.h" #include "index_partition.h" #include +#include #ifdef QUAKE_ENABLE_GPU #include @@ -232,6 +233,35 @@ tuple >> kmeans_refine_partitions( MetricType metric, int refinement_iterations) { + // static void ensure_blas_buffers(QueryCoordinator::CoreResources& res, + // size_t max_q, + // size_t db_bs, + // int node) + // { + // const size_t ip_need = db_bs * max_q; + // if (res.blas_ip_capacity < ip_need) { + // quake_free(res.blas_ip_block, res.blas_ip_capacity * sizeof(float)); + // res.blas_ip_block = static_cast(quake_alloc(ip_need * sizeof(float), node)); + // res.blas_ip_capacity = ip_need; + // } + // if (res.blas_norms_x_cap < max_q) { + // quake_free(res.blas_norms_x, res.blas_norms_x_cap * sizeof(float)); + // res.blas_norms_x = static_cast(quake_alloc(max_q * sizeof(float), node)); + // res.blas_norms_x_cap = max_q; + // } + // if (res.blas_norms_y_cap < db_bs) { + // quake_free(res.blas_norms_y, res.blas_norms_y_cap * sizeof(float)); + // res.blas_norms_y = static_cast(quake_alloc(db_bs * sizeof(float), node)); + // res.blas_norms_y_cap = db_bs; + // } + // } + + const size_t ip_need = BLAS_DB_BS * centroids.size(0); + float * blas_ip_block = static_cast(quake_alloc(ip_need * sizeof(float), 0)); + float * blas_norms_x = static_cast(quake_alloc(BLAS_DB_BS * sizeof(float), 0)); + float * blas_norms_y = static_cast(quake_alloc(BLAS_DB_BS * sizeof(float), 0)); + + // Determine number of clusters and dimension. int n_clusters = centroids.size(0); int d = centroids.size(1); @@ -283,6 +313,7 @@ tuple >> kmeans_refine_partitions( int64_t scan_setup_time = 0; int64_t scan_time = 0; int64_t scan_push_time = 0; + batched_scan_list(part_vecs, centroids_ptr, nullptr, @@ -293,7 +324,13 @@ tuple >> kmeans_refine_partitions( &scan_setup_time, &scan_time, &scan_push_time, - metric); + metric, + /* distances*/ nullptr, + /* labels */ nullptr, + /* BLAS scratch */ blas_ip_block, + blas_norms_x, + blas_norms_y, + BLAS_DB_BS); // For each vector in this partition, determine its assignment. for (int i = 0; i < nvec; i++) { diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 7cb70de7..65c8fb20 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -12,6 +12,29 @@ #include //#include "parallel_hashmap/btree.h" +static void ensure_blas_buffers(QueryCoordinator::CoreResources& res, + size_t max_q, + size_t db_bs, + int node) +{ + const size_t ip_need = db_bs * max_q; + if (res.blas_ip_capacity < ip_need) { + quake_free(res.blas_ip_block, res.blas_ip_capacity * sizeof(float)); + res.blas_ip_block = static_cast(quake_alloc(ip_need * sizeof(float), node)); + res.blas_ip_capacity = ip_need; + } + if (res.blas_norms_x_cap < max_q) { + quake_free(res.blas_norms_x, res.blas_norms_x_cap * sizeof(float)); + res.blas_norms_x = static_cast(quake_alloc(max_q * sizeof(float), node)); + res.blas_norms_x_cap = max_q; + } + if (res.blas_norms_y_cap < db_bs) { + quake_free(res.blas_norms_y, res.blas_norms_y_cap * sizeof(float)); + res.blas_norms_y = static_cast(quake_alloc(db_bs * sizeof(float), node)); + res.blas_norms_y_cap = db_bs; + } +} + // Constructor QueryCoordinator::QueryCoordinator(shared_ptr parent, shared_ptr partition_manager, @@ -268,6 +291,8 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, } } + ensure_blas_buffers(res, Q, BLAS_DB_BS, node); + size_t max_q = size_t(queries_req) * D; if (res.batch_q_capacity < max_q) { quake_free(res.batch_queries, res.batch_q_capacity * sizeof(float)); @@ -315,18 +340,21 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, int64_t scan_setup_time = 0; int64_t scan_time = 0; int64_t scan_push_time = 0; - batched_scan_list( - qptr, - codes, ids, - Q, part_size, D, - res.topk_buffer_pool, - &scan_setup_time, - &scan_time, - &scan_push_time, - metric_, - res.batch_distances, - res.batch_ids - ); + batched_scan_list( + qptr, + codes, ids, + Q, part_size, D, + res.topk_buffer_pool, + &scan_setup_time, + &scan_time, + &scan_push_time, + metric_, + /* distances*/ res.batch_distances, + /* labels */ res.batch_ids, + /* BLAS scratch */ res.blas_ip_block, + res.blas_norms_x, + res.blas_norms_y, + BLAS_DB_BS); res.scan_setup_time_ns += scan_setup_time; res.scan_time_ns += scan_time; @@ -1120,6 +1148,9 @@ shared_ptr QueryCoordinator::batched_serial_scan( return empty_res; } + static CoreResources serial_res; // one per process + ensure_blas_buffers(serial_res, x.size(0), BLAS_DB_BS, /*node=*/0); + // Timing info (could be extended as needed) auto timing_info = std::make_shared(); auto start = high_resolution_clock::now(); @@ -1185,9 +1216,15 @@ shared_ptr QueryCoordinator::batched_serial_scan( d, local_buffers, &scan_setup_time, - &scan_time, - &scan_push_time, - metric_); + &scan_time, + &scan_push_time, + metric_, + /* distances*/ nullptr, + /* labels */ nullptr, + /* BLAS scratch */ serial_res.blas_ip_block, + serial_res.blas_norms_x, + serial_res.blas_norms_y, + BLAS_DB_BS); // Merge the local results into the corresponding global buffers. for (int i = 0; i < batch_size; i++) { From 4595404bcce75f036d70f0643f205d5719ac20af Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 14:25:30 -0500 Subject: [PATCH 241/323] torch matmul --- src/cpp/include/blas_dist.h | 13 +-- src/cpp/include/common.h | 4 +- src/cpp/include/list_scanning.h | 168 +++++++++++++++++++--------- src/cpp/include/query_coordinator.h | 5 +- src/cpp/src/query_coordinator.cpp | 86 +++++++------- 5 files changed, 174 insertions(+), 102 deletions(-) diff --git a/src/cpp/include/blas_dist.h b/src/cpp/include/blas_dist.h index da49c87c..dc1cd6bb 100644 --- a/src/cpp/include/blas_dist.h +++ b/src/cpp/include/blas_dist.h @@ -78,13 +78,12 @@ void exhaustive_L2sqr_blas_buf( } /* IP → L2² */ -#pragma omp parallel for if ((q_chunk*db_chunk) > 16384) - for (int64_t qi = 0; qi < (int64_t)q_chunk; ++qi) { - float* line = ip_block + qi * db_chunk; - const float xn = norms_x[qi]; - for (size_t pj = 0; pj < db_chunk; ++pj, ++line) { - float d2 = xn + norms_y[pj] - 2.f * (*line); - *line = (d2 < 0.f || !std::isfinite(d2)) ? 0.f : d2; + for (int64_t qi = 0; qi < static_cast(q_chunk); ++qi) { + float* line_ptr = ip_block + qi * db_chunk; // Pointer to current column in ip_block + const float current_norm_x = norms_x[qi]; + for (size_t pj = 0; pj < db_chunk; ++pj) { + *line_ptr = std::fma(-2.f, *line_ptr, current_norm_x + norms_y[pj]); + line_ptr++; // Move to the next element in the column } } res.add_results(j0, j1, ip_block); diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index f9120e58..e4cc197c 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -76,8 +76,8 @@ constexpr float DEFAULT_INITIAL_SEARCH_FRACTION = 0.1f; ///< Default initial fra constexpr float DEFAULT_RECOMPUTE_THRESHOLD = 0.001f; ///< Default threshold to trigger recomputation of search parameters. constexpr int DEFAULT_APS_FLUSH_PERIOD_US = 5; ///< Default period (in microseconds) for flushing the APS buffer. constexpr int MAX_SUBBATCH = 128; -constexpr int MIN_BATCH_SCAN_SIZE = 5; ///< Minimum batch size for scanning partitions. -constexpr int BLAS_DB_BS = 1024 * 16;; +constexpr int MIN_BATCH_SCAN_SIZE = 16; ///< Minimum batch size for scanning partitions. +constexpr int BLAS_DB_BS = 1024 * 16; // Default constants for maintenance policy parameters constexpr const char* DEFAULT_MAINTENANCE_POLICY = "query_cost"; ///< Default maintenance policy type. diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 9649997a..debb6252 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -41,6 +41,13 @@ inline Tensor calculate_recall(Tensor ids, Tensor gt_ids) { return recall; } +template +inline bool better(bool desc, T a, T b) noexcept +{ return desc ? (a > b) : (a < b); } + +//====================================================================== +// 1. Fast specialised buffer for k == 1 +//====================================================================== template class TypedTopKBuffer { public: @@ -120,6 +127,14 @@ class TypedTopKBuffer { reset(); } + int k() const { + return k_; + } + + int capacity() const { + return capacity_; + } + void alloc() { vals_ = static_cast(quake_alloc(sizeof(T) * capacity_, node_)); ids_ = static_cast(quake_alloc(sizeof(I) * capacity_, node_)); @@ -294,7 +309,7 @@ inline vector> create_buffers(int batch_size, int k, bool inline std::tuple buffers_to_tensor(vector> buffers) { int n = buffers.size(); - int k = buffers[0]->k_; + int k = buffers[0]->k(); Tensor topk_distances = torch::empty({n, k}, torch::kFloat32); Tensor topk_indices = torch::empty({n, k}, torch::kInt64); @@ -443,6 +458,102 @@ inline void scan_list(const float *query_vec, // } // } + +inline void l2_blas( + const float* __restrict x, + const float* __restrict y, + const int64_t *list_ids, + size_t d, + size_t nx, + size_t ny, + size_t db_blas_bs, // = bs_y + size_t k, + vector> &topk_buffers, + float* __restrict ip_block, // nx * bs_y + float* __restrict norms_x, // bs_x + float* __restrict norms_y) // db_blas_bs +{ + if (nx == 0 || ny == 0) return; + + constexpr size_t bs_x = 256; + const size_t bs_y = db_blas_bs; + int64_t *list_ids_ptr = (int64_t *) list_ids; + + for (size_t i0 = 0; i0 < nx; i0 += bs_x) { + const size_t i1 = std::min(i0 + bs_x, nx); + const size_t q_chunk = i1 - i0; + + /* ‖x‖² for this query block */ + faiss::fvec_norms_L2sqr(norms_x, x + i0 * d, d, q_chunk); + + for (size_t j0 = 0; j0 < ny; j0 += bs_y) { + const size_t j1 = std::min(j0 + bs_y, ny); + const size_t db_chunk = j1 - j0; + + /* ‖y‖² for this database block */ + faiss::fvec_norms_L2sqr(norms_y, y + j0 * d, d, db_chunk); + + // use torch matmul + Tensor x_chunk = torch::from_blob((void*)(x + i0 * d), {(int64_t) q_chunk, (int64_t) d}, torch::kFloat32); + Tensor y_chunk = torch::from_blob((void*)(y + j0 * d), {(int64_t) db_chunk, (int64_t) d}, torch::kFloat32); + Tensor out = torch::from_blob(ip_block, {(int64_t) q_chunk, (int64_t) db_chunk}, torch::kFloat32); + + torch::matmul_out(out, x_chunk, y_chunk.t()); + + // /* SGEMM */ + // { + // const float one = 1.f; + // float zero = 0.f; + // FINTEGER nyi = FINTEGER(db_chunk); + // FINTEGER nxi = FINTEGER(q_chunk); + // FINTEGER di = FINTEGER(d); + // sgemm_("Transpose","Not transpose", + // &nyi,&nxi,&di, + // &one, + // y + j0 * d, &di, + // x + i0 * d, &di, + // &zero, + // ip_block, &nyi); + // } + + /* IP → L2² */ + if (k > 1) { + for (int64_t qi = 0; qi < static_cast(q_chunk); ++qi) { + float* line_ptr = ip_block + qi * db_chunk; // Pointer to current column in ip_block + const float current_norm_x = norms_x[qi]; + for (size_t pj = 0; pj < db_chunk; ++pj) { + *line_ptr = std::sqrt(std::fma(-2.f, *line_ptr, current_norm_x + norms_y[pj])); + line_ptr++; // Move to the next element in the column + } + + topk_buffers[qi]->batch_add(ip_block + qi * db_chunk, list_ids_ptr + j0, db_chunk); + } + } else if (k == 1) { + for (int64_t qi = 0; qi < static_cast(q_chunk); ++qi) { + float* line_ptr = ip_block + qi * db_chunk; // Pointer to current column in ip_block + const float current_norm_x = norms_x[qi]; + for (size_t pj = 0; pj < db_chunk; ++pj) { + *line_ptr = std::sqrt(std::fma(-2.f, *line_ptr, current_norm_x + norms_y[pj])); + line_ptr++; // Move to the next element in the column + } + + float best_dist = std::numeric_limits::infinity(); + int64_t best_id = -1; + line_ptr = ip_block + qi * db_chunk; // Reset line_ptr to the start of the current column + for (size_t pj = 0; pj < db_chunk; ++pj) { + if (*line_ptr < best_dist) { + best_dist = *line_ptr; + best_id = list_ids_ptr[j0 + pj]; + } + line_ptr++; // Move to the next element in the column + } + topk_buffers[qi]->add(best_dist, best_id); + } + } + } + } +} + inline void batched_scan_list(const float *query_vecs, const float *list_vecs, const int64_t *list_ids, @@ -468,7 +579,7 @@ inline void batched_scan_list(const float *query_vecs, auto s1 = high_resolution_clock::now(); // Ensure k does not exceed list_size - int k = topk_buffers[0]->k_; + int k = topk_buffers[0]->k(); int k_max = std::min(k, list_size); bool alloc_results = false; @@ -480,41 +591,24 @@ inline void batched_scan_list(const float *query_vecs, auto s2 = high_resolution_clock::now(); - // inline void knn_L2sqr_buf( - // const float* x, - // const float* y, - // size_t d, - // size_t nx, - // size_t ny, - // size_t k, - // float* vals, - // int64_t* ids, - // float* ip_block, - // float* norms_x, - // float* norms_y_buf, - // size_t db_blas_bs = distance_compute_blas_database_bs, - // const float* y_norms = nullptr, - // const IDSelector* sel = nullptr) - // { - if (metric == faiss::METRIC_INNER_PRODUCT) { faiss::float_minheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; faiss::knn_inner_product(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr); } else if (metric == faiss::METRIC_L2) { // faiss::float_maxheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; - faiss::knn_L2sqr_buf( + l2_blas( query_vecs, list_vecs, + list_ids, dim, num_queries, list_size, + blas_db_bs, k_max, - distances, - labels, + topk_buffers, ip_block, norms_x, - norms_y_buf, - blas_db_bs + norms_y_buf ); // faiss::knn_L2sqr(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr, nullptr); } else { @@ -524,32 +618,6 @@ inline void batched_scan_list(const float *query_vecs, auto s3 = high_resolution_clock::now(); - // map the labels to the actual list_ids - if (list_ids != nullptr) { - for (int i = 0; i < num_queries; i++) { - for (int j = 0; j < k_max; j++) { - labels[i * k_max + j] = list_ids[labels[i * k_max + j]]; - } - } - } - - // if the metric is l2, convert the distances to sqrt - if (metric == faiss::METRIC_L2) { - for (int i = 0; i < num_queries * k_max; i++) { - distances[i] = sqrt(distances[i]); - } - } - - // add distances to the topk buffers - for (int i = 0; i < num_queries; i++) { - topk_buffers[i]->batch_add(distances + i * k_max, labels + i * k_max, k_max); - } - - if (alloc_results) { - free(distances); - free(labels); - } - auto s4 = high_resolution_clock::now(); *setup_time = duration_cast(s2 - s1).count(); diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 9c66da60..d3a2b123 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -81,6 +81,7 @@ class QueryCoordinator { int64_t queries_counter = 0; ///< Number of queries processed by this core. int64_t wait_time_ns = 0; ///< Time spent waiting for jobs. int64_t process_time_ns = 0; ///< Time spent processing jobs. + int64_t process_preamble_time_ns = 0; ///< Time spent on job processing (excluding waiting). int64_t scan_setup_time_ns = 0; ///< Time spent on scan setup. int64_t scan_time_ns = 0; ///< Time spent on scanning. int64_t scan_push_time_ns = 0; ///< Time spent pushing results. @@ -276,7 +277,9 @@ class QueryCoordinator { std::shared_ptr aggregate_scan_results(int64_t nQ, int K, - shared_ptr timing); + shared_ptr timing, + Tensor out_ids, + Tensor out_dists); }; #endif //QUERY_COORDINATOR_H diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 65c8fb20..f85c6e20 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -121,18 +121,21 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { break; } - + auto s2 = std::chrono::high_resolution_clock::now(); process_scan_job(job_buffer_[jid], res); jobs_in_flight_.fetch_sub(1, std::memory_order_relaxed); i++; end = std::chrono::high_resolution_clock::now(); + res.process_time_ns += std::chrono::duration_cast(end - s2).count(); res.job_time_ns += std::chrono::duration_cast(end - start).count(); } } void QueryCoordinator::process_scan_job(ScanJob job, CoreResources &res) { + + auto start = std::chrono::high_resolution_clock::now(); int numa_node = 0; #ifdef QUAKE_USE_NUMA numa_node = cpu_numa_node(res.core_id); @@ -171,6 +174,8 @@ void QueryCoordinator::process_scan_job(ScanJob job, } return; } + auto end = std::chrono::high_resolution_clock::now(); + res.process_preamble_time_ns += std::chrono::duration_cast(end - start).count(); if (!job.is_batched) { handle_nonbatched_job(job, res, nr); @@ -184,7 +189,6 @@ void QueryCoordinator::process_scan_job(ScanJob job, void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, CoreResources &res, NUMAResources &nr) { - // ensure buffers if (res.topk_buffer_pool.size() < 1) { res.topk_buffer_pool.resize(1); @@ -194,9 +198,9 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, /*cap=*/std::min(100 * job.k, 10000), /*node=*/cpu_numa_node(res.core_id) ); - } else if (res.topk_buffer_pool[0]->k_ != job.k) { + } else if (res.topk_buffer_pool[0]->k() != job.k) { // check capacity - if (res.topk_buffer_pool[0]->capacity_ < job.k) { + if (res.topk_buffer_pool[0]->capacity() < job.k) { res.topk_buffer_pool[0] = std::make_shared( job.k, metric_ == faiss::METRIC_INNER_PRODUCT, @@ -211,8 +215,6 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, res.topk_buffer_pool[0]->reset(); try { - // It's good practice to re-fetch or validate partition data here if it could - // have changed since process_scan_job's initial checks, especially with maintenance. const float* codes = (float*)partition_manager_->partition_store_->get_codes(job.partition_id); const int64_t* ids = (int64_t*)partition_manager_->partition_store_->get_ids(job.partition_id); int64_t part_size = partition_manager_->partition_store_->list_size(job.partition_id); @@ -257,8 +259,6 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, CoreResources &res, NUMAResources &nr) { - auto start = std::chrono::high_resolution_clock::now(); - // Total queries, Top-K, dimension, NUMA node int64_t Q = job.num_queries; int K = job.k; @@ -316,12 +316,14 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, buf->reset(); } - // init only the first chunk*K slots in scratch - float init_val = (metric_ == faiss::METRIC_INNER_PRODUCT) - ? -std::numeric_limits::infinity() - : std::numeric_limits::infinity(); - std::fill_n(res.batch_distances, Q * K, init_val); - std::fill_n(res.batch_ids, Q * K, -1LL); + // // init only the first chunk*K slots in scratch + // float init_val = (metric_ == faiss::METRIC_INNER_PRODUCT) + // ? -std::numeric_limits::infinity() + // : std::numeric_limits::infinity(); + // std::fill_n(res.batch_distances, Q * K, init_val); + // std::fill_n(res.batch_ids, Q * K, -1LL); + + // auto // gather queries float *qptr = nullptr; @@ -336,6 +338,7 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, } qptr = dst; } + // run the scan on this chunk int64_t scan_setup_time = 0; int64_t scan_time = 0; @@ -356,10 +359,12 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, res.blas_norms_y, BLAS_DB_BS); + res.scan_setup_time_ns += scan_setup_time; res.scan_time_ns += scan_time; res.scan_push_time_ns += scan_push_time; + auto start = std::chrono::high_resolution_clock::now(); // collect results for this chunk std::vector results_batch; results_batch.reserve(Q); @@ -371,16 +376,12 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, results_batch.emplace_back(ResultJob{global_q, rank_q, std::move(tv), std::move(ti)}); } - auto end = std::chrono::high_resolution_clock::now(); - res.process_time_ns += std::chrono::duration_cast(end - start).count(); - - start = std::chrono::high_resolution_clock::now(); // enqueue this sub-batch in bulk result_queue_.enqueue_bulk( std::make_move_iterator(results_batch.begin()), results_batch.size() ); - end = std::chrono::high_resolution_clock::now(); + auto end = std::chrono::high_resolution_clock::now(); res.enqueue_time_ns += std::chrono::duration_cast(end - start).count(); } @@ -613,6 +614,10 @@ void QueryCoordinator::drain_and_apply_aps(Tensor x, --parts_left[rj.query_id]; --total_left; } + + if (parts_left[rj.query_id] == 0) { + global_topk_buffer_pool_[rj.query_id]->flush(); + } } while (result_queue_.try_dequeue(rj)); continue; // Skip APS; we just did useful work. @@ -651,27 +656,18 @@ void QueryCoordinator::drain_and_apply_aps(Tensor x, std::shared_ptr QueryCoordinator::aggregate_scan_results(int64_t nQ, int K, - shared_ptr timing) -{ - // build output tensors - auto out_ids = torch::full({nQ,K}, -1, torch::kInt64); - auto out_dists = torch::full({nQ,K}, - (metric_==faiss::METRIC_INNER_PRODUCT - ? -std::numeric_limits::infinity() - : std::numeric_limits::infinity()), - torch::kFloat32); - - { - std::lock_guard lg(global_mutex_); - auto id_acc = out_ids.accessor(); - auto d_acc = out_dists.accessor(); - for (int64_t q = 0; q < nQ; ++q) { - auto tv = global_topk_buffer_pool_[q]->get_topk(); - auto ti = global_topk_buffer_pool_[q]->get_topk_indices(); - for (int i = 0; i < (int)ti.size() && i < K; ++i) { - id_acc[q][i] = ti[i]; - d_acc [q][i] = tv[i]; - } + shared_ptr timing, + Tensor out_ids, + Tensor out_dists) { + + auto id_acc = out_ids.accessor(); + auto d_acc = out_dists.accessor(); + for (int64_t q = 0; q < nQ; ++q) { + auto tv = global_topk_buffer_pool_[q]->get_topk(); + auto ti = global_topk_buffer_pool_[q]->get_topk_indices(); + for (int i = 0; i < (int)ti.size() && i < K; ++i) { + id_acc[q][i] = ti[i]; + d_acc [q][i] = tv[i]; } } @@ -698,10 +694,10 @@ std::shared_ptr QueryCoordinator::worker_scan( timing->n_clusters = partition_manager_->nlist(); timing->search_params = params; - // get initial values of the per-core resource timers; vector core_wait_time_ns(num_workers_, 0); vector core_process_time_ns(num_workers_, 0); + vector core_process_preamble_time_ns(num_workers_, 0); vector core_enqueue_time_ns(num_workers_, 0); vector core_job_time_ns(num_workers_, 0); vector core_scan_setup_time_ns(num_workers_, 0); @@ -710,6 +706,7 @@ std::shared_ptr QueryCoordinator::worker_scan( for (int i = 0; i < num_workers_; ++i) { core_wait_time_ns[i] = core_resources_[i].wait_time_ns; core_process_time_ns[i] = core_resources_[i].process_time_ns; + core_process_preamble_time_ns[i] = core_resources_[i].process_preamble_time_ns; core_enqueue_time_ns[i] = core_resources_[i].enqueue_time_ns; core_job_time_ns[i] = core_resources_[i].job_time_ns; core_scan_setup_time_ns[i] = core_resources_[i].scan_setup_time_ns; @@ -734,13 +731,16 @@ std::shared_ptr QueryCoordinator::worker_scan( auto s4 = high_resolution_clock::now(); + Tensor out_ids = torch::empty({nQ, K}, torch::kLong); + Tensor out_dists = torch::empty({nQ, K}, torch::kFloat); + // 4) drain results + APS drain_and_apply_aps(x, partition_ids, use_aps, params->recall_target, params->aps_flush_period_us, timing); auto s5 = high_resolution_clock::now(); - auto res = aggregate_scan_results(nQ, K, timing); + auto res = aggregate_scan_results(nQ, K, timing, out_ids, out_dists); auto s6 = high_resolution_clock::now(); @@ -759,6 +759,7 @@ std::shared_ptr QueryCoordinator::worker_scan( for (int i = 0; i < num_workers_; ++i) { core_wait_time_ns[i] = core_resources_[i].wait_time_ns - core_wait_time_ns[i]; core_process_time_ns[i] = core_resources_[i].process_time_ns - core_process_time_ns[i]; + core_process_preamble_time_ns[i] = core_resources_[i].process_preamble_time_ns - core_process_preamble_time_ns[i]; core_enqueue_time_ns[i] = core_resources_[i].enqueue_time_ns - core_enqueue_time_ns[i]; core_job_time_ns[i] = core_resources_[i].job_time_ns - core_job_time_ns[i]; core_scan_setup_time_ns[i] = core_resources_[i].scan_setup_time_ns - core_scan_setup_time_ns[i]; @@ -777,6 +778,7 @@ std::shared_ptr QueryCoordinator::worker_scan( << "scan_time_ms=" << (float) core_scan_time_ns[i] / 1e6 << " " << "scan_push_time_ms=" << (float) core_scan_push_time_ns[i] / 1e6 << " " << "process_time_ms=" << (float) core_process_time_ns[i] / 1e6 << " " + << "process_preamble_time_ms=" << (float) core_process_preamble_time_ns[i] / 1e6 << " " << "enqueue_time_ms=" << (float) core_enqueue_time_ns[i] / 1e6 << " " << "job_time_ms=" << (float) core_job_time_ns[i] / 1e6 << std::endl; } From 8cafa05745f18bc09d8a9da65e8689ec963854e4 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 15:18:38 -0500 Subject: [PATCH 242/323] store pivots --- src/cpp/include/list_scanning.h | 27 +++++++-- src/cpp/include/query_coordinator.h | 1 + src/cpp/src/query_coordinator.cpp | 93 +++++++++++++++++++---------- 3 files changed, 84 insertions(+), 37 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index debb6252..be29ab56 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -471,7 +471,8 @@ inline void l2_blas( vector> &topk_buffers, float* __restrict ip_block, // nx * bs_y float* __restrict norms_x, // bs_x - float* __restrict norms_y) // db_blas_bs + float* __restrict norms_y, + float* pivot) // db_blas_bs { if (nx == 0 || ny == 0) return; @@ -526,7 +527,18 @@ inline void l2_blas( line_ptr++; // Move to the next element in the column } - topk_buffers[qi]->batch_add(ip_block + qi * db_chunk, list_ids_ptr + j0, db_chunk); + // collect distances closer than pivot + if (pivot) { + line_ptr = ip_block + qi * db_chunk; // Reset line_ptr to the start of the current column + for (size_t pj = 0; pj < db_chunk; ++pj) { + if (*line_ptr < pivot[qi]) { + topk_buffers[qi]->add(*line_ptr, list_ids_ptr[j0 + pj]); + } + line_ptr++; // Move to the next element in the column + } + } else { + topk_buffers[qi]->batch_add(ip_block + qi * db_chunk, list_ids_ptr + j0, db_chunk); + } } } else if (k == 1) { for (int64_t qi = 0; qi < static_cast(q_chunk); ++qi) { @@ -570,7 +582,8 @@ inline void batched_scan_list(const float *query_vecs, float *ip_block, float *norms_x, float *norms_y_buf, - int blas_db_bs = BLAS_DB_BS) { + int blas_db_bs = BLAS_DB_BS, + vector pivots = {}) { if (list_size == 0 || list_vecs == nullptr) { // No list vectors to process; return; @@ -591,6 +604,11 @@ inline void batched_scan_list(const float *query_vecs, auto s2 = high_resolution_clock::now(); + float *pivot_ptr = nullptr; + if (!pivots.empty()) { + pivot_ptr = pivots.data(); + } + if (metric == faiss::METRIC_INNER_PRODUCT) { faiss::float_minheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; faiss::knn_inner_product(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr); @@ -608,7 +626,8 @@ inline void batched_scan_list(const float *query_vecs, topk_buffers, ip_block, norms_x, - norms_y_buf + norms_y_buf, + pivot_ptr ); // faiss::knn_L2sqr(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr, nullptr); } else { diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index d3a2b123..d3fdfcc4 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -120,6 +120,7 @@ class QueryCoordinator { std::vector job_buffer_; int next_job_id_ = 0; ///< ID for the next job to be processed. + vector> query_dist_pivots_; ///< Pivots for each query to speed up sorting vector>> job_flags_; ///< Flags to track job completion std::atomic job_pull_time_ns = 0; ///< Time spent pulling jobs from the queue. std::atomic job_process_time_ns = 0; ///< Time spent processing jobs. diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index f85c6e20..3dc937cb 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -309,40 +309,48 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, res.batch_res_capacity = max_r; } - // reset only the first 'chunk' TopK buffers - for (int64_t i = 0; i < Q; ++i) { - auto &buf = res.topk_buffer_pool[i]; - buf->set_k(K); - buf->reset(); - } + // reset only the first 'chunk' TopK buffers + for (int64_t i = 0; i < Q; ++i) { + auto &buf = res.topk_buffer_pool[i]; + buf->set_k(K); + buf->reset(); + } - // // init only the first chunk*K slots in scratch - // float init_val = (metric_ == faiss::METRIC_INNER_PRODUCT) - // ? -std::numeric_limits::infinity() - // : std::numeric_limits::infinity(); - // std::fill_n(res.batch_distances, Q * K, init_val); - // std::fill_n(res.batch_ids, Q * K, -1LL); + // // init only the first chunk*K slots in scratch + // float init_val = (metric_ == faiss::METRIC_INNER_PRODUCT) + // ? -std::numeric_limits::infinity() + // : std::numeric_limits::infinity(); + // std::fill_n(res.batch_distances, Q * K, init_val); + // std::fill_n(res.batch_ids, Q * K, -1LL); - // auto + // auto - // gather queries - float *qptr = nullptr; - if (job.scan_all) { - qptr = nr.local_query_buffer; - } else { - float *dst = res.batch_queries; - for (int64_t i = 0; i < Q; ++i) { - int qid = (*job.query_ids)[i]; - const float *src = nr.local_query_buffer + size_t(qid) * D; - std::memcpy(dst + i * D, src, D * sizeof(float)); - } - qptr = dst; + // gather queries + float *qptr = nullptr; + if (job.scan_all) { + qptr = nr.local_query_buffer; + } else { + float *dst = res.batch_queries; + for (int64_t i = 0; i < Q; ++i) { + int qid = (*job.query_ids)[i]; + const float *src = nr.local_query_buffer + size_t(qid) * D; + std::memcpy(dst + i * D, src, D * sizeof(float)); } + qptr = dst; + } - // run the scan on this chunk - int64_t scan_setup_time = 0; - int64_t scan_time = 0; - int64_t scan_push_time = 0; + + vector pivots; + pivots.resize(job.num_queries); + for (int64_t i = 0; i < Q; ++i) { + int qid = (*job.query_ids)[i]; + pivots[i] = query_dist_pivots_[qid].load(std::memory_order_relaxed); + } + + // run the scan on this chunk + int64_t scan_setup_time = 0; + int64_t scan_time = 0; + int64_t scan_push_time = 0; batched_scan_list( qptr, codes, ids, @@ -357,7 +365,8 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, /* BLAS scratch */ res.blas_ip_block, res.blas_norms_x, res.blas_norms_y, - BLAS_DB_BS); + BLAS_DB_BS, + pivots); res.scan_setup_time_ns += scan_setup_time; @@ -410,6 +419,15 @@ void QueryCoordinator::init_global_buffers(int64_t nQ, global_topk_buffer_pool_[q]->reset(); } } + + // set pivots to -1; + float max_val = (metric_ == faiss::METRIC_INNER_PRODUCT) + ? -std::numeric_limits::infinity() + : std::numeric_limits::infinity(); + query_dist_pivots_ = vector>(nQ); + for (int64_t q = 0; q < nQ; ++q) { + query_dist_pivots_[q].store(max_val, std::memory_order_relaxed); + } } void QueryCoordinator::copy_query_to_numa(const float *xptr, int64_t nQ, int64_t D) { @@ -597,6 +615,8 @@ void QueryCoordinator::drain_and_apply_aps(Tensor x, } } + vector per_query_result_count(nQ, 0); + ResultJob rj; while (total_left.load(std::memory_order_relaxed) > 0) { @@ -609,15 +629,22 @@ void QueryCoordinator::drain_and_apply_aps(Tensor x, buf->batch_add(rj.distances.data(), rj.indices.data(), static_cast(rj.indices.size())); + per_query_result_count[rj.query_id]++; + + if (per_query_result_count[rj.query_id] % 5 == 0) { + query_dist_pivots_[rj.query_id].store(global_topk_buffer_pool_[rj.query_id]->flush(), + std::memory_order_relaxed); + } + if (!job_flags_[rj.query_id][rj.rank]) { job_flags_[rj.query_id][rj.rank] = true; --parts_left[rj.query_id]; --total_left; } - if (parts_left[rj.query_id] == 0) { - global_topk_buffer_pool_[rj.query_id]->flush(); - } + // if (parts_left[rj.query_id] == 0) { + // global_topk_buffer_pool_[rj.query_id]->flush(); + // } } while (result_queue_.try_dequeue(rj)); continue; // Skip APS; we just did useful work. From ed1d39c4107b3ccdcc584ddcb60bfd1d90211e2b Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 17:22:03 -0500 Subject: [PATCH 243/323] sort improvement --- src/cpp/include/list_scanning.h | 10 +- src/cpp/include/query_coordinator.h | 2 +- src/cpp/src/query_coordinator.cpp | 144 +++++++++++++++++----------- 3 files changed, 92 insertions(+), 64 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index be29ab56..7d0678b2 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -180,7 +180,7 @@ class TypedTopKBuffer { if (++head_ == capacity_) flush(); } - void batch_add(T *distances, I *indices, int num_values) { + float batch_add(T *distances, I *indices, int num_values) { int pos = 0; while (pos < num_values) { int available = capacity_ - head_; @@ -260,8 +260,8 @@ class TypedTopKBuffer { } - std::vector get_topk() { - flush(); + std::vector get_topk(bool sort = true) { + if (sort || head_ > k_) flush(); int n = head_; std::vector out; out.reserve(n); @@ -282,8 +282,8 @@ class TypedTopKBuffer { return vals_[k_ - 1]; } - std::vector get_topk_indices() { - flush(); + std::vector get_topk_indices(bool sort = true) { + if (sort || head_ > k_) flush(); int n = head_; std::vector out; out.reserve(n); diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index d3fdfcc4..a4d5d4b9 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -111,7 +111,7 @@ class QueryCoordinator { int num_workers_; ///< Total number of worker threads. vector worker_threads_; ///< Container for worker threads. vector worker_job_counter_; ///< Job counters for each worker. - vector> global_topk_buffer_pool_; ///< Global aggregator buffers. + shared_ptr>> global_topk_buffer_pool_; ///< Global aggregator buffers. std::mutex global_mutex_; ///< Mutex for global synchronization. std::condition_variable global_cv_; ///< Condition variable for thread coordination. std::atomic stop_workers_; ///< Flag to signal workers to terminate. diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 3dc937cb..eaecc884 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -380,8 +380,8 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, for (int64_t i = 0; i < Q; ++i) { int global_q = (*job.query_ids)[i]; int rank_q = (*job.ranks) [i]; - auto tv = res.topk_buffer_pool[i]->get_topk(); - auto ti = res.topk_buffer_pool[i]->get_topk_indices(); + auto tv = res.topk_buffer_pool[i]->get_topk(false); + auto ti = res.topk_buffer_pool[i]->get_topk_indices(false); results_batch.emplace_back(ResultJob{global_q, rank_q, std::move(tv), std::move(ti)}); } @@ -401,24 +401,34 @@ void QueryCoordinator::init_global_buffers(int64_t nQ, std::lock_guard lg(global_mutex_); // resize or reset - size_t cap = std::min(100 * K, 10000); - if (global_topk_buffer_pool_.size() < (size_t) nQ) { - size_t old = global_topk_buffer_pool_.size(); - global_topk_buffer_pool_.resize(nQ); - for (int64_t q = old; q < nQ; ++q) { - global_topk_buffer_pool_[q] = std::make_shared( - K, - metric_ == faiss::METRIC_INNER_PRODUCT, - /*cap=*/cap, - /*node=*/0 - ); - } - } else { - for (int64_t q = 0; q < nQ; ++q) { - global_topk_buffer_pool_[q]->set_k(K); - global_topk_buffer_pool_[q]->reset(); - } - } + // size_t cap = std::min(100 * K, 10000); + // faiss::HeapArray>(nQ) }; + float * vals = (float *) quake_alloc(nQ * K * sizeof(float), 0); + int64_t * ids = (int64_t *) quake_alloc(nQ * K * sizeof(int64_t), 0); + std::fill_n(vals, nQ * K, + std::numeric_limits::infinity()); + std::fill_n(ids, nQ * K, -1); + + global_topk_buffer_pool_ = make_shared>>( + nQ, vals, ids, K); + global_topk_buffer_pool_->begin_multiple(0, nQ); + // if (global_topk_buffer_pool_.size() < (size_t) nQ) { + // size_t old = global_topk_buffer_pool_.size(); + // global_topk_buffer_pool_.resize(nQ); + // for (int64_t q = old; q < nQ; ++q) { + // global_topk_buffer_pool_[q] = std::make_shared( + // K, + // metric_ == faiss::METRIC_INNER_PRODUCT, + // /*cap=*/cap, + // /*node=*/0 + // ); + // } + // } else { + // for (int64_t q = 0; q < nQ; ++q) { + // global_topk_buffer_pool_[q]->set_k(K); + // global_topk_buffer_pool_[q]->reset(); + // } + // } // set pivots to -1; float max_val = (metric_ == faiss::METRIC_INNER_PRODUCT) @@ -617,6 +627,14 @@ void QueryCoordinator::drain_and_apply_aps(Tensor x, vector per_query_result_count(nQ, 0); + vector>::SingleResultHandler> + handlers; + handlers.reserve(nQ); + for (int64_t q = 0; q < nQ; ++q) { + handlers.emplace_back(*global_topk_buffer_pool_); + handlers[q].begin(q); // ← reset & heapify for query q + } + ResultJob rj; while (total_left.load(std::memory_order_relaxed) > 0) { @@ -625,17 +643,14 @@ void QueryCoordinator::drain_and_apply_aps(Tensor x, if (got_result) { do { // Drain *all* currently available results. - auto &buf = global_topk_buffer_pool_[rj.query_id]; - buf->batch_add(rj.distances.data(), rj.indices.data(), - static_cast(rj.indices.size())); + for (int64_t i = 0; i < rj.distances.size(); ++i) { + handlers[rj.query_id].add_result(rj.distances[i], rj.indices[i]); + } + query_dist_pivots_[rj.query_id].store( + handlers[rj.query_id].threshold, std::memory_order_relaxed); per_query_result_count[rj.query_id]++; - if (per_query_result_count[rj.query_id] % 5 == 0) { - query_dist_pivots_[rj.query_id].store(global_topk_buffer_pool_[rj.query_id]->flush(), - std::memory_order_relaxed); - } - if (!job_flags_[rj.query_id][rj.rank]) { job_flags_[rj.query_id][rj.rank] = true; --parts_left[rj.query_id]; @@ -650,34 +665,41 @@ void QueryCoordinator::drain_and_apply_aps(Tensor x, continue; // Skip APS; we just did useful work. } + /* (b) Timeout fired → run APS once. */ - if (use_aps) { - for (int64_t q = 0; q < nQ; ++q) { - if (parts_left[q] == 0) continue; - - auto &buf = global_topk_buffer_pool_[q]; - const float r = buf->get_kth_distance(); - if (r != query_radius[q]) { - query_radius[q] = r; - probs[q] = compute_recall_profile( - boundary_dist[q], r, D, {}, true, metric_==faiss::METRIC_L2); - } + // if (use_aps) { + // for (int64_t q = 0; q < nQ; ++q) { + // if (parts_left[q] == 0) continue; + // + // auto &buf = global_topk_buffer_pool_[q]; + // const float r = buf->get_kth_distance(); + // if (r != query_radius[q]) { + // query_radius[q] = r; + // probs[q] = compute_recall_profile( + // boundary_dist[q], r, D, {}, true, metric_==faiss::METRIC_L2); + // } + // + // float cum = 0.0f; + // for (int64_t p = 0; p < nprobe; ++p) + // if (job_flags_[q][p]) cum += probs[q][p]; + // + // if (cum >= recall_target) { + // for (int64_t p = 0; p < nprobe; ++p) + // if (!job_flags_[q][p]) { + // job_flags_[q][p] = true; + // --parts_left[q]; + // --total_left; + // } + // } + // } + // } + } - float cum = 0.0f; - for (int64_t p = 0; p < nprobe; ++p) - if (job_flags_[q][p]) cum += probs[q][p]; - - if (cum >= recall_target) { - for (int64_t p = 0; p < nprobe; ++p) - if (!job_flags_[q][p]) { - job_flags_[q][p] = true; - --parts_left[q]; - --total_left; - } - } - } - } + // end the handlers + for (int64_t q = 0; q < nQ; ++q) { + handlers[q].end(); } + } std::shared_ptr @@ -690,12 +712,18 @@ QueryCoordinator::aggregate_scan_results(int64_t nQ, auto id_acc = out_ids.accessor(); auto d_acc = out_dists.accessor(); for (int64_t q = 0; q < nQ; ++q) { - auto tv = global_topk_buffer_pool_[q]->get_topk(); - auto ti = global_topk_buffer_pool_[q]->get_topk_indices(); - for (int i = 0; i < (int)ti.size() && i < K; ++i) { - id_acc[q][i] = ti[i]; - d_acc [q][i] = tv[i]; + + for (int64_t i = 0; i < K; ++i) { + id_acc[q][i] = global_topk_buffer_pool_->heap_ids_tab[q * K + i]; + d_acc [q][i] = global_topk_buffer_pool_->heap_dis_tab[q * K + i]; } + + // auto tv = global_topk_buffer_pool_[q]->get_topk(); + // auto ti = global_topk_buffer_pool_[q]->get_topk_indices(); + // for (int i = 0; i < (int)ti.size() && i < K; ++i) { + // id_acc[q][i] = ti[i]; + // d_acc [q][i] = tv[i]; + // } } auto res = std::make_shared(); From 87945e9edd20cee0aa12ad3f2b9e77948ab217cc Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 17:37:55 -0500 Subject: [PATCH 244/323] sort improvement --- src/cpp/include/common.h | 2 +- src/cpp/include/list_scanning.h | 38 ++++++++++++++++----------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index e4cc197c..32ce00d4 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -76,7 +76,7 @@ constexpr float DEFAULT_INITIAL_SEARCH_FRACTION = 0.1f; ///< Default initial fra constexpr float DEFAULT_RECOMPUTE_THRESHOLD = 0.001f; ///< Default threshold to trigger recomputation of search parameters. constexpr int DEFAULT_APS_FLUSH_PERIOD_US = 5; ///< Default period (in microseconds) for flushing the APS buffer. constexpr int MAX_SUBBATCH = 128; -constexpr int MIN_BATCH_SCAN_SIZE = 16; ///< Minimum batch size for scanning partitions. +constexpr int MIN_BATCH_SCAN_SIZE = 4; ///< Minimum batch size for scanning partitions. constexpr int BLAS_DB_BS = 1024 * 16; // Default constants for maintenance policy parameters diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 7d0678b2..1032c3e9 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -495,27 +495,27 @@ inline void l2_blas( faiss::fvec_norms_L2sqr(norms_y, y + j0 * d, d, db_chunk); // use torch matmul - Tensor x_chunk = torch::from_blob((void*)(x + i0 * d), {(int64_t) q_chunk, (int64_t) d}, torch::kFloat32); - Tensor y_chunk = torch::from_blob((void*)(y + j0 * d), {(int64_t) db_chunk, (int64_t) d}, torch::kFloat32); - Tensor out = torch::from_blob(ip_block, {(int64_t) q_chunk, (int64_t) db_chunk}, torch::kFloat32); - - torch::matmul_out(out, x_chunk, y_chunk.t()); + // Tensor x_chunk = torch::from_blob((void*)(x + i0 * d), {(int64_t) q_chunk, (int64_t) d}, torch::kFloat32); + // Tensor y_chunk = torch::from_blob((void*)(y + j0 * d), {(int64_t) db_chunk, (int64_t) d}, torch::kFloat32); + // Tensor out = torch::from_blob(ip_block, {(int64_t) q_chunk, (int64_t) db_chunk}, torch::kFloat32); + // + // torch::matmul_out(out, x_chunk, y_chunk.t()); // /* SGEMM */ - // { - // const float one = 1.f; - // float zero = 0.f; - // FINTEGER nyi = FINTEGER(db_chunk); - // FINTEGER nxi = FINTEGER(q_chunk); - // FINTEGER di = FINTEGER(d); - // sgemm_("Transpose","Not transpose", - // &nyi,&nxi,&di, - // &one, - // y + j0 * d, &di, - // x + i0 * d, &di, - // &zero, - // ip_block, &nyi); - // } + { + const float one = 1.f; + float zero = 0.f; + FINTEGER nyi = FINTEGER(db_chunk); + FINTEGER nxi = FINTEGER(q_chunk); + FINTEGER di = FINTEGER(d); + sgemm_("Transpose","Not transpose", + &nyi,&nxi,&di, + &one, + y + j0 * d, &di, + x + i0 * d, &di, + &zero, + ip_block, &nyi); + } /* IP → L2² */ if (k > 1) { From 34edb02fa36824fa49368efb499f60fc39f9b89b Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 17:59:33 -0500 Subject: [PATCH 245/323] sort improvement --- src/cpp/include/list_scanning.h | 54 ++++++++++++++----------------- src/cpp/src/query_coordinator.cpp | 9 +++--- 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 1032c3e9..c3724daf 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -472,7 +472,7 @@ inline void l2_blas( float* __restrict ip_block, // nx * bs_y float* __restrict norms_x, // bs_x float* __restrict norms_y, - float* pivot) // db_blas_bs + vector*> pivot) // db_blas_bs { if (nx == 0 || ny == 0) return; @@ -495,27 +495,27 @@ inline void l2_blas( faiss::fvec_norms_L2sqr(norms_y, y + j0 * d, d, db_chunk); // use torch matmul - // Tensor x_chunk = torch::from_blob((void*)(x + i0 * d), {(int64_t) q_chunk, (int64_t) d}, torch::kFloat32); - // Tensor y_chunk = torch::from_blob((void*)(y + j0 * d), {(int64_t) db_chunk, (int64_t) d}, torch::kFloat32); - // Tensor out = torch::from_blob(ip_block, {(int64_t) q_chunk, (int64_t) db_chunk}, torch::kFloat32); - // - // torch::matmul_out(out, x_chunk, y_chunk.t()); + Tensor x_chunk = torch::from_blob((void*)(x + i0 * d), {(int64_t) q_chunk, (int64_t) d}, torch::kFloat32); + Tensor y_chunk = torch::from_blob((void*)(y + j0 * d), {(int64_t) db_chunk, (int64_t) d}, torch::kFloat32); + Tensor out = torch::from_blob(ip_block, {(int64_t) q_chunk, (int64_t) db_chunk}, torch::kFloat32); + + torch::matmul_out(out, x_chunk, y_chunk.t()); // /* SGEMM */ - { - const float one = 1.f; - float zero = 0.f; - FINTEGER nyi = FINTEGER(db_chunk); - FINTEGER nxi = FINTEGER(q_chunk); - FINTEGER di = FINTEGER(d); - sgemm_("Transpose","Not transpose", - &nyi,&nxi,&di, - &one, - y + j0 * d, &di, - x + i0 * d, &di, - &zero, - ip_block, &nyi); - } + // { + // const float one = 1.f; + // float zero = 0.f; + // FINTEGER nyi = FINTEGER(db_chunk); + // FINTEGER nxi = FINTEGER(q_chunk); + // FINTEGER di = FINTEGER(d); + // sgemm_("Transpose","Not transpose", + // &nyi,&nxi,&di, + // &one, + // y + j0 * d, &di, + // x + i0 * d, &di, + // &zero, + // ip_block, &nyi); + // } /* IP → L2² */ if (k > 1) { @@ -528,10 +528,11 @@ inline void l2_blas( } // collect distances closer than pivot - if (pivot) { + if (pivot.size() > 0) { + float curr_pivot = pivot[qi]->load(std::memory_order_relaxed); line_ptr = ip_block + qi * db_chunk; // Reset line_ptr to the start of the current column for (size_t pj = 0; pj < db_chunk; ++pj) { - if (*line_ptr < pivot[qi]) { + if (*line_ptr < curr_pivot) { topk_buffers[qi]->add(*line_ptr, list_ids_ptr[j0 + pj]); } line_ptr++; // Move to the next element in the column @@ -583,7 +584,7 @@ inline void batched_scan_list(const float *query_vecs, float *norms_x, float *norms_y_buf, int blas_db_bs = BLAS_DB_BS, - vector pivots = {}) { + vector*> pivots = {}) { if (list_size == 0 || list_vecs == nullptr) { // No list vectors to process; return; @@ -604,11 +605,6 @@ inline void batched_scan_list(const float *query_vecs, auto s2 = high_resolution_clock::now(); - float *pivot_ptr = nullptr; - if (!pivots.empty()) { - pivot_ptr = pivots.data(); - } - if (metric == faiss::METRIC_INNER_PRODUCT) { faiss::float_minheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; faiss::knn_inner_product(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr); @@ -627,7 +623,7 @@ inline void batched_scan_list(const float *query_vecs, ip_block, norms_x, norms_y_buf, - pivot_ptr + pivots ); // faiss::knn_L2sqr(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr, nullptr); } else { diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index eaecc884..70f41414 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -238,8 +238,8 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, metric_); // If scan_list completes, enqueue its results - auto tv = buf->get_topk(); - auto ti = buf->get_topk_indices(); + auto tv = buf->get_topk(false); + auto ti = buf->get_topk_indices(false); result_queue_.enqueue(ResultJob{job.query_id, job.rank, std::move(tv), std::move(ti)}); } catch (const std::exception& e) { @@ -340,11 +340,11 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, } - vector pivots; + vector *> pivots; pivots.resize(job.num_queries); for (int64_t i = 0; i < Q; ++i) { int qid = (*job.query_ids)[i]; - pivots[i] = query_dist_pivots_[qid].load(std::memory_order_relaxed); + pivots[i] = &query_dist_pivots_[qid]; } // run the scan on this chunk @@ -877,6 +877,7 @@ void QueryCoordinator::initialize_workers(int num_cores, bool use_numa) { // set main thread on separate thread from workers int num_cores_on_machine = std::thread::hardware_concurrency(); set_thread_affinity(num_cores % num_cores_on_machine); + // set_thread_affinity(0); } // Shutdown Worker Threads From 7612d1137514e85cfb85c69427d20e2c108d1767 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 18:04:33 -0500 Subject: [PATCH 246/323] sort improvement --- src/cpp/include/list_scanning.h | 49 ++++++++++++++++----------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index c3724daf..d66f4674 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -495,27 +495,27 @@ inline void l2_blas( faiss::fvec_norms_L2sqr(norms_y, y + j0 * d, d, db_chunk); // use torch matmul - Tensor x_chunk = torch::from_blob((void*)(x + i0 * d), {(int64_t) q_chunk, (int64_t) d}, torch::kFloat32); - Tensor y_chunk = torch::from_blob((void*)(y + j0 * d), {(int64_t) db_chunk, (int64_t) d}, torch::kFloat32); - Tensor out = torch::from_blob(ip_block, {(int64_t) q_chunk, (int64_t) db_chunk}, torch::kFloat32); - - torch::matmul_out(out, x_chunk, y_chunk.t()); - - // /* SGEMM */ - // { - // const float one = 1.f; - // float zero = 0.f; - // FINTEGER nyi = FINTEGER(db_chunk); - // FINTEGER nxi = FINTEGER(q_chunk); - // FINTEGER di = FINTEGER(d); - // sgemm_("Transpose","Not transpose", - // &nyi,&nxi,&di, - // &one, - // y + j0 * d, &di, - // x + i0 * d, &di, - // &zero, - // ip_block, &nyi); - // } + // Tensor x_chunk = torch::from_blob((void*)(x + i0 * d), {(int64_t) q_chunk, (int64_t) d}, torch::kFloat32); + // Tensor y_chunk = torch::from_blob((void*)(y + j0 * d), {(int64_t) db_chunk, (int64_t) d}, torch::kFloat32); + // Tensor out = torch::from_blob(ip_block, {(int64_t) q_chunk, (int64_t) db_chunk}, torch::kFloat32); + // + // torch::matmul_out(out, x_chunk, y_chunk.t()); + + /* SGEMM */ + { + const float one = 1.f; + float zero = 0.f; + FINTEGER nyi = FINTEGER(db_chunk); + FINTEGER nxi = FINTEGER(q_chunk); + FINTEGER di = FINTEGER(d); + sgemm_("Transpose","Not transpose", + &nyi,&nxi,&di, + &one, + y + j0 * d, &di, + x + i0 * d, &di, + &zero, + ip_block, &nyi); + } /* IP → L2² */ if (k > 1) { @@ -545,15 +545,12 @@ inline void l2_blas( for (int64_t qi = 0; qi < static_cast(q_chunk); ++qi) { float* line_ptr = ip_block + qi * db_chunk; // Pointer to current column in ip_block const float current_norm_x = norms_x[qi]; - for (size_t pj = 0; pj < db_chunk; ++pj) { - *line_ptr = std::sqrt(std::fma(-2.f, *line_ptr, current_norm_x + norms_y[pj])); - line_ptr++; // Move to the next element in the column - } float best_dist = std::numeric_limits::infinity(); int64_t best_id = -1; - line_ptr = ip_block + qi * db_chunk; // Reset line_ptr to the start of the current column + for (size_t pj = 0; pj < db_chunk; ++pj) { + *line_ptr = std::sqrt(std::fma(-2.f, *line_ptr, current_norm_x + norms_y[pj])); if (*line_ptr < best_dist) { best_dist = *line_ptr; best_id = list_ids_ptr[j0 + pj]; From 2f0651a70015f12ac782143afd396298f8ee75aa Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 21:07:41 -0500 Subject: [PATCH 247/323] sort improvement --- src/cpp/include/list_scanning.h | 225 +++++++++-------- src/cpp/include/query_coordinator.h | 7 +- src/cpp/src/clustering.cpp | 5 - src/cpp/src/maintenance_cost_estimator.cpp | 4 +- src/cpp/src/query_coordinator.cpp | 270 ++++++++++----------- 5 files changed, 253 insertions(+), 258 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index d66f4674..3095be71 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -335,10 +335,15 @@ inline void scan_list_no_ids_inner_product(const float *query_vec, const float *list_vecs, int list_size, int d, - TopkBuffer &buffer) { + TopkBuffer &buffer, + float pivot) { const float *vec = list_vecs; + float dist; for (int l = 0; l < list_size; l++) { - buffer.add(faiss::fvec_inner_product(query_vec, vec, d), l); + dist = faiss::fvec_inner_product(query_vec, vec, d); + if (dist > pivot) { + buffer.add(dist, l); + } vec += d; // move pointer to next vector } } @@ -347,10 +352,14 @@ inline void scan_list_no_ids_l2(const float *query_vec, const float *list_vecs, int list_size, int d, - TopkBuffer &buffer) { + TopkBuffer &buffer, + float pivot) { const float *vec = list_vecs; for (int l = 0; l < list_size; l++) { - buffer.add(sqrt(faiss::fvec_L2sqr(query_vec, vec, d)), l); + float dist = sqrt(faiss::fvec_L2sqr(query_vec, vec, d)); + if (dist < pivot) { + buffer.add(dist, l); + } vec += d; } } @@ -360,10 +369,14 @@ inline void scan_list_with_ids_inner_product(const float *query_vec, const int64_t *list_ids, int list_size, int d, - TopkBuffer &buffer) { + TopkBuffer &buffer, + float pivot) { const float *vec = list_vecs; for (int l = 0; l < list_size; l++) { - buffer.add(faiss::fvec_inner_product(query_vec, vec, d), list_ids[l]); + float dist = faiss::fvec_inner_product(query_vec, vec, d); + if (dist > pivot) { + buffer.add(dist, list_ids[l]); + } vec += d; } } @@ -373,7 +386,8 @@ inline void scan_list_with_ids_l2(const float *query_vec, const int64_t *list_ids, int list_size, int d, - TopkBuffer &buffer) { + TopkBuffer &buffer, + float pivot) { const float *vec = list_vecs; for (int l = 0; l < list_size; l++) { buffer.add(sqrt(faiss::fvec_L2sqr(query_vec, vec, d)), list_ids[l]); @@ -388,75 +402,104 @@ inline void scan_list(const float *query_vec, int list_size, int d, TopkBuffer &buffer, - faiss::MetricType metric = faiss::METRIC_L2) { + faiss::MetricType metric, + float pivot) { // Dispatch based on metric type and whether list_ids is provided. if (metric == faiss::METRIC_INNER_PRODUCT) { if (list_ids == nullptr) - scan_list_no_ids_inner_product(query_vec, list_vecs, list_size, d, buffer); + scan_list_no_ids_inner_product(query_vec, list_vecs, list_size, d, buffer, pivot); else - scan_list_with_ids_inner_product(query_vec, list_vecs, list_ids, list_size, d, buffer); + scan_list_with_ids_inner_product(query_vec, list_vecs, list_ids, list_size, d, buffer, pivot); } else { // Assume L2 (or similar) if (list_ids == nullptr) - scan_list_no_ids_l2(query_vec, list_vecs, list_size, d, buffer); + scan_list_no_ids_l2(query_vec, list_vecs, list_size, d, buffer, pivot); else - scan_list_with_ids_l2(query_vec, list_vecs, list_ids, list_size, d, buffer); + scan_list_with_ids_l2(query_vec, list_vecs, list_ids, list_size, d, buffer, pivot); } } -// inline void batched_scan_list( -// const float *query_vecs, -// const float *list_vecs, -// const int64_t *list_ids, -// int num_queries, -// int list_size, -// int dim, -// vector> &topk_buffers, -// MetricType metric = faiss::METRIC_L2, -// float *dist = nullptr, -// int64_t *labels = nullptr) // Optional output for distances and labels -// { -// if (list_size == 0 || list_vecs == nullptr) { -// return; -// } -// -// // Wrap raw arrays in torch Tensors, no copy -// Tensor query = torch::from_blob((void*)query_vecs, {num_queries, dim}, torch::kFloat32); -// Tensor list = torch::from_blob((void*)list_vecs, {list_size, dim}, torch::kFloat32); -// -// torch::Tensor distances; -// if (metric == faiss::METRIC_L2) { -// // Returns [num_queries, list_size], each entry is the Euclidean distance -// distances = torch::cdist(query, list, 2.0); -// } else if (metric == faiss::METRIC_INNER_PRODUCT) { -// // [num_queries, list_size], each entry is dot product -// distances = torch::matmul(query, list.t()); -// } else { -// throw std::runtime_error("Metric type not supported"); -// } -// -// // For each query, push all list vectors and their distances into TopkBuffer -// auto distances_acc = distances.accessor(); -// for (int i = 0; i < num_queries; ++i) { -// std::vector dists(list_size); -// std::vector ids(list_size); -// -// for (int j = 0; j < list_size; ++j) { -// dists[j] = distances_acc[i][j]; -// } -// -// if (list_ids) { -// for (int j = 0; j < list_size; ++j) { -// ids[j] = list_ids[j]; -// } -// } else { -// for (int j = 0; j < list_size; ++j) { -// ids[j] = j; -// } -// } -// -// topk_buffers[i]->batch_add(dists.data(), ids.data(), list_size); -// } -// } +inline void ip_blas( + const float* __restrict x, + const float* __restrict y, + const int64_t *list_ids, + size_t d, + size_t nx, + size_t ny, + size_t db_blas_bs, // = bs_y + size_t k, + vector> &topk_buffers, + float* __restrict ip_block, // nx * bs_y + vector*> pivot) // db_blas_bs +{ + if (nx == 0 || ny == 0) return; + + constexpr size_t bs_x = 256; + const size_t bs_y = db_blas_bs; + int64_t *list_ids_ptr = (int64_t *) list_ids; + + for (size_t i0 = 0; i0 < nx; i0 += bs_x) { + const size_t i1 = std::min(i0 + bs_x, nx); + const size_t q_chunk = i1 - i0; + + for (size_t j0 = 0; j0 < ny; j0 += bs_y) { + const size_t j1 = std::min(j0 + bs_y, ny); + const size_t db_chunk = j1 - j0; + + // use torch matmul + + /* SGEMM */ + { + const float one = 1.f; + float zero = 0.f; + FINTEGER nyi = FINTEGER(db_chunk); + FINTEGER nxi = FINTEGER(q_chunk); + FINTEGER di = FINTEGER(d); + sgemm_("Transpose","Not transpose", + &nyi,&nxi,&di, + &one, + y + j0 * d, &di, + x + i0 * d, &di, + &zero, + ip_block, &nyi); + } + + /* IP → L2² */ + if (k > 1) { + for (int64_t qi = 0; qi < static_cast(q_chunk); ++qi) { + float* line_ptr = ip_block + qi * db_chunk; // Pointer to current column in ip_block + // collect distances closer than pivot + if (pivot.size() > 0) { + float curr_pivot = pivot[qi]->load(std::memory_order_relaxed); + line_ptr = ip_block + qi * db_chunk; // Reset line_ptr to the start of the current column + for (size_t pj = 0; pj < db_chunk; ++pj) { + if (*line_ptr > curr_pivot) { + topk_buffers[qi]->add(*line_ptr, list_ids_ptr[j0 + pj]); + } + line_ptr++; // Move to the next element in the column + } + } else { + topk_buffers[qi]->batch_add(ip_block + qi * db_chunk, list_ids_ptr + j0, db_chunk); + } + } + } else if (k == 1) { + for (int64_t qi = 0; qi < static_cast(q_chunk); ++qi) { + float* line_ptr = ip_block + qi * db_chunk; // Pointer to current column in ip_block + float best_dist = -std::numeric_limits::infinity(); + int64_t best_id = -1; + + for (size_t pj = 0; pj < db_chunk; ++pj) { + if (*line_ptr < best_dist) { + best_dist = *line_ptr; + best_id = list_ids_ptr[j0 + pj]; + } + line_ptr++; // Move to the next element in the column + } + topk_buffers[qi]->add(best_dist, best_id); + } + } + } + } +} inline void l2_blas( @@ -495,11 +538,6 @@ inline void l2_blas( faiss::fvec_norms_L2sqr(norms_y, y + j0 * d, d, db_chunk); // use torch matmul - // Tensor x_chunk = torch::from_blob((void*)(x + i0 * d), {(int64_t) q_chunk, (int64_t) d}, torch::kFloat32); - // Tensor y_chunk = torch::from_blob((void*)(y + j0 * d), {(int64_t) db_chunk, (int64_t) d}, torch::kFloat32); - // Tensor out = torch::from_blob(ip_block, {(int64_t) q_chunk, (int64_t) db_chunk}, torch::kFloat32); - // - // torch::matmul_out(out, x_chunk, y_chunk.t()); /* SGEMM */ { @@ -571,15 +609,10 @@ inline void batched_scan_list(const float *query_vecs, int list_size, int dim, vector> &topk_buffers, - int64_t *setup_time, - int64_t *scan_time, - int64_t *push_time, MetricType metric, - float *distances, - int64_t *labels, float *ip_block, - float *norms_x, - float *norms_y_buf, + float *norms_x, + float *norms_y_buf, int blas_db_bs = BLAS_DB_BS, vector*> pivots = {}) { if (list_size == 0 || list_vecs == nullptr) { @@ -587,26 +620,26 @@ inline void batched_scan_list(const float *query_vecs, return; } - auto s1 = high_resolution_clock::now(); // Ensure k does not exceed list_size int k = topk_buffers[0]->k(); int k_max = std::min(k, list_size); - bool alloc_results = false; - if (distances == nullptr) { - alloc_results = true; - labels = (int64_t *) malloc(num_queries * k_max * sizeof(int64_t)); - distances = (float *) malloc(num_queries * k_max * sizeof(float)); - } - - auto s2 = high_resolution_clock::now(); - if (metric == faiss::METRIC_INNER_PRODUCT) { - faiss::float_minheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; - faiss::knn_inner_product(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr); + ip_blas( + query_vecs, + list_vecs, + list_ids, + dim, + num_queries, + list_size, + blas_db_bs, + k_max, + topk_buffers, + ip_block, + pivots + ); } else if (metric == faiss::METRIC_L2) { - // faiss::float_maxheap_array_t res = {size_t(num_queries), size_t(k_max), labels, distances}; l2_blas( query_vecs, list_vecs, @@ -622,19 +655,9 @@ inline void batched_scan_list(const float *query_vecs, norms_y_buf, pivots ); - // faiss::knn_L2sqr(query_vecs, list_vecs, dim, num_queries, list_size, &res, nullptr, nullptr); } else { throw std::runtime_error("Metric type not supported"); } - - auto s3 = high_resolution_clock::now(); - - - auto s4 = high_resolution_clock::now(); - - *setup_time = duration_cast(s2 - s1).count(); - *scan_time = duration_cast(s3 - s2).count(); - *push_time = duration_cast(s4 - s3).count(); } diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index a4d5d4b9..9f14fca7 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -82,9 +82,7 @@ class QueryCoordinator { int64_t wait_time_ns = 0; ///< Time spent waiting for jobs. int64_t process_time_ns = 0; ///< Time spent processing jobs. int64_t process_preamble_time_ns = 0; ///< Time spent on job processing (excluding waiting). - int64_t scan_setup_time_ns = 0; ///< Time spent on scan setup. int64_t scan_time_ns = 0; ///< Time spent on scanning. - int64_t scan_push_time_ns = 0; ///< Time spent pushing results. int64_t enqueue_time_ns = 0; ///< Time spent enqueuing. int64_t job_time_ns = 0; ///< Time spent on job processing (excluding waiting). }; @@ -111,7 +109,10 @@ class QueryCoordinator { int num_workers_; ///< Total number of worker threads. vector worker_threads_; ///< Container for worker threads. vector worker_job_counter_; ///< Job counters for each worker. - shared_ptr>> global_topk_buffer_pool_; ///< Global aggregator buffers. + + shared_ptr>> global_min_heaps_; ///< Global aggregator buffers. + shared_ptr>> global_max_heaps_; ///< Global aggregator buffers. + std::mutex global_mutex_; ///< Mutex for global synchronization. std::condition_variable global_cv_; ///< Condition variable for thread coordination. std::atomic stop_workers_; ///< Flag to signal workers to terminate. diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index 99344635..85f517e8 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -321,12 +321,7 @@ tuple >> kmeans_refine_partitions( n_clusters, d, buffers, - &scan_setup_time, - &scan_time, - &scan_push_time, metric, - /* distances*/ nullptr, - /* labels */ nullptr, /* BLAS scratch */ blas_ip_block, blas_norms_x, blas_norms_y, diff --git a/src/cpp/src/maintenance_cost_estimator.cpp b/src/cpp/src/maintenance_cost_estimator.cpp index d1f4d1ab..ed4d2eb8 100644 --- a/src/cpp/src/maintenance_cost_estimator.cpp +++ b/src/cpp/src/maintenance_cost_estimator.cpp @@ -63,6 +63,8 @@ void ListScanLatencyEstimator::profile_scan_latency() { torch::Tensor ids = torch::randperm(max_n); torch::Tensor query = torch::rand({d_}); + + for (size_t i = 0; i < n_values_.size(); ++i) { for (size_t j = 0; j < k_values_.size(); ++j) { int n = n_values_[i]; @@ -80,7 +82,7 @@ void ListScanLatencyEstimator::profile_scan_latency() { for (int m = 0; m < n_trials_; ++m) { auto start = std::chrono::high_resolution_clock::now(); scan_list(query_ptr, curr_vectors_ptr, curr_ids_ptr, n, d_, - *topk_buffer); + *topk_buffer, faiss::METRIC_L2, 10000000.0); auto end = std::chrono::high_resolution_clock::now(); auto duration = diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 70f41414..fe52be0f 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -235,7 +235,8 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, part_size, D, *buf, - metric_); + metric_, + query_dist_pivots_[job.query_id].load(std::memory_order_relaxed)); // If scan_list completes, enqueue its results auto tv = buf->get_topk(false); @@ -259,6 +260,7 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, CoreResources &res, NUMAResources &nr) { + auto start = std::chrono::high_resolution_clock::now(); // Total queries, Top-K, dimension, NUMA node int64_t Q = job.num_queries; int K = job.k; @@ -339,7 +341,6 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, qptr = dst; } - vector *> pivots; pivots.resize(job.num_queries); for (int64_t i = 0; i < Q; ++i) { @@ -348,50 +349,41 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, } // run the scan on this chunk - int64_t scan_setup_time = 0; - int64_t scan_time = 0; - int64_t scan_push_time = 0; + batched_scan_list( qptr, codes, ids, Q, part_size, D, res.topk_buffer_pool, - &scan_setup_time, - &scan_time, - &scan_push_time, metric_, - /* distances*/ res.batch_distances, - /* labels */ res.batch_ids, - /* BLAS scratch */ res.blas_ip_block, - res.blas_norms_x, - res.blas_norms_y, + res.blas_ip_block, + res.blas_norms_x, + res.blas_norms_y, BLAS_DB_BS, pivots); + auto end = std::chrono::high_resolution_clock::now(); + res.scan_time_ns += std::chrono::duration_cast(end - start).count(); - res.scan_setup_time_ns += scan_setup_time; - res.scan_time_ns += scan_time; - res.scan_push_time_ns += scan_push_time; - - auto start = std::chrono::high_resolution_clock::now(); - // collect results for this chunk - std::vector results_batch; - results_batch.reserve(Q); - for (int64_t i = 0; i < Q; ++i) { - int global_q = (*job.query_ids)[i]; - int rank_q = (*job.ranks) [i]; - auto tv = res.topk_buffer_pool[i]->get_topk(false); - auto ti = res.topk_buffer_pool[i]->get_topk_indices(false); - results_batch.emplace_back(ResultJob{global_q, rank_q, std::move(tv), std::move(ti)}); - } + start = std::chrono::high_resolution_clock::now(); + // collect results for this chunk + std::vector results_batch; + results_batch.reserve(Q); + for (int64_t i = 0; i < Q; ++i) { + int global_q = (*job.query_ids)[i]; + int rank_q = (*job.ranks) [i]; + auto tv = res.topk_buffer_pool[i]->get_topk(false); + auto ti = res.topk_buffer_pool[i]->get_topk_indices(false); + results_batch.emplace_back(ResultJob{global_q, rank_q, std::move(tv), std::move(ti)}); + } - // enqueue this sub-batch in bulk - result_queue_.enqueue_bulk( - std::make_move_iterator(results_batch.begin()), - results_batch.size() - ); - auto end = std::chrono::high_resolution_clock::now(); - res.enqueue_time_ns += std::chrono::duration_cast(end - start).count(); + // enqueue this sub-batch in bulk + result_queue_.enqueue_bulk( + std::make_move_iterator(results_batch.begin()), + results_batch.size() + ); + end = std::chrono::high_resolution_clock::now(); + res.enqueue_time_ns += std::chrono::duration_cast(end - start).count(); } void QueryCoordinator::init_global_buffers(int64_t nQ, @@ -405,35 +397,24 @@ void QueryCoordinator::init_global_buffers(int64_t nQ, // faiss::HeapArray>(nQ) }; float * vals = (float *) quake_alloc(nQ * K * sizeof(float), 0); int64_t * ids = (int64_t *) quake_alloc(nQ * K * sizeof(int64_t), 0); - std::fill_n(vals, nQ * K, - std::numeric_limits::infinity()); std::fill_n(ids, nQ * K, -1); - global_topk_buffer_pool_ = make_shared>>( - nQ, vals, ids, K); - global_topk_buffer_pool_->begin_multiple(0, nQ); - // if (global_topk_buffer_pool_.size() < (size_t) nQ) { - // size_t old = global_topk_buffer_pool_.size(); - // global_topk_buffer_pool_.resize(nQ); - // for (int64_t q = old; q < nQ; ++q) { - // global_topk_buffer_pool_[q] = std::make_shared( - // K, - // metric_ == faiss::METRIC_INNER_PRODUCT, - // /*cap=*/cap, - // /*node=*/0 - // ); - // } - // } else { - // for (int64_t q = 0; q < nQ; ++q) { - // global_topk_buffer_pool_[q]->set_k(K); - // global_topk_buffer_pool_[q]->reset(); - // } - // } - - // set pivots to -1; float max_val = (metric_ == faiss::METRIC_INNER_PRODUCT) - ? -std::numeric_limits::infinity() - : std::numeric_limits::infinity(); + ? -std::numeric_limits::infinity() + : std::numeric_limits::infinity(); + + std::fill_n(vals, nQ * K, max_val); + + if (metric_ == faiss::METRIC_INNER_PRODUCT) { + global_max_heaps_ = make_shared>>( + nQ, vals, ids, K); + } else { + std::fill_n(vals, nQ * K, + std::numeric_limits::infinity()); + global_min_heaps_ = make_shared>>( + nQ, vals, ids, K); + } + query_dist_pivots_ = vector>(nQ); for (int64_t q = 0; q < nQ; ++q) { query_dist_pivots_[q].store(max_val, std::memory_order_relaxed); @@ -627,79 +608,81 @@ void QueryCoordinator::drain_and_apply_aps(Tensor x, vector per_query_result_count(nQ, 0); - vector>::SingleResultHandler> - handlers; - handlers.reserve(nQ); - for (int64_t q = 0; q < nQ; ++q) { - handlers.emplace_back(*global_topk_buffer_pool_); - handlers[q].begin(q); // ← reset & heapify for query q - } + if (metric_ == faiss::METRIC_INNER_PRODUCT) { + vector>::SingleResultHandler> + handlers; + for (int64_t q = 0; q < nQ; ++q) { + handlers.emplace_back(*global_max_heaps_); + handlers[q].begin(q); // ← reset & heapify for query q + } - ResultJob rj; - while (total_left.load(std::memory_order_relaxed) > 0) { + ResultJob rj; + while (total_left.load(std::memory_order_relaxed) > 0) { - /* -- Wait for result or APS timeout -- */ - bool got_result = result_queue_.wait_dequeue_timed(rj, aps_dur); + /* -- Wait for result or APS timeout -- */ + bool got_result = result_queue_.wait_dequeue_timed(rj, aps_dur); - if (got_result) { - do { // Drain *all* currently available results. - for (int64_t i = 0; i < rj.distances.size(); ++i) { - handlers[rj.query_id].add_result(rj.distances[i], rj.indices[i]); - } - query_dist_pivots_[rj.query_id].store( - handlers[rj.query_id].threshold, std::memory_order_relaxed); + if (got_result) { + do { // Drain *all* currently available results. + for (int64_t i = 0; i < rj.distances.size(); ++i) { + handlers[rj.query_id].add_result(rj.distances[i], rj.indices[i]); + } + query_dist_pivots_[rj.query_id].store( + handlers[rj.query_id].threshold, std::memory_order_relaxed); - per_query_result_count[rj.query_id]++; + per_query_result_count[rj.query_id]++; - if (!job_flags_[rj.query_id][rj.rank]) { - job_flags_[rj.query_id][rj.rank] = true; - --parts_left[rj.query_id]; - --total_left; - } + if (!job_flags_[rj.query_id][rj.rank]) { + job_flags_[rj.query_id][rj.rank] = true; + --parts_left[rj.query_id]; + --total_left; + } + } while (result_queue_.try_dequeue(rj)); + } + } + // end the handlers + for (int64_t q = 0; q < nQ; ++q) { + handlers[q].end(); + } + } else { + vector>::SingleResultHandler> + handlers; + handlers.reserve(nQ); + for (int64_t q = 0; q < nQ; ++q) { + handlers.emplace_back(*global_min_heaps_); + handlers[q].begin(q); // ← reset & heapify for query q + } - // if (parts_left[rj.query_id] == 0) { - // global_topk_buffer_pool_[rj.query_id]->flush(); - // } - } while (result_queue_.try_dequeue(rj)); + ResultJob rj; + while (total_left.load(std::memory_order_relaxed) > 0) { - continue; // Skip APS; we just did useful work. - } + /* -- Wait for result or APS timeout -- */ + bool got_result = result_queue_.wait_dequeue_timed(rj, aps_dur); + if (got_result) { + do { // Drain *all* currently available results. + for (int64_t i = 0; i < rj.distances.size(); ++i) { + handlers[rj.query_id].add_result(rj.distances[i], rj.indices[i]); + } + query_dist_pivots_[rj.query_id].store( + handlers[rj.query_id].threshold, std::memory_order_relaxed); - /* (b) Timeout fired → run APS once. */ - // if (use_aps) { - // for (int64_t q = 0; q < nQ; ++q) { - // if (parts_left[q] == 0) continue; - // - // auto &buf = global_topk_buffer_pool_[q]; - // const float r = buf->get_kth_distance(); - // if (r != query_radius[q]) { - // query_radius[q] = r; - // probs[q] = compute_recall_profile( - // boundary_dist[q], r, D, {}, true, metric_==faiss::METRIC_L2); - // } - // - // float cum = 0.0f; - // for (int64_t p = 0; p < nprobe; ++p) - // if (job_flags_[q][p]) cum += probs[q][p]; - // - // if (cum >= recall_target) { - // for (int64_t p = 0; p < nprobe; ++p) - // if (!job_flags_[q][p]) { - // job_flags_[q][p] = true; - // --parts_left[q]; - // --total_left; - // } - // } - // } - // } - } + per_query_result_count[rj.query_id]++; - // end the handlers - for (int64_t q = 0; q < nQ; ++q) { - handlers[q].end(); - } + if (!job_flags_[rj.query_id][rj.rank]) { + job_flags_[rj.query_id][rj.rank] = true; + --parts_left[rj.query_id]; + --total_left; + } + } while (result_queue_.try_dequeue(rj)); + } + } + // end the handlers + for (int64_t q = 0; q < nQ; ++q) { + handlers[q].end(); + } + } } std::shared_ptr @@ -711,19 +694,22 @@ QueryCoordinator::aggregate_scan_results(int64_t nQ, auto id_acc = out_ids.accessor(); auto d_acc = out_dists.accessor(); - for (int64_t q = 0; q < nQ; ++q) { - for (int64_t i = 0; i < K; ++i) { - id_acc[q][i] = global_topk_buffer_pool_->heap_ids_tab[q * K + i]; - d_acc [q][i] = global_topk_buffer_pool_->heap_dis_tab[q * K + i]; + // copy results from the global heaps to the output tensors + if (metric_ == faiss::METRIC_INNER_PRODUCT) { + for (int64_t q = 0; q < nQ; ++q) { + for (int64_t i = 0; i < K; ++i) { + id_acc[q][i] = global_max_heaps_->heap_ids_tab[q * K + i]; + d_acc [q][i] = global_max_heaps_->heap_dis_tab[q * K + i]; + } + } + } else { + for (int64_t q = 0; q < nQ; ++q) { + for (int64_t i = 0; i < K; ++i) { + id_acc[q][i] = global_min_heaps_->heap_ids_tab[q * K + i]; + d_acc [q][i] = global_min_heaps_->heap_dis_tab[q * K + i]; + } } - - // auto tv = global_topk_buffer_pool_[q]->get_topk(); - // auto ti = global_topk_buffer_pool_[q]->get_topk_indices(); - // for (int i = 0; i < (int)ti.size() && i < K; ++i) { - // id_acc[q][i] = ti[i]; - // d_acc [q][i] = tv[i]; - // } } auto res = std::make_shared(); @@ -764,9 +750,7 @@ std::shared_ptr QueryCoordinator::worker_scan( core_process_preamble_time_ns[i] = core_resources_[i].process_preamble_time_ns; core_enqueue_time_ns[i] = core_resources_[i].enqueue_time_ns; core_job_time_ns[i] = core_resources_[i].job_time_ns; - core_scan_setup_time_ns[i] = core_resources_[i].scan_setup_time_ns; core_scan_time_ns[i] = core_resources_[i].scan_time_ns; - core_scan_push_time_ns[i] = core_resources_[i].scan_push_time_ns; } auto s1 = high_resolution_clock::now(); @@ -817,9 +801,7 @@ std::shared_ptr QueryCoordinator::worker_scan( core_process_preamble_time_ns[i] = core_resources_[i].process_preamble_time_ns - core_process_preamble_time_ns[i]; core_enqueue_time_ns[i] = core_resources_[i].enqueue_time_ns - core_enqueue_time_ns[i]; core_job_time_ns[i] = core_resources_[i].job_time_ns - core_job_time_ns[i]; - core_scan_setup_time_ns[i] = core_resources_[i].scan_setup_time_ns - core_scan_setup_time_ns[i]; core_scan_time_ns[i] = core_resources_[i].scan_time_ns - core_scan_time_ns[i]; - core_scan_push_time_ns[i] = core_resources_[i].scan_push_time_ns - core_scan_push_time_ns[i]; } @@ -1013,7 +995,8 @@ shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partitio partition_manager_->partition_store_->list_size(pi), dimension, *topk_buf, - metric_); + metric_, + query_radius); scanned_ids.push_back(pi); float curr_radius = topk_buf->get_kth_distance(); @@ -1262,10 +1245,6 @@ shared_ptr QueryCoordinator::batched_serial_scan( // Perform a single batched scan on the partition. - int64_t scan_setup_time = 0; - int64_t scan_time = 0; - int64_t scan_push_time = 0; - batched_scan_list(x_subset.data_ptr(), list_codes, list_ids, @@ -1273,12 +1252,7 @@ shared_ptr QueryCoordinator::batched_serial_scan( list_size, d, local_buffers, - &scan_setup_time, - &scan_time, - &scan_push_time, metric_, - /* distances*/ nullptr, - /* labels */ nullptr, /* BLAS scratch */ serial_res.blas_ip_block, serial_res.blas_norms_x, serial_res.blas_norms_y, From 043e12f3baae26aff302a69a37ae46bf3103dcab Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 22:06:02 -0500 Subject: [PATCH 248/323] verify numa --- src/cpp/include/parallel.h | 91 +++++++++++++++++++++++++++++++ src/cpp/src/query_coordinator.cpp | 14 ++++- 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/src/cpp/include/parallel.h b/src/cpp/include/parallel.h index ab61f6c9..13ed5a5e 100644 --- a/src/cpp/include/parallel.h +++ b/src/cpp/include/parallel.h @@ -66,6 +66,90 @@ inline bool set_thread_affinity(int core_id) { return numa_num_configured_nodes(); } + inline int get_current_cpu_numa_node() { + if (numa_available() < 0) return 0; // NUMA not available or error + int current_cpu = sched_getcpu(); + if (current_cpu < 0) { + // perror("sched_getcpu failed"); // User prefers less output + return -1; // Error + } + return numa_node_of_cpu(current_cpu); + } + + // Helper to get the NUMA node of a memory address + inline int get_memory_numa_node(const void* ptr) { + if (numa_available() < 0) return 0; // NUMA not available or error + if (!ptr) { + return -1; // Invalid pointer + } + + int page_node = -1; + // Align pointer to page boundary for numa_move_pages query + void* page_address = (void*)((uintptr_t)ptr & ~((uintptr_t)getpagesize() - 1)); + + // Use numa_move_pages with nodes=NULL to query the current node of the page. + // The 'pages' argument is an array of page addresses. + void *pages_to_query[] = { page_address }; + int status_array[] = { -1 }; // To store the node of the page + + // pid = 0 for current process's address space + if (numa_move_pages(0, 1, pages_to_query, NULL, status_array, 0) == 0) { + page_node = status_array[0]; + } else { + // perror("numa_move_pages query failed"); // User prefers less output + // This could happen if the page is not mapped, or other errors. + page_node = -2; // Indicate error in querying + } + return page_node; + } + + // Verifies if the memory at memory_address is on the same NUMA node as the current CPU. + // variable_name is for logging/debugging by the caller if verification fails. + inline bool verify_numa_locality(const void* memory_address, const char* /*variable_name*/) { + if (numa_available() < 0) return true; // NUMA not available, assume locality + if (get_num_numa_nodes() <= 1) return true; // Single NUMA node system + + if (!memory_address) { + std::cout << "Warning: Cannot verify NUMA locality for null pointer: " << variable_name << std::endl; + return true; // Or false, based on desired strictness for nullptrs. True avoids false positives. + } + + int current_cpu_node = get_current_cpu_numa_node(); + if (current_cpu_node < 0) { + std::cout << "Error: Could not determine current CPU NUMA node for " << variable_name << std::endl; + return false; // Cannot verify + } + + int memory_page_node = get_memory_numa_node(memory_address); + if (memory_page_node < -1) { // -2 indicates query error + std::cout << "Error: Could not determine NUMA node for memory of " << variable_name << std::endl; + return false; // Cannot verify due to error + } + if (memory_page_node == -1) { + // This typically means the page is not mapped or has a default/interleaved policy + // that doesn't map to a single specific node in a way numa_move_pages can report. + // For strict checking, this could be considered non-local if cpu_node is specific. + // Caller can log: "Warning: Memory for " << variable_name << " has undetermined/interleaved policy (node -1). CPU node: " << current_cpu_node + // A common case for MPOL_DEFAULT is allocation on the node of first touch. + // If it's truly interleaved, it's not "local" to any single node. + // If it's default and first touched by current_cpu_node, it would be local. + // This check is tricky. For now, if we can't determine a specific node, assume it might not be local. + std::cout << "Warning: Memory for " << variable_name << " has undetermined/interleaved policy (node -1). CPU node: " << current_cpu_node << std::endl; + return false; + } + + bool is_local = (current_cpu_node == memory_page_node); + + if (is_local) { + std::cout << "NUMA locality verified for " << variable_name << std::endl; + } else { + std::cout << "Warning: NUMA locality mismatch for " << variable_name + << ": CPU is on node " << current_cpu_node + << ", but memory is on node " << memory_page_node << std::endl; + } + + return is_local; + } #else #include #include @@ -89,6 +173,13 @@ inline int cpu_numa_node(int /*cpu*/) { inline int get_num_numa_nodes() { return 1; // Not applicable } + +inline bool verify_numa_locality(const void* /*memory_address*/, const char* /*variable_name*/) { + return true; +} +inline int get_current_cpu_numa_node() { return 0; } +inline int get_memory_numa_node(const void* /*ptr*/) { return 0; } + #endif diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index fe52be0f..15cf4d37 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -348,8 +348,20 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, pivots[i] = &query_dist_pivots_[qid]; } - // run the scan on this chunk + // check that things are on the proper NUMA node + verify_numa_locality(qptr, "qptr"); + verify_numa_locality(codes, "codes"); + verify_numa_locality(ids, "ids"); + verify_numa_locality(res.batch_distances, "batch_distances"); + verify_numa_locality(res.batch_ids, "batch_ids"); + verify_numa_locality(res.blas_ip_block, "blas_ip_block"); + verify_numa_locality(res.blas_norms_x, "blas_norms_x"); + verify_numa_locality(res.blas_norms_y, "blas_norms_y"); + verify_numa_locality(res.topk_buffer_pool[0]->ord_, "ord_"); + verify_numa_locality(res.topk_buffer_pool[0]->vals_, "vals_"); + verify_numa_locality(res.topk_buffer_pool[0]->ids_, "ids_"); + // run the scan on this chunk batched_scan_list( qptr, codes, ids, From 423178b0ce1a3559a98f9f730be2efa201dc7154 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 22:06:53 -0500 Subject: [PATCH 249/323] verify numa --- src/cpp/include/parallel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/include/parallel.h b/src/cpp/include/parallel.h index 13ed5a5e..e0cc26dc 100644 --- a/src/cpp/include/parallel.h +++ b/src/cpp/include/parallel.h @@ -105,7 +105,7 @@ inline bool set_thread_affinity(int core_id) { // Verifies if the memory at memory_address is on the same NUMA node as the current CPU. // variable_name is for logging/debugging by the caller if verification fails. - inline bool verify_numa_locality(const void* memory_address, const char* /*variable_name*/) { + inline bool verify_numa_locality(const void* memory_address, const char* variable_name) { if (numa_available() < 0) return true; // NUMA not available, assume locality if (get_num_numa_nodes() <= 1) return true; // Single NUMA node system From 88027f6cd87521b78cdd4d98dbfd4b9c2347712c Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 22:11:13 -0500 Subject: [PATCH 250/323] verify numa --- src/cpp/src/query_coordinator.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 15cf4d37..0adc6f00 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -349,17 +349,20 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, } // check that things are on the proper NUMA node - verify_numa_locality(qptr, "qptr"); - verify_numa_locality(codes, "codes"); - verify_numa_locality(ids, "ids"); - verify_numa_locality(res.batch_distances, "batch_distances"); - verify_numa_locality(res.batch_ids, "batch_ids"); - verify_numa_locality(res.blas_ip_block, "blas_ip_block"); - verify_numa_locality(res.blas_norms_x, "blas_norms_x"); - verify_numa_locality(res.blas_norms_y, "blas_norms_y"); - verify_numa_locality(res.topk_buffer_pool[0]->ord_, "ord_"); - verify_numa_locality(res.topk_buffer_pool[0]->vals_, "vals_"); - verify_numa_locality(res.topk_buffer_pool[0]->ids_, "ids_"); + // verify_numa_locality(qptr, "qptr"); + // verify_numa_locality(codes, "codes"); + // verify_numa_locality(ids, "ids"); + // verify_numa_locality(res.batch_distances, "batch_distances"); + // verify_numa_locality(res.batch_ids, "batch_ids"); + // verify_numa_locality(res.blas_ip_block, "blas_ip_block"); + // verify_numa_locality(res.blas_norms_x, "blas_norms_x"); + // verify_numa_locality(res.blas_norms_y, "blas_norms_y"); + + for (int64_t i = 0; i < Q; ++i) { + verify_numa_locality(res.topk_buffer_pool[i]->ord_, "ord_"); + verify_numa_locality(res.topk_buffer_pool[i]->vals_, "vals_"); + verify_numa_locality(res.topk_buffer_pool[i]->ids_, "ids_"); + } // run the scan on this chunk batched_scan_list( From 092a6676ff89ee2d048bbd36dd025e6af14d3b69 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 22:13:01 -0500 Subject: [PATCH 251/323] verify numa --- src/cpp/src/query_coordinator.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 0adc6f00..c7b23f8d 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -358,11 +358,11 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, // verify_numa_locality(res.blas_norms_x, "blas_norms_x"); // verify_numa_locality(res.blas_norms_y, "blas_norms_y"); - for (int64_t i = 0; i < Q; ++i) { - verify_numa_locality(res.topk_buffer_pool[i]->ord_, "ord_"); - verify_numa_locality(res.topk_buffer_pool[i]->vals_, "vals_"); - verify_numa_locality(res.topk_buffer_pool[i]->ids_, "ids_"); - } + // for (int64_t i = 0; i < Q; ++i) { + // verify_numa_locality(res.topk_buffer_pool[i]->ord_, "ord_"); + // verify_numa_locality(res.topk_buffer_pool[i]->vals_, "vals_"); + // verify_numa_locality(res.topk_buffer_pool[i]->ids_, "ids_"); + // } // run the scan on this chunk batched_scan_list( From e3ad685ce691a9b3dd10362e38006cc789f176cc Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 22:15:54 -0500 Subject: [PATCH 252/323] verify numa --- src/cpp/include/parallel.h | 2 +- src/cpp/src/query_coordinator.cpp | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/cpp/include/parallel.h b/src/cpp/include/parallel.h index e0cc26dc..e2150100 100644 --- a/src/cpp/include/parallel.h +++ b/src/cpp/include/parallel.h @@ -141,7 +141,7 @@ inline bool set_thread_affinity(int core_id) { bool is_local = (current_cpu_node == memory_page_node); if (is_local) { - std::cout << "NUMA locality verified for " << variable_name << std::endl; + // std::cout << "NUMA locality verified for " << variable_name << std::endl; } else { std::cout << "Warning: NUMA locality mismatch for " << variable_name << ": CPU is on node " << current_cpu_node diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index c7b23f8d..bf6b5940 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -349,6 +349,23 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, } // check that things are on the proper NUMA node + bool ok = true; + ok = ok & verify_numa_locality(res.batch_queries, "batch_queries"); + ok = ok & verify_numa_locality(res.batch_distances, "batch_distances"); + ok = ok & verify_numa_locality(res.batch_ids, "batch_ids"); + ok = ok & verify_numa_locality(res.blas_ip_block, "blas_ip_block"); + ok = ok & verify_numa_locality(res.blas_norms_x, "blas_norms_x"); + ok = ok & verify_numa_locality(res.blas_norms_y, "blas_norms_y"); + for (int64_t i = 0; i < Q; ++i) { + ok = ok & verify_numa_locality(res.topk_buffer_pool[i]->ord_, "ord_"); + ok = ok & verify_numa_locality(res.topk_buffer_pool[i]->vals_, "vals_"); + ok = ok & verify_numa_locality(res.topk_buffer_pool[i]->ids_, "ids_"); + } + if (!ok) { + std::cerr << "[QueryCoordinator::handle_batched_job] NUMA locality check failed.\n"; + throw std::runtime_error("NUMA locality check failed"); + } + // verify_numa_locality(qptr, "qptr"); // verify_numa_locality(codes, "codes"); // verify_numa_locality(ids, "ids"); @@ -357,7 +374,7 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, // verify_numa_locality(res.blas_ip_block, "blas_ip_block"); // verify_numa_locality(res.blas_norms_x, "blas_norms_x"); // verify_numa_locality(res.blas_norms_y, "blas_norms_y"); - + // // for (int64_t i = 0; i < Q; ++i) { // verify_numa_locality(res.topk_buffer_pool[i]->ord_, "ord_"); // verify_numa_locality(res.topk_buffer_pool[i]->vals_, "vals_"); From e7634c6cc99afd6f9e5079fa400cb2a797c3f74b Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 22:20:41 -0500 Subject: [PATCH 253/323] verify numa --- src/cpp/src/query_coordinator.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index bf6b5940..6d6c1ba9 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -350,16 +350,19 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, // check that things are on the proper NUMA node bool ok = true; - ok = ok & verify_numa_locality(res.batch_queries, "batch_queries"); - ok = ok & verify_numa_locality(res.batch_distances, "batch_distances"); - ok = ok & verify_numa_locality(res.batch_ids, "batch_ids"); - ok = ok & verify_numa_locality(res.blas_ip_block, "blas_ip_block"); - ok = ok & verify_numa_locality(res.blas_norms_x, "blas_norms_x"); - ok = ok & verify_numa_locality(res.blas_norms_y, "blas_norms_y"); + ok = ok && verify_numa_locality(qptr, "qptr"); + ok = ok && verify_numa_locality(codes, "codes"); + ok = ok && verify_numa_locality(ids, "ids"); + ok = ok && verify_numa_locality(res.batch_queries, "batch_queries"); + ok = ok && verify_numa_locality(res.batch_distances, "batch_distances"); + ok = ok && verify_numa_locality(res.batch_ids, "batch_ids"); + ok = ok && verify_numa_locality(res.blas_ip_block, "blas_ip_block"); + ok = ok && verify_numa_locality(res.blas_norms_x, "blas_norms_x"); + ok = ok && verify_numa_locality(res.blas_norms_y, "blas_norms_y"); for (int64_t i = 0; i < Q; ++i) { - ok = ok & verify_numa_locality(res.topk_buffer_pool[i]->ord_, "ord_"); - ok = ok & verify_numa_locality(res.topk_buffer_pool[i]->vals_, "vals_"); - ok = ok & verify_numa_locality(res.topk_buffer_pool[i]->ids_, "ids_"); + ok = ok && verify_numa_locality(res.topk_buffer_pool[i]->ord_, "ord_"); + ok = ok && verify_numa_locality(res.topk_buffer_pool[i]->vals_, "vals_"); + ok = ok && verify_numa_locality(res.topk_buffer_pool[i]->ids_, "ids_"); } if (!ok) { std::cerr << "[QueryCoordinator::handle_batched_job] NUMA locality check failed.\n"; From b3a7d4444ef643656e0b8fcb65ad22926e9b73e7 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 22:23:03 -0500 Subject: [PATCH 254/323] verify numa --- src/cpp/src/query_coordinator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 6d6c1ba9..cec8b55d 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -354,8 +354,8 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, ok = ok && verify_numa_locality(codes, "codes"); ok = ok && verify_numa_locality(ids, "ids"); ok = ok && verify_numa_locality(res.batch_queries, "batch_queries"); - ok = ok && verify_numa_locality(res.batch_distances, "batch_distances"); - ok = ok && verify_numa_locality(res.batch_ids, "batch_ids"); + // ok = ok && verify_numa_locality(res.batch_distances, "batch_distances"); + // ok = ok && verify_numa_locality(res.batch_ids, "batch_ids"); ok = ok && verify_numa_locality(res.blas_ip_block, "blas_ip_block"); ok = ok && verify_numa_locality(res.blas_norms_x, "blas_norms_x"); ok = ok && verify_numa_locality(res.blas_norms_y, "blas_norms_y"); From df30166514c376c781664b941e8dd7767b5bbbb8 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 22:25:03 -0500 Subject: [PATCH 255/323] verify numa --- src/cpp/include/parallel.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cpp/include/parallel.h b/src/cpp/include/parallel.h index e2150100..007a30cf 100644 --- a/src/cpp/include/parallel.h +++ b/src/cpp/include/parallel.h @@ -122,6 +122,7 @@ inline bool set_thread_affinity(int core_id) { int memory_page_node = get_memory_numa_node(memory_address); if (memory_page_node < -1) { // -2 indicates query error + std::cout << "memory_page_node = " << memory_page_node << std::endl; std::cout << "Error: Could not determine NUMA node for memory of " << variable_name << std::endl; return false; // Cannot verify due to error } From 9982cfd67431262fd968d91b6781319f30004d57 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 22:27:58 -0500 Subject: [PATCH 256/323] verify numa --- src/cpp/src/query_coordinator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index cec8b55d..552de192 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -366,7 +366,7 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, } if (!ok) { std::cerr << "[QueryCoordinator::handle_batched_job] NUMA locality check failed.\n"; - throw std::runtime_error("NUMA locality check failed"); + // throw std::runtime_error("NUMA locality check failed"); } // verify_numa_locality(qptr, "qptr"); From aceb22a35b3f9452b8de30a31d7e6cebf6c8acf3 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 22:35:31 -0500 Subject: [PATCH 257/323] verify numa --- src/cpp/include/parallel.h | 22 ++++++++++++---------- src/cpp/include/query_coordinator.h | 3 --- src/cpp/src/query_coordinator.cpp | 20 +++++++------------- 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/src/cpp/include/parallel.h b/src/cpp/include/parallel.h index 007a30cf..4158ce83 100644 --- a/src/cpp/include/parallel.h +++ b/src/cpp/include/parallel.h @@ -80,28 +80,30 @@ inline bool set_thread_affinity(int core_id) { inline int get_memory_numa_node(const void* ptr) { if (numa_available() < 0) return 0; // NUMA not available or error if (!ptr) { - return -1; // Invalid pointer + return -1; // Invalid pointer (e.g. NULL) } - int page_node = -1; // Align pointer to page boundary for numa_move_pages query void* page_address = (void*)((uintptr_t)ptr & ~((uintptr_t)getpagesize() - 1)); - // Use numa_move_pages with nodes=NULL to query the current node of the page. - // The 'pages' argument is an array of page addresses. void *pages_to_query[] = { page_address }; int status_array[] = { -1 }; // To store the node of the page + errno = 0; // Clear errno before system call // pid = 0 for current process's address space + // nodes = NULL to query current node + // flags = 0 for query if (numa_move_pages(0, 1, pages_to_query, NULL, status_array, 0) == 0) { - page_node = status_array[0]; + // Success. status_array[0] contains the node. + // It can be -1 if the page has a policy like MPOL_INTERLEAVE or is not mapped to a specific node. + return status_array[0]; } else { - // perror("numa_move_pages query failed"); // User prefers less output - // This could happen if the page is not mapped, or other errors. - page_node = -2; // Indicate error in querying + // numa_move_pages failed, return negative errno. + // errno is set by numa_move_pages. + // Common errors: EFAULT (-14), EINVAL (-22), EPERM (-1), ESRCH (-3), ENOMEM (-12) + return -errno; } - return page_node; - } +} // Verifies if the memory at memory_address is on the same NUMA node as the current CPU. // variable_name is for logging/debugging by the caller if verification fails. diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 9f14fca7..07b512f6 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -63,10 +63,7 @@ class QueryCoordinator { // Thread-local buffers for batched queries float* batch_queries = nullptr; // batched query buffer (NUMA-allocated) - float* batch_distances = nullptr; // scratch space for distances - int64_t* batch_ids = nullptr; // scratch space for ids size_t batch_q_capacity = 0; // number of floats in batch_queries - size_t batch_res_capacity = 0; // number of (k×Q) slots in distances & ids float* blas_ip_block = nullptr; // capacity: db_blas_bs * max_Q size_t blas_ip_capacity = 0; // # floats diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 552de192..3cdc4c67 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -70,8 +70,13 @@ void QueryCoordinator::allocate_core_resources(int core_idx, // --- ZERO‐INITIALIZE our batched‐query buffers so we never free garbage pointers --- CR.batch_queries = nullptr; - CR.batch_distances = nullptr; - CR.batch_ids = nullptr; + + CR.blas_ip_block = nullptr; + CR.blas_ip_capacity = 0; + CR.blas_norms_x = nullptr; + CR.blas_norms_x_cap = 0; + CR.blas_norms_y = nullptr; + CR.blas_norms_y_cap = 0; int numa_node = 0; #ifdef QUAKE_USE_NUMA @@ -302,15 +307,6 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, res.batch_q_capacity = max_q; } - size_t max_r = size_t(queries_req) * K; - if (res.batch_res_capacity < max_r) { - quake_free(res.batch_distances, res.batch_res_capacity * sizeof(float)); - quake_free(res.batch_ids, res.batch_res_capacity * sizeof(int64_t)); - res.batch_distances = static_cast (quake_alloc(max_r * sizeof(float), node)); - res.batch_ids = static_cast(quake_alloc(max_r * sizeof(int64_t), node)); - res.batch_res_capacity = max_r; - } - // reset only the first 'chunk' TopK buffers for (int64_t i = 0; i < Q; ++i) { auto &buf = res.topk_buffer_pool[i]; @@ -354,8 +350,6 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, ok = ok && verify_numa_locality(codes, "codes"); ok = ok && verify_numa_locality(ids, "ids"); ok = ok && verify_numa_locality(res.batch_queries, "batch_queries"); - // ok = ok && verify_numa_locality(res.batch_distances, "batch_distances"); - // ok = ok && verify_numa_locality(res.batch_ids, "batch_ids"); ok = ok && verify_numa_locality(res.blas_ip_block, "blas_ip_block"); ok = ok && verify_numa_locality(res.blas_norms_x, "blas_norms_x"); ok = ok && verify_numa_locality(res.blas_norms_y, "blas_norms_y"); From a4846ad6ce3168f9c73b191fe8bbbd4f5cb52a89 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 22:40:26 -0500 Subject: [PATCH 258/323] verify numa --- src/cpp/src/query_coordinator.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 3cdc4c67..4735bbf6 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -19,6 +19,8 @@ static void ensure_blas_buffers(QueryCoordinator::CoreResources& res, { const size_t ip_need = db_bs * max_q; if (res.blas_ip_capacity < ip_need) { + std::cerr << "Reallocating BLAS buffers: " << res.blas_ip_capacity + << " -> " << ip_need << std::endl; quake_free(res.blas_ip_block, res.blas_ip_capacity * sizeof(float)); res.blas_ip_block = static_cast(quake_alloc(ip_need * sizeof(float), node)); res.blas_ip_capacity = ip_need; From 2e0919d28aa7463a547354fcff03b1c19b174939 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 22:49:09 -0500 Subject: [PATCH 259/323] verify numa --- src/cpp/src/query_coordinator.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 4735bbf6..c5416978 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -24,16 +24,22 @@ static void ensure_blas_buffers(QueryCoordinator::CoreResources& res, quake_free(res.blas_ip_block, res.blas_ip_capacity * sizeof(float)); res.blas_ip_block = static_cast(quake_alloc(ip_need * sizeof(float), node)); res.blas_ip_capacity = ip_need; + // zero out the new memory + memset(res.blas_ip_block, 0, ip_need * sizeof(float)); } if (res.blas_norms_x_cap < max_q) { quake_free(res.blas_norms_x, res.blas_norms_x_cap * sizeof(float)); res.blas_norms_x = static_cast(quake_alloc(max_q * sizeof(float), node)); res.blas_norms_x_cap = max_q; + // zero out the new memory + memset(res.blas_norms_x, 0, max_q * sizeof(float)); } if (res.blas_norms_y_cap < db_bs) { quake_free(res.blas_norms_y, res.blas_norms_y_cap * sizeof(float)); res.blas_norms_y = static_cast(quake_alloc(db_bs * sizeof(float), node)); res.blas_norms_y_cap = db_bs; + // zero out the new memory + memset(res.blas_norms_y, 0, db_bs * sizeof(float)); } } From 53c7f86d8ca4b217dc898637c6d659e908d0f531 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 22:51:04 -0500 Subject: [PATCH 260/323] verify numa --- src/cpp/src/query_coordinator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index c5416978..c450233e 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -21,21 +21,21 @@ static void ensure_blas_buffers(QueryCoordinator::CoreResources& res, if (res.blas_ip_capacity < ip_need) { std::cerr << "Reallocating BLAS buffers: " << res.blas_ip_capacity << " -> " << ip_need << std::endl; - quake_free(res.blas_ip_block, res.blas_ip_capacity * sizeof(float)); + if (res.blas_ip_block) quake_free(res.blas_ip_block, res.blas_ip_capacity * sizeof(float)); res.blas_ip_block = static_cast(quake_alloc(ip_need * sizeof(float), node)); res.blas_ip_capacity = ip_need; // zero out the new memory memset(res.blas_ip_block, 0, ip_need * sizeof(float)); } if (res.blas_norms_x_cap < max_q) { - quake_free(res.blas_norms_x, res.blas_norms_x_cap * sizeof(float)); + if (res.blas_norms_x) quake_free(res.blas_norms_x, res.blas_norms_x_cap * sizeof(float)); res.blas_norms_x = static_cast(quake_alloc(max_q * sizeof(float), node)); res.blas_norms_x_cap = max_q; // zero out the new memory memset(res.blas_norms_x, 0, max_q * sizeof(float)); } if (res.blas_norms_y_cap < db_bs) { - quake_free(res.blas_norms_y, res.blas_norms_y_cap * sizeof(float)); + if (res.blas_norms_y) quake_free(res.blas_norms_y, res.blas_norms_y_cap * sizeof(float)); res.blas_norms_y = static_cast(quake_alloc(db_bs * sizeof(float), node)); res.blas_norms_y_cap = db_bs; // zero out the new memory From 3518b7b32e85f6d1ac52cc3d1769d598c05dda4d Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 22:52:45 -0500 Subject: [PATCH 261/323] verify numa --- src/cpp/include/parallel.h | 2 ++ src/cpp/src/query_coordinator.cpp | 6 ------ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/cpp/include/parallel.h b/src/cpp/include/parallel.h index 4158ce83..68c90199 100644 --- a/src/cpp/include/parallel.h +++ b/src/cpp/include/parallel.h @@ -49,6 +49,7 @@ inline bool set_thread_affinity(int core_id) { if (ptr == nullptr || ptr == MAP_FAILED) { throw std::bad_alloc(); } + memset(ptr, 0, sz); // Initialize memory to zero return ptr; } @@ -162,6 +163,7 @@ inline void* quake_alloc(size_t sz, int /*node*/) { if (!ptr) { throw std::bad_alloc(); } + memset(ptr, 0, sz); // Initialize memory to zero return ptr; } diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index c450233e..12cff364 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -24,22 +24,16 @@ static void ensure_blas_buffers(QueryCoordinator::CoreResources& res, if (res.blas_ip_block) quake_free(res.blas_ip_block, res.blas_ip_capacity * sizeof(float)); res.blas_ip_block = static_cast(quake_alloc(ip_need * sizeof(float), node)); res.blas_ip_capacity = ip_need; - // zero out the new memory - memset(res.blas_ip_block, 0, ip_need * sizeof(float)); } if (res.blas_norms_x_cap < max_q) { if (res.blas_norms_x) quake_free(res.blas_norms_x, res.blas_norms_x_cap * sizeof(float)); res.blas_norms_x = static_cast(quake_alloc(max_q * sizeof(float), node)); res.blas_norms_x_cap = max_q; - // zero out the new memory - memset(res.blas_norms_x, 0, max_q * sizeof(float)); } if (res.blas_norms_y_cap < db_bs) { if (res.blas_norms_y) quake_free(res.blas_norms_y, res.blas_norms_y_cap * sizeof(float)); res.blas_norms_y = static_cast(quake_alloc(db_bs * sizeof(float), node)); res.blas_norms_y_cap = db_bs; - // zero out the new memory - memset(res.blas_norms_y, 0, db_bs * sizeof(float)); } } From 3330a6a523681bae31de0bb3cc8bf0929ceaaf3a Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 23:02:05 -0500 Subject: [PATCH 262/323] verify numa --- src/cpp/include/list_scanning.h | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 3095be71..0fb5a6dc 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -538,22 +538,26 @@ inline void l2_blas( faiss::fvec_norms_L2sqr(norms_y, y + j0 * d, d, db_chunk); // use torch matmul + Tensor x_tensor = torch::from_blob((void*) x + i0 * d, {q_chunk, d}, torch::kFloat32); + Tensor y_tensor = torch::from_blob((void*) y + j0 * d, {db_chunk, d}, torch::kFloat32); + Tensor ip_tensor = torch::from_blob(ip_block, {q_chunk, db_chunk}, torch::kFloat32); + torch::matmul_out(ip_tensor, x_tensor, y_tensor.transpose(0, 1)); /* SGEMM */ - { - const float one = 1.f; - float zero = 0.f; - FINTEGER nyi = FINTEGER(db_chunk); - FINTEGER nxi = FINTEGER(q_chunk); - FINTEGER di = FINTEGER(d); - sgemm_("Transpose","Not transpose", - &nyi,&nxi,&di, - &one, - y + j0 * d, &di, - x + i0 * d, &di, - &zero, - ip_block, &nyi); - } + // { + // const float one = 1.f; + // float zero = 0.f; + // FINTEGER nyi = FINTEGER(db_chunk); + // FINTEGER nxi = FINTEGER(q_chunk); + // FINTEGER di = FINTEGER(d); + // sgemm_("Transpose","Not transpose", + // &nyi,&nxi,&di, + // &one, + // y + j0 * d, &di, + // x + i0 * d, &di, + // &zero, + // ip_block, &nyi); + // } /* IP → L2² */ if (k > 1) { From 44d63706adb22907fd85ef99baf750181c4a4a32 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 23:02:31 -0500 Subject: [PATCH 263/323] verify numa --- src/cpp/src/query_coordinator.cpp | 45 +++++++++++-------------------- 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 12cff364..393ba07d 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -347,37 +347,22 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, } // check that things are on the proper NUMA node - bool ok = true; - ok = ok && verify_numa_locality(qptr, "qptr"); - ok = ok && verify_numa_locality(codes, "codes"); - ok = ok && verify_numa_locality(ids, "ids"); - ok = ok && verify_numa_locality(res.batch_queries, "batch_queries"); - ok = ok && verify_numa_locality(res.blas_ip_block, "blas_ip_block"); - ok = ok && verify_numa_locality(res.blas_norms_x, "blas_norms_x"); - ok = ok && verify_numa_locality(res.blas_norms_y, "blas_norms_y"); - for (int64_t i = 0; i < Q; ++i) { - ok = ok && verify_numa_locality(res.topk_buffer_pool[i]->ord_, "ord_"); - ok = ok && verify_numa_locality(res.topk_buffer_pool[i]->vals_, "vals_"); - ok = ok && verify_numa_locality(res.topk_buffer_pool[i]->ids_, "ids_"); - } - if (!ok) { - std::cerr << "[QueryCoordinator::handle_batched_job] NUMA locality check failed.\n"; - // throw std::runtime_error("NUMA locality check failed"); - } - - // verify_numa_locality(qptr, "qptr"); - // verify_numa_locality(codes, "codes"); - // verify_numa_locality(ids, "ids"); - // verify_numa_locality(res.batch_distances, "batch_distances"); - // verify_numa_locality(res.batch_ids, "batch_ids"); - // verify_numa_locality(res.blas_ip_block, "blas_ip_block"); - // verify_numa_locality(res.blas_norms_x, "blas_norms_x"); - // verify_numa_locality(res.blas_norms_y, "blas_norms_y"); - // + // bool ok = true; + // ok = ok && verify_numa_locality(qptr, "qptr"); + // ok = ok && verify_numa_locality(codes, "codes"); + // ok = ok && verify_numa_locality(ids, "ids"); + // ok = ok && verify_numa_locality(res.batch_queries, "batch_queries"); + // ok = ok && verify_numa_locality(res.blas_ip_block, "blas_ip_block"); + // ok = ok && verify_numa_locality(res.blas_norms_x, "blas_norms_x"); + // ok = ok && verify_numa_locality(res.blas_norms_y, "blas_norms_y"); // for (int64_t i = 0; i < Q; ++i) { - // verify_numa_locality(res.topk_buffer_pool[i]->ord_, "ord_"); - // verify_numa_locality(res.topk_buffer_pool[i]->vals_, "vals_"); - // verify_numa_locality(res.topk_buffer_pool[i]->ids_, "ids_"); + // ok = ok && verify_numa_locality(res.topk_buffer_pool[i]->ord_, "ord_"); + // ok = ok && verify_numa_locality(res.topk_buffer_pool[i]->vals_, "vals_"); + // ok = ok && verify_numa_locality(res.topk_buffer_pool[i]->ids_, "ids_"); + // } + // if (!ok) { + // std::cerr << "[QueryCoordinator::handle_batched_job] NUMA locality check failed.\n"; + // // throw std::runtime_error("NUMA locality check failed"); // } // run the scan on this chunk From 16d0f2f68a82d006f0f7cc879bfe75e82cb38a08 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 23:11:26 -0500 Subject: [PATCH 264/323] verify numa --- src/cpp/src/query_coordinator.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 393ba07d..81863f84 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -268,6 +268,7 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, NUMAResources &nr) { auto start = std::chrono::high_resolution_clock::now(); + auto s1 = std::chrono::high_resolution_clock::now(); // Total queries, Top-K, dimension, NUMA node int64_t Q = job.num_queries; int K = job.k; @@ -316,6 +317,8 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, buf->reset(); } + auto s2 = std::chrono::high_resolution_clock::now(); + // // init only the first chunk*K slots in scratch // float init_val = (metric_ == faiss::METRIC_INNER_PRODUCT) // ? -std::numeric_limits::infinity() @@ -346,6 +349,7 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, pivots[i] = &query_dist_pivots_[qid]; } + auto s3 = std::chrono::high_resolution_clock::now(); // check that things are on the proper NUMA node // bool ok = true; // ok = ok && verify_numa_locality(qptr, "qptr"); @@ -378,6 +382,8 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, BLAS_DB_BS, pivots); + auto s4 = std::chrono::high_resolution_clock::now(); + auto end = std::chrono::high_resolution_clock::now(); res.scan_time_ns += std::chrono::duration_cast(end - start).count(); @@ -399,7 +405,23 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, results_batch.size() ); end = std::chrono::high_resolution_clock::now(); + auto s5 = std::chrono::high_resolution_clock::now(); res.enqueue_time_ns += std::chrono::duration_cast(end - start).count(); + + // print out debug timing info s1, ... s5 + std::cout << "QueryCoordinator::handle_batched_job: " + << "wait: " << res.wait_time_ns + << ", preamble: " << res.process_preamble_time_ns + << ", process: " << res.process_time_ns + << ", scan: " << res.scan_time_ns + << ", enqueue: " << res.enqueue_time_ns + << ", job: " << res.job_time_ns + << ", s1: " << std::chrono::duration_cast(s1 - start).count() + << ", s2: " << std::chrono::duration_cast(s2 - s1).count() + << ", s3: " << std::chrono::duration_cast(s3 - s2).count() + << ", s4: " << std::chrono::duration_cast(s4 - s3).count() + << ", s5: " << std::chrono::duration_cast(end - s4).count() + << std::endl; } void QueryCoordinator::init_global_buffers(int64_t nQ, From 8282f0074c4ab935575ae1b2d90b040a665970b3 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 23:14:06 -0500 Subject: [PATCH 265/323] verify numa --- src/cpp/src/query_coordinator.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 81863f84..6d1f0977 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -410,17 +410,17 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, // print out debug timing info s1, ... s5 std::cout << "QueryCoordinator::handle_batched_job: " - << "wait: " << res.wait_time_ns - << ", preamble: " << res.process_preamble_time_ns - << ", process: " << res.process_time_ns - << ", scan: " << res.scan_time_ns - << ", enqueue: " << res.enqueue_time_ns - << ", job: " << res.job_time_ns - << ", s1: " << std::chrono::duration_cast(s1 - start).count() - << ", s2: " << std::chrono::duration_cast(s2 - s1).count() - << ", s3: " << std::chrono::duration_cast(s3 - s2).count() - << ", s4: " << std::chrono::duration_cast(s4 - s3).count() - << ", s5: " << std::chrono::duration_cast(end - s4).count() + << "job_id: " << job.job_id + << ", core_id: " << res.core_id + << ", num_queries: " << job.num_queries + << ", partition_id: " << job.partition_id + << ", k: " << job.k + << ", rank: " << job.rank + << ", numa_node: " << node + << ", preamble: " << std::chrono::duration_cast(s2 - s1).count() + << ", query copy: " << std::chrono::duration_cast(s3 - s2).count() + << ", scan: " << std::chrono::duration_cast(s4 - s3).count() + << ", enqueue: " << std::chrono::duration_cast(end - s4).count() << std::endl; } From 9efd3007e50acc281e8ba168af8e68379adb22bc Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 23:19:59 -0500 Subject: [PATCH 266/323] verify numa --- src/cpp/include/list_scanning.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 0fb5a6dc..41af1de8 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -517,6 +517,16 @@ inline void l2_blas( float* __restrict norms_y, vector*> pivot) // db_blas_bs { + + auto t1 = std::chrono::high_resolution_clock::now(); + auto t2 = std::chrono::high_resolution_clock::now(); + + int64_t x_norm_ns = 0; + int64_t y_norm_ns = 0; + int64_t ip_ns = 0; + int64_t l2_ns = 0; + int64_t topk_ns = 0; + if (nx == 0 || ny == 0) return; constexpr size_t bs_x = 256; @@ -528,20 +538,29 @@ inline void l2_blas( const size_t q_chunk = i1 - i0; /* ‖x‖² for this query block */ + t1 = std::chrono::high_resolution_clock::now(); faiss::fvec_norms_L2sqr(norms_x, x + i0 * d, d, q_chunk); + t2 = std::chrono::high_resolution_clock::now(); + x_norm_ns += std::chrono::duration_cast(t2 - t1).count(); for (size_t j0 = 0; j0 < ny; j0 += bs_y) { const size_t j1 = std::min(j0 + bs_y, ny); const size_t db_chunk = j1 - j0; /* ‖y‖² for this database block */ + t1 = std::chrono::high_resolution_clock::now(); faiss::fvec_norms_L2sqr(norms_y, y + j0 * d, d, db_chunk); + t2 = std::chrono::high_resolution_clock::now(); + y_norm_ns += std::chrono::duration_cast(t2 - t1).count(); // use torch matmul + t1 = std::chrono::high_resolution_clock::now(); Tensor x_tensor = torch::from_blob((void*) x + i0 * d, {q_chunk, d}, torch::kFloat32); Tensor y_tensor = torch::from_blob((void*) y + j0 * d, {db_chunk, d}, torch::kFloat32); Tensor ip_tensor = torch::from_blob(ip_block, {q_chunk, db_chunk}, torch::kFloat32); torch::matmul_out(ip_tensor, x_tensor, y_tensor.transpose(0, 1)); + t2 = std::chrono::high_resolution_clock::now(); + ip_ns += std::chrono::duration_cast(t2 - t1).count(); /* SGEMM */ // { @@ -560,6 +579,7 @@ inline void l2_blas( // } /* IP → L2² */ + t1 = std::chrono::high_resolution_clock::now(); if (k > 1) { for (int64_t qi = 0; qi < static_cast(q_chunk); ++qi) { float* line_ptr = ip_block + qi * db_chunk; // Pointer to current column in ip_block @@ -602,8 +622,14 @@ inline void l2_blas( topk_buffers[qi]->add(best_dist, best_id); } } + t2 = std::chrono::high_resolution_clock::now(); + l2_ns += std::chrono::duration_cast(t2 - t1).count(); } } + std::cout << " x_norm_ns: " << x_norm_ns << std::endl; + std::cout << " y_norm_ns: " << y_norm_ns << std::endl; + std::cout << " ip_ns: " << ip_ns << std::endl; + std::cout << " l2_ns: " << l2_ns << std::endl; } inline void batched_scan_list(const float *query_vecs, From 8f15d8009018a6f2c4db0b4e77012e017a7bc955 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 23:25:48 -0500 Subject: [PATCH 267/323] verify numa --- src/cpp/include/list_scanning.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 41af1de8..54e14cf3 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -578,6 +578,15 @@ inline void l2_blas( // ip_block, &nyi); // } + // for (int64_t qi = 0; qi < (int64_t)q_chunk; ++qi) { + // float* line = ip_block + qi * db_chunk; + // const float xn = norms_x[qi]; + // for (size_t pj = 0; pj < db_chunk; ++pj, ++line) { + // float d2 = xn + norms_y[pj] - 2.f * (*line); + // *line = (d2 < 0.f || !std::isfinite(d2)) ? 0.f : d2; + // } + // } + /* IP → L2² */ t1 = std::chrono::high_resolution_clock::now(); if (k > 1) { @@ -612,14 +621,14 @@ inline void l2_blas( int64_t best_id = -1; for (size_t pj = 0; pj < db_chunk; ++pj) { - *line_ptr = std::sqrt(std::fma(-2.f, *line_ptr, current_norm_x + norms_y[pj])); + *line_ptr = current_norm_x + norms_y[pj] - 2.f * (*line_ptr); if (*line_ptr < best_dist) { best_dist = *line_ptr; best_id = list_ids_ptr[j0 + pj]; } line_ptr++; // Move to the next element in the column } - topk_buffers[qi]->add(best_dist, best_id); + topk_buffers[qi]->add(sqrt(best_dist), best_id); } } t2 = std::chrono::high_resolution_clock::now(); From ac3650ce01dc8c2f5e350f9cc6f6790361d03a76 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 23:28:56 -0500 Subject: [PATCH 268/323] verify numa --- src/cpp/include/list_scanning.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 54e14cf3..6ee89ba5 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -594,17 +594,18 @@ inline void l2_blas( float* line_ptr = ip_block + qi * db_chunk; // Pointer to current column in ip_block const float current_norm_x = norms_x[qi]; for (size_t pj = 0; pj < db_chunk; ++pj) { - *line_ptr = std::sqrt(std::fma(-2.f, *line_ptr, current_norm_x + norms_y[pj])); + *line_ptr = current_norm_x + norms_y[pj] - 2.f * (*line_ptr); line_ptr++; // Move to the next element in the column } // collect distances closer than pivot if (pivot.size() > 0) { float curr_pivot = pivot[qi]->load(std::memory_order_relaxed); + curr_pivot = curr_pivot * curr_pivot; // Convert to squared distance line_ptr = ip_block + qi * db_chunk; // Reset line_ptr to the start of the current column for (size_t pj = 0; pj < db_chunk; ++pj) { if (*line_ptr < curr_pivot) { - topk_buffers[qi]->add(*line_ptr, list_ids_ptr[j0 + pj]); + topk_buffers[qi]->add(std::sqrt(*line_ptr), list_ids_ptr[j0 + pj]); } line_ptr++; // Move to the next element in the column } From 89af90c76bcdf8bfe48b9c7be22a056cef0b0faf Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 23:32:45 -0500 Subject: [PATCH 269/323] verify numa --- src/cpp/include/list_scanning.h | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 6ee89ba5..9b2272a5 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -517,16 +517,6 @@ inline void l2_blas( float* __restrict norms_y, vector*> pivot) // db_blas_bs { - - auto t1 = std::chrono::high_resolution_clock::now(); - auto t2 = std::chrono::high_resolution_clock::now(); - - int64_t x_norm_ns = 0; - int64_t y_norm_ns = 0; - int64_t ip_ns = 0; - int64_t l2_ns = 0; - int64_t topk_ns = 0; - if (nx == 0 || ny == 0) return; constexpr size_t bs_x = 256; @@ -538,29 +528,20 @@ inline void l2_blas( const size_t q_chunk = i1 - i0; /* ‖x‖² for this query block */ - t1 = std::chrono::high_resolution_clock::now(); faiss::fvec_norms_L2sqr(norms_x, x + i0 * d, d, q_chunk); - t2 = std::chrono::high_resolution_clock::now(); - x_norm_ns += std::chrono::duration_cast(t2 - t1).count(); for (size_t j0 = 0; j0 < ny; j0 += bs_y) { const size_t j1 = std::min(j0 + bs_y, ny); const size_t db_chunk = j1 - j0; /* ‖y‖² for this database block */ - t1 = std::chrono::high_resolution_clock::now(); faiss::fvec_norms_L2sqr(norms_y, y + j0 * d, d, db_chunk); - t2 = std::chrono::high_resolution_clock::now(); - y_norm_ns += std::chrono::duration_cast(t2 - t1).count(); // use torch matmul - t1 = std::chrono::high_resolution_clock::now(); Tensor x_tensor = torch::from_blob((void*) x + i0 * d, {q_chunk, d}, torch::kFloat32); Tensor y_tensor = torch::from_blob((void*) y + j0 * d, {db_chunk, d}, torch::kFloat32); Tensor ip_tensor = torch::from_blob(ip_block, {q_chunk, db_chunk}, torch::kFloat32); torch::matmul_out(ip_tensor, x_tensor, y_tensor.transpose(0, 1)); - t2 = std::chrono::high_resolution_clock::now(); - ip_ns += std::chrono::duration_cast(t2 - t1).count(); /* SGEMM */ // { @@ -588,7 +569,6 @@ inline void l2_blas( // } /* IP → L2² */ - t1 = std::chrono::high_resolution_clock::now(); if (k > 1) { for (int64_t qi = 0; qi < static_cast(q_chunk); ++qi) { float* line_ptr = ip_block + qi * db_chunk; // Pointer to current column in ip_block @@ -632,14 +612,8 @@ inline void l2_blas( topk_buffers[qi]->add(sqrt(best_dist), best_id); } } - t2 = std::chrono::high_resolution_clock::now(); - l2_ns += std::chrono::duration_cast(t2 - t1).count(); } } - std::cout << " x_norm_ns: " << x_norm_ns << std::endl; - std::cout << " y_norm_ns: " << y_norm_ns << std::endl; - std::cout << " ip_ns: " << ip_ns << std::endl; - std::cout << " l2_ns: " << l2_ns << std::endl; } inline void batched_scan_list(const float *query_vecs, From bdda82ac7891a6013618202ced4ccf7a6b0dbde7 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 23:34:43 -0500 Subject: [PATCH 270/323] verify numa --- src/cpp/include/list_scanning.h | 6 +++--- src/cpp/src/query_coordinator.cpp | 28 ++++++++++++++-------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 9b2272a5..d0a89344 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -538,9 +538,9 @@ inline void l2_blas( faiss::fvec_norms_L2sqr(norms_y, y + j0 * d, d, db_chunk); // use torch matmul - Tensor x_tensor = torch::from_blob((void*) x + i0 * d, {q_chunk, d}, torch::kFloat32); - Tensor y_tensor = torch::from_blob((void*) y + j0 * d, {db_chunk, d}, torch::kFloat32); - Tensor ip_tensor = torch::from_blob(ip_block, {q_chunk, db_chunk}, torch::kFloat32); + Tensor x_tensor = torch::from_blob((void*) x + i0 * d, {(int64_t) q_chunk, (int64_t) d}, torch::kFloat32); + Tensor y_tensor = torch::from_blob((void*) y + j0 * d, {(int64_t) db_chunk, (int64_t) d}, torch::kFloat32); + Tensor ip_tensor = torch::from_blob(ip_block, {(int64_t) q_chunk, (int64_t) db_chunk}, torch::kFloat32); torch::matmul_out(ip_tensor, x_tensor, y_tensor.transpose(0, 1)); /* SGEMM */ diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 6d1f0977..896842b3 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -408,20 +408,20 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, auto s5 = std::chrono::high_resolution_clock::now(); res.enqueue_time_ns += std::chrono::duration_cast(end - start).count(); - // print out debug timing info s1, ... s5 - std::cout << "QueryCoordinator::handle_batched_job: " - << "job_id: " << job.job_id - << ", core_id: " << res.core_id - << ", num_queries: " << job.num_queries - << ", partition_id: " << job.partition_id - << ", k: " << job.k - << ", rank: " << job.rank - << ", numa_node: " << node - << ", preamble: " << std::chrono::duration_cast(s2 - s1).count() - << ", query copy: " << std::chrono::duration_cast(s3 - s2).count() - << ", scan: " << std::chrono::duration_cast(s4 - s3).count() - << ", enqueue: " << std::chrono::duration_cast(end - s4).count() - << std::endl; + // // print out debug timing info s1, ... s5 + // std::cout << "QueryCoordinator::handle_batched_job: " + // << "job_id: " << job.job_id + // << ", core_id: " << res.core_id + // << ", num_queries: " << job.num_queries + // << ", partition_id: " << job.partition_id + // << ", k: " << job.k + // << ", rank: " << job.rank + // << ", numa_node: " << node + // << ", preamble: " << std::chrono::duration_cast(s2 - s1).count() + // << ", query copy: " << std::chrono::duration_cast(s3 - s2).count() + // << ", scan: " << std::chrono::duration_cast(s4 - s3).count() + // << ", enqueue: " << std::chrono::duration_cast(end - s4).count() + // << std::endl; } void QueryCoordinator::init_global_buffers(int64_t nQ, From e5ea147ee9d2603f5286527f46c1876125662d45 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 24 May 2025 23:42:26 -0500 Subject: [PATCH 271/323] verify numa --- src/cpp/include/list_scanning.h | 36 ++++++++++++++++----------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index d0a89344..05998e76 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -538,26 +538,26 @@ inline void l2_blas( faiss::fvec_norms_L2sqr(norms_y, y + j0 * d, d, db_chunk); // use torch matmul - Tensor x_tensor = torch::from_blob((void*) x + i0 * d, {(int64_t) q_chunk, (int64_t) d}, torch::kFloat32); - Tensor y_tensor = torch::from_blob((void*) y + j0 * d, {(int64_t) db_chunk, (int64_t) d}, torch::kFloat32); - Tensor ip_tensor = torch::from_blob(ip_block, {(int64_t) q_chunk, (int64_t) db_chunk}, torch::kFloat32); - torch::matmul_out(ip_tensor, x_tensor, y_tensor.transpose(0, 1)); + // Tensor x_tensor = torch::from_blob((void*) (x + i0 * d), {(int64_t) q_chunk, (int64_t) d}, torch::kFloat32); + // Tensor y_tensor = torch::from_blob((void*) (y + j0 * d), {(int64_t) db_chunk, (int64_t) d}, torch::kFloat32); + // Tensor ip_tensor = torch::from_blob(ip_block, {(int64_t) q_chunk, (int64_t) db_chunk}, torch::kFloat32); + // torch::matmul_out(ip_tensor, x_tensor, y_tensor.transpose(0, 1)); /* SGEMM */ - // { - // const float one = 1.f; - // float zero = 0.f; - // FINTEGER nyi = FINTEGER(db_chunk); - // FINTEGER nxi = FINTEGER(q_chunk); - // FINTEGER di = FINTEGER(d); - // sgemm_("Transpose","Not transpose", - // &nyi,&nxi,&di, - // &one, - // y + j0 * d, &di, - // x + i0 * d, &di, - // &zero, - // ip_block, &nyi); - // } + { + const float one = 1.f; + float zero = 0.f; + FINTEGER nyi = FINTEGER(db_chunk); + FINTEGER nxi = FINTEGER(q_chunk); + FINTEGER di = FINTEGER(d); + sgemm_("Transpose","Not transpose", + &nyi,&nxi,&di, + &one, + y + j0 * d, &di, + x + i0 * d, &di, + &zero, + ip_block, &nyi); + } // for (int64_t qi = 0; qi < (int64_t)q_chunk; ++qi) { // float* line = ip_block + qi * db_chunk; From b66c476196f967d37fa18e8af418d5e001a291ef Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 25 May 2025 01:31:13 -0500 Subject: [PATCH 272/323] use reservoir handler --- src/cpp/include/query_coordinator.h | 4 ++-- src/cpp/src/query_coordinator.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 07b512f6..d27ac7a5 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -107,8 +107,8 @@ class QueryCoordinator { vector worker_threads_; ///< Container for worker threads. vector worker_job_counter_; ///< Job counters for each worker. - shared_ptr>> global_min_heaps_; ///< Global aggregator buffers. - shared_ptr>> global_max_heaps_; ///< Global aggregator buffers. + shared_ptr>> global_min_heaps_; ///< Global aggregator buffers. + shared_ptr>> global_max_heaps_; ///< Global aggregator buffers. std::mutex global_mutex_; ///< Mutex for global synchronization. std::condition_variable global_cv_; ///< Condition variable for thread coordination. diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 896842b3..98e880e0 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -444,12 +444,12 @@ void QueryCoordinator::init_global_buffers(int64_t nQ, std::fill_n(vals, nQ * K, max_val); if (metric_ == faiss::METRIC_INNER_PRODUCT) { - global_max_heaps_ = make_shared>>( + global_max_heaps_ = make_shared>>( nQ, vals, ids, K); } else { std::fill_n(vals, nQ * K, std::numeric_limits::infinity()); - global_min_heaps_ = make_shared>>( + global_min_heaps_ = make_shared>>( nQ, vals, ids, K); } @@ -647,7 +647,7 @@ void QueryCoordinator::drain_and_apply_aps(Tensor x, vector per_query_result_count(nQ, 0); if (metric_ == faiss::METRIC_INNER_PRODUCT) { - vector>::SingleResultHandler> + vector>::SingleResultHandler> handlers; for (int64_t q = 0; q < nQ; ++q) { handlers.emplace_back(*global_max_heaps_); @@ -683,7 +683,7 @@ void QueryCoordinator::drain_and_apply_aps(Tensor x, handlers[q].end(); } } else { - vector>::SingleResultHandler> + vector>::SingleResultHandler> handlers; handlers.reserve(nQ); for (int64_t q = 0; q < nQ; ++q) { From 0fb32355b4178a99283b6945e89d440e048e033b Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 25 May 2025 15:02:59 -0500 Subject: [PATCH 273/323] add merge threads --- src/cpp/include/list_scanning.h | 10 +- src/cpp/include/query_coordinator.h | 28 ++- src/cpp/src/query_coordinator.cpp | 281 ++++++++++++++-------------- 3 files changed, 165 insertions(+), 154 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 05998e76..925943ca 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -403,8 +403,15 @@ inline void scan_list(const float *query_vec, int d, TopkBuffer &buffer, faiss::MetricType metric, - float pivot) { + float pivot = -1) { // Dispatch based on metric type and whether list_ids is provided. + + if (pivot == 0) { + pivot = metric == faiss::METRIC_INNER_PRODUCT + ? -std::numeric_limits::infinity() + : std::numeric_limits::infinity(); + } + if (metric == faiss::METRIC_INNER_PRODUCT) { if (list_ids == nullptr) scan_list_no_ids_inner_product(query_vec, list_vecs, list_size, d, buffer, pivot); @@ -634,7 +641,6 @@ inline void batched_scan_list(const float *query_vecs, return; } - // Ensure k does not exceed list_size int k = topk_buffers[0]->k(); int k_max = std::min(k, list_size); diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index d27ac7a5..3c9c6c69 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -97,23 +97,28 @@ class QueryCoordinator { std::vector indices; }; + struct MergeResources { + moodycamel::BlockingConcurrentQueue queue; + std::vector handlers; // points to HandlerIP or HandlerL2 + }; + vector core_resources_; ///< Per‑core resources for worker threads. vector numa_resources_; - moodycamel::BlockingConcurrentQueue result_queue_; -// moodycamel::ConcurrentQueue result_queue_; + vector merge_res_; // size == num_merge_workers_ bool workers_initialized_ = false; ///< Flag indicating if worker threads are initialized. int num_workers_; ///< Total number of worker threads. + int num_merge_workers_; ///< Number of merge worker threads. vector worker_threads_; ///< Container for worker threads. + vector merge_threads_; ///< Container for merge threads. vector worker_job_counter_; ///< Job counters for each worker. - shared_ptr>> global_min_heaps_; ///< Global aggregator buffers. - shared_ptr>> global_max_heaps_; ///< Global aggregator buffers. + shared_ptr>> global_min_heaps_; ///< Global aggregator buffers. + shared_ptr>> global_max_heaps_; ///< Global aggregator buffers. std::mutex global_mutex_; ///< Mutex for global synchronization. std::condition_variable global_cv_; ///< Condition variable for thread coordination. std::atomic stop_workers_; ///< Flag to signal workers to terminate. - std::atomic jobs_in_flight_; ///< Number of jobs in flight. bool debug_ = false; ///< Debug mode flag. std::vector job_buffer_; @@ -122,6 +127,7 @@ class QueryCoordinator { vector>> job_flags_; ///< Flags to track job completion std::atomic job_pull_time_ns = 0; ///< Time spent pulling jobs from the queue. std::atomic job_process_time_ns = 0; ///< Time spent processing jobs. + std::atomic total_left_; /** * @brief Constructs a QueryCoordinator. @@ -137,7 +143,8 @@ class QueryCoordinator { shared_ptr maintenance_policy, MetricType metric, int num_workers=0, - bool use_numa=false); + bool use_numa=false, + int num_merge_workers=2); /** * @brief Destructor for QueryCoordinator. @@ -200,7 +207,7 @@ class QueryCoordinator { * * @param num_workers Number of worker threads to initialize. */ - void initialize_workers(int num_workers, bool use_numa=false); + void initialize_workers(int num_workers, int num_merge_workers=1, bool use_numa=false); /** * @brief Shuts down all worker threads. @@ -218,6 +225,8 @@ class QueryCoordinator { */ void partition_scan_worker_fn(int worker_id); + void merge_worker_fn(int merge_worker_id); + /** * @brief Worker thread function to perform partition scanning. * @@ -243,7 +252,6 @@ class QueryCoordinator { */ void allocate_core_resources(int core_idx, int num_queries, int k, int d); - int64_t pop_scan_job(CoreResources &res); void process_scan_job(ScanJob job, CoreResources &res); // handles the non‐batched branch @@ -267,11 +275,13 @@ class QueryCoordinator { Tensor partition_ids, shared_ptr params); + void enqueue_result_job(ResultJob job); + void drain_and_apply_aps(Tensor x, Tensor partition_ids, bool use_aps, float recall_target, - float aps_flush_period_us, + int aps_flush_period_us, shared_ptr timing); std::shared_ptr diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 98e880e0..ed5d9465 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -43,16 +43,18 @@ QueryCoordinator::QueryCoordinator(shared_ptr parent, shared_ptr maintenance_policy, MetricType metric, int num_workers, - bool use_numa) + bool use_numa, + int num_merge_workers) : parent_(parent), partition_manager_(partition_manager), maintenance_policy_(maintenance_policy), metric_(metric), num_workers_(num_workers), + num_merge_workers_(num_merge_workers), workers_initialized_(false) { if (num_workers_ > 0) { - initialize_workers(num_workers_, use_numa); + initialize_workers(num_workers_, num_merge_workers_, use_numa); } } @@ -97,6 +99,42 @@ void QueryCoordinator::allocate_core_resources(int core_idx, } +void QueryCoordinator::merge_worker_fn(int mid) +{ + auto& MR = merge_res_[mid]; + ResultJob rj; + + while (true) { + MR.queue.wait_dequeue(rj); + + if (rj.query_id == -1) break; // poison-pill + + /* ---- grab the pre-built handler ---------------------------------- */ + if (metric_ == faiss::METRIC_INNER_PRODUCT) { + using H = faiss::HeapBlockResultHandler< + faiss::CMin>::SingleResultHandler; + auto* h = static_cast(MR.handlers[rj.query_id]); + for (size_t i = 0; i < rj.distances.size(); ++i) + h->add_result(rj.distances[i], rj.indices[i]); + query_dist_pivots_[rj.query_id].store(h->threshold, + std::memory_order_relaxed); + } else { + using H = faiss::HeapBlockResultHandler< + faiss::CMax>::SingleResultHandler; + auto* h = static_cast(MR.handlers[rj.query_id]); + for (size_t i = 0; i < rj.distances.size(); ++i) + h->add_result(rj.distances[i], rj.indices[i]); + query_dist_pivots_[rj.query_id].store(h->threshold, + std::memory_order_relaxed); + } + + /* ---- bookkeeping -------------------------------------------------- */ + if (!job_flags_[rj.query_id][rj.rank]) { + job_flags_[rj.query_id][rj.rank] = true; + --total_left_; + } + } +} void QueryCoordinator::partition_scan_worker_fn(int core_index) { @@ -130,7 +168,6 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { auto s2 = std::chrono::high_resolution_clock::now(); process_scan_job(job_buffer_[jid], res); - jobs_in_flight_.fetch_sub(1, std::memory_order_relaxed); i++; end = std::chrono::high_resolution_clock::now(); @@ -162,10 +199,10 @@ void QueryCoordinator::process_scan_job(ScanJob job, << " invalid: " << e.what() << ". Returning empty result(s).\n"; if (job.is_batched) { for (int64_t i = 0; i < job.num_queries; ++i) { - result_queue_.enqueue(ResultJob{(*job.query_ids)[i], (*job.ranks)[i], {}, {}}); + enqueue_result_job(ResultJob{(*job.query_ids)[i], (*job.ranks)[i], {}, {}}); } } else { - result_queue_.enqueue(ResultJob{job.query_id, job.rank, {}, {}}); + enqueue_result_job(ResultJob{job.query_id, job.rank, {}, {}}); } return; } @@ -174,10 +211,10 @@ void QueryCoordinator::process_scan_job(ScanJob job, // empty => enqueue zero‐work per query if (job.is_batched) { for (int64_t i = 0; i < job.num_queries; ++i) { - result_queue_.enqueue(ResultJob{(*job.query_ids)[i], (*job.ranks)[i], {}, {}}); + enqueue_result_job(ResultJob{(*job.query_ids)[i], (*job.ranks)[i], {}, {}}); } } else { - result_queue_.enqueue(ResultJob{job.query_id, job.rank, {}, {}}); + enqueue_result_job(ResultJob{job.query_id, job.rank, {}, {}}); } return; } @@ -232,7 +269,7 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, std::cerr << "[QueryCoordinator::handle_nonbatched_job] Partition " << job.partition_id << " invalid or empty before scan for query " << job.query_id << ". Enqueuing empty result.\n"; - result_queue_.enqueue(ResultJob{job.query_id, job.rank, {}, {}}); + enqueue_result_job(ResultJob{job.query_id, job.rank, {}, {}}); return; // Important to return after enqueueing the placeholder } @@ -248,18 +285,18 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, // If scan_list completes, enqueue its results auto tv = buf->get_topk(false); auto ti = buf->get_topk_indices(false); - result_queue_.enqueue(ResultJob{job.query_id, job.rank, std::move(tv), std::move(ti)}); + enqueue_result_job(ResultJob{job.query_id, job.rank, std::move(tv), std::move(ti)}); } catch (const std::exception& e) { std::cerr << "[QueryCoordinator::handle_nonbatched_job] Exception during scan for partition " << job.partition_id << ", query " << job.query_id << ": " << e.what() << ". Enqueuing empty result.\n"; - result_queue_.enqueue(ResultJob{job.query_id, job.rank, {}, {}}); // Enqueue empty result on error + enqueue_result_job(ResultJob{job.query_id, job.rank, {}, {}}); // Enqueue empty result on error } catch (...) { std::cerr << "[QueryCoordinator::handle_nonbatched_job] Unknown exception during scan for partition " << job.partition_id << ", query " << job.query_id << ". Enqueuing empty result.\n"; - result_queue_.enqueue(ResultJob{job.query_id, job.rank, {}, {}}); // Enqueue empty result on error + enqueue_result_job(ResultJob{job.query_id, job.rank, {}, {}}); // Enqueue empty result on error } } @@ -281,7 +318,7 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, int64_t part_size = partition_manager_->partition_store_->list_size(job.partition_id); if (!codes || !ids || part_size <= 0) { for (int64_t i = 0; i < Q; ++i) { - result_queue_.enqueue(ResultJob{(*job.query_ids)[i], (*job.ranks)[i], {}, {}}); + enqueue_result_job(ResultJob{(*job.query_ids)[i], (*job.ranks)[i], {}, {}}); } return; } @@ -396,14 +433,9 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, int rank_q = (*job.ranks) [i]; auto tv = res.topk_buffer_pool[i]->get_topk(false); auto ti = res.topk_buffer_pool[i]->get_topk_indices(false); - results_batch.emplace_back(ResultJob{global_q, rank_q, std::move(tv), std::move(ti)}); + enqueue_result_job(ResultJob{global_q, rank_q, std::move(tv), std::move(ti)}); } - // enqueue this sub-batch in bulk - result_queue_.enqueue_bulk( - std::make_move_iterator(results_batch.begin()), - results_batch.size() - ); end = std::chrono::high_resolution_clock::now(); auto s5 = std::chrono::high_resolution_clock::now(); res.enqueue_time_ns += std::chrono::duration_cast(end - start).count(); @@ -424,6 +456,11 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, // << std::endl; } +void QueryCoordinator::enqueue_result_job(ResultJob job) { + merge_res_[job.query_id % num_merge_workers_].queue.enqueue(std::move(job)); +} + + void QueryCoordinator::init_global_buffers(int64_t nQ, int K, Tensor &partition_ids, @@ -444,13 +481,35 @@ void QueryCoordinator::init_global_buffers(int64_t nQ, std::fill_n(vals, nQ * K, max_val); if (metric_ == faiss::METRIC_INNER_PRODUCT) { - global_max_heaps_ = make_shared>>( - nQ, vals, ids, K); + global_max_heaps_ = std::make_shared< + faiss::HeapBlockResultHandler< + faiss::CMin>>(nQ, vals, ids, K); } else { - std::fill_n(vals, nQ * K, - std::numeric_limits::infinity()); - global_min_heaps_ = make_shared>>( - nQ, vals, ids, K); + global_min_heaps_ = std::make_shared< + faiss::HeapBlockResultHandler< + faiss::CMax>>(nQ, vals, ids, K); + } + + for (auto& mr : merge_res_) { + mr.handlers.clear(); + mr.handlers.resize(nQ, nullptr); + + /* allocate handler objects once per query --------------------------- */ + if (metric_ == faiss::METRIC_INNER_PRODUCT) { + using H = faiss::HeapBlockResultHandler< + faiss::CMin>::SingleResultHandler; + for (int64_t q = 0; q < nQ; ++q) { + mr.handlers[q] = new H(*global_max_heaps_); + static_cast(mr.handlers[q])->begin(q); + } + } else { + using H = faiss::HeapBlockResultHandler< + faiss::CMax>::SingleResultHandler; + for (int64_t q = 0; q < nQ; ++q) { + mr.handlers[q] = new H(*global_min_heaps_); + static_cast(mr.handlers[q])->begin(q); + } + } } query_dist_pivots_ = vector>(nQ); @@ -492,6 +551,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, // flatten jobs next_job_id_ = 0; + total_left_.store(0, std::memory_order_relaxed); job_flags_.clear(); job_flags_.resize(nQ); for (int64_t q = 0; q < nQ; ++q) { @@ -522,7 +582,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, job_buffer_.push_back(job); numa_resources_[core_to_numa[pid % num_workers_]].job_queue.enqueue(next_job_id_); next_job_id_++; - jobs_in_flight_.fetch_add(1, std::memory_order_relaxed); + total_left_.fetch_add(1, std::memory_order_relaxed); } } } else { @@ -573,7 +633,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, job_buffer_.push_back(job); numa_resources_[core_to_numa[pid % num_workers_]].job_queue.enqueue(next_job_id_); next_job_id_++; - jobs_in_flight_.fetch_add(1, std::memory_order_relaxed); + total_left_.fetch_add(1, std::memory_order_relaxed); } } else { ScanJob job; @@ -593,7 +653,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, int node = core_to_numa[core]; numa_resources_[node].job_queue.enqueue(next_job_id_); next_job_id_++; - jobs_in_flight_.fetch_add(1, std::memory_order_relaxed); + total_left_.fetch_add(chunk, std::memory_order_relaxed); } } } @@ -605,122 +665,19 @@ void QueryCoordinator::drain_and_apply_aps(Tensor x, Tensor partition_ids, bool use_aps, float recall_target, - float aps_flush_period_us, + int aps_flush_period_us, std::shared_ptr timing) { - const int64_t nQ = x.size(0); - const int64_t D = x.size(1); - const int64_t nprobe = partition_ids.size(1); - const auto aps_dur = std::chrono::microseconds( - static_cast(aps_flush_period_us)); - - /* ------------------------------------------------------------------------ */ - /* Book-keeping */ - /* ------------------------------------------------------------------------ */ - std::vector parts_left(nQ, 0); - std::atomic total_left{0}; - - for (int64_t q = 0; q < nQ; ++q) { - for (int64_t p = 0; p < nprobe; ++p) - if (!job_flags_[q][p]) { ++parts_left[q]; ++total_left; } - } - - /* APS pre-computations -------------------------------------------------- */ - std::vector query_radius(nQ, 0.0f); - std::vector> boundary_dist(nQ); - std::vector> probs(nQ); - if (use_aps) { - query_radius.resize(nQ); - boundary_dist.resize(nQ); - probs.resize(nQ); - for (int64_t q = 0; q < nQ; ++q) { - std::vector pids(partition_ids[q].data_ptr(), - partition_ids[q].data_ptr()+nprobe); - auto centroids = parent_->partition_manager_->get_vectors(pids); - centroids.erase(std::remove(centroids.begin(), centroids.end(), nullptr), - centroids.end()); - boundary_dist[q] = - compute_boundary_distances(x[q], centroids, metric_==faiss::METRIC_L2); - } - } - - vector per_query_result_count(nQ, 0); - - if (metric_ == faiss::METRIC_INNER_PRODUCT) { - vector>::SingleResultHandler> - handlers; - for (int64_t q = 0; q < nQ; ++q) { - handlers.emplace_back(*global_max_heaps_); - handlers[q].begin(q); // ← reset & heapify for query q - } - - ResultJob rj; - while (total_left.load(std::memory_order_relaxed) > 0) { - - /* -- Wait for result or APS timeout -- */ - bool got_result = result_queue_.wait_dequeue_timed(rj, aps_dur); - if (got_result) { - do { // Drain *all* currently available results. - for (int64_t i = 0; i < rj.distances.size(); ++i) { - handlers[rj.query_id].add_result(rj.distances[i], rj.indices[i]); - } - query_dist_pivots_[rj.query_id].store( - handlers[rj.query_id].threshold, std::memory_order_relaxed); - - per_query_result_count[rj.query_id]++; - - if (!job_flags_[rj.query_id][rj.rank]) { - job_flags_[rj.query_id][rj.rank] = true; - --parts_left[rj.query_id]; - --total_left; - } - } while (result_queue_.try_dequeue(rj)); - } - } - // end the handlers - for (int64_t q = 0; q < nQ; ++q) { - handlers[q].end(); - } - } else { - vector>::SingleResultHandler> - handlers; - handlers.reserve(nQ); - for (int64_t q = 0; q < nQ; ++q) { - handlers.emplace_back(*global_min_heaps_); - handlers[q].begin(q); // ← reset & heapify for query q - } - - ResultJob rj; - while (total_left.load(std::memory_order_relaxed) > 0) { + int64_t nQ = x.size(0), D = x.size(1); + // compute boundary distances - /* -- Wait for result or APS timeout -- */ - bool got_result = result_queue_.wait_dequeue_timed(rj, aps_dur); + while (total_left_.load(std::memory_order_relaxed) > 0) + std::this_thread::sleep_for(std::chrono::microseconds(aps_flush_period_us)); - if (got_result) { - do { // Drain *all* currently available results. - for (int64_t i = 0; i < rj.distances.size(); ++i) { - handlers[rj.query_id].add_result(rj.distances[i], rj.indices[i]); - } - query_dist_pivots_[rj.query_id].store( - handlers[rj.query_id].threshold, std::memory_order_relaxed); - per_query_result_count[rj.query_id]++; - - if (!job_flags_[rj.query_id][rj.rank]) { - job_flags_[rj.query_id][rj.rank] = true; - --parts_left[rj.query_id]; - --total_left; - } - } while (result_queue_.try_dequeue(rj)); - } - } - // end the handlers - for (int64_t q = 0; q < nQ; ++q) { - handlers[q].end(); - } - } + // check if we need to apply APS } std::shared_ptr @@ -730,6 +687,23 @@ QueryCoordinator::aggregate_scan_results(int64_t nQ, Tensor out_ids, Tensor out_dists) { + for (int64_t q = 0; q < nQ; ++q) { + int merge_worker_idx = q % num_merge_workers_; + MergeResources& mr = merge_res_[merge_worker_idx]; + + if (q < static_cast(mr.handlers.size()) && mr.handlers[q] != nullptr) { + if (metric_ == faiss::METRIC_INNER_PRODUCT) { + using H = faiss::HeapBlockResultHandler< + faiss::CMin>::SingleResultHandler; + static_cast(mr.handlers[q])->end(); + } else { + using H = faiss::HeapBlockResultHandler< + faiss::CMax>::SingleResultHandler; + static_cast(mr.handlers[q])->end(); + } + } + } + auto id_acc = out_ids.accessor(); auto d_acc = out_dists.accessor(); @@ -871,20 +845,20 @@ std::shared_ptr QueryCoordinator::worker_scan( } // Initialize Worker Threads -void QueryCoordinator::initialize_workers(int num_cores, bool use_numa) { +void QueryCoordinator::initialize_workers(int num_workers, int num_merge_workers, bool use_numa) { if (workers_initialized_) { std::cerr << "[QueryCoordinator::initialize_workers] Workers already initialized." << std::endl; return; } - std::cout << "[QueryCoordinator::initialize_workers] Initializing " << num_cores << " worker threads with use_numa=" << use_numa << + std::cout << "[QueryCoordinator::initialize_workers] Initializing " << num_workers << " worker threads with use_numa=" << use_numa << std::endl; - partition_manager_->distribute_partitions(num_cores, use_numa); - core_resources_.resize(num_cores); - worker_threads_.resize(num_cores); + partition_manager_->distribute_partitions(num_workers, use_numa); + core_resources_.resize(num_workers); + worker_threads_.resize(num_workers); stop_workers_.store(false); - for (int i = 0; i < num_cores; i++) { + for (int i = 0; i < num_workers; i++) { if (!set_thread_affinity(i)) { std::cout << "[QueryCoordinator::initialize_workers] Failed to set thread affinity on core " << i << std::endl; } @@ -892,11 +866,19 @@ void QueryCoordinator::initialize_workers(int num_cores, bool use_numa) { worker_threads_[i] = std::thread(&QueryCoordinator::partition_scan_worker_fn, this, i); } + merge_res_.resize(num_merge_workers_); + for (int i = 0; i < num_merge_workers; i++) { + if (!set_thread_affinity(i + num_workers)) { + std::cout << "[QueryCoordinator::initialize_workers] Failed to set thread affinity on core " << i + num_workers << std::endl; + } + merge_threads_.emplace_back(&QueryCoordinator::merge_worker_fn, this, i); + } + workers_initialized_ = true; // set main thread on separate thread from workers int num_cores_on_machine = std::thread::hardware_concurrency(); - set_thread_affinity(num_cores % num_cores_on_machine); + set_thread_affinity(num_workers + num_merge_workers); // set_thread_affinity(0); } @@ -912,11 +894,24 @@ void QueryCoordinator::shutdown_workers() { for (int i = 0; i < num_workers_; ++i) res.job_queue.enqueue(-1); } + + for (int m = 0; m < num_merge_workers_; ++m) { + enqueue_result_job(ResultJob{-1,0,{},{}}); + } + // Join all worker threads. for (auto &thr : worker_threads_) { if (thr.joinable()) thr.join(); } + + for (auto &t : merge_threads_) { + if (t.joinable()) + t.join(); + } + + + merge_threads_.clear(); worker_threads_.clear(); workers_initialized_ = false; } From 2022507aaed237c617fabbfbb109261dc131ba50 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 26 May 2025 00:05:25 -0500 Subject: [PATCH 274/323] parallelize sort --- src/cpp/bindings/wrap.cpp | 2 ++ src/cpp/include/common.h | 2 ++ src/cpp/include/quake_index.h | 2 +- src/cpp/include/query_coordinator.h | 3 ++- src/cpp/src/quake_index.cpp | 19 +++++++++++---- src/cpp/src/query_coordinator.cpp | 37 ++++++++++++++++++++++++++--- src/python/index_wrappers/quake.py | 22 +++++++++++++---- 7 files changed, 72 insertions(+), 15 deletions(-) diff --git a/src/cpp/bindings/wrap.cpp b/src/cpp/bindings/wrap.cpp index 5e5b1563..cfd0f29d 100644 --- a/src/cpp/bindings/wrap.cpp +++ b/src/cpp/bindings/wrap.cpp @@ -148,6 +148,8 @@ PYBIND11_MODULE(_bindings, m) { (std::string("Number of workers. default = ") + std::to_string(DEFAULT_NUM_WORKERS)).c_str()) .def_readwrite("parent_params", &IndexBuildParams::parent_params, "Parameters for the parent index, if any.") + .def_readwrite("num_merge_workers", &IndexBuildParams::num_merge_workers, + (std::string("Number of workers for merging. default = ") + std::to_string(DEFAULT_NUM_MERGE_WORKERS)).c_str()) .def_readwrite("use_numa", &IndexBuildParams::use_numa, (std::string("Flag to use NUMA for index building. default = ") + std::to_string(false)).c_str()) .def_readwrite("use_gpu", &IndexBuildParams::use_gpu, diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index 32ce00d4..bf1038ed 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -63,6 +63,7 @@ constexpr int DEFAULT_NLIST = 0; ///< Default number of cluste constexpr int DEFAULT_NITER = 5; ///< Default number of k-means iterations used during clustering. constexpr const char* DEFAULT_METRIC = "l2"; ///< Default distance metric (either "l2" for Euclidean or "ip" for inner product). constexpr int DEFAULT_NUM_WORKERS = 0; ///< Default number of workers (0 means single-threaded). +constexpr int DEFAULT_NUM_MERGE_WORKERS = 1; ///< Default number of merge workers (for worker_scan) constexpr int DEFAULT_GPU_BATCH_SIZE = 100000; ///< Default batch size for GPU index building. constexpr int DEFAULT_GPU_SAMPLE_SIZE = 1000000; ///< Default sample size for GPU index building. @@ -125,6 +126,7 @@ struct IndexBuildParams { int dimension = 0; int nlist = DEFAULT_NLIST; int num_workers = DEFAULT_NUM_WORKERS; + int num_merge_workers = DEFAULT_NUM_MERGE_WORKERS; int code_size = -1; // for PQ int num_codebooks = -1; // for PQ string metric = DEFAULT_METRIC; diff --git a/src/cpp/include/quake_index.h b/src/cpp/include/quake_index.h index 0358aec9..69edb3f8 100644 --- a/src/cpp/include/quake_index.h +++ b/src/cpp/include/quake_index.h @@ -122,7 +122,7 @@ class QuakeIndex { * @param path Path to load the index. * @param n_workers Number of workers to use for query processing. */ - void load(const std::string &path, int n_workers = 0, bool use_numa=false, int parent_n_workers=0); + void load(const std::string &path, shared_ptr params); /** * @brief Get the total number of vectors in the index. diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 3c9c6c69..88b07e32 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -128,6 +128,7 @@ class QueryCoordinator { std::atomic job_pull_time_ns = 0; ///< Time spent pulling jobs from the queue. std::atomic job_process_time_ns = 0; ///< Time spent processing jobs. std::atomic total_left_; + vector> per_query_total_left_; ///< Total jobs left for each query. /** * @brief Constructs a QueryCoordinator. @@ -144,7 +145,7 @@ class QueryCoordinator { MetricType metric, int num_workers=0, bool use_numa=false, - int num_merge_workers=2); + int num_merge_workers=1); /** * @brief Destructor for QueryCoordinator. diff --git a/src/cpp/src/quake_index.cpp b/src/cpp/src/quake_index.cpp index 36f04661..e1d6697e 100644 --- a/src/cpp/src/quake_index.cpp +++ b/src/cpp/src/quake_index.cpp @@ -236,7 +236,7 @@ void QuakeIndex::save(const std::string& dir_path) { std::cout << "[QuakeIndex::save] Index saved to directory: " << dir_path << "\n"; } -void QuakeIndex::load(const std::string& dir_path, int n_workers, bool use_numa, int parent_n_workers) { +void QuakeIndex::load(const std::string& dir_path, shared_ptr build_params) { namespace fs = std::filesystem; if (!fs::exists(dir_path) || !fs::is_directory(dir_path)) { @@ -282,7 +282,11 @@ void QuakeIndex::load(const std::string& dir_path, int n_workers, bool use_numa, if (fs::exists(parent_dir) && fs::is_directory(parent_dir)) { parent_ = std::make_shared(); int n_parts = partition_manager_->nlist(); - parent_->load(parent_dir, parent_n_workers, use_numa); + auto parent_params = make_shared(); + if (build_params->parent_params != nullptr) { + parent_params = build_params->parent_params; + } + parent_->load(parent_dir, parent_params); partition_manager_->parent_ = parent_; } else { parent_ = nullptr; @@ -293,9 +297,14 @@ void QuakeIndex::load(const std::string& dir_path, int n_workers, bool use_numa, initialize_maintenance_policy(default_params); // 5. Create query coordinator - std::cout << "Loading coordinator with n_workers=" << n_workers << " and use_numa=" << use_numa << '\n'; - query_coordinator_ = std::make_shared(parent_, partition_manager_, maintenance_policy_, metric_, n_workers, use_numa); - std::cout << "Loaded coordinator\n"; + std::cout << "Loading coordinator with n_workers=" << build_params->num_workers << " and use_numa=" << build_params->use_numa << '\n'; + query_coordinator_ = std::make_shared(parent_, + partition_manager_, + maintenance_policy_, + metric_, + build_params->num_workers, + build_params->use_numa, + build_params->num_merge_workers); } int64_t QuakeIndex::ntotal() { diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index ed5d9465..975cb958 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -104,6 +104,23 @@ void QueryCoordinator::merge_worker_fn(int mid) auto& MR = merge_res_[mid]; ResultJob rj; + // for (int64_t q = 0; q < nQ; ++q) { + // int merge_worker_idx = q % num_merge_workers_; + // MergeResources& mr = merge_res_[merge_worker_idx]; + // + // if (q < static_cast(mr.handlers.size()) && mr.handlers[q] != nullptr) { + // if (metric_ == faiss::METRIC_INNER_PRODUCT) { + // using H = faiss::HeapBlockResultHandler< + // faiss::CMin>::SingleResultHandler; + // static_cast(mr.handlers[q])->end(); + // } else { + // using H = faiss::HeapBlockResultHandler< + // faiss::CMax>::SingleResultHandler; + // static_cast(mr.handlers[q])->end(); + // } + // } + // } + while (true) { MR.queue.wait_dequeue(rj); @@ -131,6 +148,19 @@ void QueryCoordinator::merge_worker_fn(int mid) /* ---- bookkeeping -------------------------------------------------- */ if (!job_flags_[rj.query_id][rj.rank]) { job_flags_[rj.query_id][rj.rank] = true; + --per_query_total_left_[rj.query_id]; + + if (per_query_total_left_[rj.query_id] == 0) { + if (metric_ == faiss::METRIC_INNER_PRODUCT) { + using H = faiss::HeapBlockResultHandler< + faiss::CMin>::SingleResultHandler; + static_cast(MR.handlers[rj.query_id])->end(); + } else { + using H = faiss::HeapBlockResultHandler< + faiss::CMax>::SingleResultHandler; + static_cast(MR.handlers[rj.query_id])->end(); + } + } --total_left_; } } @@ -387,6 +417,7 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, } auto s3 = std::chrono::high_resolution_clock::now(); + // check that things are on the proper NUMA node // bool ok = true; // ok = ok && verify_numa_locality(qptr, "qptr"); @@ -468,8 +499,6 @@ void QueryCoordinator::init_global_buffers(int64_t nQ, std::lock_guard lg(global_mutex_); // resize or reset - // size_t cap = std::min(100 * K, 10000); - // faiss::HeapArray>(nQ) }; float * vals = (float *) quake_alloc(nQ * K * sizeof(float), 0); int64_t * ids = (int64_t *) quake_alloc(nQ * K * sizeof(int64_t), 0); std::fill_n(ids, nQ * K, -1); @@ -549,17 +578,19 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, core_to_numa[i] = cpu_numa_node(i); } - // flatten jobs + // Reset job state next_job_id_ = 0; total_left_.store(0, std::memory_order_relaxed); job_flags_.clear(); job_flags_.resize(nQ); + per_query_total_left_ = vector>(nQ); for (int64_t q = 0; q < nQ; ++q) { job_flags_[q] = vector>(partition_ids.size(1)); for (int p = 0; p < partition_ids.size(1); ++p) { job_flags_[q][p].store(false); if (partition_ids_acc[q][p] < 0) job_flags_[q][p] = true; } + per_query_total_left_[q].store(partition_ids.size(1), std::memory_order_relaxed); } job_buffer_.clear(); job_buffer_.reserve(nQ * partition_ids.size(1)); diff --git a/src/python/index_wrappers/quake.py b/src/python/index_wrappers/quake.py index 99ea9846..d6558d59 100644 --- a/src/python/index_wrappers/quake.py +++ b/src/python/index_wrappers/quake.py @@ -65,6 +65,7 @@ def build( metric: str = "l2", ids: Optional[torch.Tensor] = None, num_workers: int = 0, + num_merge_workers: int = 1, m: int = -1, code_size: int = 8, parent=None, @@ -94,11 +95,15 @@ def build( build_params.metric = metric build_params.nlist = nc build_params.num_workers = num_workers + build_params.num_merge_workers = num_merge_workers build_params.use_numa = use_numa if parent is not None: build_params.parent_params = quake.IndexBuildParams() build_params.parent_params.nlist = parent.get("nc", 1) + build_params.parent_params.num_workers = parent.get("num_workers", 0) + build_params.parent_params.num_merge_workers = parent.get("num_merge_workers", 1) + build_params.use_gpu = use_gpu build_params.gpu_batch_size = gpu_batch_size @@ -178,8 +183,6 @@ def search( search_params.sample_stride = sample_stride search_params.batch_size = batch_size - print(parent) - if parent is not None: search_params.parent_params = quake.SearchParams() search_params.parent_params.nprobe = parent.get("nprobe", 1) @@ -209,8 +212,9 @@ def load( self, filename: str, num_workers: int = 0, - parent_num_workers: int = 0, + num_merge_workers: int = 1, use_numa: bool = False, + parent: dict = None, verbose: bool = False, ): """ @@ -219,10 +223,18 @@ def load( :param filename: The name of the file to load the index from. """ print( - f"Loading index from {filename}, with {num_workers} workers, use_numa={use_numa}, parent_num_workers={parent_num_workers}" + f"Loading index from {filename}, with {num_workers} workers, use_numa={use_numa}, parent={parent}" ) self.index = QuakeIndex() - self.index.load(str(filename), num_workers, use_numa, parent_num_workers) + build_params = quake.IndexBuildParams() + build_params.num_workers = num_workers + build_params.use_numa = use_numa + build_params.parent_params = quake.IndexBuildParams() + if parent is not None: + build_params.parent_params.num_workers = parent.get("num_workers", 0) + build_params.parent_params.num_merge_workers = parent.get("num_merge_workers", 1) + build_params.parent_params.use_numa = parent.get("use_numa", build_params.use_numa) + self.index.load(str(filename), build_params) def centroids(self) -> torch.Tensor: """ From 770030c69b615405d38ce44983d6f1cc7089ff0c Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 26 May 2025 00:26:55 -0500 Subject: [PATCH 275/323] parallelize sort --- src/cpp/include/query_coordinator.h | 2 +- src/cpp/src/query_coordinator.cpp | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 88b07e32..26c567a2 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -118,7 +118,7 @@ class QueryCoordinator { std::mutex global_mutex_; ///< Mutex for global synchronization. std::condition_variable global_cv_; ///< Condition variable for thread coordination. - std::atomic stop_workers_; ///< Flag to signal workers to terminate. + std::atomic stop_workers_; ///< Flag to signal workers to terminate. bool debug_ = false; ///< Debug mode flag. std::vector job_buffer_; diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 975cb958..1d4f1f66 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -487,8 +487,18 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, // << std::endl; } -void QueryCoordinator::enqueue_result_job(ResultJob job) { - merge_res_[job.query_id % num_merge_workers_].queue.enqueue(std::move(job)); +// --- replace old enqueue ------------------------------------------------- +inline void QueryCoordinator::enqueue_result_job(ResultJob job) +{ + if (job.query_id < 0) { + // Poison pill to stop the merge worker + for (auto& mr : merge_res_) { + mr.queue.enqueue(ResultJob{-1, 0, {}, {}}); + } + return; + } + const size_t mid = static_cast(job.query_id) % num_merge_workers_; + merge_res_[mid].queue.enqueue(std::move(job)); } @@ -920,14 +930,15 @@ void QueryCoordinator::shutdown_workers() { } stop_workers_.store(true); - // Enqueue a special shutdown job for each core. + // Enqueue poison pills to all worker threads. for (auto &res : numa_resources_) { for (int i = 0; i < num_workers_; ++i) res.job_queue.enqueue(-1); } + // Enqueue poison pills to all merge workers. for (int m = 0; m < num_merge_workers_; ++m) { - enqueue_result_job(ResultJob{-1,0,{},{}}); + merge_res_[m].queue.enqueue(ResultJob{-1, 0, {}, {}}); } // Join all worker threads. From 09f905e3a28b0f76c8fa18936100d783ad249d9c Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 26 May 2025 01:36:32 -0500 Subject: [PATCH 276/323] parallelize sort --- src/cpp/src/query_coordinator.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 1d4f1f66..f6940cba 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -596,11 +596,16 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, per_query_total_left_ = vector>(nQ); for (int64_t q = 0; q < nQ; ++q) { job_flags_[q] = vector>(partition_ids.size(1)); + + int valid_count = 0; for (int p = 0; p < partition_ids.size(1); ++p) { job_flags_[q][p].store(false); - if (partition_ids_acc[q][p] < 0) job_flags_[q][p] = true; + if (partition_ids_acc[q][p] < 0) { + job_flags_[q][p] = true; + valid_count++; + } } - per_query_total_left_[q].store(partition_ids.size(1), std::memory_order_relaxed); + per_query_total_left_[q].store(valid_count, std::memory_order_relaxed); } job_buffer_.clear(); job_buffer_.reserve(nQ * partition_ids.size(1)); From a3b284407716bf568bbd2d79b9a90b7743f64d57 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 26 May 2025 01:56:44 -0500 Subject: [PATCH 277/323] parallelize sort --- src/cpp/src/query_coordinator.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index f6940cba..0a74328f 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -163,6 +163,12 @@ void QueryCoordinator::merge_worker_fn(int mid) } --total_left_; } + + std::cout << "[merge_worker_fn] Query ID: " << rj.query_id + << ", Rank: " << rj.rank + << ", Distances: " << rj.distances.size() + << ", Indices: " << rj.indices.size() + << ", Total left: " << total_left_.load() << std::endl; } } From 80f6e84c34ecad9bdcf20e207388940ead188ee1 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 26 May 2025 01:59:00 -0500 Subject: [PATCH 278/323] parallelize sort --- src/cpp/src/query_coordinator.cpp | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 0a74328f..8dbd7851 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -104,24 +104,7 @@ void QueryCoordinator::merge_worker_fn(int mid) auto& MR = merge_res_[mid]; ResultJob rj; - // for (int64_t q = 0; q < nQ; ++q) { - // int merge_worker_idx = q % num_merge_workers_; - // MergeResources& mr = merge_res_[merge_worker_idx]; - // - // if (q < static_cast(mr.handlers.size()) && mr.handlers[q] != nullptr) { - // if (metric_ == faiss::METRIC_INNER_PRODUCT) { - // using H = faiss::HeapBlockResultHandler< - // faiss::CMin>::SingleResultHandler; - // static_cast(mr.handlers[q])->end(); - // } else { - // using H = faiss::HeapBlockResultHandler< - // faiss::CMax>::SingleResultHandler; - // static_cast(mr.handlers[q])->end(); - // } - // } - // } - - while (true) { + while (!stop_workers_) { MR.queue.wait_dequeue(rj); if (rj.query_id == -1) break; // poison-pill @@ -209,6 +192,14 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { res.process_time_ns += std::chrono::duration_cast(end - s2).count(); res.job_time_ns += std::chrono::duration_cast(end - start).count(); + + std::cout << "[partition_scan_worker_fn] Core: " << core_index + << ", Job ID: " << jid + << ", Processed: " << i + << ", Wait time: " << res.wait_time_ns / 1e6 << " ms" + << ", Process time: " << res.process_time_ns / 1e6 << " ms" + << ", Enqueue time: " << res.enqueue_time_ns / 1e6 << " ms" + << ", Job time: " << res.job_time_ns / 1e6 << " ms" << std::endl; } } From 8507b8c95805579b253e421ff2ae58e6a0eaf872 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 26 May 2025 02:01:39 -0500 Subject: [PATCH 279/323] parallelize sort --- src/cpp/src/query_coordinator.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 8dbd7851..da7bee21 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -599,6 +599,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, job_flags_[q][p].store(false); if (partition_ids_acc[q][p] < 0) { job_flags_[q][p] = true; + } else { valid_count++; } } From 1eb008dc622f331d3e1830b6f6b65789e77ccba4 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 26 May 2025 02:10:28 -0500 Subject: [PATCH 280/323] parallelize sort --- src/cpp/src/query_coordinator.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index da7bee21..0a69237a 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -585,6 +585,11 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, core_to_numa[i] = cpu_numa_node(i); } + std::cout << "[enqueue_scan_jobs] Enqueuing jobs for " << nQ + << " queries, " << partition_ids.size(1) + << " partitions, k = " << params->k + << ", batched scan: " << (params->batched_scan ? "yes" : "no") << std::endl; + // Reset job state next_job_id_ = 0; total_left_.store(0, std::memory_order_relaxed); From 632c36feff05d010ff6f4800820738817d8d7267 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 26 May 2025 02:13:50 -0500 Subject: [PATCH 281/323] parallelize sort --- src/cpp/src/query_coordinator.cpp | 32 +++++++++---------- .../osdi2025/numa_multi_query/run.py | 3 +- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 0a69237a..0a721568 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -147,11 +147,11 @@ void QueryCoordinator::merge_worker_fn(int mid) --total_left_; } - std::cout << "[merge_worker_fn] Query ID: " << rj.query_id - << ", Rank: " << rj.rank - << ", Distances: " << rj.distances.size() - << ", Indices: " << rj.indices.size() - << ", Total left: " << total_left_.load() << std::endl; + // std::cout << "[merge_worker_fn] Query ID: " << rj.query_id + // << ", Rank: " << rj.rank + // << ", Distances: " << rj.distances.size() + // << ", Indices: " << rj.indices.size() + // << ", Total left: " << total_left_.load() << std::endl; } } @@ -193,13 +193,13 @@ void QueryCoordinator::partition_scan_worker_fn(int core_index) { res.process_time_ns += std::chrono::duration_cast(end - s2).count(); res.job_time_ns += std::chrono::duration_cast(end - start).count(); - std::cout << "[partition_scan_worker_fn] Core: " << core_index - << ", Job ID: " << jid - << ", Processed: " << i - << ", Wait time: " << res.wait_time_ns / 1e6 << " ms" - << ", Process time: " << res.process_time_ns / 1e6 << " ms" - << ", Enqueue time: " << res.enqueue_time_ns / 1e6 << " ms" - << ", Job time: " << res.job_time_ns / 1e6 << " ms" << std::endl; + // std::cout << "[partition_scan_worker_fn] Core: " << core_index + // << ", Job ID: " << jid + // << ", Processed: " << i + // << ", Wait time: " << res.wait_time_ns / 1e6 << " ms" + // << ", Process time: " << res.process_time_ns / 1e6 << " ms" + // << ", Enqueue time: " << res.enqueue_time_ns / 1e6 << " ms" + // << ", Job time: " << res.job_time_ns / 1e6 << " ms" << std::endl; } } @@ -585,10 +585,10 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, core_to_numa[i] = cpu_numa_node(i); } - std::cout << "[enqueue_scan_jobs] Enqueuing jobs for " << nQ - << " queries, " << partition_ids.size(1) - << " partitions, k = " << params->k - << ", batched scan: " << (params->batched_scan ? "yes" : "no") << std::endl; + // std::cout << "[enqueue_scan_jobs] Enqueuing jobs for " << nQ + // << " queries, " << partition_ids.size(1) + // << " partitions, k = " << params->k + // << ", batched scan: " << (params->batched_scan ? "yes" : "no") << std::endl; // Reset job state next_job_id_ = 0; diff --git a/test/experiments/osdi2025/numa_multi_query/run.py b/test/experiments/osdi2025/numa_multi_query/run.py index 6d679069..c424b04b 100644 --- a/test/experiments/osdi2025/numa_multi_query/run.py +++ b/test/experiments/osdi2025/numa_multi_query/run.py @@ -96,7 +96,8 @@ def task_search_index( load_kwargs = {} if "num_workers" in current_build_params_for_load: load_kwargs["num_workers"] = current_build_params_for_load.get("num_workers") if "use_numa" in current_build_params_for_load: load_kwargs["use_numa"] = current_build_params_for_load.get("use_numa") - if "parent_num_workers" in current_build_params_for_load: load_kwargs["parent_num_workers"] = current_build_params_for_load.get("parent_num_workers") + if "num_merge_workers" in current_build_params_for_load: load_kwargs["num_merge_workers"] = current_build_params_for_load.get("num_merge_workers") + if "parent" in current_build_params_for_load: load_kwargs["parent"] = current_build_params_for_load.get("parent") idx_instance.load(str(index_file_path), **load_kwargs) print(f"[{index_name} SEARCH_TASK] Index loaded with kwargs: {load_kwargs}") From 48a2bfb15c335b7f6e8220bfa927c6e08ca7f74e Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 27 May 2025 13:52:39 -0500 Subject: [PATCH 282/323] add batch size exp --- src/cpp/include/list_scanning.h | 49 +++-- src/cpp/include/query_coordinator.h | 3 +- src/cpp/src/clustering.cpp | 1 + src/cpp/src/quake_index.cpp | 7 +- src/cpp/src/query_coordinator.cpp | 139 +++++++------- src/python/datasets/ann_datasets.py | 106 +++++++++++ .../experiments/osdi2025/experiment_runner.py | 2 + .../configs/wiki_single_thread.yaml | 62 ++++++ .../osdi2025/vary_batch_size/run.py | 178 ++++++++++++++++++ 9 files changed, 448 insertions(+), 99 deletions(-) create mode 100644 test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml create mode 100644 test/experiments/osdi2025/vary_batch_size/run.py diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 925943ca..b42d810a 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -180,7 +180,7 @@ class TypedTopKBuffer { if (++head_ == capacity_) flush(); } - float batch_add(T *distances, I *indices, int num_values) { + void batch_add(T *distances, I *indices, int num_values) { int pos = 0; while (pos < num_values) { int available = capacity_ - head_; @@ -208,28 +208,26 @@ class TypedTopKBuffer { for (int i = 0; i < n; ++i) { ord_[i] = i; } - // comparator by value - auto cmpIdx = [&](int a, int b) { - return is_desc_ ? (vals_[a] > vals_[b]) - : (vals_[a] < vals_[b]); + + auto cmp = [&](int a, int b) { + return is_desc_ ? vals_[a] > vals_[b] : vals_[a] < vals_[b]; }; + // 2) select top‐m indices into ord_[0..m) if (n > m) { if (m < 10) { - miniselect::heap_select(ord_, ord_ + m, ord_ + n, cmpIdx); + miniselect::heap_select(ord_, ord_ + m, ord_ + n, cmp); } else if (m < n * 0.001) { - miniselect::floyd_rivest_select(ord_, ord_ + m, ord_ + n, cmpIdx); + miniselect::floyd_rivest_select(ord_, ord_ + m, ord_ + n, cmp); } else { - miniselect::pdqpartial_sort_branchless(ord_, ord_ + m, ord_ + n, cmpIdx); + miniselect::pdqpartial_sort_branchless(ord_, ord_ + m, ord_ + n, cmp); } } else { - miniselect::pdqsort_branchless(ord_, ord_ + n, cmpIdx); + miniselect::pdqsort_branchless(ord_, ord_ + n, cmp); } - // 4) fully sort the top-m indices so they are in strictly correct order - miniselect::pdqsort_branchless(ord_, ord_ + m, cmpIdx); // 5) copy the winners back to vals_/ids_ and clamp head_ std::vector temp_v(m); @@ -390,7 +388,10 @@ inline void scan_list_with_ids_l2(const float *query_vec, float pivot) { const float *vec = list_vecs; for (int l = 0; l < list_size; l++) { - buffer.add(sqrt(faiss::fvec_L2sqr(query_vec, vec, d)), list_ids[l]); + float dist = sqrt(faiss::fvec_L2sqr(query_vec, vec, d)); + if (dist < pivot) { + buffer.add(sqrt(faiss::fvec_L2sqr(query_vec, vec, d)), list_ids[l]); + } vec += d; } } @@ -403,10 +404,10 @@ inline void scan_list(const float *query_vec, int d, TopkBuffer &buffer, faiss::MetricType metric, - float pivot = -1) { + float pivot = NULL) { // Dispatch based on metric type and whether list_ids is provided. - if (pivot == 0) { + if (pivot == NULL) { pivot = metric == faiss::METRIC_INNER_PRODUCT ? -std::numeric_limits::infinity() : std::numeric_limits::infinity(); @@ -436,11 +437,11 @@ inline void ip_blas( size_t k, vector> &topk_buffers, float* __restrict ip_block, // nx * bs_y - vector*> pivot) // db_blas_bs + vector*> pivot = {}) // db_blas_bs { if (nx == 0 || ny == 0) return; - constexpr size_t bs_x = 256; + const size_t bs_x = nx; const size_t bs_y = db_blas_bs; int64_t *list_ids_ptr = (int64_t *) list_ids; @@ -453,8 +454,12 @@ inline void ip_blas( const size_t db_chunk = j1 - j0; // use torch matmul - - /* SGEMM */ +# ifdef __APPLE__ // use torch on macOS + Tensor x_tensor = torch::from_blob((void*) (x + i0 * d), {(int64_t) q_chunk, (int64_t) d}, torch::kFloat32); + Tensor y_tensor = torch::from_blob((void*) (y + j0 * d), {(int64_t) db_chunk, (int64_t) d}, torch::kFloat32); + Tensor ip_tensor = torch::from_blob(ip_block, {(int64_t) q_chunk, (int64_t) db_chunk}, torch::kFloat32); + torch::matmul_out(ip_tensor, x_tensor, y_tensor.transpose(0, 1)); +#else // use BLAS on Linux { const float one = 1.f; float zero = 0.f; @@ -469,11 +474,14 @@ inline void ip_blas( &zero, ip_block, &nyi); } +#endif + /* IP → L2² */ if (k > 1) { for (int64_t qi = 0; qi < static_cast(q_chunk); ++qi) { float* line_ptr = ip_block + qi * db_chunk; // Pointer to current column in ip_block + // collect distances closer than pivot if (pivot.size() > 0) { float curr_pivot = pivot[qi]->load(std::memory_order_relaxed); @@ -495,7 +503,7 @@ inline void ip_blas( int64_t best_id = -1; for (size_t pj = 0; pj < db_chunk; ++pj) { - if (*line_ptr < best_dist) { + if (*line_ptr > best_dist) { best_dist = *line_ptr; best_id = list_ids_ptr[j0 + pj]; } @@ -526,7 +534,7 @@ inline void l2_blas( { if (nx == 0 || ny == 0) return; - constexpr size_t bs_x = 256; + const size_t bs_x = nx; const size_t bs_y = db_blas_bs; int64_t *list_ids_ptr = (int64_t *) list_ids; @@ -660,6 +668,7 @@ inline void batched_scan_list(const float *query_vecs, pivots ); } else if (metric == faiss::METRIC_L2) { + std::cout << "Using L2 metric for batched scan." << std::endl; l2_blas( query_vecs, list_vecs, diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 26c567a2..2bfd93cd 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -226,7 +226,8 @@ class QueryCoordinator { */ void partition_scan_worker_fn(int worker_id); - void merge_worker_fn(int merge_worker_id); + template + void merge_worker_fn(int worker_id); /** * @brief Worker thread function to perform partition scanning. diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index 85f517e8..f46ad13e 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -163,6 +163,7 @@ shared_ptr kmeans_cpu(Tensor vectors, faiss::ClusteringParameters cp; cp.niter = build_params->niter; + cp.spherical = (metric_type == faiss::METRIC_INNER_PRODUCT); faiss::Clustering clus(d, build_params->nlist, cp); clus.train(n, vectors.data_ptr(), *index_ptr); diff --git a/src/cpp/src/quake_index.cpp b/src/cpp/src/quake_index.cpp index e1d6697e..946292b2 100644 --- a/src/cpp/src/quake_index.cpp +++ b/src/cpp/src/quake_index.cpp @@ -39,6 +39,8 @@ shared_ptr QuakeIndex::build(Tensor x, Tensor ids, shared_ptrnum_workers << " workers, NUMA: " << (build_params->use_numa ? "enabled" : "disabled") << " and metric " << metric_ << std::endl; query_coordinator_ = std::make_shared(parent_, partition_manager_, maintenance_policy_, diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 0a721568..10b192ba 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -99,63 +99,61 @@ void QueryCoordinator::allocate_core_resources(int core_idx, } -void QueryCoordinator::merge_worker_fn(int mid) -{ +// The heart of it: one function, two instantiations. +template +void QueryCoordinator::merge_worker_fn(int mid) { auto& MR = merge_res_[mid]; ResultJob rj; - while (!stop_workers_) { + while (true) { MR.queue.wait_dequeue(rj); + if (rj.query_id == -1) // poison pill + return; - if (rj.query_id == -1) break; // poison-pill + // single cast, based on the Compare template + using Handler = typename faiss::HeapBlockResultHandler::SingleResultHandler; + auto* h = static_cast(MR.handlers[rj.query_id]); - /* ---- grab the pre-built handler ---------------------------------- */ - if (metric_ == faiss::METRIC_INNER_PRODUCT) { - using H = faiss::HeapBlockResultHandler< - faiss::CMin>::SingleResultHandler; - auto* h = static_cast(MR.handlers[rj.query_id]); - for (size_t i = 0; i < rj.distances.size(); ++i) - h->add_result(rj.distances[i], rj.indices[i]); - query_dist_pivots_[rj.query_id].store(h->threshold, - std::memory_order_relaxed); - } else { - using H = faiss::HeapBlockResultHandler< - faiss::CMax>::SingleResultHandler; - auto* h = static_cast(MR.handlers[rj.query_id]); - for (size_t i = 0; i < rj.distances.size(); ++i) - h->add_result(rj.distances[i], rj.indices[i]); - query_dist_pivots_[rj.query_id].store(h->threshold, - std::memory_order_relaxed); + // feed all partial results + for (size_t i = 0; i < rj.distances.size(); ++i) { + h->add_result(rj.distances[i], rj.indices[i]); } + // update pivot + query_dist_pivots_[rj.query_id].store(h->threshold, + std::memory_order_relaxed); - /* ---- bookkeeping -------------------------------------------------- */ + // once all ranks for this query are in, finalize & sort if (!job_flags_[rj.query_id][rj.rank]) { job_flags_[rj.query_id][rj.rank] = true; - --per_query_total_left_[rj.query_id]; + if (--per_query_total_left_[rj.query_id] == 0) { + h->end(); + + // pack into pairs for sorting + int k = h->k; + std::vector> result; + result.reserve(k); + for (int i = 0; i < k; ++i) { + result.emplace_back(h->heap_dis[i], h->heap_ids[i]); + } - if (per_query_total_left_[rj.query_id] == 0) { - if (metric_ == faiss::METRIC_INNER_PRODUCT) { - using H = faiss::HeapBlockResultHandler< - faiss::CMin>::SingleResultHandler; - static_cast(MR.handlers[rj.query_id])->end(); - } else { - using H = faiss::HeapBlockResultHandler< - faiss::CMax>::SingleResultHandler; - static_cast(MR.handlers[rj.query_id])->end(); + // for CMin (inner-product) we want descending distances + // for CMax (L2) we want ascending distances + auto cmp = [](auto& a, auto& b) { + return Compare::cmp(a.first, b.first); + }; + std::sort(result.begin(), result.end(), cmp); + + // write them back + for (int i = 0; i < k; ++i) { + h->heap_dis[i] = result[i].first; + h->heap_ids[i] = result[i].second; } } - --total_left_; } - - // std::cout << "[merge_worker_fn] Query ID: " << rj.query_id - // << ", Rank: " << rj.rank - // << ", Distances: " << rj.distances.size() - // << ", Indices: " << rj.indices.size() - // << ", Total left: " << total_left_.load() << std::endl; + --total_left_; } } - void QueryCoordinator::partition_scan_worker_fn(int core_index) { CoreResources &res = core_resources_[core_index]; int numa_node = 0; @@ -394,17 +392,13 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, // gather queries float *qptr = nullptr; - if (job.scan_all) { - qptr = nr.local_query_buffer; - } else { - float *dst = res.batch_queries; - for (int64_t i = 0; i < Q; ++i) { - int qid = (*job.query_ids)[i]; - const float *src = nr.local_query_buffer + size_t(qid) * D; - std::memcpy(dst + i * D, src, D * sizeof(float)); - } - qptr = dst; + float *dst = res.batch_queries; + for (int64_t i = 0; i < Q; ++i) { + int qid = (*job.query_ids)[i]; + const float *src = nr.local_query_buffer + size_t(qid) * D; + std::memcpy(dst + i * D, src, D * sizeof(float)); } + qptr = dst; vector *> pivots; pivots.resize(job.num_queries); @@ -735,24 +729,6 @@ QueryCoordinator::aggregate_scan_results(int64_t nQ, shared_ptr timing, Tensor out_ids, Tensor out_dists) { - - for (int64_t q = 0; q < nQ; ++q) { - int merge_worker_idx = q % num_merge_workers_; - MergeResources& mr = merge_res_[merge_worker_idx]; - - if (q < static_cast(mr.handlers.size()) && mr.handlers[q] != nullptr) { - if (metric_ == faiss::METRIC_INNER_PRODUCT) { - using H = faiss::HeapBlockResultHandler< - faiss::CMin>::SingleResultHandler; - static_cast(mr.handlers[q])->end(); - } else { - using H = faiss::HeapBlockResultHandler< - faiss::CMax>::SingleResultHandler; - static_cast(mr.handlers[q])->end(); - } - } - } - auto id_acc = out_ids.accessor(); auto d_acc = out_dists.accessor(); @@ -854,8 +830,8 @@ std::shared_ptr QueryCoordinator::worker_scan( duration_cast(s5 - s4).count(); res->timing_info->result_aggregate_time_ns = duration_cast(s6 - s5).count(); - - // retrieve the final values of the per-core resource timers; + // + // // retrieve the final values of the per-core resource timers; for (int i = 0; i < num_workers_; ++i) { core_wait_time_ns[i] = core_resources_[i].wait_time_ns - core_wait_time_ns[i]; core_process_time_ns[i] = core_resources_[i].process_time_ns - core_process_time_ns[i]; @@ -866,7 +842,7 @@ std::shared_ptr QueryCoordinator::worker_scan( } - // print out the per-core resource timers; + // // print out the per-core resource timers; for (int i = 0; i < num_workers_; ++i) { std::cout << "[QueryCoordinator::worker_scan] Core " << i << ": " << "job_counter=" << core_resources_[i].job_counter << " " @@ -915,12 +891,22 @@ void QueryCoordinator::initialize_workers(int num_workers, int num_merge_workers worker_threads_[i] = std::thread(&QueryCoordinator::partition_scan_worker_fn, this, i); } + merge_threads_.resize(num_merge_workers_); merge_res_.resize(num_merge_workers_); - for (int i = 0; i < num_merge_workers; i++) { - if (!set_thread_affinity(i + num_workers)) { - std::cout << "[QueryCoordinator::initialize_workers] Failed to set thread affinity on core " << i + num_workers << std::endl; + if (metric_ == faiss::METRIC_INNER_PRODUCT) { + // CMin: we want largest-inner-product first + for (int i = 0; i < num_merge_workers_; ++i) { + merge_threads_[i] = std::thread( + &QueryCoordinator::merge_worker_fn>, + this, i); + } + } else { + // CMax: we want smallest-L2 first + for (int i = 0; i < num_merge_workers_; ++i) { + merge_threads_[i] = std::thread( + &QueryCoordinator::merge_worker_fn>, + this, i); } - merge_threads_.emplace_back(&QueryCoordinator::merge_worker_fn, this, i); } workers_initialized_ = true; @@ -1072,6 +1058,7 @@ shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partitio float *list_vectors = (float *) partition_manager_->partition_store_->get_codes(pi); int64_t *list_ids = (int64_t *) partition_manager_->partition_store_->get_ids(pi); int64_t list_size = partition_manager_->partition_store_->list_size(pi); + scan_list(query_vec, list_vectors, list_ids, @@ -1079,7 +1066,7 @@ shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partitio dimension, *topk_buf, metric_, - query_radius); + NULL); scanned_ids.push_back(pi); float curr_radius = topk_buf->get_kth_distance(); diff --git a/src/python/datasets/ann_datasets.py b/src/python/datasets/ann_datasets.py index a7ba1459..44e7bdc9 100644 --- a/src/python/datasets/ann_datasets.py +++ b/src/python/datasets/ann_datasets.py @@ -244,6 +244,106 @@ def load_ground_truth(self) -> Union[np.ndarray, torch.Tensor]: return torch.from_numpy(ids).long() +class Wiki13M(Dataset): + def __init__(self, download_dir: Union[str, Path] = DEFAULT_DOWNLOAD_DIR): + self.download_dir = to_path(download_dir) + self.data_dir = self.download_dir / "wiki13m" + self.downloaded = False + self.metric = "ip" + + def is_downloaded(self) -> bool: + base = self.data_dir / "wiki.npy" + query = self.data_dir / "wiki_queries.npy" + gt = self.data_dir / "wiki_gt.npy" + return base.exists() and query.exists() and gt.exists() + + def download(self, overwrite: bool = False): + pass + + def load_vectors(self) -> Union[np.ndarray, torch.Tensor]: + fname = self.data_dir / "wiki.npy" + return torch.from_numpy(np.load(fname)).to(torch.float32) + + def load_queries(self) -> Union[np.ndarray, torch.Tensor]: + fname = self.data_dir / "wiki_queries.npy" + return torch.from_numpy(np.load(fname)).to(torch.float32) + + def load_ground_truth(self) -> Union[np.ndarray, torch.Tensor]: + fname = self.data_dir / "wiki_gt.npy" + return torch.from_numpy(np.load(fname)).long() + + +class WikiCohere1M(Dataset): + def __init__(self, download_dir: Union[str, Path] = DEFAULT_DOWNLOAD_DIR): + self.download_dir = to_path(download_dir) + self.data_dir = self.download_dir / "wikipedia_cohere" + self.downloaded = False + self.metric = "ip" + + def is_downloaded(self) -> bool: + base = self.data_dir / "wikipedia_base.bin.crop_nb_1000000" + query = self.data_dir / "wikipedia_query.bin" + gt = self.data_dir / " wikipedia-1M" + return base.exists() and query.exists() and gt.exists() + + def download(self, overwrite: bool = False): + pass + + def load_vectors(self) -> Union[np.ndarray, torch.Tensor]: + fname = self.data_dir / "wikipedia_base.bin.crop_nb_1000000" + n, d = map(int, np.fromfile(fname, dtype="uint32", count=2)) + return torch.from_numpy(np.fromfile(fname, dtype=np.float32, offset=8).reshape((n, d))) + + def load_queries(self) -> Union[np.ndarray, torch.Tensor]: + fname = self.data_dir / "wikipedia_query.bin" + n, d = map(int, np.fromfile(fname, dtype="uint32", count=2)) + return torch.from_numpy(np.fromfile(fname, dtype=np.float32, offset=8).reshape((n, d))) + + def load_ground_truth(self) -> Union[np.ndarray, torch.Tensor]: + fname = self.data_dir / "wikipedia-1M" + n, d = map(int, np.fromfile(fname, dtype="uint32", count=2)) + assert os.stat(fname).st_size == 8 + n * d * (4 + 4) + f = open(fname, "rb") + f.seek(4 + 4) + ids = np.fromfile(f, dtype="int32", count=n * d).reshape(n, d) + return torch.from_numpy(ids).long() + +class T2I1M(Dataset): + def __init__(self, download_dir: Union[str, Path] = DEFAULT_DOWNLOAD_DIR): + self.download_dir = to_path(download_dir) + self.data_dir = self.download_dir / "text2image1B" + self.downloaded = False + self.metric = "ip" + + def is_downloaded(self) -> bool: + base = self.data_dir / "base.1B.fbin.crop_nb_1000000" + query = self.data_dir / "query.heldout.30K.fbin" + gt = self.data_dir / "gt100-heldout.30K.fbin" + return base.exists() and query.exists() and gt.exists() + + def download(self, overwrite: bool = False): + pass + + def load_vectors(self) -> Union[np.ndarray, torch.Tensor]: + fname = self.data_dir / "base.1B.fbin.crop_nb_1000000" + n, d = map(int, np.fromfile(fname, dtype="uint32", count=2)) + return torch.from_numpy(np.fromfile(fname, dtype=np.float32, offset=8).reshape((n, d))) + + def load_queries(self) -> Union[np.ndarray, torch.Tensor]: + fname = self.data_dir / "query.heldout.30K.fbin" + n, d = map(int, np.fromfile(fname, dtype="uint32", count=2)) + return torch.from_numpy(np.fromfile(fname, dtype=np.float32, offset=8).reshape((n, d))) + + def load_ground_truth(self) -> Union[np.ndarray, torch.Tensor]: + fname = self.data_dir / "gt100-heldout.30K.fbin" + n, d = map(int, np.fromfile(fname, dtype="uint32", count=2)) + assert os.stat(fname).st_size == 8 + n * d * (4 + 4) + f = open(fname, "rb") + f.seek(4 + 4) + ids = np.fromfile(f, dtype="int32", count=n * d).reshape(n, d) + return torch.from_numpy(ids).long() + + def load_dataset( @@ -259,6 +359,12 @@ def load_dataset( dataset = MSTuring100m(download_dir=download_dir) elif name.lower() == "sift10m": dataset = Sift10m(download_dir=download_dir) + elif name.lower() == "wiki13m": + dataset = Wiki13M(download_dir=download_dir) + elif name.lower() == "t2i1m": + dataset = T2I1M(download_dir=download_dir) + elif name.lower() == "wikicohere1m": + dataset = WikiCohere1M(download_dir=download_dir) else: raise RuntimeError("Unimplemented dataset + " + name) diff --git a/test/experiments/osdi2025/experiment_runner.py b/test/experiments/osdi2025/experiment_runner.py index b51b8725..1cad31e1 100644 --- a/test/experiments/osdi2025/experiment_runner.py +++ b/test/experiments/osdi2025/experiment_runner.py @@ -13,6 +13,7 @@ from test.experiments.osdi2025.multi_level.run import run_experiment as run_multi_level from test.experiments.osdi2025.vary_levels.run import run_experiment as run_vary_levels from test.experiments.osdi2025.maintenance_ablation.run import run_experiment as run_ablation +from test.experiments.osdi2025.vary_batch_size.run import run_experiment as run_vary_batch_size EXPERIMENTS = { "kick_the_tires": run_kick_the_tires, @@ -23,6 +24,7 @@ "multi_level": run_multi_level, "vary_levels": run_vary_levels, "maintenance_ablation": run_ablation, + "vary_batch_size": run_vary_batch_size, } def main(): diff --git a/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml b/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml new file mode 100644 index 00000000..ead0177e --- /dev/null +++ b/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml @@ -0,0 +1,62 @@ +dataset: + name: wiki13m + # Instead of a single num_queries, we sweep over these batch sizes: +# query_batch_sizes: [1, 8, 16, 32, 64, 128, 256, 512] + num_queries: 4096 + query_batch_sizes: [1, 4, 16, 64, 256, 1024, 4096] + k: 100 + +trials: 3 +warmup: 1 +overwrite: true +force_rebuild: false + +indexes: + - name: Quake_Unbatched + index: Quake + build_params: + nc: 3500 + metric: ip + num_workers: 0 + use_numa: true + omp_num_threads_build: 8 + parent: + num_workers: 0 + search_params: + nprobe: 4 + batch_size: 128 + parent: + batched_scan: true + batch_size: 128 + batched_scan: false + + - name: Quake_Batched + index: Quake + build_params: + nc: 3500 + metric: ip + num_workers: 0 + omp_num_threads_build: 8 + use_numa: true + parent: + num_workers: 0 + search_params: + nprobe: 4 + batch_size: 128 + parent: + batched_scan: true + batch_size: 128 + batched_scan: true + + - name: FaissIVF + index: IVF + build_params: + nc: 3500 + metric: ip + omp_num_threads_build: 1 + search_params: + nprobe: 4 + omp_num_threads_search: 1 + +output: + results_csv: numa_query_batch_results.csv \ No newline at end of file diff --git a/test/experiments/osdi2025/vary_batch_size/run.py b/test/experiments/osdi2025/vary_batch_size/run.py new file mode 100644 index 00000000..ef927d15 --- /dev/null +++ b/test/experiments/osdi2025/vary_batch_size/run.py @@ -0,0 +1,178 @@ +import logging +from pathlib import Path +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt +import os +import faiss + +import test.experiments.osdi2025.experiment_utils as common_utils +from quake.utils import compute_recall +from quake.index_wrappers.faiss_ivf import FaissIVF +from quake.index_wrappers.faiss_hnsw import FaissHNSW +from quake.index_wrappers.quake import QuakeWrapper # type: ignore + +# optional wrappers +try: from quake.index_wrappers.scann import Scann +except ImportError: Scann = None +try: from quake.index_wrappers.diskann import DiskANNDynamic +except ImportError: DiskANNDynamic = None +try: from quake.index_wrappers.vamana import Vamana +except ImportError: Vamana = None + +INDEX_CLASSES = { + "Quake": QuakeWrapper, + "IVF": FaissIVF, + "HNSW": FaissHNSW, + "SCANN": Scann, + "DiskANN": DiskANNDynamic, + "SVS": Vamana, +} + +logger = logging.getLogger("numa_query_batch_orchestrator") + +def _set_faiss_threads(val: str, tag: str): + t = int(val) + faiss.omp_set_num_threads(t) + print(f"[{tag}] faiss.omp_set_num_threads({t})") + +def task_build_index(idx_cfg, ds_cfg, run_params, idx_file: Path): + name = idx_cfg["name"] + print(f"[{name} BUILD] PID={os.getpid()} -> {idx_file}") + bp = dict(idx_cfg.get("build_params", {})) + omp_build = str(bp.pop("omp_num_threads_build", "1")) + _set_faiss_threads(omp_build, f"{name} BUILD") + + # only need 1 query vector to build + base_vecs, _, _ = common_utils.load_data(ds_cfg["name"], nq_override=1) + Cls = INDEX_CLASSES[idx_cfg["index"]] + idx = common_utils.prepare_wrapper_index( + Cls, idx_file, base_vecs, bp, run_params["force_rebuild_indices"] + ) + del base_vecs + if idx is None: + return {"error": "build failed"} + return {"status": "success", "index_file_path": str(idx_file)} + +def task_search_index(idx_cfg, ds_cfg, run_params, idx_file: Path, batch_size: int): + name = idx_cfg["name"] + itype = idx_cfg["index"] + print(f"[{name} SEARCH bs={batch_size}] Loading index") + bp = dict(idx_cfg.get("build_params", {})) + sp = dict(idx_cfg.get("search_params", {})) + omp_search = str(sp.pop("omp_num_threads_search", "1")) + _set_faiss_threads(omp_search, f"{name} SEARCH") + + # load all nq queries & gt + _, all_qvecs, all_gt = common_utils.load_data(ds_cfg["name"], nq_override=ds_cfg["num_queries"]) + nq = all_qvecs.shape[0] + Cls = INDEX_CLASSES[itype] + inst = Cls() + load_kwargs = { + k: bp[k] for k in ("num_workers","use_numa","num_merge_workers","parent") if k in bp + } + inst.load(str(idx_file), **load_kwargs) + + # warmup on a single chunk + warmup_chunk = all_qvecs[:batch_size] + for _ in range(run_params["num_warmup"]): + _ = inst.search(warmup_chunk, run_params["k_val"], **sp) + + trial_total_latencies = [] + trial_recalls = [] + + for t in range(run_params["num_trials"]): + # iterate over chunks, summing latency + total_ns = 0 + ids_list = [] # collect results per chunk + for i in range(0, nq, batch_size): + chunk = all_qvecs[i : min(i+batch_size, nq)] + res = inst.search(chunk, run_params["k_val"], **sp) + ti = getattr(res, "timing_info", None) + ns = getattr(ti, "total_time_ns", None) or getattr(ti, "child_total_time_ns", 0) + total_ns += ns + ids_list.append(res.ids) + + total_ms = total_ns / 1e6 + trial_total_latencies.append(total_ms) + + # concatenate all ids and compute recall over nq + all_ids = np.vstack(ids_list) # shape (nq, k) + rec = float(compute_recall(all_ids, all_gt, run_params["k_val"]).mean()) + trial_recalls.append(rec) + + mean_lat = float(np.mean(trial_total_latencies)) + std_lat = float(np.std(trial_total_latencies)) + mean_rec = float(np.mean(trial_recalls)) + std_rec = float(np.std(trial_recalls)) + + return { + "index": name, + "query_batch_size": batch_size, + "nq": nq, + "mean_total_latency_ms": mean_lat, + "std_total_latency_ms": std_lat, + "mean_recall": mean_rec, + "std_recall": std_rec + } + +def run_experiment(cfg_path, out_dir): + logging.basicConfig(level=logging.INFO) + cfg = common_utils.load_config(cfg_path) + out = Path(out_dir); out.mkdir(exist_ok=True, parents=True) + + ds_cfg = cfg["dataset"] + batch_sizes = ds_cfg["query_batch_sizes"] + run_params = { + "num_trials": cfg.get("trials",3), + "num_warmup": cfg.get("warmup",1), + "k_val": ds_cfg["k"], + "force_rebuild_indices": cfg.get("force_rebuild",False) + } + + all_rows = [] + # build once per index + idx_store = out/"indices" + idx_store.mkdir(exist_ok=True) + for idx_cfg in cfg["indexes"]: + idx_file = idx_store/f"{idx_cfg['name']}.bin" + br = task_build_index(idx_cfg, ds_cfg, run_params, idx_file) + if br.get("error"): + logger.error(f"Build failed for {idx_cfg['name']}: {br['error']}") + + # now search for each batch_size + for bs in batch_sizes: + logger.info(f"--- Running batch size = {bs} ---") + for idx_cfg in cfg["indexes"]: + idx_file = idx_store/f"{idx_cfg['name']}.bin" + row = task_search_index(idx_cfg, ds_cfg, run_params, idx_file, bs) + all_rows.append(row) + + df = pd.DataFrame(all_rows) + # compute QPS = nq*1000 / mean_total_latency_ms + df["QPS"] = df["nq"] * 1000.0 / df["mean_total_latency_ms"] + df.to_csv(out/cfg["output"]["results_csv"], index=False) + logger.info(f"Wrote results to {cfg['output']['results_csv']}") + + # plot only points with recall ≥ 0.9 + # plot_df = df[df["mean_recall"] >= 0.9] + plt.figure(figsize=(8,6)) + for name, grp in df.groupby("index"): + grp = grp.sort_values("query_batch_size") + plt.errorbar( + grp["query_batch_size"], + grp["QPS"], + yerr=None, + marker="o", + label=name + ) + plt.xscale("log") + plt.xlabel("Query Batch Size") + plt.ylabel("QPS (@ Recall ≥ 0.9)") + plt.title(f"QPS vs Batch Size ({ds_cfg['name']}, k={ds_cfg['k']})") + plt.legend(bbox_to_anchor=(1.05,1), loc="upper left") + plt.grid(True, which="both", ls="--", alpha=0.5) + plt.tight_layout(rect=[0,0,0.8,1]) + plt.savefig(out/f"qps_vs_batch_{ds_cfg['name']}.png") + plt.close() + logger.info("Saved QPS vs Batch Size plot to " + str(out/f"qps_vs_batch_{ds_cfg['name']}.png")) \ No newline at end of file From 9b394491f492b030ec01133dfcbec963c8095379 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 27 May 2025 14:46:37 -0500 Subject: [PATCH 283/323] add batch size exp --- .../vary_batch_size/configs/wiki_single_thread.yaml | 3 +++ test/experiments/osdi2025/vary_batch_size/run.py | 9 +++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml b/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml index ead0177e..c3f77323 100644 --- a/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml +++ b/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml @@ -14,6 +14,7 @@ force_rebuild: false indexes: - name: Quake_Unbatched index: Quake + index_file: /Users/jason/projects/quake/test/experiments/osdi2025/vary_batch_size/indices/Quake_3500.bin build_params: nc: 3500 metric: ip @@ -32,6 +33,7 @@ indexes: - name: Quake_Batched index: Quake + index_file: /Users/jason/projects/quake/test/experiments/osdi2025/vary_batch_size/indices/Quake_3500.bin build_params: nc: 3500 metric: ip @@ -50,6 +52,7 @@ indexes: - name: FaissIVF index: IVF + index_file: /Users/jason/projects/quake/test/experiments/osdi2025/vary_batch_size/indices/FaissIVF.bin build_params: nc: 3500 metric: ip diff --git a/test/experiments/osdi2025/vary_batch_size/run.py b/test/experiments/osdi2025/vary_batch_size/run.py index ef927d15..46491143 100644 --- a/test/experiments/osdi2025/vary_batch_size/run.py +++ b/test/experiments/osdi2025/vary_batch_size/run.py @@ -135,8 +135,9 @@ def run_experiment(cfg_path, out_dir): idx_store = out/"indices" idx_store.mkdir(exist_ok=True) for idx_cfg in cfg["indexes"]: - idx_file = idx_store/f"{idx_cfg['name']}.bin" - br = task_build_index(idx_cfg, ds_cfg, run_params, idx_file) + idx_path = Path(idx_cfg.get("index_file", idx_store/f"{idx_cfg['name']}.bin")) + idx_path.parent.mkdir(parents=True, exist_ok=True) + br = task_build_index(idx_cfg, ds_cfg, run_params, idx_path) if br.get("error"): logger.error(f"Build failed for {idx_cfg['name']}: {br['error']}") @@ -144,8 +145,8 @@ def run_experiment(cfg_path, out_dir): for bs in batch_sizes: logger.info(f"--- Running batch size = {bs} ---") for idx_cfg in cfg["indexes"]: - idx_file = idx_store/f"{idx_cfg['name']}.bin" - row = task_search_index(idx_cfg, ds_cfg, run_params, idx_file, bs) + idx_path = Path(idx_cfg.get("index_file", idx_store/f"{idx_cfg['name']}.bin")) + row = task_search_index(idx_cfg, ds_cfg, run_params, idx_path, bs) all_rows.append(row) df = pd.DataFrame(all_rows) From 79a5c2cf6c9a4e1fe640ead5472835ef637645a9 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 27 May 2025 14:47:51 -0500 Subject: [PATCH 284/323] add batch size exp --- .../vary_batch_size/configs/wiki_single_thread.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml b/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml index c3f77323..bf3fd6aa 100644 --- a/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml +++ b/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml @@ -14,7 +14,7 @@ force_rebuild: false indexes: - name: Quake_Unbatched index: Quake - index_file: /Users/jason/projects/quake/test/experiments/osdi2025/vary_batch_size/indices/Quake_3500.bin + index_file: /opt/quake/data/vary_batch_sizes/indices/Quake_3500.bin build_params: nc: 3500 metric: ip @@ -33,7 +33,7 @@ indexes: - name: Quake_Batched index: Quake - index_file: /Users/jason/projects/quake/test/experiments/osdi2025/vary_batch_size/indices/Quake_3500.bin + index_file: /opt/quake/data/vary_batch_sizes/indices/Quake_3500.bin build_params: nc: 3500 metric: ip @@ -52,7 +52,7 @@ indexes: - name: FaissIVF index: IVF - index_file: /Users/jason/projects/quake/test/experiments/osdi2025/vary_batch_size/indices/FaissIVF.bin + index_file: /opt/quake/data/vary_batch_sizes/indices/FaissIVF.bin build_params: nc: 3500 metric: ip From fd6ccb78a7a3916aecc2e612c14c26b6bade9790 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 27 May 2025 15:31:14 -0500 Subject: [PATCH 285/323] hide timers --- src/cpp/src/query_coordinator.cpp | 46 +++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 10b192ba..f6143f9e 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -842,29 +842,29 @@ std::shared_ptr QueryCoordinator::worker_scan( } - // // print out the per-core resource timers; - for (int i = 0; i < num_workers_; ++i) { - std::cout << "[QueryCoordinator::worker_scan] Core " << i << ": " - << "job_counter=" << core_resources_[i].job_counter << " " - << "queries_counter=" << core_resources_[i].queries_counter << " " - << "wait_time_ms=" << (float) core_wait_time_ns[i] / 1e6 << " " - << "scan_setup_time_ms=" << (float) core_scan_setup_time_ns[i] / 1e6 << " " - << "scan_time_ms=" << (float) core_scan_time_ns[i] / 1e6 << " " - << "scan_push_time_ms=" << (float) core_scan_push_time_ns[i] / 1e6 << " " - << "process_time_ms=" << (float) core_process_time_ns[i] / 1e6 << " " - << "process_preamble_time_ms=" << (float) core_process_preamble_time_ns[i] / 1e6 << " " - << "enqueue_time_ms=" << (float) core_enqueue_time_ns[i] / 1e6 << " " - << "job_time_ms=" << (float) core_job_time_ns[i] / 1e6 << std::endl; - } - - // print out the main thread timers; - std::cout << "[QueryCoordinator::worker_scan] Main thread: " - << "buffer_init_time_ms=" << (float) res->timing_info->buffer_init_time_ns / 1e6 << " " - << "copy_query_time_ms=" << (float) res->timing_info->copy_query_time_ns / 1e6 << " " - << "job_enqueue_time_ms=" << (float) res->timing_info->job_enqueue_time_ns / 1e6 << " " - << "job_wait_time_ms=" << (float) res->timing_info->job_wait_time_ns / 1e6 << " " - << "result_aggregate_time_ms=" << (float) res->timing_info->result_aggregate_time_ns / 1e6 - << std::endl; + // // // print out the per-core resource timers; + // for (int i = 0; i < num_workers_; ++i) { + // std::cout << "[QueryCoordinator::worker_scan] Core " << i << ": " + // << "job_counter=" << core_resources_[i].job_counter << " " + // << "queries_counter=" << core_resources_[i].queries_counter << " " + // << "wait_time_ms=" << (float) core_wait_time_ns[i] / 1e6 << " " + // << "scan_setup_time_ms=" << (float) core_scan_setup_time_ns[i] / 1e6 << " " + // << "scan_time_ms=" << (float) core_scan_time_ns[i] / 1e6 << " " + // << "scan_push_time_ms=" << (float) core_scan_push_time_ns[i] / 1e6 << " " + // << "process_time_ms=" << (float) core_process_time_ns[i] / 1e6 << " " + // << "process_preamble_time_ms=" << (float) core_process_preamble_time_ns[i] / 1e6 << " " + // << "enqueue_time_ms=" << (float) core_enqueue_time_ns[i] / 1e6 << " " + // << "job_time_ms=" << (float) core_job_time_ns[i] / 1e6 << std::endl; + // } + // + // // print out the main thread timers; + // std::cout << "[QueryCoordinator::worker_scan] Main thread: " + // << "buffer_init_time_ms=" << (float) res->timing_info->buffer_init_time_ns / 1e6 << " " + // << "copy_query_time_ms=" << (float) res->timing_info->copy_query_time_ns / 1e6 << " " + // << "job_enqueue_time_ms=" << (float) res->timing_info->job_enqueue_time_ns / 1e6 << " " + // << "job_wait_time_ms=" << (float) res->timing_info->job_wait_time_ns / 1e6 << " " + // << "result_aggregate_time_ms=" << (float) res->timing_info->result_aggregate_time_ns / 1e6 + // << std::endl; return res; } From 3a73c716a48b857cc599a70c98f4e6d100ac8a09 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 27 May 2025 15:51:51 -0500 Subject: [PATCH 286/323] update wiki vary batch size --- .../configs/wiki_single_thread.yaml | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml b/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml index bf3fd6aa..244e5fa8 100644 --- a/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml +++ b/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml @@ -2,8 +2,8 @@ dataset: name: wiki13m # Instead of a single num_queries, we sweep over these batch sizes: # query_batch_sizes: [1, 8, 16, 32, 64, 128, 256, 512] - num_queries: 4096 - query_batch_sizes: [1, 4, 16, 64, 256, 1024, 4096] + num_queries: 8192 + query_batch_sizes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192] k: 100 trials: 3 @@ -18,11 +18,11 @@ indexes: build_params: nc: 3500 metric: ip - num_workers: 0 + num_workers: 16 use_numa: true omp_num_threads_build: 8 parent: - num_workers: 0 + num_workers: 4 search_params: nprobe: 4 batch_size: 128 @@ -37,11 +37,11 @@ indexes: build_params: nc: 3500 metric: ip - num_workers: 0 + num_workers: 16 omp_num_threads_build: 8 use_numa: true parent: - num_workers: 0 + num_workers: 4 search_params: nprobe: 4 batch_size: 128 @@ -59,7 +59,20 @@ indexes: omp_num_threads_build: 1 search_params: nprobe: 4 - omp_num_threads_search: 1 + omp_num_threads_search: 16 + + - name: FaissHNSW + index: HNSW + index_file: /opt/quake/data/vary_batch_sizes/indices/FaissHNSW.bin + build_params: + m: 64 + ef_construction: 128 + metric: ip + omp_num_threads_build: 1 + search_params: + ef_search: 16 + omp_num_threads_search: 16 + output: results_csv: numa_query_batch_results.csv \ No newline at end of file From d99aa63474c0845a1cc88b81e9ca73d14eaedf18 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 27 May 2025 18:13:50 -0500 Subject: [PATCH 287/323] update wiki vary batch size --- src/cpp/src/query_coordinator.cpp | 13 ++ .../configs/wiki_single_thread.yaml | 4 +- .../osdi2025/vary_batch_size/run.py | 157 ++++++++++++------ 3 files changed, 121 insertions(+), 53 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index f6143f9e..ec989d9d 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -258,6 +258,8 @@ void QueryCoordinator::process_scan_job(ScanJob job, void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, CoreResources &res, NUMAResources &nr) { + + auto start = std::chrono::high_resolution_clock::now(); // ensure buffers if (res.topk_buffer_pool.size() < 1) { res.topk_buffer_pool.resize(1); @@ -307,11 +309,22 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, metric_, query_dist_pivots_[job.query_id].load(std::memory_order_relaxed)); + auto end = std::chrono::high_resolution_clock::now(); + + res.scan_time_ns += std::chrono::duration_cast(end - start).count(); + + start = std::chrono::high_resolution_clock::now(); + // If scan_list completes, enqueue its results auto tv = buf->get_topk(false); auto ti = buf->get_topk_indices(false); enqueue_result_job(ResultJob{job.query_id, job.rank, std::move(tv), std::move(ti)}); + end = std::chrono::high_resolution_clock::now(); + res.enqueue_time_ns += std::chrono::duration_cast(end - start).count(); + + + } catch (const std::exception& e) { std::cerr << "[QueryCoordinator::handle_nonbatched_job] Exception during scan for partition " << job.partition_id << ", query " << job.query_id << ": " << e.what() diff --git a/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml b/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml index 244e5fa8..29028fa7 100644 --- a/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml +++ b/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml @@ -3,7 +3,7 @@ dataset: # Instead of a single num_queries, we sweep over these batch sizes: # query_batch_sizes: [1, 8, 16, 32, 64, 128, 256, 512] num_queries: 8192 - query_batch_sizes: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192] + query_batch_sizes: [1, 4, 16, 64, 256, 1024, 4096, 8192] k: 100 trials: 3 @@ -30,6 +30,7 @@ indexes: batched_scan: true batch_size: 128 batched_scan: false + omp_num_threads_search: 1 - name: Quake_Batched index: Quake @@ -49,6 +50,7 @@ indexes: batched_scan: true batch_size: 128 batched_scan: true + omp_num_threads_search: 1 - name: FaissIVF index: IVF diff --git a/test/experiments/osdi2025/vary_batch_size/run.py b/test/experiments/osdi2025/vary_batch_size/run.py index 46491143..b9c4b4cb 100644 --- a/test/experiments/osdi2025/vary_batch_size/run.py +++ b/test/experiments/osdi2025/vary_batch_size/run.py @@ -43,7 +43,9 @@ def task_build_index(idx_cfg, ds_cfg, run_params, idx_file: Path): omp_build = str(bp.pop("omp_num_threads_build", "1")) _set_faiss_threads(omp_build, f"{name} BUILD") - # only need 1 query vector to build + if idx_file.exists() and not run_params["force_rebuild_indices"]: + return {"status": "skipped", "index_file_path": str(idx_file)} + base_vecs, _, _ = common_utils.load_data(ds_cfg["name"], nq_override=1) Cls = INDEX_CLASSES[idx_cfg["index"]] idx = common_utils.prepare_wrapper_index( @@ -64,29 +66,33 @@ def task_search_index(idx_cfg, ds_cfg, run_params, idx_file: Path, batch_size: i _set_faiss_threads(omp_search, f"{name} SEARCH") # load all nq queries & gt - _, all_qvecs, all_gt = common_utils.load_data(ds_cfg["name"], nq_override=ds_cfg["num_queries"]) + _, all_qvecs, all_gt = common_utils.load_data( + ds_cfg["name"], nq_override=ds_cfg["num_queries"] + ) nq = all_qvecs.shape[0] + Cls = INDEX_CLASSES[itype] inst = Cls() load_kwargs = { - k: bp[k] for k in ("num_workers","use_numa","num_merge_workers","parent") if k in bp + k: bp[k] + for k in ("num_workers", "use_numa", "num_merge_workers", "parent") + if k in bp } inst.load(str(idx_file), **load_kwargs) - # warmup on a single chunk - warmup_chunk = all_qvecs[:batch_size] + # warmup on one chunk + warmup = all_qvecs[:batch_size] for _ in range(run_params["num_warmup"]): - _ = inst.search(warmup_chunk, run_params["k_val"], **sp) + _ = inst.search(warmup, run_params["k_val"], **sp) - trial_total_latencies = [] + trial_latencies = [] trial_recalls = [] - for t in range(run_params["num_trials"]): - # iterate over chunks, summing latency + for _ in range(run_params["num_trials"]): total_ns = 0 - ids_list = [] # collect results per chunk + ids_list = [] for i in range(0, nq, batch_size): - chunk = all_qvecs[i : min(i+batch_size, nq)] + chunk = all_qvecs[i : min(i + batch_size, nq)] res = inst.search(chunk, run_params["k_val"], **sp) ti = getattr(res, "timing_info", None) ns = getattr(ti, "total_time_ns", None) or getattr(ti, "child_total_time_ns", 0) @@ -94,86 +100,133 @@ def task_search_index(idx_cfg, ds_cfg, run_params, idx_file: Path, batch_size: i ids_list.append(res.ids) total_ms = total_ns / 1e6 - trial_total_latencies.append(total_ms) + trial_latencies.append(total_ms) - # concatenate all ids and compute recall over nq - all_ids = np.vstack(ids_list) # shape (nq, k) + all_ids = np.vstack(ids_list) rec = float(compute_recall(all_ids, all_gt, run_params["k_val"]).mean()) trial_recalls.append(rec) - mean_lat = float(np.mean(trial_total_latencies)) - std_lat = float(np.std(trial_total_latencies)) - mean_rec = float(np.mean(trial_recalls)) - std_rec = float(np.std(trial_recalls)) - return { - "index": name, - "query_batch_size": batch_size, - "nq": nq, - "mean_total_latency_ms": mean_lat, - "std_total_latency_ms": std_lat, - "mean_recall": mean_rec, - "std_recall": std_rec + "mean_total_latency_ms": float(np.mean(trial_latencies)), + "std_total_latency_ms": float(np.std(trial_latencies)), + "mean_recall": float(np.mean(trial_recalls)), + "std_recall": float(np.std(trial_recalls)), + "nq": nq, + "query_batch_size": batch_size, } def run_experiment(cfg_path, out_dir): logging.basicConfig(level=logging.INFO) cfg = common_utils.load_config(cfg_path) - out = Path(out_dir); out.mkdir(exist_ok=True, parents=True) + out = Path(out_dir); out.mkdir(parents=True, exist_ok=True) ds_cfg = cfg["dataset"] batch_sizes = ds_cfg["query_batch_sizes"] run_params = { - "num_trials": cfg.get("trials",3), - "num_warmup": cfg.get("warmup",1), - "k_val": ds_cfg["k"], - "force_rebuild_indices": cfg.get("force_rebuild",False) + "num_trials": cfg.get("trials", 3), + "num_warmup": cfg.get("warmup", 1), + "k_val": ds_cfg["k"], + "force_rebuild_indices": cfg.get("force_rebuild", False), + "enable_glances": cfg.get("enable_glances_monitoring", False), } + # prepare directories + process_logs_dir = out / "process_logs"; process_logs_dir.mkdir(exist_ok=True) + index_store_dir = out / "indices"; index_store_dir.mkdir(exist_ok=True) + all_rows = [] - # build once per index - idx_store = out/"indices" - idx_store.mkdir(exist_ok=True) + + # === BUILD TASKS === for idx_cfg in cfg["indexes"]: - idx_path = Path(idx_cfg.get("index_file", idx_store/f"{idx_cfg['name']}.bin")) + name = idx_cfg["name"] + idx_path = Path(idx_cfg.get("index_file", index_store_dir/f"{name}.bin")) idx_path.parent.mkdir(parents=True, exist_ok=True) - br = task_build_index(idx_cfg, ds_cfg, run_params, idx_path) - if br.get("error"): - logger.error(f"Build failed for {idx_cfg['name']}: {br['error']}") - # now search for each batch_size + build_log = process_logs_dir / f"{name}_build.log" + build_env = idx_cfg.get("build_env_vars", {}) + timeout = idx_cfg.get("process_timeout", cfg.get("default_process_timeout", 7200)) + + build_res = common_utils.run_operation_in_process( + task_build_index, + (idx_cfg, ds_cfg, run_params, idx_path), + env_vars=build_env, + log_file_path=str(build_log), + process_name=f"BuildTask_{name}", + timeout_seconds=timeout, + enable_glances=run_params["enable_glances"] + ) + + # check build result + data = build_res.get("data", {}) + if build_res.get("status") != "success" or data.get("error"): + logger.error(f"[BUILD FAILED] {name}: {data.get('error', 'unknown')}") + else: + logger.info(f"[BUILD OK] {name} → {data.get('index_file_path')} ({data.get('status')})") + + # === SEARCH TASKS === for bs in batch_sizes: - logger.info(f"--- Running batch size = {bs} ---") for idx_cfg in cfg["indexes"]: - idx_path = Path(idx_cfg.get("index_file", idx_store/f"{idx_cfg['name']}.bin")) - row = task_search_index(idx_cfg, ds_cfg, run_params, idx_path, bs) + name = idx_cfg["name"] + idx_path = Path(idx_cfg.get("index_file", index_store_dir/f"{name}.bin")) + + search_log = process_logs_dir / f"{name}_search_bs{bs}.log" + search_env = idx_cfg.get("search_env_vars", {}) + timeout = idx_cfg.get("process_timeout", cfg.get("default_process_timeout", 7200)) + + search_res = common_utils.run_operation_in_process( + task_search_index, + (idx_cfg, ds_cfg, run_params, idx_path, bs), + env_vars=search_env, + log_file_path=str(search_log), + process_name=f"SearchTask_{name}_bs{bs}", + timeout_seconds=timeout, + enable_glances=run_params["enable_glances"] + ) + + if search_res.get("status") == "success": + data = search_res.get("data", {}) + if data.get("error"): + row = {"index": name, "query_batch_size": bs, "error": data["error"]} + logger.error(f"[SEARCH ERROR] {name} bs={bs}: {data['error']}") + else: + row = { + "index": name, + **data + } + logger.info(f"[SEARCH OK] {name} bs={bs}: latency={data['mean_total_latency_ms']:.2f}ms, recall={data['mean_recall']:.3f}") + else: + err = search_res.get("data", {}).get("error", "process failed") + row = {"index": name, "query_batch_size": bs, "error": err} + logger.error(f"[SEARCH PROC FAIL] {name} bs={bs}: {err}") + all_rows.append(row) + # === AGGREGATE & PLOT === df = pd.DataFrame(all_rows) - # compute QPS = nq*1000 / mean_total_latency_ms + # compute QPS df["QPS"] = df["nq"] * 1000.0 / df["mean_total_latency_ms"] - df.to_csv(out/cfg["output"]["results_csv"], index=False) - logger.info(f"Wrote results to {cfg['output']['results_csv']}") + out_csv = out / cfg["output"]["results_csv"] + df.to_csv(out_csv, index=False) + logger.info(f"Wrote results to {out_csv}") - # plot only points with recall ≥ 0.9 - # plot_df = df[df["mean_recall"] >= 0.9] + # plot QPS vs batch size plt.figure(figsize=(8,6)) for name, grp in df.groupby("index"): grp = grp.sort_values("query_batch_size") plt.errorbar( grp["query_batch_size"], grp["QPS"], - yerr=None, marker="o", label=name ) - plt.xscale("log") + plt.xscale("log", base=2) plt.xlabel("Query Batch Size") - plt.ylabel("QPS (@ Recall ≥ 0.9)") + plt.ylabel("QPS") plt.title(f"QPS vs Batch Size ({ds_cfg['name']}, k={ds_cfg['k']})") plt.legend(bbox_to_anchor=(1.05,1), loc="upper left") plt.grid(True, which="both", ls="--", alpha=0.5) plt.tight_layout(rect=[0,0,0.8,1]) - plt.savefig(out/f"qps_vs_batch_{ds_cfg['name']}.png") + plot_path = out / f"qps_vs_batch_{ds_cfg['name']}.png" + plt.savefig(plot_path) plt.close() - logger.info("Saved QPS vs Batch Size plot to " + str(out/f"qps_vs_batch_{ds_cfg['name']}.png")) \ No newline at end of file + logger.info(f"Saved plot to {plot_path}") \ No newline at end of file From b1553d0deeee8a4f2f7cc6a1cbd20c40fb480c3c Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 27 May 2025 21:05:25 -0500 Subject: [PATCH 288/323] add baselines to batch experiment --- .../configs/wiki_single_thread.yaml | 39 +++++++++ .../osdi2025/vary_batch_size/run.py | 82 +++++++++++-------- 2 files changed, 85 insertions(+), 36 deletions(-) diff --git a/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml b/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml index 29028fa7..95d9f255 100644 --- a/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml +++ b/test/experiments/osdi2025/vary_batch_size/configs/wiki_single_thread.yaml @@ -75,6 +75,45 @@ indexes: ef_search: 16 omp_num_threads_search: 16 + - name: SCANN + index: SCANN + index_file: /opt/quake/data/vary_batch_sizes/indices/SCANN.bin + build_params: + num_leaves: 3500 + metric: dot_product + omp_num_threads_build: 16 + search_params: + leaves_to_search: 4 + omp_num_threads_search: 1 + n_threads: 16 + + - name: DiskANN + index: DiskANN + index_file: /opt/quake/data/vary_batch_sizes/indices/DiskANN.bin + build_params: + complexity: 128 + graph_degree: 64 + metric: mips + num_threads: 16 + omp_num_threads_build: 1 + search_params: + complexity: 128 + num_threads: 16 + omp_num_threads_search: 1 + + - name: SVS + index: SVS + index_file: /opt/quake/data/vary_batch_sizes/indices/SVS.bin + build_params: + graph_max_degree: 64 + alpha: 1.1 + window_size: 128 + metric: ip + num_threads: 16 + omp_num_threads_build: 1 + search_params: + search_window_size: 24 + omp_num_threads_search: 16 output: results_csv: numa_query_batch_results.csv \ No newline at end of file diff --git a/test/experiments/osdi2025/vary_batch_size/run.py b/test/experiments/osdi2025/vary_batch_size/run.py index b9c4b4cb..d30ec6f7 100644 --- a/test/experiments/osdi2025/vary_batch_size/run.py +++ b/test/experiments/osdi2025/vary_batch_size/run.py @@ -59,7 +59,7 @@ def task_build_index(idx_cfg, ds_cfg, run_params, idx_file: Path): def task_search_index(idx_cfg, ds_cfg, run_params, idx_file: Path, batch_size: int): name = idx_cfg["name"] itype = idx_cfg["index"] - print(f"[{name} SEARCH bs={batch_size}] Loading index") + print(f"[{name} SEARCH bs={batch_size}] PID={os.getpid()} Loading index") bp = dict(idx_cfg.get("build_params", {})) sp = dict(idx_cfg.get("search_params", {})) omp_search = str(sp.pop("omp_num_threads_search", "1")) @@ -123,16 +123,29 @@ def run_experiment(cfg_path, out_dir): ds_cfg = cfg["dataset"] batch_sizes = ds_cfg["query_batch_sizes"] run_params = { - "num_trials": cfg.get("trials", 3), - "num_warmup": cfg.get("warmup", 1), - "k_val": ds_cfg["k"], - "force_rebuild_indices": cfg.get("force_rebuild", False), - "enable_glances": cfg.get("enable_glances_monitoring", False), + "num_trials": cfg.get("trials", 3), + "num_warmup": cfg.get("warmup", 1), + "k_val": ds_cfg["k"], + "force_rebuild_indices": cfg.get("force_rebuild", False), + "force_overwrite": cfg.get("overwrite", False), + "enable_glances": cfg.get("enable_glances_monitoring", False), } # prepare directories - process_logs_dir = out / "process_logs"; process_logs_dir.mkdir(exist_ok=True) - index_store_dir = out / "indices"; index_store_dir.mkdir(exist_ok=True) + process_logs_dir = out / "process_logs"; process_logs_dir.mkdir(exist_ok=True) + index_store_dir = out / "indices"; index_store_dir.mkdir(exist_ok=True) + + # load existing results if present + results_csv = out / cfg["output"]["results_csv"] + print(results_csv) + if results_csv.exists() and not run_params["force_overwrite"]: + existing_df = pd.read_csv(results_csv) + done_pairs = set(zip(existing_df["index"], existing_df["query_batch_size"])) + print(done_pairs) + else: + print("No existing results found") + existing_df = None + done_pairs = set() all_rows = [] @@ -146,7 +159,7 @@ def run_experiment(cfg_path, out_dir): build_env = idx_cfg.get("build_env_vars", {}) timeout = idx_cfg.get("process_timeout", cfg.get("default_process_timeout", 7200)) - build_res = common_utils.run_operation_in_process( + res = common_utils.run_operation_in_process( task_build_index, (idx_cfg, ds_cfg, run_params, idx_path), env_vars=build_env, @@ -155,25 +168,26 @@ def run_experiment(cfg_path, out_dir): timeout_seconds=timeout, enable_glances=run_params["enable_glances"] ) - - # check build result - data = build_res.get("data", {}) - if build_res.get("status") != "success" or data.get("error"): - logger.error(f"[BUILD FAILED] {name}: {data.get('error', 'unknown')}") + data = res.get("data", {}) + if res.get("status")!="success" or data.get("error"): + logger.error(f"[BUILD FAILED] {name}: {data.get('error','unknown')}") else: - logger.info(f"[BUILD OK] {name} → {data.get('index_file_path')} ({data.get('status')})") + logger.info(f"[BUILD OK] {name} → {data['index_file_path']}") # === SEARCH TASKS === for bs in batch_sizes: for idx_cfg in cfg["indexes"]: name = idx_cfg["name"] - idx_path = Path(idx_cfg.get("index_file", index_store_dir/f"{name}.bin")) + if (name, bs) in done_pairs: + logger.info(f"Skipping existing result for {name}, batch={bs}") + continue + idx_path = Path(idx_cfg.get("index_file", index_store_dir/f"{name}.bin")) search_log = process_logs_dir / f"{name}_search_bs{bs}.log" search_env = idx_cfg.get("search_env_vars", {}) timeout = idx_cfg.get("process_timeout", cfg.get("default_process_timeout", 7200)) - search_res = common_utils.run_operation_in_process( + res = common_utils.run_operation_in_process( task_search_index, (idx_cfg, ds_cfg, run_params, idx_path, bs), env_vars=search_env, @@ -183,33 +197,29 @@ def run_experiment(cfg_path, out_dir): enable_glances=run_params["enable_glances"] ) - if search_res.get("status") == "success": - data = search_res.get("data", {}) - if data.get("error"): - row = {"index": name, "query_batch_size": bs, "error": data["error"]} - logger.error(f"[SEARCH ERROR] {name} bs={bs}: {data['error']}") - else: - row = { - "index": name, - **data - } - logger.info(f"[SEARCH OK] {name} bs={bs}: latency={data['mean_total_latency_ms']:.2f}ms, recall={data['mean_recall']:.3f}") + if res.get("status")=="success" and not res.get("data",{}).get("error"): + row = {"index": name, **res["data"]} + logger.info(f"[SEARCH OK] {name}, batch={bs}: {row}") else: - err = search_res.get("data", {}).get("error", "process failed") + err = res.get("data",{}).get("error","proc failed") row = {"index": name, "query_batch_size": bs, "error": err} - logger.error(f"[SEARCH PROC FAIL] {name} bs={bs}: {err}") + logger.error(f"[SEARCH ERR] {name}, batch={bs}: {err}") all_rows.append(row) - # === AGGREGATE & PLOT === - df = pd.DataFrame(all_rows) + # === MERGE & SAVE === + new_df = pd.DataFrame(all_rows) + if existing_df is not None and not run_params["force_overwrite"]: + df = pd.concat([existing_df, new_df], ignore_index=True) + else: + df = new_df + # compute QPS df["QPS"] = df["nq"] * 1000.0 / df["mean_total_latency_ms"] - out_csv = out / cfg["output"]["results_csv"] - df.to_csv(out_csv, index=False) - logger.info(f"Wrote results to {out_csv}") + df.to_csv(results_csv, index=False) + logger.info(f"Wrote results to {results_csv}") - # plot QPS vs batch size + # === PLOT === plt.figure(figsize=(8,6)) for name, grp in df.groupby("index"): grp = grp.sort_values("query_batch_size") From 37ab02784f19a0c2bc188f1081dc7c396979cf01 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 29 May 2025 01:25:55 -0500 Subject: [PATCH 289/323] update scann for multi-query experiment --- .../osdi2025/vary_batch_size/run.py | 140 ++++++++++-- .../experiments/osdi2025/wiki_workload/run.py | 214 ++++++++++++++++++ .../osdi2025/workload_comparison/run.py | 2 - 3 files changed, 335 insertions(+), 21 deletions(-) create mode 100644 test/experiments/osdi2025/wiki_workload/run.py delete mode 100644 test/experiments/osdi2025/workload_comparison/run.py diff --git a/test/experiments/osdi2025/vary_batch_size/run.py b/test/experiments/osdi2025/vary_batch_size/run.py index d30ec6f7..93215eae 100644 --- a/test/experiments/osdi2025/vary_batch_size/run.py +++ b/test/experiments/osdi2025/vary_batch_size/run.py @@ -115,11 +115,119 @@ def task_search_index(idx_cfg, ds_cfg, run_params, idx_file: Path, batch_size: i "query_batch_size": batch_size, } + +def bench_scann(cfg_path: str, out_dir: Path, force_rebuild: bool, force_overwrite: bool): + """ + Build and benchmark SCANN across all batch sizes defined in the config. SCANNs serialization is broken, so it needs to be handled separately. + """ + if Scann is None: + raise ImportError("SCANN wrapper not installed; please install quake.index_wrappers.scann") + + # load config and dataset settings + cfg = common_utils.load_config(cfg_path) + ds_cfg = cfg["dataset"] + batch_sizes = ds_cfg["query_batch_sizes"] + k_val = ds_cfg["k"] + num_trials = cfg.get("trials", 3) + num_warmup = cfg.get("warmup", 1) + + # prepare paths + out_dir = Path(out_dir) + results_csv = out_dir / cfg["output"]["results_csv"] + results_csv.parent.mkdir(parents=True, exist_ok=True) + + # find SCANN entry in indexes + scann_cfg = next((ic for ic in cfg["indexes"] if ic["index"] == "SCANN"), None) + if scann_cfg is None: + return # no SCANN to run + + idx_name = scann_cfg["name"] + # check existing results + if results_csv.exists() and not force_overwrite: + df_existing = pd.read_csv(results_csv) + if idx_name in df_existing["index"].unique() and not force_rebuild: + logger.info(f"[SCANN] results already exist and no force overwrite → skipping") + return + + # BUILD SCANN index + logger.info(f"[{idx_name} BUILD] building SCANN index") + base_vecs, _, _ = common_utils.load_data(ds_cfg["name"], nq_override=1) + scann = Scann() + scann.build(base_vecs, **scann_cfg.get("build_params", {})) + idx_file = Path(scann_cfg.get("index_file", out_dir / "indices" / f"{idx_name}.bin")) + idx_file.parent.mkdir(parents=True, exist_ok=True) + scann.save(str(idx_file)) + del base_vecs + + # LOAD queries & GT once + _, all_qvecs, all_gt = common_utils.load_data( + ds_cfg["name"], nq_override=ds_cfg["num_queries"] + ) + nq = all_qvecs.shape[0] + + # BENCHMARK SCANN over batch sizes + records = [] + for bs in batch_sizes: + logger.info(f"[{idx_name} SEARCH] batch_size={bs}") + inst = Scann() + inst.load(str(idx_file)) + + # warmup runs + warmup_q = all_qvecs[:bs] + for _ in range(num_warmup): + inst.search(warmup_q, k_val, **scann_cfg.get("search_params", {})) + + latencies = [] + recalls = [] + for _ in range(num_trials): + total_ns = 0 + ids_batches = [] + for i in range(0, nq, bs): + chunk = all_qvecs[i : min(i + bs, nq)] + res = inst.search(chunk, k_val, **scann_cfg.get("search_params", {})) + ti = getattr(res, "timing_info", None) + ns = getattr(ti, "total_time_ns", None) or getattr(ti, "child_total_time_ns", 0) + total_ns += ns + ids_batches.append(res.ids) + + latencies.append(total_ns / 1e6) + all_ids = np.vstack(ids_batches) + recalls.append(float(compute_recall(all_ids, all_gt, k_val).mean())) + + records.append({ + "index": idx_name, + "query_batch_size": bs, + "nq": nq, + "mean_total_latency_ms": float(np.mean(latencies)), + "std_total_latency_ms": float(np.std(latencies)), + "mean_recall": float(np.mean(recalls)), + "std_recall": float(np.std(recalls)), + "QPS": float(nq * 1000.0 / np.mean(latencies)), + }) + + # save (or overwrite) SCANN results + df = pd.DataFrame(records) + df.to_csv(results_csv, index=False) + logger.info(f"[{idx_name}] SCANN benchmark results saved to {results_csv}") + + def run_experiment(cfg_path, out_dir): + """ + Main entrypoint: first runs SCANN via bench_scann, then + proceeds with build/search for all other indexes. + """ logging.basicConfig(level=logging.INFO) cfg = common_utils.load_config(cfg_path) out = Path(out_dir); out.mkdir(parents=True, exist_ok=True) + # run SCANN special path + bench_scann( + cfg_path=cfg_path, + out_dir=out, + force_rebuild=cfg.get("force_rebuild", False), + force_overwrite=cfg.get("overwrite", False) + ) + ds_cfg = cfg["dataset"] batch_sizes = ds_cfg["query_batch_sizes"] run_params = { @@ -135,37 +243,33 @@ def run_experiment(cfg_path, out_dir): process_logs_dir = out / "process_logs"; process_logs_dir.mkdir(exist_ok=True) index_store_dir = out / "indices"; index_store_dir.mkdir(exist_ok=True) - # load existing results if present + # load existing results results_csv = out / cfg["output"]["results_csv"] - print(results_csv) if results_csv.exists() and not run_params["force_overwrite"]: existing_df = pd.read_csv(results_csv) done_pairs = set(zip(existing_df["index"], existing_df["query_batch_size"])) - print(done_pairs) else: - print("No existing results found") existing_df = None done_pairs = set() all_rows = [] - # === BUILD TASKS === + # === BUILD OTHER INDEXES === for idx_cfg in cfg["indexes"]: + if idx_cfg["index"] == "SCANN": + continue # already handled name = idx_cfg["name"] idx_path = Path(idx_cfg.get("index_file", index_store_dir/f"{name}.bin")) idx_path.parent.mkdir(parents=True, exist_ok=True) build_log = process_logs_dir / f"{name}_build.log" - build_env = idx_cfg.get("build_env_vars", {}) - timeout = idx_cfg.get("process_timeout", cfg.get("default_process_timeout", 7200)) - res = common_utils.run_operation_in_process( task_build_index, (idx_cfg, ds_cfg, run_params, idx_path), - env_vars=build_env, + env_vars=idx_cfg.get("build_env_vars", {}), log_file_path=str(build_log), process_name=f"BuildTask_{name}", - timeout_seconds=timeout, + timeout_seconds=idx_cfg.get("process_timeout", cfg.get("default_process_timeout", 7200)), enable_glances=run_params["enable_glances"] ) data = res.get("data", {}) @@ -174,26 +278,25 @@ def run_experiment(cfg_path, out_dir): else: logger.info(f"[BUILD OK] {name} → {data['index_file_path']}") - # === SEARCH TASKS === + # === SEARCH OTHER INDEXES === for bs in batch_sizes: for idx_cfg in cfg["indexes"]: + if idx_cfg["index"] == "SCANN": + continue # skip SCANN in normal loop name = idx_cfg["name"] if (name, bs) in done_pairs: logger.info(f"Skipping existing result for {name}, batch={bs}") continue - idx_path = Path(idx_cfg.get("index_file", index_store_dir/f"{name}.bin")) + idx_path = Path(idx_cfg.get("index_file", index_store_dir/f"{name}.bin")) search_log = process_logs_dir / f"{name}_search_bs{bs}.log" - search_env = idx_cfg.get("search_env_vars", {}) - timeout = idx_cfg.get("process_timeout", cfg.get("default_process_timeout", 7200)) - res = common_utils.run_operation_in_process( task_search_index, (idx_cfg, ds_cfg, run_params, idx_path, bs), - env_vars=search_env, + env_vars=idx_cfg.get("search_env_vars", {}), log_file_path=str(search_log), process_name=f"SearchTask_{name}_bs{bs}", - timeout_seconds=timeout, + timeout_seconds=idx_cfg.get("process_timeout", cfg.get("default_process_timeout", 7200)), enable_glances=run_params["enable_glances"] ) @@ -207,14 +310,13 @@ def run_experiment(cfg_path, out_dir): all_rows.append(row) - # === MERGE & SAVE === + # === MERGE & SAVE ALL RESULTS === new_df = pd.DataFrame(all_rows) if existing_df is not None and not run_params["force_overwrite"]: df = pd.concat([existing_df, new_df], ignore_index=True) else: df = new_df - # compute QPS df["QPS"] = df["nq"] * 1000.0 / df["mean_total_latency_ms"] df.to_csv(results_csv, index=False) logger.info(f"Wrote results to {results_csv}") diff --git a/test/experiments/osdi2025/wiki_workload/run.py b/test/experiments/osdi2025/wiki_workload/run.py new file mode 100644 index 00000000..e0c65dab --- /dev/null +++ b/test/experiments/osdi2025/wiki_workload/run.py @@ -0,0 +1,214 @@ +#!/usr/bin/env python3 +""" +Wikidata Workload Experiment Runner +───────────────────────────────────── +This experiment runs a Wikidata workload across multiple index configurations. +It generates detailed reports including: +1. Per-index CSV logs of operations. +2. A 9-panel unified plot comparing various metrics across configurations. +3. A stacked bar chart breaking down cumulative time per operation type. +4. A summary table (CSV and Markdown) of key performance indicators. +""" +from __future__ import annotations + +import logging +from pathlib import Path +from typing import Dict, List, Any, Optional + +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +from tabulate import tabulate +from matplotlib.cm import get_cmap +from matplotlib.lines import Line2D + +# Common utilities +import test.experiments.osdi2025.experiment_utils as common_utils + +# evaluator and wrappers +from .wiki_workload import WikidataWorkloadEvaluator +from quake.index_wrappers.quake import QuakeWrapper +from quake.index_wrappers.faiss_ivf import FaissIVF +from quake.index_wrappers.faiss_hnsw import FaissHNSW +try: from quake.index_wrappers.scann import Scann +except ImportError: Scann = None +try: from quake.index_wrappers.diskann import DiskANNDynamic +except ImportError: DiskANNDynamic = None +try: from quake.index_wrappers.vamana import Vamana +except ImportError: Vamana = None + +INDEX_CLASSES: Dict[str, Any] = { + "Quake": QuakeWrapper, + "IVF": FaissIVF, + "HNSW": FaissHNSW, + "SCANN": Scann, + "DiskANN": DiskANNDynamic, + "SVS": Vamana, +} + +logging.basicConfig(level=logging.INFO, + format="%(asctime)s | %(levelname)s | %(message)s") +log = logging.getLogger(__name__) + +OP_STYLE = { + "query": dict(ls="-", marker="o", mfc="none", ms=4, lw=1.2), + "insert": dict(ls="-", marker="s", mfc="none", ms=4, lw=1.2), + "delete": dict(ls="-", marker="^", mfc="none", ms=4, lw=1.2), + "maintain": dict(ls="None", marker="X", mfc="black", ms=5), +} +LAT_OPS = ["query", "insert", "delete", "maintain"] +IDX_LAT_Q, IDX_LAT_I, IDX_LAT_D, IDX_LAT_M = 0, 1, 2, 3 +IDX_PART, IDX_RES, IDX_REC, IDX_TOT, IDX_SPL = 4, 5, 6, 7, 8 + + +def unified_plot(cfg: Dict[str, Any], out_dir: Path) -> None: + styles = cfg.get("plot", {}).get("styles", {}) + fig, axs2d = plt.subplots(3, 3, figsize=(18, 12), sharex="col") + axs = axs2d.flatten() + + idx_handles: List[Line2D] = [] + for j, idx_cfg in enumerate(cfg.get("indexes", [])): + nm = idx_cfg["name"] + st = styles.get(nm, {}) + idx_handles.append(Line2D([0], [0], + color=st.get("color", f"C{j % 10}"), + marker=st.get("marker", "o"), + ls="", markersize=6, label=nm)) + + max_ops_overall = 0 + for j, idx_cfg in enumerate(cfg.get("indexes", [])): + name = idx_cfg["name"] + colour = styles.get(name, {}).get("color", f"C{j % 10}") + marker = styles.get(name, {}).get("marker", "o") + + csv_path = out_dir / name / "results.csv" + if not csv_path.exists(): + log.warning("[unified_plot] missing %s", csv_path) + continue + try: + df = pd.read_csv(csv_path) + if df.empty: continue + max_ops_overall = max(max_ops_overall, df.operation_number.max()) + except Exception: + log.warning("[unified_plot] failed to read %s", csv_path) + continue + + # latency + for op, ax_idx in zip(LAT_OPS, [IDX_LAT_Q, IDX_LAT_I, IDX_LAT_D, IDX_LAT_M]): + ax = axs[ax_idx] + if op != "maintain": + sub = df[df.operation_type == op] + if not sub.empty: + ax.plot(sub.operation_number, sub.latency_ms, color=colour, **OP_STYLE[op]) + + # partitions, resident blank + # recall + rec_ix = IDX_REC + sub = df[df.operation_type=="query"] + if "recall" in sub: + axs[rec_ix].plot(sub.operation_number, sub.recall, color=colour, marker=marker, lw=1.2) + # cumulative time + tot_ix = IDX_TOT + cum = np.cumsum(df.latency_ms.fillna(0)) + axs[tot_ix].plot(df.operation_number, cum, color=colour, marker=marker, lw=1.2) + + # titles and labels + titles = { + IDX_LAT_Q: "Latency – Query", IDX_LAT_I: "Insert", IDX_LAT_D: "Delete", IDX_LAT_M: "Maintain", + IDX_PART: "# Partitions", IDX_RES: "Resident", IDX_REC: "Recall", + IDX_TOT: "Cum. Time (ms)", IDX_SPL: "Splits/Deletes" + } + for i, ax in enumerate(axs): + ax.set_title(titles.get(i, "")) + ax.grid(True, ls=":", alpha=0.7) + if i//3==2: ax.set_xlabel("Op #") + if max_ops_overall>0: + for ax in axs: ax.set_xlim(0, max_ops_overall) + + fig.legend(idx_handles, [h.get_label() for h in idx_handles], + loc="upper center", ncol=min(4,len(idx_handles)), frameon=False) + plt.tight_layout(rect=[0,0.03,1,0.97]) + path = out_dir / "unified_plot.png" + plt.savefig(path, dpi=150) + log.info("Saved unified_plot to %s", path) + plt.close(fig) + + +def make_time_breakdown(cfg: Dict[str, Any], out_dir: Path) -> None: + categories = ["Query","Insert","Delete","Total"] + data = {} + for idx_cfg in cfg.get("indexes", []): + name = idx_cfg["name"] + df = pd.read_csv(out_dir/name/"results.csv") + data[name] = [ + df[df.operation_type=="query"].latency_ms.sum(), + df[df.operation_type=="insert"].latency_ms.sum(), + df[df.operation_type=="delete"].latency_ms.sum(), + ] + data[name].append(sum(data[name])) + fig, ax = plt.subplots(figsize=(8,6)) + cmap = get_cmap("tab10") + n = len(data) + x = np.arange(len(categories)) + w = 0.8/n + for j,(name,vals) in enumerate(data.items()): + ax.bar(x + j*w, vals, width=w, label=name, color=cmap(j)) + ax.set_xticks(x); ax.set_xticklabels(categories) + ax.set_ylabel("Cumulative ms") + ax.legend(frameon=False) + path = out_dir/"time_breakdown.png" + plt.savefig(path, dpi=150) + log.info("Saved time_breakdown to %s", path) + plt.close(fig) + + +def produce_summary_table(cfg: Dict[str, Any], out_dir: Path) -> None: + rows = [] + for idx_cfg in cfg.get("indexes", []): + name = idx_cfg["name"] + df = pd.read_csv(out_dir/name/"results.csv") + q = df[df.operation_type=="query"] + rows.append({ + "Index": name, + "MeanLatency": float(q.latency_ms.mean()), + "MeanRecall": float(q.recall.mean()) if "recall" in q else None, + }) + if not rows: return + sdf = pd.DataFrame(rows) + common_utils.save_results_csv(sdf, out_dir/"summary_table.csv") + md = tabulate(sdf, headers="keys", tablefmt="github", showindex=False) + print(md) + + +def run_experiment(cfg_path_str: str, output_dir_str: str) -> None: + cfg = common_utils.load_config(cfg_path_str) + out = Path(output_dir_str).expanduser(); out.mkdir(parents=True, exist_ok=True) + mode = cfg.get("mode","run") + log.info("Mode: %s", mode) + + workload_dir = cfg["workload_dir"] + + if mode in {"run"}: # Phase 2: evaluation + for idx_cfg in cfg.get("indexes", []): + name = idx_cfg["name"] + key = idx_cfg["index"] + Cls = INDEX_CLASSES.get(key) + if Cls is None: + log.warning("Unknown index %s", key); continue + wrapper = Cls() + maint = idx_cfg.get("maintenance_params") + do_maint = maint is not None + ev = WikidataWorkloadEvaluator(workload_dir, out/name) + ev.evaluate_workload( + name=name, + index=wrapper, + build_params=idx_cfg.get("build_params",{}), + search_params=idx_cfg.get("search_params",{}), + do_maintenance=do_maint, + m_params=maint, + batch=bool(idx_cfg.get("batch",False)), + ) + if mode in {"run","plot"}: # Phase 3 + unified_plot(cfg, out) + make_time_breakdown(cfg, out) + produce_summary_table(cfg, out) \ No newline at end of file diff --git a/test/experiments/osdi2025/workload_comparison/run.py b/test/experiments/osdi2025/workload_comparison/run.py deleted file mode 100644 index 139597f9..00000000 --- a/test/experiments/osdi2025/workload_comparison/run.py +++ /dev/null @@ -1,2 +0,0 @@ - - From eb9efe4da5e8a1218e405eaa459e728936f76a75 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 29 May 2025 01:34:06 -0500 Subject: [PATCH 290/323] update scann for multi-query experiment --- .../osdi2025/vary_batch_size/run.py | 140 +++--------------- 1 file changed, 19 insertions(+), 121 deletions(-) diff --git a/test/experiments/osdi2025/vary_batch_size/run.py b/test/experiments/osdi2025/vary_batch_size/run.py index 93215eae..d30ec6f7 100644 --- a/test/experiments/osdi2025/vary_batch_size/run.py +++ b/test/experiments/osdi2025/vary_batch_size/run.py @@ -115,119 +115,11 @@ def task_search_index(idx_cfg, ds_cfg, run_params, idx_file: Path, batch_size: i "query_batch_size": batch_size, } - -def bench_scann(cfg_path: str, out_dir: Path, force_rebuild: bool, force_overwrite: bool): - """ - Build and benchmark SCANN across all batch sizes defined in the config. SCANNs serialization is broken, so it needs to be handled separately. - """ - if Scann is None: - raise ImportError("SCANN wrapper not installed; please install quake.index_wrappers.scann") - - # load config and dataset settings - cfg = common_utils.load_config(cfg_path) - ds_cfg = cfg["dataset"] - batch_sizes = ds_cfg["query_batch_sizes"] - k_val = ds_cfg["k"] - num_trials = cfg.get("trials", 3) - num_warmup = cfg.get("warmup", 1) - - # prepare paths - out_dir = Path(out_dir) - results_csv = out_dir / cfg["output"]["results_csv"] - results_csv.parent.mkdir(parents=True, exist_ok=True) - - # find SCANN entry in indexes - scann_cfg = next((ic for ic in cfg["indexes"] if ic["index"] == "SCANN"), None) - if scann_cfg is None: - return # no SCANN to run - - idx_name = scann_cfg["name"] - # check existing results - if results_csv.exists() and not force_overwrite: - df_existing = pd.read_csv(results_csv) - if idx_name in df_existing["index"].unique() and not force_rebuild: - logger.info(f"[SCANN] results already exist and no force overwrite → skipping") - return - - # BUILD SCANN index - logger.info(f"[{idx_name} BUILD] building SCANN index") - base_vecs, _, _ = common_utils.load_data(ds_cfg["name"], nq_override=1) - scann = Scann() - scann.build(base_vecs, **scann_cfg.get("build_params", {})) - idx_file = Path(scann_cfg.get("index_file", out_dir / "indices" / f"{idx_name}.bin")) - idx_file.parent.mkdir(parents=True, exist_ok=True) - scann.save(str(idx_file)) - del base_vecs - - # LOAD queries & GT once - _, all_qvecs, all_gt = common_utils.load_data( - ds_cfg["name"], nq_override=ds_cfg["num_queries"] - ) - nq = all_qvecs.shape[0] - - # BENCHMARK SCANN over batch sizes - records = [] - for bs in batch_sizes: - logger.info(f"[{idx_name} SEARCH] batch_size={bs}") - inst = Scann() - inst.load(str(idx_file)) - - # warmup runs - warmup_q = all_qvecs[:bs] - for _ in range(num_warmup): - inst.search(warmup_q, k_val, **scann_cfg.get("search_params", {})) - - latencies = [] - recalls = [] - for _ in range(num_trials): - total_ns = 0 - ids_batches = [] - for i in range(0, nq, bs): - chunk = all_qvecs[i : min(i + bs, nq)] - res = inst.search(chunk, k_val, **scann_cfg.get("search_params", {})) - ti = getattr(res, "timing_info", None) - ns = getattr(ti, "total_time_ns", None) or getattr(ti, "child_total_time_ns", 0) - total_ns += ns - ids_batches.append(res.ids) - - latencies.append(total_ns / 1e6) - all_ids = np.vstack(ids_batches) - recalls.append(float(compute_recall(all_ids, all_gt, k_val).mean())) - - records.append({ - "index": idx_name, - "query_batch_size": bs, - "nq": nq, - "mean_total_latency_ms": float(np.mean(latencies)), - "std_total_latency_ms": float(np.std(latencies)), - "mean_recall": float(np.mean(recalls)), - "std_recall": float(np.std(recalls)), - "QPS": float(nq * 1000.0 / np.mean(latencies)), - }) - - # save (or overwrite) SCANN results - df = pd.DataFrame(records) - df.to_csv(results_csv, index=False) - logger.info(f"[{idx_name}] SCANN benchmark results saved to {results_csv}") - - def run_experiment(cfg_path, out_dir): - """ - Main entrypoint: first runs SCANN via bench_scann, then - proceeds with build/search for all other indexes. - """ logging.basicConfig(level=logging.INFO) cfg = common_utils.load_config(cfg_path) out = Path(out_dir); out.mkdir(parents=True, exist_ok=True) - # run SCANN special path - bench_scann( - cfg_path=cfg_path, - out_dir=out, - force_rebuild=cfg.get("force_rebuild", False), - force_overwrite=cfg.get("overwrite", False) - ) - ds_cfg = cfg["dataset"] batch_sizes = ds_cfg["query_batch_sizes"] run_params = { @@ -243,33 +135,37 @@ def run_experiment(cfg_path, out_dir): process_logs_dir = out / "process_logs"; process_logs_dir.mkdir(exist_ok=True) index_store_dir = out / "indices"; index_store_dir.mkdir(exist_ok=True) - # load existing results + # load existing results if present results_csv = out / cfg["output"]["results_csv"] + print(results_csv) if results_csv.exists() and not run_params["force_overwrite"]: existing_df = pd.read_csv(results_csv) done_pairs = set(zip(existing_df["index"], existing_df["query_batch_size"])) + print(done_pairs) else: + print("No existing results found") existing_df = None done_pairs = set() all_rows = [] - # === BUILD OTHER INDEXES === + # === BUILD TASKS === for idx_cfg in cfg["indexes"]: - if idx_cfg["index"] == "SCANN": - continue # already handled name = idx_cfg["name"] idx_path = Path(idx_cfg.get("index_file", index_store_dir/f"{name}.bin")) idx_path.parent.mkdir(parents=True, exist_ok=True) build_log = process_logs_dir / f"{name}_build.log" + build_env = idx_cfg.get("build_env_vars", {}) + timeout = idx_cfg.get("process_timeout", cfg.get("default_process_timeout", 7200)) + res = common_utils.run_operation_in_process( task_build_index, (idx_cfg, ds_cfg, run_params, idx_path), - env_vars=idx_cfg.get("build_env_vars", {}), + env_vars=build_env, log_file_path=str(build_log), process_name=f"BuildTask_{name}", - timeout_seconds=idx_cfg.get("process_timeout", cfg.get("default_process_timeout", 7200)), + timeout_seconds=timeout, enable_glances=run_params["enable_glances"] ) data = res.get("data", {}) @@ -278,25 +174,26 @@ def run_experiment(cfg_path, out_dir): else: logger.info(f"[BUILD OK] {name} → {data['index_file_path']}") - # === SEARCH OTHER INDEXES === + # === SEARCH TASKS === for bs in batch_sizes: for idx_cfg in cfg["indexes"]: - if idx_cfg["index"] == "SCANN": - continue # skip SCANN in normal loop name = idx_cfg["name"] if (name, bs) in done_pairs: logger.info(f"Skipping existing result for {name}, batch={bs}") continue - idx_path = Path(idx_cfg.get("index_file", index_store_dir/f"{name}.bin")) + idx_path = Path(idx_cfg.get("index_file", index_store_dir/f"{name}.bin")) search_log = process_logs_dir / f"{name}_search_bs{bs}.log" + search_env = idx_cfg.get("search_env_vars", {}) + timeout = idx_cfg.get("process_timeout", cfg.get("default_process_timeout", 7200)) + res = common_utils.run_operation_in_process( task_search_index, (idx_cfg, ds_cfg, run_params, idx_path, bs), - env_vars=idx_cfg.get("search_env_vars", {}), + env_vars=search_env, log_file_path=str(search_log), process_name=f"SearchTask_{name}_bs{bs}", - timeout_seconds=idx_cfg.get("process_timeout", cfg.get("default_process_timeout", 7200)), + timeout_seconds=timeout, enable_glances=run_params["enable_glances"] ) @@ -310,13 +207,14 @@ def run_experiment(cfg_path, out_dir): all_rows.append(row) - # === MERGE & SAVE ALL RESULTS === + # === MERGE & SAVE === new_df = pd.DataFrame(all_rows) if existing_df is not None and not run_params["force_overwrite"]: df = pd.concat([existing_df, new_df], ignore_index=True) else: df = new_df + # compute QPS df["QPS"] = df["nq"] * 1000.0 / df["mean_total_latency_ms"] df.to_csv(results_csv, index=False) logger.info(f"Wrote results to {results_csv}") From 74b9278c41ff879aa7dd8110abfb05e9f6ff6656 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 29 May 2025 01:40:59 -0500 Subject: [PATCH 291/323] update scann for multi-query experiment --- .../osdi2025/vary_batch_size/run.py | 140 +++++++++++++++--- 1 file changed, 121 insertions(+), 19 deletions(-) diff --git a/test/experiments/osdi2025/vary_batch_size/run.py b/test/experiments/osdi2025/vary_batch_size/run.py index d30ec6f7..3844e8f2 100644 --- a/test/experiments/osdi2025/vary_batch_size/run.py +++ b/test/experiments/osdi2025/vary_batch_size/run.py @@ -115,11 +115,119 @@ def task_search_index(idx_cfg, ds_cfg, run_params, idx_file: Path, batch_size: i "query_batch_size": batch_size, } + +def bench_scann(cfg_path: str, out_dir: Path, force_rebuild: bool, force_overwrite: bool): + """ + Build and benchmark SCANN across all batch sizes defined in the config. SCANNs serialization is broken when run in a subprocess, so it is handled separately. + """ + if Scann is None: + raise ImportError("SCANN wrapper not installed; please install quake.index_wrappers.scann") + + # load config and dataset settings + cfg = common_utils.load_config(cfg_path) + ds_cfg = cfg["dataset"] + batch_sizes = ds_cfg["query_batch_sizes"] + k_val = ds_cfg["k"] + num_trials = cfg.get("trials", 3) + num_warmup = cfg.get("warmup", 1) + + # prepare paths + out_dir = Path(out_dir) + results_csv = out_dir / cfg["output"]["results_csv"] + results_csv.parent.mkdir(parents=True, exist_ok=True) + + # find SCANN entry in indexes + scann_cfg = next((ic for ic in cfg["indexes"] if ic["index"] == "SCANN"), None) + if scann_cfg is None: + return # no SCANN to run + + idx_name = scann_cfg["name"] + # check existing results + if results_csv.exists() and not force_overwrite: + df_existing = pd.read_csv(results_csv) + if idx_name in df_existing["index"].unique() and not force_rebuild: + logger.info(f"[SCANN] results already exist and no force overwrite → skipping") + return + + # BUILD SCANN index + logger.info(f"[{idx_name} BUILD] building SCANN index") + base_vecs, _, _ = common_utils.load_data(ds_cfg["name"], nq_override=1) + scann = Scann() + scann.build(base_vecs, **scann_cfg.get("build_params", {})) + idx_file = Path(scann_cfg.get("index_file", out_dir / "indices" / f"{idx_name}.bin")) + idx_file.parent.mkdir(parents=True, exist_ok=True) + scann.save(str(idx_file)) + del base_vecs + + # LOAD queries & GT once + _, all_qvecs, all_gt = common_utils.load_data( + ds_cfg["name"], nq_override=ds_cfg["num_queries"] + ) + nq = all_qvecs.shape[0] + + # BENCHMARK SCANN over batch sizes + records = [] + for bs in batch_sizes: + logger.info(f"[{idx_name} SEARCH] batch_size={bs}") + inst = Scann() + inst.load(str(idx_file)) + + # warmup runs + warmup_q = all_qvecs[:bs] + for _ in range(num_warmup): + inst.search(warmup_q, k_val, **scann_cfg.get("search_params", {})) + + latencies = [] + recalls = [] + for _ in range(num_trials): + total_ns = 0 + ids_batches = [] + for i in range(0, nq, bs): + chunk = all_qvecs[i : min(i + bs, nq)] + res = inst.search(chunk, k_val, **scann_cfg.get("search_params", {})) + ti = getattr(res, "timing_info", None) + ns = getattr(ti, "total_time_ns", None) or getattr(ti, "child_total_time_ns", 0) + total_ns += ns + ids_batches.append(res.ids) + + latencies.append(total_ns / 1e6) + all_ids = np.vstack(ids_batches) + recalls.append(float(compute_recall(all_ids, all_gt, k_val).mean())) + + records.append({ + "index": idx_name, + "query_batch_size": bs, + "nq": nq, + "mean_total_latency_ms": float(np.mean(latencies)), + "std_total_latency_ms": float(np.std(latencies)), + "mean_recall": float(np.mean(recalls)), + "std_recall": float(np.std(recalls)), + "QPS": float(nq * 1000.0 / np.mean(latencies)), + }) + + # save (or overwrite) SCANN results + df = pd.DataFrame(records) + df.to_csv(results_csv, index=False) + logger.info(f"[{idx_name}] SCANN benchmark results saved to {results_csv}") + + def run_experiment(cfg_path, out_dir): + """ + Main entrypoint: first runs SCANN via bench_scann, then + proceeds with build/search for all other indexes. + """ logging.basicConfig(level=logging.INFO) cfg = common_utils.load_config(cfg_path) out = Path(out_dir); out.mkdir(parents=True, exist_ok=True) + # run SCANN special path + bench_scann( + cfg_path=cfg_path, + out_dir=out, + force_rebuild=cfg.get("force_rebuild", False), + force_overwrite=cfg.get("overwrite", False) + ) + ds_cfg = cfg["dataset"] batch_sizes = ds_cfg["query_batch_sizes"] run_params = { @@ -135,37 +243,33 @@ def run_experiment(cfg_path, out_dir): process_logs_dir = out / "process_logs"; process_logs_dir.mkdir(exist_ok=True) index_store_dir = out / "indices"; index_store_dir.mkdir(exist_ok=True) - # load existing results if present + # load existing results results_csv = out / cfg["output"]["results_csv"] - print(results_csv) if results_csv.exists() and not run_params["force_overwrite"]: existing_df = pd.read_csv(results_csv) done_pairs = set(zip(existing_df["index"], existing_df["query_batch_size"])) - print(done_pairs) else: - print("No existing results found") existing_df = None done_pairs = set() all_rows = [] - # === BUILD TASKS === + # === BUILD OTHER INDEXES === for idx_cfg in cfg["indexes"]: + if idx_cfg["index"] == "SCANN": + continue # already handled name = idx_cfg["name"] idx_path = Path(idx_cfg.get("index_file", index_store_dir/f"{name}.bin")) idx_path.parent.mkdir(parents=True, exist_ok=True) build_log = process_logs_dir / f"{name}_build.log" - build_env = idx_cfg.get("build_env_vars", {}) - timeout = idx_cfg.get("process_timeout", cfg.get("default_process_timeout", 7200)) - res = common_utils.run_operation_in_process( task_build_index, (idx_cfg, ds_cfg, run_params, idx_path), - env_vars=build_env, + env_vars=idx_cfg.get("build_env_vars", {}), log_file_path=str(build_log), process_name=f"BuildTask_{name}", - timeout_seconds=timeout, + timeout_seconds=idx_cfg.get("process_timeout", cfg.get("default_process_timeout", 7200)), enable_glances=run_params["enable_glances"] ) data = res.get("data", {}) @@ -174,26 +278,25 @@ def run_experiment(cfg_path, out_dir): else: logger.info(f"[BUILD OK] {name} → {data['index_file_path']}") - # === SEARCH TASKS === + # === SEARCH OTHER INDEXES === for bs in batch_sizes: for idx_cfg in cfg["indexes"]: + if idx_cfg["index"] == "SCANN": + continue # skip SCANN in normal loop name = idx_cfg["name"] if (name, bs) in done_pairs: logger.info(f"Skipping existing result for {name}, batch={bs}") continue - idx_path = Path(idx_cfg.get("index_file", index_store_dir/f"{name}.bin")) + idx_path = Path(idx_cfg.get("index_file", index_store_dir/f"{name}.bin")) search_log = process_logs_dir / f"{name}_search_bs{bs}.log" - search_env = idx_cfg.get("search_env_vars", {}) - timeout = idx_cfg.get("process_timeout", cfg.get("default_process_timeout", 7200)) - res = common_utils.run_operation_in_process( task_search_index, (idx_cfg, ds_cfg, run_params, idx_path, bs), - env_vars=search_env, + env_vars=idx_cfg.get("search_env_vars", {}), log_file_path=str(search_log), process_name=f"SearchTask_{name}_bs{bs}", - timeout_seconds=timeout, + timeout_seconds=idx_cfg.get("process_timeout", cfg.get("default_process_timeout", 7200)), enable_glances=run_params["enable_glances"] ) @@ -207,14 +310,13 @@ def run_experiment(cfg_path, out_dir): all_rows.append(row) - # === MERGE & SAVE === + # === MERGE & SAVE ALL RESULTS === new_df = pd.DataFrame(all_rows) if existing_df is not None and not run_params["force_overwrite"]: df = pd.concat([existing_df, new_df], ignore_index=True) else: df = new_df - # compute QPS df["QPS"] = df["nq"] * 1000.0 / df["mean_total_latency_ms"] df.to_csv(results_csv, index=False) logger.info(f"Wrote results to {results_csv}") From c58b1d5f9d830614b5d2dfbc004a489fabd095d1 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 29 May 2025 01:42:38 -0500 Subject: [PATCH 292/323] update scann for multi-query experiment --- test/experiments/osdi2025/vary_batch_size/run.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/test/experiments/osdi2025/vary_batch_size/run.py b/test/experiments/osdi2025/vary_batch_size/run.py index 3844e8f2..138aa120 100644 --- a/test/experiments/osdi2025/vary_batch_size/run.py +++ b/test/experiments/osdi2025/vary_batch_size/run.py @@ -152,11 +152,10 @@ def bench_scann(cfg_path: str, out_dir: Path, force_rebuild: bool, force_overwri # BUILD SCANN index logger.info(f"[{idx_name} BUILD] building SCANN index") base_vecs, _, _ = common_utils.load_data(ds_cfg["name"], nq_override=1) - scann = Scann() - scann.build(base_vecs, **scann_cfg.get("build_params", {})) + scann_idx = Scann() + scann_idx.build(base_vecs, **scann_cfg.get("build_params", {})) idx_file = Path(scann_cfg.get("index_file", out_dir / "indices" / f"{idx_name}.bin")) idx_file.parent.mkdir(parents=True, exist_ok=True) - scann.save(str(idx_file)) del base_vecs # LOAD queries & GT once @@ -169,13 +168,11 @@ def bench_scann(cfg_path: str, out_dir: Path, force_rebuild: bool, force_overwri records = [] for bs in batch_sizes: logger.info(f"[{idx_name} SEARCH] batch_size={bs}") - inst = Scann() - inst.load(str(idx_file)) # warmup runs warmup_q = all_qvecs[:bs] for _ in range(num_warmup): - inst.search(warmup_q, k_val, **scann_cfg.get("search_params", {})) + scann_idx.search(warmup_q, k_val, **scann_cfg.get("search_params", {})) latencies = [] recalls = [] @@ -184,7 +181,7 @@ def bench_scann(cfg_path: str, out_dir: Path, force_rebuild: bool, force_overwri ids_batches = [] for i in range(0, nq, bs): chunk = all_qvecs[i : min(i + bs, nq)] - res = inst.search(chunk, k_val, **scann_cfg.get("search_params", {})) + res = scann_idx.search(chunk, k_val, **scann_cfg.get("search_params", {})) ti = getattr(res, "timing_info", None) ns = getattr(ti, "total_time_ns", None) or getattr(ti, "child_total_time_ns", 0) total_ns += ns From e46b1e6c9f8fbe78e10cb1369a32fb32c62eca1d Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 29 May 2025 02:32:31 -0500 Subject: [PATCH 293/323] update scann for multi-query experiment --- test/experiments/osdi2025/vary_batch_size/run.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/experiments/osdi2025/vary_batch_size/run.py b/test/experiments/osdi2025/vary_batch_size/run.py index 138aa120..95bdeae1 100644 --- a/test/experiments/osdi2025/vary_batch_size/run.py +++ b/test/experiments/osdi2025/vary_batch_size/run.py @@ -204,6 +204,12 @@ def bench_scann(cfg_path: str, out_dir: Path, force_rebuild: bool, force_overwri # save (or overwrite) SCANN results df = pd.DataFrame(records) + + # append to existing results if available + if results_csv.exists() and not force_overwrite: + existing_df = pd.read_csv(results_csv) + df = pd.concat([existing_df, df], ignore_index=True) + df.to_csv(results_csv, index=False) logger.info(f"[{idx_name}] SCANN benchmark results saved to {results_csv}") From d97741eb13a262633c3be334471d0ea0ea480baf Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 29 May 2025 02:46:14 -0500 Subject: [PATCH 294/323] update scann for multi-query experiment --- test/experiments/osdi2025/vary_batch_size/run.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/experiments/osdi2025/vary_batch_size/run.py b/test/experiments/osdi2025/vary_batch_size/run.py index 95bdeae1..4014ebda 100644 --- a/test/experiments/osdi2025/vary_batch_size/run.py +++ b/test/experiments/osdi2025/vary_batch_size/run.py @@ -80,8 +80,8 @@ def task_search_index(idx_cfg, ds_cfg, run_params, idx_file: Path, batch_size: i } inst.load(str(idx_file), **load_kwargs) - # warmup on one chunk - warmup = all_qvecs[:batch_size] + # warmup on one chunk using random vectors + warmup = np.random.randn(batch_size, all_qvecs.shape[1]).astype(np.float32) for _ in range(run_params["num_warmup"]): _ = inst.search(warmup, run_params["k_val"], **sp) From a87367faa01d81690b1770d7297c21a3698a0f65 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 29 May 2025 03:07:57 -0500 Subject: [PATCH 295/323] update scann for multi-query experiment --- test/experiments/osdi2025/vary_batch_size/run.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/experiments/osdi2025/vary_batch_size/run.py b/test/experiments/osdi2025/vary_batch_size/run.py index 4014ebda..90bc471e 100644 --- a/test/experiments/osdi2025/vary_batch_size/run.py +++ b/test/experiments/osdi2025/vary_batch_size/run.py @@ -5,6 +5,7 @@ import matplotlib.pyplot as plt import os import faiss +import torch import test.experiments.osdi2025.experiment_utils as common_utils from quake.utils import compute_recall @@ -81,7 +82,7 @@ def task_search_index(idx_cfg, ds_cfg, run_params, idx_file: Path, batch_size: i inst.load(str(idx_file), **load_kwargs) # warmup on one chunk using random vectors - warmup = np.random.randn(batch_size, all_qvecs.shape[1]).astype(np.float32) + warmup = torch.randn(batch_size, all_qvecs.shape[1]).astype(np.float32) for _ in range(run_params["num_warmup"]): _ = inst.search(warmup, run_params["k_val"], **sp) From 9557e2933f7e0a74b07fcc2c69d5496ff90fe42a Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 29 May 2025 03:09:31 -0500 Subject: [PATCH 296/323] update scann for multi-query experiment --- test/experiments/osdi2025/vary_batch_size/run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/experiments/osdi2025/vary_batch_size/run.py b/test/experiments/osdi2025/vary_batch_size/run.py index 90bc471e..78a09178 100644 --- a/test/experiments/osdi2025/vary_batch_size/run.py +++ b/test/experiments/osdi2025/vary_batch_size/run.py @@ -82,7 +82,7 @@ def task_search_index(idx_cfg, ds_cfg, run_params, idx_file: Path, batch_size: i inst.load(str(idx_file), **load_kwargs) # warmup on one chunk using random vectors - warmup = torch.randn(batch_size, all_qvecs.shape[1]).astype(np.float32) + warmup = torch.randn(batch_size, all_qvecs.shape[1]) for _ in range(run_params["num_warmup"]): _ = inst.search(warmup, run_params["k_val"], **sp) From 5cbd157d97c96aa4fb5e7dc786085da1c985378b Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 29 May 2025 03:33:19 -0500 Subject: [PATCH 297/323] update diskann for multi-query experiment --- test/experiments/osdi2025/vary_batch_size/run.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/experiments/osdi2025/vary_batch_size/run.py b/test/experiments/osdi2025/vary_batch_size/run.py index 78a09178..41efe44c 100644 --- a/test/experiments/osdi2025/vary_batch_size/run.py +++ b/test/experiments/osdi2025/vary_batch_size/run.py @@ -79,6 +79,13 @@ def task_search_index(idx_cfg, ds_cfg, run_params, idx_file: Path, batch_size: i for k in ("num_workers", "use_numa", "num_merge_workers", "parent") if k in bp } + + if itype == "DiskANN": + # DiskANN requires special handling for loading, all build params are passed as kwargs + load_kwargs = bp.copy() + bp.pop("omp_num_threads_build", None) # remove omp threads from load params + + inst.load(str(idx_file), **load_kwargs) # warmup on one chunk using random vectors From 9df34048ea203b04c28ce08cede23e3488731b29 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 29 May 2025 04:12:34 -0500 Subject: [PATCH 298/323] update diskann for multi-query experiment --- test/experiments/osdi2025/vary_batch_size/run.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/experiments/osdi2025/vary_batch_size/run.py b/test/experiments/osdi2025/vary_batch_size/run.py index 41efe44c..ff32951e 100644 --- a/test/experiments/osdi2025/vary_batch_size/run.py +++ b/test/experiments/osdi2025/vary_batch_size/run.py @@ -72,6 +72,8 @@ def task_search_index(idx_cfg, ds_cfg, run_params, idx_file: Path, batch_size: i ) nq = all_qvecs.shape[0] + # randomize queries for fair comparison + Cls = INDEX_CLASSES[itype] inst = Cls() load_kwargs = { @@ -99,6 +101,9 @@ def task_search_index(idx_cfg, ds_cfg, run_params, idx_file: Path, batch_size: i for _ in range(run_params["num_trials"]): total_ns = 0 ids_list = [] + rand_perm = torch.randperm(nq) + all_gt = all_gt[rand_perm] + all_qvecs = all_qvecs[rand_perm] for i in range(0, nq, batch_size): chunk = all_qvecs[i : min(i + batch_size, nq)] res = inst.search(chunk, run_params["k_val"], **sp) From 3278151d4189dd918956054591241294596ed096 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 30 May 2025 09:23:52 -0500 Subject: [PATCH 299/323] fix refinement --- src/cpp/include/list_scanning.h | 1 - src/cpp/include/query_coordinator.h | 4 +- src/cpp/src/clustering.cpp | 71 ++++++++++++++--------------- src/cpp/src/query_coordinator.cpp | 27 ++++++++--- 4 files changed, 54 insertions(+), 49 deletions(-) diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index b42d810a..5dcb9ac6 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -668,7 +668,6 @@ inline void batched_scan_list(const float *query_vecs, pivots ); } else if (metric == faiss::METRIC_L2) { - std::cout << "Using L2 metric for batched scan." << std::endl; l2_blas( query_vecs, list_vecs, diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 2bfd93cd..4e0193b8 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -281,9 +281,7 @@ class QueryCoordinator { void drain_and_apply_aps(Tensor x, Tensor partition_ids, - bool use_aps, - float recall_target, - int aps_flush_period_us, + shared_ptr params, shared_ptr timing); std::shared_ptr diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index f46ad13e..6b3a884d 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -234,39 +234,23 @@ tuple >> kmeans_refine_partitions( MetricType metric, int refinement_iterations) { - // static void ensure_blas_buffers(QueryCoordinator::CoreResources& res, - // size_t max_q, - // size_t db_bs, - // int node) - // { - // const size_t ip_need = db_bs * max_q; - // if (res.blas_ip_capacity < ip_need) { - // quake_free(res.blas_ip_block, res.blas_ip_capacity * sizeof(float)); - // res.blas_ip_block = static_cast(quake_alloc(ip_need * sizeof(float), node)); - // res.blas_ip_capacity = ip_need; - // } - // if (res.blas_norms_x_cap < max_q) { - // quake_free(res.blas_norms_x, res.blas_norms_x_cap * sizeof(float)); - // res.blas_norms_x = static_cast(quake_alloc(max_q * sizeof(float), node)); - // res.blas_norms_x_cap = max_q; - // } - // if (res.blas_norms_y_cap < db_bs) { - // quake_free(res.blas_norms_y, res.blas_norms_y_cap * sizeof(float)); - // res.blas_norms_y = static_cast(quake_alloc(db_bs * sizeof(float), node)); - // res.blas_norms_y_cap = db_bs; - // } - // } - - const size_t ip_need = BLAS_DB_BS * centroids.size(0); - float * blas_ip_block = static_cast(quake_alloc(ip_need * sizeof(float), 0)); - float * blas_norms_x = static_cast(quake_alloc(BLAS_DB_BS * sizeof(float), 0)); - float * blas_norms_y = static_cast(quake_alloc(BLAS_DB_BS * sizeof(float), 0)); - + size_t max_nq = 0; + for (auto &p : partitions) { + max_nq = std::max(max_nq, (size_t)p->num_vectors_); + } + max_nq = max_nq * 20; // double the max_nq to ensure enough space for batched_scan_list, as assignments may change. // Determine number of clusters and dimension. int n_clusters = centroids.size(0); int d = centroids.size(1); + const size_t ip_need = n_clusters * max_nq; + float * blas_ip_block = static_cast(quake_alloc(ip_need * sizeof(float), 0)); + float * blas_norms_x = static_cast(quake_alloc(max_nq * sizeof(float), 0)); + float * blas_norms_y = static_cast(quake_alloc(n_clusters * sizeof(float), 0)); + vector > buffers = create_buffers(max_nq, 1, (metric == faiss::METRIC_INNER_PRODUCT), n_clusters); + + // Run for the desired number of iterations (if refinement_iterations==0, do one pass). int iterations = (refinement_iterations > 0) ? refinement_iterations : 1; @@ -274,14 +258,23 @@ tuple >> kmeans_refine_partitions( Tensor centroid_counts = torch::zeros({n_clusters}, torch::kInt64); auto centroid_sums_accessor = centroid_sums.accessor(); auto centroid_counts_accessor = centroid_counts.accessor(); + Tensor centroid_ids = torch::arange(n_clusters, torch::kInt64); + auto centroid_ids_ptr = centroid_ids.data_ptr(); vector> prev_partitions = partitions; vector> new_partitions; for (int iter = 0; iter < iterations; iter++) { - if (iter > 0) { centroids = centroid_sums / centroid_counts.unsqueeze(1).to(torch::kFloat32); + + // normalize centroids if using inner product metric + if (metric == faiss::METRIC_INNER_PRODUCT) { + centroids = centroids + / centroids.norm(2,1) + .unsqueeze(1) + .to(torch::kFloat32); + } } // Reset accumulators. @@ -299,7 +292,6 @@ tuple >> kmeans_refine_partitions( float *centroids_ptr = centroids.data_ptr(); - // Process each existing partition. for (auto &part: partitions) { int64_t nvec = part->num_vectors_; if (nvec <= 0) continue; @@ -307,17 +299,10 @@ tuple >> kmeans_refine_partitions( float *part_vecs = (float *) part->codes_; int64_t *part_vec_ids = part->ids_; - // Create batched TopK buffers (k=1 for nearest centroid). - vector > buffers = create_buffers(nvec, 1, false); - // Use batched_scan_list to get nearest centroid for each vector. - int64_t scan_setup_time = 0; - int64_t scan_time = 0; - int64_t scan_push_time = 0; - batched_scan_list(part_vecs, centroids_ptr, - nullptr, + centroid_ids_ptr, nvec, n_clusters, d, @@ -343,10 +328,20 @@ tuple >> kmeans_refine_partitions( centroid_counts_accessor[assigned_cluster]++; new_partitions[assigned_cluster]->append(1, vec_id, (uint8_t *) vec_ptr); + + // reset the buffer for this slot + buffers[i]->reset(); } } // end for each partition + + std::move(new_partitions.begin(), new_partitions.end(), partitions.begin()); } // end iterations + // Clean up and return the refined centroids and partitions. + quake_free(blas_ip_block, ip_need * sizeof(float)); + quake_free(blas_norms_x, max_nq * sizeof(float)); + quake_free(blas_norms_y, BLAS_DB_BS * sizeof(float)); + return std::make_tuple(centroids, partitions); } diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index ec989d9d..248a29f7 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -643,7 +643,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, } } else { /* Build per-partition query lists -------------------------------------- */ - std::vector>> qlist(partition_manager_->nlist()); + std::unordered_map>> qlist; for (int64_t q = 0; q < nQ; ++q) { for (int p = 0; p < partition_ids.size(1); ++p) { int64_t pid = pid_acc[q][p]; @@ -719,9 +719,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, void QueryCoordinator::drain_and_apply_aps(Tensor x, Tensor partition_ids, - bool use_aps, - float recall_target, - int aps_flush_period_us, + shared_ptr search_params, std::shared_ptr timing) { @@ -729,10 +727,26 @@ void QueryCoordinator::drain_and_apply_aps(Tensor x, // compute boundary distances while (total_left_.load(std::memory_order_relaxed) > 0) - std::this_thread::sleep_for(std::chrono::microseconds(aps_flush_period_us)); + std::this_thread::sleep_for(std::chrono::microseconds(search_params->aps_flush_period_us)); + // mark hits + if (search_params->track_hits && maintenance_policy_) { + for (int64_t q = 0; q < nQ; ++q) { + std::vector scanned_ids; + scanned_ids.reserve(partition_ids.size(1)); + for (int p = 0; p < partition_ids.size(1); ++p) { + int64_t pid = partition_ids[q][p].item(); + if (pid < 0) continue; + scanned_ids.emplace_back(pid); + } + maintenance_policy_->record_query_hits(scanned_ids); + } + // maintenance_policy_->record_query_hits(std::vector(scanned_ids.begin(), scanned_ids.end())); + } + + // check if we need to apply APS } @@ -824,8 +838,7 @@ std::shared_ptr QueryCoordinator::worker_scan( Tensor out_dists = torch::empty({nQ, K}, torch::kFloat); // 4) drain results + APS - drain_and_apply_aps(x, partition_ids, use_aps, params->recall_target, - params->aps_flush_period_us, timing); + drain_and_apply_aps(x, partition_ids, params, timing); auto s5 = high_resolution_clock::now(); From 41d3d05da299bedaf190331b727506a7b3e15211 Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 1 Jun 2025 00:07:00 -0500 Subject: [PATCH 300/323] update aps + workers --- src/cpp/bindings/wrap.cpp | 7 +- src/cpp/include/clustering.h | 5 +- src/cpp/include/common.h | 3 +- src/cpp/include/geometry.h | 183 ++- src/cpp/include/query_coordinator.h | 1 + src/cpp/src/clustering.cpp | 7 +- src/cpp/src/maintenance_policies.cpp | 2 + src/cpp/src/query_coordinator.cpp | 224 +++- test/cpp/benchmark.cpp | 14 +- test/cpp/latency_estimator.cpp | 3 +- test/cpp/list_scanning.cpp | 1124 ++++++++--------- test/cpp/quake_index.cpp | 3 +- .../aps_recall_targets/configs/sift1m.yaml | 9 +- .../osdi2025/aps_recall_targets/run.py | 39 +- .../experiments/osdi2025/experiment_runner.py | 2 + test/experiments/osdi2025/experiment_utils.py | 11 +- .../numa_multi_query/configs/sift1m.yaml | 34 +- .../experiments/osdi2025/wiki_workload/run.py | 39 +- 18 files changed, 986 insertions(+), 724 deletions(-) diff --git a/src/cpp/bindings/wrap.cpp b/src/cpp/bindings/wrap.cpp index cfd0f29d..2c8f5f08 100644 --- a/src/cpp/bindings/wrap.cpp +++ b/src/cpp/bindings/wrap.cpp @@ -279,10 +279,8 @@ PYBIND11_MODULE(_bindings, m) { "Time taken for split operations in microseconds.") .def_readonly("delete_time_us", &MaintenanceTimingInfo::delete_time_us, "Time taken for delete operations in microseconds.") - .def_readonly("split_refine_time_us", &MaintenanceTimingInfo::split_refine_time_us, + .def_readonly("refinement_time_us", &MaintenanceTimingInfo::refinement_time_us, "Time taken for refinement of split operations in microseconds.") - .def_readonly("delete_refine_time_us", &MaintenanceTimingInfo::delete_refine_time_us, - "Time taken for refinement of delete operations in microseconds.") .def_readonly("n_splits", &MaintenanceTimingInfo::n_splits, "Number of partition split operations performed.") .def_readonly("n_deletes", &MaintenanceTimingInfo::n_deletes, @@ -293,8 +291,7 @@ PYBIND11_MODULE(_bindings, m) { oss << "\"total_time_us\": " << t.total_time_us << ", "; oss << "\"split_time_us\": " << t.split_time_us << ", "; oss << "\"delete_time_us\": " << t.delete_time_us << ", "; - oss << "\"split_refine_time_us\": " << t.split_refine_time_us << ", "; - oss << "\"delete_refine_time_us\": " << t.delete_refine_time_us << ", "; + oss << "\"refinement_time_us\": " << t.refinement_time_us << ", "; oss << "\"n_splits\": " << t.n_splits << ", "; oss << "\"n_deletes\": " << t.n_deletes; oss << "}"; diff --git a/src/cpp/include/clustering.h b/src/cpp/include/clustering.h index d83d563b..449c99d5 100644 --- a/src/cpp/include/clustering.h +++ b/src/cpp/include/clustering.h @@ -75,8 +75,9 @@ shared_ptr kmeans(Tensor vectors, */ tuple>> kmeans_refine_partitions( Tensor centroids, - vector> index_partitions, + vector> &index_partitions, MetricType metric, - int refinement_iterations = 0); + int refinement_iterations = 0, + int num_threads = -1); #endif //CLUSTERING_H diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index bf1038ed..f840282a 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -261,9 +261,8 @@ struct MaintenanceTimingInfo { int64_t n_splits; ///< Number of splits. int64_t n_deletes; ///< Number of merges. int64_t delete_time_us; ///< Time spent on deletions in microseconds. - int64_t delete_refine_time_us; ///< Time spent on deletions with refinement in microseconds. int64_t split_time_us; ///< Time spent on splits in microseconds. - int64_t split_refine_time_us; ///< Time spent on splits with refinement in microseconds. + int64_t refinement_time_us; ///< Time spent on refinement in microseconds. int64_t total_time_us; ///< Total time spent in microseconds. }; diff --git a/src/cpp/include/geometry.h b/src/cpp/include/geometry.h index 5e54890e..5abbc7f9 100644 --- a/src/cpp/include/geometry.h +++ b/src/cpp/include/geometry.h @@ -55,48 +55,6 @@ inline void print_array(const float *array, int dimension) { std::cout << std::endl << std::endl; } -inline std::vector -compute_boundary_distances(const torch::Tensor& query, - std::vector& centroids, - bool euclidean /* kept for API */ ) -{ - int dim = query.size(0); - const float* q = query.data_ptr(); - - /* --- ensure centroids[0] is the nearest --------------------- */ - size_t nearest = 0; - float best_d2 = std::numeric_limits::max(); - for (size_t i = 0; i < centroids.size(); ++i) { - float d2 = faiss::fvec_L2sqr(q, centroids[i], dim); - if (d2 < best_d2) { best_d2 = d2; nearest = i; } - } - if (nearest != 0) std::swap(centroids[0], centroids[nearest]); - - const float* c0 = centroids[0]; - std::vector d(centroids.size(), 0.0f); - std::vector v(dim); - - for (size_t j = 1; j < centroids.size(); ++j) - { - const float* cj = centroids[j]; - - /* v = cj - c0, ||v|| */ - faiss::fvec_sub(dim, cj, c0, v.data()); - float v_norm = std::sqrt( - faiss::fvec_inner_product(v.data(), v.data(), dim)); - - /* b = ½ (||cj||² - ||c0||²) */ - float b = 0.5f * ( - faiss::fvec_inner_product(cj, cj, dim) - - faiss::fvec_inner_product(c0, c0, dim)); - - /* signed distance (q·v − b) / ||v|| */ - float dot_qv = faiss::fvec_inner_product(q, v.data(), dim); - d[j] = std::fabs(dot_qv - b) / v_norm; // plane distance - } - return d; // d[0] = 0 -} - inline double incomplete_beta(double a, double b, double x) { if (x < 0.0 || x > 1.0) return 1.0 / 0.0; @@ -203,8 +161,57 @@ inline double log_hypersphere_volume(double radius, int dimension) { return log_volume; } + +inline std::vector +compute_boundary_distances(const Tensor& query, + std::vector& centroids, + bool euclidean) +{ + const int dim = query.size(0); + const float* q = query.data_ptr(); + + const float* c0 = centroids[0]; + std::vector dist(centroids.size(), 0.0f); + + std::vector v(dim); // c_j - c0 + std::vector m(dim); // midpoint for IP + + for (std::size_t j = 1; j < centroids.size(); ++j) { + const float* cj = centroids[j]; + + if (euclidean) { + /* plane distance d = |q·v − b| / ||v|| , b = ½(||cj||²−||c0||²) */ + faiss::fvec_sub(dim, cj, c0, v.data()); + float v_norm = std::sqrt(faiss::fvec_inner_product(v.data(), v.data(), dim)); + float b = 0.5f * (faiss::fvec_inner_product(cj, cj, dim) - + faiss::fvec_inner_product(c0, c0, dim)); + float dot_qv = faiss::fvec_inner_product(q, v.data(), dim); + dist[j] = std::fabs(dot_qv - b) / (v_norm + 1e-12f); + } else { + faiss::fvec_sub(dim, cj, c0, v.data()); // v = cj - c0 + float v_norm = std::sqrt(faiss::fvec_inner_product(v.data(), v.data(), dim)); + divide_array_by_constant(v.data(), v_norm, v.data(), dim); // v̂ + float s = std::fabs(faiss::fvec_inner_product(q, v.data(), dim)); + s = std::clamp(s, 0.0f, 1.0f); + dist[j] = std::asin(s); // 0–π/2 + + // /* unit-sphere model – distance is polar angle to great-circle bisector between c0 and cj. */ + // add_arrays(c0, cj, m.data(), dim); // midpoint vector + // float m_norm = std::sqrt(faiss::fvec_inner_product(m.data(), m.data(), dim)); + // if (m_norm > 0) divide_array_by_constant(m.data(), m_norm, m.data(), dim); + // float cos_ang = faiss::fvec_inner_product(q, m.data(), dim); + // cos_ang = std::clamp(cos_ang, -1.0f, 1.0f); + // dist[j] = std::acos(cos_ang); // radians + } + } + return dist; // dist[0] = 0 by construction +} + inline double hyperspherical_cap_volume(double radius, double boundary_distance, int d, bool use_precomputed = true, bool euclidean = true) { + + if (euclidean) { + // Ensure boundary distance is non-negative double boundary_distance = std::max(0.0, boundary_distance); @@ -224,11 +231,32 @@ inline double hyperspherical_cap_volume(double radius, double boundary_distance, return std::clamp(0.5 * I, 0.0, 0.5); } else { - // v_i = (1/2) * [ I( sin^2(phi/2); d/2, 1/2 ) - I( sin^2(theta_i/2); d/2, 1/2 ) ] - double log_inc_beta = std::log(incomplete_beta((d - 1) / 2.0, 0.5, std::sin(radius / 2.0) * std::sin(radius / 2.0))); - double log_inc_beta_boundary = std::log(incomplete_beta((d - 1) / 2.0, 0.5, std::sin(boundary_distance / 2.0) * std::sin(boundary_distance / 2.0))); - double log_cap_volume = std::log(0.5) + log_inc_beta - log_inc_beta_boundary; - return log_cap_volume; + // spherical / IP ----------------------------------------------------------------- + double theta_q = radius; // query cap angle (rad) + double delta = boundary_distance; // distance to bisector (rad) + + /* 1. trivial cases ------------------------------------------------------------ */ + if (delta >= theta_q) return 0.0; // cap entirely in c0 + if (theta_q >= M_PI_2 - delta) return 1.0; // cap entirely in cj + + /* 2. general case: Lee & Kim (2014) cases 9–10 -------------------------------- */ + double t = std::tan(delta) / std::tan(theta_q); // 0 ≤ t < 1 + t = std::clamp(t, 0.0, 1.0); // numerical safety + + double alpha = std::acos(t); // 0 < α < π/2 + double x = std::sin(alpha) * std::sin(alpha); // 0 < x < 1 + + double a = 0.5 * (d - 1); + double b = 0.5; + + double Ix = incomplete_beta(a, b, x); // regularised + return 0.5 * Ix; // leakage fraction + + + // double log_inc_beta = std::log(incomplete_beta((d - 1) / 2.0, 0.5, std::sin(radius / 2.0) * std::sin(radius / 2.0))); + // double log_inc_beta_boundary = std::log(incomplete_beta((d - 1) / 2.0, 0.5, std::sin((radius - boundary_distance) / 2.0) * std::sin(radius - boundary_distance) / 2.0)); + // double log_cap_volume = std::log(0.5) + log_inc_beta - log_inc_beta_boundary; + // return std::exp(log_cap_volume); } } @@ -243,6 +271,10 @@ compute_recall_profile(const std::vector& boundary_distances, const int m = static_cast(boundary_distances.size()); const float eps = 1e-9f; + if (!euclidean) { + query_radius = std::acos(query_radius); // Convert to angle in radians for spherical model + } + // --- Edge Cases --- if (m <= 1) { if (m == 1) return {1.0f}; // Only the central partition exists @@ -268,6 +300,8 @@ compute_recall_profile(const std::vector& boundary_distances, float S1_for_norm = 0.0f; for (int j = 1; j < m; ++j) S1_for_norm += norm_vols[j]; + // S1_for_norm = 1.0; + if (S1_for_norm > eps) { for (int j = 1; j < m; ++j) norm_vols[j] /= S1_for_norm; } else { @@ -285,20 +319,32 @@ compute_recall_profile(const std::vector& boundary_distances, // Ensure P_prime is non-negative for (int k = 1; k < m; ++k) P_prime[k] = std::max(0.0f, P_prime[k]); - // // if the cluster_sizes are given, scale P_prime[k] by the size of the cluster. this is a rudimentary density estimation - // if (partition_sizes.size() > 0) { - // for (int k = 1; k < m; ++k) { - // if (partition_sizes[k] > 0) { - // P_prime[k] *= static_cast(partition_sizes[k]); - // } - // } - // } - - // normalize probs std::vector probs(m, 0.0f); probs[0] = P0; + // for (int k = 1; k < m; ++k) { + // if (P_prime_sum > eps) { + // probs[k] = norm_vols[k]; + // } else { + // probs[k] = 0.0f; // If sum is negligible, set to zero + // } + // } + // + // // normalize probabilities + // float S = 0.0f; + // for (int k = 0; k < m; ++k) S += probs[k]; + // if (S > eps) { + // for (int k = 0; k < m; ++k) { + // probs[k] /= S; + // } + // } else { + // // If S is zero, all probabilities remain zero + // for (int k = 0; k < m; ++k) { + // probs[k] = 0.0f; + // } + // } + float target = 1.0f - P0; // Ensure target probability for neighbors is valid [0, 1] target = std::clamp(target, 0.0f, 1.0f); @@ -334,6 +380,29 @@ compute_recall_profile(const std::vector& boundary_distances, } } + // if the cluster_sizes are given, scale probs by the size of the cluster and renormalize. this is a rudimentary density estimation + // if (partition_sizes.size() > 0) { + // for (int k = 1; k < m; ++k) { + // if (partition_sizes[k] > 0) { + // probs[k] *= static_cast(partition_sizes[k]); + // } + // } + // } + + // // renormalize the probabilities to sum to 1 + // float S = 0.0f; + // for (int k = 0; k < m; ++k) S += probs[k]; + // if (S > eps) { + // for (int k = 0; k < m; ++k) { + // probs[k] /= S; + // } + // } else { + // // If S is zero, all probabilities remain zero + // for (int k = 0; k < m; ++k) { + // probs[k] = 0.0f; + // } + // } + return probs; } diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 4e0193b8..afa4d39e 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -124,6 +124,7 @@ class QueryCoordinator { std::vector job_buffer_; int next_job_id_ = 0; ///< ID for the next job to be processed. vector> query_dist_pivots_; ///< Pivots for each query to speed up sorting + vector> query_done_flags_; ///< Flags to indicate if a query is done from APS vector>> job_flags_; ///< Flags to track job completion std::atomic job_pull_time_ns = 0; ///< Time spent pulling jobs from the queue. std::atomic job_process_time_ns = 0; ///< Time spent processing jobs. diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index 6b3a884d..5a46da6a 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -10,6 +10,7 @@ #include "index_partition.h" #include #include +#include #ifdef QUAKE_ENABLE_GPU #include @@ -228,11 +229,13 @@ shared_ptr kmeans(Tensor vectors, } } + tuple >> kmeans_refine_partitions( Tensor centroids, - vector> partitions, + vector> &partitions, MetricType metric, - int refinement_iterations) { + int refinement_iterations, + int num_threads) { size_t max_nq = 0; for (auto &p : partitions) { diff --git a/src/cpp/src/maintenance_policies.cpp b/src/cpp/src/maintenance_policies.cpp index 2d357e68..106bc895 100644 --- a/src/cpp/src/maintenance_policies.cpp +++ b/src/cpp/src/maintenance_policies.cpp @@ -183,6 +183,7 @@ shared_ptr MaintenancePolicy::perform_maintenance() { local_refinement(split_partitions->partition_ids); } auto end_total = steady_clock::now(); + int64_t refinement_time_us = static_cast(duration_cast(end_total - end_split).count()); // STEP 6: Clean up any empty partitions vector empty_ids = {}; @@ -199,6 +200,7 @@ shared_ptr MaintenancePolicy::perform_maintenance() { shared_ptr timing_info = std::make_shared(); timing_info->delete_time_us = duration_cast(end_delete - start_delete).count(); timing_info->split_time_us = duration_cast(end_split - start_split).count(); + timing_info->refinement_time_us = refinement_time_us; timing_info->total_time_us = duration_cast(end_total - start_total).count(); timing_info->n_splits = static_cast(partitions_to_split.size()); diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 248a29f7..ade73c53 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -110,6 +110,13 @@ void QueryCoordinator::merge_worker_fn(int mid) { if (rj.query_id == -1) // poison pill return; + if (rj.distances.empty()) { + // empty result, nothing to do + --per_query_total_left_[rj.query_id]; + --total_left_; + continue; + } + // single cast, based on the Compare template using Handler = typename faiss::HeapBlockResultHandler::SingleResultHandler; auto* h = static_cast(MR.handlers[rj.query_id]); @@ -122,32 +129,31 @@ void QueryCoordinator::merge_worker_fn(int mid) { query_dist_pivots_[rj.query_id].store(h->threshold, std::memory_order_relaxed); + per_query_total_left_[rj.query_id]--; + // once all ranks for this query are in, finalize & sort - if (!job_flags_[rj.query_id][rj.rank]) { - job_flags_[rj.query_id][rj.rank] = true; - if (--per_query_total_left_[rj.query_id] == 0) { - h->end(); - - // pack into pairs for sorting - int k = h->k; - std::vector> result; - result.reserve(k); - for (int i = 0; i < k; ++i) { - result.emplace_back(h->heap_dis[i], h->heap_ids[i]); - } + if (per_query_total_left_[rj.query_id] <= 0) { + h->end(); + + // pack into pairs for sorting + int k = h->k; + std::vector> result; + result.reserve(k); + for (int i = 0; i < k; ++i) { + result.emplace_back(h->heap_dis[i], h->heap_ids[i]); + } - // for CMin (inner-product) we want descending distances - // for CMax (L2) we want ascending distances - auto cmp = [](auto& a, auto& b) { - return Compare::cmp(a.first, b.first); - }; - std::sort(result.begin(), result.end(), cmp); - - // write them back - for (int i = 0; i < k; ++i) { - h->heap_dis[i] = result[i].first; - h->heap_ids[i] = result[i].second; - } + // for CMin (inner-product) we want descending distances + // for CMax (L2) we want ascending distances + auto cmp = [](auto& a, auto& b) { + return Compare::cmp(b.first, a.first); + }; + std::sort(result.begin(), result.end(), cmp); + + // write them back + for (int i = 0; i < k; ++i) { + h->heap_dis[i] = result[i].first; + h->heap_ids[i] = result[i].second; } } --total_left_; @@ -260,6 +266,13 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, NUMAResources &nr) { auto start = std::chrono::high_resolution_clock::now(); + + // check that the job has not been processed yet + if (query_done_flags_[job.query_id].load(std::memory_order_relaxed)) { + enqueue_result_job(ResultJob{job.query_id, job.rank, {}, {}}); + return; + } + // ensure buffers if (res.topk_buffer_pool.size() < 1) { res.topk_buffer_pool.resize(1); @@ -300,6 +313,8 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, return; // Important to return after enqueueing the placeholder } + job_flags_[job.query_id][job.rank].store(true, std::memory_order_relaxed); // Mark this job as processed + scan_list(nr.local_query_buffer + (job.query_id * D), codes, ids, @@ -406,17 +421,33 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, // gather queries float *qptr = nullptr; float *dst = res.batch_queries; + vector query_ids; + vector ranks; + query_ids.reserve(Q); + ranks.reserve(Q); + int64_t offset = 0; for (int64_t i = 0; i < Q; ++i) { + int qid = (*job.query_ids)[i]; - const float *src = nr.local_query_buffer + size_t(qid) * D; - std::memcpy(dst + i * D, src, D * sizeof(float)); + // check that the job has not been processed yet + if (job_flags_[qid][job.rank]) { + // already processed, skip + enqueue_result_job(ResultJob{qid, job.rank, {}, {}});; + } else { + // copy query vector to the local buffer + const float *src = nr.local_query_buffer + size_t(qid) * D; + std::memcpy(dst + offset, src, D * sizeof(float)); + query_ids.push_back(qid); + ranks.push_back((*job.ranks)[i]); + offset += D; + } } qptr = dst; vector *> pivots; - pivots.resize(job.num_queries); - for (int64_t i = 0; i < Q; ++i) { - int qid = (*job.query_ids)[i]; + pivots.resize(query_ids.size()); + for (int64_t i = 0; i < query_ids.size(); ++i) { + int qid = query_ids[i]; pivots[i] = &query_dist_pivots_[qid]; } @@ -462,10 +493,10 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, start = std::chrono::high_resolution_clock::now(); // collect results for this chunk std::vector results_batch; - results_batch.reserve(Q); - for (int64_t i = 0; i < Q; ++i) { - int global_q = (*job.query_ids)[i]; - int rank_q = (*job.ranks) [i]; + results_batch.reserve(query_ids.size()); + for (int64_t i = 0; i < query_ids.size(); ++i) { + int global_q = query_ids[i]; + int rank_q = ranks[i]; auto tv = res.topk_buffer_pool[i]->get_topk(false); auto ti = res.topk_buffer_pool[i]->get_topk_indices(false); enqueue_result_job(ResultJob{global_q, rank_q, std::move(tv), std::move(ti)}); @@ -556,8 +587,10 @@ void QueryCoordinator::init_global_buffers(int64_t nQ, } query_dist_pivots_ = vector>(nQ); + query_done_flags_ = vector>(nQ); for (int64_t q = 0; q < nQ; ++q) { query_dist_pivots_[q].store(max_val, std::memory_order_relaxed); + query_done_flags_[q].store(false, std::memory_order_relaxed); } } @@ -623,9 +656,30 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, auto pid_acc = partition_ids.accessor(); if (!params->batched_scan) { // one job per (q,p) - for (int64_t q = 0; q < nQ; ++q) { - const float* qptr = xptr + q*D; - for (int p = 0; p < partition_ids.size(1); ++p) { + + // // order by query id then partition rank + // for (int64_t q = 0; q < nQ; ++q) { + // const float* qptr = xptr + q*D; + // for (int p = 0; p < partition_ids.size(1); ++p) { + // int64_t pid = pid_acc[q][p]; + // if (pid < 0) continue; + // ScanJob job; + // job.job_id = next_job_id_; + // job.is_batched = false; + // job.query_id = (int)q; + // job.partition_id = pid; + // job.k = params->k; + // job.rank = p; + // job_buffer_.push_back(job); + // numa_resources_[core_to_numa[pid % num_workers_]].job_queue.enqueue(next_job_id_); + // next_job_id_++; + // total_left_.fetch_add(1, std::memory_order_relaxed); + // } + // } + + // order by partition rank then query id + for (int p = 0; p < partition_ids.size(1); ++p) { + for (int64_t q = 0; q < nQ; ++q) { int64_t pid = pid_acc[q][p]; if (pid < 0) continue; ScanJob job; @@ -717,19 +771,96 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, } -void QueryCoordinator::drain_and_apply_aps(Tensor x, +void QueryCoordinator::drain_and_apply_aps(Tensor queries, Tensor partition_ids, shared_ptr search_params, std::shared_ptr timing) { - int64_t nQ = x.size(0), D = x.size(1); + int64_t nQ = queries.size(0), D = queries.size(1); + + auto start = std::chrono::high_resolution_clock::now(); // compute boundary distances + bool use_aps = (search_params->recall_target > 0 && parent_); + vector> boundary_distances; + vector curr_radii; + vector> recall_profiles; + if (use_aps) { + boundary_distances.resize(nQ); + recall_profiles.resize(nQ); + if (metric_ == faiss::METRIC_INNER_PRODUCT) { + curr_radii.resize(nQ, -std::numeric_limits::infinity()); + } else { + curr_radii.resize(nQ, std::numeric_limits::infinity()); + } + for (int64_t q = 0; q < nQ; ++q) { + vector curr_pids_vec(partition_ids[q].data_ptr(), + partition_ids[q].data_ptr() + partition_ids[q].size(0)); + vector curr_centroids_vec = parent_->partition_manager_->get_vectors(curr_pids_vec); + boundary_distances[q] = compute_boundary_distances(queries[q], + curr_centroids_vec, + metric_ == faiss::METRIC_L2); + } - while (total_left_.load(std::memory_order_relaxed) > 0) + } + auto end = std::chrono::high_resolution_clock::now(); + timing->boundary_distance_time_ns = + std::chrono::duration_cast(end - start).count(); + + timing->aps_time_ns = 0; + while (total_left_.load(std::memory_order_relaxed) > 0) { std::this_thread::sleep_for(std::chrono::microseconds(search_params->aps_flush_period_us)); + if (use_aps) { + // compute recall profile and mark jobs complete + start = std::chrono::high_resolution_clock::now(); + for (int64_t q = 0; q < nQ; ++q) { + int n_left = per_query_total_left_[q].load(std::memory_order_relaxed); + bool query_done = query_done_flags_[q].load(std::memory_order_relaxed); + if (!query_done && n_left < partition_ids.size(1)) { + + float query_radius = query_dist_pivots_[q].load(std::memory_order_relaxed); + + // check if the query radius has changed + float rel_difference = std::abs((curr_radii[q] - query_radius) / query_radius); + + if (rel_difference > search_params->recompute_threshold) { + // compute the recall profile for queries that are in progress + vector curr_pids_vec(partition_ids[q].data_ptr(), + partition_ids[q].data_ptr() + partition_ids[q].size(0)); + + recall_profiles[q] = compute_recall_profile(boundary_distances[q], + query_radius, + D, + {}, + search_params->use_precomputed, + metric_ == faiss::METRIC_L2); + + curr_radii[q] = query_radius; + + } + + float recall_estimate = 0.0f; + + int n_scanned = 0; + for (int p = 0; p < partition_ids.size(1); ++p) { + if (job_flags_[q][p].load(std::memory_order_relaxed)) { + n_scanned++; + recall_estimate += recall_profiles[q][p]; + } + } + + if (recall_estimate >= search_params->recall_target) { + query_done_flags_[q].store(true, std::memory_order_relaxed); + } + } + } + end = std::chrono::high_resolution_clock::now(); + timing->aps_time_ns += + std::chrono::duration_cast(end - start).count(); + } + } // mark hits if (search_params->track_hits && maintenance_policy_) { @@ -737,17 +868,16 @@ void QueryCoordinator::drain_and_apply_aps(Tensor x, std::vector scanned_ids; scanned_ids.reserve(partition_ids.size(1)); for (int p = 0; p < partition_ids.size(1); ++p) { - int64_t pid = partition_ids[q][p].item(); - if (pid < 0) continue; - scanned_ids.emplace_back(pid); + if (job_flags_[q][p].load(std::memory_order_relaxed)) { + int64_t pid = partition_ids[q][p].item(); + if (pid < 0) continue; + scanned_ids.emplace_back(pid); + } } + timing->partitions_scanned += scanned_ids.size(); maintenance_policy_->record_query_hits(scanned_ids); } - // maintenance_policy_->record_query_hits(std::vector(scanned_ids.begin(), scanned_ids.end())); } - - - // check if we need to apply APS } std::shared_ptr @@ -868,7 +998,7 @@ std::shared_ptr QueryCoordinator::worker_scan( } - // // // print out the per-core resource timers; + // // print out the per-core resource timers; // for (int i = 0; i < num_workers_; ++i) { // std::cout << "[QueryCoordinator::worker_scan] Core " << i << ": " // << "job_counter=" << core_resources_[i].job_counter << " " diff --git a/test/cpp/benchmark.cpp b/test/cpp/benchmark.cpp index e9a836c3..ed3497cb 100644 --- a/test/cpp/benchmark.cpp +++ b/test/cpp/benchmark.cpp @@ -29,7 +29,7 @@ using torch::Tensor; static const int64_t DIM = 128; static const int64_t NUM_VECTORS = 100000; // number of database vectors static const int64_t N_LIST = 1000; // number of clusters for IVF -static const int64_t NUM_QUERIES = 10000; // number of queries for search benchmark +static const int64_t NUM_QUERIES = 1000; // number of queries for search benchmark static const int64_t K = 1; // top-K neighbors static const int64_t N_PROBE = 20; // number of probes for IVF static const int64_t N_WORKERS = 12; // number of workers for parallel query coordinator @@ -517,13 +517,13 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { QuakeIndex index; auto build_params = std::make_shared(); build_params->nlist = 100; - build_params->metric = "l2"; + build_params->metric = "ip"; build_params->niter = 5; build_params->num_workers = 1; auto maintenance_params = std::make_shared(); - maintenance_params->refinement_radius = 0; - maintenance_params->refinement_iterations = 0; + maintenance_params->refinement_radius = 50; + maintenance_params->refinement_iterations = 3; maintenance_params->split_threshold_ns = 1; maintenance_params->delete_threshold_ns = 1; maintenance_params->enable_delete_rejection = false; @@ -537,7 +537,7 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { // add level auto parent_index_build_params = std::make_shared(); parent_index_build_params->nlist = 100; - parent_index_build_params->metric = "l2"; + parent_index_build_params->metric = "ip"; parent_index_build_params->niter = 5; parent_index_build_params->num_workers = 1; // build_params->parent_params = parent_index_build_params; @@ -573,12 +573,12 @@ TEST(QuakeIndexStressTest, SearchAddRemoveMaintenanceTest) { auto search_params = std::make_shared(); search_params->nprobe = 12; search_params->k = 10; - search_params->batched_scan = false; + search_params->batched_scan = true; search_params->num_threads = 1; auto parent_search_params = std::make_shared(); parent_search_params->nprobe = 50; - parent_search_params->batched_scan = false; + parent_search_params->batched_scan = true; search_params->parent_params = parent_search_params; start = std::chrono::high_resolution_clock::now(); diff --git a/test/cpp/latency_estimator.cpp b/test/cpp/latency_estimator.cpp index 495ec149..5cb95220 100644 --- a/test/cpp/latency_estimator.cpp +++ b/test/cpp/latency_estimator.cpp @@ -28,7 +28,8 @@ static float measure_actual_latency(const ListScanLatencyEstimator& estimator, uint64_t total_latency_ns = 0; for (int m = 0; m < estimator.n_trials_; ++m) { auto start = std::chrono::high_resolution_clock::now(); - scan_list(query_ptr, vectors_ptr, ids_ptr, n, estimator.d_, *topk_buffer); + scan_list(query_ptr, vectors_ptr, ids_ptr, n, estimator.d_, *topk_buffer, + faiss::METRIC_L2, 10000000.0); auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(end - start); diff --git a/test/cpp/list_scanning.cpp b/test/cpp/list_scanning.cpp index 518972e0..c90442ef 100644 --- a/test/cpp/list_scanning.cpp +++ b/test/cpp/list_scanning.cpp @@ -1,562 +1,562 @@ -// list_scanning_test.cpp - -#include -#include -#include -#include -#include -#include - -#include "list_scanning.h" // Ensure this path is correct - -// Test fixture for list scanning functions -class ListScanningTest : public ::testing::Test { -protected: - // Helper function to create a TopkBuffer - std::shared_ptr create_buffer(int k, bool is_descending) { - return std::make_shared>(k, is_descending, k * 100, 0); - } -}; - -// Test scan_list with single query and L2 metric -TEST_F(ListScanningTest, ScanList_SingleQuery_L2) { - int k = 2; - bool is_descending = false; // L2 - auto buffer = create_buffer(k, is_descending); - - // Define a query vector and a list of vectors - float query_vec[3] = {1.0f, 0.0f, 0.0f}; - float list_vecs[4 * 3] = { - 1.0f, 0.0f, 0.0f, // Distance: 0.0 - 0.0f, 1.0f, 0.0f, // Distance: 2.0 - 1.0f, 1.0f, 0.0f, // Distance: 1.0 - 2.0f, 0.0f, 0.0f // Distance: 1.0 - }; - int64_t list_ids[4] = {10, 20, 30, 40}; - - // Expected top-k: 0.0 (id=10), 1.0 (id=30 or 40) - scan_list(query_vec, list_vecs, list_ids, 4, 3, *buffer, faiss::METRIC_L2); - - std::vector expected_dists = {0.0f, 1.0f}; - std::vector expected_ids = {10, 30}; // Could also be {10, 40} based on order - - auto topk_dists = buffer->get_topk(); - auto topk_ids = buffer->get_topk_indices(); - - ASSERT_EQ(topk_dists.size(), expected_dists.size()); - ASSERT_EQ(topk_ids.size(), expected_ids.size()); - - EXPECT_FLOAT_EQ(topk_dists[0], expected_dists[0]); - EXPECT_EQ(topk_ids[0], expected_ids[0]); - - // Second element could be id=30 or id=40 - EXPECT_FLOAT_EQ(topk_dists[1], expected_dists[1]); - EXPECT_TRUE(topk_ids[1] == 30 || topk_ids[1] == 40); -} - -// Test scan_list with single query and Inner Product metric -TEST_F(ListScanningTest, ScanList_SingleQuery_InnerProduct) { - int k = 2; - bool is_descending = true; // Inner Product - auto buffer = create_buffer(k, is_descending); - - // Define a query vector and a list of vectors - float query_vec[3] = {1.0f, 0.0f, 0.0f}; - float list_vecs[4 * 3] = { - 1.0f, 0.0f, 0.0f, // Inner product: 1.0 - 0.0f, 1.0f, 0.0f, // Inner product: 0.0 - 1.0f, 1.0f, 0.0f, // Inner product: 1.0 - 2.0f, 0.0f, 0.0f // Inner product: 2.0 - }; - int64_t list_ids[4] = {10, 20, 30, 40}; - - // Expected top-k: 2.0 (id=40), 1.0 (id=10 or 30) - scan_list(query_vec, list_vecs, list_ids, 4, 3, *buffer, faiss::METRIC_INNER_PRODUCT); - - std::vector expected_dists = {2.0f, 1.0f}; - std::vector expected_ids = {40, 10}; // Could also be {40, 30} - - auto topk_dists = buffer->get_topk(); - auto topk_ids = buffer->get_topk_indices(); - - ASSERT_EQ(topk_dists.size(), expected_dists.size()); - ASSERT_EQ(topk_ids.size(), expected_ids.size()); - - EXPECT_FLOAT_EQ(topk_dists[0], expected_dists[0]); - EXPECT_EQ(topk_ids[0], expected_ids[0]); - - // Second element could be id=10 or id=30 - EXPECT_FLOAT_EQ(topk_dists[1], expected_dists[1]); - EXPECT_TRUE(topk_ids[1] == 10 || topk_ids[1] == 30); -} - -// Test batched_scan_list with multiple queries and L2 metric -TEST_F(ListScanningTest, BatchedScanList_MultipleQueries_L2) { - int k = 2; - MetricType metric = faiss::METRIC_L2; - - // Define two query vectors (dim=3) - float query_vecs[2 * 3] = { - 1.0f, 0.0f, 0.0f, // Query 0 - 0.0f, 1.0f, 0.0f // Query 1 - }; - - // Define a list of vectors (dim=3) - float list_vecs[4 * 3] = { - 1.0f, 0.0f, 0.0f, // Q0: 0.0, Q1: 2.0 - 0.0f, 1.0f, 0.0f, // Q0: 2.0, Q1: 0.0 - 1.0f, 1.0f, 0.0f, // Q0: 1.0, Q1: 1.0 - 2.0f, 0.0f, 0.0f // Q0: 4.0, Q1: 2.0 - }; - int64_t list_ids[4] = {10, 20, 30, 40}; - - // Create TopkBuffers for each query - std::vector> topk_buffers = create_buffers(2, k, false); // L2 metric (is_descending=false) - - // Perform batched_scan_list - batched_scan_list( - query_vecs, - list_vecs, - list_ids, - 2, // num_queries - 4, // list_size - 3, // dim - topk_buffers, - metric - ); - - // Expected results: - // Query 0: top-k distances: 0.0 (id=10), 1.0 (id=30) - // Query 1: top-k distances: 0.0 (id=20), 1.0 (id=30) - - // Verify Query 0 - auto topk_q0 = topk_buffers[0]->get_topk(); - auto topk_q0_ids = topk_buffers[0]->get_topk_indices(); - ASSERT_EQ(topk_q0.size(), 2); - EXPECT_FLOAT_EQ(topk_q0[0], 0.0f); - EXPECT_EQ(topk_q0_ids[0], 10); - EXPECT_FLOAT_EQ(topk_q0[1], 1.0f); - EXPECT_EQ(topk_q0_ids[1], 30); - - // Verify Query 1 - auto topk_q1 = topk_buffers[1]->get_topk(); - auto topk_q1_ids = topk_buffers[1]->get_topk_indices(); - ASSERT_EQ(topk_q1.size(), 2); - EXPECT_FLOAT_EQ(topk_q1[0], 0.0f); - EXPECT_EQ(topk_q1_ids[0], 20); - EXPECT_FLOAT_EQ(topk_q1[1], 1.0f); - EXPECT_EQ(topk_q1_ids[1], 30); -} - -// Test batched_scan_list with multiple queries and Inner Product metric -TEST_F(ListScanningTest, BatchedScanList_MultipleQueries_InnerProduct) { - int k = 2; - MetricType metric = faiss::METRIC_INNER_PRODUCT; - - // Define two query vectors (dim=3) - float query_vecs[2 * 3] = { - 1.0f, 0.0f, 0.0f, // Query 0 - 0.0f, 1.0f, 0.0f // Query 1 - }; - - // Define a list of vectors (dim=3) - float list_vecs[4 * 3] = { - 1.0f, 0.0f, 0.0f, // Inner products [1.0, 0.0] (id=10) - 0.0f, 1.0f, 0.0f, // Inner products [0.0, 1.0] (id=20) - .5f, 1.5f, 0.0f, // Inner products [.5, 1.5] (id=30) - 2.0f, 0.0f, 0.0f // Inner products [2.0, 0.0] (id=40) - }; - int64_t list_ids[4] = {10, 20, 30, 40}; - - // Create TopkBuffers for each query - std::vector> topk_buffers = create_buffers(2, k, true); // Inner Product metric (is_descending=true) - - // Perform batched_scan_list - batched_scan_list( - query_vecs, - list_vecs, - list_ids, - 2, // num_queries - 4, // list_size - 3, // dim - topk_buffers, - metric - ); - - // Expected results: - // Query 0: top-k scores: 2.0 (id=40), 1.0 (id=10) - // Query 1: top-k scores: 1.5 (id=30), 1.0 (id=20) - - // Verify Query 0 - auto topk_q0 = topk_buffers[0]->get_topk(); - auto topk_q0_ids = topk_buffers[0]->get_topk_indices(); - - std::cout << "topk_q0: " << topk_q0[0] << " " << topk_q0[1] << std::endl; - std::cout << "topk_q0_ids: " << topk_q0_ids[0] << " " << topk_q0_ids[1] << std::endl; - - ASSERT_EQ(topk_q0.size(), 2); - EXPECT_FLOAT_EQ(topk_q0[0], 2.0f); - EXPECT_TRUE(topk_q0_ids[0] == 40); - EXPECT_FLOAT_EQ(topk_q0[1], 1.0f); - EXPECT_TRUE(topk_q0_ids[1] == 10 || topk_q0_ids[1] == 20); - - // Verify Query 1 - auto topk_q1 = topk_buffers[1]->get_topk(); - auto topk_q1_ids = topk_buffers[1]->get_topk_indices(); - ASSERT_EQ(topk_q1.size(), 2); - EXPECT_FLOAT_EQ(topk_q1[0], 1.5f); - EXPECT_TRUE(topk_q1_ids[0] == 30); - EXPECT_FLOAT_EQ(topk_q1[1], 1.0f); - EXPECT_TRUE(topk_q1_ids[1] == 20); -} - -// Test batched_scan_list without list_ids (list_ids == nullptr) -TEST_F(ListScanningTest, BatchedScanList_NoListIds) { - int k = 2; - MetricType metric = faiss::METRIC_L2; - - // Define two query vectors - float query_vecs[2 * 2] = { - 1.0f, 0.0f, // Query 0 - 0.0f, 1.0f // Query 1 - }; - - // Define a list of vectors - float list_vecs[3 * 2] = { - 1.0f, 0.0f, // Distance for Q0: 0.0, Q1: 2.0 - 0.0f, 1.0f, // Distance for Q0: 2.0, Q1: 0.0 - 1.0f, 1.0f // Distance for Q0: 1.0, Q1: 1.0 - }; - // list_ids == nullptr - - // Create TopkBuffers for each query - std::vector> topk_buffers = create_buffers(2, k, false); // Inner Product metric (is_descending=true) - - - // Perform batched_scan_list - batched_scan_list( - query_vecs, - list_vecs, - nullptr, // list_ids - 2, // num_queries - 3, // list_size - 2, // dim - topk_buffers, - metric - ); - - // Expected results: - // Query 0: top-k distances: 0.0 (id=0), 1.0 (id=2) - // Query 1: top-k distances: 0.0 (id=1), 1.0 (id=2) - - std::vector expected_dists_q0 = {0.0f, 1.0f}; - std::vector expected_ids_q0 = {0, 2}; - std::vector expected_dists_q1 = {0.0f, 1.0f}; - std::vector expected_ids_q1 = {1, 2}; - - // Verify Query 0 - auto topk_q0 = topk_buffers[0]->get_topk(); - auto topk_q0_ids = topk_buffers[0]->get_topk_indices(); - - std::cout << "topk_q0: " << topk_q0[0] << " " << topk_q0[1] << std::endl; - std::cout << "topk_q0_ids: " << topk_q0_ids[0] << " " << topk_q0_ids[1] << std::endl; - - ASSERT_EQ(topk_q0.size(), 2); - EXPECT_FLOAT_EQ(topk_q0[0], 0.0f); - EXPECT_EQ(topk_q0_ids[0], 0); - EXPECT_FLOAT_EQ(topk_q0[1], 1.0f); - EXPECT_EQ(topk_q0_ids[1], 2); - - // Verify Query 1 - auto topk_q1 = topk_buffers[1]->get_topk(); - auto topk_q1_ids = topk_buffers[1]->get_topk_indices(); - ASSERT_EQ(topk_q1.size(), 2); - EXPECT_FLOAT_EQ(topk_q1[0], 0.0f); - EXPECT_EQ(topk_q1_ids[0], 1); - EXPECT_FLOAT_EQ(topk_q1[1], 1.0f); - EXPECT_EQ(topk_q1_ids[1], 2); -} - -// Test batched_scan_list with batch_size parameter -TEST_F(ListScanningTest, BatchedScanList_WithBatchSize) { - int k = 1; - MetricType metric = faiss::METRIC_L2; - - // Define three query vectors (dim=2) - float query_vecs[3 * 2] = { - 1.0f, 0.0f, // Query 0 - 0.0f, 1.0f, // Query 1 - 1.0f, 1.0f // Query 2 - }; - - // Define four list vectors (dim=2) - float list_vecs[4 * 2] = { - 1.0f, 0.0f, // Distance for Q0: 0.0, Q1: 2.0 - 0.0f, 1.0f, // Distance for Q0: 2.0, Q1: 0.0 - 1.0f, 1.0f, // Distance for Q0: 1.0, Q1: 1.0 - 2.0f, 2.0f // Distance for Q0: 4.0, Q1: 2.0 - }; - int64_t list_ids[4] = {100, 200, 300, 400}; - - // Create TopkBuffers for each query - std::vector> topk_buffers = create_buffers(3, k, false); // L2 metric (is_descending=false) - - // Perform batched_scan_list with batch_size=2 - batched_scan_list( - query_vecs, - list_vecs, - list_ids, - 3, // num_queries - 4, // list_size - 2, // dim - topk_buffers, - metric - ); - - // Expected top-k per query: - // Query 0: min distance: 0.0 (id=100) - // Query 1: min distance: 0.0 (id=200) - // Query 2: min distance: 1.0 (id=300) - - // Verify Query 0 - auto topk_q0 = topk_buffers[0]->get_topk(); - auto topk_q0_ids = topk_buffers[0]->get_topk_indices(); - ASSERT_EQ(topk_q0.size(), 1); - EXPECT_FLOAT_EQ(topk_q0[0], 0.0f); - EXPECT_EQ(topk_q0_ids[0], 100); - - // Verify Query 1 - auto topk_q1 = topk_buffers[1]->get_topk(); - auto topk_q1_ids = topk_buffers[1]->get_topk_indices(); - ASSERT_EQ(topk_q1.size(), 1); - EXPECT_FLOAT_EQ(topk_q1[0], 0.0f); - EXPECT_EQ(topk_q1_ids[0], 200); - - // Verify Query 2 - auto topk_q2 = topk_buffers[2]->get_topk(); - auto topk_q2_ids = topk_buffers[2]->get_topk_indices(); - ASSERT_EQ(topk_q2.size(), 1); - EXPECT_FLOAT_EQ(topk_q2[0], 0.0f); - EXPECT_EQ(topk_q2_ids[0], 300); -} - -// Test batched_scan_list with empty list -TEST_F(ListScanningTest, BatchedScanList_EmptyList) { - int k = 2; - MetricType metric = faiss::METRIC_L2; - - // Define one query vector (dim=2) - float query_vecs[1 * 2] = { - 1.0f, 1.0f // Query 0 - }; - int num_queries = 1; - - // Empty list - float list_vecs[0 * 2] = {}; // No list vectors - int64_t list_ids[0] = {}; - - // Create TopkBuffers for the single query - std::vector> topk_buffers = create_buffers(num_queries, k, false); // L2 metric - - // Perform batched_scan_list - batched_scan_list( - query_vecs, - list_vecs, - list_ids, - num_queries, - 0, // list_size - 2, // dim - topk_buffers, - metric - ); - - // Expected top-k: all distances remain +infinity, ids remain -1 - auto topk_q0 = topk_buffers[0]->get_topk(); - auto topk_q0_ids = topk_buffers[0]->get_topk_indices(); - ASSERT_EQ(topk_q0.size(), 0); // No valid top-k elements - - // Since there are no list vectors, all top-k entries should be default values - // However, based on TopkBuffer implementation, if no elements were inserted, get_topk() returns an empty vector - // To verify default values, you might need to adjust TopkBuffer's get_topk method to include default entries - // Alternatively, ensure that the test logic handles empty top-k appropriately -} - -// Test batched_scan_list with less than k elements -// Test batched_scan_list with less than k elements -TEST_F(ListScanningTest, BatchedScanList_LessThanKElements) { - int k = 5; - MetricType metric = faiss::METRIC_L2; - - // Define one query vector (dim=3) - float query_vecs[1 * 3] = {1.0f, 1.0f, 1.0f}; // Query 0 - int num_queries = 1; - - // Define a list with only 2 vectors (dim=3) - float list_vecs[2 * 3] = { - 1.0f, 1.0f, 1.0f, // Distance: 0.0 - 2.0f, 2.0f, 2.0f // Distance: sqrt(3) - }; - int64_t list_ids[2] = {100, 200}; - - // Create TopkBuffers for the single query - std::vector> topk_buffers = create_buffers(num_queries, k, false); // L2 metric - - // Perform batched_scan_list - batched_scan_list( - query_vecs, - list_vecs, - list_ids, - num_queries, - 2, // list_size=2 - 3, // dim=3 - topk_buffers, - metric - ); - - // Expected top-k: 0.0 (id=100), sqrt(3) (~1.73205) (id=200), inf, inf, inf - // Since TopkBuffer maintains only inserted elements, we need to handle default values separately - // Modify TopkBuffer's get_topk and get_topk_indices to include default entries if necessary - - // Retrieve top-k elements - auto topk_q0 = topk_buffers[0]->get_topk(); - auto topk_q0_ids = topk_buffers[0]->get_topk_indices(); - - // Verify inserted elements - ASSERT_EQ(topk_q0.size(), 2); // Only 2 elements were inserted - EXPECT_FLOAT_EQ(topk_q0[0], 0.0f); - EXPECT_EQ(topk_q0_ids[0], 100); - EXPECT_FLOAT_EQ(topk_q0[1], sqrt(3.0)); - EXPECT_EQ(topk_q0_ids[1], 200); -} - -TEST_F(ListScanningTest, LargeListCorrectnessInnerProduct) { - int num_queries = 100; - int64_t list_size = 10000; - int d = 128; - int k = 10; - Tensor query_vectors = torch::randn({num_queries, d}, torch::kFloat32); - Tensor list_vectors = torch::randn({list_size, d}, torch::kFloat32); - Tensor list_ids = torch::arange(0, list_size, torch::kInt64); - - // compute ground truth using pytorch matmul + topk - Tensor distances = torch::matmul(query_vectors, list_vectors.t()); - auto topk = torch::topk(distances, k, 1, true); - auto gt_ids = std::get<1>(topk); - auto gt_dists = std::get<0>(topk); - - auto gt_ids_accessor = gt_ids.accessor(); - auto gt_dists_accessor = gt_dists.accessor(); - - // perform single query scan first - auto buffer = make_shared(k, true, k * 100, 0); - for (int i = 0; i < num_queries; i++) { - scan_list( - query_vectors[i].data_ptr(), - list_vectors.data_ptr(), - list_ids.data_ptr(), - list_size, - d, - *buffer, - faiss::METRIC_INNER_PRODUCT - ); - - // check result is correct - auto topk_dist = buffer->get_topk(); - auto topk_ids = buffer->get_topk_indices(); - - for (int j = 0; j < k; j++) { - EXPECT_NEAR(topk_dist[j], gt_dists_accessor[i][j], .01); - EXPECT_EQ(topk_ids[j], gt_ids_accessor[i][j]); - } - buffer->reset(); - } - - // now perform batched scan - auto buffers = create_buffers(num_queries, k, true); - batched_scan_list( - query_vectors.data_ptr(), - list_vectors.data_ptr(), - list_ids.data_ptr(), - num_queries, - list_size, - d, - buffers, - faiss::METRIC_INNER_PRODUCT - ); - - for (int i = 0; i < num_queries; i++) { - auto topk_dist = buffers[i]->get_topk(); - auto topk_ids = buffers[i]->get_topk_indices(); - - for (int j = 0; j < k; j++) { - EXPECT_NEAR(topk_dist[j], gt_dists_accessor[i][j], .01); - EXPECT_EQ(topk_ids[j], gt_ids_accessor[i][j]); - } - } -} - -TEST_F(ListScanningTest, LargeListCorrectnessL2) { - int num_queries = 100; - int64_t list_size = 10000; - int d = 128; - int k = 10; - Tensor query_vectors = torch::randn({num_queries, d}, torch::kFloat32); - Tensor list_vectors = torch::randn({list_size, d}, torch::kFloat32); - Tensor list_ids = torch::arange(0, list_size, torch::kInt64); - - // compute ground truth using pytorch matmul + topk - Tensor distances = torch::cdist(query_vectors, list_vectors); - auto topk = torch::topk(distances, k, 1, false); - auto gt_ids = std::get<1>(topk); - auto gt_dists = std::get<0>(topk); - - auto gt_ids_accessor = gt_ids.accessor(); - auto gt_dists_accessor = gt_dists.accessor(); - - // perform single query scan first - auto buffer = make_shared(k, false, k * 100, 0); - for (int i = 0; i < num_queries; i++) { - scan_list( - query_vectors[i].data_ptr(), - list_vectors.data_ptr(), - list_ids.data_ptr(), - list_size, - d, - *buffer, - faiss::METRIC_L2 - ); - - // check result is correct - auto topk_dist = buffer->get_topk(); - auto topk_ids = buffer->get_topk_indices(); - - for (int j = 0; j < k; j++) { - EXPECT_NEAR(topk_dist[j], gt_dists_accessor[i][j], .01); - EXPECT_EQ(topk_ids[j], gt_ids_accessor[i][j]); - } - buffer->reset(); - } - - // now perform batched scan - auto buffers = create_buffers(num_queries, k, false); - batched_scan_list( - query_vectors.data_ptr(), - list_vectors.data_ptr(), - list_ids.data_ptr(), - num_queries, - list_size, - d, - buffers, - faiss::METRIC_L2 - ); - - for (int i = 0; i < num_queries; i++) { - auto topk_dist = buffers[i]->get_topk(); - auto topk_ids = buffers[i]->get_topk_indices(); - - for (int j = 0; j < k; j++) { - EXPECT_NEAR(topk_dist[j], gt_dists_accessor[i][j], .01); - EXPECT_EQ(topk_ids[j], gt_ids_accessor[i][j]); - } - } -} \ No newline at end of file +// // list_scanning_test.cpp +// +// #include +// #include +// #include +// #include +// #include +// #include +// +// #include "list_scanning.h" // Ensure this path is correct +// +// // Test fixture for list scanning functions +// class ListScanningTest : public ::testing::Test { +// protected: +// // Helper function to create a TopkBuffer +// std::shared_ptr create_buffer(int k, bool is_descending) { +// return std::make_shared>(k, is_descending, k * 100, 0); +// } +// }; +// +// // Test scan_list with single query and L2 metric +// TEST_F(ListScanningTest, ScanList_SingleQuery_L2) { +// int k = 2; +// bool is_descending = false; // L2 +// auto buffer = create_buffer(k, is_descending); +// +// // Define a query vector and a list of vectors +// float query_vec[3] = {1.0f, 0.0f, 0.0f}; +// float list_vecs[4 * 3] = { +// 1.0f, 0.0f, 0.0f, // Distance: 0.0 +// 0.0f, 1.0f, 0.0f, // Distance: 2.0 +// 1.0f, 1.0f, 0.0f, // Distance: 1.0 +// 2.0f, 0.0f, 0.0f // Distance: 1.0 +// }; +// int64_t list_ids[4] = {10, 20, 30, 40}; +// +// // Expected top-k: 0.0 (id=10), 1.0 (id=30 or 40) +// scan_list(query_vec, list_vecs, list_ids, 4, 3, *buffer, faiss::METRIC_L2, 10000000.0f); +// +// std::vector expected_dists = {0.0f, 1.0f}; +// std::vector expected_ids = {10, 30}; // Could also be {10, 40} based on order +// +// auto topk_dists = buffer->get_topk(); +// auto topk_ids = buffer->get_topk_indices(); +// +// ASSERT_EQ(topk_dists.size(), expected_dists.size()); +// ASSERT_EQ(topk_ids.size(), expected_ids.size()); +// +// EXPECT_FLOAT_EQ(topk_dists[0], expected_dists[0]); +// EXPECT_EQ(topk_ids[0], expected_ids[0]); +// +// // Second element could be id=30 or id=40 +// EXPECT_FLOAT_EQ(topk_dists[1], expected_dists[1]); +// EXPECT_TRUE(topk_ids[1] == 30 || topk_ids[1] == 40); +// } +// +// // Test scan_list with single query and Inner Product metric +// TEST_F(ListScanningTest, ScanList_SingleQuery_InnerProduct) { +// int k = 2; +// bool is_descending = true; // Inner Product +// auto buffer = create_buffer(k, is_descending); +// +// // Define a query vector and a list of vectors +// float query_vec[3] = {1.0f, 0.0f, 0.0f}; +// float list_vecs[4 * 3] = { +// 1.0f, 0.0f, 0.0f, // Inner product: 1.0 +// 0.0f, 1.0f, 0.0f, // Inner product: 0.0 +// 1.0f, 1.0f, 0.0f, // Inner product: 1.0 +// 2.0f, 0.0f, 0.0f // Inner product: 2.0 +// }; +// int64_t list_ids[4] = {10, 20, 30, 40}; +// +// // Expected top-k: 2.0 (id=40), 1.0 (id=10 or 30) +// scan_list(query_vec, list_vecs, list_ids, 4, 3, *buffer, faiss::METRIC_INNER_PRODUCT); +// +// std::vector expected_dists = {2.0f, 1.0f}; +// std::vector expected_ids = {40, 10}; // Could also be {40, 30} +// +// auto topk_dists = buffer->get_topk(); +// auto topk_ids = buffer->get_topk_indices(); +// +// ASSERT_EQ(topk_dists.size(), expected_dists.size()); +// ASSERT_EQ(topk_ids.size(), expected_ids.size()); +// +// EXPECT_FLOAT_EQ(topk_dists[0], expected_dists[0]); +// EXPECT_EQ(topk_ids[0], expected_ids[0]); +// +// // Second element could be id=10 or id=30 +// EXPECT_FLOAT_EQ(topk_dists[1], expected_dists[1]); +// EXPECT_TRUE(topk_ids[1] == 10 || topk_ids[1] == 30); +// } +// +// // Test batched_scan_list with multiple queries and L2 metric +// TEST_F(ListScanningTest, BatchedScanList_MultipleQueries_L2) { +// int k = 2; +// MetricType metric = faiss::METRIC_L2; +// +// // Define two query vectors (dim=3) +// float query_vecs[2 * 3] = { +// 1.0f, 0.0f, 0.0f, // Query 0 +// 0.0f, 1.0f, 0.0f // Query 1 +// }; +// +// // Define a list of vectors (dim=3) +// float list_vecs[4 * 3] = { +// 1.0f, 0.0f, 0.0f, // Q0: 0.0, Q1: 2.0 +// 0.0f, 1.0f, 0.0f, // Q0: 2.0, Q1: 0.0 +// 1.0f, 1.0f, 0.0f, // Q0: 1.0, Q1: 1.0 +// 2.0f, 0.0f, 0.0f // Q0: 4.0, Q1: 2.0 +// }; +// int64_t list_ids[4] = {10, 20, 30, 40}; +// +// // Create TopkBuffers for each query +// std::vector> topk_buffers = create_buffers(2, k, false); // L2 metric (is_descending=false) +// +// // Perform batched_scan_list +// batched_scan_list( +// query_vecs, +// list_vecs, +// list_ids, +// 2, // num_queries +// 4, // list_size +// 3, // dim +// topk_buffers, +// metric +// ); +// +// // Expected results: +// // Query 0: top-k distances: 0.0 (id=10), 1.0 (id=30) +// // Query 1: top-k distances: 0.0 (id=20), 1.0 (id=30) +// +// // Verify Query 0 +// auto topk_q0 = topk_buffers[0]->get_topk(); +// auto topk_q0_ids = topk_buffers[0]->get_topk_indices(); +// ASSERT_EQ(topk_q0.size(), 2); +// EXPECT_FLOAT_EQ(topk_q0[0], 0.0f); +// EXPECT_EQ(topk_q0_ids[0], 10); +// EXPECT_FLOAT_EQ(topk_q0[1], 1.0f); +// EXPECT_EQ(topk_q0_ids[1], 30); +// +// // Verify Query 1 +// auto topk_q1 = topk_buffers[1]->get_topk(); +// auto topk_q1_ids = topk_buffers[1]->get_topk_indices(); +// ASSERT_EQ(topk_q1.size(), 2); +// EXPECT_FLOAT_EQ(topk_q1[0], 0.0f); +// EXPECT_EQ(topk_q1_ids[0], 20); +// EXPECT_FLOAT_EQ(topk_q1[1], 1.0f); +// EXPECT_EQ(topk_q1_ids[1], 30); +// } +// +// // Test batched_scan_list with multiple queries and Inner Product metric +// TEST_F(ListScanningTest, BatchedScanList_MultipleQueries_InnerProduct) { +// int k = 2; +// MetricType metric = faiss::METRIC_INNER_PRODUCT; +// +// // Define two query vectors (dim=3) +// float query_vecs[2 * 3] = { +// 1.0f, 0.0f, 0.0f, // Query 0 +// 0.0f, 1.0f, 0.0f // Query 1 +// }; +// +// // Define a list of vectors (dim=3) +// float list_vecs[4 * 3] = { +// 1.0f, 0.0f, 0.0f, // Inner products [1.0, 0.0] (id=10) +// 0.0f, 1.0f, 0.0f, // Inner products [0.0, 1.0] (id=20) +// .5f, 1.5f, 0.0f, // Inner products [.5, 1.5] (id=30) +// 2.0f, 0.0f, 0.0f // Inner products [2.0, 0.0] (id=40) +// }; +// int64_t list_ids[4] = {10, 20, 30, 40}; +// +// // Create TopkBuffers for each query +// std::vector> topk_buffers = create_buffers(2, k, true); // Inner Product metric (is_descending=true) +// +// // Perform batched_scan_list +// batched_scan_list( +// query_vecs, +// list_vecs, +// list_ids, +// 2, // num_queries +// 4, // list_size +// 3, // dim +// topk_buffers, +// metric +// ); +// +// // Expected results: +// // Query 0: top-k scores: 2.0 (id=40), 1.0 (id=10) +// // Query 1: top-k scores: 1.5 (id=30), 1.0 (id=20) +// +// // Verify Query 0 +// auto topk_q0 = topk_buffers[0]->get_topk(); +// auto topk_q0_ids = topk_buffers[0]->get_topk_indices(); +// +// std::cout << "topk_q0: " << topk_q0[0] << " " << topk_q0[1] << std::endl; +// std::cout << "topk_q0_ids: " << topk_q0_ids[0] << " " << topk_q0_ids[1] << std::endl; +// +// ASSERT_EQ(topk_q0.size(), 2); +// EXPECT_FLOAT_EQ(topk_q0[0], 2.0f); +// EXPECT_TRUE(topk_q0_ids[0] == 40); +// EXPECT_FLOAT_EQ(topk_q0[1], 1.0f); +// EXPECT_TRUE(topk_q0_ids[1] == 10 || topk_q0_ids[1] == 20); +// +// // Verify Query 1 +// auto topk_q1 = topk_buffers[1]->get_topk(); +// auto topk_q1_ids = topk_buffers[1]->get_topk_indices(); +// ASSERT_EQ(topk_q1.size(), 2); +// EXPECT_FLOAT_EQ(topk_q1[0], 1.5f); +// EXPECT_TRUE(topk_q1_ids[0] == 30); +// EXPECT_FLOAT_EQ(topk_q1[1], 1.0f); +// EXPECT_TRUE(topk_q1_ids[1] == 20); +// } +// +// // Test batched_scan_list without list_ids (list_ids == nullptr) +// TEST_F(ListScanningTest, BatchedScanList_NoListIds) { +// int k = 2; +// MetricType metric = faiss::METRIC_L2; +// +// // Define two query vectors +// float query_vecs[2 * 2] = { +// 1.0f, 0.0f, // Query 0 +// 0.0f, 1.0f // Query 1 +// }; +// +// // Define a list of vectors +// float list_vecs[3 * 2] = { +// 1.0f, 0.0f, // Distance for Q0: 0.0, Q1: 2.0 +// 0.0f, 1.0f, // Distance for Q0: 2.0, Q1: 0.0 +// 1.0f, 1.0f // Distance for Q0: 1.0, Q1: 1.0 +// }; +// // list_ids == nullptr +// +// // Create TopkBuffers for each query +// std::vector> topk_buffers = create_buffers(2, k, false); // Inner Product metric (is_descending=true) +// +// +// // Perform batched_scan_list +// batched_scan_list( +// query_vecs, +// list_vecs, +// nullptr, // list_ids +// 2, // num_queries +// 3, // list_size +// 2, // dim +// topk_buffers, +// metric +// ); +// +// // Expected results: +// // Query 0: top-k distances: 0.0 (id=0), 1.0 (id=2) +// // Query 1: top-k distances: 0.0 (id=1), 1.0 (id=2) +// +// std::vector expected_dists_q0 = {0.0f, 1.0f}; +// std::vector expected_ids_q0 = {0, 2}; +// std::vector expected_dists_q1 = {0.0f, 1.0f}; +// std::vector expected_ids_q1 = {1, 2}; +// +// // Verify Query 0 +// auto topk_q0 = topk_buffers[0]->get_topk(); +// auto topk_q0_ids = topk_buffers[0]->get_topk_indices(); +// +// std::cout << "topk_q0: " << topk_q0[0] << " " << topk_q0[1] << std::endl; +// std::cout << "topk_q0_ids: " << topk_q0_ids[0] << " " << topk_q0_ids[1] << std::endl; +// +// ASSERT_EQ(topk_q0.size(), 2); +// EXPECT_FLOAT_EQ(topk_q0[0], 0.0f); +// EXPECT_EQ(topk_q0_ids[0], 0); +// EXPECT_FLOAT_EQ(topk_q0[1], 1.0f); +// EXPECT_EQ(topk_q0_ids[1], 2); +// +// // Verify Query 1 +// auto topk_q1 = topk_buffers[1]->get_topk(); +// auto topk_q1_ids = topk_buffers[1]->get_topk_indices(); +// ASSERT_EQ(topk_q1.size(), 2); +// EXPECT_FLOAT_EQ(topk_q1[0], 0.0f); +// EXPECT_EQ(topk_q1_ids[0], 1); +// EXPECT_FLOAT_EQ(topk_q1[1], 1.0f); +// EXPECT_EQ(topk_q1_ids[1], 2); +// } +// +// // Test batched_scan_list with batch_size parameter +// TEST_F(ListScanningTest, BatchedScanList_WithBatchSize) { +// int k = 1; +// MetricType metric = faiss::METRIC_L2; +// +// // Define three query vectors (dim=2) +// float query_vecs[3 * 2] = { +// 1.0f, 0.0f, // Query 0 +// 0.0f, 1.0f, // Query 1 +// 1.0f, 1.0f // Query 2 +// }; +// +// // Define four list vectors (dim=2) +// float list_vecs[4 * 2] = { +// 1.0f, 0.0f, // Distance for Q0: 0.0, Q1: 2.0 +// 0.0f, 1.0f, // Distance for Q0: 2.0, Q1: 0.0 +// 1.0f, 1.0f, // Distance for Q0: 1.0, Q1: 1.0 +// 2.0f, 2.0f // Distance for Q0: 4.0, Q1: 2.0 +// }; +// int64_t list_ids[4] = {100, 200, 300, 400}; +// +// // Create TopkBuffers for each query +// std::vector> topk_buffers = create_buffers(3, k, false); // L2 metric (is_descending=false) +// +// // Perform batched_scan_list with batch_size=2 +// batched_scan_list( +// query_vecs, +// list_vecs, +// list_ids, +// 3, // num_queries +// 4, // list_size +// 2, // dim +// topk_buffers, +// metric +// ); +// +// // Expected top-k per query: +// // Query 0: min distance: 0.0 (id=100) +// // Query 1: min distance: 0.0 (id=200) +// // Query 2: min distance: 1.0 (id=300) +// +// // Verify Query 0 +// auto topk_q0 = topk_buffers[0]->get_topk(); +// auto topk_q0_ids = topk_buffers[0]->get_topk_indices(); +// ASSERT_EQ(topk_q0.size(), 1); +// EXPECT_FLOAT_EQ(topk_q0[0], 0.0f); +// EXPECT_EQ(topk_q0_ids[0], 100); +// +// // Verify Query 1 +// auto topk_q1 = topk_buffers[1]->get_topk(); +// auto topk_q1_ids = topk_buffers[1]->get_topk_indices(); +// ASSERT_EQ(topk_q1.size(), 1); +// EXPECT_FLOAT_EQ(topk_q1[0], 0.0f); +// EXPECT_EQ(topk_q1_ids[0], 200); +// +// // Verify Query 2 +// auto topk_q2 = topk_buffers[2]->get_topk(); +// auto topk_q2_ids = topk_buffers[2]->get_topk_indices(); +// ASSERT_EQ(topk_q2.size(), 1); +// EXPECT_FLOAT_EQ(topk_q2[0], 0.0f); +// EXPECT_EQ(topk_q2_ids[0], 300); +// } +// +// // Test batched_scan_list with empty list +// TEST_F(ListScanningTest, BatchedScanList_EmptyList) { +// int k = 2; +// MetricType metric = faiss::METRIC_L2; +// +// // Define one query vector (dim=2) +// float query_vecs[1 * 2] = { +// 1.0f, 1.0f // Query 0 +// }; +// int num_queries = 1; +// +// // Empty list +// float list_vecs[0 * 2] = {}; // No list vectors +// int64_t list_ids[0] = {}; +// +// // Create TopkBuffers for the single query +// std::vector> topk_buffers = create_buffers(num_queries, k, false); // L2 metric +// +// // Perform batched_scan_list +// batched_scan_list( +// query_vecs, +// list_vecs, +// list_ids, +// num_queries, +// 0, // list_size +// 2, // dim +// topk_buffers, +// metric +// ); +// +// // Expected top-k: all distances remain +infinity, ids remain -1 +// auto topk_q0 = topk_buffers[0]->get_topk(); +// auto topk_q0_ids = topk_buffers[0]->get_topk_indices(); +// ASSERT_EQ(topk_q0.size(), 0); // No valid top-k elements +// +// // Since there are no list vectors, all top-k entries should be default values +// // However, based on TopkBuffer implementation, if no elements were inserted, get_topk() returns an empty vector +// // To verify default values, you might need to adjust TopkBuffer's get_topk method to include default entries +// // Alternatively, ensure that the test logic handles empty top-k appropriately +// } +// +// // Test batched_scan_list with less than k elements +// // Test batched_scan_list with less than k elements +// TEST_F(ListScanningTest, BatchedScanList_LessThanKElements) { +// int k = 5; +// MetricType metric = faiss::METRIC_L2; +// +// // Define one query vector (dim=3) +// float query_vecs[1 * 3] = {1.0f, 1.0f, 1.0f}; // Query 0 +// int num_queries = 1; +// +// // Define a list with only 2 vectors (dim=3) +// float list_vecs[2 * 3] = { +// 1.0f, 1.0f, 1.0f, // Distance: 0.0 +// 2.0f, 2.0f, 2.0f // Distance: sqrt(3) +// }; +// int64_t list_ids[2] = {100, 200}; +// +// // Create TopkBuffers for the single query +// std::vector> topk_buffers = create_buffers(num_queries, k, false); // L2 metric +// +// // Perform batched_scan_list +// batched_scan_list( +// query_vecs, +// list_vecs, +// list_ids, +// num_queries, +// 2, // list_size=2 +// 3, // dim=3 +// topk_buffers, +// metric +// ); +// +// // Expected top-k: 0.0 (id=100), sqrt(3) (~1.73205) (id=200), inf, inf, inf +// // Since TopkBuffer maintains only inserted elements, we need to handle default values separately +// // Modify TopkBuffer's get_topk and get_topk_indices to include default entries if necessary +// +// // Retrieve top-k elements +// auto topk_q0 = topk_buffers[0]->get_topk(); +// auto topk_q0_ids = topk_buffers[0]->get_topk_indices(); +// +// // Verify inserted elements +// ASSERT_EQ(topk_q0.size(), 2); // Only 2 elements were inserted +// EXPECT_FLOAT_EQ(topk_q0[0], 0.0f); +// EXPECT_EQ(topk_q0_ids[0], 100); +// EXPECT_FLOAT_EQ(topk_q0[1], sqrt(3.0)); +// EXPECT_EQ(topk_q0_ids[1], 200); +// } +// +// TEST_F(ListScanningTest, LargeListCorrectnessInnerProduct) { +// int num_queries = 100; +// int64_t list_size = 10000; +// int d = 128; +// int k = 10; +// Tensor query_vectors = torch::randn({num_queries, d}, torch::kFloat32); +// Tensor list_vectors = torch::randn({list_size, d}, torch::kFloat32); +// Tensor list_ids = torch::arange(0, list_size, torch::kInt64); +// +// // compute ground truth using pytorch matmul + topk +// Tensor distances = torch::matmul(query_vectors, list_vectors.t()); +// auto topk = torch::topk(distances, k, 1, true); +// auto gt_ids = std::get<1>(topk); +// auto gt_dists = std::get<0>(topk); +// +// auto gt_ids_accessor = gt_ids.accessor(); +// auto gt_dists_accessor = gt_dists.accessor(); +// +// // perform single query scan first +// auto buffer = make_shared(k, true, k * 100, 0); +// for (int i = 0; i < num_queries; i++) { +// scan_list( +// query_vectors[i].data_ptr(), +// list_vectors.data_ptr(), +// list_ids.data_ptr(), +// list_size, +// d, +// *buffer, +// faiss::METRIC_INNER_PRODUCT +// ); +// +// // check result is correct +// auto topk_dist = buffer->get_topk(); +// auto topk_ids = buffer->get_topk_indices(); +// +// for (int j = 0; j < k; j++) { +// EXPECT_NEAR(topk_dist[j], gt_dists_accessor[i][j], .01); +// EXPECT_EQ(topk_ids[j], gt_ids_accessor[i][j]); +// } +// buffer->reset(); +// } +// +// // now perform batched scan +// auto buffers = create_buffers(num_queries, k, true); +// batched_scan_list( +// query_vectors.data_ptr(), +// list_vectors.data_ptr(), +// list_ids.data_ptr(), +// num_queries, +// list_size, +// d, +// buffers, +// faiss::METRIC_INNER_PRODUCT +// ); +// +// for (int i = 0; i < num_queries; i++) { +// auto topk_dist = buffers[i]->get_topk(); +// auto topk_ids = buffers[i]->get_topk_indices(); +// +// for (int j = 0; j < k; j++) { +// EXPECT_NEAR(topk_dist[j], gt_dists_accessor[i][j], .01); +// EXPECT_EQ(topk_ids[j], gt_ids_accessor[i][j]); +// } +// } +// } +// +// TEST_F(ListScanningTest, LargeListCorrectnessL2) { +// int num_queries = 100; +// int64_t list_size = 10000; +// int d = 128; +// int k = 10; +// Tensor query_vectors = torch::randn({num_queries, d}, torch::kFloat32); +// Tensor list_vectors = torch::randn({list_size, d}, torch::kFloat32); +// Tensor list_ids = torch::arange(0, list_size, torch::kInt64); +// +// // compute ground truth using pytorch matmul + topk +// Tensor distances = torch::cdist(query_vectors, list_vectors); +// auto topk = torch::topk(distances, k, 1, false); +// auto gt_ids = std::get<1>(topk); +// auto gt_dists = std::get<0>(topk); +// +// auto gt_ids_accessor = gt_ids.accessor(); +// auto gt_dists_accessor = gt_dists.accessor(); +// +// // perform single query scan first +// auto buffer = make_shared(k, false, k * 100, 0); +// for (int i = 0; i < num_queries; i++) { +// scan_list( +// query_vectors[i].data_ptr(), +// list_vectors.data_ptr(), +// list_ids.data_ptr(), +// list_size, +// d, +// *buffer, +// faiss::METRIC_L2 +// ); +// +// // check result is correct +// auto topk_dist = buffer->get_topk(); +// auto topk_ids = buffer->get_topk_indices(); +// +// for (int j = 0; j < k; j++) { +// EXPECT_NEAR(topk_dist[j], gt_dists_accessor[i][j], .01); +// EXPECT_EQ(topk_ids[j], gt_ids_accessor[i][j]); +// } +// buffer->reset(); +// } +// +// // now perform batched scan +// auto buffers = create_buffers(num_queries, k, false); +// batched_scan_list( +// query_vectors.data_ptr(), +// list_vectors.data_ptr(), +// list_ids.data_ptr(), +// num_queries, +// list_size, +// d, +// buffers, +// faiss::METRIC_L2 +// ); +// +// for (int i = 0; i < num_queries; i++) { +// auto topk_dist = buffers[i]->get_topk(); +// auto topk_ids = buffers[i]->get_topk_indices(); +// +// for (int j = 0; j < k; j++) { +// EXPECT_NEAR(topk_dist[j], gt_dists_accessor[i][j], .01); +// EXPECT_EQ(topk_ids[j], gt_ids_accessor[i][j]); +// } +// } +// } \ No newline at end of file diff --git a/test/cpp/quake_index.cpp b/test/cpp/quake_index.cpp index 876571ac..d7e6c057 100644 --- a/test/cpp/quake_index.cpp +++ b/test/cpp/quake_index.cpp @@ -246,7 +246,8 @@ TEST_F(QuakeIndexTest, SaveLoadTest) { // Load into a new index QuakeIndex loaded_index; - loaded_index.load(path); + shared_ptr default_params = std::make_shared(); + loaded_index.load(path, default_params); // minimal checks EXPECT_EQ(loaded_index.ntotal(), index.ntotal()); diff --git a/test/experiments/osdi2025/aps_recall_targets/configs/sift1m.yaml b/test/experiments/osdi2025/aps_recall_targets/configs/sift1m.yaml index 47c5ee47..6672d1af 100644 --- a/test/experiments/osdi2025/aps_recall_targets/configs/sift1m.yaml +++ b/test/experiments/osdi2025/aps_recall_targets/configs/sift1m.yaml @@ -7,19 +7,20 @@ dataset: experiment: nq: 100 k: 100 - n_workers: 0 + n_workers: 1 recall_targets: [.2, .3, .4, .5, .6, .7, .8, .9, .95, .99, .999] recompute_ratio: 0.00001 use_precompute: true - initial_search_fraction: .1 + initial_search_fraction: .05 + aps_flush_period_us: 10 index: metric: l2 nlist: 1000 overwrite: index: false results: true -methods: ['Oracle', 'APS'] -#methods: ['APS'] +#methods: ['Oracle', 'APS'] +methods: ['APS'] #methods: ['Oracle'] paths: diff --git a/test/experiments/osdi2025/aps_recall_targets/run.py b/test/experiments/osdi2025/aps_recall_targets/run.py index 499dfd8a..8ee5d7be 100644 --- a/test/experiments/osdi2025/aps_recall_targets/run.py +++ b/test/experiments/osdi2025/aps_recall_targets/run.py @@ -81,16 +81,35 @@ def run_experiment(cfg_path: str, output_dir_str: str): per_query_stats.append((best_global_np, final_rec, final_time_ms)) elif method == "APS": - for i, q_vec in enumerate(queries): - sp = common_utils.create_search_params( - nprobe=-1, k=k, recall_target=rt, - recompute_threshold=exp_cfg["recompute_ratio"], - use_precomputed=exp_cfg["use_precompute"], - initial_search_fraction=exp_cfg["initial_search_fraction"] - ) - nprobe_scan, final_rec, final_time_ms = common_utils.run_search_trial(quake_idx, q_vec, gt[i], k, sp) - logger.debug(f"APS recall: {final_rec:.4f} (target={rt}), nprobe_scanned={nprobe_scan}") - per_query_stats.append((nprobe_scan, final_rec, final_time_ms)) + sp = common_utils.create_search_params( + nprobe=-1, k=k, recall_target=rt, + recompute_threshold=exp_cfg["recompute_ratio"], + use_precomputed=exp_cfg["use_precompute"], + initial_search_fraction=exp_cfg["initial_search_fraction"], + aps_flush_period_us=exp_cfg["aps_flush_period_us"] + ) + # for i, q_vec in enumerate(queries): + # res = quake_idx.search(q_vec.unsqueeze(0), sp) + # nprobe_scan = res.timing_info.partitions_scanned + # final_rec = common_utils.quake_compute_recall(res.ids, gt[i].unsqueeze(0), k).item() + # final_time_ms = res.timing_info.total_time_ns / 1e6 + # boundary_time_ms = res.timing_info.boundary_time_ns / 1e6 if hasattr(res.timing_info, 'boundary_time_ns') else 0.0 + # aps_time_ms = res.timing_info.aps_time_ns / 1e6 if hasattr(res.timing_info, 'aps_time_ns') else 0.0 + # + # logger.info(f"APS recall: {final_rec:.4f} (target={rt}), nprobe_scanned={nprobe_scan}, boundary_time={boundary_time_ms:.2f}ms, aps_time={aps_time_ms:.2f}ms, total_time={final_time_ms:.2f}ms") + # per_query_stats.append((nprobe_scan, final_rec, final_time_ms)) + + res = quake_idx.search(queries, sp) + nprobe_scan = res.timing_info.partitions_scanned + final_recall = common_utils.quake_compute_recall(res.ids, gt, k) + final_time_ms = res.timing_info.total_time_ns / 1e6 + boundary_time_ms = res.timing_info.boundary_distance_time_ns / 1e6 + aps_time_ms = res.timing_info.aps_time_ns / 1e6 + + logger.info(f"APS recall: {final_recall.mean():.4f} (target={rt}), nprobe_scanned={nprobe_scan}, " + f"boundary_time={boundary_time_ms:.2f}ms, aps_time={aps_time_ms:.2f}ms, total_time={final_time_ms:.2f}ms") + per_query_stats.append((nprobe_scan, final_recall.mean().item(), final_time_ms)) + else: raise ValueError(f"Unknown method: {method}") diff --git a/test/experiments/osdi2025/experiment_runner.py b/test/experiments/osdi2025/experiment_runner.py index 1cad31e1..7f9c2798 100644 --- a/test/experiments/osdi2025/experiment_runner.py +++ b/test/experiments/osdi2025/experiment_runner.py @@ -14,6 +14,7 @@ from test.experiments.osdi2025.vary_levels.run import run_experiment as run_vary_levels from test.experiments.osdi2025.maintenance_ablation.run import run_experiment as run_ablation from test.experiments.osdi2025.vary_batch_size.run import run_experiment as run_vary_batch_size +from test.experiments.osdi2025.wiki_workload.run import run_experiment as run_wiki_workload EXPERIMENTS = { "kick_the_tires": run_kick_the_tires, @@ -25,6 +26,7 @@ "vary_levels": run_vary_levels, "maintenance_ablation": run_ablation, "vary_batch_size": run_vary_batch_size, + "wiki_workload": run_wiki_workload } def main(): diff --git a/test/experiments/osdi2025/experiment_utils.py b/test/experiments/osdi2025/experiment_utils.py index 59822c44..7a2ef22b 100644 --- a/test/experiments/osdi2025/experiment_utils.py +++ b/test/experiments/osdi2025/experiment_utils.py @@ -48,17 +48,16 @@ def prepare_quake_index( load: bool = True ) -> QuakeIndex: idx = QuakeIndex() + + build_params = create_index_build_params(**build_params_dict) + if index_file_path.exists() and not force_rebuild: if load: logger.info(f"Loading index from {index_file_path}") - idx.load(str(index_file_path), num_workers_load, use_numa, num_parent_workers_load) + idx.load(str(index_file_path), build_params) else: logger.info(f"Building index -> {index_file_path}") - bp = IndexBuildParams() - for key, value in build_params_dict.items(): - setattr(bp, key, value) - - idx.build(vecs, torch.arange(len(vecs)), bp) + idx.build(vecs, torch.arange(len(vecs)), build_params) index_file_path.parent.mkdir(parents=True, exist_ok=True) idx.save(str(index_file_path)) logger.info(f"Index saved to {index_file_path}") diff --git a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml index 0ec92f83..cd56ed38 100644 --- a/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml +++ b/test/experiments/osdi2025/numa_multi_query/configs/sift1m.yaml @@ -15,11 +15,19 @@ indexes: build_params: nc: 1000 metric: l2 - num_workers: 12 + num_workers: 1 + num_merge_workers: 1 use_numa: true - parent_num_workers: 12 + parent: + num_workers: 1 + num_merge_workers: 1 + use_numa: true search_params: - nprobe: 20 + nprobe: 100 + batch_size: 64 + parent: + batched_scan: true + batch_size: 128 batched_scan: true # # - name: Quake_16_numa @@ -56,16 +64,16 @@ indexes: # omp_num_threads_search: 16 # # - - name: FaissHNSW - index: HNSW - build_params: - m: 64 - ef_construction: 128 - metric: l2 - omp_num_threads_build: 16 - search_params: - ef_search: 128 - omp_num_threads_search: 16 +# - name: FaissHNSW +# index: HNSW +# build_params: +# m: 64 +# ef_construction: 128 +# metric: l2 +# omp_num_threads_build: 1 +# search_params: +# ef_search: 16 +# omp_num_threads_search: 1 # # - name: SCANN diff --git a/test/experiments/osdi2025/wiki_workload/run.py b/test/experiments/osdi2025/wiki_workload/run.py index e0c65dab..eacdbe0f 100644 --- a/test/experiments/osdi2025/wiki_workload/run.py +++ b/test/experiments/osdi2025/wiki_workload/run.py @@ -101,7 +101,28 @@ def unified_plot(cfg: Dict[str, Any], out_dir: Path) -> None: if not sub.empty: ax.plot(sub.operation_number, sub.latency_ms, color=colour, **OP_STYLE[op]) - # partitions, resident blank + # partitions + part_ix = IDX_PART + if "nlist" in df: + axs[part_ix].plot(df.operation_number, df.nlist, color=colour, marker=marker, lw=1.2) + # resident + res_ix = IDX_RES + if "n_resident" in df: + axs[res_ix].plot(df.operation_number, df.n_resident, color=colour, marker=marker, lw=1.2) + + # splits/deletes + spl_ix = IDX_SPL + if "n_splits" in df and "n_deletes" in df: + axs[spl_ix].plot(df.operation_number, df.n_splits, color=colour, marker="x", lw=1.2, label="Splits") + axs[spl_ix].plot(df.operation_number, df.n_deletes, color=colour, marker="o", lw=1.2, label="Deletes") + # axs[spl_ix].legend(loc="upper left", frameon=False) + + # maintenance time + if "maintenance_latency_ms" in df: + m_ix = IDX_LAT_M + axs[m_ix].plot(df.operation_number, df.maintenance_latency_ms, color=colour, marker=marker, lw=1.2, + label="Maintenance") + # recall rec_ix = IDX_REC sub = df[df.operation_type=="query"] @@ -135,7 +156,7 @@ def unified_plot(cfg: Dict[str, Any], out_dir: Path) -> None: def make_time_breakdown(cfg: Dict[str, Any], out_dir: Path) -> None: - categories = ["Query","Insert","Delete","Total"] + categories = ["Query","Insert","Maintenance", "Total"] data = {} for idx_cfg in cfg.get("indexes", []): name = idx_cfg["name"] @@ -143,7 +164,7 @@ def make_time_breakdown(cfg: Dict[str, Any], out_dir: Path) -> None: data[name] = [ df[df.operation_type=="query"].latency_ms.sum(), df[df.operation_type=="insert"].latency_ms.sum(), - df[df.operation_type=="delete"].latency_ms.sum(), + df.maintenance_latency_ms.sum() if "maintenance_latency_ms" in df else 0, ] data[name].append(sum(data[name])) fig, ax = plt.subplots(figsize=(8,6)) @@ -187,9 +208,17 @@ def run_experiment(cfg_path_str: str, output_dir_str: str) -> None: log.info("Mode: %s", mode) workload_dir = cfg["workload_dir"] + dataset_dir = cfg["dataset_dir"] if mode in {"run"}: # Phase 2: evaluation for idx_cfg in cfg.get("indexes", []): + + # check if results already exist + out_name = out / idx_cfg["name"] + if out_name.is_dir() and (out_name / "results.csv").is_file() and not cfg.get("overwrite", False): + log.info("Skipping %s, results already exist", idx_cfg["name"]) + continue + name = idx_cfg["name"] key = idx_cfg["index"] Cls = INDEX_CLASSES.get(key) @@ -198,7 +227,7 @@ def run_experiment(cfg_path_str: str, output_dir_str: str) -> None: wrapper = Cls() maint = idx_cfg.get("maintenance_params") do_maint = maint is not None - ev = WikidataWorkloadEvaluator(workload_dir, out/name) + ev = WikidataWorkloadEvaluator(workload_dir, out/name, wiki_dataset_dir=dataset_dir) ev.evaluate_workload( name=name, index=wrapper, @@ -206,7 +235,7 @@ def run_experiment(cfg_path_str: str, output_dir_str: str) -> None: search_params=idx_cfg.get("search_params",{}), do_maintenance=do_maint, m_params=maint, - batch=bool(idx_cfg.get("batch",False)), + batch=cfg.get("batch",False), ) if mode in {"run","plot"}: # Phase 3 unified_plot(cfg, out) From c45b440ee5213ac6cd62b939c23ee78c89b66ace Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 1 Jun 2025 12:41:10 -0500 Subject: [PATCH 301/323] wiki config --- .../osdi2025/wiki_workload/configs/wiki.yaml | 186 ++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 test/experiments/osdi2025/wiki_workload/configs/wiki.yaml diff --git a/test/experiments/osdi2025/wiki_workload/configs/wiki.yaml b/test/experiments/osdi2025/wiki_workload/configs/wiki.yaml new file mode 100644 index 00000000..143d5f34 --- /dev/null +++ b/test/experiments/osdi2025/wiki_workload/configs/wiki.yaml @@ -0,0 +1,186 @@ +workload_dir: data/wikidata/workload +dataset_dir: /Users/jason/projects/compass/data/wikidata/wikidata +overwrite: False +batch: True + +indexes: + - name: Quake_Serial_NoAPS_NoMaintenance + index: Quake + build_params: + nc: 1000 + metric: ip + num_workers: 1 + use_numa: true + parent: + num_workers: 1 + search_params: + k: 100 + nprobe: 10 + initial_search_fraction: .05 + batched_scan: false + parent: + batched_scan: true + batch_size: 128 + maintenance_params: + refinement_radius: 50 + split_threshold_ns: 500000 + delete_threshold_ns: 500000 + enable_split_rejection: true + enable_delete_rejection: false + window_size: 10000 + + - name: Quake_Serial_NoAPS + index: Quake + build_params: + nc: 1000 + metric: ip + num_workers: 1 + use_numa: true + parent: + num_workers: 1 + search_params: + k: 100 + nprobe: 30 + initial_search_fraction: .05 + batched_scan: false + parent: + batched_scan: true + batch_size: 128 + maintenance_params: + refinement_radius: 50 + split_threshold_ns: 250 + delete_threshold_ns: 500000 + enable_split_rejection: true + enable_delete_rejection: false + window_size: 10000 + + - name: Quake_Serial + index: Quake + build_params: + nc: 1000 + metric: ip + num_workers: 1 + use_numa: true + parent: + num_workers: 1 + search_params: + k: 100 + recall_target: .9 + initial_search_fraction: .05 + batched_scan: false + parent: + batched_scan: true + batch_size: 128 + maintenance_params: + refinement_radius: 50 + split_threshold_ns: 250 + delete_threshold_ns: 500000 + enable_split_rejection: true + enable_delete_rejection: false + window_size: 10000 + + - name: QuakeNoMaintenanceNoAPS + index: Quake + build_params: + nc: 1000 + metric: ip + num_workers: 8 + use_numa: true + parent: + num_workers: 2 + search_params: + k: 100 + nprobe: 30 + batched_scan: false + aps_flush_period_us: 10 + parent: + batched_scan: true + batch_size: 128 + maintenance_params: + refinement_radius: 50 + split_threshold_ns: 500000 + delete_threshold_ns: 500000 + enable_split_rejection: true + enable_delete_rejection: false + window_size: 10000 + + - name: QuakeNoMaintenance + index: Quake + build_params: + nc: 1000 + metric: ip + num_workers: 8 + use_numa: true + parent: + num_workers: 2 + search_params: + k: 100 + recall_target: .9 + batched_scan: false + recompute_threshold: 0.01 + use_precomputed: true + initial_search_fraction: .05 + aps_flush_period_us: 10 + parent: + batched_scan: true + batch_size: 128 + maintenance_params: + refinement_radius: 50 + split_threshold_ns: 500000 + delete_threshold_ns: 500000 + enable_split_rejection: true + enable_delete_rejection: false + window_size: 10000 + + - name: QuakeNoAPS + index: Quake + build_params: + nc: 1000 + metric: ip + num_workers: 8 + use_numa: true + parent: + num_workers: 2 + search_params: + k: 100 + nprobe: 30 + batched_scan: false + aps_flush_period_us: 10 + parent: + batched_scan: true + batch_size: 128 + maintenance_params: + refinement_radius: 50 + split_threshold_ns: 250 + delete_threshold_ns: 500000 + enable_split_rejection: true + enable_delete_rejection: false + window_size: 10000 + + - name: Quake + index: Quake + build_params: + nc: 1000 + metric: ip + num_workers: 8 + use_numa: true + parent: + num_workers: 2 + search_params: + k: 100 + recall_target: .9 + batched_scan: false + recompute_threshold: 0.01 + use_precomputed: true + initial_search_fraction: .05 + aps_flush_period_us: 10 + parent: + batched_scan: true + batch_size: 128 + maintenance_params: + refinement_radius: 50 + split_threshold_ns: 250 + delete_threshold_ns: 500000 + enable_split_rejection: true + enable_delete_rejection: false + window_size: 10000 \ No newline at end of file From a29c188dff996c9800c9c9f4e58141eb7e39cde7 Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 1 Jun 2025 14:22:17 -0500 Subject: [PATCH 302/323] wiki config --- .../osdi2025/wiki_workload/wiki_workload.py | 587 ++++++++++++++++++ 1 file changed, 587 insertions(+) create mode 100644 test/experiments/osdi2025/wiki_workload/wiki_workload.py diff --git a/test/experiments/osdi2025/wiki_workload/wiki_workload.py b/test/experiments/osdi2025/wiki_workload/wiki_workload.py new file mode 100644 index 00000000..9a7f298b --- /dev/null +++ b/test/experiments/osdi2025/wiki_workload/wiki_workload.py @@ -0,0 +1,587 @@ +import json +import time +from pathlib import Path +from typing import Union, Dict, List, Optional + +import numpy as np +import torch + +import quake +from quake.utils import to_path, compute_recall +import pandas as pd +import matplotlib.pyplot as plt +from quake.index_wrappers.quake import QuakeWrapper + +TOTAL_NUM_UPDATES = 104 +TOTAL_NUM_EMBEDDINGS = 11_790_930 +K = 100 + +wikidata_dir = Path("/Users/jason/projects/compass/data/wikidata") +metric = "ip" + +def get_node_mappings() -> dict: + """ + This function retrieves the node mappings from the S3 bucket. + """ + node_mappings = None + + with open(wikidata_dir / "node_mappings.json", "r") as f: + node_mappings = json.load(f) + + return node_mappings + + +def update_id_to_month(n) -> str: + """ + This function converts the update id to the corresponding month and year. + """ + # starting point: August 2015 corresponds to update 27 + start_month = 8 + start_year = 2015 + + # calculate the number of months to add + months_to_add = n - 27 + + # calculate the target year and month + target_year = start_year + (start_month + months_to_add - 1) // 12 + target_month = (start_month + months_to_add - 1) % 12 + 1 + + # get the month and year as a string + return f"{target_year}{target_month:02d}" + + +def compute_ip_ground_truth( + queries: torch.Tensor, + base : torch.Tensor, + # ids : torch.Tensor, + k: int, +) -> np.ndarray: + + + flat_quake_index = quake.QuakeIndex() + build_params = quake.IndexBuildParams() + build_params.metric = "ip" + build_params.nlist = 1 + build_params.num_workers = 6 + ids = torch.arange(base.shape[0], dtype=torch.int64) + flat_quake_index.build(base, ids, build_params) + + search_params = quake.SearchParams() + search_params.k = k + search_params.batched_scan = True + res = flat_quake_index.search(queries, search_params) + return res.ids.numpy(), res.distances.numpy() + + +def wiki_sampler(current_ids: torch.tensor, query_size: int, update_id: int) -> torch.tensor: + """ + This function samples query ids from the current_ids. + + :param current_ids: The current ids in the index. + :param query_size: The size of the query. + :param update_id: The id of the update. + + :return: The sampled query ids. + """ + assert update_id >= -1 and update_id <= 103 + + month_str = update_id_to_month(update_id) + if month_str == "201412": + month_str = "201312" + elif month_str == "201310": + month_str = "201210" + + # for each of the current ids, get the corresponding pageviews for the given update_id + df_id = pd.DataFrame(current_ids.numpy(), columns=["id"]) + df_pageviews = pd.read_parquet(wikidata_dir / f"pageviews/pageviews_{month_str}.parquet") + # df_pageviews = pd.read_parquet(Path(f"data/wikidata/pageviews/pageviews_{month_str}.parquet")) + + df = pd.merge(df_id, df_pageviews, on="id", how="left") + df["pageviews"] = df["pageviews"].fillna(0).astype(int) + + pageviews = df["pageviews"].values + assert len(pageviews) == len(current_ids) + + # sample the query ids based on the pageviews + np.random.seed(42) + probs = pageviews / pageviews.sum() + query_ids = np.random.choice(current_ids.numpy(), size=query_size, replace=True, p=probs) + + assert len(query_ids) == query_size + return torch.tensor(query_ids) + +class WikidataWorkloadGenerator: + """ + Generates a dynamic workload from the Wikipedia data for updates + and sample embeddings for queries (for now). + + The workflow is as follows: + 1. Takes the embeddings from the Wikipedia dataset for the initial base embeddings and updates. + 2. After each update, samples a set of resident embeddings for queries. + 3. The workload is saved to a directory as a set of operations with a corresponding runbook. + """ + + def __init__( + self, + workload_dir: Union[str, Path], + num_updates: int, + query_batch_size: int, + metric: str = "ip", + seed: int = 1874, + with_patterns: bool = True, + overwrite: bool = False, + ): + # download the wikipedia dataset if not already downloaded + self.num_updates = num_updates + + assert num_updates <= TOTAL_NUM_UPDATES + + self.workload_dir = Path(workload_dir) + self.query_batch_size = query_batch_size + self.metric = metric.lower() + self.seed = seed + self.with_patterns = with_patterns + + assert self.metric == "ip" + assert self.query_batch_size > 0 + + torch.manual_seed(self.seed) + np.random.seed(self.seed) + + self.workload_dir.mkdir(parents=True, exist_ok=True) + + # delete the runbook if it exists and overwrite is True + runbook_path = self.workload_dir / "runbook.json" + if runbook_path.exists() and overwrite: + runbook_path.unlink() + + self.operations_dir = self.workload_dir / "operations" + if self.operations_dir.exists() and overwrite: + for file in self.operations_dir.iterdir(): + file.unlink() + + self.operations_dir.mkdir(parents=True, exist_ok=True) + + # set generator state + self.current_base = None + self.current_ids = None + + self.runbook = {} + + def workload_exists(self): + return (self.workload_dir / "runbook.json").exists() + + def generate_workload(self): + """ + Generate the workload. + """ + + self.runbook["parameters"] = { + "query_batch_size": self.query_batch_size, + "num_updates": self.num_updates, + "metric": self.metric, + "pattern_sampling": self.with_patterns, + } + + initial_embeddings = torch.from_numpy(np.load(wikidata_dir / "wikidata" / "embeddings_initial.npy")) + initial_embeddings /= torch.norm(initial_embeddings, dim=1, keepdim=True) + self.current_base = initial_embeddings + self.current_ids = torch.from_numpy(np.load(wikidata_dir / "wikidata" / "ids_initial.npy")) + + self.runbook["initialize"] = { + "size": self.current_ids.shape[0], + } + self.runbook["operations"] = {} + + n_inserts = 0 + n_queries = 0 + n_operations = 0 + + # the first operation is a query operation + n_resident = self.current_ids.shape[0] + assert n_resident == self.current_base.shape[0] + + if not self.with_patterns: + rand_perm = torch.randperm(n_resident)[: self.query_batch_size] + sample_ids = self.current_ids[rand_perm] + queries = self.current_base[rand_perm] + else: + sample_ids = wiki_sampler(self.current_ids, self.query_batch_size, -1) + indices = torch.tensor([torch.where(self.current_ids == s_id)[0][0] for s_id in sample_ids]) + queries = self.current_base[indices] + + entry = {"type": "query", "sample_size": len(sample_ids), "n_resident": n_resident} + torch.save(sample_ids, self.operations_dir / "0.pt") + + # compute the ground truth based on the resident set of vectors + start_time = time.time() + ids, dists = compute_ip_ground_truth(queries, self.current_base, K) + ids = self.current_ids[ids] + gt_time = time.time() - start_time + + entry["gt_time"] = gt_time + + # save the ground truth + torch.save(ids, self.operations_dir / "0_gt_ids.pt") + torch.save(dists, self.operations_dir / "0_gt_dists.pt") + + print("Operation 0", entry) + self.runbook["operations"][0] = entry + + n_queries += 1 + n_operations += 1 + + # for each of the updates, do one insert and one query operation + for i in range(self.num_updates): + print(f"Processing update {i}...") + new_embeddings = torch.from_numpy(np.load(wikidata_dir / "wikidata" / f"embeddings_update_{i}.npy")) + new_embeddings /= torch.norm(new_embeddings, dim=1, keepdim=True) + new_ids = torch.from_numpy(np.load(wikidata_dir / "wikidata" / f"ids_update_{i}.npy")) + + # insert the new embeddings + self.current_base = torch.cat([self.current_base, new_embeddings], dim=0) + self.current_ids = torch.cat([self.current_ids, new_ids], dim=0) + + n_resident = self.current_ids.shape[0] + assert n_resident == self.current_base.shape[0] + + entry = {"type": "insert", "size": new_ids.shape[0], "n_resident": n_resident} + # torch.save(new_ids, self.operations_dir / f"{n_operations}.pt") + + print(f"Operation {n_operations} (insert)", entry) + self.runbook["operations"][n_operations] = entry + + n_operations += 1 + n_inserts += 1 + + # the next operation is a query operation + if not self.with_patterns: + # randomly sample a set of resident embeddings for queries + rand_perm = torch.randperm(n_resident)[: self.query_batch_size] + sample_ids = self.current_ids[rand_perm] + queries = self.current_base[rand_perm] + else: + sample_ids = wiki_sampler(self.current_ids, self.query_batch_size, i) + indices = torch.tensor([torch.where(self.current_ids == s_id)[0][0] for s_id in sample_ids]) + queries = self.current_base[indices] + + entry = {"type": "query", "sample_size": len(sample_ids), "n_resident": n_resident} + torch.save(sample_ids, self.operations_dir / f"{n_operations}.pt") + + # compute the ground truth based on the resident set of vectors + start_time = time.time() + ids, dists = compute_ip_ground_truth(queries, self.current_base, K) + ids = self.current_ids[ids] + gt_time = time.time() - start_time + + entry["gt_time"] = gt_time + + # save the ground truth + torch.save(ids, self.operations_dir / f"{n_operations}_gt_ids.pt") + torch.save(dists, self.operations_dir / f"{n_operations}_gt_dists.pt") + + print(f"Operation {n_operations} (query)", entry) + self.runbook["operations"][n_operations] = entry + + n_operations += 1 + n_queries += 1 + + self.runbook["summary"] = { + "n_inserts": n_inserts, + "n_queries": n_queries, + "n_operations": n_operations, + } + + # save the runbook + with open(self.workload_dir / "runbook.json", "w") as f: + json.dump(self.runbook, f, indent=4) + + +class WikidataWorkloadEvaluator: + """ + Evaluates a Wikidata workload using the same interface as WorkloadEvaluator, + but with explicit NumPy-based embedding handling. + """ + + def __init__( + self, + workload_dir: Union[str, Path], + output_dir: Union[str, Path], + wiki_dataset_dir: Union[str, Path], + ): + self.workload_dir = to_path(workload_dir) + self.wiki_dataset_dir = to_path(wiki_dataset_dir) + self.output_dir = to_path(output_dir) + self.runbook_path = self.workload_dir / "runbook.json" + self.ops_dir = self.workload_dir / "operations" + + # will hold embeddings and ids + self.current_base: Optional[torch.Tensor] = None + self.current_ids: Optional[torch.Tensor] = None + self.index_initialized = False + + def _init_index(self, name: str, wrapper, build_params: Dict, + m_params: Optional[Dict]): + + idx_dir = self.workload_dir / "init_indexes" + idx_dir.mkdir(parents=True, exist_ok=True) + idx_file = idx_dir / f"{name}.index" + + vecs_init = torch.from_numpy(np.load(self.wiki_dataset_dir / "embeddings_initial.npy")) + init_ids = torch.from_numpy(np.load(self.wiki_dataset_dir / "ids_initial.npy")) + + self.current_base = vecs_init + self.current_ids = init_ids + + max_id = int(self.current_ids.max().item()) + inv_map = torch.full((max_id + 1,), -1, dtype=torch.long) + inv_map[self.current_ids] = torch.arange(len(self.current_ids), dtype=torch.long) + self.inv_map = inv_map + + if not idx_file.exists(): + print(f"[{name}] building base index …") + wrapper.build(vecs_init, ids=init_ids, **build_params) + wrapper.save(idx_file) + print(f"[{name}] stored → {idx_file}") + else: + wrapper.load(idx_file, + num_workers=build_params.get("num_workers", 0), use_numa=build_params.get("use_numa", True), parent=build_params.get("parent", None)) + print(f"[{name}] loaded ← {idx_file}") + + if isinstance(wrapper, QuakeWrapper) and m_params: + mp = quake.MaintenancePolicyParams() + for k, v in m_params.items(): + setattr(mp, k, v) + wrapper.index.initialize_maintenance_policy(mp) + print(f"[{name}] maintenance policy: {m_params}") + + + + return wrapper + + def evaluate_workload( + self, + *, + name: str, + index, + build_params: Dict, + search_params: Dict, + do_maintenance: bool = False, + m_params: Optional[Dict] = None, + batch: bool = False, + ) -> List[Dict]: + """ + Evaluate inserts, deletes, and queries by loading NumPy embeddings directly. + """ + self.output_dir.mkdir(parents=True, exist_ok=True) + index = self._init_index(name, index, build_params, m_params) + + runbook = json.load(open(self.runbook_path)) + results: List[Dict] = [] + totals = dict(query=0.0, insert=0.0, delete=0.0, maintenance=0.0) + + print(f"─ Evaluating workload on {name} ({len(runbook['operations'])} ops) ─") + for op_id, op in runbook["operations"].items(): + op_no = int(op_id) + typ = op["type"] + print(f"[{name}] op {op_no:4d} | {typ:<6}", end="", flush=True) + + if typ == "insert": + upd_idx = (op_no - 1) // 2 + emb_up = np.load(self.wiki_dataset_dir / f"embeddings_update_{upd_idx}.npy") + id_up = np.load(self.wiki_dataset_dir / f"ids_update_{upd_idx}.npy") + new_emb = torch.from_numpy(emb_up).float() + new_emb /= new_emb.norm(dim=1, keepdim=True) + new_ids = torch.from_numpy(id_up).long() + + t0 = time.perf_counter() + index.add(new_emb, ids=new_ids) + latency_ms = (time.perf_counter() - t0) * 1e3 + recall = None + + # update current state + old_len = len(self.current_ids) + self.current_base = torch.cat([self.current_base, new_emb], dim=0) + self.current_ids = torch.cat([self.current_ids, new_ids], dim=0) + + max_new_id = int(self.current_ids.max().item()) + if max_new_id >= self.inv_map.size(0): + # need a larger map + new_map = torch.full((max_new_id + 1,), -1, dtype=torch.long) + new_map[: self.inv_map.size(0)] = self.inv_map + self.inv_map = new_map + + # positions of the just‐inserted IDs + new_positions = torch.arange(old_len, old_len + len(new_ids), dtype=torch.long) + self.inv_map[new_ids] = new_positions + + elif typ == "delete": + # assume ops_dir contains .pt of ids to delete + ids = torch.load(self.ops_dir / f"{op_id}.pt") + t0 = time.perf_counter() + index.remove(ids) + latency_ms = (time.perf_counter() - t0) * 1e3 + recall = None + + elif typ == "query": + # load sample IDs and map + samp_ids = torch.load(self.ops_dir / f"{op_id}.pt", weights_only=True) + indices = self.inv_map[samp_ids] + queries = self.current_base[indices] + queries /= queries.norm(dim=1, keepdim=True) + + t0 = time.perf_counter() + + # run first 1000 queries for debugging + max_q = 10000 + queries = queries[:max_q] + if batch: + sr = index.search(queries, **search_params) + pred_ids = sr.ids + else: + parts = [] + for q in queries: + out = index.search(q.unsqueeze(0), **search_params) + parts.append(out.ids) + pred_ids = torch.cat(parts) + latency_ms = (time.perf_counter() - t0) * 1e3 + + gt_ids = torch.load(self.ops_dir / f"{op_id}_gt_ids.pt")[:max_q] + recall = compute_recall(pred_ids, gt_ids, search_params.get("k")).mean().item() + op["recall"] = recall + + else: + raise ValueError(f"Unknown op type {typ}") + + n_splits = 0 + n_deletes = 0 + split_time_ms = 0.0 + delete_time_ms = 0.0 + refinement_time_ms = 0.0 + maintenance_latency_ms = 0.0 + + if do_maintenance: + t0 = time.perf_counter() + nlist_before = index.index_state()["n_list"] + info = index.maintenance() + nlist_after = index.index_state()["n_list"] + maintenance_latency_ms = (time.perf_counter() - t0) * 1e3 + n_splits = info.n_splits + n_deletes = info.n_deletes + delete_time_ms = info.delete_time_us / 1000.0 + split_time_ms = info.split_time_us / 1000.0 + refinement_time_ms = info.refinement_time_us / 1000.0 + + n_resident = index.index_state()["n_total"] + nlist = index.index_state()["n_list"] + + totals[typ] += latency_ms + totals["maintenance"] += maintenance_latency_ms + print(f" | lat {latency_ms:8.2f} ms" + (f" | rec {recall:.3f}" if recall is not None else "")) + + row = { + "operation_number": op_no, + "operation_type": typ, + "latency_ms": latency_ms, + "n_resident": n_resident, + "n_splits": n_splits, + "n_deletes": n_deletes, + "nlist": nlist, + "split_time_ms": split_time_ms, + "delete_time_ms": delete_time_ms, + "maintenance_latency_ms": maintenance_latency_ms, + "refinement_time_ms": refinement_time_ms, + "recall": recall, + } + + results.append(row) + + # four-panel + df = pd.DataFrame(results) + self._four_panel_plot(df) + + # time breakdown + self._time_breakdown_plot(totals, name) + + # CSV output + df.to_csv(self.output_dir / "results.csv", index=False) + print(f"Results → {self.output_dir / 'results.csv'}") + return results + + # --------------------------------------------------------------------- + def _four_panel_plot(self, df: pd.DataFrame): + lat_ins = df[df.operation_type == "insert"] + lat_del = df[df.operation_type == "delete"] + lat_q = df[df.operation_type == "query"] + + fig, axs = plt.subplots(2, 2, figsize=(12, 10)) + ax = axs[0, 0] + if not lat_ins.empty: + ax.plot(lat_ins.operation_number, lat_ins.latency_ms, marker="o", label="Insert") + if not lat_del.empty: + ax.plot(lat_del.operation_number, lat_del.latency_ms, marker="s", label="Delete") + if not lat_q.empty: + ax.plot(lat_q.operation_number, lat_q.latency_ms, marker="^", label="Query") + ax.set(xlabel="Op #", ylabel="Latency (ms)", title="Latency"); ax.legend() + # other panels blank except recall + ax = axs[0, 1] + ax.text(0.5,0.5,"Partitions not tracked",ha="center") + ax.axis("off") + ax = axs[1, 0] + ax.text(0.5,0.5,"Resident not tracked",ha="center") + ax.axis("off") + rec = df[(df.operation_type=="query") & df.recall.notna()] + ax = axs[1, 1] + if not rec.empty: + ax.plot(rec.operation_number, rec.recall, marker="o") + ax.set(xlabel="Op #", ylabel="Recall", title="Recall") + else: + ax.text(0.5,0.5,"No recall",ha="center") + ax.axis("off") + plt.tight_layout() + plt.savefig(self.output_dir / "evaluation_plots.png") + plt.close() + + # --------------------------------------------------------------------- + def _time_breakdown_plot(self, totals: Dict[str, float], title: str): + plt.figure(figsize=(6,4)) + bars = [totals.get("query",0), totals.get("insert",0), totals.get("delete",0), sum(totals.values())] + labels = ["Query","Insert","Delete","Total"] + plt.bar(labels, bars) + plt.ylabel("Cumulative ms") + plt.title(f"Time breakdown – {title}") + plt.tight_layout() + plt.savefig(self.output_dir / "time_breakdown.png", dpi=150) + plt.close() + + +if __name__ == "__main__": + + # parse arguments + import argparse + parser = argparse.ArgumentParser(description="Generate a dynamic workload for Wikidata.") + parser.add_argument( + "--workload_dir", + type=str, + default="data/wikidata/workload", + help="Directory to save the workload.", + ) + parser.add_argument( + "--query_batch_size", + type=int, + default=1000, + help="Batch size for queries between updates.", + ) + + # Initialize the workload generator + args = parser.parse_args() + workload_generator = WikidataWorkloadGenerator( + workload_dir=args.workload_dir, + num_updates=TOTAL_NUM_UPDATES, + query_batch_size=args.query_batch_size, + metric=metric, + with_patterns=True, + overwrite=True, + ) + # Generate the workload + workload_generator.generate_workload() \ No newline at end of file From 476d024e00a813d243bb4672b8e29980d6a97fd0 Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 1 Jun 2025 14:52:15 -0500 Subject: [PATCH 303/323] wiki config --- test/experiments/osdi2025/wiki_workload/wiki_workload.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/experiments/osdi2025/wiki_workload/wiki_workload.py b/test/experiments/osdi2025/wiki_workload/wiki_workload.py index 9a7f298b..e769571c 100644 --- a/test/experiments/osdi2025/wiki_workload/wiki_workload.py +++ b/test/experiments/osdi2025/wiki_workload/wiki_workload.py @@ -369,6 +369,7 @@ def evaluate_workload( do_maintenance: bool = False, m_params: Optional[Dict] = None, batch: bool = False, + max_q: int = 1000, ) -> List[Dict]: """ Evaluate inserts, deletes, and queries by loading NumPy embeddings directly. @@ -432,9 +433,8 @@ def evaluate_workload( t0 = time.perf_counter() - # run first 1000 queries for debugging - max_q = 10000 - queries = queries[:max_q] + randperm = torch.randperm(len(queries)) + queries = queries[randperm[:max_q]] if batch: sr = index.search(queries, **search_params) pred_ids = sr.ids @@ -446,7 +446,7 @@ def evaluate_workload( pred_ids = torch.cat(parts) latency_ms = (time.perf_counter() - t0) * 1e3 - gt_ids = torch.load(self.ops_dir / f"{op_id}_gt_ids.pt")[:max_q] + gt_ids = torch.load(self.ops_dir / f"{op_id}_gt_ids.pt")[randperm[:max_q]] recall = compute_recall(pred_ids, gt_ids, search_params.get("k")).mean().item() op["recall"] = recall From d785ab492439f71081f9e01ad951205f49ab4667 Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 1 Jun 2025 22:53:23 -0500 Subject: [PATCH 304/323] fix fault --- src/cpp/src/query_coordinator.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index ade73c53..3be2ea09 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -476,7 +476,7 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, batched_scan_list( qptr, codes, ids, - Q, part_size, D, + query_ids.size(), part_size, D, res.topk_buffer_pool, metric_, res.blas_ip_block, @@ -1317,6 +1317,11 @@ shared_ptr QueryCoordinator::search(Tensor x, shared_ptrk <= 0) { + throw std::runtime_error("[QueryCoordinator::search] k must be greater than 0."); + } + auto parent_timing_info = std::make_shared(); auto start = high_resolution_clock::now(); @@ -1334,7 +1339,6 @@ shared_ptr QueryCoordinator::search(Tensor x, shared_ptrrecompute_threshold = search_params->recompute_threshold; // parent_search_params->initial_search_fraction = .5; parent_search_params->batched_scan = false; - if (x.size(0) > 10) { parent_search_params->batched_scan = true; } From 5b19e9b8546d4f87bc943b3dd9897bf36c9668bc Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 2 Jun 2025 10:54:42 -0500 Subject: [PATCH 305/323] fix overestimation --- src/cpp/include/query_coordinator.h | 1 + src/cpp/src/query_coordinator.cpp | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index afa4d39e..21a136a6 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -125,6 +125,7 @@ class QueryCoordinator { int next_job_id_ = 0; ///< ID for the next job to be processed. vector> query_dist_pivots_; ///< Pivots for each query to speed up sorting vector> query_done_flags_; ///< Flags to indicate if a query is done from APS + vector> max_rank_; ///< Maximum rank for each query to ensure APS doesn't overshoot vector>> job_flags_; ///< Flags to track job completion std::atomic job_pull_time_ns = 0; ///< Time spent pulling jobs from the queue. std::atomic job_process_time_ns = 0; ///< Time spent processing jobs. diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 3be2ea09..8ee178eb 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -273,6 +273,12 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, return; } + // check the job is not larger than the maximum rank + if (job.rank >= max_rank_[job.query_id].load(std::memory_order_relaxed)) { + enqueue_result_job(ResultJob{job.query_id, job.rank, {}, {}}); + return; + } + // ensure buffers if (res.topk_buffer_pool.size() < 1) { res.topk_buffer_pool.resize(1); @@ -636,6 +642,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, job_flags_.clear(); job_flags_.resize(nQ); per_query_total_left_ = vector>(nQ); + max_rank_ = vector>(nQ); for (int64_t q = 0; q < nQ; ++q) { job_flags_[q] = vector>(partition_ids.size(1)); @@ -649,6 +656,7 @@ void QueryCoordinator::enqueue_scan_jobs(Tensor x, } } per_query_total_left_[q].store(valid_count, std::memory_order_relaxed); + max_rank_[q].store(partition_ids.size(1) - 1, std::memory_order_relaxed); } job_buffer_.clear(); job_buffer_.reserve(nQ * partition_ids.size(1)); @@ -841,6 +849,17 @@ void QueryCoordinator::drain_and_apply_aps(Tensor queries, } float recall_estimate = 0.0f; + float sum = 0.0f; + int max_rank = 0; + + for (int p = 0; p < partition_ids.size(1); ++p) { + sum += recall_profiles[q][p]; + if (sum >= search_params->recall_target) { + max_rank = p; + break; + } + } + max_rank_[q].store(max_rank, std::memory_order_relaxed); int n_scanned = 0; for (int p = 0; p < partition_ids.size(1); ++p) { @@ -848,6 +867,7 @@ void QueryCoordinator::drain_and_apply_aps(Tensor queries, n_scanned++; recall_estimate += recall_profiles[q][p]; } + sum += recall_profiles[q][p]; } if (recall_estimate >= search_params->recall_target) { From 2125b0eab9c31c5258223bd542d666c2fe38b21d Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 2 Jun 2025 11:03:35 -0500 Subject: [PATCH 306/323] fix overestimation --- src/cpp/src/query_coordinator.cpp | 48 +++++++++++++++++-------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 8ee178eb..02230e50 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -793,6 +793,7 @@ void QueryCoordinator::drain_and_apply_aps(Tensor queries, vector> boundary_distances; vector curr_radii; vector> recall_profiles; + vector recall_profile_set; if (use_aps) { boundary_distances.resize(nQ); recall_profiles.resize(nQ); @@ -801,6 +802,8 @@ void QueryCoordinator::drain_and_apply_aps(Tensor queries, } else { curr_radii.resize(nQ, std::numeric_limits::infinity()); } + + recall_profile_set.resize(nQ, false); for (int64_t q = 0; q < nQ; ++q) { vector curr_pids_vec(partition_ids[q].data_ptr(), partition_ids[q].data_ptr() + partition_ids[q].size(0)); @@ -845,33 +848,36 @@ void QueryCoordinator::drain_and_apply_aps(Tensor queries, metric_ == faiss::METRIC_L2); curr_radii[q] = query_radius; + recall_profile_set[q] = true; } - float recall_estimate = 0.0f; - float sum = 0.0f; - int max_rank = 0; - - for (int p = 0; p < partition_ids.size(1); ++p) { - sum += recall_profiles[q][p]; - if (sum >= search_params->recall_target) { - max_rank = p; - break; + if (recall_profile_set[q]) { + float recall_estimate = 0.0f; + float sum = 0.0f; + int max_rank = 0; + + for (int p = 0; p < partition_ids.size(1); ++p) { + sum += recall_profiles[q][p]; + if (sum >= search_params->recall_target) { + max_rank = p; + break; + } } - } - max_rank_[q].store(max_rank, std::memory_order_relaxed); - - int n_scanned = 0; - for (int p = 0; p < partition_ids.size(1); ++p) { - if (job_flags_[q][p].load(std::memory_order_relaxed)) { - n_scanned++; - recall_estimate += recall_profiles[q][p]; + max_rank_[q].store(max_rank, std::memory_order_relaxed); + + int n_scanned = 0; + for (int p = 0; p < partition_ids.size(1); ++p) { + if (job_flags_[q][p].load(std::memory_order_relaxed)) { + n_scanned++; + recall_estimate += recall_profiles[q][p]; + } + sum += recall_profiles[q][p]; } - sum += recall_profiles[q][p]; - } - if (recall_estimate >= search_params->recall_target) { - query_done_flags_[q].store(true, std::memory_order_relaxed); + if (recall_estimate >= search_params->recall_target) { + query_done_flags_[q].store(true, std::memory_order_relaxed); + } } } } From cabcb838cd1de9301fe2975d355c7e293485037b Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 2 Jun 2025 11:41:47 -0500 Subject: [PATCH 307/323] fix overestimation --- src/cpp/src/query_coordinator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 02230e50..95235ef2 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -274,7 +274,7 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, } // check the job is not larger than the maximum rank - if (job.rank >= max_rank_[job.query_id].load(std::memory_order_relaxed)) { + if (job.rank > max_rank_[job.query_id].load(std::memory_order_relaxed)) { enqueue_result_job(ResultJob{job.query_id, job.rank, {}, {}}); return; } From d1758f6a8facd01d7d696ce759a41c4dd2a19f68 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 2 Jun 2025 11:49:39 -0500 Subject: [PATCH 308/323] fix overestimation --- .../osdi2025/wiki_workload/wiki_workload.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/experiments/osdi2025/wiki_workload/wiki_workload.py b/test/experiments/osdi2025/wiki_workload/wiki_workload.py index e769571c..51aea709 100644 --- a/test/experiments/osdi2025/wiki_workload/wiki_workload.py +++ b/test/experiments/osdi2025/wiki_workload/wiki_workload.py @@ -435,14 +435,17 @@ def evaluate_workload( randperm = torch.randperm(len(queries)) queries = queries[randperm[:max_q]] + t_infos = [] if batch: sr = index.search(queries, **search_params) pred_ids = sr.ids + t_infos.append(sr.timing_info) else: parts = [] for q in queries: out = index.search(q.unsqueeze(0), **search_params) parts.append(out.ids) + t_infos.append(out.timing_info) pred_ids = torch.cat(parts) latency_ms = (time.perf_counter() - t0) * 1e3 @@ -450,6 +453,25 @@ def evaluate_workload( recall = compute_recall(pred_ids, gt_ids, search_params.get("k")).mean().item() op["recall"] = recall + total_parent_time = 0 + total_time = 0 + total_boundary_time = 0 + total_aps_time = 0 + total_scan_time = 0 + + for t_info in t_infos: + total_parent_time += t_info.parent_info.total_time_ns / 1e6 + total_time += t_info.total_time_ns / 1e6 + total_boundary_time += t_info.boundary_distance_time_ns / 1e6 + total_aps_time += t_info.aps_time_ns / 1e6 + total_scan_time += t_info.scan_time_ns / 1e6 + + print(f" | parent {total_parent_time:.2f} ms" + f" | total {total_time:.2f} ms" + f" | boundary {total_boundary_time:.2f} ms" + f" | aps {total_aps_time:.2f} ms") + + else: raise ValueError(f"Unknown op type {typ}") @@ -472,6 +494,9 @@ def evaluate_workload( split_time_ms = info.split_time_us / 1000.0 refinement_time_ms = info.refinement_time_us / 1000.0 + + + n_resident = index.index_state()["n_total"] nlist = index.index_state()["n_list"] @@ -493,6 +518,7 @@ def evaluate_workload( "refinement_time_ms": refinement_time_ms, "recall": recall, } + print(row) results.append(row) From 4569ceb7819cbb5c4a19c85fe6a0eeac81401b96 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 2 Jun 2025 11:56:07 -0500 Subject: [PATCH 309/323] fix overestimation --- .../osdi2025/wiki_workload/wiki_workload.py | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/test/experiments/osdi2025/wiki_workload/wiki_workload.py b/test/experiments/osdi2025/wiki_workload/wiki_workload.py index 51aea709..b2236f9f 100644 --- a/test/experiments/osdi2025/wiki_workload/wiki_workload.py +++ b/test/experiments/osdi2025/wiki_workload/wiki_workload.py @@ -457,19 +457,46 @@ def evaluate_workload( total_time = 0 total_boundary_time = 0 total_aps_time = 0 - total_scan_time = 0 + + total_buffer_init_time = 0 + total_copy_query_time = 0 + total_job_enqueue_time = 0 + total_job_wait_time = 0 + total_result_aggregate_time = 0 + +# res->timing_info->buffer_init_time_ns = +# duration_cast(s2 - s1).count(); +# res->timing_info->copy_query_time_ns = +# duration_cast(s3 - s2).count(); +# res->timing_info->job_enqueue_time_ns = +# duration_cast(s4 - s3).count(); +# res->timing_info->job_wait_time_ns = +# duration_cast(s5 - s4).count(); +# res->timing_info->result_aggregate_time_ns = +# duration_cast(s6 - s5).count(); for t_info in t_infos: total_parent_time += t_info.parent_info.total_time_ns / 1e6 total_time += t_info.total_time_ns / 1e6 total_boundary_time += t_info.boundary_distance_time_ns / 1e6 total_aps_time += t_info.aps_time_ns / 1e6 - total_scan_time += t_info.scan_time_ns / 1e6 + total_buffer_init_time += t_info.buffer_init_time_ns / 1e6 + total_copy_query_time += t_info.copy_query_time_ns / 1e6 + total_job_enqueue_time += t_info.job_enqueue_time_ns / 1e6 + total_job_wait_time += t_info.job_wait_time_ns / 1e6 + total_result_aggregate_time += t_info.result_aggregate_time_ns / 1e6 + + print(f" | parent {total_parent_time:.2f} ms" f" | total {total_time:.2f} ms" f" | boundary {total_boundary_time:.2f} ms" - f" | aps {total_aps_time:.2f} ms") + f" | aps {total_aps_time:.2f} ms" + f" | buffer init {total_buffer_init_time:.2f} ms" + f" | copy query {total_copy_query_time:.2f} ms" + f" | job enqueue {total_job_enqueue_time:.2f} ms" + f" | job wait {total_job_wait_time:.2f} ms" + f" | result aggregate {total_result_aggregate_time:.2f} ms") else: From 55b3c1c5bfbac9e934f50c7d234f917f7f5c71b2 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 2 Jun 2025 15:19:42 -0500 Subject: [PATCH 310/323] add readonly workload --- .../configs/msturing10m.yaml | 46 +++++ .../osdi2025/read_only_workload/run.py | 186 ++++++++++++++++++ 2 files changed, 232 insertions(+) create mode 100644 test/experiments/osdi2025/read_only_workload/configs/msturing10m.yaml create mode 100644 test/experiments/osdi2025/read_only_workload/run.py diff --git a/test/experiments/osdi2025/read_only_workload/configs/msturing10m.yaml b/test/experiments/osdi2025/read_only_workload/configs/msturing10m.yaml new file mode 100644 index 00000000..06e25ca4 --- /dev/null +++ b/test/experiments/osdi2025/read_only_workload/configs/msturing10m.yaml @@ -0,0 +1,46 @@ +# configs/experiment.yaml +mode: run # options: build, run, plot +dataset: + name: msturing10m + metric: l2 + path: data +workload_generator: + recall_target: 0.9 + insert_ratio: 0.0 + delete_ratio: 0.0 + query_ratio: 1.0 + number_of_operations: 100 + initial_size: 10000000 + cluster_size: 1000 # N/A for read-only workload + update_batch_size: 10000 # N/A for read-only workload + query_batch_size: 1000 + cluster_sample_distribution: uniform # N/A for read-only workload + query_cluster_sample_distribution: uniform + seed: 9299 + +indexes: + - name: Quake + index: Quake + build_params: + nc: 4000 + metric: ip + num_workers: 8 + num_merge_workers: 1 + use_numa: true + parent: + num_workers: 1 + search_params: + k: 100 + recall_target: .9 + initial_search_fraction: .05 + batched_scan: false + parent: + batched_scan: false + batch_size: 128 + maintenance_params: + refinement_radius: 50 + split_threshold_ns: 100 + delete_threshold_ns: 5 + enable_split_rejection: true + enable_delete_rejection: true + window_size: 1000 diff --git a/test/experiments/osdi2025/read_only_workload/run.py b/test/experiments/osdi2025/read_only_workload/run.py new file mode 100644 index 00000000..560a8887 --- /dev/null +++ b/test/experiments/osdi2025/read_only_workload/run.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python3 +""" +Unified experiment runner + +* Reads a single YAML config (`configs/experiment.yaml`). +* Modes + - **build** –‑ only (re‑)generate the workload. + - **run** –‑ generate workload (if needed), evaluate every index that + does not already have a CSV of prior results (unless + `overwrite.results: true`), then emit the unified plot. + - **plot** –‑ skip evaluation; just regenerate the unified plot. +* A results CSV (`//results.csv`) is written after every + evaluation; its presence is what lets us skip reruns. +* Plot styling (colour / marker / linestyle) is entirely configurable from + the YAML under `plot.styles`. +""" + +import logging, shutil, time, yaml +from pathlib import Path +from typing import Dict, Any, List, Optional + +import matplotlib.pyplot as plt +from matplotlib.lines import Line2D +import numpy as np +import pandas as pd +import torch + +# ── quake imports ────────────────────────────────────────────────────────── +from quake.datasets.ann_datasets import load_dataset +from quake.index_wrappers.quake import QuakeWrapper +from quake.index_wrappers.faiss_ivf import FaissIVF +from quake.utils import compute_recall +from quake.workload_generator import DynamicWorkloadGenerator, WorkloadEvaluator + +logging.basicConfig(level=logging.INFO, + format="%(asctime)s | %(levelname)s | %(message)s") +log = logging.getLogger("runner") + +INDEX_CLASSES = { + "Quake": QuakeWrapper, + "IVF": FaissIVF, +} + +LAT_STYLE = {"insert": "--", "delete": "-.", "query": "-"} + + +# ────────────────────────────────────────────────────────────────────────── +def unified_plot(cfg: Dict[str, Any], out_dir: Path) -> None: + styles = cfg.get("plot", {}).get("styles", {}) + fig, axs = plt.subplots(2, 2, figsize=(12, 10)) + ax_lat, ax_part = axs[0] + ax_res, ax_rec = axs[1] + + legend_idx: List[Line2D] = [] + + for idx in cfg["indexes"]: + name = idx["name"] + csv = out_dir / name / "results.csv" + if not csv.exists(): + log.warning("Skipping plot for %s (no CSV).", name) + continue + df = pd.read_csv(csv) + styl = styles.get(name, {}) + col, mark = styl.get("color"), styl.get("marker") + + # latency + for op in ("insert", "delete", "query"): + sub = df[df.operation_type == op] + if not sub.empty: + ax_lat.plot(sub.operation_number, sub.latency_ms, + color=col, linestyle=LAT_STYLE[op]) + # partitions + if "n_list" in df.columns: + ax_part.plot(df.operation_number, df.n_list, color=col, marker=mark) + # resident + if "n_resident" in df.columns: + ax_res.plot(df.operation_number, df.n_resident, color=col, marker=mark) + # recall + q = df[(df.operation_type == "query") & df.recall.notna()] + if not q.empty: + ax_rec.plot(q.operation_number, q.recall, color=col, marker=mark) + + legend_idx.append(Line2D([0], [0], color=col, label=name)) + + ax_lat.set_yscale("log"); ax_lat.set_title("Latency"); ax_lat.set_xlabel("Op #") + ax_part.set_title("#Partitions"); ax_part.set_xlabel("Op #") + ax_res.set_title("Resident"); ax_res.set_xlabel("Op #") + ax_rec.set_title("Recall"); ax_rec.set_xlabel("Op #"); ax_rec.set_ylim(0, 1) + + style_handles = [Line2D([0], [0], + color="k", ls=LAT_STYLE[o], label=o.title()) + for o in ("insert", "delete", "query")] + ax_lat.legend(handles=style_handles, title="Op type", fontsize=8) + fig.legend(handles=legend_idx, loc="upper center", ncol=max(1, len(legend_idx)), + title="Index", bbox_to_anchor=(0.5, 1.02)) + fig.tight_layout() + path = out_dir / "unified_plot.png" + fig.savefig(path, bbox_inches="tight"); plt.close(fig) + print(f"Unified plot → {path}") + + +# ────────────────────────────────────────────────────────────────────────── +def _should(overwrite: bool, path: Path) -> bool: + return overwrite or not path.exists() + + +# ────────────────────────────────────────────────────────────────────────── +def _evaluate_index(cfg: Dict[str, Any], out_root: Path, batch: bool, + overwrite_results: bool) -> None: + workload_dir = out_root # workload lives in the output root + for idx in cfg["indexes"]: + name = idx["name"] + res_dir = out_root / name + csv = res_dir / "results.csv" + if not _should(overwrite_results, csv): + print(f"{name}: cached results -> skip evaluation"); continue + + cls_key = idx["index"] + cls = INDEX_CLASSES.get(cls_key) + if cls is None: + log.error("Unknown index wrapper %s – skip %s", cls_key, name); continue + res_dir.mkdir(parents=True, exist_ok=True) + + evaluator = WorkloadEvaluator(workload_dir=workload_dir, output_dir=res_dir) + evaluator.evaluate_workload( + name = name, + index = cls(), + build_params = idx.get("build_params", {}), + search_params = idx.get("search_params", {}), + do_maintenance= idx.get("maintenance_params") is not None, + m_params = idx.get("maintenance_params"), + batch = batch, + ) + + +# ────────────────────────────────────────────────────────────────────────── +def _build_workload(cfg: Dict[str, Any], out_root: Path, + overwrite_workload: bool) -> None: + + print("overwrite_workload:", overwrite_workload, "out_root:", out_root) + + if not _should(overwrite_workload, out_root / "runbook.json"): + print("Workload exists – skip generation"); return + + ds_cfg = cfg["dataset"] + vecs, qvecs, _ = load_dataset(ds_cfg["name"], ds_cfg.get("path", "")) + if ds_cfg["metric"] == "l2": # ensure normalisation for L2 if desired + pass + wg_cfg = cfg["workload_generator"] + gen = DynamicWorkloadGenerator( + workload_dir=out_root, + base_vectors=vecs, + metric=ds_cfg["metric"], + insert_ratio=wg_cfg["insert_ratio"], + delete_ratio=wg_cfg["delete_ratio"], + query_ratio =wg_cfg["query_ratio"], + number_of_operations=wg_cfg["number_of_operations"], + initial_size=wg_cfg["initial_size"], + cluster_size=wg_cfg["cluster_size"], + update_batch_size=wg_cfg["update_batch_size"], + query_batch_size =wg_cfg["query_batch_size"], + cluster_sample_distribution=wg_cfg["cluster_sample_distribution"], + queries=qvecs, + query_cluster_sample_distribution=wg_cfg["query_cluster_sample_distribution"], + seed=wg_cfg["seed"], + ) + print("Generating workload …"); gen.generate_workload() + + +# ────────────────────────────────────────────────────────────────────────── +def run_experiment(cfg_src: str | Dict[str, Any], output_dir: str | Path) -> None: + cfg = yaml.safe_load(Path(cfg_src).read_text()) if isinstance(cfg_src, (str, Path)) else cfg_src + out_root = Path(output_dir).expanduser() + out_root.mkdir(parents=True, exist_ok=True) + + mode = cfg.get("mode", "run") + overwrite_results = cfg.get("overwrite_results", False) + overwrite_workload = cfg.get("overwrite_workload", False) + batch = cfg.get("batch", False) + + if mode in {"build", "run"}: + _build_workload(cfg, out_root, overwrite_workload) + if mode == "run": + _evaluate_index(cfg, out_root, batch, overwrite_results) + if mode in {"run", "plot"}: + unified_plot(cfg, out_root) \ No newline at end of file From 4483044ca0bfe01024bdccf36d2419cef6e7a26e Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 2 Jun 2025 15:55:13 -0500 Subject: [PATCH 311/323] add readonly workload --- test/experiments/osdi2025/experiment_runner.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/experiments/osdi2025/experiment_runner.py b/test/experiments/osdi2025/experiment_runner.py index 7f9c2798..ac48516e 100644 --- a/test/experiments/osdi2025/experiment_runner.py +++ b/test/experiments/osdi2025/experiment_runner.py @@ -15,6 +15,7 @@ from test.experiments.osdi2025.maintenance_ablation.run import run_experiment as run_ablation from test.experiments.osdi2025.vary_batch_size.run import run_experiment as run_vary_batch_size from test.experiments.osdi2025.wiki_workload.run import run_experiment as run_wiki_workload +from test.experiments.osdi2025.read_only_workload.run import run_experiment as run_read_only_workload EXPERIMENTS = { "kick_the_tires": run_kick_the_tires, @@ -26,7 +27,8 @@ "vary_levels": run_vary_levels, "maintenance_ablation": run_ablation, "vary_batch_size": run_vary_batch_size, - "wiki_workload": run_wiki_workload + "wiki_workload": run_wiki_workload, + "read_only_workload": run_read_only_workload } def main(): From d6e8ceb1163eb60e8fc7ec2b94528d4f97683314 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 2 Jun 2025 16:31:45 -0500 Subject: [PATCH 312/323] readonly --- .../read_only_workload/configs/msturing10m.yaml | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/test/experiments/osdi2025/read_only_workload/configs/msturing10m.yaml b/test/experiments/osdi2025/read_only_workload/configs/msturing10m.yaml index 06e25ca4..df50e43a 100644 --- a/test/experiments/osdi2025/read_only_workload/configs/msturing10m.yaml +++ b/test/experiments/osdi2025/read_only_workload/configs/msturing10m.yaml @@ -19,12 +19,21 @@ workload_generator: seed: 9299 indexes: + - name: FaissIVF + index: IVF + build_params: + nc: 4000 + metric: l2 + search_params: + k: 100 + nprobe: 250 + - name: Quake index: Quake build_params: nc: 4000 metric: ip - num_workers: 8 + num_workers: num_merge_workers: 1 use_numa: true parent: @@ -39,8 +48,8 @@ indexes: batch_size: 128 maintenance_params: refinement_radius: 50 - split_threshold_ns: 100 - delete_threshold_ns: 5 + split_threshold_ns: 250 + delete_threshold_ns: 5000000 enable_split_rejection: true - enable_delete_rejection: true + enable_delete_rejection: false window_size: 1000 From 735cf18183c7b1827d66cd3c163d7dae0e24a30c Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 2 Jun 2025 16:37:28 -0500 Subject: [PATCH 313/323] readonly --- src/python/index_wrappers/faiss_ivf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/python/index_wrappers/faiss_ivf.py b/src/python/index_wrappers/faiss_ivf.py index 4326cfac..225a3ea3 100644 --- a/src/python/index_wrappers/faiss_ivf.py +++ b/src/python/index_wrappers/faiss_ivf.py @@ -233,6 +233,7 @@ def search( search_result.ids = to_torch(indices) search_result.distances = to_torch(distances) search_result.timing_info = timing_info + search_result.timing_info.parent_info = SearchTimingInfo() return search_result @@ -259,7 +260,7 @@ def save(self, filename: str): """ faiss.write_index(self.index, str(filename)) - def load(self, filename: str): + def load(self, filename: str, **kwargs): """ Load the index from a file. From cc17ec9a819e18a28374d3408047b702fc22ae3c Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 2 Jun 2025 18:01:29 -0500 Subject: [PATCH 314/323] add readonly workload --- src/python/workload_generator.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/python/workload_generator.py b/src/python/workload_generator.py index ab1722b1..2b127b19 100644 --- a/src/python/workload_generator.py +++ b/src/python/workload_generator.py @@ -214,13 +214,13 @@ def initialize_clustered_index(self): index_dir = self.workload_dir / "clustered_index.bin" if index_dir.exists(): index = QuakeWrapper() - index.load(index_dir) + index.load(index_dir, num_workers=1, parent={"num_workers": 1}) n_clusters = index.index.nlist() else: n_clusters = self.base_vectors.shape[0] // self.cluster_size index = QuakeWrapper() index.build( - self.base_vectors, nc=n_clusters, metric=self.metric, ids=torch.arange(self.base_vectors.shape[0]) + self.base_vectors, nc=n_clusters, metric=self.metric, ids=torch.arange(self.base_vectors.shape[0]), num_workers=1, parent={"num_workers": 1} ) index.save(str(self.workload_dir / "clustered_index.bin")) @@ -421,8 +421,11 @@ def _init_index(self, name: str, wrapper, build_params: Dict, wrapper.save(idx_file) print(f"[{name}] stored → {idx_file}") else: - wrapper.load(idx_file, - num_workers=build_params.get("num_workers", 0)) + num_workers = build_params.get("num_workers", 0) + use_numa = build_params.get("use_numa", False) + parent_params = build_params.get("parent", {}) + wrapper.load(idx_file, num_workers=num_workers, + use_numa=use_numa, parent=parent_params) print(f"[{name}] loaded ← {idx_file}") if isinstance(wrapper, QuakeWrapper) and m_params: From 5c7b1f1a9ea0e8ab761ecf351ad763f18ba994bb Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 2 Jun 2025 19:55:11 -0500 Subject: [PATCH 315/323] openimages workload --- .../configs/openimages.yaml | 186 ++++++++++++++ .../osdi2025/open_images_workload/run.py | 227 ++++++++++++++++++ 2 files changed, 413 insertions(+) create mode 100644 test/experiments/osdi2025/open_images_workload/configs/openimages.yaml create mode 100644 test/experiments/osdi2025/open_images_workload/run.py diff --git a/test/experiments/osdi2025/open_images_workload/configs/openimages.yaml b/test/experiments/osdi2025/open_images_workload/configs/openimages.yaml new file mode 100644 index 00000000..07102ce5 --- /dev/null +++ b/test/experiments/osdi2025/open_images_workload/configs/openimages.yaml @@ -0,0 +1,186 @@ +workload_dir: data/wikidata/workload +dataset_dir: /Users/jason/projects/compass/data/wikidata/wikidata +overwrite: True +batch: False + +indexes: + - name: Quake_Serial_NoAPS_NoMaintenance + index: Quake + build_params: + nc: 1000 + metric: ip + num_workers: 1 + use_numa: true + parent: + num_workers: 1 + search_params: + k: 100 + nprobe: 10 + initial_search_fraction: .05 + batched_scan: false + parent: + batched_scan: false + batch_size: 128 + maintenance_params: + refinement_radius: 50 + split_threshold_ns: 500000 + delete_threshold_ns: 500000 + enable_split_rejection: true + enable_delete_rejection: false + window_size: 1000 + + - name: Quake_Serial_NoAPS + index: Quake + build_params: + nc: 1000 + metric: ip + num_workers: 1 + use_numa: true + parent: + num_workers: 1 + search_params: + k: 100 + nprobe: 30 + initial_search_fraction: .05 + batched_scan: false + parent: + batched_scan: true + batch_size: 128 + maintenance_params: + refinement_radius: 50 + split_threshold_ns: 250 + delete_threshold_ns: 500000 + enable_split_rejection: true + enable_delete_rejection: false + window_size: 10000 + + - name: Quake_Serial + index: Quake + build_params: + nc: 1000 + metric: ip + num_workers: 1 + use_numa: true + parent: + num_workers: 1 + search_params: + k: 100 + recall_target: .9 + initial_search_fraction: .05 + batched_scan: false + parent: + batched_scan: true + batch_size: 128 + maintenance_params: + refinement_radius: 50 + split_threshold_ns: 250 + delete_threshold_ns: 500000 + enable_split_rejection: true + enable_delete_rejection: false + window_size: 10000 + + - name: QuakeNoMaintenanceNoAPS + index: Quake + build_params: + nc: 1000 + metric: ip + num_workers: 8 + use_numa: true + parent: + num_workers: 2 + search_params: + k: 100 + nprobe: 30 + batched_scan: false + aps_flush_period_us: 10 + parent: + batched_scan: true + batch_size: 128 + maintenance_params: + refinement_radius: 50 + split_threshold_ns: 500000 + delete_threshold_ns: 500000 + enable_split_rejection: true + enable_delete_rejection: false + window_size: 10000 + + - name: QuakeNoMaintenance + index: Quake + build_params: + nc: 1000 + metric: ip + num_workers: 8 + use_numa: true + parent: + num_workers: 2 + search_params: + k: 100 + recall_target: .9 + batched_scan: false + recompute_threshold: 0.01 + use_precomputed: true + initial_search_fraction: .05 + aps_flush_period_us: 10 + parent: + batched_scan: true + batch_size: 128 + maintenance_params: + refinement_radius: 50 + split_threshold_ns: 500000 + delete_threshold_ns: 500000 + enable_split_rejection: true + enable_delete_rejection: false + window_size: 10000 + + - name: QuakeNoAPS + index: Quake + build_params: + nc: 1000 + metric: ip + num_workers: 8 + use_numa: true + parent: + num_workers: 2 + search_params: + k: 100 + nprobe: 30 + batched_scan: false + aps_flush_period_us: 10 + parent: + batched_scan: true + batch_size: 128 + maintenance_params: + refinement_radius: 50 + split_threshold_ns: 250 + delete_threshold_ns: 500000 + enable_split_rejection: true + enable_delete_rejection: false + window_size: 10000 + + - name: Quake + index: Quake + build_params: + nc: 1000 + metric: ip + num_workers: 8 + use_numa: true + parent: + num_workers: 2 + search_params: + k: 100 + recall_target: .9 + batched_scan: false + recompute_threshold: 0.01 + use_precomputed: true + initial_search_fraction: .05 + aps_flush_period_us: 10 + parent: + batched_scan: true + batch_size: 128 + maintenance_params: + refinement_radius: 50 + split_threshold_ns: 250 + delete_threshold_ns: 500000 + enable_split_rejection: true + enable_delete_rejection: false + window_size: 10000 \ No newline at end of file diff --git a/test/experiments/osdi2025/open_images_workload/run.py b/test/experiments/osdi2025/open_images_workload/run.py new file mode 100644 index 00000000..4e312f5b --- /dev/null +++ b/test/experiments/osdi2025/open_images_workload/run.py @@ -0,0 +1,227 @@ +from __future__ import annotations + +import json, logging, time, shutil +from pathlib import Path +from typing import Dict, List, Any, Optional, Union + +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import torch +import quake +from quake.utils import to_path, compute_recall +from quake.index_wrappers.quake import QuakeWrapper +from quake.index_wrappers.faiss_ivf import FaissIVF +from quake.index_wrappers.faiss_hnsw import FaissHNSW +try: from quake.index_wrappers.scann import Scann +except ImportError: Scann = None # type: ignore +try: from quake.index_wrappers.diskann import DiskANNDynamic +except ImportError: DiskANNDynamic = None # type: ignore +try: from quake.index_wrappers.vamana import Vamana +except ImportError: Vamana = None # type: ignore + +INDEX_CLASSES: Dict[str, Any] = { + "Quake": QuakeWrapper, + "IVF": FaissIVF, + "HNSW": FaissHNSW, + "SCANN": Scann, + "DiskANN": DiskANNDynamic, + "SVS": Vamana, +} + +log = logging.getLogger("openimages") +logging.basicConfig(level=logging.INFO, format="%(asctime)s | %(levelname)s | %(message)s") + +WINDOW_SIZE = 2_000_000 +K = 100 + +STYLE = { + "query": dict(ls="-", marker="o", ms=4, lw=1.1, mfc="none"), + "insert": dict(ls="-", marker="s", ms=4, lw=1.1, mfc="none"), + "delete": dict(ls="-", marker="^", ms=4, lw=1.1, mfc="none"), +} + +class OpenImagesEvaluator: + def __init__(self, workload_dir: Union[str, Path], out_dir: Union[str, Path], + *, dataset_dir: Union[str, Path]): + self.workload_dir = to_path(workload_dir) + self.runbook_path = self.workload_dir / "runbook.json" + self.ops_dir = self.workload_dir / "operations" + self.out_dir = to_path(out_dir); self.out_dir.mkdir(parents=True, exist_ok=True) + + ds = to_path(dataset_dir) + self._BASE = torch.load(ds / "BASE.pt") + self._IDS = torch.load(ds / "IDS.pt") + self._QUERIES = torch.load(ds / "QUERIES.pt") + self._BASE /= self._BASE.norm(dim=1, keepdim=True) + self._QUERIES /= self._QUERIES.norm(dim=1, keepdim=True) + + self.current_start, self.current_end = 0, WINDOW_SIZE + self.current_ids = self._IDS[:WINDOW_SIZE] + self.current_base = self._BASE[:WINDOW_SIZE] + + max_id = int(self._IDS.max()) + self.inv_map = torch.full((max_id + 1,), -1, dtype=torch.long) + self.inv_map[self.current_ids] = torch.arange(len(self.current_ids)) + + # ------------------------------------------------------------------ helpers + def _init_index(self, name: str, wrapper, build_p: Dict[str, Any], + m_p: Optional[Dict[str, Any]]): + idx_dir = self.workload_dir / "init_indexes" + idx_file = idx_dir / f"{name}.index" + idx_dir.mkdir(parents=True, exist_ok=True) + + if not idx_file.exists(): + wrapper.build(self.current_base, ids=self.current_ids, **build_p) + wrapper.save(idx_file) + else: + wrapper.load(idx_file, + num_workers=build_p.get("num_workers", 0), + use_numa =build_p.get("use_numa", True), + parent =build_p.get("parent")) + + if isinstance(wrapper, QuakeWrapper) and m_p: + mp = quake.MaintenancePolicyParams() + for k, v in m_p.items(): setattr(mp, k, v) + wrapper.index.initialize_maintenance_policy(mp) + return wrapper + + # ------------------------------------------------------------------ core + def evaluate(self, *, name: str, wrapper, build_params: Dict[str, Any], + search_params: Dict[str, Any], do_maintenance: bool, + m_params: Optional[Dict[str, Any]], batch: bool, + max_q: int = 1000) -> None: + + wrapper = self._init_index(name, wrapper, build_params, m_params) + runbook = json.load(open(self.runbook_path)) + totals = dict(query=0.0, insert=0.0, delete=0.0, maintenance=0.0) + rows: List[Dict[str, Any]] = [] + + for key, op in runbook["operations"].items(): + op_id = int(key); typ = op["type"]; t0 = time.perf_counter() + + if typ == "delete": + n = op["size"]; ids_del = self.current_ids[:n] + wrapper.remove(ids_del) + self.current_start += n + self.current_ids = self._IDS[self.current_start:self.current_end] + self.current_base = self._BASE[self.current_start:self.current_end] + self.inv_map[ids_del] = -1 + + elif typ == "insert": + n = op["size"]; old_end = self.current_end; self.current_end += n + vecs = self._BASE[old_end:self.current_end]; ids = self._IDS[old_end:self.current_end] + wrapper.add(vecs, ids=ids) + self.current_ids = self._IDS[self.current_start:self.current_end] + self.current_base = self._BASE[self.current_start:self.current_end] + if int(ids.max()) >= self.inv_map.size(0): + bigger = torch.full((int(ids.max()) + 1,), -1, dtype=torch.long) + bigger[:len(self.inv_map)] = self.inv_map; self.inv_map = bigger + self.inv_map[ids] = torch.arange(len(self.current_ids)-n, len(self.current_ids)) + + elif typ == "query": + q_idx = torch.load(self.ops_dir / f"{op_id}.pt") + queries = self._QUERIES[q_idx] + if len(queries) > max_q: + perm = torch.randperm(len(queries))[:max_q] + queries, q_idx = queries[perm], q_idx[perm] + if batch: + pred_ids = wrapper.search(queries, **search_params).ids + else: + parts = [wrapper.search(q.unsqueeze(0), **search_params).ids for q in queries] + pred_ids = torch.cat(parts) + gt_ids = torch.load(self.ops_dir / f"{op_id}_gt_ids.pt")[:len(pred_ids)] + recall = compute_recall(pred_ids, gt_ids, search_params.get("k", K)).mean().item() + op["recall"] = recall + else: + raise ValueError(typ) + + lat_ms = 1e3 * (time.perf_counter() - t0) + maint_ms = spl = dele = spl_ms = del_ms = ref_ms = 0.0 + if do_maintenance: + t1 = time.perf_counter(); info = wrapper.maintenance() + maint_ms = 1e3 * (time.perf_counter() - t1) + spl, dele = info.n_splits, info.n_deletes + spl_ms, del_ms = info.split_time_us/1000.0, info.delete_time_us/1000.0 + ref_ms = info.refinement_time_us/1000.0 + + totals[typ] += lat_ms; totals["maintenance"] += maint_ms + state = wrapper.index_state() + rows.append(dict( + operation_number = op_id, + operation_type = typ, + latency_ms = lat_ms, + maintenance_latency_ms= maint_ms, + n_resident = state.get("n_total", len(self.current_ids)), + nlist = state.get("n_list", np.nan), + n_splits = spl, + n_deletes = dele, + split_time_ms = spl_ms, + delete_time_ms = del_ms, + refinement_time_ms = ref_ms, + recall = op.get("recall"), + )) + + df = pd.DataFrame(rows) + df.to_csv(self.out_dir / "results.csv", index=False) + self._plots(df, totals, name) + + # ------------------------------------------------------------------ plots + def _plots(self, df: pd.DataFrame, tot: Dict[str,float], title: str): + fig, axs = plt.subplots(2,2, figsize=(12,9)) + for t in ("query","insert","delete"): + sub = df[df.operation_type==t] + if not sub.empty: + axs[0,0].plot(sub.operation_number, sub.latency_ms, label=t, **STYLE[t]) + axs[0,0].set_title("Latency"); axs[0,0].legend(); axs[0,0].grid(ls=":") + if "nlist" in df: + axs[0,1].plot(df.operation_number, df.nlist, marker="o", lw=1.1) + axs[0,1].set_title("#Partitions"); axs[0,1].grid(ls=":") + axs[1,0].plot(df.operation_number, df.n_resident, marker="o", lw=1.1) + axs[1,0].set_title("Resident"); axs[1,0].grid(ls=":") + rec = df[(df.operation_type=="query") & df.recall.notna()] + if not rec.empty: + axs[1,1].plot(rec.operation_number, rec.recall, marker="o", lw=1.1) + axs[1,1].set_title("Recall"); axs[1,1].set_ylim(0,1); axs[1,1].grid(ls=":") + fig.suptitle(title); fig.tight_layout() + fig.savefig(self.out_dir / "four_panel.png", dpi=150); plt.close(fig) + + lbl = ["Query","Insert","Delete","Maintenance","Total"] + val = [tot.get("query",0), tot.get("insert",0), + tot.get("delete",0), tot.get("maintenance",0)] + val.append(sum(val)) + plt.bar(lbl, val); plt.title(f"Time breakdown – {title}") + plt.ylabel("ms"); plt.tight_layout() + plt.savefig(self.out_dir / "time_breakdown.png", dpi=150); plt.close() + +# ────────────────────────────────────────────────────────────────────────── +def run_experiment(cfg: Dict[str, Any], output_root: Union[str, Path]) -> None: + wdir = Path(cfg["workload_dir"]).expanduser() + dset = Path(cfg["dataset_dir"]).expanduser() + out = Path(output_root).expanduser() + batch = cfg.get("batch", False) + out.mkdir(parents=True, exist_ok=True) + + for idx in cfg["indexes"]: + name = idx["name"]; wrapper_key = idx["index"] + out_dir = out / name + + if out_dir.exists() and not cfg.get("overwrite", False): + log.info("Skip %s – results exist (overwrite=False)", name); continue + if out_dir.exists() and cfg.get("overwrite", False): + shutil.rmtree(out_dir) + + cls = INDEX_CLASSES.get(wrapper_key) + if cls is None: + log.warning("Unknown wrapper %s – skip %s", wrapper_key, name); continue + + ev = OpenImagesEvaluator(wdir, out_dir, dataset_dir=dset) + ev.evaluate( + name = name, + wrapper= cls(), + build_params = idx.get("build_params", {}), + search_params= idx.get("search_params", {}), + do_maintenance = idx.get("maintenance_params") is not None, + m_params = idx.get("maintenance_params"), + batch = batch, + ) From d5b7db43a389c7eb9a5abae3e1186fa8f7d619af Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 2 Jun 2025 20:18:10 -0500 Subject: [PATCH 316/323] openimages workload --- test/experiments/osdi2025/experiment_runner.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/experiments/osdi2025/experiment_runner.py b/test/experiments/osdi2025/experiment_runner.py index ac48516e..fe2be901 100644 --- a/test/experiments/osdi2025/experiment_runner.py +++ b/test/experiments/osdi2025/experiment_runner.py @@ -16,6 +16,7 @@ from test.experiments.osdi2025.vary_batch_size.run import run_experiment as run_vary_batch_size from test.experiments.osdi2025.wiki_workload.run import run_experiment as run_wiki_workload from test.experiments.osdi2025.read_only_workload.run import run_experiment as run_read_only_workload +from test.experiments.osdi2025.open_images_workload.run import run_experiment as run_open_images_workload EXPERIMENTS = { "kick_the_tires": run_kick_the_tires, @@ -28,7 +29,8 @@ "maintenance_ablation": run_ablation, "vary_batch_size": run_vary_batch_size, "wiki_workload": run_wiki_workload, - "read_only_workload": run_read_only_workload + "read_only_workload": run_read_only_workload, + "open_images_workload": run_open_images_workload } def main(): From 1794d1b51fc9adca82f8879cfbfc5e6078fd9452 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 2 Jun 2025 21:40:45 -0500 Subject: [PATCH 317/323] openimages workload --- test/experiments/osdi2025/open_images_workload/run.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/experiments/osdi2025/open_images_workload/run.py b/test/experiments/osdi2025/open_images_workload/run.py index 4e312f5b..61b9600c 100644 --- a/test/experiments/osdi2025/open_images_workload/run.py +++ b/test/experiments/osdi2025/open_images_workload/run.py @@ -9,6 +9,7 @@ import pandas as pd import torch import quake +import test.experiments.osdi2025.experiment_utils as common_utils from quake.utils import to_path, compute_recall from quake.index_wrappers.quake import QuakeWrapper from quake.index_wrappers.faiss_ivf import FaissIVF @@ -195,7 +196,8 @@ def _plots(self, df: pd.DataFrame, tot: Dict[str,float], title: str): plt.savefig(self.out_dir / "time_breakdown.png", dpi=150); plt.close() # ────────────────────────────────────────────────────────────────────────── -def run_experiment(cfg: Dict[str, Any], output_root: Union[str, Path]) -> None: +def run_experiment(cfg_path_str: Dict[str, Any], output_root: Union[str, Path]) -> None: + cfg = common_utils.load_config(cfg_path_str) wdir = Path(cfg["workload_dir"]).expanduser() dset = Path(cfg["dataset_dir"]).expanduser() out = Path(output_root).expanduser() From 039c6a6f56cf7ef529295019f7e0d3c27e4ee579 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 2 Jun 2025 21:51:54 -0500 Subject: [PATCH 318/323] openimages workload --- test/experiments/osdi2025/open_images_workload/run.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/experiments/osdi2025/open_images_workload/run.py b/test/experiments/osdi2025/open_images_workload/run.py index 61b9600c..cb22dad8 100644 --- a/test/experiments/osdi2025/open_images_workload/run.py +++ b/test/experiments/osdi2025/open_images_workload/run.py @@ -148,7 +148,8 @@ def evaluate(self, *, name: str, wrapper, build_params: Dict[str, Any], totals[typ] += lat_ms; totals["maintenance"] += maint_ms state = wrapper.index_state() - rows.append(dict( + + row = dict( operation_number = op_id, operation_type = typ, latency_ms = lat_ms, @@ -160,9 +161,9 @@ def evaluate(self, *, name: str, wrapper, build_params: Dict[str, Any], split_time_ms = spl_ms, delete_time_ms = del_ms, refinement_time_ms = ref_ms, - recall = op.get("recall"), - )) - + ) + print(row) + rows.append(row) df = pd.DataFrame(rows) df.to_csv(self.out_dir / "results.csv", index=False) self._plots(df, totals, name) From 01308730e6e6da6c0541e67f2fab6d5afc3e5b92 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 2 Jun 2025 21:54:29 -0500 Subject: [PATCH 319/323] openimages workload --- .../configs/openimages.yaml | 250 +++++++++--------- .../osdi2025/open_images_workload/run.py | 2 + 2 files changed, 127 insertions(+), 125 deletions(-) diff --git a/test/experiments/osdi2025/open_images_workload/configs/openimages.yaml b/test/experiments/osdi2025/open_images_workload/configs/openimages.yaml index 07102ce5..40c6d00b 100644 --- a/test/experiments/osdi2025/open_images_workload/configs/openimages.yaml +++ b/test/experiments/osdi2025/open_images_workload/configs/openimages.yaml @@ -4,55 +4,55 @@ overwrite: True batch: False indexes: - - name: Quake_Serial_NoAPS_NoMaintenance - index: Quake - build_params: - nc: 1000 - metric: ip - num_workers: 1 - use_numa: true - parent: - num_workers: 1 - search_params: - k: 100 - nprobe: 10 - initial_search_fraction: .05 - batched_scan: false - parent: - batched_scan: false - batch_size: 128 - maintenance_params: - refinement_radius: 50 - split_threshold_ns: 500000 - delete_threshold_ns: 500000 - enable_split_rejection: true - enable_delete_rejection: false - window_size: 1000 +# - name: Quake_Serial_NoAPS_NoMaintenance +# index: Quake +# build_params: +# nc: 1000 +# metric: ip +# num_workers: 1 +# use_numa: true +# parent: +# num_workers: 1 +# search_params: +# k: 100 +# nprobe: 10 +# initial_search_fraction: .05 +# batched_scan: false +# parent: +# batched_scan: false +# batch_size: 128 +# maintenance_params: +# refinement_radius: 50 +# split_threshold_ns: 500000 +# delete_threshold_ns: 500000 +# enable_split_rejection: true +# enable_delete_rejection: false +# window_size: 1000 - - name: Quake_Serial_NoAPS - index: Quake - build_params: - nc: 1000 - metric: ip - num_workers: 1 - use_numa: true - parent: - num_workers: 1 - search_params: - k: 100 - nprobe: 30 - initial_search_fraction: .05 - batched_scan: false - parent: - batched_scan: true - batch_size: 128 - maintenance_params: - refinement_radius: 50 - split_threshold_ns: 250 - delete_threshold_ns: 500000 - enable_split_rejection: true - enable_delete_rejection: false - window_size: 10000 +# - name: Quake_Serial_NoAPS +# index: Quake +# build_params: +# nc: 1000 +# metric: ip +# num_workers: 1 +# use_numa: true +# parent: +# num_workers: 1 +# search_params: +# k: 100 +# nprobe: 30 +# initial_search_fraction: .05 +# batched_scan: false +# parent: +# batched_scan: true +# batch_size: 128 +# maintenance_params: +# refinement_radius: 50 +# split_threshold_ns: 250 +# delete_threshold_ns: 500000 +# enable_split_rejection: true +# enable_delete_rejection: false +# window_size: 10000 - name: Quake_Serial index: Quake @@ -79,83 +79,83 @@ indexes: enable_delete_rejection: false window_size: 10000 - - name: QuakeNoMaintenanceNoAPS - index: Quake - build_params: - nc: 1000 - metric: ip - num_workers: 8 - use_numa: true - parent: - num_workers: 2 - search_params: - k: 100 - nprobe: 30 - batched_scan: false - aps_flush_period_us: 10 - parent: - batched_scan: true - batch_size: 128 - maintenance_params: - refinement_radius: 50 - split_threshold_ns: 500000 - delete_threshold_ns: 500000 - enable_split_rejection: true - enable_delete_rejection: false - window_size: 10000 - - - name: QuakeNoMaintenance - index: Quake - build_params: - nc: 1000 - metric: ip - num_workers: 8 - use_numa: true - parent: - num_workers: 2 - search_params: - k: 100 - recall_target: .9 - batched_scan: false - recompute_threshold: 0.01 - use_precomputed: true - initial_search_fraction: .05 - aps_flush_period_us: 10 - parent: - batched_scan: true - batch_size: 128 - maintenance_params: - refinement_radius: 50 - split_threshold_ns: 500000 - delete_threshold_ns: 500000 - enable_split_rejection: true - enable_delete_rejection: false - window_size: 10000 - - - name: QuakeNoAPS - index: Quake - build_params: - nc: 1000 - metric: ip - num_workers: 8 - use_numa: true - parent: - num_workers: 2 - search_params: - k: 100 - nprobe: 30 - batched_scan: false - aps_flush_period_us: 10 - parent: - batched_scan: true - batch_size: 128 - maintenance_params: - refinement_radius: 50 - split_threshold_ns: 250 - delete_threshold_ns: 500000 - enable_split_rejection: true - enable_delete_rejection: false - window_size: 10000 +# - name: QuakeNoMaintenanceNoAPS +# index: Quake +# build_params: +# nc: 1000 +# metric: ip +# num_workers: 8 +# use_numa: true +# parent: +# num_workers: 2 +# search_params: +# k: 100 +# nprobe: 30 +# batched_scan: false +# aps_flush_period_us: 10 +# parent: +# batched_scan: true +# batch_size: 128 +# maintenance_params: +# refinement_radius: 50 +# split_threshold_ns: 500000 +# delete_threshold_ns: 500000 +# enable_split_rejection: true +# enable_delete_rejection: false +# window_size: 10000 +# +# - name: QuakeNoMaintenance +# index: Quake +# build_params: +# nc: 1000 +# metric: ip +# num_workers: 8 +# use_numa: true +# parent: +# num_workers: 2 +# search_params: +# k: 100 +# recall_target: .9 +# batched_scan: false +# recompute_threshold: 0.01 +# use_precomputed: true +# initial_search_fraction: .05 +# aps_flush_period_us: 10 +# parent: +# batched_scan: true +# batch_size: 128 +# maintenance_params: +# refinement_radius: 50 +# split_threshold_ns: 500000 +# delete_threshold_ns: 500000 +# enable_split_rejection: true +# enable_delete_rejection: false +# window_size: 10000 +# +# - name: QuakeNoAPS +# index: Quake +# build_params: +# nc: 1000 +# metric: ip +# num_workers: 8 +# use_numa: true +# parent: +# num_workers: 2 +# search_params: +# k: 100 +# nprobe: 30 +# batched_scan: false +# aps_flush_period_us: 10 +# parent: +# batched_scan: true +# batch_size: 128 +# maintenance_params: +# refinement_radius: 50 +# split_threshold_ns: 250 +# delete_threshold_ns: 500000 +# enable_split_rejection: true +# enable_delete_rejection: false +# window_size: 10000 - name: Quake index: Quake diff --git a/test/experiments/osdi2025/open_images_workload/run.py b/test/experiments/osdi2025/open_images_workload/run.py index cb22dad8..e353c23e 100644 --- a/test/experiments/osdi2025/open_images_workload/run.py +++ b/test/experiments/osdi2025/open_images_workload/run.py @@ -98,6 +98,7 @@ def evaluate(self, *, name: str, wrapper, build_params: Dict[str, Any], totals = dict(query=0.0, insert=0.0, delete=0.0, maintenance=0.0) rows: List[Dict[str, Any]] = [] + recall = None for key, op in runbook["operations"].items(): op_id = int(key); typ = op["type"]; t0 = time.perf_counter() @@ -161,6 +162,7 @@ def evaluate(self, *, name: str, wrapper, build_params: Dict[str, Any], split_time_ms = spl_ms, delete_time_ms = del_ms, refinement_time_ms = ref_ms, + recall = recall, ) print(row) rows.append(row) From 12dbc37f086e259ae93c5076b661708520760c37 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 2 Jun 2025 21:55:03 -0500 Subject: [PATCH 320/323] openimages workload --- .../osdi2025/open_images_workload/configs/openimages.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/experiments/osdi2025/open_images_workload/configs/openimages.yaml b/test/experiments/osdi2025/open_images_workload/configs/openimages.yaml index 40c6d00b..2be55e61 100644 --- a/test/experiments/osdi2025/open_images_workload/configs/openimages.yaml +++ b/test/experiments/osdi2025/open_images_workload/configs/openimages.yaml @@ -1,5 +1,5 @@ -workload_dir: data/wikidata/workload -dataset_dir: /Users/jason/projects/compass/data/wikidata/wikidata +workload_dir: data/prepped_openimages/openimages +dataset_dir: data/openimages13m overwrite: True batch: False From 7438af21da5c7abfa78dc69ca19feff08986e2fe Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 4 Jun 2025 16:46:57 -0500 Subject: [PATCH 321/323] multi-level fixes --- src/cpp/bindings/wrap.cpp | 20 ++ src/cpp/include/common.h | 20 ++ src/cpp/include/geometry.h | 57 ++-- src/cpp/include/list_scanning.h | 425 ++++++++++++++++++++++----- src/cpp/include/query_coordinator.h | 3 + src/cpp/src/clustering.cpp | 23 +- src/cpp/src/maintenance_policies.cpp | 3 + src/cpp/src/partition_manager.cpp | 6 +- src/cpp/src/quake_index.cpp | 2 + src/cpp/src/query_coordinator.cpp | 113 ++++--- 10 files changed, 509 insertions(+), 163 deletions(-) diff --git a/src/cpp/bindings/wrap.cpp b/src/cpp/bindings/wrap.cpp index 2c8f5f08..329cfaf2 100644 --- a/src/cpp/bindings/wrap.cpp +++ b/src/cpp/bindings/wrap.cpp @@ -318,6 +318,14 @@ PYBIND11_MODULE(_bindings, m) { return oss.str(); }); + + // double worker_wait_time_ns = 0; ///< Average worker wait time in nanoseconds. + // double worker_process_time_ns = 0; ///< Average worker process time in nanoseconds. + // double worker_process_preamble_time_ns = 0; ///< Average worker process preamble time in nanoseconds. + // double worker_enqueue_time_ns = 0; ///< Average worker enqueue time in nanoseconds. + // double worker_job_time_ns = 0; ///< Average worker job time in nanoseconds. + // double worker_scan_time_ns = 0; ///< Average worker scan time in nanoseconds. + /*********** SearchTimingInfo Binding ***********/ class_>(m, "SearchTimingInfo") .def(init<>()) @@ -349,6 +357,18 @@ PYBIND11_MODULE(_bindings, m) { "Time spent on APS in nanoseconds.") .def_readwrite("scan_time_ns", &SearchTimingInfo::scan_time_ns, "Time spent on scanning in nanoseconds.") + .def_readwrite("worker_wait_time_ns", &SearchTimingInfo::worker_wait_time_ns, + "Average worker wait time in nanoseconds.") + .def_readwrite("worker_process_time_ns", &SearchTimingInfo::worker_process_time_ns, + "Average worker process time in nanoseconds.") + .def_readwrite("worker_process_preamble_time_ns", &SearchTimingInfo::worker_process_preamble_time_ns, + "Average worker process preamble time in nanoseconds.") + .def_readwrite("worker_enqueue_time_ns", &SearchTimingInfo::worker_enqueue_time_ns, + "Average worker enqueue time in nanoseconds.") + .def_readwrite("worker_job_time_ns", &SearchTimingInfo::worker_job_time_ns, + "Average worker job time in nanoseconds.") + .def_readwrite("worker_scan_time_ns", &SearchTimingInfo::worker_scan_time_ns, + "Average worker scan time in nanoseconds.") .def("__repr__", [](const SearchTimingInfo &s) { std::ostringstream oss; oss << "{"; diff --git a/src/cpp/include/common.h b/src/cpp/include/common.h index f840282a..f0d26a5e 100644 --- a/src/cpp/include/common.h +++ b/src/cpp/include/common.h @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef QUAKE_USE_NUMA #include @@ -54,6 +55,18 @@ using std::chrono::milliseconds; using faiss::idx_t; using faiss::MetricType; +struct _EnsureSingleOmp { + _EnsureSingleOmp() { + // Disable OpenMP’s dynamic adjustment and nested teams: + omp_set_dynamic(0); + omp_set_max_active_levels(0); + // Force exactly one thread: + omp_set_num_threads(1); + } +}; + +static _EnsureSingleOmp _ensure_single_omp; + // constants static const uint32_t SerializationMagicNumber = 0x44494E4C; static const uint32_t SerializationVersion = 3; @@ -184,6 +197,7 @@ struct SearchParams { int batch_size = MAX_SUBBATCH; bool track_hits = true; + bool scan_all = false; // APS params bool use_precomputed = DEFAULT_PRECOMPUTED; @@ -252,6 +266,12 @@ struct SearchTimingInfo { int64_t job_wait_time_ns; ///< Time spent waiting for jobs to complete in nanoseconds. int64_t result_aggregate_time_ns; ///< Time spent on aggregating results in nanoseconds. int64_t total_time_ns; ///< Total time spent in nanoseconds. + double worker_wait_time_ns = 0; ///< Average worker wait time in nanoseconds. + double worker_process_time_ns = 0; ///< Average worker process time in nanoseconds. + double worker_process_preamble_time_ns = 0; ///< Average worker process preamble time in nanoseconds. + double worker_enqueue_time_ns = 0; ///< Average worker enqueue time in nanoseconds. + double worker_job_time_ns = 0; ///< Average worker job time in nanoseconds. + double worker_scan_time_ns = 0; ///< Average worker scan time in nanoseconds. }; /** diff --git a/src/cpp/include/geometry.h b/src/cpp/include/geometry.h index 5abbc7f9..4e3922d7 100644 --- a/src/cpp/include/geometry.h +++ b/src/cpp/include/geometry.h @@ -179,6 +179,15 @@ compute_boundary_distances(const Tensor& query, for (std::size_t j = 1; j < centroids.size(); ++j) { const float* cj = centroids[j]; + if (centroids[j] == nullptr) { + if (euclidean) { + dist[j] = std::numeric_limits::infinity(); + } else { + dist[j] = M_PI_2; // max distance on unit sphere + } + continue; + } + if (euclidean) { /* plane distance d = |q·v − b| / ||v|| , b = ½(||cj||²−||c0||²) */ faiss::fvec_sub(dim, cj, c0, v.data()); @@ -194,14 +203,6 @@ compute_boundary_distances(const Tensor& query, float s = std::fabs(faiss::fvec_inner_product(q, v.data(), dim)); s = std::clamp(s, 0.0f, 1.0f); dist[j] = std::asin(s); // 0–π/2 - - // /* unit-sphere model – distance is polar angle to great-circle bisector between c0 and cj. */ - // add_arrays(c0, cj, m.data(), dim); // midpoint vector - // float m_norm = std::sqrt(faiss::fvec_inner_product(m.data(), m.data(), dim)); - // if (m_norm > 0) divide_array_by_constant(m.data(), m_norm, m.data(), dim); - // float cos_ang = faiss::fvec_inner_product(q, m.data(), dim); - // cos_ang = std::clamp(cos_ang, -1.0f, 1.0f); - // dist[j] = std::acos(cos_ang); // radians } } return dist; // dist[0] = 0 by construction @@ -381,27 +382,27 @@ compute_recall_profile(const std::vector& boundary_distances, } // if the cluster_sizes are given, scale probs by the size of the cluster and renormalize. this is a rudimentary density estimation - // if (partition_sizes.size() > 0) { - // for (int k = 1; k < m; ++k) { - // if (partition_sizes[k] > 0) { - // probs[k] *= static_cast(partition_sizes[k]); - // } - // } - // } + if (partition_sizes.size() > 0) { + for (int k = 0; k < m; ++k) { + if (partition_sizes[k] > 0) { + probs[k] *= static_cast(partition_sizes[k]); + } + } + } - // // renormalize the probabilities to sum to 1 - // float S = 0.0f; - // for (int k = 0; k < m; ++k) S += probs[k]; - // if (S > eps) { - // for (int k = 0; k < m; ++k) { - // probs[k] /= S; - // } - // } else { - // // If S is zero, all probabilities remain zero - // for (int k = 0; k < m; ++k) { - // probs[k] = 0.0f; - // } - // } + // renormalize the probabilities to sum to 1 + float S = 0.0f; + for (int k = 0; k < m; ++k) S += probs[k]; + if (S > eps) { + for (int k = 0; k < m; ++k) { + probs[k] /= S; + } + } else { + // If S is zero, all probabilities remain zero + for (int k = 0; k < m; ++k) { + probs[k] = 0.0f; + } + } return probs; } diff --git a/src/cpp/include/list_scanning.h b/src/cpp/include/list_scanning.h index 5dcb9ac6..33466f88 100644 --- a/src/cpp/include/list_scanning.h +++ b/src/cpp/include/list_scanning.h @@ -15,6 +15,12 @@ #include "sorting/heap_select.h" #include "parallel.h" #include "blas_dist.h" +#include + +using IP_Handler = faiss::HeapBlockResultHandler>; +using L2_Handler = faiss::HeapBlockResultHandler>; +using IP_Single = IP_Handler::SingleResultHandler; +using L2_Single = L2_Handler::SingleResultHandler; inline Tensor calculate_recall(Tensor ids, Tensor gt_ids) { Tensor num_correct = torch::zeros(ids.size(0), torch::kInt64); @@ -163,15 +169,15 @@ class TypedTopKBuffer { void reset() { head_ = 0; - for (int i = 0; i < k_; i++) { - if (is_desc_) { - vals_[i] = -std::numeric_limits::infinity(); - ids_[i] = -1; - } else { - vals_[i] = std::numeric_limits::infinity(); - ids_[i] = -1; - } - } + // for (int i = 0; i < k_; i++) { + // if (is_desc_) { + // vals_[i] = -std::numeric_limits::infinity(); + // ids_[i] = -1; + // } else { + // vals_[i] = std::numeric_limits::infinity(); + // ids_[i] = -1; + // } + // } } inline void add(T dist, I idx) { @@ -303,31 +309,31 @@ inline vector> create_buffers(int batch_size, int k, bool return buffers; } -//vector> local_buffers = create_buffers(batch_size, k, (metric_ == faiss::METRIC_INNER_PRODUCT)); +// vector> local_buffers = create_buffers(batch_size, k, (metric_ == faiss::METRIC_INNER_PRODUCT)); -inline std::tuple buffers_to_tensor(vector> buffers) { - int n = buffers.size(); - int k = buffers[0]->k(); - Tensor topk_distances = torch::empty({n, k}, torch::kFloat32); - Tensor topk_indices = torch::empty({n, k}, torch::kInt64); + inline std::tuple buffers_to_tensor(vector> buffers) { + int n = buffers.size(); + int k = buffers[0]->k(); + Tensor topk_distances = torch::empty({n, k}, torch::kFloat32); + Tensor topk_indices = torch::empty({n, k}, torch::kInt64); - auto topk_distances_accessor = topk_distances.accessor(); - auto topk_indices_accessor = topk_indices.accessor(); + auto topk_distances_accessor = topk_distances.accessor(); + auto topk_indices_accessor = topk_indices.accessor(); - for (int i = 0; i < n; i++) { - vector distances = buffers[i]->get_topk(); - vector indices = buffers[i]->get_topk_indices(); + for (int i = 0; i < n; i++) { + vector distances = buffers[i]->get_topk(); + vector indices = buffers[i]->get_topk_indices(); - int curr_k = std::min(k, (int) distances.size()); + int curr_k = std::min(k, (int) distances.size()); - for (int j = 0; j < curr_k; j++) { - topk_distances_accessor[i][j] = distances[j]; - topk_indices_accessor[i][j] = indices[j]; - } - } + for (int j = 0; j < curr_k; j++) { + topk_distances_accessor[i][j] = distances[j]; + topk_indices_accessor[i][j] = indices[j]; + } + } - return std::make_tuple(topk_indices, topk_distances); -} + return std::make_tuple(topk_indices, topk_distances); + } inline void scan_list_no_ids_inner_product(const float *query_vec, const float *list_vecs, @@ -390,7 +396,7 @@ inline void scan_list_with_ids_l2(const float *query_vec, for (int l = 0; l < list_size; l++) { float dist = sqrt(faiss::fvec_L2sqr(query_vec, vec, d)); if (dist < pivot) { - buffer.add(sqrt(faiss::fvec_L2sqr(query_vec, vec, d)), list_ids[l]); + buffer.add(dist, list_ids[l]); } vec += d; } @@ -634,60 +640,327 @@ inline void l2_blas( inline void batched_scan_list(const float *query_vecs, const float *list_vecs, const int64_t *list_ids, - int num_queries, - int list_size, - int dim, - vector> &topk_buffers, - MetricType metric, - float *ip_block, - float *norms_x, - float *norms_y_buf, - int blas_db_bs = BLAS_DB_BS, - vector*> pivots = {}) { - if (list_size == 0 || list_vecs == nullptr) { - // No list vectors to process; + int num_queries, + int list_size, + int dim, + std::vector> &topk_buffers, + MetricType metric, + /* optional scratch supplied by caller: may be nullptr */ + float *ip_block /* = nullptr */, + float *norms_x /* = nullptr */, + float *norms_y_buf /* = nullptr */, + int blas_db_bs /* = BLAS_DB_BS */, + int blas_q_bs /* = 128 */, + std::vector*> pivots /* = {} */) +{ + if (list_size == 0 || num_queries == 0 || list_vecs == nullptr) { return; } - // Ensure k does not exceed list_size - int k = topk_buffers[0]->k(); - int k_max = std::min(k, list_size); + const bool need_norm = (metric == faiss::METRIC_L2); + const int k = std::min(topk_buffers[0]->k(), list_size); + + // --------------------------------------------------------------- + // thread‐local scratch buffers: reused across calls, resized only if + // current block exceeds previous capacity + // --------------------------------------------------------------- + thread_local std::vector TLS_ip; // holds up to (blas_q_bs × blas_db_bs) + thread_local std::vector TLS_nx; // holds up to blas_q_bs + thread_local std::vector TLS_ny; // holds up to blas_db_bs + + // --------------------------------------------------------------- + // If L2 and caller gave no norms_x, ensure TLS_nx can hold blas_q_bs + // --------------------------------------------------------------- + if (need_norm && norms_x == nullptr) { + if ((int)TLS_nx.size() < blas_q_bs) { + TLS_nx.resize(blas_q_bs); + } + } - if (metric == faiss::METRIC_INNER_PRODUCT) { - ip_blas( - query_vecs, - list_vecs, - list_ids, - dim, - num_queries, - list_size, - blas_db_bs, - k_max, - topk_buffers, - ip_block, - pivots - ); - } else if (metric == faiss::METRIC_L2) { - l2_blas( - query_vecs, - list_vecs, - list_ids, - dim, - num_queries, - list_size, - blas_db_bs, - k_max, - topk_buffers, - ip_block, - norms_x, - norms_y_buf, - pivots - ); - } else { - throw std::runtime_error("Metric type not supported"); + // --------------------------------------------------------------- + // Loop over query‐blocks of size ≤ blas_q_bs + // --------------------------------------------------------------- + for (int q_off = 0; q_off < num_queries; q_off += blas_q_bs) { + int q_blk = std::min(blas_q_bs, num_queries - q_off); + const float *q_ptr = query_vecs + size_t(q_off) * dim; + float *q_norms; + + // If caller supplied norms_x, point at offset; else use TLS_nx[0..q_blk-1] + if (need_norm) { + if (norms_x != nullptr) { + q_norms = norms_x + q_off; + } else { + q_norms = TLS_nx.data(); + // compute ‖x‖² for this q‐block + for (int i = 0; i < q_blk; ++i) { + const float *xptr = q_ptr + size_t(i) * dim; + float sumsq = 0.f; + for (int d = 0; d < dim; ++d) { + sumsq += xptr[d] * xptr[d]; + } + q_norms[i] = sumsq; + } + } + } else { + q_norms = nullptr; + } + + // build a small vector of the q_blk TopkBuffers + std::vector> sub_buffers; + sub_buffers.reserve(q_blk); + for (int i = 0; i < q_blk; ++i) { + sub_buffers.push_back(topk_buffers[q_off + i]); + } + + // --------------------------------------------------------------- + // Ensure TLS_ip can hold q_blk × blas_db_bs distances if needed + // --------------------------------------------------------------- + if (ip_block == nullptr) { + size_t need_ip = size_t(q_blk) * size_t(blas_db_bs); + if (TLS_ip.size() < need_ip) { + std::cout << "Resizing TLS_ip from " << TLS_ip.size() + << " to " << need_ip << std::endl; + TLS_ip.resize(need_ip); + } + } + + // --------------------------------------------------------------- + // Loop over database blocks of size ≤ blas_db_bs + // --------------------------------------------------------------- + for (int db_off = 0; db_off < list_size; db_off += blas_db_bs) { + int blk = std::min(blas_db_bs, list_size - db_off); + const float *d_ptr = list_vecs + size_t(db_off) * dim; + const int64_t *d_ids = list_ids + db_off; + + // Decide where to write "ip_block": either caller‐owned or TLS_ip + float *blk_ip = (ip_block != nullptr ? ip_block + : TLS_ip.data()); + + // If L2 and caller gave no norms_y_buf, ensure TLS_ny fits blk + float *blk_norm_y = nullptr; + if (need_norm) { + if (norms_y_buf != nullptr) { + blk_norm_y = norms_y_buf; + } else { + if ((int)TLS_ny.size() < blk) { + TLS_ny.resize(blk); + } + blk_norm_y = TLS_ny.data(); + } + } + + // Dispatch to the appropriate BLAS kernel + if (metric == faiss::METRIC_INNER_PRODUCT) { + ip_blas(q_ptr, + d_ptr, + d_ids, + dim, + q_blk, + blk, + blk, + k, + sub_buffers, + blk_ip, + pivots); + } else { // faiss::METRIC_L2 + l2_blas(q_ptr, + d_ptr, + d_ids, + dim, + q_blk, + blk, + blk, + k, + sub_buffers, + blk_ip, + q_norms, + blk_norm_y, + pivots); + } + } } } +// inline void batched_scan_list(const float *query_vecs, +// const float *list_vecs, +// const int64_t *list_ids, +// int num_queries, +// int list_size, +// int dim, +// std::vector> &topk_buffers, +// MetricType metric, +// /* optional scratch supplied by caller: may be nullptr */ +// float *ip_block /* = nullptr */, +// float *norms_x /* = nullptr */, +// float *norms_y_buf /* = nullptr */, +// int blas_db_bs /* = BLAS_DB_BS */, +// int blas_q_bs /* = 128 */, +// std::vector*> pivots /* = {} */) +// { +// if (list_size == 0 || num_queries == 0 || list_vecs == nullptr) { +// return; +// } +// +// const bool need_norm = (metric == faiss::METRIC_L2); +// // each query has a TopkBuffer in topk_buffers[0..num_queries-1] +// const int k = std::min(topk_buffers[0]->k(), list_size); +// +// /* ------------------------------------------------------------------ */ +// /* TEMPORARY BUFFERS (only if caller did NOT supply) */ +// /* ------------------------------------------------------------------ */ +// std::vector tmp_ip; // for caller‐absent ip_block +// std::vector tmp_nx; // for norms_x if caller did not supply +// std::vector tmp_ny; // for norms_y_buf if caller did not supply +// +// /* ------------------------------------------------------------------ */ +// /* PRE‐COMPUTE ‖x‖² FOR ALL QUERIES IF L2 AND NO norms_x GIVEN */ +// /* ------------------------------------------------------------------ */ +// if (need_norm && norms_x == nullptr) { +// tmp_nx.resize(blas_q_bs); +// norms_x = tmp_nx.data(); +// } +// +// /* ------------------------------------------------------------------ */ +// /* LOOP OVER QUERY BLOCKS OF SIZE ≤ blas_q_bs */ +// /* ------------------------------------------------------------------ */ +// for (int q_off = 0; q_off < num_queries; q_off += blas_q_bs) { +// int q_blk = std::min(blas_q_bs, num_queries - q_off); +// const float *q_ptr = query_vecs + size_t(q_off) * dim; +// float *q_norms = need_norm ? (norms_x + q_off) : nullptr; +// +// // build a subvector of TopkBuffers for these q_blk queries +// std::vector> sub_buffers; +// sub_buffers.reserve(q_blk); +// for (int i = 0; i < q_blk; ++i) { +// sub_buffers.push_back(topk_buffers[q_off + i]); +// } +// +// /* ------------------------------------------------------------------ */ +// /* OPTIONALLY GROW tmp_ip TO HOLD q_blk × blas_db_bs DISTANCES */ +// /* (only if caller did not supply ip_block) */ +// /* ------------------------------------------------------------------ */ +// if (ip_block == nullptr) { +// size_t needed = size_t(q_blk) * size_t(blas_db_bs); +// if (tmp_ip.size() < needed) { +// tmp_ip.resize(needed); +// } +// } +// +// /* ------------------------------------------------------------------ */ +// /* LOOP OVER DATABASE BLOCKS OF SIZE ≤ blas_db_bs */ +// /* ------------------------------------------------------------------ */ +// for (int db_off = 0; db_off < list_size; db_off += blas_db_bs) { +// int blk = std::min(blas_db_bs, list_size - db_off); +// const float *d_ptr = list_vecs + size_t(db_off) * dim; +// const int64_t *d_ids = list_ids + db_off; +// float *blk_ip = ip_block ? ip_block : tmp_ip.data(); +// float *blk_norm_y = nullptr; +// +// /* if L2 and no caller norms_y_buf given, grow tmp_ny to size blk */ +// if (need_norm) { +// if (norms_y_buf != nullptr) { +// blk_norm_y = norms_y_buf; +// } else { +// if ((int)tmp_ny.size() < blk) { +// tmp_ny.resize(blk); +// } +// blk_norm_y = tmp_ny.data(); +// } +// } +// +// if (metric == faiss::METRIC_INNER_PRODUCT) { +// // q_blk queries, blk database rows → distances in blk_ip +// ip_blas(q_ptr, +// d_ptr, +// d_ids, +// dim, +// q_blk, +// blk, +// blk, +// k, +// sub_buffers, +// blk_ip, +// pivots); +// } else if (metric == faiss::METRIC_L2) { +// l2_blas(q_ptr, +// d_ptr, +// d_ids, +// dim, +// q_blk, +// blk, +// blk, +// k, +// sub_buffers, +// blk_ip, +// q_norms, +// blk_norm_y, +// pivots); +// } else { +// throw std::runtime_error("batched_scan_list: unsupported metric"); +// } +// } +// } +// } + +// +// +// inline void batched_scan_list(const float *query_vecs, +// const float *list_vecs, +// const int64_t *list_ids, +// int num_queries, +// int list_size, +// int dim, +// vector> &topk_buffers, +// MetricType metric, +// float *ip_block = nullptr, +// float *norms_x = nullptr, +// float *norms_y_buf = nullptr, +// int blas_db_bs = BLAS_DB_BS, +// vector*> pivots = {}) { +// if (list_size == 0 || list_vecs == nullptr) { +// // No list vectors to process; +// return; +// } +// +// // Ensure k does not exceed list_size +// int k = topk_buffers[0]->k(); +// int k_max = std::min(k, list_size); +// +// if (metric == faiss::METRIC_INNER_PRODUCT) { +// ip_blas( +// query_vecs, +// list_vecs, +// list_ids, +// dim, +// num_queries, +// list_size, +// blas_db_bs, +// k_max, +// topk_buffers, +// ip_block, +// pivots +// ); +// } else if (metric == faiss::METRIC_L2) { +// l2_blas( +// query_vecs, +// list_vecs, +// list_ids, +// dim, +// num_queries, +// list_size, +// blas_db_bs, +// k_max, +// topk_buffers, +// ip_block, +// norms_x, +// norms_y_buf, +// pivots +// ); +// } else { +// throw std::runtime_error("Metric type not supported"); +// } +// } + // } #endif //LIST_SCANNING_H \ No newline at end of file diff --git a/src/cpp/include/query_coordinator.h b/src/cpp/include/query_coordinator.h index 21a136a6..ac603307 100644 --- a/src/cpp/include/query_coordinator.h +++ b/src/cpp/include/query_coordinator.h @@ -132,6 +132,8 @@ class QueryCoordinator { std::atomic total_left_; vector> per_query_total_left_; ///< Total jobs left for each query. + int current_level_; ///< Current level of the coordinator, used for debugging. + /** * @brief Constructs a QueryCoordinator. * @@ -145,6 +147,7 @@ class QueryCoordinator { shared_ptr partition_manager, shared_ptr maintenance_policy, MetricType metric, + int current_level = 0, int num_workers=0, bool use_numa=false, int num_merge_workers=1); diff --git a/src/cpp/src/clustering.cpp b/src/cpp/src/clustering.cpp index 5a46da6a..a826cfcf 100644 --- a/src/cpp/src/clustering.cpp +++ b/src/cpp/src/clustering.cpp @@ -241,16 +241,12 @@ tuple >> kmeans_refine_partitions( for (auto &p : partitions) { max_nq = std::max(max_nq, (size_t)p->num_vectors_); } - max_nq = max_nq * 20; // double the max_nq to ensure enough space for batched_scan_list, as assignments may change. + max_nq = max_nq * 5; // double the max_nq to ensure enough space for batched_scan_list, as assignments may change. // Determine number of clusters and dimension. int n_clusters = centroids.size(0); int d = centroids.size(1); - const size_t ip_need = n_clusters * max_nq; - float * blas_ip_block = static_cast(quake_alloc(ip_need * sizeof(float), 0)); - float * blas_norms_x = static_cast(quake_alloc(max_nq * sizeof(float), 0)); - float * blas_norms_y = static_cast(quake_alloc(n_clusters * sizeof(float), 0)); vector > buffers = create_buffers(max_nq, 1, (metric == faiss::METRIC_INNER_PRODUCT), n_clusters); @@ -311,10 +307,12 @@ tuple >> kmeans_refine_partitions( d, buffers, metric, - /* BLAS scratch */ blas_ip_block, - blas_norms_x, - blas_norms_y, - BLAS_DB_BS); + nullptr, + nullptr, + nullptr, + 128, + BLAS_DB_BS, + {}); // For each vector in this partition, determine its assignment. for (int i = 0; i < nvec; i++) { @@ -337,14 +335,7 @@ tuple >> kmeans_refine_partitions( } } // end for each partition - std::move(new_partitions.begin(), new_partitions.end(), partitions.begin()); } // end iterations - - // Clean up and return the refined centroids and partitions. - quake_free(blas_ip_block, ip_need * sizeof(float)); - quake_free(blas_norms_x, max_nq * sizeof(float)); - quake_free(blas_norms_y, BLAS_DB_BS * sizeof(float)); - return std::make_tuple(centroids, partitions); } diff --git a/src/cpp/src/maintenance_policies.cpp b/src/cpp/src/maintenance_policies.cpp index 106bc895..263f68d0 100644 --- a/src/cpp/src/maintenance_policies.cpp +++ b/src/cpp/src/maintenance_policies.cpp @@ -96,6 +96,7 @@ shared_ptr MaintenancePolicy::perform_maintenance() { auto search_params = make_shared(); search_params->k = 2; // get the top 2 partitions, ignore the first one as it is the partition itself search_params->batched_scan = true; + search_params->track_hits = false; float *partition_vectors = (float *) partition_manager_->partition_store_->partitions_[partition_id]->codes_; Tensor part_vecs = torch::from_blob(partition_vectors, {(int64_t) partition_manager_->partition_store_->list_size(partition_id), partition_manager_->d()}, torch::kFloat32); @@ -223,6 +224,8 @@ void MaintenancePolicy::local_refinement(const torch::Tensor &partition_ids) { auto search_params = std::make_shared(); search_params->nprobe = 1000; search_params->k = params_->refinement_radius; + search_params->batched_scan = true; + search_params->track_hits = false; if (params_->refinement_radius == 0) { return; diff --git a/src/cpp/src/partition_manager.cpp b/src/cpp/src/partition_manager.cpp index fa068200..d72cafb3 100644 --- a/src/cpp/src/partition_manager.cpp +++ b/src/cpp/src/partition_manager.cpp @@ -225,10 +225,8 @@ shared_ptr PartitionManager::add( } auto search_params = make_shared(); search_params->k = 1; - search_params->recall_target = .999; - if (n > 10) { - search_params->batched_scan = true; - } + search_params->scan_all = true; + search_params->track_hits = false; auto parent_search_result = parent_->search(vectors, search_params); Tensor label_out = parent_search_result->ids; auto lbl_ptr = label_out.data_ptr(); diff --git a/src/cpp/src/quake_index.cpp b/src/cpp/src/quake_index.cpp index 946292b2..d384bb14 100644 --- a/src/cpp/src/quake_index.cpp +++ b/src/cpp/src/quake_index.cpp @@ -86,6 +86,7 @@ shared_ptr QuakeIndex::build(Tensor x, Tensor ids, shared_ptrnum_workers << " workers." << std::endl; query_coordinator_ = make_shared(parent_, partition_manager_, maintenance_policy_, metric_, build_params_->num_workers, build_params_->use_numa); auto end = std::chrono::high_resolution_clock::now(); @@ -305,6 +306,7 @@ void QuakeIndex::load(const std::string& dir_path, shared_ptr partition_manager_, maintenance_policy_, metric_, + current_level_, build_params->num_workers, build_params->use_numa, build_params->num_merge_workers); diff --git a/src/cpp/src/query_coordinator.cpp b/src/cpp/src/query_coordinator.cpp index 95235ef2..2d9e0024 100644 --- a/src/cpp/src/query_coordinator.cpp +++ b/src/cpp/src/query_coordinator.cpp @@ -42,6 +42,7 @@ QueryCoordinator::QueryCoordinator(shared_ptr parent, shared_ptr partition_manager, shared_ptr maintenance_policy, MetricType metric, + int current_level, int num_workers, bool use_numa, int num_merge_workers) @@ -49,6 +50,7 @@ QueryCoordinator::QueryCoordinator(shared_ptr parent, partition_manager_(partition_manager), maintenance_policy_(maintenance_policy), metric_(metric), + current_level_(current_level), num_workers_(num_workers), num_merge_workers_(num_merge_workers), workers_initialized_(false) { @@ -110,29 +112,21 @@ void QueryCoordinator::merge_worker_fn(int mid) { if (rj.query_id == -1) // poison pill return; - if (rj.distances.empty()) { - // empty result, nothing to do - --per_query_total_left_[rj.query_id]; - --total_left_; - continue; - } - - // single cast, based on the Compare template using Handler = typename faiss::HeapBlockResultHandler::SingleResultHandler; auto* h = static_cast(MR.handlers[rj.query_id]); - // feed all partial results - for (size_t i = 0; i < rj.distances.size(); ++i) { - h->add_result(rj.distances[i], rj.indices[i]); + if (!rj.distances.empty()) { + // feed all partial results + for (size_t i = 0; i < rj.distances.size(); ++i) { + h->add_result(rj.distances[i], rj.indices[i]); + } + // update pivot + query_dist_pivots_[rj.query_id].store(h->threshold, + std::memory_order_relaxed); } - // update pivot - query_dist_pivots_[rj.query_id].store(h->threshold, - std::memory_order_relaxed); - - per_query_total_left_[rj.query_id]--; // once all ranks for this query are in, finalize & sort - if (per_query_total_left_[rj.query_id] <= 0) { + if (per_query_total_left_[rj.query_id].fetch_sub(1, std::memory_order_acq_rel) == 1) { h->end(); // pack into pairs for sorting @@ -265,8 +259,6 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, CoreResources &res, NUMAResources &nr) { - auto start = std::chrono::high_resolution_clock::now(); - // check that the job has not been processed yet if (query_done_flags_[job.query_id].load(std::memory_order_relaxed)) { enqueue_result_job(ResultJob{job.query_id, job.rank, {}, {}}); @@ -321,6 +313,8 @@ void QueryCoordinator::handle_nonbatched_job(const ScanJob &job, job_flags_[job.query_id][job.rank].store(true, std::memory_order_relaxed); // Mark this job as processed + auto start = std::chrono::high_resolution_clock::now(); + scan_list(nr.local_query_buffer + (job.query_id * D), codes, ids, @@ -489,6 +483,7 @@ void QueryCoordinator::handle_batched_job(const ScanJob &job, res.blas_norms_x, res.blas_norms_y, BLAS_DB_BS, + max_q, pivots); auto s4 = std::chrono::high_resolution_clock::now(); @@ -812,7 +807,6 @@ void QueryCoordinator::drain_and_apply_aps(Tensor queries, curr_centroids_vec, metric_ == faiss::METRIC_L2); } - } auto end = std::chrono::high_resolution_clock::now(); timing->boundary_distance_time_ns = @@ -867,14 +861,24 @@ void QueryCoordinator::drain_and_apply_aps(Tensor queries, max_rank_[q].store(max_rank, std::memory_order_relaxed); int n_scanned = 0; + float partition_recall_in_flight = 0.0f; + int count_in_flight = 0; for (int p = 0; p < partition_ids.size(1); ++p) { if (job_flags_[q][p].load(std::memory_order_relaxed)) { n_scanned++; recall_estimate += recall_profiles[q][p]; + } else { + if (count_in_flight < num_workers_) { + count_in_flight++; + partition_recall_in_flight += recall_profiles[q][p]; + } + } - sum += recall_profiles[q][p]; } + // add the in-flight recall to the estimate + recall_estimate += partition_recall_in_flight; + if (recall_estimate >= search_params->recall_target) { query_done_flags_[q].store(true, std::memory_order_relaxed); } @@ -888,7 +892,6 @@ void QueryCoordinator::drain_and_apply_aps(Tensor queries, } - // mark hits if (search_params->track_hits && maintenance_policy_) { for (int64_t q = 0; q < nQ; ++q) { std::vector scanned_ids; @@ -915,9 +918,13 @@ QueryCoordinator::aggregate_scan_results(int64_t nQ, auto id_acc = out_ids.accessor(); auto d_acc = out_dists.accessor(); + + + // copy results from the global heaps to the output tensors if (metric_ == faiss::METRIC_INNER_PRODUCT) { for (int64_t q = 0; q < nQ; ++q) { + for (int64_t i = 0; i < K; ++i) { id_acc[q][i] = global_max_heaps_->heap_ids_tab[q * K + i]; d_acc [q][i] = global_max_heaps_->heap_dis_tab[q * K + i]; @@ -961,9 +968,7 @@ std::shared_ptr QueryCoordinator::worker_scan( vector core_process_preamble_time_ns(num_workers_, 0); vector core_enqueue_time_ns(num_workers_, 0); vector core_job_time_ns(num_workers_, 0); - vector core_scan_setup_time_ns(num_workers_, 0); vector core_scan_time_ns(num_workers_, 0); - vector core_scan_push_time_ns(num_workers_, 0); for (int i = 0; i < num_workers_; ++i) { core_wait_time_ns[i] = core_resources_[i].wait_time_ns; core_process_time_ns[i] = core_resources_[i].process_time_ns; @@ -1023,6 +1028,30 @@ std::shared_ptr QueryCoordinator::worker_scan( core_scan_time_ns[i] = core_resources_[i].scan_time_ns - core_scan_time_ns[i]; } + // add timers to timing info. average across all workers + int64_t num_workers = num_workers_; + double wait_time_ns = 0; + double process_time_ns = 0; + double process_preamble_time_ns = 0; + double enqueue_time_ns = 0; + double job_time_ns = 0; + double scan_time_ns = 0; + + for (int i = 0; i < num_workers; ++i) { + wait_time_ns += core_wait_time_ns[i]; + process_time_ns += core_process_time_ns[i]; + process_preamble_time_ns += core_process_preamble_time_ns[i]; + enqueue_time_ns += core_enqueue_time_ns[i]; + job_time_ns += core_job_time_ns[i]; + scan_time_ns += core_scan_time_ns[i]; + } + res->timing_info->worker_wait_time_ns = wait_time_ns / num_workers; + res->timing_info->worker_process_time_ns = process_time_ns / num_workers; + res->timing_info->worker_process_preamble_time_ns = process_preamble_time_ns / num_workers; + res->timing_info->worker_enqueue_time_ns = enqueue_time_ns / num_workers; + res->timing_info->worker_job_time_ns = job_time_ns / num_workers; + res->timing_info->worker_scan_time_ns = scan_time_ns / num_workers; + // // print out the per-core resource timers; // for (int i = 0; i < num_workers_; ++i) { @@ -1198,8 +1227,6 @@ shared_ptr QueryCoordinator::serial_scan(Tensor x, Tensor partitio auto t2 = high_resolution_clock::now(); - - Tensor partition_sizes = partition_manager_->get_partition_sizes(partition_ids[q]); vector partition_sizes_vec = vector(partition_sizes.data_ptr(), partition_sizes.data_ptr() + partition_sizes.size(0)); @@ -1354,9 +1381,10 @@ shared_ptr QueryCoordinator::search(Tensor x, shared_ptrscan_all) { // scan all partitions for each query partition_ids_to_scan = partition_manager_->get_partition_ids(); + search_params->batched_scan = true; } else { auto parent_search_params = make_shared(); if (search_params->parent_params == nullptr) { @@ -1404,6 +1432,15 @@ shared_ptr QueryCoordinator::search(Tensor x, shared_ptrtiming_info->total_time_ns = duration_cast(end - start). count(); + // print out the results and report curren_level_ + // std::cout << "[QueryCoordinator::search] " + // << "current_level_=" << current_level_ << " " + // << "n_queries=" << x.size(0) << " " + // << "k=" << search_params->k << " " + // << "batched_scan=" << search_params->batched_scan << " " + // << "total_time_ms=" << (float) search_result->timing_info->total_time_ns / 1e6 << " " + // << "parent_total_time_ms=" << (float) parent_timing_info->total_time_ns / 1e6 << " " << std::endl; + return search_result; } @@ -1445,9 +1482,6 @@ shared_ptr QueryCoordinator::batched_serial_scan( return empty_res; } - static CoreResources serial_res; // one per process - ensure_blas_buffers(serial_res, x.size(0), BLAS_DB_BS, /*node=*/0); - // Timing info (could be extended as needed) auto timing_info = std::make_shared(); auto start = high_resolution_clock::now(); @@ -1456,7 +1490,8 @@ shared_ptr QueryCoordinator::batched_serial_scan( int k = (search_params && search_params->k > 0) ? search_params->k : 1; // Global Top-K buffers: one for each query. - vector> global_buffers = create_buffers(num_queries, k, (metric_ == faiss::METRIC_INNER_PRODUCT)); + vector> global_buffers = create_buffers(num_queries, k, (metric_ == faiss::METRIC_INNER_PRODUCT), + /*cap=*/10 * k); // Ensure partition_ids is 2D. If it’s 1D, assume every query scans the same set. if (partition_ids.dim() == 1) { @@ -1481,7 +1516,7 @@ shared_ptr QueryCoordinator::batched_serial_scan( queries_vec.push_back(entry); } - parallel_for((int64_t) 0, (int64_t) queries_by_partition.size(), [&](int64_t i) { + for (int i = 0; i < queries_vec.size(); i++) { int64_t pid = queries_vec[i].first; auto query_indices = queries_vec[i].second; @@ -1509,10 +1544,12 @@ shared_ptr QueryCoordinator::batched_serial_scan( d, local_buffers, metric_, - /* BLAS scratch */ serial_res.blas_ip_block, - serial_res.blas_norms_x, - serial_res.blas_norms_y, - BLAS_DB_BS); + nullptr, + nullptr, + nullptr, + BLAS_DB_BS, + 128, + {}); // Merge the local results into the corresponding global buffers. for (int i = 0; i < batch_size; i++) { @@ -1522,9 +1559,7 @@ shared_ptr QueryCoordinator::batched_serial_scan( // Merge: global buffer adds the new candidate distances/ids. global_buffers[global_q]->batch_add(local_dists.data(), local_ids.data(), local_ids.size()); } - - - }, search_params->num_threads); + } // Aggregate the final results into output tensors. auto topk_ids = torch::full({num_queries, k}, -1, torch::kInt64); From df4aa07b6be1cb8894f3293b087c1b4571bd23ee Mon Sep 17 00:00:00 2001 From: Devesh Sarda <32046390+sarda-devesh@users.noreply.github.com> Date: Tue, 27 Jan 2026 12:56:39 -0800 Subject: [PATCH 322/323] BigANN related changes (#69) * BigAnn fixes * Fix mainteance bug * BigANN bug fixes * Memory leax fixes * Over memory usage fix * Batched scan slow debug * Big ANN debug working * Fixed segfault error * Tuned Batch Scan * Exposed metrics --- .gitignore | 1051 ++++++++- CMakeLists.txt | 20 +- README.md | 8 + requirements.txt | 14 + ..._scan_0.12_no_aps_refinment_wma_delete.csv | 11 + ...k_scan_0.1_no_aps_refinment_wma_delete.csv | 1280 ++++++++++ ...can_0.13_worker_batch_clustering_score.csv | 21 + .../perf_debug_scan_0.14_tuning.csv | 651 +++++ ...can_0.14_worker_batch_tuning_breakdown.csv | 2 + ...ug_scan_0.14_worker_batch_tuning_lower.csv | 1280 ++++++++++ .../perf_debug_scan_0.15_counters.csv | 1280 ++++++++++ ...erf_debug_scan_0.15_fine_grain_analyze.csv | 11 + ..._scan_0.15_no_aps_refinment_wma_delete.csv | 76 + .../perf_debug_scan_0.15_vary_batch_size.csv | 2101 +++++++++++++++++ ...ebug_scan_0.15_vary_num_search_workers.csv | 901 +++++++ .../scan_0.12_no_aps_refinment_wma_delete.csv | 1280 ++++++++++ .../scan_0.15_no_aps_refinment_wma_delete.csv | 1 + .../scan_0.1_no_aps_refinment_wma.csv | 307 +++ .../scan_0.1_no_aps_refinment_wma_delete.csv | 1280 ++++++++++ ...batching_250_aps_recall_0.8_search_0.1.csv | 29 + ...atching_250_aps_recall_0.9_search_0.01.csv | 47 + ...atching_250_aps_recall_0.9_search_0.05.csv | 30 + ...atching_250_aps_recall_0.9_search_0.15.csv | 1280 ++++++++++ ...ng_250_aps_recall_0.9_search_0.15_0.05.csv | 1280 ++++++++++ ...ing_250_aps_recall_0.9_search_0.1_0.01.csv | 20 + ...hing_250_aps_recall_0.9_search_0.2_0.1.csv | 469 ++++ ...batching_250_aps_recall_0.9_search_0.3.csv | 1280 ++++++++++ .../scan_using_batching_optimizations.csv | 251 ++ .../scan_vary_using_batching_250_no_aps.csv | 506 ++++ ...rf_debug_scan_0.14_worker_batch_tuning.csv | 46 + ...0.14_worker_batch_tuning_with_counters.csv | 76 + .../test_metric_collection.csv | 11 + .../test_perf_debug_scan_0.14_tuning.csv | 26 + ...rf_debug_scan_0.14_worker_batch_tuning.csv | 1280 ++++++++++ ..._debug_scan_0.15_batch_versus_nonbatch.csv | 26 + scripts/big_ann_perf_visualize.py | 282 +++ .../perf_debug_scan_0.14_tuning.png | Bin 0 -> 741337 bytes ...ug_scan_0.14_worker_batch_tuning_lower.png | Bin 0 -> 859116 bytes .../perf_debug_scan_0.15_counters.png | Bin 0 -> 482615 bytes .../perf_debug_scan_0.15_vary_batch_size.png | Bin 0 -> 2514743 bytes ...ebug_scan_0.15_vary_num_search_workers.png | Bin 0 -> 1192992 bytes .../scan_0.12_no_aps_refinment_wma_delete.png | Bin 0 -> 846411 bytes .../scan_0.15_no_aps_refinment_wma_delete.png | Bin 0 -> 564583 bytes .../scan_0.1_no_aps_refinment_wma_delete.png | Bin 0 -> 867590 bytes ...atching_250_aps_recall_0.9_search_0.15.png | Bin 0 -> 654563 bytes ...ng_250_aps_recall_0.9_search_0.15_0.05.png | Bin 0 -> 668678 bytes ...ing_250_aps_recall_0.9_search_0.1_0.01.png | Bin 0 -> 667943 bytes ...batching_250_aps_recall_0.9_search_0.3.png | Bin 0 -> 642397 bytes .../scan_using_batching_optimizations.png | Bin 0 -> 689720 bytes .../scan_vary_using_batching_250_no_aps.png | Bin 0 -> 322244 bytes ...rf_debug_scan_0.14_worker_batch_tuning.png | Bin 0 -> 847409 bytes scripts/cpp/benchmark/big_ann_debug.cpp | 888 +++++++ scripts/test_mainteance.py | 72 + setup.py | 1 + src/cpp/bindings/wrap.cpp | 17 + src/cpp/include/common.h | 27 +- src/cpp/include/dynamic_inverted_list.h | 42 +- src/cpp/include/index_partition.h | 27 +- src/cpp/include/list_scanning.h | 76 +- src/cpp/include/maintenance_policies.h | 3 + src/cpp/include/parallel.h | 1 + src/cpp/include/partition_manager.h | 22 +- src/cpp/include/query_coordinator.h | 32 +- src/cpp/src/clustering.cpp | 2 +- src/cpp/src/dynamic_inverted_list.cpp | 77 +- src/cpp/src/index_partition.cpp | 80 +- src/cpp/src/maintenance_policies.cpp | 60 +- src/cpp/src/partition_manager.cpp | 105 +- src/cpp/src/quake_index.cpp | 8 +- src/cpp/src/query_coordinator.cpp | 497 +++- 70 files changed, 20316 insertions(+), 235 deletions(-) create mode 100644 requirements.txt create mode 100644 scripts/big_ann_perf_numbers/crash_debug_scan_0.12_no_aps_refinment_wma_delete.csv create mode 100644 scripts/big_ann_perf_numbers/mem_check_scan_0.1_no_aps_refinment_wma_delete.csv create mode 100644 scripts/big_ann_perf_numbers/perf_debug_scan_0.13_worker_batch_clustering_score.csv create mode 100644 scripts/big_ann_perf_numbers/perf_debug_scan_0.14_tuning.csv create mode 100644 scripts/big_ann_perf_numbers/perf_debug_scan_0.14_worker_batch_tuning_breakdown.csv create mode 100644 scripts/big_ann_perf_numbers/perf_debug_scan_0.14_worker_batch_tuning_lower.csv create mode 100644 scripts/big_ann_perf_numbers/perf_debug_scan_0.15_counters.csv create mode 100644 scripts/big_ann_perf_numbers/perf_debug_scan_0.15_fine_grain_analyze.csv create mode 100644 scripts/big_ann_perf_numbers/perf_debug_scan_0.15_no_aps_refinment_wma_delete.csv create mode 100644 scripts/big_ann_perf_numbers/perf_debug_scan_0.15_vary_batch_size.csv create mode 100644 scripts/big_ann_perf_numbers/perf_debug_scan_0.15_vary_num_search_workers.csv create mode 100644 scripts/big_ann_perf_numbers/scan_0.12_no_aps_refinment_wma_delete.csv create mode 100644 scripts/big_ann_perf_numbers/scan_0.15_no_aps_refinment_wma_delete.csv create mode 100644 scripts/big_ann_perf_numbers/scan_0.1_no_aps_refinment_wma.csv create mode 100644 scripts/big_ann_perf_numbers/scan_0.1_no_aps_refinment_wma_delete.csv create mode 100644 scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.8_search_0.1.csv create mode 100644 scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.01.csv create mode 100644 scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.05.csv create mode 100644 scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.15.csv create mode 100644 scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.15_0.05.csv create mode 100644 scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.1_0.01.csv create mode 100644 scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.2_0.1.csv create mode 100644 scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.3.csv create mode 100644 scripts/big_ann_perf_numbers/scan_using_batching_optimizations.csv create mode 100644 scripts/big_ann_perf_numbers/scan_vary_using_batching_250_no_aps.csv create mode 100644 scripts/big_ann_perf_numbers/temp_perf_debug_scan_0.14_worker_batch_tuning.csv create mode 100644 scripts/big_ann_perf_numbers/temp_perf_debug_scan_0.14_worker_batch_tuning_with_counters.csv create mode 100644 scripts/big_ann_perf_numbers/test_metric_collection.csv create mode 100644 scripts/big_ann_perf_numbers/test_perf_debug_scan_0.14_tuning.csv create mode 100644 scripts/big_ann_perf_numbers/test_perf_debug_scan_0.14_worker_batch_tuning.csv create mode 100644 scripts/big_ann_perf_numbers/test_perf_debug_scan_0.15_batch_versus_nonbatch.csv create mode 100644 scripts/big_ann_perf_visualize.py create mode 100644 scripts/bigann_perf_vis/perf_debug_scan_0.14_tuning.png create mode 100644 scripts/bigann_perf_vis/perf_debug_scan_0.14_worker_batch_tuning_lower.png create mode 100644 scripts/bigann_perf_vis/perf_debug_scan_0.15_counters.png create mode 100644 scripts/bigann_perf_vis/perf_debug_scan_0.15_vary_batch_size.png create mode 100644 scripts/bigann_perf_vis/perf_debug_scan_0.15_vary_num_search_workers.png create mode 100644 scripts/bigann_perf_vis/scan_0.12_no_aps_refinment_wma_delete.png create mode 100644 scripts/bigann_perf_vis/scan_0.15_no_aps_refinment_wma_delete.png create mode 100644 scripts/bigann_perf_vis/scan_0.1_no_aps_refinment_wma_delete.png create mode 100644 scripts/bigann_perf_vis/scan_using_batching_250_aps_recall_0.9_search_0.15.png create mode 100644 scripts/bigann_perf_vis/scan_using_batching_250_aps_recall_0.9_search_0.15_0.05.png create mode 100644 scripts/bigann_perf_vis/scan_using_batching_250_aps_recall_0.9_search_0.1_0.01.png create mode 100644 scripts/bigann_perf_vis/scan_using_batching_250_aps_recall_0.9_search_0.3.png create mode 100644 scripts/bigann_perf_vis/scan_using_batching_optimizations.png create mode 100644 scripts/bigann_perf_vis/scan_vary_using_batching_250_no_aps.png create mode 100644 scripts/bigann_perf_vis/test_perf_debug_scan_0.14_worker_batch_tuning.png create mode 100644 scripts/cpp/benchmark/big_ann_debug.cpp create mode 100644 scripts/test_mainteance.py diff --git a/.gitignore b/.gitignore index ed8ebf58..786c4a5e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,1050 @@ -__pycache__ \ No newline at end of file +__pycache__ + +##### Windows +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +##### Linux +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +##### MacOS +# General +.DS_Store +.AppleDouble +.LSOverride + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +##### Android +# Built application files +*.apk +*.ap_ +*.aab + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ +# Uncomment the following line in case you need and you don't have the release build type files in your app +# release/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# IntelliJ +*.iml +.idea/workspace.xml +.idea/tasks.xml +.idea/gradle.xml +.idea/assetWizardSettings.xml +.idea/dictionaries +.idea/libraries +# Android Studio 3 in .gitignore file. +.idea/caches +.idea/modules.xml +# Comment next line if keeping position of elements in Navigation Editor is relevant for you +.idea/navEditor.xml + +# Keystore files +# Uncomment the following lines if you do not want to check your keystore files in. +#*.jks +#*.keystore + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild + +# Google Services (e.g. APIs or Firebase) +# google-services.json + +# Freeline +freeline.py +freeline/ +freeline_project_description.json + +# fastlane +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output +fastlane/readme.md + +# Version control +vcs.xml + +# lint +lint/intermediates/ +lint/generated/ +lint/outputs/ +lint/tmp/ +# lint/reports/ + +##### Backup +*.bak +*.gho +*.ori +*.orig +*.tmp + +##### GPG +secring.* + +##### Dropbox +# Dropbox settings and caches +.dropbox +.dropbox.attr +.dropbox.cache + +##### SynopsysVCS +# Waveform formats +*.vcd +*.vpd +*.evcd +*.fsdb + +# Default name of the simulation executable. A different name can be +# specified with this switch (the associated daidir database name is +# also taken from here): -o / +simv + +# Generated for Verilog and VHDL top configs +simv.daidir/ +simv.db.dir/ + +# Infrastructure necessary to co-simulate SystemC models with +# Verilog/VHDL models. An alternate directory may be specified with this +# switch: -Mdir= +csrc/ + +# Log file - the following switch allows to specify the file that will be +# used to write all messages from simulation: -l +*.log + +# Coverage results (generated with urg) and database location. The +# following switch can also be used: urg -dir .vdb +simv.vdb/ +urgReport/ + +# DVE and UCLI related files. +DVEfiles/ +ucli.key + +# When the design is elaborated for DirectC, the following file is created +# with declarations for C/C++ functions. +vc_hdrs.h + +##### SVN +.svn/ + +##### Mercurial +.hg/ +.hgignore +.hgsigs +.hgsub +.hgsubstate +.hgtags + +##### Bazaar +.bzr/ +.bzrignore + +##### CVS +/CVS/* +**/CVS/* +.cvsignore +*/.cvsignore + +##### TortoiseGit +# Project-level settings +/.tgitconfig + +##### PuTTY +# Private key +*.ppk + +##### Vim +# Swap +[._]*.s[a-v][a-z] +!*.svg # comment out if you don't need vector files +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist +*~ +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +##### Emacs +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +dist/ + +# Flycheck +flycheck_*.el + +# server auth directory +/server/ + +# projectiles files +.projectile + +# directory configuration +.dir-locals.el + +# network security +/network-security.data + +##### SublimeText +# Cache files for Sublime Text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# Workspace files are user-specific +*.sublime-workspace + +# Project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using Sublime Text +# *.sublime-project + +# SFTP configuration file +sftp-config.json +sftp-config-alt*.json + +# Package control specific files +Package Control.last-run +Package Control.ca-list +Package Control.ca-bundle +Package Control.system-ca-bundle +Package Control.cache/ +Package Control.ca-certs/ +Package Control.merged-ca-bundle +Package Control.user-ca-bundle +oscrypto-ca-bundle.crt +bh_unicode_properties.cache + +# Sublime-github package stores a github token in this file +# https://packagecontrol.io/packages/sublime-github +GitHub.sublime-settings + +##### Notepad++ +# Notepad++ backups # +*.bak + +##### TextMate +*.tmproj +*.tmproject +tmtags + +##### VisualStudioCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +##### NetBeans +**/nbproject/private/ +**/nbproject/Makefile-*.mk +**/nbproject/Package-*.bash +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +##### JetBrains +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +##### Eclipse +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# CDT- autotools +.autotools + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Annotation Processing +.apt_generated/ +.apt_generated_test/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +# Uncomment this line if you wish to ignore the project description file. +# Typically, this file would be tracked if it contains build/dependency configurations: +#.project + +##### Qt +# C++ objects and libs +*.slo +*.lo +*.o +*.a +*.la +*.lai +*.so +*.so.* +*.dll +*.dylib + +# Qt-es +object_script.*.Release +object_script.*.Debug +*_plugin_import.cpp +/.qmake.cache +/.qmake.stash +*.pro.user +*.pro.user.* +*.qbs.user +*.qbs.user.* +*.moc +moc_*.cpp +moc_*.h +qrc_*.cpp +ui_*.h +*.qmlc +*.jsc +Makefile* +*build-* +*.qm +*.prl + +# Qt unit tests +target_wrapper.* + +# QtCreator +*.autosave + +# QtCreator Qml +*.qmlproject.user +*.qmlproject.user.* + +# QtCreator CMake +CMakeLists.txt.user* + +# QtCreator 4.8< compilation database +compile_commands.json + +# QtCreator local machine specific files for imported projects +*creator.user* + +##### VisualStudio +##### VisualStudio +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*[.json, .xml, .info] + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +##### Gradle +.gradle +**/build/ +!src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 +# gradle/wrapper/gradle-wrapper.properties + +##### CMake +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + +##### C++ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# C/C++ binary extension file +*.bin + +##### C +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Raspberry Pi Pico Object file +*.uf2 +# Raspberry Pi Pico disassembler file +*.dis + +build +quake.egg-info diff --git a/CMakeLists.txt b/CMakeLists.txt index fa71a403..32121138 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # Compiler flags -set(CMAKE_CXX_FLAGS_DEBUG "-g") +set(CMAKE_CXX_FLAGS_DEBUG "-O3 -g") set(CMAKE_CXX_FLAGS_RELEASE "-O3") if(NOT DEFINED QUAKE_SET_ABI_MODE) set(QUAKE_SET_ABI_MODE ON) @@ -95,7 +95,7 @@ add_compile_options(-march=native) # Switch ABI mode if(QUAKE_SET_ABI_MODE) - add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0) + add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=1) endif() @@ -166,17 +166,23 @@ endif() target_link_libraries(${PROJECT_NAME} PUBLIC ${LINK_LIBS}) -IF(CMAKE_BUILD_TYPE MATCHES Debug AND QUAKE_USE_TSAN) +IF(QUAKE_USE_TSAN) message("Using thread sanitizer") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread") set(CMAKE_MODULE_LINKER_FLAGS "{$CMAKE_MODULE_LINKER_FLAGS} -fsanitize=thread") -ENDIF(CMAKE_BUILD_TYPE MATCHES Debug AND QUAKE_USE_TSAN) +ENDIF(QUAKE_USE_TSAN) -IF(CMAKE_BUILD_TYPE MATCHES Debug AND QUAKE_USE_ASAN) +IF(QUAKE_USE_ASAN) message("Using address sanitizer") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-recover=address") set(CMAKE_MODULE_LINKER_FLAGS "{$CMAKE_MODULE_LINKER_FLAGS} -fsanitize=address") -ENDIF(CMAKE_BUILD_TYPE MATCHES Debug AND QUAKE_USE_ASAN) +ENDIF(QUAKE_USE_ASAN) + +IF(QUAKE_USE_LSAN) + message("Using leak sanitizer") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=leak") + set(CMAKE_MODULE_LINKER_FLAGS "{$CMAKE_MODULE_LINKER_FLAGS} -fsanitize=leak") +ENDIF(QUAKE_USE_LSAN) # --------------------------------------------------------------- # Python Bindings @@ -192,7 +198,7 @@ add_dependencies(bindings _bindings) # --------------------------------------------------------------- # Benchmarks # --------------------------------------------------------------- -file(GLOB BENCHMARK_SOURCES "src/cpp/test/benchmark/*.cpp") +file(GLOB BENCHMARK_SOURCES "scripts/cpp/benchmark/*.cpp") foreach(SOURCE ${BENCHMARK_SOURCES}) get_filename_component(EXECUTABLE_NAME ${SOURCE} NAME_WE) diff --git a/README.md b/README.md index 8bab54fd..e9c75c70 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,14 @@ Quake’s Python API provides a set of core operations. The following sections d --- + +### Devesh Notes +Running Big ANN debug script: +``` +cmake -DCMAKE_PREFIX_PATH=$CONDA_PREFIX -DQUAKE_USE_NUMA=OFF -DQUAKE_USE_ASAN=OFF -DQUAKE_USE_AVX512=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=OFF -DQUAKE_SET_ABI_MODE=ON .. +make big_ann_debug -j$(nproc) && ./big_ann_debug &> batch_query_debug.out +``` + ## Further Documentation For detailed instructions and advanced usage, please see the documentation: http://marius-project.org/quake/ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..275bd883 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,14 @@ +--extra-index-url https://download.pytorch.org/whl/cpu +ansicolors==1.1.8 +docker==7.1.0 +h5py==3.10.0 +matplotlib==3.3.4 +numpy==1.24.2 +pyyaml==6.0 +psutil==5.9.4 +scipy==1.10.1 +scikit-learn +jinja2==3.1.2 +pandas==2.0.0 +faiss-cpu +torch diff --git a/scripts/big_ann_perf_numbers/crash_debug_scan_0.12_no_aps_refinment_wma_delete.csv b/scripts/big_ann_perf_numbers/crash_debug_scan_0.12_no_aps_refinment_wma_delete.csv new file mode 100644 index 00000000..bd346572 --- /dev/null +++ b/scripts/big_ann_perf_numbers/crash_debug_scan_0.12_no_aps_refinment_wma_delete.csv @@ -0,0 +1,11 @@ +step_num,step_type,latency_ms,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +2,search,2720.28,-1.0,-1.0,-1.0,-1.0,8.02,0.0184881,1000,38806 +3,insert,23.314,-1.0,-1.0,-1.0,-1.0,10.395,0.0226489,997,49334 +4,search,2056.05,-1.0,-1.0,-1.0,-1.0,9.641,0.0226571,995,49334 +5,insert,15.686,-1.0,-1.0,-1.0,-1.0,163.701,0.033261,985,73557 +6,search,1980.68,-1.0,-1.0,-1.0,-1.0,109.376,0.0333809,988,73557 +7,insert,22.491,-1.0,-1.0,-1.0,-1.0,105.84,0.043066,988,95766 +8,search,1991.55,-1.0,-1.0,-1.0,-1.0,97.167,0.0432598,992,95766 +9,insert,5.541,-1.0,-1.0,-1.0,-1.0,76.324,0.0449698,992,100025 +10,search,2061.73,-1.0,-1.0,-1.0,-1.0,81.606,0.0449918,994,100025 +11,insert,9.081,-1.0,-1.0,-1.0,-1.0,15.419,0.0501926,996,111417 diff --git a/scripts/big_ann_perf_numbers/mem_check_scan_0.1_no_aps_refinment_wma_delete.csv b/scripts/big_ann_perf_numbers/mem_check_scan_0.1_no_aps_refinment_wma_delete.csv new file mode 100644 index 00000000..a3c90368 --- /dev/null +++ b/scripts/big_ann_perf_numbers/mem_check_scan_0.1_no_aps_refinment_wma_delete.csv @@ -0,0 +1,1280 @@ +step_num,step_type,latency_ms,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +2,search,2336.83,-1.0,-1.0,-1.0,-1.0,4.389,0.0184873,1024,38806 +3,insert,9.285,-1.0,-1.0,-1.0,-1.0,10.822,0.0226399,1020,49334 +4,search,1637,-1.0,-1.0,-1.0,-1.0,10.937,0.0226509,1017,49334 +5,insert,14.965,-1.0,-1.0,-1.0,-1.0,157.02,0.0331879,1008,73557 +6,search,1700.63,-1.0,-1.0,-1.0,-1.0,131.037,0.0332577,1010,73557 +7,insert,32.652,-1.0,-1.0,-1.0,-1.0,128.443,0.0428645,1008,95766 +8,search,1722.13,-1.0,-1.0,-1.0,-1.0,96.171,0.0429987,1011,95766 +9,insert,3.494,-1.0,-1.0,-1.0,-1.0,89.102,0.0447152,1011,100025 +10,search,1713.11,-1.0,-1.0,-1.0,-1.0,76.216,0.044778,1013,100025 +11,insert,8.56,-1.0,-1.0,-1.0,-1.0,78.126,0.0498058,1016,111417 +12,search,1740.21,-1.0,-1.0,-1.0,-1.0,15.362,0.050202,1018,111417 +13,insert,18.508,-1.0,-1.0,-1.0,-1.0,8.029,0.0613016,1020,137139 +14,search,1737.66,-1.0,-1.0,-1.0,-1.0,13.383,0.0613061,1022,137139 +15,insert,14.621,-1.0,-1.0,-1.0,-1.0,6.594,0.0696305,1023,156710 +16,search,1765.62,-1.0,-1.0,-1.0,-1.0,15.674,0.0696334,1027,156710 +17,insert,3.996,-1.0,-1.0,-1.0,-1.0,9.588,0.0718712,1030,161773 +18,search,1764.61,-1.0,-1.0,-1.0,-1.0,10.064,0.0719439,1033,161773 +19,insert,31.771,-1.0,-1.0,-1.0,-1.0,12.815,0.0789843,1038,177161 +20,search,1655.41,-1.0,-1.0,-1.0,-1.0,3.087,0.0789843,1038,177161 +21,insert,177.536,-1.0,-1.0,-1.0,-1.0,92.183,0.200641,1084,448898 +22,search,1419.76,-1.0,-1.0,-1.0,-1.0,24.424,0.200676,1095,448898 +23,insert,188.153,-1.0,-1.0,-1.0,-1.0,140.515,0.327594,1146,733493 +24,search,1599.31,-1.0,-1.0,-1.0,-1.0,46.969,0.328483,1164,733493 +25,insert,24.87,-1.0,-1.0,-1.0,-1.0,10.945,0.345922,1168,777443 +26,search,1625.68,-1.0,-1.0,-1.0,-1.0,5.67,0.345925,1169,777443 +27,insert,14.107,-1.0,-1.0,-1.0,-1.0,7.847,0.356689,1170,805394 +28,search,1646.91,-1.0,-1.0,-1.0,-1.0,7.375,0.356776,1171,805394 +29,insert,30.787,-1.0,-1.0,-1.0,-1.0,32.308,0.383981,1186,866391 +30,search,1664.1,-1.0,-1.0,-1.0,-1.0,6.252,0.383981,1187,866391 +31,insert,254.78,-1.0,-1.0,-1.0,-1.0,203.687,0.553265,1248,1239816 +32,search,1857.4,-1.0,-1.0,-1.0,-1.0,40.651,0.553599,1257,1239816 +33,insert,24.712,-1.0,-1.0,-1.0,-1.0,15.181,0.573925,1263,1291211 +34,search,1884.75,-1.0,-1.0,-1.0,-1.0,27.534,0.5741,1268,1291211 +35,insert,16.861,-1.0,-1.0,-1.0,-1.0,15.085,0.587674,1274,1324978 +36,search,1902.28,-1.0,-1.0,-1.0,-1.0,4.367,0.587674,1274,1324978 +37,insert,21.659,-1.0,-1.0,-1.0,-1.0,14.925,0.606952,1278,1371885 +38,search,1926.21,-1.0,-1.0,-1.0,-1.0,7.017,0.606952,1279,1371885 +39,insert,4.268,-1.0,-1.0,-1.0,-1.0,3.926,0.610335,1279,1379335 +40,search,1925.94,-1.0,-1.0,-1.0,-1.0,6.523,0.610336,1280,1379335 +41,insert,17.099,-1.0,-1.0,-1.0,-1.0,8.173,0.62354,1281,1413312 +42,search,1948.95,-1.0,-1.0,-1.0,-1.0,12.054,0.623643,1282,1413312 +43,insert,6.736,-1.0,-1.0,-1.0,-1.0,8.3,0.626657,1283,1423411 +44,search,1960.35,-1.0,-1.0,-1.0,-1.0,7.253,0.626711,1284,1423411 +45,insert,116.659,-1.0,-1.0,-1.0,-1.0,21.016,0.643099,1293,1457559 +46,search,1964.04,-1.0,-1.0,-1.0,-1.0,4.698,0.643099,1293,1457559 +47,insert,159.067,-1.0,-1.0,-1.0,-1.0,151.751,0.748997,1328,1688593 +48,search,2079.41,-1.0,-1.0,-1.0,-1.0,28.83,0.748996,1332,1688593 +49,insert,18.701,-1.0,-1.0,-1.0,-1.0,16.118,0.762754,1338,1723505 +50,search,2097.02,-1.0,-1.0,-1.0,-1.0,16.35,0.762773,1340,1723505 +51,insert,197.078,-1.0,-1.0,-1.0,-1.0,160.951,0.902422,1386,2035040 +52,search,2266.09,-1.0,-1.0,-1.0,-1.0,18.447,0.902436,1389,2035040 +53,insert,28.659,-1.0,-1.0,-1.0,-1.0,31.398,0.921724,1397,2078341 +54,search,2289.3,-1.0,-1.0,-1.0,-1.0,4.352,0.921724,1397,2078341 +55,insert,206.196,-1.0,-1.0,-1.0,-1.0,280.749,1.07006,1454,2399905 +56,search,2466.19,-1.0,-1.0,-1.0,-1.0,47.658,1.0704,1467,2399905 +57,insert,11.309,-1.0,-1.0,-1.0,-1.0,8.377,1.0775,1468,2419836 +58,search,2443.28,-1.0,-1.0,-1.0,-1.0,31.209,1.07752,1473,2419836 +59,insert,127.64,-1.0,-1.0,-1.0,-1.0,78.809,1.17641,1485,2643083 +60,search,2499.14,-1.0,-1.0,-1.0,-1.0,15.664,1.17652,1488,2643083 +61,insert,5.642,-1.0,-1.0,-1.0,-1.0,7.878,1.18039,1489,2653064 +62,search,2497.54,-1.0,-1.0,-1.0,-1.0,8.4,1.18059,1490,2653064 +63,insert,2.265,-1.0,-1.0,-1.0,-1.0,4.725,1.18237,1490,2656118 +64,search,2508.82,-1.0,-1.0,-1.0,-1.0,4.816,1.18237,1490,2656118 +65,insert,39.859,-1.0,-1.0,-1.0,-1.0,55.271,1.21281,1509,2723424 +66,search,2551.77,-1.0,-1.0,-1.0,-1.0,4.928,1.21281,1509,2723424 +67,insert,22.055,-1.0,-1.0,-1.0,-1.0,43.598,1.233,1525,2769021 +68,search,2590.34,-1.0,-1.0,-1.0,-1.0,4.987,1.233,1525,2769021 +69,insert,26.783,-1.0,-1.0,-1.0,-1.0,41.015,1.25648,1537,2821777 +70,search,2602.64,-1.0,-1.0,-1.0,-1.0,7.279,1.25648,1538,2821777 +71,insert,8.187,-1.0,-1.0,-1.0,-1.0,10.274,1.26265,1540,2834921 +72,search,2624.82,-1.0,-1.0,-1.0,-1.0,5.235,1.26265,1540,2834921 +73,insert,4.355,-1.0,-1.0,-1.0,-1.0,12.37,1.26619,1542,2842044 +74,search,2611.77,-1.0,-1.0,-1.0,-1.0,5.005,1.26619,1542,2842044 +75,insert,8.118,-1.0,-1.0,-1.0,-1.0,14.921,1.27087,1546,2858890 +76,search,2635.21,-1.0,-1.0,-1.0,-1.0,6.397,1.27087,1546,2858890 +77,insert,23.39,-1.0,-1.0,-1.0,-1.0,10.204,1.27943,1547,2882818 +78,search,2624.73,-1.0,-1.0,-1.0,-1.0,5.326,1.27943,1547,2882818 +79,insert,284.164,-1.0,-1.0,-1.0,-1.0,11.058,1.30757,1549,2947806 +80,search,2653.05,-1.0,-1.0,-1.0,-1.0,5.61,1.30757,1549,2947806 +81,insert,20.671,-1.0,-1.0,-1.0,-1.0,19.613,1.3184,1552,2976895 +82,search,2666.54,-1.0,-1.0,-1.0,-1.0,10.052,1.31871,1553,2976895 +83,insert,7.349,-1.0,-1.0,-1.0,-1.0,13.113,1.32463,1555,2990682 +84,search,2674.31,-1.0,-1.0,-1.0,-1.0,5.581,1.32463,1555,2990682 +85,insert,23.783,-1.0,-1.0,-1.0,-1.0,18.624,1.33857,1559,3025613 +86,search,2681.47,-1.0,-1.0,-1.0,-1.0,5.118,1.33857,1559,3025613 +87,insert,307.676,-1.0,-1.0,-1.0,-1.0,371.562,1.54092,1640,3468632 +88,search,2909.62,-1.0,-1.0,-1.0,-1.0,64.707,1.54109,1653,3468632 +89,insert,233.126,-1.0,-1.0,-1.0,-1.0,345.566,1.70727,1738,3831692 +90,search,3129.83,-1.0,-1.0,-1.0,-1.0,37.655,1.70737,1744,3831692 +91,insert,19.274,-1.0,-1.0,-1.0,-1.0,24.634,1.71781,1749,3864067 +92,search,3132.94,-1.0,-1.0,-1.0,-1.0,7.794,1.71781,1749,3864067 +93,insert,126.897,-1.0,-1.0,-1.0,-1.0,145.668,1.82186,1786,4103827 +94,search,3242.27,-1.0,-1.0,-1.0,-1.0,22.863,1.82233,1789,4103827 +95,insert,8.147,-1.0,-1.0,-1.0,-1.0,25.319,1.8285,1795,4119898 +96,search,3251.4,-1.0,-1.0,-1.0,-1.0,8.884,1.8285,1795,4119898 +97,insert,5.289,-1.0,-1.0,-1.0,-1.0,8.189,1.83174,1795,4129367 +98,search,3255.35,-1.0,-1.0,-1.0,-1.0,8.831,1.83174,1795,4129367 +99,insert,3.001,-1.0,-1.0,-1.0,-1.0,12.28,1.83296,1796,4134502 +100,search,3254.18,-1.0,-1.0,-1.0,-1.0,8.691,1.83296,1796,4134502 +101,insert,17.69,-1.0,-1.0,-1.0,-1.0,35.67,1.84434,1805,4164482 +102,search,3292.14,-1.0,-1.0,-1.0,-1.0,9.312,1.84434,1805,4164482 +103,insert,8.039,-1.0,-1.0,-1.0,-1.0,16.545,1.84877,1807,4178601 +104,search,3286.57,-1.0,-1.0,-1.0,-1.0,9.06,1.84877,1807,4178601 +105,insert,5.41,-1.0,-1.0,-1.0,-1.0,11.712,1.85231,1808,4187774 +106,search,3286,-1.0,-1.0,-1.0,-1.0,9.157,1.85231,1808,4187774 +107,insert,9.627,-1.0,-1.0,-1.0,-1.0,8.674,1.85729,1808,4200109 +108,search,3284.27,-1.0,-1.0,-1.0,-1.0,9.146,1.85729,1808,4200109 +109,insert,231.728,-1.0,-1.0,-1.0,-1.0,299.747,2.01518,1871,4557867 +110,search,3465.45,-1.0,-1.0,-1.0,-1.0,33.959,2.0158,1878,4557867 +111,insert,16.308,-1.0,-1.0,-1.0,-1.0,38.987,2.02997,1887,4587252 +112,search,3471.71,-1.0,-1.0,-1.0,-1.0,11.009,2.02997,1887,4587252 +113,insert,6.412,-1.0,-1.0,-1.0,-1.0,10.56,2.03391,1887,4600056 +114,search,3481.72,-1.0,-1.0,-1.0,-1.0,14.974,2.03393,1888,4600056 +115,insert,17.79,-1.0,-1.0,-1.0,-1.0,28.766,2.04481,1893,4627422 +116,search,3501.25,-1.0,-1.0,-1.0,-1.0,17.313,2.04494,1895,4627422 +117,insert,7.063,-1.0,-1.0,-1.0,-1.0,19.103,2.04946,1897,4639292 +118,search,3509.01,-1.0,-1.0,-1.0,-1.0,11.485,2.04946,1897,4639292 +119,insert,2.2,-1.0,-1.0,-1.0,-1.0,10.771,2.05061,1897,4643423 +120,search,3511.29,-1.0,-1.0,-1.0,-1.0,11.462,2.05061,1897,4643423 +121,insert,9.354,-1.0,-1.0,-1.0,-1.0,23.315,2.05856,1900,4657252 +122,search,3524.37,-1.0,-1.0,-1.0,-1.0,14.789,2.05866,1901,4657252 +123,insert,211.7,-1.0,-1.0,-1.0,-1.0,260.876,2.18616,1948,4938477 +124,search,3639.87,-1.0,-1.0,-1.0,-1.0,89.885,2.18651,1959,4938477 +125,insert,29.311,-1.0,-1.0,-1.0,-1.0,37.908,2.205,1965,4980492 +126,search,3672.94,-1.0,-1.0,-1.0,-1.0,37.078,2.20509,1969,4980492 +127,insert,29.517,-1.0,-1.0,-1.0,-1.0,72.982,2.22834,1987,5030515 +128,search,3711.16,-1.0,-1.0,-1.0,-1.0,17.716,2.22838,1988,5030515 +129,delete,10.997,-1.0,-1.0,-1.0,-1.0,14.344,2.22779,1983,5009391 +130,search,3658.64,-1.0,-1.0,-1.0,-1.0,13.195,2.22779,1983,5009391 +131,delete,2.832,-1.0,-1.0,-1.0,-1.0,12.428,2.22779,1983,5004093 +132,search,3690.44,-1.0,-1.0,-1.0,-1.0,14.309,2.22779,1983,5004093 +133,delete,12.406,-1.0,-1.0,-1.0,-1.0,12.843,2.22776,1983,4991787 +134,search,3688.53,-1.0,-1.0,-1.0,-1.0,13.477,2.22776,1983,4991787 +135,delete,14.162,-1.0,-1.0,-1.0,-1.0,12.55,2.22676,1983,4974857 +136,search,3668.84,-1.0,-1.0,-1.0,-1.0,13.185,2.22676,1983,4974857 +137,delete,2.514,-1.0,-1.0,-1.0,-1.0,12.444,2.22676,1983,4971386 +138,search,3701.45,-1.0,-1.0,-1.0,-1.0,13.545,2.22676,1983,4971386 +139,delete,6.679,-1.0,-1.0,-1.0,-1.0,12.602,2.22676,1983,4963487 +140,search,3682.42,-1.0,-1.0,-1.0,-1.0,13.199,2.22676,1983,4963487 +141,delete,14.726,-1.0,-1.0,-1.0,-1.0,12.61,2.22518,1983,4941830 +142,search,3671.46,-1.0,-1.0,-1.0,-1.0,13.658,2.22518,1983,4941830 +143,delete,12.79,-1.0,-1.0,-1.0,-1.0,12.536,2.22321,1983,4925657 +144,search,3671.03,-1.0,-1.0,-1.0,-1.0,13.155,2.22321,1983,4925657 +145,delete,1.994,-1.0,-1.0,-1.0,-1.0,12.43,2.22304,1983,4922686 +146,search,3661.02,-1.0,-1.0,-1.0,-1.0,13.537,2.22304,1983,4922686 +147,delete,7.806,-1.0,-1.0,-1.0,-1.0,12.451,2.22304,1983,4913636 +148,search,3651.65,-1.0,-1.0,-1.0,-1.0,13.253,2.22304,1983,4913636 +149,delete,119.703,-1.0,-1.0,-1.0,-1.0,58.942,2.19397,1973,4717250 +150,search,3561.59,-1.0,-1.0,-1.0,-1.0,13.811,2.19397,1973,4717250 +151,delete,108.13,-1.0,-1.0,-1.0,-1.0,74.478,2.15347,1961,4560269 +152,search,3483.17,-1.0,-1.0,-1.0,-1.0,13.397,2.15347,1961,4560269 +153,delete,20.16,-1.0,-1.0,-1.0,-1.0,30.956,2.14159,1956,4521936 +154,search,3449.4,-1.0,-1.0,-1.0,-1.0,13.849,2.14159,1956,4521936 +155,delete,14.384,-1.0,-1.0,-1.0,-1.0,12.002,2.13912,1956,4502222 +156,search,3471.17,-1.0,-1.0,-1.0,-1.0,13.369,2.13912,1956,4502222 +157,delete,24.212,-1.0,-1.0,-1.0,-1.0,13.332,2.13268,1956,4456039 +158,search,3432.98,-1.0,-1.0,-1.0,-1.0,13.819,2.13268,1956,4456039 +159,delete,205.195,-1.0,-1.0,-1.0,-1.0,253.224,1.99612,1900,4143922 +160,search,3247.23,-1.0,-1.0,-1.0,-1.0,18.595,1.99632,1901,4143922 +161,delete,26.869,-1.0,-1.0,-1.0,-1.0,13.28,1.9913,1901,4101445 +162,search,3264.23,-1.0,-1.0,-1.0,-1.0,13.408,1.9913,1901,4101445 +163,delete,13.031,-1.0,-1.0,-1.0,-1.0,12.135,1.98712,1901,4080175 +164,search,3260.52,-1.0,-1.0,-1.0,-1.0,13.028,1.98712,1901,4080175 +165,delete,21.187,-1.0,-1.0,-1.0,-1.0,12.607,1.9794,1901,4047313 +166,search,3237.34,-1.0,-1.0,-1.0,-1.0,13.487,1.9794,1901,4047313 +167,delete,6.217,-1.0,-1.0,-1.0,-1.0,11.891,1.97732,1901,4040738 +168,search,3221.98,-1.0,-1.0,-1.0,-1.0,13.288,1.97732,1901,4040738 +169,delete,14.115,-1.0,-1.0,-1.0,-1.0,20.042,1.97017,1900,4022674 +170,search,3225.94,-1.0,-1.0,-1.0,-1.0,13.511,1.97017,1900,4022674 +171,delete,5.851,-1.0,-1.0,-1.0,-1.0,11.892,1.96758,1900,4015835 +172,search,3225.49,-1.0,-1.0,-1.0,-1.0,13.099,1.96758,1900,4015835 +173,delete,22.926,-1.0,-1.0,-1.0,-1.0,12.652,1.95975,1900,3986424 +174,search,3212.01,-1.0,-1.0,-1.0,-1.0,13.387,1.95975,1900,3986424 +175,delete,121.219,-1.0,-1.0,-1.0,-1.0,219.591,1.87426,1854,3804693 +176,search,3115.83,-1.0,-1.0,-1.0,-1.0,19.467,1.87445,1855,3804693 +177,delete,11.841,-1.0,-1.0,-1.0,-1.0,12.197,1.86932,1855,3786352 +178,search,3071.46,-1.0,-1.0,-1.0,-1.0,12.963,1.86932,1855,3786352 +179,delete,153.885,-1.0,-1.0,-1.0,-1.0,165.157,1.756,1799,3556994 +180,search,2960.84,-1.0,-1.0,-1.0,-1.0,12.413,1.756,1799,3556994 +181,delete,19.135,-1.0,-1.0,-1.0,-1.0,12.099,1.74619,1798,3526824 +182,search,2949.73,-1.0,-1.0,-1.0,-1.0,12.3,1.74619,1798,3526824 +183,delete,109.908,-1.0,-1.0,-1.0,-1.0,238.963,1.65983,1743,3350245 +184,search,2850.24,-1.0,-1.0,-1.0,-1.0,16.976,1.66003,1744,3350245 +185,delete,6.328,-1.0,-1.0,-1.0,-1.0,12.297,1.65808,1742,3340234 +186,search,2837.1,-1.0,-1.0,-1.0,-1.0,11.986,1.65808,1742,3340234 +187,delete,115.256,-1.0,-1.0,-1.0,-1.0,152.169,1.55932,1709,3150857 +188,search,2732.78,-1.0,-1.0,-1.0,-1.0,18.017,1.5594,1710,3150857 +189,delete,5.078,-1.0,-1.0,-1.0,-1.0,10.656,1.55758,1710,3143609 +190,search,2771.77,-1.0,-1.0,-1.0,-1.0,11.491,1.55758,1710,3143609 +191,delete,1.927,-1.0,-1.0,-1.0,-1.0,10.434,1.55701,1710,3141038 +192,search,2753.56,-1.0,-1.0,-1.0,-1.0,11.622,1.55701,1710,3141038 +193,delete,46.636,-1.0,-1.0,-1.0,-1.0,11.848,1.53278,1710,3081734 +194,search,2713.76,-1.0,-1.0,-1.0,-1.0,11.54,1.53278,1710,3081734 +195,delete,24.76,-1.0,-1.0,-1.0,-1.0,20.799,1.51748,1708,3043966 +196,search,2703.21,-1.0,-1.0,-1.0,-1.0,11.547,1.51748,1708,3043966 +197,delete,24.537,-1.0,-1.0,-1.0,-1.0,27.174,1.50337,1707,3008145 +198,search,2700.51,-1.0,-1.0,-1.0,-1.0,11.546,1.50337,1707,3008145 +199,delete,7.136,-1.0,-1.0,-1.0,-1.0,10.512,1.50019,1707,2999384 +200,search,2696.2,-1.0,-1.0,-1.0,-1.0,11.56,1.50019,1707,2999384 +201,delete,4.344,-1.0,-1.0,-1.0,-1.0,10.422,1.49727,1707,2993528 +202,search,2694.09,-1.0,-1.0,-1.0,-1.0,12.596,1.49727,1707,2993528 +203,delete,16.918,-1.0,-1.0,-1.0,-1.0,10.622,1.49322,1707,2980973 +204,search,2686.89,-1.0,-1.0,-1.0,-1.0,11.379,1.49322,1707,2980973 +205,delete,20.176,-1.0,-1.0,-1.0,-1.0,10.86,1.48257,1707,2960291 +206,search,2678.78,-1.0,-1.0,-1.0,-1.0,11.593,1.48257,1707,2960291 +207,delete,31.28,-1.0,-1.0,-1.0,-1.0,20.921,1.46165,1699,2920620 +208,search,2667.72,-1.0,-1.0,-1.0,-1.0,12.457,1.46165,1699,2920620 +209,delete,21.298,-1.0,-1.0,-1.0,-1.0,17.96,1.45286,1698,2900501 +210,search,2659.79,-1.0,-1.0,-1.0,-1.0,11.38,1.45286,1698,2900501 +211,delete,6.549,-1.0,-1.0,-1.0,-1.0,10.32,1.45001,1698,2891660 +212,search,2664.06,-1.0,-1.0,-1.0,-1.0,11.807,1.45001,1698,2891660 +213,delete,15.984,-1.0,-1.0,-1.0,-1.0,12.477,1.44168,1697,2873257 +214,search,2645.64,-1.0,-1.0,-1.0,-1.0,11.397,1.44168,1697,2873257 +215,delete,234.928,-1.0,-1.0,-1.0,-1.0,253.923,1.2605,1633,2537571 +216,search,2469.56,-1.0,-1.0,-1.0,-1.0,17.888,1.26073,1634,2537571 +217,delete,163.867,-1.0,-1.0,-1.0,-1.0,170.108,1.15096,1591,2308194 +218,search,2354.55,-1.0,-1.0,-1.0,-1.0,15.327,1.15103,1592,2308194 +219,delete,14.836,-1.0,-1.0,-1.0,-1.0,12.583,1.1441,1591,2285820 +220,search,2314.7,-1.0,-1.0,-1.0,-1.0,10.651,1.1441,1591,2285820 +221,delete,137.505,-1.0,-1.0,-1.0,-1.0,153.435,1.03423,1524,2082858 +222,search,2216.86,-1.0,-1.0,-1.0,-1.0,10.276,1.03423,1524,2082858 +223,delete,8.352,-1.0,-1.0,-1.0,-1.0,10.323,1.03088,1523,2071207 +224,search,2198.68,-1.0,-1.0,-1.0,-1.0,9.846,1.03088,1523,2071207 +225,delete,4.547,-1.0,-1.0,-1.0,-1.0,8.801,1.02931,1523,2065400 +226,search,2197.41,-1.0,-1.0,-1.0,-1.0,10.317,1.02931,1523,2065400 +227,delete,3.716,-1.0,-1.0,-1.0,-1.0,8.83,1.02778,1523,2062105 +228,search,2204.91,-1.0,-1.0,-1.0,-1.0,10.003,1.02778,1523,2062105 +229,delete,16.042,-1.0,-1.0,-1.0,-1.0,13.738,1.02037,1521,2039610 +230,search,2188.07,-1.0,-1.0,-1.0,-1.0,10.094,1.02037,1521,2039610 +231,delete,9.052,-1.0,-1.0,-1.0,-1.0,13.067,1.01385,1520,2027795 +232,search,2175.88,-1.0,-1.0,-1.0,-1.0,10.181,1.01385,1520,2027795 +233,delete,5.711,-1.0,-1.0,-1.0,-1.0,8.804,1.01131,1520,2022859 +234,search,2202.35,-1.0,-1.0,-1.0,-1.0,9.933,1.01131,1520,2022859 +235,delete,6.29,-1.0,-1.0,-1.0,-1.0,10.351,1.00832,1517,2016264 +236,search,2176.95,-1.0,-1.0,-1.0,-1.0,10.041,1.00832,1517,2016264 +237,delete,169.665,-1.0,-1.0,-1.0,-1.0,175.039,0.885904,1464,1782866 +238,search,2063.08,-1.0,-1.0,-1.0,-1.0,9.655,0.885904,1464,1782866 +239,delete,15.913,-1.0,-1.0,-1.0,-1.0,19.137,0.875419,1460,1758931 +240,search,2068.19,-1.0,-1.0,-1.0,-1.0,9.27,0.875419,1460,1758931 +241,delete,5.178,-1.0,-1.0,-1.0,-1.0,13.209,0.872546,1459,1751275 +242,search,2042.53,-1.0,-1.0,-1.0,-1.0,9.336,0.872546,1459,1751275 +243,delete,11.615,-1.0,-1.0,-1.0,-1.0,10.146,0.867792,1458,1733264 +244,search,2040.7,-1.0,-1.0,-1.0,-1.0,9.356,0.867792,1458,1733264 +245,delete,7.609,-1.0,-1.0,-1.0,-1.0,8.068,0.864776,1458,1722658 +246,search,2033.25,-1.0,-1.0,-1.0,-1.0,9.262,0.864776,1458,1722658 +247,delete,2.571,-1.0,-1.0,-1.0,-1.0,8.421,0.864104,1458,1719601 +248,search,2025.81,-1.0,-1.0,-1.0,-1.0,9.3,0.864104,1458,1719601 +249,delete,7.747,-1.0,-1.0,-1.0,-1.0,8.285,0.858977,1458,1711648 +250,search,2030.27,-1.0,-1.0,-1.0,-1.0,9.239,0.858977,1458,1711648 +251,delete,175.394,-1.0,-1.0,-1.0,-1.0,208.529,0.722563,1362,1470624 +252,search,1882.06,-1.0,-1.0,-1.0,-1.0,8.381,0.722563,1362,1470624 +253,delete,19.23,-1.0,-1.0,-1.0,-1.0,13.577,0.711876,1359,1442070 +254,search,1875.11,-1.0,-1.0,-1.0,-1.0,8.451,0.711876,1359,1442070 +255,delete,25.534,-1.0,-1.0,-1.0,-1.0,19.08,0.696489,1352,1405549 +256,search,1851.51,-1.0,-1.0,-1.0,-1.0,8.404,0.696489,1352,1405549 +257,insert,6.172,-1.0,-1.0,-1.0,-1.0,7.262,0.698638,1352,1416288 +258,search,1873.97,-1.0,-1.0,-1.0,-1.0,8.181,0.698638,1352,1416288 +259,insert,16.71,-1.0,-1.0,-1.0,-1.0,8.103,0.705291,1352,1443010 +260,search,1861.02,-1.0,-1.0,-1.0,-1.0,8.381,0.705291,1352,1443010 +261,insert,1.529,-1.0,-1.0,-1.0,-1.0,7.15,0.705618,1352,1447529 +262,search,1869.42,-1.0,-1.0,-1.0,-1.0,8.398,0.705618,1352,1447529 +263,insert,77.642,-1.0,-1.0,-1.0,-1.0,55.048,0.745655,1355,1569110 +264,search,1956.71,-1.0,-1.0,-1.0,-1.0,46.841,0.745655,1358,1569110 +265,insert,37.059,-1.0,-1.0,-1.0,-1.0,8.516,0.765288,1358,1636119 +266,search,1931.49,-1.0,-1.0,-1.0,-1.0,40.358,0.765296,1362,1636119 +267,insert,16.67,-1.0,-1.0,-1.0,-1.0,15.429,0.775432,1363,1665152 +268,search,1949.46,-1.0,-1.0,-1.0,-1.0,20.124,0.775433,1365,1665152 +269,insert,162.82,-1.0,-1.0,-1.0,-1.0,80.77,0.874826,1373,1916952 +270,search,2026.95,-1.0,-1.0,-1.0,-1.0,46.976,0.874825,1378,1916952 +271,insert,2.366,-1.0,-1.0,-1.0,-1.0,8.743,0.875937,1378,1920898 +272,search,2025.99,-1.0,-1.0,-1.0,-1.0,16.352,0.875938,1379,1920898 +273,insert,13.034,-1.0,-1.0,-1.0,-1.0,12.203,0.883856,1380,1942757 +274,search,2024.19,-1.0,-1.0,-1.0,-1.0,8.515,0.883856,1380,1942757 +275,insert,262.114,-1.0,-1.0,-1.0,-1.0,135.725,1.04525,1402,2328372 +276,search,2197,-1.0,-1.0,-1.0,-1.0,46.015,1.04533,1408,2328372 +277,insert,21.233,-1.0,-1.0,-1.0,-1.0,8.94,1.05748,1408,2363257 +278,search,2174.51,-1.0,-1.0,-1.0,-1.0,24.969,1.05748,1411,2363257 +279,insert,16.877,-1.0,-1.0,-1.0,-1.0,9.01,1.06826,1411,2388933 +280,search,2194.97,-1.0,-1.0,-1.0,-1.0,8.709,1.06826,1411,2388933 +281,insert,162.215,-1.0,-1.0,-1.0,-1.0,114.861,1.19873,1428,2684315 +282,search,2282.39,-1.0,-1.0,-1.0,-1.0,33.411,1.19879,1432,2684315 +283,insert,278.25,-1.0,-1.0,-1.0,-1.0,202.744,1.3857,1465,3109157 +284,search,2451.51,-1.0,-1.0,-1.0,-1.0,77.717,1.3864,1479,3109157 +285,insert,8.085,-1.0,-1.0,-1.0,-1.0,18.406,1.39147,1481,3122751 +286,search,2472.19,-1.0,-1.0,-1.0,-1.0,20.049,1.39147,1483,3122751 +287,insert,22.28,-1.0,-1.0,-1.0,-1.0,14.979,1.40676,1484,3163679 +288,search,2487.14,-1.0,-1.0,-1.0,-1.0,10.569,1.40676,1484,3163679 +289,insert,214.902,-1.0,-1.0,-1.0,-1.0,149.443,1.54322,1510,3472031 +290,search,2606.7,-1.0,-1.0,-1.0,-1.0,39.771,1.54321,1516,3472031 +291,insert,16.773,-1.0,-1.0,-1.0,-1.0,10.505,1.55445,1516,3495577 +292,search,2613.64,-1.0,-1.0,-1.0,-1.0,17.208,1.55445,1517,3495577 +293,insert,11.123,-1.0,-1.0,-1.0,-1.0,20.629,1.56351,1519,3515193 +294,search,2621.7,-1.0,-1.0,-1.0,-1.0,9.976,1.56351,1519,3515193 +295,insert,129.494,-1.0,-1.0,-1.0,-1.0,104.302,1.65673,1538,3723063 +296,search,2713.71,-1.0,-1.0,-1.0,-1.0,23.993,1.65695,1540,3723063 +297,insert,2.703,-1.0,-1.0,-1.0,-1.0,9.898,1.6586,1540,3727399 +298,search,2719.7,-1.0,-1.0,-1.0,-1.0,20.666,1.65885,1542,3727399 +299,insert,42.077,-1.0,-1.0,-1.0,-1.0,27.84,1.68336,1548,3788002 +300,search,2762.34,-1.0,-1.0,-1.0,-1.0,10.569,1.68336,1548,3788002 +301,insert,358.042,-1.0,-1.0,-1.0,-1.0,408.549,1.94938,1643,4370866 +302,search,3073.8,-1.0,-1.0,-1.0,-1.0,51.579,1.94972,1655,4370866 +303,insert,25.306,-1.0,-1.0,-1.0,-1.0,39.246,1.9714,1660,4420306 +304,search,3119.12,-1.0,-1.0,-1.0,-1.0,10.985,1.9714,1660,4420306 +305,insert,192.035,-1.0,-1.0,-1.0,-1.0,284.497,2.13875,1697,4789669 +306,search,3278.57,-1.0,-1.0,-1.0,-1.0,125.783,2.1392,1713,4789669 +307,insert,15.816,-1.0,-1.0,-1.0,-1.0,22.209,2.14817,1717,4815550 +308,search,3236.61,-1.0,-1.0,-1.0,-1.0,65.099,2.14818,1725,4815550 +309,insert,5.631,-1.0,-1.0,-1.0,-1.0,10.94,2.15176,1725,4823345 +310,search,3263.86,-1.0,-1.0,-1.0,-1.0,39.658,2.15183,1730,4823345 +311,insert,9.452,-1.0,-1.0,-1.0,-1.0,11.267,2.15845,1730,4843493 +312,search,3280.3,-1.0,-1.0,-1.0,-1.0,10.912,2.15845,1730,4843493 +313,insert,21.594,-1.0,-1.0,-1.0,-1.0,22.72,2.17574,1732,4885489 +314,search,3295.76,-1.0,-1.0,-1.0,-1.0,17.156,2.17574,1733,4885489 +315,insert,5.199,-1.0,-1.0,-1.0,-1.0,10.123,2.17911,1733,4892335 +316,search,3273.06,-1.0,-1.0,-1.0,-1.0,10.889,2.17911,1733,4892335 +317,insert,24.097,-1.0,-1.0,-1.0,-1.0,36.325,2.1957,1739,4932996 +318,search,3271.71,-1.0,-1.0,-1.0,-1.0,10.953,2.1957,1739,4932996 +319,insert,337.106,-1.0,-1.0,-1.0,-1.0,407.189,2.41284,1810,5430684 +320,search,3552.35,-1.0,-1.0,-1.0,-1.0,101.45,2.41481,1831,5430684 +321,insert,24.305,-1.0,-1.0,-1.0,-1.0,34.286,2.43029,1839,5471239 +322,search,3557.69,-1.0,-1.0,-1.0,-1.0,19.356,2.43032,1841,5471239 +323,insert,62.825,-1.0,-1.0,-1.0,-1.0,83.056,2.47794,1861,5575560 +324,search,3623.09,-1.0,-1.0,-1.0,-1.0,23.498,2.47831,1864,5575560 +325,insert,863.272,-1.0,-1.0,-1.0,-1.0,584.655,2.70857,1935,6069499 +326,search,3942.49,-1.0,-1.0,-1.0,-1.0,177.786,2.70878,1956,6069499 +327,insert,39.318,-1.0,-1.0,-1.0,-1.0,55.366,2.73899,1966,6139647 +328,search,3855.25,-1.0,-1.0,-1.0,-1.0,81.395,2.73962,1974,6139647 +329,insert,5.02,-1.0,-1.0,-1.0,-1.0,12.066,2.74247,1974,6146884 +330,search,3846.98,-1.0,-1.0,-1.0,-1.0,66.56,2.7428,1982,6146884 +331,insert,26.454,-1.0,-1.0,-1.0,-1.0,38.502,2.7624,1988,6188816 +332,search,3863.78,-1.0,-1.0,-1.0,-1.0,32.147,2.7624,1992,6188816 +333,insert,1.815,-1.0,-1.0,-1.0,-1.0,11.841,2.76338,1992,6190810 +334,search,3880.84,-1.0,-1.0,-1.0,-1.0,16.077,2.76346,1993,6190810 +335,insert,28.969,-1.0,-1.0,-1.0,-1.0,43.751,2.7801,2002,6230108 +336,search,3904.89,-1.0,-1.0,-1.0,-1.0,12.216,2.7801,2002,6230108 +337,insert,11.022,-1.0,-1.0,-1.0,-1.0,21.258,2.78768,2004,6249699 +338,search,3903.25,-1.0,-1.0,-1.0,-1.0,11.864,2.78768,2004,6249699 +339,insert,24.388,-1.0,-1.0,-1.0,-1.0,48.714,2.80027,2011,6290226 +340,search,3921.14,-1.0,-1.0,-1.0,-1.0,12.084,2.80027,2011,6290226 +341,insert,3.959,-1.0,-1.0,-1.0,-1.0,17.22,2.80268,2012,6297556 +342,search,3927.9,-1.0,-1.0,-1.0,-1.0,12.116,2.80268,2012,6297556 +343,insert,20.984,-1.0,-1.0,-1.0,-1.0,60.681,2.81805,2023,6330843 +344,search,3972.88,-1.0,-1.0,-1.0,-1.0,31.544,2.81868,2027,6330843 +345,insert,23.245,-1.0,-1.0,-1.0,-1.0,53.132,2.83556,2037,6370265 +346,search,4009.85,-1.0,-1.0,-1.0,-1.0,12.356,2.83556,2037,6370265 +347,insert,333.099,-1.0,-1.0,-1.0,-1.0,556.656,3.04293,2152,6831086 +348,search,4251.84,-1.0,-1.0,-1.0,-1.0,110.347,3.04561,2175,6831086 +349,insert,23.966,-1.0,-1.0,-1.0,-1.0,46.772,3.06228,2182,6876154 +350,search,4266.98,-1.0,-1.0,-1.0,-1.0,25.325,3.06242,2184,6876154 +351,insert,268.274,-1.0,-1.0,-1.0,-1.0,398.521,3.24288,2250,7288266 +352,search,4488.62,-1.0,-1.0,-1.0,-1.0,133.437,3.24398,2269,7288266 +353,insert,31.691,-1.0,-1.0,-1.0,-1.0,41.792,3.26303,2276,7333132 +354,search,4507.2,-1.0,-1.0,-1.0,-1.0,55.665,3.26312,2281,7333132 +355,insert,235.231,-1.0,-1.0,-1.0,-1.0,355.972,3.42551,2346,7696838 +356,search,4702.29,-1.0,-1.0,-1.0,-1.0,81.558,3.42605,2358,7696838 +357,insert,12.996,-1.0,-1.0,-1.0,-1.0,31.546,3.4332,2362,7714498 +358,search,4663.49,-1.0,-1.0,-1.0,-1.0,25.381,3.43343,2365,7714498 +359,insert,6.751,-1.0,-1.0,-1.0,-1.0,13.313,3.4372,2366,7725755 +360,search,4637.73,-1.0,-1.0,-1.0,-1.0,10.396,3.4372,2366,7725755 +361,insert,35.238,-1.0,-1.0,-1.0,-1.0,66.819,3.4615,2378,7789312 +362,search,4681.97,-1.0,-1.0,-1.0,-1.0,16.436,3.4615,2379,7789312 +363,insert,12.06,-1.0,-1.0,-1.0,-1.0,8.879,3.46494,2379,7803163 +364,search,4707.18,-1.0,-1.0,-1.0,-1.0,9.766,3.46494,2379,7803163 +365,insert,33.994,-1.0,-1.0,-1.0,-1.0,79.459,3.49103,2394,7863722 +366,search,4728.76,-1.0,-1.0,-1.0,-1.0,19.351,3.4913,2396,7863722 +367,insert,17.769,-1.0,-1.0,-1.0,-1.0,67.582,3.50443,2411,7895271 +368,search,4740.43,-1.0,-1.0,-1.0,-1.0,17.604,3.50485,2412,7895271 +369,insert,40.613,-1.0,-1.0,-1.0,-1.0,67.433,3.53265,2425,7961194 +370,search,4744.27,-1.0,-1.0,-1.0,-1.0,9.996,3.53265,2425,7961194 +371,insert,7.388,-1.0,-1.0,-1.0,-1.0,9.422,3.53641,2425,7970239 +372,search,4817.37,-1.0,-1.0,-1.0,-1.0,10.248,3.53641,2425,7970239 +373,insert,29.671,-1.0,-1.0,-1.0,-1.0,31.441,3.55303,2431,8010868 +374,search,4820.8,-1.0,-1.0,-1.0,-1.0,20.478,3.5533,2433,8010868 +375,insert,21.623,-1.0,-1.0,-1.0,-1.0,29.017,3.566,2437,8040698 +376,search,4790.53,-1.0,-1.0,-1.0,-1.0,11.017,3.566,2437,8040698 +377,insert,39.879,-1.0,-1.0,-1.0,-1.0,106.348,3.59464,2456,8104748 +378,search,4852.22,-1.0,-1.0,-1.0,-1.0,41.786,3.5953,2461,8104748 +379,insert,3.242,-1.0,-1.0,-1.0,-1.0,20.97,3.59731,2463,8109755 +380,search,4889.9,-1.0,-1.0,-1.0,-1.0,10.75,3.59731,2463,8109755 +381,insert,12.83,-1.0,-1.0,-1.0,-1.0,36.874,3.60633,2468,8130382 +382,search,4859.69,-1.0,-1.0,-1.0,-1.0,10.817,3.60633,2468,8130382 +383,insert,16.081,-1.0,-1.0,-1.0,-1.0,22.915,3.6142,2470,8153290 +384,search,4879.55,-1.0,-1.0,-1.0,-1.0,21.497,3.61436,2472,8153290 +385,delete,8.615,-1.0,-1.0,-1.0,-1.0,13.015,3.61436,2473,8138873 +386,search,4842.39,-1.0,-1.0,-1.0,-1.0,10.845,3.61436,2473,8138873 +387,delete,20.594,-1.0,-1.0,-1.0,-1.0,10.339,3.61371,2473,8115069 +388,search,4915.66,-1.0,-1.0,-1.0,-1.0,11.395,3.61371,2473,8115069 +389,delete,14.269,-1.0,-1.0,-1.0,-1.0,10.284,3.61371,2473,8101157 +390,search,4881.09,-1.0,-1.0,-1.0,-1.0,10.715,3.61371,2473,8101157 +391,delete,73.161,-1.0,-1.0,-1.0,-1.0,117.808,3.58733,2457,8014644 +392,search,4809.25,-1.0,-1.0,-1.0,-1.0,23.385,3.58762,2459,8014644 +393,delete,23.522,-1.0,-1.0,-1.0,-1.0,10.636,3.58717,2459,7978358 +394,search,4784.1,-1.0,-1.0,-1.0,-1.0,10.814,3.58717,2459,7978358 +395,delete,15.869,-1.0,-1.0,-1.0,-1.0,31.178,3.58119,2457,7957094 +396,search,4805.94,-1.0,-1.0,-1.0,-1.0,12.259,3.58119,2457,7957094 +397,delete,85.718,-1.0,-1.0,-1.0,-1.0,120.153,3.54694,2446,7823916 +398,search,4754.46,-1.0,-1.0,-1.0,-1.0,11.222,3.54694,2446,7823916 +399,delete,4.454,-1.0,-1.0,-1.0,-1.0,9.923,3.54666,2446,7818430 +400,search,4774,-1.0,-1.0,-1.0,-1.0,10.704,3.54666,2446,7818430 +401,delete,12.603,-1.0,-1.0,-1.0,-1.0,17.473,3.54315,2444,7800702 +402,search,4739.62,-1.0,-1.0,-1.0,-1.0,11.235,3.54315,2444,7800702 +403,delete,202.975,-1.0,-1.0,-1.0,-1.0,297.078,3.46014,2407,7517858 +404,search,4647.78,-1.0,-1.0,-1.0,-1.0,19.241,3.4602,2408,7517858 +405,delete,36.138,-1.0,-1.0,-1.0,-1.0,11.585,3.45835,2408,7451637 +406,search,4632.25,-1.0,-1.0,-1.0,-1.0,11.027,3.45835,2408,7451637 +407,delete,61.564,-1.0,-1.0,-1.0,-1.0,49.144,3.43488,2403,7360417 +408,search,4561.29,-1.0,-1.0,-1.0,-1.0,26.815,3.43538,2405,7360417 +409,delete,138.674,-1.0,-1.0,-1.0,-1.0,280.706,3.33823,2369,7131620 +410,search,4479.13,-1.0,-1.0,-1.0,-1.0,27.731,3.33917,2372,7131620 +411,delete,166.955,-1.0,-1.0,-1.0,-1.0,198.014,3.26451,2342,6867617 +412,search,4349.54,-1.0,-1.0,-1.0,-1.0,24.475,3.26486,2343,6867617 +413,delete,10.793,-1.0,-1.0,-1.0,-1.0,15.434,3.26308,2343,6850098 +414,search,4378.94,-1.0,-1.0,-1.0,-1.0,16.926,3.26308,2343,6850098 +415,delete,46.417,-1.0,-1.0,-1.0,-1.0,36.262,3.24515,2341,6782921 +416,search,4366.91,-1.0,-1.0,-1.0,-1.0,16.932,3.24515,2341,6782921 +417,delete,151.123,-1.0,-1.0,-1.0,-1.0,157.588,3.18425,2323,6562039 +418,search,4282.43,-1.0,-1.0,-1.0,-1.0,16.47,3.18425,2323,6562039 +419,delete,17.337,-1.0,-1.0,-1.0,-1.0,15.648,3.17971,2323,6536285 +420,search,4244.03,-1.0,-1.0,-1.0,-1.0,16.58,3.17971,2323,6536285 +421,delete,13.583,-1.0,-1.0,-1.0,-1.0,45.279,3.1705,2320,6510820 +422,search,4255.37,-1.0,-1.0,-1.0,-1.0,16.622,3.1705,2320,6510820 +423,delete,117.737,-1.0,-1.0,-1.0,-1.0,181.173,3.09797,2285,6334168 +424,search,4132.42,-1.0,-1.0,-1.0,-1.0,28.523,3.09827,2286,6334168 +425,delete,18.587,-1.0,-1.0,-1.0,-1.0,15.511,3.09497,2286,6316443 +426,search,4142.85,-1.0,-1.0,-1.0,-1.0,16.654,3.09497,2286,6316443 +427,delete,48.493,-1.0,-1.0,-1.0,-1.0,16.142,3.08022,2286,6266345 +428,search,4123.38,-1.0,-1.0,-1.0,-1.0,16.181,3.08022,2286,6266345 +429,delete,353.111,-1.0,-1.0,-1.0,-1.0,233.919,2.89947,2244,5883847 +430,search,3904.11,-1.0,-1.0,-1.0,-1.0,37.192,2.89983,2246,5883847 +431,delete,60.154,-1.0,-1.0,-1.0,-1.0,90.911,2.86483,2232,5801380 +432,search,3871.97,-1.0,-1.0,-1.0,-1.0,16.317,2.86483,2232,5801380 +433,delete,148.107,-1.0,-1.0,-1.0,-1.0,205.889,2.77348,2196,5607567 +434,search,3796.18,-1.0,-1.0,-1.0,-1.0,17.022,2.77348,2196,5607567 +435,delete,90.436,-1.0,-1.0,-1.0,-1.0,38.378,2.73324,2193,5512176 +436,search,3759.81,-1.0,-1.0,-1.0,-1.0,29.314,2.73323,2194,5512176 +437,delete,9.304,-1.0,-1.0,-1.0,-1.0,27.705,2.72599,2193,5501141 +438,search,3748.94,-1.0,-1.0,-1.0,-1.0,28.71,2.72599,2194,5501141 +439,delete,76.101,-1.0,-1.0,-1.0,-1.0,190.164,2.66289,2172,5369822 +440,search,3715.37,-1.0,-1.0,-1.0,-1.0,29.97,2.66339,2174,5369822 +441,delete,23.145,-1.0,-1.0,-1.0,-1.0,15.105,2.65407,2174,5338985 +442,search,3709.12,-1.0,-1.0,-1.0,-1.0,15.691,2.65407,2174,5338985 +443,delete,25.038,-1.0,-1.0,-1.0,-1.0,63.236,2.63804,2166,5307279 +444,search,3672.1,-1.0,-1.0,-1.0,-1.0,15.58,2.63804,2166,5307279 +445,delete,33.27,-1.0,-1.0,-1.0,-1.0,23.192,2.62103,2165,5268382 +446,search,3676.29,-1.0,-1.0,-1.0,-1.0,15.443,2.62103,2165,5268382 +447,delete,286.366,-1.0,-1.0,-1.0,-1.0,232.178,2.4498,2102,4922787 +448,search,3512.22,-1.0,-1.0,-1.0,-1.0,14.807,2.4498,2102,4922787 +449,delete,26.749,-1.0,-1.0,-1.0,-1.0,14.369,2.43787,2102,4887227 +450,search,3484.79,-1.0,-1.0,-1.0,-1.0,14.885,2.43787,2102,4887227 +451,delete,74.404,-1.0,-1.0,-1.0,-1.0,83.009,2.39077,2089,4795082 +452,search,3478.98,-1.0,-1.0,-1.0,-1.0,14.594,2.39077,2089,4795082 +453,delete,229.473,-1.0,-1.0,-1.0,-1.0,475.018,2.2334,2027,4500175 +454,search,3325.89,-1.0,-1.0,-1.0,-1.0,31.699,2.23395,2030,4500175 +455,delete,25.816,-1.0,-1.0,-1.0,-1.0,14.072,2.22376,2030,4462648 +456,search,3325.29,-1.0,-1.0,-1.0,-1.0,22.603,2.22415,2031,4462648 +457,delete,5.793,-1.0,-1.0,-1.0,-1.0,13.44,2.22143,2031,4456761 +458,search,3336.67,-1.0,-1.0,-1.0,-1.0,13.95,2.22143,2031,4456761 +459,delete,33.797,-1.0,-1.0,-1.0,-1.0,36.376,2.20087,2026,4419992 +460,search,3313.29,-1.0,-1.0,-1.0,-1.0,14.127,2.20087,2026,4419992 +461,delete,4.072,-1.0,-1.0,-1.0,-1.0,12.741,2.20011,2026,4415725 +462,search,3295.29,-1.0,-1.0,-1.0,-1.0,13.964,2.20011,2026,4415725 +463,delete,37.747,-1.0,-1.0,-1.0,-1.0,24.093,2.17708,2019,4370609 +464,search,3242.51,-1.0,-1.0,-1.0,-1.0,14.453,2.17708,2019,4370609 +465,delete,19.261,-1.0,-1.0,-1.0,-1.0,28.051,2.16346,2015,4345244 +466,search,3254.2,-1.0,-1.0,-1.0,-1.0,14.162,2.16346,2015,4345244 +467,delete,20.349,-1.0,-1.0,-1.0,-1.0,13.669,2.15541,2014,4319734 +468,search,3264.4,-1.0,-1.0,-1.0,-1.0,14.705,2.15541,2014,4319734 +469,delete,22.349,-1.0,-1.0,-1.0,-1.0,30.576,2.14539,2010,4298361 +470,search,3254.43,-1.0,-1.0,-1.0,-1.0,14.892,2.14539,2010,4298361 +471,delete,113.121,-1.0,-1.0,-1.0,-1.0,100.45,2.08636,1991,4188315 +472,search,3193.12,-1.0,-1.0,-1.0,-1.0,13.603,2.08636,1991,4188315 +473,delete,91.253,-1.0,-1.0,-1.0,-1.0,58.189,2.04011,1984,4074567 +474,search,3163.58,-1.0,-1.0,-1.0,-1.0,23.449,2.0404,1985,4074567 +475,delete,301.445,-1.0,-1.0,-1.0,-1.0,365.835,1.82354,1907,3691698 +476,search,2957.64,-1.0,-1.0,-1.0,-1.0,55.545,1.82393,1911,3691698 +477,delete,36.693,-1.0,-1.0,-1.0,-1.0,54.209,1.80494,1906,3642619 +478,search,2903.54,-1.0,-1.0,-1.0,-1.0,14.088,1.80494,1906,3642619 +479,delete,163.541,-1.0,-1.0,-1.0,-1.0,140.235,1.70777,1871,3421368 +480,search,2858.19,-1.0,-1.0,-1.0,-1.0,13.171,1.70777,1871,3421368 +481,delete,35.791,-1.0,-1.0,-1.0,-1.0,40.887,1.6875,1865,3378034 +482,search,2847.87,-1.0,-1.0,-1.0,-1.0,13.245,1.6875,1865,3378034 +483,delete,203.607,-1.0,-1.0,-1.0,-1.0,286.588,1.53897,1801,3115682 +484,search,2699.2,-1.0,-1.0,-1.0,-1.0,12.537,1.53897,1801,3115682 +485,delete,18.61,-1.0,-1.0,-1.0,-1.0,11.105,1.53471,1801,3094629 +486,search,2641.95,-1.0,-1.0,-1.0,-1.0,12.709,1.53471,1801,3094629 +487,delete,8.447,-1.0,-1.0,-1.0,-1.0,11.069,1.53283,1801,3086025 +488,search,2686.18,-1.0,-1.0,-1.0,-1.0,12.288,1.53283,1801,3086025 +489,delete,27.289,-1.0,-1.0,-1.0,-1.0,11.495,1.51833,1801,3052105 +490,search,2687.28,-1.0,-1.0,-1.0,-1.0,12.589,1.51833,1801,3052105 +491,delete,14.025,-1.0,-1.0,-1.0,-1.0,13.204,1.51221,1800,3038974 +492,search,2682.11,-1.0,-1.0,-1.0,-1.0,12.757,1.51221,1800,3038974 +493,delete,109.296,-1.0,-1.0,-1.0,-1.0,93.872,1.44793,1780,2911063 +494,search,2642.79,-1.0,-1.0,-1.0,-1.0,12.144,1.44793,1780,2911063 +495,delete,18.082,-1.0,-1.0,-1.0,-1.0,21.448,1.43784,1777,2888785 +496,search,2609.1,-1.0,-1.0,-1.0,-1.0,12.456,1.43784,1777,2888785 +497,delete,45.603,-1.0,-1.0,-1.0,-1.0,18.31,1.41342,1775,2829718 +498,search,2593.17,-1.0,-1.0,-1.0,-1.0,12.441,1.41342,1775,2829718 +499,delete,13.472,-1.0,-1.0,-1.0,-1.0,15.639,1.40662,1774,2816082 +500,search,2585.09,-1.0,-1.0,-1.0,-1.0,12.047,1.40662,1774,2816082 +501,delete,20.504,-1.0,-1.0,-1.0,-1.0,18.452,1.39537,1772,2790880 +502,search,2569.6,-1.0,-1.0,-1.0,-1.0,12.304,1.39537,1772,2790880 +503,delete,13.608,-1.0,-1.0,-1.0,-1.0,10.89,1.38973,1772,2774459 +504,search,2565.5,-1.0,-1.0,-1.0,-1.0,12.233,1.38973,1772,2774459 +505,delete,44.24,-1.0,-1.0,-1.0,-1.0,57.993,1.354,1759,2714683 +506,search,2547.5,-1.0,-1.0,-1.0,-1.0,11.88,1.354,1759,2714683 +507,delete,30.107,-1.0,-1.0,-1.0,-1.0,19.507,1.34295,1757,2680986 +508,search,2536.35,-1.0,-1.0,-1.0,-1.0,12.188,1.34295,1757,2680986 +509,delete,15.944,-1.0,-1.0,-1.0,-1.0,10.794,1.33628,1757,2662966 +510,search,2518.01,-1.0,-1.0,-1.0,-1.0,11.968,1.33628,1757,2662966 +511,delete,18.2,-1.0,-1.0,-1.0,-1.0,17.894,1.32637,1753,2642855 +512,search,2519.3,-1.0,-1.0,-1.0,-1.0,12.239,1.32637,1753,2642855 +513,insert,192.021,-1.0,-1.0,-1.0,-1.0,46.234,1.40705,1757,2906838 +514,search,2576.74,-1.0,-1.0,-1.0,-1.0,11.906,1.40705,1757,2906838 +515,insert,3.363,-1.0,-1.0,-1.0,-1.0,10.571,1.40763,1757,2913746 +516,search,2593.95,-1.0,-1.0,-1.0,-1.0,12.099,1.40763,1757,2913746 +517,insert,11.362,-1.0,-1.0,-1.0,-1.0,11.011,1.41094,1757,2936862 +518,search,2553.57,-1.0,-1.0,-1.0,-1.0,12.013,1.41094,1757,2936862 +519,insert,61.195,-1.0,-1.0,-1.0,-1.0,52.449,1.43576,1762,3009732 +520,search,2648.83,-1.0,-1.0,-1.0,-1.0,32.462,1.43576,1765,3009732 +521,insert,8.125,-1.0,-1.0,-1.0,-1.0,11.922,1.43872,1765,3025906 +522,search,2618.57,-1.0,-1.0,-1.0,-1.0,12.179,1.43872,1765,3025906 +523,insert,23.948,-1.0,-1.0,-1.0,-1.0,28.266,1.45084,1767,3061899 +524,search,2618.31,-1.0,-1.0,-1.0,-1.0,12.11,1.45084,1767,3061899 +525,insert,24.664,-1.0,-1.0,-1.0,-1.0,11.67,1.46028,1767,3101209 +526,search,2641.95,-1.0,-1.0,-1.0,-1.0,12.116,1.46028,1767,3101209 +527,insert,308.555,-1.0,-1.0,-1.0,-1.0,132.659,1.61253,1786,3522334 +528,search,2805.99,-1.0,-1.0,-1.0,-1.0,51.368,1.61253,1789,3522334 +529,insert,204.583,-1.0,-1.0,-1.0,-1.0,154.253,1.71662,1795,3797294 +530,search,3081,-1.0,-1.0,-1.0,-1.0,99.615,1.71662,1800,3797294 +531,insert,51.314,-1.0,-1.0,-1.0,-1.0,12.694,1.7354,1800,3853781 +532,search,3019.97,-1.0,-1.0,-1.0,-1.0,69.104,1.7354,1803,3853781 +533,insert,15.262,-1.0,-1.0,-1.0,-1.0,12.941,1.742,1803,3873352 +534,search,2982.57,-1.0,-1.0,-1.0,-1.0,68.548,1.742,1807,3873352 +535,insert,17.955,-1.0,-1.0,-1.0,-1.0,13.103,1.74945,1807,3893308 +536,search,2981.21,-1.0,-1.0,-1.0,-1.0,62.268,1.74945,1814,3893308 +537,insert,7.379,-1.0,-1.0,-1.0,-1.0,22.383,1.75355,1815,3901271 +538,search,2971.89,-1.0,-1.0,-1.0,-1.0,54.606,1.75355,1823,3901271 +539,insert,19.328,-1.0,-1.0,-1.0,-1.0,19.936,1.76154,1824,3925164 +540,search,2950.68,-1.0,-1.0,-1.0,-1.0,20.101,1.76169,1825,3925164 +541,insert,318.042,-1.0,-1.0,-1.0,-1.0,188.915,1.93219,1857,4320915 +542,search,3135.45,-1.0,-1.0,-1.0,-1.0,36.054,1.93219,1861,4320915 +543,insert,31.104,-1.0,-1.0,-1.0,-1.0,13.462,1.94706,1861,4360814 +544,search,3121.53,-1.0,-1.0,-1.0,-1.0,13.913,1.94706,1861,4360814 +545,insert,7.757,-1.0,-1.0,-1.0,-1.0,12.207,1.95022,1861,4370220 +546,search,3170.62,-1.0,-1.0,-1.0,-1.0,13.801,1.95022,1861,4370220 +547,insert,109.543,-1.0,-1.0,-1.0,-1.0,41.517,2.00816,1868,4510675 +548,search,3204.47,-1.0,-1.0,-1.0,-1.0,17.817,2.00816,1869,4510675 +549,insert,156.394,-1.0,-1.0,-1.0,-1.0,144.727,2.1117,1879,4744845 +550,search,3352.62,-1.0,-1.0,-1.0,-1.0,48.312,2.11205,1884,4744845 +551,insert,20.12,-1.0,-1.0,-1.0,-1.0,28.381,2.12418,1886,4771433 +552,search,3340.07,-1.0,-1.0,-1.0,-1.0,25.449,2.12418,1887,4771433 +553,insert,9.022,-1.0,-1.0,-1.0,-1.0,13.255,2.12916,1887,4782909 +554,search,3335.54,-1.0,-1.0,-1.0,-1.0,20.021,2.12921,1888,4782909 +555,insert,306.184,-1.0,-1.0,-1.0,-1.0,114.476,2.30188,1911,5180322 +556,search,3455.91,-1.0,-1.0,-1.0,-1.0,23.898,2.30228,1912,5180322 +557,insert,19.689,-1.0,-1.0,-1.0,-1.0,22.855,2.31295,1914,5203220 +558,search,3469.77,-1.0,-1.0,-1.0,-1.0,14.607,2.31295,1914,5203220 +559,insert,4.39,-1.0,-1.0,-1.0,-1.0,13.014,2.31511,1914,5210154 +560,search,3462.99,-1.0,-1.0,-1.0,-1.0,14.464,2.31511,1914,5210154 +561,insert,3.739,-1.0,-1.0,-1.0,-1.0,12.757,2.31665,1914,5215426 +562,search,3519.24,-1.0,-1.0,-1.0,-1.0,14.498,2.31665,1914,5215426 +563,insert,30.133,-1.0,-1.0,-1.0,-1.0,18.639,2.33201,1915,5252726 +564,search,3537.68,-1.0,-1.0,-1.0,-1.0,14.581,2.33201,1915,5252726 +565,insert,152.604,-1.0,-1.0,-1.0,-1.0,101.67,2.41641,1927,5447274 +566,search,3618.86,-1.0,-1.0,-1.0,-1.0,30.046,2.41672,1929,5447274 +567,insert,11.51,-1.0,-1.0,-1.0,-1.0,20.602,2.42334,1930,5463135 +568,search,3631.17,-1.0,-1.0,-1.0,-1.0,20.73,2.42359,1931,5463135 +569,insert,9.968,-1.0,-1.0,-1.0,-1.0,13.68,2.42949,1931,5478168 +570,search,3615.02,-1.0,-1.0,-1.0,-1.0,14.629,2.42949,1931,5478168 +571,insert,10.399,-1.0,-1.0,-1.0,-1.0,13.416,2.43617,1931,5492309 +572,search,3620.69,-1.0,-1.0,-1.0,-1.0,22.528,2.43634,1932,5492309 +573,insert,46.904,-1.0,-1.0,-1.0,-1.0,39.579,2.4625,1936,5554599 +574,search,3639.9,-1.0,-1.0,-1.0,-1.0,26.739,2.46278,1937,5554599 +575,insert,44.975,-1.0,-1.0,-1.0,-1.0,42.448,2.48538,1941,5604500 +576,search,3673.52,-1.0,-1.0,-1.0,-1.0,24.3,2.48567,1942,5604500 +577,insert,24.899,-1.0,-1.0,-1.0,-1.0,30.949,2.49933,1945,5638834 +578,search,3687.6,-1.0,-1.0,-1.0,-1.0,15.364,2.49933,1945,5638834 +579,insert,475.853,-1.0,-1.0,-1.0,-1.0,624.515,2.77208,2055,6229778 +580,search,3973.82,-1.0,-1.0,-1.0,-1.0,63.034,2.77253,2063,6229778 +581,insert,18.942,-1.0,-1.0,-1.0,-1.0,32.582,2.78478,2066,6261240 +582,search,3968.2,-1.0,-1.0,-1.0,-1.0,16.116,2.78478,2066,6261240 +583,insert,14.362,-1.0,-1.0,-1.0,-1.0,20.428,2.79299,2067,6283315 +584,search,3973.68,-1.0,-1.0,-1.0,-1.0,24.661,2.79311,2068,6283315 +585,insert,171.819,-1.0,-1.0,-1.0,-1.0,174.16,2.91558,2093,6556101 +586,search,4142.35,-1.0,-1.0,-1.0,-1.0,57.693,2.91607,2101,6556101 +587,insert,25.142,-1.0,-1.0,-1.0,-1.0,28.275,2.92975,2104,6587187 +588,search,4147.31,-1.0,-1.0,-1.0,-1.0,48.321,2.93016,2109,6587187 +589,insert,33.373,-1.0,-1.0,-1.0,-1.0,36.488,2.9495,2113,6631526 +590,search,4182.73,-1.0,-1.0,-1.0,-1.0,22.222,2.9495,2114,6631526 +591,insert,337.227,-1.0,-1.0,-1.0,-1.0,505.443,3.16397,2211,7108942 +592,search,4430.96,-1.0,-1.0,-1.0,-1.0,74.228,3.16497,2223,7108942 +593,insert,111.86,-1.0,-1.0,-1.0,-1.0,156.95,3.24707,2249,7303976 +594,search,4418.46,-1.0,-1.0,-1.0,-1.0,54.053,3.24758,2255,7303976 +595,insert,3.394,-1.0,-1.0,-1.0,-1.0,21.75,3.24926,2256,7309244 +596,search,4444.01,-1.0,-1.0,-1.0,-1.0,25.234,3.24926,2257,7309244 +597,insert,145.575,-1.0,-1.0,-1.0,-1.0,219.326,3.35653,2291,7542477 +598,search,4639.03,-1.0,-1.0,-1.0,-1.0,95.331,3.35689,2301,7542477 +599,insert,69.544,-1.0,-1.0,-1.0,-1.0,156.882,3.40088,2331,7654438 +600,search,4683.89,-1.0,-1.0,-1.0,-1.0,65.353,3.40089,2336,7654438 +601,insert,41.103,-1.0,-1.0,-1.0,-1.0,74.729,3.4279,2349,7717936 +602,search,4693.15,-1.0,-1.0,-1.0,-1.0,38.355,3.4279,2352,7717936 +603,insert,4.027,-1.0,-1.0,-1.0,-1.0,25.485,3.43054,2353,7723521 +604,search,4678.03,-1.0,-1.0,-1.0,-1.0,24.634,3.43059,2354,7723521 +605,insert,29.035,-1.0,-1.0,-1.0,-1.0,52.985,3.44933,2360,7767404 +606,search,4764.25,-1.0,-1.0,-1.0,-1.0,27.647,3.44936,2362,7767404 +607,insert,29.37,-1.0,-1.0,-1.0,-1.0,24.287,3.46899,2364,7826115 +608,search,4788.8,-1.0,-1.0,-1.0,-1.0,18.527,3.469,2365,7826115 +609,insert,127.296,-1.0,-1.0,-1.0,-1.0,255.843,3.55597,2402,8036351 +610,search,4737.42,-1.0,-1.0,-1.0,-1.0,71.877,3.55725,2412,8036351 +611,insert,14.374,-1.0,-1.0,-1.0,-1.0,31.26,3.56626,2416,8060364 +612,search,4821.49,-1.0,-1.0,-1.0,-1.0,17.646,3.56628,2417,8060364 +613,insert,131.028,-1.0,-1.0,-1.0,-1.0,221.105,3.6513,2454,8256083 +614,search,4866.67,-1.0,-1.0,-1.0,-1.0,30.642,3.65173,2457,8256083 +615,insert,242.518,-1.0,-1.0,-1.0,-1.0,412.785,3.82288,2521,8625707 +616,search,5102.47,-1.0,-1.0,-1.0,-1.0,120.483,3.82514,2543,8625707 +617,insert,200.025,-1.0,-1.0,-1.0,-1.0,388.789,3.97299,2603,8949227 +618,search,5259.7,-1.0,-1.0,-1.0,-1.0,85.16,3.97362,2615,8949227 +619,insert,140.263,-1.0,-1.0,-1.0,-1.0,310.316,4.07347,2665,9195551 +620,search,5392.28,-1.0,-1.0,-1.0,-1.0,73.69,4.07449,2678,9195551 +621,insert,22.414,-1.0,-1.0,-1.0,-1.0,68.272,4.08833,2690,9232372 +622,search,5450.47,-1.0,-1.0,-1.0,-1.0,26.665,4.08848,2692,9232372 +623,insert,12.246,-1.0,-1.0,-1.0,-1.0,26.53,4.09659,2695,9253561 +624,search,5385.22,-1.0,-1.0,-1.0,-1.0,24.483,4.09676,2696,9253561 +625,insert,43.258,-1.0,-1.0,-1.0,-1.0,102.886,4.13202,2712,9331230 +626,search,5416.87,-1.0,-1.0,-1.0,-1.0,50.789,4.13271,2718,9331230 +627,insert,30.537,-1.0,-1.0,-1.0,-1.0,50.458,4.14804,2726,9374063 +628,search,5518.11,-1.0,-1.0,-1.0,-1.0,19.811,4.14805,2727,9374063 +629,insert,11.523,-1.0,-1.0,-1.0,-1.0,30.75,4.15613,2730,9387598 +630,search,5555.18,-1.0,-1.0,-1.0,-1.0,26.831,4.15628,2732,9387598 +631,insert,26.035,-1.0,-1.0,-1.0,-1.0,34.204,4.16989,2736,9421724 +632,search,5515.15,-1.0,-1.0,-1.0,-1.0,20.486,4.17011,2737,9421724 +633,insert,33.185,-1.0,-1.0,-1.0,-1.0,51.936,4.18795,2745,9461430 +634,search,5537.33,-1.0,-1.0,-1.0,-1.0,20.319,4.18807,2746,9461430 +635,insert,15.265,-1.0,-1.0,-1.0,-1.0,33.147,4.19555,2750,9479469 +636,search,5603.49,-1.0,-1.0,-1.0,-1.0,28.843,4.1961,2752,9479469 +637,insert,338.029,-1.0,-1.0,-1.0,-1.0,651.019,4.38545,2870,9885997 +638,search,5791.68,-1.0,-1.0,-1.0,-1.0,138.752,4.38873,2894,9885997 +639,insert,256.788,-1.0,-1.0,-1.0,-1.0,551.537,4.56815,3004,10292043 +640,search,5887.28,-1.0,-1.0,-1.0,-1.0,53.134,4.56962,3012,10292043 +641,delete,124.336,-1.0,-1.0,-1.0,-1.0,155.155,4.52977,2997,10096584 +642,search,6017.26,-1.0,-1.0,-1.0,-1.0,28.82,4.53015,2998,10096584 +643,delete,11.123,-1.0,-1.0,-1.0,-1.0,15.301,4.53015,2998,10084840 +644,search,5948.27,-1.0,-1.0,-1.0,-1.0,17.502,4.53015,2998,10084840 +645,delete,17.095,-1.0,-1.0,-1.0,-1.0,15.241,4.53015,2998,10069802 +646,search,6023.01,-1.0,-1.0,-1.0,-1.0,18.046,4.53015,2998,10069802 +647,delete,75.238,-1.0,-1.0,-1.0,-1.0,103.74,4.50943,2988,9990953 +648,search,5905.68,-1.0,-1.0,-1.0,-1.0,17.262,4.50943,2988,9990953 +649,delete,29.937,-1.0,-1.0,-1.0,-1.0,13.632,4.50861,2988,9951625 +650,search,5950.29,-1.0,-1.0,-1.0,-1.0,16.659,4.50861,2988,9951625 +651,delete,19.485,-1.0,-1.0,-1.0,-1.0,15.423,4.50588,2988,9927065 +652,search,5870.95,-1.0,-1.0,-1.0,-1.0,16.941,4.50588,2988,9927065 +653,delete,78.213,-1.0,-1.0,-1.0,-1.0,116.975,4.47679,2974,9831098 +654,search,5886.23,-1.0,-1.0,-1.0,-1.0,16.579,4.47679,2974,9831098 +655,delete,280.008,-1.0,-1.0,-1.0,-1.0,334.756,4.37933,2930,9462172 +656,search,5720.72,-1.0,-1.0,-1.0,-1.0,31.41,4.37983,2933,9462172 +657,delete,169.432,-1.0,-1.0,-1.0,-1.0,184.844,4.31058,2880,9218902 +658,search,5564.1,-1.0,-1.0,-1.0,-1.0,40.484,4.31137,2884,9218902 +659,delete,82.703,-1.0,-1.0,-1.0,-1.0,124.093,4.28052,2868,9106546 +660,search,5515.9,-1.0,-1.0,-1.0,-1.0,20.093,4.2807,2869,9106546 +661,delete,30.855,-1.0,-1.0,-1.0,-1.0,25.794,4.27629,2868,9059776 +662,search,5521.08,-1.0,-1.0,-1.0,-1.0,16.078,4.27629,2868,9059776 +663,delete,55.375,-1.0,-1.0,-1.0,-1.0,62.594,4.25791,2861,8990616 +664,search,5413.12,-1.0,-1.0,-1.0,-1.0,24.444,4.2582,2862,8990616 +665,delete,42.305,-1.0,-1.0,-1.0,-1.0,33.92,4.24657,2860,8937437 +666,search,5507.95,-1.0,-1.0,-1.0,-1.0,16.179,4.24657,2860,8937437 +667,delete,137.406,-1.0,-1.0,-1.0,-1.0,199.19,4.17505,2838,8766390 +668,search,5344.07,-1.0,-1.0,-1.0,-1.0,15.292,4.17505,2838,8766390 +669,delete,156.216,-1.0,-1.0,-1.0,-1.0,264.501,4.0941,2808,8532008 +670,search,5310.38,-1.0,-1.0,-1.0,-1.0,17.26,4.0941,2808,8532008 +671,delete,52.111,-1.0,-1.0,-1.0,-1.0,31.708,4.08399,2805,8489178 +672,search,5297.66,-1.0,-1.0,-1.0,-1.0,16.358,4.08399,2805,8489178 +673,delete,56.902,-1.0,-1.0,-1.0,-1.0,75.295,4.06457,2796,8421866 +674,search,5224.77,-1.0,-1.0,-1.0,-1.0,16.462,4.06457,2796,8421866 +675,delete,112.926,-1.0,-1.0,-1.0,-1.0,47.464,4.03155,2791,8288319 +676,search,5213.4,-1.0,-1.0,-1.0,-1.0,16.407,4.03155,2791,8288319 +677,delete,152.846,-1.0,-1.0,-1.0,-1.0,164.269,3.93949,2774,8072197 +678,search,5109.77,-1.0,-1.0,-1.0,-1.0,22.645,3.93975,2775,8072197 +679,delete,24.852,-1.0,-1.0,-1.0,-1.0,29.601,3.92963,2774,8036947 +680,search,5093.55,-1.0,-1.0,-1.0,-1.0,14.051,3.92963,2774,8036947 +681,delete,7.565,-1.0,-1.0,-1.0,-1.0,13.284,3.92894,2774,8026197 +682,search,5142.02,-1.0,-1.0,-1.0,-1.0,16.459,3.92894,2774,8026197 +683,delete,247.228,-1.0,-1.0,-1.0,-1.0,86.977,3.831,2760,7744229 +684,search,4920.87,-1.0,-1.0,-1.0,-1.0,22.426,3.83113,2761,7744229 +685,delete,193.702,-1.0,-1.0,-1.0,-1.0,64.088,3.73934,2750,7541066 +686,search,4811.5,-1.0,-1.0,-1.0,-1.0,28.592,3.73948,2752,7541066 +687,delete,14.164,-1.0,-1.0,-1.0,-1.0,21.974,3.73437,2751,7522190 +688,search,4891.99,-1.0,-1.0,-1.0,-1.0,15.931,3.73437,2751,7522190 +689,delete,93.917,-1.0,-1.0,-1.0,-1.0,219.319,3.6725,2721,7409400 +690,search,4839.91,-1.0,-1.0,-1.0,-1.0,26.319,3.67289,2723,7409400 +691,delete,32.47,-1.0,-1.0,-1.0,-1.0,14.701,3.65877,2723,7375648 +692,search,4785.93,-1.0,-1.0,-1.0,-1.0,13.623,3.65877,2723,7375648 +693,delete,139.497,-1.0,-1.0,-1.0,-1.0,95.128,3.59016,2710,7222068 +694,search,4734.67,-1.0,-1.0,-1.0,-1.0,14.987,3.59016,2710,7222068 +695,delete,21.026,-1.0,-1.0,-1.0,-1.0,14.041,3.58009,2710,7196331 +696,search,4729.1,-1.0,-1.0,-1.0,-1.0,15.005,3.58009,2710,7196331 +697,delete,21.701,-1.0,-1.0,-1.0,-1.0,20.461,3.56968,2709,7170716 +698,search,4740.25,-1.0,-1.0,-1.0,-1.0,15.166,3.56968,2709,7170716 +699,delete,10.633,-1.0,-1.0,-1.0,-1.0,52.392,3.56057,2707,7155255 +700,search,4734.48,-1.0,-1.0,-1.0,-1.0,14.735,3.56057,2707,7155255 +701,delete,49.63,-1.0,-1.0,-1.0,-1.0,14.368,3.5378,2707,7097733 +702,search,4689.98,-1.0,-1.0,-1.0,-1.0,15.028,3.5378,2707,7097733 +703,delete,162.219,-1.0,-1.0,-1.0,-1.0,182.023,3.44611,2676,6924172 +704,search,4610.96,-1.0,-1.0,-1.0,-1.0,20.555,3.44628,2677,6924172 +705,delete,22.631,-1.0,-1.0,-1.0,-1.0,13.475,3.43737,2677,6896276 +706,search,4630.86,-1.0,-1.0,-1.0,-1.0,15.228,3.43737,2677,6896276 +707,delete,471.594,-1.0,-1.0,-1.0,-1.0,649.479,3.13857,2564,6385507 +708,search,4342.21,-1.0,-1.0,-1.0,-1.0,27.696,3.13877,2565,6385507 +709,delete,153.995,-1.0,-1.0,-1.0,-1.0,385.493,3.04308,2518,6207658 +710,search,4206.71,-1.0,-1.0,-1.0,-1.0,29.422,3.04352,2520,6207658 +711,delete,40.372,-1.0,-1.0,-1.0,-1.0,43.777,3.02675,2517,6162720 +712,search,4203,-1.0,-1.0,-1.0,-1.0,13.82,3.02675,2517,6162720 +713,delete,195.931,-1.0,-1.0,-1.0,-1.0,313.428,2.91293,2482,5927803 +714,search,4124.5,-1.0,-1.0,-1.0,-1.0,30.42,2.91332,2483,5927803 +715,delete,30.532,-1.0,-1.0,-1.0,-1.0,33.403,2.89727,2480,5895666 +716,search,4113.93,-1.0,-1.0,-1.0,-1.0,13.045,2.89727,2480,5895666 +717,delete,23.766,-1.0,-1.0,-1.0,-1.0,12.373,2.89091,2480,5868774 +718,search,4145.62,-1.0,-1.0,-1.0,-1.0,13.835,2.89091,2480,5868774 +719,delete,296.21,-1.0,-1.0,-1.0,-1.0,402.535,2.72206,2399,5533540 +720,search,3934.73,-1.0,-1.0,-1.0,-1.0,19.585,2.72217,2400,5533540 +721,delete,85.88,-1.0,-1.0,-1.0,-1.0,124.647,2.67524,2384,5418387 +722,search,3896.94,-1.0,-1.0,-1.0,-1.0,22.6,2.67527,2385,5418387 +723,delete,18.757,-1.0,-1.0,-1.0,-1.0,16.278,2.66796,2384,5398291 +724,search,3882.48,-1.0,-1.0,-1.0,-1.0,12.614,2.66796,2384,5398291 +725,delete,95.432,-1.0,-1.0,-1.0,-1.0,167.591,2.60731,2366,5273546 +726,search,3851.36,-1.0,-1.0,-1.0,-1.0,19.985,2.60737,2367,5273546 +727,delete,80.054,-1.0,-1.0,-1.0,-1.0,50.767,2.57023,2361,5180937 +728,search,3804.59,-1.0,-1.0,-1.0,-1.0,13.524,2.57023,2361,5180937 +729,delete,89.219,-1.0,-1.0,-1.0,-1.0,122.427,2.52013,2340,5079524 +730,search,3737.01,-1.0,-1.0,-1.0,-1.0,25.448,2.52039,2341,5079524 +731,delete,54.166,-1.0,-1.0,-1.0,-1.0,17.535,2.50078,2341,5019265 +732,search,3724.15,-1.0,-1.0,-1.0,-1.0,28.511,2.50081,2342,5019265 +733,delete,58.591,-1.0,-1.0,-1.0,-1.0,56.351,2.46966,2336,4955565 +734,search,3708.68,-1.0,-1.0,-1.0,-1.0,18.158,2.46966,2336,4955565 +735,delete,133.541,-1.0,-1.0,-1.0,-1.0,360.948,2.383,2296,4776948 +736,search,3631.86,-1.0,-1.0,-1.0,-1.0,26.472,2.38323,2297,4776948 +737,delete,98.905,-1.0,-1.0,-1.0,-1.0,67.209,2.33179,2290,4654026 +738,search,3600.01,-1.0,-1.0,-1.0,-1.0,23.732,2.33179,2291,4654026 +739,delete,54.006,-1.0,-1.0,-1.0,-1.0,78.119,2.29549,2283,4589888 +740,search,3552.5,-1.0,-1.0,-1.0,-1.0,17.236,2.29549,2283,4589888 +741,delete,131.367,-1.0,-1.0,-1.0,-1.0,117.654,2.21861,2267,4430862 +742,search,3514.94,-1.0,-1.0,-1.0,-1.0,17.403,2.21861,2267,4430862 +743,delete,153.739,-1.0,-1.0,-1.0,-1.0,284.712,2.11671,2232,4237049 +744,search,3428.02,-1.0,-1.0,-1.0,-1.0,17.544,2.11671,2232,4237049 +745,delete,202.907,-1.0,-1.0,-1.0,-1.0,361.333,1.98613,2180,4000195 +746,search,3336.28,-1.0,-1.0,-1.0,-1.0,16.378,1.98613,2180,4000195 +747,delete,146.532,-1.0,-1.0,-1.0,-1.0,169.309,1.89652,2149,3803954 +748,search,3251.84,-1.0,-1.0,-1.0,-1.0,31.236,1.89656,2150,3803954 +749,delete,78.3,-1.0,-1.0,-1.0,-1.0,52.723,1.86385,2142,3733214 +750,search,3228.36,-1.0,-1.0,-1.0,-1.0,17.277,1.86385,2142,3733214 +751,delete,25.57,-1.0,-1.0,-1.0,-1.0,28.846,1.85341,2139,3709324 +752,search,3229.38,-1.0,-1.0,-1.0,-1.0,17.233,1.85341,2139,3709324 +753,delete,59.03,-1.0,-1.0,-1.0,-1.0,96.732,1.82235,2126,3649123 +754,search,3219.01,-1.0,-1.0,-1.0,-1.0,17.066,1.82235,2126,3649123 +755,delete,29.871,-1.0,-1.0,-1.0,-1.0,14.633,1.81281,2126,3621475 +756,search,3193.91,-1.0,-1.0,-1.0,-1.0,16.573,1.81281,2126,3621475 +757,delete,32.248,-1.0,-1.0,-1.0,-1.0,34.529,1.79675,2122,3594479 +758,search,3203.44,-1.0,-1.0,-1.0,-1.0,16.78,1.79675,2122,3594479 +759,delete,25.312,-1.0,-1.0,-1.0,-1.0,25.451,1.78742,2120,3569055 +760,search,3186.49,-1.0,-1.0,-1.0,-1.0,16.778,1.78742,2120,3569055 +761,delete,40.318,-1.0,-1.0,-1.0,-1.0,20.451,1.77189,2119,3527896 +762,search,3126.14,-1.0,-1.0,-1.0,-1.0,16.188,1.77189,2119,3527896 +763,delete,22.453,-1.0,-1.0,-1.0,-1.0,26.563,1.76292,2117,3509970 +764,search,3160.73,-1.0,-1.0,-1.0,-1.0,16.614,1.76292,2117,3509970 +765,delete,309.778,-1.0,-1.0,-1.0,-1.0,317.165,1.57872,2024,3187549 +766,search,2977.5,-1.0,-1.0,-1.0,-1.0,15.355,1.57872,2024,3187549 +767,delete,330.403,-1.0,-1.0,-1.0,-1.0,456.703,1.37337,1903,2822906 +768,search,2767.85,-1.0,-1.0,-1.0,-1.0,14.371,1.37337,1903,2822906 +769,insert,7.341,-1.0,-1.0,-1.0,-1.0,12.716,1.37476,1903,2832899 +770,search,2759.64,-1.0,-1.0,-1.0,-1.0,14.186,1.37476,1903,2832899 +771,insert,27.787,-1.0,-1.0,-1.0,-1.0,19.589,1.38408,1904,2863523 +772,search,2758,-1.0,-1.0,-1.0,-1.0,14.329,1.38408,1904,2863523 +773,insert,40.632,-1.0,-1.0,-1.0,-1.0,13.924,1.39786,1904,2925169 +774,search,2772.25,-1.0,-1.0,-1.0,-1.0,14.167,1.39786,1904,2925169 +775,insert,32.929,-1.0,-1.0,-1.0,-1.0,24.025,1.40925,1905,2961356 +776,search,2809.88,-1.0,-1.0,-1.0,-1.0,14.437,1.40925,1905,2961356 +777,insert,24.67,-1.0,-1.0,-1.0,-1.0,13.102,1.41657,1905,2998678 +778,search,2802.93,-1.0,-1.0,-1.0,-1.0,14.459,1.41657,1905,2998678 +779,insert,11.176,-1.0,-1.0,-1.0,-1.0,12.565,1.41959,1905,3011024 +780,search,2804.51,-1.0,-1.0,-1.0,-1.0,14.36,1.41959,1905,3011024 +781,insert,4.955,-1.0,-1.0,-1.0,-1.0,12.462,1.42049,1905,3019515 +782,search,2797.03,-1.0,-1.0,-1.0,-1.0,14.197,1.42049,1905,3019515 +783,insert,37.875,-1.0,-1.0,-1.0,-1.0,13.467,1.43154,1905,3082298 +784,search,2832.87,-1.0,-1.0,-1.0,-1.0,14.064,1.43154,1905,3082298 +785,insert,33.313,-1.0,-1.0,-1.0,-1.0,40.725,1.44583,1908,3122090 +786,search,2818.19,-1.0,-1.0,-1.0,-1.0,36.331,1.44583,1911,3122090 +787,insert,17.105,-1.0,-1.0,-1.0,-1.0,13.783,1.45103,1911,3140294 +788,search,2840.52,-1.0,-1.0,-1.0,-1.0,14.405,1.45103,1911,3140294 +789,insert,5.169,-1.0,-1.0,-1.0,-1.0,12.701,1.4523,1911,3147819 +790,search,2837.12,-1.0,-1.0,-1.0,-1.0,14.409,1.4523,1911,3147819 +791,insert,22.431,-1.0,-1.0,-1.0,-1.0,13.133,1.46005,1911,3180668 +792,search,2860.78,-1.0,-1.0,-1.0,-1.0,14.389,1.46005,1911,3180668 +793,insert,4.059,-1.0,-1.0,-1.0,-1.0,12.404,1.46122,1911,3183235 +794,search,2879.36,-1.0,-1.0,-1.0,-1.0,14.388,1.46122,1911,3183235 +795,insert,45.856,-1.0,-1.0,-1.0,-1.0,23.218,1.47908,1912,3242089 +796,search,2873.67,-1.0,-1.0,-1.0,-1.0,14.567,1.47908,1912,3242089 +797,insert,3.95,-1.0,-1.0,-1.0,-1.0,12.846,1.47989,1912,3247192 +798,search,2900.19,-1.0,-1.0,-1.0,-1.0,14.4,1.47989,1912,3247192 +799,insert,5.295,-1.0,-1.0,-1.0,-1.0,12.784,1.48124,1912,3254626 +800,search,2904.52,-1.0,-1.0,-1.0,-1.0,14.47,1.48124,1912,3254626 +801,insert,14.833,-1.0,-1.0,-1.0,-1.0,12.748,1.48586,1912,3274953 +802,search,2904.12,-1.0,-1.0,-1.0,-1.0,15.741,1.48586,1912,3274953 +803,insert,736.635,-1.0,-1.0,-1.0,-1.0,500.742,1.81052,1978,4032688 +804,search,3244.83,-1.0,-1.0,-1.0,-1.0,152.811,1.81064,2002,4032688 +805,insert,14.074,-1.0,-1.0,-1.0,-1.0,14.496,1.81603,2002,4050220 +806,search,3259.15,-1.0,-1.0,-1.0,-1.0,27.389,1.81603,2004,4050220 +807,insert,14.245,-1.0,-1.0,-1.0,-1.0,14.506,1.82168,2004,4067940 +808,search,3265.32,-1.0,-1.0,-1.0,-1.0,15.927,1.82168,2004,4067940 +809,insert,28.751,-1.0,-1.0,-1.0,-1.0,23.068,1.83277,2005,4099369 +810,search,3278.7,-1.0,-1.0,-1.0,-1.0,15.485,1.83277,2005,4099369 +811,insert,29.022,-1.0,-1.0,-1.0,-1.0,13.877,1.84396,2005,4129509 +812,search,3292.86,-1.0,-1.0,-1.0,-1.0,15.559,1.84396,2005,4129509 +813,insert,47.156,-1.0,-1.0,-1.0,-1.0,14.932,1.86404,2005,4178669 +814,search,3304.33,-1.0,-1.0,-1.0,-1.0,15.488,1.86404,2005,4178669 +815,insert,2.313,-1.0,-1.0,-1.0,-1.0,13.755,1.86482,2005,4180960 +816,search,3297.96,-1.0,-1.0,-1.0,-1.0,15.482,1.86482,2005,4180960 +817,insert,71.695,-1.0,-1.0,-1.0,-1.0,73.243,1.89415,2013,4255359 +818,search,3313.97,-1.0,-1.0,-1.0,-1.0,15.454,1.89415,2013,4255359 +819,insert,19.295,-1.0,-1.0,-1.0,-1.0,13.929,1.90035,2013,4272706 +820,search,3300.26,-1.0,-1.0,-1.0,-1.0,15.694,1.90035,2013,4272706 +821,insert,14.281,-1.0,-1.0,-1.0,-1.0,23.035,1.90726,2014,4287851 +822,search,3324.34,-1.0,-1.0,-1.0,-1.0,22.076,1.90729,2015,4287851 +823,insert,29.444,-1.0,-1.0,-1.0,-1.0,15.065,1.92137,2015,4322788 +824,search,3334.66,-1.0,-1.0,-1.0,-1.0,15.393,1.92137,2015,4322788 +825,insert,70.094,-1.0,-1.0,-1.0,-1.0,21.356,1.95169,2016,4396408 +826,search,3341.14,-1.0,-1.0,-1.0,-1.0,15.47,1.95169,2016,4396408 +827,insert,17.47,-1.0,-1.0,-1.0,-1.0,14.3,1.95955,2016,4415721 +828,search,3343.34,-1.0,-1.0,-1.0,-1.0,15.474,1.95955,2016,4415721 +829,insert,385.982,-1.0,-1.0,-1.0,-1.0,143.465,2.13855,2036,4832079 +830,search,3495.49,-1.0,-1.0,-1.0,-1.0,15.805,2.13855,2036,4832079 +831,insert,31.484,-1.0,-1.0,-1.0,-1.0,22.39,2.1528,2037,4864525 +832,search,3538.89,-1.0,-1.0,-1.0,-1.0,15.488,2.1528,2037,4864525 +833,insert,11.253,-1.0,-1.0,-1.0,-1.0,24.174,2.15663,2039,4874443 +834,search,3543.56,-1.0,-1.0,-1.0,-1.0,15.627,2.15663,2039,4874443 +835,insert,52.528,-1.0,-1.0,-1.0,-1.0,15.479,2.18212,2039,4938267 +836,search,3570.9,-1.0,-1.0,-1.0,-1.0,15.759,2.18212,2039,4938267 +837,insert,24.011,-1.0,-1.0,-1.0,-1.0,22.086,2.1923,2040,4961147 +838,search,3571.79,-1.0,-1.0,-1.0,-1.0,21.506,2.19239,2041,4961147 +839,insert,62.471,-1.0,-1.0,-1.0,-1.0,45.599,2.22327,2046,5033740 +840,search,3596.39,-1.0,-1.0,-1.0,-1.0,20.467,2.22335,2047,5033740 +841,insert,35.289,-1.0,-1.0,-1.0,-1.0,28.626,2.2417,2049,5078736 +842,search,3600.53,-1.0,-1.0,-1.0,-1.0,23.578,2.24178,2050,5078736 +843,insert,361.049,-1.0,-1.0,-1.0,-1.0,191.729,2.41172,2075,5467376 +844,search,3766.97,-1.0,-1.0,-1.0,-1.0,56.587,2.41195,2082,5467376 +845,insert,278.896,-1.0,-1.0,-1.0,-1.0,225.736,2.56845,2119,5815547 +846,search,3918.29,-1.0,-1.0,-1.0,-1.0,59.497,2.56884,2126,5815547 +847,insert,5.395,-1.0,-1.0,-1.0,-1.0,16.385,2.57148,2126,5821782 +848,search,3921.54,-1.0,-1.0,-1.0,-1.0,38.873,2.57158,2130,5821782 +849,insert,2.493,-1.0,-1.0,-1.0,-1.0,16.209,2.57233,2130,5825594 +850,search,3890.32,-1.0,-1.0,-1.0,-1.0,17.94,2.57233,2130,5825594 +851,insert,8.501,-1.0,-1.0,-1.0,-1.0,22.053,2.57607,2131,5834880 +852,search,3925.23,-1.0,-1.0,-1.0,-1.0,26.228,2.57614,2132,5834880 +853,insert,24.906,-1.0,-1.0,-1.0,-1.0,38.625,2.58742,2135,5860274 +854,search,3947.35,-1.0,-1.0,-1.0,-1.0,17.147,2.58742,2135,5860274 +855,insert,6.576,-1.0,-1.0,-1.0,-1.0,15.572,2.5901,2135,5866064 +856,search,3943.31,-1.0,-1.0,-1.0,-1.0,17.461,2.5901,2135,5866064 +857,insert,13.692,-1.0,-1.0,-1.0,-1.0,33.249,2.59613,2138,5884456 +858,search,3962.27,-1.0,-1.0,-1.0,-1.0,17.364,2.59613,2138,5884456 +859,insert,26.927,-1.0,-1.0,-1.0,-1.0,36.18,2.60838,2140,5916786 +860,search,3979.7,-1.0,-1.0,-1.0,-1.0,23.534,2.6086,2141,5916786 +861,insert,9.33,-1.0,-1.0,-1.0,-1.0,16.291,2.61104,2141,5923467 +862,search,3978.34,-1.0,-1.0,-1.0,-1.0,17.71,2.61104,2141,5923467 +863,insert,61.168,-1.0,-1.0,-1.0,-1.0,92.296,2.64545,2155,5997844 +864,search,3982.26,-1.0,-1.0,-1.0,-1.0,17.764,2.64545,2155,5997844 +865,insert,10.42,-1.0,-1.0,-1.0,-1.0,23.241,2.64949,2156,6009561 +866,search,3999.47,-1.0,-1.0,-1.0,-1.0,17.638,2.64949,2156,6009561 +867,insert,45.412,-1.0,-1.0,-1.0,-1.0,46.745,2.67117,2161,6052876 +868,search,4017.22,-1.0,-1.0,-1.0,-1.0,23.838,2.67117,2162,6052876 +869,insert,8.101,-1.0,-1.0,-1.0,-1.0,16.1,2.67471,2162,6059234 +870,search,4017.53,-1.0,-1.0,-1.0,-1.0,17.471,2.67471,2162,6059234 +871,insert,34.635,-1.0,-1.0,-1.0,-1.0,53.859,2.69263,2166,6098225 +872,search,4063.92,-1.0,-1.0,-1.0,-1.0,24.848,2.69275,2167,6098225 +873,insert,34.627,-1.0,-1.0,-1.0,-1.0,40.176,2.71042,2170,6137308 +874,search,4063.08,-1.0,-1.0,-1.0,-1.0,30.513,2.71081,2172,6137308 +875,insert,15.802,-1.0,-1.0,-1.0,-1.0,16.466,2.71695,2172,6154089 +876,search,4061.53,-1.0,-1.0,-1.0,-1.0,17.756,2.71695,2172,6154089 +877,insert,2.655,-1.0,-1.0,-1.0,-1.0,15.987,2.71772,2172,6156061 +878,search,4057.06,-1.0,-1.0,-1.0,-1.0,17.724,2.71772,2172,6156061 +879,insert,251.467,-1.0,-1.0,-1.0,-1.0,260.633,2.84859,2210,6446004 +880,search,4168.79,-1.0,-1.0,-1.0,-1.0,56.45,2.84927,2216,6446004 +881,insert,414.907,-1.0,-1.0,-1.0,-1.0,301.357,3.08195,2267,6969764 +882,search,4352.63,-1.0,-1.0,-1.0,-1.0,97.703,3.08313,2278,6969764 +883,insert,329.906,-1.0,-1.0,-1.0,-1.0,317.612,3.28167,2335,7422501 +884,search,4585.01,-1.0,-1.0,-1.0,-1.0,94.645,3.28267,2348,7422501 +885,insert,7.337,-1.0,-1.0,-1.0,-1.0,29.984,3.28745,2350,7432053 +886,search,4578.56,-1.0,-1.0,-1.0,-1.0,43.655,3.288,2354,7432053 +887,insert,217.588,-1.0,-1.0,-1.0,-1.0,281.088,3.4449,2401,7789886 +888,search,4729.92,-1.0,-1.0,-1.0,-1.0,71.877,3.44557,2410,7789886 +889,insert,288.136,-1.0,-1.0,-1.0,-1.0,498.68,3.63516,2490,8210883 +890,search,4955.14,-1.0,-1.0,-1.0,-1.0,96.843,3.63687,2505,8210883 +891,insert,25.681,-1.0,-1.0,-1.0,-1.0,24.458,3.64619,2507,8240504 +892,search,4960.08,-1.0,-1.0,-1.0,-1.0,14.239,3.64619,2507,8240504 +893,insert,40.868,-1.0,-1.0,-1.0,-1.0,72.547,3.671,2517,8299693 +894,search,4974.43,-1.0,-1.0,-1.0,-1.0,29.236,3.67115,2519,8299693 +895,insert,40.153,-1.0,-1.0,-1.0,-1.0,56.928,3.68918,2527,8349126 +896,search,5023.05,-1.0,-1.0,-1.0,-1.0,16.714,3.68918,2527,8349126 +897,delete,54.34,-1.0,-1.0,-1.0,-1.0,85.592,3.66987,2513,8268842 +898,search,4989.18,-1.0,-1.0,-1.0,-1.0,13.827,3.66987,2513,8268842 +899,delete,12.25,-1.0,-1.0,-1.0,-1.0,11.878,3.66947,2513,8250527 +900,search,4981.15,-1.0,-1.0,-1.0,-1.0,13.801,3.66947,2513,8250527 +901,delete,43.273,-1.0,-1.0,-1.0,-1.0,50.14,3.66015,2507,8185565 +902,search,4995.77,-1.0,-1.0,-1.0,-1.0,13.464,3.66015,2507,8185565 +903,delete,38.985,-1.0,-1.0,-1.0,-1.0,82.11,3.63926,2494,8126915 +904,search,4926.5,-1.0,-1.0,-1.0,-1.0,25.543,3.63944,2496,8126915 +905,delete,17.916,-1.0,-1.0,-1.0,-1.0,12.118,3.63862,2496,8098533 +906,search,4919.55,-1.0,-1.0,-1.0,-1.0,13.523,3.63862,2496,8098533 +907,delete,18.018,-1.0,-1.0,-1.0,-1.0,25.461,3.63339,2495,8074833 +908,search,4908.04,-1.0,-1.0,-1.0,-1.0,13.756,3.63339,2495,8074833 +909,delete,25.992,-1.0,-1.0,-1.0,-1.0,12.167,3.63226,2495,8035274 +910,search,4891.24,-1.0,-1.0,-1.0,-1.0,12.855,3.63226,2495,8035274 +911,delete,51.186,-1.0,-1.0,-1.0,-1.0,22.604,3.62708,2494,7957223 +912,search,4865.19,-1.0,-1.0,-1.0,-1.0,13.215,3.62708,2494,7957223 +913,delete,27.29,-1.0,-1.0,-1.0,-1.0,39.004,3.61696,2489,7917554 +914,search,4851.38,-1.0,-1.0,-1.0,-1.0,13.089,3.61696,2489,7917554 +915,delete,46.602,-1.0,-1.0,-1.0,-1.0,64.025,3.60208,2481,7861503 +916,search,4809.36,-1.0,-1.0,-1.0,-1.0,13.291,3.60208,2481,7861503 +917,delete,11.003,-1.0,-1.0,-1.0,-1.0,11.69,3.60108,2481,7844487 +918,search,4823.35,-1.0,-1.0,-1.0,-1.0,12.952,3.60108,2481,7844487 +919,delete,17.727,-1.0,-1.0,-1.0,-1.0,11.733,3.60098,2481,7814993 +920,search,4783.52,-1.0,-1.0,-1.0,-1.0,14.089,3.60098,2481,7814993 +921,delete,30.15,-1.0,-1.0,-1.0,-1.0,25.403,3.59704,2480,7793855 +922,search,4793.3,-1.0,-1.0,-1.0,-1.0,14.398,3.59704,2480,7793855 +923,delete,52.886,-1.0,-1.0,-1.0,-1.0,29.664,3.58739,2478,7736054 +924,search,4768.24,-1.0,-1.0,-1.0,-1.0,14.525,3.58739,2478,7736054 +925,delete,125.92,-1.0,-1.0,-1.0,-1.0,83.846,3.54062,2458,7587942 +926,search,4683.34,-1.0,-1.0,-1.0,-1.0,13.875,3.54062,2458,7587942 +927,delete,16.695,-1.0,-1.0,-1.0,-1.0,19.134,3.53829,2457,7565670 +928,search,4703.62,-1.0,-1.0,-1.0,-1.0,13.772,3.53829,2457,7565670 +929,delete,32.47,-1.0,-1.0,-1.0,-1.0,12.091,3.53503,2457,7529948 +930,search,4716.79,-1.0,-1.0,-1.0,-1.0,13.378,3.53503,2457,7529948 +931,delete,372.588,-1.0,-1.0,-1.0,-1.0,567.389,3.36339,2375,7016700 +932,search,4410.93,-1.0,-1.0,-1.0,-1.0,30.877,3.36376,2378,7016700 +933,delete,24.322,-1.0,-1.0,-1.0,-1.0,25.577,3.35517,2376,6980979 +934,search,4417.15,-1.0,-1.0,-1.0,-1.0,19.296,3.35538,2377,6980979 +935,delete,16.531,-1.0,-1.0,-1.0,-1.0,57.367,3.3443,2372,6954250 +936,search,4411.37,-1.0,-1.0,-1.0,-1.0,13.03,3.3443,2372,6954250 +937,delete,24.572,-1.0,-1.0,-1.0,-1.0,17.911,3.33598,2371,6924596 +938,search,4419.23,-1.0,-1.0,-1.0,-1.0,12.798,3.33598,2371,6924596 +939,delete,113.835,-1.0,-1.0,-1.0,-1.0,19.43,3.30926,2370,6784831 +940,search,4333.55,-1.0,-1.0,-1.0,-1.0,71.374,3.30987,2371,6784831 +941,delete,30.136,-1.0,-1.0,-1.0,-1.0,12.717,3.30247,2371,6745819 +942,search,4330.67,-1.0,-1.0,-1.0,-1.0,12.732,3.30247,2371,6745819 +943,delete,3.926,-1.0,-1.0,-1.0,-1.0,11.058,3.30147,2371,6740944 +944,search,4366.41,-1.0,-1.0,-1.0,-1.0,12.535,3.30147,2371,6740944 +945,delete,93.736,-1.0,-1.0,-1.0,-1.0,199.539,3.24394,2346,6627202 +946,search,4319.36,-1.0,-1.0,-1.0,-1.0,33.006,3.24433,2348,6627202 +947,delete,18.854,-1.0,-1.0,-1.0,-1.0,19.916,3.23765,2348,6607194 +948,search,4288.22,-1.0,-1.0,-1.0,-1.0,20.621,3.23765,2348,6607194 +949,delete,42.681,-1.0,-1.0,-1.0,-1.0,48.196,3.21805,2343,6551065 +950,search,4250.98,-1.0,-1.0,-1.0,-1.0,20.464,3.21805,2343,6551065 +951,delete,26.793,-1.0,-1.0,-1.0,-1.0,69.606,3.19618,2333,6506798 +952,search,4246.45,-1.0,-1.0,-1.0,-1.0,26.338,3.19622,2334,6506798 +953,delete,32.995,-1.0,-1.0,-1.0,-1.0,19.77,3.18555,2334,6459301 +954,search,4232.84,-1.0,-1.0,-1.0,-1.0,19.86,3.18555,2334,6459301 +955,delete,16.576,-1.0,-1.0,-1.0,-1.0,33.979,3.17548,2331,6440069 +956,search,4235.73,-1.0,-1.0,-1.0,-1.0,20.421,3.17548,2331,6440069 +957,delete,268.669,-1.0,-1.0,-1.0,-1.0,221.029,3.03147,2292,6132470 +958,search,4128.47,-1.0,-1.0,-1.0,-1.0,21.843,3.03147,2292,6132470 +959,delete,56.414,-1.0,-1.0,-1.0,-1.0,34.343,3.01371,2289,6086241 +960,search,4112.55,-1.0,-1.0,-1.0,-1.0,20.916,3.01371,2289,6086241 +961,delete,26.894,-1.0,-1.0,-1.0,-1.0,18.674,3.00781,2289,6064734 +962,search,4082.74,-1.0,-1.0,-1.0,-1.0,20.617,3.00781,2289,6064734 +963,delete,113.33,-1.0,-1.0,-1.0,-1.0,48.603,2.96432,2285,5967543 +964,search,4058.9,-1.0,-1.0,-1.0,-1.0,21.554,2.96432,2285,5967543 +965,delete,67.179,-1.0,-1.0,-1.0,-1.0,55.613,2.93602,2276,5906381 +966,search,4009.15,-1.0,-1.0,-1.0,-1.0,20.161,2.93602,2276,5906381 +967,delete,47,-1.0,-1.0,-1.0,-1.0,40.206,2.91287,2274,5851849 +968,search,3965.34,-1.0,-1.0,-1.0,-1.0,20.018,2.91287,2274,5851849 +969,delete,56.338,-1.0,-1.0,-1.0,-1.0,47.274,2.88004,2268,5783023 +970,search,3975.07,-1.0,-1.0,-1.0,-1.0,20.559,2.88004,2268,5783023 +971,delete,259.243,-1.0,-1.0,-1.0,-1.0,217.078,2.74538,2234,5496517 +972,search,3856.34,-1.0,-1.0,-1.0,-1.0,19.467,2.74538,2234,5496517 +973,delete,226.259,-1.0,-1.0,-1.0,-1.0,181.513,2.61317,2200,5237981 +974,search,3754.19,-1.0,-1.0,-1.0,-1.0,30.489,2.61359,2201,5237981 +975,delete,132.689,-1.0,-1.0,-1.0,-1.0,199.342,2.53579,2150,5099794 +976,search,3657.44,-1.0,-1.0,-1.0,-1.0,18.13,2.53579,2150,5099794 +977,delete,52.254,-1.0,-1.0,-1.0,-1.0,78.576,2.50271,2140,5032210 +978,search,3597.77,-1.0,-1.0,-1.0,-1.0,18.257,2.50271,2140,5032210 +979,delete,11.77,-1.0,-1.0,-1.0,-1.0,16.311,2.4986,2140,5020211 +980,search,3597.63,-1.0,-1.0,-1.0,-1.0,18.157,2.4986,2140,5020211 +981,delete,101.316,-1.0,-1.0,-1.0,-1.0,121.87,2.44055,2120,4902291 +982,search,3574.43,-1.0,-1.0,-1.0,-1.0,17.619,2.44055,2120,4902291 +983,delete,31.714,-1.0,-1.0,-1.0,-1.0,16.322,2.42956,2120,4872577 +984,search,3520.12,-1.0,-1.0,-1.0,-1.0,17.476,2.42956,2120,4872577 +985,delete,34.577,-1.0,-1.0,-1.0,-1.0,16.548,2.41712,2120,4836730 +986,search,3530.39,-1.0,-1.0,-1.0,-1.0,17.445,2.41712,2120,4836730 +987,delete,39.239,-1.0,-1.0,-1.0,-1.0,16.788,2.40173,2120,4797164 +988,search,3523.37,-1.0,-1.0,-1.0,-1.0,17.216,2.40173,2120,4797164 +989,delete,12.688,-1.0,-1.0,-1.0,-1.0,15.714,2.39672,2120,4784789 +990,search,3512.61,-1.0,-1.0,-1.0,-1.0,17.464,2.39672,2120,4784789 +991,delete,61.333,-1.0,-1.0,-1.0,-1.0,137.212,2.36068,2113,4705420 +992,search,3479.59,-1.0,-1.0,-1.0,-1.0,38.694,2.36111,2116,4705420 +993,delete,72.683,-1.0,-1.0,-1.0,-1.0,75.269,2.32074,2107,4621807 +994,search,3426.31,-1.0,-1.0,-1.0,-1.0,16.89,2.32074,2107,4621807 +995,delete,60.223,-1.0,-1.0,-1.0,-1.0,57.913,2.28682,2100,4555849 +996,search,3383.61,-1.0,-1.0,-1.0,-1.0,17.137,2.28682,2100,4555849 +997,delete,24.865,-1.0,-1.0,-1.0,-1.0,27.743,2.27883,2099,4526975 +998,search,3369.92,-1.0,-1.0,-1.0,-1.0,17.163,2.27883,2099,4526975 +999,delete,97.553,-1.0,-1.0,-1.0,-1.0,119.046,2.21803,2079,4408448 +1000,search,3337.43,-1.0,-1.0,-1.0,-1.0,24.001,2.21824,2080,4408448 +1001,delete,97.947,-1.0,-1.0,-1.0,-1.0,100.412,2.16241,2071,4303257 +1002,search,3308.61,-1.0,-1.0,-1.0,-1.0,16.534,2.16241,2071,4303257 +1003,delete,35.279,-1.0,-1.0,-1.0,-1.0,37.221,2.14267,2066,4259551 +1004,search,3302.25,-1.0,-1.0,-1.0,-1.0,18.01,2.14267,2066,4259551 +1005,delete,28.544,-1.0,-1.0,-1.0,-1.0,15.353,2.13484,2066,4241434 +1006,search,3311.45,-1.0,-1.0,-1.0,-1.0,17.801,2.13484,2066,4241434 +1007,delete,182.116,-1.0,-1.0,-1.0,-1.0,242.601,2.02889,2030,4052722 +1008,search,3194.32,-1.0,-1.0,-1.0,-1.0,16.656,2.02889,2030,4052722 +1009,delete,277.105,-1.0,-1.0,-1.0,-1.0,256.008,1.86127,1977,3738432 +1010,search,3108.32,-1.0,-1.0,-1.0,-1.0,16.132,1.86127,1977,3738432 +1011,delete,333.503,-1.0,-1.0,-1.0,-1.0,337.499,1.67368,1909,3372539 +1012,search,2908.62,-1.0,-1.0,-1.0,-1.0,30.483,1.6741,1911,3372539 +1013,delete,10.365,-1.0,-1.0,-1.0,-1.0,22.676,1.67003,1908,3361432 +1014,search,2890.78,-1.0,-1.0,-1.0,-1.0,15.703,1.67003,1908,3361432 +1015,delete,215.704,-1.0,-1.0,-1.0,-1.0,274.977,1.53089,1849,3091692 +1016,search,2787.27,-1.0,-1.0,-1.0,-1.0,14.74,1.53089,1849,3091692 +1017,delete,263.402,-1.0,-1.0,-1.0,-1.0,316.146,1.36839,1786,2775418 +1018,search,2667.98,-1.0,-1.0,-1.0,-1.0,13.975,1.36839,1786,2775418 +1019,delete,18.369,-1.0,-1.0,-1.0,-1.0,23.121,1.36161,1784,2754073 +1020,search,2657.13,-1.0,-1.0,-1.0,-1.0,13.978,1.36161,1784,2754073 +1021,delete,99.942,-1.0,-1.0,-1.0,-1.0,63.944,1.32029,1772,2638917 +1022,search,2588.93,-1.0,-1.0,-1.0,-1.0,14.016,1.32029,1772,2638917 +1023,delete,77.689,-1.0,-1.0,-1.0,-1.0,63.857,1.27759,1757,2556494 +1024,search,2544.89,-1.0,-1.0,-1.0,-1.0,13.691,1.27759,1757,2556494 +1025,insert,24.256,-1.0,-1.0,-1.0,-1.0,13.079,1.28391,1757,2594934 +1026,search,2559.97,-1.0,-1.0,-1.0,-1.0,13.665,1.28391,1757,2594934 +1027,insert,164.284,-1.0,-1.0,-1.0,-1.0,73.742,1.34641,1763,2802105 +1028,search,2667,-1.0,-1.0,-1.0,-1.0,46.404,1.34641,1767,2802105 +1029,insert,316.617,-1.0,-1.0,-1.0,-1.0,135.059,1.48286,1782,3203975 +1030,search,2801.09,-1.0,-1.0,-1.0,-1.0,80.573,1.48314,1792,3203975 +1031,insert,488.418,-1.0,-1.0,-1.0,-1.0,295.779,1.73736,1816,3830566 +1032,search,3054.76,-1.0,-1.0,-1.0,-1.0,219.237,1.7374,1832,3830566 +1033,insert,361.841,-1.0,-1.0,-1.0,-1.0,192.924,1.91549,1862,4252669 +1034,search,3168.26,-1.0,-1.0,-1.0,-1.0,158.765,1.91581,1879,4252669 +1035,insert,200.085,-1.0,-1.0,-1.0,-1.0,219.497,2.02898,1910,4512107 +1036,search,3249.86,-1.0,-1.0,-1.0,-1.0,111.507,2.02911,1921,4512107 +1037,insert,10.06,-1.0,-1.0,-1.0,-1.0,15.174,2.03309,1921,4525815 +1038,search,3276.04,-1.0,-1.0,-1.0,-1.0,63.792,2.03309,1927,4525815 +1039,insert,61.095,-1.0,-1.0,-1.0,-1.0,20.598,2.06378,1928,4599215 +1040,search,3269.32,-1.0,-1.0,-1.0,-1.0,24.904,2.06378,1929,4599215 +1041,insert,8.694,-1.0,-1.0,-1.0,-1.0,24.941,2.0689,1931,4609851 +1042,search,3317.33,-1.0,-1.0,-1.0,-1.0,30.998,2.06891,1933,4609851 +1043,insert,12.876,-1.0,-1.0,-1.0,-1.0,14.542,2.07427,1933,4627411 +1044,search,3308.72,-1.0,-1.0,-1.0,-1.0,15.658,2.07427,1933,4627411 +1045,insert,30.762,-1.0,-1.0,-1.0,-1.0,14.782,2.0881,1933,4670607 +1046,search,3333.84,-1.0,-1.0,-1.0,-1.0,15.787,2.0881,1933,4670607 +1047,insert,4.199,-1.0,-1.0,-1.0,-1.0,14.125,2.08948,1933,4675386 +1048,search,3337.16,-1.0,-1.0,-1.0,-1.0,15.687,2.08948,1933,4675386 +1049,insert,12.827,-1.0,-1.0,-1.0,-1.0,21.172,2.09667,1934,4689998 +1050,search,3344.12,-1.0,-1.0,-1.0,-1.0,15.514,2.09667,1934,4689998 +1051,insert,84.884,-1.0,-1.0,-1.0,-1.0,30.143,2.13925,1936,4783971 +1052,search,3378.78,-1.0,-1.0,-1.0,-1.0,15.918,2.13925,1936,4783971 +1053,insert,37.651,-1.0,-1.0,-1.0,-1.0,51.936,2.1552,1941,4826219 +1054,search,3395.83,-1.0,-1.0,-1.0,-1.0,15.92,2.1552,1941,4826219 +1055,insert,32.255,-1.0,-1.0,-1.0,-1.0,23.004,2.16716,1942,4862355 +1056,search,3406.04,-1.0,-1.0,-1.0,-1.0,15.751,2.16716,1942,4862355 +1057,insert,6.316,-1.0,-1.0,-1.0,-1.0,14.279,2.1693,1942,4869564 +1058,search,3417.97,-1.0,-1.0,-1.0,-1.0,16.269,2.1693,1942,4869564 +1059,insert,22.409,-1.0,-1.0,-1.0,-1.0,14.633,2.178,1942,4898570 +1060,search,3426.67,-1.0,-1.0,-1.0,-1.0,16.246,2.178,1942,4898570 +1061,insert,9.061,-1.0,-1.0,-1.0,-1.0,14.369,2.18172,1942,4907501 +1062,search,3448.35,-1.0,-1.0,-1.0,-1.0,16.3,2.18172,1942,4907501 +1063,insert,6.513,-1.0,-1.0,-1.0,-1.0,23.057,2.18486,1943,4916386 +1064,search,3436.82,-1.0,-1.0,-1.0,-1.0,16.309,2.18486,1943,4916386 +1065,insert,242.251,-1.0,-1.0,-1.0,-1.0,246.518,2.3081,1975,5194839 +1066,search,3541.35,-1.0,-1.0,-1.0,-1.0,51.719,2.30848,1980,5194839 +1067,insert,5.253,-1.0,-1.0,-1.0,-1.0,15.723,2.31046,1980,5200182 +1068,search,3545.49,-1.0,-1.0,-1.0,-1.0,16.871,2.31046,1980,5200182 +1069,insert,31.158,-1.0,-1.0,-1.0,-1.0,18.136,2.32362,1981,5230883 +1070,search,3548.81,-1.0,-1.0,-1.0,-1.0,18.361,2.32362,1981,5230883 +1071,insert,22.407,-1.0,-1.0,-1.0,-1.0,29.521,2.33429,1983,5255659 +1072,search,3561.56,-1.0,-1.0,-1.0,-1.0,15.87,2.33429,1983,5255659 +1073,insert,28.592,-1.0,-1.0,-1.0,-1.0,35.794,2.3465,1986,5281693 +1074,search,3553.37,-1.0,-1.0,-1.0,-1.0,15.897,2.3465,1986,5281693 +1075,insert,9.203,-1.0,-1.0,-1.0,-1.0,14.308,2.34925,1986,5290081 +1076,search,3577.94,-1.0,-1.0,-1.0,-1.0,16.034,2.34925,1986,5290081 +1077,insert,25.41,-1.0,-1.0,-1.0,-1.0,14.624,2.3593,1986,5316166 +1078,search,3563.77,-1.0,-1.0,-1.0,-1.0,16.123,2.3593,1986,5316166 +1079,insert,20.262,-1.0,-1.0,-1.0,-1.0,23.153,2.36712,1988,5335531 +1080,search,3607.09,-1.0,-1.0,-1.0,-1.0,16.149,2.36712,1988,5335531 +1081,insert,309.569,-1.0,-1.0,-1.0,-1.0,154.791,2.51222,2007,5678781 +1082,search,3719.57,-1.0,-1.0,-1.0,-1.0,65.543,2.51282,2013,5678781 +1083,insert,0.752,-1.0,-1.0,-1.0,-1.0,15.909,2.51296,2013,5679848 +1084,search,3713.86,-1.0,-1.0,-1.0,-1.0,30.341,2.51296,2015,5679848 +1085,insert,22.225,-1.0,-1.0,-1.0,-1.0,34.215,2.52357,2019,5702205 +1086,search,3723.43,-1.0,-1.0,-1.0,-1.0,16.423,2.52357,2019,5702205 +1087,insert,13.901,-1.0,-1.0,-1.0,-1.0,26.36,2.5294,2021,5715514 +1088,search,3751.79,-1.0,-1.0,-1.0,-1.0,16.456,2.5294,2021,5715514 +1089,insert,342.18,-1.0,-1.0,-1.0,-1.0,279.305,2.70256,2075,6103499 +1090,search,3925.18,-1.0,-1.0,-1.0,-1.0,39.957,2.70316,2079,6103499 +1091,insert,38.646,-1.0,-1.0,-1.0,-1.0,43.807,2.72632,2086,6152505 +1092,search,3922.3,-1.0,-1.0,-1.0,-1.0,21.741,2.72641,2087,6152505 +1093,insert,13.249,-1.0,-1.0,-1.0,-1.0,26.781,2.73407,2089,6171104 +1094,search,3938.37,-1.0,-1.0,-1.0,-1.0,17.327,2.73407,2089,6171104 +1095,insert,273.956,-1.0,-1.0,-1.0,-1.0,348.398,2.90646,2144,6557850 +1096,search,4157.27,-1.0,-1.0,-1.0,-1.0,91.524,2.9065,2159,6557850 +1097,insert,15.198,-1.0,-1.0,-1.0,-1.0,18.135,2.91552,2159,6579289 +1098,search,4156.07,-1.0,-1.0,-1.0,-1.0,20.662,2.91552,2159,6579289 +1099,insert,10.807,-1.0,-1.0,-1.0,-1.0,17.967,2.9208,2159,6591442 +1100,search,4147.98,-1.0,-1.0,-1.0,-1.0,34.27,2.92117,2161,6591442 +1101,insert,30.376,-1.0,-1.0,-1.0,-1.0,46.122,2.93832,2166,6633739 +1102,search,4172.95,-1.0,-1.0,-1.0,-1.0,47.11,2.93886,2169,6633739 +1103,insert,73.701,-1.0,-1.0,-1.0,-1.0,101.663,2.98088,2187,6724357 +1104,search,4222.64,-1.0,-1.0,-1.0,-1.0,33.104,2.98095,2190,6724357 +1105,insert,1.885,-1.0,-1.0,-1.0,-1.0,25.257,2.98188,2191,6727059 +1106,search,4237.6,-1.0,-1.0,-1.0,-1.0,19.547,2.98188,2191,6727059 +1107,insert,168.696,-1.0,-1.0,-1.0,-1.0,181.969,3.0767,2214,6950869 +1108,search,4348.06,-1.0,-1.0,-1.0,-1.0,48.508,3.07793,2218,6950869 +1109,insert,5.019,-1.0,-1.0,-1.0,-1.0,25.102,3.08113,2219,6958173 +1110,search,4354.77,-1.0,-1.0,-1.0,-1.0,19.775,3.08113,2219,6958173 +1111,insert,40.06,-1.0,-1.0,-1.0,-1.0,41.543,3.09709,2224,6995273 +1112,search,4359.35,-1.0,-1.0,-1.0,-1.0,18.348,3.09709,2224,6995273 +1113,insert,40.607,-1.0,-1.0,-1.0,-1.0,81.859,3.1203,2236,7047862 +1114,search,4367.77,-1.0,-1.0,-1.0,-1.0,19.52,3.1203,2236,7047862 +1115,insert,52.365,-1.0,-1.0,-1.0,-1.0,64.424,3.15047,2245,7110727 +1116,search,4403.92,-1.0,-1.0,-1.0,-1.0,34.932,3.15087,2247,7110727 +1117,insert,13.609,-1.0,-1.0,-1.0,-1.0,25.364,3.15789,2248,7125591 +1118,search,4417.1,-1.0,-1.0,-1.0,-1.0,19.62,3.15789,2248,7125591 +1119,insert,6.412,-1.0,-1.0,-1.0,-1.0,23.022,3.1606,2249,7134442 +1120,search,4418.74,-1.0,-1.0,-1.0,-1.0,19.07,3.1606,2249,7134442 +1121,insert,25.944,-1.0,-1.0,-1.0,-1.0,39.688,3.17245,2252,7162109 +1122,search,4435.58,-1.0,-1.0,-1.0,-1.0,19.138,3.17245,2252,7162109 +1123,insert,15.439,-1.0,-1.0,-1.0,-1.0,46.499,3.17919,2257,7179509 +1124,search,4448.59,-1.0,-1.0,-1.0,-1.0,19.41,3.17919,2257,7179509 +1125,insert,6.475,-1.0,-1.0,-1.0,-1.0,35.354,3.18278,2259,7186372 +1126,search,4418.67,-1.0,-1.0,-1.0,-1.0,19.508,3.18278,2259,7186372 +1127,insert,31.978,-1.0,-1.0,-1.0,-1.0,47.127,3.20096,2264,7231450 +1128,search,4436.28,-1.0,-1.0,-1.0,-1.0,24.006,3.20106,2265,7231450 +1129,insert,8.947,-1.0,-1.0,-1.0,-1.0,22.598,3.20514,2266,7243215 +1130,search,4418.65,-1.0,-1.0,-1.0,-1.0,19.51,3.20514,2266,7243215 +1131,insert,30.431,-1.0,-1.0,-1.0,-1.0,50.219,3.2193,2270,7276107 +1132,search,4509.72,-1.0,-1.0,-1.0,-1.0,33.661,3.21953,2272,7276107 +1133,insert,11.423,-1.0,-1.0,-1.0,-1.0,36.534,3.22445,2276,7292577 +1134,search,4505.35,-1.0,-1.0,-1.0,-1.0,21.572,3.22445,2276,7292577 +1135,insert,7.718,-1.0,-1.0,-1.0,-1.0,26.536,3.22757,2277,7299867 +1136,search,4487.89,-1.0,-1.0,-1.0,-1.0,20.785,3.22757,2277,7299867 +1137,insert,25.986,-1.0,-1.0,-1.0,-1.0,26.812,3.23948,2278,7323342 +1138,search,4495.65,-1.0,-1.0,-1.0,-1.0,21.289,3.23948,2278,7323342 +1139,insert,3.293,-1.0,-1.0,-1.0,-1.0,18.499,3.24115,2278,7325844 +1140,search,4477.02,-1.0,-1.0,-1.0,-1.0,20.832,3.24115,2278,7325844 +1141,insert,203.12,-1.0,-1.0,-1.0,-1.0,238.708,3.33584,2309,7540761 +1142,search,4625.04,-1.0,-1.0,-1.0,-1.0,106.429,3.33736,2325,7540761 +1143,insert,16.621,-1.0,-1.0,-1.0,-1.0,33.945,3.34502,2328,7561926 +1144,search,4624.92,-1.0,-1.0,-1.0,-1.0,33.659,3.34516,2330,7561926 +1145,insert,9.998,-1.0,-1.0,-1.0,-1.0,34.084,3.3514,2332,7571861 +1146,search,4618.59,-1.0,-1.0,-1.0,-1.0,20.459,3.3514,2332,7571861 +1147,insert,18.524,-1.0,-1.0,-1.0,-1.0,37.566,3.35984,2335,7590881 +1148,search,4628.68,-1.0,-1.0,-1.0,-1.0,20.614,3.35984,2335,7590881 +1149,insert,6.876,-1.0,-1.0,-1.0,-1.0,36.354,3.36316,2338,7595507 +1150,search,4626.14,-1.0,-1.0,-1.0,-1.0,19.783,3.36316,2338,7595507 +1151,insert,5.569,-1.0,-1.0,-1.0,-1.0,24.519,3.36604,2339,7601664 +1152,search,4650.81,-1.0,-1.0,-1.0,-1.0,20.516,3.36604,2339,7601664 +1153,delete,21.749,-1.0,-1.0,-1.0,-1.0,19.336,3.36592,2339,7566707 +1154,search,4655.94,-1.0,-1.0,-1.0,-1.0,26.968,3.3662,2340,7566707 +1155,delete,109.228,-1.0,-1.0,-1.0,-1.0,124.225,3.33158,2328,7396192 +1156,search,4579.35,-1.0,-1.0,-1.0,-1.0,25.542,3.33161,2329,7396192 +1157,delete,220.83,-1.0,-1.0,-1.0,-1.0,269.421,3.25667,2285,7079041 +1158,search,4406.15,-1.0,-1.0,-1.0,-1.0,31.422,3.25696,2287,7079041 +1159,delete,322.134,-1.0,-1.0,-1.0,-1.0,386.976,3.08627,2207,6597115 +1160,search,4214.2,-1.0,-1.0,-1.0,-1.0,40.336,3.08714,2210,6597115 +1161,delete,193.043,-1.0,-1.0,-1.0,-1.0,168.425,2.99789,2179,6308902 +1162,search,4102.39,-1.0,-1.0,-1.0,-1.0,45.345,2.99849,2183,6308902 +1163,delete,87.126,-1.0,-1.0,-1.0,-1.0,143.403,2.9441,2164,6164514 +1164,search,4048.69,-1.0,-1.0,-1.0,-1.0,18.428,2.9441,2164,6164514 +1165,delete,30.316,-1.0,-1.0,-1.0,-1.0,34.502,2.93712,2162,6133412 +1166,search,4031.4,-1.0,-1.0,-1.0,-1.0,18.251,2.93712,2162,6133412 +1167,delete,53.048,-1.0,-1.0,-1.0,-1.0,18.145,2.92794,2162,6057218 +1168,search,4010.29,-1.0,-1.0,-1.0,-1.0,18.017,2.92794,2162,6057218 +1169,delete,17.178,-1.0,-1.0,-1.0,-1.0,63.375,2.914,2153,6028053 +1170,search,3984.79,-1.0,-1.0,-1.0,-1.0,20.121,2.914,2153,6028053 +1171,delete,30.828,-1.0,-1.0,-1.0,-1.0,17.314,2.90886,2153,6001880 +1172,search,3994.51,-1.0,-1.0,-1.0,-1.0,35.878,2.90904,2154,6001880 +1173,delete,38.68,-1.0,-1.0,-1.0,-1.0,28.453,2.89821,2152,5957180 +1174,search,3977.56,-1.0,-1.0,-1.0,-1.0,19.192,2.89821,2152,5957180 +1175,delete,18.652,-1.0,-1.0,-1.0,-1.0,16.804,2.89533,2152,5939326 +1176,search,3967.79,-1.0,-1.0,-1.0,-1.0,18.757,2.89533,2152,5939326 +1177,delete,14.312,-1.0,-1.0,-1.0,-1.0,38.737,2.8882,2150,5924145 +1178,search,3959.46,-1.0,-1.0,-1.0,-1.0,18.533,2.8882,2150,5924145 +1179,delete,57.727,-1.0,-1.0,-1.0,-1.0,69.829,2.86292,2141,5863334 +1180,search,3933.78,-1.0,-1.0,-1.0,-1.0,18.593,2.86292,2141,5863334 +1181,delete,40.985,-1.0,-1.0,-1.0,-1.0,18.509,2.8509,2140,5822703 +1182,search,3914.16,-1.0,-1.0,-1.0,-1.0,18.824,2.8509,2140,5822703 +1183,delete,37.206,-1.0,-1.0,-1.0,-1.0,31.597,2.84032,2138,5775807 +1184,search,3894.3,-1.0,-1.0,-1.0,-1.0,18.524,2.84032,2138,5775807 +1185,delete,24.606,-1.0,-1.0,-1.0,-1.0,16.228,2.83442,2138,5750627 +1186,search,3889.06,-1.0,-1.0,-1.0,-1.0,18.596,2.83442,2138,5750627 +1187,delete,136.731,-1.0,-1.0,-1.0,-1.0,120.802,2.78281,2122,5601207 +1188,search,3819.52,-1.0,-1.0,-1.0,-1.0,17.826,2.78281,2122,5601207 +1189,delete,13.763,-1.0,-1.0,-1.0,-1.0,23.318,2.78016,2121,5586425 +1190,search,3800.19,-1.0,-1.0,-1.0,-1.0,17.885,2.78016,2121,5586425 +1191,delete,11.82,-1.0,-1.0,-1.0,-1.0,16.395,2.7775,2121,5574023 +1192,search,3797.52,-1.0,-1.0,-1.0,-1.0,17.616,2.7775,2121,5574023 +1193,delete,182.738,-1.0,-1.0,-1.0,-1.0,180.278,2.67898,2099,5356157 +1194,search,3720.32,-1.0,-1.0,-1.0,-1.0,17.315,2.67898,2099,5356157 +1195,delete,15.6,-1.0,-1.0,-1.0,-1.0,15.607,2.67511,2099,5340404 +1196,search,3709.55,-1.0,-1.0,-1.0,-1.0,17.549,2.67511,2099,5340404 +1197,delete,47.874,-1.0,-1.0,-1.0,-1.0,16.469,2.65454,2099,5293259 +1198,search,3695.3,-1.0,-1.0,-1.0,-1.0,17.603,2.65454,2099,5293259 +1199,delete,10.609,-1.0,-1.0,-1.0,-1.0,15.822,2.65038,2099,5279787 +1200,search,3685.54,-1.0,-1.0,-1.0,-1.0,17.129,2.65038,2099,5279787 +1201,delete,58.635,-1.0,-1.0,-1.0,-1.0,35.241,2.62174,2096,5216567 +1202,search,3672.99,-1.0,-1.0,-1.0,-1.0,17.322,2.62174,2096,5216567 +1203,delete,19.701,-1.0,-1.0,-1.0,-1.0,15.418,2.61555,2096,5196947 +1204,search,3647.3,-1.0,-1.0,-1.0,-1.0,17.187,2.61555,2096,5196947 +1205,delete,23.253,-1.0,-1.0,-1.0,-1.0,32.809,2.60219,2094,5168447 +1206,search,3655.98,-1.0,-1.0,-1.0,-1.0,17.389,2.60219,2094,5168447 +1207,delete,18.295,-1.0,-1.0,-1.0,-1.0,37.741,2.59118,2091,5146927 +1208,search,3643.07,-1.0,-1.0,-1.0,-1.0,16.896,2.59118,2091,5146927 +1209,delete,215.407,-1.0,-1.0,-1.0,-1.0,213.528,2.45995,2057,4887612 +1210,search,3544.02,-1.0,-1.0,-1.0,-1.0,16.389,2.45995,2057,4887612 +1211,delete,7.185,-1.0,-1.0,-1.0,-1.0,14.998,2.45882,2057,4882301 +1212,search,3520.1,-1.0,-1.0,-1.0,-1.0,16.66,2.45882,2057,4882301 +1213,delete,100.927,-1.0,-1.0,-1.0,-1.0,63.868,2.41015,2050,4780915 +1214,search,3497.43,-1.0,-1.0,-1.0,-1.0,22.322,2.4103,2051,4780915 +1215,delete,12.879,-1.0,-1.0,-1.0,-1.0,15.496,2.40503,2051,4765751 +1216,search,3496.5,-1.0,-1.0,-1.0,-1.0,18.593,2.40503,2051,4765751 +1217,delete,315.641,-1.0,-1.0,-1.0,-1.0,175.292,2.24924,2009,4452306 +1218,search,3347.99,-1.0,-1.0,-1.0,-1.0,16.69,2.24924,2009,4452306 +1219,delete,91.26,-1.0,-1.0,-1.0,-1.0,109.276,2.19599,1988,4362045 +1220,search,3297.39,-1.0,-1.0,-1.0,-1.0,22.595,2.19619,1989,4362045 +1221,delete,35.976,-1.0,-1.0,-1.0,-1.0,18.362,2.18109,1987,4326917 +1222,search,3300.6,-1.0,-1.0,-1.0,-1.0,16.671,2.18109,1987,4326917 +1223,delete,195.278,-1.0,-1.0,-1.0,-1.0,181.716,2.06626,1949,4109781 +1224,search,3184.78,-1.0,-1.0,-1.0,-1.0,15.91,2.06626,1949,4109781 +1225,delete,30.747,-1.0,-1.0,-1.0,-1.0,20.406,2.05133,1947,4075879 +1226,search,3184.73,-1.0,-1.0,-1.0,-1.0,16.039,2.05133,1947,4075879 +1227,delete,67.69,-1.0,-1.0,-1.0,-1.0,61.668,2.01878,1939,4006503 +1228,search,3164.25,-1.0,-1.0,-1.0,-1.0,16.088,2.01878,1939,4006503 +1229,delete,84.219,-1.0,-1.0,-1.0,-1.0,63.244,1.9773,1932,3922625 +1230,search,3088.49,-1.0,-1.0,-1.0,-1.0,25.433,1.97747,1933,3922625 +1231,delete,74.742,-1.0,-1.0,-1.0,-1.0,117.956,1.92966,1902,3844860 +1232,search,3065.21,-1.0,-1.0,-1.0,-1.0,15.64,1.92966,1902,3844860 +1233,delete,14.49,-1.0,-1.0,-1.0,-1.0,16.067,1.92406,1901,3831414 +1234,search,3064.19,-1.0,-1.0,-1.0,-1.0,15.097,1.92406,1901,3831414 +1235,delete,129.644,-1.0,-1.0,-1.0,-1.0,95.767,1.85289,1888,3684234 +1236,search,3005.56,-1.0,-1.0,-1.0,-1.0,14.994,1.85289,1888,3684234 +1237,delete,14.282,-1.0,-1.0,-1.0,-1.0,28.324,1.84496,1886,3669074 +1238,search,2997.69,-1.0,-1.0,-1.0,-1.0,15.248,1.84496,1886,3669074 +1239,delete,49.939,-1.0,-1.0,-1.0,-1.0,14.975,1.82546,1886,3620984 +1240,search,2965.83,-1.0,-1.0,-1.0,-1.0,15.171,1.82546,1886,3620984 +1241,delete,36.557,-1.0,-1.0,-1.0,-1.0,14.228,1.81003,1886,3580113 +1242,search,2974.87,-1.0,-1.0,-1.0,-1.0,15.06,1.81003,1886,3580113 +1243,delete,44.861,-1.0,-1.0,-1.0,-1.0,21.438,1.78671,1884,3533909 +1244,search,2962.76,-1.0,-1.0,-1.0,-1.0,15.22,1.78671,1884,3533909 +1245,delete,14.323,-1.0,-1.0,-1.0,-1.0,13.523,1.78114,1884,3519590 +1246,search,2972.72,-1.0,-1.0,-1.0,-1.0,15.034,1.78114,1884,3519590 +1247,delete,51.658,-1.0,-1.0,-1.0,-1.0,73.2,1.7424,1859,3452537 +1248,search,2887.78,-1.0,-1.0,-1.0,-1.0,20.57,1.74251,1860,3452537 +1249,delete,30.881,-1.0,-1.0,-1.0,-1.0,26.128,1.72742,1858,3416711 +1250,search,2894.84,-1.0,-1.0,-1.0,-1.0,15.165,1.72742,1858,3416711 +1251,delete,28.64,-1.0,-1.0,-1.0,-1.0,25.136,1.71167,1855,3387653 +1252,search,2883.91,-1.0,-1.0,-1.0,-1.0,14.833,1.71167,1855,3387653 +1253,delete,15.4,-1.0,-1.0,-1.0,-1.0,24.615,1.70221,1852,3372157 +1254,search,2881.78,-1.0,-1.0,-1.0,-1.0,14.998,1.70221,1852,3372157 +1255,delete,88.457,-1.0,-1.0,-1.0,-1.0,94.758,1.6406,1820,3258215 +1256,search,2808.56,-1.0,-1.0,-1.0,-1.0,14.583,1.6406,1820,3258215 +1257,delete,31.328,-1.0,-1.0,-1.0,-1.0,22.694,1.62331,1816,3223657 +1258,search,2804.01,-1.0,-1.0,-1.0,-1.0,14.463,1.62331,1816,3223657 +1259,delete,41.746,-1.0,-1.0,-1.0,-1.0,36.191,1.59989,1812,3174982 +1260,search,2784.41,-1.0,-1.0,-1.0,-1.0,14.297,1.59989,1812,3174982 +1261,delete,19.12,-1.0,-1.0,-1.0,-1.0,16.33,1.59425,1811,3157038 +1262,search,2785.41,-1.0,-1.0,-1.0,-1.0,14.584,1.59425,1811,3157038 +1263,delete,88.272,-1.0,-1.0,-1.0,-1.0,86.091,1.53981,1799,3058847 +1264,search,2739.79,-1.0,-1.0,-1.0,-1.0,14.46,1.53981,1799,3058847 +1265,delete,210.687,-1.0,-1.0,-1.0,-1.0,217.952,1.40858,1715,2833531 +1266,search,2618.36,-1.0,-1.0,-1.0,-1.0,13.593,1.40858,1715,2833531 +1267,delete,56.445,-1.0,-1.0,-1.0,-1.0,42.216,1.38481,1710,2763793 +1268,search,2585.29,-1.0,-1.0,-1.0,-1.0,25.943,1.38504,1711,2763793 +1269,delete,137.857,-1.0,-1.0,-1.0,-1.0,127.213,1.31658,1686,2627384 +1270,search,2541.92,-1.0,-1.0,-1.0,-1.0,22.194,1.31668,1687,2627384 +1271,delete,72.076,-1.0,-1.0,-1.0,-1.0,61.256,1.28315,1679,2553476 +1272,search,2493.15,-1.0,-1.0,-1.0,-1.0,13.681,1.28315,1679,2553476 +1273,delete,100.724,-1.0,-1.0,-1.0,-1.0,88.624,1.22821,1657,2443067 +1274,search,2442.47,-1.0,-1.0,-1.0,-1.0,13.613,1.22821,1657,2443067 +1275,delete,24.681,-1.0,-1.0,-1.0,-1.0,22.354,1.21897,1655,2421654 +1276,search,2441.77,-1.0,-1.0,-1.0,-1.0,13.509,1.21897,1655,2421654 +1277,delete,33.139,-1.0,-1.0,-1.0,-1.0,28.164,1.20626,1650,2391396 +1278,search,2428.91,-1.0,-1.0,-1.0,-1.0,13.746,1.20626,1650,2391396 +1279,delete,28.119,-1.0,-1.0,-1.0,-1.0,11.755,1.19801,1650,2367854 +1280,search,2429.23,-1.0,-1.0,-1.0,-1.0,12.971,1.19801,1650,2367854 diff --git a/scripts/big_ann_perf_numbers/perf_debug_scan_0.13_worker_batch_clustering_score.csv b/scripts/big_ann_perf_numbers/perf_debug_scan_0.13_worker_batch_clustering_score.csv new file mode 100644 index 00000000..0bf01d50 --- /dev/null +++ b/scripts/big_ann_perf_numbers/perf_debug_scan_0.13_worker_batch_clustering_score.csv @@ -0,0 +1,21 @@ +step_num,step_type,latency_ms,worker_partition_size,worker_scan_time_ms,worker_scan_throughput,worker_result_time_ms,measured_ipc,cache_miss_rate,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors,silleheoute_mean,silleheoute_std_dev +2,search,2858.61,37.306,293.561,0.540552,482.29,-nan,-nan,0.83112,0.139674,-1.0,-1.0,7.176,0.0184881,1000,38806,0.0481552,0.0764215, +3,insert,10.949,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,30.58,0.0226893,995,49334,0.031224,0.0782707, +4,search,2353.83,65.4907,153.473,0.949213,157.785,-nan,-nan,0.84438,0.139792,-1.0,-1.0,38.521,0.0226836,988,49334,0.0306269,0.0786408, +5,insert,12.173,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,220.632,0.0330921,973,73557,0.013662,0.0728127, +6,search,1730.38,198.808,181.446,1.80123,64.426,-nan,-nan,0.91347,0.1126,-1.0,-1.0,95.583,0.0331427,974,73557,0.0136931,0.0717552, +7,insert,11.947,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,96.442,0.0428274,975,95766,0.00350572,0.0694801, +8,search,1593.52,249.649,193.196,1.62546,63.1557,-nan,-nan,0.91131,0.113758,-1.0,-1.0,20.107,0.0433047,979,95766,0.00321126,0.0697775, +9,insert,2.648,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,3.903,0.0450563,979,100025,0.00304833,0.0705768, +10,search,1736.06,253.4,176.331,1.28113,83.1989,-nan,-nan,0.91187,0.112315,-1.0,-1.0,11.029,0.0451117,983,100025,0.00274555,0.0688998, +11,insert,4.311,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,3.908,0.0499416,983,111417,-0.00256859,0.0683584, +12,search,1735.05,294.676,199.471,1.29274,73.8212,-nan,-nan,0.91046,0.11371,-1.0,-1.0,9.604,0.0500551,987,111417,-0.000659093,0.0707141, +13,insert,17.895,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,6.317,0.0610503,987,137139,-0.0030937,0.0635938, +14,search,1812.33,329.309,219.583,1.26896,77.0092,-nan,-nan,0.90656,0.116661,-1.0,-1.0,7.204,0.0610641,989,137139,-0.00323246,0.0641389, +15,insert,7.43,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,7.311,0.0695962,992,156710,-0.00404804,0.0625114, +16,search,1767.5,360.375,230.702,1.23382,71.1503,-nan,-nan,0.90344,0.11765,-1.0,-1.0,4.044,0.0695962,992,156710,-0.0021428,0.0635274, +17,insert,2.147,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,7.466,0.0718965,995,161773,-0.00578649,0.063447, +18,search,1775.58,375.119,239.23,1.14144,79.0919,-nan,-nan,0.90537,0.116405,-1.0,-1.0,6.807,0.0719006,996,161773,-0.0057422,0.0635047, +19,insert,19.104,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,5.616,0.0785021,997,177161,-0.00673169,0.0620932, +20,search,1800.4,415.047,261.647,1.20258,77.4051,-nan,-nan,0.91005,0.112435,-1.0,-1.0,5.578,0.0785021,998,177161,-0.00611008,0.0623675, +21,insert,189.577,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,103.458,0.201671,1046,448898,-0.00948841,0.0511418, diff --git a/scripts/big_ann_perf_numbers/perf_debug_scan_0.14_tuning.csv b/scripts/big_ann_perf_numbers/perf_debug_scan_0.14_tuning.csv new file mode 100644 index 00000000..95f3c854 --- /dev/null +++ b/scripts/big_ann_perf_numbers/perf_debug_scan_0.14_tuning.csv @@ -0,0 +1,651 @@ +step_num,step_type,latency_ms,worker_partition_size,worker_scan_time_ms,worker_scan_throughput,worker_result_time_ms,measured_ipc,cache_miss_rate,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +2,search,3119.98,37.4251,337.059,0.542339,590.306,-nan,-nan,0.844,0.1346,-1.0,-1.0,19.116,0.0184881,1000,38806 +3,insert,24.997,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.207,0.022655,996,49334 +4,search,2478.03,65.1954,172.243,1.02629,182.991,-nan,-nan,0.8558,0.133903,-1.0,-1.0,11.045,0.0226615,993,49334 +5,insert,16.566,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,161.104,0.033017,984,73557 +6,search,2312.4,190.054,188.271,1.6293,86.4517,-nan,-nan,0.91846,0.108847,-1.0,-1.0,140.844,0.0330521,985,73557 +7,insert,23.37,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,144.286,0.0425581,986,95766 +8,search,2398.93,238.37,199.126,1.46738,96.1916,-nan,-nan,0.9187,0.10833,-1.0,-1.0,92.957,0.0428004,989,95766 +9,insert,5.936,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,74.015,0.044627,989,100025 +10,search,2363.99,245.311,196.076,1.3594,98.7188,-nan,-nan,0.91993,0.105737,-1.0,-1.0,19.649,0.0450612,993,100025 +11,insert,8.451,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,11.19,0.049827,996,111417 +12,search,2408.5,279.141,205.534,1.18839,114.879,-nan,-nan,0.9178,0.108016,-1.0,-1.0,15.176,0.0499861,998,111417 +13,insert,19.103,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,9.188,0.0613151,1000,137139 +14,search,2438.46,315.833,232.396,1.16178,113.06,-nan,-nan,0.91348,0.110604,-1.0,-1.0,13.984,0.0613273,1003,137139 +15,insert,15.059,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,6.234,0.0698504,1003,156710 +16,search,2455.44,348.477,247.424,1.12924,104.21,-nan,-nan,0.91087,0.110722,-1.0,-1.0,9.026,0.06985,1004,156710 +17,insert,3.621,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,10.662,0.071841,1006,161773 +18,search,2430.87,359.776,247.507,1.13628,103.595,-nan,-nan,0.91165,0.110745,-1.0,-1.0,9.143,0.0718998,1007,161773 +19,insert,31.058,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,9.149,0.078733,1008,177161 +20,search,2466.25,397.871,267.363,1.1276,99.2325,-nan,-nan,0.91665,0.106402,-1.0,-1.0,9.216,0.078733,1009,177161 +21,insert,319.958,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,160.932,0.200572,1054,448898 +22,search,2680.99,804.423,477.305,1.05132,74.368,-nan,-nan,0.9029,0.113107,-1.0,-1.0,33.824,0.20057,1062,448898 +23,insert,389.466,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,252.388,0.328638,1114,733493 +24,search,2932.31,1115.83,655.345,1.02094,74.2773,-nan,-nan,0.89851,0.115125,-1.0,-1.0,71.309,0.328826,1127,733493 +25,insert,41.606,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,24.183,0.345294,1132,777443 +26,search,2982.07,1110.67,671.389,1.02779,79.1616,-nan,-nan,0.89765,0.115252,-1.0,-1.0,16.067,0.345306,1133,777443 +27,insert,31.667,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.746,0.356747,1134,805394 +28,search,2995.52,1139.21,686.448,0.989931,73.8757,-nan,-nan,0.89895,0.114194,-1.0,-1.0,12.743,0.35675,1135,805394 +29,insert,57.582,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,54.835,0.385014,1146,866391 +30,search,3045.4,1189.76,715.013,1.02242,68.7515,-nan,-nan,0.9013,0.113408,-1.0,-1.0,27.509,0.385013,1149,866391 +31,insert,455.223,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,345.366,0.553921,1213,1239816 +32,search,3320.02,1450.6,886.765,1.02501,75.4543,-nan,-nan,0.89498,0.117695,-1.0,-1.0,83.559,0.554228,1222,1239816 +33,insert,46.043,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,32.806,0.574066,1228,1291211 +34,search,3348.02,1457.37,891.257,1.01373,83.791,-nan,-nan,0.89479,0.117626,-1.0,-1.0,57.237,0.574272,1233,1291211 +35,insert,26.905,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,31.385,0.584538,1240,1324978 +36,search,3389.87,1474.14,903.984,0.987988,82.2582,-nan,-nan,0.89579,0.116858,-1.0,-1.0,23.963,0.584563,1243,1324978 +37,insert,42.242,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,39.834,0.604534,1249,1371885 +38,search,3452.11,1493.59,928.366,1.0299,81.4936,-nan,-nan,0.89552,0.116885,-1.0,-1.0,21.07,0.604534,1250,1371885 +39,insert,12.852,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,18.392,0.607423,1252,1379335 +40,search,3478.87,1492.43,941.284,0.95729,83.309,-nan,-nan,0.89597,0.117495,-1.0,-1.0,10.253,0.607423,1252,1379335 +41,insert,59.421,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,27.162,0.623012,1256,1413312 +42,search,3483.96,1517.76,959.933,0.989305,91.1776,-nan,-nan,0.89617,0.117625,-1.0,-1.0,9.987,0.623012,1256,1413312 +43,insert,14.848,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.413,0.62718,1257,1423411 +44,search,3519.87,1530.62,983.339,0.988673,75.9508,-nan,-nan,0.89649,0.117523,-1.0,-1.0,9.674,0.62718,1257,1423411 +45,insert,227.833,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,19.689,0.642324,1260,1457559 +46,search,3563.34,1559.9,983.746,1.03183,91.352,-nan,-nan,0.89822,0.115715,-1.0,-1.0,9.425,0.642324,1260,1457559 +47,insert,278.553,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,249.553,0.746998,1293,1688593 +48,search,3699.72,1691.59,1072.3,1.09593,86.8992,-nan,-nan,0.89996,0.115395,-1.0,-1.0,68.501,0.746997,1299,1688593 +49,insert,36.238,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,27.268,0.761762,1303,1723505 +50,search,3744.74,1700.35,1079.53,1.00068,89.5637,-nan,-nan,0.90036,0.11539,-1.0,-1.0,25.414,0.761763,1305,1723505 +51,insert,330.509,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,230.942,0.902099,1343,2035040 +52,search,3958.39,1892,1220.76,0.991052,92.724,-nan,-nan,0.90343,0.114527,-1.0,-1.0,39.714,0.902122,1346,2035040 +53,insert,48.276,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,63.876,0.921399,1354,2078341 +54,search,4001.99,1901.24,1234.08,0.971816,104.595,-nan,-nan,0.90307,0.114776,-1.0,-1.0,11.57,0.921399,1354,2078341 +55,insert,396.898,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,424.448,1.06795,1408,2399905 +56,search,4278.91,2074.73,1383.13,1.00095,123.162,-nan,-nan,0.9041,0.117122,-1.0,-1.0,128.021,1.06829,1430,2399905 +57,insert,26.677,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,10.075,1.0755,1430,2419836 +58,search,4336.19,2021.57,1397.92,0.982937,129.095,-nan,-nan,0.90212,0.118455,-1.0,-1.0,61.982,1.0758,1436,2419836 +59,insert,234.221,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,127.953,1.17588,1449,2643083 +60,search,4358.74,2072.32,1424.62,0.975893,128.09,-nan,-nan,0.89471,0.125998,-1.0,-1.0,40.132,1.17611,1451,2643083 +61,insert,11.949,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.128,1.18036,1453,2653064 +62,search,4359.06,2072.57,1421.73,0.984596,127.464,-nan,-nan,0.8949,0.12576,-1.0,-1.0,25.331,1.18036,1454,2653064 +63,insert,3.69,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,10.27,1.18155,1454,2656118 +64,search,4452.93,2072.72,1410.5,0.998785,123.856,-nan,-nan,0.89475,0.126188,-1.0,-1.0,10.476,1.18155,1454,2656118 +65,insert,74.112,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,96.578,1.20956,1474,2723424 +66,search,4468.76,2094.56,1439.13,0.960153,126.878,-nan,-nan,0.89558,0.125732,-1.0,-1.0,11.084,1.20956,1474,2723424 +67,insert,44.184,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,72.561,1.22986,1486,2769021 +68,search,4494.57,2113.38,1470.48,0.988697,125.167,-nan,-nan,0.89762,0.124267,-1.0,-1.0,10.621,1.22986,1486,2769021 +69,insert,53.985,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,67.337,1.25489,1496,2821777 +70,search,4531.86,2130.53,1486.5,0.993484,129.665,-nan,-nan,0.89909,0.122725,-1.0,-1.0,16.807,1.25515,1497,2821777 +71,insert,14.271,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,28.407,1.26031,1501,2834921 +72,search,4572.56,2132.4,1494.18,0.99627,128.363,-nan,-nan,0.89948,0.122461,-1.0,-1.0,13.111,1.26031,1501,2834921 +73,insert,9.161,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,11.476,1.26346,1501,2842044 +74,search,4575.15,2137.57,1501.21,0.994503,135.608,-nan,-nan,0.89968,0.122193,-1.0,-1.0,12.549,1.26346,1501,2842044 +75,insert,24.862,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,29.118,1.26811,1504,2858890 +76,search,4580.6,2141.92,1509.77,0.992986,135.215,-nan,-nan,0.89957,0.122393,-1.0,-1.0,12.081,1.26811,1504,2858890 +77,insert,41.526,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,20.098,1.27752,1506,2882818 +78,search,4596.57,2151.78,1519.25,0.932619,145.801,-nan,-nan,0.89884,0.122929,-1.0,-1.0,12.062,1.27752,1506,2882818 +79,insert,492.984,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,25.947,1.30553,1510,2947806 +80,search,4641.52,2175.43,1546.06,1.02913,139.766,-nan,-nan,0.89863,0.122712,-1.0,-1.0,11.57,1.30553,1510,2947806 +81,insert,39.362,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,23.687,1.3183,1512,2976895 +82,search,4644.8,2190.83,1553.99,0.983914,138.342,-nan,-nan,0.90005,0.122001,-1.0,-1.0,11.292,1.3183,1512,2976895 +83,insert,19.547,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,33.19,1.32542,1516,2990682 +84,search,4653.19,2193.12,1550.59,0.972272,139.66,-nan,-nan,0.90062,0.121522,-1.0,-1.0,11.356,1.32542,1516,2990682 +85,insert,36.636,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,18.638,1.33859,1518,3025613 +86,search,4660.56,2211,1564.52,1.01627,143.713,-nan,-nan,0.90126,0.121111,-1.0,-1.0,11.673,1.33859,1518,3025613 +87,insert,607.447,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,671.305,1.54426,1616,3468632 +88,search,5056.66,2348.14,1745.1,0.946497,155.837,-nan,-nan,0.90433,0.118725,-1.0,-1.0,73.669,1.54425,1623,3468632 +89,insert,365.088,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,465.159,1.70346,1698,3831692 +90,search,5332.99,2428.18,1881.95,0.944953,162.431,-nan,-nan,0.90861,0.113148,-1.0,-1.0,109.458,1.70374,1709,3831692 +91,insert,35.131,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,32.804,1.71572,1712,3864067 +92,search,5405.22,2426.49,1892.13,0.995646,170.177,-nan,-nan,0.90887,0.112731,-1.0,-1.0,22.945,1.71572,1713,3864067 +93,insert,277.158,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,204.951,1.81717,1741,4103827 +94,search,5545.58,2502.77,1995.22,0.960374,165.399,-nan,-nan,0.90971,0.11168,-1.0,-1.0,34.843,1.81735,1743,4103827 +95,insert,18.45,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,43.911,1.82396,1748,4119898 +96,search,5488.54,2502.47,1934.66,1.00477,164.727,-nan,-nan,0.91021,0.111124,-1.0,-1.0,16.38,1.82396,1748,4119898 +97,insert,11.233,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,21.243,1.82672,1749,4129367 +98,search,5575.76,2504.75,2003.35,0.983863,182.147,-nan,-nan,0.9102,0.11094,-1.0,-1.0,17.265,1.82672,1749,4129367 +99,insert,6.196,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,15.974,1.82794,1749,4134502 +100,search,5564.68,2509.17,1992.64,1.01704,174.827,-nan,-nan,0.91025,0.110986,-1.0,-1.0,17.057,1.82794,1749,4134502 +101,insert,41.573,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,32.98,1.83914,1752,4164482 +102,search,5607.22,2522.22,2020.24,1.01543,177.963,-nan,-nan,0.91064,0.110746,-1.0,-1.0,32.121,1.83945,1754,4164482 +103,insert,21.739,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,27.47,1.84604,1756,4178601 +104,search,5552.33,2523.37,1979.55,1.02499,166.706,-nan,-nan,0.91037,0.110945,-1.0,-1.0,16.78,1.84604,1756,4178601 +105,insert,11.997,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.441,1.84951,1756,4187774 +106,search,5502.13,2529,1942.3,1.00011,165.528,-nan,-nan,0.91047,0.111072,-1.0,-1.0,16.687,1.84951,1756,4187774 +107,insert,17.671,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,15.858,1.85395,1756,4200109 +108,search,5614.97,2532.91,2034.31,0.934197,174.541,-nan,-nan,0.91047,0.111126,-1.0,-1.0,16.569,1.85395,1756,4200109 +109,insert,496.536,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,503.732,2.01388,1821,4557867 +110,search,5859.15,2619.59,2153.42,0.98492,183.649,-nan,-nan,0.91274,0.10931,-1.0,-1.0,59.328,2.01407,1826,4557867 +111,insert,31.428,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,54.16,2.02685,1832,4587252 +112,search,5722.92,2622.96,2008.63,1.09146,162.387,-nan,-nan,0.91365,0.109019,-1.0,-1.0,20.141,2.02685,1832,4587252 +113,insert,12.457,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,19.949,2.03082,1832,4600056 +114,search,5920.77,2629.62,2172.37,0.975266,189.908,-nan,-nan,0.91376,0.108877,-1.0,-1.0,22.97,2.03082,1832,4600056 +115,insert,45.195,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,68.69,2.04169,1838,4627422 +116,search,6090.07,2636.04,2191.62,0.960192,188.251,-nan,-nan,0.91416,0.108522,-1.0,-1.0,20.543,2.04169,1838,4627422 +117,insert,13.667,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,20.382,2.04667,1838,4639292 +118,search,6053.31,2643.37,2207.96,0.941323,193.414,-nan,-nan,0.91428,0.108144,-1.0,-1.0,33.415,2.04681,1839,4639292 +119,insert,5.446,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,21.964,2.04888,1839,4643423 +120,search,6042.47,2644.45,2196.42,0.983484,188.806,-nan,-nan,0.91429,0.108086,-1.0,-1.0,21.309,2.04888,1839,4643423 +121,insert,20.594,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,28.429,2.05583,1840,4657252 +122,search,6366.19,2650.74,2216.77,0.915279,192.121,-nan,-nan,0.91444,0.108016,-1.0,-1.0,28.087,2.05583,1840,4657252 +123,insert,361.121,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,470.504,2.18573,1887,4938477 +124,search,6593.9,2705.44,2310.93,1.00702,202.617,-nan,-nan,0.91526,0.108757,-1.0,-1.0,162.907,2.18696,1901,4938477 +125,insert,62.651,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,81.409,2.20563,1909,4980492 +126,search,6330.79,2689.82,2311.44,1.0071,200.734,-nan,-nan,0.91571,0.108446,-1.0,-1.0,54.755,2.20582,1912,4980492 +127,insert,60.052,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,77.525,2.22659,1921,5030515 +128,search,6391.66,2702.06,2393.08,0.950757,206.509,-nan,-nan,0.91624,0.108335,-1.0,-1.0,28.225,2.22664,1922,5030515 +129,delete,20.672,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,45.664,2.22483,1892,5009391 +130,search,6173.87,2692.8,2300.12,0.969073,201.703,-nan,-nan,0.91493,0.109158,-1.0,-1.0,23.774,2.22483,1892,5009391 +131,delete,5.341,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,23.556,2.22483,1892,5004093 +132,search,6222.88,2691.3,2307.15,0.960291,195.646,-nan,-nan,0.91493,0.109168,-1.0,-1.0,23.669,2.22483,1892,5004093 +133,delete,11.638,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.681,2.22483,1892,4991787 +134,search,6319.33,2678.55,2284.4,0.944475,192.706,-nan,-nan,0.91479,0.109417,-1.0,-1.0,23.492,2.22483,1892,4991787 +135,delete,18.621,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,51.131,2.22199,1889,4974857 +136,search,6267.71,2672.07,2274.59,0.950168,198.137,-nan,-nan,0.91493,0.108993,-1.0,-1.0,23.682,2.22199,1889,4974857 +137,delete,3.551,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,23.043,2.22199,1889,4971386 +138,search,6135.45,2670.67,2264.2,0.976552,199.879,-nan,-nan,0.91484,0.109115,-1.0,-1.0,23.131,2.22199,1889,4971386 +139,delete,7.075,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.73,2.22199,1889,4963487 +140,search,6255.36,2665.43,2258.19,0.964832,191.974,-nan,-nan,0.91463,0.10915,-1.0,-1.0,23.403,2.22199,1889,4963487 +141,delete,24.72,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,66.937,2.21814,1884,4941830 +142,search,6103.91,2654.75,2242.44,0.945736,196.792,-nan,-nan,0.91432,0.109425,-1.0,-1.0,23.241,2.21814,1884,4941830 +143,delete,18.434,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,89.951,2.21346,1881,4925657 +144,search,6173.3,2651.79,2235.72,0.956113,192.844,-nan,-nan,0.91449,0.109325,-1.0,-1.0,23.193,2.21346,1881,4925657 +145,delete,3.096,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,36.797,2.21243,1879,4922686 +146,search,6317.42,2652.15,2256.6,0.974268,191.809,-nan,-nan,0.91429,0.109456,-1.0,-1.0,25.638,2.21243,1879,4922686 +147,delete,15.105,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,23.507,2.21243,1879,4913636 +148,search,6297.68,2646.02,2245.99,0.981745,195.179,-nan,-nan,0.91421,0.109628,-1.0,-1.0,24.187,2.21243,1879,4913636 +149,delete,229.755,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1097.15,2.13431,1791,4717250 +150,search,5982.28,2659.84,2148.16,0.994014,194.037,-nan,-nan,0.91348,0.110839,-1.0,-1.0,51.501,2.13472,1795,4717250 +151,delete,163.736,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1076.04,2.0627,1707,4560269 +152,search,5742.72,2690.29,2078.93,0.98504,182.555,-nan,-nan,0.91203,0.111298,-1.0,-1.0,103.877,2.06456,1716,4560269 +153,delete,30.064,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,141.871,2.05314,1702,4521936 +154,search,5764.15,2668.31,2082.45,0.989946,187.56,-nan,-nan,0.91109,0.112262,-1.0,-1.0,47.999,2.054,1704,4521936 +155,delete,19.888,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,53.721,2.05131,1702,4502222 +156,search,5702.89,2653.95,2046.29,0.985664,176.835,-nan,-nan,0.91109,0.112556,-1.0,-1.0,23.013,2.05131,1702,4502222 +157,delete,48.022,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,194.882,2.03743,1692,4456039 +158,search,5679.42,2638.63,2022.64,0.974714,187.012,-nan,-nan,0.9103,0.113402,-1.0,-1.0,29.164,2.03757,1693,4456039 +159,delete,313.229,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1745.53,1.87962,1540,4143922 +160,search,5342.63,2727.37,1903.13,0.938314,168.37,-nan,-nan,0.90936,0.114122,-1.0,-1.0,164.018,1.88237,1557,4143922 +161,delete,49.433,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,56.236,1.87788,1554,4101445 +162,search,5256.49,2654.68,1869.35,0.949412,164.865,-nan,-nan,0.90946,0.113838,-1.0,-1.0,25.957,1.87797,1555,4101445 +163,delete,18.094,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,43.874,1.87572,1553,4080175 +164,search,5241.98,2634.23,1856.13,0.961747,164.409,-nan,-nan,0.90907,0.114248,-1.0,-1.0,20.717,1.87572,1553,4080175 +165,delete,33.206,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,101.111,1.86841,1548,4047313 +166,search,5200.23,2620.48,1828.15,0.969852,161.334,-nan,-nan,0.90907,0.113915,-1.0,-1.0,20.57,1.86841,1548,4047313 +167,delete,7.663,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,20.066,1.86813,1548,4040738 +168,search,5154.33,2614.41,1797.74,1.00728,156.924,-nan,-nan,0.90899,0.114089,-1.0,-1.0,21.372,1.86813,1548,4040738 +169,delete,19.35,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,75.445,1.86351,1543,4022674 +170,search,5180.75,2610.95,1824.08,0.989895,162.014,-nan,-nan,0.90917,0.113788,-1.0,-1.0,21.449,1.86351,1543,4022674 +171,delete,9.413,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,19.08,1.86335,1543,4015835 +172,search,5137.31,2601.98,1814.88,0.95135,156.338,-nan,-nan,0.90889,0.114082,-1.0,-1.0,32.57,1.86382,1544,4015835 +173,delete,35.789,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,28.193,1.86126,1543,3986424 +174,search,5139.56,2573.99,1800.7,0.957831,158.223,-nan,-nan,0.90863,0.114403,-1.0,-1.0,20.414,1.86126,1543,3986424 +175,delete,174.245,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,713.485,1.76769,1463,3804693 +176,search,4872.68,2601.26,1733.65,0.952756,155.905,-nan,-nan,0.90618,0.115333,-1.0,-1.0,72.885,1.76896,1470,3804693 +177,delete,14.147,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,59.708,1.76481,1467,3786352 +178,search,4891.45,2578.82,1721.18,0.960007,154.281,-nan,-nan,0.90611,0.115112,-1.0,-1.0,21.652,1.76481,1467,3786352 +179,delete,248.68,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,973.429,1.63587,1323,3556994 +180,search,4492.95,2667.94,1608.86,0.958026,144.687,-nan,-nan,0.8976,0.119639,-1.0,-1.0,113.414,1.63765,1334,3556994 +181,delete,28.711,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,52.795,1.63217,1331,3526824 +182,search,4479.13,2611.69,1598.06,0.984283,147.314,-nan,-nan,0.89765,0.119537,-1.0,-1.0,32.716,1.63214,1333,3526824 +183,delete,174.912,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,719.155,1.5443,1234,3350245 +184,search,4181.42,2660.31,1499.62,0.929557,135.305,-nan,-nan,0.88174,0.137083,-1.0,-1.0,82.931,1.5452,1243,3350245 +185,delete,11.65,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,18.613,1.54382,1240,3340234 +186,search,4191.33,2619.78,1488.06,0.92047,136.115,-nan,-nan,0.88693,0.130466,-1.0,-1.0,53.968,1.54422,1243,3340234 +187,delete,205.665,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,291.214,1.45723,1204,3150857 +188,search,4079.54,2627.6,1457.29,0.968674,129.879,-nan,-nan,0.89034,0.127356,-1.0,-1.0,62.354,1.45767,1210,3150857 +189,delete,6.968,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,15.007,1.4572,1210,3143609 +190,search,4083.33,2594.37,1448.14,0.968465,130.257,-nan,-nan,0.89007,0.127593,-1.0,-1.0,15.952,1.4572,1210,3143609 +191,delete,3.783,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.554,1.45683,1210,3141038 +192,search,4084.93,2592.33,1440.65,0.967038,127.735,-nan,-nan,0.89001,0.127553,-1.0,-1.0,16.508,1.45683,1210,3141038 +193,delete,71.104,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,154.749,1.43672,1193,3081734 +194,search,4029.34,2573.01,1421.82,0.890801,133.388,-nan,-nan,0.88948,0.12832,-1.0,-1.0,34.654,1.43709,1195,3081734 +195,delete,39.719,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,139.44,1.42064,1183,3043966 +196,search,3971.16,2555.16,1397.31,0.93881,130.796,-nan,-nan,0.88878,0.128897,-1.0,-1.0,36.577,1.42102,1185,3043966 +197,delete,38.677,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,56.572,1.41188,1183,3008145 +198,search,3959.37,2528.73,1378.79,0.91426,126.8,-nan,-nan,0.88826,0.12902,-1.0,-1.0,24.28,1.41215,1184,3008145 +199,delete,11.402,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,37.694,1.40915,1181,2999384 +200,search,3959.24,2526.77,1389.88,0.926275,128.491,-nan,-nan,0.88834,0.128971,-1.0,-1.0,22.968,1.40923,1182,2999384 +201,delete,7.293,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,37.332,1.40604,1180,2993528 +202,search,3950.49,2523.18,1372.69,0.931916,126.439,-nan,-nan,0.88821,0.128993,-1.0,-1.0,15.551,1.40604,1180,2993528 +203,delete,14.402,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.209,1.40533,1180,2980973 +204,search,3962.57,2509.24,1373.83,0.92538,122.851,-nan,-nan,0.88817,0.129028,-1.0,-1.0,15.636,1.40533,1180,2980973 +205,delete,23.899,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,41.905,1.39941,1171,2960291 +206,search,3893.34,2498.18,1349.04,0.960659,125.283,-nan,-nan,0.88676,0.129922,-1.0,-1.0,15.591,1.39941,1171,2960291 +207,delete,52.213,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,125.092,1.37669,1129,2920620 +208,search,3708.77,2513,1269.17,0.98803,109.681,-nan,-nan,0.88416,0.132068,-1.0,-1.0,11.886,1.37669,1129,2920620 +209,delete,19.344,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,51.617,1.36786,1121,2900501 +210,search,3626.68,2505.61,1231.94,1.09098,111.394,-nan,-nan,0.88237,0.133141,-1.0,-1.0,27.015,1.36821,1122,2900501 +211,delete,10.979,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,27.794,1.36505,1121,2891660 +212,search,5205.09,2497.8,1275.52,0.959387,111.152,-nan,-nan,0.88187,0.133377,-1.0,-1.0,19.38,1.36505,1121,2891660 +213,delete,27.519,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,71.577,1.3592,1117,2873257 +214,search,3865.96,2486.2,1323.75,0.903887,125.706,-nan,-nan,0.88117,0.133737,-1.0,-1.0,14.285,1.3592,1117,2873257 +215,delete,395.994,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1357.35,1.16219,933,2537571 +216,search,3222.31,2657.24,1152.5,0.94589,102.934,-nan,-nan,0.87554,0.136874,-1.0,-1.0,259.399,1.16844,957,2537571 +217,delete,209.973,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,813.686,1.05035,840,2308194 +218,search,2904.63,2652.79,1044.8,0.96584,92.8842,-nan,-nan,0.86986,0.142867,-1.0,-1.0,244.69,1.05529,860,2308194 +219,delete,18.495,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,41.716,1.05021,855,2285820 +220,search,2906.42,2550.53,1029.63,0.966664,93.1492,-nan,-nan,0.86836,0.144028,-1.0,-1.0,105.551,1.0503,864,2285820 +221,delete,193.586,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,620.026,0.940495,728,2082858 +222,search,2530.26,2622.43,904.714,0.90041,90.0116,-nan,-nan,0.85837,0.150245,-1.0,-1.0,95.821,0.942306,737,2082858 +223,delete,10.206,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,20.376,0.940115,735,2071207 +224,search,2508.28,2555.35,884.903,0.990844,85.9444,-nan,-nan,0.85682,0.151192,-1.0,-1.0,31.389,0.940432,736,2071207 +225,delete,5.31,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,19.328,0.93901,735,2065400 +226,search,2520.54,2547.76,884.844,0.913892,89.4254,-nan,-nan,0.85646,0.151252,-1.0,-1.0,11.912,0.93901,735,2065400 +227,delete,6.361,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,10.221,0.938724,735,2062105 +228,search,2521.43,2541.49,895.966,0.926843,82.9567,-nan,-nan,0.85621,0.151572,-1.0,-1.0,10.895,0.938724,735,2062105 +229,delete,23.131,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,41.47,0.933072,730,2039610 +230,search,2500.99,2521.25,879.472,0.964288,85.292,-nan,-nan,0.85587,0.151941,-1.0,-1.0,10.777,0.933072,730,2039610 +231,delete,13.38,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,34.758,0.927676,726,2027795 +232,search,2485.17,2522.09,869.296,0.900644,84.4392,-nan,-nan,0.85425,0.152922,-1.0,-1.0,11.52,0.927676,726,2027795 +233,delete,7.187,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,23.01,0.925643,725,2022859 +234,search,2491.34,2516.05,877.788,0.962138,81.4811,-nan,-nan,0.85426,0.152802,-1.0,-1.0,11.051,0.925643,725,2022859 +235,delete,6.751,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.186,0.924847,722,2016264 +236,search,2484.66,2506.24,867.155,0.908193,84.3323,-nan,-nan,0.85411,0.152761,-1.0,-1.0,10.972,0.924847,722,2016264 +237,delete,294.884,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,708.471,0.801818,608,1782866 +238,search,2163.34,2652.13,785.124,0.963902,76.3068,-nan,-nan,0.84687,0.159541,-1.0,-1.0,97.717,0.803651,617,1782866 +239,delete,18.222,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,62.486,0.792048,606,1758931 +240,search,2122.95,2601.9,759.864,1.02348,75.4475,-nan,-nan,0.84349,0.160427,-1.0,-1.0,26.194,0.792114,607,1758931 +241,delete,6.829,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,24.489,0.789734,605,1751275 +242,search,2124.32,2595.67,756.378,0.987941,74.222,-nan,-nan,0.8433,0.160536,-1.0,-1.0,9.049,0.789734,605,1751275 +243,delete,18.444,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,19.121,0.786902,603,1733264 +244,search,2108.07,2564.42,751.187,0.934967,71.9551,-nan,-nan,0.84141,0.161307,-1.0,-1.0,8.986,0.786902,603,1733264 +245,delete,10.512,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,33.126,0.783914,601,1722658 +246,search,2108.6,2556.56,750.249,0.928179,69.6817,-nan,-nan,0.84101,0.161257,-1.0,-1.0,9.034,0.783914,601,1722658 +247,delete,2.778,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,7.997,0.783893,601,1719601 +248,search,2106.69,2546.65,749.016,0.928909,72.4485,-nan,-nan,0.84063,0.161243,-1.0,-1.0,9.126,0.783893,601,1719601 +249,delete,8.929,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,21.93,0.781018,599,1711648 +250,search,2080.21,2547.53,741.967,1.00086,69.5811,-nan,-nan,0.83905,0.162415,-1.0,-1.0,9.491,0.781018,599,1711648 +251,delete,296.113,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,318.081,0.661145,516,1470624 +252,search,1855.65,2601.77,669.428,0.891225,62.9496,-nan,-nan,0.83577,0.163568,-1.0,-1.0,48.934,0.662017,520,1470624 +253,delete,27.426,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,53.145,0.652972,513,1442070 +254,search,1815.55,2544.87,646.314,0.99285,60.69,-nan,-nan,0.83341,0.165021,-1.0,-1.0,10.746,0.652972,513,1442070 +255,delete,40.315,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,94.667,0.636496,494,1405549 +256,search,1775.22,2579.27,639.926,0.906175,59.7011,-nan,-nan,0.83039,0.168087,-1.0,-1.0,9.772,0.636496,494,1405549 +257,insert,14.28,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,8.949,0.639346,494,1416288 +258,search,1780.53,2589.26,639.613,0.91383,61.9908,-nan,-nan,0.83085,0.167718,-1.0,-1.0,9.6,0.639346,494,1416288 +259,insert,34.154,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,55.089,0.650013,499,1443010 +260,search,1778.92,2610.5,642.719,0.91388,61.071,-nan,-nan,0.83011,0.168087,-1.0,-1.0,9.815,0.650013,499,1443010 +261,insert,7.598,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,9.199,0.651968,499,1447529 +262,search,1788.85,2628.2,649.531,0.905286,62.631,-nan,-nan,0.8309,0.167727,-1.0,-1.0,9.943,0.651968,499,1447529 +263,insert,150.195,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,133.467,0.699697,507,1569110 +264,search,1854.68,2809.97,694.638,0.876424,64.2551,-nan,-nan,0.83182,0.169497,-1.0,-1.0,95.869,0.699709,513,1569110 +265,insert,93.525,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,103.594,0.727706,524,1636119 +266,search,1928.42,2850.1,727.629,0.896463,67.9419,-nan,-nan,0.83796,0.165634,-1.0,-1.0,54.602,0.727739,527,1636119 +267,insert,40.101,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,49.174,0.740083,531,1665152 +268,search,1969.56,2879.53,745.666,0.887858,70.9218,-nan,-nan,0.84103,0.165134,-1.0,-1.0,37.979,0.740084,534,1665152 +269,insert,330.362,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,250.968,0.853001,555,1916952 +270,search,2088.76,3140.66,830.922,0.979276,76.5083,-nan,-nan,0.84236,0.163815,-1.0,-1.0,106.265,0.853688,564,1916952 +271,insert,3.158,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,19.451,0.854762,566,1920898 +272,search,2123.62,3057.04,830.939,0.887736,79.0532,-nan,-nan,0.84263,0.163666,-1.0,-1.0,77.196,0.854853,570,1920898 +273,insert,22.143,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.456,0.861784,572,1942757 +274,search,2148.09,3067.55,843.741,0.90569,82.8889,-nan,-nan,0.84556,0.160568,-1.0,-1.0,49.184,0.861905,575,1942757 +275,insert,464.525,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,542.082,1.04008,633,2328372 +276,search,2425.56,3315.68,986.072,0.926865,93.6758,-nan,-nan,0.85166,0.158041,-1.0,-1.0,207.098,1.04144,655,2328372 +277,insert,46.243,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,99.281,1.05765,668,2363257 +278,search,2495.31,3175.4,991.974,0.942719,92.6733,-nan,-nan,0.85397,0.156245,-1.0,-1.0,65.297,1.0577,674,2363257 +279,insert,25.786,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,48.021,1.06754,680,2388933 +280,search,2535.01,3145.14,1009.77,0.936905,93.0498,-nan,-nan,0.8549,0.15567,-1.0,-1.0,50.452,1.06783,685,2388933 +281,insert,361.164,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,383.58,1.20586,714,2684315 +282,search,2682.9,3248.13,1076.02,0.925667,102.788,-nan,-nan,0.85488,0.156405,-1.0,-1.0,193.772,1.20714,724,2684315 +283,insert,472.037,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,661.599,1.40157,810,3109157 +284,search,2984.65,3342.3,1190.21,0.936701,103.014,-nan,-nan,0.86294,0.149501,-1.0,-1.0,311.221,1.40287,844,3109157 +285,insert,11.331,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.974,1.40702,845,3122751 +286,search,3126.2,3213.48,1248.06,0.971081,114.496,-nan,-nan,0.86401,0.149061,-1.0,-1.0,52.337,1.40723,848,3122751 +287,insert,39.912,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,114.106,1.42425,857,3163679 +288,search,3030.1,3210.58,1258.04,0.97031,114.301,-nan,-nan,0.86428,0.148925,-1.0,-1.0,21.199,1.42425,859,3163679 +289,insert,174.462,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,324.388,1.56134,917,3472031 +290,search,3317.68,3292.11,1350.97,0.99248,121.242,-nan,-nan,0.86804,0.147939,-1.0,-1.0,272.948,1.56309,942,3472031 +291,insert,24.653,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,42.588,1.57097,947,3495577 +292,search,3480.88,3232.97,1394.44,0.981707,125.948,-nan,-nan,0.87076,0.145814,-1.0,-1.0,124.123,1.5712,957,3495577 +293,insert,18.312,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,52.411,1.58047,961,3515193 +294,search,3524.67,3202.36,1399.05,0.984173,127.978,-nan,-nan,0.87109,0.145969,-1.0,-1.0,98.847,1.58067,970,3515193 +295,insert,250.354,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,388.107,1.67397,1021,3723063 +296,search,3719.63,3198.42,1480.91,0.9343,130.964,-nan,-nan,0.87522,0.142628,-1.0,-1.0,140.467,1.67547,1036,3723063 +297,insert,4.094,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,21.352,1.67726,1037,3727399 +298,search,3770.39,3144.85,1487.46,0.93947,133.954,-nan,-nan,0.87586,0.142256,-1.0,-1.0,21.496,1.67734,1038,3727399 +299,insert,75.026,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,116.729,1.70086,1056,3788002 +300,search,3815.37,3142.3,1505.16,0.991111,129.856,-nan,-nan,0.87783,0.140215,-1.0,-1.0,14.739,1.70086,1056,3788002 +301,insert,711.948,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1151.94,1.96941,1200,4370866 +302,search,4411.25,3308.93,1796.27,0.927771,158.499,-nan,-nan,0.90189,0.122331,-1.0,-1.0,236.101,1.96972,1233,4370866 +303,insert,51.316,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,100.479,1.98875,1243,4420306 +304,search,4505.1,3165.42,1780.07,1.00229,152.747,-nan,-nan,0.90126,0.122996,-1.0,-1.0,51.223,1.98899,1247,4420306 +305,insert,357.459,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,525.415,2.1503,1287,4789669 +306,search,4734.69,3307.35,1914.79,0.964804,164.309,-nan,-nan,0.90386,0.120864,-1.0,-1.0,234.461,2.15158,1304,4789669 +307,insert,26.048,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,64.288,2.15939,1311,4815550 +308,search,4787.48,3262.94,1934.08,0.949036,163.629,-nan,-nan,0.90443,0.120826,-1.0,-1.0,137.265,2.15946,1318,4815550 +309,insert,10.153,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,25.824,2.16286,1320,4823345 +310,search,4716.47,3246.66,1920.54,0.975944,166.067,-nan,-nan,0.90474,0.120459,-1.0,-1.0,58.869,2.16286,1323,4823345 +311,insert,14.234,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.297,2.1694,1324,4843493 +312,search,4810.9,3246.86,1932.07,0.961382,163.584,-nan,-nan,0.90465,0.120696,-1.0,-1.0,34.03,2.16961,1327,4843493 +313,insert,43.667,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,121.153,2.18781,1340,4885489 +314,search,4834.66,3227.94,1931.34,0.981969,167.749,-nan,-nan,0.90472,0.12067,-1.0,-1.0,12.587,2.18781,1340,4885489 +315,insert,8.99,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,11.111,2.19087,1340,4892335 +316,search,4851.97,3229.15,1934.84,0.9724,171.36,-nan,-nan,0.90455,0.120828,-1.0,-1.0,12.396,2.19087,1340,4892335 +317,insert,49.366,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,82.615,2.20676,1350,4932996 +318,search,4901.76,3228.8,1958.07,0.944005,167.448,-nan,-nan,0.90515,0.120305,-1.0,-1.0,12.862,2.20676,1350,4932996 +319,insert,633.704,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,874.654,2.4201,1459,5430684 +320,search,5169.48,3337.87,2028.49,1.08163,167.372,-nan,-nan,0.90973,0.116803,-1.0,-1.0,214.674,2.42296,1487,5430684 +321,insert,45.793,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,112.017,2.43951,1502,5471239 +322,search,5247.36,3269.28,2009.9,1.12298,163.949,-nan,-nan,0.91116,0.11561,-1.0,-1.0,20.345,2.43968,1503,5471239 +323,insert,126.017,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,182.823,2.48445,1524,5575560 +324,search,5351.22,3298.63,2056.36,1.05913,168.933,-nan,-nan,0.91218,0.114537,-1.0,-1.0,52.625,2.48462,1529,5575560 +325,insert,1491.98,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,762.285,2.70948,1591,6069499 +326,search,5872.44,3440.28,2419.75,0.953453,207.755,-nan,-nan,0.91425,0.11297,-1.0,-1.0,367.756,2.71255,1622,6069499 +327,insert,75.937,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,140.14,2.74124,1638,6139647 +328,search,6019.08,3377.16,2463.69,0.942684,219.682,-nan,-nan,0.91586,0.111093,-1.0,-1.0,254.287,2.74312,1659,6139647 +329,insert,8.953,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.338,2.74521,1659,6146884 +330,search,6073.37,3340.18,2460.74,0.929441,223,-nan,-nan,0.9161,0.110782,-1.0,-1.0,131.826,2.74589,1671,6146884 +331,insert,47.619,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,106.486,2.76332,1682,6188816 +332,search,5913.15,3317.47,2310.06,1.05937,187.04,-nan,-nan,0.91632,0.110938,-1.0,-1.0,58.834,2.76382,1688,6188816 +333,insert,3.901,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,21.466,2.76497,1689,6190810 +334,search,6130.51,3302.21,2474.73,0.957747,224.101,-nan,-nan,0.91641,0.110775,-1.0,-1.0,15.637,2.76497,1689,6190810 +335,insert,49.511,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,98.866,2.78109,1702,6230108 +336,search,6167.41,3302.08,2491.02,0.954316,216.113,-nan,-nan,0.91697,0.110357,-1.0,-1.0,15.684,2.78109,1702,6230108 +337,insert,24.578,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,46.249,2.78848,1705,6249699 +338,search,6068.57,3305.24,2410.19,1.02507,201.097,-nan,-nan,0.91706,0.11031,-1.0,-1.0,15.866,2.78848,1705,6249699 +339,insert,56.579,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,97.613,2.80294,1717,6290226 +340,search,6251.32,3301,2513.74,0.956294,226.386,-nan,-nan,0.91803,0.109306,-1.0,-1.0,15.875,2.80294,1717,6290226 +341,insert,11.688,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,15.174,2.80687,1717,6297556 +342,search,6083.77,3304.81,2406.17,1.04631,199.812,-nan,-nan,0.91818,0.109279,-1.0,-1.0,61.21,2.80721,1720,6297556 +343,insert,36.475,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,84.635,2.8196,1729,6330843 +344,search,6248.54,3302.72,2516,0.970047,221.259,-nan,-nan,0.91845,0.109099,-1.0,-1.0,16.21,2.8196,1729,6330843 +345,insert,45.812,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,41.435,2.83251,1733,6370265 +346,search,6281.9,3317.48,2534.94,0.946145,222.455,-nan,-nan,0.91843,0.109172,-1.0,-1.0,16.17,2.83251,1733,6370265 +347,insert,615.67,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,878.088,3.03727,1846,6831086 +348,search,6466.39,3354.92,2607.98,1.05804,223.535,-nan,-nan,0.92184,0.106616,-1.0,-1.0,144.009,3.04049,1869,6831086 +349,insert,31.235,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,69.814,3.05756,1877,6876154 +350,search,6770.07,3333.27,2718.65,0.963157,241.855,-nan,-nan,0.92242,0.106231,-1.0,-1.0,78.874,3.05856,1882,6876154 +351,insert,444.702,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,719.657,3.24799,1963,7288266 +352,search,6809.96,3355.05,2781.75,1.0092,234.913,-nan,-nan,0.92211,0.107035,-1.0,-1.0,353.395,3.25198,1996,7288266 +353,insert,57.533,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,58.604,3.27016,2005,7333132 +354,search,6737.11,3310.48,2917.64,0.953575,254.695,-nan,-nan,0.92288,0.106379,-1.0,-1.0,66.167,3.27084,2014,7333132 +355,insert,216.084,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,509.919,3.43054,2108,7696838 +356,search,7356.4,3302.74,2964.54,1.01311,246.742,-nan,-nan,0.92465,0.104911,-1.0,-1.0,188.86,3.43166,2127,7696838 +357,insert,26.111,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,58.64,3.43982,2132,7714498 +358,search,7694.46,3270.07,3072.11,0.974918,268.417,-nan,-nan,0.92501,0.104806,-1.0,-1.0,72.24,3.44013,2136,7714498 +359,insert,13.767,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,40.473,3.4436,2138,7725755 +360,search,7420.81,3268.3,2942.82,1.06859,247.021,-nan,-nan,0.92527,0.104708,-1.0,-1.0,41.055,3.44364,2140,7725755 +361,insert,72.245,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,108.521,3.46786,2150,7789312 +362,search,7797.57,3275.97,3013.26,1.00553,266.174,-nan,-nan,0.92628,0.103674,-1.0,-1.0,59.562,3.46801,2153,7789312 +363,insert,23.523,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,51.925,3.4732,2156,7803163 +364,search,7769.07,3273.58,3100.46,0.959911,266.563,-nan,-nan,0.9262,0.103727,-1.0,-1.0,37.449,3.4735,2157,7803163 +365,insert,68.959,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,120.683,3.50032,2168,7863722 +366,search,7972.26,3280.32,3132.12,0.959428,276.069,-nan,-nan,0.92701,0.10321,-1.0,-1.0,70.967,3.50117,2172,7863722 +367,insert,36.396,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,101.301,3.51448,2182,7895271 +368,search,7921.59,3275.94,3153.66,0.965028,279.418,-nan,-nan,0.92761,0.102772,-1.0,-1.0,73.37,3.51513,2187,7895271 +369,insert,78.936,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,186.831,3.54127,2205,7961194 +370,search,7964.06,3277.22,3163.65,1.03215,278.991,-nan,-nan,0.92822,0.101962,-1.0,-1.0,64.212,3.54213,2208,7961194 +371,insert,12.037,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,33.089,3.54478,2209,7970239 +372,search,8516.98,3276.67,3165.71,1.00892,274.236,-nan,-nan,0.92855,0.101739,-1.0,-1.0,27.083,3.54478,2209,7970239 +373,insert,56.363,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,88.787,3.55899,2217,8010868 +374,search,9959.97,3280.33,3162.56,0.989672,274.802,-nan,-nan,0.92889,0.10133,-1.0,-1.0,39.469,3.55906,2218,8010868 +375,insert,43.074,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,85.927,3.57032,2224,8040698 +376,search,11252,3277.98,4004.77,0.773153,328.923,-nan,-nan,0.92883,0.101317,-1.0,-1.0,51.07,3.57053,2225,8040698 +377,insert,80.514,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,167.057,3.59673,2237,8104748 +378,search,10984.5,3284.57,3703.12,0.830653,323.944,-nan,-nan,0.92944,0.100792,-1.0,-1.0,32.915,3.59673,2237,8104748 +379,insert,8.771,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,36.662,3.59897,2238,8109755 +380,search,8310.39,3284.81,3670.94,0.847375,321.899,-nan,-nan,0.92948,0.100729,-1.0,-1.0,21.938,3.59897,2238,8109755 +381,insert,22.379,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,40.728,3.60881,2241,8130382 +382,search,6799.04,3290.02,3026.57,1.07178,256.706,-nan,-nan,0.92949,0.100682,-1.0,-1.0,21.657,3.60881,2241,8130382 +383,insert,25.739,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,68.979,3.61719,2248,8153290 +384,search,6607.82,3290.08,2910.76,1.1493,245.828,-nan,-nan,0.92958,0.100719,-1.0,-1.0,19.871,3.61719,2248,8153290 +385,delete,13.399,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,19.371,3.61719,2248,8138873 +386,search,6322.71,3284.48,2700.25,1.25694,224.586,-nan,-nan,0.92954,0.100798,-1.0,-1.0,21.106,3.61719,2248,8138873 +387,delete,18.681,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,122,3.61094,2243,8115069 +388,search,7603.67,3282.02,2918.05,1.14305,243.597,-nan,-nan,0.92981,0.100564,-1.0,-1.0,38.316,3.61113,2245,8115069 +389,delete,12.058,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,62.955,3.60887,2242,8101157 +390,search,7122.21,3274.12,2426.34,1.36244,200.847,-nan,-nan,0.92947,0.100616,-1.0,-1.0,30.997,3.60914,2243,8101157 +391,delete,67.747,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,438.603,3.57372,2211,8014644 +392,search,6934.31,3284.93,2327.29,1.46986,192.579,-nan,-nan,0.92901,0.100344,-1.0,-1.0,126.106,3.57513,2223,8014644 +393,delete,32.137,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,70.174,3.57216,2221,7978358 +394,search,7035.48,3248.01,2316.65,1.45456,196.482,-nan,-nan,0.92825,0.101069,-1.0,-1.0,41.546,3.57223,2223,7978358 +395,delete,24.207,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,173.946,3.56098,2215,7957094 +396,search,7029.54,3246.88,2392.96,1.40385,199.989,-nan,-nan,0.92804,0.101247,-1.0,-1.0,41.018,3.56141,2217,7957094 +397,delete,88.756,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,744.735,3.50092,2180,7823916 +398,search,7258.37,3254.57,2647.19,1.20546,216.002,-nan,-nan,0.92788,0.101241,-1.0,-1.0,123.152,3.50274,2190,7823916 +399,delete,5.717,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,58.809,3.50059,2188,7818430 +400,search,7317.85,3240.49,2614.33,1.2245,219.375,-nan,-nan,0.9278,0.101411,-1.0,-1.0,44.786,3.50103,2189,7818430 +401,delete,21.766,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,60.618,3.49705,2186,7800702 +402,search,7779.17,3232.72,2608.14,1.25248,219.646,-nan,-nan,0.92694,0.102691,-1.0,-1.0,25.38,3.49705,2186,7800702 +403,delete,243.986,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1651.94,3.36351,2079,7517858 +404,search,10490,3278.3,3081.8,0.924907,271.745,-nan,-nan,0.92496,0.104087,-1.0,-1.0,128.764,3.36642,2095,7517858 +405,delete,44.86,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,237.49,3.35226,2085,7451637 +406,search,6975.19,3223.2,2533.83,1.20341,205.506,-nan,-nan,0.9252,0.104017,-1.0,-1.0,49.248,3.3526,2087,7451637 +407,delete,86.914,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,582.834,3.30731,2054,7360417 +408,search,6805.75,3227.11,2490.82,1.23267,198.103,-nan,-nan,0.92445,0.104946,-1.0,-1.0,56.566,3.30809,2060,7360417 +409,delete,131.726,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,581.422,3.20732,2025,7131620 +410,search,6712.63,3205.17,2442.78,1.19439,197.941,-nan,-nan,0.92433,0.104829,-1.0,-1.0,108.229,3.20827,2032,7131620 +411,delete,246.847,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1592.16,3.09473,1935,6867617 +412,search,6500.61,3223.7,2352.71,1.19726,191.469,-nan,-nan,0.92418,0.105013,-1.0,-1.0,199.88,3.09853,1955,6867617 +413,delete,15.077,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,74.288,3.09355,1951,6850098 +414,search,6625.14,3187.44,2435.66,1.16785,201.184,-nan,-nan,0.92431,0.104867,-1.0,-1.0,32.152,3.09356,1952,6850098 +415,delete,68.682,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,480.811,3.06045,1926,6782921 +416,search,6514.53,3193.65,2406.96,1.19461,193.813,-nan,-nan,0.92399,0.105186,-1.0,-1.0,63.964,3.06126,1930,6782921 +417,delete,212.107,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1097.53,2.97239,1866,6562039 +418,search,6414.29,3189.42,2406.72,1.08947,195.276,-nan,-nan,0.9231,0.105314,-1.0,-1.0,189.743,2.97472,1879,6562039 +419,delete,27.807,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,41.302,2.97239,1877,6536285 +420,search,6441.52,3158.81,2404.45,1.09911,194.264,-nan,-nan,0.92349,0.105234,-1.0,-1.0,22.79,2.97239,1877,6536285 +421,delete,25.027,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,87.081,2.96205,1872,6510820 +422,search,6684.13,3158.8,2621.75,0.96842,230.983,-nan,-nan,0.92391,0.104579,-1.0,-1.0,34.807,2.96212,1873,6510820 +423,delete,215.535,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,628.916,2.88847,1814,6334168 +424,search,6489.04,3165.54,2546.06,0.989822,235.46,-nan,-nan,0.92257,0.105145,-1.0,-1.0,118.023,2.89051,1823,6334168 +425,delete,19.474,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,40.635,2.8887,1822,6316443 +426,search,6490.65,3146.51,2546.11,0.957333,225.064,-nan,-nan,0.92288,0.105253,-1.0,-1.0,22.789,2.8887,1822,6316443 +427,delete,63.584,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,60.966,2.88323,1819,6266345 +428,search,6453.44,3115.78,2511.01,0.958659,225.548,-nan,-nan,0.92244,0.105881,-1.0,-1.0,21.797,2.88323,1819,6266345 +429,delete,557.224,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,2543.05,2.66144,1596,5883847 +430,search,5926.21,3384.79,2418.77,0.935547,219.439,-nan,-nan,0.91064,0.113696,-1.0,-1.0,499.515,2.67126,1657,5883847 +431,delete,69.745,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,308.684,2.63392,1631,5801380 +432,search,5800.48,3214.99,2251.75,1.04425,192.462,-nan,-nan,0.90907,0.115458,-1.0,-1.0,99.302,2.63486,1640,5801380 +433,delete,225.372,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1090.7,2.53741,1565,5607567 +434,search,5615.36,3236.68,2208.56,0.984912,189.901,-nan,-nan,0.90576,0.117897,-1.0,-1.0,167.465,2.54168,1579,5607567 +435,delete,87.931,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,286.953,2.50908,1554,5512176 +436,search,5607.39,3191.84,2212.8,0.962684,200.727,-nan,-nan,0.9053,0.118105,-1.0,-1.0,174.743,2.51176,1562,5512176 +437,delete,11.648,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,55.958,2.50704,1560,5501141 +438,search,5519.96,3170.06,2133.36,1.02262,188.265,-nan,-nan,0.9052,0.118537,-1.0,-1.0,103.875,2.50704,1564,5501141 +439,delete,110.255,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,454.888,2.44382,1545,5369822 +440,search,5554.66,3174.7,2184.79,0.963067,202.11,-nan,-nan,0.90782,0.115544,-1.0,-1.0,120.383,2.44633,1553,5369822 +441,delete,28.05,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,53.492,2.44106,1550,5338985 +442,search,5512.97,3147.13,2128.91,1.00086,189.06,-nan,-nan,0.9072,0.116345,-1.0,-1.0,41.334,2.44108,1552,5338985 +443,delete,29.698,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,98.771,2.42699,1544,5307279 +444,search,5523.23,3147.04,2163.42,0.968176,189.954,-nan,-nan,0.9078,0.115715,-1.0,-1.0,35.39,2.42737,1546,5307279 +445,delete,41.985,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,94.737,2.41579,1541,5268382 +446,search,5506.72,3129.04,2143.9,0.951002,193.554,-nan,-nan,0.90761,0.116014,-1.0,-1.0,17.574,2.41579,1541,5268382 +447,delete,349.785,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,983.052,2.24036,1383,4922787 +448,search,4895.33,3239.82,1981.06,0.953832,170.538,-nan,-nan,0.90091,0.120346,-1.0,-1.0,175.582,2.24344,1399,4922787 +449,delete,30.952,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,104.11,2.23526,1390,4887227 +450,search,5040.08,3194.47,1980.42,0.910561,175.049,-nan,-nan,0.90127,0.120146,-1.0,-1.0,98.822,2.23677,1393,4887227 +451,delete,122.582,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,349.999,2.19352,1361,4795082 +452,search,4923.31,3193.35,1937.36,0.919689,169.789,-nan,-nan,0.90064,0.12119,-1.0,-1.0,88.807,2.19365,1365,4795082 +453,delete,358.232,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1402.52,2.04477,1245,4500175 +454,search,4553.62,3261.13,1813.11,0.941748,161.812,-nan,-nan,0.89663,0.124143,-1.0,-1.0,317.203,2.0515,1269,4500175 +455,delete,30.412,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,72.332,2.04331,1265,4462648 +456,search,4494.7,3196.97,1730.68,1.04412,146.843,-nan,-nan,0.89717,0.123658,-1.0,-1.0,88.854,2.04407,1271,4462648 +457,delete,6.793,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,24.339,2.04262,1270,4456761 +458,search,4571.44,3180.45,1804.42,0.964246,158.702,-nan,-nan,0.89697,0.123567,-1.0,-1.0,14.987,2.04262,1270,4456761 +459,delete,45.441,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,201.136,2.02011,1256,4419992 +460,search,4512.91,3190.04,1760.27,0.979904,155.252,-nan,-nan,0.89718,0.122965,-1.0,-1.0,36.747,2.02033,1258,4419992 +461,delete,5.275,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.998,2.02003,1258,4415725 +462,search,4527.99,3179.59,1768.03,0.95511,156.571,-nan,-nan,0.89771,0.122821,-1.0,-1.0,14.951,2.02003,1258,4415725 +463,delete,56.769,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,251.944,1.99514,1230,4370609 +464,search,4421.98,3225.74,1776.17,0.94472,161.865,-nan,-nan,0.89622,0.123792,-1.0,-1.0,32.635,1.99554,1232,4370609 +465,delete,23.72,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,46.296,1.98445,1226,4345244 +466,search,4375.37,3211.69,1694.1,0.982545,149.862,-nan,-nan,0.89448,0.125143,-1.0,-1.0,23.191,1.98467,1227,4345244 +467,delete,30.491,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,67.468,1.97683,1223,4319734 +468,search,4305.94,3197.13,1648.38,1.02547,141.488,-nan,-nan,0.89421,0.125262,-1.0,-1.0,14.514,1.97683,1223,4319734 +469,delete,20.704,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,51.383,1.96637,1217,4298361 +470,search,4417.13,3196.68,1745.85,0.937627,153.634,-nan,-nan,0.89306,0.125789,-1.0,-1.0,14.451,1.96637,1217,4298361 +471,delete,150.649,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,397.33,1.91272,1169,4188315 +472,search,4281.12,3242.5,1706.12,0.922692,156.967,-nan,-nan,0.89226,0.125864,-1.0,-1.0,120.308,1.91438,1180,4188315 +473,delete,127.49,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,423.125,1.86271,1140,4074567 +474,search,4168.78,3218.7,1658.13,0.964827,152.138,-nan,-nan,0.89039,0.126814,-1.0,-1.0,108.959,1.86441,1149,4074567 +475,delete,418.496,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1611.42,1.65922,984,3691698 +476,search,3693.85,3394.64,1511.17,0.922887,135.588,-nan,-nan,0.88208,0.131647,-1.0,-1.0,383.8,1.66581,1023,3691698 +477,delete,40.924,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,181.378,1.64545,1010,3642619 +478,search,3724.25,3235.96,1493.02,0.97218,134.463,-nan,-nan,0.88194,0.131655,-1.0,-1.0,117.382,1.64701,1020,3642619 +479,delete,245.182,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1256.27,1.54268,923,3421368 +480,search,3383.89,3336.37,1339.81,1.04599,116.766,-nan,-nan,0.87648,0.142482,-1.0,-1.0,407.254,1.55264,944,3421368 +481,delete,42.286,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,115.917,1.5364,934,3378034 +482,search,3392.72,3226.07,1321.01,1.02928,115.508,-nan,-nan,0.87855,0.139709,-1.0,-1.0,165.119,1.53696,940,3378034 +483,delete,315.582,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,946.037,1.4003,830,3115682 +484,search,3153.05,3341.49,1278.01,0.921464,117.384,-nan,-nan,0.87625,0.139827,-1.0,-1.0,288.602,1.40513,855,3115682 +485,delete,19.031,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,38.607,1.40036,852,3094629 +486,search,3167.43,3220.19,1267.1,0.982993,120.341,-nan,-nan,0.87714,0.139433,-1.0,-1.0,87.118,1.40117,859,3094629 +487,delete,7.665,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,12.937,1.4009,859,3086025 +488,search,3122.8,3187.43,1225.02,0.962306,105.307,-nan,-nan,0.87685,0.139646,-1.0,-1.0,15.719,1.4009,859,3086025 +489,delete,50.19,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,102.351,1.38948,853,3052105 +490,search,3148.59,3177.11,1252.74,0.928128,114.3,-nan,-nan,0.87619,0.140249,-1.0,-1.0,27.086,1.38965,854,3052105 +491,delete,20.632,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,28.5,1.38604,852,3038974 +492,search,3154.69,3168.2,1250.23,0.904875,117.847,-nan,-nan,0.87583,0.140492,-1.0,-1.0,14.545,1.38604,852,3038974 +493,delete,187.163,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,458.372,1.3115,793,2911063 +494,search,2974.37,3267.42,1196.59,0.936926,109.166,-nan,-nan,0.87365,0.141887,-1.0,-1.0,70.731,1.31218,799,2911063 +495,delete,23.863,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,65.626,1.30448,792,2888785 +496,search,2912.16,3238.16,1155.26,0.924685,106.022,-nan,-nan,0.8717,0.142806,-1.0,-1.0,24.588,1.30452,793,2888785 +497,delete,72.247,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,143.75,1.28237,778,2829718 +498,search,2926.54,3216.66,1147.88,1.01822,102.065,-nan,-nan,0.86987,0.143957,-1.0,-1.0,20.725,1.28248,779,2829718 +499,delete,18.337,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,34.102,1.28042,778,2816082 +500,search,2882.21,3200.22,1148.47,0.937005,98.604,-nan,-nan,0.8697,0.144089,-1.0,-1.0,12.744,1.28042,778,2816082 +501,delete,31.683,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,93.026,1.2693,770,2790880 +502,search,2880.69,3205.43,1140.79,0.944859,104.155,-nan,-nan,0.86956,0.144239,-1.0,-1.0,22.434,1.26939,771,2790880 +503,delete,17.939,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,28.233,1.26629,770,2774459 +504,search,2868.03,3184.47,1132.81,0.923681,101.729,-nan,-nan,0.86923,0.144694,-1.0,-1.0,38.1,1.26687,772,2774459 +505,delete,76.395,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,160.501,1.23505,753,2714683 +506,search,2827.97,3187.6,1116.04,0.955544,108.453,-nan,-nan,0.86776,0.1453,-1.0,-1.0,53.484,1.23592,756,2714683 +507,delete,47.616,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,77.66,1.22446,749,2680986 +508,search,2805.87,3173.92,1107.84,0.919727,102.299,-nan,-nan,0.86699,0.145583,-1.0,-1.0,23.262,1.22464,750,2680986 +509,delete,23.655,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,75.38,1.21547,745,2662966 +510,search,2774.08,3168.7,1094.19,0.92405,99.8279,-nan,-nan,0.86697,0.145321,-1.0,-1.0,38.675,1.21607,747,2662966 +511,delete,25.996,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,56.976,1.21035,742,2642855 +512,search,2750.39,3154.82,1087.65,0.908356,101.78,-nan,-nan,0.86512,0.146382,-1.0,-1.0,22.626,1.21064,743,2642855 +513,insert,410.054,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,382.081,1.31505,770,2906838 +514,search,4197.41,3287.01,1263.18,0.928532,112.515,-nan,-nan,0.86792,0.144679,-1.0,-1.0,92.617,1.31577,777,2906838 +515,insert,9.314,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,23.274,1.31796,778,2913746 +516,search,3053.49,3255.62,1225.68,0.905076,112.051,-nan,-nan,0.86811,0.144618,-1.0,-1.0,11.963,1.31796,778,2913746 +517,insert,24.947,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,37.534,1.32195,781,2936862 +518,search,2629.15,3281.46,909.081,1.33386,81.5704,-nan,-nan,0.86963,0.143432,-1.0,-1.0,12.368,1.32195,781,2936862 +519,insert,126.058,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,164.45,1.35524,793,3009732 +520,search,2678.8,3312.84,935.21,1.31857,83.4887,-nan,-nan,0.87109,0.143398,-1.0,-1.0,62.243,1.35633,801,3009732 +521,insert,14.221,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,23.8,1.36152,803,3025906 +522,search,2689.25,3293.24,951.685,1.24261,83.0405,-nan,-nan,0.87132,0.14344,-1.0,-1.0,17.301,1.36176,804,3025906 +523,insert,32.75,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,55.68,1.37724,810,3061899 +524,search,2716.75,3304.14,963.869,1.29259,83.0145,-nan,-nan,0.87195,0.143205,-1.0,-1.0,34.202,1.37767,814,3061899 +525,insert,33.475,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,55.41,1.3936,821,3101209 +526,search,2779.22,3299.06,999.956,1.34183,85.362,-nan,-nan,0.8719,0.142935,-1.0,-1.0,10.744,1.3936,821,3101209 +527,insert,407.719,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,565.275,1.57791,906,3522334 +528,search,3133.36,3451.61,1174.63,1.21736,101.431,-nan,-nan,0.88115,0.136557,-1.0,-1.0,154.374,1.57969,926,3522334 +529,insert,216.392,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,379.045,1.69791,986,3797294 +530,search,3494.85,3463.63,1352.43,1.13953,113.996,-nan,-nan,0.88934,0.130951,-1.0,-1.0,273.325,1.7003,1005,3797294 +531,insert,94.709,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,119.643,1.72708,1015,3853781 +532,search,3634.71,3418.89,1381.1,1.10883,119.234,-nan,-nan,0.89036,0.129858,-1.0,-1.0,174.437,1.72741,1023,3853781 +533,insert,28.763,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,67.439,1.7364,1028,3873352 +534,search,3746.09,3390.87,1486.36,1.08824,126.386,-nan,-nan,0.89029,0.129856,-1.0,-1.0,93.025,1.7364,1033,3873352 +535,insert,25.806,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,79.607,1.74404,1042,3893308 +536,search,3748.28,3358.79,1464.43,1.10509,124.704,-nan,-nan,0.89095,0.129461,-1.0,-1.0,68.761,1.74406,1047,3893308 +537,insert,4.544,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.604,1.74509,1047,3901271 +538,search,3765.83,3342.63,1469.94,1.07062,124.819,-nan,-nan,0.89132,0.129347,-1.0,-1.0,27.822,1.74539,1048,3901271 +539,insert,27.274,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,72.86,1.75392,1054,3925164 +540,search,3884.22,3345.65,1570.93,0.976927,139.261,-nan,-nan,0.8918,0.129055,-1.0,-1.0,13.099,1.75392,1054,3925164 +541,insert,288.32,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,519.889,1.93769,1127,4320915 +542,search,4084.86,3461.81,1670.9,1.01651,138.417,-nan,-nan,0.89573,0.126208,-1.0,-1.0,202.101,1.94017,1156,4320915 +543,insert,28.873,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,66.671,1.95381,1168,4360814 +544,search,4202.85,3373.14,1693.28,1.05137,139.602,-nan,-nan,0.89722,0.124989,-1.0,-1.0,97.05,1.95428,1181,4360814 +545,insert,5.346,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,25.415,1.95676,1184,4370220 +546,search,4241.93,3331.92,1701.85,1.00673,138.713,-nan,-nan,0.8975,0.124906,-1.0,-1.0,83.794,1.9572,1191,4370220 +547,insert,209.241,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,364.985,2.021,1239,4510675 +548,search,4567.81,3299.72,1849.74,0.947838,162.107,-nan,-nan,0.90004,0.122891,-1.0,-1.0,73.443,2.02165,1246,4510675 +549,insert,257.674,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,312.431,2.12122,1269,4744845 +550,search,4681.89,3336.1,1904.54,0.927239,168.101,-nan,-nan,0.89577,0.12691,-1.0,-1.0,132.637,2.12177,1277,4744845 +551,insert,27.507,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,26.652,2.13299,1278,4771433 +552,search,4714.65,3323.77,1912.82,0.956521,169.388,-nan,-nan,0.89601,0.126477,-1.0,-1.0,109.352,2.13329,1285,4771433 +553,insert,16.972,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,24.513,2.13754,1286,4782909 +554,search,4740.64,3317.78,1903.05,0.987529,166.893,-nan,-nan,0.89763,0.12497,-1.0,-1.0,93.398,2.13779,1293,4782909 +555,insert,590.088,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,888.21,2.31344,1425,5180322 +556,search,5192.21,3284.86,2104.19,0.946767,184.134,-nan,-nan,0.90288,0.120178,-1.0,-1.0,74.753,2.31367,1434,5180322 +557,insert,35.496,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,32.682,2.32339,1437,5203220 +558,search,5088.91,3262.23,1971.66,1.11496,164.422,-nan,-nan,0.90292,0.120111,-1.0,-1.0,21.822,2.32339,1438,5203220 +559,insert,9.132,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,28.811,2.32615,1440,5210154 +560,search,5244.83,3254.97,2098.99,0.975502,179.698,-nan,-nan,0.90276,0.12038,-1.0,-1.0,15.566,2.32615,1440,5210154 +561,insert,6.901,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,17.711,2.32748,1440,5215426 +562,search,5357.42,3257.23,2086.95,0.988507,182.967,-nan,-nan,0.90285,0.120276,-1.0,-1.0,14.475,2.32748,1440,5215426 +563,insert,42.684,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,85.641,2.34257,1453,5252726 +564,search,5750.36,3258.23,2121.53,0.997865,176.306,-nan,-nan,0.90351,0.119574,-1.0,-1.0,35.906,2.34291,1455,5252726 +565,insert,300.44,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,324.057,2.43018,1487,5447274 +566,search,5414.88,3299.14,2186,0.984106,190.227,-nan,-nan,0.90484,0.118567,-1.0,-1.0,146.234,2.43139,1499,5447274 +567,insert,18.843,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.598,2.43713,1500,5463135 +568,search,5450.98,3270.13,2188.45,0.990443,190.185,-nan,-nan,0.9047,0.11883,-1.0,-1.0,86.554,2.43763,1505,5463135 +569,insert,16.618,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,44.543,2.44201,1508,5478168 +570,search,5488.66,3263.24,2194.1,0.949507,195.226,-nan,-nan,0.90486,0.118672,-1.0,-1.0,30.574,2.44203,1509,5478168 +571,insert,21.508,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,21.812,2.44837,1510,5492309 +572,search,5483.59,3261.43,2199.61,0.973606,193.734,-nan,-nan,0.90452,0.118866,-1.0,-1.0,16.91,2.44837,1510,5492309 +573,insert,73.805,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,83.905,2.46859,1518,5554599 +574,search,5501.21,3281.59,2232.38,0.968093,197.332,-nan,-nan,0.90504,0.118751,-1.0,-1.0,37.625,2.46874,1520,5554599 +575,insert,66.537,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,125.606,2.48957,1528,5604500 +576,search,5552.39,3289.59,2237.96,0.93861,194.361,-nan,-nan,0.90504,0.119129,-1.0,-1.0,24.598,2.48971,1529,5604500 +577,insert,49.331,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,100.814,2.5027,1541,5638834 +578,search,5612.9,3286.42,2263.08,0.933446,203.447,-nan,-nan,0.90557,0.11875,-1.0,-1.0,43.297,2.50312,1544,5638834 +579,insert,921.812,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1049.24,2.77858,1686,6229778 +580,search,6198.2,3367.18,2533.78,0.948054,221.55,-nan,-nan,0.91155,0.113814,-1.0,-1.0,273.502,2.78126,1714,6229778 +581,insert,32.198,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,86.985,2.79252,1721,6261240 +582,search,6247.4,3304.33,2521.12,0.950074,221.225,-nan,-nan,0.91178,0.11357,-1.0,-1.0,62.298,2.79271,1723,6261240 +583,insert,29.668,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,46.764,2.80273,1727,6283315 +584,search,6294.17,3305.15,2540.07,0.977091,229.678,-nan,-nan,0.91193,0.113599,-1.0,-1.0,73.745,2.80329,1732,6283315 +585,insert,348.634,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,471.345,2.92397,1782,6556101 +586,search,6486.97,3336.12,2638.93,0.952909,232.137,-nan,-nan,0.91432,0.112018,-1.0,-1.0,140.904,2.92509,1795,6556101 +587,insert,50.283,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,94.562,2.94017,1805,6587187 +588,search,6518.19,3303.91,2636.88,0.946984,226.113,-nan,-nan,0.91442,0.111961,-1.0,-1.0,30.543,2.94017,1806,6587187 +589,insert,62.427,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,119.223,2.95659,1819,6631526 +590,search,6579.98,3299.38,2654.39,0.992715,231.502,-nan,-nan,0.91503,0.111588,-1.0,-1.0,46.33,2.95697,1822,6631526 +591,insert,630.219,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,960.175,3.16588,1946,7108942 +592,search,6976.57,3335.4,2792.79,0.980557,233.35,-nan,-nan,0.91895,0.108614,-1.0,-1.0,203.224,3.16824,1967,7108942 +593,insert,204.785,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,220.135,3.2526,1985,7303976 +594,search,7209.96,3341.94,2911.33,0.919127,252.608,-nan,-nan,0.91992,0.108033,-1.0,-1.0,225.724,3.25401,2003,7303976 +595,insert,7.768,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.231,3.25689,2003,7309244 +596,search,7284.99,3315.55,2932.25,0.913999,255.544,-nan,-nan,0.92024,0.107825,-1.0,-1.0,84.131,3.25729,2008,7309244 +597,insert,311.703,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,422.512,3.36054,2048,7542477 +598,search,8086.42,3353.63,3209.02,0.903918,283.145,-nan,-nan,0.92204,0.10616,-1.0,-1.0,163.802,3.36183,2061,7542477 +599,insert,136.898,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,308.085,3.40494,2095,7654438 +600,search,7725.67,3333.91,3126.17,0.944382,278.702,-nan,-nan,0.92289,0.105346,-1.0,-1.0,58.802,3.40555,2099,7654438 +601,insert,80.825,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,158.596,3.43443,2117,7717936 +602,search,7726.37,3327.24,3113.9,0.950857,280.943,-nan,-nan,0.92325,0.104945,-1.0,-1.0,98.633,3.43507,2121,7717936 +603,insert,10.421,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,39.171,3.43685,2121,7723521 +604,search,9026.73,3326.14,3185.6,0.916304,278.722,-nan,-nan,0.92326,0.104931,-1.0,-1.0,58.796,3.43685,2122,7723521 +605,insert,63.938,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,123.804,3.45496,2134,7767404 +606,search,7293.93,3325.32,3644.05,0.887783,291.846,-nan,-nan,0.92371,0.104463,-1.0,-1.0,17.728,3.45496,2134,7767404 +607,insert,41.398,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,43.45,3.47631,2139,7826115 +608,search,6400.15,3328.48,2991.45,1.01256,240.241,-nan,-nan,0.92344,0.104735,-1.0,-1.0,33.77,3.47661,2141,7826115 +609,insert,139.64,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,256.395,3.56466,2187,8036351 +610,search,6543.08,3333.72,3052.62,1.04986,246.967,-nan,-nan,0.92431,0.104408,-1.0,-1.0,57.398,3.56575,2196,8036351 +611,insert,14.244,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,39.248,3.57484,2201,8060364 +612,search,6611.43,3319.32,3071.02,1.07292,247.763,-nan,-nan,0.92453,0.104122,-1.0,-1.0,23.28,3.57502,2202,8060364 +613,insert,151.595,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,194.95,3.65807,2234,8256083 +614,search,6642.16,3343.8,3090.92,1.07635,246.281,-nan,-nan,0.92525,0.103876,-1.0,-1.0,61.755,3.65927,2241,8256083 +615,insert,224.735,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,472.06,3.82817,2314,8625707 +616,search,6924.73,3359.04,3243.95,1.07001,260.333,-nan,-nan,0.92696,0.101693,-1.0,-1.0,154.013,3.83139,2339,8625707 +617,insert,193.035,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,361.739,3.97728,2394,8949227 +618,search,8308.68,3357.09,3361.04,1.03692,269.194,-nan,-nan,0.92893,0.100305,-1.0,-1.0,158.401,3.97902,2415,8949227 +619,insert,165.097,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,263.688,4.0813,2453,9195551 +620,search,8599.9,3346.84,3443.01,1.05903,280.2,-nan,-nan,0.93015,0.0988606,-1.0,-1.0,131.083,4.08361,2473,9195551 +621,insert,26.135,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,51.8,4.096,2481,9232372 +622,search,8856.68,3324.85,3595.29,0.967755,309.678,-nan,-nan,0.93056,0.0985834,-1.0,-1.0,33.617,4.09611,2482,9232372 +623,insert,22.026,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,102.632,4.10599,2491,9253561 +624,search,8989.16,3317.5,3626.47,0.979616,317.024,-nan,-nan,0.9307,0.09854,-1.0,-1.0,29.194,4.10605,2492,9253561 +625,insert,94.028,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,194.258,4.14002,2513,9331230 +626,search,9051.39,3319.93,3652.93,0.944916,320.057,-nan,-nan,0.93104,0.0982309,-1.0,-1.0,50.333,4.14109,2518,9331230 +627,insert,40.412,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,51.341,4.1601,2525,9374063 +628,search,8809.06,3319.13,3520.75,0.992993,289.97,-nan,-nan,0.93116,0.098111,-1.0,-1.0,38.621,4.16019,2527,9374063 +629,insert,21.594,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,55.369,4.16604,2531,9387598 +630,search,9027.31,3314.86,3604.02,0.962741,306.666,-nan,-nan,0.9312,0.0981281,-1.0,-1.0,27.889,4.16604,2532,9387598 +631,insert,46.738,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,70.579,4.17799,2538,9421724 +632,search,9112.2,3311.61,3655.45,0.988235,317.289,-nan,-nan,0.93133,0.0979402,-1.0,-1.0,23.896,4.17799,2538,9421724 +633,insert,81.893,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,105.468,4.19351,2546,9461430 +634,search,9005.32,3319.16,3535.16,1.03552,298.877,-nan,-nan,0.93184,0.0973423,-1.0,-1.0,57.731,4.19418,2549,9461430 +635,insert,39.126,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,66.181,4.20128,2554,9479469 +636,search,8847.88,3313.36,3408.07,1.06638,271.81,-nan,-nan,0.93188,0.0973955,-1.0,-1.0,23.088,4.20128,2554,9479469 +637,insert,608.819,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,891.752,4.38232,2649,9885997 +638,search,9602.96,3342.58,3907.55,0.953936,342.251,-nan,-nan,0.93359,0.0967035,-1.0,-1.0,269.076,4.38526,2666,9885997 +639,insert,575.348,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,892.254,4.56333,2759,10292043 +640,search,10507.1,3349.81,4241.34,0.904714,377.715,-nan,-nan,0.93604,0.0942613,-1.0,-1.0,313.619,4.56821,2792,10292043 +641,delete,182.705,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1340.25,4.49191,2744,10096584 +642,search,9898.43,3314.72,3999.5,0.954243,356.012,-nan,-nan,0.93608,0.0938486,-1.0,-1.0,207.152,4.49672,2758,10096584 +643,delete,12.621,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,89.15,4.49331,2755,10084840 +644,search,12659,3298.38,4066.13,0.922694,351.789,-nan,-nan,0.93602,0.0939665,-1.0,-1.0,66.539,4.49375,2758,10084840 +645,delete,18.887,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,33.29,4.49375,2758,10069802 +646,search,9949.69,3287.36,3879.37,1.00881,330.537,-nan,-nan,0.93603,0.0940173,-1.0,-1.0,21.62,4.49375,2758,10069802 +647,delete,76.592,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,529.306,4.45581,2729,9990953 +648,search,9162.67,3293.7,3459.92,1.13966,271.225,-nan,-nan,0.93546,0.0939989,-1.0,-1.0,105.387,4.45765,2737,9990953 +649,delete,32.802,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,94.562,4.4531,2733,9951625 +650,search,9170.99,3277.39,3453.53,1.14992,272.191,-nan,-nan,0.93565,0.0941163,-1.0,-1.0,22.056,4.4531,2733,9951625 +651,delete,27.888,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,125.592,4.44462,2728,9927065 diff --git a/scripts/big_ann_perf_numbers/perf_debug_scan_0.14_worker_batch_tuning_breakdown.csv b/scripts/big_ann_perf_numbers/perf_debug_scan_0.14_worker_batch_tuning_breakdown.csv new file mode 100644 index 00000000..38c944e9 --- /dev/null +++ b/scripts/big_ann_perf_numbers/perf_debug_scan_0.14_worker_batch_tuning_breakdown.csv @@ -0,0 +1,2 @@ +step_num,step_type,latency_ms,worker_partition_size,worker_scan_time_ms,worker_scan_throughput,worker_result_time_ms,measured_ipc,cache_miss_rate,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +2,search,3056.05,37.3917,337.096,0.511741,602.905,-nan,-nan,0.83796,0.13696,-1.0,-1.0,22.208,0.0184881,1000,38806 diff --git a/scripts/big_ann_perf_numbers/perf_debug_scan_0.14_worker_batch_tuning_lower.csv b/scripts/big_ann_perf_numbers/perf_debug_scan_0.14_worker_batch_tuning_lower.csv new file mode 100644 index 00000000..b840a2d9 --- /dev/null +++ b/scripts/big_ann_perf_numbers/perf_debug_scan_0.14_worker_batch_tuning_lower.csv @@ -0,0 +1,1280 @@ +step_num,step_type,latency_ms,worker_partition_size,worker_scan_time_ms,worker_scan_throughput,worker_result_time_ms,measured_ipc,cache_miss_rate,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +2,search,3239.02,37.4251,357.034,0.493315,641.35,-nan,-nan,0.844,0.1346,-1.0,-1.0,6.551,0.0184881,1000,38806 +3,insert,25.368,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.157,0.0226893,995,49334 +4,search,2488.24,65.147,196.543,1.11729,190.883,-nan,-nan,0.85634,0.133964,-1.0,-1.0,22.186,0.0226836,988,49334 +5,insert,19.622,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,169.101,0.032957,974,73557 +6,search,2350.69,192.202,188.762,1.59827,101.731,-nan,-nan,0.92009,0.107539,-1.0,-1.0,130.653,0.0330313,976,73557 +7,insert,24.303,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,136.573,0.0431297,975,95766 +8,search,2482.21,240.917,203.001,1.42565,101.501,-nan,-nan,0.9186,0.108923,-1.0,-1.0,85.887,0.0433072,978,95766 +9,insert,3.381,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,75.798,0.0450273,978,100025 +10,search,2381.78,249.211,206.812,1.42462,101.247,-nan,-nan,0.9196,0.106614,-1.0,-1.0,80.907,0.0450497,980,100025 +11,insert,8.515,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,17.308,0.0500298,983,111417 +12,search,2454.36,285.67,212.925,1.18862,126.949,-nan,-nan,0.91799,0.108448,-1.0,-1.0,23.612,0.0500294,985,111417 +13,insert,28.768,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,6.276,0.0610503,985,137139 +14,search,2464.69,326.778,242.915,1.11263,112.087,-nan,-nan,0.91447,0.110692,-1.0,-1.0,15.99,0.0610625,989,137139 +15,insert,14.996,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,8.747,0.0695942,990,156710 +16,search,2489.49,357.432,257.646,1.10803,103.857,-nan,-nan,0.91224,0.110953,-1.0,-1.0,6.546,0.0695942,990,156710 +17,insert,4.064,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,8.162,0.0716893,991,161773 +18,search,2429.11,375.625,256.253,1.08406,103.661,-nan,-nan,0.91322,0.110943,-1.0,-1.0,8.383,0.0717064,992,161773 +19,insert,30.481,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,8.719,0.0784282,993,177161 +20,search,2448.18,413.973,278.293,1.15302,99.1912,-nan,-nan,0.91811,0.107416,-1.0,-1.0,9.051,0.0784282,994,177161 +21,insert,324.191,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,161.699,0.201152,1037,448898 +22,search,2693.54,829.028,491.659,1.01798,77.3204,-nan,-nan,0.90318,0.111969,-1.0,-1.0,44.068,0.201151,1044,448898 +23,insert,394.341,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,293.323,0.328245,1094,733493 +24,search,3036.7,1151.67,702.744,0.995295,84.6762,-nan,-nan,0.89874,0.113726,-1.0,-1.0,90.338,0.328429,1112,733493 +25,insert,36.072,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,35.727,0.345909,1118,777443 +26,search,2990.88,1120.29,672.05,1.03339,77.8536,-nan,-nan,0.89684,0.115357,-1.0,-1.0,17.728,0.346002,1120,777443 +27,insert,28.516,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.763,0.358141,1121,805394 +28,search,3046.89,1147.7,695.02,1.04244,71.0955,-nan,-nan,0.89761,0.114545,-1.0,-1.0,9.002,0.358141,1121,805394 +29,insert,55.221,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,54.638,0.385159,1131,866391 +30,search,2988.23,1209.87,740.95,1.00112,72.9892,-nan,-nan,0.90032,0.113898,-1.0,-1.0,18.417,0.385159,1133,866391 +31,insert,448.111,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,332.948,0.554264,1191,1239816 +32,search,3353.37,1495.98,923.705,0.991814,75.0187,-nan,-nan,0.89218,0.120469,-1.0,-1.0,69.733,0.554263,1198,1239816 +33,insert,46.191,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,24.169,0.574814,1203,1291211 +34,search,3350.85,1498.08,917.448,1.00292,72.914,-nan,-nan,0.89213,0.120177,-1.0,-1.0,56.957,0.574941,1208,1291211 +35,insert,29.373,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,30.295,0.586937,1214,1324978 +36,search,3331.52,1521.07,966.584,0.926052,75.8825,-nan,-nan,0.89341,0.11922,-1.0,-1.0,39.033,0.586948,1217,1324978 +37,insert,57.408,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,24.283,0.605487,1220,1371885 +38,search,3343.68,1549.12,998.988,0.97988,78.3444,-nan,-nan,0.89441,0.11829,-1.0,-1.0,13.733,0.605487,1221,1371885 +39,insert,12.916,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,8.388,0.608722,1221,1379335 +40,search,3318.76,1550.37,989.235,0.975417,86.3315,-nan,-nan,0.89449,0.118777,-1.0,-1.0,8.823,0.608722,1221,1379335 +41,insert,45.764,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,28.185,0.623868,1225,1413312 +42,search,3364.19,1575.61,1000.7,0.987989,76.259,-nan,-nan,0.89563,0.117823,-1.0,-1.0,5.993,0.623868,1225,1413312 +43,insert,7.366,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,6.312,0.627645,1225,1423411 +44,search,3423.3,1588.91,995.033,0.996097,67.0249,-nan,-nan,0.8958,0.118005,-1.0,-1.0,8.893,0.627645,1225,1423411 +45,insert,172.698,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.959,0.641578,1230,1457559 +46,search,3373.28,1610.72,968.708,1.02897,76.0286,-nan,-nan,0.89681,0.117022,-1.0,-1.0,8.742,0.641578,1230,1457559 +47,insert,197.627,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,199.281,0.748462,1261,1688593 +48,search,3558.05,1744.31,1116.74,0.992678,79.6673,-nan,-nan,0.89773,0.118657,-1.0,-1.0,56.707,0.74846,1271,1688593 +49,insert,18.387,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.748,0.76251,1274,1723505 +50,search,3606.29,1746.5,1105.27,1.01215,81.4916,-nan,-nan,0.89881,0.117586,-1.0,-1.0,32.53,0.76251,1280,1723505 +51,insert,298.56,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,299.64,0.905831,1328,2035040 +52,search,3646.86,1900.84,1239.21,0.942485,92.116,-nan,-nan,0.90108,0.116045,-1.0,-1.0,24.097,0.906126,1333,2035040 +53,insert,28.237,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,17.899,0.92353,1336,2078341 +54,search,3222.39,1919.19,1179.75,1.05211,102.982,-nan,-nan,0.90223,0.115801,-1.0,-1.0,6.52,0.92353,1336,2078341 +55,insert,199.364,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,273.513,1.07194,1395,2399905 +56,search,4016.56,2079.68,1290.64,1.02876,104.923,-nan,-nan,0.90345,0.117146,-1.0,-1.0,105.482,1.07206,1411,2399905 +57,insert,23.742,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,21.379,1.07953,1414,2419836 +58,search,4161.97,2035.15,1304.06,1.0911,100.361,-nan,-nan,0.90193,0.118316,-1.0,-1.0,40.666,1.07955,1418,2419836 +59,insert,212.387,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,134.414,1.18011,1433,2643083 +60,search,3922.69,2091.58,1426.44,0.96094,114.17,-nan,-nan,0.8957,0.12527,-1.0,-1.0,29.111,1.18025,1437,2643083 +61,insert,7.494,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,7.07,1.18439,1437,2653064 +62,search,4174.03,2092.84,1433.79,0.999942,120.149,-nan,-nan,0.89566,0.125219,-1.0,-1.0,6.565,1.18439,1437,2653064 +63,insert,2.264,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,6.214,1.18568,1437,2656118 +64,search,3831.67,2094.01,1455.05,1.01849,119.298,-nan,-nan,0.89579,0.125109,-1.0,-1.0,6.614,1.18568,1437,2656118 +65,insert,41.662,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,52.378,1.21047,1453,2723424 +66,search,3624.52,2126.81,1415.59,1.03841,119.033,-nan,-nan,0.89669,0.12415,-1.0,-1.0,8.637,1.21061,1454,2723424 +67,insert,23.692,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,48.871,1.23206,1469,2769021 +68,search,3659.36,2131.9,1436.3,1.05355,120.01,-nan,-nan,0.89779,0.123401,-1.0,-1.0,16.706,1.23223,1473,2769021 +69,insert,24.821,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,39.243,1.25341,1484,2821777 +70,search,3695.22,2134.13,1451.23,1.05794,124.672,-nan,-nan,0.89908,0.122793,-1.0,-1.0,10.167,1.25367,1485,2821777 +71,insert,8.385,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,11.34,1.25929,1487,2834921 +72,search,4325.33,2142.27,1415.32,1.05746,117.452,-nan,-nan,0.90003,0.12229,-1.0,-1.0,16.161,1.25935,1488,2834921 +73,insert,7.535,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,17.589,1.26219,1489,2842044 +74,search,4570.26,2143.59,1543.09,0.993555,121.9,-nan,-nan,0.89981,0.122471,-1.0,-1.0,12.545,1.26219,1489,2842044 +75,insert,25.834,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.791,1.26926,1490,2858890 +76,search,4574.79,2156.74,1546.15,0.97941,131.771,-nan,-nan,0.90005,0.122329,-1.0,-1.0,11.288,1.26926,1490,2858890 +77,insert,35.561,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,17.788,1.27844,1491,2882818 +78,search,4615.18,2167.85,1564.21,0.939767,135.21,-nan,-nan,0.89984,0.122496,-1.0,-1.0,13.272,1.27844,1491,2882818 +79,insert,481.218,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.99,1.30742,1492,2947806 +80,search,4517.42,2200.72,1502.66,1.09335,124.85,-nan,-nan,0.8995,0.122604,-1.0,-1.0,11.711,1.30742,1492,2947806 +81,insert,43.179,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,39.441,1.32074,1497,2976895 +82,search,4684.37,2208.95,1605.37,0.924379,145.748,-nan,-nan,0.90072,0.121644,-1.0,-1.0,18.958,1.3208,1498,2976895 +83,insert,16.358,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,27.67,1.3266,1501,2990682 +84,search,4547.94,2210.08,1610.83,0.975595,141.36,-nan,-nan,0.90136,0.121149,-1.0,-1.0,13.405,1.32668,1502,2990682 +85,insert,24.411,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,18.028,1.34056,1506,3025613 +86,search,4094.95,2221.68,1509.22,1.02205,130.943,-nan,-nan,0.90185,0.120941,-1.0,-1.0,11.399,1.34056,1506,3025613 +87,insert,606.709,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,638.653,1.54251,1595,3468632 +88,search,4921.17,2374.19,1760.66,1.00098,147.64,-nan,-nan,0.90522,0.117856,-1.0,-1.0,86.125,1.54251,1605,3468632 +89,insert,364.446,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,307.623,1.70253,1677,3831692 +90,search,5332.64,2472.17,1946.52,0.967054,159.683,-nan,-nan,0.90929,0.113609,-1.0,-1.0,48.134,1.70253,1683,3831692 +91,insert,29.098,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,21.404,1.71237,1685,3864067 +92,search,5335.62,2477.16,1916.86,0.968151,162.061,-nan,-nan,0.90925,0.113488,-1.0,-1.0,13.903,1.71237,1685,3864067 +93,insert,210.068,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,165.551,1.8181,1715,4103827 +94,search,5600.08,2542.53,2065.02,0.927304,184.717,-nan,-nan,0.91003,0.112621,-1.0,-1.0,41.096,1.81861,1718,4103827 +95,insert,14.982,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,18.433,1.823,1719,4119898 +96,search,5477.38,2548.23,1978.07,1.05451,162.504,-nan,-nan,0.91037,0.112289,-1.0,-1.0,16.248,1.823,1719,4119898 +97,insert,9.692,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,34.187,1.82599,1722,4129367 +98,search,5442.4,2547.51,1924.89,1.03489,159.298,-nan,-nan,0.91056,0.112102,-1.0,-1.0,23.581,1.82619,1723,4129367 +99,insert,6.962,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.909,1.82783,1723,4134502 +100,search,5597.96,2549.3,2062.75,0.969111,184.331,-nan,-nan,0.91068,0.111999,-1.0,-1.0,15.915,1.82783,1723,4134502 +101,insert,36.206,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,41.113,1.83822,1727,4164482 +102,search,5507.75,2562.36,2070.23,0.951069,181.729,-nan,-nan,0.91064,0.11203,-1.0,-1.0,15.905,1.83822,1727,4164482 +103,insert,16.916,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,45.014,1.84428,1732,4178601 +104,search,5579.7,2559.78,2029.35,0.999137,170.795,-nan,-nan,0.91084,0.11206,-1.0,-1.0,15.866,1.84428,1732,4178601 +105,insert,9.308,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,21.508,1.8465,1733,4187774 +106,search,5508.6,2564.05,1975.38,0.998379,161.914,-nan,-nan,0.91085,0.112368,-1.0,-1.0,16.772,1.8465,1733,4187774 +107,insert,19.42,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.175,1.85099,1733,4200109 +108,search,4853.57,2568.7,2083.29,0.942483,179.987,-nan,-nan,0.91059,0.112565,-1.0,-1.0,10.957,1.85099,1733,4200109 +109,insert,268.984,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,353.487,2.01503,1806,4557867 +110,search,5764.89,2652.85,2176.41,0.964127,183.428,-nan,-nan,0.91289,0.110385,-1.0,-1.0,101.807,2.01605,1818,4557867 +111,insert,28.423,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,69.688,2.02776,1827,4587252 +112,search,5942.74,2631.78,2200.08,0.966084,184.989,-nan,-nan,0.91342,0.109909,-1.0,-1.0,24.935,2.02776,1828,4587252 +113,insert,13.455,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,30.299,2.03296,1830,4600056 +114,search,5886.97,2630.34,2126.88,0.991812,175.459,-nan,-nan,0.91374,0.109701,-1.0,-1.0,20.094,2.03296,1830,4600056 +115,insert,29.989,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,55.753,2.04262,1836,4627422 +116,search,5974.57,2636.82,2191.19,0.990823,183.027,-nan,-nan,0.9144,0.109338,-1.0,-1.0,31.072,2.04287,1837,4627422 +117,insert,13.504,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,46.542,2.04819,1840,4639292 +118,search,5949.29,2636.57,2165.42,1.01338,181.97,-nan,-nan,0.91432,0.109371,-1.0,-1.0,23.314,2.04819,1840,4639292 +119,insert,5.368,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,20.807,2.0492,1840,4643423 +120,search,6060.09,2638.79,2263.57,0.97286,199.949,-nan,-nan,0.91438,0.109429,-1.0,-1.0,21.5,2.0492,1840,4643423 +121,insert,17.716,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,20.694,2.0547,1840,4657252 +122,search,6060.43,2646.35,2268.34,0.978382,197.196,-nan,-nan,0.91461,0.109221,-1.0,-1.0,21.499,2.0547,1840,4657252 +123,insert,400.891,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,457.173,2.18718,1885,4938477 +124,search,6270.59,2708.85,2372.8,0.960018,206.372,-nan,-nan,0.91551,0.108998,-1.0,-1.0,169.289,2.18801,1901,4938477 +125,insert,60.857,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,77.422,2.20631,1910,4980492 +126,search,6297.01,2684.65,2363.09,0.913016,206.927,-nan,-nan,0.91578,0.109018,-1.0,-1.0,93.82,2.20686,1919,4980492 +127,insert,65.32,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,94.677,2.22905,1932,5030515 +128,search,6285.35,2670.76,2316.4,1.00421,191.923,-nan,-nan,0.91628,0.108731,-1.0,-1.0,38.75,2.22907,1934,5030515 +129,delete,19,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,52.595,2.22697,1901,5009391 +130,search,6206.9,2663.29,2303.53,0.948941,196.303,-nan,-nan,0.91474,0.1097,-1.0,-1.0,24.941,2.22697,1901,5009391 +131,delete,5.103,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,24.09,2.22697,1901,5004093 +132,search,6239.44,2659.88,2330.52,0.933567,200.013,-nan,-nan,0.9148,0.109624,-1.0,-1.0,24.584,2.22697,1901,5004093 +133,delete,11.991,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,31.917,2.22617,1900,4991787 +134,search,6256.17,2650.47,2333.63,0.959278,204.392,-nan,-nan,0.91468,0.109914,-1.0,-1.0,24.479,2.22617,1900,4991787 +135,delete,17.271,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,48.595,2.22358,1897,4974857 +136,search,6121.25,2643.61,2234.65,1.00228,185.537,-nan,-nan,0.91447,0.10983,-1.0,-1.0,24.585,2.22358,1897,4974857 +137,delete,3.223,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,23.963,2.22358,1897,4971386 +138,search,6199.54,2640.46,2296.19,0.952652,195.776,-nan,-nan,0.91441,0.109872,-1.0,-1.0,24.711,2.22358,1897,4971386 +139,delete,9.49,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,24.705,2.22358,1897,4963487 +140,search,6239.46,2635.72,2315.73,0.932836,199.945,-nan,-nan,0.9144,0.109995,-1.0,-1.0,27.144,2.22358,1897,4963487 +141,delete,40.931,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,104.844,2.21723,1890,4941830 +142,search,6116.81,2629.62,2230.89,0.968625,182.233,-nan,-nan,0.91429,0.110094,-1.0,-1.0,24.336,2.21723,1890,4941830 +143,delete,17.801,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,106.489,2.2119,1886,4925657 +144,search,6241.41,2626.18,2314.91,0.954353,206.691,-nan,-nan,0.91456,0.109763,-1.0,-1.0,24.75,2.2119,1886,4925657 +145,delete,3.511,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,23.53,2.2119,1886,4922686 +146,search,6171.69,2625.56,2280.18,0.95377,193.989,-nan,-nan,0.91446,0.109852,-1.0,-1.0,24.855,2.2119,1886,4922686 +147,delete,14.843,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,31.69,2.21112,1885,4913636 +148,search,5968.34,2618.4,2105.17,1.09628,169.414,-nan,-nan,0.91408,0.110126,-1.0,-1.0,25.277,2.21112,1885,4913636 +149,delete,223.864,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1302.35,2.12677,1783,4717250 +150,search,5884.96,2661.2,2206.16,0.937183,200.538,-nan,-nan,0.91312,0.110701,-1.0,-1.0,84.428,2.12769,1790,4717250 +151,delete,159.894,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1075.16,2.05462,1703,4560269 +152,search,5568.99,2679.2,2064.38,1.00481,172.801,-nan,-nan,0.91218,0.112074,-1.0,-1.0,127.943,2.05722,1715,4560269 +153,delete,27.506,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,128.201,2.04439,1702,4521936 +154,search,5546.05,2659.42,2030.95,0.994625,174.079,-nan,-nan,0.91132,0.112694,-1.0,-1.0,23.197,2.04439,1702,4521936 +155,delete,23.292,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,52.073,2.03931,1699,4502222 +156,search,5619.6,2650.09,2110,0.973728,191.059,-nan,-nan,0.91081,0.112923,-1.0,-1.0,32.594,2.03955,1700,4502222 +157,delete,41.423,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,183.427,2.0254,1688,4456039 +158,search,5480.81,2638.31,1995.63,1.0085,171.259,-nan,-nan,0.91089,0.113378,-1.0,-1.0,22.469,2.0254,1688,4456039 +159,delete,299.097,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1835.36,1.87414,1527,4143922 +160,search,4997.27,2749.53,1857.87,1.0208,151.177,-nan,-nan,0.90946,0.113899,-1.0,-1.0,261.886,1.88039,1562,4143922 +161,delete,41.329,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,72.183,1.8742,1558,4101445 +162,search,4951.31,2633.96,1735.78,1.10226,136.504,-nan,-nan,0.90957,0.113751,-1.0,-1.0,21.404,1.8742,1558,4101445 +163,delete,19.045,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,45.495,1.87226,1555,4080175 +164,search,5152.87,2617.81,1911.65,0.940008,171.623,-nan,-nan,0.90901,0.114164,-1.0,-1.0,21.459,1.87226,1555,4080175 +165,delete,30.365,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,105.488,1.86473,1549,4047313 +166,search,5104.63,2606.38,1884.37,0.940985,166.942,-nan,-nan,0.90922,0.113894,-1.0,-1.0,21.046,1.86473,1549,4047313 +167,delete,6.923,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,20.665,1.8645,1549,4040738 +168,search,5013.91,2601.87,1825.3,1.01188,149.682,-nan,-nan,0.90932,0.113879,-1.0,-1.0,21.053,1.8645,1549,4040738 +169,delete,22.424,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,48.181,1.86229,1547,4022674 +170,search,5083.86,2590.93,1876.55,0.939891,164.343,-nan,-nan,0.90937,0.113885,-1.0,-1.0,21.122,1.86229,1547,4022674 +171,delete,6.422,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,20.966,1.86229,1547,4015835 +172,search,5083.46,2584.95,1874.79,0.911814,162.678,-nan,-nan,0.90922,0.113929,-1.0,-1.0,21.08,1.86229,1547,4015835 +173,delete,35.471,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,32.943,1.85826,1546,3986424 +174,search,4968.43,2557.32,1780.44,1.00246,156.052,-nan,-nan,0.9087,0.114186,-1.0,-1.0,22.524,1.85826,1546,3986424 +175,delete,196.307,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,667.664,1.77137,1467,3804693 +176,search,4788.91,2585.27,1747.98,0.999854,149.163,-nan,-nan,0.90692,0.115298,-1.0,-1.0,67.559,1.77212,1472,3804693 +177,delete,19.12,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,79.175,1.76656,1467,3786352 +178,search,4822.86,2567.41,1780.5,0.960918,155.313,-nan,-nan,0.9067,0.11531,-1.0,-1.0,32.461,1.76676,1468,3786352 +179,delete,277.027,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1056.85,1.63374,1319,3556994 +180,search,4273.56,2659.04,1532.45,1.05382,128.427,-nan,-nan,0.89591,0.121702,-1.0,-1.0,90.475,1.6356,1327,3556994 +181,delete,27.897,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,67.27,1.62952,1323,3526824 +182,search,4409.88,2619.66,1642.78,0.97329,143.468,-nan,-nan,0.89651,0.121068,-1.0,-1.0,33.071,1.62965,1325,3526824 +183,delete,177.725,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,766.07,1.54039,1215,3350245 +184,search,4110.83,2703.35,1557.89,0.953996,134.8,-nan,-nan,0.8801,0.139869,-1.0,-1.0,74.203,1.54177,1224,3350245 +185,delete,10.713,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,28.32,1.53979,1219,3340234 +186,search,4088.08,2650.72,1525.64,0.909161,139.139,-nan,-nan,0.88494,0.131323,-1.0,-1.0,76.376,1.54156,1222,3340234 +187,delete,208.538,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,293.087,1.44974,1179,3150857 +188,search,3991.52,2669.46,1510.83,0.879377,133.039,-nan,-nan,0.88838,0.128941,-1.0,-1.0,51.964,1.45025,1183,3150857 +189,delete,5.765,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.249,1.45025,1183,3143609 +190,search,3947.97,2645.46,1480.44,0.928995,132.252,-nan,-nan,0.88771,0.129211,-1.0,-1.0,15.574,1.45025,1183,3143609 +191,delete,3.72,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.248,1.44994,1183,3141038 +192,search,3944.9,2642.42,1477.28,0.938585,134.787,-nan,-nan,0.88765,0.129279,-1.0,-1.0,15.468,1.44994,1183,3141038 +193,delete,61.533,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,195.747,1.42745,1163,3081734 +194,search,3822.43,2636.17,1408.42,0.985098,127.08,-nan,-nan,0.88646,0.130074,-1.0,-1.0,28.949,1.4277,1165,3081734 +195,delete,41.773,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,181.97,1.41055,1148,3043966 +196,search,3810.08,2631.49,1410.79,0.983833,126.422,-nan,-nan,0.88619,0.130706,-1.0,-1.0,56.306,1.41123,1152,3043966 +197,delete,46.868,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,60.084,1.39985,1148,3008145 +198,search,3791.53,2601.6,1390.59,0.993336,125.647,-nan,-nan,0.88571,0.130621,-1.0,-1.0,15.204,1.39985,1148,3008145 +199,delete,11.049,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,34.533,1.3969,1146,2999384 +200,search,3824.69,2602.5,1416.69,0.916913,128.082,-nan,-nan,0.88524,0.130848,-1.0,-1.0,15.232,1.3969,1146,2999384 +201,delete,5.915,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,40.514,1.39463,1144,2993528 +202,search,3831.01,2597.51,1417.67,0.953188,128.698,-nan,-nan,0.8851,0.130857,-1.0,-1.0,28.99,1.39499,1145,2993528 +203,delete,12.204,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.984,1.39463,1145,2980973 +204,search,3828.48,2583.25,1411.55,0.885326,128.193,-nan,-nan,0.88494,0.131202,-1.0,-1.0,24.844,1.39485,1146,2980973 +205,delete,23.455,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,40.644,1.3891,1137,2960291 +206,search,3793.82,2572.39,1401.72,0.944292,124.19,-nan,-nan,0.88421,0.131611,-1.0,-1.0,14.97,1.3891,1137,2960291 +207,delete,47.035,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,127.458,1.3685,1091,2920620 +208,search,3632.76,2585.86,1343.31,0.930398,117.831,-nan,-nan,0.88051,0.134818,-1.0,-1.0,18.274,1.3685,1091,2920620 +209,delete,23.518,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,52.039,1.36027,1084,2900501 +210,search,3241.03,2581.93,1331.42,0.92744,115.644,-nan,-nan,0.87964,0.135081,-1.0,-1.0,12.16,1.36027,1084,2900501 +211,delete,5.549,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,19.726,1.35739,1083,2891660 +212,search,3451.61,2575.67,1270.13,0.992371,111.12,-nan,-nan,0.87942,0.13526,-1.0,-1.0,27.299,1.35742,1084,2891660 +213,delete,20.776,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,77.62,1.35031,1078,2873257 +214,search,3454.82,2563.77,1320.7,0.944427,114.247,-nan,-nan,0.8783,0.13611,-1.0,-1.0,13.176,1.35031,1078,2873257 +215,delete,242.353,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1494.38,1.14861,879,2537571 +216,search,2819.05,2831.25,1086.51,0.997684,89.8229,-nan,-nan,0.87291,0.139252,-1.0,-1.0,283.342,1.15486,915,2537571 +217,delete,124.286,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,614.541,1.03598,777,2308194 +218,search,2242.3,2886.24,973.77,1.05279,82.8769,-nan,-nan,0.86617,0.144809,-1.0,-1.0,208.54,1.0438,816,2308194 +219,delete,10.622,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,35.81,1.03865,811,2285820 +220,search,2258.81,2664.37,937.309,1.0087,84.0616,-nan,-nan,0.8636,0.146864,-1.0,-1.0,54.036,1.0392,820,2285820 +221,delete,116.315,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,432.079,0.92963,679,2082858 +222,search,2236.92,2784.41,826.658,1.07193,73.2636,-nan,-nan,0.85355,0.153915,-1.0,-1.0,72.805,0.930751,687,2082858 +223,delete,9.198,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,28.679,0.927826,683,2071207 +224,search,2195.84,2728.25,859.636,1.05604,75.1523,-nan,-nan,0.8511,0.155631,-1.0,-1.0,25.913,0.928493,684,2071207 +225,delete,4.851,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,12.223,0.927506,683,2065400 +226,search,2325.03,2719.38,897.337,0.944892,84.1392,-nan,-nan,0.85107,0.155546,-1.0,-1.0,10.974,0.927506,683,2065400 +227,delete,3.13,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,10.145,0.927506,683,2062105 +228,search,2250.82,2713.96,906.232,0.928092,83.1459,-nan,-nan,0.85072,0.15576,-1.0,-1.0,10.109,0.927506,683,2062105 +229,delete,23.204,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,52.131,0.921084,677,2039610 +230,search,2362.79,2703.35,907.629,0.923592,82.8306,-nan,-nan,0.84902,0.156903,-1.0,-1.0,19.165,0.92136,678,2039610 +231,delete,12.669,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,50.528,0.916266,672,2027795 +232,search,2275.71,2712.62,858.851,0.978512,78.9798,-nan,-nan,0.84977,0.1567,-1.0,-1.0,40.02,0.916559,675,2027795 +233,delete,5.004,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,15.083,0.915492,674,2022859 +234,search,2361.8,2689.37,903.813,0.872645,90.1896,-nan,-nan,0.84893,0.157088,-1.0,-1.0,8.291,0.915492,674,2022859 +235,delete,4.035,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,9.819,0.915136,673,2016264 +236,search,2241.97,2684.54,838.206,1.04464,76.3599,-nan,-nan,0.84875,0.157118,-1.0,-1.0,11.084,0.915136,673,2016264 +237,delete,300.516,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,741.319,0.792515,551,1782866 +238,search,1970.75,2928.14,758.2,0.966397,66.7084,-nan,-nan,0.84117,0.164179,-1.0,-1.0,168.095,0.796057,568,1782866 +239,delete,19.763,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,63.324,0.786082,558,1758931 +240,search,1961.31,2822.31,744.12,1.04752,66.199,-nan,-nan,0.8384,0.164827,-1.0,-1.0,56.02,0.786385,563,1758931 +241,delete,6.942,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,34.026,0.782659,560,1751275 +242,search,1958.21,2792.76,733.607,1.01614,68.7278,-nan,-nan,0.83696,0.165016,-1.0,-1.0,28.018,0.782948,562,1751275 +243,delete,19.528,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,26.667,0.779254,559,1733264 +244,search,2014.6,2762.46,784.075,0.891631,75.9705,-nan,-nan,0.83554,0.166284,-1.0,-1.0,16.458,0.779466,560,1733264 +245,delete,9.118,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,9.89,0.7777,559,1722658 +246,search,1877.35,2739.45,745.89,1.00469,66.3436,-nan,-nan,0.83478,0.166521,-1.0,-1.0,8.38,0.7777,559,1722658 +247,delete,2.398,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,8.024,0.7777,559,1719601 +248,search,1999.46,2735.36,768.661,0.968369,71.9837,-nan,-nan,0.83448,0.166603,-1.0,-1.0,8.833,0.7777,559,1719601 +249,delete,9.259,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,21.894,0.774906,557,1711648 +250,search,1782.66,2729.12,744.329,0.989099,65.7997,-nan,-nan,0.83288,0.167399,-1.0,-1.0,6.575,0.774906,557,1711648 +251,delete,182.878,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,309.894,0.654489,462,1470624 +252,search,1712.59,2899.67,691.328,0.815954,63.6184,-nan,-nan,0.82899,0.168827,-1.0,-1.0,113.097,0.657254,474,1470624 +253,delete,17.523,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,33.714,0.648981,467,1442070 +254,search,1657.67,2772.52,650.173,0.905936,59.6014,-nan,-nan,0.82805,0.169312,-1.0,-1.0,9.59,0.648981,467,1442070 +255,delete,38.396,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,108.01,0.631023,448,1405549 +256,search,1607.2,2827.02,608.059,1.0469,54.6439,-nan,-nan,0.82206,0.17264,-1.0,-1.0,21.74,0.631206,450,1405549 +257,insert,12.883,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,7.83,0.634335,450,1416288 +258,search,1679.41,2822.47,658.116,0.848679,58.8,-nan,-nan,0.82329,0.172639,-1.0,-1.0,15.503,0.634382,451,1416288 +259,insert,31.684,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,53.947,0.645258,456,1443010 +260,search,1684.51,2829.23,670.994,0.949099,63.0048,-nan,-nan,0.82194,0.173316,-1.0,-1.0,6.224,0.645258,456,1443010 +261,insert,5.011,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.508,0.647009,458,1447529 +262,search,1474.77,2822.5,640.758,0.892868,57.7263,-nan,-nan,0.8238,0.172442,-1.0,-1.0,6.118,0.647009,458,1447529 +263,insert,83.539,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,78.918,0.697252,466,1569110 +264,search,1525.41,3022.32,687.238,0.896871,60.5443,-nan,-nan,0.82631,0.17282,-1.0,-1.0,48.836,0.697488,470,1569110 +265,insert,50.39,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,89.455,0.72656,488,1636119 +266,search,1771.95,3007.27,711.995,0.936005,67.3647,-nan,-nan,0.83096,0.1699,-1.0,-1.0,110.28,0.7266,496,1636119 +267,insert,32.684,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,65.499,0.740769,502,1665152 +268,search,1881.52,2988.14,767.584,0.861896,68.0138,-nan,-nan,0.83476,0.168296,-1.0,-1.0,65.923,0.74091,508,1665152 +269,insert,301.231,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,297.547,0.85372,536,1916952 +270,search,2050,3189.22,859.202,0.901939,76.5703,-nan,-nan,0.83636,0.166429,-1.0,-1.0,155.045,0.854696,549,1916952 +271,insert,5.159,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.066,0.855858,551,1920898 +272,search,2000.86,3101.84,862.519,0.910505,77.5885,-nan,-nan,0.83768,0.165902,-1.0,-1.0,37.579,0.856075,556,1920898 +273,insert,10.793,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,31.858,0.864167,562,1942757 +274,search,2053.78,3078.13,843.481,0.91838,74.443,-nan,-nan,0.8402,0.164089,-1.0,-1.0,29.238,0.864406,564,1942757 +275,insert,379.972,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,565.93,1.04288,639,2328372 +276,search,2336.01,3271.08,993.646,0.975758,86.1996,-nan,-nan,0.84997,0.158664,-1.0,-1.0,226.884,1.04488,665,2328372 +277,insert,37.932,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,58.403,1.05856,673,2363257 +278,search,2460.17,3131.63,1008.49,0.97955,88.1646,-nan,-nan,0.85234,0.157049,-1.0,-1.0,67.228,1.05894,677,2363257 +279,insert,31.067,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,27.569,1.06985,679,2388933 +280,search,2520.9,3142.43,1045.16,0.931414,97.2971,-nan,-nan,0.85343,0.156073,-1.0,-1.0,53.05,1.06985,683,2388933 +281,insert,298.475,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,389.568,1.20574,718,2684315 +282,search,2672.5,3253.24,1122.57,0.899991,102.917,-nan,-nan,0.85521,0.156094,-1.0,-1.0,151.358,1.20709,731,2684315 +283,insert,463.968,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,632.265,1.40051,821,3109157 +284,search,3023.2,3313.63,1278.21,0.935867,112.351,-nan,-nan,0.86272,0.151953,-1.0,-1.0,235.403,1.40196,850,3109157 +285,insert,13.913,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.436,1.40656,852,3122751 +286,search,3119.25,3205.68,1297.79,0.887082,115.605,-nan,-nan,0.86484,0.150778,-1.0,-1.0,71.309,1.40759,857,3122751 +287,insert,41.042,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,68.449,1.42637,863,3163679 +288,search,3173.1,3206.3,1316,0.852168,114.964,-nan,-nan,0.86478,0.1509,-1.0,-1.0,44.762,1.4271,867,3163679 +289,insert,358.136,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,481.725,1.56119,918,3472031 +290,search,3380.11,3305.24,1429.79,0.93077,127.844,-nan,-nan,0.8675,0.149583,-1.0,-1.0,244.059,1.56208,934,3472031 +291,insert,27.425,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,63.04,1.57295,943,3495577 +292,search,3475.38,3232.06,1458.91,0.880425,129.647,-nan,-nan,0.86951,0.147906,-1.0,-1.0,94.5,1.57296,951,3495577 +293,insert,19.206,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,45.569,1.58128,955,3515193 +294,search,3348.67,3209.65,1448.97,0.925965,128.635,-nan,-nan,0.86933,0.148408,-1.0,-1.0,32.365,1.58128,957,3515193 +295,insert,243.151,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,353.285,1.66991,1000,3723063 +296,search,3613.18,3267.32,1482.85,1.02531,131.682,-nan,-nan,0.87427,0.145541,-1.0,-1.0,154.276,1.67165,1021,3723063 +297,insert,3.672,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,20.66,1.6729,1022,3727399 +298,search,3679.88,3195.06,1516.01,0.93827,135.027,-nan,-nan,0.87476,0.145191,-1.0,-1.0,51.892,1.67363,1027,3727399 +299,insert,76.237,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,125.217,1.69647,1047,3788002 +300,search,3641.7,3171.8,1455.56,1.03589,123.293,-nan,-nan,0.87695,0.142589,-1.0,-1.0,20.079,1.69647,1048,3788002 +301,insert,726.209,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1123.27,1.9695,1193,4370866 +302,search,4327.18,3343.84,1834.65,0.945757,157.284,-nan,-nan,0.90184,0.122855,-1.0,-1.0,213.132,1.96994,1223,4370866 +303,insert,57.755,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,91.145,1.99022,1233,4420306 +304,search,4354.31,3221.57,1776.23,0.996096,146.162,-nan,-nan,0.90056,0.123259,-1.0,-1.0,22.087,1.99022,1235,4420306 +305,insert,389.532,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,487.363,2.15567,1282,4789669 +306,search,4670.03,3317.69,1969.46,0.90406,174.906,-nan,-nan,0.90337,0.121587,-1.0,-1.0,234.755,2.15679,1300,4789669 +307,insert,28.818,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,39.672,2.16441,1304,4815550 +308,search,4570.46,3281.93,1853.73,1.02517,154.763,-nan,-nan,0.90379,0.121146,-1.0,-1.0,120.304,2.16472,1314,4815550 +309,insert,9.142,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,18.184,2.1675,1315,4823345 +310,search,4599.27,3262.17,1847.45,1.06239,155.242,-nan,-nan,0.90476,0.120367,-1.0,-1.0,41.025,2.1675,1318,4823345 +311,insert,21.887,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,17.995,2.17652,1319,4843493 +312,search,4743.15,3259.62,1991.83,0.931453,175.201,-nan,-nan,0.90413,0.120811,-1.0,-1.0,12.58,2.17652,1319,4843493 +313,insert,45.049,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,62.42,2.19327,1325,4885489 +314,search,4593.04,3273.18,1828.36,1.08159,146.448,-nan,-nan,0.90448,0.120895,-1.0,-1.0,54.135,2.19378,1330,4885489 +315,insert,7.759,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,12.028,2.19653,1330,4892335 +316,search,4695.79,3265.1,1927.02,1.01447,159.444,-nan,-nan,0.90464,0.120699,-1.0,-1.0,28.56,2.19677,1332,4892335 +317,insert,46.084,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,75.319,2.2123,1340,4932996 +318,search,4691.72,3274.45,1903.16,0.998541,157.142,-nan,-nan,0.90497,0.120457,-1.0,-1.0,24.507,2.21274,1341,4932996 +319,insert,619.613,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,849.439,2.4253,1450,5430684 +320,search,5150.5,3367.53,2157.44,0.971539,181.974,-nan,-nan,0.90971,0.115656,-1.0,-1.0,348.74,2.43284,1498,5430684 +321,insert,48.216,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,78.077,2.44999,1507,5471239 +322,search,5396.26,3253.34,2251.74,0.980214,203.623,-nan,-nan,0.90969,0.115915,-1.0,-1.0,70.375,2.4501,1511,5471239 +323,insert,110.738,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,163.358,2.49315,1534,5575560 +324,search,5372.27,3262.58,2197.35,1.01611,187.663,-nan,-nan,0.91074,0.114487,-1.0,-1.0,64.482,2.49331,1540,5575560 +325,insert,1350.21,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,744.909,2.72229,1607,6069499 +326,search,5819.25,3387.17,2488.83,0.885272,222.315,-nan,-nan,0.91389,0.112886,-1.0,-1.0,356.899,2.72298,1637,6069499 +327,insert,74.622,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,135.3,2.75082,1652,6139647 +328,search,5961.96,3329.96,2517.82,0.890001,224.411,-nan,-nan,0.91588,0.111257,-1.0,-1.0,195.588,2.75146,1670,6139647 +329,insert,12.29,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,20.56,2.75487,1671,6146884 +330,search,5994.27,3296.34,2510.96,0.933243,224.867,-nan,-nan,0.91578,0.111413,-1.0,-1.0,79.178,2.75487,1677,6146884 +331,insert,52.508,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,65.245,2.77313,1683,6188816 +332,search,5812.49,3297.48,2411.6,0.997272,203.743,-nan,-nan,0.91598,0.111387,-1.0,-1.0,53.674,2.77336,1687,6188816 +333,insert,3.445,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,20.552,2.774,1688,6190810 +334,search,5887.92,3286.63,2408.84,1.01514,205.762,-nan,-nan,0.916,0.111293,-1.0,-1.0,16.24,2.774,1688,6190810 +335,insert,53.085,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,125.146,2.79201,1705,6230108 +336,search,6047.76,3275.75,2503.97,0.947008,216.864,-nan,-nan,0.91662,0.110599,-1.0,-1.0,24.521,2.79213,1706,6230108 +337,insert,23.83,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,53.62,2.80041,1710,6249699 +338,search,6015.1,3277.55,2464.29,0.969751,209.416,-nan,-nan,0.91734,0.109968,-1.0,-1.0,34.473,2.80082,1712,6249699 +339,insert,55.837,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,71.357,2.8143,1721,6290226 +340,search,5897.39,3273.64,2369.4,1.04496,199.284,-nan,-nan,0.91768,0.109371,-1.0,-1.0,24.682,2.81446,1722,6290226 +341,insert,10.201,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,32.565,2.81807,1724,6297556 +342,search,5910.98,3271.67,2356.73,1.03452,189.78,-nan,-nan,0.91811,0.109216,-1.0,-1.0,33.96,2.81816,1726,6297556 +343,insert,37.572,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,97.79,2.83089,1739,6330843 +344,search,6093.56,3267.8,2504.03,0.956056,212.847,-nan,-nan,0.91839,0.109113,-1.0,-1.0,16.161,2.83089,1739,6330843 +345,insert,47.194,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,99.111,2.84804,1751,6370265 +346,search,6133.34,3270.59,2510.62,1.06201,213.915,-nan,-nan,0.91898,0.108793,-1.0,-1.0,32.223,2.84845,1753,6370265 +347,insert,576.613,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1024.4,3.0527,1892,6831086 +348,search,6572.64,3264.31,2682.5,1.01507,230.679,-nan,-nan,0.92245,0.10564,-1.0,-1.0,158.023,3.05492,1911,6831086 +349,insert,46.141,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,94.702,3.071,1922,6876154 +350,search,6686.96,3240,2705.34,1.01986,233.088,-nan,-nan,0.92341,0.105273,-1.0,-1.0,91.691,3.07265,1931,6876154 +351,insert,511.096,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,590.774,3.25412,2004,7288266 +352,search,7007.87,3269.66,2866.06,1.02988,242.647,-nan,-nan,0.92153,0.107744,-1.0,-1.0,255.957,3.2571,2032,7288266 +353,insert,53.329,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,112.764,3.27437,2044,7333132 +354,search,7216.24,3227.19,2964.49,0.950497,261.174,-nan,-nan,0.92235,0.107172,-1.0,-1.0,92.679,3.27452,2050,7333132 +355,insert,420.443,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,572.177,3.4318,2118,7696838 +356,search,7260.17,3276.21,2901.06,1.07277,235.65,-nan,-nan,0.9243,0.105546,-1.0,-1.0,229.617,3.43481,2139,7696838 +357,insert,22.523,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,24.438,3.44102,2139,7714498 +358,search,7425,3251.61,2986.2,0.998383,251.154,-nan,-nan,0.92479,0.105277,-1.0,-1.0,69.872,3.44118,2143,7714498 +359,insert,14.244,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,64.194,3.44596,2148,7725755 +360,search,7417.76,3242.59,2992.08,1.0052,244.118,-nan,-nan,0.92497,0.105267,-1.0,-1.0,63.994,3.44655,2152,7725755 +361,insert,70.044,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,103.542,3.47145,2162,7789312 +362,search,7601.94,3245.29,3117.35,0.923066,263.508,-nan,-nan,0.92538,0.104971,-1.0,-1.0,57.172,3.4719,2165,7789312 +363,insert,22.973,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,63.568,3.47686,2169,7803163 +364,search,7621.73,3241.9,3132.04,0.942892,270.597,-nan,-nan,0.9255,0.104621,-1.0,-1.0,33.343,3.47698,2170,7803163 +365,insert,70.156,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,153.612,3.50109,2184,7863722 +366,search,7647.05,3246.73,3118.19,0.965928,269.034,-nan,-nan,0.92613,0.103962,-1.0,-1.0,75.502,3.50161,2189,7863722 +367,insert,37.557,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,99.471,3.51436,2199,7895271 +368,search,6683.07,3238.16,3017.39,1.09757,254.009,-nan,-nan,0.92648,0.103757,-1.0,-1.0,39.418,3.51474,2204,7895271 +369,insert,37.727,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,50.886,3.53846,2213,7961194 +370,search,7339.35,3241.68,2964.15,1.12009,235.826,-nan,-nan,0.92691,0.103002,-1.0,-1.0,25.758,3.5386,2214,7961194 +371,insert,9.048,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,23.53,3.54207,2215,7970239 +372,search,6519.07,3244.53,3064.67,1.02654,250.138,-nan,-nan,0.92707,0.102901,-1.0,-1.0,29.001,3.54244,2217,7970239 +373,insert,30.932,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,50.014,3.55884,2225,8010868 +374,search,7336.98,3249.95,3090.05,1.00083,252.335,-nan,-nan,0.92739,0.102535,-1.0,-1.0,34.458,3.55898,2226,8010868 +375,insert,42.219,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,93.999,3.57271,2235,8040698 +376,search,7581.04,3244.14,2997.68,1.07074,247.267,-nan,-nan,0.92744,0.102489,-1.0,-1.0,42.693,3.57301,2237,8040698 +377,insert,72.714,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,177.459,3.60131,2256,8104748 +378,search,7513.57,3237.15,3154.38,1.01857,266.033,-nan,-nan,0.92808,0.1021,-1.0,-1.0,31.998,3.60174,2258,8104748 +379,insert,3.647,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,28.455,3.60404,2261,8109755 +380,search,7364.77,3231.13,2987.09,1.12252,236.187,-nan,-nan,0.92815,0.102041,-1.0,-1.0,40.443,3.60412,2262,8109755 +381,insert,29.792,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,27.958,3.61216,2262,8130382 +382,search,7798.09,3235.2,3134.42,1.03693,262.457,-nan,-nan,0.92813,0.102121,-1.0,-1.0,48.38,3.61223,2263,8130382 +383,insert,45.598,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,75.628,3.62141,2268,8153290 +384,search,7966.5,3237.25,3245.31,0.97257,274.341,-nan,-nan,0.92847,0.101723,-1.0,-1.0,38.161,3.62163,2269,8153290 +385,delete,28.269,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,71.244,3.61938,2267,8138873 +386,search,7664.89,3231.25,3021.7,1.05249,252.126,-nan,-nan,0.92853,0.101602,-1.0,-1.0,29.353,3.61938,2267,8138873 +387,delete,33.958,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,172.401,3.61055,2260,8115069 +388,search,7726.69,3231.92,3220.18,0.963919,275.844,-nan,-nan,0.92851,0.101499,-1.0,-1.0,26.995,3.61059,2261,8115069 +389,delete,12.182,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,79.7,3.60667,2255,8101157 +390,search,7391.48,3233.11,2963.31,1.09291,236.608,-nan,-nan,0.92851,0.101745,-1.0,-1.0,47.989,3.60692,2257,8101157 +391,delete,118.449,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,507.92,3.57028,2222,8014644 +392,search,7563.68,3244.09,2995.7,1.06331,240.643,-nan,-nan,0.92826,0.101543,-1.0,-1.0,130.327,3.57251,2235,8014644 +393,delete,33.51,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,76.213,3.56852,2232,7978358 +394,search,7751.33,3206.08,3138.53,0.985914,264.828,-nan,-nan,0.92772,0.101938,-1.0,-1.0,38.174,3.56871,2233,7978358 +395,delete,22.898,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,268.689,3.55564,2221,7957094 +396,search,7704.65,3211.25,3096.29,1.04991,258.24,-nan,-nan,0.92721,0.102259,-1.0,-1.0,71.18,3.55647,2226,7957094 +397,delete,125.734,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,967.34,3.49258,2179,7823916 +398,search,7174.57,3224.18,2858.87,1.12191,228.633,-nan,-nan,0.92698,0.102485,-1.0,-1.0,82.525,3.49517,2191,7823916 +399,delete,3.406,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,37.283,3.49282,2189,7818430 +400,search,7138.88,3206.27,2907.31,1.04754,235.689,-nan,-nan,0.92682,0.102751,-1.0,-1.0,53.717,3.49359,2192,7818430 +401,delete,23.358,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,93.92,3.4873,2187,7800702 +402,search,7439.94,3200.29,2942.05,1.08446,240.888,-nan,-nan,0.92615,0.103543,-1.0,-1.0,27.273,3.4873,2187,7800702 +403,delete,318.744,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1971.26,3.35721,2066,7517858 +404,search,7318.57,3259.51,3021.14,0.966763,260.4,-nan,-nan,0.92413,0.104666,-1.0,-1.0,345.83,3.36418,2103,7517858 +405,delete,57.87,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,349.815,3.34562,2087,7451637 +406,search,7316.51,3199.82,2979.55,0.929866,259.63,-nan,-nan,0.9246,0.104458,-1.0,-1.0,48.129,3.34573,2089,7451637 +407,delete,119.526,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,727.889,3.29527,2050,7360417 +408,search,6820.57,3215.4,2999.82,0.940746,268.129,-nan,-nan,0.924,0.105083,-1.0,-1.0,61.222,3.29728,2058,7360417 +409,delete,123.392,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,548.886,3.19649,2015,7131620 +410,search,6648.72,3207.76,2740.55,1.08397,226.292,-nan,-nan,0.9239,0.10507,-1.0,-1.0,142.863,3.19919,2027,7131620 +411,delete,264.933,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1700.66,3.07728,1909,6867617 +412,search,5593.06,3259.32,2669.2,1.08803,217.401,-nan,-nan,0.9227,0.105923,-1.0,-1.0,181.132,3.08294,1942,6867617 +413,delete,8.448,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,50.516,3.07899,1940,6850098 +414,search,6411.45,3189.65,2667.6,1.04305,219.436,-nan,-nan,0.92311,0.105568,-1.0,-1.0,54.791,3.07974,1945,6850098 +415,delete,46.648,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,469.809,3.04976,1920,6782921 +416,search,5909.27,3193.23,2604.48,1.0886,212.761,-nan,-nan,0.92253,0.105951,-1.0,-1.0,24.338,3.05014,1922,6782921 +417,delete,132.022,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,803.787,2.95764,1853,6562039 +418,search,6111.72,3201.93,2558.21,1.06611,207.496,-nan,-nan,0.92219,0.106296,-1.0,-1.0,182.306,2.96093,1870,6562039 +419,delete,23.63,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,75.679,2.95761,1866,6536285 +420,search,5556.45,3168.45,2531.05,1.09674,207.653,-nan,-nan,0.92306,0.10547,-1.0,-1.0,36.236,2.95802,1869,6536285 +421,delete,11.328,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,88.129,2.94541,1860,6510820 +422,search,6001.67,3168.88,2316.04,1.17717,182.709,-nan,-nan,0.92304,0.105414,-1.0,-1.0,42.363,2.94554,1862,6510820 +423,delete,170.011,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,739.241,2.8699,1799,6334168 +424,search,6360.56,3182.36,2600.05,0.940237,221.347,-nan,-nan,0.92143,0.106491,-1.0,-1.0,97.606,2.87113,1807,6334168 +425,delete,18.416,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,34.612,2.86931,1806,6316443 +426,search,6253.94,3161.74,2506.7,1.0065,211.416,-nan,-nan,0.92151,0.106427,-1.0,-1.0,21.693,2.86931,1806,6316443 +427,delete,50.857,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,75.528,2.86257,1802,6266345 +428,search,6028.08,3132.44,2567.41,0.92593,220.994,-nan,-nan,0.92139,0.10683,-1.0,-1.0,14.319,2.86257,1802,6266345 +429,delete,295.611,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1903.53,2.64175,1548,5883847 +430,search,5328.28,3497.19,2354.47,1.003,190.465,-nan,-nan,0.90995,0.116189,-1.0,-1.0,554.999,2.65396,1623,5883847 +431,delete,63.918,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,326.193,2.61605,1597,5801380 +432,search,4857.96,3296.31,2196.26,1.1097,178.81,-nan,-nan,0.90944,0.116149,-1.0,-1.0,54.862,2.61728,1608,5801380 +433,delete,117.794,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,678.466,2.52854,1534,5607567 +434,search,4978.56,3302.96,2200.51,1.06557,179.068,-nan,-nan,0.9066,0.118421,-1.0,-1.0,286.748,2.53286,1550,5607567 +435,delete,108.783,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,382.521,2.49578,1517,5512176 +436,search,5266.66,3283.45,2195.8,1.02103,186.471,-nan,-nan,0.90601,0.118772,-1.0,-1.0,167.033,2.49699,1525,5512176 +437,delete,10.078,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,61.464,2.4925,1522,5501141 +438,search,5481.27,3262.13,2259.23,1.0075,200.761,-nan,-nan,0.90592,0.118847,-1.0,-1.0,109.563,2.49249,1525,5501141 +439,delete,111.867,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,446.088,2.42841,1505,5369822 +440,search,5320.47,3260.99,2178.06,1.02306,191.051,-nan,-nan,0.90804,0.116471,-1.0,-1.0,194.688,2.43167,1518,5369822 +441,delete,26.272,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,95.35,2.42335,1513,5338985 +442,search,5320.39,3220.76,2165.24,0.999202,186.557,-nan,-nan,0.9074,0.116871,-1.0,-1.0,42.142,2.42366,1515,5338985 +443,delete,30.05,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,72.807,2.40932,1510,5307279 +444,search,5405.07,3223,2234.82,0.931145,196.857,-nan,-nan,0.90823,0.116297,-1.0,-1.0,41.614,2.40992,1513,5307279 +445,delete,40.164,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,101.597,2.39975,1509,5268382 +446,search,4683.97,3202.52,2119.25,1.04606,180.897,-nan,-nan,0.90795,0.116547,-1.0,-1.0,18.87,2.39994,1510,5268382 +447,delete,248.542,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1031.85,2.22482,1344,4922787 +448,search,4541.22,3348.01,1974.92,0.932628,163.588,-nan,-nan,0.90048,0.121312,-1.0,-1.0,210.619,2.22825,1368,4922787 +449,delete,34.397,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,143.694,2.21642,1357,4887227 +450,search,4870.89,3276.33,2023.3,0.985415,177.908,-nan,-nan,0.90037,0.120997,-1.0,-1.0,145.681,2.2198,1366,4887227 +451,delete,99.202,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,346.317,2.17986,1329,4795082 +452,search,4721.15,3270.38,1926.78,0.99336,161.347,-nan,-nan,0.90048,0.120866,-1.0,-1.0,137.706,2.18065,1338,4795082 +453,delete,329.461,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1442.69,2.03676,1209,4500175 +454,search,4420.59,3342.82,1857.81,0.925934,168.886,-nan,-nan,0.89464,0.125924,-1.0,-1.0,301.371,2.04091,1233,4500175 +455,delete,27.789,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,113.083,2.03225,1227,4462648 +456,search,4306.75,3290.96,1734.81,1.02701,145.63,-nan,-nan,0.89481,0.12525,-1.0,-1.0,155.158,2.03378,1235,4462648 +457,delete,5.562,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.765,2.03339,1235,4456761 +458,search,4269.38,3260.06,1689.96,0.993304,140.033,-nan,-nan,0.89492,0.125163,-1.0,-1.0,70.001,2.03339,1237,4456761 +459,delete,37.797,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,192.458,2.01224,1222,4419992 +460,search,4459.62,3268.48,1858.21,0.891393,166.899,-nan,-nan,0.89516,0.124989,-1.0,-1.0,92.441,2.01284,1228,4419992 +461,delete,3.852,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.341,2.01284,1228,4415725 +462,search,4442.84,3251.87,1847.68,0.942499,165.987,-nan,-nan,0.89501,0.125028,-1.0,-1.0,14.627,2.01284,1228,4415725 +463,delete,59.055,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,308.44,1.98591,1196,4370609 +464,search,4366.06,3318.33,1836.73,0.91728,163.494,-nan,-nan,0.89476,0.124912,-1.0,-1.0,102.767,1.98709,1206,4370609 +465,delete,19.726,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,79.21,1.97564,1199,4345244 +466,search,4369.32,3293.81,1822.88,0.939983,163.672,-nan,-nan,0.89366,0.125433,-1.0,-1.0,46.321,1.97577,1202,4345244 +467,delete,43.129,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,73.013,1.96762,1198,4319734 +468,search,4330.04,3268.19,1812.18,0.879917,153.832,-nan,-nan,0.89333,0.125693,-1.0,-1.0,35.585,1.96823,1200,4319734 +469,delete,17.339,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,40.855,1.95915,1196,4298361 +470,search,4341.33,3258.25,1802.04,0.891265,157.429,-nan,-nan,0.89268,0.126084,-1.0,-1.0,32.088,1.95943,1197,4298361 +471,delete,138.787,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,351.396,1.90577,1155,4188315 +472,search,4204.73,3283.2,1752.54,0.927696,154.141,-nan,-nan,0.89105,0.127821,-1.0,-1.0,95.806,1.90754,1165,4188315 +473,delete,79.44,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,481.991,1.85001,1115,4074567 +474,search,4086.5,3300.73,1711.85,0.930999,153.052,-nan,-nan,0.88992,0.12902,-1.0,-1.0,197.874,1.85301,1135,4074567 +475,delete,425.331,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1660.32,1.65476,960,3691698 +476,search,3523.61,3483.51,1460.97,1.03829,125.974,-nan,-nan,0.88364,0.133768,-1.0,-1.0,416.558,1.66312,1005,3691698 +477,delete,42.84,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,209.953,1.64053,988,3642619 +478,search,3524.29,3319.99,1437.12,1.01488,118.959,-nan,-nan,0.88312,0.134124,-1.0,-1.0,109.978,1.6417,997,3642619 +479,delete,255.693,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1164.04,1.53338,904,3421368 +480,search,3485.2,3626.92,1543.99,0.865196,127.066,-nan,-nan,0.89538,0.123596,-1.0,-1.0,495.089,1.54338,938,3421368 +481,delete,50.333,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,141.596,1.52656,924,3378034 +482,search,3450.14,3298.65,1449.3,0.86281,125.651,-nan,-nan,0.8883,0.129703,-1.0,-1.0,81.255,1.52738,930,3378034 +483,delete,318.314,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1133.11,1.3873,803,3115682 +484,search,3066.05,3472.48,1322.41,0.895326,117.215,-nan,-nan,0.88012,0.135622,-1.0,-1.0,368.188,1.39393,842,3115682 +485,delete,18.781,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,41.006,1.38961,839,3094629 +486,search,3117.72,3278.94,1315.78,0.868895,116.71,-nan,-nan,0.88154,0.134697,-1.0,-1.0,78.613,1.39016,844,3094629 +487,delete,6.788,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.138,1.39016,844,3086025 +488,search,3135.63,3251.99,1316.74,0.893284,111.673,-nan,-nan,0.882,0.133896,-1.0,-1.0,14.172,1.39016,844,3086025 +489,delete,36.173,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,152.789,1.37753,833,3052105 +490,search,3062.95,3259.06,1273.43,0.868054,113.733,-nan,-nan,0.88072,0.135296,-1.0,-1.0,37.515,1.37774,835,3052105 +491,delete,14.971,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,27.361,1.37463,833,3038974 +492,search,2874.97,3244.8,1251.84,0.931173,103.951,-nan,-nan,0.88044,0.13549,-1.0,-1.0,11.328,1.37463,833,3038974 +493,delete,103.237,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,421.812,1.30586,780,2911063 +494,search,2920.62,3320.84,1236.47,0.948831,108.147,-nan,-nan,0.87808,0.136384,-1.0,-1.0,115.199,1.30818,791,2911063 +495,delete,21.528,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,65.277,1.2991,784,2888785 +496,search,2797.64,3267.04,1209.24,0.914553,107.277,-nan,-nan,0.87664,0.137255,-1.0,-1.0,16.476,1.29913,785,2888785 +497,delete,39.008,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,128.743,1.27627,768,2829718 +498,search,2830.1,3261.38,1194.34,0.907964,105.703,-nan,-nan,0.87503,0.138125,-1.0,-1.0,33.781,1.27684,770,2829718 +499,delete,16.216,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,11.746,1.27684,770,2816082 +500,search,2702.68,3229.99,1093.33,0.991909,94.7944,-nan,-nan,0.87498,0.138244,-1.0,-1.0,12.873,1.27684,770,2816082 +501,delete,27.868,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,73.406,1.26517,761,2790880 +502,search,2830.65,3239.62,1181.66,0.85648,107.407,-nan,-nan,0.87437,0.138568,-1.0,-1.0,12.431,1.26517,761,2790880 +503,delete,18.896,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,45.387,1.26025,757,2774459 +504,search,2776.97,3234.33,1154.66,0.886522,101.472,-nan,-nan,0.87338,0.13908,-1.0,-1.0,11.914,1.26025,757,2774459 +505,delete,71.802,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,153.495,1.2286,739,2714683 +506,search,2678.03,3238,1085.57,1.03208,91.0106,-nan,-nan,0.87194,0.139822,-1.0,-1.0,31.474,1.22915,741,2714683 +507,delete,40.973,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,70.144,1.21642,733,2680986 +508,search,2644.47,3225.37,1067.41,1.00653,93.7509,-nan,-nan,0.87144,0.139895,-1.0,-1.0,22.687,1.21655,734,2680986 +509,delete,22.05,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,100.48,1.20635,728,2662966 +510,search,2555.58,3229.94,1104.99,1.05744,94.2531,-nan,-nan,0.87039,0.14035,-1.0,-1.0,40.91,1.20711,731,2662966 +511,delete,14.743,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,56.617,1.19964,725,2642855 +512,search,2669.19,3215.05,1124.77,0.894691,97.1487,-nan,-nan,0.86934,0.141055,-1.0,-1.0,8.295,1.19964,725,2642855 +513,insert,195.502,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,254.596,1.30471,762,2906838 +514,search,2416.3,3328.46,1149.99,0.964045,97.2351,-nan,-nan,0.87251,0.139927,-1.0,-1.0,27.752,1.30485,765,2906838 +515,insert,3.077,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.523,1.30655,767,2913746 +516,search,2737.19,3317.83,1147.62,1.01443,99.5861,-nan,-nan,0.87328,0.139457,-1.0,-1.0,27.153,1.30677,769,2913746 +517,insert,25.525,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,27.33,1.31227,771,2936862 +518,search,2728.04,3344.85,1200.94,0.935599,105.289,-nan,-nan,0.87356,0.13903,-1.0,-1.0,11.367,1.31227,771,2936862 +519,insert,82.086,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,116.43,1.34433,780,3009732 +520,search,2836.87,3386.3,1177.05,1.05478,95.9398,-nan,-nan,0.87595,0.138859,-1.0,-1.0,71.62,1.34441,785,3009732 +521,insert,21.068,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,62.293,1.35021,789,3025906 +522,search,2980.94,3374.04,1274.3,0.951973,117.037,-nan,-nan,0.87668,0.138098,-1.0,-1.0,22.975,1.35021,790,3025906 +523,insert,51.085,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,92.046,1.36607,797,3061899 +524,search,2913.28,3385.74,1212.04,0.996898,101.61,-nan,-nan,0.87733,0.13801,-1.0,-1.0,41.261,1.36614,800,3061899 +525,insert,61.289,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,93,1.38449,808,3101209 +526,search,3059.52,3378.99,1302.23,0.926886,117.73,-nan,-nan,0.87841,0.137317,-1.0,-1.0,40.447,1.38489,811,3101209 +527,insert,632.079,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,943.075,1.57427,929,3522334 +528,search,3290.57,3368.9,1333.65,1.08197,108.472,-nan,-nan,0.88664,0.131366,-1.0,-1.0,204.792,1.57645,949,3522334 +529,insert,360.872,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,570.691,1.69686,1014,3797294 +530,search,3607.5,3364.32,1481.83,1.08783,120.726,-nan,-nan,0.89122,0.129196,-1.0,-1.0,199.66,1.69771,1030,3797294 +531,insert,97.791,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,144.098,1.72301,1044,3853781 +532,search,3857.6,3310.69,1636.18,0.896864,146.149,-nan,-nan,0.89321,0.12743,-1.0,-1.0,125.415,1.72333,1053,3853781 +533,insert,24.94,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,56.771,1.73058,1058,3873352 +534,search,3887.09,3285.75,1636.73,0.920917,148.222,-nan,-nan,0.89371,0.126638,-1.0,-1.0,103.111,1.73064,1065,3873352 +535,insert,25.506,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,70.745,1.73762,1072,3893308 +536,search,3896.47,3265,1643.05,0.911835,145.753,-nan,-nan,0.89457,0.126209,-1.0,-1.0,77.399,1.73852,1077,3893308 +537,insert,7.53,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,26.423,1.74185,1078,3901271 +538,search,3886.99,3247.83,1619.63,0.935806,141.383,-nan,-nan,0.89409,0.12659,-1.0,-1.0,15.509,1.74185,1078,3901271 +539,insert,27.201,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,42.022,1.74886,1081,3925164 +540,search,3904.94,3262.73,1624.96,0.957087,141.7,-nan,-nan,0.89496,0.125682,-1.0,-1.0,41.966,1.74897,1084,3925164 +541,insert,541.349,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,810.14,1.93325,1175,4320915 +542,search,4294.68,3330.28,1823.84,0.940486,161.564,-nan,-nan,0.89872,0.123679,-1.0,-1.0,318.031,1.93665,1208,4320915 +543,insert,58.958,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,88.189,1.95324,1218,4360814 +544,search,4383.73,3235.13,1818.1,0.921105,162.295,-nan,-nan,0.89994,0.122732,-1.0,-1.0,117.234,1.95376,1231,4360814 +545,insert,13.054,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.251,1.95761,1232,4370220 +546,search,4335.78,3192.1,1756.79,1.10201,147.775,-nan,-nan,0.90014,0.122741,-1.0,-1.0,22.882,1.9577,1233,4370220 +547,insert,200.853,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,306.213,2.02076,1275,4510675 +548,search,4555.29,3202.21,1889.69,0.970138,161.03,-nan,-nan,0.90249,0.121012,-1.0,-1.0,46.641,2.02076,1280,4510675 +549,insert,284.665,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,322.286,2.12186,1308,4744845 +550,search,4624.74,3229.6,1891.05,0.989333,159.109,-nan,-nan,0.89802,0.1265,-1.0,-1.0,100.958,2.12202,1313,4744845 +551,insert,33.162,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,49.424,2.13498,1316,4771433 +552,search,4621.49,3227.45,1869.98,0.987076,153.509,-nan,-nan,0.89837,0.12565,-1.0,-1.0,41.662,2.13498,1317,4771433 +553,insert,11.263,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,29.049,2.13784,1319,4782909 +554,search,4757.75,3220.34,1963.82,0.904206,172.122,-nan,-nan,0.89903,0.124551,-1.0,-1.0,37.499,2.13784,1320,4782909 +555,insert,549.768,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,793.104,2.31015,1440,5180322 +556,search,5117.88,3235.65,2122.06,0.927396,181.356,-nan,-nan,0.90436,0.119942,-1.0,-1.0,115.84,2.31125,1451,5180322 +557,insert,24.254,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,34.509,2.31758,1454,5203220 +558,search,5196.07,3224.55,2166.88,0.92585,192.478,-nan,-nan,0.90495,0.119581,-1.0,-1.0,41.523,2.31758,1456,5203220 +559,insert,6.812,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,35.477,2.31965,1458,5210154 +560,search,5087.95,3221.71,2066.14,1.02345,171.341,-nan,-nan,0.90543,0.1195,-1.0,-1.0,36.149,2.32,1460,5210154 +561,insert,9.354,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.334,2.32314,1460,5215426 +562,search,5185.32,3219.45,2153.78,0.986308,186.755,-nan,-nan,0.90535,0.119572,-1.0,-1.0,16.395,2.32314,1460,5215426 +563,insert,61.564,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,97.79,2.33689,1470,5252726 +564,search,5209.55,3220.33,2148.85,0.950768,187.635,-nan,-nan,0.90526,0.120055,-1.0,-1.0,29.443,2.33725,1471,5252726 +565,insert,269.718,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,290.897,2.41953,1495,5447274 +566,search,5376.48,3267.05,2264.47,0.96646,199.791,-nan,-nan,0.90562,0.119668,-1.0,-1.0,168.679,2.42028,1505,5447274 +567,insert,14.908,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.658,2.42666,1506,5463135 +568,search,5298.81,3238.46,2177.32,1.02302,182.77,-nan,-nan,0.90516,0.119967,-1.0,-1.0,70.124,2.42666,1508,5463135 +569,insert,23.048,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,24.035,2.43331,1509,5478168 +570,search,5401.51,3243.65,2256.06,0.905999,193.525,-nan,-nan,0.90599,0.119095,-1.0,-1.0,67.514,2.43379,1513,5478168 +571,insert,15.332,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,15.442,2.43966,1513,5492309 +572,search,5321.92,3236.52,2184.71,0.98884,183.577,-nan,-nan,0.90528,0.119742,-1.0,-1.0,29.056,2.43966,1514,5492309 +573,insert,85.703,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,126.855,2.463,1527,5554599 +574,search,5367.89,3246.75,2195.59,0.979563,185.358,-nan,-nan,0.90623,0.118705,-1.0,-1.0,36.847,2.46332,1529,5554599 +575,insert,70.111,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,98.898,2.4839,1538,5604500 +576,search,5561,3253.36,2316.89,0.923053,206.188,-nan,-nan,0.90647,0.11878,-1.0,-1.0,58.285,2.48492,1542,5604500 +577,insert,47.359,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,107.951,2.49914,1556,5638834 +578,search,5456.52,3237.65,2232.55,1.03513,185.643,-nan,-nan,0.90686,0.118668,-1.0,-1.0,30.767,2.49953,1557,5638834 +579,insert,880.001,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1218.2,2.77831,1710,6229778 +580,search,6020.95,3289.3,2481.6,0.980136,208.252,-nan,-nan,0.91188,0.113878,-1.0,-1.0,171.488,2.78084,1731,6229778 +581,insert,40.896,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,82.969,2.79687,1739,6261240 +582,search,6092.58,3245.73,2484.98,0.990595,206.871,-nan,-nan,0.9123,0.113578,-1.0,-1.0,26.224,2.79699,1740,6261240 +583,insert,25.523,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,44.306,2.80489,1743,6283315 +584,search,6177.28,3251.56,2538.72,0.937662,220.15,-nan,-nan,0.91255,0.113324,-1.0,-1.0,29.244,2.80508,1744,6283315 +585,insert,335.267,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,470.112,2.93011,1796,6556101 +586,search,6351.27,3285.48,2622.21,1.01137,221.724,-nan,-nan,0.91435,0.112005,-1.0,-1.0,181.241,2.93203,1816,6556101 +587,insert,43.185,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,59.765,2.9446,1821,6587187 +588,search,6479.2,3250.62,2695.91,0.964076,234.471,-nan,-nan,0.91431,0.11221,-1.0,-1.0,21.193,2.9446,1821,6587187 +589,insert,66.944,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,93.11,2.95949,1830,6631526 +590,search,6508.61,3260.34,2711.98,0.920957,234.645,-nan,-nan,0.9154,0.111066,-1.0,-1.0,33.831,2.9596,1831,6631526 +591,insert,631.616,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,766.511,3.16777,1932,7108942 +592,search,6889.86,3344.43,2864.48,0.988992,239.442,-nan,-nan,0.91832,0.10931,-1.0,-1.0,210.849,3.16954,1956,7108942 +593,insert,223.933,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,311.76,3.25236,1986,7303976 +594,search,7057.03,3325.76,2925.93,0.959346,246.421,-nan,-nan,0.91982,0.108437,-1.0,-1.0,169.082,3.25365,2001,7303976 +595,insert,6.419,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,38.514,3.25597,2003,7309244 +596,search,7055.58,3296.36,2901.17,1.00031,241.156,-nan,-nan,0.9196,0.108593,-1.0,-1.0,91.327,3.25615,2008,7309244 +597,insert,289.991,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,385.055,3.35893,2056,7542477 +598,search,7243.73,3323.32,2986.39,0.990598,249.285,-nan,-nan,0.92169,0.107232,-1.0,-1.0,171.463,3.36043,2071,7542477 +599,insert,136.018,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,244.52,3.4069,2103,7654438 +600,search,7506.33,3291.79,3143.12,0.925781,271.656,-nan,-nan,0.92225,0.10684,-1.0,-1.0,95.268,3.40767,2110,7654438 +601,insert,73.423,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,132.068,3.43467,2123,7717936 +602,search,7610.74,3294.55,3195.13,0.928727,279.136,-nan,-nan,0.92304,0.106142,-1.0,-1.0,73.587,3.43538,2128,7717936 +603,insert,7.882,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,25.409,3.4372,2128,7723521 +604,search,7200.54,3289.43,2853.97,1.08113,225.357,-nan,-nan,0.92296,0.106217,-1.0,-1.0,26.176,3.4372,2128,7723521 +605,insert,59.984,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,96.315,3.45308,2137,7767404 +606,search,7586.58,3294.9,3164.64,0.942439,267.742,-nan,-nan,0.92347,0.105808,-1.0,-1.0,45.502,3.45338,2139,7767404 +607,insert,111.187,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,253.392,3.4791,2143,7826115 +608,search,7688.8,3300.04,3209.88,0.911506,278.456,-nan,-nan,0.9232,0.106089,-1.0,-1.0,44.442,3.47936,2144,7826115 +609,insert,296.191,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,446.524,3.5665,2193,8036351 +610,search,7580.56,3320.81,3070.59,1.09276,245.937,-nan,-nan,0.92499,0.104082,-1.0,-1.0,164.089,3.56864,2207,8036351 +611,insert,26.523,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,68.695,3.57696,2212,8060364 +612,search,7769.11,3300.26,3195.35,1.07089,276.979,-nan,-nan,0.92495,0.104065,-1.0,-1.0,34.344,3.57697,2213,8060364 +613,insert,260.877,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,361.691,3.66201,2256,8256083 +614,search,7957.98,3306.31,3278.48,0.969623,274.814,-nan,-nan,0.92589,0.1035,-1.0,-1.0,98.291,3.66374,2265,8256083 +615,insert,449.977,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,650.5,3.83651,2331,8625707 +616,search,8194.06,3331.6,3381.48,1.0007,279.662,-nan,-nan,0.92772,0.102026,-1.0,-1.0,217.908,3.83863,2353,8625707 +617,insert,384.552,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,591.813,3.98468,2409,8949227 +618,search,8346.97,3350.24,3409.64,1.02301,276.429,-nan,-nan,0.9304,0.0993631,-1.0,-1.0,244.827,3.98732,2435,8949227 +619,insert,283.327,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,418.714,4.08879,2484,9195551 +620,search,8770.52,3319.01,3652.06,0.979456,308.381,-nan,-nan,0.93131,0.0988982,-1.0,-1.0,224.755,4.09265,2509,9195551 +621,insert,43.127,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,67.125,4.10566,2516,9232372 +622,search,8816.77,3289.65,3647.23,0.95471,308.845,-nan,-nan,0.93183,0.0985834,-1.0,-1.0,80.485,4.10638,2522,9232372 +623,insert,24.303,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,63.535,4.11548,2528,9253561 +624,search,8855.14,3283,3690.23,0.958383,310.701,-nan,-nan,0.93194,0.0984911,-1.0,-1.0,42.076,4.11585,2530,9253561 +625,insert,91.121,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,170.833,4.14724,2545,9331230 +626,search,8847.04,3288.19,3624.09,1.03692,295.504,-nan,-nan,0.93248,0.0980937,-1.0,-1.0,84.096,4.14776,2551,9331230 +627,insert,75.572,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,94.628,4.16479,2560,9374063 +628,search,8948.65,3284.76,3669.7,0.980996,307.108,-nan,-nan,0.93258,0.0979593,-1.0,-1.0,65.597,4.16537,2564,9374063 +629,insert,23.527,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,33.121,4.17065,2565,9387598 +630,search,9115.21,3280.88,3800.65,0.946131,331.027,-nan,-nan,0.93279,0.0978494,-1.0,-1.0,23.063,4.17065,2565,9387598 +631,insert,67.558,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,72.66,4.1864,2570,9421724 +632,search,9095.11,3283.66,3807.36,0.981128,326.061,-nan,-nan,0.93269,0.0978042,-1.0,-1.0,42.644,4.18651,2572,9421724 +633,insert,67.904,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,98.937,4.20004,2582,9461430 +634,search,9159,3282.43,3832.8,0.92092,336.461,-nan,-nan,0.93299,0.0974583,-1.0,-1.0,34.94,4.20014,2584,9461430 +635,insert,34.397,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,51.556,4.2067,2587,9479469 +636,search,9097.27,3281.65,3765.01,0.964946,318.965,-nan,-nan,0.9331,0.0973854,-1.0,-1.0,38.435,4.20685,2589,9479469 +637,insert,636.425,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,863.023,4.3964,2692,9885997 +638,search,9415.43,3311.95,3899.64,0.954167,329.644,-nan,-nan,0.9351,0.0958871,-1.0,-1.0,216.011,4.39911,2714,9885997 +639,insert,565.677,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,740.376,4.57865,2808,10292043 +640,search,9941.9,3307.56,4179.87,0.91994,359.217,-nan,-nan,0.93724,0.0939594,-1.0,-1.0,139.276,4.57969,2820,10292043 +641,delete,217.588,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1833.86,4.49654,2758,10096584 +642,search,9645.97,3306.26,4007.03,0.985974,337.27,-nan,-nan,0.93667,0.0943049,-1.0,-1.0,277.994,4.49996,2780,10096584 +643,delete,13.049,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,45.929,4.49915,2779,10084840 +644,search,9315.37,3287.58,3893.13,0.999192,318.117,-nan,-nan,0.93685,0.0942236,-1.0,-1.0,31.665,4.49944,2781,10084840 +645,delete,17.857,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,18.44,4.49944,2781,10069802 +646,search,9710.94,3277.38,4009.11,0.953299,344.175,-nan,-nan,0.93676,0.094291,-1.0,-1.0,25.873,4.49944,2781,10069802 +647,delete,108.264,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,746.711,4.45895,2743,9990953 +648,search,9745.07,3292.77,4083.91,0.926413,354.58,-nan,-nan,0.93599,0.0946826,-1.0,-1.0,122.649,4.46073,2752,9990953 +649,delete,47.061,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,153.143,4.45433,2747,9951625 +650,search,9597.89,3275.16,3955.58,0.97772,340.551,-nan,-nan,0.93601,0.0947069,-1.0,-1.0,26.18,4.45433,2747,9951625 +651,delete,32.124,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,237.751,4.44308,2737,9927065 +652,search,9674.43,3278.14,4048.95,0.952878,349.319,-nan,-nan,0.93563,0.0950678,-1.0,-1.0,42.675,4.44332,2738,9927065 +653,delete,111.208,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,767.84,4.39339,2699,9831098 +654,search,9559.78,3296.82,3997.68,0.923438,343.085,-nan,-nan,0.93507,0.0955935,-1.0,-1.0,97.221,4.39493,2706,9831098 +655,delete,393.376,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,2648,4.22352,2553,9462172 +656,search,9088.8,3337.81,3819.4,0.939661,323.689,-nan,-nan,0.93215,0.0989428,-1.0,-1.0,441.031,4.23052,2598,9462172 +657,delete,248.831,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,805.843,4.14089,2500,9218902 +658,search,8785.22,3312.64,3621.88,1.01696,306.948,-nan,-nan,0.92901,0.101543,-1.0,-1.0,121.603,4.14251,2510,9218902 +659,delete,158.515,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,686.806,4.08757,2470,9106546 +660,search,8589.87,3310.2,3516.63,1.01436,291.557,-nan,-nan,0.92807,0.102185,-1.0,-1.0,71.996,4.08802,2474,9106546 +661,delete,62.917,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,177.053,4.07751,2466,9059776 +662,search,8689.94,3292.71,3591.6,0.995117,308.226,-nan,-nan,0.92799,0.102562,-1.0,-1.0,24.414,4.07751,2466,9059776 +663,delete,111.783,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,360.318,4.05513,2447,8990616 +664,search,8712.99,3288.01,3651.25,0.900074,321.137,-nan,-nan,0.92703,0.10347,-1.0,-1.0,49.393,4.05522,2449,8990616 +665,delete,61.884,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,368.893,4.03409,2437,8937437 +666,search,8673.75,3284.6,3623.98,0.962454,319.77,-nan,-nan,0.9271,0.103282,-1.0,-1.0,56.773,4.03447,2440,8937437 +667,delete,221.628,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1216.57,3.94932,2368,8766390 +668,search,8459.26,3307.04,3552.03,0.909869,310.033,-nan,-nan,0.92629,0.104205,-1.0,-1.0,162.889,3.95188,2382,8766390 +669,delete,258.568,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,2073.57,3.83919,2268,8532008 +670,search,8140.76,3360.68,3426.4,0.946264,293.12,-nan,-nan,0.92603,0.104299,-1.0,-1.0,383.893,3.84421,2304,8532008 +671,delete,42.679,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,232.255,3.82834,2293,8489178 +672,search,8180.28,3297.18,3408.37,0.931198,297.496,-nan,-nan,0.9259,0.104167,-1.0,-1.0,103.511,3.82927,2297,8489178 +673,delete,81.055,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,319.232,3.79866,2276,8421866 +674,search,8046.67,3295.45,3332.28,1.00095,287.387,-nan,-nan,0.92554,0.104397,-1.0,-1.0,86.08,3.79943,2281,8421866 +675,delete,181.053,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,842.799,3.74487,2235,8288319 +676,search,7904.63,3299.38,3254.47,0.975021,280.612,-nan,-nan,0.92489,0.105515,-1.0,-1.0,79.637,3.74522,2239,8288319 +677,delete,246.514,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,454.167,3.66822,2213,8072197 +678,search,7796.11,3264.86,3202.44,0.925357,275.602,-nan,-nan,0.92749,0.102292,-1.0,-1.0,102.958,3.66904,2219,8072197 +679,delete,39.997,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,328.588,3.65016,2209,8036947 +680,search,7760.4,3260.04,3169.25,0.9914,270.976,-nan,-nan,0.92761,0.102059,-1.0,-1.0,56.248,3.65058,2211,8036947 +681,delete,12.87,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,31.684,3.65058,2211,8026197 +682,search,7788.1,3254.69,3192.28,0.949667,273.708,-nan,-nan,0.92772,0.10182,-1.0,-1.0,31.897,3.65058,2211,8026197 +683,delete,344.993,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1739.17,3.53022,2099,7744229 +684,search,7446.18,3308.5,3064.19,1.01988,267.961,-nan,-nan,0.92699,0.103042,-1.0,-1.0,233.063,3.53481,2123,7744229 +685,delete,255.497,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1413.79,3.43509,2027,7541066 +686,search,7075.42,3338.17,2877.98,1.04052,236.815,-nan,-nan,0.92403,0.105621,-1.0,-1.0,449.89,3.44371,2073,7541066 +687,delete,14.792,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,100.752,3.43771,2069,7522190 +688,search,7141.55,3253.29,2879.69,1.08136,239.199,-nan,-nan,0.92397,0.105999,-1.0,-1.0,74.399,3.4378,2072,7522190 +689,delete,152.383,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,550.761,3.38116,2034,7409400 +690,search,7184.57,3265.98,2951.58,0.964671,250.458,-nan,-nan,0.92259,0.106918,-1.0,-1.0,112.715,3.38232,2041,7409400 +691,delete,48.128,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,92.759,3.37629,2036,7375648 +692,search,7133.73,3246.25,2904.7,0.989166,249.998,-nan,-nan,0.92278,0.106719,-1.0,-1.0,39.792,3.37637,2037,7375648 +693,delete,227.718,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,591.912,3.30543,2007,7222068 +694,search,6878.86,3228.44,2745.95,1.0217,229.58,-nan,-nan,0.9227,0.106788,-1.0,-1.0,41.252,3.30544,2008,7222068 +695,delete,34.577,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,224.431,3.29162,2003,7196331 +696,search,6997.54,3237.2,2837.33,0.98719,241.093,-nan,-nan,0.92377,0.105733,-1.0,-1.0,86.885,3.29243,2007,7196331 +697,delete,33.48,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,170.132,3.28305,1999,7170716 +698,search,7102.67,3224.74,2928.48,0.928866,264.564,-nan,-nan,0.92339,0.106288,-1.0,-1.0,40.712,3.28317,2000,7170716 +699,delete,14.509,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,89.675,3.27644,1997,7155255 +700,search,6927.19,3227.36,2785.67,0.967335,234.12,-nan,-nan,0.92383,0.105874,-1.0,-1.0,70.937,3.27691,2001,7155255 +701,delete,74.228,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,135.817,3.26529,1994,7097733 +702,search,6835.54,3201.78,2711.68,1.08648,225.869,-nan,-nan,0.92316,0.106502,-1.0,-1.0,37.848,3.26548,1995,7097733 +703,delete,262.506,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,856.063,3.17323,1934,6924172 +704,search,6632.87,3218.5,2642.62,1.0407,216.845,-nan,-nan,0.92275,0.106903,-1.0,-1.0,153.93,3.17563,1945,6924172 +705,delete,27.772,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,127.647,3.1674,1936,6896276 +706,search,6802.06,3205.79,2759.98,0.973302,236.047,-nan,-nan,0.92327,0.106137,-1.0,-1.0,60.425,3.16774,1939,6896276 +707,delete,638.581,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,3396.94,2.8861,1661,6385507 +708,search,6175.15,3510.99,2659.52,0.915727,234.345,-nan,-nan,0.91978,0.107625,-1.0,-1.0,916.921,2.90278,1773,6385507 +709,delete,178.742,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,979.522,2.80925,1690,6207658 +710,search,5934.96,3276.84,2517.29,0.936159,221.821,-nan,-nan,0.91581,0.110963,-1.0,-1.0,324.571,2.81528,1724,6207658 +711,delete,49.498,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,241.066,2.79655,1713,6162720 +712,search,5716.21,3182.24,2292.91,1.07444,183.238,-nan,-nan,0.91483,0.1117,-1.0,-1.0,86.556,2.79725,1719,6162720 +713,delete,329.933,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1253.69,2.67509,1639,5927803 +714,search,5628.29,3209.1,2302.97,1.05357,196.002,-nan,-nan,0.91193,0.114737,-1.0,-1.0,99.351,2.67708,1651,5927803 +715,delete,23.293,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,146.326,2.66421,1639,5895666 +716,search,5657.55,3189.56,2399.94,0.941059,212.49,-nan,-nan,0.91173,0.115093,-1.0,-1.0,98.142,2.66562,1644,5895666 +717,delete,31.932,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,100.692,2.65694,1637,5868774 +718,search,5643.63,3182.37,2282.38,0.994469,190.666,-nan,-nan,0.91138,0.115746,-1.0,-1.0,25.864,2.65699,1639,5868774 +719,delete,281.875,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1706.61,2.49714,1470,5533540 +720,search,5215.64,3365.4,2151.1,0.956341,182.325,-nan,-nan,0.90702,0.118125,-1.0,-1.0,460.029,2.50549,1515,5533540 +721,delete,99.453,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,303.756,2.45168,1485,5418387 +722,search,5066.1,3255.83,2205.46,0.923712,189.657,-nan,-nan,0.90554,0.119664,-1.0,-1.0,202.548,2.45331,1499,5418387 +723,delete,18.613,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,76.981,2.44739,1494,5398291 +724,search,5277.47,3209.83,2152.41,0.952442,188.22,-nan,-nan,0.90587,0.119432,-1.0,-1.0,140.266,2.44772,1500,5398291 +725,delete,146.883,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,640.088,2.39318,1452,5273546 +726,search,4987.36,3204.66,2116.23,0.919338,181.374,-nan,-nan,0.90319,0.121324,-1.0,-1.0,206.113,2.39437,1466,5273546 +727,delete,104.103,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,559.546,2.34976,1420,5180937 +728,search,5005.79,3224.46,2056.94,1.01626,178.183,-nan,-nan,0.90313,0.120974,-1.0,-1.0,205.656,2.35276,1443,5180937 +729,delete,123.701,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,362.516,2.30332,1402,5079524 +730,search,4861.51,3173.26,2036.11,0.941638,179.697,-nan,-nan,0.90119,0.121815,-1.0,-1.0,71.166,2.30503,1412,5079524 +731,delete,42.817,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,206.033,2.28547,1396,5019265 +732,search,4792.51,3131.57,2019.15,0.948738,175.901,-nan,-nan,0.90094,0.122367,-1.0,-1.0,32.216,2.28554,1398,5019265 +733,delete,81.285,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,189.133,2.26634,1385,4955565 +734,search,4810.11,3102.42,1925.99,0.990051,165.545,-nan,-nan,0.89995,0.123379,-1.0,-1.0,49.28,2.26686,1387,4955565 +735,delete,200.653,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,593.938,2.17991,1340,4776948 +736,search,4686.78,3217.05,1973.6,0.92489,168.102,-nan,-nan,0.90812,0.115023,-1.0,-1.0,97.832,2.18202,1351,4776948 +737,delete,87.326,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,487.88,2.12778,1312,4654026 +738,search,4519.28,3131.25,1901.16,0.945156,166.783,-nan,-nan,0.90378,0.118179,-1.0,-1.0,124.719,2.12884,1323,4654026 +739,delete,65.781,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,310.02,2.09967,1304,4589888 +740,search,4520.29,3103.79,1821.12,1.02824,154.008,-nan,-nan,0.90319,0.118758,-1.0,-1.0,73.66,2.10051,1308,4589888 +741,delete,223.343,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,687.337,2.01808,1254,4430862 +742,search,4355.51,3123.65,1732.2,1.02468,144.42,-nan,-nan,0.90281,0.119315,-1.0,-1.0,144.062,2.02066,1268,4430862 +743,delete,130.975,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,882.123,1.9235,1194,4237049 +744,search,4199.5,3158.27,1740.92,0.896037,151.911,-nan,-nan,0.90151,0.120762,-1.0,-1.0,317.96,1.92923,1219,4237049 +745,delete,282.582,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1143.26,1.80541,1119,4000195 +746,search,3950,3219.77,1605.8,0.985772,137.949,-nan,-nan,0.8976,0.122308,-1.0,-1.0,255.591,1.80837,1142,4000195 +747,delete,208.048,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,957.105,1.70946,1073,3803954 +748,search,3915.35,3200.49,1621.58,0.913101,146.957,-nan,-nan,0.8953,0.123325,-1.0,-1.0,193.268,1.7128,1089,3803954 +749,delete,82.513,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,212.06,1.68856,1069,3733214 +750,search,3836.31,3154.33,1578.78,0.877801,135.642,-nan,-nan,0.89344,0.124756,-1.0,-1.0,52.054,1.68907,1071,3733214 +751,delete,29.689,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,114.009,1.67885,1062,3709324 +752,search,3770.38,3158.88,1523.88,0.964586,133.075,-nan,-nan,0.89302,0.12482,-1.0,-1.0,31.356,1.67912,1063,3709324 +753,delete,84.481,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,254.955,1.64869,1041,3649123 +754,search,3729.84,3172.58,1536.94,0.971186,133.044,-nan,-nan,0.89149,0.126626,-1.0,-1.0,46.117,1.64889,1043,3649123 +755,delete,35.269,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,105.989,1.63976,1036,3621475 +756,search,3679.84,3162.32,1481.41,1.02511,127.971,-nan,-nan,0.89225,0.125695,-1.0,-1.0,85.422,1.64084,1040,3621475 +757,delete,32.849,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,89.63,1.62761,1034,3594479 +758,search,3722.8,3149.65,1532.03,0.885333,136.826,-nan,-nan,0.89126,0.12634,-1.0,-1.0,42.611,1.62761,1035,3594479 +759,delete,30.204,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,149.995,1.61305,1024,3569055 +760,search,3711.2,3162.86,1532.54,0.920926,134.638,-nan,-nan,0.89122,0.126015,-1.0,-1.0,63.03,1.61392,1028,3569055 +761,delete,52.999,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,107.032,1.59909,1018,3527896 +762,search,3674.31,3141.54,1509.6,0.966863,129.099,-nan,-nan,0.89026,0.126915,-1.0,-1.0,18.227,1.59909,1018,3527896 +763,delete,26.175,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,75.447,1.59218,1013,3509970 +764,search,3641.66,3133.94,1495.75,0.907093,131.236,-nan,-nan,0.88937,0.127486,-1.0,-1.0,18.18,1.59218,1013,3509970 +765,delete,510.968,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1063.08,1.42964,881,3187549 +766,search,3295.33,3320.29,1393.79,0.893897,124.094,-nan,-nan,0.88662,0.128795,-1.0,-1.0,197.499,1.43297,900,3187549 +767,delete,490.407,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1365.86,1.24934,733,2822906 +768,search,2716.7,3527.14,1137.09,0.977732,97.0231,-nan,-nan,0.87531,0.138129,-1.0,-1.0,473.138,1.25893,783,2822906 +769,insert,15.111,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,10.802,1.26179,783,2832899 +770,search,2872.49,3271.73,1198.58,0.995883,101.445,-nan,-nan,0.87683,0.137203,-1.0,-1.0,56.456,1.26225,787,2832899 +771,insert,46.494,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,87.718,1.27537,794,2863523 +772,search,2948.49,3262.69,1238.96,0.881719,109.559,-nan,-nan,0.87816,0.136004,-1.0,-1.0,31.475,1.27553,796,2863523 +773,insert,93.552,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,115.638,1.29805,806,2925169 +774,search,2990.84,3303.88,1272.32,0.930932,109.366,-nan,-nan,0.87943,0.135069,-1.0,-1.0,58.015,1.29815,811,2925169 +775,insert,53.55,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,89.013,1.31457,816,2961356 +776,search,3037.12,3291.58,1285.71,0.905024,105.763,-nan,-nan,0.88021,0.135223,-1.0,-1.0,30.459,1.31474,818,2961356 +777,insert,58.072,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,85.293,1.32966,826,2998678 +778,search,3015.84,3299.7,1249.12,1.00098,109.006,-nan,-nan,0.88102,0.134273,-1.0,-1.0,25.782,1.32969,827,2998678 +779,insert,20.436,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,36.608,1.33358,829,3011024 +780,search,3014.03,3298.15,1246.7,0.976868,103.562,-nan,-nan,0.88197,0.133864,-1.0,-1.0,33.321,1.33396,831,3011024 +781,insert,13.754,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,27.621,1.33712,833,3019515 +782,search,3086.71,3288.45,1313.97,0.925489,110.587,-nan,-nan,0.88129,0.134572,-1.0,-1.0,14.607,1.33712,833,3019515 +783,insert,107.026,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,158.094,1.36263,847,3082298 +784,search,3149.25,3309.21,1339.96,0.937545,117.843,-nan,-nan,0.88256,0.133388,-1.0,-1.0,25.422,1.36274,848,3082298 +785,insert,57.939,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,77.089,1.37973,853,3122090 +786,search,3187.06,3331.58,1357.01,0.880487,121.091,-nan,-nan,0.88446,0.132369,-1.0,-1.0,51.038,1.3799,856,3122090 +787,insert,44.613,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,66.366,1.38862,862,3140294 +788,search,3203.84,3314.85,1363.36,0.879509,117.208,-nan,-nan,0.88468,0.132421,-1.0,-1.0,15.435,1.38862,862,3140294 +789,insert,18.052,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,24.853,1.39165,863,3147819 +790,search,3202.61,3319.15,1355.65,0.884131,114.052,-nan,-nan,0.88451,0.132673,-1.0,-1.0,13.812,1.39165,863,3147819 +791,insert,59.499,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,56.935,1.40444,868,3180668 +792,search,3151.96,3336.91,1303.25,1.02505,109.574,-nan,-nan,0.88512,0.132256,-1.0,-1.0,14.257,1.40444,868,3180668 +793,insert,3.601,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.091,1.40549,868,3183235 +794,search,3173.59,3338.48,1331.45,0.982895,112.068,-nan,-nan,0.8851,0.13227,-1.0,-1.0,14.158,1.40549,868,3183235 +795,insert,108.945,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,138.501,1.43114,881,3242089 +796,search,3273.06,3347.06,1396.94,0.917444,119.104,-nan,-nan,0.88497,0.132689,-1.0,-1.0,26.49,1.43122,882,3242089 +797,insert,8.403,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,23.156,1.43276,883,3247192 +798,search,3269.69,3343.06,1385.7,0.93564,124.171,-nan,-nan,0.88492,0.13288,-1.0,-1.0,14.171,1.43276,883,3247192 +799,insert,21.171,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,24.446,1.4365,884,3254626 +800,search,3239.99,3349.05,1364.26,0.928144,113.689,-nan,-nan,0.88496,0.13286,-1.0,-1.0,14.331,1.4365,884,3254626 +801,insert,41.99,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,111.227,1.44574,893,3274953 +802,search,3338.52,3334.96,1423.37,0.897877,121.546,-nan,-nan,0.88592,0.132115,-1.0,-1.0,61.6,1.44662,897,3274953 +803,insert,1319.56,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1492.12,1.80789,1045,4032688 +804,search,3955.04,3586.04,1755.96,0.919145,151.07,-nan,-nan,0.89453,0.125222,-1.0,-1.0,599.469,1.81082,1107,4032688 +805,insert,29.193,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,56.274,1.81963,1111,4050220 +806,search,4107.15,3364.8,1751.44,0.923408,156.953,-nan,-nan,0.89566,0.124153,-1.0,-1.0,162.287,1.82008,1126,4050220 +807,insert,24.215,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,70.174,1.82768,1131,4067940 +808,search,4119.01,3317.57,1737,0.935885,147.661,-nan,-nan,0.89627,0.123533,-1.0,-1.0,66.288,1.82811,1137,4067940 +809,insert,47.526,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,91.962,1.83993,1146,4099369 +810,search,4110.38,3292.69,1707.16,0.962366,141.682,-nan,-nan,0.89647,0.12303,-1.0,-1.0,32.572,1.84028,1148,4099369 +811,insert,47.788,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,66.324,1.8496,1155,4129509 +812,search,4108.83,3297.03,1695.62,1.00192,139.028,-nan,-nan,0.8966,0.122933,-1.0,-1.0,35.432,1.85006,1157,4129509 +813,insert,84.401,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,121.814,1.8675,1172,4178669 +814,search,4247.29,3287.98,1779.47,0.909623,154.293,-nan,-nan,0.8984,0.121541,-1.0,-1.0,14.212,1.8675,1172,4178669 +815,insert,4.012,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,12.159,1.86812,1172,4180960 +816,search,4166.05,3288.41,1767.86,0.958176,153.946,-nan,-nan,0.89835,0.121585,-1.0,-1.0,9.166,1.86812,1172,4180960 +817,insert,53.453,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,125.024,1.89503,1189,4255359 +818,search,4173.4,3294.31,1824.37,0.930659,164.538,-nan,-nan,0.89893,0.121313,-1.0,-1.0,43.464,1.89565,1194,4255359 +819,insert,23.605,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,27.929,1.90092,1196,4272706 +820,search,4215.1,3291.88,1836.33,0.971918,156.09,-nan,-nan,0.89935,0.120874,-1.0,-1.0,35.885,1.90131,1198,4272706 +821,insert,22.257,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,45.253,1.90882,1200,4287851 +822,search,4232.66,3291.23,1843.67,0.917557,160.74,-nan,-nan,0.89988,0.120557,-1.0,-1.0,42.168,1.90929,1202,4287851 +823,insert,46.029,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,73.245,1.92423,1207,4322788 +824,search,4307.89,3295.01,1777.45,1.0256,151.129,-nan,-nan,0.89929,0.1212,-1.0,-1.0,45.685,1.92456,1209,4322788 +825,insert,117.736,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,174.173,1.95508,1225,4396408 +826,search,4356.31,3294.59,1792.33,1.02452,147.836,-nan,-nan,0.90016,0.12039,-1.0,-1.0,40.736,1.95556,1228,4396408 +827,insert,24.769,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,32.727,1.96276,1230,4415721 +828,search,4290.6,3287.46,1720.53,1.01926,139.704,-nan,-nan,0.89985,0.120601,-1.0,-1.0,29.51,1.96282,1231,4415721 +829,insert,509.979,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,938.835,2.16135,1339,4832079 +830,search,4720.21,3302.54,1933.5,0.98671,160.24,-nan,-nan,0.90402,0.119484,-1.0,-1.0,226.112,2.16324,1361,4832079 +831,insert,46.498,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,74.658,2.17477,1368,4864525 +832,search,4742.23,3249.95,2011.67,0.91734,172.355,-nan,-nan,0.90462,0.119129,-1.0,-1.0,33.322,2.17512,1371,4864525 +833,insert,7.248,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,25.989,2.17674,1374,4874443 +834,search,4810.25,3241.06,2082.09,0.923987,180.818,-nan,-nan,0.90469,0.11905,-1.0,-1.0,16.226,2.17674,1374,4874443 +835,insert,101.847,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,153.998,2.20278,1391,4938267 +836,search,4816.55,3248.8,1940.92,1.01293,163.212,-nan,-nan,0.90528,0.118381,-1.0,-1.0,27.586,2.20294,1392,4938267 +837,insert,23.761,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.383,2.20761,1392,4961147 +838,search,4831.9,3260.72,1946.46,1.00984,159.069,-nan,-nan,0.90517,0.118636,-1.0,-1.0,15.68,2.20761,1392,4961147 +839,insert,77.766,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,96.515,2.24071,1409,5033740 +840,search,4866.19,3276.73,2114.95,0.959087,180.5,-nan,-nan,0.907,0.117484,-1.0,-1.0,75.82,2.24136,1416,5033740 +841,insert,71.438,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,60.774,2.25922,1421,5078736 +842,search,4951.91,3274.4,2007.42,1.00925,169.264,-nan,-nan,0.90719,0.117427,-1.0,-1.0,37.296,2.25933,1423,5078736 +843,insert,523.905,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,696.301,2.43231,1513,5467376 +844,search,5310.44,3318.26,2185.3,0.983241,181.994,-nan,-nan,0.90989,0.115561,-1.0,-1.0,261.173,2.43513,1536,5467376 +845,insert,403.395,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,671.019,2.59483,1618,5815547 +846,search,5593.13,3317.35,2266.97,1.03329,185.94,-nan,-nan,0.91429,0.113114,-1.0,-1.0,152.873,2.59569,1632,5815547 +847,insert,8.305,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.698,2.59744,1632,5821782 +848,search,5513.69,3292.98,2256.71,1.03303,180.017,-nan,-nan,0.9143,0.11294,-1.0,-1.0,50.94,2.59744,1636,5821782 +849,insert,3.287,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.437,2.59799,1636,5825594 +850,search,4999.02,3284.82,2361.3,1.03238,190.633,-nan,-nan,0.91445,0.112822,-1.0,-1.0,16.462,2.59821,1637,5825594 +851,insert,5.925,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,26.711,2.60192,1640,5834880 +852,search,5576.8,3283.64,2332.64,1.05082,188.839,-nan,-nan,0.91452,0.112841,-1.0,-1.0,42.859,2.60244,1641,5834880 +853,insert,41.654,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,45.563,2.61223,1643,5860274 +854,search,5818.24,3292.92,2494.25,0.916033,225.314,-nan,-nan,0.9148,0.112683,-1.0,-1.0,30.451,2.61227,1644,5860274 +855,insert,11.595,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,29.191,2.61362,1645,5866064 +856,search,5809.71,3293.4,2398.37,0.962088,203.074,-nan,-nan,0.91484,0.112508,-1.0,-1.0,19.149,2.61362,1645,5866064 +857,insert,26.349,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,46.176,2.61922,1648,5884456 +858,search,5758.67,3299.35,2484.32,0.951832,221.426,-nan,-nan,0.91471,0.112715,-1.0,-1.0,19.522,2.61922,1648,5884456 +859,insert,49.066,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,136.789,2.6314,1660,5916786 +860,search,5845.32,3291.79,2408.54,0.977346,204.7,-nan,-nan,0.91482,0.112543,-1.0,-1.0,28.226,2.63157,1661,5916786 +861,insert,15.435,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.76,2.63399,1661,5923467 +862,search,5738.55,3294.19,2488.64,0.917706,218.751,-nan,-nan,0.9148,0.112568,-1.0,-1.0,36.327,2.63425,1662,5923467 +863,insert,104.693,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,151.244,2.6673,1676,5997844 +864,search,5818.18,3300.26,2422.45,0.953566,201.917,-nan,-nan,0.91374,0.114248,-1.0,-1.0,44.908,2.66783,1682,5997844 +865,insert,10.728,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,32.945,2.67141,1685,6009561 +866,search,5673.55,3289.61,2450.85,1.04521,208.034,-nan,-nan,0.91357,0.114376,-1.0,-1.0,18.144,2.67141,1685,6009561 +867,insert,70.412,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,106.844,2.68983,1696,6052876 +868,search,5831.31,3286.33,2422.45,1.06762,201.136,-nan,-nan,0.91408,0.11392,-1.0,-1.0,27.101,2.69001,1698,6052876 +869,insert,5.054,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,20.128,2.692,1699,6059234 +870,search,5941.35,3281.35,2565.06,0.949293,224.649,-nan,-nan,0.9139,0.114053,-1.0,-1.0,18.169,2.692,1699,6059234 +871,insert,67.132,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,98.353,2.71167,1706,6098225 +872,search,5918.17,3284.25,2484.84,0.987154,211.227,-nan,-nan,0.91391,0.11407,-1.0,-1.0,37.946,2.71191,1708,6098225 +873,insert,65.028,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,65.355,2.728,1713,6137308 +874,search,6093.23,3287.1,2548.37,0.944851,218.922,-nan,-nan,0.91415,0.113946,-1.0,-1.0,41.397,2.72831,1716,6137308 +875,insert,27.522,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,41.383,2.73491,1718,6154089 +876,search,5938.3,3280.18,2475.92,1.01872,207.334,-nan,-nan,0.91431,0.114022,-1.0,-1.0,43.872,2.73538,1720,6154089 +877,insert,1.247,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,17.398,2.73538,1720,6156061 +878,search,5996.48,3278.76,2446.63,1.02037,201.245,-nan,-nan,0.91432,0.11407,-1.0,-1.0,21.26,2.73538,1720,6156061 +879,insert,381.713,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,562.948,2.86652,1774,6446004 +880,search,6206.05,3323.15,2539.18,1.01071,211.29,-nan,-nan,0.91595,0.113047,-1.0,-1.0,252.891,2.86869,1800,6446004 +881,insert,618.207,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,722.392,3.10055,1893,6969764 +882,search,6544.4,3364.9,2859.76,0.957884,250.627,-nan,-nan,0.919,0.110036,-1.0,-1.0,295.054,3.10513,1925,6969764 +883,insert,522.298,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,836.883,3.30137,2034,7422501 +884,search,6926.79,3348.38,2916.95,1.03984,242.016,-nan,-nan,0.92245,0.107041,-1.0,-1.0,189.052,3.30575,2069,7422501 +885,insert,7.92,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,15.374,3.30958,2069,7432053 +886,search,7124.19,3296.04,2998.04,0.982795,253.085,-nan,-nan,0.92316,0.10638,-1.0,-1.0,66.484,3.31014,2074,7432053 +887,insert,494.913,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,631.358,3.46521,2151,7789886 +888,search,7693.01,3306.91,3241.41,0.952449,289.456,-nan,-nan,0.92506,0.105464,-1.0,-1.0,265.571,3.4691,2179,7789886 +889,insert,563.434,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,780.283,3.65742,2275,8210883 +890,search,8017.01,3292.22,3325.65,0.983852,287.081,-nan,-nan,0.92712,0.10434,-1.0,-1.0,259.332,3.66144,2306,8210883 +891,insert,39.86,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,47.997,3.66902,2309,8240504 +892,search,7992.98,3249.05,3252.46,0.974783,271.663,-nan,-nan,0.92737,0.104403,-1.0,-1.0,83.785,3.66996,2314,8240504 +893,insert,60.129,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,75.148,3.686,2319,8299693 +894,search,8117.78,3251.6,3317.01,0.999886,280.084,-nan,-nan,0.92751,0.104143,-1.0,-1.0,42.049,3.68622,2320,8299693 +895,insert,69.983,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,136.821,3.70384,2333,8349126 +896,search,8113.74,3253.71,3302.22,1.00195,276.903,-nan,-nan,0.92801,0.103786,-1.0,-1.0,32.913,3.70384,2333,8349126 +897,delete,107.01,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,365.217,3.67093,2315,8268842 +898,search,8074.13,3253.85,3288.01,0.999854,274.309,-nan,-nan,0.92779,0.104051,-1.0,-1.0,81.474,3.67193,2321,8268842 +899,delete,22.77,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,108.085,3.6675,2317,8250527 +900,search,8088.5,3242.6,3292.28,0.962454,281.626,-nan,-nan,0.92761,0.104164,-1.0,-1.0,30.915,3.6675,2317,8250527 +901,delete,83.667,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,287.098,3.64756,2298,8185565 +902,search,8154.12,3241.14,3387.37,0.908795,300.697,-nan,-nan,0.92688,0.104648,-1.0,-1.0,61.751,3.64789,2301,8185565 +903,delete,69.543,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,218.688,3.61996,2283,8126915 +904,search,8034.43,3238.69,3300.78,0.946933,285.974,-nan,-nan,0.92564,0.10492,-1.0,-1.0,29.656,3.61996,2283,8126915 +905,delete,36.536,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,115.761,3.61443,2277,8098533 +906,search,7945.63,3233.05,3247.51,0.939565,278.312,-nan,-nan,0.92546,0.104989,-1.0,-1.0,29.345,3.61443,2277,8098533 +907,delete,29.764,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,225.379,3.6035,2270,8074833 +908,search,7925.06,3233.93,3241.39,0.978235,280.245,-nan,-nan,0.92526,0.105143,-1.0,-1.0,115.45,3.60473,2276,8074833 +909,delete,46.568,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,91.035,3.60011,2273,8035274 +910,search,7785.41,3215.71,3106.96,1.06291,260.183,-nan,-nan,0.92549,0.105064,-1.0,-1.0,59.935,3.60048,2275,8035274 +911,delete,119.353,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,241.704,3.58123,2261,7957223 +912,search,7854.02,3197.13,3179.16,0.976882,274.541,-nan,-nan,0.92478,0.105723,-1.0,-1.0,31.974,3.58123,2261,7957223 +913,delete,57.601,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,290.935,3.56155,2243,7917554 +914,search,7864.08,3207.09,3205.65,0.979685,278.804,-nan,-nan,0.92357,0.106165,-1.0,-1.0,111.485,3.56304,2249,7917554 +915,delete,81.007,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,313.246,3.53708,2227,7861503 +916,search,7803.9,3202.53,3182.93,0.976423,278.074,-nan,-nan,0.92276,0.107216,-1.0,-1.0,62.28,3.53754,2230,7861503 +917,delete,23.842,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,129.825,3.53248,2227,7844487 +918,search,7632.59,3198.26,3128.41,0.997114,268.273,-nan,-nan,0.92286,0.107006,-1.0,-1.0,29.288,3.53248,2227,7844487 +919,delete,37.034,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,85.072,3.5276,2223,7814993 +920,search,7583.42,3188.16,3091.53,1.02796,264.319,-nan,-nan,0.92292,0.107079,-1.0,-1.0,40.259,3.52784,2224,7814993 +921,delete,29.02,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,190.299,3.5179,2218,7793855 +922,search,7596.54,3189.39,3111.35,0.963566,267.746,-nan,-nan,0.9229,0.10725,-1.0,-1.0,42.209,3.51818,2219,7793855 +923,delete,69.475,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,248.205,3.50086,2206,7736054 +924,search,7521.33,3177.53,3082.05,0.961771,258.391,-nan,-nan,0.92273,0.107332,-1.0,-1.0,46.193,3.5013,2208,7736054 +925,delete,177.43,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,765.301,3.42751,2151,7587942 +926,search,7351.42,3190.16,2988.32,0.992236,251.693,-nan,-nan,0.92175,0.107907,-1.0,-1.0,149.963,3.42879,2160,7587942 +927,delete,33.092,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,60.499,3.42569,2157,7565670 +928,search,7385.68,3171.99,3020.81,0.965283,251.215,-nan,-nan,0.92136,0.10823,-1.0,-1.0,30.691,3.42569,2157,7565670 +929,delete,61.15,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,180.051,3.41487,2148,7529948 +930,search,7296.59,3168.95,2964.01,1.03978,256.231,-nan,-nan,0.92134,0.108231,-1.0,-1.0,26.125,3.41487,2148,7529948 +931,delete,478.48,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,3311.49,3.16362,1892,7016700 +932,search,6697.84,3342.03,2877.13,0.903922,254.159,-nan,-nan,0.91973,0.10893,-1.0,-1.0,568.619,3.1745,1954,7016700 +933,delete,23.057,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,119.944,3.16085,1946,6980979 +934,search,6714.43,3222.34,2858.92,0.921249,254.983,-nan,-nan,0.92039,0.107853,-1.0,-1.0,145.23,3.16216,1957,6980979 +935,delete,25.269,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,248.98,3.14955,1948,6954250 +936,search,6709.16,3208.5,2775.81,0.985029,237.485,-nan,-nan,0.92031,0.107893,-1.0,-1.0,90.886,3.15102,1952,6954250 +937,delete,32.051,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,133.949,3.14085,1944,6924596 +938,search,6663.56,3205.81,2744.8,1.01366,228.985,-nan,-nan,0.92017,0.108189,-1.0,-1.0,43.405,3.14133,1947,6924596 +939,delete,129.532,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,605.188,3.0938,1902,6784831 +940,search,6521.43,3200.31,2599.81,1.0319,213.406,-nan,-nan,0.91993,0.108758,-1.0,-1.0,62.355,3.09503,1910,6784831 +941,delete,25.125,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,28.633,3.09278,1908,6745819 +942,search,6057.95,3160.23,2638.82,1.00439,224.668,-nan,-nan,0.91899,0.109367,-1.0,-1.0,15.516,3.09278,1908,6745819 +943,delete,2.633,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,25.605,3.09182,1907,6740944 +944,search,5504.76,3158.82,2594.97,0.966075,208.419,-nan,-nan,0.91863,0.109577,-1.0,-1.0,15.307,3.09182,1907,6740944 +945,delete,76.567,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,681.426,3.01797,1844,6627202 +946,search,6479.5,3215.93,2687.87,0.941706,227.006,-nan,-nan,0.91736,0.110218,-1.0,-1.0,204.152,3.02129,1862,6627202 +947,delete,25.394,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,47.344,3.0179,1860,6607194 +948,search,6027.77,3167.16,2668.15,0.91248,227.992,-nan,-nan,0.91686,0.110702,-1.0,-1.0,42.133,3.01857,1863,6607194 +949,delete,40.603,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,141.827,2.99561,1851,6551065 +950,search,6404.01,3155.74,2612.58,0.940302,221.198,-nan,-nan,0.91657,0.110803,-1.0,-1.0,35.622,2.99588,1852,6551065 +951,delete,42.784,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,151.022,2.97454,1839,6506798 +952,search,6362.57,3157.42,2665.3,0.89236,233.043,-nan,-nan,0.9171,0.110359,-1.0,-1.0,52.017,2.97467,1841,6506798 +953,delete,68.291,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,209.461,2.95841,1833,6459301 +954,search,6194.95,3148.65,2540.95,0.956064,214.564,-nan,-nan,0.91648,0.110686,-1.0,-1.0,23.784,2.95841,1833,6459301 +955,delete,24.091,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,32.782,2.95034,1831,6440069 +956,search,6374.56,3147.56,2579.81,0.96323,216.39,-nan,-nan,0.91687,0.110172,-1.0,-1.0,22.646,2.95034,1831,6440069 +957,delete,370.613,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1512.16,2.79081,1703,6132470 +958,search,5997.66,3222.53,2436.98,0.979421,203.501,-nan,-nan,0.91351,0.112397,-1.0,-1.0,269.536,2.79636,1728,6132470 +959,delete,50.178,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,82.837,2.78235,1718,6086241 +960,search,5663.35,3166.32,2371.64,1.01319,195.826,-nan,-nan,0.91224,0.113599,-1.0,-1.0,53.578,2.78275,1721,6086241 +961,delete,26.244,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,77.374,2.77777,1716,6064734 +962,search,5330.47,3158.4,2401.35,1.00028,197.055,-nan,-nan,0.91262,0.113105,-1.0,-1.0,23.055,2.77777,1717,6064734 +963,delete,105.844,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,670.609,2.7184,1663,5967543 +964,search,5522.16,3215.08,2440.74,0.924841,210.347,-nan,-nan,0.91166,0.113295,-1.0,-1.0,82.222,2.72035,1677,5967543 +965,delete,40.779,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,170.586,2.69087,1655,5906381 +966,search,5595.88,3184.75,2305.39,0.980491,194.997,-nan,-nan,0.9106,0.114366,-1.0,-1.0,91.981,2.69247,1664,5906381 +967,delete,49.146,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,226.633,2.67365,1649,5851849 +968,search,5579.82,3158.03,2366.47,0.909297,199.373,-nan,-nan,0.9098,0.114781,-1.0,-1.0,42.222,2.67401,1651,5851849 +969,delete,66.303,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,170.778,2.64791,1640,5783023 +970,search,5641.13,3146.2,2249.6,1.04527,183.558,-nan,-nan,0.90893,0.115404,-1.0,-1.0,19.418,2.64791,1640,5783023 +971,delete,336.887,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1244.59,2.51385,1518,5496517 +972,search,5448.45,3230.97,2250.63,0.918068,186.2,-nan,-nan,0.90756,0.116626,-1.0,-1.0,349.087,2.51878,1552,5496517 +973,delete,285.464,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1018.7,2.39619,1449,5237981 +974,search,4935.48,3210.28,2129.86,0.943171,185.561,-nan,-nan,0.9045,0.119436,-1.0,-1.0,350.097,2.40256,1482,5237981 +975,delete,181.318,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,501.32,2.32805,1416,5099794 +976,search,4721.16,3199.4,2038.06,1.01523,167.26,-nan,-nan,0.90304,0.119631,-1.0,-1.0,101.611,2.33056,1436,5099794 +977,delete,38.095,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,177.039,2.30081,1415,5032210 +978,search,4768.35,3141.31,1957.72,0.990747,161.444,-nan,-nan,0.90137,0.120592,-1.0,-1.0,39.032,2.30135,1419,5032210 +979,delete,9.386,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,25.359,2.29791,1417,5020211 +980,search,4681.12,3126.39,1953.15,0.982788,159.179,-nan,-nan,0.90147,0.120695,-1.0,-1.0,17.881,2.29791,1417,5020211 +981,delete,151.79,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,500.331,2.23675,1377,4902291 +982,search,4755.27,3141.65,1989.99,0.982125,165.793,-nan,-nan,0.89886,0.122328,-1.0,-1.0,63.963,2.23768,1381,4902291 +983,delete,38.134,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,51.482,2.23312,1378,4872577 +984,search,4784,3117.67,1920.96,1.05989,160.374,-nan,-nan,0.89864,0.122252,-1.0,-1.0,18,2.23312,1378,4872577 +985,delete,51.766,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,148.472,2.22007,1367,4836730 +986,search,4818.29,3112.1,1957.1,0.965964,169.206,-nan,-nan,0.89839,0.122823,-1.0,-1.0,38.186,2.22033,1369,4836730 +987,delete,46.385,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,101.708,2.20976,1360,4797164 +988,search,4780.68,3093.87,1931.25,0.944867,164.328,-nan,-nan,0.89798,0.123455,-1.0,-1.0,39.799,2.20997,1362,4797164 +989,delete,16.727,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,15.561,2.20934,1362,4784789 +990,search,4809.28,3082.73,1964.96,0.950913,163.932,-nan,-nan,0.89771,0.123738,-1.0,-1.0,16.827,2.20934,1362,4784789 +991,delete,100.099,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,398.417,2.17137,1331,4705420 +992,search,4739.41,3144.54,1933.05,0.938592,164.542,-nan,-nan,0.90188,0.121299,-1.0,-1.0,151.635,2.17357,1342,4705420 +993,delete,103.314,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,249.255,2.13586,1321,4621807 +994,search,4666.38,3088.42,1900.98,0.923779,165.871,-nan,-nan,0.89891,0.123056,-1.0,-1.0,93.2,2.13629,1329,4621807 +995,delete,87.906,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,381.372,2.09667,1300,4555849 +996,search,4604.49,3086.99,1880.12,0.907386,158.568,-nan,-nan,0.89785,0.123605,-1.0,-1.0,76.485,2.09763,1307,4555849 +997,delete,31.707,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,144.24,2.08419,1301,4526975 +998,search,4513.21,3064.2,1794.3,0.941411,149.117,-nan,-nan,0.89774,0.123485,-1.0,-1.0,66.534,2.08516,1305,4526975 +999,delete,133.73,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,555.722,2.0225,1265,4408448 +1000,search,4454.5,3062.53,1784.84,0.927572,151.794,-nan,-nan,0.89652,0.124518,-1.0,-1.0,123.834,2.02393,1275,4408448 +1001,delete,129.242,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,568.33,1.96835,1232,4303257 +1002,search,4356.01,3071.96,1763.27,0.933816,157.947,-nan,-nan,0.89421,0.126469,-1.0,-1.0,154.688,1.9708,1245,4303257 +1003,delete,48.265,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,195.787,1.94868,1229,4259551 +1004,search,4292.47,3048.88,1717.73,0.932801,142.078,-nan,-nan,0.89382,0.126572,-1.0,-1.0,59.265,1.9491,1233,4259551 +1005,delete,23.494,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,61.493,1.94286,1229,4241434 +1006,search,4277.17,3030.66,1709.1,0.943552,142.721,-nan,-nan,0.89363,0.126881,-1.0,-1.0,14.584,1.94286,1229,4241434 +1007,delete,223.761,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,838.083,1.85308,1166,4052722 +1008,search,4124.64,3059.54,1651.82,1.02057,140.536,-nan,-nan,0.88964,0.12993,-1.0,-1.0,190.751,1.85616,1179,4052722 +1009,delete,382.663,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1100.77,1.69755,1067,3738432 +1010,search,3842.4,3130.69,1582.23,0.921132,134.401,-nan,-nan,0.88676,0.130735,-1.0,-1.0,243.024,1.70115,1084,3738432 +1011,delete,515.85,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1340.08,1.51095,932,3372539 +1012,search,3293.24,3277.58,1317.42,1.068,110.161,-nan,-nan,0.88472,0.130929,-1.0,-1.0,313.144,1.51652,962,3372539 +1013,delete,10.524,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,58.121,1.51169,956,3361432 +1014,search,3365.78,3177.3,1343.29,0.989856,114.279,-nan,-nan,0.88478,0.131664,-1.0,-1.0,45.259,1.51191,959,3361432 +1015,delete,340.819,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1030.48,1.38205,853,3091692 +1016,search,3188.14,3312.89,1350.37,0.902043,114.629,-nan,-nan,0.87991,0.134066,-1.0,-1.0,308.398,1.38728,881,3091692 +1017,delete,373.018,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1287.47,1.23363,757,2775418 +1018,search,2870.8,3416.08,1241.73,0.893312,111.917,-nan,-nan,0.87557,0.137265,-1.0,-1.0,408.173,1.24009,796,2775418 +1019,delete,18.313,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,75.69,1.23148,790,2754073 +1020,search,2929.11,3253.59,1232.59,0.933021,112.664,-nan,-nan,0.8779,0.135259,-1.0,-1.0,85.616,1.23189,796,2754073 +1021,delete,131.864,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,388.617,1.18381,754,2638917 +1022,search,2811.92,3254.98,1189.04,0.904379,104.996,-nan,-nan,0.87558,0.137214,-1.0,-1.0,106.027,1.18544,762,2638917 +1023,delete,102.543,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,268.055,1.1483,725,2556494 +1024,search,2611.47,3276.68,1060.89,1.03394,90.1421,-nan,-nan,0.87272,0.139466,-1.0,-1.0,93.949,1.14961,733,2556494 +1025,insert,56.576,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,97.452,1.16517,741,2594934 +1026,search,2771.12,3256.75,1171.59,0.892604,100.597,-nan,-nan,0.87413,0.138497,-1.0,-1.0,34.325,1.16527,743,2594934 +1027,insert,338.185,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,361.912,1.25338,771,2802105 +1028,search,2890.78,3355.08,1246.93,0.915737,105.212,-nan,-nan,0.87483,0.139294,-1.0,-1.0,159.782,1.25447,784,2802105 +1029,insert,679.525,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,860.88,1.43301,880,3203975 +1030,search,3290.37,3374.04,1417.13,0.953309,120.618,-nan,-nan,0.88207,0.134455,-1.0,-1.0,202.648,1.43399,899,3203975 +1031,insert,904.64,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1065.05,1.72035,989,3830566 +1032,search,3640.03,3520.22,1561,0.997386,126.064,-nan,-nan,0.88724,0.133039,-1.0,-1.0,517.892,1.72271,1017,3830566 +1033,insert,646.268,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,840.538,1.90804,1109,4252669 +1034,search,4096.61,3499.59,1770.55,0.975485,144.375,-nan,-nan,0.89499,0.127553,-1.0,-1.0,631.966,1.91164,1152,4252669 +1035,insert,329.382,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,430.296,2.02542,1194,4512107 +1036,search,4387.99,3422.38,1891.25,0.969788,160.763,-nan,-nan,0.89883,0.12461,-1.0,-1.0,475.673,2.02937,1234,4512107 +1037,insert,14.99,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,26.813,2.03324,1236,4525815 +1038,search,4378.77,3307.26,1794.6,0.988119,141.456,-nan,-nan,0.89988,0.123483,-1.0,-1.0,220.573,2.03326,1249,4525815 +1039,insert,104.204,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,203.865,2.06433,1275,4599215 +1040,search,4431.38,3283.4,1793.06,1.0504,140.956,-nan,-nan,0.90128,0.122274,-1.0,-1.0,139.77,2.06491,1286,4599215 +1041,insert,13.857,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,59.278,2.0701,1290,4609851 +1042,search,4664.4,3261.5,1930.29,0.916854,164.806,-nan,-nan,0.90235,0.121348,-1.0,-1.0,76.995,2.0707,1296,4609851 +1043,insert,30.261,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,27.82,2.07747,1298,4627411 +1044,search,4519.74,3246,1958.23,0.910254,170.97,-nan,-nan,0.90269,0.121305,-1.0,-1.0,25.951,2.07772,1299,4627411 +1045,insert,62.088,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,123.901,2.09343,1311,4670607 +1046,search,4742.83,3262.46,1993.84,0.889041,176.87,-nan,-nan,0.9032,0.121304,-1.0,-1.0,24.488,2.09345,1312,4670607 +1047,insert,8.144,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,35.252,2.09553,1314,4675386 +1048,search,4459.65,3255.48,1909.69,0.98907,157.457,-nan,-nan,0.90305,0.121356,-1.0,-1.0,9.929,2.09553,1314,4675386 +1049,insert,10.894,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.334,2.10047,1315,4689998 +1050,search,4506.8,3257.45,1873.52,1.0344,151.139,-nan,-nan,0.90369,0.120862,-1.0,-1.0,15.844,2.10047,1315,4689998 +1051,insert,167.865,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,190.758,2.14225,1342,4783971 +1052,search,4487.68,3250.86,1941.95,0.994664,158.679,-nan,-nan,0.90316,0.120919,-1.0,-1.0,34.815,2.14243,1344,4783971 +1053,insert,63.391,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,72.781,2.15831,1352,4826219 +1054,search,4542.87,3257.82,1955.95,0.976178,162.332,-nan,-nan,0.90373,0.120619,-1.0,-1.0,15.945,2.15848,1353,4826219 +1055,insert,30.149,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,69.142,2.17345,1365,4862355 +1056,search,4686.35,3257.97,1963.49,1.02686,165.31,-nan,-nan,0.90425,0.119892,-1.0,-1.0,47.518,2.17385,1368,4862355 +1057,insert,9.905,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,26.848,2.17573,1369,4869564 +1058,search,4811.14,3253.76,1956.75,1.04125,160.321,-nan,-nan,0.90433,0.119782,-1.0,-1.0,16.651,2.17573,1369,4869564 +1059,insert,53.775,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,59.305,2.18792,1374,4898570 +1060,search,4716.48,3263.84,1997.5,1.01339,168.056,-nan,-nan,0.90465,0.119572,-1.0,-1.0,21.518,2.18818,1376,4898570 +1061,insert,5.383,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,19.502,2.19038,1378,4907501 +1062,search,4409.23,3262.46,1993.16,0.944083,169.037,-nan,-nan,0.90439,0.11957,-1.0,-1.0,10.004,2.19038,1378,4907501 +1063,insert,6.16,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,21.853,2.19332,1380,4916386 +1064,search,4690.03,3263.34,2023.1,0.948156,169.685,-nan,-nan,0.90471,0.119431,-1.0,-1.0,29.833,2.19348,1381,4916386 +1065,insert,446.955,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,556.525,2.31082,1438,5194839 +1066,search,4648.48,3295.45,2152.48,0.957748,177.65,-nan,-nan,0.90691,0.118037,-1.0,-1.0,89.203,2.31207,1453,5194839 +1067,insert,5.102,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,17.72,2.31435,1455,5200182 +1068,search,4946.77,3259.49,2154.46,0.943549,186.496,-nan,-nan,0.90711,0.117932,-1.0,-1.0,42.406,2.31435,1457,5200182 +1069,insert,57.449,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,91.841,2.32858,1468,5230883 +1070,search,5148.51,3253.88,2113.89,0.999821,174.524,-nan,-nan,0.90804,0.117284,-1.0,-1.0,24.868,2.32863,1469,5230883 +1071,insert,35.271,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,86.293,2.33848,1477,5255659 +1072,search,4502.96,3244.5,2057.62,1.04338,167.686,-nan,-nan,0.90803,0.117259,-1.0,-1.0,34.878,2.339,1479,5255659 +1073,insert,25.441,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,38.025,2.35012,1485,5281693 +1074,search,5060.08,3244.52,2205.24,0.914463,192.152,-nan,-nan,0.90828,0.116864,-1.0,-1.0,33.511,2.35035,1486,5281693 +1075,insert,16.838,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,43.232,2.35376,1490,5290081 +1076,search,5037.78,3234.19,2215.5,0.962368,195.095,-nan,-nan,0.90841,0.116937,-1.0,-1.0,15.015,2.35397,1491,5290081 +1077,insert,20.829,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,25.984,2.36417,1494,5316166 +1078,search,4400.31,3241.65,2080.9,1.03782,169.265,-nan,-nan,0.90879,0.11668,-1.0,-1.0,15.938,2.36423,1495,5316166 +1079,insert,20.597,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,39.112,2.37186,1500,5335531 +1080,search,5157.45,3240.04,2151.48,0.9785,179.071,-nan,-nan,0.90901,0.116445,-1.0,-1.0,30.237,2.37205,1501,5335531 +1081,insert,595.974,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,688.596,2.53025,1582,5678781 +1082,search,5569.47,3262.67,2300.44,1.01978,187.238,-nan,-nan,0.91105,0.115299,-1.0,-1.0,97.589,2.53205,1590,5678781 +1083,insert,2.178,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,15.574,2.53263,1590,5679848 +1084,search,5689.33,3244.69,2375.64,0.925475,207.901,-nan,-nan,0.9111,0.115137,-1.0,-1.0,17.4,2.53263,1590,5679848 +1085,insert,45.297,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,41.8,2.54305,1593,5702205 +1086,search,5464.76,3255.26,2246.62,1.00452,185.484,-nan,-nan,0.91154,0.114971,-1.0,-1.0,22.107,2.5432,1595,5702205 +1087,insert,12.058,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,21.502,2.54677,1597,5715514 +1088,search,5680.85,3253.58,2404.37,0.902058,206.15,-nan,-nan,0.91145,0.114931,-1.0,-1.0,17.667,2.54677,1597,5715514 +1089,insert,623.688,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,612.774,2.71882,1703,6103499 +1090,search,6073.81,3261.48,2548.49,0.934832,222.431,-nan,-nan,0.91473,0.113361,-1.0,-1.0,82.197,2.71944,1712,6103499 +1091,insert,75.685,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,128.193,2.74176,1728,6152505 +1092,search,6077.19,3237.81,2508.04,0.967515,209.56,-nan,-nan,0.91513,0.113379,-1.0,-1.0,28.467,2.74193,1729,6152505 +1093,insert,25.994,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,41.201,2.74881,1731,6171104 +1094,search,6060.12,3239.69,2481.19,1.01685,207.841,-nan,-nan,0.91549,0.113125,-1.0,-1.0,14.463,2.74881,1731,6171104 +1095,insert,480.729,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,837.857,2.92301,1833,6557850 +1096,search,6388.65,3261.93,2604.18,0.95059,216.821,-nan,-nan,0.91765,0.111764,-1.0,-1.0,152.482,2.92361,1848,6557850 +1097,insert,22.789,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,28.138,2.9302,1849,6579289 +1098,search,6307.63,3234.51,2611.06,1.01043,222.265,-nan,-nan,0.91752,0.111966,-1.0,-1.0,28.286,2.93071,1851,6579289 +1099,insert,10.906,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,29.924,2.93607,1854,6591442 +1100,search,6573.15,3234.64,2747.61,0.898512,241.49,-nan,-nan,0.9178,0.111578,-1.0,-1.0,25.793,2.93607,1854,6591442 +1101,insert,61.25,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,170.561,2.95584,1871,6633739 +1102,search,6527.86,3226.18,2746.6,0.915327,240.705,-nan,-nan,0.91821,0.111188,-1.0,-1.0,32.683,2.95586,1872,6633739 +1103,insert,132.34,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,227.155,2.9965,1900,6724357 +1104,search,5952.23,3231.49,2670.39,1.016,218.682,-nan,-nan,0.92025,0.109731,-1.0,-1.0,40.499,2.99662,1904,6724357 +1105,insert,3.487,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,25.005,2.99874,1906,6727059 +1106,search,6605.25,3223.83,2729.5,0.983744,235.876,-nan,-nan,0.92011,0.109839,-1.0,-1.0,17.154,2.99874,1906,6727059 +1107,insert,263.657,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,386.665,3.09005,1951,6950869 +1108,search,6318.72,3267.2,2865.85,0.974536,244.294,-nan,-nan,0.92202,0.108309,-1.0,-1.0,63.686,3.09091,1960,6950869 +1109,insert,6.359,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.755,3.09389,1960,6958173 +1110,search,6765.47,3252.89,2864.33,0.960367,242.737,-nan,-nan,0.92208,0.108343,-1.0,-1.0,22.935,3.09389,1960,6958173 +1111,insert,76.03,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,92.934,3.10972,1970,6995273 +1112,search,6856.06,3256.74,2913.61,0.92153,249.335,-nan,-nan,0.92205,0.108126,-1.0,-1.0,32.376,3.10979,1971,6995273 +1113,insert,86.557,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,106.605,3.13243,1982,7047862 +1114,search,7071.38,3264.3,2945.77,0.928656,254.565,-nan,-nan,0.92269,0.107714,-1.0,-1.0,59.245,3.13307,1986,7047862 +1115,insert,92.851,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,104.933,3.15978,1997,7110727 +1116,search,7106.78,3272.86,2961.72,0.979007,251.075,-nan,-nan,0.92313,0.107396,-1.0,-1.0,68.3,3.16022,2001,7110727 +1117,insert,19.325,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,41.622,3.1648,2003,7125591 +1118,search,7115.06,3272.11,2963.47,0.980256,258.641,-nan,-nan,0.92335,0.107025,-1.0,-1.0,35.809,3.16501,2004,7125591 +1119,insert,10.044,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,48.855,3.16745,2007,7134442 +1120,search,7166.21,3269.02,2993.36,0.963582,255.281,-nan,-nan,0.92291,0.107377,-1.0,-1.0,26.659,3.16745,2007,7134442 +1121,insert,40.499,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,82.465,3.17772,2013,7162109 +1122,search,7196.69,3272.12,3004.92,0.920676,265.424,-nan,-nan,0.92307,0.107277,-1.0,-1.0,52.749,3.17786,2016,7162109 +1123,insert,24.635,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,85.43,3.18388,2023,7179509 +1124,search,7249.23,3258.97,3018.08,0.949831,264.103,-nan,-nan,0.92339,0.107001,-1.0,-1.0,73.501,3.18437,2026,7179509 +1125,insert,18.534,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,40.492,3.18868,2028,7186372 +1126,search,7203.99,3254.27,3004.16,0.967837,261.618,-nan,-nan,0.92327,0.106982,-1.0,-1.0,24.278,3.18868,2028,7186372 +1127,insert,65.978,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,145.384,3.20768,2038,7231450 +1128,search,7168.64,3258.19,2943.62,0.928387,248.795,-nan,-nan,0.92369,0.106766,-1.0,-1.0,70.547,3.2085,2043,7231450 +1129,insert,21.146,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,43.16,3.21306,2045,7243215 +1130,search,7102.41,3251.91,2859.07,1.00815,233.279,-nan,-nan,0.92377,0.106834,-1.0,-1.0,44.489,3.21348,2047,7243215 +1131,insert,69.413,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,68.444,3.22643,2051,7276107 +1132,search,6909.54,3253.76,2943,1.0144,243.564,-nan,-nan,0.92378,0.106792,-1.0,-1.0,27.183,3.22667,2053,7276107 +1133,insert,19.731,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,44.37,3.23416,2060,7292577 +1134,search,6950.39,3244.6,2862.07,0.999231,231.775,-nan,-nan,0.92364,0.106976,-1.0,-1.0,29.465,3.23433,2061,7292577 +1135,insert,9.737,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,29.656,3.23812,2063,7299867 +1136,search,6648.65,3243.02,2915.51,0.986755,239.622,-nan,-nan,0.92358,0.106998,-1.0,-1.0,15.808,3.23812,2063,7299867 +1137,insert,22.685,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,33.283,3.24807,2067,7323342 +1138,search,6963.59,3247.64,2866.57,1.01621,229.424,-nan,-nan,0.92372,0.107019,-1.0,-1.0,59.286,3.24848,2069,7323342 +1139,insert,3.063,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,23.056,3.24897,2069,7325844 +1140,search,7111.16,3246.78,2958.38,0.994153,243.608,-nan,-nan,0.92375,0.106985,-1.0,-1.0,38.727,3.24908,2070,7325844 +1141,insert,315.751,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,279.657,3.34656,2115,7540761 +1142,search,7118.12,3267.28,3004.05,0.984749,245.614,-nan,-nan,0.92434,0.106285,-1.0,-1.0,275.121,3.34934,2139,7540761 +1143,insert,33.736,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,59.202,3.35755,2143,7561926 +1144,search,7434.27,3225.77,2995.35,1.04848,248.808,-nan,-nan,0.92443,0.106309,-1.0,-1.0,98.442,3.35775,2146,7561926 +1145,insert,16.451,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,45.04,3.36165,2148,7571861 +1146,search,7617.27,3226.28,3151.85,0.94853,276.629,-nan,-nan,0.92445,0.106244,-1.0,-1.0,75.937,3.36165,2151,7571861 +1147,insert,34.911,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,53.829,3.3673,2154,7590881 +1148,search,7156.31,3227.89,3171.91,0.911265,276.094,-nan,-nan,0.92466,0.106063,-1.0,-1.0,41.454,3.36779,2158,7590881 +1149,insert,4.727,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,24.529,3.37033,2160,7595507 +1150,search,7468.62,3219.49,3094.68,0.97557,260.237,-nan,-nan,0.92476,0.106112,-1.0,-1.0,27.908,3.37033,2160,7595507 +1151,insert,11.826,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,25.111,3.37268,2160,7601664 +1152,search,7195.41,3222.43,3105.43,0.987124,258.673,-nan,-nan,0.92474,0.106103,-1.0,-1.0,17.886,3.37268,2160,7601664 +1153,delete,24.689,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,143.198,3.36327,2153,7566707 +1154,search,7183.88,3217.59,3128.36,0.948217,265,-nan,-nan,0.9246,0.106044,-1.0,-1.0,24.316,3.3635,2154,7566707 +1155,delete,106.129,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,621.12,3.29238,2104,7396192 +1156,search,6139.06,3221.54,2931.38,0.978245,234.878,-nan,-nan,0.92428,0.105736,-1.0,-1.0,69.353,3.29436,2112,7396192 +1157,delete,209.255,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1416.08,3.15616,1962,7079041 +1158,search,5755.24,3300.25,2807.52,1.01444,221.403,-nan,-nan,0.92245,0.107878,-1.0,-1.0,276.835,3.16314,2007,7079041 +1159,delete,298.805,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,914.855,2.95198,1854,6597115 +1160,search,6442.25,3253.84,2724.99,0.916236,227.551,-nan,-nan,0.91762,0.110606,-1.0,-1.0,320.283,2.95888,1879,6597115 +1161,delete,307.372,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1690.45,2.82687,1761,6308902 +1162,search,6270.04,3268.33,2589.96,0.966959,217.986,-nan,-nan,0.91569,0.112064,-1.0,-1.0,303.483,2.83197,1791,6308902 +1163,delete,130.781,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,865.752,2.76526,1745,6164514 +1164,search,6227.98,3241.27,2578.49,0.918979,222.166,-nan,-nan,0.91585,0.11117,-1.0,-1.0,204.427,2.76905,1764,6164514 +1165,delete,39.004,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,160.526,2.75753,1755,6133412 +1166,search,6165.8,3210.83,2505.95,0.956245,209.22,-nan,-nan,0.91567,0.111051,-1.0,-1.0,42.35,2.75783,1757,6133412 +1167,delete,93.827,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,231.887,2.73848,1743,6057218 +1168,search,6151.53,3186.24,2526.36,0.927492,213.602,-nan,-nan,0.91522,0.110819,-1.0,-1.0,21.899,2.73848,1743,6057218 +1169,delete,30.204,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,155.105,2.72194,1729,6028053 +1170,search,6172.31,3194.29,2542.87,0.939943,220.614,-nan,-nan,0.91234,0.11275,-1.0,-1.0,52.536,2.7225,1732,6028053 +1171,delete,31.925,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,111.514,2.71635,1727,6001880 +1172,search,6038.26,3181.57,2446.36,0.960407,204.136,-nan,-nan,0.91182,0.112911,-1.0,-1.0,33.931,2.71649,1728,6001880 +1173,delete,56.354,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,103.256,2.70904,1723,5957180 +1174,search,6055.06,3161.52,2466.21,0.971374,209.902,-nan,-nan,0.91156,0.113488,-1.0,-1.0,20.88,2.70904,1723,5957180 +1175,delete,22.667,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,19.906,2.70875,1723,5939326 +1176,search,5995.23,3150.14,2408.66,1.00837,196.479,-nan,-nan,0.91173,0.11335,-1.0,-1.0,20.197,2.70875,1723,5939326 +1177,delete,14.492,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,35.417,2.70529,1722,5924145 +1178,search,5922.97,3145.89,2352,1.06397,190.117,-nan,-nan,0.91183,0.113314,-1.0,-1.0,20.726,2.70529,1722,5924145 +1179,delete,77.339,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,347.724,2.67395,1699,5863334 +1180,search,5996.46,3150.76,2442.67,0.924563,206.308,-nan,-nan,0.9112,0.113941,-1.0,-1.0,32.157,2.67419,1700,5863334 +1181,delete,45.501,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,35.964,2.67101,1699,5822703 +1182,search,5961.94,3122.92,2424.82,0.955642,207.795,-nan,-nan,0.91114,0.114233,-1.0,-1.0,19.629,2.67101,1699,5822703 +1183,delete,53.213,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,150.948,2.65428,1690,5775807 +1184,search,5909.32,3111.49,2401.8,0.923841,205.977,-nan,-nan,0.91062,0.114719,-1.0,-1.0,19.47,2.65428,1690,5775807 +1185,delete,34.728,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,156.138,2.64394,1682,5750627 +1186,search,5913.77,3110.13,2404.08,0.909585,210.614,-nan,-nan,0.91058,0.114688,-1.0,-1.0,19.326,2.64394,1682,5750627 +1187,delete,188.726,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,955.969,2.57096,1618,5601207 +1188,search,5720.59,3139.71,2321.65,0.941009,199.815,-nan,-nan,0.90976,0.115495,-1.0,-1.0,154.904,2.57369,1629,5601207 +1189,delete,16.61,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,34.297,2.57213,1628,5586425 +1190,search,5616.57,3115.07,2226.75,1.01029,186.865,-nan,-nan,0.90968,0.115659,-1.0,-1.0,21.036,2.57213,1628,5586425 +1191,delete,19.747,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,41.819,2.56958,1626,5574023 +1192,search,5746.12,3113.22,2346.6,0.93763,207.346,-nan,-nan,0.90971,0.115562,-1.0,-1.0,19.297,2.56958,1626,5574023 +1193,delete,289.465,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1200.74,2.46405,1545,5356157 +1194,search,5434.01,3148.92,2208.42,0.961239,189.746,-nan,-nan,0.90702,0.117283,-1.0,-1.0,164.887,2.46635,1558,5356157 +1195,delete,18.397,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,28.134,2.46485,1557,5340404 +1196,search,5488.29,3115.33,2240.06,0.893272,192.986,-nan,-nan,0.90753,0.11643,-1.0,-1.0,18.838,2.46485,1557,5340404 +1197,delete,64.915,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,58.101,2.45771,1553,5293259 +1198,search,5326.07,3085.46,2095.62,0.994595,171.471,-nan,-nan,0.90728,0.117008,-1.0,-1.0,18.294,2.45771,1553,5293259 +1199,delete,16.95,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,61.415,2.45164,1551,5279787 +1200,search,5472.43,3083.22,2213.28,0.929211,193.071,-nan,-nan,0.90727,0.117018,-1.0,-1.0,18.251,2.45164,1551,5279787 +1201,delete,88.592,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,426.6,2.42044,1521,5216567 +1202,search,5217.55,3110.43,2060.61,1.06206,171.817,-nan,-nan,0.90614,0.117881,-1.0,-1.0,83.186,2.42172,1527,5216567 +1203,delete,28.438,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.577,2.41959,1527,5196947 +1204,search,5311.89,3080.49,2122.38,0.920915,181.444,-nan,-nan,0.90601,0.118062,-1.0,-1.0,27.649,2.4197,1528,5196947 +1205,delete,31.689,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,44.234,2.41344,1526,5168447 +1206,search,5270.82,3064.76,2092.17,0.937265,173.691,-nan,-nan,0.90571,0.118337,-1.0,-1.0,17.3,2.41344,1526,5168447 +1207,delete,26.511,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,120.599,2.40283,1518,5146927 +1208,search,5149.93,3066.41,2001.98,1.00931,162.524,-nan,-nan,0.90454,0.119549,-1.0,-1.0,56.278,2.40367,1521,5146927 +1209,delete,337.631,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,923.496,2.27413,1451,4887612 +1210,search,5109.96,3066.35,2070.94,0.928789,176.315,-nan,-nan,0.90411,0.119034,-1.0,-1.0,100.6,2.27543,1459,4887612 +1211,delete,6.629,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,29.618,2.2739,1458,4882301 +1212,search,4987.77,3051.97,1950.87,0.997806,162.322,-nan,-nan,0.90448,0.118843,-1.0,-1.0,17.349,2.2739,1458,4882301 +1213,delete,150.072,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,509.277,2.21203,1415,4780915 +1214,search,4951.69,3075.11,1963.33,0.983012,165.743,-nan,-nan,0.90263,0.120879,-1.0,-1.0,62.163,2.21251,1418,4780915 +1215,delete,25.264,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,58.672,2.20724,1415,4765751 +1216,search,4916.88,3065.92,1947.45,0.990483,160.306,-nan,-nan,0.90277,0.120751,-1.0,-1.0,34.734,2.20753,1416,4765751 +1217,delete,482.466,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1601.91,2.03999,1263,4452306 +1218,search,4426.29,3193.51,1778.91,1.00594,150.357,-nan,-nan,0.89656,0.125488,-1.0,-1.0,307.754,2.0457,1291,4452306 +1219,delete,117.064,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,385.585,1.99903,1244,4362045 +1220,search,4481.08,3180.58,1845.13,0.93269,161.292,-nan,-nan,0.89545,0.126907,-1.0,-1.0,180.052,2.0022,1259,4362045 +1221,delete,38.735,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,104.012,1.99039,1251,4326917 +1222,search,4476.12,3138.85,1831.19,0.909644,159.615,-nan,-nan,0.89542,0.126868,-1.0,-1.0,38.067,1.99054,1253,4326917 +1223,delete,281.475,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,896.497,1.88366,1174,4109781 +1224,search,4240.16,3180.96,1749,0.909114,150.806,-nan,-nan,0.8914,0.128912,-1.0,-1.0,180.441,1.8862,1189,4109781 +1225,delete,33.502,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,189.55,1.87079,1179,4075879 +1226,search,4236.22,3135.86,1730.99,0.949195,152.637,-nan,-nan,0.89087,0.129167,-1.0,-1.0,99.3,1.87257,1186,4075879 +1227,delete,90.591,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,433.009,1.83105,1156,4006503 +1228,search,4137.93,3168.59,1698.97,0.961493,146.321,-nan,-nan,0.89091,0.129308,-1.0,-1.0,152.246,1.83421,1168,4006503 +1229,delete,103.67,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,505.966,1.78748,1123,3922625 +1230,search,4051.45,3187.96,1670.47,0.951063,144.226,-nan,-nan,0.89014,0.129244,-1.0,-1.0,143.117,1.78983,1135,3922625 +1231,delete,89.355,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,366.43,1.74898,1090,3844860 +1232,search,3926.82,3223.18,1612.22,0.931313,137.361,-nan,-nan,0.88521,0.131135,-1.0,-1.0,139.671,1.75087,1103,3844860 +1233,delete,13.009,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,57.114,1.74637,1101,3831414 +1234,search,3987.85,3173.4,1633.71,0.885209,143.665,-nan,-nan,0.88513,0.131591,-1.0,-1.0,31.9,1.7466,1102,3831414 +1235,delete,179.976,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,692.848,1.67096,1044,3684234 +1236,search,3813.82,3201.5,1587.4,0.934488,140.292,-nan,-nan,0.88144,0.135014,-1.0,-1.0,133.629,1.67336,1055,3684234 +1237,delete,14.063,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,21.137,1.67182,1054,3669074 +1238,search,3793.04,3169.91,1560.75,0.933636,133.603,-nan,-nan,0.88167,0.134354,-1.0,-1.0,40.305,1.67211,1056,3669074 +1239,delete,60.95,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,84.417,1.66057,1047,3620984 +1240,search,3762.59,3131.5,1540.38,0.911211,135.353,-nan,-nan,0.88146,0.134489,-1.0,-1.0,27.15,1.66068,1048,3620984 +1241,delete,41.744,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,81.41,1.65354,1043,3580113 +1242,search,3757.74,3099.18,1524.12,0.926788,134.761,-nan,-nan,0.88133,0.134234,-1.0,-1.0,17.46,1.65354,1043,3580113 +1243,delete,59.004,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,250.871,1.62558,1020,3533909 +1244,search,3656.35,3122.9,1487.97,0.929771,132.286,-nan,-nan,0.87977,0.135232,-1.0,-1.0,42.885,1.62612,1022,3533909 +1245,delete,14.547,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,38.366,1.6235,1020,3519590 +1246,search,3593.66,3110.72,1442.89,0.968076,122.645,-nan,-nan,0.87964,0.135429,-1.0,-1.0,17.252,1.6235,1020,3519590 +1247,delete,75.79,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,116.151,1.5895,996,3452537 +1248,search,3577.43,3125.93,1445.25,0.894424,120.004,-nan,-nan,0.88126,0.133253,-1.0,-1.0,47.465,1.58995,999,3452537 +1249,delete,38.898,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,111.044,1.58048,991,3416711 +1250,search,3522.93,3106.46,1410.81,1.00246,123.055,-nan,-nan,0.88087,0.133839,-1.0,-1.0,16.34,1.58048,991,3416711 +1251,delete,38.856,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,82.257,1.56858,983,3387653 +1252,search,3467.03,3100.82,1411.56,1.05259,122.019,-nan,-nan,0.88061,0.134227,-1.0,-1.0,27.932,1.56871,984,3387653 +1253,delete,18.183,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,49.758,1.56074,980,3372157 +1254,search,3468.8,3097.95,1421.26,0.949843,124.194,-nan,-nan,0.88063,0.134351,-1.0,-1.0,18.312,1.56074,980,3372157 +1255,delete,167.292,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,175.685,1.50294,949,3258215 +1256,search,3412.51,3096.42,1382.45,0.921565,123.794,-nan,-nan,0.8775,0.135857,-1.0,-1.0,52.547,1.50317,952,3258215 +1257,delete,51.289,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,119.908,1.4855,941,3223657 +1258,search,3303.99,3083.01,1301.56,1.00455,111.083,-nan,-nan,0.87674,0.136303,-1.0,-1.0,57.725,1.48601,944,3223657 +1259,delete,59.788,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,193.63,1.46375,927,3174982 +1260,search,3234.68,3078.64,1280.54,1.00397,106.723,-nan,-nan,0.87499,0.137272,-1.0,-1.0,45.937,1.46432,929,3174982 +1261,delete,25.255,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.959,1.46279,929,3157038 +1262,search,3266.43,3051.53,1278.55,1.00793,110.198,-nan,-nan,0.87591,0.136551,-1.0,-1.0,15.509,1.46279,929,3157038 +1263,delete,133.502,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,314.586,1.41461,905,3058847 +1264,search,3241.26,3052.12,1314.07,0.931101,111.88,-nan,-nan,0.87369,0.137713,-1.0,-1.0,100.687,1.41579,911,3058847 +1265,delete,401.346,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,499.2,1.29095,818,2833531 +1266,search,2983.71,3124.46,1219.18,0.924809,108.777,-nan,-nan,0.86839,0.140311,-1.0,-1.0,136.649,1.29221,829,2833531 +1267,delete,74.814,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,226.107,1.26164,809,2763793 +1268,search,2825.32,3078.26,1157.63,1.01784,98.1842,-nan,-nan,0.86823,0.14007,-1.0,-1.0,45.507,1.2626,815,2763793 +1269,delete,107.037,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,235.988,1.19778,781,2627384 +1270,search,2510.3,3100.44,1157.62,0.929711,105.215,-nan,-nan,0.86851,0.139332,-1.0,-1.0,55.242,1.19901,788,2627384 +1271,delete,48.256,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,179.53,1.16272,763,2553476 +1272,search,2627.24,3089.51,1057.76,1.08033,90.1717,-nan,-nan,0.86737,0.140326,-1.0,-1.0,83.334,1.16378,769,2553476 +1273,delete,98.075,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,272.742,1.11092,727,2443067 +1274,search,2630.83,3104.95,1081.69,0.943602,100.004,-nan,-nan,0.86516,0.141377,-1.0,-1.0,69.494,1.11178,732,2443067 +1275,delete,22.57,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,23.779,1.10804,730,2421654 +1276,search,2545.83,3068.28,1063.37,0.942027,89.9401,-nan,-nan,0.8659,0.140918,-1.0,-1.0,26.709,1.10805,731,2421654 +1277,delete,40.245,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,81.475,1.09764,723,2391396 +1278,search,2479.67,3055.98,1051.37,0.910048,90.4225,-nan,-nan,0.8654,0.140847,-1.0,-1.0,19.58,1.09792,724,2391396 +1279,delete,21.315,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,57.374,1.09117,719,2367854 +1280,search,2559.22,3039.74,1060.02,0.905771,99.6779,-nan,-nan,0.8642,0.141876,-1.0,-1.0,18.086,1.0915,720,2367854 diff --git a/scripts/big_ann_perf_numbers/perf_debug_scan_0.15_counters.csv b/scripts/big_ann_perf_numbers/perf_debug_scan_0.15_counters.csv new file mode 100644 index 00000000..ff5c1f64 --- /dev/null +++ b/scripts/big_ann_perf_numbers/perf_debug_scan_0.15_counters.csv @@ -0,0 +1,1280 @@ +step_num,step_type,search_latency_ms,worker_partition_size,worker_scan_time_ms,worker_scan_throughput,worker_result_time_ms,measured_ipc,cache_miss_rate,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +2,search,3343.64,37.4413,563.1,0.382835,418.41,0.771449,4.85742,0.8551,0.130106,-1.0,-1.0,11.008,0.0184881,1000,38806 +3,insert,22.364,-1.0,-1.0,-1.0,-1.0,19.806,0.022655,996,49334 +4,search,2642.33,64.8478,242.19,0.677423,156.2,0.869095,22.2654,0.86686,0.128427,-1.0,-1.0,29.982,0.0226179,991,49334 +5,insert,19.66,-1.0,-1.0,-1.0,-1.0,171.169,0.0329472,982,73557 +6,search,2610.23,185.601,366.063,0.637806,144.764,1.42254,9.84325,0.92575,0.103236,-1.0,-1.0,137.704,0.0329835,983,73557 +7,insert,24.241,-1.0,-1.0,-1.0,-1.0,141.555,0.0426531,985,95766 +8,search,2605.64,234.625,294.752,0.825211,126.344,1.06839,24.9182,0.92447,0.103861,-1.0,-1.0,83.391,0.0429,989,95766 +9,insert,3.621,-1.0,-1.0,-1.0,-1.0,70.924,0.044738,989,100025 +10,search,2635.35,241.911,371.061,0.66167,137.947,1.41836,14.0481,0.92708,0.100706,-1.0,-1.0,92.459,0.0448066,995,100025 +11,insert,14.855,-1.0,-1.0,-1.0,-1.0,75.578,0.0498131,996,111417 +12,search,2707.07,277.335,468.483,0.591891,140.019,1.75245,10.7512,0.92551,0.101769,-1.0,-1.0,76.195,0.0498433,997,111417 +13,insert,19.283,-1.0,-1.0,-1.0,-1.0,77.777,0.0612885,999,137139 +14,search,2636.59,317.883,348.06,0.761631,127.324,1.44851,12.7546,0.92122,0.104957,-1.0,-1.0,18.974,0.0614097,1001,137139 +15,insert,25.797,-1.0,-1.0,-1.0,-1.0,16.905,0.069717,1003,156710 +16,search,2698.78,347.826,372.411,0.72489,137.629,1.73887,9.49277,0.91945,0.105125,-1.0,-1.0,16.094,0.069719,1005,156710 +17,insert,3.622,-1.0,-1.0,-1.0,-1.0,9.838,0.0716876,1007,161773 +18,search,2673.24,360.089,304.494,0.782145,129.382,1.40476,22.7395,0.92035,0.105235,-1.0,-1.0,17.054,0.072065,1011,161773 +19,insert,31.1,-1.0,-1.0,-1.0,-1.0,13.682,0.0788819,1015,177161 +20,search,2735.89,388.83,379.232,0.730813,124.612,1.73328,10.7717,0.9237,0.102574,-1.0,-1.0,14.512,0.0788827,1018,177161 +21,insert,336.849,-1.0,-1.0,-1.0,-1.0,204.04,0.201255,1082,448898 +22,search,2981.66,748.264,505.422,0.885998,104.243,1.87153,8.90268,0.90797,0.109463,-1.0,-1.0,67.432,0.201722,1103,448898 +23,insert,386.262,-1.0,-1.0,-1.0,-1.0,283.23,0.32894,1171,733493 +24,search,3297.87,989.892,671.849,0.850398,104.19,1.89335,6.3205,0.90064,0.113494,-1.0,-1.0,102.887,0.32979,1203,733493 +25,insert,35.669,-1.0,-1.0,-1.0,-1.0,26.802,0.347361,1210,777443 +26,search,3367.47,944.33,686.981,0.943532,102.309,2.07415,8.01136,0.89896,0.114829,-1.0,-1.0,29.189,0.347529,1218,777443 +27,insert,25.796,-1.0,-1.0,-1.0,-1.0,11.594,0.358526,1219,805394 +28,search,3436.43,953.917,732.879,0.8747,93.6469,1.99291,7.76607,0.89871,0.114554,-1.0,-1.0,23.108,0.358793,1223,805394 +29,insert,53.579,-1.0,-1.0,-1.0,-1.0,51.158,0.385772,1236,866391 +30,search,3510.98,1001.37,779.529,0.838457,95.0301,1.96025,7.48291,0.90178,0.113257,-1.0,-1.0,30.802,0.385827,1242,866391 +31,insert,453.894,-1.0,-1.0,-1.0,-1.0,330.287,0.55272,1322,1239816 +32,search,3824.11,1238.56,955.957,0.871054,94.2941,2.14795,7.71408,0.8971,0.117045,-1.0,-1.0,65.733,0.553069,1335,1239816 +33,insert,61.077,-1.0,-1.0,-1.0,-1.0,29.433,0.573909,1342,1291211 +34,search,3915.99,1244.23,1018.2,0.885409,108.255,2.15544,6.91559,0.89721,0.117937,-1.0,-1.0,21.523,0.573983,1345,1291211 +35,insert,44.337,-1.0,-1.0,-1.0,-1.0,47.193,0.585607,1359,1324978 +36,search,3950.25,1244.81,1030.4,0.866789,106.53,2.09807,8.16167,0.89696,0.1175,-1.0,-1.0,10.219,0.585607,1359,1324978 +37,insert,46.826,-1.0,-1.0,-1.0,-1.0,50.667,0.606676,1369,1371885 +38,search,3900.73,1263.54,928.406,0.916513,99.0434,2.0626,6.60548,0.89727,0.117808,-1.0,-1.0,15.693,0.606676,1370,1371885 +39,insert,8.734,-1.0,-1.0,-1.0,-1.0,11.475,0.609952,1371,1379335 +40,search,3965.23,1266.36,1042.24,0.84002,106.561,2.07557,7.68403,0.89724,0.118217,-1.0,-1.0,11.15,0.609952,1371,1379335 +41,insert,35.985,-1.0,-1.0,-1.0,-1.0,34.149,0.624036,1378,1413312 +42,search,4021.23,1272.79,1064.81,0.898335,104.657,2.13308,10.7149,0.89779,0.118505,-1.0,-1.0,10.196,0.624036,1378,1413312 +43,insert,12.111,-1.0,-1.0,-1.0,-1.0,12.928,0.628448,1379,1423411 +44,search,3987.84,1284.37,996.45,0.897737,97.177,2.07377,8.67195,0.89837,0.117447,-1.0,-1.0,11.555,0.628448,1379,1423411 +45,insert,201.309,-1.0,-1.0,-1.0,-1.0,26.144,0.643687,1386,1457559 +46,search,4010,1303.52,1040.92,0.897942,90.9448,2.13535,9.09615,0.89876,0.116768,-1.0,-1.0,12.739,0.643687,1386,1457559 +47,insert,294.876,-1.0,-1.0,-1.0,-1.0,256.013,0.747053,1426,1688593 +48,search,4246.99,1429.64,1211.66,0.880839,104.637,2.10042,8.35542,0.90176,0.116429,-1.0,-1.0,101.369,0.747412,1441,1688593 +49,insert,35.647,-1.0,-1.0,-1.0,-1.0,24.157,0.762204,1444,1723505 +50,search,4122.35,1426.84,1183.31,0.910668,113.808,2.10762,8.20371,0.90318,0.115166,-1.0,-1.0,51.665,0.762425,1451,1723505 +51,insert,337.921,-1.0,-1.0,-1.0,-1.0,301.76,0.902133,1516,2035040 +52,search,4519.27,1548.71,1310.07,0.888803,120.79,2.16496,9.48027,0.90624,0.113443,-1.0,-1.0,30.25,0.902531,1522,2035040 +53,insert,32.286,-1.0,-1.0,-1.0,-1.0,17.193,0.9201,1524,2078341 +54,search,4291.99,1566.1,1214.59,0.983559,112.032,2.17062,9.11406,0.90635,0.113561,-1.0,-1.0,14.357,0.920122,1525,2078341 +55,insert,414.422,-1.0,-1.0,-1.0,-1.0,378.968,1.06594,1589,2399905 +56,search,4656.09,1719.22,1388.49,0.955747,136.796,2.30258,7.68155,0.90836,0.114592,-1.0,-1.0,140.806,1.06696,1618,2399905 +57,insert,24.043,-1.0,-1.0,-1.0,-1.0,19.971,1.07463,1621,2419836 +58,search,4499.89,1672.88,1338.3,0.986193,125.925,2.20212,7.14915,0.90736,0.115037,-1.0,-1.0,23.35,1.07465,1625,2419836 +59,insert,189.91,-1.0,-1.0,-1.0,-1.0,125.22,1.17032,1645,2643083 +60,search,4935.21,1720.98,1434.96,0.942602,128.949,2.1497,8.73685,0.90031,0.123055,-1.0,-1.0,35.802,1.17043,1649,2643083 +61,insert,10.306,-1.0,-1.0,-1.0,-1.0,19.587,1.17387,1652,2653064 +62,search,4929.23,1716.9,1412.38,0.954052,124.956,8.52278,8.71836,0.90004,0.122916,-1.0,-1.0,12.513,1.17387,1652,2653064 +63,insert,3.187,-1.0,-1.0,-1.0,-1.0,9.73,1.17504,1652,2656118 +64,search,4516.69,1718.57,1328.51,1.04822,120.057,4.06057,8.74473,0.90016,0.122751,-1.0,-1.0,12.269,1.17505,1653,2656118 +65,insert,64.47,-1.0,-1.0,-1.0,-1.0,104.263,1.20551,1684,2723424 +66,search,4853.78,1720.22,1428.59,0.972227,124.353,2.16736,8.30377,0.90025,0.122556,-1.0,-1.0,14.435,1.20551,1684,2723424 +67,insert,44.175,-1.0,-1.0,-1.0,-1.0,81.441,1.22545,1701,2769021 +68,search,5135.36,1731.87,1498.32,0.959422,138.435,2.15068,7.8652,0.90187,0.121292,-1.0,-1.0,21.422,1.22545,1703,2769021 +69,insert,50.072,-1.0,-1.0,-1.0,-1.0,92.467,1.24732,1722,2821777 +70,search,4718.97,1733.53,1352.57,1.08966,116.895,2.11711,9.00953,0.90376,0.11984,-1.0,-1.0,26.386,1.24732,1723,2821777 +71,insert,23.904,-1.0,-1.0,-1.0,-1.0,26.357,1.25196,1725,2834921 +72,search,5102.67,1743.51,1485.33,0.93513,124.501,2.14531,7.66143,0.90416,0.119667,-1.0,-1.0,15.783,1.25196,1725,2834921 +73,insert,5.999,-1.0,-1.0,-1.0,-1.0,19.696,1.2547,1726,2842044 +74,search,5070.19,1746.59,1493.19,0.962098,141.744,2.09811,8.10587,0.90418,0.119697,-1.0,-1.0,12.176,1.2547,1726,2842044 +75,insert,18.137,-1.0,-1.0,-1.0,-1.0,21.395,1.2626,1728,2858890 +76,search,5043.96,1754.18,1507.28,0.93519,136.494,2.16475,6.54169,0.90493,0.119199,-1.0,-1.0,11.566,1.2626,1728,2858890 +77,insert,22.586,-1.0,-1.0,-1.0,-1.0,17.391,1.27306,1730,2882818 +78,search,4970.02,1764.11,1497.4,0.963509,146.672,2.23834,8.54019,0.90469,0.119578,-1.0,-1.0,17.287,1.27306,1730,2882818 +79,insert,476.204,-1.0,-1.0,-1.0,-1.0,33.669,1.30089,1735,2947806 +80,search,5231.19,1789.52,1489.09,1.01418,139.036,2.18478,8.27512,0.90501,0.119413,-1.0,-1.0,18.048,1.30089,1735,2947806 +81,insert,39.31,-1.0,-1.0,-1.0,-1.0,23.07,1.31258,1737,2976895 +82,search,5049.26,1798.55,1491.55,1.06826,140.593,2.1474,7.60697,0.90594,0.118494,-1.0,-1.0,18.058,1.31258,1737,2976895 +83,insert,16.114,-1.0,-1.0,-1.0,-1.0,30.759,1.31819,1740,2990682 +84,search,5118.52,1802.31,1544.3,0.981751,135.291,2.25565,7.38681,0.90639,0.117924,-1.0,-1.0,21.853,1.31824,1741,2990682 +85,insert,37.238,-1.0,-1.0,-1.0,-1.0,38.969,1.3335,1746,3025613 +86,search,5110.87,1811.22,1485.08,1.04874,114.62,2.15143,6.87409,0.90683,0.117967,-1.0,-1.0,24.905,1.33371,1747,3025613 +87,insert,532.086,-1.0,-1.0,-1.0,-1.0,654.492,1.53826,1855,3468632 +88,search,5496.24,1950.7,1697.82,0.986497,156.852,2.12916,7.99709,0.91167,0.112324,-1.0,-1.0,104.648,1.53851,1871,3468632 +89,insert,401.346,-1.0,-1.0,-1.0,-1.0,559.382,1.70103,1976,3831692 +90,search,5943.72,1996.96,1882.24,1.0252,172.18,2.14472,8.04168,0.91545,0.108394,-1.0,-1.0,95.251,1.70121,1987,3831692 +91,insert,35.521,-1.0,-1.0,-1.0,-1.0,59.97,1.71117,1994,3864067 +92,search,6114.88,1991.36,1848.42,1.00131,168.444,2.16376,7.86994,0.91561,0.108416,-1.0,-1.0,32.193,1.71129,1995,3864067 +93,insert,207.32,-1.0,-1.0,-1.0,-1.0,240.315,1.81579,2031,4103827 +94,search,6318.73,2053.22,1972.8,1.0405,182.822,2.59716,7.62398,0.91619,0.10706,-1.0,-1.0,40.887,1.81598,2037,4103827 +95,insert,10.008,-1.0,-1.0,-1.0,-1.0,28.395,1.82099,2039,4119898 +96,search,6194.03,2056.82,2004.49,0.987145,190.395,2.19855,6.78772,0.91625,0.107031,-1.0,-1.0,32.787,1.82099,2039,4119898 +97,insert,12.872,-1.0,-1.0,-1.0,-1.0,43.782,1.82506,2042,4129367 +98,search,6156.44,2054.65,1905.04,1.02966,160.309,2.14016,7.64524,0.91639,0.107028,-1.0,-1.0,32.582,1.82506,2042,4129367 +99,insert,10.254,-1.0,-1.0,-1.0,-1.0,31.957,1.8286,2042,4134502 +100,search,6269.72,2056.94,2015.77,0.973243,186.092,2.17079,7.43277,0.91657,0.106954,-1.0,-1.0,33.931,1.8286,2042,4134502 +101,insert,39.982,-1.0,-1.0,-1.0,-1.0,88.753,1.8413,2052,4164482 +102,search,6278.86,2063.49,1981.99,1.01025,182.027,2.15471,8.20389,0.91695,0.106522,-1.0,-1.0,37.394,1.84144,2053,4164482 +103,insert,17.307,-1.0,-1.0,-1.0,-1.0,50.679,1.84672,2056,4178601 +104,search,6265.16,2069.78,1951.69,1.01526,175.319,2.12214,7.3176,0.91727,0.106544,-1.0,-1.0,30.23,1.84672,2056,4178601 +105,insert,6.898,-1.0,-1.0,-1.0,-1.0,33.662,1.85061,2057,4187774 +106,search,6270.63,2072.77,2024.95,1.01447,177.562,2.15703,7.34658,0.91731,0.106855,-1.0,-1.0,42.152,1.85067,2058,4187774 +107,insert,16.973,-1.0,-1.0,-1.0,-1.0,44.344,1.85633,2060,4200109 +108,search,6123.58,2073.2,1896.7,1.11276,161.792,2.36266,8.51211,0.91737,0.106748,-1.0,-1.0,28.976,1.85644,2061,4200109 +109,insert,462.813,-1.0,-1.0,-1.0,-1.0,527.145,2.02013,2162,4557867 +110,search,6530.72,2117.39,2104.74,1.0288,197.263,2.14885,7.97372,0.91913,0.10597,-1.0,-1.0,101.211,2.02044,2171,4557867 +111,insert,32.82,-1.0,-1.0,-1.0,-1.0,71.928,2.03336,2178,4587252 +112,search,6416,2116.87,1936.79,1.13626,157.652,2.16537,7.58852,0.91967,0.105697,-1.0,-1.0,37.223,2.03336,2178,4587252 +113,insert,13.012,-1.0,-1.0,-1.0,-1.0,55.982,2.03803,2181,4600056 +114,search,6595.97,2119.36,2073.68,1.07972,189.415,2.11546,7.84023,0.91981,0.105686,-1.0,-1.0,34.553,2.03803,2181,4600056 +115,insert,34.968,-1.0,-1.0,-1.0,-1.0,67.464,2.04805,2187,4627422 +116,search,6704.29,2122.18,2168.41,1.01926,198.618,2.16669,7.76799,0.92041,0.105174,-1.0,-1.0,53.981,2.04847,2189,4627422 +117,insert,13.718,-1.0,-1.0,-1.0,-1.0,53.845,2.05196,2192,4639292 +118,search,6655.19,2121.82,2143.04,1.04138,208.444,2.12295,8.16661,0.9204,0.105007,-1.0,-1.0,39.124,2.05196,2192,4639292 +119,insert,6.894,-1.0,-1.0,-1.0,-1.0,36.774,2.05428,2192,4643423 +120,search,6578.79,2123.09,2111.92,1.0413,187.001,2.17971,7.36136,0.92048,0.104978,-1.0,-1.0,29.103,2.05428,2192,4643423 +121,insert,14.292,-1.0,-1.0,-1.0,-1.0,33.36,2.05997,2192,4657252 +122,search,6777.28,2130.57,2160.99,1.00088,202.948,2.18996,7.60062,0.92059,0.104705,-1.0,-1.0,31.336,2.06013,2193,4657252 +123,insert,312.978,-1.0,-1.0,-1.0,-1.0,429.263,2.1878,2245,4938477 +124,search,6917.29,2176.81,2221.89,1.02048,193.65,2.18264,7.61526,0.92134,0.104699,-1.0,-1.0,215.757,2.18954,2271,4938477 +125,insert,60.021,-1.0,-1.0,-1.0,-1.0,64.625,2.20534,2276,4980492 +126,search,7003.38,2157.72,2226.41,1.01766,206.454,2.16458,9.03005,0.92229,0.10396,-1.0,-1.0,81.609,2.20543,2281,4980492 +127,insert,60.658,-1.0,-1.0,-1.0,-1.0,115.494,2.22701,2300,5030515 +128,search,7016.39,2157.83,2209.51,1.08318,192.982,2.14825,7.85647,0.92276,0.103968,-1.0,-1.0,61.278,2.22722,2304,5030515 +129,delete,18.123,-1.0,-1.0,-1.0,-1.0,118.256,2.22527,2271,5009391 +130,search,7059.17,2151.45,2226.24,1.01281,201.325,2.12181,7.84027,0.92145,0.104919,-1.0,-1.0,25.949,2.22527,2271,5009391 +131,delete,4.212,-1.0,-1.0,-1.0,-1.0,25.202,2.22527,2271,5004093 +132,search,7025.87,2147.32,2255.33,0.996996,211.578,2.15687,7.50579,0.9215,0.104974,-1.0,-1.0,37.379,2.22527,2271,5004093 +133,delete,13.204,-1.0,-1.0,-1.0,-1.0,48.646,2.22444,2270,4991787 +134,search,7126.17,2140.82,2234.04,0.993622,200.687,2.11948,7.83604,0.9213,0.105013,-1.0,-1.0,40.859,2.22444,2270,4991787 +135,delete,34.451,-1.0,-1.0,-1.0,-1.0,72.475,2.22232,2267,4974857 +136,search,7016.59,2137.29,2148.33,1.04045,182.993,2.48524,7.93794,0.92137,0.104906,-1.0,-1.0,39.455,2.22232,2267,4974857 +137,delete,6.985,-1.0,-1.0,-1.0,-1.0,37.198,2.22232,2267,4971386 +138,search,7178.93,2135.34,2272.16,0.972406,207.63,2.1853,7.65042,0.92132,0.104948,-1.0,-1.0,38.973,2.22232,2267,4971386 +139,delete,14.092,-1.0,-1.0,-1.0,-1.0,37.073,2.22232,2267,4963487 +140,search,7163.66,2127.32,2264.75,0.973391,217.876,2.15995,11.7841,0.92114,0.105014,-1.0,-1.0,39.069,2.22232,2267,4963487 +141,delete,33.109,-1.0,-1.0,-1.0,-1.0,127.42,2.21737,2260,4941830 +142,search,7153.29,2123.29,2269.76,0.990955,220.726,2.16448,7.85508,0.92104,0.104928,-1.0,-1.0,38.234,2.21737,2260,4941830 +143,delete,21.355,-1.0,-1.0,-1.0,-1.0,108.129,2.21238,2256,4925657 +144,search,7118.81,2120.05,2252.39,0.986844,203.928,2.13921,7.77774,0.9209,0.104891,-1.0,-1.0,45.829,2.2124,2257,4925657 +145,delete,2.928,-1.0,-1.0,-1.0,-1.0,42.57,2.2121,2256,4922686 +146,search,6994.83,2118.76,2141.67,1.01598,197.506,2.16487,8.69267,0.92049,0.105265,-1.0,-1.0,37.435,2.2121,2256,4922686 +147,delete,10.281,-1.0,-1.0,-1.0,-1.0,36.44,2.2121,2256,4913636 +148,search,6887.7,2114.21,2058.2,1.10688,179.451,2.10521,7.75119,0.92053,0.105255,-1.0,-1.0,37.512,2.2121,2256,4913636 +149,delete,231.572,-1.0,-1.0,-1.0,-1.0,1414.87,2.1339,2147,4717250 +150,search,6682.84,2127.62,2046.98,1.04571,179.183,2.16299,8.59915,0.91971,0.106282,-1.0,-1.0,94.043,2.13516,2157,4717250 +151,delete,154.17,-1.0,-1.0,-1.0,-1.0,1273.24,2.06518,2056,4560269 +152,search,6507.23,2141.61,2079.53,0.98514,187.497,2.15763,8.88862,0.91875,0.107108,-1.0,-1.0,98.007,2.06623,2064,4560269 +153,delete,27.732,-1.0,-1.0,-1.0,-1.0,162.456,2.05397,2049,4521936 +154,search,6481.54,2130.82,2062.48,1.01399,184.815,2.14428,8.77076,0.91769,0.108162,-1.0,-1.0,44.362,2.05414,2051,4521936 +155,delete,19.847,-1.0,-1.0,-1.0,-1.0,102.907,2.04922,2046,4502222 +156,search,6431.13,2122.3,2047.51,0.98511,177.177,2.15809,7.23408,0.91755,0.108183,-1.0,-1.0,41.493,2.04927,2047,4502222 +157,delete,47.736,-1.0,-1.0,-1.0,-1.0,223.623,2.03523,2034,4456039 +158,search,6398.59,2108.91,2015.22,0.967369,181.31,2.17657,10.4281,0.91747,0.108479,-1.0,-1.0,50.812,2.03559,2037,4456039 +159,delete,273.004,-1.0,-1.0,-1.0,-1.0,2146.55,1.88197,1860,4143922 +160,search,5934.24,2159.5,1892.37,0.954262,170.887,2.1742,7.68506,0.91598,0.109376,-1.0,-1.0,185.51,1.88401,1887,4143922 +161,delete,50.231,-1.0,-1.0,-1.0,-1.0,123.839,1.87609,1881,4101445 +162,search,5953.01,2094.72,1877.67,0.971614,163.18,2.15354,7.97109,0.91545,0.109842,-1.0,-1.0,31.324,1.87609,1881,4101445 +163,delete,26.606,-1.0,-1.0,-1.0,-1.0,51.825,1.87447,1881,4080175 +164,search,5968.11,2077.42,1897.05,0.984801,170.173,2.15132,8.53681,0.91514,0.110002,-1.0,-1.0,29.274,1.87447,1881,4080175 +165,delete,32.609,-1.0,-1.0,-1.0,-1.0,109.855,1.86814,1876,4047313 +166,search,5904.57,2064.97,1839.3,1.00151,175.15,2.17052,8.3916,0.91509,0.109921,-1.0,-1.0,38.739,1.86819,1877,4047313 +167,delete,8.409,-1.0,-1.0,-1.0,-1.0,28.518,1.86775,1877,4040738 +168,search,5921.41,2061.71,1853.65,0.949375,165.945,2.24502,8.01764,0.91515,0.109914,-1.0,-1.0,29.728,1.86775,1877,4040738 +169,delete,21.088,-1.0,-1.0,-1.0,-1.0,51.146,1.86396,1874,4022674 +170,search,5873.3,2053.55,1832.81,0.976545,158.731,2.21558,7.44432,0.91484,0.110027,-1.0,-1.0,29.682,1.86396,1874,4022674 +171,delete,8.506,-1.0,-1.0,-1.0,-1.0,27.945,1.86357,1874,4015835 +172,search,5908.97,2049.15,1842.03,0.953863,161.732,3.18897,8.14437,0.9149,0.110019,-1.0,-1.0,29.524,1.86357,1874,4015835 +173,delete,43.605,-1.0,-1.0,-1.0,-1.0,40.984,1.85913,1873,3986424 +174,search,5880.42,2025.2,1836.88,0.940957,167.474,2.16939,8.31011,0.91415,0.110696,-1.0,-1.0,29.299,1.85913,1873,3986424 +175,delete,225.743,-1.0,-1.0,-1.0,-1.0,1031.64,1.76817,1771,3804693 +176,search,5569.3,2051.01,1744.88,0.970769,156.247,2.224,7.31876,0.91173,0.11167,-1.0,-1.0,72.567,1.7692,1776,3804693 +177,delete,17.068,-1.0,-1.0,-1.0,-1.0,85.699,1.76466,1772,3786352 +178,search,5561.93,2035.3,1727.78,0.984876,154.89,3.3266,9.19215,0.91175,0.11161,-1.0,-1.0,57.385,1.76501,1775,3786352 +179,delete,252.59,-1.0,-1.0,-1.0,-1.0,1326.71,1.64131,1615,3556994 +180,search,4931.52,2089.57,1452.86,1.07085,122.521,2.13187,8.33731,0.90383,0.11623,-1.0,-1.0,107.742,1.643,1627,3556994 +181,delete,26.204,-1.0,-1.0,-1.0,-1.0,86.457,1.63575,1623,3526824 +182,search,5103.97,2054,1594.04,0.962717,148.169,2.15728,7.93063,0.90341,0.116359,-1.0,-1.0,35.645,1.63578,1624,3526824 +183,delete,182.966,-1.0,-1.0,-1.0,-1.0,1120.95,1.54483,1493,3350245 +184,search,4622.45,2108.4,1402.98,1.0638,116.276,2.13252,7.88048,0.88762,0.134568,-1.0,-1.0,130.119,1.54707,1510,3350245 +185,delete,9.149,-1.0,-1.0,-1.0,-1.0,30.349,1.54644,1507,3340234 +186,search,4770.21,2069.54,1497.15,0.955335,132.242,2.19481,7.62293,0.89421,0.125437,-1.0,-1.0,44.865,1.54651,1510,3340234 +187,delete,192.879,-1.0,-1.0,-1.0,-1.0,362.031,1.46166,1463,3150857 +188,search,4640.37,2067.69,1458.93,0.966898,137.3,2.13962,8.2307,0.8972,0.122971,-1.0,-1.0,36.936,1.46188,1464,3150857 +189,delete,15.668,-1.0,-1.0,-1.0,-1.0,21.192,1.46159,1464,3143609 +190,search,4633.4,2054.29,1439.81,0.978528,133.097,2.19772,8.95725,0.89682,0.123066,-1.0,-1.0,21.527,1.46159,1464,3143609 +191,delete,4.539,-1.0,-1.0,-1.0,-1.0,20.495,1.46088,1464,3141038 +192,search,4628.94,2054.43,1442.13,0.970659,133.955,2.13279,8.22841,0.89674,0.123214,-1.0,-1.0,22.386,1.46088,1464,3141038 +193,delete,74.954,-1.0,-1.0,-1.0,-1.0,207.219,1.44091,1442,3081734 +194,search,4564.38,2041.03,1416.38,1.0056,131.553,2.74671,7.90809,0.8955,0.124512,-1.0,-1.0,56.637,1.44183,1445,3081734 +195,delete,47.809,-1.0,-1.0,-1.0,-1.0,193.395,1.42518,1429,3043966 +196,search,4508.67,2024.91,1400.48,0.999048,127.427,2.33406,7.86758,0.89574,0.123754,-1.0,-1.0,21.778,1.42518,1429,3043966 +197,delete,48.721,-1.0,-1.0,-1.0,-1.0,87.816,1.41246,1423,3008145 +198,search,4515.16,2012.62,1409.46,0.949411,136.273,2.15606,9.6558,0.89516,0.124258,-1.0,-1.0,38.051,1.41306,1425,3008145 +199,delete,11.635,-1.0,-1.0,-1.0,-1.0,52.326,1.41003,1422,2999384 +200,search,4486.39,2009.34,1385.96,0.969456,123.277,2.22538,8.28009,0.89493,0.124194,-1.0,-1.0,21.529,1.41003,1422,2999384 +201,delete,8.326,-1.0,-1.0,-1.0,-1.0,41.483,1.4074,1420,2993528 +202,search,4503.14,2007.69,1391.24,0.940792,132.516,2.18084,8.14495,0.89498,0.12422,-1.0,-1.0,21.711,1.4074,1420,2993528 +203,delete,18.546,-1.0,-1.0,-1.0,-1.0,19.466,1.40593,1420,2980973 +204,search,4493.94,1997.01,1399.74,0.928013,133.005,2.1573,9.09979,0.89481,0.1244,-1.0,-1.0,20.802,1.40593,1420,2980973 +205,delete,28.471,-1.0,-1.0,-1.0,-1.0,62.089,1.39933,1412,2960291 +206,search,4422.33,1985.22,1359.91,1.0322,122.608,2.161,10.1193,0.89405,0.124657,-1.0,-1.0,20.84,1.39933,1412,2960291 +207,delete,58.516,-1.0,-1.0,-1.0,-1.0,232.447,1.37681,1364,2920620 +208,search,4298.56,1997.71,1318.1,0.992786,126.293,2.14847,8.48783,0.89181,0.126233,-1.0,-1.0,19.459,1.37681,1364,2920620 +209,delete,26.851,-1.0,-1.0,-1.0,-1.0,59.408,1.36984,1358,2900501 +210,search,4266.91,1988.74,1310.61,0.980013,123.918,2.18821,9.42572,0.8908,0.126605,-1.0,-1.0,19.249,1.36984,1358,2900501 +211,delete,12.297,-1.0,-1.0,-1.0,-1.0,46.016,1.36655,1356,2891660 +212,search,4287.36,1984.83,1312.15,0.991281,129.458,2.19289,9.71508,0.89076,0.126722,-1.0,-1.0,19.458,1.36655,1356,2891660 +213,delete,18.484,-1.0,-1.0,-1.0,-1.0,48.465,1.36232,1352,2873257 +214,search,4187.95,1975.82,1254.34,1.09736,121.69,2.12177,8.11964,0.88994,0.127102,-1.0,-1.0,19.261,1.36232,1352,2873257 +215,delete,425.94,-1.0,-1.0,-1.0,-1.0,2081,1.16227,1116,2537571 +216,search,3632.37,2149.29,1168.9,0.930995,110.138,2.19071,8.85912,0.88504,0.131064,-1.0,-1.0,303.415,1.16768,1152,2537571 +217,delete,209.764,-1.0,-1.0,-1.0,-1.0,1200.97,1.05072,997,2308194 +218,search,3193.75,2170.3,1000.82,1.02597,90.5887,2.15247,8.00017,0.87882,0.135604,-1.0,-1.0,211.743,1.05422,1024,2308194 +219,delete,16.151,-1.0,-1.0,-1.0,-1.0,73.645,1.04924,1016,2285820 +220,search,3261.02,2066.39,1034.91,0.964033,95.5327,2.3101,9.31096,0.8771,0.136907,-1.0,-1.0,121.105,1.04944,1028,2285820 +221,delete,196.869,-1.0,-1.0,-1.0,-1.0,974.677,0.938243,871,2082858 +222,search,2838.43,2113.58,908.789,1.07869,81.9203,2.17687,8.54087,0.86842,0.144227,-1.0,-1.0,98.32,0.939912,881,2082858 +223,delete,10.054,-1.0,-1.0,-1.0,-1.0,54.539,0.936074,874,2071207 +224,search,2852.24,2090.14,915.73,0.889097,90.0483,2.17906,10.7037,0.86821,0.144636,-1.0,-1.0,40.417,0.936443,877,2071207 +225,delete,5.085,-1.0,-1.0,-1.0,-1.0,25.579,0.935208,876,2065400 +226,search,2800.11,2078.36,878.004,0.958665,85.8559,2.18927,9.56018,0.8677,0.144864,-1.0,-1.0,22.012,0.935313,877,2065400 +227,delete,2.74,-1.0,-1.0,-1.0,-1.0,14.52,0.935313,877,2062105 +228,search,2857.07,2073.13,900.389,0.949921,89.4051,2.24548,8.614,0.86768,0.144776,-1.0,-1.0,15.194,0.935313,877,2062105 +229,delete,19.817,-1.0,-1.0,-1.0,-1.0,52.217,0.929263,872,2039610 +230,search,2704.03,2058.16,889.762,0.989741,87.6486,2.33468,9.87168,0.86616,0.146004,-1.0,-1.0,15.604,0.929263,872,2039610 +231,delete,16.802,-1.0,-1.0,-1.0,-1.0,41.106,0.924668,868,2027795 +232,search,2803.12,2050.12,888.815,0.900543,85.3496,2.17947,8.23698,0.866,0.146053,-1.0,-1.0,15.246,0.924668,868,2027795 +233,delete,6.296,-1.0,-1.0,-1.0,-1.0,29.128,0.922931,867,2022859 +234,search,2820.48,2047.07,882.73,0.955081,87.9743,2.18152,9.20642,0.86556,0.146196,-1.0,-1.0,16.189,0.922931,867,2022859 +235,delete,11.459,-1.0,-1.0,-1.0,-1.0,32.384,0.921845,862,2016264 +236,search,2649.05,2046.05,906.29,0.950818,92.312,2.46224,9.31313,0.86441,0.147034,-1.0,-1.0,13.106,0.921845,862,2016264 +237,delete,206.463,-1.0,-1.0,-1.0,-1.0,952.584,0.803277,720,1782866 +238,search,2303.15,2188.9,799.436,0.912137,79.2275,2.24456,9.32694,0.85768,0.152504,-1.0,-1.0,150.006,0.806017,745,1782866 +239,delete,15.544,-1.0,-1.0,-1.0,-1.0,80.23,0.795133,733,1758931 +240,search,2357.68,2092.74,736.688,1.0052,73,2.17367,10.7908,0.85475,0.153855,-1.0,-1.0,57.098,0.795228,739,1758931 +241,delete,6.645,-1.0,-1.0,-1.0,-1.0,32.377,0.792553,737,1751275 +242,search,2372.94,2070.54,738.712,0.946342,67.7867,2.20752,10.1037,0.85456,0.153796,-1.0,-1.0,28.12,0.792625,739,1751275 +243,delete,16.854,-1.0,-1.0,-1.0,-1.0,51.402,0.788358,733,1733264 +244,search,2336.72,2057.52,749,0.918927,77.4291,2.18817,10.415,0.85214,0.154732,-1.0,-1.0,8.166,0.788358,733,1733264 +245,delete,7.971,-1.0,-1.0,-1.0,-1.0,16.767,0.786174,731,1722658 +246,search,2294.25,2048.83,721.519,0.965207,77.6755,2.17557,9.44945,0.85186,0.154642,-1.0,-1.0,11.927,0.786174,731,1722658 +247,delete,2.895,-1.0,-1.0,-1.0,-1.0,11.288,0.786174,731,1719601 +248,search,2268.19,2042.91,742.582,0.953413,75.8065,2.37083,9.011,0.85158,0.154755,-1.0,-1.0,11.936,0.786174,731,1719601 +249,delete,7.627,-1.0,-1.0,-1.0,-1.0,23.787,0.784841,729,1711648 +250,search,2398.95,2039.7,755.521,0.997928,78.4027,2.272,9.81759,0.85188,0.154591,-1.0,-1.0,12.187,0.784841,729,1711648 +251,delete,324.911,-1.0,-1.0,-1.0,-1.0,513.312,0.665284,615,1470624 +252,search,1995.59,2124.79,645.677,0.986468,68.7814,2.15757,9.51391,0.84743,0.157568,-1.0,-1.0,111.356,0.666953,629,1470624 +253,delete,24.469,-1.0,-1.0,-1.0,-1.0,58.503,0.659941,622,1442070 +254,search,1909.58,2042.75,616.459,0.978334,63.1977,2.14825,10.1884,0.84572,0.157951,-1.0,-1.0,7.92,0.659941,622,1442070 +255,delete,28.726,-1.0,-1.0,-1.0,-1.0,123.747,0.642208,596,1405549 +256,search,1945.83,2087.77,642.816,0.864495,72.0763,2.25833,9.64688,0.84176,0.15953,-1.0,-1.0,28.827,0.642544,599,1405549 +257,insert,12.079,-1.0,-1.0,-1.0,-1.0,8.657,0.645112,599,1416288 +258,search,1873.57,2082.04,637.869,0.927374,69.6129,2.24719,8.54538,0.84092,0.160758,-1.0,-1.0,7.779,0.645112,599,1416288 +259,insert,17.756,-1.0,-1.0,-1.0,-1.0,33.741,0.653597,603,1443010 +260,search,2030.03,2103.71,654.855,0.883785,71.522,2.28189,10.1871,0.84202,0.160199,-1.0,-1.0,10.027,0.653597,603,1443010 +261,insert,7.297,-1.0,-1.0,-1.0,-1.0,13.13,0.654982,604,1447529 +262,search,1855.29,2110.56,652.508,0.926417,74.9984,2.27443,8.97647,0.84228,0.160261,-1.0,-1.0,7.726,0.654982,604,1447529 +263,insert,152.013,-1.0,-1.0,-1.0,-1.0,151.533,0.702673,621,1569110 +264,search,2125.9,2243.58,713.107,0.943403,72.7195,2.18675,9.65041,0.84786,0.157097,-1.0,-1.0,60.793,0.703007,627,1569110 +265,insert,101.08,-1.0,-1.0,-1.0,-1.0,110.454,0.731704,643,1636119 +266,search,2205.12,2271.59,742.354,0.953802,76.8132,2.17927,8.50914,0.85161,0.155064,-1.0,-1.0,19.409,0.731706,644,1636119 +267,insert,34.725,-1.0,-1.0,-1.0,-1.0,58.695,0.744301,649,1665152 +268,search,2107.12,2293.97,754.12,0.96788,75.2651,2.15495,7.99682,0.85396,0.154407,-1.0,-1.0,23.736,0.744493,652,1665152 +269,insert,292.073,-1.0,-1.0,-1.0,-1.0,354.876,0.858188,697,1916952 +270,search,2403.92,2450.62,843.46,0.9216,84.6377,2.2077,9.56226,0.85634,0.152773,-1.0,-1.0,99.401,0.858901,713,1916952 +271,insert,2.211,-1.0,-1.0,-1.0,-1.0,10.803,0.859586,714,1920898 +272,search,2366.48,2393.48,808.799,0.96935,81.2228,2.15136,9.64716,0.85776,0.151785,-1.0,-1.0,71.869,0.859808,721,1920898 +273,insert,29.152,-1.0,-1.0,-1.0,-1.0,38.231,0.868712,726,1942757 +274,search,2479.86,2383.15,855.896,0.897697,89.3587,2.18574,7.8848,0.85876,0.150685,-1.0,-1.0,19.093,0.868758,727,1942757 +275,insert,475.216,-1.0,-1.0,-1.0,-1.0,582.341,1.04466,806,2328372 +276,search,2789.94,2562.85,1000.28,0.98127,94.2893,2.21137,10.6726,0.8655,0.146576,-1.0,-1.0,212.003,1.04621,835,2328372 +277,insert,43.11,-1.0,-1.0,-1.0,-1.0,105.886,1.06101,851,2363257 +278,search,2914.93,2454.64,1020.3,0.948617,101.755,2.1765,8.89593,0.86712,0.145417,-1.0,-1.0,112.912,1.06171,864,2363257 +279,insert,25.453,-1.0,-1.0,-1.0,-1.0,33.486,1.07092,871,2388933 +280,search,2731.22,2409.69,990.521,0.989683,92.9254,2.23177,9.1395,0.86831,0.144322,-1.0,-1.0,49.628,1.07093,875,2388933 +281,insert,379.127,-1.0,-1.0,-1.0,-1.0,276.977,1.2032,912,2684315 +282,search,2962.51,2516.8,1089.8,0.934864,106.633,2.22244,9.92197,0.8701,0.143432,-1.0,-1.0,154.927,1.20494,935,2684315 +283,insert,520.312,-1.0,-1.0,-1.0,-1.0,588.397,1.39768,1048,3109157 +284,search,3447.77,2590.69,1242.75,1.03843,114.945,2.14368,9.30139,0.88099,0.136004,-1.0,-1.0,267.02,1.39937,1088,3109157 +285,insert,13.074,-1.0,-1.0,-1.0,-1.0,40.383,1.40378,1093,3122751 +286,search,3621.89,2468.6,1247.5,1.02695,118.953,2.16076,9.10236,0.87985,0.136283,-1.0,-1.0,63.235,1.40379,1097,3122751 +287,insert,39.683,-1.0,-1.0,-1.0,-1.0,98.135,1.421,1109,3163679 +288,search,3673.23,2469.29,1256.61,1.05682,116.367,2.16274,8.76944,0.88105,0.135707,-1.0,-1.0,63.901,1.42123,1115,3163679 +289,insert,239.292,-1.0,-1.0,-1.0,-1.0,500.864,1.55676,1195,3472031 +290,search,3911.94,2537.39,1429.12,1.03242,135.382,2.17219,8.59996,0.88433,0.134192,-1.0,-1.0,207.437,1.55805,1222,3472031 +291,insert,26.277,-1.0,-1.0,-1.0,-1.0,71.039,1.56751,1236,3495577 +292,search,4012.75,2455.44,1429.12,0.966958,137.306,2.22183,9.4312,0.88595,0.133315,-1.0,-1.0,55.654,1.56756,1241,3495577 +293,insert,19.399,-1.0,-1.0,-1.0,-1.0,49.213,1.57642,1245,3515193 +294,search,4120.38,2444.8,1430.84,0.959771,136.595,2.16935,8.55833,0.88521,0.134129,-1.0,-1.0,32.527,1.57651,1249,3515193 +295,insert,237.126,-1.0,-1.0,-1.0,-1.0,396.885,1.66868,1310,3723063 +296,search,4373.24,2472.56,1514.84,0.987664,144.642,2.17865,9.83279,0.88971,0.131417,-1.0,-1.0,82.358,1.67027,1326,3723063 +297,insert,2.159,-1.0,-1.0,-1.0,-1.0,17.653,1.67175,1328,3727399 +298,search,4207.68,2448.94,1506.92,1.04082,145.439,2.17033,9.43862,0.8901,0.131163,-1.0,-1.0,39.571,1.67188,1335,3727399 +299,insert,60.11,-1.0,-1.0,-1.0,-1.0,84.189,1.69521,1355,3788002 +300,search,4403.55,2431.71,1553.98,0.982235,140.182,2.14747,9.88311,0.89229,0.128737,-1.0,-1.0,24.059,1.69532,1356,3788002 +301,insert,713.477,-1.0,-1.0,-1.0,-1.0,926.74,1.96339,1533,4370866 +302,search,5001.1,2593.69,1854.04,1.00162,177.268,2.16422,8.66389,0.91377,0.111945,-1.0,-1.0,221.328,1.96421,1571,4370866 +303,insert,58.299,-1.0,-1.0,-1.0,-1.0,112.538,1.98491,1584,4420306 +304,search,5115,2492.53,1828.48,0.979073,169.97,2.16098,9.39638,0.91312,0.112209,-1.0,-1.0,26.008,1.98491,1588,4420306 +305,insert,375.359,-1.0,-1.0,-1.0,-1.0,406.005,2.14825,1643,4789669 +306,search,5393.06,2574.91,1963.59,0.978666,179.52,2.19105,9.05689,0.91537,0.110231,-1.0,-1.0,161.34,2.15124,1663,4789669 +307,insert,21.098,-1.0,-1.0,-1.0,-1.0,52.671,2.1595,1672,4815550 +308,search,5384.23,2548.92,1980.72,0.973978,177.382,2.35076,8.74566,0.91609,0.109934,-1.0,-1.0,88.37,2.15959,1679,4815550 +309,insert,9.301,-1.0,-1.0,-1.0,-1.0,26.564,2.16191,1680,4823345 +310,search,5437.95,2538.42,1944.48,0.993976,181.333,2.18209,8.58538,0.91667,0.10956,-1.0,-1.0,43.38,2.16204,1683,4823345 +311,insert,11.631,-1.0,-1.0,-1.0,-1.0,23.945,2.1691,1684,4843493 +312,search,5549.7,2537.3,1948.75,0.983819,178.036,2.17185,8.65011,0.91617,0.110111,-1.0,-1.0,42.565,2.1691,1686,4843493 +313,insert,45.283,-1.0,-1.0,-1.0,-1.0,87.394,2.18684,1695,4885489 +314,search,5676.11,2544.87,2001.72,0.982835,183.23,2.1504,9.33695,0.9166,0.10999,-1.0,-1.0,73.874,2.18762,1704,4885489 +315,insert,7.742,-1.0,-1.0,-1.0,-1.0,17.893,2.19013,1704,4892335 +316,search,5684.22,2530.61,1996.88,1.00806,179.847,2.55152,8.69637,0.91661,0.110042,-1.0,-1.0,18.608,2.19013,1704,4892335 +317,insert,47.828,-1.0,-1.0,-1.0,-1.0,124.097,2.20582,1723,4932996 +318,search,5729.86,2521.74,2012.68,0.976576,182.355,2.20883,9.53416,0.91696,0.10981,-1.0,-1.0,22.649,2.20586,1724,4932996 +319,insert,660.978,-1.0,-1.0,-1.0,-1.0,807.641,2.42161,1850,5430684 +320,search,6215.97,2610.52,2205.29,1.01328,204.823,3.05321,8.26986,0.92124,0.106488,-1.0,-1.0,316.36,2.42604,1894,5430684 +321,insert,48.375,-1.0,-1.0,-1.0,-1.0,84.359,2.4412,1908,5471239 +322,search,6356.85,2533.55,2216.97,0.981514,207.425,2.16445,8.94242,0.92178,0.105881,-1.0,-1.0,157.595,2.44171,1917,5471239 +323,insert,123.621,-1.0,-1.0,-1.0,-1.0,202.677,2.4869,1950,5575560 +324,search,6381.44,2538.16,2274.74,0.970521,210.186,2.20896,8.85358,0.92273,0.105176,-1.0,-1.0,87.415,2.48719,1957,5575560 +325,insert,1158.77,-1.0,-1.0,-1.0,-1.0,469.445,2.71259,2032,6069499 +326,search,6671.37,2648.99,2422.04,0.969521,224.903,2.21724,8.71466,0.92545,0.103769,-1.0,-1.0,359.373,2.71346,2073,6069499 +327,insert,83.639,-1.0,-1.0,-1.0,-1.0,122.27,2.74247,2088,6139647 +328,search,6937.71,2616.29,2419.48,1.04306,221.558,2.42129,8.87681,0.92705,0.102485,-1.0,-1.0,121.022,2.74312,2100,6139647 +329,insert,10.923,-1.0,-1.0,-1.0,-1.0,32.791,2.74599,2102,6146884 +330,search,6987.47,2600.17,2445.36,1.01712,224.553,2.14537,8.4269,0.92733,0.102219,-1.0,-1.0,61.678,2.74616,2107,6146884 +331,insert,52.074,-1.0,-1.0,-1.0,-1.0,102.377,2.76355,2118,6188816 +332,search,7129.04,2602.18,2532.81,1.00669,243.526,2.14219,10.5012,0.92718,0.102344,-1.0,-1.0,59.506,2.76418,2122,6188816 +333,insert,3.359,-1.0,-1.0,-1.0,-1.0,31.732,2.76488,2123,6190810 +334,search,6979.27,2597.04,2402.16,1.09996,218.067,2.14546,8.71633,0.92742,0.102121,-1.0,-1.0,27.594,2.76488,2123,6190810 +335,insert,54.318,-1.0,-1.0,-1.0,-1.0,109.591,2.78083,2138,6230108 +336,search,7067.52,2600.33,2442.97,1.0803,221.304,2.2665,8.55772,0.92792,0.101968,-1.0,-1.0,34.8,2.7809,2139,6230108 +337,insert,26.463,-1.0,-1.0,-1.0,-1.0,68.166,2.78952,2144,6249699 +338,search,7073.12,2600.46,2441.2,1.07326,220.987,2.27178,8.28821,0.92823,0.101658,-1.0,-1.0,53.837,2.78962,2147,6249699 +339,insert,60.023,-1.0,-1.0,-1.0,-1.0,95.187,2.80547,2158,6290226 +340,search,7177.19,2603.6,2551.95,1.01223,236.846,2.173,8.5004,0.92869,0.101291,-1.0,-1.0,21.56,2.8055,2159,6290226 +341,insert,6.406,-1.0,-1.0,-1.0,-1.0,31.688,2.80948,2162,6297556 +342,search,6907.76,2600.42,2574.54,1.00255,245.02,2.18875,8.79646,0.92884,0.10121,-1.0,-1.0,38.618,2.80966,2164,6297556 +343,insert,39.77,-1.0,-1.0,-1.0,-1.0,79.514,2.82218,2172,6330843 +344,search,7109.79,2605.5,2543.23,1.00628,235.988,2.17564,8.70314,0.92874,0.101378,-1.0,-1.0,28.145,2.82218,2172,6330843 +345,insert,42.41,-1.0,-1.0,-1.0,-1.0,116.297,2.83604,2185,6370265 +346,search,7029.2,2606.69,2497.91,1.03457,226.283,2.14911,9.55573,0.9292,0.100751,-1.0,-1.0,39.154,2.83613,2187,6370265 +347,insert,475.165,-1.0,-1.0,-1.0,-1.0,945.562,3.04153,2327,6831086 +348,search,7401.28,2635.98,2660.64,1.06401,237.876,2.15236,8.61135,0.93239,0.0977587,-1.0,-1.0,241.734,3.04451,2358,6831086 +349,insert,58.136,-1.0,-1.0,-1.0,-1.0,100.766,3.06354,2368,6876154 +350,search,7815.18,2607.69,2806.16,0.988177,269.87,2.26015,8.63697,0.93287,0.097447,-1.0,-1.0,39.484,3.06377,2371,6876154 +351,insert,477.089,-1.0,-1.0,-1.0,-1.0,600.351,3.25061,2464,7288266 +352,search,8069.88,2634.61,2959.84,1.02027,283.021,2.1893,8.72282,0.93268,0.0979329,-1.0,-1.0,270.608,3.25238,2497,7288266 +353,insert,57.893,-1.0,-1.0,-1.0,-1.0,111.694,3.269,2512,7333132 +354,search,8174.84,2595.08,2964.02,0.994647,283.798,2.20741,8.63969,0.93295,0.0980115,-1.0,-1.0,70.802,3.26938,2518,7333132 +355,insert,378.692,-1.0,-1.0,-1.0,-1.0,586.842,3.42856,2613,7696838 +356,search,8500.45,2612.74,3054.05,0.990874,284.058,2.16182,8.14795,0.93432,0.0969263,-1.0,-1.0,194.683,3.43041,2639,7696838 +357,insert,26.595,-1.0,-1.0,-1.0,-1.0,49.409,3.43801,2643,7714498 +358,search,8338.06,2588.51,3062.99,1.02805,286.848,3.06089,8.63461,0.93487,0.0964041,-1.0,-1.0,57.509,3.43909,2652,7714498 +359,insert,9.184,-1.0,-1.0,-1.0,-1.0,45.021,3.4437,2659,7725755 +360,search,8552.94,2574.99,2878.64,1.1364,255.397,2.11897,9.15015,0.93477,0.096524,-1.0,-1.0,23.259,3.4437,2659,7725755 +361,insert,69.418,-1.0,-1.0,-1.0,-1.0,153.88,3.46783,2680,7789312 +362,search,8780.53,2575.79,3013.85,1.08375,271.612,2.16545,8.72537,0.93532,0.0957465,-1.0,-1.0,45.868,3.46827,2684,7789312 +363,insert,20.402,-1.0,-1.0,-1.0,-1.0,66.017,3.47275,2690,7803163 +364,search,8948.44,2569.08,3151.59,0.993175,291.7,2.18887,8.04895,0.93532,0.0955269,-1.0,-1.0,38.818,3.47309,2692,7803163 +365,insert,74.551,-1.0,-1.0,-1.0,-1.0,154.836,3.50086,2712,7863722 +366,search,9002.33,2569.38,3156.95,0.986484,302.752,2.12492,8.48667,0.93589,0.0948893,-1.0,-1.0,52.414,3.50103,2716,7863722 +367,insert,35.451,-1.0,-1.0,-1.0,-1.0,81.214,3.51314,2725,7895271 +368,search,9008.04,2567.83,3159.37,1.00794,288.498,2.14809,8.7062,0.93632,0.0944056,-1.0,-1.0,38.045,3.51315,2726,7895271 +369,insert,75.758,-1.0,-1.0,-1.0,-1.0,167.676,3.53963,2744,7961194 +370,search,9109.27,2575.97,3198.64,0.989174,301.449,2.14891,8.42396,0.93689,0.0935448,-1.0,-1.0,56.663,3.54004,2748,7961194 +371,insert,21.047,-1.0,-1.0,-1.0,-1.0,53.03,3.54531,2753,7970239 +372,search,8858.01,2569.74,2983.72,1.11587,262.503,3.06589,9.74729,0.93689,0.0935876,-1.0,-1.0,26.27,3.54531,2753,7970239 +373,insert,64.57,-1.0,-1.0,-1.0,-1.0,111.439,3.56003,2767,8010868 +374,search,8845.37,2569.67,2951.44,1.17965,249.93,2.09482,8.64276,0.93733,0.0930754,-1.0,-1.0,52.081,3.56034,2771,8010868 +375,insert,47.428,-1.0,-1.0,-1.0,-1.0,91.325,3.5726,2780,8040698 +376,search,9264.21,2566.9,3259.99,0.955315,300.855,2.16988,8.03108,0.93749,0.0930683,-1.0,-1.0,38.349,3.57273,2782,8040698 +377,insert,83.887,-1.0,-1.0,-1.0,-1.0,147.989,3.60164,2799,8104748 +378,search,9276.28,2567.38,3267.91,0.989809,305.691,2.14347,8.95744,0.93767,0.093103,-1.0,-1.0,45.697,3.60222,2802,8104748 +379,insert,6.652,-1.0,-1.0,-1.0,-1.0,24.532,3.60406,2802,8109755 +380,search,9320.73,2567.57,3279.58,0.992877,309.666,2.1128,9.56269,0.9378,0.092961,-1.0,-1.0,26.007,3.60406,2802,8109755 +381,insert,28.244,-1.0,-1.0,-1.0,-1.0,53.948,3.61153,2806,8130382 +382,search,9321.49,2569.57,3295.35,0.997692,313.372,2.60243,8.50475,0.93777,0.0931968,-1.0,-1.0,26.715,3.61153,2806,8130382 +383,insert,36.162,-1.0,-1.0,-1.0,-1.0,58.761,3.61985,2812,8153290 +384,search,9351.69,2570.37,3290.9,0.999845,304.177,2.24646,9.12021,0.9378,0.0930147,-1.0,-1.0,33.062,3.62003,2813,8153290 +385,delete,17.044,-1.0,-1.0,-1.0,-1.0,24.838,3.62003,2813,8138873 +386,search,9280.72,2567.14,3260.59,1.00195,302.043,2.28337,8.53623,0.93782,0.0929674,-1.0,-1.0,26.074,3.62003,2813,8138873 +387,delete,29.031,-1.0,-1.0,-1.0,-1.0,171.671,3.61261,2806,8115069 +388,search,9250.72,2566.41,3241.74,1.0072,292.457,2.15696,8.15193,0.93782,0.0930642,-1.0,-1.0,29.716,3.61261,2806,8115069 +389,delete,38.327,-1.0,-1.0,-1.0,-1.0,101.916,3.60976,2802,8101157 +390,search,9014.09,2560.24,3196.74,1.05458,298.127,2.16276,9.64112,0.93769,0.0932498,-1.0,-1.0,31.95,3.60999,2803,8101157 +391,delete,98.742,-1.0,-1.0,-1.0,-1.0,615.187,3.57881,2761,8014644 +392,search,9046.23,2571.82,3235.27,0.983206,302.974,2.14192,8.59784,0.93721,0.0932295,-1.0,-1.0,55.76,3.5793,2769,8014644 +393,delete,25.372,-1.0,-1.0,-1.0,-1.0,127.845,3.5726,2762,7978358 +394,search,9112.17,2555.61,3220.81,0.976934,307.595,2.14949,8.92736,0.93707,0.0934202,-1.0,-1.0,35.58,3.57281,2763,7978358 +395,delete,27.655,-1.0,-1.0,-1.0,-1.0,243.742,3.561,2752,7957094 +396,search,9100.29,2562.01,3204.3,0.970482,298.581,2.15679,9.22986,0.93654,0.0937023,-1.0,-1.0,49.903,3.56123,2754,7957094 +397,delete,153.416,-1.0,-1.0,-1.0,-1.0,844.04,3.50485,2715,7823916 +398,search,9008.13,2548.7,3161.74,0.977078,300.77,2.12993,8.71578,0.93631,0.0939026,-1.0,-1.0,110.907,3.50628,2724,7823916 +399,delete,5.444,-1.0,-1.0,-1.0,-1.0,27.28,3.50628,2724,7818430 +400,search,8933.78,2538.89,3148.3,1.01734,289.462,2.19981,9.1492,0.93625,0.0938803,-1.0,-1.0,51.834,3.50628,2726,7818430 +401,delete,17.718,-1.0,-1.0,-1.0,-1.0,43.526,3.50327,2724,7800702 +402,search,9006.37,2531.82,3146.75,1.0035,298.344,2.15859,8.56794,0.93569,0.0943286,-1.0,-1.0,38.289,3.50327,2725,7800702 +403,delete,341.149,-1.0,-1.0,-1.0,-1.0,2298.81,3.37369,2585,7517858 +404,search,8587,2563.7,3032.03,0.971629,285.496,2.15594,8.09293,0.93377,0.0959031,-1.0,-1.0,238.545,3.37793,2609,7517858 +405,delete,65.752,-1.0,-1.0,-1.0,-1.0,389.114,3.35939,2591,7451637 +406,search,8561.56,2536.65,2982.33,1.02979,273.922,2.18047,8.20061,0.93431,0.0952936,-1.0,-1.0,90.167,3.35969,2596,7451637 +407,delete,122.594,-1.0,-1.0,-1.0,-1.0,896.061,3.31242,2551,7360417 +408,search,8424.88,2542.2,2948.05,1.00764,272.193,2.15031,9.03043,0.93355,0.0960791,-1.0,-1.0,120.762,3.31401,2560,7360417 +409,delete,212.598,-1.0,-1.0,-1.0,-1.0,795.214,3.21909,2514,7131620 +410,search,8347.68,2524.17,2903.44,1.01361,283.209,2.19018,8.20904,0.93344,0.0963595,-1.0,-1.0,102.488,3.21973,2522,7131620 +411,delete,316.518,-1.0,-1.0,-1.0,-1.0,2189.21,3.09961,2380,6867617 +412,search,7944.2,2566.87,2803.17,0.967143,265.968,2.1911,8.90059,0.93331,0.0968004,-1.0,-1.0,252.826,3.10392,2411,6867617 +413,delete,16.007,-1.0,-1.0,-1.0,-1.0,71.108,3.10054,2408,6850098 +414,search,8007.49,2527.95,2793.75,0.973046,270.014,2.199,8.77855,0.93341,0.0966498,-1.0,-1.0,47.306,3.10094,2411,6850098 +415,delete,79.961,-1.0,-1.0,-1.0,-1.0,583.211,3.06758,2380,6782921 +416,search,7722.42,2528.21,2609.19,1.09466,229.022,2.16589,8.48857,0.93258,0.0972934,-1.0,-1.0,74.863,3.06832,2385,6782921 +417,delete,257.493,-1.0,-1.0,-1.0,-1.0,1367.9,2.9818,2308,6562039 +418,search,7575.24,2520.93,2594.34,1.01693,236.284,2.17532,9.08246,0.93165,0.0974473,-1.0,-1.0,185.919,2.98385,2324,6562039 +419,delete,23.194,-1.0,-1.0,-1.0,-1.0,79.132,2.98077,2321,6536285 +420,search,7514.26,2496.75,2520.31,1.09692,222.087,2.15139,8.70293,0.93201,0.0975575,-1.0,-1.0,74.801,2.98103,2324,6536285 +421,delete,21.747,-1.0,-1.0,-1.0,-1.0,170.006,2.97095,2315,6510820 +422,search,7560.43,2496.86,2564.31,1.06069,228.482,2.40558,8.86209,0.93237,0.097444,-1.0,-1.0,59.103,2.97132,2318,6510820 +423,delete,199.762,-1.0,-1.0,-1.0,-1.0,966.048,2.89478,2244,6334168 +424,search,7437.38,2502.4,2581.44,0.997804,238.606,2.16067,8.68092,0.93072,0.098534,-1.0,-1.0,136.314,2.89702,2256,6334168 +425,delete,18.531,-1.0,-1.0,-1.0,-1.0,82.728,2.89302,2254,6316443 +426,search,7439.3,2486.21,2567.43,0.987791,235.375,2.1363,9.07575,0.93095,0.0987958,-1.0,-1.0,63.558,2.89348,2257,6316443 +427,delete,63.391,-1.0,-1.0,-1.0,-1.0,68.862,2.88782,2255,6266345 +428,search,7413.69,2457.22,2541.21,0.972752,234.706,2.25231,8.92271,0.93078,0.0988302,-1.0,-1.0,36.837,2.88782,2255,6266345 +429,delete,578.757,-1.0,-1.0,-1.0,-1.0,3588.03,2.66338,1952,5883847 +430,search,6513.21,2726.33,2282.27,1.08727,200.831,2.11755,8.84706,0.92185,0.105488,-1.0,-1.0,524.061,2.6728,2029,5883847 +431,delete,77.079,-1.0,-1.0,-1.0,-1.0,388.435,2.63652,1999,5801380 +432,search,6727.47,2577.12,2365,0.995691,224.351,2.18348,9.10548,0.92033,0.107782,-1.0,-1.0,130.962,2.63714,2013,5801380 +433,delete,231.884,-1.0,-1.0,-1.0,-1.0,1439.74,2.54605,1915,5607567 +434,search,6483.88,2603.78,2296.89,0.994144,221.83,2.19264,8.68144,0.91755,0.109332,-1.0,-1.0,178.394,2.54799,1934,5607567 +435,delete,103.735,-1.0,-1.0,-1.0,-1.0,462.758,2.51488,1897,5512176 +436,search,6370.96,2581.6,2251.76,0.968345,206.561,2.16874,10.7218,0.91782,0.109203,-1.0,-1.0,95.859,2.51534,1904,5512176 +437,delete,12.697,-1.0,-1.0,-1.0,-1.0,57.613,2.51167,1901,5501141 +438,search,6396.77,2570.68,2244.42,1.00901,215.235,2.1586,8.89915,0.91777,0.109205,-1.0,-1.0,55.215,2.51191,1904,5501141 +439,delete,129.618,-1.0,-1.0,-1.0,-1.0,430.611,2.44801,1877,5369822 +440,search,6120.42,2578.05,2077.96,1.14111,178.461,2.13108,9.18204,0.91914,0.107501,-1.0,-1.0,106.147,2.44947,1885,5369822 +441,delete,32.006,-1.0,-1.0,-1.0,-1.0,133.234,2.43906,1879,5338985 +442,search,6200.72,2558.7,2135.64,1.04474,189.486,4.67728,8.7252,0.91977,0.107048,-1.0,-1.0,39.446,2.43906,1880,5338985 +443,delete,33.753,-1.0,-1.0,-1.0,-1.0,140.095,2.42389,1869,5307279 +444,search,6285.23,2560.98,2200.94,0.979808,204.708,2.49971,8.45638,0.92034,0.106458,-1.0,-1.0,27.404,2.42389,1869,5307279 +445,delete,43.244,-1.0,-1.0,-1.0,-1.0,134.994,2.41374,1861,5268382 +446,search,6111.57,2552.26,2089.77,1.05321,185.541,2.12449,8.70046,0.9198,0.106801,-1.0,-1.0,27.682,2.41374,1861,5268382 +447,delete,459.432,-1.0,-1.0,-1.0,-1.0,1991.51,2.24611,1677,4922787 +448,search,5592.46,2635.86,1938.51,1.10167,180.501,2.20981,8.4586,0.91364,0.110398,-1.0,-1.0,310.678,2.25114,1711,4922787 +449,delete,30.131,-1.0,-1.0,-1.0,-1.0,169.405,2.2402,1698,4887227 +450,search,5685.14,2577.05,2023.7,0.964678,174.163,2.11487,8.84571,0.91545,0.1089,-1.0,-1.0,108.802,2.24036,1706,4887227 +451,delete,107.494,-1.0,-1.0,-1.0,-1.0,467.829,2.19807,1660,4795082 +452,search,5593.84,2590.06,1972.74,0.991473,183.606,2.17684,9.03822,0.91532,0.108946,-1.0,-1.0,84.271,2.19914,1668,4795082 +453,delete,320.095,-1.0,-1.0,-1.0,-1.0,1801.22,2.05339,1545,4500175 +454,search,5115.68,2593.36,1753.79,1.05938,158.216,2.11067,9.12469,0.91046,0.113013,-1.0,-1.0,354.756,2.05856,1575,4500175 +455,delete,34.861,-1.0,-1.0,-1.0,-1.0,99.385,2.05011,1569,4462648 +456,search,5274.17,2537.91,1844.33,0.960378,178.156,2.17625,9.6528,0.91087,0.112478,-1.0,-1.0,185.618,2.05061,1585,4462648 +457,delete,5.418,-1.0,-1.0,-1.0,-1.0,44.443,2.04803,1583,4456761 +458,search,5220.72,2519.64,1774.72,1.01809,168.856,2.1403,9.22964,0.91125,0.112264,-1.0,-1.0,44.475,2.04803,1585,4456761 +459,delete,53.313,-1.0,-1.0,-1.0,-1.0,208.539,2.03016,1569,4419992 +460,search,5259.16,2516.24,1839.66,1.01082,164.697,2.09899,8.91067,0.91078,0.112793,-1.0,-1.0,32.957,2.03025,1570,4419992 +461,delete,6.341,-1.0,-1.0,-1.0,-1.0,20.068,2.03025,1570,4415725 +462,search,5249.63,2509.52,1826.45,0.9939,168.923,2.10075,9.39079,0.91083,0.112606,-1.0,-1.0,21.124,2.03025,1570,4415725 +463,delete,68.316,-1.0,-1.0,-1.0,-1.0,318.867,2.00716,1541,4370609 +464,search,5185.23,2537.33,1817.22,0.998811,172.244,2.18152,8.63072,0.91053,0.112584,-1.0,-1.0,57.483,2.00769,1545,4370609 +465,delete,25.78,-1.0,-1.0,-1.0,-1.0,63.821,1.99718,1539,4345244 +466,search,5177.79,2522.36,1811.3,1.01399,161.775,2.12987,8.42054,0.90872,0.114136,-1.0,-1.0,27.753,1.99718,1540,4345244 +467,delete,33.784,-1.0,-1.0,-1.0,-1.0,123.858,1.98846,1534,4319734 +468,search,5166.53,2511.93,1796.57,0.995974,172.625,2.1642,9.16951,0.9089,0.113974,-1.0,-1.0,20.349,1.98846,1534,4319734 +469,delete,21.511,-1.0,-1.0,-1.0,-1.0,93.868,1.97838,1526,4298361 +470,search,5114.79,2513.06,1775.61,1.00474,171.819,2.18925,8.89651,0.90768,0.114937,-1.0,-1.0,30.492,1.97859,1527,4298361 +471,delete,163.874,-1.0,-1.0,-1.0,-1.0,518.807,1.92156,1472,4188315 +472,search,4953.41,2535.53,1733.42,0.970177,161.183,2.12446,9.32748,0.90696,0.115027,-1.0,-1.0,112.836,1.923,1483,4188315 +473,delete,135.758,-1.0,-1.0,-1.0,-1.0,635.753,1.86554,1432,4074567 +474,search,4734.26,2525.31,1600.06,1.01734,152.174,2.1414,8.92311,0.90541,0.116332,-1.0,-1.0,126.859,1.86717,1445,4074567 +475,delete,486.122,-1.0,-1.0,-1.0,-1.0,2185.72,1.66233,1236,3691698 +476,search,4219.68,2637.52,1486.83,1.04992,136.445,2.18291,9.45118,0.89973,0.120636,-1.0,-1.0,413.417,1.67027,1284,3691698 +477,delete,43.606,-1.0,-1.0,-1.0,-1.0,190.535,1.65178,1272,3642619 +478,search,4310.45,2530.6,1503.15,0.980387,144.483,2.17805,8.76673,0.90001,0.121018,-1.0,-1.0,86.562,1.65248,1279,3642619 +479,delete,247.511,-1.0,-1.0,-1.0,-1.0,1582.97,1.55083,1164,3421368 +480,search,4007.91,2621.57,1424.68,0.959664,135.367,2.19831,8.72782,0.89505,0.130279,-1.0,-1.0,454.712,1.55957,1196,3421368 +481,delete,48.171,-1.0,-1.0,-1.0,-1.0,184.009,1.54174,1180,3378034 +482,search,3979.5,2529.27,1382.16,0.992741,131.785,2.14481,9.53647,0.89508,0.128705,-1.0,-1.0,201.372,1.54221,1187,3378034 +483,delete,336.186,-1.0,-1.0,-1.0,-1.0,1416.2,1.40325,1039,3115682 +484,search,3600.85,2638.18,1284.21,0.922017,128.774,2.19202,9.00298,0.89062,0.129891,-1.0,-1.0,323.222,1.40984,1072,3115682 +485,delete,19.948,-1.0,-1.0,-1.0,-1.0,48.105,1.40616,1069,3094629 +486,search,3668.12,2553.51,1295.73,1.02142,114.966,2.16189,10.9024,0.89195,0.129493,-1.0,-1.0,110.212,1.40638,1078,3094629 +487,delete,13.873,-1.0,-1.0,-1.0,-1.0,20.187,1.40569,1078,3086025 +488,search,3681.12,2524.88,1281.35,1.00226,125.178,2.20716,9.39144,0.89172,0.129609,-1.0,-1.0,21.998,1.40569,1078,3086025 +489,delete,52.758,-1.0,-1.0,-1.0,-1.0,150.25,1.39261,1068,3052105 +490,search,3649.02,2519.43,1275.48,1.03481,120.082,2.1119,8.091,0.89158,0.129224,-1.0,-1.0,54.492,1.39305,1071,3052105 +491,delete,15.722,-1.0,-1.0,-1.0,-1.0,48.248,1.38873,1068,3038974 +492,search,3648.5,2512.09,1283.85,0.987192,116.804,2.23156,8.72093,0.89117,0.129775,-1.0,-1.0,21.448,1.38873,1068,3038974 +493,delete,186.259,-1.0,-1.0,-1.0,-1.0,629.889,1.31941,1003,2911063 +494,search,3455.01,2564.22,1230.21,0.926686,108.416,2.14302,8.90165,0.88846,0.132009,-1.0,-1.0,89.893,1.32032,1010,2911063 +495,delete,28.382,-1.0,-1.0,-1.0,-1.0,112.754,1.31082,1000,2888785 +496,search,3430.38,2544.73,1224.82,0.984651,112.421,2.16216,9.07756,0.88804,0.131771,-1.0,-1.0,69.425,1.31125,1005,2888785 +497,delete,81.96,-1.0,-1.0,-1.0,-1.0,168.947,1.28934,987,2829718 +498,search,3383.02,2518.51,1191.55,0.939508,107.298,2.14187,7.71341,0.88672,0.132265,-1.0,-1.0,18.877,1.28934,987,2829718 +499,delete,22.841,-1.0,-1.0,-1.0,-1.0,42.399,1.28572,984,2816082 +500,search,3367.17,2511.98,1174,0.957327,117.912,2.20515,8.97271,0.88601,0.132832,-1.0,-1.0,18.086,1.28572,984,2816082 +501,delete,28.434,-1.0,-1.0,-1.0,-1.0,110.919,1.2768,975,2790880 +502,search,3230.54,2512.42,1105.96,1.08023,101.218,2.19402,9.90639,0.88581,0.132754,-1.0,-1.0,28.411,1.27698,976,2790880 +503,delete,19.576,-1.0,-1.0,-1.0,-1.0,30.515,1.27541,975,2774459 +504,search,3348.5,2498.14,1168.89,1.00288,103.05,2.1837,9.06869,0.88539,0.132951,-1.0,-1.0,18.067,1.27541,975,2774459 +505,delete,82.032,-1.0,-1.0,-1.0,-1.0,183.198,1.24704,955,2714683 +506,search,3280.94,2493.53,1151.97,0.9809,104.712,2.1232,10.2477,0.8838,0.133331,-1.0,-1.0,28.081,1.24711,956,2714683 +507,delete,54.231,-1.0,-1.0,-1.0,-1.0,122.388,1.23432,945,2680986 +508,search,3138.22,2487.34,1053.76,1.12662,91.1182,2.18904,8.66887,0.88317,0.133689,-1.0,-1.0,70.407,1.23515,951,2680986 +509,delete,23.241,-1.0,-1.0,-1.0,-1.0,123.171,1.22514,944,2662966 +510,search,3103.48,2478.31,1011.52,1.18829,96.3774,2.19827,12.3337,0.88324,0.133528,-1.0,-1.0,37.405,1.22548,946,2662966 +511,delete,26.07,-1.0,-1.0,-1.0,-1.0,54.972,1.22074,942,2642855 +512,search,3078.9,2460,995.15,1.16601,93.2664,2.14374,11.4085,0.88249,0.134501,-1.0,-1.0,16.886,1.22074,942,2642855 +513,insert,433.765,-1.0,-1.0,-1.0,-1.0,359.656,1.32573,973,2906838 +514,search,3355,2593.48,1200.44,0.977786,106.36,2.18338,11.0565,0.8846,0.133063,-1.0,-1.0,140.813,1.32593,985,2906838 +515,insert,7.785,-1.0,-1.0,-1.0,-1.0,45.797,1.32775,988,2913746 +516,search,3398.68,2568.72,1211.35,0.958387,107.009,2.10656,8.71371,0.88575,0.132443,-1.0,-1.0,17.796,1.32775,988,2913746 +517,insert,34.991,-1.0,-1.0,-1.0,-1.0,70.436,1.33458,997,2936862 +518,search,3433.66,2562.13,1224.48,0.981601,111.116,3.37818,8.96953,0.8863,0.131943,-1.0,-1.0,25.088,1.33468,998,2936862 +519,insert,122.368,-1.0,-1.0,-1.0,-1.0,142.075,1.36572,1007,3009732 +520,search,3478.76,2598.48,1246.27,0.954578,114.351,2.66438,8.88152,0.88705,0.132185,-1.0,-1.0,107.148,1.36589,1016,3009732 +521,insert,26.371,-1.0,-1.0,-1.0,-1.0,53.889,1.37147,1020,3025906 +522,search,3523.58,2584.23,1254.98,0.968291,116.471,2.16449,10.3859,0.88773,0.131781,-1.0,-1.0,48.113,1.37169,1024,3025906 +523,insert,57.76,-1.0,-1.0,-1.0,-1.0,106.28,1.38627,1034,3061899 +524,search,3552.29,2577.16,1257.66,1.00677,115.799,2.18049,10.8237,0.88832,0.131624,-1.0,-1.0,41.054,1.38632,1036,3061899 +525,insert,64.523,-1.0,-1.0,-1.0,-1.0,120.778,1.40198,1049,3101209 +526,search,3622.17,2575.56,1289.07,0.971519,117.635,2.66163,10.9425,0.88872,0.131419,-1.0,-1.0,31.666,1.40212,1051,3101209 +527,insert,738.044,-1.0,-1.0,-1.0,-1.0,872.441,1.58454,1172,3522334 +528,search,4025.58,2660.5,1458.73,0.945779,131.533,2.21129,9.00364,0.89622,0.125253,-1.0,-1.0,197.728,1.58697,1198,3522334 +529,insert,404.524,-1.0,-1.0,-1.0,-1.0,461.736,1.70442,1267,3797294 +530,search,4369.49,2688.17,1584.25,0.997461,149.367,2.16807,9.12073,0.90228,0.121865,-1.0,-1.0,138.449,1.70576,1281,3797294 +531,insert,106.363,-1.0,-1.0,-1.0,-1.0,164.276,1.72972,1299,3853781 +532,search,4444,2661.78,1590.48,1.0065,141.391,2.18883,9.09593,0.90226,0.121877,-1.0,-1.0,38.762,1.72981,1302,3853781 +533,insert,27.331,-1.0,-1.0,-1.0,-1.0,50.009,1.73654,1306,3873352 +534,search,4489.29,2661.32,1614.35,1.00901,150.409,2.19009,7.45947,0.90259,0.121664,-1.0,-1.0,18.125,1.73654,1306,3873352 +535,insert,31.017,-1.0,-1.0,-1.0,-1.0,66.631,1.74367,1313,3893308 +536,search,4401.39,2665.9,1525.86,1.05776,139.114,2.16064,8.78021,0.90293,0.121386,-1.0,-1.0,18.312,1.74367,1313,3893308 +537,insert,9.645,-1.0,-1.0,-1.0,-1.0,26.436,1.74655,1314,3901271 +538,search,4426.81,2666.57,1552.69,1.10564,142.318,2.17928,8.16269,0.90352,0.120951,-1.0,-1.0,50.016,1.74703,1318,3901271 +539,insert,33.615,-1.0,-1.0,-1.0,-1.0,52.19,1.75489,1323,3925164 +540,search,4556.89,2663.68,1643.11,0.994465,150.182,2.43607,8.25252,0.90348,0.120964,-1.0,-1.0,26.279,1.7549,1324,3925164 +541,insert,585.599,-1.0,-1.0,-1.0,-1.0,712.248,1.93387,1415,4320915 +542,search,4948.6,2770.72,1821.46,0.974694,175.161,3.39312,9.24032,0.90771,0.117638,-1.0,-1.0,327.478,1.93604,1460,4320915 +543,insert,59.679,-1.0,-1.0,-1.0,-1.0,112.541,1.95133,1475,4360814 +544,search,5056.77,2662.82,1830.39,0.989268,165.082,2.16786,9.20311,0.90782,0.117671,-1.0,-1.0,66.887,1.95148,1481,4360814 +545,insert,15.899,-1.0,-1.0,-1.0,-1.0,27.485,1.95554,1482,4370220 +546,search,4969.38,2652.38,1735.57,1.06767,155.105,2.14467,8.24008,0.90787,0.117579,-1.0,-1.0,24.673,1.9556,1483,4370220 +547,insert,235.775,-1.0,-1.0,-1.0,-1.0,328.354,2.01923,1539,4510675 +548,search,5246.73,2641.55,1885.42,0.998097,175.329,2.17084,8.20406,0.90997,0.115241,-1.0,-1.0,30.37,2.01927,1541,4510675 +549,insert,328.416,-1.0,-1.0,-1.0,-1.0,335.408,2.11719,1573,4744845 +550,search,5381.25,2686.7,1950.39,0.993686,173.21,2.16529,9.41825,0.90697,0.119394,-1.0,-1.0,163.723,2.11787,1584,4744845 +551,insert,32.276,-1.0,-1.0,-1.0,-1.0,71.025,2.13085,1588,4771433 +552,search,5327.74,2669.73,1874.76,1.08096,164.574,2.15018,8.70849,0.90719,0.118748,-1.0,-1.0,108.408,2.13123,1597,4771433 +553,insert,14.922,-1.0,-1.0,-1.0,-1.0,25.523,2.13442,1598,4782909 +554,search,5459.82,2657.68,1980.61,0.996333,182.971,2.17078,9.6716,0.9075,0.118357,-1.0,-1.0,56.253,2.13449,1601,4782909 +555,insert,645.509,-1.0,-1.0,-1.0,-1.0,815.576,2.31425,1745,5180322 +556,search,5936.61,2671.99,2149.78,1.08668,197.547,2.20235,9.53937,0.91313,0.113199,-1.0,-1.0,128.759,2.31485,1760,5180322 +557,insert,25.987,-1.0,-1.0,-1.0,-1.0,46.916,2.32078,1764,5203220 +558,search,5990.66,2654.69,2145.34,0.996794,197.71,2.19084,8.81969,0.91355,0.113124,-1.0,-1.0,43.258,2.32094,1767,5203220 +559,insert,7.168,-1.0,-1.0,-1.0,-1.0,39.318,2.32334,1769,5210154 +560,search,5972.77,2652.06,2117.66,1.04523,192.486,2.84343,7.88232,0.91373,0.112989,-1.0,-1.0,21.033,2.32334,1769,5210154 +561,insert,6.445,-1.0,-1.0,-1.0,-1.0,32.194,2.32496,1771,5215426 +562,search,6038.32,2650.64,2155.19,1.001,195.267,2.1564,9.48249,0.91377,0.113003,-1.0,-1.0,25.071,2.32496,1771,5215426 +563,insert,67.151,-1.0,-1.0,-1.0,-1.0,134.15,2.33873,1788,5252726 +564,search,6000.88,2644.21,2117.18,1.05586,187.176,2.21187,8.96971,0.91406,0.112674,-1.0,-1.0,52.216,2.33913,1792,5252726 +565,insert,305.171,-1.0,-1.0,-1.0,-1.0,360.666,2.42467,1824,5447274 +566,search,6137,2673.8,2161.11,1.04923,196.512,2.37787,8.96204,0.91434,0.112786,-1.0,-1.0,92.861,2.42534,1833,5447274 +567,insert,20.613,-1.0,-1.0,-1.0,-1.0,33.86,2.4323,1835,5463135 +568,search,6250.89,2663.19,2247.17,0.979041,209.712,2.13323,9.59511,0.91436,0.112741,-1.0,-1.0,58.353,2.43244,1839,5463135 +569,insert,23.163,-1.0,-1.0,-1.0,-1.0,60.002,2.439,1844,5478168 +570,search,6142.4,2659.16,2145.31,1.03441,191.484,2.14522,9.53366,0.91443,0.112757,-1.0,-1.0,23.289,2.439,1844,5478168 +571,insert,20.421,-1.0,-1.0,-1.0,-1.0,40.736,2.44516,1845,5492309 +572,search,6169.53,2662.04,2163.23,1.0333,193.304,2.15925,8.9191,0.91412,0.113075,-1.0,-1.0,22.457,2.44516,1845,5492309 +573,insert,91.304,-1.0,-1.0,-1.0,-1.0,119.988,2.46673,1858,5554599 +574,search,6339.62,2673.64,2281.46,1.00131,211.839,2.14418,8.67172,0.91515,0.111996,-1.0,-1.0,29.075,2.46675,1859,5554599 +575,insert,85.612,-1.0,-1.0,-1.0,-1.0,144.95,2.48883,1873,5604500 +576,search,6401.62,2680.31,2313.07,0.953921,214.822,2.17235,8.55493,0.91571,0.111582,-1.0,-1.0,45.57,2.48905,1877,5604500 +577,insert,51.996,-1.0,-1.0,-1.0,-1.0,106.091,2.50209,1893,5638834 +578,search,6340.92,2670.6,2238.16,1.0245,204.018,2.21994,8.81228,0.91593,0.111148,-1.0,-1.0,36.663,2.50238,1895,5638834 +579,insert,970.645,-1.0,-1.0,-1.0,-1.0,1254.31,2.78281,2087,6229778 +580,search,7010.14,2707.36,2503.13,1.03351,227.013,2.134,9.56808,0.92018,0.108348,-1.0,-1.0,111.855,2.78343,2100,6229778 +581,insert,42.809,-1.0,-1.0,-1.0,-1.0,115.241,2.79737,2112,6261240 +582,search,7146.12,2688.49,2590.95,0.985253,238.028,2.16376,8.87744,0.92023,0.108255,-1.0,-1.0,26.71,2.79737,2112,6261240 +583,insert,26.382,-1.0,-1.0,-1.0,-1.0,84.089,2.8057,2120,6283315 +584,search,7143.1,2687.45,2559.76,1.03084,232.881,2.14413,8.57555,0.92056,0.107933,-1.0,-1.0,60.198,2.80618,2124,6283315 +585,insert,359.395,-1.0,-1.0,-1.0,-1.0,491.914,2.93355,2181,6556101 +586,search,7189.06,2709.44,2497.04,1.11188,209.043,2.14751,8.83756,0.92199,0.107289,-1.0,-1.0,230.718,2.93579,2207,6556101 +587,insert,42.007,-1.0,-1.0,-1.0,-1.0,108.886,2.94733,2218,6587187 +588,search,7433.53,2672.29,2649.06,1.00221,238.734,2.16602,8.51224,0.92235,0.106976,-1.0,-1.0,73.504,2.94755,2223,6587187 +589,insert,71.603,-1.0,-1.0,-1.0,-1.0,104.259,2.96329,2235,6631526 +590,search,7565.79,2666.99,2730.09,0.992804,252.133,2.1562,8.65332,0.92285,0.10641,-1.0,-1.0,46.458,2.96358,2237,6631526 +591,insert,673.777,-1.0,-1.0,-1.0,-1.0,808.101,3.16818,2368,7108942 +592,search,8077.3,2729.8,2961.74,0.971779,279.272,2.16564,8.10575,0.92709,0.102706,-1.0,-1.0,195.522,3.16951,2393,7108942 +593,insert,252.832,-1.0,-1.0,-1.0,-1.0,328.295,3.25389,2436,7303976 +594,search,8305.95,2728.65,3025.86,0.975828,292.503,2.17261,9.11149,0.92836,0.102405,-1.0,-1.0,174.051,3.25566,2456,7303976 +595,insert,5.586,-1.0,-1.0,-1.0,-1.0,38.826,3.25701,2458,7309244 +596,search,8335.32,2701.51,3022.24,0.986652,279.55,2.15694,9.30662,0.92849,0.102245,-1.0,-1.0,80.36,3.2575,2464,7309244 +597,insert,325.964,-1.0,-1.0,-1.0,-1.0,434.044,3.363,2522,7542477 +598,search,8612.21,2724.73,3143.07,0.976487,300.085,2.16198,7.83561,0.9312,0.0999456,-1.0,-1.0,242.481,3.36624,2557,7542477 +599,insert,139.095,-1.0,-1.0,-1.0,-1.0,276.951,3.40765,2599,7654438 +600,search,8792.24,2683.99,3172.23,0.988879,292.758,2.18313,8.75488,0.93147,0.09954,-1.0,-1.0,82.131,3.40876,2608,7654438 +601,insert,83.612,-1.0,-1.0,-1.0,-1.0,152.116,3.43745,2627,7717936 +602,search,8872.86,2677.28,3188.44,0.966072,300.319,2.16466,8.11468,0.93235,0.0987201,-1.0,-1.0,73.057,3.43783,2634,7717936 +603,insert,6.679,-1.0,-1.0,-1.0,-1.0,25.852,3.43945,2634,7723521 +604,search,8853.14,2671.57,3177.48,1.03,290.894,2.14781,8.71958,0.93241,0.0987031,-1.0,-1.0,30.127,3.43945,2634,7723521 +605,insert,72.29,-1.0,-1.0,-1.0,-1.0,101.428,3.45583,2644,7767404 +606,search,8913.69,2678.7,3199.25,1.02127,298.382,2.15545,8.85685,0.9326,0.0987912,-1.0,-1.0,29.007,3.45583,2644,7767404 +607,insert,100.632,-1.0,-1.0,-1.0,-1.0,54.277,3.4767,2647,7826115 +608,search,8966.05,2686.91,3233.76,0.999251,306.515,2.15309,8.99679,0.93235,0.0989124,-1.0,-1.0,42.415,3.47684,2649,7826115 +609,insert,312.103,-1.0,-1.0,-1.0,-1.0,418.003,3.56603,2702,8036351 +610,search,9182.17,2695.73,3321.43,0.960355,315.761,2.20229,8.40403,0.93352,0.0977004,-1.0,-1.0,79.293,3.56629,2708,8036351 +611,insert,33.641,-1.0,-1.0,-1.0,-1.0,71.245,3.57559,2715,8060364 +612,search,9195.1,2688.82,3325,1.02786,310.155,2.18487,8.12103,0.93369,0.0976991,-1.0,-1.0,61.746,3.57576,2719,8060364 +613,insert,278.1,-1.0,-1.0,-1.0,-1.0,357.693,3.66294,2766,8256083 +614,search,9351.19,2700.68,3394.58,1.0007,317.92,2.14298,8.52057,0.93475,0.0965308,-1.0,-1.0,122.95,3.66437,2782,8256083 +615,insert,458.732,-1.0,-1.0,-1.0,-1.0,635.828,3.83282,2863,8625707 +616,search,9735.77,2714.72,3541.31,0.985341,332.138,2.88095,8.40871,0.93665,0.0945862,-1.0,-1.0,314.562,3.83537,2908,8625707 +617,insert,398.677,-1.0,-1.0,-1.0,-1.0,667.992,3.97915,2987,8949227 +618,search,10054.2,2686.41,3630.84,0.991558,340.455,2.38865,9.91561,0.93821,0.093056,-1.0,-1.0,327.396,3.98174,3031,8949227 +619,insert,284.561,-1.0,-1.0,-1.0,-1.0,418.617,4.08384,3090,9195551 +620,search,10305.7,2646.76,3671.65,0.998419,334.098,2.11931,8.82791,0.93925,0.0918332,-1.0,-1.0,200.031,4.08546,3110,9195551 +621,insert,47.078,-1.0,-1.0,-1.0,-1.0,79.83,4.10007,3118,9232372 +622,search,10421.4,2632.2,3705.75,0.988474,347.065,3.25307,7.96301,0.93946,0.0915174,-1.0,-1.0,90.594,4.10057,3123,9232372 +623,insert,25.892,-1.0,-1.0,-1.0,-1.0,60.837,4.1094,3128,9253561 +624,search,10528.3,2634.3,3764.71,0.97012,365.783,2.14437,8.70782,0.93961,0.0912735,-1.0,-1.0,77.404,4.10992,3135,9253561 +625,insert,99.417,-1.0,-1.0,-1.0,-1.0,185.105,4.14274,3154,9331230 +626,search,10599,2632.77,3782.08,1.01203,362.956,2.16451,8.92612,0.94001,0.090979,-1.0,-1.0,66.317,4.14342,3160,9331230 +627,insert,73.587,-1.0,-1.0,-1.0,-1.0,107.822,4.16176,3172,9374063 +628,search,10605.5,2629.68,3778.53,0.972963,357.274,2.65072,8.34092,0.94006,0.0909517,-1.0,-1.0,30.466,4.16176,3172,9374063 +629,insert,24.024,-1.0,-1.0,-1.0,-1.0,55.241,4.16726,3175,9387598 +630,search,10648,2630.88,3807.3,0.973403,364.099,2.13903,9.1745,0.94027,0.0907873,-1.0,-1.0,45.986,4.16742,3178,9387598 +631,insert,64.901,-1.0,-1.0,-1.0,-1.0,62.062,4.18109,3182,9421724 +632,search,10626.6,2629.75,3795.08,0.992216,354.967,2.38727,9.3418,0.94021,0.0908149,-1.0,-1.0,41.217,4.18118,3183,9421724 +633,insert,64.067,-1.0,-1.0,-1.0,-1.0,132.568,4.19669,3198,9461430 +634,search,10662.9,2632.25,3783.07,1.03107,345.474,2.16934,8.37784,0.94048,0.0905006,-1.0,-1.0,35.258,4.19669,3198,9461430 +635,insert,47.574,-1.0,-1.0,-1.0,-1.0,103.612,4.20258,3206,9479469 +636,search,10720.1,2630.59,3807.59,1.00901,355.728,2.13828,8.0844,0.94064,0.0904735,-1.0,-1.0,39.814,4.20264,3207,9479469 +637,insert,692.741,-1.0,-1.0,-1.0,-1.0,921.281,4.38872,3344,9885997 +638,search,11235,2642.49,4031.88,0.976575,386.688,2.16984,9.44998,0.94272,0.0884278,-1.0,-1.0,195.445,4.39215,3369,9885997 +639,insert,570.863,-1.0,-1.0,-1.0,-1.0,868.025,4.57013,3506,10292043 +640,search,11725.9,2629.8,4195.15,1.0085,393.803,2.15365,8.41465,0.94395,0.0876046,-1.0,-1.0,171.212,4.57199,3525,10292043 +641,delete,217.222,-1.0,-1.0,-1.0,-1.0,1881.19,4.49006,3451,10096584 +642,search,11550,2619.94,4128.4,0.970531,390.553,2.16584,8.66097,0.94314,0.088411,-1.0,-1.0,144.121,4.49216,3465,10096584 +643,delete,12.654,-1.0,-1.0,-1.0,-1.0,62.604,4.49093,3464,10084840 +644,search,11537.4,2607.87,4095.56,0.978474,375.847,2.1575,8.60995,0.94321,0.0883537,-1.0,-1.0,72.065,4.49145,3465,10084840 +645,delete,25.487,-1.0,-1.0,-1.0,-1.0,35.084,4.49145,3465,10069802 +646,search,11506,2601.88,4054.89,1.01509,366.664,2.13837,9.24514,0.94323,0.0883342,-1.0,-1.0,39.863,4.49145,3465,10069802 +647,delete,143.678,-1.0,-1.0,-1.0,-1.0,879.967,4.45564,3429,9990953 +648,search,11478.4,2606.11,4058.56,1.00749,385.302,2.15261,9.03574,0.94257,0.0885648,-1.0,-1.0,93.59,4.45623,3434,9990953 +649,delete,64.173,-1.0,-1.0,-1.0,-1.0,157.236,4.45179,3430,9951625 +650,search,11404.3,2595.44,4007.49,1.01943,378.702,2.15109,8.7427,0.94269,0.0886288,-1.0,-1.0,38.251,4.45179,3430,9951625 +651,delete,39.354,-1.0,-1.0,-1.0,-1.0,258.091,4.4419,3421,9927065 +652,search,10922.7,2599.31,3629.15,1.13513,301.883,2.08717,9.02227,0.94255,0.0888328,-1.0,-1.0,51.041,4.44204,3422,9927065 +653,delete,133.739,-1.0,-1.0,-1.0,-1.0,829.222,4.39925,3382,9831098 +654,search,10805,2599.58,3597.05,1.1459,296.216,2.09977,9.11409,0.94218,0.0888652,-1.0,-1.0,77.376,4.39983,3386,9831098 +655,delete,492.602,-1.0,-1.0,-1.0,-1.0,2909.46,4.24922,3227,9462172 +656,search,10588,2617.22,3637.82,1.04922,321.151,2.11876,10.0076,0.94031,0.0911645,-1.0,-1.0,320.995,4.25337,3260,9462172 +657,delete,251.429,-1.0,-1.0,-1.0,-1.0,880.589,4.16541,3164,9218902 +658,search,10335.7,2590.39,3549.66,1.06798,316.814,2.16572,9.47313,0.93761,0.0930735,-1.0,-1.0,104.285,4.16622,3173,9218902 +659,delete,174.642,-1.0,-1.0,-1.0,-1.0,865.158,4.11201,3125,9106546 +660,search,10312.7,2582.13,3593.95,1.04751,330.117,2.15571,9.17991,0.93701,0.0937447,-1.0,-1.0,142.668,4.11372,3136,9106546 +661,delete,68.539,-1.0,-1.0,-1.0,-1.0,199.925,4.10462,3130,9059776 +662,search,10248.1,2567.96,3511.56,1.0846,321.175,2.14406,8.52,0.93712,0.0934899,-1.0,-1.0,50.719,4.10483,3131,9059776 +663,delete,114.363,-1.0,-1.0,-1.0,-1.0,543.977,4.07693,3104,8990616 +664,search,10109.2,2564.51,3453.09,1.08002,309.673,2.13565,9.21014,0.9362,0.0942932,-1.0,-1.0,71.515,4.07767,3107,8990616 +665,delete,70.445,-1.0,-1.0,-1.0,-1.0,499.959,4.05066,3088,8937437 +666,search,10085.4,2563.26,3446.81,1.07232,309.805,2.1412,8.78845,0.93594,0.094591,-1.0,-1.0,54.399,4.05098,3090,8937437 +667,delete,225.995,-1.0,-1.0,-1.0,-1.0,1363.64,3.96971,3020,8766390 +668,search,9908.23,2564.47,3428.96,1.066,311.73,2.25289,9.05846,0.93511,0.0957063,-1.0,-1.0,197.159,3.97177,3035,8766390 +669,delete,266.828,-1.0,-1.0,-1.0,-1.0,2227.9,3.86155,2928,8532008 +670,search,9723.93,2567.7,3403.14,1.00038,312.172,2.14948,9.353,0.93439,0.0956478,-1.0,-1.0,258.65,3.86538,2953,8532008 +671,delete,50.775,-1.0,-1.0,-1.0,-1.0,223.431,3.85156,2940,8489178 +672,search,9759.74,2540.61,3416.77,0.977619,320.538,2.15648,9.6547,0.93453,0.0960209,-1.0,-1.0,89.089,3.85156,2944,8489178 +673,delete,89.68,-1.0,-1.0,-1.0,-1.0,390.338,3.82508,2922,8421866 +674,search,9698.31,2537.14,3383,0.983541,327.57,2.14177,9.34259,0.93423,0.0960861,-1.0,-1.0,64.637,3.82541,2925,8421866 +675,delete,196.046,-1.0,-1.0,-1.0,-1.0,926.449,3.77328,2870,8288319 +676,search,9541.33,2548.28,3338.13,1.00609,318.688,2.26628,9.02737,0.93415,0.0963306,-1.0,-1.0,162.613,3.77638,2876,8288319 +677,delete,220.222,-1.0,-1.0,-1.0,-1.0,640.038,3.69903,2840,8072197 +678,search,9271.78,2517.75,3139.8,1.04398,280.423,2.15358,9.22276,0.93658,0.093414,-1.0,-1.0,107.809,3.69965,2846,8072197 +679,delete,36.598,-1.0,-1.0,-1.0,-1.0,406.688,3.68265,2834,8036947 +680,search,9279.51,2514.07,3180.32,1.01138,286.983,2.33273,8.91618,0.93668,0.0932087,-1.0,-1.0,86.958,3.68341,2838,8036947 +681,delete,10.746,-1.0,-1.0,-1.0,-1.0,30.08,3.68312,2838,8026197 +682,search,9369.62,2509.86,3230,0.979416,296.899,2.15341,8.19871,0.93672,0.0931063,-1.0,-1.0,31.528,3.68312,2838,8026197 +683,delete,423.607,-1.0,-1.0,-1.0,-1.0,2021.87,3.56823,2705,7744229 +684,search,8761.33,2548.29,2948.22,1.06166,259.162,2.11819,9.0634,0.93658,0.0938199,-1.0,-1.0,192.433,3.57046,2725,7744229 +685,delete,303.567,-1.0,-1.0,-1.0,-1.0,1413.53,3.48065,2622,7541066 +686,search,8614.69,2561.92,2966.48,1.00638,272.286,2.10152,9.11044,0.93378,0.0972359,-1.0,-1.0,284.174,3.48368,2653,7541066 +687,delete,21.027,-1.0,-1.0,-1.0,-1.0,127.42,3.47826,2649,7522190 +688,search,8813.22,2522.3,3075.89,0.968207,295.715,2.15422,9.35403,0.93329,0.0974451,-1.0,-1.0,65.678,3.47893,2652,7522190 +689,delete,157.58,-1.0,-1.0,-1.0,-1.0,614.061,3.41949,2621,7409400 +690,search,8499.61,2513.22,2873.31,1.06243,255.757,2.09349,8.711,0.93258,0.0977958,-1.0,-1.0,84.78,3.42032,2626,7409400 +691,delete,50.988,-1.0,-1.0,-1.0,-1.0,88.251,3.41248,2622,7375648 +692,search,8571.33,2497.81,2935.48,1.05422,257.041,2.13216,8.99167,0.9327,0.0976918,-1.0,-1.0,48.993,3.41276,2624,7375648 +693,delete,220.197,-1.0,-1.0,-1.0,-1.0,521.984,3.34718,2597,7222068 +694,search,8361.82,2471.79,2772.67,1.07994,245.71,2.11012,9.36002,0.93278,0.0977682,-1.0,-1.0,99.422,3.34765,2603,7222068 +695,delete,31.012,-1.0,-1.0,-1.0,-1.0,236.763,3.33466,2595,7196331 +696,search,8539.62,2476.31,2939.74,0.987576,279.549,2.16114,9.22251,0.93332,0.0968277,-1.0,-1.0,67.082,3.33522,2599,7196331 +697,delete,35.124,-1.0,-1.0,-1.0,-1.0,181.247,3.32179,2592,7170716 +698,search,8491.82,2466.37,2931.93,0.98286,255.792,2.12845,8.30874,0.93347,0.0967656,-1.0,-1.0,42.428,3.32185,2593,7170716 +699,delete,22.27,-1.0,-1.0,-1.0,-1.0,120.42,3.31296,2588,7155255 +700,search,8437.25,2468.64,2876.35,1.02535,250.644,2.09744,9.6107,0.93395,0.0961656,-1.0,-1.0,49.21,3.31317,2590,7155255 +701,delete,94.179,-1.0,-1.0,-1.0,-1.0,190.212,3.30145,2582,7097733 +702,search,8487.65,2449.21,2906.54,0.979857,271.122,2.13783,9.05043,0.93351,0.0965103,-1.0,-1.0,41.417,3.30148,2583,7097733 +703,delete,294.996,-1.0,-1.0,-1.0,-1.0,1077.59,3.21184,2507,6924172 +704,search,8241.23,2459.89,2805.19,1.01214,264.488,2.156,9.32177,0.93325,0.0968531,-1.0,-1.0,143.608,3.21344,2518,6924172 +705,delete,43.311,-1.0,-1.0,-1.0,-1.0,121.27,3.20573,2510,6896276 +706,search,8272.01,2447.12,2848.82,0.98678,257.536,2.0872,9.05113,0.93325,0.0969047,-1.0,-1.0,49.708,3.20614,2512,6896276 +707,delete,770.86,-1.0,-1.0,-1.0,-1.0,4423.63,2.90875,2179,6385507 +708,search,7323.23,2663.77,2591.88,1.02386,236.149,2.32893,10.8842,0.93259,0.0991764,-1.0,-1.0,855.046,2.92513,2306,6385507 +709,delete,169.245,-1.0,-1.0,-1.0,-1.0,1225.85,2.83029,2214,6207658 +710,search,7330.57,2482.73,2518.57,0.967773,240.693,2.18859,8.42454,0.92884,0.102458,-1.0,-1.0,279.91,2.83442,2251,6207658 +711,delete,43.517,-1.0,-1.0,-1.0,-1.0,234.583,2.81646,2239,6162720 +712,search,7340.87,2420.24,2486.39,0.996043,230.237,2.151,8.00985,0.92811,0.103226,-1.0,-1.0,76.145,2.81724,2244,6162720 +713,delete,310.967,-1.0,-1.0,-1.0,-1.0,1327.89,2.7073,2164,5927803 +714,search,7087.9,2415.37,2407.72,1.00872,221.98,2.12471,8.32557,0.92549,0.105311,-1.0,-1.0,130.291,2.70867,2172,5927803 +715,delete,38.052,-1.0,-1.0,-1.0,-1.0,180.886,2.69466,2162,5895666 +716,search,6991.26,2404.87,2326.35,1.04192,204.491,2.09679,9.60724,0.9256,0.105179,-1.0,-1.0,36.096,2.69466,2162,5895666 +717,delete,51.937,-1.0,-1.0,-1.0,-1.0,177.051,2.68577,2152,5868774 +718,search,6958.39,2403.54,2295.12,1.04755,210.338,2.15991,9.69897,0.92537,0.105385,-1.0,-1.0,46.256,2.68599,2153,5868774 +719,delete,546.644,-1.0,-1.0,-1.0,-1.0,2489.14,2.52302,1942,5533540 +720,search,6529.63,2545.82,2291.33,0.960884,203.136,2.1748,9.11051,0.92251,0.107521,-1.0,-1.0,365.576,2.52871,1993,5533540 +721,delete,136.918,-1.0,-1.0,-1.0,-1.0,589.301,2.47968,1951,5418387 +722,search,6313.11,2459.83,2093.98,1.08699,189.866,2.12931,11.3094,0.92,0.109969,-1.0,-1.0,254.852,2.48212,1975,5418387 +723,delete,24.256,-1.0,-1.0,-1.0,-1.0,114.906,2.47683,1970,5398291 +724,search,6499.03,2405.03,2212.9,1.00655,216.852,2.17662,8.44342,0.91903,0.110604,-1.0,-1.0,70.927,2.47687,1973,5398291 +725,delete,168.09,-1.0,-1.0,-1.0,-1.0,833.541,2.4181,1914,5273546 +726,search,6206.13,2409.75,2143.72,1.01629,202.07,2.17903,8.85903,0.91776,0.11143,-1.0,-1.0,165.484,2.42019,1926,5273546 +727,delete,106.547,-1.0,-1.0,-1.0,-1.0,705.732,2.37913,1871,5180937 +728,search,5987.57,2437.21,2035.88,1.04677,188.216,2.17244,10.0585,0.91778,0.111042,-1.0,-1.0,112.879,2.38067,1886,5180937 +729,delete,98.49,-1.0,-1.0,-1.0,-1.0,441.748,2.33803,1843,5079524 +730,search,5961.07,2412.43,1996.04,1.03888,179.14,2.13621,10.9199,0.91676,0.111472,-1.0,-1.0,102.964,2.33901,1853,5079524 +731,delete,71.16,-1.0,-1.0,-1.0,-1.0,173.136,2.32191,1839,5019265 +732,search,5892.07,2387.1,2032.71,0.990122,192.446,2.15616,8.39025,0.91605,0.112112,-1.0,-1.0,65.98,2.32231,1843,5019265 +733,delete,91.719,-1.0,-1.0,-1.0,-1.0,258.616,2.29701,1825,4955565 +734,search,5918.27,2369,1962.45,0.990495,170.453,2.10577,8.35529,0.91573,0.112638,-1.0,-1.0,49.465,2.29729,1827,4955565 +735,delete,207.504,-1.0,-1.0,-1.0,-1.0,489.5,2.21729,1781,4776948 +736,search,5690.81,2360.02,1974.58,0.962436,169.751,2.09688,8.66426,0.91907,0.10937,-1.0,-1.0,111.802,2.21768,1791,4776948 +737,delete,146.222,-1.0,-1.0,-1.0,-1.0,578.797,2.16602,1753,4654026 +738,search,5516.17,2333.59,1806.6,1.08377,157.606,2.14175,8.39516,0.91809,0.110547,-1.0,-1.0,81.951,2.16649,1758,4654026 +739,delete,63.077,-1.0,-1.0,-1.0,-1.0,305.425,2.13489,1735,4589888 +740,search,5527.75,2328.18,1895.96,1.01374,159.442,2.12288,8.44423,0.91898,0.10927,-1.0,-1.0,100.376,2.13562,1741,4589888 +741,delete,216.607,-1.0,-1.0,-1.0,-1.0,542.953,2.05317,1676,4430862 +742,search,4393.29,2320.06,1690.48,1.10295,150.758,2.09739,9.23153,0.91759,0.11134,-1.0,-1.0,97.638,2.05565,1688,4430862 +743,delete,143.843,-1.0,-1.0,-1.0,-1.0,901.494,1.95924,1593,4237049 +744,search,4182.46,2344.86,1633.16,1.09573,139.44,2.06261,9.15419,0.91498,0.113146,-1.0,-1.0,165.507,1.96451,1614,4237049 +745,delete,196.294,-1.0,-1.0,-1.0,-1.0,961.166,1.82602,1491,4000195 +746,search,3959.94,2405.54,1551.3,1.14883,136.373,2.09702,9.26397,0.91275,0.113781,-1.0,-1.0,125.607,1.82822,1511,4000195 +747,delete,146.417,-1.0,-1.0,-1.0,-1.0,979.573,1.73233,1428,3803954 +748,search,4641.76,2395.51,1628.12,0.967005,142.968,2.07421,8.77338,0.90972,0.115958,-1.0,-1.0,141.806,1.73536,1443,3803954 +749,delete,64.079,-1.0,-1.0,-1.0,-1.0,245.964,1.70945,1420,3733214 +750,search,4517.19,2366.07,1606.09,0.932806,140.255,3.11736,8.38133,0.90955,0.115926,-1.0,-1.0,68.946,1.7099,1424,3733214 +751,delete,35.593,-1.0,-1.0,-1.0,-1.0,192.814,1.69574,1411,3709324 +752,search,4575.75,2359.56,1504.68,1.05583,132.77,2.15057,9.19086,0.90816,0.117002,-1.0,-1.0,50.277,1.69641,1414,3709324 +753,delete,87.92,-1.0,-1.0,-1.0,-1.0,402.125,1.66383,1381,3649123 +754,search,4570.57,2367.67,1555.22,0.958252,139.306,2.2067,9.18156,0.90736,0.11776,-1.0,-1.0,63.34,1.66466,1383,3649123 +755,delete,34.734,-1.0,-1.0,-1.0,-1.0,100.853,1.65854,1377,3621475 +756,search,4538.62,2355.55,1550.82,0.988006,133.716,3.79801,8.99181,0.90691,0.117519,-1.0,-1.0,60.599,1.65858,1380,3621475 +757,delete,37.511,-1.0,-1.0,-1.0,-1.0,109.797,1.64633,1372,3594479 +758,search,4541.37,2353.06,1541.35,0.977136,135.613,2.12489,8.51057,0.90675,0.117428,-1.0,-1.0,45.365,1.64662,1374,3594479 +759,delete,35.712,-1.0,-1.0,-1.0,-1.0,195.134,1.63305,1363,3569055 +760,search,4521.69,2354.61,1536.41,1.00348,132.752,2.14005,8.65962,0.90649,0.117891,-1.0,-1.0,30.33,1.63328,1364,3569055 +761,delete,52.884,-1.0,-1.0,-1.0,-1.0,113.431,1.62164,1355,3527896 +762,search,4457.12,2337.14,1494.3,0.984344,133.963,2.13178,8.54237,0.9058,0.1182,-1.0,-1.0,32.444,1.62169,1356,3527896 +763,delete,25.334,-1.0,-1.0,-1.0,-1.0,63.336,1.61659,1352,3509970 +764,search,4453.36,2329.93,1497.99,0.984101,131.573,2.17914,8.65347,0.9053,0.118781,-1.0,-1.0,18.952,1.61659,1352,3509970 +765,delete,528.504,-1.0,-1.0,-1.0,-1.0,1494.91,1.44401,1180,3187549 +766,search,4004.44,2445.18,1384.94,1.03991,122.55,2.0888,8.40654,0.90273,0.120385,-1.0,-1.0,207.735,1.44733,1205,3187549 +767,delete,506.207,-1.0,-1.0,-1.0,-1.0,1696.06,1.26088,1003,2822906 +768,search,3444.26,2536.94,1218.05,1.00733,110.852,2.18949,8.70168,0.89251,0.129839,-1.0,-1.0,269.421,1.26505,1032,2822906 +769,insert,17.612,-1.0,-1.0,-1.0,-1.0,18.041,1.26807,1032,2832899 +770,search,3505.46,2455.93,1213.77,1.03552,115.27,2.17112,9.40813,0.89385,0.128311,-1.0,-1.0,52.501,1.26838,1036,2832899 +771,insert,58.416,-1.0,-1.0,-1.0,-1.0,83.115,1.28185,1042,2863523 +772,search,3526.28,2459.32,1219.41,0.975331,114.389,2.16565,8.24167,0.89461,0.127618,-1.0,-1.0,30.144,1.28197,1043,2863523 +773,insert,111.976,-1.0,-1.0,-1.0,-1.0,149.212,1.30614,1059,2925169 +774,search,3592.07,2472.92,1249.54,1.03236,117.635,2.18723,9.92345,0.89599,0.126794,-1.0,-1.0,41.904,1.30614,1061,2925169 +775,insert,64.701,-1.0,-1.0,-1.0,-1.0,77.786,1.32189,1066,2961356 +776,search,3624.82,2487.52,1262.03,0.953143,119.279,2.18679,9.34526,0.89632,0.126877,-1.0,-1.0,41.228,1.32189,1068,2961356 +777,insert,63.519,-1.0,-1.0,-1.0,-1.0,86.73,1.33483,1074,2998678 +778,search,3668.15,2510.46,1279.59,0.964936,116.244,2.21624,8.3352,0.89797,0.125656,-1.0,-1.0,51.597,1.3351,1077,2998678 +779,insert,27.916,-1.0,-1.0,-1.0,-1.0,18.739,1.33949,1077,3011024 +780,search,3671.14,2511.22,1292.64,0.97732,117.373,2.17306,8.61488,0.89802,0.125914,-1.0,-1.0,20.665,1.33949,1077,3011024 +781,insert,14.892,-1.0,-1.0,-1.0,-1.0,43.439,1.34246,1079,3019515 +782,search,3616.02,2517.37,1227.37,1.03054,110.475,2.14348,9.65412,0.8981,0.125595,-1.0,-1.0,20.613,1.34246,1079,3019515 +783,insert,136.093,-1.0,-1.0,-1.0,-1.0,161.593,1.36702,1094,3082298 +784,search,3673.96,2538.59,1246.84,1.04347,110.722,2.17387,9.88538,0.89918,0.124243,-1.0,-1.0,48.762,1.36728,1097,3082298 +785,insert,62.323,-1.0,-1.0,-1.0,-1.0,117.481,1.38435,1105,3122090 +786,search,3694.12,2543.56,1248.12,1.08824,116.8,2.12064,10.8697,0.89982,0.123859,-1.0,-1.0,59.359,1.38435,1109,3122090 +787,insert,58.159,-1.0,-1.0,-1.0,-1.0,85.218,1.39554,1115,3140294 +788,search,3839.43,2542.41,1344.33,0.981757,127.619,2.27771,9.78827,0.90094,0.122791,-1.0,-1.0,42.494,1.39598,1118,3140294 +789,insert,15.939,-1.0,-1.0,-1.0,-1.0,25.139,1.39945,1119,3147819 +790,search,3826.81,2537.3,1350.6,0.933947,126.71,2.19263,8.85316,0.90049,0.123267,-1.0,-1.0,15.728,1.39945,1119,3147819 +791,insert,73.209,-1.0,-1.0,-1.0,-1.0,45.301,1.41151,1124,3180668 +792,search,3834.44,2550.96,1355.17,0.936811,124.63,2.2415,8.92197,0.90042,0.123442,-1.0,-1.0,15.744,1.41151,1124,3180668 +793,insert,2.563,-1.0,-1.0,-1.0,-1.0,13.519,1.41199,1124,3183235 +794,search,3837.39,2551.36,1355.82,0.917216,130.752,2.12023,10.3016,0.90051,0.123361,-1.0,-1.0,15.632,1.41199,1124,3183235 +795,insert,134.892,-1.0,-1.0,-1.0,-1.0,150.758,1.43847,1138,3242089 +796,search,3906.04,2575.38,1398.28,0.955863,122.703,2.20563,8.96474,0.9014,0.122944,-1.0,-1.0,36.679,1.43854,1140,3242089 +797,insert,8.161,-1.0,-1.0,-1.0,-1.0,23.755,1.43989,1141,3247192 +798,search,3928.78,2572.38,1395.88,0.958371,129.154,2.15228,8.65152,0.90203,0.12223,-1.0,-1.0,44.568,1.44016,1145,3247192 +799,insert,17.563,-1.0,-1.0,-1.0,-1.0,45.255,1.44411,1148,3254626 +800,search,3947.15,2556.49,1404.08,0.994113,120.737,2.10781,8.81798,0.90204,0.122409,-1.0,-1.0,15.695,1.44411,1148,3254626 +801,insert,46.355,-1.0,-1.0,-1.0,-1.0,61.149,1.45218,1153,3274953 +802,search,3947.87,2562.35,1405.49,0.934495,126.138,2.15328,9.01176,0.90183,0.122771,-1.0,-1.0,15.582,1.45218,1153,3274953 +803,insert,1571.69,-1.0,-1.0,-1.0,-1.0,1511.68,1.81391,1330,4032688 +804,search,4604.62,2804.67,1701.44,1.03278,152.817,2.11187,9.39099,0.9105,0.116725,-1.0,-1.0,595.308,1.81524,1400,4032688 +805,insert,28.241,-1.0,-1.0,-1.0,-1.0,17.128,1.82143,1400,4050220 +806,search,4814.69,2656.55,1739.78,0.997531,168.922,2.19636,8.59914,0.91107,0.116534,-1.0,-1.0,248.53,1.82235,1429,4050220 +807,insert,24.222,-1.0,-1.0,-1.0,-1.0,85.659,1.82991,1435,4067940 +808,search,4792.69,2592.49,1661.82,1.03612,153.012,2.23214,8.37958,0.91069,0.11653,-1.0,-1.0,45.406,1.83015,1438,4067940 +809,insert,48.298,-1.0,-1.0,-1.0,-1.0,73.882,1.84167,1445,4099369 +810,search,4873.95,2590.15,1720.29,1.01356,151.595,2.11195,9.19462,0.91106,0.11629,-1.0,-1.0,28.873,1.84167,1446,4099369 +811,insert,51.987,-1.0,-1.0,-1.0,-1.0,119.98,1.85319,1461,4129509 +812,search,4850.7,2584.02,1660.54,1.11221,146.611,2.63082,8.34537,0.9117,0.115432,-1.0,-1.0,45.771,1.85337,1464,4129509 +813,insert,80.452,-1.0,-1.0,-1.0,-1.0,120.901,1.86931,1480,4178669 +814,search,4958.24,2576.59,1732.68,1.03784,147.417,2.10567,9.00932,0.9128,0.113954,-1.0,-1.0,21.727,1.86931,1480,4178669 +815,insert,6.325,-1.0,-1.0,-1.0,-1.0,29.252,1.87079,1481,4180960 +816,search,5030.28,2574.87,1791.79,0.967974,154.665,2.13881,8.32997,0.9128,0.113954,-1.0,-1.0,21.843,1.87079,1481,4180960 +817,insert,119.982,-1.0,-1.0,-1.0,-1.0,189.561,1.89657,1501,4255359 +818,search,5101.15,2585.54,1808.81,0.977562,172.144,2.18547,8.59546,0.91374,0.113281,-1.0,-1.0,73.563,1.89731,1506,4255359 +819,insert,42.263,-1.0,-1.0,-1.0,-1.0,43.815,1.90324,1510,4272706 +820,search,5103.41,2579.96,1820.44,0.952022,162.435,2.0876,7.76473,0.9137,0.113434,-1.0,-1.0,20.792,1.90324,1510,4272706 +821,insert,25.012,-1.0,-1.0,-1.0,-1.0,50.386,1.91008,1513,4287851 +822,search,5122.38,2581.87,1823.96,0.946946,164.253,2.25072,7.53821,0.91356,0.113642,-1.0,-1.0,21.224,1.91008,1513,4287851 +823,insert,61.886,-1.0,-1.0,-1.0,-1.0,107.717,1.92645,1522,4322788 +824,search,5181.58,2589.54,1859.34,0.949637,168.795,2.11,8.36082,0.91368,0.113936,-1.0,-1.0,56.892,1.92691,1527,4322788 +825,insert,139.831,-1.0,-1.0,-1.0,-1.0,184.299,1.95914,1544,4396408 +826,search,5246.6,2588.67,1878.39,0.965653,164.65,4.81543,10.1274,0.91402,0.113636,-1.0,-1.0,66.323,1.95949,1549,4396408 +827,insert,35.802,-1.0,-1.0,-1.0,-1.0,46.572,1.96753,1552,4415721 +828,search,5233.55,2581.37,1858.53,1.00091,167.841,2.20301,8.20314,0.91366,0.114035,-1.0,-1.0,35.418,1.96798,1553,4415721 +829,insert,806.177,-1.0,-1.0,-1.0,-1.0,885.818,2.15704,1665,4832079 +830,search,5633.51,2653.41,2028.79,1.0014,183.066,2.19041,8.9726,0.91761,0.110602,-1.0,-1.0,342.398,2.16131,1703,4832079 +831,insert,50.291,-1.0,-1.0,-1.0,-1.0,91.489,2.17342,1712,4864525 +832,search,5644.9,2592.88,1945.91,1.10379,177.906,5.44506,9.71494,0.91786,0.110218,-1.0,-1.0,53.207,2.17399,1716,4864525 +833,insert,17.153,-1.0,-1.0,-1.0,-1.0,20.695,2.17703,1716,4874443 +834,search,5808.2,2592.67,2069.72,0.952381,181.668,2.10044,8.0333,0.91834,0.10994,-1.0,-1.0,35.94,2.17719,1718,4874443 +835,insert,110.174,-1.0,-1.0,-1.0,-1.0,178.357,2.2039,1739,4938267 +836,search,5728.54,2601.54,1958.63,1.08941,180.292,2.15451,12.0281,0.91846,0.109625,-1.0,-1.0,37.269,2.20425,1741,4938267 +837,insert,31.238,-1.0,-1.0,-1.0,-1.0,63.43,2.21092,1746,4961147 +838,search,5844.27,2603,2037.59,1.05866,184.211,2.56812,9.53002,0.91874,0.109448,-1.0,-1.0,21.453,2.21092,1746,4961147 +839,insert,116.026,-1.0,-1.0,-1.0,-1.0,187.125,2.2405,1767,5033740 +840,search,5961.82,2605.56,2108.22,1.01212,191.605,2.17005,8.40737,0.91984,0.108449,-1.0,-1.0,62.072,2.24091,1772,5033740 +841,insert,73.014,-1.0,-1.0,-1.0,-1.0,127.089,2.25956,1783,5078736 +842,search,5983.06,2601.45,2093.05,1.04934,183.37,2.14393,9.75288,0.92052,0.107805,-1.0,-1.0,43.668,2.25977,1785,5078736 +843,insert,694.797,-1.0,-1.0,-1.0,-1.0,838.052,2.43822,1896,5467376 +844,search,6423.41,2650.14,2282.98,1.02644,213.763,2.12684,9.76595,0.9234,0.105781,-1.0,-1.0,310.756,2.44091,1933,5467376 +845,insert,595.487,-1.0,-1.0,-1.0,-1.0,691.484,2.5979,2037,5815547 +846,search,6795.14,2621.44,2387.59,1.04159,215.752,2.49045,9.03916,0.92644,0.103448,-1.0,-1.0,241.643,2.59908,2063,5815547 +847,insert,9.235,-1.0,-1.0,-1.0,-1.0,33.24,2.60124,2064,5821782 +848,search,6900.05,2590.44,2433.21,1.05296,226.879,2.16568,10.4506,0.92696,0.103061,-1.0,-1.0,59.31,2.60134,2068,5821782 +849,insert,2.921,-1.0,-1.0,-1.0,-1.0,41.223,2.6019,2070,5825594 +850,search,6874.47,2584.7,2399,1.0589,221.044,2.78213,9.45366,0.92688,0.103147,-1.0,-1.0,27.306,2.6019,2070,5825594 +851,insert,15.187,-1.0,-1.0,-1.0,-1.0,53.268,2.60505,2074,5834880 +852,search,6984.49,2583.65,2464.8,0.990393,232.568,2.29277,7.97404,0.92702,0.102979,-1.0,-1.0,27.983,2.60505,2074,5834880 +853,insert,56.074,-1.0,-1.0,-1.0,-1.0,80.625,2.61632,2079,5860274 +854,search,6980.14,2588.05,2475.53,0.976324,227.597,2.15583,8.40663,0.92693,0.103108,-1.0,-1.0,27.473,2.61632,2079,5860274 +855,insert,11.832,-1.0,-1.0,-1.0,-1.0,34.254,2.61779,2081,5866064 +856,search,6741.63,2587.73,2280.86,1.12088,197.732,2.11537,9.56784,0.92717,0.102769,-1.0,-1.0,52.241,2.61815,2085,5866064 +857,insert,32.953,-1.0,-1.0,-1.0,-1.0,68.011,2.62414,2091,5884456 +858,search,7006.11,2582.69,2490.09,0.990908,222.217,2.10133,7.91699,0.92714,0.102807,-1.0,-1.0,38.102,2.62442,2092,5884456 +859,insert,56.681,-1.0,-1.0,-1.0,-1.0,65.766,2.63573,2097,5916786 +860,search,6910.03,2592.07,2379.14,1.05547,216.256,2.14157,9.98933,0.92738,0.102649,-1.0,-1.0,35.497,2.63574,2098,5916786 +861,insert,10.479,-1.0,-1.0,-1.0,-1.0,51.274,2.63729,2101,5923467 +862,search,6874.97,2589.77,2350.07,1.08012,215.127,2.44953,9.26134,0.92757,0.102579,-1.0,-1.0,27.245,2.63729,2101,5923467 +863,insert,118.781,-1.0,-1.0,-1.0,-1.0,176.594,2.66916,2118,5997844 +864,search,6879.33,2593.16,2335.47,1.1558,205.055,2.39275,9.03191,0.92637,0.104312,-1.0,-1.0,44.36,2.66932,2119,5997844 +865,insert,18.654,-1.0,-1.0,-1.0,-1.0,27.145,2.67305,2119,6009561 +866,search,6947.28,2595.67,2378.95,1.13225,214.625,2.13328,9.62793,0.92638,0.104308,-1.0,-1.0,30.433,2.67305,2119,6009561 +867,insert,70.41,-1.0,-1.0,-1.0,-1.0,125.743,2.68927,2129,6052876 +868,search,6927.54,2605.94,2336.62,1.1077,200.949,2.1015,9.26238,0.92688,0.104044,-1.0,-1.0,67.829,2.68978,2133,6052876 +869,insert,9.989,-1.0,-1.0,-1.0,-1.0,37.933,2.69176,2134,6059234 +870,search,6882.92,2600.06,2305.44,1.14373,198.106,2.08888,9.75529,0.92687,0.104041,-1.0,-1.0,43.584,2.69195,2135,6059234 +871,insert,69.024,-1.0,-1.0,-1.0,-1.0,111.232,2.70992,2143,6098225 +872,search,7210.42,2602.21,2578.84,1.01053,232.628,2.17582,8.4778,0.92702,0.103725,-1.0,-1.0,37.197,2.71,2144,6098225 +873,insert,65.179,-1.0,-1.0,-1.0,-1.0,87.025,2.72549,2150,6137308 +874,search,7252.95,2603.88,2588.88,0.999143,234.714,2.12785,7.95521,0.92719,0.103475,-1.0,-1.0,42.324,2.72569,2152,6137308 +875,insert,25.58,-1.0,-1.0,-1.0,-1.0,38.947,2.72992,2153,6154089 +876,search,7094.49,2605.78,2450.28,1.09012,227.882,2.10859,9.46428,0.92701,0.103597,-1.0,-1.0,28.987,2.72992,2153,6154089 +877,insert,6.158,-1.0,-1.0,-1.0,-1.0,26.886,2.73091,2153,6156061 +878,search,7120.75,2608.12,2474.17,1.10041,226.958,2.12908,9.2531,0.92709,0.10353,-1.0,-1.0,36.012,2.73095,2154,6156061 +879,insert,562.956,-1.0,-1.0,-1.0,-1.0,594.66,2.8621,2221,6446004 +880,search,7508.39,2631.64,2692.66,0.969374,241.273,2.0631,8.3864,0.92888,0.101857,-1.0,-1.0,196.059,2.86366,2245,6446004 +881,insert,844.309,-1.0,-1.0,-1.0,-1.0,968.21,3.10037,2384,6969764 +882,search,8034.49,2666.25,2905.51,1.00702,264.076,2.1424,8.09975,0.9321,0.0985104,-1.0,-1.0,365.227,3.10301,2430,6969764 +883,insert,643.589,-1.0,-1.0,-1.0,-1.0,865.165,3.30183,2573,7422501 +884,search,8611.83,2633.97,3071.48,0.969789,283.335,2.17227,8.15463,0.93487,0.0961859,-1.0,-1.0,312.509,3.30501,2618,7422501 +885,insert,13.991,-1.0,-1.0,-1.0,-1.0,51.27,3.30843,2622,7432053 +886,search,8768.17,2578.29,3103.99,0.982919,291.242,2.40385,8.23415,0.93513,0.0958773,-1.0,-1.0,46.6,3.30876,2625,7432053 +887,insert,547.31,-1.0,-1.0,-1.0,-1.0,617.78,3.46342,2715,7789886 +888,search,9017.43,2607.2,3184.98,1.0212,289.458,2.84615,9.38352,0.93664,0.0952044,-1.0,-1.0,242.089,3.46619,2750,7789886 +889,insert,616.641,-1.0,-1.0,-1.0,-1.0,813.239,3.65219,2875,8210883 +890,search,9497.97,2593.45,3311.29,1.02917,313.19,2.12109,9.51896,0.9385,0.0935871,-1.0,-1.0,305.161,3.65539,2920,8210883 +891,insert,47.956,-1.0,-1.0,-1.0,-1.0,91.073,3.6665,2929,8240504 +892,search,9575.71,2551.06,3295.83,1.03929,298.796,2.10904,11.667,0.93873,0.0934654,-1.0,-1.0,59.11,3.66677,2933,8240504 +893,insert,77.635,-1.0,-1.0,-1.0,-1.0,120.078,3.69017,2947,8299693 +894,search,9684.89,2553.59,3372.75,1.01418,299.739,2.10211,8.95255,0.93902,0.093178,-1.0,-1.0,42.807,3.69037,2948,8299693 +895,insert,67.473,-1.0,-1.0,-1.0,-1.0,112.215,3.70878,2962,8349126 +896,search,9734.52,2555.73,3347.45,1.0434,300.607,2.13023,9.60421,0.93941,0.0929208,-1.0,-1.0,76.784,3.70938,2966,8349126 +897,delete,113.982,-1.0,-1.0,-1.0,-1.0,503.336,3.67618,2941,8268842 +898,search,9507.04,2555.21,3204.76,1.08963,299.963,2.15244,12.4099,0.93908,0.092828,-1.0,-1.0,83.746,3.67695,2947,8268842 +899,delete,24.281,-1.0,-1.0,-1.0,-1.0,92.145,3.67338,2944,8250527 +900,search,9679.58,2548.24,3343.19,1.04889,309.666,2.15202,9.85786,0.93895,0.0930777,-1.0,-1.0,37.93,3.67339,2945,8250527 +901,delete,95.952,-1.0,-1.0,-1.0,-1.0,358.421,3.65439,2925,8185565 +902,search,9603.85,2540.15,3317.52,1.02964,304.412,2.10006,10.3516,0.93847,0.0932699,-1.0,-1.0,65.08,3.65487,2929,8185565 +903,delete,71.664,-1.0,-1.0,-1.0,-1.0,228.145,3.62931,2909,8126915 +904,search,9653.68,2533.28,3373.67,0.982307,316.391,2.16563,8.51769,0.93768,0.0936311,-1.0,-1.0,40.244,3.62931,2910,8126915 +905,delete,39.955,-1.0,-1.0,-1.0,-1.0,81.693,3.62675,2908,8098533 +906,search,9583.99,2524.85,3320.84,0.966789,301.78,2.08501,10.0696,0.93763,0.0936821,-1.0,-1.0,30.525,3.62675,2908,8098533 +907,delete,30.343,-1.0,-1.0,-1.0,-1.0,266.772,3.6154,2898,8074833 +908,search,9283.61,2525.8,3097.61,1.13641,281.817,2.15393,12.3518,0.93739,0.0939467,-1.0,-1.0,40.314,3.61562,2899,8074833 +909,delete,54.036,-1.0,-1.0,-1.0,-1.0,143.86,3.61022,2894,8035274 +910,search,9561.29,2517.18,3310.32,0.989511,306.135,2.16848,9.09616,0.93735,0.0938224,-1.0,-1.0,36.338,3.61022,2894,8035274 +911,delete,161.687,-1.0,-1.0,-1.0,-1.0,373.989,3.5899,2876,7957223 +912,search,9477.13,2502.58,3288.56,0.981954,306.028,2.14487,8.4529,0.93687,0.0940842,-1.0,-1.0,44.899,3.59014,2877,7957223 +913,delete,56.491,-1.0,-1.0,-1.0,-1.0,264.866,3.57219,2860,7917554 +914,search,9406.46,2503.38,3233.08,1.0304,294.75,2.10831,8.90828,0.93568,0.0948162,-1.0,-1.0,31.888,3.57219,2860,7917554 +915,delete,97.891,-1.0,-1.0,-1.0,-1.0,310.228,3.5507,2838,7861503 +916,search,9216.28,2503.48,3104.54,1.05182,286.941,2.15585,12.0368,0.93541,0.0952913,-1.0,-1.0,53.028,3.55098,2840,7861503 +917,delete,26.02,-1.0,-1.0,-1.0,-1.0,173.781,3.5444,2835,7844487 +918,search,9376.17,2499.05,3242.82,1.00922,316.851,2.1572,8.91296,0.93546,0.0951831,-1.0,-1.0,30.911,3.5444,2835,7844487 +919,delete,42.456,-1.0,-1.0,-1.0,-1.0,76.947,3.542,2832,7814993 +920,search,9348.09,2491.42,3234.13,0.980941,293.146,2.14237,8.63673,0.93542,0.0954277,-1.0,-1.0,29.223,3.542,2832,7814993 +921,delete,28.659,-1.0,-1.0,-1.0,-1.0,223.154,3.53304,2824,7793855 +922,search,9145.91,2490.67,3085.81,1.0453,280.872,2.79058,10.3801,0.9354,0.0955608,-1.0,-1.0,39.569,3.53329,2825,7793855 +923,delete,70.28,-1.0,-1.0,-1.0,-1.0,310.948,3.51627,2809,7736054 +924,search,9210.13,2482.78,3190.49,0.987862,271.355,2.11137,8.86392,0.93526,0.0954327,-1.0,-1.0,32.338,3.51627,2809,7736054 +925,delete,221.824,-1.0,-1.0,-1.0,-1.0,1077.12,3.44017,2732,7587942 +926,search,8945.69,2504.66,3029.5,1.03033,279.729,2.16343,9.4577,0.9339,0.0967681,-1.0,-1.0,196.563,3.44312,2752,7587942 +927,delete,27.877,-1.0,-1.0,-1.0,-1.0,75.24,3.43871,2749,7565670 +928,search,9062.44,2479.27,3134.52,0.973515,283.861,2.09302,8.62869,0.93383,0.097396,-1.0,-1.0,53.795,3.4388,2751,7565670 +929,delete,59.098,-1.0,-1.0,-1.0,-1.0,97.815,3.43471,2748,7529948 +930,search,9063.39,2467.75,3112.37,0.98447,305.364,2.15393,8.80166,0.93379,0.0974094,-1.0,-1.0,29.976,3.43471,2748,7529948 +931,delete,703.656,-1.0,-1.0,-1.0,-1.0,4820.39,3.17546,2433,7016700 +932,search,8172.31,2586.97,2901.53,0.969308,263.776,7.22249,8.65226,0.93141,0.0990332,-1.0,-1.0,664.817,3.18972,2525,7016700 +933,delete,26.011,-1.0,-1.0,-1.0,-1.0,193.808,3.17519,2514,6980979 +934,search,8294.9,2485.32,2850.41,1.00199,272.195,2.15272,9.32905,0.93262,0.098409,-1.0,-1.0,106.627,3.17591,2524,6980979 +935,delete,27.121,-1.0,-1.0,-1.0,-1.0,187.734,3.16332,2515,6954250 +936,search,8265.54,2474.91,2840.13,0.966953,269.199,2.16643,8.9057,0.93227,0.0986312,-1.0,-1.0,39.445,3.16345,2516,6954250 +937,delete,30.956,-1.0,-1.0,-1.0,-1.0,142.504,3.15392,2509,6924596 +938,search,8256.26,2470.97,2830.53,1.01086,256.603,2.13887,8.84571,0.93174,0.0990439,-1.0,-1.0,25.845,3.15392,2509,6924596 +939,delete,159.699,-1.0,-1.0,-1.0,-1.0,560.26,3.11735,2466,6784831 +940,search,8085.68,2457.08,2765.81,1.00675,257.547,2.17347,8.03399,0.93159,0.0996093,-1.0,-1.0,62.199,3.11772,2469,6784831 +941,delete,74.418,-1.0,-1.0,-1.0,-1.0,30.451,3.1155,2470,6745819 +942,search,8083.08,2431.45,2740.56,1.00385,253.336,2.15204,8.57742,0.93124,0.100536,-1.0,-1.0,50.373,3.1159,2472,6745819 +943,delete,8.334,-1.0,-1.0,-1.0,-1.0,25.93,3.1159,2472,6740944 +944,search,8133.49,2426.91,2771.55,0.971693,253.139,2.09462,8.76006,0.93115,0.100623,-1.0,-1.0,26.715,3.1159,2472,6740944 +945,delete,166.553,-1.0,-1.0,-1.0,-1.0,1136.39,3.04945,2404,6627202 +946,search,7858.65,2454.88,2675.75,0.977419,254.063,2.07366,10.0868,0.92983,0.10139,-1.0,-1.0,171.097,3.05153,2419,6627202 +947,delete,28.639,-1.0,-1.0,-1.0,-1.0,37.935,3.04836,2418,6607194 +948,search,7598.13,2431.87,2412.4,1.14952,225.157,3.56689,11.8697,0.9298,0.101671,-1.0,-1.0,101.912,3.04937,2427,6607194 +949,delete,64.914,-1.0,-1.0,-1.0,-1.0,301.032,3.02317,2406,6551065 +950,search,7725.28,2420.74,2573.1,1.04463,233.474,2.08324,9.52213,0.92929,0.102007,-1.0,-1.0,25.447,3.02317,2406,6551065 +951,delete,45.436,-1.0,-1.0,-1.0,-1.0,115.312,3.00211,2393,6506798 +952,search,7582.82,2420.83,2468.98,1.08379,213.057,2.08363,8.71755,0.92985,0.101673,-1.0,-1.0,35.404,3.00235,2394,6506798 +953,delete,67.839,-1.0,-1.0,-1.0,-1.0,190.402,2.9909,2387,6459301 +954,search,7479.5,2410.19,2386.58,1.15029,201.541,2.10645,8.4605,0.92999,0.10153,-1.0,-1.0,23.995,2.9909,2387,6459301 +955,delete,21.532,-1.0,-1.0,-1.0,-1.0,49.752,2.98324,2383,6440069 +956,search,7773.18,2408.74,2645.14,0.97434,229.746,2.09908,8.82179,0.9302,0.101074,-1.0,-1.0,24.279,2.98324,2383,6440069 +957,delete,455.421,-1.0,-1.0,-1.0,-1.0,2379.63,2.81542,2215,6132470 +958,search,7315.83,2465.35,2511.79,0.980667,223.734,2.04892,7.88782,0.92721,0.103445,-1.0,-1.0,215.133,2.81908,2238,6132470 +959,delete,58.437,-1.0,-1.0,-1.0,-1.0,139.178,2.80382,2228,6086241 +960,search,7293.72,2427.36,2444.96,1.02149,222.584,2.13002,8.78306,0.92654,0.104136,-1.0,-1.0,109.898,2.80477,2234,6086241 +961,delete,36.964,-1.0,-1.0,-1.0,-1.0,65.429,2.80193,2232,6064734 +962,search,7317.82,2413.39,2475.98,1.00098,230.055,2.1376,8.94282,0.92619,0.104623,-1.0,-1.0,54.396,2.80229,2233,6064734 +963,delete,177.392,-1.0,-1.0,-1.0,-1.0,886.726,2.74451,2167,5967543 +964,search,7187.15,2457.87,2460.03,0.981298,233.158,3.47587,8.92146,0.92645,0.104291,-1.0,-1.0,193.197,2.74719,2187,5967543 +965,delete,81.673,-1.0,-1.0,-1.0,-1.0,397.307,2.72014,2159,5906381 +966,search,6880.3,2427.53,2241.55,1.08394,201.272,2.13477,8.85683,0.92514,0.105538,-1.0,-1.0,94.673,2.72106,2168,5906381 +967,delete,71.844,-1.0,-1.0,-1.0,-1.0,310.222,2.6992,2151,5851849 +968,search,6914.76,2406.64,2276.86,1.03926,199.299,2.13339,8.60781,0.92445,0.105885,-1.0,-1.0,51.366,2.69963,2152,5851849 +969,delete,85.998,-1.0,-1.0,-1.0,-1.0,282.66,2.66998,2130,5783023 +970,search,6800.53,2404.11,2213.46,1.09707,201.807,2.14962,10.0333,0.92329,0.10657,-1.0,-1.0,44.842,2.67009,2131,5783023 +971,delete,403.349,-1.0,-1.0,-1.0,-1.0,1901.7,2.53246,1986,5496517 +972,search,6574.36,2446.67,2248.81,0.970083,215.045,2.44927,8.88685,0.92089,0.108505,-1.0,-1.0,299.562,2.53759,2018,5496517 +973,delete,326.769,-1.0,-1.0,-1.0,-1.0,1617.37,2.41478,1893,5237981 +974,search,6254.95,2437.55,2143.61,0.991296,184.823,2.07679,9.30479,0.91968,0.10864,-1.0,-1.0,295.929,2.42015,1925,5237981 +975,delete,184.472,-1.0,-1.0,-1.0,-1.0,756.521,2.34675,1851,5099794 +976,search,5953.19,2424.84,1945.29,1.06609,169.512,2.07543,10.3646,0.91898,0.110054,-1.0,-1.0,230.727,2.34899,1883,5099794 +977,delete,64.912,-1.0,-1.0,-1.0,-1.0,263.363,2.32166,1863,5032210 +978,search,6098.84,2356.09,2038.98,0.984188,193.439,2.17381,8.81301,0.91723,0.111182,-1.0,-1.0,69.252,2.32209,1869,5032210 +979,delete,14.658,-1.0,-1.0,-1.0,-1.0,50.701,2.31822,1866,5020211 +980,search,6089.39,2343.89,2043.7,1.03479,178.499,2.14918,8.31699,0.91694,0.111491,-1.0,-1.0,32.279,2.31822,1867,5020211 +981,delete,159.117,-1.0,-1.0,-1.0,-1.0,507.235,2.25942,1824,4902291 +982,search,5790.67,2338.69,1832.81,1.05637,170.422,2.13178,11.3395,0.91516,0.112856,-1.0,-1.0,81.993,2.26055,1829,4902291 +983,delete,41.458,-1.0,-1.0,-1.0,-1.0,73.944,2.25424,1826,4872577 +984,search,5970.58,2320.68,1987.08,0.97459,168.3,2.12399,9.50216,0.91518,0.113043,-1.0,-1.0,46.395,2.25453,1827,4872577 +985,delete,62.02,-1.0,-1.0,-1.0,-1.0,120.76,2.24582,1820,4836730 +986,search,5930.56,2306.06,1960.97,0.967085,182.285,2.15022,9.04172,0.91523,0.112917,-1.0,-1.0,28.463,2.24582,1820,4836730 +987,delete,72.16,-1.0,-1.0,-1.0,-1.0,97.685,2.23808,1814,4797164 +988,search,5881.55,2287.61,1933.59,0.967159,171.008,2.99881,9.20977,0.91478,0.113479,-1.0,-1.0,35.984,2.2381,1815,4797164 +989,delete,28.471,-1.0,-1.0,-1.0,-1.0,25.566,2.23648,1815,4784789 +990,search,5915.75,2277.65,1940.05,0.983346,187.87,2.17224,10.1118,0.9147,0.11361,-1.0,-1.0,26.468,2.23648,1815,4784789 +991,delete,108.447,-1.0,-1.0,-1.0,-1.0,486.794,2.20023,1788,4705420 +992,search,5847.56,2299.62,1928.79,0.982741,180.378,2.18204,9.63207,0.91618,0.112638,-1.0,-1.0,167.041,2.20167,1800,4705420 +993,delete,122.605,-1.0,-1.0,-1.0,-1.0,331.787,2.16464,1776,4621807 +994,search,5744.71,2262.77,1883.18,0.962904,176.23,2.16856,8.6393,0.91625,0.111981,-1.0,-1.0,132.133,2.16523,1787,4621807 +995,delete,99.108,-1.0,-1.0,-1.0,-1.0,458.878,2.12694,1754,4555849 +996,search,5678.34,2254.08,1855.43,0.933782,169.061,2.16634,9.59748,0.91567,0.112207,-1.0,-1.0,54.848,2.12736,1757,4555849 +997,delete,41.391,-1.0,-1.0,-1.0,-1.0,201.322,2.11429,1747,4526975 +998,search,5660.76,2253.91,1860.81,0.978483,159.036,2.1236,10.0042,0.9155,0.112424,-1.0,-1.0,37.132,2.11431,1748,4526975 +999,delete,164.186,-1.0,-1.0,-1.0,-1.0,679.749,2.05021,1696,4408448 +1000,search,5479.82,2256.2,1792.1,0.985374,164.435,2.16198,9.03923,0.91456,0.113243,-1.0,-1.0,82.35,2.05093,1702,4408448 +1001,delete,165.494,-1.0,-1.0,-1.0,-1.0,779.022,1.98935,1642,4303257 +1002,search,5329.91,2272.21,1754.29,0.947696,160.095,2.1983,8.71151,0.9128,0.113822,-1.0,-1.0,173.27,1.99162,1655,4303257 +1003,delete,47.434,-1.0,-1.0,-1.0,-1.0,190.488,1.97219,1640,4259551 +1004,search,5308.62,2257.24,1737.46,0.982959,163.518,2.17215,9.23829,0.91282,0.113775,-1.0,-1.0,45.099,1.97242,1642,4259551 +1005,delete,23.624,-1.0,-1.0,-1.0,-1.0,85.329,1.9653,1635,4241434 +1006,search,5288.57,2254.71,1738.32,0.953329,152.811,2.08458,8.86623,0.91218,0.114099,-1.0,-1.0,43.926,1.96577,1637,4241434 +1007,delete,254.472,-1.0,-1.0,-1.0,-1.0,1160.66,1.87084,1557,4052722 +1008,search,5041,2267.41,1667.52,0.999924,143.141,2.12399,8.91067,0.90908,0.116165,-1.0,-1.0,175.333,1.873,1569,4052722 +1009,delete,439.79,-1.0,-1.0,-1.0,-1.0,1453.93,1.71546,1430,3738432 +1010,search,4670.73,2293.11,1541.36,0.961886,144.437,4.18394,9.1892,0.90605,0.117974,-1.0,-1.0,285.349,1.71884,1456,3738432 +1011,delete,519.349,-1.0,-1.0,-1.0,-1.0,1959.24,1.52775,1250,3372539 +1012,search,4169.14,2408.15,1421.37,0.989617,125.784,2.19794,8.71775,0.90373,0.119678,-1.0,-1.0,296.014,1.53217,1282,3372539 +1013,delete,11.018,-1.0,-1.0,-1.0,-1.0,39.82,1.52883,1279,3361432 +1014,search,4222.51,2325,1409.23,0.987095,135.221,2.16512,8.92302,0.90359,0.118927,-1.0,-1.0,81.006,1.52939,1287,3361432 +1015,delete,380.022,-1.0,-1.0,-1.0,-1.0,1367.93,1.39475,1154,3091692 +1016,search,3886.22,2383.05,1313.91,0.982664,128.47,2.1619,9.61531,0.89805,0.122684,-1.0,-1.0,269.932,1.39925,1180,3091692 +1017,delete,456.549,-1.0,-1.0,-1.0,-1.0,1735.43,1.2454,1023,2775418 +1018,search,3485.69,2453.53,1209.48,0.958636,108.646,2.0751,8.59573,0.89524,0.125042,-1.0,-1.0,326.348,1.24908,1052,2775418 +1019,delete,23.52,-1.0,-1.0,-1.0,-1.0,75.283,1.24173,1047,2754073 +1020,search,3537.19,2380.4,1207.81,0.989858,106.666,2.1191,9.29027,0.89607,0.123999,-1.0,-1.0,79.645,1.24197,1052,2754073 +1021,delete,160.346,-1.0,-1.0,-1.0,-1.0,420.006,1.19763,1012,2638917 +1022,search,3383.68,2353.68,1154.58,0.927435,96.4403,2.10822,8.76759,0.89366,0.125958,-1.0,-1.0,82.79,1.19839,1017,2638917 +1023,delete,129.102,-1.0,-1.0,-1.0,-1.0,378.463,1.15802,974,2556494 +1024,search,3252.65,2364.87,1095,0.97622,100.706,2.15354,8.49478,0.89172,0.12808,-1.0,-1.0,67.484,1.15874,979,2556494 +1025,insert,70.982,-1.0,-1.0,-1.0,-1.0,49.379,1.17257,982,2594934 +1026,search,3307.41,2381.77,1139.05,0.948358,100.244,2.1716,8.87987,0.89262,0.126615,-1.0,-1.0,26.616,1.17262,983,2594934 +1027,insert,357.542,-1.0,-1.0,-1.0,-1.0,441.381,1.25613,1024,2802105 +1028,search,3460.59,2449.18,1213.18,1.01213,106.66,2.15436,8.12585,0.89324,0.126664,-1.0,-1.0,176.598,1.25642,1037,2802105 +1029,insert,748.03,-1.0,-1.0,-1.0,-1.0,565.535,1.43043,1105,3203975 +1030,search,3756.45,2688.28,1309.92,1.09038,118.153,3.16189,10.8905,0.89985,0.122289,-1.0,-1.0,167.845,1.43127,1123,3203975 +1031,insert,1051.4,-1.0,-1.0,-1.0,-1.0,1006,1.71754,1208,3830566 +1032,search,4311.63,2906.95,1641.8,1.00407,146.529,2.18995,9.26587,0.90486,0.119863,-1.0,-1.0,566.958,1.72141,1245,3830566 +1033,insert,757.677,-1.0,-1.0,-1.0,-1.0,960.11,1.91434,1361,4252669 +1034,search,4797.43,2845.95,1798.01,0.973044,156.654,2.45099,8.77997,0.91018,0.116006,-1.0,-1.0,425.791,1.91769,1408,4252669 +1035,insert,385.67,-1.0,-1.0,-1.0,-1.0,515.842,2.03318,1464,4512107 +1036,search,5092.35,2759.78,1873.34,0.987862,171.515,2.17578,9.91988,0.91318,0.114569,-1.0,-1.0,337.894,2.03559,1502,4512107 +1037,insert,20.039,-1.0,-1.0,-1.0,-1.0,50.267,2.04066,1506,4525815 +1038,search,5108.37,2688.8,1833.35,1.02038,166.922,2.15361,10.1935,0.91387,0.114067,-1.0,-1.0,136.401,2.04122,1519,4525815 +1039,insert,120.076,-1.0,-1.0,-1.0,-1.0,197.199,2.07218,1546,4599215 +1040,search,5137.48,2668.39,1795.76,1.10545,159.668,2.13542,8.99564,0.91484,0.113772,-1.0,-1.0,91.346,2.07264,1553,4599215 +1041,insert,11.844,-1.0,-1.0,-1.0,-1.0,49.736,2.07679,1556,4609851 +1042,search,5169.23,2657.31,1793.92,1.10066,161.525,2.55066,8.93456,0.91544,0.113261,-1.0,-1.0,36.144,2.07685,1558,4609851 +1043,insert,26.006,-1.0,-1.0,-1.0,-1.0,59.988,2.08127,1563,4627411 +1044,search,5288.68,2653.14,1876.22,1.03623,171.743,2.18378,9.80853,0.91564,0.113293,-1.0,-1.0,22.324,2.08127,1563,4627411 +1045,insert,75.188,-1.0,-1.0,-1.0,-1.0,115.804,2.09567,1576,4670607 +1046,search,5183.6,2654.34,1767.34,1.13296,152.314,2.47736,8.42621,0.91577,0.113191,-1.0,-1.0,28.341,2.09568,1577,4670607 +1047,insert,5.927,-1.0,-1.0,-1.0,-1.0,45.952,2.09695,1580,4675386 +1048,search,5408.94,2649.29,1947.18,0.951148,184.179,2.17995,9.79801,0.91598,0.112965,-1.0,-1.0,21.724,2.09695,1580,4675386 +1049,insert,22.42,-1.0,-1.0,-1.0,-1.0,42.099,2.10226,1582,4689998 +1050,search,5317.58,2656.05,1865.31,1.03289,170.949,2.12752,9.01948,0.9159,0.113006,-1.0,-1.0,21.048,2.10226,1582,4689998 +1051,insert,172.223,-1.0,-1.0,-1.0,-1.0,242.717,2.13989,1611,4783971 +1052,search,5486.64,2664.47,1974.69,0.992819,187.583,2.17076,9.37321,0.91606,0.113238,-1.0,-1.0,30.909,2.14014,1612,4783971 +1053,insert,84.685,-1.0,-1.0,-1.0,-1.0,106.621,2.15864,1624,4826219 +1054,search,5352.63,2666.93,1837.88,1.08908,162.512,2.15898,8.87809,0.91668,0.113034,-1.0,-1.0,30.262,2.15868,1625,4826219 +1055,insert,61.496,-1.0,-1.0,-1.0,-1.0,74.949,2.17052,1631,4862355 +1056,search,5577.97,2677.96,2025.13,0.957979,189.307,2.18807,8.88059,0.91681,0.112868,-1.0,-1.0,39.329,2.17075,1633,4862355 +1057,insert,13.048,-1.0,-1.0,-1.0,-1.0,35.394,2.17339,1635,4869564 +1058,search,5521.91,2676.96,1974.6,1.01911,180.596,2.23117,8.92504,0.91718,0.112731,-1.0,-1.0,28.907,2.17348,1636,4869564 +1059,insert,54.879,-1.0,-1.0,-1.0,-1.0,124.157,2.18546,1648,4898570 +1060,search,5606.73,2674.51,2020.95,1.03519,184.316,2.1591,9.48229,0.91756,0.112769,-1.0,-1.0,51.519,2.18578,1651,4898570 +1061,insert,18.545,-1.0,-1.0,-1.0,-1.0,34.963,2.1897,1653,4907501 +1062,search,5599.73,2675.1,2012.29,1.0047,188.233,2.16606,9.13353,0.91757,0.112748,-1.0,-1.0,21.675,2.1897,1653,4907501 +1063,insert,15.611,-1.0,-1.0,-1.0,-1.0,75.316,2.19396,1658,4916386 +1064,search,5536.24,2670.83,1944.22,1.04899,173.546,2.23326,7.87974,0.91776,0.112591,-1.0,-1.0,21.06,2.19396,1658,4916386 +1065,insert,524.305,-1.0,-1.0,-1.0,-1.0,624.48,2.31571,1738,5194839 +1066,search,5926.44,2691.32,2136.94,1.05362,199.14,2.11876,9.03377,0.91942,0.111235,-1.0,-1.0,156.618,2.31717,1757,5194839 +1067,insert,11.048,-1.0,-1.0,-1.0,-1.0,35.164,2.31943,1759,5200182 +1068,search,5890.67,2658.86,2086.66,1.05261,186.973,2.11988,8.41673,0.91961,0.110946,-1.0,-1.0,21.648,2.31943,1759,5200182 +1069,insert,65.208,-1.0,-1.0,-1.0,-1.0,97.746,2.33378,1775,5230883 +1070,search,6024.66,2642.75,2153.7,0.991604,199.785,2.21342,8.38735,0.92029,0.110243,-1.0,-1.0,32.198,2.33386,1776,5230883 +1071,insert,37.407,-1.0,-1.0,-1.0,-1.0,59.763,2.34337,1780,5255659 +1072,search,5945.9,2645.97,2070.46,1.09011,185.298,2.1323,8.90863,0.92057,0.11024,-1.0,-1.0,61.533,2.34384,1783,5255659 +1073,insert,61.363,-1.0,-1.0,-1.0,-1.0,65.795,2.35649,1788,5281693 +1074,search,6091.82,2649.04,2186.74,0.967611,212.116,2.29063,8.0776,0.9209,0.109909,-1.0,-1.0,45.466,2.35674,1790,5281693 +1075,insert,20.409,-1.0,-1.0,-1.0,-1.0,60.451,2.35949,1796,5290081 +1076,search,5977.35,2639.48,2090.48,1.06928,186.611,2.23902,8.98065,0.92123,0.109677,-1.0,-1.0,36.635,2.35972,1797,5290081 +1077,insert,46.099,-1.0,-1.0,-1.0,-1.0,54.253,2.37068,1800,5316166 +1078,search,6129.51,2648.09,2211.84,1.00017,199.074,2.12705,9.06837,0.92163,0.109206,-1.0,-1.0,57.938,2.37087,1804,5316166 +1079,insert,41.225,-1.0,-1.0,-1.0,-1.0,78.868,2.37819,1813,5335531 +1080,search,6136.34,2637.81,2214.38,0.971636,193.812,2.08289,9.02444,0.92135,0.109476,-1.0,-1.0,47.63,2.37839,1816,5335531 +1081,insert,674.299,-1.0,-1.0,-1.0,-1.0,719.305,2.53318,1907,5678781 +1082,search,6501.22,2674.91,2341.85,0.997725,223.092,2.19952,9.62032,0.92321,0.107267,-1.0,-1.0,228.032,2.53591,1936,5678781 +1083,insert,1.024,-1.0,-1.0,-1.0,-1.0,22.801,2.53599,1936,5679848 +1084,search,6495.39,2627.57,2298.21,1.0401,205.763,2.19417,9.09606,0.92299,0.107495,-1.0,-1.0,44.03,2.5361,1938,5679848 +1085,insert,39.544,-1.0,-1.0,-1.0,-1.0,77.429,2.54541,1945,5702205 +1086,search,6420.8,2630.14,2226.77,1.09099,200.631,2.12346,8.32705,0.92328,0.107108,-1.0,-1.0,31.972,2.54554,1946,5702205 +1087,insert,23.967,-1.0,-1.0,-1.0,-1.0,48.99,2.55021,1949,5715514 +1088,search,6527.58,2634.74,2308.09,1.05041,211.425,2.15132,9.28873,0.92348,0.106943,-1.0,-1.0,36.268,2.55046,1950,5715514 +1089,insert,770.695,-1.0,-1.0,-1.0,-1.0,879.72,2.72597,2078,6103499 +1090,search,7018.17,2669.29,2522.93,0.951755,234.513,2.18788,8.70995,0.92616,0.105068,-1.0,-1.0,161.845,2.72708,2097,6103499 +1091,insert,76.844,-1.0,-1.0,-1.0,-1.0,159.16,2.74858,2120,6152505 +1092,search,7137.62,2636.87,2553.38,0.984325,234.169,2.15808,9.1544,0.92678,0.104682,-1.0,-1.0,41.66,2.74871,2122,6152505 +1093,insert,25.096,-1.0,-1.0,-1.0,-1.0,34.059,2.75573,2123,6171104 +1094,search,7074.45,2633.72,2502.48,1.02516,223.272,2.17948,8.00192,0.92665,0.104647,-1.0,-1.0,27.988,2.75573,2123,6171104 +1095,insert,595.092,-1.0,-1.0,-1.0,-1.0,788.238,2.92678,2231,6557850 +1096,search,7457.53,2675.24,2621.73,1.08888,234.495,2.54726,8.98933,0.92863,0.102998,-1.0,-1.0,302.12,2.93019,2270,6557850 +1097,insert,24.743,-1.0,-1.0,-1.0,-1.0,83.221,2.93761,2277,6579289 +1098,search,7312.1,2619,2460.63,1.16866,210.406,2.10031,8.91564,0.92903,0.102764,-1.0,-1.0,104.75,2.93859,2287,6579289 +1099,insert,21.799,-1.0,-1.0,-1.0,-1.0,87.441,2.94442,2296,6591442 +1100,search,7373.04,2597.74,2452.6,1.18831,206.144,2.11862,9.67549,0.92897,0.102949,-1.0,-1.0,62.081,2.94486,2299,6591442 +1101,insert,71.259,-1.0,-1.0,-1.0,-1.0,199.04,2.96468,2323,6633739 +1102,search,7629.97,2585.27,2623.58,1.08019,234.171,2.15826,9.6027,0.92969,0.102378,-1.0,-1.0,50.081,2.96469,2325,6633739 +1103,insert,151.046,-1.0,-1.0,-1.0,-1.0,254.646,3.0053,2362,6724357 +1104,search,7824.06,2583.56,2740.2,1.00107,251.866,2.16299,8.68735,0.93079,0.101431,-1.0,-1.0,53.332,3.0053,2367,6724357 +1105,insert,5.322,-1.0,-1.0,-1.0,-1.0,31.498,3.00625,2368,6727059 +1106,search,7799.3,2573.74,2707.38,1.03761,244.067,2.13891,9.18781,0.9307,0.10145,-1.0,-1.0,25.154,3.00625,2368,6727059 +1107,insert,374.835,-1.0,-1.0,-1.0,-1.0,453.206,3.10227,2433,6950869 +1108,search,8061.72,2593.23,2829.72,1.02484,260.216,2.11517,8.91722,0.93158,0.100629,-1.0,-1.0,73.586,3.10254,2439,6950869 +1109,insert,9.047,-1.0,-1.0,-1.0,-1.0,24.166,3.10413,2439,6958173 +1110,search,8035.8,2591.08,2789.42,1.03697,251.319,2.17687,8.87623,0.93166,0.100628,-1.0,-1.0,26.138,3.10413,2439,6958173 +1111,insert,74.307,-1.0,-1.0,-1.0,-1.0,141.91,3.11847,2458,6995273 +1112,search,8109.11,2587.31,2829.46,1.05476,254.93,2.31832,8.8224,0.93181,0.100158,-1.0,-1.0,57.454,3.11881,2462,6995273 +1113,insert,81.207,-1.0,-1.0,-1.0,-1.0,110.267,3.13875,2475,7047862 +1114,search,8227.49,2585.32,2903.33,0.98516,264.455,2.1635,8.72425,0.93215,0.100128,-1.0,-1.0,75.467,3.13917,2480,7047862 +1115,insert,108.876,-1.0,-1.0,-1.0,-1.0,157.615,3.16479,2498,7110727 +1116,search,8265.84,2588.63,2905.43,1.01667,267.892,2.1452,9.31463,0.93261,0.099842,-1.0,-1.0,48.156,3.16493,2499,7110727 +1117,insert,31.147,-1.0,-1.0,-1.0,-1.0,47.292,3.17173,2502,7125591 +1118,search,8348.05,2591.86,2959.33,0.972743,274.021,2.26774,9.44944,0.93263,0.0996389,-1.0,-1.0,39.234,3.17191,2503,7125591 +1119,insert,21.109,-1.0,-1.0,-1.0,-1.0,25.36,3.1762,2503,7134442 +1120,search,8322.62,2595.7,2920.23,0.996233,270.302,2.15025,8.38976,0.9327,0.099598,-1.0,-1.0,28.101,3.1762,2503,7134442 +1121,insert,48.96,-1.0,-1.0,-1.0,-1.0,84.413,3.18699,2509,7162109 +1122,search,8309.44,2598.74,2906.81,1.02333,265.355,2.15523,8.75217,0.93313,0.099248,-1.0,-1.0,47.748,3.18722,2512,7162109 +1123,insert,33.149,-1.0,-1.0,-1.0,-1.0,58.422,3.19383,2516,7179509 +1124,search,8257.33,2594.43,2855.83,1.06318,256.102,2.12271,9.14633,0.93323,0.0994766,-1.0,-1.0,27.001,3.19383,2516,7179509 +1125,insert,12.134,-1.0,-1.0,-1.0,-1.0,35.894,3.19531,2517,7186372 +1126,search,8384.15,2595.5,2973.25,1.00888,274.72,2.15303,8.77167,0.93317,0.0995134,-1.0,-1.0,27.106,3.19531,2517,7186372 +1127,insert,81.164,-1.0,-1.0,-1.0,-1.0,120.974,3.21424,2527,7231450 +1128,search,8449.17,2602.29,2993.9,1.02349,275.465,2.41981,8.68664,0.93341,0.0992027,-1.0,-1.0,50.695,3.21431,2530,7231450 +1129,insert,24.325,-1.0,-1.0,-1.0,-1.0,50.464,3.2181,2533,7243215 +1130,search,8428.27,2599.81,2983.01,1.02412,273.939,2.14069,8.19819,0.93322,0.0993687,-1.0,-1.0,26.493,3.2181,2533,7243215 +1131,insert,67.543,-1.0,-1.0,-1.0,-1.0,115.404,3.22947,2543,7276107 +1132,search,8479.75,2599.53,3006.24,1.02199,273.602,2.66186,8.01478,0.93364,0.0989482,-1.0,-1.0,50.033,3.22975,2546,7276107 +1133,insert,30.026,-1.0,-1.0,-1.0,-1.0,86.305,3.23697,2556,7292577 +1134,search,8491.8,2590.05,2995.22,1.01039,272.615,2.13527,8.43897,0.93345,0.099196,-1.0,-1.0,40.685,3.23706,2557,7292577 +1135,insert,15.87,-1.0,-1.0,-1.0,-1.0,44.669,3.24022,2559,7299867 +1136,search,8529.86,2589.51,3007.32,1.00594,278.653,2.48836,8.70124,0.93346,0.099183,-1.0,-1.0,29.896,3.24022,2559,7299867 +1137,insert,56.251,-1.0,-1.0,-1.0,-1.0,80.555,3.2504,2564,7323342 +1138,search,8592.42,2593.08,3038.9,0.984682,286.428,2.18722,8.53579,0.93354,0.0991463,-1.0,-1.0,48.088,3.25084,2566,7323342 +1139,insert,4.8,-1.0,-1.0,-1.0,-1.0,37.439,3.25172,2567,7325844 +1140,search,8616.55,2590.15,3039.69,1.00264,287.025,2.15103,8.82263,0.93354,0.0991866,-1.0,-1.0,46.703,3.25193,2569,7325844 +1141,insert,423.832,-1.0,-1.0,-1.0,-1.0,426.05,3.34547,2617,7540761 +1142,search,8778.75,2613.08,3120.94,1.01143,297.671,2.18466,8.55391,0.93396,0.0991054,-1.0,-1.0,138.292,3.34652,2631,7540761 +1143,insert,36.093,-1.0,-1.0,-1.0,-1.0,38.842,3.35341,2633,7561926 +1144,search,8788.22,2602.1,3121.4,0.982615,287.378,2.15802,8.15982,0.93393,0.0992191,-1.0,-1.0,37.27,3.35353,2634,7561926 +1145,insert,19.02,-1.0,-1.0,-1.0,-1.0,56.644,3.35803,2638,7571861 +1146,search,8807.89,2601.59,3122.14,0.98747,289.121,2.31683,9.95924,0.93405,0.0991074,-1.0,-1.0,27.304,3.35803,2638,7571861 +1147,insert,39.269,-1.0,-1.0,-1.0,-1.0,66.198,3.36543,2643,7590881 +1148,search,8795.11,2604.76,3110.14,1.02546,283.791,2.76206,8.36969,0.93432,0.0990081,-1.0,-1.0,47.576,3.36584,2646,7590881 +1149,insert,9.048,-1.0,-1.0,-1.0,-1.0,30.329,3.36792,2647,7595507 +1150,search,8838.3,2601.16,3123.82,1.02953,283.12,2.1243,8.21915,0.93439,0.0988965,-1.0,-1.0,53.458,3.36809,2649,7595507 +1151,insert,10.664,-1.0,-1.0,-1.0,-1.0,34.696,3.3701,2650,7601664 +1152,search,8832.41,2600.04,3131.21,0.970351,286.02,2.18963,8.21748,0.9343,0.098989,-1.0,-1.0,30.235,3.3701,2650,7601664 +1153,delete,68.866,-1.0,-1.0,-1.0,-1.0,204.117,3.36002,2643,7566707 +1154,search,8850.05,2597.13,3136.14,0.98935,298.083,2.15297,9.78273,0.93438,0.0987966,-1.0,-1.0,56.484,3.36028,2644,7566707 +1155,delete,236.348,-1.0,-1.0,-1.0,-1.0,1083.99,3.29543,2591,7396192 +1156,search,8680.54,2592.99,3080.4,0.962204,288.968,2.18683,8.93514,0.93412,0.098891,-1.0,-1.0,118.133,3.29736,2599,7396192 +1157,delete,418.416,-1.0,-1.0,-1.0,-1.0,2002.67,3.17507,2469,7079041 +1158,search,8303.25,2574.97,2903.55,0.966921,276.495,2.60265,9.10669,0.93211,0.100272,-1.0,-1.0,252.003,3.17828,2498,7079041 +1159,delete,536.547,-1.0,-1.0,-1.0,-1.0,1484.84,2.97457,2380,6597115 +1160,search,7774.59,2492.97,2624.93,1.07038,240.469,2.26569,8.47282,0.92999,0.100221,-1.0,-1.0,187.36,2.97698,2397,6597115 +1161,delete,337.732,-1.0,-1.0,-1.0,-1.0,2166.29,2.84818,2258,6308902 +1162,search,7520.77,2508.79,2608.03,0.995052,245.47,2.18565,8.6061,0.92864,0.101373,-1.0,-1.0,335.975,2.85287,2295,6308902 +1163,delete,136.688,-1.0,-1.0,-1.0,-1.0,817.633,2.78895,2243,6164514 +1164,search,7320.98,2476.86,2481.19,1.03219,225.982,2.14087,9.42489,0.92886,0.100853,-1.0,-1.0,128.804,2.79054,2254,6164514 +1165,delete,44.036,-1.0,-1.0,-1.0,-1.0,227.807,2.77722,2243,6133412 +1166,search,7386.5,2464.41,2534.17,0.980176,235.754,2.15865,8.63389,0.92845,0.1016,-1.0,-1.0,50.829,2.77729,2244,6133412 +1167,delete,118.686,-1.0,-1.0,-1.0,-1.0,276.188,2.76201,2230,6057218 +1168,search,7345.74,2442.93,2517.31,0.989311,235.722,2.16717,9.31349,0.92803,0.101511,-1.0,-1.0,66.616,2.76242,2233,6057218 +1169,delete,31.984,-1.0,-1.0,-1.0,-1.0,186.599,2.74694,2220,6028053 +1170,search,7353.55,2440.47,2518.85,0.986848,242.159,2.21377,8.11927,0.92571,0.103154,-1.0,-1.0,62.332,2.74772,2223,6028053 +1171,delete,41.888,-1.0,-1.0,-1.0,-1.0,112.36,2.74254,2219,6001880 +1172,search,7299.88,2432.86,2480.59,1.00035,236.5,2.17068,8.5249,0.92544,0.1035,-1.0,-1.0,50.935,2.74281,2221,6001880 +1173,delete,64.641,-1.0,-1.0,-1.0,-1.0,202.7,2.73092,2212,5957180 +1174,search,7295.25,2417.84,2474.82,0.976915,239.802,2.22869,8.81107,0.92548,0.103461,-1.0,-1.0,43.914,2.73101,2213,5957180 +1175,delete,25.011,-1.0,-1.0,-1.0,-1.0,56.766,2.72957,2212,5939326 +1176,search,7280.88,2410.33,2466.99,0.993166,235.49,2.15326,8.75915,0.92553,0.103741,-1.0,-1.0,32.33,2.72957,2212,5939326 +1177,delete,18.597,-1.0,-1.0,-1.0,-1.0,105.262,2.72489,2209,5924145 +1178,search,7100.12,2408.54,2333.83,1.04793,212.658,2.33259,8.88717,0.92562,0.103731,-1.0,-1.0,42.945,2.72519,2210,5924145 +1179,delete,87.385,-1.0,-1.0,-1.0,-1.0,403.625,2.69823,2186,5863334 +1180,search,7182.42,2405.01,2434.49,0.984646,226.327,2.13463,8.11194,0.92469,0.10493,-1.0,-1.0,51.371,2.69848,2188,5863334 +1181,delete,52.775,-1.0,-1.0,-1.0,-1.0,51.987,2.69584,2186,5822703 +1182,search,7145.48,2386.21,2414.78,0.99347,232.556,2.18994,8.57101,0.92444,0.10523,-1.0,-1.0,31.713,2.69584,2186,5822703 +1183,delete,61.266,-1.0,-1.0,-1.0,-1.0,212.639,2.68118,2175,5775807 +1184,search,7111.96,2374.78,2394.73,0.976828,221.976,2.14321,8.4456,0.92415,0.105565,-1.0,-1.0,40.86,2.68137,2176,5775807 +1185,delete,30.17,-1.0,-1.0,-1.0,-1.0,138.09,2.67242,2169,5750627 +1186,search,7071.92,2369.37,2372.85,0.965385,230.739,2.11185,8.80743,0.9239,0.105678,-1.0,-1.0,40.156,2.67246,2170,5750627 +1187,delete,199.831,-1.0,-1.0,-1.0,-1.0,1214.58,2.599,2097,5601207 +1188,search,6718.89,2374.97,2204.14,1.03937,202.028,2.12529,9.25849,0.92341,0.105775,-1.0,-1.0,135.505,2.60014,2107,5601207 +1189,delete,17.813,-1.0,-1.0,-1.0,-1.0,62.353,2.59614,2104,5586425 +1190,search,6858.76,2364.43,2295.25,1.01699,217.64,2.16081,8.04666,0.92319,0.106168,-1.0,-1.0,32.775,2.59614,2104,5586425 +1191,delete,25.151,-1.0,-1.0,-1.0,-1.0,50.628,2.5947,2103,5574023 +1192,search,6862.22,2361.23,2290.05,1.00615,213.94,2.14885,8.88988,0.92308,0.106178,-1.0,-1.0,32.004,2.5947,2103,5574023 +1193,delete,316.215,-1.0,-1.0,-1.0,-1.0,1417.33,2.48682,2010,5356157 +1194,search,6550.67,2372.81,2183.28,0.999023,200.438,2.13031,7.7997,0.92139,0.106661,-1.0,-1.0,155.197,2.48885,2023,5356157 +1195,delete,19.081,-1.0,-1.0,-1.0,-1.0,56.022,2.48626,2021,5340404 +1196,search,6606.53,2350.83,2211.54,0.992503,206.99,2.13492,8.47843,0.92184,0.106419,-1.0,-1.0,29.326,2.48626,2021,5340404 +1197,delete,69.986,-1.0,-1.0,-1.0,-1.0,65.151,2.47975,2018,5293259 +1198,search,6565.85,2325.21,2198.47,0.968174,196.12,2.14395,8.81075,0.92156,0.10691,-1.0,-1.0,37.636,2.47983,2019,5293259 +1199,delete,19.934,-1.0,-1.0,-1.0,-1.0,70.466,2.47603,2016,5279787 +1200,search,6563.81,2323.13,2177.66,0.978823,208.533,2.14924,8.15585,0.92156,0.106676,-1.0,-1.0,28.816,2.47603,2016,5279787 +1201,delete,99.59,-1.0,-1.0,-1.0,-1.0,396.232,2.44703,1991,5216567 +1202,search,6473.48,2322.65,2155.26,1.01051,198.632,2.13605,7.92637,0.92084,0.106698,-1.0,-1.0,48.864,2.44735,1993,5216567 +1203,delete,30.309,-1.0,-1.0,-1.0,-1.0,34.234,2.44509,1992,5196947 +1204,search,6298.73,2310.83,1995.33,1.04849,184.537,2.15693,11.1989,0.92095,0.106983,-1.0,-1.0,48.505,2.4455,1994,5196947 +1205,delete,35.38,-1.0,-1.0,-1.0,-1.0,70.188,2.43607,1990,5168447 +1206,search,6458.18,2302.29,2139.23,0.996488,201.078,2.16621,8.11527,0.92114,0.106771,-1.0,-1.0,27.393,2.43607,1990,5168447 +1207,delete,32.69,-1.0,-1.0,-1.0,-1.0,124.936,2.42835,1983,5146927 +1208,search,6403.32,2297.06,2118.6,0.991606,191.864,2.17245,8.41306,0.92037,0.106848,-1.0,-1.0,36.666,2.42842,1984,5146927 +1209,delete,397.097,-1.0,-1.0,-1.0,-1.0,1232.16,2.29078,1890,4887612 +1210,search,6112.64,2294.33,2005.04,0.993505,184.3,2.15564,8.57613,0.91901,0.107401,-1.0,-1.0,95.233,2.29168,1897,4887612 +1211,delete,6.832,-1.0,-1.0,-1.0,-1.0,25.215,2.29117,1897,4882301 +1212,search,6091.61,2284.64,1993.29,1.04392,166.646,2.13751,8.17661,0.9195,0.106914,-1.0,-1.0,25.678,2.29117,1897,4882301 +1213,delete,154.299,-1.0,-1.0,-1.0,-1.0,620.913,2.23123,1849,4780915 +1214,search,6005.87,2290.74,1981.86,1.01102,183.571,3.25375,8.26584,0.91774,0.10801,-1.0,-1.0,111.457,2.23248,1857,4780915 +1215,delete,20.173,-1.0,-1.0,-1.0,-1.0,37.595,2.22995,1856,4765751 +1216,search,6011.65,2277.24,1965.44,0.97134,180.597,2.13647,8.65659,0.91789,0.108124,-1.0,-1.0,28.595,2.22995,1856,4765751 +1217,delete,521.421,-1.0,-1.0,-1.0,-1.0,2111.75,2.05037,1665,4452306 +1218,search,5489.22,2367.15,1858.73,0.962896,163.702,2.31055,8.63721,0.91326,0.112271,-1.0,-1.0,239.942,2.0534,1684,4452306 +1219,delete,133.451,-1.0,-1.0,-1.0,-1.0,629.542,1.9967,1619,4362045 +1220,search,5291.67,2391.74,1770.63,1.02857,167.954,3.02156,9.10938,0.9122,0.112757,-1.0,-1.0,148.189,1.99781,1633,4362045 +1221,delete,50.447,-1.0,-1.0,-1.0,-1.0,61.356,1.99188,1631,4326917 +1222,search,5364.05,2352.7,1806.49,0.99497,173.191,2.19386,8.96917,0.91226,0.112442,-1.0,-1.0,36.859,1.99219,1632,4326917 +1223,delete,300.099,-1.0,-1.0,-1.0,-1.0,916.258,1.89274,1546,4109781 +1224,search,5006.23,2359.62,1633.66,1.04319,152.707,2.1842,8.94606,0.90936,0.114209,-1.0,-1.0,171.852,1.89507,1562,4109781 +1225,delete,36.257,-1.0,-1.0,-1.0,-1.0,171.235,1.88099,1551,4075879 +1226,search,5083.97,2333.11,1714.77,0.98236,165.533,2.18253,9.51206,0.90875,0.114565,-1.0,-1.0,54.417,1.8813,1554,4075879 +1227,delete,100.602,-1.0,-1.0,-1.0,-1.0,583.007,1.84235,1515,4006503 +1228,search,4866.05,2350.25,1567.47,1.03092,138.5,2.13518,9.30138,0.90876,0.114978,-1.0,-1.0,82.301,1.84321,1521,4006503 +1229,delete,125.394,-1.0,-1.0,-1.0,-1.0,640.612,1.79824,1474,3922625 +1230,search,4877.85,2368.24,1650.27,0.955768,154.114,2.15594,8.6413,0.90851,0.114635,-1.0,-1.0,126.253,1.79979,1484,3922625 +1231,delete,99.44,-1.0,-1.0,-1.0,-1.0,431.177,1.75941,1430,3844860 +1232,search,4751.07,2406.62,1631.78,0.963039,143.653,2.46565,8.26658,0.9063,0.116154,-1.0,-1.0,123.343,1.76072,1441,3844860 +1233,delete,13.486,-1.0,-1.0,-1.0,-1.0,58.084,1.75619,1438,3831414 +1234,search,4653.62,2377.47,1533.62,1.0262,139.457,2.16057,8.34852,0.90584,0.116784,-1.0,-1.0,44.237,1.75641,1441,3831414 +1235,delete,195.811,-1.0,-1.0,-1.0,-1.0,754.52,1.68922,1381,3684234 +1236,search,4425.03,2382.03,1411.41,1.08131,130.183,2.1329,9.38378,0.90446,0.11824,-1.0,-1.0,102.78,1.69005,1391,3684234 +1237,delete,16.329,-1.0,-1.0,-1.0,-1.0,35.409,1.68712,1389,3669074 +1238,search,4576.62,2352.8,1557.91,0.936967,134.43,2.19682,8.31286,0.90425,0.118618,-1.0,-1.0,36.442,1.6873,1391,3669074 +1239,delete,66.4,-1.0,-1.0,-1.0,-1.0,142.62,1.67246,1379,3620984 +1240,search,4511.13,2330.83,1513.76,0.971475,138.883,2.22228,7.95777,0.90428,0.118788,-1.0,-1.0,18.428,1.67246,1379,3620984 +1241,delete,46.85,-1.0,-1.0,-1.0,-1.0,106.309,1.66395,1372,3580113 +1242,search,4480.58,2310.22,1498.17,0.966252,144.443,2.15409,9.31357,0.90353,0.119294,-1.0,-1.0,29.14,1.66397,1373,3580113 +1243,delete,64.744,-1.0,-1.0,-1.0,-1.0,279.193,1.64026,1350,3533909 +1244,search,4362.27,2309.77,1413.16,1.07115,131.279,2.32109,8.46927,0.90272,0.120204,-1.0,-1.0,76.601,1.64112,1355,3533909 +1245,delete,18.439,-1.0,-1.0,-1.0,-1.0,75.435,1.63507,1350,3519590 +1246,search,4363.68,2300.24,1412.06,1.07546,129.085,2.14697,8.53118,0.90267,0.120432,-1.0,-1.0,25.593,1.63517,1351,3519590 +1247,delete,80.222,-1.0,-1.0,-1.0,-1.0,187.151,1.60103,1320,3452537 +1248,search,4349.76,2317.74,1468.17,0.972276,126.791,2.11869,8.63661,0.90378,0.119014,-1.0,-1.0,63.737,1.60146,1326,3452537 +1249,delete,43.841,-1.0,-1.0,-1.0,-1.0,136.683,1.58855,1317,3416711 +1250,search,4336.98,2296.07,1442.15,1.01008,135.092,2.20769,9.48661,0.90293,0.119684,-1.0,-1.0,19.881,1.58855,1317,3416711 +1251,delete,51.841,-1.0,-1.0,-1.0,-1.0,111.999,1.57763,1309,3387653 +1252,search,4224.94,2286.67,1356.92,1.04901,124.342,3.34634,9.24213,0.90222,0.12002,-1.0,-1.0,41.987,1.57791,1311,3387653 +1253,delete,28.731,-1.0,-1.0,-1.0,-1.0,90.291,1.5696,1306,3372157 +1254,search,4278.74,2283.63,1408.9,1.01278,139.848,2.21069,8.49129,0.90185,0.120228,-1.0,-1.0,60.064,1.57001,1309,3372157 +1255,delete,177.912,-1.0,-1.0,-1.0,-1.0,241.897,1.51516,1269,3258215 +1256,search,4144.53,2278.21,1357.54,0.973876,115.543,2.13518,8.00427,0.89954,0.121339,-1.0,-1.0,55.068,1.51557,1272,3258215 +1257,delete,54.933,-1.0,-1.0,-1.0,-1.0,141.113,1.49705,1261,3223657 +1258,search,4157.8,2270.64,1378.03,0.991776,133.691,2.19949,9.26506,0.89845,0.122,-1.0,-1.0,42.57,1.49762,1263,3223657 +1259,delete,76.94,-1.0,-1.0,-1.0,-1.0,250.689,1.47133,1242,3174982 +1260,search,4095.87,2268.54,1350.1,1.00226,126.191,2.20993,8.80446,0.89753,0.122548,-1.0,-1.0,42.954,1.47156,1244,3174982 +1261,delete,26.807,-1.0,-1.0,-1.0,-1.0,40.723,1.46808,1242,3157038 +1262,search,4097.29,2253.26,1357.05,0.926059,115.132,2.15699,9.06416,0.89733,0.12236,-1.0,-1.0,30.647,1.46836,1243,3157038 +1263,delete,149.843,-1.0,-1.0,-1.0,-1.0,562.257,1.41519,1204,3058847 +1264,search,3972.09,2264.58,1324.71,0.968248,113.942,2.1321,9.04302,0.89618,0.122633,-1.0,-1.0,100.77,1.4165,1211,3058847 +1265,delete,406.985,-1.0,-1.0,-1.0,-1.0,729.207,1.29469,1091,2833531 +1266,search,3652.77,2315.97,1236.08,1.01118,112.115,2.9355,8.69796,0.89078,0.127057,-1.0,-1.0,170.448,1.29688,1106,2833531 +1267,delete,83.33,-1.0,-1.0,-1.0,-1.0,202.824,1.27274,1091,2763793 +1268,search,3551.21,2251.44,1150.54,1.02867,99.2539,2.12604,8.52954,0.89016,0.127259,-1.0,-1.0,45.289,1.27301,1093,2763793 +1269,delete,226.998,-1.0,-1.0,-1.0,-1.0,452.722,1.20637,1050,2627384 +1270,search,3499.6,2268.77,1160.19,0.939111,118.578,2.2162,8.89959,0.89077,0.126459,-1.0,-1.0,79.849,1.20738,1056,2627384 +1271,delete,94.466,-1.0,-1.0,-1.0,-1.0,357.027,1.17388,1026,2553476 +1272,search,3363.25,2261.5,1110.01,0.979234,99.7522,2.51756,7.98769,0.89049,0.126738,-1.0,-1.0,82.731,1.17454,1032,2553476 +1273,delete,168.322,-1.0,-1.0,-1.0,-1.0,437.141,1.11887,986,2443067 +1274,search,3257.61,2261.06,1083.46,0.94722,105.22,2.20769,9.19572,0.88802,0.12879,-1.0,-1.0,97.403,1.12011,993,2443067 +1275,delete,25.389,-1.0,-1.0,-1.0,-1.0,74.769,1.11408,988,2421654 +1276,search,3276.58,2240.05,1097.34,0.944785,93.662,2.22772,6.83604,0.88821,0.128379,-1.0,-1.0,18.462,1.11408,988,2421654 +1277,delete,40.105,-1.0,-1.0,-1.0,-1.0,87.168,1.10525,980,2391396 +1278,search,3254.76,2227.85,1085.88,0.942998,93.0007,2.13983,7.99082,0.88808,0.12828,-1.0,-1.0,18.699,1.10525,980,2391396 +1279,delete,29.042,-1.0,-1.0,-1.0,-1.0,45.529,1.10224,977,2367854 +1280,search,3211.46,2212.09,1066.97,0.918439,94.3906,2.1755,9.79768,0.8877,0.12839,-1.0,-1.0,18.377,1.10224,977,2367854 diff --git a/scripts/big_ann_perf_numbers/perf_debug_scan_0.15_fine_grain_analyze.csv b/scripts/big_ann_perf_numbers/perf_debug_scan_0.15_fine_grain_analyze.csv new file mode 100644 index 00000000..c98f38c7 --- /dev/null +++ b/scripts/big_ann_perf_numbers/perf_debug_scan_0.15_fine_grain_analyze.csv @@ -0,0 +1,11 @@ +step_num,step_type,latency_ms,worker_partition_size,worker_scan_time_ms,worker_scan_throughput,worker_result_time_ms,measured_ipc,cache_miss_rate,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +2,search,2820.94,37.4413,340.143,3.62873,398.433,-nan,-nan,0.8551,0.130106,-1.0,-1.0,6.414,0.0184881,1000,38806 +3,insert,10.982,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.309,0.022655,996,49334 +4,search,2945.64,64.8478,374.049,3.25734,508.487,-nan,-nan,0.86686,0.128427,-1.0,-1.0,15.332,0.0226615,993,49334 +5,insert,17.938,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,162.509,0.032935,982,73557 +6,search,3501.53,185.758,686.185,3.07149,778.034,-nan,-nan,0.92586,0.10314,-1.0,-1.0,126.549,0.0330859,984,73557 +7,insert,30.113,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,123.09,0.0427351,986,95766 +8,search,3735.66,233.069,813.092,2.83407,881.965,-nan,-nan,0.92464,0.103834,-1.0,-1.0,32.819,0.0433149,992,95766 +9,insert,6.21,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,6.485,0.0451264,992,100025 +10,search,3843.37,236.809,818.361,2.62811,975.12,-nan,-nan,0.92487,0.102107,-1.0,-1.0,19.174,0.0451705,997,100025 +11,insert,8.018,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,9.338,0.0496899,999,111417 diff --git a/scripts/big_ann_perf_numbers/perf_debug_scan_0.15_no_aps_refinment_wma_delete.csv b/scripts/big_ann_perf_numbers/perf_debug_scan_0.15_no_aps_refinment_wma_delete.csv new file mode 100644 index 00000000..5da7f512 --- /dev/null +++ b/scripts/big_ann_perf_numbers/perf_debug_scan_0.15_no_aps_refinment_wma_delete.csv @@ -0,0 +1,76 @@ +step_num,step_type,latency_ms,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +2,search,3501.12,0.8551,0.130106,-1.0,-1.0,7.247,0.0184881,1000,38806 +3,insert,21.437,-1.0,-1.0,-1.0,-1.0,11.994,0.0226489,997,49334 +4,search,2653.89,0.86623,0.128786,-1.0,-1.0,10.61,0.0226285,996,49334 +5,insert,16.162,-1.0,-1.0,-1.0,-1.0,163.62,0.0332675,987,73557 +6,search,2526.55,0.92564,0.103451,-1.0,-1.0,109.996,0.0333764,990,73557 +7,insert,23.905,-1.0,-1.0,-1.0,-1.0,107.795,0.043033,992,95766 +8,search,2533.96,0.92473,0.103666,-1.0,-1.0,89.323,0.0432141,995,95766 +9,insert,4.134,-1.0,-1.0,-1.0,-1.0,78.416,0.0448731,995,100025 +10,search,2553.3,0.92668,0.100654,-1.0,-1.0,83.164,0.0448873,997,100025 +11,insert,9.317,-1.0,-1.0,-1.0,-1.0,84.32,0.0497899,999,111417 +12,search,2556.17,0.92582,0.10188,-1.0,-1.0,82.133,0.0497899,999,111417 +13,insert,18.923,-1.0,-1.0,-1.0,-1.0,82.91,0.0609009,1000,137139 +14,search,2607.65,0.92274,0.103788,-1.0,-1.0,16.785,0.0611229,1001,137139 +15,insert,16.964,-1.0,-1.0,-1.0,-1.0,8.969,0.0699797,1002,156710 +16,search,2617.5,0.92112,0.104544,-1.0,-1.0,16.214,0.0699822,1004,156710 +17,insert,3.751,-1.0,-1.0,-1.0,-1.0,8.187,0.0719859,1005,161773 +18,search,2628.55,0.92122,0.104633,-1.0,-1.0,17.882,0.0722066,1009,161773 +19,insert,30.402,-1.0,-1.0,-1.0,-1.0,10.545,0.079079,1011,177161 +20,search,2688.58,0.92442,0.101885,-1.0,-1.0,14.093,0.0790826,1014,177161 +21,insert,357.587,-1.0,-1.0,-1.0,-1.0,170.596,0.200924,1060,448898 +22,search,2967.15,0.91162,0.106615,-1.0,-1.0,51.614,0.201311,1073,448898 +23,insert,352.27,-1.0,-1.0,-1.0,-1.0,254.625,0.329156,1128,733493 +24,search,3238.16,0.90717,0.10925,-1.0,-1.0,61.716,0.329255,1140,733493 +25,insert,36.016,-1.0,-1.0,-1.0,-1.0,20.868,0.346707,1144,777443 +26,search,3280.1,0.90784,0.108781,-1.0,-1.0,26.4,0.346754,1148,777443 +27,insert,35.986,-1.0,-1.0,-1.0,-1.0,16.827,0.357795,1149,805394 +28,search,3339.07,0.90791,0.108498,-1.0,-1.0,18.188,0.358026,1151,805394 +29,insert,60.352,-1.0,-1.0,-1.0,-1.0,48.879,0.385613,1160,866391 +30,search,3390.57,0.91036,0.107782,-1.0,-1.0,23.151,0.385612,1162,866391 +31,insert,457.127,-1.0,-1.0,-1.0,-1.0,331.116,0.554438,1231,1239816 +32,search,3743.85,0.90345,0.113196,-1.0,-1.0,56.109,0.55473,1241,1239816 +33,insert,44.652,-1.0,-1.0,-1.0,-1.0,34.628,0.574174,1249,1291211 +34,search,3793.6,0.9031,0.113418,-1.0,-1.0,9.607,0.574174,1249,1291211 +35,insert,30.328,-1.0,-1.0,-1.0,-1.0,23.274,0.586072,1253,1324978 +36,search,3796.75,0.90438,0.112151,-1.0,-1.0,9.496,0.586072,1253,1324978 +37,insert,42.266,-1.0,-1.0,-1.0,-1.0,25.146,0.605461,1256,1371885 +38,search,3897.39,0.90477,0.111023,-1.0,-1.0,18.871,0.605461,1257,1371885 +39,insert,14.817,-1.0,-1.0,-1.0,-1.0,13.322,0.608401,1258,1379335 +40,search,3869.86,0.90455,0.111586,-1.0,-1.0,10.388,0.608401,1258,1379335 +41,insert,55.458,-1.0,-1.0,-1.0,-1.0,32.478,0.624165,1263,1413312 +42,search,3907.2,0.90539,0.111602,-1.0,-1.0,16.726,0.62419,1264,1413312 +43,insert,12.375,-1.0,-1.0,-1.0,-1.0,9.321,0.627996,1264,1423411 +44,search,3908.39,0.90555,0.111557,-1.0,-1.0,9.803,0.627996,1264,1423411 +45,insert,210.399,-1.0,-1.0,-1.0,-1.0,37.258,0.642859,1272,1457559 +46,search,3943.63,0.90588,0.111224,-1.0,-1.0,9.4,0.642859,1272,1457559 +47,insert,268.08,-1.0,-1.0,-1.0,-1.0,260.586,0.747977,1309,1688593 +48,search,4162.47,0.9073,0.111488,-1.0,-1.0,73.613,0.74809,1316,1688593 +49,insert,36.419,-1.0,-1.0,-1.0,-1.0,33.041,0.763532,1321,1723505 +50,search,4195.21,0.90795,0.111388,-1.0,-1.0,35.026,0.763612,1324,1723505 +51,insert,324.511,-1.0,-1.0,-1.0,-1.0,281.385,0.904526,1374,2035040 +52,search,4524.53,0.91046,0.109908,-1.0,-1.0,62.904,0.904558,1381,2035040 +53,insert,50.771,-1.0,-1.0,-1.0,-1.0,35.12,0.921856,1385,2078341 +54,search,4525.94,0.91036,0.109832,-1.0,-1.0,17.299,0.922113,1386,2078341 +55,insert,396.289,-1.0,-1.0,-1.0,-1.0,400.726,1.06875,1440,2399905 +56,search,4907.83,0.91181,0.110055,-1.0,-1.0,133.135,1.06927,1461,2399905 +57,insert,26.12,-1.0,-1.0,-1.0,-1.0,27.496,1.07686,1464,2419836 +58,search,4651.68,0.91077,0.110844,-1.0,-1.0,51.209,1.0769,1470,2419836 +59,insert,232.29,-1.0,-1.0,-1.0,-1.0,109.939,1.1754,1483,2643083 +60,search,5000.83,0.90391,0.118459,-1.0,-1.0,34.102,1.17575,1487,2643083 +61,insert,12.219,-1.0,-1.0,-1.0,-1.0,15.476,1.18003,1488,2653064 +62,search,4923.67,0.90386,0.118465,-1.0,-1.0,17.959,1.18012,1489,2653064 +63,insert,3.41,-1.0,-1.0,-1.0,-1.0,10.734,1.18123,1489,2656118 +64,search,4742.82,0.9039,0.11847,-1.0,-1.0,11.125,1.18123,1489,2656118 +65,insert,72.96,-1.0,-1.0,-1.0,-1.0,94.552,1.20956,1508,2723424 +66,search,5103.51,0.90554,0.11719,-1.0,-1.0,11.279,1.20956,1508,2723424 +67,insert,46.114,-1.0,-1.0,-1.0,-1.0,78.987,1.23164,1523,2769021 +68,search,5131.05,0.90653,0.116421,-1.0,-1.0,24.94,1.23164,1526,2769021 +69,insert,50.266,-1.0,-1.0,-1.0,-1.0,57.509,1.25403,1535,2821777 +70,search,4863.58,0.90844,0.114447,-1.0,-1.0,23.343,1.25403,1536,2821777 +71,insert,25.548,-1.0,-1.0,-1.0,-1.0,35.735,1.26041,1540,2834921 +72,search,5273.28,0.90898,0.114243,-1.0,-1.0,11.676,1.26041,1540,2834921 +73,insert,6.716,-1.0,-1.0,-1.0,-1.0,36.706,1.26336,1544,2842044 +74,search,4944.68,0.90877,0.114226,-1.0,-1.0,12.623,1.26336,1544,2842044 +75,insert,25.716,-1.0,-1.0,-1.0,-1.0,24.623,1.26947,1546,2858890 +76,search,5254.27,0.90899,0.114142,-1.0,-1.0,12.304,1.26947,1546,2858890 diff --git a/scripts/big_ann_perf_numbers/perf_debug_scan_0.15_vary_batch_size.csv b/scripts/big_ann_perf_numbers/perf_debug_scan_0.15_vary_batch_size.csv new file mode 100644 index 00000000..c385b5b5 --- /dev/null +++ b/scripts/big_ann_perf_numbers/perf_debug_scan_0.15_vary_batch_size.csv @@ -0,0 +1,2101 @@ +batch_size,step_num,step_type,search_latency_ms,worker_partition_size,worker_scan_time_ms,worker_scan_throughput,worker_result_time_ms,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +1,2,search,3785,37.3093,123.379,27.6391,113.241,0.8551,0.130106,-1.0,-1.0,14.867,0.0184881,1000,38806 +1,3,insert,22.387,-1.0,-1.0,-1.0,-1.0,19.853,0.022655,996,49334 +1,4,search,3325.33,66.3453,498.773,15.8079,134.22,0.86686,0.128427,-1.0,-1.0,14.166,0.0226469,994,49334 +1,5,insert,17.132,-1.0,-1.0,-1.0,-1.0,178.984,0.0330329,986,73557 +1,6,search,2890.47,195.078,506.466,36.266,69.9005,0.92469,0.104049,-1.0,-1.0,126.666,0.0331418,987,73557 +1,7,insert,23.973,-1.0,-1.0,-1.0,-1.0,123.843,0.0425911,988,95766 +1,8,search,3110.59,247.911,652.613,34.9803,85.6366,0.92524,0.103379,-1.0,-1.0,20.529,0.0431778,991,95766 +1,9,insert,3.424,-1.0,-1.0,-1.0,-1.0,5.196,0.0448706,991,100025 +1,10,search,2884.13,255.196,571.217,36.791,61.7057,0.92675,0.10077,-1.0,-1.0,15.297,0.0448853,993,100025 +1,11,insert,9.188,-1.0,-1.0,-1.0,-1.0,8.919,0.049778,994,111417 +1,12,search,2938.43,297.254,608.654,39.9052,56.7331,0.92675,0.101492,-1.0,-1.0,6.847,0.049778,994,111417 +1,13,insert,18.772,-1.0,-1.0,-1.0,-1.0,8.226,0.0609625,995,137139 +1,14,search,3020.59,341.923,685.157,40.5329,63.1383,0.92349,0.103267,-1.0,-1.0,6.957,0.0609625,995,137139 +1,15,insert,14.916,-1.0,-1.0,-1.0,-1.0,6.711,0.0694257,995,156710 +1,16,search,3104.07,382.93,752.239,41.562,59.1598,0.92282,0.103406,-1.0,-1.0,9.077,0.0694257,995,156710 +1,17,insert,8.896,-1.0,-1.0,-1.0,-1.0,11.447,0.0717203,996,161773 +1,18,search,3161.34,402.544,821.252,40.8878,60.7769,0.92393,0.102988,-1.0,-1.0,7.068,0.0717203,996,161773 +1,19,insert,30.933,-1.0,-1.0,-1.0,-1.0,10.81,0.0786942,998,177161 +1,20,search,3227.24,445.222,884.604,41.1437,65.1267,0.92707,0.100522,-1.0,-1.0,6.789,0.0786942,998,177161 +1,21,insert,314.978,-1.0,-1.0,-1.0,-1.0,114.326,0.199732,1021,448898 +1,22,search,4248.28,964.817,1849.48,43.8901,77.0617,0.91928,0.101702,-1.0,-1.0,23.899,0.199731,1025,448898 +1,23,insert,366.365,-1.0,-1.0,-1.0,-1.0,242.808,0.328243,1061,733493 +1,24,search,5223.19,1355.54,2695.07,44.089,87.3084,0.91399,0.104408,-1.0,-1.0,85.314,0.328353,1074,733493 +1,25,insert,45.219,-1.0,-1.0,-1.0,-1.0,17.364,0.345328,1076,777443 +1,26,search,5245.3,1342.13,2710.74,44.9455,86.0274,0.91329,0.104989,-1.0,-1.0,24.434,0.345389,1078,777443 +1,27,insert,35.048,-1.0,-1.0,-1.0,-1.0,16.123,0.357044,1079,805394 +1,28,search,5288.02,1364.22,2781.47,44.2439,75.1515,0.91349,0.104892,-1.0,-1.0,10.499,0.357044,1079,805394 +1,29,insert,56.958,-1.0,-1.0,-1.0,-1.0,41.567,0.384589,1083,866391 +1,30,search,5548.82,1446.01,2984.79,43.7879,82.3114,0.91582,0.104342,-1.0,-1.0,25.692,0.384588,1085,866391 +1,31,insert,422.614,-1.0,-1.0,-1.0,-1.0,369.032,0.552831,1137,1239816 +1,32,search,6484.85,1754.01,3793.11,44.7031,95.442,0.90782,0.11124,-1.0,-1.0,98.829,0.553106,1145,1239816 +1,33,insert,48.956,-1.0,-1.0,-1.0,-1.0,26.499,0.572978,1147,1291211 +1,34,search,6065.62,1766.98,3830.63,43.4618,133.003,0.90787,0.110891,-1.0,-1.0,30.445,0.573056,1151,1291211 +1,35,insert,17.035,-1.0,-1.0,-1.0,-1.0,13.122,0.58561,1154,1324978 +1,36,search,6158.2,1805.8,3984.08,42.4427,142.275,0.90906,0.109653,-1.0,-1.0,16.141,0.585611,1156,1324978 +1,37,insert,22.374,-1.0,-1.0,-1.0,-1.0,15.824,0.606138,1159,1371885 +1,38,search,6214.9,1832.85,4103.54,42.1518,121.88,0.90837,0.109156,-1.0,-1.0,9.333,0.606138,1160,1371885 +1,39,insert,4.037,-1.0,-1.0,-1.0,-1.0,5.494,0.609136,1160,1379335 +1,40,search,6230.58,1838.05,4078.69,42.4024,138.418,0.90914,0.109277,-1.0,-1.0,5.65,0.609136,1160,1379335 +1,41,insert,18.99,-1.0,-1.0,-1.0,-1.0,24.053,0.624517,1167,1413312 +1,42,search,6290.95,1843.49,4104.89,42.5103,144.977,0.9092,0.109146,-1.0,-1.0,6.847,0.624517,1167,1413312 +1,43,insert,8.684,-1.0,-1.0,-1.0,-1.0,5.847,0.628827,1167,1423411 +1,44,search,6309.64,1860.65,4146.07,42.6457,147.334,0.90928,0.10923,-1.0,-1.0,9.242,0.628926,1168,1423411 +1,45,insert,122.838,-1.0,-1.0,-1.0,-1.0,23.429,0.644478,1174,1457559 +1,46,search,6409.69,1864.54,4236.68,42.2779,131.543,0.90922,0.108792,-1.0,-1.0,6.054,0.644478,1174,1457559 +1,47,insert,152.893,-1.0,-1.0,-1.0,-1.0,166.458,0.749589,1207,1688593 +1,48,search,6849.46,1993.82,4611.11,43.1549,143.331,0.91021,0.11023,-1.0,-1.0,45.272,0.749588,1213,1688593 +1,49,insert,23.842,-1.0,-1.0,-1.0,-1.0,19.125,0.76327,1217,1723505 +1,50,search,7514.42,1998.37,4690.69,43.6195,126.381,0.91018,0.110305,-1.0,-1.0,48.201,0.76327,1222,1723505 +1,51,insert,344.024,-1.0,-1.0,-1.0,-1.0,281.148,0.903601,1260,2035040 +1,52,search,8223.79,2179.1,5222.98,44.0729,133.694,0.91288,0.108774,-1.0,-1.0,45.215,0.903645,1266,2035040 +1,53,insert,47.757,-1.0,-1.0,-1.0,-1.0,43.854,0.919307,1271,2078341 +1,54,search,8576.35,2186.31,5404.67,43.383,176.64,0.91218,0.10951,-1.0,-1.0,16.129,0.919307,1272,2078341 +1,55,insert,341.624,-1.0,-1.0,-1.0,-1.0,460.007,1.06855,1324,2399905 +1,56,search,8978.33,2346.21,5802.4,44.668,131.651,0.91284,0.110422,-1.0,-1.0,113.359,1.06854,1339,2399905 +1,57,insert,21.295,-1.0,-1.0,-1.0,-1.0,29.739,1.07722,1342,2419836 +1,58,search,9327.29,2301.44,5997,42.8207,203.886,0.91248,0.110721,-1.0,-1.0,57.387,1.07727,1349,2419836 +1,59,insert,199.379,-1.0,-1.0,-1.0,-1.0,133.02,1.17411,1359,2643083 +1,60,search,10012.5,2354.41,6530.65,41.4958,232.145,0.90538,0.118027,-1.0,-1.0,37.425,1.17435,1363,2643083 +1,61,insert,9.867,-1.0,-1.0,-1.0,-1.0,19.637,1.17818,1365,2653064 +1,62,search,9832.52,2352.24,6385.87,42.6507,219.92,0.90556,0.117893,-1.0,-1.0,12.892,1.17818,1365,2653064 +1,63,insert,6.054,-1.0,-1.0,-1.0,-1.0,10.762,1.17953,1365,2656118 +1,64,search,10192.3,2354.98,6697.38,41.5597,251.818,0.9056,0.117788,-1.0,-1.0,11.898,1.17953,1365,2656118 +1,65,insert,98.426,-1.0,-1.0,-1.0,-1.0,94.471,1.20713,1379,2723424 +1,66,search,10039.7,2388.06,6549.52,42.8488,228.75,0.90587,0.116739,-1.0,-1.0,10.542,1.20713,1379,2723424 +1,67,insert,49.952,-1.0,-1.0,-1.0,-1.0,74.185,1.22813,1389,2769021 +1,68,search,10173.6,2412.89,6650.6,42.7387,230.066,0.90719,0.115754,-1.0,-1.0,21.209,1.22813,1391,2769021 +1,69,insert,58.218,-1.0,-1.0,-1.0,-1.0,94.162,1.253,1405,2821777 +1,70,search,10516,2409.48,6925.21,42.0111,239.788,0.9089,0.114001,-1.0,-1.0,20.128,1.253,1406,2821777 +1,71,insert,18.77,-1.0,-1.0,-1.0,-1.0,34.657,1.25883,1410,2834921 +1,72,search,10271.6,2409.78,6702.08,42.9864,236.982,0.90928,0.113768,-1.0,-1.0,10.665,1.25883,1410,2834921 +1,73,insert,8.635,-1.0,-1.0,-1.0,-1.0,16.66,1.26198,1411,2842044 +1,74,search,9740.84,2412.95,6254.09,45.6657,159.176,0.90928,0.113847,-1.0,-1.0,10.689,1.26198,1411,2842044 +1,75,insert,19.928,-1.0,-1.0,-1.0,-1.0,15.047,1.26802,1412,2858890 +1,76,search,10518.9,2424.08,6924.59,41.9049,253.551,0.9093,0.113967,-1.0,-1.0,12.707,1.26802,1412,2858890 +1,77,insert,54.962,-1.0,-1.0,-1.0,-1.0,10.745,1.27732,1412,2882818 +1,78,search,9844.91,2438.56,6487.59,44.8724,157.39,0.90886,0.114312,-1.0,-1.0,11.612,1.27732,1412,2882818 +1,79,insert,492.447,-1.0,-1.0,-1.0,-1.0,15.727,1.30319,1413,2947806 +1,80,search,9812.94,2473.56,6475.73,45.6723,148.727,0.90878,0.11491,-1.0,-1.0,11.012,1.30319,1413,2947806 +1,81,insert,38.534,-1.0,-1.0,-1.0,-1.0,34.242,1.31603,1417,2976895 +1,82,search,10782.6,2481.72,7169.91,42.2771,250.094,0.91008,0.114578,-1.0,-1.0,10.872,1.31603,1417,2976895 +1,83,insert,16.428,-1.0,-1.0,-1.0,-1.0,21.647,1.32033,1419,2990682 +1,84,search,10481.1,2486.87,6933.22,42.8404,234.899,0.91031,0.114278,-1.0,-1.0,10.855,1.32033,1419,2990682 +1,85,insert,36.714,-1.0,-1.0,-1.0,-1.0,66.408,1.33517,1428,3025613 +1,86,search,10958.9,2487.36,7264.06,41.5189,256.016,0.91121,0.113506,-1.0,-1.0,12.382,1.33517,1428,3025613 +1,87,insert,596.553,-1.0,-1.0,-1.0,-1.0,771.492,1.54412,1525,3468632 +1,88,search,10710.7,2625.43,6950.78,49.4382,152.406,0.91465,0.110027,-1.0,-1.0,102.949,1.54412,1536,3468632 +1,89,insert,388.993,-1.0,-1.0,-1.0,-1.0,546.679,1.70299,1621,3831692 +1,90,search,11460.6,2676.72,7457.92,49.8344,167.728,0.91857,0.105217,-1.0,-1.0,83.643,1.70312,1631,3831692 +1,91,insert,36.012,-1.0,-1.0,-1.0,-1.0,42.801,1.71484,1636,3864067 +1,92,search,11502.3,2666.19,7461.36,49.929,168.55,0.91854,0.104939,-1.0,-1.0,18.883,1.71484,1637,3864067 +1,93,insert,260.794,-1.0,-1.0,-1.0,-1.0,216.863,1.81984,1667,4103827 +1,94,search,11974.2,2730.51,7854.67,49.5306,169.955,0.91917,0.104363,-1.0,-1.0,43.275,1.82031,1671,4103827 +1,95,insert,15.929,-1.0,-1.0,-1.0,-1.0,25.121,1.82549,1673,4119898 +1,96,search,11664.1,2731.89,7601.26,51.2247,157.338,0.91886,0.104689,-1.0,-1.0,13.494,1.82549,1673,4119898 +1,97,insert,10.72,-1.0,-1.0,-1.0,-1.0,11.919,1.82885,1673,4129367 +1,98,search,11634.6,2738.02,7562.77,51.4114,157.134,0.91903,0.104409,-1.0,-1.0,22.273,1.82904,1674,4129367 +1,99,insert,7.491,-1.0,-1.0,-1.0,-1.0,35.034,1.83165,1677,4134502 +1,100,search,11260.7,2731.02,7110.69,53.8225,184.328,0.91916,0.104433,-1.0,-1.0,15.279,1.83165,1677,4134502 +1,101,insert,43.514,-1.0,-1.0,-1.0,-1.0,46.428,1.84224,1681,4164482 +1,102,search,11354.1,2738.92,7203.75,53.8262,182.13,0.9194,0.104258,-1.0,-1.0,36.416,1.84262,1683,4164482 +1,103,insert,23.342,-1.0,-1.0,-1.0,-1.0,28.387,1.84878,1685,4178601 +1,104,search,11405,2738.08,7285.04,53.7341,188.22,0.91927,0.104453,-1.0,-1.0,14.105,1.84878,1685,4178601 +1,105,insert,12.676,-1.0,-1.0,-1.0,-1.0,13.952,1.8525,1685,4187774 +1,106,search,11425.8,2742.9,7310.29,53.4763,186.545,0.9192,0.104682,-1.0,-1.0,14.422,1.8525,1685,4187774 +1,107,insert,23.042,-1.0,-1.0,-1.0,-1.0,14.452,1.85734,1685,4200109 +1,108,search,11383,2747.93,7264.48,53.8799,191.977,0.91913,0.104803,-1.0,-1.0,14.726,1.85734,1685,4200109 +1,109,insert,503.849,-1.0,-1.0,-1.0,-1.0,545.69,2.01627,1754,4557867 +1,110,search,12218.1,2831.26,7884.1,53.4149,196.997,0.92093,0.103273,-1.0,-1.0,59.129,2.01635,1759,4557867 +1,111,insert,31.183,-1.0,-1.0,-1.0,-1.0,57.71,2.02804,1766,4587252 +1,112,search,12158.6,2827.1,7805.16,54.0157,203.579,0.92092,0.10365,-1.0,-1.0,26.72,2.02804,1767,4587252 +1,113,insert,15.282,-1.0,-1.0,-1.0,-1.0,30.25,2.03355,1769,4600056 +1,114,search,12152.9,2828.49,7777.04,53.9462,201.596,0.92123,0.103552,-1.0,-1.0,17.603,2.03355,1769,4600056 +1,115,insert,34.56,-1.0,-1.0,-1.0,-1.0,81.217,2.04379,1777,4627422 +1,116,search,11978.3,2830.5,7549.56,55.465,205.494,0.9215,0.103574,-1.0,-1.0,20.763,2.04379,1777,4627422 +1,117,insert,15.109,-1.0,-1.0,-1.0,-1.0,36.899,2.04898,1779,4639292 +1,118,search,12016.9,2830.85,7655.57,55.2289,197.973,0.92157,0.103415,-1.0,-1.0,20.554,2.04898,1779,4639292 +1,119,insert,7.973,-1.0,-1.0,-1.0,-1.0,18.857,2.05149,1779,4643423 +1,120,search,12069.6,2833.13,7713.78,55.1761,205.377,0.92159,0.103442,-1.0,-1.0,19.858,2.05149,1779,4643423 +1,121,insert,19.077,-1.0,-1.0,-1.0,-1.0,43.392,2.05663,1781,4657252 +1,122,search,12116.2,2839.72,7708.93,55.6766,213.701,0.92204,0.103013,-1.0,-1.0,32.465,2.05676,1782,4657252 +1,123,insert,419.067,-1.0,-1.0,-1.0,-1.0,480.673,2.18611,1833,4938477 +1,124,search,12465.8,2889.27,8168.1,54.9565,208.725,0.92286,0.10317,-1.0,-1.0,96.912,2.1872,1846,4938477 +1,125,insert,30.611,-1.0,-1.0,-1.0,-1.0,28.761,2.20207,1850,4980492 +1,126,search,12378.7,2880.28,8152.51,54.9982,217.429,0.92341,0.102812,-1.0,-1.0,79.455,2.2024,1856,4980492 +1,127,insert,65.364,-1.0,-1.0,-1.0,-1.0,121.569,2.22632,1870,5030515 +1,128,search,12348.5,2875.3,7859.23,56.4721,240.335,0.92417,0.102472,-1.0,-1.0,24.283,2.22632,1870,5030515 +1,129,delete,36.478,-1.0,-1.0,-1.0,-1.0,86.525,2.22469,1841,5009391 +1,130,search,12111.7,2862.32,7771.58,56.4938,240.538,0.92291,0.103255,-1.0,-1.0,23.811,2.22469,1841,5009391 +1,131,delete,11.548,-1.0,-1.0,-1.0,-1.0,23.061,2.22469,1841,5004093 +1,132,search,12099.6,2859.86,7734.39,56.7888,247.63,0.92283,0.103196,-1.0,-1.0,23.387,2.22469,1841,5004093 +1,133,delete,21.076,-1.0,-1.0,-1.0,-1.0,21.575,2.22466,1841,4991787 +1,134,search,12120.1,2846.14,7765.53,56.7113,242.325,0.92254,0.103569,-1.0,-1.0,22.749,2.22466,1841,4991787 +1,135,delete,26.94,-1.0,-1.0,-1.0,-1.0,58.538,2.22255,1838,4974857 +1,136,search,12020.7,2838.41,7668.07,56.8352,244.183,0.92233,0.103418,-1.0,-1.0,22.886,2.22255,1838,4974857 +1,137,delete,5.193,-1.0,-1.0,-1.0,-1.0,22.099,2.22255,1838,4971386 +1,138,search,12031.9,2835.79,7699.79,56.6013,228.429,0.92228,0.103551,-1.0,-1.0,22.53,2.22255,1838,4971386 +1,139,delete,9.713,-1.0,-1.0,-1.0,-1.0,21.825,2.22255,1838,4963487 +1,140,search,11927,2829.35,7574.33,56.8145,240.635,0.92224,0.103487,-1.0,-1.0,22.12,2.22255,1838,4963487 +1,141,delete,27.769,-1.0,-1.0,-1.0,-1.0,66.696,2.21859,1832,4941830 +1,142,search,11882,2821.04,7554.4,56.6701,222.259,0.92197,0.103563,-1.0,-1.0,25.841,2.21859,1832,4941830 +1,143,delete,39.792,-1.0,-1.0,-1.0,-1.0,65.033,2.2149,1829,4925657 +1,144,search,11910.3,2815.94,7570.8,56.86,241.551,0.92213,0.103521,-1.0,-1.0,23.662,2.2149,1829,4925657 +1,145,delete,5.403,-1.0,-1.0,-1.0,-1.0,22.059,2.2149,1829,4922686 +1,146,search,11918.2,2812.87,7581.51,56.8352,236.277,0.92198,0.103692,-1.0,-1.0,23.144,2.2149,1829,4922686 +1,147,delete,16.425,-1.0,-1.0,-1.0,-1.0,22.267,2.2149,1829,4913636 +1,148,search,11927.4,2805.55,7634.91,56.5437,221.554,0.92185,0.103767,-1.0,-1.0,22.954,2.2149,1829,4913636 +1,149,delete,240.376,-1.0,-1.0,-1.0,-1.0,737.648,2.13462,1751,4717250 +1,150,search,11279.2,2806.58,7273.29,56.3604,226.08,0.92119,0.103966,-1.0,-1.0,73.98,2.13549,1758,4717250 +1,151,delete,150.739,-1.0,-1.0,-1.0,-1.0,976.145,2.06652,1683,4560269 +2,2,search,2693.59,37.3093,118.243,33.621,56.2831,0.8551,0.130106,-1.0,-1.0,10.738,0.0184881,1000,38806 +2,3,insert,12.852,-1.0,-1.0,-1.0,-1.0,14.997,0.0226681,998,49334 +2,4,search,2740.54,66.7645,216.519,29.109,71.1175,0.86613,0.128797,-1.0,-1.0,12.267,0.0226611,997,49334 +2,5,insert,24.602,-1.0,-1.0,-1.0,-1.0,172.348,0.0329766,993,73557 +2,6,search,2920.69,193.743,485.51,37.5235,73.9561,0.92433,0.104255,-1.0,-1.0,111.999,0.0330819,995,73557 +2,7,insert,31.824,-1.0,-1.0,-1.0,-1.0,102.906,0.0426107,995,95766 +2,8,search,3067.69,246.253,604.228,38.0433,82.8645,0.92582,0.103612,-1.0,-1.0,90.335,0.0428012,997,95766 +2,9,insert,3.562,-1.0,-1.0,-1.0,-1.0,77.996,0.0445267,997,100025 +2,10,search,3181.5,255.431,703.457,33.8131,86.5186,0.92703,0.100737,-1.0,-1.0,80.067,0.0445267,997,100025 +2,11,insert,12.959,-1.0,-1.0,-1.0,-1.0,83.044,0.0498592,998,111417 +2,12,search,3131.1,301.481,711.53,39.0233,76.1398,0.92731,0.100772,-1.0,-1.0,81.149,0.0498592,998,111417 +2,13,insert,24.282,-1.0,-1.0,-1.0,-1.0,80.176,0.061027,998,137139 +2,14,search,3224.77,347.374,813.671,38.7823,77.9262,0.92407,0.103186,-1.0,-1.0,19.31,0.0610735,999,137139 +2,15,insert,24.03,-1.0,-1.0,-1.0,-1.0,10.527,0.0698186,1000,156710 +2,16,search,3407.07,382.315,879.493,36.8138,96.1963,0.92236,0.104082,-1.0,-1.0,19.38,0.0698219,1002,156710 +2,17,insert,5.414,-1.0,-1.0,-1.0,-1.0,10.8,0.0717574,1003,161773 +2,18,search,3372.1,397.142,852.074,38.5,93.8068,0.9226,0.103835,-1.0,-1.0,20.724,0.0720553,1007,161773 +2,19,insert,32.923,-1.0,-1.0,-1.0,-1.0,9.911,0.0786767,1008,177161 +2,20,search,3486.93,432.221,934.291,38.3532,99.7491,0.92598,0.100475,-1.0,-1.0,13.964,0.0786865,1010,177161 +2,21,insert,325.44,-1.0,-1.0,-1.0,-1.0,147.799,0.201104,1044,448898 +2,22,search,4517.68,896.136,1881.14,41.1039,117.432,0.91446,0.104467,-1.0,-1.0,41.228,0.201332,1054,448898 +2,23,insert,374.091,-1.0,-1.0,-1.0,-1.0,262.331,0.328658,1110,733493 +2,24,search,5501.58,1184.26,2695.2,41.127,134.214,0.90701,0.108066,-1.0,-1.0,77.494,0.328925,1123,733493 +2,25,insert,35.336,-1.0,-1.0,-1.0,-1.0,31.249,0.345993,1127,777443 +2,26,search,5669.21,1177.24,2650.57,41.734,141.019,0.90771,0.107577,-1.0,-1.0,24.881,0.346027,1129,777443 +2,27,insert,47.015,-1.0,-1.0,-1.0,-1.0,25.65,0.357907,1132,805394 +2,28,search,5672.26,1192.73,2814.07,41.4023,133.542,0.90763,0.108027,-1.0,-1.0,12.975,0.357914,1133,805394 +2,29,insert,68.267,-1.0,-1.0,-1.0,-1.0,57.946,0.385733,1144,866391 +2,30,search,5785.96,1241.86,2897.96,41.5407,134.085,0.9087,0.109043,-1.0,-1.0,27.03,0.385754,1147,866391 +2,31,insert,449.087,-1.0,-1.0,-1.0,-1.0,343.852,0.553944,1209,1239816 +2,32,search,6837.46,1513.27,3767.59,42.0494,165.172,0.90265,0.113124,-1.0,-1.0,88.955,0.553953,1217,1239816 +2,33,insert,50.549,-1.0,-1.0,-1.0,-1.0,26.338,0.573596,1221,1291211 +2,34,search,6806.24,1526.36,3746.12,42.5053,151.136,0.90287,0.112714,-1.0,-1.0,49.885,0.573606,1224,1291211 +2,35,insert,33.195,-1.0,-1.0,-1.0,-1.0,31.44,0.585225,1230,1324978 +2,36,search,6945.65,1551.71,3834.48,42.6607,148.921,0.90399,0.112372,-1.0,-1.0,53.639,0.585234,1234,1324978 +2,37,insert,67.41,-1.0,-1.0,-1.0,-1.0,44.878,0.605375,1241,1371885 +2,38,search,7062.01,1564.86,3962.01,42.5376,150.66,0.90363,0.112762,-1.0,-1.0,15.782,0.605375,1242,1371885 +2,39,insert,9.348,-1.0,-1.0,-1.0,-1.0,15.499,0.608745,1244,1379335 +2,40,search,6849.8,1562.69,3783.64,43.1409,153.353,0.9032,0.113324,-1.0,-1.0,9.812,0.608745,1244,1379335 +2,41,insert,49.812,-1.0,-1.0,-1.0,-1.0,24.519,0.624458,1247,1413312 +2,42,search,6965.62,1588.12,3854.94,43.4796,153.557,0.90416,0.113393,-1.0,-1.0,9.98,0.624458,1247,1413312 +2,43,insert,9.939,-1.0,-1.0,-1.0,-1.0,12.987,0.627111,1248,1423411 +2,44,search,7206.64,1599.71,4017.09,41.7536,174.271,0.90417,0.113371,-1.0,-1.0,9.694,0.627111,1248,1423411 +2,45,insert,217.246,-1.0,-1.0,-1.0,-1.0,32.8,0.644387,1254,1457559 +2,46,search,6983.44,1617.25,3865.84,43.9745,138.715,0.90527,0.112404,-1.0,-1.0,11.962,0.644387,1254,1457559 +2,47,insert,321.031,-1.0,-1.0,-1.0,-1.0,251.386,0.748311,1288,1688593 +2,48,search,8182.65,1755.36,4854.24,41.8663,193.871,0.90615,0.113797,-1.0,-1.0,103.553,0.748398,1297,1688593 +2,49,insert,49.265,-1.0,-1.0,-1.0,-1.0,26.261,0.762867,1300,1723505 +2,50,search,8180.66,1763.99,4833.36,41.6412,198.474,0.90775,0.112454,-1.0,-1.0,41.852,0.762867,1303,1723505 +2,51,insert,366.805,-1.0,-1.0,-1.0,-1.0,234.55,0.901317,1341,2035040 +2,52,search,8731.97,1950.21,5323.24,41.9332,203.019,0.91007,0.111707,-1.0,-1.0,43.734,0.901342,1346,2035040 +2,53,insert,44.175,-1.0,-1.0,-1.0,-1.0,27.763,0.919668,1349,2078341 +2,54,search,8775.63,1967.64,5295.41,41.81,216.702,0.91003,0.111613,-1.0,-1.0,12.773,0.919668,1349,2078341 +2,55,insert,406.671,-1.0,-1.0,-1.0,-1.0,433.95,1.06736,1405,2399905 +2,56,search,9541.8,2123.65,6015.5,42.1028,237.576,0.91051,0.112346,-1.0,-1.0,146.722,1.06781,1425,2399905 +2,57,insert,26.869,-1.0,-1.0,-1.0,-1.0,24.34,1.07534,1428,2419836 +2,58,search,9463.73,2068.54,5875.04,43.4426,216.588,0.91039,0.112441,-1.0,-1.0,35.542,1.07534,1430,2419836 +2,59,insert,244.893,-1.0,-1.0,-1.0,-1.0,183.822,1.17537,1447,2643083 +2,60,search,9837.96,2126,6181.49,42.6422,222.013,0.90453,0.118971,-1.0,-1.0,47.297,1.17539,1452,2643083 +2,61,insert,13.908,-1.0,-1.0,-1.0,-1.0,11.008,1.18001,1452,2653064 +2,62,search,9524.35,2122.91,5961.1,43.4819,214.458,0.90357,0.119918,-1.0,-1.0,17.606,1.18001,1452,2653064 +2,63,insert,4.286,-1.0,-1.0,-1.0,-1.0,12.346,1.18096,1452,2656118 +2,64,search,10208.1,2125.25,6436.3,41.3493,263.158,0.90378,0.119743,-1.0,-1.0,12.749,1.18096,1452,2656118 +2,65,insert,96.667,-1.0,-1.0,-1.0,-1.0,95.514,1.20953,1469,2723424 +2,66,search,10418.5,2151.43,6605.56,42.0996,268.614,0.90515,0.118597,-1.0,-1.0,11.854,1.20953,1469,2723424 +2,67,insert,58.71,-1.0,-1.0,-1.0,-1.0,105.438,1.23187,1486,2769021 +2,68,search,10125.7,2157.26,6416.3,43.2596,229.024,0.90598,0.11749,-1.0,-1.0,19.032,1.23186,1487,2769021 +2,69,insert,59.606,-1.0,-1.0,-1.0,-1.0,71.285,1.25385,1496,2821777 +2,70,search,10278.2,2173.76,6495.31,42.672,245.153,0.90789,0.115809,-1.0,-1.0,20.076,1.25385,1497,2821777 +2,71,insert,19.627,-1.0,-1.0,-1.0,-1.0,31.304,1.25943,1500,2834921 +2,72,search,10706.9,2182.26,6821.04,41.4029,269.086,0.9087,0.115093,-1.0,-1.0,16.304,1.25943,1501,2834921 +2,73,insert,9.077,-1.0,-1.0,-1.0,-1.0,11.118,1.26323,1501,2842044 +2,74,search,10638.5,2183.98,6752.34,41.6559,255.768,0.90865,0.11511,-1.0,-1.0,12.954,1.26323,1501,2842044 +2,75,insert,27.074,-1.0,-1.0,-1.0,-1.0,27.216,1.26918,1503,2858890 +2,76,search,10464.8,2192.33,6700.52,42.6117,232.054,0.90865,0.114788,-1.0,-1.0,22.55,1.26939,1504,2858890 +2,77,insert,43.909,-1.0,-1.0,-1.0,-1.0,24.497,1.27774,1506,2882818 +2,78,search,10563,2198.01,6786.69,42.3209,237.463,0.90813,0.115319,-1.0,-1.0,12.627,1.27774,1506,2882818 +2,79,insert,447.347,-1.0,-1.0,-1.0,-1.0,18.206,1.30506,1508,2947806 +2,80,search,10217.1,2227.32,6492.74,43.6831,228.57,0.90813,0.115769,-1.0,-1.0,12.153,1.30506,1508,2947806 +2,81,insert,42.973,-1.0,-1.0,-1.0,-1.0,27.051,1.31812,1510,2976895 +2,82,search,10192.8,2239.14,6520.05,43.7236,218.772,0.90903,0.115044,-1.0,-1.0,12.405,1.31812,1510,2976895 +2,83,insert,17.137,-1.0,-1.0,-1.0,-1.0,11.534,1.32351,1510,2990682 +2,84,search,10318.4,2250.37,6637.17,42.7786,213.924,0.90956,0.114619,-1.0,-1.0,11.789,1.32351,1510,2990682 +2,85,insert,37.426,-1.0,-1.0,-1.0,-1.0,11.642,1.33752,1510,3025613 +2,86,search,10074.1,2274.35,6411.84,44.3303,226.063,0.91042,0.114187,-1.0,-1.0,13.788,1.33752,1510,3025613 +2,87,insert,572.751,-1.0,-1.0,-1.0,-1.0,667.37,1.54243,1602,3468632 +2,88,search,11787.3,2421.35,7776.13,43.274,256.83,0.91413,0.110686,-1.0,-1.0,74.753,1.54243,1611,3468632 +2,89,insert,407.292,-1.0,-1.0,-1.0,-1.0,429.672,1.69953,1676,3831692 +2,90,search,10634.8,2542.81,6687.01,54.0863,176.149,0.91866,0.10478,-1.0,-1.0,78.924,1.70011,1684,3831692 +2,91,insert,36.935,-1.0,-1.0,-1.0,-1.0,44.861,1.71202,1689,3864067 +2,92,search,10929.5,2543.26,6772.59,53.6595,174.411,0.91899,0.104408,-1.0,-1.0,13.942,1.71202,1689,3864067 +2,93,insert,276.752,-1.0,-1.0,-1.0,-1.0,281.679,1.81766,1724,4103827 +2,94,search,11260.1,2606.64,7037.48,54.0505,181.927,0.91969,0.103577,-1.0,-1.0,64.073,1.81829,1730,4103827 +2,95,insert,19.084,-1.0,-1.0,-1.0,-1.0,35.414,1.82569,1734,4119898 +2,96,search,11424.2,2597.52,7139.05,53.3747,168.802,0.91974,0.10332,-1.0,-1.0,16.072,1.82569,1734,4119898 +2,97,insert,11.412,-1.0,-1.0,-1.0,-1.0,34.564,1.82998,1737,4129367 +2,98,search,11266.8,2598.66,7014.69,53.7849,178.826,0.91966,0.103387,-1.0,-1.0,17.537,1.82998,1737,4129367 +2,99,insert,10.316,-1.0,-1.0,-1.0,-1.0,23.819,1.83231,1738,4134502 +2,100,search,11401.8,2599.34,7177.21,53.2721,172.405,0.9197,0.103309,-1.0,-1.0,18.116,1.83231,1738,4134502 +2,101,insert,49.351,-1.0,-1.0,-1.0,-1.0,70.102,1.8437,1745,4164482 +2,102,search,11436.7,2601.34,7137.01,54.0505,183.575,0.9198,0.10352,-1.0,-1.0,17.679,1.8437,1745,4164482 +2,103,insert,23.575,-1.0,-1.0,-1.0,-1.0,31.346,1.84911,1747,4178601 +2,104,search,11463.2,2606.7,7144.46,54.2878,186.698,0.9202,0.103087,-1.0,-1.0,26.683,1.84931,1748,4178601 +2,105,insert,12.216,-1.0,-1.0,-1.0,-1.0,32.195,1.85251,1750,4187774 +2,106,search,11372.8,2603.94,7113.22,54.1556,185.488,0.92008,0.103526,-1.0,-1.0,17.916,1.85251,1750,4187774 +2,107,insert,23.481,-1.0,-1.0,-1.0,-1.0,16.803,1.85739,1750,4200109 +2,108,search,11431.4,2608.5,7153.59,53.952,182.358,0.92005,0.103416,-1.0,-1.0,17.439,1.85739,1750,4200109 +2,109,insert,481.08,-1.0,-1.0,-1.0,-1.0,547.819,2.01829,1823,4557867 +2,110,search,12200.5,2688.19,7644.45,53.7306,191.237,0.92215,0.102318,-1.0,-1.0,88.391,2.01923,1829,4557867 +2,111,insert,30.535,-1.0,-1.0,-1.0,-1.0,42.292,2.03045,1832,4587252 +2,112,search,12178.3,2692.28,7671.85,54.0805,193.848,0.92241,0.102185,-1.0,-1.0,29.44,2.03045,1833,4587252 +2,113,insert,14.32,-1.0,-1.0,-1.0,-1.0,51.794,2.03508,1837,4600056 +2,114,search,12406.5,2688.98,7851.06,53.5583,200.165,0.92256,0.102187,-1.0,-1.0,22.852,2.03508,1837,4600056 +2,115,insert,50.323,-1.0,-1.0,-1.0,-1.0,65.709,2.04552,1843,4627422 +2,116,search,12383.6,2693.51,7823.61,53.8058,206.31,0.92329,0.101976,-1.0,-1.0,22.305,2.04552,1843,4627422 +2,117,insert,12.132,-1.0,-1.0,-1.0,-1.0,21.024,2.0479,1843,4639292 +2,118,search,11826.3,2699.04,7294.55,56.9307,221.395,0.92321,0.101882,-1.0,-1.0,21.964,2.0479,1843,4639292 +2,119,insert,4.109,-1.0,-1.0,-1.0,-1.0,20.943,2.04896,1843,4643423 +2,120,search,11797.5,2701.16,7271.53,57.0946,225.91,0.92325,0.101889,-1.0,-1.0,22.022,2.04896,1843,4643423 +2,121,insert,26.669,-1.0,-1.0,-1.0,-1.0,55.5,2.05586,1847,4657252 +2,122,search,11847.6,2703.08,7273.14,57.1211,223.5,0.92376,0.101188,-1.0,-1.0,23.131,2.05586,1847,4657252 +2,123,insert,403.119,-1.0,-1.0,-1.0,-1.0,476.935,2.18421,1895,4938477 +2,124,search,12439.8,2750.45,7773.38,56.3693,214.242,0.9238,0.101873,-1.0,-1.0,145.141,2.18469,1905,4938477 +2,125,insert,67.431,-1.0,-1.0,-1.0,-1.0,59.486,2.20267,1911,4980492 +2,126,search,12460,2738.61,7752.11,56.6027,228.182,0.92372,0.102101,-1.0,-1.0,80.723,2.20268,1916,4980492 +2,127,insert,64.02,-1.0,-1.0,-1.0,-1.0,71.923,2.22396,1924,5030515 +2,128,search,12574.4,2755.95,7823.46,56.7546,232.915,0.92492,0.101283,-1.0,-1.0,31.854,2.22396,1925,5030515 +2,129,delete,23.453,-1.0,-1.0,-1.0,-1.0,95.556,2.22208,1893,5009391 +2,130,search,12276.7,2740.92,7605.33,57.0149,231.267,0.92364,0.102078,-1.0,-1.0,25.223,2.22208,1893,5009391 +2,131,delete,7.058,-1.0,-1.0,-1.0,-1.0,24.654,2.22208,1893,5004093 +2,132,search,12313.6,2738.6,7676.58,56.8081,221.224,0.92357,0.102063,-1.0,-1.0,25.022,2.22208,1893,5004093 +2,133,delete,13.181,-1.0,-1.0,-1.0,-1.0,23.35,2.22208,1893,4991787 +2,134,search,12219.3,2725.52,7563.12,56.82,224.397,0.92347,0.102221,-1.0,-1.0,24.682,2.22208,1893,4991787 +2,135,delete,18.699,-1.0,-1.0,-1.0,-1.0,62.36,2.21919,1890,4974857 +2,136,search,12165.2,2718.43,7498.65,56.8339,217.357,0.9236,0.102087,-1.0,-1.0,27.633,2.21919,1890,4974857 +2,137,delete,8.16,-1.0,-1.0,-1.0,-1.0,25.259,2.21919,1890,4971386 +2,138,search,12211.2,2715.9,7537.85,57.0112,226.076,0.92344,0.102222,-1.0,-1.0,26.394,2.21919,1890,4971386 +2,139,delete,17.729,-1.0,-1.0,-1.0,-1.0,24.645,2.21919,1890,4963487 +2,140,search,12199.9,2709.86,7548.66,56.9793,224.968,0.92328,0.102168,-1.0,-1.0,25.179,2.21919,1890,4963487 +2,141,delete,37.799,-1.0,-1.0,-1.0,-1.0,105.777,2.21347,1883,4941830 +2,142,search,12218.2,2702.88,7570.19,56.7141,231.637,0.92312,0.102346,-1.0,-1.0,24.942,2.21347,1883,4941830 +2,143,delete,25.64,-1.0,-1.0,-1.0,-1.0,84.257,2.21031,1880,4925657 +2,144,search,12168.4,2698.33,7520.38,56.6389,228.274,0.92321,0.102264,-1.0,-1.0,25.932,2.21031,1880,4925657 +2,145,delete,4.028,-1.0,-1.0,-1.0,-1.0,35.832,2.2095,1878,4922686 +2,146,search,12100.9,2698.19,7463.31,56.7152,230.021,0.92293,0.102602,-1.0,-1.0,24.909,2.2095,1878,4922686 +2,147,delete,11.364,-1.0,-1.0,-1.0,-1.0,24.055,2.2095,1878,4913636 +2,148,search,12065,2691.18,7358.57,56.7867,227.498,0.92289,0.102605,-1.0,-1.0,26.303,2.2095,1878,4913636 +2,149,delete,239.812,-1.0,-1.0,-1.0,-1.0,1080.75,2.13338,1799,4717250 +2,150,search,11539.2,2687.18,7106.93,56.6346,216.873,0.92205,0.103563,-1.0,-1.0,60.656,2.13392,1803,4717250 +2,151,delete,180.977,-1.0,-1.0,-1.0,-1.0,1079.82,2.06492,1724,4560269 +4,2,search,2566.29,37.3142,238.232,4.5843,70.2033,0.8551,0.130106,-1.0,-1.0,7.675,0.0184881,1000,38806 +4,3,insert,10.248,-1.0,-1.0,-1.0,-1.0,6.376,0.0226644,1000,49334 +4,4,search,2802.96,65.7492,310.22,4.85697,71.6462,0.86604,0.12886,-1.0,-1.0,7.211,0.0226644,1000,49334 +4,5,insert,27.002,-1.0,-1.0,-1.0,-1.0,169.617,0.0330953,997,73557 +4,6,search,2891.25,191.294,470.737,7.59158,65.4699,0.92386,0.105036,-1.0,-1.0,124.65,0.0330953,997,73557 +4,7,insert,28.335,-1.0,-1.0,-1.0,-1.0,102.482,0.0427388,997,95766 +4,8,search,2884.2,246.513,521.621,9.25031,58.3556,0.92559,0.103709,-1.0,-1.0,83.136,0.0429143,998,95766 +4,9,insert,4.117,-1.0,-1.0,-1.0,-1.0,74.836,0.0447637,998,100025 +4,10,search,2960.38,257.725,558.203,8.99203,65.3267,0.92806,0.0998639,-1.0,-1.0,76.171,0.0447637,998,100025 +4,11,insert,10.895,-1.0,-1.0,-1.0,-1.0,82.004,0.0496597,999,111417 +4,12,search,3008.08,302.85,616.17,9.51679,65.6407,0.92812,0.10013,-1.0,-1.0,19.381,0.0500379,1000,111417 +4,13,insert,24.477,-1.0,-1.0,-1.0,-1.0,6.841,0.0611825,1000,137139 +4,14,search,3007.5,345.115,605.527,10.4247,65.2688,0.92499,0.10227,-1.0,-1.0,18.886,0.0611939,1002,137139 +4,15,insert,22.595,-1.0,-1.0,-1.0,-1.0,6.822,0.0699043,1002,156710 +4,16,search,3129.95,380.852,705.22,10.0784,67.8908,0.92274,0.103392,-1.0,-1.0,7.096,0.0699043,1002,156710 +4,17,insert,5.045,-1.0,-1.0,-1.0,-1.0,6.559,0.0715465,1002,161773 +4,18,search,3133.31,400.814,709.681,10.4246,68.172,0.9242,0.102652,-1.0,-1.0,7.241,0.0715465,1002,161773 +4,19,insert,36.729,-1.0,-1.0,-1.0,-1.0,6.764,0.0781136,1002,177161 +4,20,search,3066.15,446.577,730.09,11.5957,59.8781,0.92842,0.0993882,-1.0,-1.0,7.178,0.0781136,1002,177161 +4,21,insert,335.286,-1.0,-1.0,-1.0,-1.0,95.322,0.199618,1017,448898 +4,22,search,3925.14,992.028,1502.96,13.0063,85.0196,0.92146,0.100464,-1.0,-1.0,14.521,0.199617,1018,448898 +4,23,insert,388.222,-1.0,-1.0,-1.0,-1.0,238.123,0.327875,1050,733493 +4,24,search,4549.79,1419.79,2042.95,14.4904,101.434,0.91739,0.102601,-1.0,-1.0,72.345,0.327872,1061,733493 +4,25,insert,39.18,-1.0,-1.0,-1.0,-1.0,24.355,0.3443,1064,777443 +4,26,search,4580.95,1421.97,2011.93,15.2209,100.163,0.91738,0.102935,-1.0,-1.0,9.154,0.3443,1064,777443 +4,27,insert,40.667,-1.0,-1.0,-1.0,-1.0,16.257,0.356074,1065,805394 +4,28,search,4979.88,1450.09,2379.78,13.2298,105.818,0.91789,0.102706,-1.0,-1.0,9.619,0.356074,1065,805394 +4,29,insert,96.239,-1.0,-1.0,-1.0,-1.0,42.047,0.383832,1069,866391 +4,30,search,4914.06,1527.32,2301.64,14.4741,103.109,0.91956,0.10247,-1.0,-1.0,22.783,0.383831,1071,866391 +4,31,insert,487.495,-1.0,-1.0,-1.0,-1.0,369.243,0.55599,1120,1239816 +4,32,search,5891.7,1853.05,3135.35,13.634,130.313,0.91241,0.108427,-1.0,-1.0,89.197,0.556021,1126,1239816 +4,33,insert,56.137,-1.0,-1.0,-1.0,-1.0,13.991,0.576749,1127,1291211 +4,34,search,5924.86,1869.03,3018.52,14.605,130.563,0.91202,0.108497,-1.0,-1.0,62.804,0.576765,1131,1291211 +4,35,insert,29.13,-1.0,-1.0,-1.0,-1.0,24.562,0.58573,1134,1324978 +4,36,search,5783.45,1910.03,3001.87,14.6358,128.274,0.91335,0.107448,-1.0,-1.0,33.429,0.58573,1137,1324978 +4,37,insert,50.629,-1.0,-1.0,-1.0,-1.0,41.728,0.605563,1142,1371885 +4,38,search,5820.57,1923.15,3000.79,15.1064,128.272,0.9123,0.108101,-1.0,-1.0,21.971,0.605563,1143,1371885 +4,39,insert,12.346,-1.0,-1.0,-1.0,-1.0,8.701,0.608722,1143,1379335 +4,40,search,5850.56,1929.73,3014.37,14.8093,123.809,0.91247,0.108415,-1.0,-1.0,9.303,0.608722,1143,1379335 +4,41,insert,45.651,-1.0,-1.0,-1.0,-1.0,30.85,0.625451,1147,1413312 +4,42,search,6016.92,1949.46,3183.06,15.0029,133.109,0.91313,0.108296,-1.0,-1.0,10.389,0.625451,1147,1413312 +4,43,insert,16.623,-1.0,-1.0,-1.0,-1.0,33.743,0.630251,1151,1423411 +4,44,search,6106.34,1945.45,3272.22,14.3544,131.016,0.91279,0.107714,-1.0,-1.0,9.866,0.630251,1151,1423411 +4,45,insert,230.086,-1.0,-1.0,-1.0,-1.0,57.726,0.646294,1159,1457559 +4,46,search,6210.26,1946.6,3345.54,14.0433,135.26,0.91244,0.107128,-1.0,-1.0,9.225,0.646294,1159,1457559 +4,47,insert,288.891,-1.0,-1.0,-1.0,-1.0,261.122,0.750285,1184,1688593 +4,48,search,6648.85,2095.94,3694.28,14.1521,157.026,0.9128,0.108191,-1.0,-1.0,75.253,0.750284,1190,1688593 +4,49,insert,37.925,-1.0,-1.0,-1.0,-1.0,29.338,0.7648,1193,1723505 +4,50,search,6709.54,2104.28,3744.55,14.011,157.827,0.91347,0.108022,-1.0,-1.0,33.684,0.7648,1196,1723505 +4,51,insert,326.457,-1.0,-1.0,-1.0,-1.0,240.729,0.902044,1229,2035040 +4,52,search,7060.44,2310.82,4014.15,14.7269,162.456,0.91649,0.106604,-1.0,-1.0,34.789,0.902043,1233,2035040 +4,53,insert,41.155,-1.0,-1.0,-1.0,-1.0,60.449,0.919696,1241,2078341 +4,54,search,7130.09,2318.11,4021.39,14.7339,166.892,0.91654,0.106798,-1.0,-1.0,10.362,0.919696,1241,2078341 +4,55,insert,346.436,-1.0,-1.0,-1.0,-1.0,535.517,1.06898,1301,2399905 +4,56,search,8106.35,2442.15,4532.92,14.8157,195.781,0.91505,0.109318,-1.0,-1.0,101.978,1.06898,1313,2399905 +4,57,insert,27.644,-1.0,-1.0,-1.0,-1.0,32.115,1.07747,1317,2419836 +4,58,search,8093.38,2399.77,4716.97,14.6695,200.695,0.914,0.110185,-1.0,-1.0,35.86,1.07748,1319,2419836 +4,59,insert,273.915,-1.0,-1.0,-1.0,-1.0,201.44,1.17784,1333,2643083 +4,60,search,8324.58,2466.32,4909.67,14.3752,198.045,0.908,0.116845,-1.0,-1.0,72.026,1.17812,1337,2643083 +4,61,insert,11.371,-1.0,-1.0,-1.0,-1.0,9.375,1.18161,1337,2653064 +4,62,search,8169.68,2468.87,4798.47,14.4991,195.809,0.90816,0.11719,-1.0,-1.0,18.106,1.18161,1338,2653064 +4,63,insert,4.351,-1.0,-1.0,-1.0,-1.0,8.93,1.18318,1338,2656118 +4,64,search,8019.86,2468.07,4642.3,14.8322,196.218,0.90806,0.117376,-1.0,-1.0,11.146,1.18318,1338,2656118 +4,65,insert,94.745,-1.0,-1.0,-1.0,-1.0,142.695,1.21176,1356,2723424 +4,66,search,8139.33,2483.74,4717.94,14.9903,201.225,0.90904,0.115995,-1.0,-1.0,11.513,1.21176,1356,2723424 +4,67,insert,60.847,-1.0,-1.0,-1.0,-1.0,107.753,1.23233,1370,2769021 +4,68,search,8367.51,2481.38,4908.01,14.9139,209.155,0.90964,0.115255,-1.0,-1.0,23.19,1.23233,1372,2769021 +4,69,insert,59.313,-1.0,-1.0,-1.0,-1.0,92.026,1.25357,1384,2821777 +4,70,search,8458.36,2489.87,4961.7,14.8529,210.198,0.9107,0.114342,-1.0,-1.0,10.64,1.25357,1384,2821777 +4,71,insert,17.965,-1.0,-1.0,-1.0,-1.0,29.962,1.25907,1387,2834921 +4,72,search,8663.89,2495.5,5160.22,14.3619,207.755,0.91115,0.113886,-1.0,-1.0,16.292,1.25907,1388,2834921 +4,73,insert,6.608,-1.0,-1.0,-1.0,-1.0,16.627,1.26136,1389,2842044 +4,74,search,8342.94,2495.79,4835.3,14.9625,202.948,0.91106,0.114024,-1.0,-1.0,10.41,1.26136,1389,2842044 +4,75,insert,20.488,-1.0,-1.0,-1.0,-1.0,26.793,1.26775,1392,2858890 +4,76,search,8235.45,2500.82,4402.1,16.0388,189.168,0.91078,0.114212,-1.0,-1.0,10.949,1.26775,1392,2858890 +4,77,insert,35.709,-1.0,-1.0,-1.0,-1.0,16.585,1.2782,1393,2882818 +4,78,search,8336.71,2511.85,4563.78,15.2496,206.434,0.91042,0.114581,-1.0,-1.0,11.17,1.2782,1393,2882818 +4,79,insert,498.6,-1.0,-1.0,-1.0,-1.0,22.095,1.30497,1395,2947806 +4,80,search,8699.87,2547.39,4868.51,15.3436,207.687,0.91073,0.114524,-1.0,-1.0,10.329,1.30497,1395,2947806 +4,81,insert,37.258,-1.0,-1.0,-1.0,-1.0,37.49,1.31772,1398,2976895 +4,82,search,9031.45,2560.11,5346.9,14.5212,211.305,0.91186,0.113613,-1.0,-1.0,10.785,1.31772,1398,2976895 +4,83,insert,17.215,-1.0,-1.0,-1.0,-1.0,29.255,1.32397,1401,2990682 +4,84,search,8698.64,2564.17,5160.24,14.926,217.952,0.91213,0.113052,-1.0,-1.0,27.503,1.3241,1403,2990682 +4,85,insert,40.366,-1.0,-1.0,-1.0,-1.0,43.901,1.3388,1408,3025613 +4,86,search,7992.03,2561.48,4531.81,16.48,165.321,0.91251,0.113056,-1.0,-1.0,10.888,1.3388,1408,3025613 +4,87,insert,518.285,-1.0,-1.0,-1.0,-1.0,620.42,1.54234,1484,3468632 +4,88,search,8905.44,2747.53,5102.53,16.419,187.805,0.91575,0.109845,-1.0,-1.0,104.286,1.54234,1494,3468632 +4,89,insert,386.155,-1.0,-1.0,-1.0,-1.0,571.522,1.70706,1572,3831692 +4,90,search,9294.62,2803.08,5407.93,16.4803,214.279,0.91957,0.105115,-1.0,-1.0,78.412,1.70718,1582,3831692 +4,91,insert,29.712,-1.0,-1.0,-1.0,-1.0,37.975,1.71776,1586,3864067 +4,92,search,9646,2794.12,5471.13,16.4653,211.152,0.91985,0.104892,-1.0,-1.0,13.075,1.71776,1586,3864067 +4,93,insert,291.266,-1.0,-1.0,-1.0,-1.0,298.629,1.82319,1626,4103827 +4,94,search,9950.11,2834.38,5768.71,16.5091,216.605,0.91994,0.103918,-1.0,-1.0,37.678,1.82319,1629,4103827 +4,95,insert,19.15,-1.0,-1.0,-1.0,-1.0,38.03,1.82947,1633,4119898 +4,96,search,10089.6,2833.05,5878.14,16.3276,215.884,0.92017,0.104034,-1.0,-1.0,22.873,1.82979,1634,4119898 +4,97,insert,10.365,-1.0,-1.0,-1.0,-1.0,24.355,1.83317,1636,4129367 +4,98,search,9871.05,2833.05,5837.05,16.4445,216.945,0.92051,0.103658,-1.0,-1.0,13.189,1.83317,1636,4129367 +4,99,insert,7.157,-1.0,-1.0,-1.0,-1.0,11.326,1.83523,1636,4134502 +4,100,search,9523.71,2837.2,5517.75,17.5498,199.69,0.9205,0.10376,-1.0,-1.0,12.735,1.83523,1636,4134502 +4,101,insert,43.891,-1.0,-1.0,-1.0,-1.0,51.902,1.84728,1641,4164482 +4,102,search,9989.25,2847.51,5920.1,16.2491,218.19,0.92097,0.103232,-1.0,-1.0,12.341,1.84728,1641,4164482 +4,103,insert,20.393,-1.0,-1.0,-1.0,-1.0,26.827,1.85411,1643,4178601 +4,104,search,9923.56,2852.69,5834.73,16.3525,217.987,0.92096,0.103366,-1.0,-1.0,13.223,1.85411,1643,4178601 +4,105,insert,11.448,-1.0,-1.0,-1.0,-1.0,38.715,1.85785,1646,4187774 +4,106,search,10015.8,2849.58,5909.68,16.3511,222.718,0.92068,0.103931,-1.0,-1.0,13.065,1.85785,1646,4187774 +4,107,insert,26.991,-1.0,-1.0,-1.0,-1.0,32.367,1.86437,1648,4200109 +4,108,search,10140.6,2853.16,6040.07,16.1953,221.267,0.92098,0.103761,-1.0,-1.0,23.594,1.8645,1649,4200109 +4,109,insert,500.383,-1.0,-1.0,-1.0,-1.0,553.049,2.01995,1719,4557867 +4,110,search,11118.5,2937.63,6488.63,16.2248,227.182,0.92273,0.102313,-1.0,-1.0,80.634,2.02024,1726,4557867 +4,111,insert,37.255,-1.0,-1.0,-1.0,-1.0,64.063,2.03314,1733,4587252 +4,112,search,10789.6,2928.15,6518.6,16.1689,227.581,0.92292,0.102371,-1.0,-1.0,15.758,2.03314,1733,4587252 +4,113,insert,14.985,-1.0,-1.0,-1.0,-1.0,30.651,2.03841,1735,4600056 +4,114,search,10672.8,2932.74,6345.94,16.6535,234.389,0.92329,0.10226,-1.0,-1.0,15.781,2.03841,1735,4600056 +4,115,insert,34.543,-1.0,-1.0,-1.0,-1.0,48.59,2.04878,1740,4627422 +4,116,search,10667.8,2941.48,6337.99,16.5898,228.903,0.92406,0.101699,-1.0,-1.0,15.529,2.04878,1740,4627422 +4,117,insert,14.421,-1.0,-1.0,-1.0,-1.0,27.056,2.05381,1742,4639292 +4,118,search,10633.7,2943.1,6290.66,16.7204,232.647,0.9239,0.10191,-1.0,-1.0,16.512,2.05381,1742,4639292 +4,119,insert,5.823,-1.0,-1.0,-1.0,-1.0,14.184,2.05555,1742,4643423 +4,120,search,10984.2,2945.4,6413.99,16.5301,241.605,0.92396,0.101984,-1.0,-1.0,15.87,2.05555,1742,4643423 +4,121,insert,19.58,-1.0,-1.0,-1.0,-1.0,47.02,2.0614,1746,4657252 +4,122,search,10428.3,2942.02,6141.82,17.4511,227.605,0.92389,0.102066,-1.0,-1.0,16.422,2.0614,1746,4657252 +4,123,insert,378.145,-1.0,-1.0,-1.0,-1.0,471.747,2.18998,1792,4938477 +4,124,search,11252.7,2991.21,6737.42,16.4344,245.472,0.92413,0.102572,-1.0,-1.0,152.307,2.19049,1801,4938477 +4,125,insert,64.19,-1.0,-1.0,-1.0,-1.0,65.3,2.20863,1808,4980492 +4,126,search,11263,2981.27,6767.18,16.5973,249.533,0.92484,0.10241,-1.0,-1.0,86.617,2.20882,1812,4980492 +4,127,insert,66.2,-1.0,-1.0,-1.0,-1.0,102.143,2.23154,1825,5030515 +4,128,search,11329,2978.53,6797.47,16.584,248.705,0.92532,0.102263,-1.0,-1.0,64.464,2.23154,1828,5030515 +4,129,delete,17.666,-1.0,-1.0,-1.0,-1.0,85.275,2.22982,1798,5009391 +4,130,search,11546.2,2962.66,6576.32,16.6187,241.732,0.92432,0.10286,-1.0,-1.0,38.741,2.22982,1799,5009391 +4,131,delete,9.418,-1.0,-1.0,-1.0,-1.0,20.439,2.22982,1799,5004093 +4,132,search,11620.6,2959.46,6651.79,16.4689,243.702,0.92428,0.102898,-1.0,-1.0,21.087,2.22982,1799,5004093 +4,133,delete,20.651,-1.0,-1.0,-1.0,-1.0,33.743,2.22833,1798,4991787 +4,134,search,11621.5,2947.87,6666.93,16.5131,240.319,0.92416,0.102938,-1.0,-1.0,21.043,2.22833,1798,4991787 +4,135,delete,25.116,-1.0,-1.0,-1.0,-1.0,41.128,2.22658,1796,4974857 +4,136,search,11656.5,2938.13,6702.51,16.4483,240.048,0.92428,0.102694,-1.0,-1.0,20.828,2.22658,1796,4974857 +4,137,delete,6.089,-1.0,-1.0,-1.0,-1.0,19.502,2.22658,1796,4971386 +4,138,search,11673.9,2935.15,6731.16,16.3914,242.778,0.92422,0.10267,-1.0,-1.0,20.179,2.22658,1796,4971386 +4,139,delete,11.98,-1.0,-1.0,-1.0,-1.0,21.772,2.22658,1796,4963487 +4,140,search,11871.4,2928.25,6648.24,16.4898,235.353,0.92419,0.102669,-1.0,-1.0,20.558,2.22658,1796,4963487 +4,141,delete,25.619,-1.0,-1.0,-1.0,-1.0,58.409,2.22301,1791,4941830 +4,142,search,11435.2,2917.42,6490.98,16.7802,224.737,0.92395,0.103092,-1.0,-1.0,19.761,2.22301,1791,4941830 +4,143,delete,17.216,-1.0,-1.0,-1.0,-1.0,60.039,2.21927,1788,4925657 +4,144,search,11686.7,2911.04,6482.81,16.4551,233.184,0.92397,0.103139,-1.0,-1.0,21.355,2.21927,1788,4925657 +4,145,delete,6.865,-1.0,-1.0,-1.0,-1.0,26.229,2.21881,1787,4922686 +4,146,search,11688.2,2910.09,6453.07,16.9285,217.503,0.92379,0.103392,-1.0,-1.0,20.576,2.21881,1787,4922686 +4,147,delete,13.426,-1.0,-1.0,-1.0,-1.0,19.767,2.21881,1787,4913636 +4,148,search,11472.7,2902.45,6543.42,16.8217,214.832,0.92375,0.103449,-1.0,-1.0,21.242,2.21881,1787,4913636 +4,149,delete,243.73,-1.0,-1.0,-1.0,-1.0,1072.59,2.1391,1707,4717250 +4,150,search,10855.4,2904.5,6167.59,16.9427,212.359,0.92255,0.104352,-1.0,-1.0,52.93,2.14012,1711,4717250 +4,151,delete,162.667,-1.0,-1.0,-1.0,-1.0,938.761,2.07097,1640,4560269 +8,2,search,2872.91,37.32,332.077,2.04143,129.967,0.8551,0.130106,-1.0,-1.0,7.463,0.0184881,1000,38806 +8,3,insert,11.925,-1.0,-1.0,-1.0,-1.0,14.718,0.0226681,998,49334 +8,4,search,2731.74,66.6883,222.064,3.8079,93.4078,0.86613,0.128797,-1.0,-1.0,13.162,0.0226611,997,49334 +8,5,insert,25.182,-1.0,-1.0,-1.0,-1.0,174.253,0.0329766,993,73557 +8,6,search,2646.1,193.295,325.122,6.06004,56.0027,0.92433,0.104255,-1.0,-1.0,111.805,0.0330819,995,73557 +8,7,insert,31.91,-1.0,-1.0,-1.0,-1.0,104.099,0.0426107,995,95766 +8,8,search,2745.52,245.53,386.325,6.35336,69.1233,0.92582,0.103612,-1.0,-1.0,90.744,0.0428012,997,95766 +8,9,insert,4.544,-1.0,-1.0,-1.0,-1.0,78.425,0.0445267,997,100025 +8,10,search,2754.37,254.798,390.632,6.54646,69.2487,0.92703,0.100737,-1.0,-1.0,79.781,0.0445267,997,100025 +8,11,insert,13.651,-1.0,-1.0,-1.0,-1.0,80.228,0.0497772,997,111417 +8,12,search,2791.65,301.907,431.768,6.96195,65.594,0.92784,0.100473,-1.0,-1.0,18.801,0.049818,998,111417 +8,13,insert,27.375,-1.0,-1.0,-1.0,-1.0,7.23,0.0610837,998,137139 +8,14,search,2805.39,343.746,454.958,7.05071,73.8489,0.92376,0.103456,-1.0,-1.0,18.362,0.0610898,1000,137139 +8,15,insert,23.186,-1.0,-1.0,-1.0,-1.0,7.083,0.0698161,1000,156710 +8,16,search,2852.72,379.776,499.958,7.28536,73.1593,0.92221,0.104397,-1.0,-1.0,7.549,0.0698161,1000,156710 +8,17,insert,6.055,-1.0,-1.0,-1.0,-1.0,14.957,0.07189,1002,161773 +8,18,search,2917.57,396.368,526.687,7.39429,72.1474,0.92306,0.103575,-1.0,-1.0,8.022,0.07189,1002,161773 +8,19,insert,42.115,-1.0,-1.0,-1.0,-1.0,7.379,0.0785567,1002,177161 +8,20,search,2906.16,442.002,550.537,7.67054,72.8881,0.9275,0.0997837,-1.0,-1.0,7.628,0.0785567,1002,177161 +8,21,insert,386.86,-1.0,-1.0,-1.0,-1.0,122.182,0.199676,1026,448898 +8,22,search,3342.61,946.371,1024.64,9.31362,72.7231,0.91757,0.102984,-1.0,-1.0,15.438,0.199676,1027,448898 +8,23,insert,404.437,-1.0,-1.0,-1.0,-1.0,268.248,0.328139,1072,733493 +8,24,search,3934.89,1317.55,1476.01,9.73431,94.8916,0.9124,0.10614,-1.0,-1.0,66.474,0.328138,1081,733493 +8,25,insert,46.237,-1.0,-1.0,-1.0,-1.0,26.342,0.345341,1084,777443 +8,26,search,3929,1327.77,1441.51,10.1069,88.0319,0.91363,0.105454,-1.0,-1.0,24.088,0.345427,1086,777443 +8,27,insert,39.192,-1.0,-1.0,-1.0,-1.0,19.588,0.35769,1087,805394 +8,28,search,4020.02,1348.37,1519.02,9.86643,88.7745,0.91437,0.105238,-1.0,-1.0,17.875,0.357691,1088,805394 +8,29,insert,83.741,-1.0,-1.0,-1.0,-1.0,52.794,0.384731,1093,866391 +8,30,search,4074.75,1422.53,1559.58,10.0372,88.9072,0.91596,0.104891,-1.0,-1.0,28.852,0.384731,1095,866391 +8,31,insert,492.946,-1.0,-1.0,-1.0,-1.0,359.53,0.55411,1150,1239816 +8,32,search,4691.21,1731.94,2029.16,10.0925,110.475,0.90942,0.109454,-1.0,-1.0,91.991,0.554467,1156,1239816 +8,33,insert,55.474,-1.0,-1.0,-1.0,-1.0,31.17,0.574903,1161,1291211 +8,34,search,4529.2,1734.06,1857.56,10.9023,99.4259,0.90938,0.108679,-1.0,-1.0,60.736,0.574919,1165,1291211 +8,35,insert,36.462,-1.0,-1.0,-1.0,-1.0,33.936,0.587117,1170,1324978 +8,36,search,4537.59,1764.32,1856.06,11.1478,93.7796,0.90946,0.108328,-1.0,-1.0,27.319,0.587121,1172,1324978 +8,37,insert,53.207,-1.0,-1.0,-1.0,-1.0,33.071,0.607443,1176,1371885 +8,38,search,4696.47,1786.54,1980.43,10.676,100.323,0.90903,0.108624,-1.0,-1.0,9.177,0.607443,1176,1371885 +8,39,insert,10.236,-1.0,-1.0,-1.0,-1.0,8.713,0.611104,1176,1379335 +8,40,search,4882.73,1795.24,2139.18,10.1108,114.046,0.90955,0.108391,-1.0,-1.0,11.57,0.611104,1176,1379335 +8,41,insert,62.94,-1.0,-1.0,-1.0,-1.0,43.096,0.625089,1181,1413312 +8,42,search,4985.02,1816.16,2248.28,10.1237,119.784,0.91024,0.108455,-1.0,-1.0,9.786,0.625089,1181,1413312 +8,43,insert,12.549,-1.0,-1.0,-1.0,-1.0,14.971,0.628586,1182,1423411 +8,44,search,4885.57,1828.88,2135.91,10.5541,110.344,0.91039,0.108723,-1.0,-1.0,9.625,0.628586,1182,1423411 +8,45,insert,236.554,-1.0,-1.0,-1.0,-1.0,19.238,0.643369,1184,1457559 +8,46,search,4820.59,1857.91,2108.99,10.9321,104.578,0.91083,0.107889,-1.0,-1.0,10.151,0.643369,1184,1457559 +8,47,insert,315.558,-1.0,-1.0,-1.0,-1.0,266.957,0.748453,1214,1688593 +8,48,search,5276.87,2008.65,2425.74,10.5893,125.096,0.91184,0.109063,-1.0,-1.0,112.529,0.749047,1224,1688593 +8,49,insert,46.191,-1.0,-1.0,-1.0,-1.0,44.844,0.764861,1229,1723505 +8,50,search,5362.73,1997.34,2493.34,10.2681,125.844,0.91226,0.108495,-1.0,-1.0,42.11,0.764861,1232,1723505 +8,51,insert,360.349,-1.0,-1.0,-1.0,-1.0,264.065,0.90579,1270,2035040 +8,52,search,5582.88,2179.53,2624.75,10.859,136.152,0.91427,0.10776,-1.0,-1.0,66.725,0.905862,1278,2035040 +8,53,insert,42.018,-1.0,-1.0,-1.0,-1.0,34.363,0.922294,1281,2078341 +8,54,search,5731.04,2189.53,2747.2,10.6508,137.392,0.91436,0.10751,-1.0,-1.0,17.354,0.922312,1282,2078341 +8,55,insert,361.98,-1.0,-1.0,-1.0,-1.0,441.474,1.07139,1331,2399905 +8,56,search,6414.05,2369.55,3285.77,10.242,165.657,0.91483,0.108346,-1.0,-1.0,115.847,1.07154,1345,2399905 +8,57,insert,22.422,-1.0,-1.0,-1.0,-1.0,15.79,1.07951,1346,2419836 +8,58,search,6094.31,2332.43,2963.42,11.0179,146.059,0.91338,0.109028,-1.0,-1.0,46.279,1.07952,1350,2419836 +8,59,insert,229.794,-1.0,-1.0,-1.0,-1.0,219.048,1.17622,1370,2643083 +8,60,search,6307.53,2368.4,3103.57,10.8425,154.444,0.90767,0.11597,-1.0,-1.0,51.574,1.17659,1376,2643083 +8,61,insert,11.848,-1.0,-1.0,-1.0,-1.0,15.858,1.18143,1377,2653064 +8,62,search,6480.86,2362.07,3221.66,10.6086,160.225,0.90785,0.115693,-1.0,-1.0,12.238,1.18143,1377,2653064 +8,63,insert,4.678,-1.0,-1.0,-1.0,-1.0,19.182,1.18228,1378,2656118 +8,64,search,6476.85,2360.66,3234.55,11.0404,161.23,0.90783,0.11549,-1.0,-1.0,12.836,1.18228,1378,2656118 +8,65,insert,101.278,-1.0,-1.0,-1.0,-1.0,101.775,1.20876,1393,2723424 +8,66,search,6533.26,2391.13,3255.78,10.9442,167.971,0.90889,0.114082,-1.0,-1.0,11.982,1.20876,1393,2723424 +8,67,insert,52.79,-1.0,-1.0,-1.0,-1.0,88.826,1.22792,1405,2769021 +8,68,search,6718.23,2401.6,3401.14,10.7149,172.558,0.90971,0.113439,-1.0,-1.0,16.682,1.22797,1406,2769021 +8,69,insert,55.935,-1.0,-1.0,-1.0,-1.0,61.883,1.24984,1414,2821777 +8,70,search,6883.22,2423.2,3523.6,10.4966,178.704,0.91105,0.112088,-1.0,-1.0,22.917,1.24986,1416,2821777 +8,71,insert,16.738,-1.0,-1.0,-1.0,-1.0,43.313,1.25527,1421,2834921 +8,72,search,6587.63,2418.81,3275.29,11.311,158.933,0.91137,0.112008,-1.0,-1.0,17.293,1.25527,1422,2834921 +8,73,insert,9.732,-1.0,-1.0,-1.0,-1.0,23.061,1.25869,1424,2842044 +8,74,search,6227.22,2415.78,2960.2,12.0174,134.286,0.91118,0.112292,-1.0,-1.0,11.398,1.25869,1424,2842044 +8,75,insert,23.81,-1.0,-1.0,-1.0,-1.0,10.98,1.26632,1424,2858890 +8,76,search,6909.47,2430.04,3528.52,10.3209,177.169,0.91155,0.112034,-1.0,-1.0,13.498,1.26632,1424,2858890 +8,77,insert,49.301,-1.0,-1.0,-1.0,-1.0,11.989,1.27694,1424,2882818 +8,78,search,6747.93,2443.85,3395.28,10.7852,170.274,0.9113,0.112371,-1.0,-1.0,12.123,1.27694,1424,2882818 +8,79,insert,523.23,-1.0,-1.0,-1.0,-1.0,30.404,1.30532,1427,2947806 +8,80,search,6991.46,2472.74,3609.79,10.757,184.848,0.9113,0.11246,-1.0,-1.0,11.632,1.30532,1427,2947806 +8,81,insert,45.808,-1.0,-1.0,-1.0,-1.0,67.811,1.32034,1434,2976895 +8,82,search,6948.85,2478,3549.45,10.7966,183.056,0.9124,0.112079,-1.0,-1.0,11.261,1.32034,1434,2976895 +8,83,insert,17.817,-1.0,-1.0,-1.0,-1.0,31.097,1.32678,1437,2990682 +8,84,search,6903.81,2483.79,3513.76,10.7774,176.925,0.91258,0.111729,-1.0,-1.0,12.077,1.32678,1437,2990682 +8,85,insert,43.356,-1.0,-1.0,-1.0,-1.0,48.937,1.34097,1442,3025613 +8,86,search,7030.35,2493.69,3623.56,10.6591,181.194,0.91311,0.111704,-1.0,-1.0,20.859,1.34123,1443,3025613 +8,87,insert,535.974,-1.0,-1.0,-1.0,-1.0,714.305,1.54435,1535,3468632 +8,88,search,7540.62,2630.86,3941.45,10.8957,191.175,0.91552,0.10882,-1.0,-1.0,122.17,1.54434,1550,3468632 +8,89,insert,401.243,-1.0,-1.0,-1.0,-1.0,480.238,1.70513,1619,3831692 +8,90,search,7955.03,2715.68,4171.86,11.0058,200.987,0.91908,0.104677,-1.0,-1.0,58.245,1.70543,1626,3831692 +8,91,insert,30.704,-1.0,-1.0,-1.0,-1.0,58.261,1.71718,1634,3864067 +8,92,search,8155.65,2699.91,4315.3,10.681,213.36,0.91899,0.104523,-1.0,-1.0,24.951,1.7172,1635,3864067 +8,93,insert,304.334,-1.0,-1.0,-1.0,-1.0,245.158,1.82158,1668,4103827 +8,94,search,8455.4,2760.05,4530.72,10.9233,225.026,0.91909,0.104192,-1.0,-1.0,39.228,1.82164,1671,4103827 +8,95,insert,22.159,-1.0,-1.0,-1.0,-1.0,19.841,1.82847,1672,4119898 +8,96,search,8801.65,2767.62,4845.67,10.5941,246.17,0.91931,0.103976,-1.0,-1.0,14.792,1.82847,1672,4119898 +8,97,insert,12.148,-1.0,-1.0,-1.0,-1.0,25.468,1.831,1673,4129367 +8,98,search,8526.33,2772.02,4582.32,10.8524,227.82,0.91939,0.103944,-1.0,-1.0,13.439,1.831,1673,4129367 +8,99,insert,9.745,-1.0,-1.0,-1.0,-1.0,13.543,1.83288,1673,4134502 +8,100,search,8265.51,2775.87,4365.23,11.2359,208.956,0.91947,0.103948,-1.0,-1.0,13.865,1.83288,1673,4134502 +8,101,insert,37.562,-1.0,-1.0,-1.0,-1.0,61.231,1.84276,1679,4164482 +8,102,search,7970.57,2784.43,4088.17,11.9717,188.969,0.92012,0.103314,-1.0,-1.0,13.379,1.84276,1679,4164482 +8,103,insert,19.63,-1.0,-1.0,-1.0,-1.0,26.336,1.84934,1681,4178601 +8,104,search,8303.45,2790.37,4361.96,11.1525,213.626,0.92046,0.103276,-1.0,-1.0,15.231,1.84934,1681,4178601 +8,105,insert,11.453,-1.0,-1.0,-1.0,-1.0,31.951,1.85321,1683,4187774 +8,106,search,8860.65,2790.32,4854.79,10.3265,240.829,0.92027,0.103706,-1.0,-1.0,28.25,1.85323,1684,4187774 +8,107,insert,30.005,-1.0,-1.0,-1.0,-1.0,34.364,1.85858,1686,4200109 +8,108,search,8871.14,2791.85,4878.83,10.5445,247.916,0.92014,0.103767,-1.0,-1.0,16.125,1.85858,1686,4200109 +8,109,insert,522.963,-1.0,-1.0,-1.0,-1.0,590.254,2.02021,1758,4557867 +8,110,search,9007.13,2868.13,4865.86,11.0401,242.864,0.92195,0.101653,-1.0,-1.0,68.616,2.02073,1764,4557867 +8,111,insert,31.507,-1.0,-1.0,-1.0,-1.0,58.338,2.032,1770,4587252 +8,112,search,9426.71,2861.64,5227.94,10.5488,259.084,0.92236,0.101484,-1.0,-1.0,18.571,2.032,1770,4587252 +8,113,insert,14.962,-1.0,-1.0,-1.0,-1.0,25.213,2.0368,1771,4600056 +8,114,search,9163.83,2866.13,4983.75,10.8102,248.202,0.92245,0.101389,-1.0,-1.0,19.323,2.0368,1771,4600056 +8,115,insert,42.225,-1.0,-1.0,-1.0,-1.0,60.48,2.04926,1777,4627422 +8,116,search,8629.68,2868.08,4502.16,11.7284,209.727,0.92297,0.101065,-1.0,-1.0,18.215,2.04926,1777,4627422 +8,117,insert,14.434,-1.0,-1.0,-1.0,-1.0,25.775,2.05439,1778,4639292 +8,118,search,9097.09,2872.99,4900.82,10.8086,237.234,0.92307,0.101124,-1.0,-1.0,19.829,2.05439,1778,4639292 +8,119,insert,4.601,-1.0,-1.0,-1.0,-1.0,18.505,2.05563,1778,4643423 +8,120,search,9435.74,2875.63,5198.17,10.557,257.417,0.92309,0.101098,-1.0,-1.0,19.975,2.05563,1778,4643423 +8,121,insert,20.465,-1.0,-1.0,-1.0,-1.0,46.315,2.06152,1781,4657252 +8,122,search,9340.35,2879,5130.83,10.7615,254.158,0.92329,0.100783,-1.0,-1.0,19.815,2.06152,1781,4657252 +8,123,insert,408.429,-1.0,-1.0,-1.0,-1.0,474.403,2.19199,1828,4938477 +8,124,search,9732.51,2923.75,5402.53,10.755,270.272,0.92334,0.101597,-1.0,-1.0,156.069,2.19279,1839,4938477 +8,125,insert,58.031,-1.0,-1.0,-1.0,-1.0,102.392,2.20915,1851,4980492 +8,126,search,9597.11,2901.53,5235.79,11.0823,251.41,0.92378,0.101354,-1.0,-1.0,95.473,2.20918,1856,4980492 +8,127,insert,61.052,-1.0,-1.0,-1.0,-1.0,65.737,2.22746,1863,5030515 +8,128,search,9013.01,2914.98,4680.55,12.201,209.48,0.92462,0.100902,-1.0,-1.0,31.754,2.22749,1864,5030515 +8,129,delete,19.129,-1.0,-1.0,-1.0,-1.0,91.186,2.22572,1833,5009391 +8,130,search,9411.28,2901.08,5100.96,10.9075,253.918,0.92306,0.102244,-1.0,-1.0,22.486,2.22572,1833,5009391 +8,131,delete,4.717,-1.0,-1.0,-1.0,-1.0,22.105,2.22572,1833,5004093 +8,132,search,9460.87,2898.4,5141.78,10.8288,246.934,0.92304,0.102236,-1.0,-1.0,23.319,2.22572,1833,5004093 +8,133,delete,18.499,-1.0,-1.0,-1.0,-1.0,21.806,2.22572,1833,4991787 +8,134,search,9115.2,2884.04,4819.04,11.6074,228.4,0.92293,0.102309,-1.0,-1.0,23.492,2.22572,1833,4991787 +8,135,delete,25.503,-1.0,-1.0,-1.0,-1.0,57.127,2.223,1830,4974857 +8,136,search,9560.7,2876.42,5207.54,10.8087,261.639,0.92309,0.102112,-1.0,-1.0,23.492,2.223,1830,4974857 +8,137,delete,5.02,-1.0,-1.0,-1.0,-1.0,21.987,2.223,1830,4971386 +8,138,search,9673.84,2873.55,5328,10.7434,267.252,0.92295,0.102268,-1.0,-1.0,22.99,2.223,1830,4971386 +8,139,delete,12.338,-1.0,-1.0,-1.0,-1.0,21.926,2.223,1830,4963487 +8,140,search,9625.76,2866.25,5271.62,10.7711,257.944,0.92282,0.102317,-1.0,-1.0,23.174,2.223,1830,4963487 +8,141,delete,28.28,-1.0,-1.0,-1.0,-1.0,71.714,2.21967,1825,4941830 +8,142,search,9537.66,2856.02,5209.27,10.8065,256.165,0.92252,0.102558,-1.0,-1.0,23.622,2.21967,1825,4941830 +8,143,delete,21.684,-1.0,-1.0,-1.0,-1.0,78.954,2.21512,1822,4925657 +8,144,search,8835.97,2851.92,4568.97,11.9084,212.227,0.92274,0.102235,-1.0,-1.0,22.745,2.21512,1822,4925657 +8,145,delete,2.918,-1.0,-1.0,-1.0,-1.0,26.68,2.21484,1821,4922686 +8,146,search,9604.57,2849.67,5051.16,10.8808,244.744,0.92265,0.102138,-1.0,-1.0,22.571,2.21484,1821,4922686 +8,147,delete,10.186,-1.0,-1.0,-1.0,-1.0,21.782,2.2146,1821,4913636 +8,148,search,9378.56,2842.06,4839.28,11.208,231.987,0.92261,0.102209,-1.0,-1.0,23.933,2.2146,1821,4913636 +8,149,delete,234.634,-1.0,-1.0,-1.0,-1.0,1074.1,2.13663,1741,4717250 +8,150,search,9321.51,2847.49,4938.46,10.8649,247.768,0.9219,0.103039,-1.0,-1.0,68.771,2.13715,1746,4717250 +8,151,delete,188.33,-1.0,-1.0,-1.0,-1.0,925.633,2.06948,1672,4560269 +16,2,search,2646.28,37.3196,160.794,2.32472,102.764,0.8551,0.130106,-1.0,-1.0,7.887,0.0184881,1000,38806 +16,3,insert,14.569,-1.0,-1.0,-1.0,-1.0,15.578,0.0226681,998,49334 +16,4,search,2613.88,66.6444,159.881,2.94427,102.904,0.86613,0.128797,-1.0,-1.0,13.98,0.0226611,997,49334 +16,5,insert,34.125,-1.0,-1.0,-1.0,-1.0,174.437,0.0329766,993,73557 +16,6,search,2604.61,193.073,266.948,4.15128,68.3108,0.92433,0.104255,-1.0,-1.0,112.606,0.0330819,995,73557 +16,7,insert,36.112,-1.0,-1.0,-1.0,-1.0,106.48,0.0426107,995,95766 +16,8,search,2655.74,245.079,293.537,4.64327,71.1985,0.92582,0.103612,-1.0,-1.0,95.831,0.0428012,997,95766 +16,9,insert,5.755,-1.0,-1.0,-1.0,-1.0,78.984,0.0445267,997,100025 +16,10,search,2637.37,254.375,295.299,4.72495,72.7382,0.92703,0.100737,-1.0,-1.0,80.289,0.0445267,997,100025 +16,11,insert,15.686,-1.0,-1.0,-1.0,-1.0,80.728,0.0497772,997,111417 +16,12,search,2673,301.372,328.841,4.96063,70.2381,0.92784,0.100473,-1.0,-1.0,82.329,0.0497772,997,111417 +16,13,insert,31.956,-1.0,-1.0,-1.0,-1.0,81.183,0.0610515,997,137139 +16,14,search,2676.21,347.51,358.514,5.19002,71.1586,0.92449,0.102927,-1.0,-1.0,20.848,0.061098,998,137139 +16,15,insert,30.374,-1.0,-1.0,-1.0,-1.0,7.818,0.0698157,998,156710 +16,16,search,2671.51,383.909,365.2,5.34038,71.938,0.92241,0.104278,-1.0,-1.0,19.734,0.0698182,1000,156710 +16,17,insert,7.069,-1.0,-1.0,-1.0,-1.0,7.121,0.0717762,1000,161773 +16,18,search,2779.65,400.184,386.568,5.1967,78.8566,0.92371,0.103298,-1.0,-1.0,16.876,0.0719569,1002,161773 +16,19,insert,40.709,-1.0,-1.0,-1.0,-1.0,7.721,0.0785469,1002,177161 +16,20,search,2769.4,441.39,416.522,5.38885,74.3241,0.92719,0.0999856,-1.0,-1.0,7.667,0.0785469,1002,177161 +16,21,insert,393.069,-1.0,-1.0,-1.0,-1.0,161.109,0.201067,1037,448898 +16,22,search,3082.7,906.422,742.932,6.49531,66.4159,0.91597,0.103468,-1.0,-1.0,31.805,0.201067,1042,448898 +16,23,insert,427.335,-1.0,-1.0,-1.0,-1.0,244.652,0.32776,1084,733493 +16,24,search,3493.95,1278.47,1063.25,6.78262,76.0798,0.91152,0.106469,-1.0,-1.0,74.589,0.327759,1094,733493 +16,25,insert,47.007,-1.0,-1.0,-1.0,-1.0,36.015,0.345775,1099,777443 +16,26,search,3568.53,1272.02,1075.36,6.81113,82.0328,0.91116,0.106938,-1.0,-1.0,25.994,0.345815,1101,777443 +16,27,insert,49.724,-1.0,-1.0,-1.0,-1.0,20.003,0.358047,1102,805394 +16,28,search,3586.43,1290.23,1111.03,6.8628,74.0825,0.91158,0.106722,-1.0,-1.0,21.402,0.358055,1103,805394 +16,29,insert,95.383,-1.0,-1.0,-1.0,-1.0,62.011,0.385238,1111,866391 +16,30,search,3647.15,1349.79,1150.14,6.88785,81.5473,0.91278,0.107318,-1.0,-1.0,28.286,0.385238,1113,866391 +16,31,insert,512.212,-1.0,-1.0,-1.0,-1.0,347.804,0.551645,1165,1239816 +16,32,search,3919.85,1663.86,1322.31,7.62769,82.9215,0.90573,0.111989,-1.0,-1.0,106.617,0.551893,1173,1239816 +16,33,insert,58.332,-1.0,-1.0,-1.0,-1.0,18.943,0.571773,1175,1291211 +16,34,search,4111.29,1675.38,1470.04,7.08703,96.4712,0.90682,0.110791,-1.0,-1.0,63.436,0.57179,1179,1291211 +16,35,insert,42.158,-1.0,-1.0,-1.0,-1.0,41.985,0.584151,1185,1324978 +16,36,search,4151.12,1705.25,1457.76,7.20558,97.0179,0.90805,0.110128,-1.0,-1.0,19.078,0.584151,1186,1324978 +16,37,insert,63.154,-1.0,-1.0,-1.0,-1.0,30.805,0.604236,1189,1371885 +16,38,search,4149.11,1733.6,1465.17,7.29541,95.6378,0.90811,0.110169,-1.0,-1.0,17.891,0.604236,1190,1371885 +16,39,insert,11.253,-1.0,-1.0,-1.0,-1.0,9.024,0.607442,1190,1379335 +16,40,search,4200.04,1741.72,1529.06,7.09852,94.994,0.90842,0.110616,-1.0,-1.0,10.557,0.607442,1190,1379335 +16,41,insert,50.753,-1.0,-1.0,-1.0,-1.0,48.677,0.623707,1196,1413312 +16,42,search,4270.26,1756.94,1561.38,7.08434,95.8333,0.90912,0.11016,-1.0,-1.0,9.76,0.623707,1196,1413312 +16,43,insert,13.355,-1.0,-1.0,-1.0,-1.0,25.353,0.627725,1199,1423411 +16,44,search,4273.46,1759.71,1563.04,7.09458,94.9439,0.90864,0.110747,-1.0,-1.0,9.978,0.627725,1199,1423411 +16,45,insert,227.337,-1.0,-1.0,-1.0,-1.0,33.31,0.643337,1204,1457559 +16,46,search,4268.12,1777.23,1544.13,7.26637,98.5551,0.90879,0.1103,-1.0,-1.0,9.463,0.643337,1204,1457559 +16,47,insert,319.649,-1.0,-1.0,-1.0,-1.0,260.7,0.749984,1234,1688593 +16,48,search,4571,1920.94,1763.5,7.14922,108.388,0.91037,0.110203,-1.0,-1.0,91.242,0.749984,1241,1688593 +16,49,insert,38.203,-1.0,-1.0,-1.0,-1.0,30.119,0.763725,1244,1723505 +16,50,search,4465.04,1926.95,1657.16,7.52931,98.5739,0.9102,0.110561,-1.0,-1.0,33.777,0.763724,1246,1723505 +16,51,insert,350.366,-1.0,-1.0,-1.0,-1.0,244.552,0.902309,1283,2035040 +16,52,search,4779.79,2128.2,1878.13,7.6784,114.429,0.91354,0.107937,-1.0,-1.0,49.461,0.902328,1289,2035040 +16,53,insert,47.122,-1.0,-1.0,-1.0,-1.0,31.219,0.920683,1292,2078341 +16,54,search,4921.21,2136.35,1985.69,7.45249,119.14,0.91301,0.108384,-1.0,-1.0,11.971,0.920683,1292,2078341 +16,55,insert,387.549,-1.0,-1.0,-1.0,-1.0,425.797,1.06954,1341,2399905 +16,56,search,5294.88,2310.69,2232.41,7.60286,135.579,0.91379,0.108663,-1.0,-1.0,151.621,1.07019,1357,2399905 +16,57,insert,33.408,-1.0,-1.0,-1.0,-1.0,27.544,1.08007,1360,2419836 +16,58,search,5492.34,2256.73,2366.24,7.13082,149.928,0.91285,0.10969,-1.0,-1.0,60.067,1.08009,1365,2419836 +16,59,insert,260.516,-1.0,-1.0,-1.0,-1.0,168.153,1.17785,1380,2643083 +16,60,search,5603.92,2307.7,2451.14,7.18871,147.154,0.90692,0.116472,-1.0,-1.0,96.817,1.17831,1390,2643083 +16,61,insert,12.024,-1.0,-1.0,-1.0,-1.0,16.797,1.18227,1391,2653064 +16,62,search,5559.57,2283.73,2388.41,7.24766,145.581,0.90629,0.1167,-1.0,-1.0,23.719,1.18227,1392,2653064 +16,63,insert,4.876,-1.0,-1.0,-1.0,-1.0,10.451,1.18381,1392,2656118 +16,64,search,5348.94,2285.01,2205.93,7.65576,132.067,0.90622,0.116862,-1.0,-1.0,12.408,1.18381,1392,2656118 +16,65,insert,83.013,-1.0,-1.0,-1.0,-1.0,109.389,1.2119,1410,2723424 +16,66,search,5651.54,2306.06,2424.19,7.22369,142.89,0.90657,0.116307,-1.0,-1.0,16.938,1.21217,1411,2723424 +16,67,insert,46.477,-1.0,-1.0,-1.0,-1.0,67.923,1.23089,1420,2769021 +16,68,search,5520.9,2333.74,2283.19,7.65861,136.652,0.90814,0.115123,-1.0,-1.0,10.79,1.23089,1420,2769021 +16,69,insert,56.324,-1.0,-1.0,-1.0,-1.0,86.646,1.25379,1431,2821777 +16,70,search,5489.19,2350.69,2255.87,7.76707,132.902,0.90999,0.113131,-1.0,-1.0,11.091,1.25379,1431,2821777 +16,71,insert,14.748,-1.0,-1.0,-1.0,-1.0,44.564,1.25882,1436,2834921 +16,72,search,5560.97,2353.17,2302.87,7.71845,140.115,0.91037,0.112893,-1.0,-1.0,11.229,1.25882,1436,2834921 +16,73,insert,8.431,-1.0,-1.0,-1.0,-1.0,16.937,1.26192,1437,2842044 +16,74,search,5740.54,2356.28,2465.98,7.28877,148.998,0.91026,0.11299,-1.0,-1.0,12.455,1.26192,1437,2842044 +16,75,insert,25.02,-1.0,-1.0,-1.0,-1.0,27.411,1.26779,1439,2858890 +16,76,search,5623.68,2366.31,2365.43,7.77662,142.205,0.91064,0.112609,-1.0,-1.0,13.65,1.26779,1439,2858890 +16,77,insert,53.44,-1.0,-1.0,-1.0,-1.0,25.988,1.27756,1441,2882818 +16,78,search,5710.34,2374.06,2425.39,7.73178,150.658,0.91066,0.1127,-1.0,-1.0,18.267,1.27772,1442,2882818 +16,79,insert,529.433,-1.0,-1.0,-1.0,-1.0,18.395,1.3048,1443,2947806 +16,80,search,5698.14,2405.07,2420.98,7.69986,145.609,0.91032,0.11305,-1.0,-1.0,12.254,1.3048,1443,2947806 +16,81,insert,44.341,-1.0,-1.0,-1.0,-1.0,33.765,1.31831,1446,2976895 +16,82,search,5544.93,2415.92,2287.66,8.0336,135.661,0.91137,0.112543,-1.0,-1.0,18.622,1.31837,1447,2976895 +16,83,insert,16.742,-1.0,-1.0,-1.0,-1.0,18.286,1.32442,1448,2990682 +16,84,search,5771.32,2421.78,2470.09,7.6312,148.867,0.91197,0.111953,-1.0,-1.0,11.875,1.32442,1448,2990682 +16,85,insert,41.815,-1.0,-1.0,-1.0,-1.0,37.321,1.33817,1451,3025613 +16,86,search,6022.72,2439.18,2685.98,7.18223,165.698,0.91231,0.111853,-1.0,-1.0,11.734,1.33817,1451,3025613 +16,87,insert,558.638,-1.0,-1.0,-1.0,-1.0,738.592,1.5446,1551,3468632 +16,88,search,6339.56,2557.79,2836.07,7.66008,169.24,0.9151,0.109525,-1.0,-1.0,97.25,1.5446,1563,3468632 +16,89,insert,383.234,-1.0,-1.0,-1.0,-1.0,421.384,1.70273,1628,3831692 +16,90,search,6775.95,2671.81,3045.3,7.4872,183.257,0.91973,0.104333,-1.0,-1.0,42.972,1.70273,1632,3831692 +16,91,insert,31.369,-1.0,-1.0,-1.0,-1.0,35.238,1.71361,1636,3864067 +16,92,search,6821.96,2679.08,3093.25,7.50437,185.615,0.91978,0.104169,-1.0,-1.0,12.808,1.71361,1636,3864067 +16,93,insert,248.71,-1.0,-1.0,-1.0,-1.0,269.95,1.81862,1677,4103827 +16,94,search,6786.36,2724.41,3003.62,7.97399,170.156,0.92005,0.103618,-1.0,-1.0,42.81,1.81911,1681,4103827 +16,95,insert,15.571,-1.0,-1.0,-1.0,-1.0,18.186,1.82435,1682,4119898 +16,96,search,6747.11,2723.21,2948.48,8.12453,170.109,0.92034,0.103466,-1.0,-1.0,14.831,1.82435,1682,4119898 +16,97,insert,14.049,-1.0,-1.0,-1.0,-1.0,19.081,1.82818,1683,4129367 +16,98,search,7359.44,2726.66,3506.3,7.1764,207.235,0.92044,0.103295,-1.0,-1.0,15.468,1.82818,1683,4129367 +16,99,insert,9.266,-1.0,-1.0,-1.0,-1.0,14.64,1.83003,1683,4134502 +16,100,search,7018.25,2730.79,3178.1,7.72565,192.969,0.92058,0.103141,-1.0,-1.0,14.987,1.83003,1683,4134502 +16,101,insert,43.84,-1.0,-1.0,-1.0,-1.0,35.794,1.84016,1686,4164482 +16,102,search,6917.33,2742.51,3101.26,7.9446,183.184,0.92068,0.103217,-1.0,-1.0,14.853,1.84016,1686,4164482 +16,103,insert,20.451,-1.0,-1.0,-1.0,-1.0,40.056,1.84645,1689,4178601 +16,104,search,7228.34,2744.11,3354.13,7.56212,202.496,0.92104,0.102877,-1.0,-1.0,14.595,1.84645,1689,4178601 +16,105,insert,9.026,-1.0,-1.0,-1.0,-1.0,22.506,1.84903,1690,4187774 +16,106,search,7158.12,2748.22,3296.35,7.68553,194.795,0.92111,0.103017,-1.0,-1.0,14.906,1.84903,1690,4187774 +16,107,insert,21.069,-1.0,-1.0,-1.0,-1.0,36.82,1.85373,1692,4200109 +16,108,search,7287.82,2751.47,3409.43,7.37056,208.106,0.92099,0.10299,-1.0,-1.0,22.6,1.85398,1693,4200109 +16,109,insert,475.73,-1.0,-1.0,-1.0,-1.0,594.121,2.01915,1763,4557867 +16,110,search,7505.8,2827.61,3459.93,7.61127,199.752,0.92274,0.101843,-1.0,-1.0,91.793,2.02012,1770,4557867 +16,111,insert,29.019,-1.0,-1.0,-1.0,-1.0,70.915,2.0313,1779,4587252 +16,112,search,7581.39,2818.44,3504.89,7.65254,208.001,0.92282,0.101759,-1.0,-1.0,19.607,2.0313,1779,4587252 +16,113,insert,14.538,-1.0,-1.0,-1.0,-1.0,34.388,2.03604,1781,4600056 +16,114,search,7790.34,2820.49,3667.44,7.50148,219.793,0.92325,0.101476,-1.0,-1.0,28.613,2.03607,1782,4600056 +16,115,insert,46.69,-1.0,-1.0,-1.0,-1.0,50.454,2.04695,1786,4627422 +16,116,search,7742.46,2830.42,3638.92,7.58418,216.157,0.92344,0.101387,-1.0,-1.0,19.879,2.04695,1786,4627422 +16,117,insert,20.029,-1.0,-1.0,-1.0,-1.0,31.508,2.05196,1787,4639292 +16,118,search,7760.73,2835.66,3643.32,7.65253,217.354,0.92393,0.10079,-1.0,-1.0,29.884,2.05216,1788,4639292 +16,119,insert,6.867,-1.0,-1.0,-1.0,-1.0,18.565,2.05405,1788,4643423 +16,120,search,7797.08,2834.06,3699.21,7.52746,222.098,0.92386,0.101026,-1.0,-1.0,20.271,2.05405,1788,4643423 +16,121,insert,20.558,-1.0,-1.0,-1.0,-1.0,19.201,2.05966,1788,4657252 +16,122,search,7804.72,2843.32,3711.29,7.47564,218.253,0.92413,0.100752,-1.0,-1.0,20.311,2.05966,1788,4657252 +16,123,insert,390.164,-1.0,-1.0,-1.0,-1.0,541.223,2.18968,1842,4938477 +16,124,search,7729.9,2877.61,3542.77,8.01018,196.048,0.924,0.101579,-1.0,-1.0,138.927,2.18981,1850,4938477 +16,125,insert,53.705,-1.0,-1.0,-1.0,-1.0,80.121,2.20515,1858,4980492 +16,126,search,8208.6,2876.69,3919.44,7.25018,230.075,0.92462,0.101259,-1.0,-1.0,128.233,2.20555,1866,4980492 +16,127,insert,59.555,-1.0,-1.0,-1.0,-1.0,124.617,2.22656,1883,5030515 +16,128,search,8215.08,2852.82,3876.54,7.53119,226.983,0.92484,0.101517,-1.0,-1.0,42.871,2.22656,1884,5030515 +16,129,delete,26.562,-1.0,-1.0,-1.0,-1.0,95.357,2.22477,1852,5009391 +16,130,search,7947.48,2839.95,3697.05,7.75345,220.525,0.92369,0.102122,-1.0,-1.0,25.624,2.22477,1852,5009391 +16,131,delete,8.556,-1.0,-1.0,-1.0,-1.0,23.916,2.22477,1852,5004093 +16,132,search,7722.7,2836.65,3480.34,8.01132,203.071,0.92368,0.102026,-1.0,-1.0,24.748,2.22477,1852,5004093 +16,133,delete,14.776,-1.0,-1.0,-1.0,-1.0,23.155,2.22477,1852,4991787 +16,134,search,8088.4,2823.33,3815.97,7.54235,226.125,0.92348,0.102249,-1.0,-1.0,24.671,2.22477,1852,4991787 +16,135,delete,25.035,-1.0,-1.0,-1.0,-1.0,62.744,2.22148,1849,4974857 +16,136,search,7820.34,2816.34,3593.25,7.86617,206.763,0.92383,0.101948,-1.0,-1.0,24.99,2.22148,1849,4974857 +16,137,delete,5.122,-1.0,-1.0,-1.0,-1.0,23.347,2.22148,1849,4971386 +16,138,search,7701.16,2813.54,3448.92,8.05285,200.577,0.92377,0.102075,-1.0,-1.0,24.384,2.22148,1849,4971386 +16,139,delete,8.836,-1.0,-1.0,-1.0,-1.0,24.34,2.22148,1849,4963487 +16,140,search,7680.33,2807.31,3464.36,8.03639,199.023,0.92371,0.102061,-1.0,-1.0,24.46,2.22148,1849,4963487 +16,141,delete,24.208,-1.0,-1.0,-1.0,-1.0,91.028,2.21645,1843,4941830 +16,142,search,7948.07,2798.62,3715.41,7.4674,222.97,0.92346,0.102376,-1.0,-1.0,24.356,2.21645,1843,4941830 +16,143,delete,18.547,-1.0,-1.0,-1.0,-1.0,70.514,2.21272,1840,4925657 +16,144,search,7936.96,2793.74,3672.62,7.49025,215.329,0.92347,0.102358,-1.0,-1.0,24.3,2.21272,1840,4925657 +16,145,delete,3.144,-1.0,-1.0,-1.0,-1.0,28.91,2.2126,1839,4922686 +16,146,search,7879.54,2792.17,3643.22,7.48754,215.255,0.92316,0.102619,-1.0,-1.0,24.781,2.2126,1839,4922686 +16,147,delete,8.787,-1.0,-1.0,-1.0,-1.0,23.404,2.2126,1839,4913636 +16,148,search,7708.04,2784.58,3501.45,7.71997,201.013,0.92307,0.102636,-1.0,-1.0,24.06,2.2126,1839,4913636 +16,149,delete,245.551,-1.0,-1.0,-1.0,-1.0,1159.16,2.12996,1755,4717250 +16,150,search,7509.31,2794.1,3442.17,7.58149,205.721,0.92247,0.104006,-1.0,-1.0,48.272,2.13058,1758,4717250 +16,151,delete,169.885,-1.0,-1.0,-1.0,-1.0,907.976,2.06241,1687,4560269 +32,2,search,2599.15,37.3245,137.518,2.05555,145.33,0.8551,0.130106,-1.0,-1.0,7.807,0.0184881,1000,38806 +32,3,insert,16.466,-1.0,-1.0,-1.0,-1.0,15.625,0.0226681,998,49334 +32,4,search,2627.96,66.5585,137.808,2.35615,142.371,0.86613,0.128797,-1.0,-1.0,14.461,0.0226611,997,49334 +32,5,insert,34.935,-1.0,-1.0,-1.0,-1.0,176.276,0.0329766,993,73557 +32,6,search,2613.1,192.225,215.273,3.29354,92.8759,0.92433,0.104255,-1.0,-1.0,106.377,0.0329766,993,73557 +32,7,insert,41.685,-1.0,-1.0,-1.0,-1.0,103.164,0.0425054,993,95766 +32,8,search,2582.74,247.251,240.507,3.42631,96.8515,0.9262,0.103389,-1.0,-1.0,87.324,0.042614,994,95766 +32,9,insert,6.115,-1.0,-1.0,-1.0,-1.0,77.886,0.0443284,994,100025 +32,10,search,2607.19,258.65,241.855,3.43259,101.206,0.92954,0.0985602,-1.0,-1.0,80.099,0.0443284,994,100025 +32,11,insert,18.587,-1.0,-1.0,-1.0,-1.0,80.554,0.0497523,994,111417 +32,12,search,2611.92,306.036,271.119,3.52729,96.3119,0.93027,0.0988801,-1.0,-1.0,20.622,0.0498144,995,111417 +32,13,insert,37.787,-1.0,-1.0,-1.0,-1.0,7.277,0.0611217,995,137139 +32,14,search,2674.45,349.111,291.975,3.41849,109.403,0.92593,0.101996,-1.0,-1.0,20.475,0.061131,997,137139 +32,15,insert,34.652,-1.0,-1.0,-1.0,-1.0,7.392,0.0697407,997,156710 +32,16,search,2663.42,384.787,307.9,3.58703,96.6557,0.92334,0.103711,-1.0,-1.0,7.765,0.0697407,997,156710 +32,17,insert,7.943,-1.0,-1.0,-1.0,-1.0,7.144,0.071544,997,161773 +32,18,search,2682.51,406.081,323.102,3.58594,101.801,0.92497,0.102835,-1.0,-1.0,7.918,0.071544,997,161773 +32,19,insert,45.301,-1.0,-1.0,-1.0,-1.0,7.092,0.0782662,997,177161 +32,20,search,2695.09,451.935,343.362,3.67672,100.064,0.92892,0.0991464,-1.0,-1.0,7.753,0.0782662,997,177161 +32,21,insert,429.99,-1.0,-1.0,-1.0,-1.0,111.451,0.199605,1012,448898 +32,22,search,2889.6,997.456,648.193,4.21537,73.1439,0.92131,0.100373,-1.0,-1.0,17.648,0.199605,1013,448898 +32,23,insert,456.168,-1.0,-1.0,-1.0,-1.0,235.996,0.32773,1041,733493 +32,24,search,3249.32,1455.35,947.741,4.34214,91.1731,0.91819,0.101904,-1.0,-1.0,73.474,0.327728,1049,733493 +32,25,insert,50.041,-1.0,-1.0,-1.0,-1.0,29.043,0.34431,1052,777443 +32,26,search,3235.59,1451.63,929.517,4.37148,81.3696,0.91778,0.102617,-1.0,-1.0,27.541,0.344429,1055,777443 +32,27,insert,39.999,-1.0,-1.0,-1.0,-1.0,16.611,0.356493,1056,805394 +32,28,search,3234.01,1464.13,905.766,4.59362,75.0954,0.91795,0.102405,-1.0,-1.0,9.018,0.356493,1056,805394 +32,29,insert,79.636,-1.0,-1.0,-1.0,-1.0,43.493,0.383726,1059,866391 +32,30,search,3314.41,1549.54,994.87,4.45809,86.9381,0.91927,0.102159,-1.0,-1.0,21.959,0.383726,1060,866391 +32,31,insert,490.527,-1.0,-1.0,-1.0,-1.0,367.233,0.555082,1108,1239816 +32,32,search,3781.33,1874.89,1301.34,4.36104,111.53,0.91233,0.107674,-1.0,-1.0,104.767,0.555111,1115,1239816 +32,33,insert,65.577,-1.0,-1.0,-1.0,-1.0,25.298,0.57604,1117,1291211 +32,34,search,3806.39,1890.49,1329.63,4.40896,106.441,0.91192,0.108396,-1.0,-1.0,69.747,0.576056,1121,1291211 +32,35,insert,49.753,-1.0,-1.0,-1.0,-1.0,51.405,0.588046,1127,1324978 +32,36,search,3772.49,1912.47,1276.76,4.63068,99.7529,0.91222,0.10816,-1.0,-1.0,43.054,0.588048,1131,1324978 +32,37,insert,61.654,-1.0,-1.0,-1.0,-1.0,26.828,0.607285,1133,1371885 +32,38,search,3887.15,1937.76,1378.16,4.40796,103.556,0.91058,0.108864,-1.0,-1.0,16.963,0.607285,1134,1371885 +32,39,insert,13.177,-1.0,-1.0,-1.0,-1.0,9.908,0.610575,1134,1379335 +32,40,search,3910.05,1943.48,1373.71,4.42952,106.59,0.91147,0.108628,-1.0,-1.0,10.652,0.610575,1134,1379335 +32,41,insert,62.288,-1.0,-1.0,-1.0,-1.0,54.384,0.62614,1140,1413312 +32,42,search,3948.78,1954.1,1401.81,4.40728,115.702,0.91178,0.109014,-1.0,-1.0,10.022,0.62614,1140,1413312 +32,43,insert,15.009,-1.0,-1.0,-1.0,-1.0,9.423,0.629338,1140,1423411 +32,44,search,3930.67,1971.13,1398.35,4.432,109.846,0.91217,0.108523,-1.0,-1.0,10.636,0.629338,1140,1423411 +32,45,insert,227.738,-1.0,-1.0,-1.0,-1.0,23.157,0.643618,1142,1457559 +32,46,search,3953.28,1997.5,1420.62,4.41212,107.515,0.91266,0.107608,-1.0,-1.0,10.738,0.643618,1142,1457559 +32,47,insert,344.305,-1.0,-1.0,-1.0,-1.0,312.76,0.748328,1173,1688593 +32,48,search,4074.37,2125.22,1468.13,4.63507,108.418,0.91136,0.109784,-1.0,-1.0,102.804,0.748326,1180,1688593 +32,49,insert,49.722,-1.0,-1.0,-1.0,-1.0,45.492,0.764662,1185,1723505 +32,50,search,4057.12,2117.38,1423.6,4.70802,108.185,0.91181,0.109462,-1.0,-1.0,60.981,0.764661,1190,1723505 +32,51,insert,374.875,-1.0,-1.0,-1.0,-1.0,247.489,0.904898,1223,2035040 +32,52,search,4480.15,2324.51,1746.15,4.45385,135.223,0.91498,0.107963,-1.0,-1.0,57.57,0.905006,1230,2035040 +32,53,insert,48.043,-1.0,-1.0,-1.0,-1.0,36.1,0.923389,1234,2078341 +32,54,search,4522.34,2333.15,1759.77,4.46151,134.963,0.91534,0.107645,-1.0,-1.0,9.94,0.923389,1234,2078341 +32,55,insert,352.015,-1.0,-1.0,-1.0,-1.0,482.272,1.07305,1289,2399905 +32,56,search,4802.63,2465.38,1961,4.47486,140.932,0.91451,0.110065,-1.0,-1.0,103.744,1.07305,1300,2399905 +32,57,insert,23.257,-1.0,-1.0,-1.0,-1.0,27.416,1.08127,1303,2419836 +32,58,search,4926.35,2434.18,1998.79,4.41544,147.17,0.91435,0.110377,-1.0,-1.0,55.742,1.08128,1307,2419836 +32,59,insert,261.739,-1.0,-1.0,-1.0,-1.0,244.663,1.17969,1330,2643083 +32,60,search,4784.73,2462.14,1821.67,4.96349,136.243,0.90825,0.117149,-1.0,-1.0,41.768,1.17977,1334,2643083 +32,61,insert,11.967,-1.0,-1.0,-1.0,-1.0,10.147,1.18231,1334,2653064 +32,62,search,5097.52,2458.95,2082.44,4.47541,167.177,0.90855,0.117077,-1.0,-1.0,10.959,1.18231,1334,2653064 +32,63,insert,4.76,-1.0,-1.0,-1.0,-1.0,10.171,1.18346,1334,2656118 +32,64,search,4712.86,2461.46,1762.22,5.12754,130.132,0.90863,0.116945,-1.0,-1.0,11.951,1.18346,1334,2656118 +32,65,insert,102.236,-1.0,-1.0,-1.0,-1.0,129.854,1.21094,1351,2723424 +32,66,search,4741.11,2477.93,1751.55,5.19898,124.814,0.90897,0.116223,-1.0,-1.0,10.363,1.21094,1351,2723424 +32,67,insert,52.443,-1.0,-1.0,-1.0,-1.0,89.019,1.23151,1363,2769021 +32,68,search,5146.23,2493.73,2091.46,4.4726,155.839,0.91038,0.114854,-1.0,-1.0,22.04,1.23151,1365,2769021 +32,69,insert,62.473,-1.0,-1.0,-1.0,-1.0,72.087,1.25454,1373,2821777 +32,70,search,5177.23,2510.27,2114.24,4.4628,155.792,0.91147,0.11357,-1.0,-1.0,21.263,1.25454,1374,2821777 +32,71,insert,15.938,-1.0,-1.0,-1.0,-1.0,49.644,1.2603,1380,2834921 +32,72,search,5023.58,2503.71,1940.5,4.78457,135.07,0.91209,0.112961,-1.0,-1.0,12.723,1.2603,1380,2834921 +32,73,insert,9.246,-1.0,-1.0,-1.0,-1.0,28.346,1.263,1382,2842044 +32,74,search,5018.61,2502.89,1964.83,4.74747,135.676,0.91189,0.113165,-1.0,-1.0,11.916,1.263,1382,2842044 +32,75,insert,27.767,-1.0,-1.0,-1.0,-1.0,46.402,1.27109,1386,2858890 +32,76,search,4919.72,2504.64,1870.6,5.03758,132.23,0.91186,0.113287,-1.0,-1.0,21.896,1.27134,1387,2858890 +32,77,insert,36.036,-1.0,-1.0,-1.0,-1.0,30.118,1.28071,1390,2882818 +32,78,search,5111.01,2507.56,2007.43,4.79805,145.181,0.91169,0.113496,-1.0,-1.0,20.472,1.28085,1391,2882818 +32,79,insert,509.921,-1.0,-1.0,-1.0,-1.0,20.958,1.3085,1393,2947806 +32,80,search,5168.3,2541.17,2068.25,4.78536,150.361,0.91148,0.113434,-1.0,-1.0,12.239,1.3085,1393,2947806 +32,81,insert,41.732,-1.0,-1.0,-1.0,-1.0,37.488,1.31964,1396,2976895 +32,82,search,5352.36,2555.09,2218.22,4.53075,161.852,0.91284,0.112522,-1.0,-1.0,11.751,1.31964,1396,2976895 +32,83,insert,22.037,-1.0,-1.0,-1.0,-1.0,28.293,1.32663,1398,2990682 +32,84,search,5067.64,2563.24,1968.97,4.94971,138.722,0.91301,0.112255,-1.0,-1.0,11.819,1.32663,1398,2990682 +32,85,insert,43.023,-1.0,-1.0,-1.0,-1.0,28.975,1.34015,1400,3025613 +32,86,search,5308.33,2583.96,2176.26,4.59166,153.811,0.91432,0.111409,-1.0,-1.0,10.987,1.34015,1400,3025613 +32,87,insert,551.364,-1.0,-1.0,-1.0,-1.0,690.61,1.5435,1489,3468632 +32,88,search,5857.78,2731.79,2517.74,4.49193,177.659,0.91693,0.108862,-1.0,-1.0,121.07,1.5435,1503,3468632 +32,89,insert,389.907,-1.0,-1.0,-1.0,-1.0,522.361,1.70464,1583,3831692 +32,90,search,5891.97,2777.19,2379.63,4.90476,179.767,0.91993,0.105206,-1.0,-1.0,88.843,1.70484,1593,3831692 +32,91,insert,33.171,-1.0,-1.0,-1.0,-1.0,58.143,1.71752,1601,3864067 +32,92,search,5979.17,2755.37,2419.44,4.91327,167.911,0.92008,0.105241,-1.0,-1.0,22.957,1.71763,1602,3864067 +32,93,insert,285.987,-1.0,-1.0,-1.0,-1.0,256.082,1.81873,1634,4103827 +32,94,search,6112.24,2821.78,2494.99,4.96229,182.23,0.92056,0.104707,-1.0,-1.0,34.848,1.81898,1637,4103827 +32,95,insert,15.503,-1.0,-1.0,-1.0,-1.0,25.035,1.82434,1639,4119898 +32,96,search,6168.4,2821.39,2534.73,4.92604,184.211,0.92053,0.104817,-1.0,-1.0,12.872,1.82434,1639,4119898 +32,97,insert,12.55,-1.0,-1.0,-1.0,-1.0,25.892,1.82883,1641,4129367 +32,98,search,6388.64,2823.2,2729.2,4.69383,195.325,0.92089,0.10462,-1.0,-1.0,13.437,1.82883,1641,4129367 +32,99,insert,7.63,-1.0,-1.0,-1.0,-1.0,19.612,1.83068,1642,4134502 +32,100,search,6236.83,2825.09,2598.25,4.90864,186.198,0.92088,0.104631,-1.0,-1.0,13.641,1.83068,1642,4134502 +32,101,insert,41.908,-1.0,-1.0,-1.0,-1.0,54.443,1.84314,1648,4164482 +32,102,search,6210.66,2830.83,2536.26,5.05231,184.124,0.92089,0.104696,-1.0,-1.0,13.12,1.84314,1648,4164482 +32,103,insert,22.164,-1.0,-1.0,-1.0,-1.0,30.863,1.84967,1650,4178601 +32,104,search,6100.57,2836,2453.1,5.06245,186.126,0.92073,0.104873,-1.0,-1.0,13.47,1.84967,1650,4178601 +32,105,insert,10.33,-1.0,-1.0,-1.0,-1.0,12.323,1.85245,1650,4187774 +32,106,search,6577.07,2841.1,2881.92,4.57833,211.112,0.921,0.104902,-1.0,-1.0,13.26,1.85245,1650,4187774 +32,107,insert,24.569,-1.0,-1.0,-1.0,-1.0,12.732,1.85802,1650,4200109 +32,108,search,6334.66,2846.34,2674.33,4.7373,200.32,0.92096,0.104836,-1.0,-1.0,12.995,1.85802,1650,4200109 +32,109,insert,480.493,-1.0,-1.0,-1.0,-1.0,614.198,2.02461,1731,4557867 +32,110,search,6705.44,2894.55,2856.14,4.73759,198.711,0.92221,0.103473,-1.0,-1.0,53.152,2.02464,1736,4557867 +32,111,insert,29.129,-1.0,-1.0,-1.0,-1.0,47.835,2.03593,1741,4587252 +32,112,search,6903.01,2894.66,2972.94,4.63044,209.828,0.92282,0.103067,-1.0,-1.0,25.818,2.03597,1742,4587252 +32,113,insert,13.009,-1.0,-1.0,-1.0,-1.0,23.823,2.04103,1743,4600056 +32,114,search,6760.53,2897.42,2881.8,4.76055,200.467,0.92279,0.103218,-1.0,-1.0,17.831,2.04103,1743,4600056 +32,115,insert,37.651,-1.0,-1.0,-1.0,-1.0,39.307,2.05134,1746,4627422 +32,116,search,6791.85,2912.05,2905.79,4.78149,207.477,0.92302,0.103146,-1.0,-1.0,18.304,2.05134,1746,4627422 +32,117,insert,12.864,-1.0,-1.0,-1.0,-1.0,26.414,2.05516,1747,4639292 +32,118,search,6980.54,2916.11,3048.33,4.66403,217.828,0.92337,0.102706,-1.0,-1.0,18.245,2.05516,1747,4639292 +32,119,insert,6.365,-1.0,-1.0,-1.0,-1.0,17.292,2.05687,1747,4643423 +32,120,search,7165.76,2917.98,3240.57,4.43832,228.887,0.92345,0.102684,-1.0,-1.0,18.826,2.05687,1747,4643423 +32,121,insert,18.022,-1.0,-1.0,-1.0,-1.0,26.976,2.06238,1748,4657252 +32,122,search,6781.9,2925.18,2883.43,4.86447,197.726,0.92367,0.102644,-1.0,-1.0,19.051,2.06238,1748,4657252 +32,123,insert,373.755,-1.0,-1.0,-1.0,-1.0,461.743,2.1879,1791,4938477 +32,124,search,7385.03,2986.53,3350,4.49559,238.204,0.92435,0.102825,-1.0,-1.0,151.971,2.18851,1802,4938477 +32,125,insert,62.108,-1.0,-1.0,-1.0,-1.0,94.538,2.20647,1813,4980492 +32,126,search,7436.53,2967.16,3354.13,4.49473,232.51,0.92439,0.10301,-1.0,-1.0,50.007,2.20681,1816,4980492 +32,127,insert,58.812,-1.0,-1.0,-1.0,-1.0,105.269,2.22753,1828,5030515 +32,128,search,7412.12,2962.95,3292.38,4.469,224.935,0.92505,0.102382,-1.0,-1.0,43.026,2.2277,1830,5030515 +32,129,delete,29.283,-1.0,-1.0,-1.0,-1.0,87.677,2.22608,1801,5009391 +32,130,search,7320.74,2947.77,3261.66,4.43298,227.742,0.92378,0.103338,-1.0,-1.0,23.209,2.22608,1801,5009391 +32,131,delete,8.148,-1.0,-1.0,-1.0,-1.0,21.495,2.22608,1801,5004093 +32,132,search,7065.68,2944.8,3026.37,4.8042,214.271,0.92374,0.103506,-1.0,-1.0,23.316,2.22608,1801,5004093 +32,133,delete,18.49,-1.0,-1.0,-1.0,-1.0,38.119,2.22465,1800,4991787 +32,134,search,7094.82,2932.84,3055.44,4.75779,221.056,0.92371,0.103607,-1.0,-1.0,22.414,2.22465,1800,4991787 +32,135,delete,23.12,-1.0,-1.0,-1.0,-1.0,49.523,2.22234,1798,4974857 +32,136,search,7156.63,2924.28,3117.37,4.66818,220.155,0.92347,0.103572,-1.0,-1.0,22.464,2.22234,1798,4974857 +32,137,delete,6.595,-1.0,-1.0,-1.0,-1.0,20.962,2.22234,1798,4971386 +32,138,search,7225.06,2920.85,3184.26,4.57692,224.688,0.92341,0.103626,-1.0,-1.0,21.86,2.22234,1798,4971386 +32,139,delete,10.847,-1.0,-1.0,-1.0,-1.0,21.69,2.22234,1798,4963487 +32,140,search,7130,2913.46,3077.49,4.69119,225.883,0.92334,0.10374,-1.0,-1.0,22.114,2.22234,1798,4963487 +32,141,delete,27.41,-1.0,-1.0,-1.0,-1.0,66.745,2.21837,1793,4941830 +32,142,search,7181.4,2903.59,3142.74,4.56458,220.061,0.92315,0.103854,-1.0,-1.0,22.876,2.21837,1793,4941830 +32,143,delete,21.419,-1.0,-1.0,-1.0,-1.0,72.829,2.21437,1790,4925657 +32,144,search,6903.93,2898.02,2893.78,4.87989,201.182,0.92324,0.103736,-1.0,-1.0,21.938,2.21437,1790,4925657 +32,145,delete,3.191,-1.0,-1.0,-1.0,-1.0,28.894,2.21377,1789,4922686 +32,146,search,6930.06,2897.27,2920.77,4.80801,200.654,0.92309,0.103918,-1.0,-1.0,21.58,2.21377,1789,4922686 +32,147,delete,9.314,-1.0,-1.0,-1.0,-1.0,20.911,2.21377,1789,4913636 +32,148,search,6966.02,2889.44,2949.78,4.79149,201.401,0.92311,0.103935,-1.0,-1.0,22.793,2.21377,1789,4913636 +32,149,delete,236.835,-1.0,-1.0,-1.0,-1.0,1090.42,2.13176,1704,4717250 +32,150,search,6763.5,2910.02,2920.83,4.69217,204.291,0.92204,0.104698,-1.0,-1.0,101.482,2.1335,1714,4717250 +32,151,delete,166.618,-1.0,-1.0,-1.0,-1.0,965.723,2.06444,1639,4560269 +64,2,search,2626.54,37.3338,157.931,1.81926,145.912,0.8551,0.130106,-1.0,-1.0,8.01,0.0184881,1000,38806 +64,3,insert,18.741,-1.0,-1.0,-1.0,-1.0,15.725,0.0226681,998,49334 +64,4,search,2594.21,66.3942,122.972,1.86496,137.089,0.86613,0.128797,-1.0,-1.0,14.256,0.0226611,997,49334 +64,5,insert,39.042,-1.0,-1.0,-1.0,-1.0,172.777,0.032979,994,73557 +64,6,search,2566.55,190.088,193.23,2.40647,101.882,0.92449,0.104144,-1.0,-1.0,105.28,0.032979,994,73557 +64,7,insert,44.54,-1.0,-1.0,-1.0,-1.0,103.249,0.0425732,994,95766 +64,8,search,2562.18,244.304,215.647,2.42346,101.197,0.92654,0.103026,-1.0,-1.0,96.08,0.0427523,996,95766 +64,9,insert,7.37,-1.0,-1.0,-1.0,-1.0,78.037,0.044525,996,100025 +64,10,search,2575.18,253.874,221.306,2.35147,102.972,0.92803,0.0997921,-1.0,-1.0,79.695,0.044525,996,100025 +64,11,insert,19.118,-1.0,-1.0,-1.0,-1.0,80.238,0.049798,996,111417 +64,12,search,2604.66,300.709,244.029,2.38548,100.375,0.92891,0.0999099,-1.0,-1.0,21.586,0.0498425,997,111417 +64,13,insert,38.835,-1.0,-1.0,-1.0,-1.0,7.38,0.0608291,997,137139 +64,14,search,2631.97,342.548,262.26,2.28254,102.83,0.92411,0.103417,-1.0,-1.0,21.674,0.0608373,999,137139 +64,15,insert,35.691,-1.0,-1.0,-1.0,-1.0,7.332,0.0696721,999,156710 +64,16,search,2721.14,379.057,279.223,2.33664,103.049,0.92194,0.104881,-1.0,-1.0,8.071,0.0696721,999,156710 +64,17,insert,8.804,-1.0,-1.0,-1.0,-1.0,7.098,0.0715856,999,161773 +64,18,search,2639.29,400.355,288.807,2.34008,98.4303,0.92332,0.103959,-1.0,-1.0,8.064,0.0715856,999,161773 +64,19,insert,45.099,-1.0,-1.0,-1.0,-1.0,7.12,0.0782744,999,177161 +64,20,search,2655.04,446.26,307.722,2.35572,95.6592,0.92759,0.100352,-1.0,-1.0,7.872,0.0782744,999,177161 +64,21,insert,443.576,-1.0,-1.0,-1.0,-1.0,124.861,0.199902,1018,448898 +64,22,search,2852.39,961.397,566.215,2.59674,79.3837,0.91872,0.101788,-1.0,-1.0,35.13,0.199993,1022,448898 +64,23,insert,460.691,-1.0,-1.0,-1.0,-1.0,259.602,0.328074,1053,733493 +64,24,search,3066.49,1390.87,782.442,2.68344,77.5245,0.91622,0.103371,-1.0,-1.0,78.15,0.328117,1062,733493 +64,25,insert,50.668,-1.0,-1.0,-1.0,-1.0,23.164,0.344285,1064,777443 +64,26,search,3148.99,1400.32,819.546,2.6369,84.5871,0.91637,0.103615,-1.0,-1.0,9.676,0.344285,1064,777443 +64,27,insert,41.782,-1.0,-1.0,-1.0,-1.0,17.789,0.356204,1065,805394 +64,28,search,3157.17,1428.33,849.198,2.63435,77.996,0.91692,0.103149,-1.0,-1.0,10.106,0.356204,1065,805394 +64,29,insert,82.701,-1.0,-1.0,-1.0,-1.0,48.727,0.383698,1069,866391 +64,30,search,3243.73,1506.54,900.829,2.61476,84.946,0.91896,0.102205,-1.0,-1.0,29.156,0.383698,1071,866391 +64,31,insert,513.96,-1.0,-1.0,-1.0,-1.0,335.386,0.552921,1115,1239816 +64,32,search,3598.75,1843.84,1135.49,2.61469,99.6489,0.91092,0.107936,-1.0,-1.0,96.476,0.553407,1122,1239816 +64,33,insert,61.787,-1.0,-1.0,-1.0,-1.0,33.413,0.573868,1126,1291211 +64,34,search,3585.62,1849.01,1134.71,2.65708,88.5778,0.91006,0.108664,-1.0,-1.0,62.882,0.573882,1130,1291211 +64,35,insert,40.761,-1.0,-1.0,-1.0,-1.0,34.036,0.586277,1134,1324978 +64,36,search,3712.72,1884.07,1200.13,2.59181,95.4756,0.91107,0.108028,-1.0,-1.0,42.471,0.586279,1137,1324978 +64,37,insert,67.803,-1.0,-1.0,-1.0,-1.0,26.197,0.604752,1139,1371885 +64,38,search,3730.95,1912.15,1239.69,2.60032,95.8629,0.91006,0.108267,-1.0,-1.0,10.964,0.604752,1139,1371885 +64,39,insert,15.303,-1.0,-1.0,-1.0,-1.0,10.194,0.609275,1139,1379335 +64,40,search,3729.19,1919.78,1238.29,2.59377,97.6537,0.9105,0.107984,-1.0,-1.0,10.983,0.609275,1139,1379335 +64,41,insert,57.236,-1.0,-1.0,-1.0,-1.0,48.924,0.624207,1145,1413312 +64,42,search,3930.17,1932.81,1249.87,2.60046,99.6635,0.91102,0.107985,-1.0,-1.0,10.681,0.624207,1145,1413312 +64,43,insert,22.665,-1.0,-1.0,-1.0,-1.0,15.673,0.628627,1146,1423411 +64,44,search,3885.09,1947.56,1254.09,2.61554,99.1629,0.91106,0.107969,-1.0,-1.0,10.256,0.628627,1146,1423411 +64,45,insert,226.847,-1.0,-1.0,-1.0,-1.0,34.818,0.644894,1150,1457559 +64,46,search,3760.51,1964.56,1239.46,2.686,99.1448,0.91177,0.107316,-1.0,-1.0,10.315,0.644894,1150,1457559 +64,47,insert,317.506,-1.0,-1.0,-1.0,-1.0,264.848,0.748132,1178,1688593 +64,48,search,3980.84,2108.44,1380.86,2.63049,107.889,0.91133,0.109385,-1.0,-1.0,110.34,0.74835,1187,1688593 +64,49,insert,48.873,-1.0,-1.0,-1.0,-1.0,66.261,0.76353,1195,1723505 +64,50,search,4015.77,2082.94,1386.14,2.62056,112.372,0.91207,0.108626,-1.0,-1.0,46.321,0.76353,1198,1723505 +64,51,insert,410.519,-1.0,-1.0,-1.0,-1.0,289.158,0.904273,1238,2035040 +64,52,search,4270.79,2266.8,1545.67,2.63651,119.882,0.9137,0.108734,-1.0,-1.0,65.429,0.904361,1246,2035040 +64,53,insert,49.301,-1.0,-1.0,-1.0,-1.0,16.945,0.920874,1247,2078341 +64,54,search,4220.9,2280.27,1464.39,2.8638,109.179,0.91404,0.108533,-1.0,-1.0,9.934,0.920874,1247,2078341 +64,55,insert,375.888,-1.0,-1.0,-1.0,-1.0,456.454,1.06931,1297,2399905 +64,56,search,4613.54,2439.32,1732.05,2.59923,132.804,0.91369,0.110102,-1.0,-1.0,105.217,1.06931,1307,2399905 +64,57,insert,23.96,-1.0,-1.0,-1.0,-1.0,25.279,1.0777,1310,2419836 +64,58,search,4586.64,2407.26,1689.46,2.70535,129.619,0.91319,0.110856,-1.0,-1.0,48.253,1.07771,1314,2419836 +64,59,insert,237.718,-1.0,-1.0,-1.0,-1.0,199.74,1.17583,1333,2643083 +64,60,search,4713.57,2457.41,1763.97,2.63271,138.297,0.90689,0.117823,-1.0,-1.0,48.552,1.1759,1335,2643083 +64,61,insert,10.891,-1.0,-1.0,-1.0,-1.0,10.366,1.17948,1335,2653064 +64,62,search,4784.12,2464.92,1811.23,2.58567,153.289,0.90746,0.117809,-1.0,-1.0,18.506,1.17949,1336,2653064 +64,63,insert,4.756,-1.0,-1.0,-1.0,-1.0,10.292,1.18057,1336,2656118 +64,64,search,4840.05,2464.19,1864.4,2.56628,164.521,0.90761,0.117555,-1.0,-1.0,11.879,1.18057,1336,2656118 +64,65,insert,121.704,-1.0,-1.0,-1.0,-1.0,148.988,1.21204,1357,2723424 +64,66,search,4663.62,2468.13,1671.83,2.92842,139.751,0.90775,0.116817,-1.0,-1.0,11.031,1.21204,1357,2723424 +64,67,insert,59.91,-1.0,-1.0,-1.0,-1.0,78.777,1.234,1367,2769021 +64,68,search,4917.55,2493.27,1888.63,2.61351,145.428,0.90907,0.11564,-1.0,-1.0,21.68,1.234,1369,2769021 +64,69,insert,57.066,-1.0,-1.0,-1.0,-1.0,82.344,1.25611,1379,2821777 +64,70,search,4964.19,2495.61,1904.1,2.64779,155.12,0.91,0.114672,-1.0,-1.0,20.658,1.25611,1380,2821777 +64,71,insert,17.729,-1.0,-1.0,-1.0,-1.0,36.07,1.26203,1384,2834921 +64,72,search,4873.27,2499.39,1818.64,2.80486,143.96,0.91027,0.114485,-1.0,-1.0,11.103,1.26203,1384,2834921 +64,73,insert,8.046,-1.0,-1.0,-1.0,-1.0,10.355,1.26404,1384,2842044 +64,74,search,4662.47,2505.65,1638.91,3.06525,120.376,0.91029,0.11452,-1.0,-1.0,11.078,1.26404,1384,2842044 +64,75,insert,28.554,-1.0,-1.0,-1.0,-1.0,25.112,1.27211,1386,2858890 +64,76,search,4980.15,2512.95,1917.29,2.6076,156.148,0.91015,0.11481,-1.0,-1.0,11.072,1.27211,1386,2858890 +64,77,insert,35.684,-1.0,-1.0,-1.0,-1.0,10.399,1.28091,1386,2882818 +64,78,search,4976.02,2527.06,1917.67,2.6283,156.33,0.90983,0.115032,-1.0,-1.0,10.928,1.28091,1386,2882818 +64,79,insert,460.971,-1.0,-1.0,-1.0,-1.0,32.498,1.30751,1390,2947806 +64,80,search,4750.48,2548.78,1697.25,3.02889,129.785,0.90985,0.114626,-1.0,-1.0,11.002,1.30751,1390,2947806 +64,81,insert,37.064,-1.0,-1.0,-1.0,-1.0,52.572,1.31993,1396,2976895 +64,82,search,5027.33,2554.56,1934.29,2.64605,154.159,0.91102,0.114083,-1.0,-1.0,11.436,1.31993,1396,2976895 +64,83,insert,17.578,-1.0,-1.0,-1.0,-1.0,37.354,1.32588,1400,2990682 +64,84,search,5064.99,2558.65,1951.53,2.62494,145.832,0.91144,0.113844,-1.0,-1.0,13.093,1.32588,1400,2990682 +64,85,insert,44.917,-1.0,-1.0,-1.0,-1.0,61.536,1.34102,1405,3025613 +64,86,search,4990.9,2576.22,1875.01,2.76205,140.681,0.91205,0.112905,-1.0,-1.0,14.145,1.34102,1405,3025613 +64,87,insert,574.055,-1.0,-1.0,-1.0,-1.0,691.309,1.5448,1494,3468632 +64,88,search,5387.75,2720.13,2091.58,2.78009,159.432,0.91491,0.109854,-1.0,-1.0,124.351,1.54479,1509,3468632 +64,89,insert,404.361,-1.0,-1.0,-1.0,-1.0,508.891,1.70607,1581,3831692 +64,90,search,5702.04,2779.78,2214.29,2.88679,168.557,0.91865,0.105792,-1.0,-1.0,50.516,1.7064,1586,3831692 +64,91,insert,32.196,-1.0,-1.0,-1.0,-1.0,40.277,1.71659,1590,3864067 +64,92,search,5957.23,2787.03,2437.6,2.58567,189.506,0.91865,0.10565,-1.0,-1.0,12.305,1.71659,1590,3864067 +64,93,insert,275.036,-1.0,-1.0,-1.0,-1.0,294.332,1.8221,1629,4103827 +64,94,search,5888.04,2840.72,2306.88,2.86596,172.855,0.91955,0.10462,-1.0,-1.0,37.238,1.82234,1632,4103827 +64,95,insert,16.997,-1.0,-1.0,-1.0,-1.0,25.793,1.82804,1634,4119898 +64,96,search,5916.66,2842.41,2324.77,2.88803,171.48,0.91973,0.104353,-1.0,-1.0,15.759,1.82804,1634,4119898 +64,97,insert,10.766,-1.0,-1.0,-1.0,-1.0,25.968,1.83127,1636,4129367 +64,98,search,6117.93,2842.66,2512.49,2.63016,190.134,0.91951,0.104303,-1.0,-1.0,12.607,1.83127,1636,4129367 +64,99,insert,6.656,-1.0,-1.0,-1.0,-1.0,31.873,1.8335,1639,4134502 +64,100,search,5923.55,2837.85,2354.92,2.83582,181.23,0.91934,0.104498,-1.0,-1.0,13.298,1.8335,1639,4134502 +64,101,insert,37.469,-1.0,-1.0,-1.0,-1.0,93.62,1.84511,1649,4164482 +64,102,search,6199.86,2832.1,2549.99,2.60515,193.826,0.91973,0.104439,-1.0,-1.0,13.19,1.84511,1649,4164482 +64,103,insert,15.824,-1.0,-1.0,-1.0,-1.0,55.454,1.85108,1655,4178601 +64,104,search,5889.07,2825.08,2251.31,2.90414,171.495,0.91975,0.104487,-1.0,-1.0,26.986,1.85145,1657,4178601 +64,105,insert,9.428,-1.0,-1.0,-1.0,-1.0,19.004,1.85467,1658,4187774 +64,106,search,6067.49,2825.07,2425.57,2.72635,181.892,0.91962,0.104749,-1.0,-1.0,14.758,1.85467,1658,4187774 +64,107,insert,24.768,-1.0,-1.0,-1.0,-1.0,34.64,1.8593,1660,4200109 +64,108,search,5942.58,2827.34,2284.97,2.9041,175.873,0.91962,0.104921,-1.0,-1.0,24.053,1.85956,1661,4200109 +64,109,insert,485.176,-1.0,-1.0,-1.0,-1.0,558.126,2.02228,1730,4557867 +64,110,search,6637.35,2909.7,2782.8,2.57447,225.816,0.92101,0.103273,-1.0,-1.0,33.788,2.02255,1732,4557867 +64,111,insert,29.064,-1.0,-1.0,-1.0,-1.0,55.614,2.03407,1738,4587252 +64,112,search,6260.58,2919.14,2424.25,2.95996,181.822,0.92132,0.103141,-1.0,-1.0,16.518,2.03407,1738,4587252 +64,113,insert,12.372,-1.0,-1.0,-1.0,-1.0,30.665,2.03837,1740,4600056 +64,114,search,6602.94,2924.35,2718.56,2.68409,211.139,0.92172,0.102893,-1.0,-1.0,24.827,2.0386,1741,4600056 +64,115,insert,31.006,-1.0,-1.0,-1.0,-1.0,44.215,2.04678,1745,4627422 +64,116,search,6646.24,2932.06,2798.54,2.56826,219.97,0.92204,0.102585,-1.0,-1.0,17.215,2.04678,1745,4627422 +64,117,insert,16.372,-1.0,-1.0,-1.0,-1.0,22.83,2.0526,1746,4639292 +64,118,search,6355.5,2936.91,2512.25,2.87826,189.021,0.92214,0.102435,-1.0,-1.0,17.556,2.0526,1746,4639292 +64,119,insert,6.316,-1.0,-1.0,-1.0,-1.0,24.198,2.05443,1747,4643423 +64,120,search,6707.79,2938.27,2795.43,2.64371,221.212,0.92254,0.10212,-1.0,-1.0,25.173,2.05469,1748,4643423 +64,121,insert,17.557,-1.0,-1.0,-1.0,-1.0,57.198,2.05992,1753,4657252 +64,122,search,6716.27,2934.77,2835.79,2.54687,222.412,0.9223,0.102201,-1.0,-1.0,18.247,2.05992,1753,4657252 +64,123,insert,380.504,-1.0,-1.0,-1.0,-1.0,463.51,2.18724,1797,4938477 +64,124,search,6815.01,2987.69,2828.75,2.69943,224.598,0.92269,0.10321,-1.0,-1.0,134.393,2.18771,1805,4938477 +64,125,insert,57.278,-1.0,-1.0,-1.0,-1.0,92.241,2.20649,1815,4980492 +64,126,search,6944.53,2977.75,2900.57,2.58266,220.596,0.92346,0.102659,-1.0,-1.0,109.982,2.20652,1820,4980492 +64,127,insert,65.698,-1.0,-1.0,-1.0,-1.0,116.296,2.23159,1834,5030515 +64,128,search,7028.62,2967.04,2931,2.59624,225.599,0.92426,0.102161,-1.0,-1.0,64.747,2.23163,1837,5030515 +64,129,delete,26.443,-1.0,-1.0,-1.0,-1.0,91.197,2.22978,1806,5009391 +64,130,search,6861.19,2952.42,2852.46,2.63984,228.079,0.92288,0.102948,-1.0,-1.0,21.99,2.22978,1806,5009391 +64,131,delete,6.792,-1.0,-1.0,-1.0,-1.0,20.697,2.22978,1806,5004093 +64,132,search,6628.08,2949.46,2640.26,2.87616,210.861,0.9229,0.10289,-1.0,-1.0,22.589,2.22978,1806,5004093 +64,133,delete,15.767,-1.0,-1.0,-1.0,-1.0,20.134,2.22978,1806,4991787 +64,134,search,6865.4,2933.85,2877.2,2.62521,226.831,0.92276,0.103186,-1.0,-1.0,21.775,2.22978,1806,4991787 +64,135,delete,22.055,-1.0,-1.0,-1.0,-1.0,47.219,2.22742,1804,4974857 +64,136,search,6982.47,2925.65,2956.19,2.55784,234.508,0.92274,0.102976,-1.0,-1.0,22.335,2.22742,1804,4974857 +64,137,delete,6.377,-1.0,-1.0,-1.0,-1.0,20.403,2.22742,1804,4971386 +64,138,search,6647.41,2922.99,2650.07,2.83395,203.169,0.9227,0.102915,-1.0,-1.0,21.666,2.22742,1804,4971386 +64,139,delete,10.796,-1.0,-1.0,-1.0,-1.0,21.549,2.22742,1804,4963487 +64,140,search,6676.66,2916.5,2690.98,2.81427,206.833,0.92261,0.103047,-1.0,-1.0,21.254,2.22742,1804,4963487 +64,141,delete,25.754,-1.0,-1.0,-1.0,-1.0,88.26,2.22259,1799,4941830 +64,142,search,6847.06,2907.89,2839.11,2.58996,219.557,0.9224,0.103361,-1.0,-1.0,21.465,2.22259,1799,4941830 +64,143,delete,16.859,-1.0,-1.0,-1.0,-1.0,71.392,2.21822,1795,4925657 +64,144,search,6206.4,2903.07,2268.98,3.26355,167.899,0.92263,0.103238,-1.0,-1.0,24.347,2.21822,1795,4925657 +64,145,delete,5.46,-1.0,-1.0,-1.0,-1.0,20.909,2.21822,1795,4922686 +64,146,search,6569.64,2900.63,2581.43,2.88622,199.478,0.92252,0.103286,-1.0,-1.0,23.414,2.21822,1795,4922686 +64,147,delete,14.775,-1.0,-1.0,-1.0,-1.0,20.692,2.21822,1795,4913636 +64,148,search,6844.56,2892.29,2835.33,2.57608,222.499,0.92231,0.103517,-1.0,-1.0,23.082,2.21822,1795,4913636 +64,149,delete,234.826,-1.0,-1.0,-1.0,-1.0,938.215,2.13896,1726,4717250 +64,150,search,6560.45,2870.52,2686.87,2.60014,221.504,0.92092,0.104763,-1.0,-1.0,50.944,2.13959,1729,4717250 +64,151,delete,180.865,-1.0,-1.0,-1.0,-1.0,882.738,2.0694,1662,4560269 +128,2,search,2672.92,37.3734,193.408,1.57112,146.09,0.8551,0.130106,-1.0,-1.0,8.273,0.0184881,1000,38806 +128,3,insert,19.778,-1.0,-1.0,-1.0,-1.0,12.527,0.0226428,999,49334 +128,4,search,2577.16,66.2194,114.734,1.56425,137.43,0.86574,0.128987,-1.0,-1.0,14.508,0.0226534,998,49334 +128,5,insert,38.547,-1.0,-1.0,-1.0,-1.0,170.823,0.0329117,995,73557 +128,6,search,2556.42,187.295,189.044,1.91824,100.373,0.92412,0.104554,-1.0,-1.0,106.033,0.0329117,995,73557 +128,7,insert,44.506,-1.0,-1.0,-1.0,-1.0,103.567,0.042543,995,95766 +128,8,search,2588.87,240.494,203.781,1.75569,104.853,0.92577,0.103649,-1.0,-1.0,91.689,0.0427935,997,95766 +128,9,insert,7.264,-1.0,-1.0,-1.0,-1.0,78.597,0.0446825,997,100025 +128,10,search,2571.7,250.307,204.436,1.78213,98.4934,0.92722,0.100238,-1.0,-1.0,80.141,0.0446825,997,100025 +128,11,insert,19.346,-1.0,-1.0,-1.0,-1.0,80.695,0.0499327,997,111417 +128,12,search,2587.18,295.418,227.1,1.75309,98.531,0.92777,0.100455,-1.0,-1.0,82.699,0.0499327,997,111417 +128,13,insert,39.192,-1.0,-1.0,-1.0,-1.0,81.02,0.0609344,997,137139 +128,14,search,2607.11,340.65,244.88,1.7373,97.6542,0.9243,0.102713,-1.0,-1.0,22.357,0.0610009,998,137139 +128,15,insert,33.217,-1.0,-1.0,-1.0,-1.0,7.481,0.0696093,998,156710 +128,16,search,2728.37,376.497,266.477,1.56422,114.592,0.9225,0.103704,-1.0,-1.0,20.464,0.0696162,1000,156710 +128,17,insert,9.048,-1.0,-1.0,-1.0,-1.0,7.315,0.0716815,1000,161773 +128,18,search,2732.98,392.205,276.734,1.5835,111.851,0.92366,0.102827,-1.0,-1.0,7.88,0.0716815,1000,161773 +128,19,insert,44.099,-1.0,-1.0,-1.0,-1.0,7.187,0.0784176,1000,177161 +128,20,search,2719.71,437.328,298.856,1.60736,99.0863,0.92789,0.0995028,-1.0,-1.0,8.126,0.0784176,1000,177161 +128,21,insert,440.718,-1.0,-1.0,-1.0,-1.0,117.706,0.200022,1019,448898 +128,22,search,2843.27,957.76,547.629,1.58212,86.4297,0.91922,0.101238,-1.0,-1.0,15.914,0.200021,1020,448898 +128,23,insert,462.344,-1.0,-1.0,-1.0,-1.0,270.342,0.328597,1057,733493 +128,24,search,3055.96,1347.73,748.178,1.60548,81.3464,0.91455,0.103761,-1.0,-1.0,76.181,0.328595,1066,733493 +128,25,insert,51.247,-1.0,-1.0,-1.0,-1.0,22.264,0.345498,1068,777443 +128,26,search,3159.81,1361.1,787.472,1.56722,84.5448,0.91515,0.103898,-1.0,-1.0,10.008,0.345498,1068,777443 +128,27,insert,42.327,-1.0,-1.0,-1.0,-1.0,16.808,0.357461,1069,805394 +128,28,search,3135.43,1387.96,818.094,1.57461,76.0259,0.91631,0.103092,-1.0,-1.0,10.714,0.357461,1069,805394 +128,29,insert,83.756,-1.0,-1.0,-1.0,-1.0,44.067,0.385205,1073,866391 +128,30,search,3247.34,1465.03,857.04,1.57942,81.5404,0.91711,0.103313,-1.0,-1.0,19.549,0.385205,1074,866391 +128,31,insert,490.293,-1.0,-1.0,-1.0,-1.0,374.179,0.551257,1119,1239816 +128,32,search,3468.09,1819.27,1017.75,1.63485,93.6226,0.91062,0.107705,-1.0,-1.0,95.024,0.551731,1125,1239816 +128,33,insert,72.548,-1.0,-1.0,-1.0,-1.0,27.9,0.574347,1128,1291211 +128,34,search,3631.86,1838.72,1128.5,1.52663,108.611,0.91159,0.107419,-1.0,-1.0,67.711,0.574363,1132,1291211 +128,35,insert,58.072,-1.0,-1.0,-1.0,-1.0,48.49,0.587698,1138,1324978 +128,36,search,3647.91,1864.39,1151.51,1.54002,109.336,0.91216,0.106088,-1.0,-1.0,44.172,0.587822,1142,1324978 +128,37,insert,70.171,-1.0,-1.0,-1.0,-1.0,36.307,0.607045,1145,1371885 +128,38,search,3660.8,1881.28,1167.42,1.53074,100.707,0.91112,0.106482,-1.0,-1.0,16.776,0.607045,1146,1371885 +128,39,insert,10.05,-1.0,-1.0,-1.0,-1.0,9.774,0.609242,1146,1379335 +128,40,search,3568.35,1884.38,1071.17,1.70063,94.0265,0.91113,0.107087,-1.0,-1.0,11.165,0.609242,1146,1379335 +128,41,insert,65.889,-1.0,-1.0,-1.0,-1.0,46.712,0.62536,1151,1413312 +128,42,search,3709.76,1900.02,1174.61,1.56063,109.564,0.9115,0.107412,-1.0,-1.0,10.085,0.62536,1151,1413312 +128,43,insert,17.864,-1.0,-1.0,-1.0,-1.0,27.933,0.629531,1154,1423411 +128,44,search,3720.37,1905.36,1186.06,1.52132,110.368,0.91175,0.107427,-1.0,-1.0,10.578,0.629531,1154,1423411 +128,45,insert,234.891,-1.0,-1.0,-1.0,-1.0,47.866,0.642682,1160,1457559 +128,46,search,3758.61,1917.02,1194.5,1.50288,110.1,0.91241,0.106509,-1.0,-1.0,10.125,0.642682,1160,1457559 +128,47,insert,357.856,-1.0,-1.0,-1.0,-1.0,299.407,0.749851,1192,1688593 +128,48,search,3876.12,2042.75,1264.3,1.58569,109.413,0.911,0.109397,-1.0,-1.0,94.367,0.74999,1199,1688593 +128,49,insert,49.951,-1.0,-1.0,-1.0,-1.0,27.559,0.764228,1201,1723505 +128,50,search,3867.46,2052.05,1231.36,1.63839,102.87,0.91241,0.10851,-1.0,-1.0,34.011,0.764229,1203,1723505 +128,51,insert,396.871,-1.0,-1.0,-1.0,-1.0,226.529,0.902507,1233,2035040 +128,52,search,3967.37,2275.67,1299.85,1.73018,104.569,0.91476,0.107578,-1.0,-1.0,50.752,0.902566,1238,2035040 +128,53,insert,57.107,-1.0,-1.0,-1.0,-1.0,36.495,0.921763,1241,2078341 +128,54,search,4134.24,2290.9,1406.42,1.63922,112.607,0.91496,0.107858,-1.0,-1.0,17.827,0.921977,1242,2078341 +128,55,insert,375.758,-1.0,-1.0,-1.0,-1.0,441.649,1.07026,1292,2399905 +128,56,search,4275.94,2444.12,1457.7,1.71297,112.143,0.91459,0.108633,-1.0,-1.0,93.156,1.07026,1300,2399905 +128,57,insert,24.301,-1.0,-1.0,-1.0,-1.0,27.733,1.07801,1303,2419836 +128,58,search,4522.63,2429.77,1659.22,1.54172,131.006,0.91462,0.108049,-1.0,-1.0,65.763,1.07802,1309,2419836 +128,59,insert,238.196,-1.0,-1.0,-1.0,-1.0,246.929,1.17777,1335,2643083 +128,60,search,4689.56,2451.35,1737.72,1.53919,136.991,0.90933,0.114786,-1.0,-1.0,71.702,1.17783,1339,2643083 +128,61,insert,18.728,-1.0,-1.0,-1.0,-1.0,10.54,1.18183,1339,2653064 +128,62,search,4399.76,2448.45,1482.53,1.79632,116.341,0.90872,0.115477,-1.0,-1.0,11.557,1.18183,1339,2653064 +128,63,insert,4.994,-1.0,-1.0,-1.0,-1.0,10.679,1.18277,1339,2656118 +128,64,search,4300.7,2450.54,1406.54,1.9001,111.818,0.90895,0.115223,-1.0,-1.0,10.843,1.18277,1339,2656118 +128,65,insert,96.497,-1.0,-1.0,-1.0,-1.0,118.642,1.21013,1355,2723424 +128,66,search,4344.74,2481.23,1414.44,1.92827,107.8,0.90971,0.115128,-1.0,-1.0,10.815,1.21013,1355,2723424 +128,67,insert,50.475,-1.0,-1.0,-1.0,-1.0,83.197,1.23159,1367,2769021 +128,68,search,4865.18,2501.05,1837.8,1.48516,152.946,0.91084,0.114243,-1.0,-1.0,22.388,1.23159,1369,2769021 +128,69,insert,71.992,-1.0,-1.0,-1.0,-1.0,91.249,1.25528,1380,2821777 +128,70,search,4818.08,2507.25,1837.02,1.48939,161.161,0.91229,0.112735,-1.0,-1.0,29.664,1.25528,1382,2821777 +128,71,insert,20.39,-1.0,-1.0,-1.0,-1.0,42.327,1.2608,1387,2834921 +128,72,search,4760.19,2496.71,1710.85,1.65207,139.021,0.91219,0.112676,-1.0,-1.0,11.215,1.2608,1387,2834921 +128,73,insert,10.428,-1.0,-1.0,-1.0,-1.0,39.387,1.26407,1390,2842044 +128,74,search,4632.54,2496.01,1610.51,1.7445,124.843,0.91198,0.112816,-1.0,-1.0,11.676,1.26407,1390,2842044 +128,75,insert,24.51,-1.0,-1.0,-1.0,-1.0,33.275,1.27168,1393,2858890 +128,76,search,4716.86,2502.38,1678.82,1.64033,137.458,0.91211,0.11258,-1.0,-1.0,11.768,1.27168,1393,2858890 +128,77,insert,35.895,-1.0,-1.0,-1.0,-1.0,22.862,1.28123,1395,2882818 +128,78,search,4736.67,2509.86,1649.89,1.74866,133.845,0.91192,0.113269,-1.0,-1.0,11.145,1.28123,1395,2882818 +128,79,insert,522.997,-1.0,-1.0,-1.0,-1.0,28.77,1.3082,1398,2947806 +128,80,search,4742.67,2535.28,1696.37,1.69836,133.443,0.91112,0.114186,-1.0,-1.0,11.044,1.3082,1398,2947806 +128,81,insert,40.581,-1.0,-1.0,-1.0,-1.0,26.973,1.32114,1400,2976895 +128,82,search,4717.08,2552.33,1642.97,1.7715,128.507,0.91269,0.113262,-1.0,-1.0,13.845,1.32114,1400,2976895 +128,83,insert,21.89,-1.0,-1.0,-1.0,-1.0,43.234,1.32735,1404,2990682 +128,84,search,4978.83,2545.85,1881.72,1.52826,169.901,0.91255,0.113483,-1.0,-1.0,12.03,1.32735,1404,2990682 +128,85,insert,39.963,-1.0,-1.0,-1.0,-1.0,36.838,1.34118,1407,3025613 +128,86,search,5027.54,2567.03,1894.99,1.50228,171.252,0.91364,0.112676,-1.0,-1.0,11.94,1.34118,1407,3025613 +128,87,insert,583.273,-1.0,-1.0,-1.0,-1.0,713.119,1.5438,1496,3468632 +128,88,search,5274.38,2714.3,1987.12,1.65221,162.617,0.91636,0.109635,-1.0,-1.0,133.633,1.54406,1511,3468632 +128,89,insert,407.613,-1.0,-1.0,-1.0,-1.0,525.221,1.70293,1589,3831692 +128,90,search,5671.03,2765.8,2162.66,1.61618,181.652,0.92028,0.105347,-1.0,-1.0,53.068,1.70303,1594,3831692 +128,91,insert,34.169,-1.0,-1.0,-1.0,-1.0,78.722,1.71425,1604,3864067 +128,92,search,5821.99,2747.5,2286.43,1.48336,187.114,0.91968,0.105539,-1.0,-1.0,12.755,1.71425,1604,3864067 +128,93,insert,276.199,-1.0,-1.0,-1.0,-1.0,267.595,1.81715,1637,4103827 +128,94,search,5678.44,2813.67,2103.71,1.72851,170.906,0.91939,0.105292,-1.0,-1.0,31.991,1.81715,1639,4103827 +128,95,insert,18.536,-1.0,-1.0,-1.0,-1.0,38.089,1.82414,1643,4119898 +128,96,search,6057.54,2810.38,2421.27,1.47388,211.26,0.9196,0.105084,-1.0,-1.0,12.83,1.82414,1643,4119898 +128,97,insert,10.326,-1.0,-1.0,-1.0,-1.0,12.189,1.82646,1643,4129367 +128,98,search,5702.45,2816.05,2137.41,1.67699,170.89,0.91974,0.105019,-1.0,-1.0,13.07,1.82646,1643,4129367 +128,99,insert,8.41,-1.0,-1.0,-1.0,-1.0,12.688,1.8286,1643,4134502 +128,100,search,5987.11,2820.8,2389.7,1.4877,197.015,0.91982,0.104903,-1.0,-1.0,13.215,1.8286,1643,4134502 +128,101,insert,40.264,-1.0,-1.0,-1.0,-1.0,49.839,1.83958,1647,4164482 +128,102,search,5694.63,2833.56,2086.72,1.73857,167.614,0.92025,0.104626,-1.0,-1.0,14.783,1.83958,1647,4164482 +128,103,insert,22.082,-1.0,-1.0,-1.0,-1.0,12.923,1.8457,1647,4178601 +128,104,search,5749.82,2845.16,2148.51,1.68581,176.209,0.92047,0.104456,-1.0,-1.0,14.423,1.8457,1647,4178601 +128,105,insert,16.612,-1.0,-1.0,-1.0,-1.0,32.099,1.85116,1649,4187774 +128,106,search,5413.62,2847.28,1870.44,1.94771,143.915,0.92032,0.104794,-1.0,-1.0,13.717,1.85116,1649,4187774 +128,107,insert,27.985,-1.0,-1.0,-1.0,-1.0,14.34,1.8579,1649,4200109 +128,108,search,6076.41,2853.33,2452.8,1.45184,219.078,0.92012,0.104965,-1.0,-1.0,13.389,1.8579,1649,4200109 +128,109,insert,508.097,-1.0,-1.0,-1.0,-1.0,566.208,2.0223,1719,4557867 +128,110,search,6250.29,2931.18,2450.76,1.59353,202.399,0.92161,0.103518,-1.0,-1.0,71.441,2.02237,1725,4557867 +128,111,insert,32.616,-1.0,-1.0,-1.0,-1.0,77.828,2.03297,1734,4587252 +128,112,search,6527.12,2917.35,2662.05,1.47734,233.423,0.92226,0.103215,-1.0,-1.0,16.59,2.03297,1734,4587252 +128,113,insert,13.929,-1.0,-1.0,-1.0,-1.0,45.537,2.03783,1738,4600056 +128,114,search,6084.71,2916.91,2295.75,1.7641,183.922,0.92221,0.103193,-1.0,-1.0,17.617,2.03783,1738,4600056 +128,115,insert,38.522,-1.0,-1.0,-1.0,-1.0,84.571,2.05028,1748,4627422 +128,116,search,6440.85,2910.52,2565.7,1.51956,217.169,0.92258,0.102955,-1.0,-1.0,17.666,2.05028,1748,4627422 +128,117,insert,16.603,-1.0,-1.0,-1.0,-1.0,42.956,2.05526,1751,4639292 +128,118,search,6181.35,2911.34,2348.08,1.73787,184.706,0.92262,0.102713,-1.0,-1.0,18.672,2.05526,1751,4639292 +128,119,insert,6.167,-1.0,-1.0,-1.0,-1.0,17.446,2.05682,1751,4643423 +128,120,search,6285.1,2913.87,2457.09,1.65481,196.518,0.92262,0.102801,-1.0,-1.0,18.54,2.05682,1751,4643423 +128,121,insert,15.847,-1.0,-1.0,-1.0,-1.0,54.095,2.0624,1756,4657252 +128,122,search,6507.64,2909.48,2618.13,1.51251,215.915,0.92286,0.102655,-1.0,-1.0,17.725,2.0624,1756,4657252 +128,123,insert,364.47,-1.0,-1.0,-1.0,-1.0,444.934,2.18895,1798,4938477 +128,124,search,6696.12,2972.57,2724.92,1.48439,225.272,0.92318,0.102883,-1.0,-1.0,122.379,2.18966,1806,4938477 +128,125,insert,54.468,-1.0,-1.0,-1.0,-1.0,68.089,2.20631,1813,4980492 +128,126,search,6790.38,2965.59,2769.86,1.48993,230.4,0.92326,0.102501,-1.0,-1.0,75.712,2.20633,1815,4980492 +128,127,insert,60.263,-1.0,-1.0,-1.0,-1.0,95.113,2.22727,1825,5030515 +128,128,search,6626.47,2978.65,2597.07,1.63349,212.357,0.92397,0.102067,-1.0,-1.0,49.162,2.22728,1827,5030515 +128,129,delete,22.025,-1.0,-1.0,-1.0,-1.0,89.334,2.22556,1796,5009391 +128,130,search,6474.79,2966.61,2512.51,1.66005,210.533,0.92287,0.102821,-1.0,-1.0,22.5,2.22556,1796,5009391 +128,131,delete,7.617,-1.0,-1.0,-1.0,-1.0,20.786,2.22556,1796,5004093 +128,132,search,6760.28,2963.63,2780.61,1.4696,232.463,0.92289,0.102829,-1.0,-1.0,21.653,2.22556,1796,5004093 +128,133,delete,15.215,-1.0,-1.0,-1.0,-1.0,20.319,2.22556,1796,4991787 +128,134,search,6748.44,2949.28,2765.75,1.48629,224.709,0.92269,0.102958,-1.0,-1.0,21.504,2.22556,1796,4991787 +128,135,delete,20.041,-1.0,-1.0,-1.0,-1.0,47.122,2.22298,1794,4974857 +128,136,search,6701.61,2940.97,2719.4,1.47086,225.483,0.92294,0.102725,-1.0,-1.0,29.69,2.22322,1795,4974857 +128,137,delete,3.645,-1.0,-1.0,-1.0,-1.0,20.462,2.22322,1795,4971386 +128,138,search,6661.84,2935.76,2683.09,1.532,222.81,0.92286,0.102908,-1.0,-1.0,21.85,2.22322,1795,4971386 +128,139,delete,11.537,-1.0,-1.0,-1.0,-1.0,21.169,2.22322,1795,4963487 +128,140,search,6743.66,2928.45,2752.26,1.4665,238.529,0.92279,0.102956,-1.0,-1.0,21.319,2.22322,1795,4963487 +128,141,delete,26.521,-1.0,-1.0,-1.0,-1.0,74.554,2.21841,1789,4941830 +128,142,search,6465.21,2920.1,2513.18,1.61547,208.331,0.92273,0.102956,-1.0,-1.0,21.831,2.21841,1789,4941830 +128,143,delete,18.795,-1.0,-1.0,-1.0,-1.0,53.512,2.21435,1786,4925657 +128,144,search,6464.88,2913.74,2530.09,1.61155,204.737,0.92248,0.103227,-1.0,-1.0,21.384,2.21435,1786,4925657 +128,145,delete,2.652,-1.0,-1.0,-1.0,-1.0,20.083,2.21435,1786,4922686 +128,146,search,6643.56,2911.38,2664.46,1.49956,226.949,0.9224,0.103458,-1.0,-1.0,22.681,2.21435,1786,4922686 +128,147,delete,16.747,-1.0,-1.0,-1.0,-1.0,20.977,2.21435,1786,4913636 +128,148,search,6312.67,2904.26,2374.72,1.69628,193.394,0.92221,0.103657,-1.0,-1.0,21.821,2.21435,1786,4913636 +128,149,delete,236.893,-1.0,-1.0,-1.0,-1.0,1040.08,2.13458,1710,4717250 +128,150,search,6054.93,2897.64,2303.56,1.73004,185.692,0.92174,0.104141,-1.0,-1.0,48.316,2.13515,1713,4717250 +128,151,delete,164.27,-1.0,-1.0,-1.0,-1.0,1020.29,2.06202,1632,4560269 +256,2,search,2866.33,37.4413,330.337,1.38984,158.664,0.8551,0.130106,-1.0,-1.0,8.102,0.0184881,1000,38806 +256,3,insert,20.283,-1.0,-1.0,-1.0,-1.0,16.146,0.0226681,998,49334 +256,4,search,2651.24,65.2517,113.564,1.3625,157.538,0.86613,0.128797,-1.0,-1.0,14.509,0.0226611,997,49334 +256,5,insert,40.119,-1.0,-1.0,-1.0,-1.0,175.679,0.0329766,993,73557 +256,6,search,2630.64,184.092,193.766,1.61817,109.375,0.92433,0.104255,-1.0,-1.0,105.528,0.0329766,993,73557 +256,7,insert,44.735,-1.0,-1.0,-1.0,-1.0,103.687,0.0425054,993,95766 +256,8,search,2663.43,234.618,202.5,1.43228,122.105,0.9262,0.103389,-1.0,-1.0,92.553,0.0426968,995,95766 +256,9,insert,6.946,-1.0,-1.0,-1.0,-1.0,78.873,0.0444112,995,100025 +256,10,search,2645.79,242.678,201.303,1.41079,120.474,0.92898,0.0992193,-1.0,-1.0,80.217,0.0444112,995,100025 +256,11,insert,19.58,-1.0,-1.0,-1.0,-1.0,80.938,0.0498874,995,111417 +256,12,search,2592.93,287.737,228.644,1.37054,114.145,0.92977,0.0991206,-1.0,-1.0,22.504,0.0499416,996,111417 +256,13,insert,39.701,-1.0,-1.0,-1.0,-1.0,7.54,0.061167,996,137139 +256,14,search,2646.73,329.176,246.49,1.26251,124.809,0.92541,0.102488,-1.0,-1.0,21.691,0.0611767,998,137139 +256,15,insert,33.622,-1.0,-1.0,-1.0,-1.0,7.52,0.0697745,998,156710 +256,16,search,2736.8,363.55,265.618,1.17019,122.11,0.92281,0.104133,-1.0,-1.0,8.082,0.0697745,998,156710 +256,17,insert,9.018,-1.0,-1.0,-1.0,-1.0,7.422,0.0715571,998,161773 +256,18,search,2722.54,383.144,280.243,1.22124,117.091,0.92457,0.102932,-1.0,-1.0,8.016,0.0715571,998,161773 +256,19,insert,43.901,-1.0,-1.0,-1.0,-1.0,7.708,0.0780545,998,177161 +256,20,search,2731.35,426.895,296.71,1.15218,115.739,0.92857,0.0994008,-1.0,-1.0,7.988,0.0780545,998,177161 +256,21,insert,434.263,-1.0,-1.0,-1.0,-1.0,130.134,0.2,1020,448898 +256,22,search,2989.65,920.288,555.602,1.09872,100.624,0.91983,0.101275,-1.0,-1.0,24.346,0.199999,1022,448898 +256,23,insert,461.042,-1.0,-1.0,-1.0,-1.0,253.765,0.328127,1055,733493 +256,24,search,3149,1326.46,796.222,1.01771,96.2053,0.91588,0.104384,-1.0,-1.0,84.882,0.328126,1066,733493 +256,25,insert,52.962,-1.0,-1.0,-1.0,-1.0,23.132,0.344823,1068,777443 +256,26,search,3257.76,1323.09,791.535,1.02197,101.93,0.91588,0.104126,-1.0,-1.0,14.648,0.344825,1069,777443 +256,27,insert,41.55,-1.0,-1.0,-1.0,-1.0,17.491,0.356823,1070,805394 +256,28,search,3007.11,1346.48,686.649,1.25006,60.8945,0.91612,0.103925,-1.0,-1.0,10.542,0.356823,1070,805394 +256,29,insert,80.746,-1.0,-1.0,-1.0,-1.0,49.045,0.38411,1074,866391 +256,30,search,3225.46,1422.7,853.496,1.0155,90.8802,0.91789,0.103308,-1.0,-1.0,31.605,0.384109,1076,866391 +256,31,insert,535.243,-1.0,-1.0,-1.0,-1.0,338.05,0.554277,1118,1239816 +256,32,search,3496.15,1769.06,1097.16,0.937941,105.159,0.91086,0.10801,-1.0,-1.0,90.883,0.554304,1124,1239816 +256,33,insert,65.119,-1.0,-1.0,-1.0,-1.0,10.187,0.574957,1124,1291211 +256,34,search,3590.48,1796.63,1128.59,0.965828,94.8247,0.91146,0.107481,-1.0,-1.0,65.144,0.574972,1128,1291211 +256,35,insert,44.384,-1.0,-1.0,-1.0,-1.0,27.639,0.586001,1131,1324978 +256,36,search,3621.82,1836.28,1149.15,0.949324,101.944,0.91204,0.106854,-1.0,-1.0,32.279,0.586003,1133,1324978 +256,37,insert,73.402,-1.0,-1.0,-1.0,-1.0,25.869,0.605043,1135,1371885 +256,38,search,3680.43,1867.93,1186.04,0.982134,106.601,0.91197,0.107114,-1.0,-1.0,9.939,0.605043,1135,1371885 +256,39,insert,14.426,-1.0,-1.0,-1.0,-1.0,9.05,0.608616,1135,1379335 +256,40,search,3678.11,1877.3,1190.66,0.975344,96.5397,0.91244,0.107044,-1.0,-1.0,11.623,0.608616,1135,1379335 +256,41,insert,69.362,-1.0,-1.0,-1.0,-1.0,61.036,0.625497,1142,1413312 +256,42,search,3678.45,1889.6,1184.38,0.982888,97.1329,0.91241,0.107267,-1.0,-1.0,10.661,0.625497,1142,1413312 +256,43,insert,21.297,-1.0,-1.0,-1.0,-1.0,23.908,0.630431,1144,1423411 +256,44,search,3680.06,1896.38,1198.79,0.997243,99.01,0.91228,0.107439,-1.0,-1.0,17.045,0.63057,1145,1423411 +256,45,insert,224.293,-1.0,-1.0,-1.0,-1.0,48.184,0.64474,1151,1457559 +256,46,search,3700.12,1897.31,1192.76,0.971471,99.873,0.91199,0.106876,-1.0,-1.0,10.125,0.64474,1151,1457559 +256,47,insert,334.543,-1.0,-1.0,-1.0,-1.0,297.361,0.749693,1181,1688593 +256,48,search,3925.2,2031.93,1323.09,0.943001,115.165,0.91136,0.109144,-1.0,-1.0,101.757,0.749692,1188,1688593 +256,49,insert,49.098,-1.0,-1.0,-1.0,-1.0,49.923,0.764331,1193,1723505 +256,50,search,3931.86,2031.26,1315.67,0.95153,115.329,0.91121,0.109561,-1.0,-1.0,53.741,0.764331,1196,1723505 +256,51,insert,403.629,-1.0,-1.0,-1.0,-1.0,275.633,0.903658,1231,2035040 +256,52,search,4049.83,2227.73,1365.35,1.04454,109.593,0.91414,0.108013,-1.0,-1.0,65.174,0.903742,1239,2035040 +256,53,insert,48.623,-1.0,-1.0,-1.0,-1.0,23.635,0.920441,1241,2078341 +256,54,search,4026.55,2234.68,1315.46,1.03059,105.334,0.9147,0.10715,-1.0,-1.0,10.294,0.920441,1241,2078341 +256,55,insert,388.35,-1.0,-1.0,-1.0,-1.0,431.382,1.0691,1294,2399905 +256,56,search,4508.55,2386.52,1653.19,0.934143,138.976,0.9147,0.109905,-1.0,-1.0,79.398,1.0691,1302,2399905 +256,57,insert,23.073,-1.0,-1.0,-1.0,-1.0,16.346,1.07595,1303,2419836 +256,58,search,4482.37,2367.03,1641.36,0.958809,136.756,0.91404,0.110006,-1.0,-1.0,38.654,1.07596,1306,2419836 +256,59,insert,262.715,-1.0,-1.0,-1.0,-1.0,138.061,1.17566,1317,2643083 +256,60,search,4556.06,2445.47,1668.06,0.986127,135.888,0.90783,0.117466,-1.0,-1.0,32.403,1.17566,1320,2643083 +256,61,insert,12.504,-1.0,-1.0,-1.0,-1.0,9.865,1.17978,1320,2653064 +256,62,search,4657.78,2450.05,1728.37,0.933409,140.965,0.90795,0.117649,-1.0,-1.0,12.166,1.17978,1320,2653064 +256,63,insert,5.623,-1.0,-1.0,-1.0,-1.0,10.825,1.18088,1320,2656118 +256,64,search,4649.03,2453.17,1739.01,0.933658,149.92,0.90797,0.117517,-1.0,-1.0,12.316,1.18088,1320,2656118 +256,65,insert,106.05,-1.0,-1.0,-1.0,-1.0,94.81,1.20921,1332,2723424 +256,66,search,4634.52,2493.86,1714.58,0.947239,143.737,0.90884,0.116484,-1.0,-1.0,10.767,1.20921,1332,2723424 +256,67,insert,51.307,-1.0,-1.0,-1.0,-1.0,112.12,1.23034,1348,2769021 +256,68,search,4542.21,2497.1,1581.95,1.08508,132.845,0.90983,0.115543,-1.0,-1.0,16.93,1.23034,1349,2769021 +256,69,insert,61.417,-1.0,-1.0,-1.0,-1.0,86.023,1.2527,1359,2821777 +256,70,search,4780.07,2507.73,1801.43,0.966099,158.153,0.91055,0.11448,-1.0,-1.0,20.453,1.2527,1360,2821777 +256,71,insert,18.378,-1.0,-1.0,-1.0,-1.0,37.117,1.25796,1364,2834921 +256,72,search,4834.85,2509.13,1817.14,0.922589,167.184,0.91112,0.114098,-1.0,-1.0,11.275,1.25796,1364,2834921 +256,73,insert,12.435,-1.0,-1.0,-1.0,-1.0,10.345,1.26159,1364,2842044 +256,74,search,4778.43,2514.37,1796.74,0.960248,153.768,0.91113,0.114122,-1.0,-1.0,11.267,1.26159,1364,2842044 +256,75,insert,29.17,-1.0,-1.0,-1.0,-1.0,24.27,1.2705,1366,2858890 +256,76,search,4562.94,2524.17,1607.64,1.09059,132.605,0.91126,0.113863,-1.0,-1.0,11.524,1.2705,1366,2858890 +256,77,insert,39.64,-1.0,-1.0,-1.0,-1.0,10.593,1.28015,1366,2882818 +256,78,search,4782.35,2537.01,1817.36,0.958382,148.02,0.91092,0.114045,-1.0,-1.0,11.797,1.28015,1366,2882818 +256,79,insert,514.244,-1.0,-1.0,-1.0,-1.0,18.395,1.30633,1367,2947806 +256,80,search,4880.56,2575.58,1870.15,0.921732,161.661,0.91098,0.114338,-1.0,-1.0,18.337,1.30654,1368,2947806 +256,81,insert,38.66,-1.0,-1.0,-1.0,-1.0,55.447,1.31819,1374,2976895 +256,82,search,4784,2581.7,1753.4,0.995773,143.095,0.91195,0.113698,-1.0,-1.0,11.056,1.31819,1374,2976895 +256,83,insert,17.081,-1.0,-1.0,-1.0,-1.0,35.815,1.32434,1378,2990682 +256,84,search,4633.4,2577.11,1646.72,1.06359,129.527,0.91184,0.113599,-1.0,-1.0,11.679,1.32434,1378,2990682 +256,85,insert,39.969,-1.0,-1.0,-1.0,-1.0,61.15,1.3397,1385,3025613 +256,86,search,4928.29,2585.27,1887.93,0.92073,154.339,0.91249,0.113156,-1.0,-1.0,11.172,1.3397,1385,3025613 +256,87,insert,569.139,-1.0,-1.0,-1.0,-1.0,773.146,1.5473,1487,3468632 +256,88,search,5326.17,2689.83,2057.41,0.925801,163.066,0.91491,0.110715,-1.0,-1.0,116.108,1.54746,1499,3468632 +256,89,insert,414.199,-1.0,-1.0,-1.0,-1.0,504.674,1.70663,1574,3831692 +256,90,search,5748.78,2764.38,2270.67,0.903898,186.019,0.91887,0.106379,-1.0,-1.0,77.178,1.70668,1582,3831692 +256,91,insert,36.18,-1.0,-1.0,-1.0,-1.0,60.497,1.71714,1589,3864067 +256,92,search,5785.23,2750.71,2285.2,0.881235,184.123,0.91881,0.106611,-1.0,-1.0,12.829,1.71714,1589,3864067 +256,93,insert,307.138,-1.0,-1.0,-1.0,-1.0,259.868,1.82079,1619,4103827 +256,94,search,5876.67,2829.51,2316.68,0.946039,198.877,0.91912,0.105968,-1.0,-1.0,29.653,1.82079,1621,4103827 +256,95,insert,18.506,-1.0,-1.0,-1.0,-1.0,51.153,1.82827,1627,4119898 +256,96,search,5964.28,2825.48,2380.98,0.911465,187.887,0.91964,0.105314,-1.0,-1.0,13.181,1.82827,1627,4119898 +256,97,insert,12.408,-1.0,-1.0,-1.0,-1.0,20.91,1.8316,1628,4129367 +256,98,search,5828.58,2828.91,2275.18,0.97034,184.668,0.91976,0.105313,-1.0,-1.0,13.327,1.8316,1628,4129367 +256,99,insert,8.518,-1.0,-1.0,-1.0,-1.0,12.492,1.83383,1628,4134502 +256,100,search,5949.02,2832.12,2384.27,0.899291,193.251,0.91983,0.105226,-1.0,-1.0,13.375,1.83383,1628,4134502 +256,101,insert,38.787,-1.0,-1.0,-1.0,-1.0,76.393,1.84491,1636,4164482 +256,102,search,5794.24,2833.34,2234.06,1.04672,185.466,0.91992,0.105399,-1.0,-1.0,12.908,1.84491,1636,4164482 +256,103,insert,17.349,-1.0,-1.0,-1.0,-1.0,50.529,1.85182,1642,4178601 +256,104,search,6008.08,2826.94,2408.94,0.909554,195.455,0.9199,0.105363,-1.0,-1.0,12.987,1.85182,1642,4178601 +256,105,insert,8.85,-1.0,-1.0,-1.0,-1.0,12.267,1.85431,1642,4187774 +256,106,search,5813.17,2832.66,2229.58,1.02871,187.355,0.91983,0.105587,-1.0,-1.0,13.668,1.85431,1642,4187774 +256,107,insert,18.205,-1.0,-1.0,-1.0,-1.0,12.785,1.85962,1642,4200109 +256,108,search,5842.4,2837.99,2244.56,0.989398,186.496,0.91989,0.105406,-1.0,-1.0,23.361,1.85983,1643,4200109 +256,109,insert,500.814,-1.0,-1.0,-1.0,-1.0,624.11,2.0205,1720,4557867 +256,110,search,6396.58,2901.06,2596.91,0.929012,225.455,0.92197,0.103476,-1.0,-1.0,80.567,2.02122,1728,4557867 +256,111,insert,31.387,-1.0,-1.0,-1.0,-1.0,75.726,2.03278,1737,4587252 +256,112,search,6109.01,2884.77,2291.3,1.078,182.615,0.9221,0.103374,-1.0,-1.0,17.436,2.03278,1737,4587252 +256,113,insert,14.404,-1.0,-1.0,-1.0,-1.0,32.235,2.03735,1739,4600056 +256,114,search,6524.41,2888.06,2480.84,0.961726,199.095,0.92215,0.103368,-1.0,-1.0,17.999,2.03735,1739,4600056 +256,115,insert,43.309,-1.0,-1.0,-1.0,-1.0,47.142,2.04779,1743,4627422 +256,116,search,6492.41,2899.32,2630.39,0.920091,220.396,0.92267,0.102705,-1.0,-1.0,17.624,2.04779,1743,4627422 +256,117,insert,13.62,-1.0,-1.0,-1.0,-1.0,34.505,2.05203,1745,4639292 +256,118,search,6134.54,2899.47,2336.07,1.07785,183.971,0.92248,0.102926,-1.0,-1.0,18.03,2.05203,1745,4639292 +256,119,insert,6.298,-1.0,-1.0,-1.0,-1.0,24.207,2.05389,1746,4643423 +256,120,search,6400,2899.72,2550.14,0.950733,214.22,0.92252,0.102928,-1.0,-1.0,17.738,2.05389,1746,4643423 +256,121,insert,20.098,-1.0,-1.0,-1.0,-1.0,26.22,2.06078,1747,4657252 +256,122,search,6498.7,2903.95,2633.75,0.930259,224.178,0.92294,0.102599,-1.0,-1.0,17.682,2.06078,1747,4657252 +256,123,insert,379.336,-1.0,-1.0,-1.0,-1.0,485.271,2.18936,1795,4938477 +256,124,search,6715.31,2956.24,2744.62,0.919639,231.059,0.92372,0.103096,-1.0,-1.0,141.044,2.18969,1806,4938477 +256,125,insert,56.514,-1.0,-1.0,-1.0,-1.0,68.034,2.20571,1813,4980492 +256,126,search,6732.05,2942.33,2743.16,0.933147,215.235,0.92371,0.102968,-1.0,-1.0,40.245,2.20572,1815,4980492 +256,127,insert,57.406,-1.0,-1.0,-1.0,-1.0,94.105,2.22736,1827,5030515 +256,128,search,6795.51,2946,2758.05,0.922444,222.095,0.92462,0.102437,-1.0,-1.0,38.843,2.22736,1828,5030515 +256,129,delete,28.434,-1.0,-1.0,-1.0,-1.0,90.75,2.2254,1797,5009391 +256,130,search,6696.33,2939.33,2725.81,0.918491,222.668,0.92307,0.103577,-1.0,-1.0,22.207,2.2254,1797,5009391 +256,131,delete,7.269,-1.0,-1.0,-1.0,-1.0,20.997,2.2254,1797,5004093 +256,132,search,6810.16,2936.88,2733.65,0.910311,226.461,0.92292,0.103672,-1.0,-1.0,22.719,2.2254,1797,5004093 +256,133,delete,18.759,-1.0,-1.0,-1.0,-1.0,36.288,2.22391,1796,4991787 +256,134,search,6683.1,2925.37,2720.98,0.915476,218.388,0.92282,0.103783,-1.0,-1.0,21.952,2.22391,1796,4991787 +256,135,delete,23.352,-1.0,-1.0,-1.0,-1.0,44.279,2.22165,1794,4974857 +256,136,search,6310.71,2918.86,2377.65,1.02803,193.222,0.92308,0.103255,-1.0,-1.0,22.246,2.22165,1794,4974857 +256,137,delete,4.952,-1.0,-1.0,-1.0,-1.0,20.796,2.22165,1794,4971386 +256,138,search,6671.55,2914.84,2701.87,0.90167,229.279,0.92288,0.103539,-1.0,-1.0,21.552,2.22165,1794,4971386 +256,139,delete,9.822,-1.0,-1.0,-1.0,-1.0,21.417,2.22165,1794,4963487 +256,140,search,6640,2907.48,2685.61,0.910211,217.249,0.92285,0.103533,-1.0,-1.0,21.345,2.22165,1794,4963487 +256,141,delete,25.446,-1.0,-1.0,-1.0,-1.0,75.564,2.21747,1788,4941830 +256,142,search,6357.26,2898.23,2441.96,0.997016,193.82,0.9226,0.103556,-1.0,-1.0,22.321,2.21747,1788,4941830 +256,143,delete,24.262,-1.0,-1.0,-1.0,-1.0,84.533,2.21355,1785,4925657 +256,144,search,6583.42,2894.91,2664.5,0.931983,220.398,0.92211,0.104108,-1.0,-1.0,21.51,2.21355,1785,4925657 +256,145,delete,3.551,-1.0,-1.0,-1.0,-1.0,28.247,2.21299,1784,4922686 +256,146,search,6543.69,2895.28,2643.58,0.91346,209.633,0.92193,0.104468,-1.0,-1.0,21.319,2.21299,1784,4922686 +256,147,delete,10.092,-1.0,-1.0,-1.0,-1.0,20.777,2.21299,1784,4913636 +256,148,search,6308.84,2888.37,2396.65,1.03852,191.941,0.92179,0.104427,-1.0,-1.0,23.12,2.21299,1784,4913636 +256,149,delete,244.769,-1.0,-1.0,-1.0,-1.0,1058.02,2.13531,1709,4717250 +256,150,search,6101.67,2880.55,2358.59,1.01385,189.857,0.9211,0.10525,-1.0,-1.0,75.315,2.13636,1715,4717250 +256,151,delete,157.611,-1.0,-1.0,-1.0,-1.0,914.043,2.06733,1647,4560269 +512,2,search,3081.92,37.5312,516.295,1.35883,171.176,0.8551,0.130106,-1.0,-1.0,8.376,0.0184881,1000,38806 +512,3,insert,21.57,-1.0,-1.0,-1.0,-1.0,16.587,0.0226681,998,49334 +512,4,search,2588.01,63.6871,110.971,1.29105,164.717,0.86613,0.128797,-1.0,-1.0,14.859,0.0226611,997,49334 +512,5,insert,39.785,-1.0,-1.0,-1.0,-1.0,176.651,0.0329766,993,73557 +512,6,search,2628.96,173.704,192.378,1.40674,127.296,0.92433,0.104255,-1.0,-1.0,114.93,0.0330819,995,73557 +512,7,insert,47.141,-1.0,-1.0,-1.0,-1.0,104.677,0.0426107,995,95766 +512,8,search,2650.17,218.462,207.347,1.26948,124.911,0.92582,0.103612,-1.0,-1.0,94.22,0.0428012,997,95766 +512,9,insert,7.661,-1.0,-1.0,-1.0,-1.0,78.959,0.0445267,997,100025 +512,10,search,2660.56,224.701,201.025,1.21733,137.267,0.92703,0.100737,-1.0,-1.0,81.375,0.0445267,997,100025 +512,11,insert,18.595,-1.0,-1.0,-1.0,-1.0,81.095,0.0497772,997,111417 +512,12,search,2668.86,265.794,234.323,1.14347,134.971,0.92784,0.100473,-1.0,-1.0,82.498,0.0497772,997,111417 +512,13,insert,41.156,-1.0,-1.0,-1.0,-1.0,81.183,0.0610515,997,137139 +512,14,search,2694.24,309.176,256.388,1.09032,131.669,0.92449,0.102927,-1.0,-1.0,22.082,0.061098,998,137139 +512,15,insert,37.121,-1.0,-1.0,-1.0,-1.0,7.587,0.0698157,998,156710 +512,16,search,2757.94,340.453,280.127,0.995509,138.001,0.92241,0.104278,-1.0,-1.0,22.401,0.0698182,1000,156710 +512,17,insert,8.947,-1.0,-1.0,-1.0,-1.0,7.636,0.0717762,1000,161773 +512,18,search,2774.93,355.577,284.893,0.973773,145.56,0.92371,0.103298,-1.0,-1.0,14.669,0.0718484,1001,161773 +512,19,insert,43.717,-1.0,-1.0,-1.0,-1.0,7.452,0.0784384,1001,177161 +512,20,search,2701.02,391.993,306.172,0.932754,124.974,0.92743,0.0998076,-1.0,-1.0,8.73,0.0784384,1001,177161 +512,21,insert,463.774,-1.0,-1.0,-1.0,-1.0,131.862,0.199859,1022,448898 +512,22,search,2948.97,864.317,597.271,0.751287,103.408,0.91911,0.101388,-1.0,-1.0,17.117,0.199859,1023,448898 +512,23,insert,483.702,-1.0,-1.0,-1.0,-1.0,300.494,0.327972,1065,733493 +512,24,search,3264.54,1225.65,868.738,0.733657,115.833,0.91418,0.105459,-1.0,-1.0,79.017,0.32797,1075,733493 +512,25,insert,52.827,-1.0,-1.0,-1.0,-1.0,28.909,0.344801,1078,777443 +512,26,search,3362.24,1225.59,858.826,0.737085,120.645,0.91477,0.104863,-1.0,-1.0,20.832,0.344805,1079,777443 +512,27,insert,42.216,-1.0,-1.0,-1.0,-1.0,18.415,0.357304,1080,805394 +512,28,search,3317.34,1248.94,877.108,0.742225,99.2403,0.91561,0.104355,-1.0,-1.0,11.356,0.357304,1080,805394 +512,29,insert,85.074,-1.0,-1.0,-1.0,-1.0,59.617,0.385079,1086,866391 +512,30,search,3185.1,1317.81,823.326,0.747189,88.5482,0.91631,0.10471,-1.0,-1.0,32.504,0.385078,1088,866391 +512,31,insert,558.846,-1.0,-1.0,-1.0,-1.0,322.519,0.550965,1128,1239816 +512,32,search,3731.35,1675.45,1236.99,0.664256,118.219,0.91144,0.107881,-1.0,-1.0,124.58,0.55147,1139,1239816 +512,33,insert,79.799,-1.0,-1.0,-1.0,-1.0,23.179,0.573302,1141,1291211 +512,34,search,3793.96,1681.91,1256.77,0.630706,122.548,0.91095,0.107869,-1.0,-1.0,69.28,0.573315,1145,1291211 +512,35,insert,48.661,-1.0,-1.0,-1.0,-1.0,48.619,0.586868,1152,1324978 +512,36,search,3824.76,1703.33,1276.63,0.691769,120.023,0.91059,0.10817,-1.0,-1.0,35.953,0.58687,1154,1324978 +512,37,insert,68.793,-1.0,-1.0,-1.0,-1.0,27.225,0.605706,1156,1371885 +512,38,search,3800.46,1737.65,1256.95,0.752149,114.153,0.91053,0.108734,-1.0,-1.0,17.938,0.605705,1157,1371885 +512,39,insert,16.888,-1.0,-1.0,-1.0,-1.0,9.552,0.609685,1157,1379335 +512,40,search,3867.03,1743.21,1323.8,0.674302,109.203,0.91065,0.109062,-1.0,-1.0,10.452,0.609685,1157,1379335 +512,41,insert,60.531,-1.0,-1.0,-1.0,-1.0,51.73,0.625533,1163,1413312 +512,42,search,3881.89,1764.45,1338.56,0.659283,118.142,0.91106,0.109194,-1.0,-1.0,10.27,0.625533,1163,1413312 +512,43,insert,20.684,-1.0,-1.0,-1.0,-1.0,14.461,0.630493,1164,1423411 +512,44,search,3882.78,1772.39,1337.51,0.644442,119.439,0.9113,0.108826,-1.0,-1.0,10.48,0.630493,1164,1423411 +512,45,insert,234.58,-1.0,-1.0,-1.0,-1.0,56.999,0.64488,1172,1457559 +512,46,search,3918.2,1768.07,1346.81,0.660804,119.2,0.91107,0.108305,-1.0,-1.0,10.153,0.64488,1172,1457559 +512,47,insert,335.362,-1.0,-1.0,-1.0,-1.0,308.094,0.748794,1205,1688593 +512,48,search,3993.75,1901.18,1337.68,0.707576,122.709,0.9109,0.110261,-1.0,-1.0,104.577,0.748794,1212,1688593 +512,49,insert,49.072,-1.0,-1.0,-1.0,-1.0,47.586,0.763736,1217,1723505 +512,50,search,3921.81,1898.64,1271.33,0.780305,117.901,0.91129,0.110653,-1.0,-1.0,51.845,0.763766,1221,1723505 +512,51,insert,405.153,-1.0,-1.0,-1.0,-1.0,286.593,0.903308,1260,2035040 +512,52,search,4443.97,2085.42,1659.54,0.585809,156.198,0.91413,0.109514,-1.0,-1.0,68.825,0.903336,1268,2035040 +512,53,insert,50.925,-1.0,-1.0,-1.0,-1.0,18.409,0.92077,1269,2078341 +512,54,search,4482.87,2097.86,1678.09,0.636733,147.067,0.91366,0.10979,-1.0,-1.0,10.874,0.92077,1269,2078341 +512,55,insert,397.23,-1.0,-1.0,-1.0,-1.0,423.494,1.07045,1318,2399905 +512,56,search,4776.24,2267.77,1879.58,0.639122,150.332,0.91344,0.111654,-1.0,-1.0,84.038,1.07076,1325,2399905 +512,57,insert,25.015,-1.0,-1.0,-1.0,-1.0,28.281,1.07864,1328,2419836 +512,58,search,4808.94,2252.93,1877.33,0.587096,162.016,0.91372,0.111281,-1.0,-1.0,56.903,1.07867,1333,2419836 +512,59,insert,244.817,-1.0,-1.0,-1.0,-1.0,145.65,1.17433,1347,2643083 +512,60,search,4629.96,2325.58,1670.39,0.710197,133.376,0.90771,0.117562,-1.0,-1.0,60.565,1.17482,1354,2643083 +512,61,insert,11.55,-1.0,-1.0,-1.0,-1.0,10.481,1.17852,1354,2653064 +512,62,search,4987.84,2319.44,1964.48,0.563008,173.155,0.90754,0.117818,-1.0,-1.0,20.038,1.17852,1355,2653064 +512,63,insert,6.224,-1.0,-1.0,-1.0,-1.0,10.684,1.17993,1355,2656118 +512,64,search,4972.27,2318.93,1966.38,0.570011,169.715,0.90759,0.117622,-1.0,-1.0,12.398,1.17993,1355,2656118 +512,65,insert,119.725,-1.0,-1.0,-1.0,-1.0,99.531,1.20809,1368,2723424 +512,66,search,4807.67,2356.59,1798.47,0.644744,150.982,0.90837,0.117018,-1.0,-1.0,12.408,1.20809,1368,2723424 +512,67,insert,59.906,-1.0,-1.0,-1.0,-1.0,104.963,1.22948,1383,2769021 +512,68,search,5082.92,2359.33,2025.23,0.580215,165.056,0.90922,0.116233,-1.0,-1.0,18.318,1.22948,1384,2769021 +512,69,insert,61.881,-1.0,-1.0,-1.0,-1.0,63.782,1.25058,1391,2821777 +512,70,search,4936.27,2381.43,1877.1,0.726242,162.436,0.91037,0.114581,-1.0,-1.0,23.297,1.25058,1392,2821777 +512,71,insert,14.918,-1.0,-1.0,-1.0,-1.0,16.711,1.25397,1393,2834921 +512,72,search,4611.86,2396.06,1591.7,0.831008,131.348,0.91097,0.11416,-1.0,-1.0,20.597,1.25397,1394,2834921 +512,73,insert,8.671,-1.0,-1.0,-1.0,-1.0,24.391,1.25693,1396,2842044 +512,74,search,4651.18,2392.53,1598.17,0.792235,129.101,0.91099,0.114251,-1.0,-1.0,11.667,1.25693,1396,2842044 +512,75,insert,26.555,-1.0,-1.0,-1.0,-1.0,19.584,1.26347,1397,2858890 +512,76,search,5170.78,2403.75,2085.79,0.619548,178.94,0.91135,0.113769,-1.0,-1.0,11.319,1.26347,1397,2858890 +512,77,insert,44.222,-1.0,-1.0,-1.0,-1.0,10.823,1.27511,1397,2882818 +512,78,search,5166.66,2418.08,2091.55,0.671844,182.177,0.911,0.114026,-1.0,-1.0,11.415,1.27511,1397,2882818 +512,79,insert,476.658,-1.0,-1.0,-1.0,-1.0,10.197,1.30272,1397,2947806 +512,80,search,4822.15,2463.4,1775.46,0.675066,142.889,0.91097,0.114335,-1.0,-1.0,11.222,1.30272,1397,2947806 +512,81,insert,43.264,-1.0,-1.0,-1.0,-1.0,56.613,1.31738,1403,2976895 +512,82,search,5244.31,2471.72,2141.85,0.578193,189.208,0.91223,0.113488,-1.0,-1.0,10.882,1.31738,1403,2976895 +512,83,insert,19.189,-1.0,-1.0,-1.0,-1.0,43.692,1.32452,1408,2990682 +512,84,search,5233.7,2470.63,2112.28,0.671295,180.946,0.91241,0.113228,-1.0,-1.0,11.203,1.32452,1408,2990682 +512,85,insert,36.68,-1.0,-1.0,-1.0,-1.0,53.746,1.33787,1414,3025613 +512,86,search,4950.47,2481.92,1818.88,0.703009,158.136,0.91319,0.112903,-1.0,-1.0,11.061,1.33787,1414,3025613 +512,87,insert,567.909,-1.0,-1.0,-1.0,-1.0,770.438,1.54343,1513,3468632 +512,88,search,5501.3,2598.16,2163.89,0.676666,176.28,0.91582,0.110623,-1.0,-1.0,125.195,1.54374,1526,3468632 +512,89,insert,453.461,-1.0,-1.0,-1.0,-1.0,497.151,1.70287,1603,3831692 +512,90,search,5702.51,2668.34,2189.04,0.71032,178.989,0.91955,0.106091,-1.0,-1.0,50.412,1.70335,1608,3831692 +512,91,insert,32.159,-1.0,-1.0,-1.0,-1.0,44.157,1.71428,1613,3864067 +512,92,search,6107.53,2670.1,2542.61,0.627766,218.173,0.91937,0.106426,-1.0,-1.0,12.795,1.71428,1613,3864067 +512,93,insert,294.786,-1.0,-1.0,-1.0,-1.0,230.27,1.82032,1642,4103827 +512,94,search,6340.33,2753.31,2706.44,0.623243,229.026,0.91981,0.105658,-1.0,-1.0,43.453,1.8206,1646,4103827 +512,95,insert,14.277,-1.0,-1.0,-1.0,-1.0,24.167,1.82533,1648,4119898 +512,96,search,5888.4,2751.38,2288.82,0.728323,186.163,0.9201,0.105395,-1.0,-1.0,13.465,1.82533,1648,4119898 +512,97,insert,11.469,-1.0,-1.0,-1.0,-1.0,26.373,1.82872,1650,4129367 +512,98,search,6178.56,2752.44,2567.13,0.679557,215.853,0.92015,0.105233,-1.0,-1.0,13.573,1.82872,1650,4129367 +512,99,insert,7.803,-1.0,-1.0,-1.0,-1.0,24.642,1.83062,1652,4134502 +512,100,search,6391.94,2747.24,2742.74,0.57341,240.976,0.91998,0.105392,-1.0,-1.0,13.328,1.83062,1652,4134502 +512,101,insert,38.886,-1.0,-1.0,-1.0,-1.0,62.067,1.84203,1658,4164482 +512,102,search,6011.95,2752.25,2374.12,0.738195,204.204,0.92009,0.105303,-1.0,-1.0,12.924,1.84203,1658,4164482 +512,103,insert,17.819,-1.0,-1.0,-1.0,-1.0,31.192,1.84868,1660,4178601 +512,104,search,6214.56,2760.63,2567.53,0.648883,207.183,0.92053,0.104989,-1.0,-1.0,13.12,1.84868,1660,4178601 +512,105,insert,8.564,-1.0,-1.0,-1.0,-1.0,27.611,1.85143,1662,4187774 +512,106,search,5751.47,2759.93,2155.88,0.824231,173.431,0.92042,0.105291,-1.0,-1.0,13.33,1.85143,1662,4187774 +512,107,insert,18.726,-1.0,-1.0,-1.0,-1.0,18.893,1.85624,1663,4200109 +512,108,search,6402.99,2763.01,2750.9,0.615754,234.532,0.9202,0.105456,-1.0,-1.0,13.765,1.85624,1663,4200109 +512,109,insert,453.74,-1.0,-1.0,-1.0,-1.0,599.418,2.0185,1741,4557867 +512,110,search,6855.67,2823.18,2972.17,0.590868,237.469,0.92177,0.103787,-1.0,-1.0,79.842,2.01902,1746,4557867 +512,111,insert,32.532,-1.0,-1.0,-1.0,-1.0,95.567,2.03066,1757,4587252 +512,112,search,6908.58,2814.09,2983.51,0.592655,255.799,0.92215,0.103677,-1.0,-1.0,18.519,2.03066,1757,4587252 +512,113,insert,15.137,-1.0,-1.0,-1.0,-1.0,17.487,2.03591,1757,4600056 +512,114,search,6928.64,2819.81,3014.81,0.65285,251.051,0.92232,0.103657,-1.0,-1.0,18.944,2.03591,1757,4600056 +512,115,insert,42.619,-1.0,-1.0,-1.0,-1.0,87.358,2.04542,1766,4627422 +512,116,search,6593.19,2820.7,2712.59,0.634338,217.08,0.92254,0.103405,-1.0,-1.0,18.956,2.04542,1766,4627422 +512,117,insert,17.602,-1.0,-1.0,-1.0,-1.0,27.627,2.05006,1767,4639292 +512,118,search,6581,2825.46,2665.46,0.676412,221.738,0.92288,0.103317,-1.0,-1.0,18.943,2.05006,1767,4639292 +512,119,insert,5.172,-1.0,-1.0,-1.0,-1.0,17.954,2.05101,1767,4643423 +512,120,search,6865.76,2828.13,2926.09,0.678233,251.76,0.92295,0.103358,-1.0,-1.0,19.736,2.05101,1767,4643423 +512,121,insert,26.05,-1.0,-1.0,-1.0,-1.0,44.866,2.05868,1770,4657252 +512,122,search,6963.5,2831.94,3032.65,0.605625,264.525,0.92295,0.1033,-1.0,-1.0,19.192,2.05868,1770,4657252 +512,123,insert,405.919,-1.0,-1.0,-1.0,-1.0,431.684,2.18824,1812,4938477 +512,124,search,6759.88,2900.36,2778.96,0.672563,226.031,0.9235,0.103249,-1.0,-1.0,138.763,2.1889,1822,4938477 +512,125,insert,57.65,-1.0,-1.0,-1.0,-1.0,77.841,2.20656,1831,4980492 +512,126,search,7242.35,2884.61,3148.94,0.635022,258.651,0.92393,0.103134,-1.0,-1.0,100.548,2.20672,1836,4980492 +512,127,insert,58.397,-1.0,-1.0,-1.0,-1.0,88.907,2.22588,1846,5030515 +512,128,search,7357.2,2884.76,3209.58,0.626576,279.585,0.9246,0.102437,-1.0,-1.0,55.391,2.22589,1848,5030515 +512,129,delete,27.019,-1.0,-1.0,-1.0,-1.0,94.329,2.22438,1817,5009391 +512,130,search,7220.03,2884.87,3160.09,0.565198,272.008,0.92342,0.103273,-1.0,-1.0,23.694,2.22438,1817,5009391 +512,131,delete,7.264,-1.0,-1.0,-1.0,-1.0,22.432,2.22438,1817,5004093 +512,132,search,6961.85,2883.13,2912.6,0.643764,236.532,0.92346,0.10332,-1.0,-1.0,22.87,2.22438,1817,5004093 +512,133,delete,14.969,-1.0,-1.0,-1.0,-1.0,21.678,2.22438,1817,4991787 +512,134,search,6791.35,2869.03,2789.76,0.664741,227.585,0.92336,0.103664,-1.0,-1.0,23.223,2.22438,1817,4991787 +512,135,delete,21.123,-1.0,-1.0,-1.0,-1.0,49.407,2.222,1815,4974857 +512,136,search,7006.68,2861.27,2955,0.613294,255.432,0.92336,0.103461,-1.0,-1.0,23.104,2.222,1815,4974857 +512,137,delete,4.225,-1.0,-1.0,-1.0,-1.0,22.027,2.222,1815,4971386 +512,138,search,7181.92,2856.89,3108.05,0.567017,263.827,0.92334,0.103556,-1.0,-1.0,22.951,2.222,1815,4971386 +512,139,delete,9.612,-1.0,-1.0,-1.0,-1.0,22.991,2.222,1815,4963487 +512,140,search,6944.26,2851.74,2908.12,0.645543,234.228,0.92325,0.103631,-1.0,-1.0,22.751,2.222,1815,4963487 +512,141,delete,28.646,-1.0,-1.0,-1.0,-1.0,73.261,2.21797,1810,4941830 +512,142,search,7116,2842.22,3073.73,0.626838,248.974,0.92283,0.103728,-1.0,-1.0,26.163,2.21797,1810,4941830 +512,143,delete,19.414,-1.0,-1.0,-1.0,-1.0,59.73,2.2144,1807,4925657 +512,144,search,7089.58,2837.8,3060.71,0.589932,251.4,0.92311,0.103579,-1.0,-1.0,22.428,2.2144,1807,4925657 +512,145,delete,2.941,-1.0,-1.0,-1.0,-1.0,21.721,2.2144,1807,4922686 +512,146,search,7108.02,2834.44,3058.27,0.57106,262.15,0.92303,0.103629,-1.0,-1.0,22.461,2.2144,1807,4922686 +512,147,delete,9.492,-1.0,-1.0,-1.0,-1.0,22.069,2.2144,1807,4913636 +512,148,search,7104.68,2827.43,3062.03,0.570765,254.555,0.92295,0.10357,-1.0,-1.0,22.418,2.2144,1807,4913636 +512,149,delete,214.69,-1.0,-1.0,-1.0,-1.0,1177.88,2.12967,1720,4717250 +512,150,search,6799.12,2845.64,2927.37,0.58456,256.01,0.92191,0.105071,-1.0,-1.0,81.759,2.13043,1726,4717250 +512,151,delete,168.829,-1.0,-1.0,-1.0,-1.0,859.111,2.06375,1658,4560269 +1024,2,search,4156.4,37.7178,1683.56,1.08576,180.653,0.8551,0.130106,-1.0,-1.0,8.616,0.0184881,1000,38806 +1024,3,insert,22.422,-1.0,-1.0,-1.0,-1.0,7.153,0.0226644,1000,49334 +1024,4,search,2593.21,60.1351,115.112,1.13082,157.639,0.86604,0.12886,-1.0,-1.0,8.504,0.0226644,1000,49334 +1024,5,insert,44.055,-1.0,-1.0,-1.0,-1.0,172.688,0.0330953,997,73557 +1024,6,search,2566.38,152.235,189.893,1.3901,112.374,0.92386,0.105036,-1.0,-1.0,151.81,0.0330953,997,73557 +1024,7,insert,47.627,-1.0,-1.0,-1.0,-1.0,133.077,0.0428118,998,95766 +1024,8,search,2595.91,196.454,213.153,1.24889,122.614,0.92518,0.103938,-1.0,-1.0,97.464,0.043126,1001,95766 +1024,9,insert,8.509,-1.0,-1.0,-1.0,-1.0,77.332,0.0448678,1001,100025 +1024,10,search,2618.16,198.864,205.362,1.1218,126.702,0.92729,0.100268,-1.0,-1.0,79.583,0.0448678,1001,100025 +1024,11,insert,19.687,-1.0,-1.0,-1.0,-1.0,79.851,0.0495679,1001,111417 +1024,12,search,2604.84,231.702,227.512,1.13444,105.362,0.92776,0.10035,-1.0,-1.0,81.82,0.0495679,1001,111417 +1024,13,insert,47.896,-1.0,-1.0,-1.0,-1.0,79.416,0.0609091,1001,137139 +1024,14,search,2697.94,272.126,264.564,1.04029,118.966,0.925,0.102401,-1.0,-1.0,22.793,0.0612763,1002,137139 +1024,15,insert,38.358,-1.0,-1.0,-1.0,-1.0,7.971,0.0699749,1002,156710 +1024,16,search,2626.4,302.617,276.521,0.916084,119.266,0.92291,0.103342,-1.0,-1.0,16.589,0.0699785,1004,156710 +1024,17,insert,5.059,-1.0,-1.0,-1.0,-1.0,5.989,0.0718398,1004,161773 +1024,18,search,2520.66,315.478,261.15,1.08999,73.8584,0.92324,0.103581,-1.0,-1.0,13.758,0.0720618,1006,161773 +1024,19,insert,27.544,-1.0,-1.0,-1.0,-1.0,6.228,0.0785082,1006,177161 +1024,20,search,2514.58,345.081,274.751,1.05888,69.5007,0.92715,0.100366,-1.0,-1.0,8.848,0.0785082,1006,177161 +1024,21,insert,475.581,-1.0,-1.0,-1.0,-1.0,155.617,0.200219,1032,448898 +1024,22,search,2833.4,755.351,534.382,0.866427,84.0046,0.91772,0.102929,-1.0,-1.0,13.424,0.200219,1033,448898 +1024,23,insert,489.331,-1.0,-1.0,-1.0,-1.0,304.132,0.328777,1077,733493 +1024,24,search,3107.86,1085.92,757.957,0.741973,95.6478,0.91205,0.105883,-1.0,-1.0,74.838,0.328776,1086,733493 +1024,25,insert,54.695,-1.0,-1.0,-1.0,-1.0,38.112,0.346067,1090,777443 +1024,26,search,3139.71,1101.92,766.936,0.753231,84.8261,0.91281,0.105451,-1.0,-1.0,23.219,0.346096,1092,777443 +1024,27,insert,43.049,-1.0,-1.0,-1.0,-1.0,23.783,0.357867,1094,805394 +1024,28,search,3181.04,1113.12,806.053,0.7277,77.2537,0.91366,0.104823,-1.0,-1.0,12.014,0.357867,1094,805394 +1024,29,insert,85.375,-1.0,-1.0,-1.0,-1.0,58.664,0.385698,1101,866391 +1024,30,search,3233.21,1179.57,836.831,0.783533,90.6841,0.91502,0.105035,-1.0,-1.0,27.609,0.385698,1103,866391 +1024,31,insert,520.827,-1.0,-1.0,-1.0,-1.0,331.181,0.552656,1145,1239816 +1024,32,search,3564.76,1503.64,1045.57,0.717741,96.3234,0.9084,0.110647,-1.0,-1.0,110.586,0.553129,1154,1239816 +1024,33,insert,67.492,-1.0,-1.0,-1.0,-1.0,15.381,0.574155,1155,1291211 +1024,34,search,3592.48,1522.11,1061.16,0.706883,92.1074,0.90896,0.110692,-1.0,-1.0,78.639,0.574166,1159,1291211 +1024,35,insert,60.493,-1.0,-1.0,-1.0,-1.0,14.333,0.587188,1160,1324978 +1024,36,search,3648.26,1564.94,1101.79,0.673446,96.4307,0.91053,0.109293,-1.0,-1.0,41.522,0.587191,1163,1324978 +1024,37,insert,77.78,-1.0,-1.0,-1.0,-1.0,40.151,0.607736,1167,1371885 +1024,38,search,3670.18,1589.1,1114.98,0.700587,94.313,0.91012,0.1092,-1.0,-1.0,10.694,0.607736,1167,1371885 +1024,39,insert,11.776,-1.0,-1.0,-1.0,-1.0,9.12,0.610103,1167,1379335 +1024,40,search,3688.25,1593.49,1086.3,0.720698,93.588,0.91046,0.109269,-1.0,-1.0,10.014,0.610103,1167,1379335 +1024,41,insert,58.86,-1.0,-1.0,-1.0,-1.0,40.122,0.625259,1171,1413312 +1024,42,search,3822.89,1616.52,1204.23,0.649201,107.438,0.91075,0.109144,-1.0,-1.0,10.427,0.625259,1171,1413312 +1024,43,insert,15.894,-1.0,-1.0,-1.0,-1.0,9.172,0.628465,1171,1423411 +1024,44,search,3735.7,1632.61,1196.86,0.643744,104.404,0.91088,0.108697,-1.0,-1.0,10.535,0.628465,1171,1423411 +1024,45,insert,249.706,-1.0,-1.0,-1.0,-1.0,56.59,0.643933,1179,1457559 +1024,46,search,4054.73,1638.96,1463.71,0.561357,126.567,0.91109,0.107577,-1.0,-1.0,10.946,0.643933,1179,1457559 +1024,47,insert,366.881,-1.0,-1.0,-1.0,-1.0,273.832,0.74974,1210,1688593 +1024,48,search,4236.87,1770.27,1570.21,0.502076,141.142,0.91084,0.108671,-1.0,-1.0,94.613,0.749914,1218,1688593 +1024,49,insert,49.705,-1.0,-1.0,-1.0,-1.0,33.041,0.764466,1221,1723505 +1024,50,search,4277.12,1778.09,1584.78,0.530734,140.745,0.91194,0.108094,-1.0,-1.0,27.187,0.764466,1223,1723505 +1024,51,insert,421.391,-1.0,-1.0,-1.0,-1.0,242.778,0.903494,1254,2035040 +1024,52,search,4518.28,1991.14,1750.36,0.55433,138.836,0.9144,0.107707,-1.0,-1.0,40.605,0.903493,1258,2035040 +1024,53,insert,47.289,-1.0,-1.0,-1.0,-1.0,47.679,0.919506,1263,2078341 +1024,54,search,4609.23,2002.07,1802.07,0.537326,160.335,0.91418,0.107988,-1.0,-1.0,10.555,0.919506,1263,2078341 +1024,55,insert,393.18,-1.0,-1.0,-1.0,-1.0,416.97,1.06716,1310,2399905 +1024,56,search,4611.28,2190.59,1739.05,0.570061,132.609,0.91468,0.108578,-1.0,-1.0,83.312,1.06757,1320,2399905 +1024,57,insert,26.971,-1.0,-1.0,-1.0,-1.0,14.844,1.07568,1321,2419836 +1024,58,search,4982.06,2178.2,2041.18,0.529086,175.504,0.91488,0.108426,-1.0,-1.0,46.572,1.07577,1325,2419836 +1024,59,insert,261.219,-1.0,-1.0,-1.0,-1.0,187.767,1.17357,1344,2643083 +1024,60,search,4895.08,2259.06,1924.61,0.528271,157.962,0.90831,0.115342,-1.0,-1.0,52.311,1.17363,1347,2643083 +1024,61,insert,17.139,-1.0,-1.0,-1.0,-1.0,23.684,1.17866,1349,2653064 +1024,62,search,4743.62,2258.67,1775.5,0.638926,138.017,0.90837,0.115565,-1.0,-1.0,12.467,1.17866,1349,2653064 +1024,63,insert,6.244,-1.0,-1.0,-1.0,-1.0,10.66,1.18016,1349,2656118 +1024,64,search,5116.73,2260.15,2131.22,0.52302,175.461,0.90843,0.115564,-1.0,-1.0,11.893,1.18016,1349,2656118 +1024,65,insert,104.033,-1.0,-1.0,-1.0,-1.0,140.93,1.20831,1370,2723424 +1024,66,search,5092.93,2271.19,2047.74,0.493882,183.315,0.90874,0.115489,-1.0,-1.0,17.422,1.20831,1371,2723424 +1024,67,insert,50.39,-1.0,-1.0,-1.0,-1.0,88.455,1.22886,1382,2769021 +1024,68,search,4842.73,2286.9,1795.38,0.577678,151.773,0.90992,0.113859,-1.0,-1.0,29.179,1.22886,1385,2769021 +1024,69,insert,64.163,-1.0,-1.0,-1.0,-1.0,72.011,1.25155,1394,2821777 +1024,70,search,5290.77,2304.92,2178.33,0.528784,197.873,0.91151,0.112646,-1.0,-1.0,11.223,1.25155,1394,2821777 +1024,71,insert,21.267,-1.0,-1.0,-1.0,-1.0,42.659,1.25732,1399,2834921 +1024,72,search,5173.23,2304.07,2084.12,0.53491,181.783,0.91113,0.112915,-1.0,-1.0,11.75,1.25732,1399,2834921 +1024,73,insert,12.111,-1.0,-1.0,-1.0,-1.0,18.318,1.26035,1400,2842044 +1024,74,search,4969.72,2307.32,1877.41,0.602331,161.38,0.91157,0.112699,-1.0,-1.0,11.465,1.26035,1400,2842044 +1024,75,insert,28.075,-1.0,-1.0,-1.0,-1.0,18.1,1.26732,1401,2858890 +1024,76,search,5315.01,2317.4,2195.96,0.555956,202.132,0.91178,0.112339,-1.0,-1.0,21.143,1.2676,1402,2858890 +1024,77,insert,44.183,-1.0,-1.0,-1.0,-1.0,19.336,1.27827,1403,2882818 +1024,78,search,5238.5,2329.58,2120.09,0.544313,186.06,0.91141,0.112962,-1.0,-1.0,12.033,1.27827,1403,2882818 +1024,79,insert,476.444,-1.0,-1.0,-1.0,-1.0,22.699,1.30627,1405,2947806 +1024,80,search,5335.75,2366.81,2240.07,0.483499,189.294,0.91107,0.11342,-1.0,-1.0,11.588,1.30627,1405,2947806 +1024,81,insert,43.065,-1.0,-1.0,-1.0,-1.0,52.053,1.31924,1410,2976895 +1024,82,search,5374.53,2380.83,2231.17,0.535648,198.968,0.91196,0.112857,-1.0,-1.0,11.438,1.31924,1410,2976895 +1024,83,insert,21.132,-1.0,-1.0,-1.0,-1.0,28.954,1.3255,1413,2990682 +1024,84,search,5102.89,2382.48,2018.97,0.497242,160.719,0.9119,0.112762,-1.0,-1.0,11.413,1.3255,1413,2990682 +1024,85,insert,43.103,-1.0,-1.0,-1.0,-1.0,16.692,1.34017,1414,3025613 +1024,86,search,5482.32,2405.37,2313.82,0.487979,198.817,0.91309,0.111948,-1.0,-1.0,11.255,1.34017,1414,3025613 +1024,87,insert,570.854,-1.0,-1.0,-1.0,-1.0,762.307,1.54546,1508,3468632 +1024,88,search,5691.59,2525.04,2340.01,0.513802,193.902,0.91552,0.109972,-1.0,-1.0,134.244,1.54555,1522,3468632 +1024,89,insert,460.769,-1.0,-1.0,-1.0,-1.0,527.896,1.70471,1598,3831692 +1024,90,search,6345.62,2604.67,2785.81,0.429967,238.102,0.9198,0.104873,-1.0,-1.0,82.505,1.705,1606,3831692 +1024,91,insert,46.403,-1.0,-1.0,-1.0,-1.0,25,1.71846,1608,3864067 +1024,92,search,6386.95,2608.74,2799.86,0.406024,243.026,0.92019,0.1043,-1.0,-1.0,20.829,1.71846,1609,3864067 +1024,93,insert,299.929,-1.0,-1.0,-1.0,-1.0,248.579,1.82062,1637,4103827 +1024,94,search,6610.87,2698.59,2976.39,0.453617,234.24,0.92055,0.103021,-1.0,-1.0,66.195,1.82114,1643,4103827 +1024,95,insert,17.629,-1.0,-1.0,-1.0,-1.0,36.143,1.82687,1647,4119898 +1024,96,search,6088.04,2690.95,2474.01,0.570459,194.634,0.92122,0.102616,-1.0,-1.0,10.356,1.82687,1647,4119898 +1024,97,insert,7.11,-1.0,-1.0,-1.0,-1.0,18.275,1.83046,1649,4129367 +1024,98,search,6189.24,2692.6,2627.06,0.526888,207.319,0.92118,0.102716,-1.0,-1.0,14.332,1.83046,1649,4129367 +1024,99,insert,7.265,-1.0,-1.0,-1.0,-1.0,29.129,1.83226,1651,4134502 +1024,100,search,6025.99,2691.24,2434.69,0.53804,182.205,0.92111,0.102676,-1.0,-1.0,13.558,1.83226,1651,4134502 +1024,101,insert,33.673,-1.0,-1.0,-1.0,-1.0,34.253,1.84153,1654,4164482 +1024,102,search,6355.73,2702.54,2721.85,0.449682,214.393,0.92143,0.1029,-1.0,-1.0,13.044,1.84153,1654,4164482 +1024,103,insert,16.949,-1.0,-1.0,-1.0,-1.0,34.685,1.84755,1657,4178601 +1024,104,search,6652.48,2706.25,2973.83,0.43,243.91,0.92153,0.10295,-1.0,-1.0,13.879,1.84755,1657,4178601 +1024,105,insert,10.163,-1.0,-1.0,-1.0,-1.0,29.102,1.8512,1659,4187774 +1024,106,search,6513.58,2704.54,2857.85,0.447926,221.593,0.92135,0.103329,-1.0,-1.0,13.838,1.8512,1659,4187774 +1024,107,insert,27.049,-1.0,-1.0,-1.0,-1.0,33.904,1.85701,1660,4200109 +1024,108,search,6670.84,2710.27,2782.3,0.517149,222.806,0.92158,0.103009,-1.0,-1.0,14.829,1.85701,1660,4200109 +1024,109,insert,522.06,-1.0,-1.0,-1.0,-1.0,518.574,2.02064,1727,4557867 +1024,110,search,6711.63,2800.18,2895.61,0.532292,220.407,0.92276,0.101839,-1.0,-1.0,86.302,2.02146,1734,4557867 +1024,111,insert,34.372,-1.0,-1.0,-1.0,-1.0,36.52,2.03452,1737,4587252 +1024,112,search,6622.39,2805.76,2785.39,0.550835,214.625,0.92287,0.101961,-1.0,-1.0,25.707,2.03484,1738,4587252 +1024,113,insert,12.449,-1.0,-1.0,-1.0,-1.0,38.711,2.03916,1741,4600056 +1024,114,search,6988.4,2806.92,3097.77,0.507906,253.511,0.92329,0.101878,-1.0,-1.0,26.444,2.03943,1742,4600056 +1024,115,insert,24.896,-1.0,-1.0,-1.0,-1.0,49.344,2.05031,1749,4627422 +1024,116,search,6747.23,2804.77,2922.9,0.552354,231.931,0.92368,0.101535,-1.0,-1.0,15.284,2.05031,1749,4627422 +1024,117,insert,10.355,-1.0,-1.0,-1.0,-1.0,14.584,2.05359,1749,4639292 +1024,118,search,6257.71,2811.71,2493.2,0.636731,181.535,0.92384,0.101548,-1.0,-1.0,17.944,2.05359,1749,4639292 +1024,119,insert,5.23,-1.0,-1.0,-1.0,-1.0,16.974,2.05533,1749,4643423 +1024,120,search,6337.98,2814.64,2521.65,0.598795,197.447,0.92393,0.101443,-1.0,-1.0,18.08,2.05533,1749,4643423 +1024,121,insert,22.115,-1.0,-1.0,-1.0,-1.0,32.572,2.06132,1751,4657252 +1024,122,search,6320.37,2820.75,2517.17,0.627765,186.781,0.92403,0.101291,-1.0,-1.0,17.71,2.06132,1751,4657252 +1024,123,insert,385.938,-1.0,-1.0,-1.0,-1.0,512.513,2.19323,1803,4938477 +1024,124,search,6549.86,2862.33,2621.58,0.602142,199.883,0.92429,0.101724,-1.0,-1.0,121.496,2.19351,1810,4938477 +1024,125,insert,53.762,-1.0,-1.0,-1.0,-1.0,48.923,2.20886,1814,4980492 +1024,126,search,6591.26,2860.05,2636.09,0.626291,191.325,0.92476,0.101477,-1.0,-1.0,102.647,2.20916,1820,4980492 +1024,127,insert,53.362,-1.0,-1.0,-1.0,-1.0,123.37,2.22969,1836,5030515 +1024,128,search,6660.44,2850.55,2657.45,0.579917,191.531,0.92509,0.101655,-1.0,-1.0,82.714,2.22995,1840,5030515 +1024,129,delete,24.09,-1.0,-1.0,-1.0,-1.0,87.607,2.22829,1811,5009391 +1024,130,search,7087.24,2855.28,3075.81,0.482755,242.471,0.92381,0.102261,-1.0,-1.0,23.519,2.22829,1811,5009391 +1024,131,delete,8.208,-1.0,-1.0,-1.0,-1.0,22.402,2.22829,1811,5004093 +1024,132,search,7306.4,2854.41,3291.7,0.443693,262.82,0.92376,0.102455,-1.0,-1.0,22.78,2.22829,1811,5004093 +1024,133,delete,18.047,-1.0,-1.0,-1.0,-1.0,21.171,2.2281,1811,4991787 +1024,134,search,7397.86,2842.02,3380.93,0.472723,260.765,0.92355,0.102818,-1.0,-1.0,22.546,2.2281,1811,4991787 +1024,135,delete,23.857,-1.0,-1.0,-1.0,-1.0,48.985,2.22583,1809,4974857 +1024,136,search,7454.09,2836.22,3423.97,0.466644,263.887,0.92378,0.102658,-1.0,-1.0,23.168,2.22583,1809,4974857 +1024,137,delete,5.584,-1.0,-1.0,-1.0,-1.0,21.481,2.22583,1809,4971386 +1024,138,search,7112.33,2833.97,3120.98,0.517431,244.175,0.92373,0.102765,-1.0,-1.0,22.493,2.22583,1809,4971386 +1024,139,delete,13.198,-1.0,-1.0,-1.0,-1.0,22.138,2.22583,1809,4963487 +1024,140,search,7070.88,2827.44,3085.6,0.48844,233.113,0.92373,0.102785,-1.0,-1.0,22.942,2.22583,1809,4963487 +1024,141,delete,30.309,-1.0,-1.0,-1.0,-1.0,103.479,2.22028,1802,4941830 +1024,142,search,6953.21,2822.55,2985.95,0.543922,240.907,0.92327,0.103116,-1.0,-1.0,22.36,2.22028,1802,4941830 +1024,143,delete,20.909,-1.0,-1.0,-1.0,-1.0,69.646,2.21654,1799,4925657 +1024,144,search,6763.82,2818.91,2826.28,0.487967,219.737,0.92333,0.102825,-1.0,-1.0,21.816,2.21654,1799,4925657 +1024,145,delete,3.38,-1.0,-1.0,-1.0,-1.0,29.49,2.21596,1798,4922686 +1024,146,search,6924.72,2817.45,2979.24,0.496258,230.761,0.92319,0.103032,-1.0,-1.0,21.57,2.21596,1798,4922686 +1024,147,delete,9.394,-1.0,-1.0,-1.0,-1.0,20.955,2.21596,1798,4913636 +1024,148,search,7081.63,2809.68,3122.49,0.523638,242.846,0.923,0.103226,-1.0,-1.0,21.597,2.21596,1798,4913636 +1024,149,delete,214.356,-1.0,-1.0,-1.0,-1.0,959.296,2.13906,1723,4717250 +1024,150,search,6810.74,2808.36,2978.95,0.479757,234.225,0.92222,0.103874,-1.0,-1.0,44.357,2.13936,1725,4717250 +1024,151,delete,188.117,-1.0,-1.0,-1.0,-1.0,933.706,2.07349,1656,4560269 +2048,2,search,6742.84,38.1808,4094.74,0.625102,225.389,0.8551,0.130106,-1.0,-1.0,8.889,0.0184881,1000,38806 +2048,3,insert,22.519,-1.0,-1.0,-1.0,-1.0,13.022,0.0226428,999,49334 +2048,4,search,2740.93,56.9112,149.111,0.993296,153.74,0.86574,0.128987,-1.0,-1.0,15.323,0.0226534,998,49334 +2048,5,insert,44.239,-1.0,-1.0,-1.0,-1.0,171.948,0.0329117,995,73557 +2048,6,search,2723.23,129.722,201.192,1.1712,144.326,0.92412,0.104554,-1.0,-1.0,114.753,0.0330823,997,73557 +2048,7,insert,48.179,-1.0,-1.0,-1.0,-1.0,104.634,0.0427115,997,95766 +2048,8,search,2628.34,164.396,222.138,1.19541,128.463,0.92484,0.104181,-1.0,-1.0,93.325,0.0429608,999,95766 +2048,9,insert,7.252,-1.0,-1.0,-1.0,-1.0,79.074,0.0446793,999,100025 +2048,10,search,2705.43,164.114,227.821,1.10528,132.361,0.92622,0.1008,-1.0,-1.0,81.467,0.0446793,999,100025 +2048,11,insert,20.081,-1.0,-1.0,-1.0,-1.0,84.72,0.0499514,1000,111417 +2048,12,search,2755.25,190.563,257.286,1.07247,136.184,0.92709,0.101116,-1.0,-1.0,82.433,0.0499514,1000,111417 +2048,13,insert,43.435,-1.0,-1.0,-1.0,-1.0,80.953,0.0611204,1000,137139 +2048,14,search,2748.16,223.38,281.738,1.04415,116.204,0.92369,0.103096,-1.0,-1.0,23.415,0.0611731,1001,137139 +2048,15,insert,36.85,-1.0,-1.0,-1.0,-1.0,12.185,0.0698492,1002,156710 +2048,16,search,2727.03,252.366,302.489,0.919837,128.508,0.92188,0.104282,-1.0,-1.0,22.227,0.0698525,1004,156710 +2048,17,insert,8.338,-1.0,-1.0,-1.0,-1.0,12.027,0.0717117,1005,161773 +2048,18,search,2744.01,261.259,315.974,0.901413,127.232,0.92195,0.10416,-1.0,-1.0,25.607,0.0720242,1009,161773 +2048,19,insert,44.976,-1.0,-1.0,-1.0,-1.0,7.581,0.0788276,1009,177161 +2048,20,search,2872.16,286.768,335.37,0.869878,138.31,0.92592,0.10087,-1.0,-1.0,16.595,0.0788403,1011,177161 +2048,21,insert,468.412,-1.0,-1.0,-1.0,-1.0,184.684,0.201129,1048,448898 +2048,22,search,3135.37,614.833,653.794,0.71205,125.427,0.9153,0.104003,-1.0,-1.0,41.049,0.201127,1055,448898 +2048,23,insert,497.115,-1.0,-1.0,-1.0,-1.0,335.132,0.329899,1118,733493 +2048,24,search,3454.43,855.454,906.361,0.628783,122.254,0.9075,0.108471,-1.0,-1.0,94.077,0.330124,1131,733493 +2048,25,insert,52.842,-1.0,-1.0,-1.0,-1.0,26.818,0.347154,1134,777443 +2048,26,search,3504.74,864.581,922.437,0.605595,119.575,0.90754,0.109082,-1.0,-1.0,33.388,0.347255,1138,777443 +2048,27,insert,39.612,-1.0,-1.0,-1.0,-1.0,18.687,0.358619,1139,805394 +2048,28,search,3515.79,881.488,941.29,0.601415,116.161,0.90782,0.108748,-1.0,-1.0,24.031,0.358666,1141,805394 +2048,29,insert,104.047,-1.0,-1.0,-1.0,-1.0,76.768,0.385983,1153,866391 +2048,30,search,3389.89,926.83,857.141,0.597795,103.732,0.90867,0.10922,-1.0,-1.0,18.4,0.385983,1154,866391 +2048,31,insert,575.665,-1.0,-1.0,-1.0,-1.0,366.747,0.554142,1217,1239816 +2048,32,search,3965.82,1190.22,1292.23,0.534433,117.167,0.90248,0.114527,-1.0,-1.0,75.247,0.554141,1221,1239816 +2048,33,insert,70.154,-1.0,-1.0,-1.0,-1.0,33.874,0.574312,1226,1291211 +2048,34,search,3966.8,1221,1292.74,0.555395,126.132,0.90381,0.113789,-1.0,-1.0,79.728,0.574419,1231,1291211 +2048,35,insert,42.024,-1.0,-1.0,-1.0,-1.0,35.024,0.585956,1238,1324978 +2048,36,search,3980.07,1240.34,1247.54,0.548734,123.797,0.90463,0.112786,-1.0,-1.0,30.401,0.58596,1240,1324978 +2048,37,insert,65.165,-1.0,-1.0,-1.0,-1.0,41.666,0.605734,1246,1371885 +2048,38,search,4036.46,1269.6,1306.84,0.518811,134.771,0.90411,0.113705,-1.0,-1.0,10.906,0.605734,1246,1371885 +2048,39,insert,12.073,-1.0,-1.0,-1.0,-1.0,13.037,0.609226,1247,1379335 +2048,40,search,4083.56,1273.97,1332.48,0.52759,135.55,0.90497,0.113576,-1.0,-1.0,10.738,0.609226,1247,1379335 +2048,41,insert,56.732,-1.0,-1.0,-1.0,-1.0,46.351,0.624915,1253,1413312 +2048,42,search,4106.06,1293.05,1370.49,0.622234,126.676,0.90511,0.11338,-1.0,-1.0,10.861,0.624915,1253,1413312 +2048,43,insert,16.844,-1.0,-1.0,-1.0,-1.0,14.469,0.629132,1254,1423411 +2048,44,search,4117.58,1304.56,1367.39,0.55397,131.252,0.90559,0.112642,-1.0,-1.0,11.525,0.629132,1254,1423411 +2048,45,insert,249.536,-1.0,-1.0,-1.0,-1.0,45.909,0.64488,1263,1457559 +2048,46,search,4165.78,1321.11,1404.98,0.519079,131.042,0.90547,0.112419,-1.0,-1.0,10.64,0.64488,1263,1457559 +2048,47,insert,349.308,-1.0,-1.0,-1.0,-1.0,261.785,0.749534,1295,1688593 +2048,48,search,4438.71,1458.96,1583.71,0.500374,133.171,0.90606,0.112788,-1.0,-1.0,91.571,0.749653,1303,1688593 +2048,49,insert,47.098,-1.0,-1.0,-1.0,-1.0,36.469,0.763584,1306,1723505 +2048,50,search,4409.39,1476.08,1548.69,0.507646,134.448,0.90694,0.112199,-1.0,-1.0,49.604,0.763585,1309,1723505 +2048,51,insert,422.672,-1.0,-1.0,-1.0,-1.0,250.498,0.9014,1349,2035040 +2048,52,search,4520.03,1654.38,1544.48,0.522612,144.672,0.90984,0.111246,-1.0,-1.0,22.663,0.9014,1350,2035040 +2048,53,insert,60.141,-1.0,-1.0,-1.0,-1.0,31.006,0.920433,1352,2078341 +2048,54,search,4547.03,1685.71,1590.01,0.558232,128.025,0.90997,0.111087,-1.0,-1.0,18.675,0.920439,1353,2078341 +2048,55,insert,435.085,-1.0,-1.0,-1.0,-1.0,454.65,1.06876,1407,2399905 +2048,56,search,4969.16,1856.72,1857.27,0.500387,157.96,0.91043,0.112915,-1.0,-1.0,140.484,1.06922,1425,2399905 +2048,57,insert,31.869,-1.0,-1.0,-1.0,-1.0,10.703,1.07779,1425,2419836 +2048,58,search,4917.67,1827.12,1813.66,0.514087,143.291,0.90925,0.113682,-1.0,-1.0,39.174,1.0778,1427,2419836 +2048,59,insert,280.612,-1.0,-1.0,-1.0,-1.0,155.791,1.17593,1439,2643083 +2048,60,search,4907.59,1939.02,1765.11,0.50224,140.903,0.90268,0.121482,-1.0,-1.0,26.122,1.17622,1442,2643083 +2048,61,insert,15.047,-1.0,-1.0,-1.0,-1.0,19.272,1.18079,1444,2653064 +2048,62,search,4693.67,1935.9,1567.94,0.572034,127.276,0.90252,0.121329,-1.0,-1.0,11.725,1.18079,1444,2653064 +2048,63,insert,4.471,-1.0,-1.0,-1.0,-1.0,10.946,1.18198,1444,2656118 +2048,64,search,4719.93,1937.83,1602.29,0.552913,123.179,0.90257,0.121347,-1.0,-1.0,11.875,1.18198,1444,2656118 +2048,65,insert,82.519,-1.0,-1.0,-1.0,-1.0,154.654,1.20928,1469,2723424 +2048,66,search,5328.4,1953.4,2097.21,0.465194,167.973,0.90364,0.120202,-1.0,-1.0,15.347,1.20942,1470,2723424 +2048,67,insert,57.976,-1.0,-1.0,-1.0,-1.0,60.674,1.22984,1477,2769021 +2048,68,search,5143.77,1981.12,1882.15,0.438606,159.532,0.90529,0.11916,-1.0,-1.0,21.895,1.22984,1478,2769021 +2048,69,insert,74.258,-1.0,-1.0,-1.0,-1.0,69.73,1.2524,1486,2821777 +2048,70,search,5428.52,2001.89,2133.43,0.472196,184.831,0.90686,0.118102,-1.0,-1.0,23.774,1.2524,1487,2821777 +2048,71,insert,27.641,-1.0,-1.0,-1.0,-1.0,26.049,1.25813,1489,2834921 +2048,72,search,5352.68,2009.71,2074.71,0.3972,167.95,0.90739,0.117505,-1.0,-1.0,13.639,1.25813,1489,2834921 +2048,73,insert,12.847,-1.0,-1.0,-1.0,-1.0,54.782,1.26204,1494,2842044 +2048,74,search,5019.52,2008.45,1766.47,0.656906,141.656,0.90749,0.117568,-1.0,-1.0,12.456,1.26204,1494,2842044 +2048,75,insert,31.311,-1.0,-1.0,-1.0,-1.0,33.025,1.26869,1497,2858890 +2048,76,search,5399.3,2011.77,2139.59,0.50247,177.551,0.90744,0.117533,-1.0,-1.0,13.086,1.26869,1497,2858890 +2048,77,insert,47.355,-1.0,-1.0,-1.0,-1.0,18.416,1.27953,1498,2882818 +2048,78,search,5298.95,2024.41,2033.74,0.448168,165.197,0.90698,0.118,-1.0,-1.0,13.241,1.27953,1498,2882818 +2048,79,insert,537.525,-1.0,-1.0,-1.0,-1.0,12.226,1.30734,1498,2947806 +2048,80,search,5518.07,2064.93,2230.95,0.455563,184.548,0.90674,0.118262,-1.0,-1.0,12.701,1.30734,1498,2947806 +2048,81,insert,44.161,-1.0,-1.0,-1.0,-1.0,32.475,1.31975,1501,2976895 +2048,82,search,5354.69,2078.04,2111.04,0.432005,170.838,0.90828,0.116564,-1.0,-1.0,17.744,1.31992,1502,2976895 +2048,83,insert,16.296,-1.0,-1.0,-1.0,-1.0,30.149,1.32547,1505,2990682 +2048,84,search,5350.32,2080.57,2072.76,0.540098,159.506,0.90826,0.116674,-1.0,-1.0,12.538,1.32547,1505,2990682 +2048,85,insert,41.798,-1.0,-1.0,-1.0,-1.0,40.527,1.33918,1509,3025613 +2048,86,search,5628.2,2097.94,2278.99,0.443742,188.055,0.90921,0.116184,-1.0,-1.0,25.277,1.33931,1510,3025613 +2048,87,insert,592.922,-1.0,-1.0,-1.0,-1.0,614.934,1.5415,1591,3468632 +2048,88,search,5921.72,2269.6,2412.94,0.394859,183.692,0.91216,0.113617,-1.0,-1.0,116.447,1.54172,1602,3468632 +2048,89,insert,467.709,-1.0,-1.0,-1.0,-1.0,429.346,1.69991,1661,3831692 +2048,90,search,6229.87,2388.86,2585.22,0.392498,191.146,0.91705,0.108027,-1.0,-1.0,87.633,1.70015,1672,3831692 +2048,91,insert,39.709,-1.0,-1.0,-1.0,-1.0,46.311,1.71321,1677,3864067 +2048,92,search,6506.9,2386.25,2813.45,0.421943,214.461,0.91692,0.107888,-1.0,-1.0,13.854,1.71321,1677,3864067 +2048,93,insert,321.099,-1.0,-1.0,-1.0,-1.0,232.426,1.82048,1703,4103827 +2048,94,search,6468.13,2477.07,2740.28,0.461241,199.34,0.91734,0.106625,-1.0,-1.0,56.038,1.821,1710,4103827 +2048,95,insert,18.091,-1.0,-1.0,-1.0,-1.0,20.218,1.8269,1711,4119898 +2048,96,search,6828.39,2472.01,3061.25,0.441398,215.175,0.91745,0.106627,-1.0,-1.0,15.204,1.8269,1711,4119898 +2048,97,insert,12.364,-1.0,-1.0,-1.0,-1.0,28.418,1.831,1713,4129367 +2048,98,search,6468.58,2472.4,2729.24,0.411449,204.303,0.9175,0.106464,-1.0,-1.0,15.568,1.831,1713,4129367 +2048,99,insert,6.452,-1.0,-1.0,-1.0,-1.0,27.485,1.83268,1715,4134502 +2048,100,search,6786.15,2475.46,2989.64,0.418089,221.037,0.91779,0.106131,-1.0,-1.0,51.51,1.83329,1719,4134502 +2048,101,insert,38.952,-1.0,-1.0,-1.0,-1.0,50.831,1.84454,1724,4164482 +2048,102,search,6813.99,2474.08,2988.68,0.370013,228.209,0.91795,0.10623,-1.0,-1.0,17.647,1.84454,1724,4164482 +2048,103,insert,20.525,-1.0,-1.0,-1.0,-1.0,21.771,1.84924,1725,4178601 +2048,104,search,6606.28,2481.58,2841.28,0.382123,206.268,0.91804,0.106241,-1.0,-1.0,17.022,1.84924,1725,4178601 +2048,105,insert,11.356,-1.0,-1.0,-1.0,-1.0,15.685,1.85258,1725,4187774 +2048,106,search,6552.14,2485.92,2776.62,0.390638,209.825,0.91794,0.106552,-1.0,-1.0,17.834,1.85258,1725,4187774 +2048,107,insert,29.104,-1.0,-1.0,-1.0,-1.0,26.982,1.8574,1726,4200109 +2048,108,search,6736.98,2489.03,2956.82,0.385353,223.947,0.91786,0.106677,-1.0,-1.0,17.187,1.8574,1726,4200109 +2048,109,insert,522.425,-1.0,-1.0,-1.0,-1.0,579.021,2.01818,1799,4557867 +2048,110,search,6923.31,2576.33,2942.92,0.410608,217.347,0.91983,0.104607,-1.0,-1.0,71.862,2.01924,1805,4557867 +2048,111,insert,32.28,-1.0,-1.0,-1.0,-1.0,76.373,2.03042,1814,4587252 +2048,112,search,6884.34,2571.63,2901.69,0.468932,212.906,0.92042,0.104423,-1.0,-1.0,20.572,2.03042,1814,4587252 +2048,113,insert,15.221,-1.0,-1.0,-1.0,-1.0,19.938,2.03474,1814,4600056 +2048,114,search,7151.75,2581.25,3155.64,0.411619,240.399,0.92058,0.104346,-1.0,-1.0,20.618,2.03474,1814,4600056 +2048,115,insert,36.134,-1.0,-1.0,-1.0,-1.0,35.605,2.04452,1816,4627422 +2048,116,search,7196.25,2594.02,3192.28,0.411645,227.222,0.92095,0.104131,-1.0,-1.0,22.449,2.04452,1816,4627422 +2048,117,insert,14.037,-1.0,-1.0,-1.0,-1.0,43.694,2.04869,1819,4639292 +2048,118,search,7121.47,2593.25,3134.87,0.500174,218.009,0.92074,0.104242,-1.0,-1.0,24.287,2.04869,1819,4639292 +2048,119,insert,7.38,-1.0,-1.0,-1.0,-1.0,20.988,2.04994,1819,4643423 +2048,120,search,6920.43,2595.38,2952.9,0.427788,209.225,0.92081,0.104142,-1.0,-1.0,22.215,2.04994,1819,4643423 +2048,121,insert,23.277,-1.0,-1.0,-1.0,-1.0,40.747,2.05642,1821,4657252 +2048,122,search,7036.68,2600.16,3035.27,0.400545,218.883,0.92134,0.103846,-1.0,-1.0,22.389,2.05642,1821,4657252 +2048,123,insert,436.066,-1.0,-1.0,-1.0,-1.0,512.294,2.18478,1872,4938477 +2048,124,search,7341.63,2665.3,3213.85,0.436446,221.918,0.92153,0.104665,-1.0,-1.0,169.19,2.18551,1885,4938477 +2048,125,insert,64.48,-1.0,-1.0,-1.0,-1.0,74.46,2.20322,1893,4980492 +2048,126,search,7704.98,2654.29,3537.74,0.417725,245.543,0.92206,0.104337,-1.0,-1.0,66.207,2.2034,1896,4980492 +2048,127,insert,61.834,-1.0,-1.0,-1.0,-1.0,117.969,2.2231,1911,5030515 +2048,128,search,7116.91,2653.63,2942.42,0.509782,207.576,0.92256,0.104145,-1.0,-1.0,29.028,2.2231,1912,5030515 +2048,129,delete,18.517,-1.0,-1.0,-1.0,-1.0,95.691,2.22108,1880,5009391 +2048,130,search,7309.35,2677.13,3174.26,0.362236,224.065,0.92113,0.105126,-1.0,-1.0,27.897,2.22108,1880,5009391 +2048,131,delete,12.08,-1.0,-1.0,-1.0,-1.0,25.325,2.22108,1880,5004093 +2048,132,search,7625.39,2674.78,3479.55,0.3292,238.119,0.92118,0.105169,-1.0,-1.0,25.809,2.22108,1880,5004093 +2048,133,delete,20.43,-1.0,-1.0,-1.0,-1.0,33.932,2.22018,1879,4991787 +2048,134,search,7582.44,2667.67,3438.84,0.334598,249.479,0.92086,0.105415,-1.0,-1.0,26.374,2.22018,1879,4991787 +2048,135,delete,30.135,-1.0,-1.0,-1.0,-1.0,57.904,2.21743,1876,4974857 +2048,136,search,7361.16,2660.84,3238.58,0.369661,233.985,0.92106,0.105195,-1.0,-1.0,25.816,2.21743,1876,4974857 +2048,137,delete,7.7,-1.0,-1.0,-1.0,-1.0,24.36,2.21743,1876,4971386 +2048,138,search,7334.13,2660,3201.2,0.374534,232.622,0.92098,0.105254,-1.0,-1.0,25.297,2.21743,1876,4971386 +2048,139,delete,13.23,-1.0,-1.0,-1.0,-1.0,25.487,2.21743,1876,4963487 +2048,140,search,7465.1,2655.27,3322.74,0.348421,252.004,0.92083,0.105372,-1.0,-1.0,25.653,2.21743,1876,4963487 +2048,141,delete,32.069,-1.0,-1.0,-1.0,-1.0,78.888,2.21332,1870,4941830 +2048,142,search,7478.11,2650.41,3356.26,0.389279,249.511,0.92058,0.105462,-1.0,-1.0,24.636,2.21332,1870,4941830 +2048,143,delete,19.449,-1.0,-1.0,-1.0,-1.0,70.413,2.20912,1867,4925657 +2048,144,search,7470.87,2646.64,3432.68,0.36775,237.806,0.92083,0.105229,-1.0,-1.0,24.636,2.20912,1867,4925657 +2048,145,delete,3.359,-1.0,-1.0,-1.0,-1.0,36.81,2.20836,1865,4922686 +2048,146,search,7131.68,2645.3,3036.48,0.386342,216.476,0.92031,0.105418,-1.0,-1.0,28.188,2.20836,1865,4922686 +2048,147,delete,20.35,-1.0,-1.0,-1.0,-1.0,24.718,2.20836,1865,4913636 +2048,148,search,7141.47,2640.91,3045.77,0.377016,219.715,0.92033,0.105436,-1.0,-1.0,25.784,2.20836,1865,4913636 +2048,149,delete,240.523,-1.0,-1.0,-1.0,-1.0,1031.16,2.13667,1789,4717250 +2048,150,search,6839.69,2637.2,2910.69,0.483281,212.888,0.91992,0.106344,-1.0,-1.0,59.668,2.13755,1791,4717250 +2048,151,delete,183.961,-1.0,-1.0,-1.0,-1.0,1015.17,2.06786,1713,4560269 +4096,2,search,11537.4,38.5561,9121.22,0.649295,167.197,0.8551,0.130106,-1.0,-1.0,8.612,0.0184881,1000,38806 +4096,3,insert,22.857,-1.0,-1.0,-1.0,-1.0,7.288,0.0226644,1000,49334 +4096,4,search,2799.94,52.5464,270.13,0.683308,254.698,0.86604,0.12886,-1.0,-1.0,8.689,0.0226644,1000,49334 +4096,5,insert,44.31,-1.0,-1.0,-1.0,-1.0,172.752,0.0330953,997,73557 +4096,6,search,2754.42,107.344,205.689,1.13465,158.168,0.92386,0.105036,-1.0,-1.0,151.793,0.0330953,997,73557 +4096,7,insert,49.145,-1.0,-1.0,-1.0,-1.0,133.301,0.0428118,998,95766 +4096,8,search,2768.75,132.008,239.421,1.13271,152.771,0.92518,0.103938,-1.0,-1.0,95.591,0.043126,1001,95766 +4096,9,insert,7.458,-1.0,-1.0,-1.0,-1.0,76.451,0.0448678,1001,100025 +4096,10,search,2745.72,130.256,231.426,1.08274,151.019,0.92729,0.100268,-1.0,-1.0,78.206,0.0448678,1001,100025 +4096,11,insert,17.922,-1.0,-1.0,-1.0,-1.0,78.23,0.0495679,1001,111417 +4096,12,search,2755.88,148.883,281.088,1.04146,148.926,0.92776,0.10035,-1.0,-1.0,79.991,0.0495679,1001,111417 +4096,13,insert,40.671,-1.0,-1.0,-1.0,-1.0,78.801,0.0609091,1001,137139 +4096,14,search,2840.34,175.671,296.333,0.985786,156.798,0.925,0.102401,-1.0,-1.0,23.024,0.0612763,1002,137139 +4096,15,insert,35.517,-1.0,-1.0,-1.0,-1.0,7.929,0.0699749,1002,156710 +4096,16,search,2855.65,198.98,317.811,0.900885,161.626,0.92291,0.103342,-1.0,-1.0,24.559,0.0699785,1004,156710 +4096,17,insert,9.365,-1.0,-1.0,-1.0,-1.0,7.949,0.0718398,1004,161773 +4096,18,search,2861.04,206.396,333.949,0.908278,145.187,0.92324,0.103581,-1.0,-1.0,18.224,0.0720618,1006,161773 +4096,19,insert,47.924,-1.0,-1.0,-1.0,-1.0,7.903,0.0785082,1006,177161 +4096,20,search,2804.17,227.616,369.988,0.966953,123.585,0.92715,0.100366,-1.0,-1.0,9.062,0.0785082,1006,177161 +4096,21,insert,491.853,-1.0,-1.0,-1.0,-1.0,168.208,0.200555,1036,448898 +4096,22,search,3095.19,528.188,721.056,0.769119,113.52,0.91727,0.103129,-1.0,-1.0,35.698,0.200553,1041,448898 +4096,23,insert,523.075,-1.0,-1.0,-1.0,-1.0,302.251,0.328603,1083,733493 +4096,24,search,3489.73,784.676,997.183,0.694697,126.244,0.91257,0.105198,-1.0,-1.0,88.678,0.328664,1094,733493 +4096,25,insert,58.378,-1.0,-1.0,-1.0,-1.0,41.8,0.345761,1099,777443 +4096,26,search,3463.02,804.589,1005.93,0.662109,123.056,0.91175,0.106454,-1.0,-1.0,20.478,0.345766,1100,777443 +4096,27,insert,48.337,-1.0,-1.0,-1.0,-1.0,22.061,0.357943,1101,805394 +4096,28,search,3573.48,821.934,1044.3,0.678013,121.137,0.91364,0.105069,-1.0,-1.0,12.981,0.357943,1101,805394 +4096,29,insert,93.307,-1.0,-1.0,-1.0,-1.0,61.904,0.385594,1108,866391 +4096,30,search,3672.01,869.688,1078.15,0.634186,126.102,0.91483,0.105673,-1.0,-1.0,29.306,0.385593,1110,866391 +4096,31,insert,581.097,-1.0,-1.0,-1.0,-1.0,389.249,0.553916,1161,1239816 +4096,32,search,3960.5,1143.99,1370.29,0.597561,132.723,0.9091,0.110302,-1.0,-1.0,109.853,0.554335,1169,1239816 +4096,33,insert,66.458,-1.0,-1.0,-1.0,-1.0,22.409,0.574261,1171,1291211 +4096,34,search,4017.04,1174.43,1374.24,0.542666,137.238,0.90811,0.111001,-1.0,-1.0,57.884,0.57434,1175,1291211 +4096,35,insert,44.444,-1.0,-1.0,-1.0,-1.0,24.812,0.586385,1178,1324978 +4096,36,search,3939.25,1195.55,1322.23,0.55502,139.24,0.90887,0.110037,-1.0,-1.0,48.177,0.586387,1181,1324978 +4096,37,insert,75.677,-1.0,-1.0,-1.0,-1.0,29.571,0.607092,1183,1371885 +4096,38,search,3853.88,1229.65,1230.77,0.607154,121.091,0.90916,0.109973,-1.0,-1.0,18.994,0.607091,1184,1371885 +4096,39,insert,9.905,-1.0,-1.0,-1.0,-1.0,10.018,0.608986,1184,1379335 +4096,40,search,3898.2,1234.71,1294.14,0.570971,126.337,0.90899,0.110654,-1.0,-1.0,11.122,0.608986,1184,1379335 +4096,41,insert,66.038,-1.0,-1.0,-1.0,-1.0,44.678,0.623349,1189,1413312 +4096,42,search,3870.12,1255.56,1240.32,0.580447,124.789,0.90972,0.110182,-1.0,-1.0,11.791,0.623349,1189,1413312 +4096,43,insert,23.114,-1.0,-1.0,-1.0,-1.0,15.579,0.628273,1190,1423411 +4096,44,search,3910.16,1264.86,1298.99,0.559865,122.918,0.90991,0.109793,-1.0,-1.0,11.04,0.628273,1190,1423411 +4096,45,insert,263.118,-1.0,-1.0,-1.0,-1.0,54.475,0.644578,1198,1457559 +4096,46,search,3894.73,1281.24,1261.15,0.680918,114.928,0.90971,0.109171,-1.0,-1.0,10.355,0.644578,1198,1457559 +4096,47,insert,376.972,-1.0,-1.0,-1.0,-1.0,254.505,0.749623,1225,1688593 +4096,48,search,4343.41,1429.73,1630.46,0.50611,149.003,0.90995,0.109918,-1.0,-1.0,100.956,0.749754,1234,1688593 +4096,49,insert,53.041,-1.0,-1.0,-1.0,-1.0,32.993,0.764617,1237,1723505 +4096,50,search,4405.9,1444.44,1647.52,0.508175,149.463,0.91121,0.109342,-1.0,-1.0,29.689,0.764617,1239,1723505 +4096,51,insert,429.229,-1.0,-1.0,-1.0,-1.0,229.188,0.901089,1269,2035040 +4096,52,search,4590.49,1638.63,1778.94,0.499362,131.895,0.91364,0.107785,-1.0,-1.0,34.504,0.901089,1272,2035040 +4096,53,insert,50.689,-1.0,-1.0,-1.0,-1.0,44.777,0.918886,1276,2078341 +4096,54,search,4508.4,1663.8,1671.16,0.483307,138.783,0.91337,0.108109,-1.0,-1.0,20.977,0.918887,1277,2078341 +4096,55,insert,437.42,-1.0,-1.0,-1.0,-1.0,452.122,1.06679,1322,2399905 +4096,56,search,4672.69,1856.9,1748.64,0.484284,130.126,0.91426,0.109757,-1.0,-1.0,107.807,1.06718,1335,2399905 +4096,57,insert,33.547,-1.0,-1.0,-1.0,-1.0,23.068,1.07592,1337,2419836 +4096,58,search,5098.63,1850.79,2111.06,0.523936,175.457,0.91347,0.109913,-1.0,-1.0,53.512,1.07595,1342,2419836 +4096,59,insert,311.752,-1.0,-1.0,-1.0,-1.0,137.822,1.17537,1354,2643083 +4096,60,search,4899.23,1982.2,1917.81,0.46155,151.064,0.90847,0.115012,-1.0,-1.0,88.181,1.17571,1362,2643083 +4096,61,insert,16.138,-1.0,-1.0,-1.0,-1.0,30.006,1.18049,1365,2653064 +4096,62,search,5309.94,1970.91,2294.68,0.436011,161.393,0.90728,0.116262,-1.0,-1.0,11.674,1.18049,1365,2653064 +4096,63,insert,5.649,-1.0,-1.0,-1.0,-1.0,10.376,1.1818,1365,2656118 +4096,64,search,5210.06,1973.07,2185.5,0.4237,172.645,0.90743,0.116167,-1.0,-1.0,11.874,1.1818,1365,2656118 +4096,65,insert,100.981,-1.0,-1.0,-1.0,-1.0,136.555,1.20999,1385,2723424 +4096,66,search,4948.19,1993.67,1896.19,0.437753,149.379,0.90789,0.115619,-1.0,-1.0,11.422,1.20999,1385,2723424 +4096,67,insert,60.125,-1.0,-1.0,-1.0,-1.0,93.799,1.23121,1397,2769021 +4096,68,search,5444.03,2007.79,2273.09,0.459303,187.885,0.90935,0.114185,-1.0,-1.0,18.531,1.23121,1398,2769021 +4096,69,insert,67.153,-1.0,-1.0,-1.0,-1.0,76.888,1.2544,1407,2821777 +4096,70,search,5537.21,2027.73,2365.68,0.39594,188.286,0.91111,0.112628,-1.0,-1.0,12.941,1.2544,1407,2821777 +4096,71,insert,23.002,-1.0,-1.0,-1.0,-1.0,36.406,1.25961,1410,2834921 +4096,72,search,5547.46,2031.97,2431.2,0.390223,168.778,0.91144,0.112492,-1.0,-1.0,13.946,1.25961,1410,2834921 +4096,73,insert,10.863,-1.0,-1.0,-1.0,-1.0,30.17,1.2625,1412,2842044 +4096,74,search,5441.66,2033.48,2320.63,0.378742,183.498,0.91132,0.112676,-1.0,-1.0,12.394,1.2625,1412,2842044 +4096,75,insert,31.21,-1.0,-1.0,-1.0,-1.0,27.19,1.26976,1414,2858890 +4096,76,search,5165.45,2046.38,2048.37,0.465175,146.866,0.91155,0.112409,-1.0,-1.0,12.075,1.26976,1414,2858890 +4096,77,insert,53.452,-1.0,-1.0,-1.0,-1.0,24.016,1.28098,1416,2882818 +4096,78,search,5482.48,2054.93,2357.63,0.374653,185.122,0.91097,0.11329,-1.0,-1.0,12.482,1.28098,1416,2882818 +4096,79,insert,513.061,-1.0,-1.0,-1.0,-1.0,24.024,1.308,1418,2947806 +4096,80,search,5180.5,2099.72,2083.37,0.399101,158.031,0.91061,0.113692,-1.0,-1.0,12.138,1.308,1418,2947806 +4096,81,insert,46.767,-1.0,-1.0,-1.0,-1.0,36.942,1.32035,1421,2976895 +4096,82,search,5610.66,2114.16,2441.24,0.373434,183.814,0.91171,0.11318,-1.0,-1.0,11.635,1.32035,1421,2976895 +4096,83,insert,19.421,-1.0,-1.0,-1.0,-1.0,19.759,1.32527,1422,2990682 +4096,84,search,5402.42,2122.71,2274.53,0.392965,173.631,0.91202,0.112614,-1.0,-1.0,23.585,1.32539,1423,2990682 +4096,85,insert,50.858,-1.0,-1.0,-1.0,-1.0,26.646,1.34123,1425,3025613 +4096,86,search,5286.02,2142.15,2159.19,0.456139,151.799,0.91262,0.112591,-1.0,-1.0,11.733,1.34123,1425,3025613 +4096,87,insert,587.825,-1.0,-1.0,-1.0,-1.0,752.543,1.54568,1520,3468632 +4096,88,search,6099.7,2290.88,2708.21,0.339739,207.368,0.91535,0.110627,-1.0,-1.0,133.677,1.54574,1533,3468632 +4096,89,insert,446.131,-1.0,-1.0,-1.0,-1.0,515.886,1.70627,1607,3831692 +4096,90,search,6490.04,2390.55,2936.66,0.313765,218.65,0.91944,0.105925,-1.0,-1.0,90.857,1.70639,1617,3831692 +4096,91,insert,33.781,-1.0,-1.0,-1.0,-1.0,31.547,1.71499,1620,3864067 +4096,92,search,6205.87,2391.83,2636.04,0.397321,187.294,0.91939,0.105661,-1.0,-1.0,13.996,1.71499,1620,3864067 +4096,93,insert,307.688,-1.0,-1.0,-1.0,-1.0,298.73,1.8202,1655,4103827 +4096,94,search,6464.47,2482.82,2825.25,0.404702,186.64,0.92019,0.104663,-1.0,-1.0,44.223,1.82042,1659,4103827 +4096,95,insert,23.736,-1.0,-1.0,-1.0,-1.0,12.922,1.82791,1659,4119898 +4096,96,search,6188.74,2487.29,2577.01,0.383051,177.416,0.92061,0.104447,-1.0,-1.0,13.583,1.82791,1659,4119898 +4096,97,insert,11.805,-1.0,-1.0,-1.0,-1.0,24.876,1.83119,1661,4129367 +4096,98,search,6771.21,2490.06,3073.32,0.332482,237.509,0.92081,0.104334,-1.0,-1.0,21.59,1.83131,1662,4129367 +4096,99,insert,7.959,-1.0,-1.0,-1.0,-1.0,19.973,1.83383,1663,4134502 +4096,100,search,6496.61,2490.21,2844.78,0.394863,192.706,0.9209,0.10425,-1.0,-1.0,16.766,1.83383,1663,4134502 +4096,101,insert,52.454,-1.0,-1.0,-1.0,-1.0,62.471,1.84586,1669,4164482 +4096,102,search,6569.1,2498.76,2711.24,0.346932,197.719,0.92102,0.103942,-1.0,-1.0,14.331,1.84586,1669,4164482 +4096,103,insert,22.453,-1.0,-1.0,-1.0,-1.0,31.045,1.8521,1671,4178601 +4096,104,search,6903.95,2506.03,3031.24,0.366423,226.193,0.92097,0.104024,-1.0,-1.0,28.344,1.85231,1672,4178601 +4096,105,insert,13.386,-1.0,-1.0,-1.0,-1.0,39.262,1.85552,1675,4187774 +4096,106,search,7030.28,2503.9,3140.33,0.326805,234.901,0.92107,0.104309,-1.0,-1.0,15.084,1.85552,1675,4187774 +4096,107,insert,30.63,-1.0,-1.0,-1.0,-1.0,41.566,1.86065,1677,4200109 +4096,108,search,7175.58,2508.2,3277.4,0.328379,224.37,0.92093,0.10439,-1.0,-1.0,14.399,1.86065,1677,4200109 +4096,109,insert,521.929,-1.0,-1.0,-1.0,-1.0,466.844,2.02066,1735,4557867 +4096,110,search,6815.46,2630.61,2822.69,0.36691,189.815,0.92255,0.102885,-1.0,-1.0,60.346,2.02108,1741,4557867 +4096,111,insert,29.804,-1.0,-1.0,-1.0,-1.0,58.894,2.03292,1748,4587252 +4096,112,search,7458.85,2625.53,3388.75,0.358886,216.216,0.92282,0.102756,-1.0,-1.0,28.748,2.03316,1749,4587252 +4096,113,insert,14.724,-1.0,-1.0,-1.0,-1.0,35.564,2.03889,1751,4600056 +4096,114,search,7633.12,2628.06,3557.25,0.335104,229.629,0.92277,0.10292,-1.0,-1.0,19.745,2.03889,1751,4600056 +4096,115,insert,51.483,-1.0,-1.0,-1.0,-1.0,75.368,2.05096,1757,4627422 +4096,116,search,7693.53,2634.63,3595.67,0.302892,226.727,0.92333,0.102289,-1.0,-1.0,28.141,2.05119,1758,4627422 +4096,117,insert,15.346,-1.0,-1.0,-1.0,-1.0,27.896,2.05471,1759,4639292 +4096,118,search,7220.39,2638.34,3159.84,0.3979,198.438,0.92334,0.102322,-1.0,-1.0,19.363,2.05471,1759,4639292 +4096,119,insert,6.402,-1.0,-1.0,-1.0,-1.0,17.877,2.05602,1759,4643423 +4096,120,search,7199.61,2640.66,3155.08,0.325026,210.354,0.9234,0.102292,-1.0,-1.0,18.852,2.05602,1759,4643423 +4096,121,insert,23.268,-1.0,-1.0,-1.0,-1.0,61.097,2.06126,1763,4657252 +4096,122,search,7130.64,2642.62,3070.67,0.340196,209.09,0.9236,0.101959,-1.0,-1.0,33.995,2.06168,1765,4657252 +4096,123,insert,391.016,-1.0,-1.0,-1.0,-1.0,504.237,2.1885,1815,4938477 +4096,124,search,7965.69,2719.32,3750.84,0.303044,242.027,0.92404,0.102309,-1.0,-1.0,180.113,2.18895,1828,4938477 +4096,125,insert,62.575,-1.0,-1.0,-1.0,-1.0,58.021,2.20754,1834,4980492 +4096,126,search,7833.4,2713.13,3547.79,0.31354,253.025,0.92454,0.102277,-1.0,-1.0,97.297,2.20758,1838,4980492 +4096,127,insert,71.531,-1.0,-1.0,-1.0,-1.0,111.287,2.22997,1852,5030515 +4096,128,search,7811.23,2711.34,3455.76,0.320415,243.675,0.92452,0.102294,-1.0,-1.0,40.519,2.22997,1853,5030515 +4096,129,delete,28.343,-1.0,-1.0,-1.0,-1.0,95.209,2.22825,1822,5009391 +4096,130,search,7661.59,2746.96,3406.54,0.305481,245.874,0.92342,0.102894,-1.0,-1.0,24.101,2.22825,1822,5009391 +4096,131,delete,8.353,-1.0,-1.0,-1.0,-1.0,22.636,2.22825,1822,5004093 +4096,132,search,7683.01,2743.88,3433.27,0.313807,247.491,0.92333,0.103,-1.0,-1.0,23.053,2.22825,1822,5004093 +4096,133,delete,15.1,-1.0,-1.0,-1.0,-1.0,34.605,2.22726,1821,4991787 +4096,134,search,7752.9,2738.21,3504.2,0.283415,251.929,0.9232,0.103135,-1.0,-1.0,23.23,2.22726,1821,4991787 +4096,135,delete,20.635,-1.0,-1.0,-1.0,-1.0,49.06,2.22456,1819,4974857 +4096,136,search,7773.97,2732.2,3515.24,0.28179,248.904,0.92303,0.103067,-1.0,-1.0,26.667,2.22456,1819,4974857 +4096,137,delete,9.494,-1.0,-1.0,-1.0,-1.0,23.031,2.22456,1819,4971386 +4096,138,search,7790.28,2730.25,3516.06,0.273334,254.58,0.92301,0.103095,-1.0,-1.0,24.909,2.22456,1819,4971386 +4096,139,delete,18.595,-1.0,-1.0,-1.0,-1.0,23.739,2.22456,1819,4963487 +4096,140,search,7382.75,2725.63,3177.17,0.29731,210.383,0.92291,0.103314,-1.0,-1.0,23.773,2.22456,1819,4963487 +4096,141,delete,39.383,-1.0,-1.0,-1.0,-1.0,97.7,2.21991,1813,4941830 +4096,142,search,7433.65,2720.77,3240.03,0.399913,209.053,0.92276,0.10336,-1.0,-1.0,23.754,2.21991,1813,4941830 +4096,143,delete,25.403,-1.0,-1.0,-1.0,-1.0,93.184,2.21495,1809,4925657 +4096,144,search,7314.47,2719.58,3149.11,0.289173,216.74,0.92282,0.103406,-1.0,-1.0,34.209,2.21498,1810,4925657 +4096,145,delete,3.372,-1.0,-1.0,-1.0,-1.0,30.403,2.2144,1809,4922686 +4096,146,search,7388.57,2717.94,3180.17,0.282511,228.958,0.9227,0.103805,-1.0,-1.0,26.416,2.2144,1809,4922686 +4096,147,delete,20.965,-1.0,-1.0,-1.0,-1.0,22.915,2.2144,1809,4913636 +4096,148,search,7195.7,2711.48,3019.84,0.331553,215.287,0.92268,0.103803,-1.0,-1.0,24.401,2.2144,1809,4913636 +4096,149,delete,276.274,-1.0,-1.0,-1.0,-1.0,1051.77,2.13983,1730,4717250 +4096,150,search,7088.36,2722.99,3071.76,0.281484,211.682,0.92226,0.104236,-1.0,-1.0,55.043,2.14033,1733,4717250 +4096,151,delete,183.103,-1.0,-1.0,-1.0,-1.0,858.619,2.07207,1666,4560269 +8192,2,search,27565.3,38.7532,24395.7,1.30728,115.15,0.8551,0.130106,-1.0,-1.0,8.553,0.0184881,1000,38806 +8192,3,insert,22.577,-1.0,-1.0,-1.0,-1.0,16.498,0.0226681,998,49334 +8192,4,search,12399.3,50.3434,7828.17,0.825033,165.07,0.86613,0.128797,-1.0,-1.0,14.952,0.0226611,997,49334 +8192,5,insert,40.973,-1.0,-1.0,-1.0,-1.0,176.879,0.0329766,993,73557 +8192,6,search,4042.9,91.1717,774.971,0.683991,253.458,0.92433,0.104255,-1.0,-1.0,114.347,0.0330819,995,73557 +8192,7,insert,48.308,-1.0,-1.0,-1.0,-1.0,104.903,0.0426107,995,95766 +8192,8,search,2799.43,109.607,232.022,1.14273,147.147,0.92582,0.103612,-1.0,-1.0,94.258,0.0428012,997,95766 +8192,9,insert,7.508,-1.0,-1.0,-1.0,-1.0,79.078,0.0445267,997,100025 +8192,10,search,2765.81,105.062,249.059,1.08397,148.386,0.92703,0.100737,-1.0,-1.0,80.411,0.0445267,997,100025 +8192,11,insert,19.307,-1.0,-1.0,-1.0,-1.0,81.366,0.0497772,997,111417 +8192,12,search,2805.15,119.099,284.257,1.11498,131.466,0.92784,0.100473,-1.0,-1.0,82.539,0.0497772,997,111417 +8192,13,insert,40.199,-1.0,-1.0,-1.0,-1.0,86.656,0.0610515,997,137139 +8192,14,search,2845.37,142.935,302.696,1.00175,142.35,0.92449,0.102927,-1.0,-1.0,24.298,0.061098,998,137139 +8192,15,insert,39.328,-1.0,-1.0,-1.0,-1.0,8.292,0.0698157,998,156710 +8192,16,search,2865.05,161.365,339.939,1.0034,146.305,0.92241,0.104278,-1.0,-1.0,23.602,0.0698182,1000,156710 +8192,17,insert,10.93,-1.0,-1.0,-1.0,-1.0,11.833,0.0717892,1001,161773 +8192,18,search,2880.69,166.103,348.815,0.931538,154.133,0.92357,0.10331,-1.0,-1.0,20.208,0.07197,1003,161773 +8192,19,insert,48.928,-1.0,-1.0,-1.0,-1.0,7.77,0.07856,1003,177161 +8192,20,search,2909,182.593,367.665,0.94727,147.493,0.92703,0.10003,-1.0,-1.0,8.824,0.07856,1003,177161 +8192,21,insert,499.527,-1.0,-1.0,-1.0,-1.0,199.508,0.201212,1039,448898 +8192,22,search,3172.07,431.198,709.276,0.849123,117.527,0.91539,0.10383,-1.0,-1.0,28.701,0.201211,1042,448898 +8192,23,insert,518.481,-1.0,-1.0,-1.0,-1.0,317.188,0.328128,1088,733493 +8192,24,search,3241.73,672.368,822.975,0.896863,98.9298,0.91169,0.106081,-1.0,-1.0,90.829,0.328126,1100,733493 +8192,25,insert,59.504,-1.0,-1.0,-1.0,-1.0,45.874,0.345871,1106,777443 +8192,26,search,3347.11,701.086,893.971,0.656742,119.87,0.91074,0.107309,-1.0,-1.0,20.215,0.345873,1107,777443 +8192,27,insert,46.304,-1.0,-1.0,-1.0,-1.0,13.065,0.357604,1107,805394 +8192,28,search,3540.13,725.635,1034.44,0.698074,119.065,0.91184,0.106671,-1.0,-1.0,24.35,0.357714,1108,805394 +8192,29,insert,94.716,-1.0,-1.0,-1.0,-1.0,61.834,0.38539,1115,866391 +8192,30,search,3562.24,775.002,1065.18,0.6865,129.469,0.91289,0.10726,-1.0,-1.0,31.502,0.38539,1117,866391 +8192,31,insert,582.361,-1.0,-1.0,-1.0,-1.0,364.37,0.552645,1171,1239816 +8192,32,search,3998.64,1057.88,1365.6,0.554018,133.373,0.9057,0.112014,-1.0,-1.0,113.838,0.552897,1179,1239816 +8192,33,insert,82.806,-1.0,-1.0,-1.0,-1.0,13.304,0.573687,1180,1291211 +8192,34,search,4061.73,1093.34,1396.13,0.539061,138.055,0.90713,0.110999,-1.0,-1.0,72.964,0.573978,1186,1291211 +8192,35,insert,49.616,-1.0,-1.0,-1.0,-1.0,26.451,0.585004,1190,1324978 +8192,36,search,3853.65,1112.51,1210.89,0.553019,132.283,0.90718,0.110544,-1.0,-1.0,43.757,0.58501,1193,1324978 +8192,37,insert,73.951,-1.0,-1.0,-1.0,-1.0,27.081,0.604548,1195,1371885 +8192,38,search,4105.31,1147.08,1435.28,0.532165,135.079,0.90718,0.111175,-1.0,-1.0,10.591,0.604548,1195,1371885 +8192,39,insert,17.421,-1.0,-1.0,-1.0,-1.0,15.747,0.6081,1196,1379335 +8192,40,search,4100.15,1151.39,1465.26,0.533851,130.947,0.90763,0.111373,-1.0,-1.0,18.14,0.608219,1197,1379335 +8192,41,insert,63.876,-1.0,-1.0,-1.0,-1.0,41.647,0.623929,1202,1413312 +8192,42,search,4160.05,1173.88,1492.12,0.558511,131.177,0.90792,0.11131,-1.0,-1.0,11.251,0.623929,1202,1413312 +8192,43,insert,19.625,-1.0,-1.0,-1.0,-1.0,15.026,0.627703,1203,1423411 +8192,44,search,4106.37,1181.28,1471.83,0.551127,135.371,0.90817,0.111101,-1.0,-1.0,10.587,0.627703,1203,1423411 +8192,45,insert,248.527,-1.0,-1.0,-1.0,-1.0,32.825,0.642549,1207,1457559 +8192,46,search,4035.01,1205.62,1361.81,0.533036,124.136,0.90912,0.109805,-1.0,-1.0,10.387,0.642549,1207,1457559 +8192,47,insert,370.411,-1.0,-1.0,-1.0,-1.0,275.658,0.748957,1237,1688593 +8192,48,search,4430.78,1361.81,1674.91,0.497981,148.391,0.90942,0.110545,-1.0,-1.0,117.808,0.748956,1245,1688593 +8192,49,insert,56.928,-1.0,-1.0,-1.0,-1.0,50.983,0.763786,1251,1723505 +8192,50,search,4121.75,1374.44,1374.35,0.522257,130.457,0.90992,0.109936,-1.0,-1.0,47.022,0.763785,1254,1723505 +8192,51,insert,470.613,-1.0,-1.0,-1.0,-1.0,268.323,0.902564,1291,2035040 +8192,52,search,4425.91,1573.92,1576.98,0.470998,138.53,0.91274,0.108916,-1.0,-1.0,64.459,0.902624,1298,2035040 +8192,53,insert,61.764,-1.0,-1.0,-1.0,-1.0,23.878,0.920093,1299,2078341 +8192,54,search,4790.64,1597.52,1908.38,0.428668,155.489,0.91205,0.109496,-1.0,-1.0,21.213,0.920303,1300,2078341 +8192,55,insert,457.122,-1.0,-1.0,-1.0,-1.0,480.599,1.07101,1357,2399905 +8192,56,search,4937.2,1765.96,1942.93,0.425863,151.744,0.91214,0.110282,-1.0,-1.0,120.538,1.07107,1369,2399905 +8192,57,insert,28.545,-1.0,-1.0,-1.0,-1.0,27.7,1.07944,1372,2419836 +8192,58,search,5124.88,1761.19,2072.63,0.406386,169.861,0.91137,0.111192,-1.0,-1.0,54.552,1.07946,1377,2419836 +8192,59,insert,304.754,-1.0,-1.0,-1.0,-1.0,211.281,1.18038,1394,2643083 +8192,60,search,4930.78,1893.35,1846.41,0.424805,143.685,0.90594,0.118054,-1.0,-1.0,86.225,1.18088,1401,2643083 +8192,61,insert,16.023,-1.0,-1.0,-1.0,-1.0,18.753,1.18529,1402,2653064 +8192,62,search,5339.38,1889.67,2205.53,0.3813,172.066,0.90631,0.117868,-1.0,-1.0,13.144,1.18529,1402,2653064 +8192,63,insert,4.547,-1.0,-1.0,-1.0,-1.0,11.297,1.18588,1402,2656118 +8192,64,search,5116.23,1891.85,2019.09,0.407683,156.989,0.90633,0.11773,-1.0,-1.0,13.184,1.18588,1402,2656118 +8192,65,insert,117.909,-1.0,-1.0,-1.0,-1.0,125.498,1.21169,1420,2723424 +8192,66,search,4852.88,1917.9,1743.11,0.466117,137.498,0.90733,0.116659,-1.0,-1.0,11.668,1.21169,1420,2723424 +8192,67,insert,65.925,-1.0,-1.0,-1.0,-1.0,118.319,1.23214,1437,2769021 +8192,68,search,5436.8,1926.95,2241.65,0.372674,181.425,0.90769,0.116154,-1.0,-1.0,27.977,1.23214,1439,2769021 +8192,69,insert,76.671,-1.0,-1.0,-1.0,-1.0,75.56,1.25331,1447,2821777 +8192,70,search,5327.4,1950.09,2147.68,0.384288,160.508,0.90948,0.114699,-1.0,-1.0,17.875,1.25345,1448,2821777 +8192,71,insert,19.312,-1.0,-1.0,-1.0,-1.0,31.252,1.25843,1451,2834921 +8192,72,search,5134.81,1953.77,1951.81,0.463296,148.114,0.9097,0.114723,-1.0,-1.0,14.841,1.25843,1451,2834921 +8192,73,insert,11.596,-1.0,-1.0,-1.0,-1.0,12.747,1.26121,1451,2842044 +8192,74,search,5215.42,1958.68,2029.49,0.370849,159.953,0.90969,0.114613,-1.0,-1.0,14.86,1.26121,1451,2842044 +8192,75,insert,38.825,-1.0,-1.0,-1.0,-1.0,34.746,1.26706,1453,2858890 +8192,76,search,5303.64,1967.58,2119.63,0.369611,166.499,0.91007,0.114344,-1.0,-1.0,13.078,1.26706,1453,2858890 +8192,77,insert,58.39,-1.0,-1.0,-1.0,-1.0,20.514,1.27736,1454,2882818 +8192,78,search,5670.94,1982.68,2435,0.364955,173.682,0.91025,0.11435,-1.0,-1.0,23.729,1.27744,1455,2882818 +8192,79,insert,533.076,-1.0,-1.0,-1.0,-1.0,18.132,1.30368,1456,2947806 +8192,80,search,5341.12,2024.59,2153.74,0.370877,162.05,0.90978,0.11485,-1.0,-1.0,12.629,1.30368,1456,2947806 +8192,81,insert,47.764,-1.0,-1.0,-1.0,-1.0,26.131,1.31749,1458,2976895 +8192,82,search,5648.94,2041.77,2428.61,0.361755,174.395,0.9108,0.113888,-1.0,-1.0,14.892,1.31749,1458,2976895 +8192,83,insert,24.806,-1.0,-1.0,-1.0,-1.0,22.184,1.32363,1459,2990682 +8192,84,search,5553.11,2049.82,2335.34,0.344939,171.562,0.91098,0.113601,-1.0,-1.0,14.935,1.32363,1459,2990682 +8192,85,insert,60.989,-1.0,-1.0,-1.0,-1.0,19.867,1.33978,1460,3025613 +8192,86,search,5286.85,2072.34,2062.76,0.414272,156.159,0.91203,0.113107,-1.0,-1.0,13.248,1.33978,1460,3025613 +8192,87,insert,631.356,-1.0,-1.0,-1.0,-1.0,715.326,1.54402,1550,3468632 +8192,88,search,6254.67,2237.83,2810.73,0.324781,200.353,0.91507,0.110386,-1.0,-1.0,112.843,1.54402,1561,3468632 +8192,89,insert,453.651,-1.0,-1.0,-1.0,-1.0,468.107,1.70228,1625,3831692 +8192,90,search,6621.61,2357.96,3032.51,0.314883,205.523,0.91908,0.105571,-1.0,-1.0,65.102,1.70242,1633,3831692 +8192,91,insert,32.477,-1.0,-1.0,-1.0,-1.0,49.861,1.71305,1638,3864067 +8192,92,search,6735.16,2359.02,3074.76,0.303641,211.278,0.91921,0.105488,-1.0,-1.0,16.226,1.71305,1638,3864067 +8192,93,insert,350.506,-1.0,-1.0,-1.0,-1.0,222.082,1.81842,1666,4103827 +8192,94,search,6930.91,2460.35,3236.88,0.308049,213.079,0.91986,0.104438,-1.0,-1.0,40.547,1.8185,1669,4103827 +8192,95,insert,24.082,-1.0,-1.0,-1.0,-1.0,51.934,1.8257,1674,4119898 +8192,96,search,6606.96,2458.2,2912.07,0.342406,200.054,0.92011,0.104232,-1.0,-1.0,14.123,1.8257,1674,4119898 +8192,97,insert,15.511,-1.0,-1.0,-1.0,-1.0,24.735,1.82997,1675,4129367 +8192,98,search,6389.08,2462.38,2720.02,0.343961,199.724,0.92035,0.10404,-1.0,-1.0,14.265,1.82997,1675,4129367 +8192,99,insert,8.655,-1.0,-1.0,-1.0,-1.0,13.287,1.83221,1675,4134502 +8192,100,search,6834.22,2465.44,3130.51,0.319901,224.746,0.92046,0.103952,-1.0,-1.0,16.75,1.83221,1675,4134502 +8192,101,insert,50.478,-1.0,-1.0,-1.0,-1.0,88.292,1.84226,1683,4164482 +8192,102,search,7005.34,2471.53,3268.29,0.308466,215.502,0.92086,0.103481,-1.0,-1.0,16.07,1.84226,1683,4164482 +8192,103,insert,31.092,-1.0,-1.0,-1.0,-1.0,34.872,1.849,1685,4178601 +8192,104,search,6960.83,2476.97,3246.07,0.313931,221.263,0.92098,0.103269,-1.0,-1.0,15.822,1.849,1685,4178601 +8192,105,insert,17.25,-1.0,-1.0,-1.0,-1.0,44.796,1.85329,1688,4187774 +8192,106,search,6962.69,2478,3241.28,0.31205,220.841,0.92116,0.103197,-1.0,-1.0,24.817,1.85333,1689,4187774 +8192,107,insert,27.477,-1.0,-1.0,-1.0,-1.0,14.05,1.85883,1689,4200109 +8192,108,search,6769.1,2483.83,3048.23,0.33667,214.721,0.92091,0.103435,-1.0,-1.0,15.124,1.85883,1689,4200109 +8192,109,insert,494.398,-1.0,-1.0,-1.0,-1.0,557.68,2.0177,1760,4557867 +8192,110,search,7146.39,2586.78,3221.1,0.321154,218.577,0.92209,0.102209,-1.0,-1.0,69.707,2.01814,1763,4557867 +8192,111,insert,45.849,-1.0,-1.0,-1.0,-1.0,89.292,2.0318,1772,4587252 +8192,112,search,7070.46,2585.85,3136.72,0.291171,209.268,0.92212,0.102458,-1.0,-1.0,19.975,2.0318,1772,4587252 +8192,113,insert,18.157,-1.0,-1.0,-1.0,-1.0,44.694,2.03766,1775,4600056 +8192,114,search,7006.56,2588.69,3085.4,0.318095,222.53,0.92258,0.102156,-1.0,-1.0,19.393,2.03766,1775,4600056 +8192,115,insert,46.474,-1.0,-1.0,-1.0,-1.0,66.893,2.04733,1780,4627422 +8192,116,search,7170.25,2596.78,3233.81,0.304241,224.977,0.92328,0.101834,-1.0,-1.0,19.577,2.04733,1780,4627422 +8192,117,insert,12.698,-1.0,-1.0,-1.0,-1.0,18.161,2.05008,1780,4639292 +8192,118,search,7392.91,2603.44,3434.97,0.312541,246.193,0.9234,0.101497,-1.0,-1.0,34.449,2.05016,1781,4639292 +8192,119,insert,7.315,-1.0,-1.0,-1.0,-1.0,41.273,2.05214,1783,4643423 +8192,120,search,7036.11,2601.38,3104.92,0.357798,205.222,0.92337,0.10157,-1.0,-1.0,21.596,2.05214,1783,4643423 +8192,121,insert,25.754,-1.0,-1.0,-1.0,-1.0,32.389,2.05929,1784,4657252 +8192,122,search,6857.13,2607.67,2938.57,0.329138,210.235,0.92342,0.101367,-1.0,-1.0,34.779,2.05932,1785,4657252 +8192,123,insert,473.435,-1.0,-1.0,-1.0,-1.0,517.542,2.19035,1837,4938477 +8192,124,search,7642.46,2685.44,3570.99,0.280006,254.132,0.92357,0.102073,-1.0,-1.0,173.211,2.19174,1848,4938477 +8192,125,insert,57.507,-1.0,-1.0,-1.0,-1.0,76.128,2.2081,1855,4980492 +8192,126,search,7713.69,2682.04,3588.83,0.306597,248.986,0.92413,0.101583,-1.0,-1.0,175.556,2.20867,1864,4980492 +8192,127,insert,70.373,-1.0,-1.0,-1.0,-1.0,100.452,2.23104,1876,5030515 +8192,128,search,7693.47,2678.68,3513.74,0.29093,248.194,0.9249,0.101125,-1.0,-1.0,39.427,2.23104,1877,5030515 +8192,129,delete,28.464,-1.0,-1.0,-1.0,-1.0,95.492,2.22913,1845,5009391 +8192,130,search,7589.27,2715.12,3509.87,0.259519,245.114,0.92323,0.1024,-1.0,-1.0,24.819,2.22913,1845,5009391 +8192,131,delete,9.509,-1.0,-1.0,-1.0,-1.0,23.661,2.22913,1845,5004093 +8192,132,search,7390.59,2712.25,3311.2,0.265846,241.806,0.92319,0.102526,-1.0,-1.0,23.834,2.22913,1845,5004093 +8192,133,delete,15.927,-1.0,-1.0,-1.0,-1.0,23.198,2.2289,1845,4991787 +8192,134,search,6680.22,2705.58,2653.1,0.335831,183.033,0.92303,0.102513,-1.0,-1.0,26.692,2.2289,1845,4991787 +8192,135,delete,37.285,-1.0,-1.0,-1.0,-1.0,75.236,2.2259,1842,4974857 +8192,136,search,7639.75,2700.79,3543,0.249413,247.792,0.92328,0.102246,-1.0,-1.0,25.977,2.2259,1842,4974857 +8192,137,delete,11.887,-1.0,-1.0,-1.0,-1.0,25.114,2.2259,1842,4971386 +8192,138,search,7113,2698.91,3126.47,0.267756,219.484,0.9232,0.102395,-1.0,-1.0,25.437,2.2259,1842,4971386 +8192,139,delete,15.956,-1.0,-1.0,-1.0,-1.0,23.211,2.2259,1842,4963487 +8192,140,search,7273.39,2694.62,3212.27,0.267613,225.756,0.92306,0.102488,-1.0,-1.0,24.497,2.2259,1842,4963487 +8192,141,delete,36.837,-1.0,-1.0,-1.0,-1.0,82.322,2.22131,1836,4941830 +8192,142,search,7347.15,2691.63,3294.47,0.265634,242.144,0.92275,0.102675,-1.0,-1.0,27.342,2.22131,1836,4941830 +8192,143,delete,31.469,-1.0,-1.0,-1.0,-1.0,79.263,2.21694,1832,4925657 +8192,144,search,7444.06,2688.68,3379.64,0.256733,251.063,0.92256,0.102539,-1.0,-1.0,26.662,2.21694,1832,4925657 +8192,145,delete,8.052,-1.0,-1.0,-1.0,-1.0,36.026,2.21602,1830,4922686 +8192,146,search,7585.19,2689.99,3515.08,0.251207,245.758,0.9223,0.103048,-1.0,-1.0,25.48,2.21602,1830,4922686 +8192,147,delete,22.881,-1.0,-1.0,-1.0,-1.0,23.918,2.21602,1830,4913636 +8192,148,search,7354.09,2685.05,3323.94,0.288858,219.784,0.92238,0.103047,-1.0,-1.0,24.987,2.21602,1830,4913636 +8192,149,delete,263.512,-1.0,-1.0,-1.0,-1.0,1064.58,2.13653,1750,4717250 +8192,150,search,7194.72,2695.57,3295,0.253421,246.721,0.92125,0.104502,-1.0,-1.0,49.497,2.13706,1753,4717250 +8192,151,delete,162.583,-1.0,-1.0,-1.0,-1.0,1026.41,2.06946,1675,4560269 diff --git a/scripts/big_ann_perf_numbers/perf_debug_scan_0.15_vary_num_search_workers.csv b/scripts/big_ann_perf_numbers/perf_debug_scan_0.15_vary_num_search_workers.csv new file mode 100644 index 00000000..b3e274fc --- /dev/null +++ b/scripts/big_ann_perf_numbers/perf_debug_scan_0.15_vary_num_search_workers.csv @@ -0,0 +1,901 @@ +num_search_workers,step_num,step_type,search_latency_ms,worker_partition_size,worker_scan_throughput,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +1,2,search,3041.02,37.5515,2.35049,0.8551,0.130106,-1.0,-1.0,6.569,0.0184881,1000,38806 +1,3,insert,12.216,-1.0,-1.0,-1.0,-1.0,13.346,0.022655,996,49334 +1,4,search,3219.15,63.4255,1.99793,0.86686,0.128427,-1.0,-1.0,17.589,0.0226615,993,49334 +1,5,insert,18.915,-1.0,-1.0,-1.0,-1.0,161.53,0.033017,984,73557 +1,6,search,4124.28,173.596,1.72628,0.92515,0.103785,-1.0,-1.0,121.338,0.0331618,986,73557 +1,7,insert,22.396,-1.0,-1.0,-1.0,-1.0,121.051,0.0426658,987,95766 +1,8,search,4544.66,220.032,1.52979,0.92462,0.103689,-1.0,-1.0,89.651,0.0428151,991,95766 +1,9,insert,4.503,-1.0,-1.0,-1.0,-1.0,74.201,0.0445618,991,100025 +1,10,search,4570.37,226.619,1.59938,0.92565,0.101549,-1.0,-1.0,80.666,0.0446017,994,100025 +1,11,insert,8.797,-1.0,-1.0,-1.0,-1.0,78.762,0.0498511,995,111417 +1,12,search,4870.43,261.637,1.48005,0.92608,0.101825,-1.0,-1.0,22.111,0.0498866,996,111417 +1,13,insert,25.643,-1.0,-1.0,-1.0,-1.0,7.968,0.0611449,997,137139 +1,14,search,5269.66,299.297,1.29259,0.92196,0.104759,-1.0,-1.0,15.705,0.0611514,999,137139 +1,15,insert,15.116,-1.0,-1.0,-1.0,-1.0,6.531,0.0699051,999,156710 +1,16,search,5533.3,330.607,1.22835,0.92003,0.105131,-1.0,-1.0,21.036,0.06991,1003,156710 +1,17,insert,5.158,-1.0,-1.0,-1.0,-1.0,8.72,0.0717831,1004,161773 +1,18,search,5637.13,338.418,1.16719,0.92029,0.105277,-1.0,-1.0,6.641,0.0717831,1004,161773 +1,19,insert,30.59,-1.0,-1.0,-1.0,-1.0,10.387,0.0787456,1006,177161 +1,20,search,5925.42,373.957,1.17113,0.92341,0.102841,-1.0,-1.0,9.065,0.0787456,1006,177161 +1,21,insert,332.691,-1.0,-1.0,-1.0,-1.0,162.922,0.200847,1051,448898 +1,22,search,9672.62,768.462,0.974077,0.91039,0.107984,-1.0,-1.0,39.3,0.200845,1061,448898 +1,23,insert,385.399,-1.0,-1.0,-1.0,-1.0,251.556,0.328422,1116,733493 +1,24,search,12577.6,1064.04,0.900795,0.90613,0.110085,-1.0,-1.0,72.28,0.328846,1129,733493 +1,25,insert,39.546,-1.0,-1.0,-1.0,-1.0,22.684,0.345771,1133,777443 +1,26,search,9218.54,1068.79,1.36891,0.9063,0.110352,-1.0,-1.0,24.831,0.345966,1137,777443 +1,27,insert,26.449,-1.0,-1.0,-1.0,-1.0,20.158,0.357754,1140,805394 +1,28,search,9415.66,1079.21,1.27462,0.90756,0.109157,-1.0,-1.0,9.438,0.357754,1140,805394 +1,29,insert,53.934,-1.0,-1.0,-1.0,-1.0,59.476,0.385616,1153,866391 +1,30,search,9687.31,1130.84,1.26147,0.90884,0.109052,-1.0,-1.0,37.249,0.385713,1157,866391 +1,31,insert,499.712,-1.0,-1.0,-1.0,-1.0,316.025,0.554314,1222,1239816 +1,32,search,11999.8,1403.7,1.23337,0.9035,0.113402,-1.0,-1.0,40.458,0.554578,1229,1239816 +1,33,insert,45.495,-1.0,-1.0,-1.0,-1.0,26.435,0.575056,1233,1291211 +1,34,search,12195.2,1430.14,1.33286,0.9036,0.113131,-1.0,-1.0,21.768,0.575285,1235,1291211 +1,35,insert,42.954,-1.0,-1.0,-1.0,-1.0,31.873,0.586476,1241,1324978 +1,36,search,12528.4,1457.45,1.20186,0.90569,0.111542,-1.0,-1.0,9.11,0.586476,1241,1324978 +1,37,insert,42.945,-1.0,-1.0,-1.0,-1.0,39.799,0.606427,1248,1371885 +1,38,search,12661.1,1480.18,1.19221,0.90461,0.112684,-1.0,-1.0,17.839,0.606427,1249,1371885 +1,39,insert,9.151,-1.0,-1.0,-1.0,-1.0,12.12,0.608926,1250,1379335 +1,40,search,12711.8,1482.08,1.23777,0.90496,0.112945,-1.0,-1.0,18.692,0.608925,1251,1379335 +1,41,insert,53.392,-1.0,-1.0,-1.0,-1.0,31.297,0.624188,1256,1413312 +1,42,search,12893,1502.65,1.33865,0.90518,0.112837,-1.0,-1.0,12.926,0.624188,1257,1413312 +1,43,insert,10.728,-1.0,-1.0,-1.0,-1.0,9.036,0.627895,1257,1423411 +1,44,search,13007.2,1513.1,1.30939,0.90522,0.112906,-1.0,-1.0,10.922,0.627895,1257,1423411 +1,45,insert,212.004,-1.0,-1.0,-1.0,-1.0,34.05,0.644498,1265,1457559 +1,46,search,13126.9,1526.57,1.20765,0.90558,0.111887,-1.0,-1.0,9.265,0.644498,1265,1457559 +1,47,insert,270.324,-1.0,-1.0,-1.0,-1.0,257.348,0.749159,1302,1688593 +1,48,search,14267,1647.21,1.16508,0.90715,0.111944,-1.0,-1.0,87.88,0.74928,1312,1688593 +1,49,insert,41.69,-1.0,-1.0,-1.0,-1.0,32.611,0.764772,1316,1723505 +1,50,search,14421.7,1652.59,1.25374,0.90783,0.111678,-1.0,-1.0,36.094,0.764799,1320,1723505 +1,51,insert,340.488,-1.0,-1.0,-1.0,-1.0,267.538,0.904316,1368,2035040 +1,52,search,16192,1816.7,1.1727,0.91084,0.110713,-1.0,-1.0,37.51,0.904316,1373,2035040 +1,53,insert,40.587,-1.0,-1.0,-1.0,-1.0,27.702,0.92232,1377,2078341 +1,54,search,16424.8,1835.53,1.05095,0.91104,0.110612,-1.0,-1.0,21.08,0.92246,1378,2078341 +1,55,insert,376.04,-1.0,-1.0,-1.0,-1.0,343.893,1.06819,1428,2399905 +1,56,search,18190.4,2005.34,1.13022,0.91146,0.113147,-1.0,-1.0,110.494,1.06853,1446,2399905 +1,57,insert,24.763,-1.0,-1.0,-1.0,-1.0,10.311,1.0757,1446,2419836 +1,58,search,18239.1,1975.18,1.18929,0.91027,0.114083,-1.0,-1.0,38.572,1.07571,1449,2419836 +1,59,insert,223.012,-1.0,-1.0,-1.0,-1.0,153.288,1.17443,1467,2643083 +1,60,search,18895.6,2046.33,1.1691,0.90396,0.121349,-1.0,-1.0,48.185,1.17467,1473,2643083 +1,61,insert,11.389,-1.0,-1.0,-1.0,-1.0,18.057,1.17897,1475,2653064 +1,62,search,18868.6,2034.29,1.09455,0.90343,0.122239,-1.0,-1.0,33.74,1.17897,1477,2653064 +1,63,insert,3.327,-1.0,-1.0,-1.0,-1.0,10.78,1.18007,1477,2656118 +1,64,search,18872.5,2035.01,1.11813,0.90337,0.122128,-1.0,-1.0,10.967,1.18007,1477,2656118 +1,65,insert,74.924,-1.0,-1.0,-1.0,-1.0,104.973,1.2077,1498,2723424 +1,66,search,19248.3,2046.74,1.09577,0.90431,0.120908,-1.0,-1.0,13.283,1.2077,1498,2723424 +1,67,insert,47.134,-1.0,-1.0,-1.0,-1.0,85.911,1.22905,1510,2769021 +1,68,search,19692.9,2069.1,1.04242,0.90574,0.119845,-1.0,-1.0,29.403,1.22908,1513,2769021 +1,69,insert,74.313,-1.0,-1.0,-1.0,-1.0,86.767,1.25251,1526,2821777 +1,70,search,19884.3,2076.75,1.16115,0.90762,0.118339,-1.0,-1.0,24.1,1.25252,1528,2821777 +1,71,insert,16.359,-1.0,-1.0,-1.0,-1.0,11.324,1.25746,1528,2834921 +1,72,search,20108.4,2086.32,1.16793,0.90859,0.11757,-1.0,-1.0,11.825,1.25746,1528,2834921 +1,73,insert,11.288,-1.0,-1.0,-1.0,-1.0,18.508,1.26103,1529,2842044 +1,74,search,20038.5,2089.51,1.22707,0.90865,0.117458,-1.0,-1.0,11.755,1.26103,1529,2842044 +1,75,insert,21.897,-1.0,-1.0,-1.0,-1.0,22.823,1.26745,1531,2858890 +1,76,search,20081.6,2099.23,1.16853,0.90883,0.117172,-1.0,-1.0,11.751,1.26745,1531,2858890 +1,77,insert,32.323,-1.0,-1.0,-1.0,-1.0,17.737,1.27654,1532,2882818 +1,78,search,20165.7,2109.99,1.15245,0.90837,0.117274,-1.0,-1.0,11.78,1.27654,1532,2882818 +1,79,insert,496.959,-1.0,-1.0,-1.0,-1.0,15.973,1.306,1533,2947806 +1,80,search,20489,2147.08,1.14943,0.90817,0.117139,-1.0,-1.0,13.549,1.306,1533,2947806 +1,81,insert,45.492,-1.0,-1.0,-1.0,-1.0,19.005,1.31888,1534,2976895 +1,82,search,20712.6,2161.9,1.08715,0.90956,0.115938,-1.0,-1.0,20.492,1.31888,1535,2976895 +1,83,insert,23.294,-1.0,-1.0,-1.0,-1.0,42.008,1.32482,1539,2990682 +1,84,search,20862.9,2161.48,1.06221,0.90964,0.115826,-1.0,-1.0,11.871,1.32482,1539,2990682 +1,85,insert,40.832,-1.0,-1.0,-1.0,-1.0,59.913,1.33944,1548,3025613 +1,86,search,20941.7,2163.01,1.11224,0.9107,0.114971,-1.0,-1.0,26.67,1.3396,1550,3025613 +1,87,insert,589.157,-1.0,-1.0,-1.0,-1.0,694.865,1.54209,1653,3468632 +1,88,search,23208.7,2295.57,1.16528,0.91363,0.11126,-1.0,-1.0,105.548,1.54266,1668,3468632 +1,89,insert,384.214,-1.0,-1.0,-1.0,-1.0,467.021,1.7034,1743,3831692 +1,90,search,25344.1,2383.57,1.05045,0.9182,0.106233,-1.0,-1.0,113.544,1.70406,1754,3831692 +1,91,insert,33.999,-1.0,-1.0,-1.0,-1.0,45.218,1.71379,1759,3864067 +1,92,search,25686.5,2375.4,1.0641,0.91838,0.10623,-1.0,-1.0,18.872,1.71379,1759,3864067 +1,93,insert,301.532,-1.0,-1.0,-1.0,-1.0,281.691,1.81925,1800,4103827 +1,94,search,27210.3,2434.02,1.06267,0.9187,0.105629,-1.0,-1.0,55.701,1.81954,1806,4103827 +1,95,insert,18.538,-1.0,-1.0,-1.0,-1.0,67.53,1.82616,1816,4119898 +1,96,search,26839.5,2411.5,1.13688,0.91844,0.10598,-1.0,-1.0,20.941,1.82616,1816,4119898 +1,97,insert,13.85,-1.0,-1.0,-1.0,-1.0,25.361,1.82956,1817,4129367 +1,98,search,26775.9,2414.53,1.12283,0.91849,0.105796,-1.0,-1.0,24.067,1.82956,1817,4129367 +1,99,insert,13.378,-1.0,-1.0,-1.0,-1.0,31.307,1.83169,1818,4134502 +1,100,search,26830.4,2416.9,1.12109,0.91857,0.105814,-1.0,-1.0,23.206,1.83169,1818,4134502 +1,101,insert,58.333,-1.0,-1.0,-1.0,-1.0,85.61,1.84323,1826,4164482 +1,102,search,27088.1,2419.71,1.09843,0.91865,0.105877,-1.0,-1.0,22.016,1.84323,1826,4164482 +1,103,insert,23.192,-1.0,-1.0,-1.0,-1.0,54.56,1.84952,1831,4178601 +1,104,search,27049,2421.94,1.17848,0.91888,0.105524,-1.0,-1.0,21.449,1.84952,1831,4178601 +1,105,insert,12.052,-1.0,-1.0,-1.0,-1.0,37.175,1.85301,1833,4187774 +1,106,search,27022.3,2423.68,1.13577,0.91875,0.105755,-1.0,-1.0,25.738,1.85301,1833,4187774 +1,107,insert,36.091,-1.0,-1.0,-1.0,-1.0,32.634,1.85861,1834,4200109 +1,108,search,27399,2427.01,1.16731,0.91902,0.105516,-1.0,-1.0,41.12,1.85888,1836,4200109 +1,109,insert,532.018,-1.0,-1.0,-1.0,-1.0,567.056,2.01715,1916,4557867 +1,110,search,29073.2,2500.08,1.02343,0.92089,0.104333,-1.0,-1.0,114.965,2.01799,1929,4557867 +1,111,insert,32.011,-1.0,-1.0,-1.0,-1.0,55.554,2.02985,1935,4587252 +1,112,search,29103.3,2488.06,1.16266,0.92124,0.104354,-1.0,-1.0,38.985,2.03016,1936,4587252 +1,113,insert,16.645,-1.0,-1.0,-1.0,-1.0,33.021,2.03619,1937,4600056 +1,114,search,29182.7,2493.22,1.12484,0.92124,0.104306,-1.0,-1.0,30.348,2.03619,1937,4600056 +1,115,insert,55.663,-1.0,-1.0,-1.0,-1.0,91.788,2.04608,1945,4627422 +1,116,search,29414.3,2497.54,1.09819,0.92178,0.103821,-1.0,-1.0,38.11,2.04616,1946,4627422 +1,117,insert,16.611,-1.0,-1.0,-1.0,-1.0,61.986,2.0508,1951,4639292 +1,118,search,29601.1,2493.74,1.11525,0.92188,0.103609,-1.0,-1.0,27.882,2.0508,1951,4639292 +1,119,insert,6.609,-1.0,-1.0,-1.0,-1.0,26.508,2.05212,1951,4643423 +1,120,search,29514.8,2495.48,1.08879,0.92191,0.103644,-1.0,-1.0,29.764,2.05212,1951,4643423 +1,121,insert,25.536,-1.0,-1.0,-1.0,-1.0,47.392,2.05838,1953,4657252 +1,122,search,29667.7,2499.6,1.12896,0.92212,0.103439,-1.0,-1.0,41.421,2.05851,1954,4657252 +1,123,insert,441.318,-1.0,-1.0,-1.0,-1.0,394.679,2.1853,2001,4938477 +1,124,search,31092.7,2552.94,1.09875,0.9227,0.104324,-1.0,-1.0,150.875,2.18609,2017,4938477 +1,125,insert,66.458,-1.0,-1.0,-1.0,-1.0,88.746,2.20322,2027,4980492 +1,126,search,30867.6,2529.58,1.15167,0.92297,0.104232,-1.0,-1.0,79.895,2.20375,2033,4980492 +1,127,insert,61.024,-1.0,-1.0,-1.0,-1.0,127.246,2.22506,2050,5030515 +1,128,search,31279.9,2527,1.02765,0.92343,0.103974,-1.0,-1.0,34.822,2.22506,2050,5030515 +1,129,delete,47.274,-1.0,-1.0,-1.0,-1.0,56.363,2.22344,2021,5009391 +1,130,search,30939.4,2527.96,1.08557,0.9225,0.104636,-1.0,-1.0,33.142,2.22344,2021,5009391 +1,131,delete,10.986,-1.0,-1.0,-1.0,-1.0,31.055,2.22344,2021,5004093 +1,132,search,30961.6,2525.17,1.06026,0.92251,0.104598,-1.0,-1.0,32.226,2.22344,2021,5004093 +1,133,delete,17.161,-1.0,-1.0,-1.0,-1.0,30.524,2.22344,2021,4991787 +1,134,search,30542.5,2515.05,1.10369,0.92255,0.104611,-1.0,-1.0,34.636,2.22344,2021,4991787 +1,135,delete,40.929,-1.0,-1.0,-1.0,-1.0,57.954,2.22061,2018,4974857 +1,136,search,30610.8,2507.9,1.12306,0.92213,0.104712,-1.0,-1.0,33.452,2.22061,2018,4974857 +1,137,delete,8.038,-1.0,-1.0,-1.0,-1.0,31.016,2.22061,2018,4971386 +1,138,search,30676.7,2506.68,1.08796,0.9221,0.104825,-1.0,-1.0,32.099,2.22061,2018,4971386 +1,139,delete,12.664,-1.0,-1.0,-1.0,-1.0,30.713,2.22061,2018,4963487 +1,140,search,30628.7,2500.68,1.09972,0.92203,0.104831,-1.0,-1.0,34.227,2.22061,2018,4963487 +1,141,delete,49.162,-1.0,-1.0,-1.0,-1.0,104.43,2.21454,2010,4941830 +1,142,search,30669.6,2496.64,1.09216,0.92204,0.104832,-1.0,-1.0,33.196,2.21454,2010,4941830 +1,143,delete,27.193,-1.0,-1.0,-1.0,-1.0,57.255,2.2117,2007,4925657 +1,144,search,30398.4,2490.26,1.12346,0.92212,0.104698,-1.0,-1.0,32.262,2.2117,2007,4925657 +1,145,delete,3.933,-1.0,-1.0,-1.0,-1.0,41.687,2.21131,2006,4922686 +1,146,search,30044.9,2490.88,1.12654,0.92143,0.105387,-1.0,-1.0,33.459,2.21131,2006,4922686 +1,147,delete,23.872,-1.0,-1.0,-1.0,-1.0,30.86,2.21131,2006,4913636 +1,148,search,29974.5,2485.2,1.12118,0.9213,0.105497,-1.0,-1.0,33.342,2.21131,2006,4913636 +1,149,delete,271.29,-1.0,-1.0,-1.0,-1.0,1172.09,2.13327,1914,4717250 +1,150,search,28869.3,2493.96,1.0694,0.92059,0.106552,-1.0,-1.0,129.75,2.13493,1927,4717250 +1,151,delete,163.281,-1.0,-1.0,-1.0,-1.0,954.39,2.06358,1846,4560269 +2,2,search,2622.87,37.5515,2.68484,0.8551,0.130106,-1.0,-1.0,6.887,0.0184881,1000,38806 +2,3,insert,9.276,-1.0,-1.0,-1.0,-1.0,13.925,0.022655,996,49334 +2,4,search,2735.03,63.4255,1.7385,0.86686,0.128427,-1.0,-1.0,12.3,0.0226615,993,49334 +2,5,insert,20.579,-1.0,-1.0,-1.0,-1.0,162.297,0.0329603,983,73557 +2,6,search,2854.5,173.821,1.70125,0.92559,0.103361,-1.0,-1.0,124.129,0.0331112,985,73557 +2,7,insert,25.151,-1.0,-1.0,-1.0,-1.0,123.007,0.0427474,986,95766 +2,8,search,2971.72,219.876,1.4926,0.92461,0.104001,-1.0,-1.0,88.291,0.0428988,990,95766 +2,9,insert,3.502,-1.0,-1.0,-1.0,-1.0,74.374,0.0446421,990,100025 +2,10,search,3008.89,226.697,1.44461,0.92644,0.101101,-1.0,-1.0,82.823,0.0446707,993,100025 +2,11,insert,10.034,-1.0,-1.0,-1.0,-1.0,81.162,0.0497634,995,111417 +2,12,search,3132.37,262.143,1.3789,0.92604,0.10176,-1.0,-1.0,16.724,0.0498139,996,111417 +2,13,insert,28.447,-1.0,-1.0,-1.0,-1.0,9.872,0.0610221,996,137139 +2,14,search,3239.37,298.935,1.17255,0.92257,0.104007,-1.0,-1.0,21.857,0.0611274,999,137139 +2,15,insert,21.913,-1.0,-1.0,-1.0,-1.0,9.669,0.0699557,1000,156710 +2,16,search,3204.3,330.019,1.27262,0.92096,0.104291,-1.0,-1.0,19.105,0.069963,1004,156710 +2,17,insert,6.122,-1.0,-1.0,-1.0,-1.0,8.861,0.0721458,1005,161773 +2,18,search,3179.88,339.902,1.41786,0.92005,0.105323,-1.0,-1.0,13.175,0.0722572,1007,161773 +2,19,insert,34.962,-1.0,-1.0,-1.0,-1.0,12.462,0.0789908,1009,177161 +2,20,search,3473.31,372.582,1.12162,0.92394,0.102681,-1.0,-1.0,9.612,0.0789912,1010,177161 +2,21,insert,261.815,-1.0,-1.0,-1.0,-1.0,116.736,0.202448,1069,448898 +2,22,search,4376.49,737.114,1.09947,0.90854,0.108821,-1.0,-1.0,57.076,0.202448,1082,448898 +2,23,insert,235.101,-1.0,-1.0,-1.0,-1.0,208.2,0.329637,1147,733493 +2,24,search,5781.84,1002.24,0.824772,0.90335,0.112134,-1.0,-1.0,105.092,0.330475,1175,733493 +2,25,insert,34.492,-1.0,-1.0,-1.0,-1.0,24.483,0.346577,1180,777443 +2,26,search,5566.65,969.016,0.956156,0.90152,0.113747,-1.0,-1.0,19.396,0.34669,1185,777443 +2,27,insert,20.974,-1.0,-1.0,-1.0,-1.0,16.754,0.357375,1189,805394 +2,28,search,5593.76,972.996,0.911176,0.90191,0.113691,-1.0,-1.0,16.712,0.357599,1191,805394 +2,29,insert,61.353,-1.0,-1.0,-1.0,-1.0,67.285,0.384967,1206,866391 +2,30,search,5399.15,1018.22,0.93607,0.9037,0.113636,-1.0,-1.0,17.583,0.384967,1211,866391 +2,31,insert,226.388,-1.0,-1.0,-1.0,-1.0,201.031,0.555095,1293,1239816 +2,32,search,5873.16,1251.44,0.927909,0.89675,0.117471,-1.0,-1.0,38.566,0.555304,1303,1239816 +2,33,insert,32.247,-1.0,-1.0,-1.0,-1.0,21.848,0.575302,1311,1291211 +2,34,search,7228.25,1258.37,0.8108,0.89778,0.118167,-1.0,-1.0,13.817,0.575325,1312,1291211 +2,35,insert,42.78,-1.0,-1.0,-1.0,-1.0,20.86,0.586996,1317,1324978 +2,36,search,7466.19,1286.04,0.769098,0.89898,0.117229,-1.0,-1.0,10.704,0.586996,1317,1324978 +2,37,insert,55.749,-1.0,-1.0,-1.0,-1.0,44.84,0.607123,1325,1371885 +2,38,search,7469.77,1308.58,0.814424,0.89885,0.117051,-1.0,-1.0,16.289,0.607123,1326,1371885 +2,39,insert,10.446,-1.0,-1.0,-1.0,-1.0,18.827,0.610253,1329,1379335 +2,40,search,7855.46,1306.97,0.740569,0.89908,0.117339,-1.0,-1.0,13.571,0.610254,1330,1379335 +2,41,insert,43.425,-1.0,-1.0,-1.0,-1.0,24.914,0.625029,1333,1413312 +2,42,search,7655.77,1331.6,0.859088,0.89972,0.117315,-1.0,-1.0,15.759,0.625034,1335,1413312 +2,43,insert,11.887,-1.0,-1.0,-1.0,-1.0,15.179,0.629252,1337,1423411 +2,44,search,7746.13,1336.27,0.801166,0.89988,0.116567,-1.0,-1.0,12.605,0.629252,1337,1423411 +2,45,insert,251.92,-1.0,-1.0,-1.0,-1.0,59.529,0.644735,1353,1457559 +2,46,search,7877.17,1334.49,0.851159,0.89993,0.115641,-1.0,-1.0,10.259,0.644735,1353,1457559 +2,47,insert,291.085,-1.0,-1.0,-1.0,-1.0,239.235,0.747711,1393,1688593 +2,48,search,8469.82,1451.52,0.756066,0.90206,0.115209,-1.0,-1.0,73.103,0.747883,1401,1688593 +2,49,insert,40.099,-1.0,-1.0,-1.0,-1.0,35.081,0.764194,1408,1723505 +2,50,search,8473.38,1454.77,0.797663,0.90358,0.11361,-1.0,-1.0,34.384,0.764268,1412,1723505 +2,51,insert,322.679,-1.0,-1.0,-1.0,-1.0,291.354,0.904976,1477,2035040 +2,52,search,9258.04,1591.15,0.77644,0.90669,0.112468,-1.0,-1.0,39.385,0.905048,1483,2035040 +2,53,insert,39.477,-1.0,-1.0,-1.0,-1.0,33.376,0.922384,1488,2078341 +2,54,search,9511.5,1600.53,0.755075,0.90694,0.112608,-1.0,-1.0,13.996,0.922384,1488,2078341 +2,55,insert,348.494,-1.0,-1.0,-1.0,-1.0,326.501,1.06856,1559,2399905 +2,56,search,8307.67,1747.65,1.07564,0.90864,0.11261,-1.0,-1.0,129.971,1.0695,1581,2399905 +2,57,insert,24.296,-1.0,-1.0,-1.0,-1.0,11.264,1.0766,1581,2419836 +2,58,search,10458.1,1713.75,0.776625,0.90815,0.11283,-1.0,-1.0,61.064,1.07665,1587,2419836 +2,59,insert,245.827,-1.0,-1.0,-1.0,-1.0,192.683,1.1748,1612,2643083 +2,60,search,11234.5,1758.44,0.697863,0.90112,0.121304,-1.0,-1.0,34.306,1.17485,1617,2643083 +2,61,insert,10.514,-1.0,-1.0,-1.0,-1.0,26.086,1.17871,1621,2653064 +2,62,search,11273,1749.71,0.690127,0.90109,0.121204,-1.0,-1.0,15.051,1.17871,1621,2653064 +2,63,insert,5.668,-1.0,-1.0,-1.0,-1.0,12.601,1.1797,1621,2656118 +2,64,search,11229.1,1750.71,0.759291,0.90126,0.121037,-1.0,-1.0,14.49,1.1797,1621,2656118 +2,65,insert,106.115,-1.0,-1.0,-1.0,-1.0,137.157,1.20972,1653,2723424 +2,66,search,10775.7,1754.85,0.813801,0.90142,0.120116,-1.0,-1.0,16.838,1.20979,1654,2723424 +2,67,insert,42.991,-1.0,-1.0,-1.0,-1.0,75.173,1.22933,1672,2769021 +2,68,search,10816.2,1762.53,0.828548,0.90262,0.119441,-1.0,-1.0,25.062,1.22951,1675,2769021 +2,69,insert,49.907,-1.0,-1.0,-1.0,-1.0,75.983,1.25182,1687,2821777 +2,70,search,10841.5,1776.03,0.771849,0.90441,0.117906,-1.0,-1.0,13.237,1.25182,1688,2821777 +2,71,insert,8.558,-1.0,-1.0,-1.0,-1.0,17.199,1.25778,1692,2834921 +2,72,search,10758.3,1781.19,0.836105,0.90467,0.117858,-1.0,-1.0,16.076,1.25778,1692,2834921 +2,73,insert,6.875,-1.0,-1.0,-1.0,-1.0,14.347,1.25976,1692,2842044 +2,74,search,11592.8,1784.12,0.733229,0.90467,0.117884,-1.0,-1.0,16.53,1.25976,1692,2842044 +2,75,insert,34.574,-1.0,-1.0,-1.0,-1.0,19.116,1.26646,1693,2858890 +2,76,search,10717.5,1793.88,0.809648,0.90492,0.117903,-1.0,-1.0,15.598,1.26646,1693,2858890 +2,77,insert,47.949,-1.0,-1.0,-1.0,-1.0,19.568,1.2767,1694,2882818 +2,78,search,9197.41,1804.2,1.04464,0.905,0.117738,-1.0,-1.0,14.783,1.2767,1694,2882818 +2,79,insert,410.481,-1.0,-1.0,-1.0,-1.0,18.173,1.30315,1698,2947806 +2,80,search,9127.76,1832.23,1.10464,0.90462,0.117982,-1.0,-1.0,14.542,1.30315,1698,2947806 +2,81,insert,38.046,-1.0,-1.0,-1.0,-1.0,34.851,1.31631,1702,2976895 +2,82,search,9304.43,1842.15,1.03268,0.90598,0.117141,-1.0,-1.0,14.477,1.31631,1702,2976895 +2,83,insert,15.115,-1.0,-1.0,-1.0,-1.0,31.38,1.3224,1706,2990682 +2,84,search,9304.42,1844.16,1.04165,0.90608,0.117089,-1.0,-1.0,14.92,1.3224,1706,2990682 +2,85,insert,34.561,-1.0,-1.0,-1.0,-1.0,36.295,1.33694,1709,3025613 +2,86,search,9435.46,1861.59,1.06848,0.90692,0.116369,-1.0,-1.0,16.285,1.33694,1709,3025613 +2,87,insert,471.289,-1.0,-1.0,-1.0,-1.0,559.258,1.54077,1809,3468632 +2,88,search,10435,2004.02,0.985132,0.91044,0.113806,-1.0,-1.0,108.46,1.54079,1822,3468632 +2,89,insert,311.964,-1.0,-1.0,-1.0,-1.0,491.747,1.70225,1925,3831692 +2,90,search,10998.7,2060.14,1.01067,0.91457,0.108833,-1.0,-1.0,87.647,1.7027,1935,3831692 +2,91,insert,33.889,-1.0,-1.0,-1.0,-1.0,63.145,1.71386,1942,3864067 +2,92,search,10836.4,2059.49,1.1055,0.91551,0.107688,-1.0,-1.0,45.413,1.7144,1945,3864067 +2,93,insert,282.536,-1.0,-1.0,-1.0,-1.0,268.715,1.81848,1988,4103827 +2,94,search,11139.2,2110.25,1.13448,0.91595,0.107422,-1.0,-1.0,56.783,1.81879,1993,4103827 +2,95,insert,16.346,-1.0,-1.0,-1.0,-1.0,51.138,1.82422,1998,4119898 +2,96,search,10910.1,2106.72,1.0892,0.91607,0.107545,-1.0,-1.0,24.122,1.82423,1999,4119898 +2,97,insert,7.635,-1.0,-1.0,-1.0,-1.0,26.692,1.82934,2001,4129367 +2,98,search,11027,2105.71,1.09818,0.91617,0.107333,-1.0,-1.0,27.279,1.82954,2002,4129367 +2,99,insert,5.776,-1.0,-1.0,-1.0,-1.0,20.894,1.83117,2002,4134502 +2,100,search,11152.5,2108.08,1.18036,0.91631,0.107257,-1.0,-1.0,33.603,1.83117,2002,4134502 +2,101,insert,50.088,-1.0,-1.0,-1.0,-1.0,44.94,1.84336,2004,4164482 +2,102,search,11338.2,2121.6,1.10594,0.91628,0.107175,-1.0,-1.0,40.111,1.84346,2005,4164482 +2,103,insert,21.997,-1.0,-1.0,-1.0,-1.0,44.11,1.85056,2007,4178601 +2,104,search,11637.7,2126.2,1.08574,0.91682,0.106858,-1.0,-1.0,36.743,1.85063,2008,4178601 +2,105,insert,9.666,-1.0,-1.0,-1.0,-1.0,45.321,1.85401,2010,4187774 +2,106,search,11586.7,2127.37,1.09732,0.91654,0.106957,-1.0,-1.0,31.608,1.85401,2010,4187774 +2,107,insert,18.797,-1.0,-1.0,-1.0,-1.0,37.759,1.85839,2011,4200109 +2,108,search,11602.4,2129.81,1.06016,0.91637,0.107267,-1.0,-1.0,32.963,1.85839,2011,4200109 +2,109,insert,495.046,-1.0,-1.0,-1.0,-1.0,493.929,2.01985,2094,4557867 +2,110,search,11718.8,2205.76,1.11053,0.91902,0.104918,-1.0,-1.0,86.253,2.0212,2111,4557867 +2,111,insert,16.295,-1.0,-1.0,-1.0,-1.0,54.711,2.03354,2123,4587252 +2,112,search,12240.9,2186.1,1.09333,0.91947,0.104973,-1.0,-1.0,37.383,2.03354,2123,4587252 +2,113,insert,12.797,-1.0,-1.0,-1.0,-1.0,57.449,2.03787,2126,4600056 +2,114,search,12417.5,2189.23,1.10715,0.91945,0.105078,-1.0,-1.0,38.195,2.03787,2126,4600056 +2,115,insert,48.612,-1.0,-1.0,-1.0,-1.0,57.932,2.04858,2130,4627422 +2,116,search,12261.6,2197.43,1.13185,0.92001,0.104622,-1.0,-1.0,30.143,2.04884,2131,4627422 +2,117,insert,9.377,-1.0,-1.0,-1.0,-1.0,24.399,2.05297,2131,4639292 +2,118,search,12350,2200.12,1.04967,0.91996,0.104482,-1.0,-1.0,37.497,2.05297,2131,4639292 +2,119,insert,5.715,-1.0,-1.0,-1.0,-1.0,35.253,2.05445,2131,4643423 +2,120,search,12531.7,2202.67,1.07882,0.91998,0.104392,-1.0,-1.0,37.51,2.05445,2131,4643423 +2,121,insert,22.101,-1.0,-1.0,-1.0,-1.0,58.241,2.06029,2135,4657252 +2,122,search,12535.8,2201.42,1.11668,0.92024,0.104231,-1.0,-1.0,36.267,2.06029,2135,4657252 +2,123,insert,379.367,-1.0,-1.0,-1.0,-1.0,501.033,2.18966,2192,4938477 +2,124,search,12939.9,2251.48,1.14946,0.92104,0.104985,-1.0,-1.0,112.442,2.19082,2213,4938477 +2,125,insert,35.285,-1.0,-1.0,-1.0,-1.0,76.917,2.20853,2223,4980492 +2,126,search,13019.6,2230.79,1.09592,0.92136,0.104736,-1.0,-1.0,53.808,2.20864,2225,4980492 +2,127,insert,61.168,-1.0,-1.0,-1.0,-1.0,99.831,2.22879,2237,5030515 +2,128,search,13266.6,2238.79,1.05305,0.92201,0.10452,-1.0,-1.0,38.213,2.22879,2237,5030515 +2,129,delete,29.933,-1.0,-1.0,-1.0,-1.0,69.706,2.22675,2203,5009391 +2,130,search,12714.2,2240.61,1.12574,0.92103,0.105021,-1.0,-1.0,26.686,2.22675,2203,5009391 +2,131,delete,5.729,-1.0,-1.0,-1.0,-1.0,24.447,2.22675,2203,5004093 +2,132,search,12777.4,2237.64,1.09228,0.92097,0.105096,-1.0,-1.0,37.637,2.22675,2203,5004093 +2,133,delete,17.745,-1.0,-1.0,-1.0,-1.0,35.395,2.22675,2203,4991787 +2,134,search,12178.9,2228.22,1.1266,0.92076,0.105241,-1.0,-1.0,25.304,2.22675,2203,4991787 +2,135,delete,12.956,-1.0,-1.0,-1.0,-1.0,43.194,2.22455,2200,4974857 +2,136,search,12682.4,2222.2,1.07994,0.9208,0.105187,-1.0,-1.0,36.379,2.22455,2200,4974857 +2,137,delete,5.963,-1.0,-1.0,-1.0,-1.0,35.415,2.22455,2200,4971386 +2,138,search,12937.6,2220.74,1.08516,0.92077,0.105184,-1.0,-1.0,37.908,2.22455,2200,4971386 +2,139,delete,16.301,-1.0,-1.0,-1.0,-1.0,36.547,2.22455,2200,4963487 +2,140,search,12938.4,2216.32,1.18035,0.92065,0.105145,-1.0,-1.0,37.983,2.22455,2200,4963487 +2,141,delete,36.952,-1.0,-1.0,-1.0,-1.0,98.434,2.21998,2194,4941830 +2,142,search,12897.5,2209.62,1.08392,0.92046,0.105366,-1.0,-1.0,39.036,2.21998,2194,4941830 +2,143,delete,26.972,-1.0,-1.0,-1.0,-1.0,108.522,2.21458,2190,4925657 +2,144,search,12755.3,2206.7,1.11067,0.92037,0.105149,-1.0,-1.0,45.762,2.21467,2191,4925657 +2,145,delete,4.286,-1.0,-1.0,-1.0,-1.0,50.429,2.21359,2188,4922686 +2,146,search,12763.1,2206.43,1.09121,0.92014,0.105734,-1.0,-1.0,36.458,2.21359,2188,4922686 +2,147,delete,11.503,-1.0,-1.0,-1.0,-1.0,35.077,2.21359,2188,4913636 +2,148,search,12339.9,2200.89,1.09756,0.92013,0.105596,-1.0,-1.0,24.743,2.21359,2188,4913636 +2,149,delete,132.089,-1.0,-1.0,-1.0,-1.0,881.557,2.13101,2079,4717250 +2,150,search,12052.9,2225.63,1.09906,0.91965,0.106045,-1.0,-1.0,92.825,2.13244,2089,4717250 +2,151,delete,154.315,-1.0,-1.0,-1.0,-1.0,1144.17,2.06134,1991,4560269 +4,2,search,2648.89,37.5515,1.88773,0.8551,0.130106,-1.0,-1.0,7.64,0.0184881,1000,38806 +4,3,insert,12.009,-1.0,-1.0,-1.0,-1.0,14.808,0.022655,996,49334 +4,4,search,2539.51,63.4255,1.99265,0.86686,0.128427,-1.0,-1.0,17.91,0.0226819,989,49334 +4,5,insert,26.97,-1.0,-1.0,-1.0,-1.0,166.437,0.0328921,977,73557 +4,6,search,2658.6,177.353,1.62788,0.92606,0.103259,-1.0,-1.0,125.644,0.0330517,979,73557 +4,7,insert,30.268,-1.0,-1.0,-1.0,-1.0,125.916,0.0426943,980,95766 +4,8,search,2713.67,222.757,1.4305,0.92504,0.103629,-1.0,-1.0,32.131,0.0432982,985,95766 +4,9,insert,4.869,-1.0,-1.0,-1.0,-1.0,6.717,0.0450828,985,100025 +4,10,search,2759.96,227.581,1.28173,0.92592,0.101876,-1.0,-1.0,22.944,0.0451207,989,100025 +4,11,insert,13.801,-1.0,-1.0,-1.0,-1.0,13.078,0.0499266,992,111417 +4,12,search,2799.06,258.957,1.16719,0.92491,0.102748,-1.0,-1.0,23.034,0.0501546,997,111417 +4,13,insert,26.965,-1.0,-1.0,-1.0,-1.0,6.758,0.0612286,997,137139 +4,14,search,2638.15,293.564,1.37405,0.92153,0.10454,-1.0,-1.0,13.427,0.0612375,999,137139 +4,15,insert,25.853,-1.0,-1.0,-1.0,-1.0,13.327,0.069562,1001,156710 +4,16,search,2851.49,324.727,1.10201,0.91974,0.105152,-1.0,-1.0,7.265,0.069562,1001,156710 +4,17,insert,6.305,-1.0,-1.0,-1.0,-1.0,12.1,0.0715575,1003,161773 +4,18,search,2853.58,339.476,1.05827,0.92081,0.105107,-1.0,-1.0,7.396,0.0715575,1003,161773 +4,19,insert,37.852,-1.0,-1.0,-1.0,-1.0,12.907,0.0785114,1005,177161 +4,20,search,2826.04,375.64,1.0772,0.92445,0.101871,-1.0,-1.0,10.978,0.0785114,1006,177161 +4,21,insert,361.589,-1.0,-1.0,-1.0,-1.0,201.885,0.201554,1063,448898 +4,22,search,3374.26,744.238,0.854057,0.90874,0.108744,-1.0,-1.0,53.438,0.201553,1074,448898 +4,23,insert,394.692,-1.0,-1.0,-1.0,-1.0,259.614,0.329691,1134,733493 +4,24,search,3973.07,1027.45,0.777998,0.90456,0.110585,-1.0,-1.0,119.009,0.330318,1161,733493 +4,25,insert,41.615,-1.0,-1.0,-1.0,-1.0,25.088,0.347655,1165,777443 +4,26,search,3980.72,989.61,0.808181,0.90156,0.113667,-1.0,-1.0,21.389,0.347813,1168,777443 +4,27,insert,31.006,-1.0,-1.0,-1.0,-1.0,13.945,0.359663,1169,805394 +4,28,search,4042.56,1012.24,0.791303,0.90312,0.112023,-1.0,-1.0,14.428,0.359665,1170,805394 +4,29,insert,66.039,-1.0,-1.0,-1.0,-1.0,66.568,0.38664,1184,866391 +4,30,search,4162.44,1063.32,0.782776,0.90536,0.110946,-1.0,-1.0,28.54,0.386639,1187,866391 +4,31,insert,428.089,-1.0,-1.0,-1.0,-1.0,310.7,0.551452,1251,1239816 +4,32,search,4801.03,1334.93,0.683276,0.9004,0.115641,-1.0,-1.0,119.586,0.552172,1263,1239816 +4,33,insert,69.549,-1.0,-1.0,-1.0,-1.0,23.87,0.57367,1268,1291211 +4,34,search,4792.31,1335.96,0.758786,0.90063,0.115592,-1.0,-1.0,70.503,0.573836,1274,1291211 +4,35,insert,42.976,-1.0,-1.0,-1.0,-1.0,28.067,0.585118,1279,1324978 +4,36,search,4572.43,1359.92,0.850717,0.90129,0.114334,-1.0,-1.0,42.211,0.58512,1282,1324978 +4,37,insert,65.822,-1.0,-1.0,-1.0,-1.0,34.349,0.606691,1288,1371885 +4,38,search,4978,1380.02,0.769329,0.9023,0.113605,-1.0,-1.0,10.303,0.606691,1288,1371885 +4,39,insert,9.559,-1.0,-1.0,-1.0,-1.0,14.027,0.609658,1290,1379335 +4,40,search,4785.97,1381.63,0.847907,0.90231,0.113761,-1.0,-1.0,10.332,0.609658,1290,1379335 +4,41,insert,49.91,-1.0,-1.0,-1.0,-1.0,36.364,0.625428,1296,1413312 +4,42,search,4731.48,1400.39,0.778653,0.90314,0.113453,-1.0,-1.0,10.085,0.625428,1296,1413312 +4,43,insert,11.275,-1.0,-1.0,-1.0,-1.0,13.184,0.628646,1297,1423411 +4,44,search,4790.58,1410.94,0.823537,0.90341,0.113374,-1.0,-1.0,10.323,0.628646,1297,1423411 +4,45,insert,227.598,-1.0,-1.0,-1.0,-1.0,35.812,0.643613,1305,1457559 +4,46,search,5068.68,1425.96,0.731091,0.90349,0.11292,-1.0,-1.0,9.942,0.643613,1305,1457559 +4,47,insert,299.283,-1.0,-1.0,-1.0,-1.0,247.048,0.749626,1343,1688593 +4,48,search,5039.08,1552.73,0.957053,0.90646,0.111837,-1.0,-1.0,83.071,0.749902,1352,1688593 +4,49,insert,36.858,-1.0,-1.0,-1.0,-1.0,28.453,0.765001,1356,1723505 +4,50,search,5489.19,1556.37,0.707924,0.907,0.111429,-1.0,-1.0,31.424,0.765,1359,1723505 +4,51,insert,330.217,-1.0,-1.0,-1.0,-1.0,283.815,0.905145,1417,2035040 +4,52,search,5719.34,1704.72,0.852746,0.90888,0.112071,-1.0,-1.0,39.682,0.905144,1422,2035040 +4,53,insert,41.901,-1.0,-1.0,-1.0,-1.0,17.864,0.921853,1423,2078341 +4,54,search,5861.86,1723.97,0.774239,0.90922,0.11148,-1.0,-1.0,11.964,0.921853,1423,2078341 +4,55,insert,352.446,-1.0,-1.0,-1.0,-1.0,431.969,1.06922,1489,2399905 +4,56,search,6301.59,1874.54,0.740148,0.91068,0.11224,-1.0,-1.0,101.913,1.06982,1505,2399905 +4,57,insert,23.727,-1.0,-1.0,-1.0,-1.0,21.8,1.07862,1508,2419836 +4,58,search,6559.39,1843.56,0.701931,0.90999,0.113061,-1.0,-1.0,40.52,1.07863,1511,2419836 +4,59,insert,248.512,-1.0,-1.0,-1.0,-1.0,182.297,1.17688,1531,2643083 +4,60,search,6699.78,1901.36,0.70948,0.90319,0.120837,-1.0,-1.0,67.913,1.17725,1539,2643083 +4,61,insert,10.687,-1.0,-1.0,-1.0,-1.0,14.857,1.18091,1540,2653064 +4,62,search,6700.39,1897.07,0.745074,0.90331,0.12042,-1.0,-1.0,26.509,1.18092,1543,2653064 +4,63,insert,3.528,-1.0,-1.0,-1.0,-1.0,11.123,1.18201,1543,2656118 +4,64,search,6685.34,1888.97,0.746461,0.90299,0.120674,-1.0,-1.0,11.788,1.18201,1543,2656118 +4,65,insert,74.34,-1.0,-1.0,-1.0,-1.0,131.029,1.20991,1572,2723424 +4,66,search,6888.25,1895.61,0.683151,0.90394,0.119328,-1.0,-1.0,22.013,1.21014,1573,2723424 +4,67,insert,46.322,-1.0,-1.0,-1.0,-1.0,78.547,1.23016,1587,2769021 +4,68,search,6995.43,1909.97,0.685908,0.90523,0.118301,-1.0,-1.0,27.766,1.23016,1590,2769021 +4,69,insert,67.441,-1.0,-1.0,-1.0,-1.0,69.323,1.25091,1599,2821777 +4,70,search,7002.65,1927.43,0.651686,0.90672,0.116866,-1.0,-1.0,29.874,1.25091,1601,2821777 +4,71,insert,23.412,-1.0,-1.0,-1.0,-1.0,29.66,1.257,1605,2834921 +4,72,search,6870.86,1928.3,0.732529,0.90711,0.116825,-1.0,-1.0,22.036,1.257,1606,2834921 +4,73,insert,7.286,-1.0,-1.0,-1.0,-1.0,11.805,1.25884,1606,2842044 +4,74,search,6762.91,1932.73,0.784468,0.90711,0.116885,-1.0,-1.0,13.017,1.25884,1606,2842044 +4,75,insert,26.468,-1.0,-1.0,-1.0,-1.0,36.577,1.26508,1610,2858890 +4,76,search,6968.68,1938.27,0.769314,0.90753,0.116645,-1.0,-1.0,17.094,1.26528,1611,2858890 +4,77,insert,33.335,-1.0,-1.0,-1.0,-1.0,11.373,1.27555,1611,2882818 +4,78,search,7140.85,1948.65,0.685717,0.90725,0.116846,-1.0,-1.0,12.119,1.27555,1611,2882818 +4,79,insert,473.154,-1.0,-1.0,-1.0,-1.0,21.667,1.30353,1614,2947806 +4,80,search,7226.32,1976.62,0.70684,0.90699,0.116916,-1.0,-1.0,17.937,1.30359,1615,2947806 +4,81,insert,29.663,-1.0,-1.0,-1.0,-1.0,45.95,1.3149,1621,2976895 +4,82,search,6810.25,1982.52,0.782588,0.90821,0.116149,-1.0,-1.0,12.236,1.3149,1621,2976895 +4,83,insert,17.009,-1.0,-1.0,-1.0,-1.0,18.907,1.32219,1622,2990682 +4,84,search,6926.49,1991.13,0.723782,0.90831,0.115947,-1.0,-1.0,12.076,1.32219,1622,2990682 +4,85,insert,36.181,-1.0,-1.0,-1.0,-1.0,41.221,1.33756,1627,3025613 +4,86,search,7097.74,2005.05,0.729937,0.90951,0.115039,-1.0,-1.0,14.288,1.33756,1627,3025613 +4,87,insert,577.638,-1.0,-1.0,-1.0,-1.0,661.733,1.54487,1740,3468632 +4,88,search,7767.6,2121.4,0.729338,0.91298,0.111325,-1.0,-1.0,101.632,1.54554,1752,3468632 +4,89,insert,411.545,-1.0,-1.0,-1.0,-1.0,467.189,1.70655,1839,3831692 +4,90,search,8261.35,2195.93,0.719684,0.917,0.106903,-1.0,-1.0,85.11,1.70673,1849,3831692 +4,91,insert,29.693,-1.0,-1.0,-1.0,-1.0,79.226,1.71688,1861,3864067 +4,92,search,8359.11,2182.33,0.730181,0.9171,0.106494,-1.0,-1.0,28.629,1.71693,1862,3864067 +4,93,insert,284.488,-1.0,-1.0,-1.0,-1.0,219.341,1.82177,1892,4103827 +4,94,search,8287.5,2256.56,0.873714,0.91791,0.106212,-1.0,-1.0,83.117,1.82215,1901,4103827 +4,95,insert,16.547,-1.0,-1.0,-1.0,-1.0,34.717,1.82807,1904,4119898 +4,96,search,7791.13,2248.21,0.968586,0.91818,0.105858,-1.0,-1.0,29.828,1.82823,1905,4119898 +4,97,insert,10.473,-1.0,-1.0,-1.0,-1.0,37.435,1.83185,1908,4129367 +4,98,search,9015.74,2245.99,0.655722,0.9181,0.105883,-1.0,-1.0,27.074,1.83185,1908,4129367 +4,99,insert,10.006,-1.0,-1.0,-1.0,-1.0,32.305,1.83379,1909,4134502 +4,100,search,8988.86,2247.48,0.714673,0.91818,0.105801,-1.0,-1.0,28.105,1.83379,1909,4134502 +4,101,insert,51.863,-1.0,-1.0,-1.0,-1.0,57.339,1.84591,1913,4164482 +4,102,search,8850.84,2258.9,0.742483,0.91828,0.106099,-1.0,-1.0,27.98,1.84591,1913,4164482 +4,103,insert,20.444,-1.0,-1.0,-1.0,-1.0,46.398,1.85193,1916,4178601 +4,104,search,8920.03,2264.44,0.73229,0.91851,0.106034,-1.0,-1.0,34.209,1.85205,1917,4178601 +4,105,insert,12.976,-1.0,-1.0,-1.0,-1.0,33.917,1.85626,1918,4187774 +4,106,search,8853.27,2266.53,0.672879,0.91855,0.105945,-1.0,-1.0,26.994,1.85626,1918,4187774 +4,107,insert,19.602,-1.0,-1.0,-1.0,-1.0,25.712,1.86002,1918,4200109 +4,108,search,9084.87,2270.15,0.666449,0.91843,0.10604,-1.0,-1.0,27.101,1.86002,1918,4200109 +4,109,insert,468.415,-1.0,-1.0,-1.0,-1.0,636.48,2.02206,2014,4557867 +4,110,search,9628.79,2327.85,0.697749,0.92049,0.10383,-1.0,-1.0,92.488,2.02302,2026,4557867 +4,111,insert,29.913,-1.0,-1.0,-1.0,-1.0,72.646,2.03557,2035,4587252 +4,112,search,9742.57,2310.57,0.690824,0.92065,0.103806,-1.0,-1.0,48.949,2.03598,2036,4587252 +4,113,insert,14.657,-1.0,-1.0,-1.0,-1.0,57.675,2.04124,2040,4600056 +4,114,search,9540.73,2310.61,0.733133,0.92096,0.103656,-1.0,-1.0,39.694,2.04133,2041,4600056 +4,115,insert,35.234,-1.0,-1.0,-1.0,-1.0,61.425,2.04849,2046,4627422 +4,116,search,9788.63,2315.14,0.650192,0.92128,0.103612,-1.0,-1.0,34.838,2.04849,2046,4627422 +4,117,insert,17.306,-1.0,-1.0,-1.0,-1.0,36.272,2.05248,2047,4639292 +4,118,search,8741.98,2318.28,0.877847,0.92155,0.103384,-1.0,-1.0,33.183,2.05248,2047,4639292 +4,119,insert,5.926,-1.0,-1.0,-1.0,-1.0,46.34,2.05441,2049,4643423 +4,120,search,9853.57,2316.8,0.670908,0.92149,0.103387,-1.0,-1.0,33.062,2.05441,2049,4643423 +4,121,insert,23.242,-1.0,-1.0,-1.0,-1.0,40.227,2.05936,2050,4657252 +4,122,search,9828.76,2321.93,0.657878,0.92151,0.103251,-1.0,-1.0,33.081,2.05936,2050,4657252 +4,123,insert,366.663,-1.0,-1.0,-1.0,-1.0,436.498,2.18515,2092,4938477 +4,124,search,10015.9,2387.89,0.701238,0.92241,0.103768,-1.0,-1.0,223.511,2.18602,2110,4938477 +4,125,insert,60.021,-1.0,-1.0,-1.0,-1.0,87.829,2.2052,2119,4980492 +4,126,search,10274.8,2373.28,0.687235,0.92244,0.103677,-1.0,-1.0,129.009,2.20565,2127,4980492 +4,127,insert,65.731,-1.0,-1.0,-1.0,-1.0,134.898,2.2263,2149,5030515 +4,128,search,10429.2,2358.04,0.682777,0.92328,0.103084,-1.0,-1.0,77.967,2.22646,2154,5030515 +4,129,delete,18.805,-1.0,-1.0,-1.0,-1.0,58.088,2.22483,2126,5009391 +4,130,search,9838.25,2349.94,0.777618,0.92231,0.103546,-1.0,-1.0,36.301,2.22483,2126,5009391 +4,131,delete,6.265,-1.0,-1.0,-1.0,-1.0,40.916,2.22483,2126,5004093 +4,132,search,9770.16,2348.02,0.752127,0.92222,0.103691,-1.0,-1.0,37.315,2.22483,2126,5004093 +4,133,delete,15.734,-1.0,-1.0,-1.0,-1.0,35.202,2.2248,2126,4991787 +4,134,search,10013,2336.42,0.712997,0.92204,0.103845,-1.0,-1.0,35.808,2.2248,2126,4991787 +4,135,delete,22.078,-1.0,-1.0,-1.0,-1.0,80.696,2.22171,2122,4974857 +4,136,search,10018.2,2333.46,0.684522,0.92231,0.103575,-1.0,-1.0,36.159,2.22171,2122,4974857 +4,137,delete,6.066,-1.0,-1.0,-1.0,-1.0,35.121,2.22171,2122,4971386 +4,138,search,9706.09,2331.39,0.761608,0.92225,0.103658,-1.0,-1.0,35.748,2.22171,2122,4971386 +4,139,delete,8.958,-1.0,-1.0,-1.0,-1.0,35.77,2.22171,2122,4963487 +4,140,search,9921.51,2326.33,0.741001,0.92224,0.103564,-1.0,-1.0,37.479,2.22171,2122,4963487 +4,141,delete,36.536,-1.0,-1.0,-1.0,-1.0,111.073,2.21759,2115,4941830 +4,142,search,9625.52,2321.07,0.78902,0.92212,0.103729,-1.0,-1.0,38.118,2.21759,2115,4941830 +4,143,delete,26.653,-1.0,-1.0,-1.0,-1.0,106.51,2.2123,2111,4925657 +4,144,search,10129.5,2317.06,0.687404,0.92216,0.103679,-1.0,-1.0,38.092,2.2123,2111,4925657 +4,145,delete,5.385,-1.0,-1.0,-1.0,-1.0,45.165,2.21141,2109,4922686 +4,146,search,10075.1,2317.57,0.66731,0.92202,0.103733,-1.0,-1.0,36.875,2.21141,2109,4922686 +4,147,delete,12.72,-1.0,-1.0,-1.0,-1.0,35.394,2.21141,2109,4913636 +4,148,search,10100.2,2311.94,0.680439,0.92196,0.103714,-1.0,-1.0,36.754,2.21141,2109,4913636 +4,149,delete,227.333,-1.0,-1.0,-1.0,-1.0,1262.45,2.12783,2007,4717250 +4,150,search,9254.72,2333.41,0.774102,0.92147,0.10475,-1.0,-1.0,86.86,2.1292,2014,4717250 +4,151,delete,166.137,-1.0,-1.0,-1.0,-1.0,1087.57,2.05883,1920,4560269 +8,2,search,3176.13,37.5515,0.685469,0.8551,0.130106,-1.0,-1.0,7.519,0.0184881,1000,38806 +8,3,insert,14.061,-1.0,-1.0,-1.0,-1.0,15.915,0.022655,996,49334 +8,4,search,2689.35,63.4255,1.05853,0.86686,0.128427,-1.0,-1.0,14.033,0.0226615,993,49334 +8,5,insert,29.243,-1.0,-1.0,-1.0,-1.0,167.398,0.032935,982,73557 +8,6,search,2602.73,175.313,1.44387,0.92586,0.10314,-1.0,-1.0,144.996,0.0329729,983,73557 +8,7,insert,33.212,-1.0,-1.0,-1.0,-1.0,149.245,0.0426748,985,95766 +8,8,search,2602.98,220.999,1.27385,0.92475,0.103899,-1.0,-1.0,91.19,0.0429489,989,95766 +8,9,insert,5.46,-1.0,-1.0,-1.0,-1.0,74.862,0.0447658,989,100025 +8,10,search,2603,227.069,1.22283,0.92685,0.101224,-1.0,-1.0,86.632,0.0448143,993,100025 +8,11,insert,14.031,-1.0,-1.0,-1.0,-1.0,84.775,0.0499416,996,111417 +8,12,search,2618.52,260.537,1.16238,0.92563,0.102114,-1.0,-1.0,19.706,0.0499841,997,111417 +8,13,insert,29.638,-1.0,-1.0,-1.0,-1.0,11.314,0.0612257,999,137139 +8,14,search,2671.04,294.111,0.993493,0.92128,0.10523,-1.0,-1.0,28.055,0.0613236,1002,137139 +8,15,insert,32.741,-1.0,-1.0,-1.0,-1.0,15.749,0.0700361,1005,156710 +8,16,search,2697.61,322.814,0.995554,0.91926,0.105592,-1.0,-1.0,20.677,0.0700409,1009,156710 +8,17,insert,6.873,-1.0,-1.0,-1.0,-1.0,11.988,0.0720871,1011,161773 +8,18,search,2718.78,331.447,0.949806,0.91922,0.106363,-1.0,-1.0,21.651,0.0722678,1016,161773 +8,19,insert,43.185,-1.0,-1.0,-1.0,-1.0,17.725,0.0792022,1020,177161 +8,20,search,2779.57,358.088,0.966152,0.92312,0.102872,-1.0,-1.0,14.555,0.0792022,1022,177161 +8,21,insert,385.316,-1.0,-1.0,-1.0,-1.0,228.807,0.202194,1094,448898 +8,22,search,3056.74,691.199,0.815705,0.90671,0.108756,-1.0,-1.0,81.923,0.20226,1112,448898 +8,23,insert,429.022,-1.0,-1.0,-1.0,-1.0,269.899,0.328827,1180,733493 +8,24,search,3343.87,945.68,0.731784,0.90352,0.111145,-1.0,-1.0,119.369,0.32956,1210,733493 +8,25,insert,48.946,-1.0,-1.0,-1.0,-1.0,34.083,0.347375,1218,777443 +8,26,search,3481.64,909.867,0.771286,0.90169,0.112692,-1.0,-1.0,29.199,0.347516,1225,777443 +8,27,insert,35.257,-1.0,-1.0,-1.0,-1.0,28.761,0.359307,1230,805394 +8,28,search,3471.19,918.894,0.767757,0.90131,0.113193,-1.0,-1.0,16.102,0.359438,1232,805394 +8,29,insert,73.173,-1.0,-1.0,-1.0,-1.0,70.278,0.386063,1248,866391 +8,30,search,3599.43,959.047,0.828177,0.90373,0.112592,-1.0,-1.0,33.904,0.386066,1253,866391 +8,31,insert,485.523,-1.0,-1.0,-1.0,-1.0,311.352,0.554971,1336,1239816 +8,32,search,3936.92,1190.76,0.763297,0.89809,0.117141,-1.0,-1.0,52.913,0.555102,1345,1239816 +8,33,insert,52.131,-1.0,-1.0,-1.0,-1.0,48.984,0.574791,1356,1291211 +8,34,search,3982.56,1197.43,0.684143,0.89932,0.116194,-1.0,-1.0,17.949,0.574833,1358,1291211 +8,35,insert,36.475,-1.0,-1.0,-1.0,-1.0,28.721,0.586575,1365,1324978 +8,36,search,3986.52,1221.58,0.686129,0.90058,0.115202,-1.0,-1.0,10.591,0.586575,1365,1324978 +8,37,insert,58.661,-1.0,-1.0,-1.0,-1.0,43.29,0.607156,1371,1371885 +8,38,search,4067.71,1248.28,0.685673,0.89998,0.115727,-1.0,-1.0,23.157,0.607161,1374,1371885 +8,39,insert,10.475,-1.0,-1.0,-1.0,-1.0,12.095,0.610528,1375,1379335 +8,40,search,4065.6,1245.38,0.68669,0.89994,0.116434,-1.0,-1.0,15.046,0.610528,1376,1379335 +8,41,insert,40.328,-1.0,-1.0,-1.0,-1.0,32.987,0.62445,1382,1413312 +8,42,search,4077.28,1264.69,0.702071,0.90119,0.115424,-1.0,-1.0,18.169,0.624455,1384,1413312 +8,43,insert,12.139,-1.0,-1.0,-1.0,-1.0,18.337,0.628464,1387,1423411 +8,44,search,4109.98,1266.03,0.701159,0.90151,0.115193,-1.0,-1.0,10.705,0.628464,1387,1423411 +8,45,insert,236.562,-1.0,-1.0,-1.0,-1.0,33.403,0.642904,1396,1457559 +8,46,search,4121.1,1268.71,0.682604,0.90136,0.115086,-1.0,-1.0,11.027,0.642904,1396,1457559 +8,47,insert,292.157,-1.0,-1.0,-1.0,-1.0,241.667,0.747845,1434,1688593 +8,48,search,4306.7,1397.23,0.678486,0.90367,0.114957,-1.0,-1.0,89.633,0.748038,1443,1688593 +8,49,insert,38.484,-1.0,-1.0,-1.0,-1.0,27.452,0.761785,1449,1723505 +8,50,search,4343.53,1398.53,0.682565,0.90418,0.114696,-1.0,-1.0,34.902,0.761785,1452,1723505 +8,51,insert,406.498,-1.0,-1.0,-1.0,-1.0,281.605,0.905733,1516,2035040 +8,52,search,4448.59,1533.08,0.734685,0.90781,0.112832,-1.0,-1.0,52.812,0.906125,1522,2035040 +8,53,insert,51.825,-1.0,-1.0,-1.0,-1.0,22.037,0.923049,1525,2078341 +8,54,search,4669.03,1548.07,0.645888,0.90762,0.113182,-1.0,-1.0,12.546,0.923049,1525,2078341 +8,55,insert,375.867,-1.0,-1.0,-1.0,-1.0,394.89,1.07034,1595,2399905 +8,56,search,4783.98,1694.62,0.710547,0.90918,0.113835,-1.0,-1.0,170.218,1.07162,1628,2399905 +8,57,insert,23.926,-1.0,-1.0,-1.0,-1.0,20.019,1.07807,1629,2419836 +8,58,search,5051.66,1640.23,0.653922,0.90808,0.114567,-1.0,-1.0,64.517,1.07811,1637,2419836 +8,59,insert,158.018,-1.0,-1.0,-1.0,-1.0,90.116,1.17634,1659,2643083 +8,60,search,4351.15,1682.8,0.808787,0.90131,0.121765,-1.0,-1.0,35.709,1.17634,1662,2643083 +8,61,insert,13.848,-1.0,-1.0,-1.0,-1.0,17.253,1.1806,1664,2653064 +8,62,search,5041.17,1683.09,0.73793,0.90154,0.121725,-1.0,-1.0,13.262,1.1806,1664,2653064 +8,63,insert,4.825,-1.0,-1.0,-1.0,-1.0,12.61,1.18193,1664,2656118 +8,64,search,5110.88,1683.41,0.727436,0.90152,0.121617,-1.0,-1.0,17.684,1.18196,1665,2656118 +8,65,insert,83.676,-1.0,-1.0,-1.0,-1.0,107.23,1.20876,1690,2723424 +8,66,search,5373.68,1700.4,0.705238,0.90262,0.120814,-1.0,-1.0,11.716,1.20876,1690,2723424 +8,67,insert,26.402,-1.0,-1.0,-1.0,-1.0,34.132,1.22762,1700,2769021 +8,68,search,4886.46,1726.67,0.851401,0.90453,0.119315,-1.0,-1.0,35.85,1.22772,1705,2769021 +8,69,insert,51.785,-1.0,-1.0,-1.0,-1.0,46.064,1.25083,1715,2821777 +8,70,search,5127.14,1740.81,0.723305,0.90625,0.117871,-1.0,-1.0,23.995,1.25083,1716,2821777 +8,71,insert,17.388,-1.0,-1.0,-1.0,-1.0,15.564,1.25673,1716,2834921 +8,72,search,5109.72,1752.4,0.6421,0.90696,0.117325,-1.0,-1.0,10.691,1.25673,1716,2834921 +8,73,insert,4.319,-1.0,-1.0,-1.0,-1.0,10.353,1.2596,1716,2842044 +8,74,search,5033.51,1756.55,0.794706,0.90711,0.117346,-1.0,-1.0,16.356,1.2596,1716,2842044 +8,75,insert,20.184,-1.0,-1.0,-1.0,-1.0,27.704,1.26635,1719,2858890 +8,76,search,4303.88,1764.55,0.774132,0.90728,0.117017,-1.0,-1.0,10.955,1.26635,1719,2858890 +8,77,insert,18.86,-1.0,-1.0,-1.0,-1.0,13.697,1.27844,1720,2882818 +8,78,search,5233.81,1774.78,0.698777,0.90726,0.117219,-1.0,-1.0,11.338,1.27844,1720,2882818 +8,79,insert,302.014,-1.0,-1.0,-1.0,-1.0,33.94,1.30644,1727,2947806 +8,80,search,5285.79,1795.69,0.653776,0.9067,0.117696,-1.0,-1.0,11.464,1.30644,1727,2947806 +8,81,insert,22.483,-1.0,-1.0,-1.0,-1.0,32.321,1.31943,1734,2976895 +8,82,search,4963.58,1802.23,0.777655,0.90783,0.117099,-1.0,-1.0,15.303,1.31943,1734,2976895 +8,83,insert,10.363,-1.0,-1.0,-1.0,-1.0,35.623,1.32481,1740,2990682 +8,84,search,4899.55,1800.34,0.69544,0.90828,0.116521,-1.0,-1.0,12.173,1.32481,1740,2990682 +8,85,insert,22.006,-1.0,-1.0,-1.0,-1.0,39.106,1.33931,1749,3025613 +8,86,search,4241.48,1806.75,0.876135,0.90876,0.116276,-1.0,-1.0,16.928,1.33947,1750,3025613 +8,87,insert,289.598,-1.0,-1.0,-1.0,-1.0,367.117,1.54024,1849,3468632 +8,88,search,5512.9,1951.34,0.805257,0.91199,0.113166,-1.0,-1.0,112.214,1.54077,1863,3468632 +8,89,insert,416.423,-1.0,-1.0,-1.0,-1.0,314.865,1.69997,1957,3831692 +8,90,search,6012.27,2023.44,0.653866,0.91651,0.108674,-1.0,-1.0,106.121,1.70023,1970,3831692 +8,91,insert,37.445,-1.0,-1.0,-1.0,-1.0,61.029,1.71205,1978,3864067 +8,92,search,5959.5,2014.52,0.817775,0.91645,0.108514,-1.0,-1.0,28.546,1.71213,1979,3864067 +8,93,insert,278.89,-1.0,-1.0,-1.0,-1.0,290.921,1.81872,2020,4103827 +8,94,search,6054.24,2075.54,0.708834,0.9175,0.10711,-1.0,-1.0,56.813,1.81956,2033,4103827 +8,95,insert,9.402,-1.0,-1.0,-1.0,-1.0,47.104,1.82588,2039,4119898 +8,96,search,6627.87,2059.2,0.68994,0.91742,0.1071,-1.0,-1.0,32.618,1.82588,2039,4119898 +8,97,insert,8.503,-1.0,-1.0,-1.0,-1.0,30.094,1.83006,2041,4129367 +8,98,search,6222.6,2062.4,0.714383,0.91766,0.106837,-1.0,-1.0,32.944,1.83006,2041,4129367 +8,99,insert,7.136,-1.0,-1.0,-1.0,-1.0,35.909,1.8322,2042,4134502 +8,100,search,6221.55,2063.59,0.759507,0.91764,0.106875,-1.0,-1.0,30.65,1.8322,2042,4134502 +8,101,insert,21.42,-1.0,-1.0,-1.0,-1.0,45.521,1.84339,2046,4164482 +8,102,search,6565.39,2072.3,0.647449,0.91775,0.106861,-1.0,-1.0,24.993,1.84339,2046,4164482 +8,103,insert,9.864,-1.0,-1.0,-1.0,-1.0,53.827,1.84903,2055,4178601 +8,104,search,6093.72,2068.72,0.735142,0.91805,0.106529,-1.0,-1.0,46.444,1.8493,2057,4178601 +8,105,insert,13.583,-1.0,-1.0,-1.0,-1.0,40.515,1.8543,2058,4187774 +8,106,search,6585.51,2068.95,0.690668,0.9179,0.106911,-1.0,-1.0,30.959,1.8543,2058,4187774 +8,107,insert,15.151,-1.0,-1.0,-1.0,-1.0,31.821,1.85872,2058,4200109 +8,108,search,6404.43,2071.97,0.604212,0.91794,0.106955,-1.0,-1.0,35.873,1.85872,2058,4200109 +8,109,insert,320.646,-1.0,-1.0,-1.0,-1.0,602.967,2.02124,2150,4557867 +8,110,search,7153.59,2140.69,0.693012,0.92017,0.105304,-1.0,-1.0,104.239,2.02202,2163,4557867 +8,111,insert,32.898,-1.0,-1.0,-1.0,-1.0,53.763,2.0339,2171,4587252 +8,112,search,7158.54,2127.7,0.657832,0.92017,0.105428,-1.0,-1.0,34.968,2.03393,2172,4587252 +8,113,insert,11.741,-1.0,-1.0,-1.0,-1.0,46.723,2.03913,2175,4600056 +8,114,search,6383.12,2128.96,0.71362,0.92038,0.105364,-1.0,-1.0,30.166,2.03913,2175,4600056 +8,115,insert,17.14,-1.0,-1.0,-1.0,-1.0,42.07,2.04729,2181,4627422 +8,116,search,7327.13,2133.52,0.647492,0.92103,0.104697,-1.0,-1.0,38.295,2.04729,2181,4627422 +8,117,insert,11.883,-1.0,-1.0,-1.0,-1.0,46.386,2.04997,2182,4639292 +8,118,search,6738.96,2137.51,0.659331,0.92111,0.104185,-1.0,-1.0,40.459,2.05014,2183,4639292 +8,119,insert,4.012,-1.0,-1.0,-1.0,-1.0,35.517,2.05197,2183,4643423 +8,120,search,7528.54,2137.22,0.661673,0.92109,0.104264,-1.0,-1.0,38.142,2.05197,2183,4643423 +8,121,insert,17.641,-1.0,-1.0,-1.0,-1.0,50.454,2.05669,2185,4657252 +8,122,search,7099.18,2143.5,0.672221,0.92114,0.104374,-1.0,-1.0,35.404,2.05669,2185,4657252 +8,123,insert,286.358,-1.0,-1.0,-1.0,-1.0,320.932,2.18474,2248,4938477 +8,124,search,7608.35,2181.7,0.693711,0.92161,0.105792,-1.0,-1.0,119.299,2.18546,2258,4938477 +8,125,insert,61.145,-1.0,-1.0,-1.0,-1.0,88.448,2.20134,2267,4980492 +8,126,search,7301.51,2175.8,0.679197,0.92208,0.105404,-1.0,-1.0,29.687,2.20139,2268,4980492 +8,127,insert,41.357,-1.0,-1.0,-1.0,-1.0,105.157,2.22438,2285,5030515 +8,128,search,7995.05,2178.81,0.637915,0.92257,0.105088,-1.0,-1.0,38.616,2.22438,2285,5030515 +8,129,delete,25.744,-1.0,-1.0,-1.0,-1.0,69.265,2.22253,2253,5009391 +8,130,search,7814.56,2180.7,0.633245,0.92157,0.105796,-1.0,-1.0,38.277,2.22253,2253,5009391 +8,131,delete,7.197,-1.0,-1.0,-1.0,-1.0,37.148,2.22253,2253,5004093 +8,132,search,7768.08,2177.63,0.65513,0.9215,0.105847,-1.0,-1.0,38.684,2.22253,2253,5004093 +8,133,delete,15.394,-1.0,-1.0,-1.0,-1.0,53.829,2.22124,2251,4991787 +8,134,search,6701.67,2171.67,0.804316,0.92154,0.105829,-1.0,-1.0,34.674,2.22124,2251,4991787 +8,135,delete,12.995,-1.0,-1.0,-1.0,-1.0,74.343,2.21864,2248,4974857 +8,136,search,7085.72,2165.1,0.859149,0.92153,0.105502,-1.0,-1.0,26.391,2.21864,2248,4974857 +8,137,delete,3.77,-1.0,-1.0,-1.0,-1.0,25.479,2.21864,2248,4971386 +8,138,search,7208.63,2163.21,0.785935,0.92144,0.105715,-1.0,-1.0,38.403,2.21864,2248,4971386 +8,139,delete,9.67,-1.0,-1.0,-1.0,-1.0,37.649,2.21864,2248,4963487 +8,140,search,7705.17,2158.85,0.683466,0.92137,0.105704,-1.0,-1.0,37.723,2.21864,2248,4963487 +8,141,delete,23.182,-1.0,-1.0,-1.0,-1.0,80.88,2.21502,2242,4941830 +8,142,search,7775.59,2152.13,0.669927,0.92127,0.105854,-1.0,-1.0,37.55,2.21502,2242,4941830 +8,143,delete,17.744,-1.0,-1.0,-1.0,-1.0,88.389,2.21103,2238,4925657 +8,144,search,7750.08,2148.97,0.653724,0.92122,0.106047,-1.0,-1.0,37.699,2.21103,2238,4925657 +8,145,delete,3.158,-1.0,-1.0,-1.0,-1.0,54.308,2.20993,2234,4922686 +8,146,search,7712.17,2150.62,0.660421,0.92127,0.106081,-1.0,-1.0,39,2.20993,2234,4922686 +8,147,delete,14.882,-1.0,-1.0,-1.0,-1.0,36.937,2.20993,2234,4913636 +8,148,search,7730.15,2145.36,0.66315,0.92106,0.106189,-1.0,-1.0,39.756,2.20993,2234,4913636 +8,149,delete,238.758,-1.0,-1.0,-1.0,-1.0,1269.57,2.13175,2130,4717250 +8,150,search,7429.46,2156.56,0.630906,0.92091,0.106747,-1.0,-1.0,100.956,2.13338,2138,4717250 +8,151,delete,161.725,-1.0,-1.0,-1.0,-1.0,1053.46,2.06482,2046,4560269 +16,2,search,2817.57,37.5515,1.01605,0.8551,0.130106,-1.0,-1.0,9.901,0.0184881,1000,38806 +16,3,insert,20.093,-1.0,-1.0,-1.0,-1.0,18.702,0.022655,996,49334 +16,4,search,2732.33,63.4255,1.05145,0.86686,0.128427,-1.0,-1.0,19.63,0.0226615,993,49334 +16,5,insert,42.354,-1.0,-1.0,-1.0,-1.0,208.22,0.033017,984,73557 +16,6,search,2709.92,173.596,1.14988,0.92515,0.103785,-1.0,-1.0,165.305,0.0330521,985,73557 +16,7,insert,84.96,-1.0,-1.0,-1.0,-1.0,159.301,0.0425699,987,95766 +16,8,search,2733.96,221.115,1.01108,0.92467,0.103645,-1.0,-1.0,118.73,0.0428123,991,95766 +16,9,insert,16.124,-1.0,-1.0,-1.0,-1.0,76.406,0.0446389,991,100025 +16,10,search,2633.24,226.599,0.941417,0.925,0.102401,-1.0,-1.0,98.236,0.0447131,996,100025 +16,11,insert,33.207,-1.0,-1.0,-1.0,-1.0,83.788,0.0498507,997,111417 +16,12,search,2746.25,260.601,0.888242,0.92407,0.103321,-1.0,-1.0,36.232,0.0498804,998,111417 +16,13,insert,69.913,-1.0,-1.0,-1.0,-1.0,14.412,0.0612045,1000,137139 +16,14,search,2794.07,295.052,0.772953,0.92074,0.105501,-1.0,-1.0,39.099,0.06132,1003,137139 +16,15,insert,67.323,-1.0,-1.0,-1.0,-1.0,21.626,0.0698961,1005,156710 +16,16,search,2786.13,322.174,0.747958,0.91771,0.106381,-1.0,-1.0,32.804,0.0698982,1009,156710 +16,17,insert,16.874,-1.0,-1.0,-1.0,-1.0,18.425,0.0718627,1011,161773 +16,18,search,2776.61,328.292,0.79122,0.91744,0.107279,-1.0,-1.0,24.74,0.0720365,1015,161773 +16,19,insert,63.682,-1.0,-1.0,-1.0,-1.0,14.765,0.0789864,1016,177161 +16,20,search,2861.3,361.6,0.81055,0.92123,0.103851,-1.0,-1.0,8.506,0.0789864,1016,177161 +16,21,insert,516.636,-1.0,-1.0,-1.0,-1.0,297.165,0.202475,1087,448898 +16,22,search,3036.86,703.72,0.583757,0.90764,0.109503,-1.0,-1.0,137.383,0.202472,1107,448898 +16,23,insert,737.783,-1.0,-1.0,-1.0,-1.0,352.994,0.329412,1173,733493 +16,24,search,3282.01,955.037,0.61648,0.90117,0.11289,-1.0,-1.0,150.251,0.330087,1200,733493 +16,25,insert,72.504,-1.0,-1.0,-1.0,-1.0,40.715,0.346546,1208,777443 +16,26,search,3367.46,919.947,0.617036,0.89993,0.114372,-1.0,-1.0,49.409,0.34667,1216,777443 +16,27,insert,62.555,-1.0,-1.0,-1.0,-1.0,19.055,0.358247,1217,805394 +16,28,search,3338.27,927.827,0.585935,0.89987,0.11462,-1.0,-1.0,15.156,0.358252,1218,805394 +16,29,insert,137.986,-1.0,-1.0,-1.0,-1.0,89.811,0.385584,1232,866391 +16,30,search,3388.86,971.62,0.664151,0.90176,0.114279,-1.0,-1.0,53.422,0.385866,1238,866391 +16,31,insert,794.46,-1.0,-1.0,-1.0,-1.0,428.749,0.554962,1313,1239816 +16,32,search,3672.23,1205.18,0.62597,0.89529,0.119038,-1.0,-1.0,156.606,0.555114,1325,1239816 +16,33,insert,134.751,-1.0,-1.0,-1.0,-1.0,40.655,0.574731,1332,1291211 +16,34,search,3754.63,1209.75,0.58402,0.89595,0.118634,-1.0,-1.0,96.799,0.574907,1339,1291211 +16,35,insert,66.629,-1.0,-1.0,-1.0,-1.0,45.457,0.586082,1348,1324978 +16,36,search,3736.79,1223.14,0.623036,0.89787,0.116258,-1.0,-1.0,52.92,0.586082,1352,1324978 +16,37,insert,92.917,-1.0,-1.0,-1.0,-1.0,35.545,0.606319,1355,1371885 +16,38,search,3778.56,1250.97,0.607034,0.89722,0.117355,-1.0,-1.0,25.115,0.606319,1357,1371885 +16,39,insert,18.239,-1.0,-1.0,-1.0,-1.0,15.538,0.610146,1359,1379335 +16,40,search,3809.96,1247.57,0.574779,0.89679,0.118082,-1.0,-1.0,11.53,0.610146,1359,1379335 +16,41,insert,71.735,-1.0,-1.0,-1.0,-1.0,40.759,0.624828,1364,1413312 +16,42,search,3785.31,1269.57,0.644573,0.89786,0.117603,-1.0,-1.0,11.067,0.624828,1364,1413312 +16,43,insert,18.626,-1.0,-1.0,-1.0,-1.0,16.044,0.628473,1366,1423411 +16,44,search,3844.81,1274.95,0.602784,0.89774,0.117697,-1.0,-1.0,18.054,0.628473,1366,1423411 +16,45,insert,341.749,-1.0,-1.0,-1.0,-1.0,46.519,0.644515,1374,1457559 +16,46,search,3974.18,1292.36,0.458881,0.89947,0.116045,-1.0,-1.0,11.558,0.644515,1374,1457559 +16,47,insert,506.119,-1.0,-1.0,-1.0,-1.0,308.225,0.748912,1415,1688593 +16,48,search,3937.23,1415.03,0.643038,0.9027,0.115195,-1.0,-1.0,110.563,0.749405,1425,1688593 +16,49,insert,62.741,-1.0,-1.0,-1.0,-1.0,31.081,0.763859,1428,1723505 +16,50,search,4010.81,1419.92,0.610572,0.90368,0.114848,-1.0,-1.0,46.65,0.76386,1431,1723505 +16,51,insert,503.026,-1.0,-1.0,-1.0,-1.0,266.592,0.904667,1483,2035040 +16,52,search,4255.14,1585.05,0.5986,0.90786,0.111588,-1.0,-1.0,58.248,0.904667,1489,2035040 +16,53,insert,79.282,-1.0,-1.0,-1.0,-1.0,56.206,0.921761,1495,2078341 +16,54,search,4413.42,1593.68,0.523337,0.9077,0.112333,-1.0,-1.0,22.732,0.921763,1496,2078341 +16,55,insert,726.496,-1.0,-1.0,-1.0,-1.0,520.786,1.06983,1569,2399905 +16,56,search,4685.83,1727.96,0.526217,0.91008,0.112374,-1.0,-1.0,184.365,1.07079,1593,2399905 +16,57,insert,43.863,-1.0,-1.0,-1.0,-1.0,35.983,1.07804,1597,2419836 +16,58,search,4695.34,1687.35,0.560566,0.90881,0.113087,-1.0,-1.0,61.224,1.07806,1602,2419836 +16,59,insert,317.248,-1.0,-1.0,-1.0,-1.0,239.614,1.17733,1620,2643083 +16,60,search,4634.47,1730.57,0.613968,0.90048,0.123551,-1.0,-1.0,74.559,1.17747,1625,2643083 +16,61,insert,14.966,-1.0,-1.0,-1.0,-1.0,23.928,1.18108,1628,2653064 +16,62,search,4654.67,1721.19,0.613519,0.90039,0.123363,-1.0,-1.0,46.007,1.18108,1629,2653064 +16,63,insert,6.906,-1.0,-1.0,-1.0,-1.0,13.393,1.18216,1629,2656118 +16,64,search,4793.88,1723.34,0.546362,0.90053,0.123248,-1.0,-1.0,14.845,1.18216,1629,2656118 +16,65,insert,155.212,-1.0,-1.0,-1.0,-1.0,138.071,1.21245,1655,2723424 +16,66,search,4569.15,1743.68,0.659975,0.90144,0.122511,-1.0,-1.0,21.439,1.21245,1656,2723424 +16,67,insert,74.376,-1.0,-1.0,-1.0,-1.0,73.182,1.23228,1667,2769021 +16,68,search,4814.98,1763.99,0.582264,0.90307,0.121137,-1.0,-1.0,23.424,1.23238,1669,2769021 +16,69,insert,83.006,-1.0,-1.0,-1.0,-1.0,77.04,1.2549,1680,2821777 +16,70,search,4823.18,1777.17,0.596263,0.90506,0.119497,-1.0,-1.0,32.98,1.2549,1682,2821777 +16,71,insert,18.471,-1.0,-1.0,-1.0,-1.0,28.471,1.25961,1685,2834921 +16,72,search,4834.46,1783.22,0.594418,0.90494,0.119449,-1.0,-1.0,15.635,1.25961,1685,2834921 +16,73,insert,12.026,-1.0,-1.0,-1.0,-1.0,20.782,1.26303,1686,2842044 +16,74,search,4834.28,1785.39,0.583287,0.905,0.119417,-1.0,-1.0,15.543,1.26303,1686,2842044 +16,75,insert,26.46,-1.0,-1.0,-1.0,-1.0,27.639,1.26892,1688,2858890 +16,76,search,4887.8,1792.61,0.591188,0.90584,0.118653,-1.0,-1.0,20.843,1.26908,1689,2858890 +16,77,insert,43.241,-1.0,-1.0,-1.0,-1.0,14.605,1.27934,1689,2882818 +16,78,search,4886.24,1803.27,0.609436,0.90539,0.119204,-1.0,-1.0,26.663,1.27934,1689,2882818 +16,79,insert,548.593,-1.0,-1.0,-1.0,-1.0,24.469,1.30775,1691,2947806 +16,80,search,4940.3,1833.42,0.556805,0.90537,0.119374,-1.0,-1.0,16.126,1.30775,1691,2947806 +16,81,insert,58.835,-1.0,-1.0,-1.0,-1.0,38.402,1.31962,1694,2976895 +16,82,search,4972.19,1845.27,0.548699,0.90738,0.117193,-1.0,-1.0,39.754,1.31985,1696,2976895 +16,83,insert,32.489,-1.0,-1.0,-1.0,-1.0,53.262,1.32589,1700,2990682 +16,84,search,5002.44,1842.46,0.553189,0.90769,0.116807,-1.0,-1.0,22.656,1.32593,1701,2990682 +16,85,insert,59.175,-1.0,-1.0,-1.0,-1.0,42.931,1.33998,1705,3025613 +16,86,search,4898.37,1855.52,0.60492,0.90778,0.116864,-1.0,-1.0,16.583,1.33998,1705,3025613 +16,87,insert,767.31,-1.0,-1.0,-1.0,-1.0,684.167,1.54372,1807,3468632 +16,88,search,5398.51,1996.52,0.576777,0.91163,0.112764,-1.0,-1.0,133.81,1.54408,1823,3468632 +16,89,insert,512.088,-1.0,-1.0,-1.0,-1.0,533.546,1.70224,1914,3831692 +16,90,search,5632.56,2058.69,0.576022,0.91581,0.108058,-1.0,-1.0,114.917,1.70308,1927,3831692 +16,91,insert,45.967,-1.0,-1.0,-1.0,-1.0,53.022,1.71469,1932,3864067 +16,92,search,5655.79,2053.73,0.592965,0.91599,0.108021,-1.0,-1.0,28.66,1.71469,1932,3864067 +16,93,insert,320.686,-1.0,-1.0,-1.0,-1.0,230.135,1.81799,1965,4103827 +16,94,search,5849.83,2117.22,0.577777,0.91615,0.108323,-1.0,-1.0,118.236,1.81868,1972,4103827 +16,95,insert,35.635,-1.0,-1.0,-1.0,-1.0,55.287,1.82467,1975,4119898 +16,96,search,5938.31,2115.66,0.581457,0.91673,0.107949,-1.0,-1.0,44.931,1.82495,1977,4119898 +16,97,insert,20.705,-1.0,-1.0,-1.0,-1.0,37.086,1.82902,1978,4129367 +16,98,search,5872.13,2114.62,0.6034,0.91663,0.10783,-1.0,-1.0,31.66,1.82902,1978,4129367 +16,99,insert,12.325,-1.0,-1.0,-1.0,-1.0,30.61,1.83103,1978,4134502 +16,100,search,5820.14,2116.75,0.625382,0.91668,0.107799,-1.0,-1.0,31.27,1.83103,1978,4134502 +16,101,insert,57.475,-1.0,-1.0,-1.0,-1.0,47.831,1.84334,1981,4164482 +16,102,search,5738.46,2129.3,0.62206,0.91707,0.107525,-1.0,-1.0,46.131,1.8436,1983,4164482 +16,103,insert,25.27,-1.0,-1.0,-1.0,-1.0,48.071,1.85038,1986,4178601 +16,104,search,5793.29,2132.74,0.600731,0.91713,0.107535,-1.0,-1.0,37.711,1.85056,1987,4178601 +16,105,insert,11.873,-1.0,-1.0,-1.0,-1.0,40.594,1.85378,1989,4187774 +16,106,search,5753.62,2131.1,0.569714,0.91732,0.107382,-1.0,-1.0,36.792,1.85381,1990,4187774 +16,107,insert,26.384,-1.0,-1.0,-1.0,-1.0,30.471,1.85976,1990,4200109 +16,108,search,5682.18,2135.19,0.623803,0.91701,0.107663,-1.0,-1.0,34.446,1.85976,1990,4200109 +16,109,insert,698.569,-1.0,-1.0,-1.0,-1.0,651.196,2.02263,2074,4557867 +16,110,search,6199.29,2207.29,0.574436,0.91943,0.10517,-1.0,-1.0,158.412,2.02343,2086,4557867 +16,111,insert,55.811,-1.0,-1.0,-1.0,-1.0,83.162,2.03652,2095,4587252 +16,112,search,6339.84,2194.57,0.550224,0.91987,0.10465,-1.0,-1.0,36.396,2.03652,2095,4587252 +16,113,insert,20.809,-1.0,-1.0,-1.0,-1.0,44.662,2.04163,2096,4600056 +16,114,search,6309.39,2199.62,0.575326,0.91998,0.104612,-1.0,-1.0,35.985,2.04163,2096,4600056 +16,115,insert,44.993,-1.0,-1.0,-1.0,-1.0,68.986,2.05195,2101,4627422 +16,116,search,6311.47,2207.42,0.571418,0.92046,0.104585,-1.0,-1.0,43.334,2.05201,2102,4627422 +16,117,insert,16.663,-1.0,-1.0,-1.0,-1.0,42.2,2.05581,2103,4639292 +16,118,search,6202.23,2212.04,0.559177,0.92044,0.104345,-1.0,-1.0,36.269,2.05581,2103,4639292 +16,119,insert,5.425,-1.0,-1.0,-1.0,-1.0,42.443,2.05725,2104,4643423 +16,120,search,6225.6,2213.47,0.586058,0.92051,0.104244,-1.0,-1.0,40.686,2.05725,2104,4643423 +16,121,insert,32.965,-1.0,-1.0,-1.0,-1.0,53.254,2.06358,2106,4657252 +16,122,search,6425.24,2217.93,0.5072,0.9205,0.104241,-1.0,-1.0,39.496,2.06358,2106,4657252 +16,123,insert,561.921,-1.0,-1.0,-1.0,-1.0,518.741,2.1905,2161,4938477 +16,124,search,6533.45,2265.37,0.551593,0.92145,0.104814,-1.0,-1.0,257.183,2.19091,2180,4938477 +16,125,insert,104.858,-1.0,-1.0,-1.0,-1.0,86.276,2.20755,2187,4980492 +16,126,search,6526.68,2250.4,0.542127,0.92186,0.104236,-1.0,-1.0,101.913,2.2078,2194,4980492 +16,127,insert,82.796,-1.0,-1.0,-1.0,-1.0,128.381,2.22715,2212,5030515 +16,128,search,6541.78,2244.59,0.576165,0.92202,0.104444,-1.0,-1.0,44.99,2.22733,2213,5030515 +16,129,delete,21.272,-1.0,-1.0,-1.0,-1.0,71.383,2.22527,2179,5009391 +16,130,search,6402.65,2244.97,0.573326,0.92079,0.105098,-1.0,-1.0,37.724,2.22527,2179,5009391 +16,131,delete,6.096,-1.0,-1.0,-1.0,-1.0,37.006,2.22527,2179,5004093 +16,132,search,6416.31,2244.82,0.578844,0.92087,0.105065,-1.0,-1.0,37.375,2.22527,2179,5004093 +16,133,delete,13.569,-1.0,-1.0,-1.0,-1.0,44.018,2.22464,2178,4991787 +16,134,search,6425.04,2236.06,0.550619,0.92082,0.105179,-1.0,-1.0,37.412,2.22464,2178,4991787 +16,135,delete,18.85,-1.0,-1.0,-1.0,-1.0,67.414,2.22224,2175,4974857 +16,136,search,6478.56,2229.62,0.596052,0.92079,0.105335,-1.0,-1.0,42.323,2.22224,2175,4974857 +16,137,delete,10.507,-1.0,-1.0,-1.0,-1.0,37.488,2.22224,2175,4971386 +16,138,search,6488.41,2227.44,0.549725,0.92081,0.105383,-1.0,-1.0,38.477,2.22224,2175,4971386 +16,139,delete,12.554,-1.0,-1.0,-1.0,-1.0,37.799,2.22224,2175,4963487 +16,140,search,6559.85,2222.19,0.558919,0.9207,0.105432,-1.0,-1.0,37.391,2.22224,2175,4963487 +16,141,delete,28.797,-1.0,-1.0,-1.0,-1.0,107.622,2.21712,2168,4941830 +16,142,search,6393.39,2216.68,0.612253,0.92065,0.105705,-1.0,-1.0,37.301,2.21712,2168,4941830 +16,143,delete,19.598,-1.0,-1.0,-1.0,-1.0,112.971,2.21238,2164,4925657 +16,144,search,6385.35,2214.98,0.550079,0.92038,0.105724,-1.0,-1.0,37.345,2.21238,2164,4925657 +16,145,delete,3.585,-1.0,-1.0,-1.0,-1.0,48.467,2.21133,2162,4922686 +16,146,search,6366.52,2215.54,0.598512,0.92003,0.105917,-1.0,-1.0,37.584,2.21133,2162,4922686 +16,147,delete,10.237,-1.0,-1.0,-1.0,-1.0,36.012,2.21133,2162,4913636 +16,148,search,6396.97,2210.63,0.613517,0.92003,0.105861,-1.0,-1.0,37.44,2.21133,2162,4913636 +16,149,delete,229.895,-1.0,-1.0,-1.0,-1.0,1408.22,2.1276,2050,4717250 +16,150,search,6129.75,2240.28,0.598705,0.91978,0.106231,-1.0,-1.0,70.144,2.12806,2055,4717250 +16,151,delete,179.278,-1.0,-1.0,-1.0,-1.0,1164.6,2.0563,1956,4560269 +32,2,search,3152.99,37.5515,1.09161,0.8551,0.130106,-1.0,-1.0,9.845,0.0184881,1000,38806 +32,3,insert,20.979,-1.0,-1.0,-1.0,-1.0,18.146,0.022655,996,49334 +32,4,search,2809.98,63.4255,0.677353,0.86686,0.128427,-1.0,-1.0,19.314,0.0226615,993,49334 +32,5,insert,37.142,-1.0,-1.0,-1.0,-1.0,173.187,0.032935,982,73557 +32,6,search,2751.87,175.313,0.777635,0.92586,0.10314,-1.0,-1.0,123.81,0.032935,982,73557 +32,7,insert,49.092,-1.0,-1.0,-1.0,-1.0,129.267,0.0426217,983,95766 +32,8,search,2761.65,222.921,0.667287,0.92535,0.103423,-1.0,-1.0,86.385,0.0426805,984,95766 +32,9,insert,8.69,-1.0,-1.0,-1.0,-1.0,77.525,0.0446446,984,100025 +32,10,search,2773.43,232.551,0.729023,0.92768,0.100456,-1.0,-1.0,25.301,0.0450518,985,100025 +32,11,insert,18.085,-1.0,-1.0,-1.0,-1.0,12.179,0.0496924,986,111417 +32,12,search,2791.95,268.048,0.665201,0.92761,0.101391,-1.0,-1.0,24.448,0.0498906,988,111417 +32,13,insert,41.374,-1.0,-1.0,-1.0,-1.0,12.136,0.0611151,989,137139 +32,14,search,2807.11,307.155,0.609106,0.9233,0.103527,-1.0,-1.0,10.343,0.0611151,989,137139 +32,15,insert,36.061,-1.0,-1.0,-1.0,-1.0,9.942,0.0697011,989,156710 +32,16,search,2841.7,343.221,0.560725,0.92311,0.103114,-1.0,-1.0,10.494,0.0697011,989,156710 +32,17,insert,9.865,-1.0,-1.0,-1.0,-1.0,9.443,0.0717366,989,161773 +32,18,search,2886.36,363.437,0.547855,0.92423,0.103307,-1.0,-1.0,10.559,0.0717366,989,161773 +32,19,insert,65.892,-1.0,-1.0,-1.0,-1.0,20.761,0.0787309,992,177161 +32,20,search,2889.06,396.114,0.56205,0.92696,0.100685,-1.0,-1.0,12.274,0.0787309,992,177161 +32,21,insert,613.371,-1.0,-1.0,-1.0,-1.0,156.316,0.198936,1009,448898 +32,22,search,2955.49,898.062,0.504195,0.92019,0.101747,-1.0,-1.0,61.885,0.199224,1013,448898 +32,23,insert,783.995,-1.0,-1.0,-1.0,-1.0,366.396,0.328246,1049,733493 +32,24,search,3063.41,1264.86,0.457447,0.91566,0.104648,-1.0,-1.0,68.485,0.328244,1056,733493 +32,25,insert,87.178,-1.0,-1.0,-1.0,-1.0,18.538,0.346121,1057,777443 +32,26,search,3066.36,1290.03,0.480837,0.91614,0.104417,-1.0,-1.0,17.395,0.346121,1057,777443 +32,27,insert,94.104,-1.0,-1.0,-1.0,-1.0,29.762,0.3581,1059,805394 +32,28,search,3068.55,1315.35,0.466007,0.91624,0.1045,-1.0,-1.0,10.929,0.3581,1059,805394 +32,29,insert,119.32,-1.0,-1.0,-1.0,-1.0,60.289,0.384547,1064,866391 +32,30,search,3082.21,1381.23,0.469378,0.91804,0.103832,-1.0,-1.0,32.417,0.384547,1066,866391 +32,31,insert,690.271,-1.0,-1.0,-1.0,-1.0,551.883,0.555044,1126,1239816 +32,32,search,3345.37,1680.42,0.478118,0.90916,0.109836,-1.0,-1.0,183.371,0.555051,1135,1239816 +32,33,insert,145.198,-1.0,-1.0,-1.0,-1.0,11.551,0.575612,1135,1291211 +32,34,search,3333.53,1687.35,0.433124,0.90883,0.110004,-1.0,-1.0,82.311,0.57563,1139,1291211 +32,35,insert,64.531,-1.0,-1.0,-1.0,-1.0,44.355,0.586911,1144,1324978 +32,36,search,3261.72,1714.62,0.471049,0.90924,0.109507,-1.0,-1.0,67.516,0.587002,1150,1324978 +32,37,insert,79.106,-1.0,-1.0,-1.0,-1.0,56.05,0.606628,1156,1371885 +32,38,search,3335.41,1731.06,0.451322,0.90906,0.109021,-1.0,-1.0,17.922,0.606627,1157,1371885 +32,39,insert,15.853,-1.0,-1.0,-1.0,-1.0,9.873,0.610073,1157,1379335 +32,40,search,3366.05,1736.66,0.535322,0.90916,0.109617,-1.0,-1.0,10.584,0.610073,1157,1379335 +32,41,insert,62.141,-1.0,-1.0,-1.0,-1.0,31.523,0.62424,1160,1413312 +32,42,search,3374.14,1764.83,0.504377,0.91017,0.109498,-1.0,-1.0,17.55,0.62424,1160,1413312 +32,43,insert,38.567,-1.0,-1.0,-1.0,-1.0,20.237,0.628433,1161,1423411 +32,44,search,3397.31,1773.5,0.439306,0.91018,0.109458,-1.0,-1.0,10.994,0.628433,1161,1423411 +32,45,insert,260.44,-1.0,-1.0,-1.0,-1.0,42.571,0.643658,1167,1457559 +32,46,search,3373.22,1785.09,0.463988,0.91056,0.108557,-1.0,-1.0,11.086,0.643658,1167,1457559 +32,47,insert,423.869,-1.0,-1.0,-1.0,-1.0,273.435,0.749948,1194,1688593 +32,48,search,3471.22,1937.53,0.447244,0.91201,0.10815,-1.0,-1.0,105.543,0.750168,1203,1688593 +32,49,insert,49.99,-1.0,-1.0,-1.0,-1.0,38.076,0.763668,1206,1723505 +32,50,search,3454.73,1934.4,0.527042,0.91174,0.108089,-1.0,-1.0,38.551,0.763668,1208,1723505 +32,51,insert,429.602,-1.0,-1.0,-1.0,-1.0,352.086,0.904785,1256,2035040 +32,52,search,3628.58,2095.1,0.483117,0.91372,0.107114,-1.0,-1.0,67.437,0.904813,1264,2035040 +32,53,insert,58.234,-1.0,-1.0,-1.0,-1.0,24.359,0.921852,1266,2078341 +32,54,search,3615.88,2107.39,0.533986,0.91343,0.10822,-1.0,-1.0,18.975,0.921959,1267,2078341 +32,55,insert,375.731,-1.0,-1.0,-1.0,-1.0,455.464,1.07141,1320,2399905 +32,56,search,3779.43,2280.94,0.495227,0.91403,0.108017,-1.0,-1.0,134.108,1.07164,1336,2399905 +32,57,insert,25.53,-1.0,-1.0,-1.0,-1.0,15.967,1.07834,1337,2419836 +32,58,search,3829.07,2236.79,0.55455,0.91346,0.10874,-1.0,-1.0,88.426,1.07835,1344,2419836 +32,59,insert,407.146,-1.0,-1.0,-1.0,-1.0,214.552,1.17965,1359,2643083 +32,60,search,3961.96,2306.28,0.41845,0.90639,0.11691,-1.0,-1.0,60.34,1.18002,1362,2643083 +32,61,insert,15.277,-1.0,-1.0,-1.0,-1.0,16.61,1.18332,1363,2653064 +32,62,search,3877.72,2308.89,0.487889,0.90677,0.116483,-1.0,-1.0,28.438,1.18332,1364,2653064 +32,63,insert,6.116,-1.0,-1.0,-1.0,-1.0,17.528,1.18481,1365,2656118 +32,64,search,3921.93,2306.46,0.506081,0.90661,0.116879,-1.0,-1.0,24.976,1.18481,1366,2656118 +32,65,insert,97.344,-1.0,-1.0,-1.0,-1.0,112.638,1.21099,1381,2723424 +32,66,search,4021.02,2335.2,0.482632,0.90789,0.116034,-1.0,-1.0,11.671,1.21099,1381,2723424 +32,67,insert,56.494,-1.0,-1.0,-1.0,-1.0,77.504,1.23026,1390,2769021 +32,68,search,3992.36,2361.96,0.528996,0.90906,0.115757,-1.0,-1.0,19.219,1.23026,1391,2769021 +32,69,insert,70.921,-1.0,-1.0,-1.0,-1.0,102.063,1.25386,1404,2821777 +32,70,search,3990.65,2375.91,0.517398,0.91096,0.113715,-1.0,-1.0,19.771,1.25386,1405,2821777 +32,71,insert,22.685,-1.0,-1.0,-1.0,-1.0,23.472,1.26051,1407,2834921 +32,72,search,4031.11,2385.71,0.547386,0.91158,0.113305,-1.0,-1.0,12.195,1.26051,1407,2834921 +32,73,insert,12.922,-1.0,-1.0,-1.0,-1.0,17.428,1.26464,1408,2842044 +32,74,search,4043.87,2386.59,0.519457,0.91154,0.113341,-1.0,-1.0,11.952,1.26464,1408,2842044 +32,75,insert,26.402,-1.0,-1.0,-1.0,-1.0,36.801,1.27259,1412,2858890 +32,76,search,3320.32,2390.01,0.488242,0.91143,0.113519,-1.0,-1.0,7.408,1.27259,1412,2858890 +32,77,insert,19.017,-1.0,-1.0,-1.0,-1.0,14.661,1.28196,1414,2882818 +32,78,search,2979.92,2401,0.631615,0.91117,0.113574,-1.0,-1.0,7.223,1.28196,1414,2882818 +32,79,insert,319.671,-1.0,-1.0,-1.0,-1.0,21.851,1.3102,1418,2947806 +32,80,search,2981.07,2428.15,0.600424,0.91101,0.114224,-1.0,-1.0,7.528,1.3102,1418,2947806 +32,81,insert,21.277,-1.0,-1.0,-1.0,-1.0,39.747,1.32343,1426,2976895 +32,82,search,3006.92,2431.06,0.642677,0.91189,0.11401,-1.0,-1.0,7.46,1.32343,1426,2976895 +32,83,insert,10.895,-1.0,-1.0,-1.0,-1.0,15.845,1.32988,1428,2990682 +32,84,search,3010.46,2438.48,0.60147,0.91265,0.113296,-1.0,-1.0,7.278,1.32988,1428,2990682 +32,85,insert,22.524,-1.0,-1.0,-1.0,-1.0,48.272,1.34419,1438,3025613 +32,86,search,3073.21,2438.24,0.554873,0.91303,0.113119,-1.0,-1.0,9.622,1.34419,1438,3025613 +32,87,insert,449.234,-1.0,-1.0,-1.0,-1.0,564.093,1.54861,1539,3468632 +32,88,search,3326.41,2555.12,0.578607,0.91498,0.110661,-1.0,-1.0,109.324,1.54901,1552,3468632 +32,89,insert,412.742,-1.0,-1.0,-1.0,-1.0,430.639,1.70968,1636,3831692 +32,90,search,3549.71,2612.39,0.521716,0.91902,0.105289,-1.0,-1.0,49.236,1.70996,1646,3831692 +32,91,insert,20.308,-1.0,-1.0,-1.0,-1.0,34.443,1.72081,1653,3864067 +32,92,search,3441.92,2601.47,0.653902,0.9191,0.105075,-1.0,-1.0,18.533,1.72109,1655,3864067 +32,93,insert,160.597,-1.0,-1.0,-1.0,-1.0,162.336,1.82303,1691,4103827 +32,94,search,3578.61,2669.61,0.631089,0.91971,0.103989,-1.0,-1.0,26.195,1.82325,1695,4103827 +32,95,insert,10.488,-1.0,-1.0,-1.0,-1.0,29.344,1.82952,1701,4119898 +32,96,search,3598.81,2662.1,0.623401,0.9204,0.103501,-1.0,-1.0,9.745,1.82952,1701,4119898 +32,97,insert,6.098,-1.0,-1.0,-1.0,-1.0,12.916,1.83247,1702,4129367 +32,98,search,3583.04,2667.15,0.582576,0.92056,0.103148,-1.0,-1.0,14.945,1.83254,1703,4129367 +32,99,insert,4.394,-1.0,-1.0,-1.0,-1.0,13.348,1.83469,1704,4134502 +32,100,search,3592.21,2667.44,0.600535,0.92049,0.103347,-1.0,-1.0,10.132,1.83469,1704,4134502 +32,101,insert,21.561,-1.0,-1.0,-1.0,-1.0,39.122,1.84626,1711,4164482 +32,102,search,3557.15,2673.6,0.609146,0.92077,0.103167,-1.0,-1.0,15.253,1.84628,1712,4164482 +32,103,insert,8.822,-1.0,-1.0,-1.0,-1.0,29.006,1.8516,1717,4178601 +32,104,search,3632.88,2676.3,0.611925,0.92106,0.103053,-1.0,-1.0,10.378,1.8516,1717,4178601 +32,105,insert,5.905,-1.0,-1.0,-1.0,-1.0,17.712,1.8554,1719,4187774 +32,106,search,3622.74,2679,0.634476,0.92095,0.10334,-1.0,-1.0,10.613,1.8554,1719,4187774 +32,107,insert,10.507,-1.0,-1.0,-1.0,-1.0,10.284,1.8605,1719,4200109 +32,108,search,3496.85,2680.74,0.631482,0.9208,0.103615,-1.0,-1.0,10.286,1.8605,1719,4200109 +32,109,insert,236.43,-1.0,-1.0,-1.0,-1.0,414.991,2.0182,1797,4557867 +32,110,search,3824.08,2751.86,0.624412,0.92327,0.101187,-1.0,-1.0,44.082,2.01856,1804,4557867 +32,111,insert,18.026,-1.0,-1.0,-1.0,-1.0,48.553,2.03147,1813,4587252 +32,112,search,3824.64,2751.52,0.596598,0.92369,0.100851,-1.0,-1.0,17.616,2.03154,1814,4587252 +32,113,insert,7.503,-1.0,-1.0,-1.0,-1.0,28.71,2.03675,1818,4600056 +32,114,search,3826.58,2750.43,0.631511,0.92397,0.100526,-1.0,-1.0,18.993,2.03675,1818,4600056 +32,115,insert,32.211,-1.0,-1.0,-1.0,-1.0,54.411,2.04892,1827,4627422 +32,116,search,3887.49,2752.19,0.589801,0.9246,0.100227,-1.0,-1.0,17.399,2.04916,1828,4627422 +32,117,insert,9.807,-1.0,-1.0,-1.0,-1.0,25.725,2.05452,1830,4639292 +32,118,search,3888.31,2755.85,0.612499,0.92452,0.10023,-1.0,-1.0,17.042,2.05452,1830,4639292 +32,119,insert,4.54,-1.0,-1.0,-1.0,-1.0,23.543,2.05697,1832,4643423 +32,120,search,3890.01,2752.58,0.571857,0.92452,0.10017,-1.0,-1.0,14.071,2.05697,1832,4643423 +32,121,insert,10.759,-1.0,-1.0,-1.0,-1.0,28.499,2.06233,1835,4657252 +32,122,search,3879.81,2756.35,0.610568,0.92474,0.10008,-1.0,-1.0,14.884,2.06233,1835,4657252 +32,123,insert,265.918,-1.0,-1.0,-1.0,-1.0,302.129,2.19105,1883,4938477 +32,124,search,4018.88,2812.42,0.624501,0.92523,0.101005,-1.0,-1.0,127.475,2.19167,1896,4938477 +32,125,insert,49.845,-1.0,-1.0,-1.0,-1.0,43.173,2.20899,1902,4980492 +32,126,search,4048.5,2810.72,0.593577,0.92576,0.100583,-1.0,-1.0,57.557,2.20909,1909,4980492 +32,127,insert,40.787,-1.0,-1.0,-1.0,-1.0,59.317,2.22996,1920,5030515 +32,128,search,4076.3,2815.91,0.645079,0.92675,0.0998028,-1.0,-1.0,25.699,2.23018,1922,5030515 +32,129,delete,11.287,-1.0,-1.0,-1.0,-1.0,30.707,2.22864,1893,5009391 +32,130,search,4016.26,2813.58,0.615433,0.92526,0.100871,-1.0,-1.0,16.425,2.22864,1893,5009391 +32,131,delete,3.149,-1.0,-1.0,-1.0,-1.0,15.971,2.22864,1893,5004093 +32,132,search,3984.39,2809.86,0.61735,0.92521,0.100976,-1.0,-1.0,15.833,2.22864,1893,5004093 +32,133,delete,7.07,-1.0,-1.0,-1.0,-1.0,15.629,2.22828,1893,4991787 +32,134,search,4045.95,2797.66,0.616977,0.92532,0.101013,-1.0,-1.0,18.564,2.22828,1893,4991787 +32,135,delete,22.934,-1.0,-1.0,-1.0,-1.0,48.688,2.22478,1889,4974857 +32,136,search,4050.92,2791.07,0.603725,0.92538,0.100812,-1.0,-1.0,20.261,2.2249,1890,4974857 +32,137,delete,2.717,-1.0,-1.0,-1.0,-1.0,16.051,2.2249,1890,4971386 +32,138,search,4037.52,2785.44,0.647033,0.92526,0.100989,-1.0,-1.0,16.75,2.2249,1890,4971386 +32,139,delete,8.05,-1.0,-1.0,-1.0,-1.0,16.303,2.2249,1890,4963487 +32,140,search,4037.92,2779.6,0.634301,0.92523,0.100936,-1.0,-1.0,16.247,2.2249,1890,4963487 +32,141,delete,15.493,-1.0,-1.0,-1.0,-1.0,62.528,2.22014,1885,4941830 +32,142,search,4041.46,2771.32,0.677359,0.92509,0.100993,-1.0,-1.0,26.282,2.22022,1886,4941830 +32,143,delete,16.51,-1.0,-1.0,-1.0,-1.0,45.137,2.21621,1883,4925657 +32,144,search,4060.78,2764.64,0.623418,0.9251,0.101059,-1.0,-1.0,16.361,2.21621,1883,4925657 +32,145,delete,2.121,-1.0,-1.0,-1.0,-1.0,18.728,2.21579,1882,4922686 +32,146,search,4025.03,2763.33,0.612749,0.92487,0.10134,-1.0,-1.0,16.643,2.21579,1882,4922686 +32,147,delete,6.556,-1.0,-1.0,-1.0,-1.0,15.995,2.21579,1882,4913636 +32,148,search,4073.35,2756.05,0.625526,0.92488,0.101322,-1.0,-1.0,19.815,2.21579,1882,4913636 +32,149,delete,184.94,-1.0,-1.0,-1.0,-1.0,733.934,2.13643,1798,4717250 +32,150,search,3881.7,2759.03,0.547399,0.92341,0.102958,-1.0,-1.0,43.829,2.13711,1804,4717250 +32,151,delete,107.072,-1.0,-1.0,-1.0,-1.0,609.644,2.06459,1728,4560269 diff --git a/scripts/big_ann_perf_numbers/scan_0.12_no_aps_refinment_wma_delete.csv b/scripts/big_ann_perf_numbers/scan_0.12_no_aps_refinment_wma_delete.csv new file mode 100644 index 00000000..2ec7394c --- /dev/null +++ b/scripts/big_ann_perf_numbers/scan_0.12_no_aps_refinment_wma_delete.csv @@ -0,0 +1,1280 @@ +step_num,step_type,latency_ms,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +2,search,2819.48,0.82013,0.14515,27.0527,17.7427,6.012,0.0184873,1024,38806 +3,insert,13.18,-1.0,-1.0,-1.0,-1.0,12.711,0.0226399,1020,49334 +4,search,2296.29,0.83661,0.14314,25.2135,17.2457,11.828,0.0226509,1017,49334 +5,insert,18.38,-1.0,-1.0,-1.0,-1.0,173.097,0.0331879,1008,73557 +6,search,2154.01,0.90249,0.119256,18.2191,16.1598,112.693,0.033274,1011,73557 +7,insert,26.243,-1.0,-1.0,-1.0,-1.0,116.238,0.0430081,1011,95766 +8,search,2172.58,0.89956,0.120187,18.1714,15.5465,84.763,0.0431558,1016,95766 +9,insert,4.183,-1.0,-1.0,-1.0,-1.0,72.427,0.0448967,1016,100025 +10,search,2162.64,0.89898,0.11857,18.1642,15.222,80.648,0.0448992,1018,100025 +11,insert,17.777,-1.0,-1.0,-1.0,-1.0,78.882,0.0497682,1020,111417 +12,search,2135.12,0.89918,0.118288,18.097,15.0779,75.841,0.0497682,1020,111417 +13,insert,22.916,-1.0,-1.0,-1.0,-1.0,78.721,0.0609858,1022,137139 +14,search,2158.7,0.89359,0.122992,18.2578,14.9262,17.882,0.0613763,1024,137139 +15,insert,17.269,-1.0,-1.0,-1.0,-1.0,9.732,0.0695815,1026,156710 +16,search,2231.91,0.88962,0.124808,18.4363,14.666,14.858,0.0695844,1028,156710 +17,insert,4.479,-1.0,-1.0,-1.0,-1.0,13.183,0.0718655,1033,161773 +18,search,2233.91,0.88844,0.125566,18.4228,14.6267,17.441,0.0721103,1037,161773 +19,insert,40.501,-1.0,-1.0,-1.0,-1.0,12.538,0.0790973,1041,177161 +20,search,2242.42,0.89172,0.12179,18.3386,14.5539,12.475,0.0791022,1044,177161 +21,insert,358.483,-1.0,-1.0,-1.0,-1.0,206.46,0.202279,1110,448898 +22,search,2510.4,0.87696,0.127124,20.5626,15.6941,61.57,0.202339,1128,448898 +23,insert,377.899,-1.0,-1.0,-1.0,-1.0,268.954,0.329047,1197,733493 +24,search,2712.51,0.871,0.129739,21.4788,16.392,127.525,0.330218,1234,733493 +25,insert,54.435,-1.0,-1.0,-1.0,-1.0,22.158,0.34713,1239,777443 +26,search,2814.86,0.8675,0.132112,21.9584,16.6427,21.56,0.347176,1244,777443 +27,insert,33.089,-1.0,-1.0,-1.0,-1.0,26.448,0.358537,1249,805394 +28,search,2856.33,0.86719,0.132299,21.9418,16.629,7.825,0.358623,1251,805394 +29,insert,31.837,-1.0,-1.0,-1.0,-1.0,43.19,0.38611,1271,866391 +30,search,2888.24,0.87082,0.130932,21.634,16.5702,20.502,0.386117,1276,866391 +31,insert,470.18,-1.0,-1.0,-1.0,-1.0,221.934,0.553713,1361,1239816 +32,search,3008.12,0.86487,0.136168,22.4565,17.1789,50.395,0.553906,1374,1239816 +33,insert,51.52,-1.0,-1.0,-1.0,-1.0,28.172,0.57357,1380,1291211 +34,search,3130.07,0.86611,0.134976,22.4059,17.2331,8.166,0.573626,1381,1291211 +35,insert,23.043,-1.0,-1.0,-1.0,-1.0,23.585,0.585766,1391,1324978 +36,search,3275.37,0.86711,0.133861,22.3074,17.1842,10.215,0.585766,1391,1324978 +37,insert,58.822,-1.0,-1.0,-1.0,-1.0,34.93,0.605394,1399,1371885 +38,search,3265.79,0.86746,0.133755,22.418,17.4658,22.055,0.605443,1402,1371885 +39,insert,10.044,-1.0,-1.0,-1.0,-1.0,11.865,0.608672,1403,1379335 +40,search,3193.58,0.86832,0.133531,22.4442,17.5762,9.879,0.608672,1403,1379335 +41,insert,28.917,-1.0,-1.0,-1.0,-1.0,14.688,0.623574,1407,1413312 +42,search,3092.64,0.86917,0.133389,22.3312,17.6052,9.675,0.623574,1407,1413312 +43,insert,12.135,-1.0,-1.0,-1.0,-1.0,13.73,0.62731,1409,1423411 +44,search,3023.98,0.86981,0.132778,22.3791,17.6557,6.64,0.62731,1409,1423411 +45,insert,150.707,-1.0,-1.0,-1.0,-1.0,26.163,0.641533,1420,1457559 +46,search,3326.98,0.87022,0.132487,22.3876,17.7134,9.838,0.641533,1420,1457559 +47,insert,223.585,-1.0,-1.0,-1.0,-1.0,164.715,0.746675,1465,1688593 +48,search,3386.7,0.87338,0.13363,22.0334,17.8572,94.833,0.746992,1479,1688593 +49,insert,44.358,-1.0,-1.0,-1.0,-1.0,27.304,0.761896,1484,1723505 +50,search,3555.84,0.87546,0.132107,21.943,17.8973,38.566,0.76199,1489,1723505 +51,insert,367.719,-1.0,-1.0,-1.0,-1.0,215.888,0.903029,1553,2035040 +52,search,3701.77,0.88182,0.129171,21.4981,18.166,30.076,0.903121,1563,2035040 +53,insert,30.203,-1.0,-1.0,-1.0,-1.0,21.571,0.920373,1568,2078341 +54,search,3777.61,0.88236,0.12875,21.4871,18.1465,7.054,0.920373,1568,2078341 +55,insert,212.543,-1.0,-1.0,-1.0,-1.0,284.102,1.06805,1642,2399905 +56,search,3917.53,0.88589,0.128152,21.1166,18.2308,164.743,1.06906,1676,2399905 +57,insert,25.215,-1.0,-1.0,-1.0,-1.0,15.761,1.07702,1677,2419836 +58,search,4202.76,0.88436,0.129192,21.3257,18.3327,46.309,1.07702,1681,2419836 +59,insert,228.33,-1.0,-1.0,-1.0,-1.0,139.254,1.17595,1696,2643083 +60,search,4257.76,0.87855,0.135346,22.4206,19.4819,50.639,1.17611,1702,2643083 +61,insert,11.488,-1.0,-1.0,-1.0,-1.0,19.971,1.17992,1704,2653064 +62,search,4274.71,0.87821,0.135799,22.4815,19.562,21.268,1.18006,1706,2653064 +63,insert,4.243,-1.0,-1.0,-1.0,-1.0,12.258,1.18158,1706,2656118 +64,search,4094.16,0.87832,0.13561,22.4734,19.5735,13.148,1.18158,1706,2656118 +65,insert,77.325,-1.0,-1.0,-1.0,-1.0,110.681,1.20883,1738,2723424 +66,search,4376.59,0.87891,0.134528,22.4755,19.5986,16.213,1.20883,1738,2723424 +67,insert,60.422,-1.0,-1.0,-1.0,-1.0,79.027,1.22962,1757,2769021 +68,search,4266.67,0.88005,0.13366,22.3045,19.4955,19.765,1.2297,1758,2769021 +69,insert,61.575,-1.0,-1.0,-1.0,-1.0,66.774,1.24981,1768,2821777 +70,search,4496.96,0.88252,0.132208,22.0513,19.3808,24.376,1.24981,1769,2821777 +71,insert,19.46,-1.0,-1.0,-1.0,-1.0,28.468,1.25513,1772,2834921 +72,search,4189.68,0.88321,0.131664,21.9397,19.3137,17.138,1.25513,1772,2834921 +73,insert,10.807,-1.0,-1.0,-1.0,-1.0,20.768,1.25859,1773,2842044 +74,search,4477.73,0.88311,0.131709,21.929,19.315,16.717,1.25859,1773,2842044 +75,insert,25.405,-1.0,-1.0,-1.0,-1.0,33.817,1.26723,1777,2858890 +76,search,4215.89,0.88334,0.13162,21.8792,19.2534,16.564,1.26723,1777,2858890 +77,insert,34.616,-1.0,-1.0,-1.0,-1.0,18.521,1.27747,1778,2882818 +78,search,4500.46,0.88334,0.131658,21.9509,19.3011,16.559,1.27747,1778,2882818 +79,insert,530.73,-1.0,-1.0,-1.0,-1.0,48.219,1.30615,1787,2947806 +80,search,4556.32,0.88298,0.131908,22.0778,19.4783,18.191,1.30615,1787,2947806 +81,insert,48.941,-1.0,-1.0,-1.0,-1.0,24.089,1.31915,1789,2976895 +82,search,4333.07,0.8841,0.130863,21.8776,19.3785,20.582,1.31917,1790,2976895 +83,insert,14.381,-1.0,-1.0,-1.0,-1.0,24.704,1.32435,1792,2990682 +84,search,4457.43,0.88504,0.130283,21.8483,19.3678,25.76,1.3245,1794,2990682 +85,insert,51.476,-1.0,-1.0,-1.0,-1.0,44.603,1.33889,1800,3025613 +86,search,4438.05,0.88595,0.130118,21.7465,19.3817,12.008,1.33889,1800,3025613 +87,insert,497.437,-1.0,-1.0,-1.0,-1.0,701.709,1.54462,1933,3468632 +88,search,4889.31,0.88965,0.127362,21.2515,19.1936,107.801,1.54488,1949,3468632 +89,insert,391.713,-1.0,-1.0,-1.0,-1.0,392.827,1.70077,2035,3831692 +90,search,5252.61,0.89506,0.121518,20.6746,18.7578,69.155,1.70146,2049,3831692 +91,insert,22.394,-1.0,-1.0,-1.0,-1.0,42.981,1.71228,2056,3864067 +92,search,4938.63,0.89495,0.121311,20.6944,18.7848,31.649,1.71228,2057,3864067 +93,insert,215.562,-1.0,-1.0,-1.0,-1.0,326.612,1.82009,2106,4103827 +94,search,5370.82,0.89548,0.121323,20.5744,18.7796,48.045,1.82029,2112,4103827 +95,insert,15.42,-1.0,-1.0,-1.0,-1.0,47.88,1.82701,2118,4119898 +96,search,5114.47,0.89602,0.121042,20.5233,18.7499,31.491,1.82729,2120,4119898 +97,insert,6.268,-1.0,-1.0,-1.0,-1.0,34.852,1.83058,2123,4129367 +98,search,5175.03,0.89571,0.120922,20.5378,18.748,24.91,1.83058,2123,4129367 +99,insert,4.421,-1.0,-1.0,-1.0,-1.0,26.125,1.83218,2123,4134502 +100,search,5729.91,0.89572,0.121015,20.514,18.7408,29.912,1.83218,2123,4134502 +101,insert,45.061,-1.0,-1.0,-1.0,-1.0,64.225,1.84414,2130,4164482 +102,search,5752.75,0.89616,0.121057,20.4725,18.7317,30.308,1.84414,2130,4164482 +103,insert,25.77,-1.0,-1.0,-1.0,-1.0,54.016,1.85165,2136,4178601 +104,search,5605.08,0.89655,0.120745,20.4561,18.7379,33.101,1.85175,2137,4178601 +105,insert,14.593,-1.0,-1.0,-1.0,-1.0,45.172,1.85609,2140,4187774 +106,search,5645.7,0.89622,0.121203,20.458,18.7306,30.578,1.85609,2140,4187774 +107,insert,17.451,-1.0,-1.0,-1.0,-1.0,35.381,1.8606,2141,4200109 +108,search,5581.3,0.89597,0.121323,20.4694,18.7457,30.218,1.8606,2141,4200109 +109,insert,437.681,-1.0,-1.0,-1.0,-1.0,520.513,2.02021,2225,4557867 +110,search,4713.71,0.89929,0.119237,20.1499,18.689,57.936,2.02104,2237,4557867 +111,insert,18.159,-1.0,-1.0,-1.0,-1.0,39.396,2.03279,2246,4587252 +112,search,4660.93,0.89944,0.119275,20.0991,18.684,22.528,2.03279,2246,4587252 +113,insert,8.706,-1.0,-1.0,-1.0,-1.0,24.725,2.03725,2247,4600056 +114,search,4720.91,0.89953,0.119331,20.0614,18.6614,22.553,2.03725,2247,4600056 +115,insert,22.244,-1.0,-1.0,-1.0,-1.0,27.979,2.04577,2249,4627422 +116,search,4691.98,0.90004,0.119231,19.982,18.6513,22.529,2.04577,2249,4627422 +117,insert,8.554,-1.0,-1.0,-1.0,-1.0,23.569,2.04938,2250,4639292 +118,search,4760.08,0.9006,0.11878,19.9803,18.6632,33.454,2.04969,2253,4639292 +119,insert,4.719,-1.0,-1.0,-1.0,-1.0,21.473,2.05197,2253,4643423 +120,search,4763.12,0.9006,0.118805,19.9626,18.6546,22.498,2.05197,2253,4643423 +121,insert,10.998,-1.0,-1.0,-1.0,-1.0,33.532,2.05722,2257,4657252 +122,search,4730.68,0.9008,0.118614,19.9484,18.6672,22.379,2.05722,2257,4657252 +123,insert,178.663,-1.0,-1.0,-1.0,-1.0,285.88,2.18607,2313,4938477 +124,search,4848.87,0.90183,0.119048,19.662,18.4961,88.466,2.18677,2332,4938477 +125,insert,30.379,-1.0,-1.0,-1.0,-1.0,64.452,2.20566,2346,4980492 +126,search,4938.48,0.90217,0.118781,19.6551,18.5636,23.903,2.20566,2346,4980492 +127,insert,32.023,-1.0,-1.0,-1.0,-1.0,69.858,2.22426,2364,5030515 +128,search,4950.72,0.90283,0.118098,19.5708,18.5454,14.426,2.22426,2364,5030515 +129,delete,11.967,-1.0,-1.0,-1.0,-1.0,15.817,2.22355,2358,5009391 +130,search,4902.7,0.90244,0.118391,19.6048,18.5991,15.755,2.22355,2358,5009391 +131,delete,3.887,-1.0,-1.0,-1.0,-1.0,14.104,2.22355,2358,5004093 +132,search,4943.46,0.9026,0.118315,19.5881,18.5922,15.588,2.22355,2358,5004093 +133,delete,6.931,-1.0,-1.0,-1.0,-1.0,14.008,2.22355,2358,4991787 +134,search,4847.19,0.9025,0.118344,19.6048,18.5937,15.748,2.22355,2358,4991787 +135,delete,10.638,-1.0,-1.0,-1.0,-1.0,22.151,2.22185,2357,4974857 +136,search,4944.82,0.90264,0.118379,19.6113,18.6162,24.214,2.22185,2357,4974857 +137,delete,2.046,-1.0,-1.0,-1.0,-1.0,22.582,2.22185,2357,4971386 +138,search,4923.29,0.90253,0.118506,19.6256,18.6276,23.777,2.22185,2357,4971386 +139,delete,4.214,-1.0,-1.0,-1.0,-1.0,22.395,2.22185,2357,4963487 +140,search,4895.77,0.90231,0.118352,19.6339,18.6318,23.706,2.22185,2357,4963487 +141,delete,11.353,-1.0,-1.0,-1.0,-1.0,22.51,2.2199,2357,4941830 +142,search,4926.02,0.90252,0.118553,19.6331,18.6513,24.427,2.2199,2357,4941830 +143,delete,8.871,-1.0,-1.0,-1.0,-1.0,34.134,2.21751,2355,4925657 +144,search,4872.89,0.9026,0.118484,19.6404,18.6479,25.076,2.21751,2355,4925657 +145,delete,2.015,-1.0,-1.0,-1.0,-1.0,22.489,2.21722,2355,4922686 +146,search,4913.85,0.90236,0.118653,19.6571,18.64,24.832,2.21722,2355,4922686 +147,delete,6.5,-1.0,-1.0,-1.0,-1.0,22.361,2.21722,2355,4913636 +148,search,4903.9,0.90236,0.118518,19.6823,18.6604,24.63,2.21722,2355,4913636 +149,delete,128.055,-1.0,-1.0,-1.0,-1.0,83.697,2.1865,2343,4717250 +150,search,4826.65,0.90153,0.119573,19.7834,18.7481,29.14,2.1866,2344,4717250 +151,delete,108.357,-1.0,-1.0,-1.0,-1.0,106.191,2.14494,2328,4560269 +152,search,4635.3,0.90037,0.120542,19.9054,18.7933,24.168,2.14494,2328,4560269 +153,delete,18.871,-1.0,-1.0,-1.0,-1.0,50.224,2.13495,2322,4521936 +154,search,4698.99,0.89931,0.121292,20.0455,18.8794,23.448,2.13495,2322,4521936 +155,delete,11.207,-1.0,-1.0,-1.0,-1.0,30.19,2.13131,2321,4502222 +156,search,4670.8,0.89919,0.121341,20.0752,18.9093,23.337,2.13131,2321,4502222 +157,delete,23.244,-1.0,-1.0,-1.0,-1.0,35.858,2.12403,2319,4456039 +158,search,4667.83,0.89859,0.121772,20.1359,18.9751,23.349,2.12403,2319,4456039 +159,delete,193.098,-1.0,-1.0,-1.0,-1.0,304.645,1.98503,2264,4143922 +160,search,4421.26,0.89674,0.123659,20.3788,19.1921,23.323,1.98503,2264,4143922 +161,delete,31.146,-1.0,-1.0,-1.0,-1.0,21.357,1.97923,2264,4101445 +162,search,4459.94,0.89699,0.123295,20.3778,19.1848,23.152,1.97923,2264,4101445 +163,delete,13.655,-1.0,-1.0,-1.0,-1.0,26.354,1.97421,2263,4080175 +164,search,4445.82,0.89664,0.123391,20.4191,19.1965,23.159,1.97421,2263,4080175 +165,delete,22.685,-1.0,-1.0,-1.0,-1.0,21.183,1.96716,2263,4047313 +166,search,4434.14,0.8967,0.123494,20.3819,19.165,23.269,1.96716,2263,4047313 +167,delete,6.114,-1.0,-1.0,-1.0,-1.0,21.242,1.96479,2263,4040738 +168,search,4424.85,0.89662,0.123369,20.4128,19.1746,22.855,1.96479,2263,4040738 +169,delete,13.683,-1.0,-1.0,-1.0,-1.0,35.281,1.95767,2261,4022674 +170,search,4436.82,0.89635,0.123576,20.4644,19.2106,22.854,1.95767,2261,4022674 +171,delete,5.216,-1.0,-1.0,-1.0,-1.0,21.128,1.95566,2261,4015835 +172,search,4425.38,0.89617,0.123823,20.4661,19.2149,22.617,1.95566,2261,4015835 +173,delete,23.436,-1.0,-1.0,-1.0,-1.0,21.331,1.94754,2261,3986424 +174,search,4370.75,0.89595,0.124146,20.5282,19.2546,22.848,1.94754,2261,3986424 +175,delete,115.968,-1.0,-1.0,-1.0,-1.0,306.028,1.86541,2200,3804693 +176,search,4264.88,0.89452,0.124553,20.8343,19.4217,27.521,1.86541,2201,3804693 +177,delete,13.017,-1.0,-1.0,-1.0,-1.0,20.4,1.86073,2201,3786352 +178,search,4284.2,0.89415,0.124764,20.8761,19.4317,22.392,1.86073,2201,3786352 +179,delete,179.046,-1.0,-1.0,-1.0,-1.0,242.681,1.74394,2131,3556994 +180,search,4064.63,0.88846,0.12721,21.6756,19.6591,28.95,1.74416,2133,3556994 +181,delete,22.23,-1.0,-1.0,-1.0,-1.0,21.615,1.73511,2132,3526824 +182,search,4059.59,0.88824,0.127371,21.696,19.701,22.024,1.73511,2132,3526824 +183,delete,121.409,-1.0,-1.0,-1.0,-1.0,258.727,1.65509,2069,3350245 +184,search,3895.89,0.87925,0.134225,22.8945,20.2389,21.317,1.65509,2069,3350245 +185,delete,9.303,-1.0,-1.0,-1.0,-1.0,20.277,1.6511,2067,3340234 +186,search,3914.18,0.88097,0.132111,22.7058,20.1374,20.819,1.6511,2067,3340234 +187,delete,133.301,-1.0,-1.0,-1.0,-1.0,183.5,1.55699,2030,3150857 +188,search,3811.2,0.88318,0.129679,22.1821,19.5923,22.833,1.55705,2031,3150857 +189,delete,5.023,-1.0,-1.0,-1.0,-1.0,18.663,1.5555,2031,3143609 +190,search,3815.84,0.88275,0.130293,22.2171,19.6008,20.258,1.5555,2031,3143609 +191,delete,1.825,-1.0,-1.0,-1.0,-1.0,18.796,1.55495,2031,3141038 +192,search,3769.44,0.88274,0.13033,22.2083,19.5878,20.059,1.55495,2031,3141038 +193,delete,42.987,-1.0,-1.0,-1.0,-1.0,19.325,1.53067,2031,3081734 +194,search,3774.83,0.88114,0.131431,22.411,19.7055,20.131,1.53067,2031,3081734 +195,delete,25.929,-1.0,-1.0,-1.0,-1.0,30.756,1.51323,2029,3043966 +196,search,3744.61,0.8801,0.13236,22.502,19.7694,20.978,1.51323,2029,3043966 +197,delete,29.364,-1.0,-1.0,-1.0,-1.0,40.625,1.4988,2027,3008145 +198,search,3717.92,0.87957,0.1325,22.5923,19.8148,20.707,1.4988,2027,3008145 +199,delete,9.255,-1.0,-1.0,-1.0,-1.0,18.851,1.49494,2027,2999384 +200,search,3754.83,0.87934,0.132473,22.6517,19.8478,20.662,1.49494,2027,2999384 +201,delete,5.092,-1.0,-1.0,-1.0,-1.0,19.077,1.49249,2027,2993528 +202,search,3747.34,0.8791,0.132723,22.6819,19.8518,20.495,1.49249,2027,2993528 +203,delete,9.951,-1.0,-1.0,-1.0,-1.0,18.612,1.48903,2027,2980973 +204,search,3737.37,0.87914,0.13257,22.6908,19.851,20.777,1.48903,2027,2980973 +205,delete,18.476,-1.0,-1.0,-1.0,-1.0,18.915,1.48045,2027,2960291 +206,search,3741.85,0.87901,0.132325,22.7402,19.8635,20.599,1.48045,2027,2960291 +207,delete,33.148,-1.0,-1.0,-1.0,-1.0,30.9,1.45967,2018,2920620 +208,search,3706.92,0.87831,0.132892,22.7719,19.8303,20.415,1.45967,2018,2920620 +209,delete,15.331,-1.0,-1.0,-1.0,-1.0,26.808,1.45225,2017,2900501 +210,search,3699.98,0.8776,0.13303,22.9155,19.8649,20.137,1.45225,2017,2900501 +211,delete,6.094,-1.0,-1.0,-1.0,-1.0,18.518,1.44952,2017,2891660 +212,search,3680.45,0.87727,0.133236,22.9495,19.881,20.019,1.44952,2017,2891660 +213,delete,12.097,-1.0,-1.0,-1.0,-1.0,24.91,1.44233,2015,2873257 +214,search,3646.65,0.87625,0.133945,23.0074,19.8618,19.835,1.44233,2015,2873257 +215,delete,245.835,-1.0,-1.0,-1.0,-1.0,369.569,1.25737,1917,2537571 +216,search,3448.23,0.87204,0.136502,23.6432,20.101,26.946,1.25748,1918,2537571 +217,delete,157.588,-1.0,-1.0,-1.0,-1.0,202.672,1.14403,1870,2308194 +218,search,3300.66,0.86822,0.139188,24.0721,20.319,18.971,1.14403,1870,2308194 +219,delete,20.527,-1.0,-1.0,-1.0,-1.0,16.564,1.13825,1870,2285820 +220,search,3278.25,0.86703,0.140095,24.1672,20.3359,18.396,1.13825,1870,2285820 +221,delete,157.829,-1.0,-1.0,-1.0,-1.0,207.851,1.02589,1796,2082858 +222,search,3130.7,0.86358,0.14281,24.5167,20.4545,17.733,1.02589,1796,2082858 +223,delete,9.87,-1.0,-1.0,-1.0,-1.0,19.581,1.02192,1795,2071207 +224,search,3136.21,0.8617,0.144283,24.7043,20.5445,17.318,1.02192,1795,2071207 +225,delete,4.402,-1.0,-1.0,-1.0,-1.0,15.189,1.02081,1795,2065400 +226,search,3146.03,0.86158,0.144343,24.7423,20.5608,16.879,1.02081,1795,2065400 +227,delete,2.693,-1.0,-1.0,-1.0,-1.0,15.322,1.01992,1795,2062105 +228,search,3084.84,0.8615,0.144419,24.7481,20.5643,17.225,1.01992,1795,2062105 +229,delete,15.748,-1.0,-1.0,-1.0,-1.0,21.324,1.01234,1793,2039610 +230,search,3104.05,0.86037,0.144683,24.9508,20.6028,17.42,1.01234,1793,2039610 +231,delete,9.929,-1.0,-1.0,-1.0,-1.0,22.408,1.00468,1790,2027795 +232,search,3080.79,0.85944,0.14515,25.0359,20.6046,17.028,1.00468,1790,2027795 +233,delete,3.634,-1.0,-1.0,-1.0,-1.0,15.206,1.00306,1790,2022859 +234,search,3088.1,0.85916,0.145319,25.0434,20.605,16.878,1.00306,1790,2022859 +235,delete,5.658,-1.0,-1.0,-1.0,-1.0,16.987,1.00002,1787,2016264 +236,search,3084.33,0.85902,0.145337,25.1024,20.6355,16.72,1.00002,1787,2016264 +237,delete,172.193,-1.0,-1.0,-1.0,-1.0,214.49,0.88084,1718,1782866 +238,search,2991.91,0.85515,0.147735,25.6267,20.94,16.267,0.88084,1718,1782866 +239,delete,14.972,-1.0,-1.0,-1.0,-1.0,35.638,0.869252,1711,1758931 +240,search,2950.99,0.85281,0.148894,25.9156,21.0402,16.376,0.869252,1711,1758931 +241,delete,5.591,-1.0,-1.0,-1.0,-1.0,19.934,0.86711,1710,1751275 +242,search,2921.09,0.85238,0.148785,25.9883,21.0705,16.2,0.86711,1710,1751275 +243,delete,12.757,-1.0,-1.0,-1.0,-1.0,14.508,0.862142,1710,1733264 +244,search,2954.12,0.8509,0.149299,26.2022,21.0935,17.984,0.862142,1710,1733264 +245,delete,11.347,-1.0,-1.0,-1.0,-1.0,19.458,0.858286,1709,1722658 +246,search,2970.42,0.85048,0.149365,26.3065,21.1166,16.587,0.858286,1709,1722658 +247,delete,3.644,-1.0,-1.0,-1.0,-1.0,14.437,0.857302,1709,1719601 +248,search,2960.62,0.85038,0.149441,26.3419,21.1347,16.295,0.857302,1709,1719601 +249,delete,7.603,-1.0,-1.0,-1.0,-1.0,14.651,0.853426,1709,1711648 +250,search,2965.1,0.84991,0.149603,26.399,21.1728,16.759,0.853426,1709,1711648 +251,delete,191.205,-1.0,-1.0,-1.0,-1.0,240.409,0.726617,1615,1470624 +252,search,2745.07,0.84819,0.150632,26.4705,21.1024,31.914,0.726617,1617,1470624 +253,delete,21.313,-1.0,-1.0,-1.0,-1.0,19.239,0.715733,1615,1442070 +254,search,2785.41,0.84723,0.150899,26.5916,21.1194,15.598,0.715733,1615,1442070 +255,delete,29.45,-1.0,-1.0,-1.0,-1.0,16.174,0.700021,1613,1405549 +256,search,2775.65,0.8435,0.153008,27.0613,21.2757,21.912,0.700022,1614,1405549 +257,insert,6.455,-1.0,-1.0,-1.0,-1.0,13.897,0.702302,1614,1416288 +258,search,2730,0.84379,0.152949,27.0388,21.25,15.228,0.702302,1614,1416288 +259,insert,16.849,-1.0,-1.0,-1.0,-1.0,18.465,0.708545,1615,1443010 +260,search,2771.65,0.84407,0.15316,27.0032,21.3093,15.336,0.708545,1615,1443010 +261,insert,1.332,-1.0,-1.0,-1.0,-1.0,13.901,0.708683,1615,1447529 +262,search,2780.88,0.84467,0.152665,26.923,21.297,15.17,0.708683,1615,1447529 +263,insert,82.053,-1.0,-1.0,-1.0,-1.0,42.04,0.747569,1620,1569110 +264,search,2753.05,0.84634,0.153442,26.517,21.3223,20.036,0.747569,1621,1569110 +265,insert,45.073,-1.0,-1.0,-1.0,-1.0,14.2,0.767608,1621,1636119 +266,search,2834.41,0.85003,0.151125,26.1002,21.22,20.436,0.767614,1622,1636119 +267,insert,23.653,-1.0,-1.0,-1.0,-1.0,24.479,0.778431,1624,1665152 +268,search,2843.15,0.8522,0.150407,25.7405,21.1295,15.339,0.778431,1624,1665152 +269,insert,179.541,-1.0,-1.0,-1.0,-1.0,86.152,0.872611,1636,1916952 +270,search,2906.08,0.8546,0.148651,25.4714,21.0758,57.422,0.872739,1643,1916952 +271,insert,4.016,-1.0,-1.0,-1.0,-1.0,14.439,0.874215,1643,1920898 +272,search,2917.88,0.85488,0.148663,25.4171,21.042,24.846,0.874214,1645,1920898 +273,insert,19.591,-1.0,-1.0,-1.0,-1.0,18.006,0.882635,1646,1942757 +274,search,2916.2,0.85682,0.147718,25.1912,20.9736,15.934,0.882635,1646,1942757 +275,insert,324.501,-1.0,-1.0,-1.0,-1.0,168.27,1.04517,1678,2328372 +276,search,3029.32,0.86068,0.144136,24.8361,20.7816,70.954,1.0453,1689,2328372 +277,insert,29.94,-1.0,-1.0,-1.0,-1.0,14.321,1.0578,1689,2363257 +278,search,3085.88,0.86179,0.143461,24.7037,20.7305,25.649,1.0578,1691,2363257 +279,insert,20.055,-1.0,-1.0,-1.0,-1.0,14.081,1.06657,1691,2388933 +280,search,3073.99,0.86278,0.142819,24.6311,20.6921,15.355,1.06657,1691,2388933 +281,insert,220.393,-1.0,-1.0,-1.0,-1.0,105.255,1.20017,1706,2684315 +282,search,3141.13,0.86403,0.142598,24.5614,20.9276,41.283,1.20017,1710,2684315 +283,insert,342.882,-1.0,-1.0,-1.0,-1.0,174.833,1.38747,1745,3109157 +284,search,3344.7,0.87019,0.138965,23.8041,20.4843,79.716,1.38747,1757,3109157 +285,insert,10.529,-1.0,-1.0,-1.0,-1.0,14.924,1.39245,1757,3122751 +286,search,3395.91,0.87077,0.138835,23.7482,20.4923,29.338,1.39245,1760,3122751 +287,insert,27.482,-1.0,-1.0,-1.0,-1.0,14.86,1.40753,1760,3163679 +288,search,3387.1,0.87172,0.13846,23.6567,20.4411,18.372,1.40753,1761,3163679 +289,insert,221.028,-1.0,-1.0,-1.0,-1.0,158.647,1.54547,1790,3472031 +290,search,3567.86,0.87504,0.136598,23.2109,20.4557,80.302,1.5461,1803,3472031 +291,insert,18.089,-1.0,-1.0,-1.0,-1.0,15.331,1.55739,1803,3495577 +292,search,3608.18,0.87742,0.134492,23.0026,20.3295,26.45,1.55739,1805,3495577 +293,insert,11.772,-1.0,-1.0,-1.0,-1.0,26.963,1.56647,1808,3515193 +294,search,3594.81,0.87735,0.134767,22.9777,20.363,16.365,1.56647,1808,3515193 +295,insert,146.339,-1.0,-1.0,-1.0,-1.0,109.324,1.65865,1826,3723063 +296,search,3720.62,0.87962,0.133864,22.6467,20.2314,48.564,1.65889,1833,3723063 +297,insert,3.528,-1.0,-1.0,-1.0,-1.0,15.685,1.66076,1833,3727399 +298,search,3702.38,0.87946,0.133991,22.6362,20.2483,21.989,1.66076,1834,3727399 +299,insert,56.42,-1.0,-1.0,-1.0,-1.0,24.948,1.68585,1838,3788002 +300,search,3748.67,0.88188,0.131786,22.463,20.1491,21.038,1.68601,1840,3788002 +301,insert,450.33,-1.0,-1.0,-1.0,-1.0,404.458,1.94921,1953,4370866 +302,search,4155.34,0.90387,0.118005,19.6158,18.9384,58.062,1.94949,1969,4370866 +303,insert,29.288,-1.0,-1.0,-1.0,-1.0,42.342,1.96941,1974,4420306 +304,search,4163.12,0.90345,0.118311,19.6595,18.9396,16.471,1.96941,1974,4420306 +305,insert,231.341,-1.0,-1.0,-1.0,-1.0,260.382,2.13414,2020,4789669 +306,search,4330.44,0.90573,0.116557,19.359,18.8201,97.64,2.13465,2040,4789669 +307,insert,17.287,-1.0,-1.0,-1.0,-1.0,15.495,2.14404,2040,4815550 +308,search,4350.13,0.90587,0.116318,19.3133,18.7665,21.474,2.14404,2041,4815550 +309,insert,4.274,-1.0,-1.0,-1.0,-1.0,19.111,2.14616,2042,4823345 +310,search,4368.32,0.90615,0.116205,19.3108,18.7724,27.172,2.14661,2046,4823345 +311,insert,9.427,-1.0,-1.0,-1.0,-1.0,15.669,2.15296,2046,4843493 +312,search,4322.01,0.90582,0.116514,19.3463,18.8024,16.578,2.15296,2046,4843493 +313,insert,28.979,-1.0,-1.0,-1.0,-1.0,42.769,2.17409,2053,4885489 +314,search,4378.38,0.90599,0.116292,19.2962,18.7571,39.588,2.17437,2058,4885489 +315,insert,4.493,-1.0,-1.0,-1.0,-1.0,16.041,2.17686,2058,4892335 +316,search,4386.26,0.90582,0.116402,19.3257,18.7959,16.383,2.17686,2058,4892335 +317,insert,32.431,-1.0,-1.0,-1.0,-1.0,43.58,2.19544,2066,4932996 +318,search,4425.59,0.90595,0.116691,19.2491,18.7427,20.671,2.1955,2067,4932996 +319,insert,399.197,-1.0,-1.0,-1.0,-1.0,429.918,2.41217,2156,5430684 +320,search,4713.33,0.90959,0.113436,18.6932,18.4726,115.317,2.41337,2182,5430684 +321,insert,31.001,-1.0,-1.0,-1.0,-1.0,50.625,2.42984,2195,5471239 +322,search,4684.16,0.9102,0.113118,18.6372,18.4358,36.371,2.42991,2198,5471239 +323,insert,76.398,-1.0,-1.0,-1.0,-1.0,121.529,2.47705,2233,5575560 +324,search,4848.07,0.91027,0.113123,18.5625,18.431,30.676,2.47731,2237,5575560 +325,insert,948.436,-1.0,-1.0,-1.0,-1.0,574.684,2.70384,2328,6069499 +326,search,5110.68,0.91354,0.111268,18.0326,18.193,148.689,2.70507,2358,6069499 +327,insert,42.552,-1.0,-1.0,-1.0,-1.0,60.403,2.73491,2369,6139647 +328,search,5183.73,0.91392,0.111331,17.9149,18.1294,45.508,2.73508,2377,6139647 +329,insert,5.042,-1.0,-1.0,-1.0,-1.0,12.083,2.73776,2377,6146884 +330,search,5160.34,0.91398,0.111124,17.8869,18.0966,13.944,2.73776,2377,6146884 +331,insert,27.059,-1.0,-1.0,-1.0,-1.0,47.104,2.75537,2386,6188816 +332,search,5284.84,0.91401,0.111048,17.887,18.1108,20.871,2.75549,2388,6188816 +333,insert,1.743,-1.0,-1.0,-1.0,-1.0,11.949,2.7559,2388,6190810 +334,search,5227.51,0.91401,0.11112,17.8851,18.1072,13.715,2.7559,2388,6190810 +335,insert,35.515,-1.0,-1.0,-1.0,-1.0,47.165,2.77262,2401,6230108 +336,search,5283.66,0.91432,0.110481,17.8633,18.0816,13.337,2.77262,2401,6230108 +337,insert,15.593,-1.0,-1.0,-1.0,-1.0,17.643,2.7802,2402,6249699 +338,search,5317.58,0.91465,0.110236,17.8187,18.0696,13.673,2.7802,2402,6249699 +339,insert,32.396,-1.0,-1.0,-1.0,-1.0,54.677,2.79596,2414,6290226 +340,search,5296.5,0.91533,0.109644,17.7376,17.9928,15.801,2.79602,2415,6290226 +341,insert,7.6,-1.0,-1.0,-1.0,-1.0,28.822,2.80017,2420,6297556 +342,search,5274.29,0.9155,0.109586,17.7026,17.9711,17.671,2.80018,2421,6297556 +343,insert,23.79,-1.0,-1.0,-1.0,-1.0,62.141,2.81502,2435,6330843 +344,search,5317.94,0.91562,0.109584,17.681,17.9766,20.477,2.81512,2437,6330843 +345,insert,28.843,-1.0,-1.0,-1.0,-1.0,45.01,2.83073,2448,6370265 +346,search,5374.02,0.91566,0.109531,17.6431,17.9511,18.69,2.83092,2449,6370265 +347,insert,392.628,-1.0,-1.0,-1.0,-1.0,576.514,3.03809,2588,6831086 +348,search,5753.14,0.91878,0.107222,17.2214,17.7598,107.14,3.04053,2616,6831086 +349,insert,30.735,-1.0,-1.0,-1.0,-1.0,53.212,3.05502,2629,6876154 +350,search,5739.4,0.91902,0.107097,17.2034,17.7477,21.113,3.05519,2630,6876154 +351,insert,259.337,-1.0,-1.0,-1.0,-1.0,413.16,3.23634,2718,7288266 +352,search,5993.3,0.918,0.108436,17.2102,17.6943,134.83,3.23832,2747,7288266 +353,insert,34.408,-1.0,-1.0,-1.0,-1.0,64.88,3.25846,2762,7333132 +354,search,6096.04,0.91806,0.108716,17.1544,17.6919,29.676,3.25846,2764,7333132 +355,insert,248.269,-1.0,-1.0,-1.0,-1.0,424.316,3.42183,2857,7696838 +356,search,6328.89,0.91954,0.107359,16.8386,17.4891,128.651,3.42376,2884,7696838 +357,insert,13.956,-1.0,-1.0,-1.0,-1.0,25.225,3.42962,2885,7714498 +358,search,6340.62,0.92014,0.107181,16.7756,17.439,37.746,3.42995,2891,7714498 +359,insert,9.669,-1.0,-1.0,-1.0,-1.0,26.288,3.43463,2893,7725755 +360,search,6387.01,0.92023,0.107122,16.7623,17.435,25.245,3.4348,2894,7725755 +361,insert,49.946,-1.0,-1.0,-1.0,-1.0,81.173,3.46246,2911,7789312 +362,search,6446.64,0.9211,0.106309,16.6174,17.3231,34.044,3.46292,2914,7789312 +363,insert,13.065,-1.0,-1.0,-1.0,-1.0,28.441,3.46777,2916,7803163 +364,search,6409.49,0.92126,0.106147,16.6027,17.3237,25.953,3.4678,2917,7803163 +365,insert,43.161,-1.0,-1.0,-1.0,-1.0,95.711,3.49232,2936,7863722 +366,search,6501.1,0.92189,0.10578,16.5382,17.2557,31.687,3.49248,2939,7863722 +367,insert,20.848,-1.0,-1.0,-1.0,-1.0,47.739,3.5051,2947,7895271 +368,search,6464.21,0.92231,0.105384,16.4794,17.2476,43.167,3.50559,2953,7895271 +369,insert,45.486,-1.0,-1.0,-1.0,-1.0,75.163,3.53114,2969,7961194 +370,search,6606.33,0.92276,0.104887,16.4305,17.2181,36.086,3.53153,2973,7961194 +371,insert,8.405,-1.0,-1.0,-1.0,-1.0,29.211,3.53516,2975,7970239 +372,search,6563.45,0.92302,0.104819,16.4187,17.2194,28.076,3.53537,2976,7970239 +373,insert,33.875,-1.0,-1.0,-1.0,-1.0,76.463,3.55161,2993,8010868 +374,search,6611.28,0.92338,0.104613,16.3686,17.1938,43.118,3.55243,2999,8010868 +375,insert,23.42,-1.0,-1.0,-1.0,-1.0,57.409,3.56424,3008,8040698 +376,search,6589.53,0.92343,0.104626,16.3219,17.1802,26.891,3.56447,3009,8040698 +377,insert,48.118,-1.0,-1.0,-1.0,-1.0,70.227,3.59258,3024,8104748 +378,search,6661.02,0.92402,0.10433,16.2207,17.1264,45.839,3.59342,3031,8104748 +379,insert,4.61,-1.0,-1.0,-1.0,-1.0,24.208,3.59637,3032,8109755 +380,search,6507.83,0.92399,0.104537,16.2237,17.1369,23.226,3.59637,3032,8109755 +381,insert,17.13,-1.0,-1.0,-1.0,-1.0,30.115,3.6053,3034,8130382 +382,search,6613.44,0.92429,0.104421,16.1941,17.136,33.58,3.60551,3037,8130382 +383,insert,18.332,-1.0,-1.0,-1.0,-1.0,34.139,3.61265,3041,8153290 +384,search,6583.82,0.92417,0.104416,16.1712,17.1088,23.402,3.61265,3041,8153290 +385,delete,9.626,-1.0,-1.0,-1.0,-1.0,23.899,3.61274,3041,8138873 +386,search,6662.56,0.92429,0.104363,16.1585,17.1077,23.218,3.61274,3041,8138873 +387,delete,13.844,-1.0,-1.0,-1.0,-1.0,21.758,3.61093,3041,8115069 +388,search,6621.21,0.92436,0.104261,16.1369,17.0894,22.527,3.61093,3041,8115069 +389,delete,9.509,-1.0,-1.0,-1.0,-1.0,21.637,3.61076,3041,8101157 +390,search,6663.5,0.92427,0.104427,16.1291,17.0901,23.027,3.61076,3041,8101157 +391,delete,55.533,-1.0,-1.0,-1.0,-1.0,97.083,3.5896,3034,8014644 +392,search,6573.87,0.92393,0.104185,16.2281,17.0745,38.48,3.58979,3037,8014644 +393,delete,21.682,-1.0,-1.0,-1.0,-1.0,33.913,3.5881,3036,7978358 +394,search,6616.64,0.92357,0.104264,16.2751,17.0997,28.252,3.5881,3037,7978358 +395,delete,14.187,-1.0,-1.0,-1.0,-1.0,47.181,3.58104,3034,7957094 +396,search,6555.08,0.92351,0.104265,16.2972,17.1093,23.817,3.58104,3034,7957094 +397,delete,78.959,-1.0,-1.0,-1.0,-1.0,125.744,3.547,3026,7823916 +398,search,6587.48,0.92355,0.104334,16.2962,17.1308,35.386,3.54721,3028,7823916 +399,delete,3.5,-1.0,-1.0,-1.0,-1.0,21.887,3.54721,3028,7818430 +400,search,6471.4,0.92349,0.104547,16.3008,17.1457,23.386,3.54721,3028,7818430 +401,delete,13.963,-1.0,-1.0,-1.0,-1.0,28.775,3.54402,3026,7800702 +402,search,6511.05,0.92329,0.104705,16.2919,17.1072,27.165,3.54412,3027,7800702 +403,delete,211.735,-1.0,-1.0,-1.0,-1.0,354.656,3.46246,2984,7517858 +404,search,6369.86,0.92226,0.105562,16.4731,17.2222,45.303,3.46302,2988,7517858 +405,delete,43.205,-1.0,-1.0,-1.0,-1.0,22.379,3.45942,2988,7451637 +406,search,6393.05,0.92236,0.105882,16.4494,17.2125,37.529,3.45974,2990,7451637 +407,delete,67.804,-1.0,-1.0,-1.0,-1.0,91.244,3.43441,2981,7360417 +408,search,6276.86,0.92208,0.106151,16.5097,17.2482,24.179,3.43441,2981,7360417 +409,delete,151.569,-1.0,-1.0,-1.0,-1.0,370.266,3.33999,2941,7131620 +410,search,6188.32,0.92191,0.105934,16.5616,17.2924,40.32,3.34004,2944,7131620 +411,delete,170.885,-1.0,-1.0,-1.0,-1.0,246.517,3.26409,2911,6867617 +412,search,5989.61,0.92112,0.106403,16.71,17.4123,27.642,3.26425,2912,6867617 +413,delete,12.987,-1.0,-1.0,-1.0,-1.0,21.12,3.26068,2912,6850098 +414,search,6057.78,0.92102,0.106415,16.7236,17.415,22.908,3.26068,2912,6850098 +415,delete,51.212,-1.0,-1.0,-1.0,-1.0,36.342,3.24227,2910,6782921 +416,search,6074.6,0.92088,0.106441,16.7495,17.4063,23.222,3.24227,2910,6782921 +417,delete,163.508,-1.0,-1.0,-1.0,-1.0,216.486,3.17649,2885,6562039 +418,search,5899.48,0.92057,0.106596,16.8039,17.4025,27.774,3.17667,2886,6562039 +419,delete,19.038,-1.0,-1.0,-1.0,-1.0,20.742,3.17271,2886,6536285 +420,search,5940.68,0.92055,0.10687,16.7943,17.4164,22.773,3.17271,2886,6536285 +421,delete,14.742,-1.0,-1.0,-1.0,-1.0,67.033,3.16346,2880,6510820 +422,search,5886.74,0.9206,0.106942,16.7772,17.4234,22.163,3.16346,2880,6510820 +423,delete,123.252,-1.0,-1.0,-1.0,-1.0,219.771,3.09202,2841,6334168 +424,search,5844.47,0.91968,0.107306,16.932,17.5263,22.323,3.09202,2841,6334168 +425,delete,16.823,-1.0,-1.0,-1.0,-1.0,20.065,3.08629,2841,6316443 +426,search,5750.99,0.91975,0.107274,16.9362,17.5664,22.66,3.08629,2841,6316443 +427,delete,45.275,-1.0,-1.0,-1.0,-1.0,20.307,3.07287,2841,6266345 +428,search,5815.04,0.91938,0.107645,17.0024,17.6113,22.647,3.07287,2841,6266345 +429,delete,371.157,-1.0,-1.0,-1.0,-1.0,308.726,2.89414,2781,5883847 +430,search,5511.1,0.9118,0.112421,18.0883,18.0513,33.338,2.8942,2783,5883847 +431,delete,64.132,-1.0,-1.0,-1.0,-1.0,125.418,2.85541,2765,5801380 +432,search,5446,0.9114,0.112888,18.1802,18.1542,22.066,2.85541,2765,5801380 +433,delete,145.931,-1.0,-1.0,-1.0,-1.0,337.764,2.76279,2727,5607567 +434,search,5375.56,0.90997,0.113676,18.3842,18.2312,38.084,2.76279,2729,5607567 +435,delete,82.531,-1.0,-1.0,-1.0,-1.0,35.338,2.72037,2726,5512176 +436,search,5331.14,0.9103,0.113314,18.3825,18.1838,36.526,2.72037,2728,5512176 +437,delete,10.128,-1.0,-1.0,-1.0,-1.0,32.441,2.71378,2727,5501141 +438,search,5307.26,0.9104,0.113317,18.357,18.1713,31.746,2.71378,2729,5501141 +439,delete,81.769,-1.0,-1.0,-1.0,-1.0,235.392,2.65255,2701,5369822 +440,search,5273.92,0.9099,0.113918,18.3904,18.1751,21.454,2.65255,2701,5369822 +441,delete,26.566,-1.0,-1.0,-1.0,-1.0,28.292,2.64012,2700,5338985 +442,search,5281.28,0.91066,0.112931,18.3401,18.1587,21.556,2.64012,2700,5338985 +443,delete,26.233,-1.0,-1.0,-1.0,-1.0,71.928,2.62514,2691,5307279 +444,search,5241.34,0.91018,0.113416,18.351,18.1364,21.281,2.62514,2691,5307279 +445,delete,32.484,-1.0,-1.0,-1.0,-1.0,22.359,2.61099,2690,5268382 +446,search,5218.38,0.91007,0.113422,18.3545,18.1094,20.919,2.61099,2690,5268382 +447,delete,283.568,-1.0,-1.0,-1.0,-1.0,311.703,2.44073,2617,4922787 +448,search,5016.43,0.90661,0.115778,18.8917,18.4635,19.99,2.44073,2617,4922787 +449,delete,30.299,-1.0,-1.0,-1.0,-1.0,18.274,2.42687,2617,4887227 +450,search,5037.85,0.90653,0.115758,18.8956,18.4511,20.94,2.42687,2617,4887227 +451,delete,88.039,-1.0,-1.0,-1.0,-1.0,96.046,2.38218,2600,4795082 +452,search,4951.65,0.90584,0.116415,19.0182,18.545,25.102,2.38235,2601,4795082 +453,delete,241.883,-1.0,-1.0,-1.0,-1.0,568.526,2.23352,2535,4500175 +454,search,4802.01,0.90362,0.118217,19.3241,18.744,85.502,2.23453,2543,4500175 +455,delete,31.898,-1.0,-1.0,-1.0,-1.0,25.816,2.2211,2542,4462648 +456,search,4772.79,0.90313,0.118316,19.4233,18.765,46.6,2.2211,2546,4462648 +457,delete,5.921,-1.0,-1.0,-1.0,-1.0,18.368,2.218,2546,4456761 +458,search,4803.16,0.90319,0.118192,19.4133,18.7674,26.117,2.218,2547,4456761 +459,delete,29.77,-1.0,-1.0,-1.0,-1.0,46.07,2.19848,2541,4419992 +460,search,4740.36,0.90301,0.118142,19.4714,18.8161,19.647,2.19848,2541,4419992 +461,delete,3.905,-1.0,-1.0,-1.0,-1.0,17.434,2.19698,2541,4415725 +462,search,4749.81,0.90301,0.118151,19.4547,18.7936,20.125,2.19698,2541,4415725 +463,delete,40.827,-1.0,-1.0,-1.0,-1.0,33.113,2.17563,2533,4370609 +464,search,4745.63,0.90217,0.118865,19.5389,18.8217,20.05,2.17563,2533,4370609 +465,delete,19.516,-1.0,-1.0,-1.0,-1.0,48.43,2.16387,2526,4345244 +466,search,4768.58,0.90165,0.119196,19.6592,18.8869,19.896,2.16387,2526,4345244 +467,delete,24.059,-1.0,-1.0,-1.0,-1.0,26.543,2.15404,2524,4319734 +468,search,4680.2,0.90095,0.119631,19.747,18.9275,19.757,2.15404,2524,4319734 +469,delete,16.12,-1.0,-1.0,-1.0,-1.0,36.118,2.14379,2519,4298361 +470,search,4704.45,0.90038,0.120023,19.8688,18.963,19.711,2.14379,2519,4298361 +471,delete,93.577,-1.0,-1.0,-1.0,-1.0,137.657,2.08388,2493,4188315 +472,search,4614.57,0.90016,0.120049,19.9511,19.0217,19.607,2.08388,2493,4188315 +473,delete,100.8,-1.0,-1.0,-1.0,-1.0,77.109,2.03248,2485,4074567 +474,search,4560.41,0.89965,0.120228,19.9979,19.0247,19.014,2.03248,2485,4074567 +475,delete,298.575,-1.0,-1.0,-1.0,-1.0,498.839,1.81887,2382,3691698 +476,search,4278.05,0.89501,0.124531,20.4571,19.2513,24.311,1.81907,2383,3691698 +477,delete,38.226,-1.0,-1.0,-1.0,-1.0,47.747,1.79992,2378,3642619 +478,search,4241.19,0.89459,0.124366,20.4724,19.2384,18.83,1.79992,2378,3642619 +479,delete,177.284,-1.0,-1.0,-1.0,-1.0,209.453,1.70522,2343,3421368 +480,search,4219.18,0.89438,0.124762,20.7086,19.4544,40.627,1.70522,2345,3421368 +481,delete,44.302,-1.0,-1.0,-1.0,-1.0,57.744,1.6844,2339,3378034 +482,search,4183.44,0.89415,0.124403,20.7203,19.4082,30.774,1.6844,2340,3378034 +483,delete,220.117,-1.0,-1.0,-1.0,-1.0,417.85,1.53445,2251,3115682 +484,search,3987.97,0.89109,0.125805,21.2638,19.7639,22.819,1.53445,2251,3115682 +485,delete,20.17,-1.0,-1.0,-1.0,-1.0,20.409,1.52863,2251,3094629 +486,search,3978.01,0.89107,0.125804,21.2578,19.7474,22.452,1.52863,2251,3094629 +487,delete,7.958,-1.0,-1.0,-1.0,-1.0,20.326,1.52635,2251,3086025 +488,search,3985.35,0.89081,0.125651,21.3205,19.757,22.542,1.52635,2251,3086025 +489,delete,27.968,-1.0,-1.0,-1.0,-1.0,20.545,1.51272,2251,3052105 +490,search,3931.46,0.89082,0.125455,21.3158,19.7487,22.455,1.51272,2251,3052105 +491,delete,10.966,-1.0,-1.0,-1.0,-1.0,26.058,1.50697,2249,3038974 +492,search,3910.51,0.89033,0.125482,21.4023,19.7797,23.532,1.50697,2249,3038974 +493,delete,107.845,-1.0,-1.0,-1.0,-1.0,126.473,1.44188,2231,2911063 +494,search,3857.27,0.88928,0.126265,21.5477,19.8369,21.727,1.44188,2231,2911063 +495,delete,17.588,-1.0,-1.0,-1.0,-1.0,28.953,1.43277,2228,2888785 +496,search,3878.22,0.88904,0.126532,21.5763,19.8066,23.131,1.43277,2228,2888785 +497,delete,55.098,-1.0,-1.0,-1.0,-1.0,52.812,1.40605,2218,2829718 +498,search,3860.99,0.88796,0.127378,21.7236,19.9286,23.274,1.40605,2218,2829718 +499,delete,18.283,-1.0,-1.0,-1.0,-1.0,25.672,1.40021,2217,2816082 +500,search,3869.31,0.88817,0.127224,21.7198,19.9164,22.361,1.40021,2217,2816082 +501,delete,25.638,-1.0,-1.0,-1.0,-1.0,39.187,1.38658,2213,2790880 +502,search,3855.82,0.88782,0.127605,21.7274,19.9472,22.819,1.38658,2213,2790880 +503,delete,15.861,-1.0,-1.0,-1.0,-1.0,19.787,1.38226,2213,2774459 +504,search,3840.28,0.88743,0.127828,21.7727,19.9551,22.28,1.38226,2213,2774459 +505,delete,47.021,-1.0,-1.0,-1.0,-1.0,79.519,1.34889,2199,2714683 +506,search,3839.39,0.88651,0.127664,21.9351,20.0096,22.157,1.34889,2199,2714683 +507,delete,29.974,-1.0,-1.0,-1.0,-1.0,46.549,1.33398,2191,2680986 +508,search,3755.68,0.88649,0.127324,21.9707,19.9876,21.827,1.33398,2191,2680986 +509,delete,15.196,-1.0,-1.0,-1.0,-1.0,22.862,1.32667,2190,2662966 +510,search,3789.24,0.88633,0.127474,22.0082,20.014,21.335,1.32667,2190,2662966 +511,delete,17.794,-1.0,-1.0,-1.0,-1.0,25.071,1.31822,2187,2642855 +512,search,3770.99,0.88587,0.128033,22.0562,20.0217,21.238,1.31822,2187,2642855 +513,insert,216.618,-1.0,-1.0,-1.0,-1.0,84.719,1.40184,2197,2906838 +514,search,3831.24,0.88583,0.128548,22.1189,20.1942,30.931,1.40197,2198,2906838 +515,insert,4.568,-1.0,-1.0,-1.0,-1.0,19.893,1.40303,2198,2913746 +516,search,3842.25,0.88589,0.12851,22.0965,20.1848,22.801,1.40303,2198,2913746 +517,insert,13.374,-1.0,-1.0,-1.0,-1.0,19.915,1.40599,2198,2936862 +518,search,3853.7,0.88644,0.128309,22.0379,20.1478,22.327,1.40599,2198,2936862 +519,insert,64.845,-1.0,-1.0,-1.0,-1.0,70.39,1.43109,2206,3009732 +520,search,3868.04,0.8877,0.128545,21.736,20.0812,43.392,1.43109,2210,3009732 +521,insert,10.486,-1.0,-1.0,-1.0,-1.0,20.569,1.43398,2210,3025906 +522,search,3890.39,0.88838,0.128311,21.6857,20.0501,22.663,1.43398,2210,3025906 +523,insert,28.977,-1.0,-1.0,-1.0,-1.0,34.614,1.44497,2212,3061899 +524,search,3877.83,0.88868,0.128471,21.5428,19.9892,28.86,1.44497,2213,3061899 +525,insert,28.344,-1.0,-1.0,-1.0,-1.0,32.159,1.45396,2215,3101209 +526,search,3888.43,0.88903,0.128127,21.4934,19.9562,22.532,1.45396,2215,3101209 +527,insert,380.829,-1.0,-1.0,-1.0,-1.0,144.479,1.6099,2239,3522334 +528,search,4069.67,0.89323,0.125636,20.9131,19.6622,41.523,1.6099,2242,3522334 +529,insert,213.606,-1.0,-1.0,-1.0,-1.0,112.67,1.71417,2254,3797294 +530,search,4234.4,0.89954,0.122822,19.9691,19.4243,102.32,1.71438,2263,3797294 +531,insert,50.109,-1.0,-1.0,-1.0,-1.0,21.041,1.73313,2263,3853781 +532,search,4238.7,0.89982,0.122781,19.9106,19.39,47.67,1.73313,2265,3853781 +533,insert,20.1,-1.0,-1.0,-1.0,-1.0,21.105,1.7397,2265,3873352 +534,search,4280.65,0.89994,0.122536,19.8717,19.3805,45.836,1.7397,2267,3873352 +535,insert,21.354,-1.0,-1.0,-1.0,-1.0,21.183,1.74695,2267,3893308 +536,search,4275.22,0.90055,0.122122,19.8322,19.3467,48.125,1.74695,2271,3893308 +537,insert,4.631,-1.0,-1.0,-1.0,-1.0,21.289,1.74874,2271,3901271 +538,search,4295.21,0.90035,0.122144,19.8387,19.3397,28.844,1.74874,2272,3901271 +539,insert,22.96,-1.0,-1.0,-1.0,-1.0,25.574,1.75654,2273,3925164 +540,search,4293.07,0.90047,0.122097,19.8243,19.3296,23.161,1.75654,2273,3925164 +541,insert,384.242,-1.0,-1.0,-1.0,-1.0,198.598,1.92758,2310,4320915 +542,search,4499.9,0.9038,0.119133,19.367,19.0611,42.613,1.92777,2314,4320915 +543,insert,33.782,-1.0,-1.0,-1.0,-1.0,21.396,1.94385,2314,4360814 +544,search,4480.11,0.90422,0.118577,19.3291,19.037,22.539,1.94385,2314,4360814 +545,insert,7.044,-1.0,-1.0,-1.0,-1.0,20.868,1.94689,2314,4370220 +546,search,4479.82,0.90431,0.118595,19.3191,19.028,23.428,1.94689,2314,4370220 +547,insert,129.649,-1.0,-1.0,-1.0,-1.0,44.573,2.00618,2323,4510675 +548,search,4557.1,0.90652,0.116442,19.0128,18.8588,23.019,2.00618,2323,4510675 +549,insert,215.424,-1.0,-1.0,-1.0,-1.0,71.1,2.1066,2334,4744845 +550,search,4671.34,0.90236,0.121089,19.8253,19.7451,35.14,2.1066,2336,4744845 +551,insert,18.923,-1.0,-1.0,-1.0,-1.0,44.352,2.11815,2339,4771433 +552,search,4659.4,0.90216,0.12128,19.8288,19.7386,23.616,2.11815,2339,4771433 +553,insert,12.069,-1.0,-1.0,-1.0,-1.0,21.351,2.12274,2339,4782909 +554,search,4669.05,0.90243,0.121182,19.7827,19.7131,23.493,2.12274,2339,4782909 +555,insert,365.151,-1.0,-1.0,-1.0,-1.0,132.842,2.29217,2369,5180322 +556,search,4884.25,0.90891,0.114775,19.1523,19.3571,31.407,2.29242,2373,5180322 +557,insert,23.265,-1.0,-1.0,-1.0,-1.0,15.551,2.30357,2373,5203220 +558,search,4846.38,0.90929,0.114494,19.1117,19.3478,16.52,2.30357,2373,5203220 +559,insert,5.903,-1.0,-1.0,-1.0,-1.0,14.952,2.3064,2373,5210154 +560,search,4880.57,0.90951,0.114367,19.11,19.3595,16.997,2.3064,2373,5210154 +561,insert,5.952,-1.0,-1.0,-1.0,-1.0,15.006,2.3087,2373,5215426 +562,search,4893.18,0.90959,0.114279,19.1028,19.3568,16.976,2.3087,2373,5215426 +563,insert,41.468,-1.0,-1.0,-1.0,-1.0,22.02,2.32189,2374,5252726 +564,search,4896.46,0.90971,0.114186,19.0857,19.3503,16.894,2.32189,2374,5252726 +565,insert,196.409,-1.0,-1.0,-1.0,-1.0,82.645,2.40987,2386,5447274 +566,search,4968.44,0.9101,0.11344,19.0621,19.3445,32.146,2.40991,2388,5447274 +567,insert,11.764,-1.0,-1.0,-1.0,-1.0,15.626,2.41591,2388,5463135 +568,search,5015.08,0.90994,0.113561,19.0865,19.3717,22.62,2.41591,2389,5463135 +569,insert,12.888,-1.0,-1.0,-1.0,-1.0,15.238,2.42097,2389,5478168 +570,search,5015.61,0.90989,0.113536,19.0676,19.3416,17.023,2.42097,2389,5478168 +571,insert,13.664,-1.0,-1.0,-1.0,-1.0,23.146,2.42736,2390,5492309 +572,search,4959.01,0.90948,0.113815,19.1322,19.4145,16.591,2.42736,2390,5492309 +573,insert,53.979,-1.0,-1.0,-1.0,-1.0,47.167,2.45387,2397,5554599 +574,search,5005.37,0.91006,0.113295,19.048,19.3634,16.594,2.45387,2397,5554599 +575,insert,42.931,-1.0,-1.0,-1.0,-1.0,35.424,2.47493,2401,5604500 +576,search,5060.18,0.91059,0.113141,18.9662,19.3076,17.441,2.47493,2401,5604500 +577,insert,35.974,-1.0,-1.0,-1.0,-1.0,41.395,2.48897,2410,5638834 +578,search,5106.52,0.91101,0.112814,18.9403,19.3168,25.76,2.48926,2412,5638834 +579,insert,568.125,-1.0,-1.0,-1.0,-1.0,623.967,2.76616,2555,6229778 +580,search,5471.26,0.91415,0.109214,18.5775,19.1598,55.993,2.76635,2563,6229778 +581,insert,25.363,-1.0,-1.0,-1.0,-1.0,22.009,2.77694,2564,6261240 +582,search,5475.41,0.91407,0.109449,18.5712,19.1734,27.141,2.77703,2565,6261240 +583,insert,19.461,-1.0,-1.0,-1.0,-1.0,22.48,2.78533,2566,6283315 +584,search,5481.88,0.91405,0.109621,18.5519,19.1683,18.267,2.78533,2566,6283315 +585,insert,210.653,-1.0,-1.0,-1.0,-1.0,213.292,2.91052,2603,6556101 +586,search,5611,0.91535,0.108988,18.268,18.9414,84.965,2.91143,2620,6556101 +587,insert,25.757,-1.0,-1.0,-1.0,-1.0,41.196,2.92609,2626,6587187 +588,search,5658.93,0.91582,0.10845,18.2069,18.9133,27.821,2.92649,2628,6587187 +589,insert,47.739,-1.0,-1.0,-1.0,-1.0,39.051,2.94943,2633,6631526 +590,search,5707.69,0.91604,0.108224,18.1832,18.9107,24.102,2.94943,2634,6631526 +591,insert,401.419,-1.0,-1.0,-1.0,-1.0,406.047,3.1542,2726,7108942 +592,search,6049.9,0.91912,0.106213,17.7528,18.7515,84.503,3.15512,2740,7108942 +593,insert,143.626,-1.0,-1.0,-1.0,-1.0,178.711,3.24043,2773,7303976 +594,search,6160.48,0.92026,0.105245,17.512,18.5989,77.824,3.24093,2786,7303976 +595,insert,4.68,-1.0,-1.0,-1.0,-1.0,26.905,3.24271,2788,7309244 +596,search,6139.19,0.92031,0.105209,17.505,18.6021,24.794,3.24271,2789,7309244 +597,insert,159.787,-1.0,-1.0,-1.0,-1.0,214.74,3.34756,2831,7542477 +598,search,6269.41,0.92211,0.104185,17.2125,18.4905,83.117,3.34799,2847,7542477 +599,insert,93.319,-1.0,-1.0,-1.0,-1.0,154.705,3.39511,2884,7654438 +600,search,6454.26,0.9227,0.103902,17.1277,18.4557,42.568,3.39574,2890,7654438 +601,insert,52.34,-1.0,-1.0,-1.0,-1.0,60.675,3.42099,2901,7717936 +602,search,6445.1,0.92327,0.103223,17.0446,18.3802,24.408,3.42106,2902,7717936 +603,insert,6.521,-1.0,-1.0,-1.0,-1.0,18.778,3.4237,2902,7723521 +604,search,6436.21,0.92321,0.103306,17.0501,18.3823,24.987,3.42373,2903,7723521 +605,insert,43.141,-1.0,-1.0,-1.0,-1.0,67.409,3.44283,2916,7767404 +606,search,6473.86,0.92325,0.103147,17.0378,18.3863,23.632,3.44289,2917,7767404 +607,insert,42.044,-1.0,-1.0,-1.0,-1.0,44.809,3.46557,2924,7826115 +608,search,6404.35,0.92286,0.103586,17.0766,18.4001,29.926,3.46591,2926,7826115 +609,insert,145.003,-1.0,-1.0,-1.0,-1.0,214.242,3.55411,2964,8036351 +610,search,6589.82,0.92377,0.103196,16.8412,18.2472,71.459,3.55522,2977,8036351 +611,insert,17.316,-1.0,-1.0,-1.0,-1.0,51.176,3.56409,2985,8060364 +612,search,6698,0.92411,0.102971,16.8145,18.2273,31.359,3.56429,2988,8060364 +613,insert,158.522,-1.0,-1.0,-1.0,-1.0,242.084,3.65251,3035,8256083 +614,search,6821.4,0.92479,0.102962,16.6784,18.1367,70.959,3.65379,3050,8256083 +615,insert,284.625,-1.0,-1.0,-1.0,-1.0,482.9,3.8257,3137,8625707 +616,search,7052.77,0.92679,0.101109,16.325,17.9032,167.788,3.82824,3176,8625707 +617,insert,244.245,-1.0,-1.0,-1.0,-1.0,413.471,3.97388,3253,8949227 +618,search,7236.15,0.92827,0.100513,16.023,17.777,167.016,3.97571,3286,8949227 +619,insert,164.41,-1.0,-1.0,-1.0,-1.0,206.491,4.07759,3326,9195551 +620,search,7414.81,0.92908,0.100124,15.9455,17.7272,111.4,4.07959,3350,9195551 +621,insert,28.922,-1.0,-1.0,-1.0,-1.0,62.65,4.09275,3360,9232372 +622,search,7499.19,0.92951,0.0998432,15.8898,17.7093,33.405,4.09307,3363,9232372 +623,insert,20.06,-1.0,-1.0,-1.0,-1.0,35.626,4.10154,3367,9253561 +624,search,7487.6,0.9298,0.099624,15.8472,17.6899,36.533,4.1018,3370,9253561 +625,insert,58.792,-1.0,-1.0,-1.0,-1.0,102.762,4.13549,3387,9331230 +626,search,7472.93,0.9303,0.0992441,15.7396,17.637,61.726,4.13592,3396,9331230 +627,insert,38.4,-1.0,-1.0,-1.0,-1.0,93.687,4.15357,3415,9374063 +628,search,7566.73,0.93044,0.0992346,15.7047,17.6331,30.966,4.15366,3417,9374063 +629,insert,11.209,-1.0,-1.0,-1.0,-1.0,42.914,4.16235,3421,9387598 +630,search,7563.45,0.93059,0.0990341,15.676,17.602,24.018,4.16235,3421,9387598 +631,insert,29.034,-1.0,-1.0,-1.0,-1.0,65.991,4.17584,3430,9421724 +632,search,7624.4,0.93073,0.0988847,15.6555,17.5843,32.226,4.17603,3433,9421724 +633,insert,37.846,-1.0,-1.0,-1.0,-1.0,77.568,4.1924,3451,9461430 +634,search,7455.1,0.93087,0.0986654,15.604,17.5313,30.964,4.19244,3453,9461430 +635,insert,20.955,-1.0,-1.0,-1.0,-1.0,43.175,4.20168,3458,9479469 +636,search,7618.31,0.93082,0.0988289,15.5745,17.5238,22.974,4.20168,3458,9479469 +637,insert,354.854,-1.0,-1.0,-1.0,-1.0,602.255,4.3818,3585,9885997 +638,search,7889.22,0.93277,0.0976526,15.1912,17.3042,125.037,4.38387,3614,9885997 +639,insert,352.908,-1.0,-1.0,-1.0,-1.0,588.143,4.56701,3747,10292043 +640,search,8241.55,0.9349,0.0958349,14.8576,17.1239,120.571,4.56941,3771,10292043 +641,delete,142.933,-1.0,-1.0,-1.0,-1.0,235.89,4.52861,3751,10096584 +642,search,8222.28,0.93484,0.0958622,14.8691,17.1068,27.634,4.52861,3751,10096584 +643,delete,7.853,-1.0,-1.0,-1.0,-1.0,25.147,4.52861,3751,10084840 +644,search,8200.7,0.93481,0.0959495,14.8736,17.1182,27.394,4.52861,3751,10084840 +645,delete,11.082,-1.0,-1.0,-1.0,-1.0,25.018,4.52861,3751,10069802 +646,search,8193.05,0.93474,0.0960169,14.8784,17.121,28.711,4.52861,3751,10069802 +647,delete,56.577,-1.0,-1.0,-1.0,-1.0,191.543,4.50509,3737,9990953 +648,search,8236.14,0.93459,0.0962715,14.8839,17.1118,29.59,4.50509,3737,9990953 +649,delete,28.536,-1.0,-1.0,-1.0,-1.0,37.769,4.50331,3736,9951625 +650,search,8177.89,0.93455,0.0965273,14.8786,17.1195,28.177,4.50331,3736,9951625 +651,delete,15.628,-1.0,-1.0,-1.0,-1.0,24.947,4.50153,3736,9927065 +652,search,8208.91,0.93437,0.09662,14.9451,17.1622,28.257,4.50153,3736,9927065 +653,delete,70.201,-1.0,-1.0,-1.0,-1.0,171.759,4.47255,3719,9831098 +654,search,8035.3,0.93415,0.0967345,14.9914,17.1863,28.773,4.47255,3719,9831098 +655,delete,296.053,-1.0,-1.0,-1.0,-1.0,461.123,4.37901,3665,9462172 +656,search,7874.09,0.93252,0.0981123,15.2711,17.3412,32.483,4.37909,3666,9462172 +657,delete,178.075,-1.0,-1.0,-1.0,-1.0,168.042,4.31189,3613,9218902 +658,search,7754.15,0.92942,0.100426,15.7002,17.5837,26.847,4.31189,3613,9218902 +659,delete,86.669,-1.0,-1.0,-1.0,-1.0,196.409,4.27709,3594,9106546 +660,search,7569.22,0.92922,0.100667,15.7652,17.6157,27.088,4.27709,3594,9106546 +661,delete,35.586,-1.0,-1.0,-1.0,-1.0,45.12,4.27035,3592,9059776 +662,search,7647.81,0.92906,0.100921,15.753,17.5882,28.303,4.27035,3592,9059776 +663,delete,68.719,-1.0,-1.0,-1.0,-1.0,73.66,4.25159,3585,8990616 +664,search,7622.84,0.9287,0.101593,15.7675,17.5999,45.303,4.25183,3586,8990616 +665,delete,47.062,-1.0,-1.0,-1.0,-1.0,100.588,4.23535,3580,8937437 +666,search,7589.97,0.92862,0.101667,15.766,17.5968,27.767,4.23535,3580,8937437 +667,delete,155.598,-1.0,-1.0,-1.0,-1.0,247.156,4.16386,3554,8766390 +668,search,7446.49,0.92828,0.10174,15.8049,17.6173,26.342,4.16386,3554,8766390 +669,delete,175.725,-1.0,-1.0,-1.0,-1.0,398.06,4.081,3516,8532008 +670,search,7362.52,0.92793,0.102049,15.8911,17.67,26.88,4.081,3516,8532008 +671,delete,36.453,-1.0,-1.0,-1.0,-1.0,57.894,4.06979,3513,8489178 +672,search,7383.71,0.92769,0.102237,15.9375,17.7247,27.484,4.06979,3513,8489178 +673,delete,56.805,-1.0,-1.0,-1.0,-1.0,89.114,4.04865,3505,8421866 +674,search,7330.79,0.92777,0.102564,15.9489,17.7549,26.643,4.04865,3505,8421866 +675,delete,109.909,-1.0,-1.0,-1.0,-1.0,127.548,4.01288,3491,8288319 +676,search,7281.69,0.92717,0.103284,16.0209,17.826,25.753,4.01288,3491,8288319 +677,delete,144.042,-1.0,-1.0,-1.0,-1.0,137.403,3.93361,3479,8072197 +678,search,7209.72,0.9297,0.100816,15.5078,17.2749,26.297,3.93361,3479,8072197 +679,delete,27.589,-1.0,-1.0,-1.0,-1.0,62.206,3.92247,3477,8036947 +680,search,7195.37,0.92963,0.100846,15.519,17.2631,26.874,3.92247,3477,8036947 +681,delete,8.78,-1.0,-1.0,-1.0,-1.0,22.945,3.92138,3477,8026197 +682,search,7174.4,0.92975,0.100675,15.5158,17.2512,26.695,3.92138,3477,8026197 +683,delete,263.284,-1.0,-1.0,-1.0,-1.0,119.961,3.82631,3460,7744229 +684,search,7053.95,0.92851,0.101597,15.6704,17.29,31.031,3.82637,3461,7744229 +685,delete,207.559,-1.0,-1.0,-1.0,-1.0,92.149,3.72764,3447,7541066 +686,search,6891.36,0.92545,0.104202,16.0531,17.5897,30.643,3.72778,3448,7541066 +687,delete,18.352,-1.0,-1.0,-1.0,-1.0,30.312,3.7215,3447,7522190 +688,search,6806.83,0.92524,0.104505,16.0733,17.6026,25.989,3.7215,3447,7522190 +689,delete,101.58,-1.0,-1.0,-1.0,-1.0,257.473,3.66252,3412,7409400 +690,search,6771.3,0.92423,0.105035,16.2684,17.735,26.114,3.66252,3412,7409400 +691,delete,39.46,-1.0,-1.0,-1.0,-1.0,22.478,3.64817,3412,7375648 +692,search,6791.02,0.92404,0.105172,16.2967,17.7585,25.468,3.64817,3412,7375648 +693,delete,154.595,-1.0,-1.0,-1.0,-1.0,143.729,3.58232,3401,7222068 +694,search,6759.56,0.92421,0.104959,16.3403,17.7852,25.007,3.58232,3401,7222068 +695,delete,22.268,-1.0,-1.0,-1.0,-1.0,68.514,3.5705,3398,7196331 +696,search,6723.8,0.92455,0.104752,16.2801,17.7698,24.677,3.5705,3398,7196331 +697,delete,28.183,-1.0,-1.0,-1.0,-1.0,42.716,3.55968,3396,7170716 +698,search,6631.32,0.92453,0.104697,16.2973,17.7699,25.571,3.55968,3396,7170716 +699,delete,11.868,-1.0,-1.0,-1.0,-1.0,71.918,3.55033,3393,7155255 +700,search,6686.68,0.92496,0.104135,16.2667,17.7487,28.604,3.55033,3393,7155255 +701,delete,57.228,-1.0,-1.0,-1.0,-1.0,22.78,3.53166,3393,7097733 +702,search,6721.73,0.92479,0.104303,16.2694,17.7391,25.404,3.53166,3393,7097733 +703,delete,170.891,-1.0,-1.0,-1.0,-1.0,264.899,3.44243,3353,6924172 +704,search,6555.66,0.92476,0.103989,16.2973,17.6906,29.983,3.44253,3354,6924172 +705,delete,27.13,-1.0,-1.0,-1.0,-1.0,21.651,3.4295,3354,6896276 +706,search,6546.15,0.92462,0.103843,16.3117,17.7024,24.136,3.4295,3354,6896276 +707,delete,497.346,-1.0,-1.0,-1.0,-1.0,850.655,3.13885,3211,6385507 +708,search,6181.27,0.92174,0.106402,16.616,17.7932,52.009,3.13929,3215,6385507 +709,delete,163.685,-1.0,-1.0,-1.0,-1.0,520.309,3.04719,3155,6207658 +710,search,6072.08,0.92018,0.107048,16.918,17.971,47.78,3.04737,3158,6207658 +711,delete,44.896,-1.0,-1.0,-1.0,-1.0,40.848,3.0294,3156,6162720 +712,search,5983.77,0.9202,0.106823,16.9149,17.9647,31.274,3.0294,3157,6162720 +713,delete,231.028,-1.0,-1.0,-1.0,-1.0,464.259,2.90718,3103,5927803 +714,search,5915.22,0.9185,0.108691,17.1383,18.1629,28.775,2.90731,3104,5927803 +715,delete,26.325,-1.0,-1.0,-1.0,-1.0,48.004,2.8933,3100,5895666 +716,search,5780.71,0.91828,0.108669,17.1771,18.1635,22.344,2.8933,3100,5895666 +717,delete,26.131,-1.0,-1.0,-1.0,-1.0,28.92,2.88731,3099,5868774 +718,search,5750.69,0.91784,0.109159,17.2167,18.1937,23.101,2.88731,3099,5868774 +719,delete,334.482,-1.0,-1.0,-1.0,-1.0,541.185,2.71899,3004,5533540 +720,search,5646.44,0.91553,0.111663,17.4607,18.3258,33.953,2.71935,3006,5533540 +721,delete,98.82,-1.0,-1.0,-1.0,-1.0,138.326,2.67155,2985,5418387 +722,search,5599.37,0.91516,0.112038,17.5501,18.3596,22.42,2.67155,2985,5418387 +723,delete,18.884,-1.0,-1.0,-1.0,-1.0,25.454,2.66433,2984,5398291 +724,search,5554.33,0.91505,0.112011,17.561,18.3488,22.244,2.66433,2984,5398291 +725,delete,104.715,-1.0,-1.0,-1.0,-1.0,211.499,2.60872,2965,5273546 +726,search,5507.66,0.91425,0.112385,17.669,18.3741,44.306,2.60872,2967,5273546 +727,delete,78.715,-1.0,-1.0,-1.0,-1.0,49.009,2.56985,2962,5180937 +728,search,5424.87,0.91391,0.112596,17.7196,18.4468,38.145,2.56985,2964,5180937 +729,delete,94.683,-1.0,-1.0,-1.0,-1.0,168.179,2.51763,2939,5079524 +730,search,5358.44,0.91344,0.113069,17.7963,18.4727,21.825,2.51763,2939,5079524 +731,delete,76.447,-1.0,-1.0,-1.0,-1.0,19.505,2.49582,2939,5019265 +732,search,5351.1,0.91234,0.114484,17.8794,18.5083,21.816,2.49582,2939,5019265 +733,delete,80.774,-1.0,-1.0,-1.0,-1.0,81.81,2.46434,2932,4955565 +734,search,5362.33,0.91201,0.114501,17.9772,18.6216,22.209,2.46434,2932,4955565 +735,delete,146.477,-1.0,-1.0,-1.0,-1.0,542.721,2.37452,2878,4776948 +736,search,5248.76,0.91397,0.112648,18.0921,18.9202,39.16,2.37508,2880,4776948 +737,delete,107.017,-1.0,-1.0,-1.0,-1.0,112.156,2.32613,2870,4654026 +738,search,5204.25,0.91525,0.110854,17.812,18.6044,28.817,2.32613,2871,4654026 +739,delete,53.935,-1.0,-1.0,-1.0,-1.0,84.853,2.29511,2859,4589888 +740,search,5165.73,0.91548,0.110385,17.831,18.5932,28.743,2.29511,2860,4589888 +741,delete,144.109,-1.0,-1.0,-1.0,-1.0,206.776,2.21219,2834,4430862 +742,search,5075.53,0.9147,0.110522,17.8879,18.5051,27.773,2.21224,2835,4430862 +743,delete,181.883,-1.0,-1.0,-1.0,-1.0,361.701,2.11645,2787,4237049 +744,search,4944.35,0.91312,0.111923,18.0071,18.5605,38.518,2.1165,2789,4237049 +745,delete,231.196,-1.0,-1.0,-1.0,-1.0,529.938,1.98718,2718,4000195 +746,search,4862.79,0.91113,0.113251,18.398,18.7438,19.837,1.98718,2718,4000195 +747,delete,168.086,-1.0,-1.0,-1.0,-1.0,262.252,1.89345,2673,3803954 +748,search,4744.29,0.91022,0.113322,18.5713,18.7849,33.994,1.89362,2675,3803954 +749,delete,68.386,-1.0,-1.0,-1.0,-1.0,74.075,1.85842,2665,3733214 +750,search,4725.48,0.90995,0.113552,18.6939,18.8838,19.07,1.85842,2665,3733214 +751,delete,19.699,-1.0,-1.0,-1.0,-1.0,32.319,1.84728,2662,3709324 +752,search,4684.89,0.9098,0.113511,18.7632,18.907,18.509,1.84728,2662,3709324 +753,delete,51.525,-1.0,-1.0,-1.0,-1.0,133.733,1.81412,2647,3649123 +754,search,4669.61,0.90854,0.114874,18.9421,19.0797,28.183,1.81412,2648,3649123 +755,delete,26.644,-1.0,-1.0,-1.0,-1.0,26.477,1.80274,2647,3621475 +756,search,4665.78,0.90844,0.114648,18.9399,19.0191,20.158,1.80274,2647,3621475 +757,delete,34.524,-1.0,-1.0,-1.0,-1.0,38.622,1.79004,2643,3594479 +758,search,4598.75,0.9083,0.114524,18.998,19.0471,19.503,1.79004,2643,3594479 +759,delete,24.848,-1.0,-1.0,-1.0,-1.0,27.947,1.78077,2641,3569055 +760,search,4650.59,0.90788,0.114867,19.0391,19.0473,19.596,1.78077,2641,3569055 +761,delete,42.028,-1.0,-1.0,-1.0,-1.0,32.075,1.76395,2639,3527896 +762,search,4618.87,0.90728,0.115165,19.1011,19.0604,19.695,1.76395,2639,3527896 +763,delete,20.899,-1.0,-1.0,-1.0,-1.0,31.174,1.75444,2637,3509970 +764,search,4538.07,0.90714,0.115309,19.138,19.0931,18.948,1.75444,2637,3509970 +765,delete,305.617,-1.0,-1.0,-1.0,-1.0,440.663,1.58012,2515,3187549 +766,search,4380.39,0.90402,0.117696,19.5296,19.2017,17.498,1.58012,2515,3187549 +767,delete,337.969,-1.0,-1.0,-1.0,-1.0,561.444,1.37103,2361,2822906 +768,search,4032.46,0.89765,0.123147,20.4353,19.7379,26.292,1.37108,2362,2822906 +769,insert,5.77,-1.0,-1.0,-1.0,-1.0,14.927,1.37227,2362,2832899 +770,search,4015.63,0.89807,0.12282,20.3743,19.7123,17.225,1.37227,2362,2832899 +771,insert,32.301,-1.0,-1.0,-1.0,-1.0,14.4,1.38097,2362,2863523 +772,search,4071.09,0.89845,0.122622,20.341,19.743,17.245,1.38097,2362,2863523 +773,insert,50.326,-1.0,-1.0,-1.0,-1.0,15.302,1.39522,2362,2925169 +774,search,4151.4,0.89971,0.121515,20.1415,19.628,17.289,1.39522,2362,2925169 +775,insert,37.1,-1.0,-1.0,-1.0,-1.0,36.768,1.40695,2365,2961356 +776,search,4146.04,0.90001,0.121711,20.0759,19.6566,17.153,1.40695,2365,2961356 +777,insert,30.564,-1.0,-1.0,-1.0,-1.0,14.547,1.41501,2365,2998678 +778,search,4127.45,0.90106,0.12055,19.9366,19.5541,17.293,1.41501,2365,2998678 +779,insert,11.856,-1.0,-1.0,-1.0,-1.0,14.224,1.41767,2365,3011024 +780,search,4151.64,0.90163,0.120271,19.8475,19.5228,16.983,1.41767,2365,3011024 +781,insert,4.802,-1.0,-1.0,-1.0,-1.0,14.164,1.41842,2365,3019515 +782,search,4145.24,0.90177,0.120171,19.8358,19.5165,16.785,1.41842,2365,3019515 +783,insert,51.63,-1.0,-1.0,-1.0,-1.0,14.658,1.43242,2365,3082298 +784,search,4093.16,0.9025,0.119622,19.6864,19.4547,16.288,1.43242,2365,3082298 +785,insert,34.324,-1.0,-1.0,-1.0,-1.0,39.865,1.44674,2367,3122090 +786,search,4156.03,0.9038,0.118822,19.513,19.4034,40.098,1.44674,2370,3122090 +787,insert,19.991,-1.0,-1.0,-1.0,-1.0,14.754,1.45222,2370,3140294 +788,search,4197.54,0.90387,0.11911,19.478,19.3902,35.417,1.45222,2373,3140294 +789,insert,6.632,-1.0,-1.0,-1.0,-1.0,14.817,1.45353,2373,3147819 +790,search,4203.83,0.904,0.118994,19.4362,19.3607,17.159,1.45353,2373,3147819 +791,insert,31.773,-1.0,-1.0,-1.0,-1.0,14.445,1.46095,2373,3180668 +792,search,4172.82,0.90406,0.118894,19.4088,19.3678,17.396,1.46095,2373,3180668 +793,insert,2.211,-1.0,-1.0,-1.0,-1.0,14.298,1.46135,2373,3183235 +794,search,4174.52,0.90407,0.118933,19.4056,19.367,17.24,1.46135,2373,3183235 +795,insert,59.508,-1.0,-1.0,-1.0,-1.0,21.118,1.47987,2374,3242089 +796,search,4206.67,0.90483,0.118308,19.3224,19.3406,17.196,1.47987,2374,3242089 +797,insert,4.242,-1.0,-1.0,-1.0,-1.0,14.387,1.48068,2374,3247192 +798,search,4225.86,0.90487,0.118229,19.3215,19.3404,16.717,1.48068,2374,3247192 +799,insert,6.142,-1.0,-1.0,-1.0,-1.0,14.28,1.48209,2374,3254626 +800,search,4222.47,0.90503,0.118248,19.2935,19.3418,16.41,1.48209,2374,3254626 +801,insert,18.09,-1.0,-1.0,-1.0,-1.0,14.309,1.48772,2374,3274953 +802,search,4215.12,0.90535,0.118337,19.2112,19.3056,16.831,1.48772,2374,3274953 +803,insert,858.198,-1.0,-1.0,-1.0,-1.0,474.775,1.80987,2456,4032688 +804,search,4661.42,0.9117,0.113307,18.4461,18.9365,124.336,1.81001,2477,4032688 +805,insert,19.606,-1.0,-1.0,-1.0,-1.0,15.399,1.81516,2477,4050220 +806,search,4653.6,0.91179,0.113178,18.454,18.9645,31.74,1.81516,2480,4050220 +807,insert,19.143,-1.0,-1.0,-1.0,-1.0,15.387,1.8222,2480,4067940 +808,search,4673.31,0.91169,0.113337,18.4514,18.9663,18.693,1.8222,2480,4067940 +809,insert,33.89,-1.0,-1.0,-1.0,-1.0,23.148,1.83399,2482,4099369 +810,search,4682.23,0.91215,0.113036,18.398,18.94,17.821,1.83399,2482,4099369 +811,insert,30.122,-1.0,-1.0,-1.0,-1.0,15.157,1.84486,2482,4129509 +812,search,4839.7,0.91265,0.112623,18.386,18.9626,17.686,1.84486,2482,4129509 +813,insert,48.64,-1.0,-1.0,-1.0,-1.0,19.853,1.86459,2484,4178669 +814,search,4688.91,0.91385,0.11152,18.266,18.8741,17.238,1.86459,2484,4178669 +815,insert,2,-1.0,-1.0,-1.0,-1.0,14.997,1.86549,2484,4180960 +816,search,4680.62,0.91387,0.111388,18.268,18.8732,18.217,1.86549,2484,4180960 +817,insert,96.773,-1.0,-1.0,-1.0,-1.0,92.701,1.89685,2498,4255359 +818,search,4758.83,0.91386,0.111631,18.2122,18.8355,30.532,1.89696,2500,4255359 +819,insert,23.657,-1.0,-1.0,-1.0,-1.0,15.448,1.90449,2500,4272706 +820,search,4738.63,0.91431,0.111261,18.1731,18.8073,18.665,1.90449,2500,4272706 +821,insert,18.751,-1.0,-1.0,-1.0,-1.0,22.676,1.9109,2501,4287851 +822,search,4786.77,0.91423,0.111298,18.1875,18.8322,18.792,1.9109,2501,4287851 +823,insert,39.543,-1.0,-1.0,-1.0,-1.0,15.691,1.9251,2501,4322788 +824,search,4773.06,0.91435,0.111468,18.1271,18.8409,18.278,1.9251,2501,4322788 +825,insert,79.886,-1.0,-1.0,-1.0,-1.0,35.168,1.95584,2504,4396408 +826,search,4790.89,0.91411,0.111693,18.1493,18.8883,17.775,1.95584,2504,4396408 +827,insert,21.744,-1.0,-1.0,-1.0,-1.0,22.348,1.96382,2505,4415721 +828,search,4762.18,0.91389,0.112095,18.1568,18.8748,17.943,1.96382,2505,4415721 +829,insert,477.33,-1.0,-1.0,-1.0,-1.0,190.783,2.14384,2538,4832079 +830,search,5005.03,0.91649,0.11002,17.7732,18.7324,41.275,2.14432,2544,4832079 +831,insert,45.526,-1.0,-1.0,-1.0,-1.0,22.44,2.15861,2545,4864525 +832,search,5012.93,0.91665,0.109879,17.7505,18.7421,21.307,2.15863,2546,4864525 +833,insert,10.195,-1.0,-1.0,-1.0,-1.0,19.804,2.16133,2547,4874443 +834,search,4963.79,0.91661,0.109869,17.7472,18.739,18.811,2.16133,2547,4874443 +835,insert,73.609,-1.0,-1.0,-1.0,-1.0,33.959,2.18886,2551,4938267 +836,search,4967.3,0.91733,0.109362,17.6679,18.6926,18.339,2.18886,2551,4938267 +837,insert,26.853,-1.0,-1.0,-1.0,-1.0,32.691,2.19807,2554,4961147 +838,search,5003.34,0.91724,0.109492,17.6587,18.6898,18.003,2.19807,2554,4961147 +839,insert,75.917,-1.0,-1.0,-1.0,-1.0,50.236,2.22907,2561,5033740 +840,search,5107.62,0.91872,0.108374,17.5235,18.6423,18.063,2.22907,2561,5033740 +841,insert,52.284,-1.0,-1.0,-1.0,-1.0,35.702,2.24836,2564,5078736 +842,search,5123.7,0.91902,0.10824,17.4628,18.5911,22.214,2.2484,2565,5078736 +843,insert,458.377,-1.0,-1.0,-1.0,-1.0,214.459,2.41988,2601,5467376 +844,search,5343.05,0.92104,0.106554,17.1631,18.3889,76.018,2.42027,2614,5467376 +845,insert,384.143,-1.0,-1.0,-1.0,-1.0,252.852,2.57785,2663,5815547 +846,search,5495.24,0.92302,0.105324,16.8484,18.2583,78.75,2.57801,2676,5815547 +847,insert,7.162,-1.0,-1.0,-1.0,-1.0,18.211,2.58062,2676,5821782 +848,search,5420.75,0.92329,0.105248,16.8382,18.2571,27.881,2.58066,2678,5821782 +849,insert,2.423,-1.0,-1.0,-1.0,-1.0,21.81,2.58145,2679,5825594 +850,search,5452.44,0.92317,0.105286,16.8356,18.2627,19.281,2.58145,2679,5825594 +851,insert,10.562,-1.0,-1.0,-1.0,-1.0,17.465,2.58573,2679,5834880 +852,search,5445.77,0.92327,0.105229,16.8151,18.2508,19.646,2.58573,2679,5834880 +853,insert,27.076,-1.0,-1.0,-1.0,-1.0,17.598,2.59607,2679,5860274 +854,search,5456.97,0.9235,0.104978,16.7952,18.2678,20.035,2.59607,2679,5860274 +855,insert,10.598,-1.0,-1.0,-1.0,-1.0,19.674,2.59899,2680,5866064 +856,search,5483.03,0.92346,0.104933,16.797,18.2714,20.159,2.59899,2680,5866064 +857,insert,19.954,-1.0,-1.0,-1.0,-1.0,17.703,2.60415,2680,5884456 +858,search,5499.83,0.92373,0.10477,16.7585,18.2398,20.224,2.60415,2680,5884456 +859,insert,45.136,-1.0,-1.0,-1.0,-1.0,41.726,2.61837,2685,5916786 +860,search,5468.18,0.92388,0.104375,16.7233,18.2034,23.769,2.61843,2686,5916786 +861,insert,8.089,-1.0,-1.0,-1.0,-1.0,17.787,2.62143,2686,5923467 +862,search,5527.84,0.92402,0.104301,16.6949,18.1731,19.554,2.62143,2686,5923467 +863,insert,70.302,-1.0,-1.0,-1.0,-1.0,79.324,2.65223,2702,5997844 +864,search,5518.16,0.92341,0.104721,16.746,18.1673,32.059,2.65235,2704,5997844 +865,insert,10.637,-1.0,-1.0,-1.0,-1.0,18.304,2.6563,2704,6009561 +866,search,5563.32,0.92334,0.104766,16.7382,18.1589,20.195,2.6563,2704,6009561 +867,insert,52.199,-1.0,-1.0,-1.0,-1.0,36.165,2.67342,2707,6052876 +868,search,5619.16,0.92344,0.105183,16.7245,18.1906,27.985,2.67348,2708,6052876 +869,insert,8.145,-1.0,-1.0,-1.0,-1.0,18.185,2.67634,2708,6059234 +870,search,5647.94,0.92351,0.105135,16.7287,18.2101,20.804,2.67634,2708,6059234 +871,insert,45.016,-1.0,-1.0,-1.0,-1.0,40.118,2.69207,2712,6098225 +872,search,5680.72,0.9236,0.105175,16.7311,18.221,27.029,2.6922,2713,6098225 +873,insert,46.687,-1.0,-1.0,-1.0,-1.0,52.197,2.71051,2719,6137308 +874,search,5692.87,0.92371,0.105026,16.7405,18.24,22.321,2.71057,2720,6137308 +875,insert,16.459,-1.0,-1.0,-1.0,-1.0,23.74,2.71703,2721,6154089 +876,search,5603.77,0.92354,0.105133,16.7582,18.2631,20.158,2.71703,2721,6154089 +877,insert,1.386,-1.0,-1.0,-1.0,-1.0,21.871,2.71742,2722,6156061 +878,search,5605.61,0.9235,0.105082,16.7667,18.2741,20.571,2.71742,2722,6156061 +879,insert,306.492,-1.0,-1.0,-1.0,-1.0,308.444,2.84711,2779,6446004 +880,search,5874.35,0.92463,0.104127,16.6206,18.2213,62.794,2.84754,2787,6446004 +881,insert,522.406,-1.0,-1.0,-1.0,-1.0,358.288,3.08474,2860,6969764 +882,search,6155.42,0.92638,0.102714,16.299,17.9806,72.556,3.0854,2870,6969764 +883,insert,446.415,-1.0,-1.0,-1.0,-1.0,359.043,3.28807,2947,7422501 +884,search,6359.38,0.92851,0.100965,15.9096,17.8162,87.808,3.28853,2963,7422501 +885,insert,8.69,-1.0,-1.0,-1.0,-1.0,32.882,3.29354,2966,7432053 +886,search,6407.71,0.92865,0.100724,15.892,17.8122,28.587,3.29353,2967,7432053 +887,insert,304.472,-1.0,-1.0,-1.0,-1.0,447.129,3.44856,3048,7789886 +888,search,6516.33,0.93074,0.0998006,15.5523,17.6356,110.119,3.45053,3074,7789886 +889,insert,356.502,-1.0,-1.0,-1.0,-1.0,529.158,3.64263,3183,8210883 +890,search,6906.07,0.93189,0.0990997,15.2997,17.4957,117.534,3.64361,3208,8210883 +891,insert,33.393,-1.0,-1.0,-1.0,-1.0,59.591,3.65695,3217,8240504 +892,search,6988.11,0.93208,0.0990883,15.2803,17.5001,39.189,3.65711,3220,8240504 +893,insert,51.696,-1.0,-1.0,-1.0,-1.0,68.554,3.67943,3230,8299693 +894,search,6979.58,0.93235,0.0988719,15.2139,17.4548,28.238,3.67953,3231,8299693 +895,insert,38.542,-1.0,-1.0,-1.0,-1.0,55.38,3.69728,3240,8349126 +896,search,7002.44,0.93271,0.0986758,15.1839,17.423,39.633,3.69743,3243,8349126 +897,delete,45.865,-1.0,-1.0,-1.0,-1.0,145.685,3.67681,3229,8268842 +898,search,6930,0.93249,0.0987212,15.2393,17.4642,27.053,3.67681,3229,8268842 +899,delete,12.013,-1.0,-1.0,-1.0,-1.0,30.87,3.676,3228,8250527 +900,search,6933.16,0.93244,0.0987455,15.2552,17.4785,26.769,3.676,3228,8250527 +901,delete,42.283,-1.0,-1.0,-1.0,-1.0,39.532,3.67112,3226,8185565 +902,search,6929.54,0.9321,0.0990267,15.319,17.5097,27.007,3.67112,3226,8185565 +903,delete,40.234,-1.0,-1.0,-1.0,-1.0,126.869,3.64973,3209,8126915 +904,search,6965.41,0.93095,0.0994818,15.5192,17.5674,26.225,3.64973,3209,8126915 +905,delete,16.651,-1.0,-1.0,-1.0,-1.0,24.096,3.64882,3209,8098533 +906,search,6829.13,0.9309,0.0996417,15.5121,17.5809,25.908,3.64882,3209,8098533 +907,delete,16.598,-1.0,-1.0,-1.0,-1.0,45.579,3.64427,3208,8074833 +908,search,6736.31,0.93066,0.0997912,15.5179,17.5789,26.858,3.64427,3208,8074833 +909,delete,29.131,-1.0,-1.0,-1.0,-1.0,28.593,3.64202,3207,8035274 +910,search,6831.04,0.93053,0.0997406,15.5233,17.5576,27.189,3.64202,3207,8035274 +911,delete,60.1,-1.0,-1.0,-1.0,-1.0,31.074,3.63862,3206,7957223 +912,search,6806.75,0.93008,0.0999056,15.6143,17.5928,31.476,3.6388,3207,7957223 +913,delete,29.921,-1.0,-1.0,-1.0,-1.0,69.943,3.62771,3200,7917554 +914,search,6718.21,0.92995,0.0999436,15.6149,17.5746,26.44,3.62771,3200,7917554 +915,delete,41.465,-1.0,-1.0,-1.0,-1.0,93.637,3.61352,3191,7861503 +916,search,6733.68,0.9296,0.100317,15.667,17.6302,32.051,3.61357,3192,7861503 +917,delete,12.34,-1.0,-1.0,-1.0,-1.0,23.868,3.6122,3192,7844487 +918,search,6634.83,0.93003,0.0999808,15.6558,17.6143,26.695,3.6122,3192,7844487 +919,delete,21.773,-1.0,-1.0,-1.0,-1.0,24.18,3.6106,3192,7814993 +920,search,6760.88,0.93004,0.100035,15.6822,17.627,27.128,3.6106,3192,7814993 +921,delete,20.014,-1.0,-1.0,-1.0,-1.0,33.616,3.60603,3191,7793855 +922,search,6814.65,0.92972,0.100199,15.6843,17.6216,26.73,3.60603,3191,7793855 +923,delete,43.915,-1.0,-1.0,-1.0,-1.0,35.591,3.59832,3189,7736054 +924,search,6664.92,0.92929,0.100605,15.7488,17.6544,26.301,3.59832,3189,7736054 +925,delete,107.643,-1.0,-1.0,-1.0,-1.0,147.976,3.55068,3161,7587942 +926,search,6622.33,0.92819,0.10126,15.9163,17.7767,38.13,3.55078,3163,7587942 +927,delete,18.009,-1.0,-1.0,-1.0,-1.0,38.951,3.54789,3162,7565670 +928,search,6638.21,0.92829,0.101073,15.9387,17.7787,26.406,3.54789,3162,7565670 +929,delete,31.472,-1.0,-1.0,-1.0,-1.0,23.607,3.54349,3162,7529948 +930,search,6600.16,0.92818,0.101423,15.9238,17.8174,26.398,3.54349,3162,7529948 +931,delete,404.539,-1.0,-1.0,-1.0,-1.0,837.814,3.36443,3045,7016700 +932,search,6206.2,0.92686,0.102398,16.0404,17.8097,42.196,3.36474,3049,7016700 +933,delete,22.063,-1.0,-1.0,-1.0,-1.0,44.104,3.35501,3045,6980979 +934,search,6178.13,0.92671,0.102493,16.0654,17.8062,25.209,3.35501,3045,6980979 +935,delete,16.973,-1.0,-1.0,-1.0,-1.0,53.382,3.34631,3042,6954250 +936,search,6257.53,0.92669,0.102416,16.0955,17.8175,24.805,3.34631,3042,6954250 +937,delete,21.784,-1.0,-1.0,-1.0,-1.0,29.493,3.33636,3041,6924596 +938,search,6133.21,0.9263,0.102712,16.126,17.8202,25.143,3.33636,3041,6924596 +939,delete,120.802,-1.0,-1.0,-1.0,-1.0,38.484,3.30842,3039,6784831 +940,search,6209.65,0.92578,0.103867,16.1509,17.8809,31.264,3.30848,3040,6784831 +941,delete,38.363,-1.0,-1.0,-1.0,-1.0,22.874,3.30168,3040,6745819 +942,search,6089.49,0.92586,0.103874,16.1671,17.9229,33.243,3.30186,3041,6745819 +943,delete,3.676,-1.0,-1.0,-1.0,-1.0,22.361,3.30148,3041,6740944 +944,search,6142.24,0.92613,0.10349,16.1548,17.9201,25.281,3.30148,3041,6740944 +945,delete,106.64,-1.0,-1.0,-1.0,-1.0,227.688,3.24737,3017,6627202 +946,search,6120.78,0.92571,0.103975,16.2326,17.979,44.229,3.24795,3020,6627202 +947,delete,19.363,-1.0,-1.0,-1.0,-1.0,22.884,3.24163,3020,6607194 +948,search,5923.01,0.9253,0.104215,16.274,17.9943,24.17,3.24163,3020,6607194 +949,delete,48.07,-1.0,-1.0,-1.0,-1.0,57.542,3.22405,3015,6551065 +950,search,6066.47,0.92492,0.104758,16.3155,18.0527,25.046,3.22405,3015,6551065 +951,delete,33.352,-1.0,-1.0,-1.0,-1.0,87.928,3.19946,3000,6506798 +952,search,6021.98,0.92517,0.103879,16.3286,18.0371,25.078,3.19946,3000,6506798 +953,delete,44.651,-1.0,-1.0,-1.0,-1.0,35.079,3.18549,2998,6459301 +954,search,5988.19,0.92484,0.10422,16.3338,18.0296,25.154,3.18549,2998,6459301 +955,delete,17.493,-1.0,-1.0,-1.0,-1.0,41.848,3.1762,2994,6440069 +956,search,6041,0.92486,0.104042,16.3743,18.0611,25.029,3.1762,2994,6440069 +957,delete,301.736,-1.0,-1.0,-1.0,-1.0,307.974,3.02982,2946,6132470 +958,search,5783.41,0.92346,0.105352,16.6271,18.2566,23.641,3.02982,2946,6132470 +959,delete,39.638,-1.0,-1.0,-1.0,-1.0,47.313,3.01225,2942,6086241 +960,search,5721.18,0.92253,0.105913,16.7546,18.292,23.823,3.01225,2942,6086241 +961,delete,22.398,-1.0,-1.0,-1.0,-1.0,21.327,3.00629,2942,6064734 +962,search,5745.51,0.92245,0.105952,16.7445,18.2451,30.281,3.00631,2943,6064734 +963,delete,121.505,-1.0,-1.0,-1.0,-1.0,72.131,2.96025,2936,5967543 +964,search,5789.66,0.9222,0.105924,16.7865,18.3255,30.583,2.96046,2937,5967543 +965,delete,60.359,-1.0,-1.0,-1.0,-1.0,84.305,2.93253,2924,5906381 +966,search,5665.72,0.92173,0.106217,16.8793,18.4155,29.572,2.93262,2925,5906381 +967,delete,47.794,-1.0,-1.0,-1.0,-1.0,48.105,2.91159,2921,5851849 +968,search,5612.67,0.92154,0.106206,16.9706,18.4689,24.07,2.91159,2921,5851849 +969,delete,55.549,-1.0,-1.0,-1.0,-1.0,57.935,2.88108,2913,5783023 +970,search,5676.74,0.9208,0.106903,17.0556,18.5058,23.469,2.88108,2913,5783023 +971,delete,249.602,-1.0,-1.0,-1.0,-1.0,295.988,2.74224,2871,5496517 +972,search,5521.72,0.91904,0.108058,17.2906,18.6846,24.251,2.74224,2871,5496517 +973,delete,248.33,-1.0,-1.0,-1.0,-1.0,248.905,2.61386,2827,5237981 +974,search,5360.87,0.91716,0.109554,17.6557,18.9215,23.355,2.61386,2827,5237981 +975,delete,141.986,-1.0,-1.0,-1.0,-1.0,276.079,2.53443,2761,5099794 +976,search,5198.63,0.91596,0.110473,17.7418,18.867,22.8,2.53443,2761,5099794 +977,delete,58.444,-1.0,-1.0,-1.0,-1.0,108.052,2.50345,2747,5032210 +978,search,5164.34,0.91496,0.111434,17.8814,18.956,23.271,2.50345,2747,5032210 +979,delete,11.9,-1.0,-1.0,-1.0,-1.0,25.573,2.49933,2746,5020211 +980,search,5155.97,0.91479,0.11184,17.9032,18.9576,22.387,2.49933,2746,5020211 +981,delete,102.964,-1.0,-1.0,-1.0,-1.0,153.026,2.4434,2724,4902291 +982,search,5113.07,0.91323,0.112869,18.1022,19.0422,28.914,2.44356,2725,4902291 +983,delete,31.589,-1.0,-1.0,-1.0,-1.0,19.615,2.43232,2725,4872577 +984,search,5111.24,0.91325,0.112633,18.1414,19.0546,21.372,2.43232,2725,4872577 +985,delete,38.077,-1.0,-1.0,-1.0,-1.0,19.448,2.41931,2725,4836730 +986,search,5576.76,0.91288,0.112614,18.2149,19.088,22.507,2.41931,2725,4836730 +987,delete,53.858,-1.0,-1.0,-1.0,-1.0,28.592,2.40334,2723,4797164 +988,search,5055.1,0.91291,0.112648,18.2138,19.077,22.821,2.40334,2723,4797164 +989,delete,15.699,-1.0,-1.0,-1.0,-1.0,19.116,2.3993,2723,4784789 +990,search,5947.5,0.91286,0.112766,18.1989,19.0627,22.637,2.3993,2723,4784789 +991,delete,59.951,-1.0,-1.0,-1.0,-1.0,140.893,2.36585,2712,4705420 +992,search,5005.07,0.91425,0.111939,18.1536,19.1053,44.008,2.36621,2715,4705420 +993,delete,91.625,-1.0,-1.0,-1.0,-1.0,74.701,2.32109,2707,4621807 +994,search,4980.17,0.91379,0.111847,18.2424,19.1514,30.175,2.32109,2708,4621807 +995,delete,58.756,-1.0,-1.0,-1.0,-1.0,84.202,2.28975,2695,4555849 +996,search,4947.71,0.91374,0.111832,18.2588,19.1257,24.955,2.28982,2696,4555849 +997,delete,27.668,-1.0,-1.0,-1.0,-1.0,42.762,2.27801,2692,4526975 +998,search,4936.25,0.91379,0.111794,18.2498,19.1183,22.203,2.27801,2692,4526975 +999,delete,123.523,-1.0,-1.0,-1.0,-1.0,154.382,2.21526,2669,4408448 +1000,search,4953.88,0.91308,0.112274,18.4112,19.2198,22.233,2.21526,2669,4408448 +1001,delete,119.455,-1.0,-1.0,-1.0,-1.0,159.54,2.15704,2650,4303257 +1002,search,4870.07,0.91264,0.11309,18.4788,19.2427,23.048,2.15704,2650,4303257 +1003,delete,42.446,-1.0,-1.0,-1.0,-1.0,38.561,2.13794,2646,4259551 +1004,search,4811,0.91193,0.113792,18.5313,19.2611,22.108,2.13794,2646,4259551 +1005,delete,20.97,-1.0,-1.0,-1.0,-1.0,28.165,2.12893,2644,4241434 +1006,search,4846.7,0.91163,0.113788,18.6018,19.3298,21.47,2.12893,2644,4241434 +1007,delete,168.676,-1.0,-1.0,-1.0,-1.0,341.525,2.02637,2591,4052722 +1008,search,4683.35,0.90984,0.115151,18.9,19.4718,27.121,2.02656,2592,4052722 +1009,delete,276.898,-1.0,-1.0,-1.0,-1.0,344.514,1.86344,2523,3738432 +1010,search,4494.91,0.90794,0.115664,19.1069,19.4984,20.181,1.86344,2523,3738432 +1011,delete,347.14,-1.0,-1.0,-1.0,-1.0,446.825,1.67158,2425,3372539 +1012,search,4310.91,0.90541,0.117513,19.6973,19.9227,26.831,1.67178,2426,3372539 +1013,delete,13.389,-1.0,-1.0,-1.0,-1.0,22.11,1.66778,2424,3361432 +1014,search,4272.59,0.90465,0.118167,19.7757,19.9782,20.172,1.66778,2424,3361432 +1015,delete,254.48,-1.0,-1.0,-1.0,-1.0,350.469,1.53475,2351,3091692 +1016,search,4166.07,0.90172,0.119774,20.1979,20.0796,27.488,1.53475,2351,3091692 +1017,delete,311.206,-1.0,-1.0,-1.0,-1.0,420.726,1.37195,2272,2775418 +1018,search,3934.55,0.90041,0.12107,20.3901,20.2231,26.996,1.37195,2272,2775418 +1019,delete,22.156,-1.0,-1.0,-1.0,-1.0,39.601,1.36425,2269,2754073 +1020,search,3981.06,0.89999,0.121514,20.4792,20.3216,25.361,1.36425,2269,2754073 +1021,delete,112.634,-1.0,-1.0,-1.0,-1.0,66.938,1.31617,2259,2638917 +1022,search,3925.41,0.89799,0.122348,20.7489,20.4117,25.387,1.31617,2259,2638917 +1023,delete,71.866,-1.0,-1.0,-1.0,-1.0,102.395,1.27737,2234,2556494 +1024,search,3858.92,0.8959,0.123465,20.9969,20.5391,37.411,1.27749,2236,2556494 +1025,insert,21.013,-1.0,-1.0,-1.0,-1.0,22.936,1.28365,2236,2594934 +1026,search,3909.5,0.8965,0.12292,20.896,20.4739,25.268,1.28365,2236,2594934 +1027,insert,177.873,-1.0,-1.0,-1.0,-1.0,109.6,1.34352,2246,2802105 +1028,search,3959.81,0.89633,0.123924,20.8157,20.5095,63.724,1.34352,2251,2802105 +1029,insert,403.011,-1.0,-1.0,-1.0,-1.0,168.533,1.48498,2274,3203975 +1030,search,4173.05,0.90146,0.12138,20.1155,20.1714,112.014,1.48506,2291,3203975 +1031,insert,602.39,-1.0,-1.0,-1.0,-1.0,252.571,1.73736,2322,3830566 +1032,search,4410.6,0.90296,0.120723,19.8352,20.2113,110.694,1.73736,2333,3830566 +1033,insert,445.702,-1.0,-1.0,-1.0,-1.0,271.015,1.91499,2383,4252669 +1034,search,4585.76,0.9075,0.117738,18.924,19.5864,85.54,1.91502,2395,4252669 +1035,insert,248.997,-1.0,-1.0,-1.0,-1.0,205.961,2.02817,2425,4512107 +1036,search,4660.82,0.90923,0.117173,18.6963,19.5535,68.729,2.02858,2436,4512107 +1037,insert,10.027,-1.0,-1.0,-1.0,-1.0,16.078,2.03237,2436,4525815 +1038,search,4738.16,0.90941,0.117033,18.6536,19.5272,17.755,2.03237,2436,4525815 +1039,insert,73.591,-1.0,-1.0,-1.0,-1.0,19.454,2.06137,2437,4599215 +1040,search,4763.34,0.90956,0.11702,18.5499,19.4156,17.962,2.06137,2437,4599215 +1041,insert,12.068,-1.0,-1.0,-1.0,-1.0,30.091,2.06566,2440,4609851 +1042,search,4772.38,0.90955,0.117111,18.5255,19.4094,18.099,2.06566,2440,4609851 +1043,insert,23.384,-1.0,-1.0,-1.0,-1.0,20.687,2.07238,2441,4627411 +1044,search,4703.43,0.9096,0.116905,18.5146,19.3751,18.18,2.07238,2441,4627411 +1045,insert,47.006,-1.0,-1.0,-1.0,-1.0,15.876,2.08779,2441,4670607 +1046,search,4743.95,0.90999,0.116726,18.4698,19.3781,18.121,2.08779,2441,4670607 +1047,insert,5.649,-1.0,-1.0,-1.0,-1.0,15.592,2.08921,2441,4675386 +1048,search,4795.63,0.91007,0.116597,18.4525,19.369,18.074,2.08921,2441,4675386 +1049,insert,18.344,-1.0,-1.0,-1.0,-1.0,15.662,2.095,2441,4689998 +1050,search,4739,0.9102,0.116523,18.4217,19.3451,17.482,2.095,2441,4689998 +1051,insert,104.338,-1.0,-1.0,-1.0,-1.0,34.569,2.13582,2445,4783971 +1052,search,4821.43,0.91115,0.115646,18.3033,19.2953,27.44,2.13589,2447,4783971 +1053,insert,53.088,-1.0,-1.0,-1.0,-1.0,19.305,2.15355,2448,4826219 +1054,search,4840.51,0.91117,0.115331,18.2327,19.2426,18.221,2.15355,2448,4826219 +1055,insert,48.748,-1.0,-1.0,-1.0,-1.0,32.523,2.1687,2452,4862355 +1056,search,4858.63,0.91155,0.115169,18.1879,19.2343,23.648,2.1687,2453,4862355 +1057,insert,6.866,-1.0,-1.0,-1.0,-1.0,16.053,2.17035,2453,4869564 +1058,search,4859.41,0.9116,0.115042,18.1889,19.2321,18.518,2.17035,2453,4869564 +1059,insert,29.556,-1.0,-1.0,-1.0,-1.0,15.904,2.17907,2453,4898570 +1060,search,4873.17,0.91196,0.114972,18.1542,19.2146,18.035,2.17907,2453,4898570 +1061,insert,10.465,-1.0,-1.0,-1.0,-1.0,15.739,2.18251,2453,4907501 +1062,search,4874.85,0.9122,0.114666,18.1158,19.1959,17.794,2.18251,2453,4907501 +1063,insert,13.202,-1.0,-1.0,-1.0,-1.0,16.005,2.18631,2453,4916386 +1064,search,4850.95,0.91212,0.114719,18.1436,19.2283,17.338,2.18631,2453,4916386 +1065,insert,306.059,-1.0,-1.0,-1.0,-1.0,239.502,2.30929,2491,5194839 +1066,search,5001.32,0.91344,0.113836,17.9165,19.0745,63.297,2.30973,2500,5194839 +1067,insert,8.901,-1.0,-1.0,-1.0,-1.0,19.458,2.31195,2501,5200182 +1068,search,5027.78,0.91396,0.113447,17.8953,19.0771,18.865,2.31195,2501,5200182 +1069,insert,43.308,-1.0,-1.0,-1.0,-1.0,42.254,2.32665,2512,5230883 +1070,search,5068.16,0.91397,0.113417,17.8262,19.0047,18.722,2.32665,2512,5230883 +1071,insert,28.614,-1.0,-1.0,-1.0,-1.0,27.136,2.33653,2514,5255659 +1072,search,5094.65,0.91383,0.113667,17.8333,19.0344,25.961,2.33667,2515,5255659 +1073,insert,31.024,-1.0,-1.0,-1.0,-1.0,25.62,2.34727,2517,5281693 +1074,search,5133.32,0.91415,0.113427,17.7959,19.0096,19.194,2.34727,2517,5281693 +1075,insert,7.761,-1.0,-1.0,-1.0,-1.0,16.706,2.34937,2517,5290081 +1076,search,5120.54,0.91438,0.113194,17.7884,19.0034,18.756,2.34937,2517,5290081 +1077,insert,31.624,-1.0,-1.0,-1.0,-1.0,29.662,2.36121,2519,5316166 +1078,search,5119.42,0.91449,0.113005,17.7763,19.0135,18.511,2.36121,2519,5316166 +1079,insert,21.543,-1.0,-1.0,-1.0,-1.0,28.496,2.36936,2523,5335531 +1080,search,5047.65,0.91445,0.112787,17.7544,18.99,18.987,2.36936,2523,5335531 +1081,insert,432.024,-1.0,-1.0,-1.0,-1.0,170.085,2.51951,2551,5678781 +1082,search,5301.27,0.91543,0.112503,17.69,19.0044,46.327,2.51961,2555,5678781 +1083,insert,1.924,-1.0,-1.0,-1.0,-1.0,17.47,2.52014,2555,5679848 +1084,search,5294.24,0.91525,0.112546,17.6934,19.0017,28.2,2.52014,2556,5679848 +1085,insert,28.976,-1.0,-1.0,-1.0,-1.0,21.162,2.52964,2558,5702205 +1086,search,5267.88,0.91542,0.112034,17.6601,18.9734,19.273,2.52964,2558,5702205 +1087,insert,16.826,-1.0,-1.0,-1.0,-1.0,19.142,2.53445,2559,5715514 +1088,search,5254.87,0.91571,0.111869,17.6662,18.9802,19.027,2.53445,2559,5715514 +1089,insert,426.914,-1.0,-1.0,-1.0,-1.0,326.002,2.70573,2637,6103499 +1090,search,5518.19,0.91714,0.111186,17.3868,18.7838,48.836,2.70633,2645,6103499 +1091,insert,44.888,-1.0,-1.0,-1.0,-1.0,69.574,2.72744,2660,6152505 +1092,search,5566.01,0.91797,0.11044,17.2752,18.7237,30.337,2.72768,2662,6152505 +1093,insert,20.913,-1.0,-1.0,-1.0,-1.0,26.908,2.7348,2663,6171104 +1094,search,5499.81,0.91813,0.110245,17.2579,18.7142,23.214,2.7348,2663,6171104 +1095,insert,391.868,-1.0,-1.0,-1.0,-1.0,388.492,2.90807,2741,6557850 +1096,search,5828.15,0.92046,0.109151,16.8991,18.5694,94.406,2.90879,2756,6557850 +1097,insert,24.048,-1.0,-1.0,-1.0,-1.0,25.176,2.91719,2758,6579289 +1098,search,5792.53,0.92069,0.109092,16.8669,18.5409,37.405,2.91726,2761,6579289 +1099,insert,16.458,-1.0,-1.0,-1.0,-1.0,19.826,2.92425,2761,6591442 +1100,search,5781.48,0.92095,0.108892,16.8495,18.532,21.294,2.92425,2761,6591442 +1101,insert,43.094,-1.0,-1.0,-1.0,-1.0,24.319,2.94168,2762,6633739 +1102,search,5800.34,0.92112,0.108663,16.8068,18.5041,21.206,2.94168,2762,6633739 +1103,insert,83.717,-1.0,-1.0,-1.0,-1.0,118.034,2.98162,2793,6724357 +1104,search,5940.96,0.92246,0.107863,16.6399,18.4617,35.607,2.98166,2797,6724357 +1105,insert,3.211,-1.0,-1.0,-1.0,-1.0,20.138,2.98251,2797,6727059 +1106,search,5940.84,0.92231,0.108008,16.6636,18.4858,22.128,2.98251,2797,6727059 +1107,insert,257.033,-1.0,-1.0,-1.0,-1.0,196.608,3.08522,2833,6950869 +1108,search,9365.57,0.92306,0.107471,16.5731,18.4539,58.889,3.0858,2840,6950869 +1109,insert,6.469,-1.0,-1.0,-1.0,-1.0,20.534,3.08751,2840,6958173 +1110,search,6092.1,0.92313,0.107461,16.5663,18.4511,21.843,3.08751,2840,6958173 +1111,insert,44.122,-1.0,-1.0,-1.0,-1.0,62.184,3.10605,2855,6995273 +1112,search,6073.85,0.92307,0.107621,16.5703,18.4566,22.277,3.10605,2855,6995273 +1113,insert,58.335,-1.0,-1.0,-1.0,-1.0,71.491,3.1277,2865,7047862 +1114,search,6074.86,0.9236,0.106938,16.537,18.4476,22.92,3.1277,2865,7047862 +1115,insert,67.682,-1.0,-1.0,-1.0,-1.0,57.548,3.15131,2876,7110727 +1116,search,6103.01,0.9239,0.106545,16.4752,18.3969,23.033,3.15131,2876,7110727 +1117,insert,17.916,-1.0,-1.0,-1.0,-1.0,23.874,3.15631,2877,7125591 +1118,search,6204.25,0.92398,0.106504,16.459,18.3808,23.119,3.15631,2877,7125591 +1119,insert,12.005,-1.0,-1.0,-1.0,-1.0,26.639,3.16037,2879,7134442 +1120,search,6151.81,0.92406,0.106709,16.4402,18.3703,22.78,3.16037,2879,7134442 +1121,insert,29.259,-1.0,-1.0,-1.0,-1.0,53.768,3.17153,2886,7162109 +1122,search,6208.09,0.92447,0.106345,16.3967,18.3416,21.94,3.17153,2886,7162109 +1123,insert,15.107,-1.0,-1.0,-1.0,-1.0,23.71,3.17607,2887,7179509 +1124,search,6146.65,0.92441,0.106426,16.3901,18.337,21.986,3.17607,2887,7179509 +1125,insert,6.756,-1.0,-1.0,-1.0,-1.0,20.326,3.17851,2887,7186372 +1126,search,6146.12,0.92438,0.10647,16.3883,18.3385,22.373,3.17851,2887,7186372 +1127,insert,44.38,-1.0,-1.0,-1.0,-1.0,37.817,3.19583,2890,7231450 +1128,search,6234.93,0.92438,0.106451,16.3843,18.3552,22.583,3.19583,2890,7231450 +1129,insert,15.729,-1.0,-1.0,-1.0,-1.0,20.174,3.20059,2890,7243215 +1130,search,6161.13,0.9245,0.106305,16.3783,18.352,22.666,3.20059,2890,7243215 +1131,insert,44.392,-1.0,-1.0,-1.0,-1.0,49.878,3.21665,2895,7276107 +1132,search,6275.21,0.92475,0.106297,16.3711,18.3642,22.314,3.21665,2895,7276107 +1133,insert,19.686,-1.0,-1.0,-1.0,-1.0,34.447,3.22355,2899,7292577 +1134,search,6246.01,0.92474,0.106423,16.3348,18.318,21.937,3.22355,2899,7292577 +1135,insert,6.659,-1.0,-1.0,-1.0,-1.0,24.98,3.2259,2900,7299867 +1136,search,6177.37,0.92503,0.106206,16.3301,18.3251,28.294,3.22604,2902,7299867 +1137,insert,28.152,-1.0,-1.0,-1.0,-1.0,50.958,3.2367,2910,7323342 +1138,search,6274.75,0.92526,0.105948,16.3131,18.3193,25.507,3.23679,2911,7323342 +1139,insert,2.787,-1.0,-1.0,-1.0,-1.0,28.877,3.23795,2913,7325844 +1140,search,6255.28,0.92511,0.106092,16.3229,18.3253,23.067,3.23795,2913,7325844 +1141,insert,225.828,-1.0,-1.0,-1.0,-1.0,249.523,3.33369,2959,7540761 +1142,search,6412.92,0.9254,0.105969,16.2104,18.2427,63.501,3.33434,2970,7540761 +1143,insert,18.852,-1.0,-1.0,-1.0,-1.0,43.294,3.34149,2975,7561926 +1144,search,6375.32,0.92557,0.106085,16.2134,18.2724,28.86,3.34156,2977,7561926 +1145,insert,8.962,-1.0,-1.0,-1.0,-1.0,33.61,3.34651,2980,7571861 +1146,search,6319.11,0.92556,0.10613,16.2044,18.2664,23.323,3.34651,2980,7571861 +1147,insert,16.13,-1.0,-1.0,-1.0,-1.0,46.11,3.35419,2985,7590881 +1148,search,6410.73,0.92579,0.106091,16.1649,18.2505,26.368,3.35426,2986,7590881 +1149,insert,5.951,-1.0,-1.0,-1.0,-1.0,29.397,3.35611,2988,7595507 +1150,search,6671.49,0.92569,0.106119,16.1731,18.2576,23.963,3.35611,2988,7595507 +1151,insert,8.242,-1.0,-1.0,-1.0,-1.0,27.237,3.35899,2989,7601664 +1152,search,6444.46,0.9257,0.106054,16.1687,18.2483,24.195,3.35899,2989,7601664 +1153,delete,21.542,-1.0,-1.0,-1.0,-1.0,21.936,3.35707,2989,7566707 +1154,search,6453.71,0.92562,0.106001,16.1764,18.2615,23.837,3.35707,2989,7566707 +1155,delete,107.154,-1.0,-1.0,-1.0,-1.0,175.353,3.32401,2971,7396192 +1156,search,6337.92,0.92516,0.106319,16.2627,18.2974,23.278,3.32401,2971,7396192 +1157,delete,219.903,-1.0,-1.0,-1.0,-1.0,361.786,3.24518,2921,7079041 +1158,search,6180.1,0.92406,0.106962,16.378,18.3713,35.726,3.24538,2923,7079041 +1159,delete,319.29,-1.0,-1.0,-1.0,-1.0,448.667,3.08636,2863,6597115 +1160,search,5925.14,0.92213,0.107465,16.7798,18.5013,52.873,3.08705,2867,6597115 +1161,delete,230.195,-1.0,-1.0,-1.0,-1.0,277.615,2.9973,2825,6308902 +1162,search,5806.93,0.92063,0.108264,17.0826,18.7185,42.532,2.99776,2828,6308902 +1163,delete,108.427,-1.0,-1.0,-1.0,-1.0,184.509,2.94359,2805,6164514 +1164,search,5785.36,0.92027,0.108281,17.0775,18.6527,23.145,2.94359,2805,6164514 +1165,delete,27.301,-1.0,-1.0,-1.0,-1.0,49.737,2.93685,2802,6133412 +1166,search,5572.1,0.9201,0.108481,17.1098,18.7054,22.743,2.93685,2802,6133412 +1167,delete,56.243,-1.0,-1.0,-1.0,-1.0,20.6,2.92432,2802,6057218 +1168,search,5686.36,0.91981,0.108599,17.1916,18.796,28.415,2.92433,2803,6057218 +1169,delete,16.685,-1.0,-1.0,-1.0,-1.0,57.757,2.91271,2795,6028053 +1170,search,5650.04,0.91906,0.108971,17.3081,18.8725,22.585,2.91271,2795,6028053 +1171,delete,23.641,-1.0,-1.0,-1.0,-1.0,25.744,2.90549,2794,6001880 +1172,search,5627.36,0.91906,0.109127,17.3106,18.8609,22.714,2.90549,2794,6001880 +1173,delete,38.149,-1.0,-1.0,-1.0,-1.0,45.383,2.89563,2791,5957180 +1174,search,5608.24,0.91875,0.109627,17.3728,18.9137,23.021,2.89563,2791,5957180 +1175,delete,16.602,-1.0,-1.0,-1.0,-1.0,20.015,2.8935,2791,5939326 +1176,search,5615.73,0.91876,0.109577,17.3761,18.9135,22.767,2.8935,2791,5939326 +1177,delete,11.088,-1.0,-1.0,-1.0,-1.0,24.527,2.88879,2790,5924145 +1178,search,5595.47,0.91882,0.109487,17.3826,18.9252,22.579,2.88879,2790,5924145 +1179,delete,54.481,-1.0,-1.0,-1.0,-1.0,56.433,2.86326,2785,5863334 +1180,search,5598.37,0.91834,0.109822,17.4288,18.9442,22.104,2.86326,2785,5863334 +1181,delete,32.588,-1.0,-1.0,-1.0,-1.0,20.154,2.8536,2785,5822703 +1182,search,5571.27,0.91804,0.11025,17.4944,18.9938,21.951,2.8536,2785,5822703 +1183,delete,39.642,-1.0,-1.0,-1.0,-1.0,43.138,2.83969,2782,5775807 +1184,search,5563.45,0.91714,0.110871,17.5849,19.0212,22.958,2.83969,2782,5775807 +1185,delete,22.768,-1.0,-1.0,-1.0,-1.0,24.798,2.8358,2781,5750627 +1186,search,7299.77,0.9169,0.1108,17.6265,19.0393,23.789,2.8358,2781,5750627 +1187,delete,142.981,-1.0,-1.0,-1.0,-1.0,127.417,2.78844,2765,5601207 +1188,search,5497,0.91672,0.111148,17.6646,19.1089,22.983,2.78844,2765,5601207 +1189,delete,17.989,-1.0,-1.0,-1.0,-1.0,19.732,2.78304,2765,5586425 +1190,search,5479.37,0.91639,0.111279,17.6848,19.109,22.567,2.78304,2765,5586425 +1191,delete,11.647,-1.0,-1.0,-1.0,-1.0,28.199,2.77953,2764,5574023 +1192,search,5443.65,0.91633,0.111268,17.7014,19.1097,21.996,2.77953,2764,5574023 +1193,delete,179.02,-1.0,-1.0,-1.0,-1.0,316.363,2.67069,2726,5356157 +1194,search,5323.69,0.91586,0.111972,17.8002,19.2239,38.794,2.67108,2728,5356157 +1195,delete,17.324,-1.0,-1.0,-1.0,-1.0,19.609,2.66719,2728,5340404 +1196,search,5313.23,0.91612,0.11185,17.786,19.2294,22.14,2.66719,2728,5340404 +1197,delete,54.451,-1.0,-1.0,-1.0,-1.0,19.687,2.65219,2728,5293259 +1198,search,5324.93,0.91597,0.112259,17.8006,19.2318,22.505,2.65219,2728,5293259 +1199,delete,13.247,-1.0,-1.0,-1.0,-1.0,19.301,2.64688,2728,5279787 +1200,search,5307.9,0.91599,0.112244,17.7818,19.2127,22.813,2.64688,2728,5279787 +1201,delete,66.267,-1.0,-1.0,-1.0,-1.0,65.086,2.61457,2721,5216567 +1202,search,5272.48,0.91519,0.112454,17.9187,19.2792,22.001,2.61457,2721,5216567 +1203,delete,21.084,-1.0,-1.0,-1.0,-1.0,19.08,2.60765,2721,5196947 +1204,search,5249.69,0.9151,0.112774,17.9017,19.256,21.576,2.60765,2721,5196947 +1205,delete,20.822,-1.0,-1.0,-1.0,-1.0,44.778,2.59503,2717,5168447 +1206,search,5223.93,0.91512,0.112785,17.9099,19.2371,21.314,2.59503,2717,5168447 +1207,delete,20.4,-1.0,-1.0,-1.0,-1.0,36.002,2.58558,2715,5146927 +1208,search,5204.36,0.91447,0.113131,17.9912,19.2332,22.351,2.58558,2715,5146927 +1209,delete,254.866,-1.0,-1.0,-1.0,-1.0,308.057,2.45342,2672,4887612 +1210,search,5106.48,0.9141,0.113471,18.0622,19.2556,21.827,2.45342,2672,4887612 +1211,delete,6.858,-1.0,-1.0,-1.0,-1.0,18.453,2.45164,2672,4882301 +1212,search,5149.37,0.91387,0.113654,18.0714,19.2774,22.304,2.45164,2672,4882301 +1213,delete,107.26,-1.0,-1.0,-1.0,-1.0,79.648,2.40332,2661,4780915 +1214,search,5086.78,0.91326,0.113942,18.2268,19.4099,21.598,2.40332,2661,4780915 +1215,delete,12.553,-1.0,-1.0,-1.0,-1.0,18.483,2.40026,2661,4765751 +1216,search,4945.48,0.91319,0.114145,18.2247,19.4115,21.113,2.40026,2661,4765751 +1217,delete,293.166,-1.0,-1.0,-1.0,-1.0,367.354,2.23106,2581,4452306 +1218,search,4833.48,0.91099,0.115409,18.4955,19.5476,19.618,2.23106,2581,4452306 +1219,delete,75.392,-1.0,-1.0,-1.0,-1.0,134.245,2.18104,2556,4362045 +1220,search,4764.95,0.91023,0.116076,18.6339,19.6852,20.667,2.18104,2556,4362045 +1221,delete,37.259,-1.0,-1.0,-1.0,-1.0,35.716,2.16834,2551,4326917 +1222,search,4775.58,0.91006,0.116405,18.6905,19.6921,20.459,2.16834,2551,4326917 +1223,delete,205.112,-1.0,-1.0,-1.0,-1.0,257.206,2.05993,2502,4109781 +1224,search,4633.11,0.90782,0.117655,19.0711,19.9174,19.611,2.05993,2502,4109781 +1225,delete,30.218,-1.0,-1.0,-1.0,-1.0,32.839,2.04406,2497,4075879 +1226,search,4636.58,0.90721,0.118166,19.1032,19.9167,19.952,2.04406,2497,4075879 +1227,delete,68.257,-1.0,-1.0,-1.0,-1.0,68.967,2.01382,2490,4006503 +1228,search,4578.32,0.90715,0.118335,19.1436,19.9212,30.336,2.01427,2492,4006503 +1229,delete,84.968,-1.0,-1.0,-1.0,-1.0,52.243,1.97686,2487,3922625 +1230,search,4557.35,0.9064,0.118962,19.1807,19.9425,19.09,1.97686,2487,3922625 +1231,delete,65.599,-1.0,-1.0,-1.0,-1.0,133.682,1.93415,2450,3844860 +1232,search,4476.93,0.90534,0.120033,19.2537,19.9752,18.436,1.93415,2450,3844860 +1233,delete,11.795,-1.0,-1.0,-1.0,-1.0,19.326,1.92943,2448,3831414 +1234,search,4460.31,0.90475,0.120514,19.2819,19.9871,18.115,1.92943,2448,3831414 +1235,delete,132.636,-1.0,-1.0,-1.0,-1.0,106.587,1.86125,2432,3684234 +1236,search,4378.22,0.90346,0.120601,19.4914,20.1409,19.257,1.86125,2432,3684234 +1237,delete,20.277,-1.0,-1.0,-1.0,-1.0,16.216,1.85446,2432,3669074 +1238,search,4408.47,0.9036,0.120419,19.5018,20.1533,18.953,1.85446,2432,3669074 +1239,delete,63.54,-1.0,-1.0,-1.0,-1.0,17.639,1.83477,2431,3620984 +1240,search,4407.67,0.90383,0.12043,19.4768,20.1593,19.214,1.83477,2431,3620984 +1241,delete,43.807,-1.0,-1.0,-1.0,-1.0,23.164,1.81546,2430,3580113 +1242,search,4384.65,0.90352,0.12043,19.5896,20.2535,19.057,1.81546,2430,3580113 +1243,delete,50.022,-1.0,-1.0,-1.0,-1.0,32.961,1.79251,2425,3533909 +1244,search,4351.95,0.90284,0.12086,19.6866,20.3083,18.989,1.79251,2425,3533909 +1245,delete,15.993,-1.0,-1.0,-1.0,-1.0,16.284,1.78537,2425,3519590 +1246,search,4340.42,0.90268,0.121375,19.7009,20.3521,18.335,1.78537,2425,3519590 +1247,delete,48.155,-1.0,-1.0,-1.0,-1.0,94.621,1.74831,2388,3452537 +1248,search,4263.75,0.90121,0.1217,20.0605,20.5228,21.031,1.7484,2389,3452537 +1249,delete,33.484,-1.0,-1.0,-1.0,-1.0,31.095,1.73126,2387,3416711 +1250,search,4270.29,0.90092,0.121829,20.0936,20.5462,18.042,1.73126,2387,3416711 +1251,delete,28.05,-1.0,-1.0,-1.0,-1.0,30.297,1.71824,2383,3387653 +1252,search,4233.17,0.90063,0.121753,20.1729,20.6226,19.307,1.71824,2383,3387653 +1253,delete,19.776,-1.0,-1.0,-1.0,-1.0,21.892,1.70978,2382,3372157 +1254,search,4286.63,0.90075,0.121695,20.175,20.648,18.999,1.70978,2382,3372157 +1255,delete,104.067,-1.0,-1.0,-1.0,-1.0,106.524,1.64867,2338,3258215 +1256,search,4180.35,0.89863,0.122703,20.5796,20.9086,26.768,1.64867,2338,3258215 +1257,delete,38.372,-1.0,-1.0,-1.0,-1.0,46.929,1.62971,2330,3223657 +1258,search,4143.72,0.89812,0.122966,20.7238,21.0369,26.412,1.62971,2330,3223657 +1259,delete,50.26,-1.0,-1.0,-1.0,-1.0,50.412,1.60536,2325,3174982 +1260,search,4146.18,0.89795,0.122765,20.8811,21.186,26.516,1.60536,2325,3174982 +1261,delete,18.25,-1.0,-1.0,-1.0,-1.0,23.791,1.59939,2325,3157038 +1262,search,4146.65,0.89783,0.122617,20.9483,21.2339,25.966,1.59939,2325,3157038 +1263,delete,98.253,-1.0,-1.0,-1.0,-1.0,171.521,1.54396,2306,3058847 +1264,search,4060.34,0.89737,0.122726,21.0697,21.3257,34.282,1.54401,2307,3058847 +1265,delete,220.385,-1.0,-1.0,-1.0,-1.0,253.927,1.41204,2202,2833531 +1266,search,3858.02,0.89452,0.124569,21.4105,21.3276,23.525,1.41204,2202,2833531 +1267,delete,65.939,-1.0,-1.0,-1.0,-1.0,56.966,1.38404,2195,2763793 +1268,search,3866.22,0.89307,0.125898,21.6084,21.3697,23.465,1.38404,2195,2763793 +1269,delete,130.881,-1.0,-1.0,-1.0,-1.0,171.78,1.31519,2164,2627384 +1270,search,3809.89,0.89328,0.12557,21.5303,21.3216,24.057,1.31519,2164,2627384 +1271,delete,81.5,-1.0,-1.0,-1.0,-1.0,56.285,1.282,2159,2553476 +1272,search,3815.04,0.89273,0.125503,21.7382,21.4696,24.129,1.282,2159,2553476 +1273,delete,120.712,-1.0,-1.0,-1.0,-1.0,141.902,1.22198,2129,2443067 +1274,search,3735.09,0.89186,0.125312,21.9827,21.562,23.625,1.22198,2129,2443067 +1275,delete,25.49,-1.0,-1.0,-1.0,-1.0,27.169,1.21432,2128,2421654 +1276,search,3741.5,0.89114,0.125439,22.1054,21.6495,23.043,1.21432,2128,2421654 +1277,delete,29.033,-1.0,-1.0,-1.0,-1.0,44.226,1.20299,2122,2391396 +1278,search,3718.06,0.89045,0.125808,22.2342,21.7367,23.123,1.20299,2122,2391396 +1279,delete,25.79,-1.0,-1.0,-1.0,-1.0,20.858,1.19363,2122,2367854 +1280,search,3687.91,0.89038,0.125743,22.2709,21.7681,23.173,1.19363,2122,2367854 diff --git a/scripts/big_ann_perf_numbers/scan_0.15_no_aps_refinment_wma_delete.csv b/scripts/big_ann_perf_numbers/scan_0.15_no_aps_refinment_wma_delete.csv new file mode 100644 index 00000000..2a550f66 --- /dev/null +++ b/scripts/big_ann_perf_numbers/scan_0.15_no_aps_refinment_wma_delete.csv @@ -0,0 +1 @@ +step_num,step_type,latency_ms,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors diff --git a/scripts/big_ann_perf_numbers/scan_0.1_no_aps_refinment_wma.csv b/scripts/big_ann_perf_numbers/scan_0.1_no_aps_refinment_wma.csv new file mode 100644 index 00000000..f44212e9 --- /dev/null +++ b/scripts/big_ann_perf_numbers/scan_0.1_no_aps_refinment_wma.csv @@ -0,0 +1,307 @@ +step_num,step_type,latency_ms,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +2,search,2474.44,0.78814,0.157167,27.1243,17.7481,5.575,0.0184881,1024,38806 +3,insert,14.943,-1.0,-1.0,-1.0,-1.0,11.622,0.0226305,1020,49334 +4,search,1936.45,0.80572,0.156545,25.2691,17.2559,24.277,0.0226346,1017,49334 +5,insert,40.838,-1.0,-1.0,-1.0,-1.0,155.556,0.0332047,1008,73557 +6,search,1840.04,0.88145,0.133136,18.3181,16.1764,108.067,0.0333193,1011,73557 +7,insert,26.377,-1.0,-1.0,-1.0,-1.0,97.27,0.0429624,1011,95766 +8,search,1852.77,0.87507,0.134743,18.3914,15.6164,78.654,0.043044,1013,95766 +9,insert,8.297,-1.0,-1.0,-1.0,-1.0,68.645,0.0449143,1013,100025 +10,search,1852.78,0.87503,0.133335,18.2295,15.3042,71.031,0.0449171,1014,100025 +11,insert,10.258,-1.0,-1.0,-1.0,-1.0,74.512,0.0496414,1016,111417 +12,search,1770.43,0.8755,0.13347,18.0777,15.1491,73.301,0.0496671,1017,111417 +13,insert,23.314,-1.0,-1.0,-1.0,-1.0,73.03,0.0608246,1018,137139 +14,search,1847.34,0.87032,0.137551,18.2122,14.9817,13.688,0.0611184,1019,137139 +15,insert,17.826,-1.0,-1.0,-1.0,-1.0,9.192,0.0696652,1021,156710 +16,search,1902.5,0.86659,0.138558,18.302,14.6745,18.616,0.0696684,1023,156710 +17,insert,7.79,-1.0,-1.0,-1.0,-1.0,8.297,0.0717321,1025,161773 +18,search,1917.43,0.86518,0.138967,18.2843,14.6284,14.618,0.0719741,1029,161773 +19,insert,33.733,-1.0,-1.0,-1.0,-1.0,8.601,0.0790512,1031,177161 +20,search,1897.46,0.86927,0.134747,18.1524,14.4929,7.507,0.079052,1032,177161 +21,insert,356.684,-1.0,-1.0,-1.0,-1.0,169.807,0.200689,1081,448898 +22,search,2122.75,0.85509,0.139029,19.9947,15.3547,50.861,0.200685,1095,448898 +23,insert,393.898,-1.0,-1.0,-1.0,-1.0,250.916,0.327744,1152,733493 +24,search,2275.95,0.84922,0.140953,20.8617,15.957,96.691,0.328842,1182,733493 +25,insert,47.875,-1.0,-1.0,-1.0,-1.0,25.103,0.345984,1188,777443 +26,search,2371.65,0.84568,0.143666,21.2454,16.1756,16.276,0.345987,1191,777443 +27,insert,29.855,-1.0,-1.0,-1.0,-1.0,22.008,0.358023,1195,805394 +28,search,2384.53,0.84718,0.14228,21.217,16.1749,14.681,0.358152,1198,805394 +29,insert,57.885,-1.0,-1.0,-1.0,-1.0,49.159,0.386003,1211,866391 +30,search,2435.04,0.85166,0.141473,20.8367,16.1121,22.93,0.386032,1216,866391 +31,insert,524.088,-1.0,-1.0,-1.0,-1.0,323.368,0.553558,1287,1239816 +32,search,2672.22,0.84472,0.146027,21.7483,16.8256,34.923,0.553557,1294,1239816 +33,insert,52.224,-1.0,-1.0,-1.0,-1.0,32.113,0.573287,1303,1291211 +34,search,2711.1,0.84689,0.144118,21.8038,16.9059,7.72,0.573287,1303,1291211 +35,insert,32.721,-1.0,-1.0,-1.0,-1.0,21.36,0.585495,1308,1324978 +36,search,2671.48,0.84891,0.142213,21.6701,16.8286,7.382,0.585495,1308,1324978 +37,insert,49.162,-1.0,-1.0,-1.0,-1.0,33.544,0.606042,1314,1371885 +38,search,2749.11,0.85002,0.141407,21.8092,17.1229,20.051,0.606086,1317,1371885 +39,insert,16.78,-1.0,-1.0,-1.0,-1.0,12.528,0.609949,1318,1379335 +40,search,2762.19,0.84972,0.141774,21.8719,17.1904,10.901,0.60995,1319,1379335 +41,insert,51.874,-1.0,-1.0,-1.0,-1.0,18.261,0.623571,1322,1413312 +42,search,2729.04,0.85201,0.14091,21.8075,17.2453,11.334,0.623689,1323,1413312 +43,insert,12.207,-1.0,-1.0,-1.0,-1.0,13.67,0.627857,1326,1423411 +44,search,2781.39,0.85154,0.140795,21.8802,17.2859,7.572,0.627857,1326,1423411 +45,insert,225.454,-1.0,-1.0,-1.0,-1.0,20.159,0.642389,1331,1457559 +46,search,2748.25,0.8539,0.13963,21.7753,17.307,9.709,0.642389,1331,1457559 +47,insert,294.348,-1.0,-1.0,-1.0,-1.0,280.479,0.748614,1378,1688593 +48,search,2848.64,0.85676,0.141666,21.3603,17.3262,82.146,0.748714,1389,1688593 +49,insert,37.629,-1.0,-1.0,-1.0,-1.0,32.657,0.761819,1396,1723505 +50,search,2819.92,0.85785,0.141257,21.3848,17.4382,25.806,0.761833,1398,1723505 +51,insert,419.726,-1.0,-1.0,-1.0,-1.0,300.188,0.903659,1457,2035040 +52,search,3160.86,0.86258,0.139367,21.1566,17.7708,51.847,0.903666,1465,2035040 +53,insert,57.602,-1.0,-1.0,-1.0,-1.0,26.42,0.920326,1468,2078341 +54,search,3203.74,0.86312,0.138866,21.1651,17.7897,17.336,0.920539,1469,2078341 +55,insert,398.497,-1.0,-1.0,-1.0,-1.0,409.142,1.06886,1529,2399905 +56,search,3307.74,0.86598,0.138903,20.8097,17.9137,106.556,1.06975,1550,2399905 +57,insert,24.266,-1.0,-1.0,-1.0,-1.0,30.39,1.07846,1555,2419836 +58,search,3378.47,0.86491,0.139268,21.0153,18.057,32.327,1.07847,1557,2419836 +59,insert,245.099,-1.0,-1.0,-1.0,-1.0,151.647,1.17751,1578,2643083 +60,search,3483.57,0.85878,0.145052,22.3401,19.5367,56.963,1.17805,1587,2643083 +61,insert,14.836,-1.0,-1.0,-1.0,-1.0,15.744,1.18214,1589,2653064 +62,search,3523.8,0.85835,0.145686,22.4059,19.6398,16.362,1.18214,1590,2653064 +63,insert,5.228,-1.0,-1.0,-1.0,-1.0,8.636,1.18347,1590,2656118 +64,search,3542.63,0.85918,0.145274,22.3934,19.6431,17.117,1.18356,1592,2656118 +65,insert,98.241,-1.0,-1.0,-1.0,-1.0,68.465,1.20998,1608,2723424 +66,search,3608.58,0.8598,0.14485,22.3636,19.6494,13.138,1.20998,1609,2723424 +67,insert,53.68,-1.0,-1.0,-1.0,-1.0,69.099,1.22946,1624,2769021 +68,search,3625.45,0.86142,0.143871,22.2031,19.5608,13.308,1.22946,1625,2769021 +69,insert,57.788,-1.0,-1.0,-1.0,-1.0,69.951,1.25255,1637,2821777 +70,search,3650.21,0.86296,0.143051,21.9621,19.4246,15.579,1.25273,1638,2821777 +71,insert,17.468,-1.0,-1.0,-1.0,-1.0,17.826,1.25823,1640,2834921 +72,search,3687.49,0.86411,0.142111,21.8769,19.3657,10.379,1.25823,1640,2834921 +73,insert,9.043,-1.0,-1.0,-1.0,-1.0,9.037,1.26175,1640,2842044 +74,search,3622.89,0.86421,0.142082,21.8687,19.36,10.593,1.26175,1640,2842044 +75,insert,25.854,-1.0,-1.0,-1.0,-1.0,26.221,1.26836,1643,2858890 +76,search,3673.33,0.86424,0.141994,21.7892,19.3139,10.378,1.26836,1643,2858890 +77,insert,36.67,-1.0,-1.0,-1.0,-1.0,16.391,1.27777,1644,2882818 +78,search,3515.92,0.86404,0.141792,21.8563,19.3335,10.448,1.27777,1644,2882818 +79,insert,516.736,-1.0,-1.0,-1.0,-1.0,32.008,1.30594,1648,2947806 +80,search,3644.34,0.86364,0.142101,21.945,19.4665,10.085,1.30594,1648,2947806 +81,insert,41.13,-1.0,-1.0,-1.0,-1.0,32.416,1.31784,1652,2976895 +82,search,3618.55,0.86536,0.141395,21.7271,19.3549,23.194,1.31822,1655,2976895 +83,insert,16.364,-1.0,-1.0,-1.0,-1.0,26.413,1.32418,1658,2990682 +84,search,3585.86,0.86536,0.141607,21.7303,19.3555,9.955,1.32418,1658,2990682 +85,insert,40.194,-1.0,-1.0,-1.0,-1.0,15.823,1.33888,1659,3025613 +86,search,3749.05,0.86622,0.141088,21.5963,19.3407,11.276,1.33888,1659,3025613 +87,insert,667.543,-1.0,-1.0,-1.0,-1.0,702.849,1.54517,1771,3468632 +88,search,4125.22,0.87163,0.137083,21.0748,19.0563,116.053,1.54609,1788,3468632 +89,insert,434.835,-1.0,-1.0,-1.0,-1.0,559.573,1.70351,1881,3831692 +90,search,4379.66,0.87643,0.133152,20.5457,18.6692,60.419,1.70362,1889,3831692 +91,insert,41.588,-1.0,-1.0,-1.0,-1.0,32.255,1.71402,1891,3864067 +92,search,4446.58,0.87675,0.132666,20.5604,18.6668,22.044,1.71419,1893,3864067 +93,insert,269.092,-1.0,-1.0,-1.0,-1.0,274.718,1.81794,1934,4103827 +94,search,4567.02,0.87736,0.133347,20.505,18.6745,73.326,1.81856,1944,4103827 +95,insert,19.518,-1.0,-1.0,-1.0,-1.0,25.466,1.82449,1946,4119898 +96,search,4592.71,0.87754,0.133017,20.4252,18.6205,20.469,1.82449,1946,4119898 +97,insert,12.393,-1.0,-1.0,-1.0,-1.0,32.21,1.8272,1948,4129367 +98,search,4438.91,0.87748,0.132938,20.4399,18.6349,19.884,1.8272,1948,4129367 +99,insert,6.19,-1.0,-1.0,-1.0,-1.0,18.924,1.8287,1948,4134502 +100,search,4572.13,0.87752,0.132966,20.4259,18.6289,19.844,1.8287,1948,4134502 +101,insert,42.201,-1.0,-1.0,-1.0,-1.0,74.621,1.84239,1958,4164482 +102,search,4624.09,0.87805,0.132783,20.3931,18.6031,27.773,1.84243,1959,4164482 +103,insert,17.344,-1.0,-1.0,-1.0,-1.0,25.205,1.84798,1960,4178601 +104,search,4629.28,0.87887,0.132246,20.3717,18.6031,37.265,1.84839,1963,4178601 +105,insert,14.028,-1.0,-1.0,-1.0,-1.0,19.603,1.8523,1963,4187774 +106,search,4625.17,0.8788,0.132205,20.364,18.5929,26.858,1.85234,1964,4187774 +107,insert,24.552,-1.0,-1.0,-1.0,-1.0,26.947,1.85767,1965,4200109 +108,search,4626.83,0.87878,0.132318,20.3727,18.6062,21.665,1.85767,1965,4200109 +109,insert,588.079,-1.0,-1.0,-1.0,-1.0,448.028,2.01751,2040,4557867 +110,search,4929.65,0.88226,0.129651,20.0292,18.5651,62.383,2.01827,2046,4557867 +111,insert,41.996,-1.0,-1.0,-1.0,-1.0,52.224,2.03033,2053,4587252 +112,search,4932.13,0.88255,0.129516,19.9377,18.5272,23.869,2.03033,2053,4587252 +113,insert,17.388,-1.0,-1.0,-1.0,-1.0,22.481,2.03487,2053,4600056 +114,search,4923.82,0.88282,0.129248,19.8918,18.5044,23.383,2.03487,2053,4600056 +115,insert,40.076,-1.0,-1.0,-1.0,-1.0,51.11,2.0448,2058,4627422 +116,search,4912.78,0.88314,0.129103,19.8187,18.4959,23.431,2.0448,2058,4627422 +117,insert,19.72,-1.0,-1.0,-1.0,-1.0,22.324,2.05058,2058,4639292 +118,search,4925.89,0.8832,0.128945,19.8098,18.4701,24.69,2.05058,2058,4639292 +119,insert,7.489,-1.0,-1.0,-1.0,-1.0,22.544,2.05277,2058,4643423 +120,search,4936.77,0.88329,0.128863,19.8028,18.4657,24.165,2.05277,2058,4643423 +121,insert,20.916,-1.0,-1.0,-1.0,-1.0,34.72,2.05829,2060,4657252 +122,search,4981.14,0.88396,0.128376,19.7944,18.4832,28.731,2.05834,2061,4657252 +123,insert,440.351,-1.0,-1.0,-1.0,-1.0,393.619,2.18802,2110,4938477 +124,search,5154.4,0.88517,0.128615,19.5603,18.3541,138.387,2.1892,2126,4938477 +125,insert,62.888,-1.0,-1.0,-1.0,-1.0,98.223,2.20625,2137,4980492 +126,search,5165.66,0.88528,0.128865,19.4884,18.3759,42.501,2.20626,2139,4980492 +127,insert,74.395,-1.0,-1.0,-1.0,-1.0,95.393,2.22756,2154,5030515 +128,search,5190.51,0.88593,0.128553,19.4324,18.3591,41.906,2.22788,2156,5030515 +129,delete,17.913,-1.0,-1.0,-1.0,-1.0,25.557,2.22739,2156,5009391 +130,search,5178.89,0.88585,0.128609,19.43,18.3786,26.26,2.22739,2156,5009391 +131,delete,4.61,-1.0,-1.0,-1.0,-1.0,26.161,2.22739,2156,5004093 +132,search,5161.23,0.88598,0.128629,19.4055,18.3651,27.925,2.22739,2156,5004093 +133,delete,12.353,-1.0,-1.0,-1.0,-1.0,25.46,2.22723,2156,4991787 +134,search,4934.01,0.88589,0.128658,19.4177,18.3638,27.523,2.22723,2156,4991787 +135,delete,18.448,-1.0,-1.0,-1.0,-1.0,25.642,2.22623,2156,4974857 +136,search,4962.35,0.88602,0.12844,19.4134,18.3911,27.346,2.22623,2156,4974857 +137,delete,4.441,-1.0,-1.0,-1.0,-1.0,25.743,2.22623,2156,4971386 +138,search,4918.04,0.88587,0.128664,19.4149,18.3973,27.667,2.22623,2156,4971386 +139,delete,9.117,-1.0,-1.0,-1.0,-1.0,25.365,2.22623,2156,4963487 +140,search,4822.54,0.88574,0.128627,19.4484,18.4051,27.066,2.22623,2156,4963487 +141,delete,20.855,-1.0,-1.0,-1.0,-1.0,25.411,2.22477,2156,4941830 +142,search,5159.78,0.8858,0.128558,19.4561,18.4336,26.745,2.22477,2156,4941830 +143,delete,18.68,-1.0,-1.0,-1.0,-1.0,25.542,2.22286,2156,4925657 +144,search,5141.05,0.88574,0.12858,19.4585,18.4319,27.7,2.22286,2156,4925657 +145,delete,2.57,-1.0,-1.0,-1.0,-1.0,25.388,2.22258,2156,4922686 +146,search,5150.9,0.88559,0.12859,19.4607,18.4243,27.894,2.22258,2156,4922686 +147,delete,11.208,-1.0,-1.0,-1.0,-1.0,25.241,2.22237,2156,4913636 +148,search,5156.6,0.88575,0.128589,19.4718,18.4394,27.872,2.22237,2156,4913636 +149,delete,226.035,-1.0,-1.0,-1.0,-1.0,26.204,2.19594,2156,4717250 +150,search,4828.65,0.88448,0.129753,19.5149,18.5196,28.129,2.19594,2156,4717250 +151,delete,190.593,-1.0,-1.0,-1.0,-1.0,26.209,2.15983,2156,4560269 +152,search,4760.54,0.88354,0.130214,19.6133,18.5502,28.061,2.15983,2156,4560269 +153,delete,40.378,-1.0,-1.0,-1.0,-1.0,25.797,2.14888,2156,4521936 +154,search,4701.02,0.88231,0.131004,19.7578,18.628,27.56,2.14888,2156,4521936 +155,delete,21.538,-1.0,-1.0,-1.0,-1.0,25.562,2.1453,2156,4502222 +156,search,4623.31,0.88226,0.131292,19.789,18.6663,27.56,2.1453,2156,4502222 +157,delete,44.056,-1.0,-1.0,-1.0,-1.0,25.672,2.13806,2156,4456039 +158,search,4622.15,0.88186,0.131449,19.8555,18.7279,27.541,2.13806,2156,4456039 +159,delete,306.839,-1.0,-1.0,-1.0,-1.0,24.69,2.0221,2156,4143922 +160,search,4763,0.88064,0.131761,20.0619,18.8865,28.948,2.0221,2156,4143922 +161,delete,57.895,-1.0,-1.0,-1.0,-1.0,26.154,2.01502,2156,4101445 +162,search,4757.49,0.88061,0.131996,20.0804,18.9124,28.731,2.01502,2156,4101445 +163,delete,32.376,-1.0,-1.0,-1.0,-1.0,25.569,2.00505,2156,4080175 +164,search,4780.71,0.88001,0.13261,20.123,18.9419,28.213,2.00505,2156,4080175 +165,delete,44.832,-1.0,-1.0,-1.0,-1.0,25.764,1.99596,2156,4047313 +166,search,4890.05,0.87977,0.13286,20.116,18.9171,28.59,1.99596,2156,4047313 +167,delete,11.397,-1.0,-1.0,-1.0,-1.0,25.566,1.99405,2156,4040738 +168,search,4833.99,0.87941,0.133098,20.1303,18.9118,27.724,1.99405,2156,4040738 +169,delete,24.823,-1.0,-1.0,-1.0,-1.0,25.367,1.98666,2156,4022674 +170,search,4885.51,0.87895,0.133293,20.2177,18.9867,27.508,1.98666,2156,4022674 +171,delete,10.251,-1.0,-1.0,-1.0,-1.0,25.533,1.98329,2156,4015835 +172,search,4856.18,0.87889,0.133397,20.2252,18.9875,28.831,1.98329,2156,4015835 +173,delete,46.534,-1.0,-1.0,-1.0,-1.0,25.729,1.9715,2156,3986424 +174,search,4830.26,0.87768,0.134187,20.3609,19.0836,28.745,1.9715,2156,3986424 +175,delete,223.824,-1.0,-1.0,-1.0,-1.0,25.469,1.90142,2156,3804693 +176,search,4718.66,0.87645,0.134148,20.6133,19.1572,28.607,1.90142,2156,3804693 +177,delete,28.814,-1.0,-1.0,-1.0,-1.0,25.554,1.89195,2156,3786352 +178,search,4676.78,0.87598,0.134221,20.6848,19.1789,28.407,1.89195,2156,3786352 +179,delete,311.522,-1.0,-1.0,-1.0,-1.0,25.727,1.78583,2156,3556994 +180,search,4458.28,0.87173,0.135348,21.2028,19.3133,38.785,1.78591,2157,3556994 +181,delete,42.346,-1.0,-1.0,-1.0,-1.0,25.885,1.77456,2157,3526824 +182,search,4508.32,0.87141,0.135263,21.2739,19.3705,28.013,1.77456,2157,3526824 +183,delete,183.158,-1.0,-1.0,-1.0,-1.0,25.121,1.70473,2157,3350245 +184,search,4587.8,0.86489,0.139895,22.0921,19.7246,28.144,1.70473,2157,3350245 +185,delete,19.294,-1.0,-1.0,-1.0,-1.0,25.646,1.69876,2157,3340234 +186,search,4614.79,0.86483,0.139711,22.0941,19.7163,29.058,1.69876,2157,3340234 +187,delete,247.624,-1.0,-1.0,-1.0,-1.0,26.262,1.61039,2157,3150857 +188,search,4542.1,0.86825,0.137815,21.541,19.1875,29.323,1.61039,2157,3150857 +189,delete,16.291,-1.0,-1.0,-1.0,-1.0,25.62,1.60613,2157,3143609 +190,search,4626.18,0.86793,0.137925,21.5527,19.1642,28.667,1.60613,2157,3143609 +191,delete,4.211,-1.0,-1.0,-1.0,-1.0,25.356,1.60532,2157,3141038 +192,search,4626.87,0.86799,0.137911,21.5548,19.1613,28.39,1.60532,2157,3141038 +193,delete,88.542,-1.0,-1.0,-1.0,-1.0,27.029,1.57657,2157,3081734 +194,search,4603.9,0.86648,0.138724,21.7186,19.2356,28.375,1.57657,2157,3081734 +195,delete,53.738,-1.0,-1.0,-1.0,-1.0,26.248,1.55782,2157,3043966 +196,search,4520.8,0.86567,0.13938,21.8145,19.2978,27.817,1.55782,2157,3043966 +197,delete,48.247,-1.0,-1.0,-1.0,-1.0,26.284,1.54167,2157,3008145 +198,search,4545.97,0.86506,0.139286,21.9121,19.3272,27.87,1.54167,2157,3008145 +199,delete,13.242,-1.0,-1.0,-1.0,-1.0,25.998,1.53776,2157,2999384 +200,search,4557.1,0.86463,0.139577,21.9858,19.3904,27.883,1.53776,2157,2999384 +201,delete,8.886,-1.0,-1.0,-1.0,-1.0,25.75,1.53387,2157,2993528 +202,search,4573.25,0.86454,0.139724,22.0115,19.3967,29.247,1.53387,2157,2993528 +203,delete,23.835,-1.0,-1.0,-1.0,-1.0,25.537,1.52663,2157,2980973 +204,search,4284.43,0.86439,0.139713,22.019,19.3891,29.465,1.52663,2157,2980973 +205,delete,39.989,-1.0,-1.0,-1.0,-1.0,25.914,1.51751,2157,2960291 +206,search,4489.24,0.86422,0.139675,22.0462,19.4043,28.42,1.51751,2157,2960291 +207,delete,58.631,-1.0,-1.0,-1.0,-1.0,25.753,1.49751,2157,2920620 +208,search,4509.48,0.8639,0.139818,22.0269,19.3626,28.69,1.49751,2157,2920620 +209,delete,33.556,-1.0,-1.0,-1.0,-1.0,25.962,1.48663,2157,2900501 +210,search,4546.77,0.86317,0.140219,22.1533,19.4234,28.657,1.48663,2157,2900501 +211,delete,13.992,-1.0,-1.0,-1.0,-1.0,25.445,1.48207,2157,2891660 +212,search,4462.44,0.86283,0.140591,22.1774,19.4375,27.871,1.48207,2157,2891660 +213,delete,22.484,-1.0,-1.0,-1.0,-1.0,25.73,1.4725,2157,2873257 +214,search,4546.73,0.86182,0.141173,22.2549,19.4645,27.851,1.4725,2157,2873257 +215,delete,360.116,-1.0,-1.0,-1.0,-1.0,24.555,1.30946,2157,2537571 +216,search,4373.68,0.85573,0.14394,23.03,19.7104,29.605,1.30946,2157,2537571 +217,delete,277.173,-1.0,-1.0,-1.0,-1.0,24.817,1.19384,2157,2308194 +218,search,4280.43,0.85041,0.146946,23.7204,20.157,28.968,1.19384,2157,2308194 +219,delete,37.195,-1.0,-1.0,-1.0,-1.0,26.382,1.18208,2157,2285820 +220,search,4327.78,0.84915,0.147933,23.835,20.2401,29.06,1.18208,2157,2285820 +221,delete,292.139,-1.0,-1.0,-1.0,-1.0,25.55,1.07904,2157,2082858 +222,search,4258.14,0.84847,0.148016,24.0135,20.3769,29.155,1.07904,2157,2082858 +223,delete,19.551,-1.0,-1.0,-1.0,-1.0,25.836,1.07244,2157,2071207 +224,search,4363.44,0.8466,0.148741,24.1423,20.4217,28.428,1.07244,2157,2071207 +225,delete,11.46,-1.0,-1.0,-1.0,-1.0,25.866,1.06874,2157,2065400 +226,search,4248.87,0.84634,0.148911,24.1557,20.4035,28.535,1.06874,2157,2065400 +227,delete,5.468,-1.0,-1.0,-1.0,-1.0,25.665,1.06695,2157,2062105 +228,search,4344.44,0.84636,0.148823,24.1913,20.4172,28.231,1.06695,2157,2062105 +229,delete,29.337,-1.0,-1.0,-1.0,-1.0,26.043,1.05691,2157,2039610 +230,search,4296.81,0.84453,0.149053,24.5457,20.6348,28.377,1.05691,2157,2039610 +231,delete,16.441,-1.0,-1.0,-1.0,-1.0,25.779,1.05112,2157,2027795 +232,search,4355.52,0.84377,0.149205,24.6821,20.6599,28.263,1.05112,2157,2027795 +233,delete,7.141,-1.0,-1.0,-1.0,-1.0,25.871,1.04822,2157,2022859 +234,search,4327.33,0.84359,0.149064,24.7145,20.6756,30.656,1.04822,2157,2022859 +235,delete,13.511,-1.0,-1.0,-1.0,-1.0,25.81,1.04464,2157,2016264 +236,search,4261.65,0.84358,0.149063,24.7298,20.6732,29.706,1.04464,2157,2016264 +237,delete,369.253,-1.0,-1.0,-1.0,-1.0,26.72,0.924536,2157,1782866 +238,search,4306.43,0.838,0.153124,25.4226,21.0895,29.824,0.924536,2157,1782866 +239,delete,36.379,-1.0,-1.0,-1.0,-1.0,26.451,0.911847,2157,1758931 +240,search,4269.73,0.83609,0.153589,25.6725,21.1656,28.901,0.911847,2157,1758931 +241,delete,13.639,-1.0,-1.0,-1.0,-1.0,26.134,0.906906,2157,1751275 +242,search,4185.14,0.8354,0.1538,25.7673,21.2139,29.259,0.906906,2157,1751275 +243,delete,29.147,-1.0,-1.0,-1.0,-1.0,26.402,0.897618,2157,1733264 +244,search,4121.92,0.83143,0.155579,26.9636,22.4739,29.077,0.897618,2157,1733264 +245,delete,15.71,-1.0,-1.0,-1.0,-1.0,26.127,0.891938,2157,1722658 +246,search,4260.98,0.83066,0.155937,27.1447,22.6701,28.446,0.891938,2157,1722658 +247,delete,5.46,-1.0,-1.0,-1.0,-1.0,25.767,0.889939,2157,1719601 +248,search,4270.59,0.82993,0.156119,27.337,22.8898,28.564,0.889939,2157,1719601 +249,delete,12.204,-1.0,-1.0,-1.0,-1.0,25.862,0.885132,2157,1711648 +250,search,4184.71,0.82928,0.156483,27.4542,22.9667,30.992,0.885132,2157,1711648 +251,delete,334.872,-1.0,-1.0,-1.0,-1.0,39.362,0.762469,2158,1470624 +252,search,4225.45,0.82819,0.156192,28.6022,24.2926,29.991,0.762469,2158,1470624 +253,delete,52.671,-1.0,-1.0,-1.0,-1.0,27.002,0.747616,2158,1442070 +254,search,4230.89,0.82654,0.156397,29.0905,24.701,30.157,0.747616,2158,1442070 +255,delete,59.152,-1.0,-1.0,-1.0,-1.0,26.542,0.729171,2158,1405549 +256,search,4103.03,0.82083,0.159156,29.8269,25.0357,29.2,0.729171,2158,1405549 +257,insert,14.114,-1.0,-1.0,-1.0,-1.0,25.679,0.730899,2158,1416288 +258,search,4135.56,0.82131,0.159031,29.7062,24.9671,29.262,0.730899,2158,1416288 +259,insert,27.946,-1.0,-1.0,-1.0,-1.0,26.187,0.736486,2158,1443010 +260,search,4189.15,0.82249,0.159485,29.4463,24.9074,28.325,0.736486,2158,1443010 +261,insert,3.34,-1.0,-1.0,-1.0,-1.0,25.739,0.736822,2158,1447529 +262,search,4115.37,0.82316,0.159063,29.3614,24.8817,28.28,0.736822,2158,1447529 +263,insert,170.884,-1.0,-1.0,-1.0,-1.0,83.175,0.773697,2160,1569110 +264,search,4224.27,0.82722,0.159735,28.468,24.4792,85.44,0.773695,2164,1569110 +265,insert,76.676,-1.0,-1.0,-1.0,-1.0,26.255,0.789744,2164,1636119 +266,search,4270.27,0.8328,0.156434,27.8924,24.2468,78.455,0.789748,2169,1636119 +267,insert,41.389,-1.0,-1.0,-1.0,-1.0,42.387,0.799427,2171,1665152 +268,search,4254.76,0.83496,0.155953,27.5911,24.2011,29.731,0.799427,2171,1665152 +269,insert,413.543,-1.0,-1.0,-1.0,-1.0,175.557,0.89276,2185,1916952 +270,search,4343.85,0.83758,0.154804,26.9966,23.8127,110.868,0.892758,2192,1916952 +271,insert,6.068,-1.0,-1.0,-1.0,-1.0,35.509,0.893753,2193,1920898 +272,search,4325.44,0.83857,0.154145,26.9142,23.8152,48.69,0.893754,2195,1920898 +273,insert,31.617,-1.0,-1.0,-1.0,-1.0,26.411,0.901482,2195,1942757 +274,search,4318.62,0.84122,0.153066,26.4468,23.4535,29.105,0.901482,2195,1942757 +275,insert,648.039,-1.0,-1.0,-1.0,-1.0,269.614,1.06044,2223,2328372 +276,search,4488.44,0.84589,0.150628,25.7651,23.1174,83.691,1.06043,2230,2328372 +277,insert,48.368,-1.0,-1.0,-1.0,-1.0,26.281,1.07206,2230,2363257 +278,search,4490.63,0.84772,0.149327,25.5889,23.0383,27.286,1.07206,2230,2363257 +279,insert,35.264,-1.0,-1.0,-1.0,-1.0,25.798,1.08104,2230,2388933 +280,search,4463.48,0.84853,0.149108,25.5018,23.0004,28.277,1.08104,2230,2388933 +281,insert,427.199,-1.0,-1.0,-1.0,-1.0,131.256,1.21004,2250,2684315 +282,search,3376.62,0.8499,0.149353,25.1426,22.8688,46.759,1.21032,2254,2684315 +283,insert,342.288,-1.0,-1.0,-1.0,-1.0,135.081,1.39481,2281,3109157 +284,search,3551.58,0.85713,0.144358,24.2364,22.4297,64.495,1.39484,2290,3109157 +285,insert,11.289,-1.0,-1.0,-1.0,-1.0,18.136,1.39958,2290,3122751 +286,search,3574.38,0.85761,0.144192,24.1713,22.4137,28.887,1.39958,2292,3122751 +287,insert,28.112,-1.0,-1.0,-1.0,-1.0,22.159,1.41475,2293,3163679 +288,search,3568.48,0.85826,0.144268,24.0742,22.3686,18.851,1.41475,2293,3163679 +289,insert,240.918,-1.0,-1.0,-1.0,-1.0,140.547,1.55095,2317,3472031 +290,search,3684.91,0.86252,0.141948,23.4338,22.0721,49.971,1.55096,2323,3472031 +291,insert,19.492,-1.0,-1.0,-1.0,-1.0,18.164,1.56276,2323,3495577 +292,search,3688.63,0.86469,0.141022,23.2741,22.0288,28.027,1.56276,2325,3495577 +293,insert,11.627,-1.0,-1.0,-1.0,-1.0,26.919,1.57188,2327,3515193 +294,search,3713.54,0.86469,0.141355,23.1969,22.0472,18.952,1.57188,2327,3515193 +295,insert,144.894,-1.0,-1.0,-1.0,-1.0,70.941,1.65897,2337,3723063 +296,search,3787.19,0.86775,0.139383,22.7609,21.8177,25.848,1.65897,2338,3723063 +297,insert,2.889,-1.0,-1.0,-1.0,-1.0,22.252,1.66035,2339,3727399 +298,search,3754.52,0.86773,0.139319,22.7574,21.8104,19.883,1.66035,2339,3727399 +299,insert,56.873,-1.0,-1.0,-1.0,-1.0,22.49,1.68617,2340,3788002 +300,search,3819.59,0.87095,0.137514,22.4226,21.5306,19.794,1.68617,2340,3788002 +301,insert,475.938,-1.0,-1.0,-1.0,-1.0,262.819,1.94647,2410,4370866 +302,search,4107.62,0.89534,0.121218,19.3653,19.9771,47.656,1.94659,2424,4370866 +303,insert,38.254,-1.0,-1.0,-1.0,-1.0,10.167,1.96889,2424,4420306 +304,search,4117.14,0.8949,0.121793,19.4215,20.0113,10.593,1.96889,2424,4420306 +305,insert,243.639,-1.0,-1.0,-1.0,-1.0,267.654,2.13559,2463,4789669 +306,search,4286.64,0.89617,0.121268,19.1775,19.8657,82.34,2.13568,2474,4789669 +307,insert,19.163,-1.0,-1.0,-1.0,-1.0,12,2.14405,2475,4815550 diff --git a/scripts/big_ann_perf_numbers/scan_0.1_no_aps_refinment_wma_delete.csv b/scripts/big_ann_perf_numbers/scan_0.1_no_aps_refinment_wma_delete.csv new file mode 100644 index 00000000..429108ea --- /dev/null +++ b/scripts/big_ann_perf_numbers/scan_0.1_no_aps_refinment_wma_delete.csv @@ -0,0 +1,1280 @@ +step_num,step_type,latency_ms,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +2,search,2510.87,0.78885,0.157032,27.0527,17.7427,5.294,0.0184873,1024,38806 +3,insert,17.992,-1.0,-1.0,-1.0,-1.0,12.211,0.0226399,1020,49334 +4,search,1897.33,0.80641,0.155898,25.2135,17.2457,16.15,0.0226509,1017,49334 +5,insert,27.331,-1.0,-1.0,-1.0,-1.0,161.442,0.0331879,1008,73557 +6,search,1836.14,0.8825,0.132204,18.2191,16.1598,126.261,0.0332585,1010,73557 +7,insert,26.905,-1.0,-1.0,-1.0,-1.0,132.605,0.0429522,1009,95766 +8,search,1853.5,0.87644,0.134428,18.092,15.5519,99.892,0.0430787,1012,95766 +9,insert,4.133,-1.0,-1.0,-1.0,-1.0,90.646,0.0448135,1012,100025 +10,search,1790.94,0.87833,0.131411,17.9568,15.225,95.3,0.0448135,1012,100025 +11,insert,18.763,-1.0,-1.0,-1.0,-1.0,83.347,0.0498246,1016,111417 +12,search,1824.12,0.87698,0.132463,17.9426,15.0717,77.56,0.0498241,1017,111417 +13,insert,23.346,-1.0,-1.0,-1.0,-1.0,79.317,0.0609413,1019,137139 +14,search,1829.88,0.86956,0.13772,18.1671,14.9146,18.292,0.0613979,1021,137139 +15,insert,18.767,-1.0,-1.0,-1.0,-1.0,11.578,0.0700046,1024,156710 +16,search,1862.19,0.86521,0.138489,18.3854,14.6427,14.23,0.0700071,1026,156710 +17,insert,4.574,-1.0,-1.0,-1.0,-1.0,11.715,0.0722099,1030,161773 +18,search,1867.57,0.86589,0.138037,18.336,14.6029,15.972,0.07242,1034,161773 +19,insert,32.365,-1.0,-1.0,-1.0,-1.0,9.038,0.0790778,1036,177161 +20,search,1879.51,0.86879,0.135162,18.2326,14.4954,13.795,0.079081,1038,177161 +21,insert,395.862,-1.0,-1.0,-1.0,-1.0,216.196,0.201797,1100,448898 +22,search,2093.61,0.85609,0.137369,20.1353,15.4665,65.331,0.201875,1119,448898 +23,insert,389.892,-1.0,-1.0,-1.0,-1.0,290.344,0.3288,1186,733493 +24,search,2311.41,0.84861,0.140954,21.0543,16.1878,116.111,0.329953,1226,733493 +25,insert,37.211,-1.0,-1.0,-1.0,-1.0,30.434,0.347036,1234,777443 +26,search,2350.33,0.84505,0.143622,21.5492,16.4151,20.538,0.347098,1239,777443 +27,insert,28.429,-1.0,-1.0,-1.0,-1.0,23.696,0.358705,1244,805394 +28,search,2414.18,0.84439,0.144252,21.5598,16.4382,15.145,0.358809,1246,805394 +29,insert,69.083,-1.0,-1.0,-1.0,-1.0,72.422,0.385949,1266,866391 +30,search,2466.8,0.84816,0.143571,21.2681,16.4132,32.437,0.385959,1272,866391 +31,insert,490.382,-1.0,-1.0,-1.0,-1.0,330.674,0.554488,1355,1239816 +32,search,2685.18,0.84428,0.146244,21.9635,17.0705,58.568,0.55463,1371,1239816 +33,insert,30.903,-1.0,-1.0,-1.0,-1.0,32.743,0.574816,1383,1291211 +34,search,2714.91,0.84521,0.145599,22.1202,17.2401,23.198,0.574899,1388,1291211 +35,insert,32.543,-1.0,-1.0,-1.0,-1.0,31.841,0.586482,1398,1324978 +36,search,2768.03,0.84496,0.145398,22.0964,17.2303,10.165,0.586482,1398,1324978 +37,insert,62.535,-1.0,-1.0,-1.0,-1.0,43.626,0.606693,1407,1371885 +38,search,2792.24,0.84707,0.144021,22.1626,17.499,22.124,0.606804,1411,1371885 +39,insert,12.952,-1.0,-1.0,-1.0,-1.0,7.515,0.60949,1411,1379335 +40,search,2822.45,0.84787,0.143573,22.1817,17.5559,8.231,0.60949,1411,1379335 +41,insert,41.932,-1.0,-1.0,-1.0,-1.0,26.331,0.623605,1416,1413312 +42,search,2797.33,0.84873,0.143042,22.1136,17.6173,8.04,0.623605,1416,1413312 +43,insert,12.656,-1.0,-1.0,-1.0,-1.0,19.089,0.62779,1421,1423411 +44,search,2819.4,0.84895,0.142384,22.1871,17.6613,10.247,0.62779,1421,1423411 +45,insert,233.263,-1.0,-1.0,-1.0,-1.0,39.909,0.642786,1432,1457559 +46,search,2844,0.85025,0.142214,22.1521,17.7282,8.364,0.642786,1432,1457559 +47,insert,267.434,-1.0,-1.0,-1.0,-1.0,287.766,0.7478,1481,1688593 +48,search,3002.87,0.85338,0.144828,21.7492,17.7945,99.084,0.747934,1495,1688593 +49,insert,55.199,-1.0,-1.0,-1.0,-1.0,40.902,0.763193,1504,1723505 +50,search,2981.46,0.8542,0.144603,21.688,17.8515,25.353,0.763202,1508,1723505 +51,insert,406.42,-1.0,-1.0,-1.0,-1.0,323.47,0.90266,1583,2035040 +52,search,3249.42,0.86035,0.143096,21.4189,18.2485,42.354,0.902663,1592,2035040 +53,insert,46.754,-1.0,-1.0,-1.0,-1.0,27.989,0.920688,1597,2078341 +54,search,3281.34,0.86001,0.142983,21.4531,18.2694,9.85,0.920688,1597,2078341 +55,insert,413.547,-1.0,-1.0,-1.0,-1.0,459.84,1.06742,1672,2399905 +56,search,3552.58,0.86391,0.141969,21.1968,18.328,128.988,1.0684,1699,2399905 +57,insert,24.698,-1.0,-1.0,-1.0,-1.0,15.742,1.07695,1701,2419836 +58,search,3569.92,0.86325,0.142288,21.2595,18.3659,38.284,1.07698,1708,2419836 +59,insert,269.239,-1.0,-1.0,-1.0,-1.0,159.421,1.1761,1729,2643083 +60,search,3638.98,0.85309,0.152819,22.8749,19.9851,44.941,1.17614,1735,2643083 +61,insert,16.19,-1.0,-1.0,-1.0,-1.0,15.403,1.18034,1736,2653064 +62,search,3655.61,0.85333,0.152467,22.9282,20.0064,16.153,1.18039,1737,2653064 +63,insert,4.151,-1.0,-1.0,-1.0,-1.0,12.124,1.18138,1737,2656118 +64,search,3633.9,0.85343,0.152435,22.9259,20.0216,13.174,1.18138,1737,2656118 +65,insert,86.234,-1.0,-1.0,-1.0,-1.0,109.786,1.21057,1768,2723424 +66,search,3716.87,0.85431,0.150963,22.9123,20.0327,14.347,1.21057,1768,2723424 +67,insert,49.027,-1.0,-1.0,-1.0,-1.0,83.741,1.23077,1788,2769021 +68,search,3760.49,0.85583,0.149979,22.7181,19.9901,22.765,1.23086,1790,2769021 +69,insert,60.273,-1.0,-1.0,-1.0,-1.0,72.098,1.25285,1805,2821777 +70,search,3808.74,0.85829,0.148571,22.4546,19.8502,20.195,1.25285,1806,2821777 +71,insert,22.349,-1.0,-1.0,-1.0,-1.0,28.494,1.25871,1810,2834921 +72,search,3848.06,0.85951,0.147675,22.3654,19.7941,28.525,1.2589,1812,2834921 +73,insert,9.799,-1.0,-1.0,-1.0,-1.0,15.601,1.26118,1812,2842044 +74,search,3862,0.85942,0.14784,22.3547,19.7868,16.648,1.26118,1812,2842044 +75,insert,30.891,-1.0,-1.0,-1.0,-1.0,27.062,1.26972,1815,2858890 +76,search,3845.98,0.85954,0.147692,22.2835,19.7363,23.779,1.2699,1816,2858890 +77,insert,33.306,-1.0,-1.0,-1.0,-1.0,22.667,1.27909,1817,2882818 +78,search,3925.13,0.85907,0.148255,22.3278,19.7485,16.603,1.27909,1817,2882818 +79,insert,469.443,-1.0,-1.0,-1.0,-1.0,31.291,1.30629,1821,2947806 +80,search,4394.29,0.85997,0.147338,22.3646,19.8183,11.012,1.30629,1821,2947806 +81,insert,18.05,-1.0,-1.0,-1.0,-1.0,14.638,1.31727,1823,2976895 +82,search,2979.97,0.86133,0.146238,22.1634,19.7422,11.299,1.31727,1823,2976895 +83,insert,9.38,-1.0,-1.0,-1.0,-1.0,25.596,1.32417,1829,2990682 +84,search,3114.54,0.86122,0.146055,22.1316,19.7434,11.634,1.32417,1829,2990682 +85,insert,24.363,-1.0,-1.0,-1.0,-1.0,32.79,1.33769,1837,3025613 +86,search,2998.78,0.8627,0.145252,22.0215,19.7358,14.857,1.33779,1838,3025613 +87,insert,339.628,-1.0,-1.0,-1.0,-1.0,428.053,1.54249,1956,3468632 +88,search,4326.23,0.86737,0.142602,21.3978,19.4815,102.349,1.5428,1968,3468632 +89,insert,572.502,-1.0,-1.0,-1.0,-1.0,790.31,1.70218,2080,3831692 +90,search,4595.32,0.87385,0.13641,20.801,19.034,108.454,1.70282,2093,3831692 +91,insert,43.126,-1.0,-1.0,-1.0,-1.0,62.001,1.71585,2102,3864067 +92,search,4613.09,0.87431,0.135531,20.7768,19.0553,46.046,1.71599,2106,3864067 +93,insert,336.949,-1.0,-1.0,-1.0,-1.0,256.014,1.82029,2147,4103827 +94,search,4736.66,0.87541,0.134931,20.7224,19.0464,60.971,1.82068,2152,4103827 +95,insert,20.053,-1.0,-1.0,-1.0,-1.0,49.179,1.82706,2158,4119898 +96,search,4734.31,0.8757,0.135004,20.6472,18.996,34.293,1.82725,2159,4119898 +97,insert,11.546,-1.0,-1.0,-1.0,-1.0,25.891,1.83071,2159,4129367 +98,search,4737.63,0.8758,0.13482,20.6529,18.9927,34.546,1.83091,2161,4129367 +99,insert,8.566,-1.0,-1.0,-1.0,-1.0,30.993,1.83401,2162,4134502 +100,search,4755.38,0.87601,0.134731,20.6395,18.9914,41.147,1.83431,2165,4134502 +101,insert,40.52,-1.0,-1.0,-1.0,-1.0,48.615,1.84703,2169,4164482 +102,search,4768.65,0.87619,0.134728,20.5941,18.9886,28.01,1.84703,2169,4164482 +103,insert,25.527,-1.0,-1.0,-1.0,-1.0,38.153,1.85371,2172,4178601 +104,search,4815.29,0.87643,0.134586,20.5674,18.972,28.654,1.85371,2172,4178601 +105,insert,14.549,-1.0,-1.0,-1.0,-1.0,42.168,1.85761,2175,4187774 +106,search,4820.41,0.87637,0.134725,20.5533,18.9576,28.761,1.85761,2175,4187774 +107,insert,22.995,-1.0,-1.0,-1.0,-1.0,44.912,1.86285,2177,4200109 +108,search,4596.47,0.87629,0.1348,20.5572,18.9789,27.758,1.86285,2177,4200109 +109,insert,566.298,-1.0,-1.0,-1.0,-1.0,551.967,2.01867,2268,4557867 +110,search,3894.16,0.87927,0.133266,20.2417,18.9546,56.973,2.01936,2280,4557867 +111,insert,17.108,-1.0,-1.0,-1.0,-1.0,30.656,2.03011,2286,4587252 +112,search,3910.36,0.87976,0.13298,20.1785,18.9401,26.966,2.03048,2288,4587252 +113,insert,6.74,-1.0,-1.0,-1.0,-1.0,22.023,2.03475,2289,4600056 +114,search,3871.89,0.87983,0.133041,20.1453,18.9389,19.401,2.03475,2289,4600056 +115,insert,18.266,-1.0,-1.0,-1.0,-1.0,38.622,2.0463,2297,4627422 +116,search,3912.43,0.88064,0.132247,20.059,18.8716,22.081,2.04634,2298,4627422 +117,insert,8.143,-1.0,-1.0,-1.0,-1.0,18.55,2.05045,2298,4639292 +118,search,3904.84,0.88056,0.132404,20.0593,18.8578,23.538,2.05045,2298,4639292 +119,insert,5.514,-1.0,-1.0,-1.0,-1.0,22.996,2.0539,2299,4643423 +120,search,3945.45,0.88049,0.132455,20.0604,18.8648,19.738,2.0539,2299,4643423 +121,insert,12.382,-1.0,-1.0,-1.0,-1.0,22.345,2.05979,2300,4657252 +122,search,3931.43,0.88123,0.131974,20.0423,18.8702,27.411,2.05997,2302,4657252 +123,insert,202.928,-1.0,-1.0,-1.0,-1.0,279.064,2.19066,2361,4938477 +124,search,4072.44,0.88257,0.132693,19.7338,18.6822,88.191,2.19211,2380,4938477 +125,insert,33.54,-1.0,-1.0,-1.0,-1.0,33.448,2.2076,2386,4980492 +126,search,4044.42,0.88261,0.132702,19.6938,18.6786,22.979,2.20761,2388,4980492 +127,insert,35.448,-1.0,-1.0,-1.0,-1.0,35.554,2.22594,2399,5030515 +128,search,4111.11,0.88355,0.132007,19.5949,18.6696,15.99,2.22605,2401,5030515 +129,delete,10.875,-1.0,-1.0,-1.0,-1.0,15.381,2.22518,2390,5009391 +130,search,4065.59,0.88353,0.132007,19.6651,18.7597,11.302,2.22518,2390,5009391 +131,delete,2.677,-1.0,-1.0,-1.0,-1.0,10.668,2.22518,2390,5004093 +132,search,4046.49,0.88367,0.131942,19.6413,18.7374,11.049,2.22518,2390,5004093 +133,delete,6.279,-1.0,-1.0,-1.0,-1.0,10.115,2.22491,2390,4991787 +134,search,4046.43,0.88351,0.131898,19.6427,18.7376,11.551,2.22491,2390,4991787 +135,delete,9.434,-1.0,-1.0,-1.0,-1.0,27.575,2.22258,2387,4974857 +136,search,4039.39,0.883,0.132265,19.6683,18.7623,12.185,2.22258,2387,4974857 +137,delete,2.362,-1.0,-1.0,-1.0,-1.0,10.36,2.22258,2387,4971386 +138,search,4057.48,0.88287,0.132469,19.6712,18.7573,11.958,2.22258,2387,4971386 +139,delete,5.447,-1.0,-1.0,-1.0,-1.0,10.429,2.22245,2387,4963487 +140,search,4062.17,0.88288,0.132341,19.6986,18.7787,12.053,2.22245,2387,4963487 +141,delete,13.308,-1.0,-1.0,-1.0,-1.0,20.167,2.21949,2386,4941830 +142,search,4037.05,0.88321,0.132407,19.697,18.7964,12.319,2.21949,2386,4941830 +143,delete,10.279,-1.0,-1.0,-1.0,-1.0,17.547,2.21729,2385,4925657 +144,search,4028.73,0.88324,0.132271,19.7095,18.8049,12.33,2.21729,2385,4925657 +145,delete,1.743,-1.0,-1.0,-1.0,-1.0,14.006,2.21658,2384,4922686 +146,search,4014.98,0.88303,0.13252,19.724,18.8127,12.185,2.21658,2384,4922686 +147,delete,5.1,-1.0,-1.0,-1.0,-1.0,10.464,2.21658,2384,4913636 +148,search,4012.84,0.88304,0.132429,19.7508,18.8428,11.787,2.21658,2384,4913636 +149,delete,117.69,-1.0,-1.0,-1.0,-1.0,133.638,2.17954,2362,4717250 +150,search,3930.48,0.88261,0.133304,19.8735,18.9888,13.71,2.17954,2362,4717250 +151,delete,101.013,-1.0,-1.0,-1.0,-1.0,196.393,2.13132,2331,4560269 +152,search,3865.91,0.88165,0.132922,19.9984,19.005,20.433,2.13132,2331,4560269 +153,delete,18.784,-1.0,-1.0,-1.0,-1.0,57.252,2.12073,2324,4521936 +154,search,3839.32,0.88037,0.133873,20.1779,19.1118,20.624,2.12073,2324,4521936 +155,delete,12.051,-1.0,-1.0,-1.0,-1.0,25.355,2.11791,2323,4502222 +156,search,3837.44,0.8804,0.133817,20.1913,19.1337,20.708,2.11791,2323,4502222 +157,delete,26.591,-1.0,-1.0,-1.0,-1.0,30.605,2.1101,2321,4456039 +158,search,3820.92,0.87991,0.134283,20.2717,19.214,20.866,2.1101,2321,4456039 +159,delete,208.357,-1.0,-1.0,-1.0,-1.0,453.862,1.97109,2238,4143922 +160,search,3635.29,0.87769,0.135237,20.4918,19.3176,20.514,1.97109,2238,4143922 +161,delete,33.627,-1.0,-1.0,-1.0,-1.0,28.623,1.96262,2236,4101445 +162,search,3628.3,0.87768,0.135404,20.5386,19.3597,20.361,1.96262,2236,4101445 +163,delete,12.006,-1.0,-1.0,-1.0,-1.0,18.079,1.96003,2236,4080175 +164,search,3601.03,0.87722,0.135556,20.5887,19.3723,20.028,1.96003,2236,4080175 +165,delete,21.628,-1.0,-1.0,-1.0,-1.0,18.438,1.95454,2236,4047313 +166,search,3607.15,0.87701,0.135766,20.6206,19.4205,19.911,1.95454,2236,4047313 +167,delete,5.064,-1.0,-1.0,-1.0,-1.0,18.025,1.95281,2236,4040738 +168,search,3615.71,0.87678,0.136059,20.6495,19.4505,19.906,1.95281,2236,4040738 +169,delete,14.479,-1.0,-1.0,-1.0,-1.0,29.901,1.94716,2234,4022674 +170,search,3580.43,0.87651,0.136134,20.7229,19.4958,20.262,1.94716,2234,4022674 +171,delete,5.534,-1.0,-1.0,-1.0,-1.0,18.005,1.94567,2234,4015835 +172,search,3604.81,0.87631,0.136348,20.7356,19.4954,20.262,1.94567,2234,4015835 +173,delete,27.388,-1.0,-1.0,-1.0,-1.0,18.51,1.9367,2234,3986424 +174,search,3563.9,0.87545,0.137163,20.8375,19.5712,20.1,1.9367,2234,3986424 +175,delete,126.439,-1.0,-1.0,-1.0,-1.0,321.052,1.85196,2168,3804693 +176,search,3496.29,0.8735,0.137228,21.2564,19.8103,24.443,1.85224,2169,3804693 +177,delete,11.721,-1.0,-1.0,-1.0,-1.0,18.031,1.8479,2169,3786352 +178,search,3468.17,0.87312,0.137254,21.317,19.8345,20.786,1.8479,2169,3786352 +179,delete,202.676,-1.0,-1.0,-1.0,-1.0,303.802,1.72733,2085,3556994 +180,search,3421.15,0.86702,0.138478,22.2013,20.0513,24.376,1.72759,2086,3556994 +181,delete,18.816,-1.0,-1.0,-1.0,-1.0,17.531,1.72174,2085,3526824 +182,search,3285.16,0.86674,0.138693,22.2484,20.1216,21.141,1.72179,2086,3526824 +183,delete,127.528,-1.0,-1.0,-1.0,-1.0,339.736,1.63432,2004,3350245 +184,search,3160.55,0.85619,0.147825,23.3857,20.7234,18.28,1.63432,2004,3350245 +185,delete,7.062,-1.0,-1.0,-1.0,-1.0,17.24,1.63146,2002,3340234 +186,search,3138.15,0.85866,0.145296,23.1659,20.6214,17.868,1.63146,2002,3340234 +187,delete,122.46,-1.0,-1.0,-1.0,-1.0,191.066,1.53657,1967,3150857 +188,search,3093.07,0.86246,0.142132,22.3533,19.9071,26.262,1.53672,1969,3150857 +189,delete,4.71,-1.0,-1.0,-1.0,-1.0,15.849,1.53573,1969,3143609 +190,search,3072.21,0.86151,0.142415,22.4986,20.0336,17.636,1.53573,1969,3143609 +191,delete,1.648,-1.0,-1.0,-1.0,-1.0,15.639,1.53544,1969,3141038 +192,search,3061.69,0.86152,0.142414,22.503,20.0285,18.518,1.53544,1969,3141038 +193,delete,49.868,-1.0,-1.0,-1.0,-1.0,20.851,1.51712,1968,3081734 +194,search,3067.98,0.85982,0.144074,22.7053,20.0646,17.784,1.51712,1968,3081734 +195,delete,30.833,-1.0,-1.0,-1.0,-1.0,42.124,1.50054,1962,3043966 +196,search,3047.56,0.85906,0.144593,22.8204,20.1718,17.827,1.50054,1962,3043966 +197,delete,27.39,-1.0,-1.0,-1.0,-1.0,43.851,1.4878,1959,3008145 +198,search,3060.06,0.85802,0.144847,22.8781,20.1934,18.21,1.4878,1959,3008145 +199,delete,9.807,-1.0,-1.0,-1.0,-1.0,15.645,1.48378,1959,2999384 +200,search,3045.74,0.85797,0.144687,22.9556,20.2378,17.403,1.48378,1959,2999384 +201,delete,5.271,-1.0,-1.0,-1.0,-1.0,15.576,1.48111,1959,2993528 +202,search,3020.62,0.85774,0.144815,22.9821,20.2325,17.54,1.48111,1959,2993528 +203,delete,10.097,-1.0,-1.0,-1.0,-1.0,15.46,1.47758,1959,2980973 +204,search,3032.81,0.85726,0.145024,22.9876,20.2275,17.555,1.47758,1959,2980973 +205,delete,18.217,-1.0,-1.0,-1.0,-1.0,15.917,1.46936,1959,2960291 +206,search,3016.76,0.85721,0.145069,23.0212,20.2673,17.644,1.46936,1959,2960291 +207,delete,35.144,-1.0,-1.0,-1.0,-1.0,35.479,1.44714,1945,2920620 +208,search,2981.37,0.85644,0.146025,23.0808,20.3003,17.75,1.44714,1945,2920620 +209,delete,15.106,-1.0,-1.0,-1.0,-1.0,19.778,1.44065,1944,2900501 +210,search,2987.89,0.85582,0.146046,23.1376,20.2996,17.621,1.44065,1944,2900501 +211,delete,6.934,-1.0,-1.0,-1.0,-1.0,15.277,1.43712,1944,2891660 +212,search,2993.39,0.85585,0.146071,23.1515,20.3094,17.213,1.43712,1944,2891660 +213,delete,12.804,-1.0,-1.0,-1.0,-1.0,24.594,1.42917,1941,2873257 +214,search,2979.66,0.85506,0.146632,23.2227,20.3069,17.09,1.42917,1941,2873257 +215,delete,253.796,-1.0,-1.0,-1.0,-1.0,446.583,1.24234,1829,2537571 +216,search,2754.77,0.84921,0.14989,23.9383,20.441,26.915,1.24251,1831,2537571 +217,delete,155.398,-1.0,-1.0,-1.0,-1.0,281.1,1.13259,1761,2308194 +218,search,2609.24,0.84494,0.153393,24.4765,20.7676,15.126,1.13259,1761,2308194 +219,delete,14.009,-1.0,-1.0,-1.0,-1.0,20.575,1.12608,1759,2285820 +220,search,2630.88,0.84293,0.154444,24.6461,20.8375,15.547,1.12608,1759,2285820 +221,delete,148.965,-1.0,-1.0,-1.0,-1.0,268.937,1.01224,1666,2082858 +222,search,2477.86,0.8393,0.156557,25.1999,21.0657,14.019,1.01224,1666,2082858 +223,delete,9.23,-1.0,-1.0,-1.0,-1.0,14.901,1.0089,1665,2071207 +224,search,2472.94,0.83761,0.157449,25.2589,21.0267,14.529,1.0089,1665,2071207 +225,delete,4.836,-1.0,-1.0,-1.0,-1.0,12.31,1.00783,1665,2065400 +226,search,2471.69,0.8374,0.157636,25.2722,21.0276,14.312,1.00783,1665,2065400 +227,delete,3.22,-1.0,-1.0,-1.0,-1.0,12.337,1.00687,1665,2062105 +228,search,2470.23,0.83712,0.157576,25.3045,21.037,14.151,1.00687,1665,2062105 +229,delete,16.339,-1.0,-1.0,-1.0,-1.0,23.149,0.9991,1662,2039610 +230,search,2432.97,0.83571,0.15796,25.4911,21.0527,14.325,0.9991,1662,2039610 +231,delete,9.41,-1.0,-1.0,-1.0,-1.0,22.53,0.992544,1660,2027795 +232,search,2442.6,0.83513,0.157973,25.5951,21.0602,14.21,0.992544,1660,2027795 +233,delete,3.819,-1.0,-1.0,-1.0,-1.0,12.34,0.991211,1660,2022859 +234,search,2413.68,0.83482,0.158083,25.6066,21.0523,14.153,0.991211,1660,2022859 +235,delete,5.122,-1.0,-1.0,-1.0,-1.0,14.374,0.989339,1656,2016264 +236,search,2398.28,0.83417,0.158355,25.6888,21.0969,13.852,0.989339,1656,2016264 +237,delete,177.277,-1.0,-1.0,-1.0,-1.0,296.172,0.865572,1557,1782866 +238,search,2297.55,0.83006,0.161128,26.1586,21.3209,30.543,0.866272,1560,1782866 +239,delete,14.333,-1.0,-1.0,-1.0,-1.0,32.925,0.855528,1552,1758931 +240,search,2272.19,0.82854,0.161613,26.4253,21.4717,13.116,0.855528,1552,1758931 +241,delete,4.268,-1.0,-1.0,-1.0,-1.0,16.808,0.853507,1551,1751275 +242,search,2251.2,0.82817,0.161747,26.4988,21.4934,13.107,0.853507,1551,1751275 +243,delete,11.7,-1.0,-1.0,-1.0,-1.0,11.653,0.850073,1551,1733264 +244,search,2282.77,0.82629,0.162439,26.6447,21.5022,13.045,0.850073,1551,1733264 +245,delete,7.354,-1.0,-1.0,-1.0,-1.0,14.793,0.846959,1550,1722658 +246,search,2257.05,0.82555,0.162322,26.7402,21.5217,13.493,0.846959,1550,1722658 +247,delete,2.493,-1.0,-1.0,-1.0,-1.0,11.622,0.846386,1550,1719601 +248,search,2281.74,0.82523,0.162438,26.7692,21.5252,12.995,0.846386,1550,1719601 +249,delete,5.416,-1.0,-1.0,-1.0,-1.0,14.756,0.843263,1549,1711648 +250,search,2297.42,0.82415,0.162777,26.7984,21.5352,13.516,0.843263,1549,1711648 +251,delete,184.749,-1.0,-1.0,-1.0,-1.0,273.886,0.715505,1441,1470624 +252,search,2124.82,0.82335,0.162223,27.1209,21.5951,23.327,0.71584,1443,1470624 +253,delete,18.787,-1.0,-1.0,-1.0,-1.0,29.352,0.705441,1437,1442070 +254,search,2096.86,0.82177,0.162752,27.2435,21.6241,12.284,0.705441,1437,1442070 +255,delete,31.416,-1.0,-1.0,-1.0,-1.0,28.923,0.687757,1424,1405549 +256,search,2064.03,0.81792,0.165585,27.6843,21.7469,11.957,0.687757,1424,1405549 +257,insert,5.925,-1.0,-1.0,-1.0,-1.0,10.222,0.689618,1424,1416288 +258,search,2107.34,0.8182,0.16529,27.6103,21.7173,11.901,0.689618,1424,1416288 +259,insert,18.096,-1.0,-1.0,-1.0,-1.0,19.107,0.696107,1426,1443010 +260,search,2082.32,0.81806,0.165817,27.5624,21.7689,12.094,0.696107,1426,1443010 +261,insert,2.277,-1.0,-1.0,-1.0,-1.0,10.256,0.696853,1426,1447529 +262,search,2100.92,0.81891,0.165462,27.473,21.7392,12.121,0.696853,1426,1447529 +263,insert,93.909,-1.0,-1.0,-1.0,-1.0,25.877,0.734676,1429,1569110 +264,search,2133.75,0.82069,0.167103,26.8997,21.6203,17.766,0.73476,1430,1569110 +265,insert,54.653,-1.0,-1.0,-1.0,-1.0,18.328,0.757392,1432,1636119 +266,search,2112.58,0.82597,0.164696,26.4671,21.5103,12.076,0.757392,1432,1636119 +267,insert,24.993,-1.0,-1.0,-1.0,-1.0,25.055,0.767888,1435,1665152 +268,search,2126.63,0.82768,0.16473,26.1749,21.4363,11.81,0.767888,1435,1665152 +269,insert,191.249,-1.0,-1.0,-1.0,-1.0,66.769,0.86483,1445,1916952 +270,search,2232.49,0.8273,0.165135,26.0742,21.4135,33.571,0.864829,1448,1916952 +271,insert,3.63,-1.0,-1.0,-1.0,-1.0,10.704,0.866337,1448,1920898 +272,search,2193.28,0.82736,0.16492,26.032,21.407,12.095,0.866337,1448,1920898 +273,insert,18.481,-1.0,-1.0,-1.0,-1.0,12.708,0.876632,1449,1942757 +274,search,2214.24,0.83006,0.16331,25.7995,21.3159,11.876,0.876632,1449,1942757 +275,insert,320.733,-1.0,-1.0,-1.0,-1.0,195.504,1.04179,1480,2328372 +276,search,2350.67,0.83448,0.160991,25.4694,21.2769,82.428,1.04185,1493,2328372 +277,insert,26.353,-1.0,-1.0,-1.0,-1.0,11.046,1.05501,1493,2363257 +278,search,2371.52,0.83605,0.160407,25.3155,21.2328,41.523,1.05511,1500,2363257 +279,insert,20.423,-1.0,-1.0,-1.0,-1.0,11.216,1.06561,1500,2388933 +280,search,2407.83,0.83718,0.159445,25.2312,21.1948,16.506,1.06561,1501,2388933 +281,insert,183.965,-1.0,-1.0,-1.0,-1.0,104.981,1.19524,1512,2684315 +282,search,2492.13,0.83677,0.160492,25.3616,21.5698,19.952,1.19556,1514,2684315 +283,insert,333.32,-1.0,-1.0,-1.0,-1.0,196.387,1.38706,1556,3109157 +284,search,2621.9,0.84381,0.156855,24.5354,21.1729,71.166,1.38706,1569,3109157 +285,insert,9.398,-1.0,-1.0,-1.0,-1.0,14.405,1.39244,1570,3122751 +286,search,2631.28,0.84452,0.156419,24.5279,21.1891,37.851,1.39254,1576,3122751 +287,insert,30.937,-1.0,-1.0,-1.0,-1.0,17.856,1.40912,1577,3163679 +288,search,2656.42,0.84439,0.156573,24.4413,21.1451,17.482,1.40912,1578,3163679 +289,insert,227.542,-1.0,-1.0,-1.0,-1.0,181.255,1.54573,1611,3472031 +290,search,2770.36,0.8488,0.15505,23.9579,21.0016,65.804,1.54591,1619,3472031 +291,insert,21.224,-1.0,-1.0,-1.0,-1.0,14.031,1.55666,1620,3495577 +292,search,2772.04,0.85099,0.153805,23.7766,20.9749,36.807,1.55666,1624,3495577 +293,insert,12.77,-1.0,-1.0,-1.0,-1.0,25.178,1.56465,1627,3515193 +294,search,2819.03,0.8508,0.153968,23.7452,21.0188,18.263,1.56465,1628,3515193 +295,insert,151.958,-1.0,-1.0,-1.0,-1.0,162.832,1.65793,1660,3723063 +296,search,2874.47,0.855,0.151723,23.2139,20.781,39.295,1.65811,1665,3723063 +297,insert,3.472,-1.0,-1.0,-1.0,-1.0,11.936,1.65967,1665,3727399 +298,search,2880.43,0.85481,0.151958,23.2004,20.7771,20.402,1.65967,1666,3727399 +299,insert,52.73,-1.0,-1.0,-1.0,-1.0,29.312,1.68545,1672,3788002 +300,search,2935.55,0.85791,0.149034,22.9831,20.6083,17.687,1.68551,1673,3788002 +301,insert,443.376,-1.0,-1.0,-1.0,-1.0,522.936,1.94992,1812,4370866 +302,search,3293.47,0.88338,0.133219,20.2272,19.6253,91.483,1.95055,1843,4370866 +303,insert,27.242,-1.0,-1.0,-1.0,-1.0,59.855,1.97069,1853,4420306 +304,search,3299.07,0.88193,0.133859,20.3161,19.6364,17.859,1.97098,1854,4420306 +305,insert,194.903,-1.0,-1.0,-1.0,-1.0,309.532,2.13859,1911,4789669 +306,search,3450.71,0.88433,0.132829,19.9728,19.497,138.796,2.13988,1936,4789669 +307,insert,16.021,-1.0,-1.0,-1.0,-1.0,16.602,2.1481,1938,4815550 +308,search,3469.02,0.88473,0.132234,19.891,19.4585,42.407,2.1482,1944,4815550 +309,insert,5.55,-1.0,-1.0,-1.0,-1.0,12.971,2.15137,1944,4823345 +310,search,3485.4,0.88533,0.13201,19.8575,19.4432,16.576,2.15151,1945,4823345 +311,insert,9.633,-1.0,-1.0,-1.0,-1.0,12.662,2.15751,1945,4843493 +312,search,3525.93,0.88493,0.132405,19.9153,19.4709,13.858,2.15751,1945,4843493 +313,insert,31.596,-1.0,-1.0,-1.0,-1.0,61.231,2.17661,1954,4885489 +314,search,3560.63,0.88554,0.132065,19.8348,19.4153,17.747,2.17661,1955,4885489 +315,insert,5.255,-1.0,-1.0,-1.0,-1.0,12.472,2.17981,1955,4892335 +316,search,3510.67,0.88539,0.132098,19.8837,19.4734,13.594,2.17981,1955,4892335 +317,insert,35.303,-1.0,-1.0,-1.0,-1.0,44.096,2.19613,1964,4932996 +318,search,3535.19,0.88565,0.13189,19.8342,19.4305,21.391,2.19645,1966,4932996 +319,insert,390.584,-1.0,-1.0,-1.0,-1.0,420.137,2.4086,2050,5430684 +320,search,3765.28,0.89008,0.127945,19.2677,19.1523,114.015,2.4105,2079,5430684 +321,insert,29.723,-1.0,-1.0,-1.0,-1.0,70.109,2.42658,2099,5471239 +322,search,3818.29,0.89035,0.127552,19.1785,19.1051,42.486,2.42705,2108,5471239 +323,insert,70.88,-1.0,-1.0,-1.0,-1.0,118.492,2.47349,2137,5575560 +324,search,3870.29,0.89114,0.126874,19.1313,19.1053,28.493,2.47371,2141,5575560 +325,insert,936.469,-1.0,-1.0,-1.0,-1.0,544.041,2.70261,2221,6069499 +326,search,4085.11,0.89535,0.124076,18.5299,18.7791,185.349,2.70398,2258,6069499 +327,insert,41.762,-1.0,-1.0,-1.0,-1.0,54.66,2.7317,2270,6139647 +328,search,4153.75,0.89631,0.123221,18.3642,18.6525,69.543,2.7319,2282,6139647 +329,insert,5.247,-1.0,-1.0,-1.0,-1.0,17.599,2.73442,2282,6146884 +330,search,4200.29,0.89651,0.123116,18.332,18.6469,18.758,2.73442,2282,6146884 +331,insert,29.805,-1.0,-1.0,-1.0,-1.0,61.897,2.75343,2294,6188816 +332,search,4232.27,0.89644,0.123271,18.3477,18.6497,28.423,2.75362,2296,6188816 +333,insert,1.355,-1.0,-1.0,-1.0,-1.0,17.572,2.75399,2296,6190810 +334,search,4230.47,0.89637,0.123338,18.345,18.6488,19.015,2.75399,2296,6190810 +335,insert,35.778,-1.0,-1.0,-1.0,-1.0,39.598,2.77145,2304,6230108 +336,search,4251.48,0.89704,0.122932,18.2916,18.6219,18.681,2.77145,2304,6230108 +337,insert,14.422,-1.0,-1.0,-1.0,-1.0,28.879,2.7796,2306,6249699 +338,search,4241.69,0.89756,0.122546,18.2252,18.604,23.028,2.7796,2307,6249699 +339,insert,38.176,-1.0,-1.0,-1.0,-1.0,49.526,2.79706,2316,6290226 +340,search,4270.92,0.89803,0.121979,18.1315,18.5398,21.836,2.79714,2317,6290226 +341,insert,7.023,-1.0,-1.0,-1.0,-1.0,22.975,2.80047,2319,6297556 +342,search,4273.91,0.89797,0.122105,18.1255,18.5533,18.356,2.80047,2319,6297556 +343,insert,23.493,-1.0,-1.0,-1.0,-1.0,52.485,2.81354,2328,6330843 +344,search,4243.22,0.89822,0.121976,18.099,18.5404,24.531,2.81379,2330,6330843 +345,insert,25.659,-1.0,-1.0,-1.0,-1.0,50.888,2.82906,2340,6370265 +346,search,4296.43,0.89919,0.121283,18.0581,18.5243,30.94,2.82947,2344,6370265 +347,insert,325.928,-1.0,-1.0,-1.0,-1.0,564.027,3.03133,2469,6831086 +348,search,4596.63,0.90249,0.118953,17.587,18.2818,107.995,3.03407,2494,6831086 +349,insert,34.934,-1.0,-1.0,-1.0,-1.0,44.402,3.05232,2503,6876154 +350,search,4628.88,0.90311,0.118635,17.5586,18.2489,28.937,3.0526,2508,6876154 +351,insert,279.276,-1.0,-1.0,-1.0,-1.0,391.172,3.23727,2593,7288266 +352,search,4838.8,0.90164,0.121343,17.5257,18.1502,129.658,3.23869,2621,7288266 +353,insert,34.803,-1.0,-1.0,-1.0,-1.0,43.909,3.25699,2630,7333132 +354,search,4864.58,0.9023,0.120799,17.491,18.1536,55.557,3.25741,2640,7333132 +355,insert,269.038,-1.0,-1.0,-1.0,-1.0,500.907,3.42642,2747,7696838 +356,search,5095.65,0.90502,0.119472,17.1148,17.9863,135.12,3.42836,2773,7696838 +357,insert,12.483,-1.0,-1.0,-1.0,-1.0,36.753,3.4355,2777,7714498 +358,search,5045.1,0.90509,0.119502,17.0812,17.9673,31.587,3.43588,2781,7714498 +359,insert,7.134,-1.0,-1.0,-1.0,-1.0,28.24,3.43964,2784,7725755 +360,search,5079.92,0.90557,0.119212,17.025,17.9236,20.278,3.43964,2785,7725755 +361,insert,41.042,-1.0,-1.0,-1.0,-1.0,52.03,3.46528,2794,7789312 +362,search,5106.99,0.90652,0.118452,16.9221,17.8621,31.767,3.46565,2798,7789312 +363,insert,14.71,-1.0,-1.0,-1.0,-1.0,20.818,3.47075,2799,7803163 +364,search,5192.12,0.90633,0.118703,16.909,17.849,17.471,3.47075,2799,7803163 +365,insert,45.39,-1.0,-1.0,-1.0,-1.0,82.239,3.49651,2814,7863722 +366,search,5197.53,0.90691,0.118265,16.8294,17.7693,26.044,3.49681,2816,7863722 +367,insert,25.397,-1.0,-1.0,-1.0,-1.0,43.454,3.50868,2825,7895271 +368,search,5219.27,0.90752,0.117739,16.7723,17.7433,20.653,3.50868,2826,7895271 +369,insert,53.127,-1.0,-1.0,-1.0,-1.0,75.696,3.53592,2842,7961194 +370,search,5231.85,0.90804,0.117275,16.7122,17.7048,31.6,3.53645,2847,7961194 +371,insert,7.917,-1.0,-1.0,-1.0,-1.0,20.509,3.54012,2849,7970239 +372,search,5216.28,0.90803,0.1176,16.6961,17.7058,16.976,3.54012,2849,7970239 +373,insert,31.52,-1.0,-1.0,-1.0,-1.0,48.699,3.55836,2859,8010868 +374,search,5242.86,0.90859,0.116914,16.6505,17.6737,40.26,3.55922,2865,8010868 +375,insert,19.462,-1.0,-1.0,-1.0,-1.0,33.972,3.56874,2869,8040698 +376,search,5371.04,0.90871,0.117064,16.6138,17.6514,21.775,3.56887,2870,8040698 +377,insert,43.733,-1.0,-1.0,-1.0,-1.0,89.043,3.59598,2888,8104748 +378,search,5397.43,0.90915,0.116873,16.5022,17.5713,38.519,3.59637,2894,8104748 +379,insert,5.354,-1.0,-1.0,-1.0,-1.0,24.032,3.59877,2896,8109755 +380,search,5360.47,0.90921,0.116794,16.4999,17.5681,23.258,3.59899,2898,8109755 +381,insert,14.142,-1.0,-1.0,-1.0,-1.0,40.459,3.60637,2903,8130382 +382,search,5356.35,0.9093,0.11681,16.4846,17.5567,26.357,3.60677,2905,8130382 +383,insert,21.75,-1.0,-1.0,-1.0,-1.0,56.739,3.6157,2915,8153290 +384,search,5358.06,0.90963,0.116699,16.444,17.5315,21.717,3.6157,2916,8153290 +385,delete,9.798,-1.0,-1.0,-1.0,-1.0,16.976,3.61566,2916,8138873 +386,search,5374.49,0.90978,0.116655,16.4404,17.5435,18.319,3.61566,2916,8138873 +387,delete,13.178,-1.0,-1.0,-1.0,-1.0,17.678,3.61453,2916,8115069 +388,search,5386.07,0.91003,0.116394,16.4206,17.5232,20.608,3.61453,2916,8115069 +389,delete,11.745,-1.0,-1.0,-1.0,-1.0,23.327,3.61354,2915,8101157 +390,search,5378.98,0.90978,0.116603,16.4185,17.5218,18.638,3.61354,2915,8101157 +391,delete,51.951,-1.0,-1.0,-1.0,-1.0,46.455,3.59335,2914,8014644 +392,search,5386.79,0.9091,0.11651,16.5601,17.5774,37.071,3.59337,2917,8014644 +393,delete,22.653,-1.0,-1.0,-1.0,-1.0,17.479,3.59271,2917,7978358 +394,search,5361.96,0.90882,0.116643,16.5858,17.579,25.172,3.59271,2918,7978358 +395,delete,14.391,-1.0,-1.0,-1.0,-1.0,47.477,3.58671,2914,7957094 +396,search,5392.39,0.90873,0.116631,16.6155,17.5884,22.974,3.58684,2915,7957094 +397,delete,77.025,-1.0,-1.0,-1.0,-1.0,145.573,3.55177,2907,7823916 +398,search,5220.47,0.90866,0.116875,16.6141,17.5791,43.278,3.55207,2911,7823916 +399,delete,3.408,-1.0,-1.0,-1.0,-1.0,17.243,3.55165,2911,7818430 +400,search,5268.8,0.90873,0.116914,16.6373,17.6121,19.476,3.55165,2911,7818430 +401,delete,11.631,-1.0,-1.0,-1.0,-1.0,20.425,3.54919,2910,7800702 +402,search,5288.18,0.90833,0.117373,16.669,17.629,19.469,3.54919,2910,7800702 +403,delete,203.733,-1.0,-1.0,-1.0,-1.0,502.199,3.45965,2852,7517858 +404,search,5115.8,0.90769,0.117617,16.849,17.7301,24.768,3.45985,2853,7517858 +405,delete,44.31,-1.0,-1.0,-1.0,-1.0,17.122,3.45599,2853,7451637 +406,search,5072.64,0.90798,0.117583,16.828,17.7858,18.541,3.45599,2853,7451637 +407,delete,66.374,-1.0,-1.0,-1.0,-1.0,132.239,3.4263,2840,7360417 +408,search,5237.95,0.90762,0.117703,16.9023,17.8276,18.974,3.4263,2840,7360417 +409,delete,135.721,-1.0,-1.0,-1.0,-1.0,262.562,3.33262,2817,7131620 +410,search,5122.4,0.90787,0.117324,16.777,17.6487,38.608,3.33262,2820,7131620 +411,delete,175.167,-1.0,-1.0,-1.0,-1.0,345.101,3.2481,2772,6867617 +412,search,4979.09,0.90702,0.117955,16.8449,17.6781,23.975,3.24815,2773,6867617 +413,delete,10.001,-1.0,-1.0,-1.0,-1.0,22.323,3.24529,2772,6850098 +414,search,4962.54,0.90677,0.118137,16.8754,17.7056,23.694,3.24545,2773,6850098 +415,delete,47.317,-1.0,-1.0,-1.0,-1.0,48.782,3.22679,2770,6782921 +416,search,4957.11,0.90664,0.118503,16.8746,17.6942,18.324,3.22679,2770,6782921 +417,delete,150.89,-1.0,-1.0,-1.0,-1.0,320.965,3.15803,2739,6562039 +418,search,4893.02,0.90583,0.118968,16.9232,17.6831,48.758,3.15825,2742,6562039 +419,delete,20.116,-1.0,-1.0,-1.0,-1.0,16.415,3.15572,2742,6536285 +420,search,4848.14,0.9061,0.118681,16.9328,17.7013,35.592,3.15572,2744,6536285 +421,delete,16.786,-1.0,-1.0,-1.0,-1.0,67.442,3.14431,2738,6510820 +422,search,4889.31,0.906,0.118949,16.8834,17.6589,29.537,3.14459,2740,6510820 +423,delete,130.123,-1.0,-1.0,-1.0,-1.0,318.034,3.06726,2686,6334168 +424,search,4764.71,0.90425,0.119959,17.0926,17.8105,17.513,3.06726,2686,6334168 +425,delete,15.666,-1.0,-1.0,-1.0,-1.0,15.349,3.06427,2686,6316443 +426,search,4742.42,0.90402,0.120161,17.1117,17.8367,17.285,3.06427,2686,6316443 +427,delete,37.862,-1.0,-1.0,-1.0,-1.0,15.818,3.05068,2686,6266345 +428,search,4758.29,0.90359,0.120538,17.1783,17.8742,17.783,3.05068,2686,6266345 +429,delete,375.527,-1.0,-1.0,-1.0,-1.0,606.975,2.84772,2579,5883847 +430,search,4505.51,0.89414,0.126702,18.2726,18.2846,76.02,2.84867,2590,5883847 +431,delete,65.004,-1.0,-1.0,-1.0,-1.0,150.07,2.81391,2570,5801380 +432,search,4455.75,0.89388,0.126593,18.4275,18.404,24.268,2.81407,2571,5801380 +433,delete,160.422,-1.0,-1.0,-1.0,-1.0,385.991,2.72084,2517,5607567 +434,search,4342.06,0.89227,0.127489,18.6718,18.4994,41.668,2.72158,2520,5607567 +435,delete,80.821,-1.0,-1.0,-1.0,-1.0,45.387,2.68848,2515,5512176 +436,search,4363.23,0.89153,0.127892,18.6768,18.4943,22.607,2.68847,2516,5512176 +437,delete,7.875,-1.0,-1.0,-1.0,-1.0,31.306,2.68302,2514,5501141 +438,search,4329.37,0.8917,0.12784,18.6575,18.4784,16.468,2.68302,2514,5501141 +439,delete,81.165,-1.0,-1.0,-1.0,-1.0,278.715,2.6205,2482,5369822 +440,search,4241.24,0.89179,0.127894,18.5716,18.4056,27.865,2.6209,2484,5369822 +441,delete,23.624,-1.0,-1.0,-1.0,-1.0,26.268,2.60815,2483,5338985 +442,search,4224.32,0.89208,0.127643,18.5909,18.4407,17.191,2.60815,2483,5338985 +443,delete,25.95,-1.0,-1.0,-1.0,-1.0,74.761,2.5917,2474,5307279 +444,search,4231.09,0.89219,0.127654,18.4896,18.2809,27.07,2.5919,2476,5307279 +445,delete,33.688,-1.0,-1.0,-1.0,-1.0,29.165,2.57727,2474,5268382 +446,search,4273.79,0.89205,0.127456,18.5394,18.3365,16.607,2.57727,2474,5268382 +447,delete,305.14,-1.0,-1.0,-1.0,-1.0,408.007,2.40473,2384,4922787 +448,search,4035.58,0.88853,0.129326,19.0401,18.5828,35.831,2.40473,2386,4922787 +449,delete,27.367,-1.0,-1.0,-1.0,-1.0,20.099,2.39553,2385,4887227 +450,search,4046.61,0.88836,0.129109,18.9766,18.5188,24.275,2.39553,2386,4887227 +451,delete,79.166,-1.0,-1.0,-1.0,-1.0,114.116,2.35118,2364,4795082 +452,search,4000.52,0.88733,0.130036,19.0369,18.5393,15.855,2.35118,2364,4795082 +453,delete,241.265,-1.0,-1.0,-1.0,-1.0,681.014,2.19765,2293,4500175 +454,search,3826.53,0.88509,0.131616,19.4417,18.7688,89.293,2.19834,2301,4500175 +455,delete,23.764,-1.0,-1.0,-1.0,-1.0,31.695,2.1877,2299,4462648 +456,search,3801.9,0.88428,0.131685,19.5595,18.8299,53.411,2.1877,2304,4462648 +457,delete,4.787,-1.0,-1.0,-1.0,-1.0,18.335,2.18621,2304,4456761 +458,search,3826.78,0.88462,0.131657,19.5572,18.8342,25.667,2.18621,2305,4456761 +459,delete,30.993,-1.0,-1.0,-1.0,-1.0,79.939,2.1664,2294,4419992 +460,search,3841.33,0.88475,0.131457,19.5558,18.8702,19.864,2.1664,2294,4419992 +461,delete,4.952,-1.0,-1.0,-1.0,-1.0,17.569,2.16549,2294,4415725 +462,search,3786,0.88479,0.131467,19.5512,18.8872,19.688,2.16549,2294,4415725 +463,delete,37.318,-1.0,-1.0,-1.0,-1.0,42.93,2.14616,2282,4370609 +464,search,3748.1,0.88378,0.132141,19.6813,18.9521,19.791,2.14616,2282,4370609 +465,delete,18.155,-1.0,-1.0,-1.0,-1.0,39.159,2.13432,2276,4345244 +466,search,3731.18,0.88289,0.132492,19.8063,19.0151,19.516,2.13432,2276,4345244 +467,delete,21.692,-1.0,-1.0,-1.0,-1.0,26.877,2.12506,2273,4319734 +468,search,3732.37,0.88245,0.132865,19.8885,19.0692,19.749,2.12506,2273,4319734 +469,delete,15.921,-1.0,-1.0,-1.0,-1.0,49.651,2.11321,2264,4298361 +470,search,3714.1,0.88186,0.13321,19.9841,19.1063,19.391,2.11321,2264,4298361 +471,delete,92.319,-1.0,-1.0,-1.0,-1.0,146.717,2.05214,2232,4188315 +472,search,3631.51,0.88072,0.133855,20.0749,19.1223,18.917,2.05214,2232,4188315 +473,delete,96.901,-1.0,-1.0,-1.0,-1.0,131.474,2.00174,2216,4074567 +474,search,3596.58,0.87985,0.134741,20.2281,19.2537,18.806,2.00174,2216,4074567 +475,delete,300.107,-1.0,-1.0,-1.0,-1.0,588.142,1.78892,2101,3691698 +476,search,3386.41,0.87521,0.137182,20.8152,19.4593,24.032,1.78894,2102,3691698 +477,delete,40.539,-1.0,-1.0,-1.0,-1.0,77.175,1.7694,2094,3642619 +478,search,3340.16,0.87431,0.137864,20.88,19.4957,17.811,1.7694,2094,3642619 +479,delete,164.335,-1.0,-1.0,-1.0,-1.0,296.187,1.67867,2044,3421368 +480,search,3289.26,0.87244,0.139121,21.3095,19.7615,34.925,1.67885,2046,3421368 +481,delete,35.287,-1.0,-1.0,-1.0,-1.0,54.585,1.66212,2039,3378034 +482,search,3248.44,0.87289,0.138361,21.1966,19.66,24.656,1.66212,2040,3378034 +483,delete,214.34,-1.0,-1.0,-1.0,-1.0,469.66,1.51134,1941,3115682 +484,search,3075.59,0.86953,0.14094,21.6468,19.8255,16.616,1.51134,1941,3115682 +485,delete,19.291,-1.0,-1.0,-1.0,-1.0,14.663,1.50569,1941,3094629 +486,search,3069.06,0.86903,0.141207,21.7076,19.8791,16.523,1.50569,1941,3094629 +487,delete,6.363,-1.0,-1.0,-1.0,-1.0,14.357,1.50403,1941,3086025 +488,search,3082.58,0.86866,0.141379,21.7621,19.8796,16.394,1.50403,1941,3086025 +489,delete,26.507,-1.0,-1.0,-1.0,-1.0,20.661,1.49275,1940,3052105 +490,search,3075.6,0.86866,0.14089,21.7672,19.883,16.599,1.49275,1940,3052105 +491,delete,11.702,-1.0,-1.0,-1.0,-1.0,19.967,1.48652,1938,3038974 +492,search,3028.85,0.86797,0.140919,21.8737,19.9392,16.545,1.48652,1938,3038974 +493,delete,110.131,-1.0,-1.0,-1.0,-1.0,176.11,1.42234,1907,2911063 +494,search,2954.92,0.86685,0.14165,22.0065,20.0249,16.337,1.42234,1907,2911063 +495,delete,15.755,-1.0,-1.0,-1.0,-1.0,34.623,1.41361,1901,2888785 +496,search,2941.3,0.86628,0.142241,22.0527,20.0192,24.877,1.41386,1902,2888785 +497,delete,41.916,-1.0,-1.0,-1.0,-1.0,39.484,1.39202,1892,2829718 +498,search,2905.18,0.8655,0.142387,22.2043,20.0793,16.034,1.39202,1892,2829718 +499,delete,12.524,-1.0,-1.0,-1.0,-1.0,19.069,1.38597,1891,2816082 +500,search,2915.36,0.86551,0.142159,22.2222,20.0618,16.155,1.38597,1891,2816082 +501,delete,18.402,-1.0,-1.0,-1.0,-1.0,46.901,1.37424,1883,2790880 +502,search,2915.64,0.86523,0.141898,22.279,20.1062,17.378,1.37424,1883,2790880 +503,delete,15.081,-1.0,-1.0,-1.0,-1.0,22.541,1.37007,1882,2774459 +504,search,2917.76,0.8646,0.142237,22.3702,20.148,16.731,1.37007,1882,2774459 +505,delete,55.938,-1.0,-1.0,-1.0,-1.0,80.466,1.3356,1864,2714683 +506,search,2893.46,0.86302,0.142756,22.5755,20.2315,17.044,1.3356,1864,2714683 +507,delete,36.531,-1.0,-1.0,-1.0,-1.0,43.923,1.32156,1858,2680986 +508,search,2880.52,0.86233,0.142898,22.6363,20.2393,16.202,1.32156,1858,2680986 +509,delete,16.613,-1.0,-1.0,-1.0,-1.0,20.136,1.31292,1857,2662966 +510,search,2876.1,0.86207,0.143116,22.6534,20.2435,16.404,1.31292,1857,2662966 +511,delete,18.441,-1.0,-1.0,-1.0,-1.0,23.095,1.3044,1854,2642855 +512,search,2844.64,0.86103,0.143997,22.734,20.2679,16.158,1.3044,1854,2642855 +513,insert,226.702,-1.0,-1.0,-1.0,-1.0,98.407,1.38807,1866,2906838 +514,search,2903.64,0.86074,0.144675,22.8497,20.4903,16.149,1.38807,1866,2906838 +515,insert,4.398,-1.0,-1.0,-1.0,-1.0,13.809,1.3896,1866,2913746 +516,search,2895.5,0.86075,0.144615,22.8256,20.4754,16.222,1.3896,1866,2913746 +517,insert,12.943,-1.0,-1.0,-1.0,-1.0,13.997,1.39305,1866,2936862 +518,search,2905.4,0.86168,0.143768,22.7599,20.4582,16.076,1.39305,1866,2936862 +519,insert,62.976,-1.0,-1.0,-1.0,-1.0,56.086,1.41868,1870,3009732 +520,search,2937.74,0.86321,0.143986,22.4502,20.3824,48.763,1.41867,1875,3009732 +521,insert,9.933,-1.0,-1.0,-1.0,-1.0,14.867,1.4213,1875,3025906 +522,search,2938.74,0.86342,0.144172,22.4002,20.3754,15.978,1.4213,1875,3025906 +523,insert,29.497,-1.0,-1.0,-1.0,-1.0,25.176,1.4323,1876,3061899 +524,search,2951.83,0.86389,0.14448,22.3327,20.3585,25.519,1.4323,1877,3061899 +525,insert,30.619,-1.0,-1.0,-1.0,-1.0,26.46,1.44215,1879,3101209 +526,search,2940.7,0.86425,0.144369,22.2443,20.3239,23.69,1.44215,1880,3101209 +527,insert,383.457,-1.0,-1.0,-1.0,-1.0,155.913,1.59995,1907,3522334 +528,search,3265.91,0.86981,0.140251,21.5881,20.0377,66.204,1.60025,1915,3522334 +529,insert,225.708,-1.0,-1.0,-1.0,-1.0,104.501,1.71173,1928,3797294 +530,search,3280.68,0.87783,0.137689,20.6472,19.8543,58.913,1.71173,1934,3797294 +531,insert,51.493,-1.0,-1.0,-1.0,-1.0,33.504,1.73056,1937,3853781 +532,search,3286.94,0.87823,0.137104,20.5741,19.8052,42.256,1.73056,1941,3853781 +533,insert,17.215,-1.0,-1.0,-1.0,-1.0,15.269,1.73739,1941,3873352 +534,search,3287.58,0.87869,0.136745,20.5544,19.7852,37.195,1.73739,1944,3873352 +535,insert,18.031,-1.0,-1.0,-1.0,-1.0,15.248,1.74403,1944,3893308 +536,search,3296.11,0.87929,0.136206,20.4915,19.7577,16.784,1.74403,1944,3893308 +537,insert,7.38,-1.0,-1.0,-1.0,-1.0,27.586,1.74716,1946,3901271 +538,search,3307.59,0.87921,0.136278,20.4746,19.7442,16.814,1.74716,1946,3901271 +539,insert,26.122,-1.0,-1.0,-1.0,-1.0,29.763,1.7559,1949,3925164 +540,search,3303.03,0.87923,0.136182,20.4656,19.7295,16.862,1.7559,1949,3925164 +541,insert,393.762,-1.0,-1.0,-1.0,-1.0,258.019,1.92991,1997,4320915 +542,search,3472.1,0.88355,0.133304,19.8984,19.432,46.829,1.93063,2003,4320915 +543,insert,32.552,-1.0,-1.0,-1.0,-1.0,23.851,1.94589,2005,4360814 +544,search,3428.97,0.8843,0.132638,19.7949,19.3498,16.847,1.94589,2005,4360814 +545,insert,8.399,-1.0,-1.0,-1.0,-1.0,22.464,1.94941,2007,4370220 +546,search,3536.27,0.88408,0.132616,19.8112,19.3642,17.454,1.94941,2007,4370220 +547,insert,137.117,-1.0,-1.0,-1.0,-1.0,51.325,2.00967,2021,4510675 +548,search,3572.68,0.88764,0.130017,19.3981,19.1179,33.97,2.01017,2025,4510675 +549,insert,194.508,-1.0,-1.0,-1.0,-1.0,110.612,2.10866,2044,4744845 +550,search,3680.62,0.88456,0.133421,19.8405,19.5803,37.516,2.10866,2046,4744845 +551,insert,23.56,-1.0,-1.0,-1.0,-1.0,40.777,2.12098,2049,4771433 +552,search,3704.53,0.88449,0.133336,19.8301,19.5831,24.721,2.12098,2050,4771433 +553,insert,11.84,-1.0,-1.0,-1.0,-1.0,18.27,2.12521,2051,4782909 +554,search,3642.94,0.88555,0.132377,19.7639,19.5546,22.701,2.12546,2052,4782909 +555,insert,368.727,-1.0,-1.0,-1.0,-1.0,234.89,2.29619,2121,5180322 +556,search,3874.59,0.89188,0.126575,19.2378,19.3081,23.425,2.2963,2123,5180322 +557,insert,19.801,-1.0,-1.0,-1.0,-1.0,25.338,2.30548,2126,5203220 +558,search,3872.67,0.89214,0.126527,19.2401,19.3286,19.076,2.30548,2126,5203220 +559,insert,5.447,-1.0,-1.0,-1.0,-1.0,17.401,2.30801,2126,5210154 +560,search,3867.27,0.89217,0.126684,19.2168,19.324,18.817,2.30801,2126,5210154 +561,insert,4.657,-1.0,-1.0,-1.0,-1.0,17.252,2.31014,2126,5215426 +562,search,3871.54,0.89224,0.12664,19.2117,19.3236,18.695,2.31014,2126,5215426 +563,insert,34.53,-1.0,-1.0,-1.0,-1.0,17.517,2.32673,2126,5252726 +564,search,3867.41,0.89234,0.126655,19.1556,19.287,19.164,2.32673,2126,5252726 +565,insert,179.868,-1.0,-1.0,-1.0,-1.0,108.143,2.40853,2144,5447274 +566,search,3952.7,0.89332,0.126078,19.0104,19.1908,40.241,2.40892,2147,5447274 +567,insert,13.644,-1.0,-1.0,-1.0,-1.0,20.919,2.41548,2147,5463135 +568,search,4006.31,0.89318,0.126489,19.0306,19.2027,26.785,2.41548,2148,5463135 +569,insert,16.512,-1.0,-1.0,-1.0,-1.0,23.096,2.42168,2149,5478168 +570,search,3966.77,0.89309,0.126627,19.0007,19.1778,22.648,2.4217,2150,5478168 +571,insert,8.824,-1.0,-1.0,-1.0,-1.0,27.129,2.42793,2151,5492309 +572,search,4019.06,0.89313,0.126721,19.0561,19.2415,21.494,2.428,2152,5492309 +573,insert,60.995,-1.0,-1.0,-1.0,-1.0,53.374,2.454,2162,5554599 +574,search,4045.22,0.89363,0.126193,19.0527,19.2777,19.289,2.454,2162,5554599 +575,insert,43.614,-1.0,-1.0,-1.0,-1.0,34.826,2.47261,2166,5604500 +576,search,4057.98,0.89362,0.12633,18.9889,19.1845,19.297,2.47261,2166,5604500 +577,insert,31.881,-1.0,-1.0,-1.0,-1.0,45.1,2.48631,2176,5638834 +578,search,4070.56,0.89364,0.126416,18.9556,19.19,20.107,2.48631,2176,5638834 +579,insert,502.5,-1.0,-1.0,-1.0,-1.0,641.7,2.76371,2312,6229778 +580,search,4377.44,0.89888,0.121645,18.4571,18.996,51.336,2.76424,2321,6229778 +581,insert,21.059,-1.0,-1.0,-1.0,-1.0,40.014,2.777,2326,6261240 +582,search,4398.27,0.89856,0.122021,18.4502,19.0041,21.331,2.777,2326,6261240 +583,insert,18.862,-1.0,-1.0,-1.0,-1.0,25.617,2.78765,2327,6283315 +584,search,4406.86,0.8988,0.122078,18.4242,19.0089,21.442,2.78765,2327,6283315 +585,insert,199.902,-1.0,-1.0,-1.0,-1.0,244.257,2.91305,2370,6556101 +586,search,4534.72,0.90032,0.121445,18.1676,18.8065,93.278,2.91386,2388,6556101 +587,insert,27.464,-1.0,-1.0,-1.0,-1.0,34.071,2.92782,2394,6587187 +588,search,4567.33,0.90049,0.121461,18.1065,18.7614,25.828,2.92801,2397,6587187 +589,insert,40.529,-1.0,-1.0,-1.0,-1.0,39.769,2.94626,2402,6631526 +590,search,4600.99,0.90081,0.120997,18.0705,18.7435,27.996,2.94631,2405,6631526 +591,insert,387.594,-1.0,-1.0,-1.0,-1.0,533.804,3.15635,2524,7108942 +592,search,4879.61,0.90399,0.119053,17.6732,18.6006,131.864,3.1578,2551,7108942 +593,insert,125.141,-1.0,-1.0,-1.0,-1.0,172.211,3.24643,2583,7303976 +594,search,4925.48,0.9059,0.118243,17.3578,18.4301,99.22,3.24769,2603,7303976 +595,insert,3.312,-1.0,-1.0,-1.0,-1.0,26.825,3.24946,2606,7309244 +596,search,4974.94,0.90594,0.118156,17.3405,18.4192,41.208,3.24948,2612,7309244 +597,insert,149.842,-1.0,-1.0,-1.0,-1.0,164.764,3.3521,2648,7542477 +598,search,5093.58,0.90756,0.117446,17.1181,18.3228,55.248,3.35266,2658,7542477 +599,insert,94.56,-1.0,-1.0,-1.0,-1.0,140.768,3.39766,2690,7654438 +600,search,5168.46,0.90831,0.116343,17.0572,18.2854,61.027,3.39852,2702,7654438 +601,insert,49.013,-1.0,-1.0,-1.0,-1.0,73.539,3.42586,2717,7717936 +602,search,5222.05,0.90855,0.1164,16.9957,18.2647,28.535,3.42592,2720,7717936 +603,insert,5.726,-1.0,-1.0,-1.0,-1.0,18.779,3.42841,2721,7723521 +604,search,5224.4,0.9087,0.1162,16.9956,18.2687,15.915,3.42841,2721,7723521 +605,insert,41.193,-1.0,-1.0,-1.0,-1.0,40.059,3.44661,2726,7767404 +606,search,5219.67,0.90912,0.11591,16.9197,18.2198,15.349,3.44661,2726,7767404 +607,insert,41.362,-1.0,-1.0,-1.0,-1.0,29.268,3.47052,2729,7826115 +608,search,5201.58,0.90862,0.116517,16.9264,18.2016,19.971,3.47065,2730,7826115 +609,insert,150.895,-1.0,-1.0,-1.0,-1.0,267.585,3.56125,2778,8036351 +610,search,5314.38,0.91005,0.115757,16.7115,18.1222,80.299,3.56248,2795,8036351 +611,insert,23.817,-1.0,-1.0,-1.0,-1.0,44.373,3.57504,2802,8060364 +612,search,5371.44,0.91033,0.115551,16.6926,18.0989,35.349,3.57545,2807,8060364 +613,insert,150.313,-1.0,-1.0,-1.0,-1.0,206.299,3.65928,2851,8256083 +614,search,5522.31,0.91153,0.114417,16.5839,18.0471,48.865,3.65964,2862,8256083 +615,insert,283.372,-1.0,-1.0,-1.0,-1.0,397.878,3.8261,2936,8625707 +616,search,5732.69,0.9132,0.113324,16.2279,17.8244,165.204,3.82973,2970,8625707 +617,insert,238.803,-1.0,-1.0,-1.0,-1.0,415.194,3.97977,3045,8949227 +618,search,5875.59,0.91572,0.111523,15.8575,17.6005,202.706,3.98199,3083,8949227 +619,insert,165.242,-1.0,-1.0,-1.0,-1.0,223.894,4.08513,3124,9195551 +620,search,5931.33,0.91648,0.111119,15.7509,17.5468,181.414,4.08869,3165,9195551 +621,insert,26.516,-1.0,-1.0,-1.0,-1.0,47.317,4.10373,3172,9232372 +622,search,6087.17,0.91689,0.110726,15.7224,17.5541,34.178,4.1041,3177,9232372 +623,insert,17.292,-1.0,-1.0,-1.0,-1.0,35.862,4.1141,3183,9253561 +624,search,6080.87,0.91721,0.110697,15.6772,17.5332,18.731,4.1141,3183,9253561 +625,insert,61.393,-1.0,-1.0,-1.0,-1.0,80.545,4.14533,3197,9331230 +626,search,6115.02,0.91766,0.110446,15.6341,17.5351,45.473,4.14569,3201,9331230 +627,insert,37.687,-1.0,-1.0,-1.0,-1.0,78.684,4.16271,3215,9374063 +628,search,6181.94,0.91786,0.11059,15.5467,17.4575,36.998,4.16293,3219,9374063 +629,insert,13.206,-1.0,-1.0,-1.0,-1.0,36.825,4.16859,3222,9387598 +630,search,6131.13,0.91815,0.110229,15.5335,17.4561,37.764,4.16886,3226,9387598 +631,insert,25.155,-1.0,-1.0,-1.0,-1.0,53.723,4.1833,3233,9421724 +632,search,6168.71,0.9184,0.110059,15.5077,17.4277,32.721,4.18384,3237,9421724 +633,insert,39.062,-1.0,-1.0,-1.0,-1.0,67.418,4.19877,3250,9461430 +634,search,6222.2,0.91887,0.109593,15.4601,17.4151,25.313,4.19884,3252,9461430 +635,insert,19.927,-1.0,-1.0,-1.0,-1.0,39.76,4.20729,3258,9479469 +636,search,6254.73,0.91879,0.109911,15.4385,17.4062,19.384,4.20729,3258,9479469 +637,insert,362.618,-1.0,-1.0,-1.0,-1.0,621.587,4.38799,3384,9885997 +638,search,6527.72,0.92098,0.108362,15.1207,17.243,150.441,4.39094,3418,9885997 +639,insert,333.22,-1.0,-1.0,-1.0,-1.0,589.433,4.57139,3545,10292043 +640,search,6759.48,0.92332,0.106422,14.7372,17.0475,136.434,4.57397,3577,10292043 +641,delete,122.727,-1.0,-1.0,-1.0,-1.0,434.973,4.52078,3544,10096584 +642,search,6676.62,0.92304,0.106762,14.8085,17.1377,29.705,4.52085,3546,10096584 +643,delete,8.653,-1.0,-1.0,-1.0,-1.0,19.427,4.52023,3546,10084840 +644,search,6695.52,0.92316,0.106465,14.8071,17.1308,22.49,4.52023,3546,10084840 +645,delete,11.856,-1.0,-1.0,-1.0,-1.0,19.385,4.52,3546,10069802 +646,search,6732.2,0.92308,0.106535,14.8316,17.1546,22.716,4.52,3546,10069802 +647,delete,55.593,-1.0,-1.0,-1.0,-1.0,189.337,4.49645,3531,9990953 +648,search,6669.23,0.92278,0.106784,14.8754,17.1761,28.247,4.4967,3532,9990953 +649,delete,29.03,-1.0,-1.0,-1.0,-1.0,32.533,4.49465,3531,9951625 +650,search,6623.74,0.92281,0.106751,14.8731,17.1785,22.72,4.49465,3531,9951625 +651,delete,15.329,-1.0,-1.0,-1.0,-1.0,19.698,4.49232,3531,9927065 +652,search,6599.73,0.92271,0.106643,14.9199,17.2022,22.834,4.49232,3531,9927065 +653,delete,72.129,-1.0,-1.0,-1.0,-1.0,167.464,4.46289,3512,9831098 +654,search,6620.68,0.92228,0.107075,15.0115,17.2753,22.99,4.46289,3512,9831098 +655,delete,292.469,-1.0,-1.0,-1.0,-1.0,611.422,4.35904,3437,9462172 +656,search,6389.1,0.92024,0.108472,15.329,17.4523,37.668,4.35961,3441,9462172 +657,delete,157.741,-1.0,-1.0,-1.0,-1.0,265.813,4.27969,3386,9218902 +658,search,6230.84,0.91711,0.110136,15.8094,17.714,51.03,4.27988,3391,9218902 +659,delete,85.642,-1.0,-1.0,-1.0,-1.0,239.917,4.24242,3366,9106546 +660,search,6156.19,0.91634,0.11075,15.9291,17.792,31.226,4.24242,3367,9106546 +661,delete,35.449,-1.0,-1.0,-1.0,-1.0,47.332,4.23524,3365,9059776 +662,search,6265.21,0.91652,0.110644,15.9454,17.808,21.963,4.23524,3365,9059776 +663,delete,65.992,-1.0,-1.0,-1.0,-1.0,135.543,4.21456,3352,8990616 +664,search,6143.69,0.91607,0.110823,16.0211,17.8334,22.354,4.21456,3352,8990616 +665,delete,42.631,-1.0,-1.0,-1.0,-1.0,109.394,4.19639,3344,8937437 +666,search,6136.57,0.91591,0.110722,16.0556,17.8663,28.325,4.1967,3345,8937437 +667,delete,151.552,-1.0,-1.0,-1.0,-1.0,293.107,4.12794,3316,8766390 +668,search,6037.03,0.9155,0.110676,16.0924,17.8631,25.318,4.12801,3317,8766390 +669,delete,168.075,-1.0,-1.0,-1.0,-1.0,504.727,4.04164,3268,8532008 +670,search,5876.3,0.91467,0.111121,16.1992,17.9248,24.954,4.04188,3269,8532008 +671,delete,27.981,-1.0,-1.0,-1.0,-1.0,54.794,4.03206,3266,8489178 +672,search,5861.97,0.91451,0.111419,16.2472,17.9674,21.572,4.03206,3266,8489178 +673,delete,50.536,-1.0,-1.0,-1.0,-1.0,113.024,4.01281,3256,8421866 +674,search,5820.65,0.91432,0.111606,16.305,17.9975,21.545,4.01281,3256,8421866 +675,delete,104.337,-1.0,-1.0,-1.0,-1.0,70.059,3.98826,3250,8288319 +676,search,5815.02,0.91399,0.111765,16.4211,18.064,42.705,3.98896,3253,8288319 +677,delete,150.541,-1.0,-1.0,-1.0,-1.0,154.929,3.90664,3235,8072197 +678,search,5738.73,0.91561,0.10989,15.9958,17.645,21.228,3.90664,3235,8072197 +679,delete,27.516,-1.0,-1.0,-1.0,-1.0,48.077,3.89613,3233,8036947 +680,search,5721.08,0.91549,0.110015,16.0062,17.6381,20.387,3.89613,3233,8036947 +681,delete,6.878,-1.0,-1.0,-1.0,-1.0,17.796,3.89475,3233,8026197 +682,search,5706.62,0.91553,0.109975,16.0095,17.6378,20.798,3.89475,3233,8026197 +683,delete,258.106,-1.0,-1.0,-1.0,-1.0,220.927,3.79586,3200,7744229 +684,search,5588.21,0.91369,0.112145,16.2274,17.7987,26.081,3.79588,3201,7744229 +685,delete,217.073,-1.0,-1.0,-1.0,-1.0,130.506,3.70409,3182,7541066 +686,search,5485.97,0.91064,0.114894,16.5758,18.1433,36.062,3.7044,3185,7541066 +687,delete,16.961,-1.0,-1.0,-1.0,-1.0,17.8,3.69923,3185,7522190 +688,search,5612.29,0.91037,0.115025,16.6039,18.1775,20.843,3.69923,3185,7522190 +689,delete,98.621,-1.0,-1.0,-1.0,-1.0,260.812,3.64017,3158,7409400 +690,search,5419.38,0.9096,0.115458,16.7361,18.2871,37.357,3.64063,3161,7409400 +691,delete,36.815,-1.0,-1.0,-1.0,-1.0,17.997,3.62601,3161,7375648 +692,search,5688.53,0.90954,0.115487,16.7431,18.2998,19.937,3.62601,3161,7375648 +693,delete,144.25,-1.0,-1.0,-1.0,-1.0,200.663,3.55434,3138,7222068 +694,search,5364.12,0.90827,0.116378,16.8797,18.3344,26.663,3.55443,3139,7222068 +695,delete,23.708,-1.0,-1.0,-1.0,-1.0,153.341,3.53938,3133,7196331 +696,search,5767.41,0.90921,0.115519,16.7216,18.1959,36.723,3.53966,3135,7196331 +697,delete,26.322,-1.0,-1.0,-1.0,-1.0,33.465,3.52835,3133,7170716 +698,search,5786.02,0.90884,0.115838,16.7886,18.2398,20.884,3.52835,3133,7170716 +699,delete,10.736,-1.0,-1.0,-1.0,-1.0,63.66,3.52059,3131,7155255 +700,search,6211.35,0.90917,0.115368,16.7569,18.2154,49.498,3.52085,3132,7155255 +701,delete,89.001,-1.0,-1.0,-1.0,-1.0,34.093,3.50085,3132,7097733 +702,search,6257.01,0.90886,0.115227,16.7988,18.2282,19.535,3.50085,3132,7097733 +703,delete,154.684,-1.0,-1.0,-1.0,-1.0,316.567,3.4098,3087,6924172 +704,search,5255.84,0.90899,0.115976,16.7216,18.2641,26.788,3.41001,3088,6924172 +705,delete,33.472,-1.0,-1.0,-1.0,-1.0,23.986,3.39899,3087,6896276 +706,search,5323.04,0.90861,0.115881,16.7709,18.2524,20.164,3.39899,3087,6896276 +707,delete,516.352,-1.0,-1.0,-1.0,-1.0,946.962,3.10596,2923,6385507 +708,search,4802.83,0.90513,0.118804,16.9913,18.2016,28.879,3.10612,2925,6385507 +709,delete,155.422,-1.0,-1.0,-1.0,-1.0,540.973,3.0098,2865,6207658 +710,search,4834.78,0.90281,0.120682,17.2774,18.3161,34.073,3.01015,2868,6207658 +711,delete,39.513,-1.0,-1.0,-1.0,-1.0,59.247,2.99421,2864,6162720 +712,search,4745.23,0.90268,0.120821,17.3169,18.3644,24.481,2.99445,2865,6162720 +713,delete,204.44,-1.0,-1.0,-1.0,-1.0,407.72,2.88055,2813,5927803 +714,search,4674.16,0.90113,0.122537,17.525,18.5304,36.587,2.8808,2815,5927803 +715,delete,30.966,-1.0,-1.0,-1.0,-1.0,48.725,2.86724,2810,5895666 +716,search,4672.94,0.90081,0.122835,17.5584,18.5396,18.292,2.86724,2810,5895666 +717,delete,24.541,-1.0,-1.0,-1.0,-1.0,39.826,2.86086,2808,5868774 +718,search,4596.58,0.90018,0.123358,17.5894,18.5694,18.001,2.86086,2808,5868774 +719,delete,307.949,-1.0,-1.0,-1.0,-1.0,704.747,2.69211,2679,5533540 +720,search,4401,0.8967,0.126217,17.9225,18.6437,33.855,2.69253,2682,5533540 +721,delete,92.503,-1.0,-1.0,-1.0,-1.0,149.374,2.64318,2656,5418387 +722,search,4327.78,0.89642,0.12597,18.0273,18.7036,28.142,2.64362,2658,5418387 +723,delete,18.027,-1.0,-1.0,-1.0,-1.0,24.699,2.63612,2657,5398291 +724,search,4364.43,0.8961,0.126228,18.0383,18.7047,16.592,2.63612,2657,5398291 +725,delete,91.701,-1.0,-1.0,-1.0,-1.0,167.764,2.58455,2646,5273546 +726,search,4332.69,0.89541,0.126657,18.0928,18.6888,39.621,2.58455,2648,5273546 +727,delete,78.149,-1.0,-1.0,-1.0,-1.0,119.219,2.5427,2634,5180937 +728,search,4277.19,0.89484,0.12754,18.1689,18.7268,33.562,2.5427,2636,5180937 +729,delete,105.762,-1.0,-1.0,-1.0,-1.0,136.641,2.49521,2615,5079524 +730,search,4244.68,0.89392,0.128506,18.2827,18.7702,16.935,2.49521,2615,5079524 +731,delete,66.057,-1.0,-1.0,-1.0,-1.0,14.791,2.47665,2615,5019265 +732,search,4215.41,0.89256,0.129541,18.4127,18.8229,16.823,2.47665,2615,5019265 +733,delete,71.625,-1.0,-1.0,-1.0,-1.0,75.857,2.44644,2608,4955565 +734,search,4180.59,0.89226,0.130061,18.4737,18.9343,16.608,2.44644,2608,4955565 +735,delete,142.668,-1.0,-1.0,-1.0,-1.0,507.775,2.35695,2552,4776948 +736,search,4107.62,0.89902,0.122935,18.0878,18.8437,73.36,2.35869,2561,4776948 +737,delete,105.46,-1.0,-1.0,-1.0,-1.0,94.595,2.3107,2550,4654026 +738,search,4048.45,0.89703,0.124588,18.2876,18.9293,41.696,2.31083,2554,4654026 +739,delete,57.945,-1.0,-1.0,-1.0,-1.0,157.982,2.26999,2538,4589888 +740,search,4017.48,0.897,0.123818,18.2721,18.8944,20.915,2.26998,2539,4589888 +741,delete,138.158,-1.0,-1.0,-1.0,-1.0,195.887,2.19686,2508,4430862 +742,search,3944.58,0.89575,0.125152,18.3497,18.8476,16.514,2.19686,2508,4430862 +743,delete,162.406,-1.0,-1.0,-1.0,-1.0,355.449,2.09781,2456,4237049 +744,search,3844.92,0.89526,0.125837,18.5328,19.0562,16.252,2.09781,2456,4237049 +745,delete,225.247,-1.0,-1.0,-1.0,-1.0,540.07,1.96723,2380,4000195 +746,search,3747.27,0.89273,0.127346,18.9081,19.2737,44.197,1.96809,2384,4000195 +747,delete,176.922,-1.0,-1.0,-1.0,-1.0,252.939,1.87543,2339,3803954 +748,search,3662.45,0.89127,0.127865,19.0317,19.237,37.242,1.87536,2341,3803954 +749,delete,69.892,-1.0,-1.0,-1.0,-1.0,66.473,1.84543,2333,3733214 +750,search,3638.24,0.89095,0.127571,19.2037,19.3349,22.389,1.84543,2333,3733214 +751,delete,19.774,-1.0,-1.0,-1.0,-1.0,51.178,1.83349,2327,3709324 +752,search,3637.91,0.89003,0.128186,19.2978,19.3776,22.513,1.83349,2327,3709324 +753,delete,52.249,-1.0,-1.0,-1.0,-1.0,130.821,1.80289,2313,3649123 +754,search,3592.77,0.88923,0.128572,19.4685,19.5279,22.025,1.80289,2313,3649123 +755,delete,24.082,-1.0,-1.0,-1.0,-1.0,32.733,1.79243,2311,3621475 +756,search,3581.15,0.88905,0.128907,19.4456,19.5015,31.533,1.79273,2312,3621475 +757,delete,23.534,-1.0,-1.0,-1.0,-1.0,37.809,1.78053,2308,3594479 +758,search,3570.82,0.88897,0.128537,19.4496,19.4771,21.802,1.78053,2308,3594479 +759,delete,20.864,-1.0,-1.0,-1.0,-1.0,48.661,1.76757,2304,3569055 +760,search,3564.14,0.88876,0.128606,19.5026,19.4777,21.67,1.76757,2304,3569055 +761,delete,32.787,-1.0,-1.0,-1.0,-1.0,41.354,1.75132,2299,3527896 +762,search,3553.82,0.88786,0.129361,19.604,19.5377,22.429,1.75132,2299,3527896 +763,delete,23.587,-1.0,-1.0,-1.0,-1.0,36.292,1.74271,2296,3509970 +764,search,3554.09,0.88776,0.129346,19.6463,19.5931,22.746,1.74271,2296,3509970 +765,delete,324.974,-1.0,-1.0,-1.0,-1.0,495.119,1.55885,2168,3187549 +766,search,3337.92,0.88482,0.131058,20.0447,19.7647,20.313,1.55885,2168,3187549 +767,delete,345.902,-1.0,-1.0,-1.0,-1.0,701.792,1.34987,1978,2822906 +768,search,3036.31,0.87664,0.136429,20.8919,20.0749,18.732,1.34987,1978,2822906 +769,insert,9.685,-1.0,-1.0,-1.0,-1.0,15.85,1.35187,1978,2832899 +770,search,3052.35,0.87715,0.136058,20.8717,20.0547,17.984,1.35187,1978,2832899 +771,insert,34.008,-1.0,-1.0,-1.0,-1.0,23.248,1.36176,1979,2863523 +772,search,3062.2,0.87739,0.136314,20.8203,20.0761,18.128,1.36176,1979,2863523 +773,insert,47.991,-1.0,-1.0,-1.0,-1.0,25.79,1.37782,1981,2925169 +774,search,3089.32,0.87922,0.134884,20.6937,20.0304,18.194,1.37782,1981,2925169 +775,insert,37.288,-1.0,-1.0,-1.0,-1.0,38.859,1.39007,1984,2961356 +776,search,3085.71,0.87914,0.134858,20.6521,20.0045,17.938,1.39007,1984,2961356 +777,insert,28.21,-1.0,-1.0,-1.0,-1.0,16.057,1.39827,1984,2998678 +778,search,3081.53,0.88016,0.134193,20.5498,19.9156,18.029,1.39827,1984,2998678 +779,insert,13.461,-1.0,-1.0,-1.0,-1.0,22.763,1.40208,1985,3011024 +780,search,3096.71,0.88032,0.134011,20.5229,19.9172,17.916,1.40208,1985,3011024 +781,insert,6.622,-1.0,-1.0,-1.0,-1.0,15.756,1.40335,1985,3019515 +782,search,3095.76,0.88048,0.133866,20.5205,19.9224,17.664,1.40335,1985,3019515 +783,insert,47.05,-1.0,-1.0,-1.0,-1.0,16.128,1.41718,1985,3082298 +784,search,3114.09,0.88139,0.133223,20.3805,19.8343,17.787,1.41718,1985,3082298 +785,insert,39.595,-1.0,-1.0,-1.0,-1.0,64.008,1.43369,1991,3122090 +786,search,3139.53,0.8827,0.132825,20.1985,19.7658,43.526,1.43369,1995,3122090 +787,insert,21.126,-1.0,-1.0,-1.0,-1.0,16.502,1.4394,1995,3140294 +788,search,3156,0.8829,0.132518,20.1396,19.7392,24.732,1.4394,1996,3140294 +789,insert,6.972,-1.0,-1.0,-1.0,-1.0,16.264,1.44104,1996,3147819 +790,search,3154.77,0.88271,0.132592,20.1426,19.7307,18.275,1.44104,1996,3147819 +791,insert,32.587,-1.0,-1.0,-1.0,-1.0,16.638,1.45033,1996,3180668 +792,search,3173.86,0.88292,0.132709,20.1053,19.7152,18.255,1.45033,1996,3180668 +793,insert,1.74,-1.0,-1.0,-1.0,-1.0,16.109,1.45072,1996,3183235 +794,search,3163.79,0.88293,0.132689,20.1072,19.7162,18.166,1.45072,1996,3183235 +795,insert,60.475,-1.0,-1.0,-1.0,-1.0,22.414,1.46941,1997,3242089 +796,search,3168.57,0.88401,0.131886,19.9988,19.648,18.336,1.46941,1997,3242089 +797,insert,5.638,-1.0,-1.0,-1.0,-1.0,16.042,1.47101,1997,3247192 +798,search,3181.61,0.88396,0.131911,19.9989,19.6463,18.414,1.47101,1997,3247192 +799,insert,5.692,-1.0,-1.0,-1.0,-1.0,16.1,1.47244,1997,3254626 +800,search,3191.15,0.88397,0.131863,19.9685,19.6184,18.231,1.47244,1997,3254626 +801,insert,17.007,-1.0,-1.0,-1.0,-1.0,21.565,1.47727,1998,3274953 +802,search,3195.71,0.8845,0.131566,19.8736,19.5652,18.112,1.47727,1998,3274953 +803,insert,828.268,-1.0,-1.0,-1.0,-1.0,544.966,1.80826,2090,4032688 +804,search,3532.73,0.89223,0.125314,19.0017,19.1737,132.281,1.80866,2112,4032688 +805,insert,18.291,-1.0,-1.0,-1.0,-1.0,17.535,1.81519,2112,4050220 +806,search,3550.06,0.8918,0.125815,19.0258,19.1689,44.888,1.81547,2117,4050220 +807,insert,15.536,-1.0,-1.0,-1.0,-1.0,17.859,1.82099,2117,4067940 +808,search,3568.07,0.89173,0.125797,19.0408,19.1715,19.85,1.82099,2117,4067940 +809,insert,40.525,-1.0,-1.0,-1.0,-1.0,27.962,1.83531,2119,4099369 +810,search,3573.09,0.89221,0.125512,18.9758,19.1589,19.805,1.83531,2119,4099369 +811,insert,34.081,-1.0,-1.0,-1.0,-1.0,17.342,1.84704,2119,4129509 +812,search,3584.85,0.89253,0.125256,18.9621,19.1273,19.92,1.84704,2119,4129509 +813,insert,51.838,-1.0,-1.0,-1.0,-1.0,21.628,1.86653,2120,4178669 +814,search,3599.21,0.89407,0.124337,18.7448,18.9716,20.054,1.86653,2120,4178669 +815,insert,3.528,-1.0,-1.0,-1.0,-1.0,17.341,1.86751,2120,4180960 +816,search,3614.21,0.89404,0.12439,18.7506,18.978,19.78,1.86751,2120,4180960 +817,insert,81.388,-1.0,-1.0,-1.0,-1.0,87.215,1.89561,2132,4255359 +818,search,3619.14,0.8944,0.124324,18.6601,18.9064,19.997,1.89561,2132,4255359 +819,insert,17.41,-1.0,-1.0,-1.0,-1.0,22.648,1.90139,2134,4272706 +820,search,3631.25,0.89481,0.123747,18.6251,18.8746,19.759,1.90139,2134,4272706 +821,insert,16.241,-1.0,-1.0,-1.0,-1.0,32.628,1.90758,2136,4287851 +822,search,3632.92,0.89471,0.123836,18.6069,18.8704,20.727,1.90758,2136,4287851 +823,insert,36.521,-1.0,-1.0,-1.0,-1.0,30.921,1.92273,2137,4322788 +824,search,3648.2,0.89461,0.123863,18.5713,18.8394,26.461,1.92286,2138,4322788 +825,insert,91.997,-1.0,-1.0,-1.0,-1.0,35.617,1.95437,2141,4396408 +826,search,3701.76,0.89506,0.122885,18.6684,18.9726,19.701,1.95437,2141,4396408 +827,insert,23.251,-1.0,-1.0,-1.0,-1.0,23.378,1.96323,2142,4415721 +828,search,3679.18,0.89488,0.123023,18.7113,19.0177,19.496,1.96323,2142,4415721 +829,insert,465.379,-1.0,-1.0,-1.0,-1.0,231.052,2.14502,2182,4832079 +830,search,3861.48,0.8971,0.122098,18.3135,18.8263,69.372,2.14595,2192,4832079 +831,insert,36.684,-1.0,-1.0,-1.0,-1.0,30.309,2.15941,2194,4864525 +832,search,3841.76,0.89766,0.121877,18.2841,18.8333,26.266,2.15943,2195,4864525 +833,insert,7.831,-1.0,-1.0,-1.0,-1.0,28.831,2.16191,2198,4874443 +834,search,3863,0.89737,0.12222,18.3049,18.862,20.432,2.16191,2198,4874443 +835,insert,68.444,-1.0,-1.0,-1.0,-1.0,38.492,2.18926,2203,4938267 +836,search,3898.74,0.89818,0.121769,18.1888,18.7928,29.569,2.18931,2205,4938267 +837,insert,23.933,-1.0,-1.0,-1.0,-1.0,24.809,2.1978,2206,4961147 +838,search,3997.69,0.89817,0.121699,18.195,18.7946,20.416,2.1978,2206,4961147 +839,insert,72.922,-1.0,-1.0,-1.0,-1.0,48.335,2.22722,2211,5033740 +840,search,3940.39,0.89928,0.120994,18.0729,18.7598,20.807,2.22722,2211,5033740 +841,insert,57.168,-1.0,-1.0,-1.0,-1.0,28.293,2.24701,2213,5078736 +842,search,3958.4,0.89936,0.12092,18.0747,18.7694,24.064,2.24712,2214,5078736 +843,insert,434.884,-1.0,-1.0,-1.0,-1.0,273.51,2.41921,2262,5467376 +844,search,4145.5,0.90217,0.11931,17.7952,18.6723,98.512,2.42005,2280,5467376 +845,insert,346.726,-1.0,-1.0,-1.0,-1.0,303.791,2.57716,2335,5815547 +846,search,4311.07,0.9048,0.117792,17.4489,18.5286,65.407,2.578,2343,5815547 +847,insert,7.233,-1.0,-1.0,-1.0,-1.0,20.608,2.58083,2343,5821782 +848,search,4316.64,0.90501,0.117471,17.4286,18.5178,35.502,2.58108,2346,5821782 +849,insert,1.977,-1.0,-1.0,-1.0,-1.0,25.173,2.58169,2347,5825594 +850,search,4319.03,0.90493,0.117602,17.4296,18.5248,22.046,2.58169,2347,5825594 +851,insert,11.462,-1.0,-1.0,-1.0,-1.0,23.476,2.58657,2348,5834880 +852,search,4303.76,0.90502,0.117599,17.4082,18.5194,22.028,2.58657,2348,5834880 +853,insert,25.055,-1.0,-1.0,-1.0,-1.0,37.358,2.59676,2351,5860274 +854,search,4320.9,0.90541,0.117419,17.3735,18.5008,34.166,2.59698,2354,5860274 +855,insert,7.47,-1.0,-1.0,-1.0,-1.0,25.76,2.59935,2356,5866064 +856,search,4330.42,0.90532,0.117607,17.38,18.5059,22.16,2.59935,2356,5866064 +857,insert,22.392,-1.0,-1.0,-1.0,-1.0,28.92,2.60535,2358,5884456 +858,search,4344.36,0.90544,0.117618,17.3165,18.4343,20.431,2.60535,2358,5884456 +859,insert,39.592,-1.0,-1.0,-1.0,-1.0,51.083,2.61823,2366,5916786 +860,search,4350.52,0.9057,0.117615,17.2488,18.3804,15.666,2.61823,2366,5916786 +861,insert,8.984,-1.0,-1.0,-1.0,-1.0,17.822,2.62101,2367,5923467 +862,search,4349.63,0.90563,0.117694,17.2416,18.3789,15.698,2.62101,2367,5923467 +863,insert,77.222,-1.0,-1.0,-1.0,-1.0,75.839,2.65345,2379,5997844 +864,search,4369.28,0.9042,0.119152,17.3102,18.3882,15.392,2.65345,2379,5997844 +865,insert,14.313,-1.0,-1.0,-1.0,-1.0,16.505,2.65821,2380,6009561 +866,search,4362.81,0.90465,0.118985,17.3113,18.4005,22.434,2.65824,2381,6009561 +867,insert,47.338,-1.0,-1.0,-1.0,-1.0,45.016,2.67867,2389,6052876 +868,search,4386.73,0.90433,0.119397,17.2814,18.3977,20.614,2.67879,2390,6052876 +869,insert,5.392,-1.0,-1.0,-1.0,-1.0,26.261,2.68106,2392,6059234 +870,search,4395.8,0.90469,0.119117,17.2875,18.4225,15.583,2.68106,2392,6059234 +871,insert,38.407,-1.0,-1.0,-1.0,-1.0,39.744,2.69695,2397,6098225 +872,search,4408.44,0.90472,0.119178,17.2696,18.4256,15.498,2.69695,2397,6098225 +873,insert,41.511,-1.0,-1.0,-1.0,-1.0,43.746,2.71274,2402,6137308 +874,search,4435.01,0.90498,0.118829,17.3054,18.4544,15.828,2.71274,2402,6137308 +875,insert,19.454,-1.0,-1.0,-1.0,-1.0,19.305,2.71829,2403,6154089 +876,search,4474.45,0.90492,0.119009,17.3234,18.4822,15.474,2.71829,2403,6154089 +877,insert,2.846,-1.0,-1.0,-1.0,-1.0,13.451,2.71906,2403,6156061 +878,search,4455.55,0.90499,0.118935,17.3185,18.4919,15.712,2.71906,2403,6156061 +879,insert,296.348,-1.0,-1.0,-1.0,-1.0,309.423,2.8535,2458,6446004 +880,search,4558.95,0.90638,0.11819,17.0673,18.3504,88.378,2.85476,2473,6446004 +881,insert,437.451,-1.0,-1.0,-1.0,-1.0,396.505,3.08658,2556,6969764 +882,search,4797.43,0.90838,0.116372,16.8808,18.2394,134.222,3.08758,2582,6969764 +883,insert,373.834,-1.0,-1.0,-1.0,-1.0,503.402,3.29059,2689,7422501 +884,search,5089.04,0.9114,0.114367,16.4222,17.996,120.445,3.29253,2716,7422501 +885,insert,6.907,-1.0,-1.0,-1.0,-1.0,23.924,3.29513,2718,7432053 +886,search,5138.38,0.91164,0.114411,16.3837,17.9817,35.741,3.29556,2724,7432053 +887,insert,293.583,-1.0,-1.0,-1.0,-1.0,378.336,3.45252,2801,7789886 +888,search,5316.11,0.91338,0.113557,16.1025,17.9509,108.805,3.45412,2825,7789886 +889,insert,343.116,-1.0,-1.0,-1.0,-1.0,501.432,3.64403,2923,8210883 +890,search,5511.19,0.91563,0.111811,15.8296,17.8311,152.837,3.6461,2957,8210883 +891,insert,25.78,-1.0,-1.0,-1.0,-1.0,40.357,3.65751,2964,8240504 +892,search,5540.18,0.91561,0.111946,15.8071,17.8085,33.553,3.65765,2968,8240504 +893,insert,39.118,-1.0,-1.0,-1.0,-1.0,74.205,3.67896,2981,8299693 +894,search,5560.97,0.91606,0.111493,15.7691,17.7964,32.533,3.67918,2984,8299693 +895,insert,48.801,-1.0,-1.0,-1.0,-1.0,74.968,3.69614,3001,8349126 +896,search,5622.35,0.91637,0.111213,15.7345,17.7894,27.952,3.69648,3003,8349126 +897,delete,50.157,-1.0,-1.0,-1.0,-1.0,124.839,3.67597,2995,8268842 +898,search,5611.44,0.91622,0.11103,15.7485,17.8063,25.659,3.67621,2996,8268842 +899,delete,10.982,-1.0,-1.0,-1.0,-1.0,16.994,3.67621,2996,8250527 +900,search,5611.47,0.91613,0.111158,15.7833,17.8247,18.93,3.67621,2996,8250527 +901,delete,40.461,-1.0,-1.0,-1.0,-1.0,77.902,3.66581,2986,8185565 +902,search,5557.15,0.91572,0.111389,15.8264,17.8364,25.714,3.66602,2987,8185565 +903,delete,40.624,-1.0,-1.0,-1.0,-1.0,103.32,3.64473,2973,8126915 +904,search,5516.94,0.91467,0.111785,16.0078,17.9142,24.4,3.64474,2974,8126915 +905,delete,16.851,-1.0,-1.0,-1.0,-1.0,17.061,3.64426,2974,8098533 +906,search,5507.88,0.91457,0.111878,16.011,17.9316,19.03,3.64426,2974,8098533 +907,delete,17.638,-1.0,-1.0,-1.0,-1.0,38.226,3.63997,2972,8074833 +908,search,5540.36,0.91446,0.111872,16.0199,17.9116,19.14,3.63997,2972,8074833 +909,delete,28.39,-1.0,-1.0,-1.0,-1.0,17.02,3.6389,2972,8035274 +910,search,5517.63,0.91432,0.112098,16.0486,17.9332,19.518,3.6389,2972,8035274 +911,delete,59.417,-1.0,-1.0,-1.0,-1.0,38.217,3.63326,2970,7957223 +912,search,5474.48,0.9137,0.112717,16.1267,18.0162,19.79,3.63326,2970,7957223 +913,delete,27.417,-1.0,-1.0,-1.0,-1.0,73.935,3.61963,2960,7917554 +914,search,5448.11,0.91302,0.112863,16.191,18.003,18.792,3.61963,2960,7917554 +915,delete,47.54,-1.0,-1.0,-1.0,-1.0,108.381,3.60322,2946,7861503 +916,search,5397.55,0.91268,0.112959,16.2246,17.9967,18.891,3.60322,2946,7861503 +917,delete,10.413,-1.0,-1.0,-1.0,-1.0,16.232,3.60244,2946,7844487 +918,search,5405.81,0.91257,0.112929,16.2323,18.007,18.955,3.60244,2946,7844487 +919,delete,21.103,-1.0,-1.0,-1.0,-1.0,29.126,3.60063,2945,7814993 +920,search,5396.75,0.91258,0.113152,16.2579,18.0381,19.288,3.60063,2945,7814993 +921,delete,18.015,-1.0,-1.0,-1.0,-1.0,51.813,3.59541,2942,7793855 +922,search,5427.73,0.91257,0.112938,16.2784,18.0504,19.223,3.59541,2942,7793855 +923,delete,43.377,-1.0,-1.0,-1.0,-1.0,27.879,3.58937,2940,7736054 +924,search,5387.24,0.91248,0.112868,16.3158,18.0607,19.178,3.58937,2940,7736054 +925,delete,112.837,-1.0,-1.0,-1.0,-1.0,201.146,3.53752,2907,7587942 +926,search,5286,0.91135,0.113971,16.4392,18.1148,53.132,3.53862,2913,7587942 +927,delete,18.358,-1.0,-1.0,-1.0,-1.0,22.175,3.53554,2912,7565670 +928,search,5259.41,0.91127,0.113929,16.4682,18.1377,25.525,3.53554,2913,7565670 +929,delete,23.941,-1.0,-1.0,-1.0,-1.0,16.393,3.53278,2913,7529948 +930,search,5270.27,0.91096,0.114224,16.4859,18.1796,18.724,3.53278,2913,7529948 +931,delete,397.775,-1.0,-1.0,-1.0,-1.0,966.565,3.34873,2786,7016700 +932,search,4989.6,0.90943,0.115662,16.5599,18.1023,57.01,3.34968,2796,7016700 +933,delete,21.73,-1.0,-1.0,-1.0,-1.0,58.655,3.33751,2790,6980979 +934,search,5002.37,0.90927,0.115759,16.5909,18.0971,23.285,3.33772,2791,6980979 +935,delete,16.819,-1.0,-1.0,-1.0,-1.0,69.246,3.3284,2787,6954250 +936,search,4986.3,0.90886,0.1161,16.6094,18.1146,18.132,3.3284,2787,6954250 +937,delete,23.926,-1.0,-1.0,-1.0,-1.0,37.839,3.31908,2785,6924596 +938,search,4967.88,0.90859,0.116313,16.6639,18.1457,17.541,3.31908,2785,6924596 +939,delete,120.655,-1.0,-1.0,-1.0,-1.0,60.179,3.29039,2779,6784831 +940,search,4901.97,0.90776,0.117657,16.705,18.1626,17.77,3.29039,2779,6784831 +941,delete,32.685,-1.0,-1.0,-1.0,-1.0,15.301,3.28281,2779,6745819 +942,search,4890.73,0.90761,0.117691,16.7227,18.1425,17.814,3.28281,2779,6745819 +943,delete,3.376,-1.0,-1.0,-1.0,-1.0,15.333,3.28237,2779,6740944 +944,search,4906.98,0.90757,0.117696,16.7338,18.1532,20.426,3.28237,2779,6740944 +945,delete,106.167,-1.0,-1.0,-1.0,-1.0,311.478,3.22578,2745,6627202 +946,search,4822.83,0.90709,0.117855,16.8465,18.2016,34.511,3.22631,2749,6627202 +947,delete,19.296,-1.0,-1.0,-1.0,-1.0,15.307,3.22214,2749,6607194 +948,search,4817.79,0.90655,0.11817,16.8884,18.2178,17.715,3.22214,2749,6607194 +949,delete,49.202,-1.0,-1.0,-1.0,-1.0,68.406,3.20143,2740,6551065 +950,search,4776.78,0.90647,0.118308,16.9079,18.1958,17.41,3.20143,2740,6551065 +951,delete,30.241,-1.0,-1.0,-1.0,-1.0,50.028,3.18016,2729,6506798 +952,search,4749.12,0.90657,0.118039,16.9431,18.1965,22.49,3.18027,2730,6506798 +953,delete,37.547,-1.0,-1.0,-1.0,-1.0,72.968,3.16403,2727,6459301 +954,search,4743.47,0.90653,0.117898,16.953,18.2148,17.536,3.16403,2727,6459301 +955,delete,13.276,-1.0,-1.0,-1.0,-1.0,29.106,3.15594,2723,6440069 +956,search,4760.15,0.9066,0.117794,16.999,18.2937,17.996,3.15594,2723,6440069 +957,delete,308.972,-1.0,-1.0,-1.0,-1.0,410.632,3.00458,2663,6132470 +958,search,4617.65,0.90451,0.119081,17.2853,18.5269,17.339,3.00458,2663,6132470 +959,delete,46.403,-1.0,-1.0,-1.0,-1.0,44.842,2.98572,2658,6086241 +960,search,4572.99,0.9034,0.119893,17.4475,18.6325,17.288,2.98572,2658,6086241 +961,delete,21.752,-1.0,-1.0,-1.0,-1.0,14.402,2.98031,2658,6064734 +962,search,4573.74,0.90353,0.119779,17.4439,18.6402,16.8,2.98031,2658,6064734 +963,delete,102.242,-1.0,-1.0,-1.0,-1.0,61.091,2.93351,2650,5967543 +964,search,4522.71,0.90317,0.119733,17.5223,18.6698,16.353,2.93351,2650,5967543 +965,delete,50.943,-1.0,-1.0,-1.0,-1.0,83.093,2.90742,2637,5906381 +966,search,4486.16,0.90253,0.12039,17.5545,18.6878,17.026,2.90742,2637,5906381 +967,delete,44.546,-1.0,-1.0,-1.0,-1.0,52.479,2.88715,2632,5851849 +968,search,4470.37,0.9025,0.120504,17.6045,18.7245,21.756,2.88731,2633,5851849 +969,delete,61.005,-1.0,-1.0,-1.0,-1.0,54.392,2.85719,2626,5783023 +970,search,4457.69,0.90174,0.120959,17.7137,18.7821,16.996,2.85719,2626,5783023 +971,delete,276.489,-1.0,-1.0,-1.0,-1.0,393.143,2.71357,2571,5496517 +972,search,4320.59,0.90044,0.122013,17.9114,18.8624,22.583,2.71383,2572,5496517 +973,delete,239.77,-1.0,-1.0,-1.0,-1.0,324.439,2.5779,2514,5237981 +974,search,4165.48,0.8972,0.12466,18.3128,19.0926,26.537,2.57828,2516,5237981 +975,delete,118.201,-1.0,-1.0,-1.0,-1.0,250.328,2.50254,2455,5099794 +976,search,4059.75,0.89496,0.126095,18.627,19.1827,15.197,2.50254,2455,5099794 +977,delete,51.007,-1.0,-1.0,-1.0,-1.0,121.567,2.47305,2441,5032210 +978,search,4023.9,0.89434,0.126473,18.741,19.2642,15.251,2.47305,2441,5032210 +979,delete,9.19,-1.0,-1.0,-1.0,-1.0,17.181,2.46955,2440,5020211 +980,search,4009.43,0.89428,0.126642,18.7422,19.2532,15.738,2.46955,2440,5020211 +981,delete,102.001,-1.0,-1.0,-1.0,-1.0,173.118,2.41247,2415,4902291 +982,search,3972.27,0.89279,0.127392,18.9343,19.3171,22.684,2.41248,2416,4902291 +983,delete,35.717,-1.0,-1.0,-1.0,-1.0,13.441,2.40354,2416,4872577 +984,search,3973.35,0.89278,0.127613,18.9553,19.3352,15.583,2.40354,2416,4872577 +985,delete,38.861,-1.0,-1.0,-1.0,-1.0,23.371,2.39136,2415,4836730 +986,search,3953.26,0.89235,0.127828,18.9956,19.3682,15.757,2.39136,2415,4836730 +987,delete,41.455,-1.0,-1.0,-1.0,-1.0,24.636,2.37774,2413,4797164 +988,search,3921.03,0.89207,0.1282,19.095,19.4159,30.222,2.3784,2414,4797164 +989,delete,13.554,-1.0,-1.0,-1.0,-1.0,13.35,2.37433,2414,4784789 +990,search,3920.91,0.89222,0.127989,19.0587,19.3921,15.401,2.37433,2414,4784789 +991,delete,66.729,-1.0,-1.0,-1.0,-1.0,226.377,2.33598,2391,4705420 +992,search,3901.93,0.89522,0.125494,18.8565,19.4593,49.407,2.33668,2396,4705420 +993,delete,74.828,-1.0,-1.0,-1.0,-1.0,102.404,2.29672,2385,4621807 +994,search,3853.21,0.89396,0.125974,18.956,19.4514,23.592,2.29677,2387,4621807 +995,delete,58.369,-1.0,-1.0,-1.0,-1.0,71.282,2.26522,2378,4555849 +996,search,3826.49,0.89349,0.126335,19.0319,19.47,15.494,2.26522,2378,4555849 +997,delete,28.017,-1.0,-1.0,-1.0,-1.0,50.617,2.2524,2375,4526975 +998,search,3847.7,0.8935,0.126484,19.0376,19.462,15.373,2.2524,2375,4526975 +999,delete,110.466,-1.0,-1.0,-1.0,-1.0,154.198,2.19358,2351,4408448 +1000,search,3800.63,0.89326,0.126231,19.08,19.4691,28.113,2.19382,2352,4408448 +1001,delete,115.589,-1.0,-1.0,-1.0,-1.0,130.855,2.13752,2337,4303257 +1002,search,3764.08,0.8928,0.126275,19.1727,19.5384,22.456,2.13752,2337,4303257 +1003,delete,41.725,-1.0,-1.0,-1.0,-1.0,54.85,2.11493,2331,4259551 +1004,search,3720.43,0.8926,0.126544,19.2315,19.5582,22.222,2.11493,2331,4259551 +1005,delete,18.607,-1.0,-1.0,-1.0,-1.0,26.14,2.10764,2330,4241434 +1006,search,3730.14,0.89263,0.126606,19.2302,19.5676,22.249,2.10764,2330,4241434 +1007,delete,171.133,-1.0,-1.0,-1.0,-1.0,326.898,2.00702,2281,4052722 +1008,search,3627.38,0.89065,0.128185,19.5065,19.7274,21.684,2.00702,2281,4052722 +1009,delete,273.552,-1.0,-1.0,-1.0,-1.0,379.394,1.84592,2204,3738432 +1010,search,3486.49,0.88807,0.12956,19.6378,19.6654,29.83,1.84624,2205,3738432 +1011,delete,332.766,-1.0,-1.0,-1.0,-1.0,525.162,1.65252,2090,3372539 +1012,search,3272.8,0.88334,0.13124,20.0682,19.7994,36.887,1.65305,2093,3372539 +1013,delete,9.458,-1.0,-1.0,-1.0,-1.0,39.702,1.64766,2088,3361432 +1014,search,3261.47,0.88255,0.131645,20.193,19.8993,26.807,1.64773,2089,3361432 +1015,delete,231.539,-1.0,-1.0,-1.0,-1.0,360.837,1.51355,2011,3091692 +1016,search,3167.21,0.87943,0.133227,20.7062,20.0308,18.446,1.51355,2011,3091692 +1017,delete,300.616,-1.0,-1.0,-1.0,-1.0,473.47,1.34699,1923,2775418 +1018,search,2969.91,0.87768,0.13406,20.8793,20.0382,28.194,1.34744,1924,2775418 +1019,delete,18.823,-1.0,-1.0,-1.0,-1.0,36.362,1.33951,1921,2754073 +1020,search,2981.47,0.87713,0.134475,20.9658,20.1365,17.751,1.33951,1921,2754073 +1021,delete,104.465,-1.0,-1.0,-1.0,-1.0,73.467,1.30063,1907,2638917 +1022,search,2922.3,0.87535,0.135607,21.1329,20.2157,17.42,1.30063,1907,2638917 +1023,delete,75.146,-1.0,-1.0,-1.0,-1.0,101.163,1.26316,1879,2556494 +1024,search,2857.85,0.87207,0.138725,21.4336,20.4014,16.957,1.26316,1879,2556494 +1025,insert,22.274,-1.0,-1.0,-1.0,-1.0,27.721,1.26968,1881,2594934 +1026,search,2887.49,0.87297,0.138201,21.2935,20.3187,16.793,1.26968,1881,2594934 +1027,insert,182.326,-1.0,-1.0,-1.0,-1.0,85.044,1.3307,1889,2802105 +1028,search,2942.79,0.87323,0.138801,21.2512,20.4404,41.655,1.3307,1892,2802105 +1029,insert,377.993,-1.0,-1.0,-1.0,-1.0,212.263,1.47454,1923,3203975 +1030,search,3116.16,0.87935,0.134747,20.6259,20.1683,102.333,1.47465,1938,3203975 +1031,insert,551.468,-1.0,-1.0,-1.0,-1.0,308.514,1.73082,1968,3830566 +1032,search,3339.87,0.88214,0.13567,20.2031,20.2685,87.47,1.73082,1979,3830566 +1033,insert,415.119,-1.0,-1.0,-1.0,-1.0,270.063,1.91549,2027,4252669 +1034,search,3504.2,0.88779,0.132399,19.2201,19.5834,93.276,1.91553,2039,4252669 +1035,insert,216.563,-1.0,-1.0,-1.0,-1.0,234.989,2.02793,2072,4512107 +1036,search,3614.11,0.8892,0.132134,19.0263,19.5445,89.305,2.02858,2085,4512107 +1037,insert,17.062,-1.0,-1.0,-1.0,-1.0,21.569,2.03365,2086,4525815 +1038,search,3626.07,0.8894,0.132015,18.9895,19.5214,18.28,2.03365,2086,4525815 +1039,insert,85.733,-1.0,-1.0,-1.0,-1.0,32.089,2.06173,2091,4599215 +1040,search,3637.27,0.89003,0.13175,18.8562,19.4363,18.374,2.06173,2091,4599215 +1041,insert,12.391,-1.0,-1.0,-1.0,-1.0,16.547,2.06583,2091,4609851 +1042,search,3663.58,0.89025,0.131838,18.813,19.4291,18.388,2.06583,2091,4609851 +1043,insert,21.397,-1.0,-1.0,-1.0,-1.0,26.088,2.07265,2093,4627411 +1044,search,3657.55,0.89031,0.131778,18.7959,19.4187,18.256,2.07265,2093,4627411 +1045,insert,50.111,-1.0,-1.0,-1.0,-1.0,18.903,2.08969,2094,4670607 +1046,search,3654.09,0.89069,0.132007,18.729,19.4353,18.276,2.08969,2094,4670607 +1047,insert,6.353,-1.0,-1.0,-1.0,-1.0,21.549,2.09164,2095,4675386 +1048,search,3666.22,0.89086,0.131947,18.711,19.4208,18.113,2.09164,2095,4675386 +1049,insert,18.079,-1.0,-1.0,-1.0,-1.0,22.218,2.09808,2096,4689998 +1050,search,3661.99,0.89095,0.131895,18.6839,19.4094,26.067,2.09828,2097,4689998 +1051,insert,102.614,-1.0,-1.0,-1.0,-1.0,69.583,2.13841,2111,4783971 +1052,search,3724.22,0.89131,0.131895,18.6613,19.4049,21.888,2.13848,2112,4783971 +1053,insert,50.467,-1.0,-1.0,-1.0,-1.0,37.465,2.15505,2117,4826219 +1054,search,3735,0.89113,0.132139,18.6362,19.365,18.268,2.15505,2117,4826219 +1055,insert,45.192,-1.0,-1.0,-1.0,-1.0,21.102,2.16831,2118,4862355 +1056,search,3757.83,0.89172,0.132032,18.5487,19.3058,18.302,2.16831,2118,4862355 +1057,insert,9.664,-1.0,-1.0,-1.0,-1.0,16.709,2.17047,2118,4869564 +1058,search,3754.78,0.89182,0.132035,18.5548,19.3001,18.423,2.17047,2118,4869564 +1059,insert,30.88,-1.0,-1.0,-1.0,-1.0,16.741,2.17903,2118,4898570 +1060,search,3752.78,0.89208,0.131799,18.5221,19.2767,18.381,2.17903,2118,4898570 +1061,insert,12.267,-1.0,-1.0,-1.0,-1.0,19.299,2.18265,2119,4907501 +1062,search,3776.47,0.892,0.13183,18.4976,19.2457,24.722,2.18281,2120,4907501 +1063,insert,8.82,-1.0,-1.0,-1.0,-1.0,28.889,2.1861,2122,4916386 +1064,search,3769.11,0.89237,0.131491,18.4965,19.2376,21.784,2.18615,2123,4916386 +1065,insert,313.719,-1.0,-1.0,-1.0,-1.0,255.608,2.3092,2168,5194839 +1066,search,3882.72,0.8942,0.129415,18.2529,19.0722,56.868,2.3093,2174,5194839 +1067,insert,5.91,-1.0,-1.0,-1.0,-1.0,18.037,2.31135,2174,5200182 +1068,search,3889.32,0.89465,0.12905,18.2186,19.0463,32.087,2.31152,2177,5200182 +1069,insert,32.787,-1.0,-1.0,-1.0,-1.0,42.549,2.32452,2187,5230883 +1070,search,3915.69,0.89494,0.128397,18.121,18.9842,19.363,2.32452,2187,5230883 +1071,insert,24.659,-1.0,-1.0,-1.0,-1.0,53.328,2.33532,2193,5255659 +1072,search,3930.59,0.8954,0.128218,18.0972,18.9911,19.413,2.33532,2193,5255659 +1073,insert,42.067,-1.0,-1.0,-1.0,-1.0,17.914,2.34888,2193,5281693 +1074,search,3937.12,0.8956,0.128056,18.0648,18.9683,21.51,2.34888,2193,5281693 +1075,insert,11.252,-1.0,-1.0,-1.0,-1.0,17.953,2.35235,2193,5290081 +1076,search,3949.57,0.89567,0.128075,18.0346,18.9325,19.773,2.35235,2193,5290081 +1077,insert,30.592,-1.0,-1.0,-1.0,-1.0,23.574,2.36256,2194,5316166 +1078,search,3942.28,0.89562,0.127978,18.0559,18.9651,19.435,2.36256,2194,5316166 +1079,insert,24.457,-1.0,-1.0,-1.0,-1.0,21.262,2.37079,2195,5335531 +1080,search,3967.7,0.89599,0.127799,18.0337,18.9715,19.339,2.37079,2195,5335531 +1081,insert,383.642,-1.0,-1.0,-1.0,-1.0,218.852,2.52355,2232,5678781 +1082,search,4083.12,0.89744,0.126754,17.8416,18.9768,88.64,2.52489,2245,5678781 +1083,insert,1.048,-1.0,-1.0,-1.0,-1.0,19.194,2.52527,2245,5679848 +1084,search,4096.89,0.89729,0.126928,17.8642,18.9911,31.717,2.52527,2247,5679848 +1085,insert,21.33,-1.0,-1.0,-1.0,-1.0,33.108,2.53382,2251,5702205 +1086,search,4102.89,0.89756,0.12679,17.8317,18.9699,20.479,2.53382,2251,5702205 +1087,insert,16.803,-1.0,-1.0,-1.0,-1.0,26.963,2.5393,2253,5715514 +1088,search,4117.02,0.89767,0.126701,17.8003,18.9587,26.169,2.53957,2254,5715514 +1089,insert,428.356,-1.0,-1.0,-1.0,-1.0,353.092,2.70722,2336,6103499 +1090,search,4328.15,0.89983,0.124974,17.5956,18.8381,69.448,2.70755,2348,6103499 +1091,insert,53.621,-1.0,-1.0,-1.0,-1.0,58.113,2.7293,2362,6152505 +1092,search,4349.66,0.90017,0.125037,17.5816,18.8423,15.698,2.7293,2362,6152505 +1093,insert,19.306,-1.0,-1.0,-1.0,-1.0,23.251,2.73674,2364,6171104 +1094,search,4339.63,0.90027,0.12497,17.5631,18.8404,25.543,2.73716,2365,6171104 +1095,insert,371.748,-1.0,-1.0,-1.0,-1.0,490.563,2.91159,2457,6557850 +1096,search,4546.45,0.90316,0.123043,17.1815,18.6211,97.648,2.91264,2474,6557850 +1097,insert,17.73,-1.0,-1.0,-1.0,-1.0,25.696,2.92036,2477,6579289 +1098,search,4581.86,0.90356,0.122644,17.1444,18.6058,23.224,2.92036,2479,6579289 +1099,insert,10.733,-1.0,-1.0,-1.0,-1.0,14.064,2.92478,2479,6591442 +1100,search,4571.91,0.90372,0.122582,17.111,18.5635,15.636,2.92478,2479,6591442 +1101,insert,39.951,-1.0,-1.0,-1.0,-1.0,33.897,2.94152,2484,6633739 +1102,search,4580.93,0.9042,0.122161,17.0778,18.5504,26.955,2.94182,2487,6633739 +1103,insert,96.978,-1.0,-1.0,-1.0,-1.0,112.674,2.98458,2519,6724357 +1104,search,4675.59,0.90587,0.121029,16.9194,18.4708,26.567,2.98471,2522,6724357 +1105,insert,2.349,-1.0,-1.0,-1.0,-1.0,14.585,2.98561,2522,6727059 +1106,search,4698.91,0.90601,0.120891,16.9345,18.4836,23.88,2.98597,2523,6727059 +1107,insert,224.06,-1.0,-1.0,-1.0,-1.0,258.676,3.08338,2576,6950869 +1108,search,4816.99,0.90637,0.1204,16.8188,18.4172,41.445,3.08358,2581,6950869 +1109,insert,5.113,-1.0,-1.0,-1.0,-1.0,21.805,3.08526,2582,6958173 +1110,search,4817.32,0.90653,0.120358,16.7917,18.3984,16.263,3.08526,2582,6958173 +1111,insert,33.787,-1.0,-1.0,-1.0,-1.0,55.106,3.09831,2593,6995273 +1112,search,4791.35,0.90675,0.120214,16.774,18.3817,16.071,3.09831,2593,6995273 +1113,insert,46.542,-1.0,-1.0,-1.0,-1.0,65.197,3.12207,2608,7047862 +1114,search,4832.1,0.90676,0.120178,16.7418,18.351,34.381,3.12224,2611,7047862 +1115,insert,62.041,-1.0,-1.0,-1.0,-1.0,98.248,3.14732,2632,7110727 +1116,search,4881.35,0.90771,0.119961,16.6864,18.3606,31.113,3.14772,2635,7110727 +1117,insert,16.247,-1.0,-1.0,-1.0,-1.0,28.918,3.15306,2639,7125591 +1118,search,4922.02,0.9077,0.120119,16.6926,18.3704,16.777,3.15306,2639,7125591 +1119,insert,9.446,-1.0,-1.0,-1.0,-1.0,14.745,3.15605,2639,7134442 +1120,search,4942.14,0.9077,0.120202,16.6672,18.3585,16.631,3.15605,2639,7134442 +1121,insert,35.046,-1.0,-1.0,-1.0,-1.0,40.613,3.16933,2644,7162109 +1122,search,4957.82,0.90802,0.120078,16.6191,18.3359,20.4,3.16934,2645,7162109 +1123,insert,20.104,-1.0,-1.0,-1.0,-1.0,36.842,3.17753,2650,7179509 +1124,search,4943.4,0.90849,0.119653,16.6069,18.3227,22.328,3.17764,2651,7179509 +1125,insert,6.846,-1.0,-1.0,-1.0,-1.0,23.349,3.18061,2652,7186372 +1126,search,4942.22,0.90839,0.119742,16.6007,18.3128,24.004,3.18081,2653,7186372 +1127,insert,42.876,-1.0,-1.0,-1.0,-1.0,61.358,3.20147,2663,7231450 +1128,search,4950.53,0.90835,0.119727,16.6012,18.3197,31.878,3.20183,2667,7231450 +1129,insert,13.438,-1.0,-1.0,-1.0,-1.0,29.213,3.20663,2670,7243215 +1130,search,5005.94,0.9085,0.119535,16.5827,18.3082,23.793,3.20673,2672,7243215 +1131,insert,39.691,-1.0,-1.0,-1.0,-1.0,43.999,3.22105,2678,7276107 +1132,search,5005.45,0.90816,0.119882,16.5835,18.3448,16.985,3.22105,2678,7276107 +1133,insert,19.035,-1.0,-1.0,-1.0,-1.0,22.783,3.22762,2680,7292577 +1134,search,5025.78,0.90862,0.11929,16.5698,18.3275,25.24,3.22779,2682,7292577 +1135,insert,8.844,-1.0,-1.0,-1.0,-1.0,30.699,3.23105,2685,7299867 +1136,search,5015.91,0.90851,0.119314,16.5772,18.32,16.927,3.23105,2685,7299867 +1137,insert,25.923,-1.0,-1.0,-1.0,-1.0,30.626,3.24003,2689,7323342 +1138,search,5022.79,0.90839,0.119415,16.5786,18.3219,16.425,3.24003,2689,7323342 +1139,insert,3.958,-1.0,-1.0,-1.0,-1.0,26.955,3.24209,2691,7325844 +1140,search,5020.71,0.90873,0.119092,16.5687,18.3054,23.781,3.24223,2693,7325844 +1141,insert,206.014,-1.0,-1.0,-1.0,-1.0,275.949,3.33407,2750,7540761 +1142,search,5156.6,0.91005,0.117957,16.3558,18.1282,65.615,3.33526,2764,7540761 +1143,insert,23.708,-1.0,-1.0,-1.0,-1.0,34.327,3.3451,2769,7561926 +1144,search,5183.69,0.91002,0.117766,16.3447,18.1386,22.657,3.34515,2770,7561926 +1145,insert,10.215,-1.0,-1.0,-1.0,-1.0,28.445,3.34922,2773,7571861 +1146,search,5186.87,0.91027,0.117572,16.3464,18.141,23.551,3.34943,2774,7571861 +1147,insert,19.864,-1.0,-1.0,-1.0,-1.0,31.191,3.35688,2777,7590881 +1148,search,5184.25,0.91023,0.117736,16.3253,18.1129,20.241,3.35692,2778,7590881 +1149,insert,6.132,-1.0,-1.0,-1.0,-1.0,20.823,3.35917,2779,7595507 +1150,search,5175.79,0.91021,0.117807,16.3184,18.1037,17.245,3.35917,2779,7595507 +1151,insert,5.772,-1.0,-1.0,-1.0,-1.0,19.855,3.36091,2780,7601664 +1152,search,5174.16,0.91048,0.117638,16.3059,18.0976,38.971,3.36168,2785,7601664 +1153,delete,17.335,-1.0,-1.0,-1.0,-1.0,24.442,3.35959,2784,7566707 +1154,search,5166.86,0.91016,0.117801,16.3365,18.1327,17.792,3.35959,2784,7566707 +1155,delete,104.003,-1.0,-1.0,-1.0,-1.0,202.038,3.32428,2765,7396192 +1156,search,5125.75,0.90961,0.117762,16.3816,18.1447,23.796,3.32431,2766,7396192 +1157,delete,237.989,-1.0,-1.0,-1.0,-1.0,444.279,3.24074,2705,7079041 +1158,search,4998.14,0.90829,0.118976,16.5685,18.2335,45.227,3.24144,2709,7079041 +1159,delete,331.938,-1.0,-1.0,-1.0,-1.0,450.006,3.07665,2648,6597115 +1160,search,4841.62,0.90564,0.119313,17.0006,18.38,72.404,3.07762,2655,6597115 +1161,delete,212.053,-1.0,-1.0,-1.0,-1.0,306.323,2.98165,2605,6308902 +1162,search,4655.65,0.90393,0.120306,17.2842,18.5806,33.739,2.98186,2608,6308902 +1163,delete,93.166,-1.0,-1.0,-1.0,-1.0,233.264,2.9251,2579,6164514 +1164,search,4583.41,0.90354,0.12074,17.3274,18.5752,25.827,2.92532,2580,6164514 +1165,delete,28.361,-1.0,-1.0,-1.0,-1.0,37.398,2.91859,2577,6133412 +1166,search,4549.93,0.90347,0.120642,17.3554,18.6026,17.213,2.91859,2577,6133412 +1167,delete,52.193,-1.0,-1.0,-1.0,-1.0,15.396,2.90749,2577,6057218 +1168,search,4547.02,0.9028,0.121199,17.4523,18.7013,17.341,2.90749,2577,6057218 +1169,delete,18.006,-1.0,-1.0,-1.0,-1.0,85.726,2.89318,2566,6028053 +1170,search,4540.28,0.90054,0.12207,17.8459,18.893,17.225,2.89318,2566,6028053 +1171,delete,24.687,-1.0,-1.0,-1.0,-1.0,21.219,2.88651,2565,6001880 +1172,search,4506.82,0.90043,0.122081,17.8574,18.9027,17.383,2.88651,2565,6001880 +1173,delete,38.019,-1.0,-1.0,-1.0,-1.0,41.562,2.87506,2562,5957180 +1174,search,4505.01,0.90013,0.122476,17.8923,18.9304,17.261,2.87506,2562,5957180 +1175,delete,15.351,-1.0,-1.0,-1.0,-1.0,14.571,2.87324,2562,5939326 +1176,search,4516.26,0.90019,0.122519,17.8759,18.9134,17.097,2.87324,2562,5939326 +1177,delete,12.221,-1.0,-1.0,-1.0,-1.0,35.182,2.86878,2561,5924145 +1178,search,4477.91,0.90028,0.122537,17.867,18.9081,16.83,2.86878,2561,5924145 +1179,delete,53.033,-1.0,-1.0,-1.0,-1.0,93.176,2.84409,2550,5863334 +1180,search,4435.8,0.90017,0.122549,17.9083,18.9173,16.755,2.84409,2550,5863334 +1181,delete,34.875,-1.0,-1.0,-1.0,-1.0,14.79,2.83161,2550,5822703 +1182,search,4450.71,0.89995,0.123176,17.9215,18.9417,17.193,2.83161,2550,5822703 +1183,delete,40.245,-1.0,-1.0,-1.0,-1.0,50.732,2.81737,2545,5775807 +1184,search,4422.6,0.89901,0.124013,17.9807,18.9527,17.081,2.81737,2545,5775807 +1185,delete,23.714,-1.0,-1.0,-1.0,-1.0,28.102,2.81091,2543,5750627 +1186,search,4436.42,0.89881,0.124075,18.0253,18.9551,17.173,2.81091,2543,5750627 +1187,delete,137.605,-1.0,-1.0,-1.0,-1.0,191.88,2.75749,2518,5601207 +1188,search,4361.04,0.89813,0.124507,18.1217,19.0574,22.841,2.75751,2519,5601207 +1189,delete,13.255,-1.0,-1.0,-1.0,-1.0,14.364,2.75516,2519,5586425 +1190,search,4323.71,0.89791,0.124741,18.1179,19.0514,16.676,2.75516,2519,5586425 +1191,delete,10.119,-1.0,-1.0,-1.0,-1.0,21.575,2.75248,2518,5574023 +1192,search,4355.59,0.89785,0.124629,18.1584,19.0781,21.909,2.75259,2519,5574023 +1193,delete,179.87,-1.0,-1.0,-1.0,-1.0,319.61,2.64866,2481,5356157 +1194,search,4223.98,0.89695,0.124666,18.3255,19.1348,16.314,2.64866,2481,5356157 +1195,delete,13.026,-1.0,-1.0,-1.0,-1.0,14.073,2.64523,2481,5340404 +1196,search,4231.56,0.89682,0.124881,18.305,19.1347,16.517,2.64523,2481,5340404 +1197,delete,49.841,-1.0,-1.0,-1.0,-1.0,14.398,2.62958,2481,5293259 +1198,search,4213.5,0.89649,0.125362,18.3267,19.1591,16.493,2.62958,2481,5293259 +1199,delete,11.574,-1.0,-1.0,-1.0,-1.0,19.664,2.62421,2480,5279787 +1200,search,4212.39,0.89662,0.125124,18.3056,19.1277,16.723,2.62421,2480,5279787 +1201,delete,71.12,-1.0,-1.0,-1.0,-1.0,104.345,2.58937,2468,5216567 +1202,search,4199.9,0.89557,0.125814,18.4141,19.2112,16.567,2.58937,2468,5216567 +1203,delete,20.718,-1.0,-1.0,-1.0,-1.0,13.902,2.58403,2468,5196947 +1204,search,4153.9,0.89563,0.125794,18.4381,19.2321,16.291,2.58403,2468,5196947 +1205,delete,20.735,-1.0,-1.0,-1.0,-1.0,39.023,2.57214,2464,5168447 +1206,search,4160.14,0.89539,0.125812,18.46,19.205,16.328,2.57214,2464,5168447 +1207,delete,20.536,-1.0,-1.0,-1.0,-1.0,48.044,2.56042,2460,5146927 +1208,search,4119.18,0.89535,0.125383,18.5226,19.1917,32.15,2.56087,2463,5146927 +1209,delete,234.793,-1.0,-1.0,-1.0,-1.0,318.21,2.42836,2416,4887612 +1210,search,4039.75,0.89423,0.126295,18.5014,19.0551,21.657,2.4286,2417,4887612 +1211,delete,4.279,-1.0,-1.0,-1.0,-1.0,13.693,2.42684,2417,4882301 +1212,search,4032.7,0.89435,0.126289,18.5046,19.0499,16.38,2.42684,2417,4882301 +1213,delete,107.114,-1.0,-1.0,-1.0,-1.0,103.29,2.37985,2405,4780915 +1214,search,4008.04,0.89339,0.126939,18.6922,19.1902,15.994,2.37985,2405,4780915 +1215,delete,14.959,-1.0,-1.0,-1.0,-1.0,13.598,2.3758,2405,4765751 +1216,search,4015.37,0.89326,0.126658,18.6929,19.1685,16.034,2.3758,2405,4765751 +1217,delete,313.116,-1.0,-1.0,-1.0,-1.0,425.142,2.20907,2317,4452306 +1218,search,3836.16,0.89072,0.127679,19.0472,19.3778,29.321,2.2092,2318,4452306 +1219,delete,79.884,-1.0,-1.0,-1.0,-1.0,168.953,2.15866,2285,4362045 +1220,search,3776.47,0.88921,0.128834,19.1923,19.4092,25.45,2.15866,2286,4362045 +1221,delete,31.035,-1.0,-1.0,-1.0,-1.0,34.881,2.14681,2283,4326917 +1222,search,3763.19,0.889,0.129175,19.2281,19.4299,25.602,2.14687,2284,4326917 +1223,delete,181.218,-1.0,-1.0,-1.0,-1.0,287.705,2.03944,2228,4109781 +1224,search,3642.64,0.88613,0.131328,19.5099,19.5291,20.628,2.03944,2228,4109781 +1225,delete,25.601,-1.0,-1.0,-1.0,-1.0,47.126,2.02571,2224,4075879 +1226,search,3630.47,0.88581,0.131756,19.5161,19.484,20.535,2.02571,2224,4075879 +1227,delete,62.548,-1.0,-1.0,-1.0,-1.0,97.999,1.99317,2212,4006503 +1228,search,3599.72,0.88549,0.131615,19.613,19.5174,26.709,1.99321,2213,4006503 +1229,delete,72.632,-1.0,-1.0,-1.0,-1.0,82.775,1.95396,2204,3922625 +1230,search,3537.87,0.88456,0.132527,19.703,19.5672,21.218,1.95396,2204,3922625 +1231,delete,77.212,-1.0,-1.0,-1.0,-1.0,153.205,1.91059,2165,3844860 +1232,search,3512.75,0.88255,0.134077,19.858,19.5616,20.028,1.91059,2165,3844860 +1233,delete,12.817,-1.0,-1.0,-1.0,-1.0,21.937,1.90637,2164,3831414 +1234,search,3487.01,0.88235,0.134089,19.9051,19.5939,20.243,1.90637,2164,3831414 +1235,delete,144.989,-1.0,-1.0,-1.0,-1.0,151.89,1.83465,2143,3684234 +1236,search,3424.41,0.88158,0.134207,20.0265,19.6125,20.176,1.83465,2143,3684234 +1237,delete,13.084,-1.0,-1.0,-1.0,-1.0,23.67,1.8308,2142,3669074 +1238,search,3433.55,0.88144,0.134108,20.0168,19.5975,19.668,1.8308,2142,3669074 +1239,delete,52.075,-1.0,-1.0,-1.0,-1.0,18.085,1.81247,2142,3620984 +1240,search,3411.88,0.88111,0.134549,20.0523,19.609,19.72,1.81247,2142,3620984 +1241,delete,37.731,-1.0,-1.0,-1.0,-1.0,17.727,1.79797,2142,3580113 +1242,search,3397.82,0.88072,0.13503,20.0874,19.6343,19.646,1.79797,2142,3580113 +1243,delete,46.127,-1.0,-1.0,-1.0,-1.0,40.026,1.774,2138,3533909 +1244,search,3403.08,0.88046,0.135635,20.0601,19.6079,19.583,1.774,2138,3533909 +1245,delete,13.76,-1.0,-1.0,-1.0,-1.0,21.248,1.7675,2137,3519590 +1246,search,3371.48,0.88008,0.136104,20.0736,19.6238,19.297,1.7675,2137,3519590 +1247,delete,48.734,-1.0,-1.0,-1.0,-1.0,77.926,1.73201,2107,3452537 +1248,search,3313.37,0.88094,0.134287,20.4095,19.8576,22.041,1.73206,2108,3452537 +1249,delete,33.433,-1.0,-1.0,-1.0,-1.0,39.434,1.71709,2105,3416711 +1250,search,3302.45,0.88027,0.134608,20.4307,19.8369,19.113,1.71709,2105,3416711 +1251,delete,25.444,-1.0,-1.0,-1.0,-1.0,34.571,1.70445,2101,3387653 +1252,search,3303.63,0.87985,0.134845,20.4647,19.832,19.745,1.70445,2101,3387653 +1253,delete,14.49,-1.0,-1.0,-1.0,-1.0,25.488,1.69821,2099,3372157 +1254,search,3312.22,0.87951,0.135044,20.4681,19.8386,19.931,1.69821,2099,3372157 +1255,delete,105.78,-1.0,-1.0,-1.0,-1.0,95.31,1.63936,2065,3258215 +1256,search,3255.41,0.87782,0.135303,20.8373,20.0105,18.762,1.63936,2065,3258215 +1257,delete,34.914,-1.0,-1.0,-1.0,-1.0,70.5,1.62005,2052,3223657 +1258,search,3216.7,0.87735,0.135522,20.9455,20.0295,33.574,1.62025,2054,3223657 +1259,delete,43.552,-1.0,-1.0,-1.0,-1.0,71.192,1.59594,2043,3174982 +1260,search,3199.14,0.87676,0.136062,20.9941,20.0345,18.486,1.59594,2043,3174982 +1261,delete,20.632,-1.0,-1.0,-1.0,-1.0,16.292,1.58728,2043,3157038 +1262,search,3201.68,0.87655,0.136242,21.0488,20.068,18.659,1.58728,2043,3157038 +1263,delete,96.074,-1.0,-1.0,-1.0,-1.0,172.066,1.5309,2021,3058847 +1264,search,3154.73,0.87607,0.135894,21.1419,20.1005,18.239,1.5309,2021,3058847 +1265,delete,221.662,-1.0,-1.0,-1.0,-1.0,292.673,1.39603,1911,2833531 +1266,search,2986.09,0.87245,0.138987,21.5975,20.2781,44.185,1.39651,1914,2833531 +1267,delete,59.181,-1.0,-1.0,-1.0,-1.0,48.174,1.37352,1906,2763793 +1268,search,2946.84,0.87096,0.139493,21.7849,20.3687,17.029,1.37352,1906,2763793 +1269,delete,128.328,-1.0,-1.0,-1.0,-1.0,143.012,1.3081,1870,2627384 +1270,search,2888.27,0.87091,0.139068,21.9489,20.5068,16.75,1.3081,1870,2627384 +1271,delete,69.914,-1.0,-1.0,-1.0,-1.0,85.781,1.27188,1860,2553476 +1272,search,2852.46,0.87026,0.139427,22.1786,20.7333,16.189,1.27188,1860,2553476 +1273,delete,99.231,-1.0,-1.0,-1.0,-1.0,156.533,1.21056,1826,2443067 +1274,search,2805.45,0.86805,0.141061,22.4193,20.8485,15.942,1.21056,1826,2443067 +1275,delete,19.117,-1.0,-1.0,-1.0,-1.0,28.127,1.20158,1824,2421654 +1276,search,2810.13,0.86736,0.141163,22.4812,20.8669,17.037,1.20158,1824,2421654 +1277,delete,35.325,-1.0,-1.0,-1.0,-1.0,52.197,1.18811,1816,2391396 +1278,search,2770.39,0.86736,0.140894,22.5549,20.9303,16.479,1.18811,1816,2391396 +1279,delete,29.439,-1.0,-1.0,-1.0,-1.0,14.178,1.17976,1816,2367854 +1280,search,2790.09,0.86689,0.141322,22.5976,20.9709,16.123,1.17976,1816,2367854 diff --git a/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.8_search_0.1.csv b/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.8_search_0.1.csv new file mode 100644 index 00000000..2be61257 --- /dev/null +++ b/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.8_search_0.1.csv @@ -0,0 +1,29 @@ +step_num,step_type,latency_ms,recall_mean,recall_std_dev,mainteance_ms,index_mem_gb +2,search,1966.88,0.71332,0.182665,1.162,0.0183453 +3,insert,22.103,-1.0,-1.0,0.0,0.0223841 +4,search,1398.1,0.72815,0.180415,1.184,0.0223841 +5,insert,31.968,-1.0,-1.0,0.0,0.0328105 +6,search,1389.93,0.799,0.180539,177.015,0.032773 +7,insert,34.503,-1.0,-1.0,0.0,0.0427686 +8,search,1399.31,0.81574,0.16815,133.372,0.0427686 +9,insert,4.49,-1.0,-1.0,0.0,0.044299 +10,search,1407.64,0.82142,0.165197,134.381,0.044299 +11,insert,13.766,-1.0,-1.0,0.0,0.0500224 +12,search,1431.51,0.82763,0.16291,180.121,0.0500224 +13,insert,52.451,-1.0,-1.0,0.0,0.0608752 +14,search,1446.61,0.82239,0.165688,170.954,0.0605223 +15,insert,21.708,-1.0,-1.0,0.0,0.0686713 +16,search,1425.14,0.83243,0.15671,135.156,0.0688671 +17,insert,3.033,-1.0,-1.0,0.0,0.0705889 +18,search,1456.43,0.83221,0.15824,159.039,0.071309 +19,insert,40.076,-1.0,-1.0,0.0,0.0784319 +20,search,1487.27,0.84655,0.148915,158.331,0.0782972 +21,insert,491.279,-1.0,-1.0,0.0,0.197168 +22,search,1818.86,0.85366,0.143039,430.002,0.197955 +23,insert,376.862,-1.0,-1.0,0.0,0.321783 +24,search,2471.47,0.85815,0.14255,1096.25,0.320824 +25,insert,45.479,-1.0,-1.0,0.0,0.338688 +26,search,2243.45,0.81484,0.162522,854.74,0.34008 +27,insert,43.335,-1.0,-1.0,0.0,0.353591 +28,search,2075.38,0.78549,0.174883,730.448,0.352456 +29,insert,84.975,-1.0,-1.0,0.0,0.379445 diff --git a/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.01.csv b/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.01.csv new file mode 100644 index 00000000..829e94e3 --- /dev/null +++ b/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.01.csv @@ -0,0 +1,47 @@ +step_num,step_type,latency_ms,recall_mean,recall_std_dev,mainteance_ms,index_mem_gb +2,search,585.299,0.30402,0.225896,0.511,0.0183457 +3,insert,10.04,-1.0,-1.0,0.0,0.0223845 +4,search,415.75,0.30883,0.227605,0.559,0.0223845 +5,insert,14.88,-1.0,-1.0,0.0,0.032811 +6,search,402.922,0.33185,0.257537,55.708,0.0331737 +7,insert,22.003,-1.0,-1.0,0.0,0.0421803 +8,search,540.134,0.45891,0.279876,120.639,0.0421925 +9,insert,3.849,-1.0,-1.0,0.0,0.0445059 +10,search,471.401,0.48103,0.267652,100.67,0.0442721 +11,insert,7.19,-1.0,-1.0,0.0,0.0493354 +12,search,482.474,0.46609,0.261136,109.657,0.049213 +13,insert,19.952,-1.0,-1.0,0.0,0.0602477 +14,search,424.731,0.42959,0.256302,85.101,0.0596525 +15,insert,17.45,-1.0,-1.0,0.0,0.0691225 +16,search,535.665,0.42391,0.248077,118.329,0.0688002 +17,insert,3.757,-1.0,-1.0,0.0,0.0712164 +18,search,557.768,0.42416,0.250314,146.088,0.0713127 +19,insert,55.46,-1.0,-1.0,0.0,0.0778346 +20,search,508.566,0.46841,0.253801,154.774,0.0778554 +21,insert,344.779,-1.0,-1.0,0.0,0.197099 +22,search,632.27,0.45878,0.247826,615.33,0.1968 +23,insert,257.694,-1.0,-1.0,0.0,0.315962 +24,search,787.558,0.44987,0.248761,1127.29,0.320233 +25,insert,29.082,-1.0,-1.0,0.0,0.339114 +26,search,740.793,0.4214,0.246488,656.74,0.33744 +27,insert,22.399,-1.0,-1.0,0.0,0.351942 +28,search,630.734,0.40953,0.248731,559.74,0.352849 +29,insert,34.986,-1.0,-1.0,0.0,0.37803 +30,search,632.673,0.41583,0.25098,631.984,0.37854 +31,insert,211.411,-1.0,-1.0,0.0,0.542229 +32,search,870.634,0.42194,0.250413,2233.28,0.543381 +33,insert,42.188,-1.0,-1.0,0.0,0.563387 +34,search,672.622,0.4093,0.250446,963.042,0.563182 +35,insert,26.475,-1.0,-1.0,0.0,0.579811 +36,search,735.102,0.40922,0.250803,911.636,0.578841 +37,insert,41.002,-1.0,-1.0,0.0,0.6011 +38,search,706.686,0.41145,0.251707,0.82,0.6011 +39,insert,5.553,-1.0,-1.0,0.0,0.603488 +40,search,772.152,0.41287,0.252508,846.74,0.602592 +41,insert,33.772,-1.0,-1.0,0.0,0.616597 +42,search,710.203,0.41421,0.252721,711.144,0.615995 +43,insert,8.314,-1.0,-1.0,0.0,0.621732 +44,search,720.162,0.44295,0.251208,1436.69,0.62276 +45,insert,221.623,-1.0,-1.0,0.0,0.637596 +46,search,801.289,0.4398,0.251661,697.218,0.638071 +47,insert,193.781,-1.0,-1.0,0.0,0.739662 diff --git a/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.05.csv b/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.05.csv new file mode 100644 index 00000000..40c50321 --- /dev/null +++ b/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.05.csv @@ -0,0 +1,30 @@ +step_num,step_type,latency_ms,recall_mean,recall_std_dev,mainteance_ms,index_mem_gb +2,search,1212.99,0.57318,0.215132,0.692,0.0183457 +3,insert,12.785,-1.0,-1.0,0.0,0.0223845 +4,search,886.228,0.58479,0.214352,0.713,0.0223845 +5,insert,28.288,-1.0,-1.0,0.0,0.032811 +6,search,921.25,0.6501,0.234824,52.991,0.0331737 +7,insert,31.242,-1.0,-1.0,0.0,0.0421803 +8,search,938.611,0.71684,0.210044,138.231,0.0421803 +9,insert,9.044,-1.0,-1.0,0.0,0.044432 +10,search,923.082,0.72108,0.207619,140.308,0.044432 +11,insert,51.868,-1.0,-1.0,0.0,0.0500424 +12,search,950.845,0.7306,0.208018,180.701,0.0500424 +13,insert,33.462,-1.0,-1.0,0.0,0.0608618 +14,search,962.175,0.72104,0.210593,319.951,0.0609393 +15,insert,22.704,-1.0,-1.0,0.0,0.0695069 +16,search,983.141,0.73115,0.202415,298.381,0.0693388 +17,insert,4.653,-1.0,-1.0,0.0,0.0717288 +18,search,966.999,0.73309,0.205165,305.028,0.0708937 +19,insert,43.22,-1.0,-1.0,0.0,0.0785575 +20,search,990.416,0.74476,0.195827,132.452,0.0786428 +21,insert,444.208,-1.0,-1.0,0.0,0.197663 +22,search,1275.96,0.7618,0.184556,483.58,0.196977 +23,insert,373.099,-1.0,-1.0,0.0,0.3222 +24,search,1701.5,0.74563,0.192421,1089,0.321832 +25,insert,66.437,-1.0,-1.0,0.0,0.342217 +26,search,1452.44,0.69651,0.207331,861.978,0.342148 +27,insert,44.298,-1.0,-1.0,0.0,0.353195 +28,search,1261.29,0.6582,0.217089,585.985,0.352812 +29,insert,93.125,-1.0,-1.0,0.0,0.379974 +30,search,1289.35,0.66812,0.215953,427.994,0.379034 diff --git a/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.15.csv b/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.15.csv new file mode 100644 index 00000000..b2e68761 --- /dev/null +++ b/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.15.csv @@ -0,0 +1,1280 @@ +step_num,step_type,latency_ms,recall_mean,recall_std_dev,mainteance_ms,index_mem_gb +2,search,2370.43,0.79264,0.15727,1.745,0.0183465 +3,insert,20.312,-1.0,-1.0,0.0,0.0223853 +4,search,1849.53,0.80591,0.154693,1.568,0.0223853 +5,insert,26.312,-1.0,-1.0,0.0,0.0328118 +6,search,1806.6,0.86827,0.143601,170.432,0.0327742 +7,insert,33.965,-1.0,-1.0,0.0,0.0427698 +8,search,1837.66,0.86926,0.140821,211.307,0.0423957 +9,insert,4.234,-1.0,-1.0,0.0,0.0443512 +10,search,1872,0.87893,0.134219,236.555,0.044146 +11,insert,14.287,-1.0,-1.0,0.0,0.0492725 +12,search,1909.27,0.89952,0.119695,178.682,0.0491815 +13,insert,27.952,-1.0,-1.0,0.0,0.0605692 +14,search,1865.12,0.89471,0.123545,137.244,0.0605256 +15,insert,23.923,-1.0,-1.0,0.0,0.0695469 +16,search,1934.97,0.90145,0.117855,157.477,0.0691939 +17,insert,4.199,-1.0,-1.0,0.0,0.07132 +18,search,1958.84,0.90297,0.117948,153.911,0.0712368 +19,insert,43.037,-1.0,-1.0,0.0,0.0782773 +20,search,2032.41,0.91147,0.111212,117.065,0.0782683 +21,insert,482.318,-1.0,-1.0,0.0,0.197889 +22,search,2391.27,0.91268,0.107618,540.626,0.197268 +23,insert,367.092,-1.0,-1.0,0.0,0.322254 +24,search,3112.75,0.91586,0.105317,1270.93,0.321147 +25,insert,51.624,-1.0,-1.0,0.0,0.341713 +26,search,2946.23,0.89096,0.120569,933.838,0.341172 +27,insert,30.927,-1.0,-1.0,0.0,0.3528 +28,search,2878.29,0.86545,0.135159,591.642,0.353767 +29,insert,85.583,-1.0,-1.0,0.0,0.379818 +30,search,2912.4,0.86581,0.135647,436.711,0.379959 +31,insert,454.665,-1.0,-1.0,0.0,0.541888 +32,search,3562,0.87398,0.131974,1769.48,0.541311 +33,insert,71.333,-1.0,-1.0,0.0,0.564693 +34,search,3449.56,0.85727,0.141115,1305.06,0.566473 +35,insert,42.006,-1.0,-1.0,0.0,0.580664 +36,search,3434.88,0.85308,0.143894,418.574,0.580322 +37,insert,54.78,-1.0,-1.0,0.0,0.600903 +38,search,3437.14,0.85261,0.144287,315.559,0.601657 +39,insert,4.759,-1.0,-1.0,0.0,0.604079 +40,search,2894.42,0.85691,0.142132,320.784,0.603973 +41,insert,44.326,-1.0,-1.0,0.0,0.618961 +42,search,3486.31,0.85956,0.140792,513.456,0.618796 +43,insert,10.257,-1.0,-1.0,0.0,0.623914 +44,search,3480.71,0.85911,0.140584,446.153,0.624144 +45,insert,257.317,-1.0,-1.0,0.0,0.638205 +46,search,3462.88,0.86065,0.139706,499.457,0.63791 +47,insert,303.829,-1.0,-1.0,0.0,0.741015 +48,search,3558.95,0.8649,0.13903,1306.45,0.740241 +49,insert,42.084,-1.0,-1.0,0.0,0.75487 +50,search,3796.34,0.86379,0.141246,890.549,0.75556 +51,insert,495.022,-1.0,-1.0,0.0,0.891335 +52,search,3945.57,0.87665,0.132782,1925.26,0.890553 +53,insert,61.582,-1.0,-1.0,0.0,0.909738 +54,search,4196.81,0.86639,0.139038,1272.46,0.909348 +55,insert,402.291,-1.0,-1.0,0.0,1.04916 +56,search,4498.11,0.87953,0.133721,3073.49,1.04993 +57,insert,33.233,-1.0,-1.0,0.0,1.05899 +58,search,4535.96,0.87348,0.137471,1580.18,1.05987 +59,insert,295.398,-1.0,-1.0,0.0,1.15773 +60,search,4644.69,0.87461,0.135688,2346.47,1.1571 +61,insert,23.623,-1.0,-1.0,0.0,1.16123 +62,search,4522.09,0.86913,0.141141,1087.59,1.16131 +63,insert,5.186,-1.0,-1.0,0.0,1.16269 +64,search,4473.07,0.86846,0.141798,1028.11,1.16244 +65,insert,184.46,-1.0,-1.0,0.0,1.19188 +66,search,4570.56,0.87171,0.139973,1547.37,1.19192 +67,insert,63.577,-1.0,-1.0,0.0,1.21131 +68,search,4528.54,0.87268,0.139645,1110.3,1.2113 +69,insert,74.782,-1.0,-1.0,0.0,1.23668 +70,search,4825.38,0.87426,0.137943,1406.35,1.23644 +71,insert,21.709,-1.0,-1.0,0.0,1.242 +72,search,4706.48,0.87457,0.137918,816.532,1.24103 +73,insert,9.165,-1.0,-1.0,0.0,1.24542 +74,search,4647.51,0.8747,0.137987,6.208,1.24542 +75,insert,26.83,-1.0,-1.0,0.0,1.25231 +76,search,4748.15,0.87493,0.137693,717.19,1.25222 +77,insert,32.082,-1.0,-1.0,0.0,1.26245 +78,search,4808.37,0.87439,0.137938,792.425,1.26191 +79,insert,680.873,-1.0,-1.0,0.0,1.29251 +80,search,4695.98,0.87394,0.137836,1079.18,1.29272 +81,insert,40.776,-1.0,-1.0,0.0,1.30371 +82,search,4739.84,0.87515,0.136642,1101.36,1.3041 +83,insert,22.124,-1.0,-1.0,0.0,1.31046 +84,search,4775.22,0.87618,0.135781,1161.59,1.31139 +85,insert,49.498,-1.0,-1.0,0.0,1.3266 +86,search,4838.35,0.87705,0.135723,1192.89,1.32693 +87,insert,751.012,-1.0,-1.0,0.0,1.51832 +88,search,4875.43,0.88738,0.127872,5076.96,1.51677 +89,insert,572.394,-1.0,-1.0,0.0,1.67498 +90,search,4925.56,0.88854,0.126729,3663.53,1.6757 +91,insert,47.421,-1.0,-1.0,0.0,1.69296 +92,search,4803.1,0.88502,0.129077,1345.4,1.69345 +93,insert,396.746,-1.0,-1.0,0.0,1.79526 +94,search,4968.18,0.88594,0.128361,1599.27,1.7949 +95,insert,16.004,-1.0,-1.0,0.0,1.80045 +96,search,4963.7,0.88555,0.128435,1122.98,1.8018 +97,insert,9.724,-1.0,-1.0,0.0,1.8061 +98,search,4954.49,0.88538,0.128785,1043.43,1.8063 +99,insert,5.957,-1.0,-1.0,0.0,1.80903 +100,search,5036.91,0.88547,0.128725,3.57,1.80903 +101,insert,42.547,-1.0,-1.0,0.0,1.82065 +102,search,5074.71,0.88613,0.12837,1213.36,1.82145 +103,insert,18.565,-1.0,-1.0,0.0,1.82798 +104,search,5841.38,0.88609,0.128253,5.714,1.82798 +105,insert,17.381,-1.0,-1.0,0.0,1.83237 +106,search,5818.99,0.88637,0.128023,1335.4,1.8323 +107,insert,18.866,-1.0,-1.0,0.0,1.8371 +108,search,5839.12,0.88646,0.127926,3.77,1.8371 +109,insert,733.292,-1.0,-1.0,0.0,1.9988 +110,search,6164.55,0.88955,0.125923,4735.24,2.00004 +111,insert,38.372,-1.0,-1.0,0.0,2.01247 +112,search,6103.05,0.88945,0.12652,1937.94,2.01379 +113,insert,14.636,-1.0,-1.0,0.0,2.0189 +114,search,6310.7,0.88945,0.126346,1381.47,2.01878 +115,insert,44.495,-1.0,-1.0,0.0,2.02936 +116,search,6244.65,0.89028,0.125654,6.779,2.02936 +117,insert,23.195,-1.0,-1.0,0.0,2.03489 +118,search,6327.02,0.89043,0.125243,7.15,2.03489 +119,insert,10.161,-1.0,-1.0,0.0,2.03665 +120,search,6119.13,0.89048,0.12524,1319.98,2.03681 +121,insert,24.167,-1.0,-1.0,0.0,2.04243 +122,search,6288.69,0.89048,0.1252,1314.92,2.04179 +123,insert,591.925,-1.0,-1.0,0.0,2.16494 +124,search,6752.83,0.89348,0.124014,2990.92,2.16236 +125,insert,75.521,-1.0,-1.0,0.0,2.18253 +126,search,5704.28,0.89371,0.123867,1846.69,2.18363 +127,insert,76.199,-1.0,-1.0,0.0,2.20661 +128,search,6330.02,0.89507,0.123169,2172.15,2.20556 +129,delete,10.361,-1.0,-1.0,0.0,2.20475 +130,search,6444.44,0.89481,0.123189,2002.84,2.20509 +131,delete,3.57,-1.0,-1.0,0.0,2.20505 +132,search,6676.43,0.89513,0.123071,9.029,2.20505 +133,delete,14.905,-1.0,-1.0,0.0,2.20505 +134,search,6523.89,0.8952,0.1231,8.679,2.20505 +135,delete,25.164,-1.0,-1.0,0.0,2.20361 +136,search,6718.7,0.89665,0.121675,8.589,2.20361 +137,delete,4.641,-1.0,-1.0,0.0,2.20324 +138,search,6734.1,0.89661,0.121687,8.782,2.20324 +139,delete,9.82,-1.0,-1.0,0.0,2.20122 +140,search,6477.88,0.89667,0.121626,8.582,2.20122 +141,delete,22.458,-1.0,-1.0,0.0,2.19894 +142,search,6548.58,0.89691,0.121608,8.575,2.19894 +143,delete,16.012,-1.0,-1.0,0.0,2.19751 +144,search,6703.05,0.89714,0.12144,8.571,2.19751 +145,delete,3.161,-1.0,-1.0,0.0,2.19666 +146,search,6548.61,0.89669,0.121652,8.618,2.19666 +147,delete,9.508,-1.0,-1.0,0.0,2.19632 +148,search,6644.73,0.89683,0.121682,8.586,2.19632 +149,delete,217.473,-1.0,-1.0,0.0,2.15297 +150,search,6651.4,0.90159,0.117581,6.822,2.15297 +151,delete,116.943,-1.0,-1.0,0.0,2.11581 +152,search,5838.79,0.90153,0.117719,5.858,2.11581 +153,delete,29.835,-1.0,-1.0,0.0,2.10282 +154,search,6308.56,0.90122,0.118108,8.811,2.10282 +155,delete,30.911,-1.0,-1.0,0.0,2.09805 +156,search,6093.38,0.90118,0.11805,9.087,2.09805 +157,delete,53.782,-1.0,-1.0,0.0,2.08773 +158,search,6124.56,0.90091,0.118504,8.743,2.08773 +159,delete,362.993,-1.0,-1.0,0.0,1.97016 +160,search,6411.57,0.90044,0.118671,8.644,1.97016 +161,delete,56.72,-1.0,-1.0,0.0,1.95529 +162,search,6090.25,0.9005,0.118557,8.892,1.95529 +163,delete,30.217,-1.0,-1.0,0.0,1.94444 +164,search,6373.51,0.90029,0.118643,11.121,1.94444 +165,delete,40.536,-1.0,-1.0,0.0,1.93449 +166,search,5896.14,0.90042,0.118582,5.746,1.93449 +167,delete,4.756,-1.0,-1.0,0.0,1.93286 +168,search,5445.44,0.90041,0.118524,5.719,1.93286 +169,delete,12.693,-1.0,-1.0,0.0,1.92527 +170,search,5320.26,0.90017,0.11866,5.731,1.92527 +171,delete,6,-1.0,-1.0,0.0,1.92215 +172,search,5619.92,0.89991,0.11887,5.729,1.92215 +173,delete,24.528,-1.0,-1.0,0.0,1.91119 +174,search,6016.14,0.89875,0.120062,8.809,1.91119 +175,delete,187.373,-1.0,-1.0,0.0,1.83751 +176,search,6197.75,0.89881,0.119869,8.636,1.83751 +177,delete,18.243,-1.0,-1.0,0.0,1.83167 +178,search,6036.82,0.89839,0.119965,9.487,1.83167 +179,delete,277.993,-1.0,-1.0,0.0,1.72953 +180,search,6040.89,0.89511,0.1217,8.866,1.72953 +181,delete,37.367,-1.0,-1.0,0.0,1.71671 +182,search,5816.15,0.89504,0.121898,8.845,1.71671 +183,delete,185.154,-1.0,-1.0,0.0,1.64609 +184,search,5900.02,0.89018,0.124488,9.281,1.64609 +185,delete,18.741,-1.0,-1.0,0.0,1.64284 +186,search,5709.96,0.89038,0.124311,9.385,1.64284 +187,delete,243.213,-1.0,-1.0,0.0,1.55335 +188,search,5861.75,0.89384,0.12119,8.846,1.55335 +189,delete,13.405,-1.0,-1.0,0.0,1.54912 +190,search,5679.7,0.89361,0.121327,8.965,1.54912 +191,delete,5.429,-1.0,-1.0,0.0,1.54841 +192,search,5886.29,0.89365,0.121283,8.8,1.54841 +193,delete,78.305,-1.0,-1.0,0.0,1.52053 +194,search,5698.73,0.89092,0.123385,8.73,1.52053 +195,delete,45.966,-1.0,-1.0,0.0,1.50421 +196,search,5465.24,0.89003,0.123804,8.928,1.50421 +197,delete,46.866,-1.0,-1.0,0.0,1.49285 +198,search,5438.47,0.88996,0.123851,8.797,1.49285 +199,delete,15.619,-1.0,-1.0,0.0,1.48822 +200,search,5574.72,0.88935,0.124253,8.764,1.48822 +201,delete,8.344,-1.0,-1.0,0.0,1.48599 +202,search,5725.68,0.88915,0.124342,8.8,1.48599 +203,delete,16.788,-1.0,-1.0,0.0,1.48215 +204,search,5558.64,0.88882,0.124659,8.833,1.48215 +205,delete,28.878,-1.0,-1.0,0.0,1.47233 +206,search,5694.39,0.88905,0.124582,8.825,1.47233 +207,delete,59.744,-1.0,-1.0,0.0,1.4524 +208,search,5668.62,0.88934,0.124024,8.814,1.4524 +209,delete,30.581,-1.0,-1.0,0.0,1.43977 +210,search,5645.99,0.88906,0.124042,9.525,1.43977 +211,delete,24.687,-1.0,-1.0,0.0,1.43462 +212,search,5667.02,0.88889,0.12418,9.006,1.43462 +213,delete,25.319,-1.0,-1.0,0.0,1.42514 +214,search,5450,0.88823,0.124256,9.246,1.42514 +215,delete,408.223,-1.0,-1.0,0.0,1.26758 +216,search,5429.99,0.88258,0.129093,8.993,1.26758 +217,delete,281.247,-1.0,-1.0,0.0,1.16842 +218,search,5372.85,0.87823,0.132255,9.007,1.16842 +219,delete,42.548,-1.0,-1.0,0.0,1.15408 +220,search,5513.66,0.87674,0.133329,8.978,1.15408 +221,delete,235.925,-1.0,-1.0,0.0,1.05579 +222,search,5407.92,0.87681,0.133623,8.994,1.05579 +223,delete,19.145,-1.0,-1.0,0.0,1.0512 +224,search,5347.71,0.87538,0.135072,9.063,1.0512 +225,delete,10.507,-1.0,-1.0,0.0,1.04769 +226,search,5350.19,0.87525,0.135197,8.79,1.04769 +227,delete,5.905,-1.0,-1.0,0.0,1.04609 +228,search,5257.85,0.87509,0.135253,8.965,1.04609 +229,delete,30.699,-1.0,-1.0,0.0,1.03552 +230,search,5341.46,0.87409,0.135644,9.141,1.03552 +231,delete,16.536,-1.0,-1.0,0.0,1.02886 +232,search,5316.52,0.87332,0.135818,8.837,1.02886 +233,delete,8.661,-1.0,-1.0,0.0,1.02533 +234,search,5322.72,0.87292,0.136189,9.005,1.02533 +235,delete,10.637,-1.0,-1.0,0.0,1.02217 +236,search,5317.07,0.87301,0.13615,8.789,1.02217 +237,delete,287.863,-1.0,-1.0,0.0,0.912288 +238,search,5177.42,0.87081,0.137601,8.837,0.912288 +239,delete,27.627,-1.0,-1.0,0.0,0.898865 +240,search,5170.96,0.86924,0.138058,8.98,0.898865 +241,delete,10.716,-1.0,-1.0,0.0,0.894298 +242,search,5150.72,0.86902,0.138144,8.84,0.894298 +243,delete,24.795,-1.0,-1.0,0.0,0.884985 +244,search,5196.43,0.86713,0.13941,8.889,0.884985 +245,delete,17.391,-1.0,-1.0,0.0,0.878583 +246,search,5132.12,0.8667,0.139723,10.996,0.878583 +247,delete,7.15,-1.0,-1.0,0.0,0.87733 +248,search,5141.86,0.86651,0.139753,8.955,0.87733 +249,delete,13.223,-1.0,-1.0,0.0,0.873851 +250,search,5144.65,0.86582,0.140295,9.24,0.873851 +251,delete,317.227,-1.0,-1.0,0.0,0.758392 +252,search,5070.06,0.86618,0.139086,8.905,0.758392 +253,delete,42.376,-1.0,-1.0,0.0,0.741415 +254,search,4821.72,0.86449,0.139571,8.884,0.741415 +255,delete,54.052,-1.0,-1.0,0.0,0.722807 +256,search,5018.51,0.8609,0.142023,8.867,0.722807 +257,insert,12.038,-1.0,-1.0,0.0,0.723916 +258,search,5016.29,0.86076,0.142187,8.998,0.723916 +259,insert,42.693,-1.0,-1.0,0.0,0.730189 +260,search,5022.22,0.86179,0.141523,8.817,0.730189 +261,insert,3.396,-1.0,-1.0,0.0,0.730437 +262,search,5022.49,0.86256,0.140984,8.835,0.730437 +263,insert,259.267,-1.0,-1.0,0.0,0.772004 +264,search,5014.95,0.86646,0.140574,1166.41,0.772104 +265,insert,103.202,-1.0,-1.0,0.0,0.789935 +266,search,5025.99,0.86985,0.138825,825.798,0.790054 +267,insert,50.407,-1.0,-1.0,0.0,0.800599 +268,search,5014.8,0.8713,0.138488,847.96,0.799977 +269,insert,513.745,-1.0,-1.0,0.0,0.891504 +270,search,5130.13,0.87429,0.136771,1279.28,0.890334 +271,insert,5.331,-1.0,-1.0,0.0,0.891911 +272,search,5149.88,0.87361,0.137422,1258.84,0.891877 +273,insert,41.612,-1.0,-1.0,0.0,0.901871 +274,search,5045.29,0.87421,0.137165,989.221,0.901719 +275,insert,791.315,-1.0,-1.0,0.0,1.05598 +276,search,5346.1,0.87704,0.136278,2098.19,1.0565 +277,insert,57.582,-1.0,-1.0,0.0,1.0677 +278,search,5375,0.87769,0.135739,1580.51,1.06678 +279,insert,40.624,-1.0,-1.0,0.0,1.07585 +280,search,5480.81,0.8793,0.134535,10.506,1.07585 +281,insert,604.308,-1.0,-1.0,0.0,1.1981 +282,search,5611.5,0.88164,0.134186,1788.17,1.19842 +283,insert,784.395,-1.0,-1.0,0.0,1.37921 +284,search,5932.94,0.88467,0.131886,2576.28,1.37934 +285,insert,21.556,-1.0,-1.0,0.0,1.38514 +286,search,5797.82,0.88506,0.131404,1866.46,1.38421 +287,insert,62.823,-1.0,-1.0,0.0,1.39938 +288,search,5830.48,0.8851,0.131078,1763.53,1.39929 +289,insert,543.531,-1.0,-1.0,0.0,1.5316 +290,search,6166.93,0.89045,0.128085,2400.47,1.52969 +291,insert,38.436,-1.0,-1.0,0.0,1.54102 +292,search,6112.56,0.89099,0.128259,1700.03,1.53999 +293,insert,27.261,-1.0,-1.0,0.0,1.54861 +294,search,6208.77,0.89093,0.128322,1684.94,1.54823 +295,insert,353.553,-1.0,-1.0,0.0,1.63759 +296,search,6424.34,0.89386,0.12716,2325.26,1.63953 +297,insert,3.891,-1.0,-1.0,0.0,1.64104 +298,search,6415.45,0.89321,0.127759,1747.3,1.64031 +299,insert,135.65,-1.0,-1.0,0.0,1.66604 +300,search,6523.38,0.89705,0.123993,12.311,1.66604 +301,insert,1160.8,-1.0,-1.0,0.0,1.91598 +302,search,6960.7,0.91789,0.107698,4464.85,1.9183 +303,insert,85.993,-1.0,-1.0,0.0,1.94002 +304,search,7195.47,0.91638,0.109388,4328.16,1.93932 +305,insert,746.137,-1.0,-1.0,0.0,2.10153 +306,search,7351.41,0.91533,0.110426,3434.2,2.10152 +307,insert,48.995,-1.0,-1.0,0.0,2.11233 +308,search,7419.37,0.91623,0.109571,2555.2,2.1128 +309,insert,14.309,-1.0,-1.0,0.0,2.11684 +310,search,7051.92,0.91685,0.109342,2183.21,2.117 +311,insert,26.961,-1.0,-1.0,0.0,2.12568 +312,search,7564.24,0.91726,0.109026,13.673,2.12568 +313,insert,83.784,-1.0,-1.0,0.0,2.14206 +314,search,7592.21,0.91748,0.108923,2312.42,2.14163 +315,insert,14.04,-1.0,-1.0,0.0,2.14306 +316,search,7420.44,0.91743,0.108927,13.91,2.14306 +317,insert,122.815,-1.0,-1.0,0.0,2.1608 +318,search,7338.61,0.91784,0.108682,2384.86,2.16105 +319,insert,1146.96,-1.0,-1.0,0.0,2.38195 +320,search,7852.97,0.92089,0.106402,5372.35,2.37786 +321,insert,82.775,-1.0,-1.0,0.0,2.39468 +322,search,7618.29,0.92003,0.107538,2980.58,2.39472 +323,insert,166.946,-1.0,-1.0,0.0,2.44016 +324,search,7866.62,0.9208,0.107211,3002.53,2.4388 +325,insert,2226.89,-1.0,-1.0,0.0,2.65967 +326,search,8381.94,0.92228,0.106334,4897.01,2.66044 +327,insert,147.069,-1.0,-1.0,0.0,2.69139 +328,search,8357.83,0.92279,0.10566,3627.67,2.69166 +329,insert,15.328,-1.0,-1.0,0.0,2.69491 +330,search,8189.53,0.92329,0.105514,3530.85,2.69474 +331,insert,83.476,-1.0,-1.0,0.0,2.71384 +332,search,8352.53,0.92356,0.105284,2776.4,2.71408 +333,insert,3.494,-1.0,-1.0,0.0,2.71484 +334,search,8473.44,0.92347,0.105287,15.048,2.71484 +335,insert,78.487,-1.0,-1.0,0.0,2.73121 +336,search,8363.5,0.92409,0.104486,2714.03,2.73168 +337,insert,37.908,-1.0,-1.0,0.0,2.73911 +338,search,8502.58,0.92431,0.103918,2439.03,2.73891 +339,insert,88.943,-1.0,-1.0,0.0,2.75685 +340,search,8585.06,0.92473,0.103492,2555.65,2.75659 +341,insert,12.339,-1.0,-1.0,0.0,2.76027 +342,search,8715.8,0.9248,0.103535,2655.13,2.7606 +343,insert,84.997,-1.0,-1.0,0.0,2.77526 +344,search,8682.78,0.92537,0.103092,2583.91,2.77513 +345,insert,90.266,-1.0,-1.0,0.0,2.79192 +346,search,8649.29,0.92583,0.102763,3132.62,2.7914 +347,insert,1041.98,-1.0,-1.0,0.0,2.99312 +348,search,9087.48,0.92839,0.100279,7424.27,2.99149 +349,insert,71.412,-1.0,-1.0,0.0,3.01042 +350,search,9040.91,0.92869,0.0997187,3883.62,3.01079 +351,insert,764.418,-1.0,-1.0,0.0,3.19679 +352,search,9336.98,0.9295,0.10007,6952.37,3.19772 +353,insert,124.962,-1.0,-1.0,0.0,3.21686 +354,search,9287.24,0.92861,0.101091,3964.58,3.21663 +355,insert,807.433,-1.0,-1.0,0.0,3.37221 +356,search,9718.97,0.93041,0.099033,7143.5,3.37682 +357,insert,43.448,-1.0,-1.0,0.0,3.38417 +358,search,9671.05,0.93058,0.0990375,4168.5,3.38394 +359,insert,24.307,-1.0,-1.0,0.0,3.39016 +360,search,9940.82,0.93098,0.0988698,3368.02,3.39082 +361,insert,123.511,-1.0,-1.0,0.0,3.42146 +362,search,10074.7,0.93159,0.0978674,3238.78,3.42064 +363,insert,42.904,-1.0,-1.0,0.0,3.42586 +364,search,9835.23,0.9316,0.0978978,18.044,3.42586 +365,insert,155.149,-1.0,-1.0,0.0,3.45207 +366,search,9866,0.93189,0.0976154,3439.17,3.45261 +367,insert,76.222,-1.0,-1.0,0.0,3.46529 +368,search,9807.51,0.9323,0.0973215,4079.88,3.46452 +369,insert,153.032,-1.0,-1.0,0.0,3.48997 +370,search,9899.71,0.93249,0.0971594,4308.65,3.49143 +371,insert,30.13,-1.0,-1.0,0.0,3.49764 +372,search,10031.6,0.93299,0.096737,3415.49,3.49774 +373,insert,125.685,-1.0,-1.0,0.0,3.51628 +374,search,9875.67,0.93317,0.0964727,4445.13,3.51512 +375,insert,80.979,-1.0,-1.0,0.0,3.52836 +376,search,9953.98,0.93327,0.0965464,3741.86,3.52838 +377,insert,142.22,-1.0,-1.0,0.0,3.55477 +378,search,10211.2,0.93369,0.0962969,4467.36,3.55376 +379,insert,15.817,-1.0,-1.0,0.0,3.55607 +380,search,10139.8,0.93377,0.0964232,3482.1,3.55603 +381,insert,51.693,-1.0,-1.0,0.0,3.56491 +382,search,10060.1,0.9338,0.0964065,18.252,3.56491 +383,insert,59.078,-1.0,-1.0,0.0,3.57517 +384,search,10100.9,0.93368,0.0964881,3571.42,3.57391 +385,delete,9.837,-1.0,-1.0,0.0,3.57373 +386,search,10174.2,0.93386,0.0962398,3481.62,3.57394 +387,delete,18.541,-1.0,-1.0,0.0,3.57256 +388,search,10109.2,0.93396,0.0961754,18.505,3.57256 +389,delete,22.434,-1.0,-1.0,0.0,3.57159 +390,search,10188.2,0.934,0.096091,18.557,3.57159 +391,delete,122.187,-1.0,-1.0,0.0,3.55045 +392,search,9910.3,0.93367,0.0963981,18.353,3.55045 +393,delete,40.525,-1.0,-1.0,0.0,3.54915 +394,search,10064.5,0.93354,0.0964366,18.3,3.54915 +395,delete,26.297,-1.0,-1.0,0.0,3.54175 +396,search,10008.6,0.93351,0.0964171,18.382,3.54175 +397,delete,142.452,-1.0,-1.0,0.0,3.50887 +398,search,10104.2,0.93343,0.096543,19.096,3.50887 +399,delete,12.871,-1.0,-1.0,0.0,3.5085 +400,search,10135.8,0.93342,0.0965799,18.827,3.5085 +401,delete,33.415,-1.0,-1.0,0.0,3.50574 +402,search,9902.35,0.93325,0.0966256,18.579,3.50574 +403,delete,397.753,-1.0,-1.0,0.0,3.42029 +404,search,9787.99,0.93327,0.0966603,18.901,3.42029 +405,delete,86.374,-1.0,-1.0,0.0,3.41322 +406,search,9751.06,0.93442,0.0959388,18.943,3.41322 +407,delete,123.419,-1.0,-1.0,0.0,3.38609 +408,search,9631.36,0.93481,0.0952276,18.8,3.38609 +409,delete,270.525,-1.0,-1.0,0.0,3.30027 +410,search,9552.1,0.93481,0.0951436,18.363,3.30027 +411,delete,299.539,-1.0,-1.0,0.0,3.22306 +412,search,9402.47,0.9338,0.0965309,19.356,3.22306 +413,delete,41.105,-1.0,-1.0,0.0,3.21762 +414,search,9534.32,0.93368,0.096633,18.954,3.21762 +415,delete,111.542,-1.0,-1.0,0.0,3.19706 +416,search,9296.31,0.9336,0.096645,18.822,3.19706 +417,delete,278.283,-1.0,-1.0,0.0,3.13278 +418,search,9512.22,0.93392,0.0961475,18.832,3.13278 +419,delete,32.752,-1.0,-1.0,0.0,3.13066 +420,search,9296.51,0.93364,0.09643,18.587,3.13066 +421,delete,36.27,-1.0,-1.0,0.0,3.12104 +422,search,9490.53,0.9337,0.09639,18.437,3.12104 +423,delete,220.637,-1.0,-1.0,0.0,3.05721 +424,search,9424.6,0.93372,0.0959603,18.54,3.05721 +425,delete,29.558,-1.0,-1.0,0.0,3.04986 +426,search,9091.03,0.93388,0.0959724,18.363,3.04986 +427,delete,64.523,-1.0,-1.0,0.0,3.03756 +428,search,9122.95,0.93323,0.0969718,19.462,3.03756 +429,delete,581.073,-1.0,-1.0,0.0,2.88377 +430,search,8819.64,0.92593,0.104044,18.871,2.88377 +431,delete,129.953,-1.0,-1.0,0.0,2.84768 +432,search,8753.34,0.92595,0.104119,18.59,2.84768 +433,delete,287.576,-1.0,-1.0,0.0,2.76654 +434,search,8709.19,0.92545,0.104192,18.71,2.76654 +435,delete,162.44,-1.0,-1.0,0.0,2.71817 +436,search,8868.72,0.92478,0.104982,18.953,2.71817 +437,delete,24.708,-1.0,-1.0,0.0,2.71203 +438,search,8703.93,0.92484,0.104918,18.596,2.71203 +439,delete,173.496,-1.0,-1.0,0.0,2.6552 +440,search,8629.91,0.92454,0.104826,18.538,2.6552 +441,delete,42.827,-1.0,-1.0,0.0,2.6445 +442,search,8472.11,0.92422,0.104982,18.502,2.6445 +443,delete,38.133,-1.0,-1.0,0.0,2.63085 +444,search,8474.06,0.92454,0.104807,19.531,2.63085 +445,delete,74.5,-1.0,-1.0,0.0,2.6134 +446,search,8685.8,0.92438,0.104822,18.806,2.6134 +447,delete,528.064,-1.0,-1.0,0.0,2.4595 +448,search,8040.53,0.92388,0.104566,18.899,2.4595 +449,delete,62.439,-1.0,-1.0,0.0,2.44375 +450,search,8147.22,0.92325,0.105012,18.609,2.44375 +451,delete,134.091,-1.0,-1.0,0.0,2.40159 +452,search,8464.67,0.92208,0.105963,18.878,2.40159 +453,delete,399.294,-1.0,-1.0,0.0,2.28838 +454,search,8264.59,0.92124,0.106366,18.77,2.28838 +455,delete,69.72,-1.0,-1.0,0.0,2.27165 +456,search,8186.68,0.92079,0.106412,18.567,2.27165 +457,delete,10.357,-1.0,-1.0,0.0,2.26856 +458,search,8198.72,0.92073,0.106463,18.69,2.26856 +459,delete,55.975,-1.0,-1.0,0.0,2.24889 +460,search,8199.36,0.92083,0.106467,18.334,2.24889 +461,delete,9.344,-1.0,-1.0,0.0,2.24647 +462,search,8185.23,0.92094,0.10631,19.383,2.24647 +463,delete,95.873,-1.0,-1.0,0.0,2.22179 +464,search,8299.45,0.92059,0.106786,19.17,2.22179 +465,delete,40.723,-1.0,-1.0,0.0,2.21214 +466,search,8195.89,0.92024,0.107127,19.292,2.21214 +467,delete,59.915,-1.0,-1.0,0.0,2.19875 +468,search,8221.2,0.9199,0.107524,18.705,2.19875 +469,delete,38.87,-1.0,-1.0,0.0,2.18744 +470,search,8100.32,0.91945,0.10783,18.975,2.18744 +471,delete,169.402,-1.0,-1.0,0.0,2.13073 +472,search,8083.44,0.91839,0.108645,18.618,2.13073 +473,delete,186.419,-1.0,-1.0,0.0,2.08024 +474,search,8111.31,0.91764,0.10939,18.788,2.08024 +475,delete,489.547,-1.0,-1.0,0.0,1.89124 +476,search,7701.34,0.91494,0.111263,18.467,1.89124 +477,delete,72.402,-1.0,-1.0,0.0,1.86868 +478,search,7845.18,0.91472,0.111308,18.486,1.86868 +479,delete,264.49,-1.0,-1.0,0.0,1.77566 +480,search,8013.58,0.91639,0.109358,19.229,1.77566 +481,delete,89.231,-1.0,-1.0,0.0,1.756 +482,search,7888.54,0.91597,0.109544,19.184,1.756 +483,delete,384.857,-1.0,-1.0,0.0,1.62161 +484,search,7711.13,0.91422,0.110846,18.875,1.62161 +485,delete,48.874,-1.0,-1.0,0.0,1.61231 +486,search,7736.65,0.91406,0.111218,18.508,1.61231 +487,delete,19.229,-1.0,-1.0,0.0,1.6077 +488,search,7767.84,0.91364,0.111336,19.181,1.6077 +489,delete,55.771,-1.0,-1.0,0.0,1.5901 +490,search,7761.1,0.9134,0.111384,19.055,1.5901 +491,delete,32.457,-1.0,-1.0,0.0,1.58259 +492,search,7699.92,0.91321,0.111353,18.608,1.58259 +493,delete,199.825,-1.0,-1.0,0.0,1.52016 +494,search,7737.03,0.91315,0.111238,18.465,1.52016 +495,delete,26.272,-1.0,-1.0,0.0,1.50998 +496,search,7646.78,0.91258,0.111729,18.46,1.50998 +497,delete,86.569,-1.0,-1.0,0.0,1.47853 +498,search,7694.04,0.91197,0.112167,18.423,1.47853 +499,delete,21.136,-1.0,-1.0,0.0,1.47278 +500,search,7722.97,0.91142,0.112783,19.157,1.47278 +501,delete,54.462,-1.0,-1.0,0.0,1.46045 +502,search,7589.77,0.9112,0.113236,18.966,1.46045 +503,delete,42.572,-1.0,-1.0,0.0,1.45221 +504,search,7740.52,0.91103,0.113445,19.086,1.45221 +505,delete,100.246,-1.0,-1.0,0.0,1.42046 +506,search,7680.75,0.91057,0.113633,18.687,1.42046 +507,delete,66.136,-1.0,-1.0,0.0,1.40249 +508,search,7648.9,0.9103,0.113649,18.644,1.40249 +509,delete,30.629,-1.0,-1.0,0.0,1.39219 +510,search,7665.6,0.91026,0.113626,18.577,1.39219 +511,delete,44.483,-1.0,-1.0,0.0,1.38136 +512,search,7670.25,0.9098,0.113854,18.623,1.38136 +513,insert,606.419,-1.0,-1.0,0.0,1.46906 +514,search,7469.68,0.90994,0.114228,1672.39,1.46854 +515,insert,9.926,-1.0,-1.0,0.0,1.46912 +516,search,7623.43,0.91002,0.114107,1457.58,1.46947 +517,insert,29.901,-1.0,-1.0,0.0,1.47395 +518,search,7594.4,0.9108,0.113431,1202.48,1.47333 +519,insert,156.446,-1.0,-1.0,0.0,1.4973 +520,search,7449.24,0.91159,0.113803,18.838,1.4973 +521,insert,36.478,-1.0,-1.0,0.0,1.50124 +522,search,7502.1,0.91173,0.11379,18.94,1.50124 +523,insert,86.419,-1.0,-1.0,0.0,1.5117 +524,search,7491.89,0.91149,0.114405,18.634,1.5117 +525,insert,87.142,-1.0,-1.0,0.0,1.52068 +526,search,7514.79,0.91181,0.114132,18.704,1.52068 +527,insert,1041.38,-1.0,-1.0,0.0,1.6795 +528,search,7663.87,0.91329,0.113722,2617.73,1.67656 +529,insert,529.129,-1.0,-1.0,0.0,1.76951 +530,search,8086.74,0.91832,0.110638,2417.77,1.77148 +531,insert,98.448,-1.0,-1.0,0.0,1.78419 +532,search,7888.23,0.91964,0.109622,2077.5,1.78343 +533,insert,30.908,-1.0,-1.0,0.0,1.78967 +534,search,8077.57,0.91995,0.10919,2127.7,1.79036 +535,insert,37.665,-1.0,-1.0,0.0,1.79605 +536,search,8106.08,0.92023,0.108881,1947.31,1.79579 +537,insert,16.351,-1.0,-1.0,0.0,1.79866 +538,search,8042.77,0.9201,0.108968,12.543,1.79866 +539,insert,69.071,-1.0,-1.0,0.0,1.8085 +540,search,7886.23,0.92029,0.108928,2068.88,1.80905 +541,insert,898.759,-1.0,-1.0,0.0,1.96806 +542,search,8475.73,0.92346,0.10609,3340.06,1.9679 +543,insert,69.665,-1.0,-1.0,0.0,1.98096 +544,search,8449.07,0.92369,0.106315,2021.76,1.98147 +545,insert,11.551,-1.0,-1.0,0.0,1.98324 +546,search,8411.9,0.92375,0.106178,12.603,1.98324 +547,insert,275.414,-1.0,-1.0,0.0,2.03775 +548,search,8491.34,0.92608,0.104222,2298.13,2.03785 +549,insert,575.872,-1.0,-1.0,0.0,2.13247 +550,search,8587.87,0.92413,0.106531,2660.57,2.13477 +551,insert,46.837,-1.0,-1.0,0.0,2.14489 +552,search,8598.71,0.92439,0.106099,2713.38,2.14476 +553,insert,29.178,-1.0,-1.0,0.0,2.15031 +554,search,8758.4,0.92534,0.105505,2682.65,2.15041 +555,insert,917.151,-1.0,-1.0,0.0,2.31594 +556,search,8980.65,0.93136,0.0986931,3009.83,2.31594 +557,insert,49.232,-1.0,-1.0,0.0,2.32667 +558,search,8932.33,0.93152,0.0985567,2277.57,2.32665 +559,insert,10.14,-1.0,-1.0,0.0,2.32892 +560,search,9144.37,0.93165,0.0983563,12.914,2.32892 +561,insert,7.646,-1.0,-1.0,0.0,2.32974 +562,search,9014.16,0.93164,0.0983779,12.536,2.32974 +563,insert,141.584,-1.0,-1.0,0.0,2.34584 +564,search,9159.04,0.9321,0.097889,2558.38,2.34623 +565,insert,546.319,-1.0,-1.0,0.0,2.42876 +566,search,9058.34,0.93181,0.0984864,3100.28,2.42946 +567,insert,33.436,-1.0,-1.0,0.0,2.43492 +568,search,9064.41,0.93181,0.0985574,2565.55,2.43484 +569,insert,34.155,-1.0,-1.0,0.0,2.44206 +570,search,8067.59,0.93196,0.0984996,1788.61,2.4419 +571,insert,24.772,-1.0,-1.0,0.0,2.44743 +572,search,9185.15,0.93164,0.0988141,2408.62,2.44722 +573,insert,135.294,-1.0,-1.0,0.0,2.47192 +574,search,8703.94,0.93271,0.0976571,12.839,2.47192 +575,insert,152.525,-1.0,-1.0,0.0,2.49139 +576,search,8568.19,0.9325,0.0979077,12.415,2.49139 +577,insert,95.869,-1.0,-1.0,0.0,2.50722 +578,search,9151.63,0.93289,0.0976847,2732.69,2.50691 +579,insert,1525.79,-1.0,-1.0,0.0,2.76571 +580,search,9741.21,0.9371,0.0939612,7412.18,2.76528 +581,insert,41.865,-1.0,-1.0,0.0,2.77226 +582,search,9734.44,0.93626,0.0953554,4427.44,2.77442 +583,insert,32.47,-1.0,-1.0,0.0,2.78131 +584,search,9752.42,0.93596,0.0956456,2968.42,2.78087 +585,insert,574.049,-1.0,-1.0,0.0,2.90131 +586,search,9971.74,0.93687,0.0946458,3278.01,2.90037 +587,insert,99.654,-1.0,-1.0,0.0,2.91372 +588,search,9940.95,0.93735,0.0943432,3502.11,2.91342 +589,insert,157.965,-1.0,-1.0,0.0,2.93531 +590,search,10031.3,0.93758,0.0940884,2943.7,2.93624 +591,insert,1128.71,-1.0,-1.0,0.0,3.14169 +592,search,10443.6,0.93983,0.0918912,6641.51,3.14491 +593,insert,340.693,-1.0,-1.0,0.0,3.22742 +594,search,10540.2,0.9396,0.0924035,5020.26,3.23087 +595,insert,12.502,-1.0,-1.0,0.0,3.23284 +596,search,10610.2,0.93979,0.0921867,3293.24,3.23036 +597,insert,541.161,-1.0,-1.0,0.0,3.33021 +598,search,10762,0.94105,0.0909527,4614.32,3.33044 +599,insert,215.304,-1.0,-1.0,0.0,3.37714 +600,search,10825.8,0.9417,0.0902752,4777.77,3.37657 +601,insert,111.947,-1.0,-1.0,0.0,3.40341 +602,search,10950.1,0.94217,0.0900294,3381.29,3.40189 +603,insert,13.102,-1.0,-1.0,0.0,3.40459 +604,search,10933.8,0.94228,0.0899401,3484.57,3.405 +605,insert,160.949,-1.0,-1.0,0.0,3.42483 +606,search,10979.3,0.94226,0.0900049,4028.65,3.42445 +607,insert,139.761,-1.0,-1.0,0.0,3.43876 +608,search,10928.6,0.94198,0.0904536,13.074,3.43876 +609,insert,517.408,-1.0,-1.0,0.0,3.5293 +610,search,10999.8,0.94234,0.0903041,4378.48,3.5307 +611,insert,43.353,-1.0,-1.0,0.0,3.54038 +612,search,10360.7,0.94297,0.0898629,2555.83,3.54067 +613,insert,440.276,-1.0,-1.0,0.0,3.62649 +614,search,10726.6,0.94332,0.0896098,3718.33,3.62575 +615,insert,729.793,-1.0,-1.0,0.0,3.78343 +616,search,11521.3,0.94409,0.0888817,8273.68,3.78143 +617,insert,725.668,-1.0,-1.0,0.0,3.92426 +618,search,11811,0.94501,0.0880444,5062.44,3.92492 +619,insert,449.278,-1.0,-1.0,0.0,4.03573 +620,search,11913.9,0.94528,0.088171,5877.11,4.03532 +621,insert,88.709,-1.0,-1.0,0.0,4.05046 +622,search,11928.3,0.94573,0.0876028,4757.1,4.05196 +623,insert,49.561,-1.0,-1.0,0.0,4.06222 +624,search,11826.5,0.94585,0.087622,3696.12,4.06263 +625,insert,184.936,-1.0,-1.0,0.0,4.09456 +626,search,12014.5,0.94575,0.0878827,4100.38,4.09495 +627,insert,122.69,-1.0,-1.0,0.0,4.11522 +628,search,10623.6,0.94628,0.0871616,3341.99,4.11648 +629,insert,24.294,-1.0,-1.0,0.0,4.12272 +630,search,11837.4,0.94645,0.0870205,2896.06,4.12184 +631,insert,96.006,-1.0,-1.0,0.0,4.13573 +632,search,11103.6,0.94657,0.0869753,3400.56,4.13638 +633,insert,122.806,-1.0,-1.0,0.0,4.15355 +634,search,11773,0.94687,0.0865742,3344.78,4.15559 +635,insert,46.435,-1.0,-1.0,0.0,4.16414 +636,search,11100.4,0.94685,0.0865742,16.477,4.16414 +637,insert,989.045,-1.0,-1.0,0.0,4.33947 +638,search,12395.5,0.94802,0.0847487,9483.3,4.34113 +639,insert,946.264,-1.0,-1.0,0.0,4.51501 +640,search,12781,0.9491,0.0836172,7876.76,4.51652 +641,delete,133.665,-1.0,-1.0,0.0,4.48952 +642,search,12061.5,0.94903,0.0836762,3839.6,4.48714 +643,delete,6.473,-1.0,-1.0,0.0,4.487 +644,search,11331.2,0.94935,0.0834897,3131.75,4.48708 +645,delete,9.697,-1.0,-1.0,0.0,4.48674 +646,search,12519.7,0.94934,0.0835006,13.295,4.48674 +647,delete,45.385,-1.0,-1.0,0.0,4.46796 +648,search,12087.6,0.94918,0.0834752,21.459,4.46796 +649,delete,81.786,-1.0,-1.0,0.0,4.46358 +650,search,12809.5,0.94919,0.0836432,21.043,4.46358 +651,delete,47.599,-1.0,-1.0,0.0,4.45937 +652,search,12613.4,0.9491,0.0836411,20.753,4.45937 +653,delete,183.824,-1.0,-1.0,0.0,4.42891 +654,search,12750.1,0.94894,0.0837811,20.255,4.42891 +655,delete,561.212,-1.0,-1.0,0.0,4.31865 +656,search,12465.1,0.94851,0.0832268,19.943,4.31865 +657,delete,326.615,-1.0,-1.0,0.0,4.23759 +658,search,12388.5,0.94646,0.0844983,19.821,4.23759 +659,delete,163.5,-1.0,-1.0,0.0,4.20045 +660,search,11957.1,0.94628,0.0845764,21.059,4.20045 +661,delete,111.485,-1.0,-1.0,0.0,4.1905 +662,search,12247,0.94609,0.0847802,20.463,4.1905 +663,delete,151.691,-1.0,-1.0,0.0,4.17113 +664,search,12220.6,0.94587,0.0850159,20.45,4.17113 +665,delete,99.059,-1.0,-1.0,0.0,4.15584 +666,search,12206.1,0.94583,0.0850366,20.142,4.15584 +667,delete,308.165,-1.0,-1.0,0.0,4.0896 +668,search,12231,0.94546,0.085491,19.947,4.0896 +669,delete,315.766,-1.0,-1.0,0.0,4.03 +670,search,11944.7,0.94517,0.0855174,19.783,4.03 +671,delete,52.335,-1.0,-1.0,0.0,4.02036 +672,search,11959.5,0.94496,0.0857042,21.119,4.02036 +673,delete,131.821,-1.0,-1.0,0.0,4.0012 +674,search,11932.6,0.94501,0.085673,20.561,4.0012 +675,delete,209.45,-1.0,-1.0,0.0,3.97016 +676,search,11908.2,0.94416,0.0866518,20.329,3.97016 +677,delete,301.152,-1.0,-1.0,0.0,3.88659 +678,search,11749.8,0.94472,0.0860051,20.263,3.88659 +679,delete,56.729,-1.0,-1.0,0.0,3.87584 +680,search,11737,0.94465,0.0860713,19.804,3.87584 +681,delete,20.461,-1.0,-1.0,0.0,3.87339 +682,search,11807.8,0.94464,0.0861835,19.93,3.87339 +683,delete,410.347,-1.0,-1.0,0.0,3.79015 +684,search,11573.5,0.94186,0.089433,20.714,3.79015 +685,delete,399.201,-1.0,-1.0,0.0,3.69625 +686,search,11349.6,0.93812,0.0931982,20.966,3.69625 +687,delete,44.049,-1.0,-1.0,0.0,3.68985 +688,search,11367,0.93807,0.0932882,20.391,3.68985 +689,delete,196.22,-1.0,-1.0,0.0,3.63962 +690,search,11355.4,0.93793,0.0932278,20.596,3.63962 +691,delete,90.646,-1.0,-1.0,0.0,3.62423 +692,search,11279.6,0.93749,0.0936147,20.04,3.62423 +693,delete,273.616,-1.0,-1.0,0.0,3.55997 +694,search,9800.17,0.93775,0.0935914,13.287,3.55997 +695,delete,20.401,-1.0,-1.0,0.0,3.54933 +696,search,10410.7,0.93786,0.0934303,15.775,3.54933 +697,delete,27.129,-1.0,-1.0,0.0,3.54065 +698,search,10172.7,0.93789,0.093436,20.851,3.54065 +699,delete,29.286,-1.0,-1.0,0.0,3.53419 +700,search,10903.5,0.93799,0.0933197,21.232,3.53419 +701,delete,124.8,-1.0,-1.0,0.0,3.51537 +702,search,10797.6,0.93771,0.0935422,20.373,3.51537 +703,delete,337.802,-1.0,-1.0,0.0,3.43972 +704,search,10576,0.93841,0.0928648,13.962,3.43972 +705,delete,43.118,-1.0,-1.0,0.0,3.42626 +706,search,9497.62,0.93803,0.0931741,13.811,3.42626 +707,delete,544.563,-1.0,-1.0,0.0,3.17575 +708,search,9750.32,0.93264,0.0990654,13.592,3.17575 +709,delete,143.313,-1.0,-1.0,0.0,3.09488 +710,search,10269.3,0.93141,0.0999181,20.164,3.09488 +711,delete,73.979,-1.0,-1.0,0.0,3.07488 +712,search,10620.8,0.93131,0.100214,19.98,3.07488 +713,delete,354.822,-1.0,-1.0,0.0,2.96643 +714,search,9442.79,0.93055,0.100926,14.346,2.96643 +715,delete,49.761,-1.0,-1.0,0.0,2.95109 +716,search,9836,0.93039,0.101083,14.346,2.95109 +717,delete,41.727,-1.0,-1.0,0.0,2.93654 +718,search,9316.86,0.93026,0.101185,13.852,2.93654 +719,delete,317.139,-1.0,-1.0,0.0,2.77923 +720,search,10235,0.92708,0.104737,14.53,2.77923 +721,delete,105.213,-1.0,-1.0,0.0,2.73318 +722,search,8939.64,0.92733,0.104416,19.818,2.73318 +723,delete,36.619,-1.0,-1.0,0.0,2.72293 +724,search,8926.69,0.92696,0.10484,13.621,2.72293 +725,delete,94.637,-1.0,-1.0,0.0,2.67626 +726,search,9935.44,0.92702,0.104875,13.403,2.67626 +727,delete,81.733,-1.0,-1.0,0.0,2.6275 +728,search,8544.32,0.9265,0.105254,14.371,2.6275 +729,delete,86.613,-1.0,-1.0,0.0,2.57527 +730,search,8836.84,0.92515,0.106486,14.237,2.57527 +731,delete,84.755,-1.0,-1.0,0.0,2.54735 +732,search,9300.29,0.92426,0.107475,20.795,2.54735 +733,delete,136.296,-1.0,-1.0,0.0,2.51602 +734,search,9674.46,0.92374,0.10772,20.723,2.51602 +735,delete,284.887,-1.0,-1.0,0.0,2.43589 +736,search,8936.2,0.92721,0.103164,15.277,2.43589 +737,delete,131.278,-1.0,-1.0,0.0,2.37699 +738,search,9350.6,0.9271,0.103136,13.345,2.37699 +739,delete,57.294,-1.0,-1.0,0.0,2.34728 +740,search,9863.04,0.92719,0.102904,13.55,2.34728 +741,delete,139.304,-1.0,-1.0,0.0,2.27506 +742,search,9850.31,0.92765,0.102621,20.457,2.27506 +743,delete,307.176,-1.0,-1.0,0.0,2.1823 +744,search,9493.86,0.92778,0.102272,13.177,2.1823 +745,delete,204.322,-1.0,-1.0,0.0,2.07413 +746,search,9683.31,0.92739,0.102535,21.283,2.07413 +747,delete,255.443,-1.0,-1.0,0.0,1.96997 +748,search,9901.76,0.9267,0.102416,14.564,1.96997 +749,delete,79.95,-1.0,-1.0,0.0,1.934 +750,search,10168.5,0.92619,0.102547,20.386,1.934 +751,delete,42.99,-1.0,-1.0,0.0,1.92225 +752,search,9871.71,0.92591,0.102781,20.198,1.92225 +753,delete,127.042,-1.0,-1.0,0.0,1.89104 +754,search,10085,0.9259,0.102737,20.464,1.89104 +755,delete,55.942,-1.0,-1.0,0.0,1.87483 +756,search,9783.78,0.92522,0.103377,20.086,1.87483 +757,delete,48.181,-1.0,-1.0,0.0,1.86127 +758,search,9927.9,0.92515,0.103486,20.089,1.86127 +759,delete,40.633,-1.0,-1.0,0.0,1.84845 +760,search,9183.86,0.92498,0.10368,20.053,1.84845 +761,delete,61.69,-1.0,-1.0,0.0,1.82818 +762,search,9912.19,0.9245,0.103975,21.203,1.82818 +763,delete,61.745,-1.0,-1.0,0.0,1.81926 +764,search,10010.3,0.92457,0.103889,20.438,1.81926 +765,delete,579.359,-1.0,-1.0,0.0,1.66301 +766,search,10101.7,0.92419,0.103928,20.235,1.66301 +767,delete,607.836,-1.0,-1.0,0.0,1.4741 +768,search,9377.71,0.92113,0.105288,20.827,1.4741 +769,insert,18.714,-1.0,-1.0,0.0,1.47506 +770,search,9910.57,0.9211,0.105184,20.206,1.47506 +771,insert,56.145,-1.0,-1.0,0.0,1.48227 +772,search,9454.47,0.92128,0.105154,20.365,1.48227 +773,insert,98.813,-1.0,-1.0,0.0,1.49283 +774,search,9839.8,0.92181,0.1049,20.089,1.49283 +775,insert,83.041,-1.0,-1.0,0.0,1.50213 +776,search,9327.65,0.92199,0.105095,1697.24,1.50195 +777,insert,63.219,-1.0,-1.0,0.0,1.50746 +778,search,9390.1,0.92218,0.104573,20.921,1.50746 +779,insert,48.379,-1.0,-1.0,0.0,1.51037 +780,search,9939.46,0.92238,0.104522,20.668,1.51037 +781,insert,16.792,-1.0,-1.0,0.0,1.5111 +782,search,9547.11,0.92236,0.104533,21.029,1.5111 +783,insert,124.802,-1.0,-1.0,0.0,1.52341 +784,search,9913.93,0.92291,0.104191,20.687,1.52341 +785,insert,109.617,-1.0,-1.0,0.0,1.53745 +786,search,9345.31,0.92419,0.103793,19.965,1.53745 +787,insert,34.438,-1.0,-1.0,0.0,1.54025 +788,search,9650.86,0.92437,0.10353,20.016,1.54025 +789,insert,11.404,-1.0,-1.0,0.0,1.54126 +790,search,9380.38,0.92443,0.103574,20.058,1.54126 +791,insert,59.626,-1.0,-1.0,0.0,1.5481 +792,search,9790.42,0.92497,0.103097,20.107,1.5481 +793,insert,2.595,-1.0,-1.0,0.0,1.54834 +794,search,9478.27,0.92495,0.103081,21.438,1.54834 +795,insert,173.76,-1.0,-1.0,0.0,1.5649 +796,search,9791.58,0.92552,0.102455,20.816,1.5649 +797,insert,9.45,-1.0,-1.0,0.0,1.56518 +798,search,9435.71,0.92561,0.1024,20.484,1.56518 +799,insert,10.09,-1.0,-1.0,0.0,1.5657 +800,search,9856.55,0.92564,0.102411,20.503,1.5657 +801,insert,38.605,-1.0,-1.0,0.0,1.56826 +802,search,9520.11,0.92581,0.102251,20.224,1.56826 +803,insert,2066.61,-1.0,-1.0,0.0,1.85996 +804,search,9819.41,0.93053,0.0985602,3693.18,1.86054 +805,insert,31.84,-1.0,-1.0,0.0,1.86579 +806,search,10000.5,0.93097,0.0984954,2753.69,1.86658 +807,insert,38.733,-1.0,-1.0,0.0,1.87177 +808,search,10146.2,0.93078,0.0987695,2147.63,1.87169 +809,insert,91.074,-1.0,-1.0,0.0,1.8841 +810,search,10178.2,0.93109,0.0985241,2096.44,1.88408 +811,insert,89.769,-1.0,-1.0,0.0,1.89535 +812,search,10065.1,0.93171,0.0977382,20.582,1.89535 +813,insert,142.866,-1.0,-1.0,0.0,1.91287 +814,search,10162.1,0.933,0.09656,20.513,1.91287 +815,insert,4.218,-1.0,-1.0,0.0,1.91338 +816,search,10032.4,0.93301,0.0965816,20.078,1.91338 +817,insert,243.129,-1.0,-1.0,0.0,1.94399 +818,search,10081.2,0.93316,0.0965896,2399.3,1.94306 +819,insert,47.365,-1.0,-1.0,0.0,1.94967 +820,search,10156.4,0.9337,0.0960053,20.628,1.94967 +821,insert,31.652,-1.0,-1.0,0.0,1.9538 +822,search,10334.5,0.9336,0.0961158,20.505,1.9538 +823,insert,104.64,-1.0,-1.0,0.0,1.96726 +824,search,10121.6,0.93377,0.0960281,20.555,1.96726 +825,insert,277.918,-1.0,-1.0,0.0,1.99787 +826,search,10348.6,0.93391,0.0958361,2544.09,1.99681 +827,insert,44.017,-1.0,-1.0,0.0,2.00347 +828,search,10148,0.93353,0.0961304,20.081,2.00347 +829,insert,1102.69,-1.0,-1.0,0.0,2.17002 +830,search,10351.4,0.93543,0.0937886,2833.2,2.16875 +831,insert,61.806,-1.0,-1.0,0.0,2.17934 +832,search,10593.9,0.93551,0.0942154,2375.53,2.17938 +833,insert,25.091,-1.0,-1.0,0.0,2.18336 +834,search,10421.2,0.93564,0.0941307,20.994,2.18336 +835,insert,171.632,-1.0,-1.0,0.0,2.20683 +836,search,10701.1,0.93631,0.0933472,20.488,2.20683 +837,insert,73.279,-1.0,-1.0,0.0,2.21652 +838,search,10521.5,0.93636,0.0932796,20.517,2.21652 +839,insert,228.299,-1.0,-1.0,0.0,2.24323 +840,search,10570.6,0.93703,0.0928895,2687.41,2.24332 +841,insert,110.814,-1.0,-1.0,0.0,2.25978 +842,search,10607.2,0.93717,0.092616,19.674,2.25978 +843,insert,1025.86,-1.0,-1.0,0.0,2.42052 +844,search,10981.9,0.9388,0.0907831,3179.49,2.42103 +845,insert,854.433,-1.0,-1.0,0.0,2.57111 +846,search,11016.8,0.93953,0.0905515,3596.34,2.57167 +847,insert,8.653,-1.0,-1.0,0.0,2.57232 +848,search,11179.7,0.93959,0.0905889,3406.43,2.57239 +849,insert,10.078,-1.0,-1.0,0.0,2.57415 +850,search,10994.9,0.93942,0.0908013,20.437,2.57415 +851,insert,31.947,-1.0,-1.0,0.0,2.57844 +852,search,10976.9,0.93942,0.0908453,20.389,2.57844 +853,insert,68.769,-1.0,-1.0,0.0,2.58789 +854,search,10950.8,0.93949,0.0908109,20.235,2.58789 +855,insert,18.889,-1.0,-1.0,0.0,2.59032 +856,search,11078,0.93953,0.090706,21.376,2.59032 +857,insert,62.061,-1.0,-1.0,0.0,2.59773 +858,search,11281.2,0.93971,0.0905357,2915.12,2.59751 +859,insert,119.684,-1.0,-1.0,0.0,2.61279 +860,search,11168.6,0.93984,0.0902744,20.687,2.61279 +861,insert,33.772,-1.0,-1.0,0.0,2.61558 +862,search,11214,0.93985,0.090195,20.626,2.61558 +863,insert,207.826,-1.0,-1.0,0.0,2.64567 +864,search,11084.1,0.93892,0.0915658,3281.35,2.64613 +865,insert,32.595,-1.0,-1.0,0.0,2.65181 +866,search,10991.2,0.93898,0.0915263,2837.59,2.65129 +867,insert,102.809,-1.0,-1.0,0.0,2.66844 +868,search,11082.9,0.93919,0.0913342,3156.36,2.66871 +869,insert,18.044,-1.0,-1.0,0.0,2.67104 +870,search,11177.5,0.93913,0.0912949,21.027,2.67104 +871,insert,110.664,-1.0,-1.0,0.0,2.68713 +872,search,11039.8,0.9391,0.0912988,3159.51,2.6875 +873,insert,112.825,-1.0,-1.0,0.0,2.70475 +874,search,11443,0.93919,0.0912576,3281.63,2.70396 +875,insert,55.843,-1.0,-1.0,0.0,2.71153 +876,search,11156.2,0.93917,0.0912327,20.289,2.71153 +877,insert,4.718,-1.0,-1.0,0.0,2.7124 +878,search,11176.3,0.93919,0.0912247,20.361,2.7124 +879,insert,674.385,-1.0,-1.0,0.0,2.83785 +880,search,11510.7,0.93966,0.09099,4459.48,2.83779 +881,insert,1464.45,-1.0,-1.0,0.0,3.06579 +882,search,11785,0.94123,0.0893865,6439.14,3.06579 +883,insert,1123.26,-1.0,-1.0,0.0,3.26232 +884,search,12142.1,0.94323,0.0879599,5916.77,3.26188 +885,insert,17.598,-1.0,-1.0,0.0,3.26586 +886,search,11957.7,0.94321,0.0882404,3837.97,3.26598 +887,insert,733.579,-1.0,-1.0,0.0,3.42247 +888,search,12308.6,0.94464,0.0874738,5621.16,3.422 +889,insert,1009.45,-1.0,-1.0,0.0,3.60575 +890,search,12703,0.94578,0.0865391,7548.34,3.60807 +891,insert,85.319,-1.0,-1.0,0.0,3.61957 +892,search,12855.5,0.9459,0.0862532,4354.38,3.61832 +893,insert,106.678,-1.0,-1.0,0.0,3.64619 +894,search,12755.2,0.94617,0.0858636,4237.99,3.64616 +895,insert,139.086,-1.0,-1.0,0.0,3.66895 +896,search,12895,0.94623,0.0858522,3907.81,3.66861 +897,delete,73.14,-1.0,-1.0,0.0,3.65386 +898,search,12791,0.9462,0.0858761,22.506,3.65386 +899,delete,27.02,-1.0,-1.0,0.0,3.65241 +900,search,12578,0.94622,0.0858374,22.526,3.65241 +901,delete,77.959,-1.0,-1.0,0.0,3.6465 +902,search,12756.5,0.94594,0.0862095,22.018,3.6465 +903,delete,70.406,-1.0,-1.0,0.0,3.6272 +904,search,12625.2,0.94549,0.0863827,22.917,3.6272 +905,delete,46.12,-1.0,-1.0,0.0,3.62462 +906,search,12584.1,0.9455,0.0864214,23.226,3.62462 +907,delete,57.406,-1.0,-1.0,0.0,3.62133 +908,search,12979.2,0.9454,0.0864007,23.15,3.62133 +909,delete,63.056,-1.0,-1.0,0.0,3.61818 +910,search,12480.6,0.94526,0.0864108,22.674,3.61818 +911,delete,124.857,-1.0,-1.0,0.0,3.60783 +912,search,12587.7,0.94495,0.086919,22.323,3.60783 +913,delete,50.255,-1.0,-1.0,0.0,3.59805 +914,search,12552.8,0.94499,0.0871997,22.061,3.59805 +915,delete,75.901,-1.0,-1.0,0.0,3.58357 +916,search,12633.2,0.94463,0.0875453,22.482,3.58357 +917,delete,17.566,-1.0,-1.0,0.0,3.58198 +918,search,12490.9,0.94467,0.087274,23.592,3.58198 +919,delete,63.852,-1.0,-1.0,0.0,3.57931 +920,search,12383.8,0.94466,0.0873742,23.031,3.57931 +921,delete,43.826,-1.0,-1.0,0.0,3.57491 +922,search,12381.4,0.94473,0.0872857,22.885,3.57491 +923,delete,109.17,-1.0,-1.0,0.0,3.56247 +924,search,12491.4,0.9445,0.0874321,22.484,3.56247 +925,delete,224.453,-1.0,-1.0,0.0,3.51015 +926,search,12592.2,0.94325,0.0888414,22.095,3.51015 +927,delete,25.336,-1.0,-1.0,0.0,3.50639 +928,search,12400.6,0.94306,0.0890213,22.646,3.50639 +929,delete,40.226,-1.0,-1.0,0.0,3.49994 +930,search,12513.5,0.94307,0.0890122,24.249,3.49994 +931,delete,724.863,-1.0,-1.0,0.0,3.37018 +932,search,11907.5,0.9414,0.0907115,22.705,3.37018 +933,delete,52.065,-1.0,-1.0,0.0,3.35814 +934,search,11825.4,0.94142,0.0906305,23.015,3.35814 +935,delete,44.775,-1.0,-1.0,0.0,3.35047 +936,search,11794,0.94141,0.0906065,21.907,3.35047 +937,delete,48.988,-1.0,-1.0,0.0,3.3394 +938,search,11517,0.94122,0.0908628,22.383,3.3394 +939,delete,211.334,-1.0,-1.0,0.0,3.30743 +940,search,11768.4,0.93993,0.0924315,22.649,3.30743 +941,delete,62.808,-1.0,-1.0,0.0,3.29344 +942,search,11790.7,0.93904,0.0932671,23.616,3.29344 +943,delete,12.581,-1.0,-1.0,0.0,3.29256 +944,search,11883.9,0.93897,0.0933302,23.044,3.29256 +945,delete,210.372,-1.0,-1.0,0.0,3.24109 +946,search,12051.8,0.93875,0.0934368,22.77,3.24109 +947,delete,52.558,-1.0,-1.0,0.0,3.23337 +948,search,11744.2,0.93836,0.0937092,22.906,3.23337 +949,delete,93.754,-1.0,-1.0,0.0,3.2136 +950,search,11695.6,0.93844,0.0938044,23.1,3.2136 +951,delete,53.623,-1.0,-1.0,0.0,3.19276 +952,search,11773.5,0.93833,0.0937667,22.159,3.19276 +953,delete,67.418,-1.0,-1.0,0.0,3.1791 +954,search,11767.3,0.93807,0.0940783,23.522,3.1791 +955,delete,40.679,-1.0,-1.0,0.0,3.17088 +956,search,11885.5,0.93842,0.0937677,26.798,3.17088 +957,delete,545.324,-1.0,-1.0,0.0,3.04551 +958,search,11551.5,0.9376,0.0946303,22.589,3.04551 +959,delete,96.787,-1.0,-1.0,0.0,3.02536 +960,search,11657.9,0.93722,0.0951841,22.53,3.02536 +961,delete,60.08,-1.0,-1.0,0.0,3.01517 +962,search,11697,0.93693,0.095406,22.312,3.01517 +963,delete,187.591,-1.0,-1.0,0.0,2.96868 +964,search,11476.8,0.93601,0.0962363,22.338,2.96868 +965,delete,96.005,-1.0,-1.0,0.0,2.93849 +966,search,11574.1,0.93572,0.0964939,24.392,2.93849 +967,delete,92.308,-1.0,-1.0,0.0,2.91801 +968,search,11534.9,0.93545,0.0967102,22.796,2.91801 +969,delete,121.226,-1.0,-1.0,0.0,2.88856 +970,search,11434.8,0.93523,0.0967639,22.803,2.88856 +971,delete,509.202,-1.0,-1.0,0.0,2.7672 +972,search,11301,0.93413,0.097536,22.693,2.7672 +973,delete,456.644,-1.0,-1.0,0.0,2.64443 +974,search,11126.1,0.93264,0.0996393,22.267,2.64443 +975,delete,223.373,-1.0,-1.0,0.0,2.5802 +976,search,10979.5,0.9301,0.10169,22.108,2.5802 +977,delete,97.631,-1.0,-1.0,0.0,2.54584 +978,search,10945.3,0.92993,0.101778,22.176,2.54584 +979,delete,21.081,-1.0,-1.0,0.0,2.53934 +980,search,11003.8,0.92983,0.101813,23.49,2.53934 +981,delete,220.891,-1.0,-1.0,0.0,2.48699 +982,search,11134.5,0.92923,0.102142,23.036,2.48699 +983,delete,80.775,-1.0,-1.0,0.0,2.47241 +984,search,10901.2,0.92899,0.10242,22.441,2.47241 +985,delete,82.049,-1.0,-1.0,0.0,2.45261 +986,search,10646.2,0.92851,0.10285,23.334,2.45261 +987,delete,103.729,-1.0,-1.0,0.0,2.43129 +988,search,10481.5,0.92812,0.103712,22.373,2.43129 +989,delete,28.82,-1.0,-1.0,0.0,2.42451 +990,search,11073.3,0.92799,0.103774,22.855,2.42451 +991,delete,112.849,-1.0,-1.0,0.0,2.39021 +992,search,10759.5,0.93008,0.10105,22.595,2.39021 +993,delete,149.641,-1.0,-1.0,0.0,2.34855 +994,search,10783.4,0.92991,0.101013,23.865,2.34855 +995,delete,163.514,-1.0,-1.0,0.0,2.31388 +996,search,10858.4,0.92924,0.10195,23.203,2.31388 +997,delete,66.565,-1.0,-1.0,0.0,2.30315 +998,search,11032.9,0.92916,0.101977,23.033,2.30315 +999,delete,214.043,-1.0,-1.0,0.0,2.24696 +1000,search,10655.2,0.92907,0.101788,22.787,2.24696 +1001,delete,224.534,-1.0,-1.0,0.0,2.1951 +1002,search,10190.4,0.92906,0.101759,15.351,2.1951 +1003,delete,48.697,-1.0,-1.0,0.0,2.17226 +1004,search,10917.9,0.92887,0.101921,22.58,2.17226 +1005,delete,30.945,-1.0,-1.0,0.0,2.16246 +1006,search,10572.9,0.92851,0.102245,22.461,2.16246 +1007,delete,276.454,-1.0,-1.0,0.0,2.07703 +1008,search,10393.5,0.92823,0.102227,23.271,2.07703 +1009,delete,568.339,-1.0,-1.0,0.0,1.92822 +1010,search,10027.6,0.92791,0.102236,23.186,1.92822 +1011,delete,684.891,-1.0,-1.0,0.0,1.74666 +1012,search,11111.4,0.92572,0.104457,23.011,1.74666 +1013,delete,22.364,-1.0,-1.0,0.0,1.74125 +1014,search,10798.1,0.92568,0.104534,22.552,1.74125 +1015,delete,468.331,-1.0,-1.0,0.0,1.60232 +1016,search,10307,0.92413,0.105038,14.857,1.60232 +1017,delete,292.475,-1.0,-1.0,0.0,1.445 +1018,search,10801.6,0.92424,0.104801,22.446,1.445 +1019,delete,32.295,-1.0,-1.0,0.0,1.43507 +1020,search,10987,0.92409,0.104878,22.57,1.43507 +1021,delete,200.335,-1.0,-1.0,0.0,1.37596 +1022,search,11026,0.92379,0.104947,23.711,1.37596 +1023,delete,200.849,-1.0,-1.0,0.0,1.33407 +1024,search,10267.7,0.92237,0.105907,23.145,1.33407 +1025,insert,85.641,-1.0,-1.0,0.0,1.34118 +1026,search,10658.7,0.92241,0.105962,22.978,1.34118 +1027,insert,503.002,-1.0,-1.0,0.0,1.3933 +1028,search,10230.2,0.92343,0.105728,1706.48,1.39281 +1029,insert,1039.21,-1.0,-1.0,0.0,1.52543 +1030,search,10529.8,0.9266,0.103746,2132.18,1.52562 +1031,insert,1589.92,-1.0,-1.0,0.0,1.775 +1032,search,10628.2,0.92841,0.103865,3446.6,1.77208 +1033,insert,1049.79,-1.0,-1.0,0.0,1.94074 +1034,search,10859.6,0.9306,0.102189,3545.68,1.94258 +1035,insert,632.119,-1.0,-1.0,0.0,2.04904 +1036,search,11245.5,0.93115,0.102103,3499.63,2.05049 +1037,insert,29.547,-1.0,-1.0,0.0,2.05364 +1038,search,11224.5,0.93075,0.102592,2254.2,2.05342 +1039,insert,171.083,-1.0,-1.0,0.0,2.07994 +1040,search,11009.8,0.93132,0.101962,2394.57,2.07948 +1041,insert,23.613,-1.0,-1.0,0.0,2.08296 +1042,search,11211,0.93142,0.101849,23.419,2.08296 +1043,insert,44.315,-1.0,-1.0,0.0,2.08955 +1044,search,10747.2,0.9316,0.101617,24.846,2.08955 +1045,insert,126.196,-1.0,-1.0,0.0,2.10402 +1046,search,11171.2,0.93217,0.10103,24.062,2.10402 +1047,insert,9.708,-1.0,-1.0,0.0,2.10496 +1048,search,11047.5,0.93221,0.101026,25.218,2.10496 +1049,insert,51.301,-1.0,-1.0,0.0,2.11091 +1050,search,11211.3,0.9321,0.101283,24.193,2.11091 +1051,insert,287.207,-1.0,-1.0,0.0,2.14832 +1052,search,11103,0.93242,0.10075,23.834,2.14832 +1053,insert,115.384,-1.0,-1.0,0.0,2.16468 +1054,search,11198.4,0.93276,0.10028,23.166,2.16468 +1055,insert,86.219,-1.0,-1.0,0.0,2.17834 +1056,search,11021.9,0.93309,0.100119,24.336,2.17834 +1057,insert,18.574,-1.0,-1.0,0.0,2.18037 +1058,search,11395.8,0.93308,0.100213,24.129,2.18037 +1059,insert,77.037,-1.0,-1.0,0.0,2.18645 +1060,search,11441.2,0.93334,0.100035,23.746,2.18645 +1061,insert,31.635,-1.0,-1.0,0.0,2.19008 +1062,search,11179.3,0.93324,0.100149,26.335,2.19008 +1063,insert,32.77,-1.0,-1.0,0.0,2.19361 +1064,search,11186.2,0.93314,0.100314,2802.58,2.19314 +1065,insert,803.164,-1.0,-1.0,0.0,2.31336 +1066,search,11578.8,0.93427,0.0991946,3318.46,2.3137 +1067,insert,13.328,-1.0,-1.0,0.0,2.3171 +1068,search,11318.1,0.93426,0.0990603,2503.94,2.31595 +1069,insert,84.039,-1.0,-1.0,0.0,2.32832 +1070,search,11370.8,0.93521,0.0977099,2440.07,2.3289 +1071,insert,62.896,-1.0,-1.0,0.0,2.33927 +1072,search,11441.2,0.9352,0.0978654,24.007,2.33927 +1073,insert,81.88,-1.0,-1.0,0.0,2.3487 +1074,search,11406.6,0.93524,0.0979667,23.731,2.3487 +1075,insert,29.977,-1.0,-1.0,0.0,2.35163 +1076,search,11394.9,0.93556,0.0975113,24.333,2.35163 +1077,insert,73.133,-1.0,-1.0,0.0,2.36166 +1078,search,11367.6,0.93535,0.0979435,23.597,2.36166 +1079,insert,53.91,-1.0,-1.0,0.0,2.36913 +1080,search,11444.4,0.93556,0.0976445,24.759,2.36913 +1081,insert,1074.45,-1.0,-1.0,0.0,2.50923 +1082,search,11457.4,0.93557,0.0982474,3076.81,2.50971 +1083,insert,3.903,-1.0,-1.0,0.0,2.51037 +1084,search,11737.7,0.93562,0.0982153,1683.93,2.50986 +1085,insert,70.002,-1.0,-1.0,0.0,2.51992 +1086,search,11745,0.93583,0.0980727,23.643,2.51992 +1087,insert,53.956,-1.0,-1.0,0.0,2.52598 +1088,search,11634.6,0.93585,0.0981136,23.624,2.52598 +1089,insert,1078.11,-1.0,-1.0,0.0,2.69203 +1090,search,11929,0.93776,0.0963279,3929.28,2.6923 +1091,insert,107.929,-1.0,-1.0,0.0,2.71349 +1092,search,12059.6,0.93855,0.0956363,3247.95,2.71375 +1093,insert,49.724,-1.0,-1.0,0.0,2.72085 +1094,search,12030.4,0.93859,0.0955644,2902.68,2.72033 +1095,insert,1112.55,-1.0,-1.0,0.0,2.88354 +1096,search,12321.6,0.9402,0.0941433,4904.11,2.88522 +1097,insert,48.363,-1.0,-1.0,0.0,2.89475 +1098,search,12479.5,0.94059,0.0940135,3176.52,2.89393 +1099,insert,23.424,-1.0,-1.0,0.0,2.89866 +1100,search,12635.9,0.9405,0.0941726,3042.82,2.89891 +1101,insert,113.03,-1.0,-1.0,0.0,2.91645 +1102,search,12562.1,0.94087,0.0937852,25.293,2.91645 +1103,insert,261.194,-1.0,-1.0,0.0,2.95628 +1104,search,12251.4,0.94257,0.0917806,3694.84,2.95602 +1105,insert,5.014,-1.0,-1.0,0.0,2.95682 +1106,search,12461.3,0.94279,0.0914158,24.404,2.95682 +1107,insert,599.639,-1.0,-1.0,0.0,3.05417 +1108,search,12368.8,0.94347,0.0904353,3954.2,3.05337 +1109,insert,14.675,-1.0,-1.0,0.0,3.05641 +1110,search,12327.7,0.94337,0.0906025,3374.02,3.05647 +1111,insert,122.996,-1.0,-1.0,0.0,3.07384 +1112,search,12435.3,0.94361,0.0903466,3651.05,3.07365 +1113,insert,176.768,-1.0,-1.0,0.0,3.098 +1114,search,12672.1,0.9439,0.0899554,3803.27,3.0976 +1115,insert,174.405,-1.0,-1.0,0.0,3.12309 +1116,search,12883.7,0.94453,0.0890904,24.432,3.12309 +1117,insert,35.816,-1.0,-1.0,0.0,3.12926 +1118,search,12521.5,0.94464,0.0888804,24.537,3.12926 +1119,insert,23.354,-1.0,-1.0,0.0,3.13339 +1120,search,12592,0.94475,0.0886946,26.172,3.13339 +1121,insert,79.876,-1.0,-1.0,0.0,3.14545 +1122,search,12727.2,0.94464,0.0889367,3742.9,3.1452 +1123,insert,59.258,-1.0,-1.0,0.0,3.15439 +1124,search,12752.6,0.94451,0.089301,25.418,3.15439 +1125,insert,32.67,-1.0,-1.0,0.0,3.15839 +1126,search,12763.2,0.94453,0.089281,3861.12,3.15885 +1127,insert,98.321,-1.0,-1.0,0.0,3.17502 +1128,search,12522.6,0.94447,0.0894965,24.488,3.17502 +1129,insert,39.447,-1.0,-1.0,0.0,3.18185 +1130,search,12705.4,0.94444,0.0895772,3500.85,3.18151 +1131,insert,116.574,-1.0,-1.0,0.0,3.1951 +1132,search,12802.4,0.94448,0.0893989,25.347,3.1951 +1133,insert,61.56,-1.0,-1.0,0.0,3.20091 +1134,search,12951.2,0.94445,0.0894529,25.215,3.20091 +1135,insert,28.393,-1.0,-1.0,0.0,3.20356 +1136,search,12742.9,0.94448,0.0893877,24.908,3.20356 +1137,insert,83.852,-1.0,-1.0,0.0,3.21235 +1138,search,12791.1,0.94444,0.0894094,24.729,3.21235 +1139,insert,6.562,-1.0,-1.0,0.0,3.21328 +1140,search,12587.4,0.94448,0.0893989,24.715,3.21328 +1141,insert,665.513,-1.0,-1.0,0.0,3.30944 +1142,search,12691.1,0.9447,0.0893043,4800.33,3.30872 +1143,insert,62.792,-1.0,-1.0,0.0,3.31725 +1144,search,13049.7,0.94466,0.0893208,3995.88,3.31735 +1145,insert,20.478,-1.0,-1.0,0.0,3.32176 +1146,search,10695.2,0.9449,0.0891558,2408.92,3.32264 +1147,insert,49.148,-1.0,-1.0,0.0,3.33275 +1148,search,12888.8,0.94489,0.0892655,25.008,3.33275 +1149,insert,14.385,-1.0,-1.0,0.0,3.33456 +1150,search,12911.6,0.9449,0.0892455,24.823,3.33456 +1151,insert,12.767,-1.0,-1.0,0.0,3.33669 +1152,search,12806.2,0.94491,0.0892601,26.449,3.33669 +1153,delete,56.175,-1.0,-1.0,0.0,3.33444 +1154,search,12714.6,0.94484,0.0894021,26.068,3.33444 +1155,delete,215.555,-1.0,-1.0,0.0,3.31012 +1156,search,12865.2,0.94445,0.0895979,25.992,3.31012 +1157,delete,407.24,-1.0,-1.0,0.0,3.24417 +1158,search,12891.6,0.94394,0.0901793,25.171,3.24417 +1159,delete,579.351,-1.0,-1.0,0.0,3.08195 +1160,search,12242.1,0.94346,0.0896556,24.771,3.08195 +1161,delete,350.144,-1.0,-1.0,0.0,2.99927 +1162,search,12195.4,0.94267,0.0899649,24.737,2.99927 +1163,delete,157.559,-1.0,-1.0,0.0,2.94686 +1164,search,12259.7,0.94262,0.0899356,26.665,2.94686 +1165,delete,79.921,-1.0,-1.0,0.0,2.94128 +1166,search,12333.4,0.9424,0.0900969,25.812,2.94128 +1167,delete,127.375,-1.0,-1.0,0.0,2.92531 +1168,search,12137.4,0.94205,0.0902859,25.447,2.92531 +1169,delete,43.005,-1.0,-1.0,0.0,2.91273 +1170,search,12358.4,0.94162,0.0904572,25.093,2.91273 +1171,delete,56.445,-1.0,-1.0,0.0,2.90197 +1172,search,12381.1,0.94145,0.0908488,24.942,2.90197 +1173,delete,56.882,-1.0,-1.0,0.0,2.89364 +1174,search,12170.8,0.94107,0.0914135,25.019,2.89364 +1175,delete,24.017,-1.0,-1.0,0.0,2.89006 +1176,search,11982.4,0.94081,0.0916731,26.677,2.89006 +1177,delete,33.123,-1.0,-1.0,0.0,2.88361 +1178,search,12119,0.94078,0.091706,26.022,2.88361 +1179,delete,116.65,-1.0,-1.0,0.0,2.86579 +1180,search,11976,0.94041,0.0920352,25.957,2.86579 +1181,delete,89.881,-1.0,-1.0,0.0,2.8524 +1182,search,11914.9,0.93984,0.0926575,25.187,2.8524 +1183,delete,73.489,-1.0,-1.0,0.0,2.83482 +1184,search,12102.3,0.9392,0.0932981,24.881,2.83482 +1185,delete,32.919,-1.0,-1.0,0.0,2.8279 +1186,search,11934.1,0.9391,0.0934209,24.7,2.8279 +1187,delete,196.126,-1.0,-1.0,0.0,2.7884 +1188,search,11731,0.93844,0.0939108,26.436,2.7884 +1189,delete,36.447,-1.0,-1.0,0.0,2.78282 +1190,search,11799.1,0.9384,0.0939366,25.998,2.78282 +1191,delete,27.037,-1.0,-1.0,0.0,2.77922 +1192,search,11819.3,0.93849,0.0939393,25.331,2.77922 +1193,delete,360.862,-1.0,-1.0,0.0,2.6865 +1194,search,11669.2,0.93854,0.0937826,25.114,2.6865 +1195,delete,43.601,-1.0,-1.0,0.0,2.68005 +1196,search,11692.4,0.93834,0.0939404,24.822,2.68005 +1197,delete,92.407,-1.0,-1.0,0.0,2.65755 +1198,search,11673,0.93726,0.0954506,24.901,2.65755 +1199,delete,18.254,-1.0,-1.0,0.0,2.65162 +1200,search,11711.7,0.93722,0.0954464,25.936,2.65162 +1201,delete,116.153,-1.0,-1.0,0.0,2.62378 +1202,search,11733.7,0.93692,0.0954684,25.799,2.62378 +1203,delete,61.731,-1.0,-1.0,0.0,2.6153 +1204,search,11909.2,0.93658,0.095761,25.872,2.6153 +1205,delete,46.47,-1.0,-1.0,0.0,2.60364 +1206,search,11914.3,0.93657,0.0956987,25.506,2.60364 +1207,delete,53.522,-1.0,-1.0,0.0,2.59517 +1208,search,11752.8,0.93632,0.0961171,25.29,2.59517 +1209,delete,421.044,-1.0,-1.0,0.0,2.48365 +1210,search,11557.8,0.93645,0.0959836,25.585,2.48365 +1211,delete,9.201,-1.0,-1.0,0.0,2.48123 +1212,search,11620,0.93638,0.096124,24.86,2.48123 +1213,delete,165.486,-1.0,-1.0,0.0,2.43512 +1214,search,11650.3,0.93583,0.0970165,26.395,2.43512 +1215,delete,48.201,-1.0,-1.0,0.0,2.42722 +1216,search,11736.3,0.93571,0.0970698,25.846,2.42722 +1217,delete,573.38,-1.0,-1.0,0.0,2.27596 +1218,search,11526.2,0.93372,0.0983995,25.704,2.27596 +1219,delete,168.957,-1.0,-1.0,0.0,2.23087 +1220,search,11540.9,0.9318,0.100043,25.329,2.23087 +1221,delete,61.17,-1.0,-1.0,0.0,2.21446 +1222,search,11554.6,0.93172,0.100313,25.252,2.21446 +1223,delete,345.553,-1.0,-1.0,0.0,2.11115 +1224,search,11584.3,0.93041,0.101151,24.958,2.11115 +1225,delete,54.708,-1.0,-1.0,0.0,2.0922 +1226,search,11552.4,0.92997,0.101481,27.014,2.0922 +1227,delete,153.984,-1.0,-1.0,0.0,2.05692 +1228,search,11277.9,0.92999,0.101195,25.846,2.05692 +1229,delete,181.601,-1.0,-1.0,0.0,2.01934 +1230,search,11020.3,0.92932,0.101863,26.114,2.01934 +1231,delete,131.621,-1.0,-1.0,0.0,1.98088 +1232,search,11000,0.92665,0.103937,25.831,1.98088 +1233,delete,35.55,-1.0,-1.0,0.0,1.97416 +1234,search,11264,0.92668,0.103882,25.304,1.97416 +1235,delete,255.213,-1.0,-1.0,0.0,1.90024 +1236,search,11307.8,0.92642,0.103978,24.959,1.90024 +1237,delete,24.611,-1.0,-1.0,0.0,1.89271 +1238,search,11414.7,0.92624,0.104009,25.532,1.89271 +1239,delete,86.599,-1.0,-1.0,0.0,1.86959 +1240,search,11525,0.92551,0.10459,26.448,1.86959 +1241,delete,100.431,-1.0,-1.0,0.0,1.84945 +1242,search,11162.2,0.9249,0.105235,26.223,1.84945 +1243,delete,103.553,-1.0,-1.0,0.0,1.82668 +1244,search,10695.9,0.92415,0.106189,25.484,1.82668 +1245,delete,36.071,-1.0,-1.0,0.0,1.81732 +1246,search,11234.7,0.92373,0.106643,25.81,1.81732 +1247,delete,104.959,-1.0,-1.0,0.0,1.78334 +1248,search,11296.9,0.92649,0.10287,25.242,1.78334 +1249,delete,64.177,-1.0,-1.0,0.0,1.76659 +1250,search,11299.8,0.92646,0.103012,25.063,1.76659 +1251,delete,53.82,-1.0,-1.0,0.0,1.751 +1252,search,11403.2,0.92612,0.103364,25.295,1.751 +1253,delete,23.088,-1.0,-1.0,0.0,1.74497 +1254,search,10732.6,0.92621,0.103341,26.578,1.74497 +1255,delete,217.329,-1.0,-1.0,0.0,1.69026 +1256,search,11197,0.92551,0.104101,25.943,1.69026 +1257,delete,73.87,-1.0,-1.0,0.0,1.67396 +1258,search,11244.1,0.92524,0.104361,25.69,1.67396 +1259,delete,106.66,-1.0,-1.0,0.0,1.64912 +1260,search,11419.3,0.92492,0.104796,25.408,1.64912 +1261,delete,48.538,-1.0,-1.0,0.0,1.63668 +1262,search,11466.6,0.92454,0.105141,25.627,1.63668 +1263,delete,168.893,-1.0,-1.0,0.0,1.58836 +1264,search,11578.5,0.92467,0.10493,25.42,1.58836 +1265,delete,403.826,-1.0,-1.0,0.0,1.46797 +1266,search,11650.7,0.92319,0.106073,25.677,1.46797 +1267,delete,153.056,-1.0,-1.0,0.0,1.43126 +1268,search,11592.5,0.92253,0.1069,26.013,1.43126 +1269,delete,288.938,-1.0,-1.0,0.0,1.3678 +1270,search,11606.8,0.92315,0.105998,26.373,1.3678 +1271,delete,163.603,-1.0,-1.0,0.0,1.32805 +1272,search,11624.7,0.92247,0.10658,25.906,1.32805 +1273,delete,226.867,-1.0,-1.0,0.0,1.27181 +1274,search,11597.1,0.92252,0.106076,25.305,1.27181 +1275,delete,42.498,-1.0,-1.0,0.0,1.26047 +1276,search,11582.1,0.92225,0.106155,25.012,1.26047 +1277,delete,55.772,-1.0,-1.0,0.0,1.24434 +1278,search,11197.7,0.92227,0.105984,25.108,1.24434 +1279,delete,48.211,-1.0,-1.0,0.0,1.23193 +1280,search,10915.2,0.92219,0.106108,26.295,1.23193 diff --git a/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.15_0.05.csv b/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.15_0.05.csv new file mode 100644 index 00000000..fd3b1527 --- /dev/null +++ b/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.15_0.05.csv @@ -0,0 +1,1280 @@ +step_num,step_type,latency_ms,recall_mean,recall_std_dev,mainteance_ms,index_mem_gb +2,search,2478.36,0.79265,0.157278,1.573,0.0183461 +3,insert,12.534,-1.0,-1.0,0.0,0.0223849 +4,search,1841.16,0.80591,0.154693,1.644,0.0223849 +5,insert,24.405,-1.0,-1.0,0.0,0.0328114 +6,search,1853.36,0.86827,0.143601,64.501,0.0328114 +7,insert,50.438,-1.0,-1.0,0.0,0.042328 +8,search,1854.38,0.85514,0.150788,62.558,0.0427421 +9,insert,3.552,-1.0,-1.0,0.0,0.0441925 +10,search,1872.83,0.86976,0.14109,201.125,0.0445361 +11,insert,11.731,-1.0,-1.0,0.0,0.0496132 +12,search,1892.94,0.87701,0.136764,128.288,0.0493651 +13,insert,27.074,-1.0,-1.0,0.0,0.060446 +14,search,1918.72,0.87481,0.138646,122.849,0.0600482 +15,insert,23.592,-1.0,-1.0,0.0,0.0693449 +16,search,1946.37,0.87969,0.134277,116.483,0.0690895 +17,insert,4.149,-1.0,-1.0,0.0,0.0711776 +18,search,1948.86,0.88182,0.134675,150.359,0.0710969 +19,insert,43.253,-1.0,-1.0,0.0,0.0780043 +20,search,2025.2,0.89383,0.125522,164.391,0.0779207 +21,insert,481.439,-1.0,-1.0,0.0,0.195993 +22,search,2391.5,0.90447,0.114981,532.143,0.197184 +23,insert,362.683,-1.0,-1.0,0.0,0.322902 +24,search,3057.96,0.90553,0.115544,1048.4,0.321499 +25,insert,49.14,-1.0,-1.0,0.0,0.341429 +26,search,2978.97,0.88326,0.128743,864.672,0.33958 +27,insert,32.645,-1.0,-1.0,0.0,0.352045 +28,search,2828.43,0.85572,0.143934,581.507,0.353742 +29,insert,73.045,-1.0,-1.0,0.0,0.380439 +30,search,2932.48,0.85548,0.145531,431.951,0.381391 +31,insert,409.685,-1.0,-1.0,0.0,0.542076 +32,search,3635.2,0.86522,0.142505,2156.88,0.542371 +33,insert,86.042,-1.0,-1.0,0.0,0.564849 +34,search,3380.54,0.84203,0.156818,1340.2,0.566884 +35,insert,51.7,-1.0,-1.0,0.0,0.582861 +36,search,3444.97,0.84006,0.158726,505.095,0.582021 +37,insert,59.788,-1.0,-1.0,0.0,0.603509 +38,search,3483.23,0.83988,0.159201,487.089,0.604192 +39,insert,7.6,-1.0,-1.0,0.0,0.606748 +40,search,3362.4,0.84252,0.156966,536.257,0.605784 +41,insert,48.764,-1.0,-1.0,0.0,0.620256 +42,search,3466.98,0.84319,0.156288,521.115,0.621045 +43,insert,10.116,-1.0,-1.0,0.0,0.624561 +44,search,3396.18,0.84228,0.156299,496.466,0.624738 +45,insert,301.695,-1.0,-1.0,0.0,0.638764 +46,search,3493.55,0.84579,0.154272,883.896,0.638924 +47,insert,339.656,-1.0,-1.0,0.0,0.740057 +48,search,3800.23,0.85236,0.152054,1720.09,0.739191 +49,insert,77.807,-1.0,-1.0,0.0,0.75536 +50,search,3697.67,0.84931,0.154299,1145.76,0.755521 +51,insert,374.126,-1.0,-1.0,0.0,0.890766 +52,search,4064.79,0.86407,0.143891,2663.65,0.890432 +53,insert,55.108,-1.0,-1.0,0.0,0.909918 +54,search,4124.36,0.85025,0.151859,1558.59,0.91115 +55,insert,361.036,-1.0,-1.0,0.0,1.05393 +56,search,4586.64,0.86635,0.144103,2958.37,1.05086 +57,insert,32.196,-1.0,-1.0,0.0,1.05961 +58,search,4354.18,0.86148,0.146311,1520.23,1.06001 +59,insert,285.429,-1.0,-1.0,0.0,1.15585 +60,search,4560.34,0.86215,0.145231,1891.05,1.15471 +61,insert,23.193,-1.0,-1.0,0.0,1.15945 +62,search,4489.36,0.85717,0.149653,1009.45,1.15956 +63,insert,3.645,-1.0,-1.0,0.0,1.16042 +64,search,4490.85,0.85732,0.149697,8.561,1.16042 +65,insert,147.489,-1.0,-1.0,0.0,1.19046 +66,search,4514.34,0.8605,0.148254,2089.42,1.18982 +67,insert,64.344,-1.0,-1.0,0.0,1.21097 +68,search,4585.89,0.86106,0.148292,1361.3,1.21082 +69,insert,77.203,-1.0,-1.0,0.0,1.23493 +70,search,4453.36,0.86193,0.147393,1136.63,1.23453 +71,insert,20.693,-1.0,-1.0,0.0,1.24011 +72,search,4665.79,0.86302,0.146872,1073.98,1.23994 +73,insert,8.357,-1.0,-1.0,0.0,1.24274 +74,search,4398.68,0.86269,0.147179,8.77,1.24274 +75,insert,27.044,-1.0,-1.0,0.0,1.24926 +76,search,4625.14,0.8631,0.146792,9.465,1.24926 +77,insert,85.246,-1.0,-1.0,0.0,1.26026 +78,search,4679.16,0.86282,0.1471,1148.24,1.26015 +79,insert,728.392,-1.0,-1.0,0.0,1.28933 +80,search,4729.39,0.86233,0.147337,1329.57,1.28987 +81,insert,52.829,-1.0,-1.0,0.0,1.30123 +82,search,4649.69,0.86303,0.146853,9.057,1.30123 +83,insert,26.88,-1.0,-1.0,0.0,1.30624 +84,search,4537.01,0.86282,0.147059,1141.43,1.30697 +85,insert,68.899,-1.0,-1.0,0.0,1.3248 +86,search,4767.23,0.86486,0.146225,1235.05,1.3253 +87,insert,792.027,-1.0,-1.0,0.0,1.51798 +88,search,5050.8,0.87695,0.134579,5408.71,1.51853 +89,insert,474.304,-1.0,-1.0,0.0,1.67437 +90,search,5735.9,0.87769,0.133345,6802.8,1.67697 +91,insert,49.091,-1.0,-1.0,0.0,1.69194 +92,search,5622.94,0.87292,0.137766,2119.28,1.69232 +93,insert,417.36,-1.0,-1.0,0.0,1.79528 +94,search,5541.67,0.87452,0.136528,2110.43,1.79606 +95,insert,20.649,-1.0,-1.0,0.0,1.80208 +96,search,5561.98,0.87461,0.136577,1563.52,1.80175 +97,insert,17.552,-1.0,-1.0,0.0,1.80725 +98,search,5513.68,0.87443,0.136729,5.09,1.80725 +99,insert,13.31,-1.0,-1.0,0.0,1.80993 +100,search,5719.86,0.87457,0.136614,4.988,1.80993 +101,insert,58.03,-1.0,-1.0,0.0,1.82143 +102,search,5569.1,0.87553,0.135739,1752.98,1.82252 +103,insert,26.114,-1.0,-1.0,0.0,1.82831 +104,search,5701.71,0.87576,0.135659,5.021,1.82831 +105,insert,14.803,-1.0,-1.0,0.0,1.83187 +106,search,5566.32,0.87537,0.135924,5.158,1.83187 +107,insert,30.411,-1.0,-1.0,0.0,1.83832 +108,search,5755.71,0.87544,0.135823,1577.6,1.8375 +109,insert,807.522,-1.0,-1.0,0.0,1.99301 +110,search,6002.68,0.87866,0.133779,4739.76,1.99591 +111,insert,41.069,-1.0,-1.0,0.0,2.01051 +112,search,5854.25,0.8776,0.134592,2301.17,2.00976 +113,insert,13.825,-1.0,-1.0,0.0,2.01363 +114,search,5880.59,0.87749,0.134656,1768.14,2.01361 +115,insert,43.545,-1.0,-1.0,0.0,2.0251 +116,search,5817.8,0.87814,0.134078,1978.89,2.02517 +117,insert,20.328,-1.0,-1.0,0.0,2.03094 +118,search,5801.19,0.87785,0.133866,5.54,2.03094 +119,insert,4.48,-1.0,-1.0,0.0,2.0321 +120,search,6083.57,0.87794,0.133861,5.483,2.0321 +121,insert,48.315,-1.0,-1.0,0.0,2.03746 +122,search,5840.58,0.87813,0.133744,1892.19,2.03721 +123,insert,602.549,-1.0,-1.0,0.0,2.16106 +124,search,6128.66,0.88084,0.132932,3866.97,2.15906 +125,insert,85.81,-1.0,-1.0,0.0,2.17875 +126,search,6286.2,0.8804,0.133098,2672.51,2.18027 +127,insert,82.464,-1.0,-1.0,0.0,2.20135 +128,search,6192.76,0.88153,0.132764,2885,2.20137 +129,delete,15.611,-1.0,-1.0,0.0,2.20052 +130,search,6082.36,0.88058,0.133406,1980.45,2.20037 +131,delete,2.824,-1.0,-1.0,0.0,2.20037 +132,search,6188.3,0.88083,0.133338,5.665,2.20037 +133,delete,10.391,-1.0,-1.0,0.0,2.19995 +134,search,6146.93,0.88096,0.133275,6.29,2.19995 +135,delete,32.089,-1.0,-1.0,0.0,2.19862 +136,search,6034,0.88397,0.129876,5.809,2.19862 +137,delete,4.787,-1.0,-1.0,0.0,2.19862 +138,search,6193.91,0.88394,0.129951,5.846,2.19862 +139,delete,13.456,-1.0,-1.0,0.0,2.19704 +140,search,5950.32,0.88361,0.130279,5.99,2.19704 +141,delete,25.381,-1.0,-1.0,0.0,2.19455 +142,search,6104.23,0.88446,0.12972,6.044,2.19455 +143,delete,21.115,-1.0,-1.0,0.0,2.19209 +144,search,5985.06,0.88467,0.129552,5.787,2.19209 +145,delete,3.305,-1.0,-1.0,0.0,2.19153 +146,search,5989.38,0.88427,0.129744,5.899,2.19153 +147,delete,13.181,-1.0,-1.0,0.0,2.19074 +148,search,5939.73,0.88441,0.129778,5.671,2.19074 +149,delete,211.311,-1.0,-1.0,0.0,2.15126 +150,search,5920.76,0.88901,0.126316,5.763,2.15126 +151,delete,185.58,-1.0,-1.0,0.0,2.11187 +152,search,5809.26,0.88897,0.126617,5.806,2.11187 +153,delete,42.572,-1.0,-1.0,0.0,2.09711 +154,search,5815.99,0.8886,0.127082,5.762,2.09711 +155,delete,20.702,-1.0,-1.0,0.0,2.09221 +156,search,5907.66,0.88857,0.127081,5.719,2.09221 +157,delete,48.034,-1.0,-1.0,0.0,2.08237 +158,search,5773.87,0.88769,0.127709,5.777,2.08237 +159,delete,321.389,-1.0,-1.0,0.0,1.96167 +160,search,5692.61,0.88667,0.128574,6.021,1.96167 +161,delete,46.095,-1.0,-1.0,0.0,1.95016 +162,search,5480.32,0.88681,0.128456,6.476,1.95016 +163,delete,43.223,-1.0,-1.0,0.0,1.94007 +164,search,5219.5,0.88618,0.128767,6.186,1.94007 +165,delete,47.051,-1.0,-1.0,0.0,1.92987 +166,search,5596.24,0.88636,0.128854,6.074,1.92987 +167,delete,11.975,-1.0,-1.0,0.0,1.92722 +168,search,5434.19,0.88573,0.129239,5.963,1.92722 +169,delete,28.41,-1.0,-1.0,0.0,1.91789 +170,search,5377.57,0.88545,0.129615,5.874,1.91789 +171,delete,16.186,-1.0,-1.0,0.0,1.91382 +172,search,5590.21,0.88514,0.129925,5.838,1.91382 +173,delete,51.633,-1.0,-1.0,0.0,1.90235 +174,search,5403.09,0.88394,0.13065,5.832,1.90235 +175,delete,207.19,-1.0,-1.0,0.0,1.83231 +176,search,5494.86,0.88398,0.130233,5.931,1.83231 +177,delete,22.514,-1.0,-1.0,0.0,1.82606 +178,search,5397.71,0.88288,0.130668,6.038,1.82606 +179,delete,267.643,-1.0,-1.0,0.0,1.72411 +180,search,5034.55,0.87965,0.131832,6.232,1.72411 +181,delete,31.629,-1.0,-1.0,0.0,1.71091 +182,search,5287.41,0.87934,0.132458,6.236,1.71091 +183,delete,188.799,-1.0,-1.0,0.0,1.64133 +184,search,5057.33,0.87455,0.134677,6.135,1.64133 +185,delete,11.897,-1.0,-1.0,0.0,1.63781 +186,search,4909.34,0.87414,0.134872,5.931,1.63781 +187,delete,224.575,-1.0,-1.0,0.0,1.54994 +188,search,5121.41,0.87738,0.132038,6.132,1.54994 +189,delete,10.57,-1.0,-1.0,0.0,1.54637 +190,search,4926.5,0.87733,0.131965,6.229,1.54637 +191,delete,3.941,-1.0,-1.0,0.0,1.54521 +192,search,4937.78,0.87736,0.131998,6.225,1.54521 +193,delete,66.946,-1.0,-1.0,0.0,1.51521 +194,search,5087.8,0.87423,0.134004,6.461,1.51521 +195,delete,50.011,-1.0,-1.0,0.0,1.50018 +196,search,5223.3,0.87238,0.13519,6.312,1.50018 +197,delete,49.944,-1.0,-1.0,0.0,1.48792 +198,search,5121.57,0.87239,0.135136,1424.57,1.48475 +199,delete,43.656,-1.0,-1.0,0.0,1.47944 +200,search,4955.57,0.87175,0.135413,6.151,1.47944 +201,delete,10.797,-1.0,-1.0,0.0,1.47612 +202,search,5098.1,0.8716,0.13554,6.353,1.47612 +203,delete,19.562,-1.0,-1.0,0.0,1.47069 +204,search,4951.74,0.87137,0.135821,6.105,1.47069 +205,delete,33.241,-1.0,-1.0,0.0,1.46155 +206,search,4784,0.87109,0.136011,6.108,1.46155 +207,delete,64.913,-1.0,-1.0,0.0,1.44045 +208,search,4880.87,0.87141,0.135728,5.94,1.44045 +209,delete,28.569,-1.0,-1.0,0.0,1.42993 +210,search,5134.09,0.87107,0.13558,6.117,1.42993 +211,delete,12.444,-1.0,-1.0,0.0,1.42611 +212,search,4973.64,0.87092,0.135626,6.587,1.42611 +213,delete,24.888,-1.0,-1.0,0.0,1.41721 +214,search,5039.05,0.87047,0.135796,5.966,1.41721 +215,delete,389.371,-1.0,-1.0,0.0,1.26704 +216,search,4841.32,0.86368,0.140725,6.365,1.26704 +217,delete,257.97,-1.0,-1.0,0.0,1.16702 +218,search,4738.05,0.85877,0.14386,6.371,1.16702 +219,delete,30.419,-1.0,-1.0,0.0,1.15345 +220,search,4662.81,0.85727,0.144926,6.266,1.15345 +221,delete,238.093,-1.0,-1.0,0.0,1.05006 +222,search,4498.32,0.85745,0.145373,6.249,1.05006 +223,delete,14.601,-1.0,-1.0,0.0,1.04442 +224,search,4581.92,0.85577,0.146588,6.183,1.04442 +225,delete,6.764,-1.0,-1.0,0.0,1.0422 +226,search,4518.76,0.8548,0.147296,6.411,1.0422 +227,delete,9.336,-1.0,-1.0,0.0,1.04058 +228,search,4556.44,0.85459,0.147346,6.296,1.04058 +229,delete,34.257,-1.0,-1.0,0.0,1.02885 +230,search,4448.45,0.85282,0.149097,6.183,1.02885 +231,delete,18.31,-1.0,-1.0,0.0,1.02245 +232,search,4309.72,0.85219,0.149564,6.169,1.02245 +233,delete,7.978,-1.0,-1.0,0.0,1.02059 +234,search,4479.33,0.85183,0.149804,6.158,1.02059 +235,delete,14.012,-1.0,-1.0,0.0,1.01663 +236,search,4415.61,0.85113,0.150262,6.184,1.01663 +237,delete,297.671,-1.0,-1.0,0.0,0.904098 +238,search,4326.41,0.84896,0.151575,6.152,0.904098 +239,delete,28.519,-1.0,-1.0,0.0,0.891171 +240,search,4326.78,0.84719,0.151772,6.126,0.891171 +241,delete,11.374,-1.0,-1.0,0.0,0.887242 +242,search,4331.92,0.84669,0.152021,6.232,0.887242 +243,delete,23.768,-1.0,-1.0,0.0,0.879869 +244,search,4295.36,0.84377,0.153611,6.321,0.879869 +245,delete,17.427,-1.0,-1.0,0.0,0.874374 +246,search,4287.64,0.84324,0.153727,6.073,0.874374 +247,delete,5.966,-1.0,-1.0,0.0,0.872423 +248,search,4268.57,0.84296,0.153881,6.23,0.872423 +249,delete,10.142,-1.0,-1.0,0.0,0.868603 +250,search,4052.89,0.84231,0.154146,6.184,0.868603 +251,delete,303.096,-1.0,-1.0,0.0,0.759665 +252,search,3814.35,0.84161,0.153805,6.073,0.759665 +253,delete,38.52,-1.0,-1.0,0.0,0.745505 +254,search,3918.58,0.83925,0.154876,5.932,0.745505 +255,delete,47.826,-1.0,-1.0,0.0,0.726537 +256,search,3922.35,0.83482,0.157373,5.956,0.726537 +257,insert,10.63,-1.0,-1.0,0.0,0.727565 +258,search,3900.57,0.83479,0.157399,6.198,0.727565 +259,insert,34.249,-1.0,-1.0,0.0,0.733859 +260,search,3902.62,0.83625,0.157024,6.04,0.733859 +261,insert,3.358,-1.0,-1.0,0.0,0.7343 +262,search,4065.98,0.8372,0.156322,6.15,0.7343 +263,insert,249.528,-1.0,-1.0,0.0,0.776752 +264,search,4118.63,0.8454,0.150513,1066.57,0.776424 +265,insert,99.827,-1.0,-1.0,0.0,0.793373 +266,search,4076.73,0.84708,0.149798,927.14,0.793225 +267,insert,57.458,-1.0,-1.0,0.0,0.804204 +268,search,3956.49,0.84978,0.14915,821.557,0.804047 +269,insert,514.397,-1.0,-1.0,0.0,0.893202 +270,search,4076.99,0.85261,0.148562,1600.83,0.890283 +271,insert,4.607,-1.0,-1.0,0.0,0.891292 +272,search,4211.53,0.8515,0.149382,1452.06,0.894095 +273,insert,33.554,-1.0,-1.0,0.0,0.901891 +274,search,4086.99,0.85238,0.148462,1454.45,0.901183 +275,insert,801.61,-1.0,-1.0,0.0,1.05381 +276,search,4460.4,0.85611,0.146582,1841.74,1.05301 +277,insert,57.89,-1.0,-1.0,0.0,1.06426 +278,search,4277.09,0.85599,0.146656,1150.59,1.06564 +279,insert,36.155,-1.0,-1.0,0.0,1.07496 +280,search,4436.94,0.85759,0.145204,1206.83,1.07339 +281,insert,593.381,-1.0,-1.0,0.0,1.2014 +282,search,4539.95,0.86017,0.14521,1695.77,1.19509 +283,insert,683.588,-1.0,-1.0,0.0,1.37559 +284,search,4571.61,0.86273,0.144432,2125.09,1.3758 +285,insert,16.862,-1.0,-1.0,0.0,1.38118 +286,search,4750.93,0.86337,0.143932,2099.53,1.38302 +287,insert,57.602,-1.0,-1.0,0.0,1.39911 +288,search,4858.86,0.86405,0.143433,1519.61,1.3994 +289,insert,552.833,-1.0,-1.0,0.0,1.52845 +290,search,4861.1,0.86965,0.141111,2086.18,1.52879 +291,insert,41.152,-1.0,-1.0,0.0,1.53873 +292,search,5020.96,0.87025,0.140568,1780.85,1.53922 +293,insert,29.486,-1.0,-1.0,0.0,1.54695 +294,search,5037.55,0.87003,0.140637,1606.44,1.54692 +295,insert,387.603,-1.0,-1.0,0.0,1.63458 +296,search,5024.42,0.87296,0.139928,1689.35,1.63495 +297,insert,5.037,-1.0,-1.0,0.0,1.63632 +298,search,5190.75,0.87203,0.140411,7.515,1.63632 +299,insert,115.888,-1.0,-1.0,0.0,1.66174 +300,search,4890.32,0.87539,0.137518,7.446,1.66174 +301,insert,1099.41,-1.0,-1.0,0.0,1.9191 +302,search,5778.8,0.89804,0.121196,4792.43,1.91738 +303,insert,78.374,-1.0,-1.0,0.0,1.93856 +304,search,5776.28,0.89763,0.121678,3831.84,1.93833 +305,insert,559.415,-1.0,-1.0,0.0,2.10275 +306,search,6061.46,0.89691,0.122395,2967.63,2.10265 +307,insert,51.057,-1.0,-1.0,0.0,2.11286 +308,search,5838.62,0.89785,0.121993,2310.45,2.11243 +309,insert,15.716,-1.0,-1.0,0.0,2.11586 +310,search,5781.07,0.89813,0.121778,2070.58,2.11404 +311,insert,31.893,-1.0,-1.0,0.0,2.1226 +312,search,5812.5,0.89835,0.121659,2024.76,2.12238 +313,insert,96.441,-1.0,-1.0,0.0,2.14197 +314,search,5803.18,0.89853,0.121699,2019.09,2.14153 +315,insert,11.166,-1.0,-1.0,0.0,2.14316 +316,search,5713.62,0.89838,0.121768,9.597,2.14316 +317,insert,118.329,-1.0,-1.0,0.0,2.16223 +318,search,6010.4,0.89799,0.122315,9.655,2.16223 +319,insert,1011.75,-1.0,-1.0,0.0,2.37749 +320,search,6227.76,0.90141,0.1194,5437.54,2.38127 +321,insert,69.056,-1.0,-1.0,0.0,2.39988 +322,search,6260.98,0.89998,0.121042,2532.12,2.39935 +323,insert,168.189,-1.0,-1.0,0.0,2.44672 +324,search,6189.55,0.9013,0.120014,2768.02,2.4458 +325,insert,2188.15,-1.0,-1.0,0.0,2.66086 +326,search,6612.59,0.90248,0.11945,4239.24,2.66078 +327,insert,122.826,-1.0,-1.0,0.0,2.69141 +328,search,6710.61,0.9031,0.118616,3655.9,2.68907 +329,insert,22.665,-1.0,-1.0,0.0,2.69317 +330,search,6492.93,0.90348,0.118322,2578.82,2.69359 +331,insert,90.729,-1.0,-1.0,0.0,2.71268 +332,search,6664.61,0.90391,0.11823,2588.78,2.71361 +333,insert,5.227,-1.0,-1.0,0.0,2.71509 +334,search,6502.69,0.90445,0.117725,2333.28,2.71457 +335,insert,70.948,-1.0,-1.0,0.0,2.73203 +336,search,6778.49,0.90494,0.117192,2426.23,2.73198 +337,insert,41.013,-1.0,-1.0,0.0,2.74068 +338,search,6783.22,0.9053,0.116648,2393.09,2.74095 +339,insert,102.653,-1.0,-1.0,0.0,2.75847 +340,search,6594.18,0.90573,0.116359,2464.66,2.75952 +341,insert,17.651,-1.0,-1.0,0.0,2.76236 +342,search,6631.75,0.90541,0.116496,10.641,2.76236 +343,insert,79.342,-1.0,-1.0,0.0,2.77735 +344,search,6604.18,0.90578,0.116182,10.591,2.77735 +345,insert,103.404,-1.0,-1.0,0.0,2.79561 +346,search,6565.74,0.90632,0.115658,2508.59,2.79623 +347,insert,936.765,-1.0,-1.0,0.0,2.99042 +348,search,6960.63,0.90959,0.112568,8905.32,2.99036 +349,insert,70.745,-1.0,-1.0,0.0,3.01012 +350,search,7176.34,0.90941,0.112954,3603.63,3.00827 +351,insert,703.683,-1.0,-1.0,0.0,3.18858 +352,search,7293.73,0.90999,0.112715,5368.6,3.18805 +353,insert,121.815,-1.0,-1.0,0.0,3.20888 +354,search,7186.93,0.90767,0.114843,3504.05,3.21207 +355,insert,731.807,-1.0,-1.0,0.0,3.37289 +356,search,7371.98,0.90964,0.113621,5172.55,3.37221 +357,insert,38.819,-1.0,-1.0,0.0,3.37938 +358,search,7407.14,0.90948,0.113754,3304.22,3.37986 +359,insert,21.129,-1.0,-1.0,0.0,3.38425 +360,search,7305.46,0.90918,0.114063,11.087,3.38425 +361,insert,130.18,-1.0,-1.0,0.0,3.41329 +362,search,7081.85,0.91017,0.113252,3559.47,3.41311 +363,insert,31.731,-1.0,-1.0,0.0,3.41948 +364,search,7311.31,0.91013,0.113339,3301.06,3.4192 +365,insert,124.99,-1.0,-1.0,0.0,3.44465 +366,search,7602.32,0.91057,0.11274,3334.48,3.44562 +367,insert,60.259,-1.0,-1.0,0.0,3.45981 +368,search,7453.81,0.91086,0.112748,3127.46,3.45949 +369,insert,159.569,-1.0,-1.0,0.0,3.49044 +370,search,7424.27,0.91141,0.11202,3308.41,3.49014 +371,insert,24.101,-1.0,-1.0,0.0,3.49414 +372,search,7484.45,0.91143,0.112002,3320.36,3.4941 +373,insert,115.591,-1.0,-1.0,0.0,3.51237 +374,search,7547.67,0.91178,0.111454,3883.23,3.5131 +375,insert,70.585,-1.0,-1.0,0.0,3.52665 +376,search,7699.95,0.91166,0.111606,3309.3,3.52717 +377,insert,110.206,-1.0,-1.0,0.0,3.55181 +378,search,7707.21,0.91193,0.111842,4026.41,3.5521 +379,insert,12.54,-1.0,-1.0,0.0,3.55435 +380,search,7505.7,0.9118,0.11202,3269.23,3.55385 +381,insert,40.752,-1.0,-1.0,0.0,3.56187 +382,search,7502.26,0.91192,0.111874,11.409,3.56187 +383,insert,64.08,-1.0,-1.0,0.0,3.57171 +384,search,7497.77,0.9119,0.111979,3355.08,3.57211 +385,delete,9.179,-1.0,-1.0,0.0,3.57196 +386,search,7533.67,0.91185,0.112102,11.152,3.57196 +387,delete,21.734,-1.0,-1.0,0.0,3.57094 +388,search,7541.08,0.91201,0.111993,11.156,3.57094 +389,delete,18.691,-1.0,-1.0,0.0,3.56969 +390,search,7404.64,0.91157,0.112362,11.208,3.56969 +391,delete,98.044,-1.0,-1.0,0.0,3.54853 +392,search,7607.2,0.91148,0.112744,11.932,3.54853 +393,delete,59.058,-1.0,-1.0,0.0,3.54706 +394,search,7169.97,0.91133,0.112824,11.633,3.54706 +395,delete,33.747,-1.0,-1.0,0.0,3.53993 +396,search,7152.63,0.91125,0.112833,11.695,3.53993 +397,delete,163.238,-1.0,-1.0,0.0,3.50846 +398,search,7473.83,0.9109,0.113162,11.495,3.50846 +399,delete,8.314,-1.0,-1.0,0.0,3.50799 +400,search,7508.49,0.91088,0.113187,11.934,3.50799 +401,delete,24.518,-1.0,-1.0,0.0,3.50527 +402,search,7499.29,0.91067,0.113519,11.532,3.50527 +403,delete,358.375,-1.0,-1.0,0.0,3.42014 +404,search,7377.91,0.91058,0.112975,11.435,3.42014 +405,delete,71.045,-1.0,-1.0,0.0,3.41151 +406,search,7285.21,0.91202,0.112409,11.447,3.41151 +407,delete,125.299,-1.0,-1.0,0.0,3.38258 +408,search,7350.46,0.91245,0.111952,11.37,3.38258 +409,delete,251.026,-1.0,-1.0,0.0,3.29698 +410,search,7210.22,0.91224,0.112039,11.221,3.29698 +411,delete,283.096,-1.0,-1.0,0.0,3.22401 +412,search,6903.76,0.91102,0.113274,11.73,3.22401 +413,delete,33.28,-1.0,-1.0,0.0,3.21697 +414,search,6834.86,0.9109,0.113347,11.73,3.21697 +415,delete,102.637,-1.0,-1.0,0.0,3.19667 +416,search,6803.85,0.91072,0.113424,11.585,3.19667 +417,delete,251.516,-1.0,-1.0,0.0,3.13049 +418,search,6539.71,0.9107,0.113376,11.465,3.13049 +419,delete,32.951,-1.0,-1.0,0.0,3.12623 +420,search,6786.64,0.91031,0.113691,11.515,3.12623 +421,delete,32.175,-1.0,-1.0,0.0,3.116 +422,search,6887.87,0.91041,0.113577,11.477,3.116 +423,delete,201.995,-1.0,-1.0,0.0,3.05635 +424,search,6718.32,0.90985,0.113969,11.126,3.05635 +425,delete,23.994,-1.0,-1.0,0.0,3.05145 +426,search,6772.74,0.91019,0.113755,11.168,3.05145 +427,delete,62.614,-1.0,-1.0,0.0,3.04109 +428,search,6400.42,0.90947,0.114326,11.108,3.04109 +429,delete,558.157,-1.0,-1.0,0.0,2.88633 +430,search,5520.87,0.89995,0.12329,7.479,2.88633 +431,delete,53.899,-1.0,-1.0,0.0,2.84769 +432,search,6262.02,0.90008,0.123133,11.081,2.84769 +433,delete,230.931,-1.0,-1.0,0.0,2.77155 +434,search,5975.25,0.89983,0.123087,11.68,2.77155 +435,delete,151.502,-1.0,-1.0,0.0,2.72474 +436,search,6229.89,0.89889,0.124231,11.567,2.72474 +437,delete,21.18,-1.0,-1.0,0.0,2.7196 +438,search,6032.29,0.89845,0.124508,11.42,2.7196 +439,delete,169.906,-1.0,-1.0,0.0,2.66641 +440,search,6206,0.89797,0.124529,11.388,2.66641 +441,delete,49.703,-1.0,-1.0,0.0,2.65253 +442,search,5997.26,0.89785,0.124741,11.357,2.65253 +443,delete,44.388,-1.0,-1.0,0.0,2.63904 +444,search,6162.58,0.89761,0.124901,11.16,2.63904 +445,delete,53.999,-1.0,-1.0,0.0,2.62242 +446,search,5931.22,0.89757,0.124943,11.05,2.62242 +447,delete,468.763,-1.0,-1.0,0.0,2.46324 +448,search,5942.04,0.89747,0.124589,11.114,2.46324 +449,delete,45.661,-1.0,-1.0,0.0,2.45092 +450,search,5928.56,0.89633,0.125216,11.033,2.45092 +451,delete,118.521,-1.0,-1.0,0.0,2.40849 +452,search,5879.94,0.89476,0.126614,11.08,2.40849 +453,delete,368.603,-1.0,-1.0,0.0,2.2903 +454,search,5766.87,0.89381,0.126825,11.003,2.2903 +455,delete,45.083,-1.0,-1.0,0.0,2.27424 +456,search,5570.75,0.89301,0.127219,10.938,2.27424 +457,delete,8.377,-1.0,-1.0,0.0,2.27111 +458,search,5559.27,0.89238,0.127513,11.548,2.27111 +459,delete,67.453,-1.0,-1.0,0.0,2.2525 +460,search,5728.46,0.89234,0.12738,11.241,2.2525 +461,delete,12.261,-1.0,-1.0,0.0,2.25075 +462,search,5497.49,0.89233,0.127325,11.443,2.25075 +463,delete,93.478,-1.0,-1.0,0.0,2.2265 +464,search,5674.98,0.89164,0.12783,11.252,2.2265 +465,delete,39.379,-1.0,-1.0,0.0,2.21419 +466,search,5555.44,0.89083,0.128229,11.059,2.21419 +467,delete,44.995,-1.0,-1.0,0.0,2.20259 +468,search,5666.69,0.89038,0.12873,11.06,2.20259 +469,delete,30.135,-1.0,-1.0,0.0,2.19197 +470,search,5633.6,0.88928,0.129278,11.084,2.19197 +471,delete,173.173,-1.0,-1.0,0.0,2.13495 +472,search,5527.45,0.88853,0.130066,10.812,2.13495 +473,delete,157.439,-1.0,-1.0,0.0,2.083 +474,search,5513.45,0.88811,0.130488,10.951,2.083 +475,delete,486.715,-1.0,-1.0,0.0,1.89445 +476,search,5159.44,0.88494,0.132468,11.106,1.89445 +477,delete,70.517,-1.0,-1.0,0.0,1.87034 +478,search,5223.68,0.88425,0.132937,10.895,1.87034 +479,delete,252.924,-1.0,-1.0,0.0,1.77785 +480,search,5422.44,0.88593,0.13108,10.928,1.77785 +481,delete,65.339,-1.0,-1.0,0.0,1.75463 +482,search,5447.27,0.8853,0.131296,10.93,1.75463 +483,delete,329.813,-1.0,-1.0,0.0,1.625 +484,search,5278.61,0.88179,0.134075,11.253,1.625 +485,delete,42.313,-1.0,-1.0,0.0,1.61306 +486,search,5115.4,0.88156,0.134065,11.307,1.61306 +487,delete,20.76,-1.0,-1.0,0.0,1.60918 +488,search,5263.3,0.88113,0.134127,11.464,1.60918 +489,delete,59.88,-1.0,-1.0,0.0,1.59253 +490,search,5239.18,0.88027,0.134802,11.041,1.59253 +491,delete,27.561,-1.0,-1.0,0.0,1.58489 +492,search,5126.03,0.88012,0.134846,10.865,1.58489 +493,delete,188.058,-1.0,-1.0,0.0,1.52173 +494,search,5198.09,0.87971,0.135112,10.916,1.52173 +495,delete,31.484,-1.0,-1.0,0.0,1.50927 +496,search,5161.87,0.87844,0.13583,11.059,1.50927 +497,delete,86.138,-1.0,-1.0,0.0,1.47985 +498,search,5053.76,0.87731,0.136356,11.042,1.47985 +499,delete,24.964,-1.0,-1.0,0.0,1.47283 +500,search,5124.18,0.87681,0.136702,10.861,1.47283 +501,delete,38.414,-1.0,-1.0,0.0,1.45849 +502,search,5104.4,0.87587,0.137567,10.644,1.45849 +503,delete,25.81,-1.0,-1.0,0.0,1.45023 +504,search,4931.83,0.87591,0.137674,10.828,1.45023 +505,delete,85.753,-1.0,-1.0,0.0,1.41925 +506,search,4895.03,0.87517,0.137859,10.8,1.41925 +507,delete,50.484,-1.0,-1.0,0.0,1.40182 +508,search,5103.72,0.87497,0.137684,10.814,1.40182 +509,delete,26.673,-1.0,-1.0,0.0,1.39144 +510,search,5035.28,0.87433,0.13815,11.292,1.39144 +511,delete,48.287,-1.0,-1.0,0.0,1.3821 +512,search,5001.15,0.87361,0.138813,10.984,1.3821 +513,insert,550.844,-1.0,-1.0,0.0,1.469 +514,search,4970.43,0.87365,0.139377,11.196,1.469 +515,insert,10.574,-1.0,-1.0,0.0,1.46985 +516,search,4718.05,0.87329,0.139762,10.841,1.46985 +517,insert,38.752,-1.0,-1.0,0.0,1.4734 +518,search,4944.18,0.87447,0.139016,10.894,1.4734 +519,insert,172.481,-1.0,-1.0,0.0,1.49714 +520,search,4953.84,0.87584,0.138708,11.168,1.49714 +521,insert,25.967,-1.0,-1.0,0.0,1.49994 +522,search,4746.16,0.87537,0.139232,10.86,1.49994 +523,insert,75.319,-1.0,-1.0,0.0,1.51006 +524,search,4863.31,0.87546,0.13922,1653.15,1.50924 +525,insert,82.93,-1.0,-1.0,0.0,1.51822 +526,search,4688.25,0.87555,0.139243,10.975,1.51822 +527,insert,924.391,-1.0,-1.0,0.0,1.67234 +528,search,5064.02,0.87973,0.13713,2251.73,1.67247 +529,insert,513.679,-1.0,-1.0,0.0,1.76844 +530,search,5090.37,0.88615,0.134159,2668.67,1.76935 +531,insert,92.832,-1.0,-1.0,0.0,1.7825 +532,search,4993.24,0.88577,0.134676,2132.81,1.78165 +533,insert,25.034,-1.0,-1.0,0.0,1.78648 +534,search,5101.84,0.8864,0.134202,1793.69,1.7866 +535,insert,36.653,-1.0,-1.0,0.0,1.79229 +536,search,5256.83,0.88755,0.133159,1680.92,1.79189 +537,insert,12.704,-1.0,-1.0,0.0,1.79474 +538,search,5234.11,0.8876,0.133049,1702.3,1.79495 +539,insert,54.105,-1.0,-1.0,0.0,1.80496 +540,search,5210.01,0.88717,0.133382,1747.23,1.80506 +541,insert,807.721,-1.0,-1.0,0.0,1.96343 +542,search,5295.03,0.89095,0.13053,2491.73,1.96372 +543,insert,69.153,-1.0,-1.0,0.0,1.97743 +544,search,5242.39,0.89156,0.129811,2165.53,1.97625 +545,insert,10.18,-1.0,-1.0,0.0,1.9778 +546,search,5263.97,0.89121,0.130166,1810.8,1.97779 +547,insert,252.86,-1.0,-1.0,0.0,2.03051 +548,search,5198.2,0.89437,0.128148,2203.21,2.03049 +549,insert,514.123,-1.0,-1.0,0.0,2.13099 +550,search,5625.44,0.89184,0.129767,2632.66,2.12978 +551,insert,39.765,-1.0,-1.0,0.0,2.14031 +552,search,5630.17,0.89263,0.129071,2445.25,2.14044 +553,insert,17.588,-1.0,-1.0,0.0,2.14489 +554,search,5528.99,0.89243,0.129623,2235.13,2.14635 +555,insert,976.956,-1.0,-1.0,0.0,2.31797 +556,search,5756.25,0.89846,0.123712,2348.04,2.31776 +557,insert,52.245,-1.0,-1.0,0.0,2.32883 +558,search,5681.94,0.89875,0.12339,2175.08,2.32888 +559,insert,15.262,-1.0,-1.0,0.0,2.33169 +560,search,5689.1,0.89878,0.123375,11.303,2.33169 +561,insert,7.556,-1.0,-1.0,0.0,2.33253 +562,search,5887.35,0.89881,0.123364,11.164,2.33253 +563,insert,100.421,-1.0,-1.0,0.0,2.34852 +564,search,5651.61,0.89898,0.123284,10.961,2.34852 +565,insert,499.866,-1.0,-1.0,0.0,2.42994 +566,search,5614.79,0.89882,0.123784,2882.81,2.43048 +567,insert,22.466,-1.0,-1.0,0.0,2.43496 +568,search,5685.67,0.89884,0.12391,2497.65,2.43375 +569,insert,31.165,-1.0,-1.0,0.0,2.4413 +570,search,5719.84,0.89886,0.124073,11.597,2.4413 +571,insert,36.988,-1.0,-1.0,0.0,2.44673 +572,search,5962.47,0.89822,0.124756,11.266,2.44673 +573,insert,152.009,-1.0,-1.0,0.0,2.47152 +574,search,5974.85,0.89863,0.124411,11.231,2.47152 +575,insert,138.262,-1.0,-1.0,0.0,2.49136 +576,search,5754.43,0.89877,0.124438,11.184,2.49136 +577,insert,84.866,-1.0,-1.0,0.0,2.50686 +578,search,6027.73,0.89926,0.124211,2604.8,2.50725 +579,insert,1366.38,-1.0,-1.0,0.0,2.76007 +580,search,6354.11,0.9044,0.119568,5269.21,2.76287 +581,insert,39.387,-1.0,-1.0,0.0,2.77052 +582,search,6381.21,0.90444,0.119882,2771.86,2.77022 +583,insert,37.341,-1.0,-1.0,0.0,2.77907 +584,search,6358.35,0.90444,0.119682,11.124,2.77907 +585,insert,484.959,-1.0,-1.0,0.0,2.89806 +586,search,6245.25,0.90557,0.119019,3033.45,2.89875 +587,insert,58.185,-1.0,-1.0,0.0,2.91176 +588,search,6459.08,0.90564,0.119153,2936.78,2.91091 +589,insert,119.834,-1.0,-1.0,0.0,2.93013 +590,search,6277.04,0.90563,0.118988,11.696,2.93013 +591,insert,1058.21,-1.0,-1.0,0.0,3.13943 +592,search,6523.66,0.90819,0.116968,5283.25,3.13808 +593,insert,402.238,-1.0,-1.0,0.0,3.2268 +594,search,6662.17,0.90778,0.117751,3805.95,3.22583 +595,insert,7.376,-1.0,-1.0,0.0,3.22743 +596,search,6666.03,0.90769,0.117973,3347.18,3.22708 +597,insert,492.459,-1.0,-1.0,0.0,3.331 +598,search,6722.31,0.90869,0.117461,3684.26,3.32957 +599,insert,187.674,-1.0,-1.0,0.0,3.38614 +600,search,6767.3,0.90944,0.117083,4030.1,3.38361 +601,insert,102.521,-1.0,-1.0,0.0,3.40693 +602,search,6911.36,0.90968,0.116898,3344.42,3.40537 +603,insert,15.17,-1.0,-1.0,0.0,3.40791 +604,search,6765.48,0.90971,0.116784,12.423,3.40791 +605,insert,124.879,-1.0,-1.0,0.0,3.4262 +606,search,6810.94,0.90942,0.117134,11.974,3.4262 +607,insert,110.818,-1.0,-1.0,0.0,3.44181 +608,search,6764.51,0.90922,0.117431,12.305,3.44181 +609,insert,485.73,-1.0,-1.0,0.0,3.53301 +610,search,6844.09,0.90955,0.117511,4026.31,3.53305 +611,insert,60.348,-1.0,-1.0,0.0,3.54418 +612,search,6915.42,0.90963,0.117408,3596.67,3.54298 +613,insert,314.486,-1.0,-1.0,0.0,3.62683 +614,search,6928.42,0.91027,0.116786,4199.24,3.62699 +615,insert,651.142,-1.0,-1.0,0.0,3.79368 +616,search,7313,0.91158,0.115931,5466.07,3.79124 +617,insert,683.633,-1.0,-1.0,0.0,3.93388 +618,search,7243.53,0.9128,0.115124,7599.08,3.9323 +619,insert,534.1,-1.0,-1.0,0.0,4.04058 +620,search,7217.99,0.91289,0.115181,3565.28,4.04166 +621,insert,68.733,-1.0,-1.0,0.0,4.05881 +622,search,7318.37,0.91331,0.114983,12.233,4.05881 +623,insert,43.813,-1.0,-1.0,0.0,4.06868 +624,search,7368.86,0.91293,0.115343,12.066,4.06868 +625,insert,137.781,-1.0,-1.0,0.0,4.10167 +626,search,7369.02,0.91332,0.115004,3918.27,4.10273 +627,insert,90.246,-1.0,-1.0,0.0,4.12282 +628,search,7313.22,0.91374,0.11472,4059.91,4.12204 +629,insert,31.63,-1.0,-1.0,0.0,4.12834 +630,search,7363.74,0.9138,0.114582,3744.1,4.12938 +631,insert,91.514,-1.0,-1.0,0.0,4.14318 +632,search,7449.99,0.9139,0.114613,4187.73,4.14254 +633,insert,130.38,-1.0,-1.0,0.0,4.16204 +634,search,7313.98,0.91427,0.114115,4047.16,4.16146 +635,insert,69.295,-1.0,-1.0,0.0,4.17068 +636,search,7529.44,0.91397,0.114436,11.942,4.17068 +637,insert,900.742,-1.0,-1.0,0.0,4.34102 +638,search,7611.42,0.91559,0.113038,9246.49,4.34343 +639,insert,803.134,-1.0,-1.0,0.0,4.51737 +640,search,7710.3,0.91687,0.111696,10348.9,4.5175 +641,delete,177.283,-1.0,-1.0,0.0,4.49226 +642,search,7855.61,0.91652,0.112242,5676.94,4.4915 +643,delete,9.512,-1.0,-1.0,0.0,4.49112 +644,search,7689.23,0.91653,0.11211,4395.22,4.4907 +645,delete,12.116,-1.0,-1.0,0.0,4.49005 +646,search,7466.11,0.91613,0.112455,4217.52,4.48821 +647,delete,55.557,-1.0,-1.0,0.0,4.47236 +648,search,7532.85,0.91569,0.112865,12.93,4.47236 +649,delete,40.445,-1.0,-1.0,0.0,4.46946 +650,search,7558.39,0.91582,0.112905,12.91,4.46946 +651,delete,29.949,-1.0,-1.0,0.0,4.46569 +652,search,7636.57,0.91565,0.112897,13.878,4.46569 +653,delete,121.082,-1.0,-1.0,0.0,4.43522 +654,search,7728.73,0.91522,0.112876,13.888,4.43522 +655,delete,497.406,-1.0,-1.0,0.0,4.32935 +656,search,7567.26,0.91437,0.113381,13.465,4.32935 +657,delete,330.176,-1.0,-1.0,0.0,4.255 +658,search,7357.88,0.91022,0.115948,13.273,4.255 +659,delete,175.483,-1.0,-1.0,0.0,4.21948 +660,search,7424.98,0.91019,0.115777,13.179,4.21948 +661,delete,71.56,-1.0,-1.0,0.0,4.2099 +662,search,7375.38,0.91025,0.115845,11.974,4.2099 +663,delete,72.618,-1.0,-1.0,0.0,4.19336 +664,search,7241.95,0.90965,0.116418,12.967,4.19336 +665,delete,68.501,-1.0,-1.0,0.0,4.17802 +666,search,7361.54,0.90965,0.11641,12.747,4.17802 +667,delete,266.569,-1.0,-1.0,0.0,4.11425 +668,search,7247.61,0.90938,0.116366,12.869,4.11425 +669,delete,279.686,-1.0,-1.0,0.0,4.04729 +670,search,7128.99,0.9085,0.116843,13.682,4.04729 +671,delete,84.994,-1.0,-1.0,0.0,4.03901 +672,search,7002.1,0.90829,0.117035,13.387,4.03901 +673,delete,113.585,-1.0,-1.0,0.0,4.02027 +674,search,7097.33,0.90844,0.116834,13.446,4.02027 +675,delete,187.768,-1.0,-1.0,0.0,3.99687 +676,search,6727.01,0.90689,0.117993,13.157,3.99687 +677,delete,275.589,-1.0,-1.0,0.0,3.91368 +678,search,6745.9,0.90811,0.116966,12.017,3.91368 +679,delete,39.869,-1.0,-1.0,0.0,3.9023 +680,search,6676.53,0.90767,0.116992,12.866,3.9023 +681,delete,15.422,-1.0,-1.0,0.0,3.90012 +682,search,6391.92,0.90767,0.117052,13.054,3.90012 +683,delete,410.335,-1.0,-1.0,0.0,3.81113 +684,search,6486.17,0.90443,0.121256,12.689,3.81113 +685,delete,348.497,-1.0,-1.0,0.0,3.71703 +686,search,6345.94,0.89898,0.12644,13.848,3.71703 +687,delete,35.713,-1.0,-1.0,0.0,3.71177 +688,search,6034.65,0.89904,0.126478,13.458,3.71177 +689,delete,139.213,-1.0,-1.0,0.0,3.66147 +690,search,6005.73,0.8988,0.126503,11.646,3.66147 +691,delete,61,-1.0,-1.0,0.0,3.64485 +692,search,5994.03,0.89779,0.127366,11.283,3.64485 +693,delete,160.802,-1.0,-1.0,0.0,3.57767 +694,search,5928.87,0.89808,0.127162,11.334,3.57767 +695,delete,31.465,-1.0,-1.0,0.0,3.56676 +696,search,6057.83,0.89807,0.127314,11.285,3.56676 +697,delete,39.682,-1.0,-1.0,0.0,3.55401 +698,search,5957.35,0.89768,0.127724,12.686,3.55401 +699,delete,17.58,-1.0,-1.0,0.0,3.5473 +700,search,6379.11,0.89783,0.127511,12.607,3.5473 +701,delete,87.365,-1.0,-1.0,0.0,3.52798 +702,search,6110.18,0.89786,0.127315,12.689,3.52798 +703,delete,282.833,-1.0,-1.0,0.0,3.45272 +704,search,6143.3,0.89852,0.126387,12.601,3.45272 +705,delete,53.765,-1.0,-1.0,0.0,3.43882 +706,search,6253.98,0.89798,0.126772,13.524,3.43882 +707,delete,801.142,-1.0,-1.0,0.0,3.18566 +708,search,5805.07,0.8899,0.133624,13.031,3.18566 +709,delete,286.458,-1.0,-1.0,0.0,3.10387 +710,search,5950.46,0.88804,0.13478,13.221,3.10387 +711,delete,102.251,-1.0,-1.0,0.0,3.08141 +712,search,5644.02,0.88799,0.134978,12.918,3.08141 +713,delete,341.357,-1.0,-1.0,0.0,2.97453 +714,search,5825.99,0.88624,0.135836,15.509,2.97453 +715,delete,54.029,-1.0,-1.0,0.0,2.96095 +716,search,5567.69,0.88588,0.135893,12.614,2.96095 +717,delete,49.91,-1.0,-1.0,0.0,2.94929 +718,search,5809.84,0.88543,0.136285,12.635,2.94929 +719,delete,539.434,-1.0,-1.0,0.0,2.79039 +720,search,5374.68,0.88063,0.1416,12.553,2.79039 +721,delete,144.486,-1.0,-1.0,0.0,2.74261 +722,search,5579.21,0.88086,0.141401,12.607,2.74261 +723,delete,33.329,-1.0,-1.0,0.0,2.73255 +724,search,5406.81,0.88053,0.141406,12.537,2.73255 +725,delete,173.551,-1.0,-1.0,0.0,2.6806 +726,search,5500.03,0.87993,0.141509,12.485,2.6806 +727,delete,138.177,-1.0,-1.0,0.0,2.63424 +728,search,5448.55,0.87926,0.141842,13.307,2.63424 +729,delete,191.987,-1.0,-1.0,0.0,2.58508 +730,search,5399.36,0.87744,0.142715,12.887,2.58508 +731,delete,134.727,-1.0,-1.0,0.0,2.55171 +732,search,5396.81,0.8764,0.144012,12.82,2.55171 +733,delete,134.661,-1.0,-1.0,0.0,2.51523 +734,search,5192.72,0.87573,0.144294,12.543,2.51523 +735,delete,246.512,-1.0,-1.0,0.0,2.43798 +736,search,5274.53,0.88056,0.139043,13.034,2.43798 +737,delete,198.893,-1.0,-1.0,0.0,2.38472 +738,search,5293.73,0.88019,0.139207,12.658,2.38472 +739,delete,98.965,-1.0,-1.0,0.0,2.3557 +740,search,5294.44,0.88012,0.139088,12.534,2.3557 +741,delete,252.644,-1.0,-1.0,0.0,2.27662 +742,search,5454.36,0.87942,0.139461,12.395,2.27662 +743,delete,287.884,-1.0,-1.0,0.0,2.1817 +744,search,5250.82,0.87888,0.139431,12.366,2.1817 +745,delete,359.057,-1.0,-1.0,0.0,2.06655 +746,search,5256.36,0.87758,0.140345,12.332,2.06655 +747,delete,287.877,-1.0,-1.0,0.0,1.9647 +748,search,5247.35,0.87613,0.140669,12.345,1.9647 +749,delete,100.155,-1.0,-1.0,0.0,1.92874 +750,search,5016.19,0.87528,0.141165,13.078,1.92874 +751,delete,57.581,-1.0,-1.0,0.0,1.91626 +752,search,5102.81,0.87474,0.141216,12.928,1.91626 +753,delete,105.528,-1.0,-1.0,0.0,1.88665 +754,search,5244.79,0.87417,0.141297,12.608,1.88665 +755,delete,67.678,-1.0,-1.0,0.0,1.8708 +756,search,4995.93,0.87344,0.141984,12.158,1.8708 +757,delete,58.211,-1.0,-1.0,0.0,1.85706 +758,search,5181.87,0.8729,0.142188,12.119,1.85706 +759,delete,47.603,-1.0,-1.0,0.0,1.84432 +760,search,5171.65,0.8727,0.14225,12.313,1.84432 +761,delete,73.58,-1.0,-1.0,0.0,1.82521 +762,search,5007.22,0.87186,0.142639,12.407,1.82521 +763,delete,34.12,-1.0,-1.0,0.0,1.81629 +764,search,5116.44,0.87137,0.142805,12.367,1.81629 +765,delete,507.637,-1.0,-1.0,0.0,1.65949 +766,search,5051.17,0.86984,0.14348,12.158,1.65949 +767,delete,506.107,-1.0,-1.0,0.0,1.47454 +768,search,4919.41,0.86459,0.146133,7.993,1.47454 +769,insert,7.317,-1.0,-1.0,0.0,1.47518 +770,search,3853.14,0.8641,0.146356,8.035,1.47518 +771,insert,40.869,-1.0,-1.0,0.0,1.48031 +772,search,7737.46,0.86422,0.1464,17.543,1.48031 +773,insert,115.177,-1.0,-1.0,0.0,1.49027 +774,search,4734.72,0.8655,0.145446,1011.18,1.49058 +775,insert,62.863,-1.0,-1.0,0.0,1.4999 +776,search,4511.01,0.86512,0.146109,10.794,1.4999 +777,insert,46.22,-1.0,-1.0,0.0,1.50415 +778,search,4483.15,0.86596,0.144971,10.862,1.50415 +779,insert,25.008,-1.0,-1.0,0.0,1.50653 +780,search,4496.82,0.86624,0.144974,12.443,1.50653 +781,insert,12.768,-1.0,-1.0,0.0,1.50737 +782,search,4596.66,0.86589,0.14535,10.895,1.50737 +783,insert,103.64,-1.0,-1.0,0.0,1.51997 +784,search,4570.82,0.86666,0.144712,12.151,1.51997 +785,insert,98.292,-1.0,-1.0,0.0,1.53457 +786,search,4582.19,0.86936,0.143983,12.563,1.53457 +787,insert,46.972,-1.0,-1.0,0.0,1.53844 +788,search,4436.64,0.86882,0.144413,11.964,1.53844 +789,insert,10.271,-1.0,-1.0,0.0,1.53962 +790,search,4532.05,0.86891,0.144455,12.263,1.53962 +791,insert,56.065,-1.0,-1.0,0.0,1.54547 +792,search,4515.56,0.86907,0.144409,11.744,1.54547 +793,insert,3.247,-1.0,-1.0,0.0,1.54575 +794,search,4774.92,0.86906,0.144422,11.78,1.54575 +795,insert,124.219,-1.0,-1.0,0.0,1.56208 +796,search,4661.88,0.8697,0.143874,11.841,1.56208 +797,insert,5.75,-1.0,-1.0,0.0,1.56237 +798,search,4726.11,0.86928,0.144228,11.698,1.56237 +799,insert,7.213,-1.0,-1.0,0.0,1.56269 +800,search,4762.04,0.86933,0.144238,12.474,1.56269 +801,insert,36.198,-1.0,-1.0,0.0,1.56589 +802,search,4700.88,0.86934,0.144384,12.187,1.56589 +803,insert,2086.08,-1.0,-1.0,0.0,1.85626 +804,search,4893.93,0.87644,0.140297,2137.32,1.85954 +805,insert,29.767,-1.0,-1.0,0.0,1.86489 +806,search,4796.68,0.87676,0.139667,2044.66,1.86294 +807,insert,28.347,-1.0,-1.0,0.0,1.86827 +808,search,4829.87,0.8763,0.139742,10.453,1.86827 +809,insert,52.813,-1.0,-1.0,0.0,1.87851 +810,search,4684.62,0.87699,0.139333,12.125,1.87851 +811,insert,64.41,-1.0,-1.0,0.0,1.88905 +812,search,4980.87,0.87759,0.138851,11.999,1.88905 +813,insert,95.58,-1.0,-1.0,0.0,1.9071 +814,search,4981.14,0.87924,0.136944,10.531,1.9071 +815,insert,2.012,-1.0,-1.0,0.0,1.9076 +816,search,4719.81,0.87928,0.136923,10.654,1.9076 +817,insert,146.859,-1.0,-1.0,0.0,1.94059 +818,search,5016.45,0.87887,0.137395,11.834,1.94059 +819,insert,37.976,-1.0,-1.0,0.0,1.94673 +820,search,5042.95,0.87936,0.136751,12.395,1.94673 +821,insert,27.529,-1.0,-1.0,0.0,1.95041 +822,search,5039.18,0.8793,0.136733,12.916,1.95041 +823,insert,75.031,-1.0,-1.0,0.0,1.96298 +824,search,5015.98,0.87887,0.136702,12.371,1.96298 +825,insert,241.691,-1.0,-1.0,0.0,1.99253 +826,search,5031.16,0.87917,0.136564,12.268,1.99253 +827,insert,42.984,-1.0,-1.0,0.0,1.99896 +828,search,5050.2,0.87879,0.13657,12.23,1.99896 +829,insert,1126.19,-1.0,-1.0,0.0,2.16788 +830,search,5215.68,0.882,0.134552,2709.73,2.16781 +831,insert,73.74,-1.0,-1.0,0.0,2.17931 +832,search,5175.52,0.88216,0.134616,11.853,2.17931 +833,insert,18.667,-1.0,-1.0,0.0,2.18281 +834,search,5005.18,0.88229,0.134498,11.828,2.18281 +835,insert,138.155,-1.0,-1.0,0.0,2.20798 +836,search,5030.84,0.8829,0.134004,11.912,2.20798 +837,insert,45.138,-1.0,-1.0,0.0,2.21628 +838,search,5121.45,0.88305,0.134021,11.656,2.21628 +839,insert,160.068,-1.0,-1.0,0.0,2.24429 +840,search,5053.49,0.88414,0.133175,2077.42,2.24481 +841,insert,98.166,-1.0,-1.0,0.0,2.26104 +842,search,4985.46,0.88391,0.132993,8.659,2.26104 +843,insert,1009.86,-1.0,-1.0,0.0,2.42153 +844,search,5211.96,0.88643,0.131608,2844.65,2.42169 +845,insert,899.935,-1.0,-1.0,0.0,2.5745 +846,search,5341.47,0.88804,0.130712,2811.98,2.57394 +847,insert,4.581,-1.0,-1.0,0.0,2.57481 +848,search,4490.87,0.8878,0.130893,1681.78,2.57425 +849,insert,7.96,-1.0,-1.0,0.0,2.57893 +850,search,4458.84,0.88735,0.131249,7.961,2.57893 +851,insert,13.601,-1.0,-1.0,0.0,2.58263 +852,search,5285.59,0.88742,0.131269,11.834,2.58263 +853,insert,55.16,-1.0,-1.0,0.0,2.59048 +854,search,5399.2,0.88746,0.131271,11.867,2.59048 +855,insert,14.223,-1.0,-1.0,0.0,2.5929 +856,search,4878.39,0.88712,0.131528,10.948,2.5929 +857,insert,36.285,-1.0,-1.0,0.0,2.59988 +858,search,5279.62,0.88739,0.131472,12.577,2.59988 +859,insert,73.661,-1.0,-1.0,0.0,2.61329 +860,search,5308.67,0.8876,0.131392,12.591,2.61329 +861,insert,31.07,-1.0,-1.0,0.0,2.61677 +862,search,5265.05,0.88699,0.131793,9.054,2.61677 +863,insert,197.026,-1.0,-1.0,0.0,2.64645 +864,search,5425.94,0.88519,0.133514,12.371,2.64645 +865,insert,33.098,-1.0,-1.0,0.0,2.65107 +866,search,5210.81,0.88513,0.133582,12.384,2.65107 +867,insert,133.37,-1.0,-1.0,0.0,2.66938 +868,search,5195.67,0.88473,0.133805,11.174,2.66938 +869,insert,17.825,-1.0,-1.0,0.0,2.67232 +870,search,5262.91,0.8848,0.133755,11.975,2.67232 +871,insert,118.747,-1.0,-1.0,0.0,2.68899 +872,search,5164.23,0.88439,0.134013,11.504,2.68899 +873,insert,118.499,-1.0,-1.0,0.0,2.70755 +874,search,5380.57,0.88463,0.133954,12.089,2.70755 +875,insert,62.373,-1.0,-1.0,0.0,2.71399 +876,search,4747.5,0.88468,0.133961,7.897,2.71399 +877,insert,2.286,-1.0,-1.0,0.0,2.71499 +878,search,4424.94,0.88424,0.134353,8.04,2.71499 +879,insert,691.964,-1.0,-1.0,0.0,2.83636 +880,search,5473.75,0.88506,0.134079,3421.21,2.83566 +881,insert,1214.38,-1.0,-1.0,0.0,3.06275 +882,search,5675.83,0.88673,0.13301,4541.31,3.06151 +883,insert,1093.8,-1.0,-1.0,0.0,3.26334 +884,search,5849.48,0.88986,0.130746,4090.81,3.26281 +885,insert,25.147,-1.0,-1.0,0.0,3.26693 +886,search,5847.21,0.88991,0.130566,3388.24,3.26724 +887,insert,723.721,-1.0,-1.0,0.0,3.42099 +888,search,5875.58,0.89071,0.130779,4293.71,3.42124 +889,insert,722.376,-1.0,-1.0,0.0,3.60557 +890,search,6074.72,0.89243,0.13007,4877.87,3.60723 +891,insert,79.219,-1.0,-1.0,0.0,3.61987 +892,search,5913.9,0.8924,0.130168,3014.45,3.61916 +893,insert,131.396,-1.0,-1.0,0.0,3.64781 +894,search,5912.63,0.8927,0.130056,3538.32,3.64516 +895,insert,130.193,-1.0,-1.0,0.0,3.6675 +896,search,5943.87,0.89235,0.130308,9.403,3.6675 +897,delete,86.891,-1.0,-1.0,0.0,3.65521 +898,search,5937.36,0.89187,0.13054,8.829,3.65521 +899,delete,16.123,-1.0,-1.0,0.0,3.65498 +900,search,5873.52,0.89176,0.130647,8.754,3.65498 +901,delete,60.3,-1.0,-1.0,0.0,3.64741 +902,search,5839.46,0.89083,0.13119,8.753,3.64741 +903,delete,70.712,-1.0,-1.0,0.0,3.62754 +904,search,5779.23,0.88957,0.13132,8.638,3.62754 +905,delete,31.806,-1.0,-1.0,0.0,3.62418 +906,search,5634.8,0.88955,0.131258,10.431,3.62418 +907,delete,44.043,-1.0,-1.0,0.0,3.62065 +908,search,5817.26,0.88899,0.131522,9.36,3.62065 +909,delete,60.026,-1.0,-1.0,0.0,3.61659 +910,search,5684.07,0.88891,0.131766,8.313,3.61659 +911,delete,88.552,-1.0,-1.0,0.0,3.60887 +912,search,5854.99,0.88791,0.132469,9.166,3.60887 +913,delete,58.165,-1.0,-1.0,0.0,3.6 +914,search,5854.82,0.88842,0.132621,9.029,3.6 +915,delete,86.736,-1.0,-1.0,0.0,3.58595 +916,search,5841.65,0.88754,0.13338,8.928,3.58595 +917,delete,20.128,-1.0,-1.0,0.0,3.58574 +918,search,5750.84,0.88712,0.133625,5.751,3.58574 +919,delete,19.075,-1.0,-1.0,0.0,3.58368 +920,search,5615.77,0.88692,0.133694,8.637,3.58368 +921,delete,28.899,-1.0,-1.0,0.0,3.57837 +922,search,5554.98,0.88649,0.13402,8.922,3.57837 +923,delete,72.263,-1.0,-1.0,0.0,3.56558 +924,search,5556.02,0.88592,0.134411,8.447,3.56558 +925,delete,186.892,-1.0,-1.0,0.0,3.5162 +926,search,5574.52,0.88383,0.136458,8.548,3.5162 +927,delete,21.586,-1.0,-1.0,0.0,3.51463 +928,search,5421.46,0.88295,0.137095,8.21,3.51463 +929,delete,45.637,-1.0,-1.0,0.0,3.51001 +930,search,5632.87,0.88294,0.136991,9.38,3.51001 +931,delete,626.369,-1.0,-1.0,0.0,3.37267 +932,search,5262,0.88024,0.139908,6.419,3.37267 +933,delete,32.753,-1.0,-1.0,0.0,3.35932 +934,search,5261.25,0.87985,0.140319,9.002,3.35932 +935,delete,31.753,-1.0,-1.0,0.0,3.35205 +936,search,5302.32,0.87976,0.140327,8.953,3.35205 +937,delete,51.074,-1.0,-1.0,0.0,3.33867 +938,search,5218.61,0.87893,0.140567,5.848,3.33867 +939,delete,117.295,-1.0,-1.0,0.0,3.30522 +940,search,5070.9,0.87706,0.142577,8.852,3.30522 +941,delete,60.748,-1.0,-1.0,0.0,3.29361 +942,search,5206.34,0.87589,0.143312,8.685,3.29361 +943,delete,5.965,-1.0,-1.0,0.0,3.29276 +944,search,5089.78,0.87528,0.143644,8.911,3.29276 +945,delete,147.901,-1.0,-1.0,0.0,3.24265 +946,search,5073.63,0.87498,0.143788,8.754,3.24265 +947,delete,40.197,-1.0,-1.0,0.0,3.23709 +948,search,5135.96,0.87428,0.144476,8.825,3.23709 +949,delete,62.855,-1.0,-1.0,0.0,3.2194 +950,search,5005.22,0.87388,0.145077,9.451,3.2194 +951,delete,62.847,-1.0,-1.0,0.0,3.19959 +952,search,5045.04,0.87333,0.145234,9.064,3.19959 +953,delete,76.023,-1.0,-1.0,0.0,3.18954 +954,search,5010.29,0.87256,0.145546,9.795,3.18954 +955,delete,31.639,-1.0,-1.0,0.0,3.18065 +956,search,5080.68,0.87286,0.14535,9.53,3.18065 +957,delete,463.486,-1.0,-1.0,0.0,3.06202 +958,search,5028.17,0.8711,0.146812,9.32,3.06202 +959,delete,77.104,-1.0,-1.0,0.0,3.04476 +960,search,5017.82,0.86986,0.147618,9.076,3.04476 +961,delete,48.441,-1.0,-1.0,0.0,3.03563 +962,search,4927.94,0.86954,0.147887,6.084,3.03563 +963,delete,100.413,-1.0,-1.0,0.0,2.99043 +964,search,4047.98,0.8673,0.148951,5.504,2.99043 +965,delete,51.202,-1.0,-1.0,0.0,2.96299 +966,search,4047.5,0.86673,0.149177,5.397,2.96299 +967,delete,37.06,-1.0,-1.0,0.0,2.94278 +968,search,4020.02,0.86638,0.149376,5.483,2.94278 +969,delete,48.187,-1.0,-1.0,0.0,2.91184 +970,search,3979.33,0.86513,0.149958,5.448,2.91184 +971,delete,224.282,-1.0,-1.0,0.0,2.78632 +972,search,3896.36,0.86315,0.151453,5.555,2.78632 +973,delete,194.742,-1.0,-1.0,0.0,2.66581 +974,search,4672.31,0.86071,0.153874,7.428,2.66581 +975,delete,128.406,-1.0,-1.0,0.0,2.59885 +976,search,4445.22,0.85621,0.157798,7.669,2.59885 +977,delete,74.889,-1.0,-1.0,0.0,2.56284 +978,search,4440.25,0.85586,0.157831,10.214,2.56284 +979,delete,29.839,-1.0,-1.0,0.0,2.55741 +980,search,4432.47,0.85496,0.15842,9.554,2.55741 +981,delete,182.804,-1.0,-1.0,0.0,2.50316 +982,search,4552.03,0.85404,0.158745,9.578,2.50316 +983,delete,71.322,-1.0,-1.0,0.0,2.48808 +984,search,4427.2,0.8536,0.159241,9.359,2.48808 +985,delete,72.74,-1.0,-1.0,0.0,2.47091 +986,search,4510.24,0.85185,0.160648,9.164,2.47091 +987,delete,76.914,-1.0,-1.0,0.0,2.45173 +988,search,4482.64,0.85137,0.161231,9.179,2.45173 +989,delete,32.73,-1.0,-1.0,0.0,2.44432 +990,search,4478.85,0.85115,0.161431,8.745,2.44432 +991,delete,110.526,-1.0,-1.0,0.0,2.40929 +992,search,4464.43,0.85514,0.156573,9.055,2.40929 +993,delete,146.108,-1.0,-1.0,0.0,2.37182 +994,search,4534.73,0.85466,0.156757,6.078,2.37182 +995,delete,71.242,-1.0,-1.0,0.0,2.33899 +996,search,4548.5,0.85297,0.158104,8.553,2.33899 +997,delete,48.196,-1.0,-1.0,0.0,2.3246 +998,search,4897.73,0.85288,0.158189,8.954,2.3246 +999,delete,184.913,-1.0,-1.0,0.0,2.2681 +1000,search,4842.4,0.85191,0.158325,8.652,2.2681 +1001,delete,192.119,-1.0,-1.0,0.0,2.2139 +1002,search,4721.6,0.85083,0.159079,8.838,2.2139 +1003,delete,77.874,-1.0,-1.0,0.0,2.19173 +1004,search,4838.87,0.85056,0.159448,9.657,2.19173 +1005,delete,44.494,-1.0,-1.0,0.0,2.18165 +1006,search,4937.46,0.84988,0.159804,9.346,2.18165 +1007,delete,301.365,-1.0,-1.0,0.0,2.08453 +1008,search,4822.04,0.84812,0.160736,9.198,2.08453 +1009,delete,499.087,-1.0,-1.0,0.0,1.93794 +1010,search,4658.6,0.84779,0.160149,10.54,1.93794 +1011,delete,685.317,-1.0,-1.0,0.0,1.75694 +1012,search,4474.97,0.84243,0.162592,9.138,1.75694 +1013,delete,21.119,-1.0,-1.0,0.0,1.75079 +1014,search,4433.93,0.84233,0.162589,9.529,1.75079 +1015,delete,421.241,-1.0,-1.0,0.0,1.61054 +1016,search,5154.16,0.83983,0.163054,11.564,1.61054 +1017,delete,574.61,-1.0,-1.0,0.0,1.45285 +1018,search,4367.08,0.83867,0.163142,9.368,1.45285 +1019,delete,35.649,-1.0,-1.0,0.0,1.4406 +1020,search,4386.8,0.83855,0.162983,8.659,1.4406 +1021,delete,186.004,-1.0,-1.0,0.0,1.3834 +1022,search,4277.7,0.83628,0.164337,9.157,1.3834 +1023,delete,141.716,-1.0,-1.0,0.0,1.34051 +1024,search,4195.5,0.83442,0.165907,8.794,1.34051 +1025,insert,67.183,-1.0,-1.0,0.0,1.34772 +1026,search,4297.26,0.83477,0.165493,8.254,1.34772 +1027,insert,413.522,-1.0,-1.0,0.0,1.39918 +1028,search,4523.74,0.837,0.164666,9.98,1.39918 +1029,insert,1118.95,-1.0,-1.0,0.0,1.53221 +1030,search,4108.91,0.84216,0.16135,2500.39,1.53226 +1031,insert,1865.01,-1.0,-1.0,0.0,1.7822 +1032,search,4337.89,0.84574,0.161938,3319.96,1.78073 +1033,insert,1154.67,-1.0,-1.0,0.0,1.94648 +1034,search,4440.96,0.84954,0.160537,2606.85,1.94561 +1035,insert,686.512,-1.0,-1.0,0.0,2.05195 +1036,search,4509.97,0.84966,0.161371,2586.75,2.05221 +1037,insert,28.736,-1.0,-1.0,0.0,2.05679 +1038,search,4401.76,0.84996,0.161042,8.771,2.05679 +1039,insert,151.903,-1.0,-1.0,0.0,2.08479 +1040,search,4538.91,0.85054,0.160797,8.736,2.08479 +1041,insert,16.031,-1.0,-1.0,0.0,2.08751 +1042,search,4460.23,0.85016,0.161333,10.195,2.08751 +1043,insert,56.116,-1.0,-1.0,0.0,2.09493 +1044,search,4477.3,0.85032,0.161079,9.8,2.09493 +1045,insert,128.893,-1.0,-1.0,0.0,2.11048 +1046,search,4519.2,0.85158,0.16001,9.751,2.11048 +1047,insert,10.622,-1.0,-1.0,0.0,2.1117 +1048,search,4394.12,0.85102,0.16032,9.427,2.1117 +1049,insert,45.545,-1.0,-1.0,0.0,2.11761 +1050,search,4475.89,0.8511,0.160335,10.652,2.11761 +1051,insert,290.453,-1.0,-1.0,0.0,2.15328 +1052,search,4422.84,0.85199,0.159646,9.269,2.15328 +1053,insert,138.916,-1.0,-1.0,0.0,2.17072 +1054,search,4463.37,0.85218,0.159523,8.968,2.17072 +1055,insert,89.333,-1.0,-1.0,0.0,2.18452 +1056,search,4422.53,0.85294,0.158907,8.779,2.18452 +1057,insert,16.084,-1.0,-1.0,0.0,2.1864 +1058,search,4292.78,0.85237,0.159239,8.835,2.1864 +1059,insert,56.422,-1.0,-1.0,0.0,2.1913 +1060,search,4295.49,0.85274,0.159064,8.497,2.1913 +1061,insert,23.715,-1.0,-1.0,0.0,2.1948 +1062,search,4311.73,0.85285,0.159017,8.822,2.1948 +1063,insert,33.236,-1.0,-1.0,0.0,2.19881 +1064,search,4280.13,0.85218,0.159498,8.649,2.19881 +1065,insert,773.199,-1.0,-1.0,0.0,2.31456 +1066,search,4372.74,0.85367,0.158251,2790.62,2.31483 +1067,insert,11.875,-1.0,-1.0,0.0,2.31714 +1068,search,4347.21,0.85365,0.158007,8.901,2.31714 +1069,insert,90.968,-1.0,-1.0,0.0,2.33183 +1070,search,4352.5,0.85448,0.157106,9.307,2.33183 +1071,insert,68.97,-1.0,-1.0,0.0,2.34138 +1072,search,4359.06,0.8545,0.157207,9.442,2.34138 +1073,insert,76.055,-1.0,-1.0,0.0,2.34905 +1074,search,4296.23,0.85373,0.157726,9.001,2.34905 +1075,insert,31.955,-1.0,-1.0,0.0,2.35244 +1076,search,4345.81,0.85403,0.157443,8.606,2.35244 +1077,insert,75.621,-1.0,-1.0,0.0,2.36249 +1078,search,4346.85,0.85408,0.157559,8.878,2.36249 +1079,insert,68.06,-1.0,-1.0,0.0,2.36937 +1080,search,4315.77,0.85379,0.157635,8.937,2.36937 +1081,insert,1043.3,-1.0,-1.0,0.0,2.51008 +1082,search,4412,0.85588,0.157168,8.787,2.51008 +1083,insert,1.696,-1.0,-1.0,0.0,2.51043 +1084,search,4400.68,0.85586,0.157202,8.749,2.51043 +1085,insert,55.342,-1.0,-1.0,0.0,2.51919 +1086,search,4382.35,0.8562,0.156887,8.383,2.51919 +1087,insert,31.023,-1.0,-1.0,0.0,2.52385 +1088,search,4361.04,0.85641,0.156856,8.458,2.52385 +1089,insert,951.639,-1.0,-1.0,0.0,2.68921 +1090,search,4506.16,0.85922,0.154965,3679.32,2.69184 +1091,insert,116.785,-1.0,-1.0,0.0,2.71377 +1092,search,4536.92,0.86075,0.153837,2849.45,2.71456 +1093,insert,57.128,-1.0,-1.0,0.0,2.72434 +1094,search,4512.56,0.86031,0.15394,9.224,2.72434 +1095,insert,1008.01,-1.0,-1.0,0.0,2.89405 +1096,search,4495.01,0.86289,0.152949,3056.82,2.89374 +1097,insert,53.305,-1.0,-1.0,0.0,2.90153 +1098,search,4437.25,0.86285,0.153118,8.746,2.90153 +1099,insert,26.241,-1.0,-1.0,0.0,2.90558 +1100,search,4399.68,0.86245,0.153379,8.434,2.90558 +1101,insert,112.315,-1.0,-1.0,0.0,2.92325 +1102,search,4603.35,0.86302,0.153121,8.775,2.92325 +1103,insert,209.149,-1.0,-1.0,0.0,2.96313 +1104,search,4583.48,0.86541,0.151755,8.806,2.96313 +1105,insert,1.853,-1.0,-1.0,0.0,2.96337 +1106,search,4460.47,0.8654,0.151768,8.117,2.96337 +1107,insert,514.896,-1.0,-1.0,0.0,3.05956 +1108,search,4639.09,0.86724,0.15002,3601.57,3.06008 +1109,insert,14.304,-1.0,-1.0,0.0,3.06263 +1110,search,4614.89,0.86634,0.150637,8.157,3.06263 +1111,insert,97.494,-1.0,-1.0,0.0,3.0776 +1112,search,4529.16,0.86665,0.150321,9.51,3.0776 +1113,insert,126.464,-1.0,-1.0,0.0,3.10023 +1114,search,4683.18,0.86697,0.150288,9.221,3.10023 +1115,insert,174.275,-1.0,-1.0,0.0,3.12912 +1116,search,4676.36,0.86692,0.150054,9.264,3.12912 +1117,insert,50.009,-1.0,-1.0,0.0,3.13756 +1118,search,4545.07,0.86704,0.14995,3350.72,3.13722 +1119,insert,24.514,-1.0,-1.0,0.0,3.14077 +1120,search,4564.93,0.86664,0.150209,8.701,3.14077 +1121,insert,76.866,-1.0,-1.0,0.0,3.15244 +1122,search,4432.6,0.8661,0.15062,8.452,3.15244 +1123,insert,55.642,-1.0,-1.0,0.0,3.16084 +1124,search,4664.56,0.8661,0.150746,7.949,3.16084 +1125,insert,25.855,-1.0,-1.0,0.0,3.16443 +1126,search,4636.11,0.8652,0.151598,8.157,3.16443 +1127,insert,131.611,-1.0,-1.0,0.0,3.18547 +1128,search,4560.39,0.86541,0.151774,8.122,3.18547 +1129,insert,29.586,-1.0,-1.0,0.0,3.18998 +1130,search,4617.82,0.86541,0.151794,8.11,3.18998 +1131,insert,103.283,-1.0,-1.0,0.0,3.2014 +1132,search,4599.8,0.8647,0.152286,7.968,3.2014 +1133,insert,46.548,-1.0,-1.0,0.0,3.20834 +1134,search,4617.07,0.86475,0.152255,7.859,3.20834 +1135,insert,10.276,-1.0,-1.0,0.0,3.20963 +1136,search,4630.29,0.86474,0.152258,9.068,3.20963 +1137,insert,72.954,-1.0,-1.0,0.0,3.21792 +1138,search,4631.75,0.86408,0.152698,3669.24,3.21766 +1139,insert,8.587,-1.0,-1.0,0.0,3.21954 +1140,search,4628.07,0.86405,0.152733,8.765,3.21954 +1141,insert,624.502,-1.0,-1.0,0.0,3.31071 +1142,search,4644.65,0.8638,0.153372,3418.56,3.31093 +1143,insert,77.853,-1.0,-1.0,0.0,3.3217 +1144,search,4662.99,0.86383,0.153455,8.2,3.3217 +1145,insert,18.273,-1.0,-1.0,0.0,3.32469 +1146,search,4638.81,0.86379,0.153443,8.211,3.32469 +1147,insert,61.426,-1.0,-1.0,0.0,3.33225 +1148,search,4632.6,0.86309,0.153739,7.934,3.33225 +1149,insert,7.583,-1.0,-1.0,0.0,3.33277 +1150,search,4619.58,0.86313,0.15376,7.978,3.33277 +1151,insert,21.926,-1.0,-1.0,0.0,3.33676 +1152,search,4610.75,0.86315,0.153759,7.994,3.33676 +1153,delete,32.136,-1.0,-1.0,0.0,3.33486 +1154,search,4570.31,0.8624,0.154224,8.05,3.33486 +1155,delete,161.426,-1.0,-1.0,0.0,3.31668 +1156,search,4537.55,0.86151,0.154566,7.794,3.31668 +1157,delete,331.696,-1.0,-1.0,0.0,3.25435 +1158,search,4421.35,0.8595,0.155665,9.074,3.25435 +1159,delete,480.553,-1.0,-1.0,0.0,3.09651 +1160,search,4290.38,0.8571,0.155769,8.999,3.09651 +1161,delete,323.204,-1.0,-1.0,0.0,3.01376 +1162,search,4215.62,0.85492,0.15688,8.457,3.01376 +1163,delete,174.01,-1.0,-1.0,0.0,2.96792 +1164,search,4187.2,0.85388,0.157354,8.201,2.96792 +1165,delete,45.716,-1.0,-1.0,0.0,2.96335 +1166,search,4162.81,0.85349,0.157448,8.555,2.96335 +1167,delete,96.228,-1.0,-1.0,0.0,2.94549 +1168,search,4139.13,0.85316,0.157258,8.218,2.94549 +1169,delete,31.737,-1.0,-1.0,0.0,2.93301 +1170,search,4116.07,0.85073,0.158251,8.321,2.93301 +1171,delete,46.528,-1.0,-1.0,0.0,2.92267 +1172,search,4095.52,0.85032,0.158658,10.772,2.92267 +1173,delete,55.891,-1.0,-1.0,0.0,2.91458 +1174,search,4057.69,0.84885,0.159779,8.42,2.91458 +1175,delete,23.075,-1.0,-1.0,0.0,2.91149 +1176,search,4050.94,0.8485,0.160167,7.767,2.91149 +1177,delete,19.627,-1.0,-1.0,0.0,2.90696 +1178,search,4028.93,0.84853,0.160112,7.797,2.90696 +1179,delete,74.17,-1.0,-1.0,0.0,2.889 +1180,search,3982.12,0.84731,0.160971,7.883,2.889 +1181,delete,58.276,-1.0,-1.0,0.0,2.87272 +1182,search,3961.72,0.84658,0.161702,7.862,2.87272 +1183,delete,62.292,-1.0,-1.0,0.0,2.85506 +1184,search,3948.22,0.84469,0.163316,7.85,2.85506 +1185,delete,28.765,-1.0,-1.0,0.0,2.84884 +1186,search,3972.6,0.84443,0.163476,8.963,2.84884 +1187,delete,196.841,-1.0,-1.0,0.0,2.81111 +1188,search,3922.23,0.84326,0.164508,8.321,2.81111 +1189,delete,23.199,-1.0,-1.0,0.0,2.80537 +1190,search,3896.89,0.84238,0.164976,8.657,2.80537 +1191,delete,22.773,-1.0,-1.0,0.0,2.80077 +1192,search,3892.02,0.84227,0.165017,8.451,2.80077 +1193,delete,321.021,-1.0,-1.0,0.0,2.70979 +1194,search,3864.4,0.84167,0.165523,8.035,2.70979 +1195,delete,28.838,-1.0,-1.0,0.0,2.70548 +1196,search,3820.93,0.84064,0.166421,8.315,2.70548 +1197,delete,87.099,-1.0,-1.0,0.0,2.68358 +1198,search,3796.31,0.83932,0.167531,7.984,2.68358 +1199,delete,18.117,-1.0,-1.0,0.0,2.67841 +1200,search,3753.97,0.83835,0.168165,8.23,2.67841 +1201,delete,104.701,-1.0,-1.0,0.0,2.64836 +1202,search,3750.17,0.83764,0.167974,7.936,2.64836 +1203,delete,42.191,-1.0,-1.0,0.0,2.63965 +1204,search,3732.79,0.83701,0.168803,7.695,2.63965 +1205,delete,32.237,-1.0,-1.0,0.0,2.62925 +1206,search,3728.64,0.83598,0.169301,7.864,2.62925 +1207,delete,31.942,-1.0,-1.0,0.0,2.61917 +1208,search,3712.29,0.83554,0.169323,7.793,2.61917 +1209,delete,355.419,-1.0,-1.0,0.0,2.50672 +1210,search,3616.35,0.83331,0.17004,7.944,2.50672 +1211,delete,8.816,-1.0,-1.0,0.0,2.50441 +1212,search,3611.67,0.83332,0.170126,7.711,2.50441 +1213,delete,152.668,-1.0,-1.0,0.0,2.45867 +1214,search,3606.39,0.83198,0.170747,7.859,2.45867 +1215,delete,29.287,-1.0,-1.0,0.0,2.45003 +1216,search,3580.23,0.8309,0.171563,7.747,2.45003 +1217,delete,469.425,-1.0,-1.0,0.0,2.28733 +1218,search,3505.1,0.82607,0.174743,8.718,2.28733 +1219,delete,153.687,-1.0,-1.0,0.0,2.24073 +1220,search,3453.08,0.82209,0.177582,7.998,2.24073 +1221,delete,58.594,-1.0,-1.0,0.0,2.2248 +1222,search,3446.45,0.82154,0.178002,7.999,2.2248 +1223,delete,314.14,-1.0,-1.0,0.0,2.11667 +1224,search,3674.33,0.81822,0.179098,7.861,2.11667 +1225,delete,60.23,-1.0,-1.0,0.0,2.09987 +1226,search,3672.06,0.81683,0.17977,7.667,2.09987 +1227,delete,114.421,-1.0,-1.0,0.0,2.06556 +1228,search,3646.77,0.8165,0.179851,7.567,2.06556 +1229,delete,133.483,-1.0,-1.0,0.0,2.02945 +1230,search,3567.58,0.8147,0.180757,8.264,2.02945 +1231,delete,117.354,-1.0,-1.0,0.0,1.99008 +1232,search,3572.55,0.81033,0.183863,7.966,1.99008 +1233,delete,24.795,-1.0,-1.0,0.0,1.98462 +1234,search,3550.76,0.81021,0.183862,8.425,1.98462 +1235,delete,235.574,-1.0,-1.0,0.0,1.90479 +1236,search,3492.4,0.80746,0.185277,8.022,1.90479 +1237,delete,24.324,-1.0,-1.0,0.0,1.89726 +1238,search,3486.61,0.80732,0.185258,8.057,1.89726 +1239,delete,85.468,-1.0,-1.0,0.0,1.87582 +1240,search,3475.77,0.80619,0.185781,8.277,1.87582 +1241,delete,57.912,-1.0,-1.0,0.0,1.85745 +1242,search,3468.89,0.80444,0.18703,7.91,1.85745 +1243,delete,71.36,-1.0,-1.0,0.0,1.83406 +1244,search,3447,0.80337,0.187796,8.087,1.83406 +1245,delete,21.338,-1.0,-1.0,0.0,1.82723 +1246,search,3424.46,0.80209,0.188571,7.633,1.82723 +1247,delete,82.508,-1.0,-1.0,0.0,1.79386 +1248,search,3389.62,0.81257,0.177003,7.581,1.79386 +1249,delete,58.914,-1.0,-1.0,0.0,1.77573 +1250,search,3452.09,0.81238,0.17668,7.619,1.77573 +1251,delete,46.519,-1.0,-1.0,0.0,1.76002 +1252,search,3358.75,0.81045,0.177932,8.465,1.76002 +1253,delete,35.073,-1.0,-1.0,0.0,1.75171 +1254,search,3430.4,0.81051,0.17789,8.015,1.75171 +1255,delete,166.057,-1.0,-1.0,0.0,1.69047 +1256,search,3346.6,0.80753,0.17906,7.75,1.69047 +1257,delete,55.996,-1.0,-1.0,0.0,1.67352 +1258,search,3263.9,0.80705,0.179135,7.776,1.67352 +1259,delete,88.586,-1.0,-1.0,0.0,1.65014 +1260,search,3339.92,0.80672,0.179259,7.649,1.65014 +1261,delete,36.982,-1.0,-1.0,0.0,1.64069 +1262,search,3334.46,0.80516,0.179967,8.082,1.64069 +1263,delete,163.63,-1.0,-1.0,0.0,1.58904 +1264,search,3229.1,0.80486,0.179714,9.626,1.58904 +1265,delete,407.377,-1.0,-1.0,0.0,1.46964 +1266,search,3290.99,0.80132,0.18179,8.041,1.46964 +1267,delete,133.411,-1.0,-1.0,0.0,1.4352 +1268,search,3266.01,0.79971,0.182844,7.885,1.4352 +1269,delete,226.382,-1.0,-1.0,0.0,1.36775 +1270,search,3244.92,0.79943,0.182201,8.015,1.36775 +1271,delete,125.233,-1.0,-1.0,0.0,1.33322 +1272,search,3217.08,0.79724,0.182956,7.731,1.33322 +1273,delete,189.962,-1.0,-1.0,0.0,1.27725 +1274,search,3124.91,0.79615,0.18324,8.008,1.27725 +1275,delete,34.567,-1.0,-1.0,0.0,1.26662 +1276,search,3187.09,0.79548,0.183411,7.486,1.26662 +1277,delete,53.252,-1.0,-1.0,0.0,1.25059 +1278,search,3185.27,0.79393,0.18395,7.772,1.25059 +1279,delete,45.265,-1.0,-1.0,0.0,1.23757 +1280,search,3161.14,0.79329,0.18385,7.587,1.23757 diff --git a/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.1_0.01.csv b/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.1_0.01.csv new file mode 100644 index 00000000..5b36e1d9 --- /dev/null +++ b/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.1_0.01.csv @@ -0,0 +1,20 @@ +step_num,step_type,latency_ms,recall_mean,recall_std_dev,mainteance_ms,index_mem_gb,num_partitions +2,search,3046.98,0.84693,0.134675,2.186,0.0183474,512 +3,insert,14.156,-1.0,-1.0,3.004,0.0223861,512 +4,search,2186.43,0.85904,0.131452,2.242,0.0223861,512 +5,insert,15.789,-1.0,-1.0,258.383,0.0328126,512 +6,search,2233.5,0.9098,0.11532,443.456,0.0328126,512 +7,insert,21.474,-1.0,-1.0,363.255,0.0423292,512 +8,search,2288.37,0.89642,0.124485,385.37,0.0423292,512 +9,insert,2.728,-1.0,-1.0,273.156,0.044075,512 +10,search,2309.24,0.90145,0.121325,56.822,0.0441819,513 +11,insert,8.477,-1.0,-1.0,2.087,0.0495871,513 +12,search,2336.46,0.91057,0.11373,1227.26,0.0495871,513 +13,insert,16.719,-1.0,-1.0,102.781,0.0604693,515 +14,search,2275.27,0.90893,0.115698,105.085,0.0605239,517 +15,insert,18.723,-1.0,-1.0,2.137,0.0687174,517 +16,search,2379.33,0.91358,0.111333,94.063,0.0688859,518 +17,insert,3.892,-1.0,-1.0,84.857,0.0712152,519 +18,search,2447.64,0.9167,0.109808,92.406,0.0710169,520 +19,insert,32.769,-1.0,-1.0,135.536,0.0784119,521 +20,search,2493.74,0.92503,0.102272,109.37,0.0780337,522 diff --git a/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.2_0.1.csv b/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.2_0.1.csv new file mode 100644 index 00000000..398664eb --- /dev/null +++ b/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.2_0.1.csv @@ -0,0 +1,469 @@ +step_num,step_type,latency_ms,recall_mean,recall_std_dev,mainteance_ms,index_mem_gb,num_partitions +2,search,3052.35,0.84693,0.134675,2.217,0.0183474,512 +3,insert,14.282,-1.0,-1.0,3.021,0.0223861,512 +4,search,2283.72,0.85904,0.131452,2.216,0.0223861,512 +5,insert,14.95,-1.0,-1.0,258.384,0.0328126,512 +6,search,2255.33,0.9098,0.11532,348.912,0.0328126,512 +7,insert,19.231,-1.0,-1.0,256.457,0.0423292,512 +8,search,2350.71,0.89642,0.124485,57.375,0.0427433,513 +9,insert,2.791,-1.0,-1.0,2.168,0.0441937,513 +10,search,2494.97,0.90505,0.117919,77.743,0.04443,514 +11,insert,6.965,-1.0,-1.0,96.058,0.0489257,515 +12,search,2473.79,0.91055,0.114017,89.258,0.0489114,517 +13,insert,17.309,-1.0,-1.0,2.193,0.0602538,517 +14,search,2367.95,0.91146,0.113818,2.389,0.0602538,517 +15,insert,16.701,-1.0,-1.0,99.638,0.0690209,518 +16,search,2371.72,0.92203,0.104381,114.965,0.0689206,520 +17,insert,8.23,-1.0,-1.0,114.55,0.0709671,521 +18,search,2407.12,0.93166,0.0964676,113.601,0.0708729,522 +19,insert,36.7,-1.0,-1.0,123.103,0.0777375,524 +20,search,2524.69,0.93605,0.0926929,105.129,0.0774755,525 +21,insert,248.299,-1.0,-1.0,347.905,0.197139,533 +22,search,3098.35,0.93738,0.089284,240.915,0.196603,539 +23,insert,311.149,-1.0,-1.0,701.58,0.320968,550 +24,search,3763.64,0.9407,0.0865359,653.624,0.322969,564 +25,insert,34.842,-1.0,-1.0,226.891,0.340715,565 +26,search,3675.66,0.93489,0.0911314,457.782,0.341604,581 +27,insert,24.565,-1.0,-1.0,320.225,0.35472,583 +28,search,3831.67,0.93092,0.0935963,276.442,0.355065,584 +29,insert,47.836,-1.0,-1.0,409.284,0.380826,588 +30,search,3661.84,0.93314,0.0922327,293.379,0.380524,591 +31,insert,263.561,-1.0,-1.0,983.444,0.543114,623 +32,search,3744.25,0.92264,0.100038,651.387,0.543589,643 +33,insert,22.17,-1.0,-1.0,370.234,0.566268,648 +34,search,3704.13,0.9145,0.106455,424.587,0.565921,654 +35,insert,12.771,-1.0,-1.0,296.185,0.58143,655 +36,search,3756.2,0.9156,0.106257,2.038,0.58143,655 +37,insert,20.379,-1.0,-1.0,379.895,0.60236,658 +38,search,4105.65,0.9135,0.109151,460.824,0.603224,659 +39,insert,6.857,-1.0,-1.0,469.649,0.607435,660 +40,search,4797.99,0.9148,0.108053,491.135,0.607466,661 +41,insert,40.07,-1.0,-1.0,500.578,0.620233,663 +42,search,4873.97,0.91496,0.107617,489.722,0.620301,664 +43,insert,9.937,-1.0,-1.0,472.886,0.624885,665 +44,search,4661.96,0.91463,0.107989,3.232,0.624885,665 +45,insert,269.159,-1.0,-1.0,658.811,0.639031,671 +46,search,4890.71,0.91339,0.108861,3.238,0.639031,671 +47,insert,238.904,-1.0,-1.0,1291.38,0.73905,686 +48,search,5221.34,0.91545,0.107941,851.538,0.741011,696 +49,insert,31.528,-1.0,-1.0,654.285,0.758237,699 +50,search,4529.81,0.91473,0.109044,494.586,0.757864,703 +51,insert,132.057,-1.0,-1.0,1559.14,0.893247,734 +52,search,4427.44,0.91232,0.111366,804.942,0.891891,750 +53,insert,21.26,-1.0,-1.0,577.861,0.910586,753 +54,search,4404.74,0.90858,0.113416,586.523,0.911836,757 +55,insert,125.001,-1.0,-1.0,1776.06,1.05273,789 +56,search,4608.43,0.91628,0.110746,936.412,1.05106,802 +57,insert,13.789,-1.0,-1.0,639.656,1.05947,804 +58,search,5009.62,0.91468,0.111657,888.131,1.05992,805 +59,insert,205.321,-1.0,-1.0,2174.54,1.15633,826 +60,search,5927,0.90928,0.11718,962.293,1.15565,828 +61,insert,11.376,-1.0,-1.0,4.373,1.16078,828 +62,search,5763.05,0.90895,0.117372,5.126,1.16078,828 +63,insert,3.814,-1.0,-1.0,4.649,1.1617,828 +64,search,5581.48,0.90894,0.117334,5.087,1.1617,828 +65,insert,111.66,-1.0,-1.0,1263.49,1.19418,836 +66,search,5499.45,0.90933,0.117046,5.138,1.19418,836 +67,insert,36.671,-1.0,-1.0,1006.52,1.21327,842 +68,search,5791.25,0.91032,0.116578,5.819,1.21327,842 +69,insert,58.083,-1.0,-1.0,1096.69,1.23725,850 +70,search,5703.49,0.91142,0.115672,1248.27,1.23743,852 +71,insert,17.695,-1.0,-1.0,1177.65,1.24374,853 +72,search,5995.16,0.91111,0.11604,5.842,1.24374,853 +73,insert,8.156,-1.0,-1.0,5.4,1.24732,853 +74,search,5964.59,0.9112,0.115993,5.956,1.24732,853 +75,insert,23.489,-1.0,-1.0,5.636,1.25521,853 +76,search,6199.02,0.91155,0.115585,5.899,1.25521,853 +77,insert,30.555,-1.0,-1.0,983.17,1.26545,854 +78,search,5287.02,0.91064,0.116364,4.177,1.26545,854 +79,insert,354.395,-1.0,-1.0,777.317,1.29489,855 +80,search,5350.82,0.91039,0.116305,4.391,1.29489,855 +81,insert,32.461,-1.0,-1.0,777.546,1.30896,857 +82,search,4440.17,0.91125,0.114905,4.217,1.30896,857 +83,insert,7.25,-1.0,-1.0,810.006,1.31255,860 +84,search,4484.46,0.9107,0.115327,4.163,1.31255,860 +85,insert,16.15,-1.0,-1.0,911.038,1.32862,865 +86,search,4481.53,0.91193,0.114554,797.126,1.32849,867 +87,insert,187.904,-1.0,-1.0,3042.79,1.51841,920 +88,search,4912.97,0.91393,0.111865,1409.96,1.521,943 +89,insert,160.052,-1.0,-1.0,1997.85,1.67828,981 +90,search,5286.75,0.91467,0.110616,1337.33,1.67712,995 +91,insert,13.936,-1.0,-1.0,997.995,1.69163,997 +92,search,5455.93,0.91434,0.111025,1125.78,1.69192,1003 +93,insert,124.985,-1.0,-1.0,1963.63,1.79726,1024 +94,search,5895.55,0.91415,0.111497,1199.42,1.7972,1032 +95,insert,5.701,-1.0,-1.0,1044.99,1.80288,1033 +96,search,5896.65,0.9146,0.111024,1057.3,1.80322,1034 +97,insert,4.663,-1.0,-1.0,8.24,1.80683,1034 +98,search,5833.63,0.91477,0.110745,8.447,1.80683,1034 +99,insert,5.847,-1.0,-1.0,1088.66,1.80694,1035 +100,search,5799.42,0.91485,0.110668,8.309,1.80694,1035 +101,insert,22.099,-1.0,-1.0,1123.97,1.81983,1037 +102,search,5855.8,0.91494,0.110497,8.317,1.81983,1037 +103,insert,14.465,-1.0,-1.0,1150.57,1.82976,1040 +104,search,5804.81,0.91475,0.110716,1099.26,1.8295,1041 +105,insert,5.179,-1.0,-1.0,8.17,1.83331,1041 +106,search,5895.48,0.91479,0.110797,8.371,1.83331,1041 +107,insert,11.734,-1.0,-1.0,1092.05,1.83849,1042 +108,search,5975.61,0.91458,0.110844,8.252,1.83849,1042 +109,insert,197.997,-1.0,-1.0,3063.23,1.99576,1079 +110,search,6149.16,0.91548,0.11004,1553.92,1.99567,1097 +111,insert,11.732,-1.0,-1.0,1332.83,2.00801,1102 +112,search,6122.51,0.91542,0.110197,1323.44,2.00872,1106 +113,insert,5.782,-1.0,-1.0,8.88,2.0138,1106 +114,search,6141.48,0.91557,0.109872,8.942,2.0138,1106 +115,insert,19.666,-1.0,-1.0,1229.71,2.02434,1107 +116,search,6104.92,0.91617,0.10951,9.044,2.02434,1107 +117,insert,8.674,-1.0,-1.0,8.446,2.03136,1107 +118,search,6172.57,0.91634,0.108783,8.799,2.03136,1107 +119,insert,1.936,-1.0,-1.0,1244.46,2.03269,1108 +120,search,6162.88,0.91626,0.108889,8.647,2.03269,1108 +121,insert,8.075,-1.0,-1.0,1238.1,2.03781,1109 +122,search,6233.4,0.91638,0.108866,8.607,2.03781,1109 +123,insert,153.082,-1.0,-1.0,2143.24,2.15911,1131 +124,search,6420.27,0.91807,0.108131,1547.03,2.15856,1139 +125,insert,26.847,-1.0,-1.0,1583.11,2.17651,1144 +126,search,6462.16,0.91834,0.108179,1470.62,2.17642,1149 +127,insert,25.268,-1.0,-1.0,1513.76,2.19856,1153 +128,search,6399.86,0.91892,0.107972,3.87,2.19856,1153 +129,delete,18.062,-1.0,-1.0,3.497,2.19773,1153 +130,search,6444.74,0.9189,0.107963,3.876,2.19773,1153 +131,delete,4.565,-1.0,-1.0,3.408,2.19771,1153 +132,search,6383.23,0.91877,0.10812,3.772,2.19771,1153 +133,delete,11.167,-1.0,-1.0,3.341,2.19771,1153 +134,search,6483.82,0.91888,0.108127,4.116,2.19771,1153 +135,delete,14.501,-1.0,-1.0,3.386,2.1966,1153 +136,search,6469.52,0.92072,0.106066,3.73,2.1966,1153 +137,delete,2.634,-1.0,-1.0,3.742,2.1966,1153 +138,search,6475.9,0.92067,0.106148,3.546,2.1966,1153 +139,delete,5.285,-1.0,-1.0,3.357,2.19476,1153 +140,search,6483.8,0.92076,0.106168,3.72,2.19476,1153 +141,delete,12.969,-1.0,-1.0,3.371,2.19209,1153 +142,search,6375.5,0.92063,0.10625,3.822,2.19209,1153 +143,delete,9.447,-1.0,-1.0,3.507,2.19094,1153 +144,search,6353.47,0.92101,0.105893,3.852,2.19094,1153 +145,delete,1.08,-1.0,-1.0,3.494,2.18996,1153 +146,search,6277.37,0.92074,0.105992,3.957,2.18996,1153 +147,delete,4.924,-1.0,-1.0,3.46,2.18996,1153 +148,search,6196.31,0.92095,0.105987,4.169,2.18996,1153 +149,delete,116.567,-1.0,-1.0,4.018,2.15109,1153 +150,search,6173.55,0.92505,0.102518,3.965,2.15109,1153 +151,delete,99.398,-1.0,-1.0,3.947,2.11278,1153 +152,search,6065.52,0.92496,0.102772,4.007,2.11278,1153 +153,delete,25.863,-1.0,-1.0,3.64,2.09877,1153 +154,search,6035.93,0.92453,0.10304,3.883,2.09877,1153 +155,delete,16.222,-1.0,-1.0,3.569,2.09375,1153 +156,search,6064.41,0.92446,0.102959,4.155,2.09375,1153 +157,delete,29.56,-1.0,-1.0,3.696,2.08025,1153 +158,search,5924.03,0.92418,0.103226,4.068,2.08025,1153 +159,delete,172.126,-1.0,-1.0,4.003,1.96092,1153 +160,search,5785.15,0.92396,0.103193,3.961,1.96092,1153 +161,delete,27.567,-1.0,-1.0,3.837,1.94874,1153 +162,search,5698.39,0.92407,0.102953,4.005,1.94874,1153 +163,delete,14.272,-1.0,-1.0,3.92,1.94086,1153 +164,search,5659.06,0.92373,0.103241,3.915,1.94086,1153 +165,delete,18.949,-1.0,-1.0,3.666,1.9336,1153 +166,search,5626.15,0.92353,0.103286,4.16,1.9336,1153 +167,delete,4.409,-1.0,-1.0,3.66,1.93146,1153 +168,search,5551.9,0.92352,0.103261,3.884,1.93146,1153 +169,delete,9.558,-1.0,-1.0,3.691,1.92459,1153 +170,search,5584.82,0.9232,0.103599,4.065,1.92459,1153 +171,delete,11.274,-1.0,-1.0,3.64,1.92018,1153 +172,search,5505.71,0.92309,0.103802,4.301,1.92018,1153 +173,delete,31.303,-1.0,-1.0,3.813,1.9063,1153 +174,search,5489.1,0.92229,0.104104,4.112,1.9063,1153 +175,delete,105.432,-1.0,-1.0,3.971,1.83547,1153 +176,search,5490.7,0.92253,0.104055,4.076,1.83547,1153 +177,delete,15.187,-1.0,-1.0,3.74,1.82813,1153 +178,search,5503.23,0.92231,0.104239,4.169,1.82813,1153 +179,delete,143.969,-1.0,-1.0,4.117,1.72375,1153 +180,search,5271.7,0.92058,0.105481,4.099,1.72375,1153 +181,delete,20.913,-1.0,-1.0,3.865,1.71111,1153 +182,search,5206,0.92036,0.105689,4.261,1.71111,1153 +183,delete,100.301,-1.0,-1.0,3.986,1.63978,1153 +184,search,4974.46,0.91493,0.109643,4.182,1.63978,1153 +185,delete,6.688,-1.0,-1.0,3.826,1.63574,1153 +186,search,5002.32,0.91506,0.109521,4.037,1.63574,1153 +187,delete,109.541,-1.0,-1.0,4.053,1.54781,1153 +188,search,4915.33,0.91745,0.107188,4.023,1.54781,1153 +189,delete,7.404,-1.0,-1.0,3.579,1.54396,1153 +190,search,4974.13,0.91742,0.107249,4.184,1.54396,1153 +191,delete,2.242,-1.0,-1.0,3.624,1.54259,1153 +192,search,4918.8,0.91745,0.1073,4.193,1.54259,1153 +193,delete,36.596,-1.0,-1.0,3.98,1.51623,1153 +194,search,4824.22,0.91538,0.108643,4.066,1.51623,1153 +195,delete,19.516,-1.0,-1.0,3.799,1.50287,1153 +196,search,4744.93,0.91433,0.109036,4.189,1.50287,1153 +197,delete,21.643,-1.0,-1.0,3.958,1.48945,1153 +198,search,4716.06,0.91383,0.10949,4.449,1.48945,1153 +199,delete,17.216,-1.0,-1.0,3.661,1.48184,1153 +200,search,4718.11,0.91339,0.109848,4.002,1.48184,1153 +201,delete,5.336,-1.0,-1.0,3.802,1.47975,1153 +202,search,4777.82,0.91323,0.109906,4.074,1.47975,1153 +203,delete,12.722,-1.0,-1.0,3.541,1.4732,1153 +204,search,4731.87,0.91295,0.110299,4.254,1.4732,1153 +205,delete,20.778,-1.0,-1.0,3.843,1.46154,1153 +206,search,4731.49,0.91351,0.10985,3.961,1.46154,1153 +207,delete,31.372,-1.0,-1.0,4.034,1.44092,1153 +208,search,4707.48,0.91391,0.109435,4.22,1.44092,1153 +209,delete,19.623,-1.0,-1.0,3.562,1.43141,1153 +210,search,4630.42,0.91333,0.109776,4.093,1.43141,1153 +211,delete,6.917,-1.0,-1.0,3.931,1.42706,1153 +212,search,4586.97,0.91312,0.109949,4.245,1.42706,1153 +213,delete,12.798,-1.0,-1.0,3.483,1.41816,1153 +214,search,4676.84,0.91272,0.1102,4.19,1.41816,1153 +215,delete,199.513,-1.0,-1.0,3.981,1.26588,1153 +216,search,4289.06,0.90663,0.114276,4.034,1.26588,1153 +217,delete,139.719,-1.0,-1.0,3.927,1.16612,1153 +218,search,4132.07,0.90328,0.116867,4,1.16612,1153 +219,delete,15.351,-1.0,-1.0,3.696,1.15474,1153 +220,search,4048.89,0.90155,0.118081,3.932,1.15474,1153 +221,delete,123.581,-1.0,-1.0,4.231,1.0544,1153 +222,search,3947.95,0.90218,0.118364,3.88,1.0544,1153 +223,delete,7.825,-1.0,-1.0,3.438,1.04891,1153 +224,search,3919.35,0.90061,0.119375,4.146,1.04891,1153 +225,delete,3.973,-1.0,-1.0,3.474,1.04662,1153 +226,search,3917.33,0.90058,0.119389,3.921,1.04662,1153 +227,delete,2.636,-1.0,-1.0,3.582,1.04476,1153 +228,search,3935.56,0.90036,0.119487,4.563,1.04476,1153 +229,delete,31.558,-1.0,-1.0,3.643,1.03179,1153 +230,search,3951.54,0.89919,0.120048,4.035,1.03179,1153 +231,delete,10.124,-1.0,-1.0,3.516,1.02612,1153 +232,search,3909.12,0.89799,0.120694,4.35,1.02612,1153 +233,delete,5.38,-1.0,-1.0,3.452,1.02388,1153 +234,search,3891.82,0.89777,0.120781,4.309,1.02388,1153 +235,delete,8.405,-1.0,-1.0,3.569,1.02006,1153 +236,search,3883.39,0.89786,0.120734,3.899,1.02006,1153 +237,delete,151.855,-1.0,-1.0,4.116,0.910563,1153 +238,search,3741.91,0.8962,0.121527,4.095,0.910563,1153 +239,delete,15.389,-1.0,-1.0,3.978,0.89924,1153 +240,search,3691.3,0.89493,0.121918,4.134,0.89924,1153 +241,delete,7.364,-1.0,-1.0,3.8,0.895275,1153 +242,search,3620.58,0.89419,0.122376,4.14,0.895275,1153 +243,delete,15.819,-1.0,-1.0,3.844,0.883871,1153 +244,search,3694.01,0.89262,0.12356,4.144,0.883871,1153 +245,delete,8.208,-1.0,-1.0,3.556,0.879081,1153 +246,search,3659.78,0.89229,0.123617,3.943,0.879081,1153 +247,delete,2.513,-1.0,-1.0,3.514,0.8774,1153 +248,search,3628.32,0.89203,0.123873,4.02,0.8774,1153 +249,delete,5.582,-1.0,-1.0,3.748,0.872927,1153 +250,search,3639.07,0.89155,0.124305,4.07,0.872927,1153 +251,delete,150.946,-1.0,-1.0,3.911,0.760005,1153 +252,search,3503.98,0.89232,0.122071,4.142,0.760005,1153 +253,delete,19.236,-1.0,-1.0,3.661,0.744569,1153 +254,search,3434.89,0.89072,0.123222,4.109,0.744569,1153 +255,delete,23.618,-1.0,-1.0,3.785,0.725047,1153 +256,search,3430.3,0.88815,0.124611,4.071,0.725047,1153 +257,insert,5.522,-1.0,-1.0,3.491,0.726133,1153 +258,search,3422.48,0.88804,0.124748,3.863,0.726133,1153 +259,insert,16.065,-1.0,-1.0,3.846,0.732707,1153 +260,search,3439.03,0.88908,0.12451,4.072,0.732707,1153 +261,insert,1.972,-1.0,-1.0,3.489,0.732774,1153 +262,search,3418.14,0.88963,0.124277,3.994,0.732774,1153 +263,insert,83.462,-1.0,-1.0,804.713,0.77496,1154 +264,search,3586.01,0.89422,0.122164,746.743,0.776675,1156 +265,insert,41.376,-1.0,-1.0,664,0.792917,1158 +266,search,3637.9,0.89566,0.121119,580,0.79357,1162 +267,insert,15.512,-1.0,-1.0,511.373,0.804373,1165 +268,search,3625.73,0.89722,0.120483,550.332,0.804867,1166 +269,insert,161.238,-1.0,-1.0,952.831,0.889974,1169 +270,search,3956.57,0.8995,0.119162,938.492,0.890233,1171 +271,insert,3.068,-1.0,-1.0,799.571,0.8918,1172 +272,search,3835.65,0.89919,0.119464,796.361,0.892792,1176 +273,insert,12.437,-1.0,-1.0,633.129,0.900367,1177 +274,search,3843.86,0.89992,0.119355,686.219,0.900117,1182 +275,insert,225.914,-1.0,-1.0,1173.93,1.05151,1195 +276,search,4166.73,0.90099,0.120155,1025.88,1.05295,1204 +277,insert,20.736,-1.0,-1.0,755.166,1.06493,1205 +278,search,4698.92,0.90301,0.118091,828.311,1.06402,1215 +279,insert,14.709,-1.0,-1.0,3.992,1.07443,1215 +280,search,4165.15,0.90408,0.117383,4.084,1.07443,1215 +281,insert,204.643,-1.0,-1.0,1128.67,1.20099,1218 +282,search,4299.96,0.9058,0.117827,4.197,1.20099,1218 +283,insert,253.001,-1.0,-1.0,1266.41,1.38004,1229 +284,search,4756.58,0.90979,0.113743,1189.43,1.38021,1240 +285,insert,7.992,-1.0,-1.0,1230.74,1.38999,1242 +286,search,4763.79,0.90991,0.113537,1157.73,1.38867,1246 +287,insert,22.759,-1.0,-1.0,1175.87,1.40193,1248 +288,search,4746.14,0.9102,0.113198,1170.24,1.40302,1251 +289,insert,163.72,-1.0,-1.0,1658.13,1.53253,1271 +290,search,4991.18,0.91291,0.112043,1511.82,1.53292,1288 +291,insert,12.48,-1.0,-1.0,1132.97,1.54126,1289 +292,search,5074.16,0.91458,0.110165,986.55,1.54166,1291 +293,insert,9.028,-1.0,-1.0,946.037,1.54987,1292 +294,search,4976.03,0.91436,0.1107,3.936,1.54987,1292 +295,insert,135.674,-1.0,-1.0,1281.81,1.63765,1296 +296,search,5154.35,0.91618,0.110061,1228.32,1.63729,1297 +297,insert,2.566,-1.0,-1.0,1224.61,1.63849,1298 +298,search,5128.09,0.91607,0.11029,1237.42,1.63783,1300 +299,insert,40.869,-1.0,-1.0,4.58,1.66244,1300 +300,search,5221.84,0.91928,0.107226,1236.41,1.66334,1301 +301,insert,342.361,-1.0,-1.0,2219.76,1.9198,1330 +302,search,5949.96,0.93459,0.0944572,1963.29,1.92088,1348 +303,insert,30.827,-1.0,-1.0,4.143,1.94289,1348 +304,search,5897.76,0.93404,0.0949337,3.926,1.94289,1348 +305,insert,189.113,-1.0,-1.0,1823.75,2.10613,1357 +306,search,6193.41,0.93516,0.0947539,1749.5,2.10772,1367 +307,insert,15.094,-1.0,-1.0,1561.69,2.11762,1370 +308,search,6145.15,0.93549,0.0941362,1690.04,2.11715,1384 +309,insert,4.601,-1.0,-1.0,1372.15,2.12031,1385 +310,search,6245.96,0.93578,0.0939642,1411.44,2.11805,1388 +311,insert,6.952,-1.0,-1.0,4.377,2.12375,1388 +312,search,6145.32,0.93554,0.0942885,4.247,2.12375,1388 +313,insert,19.971,-1.0,-1.0,1370.89,2.1401,1389 +314,search,6205.67,0.93585,0.0941606,4.252,2.1401,1389 +315,insert,4.039,-1.0,-1.0,3.997,2.14185,1389 +316,search,6419.22,0.93569,0.094371,4.699,2.14185,1389 +317,insert,28.355,-1.0,-1.0,1478.38,2.15897,1394 +318,search,9048.61,0.93606,0.0941628,6.876,2.15897,1394 +319,insert,393.965,-1.0,-1.0,4162.67,2.37779,1429 +320,search,6079.68,0.93679,0.0933401,1922.31,2.37782,1442 +321,insert,26.174,-1.0,-1.0,1705.65,2.39405,1447 +322,search,5993.44,0.93659,0.093449,1691.63,2.39595,1449 +323,insert,56.318,-1.0,-1.0,1752.1,2.44048,1456 +324,search,6670.65,0.93745,0.0928764,1588.98,2.44089,1460 +325,insert,1009.93,-1.0,-1.0,2742.26,2.6558,1478 +326,search,7103.15,0.93947,0.0913953,2145.77,2.65662,1493 +327,insert,37.145,-1.0,-1.0,1918.03,2.68409,1498 +328,search,7141.57,0.93954,0.0911321,2061.45,2.68614,1520 +329,insert,5.497,-1.0,-1.0,1620.05,2.69066,1521 +330,search,7159.38,0.93986,0.0908158,1876.56,2.69134,1531 +331,insert,29.237,-1.0,-1.0,1705.85,2.71106,1534 +332,search,7165.61,0.93955,0.0915084,1662.81,2.71149,1535 +333,insert,2.349,-1.0,-1.0,5.757,2.71295,1535 +334,search,7256.15,0.93952,0.0914037,6.233,2.71295,1535 +335,insert,24.585,-1.0,-1.0,1738.52,2.72987,1538 +336,search,7283.3,0.93955,0.0912567,6.064,2.72987,1538 +337,insert,15.998,-1.0,-1.0,6.016,2.73887,1538 +338,search,7107.19,0.93988,0.0908077,6.136,2.73887,1538 +339,insert,32.76,-1.0,-1.0,1668.07,2.75751,1539 +340,search,7176.39,0.94001,0.0906378,5.981,2.75751,1539 +341,insert,3.654,-1.0,-1.0,1757.29,2.76077,1540 +342,search,7197.71,0.94023,0.0905341,1742.13,2.7606,1543 +343,insert,15.744,-1.0,-1.0,1743.88,2.77506,1545 +344,search,7259.57,0.94017,0.0907631,1699.47,2.77449,1547 +345,insert,20.238,-1.0,-1.0,1742.3,2.78993,1549 +346,search,7189.16,0.94045,0.0906642,6.579,2.78993,1549 +347,insert,255.264,-1.0,-1.0,4444.04,2.99918,1601 +348,search,7619.72,0.94147,0.0891616,2549.61,2.99675,1619 +349,insert,25.204,-1.0,-1.0,1930.91,3.01304,1622 +350,search,7594.81,0.9419,0.0885028,7.97,3.01304,1622 +351,insert,249.628,-1.0,-1.0,3884.1,3.19111,1646 +352,search,7823.16,0.94124,0.0893777,2516.78,3.19011,1657 +353,insert,39.868,-1.0,-1.0,2175.3,3.21129,1662 +354,search,7841.26,0.94155,0.0893639,2356.58,3.21083,1671 +355,insert,255.809,-1.0,-1.0,3238.49,3.36661,1696 +356,search,8157,0.94353,0.0873895,2757.86,3.3669,1709 +357,insert,16.516,-1.0,-1.0,2141.51,3.37405,1710 +358,search,8196.74,0.94368,0.0871058,2172.97,3.37399,1711 +359,insert,6.28,-1.0,-1.0,8.941,3.37673,1711 +360,search,8182.95,0.9436,0.087212,9.329,3.37673,1711 +361,insert,39.374,-1.0,-1.0,2239.98,3.40689,1714 +362,search,8288.73,0.94414,0.0865814,9.074,3.40689,1714 +363,insert,13.072,-1.0,-1.0,2209.23,3.41321,1715 +364,search,8192.05,0.94422,0.0865552,9.536,3.41321,1715 +365,insert,33.758,-1.0,-1.0,2251.66,3.43765,1717 +366,search,8231.47,0.94443,0.0862566,9.19,3.43765,1717 +367,insert,17.864,-1.0,-1.0,2237.19,3.45043,1720 +368,search,8278.38,0.94442,0.0862554,9.113,3.45043,1720 +369,insert,37.219,-1.0,-1.0,2301.8,3.4769,1723 +370,search,8188.26,0.94504,0.0854552,9.068,3.4769,1723 +371,insert,7.427,-1.0,-1.0,8.598,3.48077,1723 +372,search,7991.94,0.94476,0.0857052,9.132,3.48077,1723 +373,insert,33.404,-1.0,-1.0,2369.08,3.49968,1727 +374,search,8239.68,0.94514,0.0849398,8.932,3.49968,1727 +375,insert,22.641,-1.0,-1.0,2266.81,3.51311,1728 +376,search,8128.52,0.94516,0.0849293,8.904,3.51311,1728 +377,insert,38.792,-1.0,-1.0,2496.63,3.54356,1735 +378,search,8106.28,0.94565,0.084695,2304.79,3.54381,1736 +379,insert,4.017,-1.0,-1.0,8.91,3.54592,1736 +380,search,8186.97,0.94542,0.0848749,9.557,3.54592,1736 +381,insert,14.016,-1.0,-1.0,2346.47,3.5531,1738 +382,search,8403.18,0.94568,0.0846151,9.314,3.5531,1738 +383,insert,20.972,-1.0,-1.0,2439.98,3.56668,1743 +384,search,8430.89,0.94555,0.0847045,9.121,3.56668,1743 +385,delete,8.564,-1.0,-1.0,8.754,3.56653,1743 +386,search,8461.71,0.94561,0.0847053,8.891,3.56653,1743 +387,delete,11.953,-1.0,-1.0,8.658,3.56565,1743 +388,search,8441.58,0.94572,0.0847462,8.768,3.56565,1743 +389,delete,11.388,-1.0,-1.0,8.617,3.56441,1743 +390,search,8337.02,0.94547,0.0850283,9,3.56441,1743 +391,delete,48.96,-1.0,-1.0,8.779,3.54212,1743 +392,search,8217.54,0.94531,0.0852318,9.452,3.54212,1743 +393,delete,35.803,-1.0,-1.0,9.08,3.54039,1743 +394,search,8132.38,0.9451,0.0853607,9.538,3.54039,1743 +395,delete,23.113,-1.0,-1.0,8.799,3.53324,1743 +396,search,8170.82,0.94486,0.0856316,9.218,3.53324,1743 +397,delete,84.115,-1.0,-1.0,8.864,3.50095,1743 +398,search,8167.56,0.94499,0.0855088,9.068,3.50095,1743 +399,delete,3.86,-1.0,-1.0,9.159,3.50051,1743 +400,search,8188.63,0.94505,0.0854564,9.004,3.50051,1743 +401,delete,11.824,-1.0,-1.0,8.569,3.49808,1743 +402,search,8171.72,0.94511,0.0854112,9.037,3.49808,1743 +403,delete,185.28,-1.0,-1.0,9.08,3.41189,1743 +404,search,8066.22,0.94477,0.0858122,8.948,3.41189,1743 +405,delete,33.028,-1.0,-1.0,8.793,3.40359,1743 +406,search,7962.33,0.9457,0.0849701,9.02,3.40359,1743 +407,delete,57.118,-1.0,-1.0,9.011,3.38102,1743 +408,search,7736.92,0.94591,0.0847342,9.359,3.38102,1743 +409,delete,129.271,-1.0,-1.0,9.086,3.29733,1743 +410,search,7783.45,0.94611,0.0845069,9.489,3.29733,1743 +411,delete,169.371,-1.0,-1.0,9.425,3.22559,1743 +412,search,7569.65,0.94508,0.0851739,9.053,3.22559,1743 +413,delete,15.871,-1.0,-1.0,8.689,3.22075,1743 +414,search,7633.09,0.94494,0.0852703,9.107,3.22075,1743 +415,delete,50.014,-1.0,-1.0,8.974,3.20189,1743 +416,search,7564.91,0.94486,0.0853977,9.053,3.20189,1743 +417,delete,125.898,-1.0,-1.0,8.928,3.13551,1743 +418,search,7473.87,0.94499,0.0851689,9.02,3.13551,1743 +419,delete,16.642,-1.0,-1.0,8.621,3.13185,1743 +420,search,7446.49,0.94476,0.0854248,8.919,3.13185,1743 +421,delete,13.671,-1.0,-1.0,8.654,3.12316,1743 +422,search,7414.94,0.94473,0.085468,8.847,3.12316,1743 +423,delete,90.278,-1.0,-1.0,8.913,3.05712,1743 +424,search,7308.5,0.94484,0.0849506,9.036,3.05712,1743 +425,delete,16.508,-1.0,-1.0,8.582,3.05061,1743 +426,search,7247.53,0.94486,0.0850221,9.53,3.05061,1743 +427,delete,46.729,-1.0,-1.0,8.757,3.04079,1743 +428,search,7225.04,0.94413,0.0860246,9.381,3.04079,1743 +429,delete,293.791,-1.0,-1.0,9.154,2.88888,1743 +430,search,6833.66,0.938,0.0915924,9.24,2.88888,1743 +431,delete,65.129,-1.0,-1.0,8.971,2.85156,1743 +432,search,6812.9,0.93821,0.0915828,9.11,2.85156,1743 +433,delete,137.132,-1.0,-1.0,8.864,2.77189,1743 +434,search,6720.24,0.93767,0.0916961,9.095,2.77189,1743 +435,delete,77.132,-1.0,-1.0,9.056,2.72036,1743 +436,search,6633.73,0.937,0.0925581,9.081,2.72036,1743 +437,delete,10.144,-1.0,-1.0,8.645,2.71365,1743 +438,search,6637.8,0.93698,0.0926248,9.126,2.71365,1743 +439,delete,70.767,-1.0,-1.0,8.921,2.65888,1743 +440,search,6568.08,0.93669,0.0929047,9.081,2.65888,1743 +441,delete,19.925,-1.0,-1.0,8.767,2.6466,1743 +442,search,6531.15,0.93662,0.0927499,8.931,2.6466,1743 +443,delete,17.557,-1.0,-1.0,8.776,2.63339,1743 +444,search,6494.21,0.93692,0.092521,8.908,2.63339,1743 +445,delete,29.027,-1.0,-1.0,8.56,2.61487,1743 +446,search,6387.8,0.93694,0.0923465,9.129,2.61487,1743 +447,delete,228.642,-1.0,-1.0,8.962,2.45733,1743 +448,search,6272.01,0.93607,0.0926135,9.438,2.45733,1743 +449,delete,42.026,-1.0,-1.0,8.941,2.44289,1743 +450,search,6266.65,0.9356,0.0929919,9.422,2.44289,1743 +451,delete,72.88,-1.0,-1.0,8.977,2.40484,1743 +452,search,6210.45,0.93454,0.0941704,9.185,2.40484,1743 +453,delete,185.323,-1.0,-1.0,8.956,2.28499,1743 +454,search,6034.5,0.9339,0.0942232,9.106,2.28499,1743 +455,delete,32.683,-1.0,-1.0,8.747,2.26945,1743 +456,search,6051.89,0.93322,0.0946883,9.073,2.26945,1743 +457,delete,6.434,-1.0,-1.0,8.665,2.26532,1743 +458,search,6048.9,0.93316,0.0947603,9.432,2.26532,1743 +459,delete,27.906,-1.0,-1.0,8.803,2.24885,1743 +460,search,6003.24,0.93325,0.0947971,9.04,2.24885,1743 +461,delete,4.568,-1.0,-1.0,8.88,2.24742,1743 +462,search,6016.16,0.93298,0.0950661,8.971,2.24742,1743 +463,delete,37.349,-1.0,-1.0,8.815,2.22261,1743 +464,search,5912.53,0.93337,0.0947664,9.061,2.22261,1743 +465,delete,17.706,-1.0,-1.0,8.576,2.21194,1743 +466,search,5922,0.93332,0.0947816,8.997,2.21194,1743 +467,delete,24.231,-1.0,-1.0,8.554,2.1986,1743 +468,search,5873.96,0.9332,0.0950936,9.069,2.1986,1743 +469,delete,12.903,-1.0,-1.0,8.653,2.18832,1743 diff --git a/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.3.csv b/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.3.csv new file mode 100644 index 00000000..039394ce --- /dev/null +++ b/scripts/big_ann_perf_numbers/scan_using_batching_250_aps_recall_0.9_search_0.3.csv @@ -0,0 +1,1280 @@ +step_num,step_type,latency_ms,recall_mean,recall_std_dev,mainteance_ms,index_mem_gb +2,search,3748.95,0.91201,0.102646,2.974,0.0183461 +3,insert,13.614,-1.0,-1.0,0.0,0.0223849 +4,search,3057.03,0.91992,0.0979933,23.939,0.0224592 +5,insert,36.075,-1.0,-1.0,0.0,0.0330443 +6,search,3121.34,0.95483,0.0772748,99.381,0.0329754 +7,insert,35.987,-1.0,-1.0,0.0,0.0423855 +8,search,3241.03,0.95122,0.0804345,149.885,0.0422513 +9,insert,5.164,-1.0,-1.0,0.0,0.0442505 +10,search,3346.96,0.95818,0.0725195,164.741,0.0442631 +11,insert,13.129,-1.0,-1.0,0.0,0.0495251 +12,search,3459.44,0.95472,0.0765104,202.715,0.0493472 +13,insert,32.082,-1.0,-1.0,0.0,0.0607594 +14,search,3710.29,0.94835,0.0813495,298.256,0.0605403 +15,insert,35.712,-1.0,-1.0,0.0,0.0692233 +16,search,3973.52,0.946,0.0820631,297.233,0.0692376 +17,insert,4.884,-1.0,-1.0,0.0,0.0713612 +18,search,4212.9,0.94276,0.084701,278.457,0.0712972 +19,insert,48.047,-1.0,-1.0,0.0,0.0780582 +20,search,4424.03,0.94469,0.0831914,250.772,0.0779325 +21,insert,447.638,-1.0,-1.0,0.0,0.19733 +22,search,4847.38,0.94669,0.0799093,1227.74,0.196926 +23,insert,457.186,-1.0,-1.0,0.0,0.321974 +24,search,5262.17,0.93336,0.0925517,1921.82,0.321603 +25,insert,56.324,-1.0,-1.0,0.0,0.340791 +26,search,7364.43,0.92558,0.097945,2473.26,0.340803 +27,insert,49.323,-1.0,-1.0,0.0,0.353285 +28,search,9179.81,0.92288,0.09977,1740.47,0.353604 +29,insert,91.165,-1.0,-1.0,0.0,0.380443 +30,search,9166.82,0.92855,0.096077,652.576,0.380629 +31,insert,619.055,-1.0,-1.0,0.0,0.544489 +32,search,11505.4,0.93309,0.093111,4951.6,0.544117 +33,insert,86.913,-1.0,-1.0,0.0,0.566514 +34,search,13416.8,0.93383,0.0926381,3484.35,0.566909 +35,insert,70.459,-1.0,-1.0,0.0,0.582114 +36,search,12470.2,0.93599,0.0915027,1314.85,0.582573 +37,insert,114.705,-1.0,-1.0,0.0,0.603454 +38,search,15553,0.93783,0.0899942,958.943,0.603449 +39,insert,15.146,-1.0,-1.0,0.0,0.606742 +40,search,15617.8,0.93755,0.090397,404.489,0.606713 +41,insert,65.483,-1.0,-1.0,0.0,0.621102 +42,search,15531.9,0.93842,0.0896568,796.485,0.621644 +43,insert,19.609,-1.0,-1.0,0.0,0.625649 +44,search,15454.8,0.93934,0.0891817,475.391,0.625488 +45,insert,349.031,-1.0,-1.0,0.0,0.640433 +46,search,12608.9,0.9409,0.0880706,776.315,0.640496 +47,insert,472.393,-1.0,-1.0,0.0,0.741606 +48,search,16275.3,0.94461,0.0855662,3697.76,0.740908 +49,insert,58.978,-1.0,-1.0,0.0,0.756258 +50,search,15812.3,0.94578,0.0850588,2373.69,0.756896 +51,insert,650.762,-1.0,-1.0,0.0,0.893122 +52,search,18486.4,0.95167,0.0802847,9590.41,0.893064 +53,insert,105.303,-1.0,-1.0,0.0,0.912425 +54,search,20556.1,0.95131,0.0810455,4045.01,0.912818 +55,insert,659.937,-1.0,-1.0,0.0,1.05328 +56,search,23672.2,0.95728,0.0759152,9180.75,1.05401 +57,insert,59.095,-1.0,-1.0,0.0,1.0632 +58,search,23032.5,0.95659,0.0758089,3113.05,1.06259 +59,insert,481.023,-1.0,-1.0,0.0,1.15957 +60,search,25631.6,0.95784,0.0743588,4058.99,1.15849 +61,insert,18.897,-1.0,-1.0,0.0,1.16262 +62,search,26410.8,0.95395,0.08027,2285.74,1.1637 +63,insert,5.858,-1.0,-1.0,0.0,1.16503 +64,search,26971,0.95453,0.0790186,1485.59,1.16426 +65,insert,173.27,-1.0,-1.0,0.0,1.19352 +66,search,25436.5,0.95582,0.0772086,2311.86,1.19431 +67,insert,118.377,-1.0,-1.0,0.0,1.21381 +68,search,27590.2,0.95656,0.0762358,2547.71,1.21439 +69,insert,139.229,-1.0,-1.0,0.0,1.23671 +70,search,25447,0.95742,0.0753606,1361.89,1.23639 +71,insert,41.005,-1.0,-1.0,0.0,1.24248 +72,search,29140.1,0.95763,0.0752386,1632.31,1.24257 +73,insert,21.114,-1.0,-1.0,0.0,1.24584 +74,search,28418.6,0.95757,0.0753229,1344.99,1.24576 +75,insert,77.12,-1.0,-1.0,0.0,1.25383 +76,search,28175.5,0.95768,0.0750396,1643.4,1.25361 +77,insert,93.658,-1.0,-1.0,0.0,1.2645 +78,search,28797.6,0.9576,0.0751443,989.816,1.26461 +79,insert,845.002,-1.0,-1.0,0.0,1.29217 +80,search,22415.4,0.95776,0.0749976,1373.19,1.29238 +81,insert,91.654,-1.0,-1.0,0.0,1.3053 +82,search,29191.4,0.95858,0.0737777,1392.21,1.30562 +83,insert,38.357,-1.0,-1.0,0.0,1.31189 +84,search,29792,0.95885,0.0733661,1622.57,1.31128 +85,insert,104.426,-1.0,-1.0,0.0,1.3277 +86,search,29759.9,0.9593,0.0727576,1594.69,1.32781 +87,insert,1117.91,-1.0,-1.0,0.0,1.52264 +88,search,30787.1,0.96327,0.0676942,15582.9,1.52422 +89,insert,1019.8,-1.0,-1.0,0.0,1.68107 +90,search,34169.4,0.96667,0.06386,16086.1,1.68166 +91,insert,122.495,-1.0,-1.0,0.0,1.69657 +92,search,32976.8,0.96678,0.0644734,4010.37,1.69663 +93,insert,827.294,-1.0,-1.0,0.0,1.80078 +94,search,37109.2,0.96712,0.0638375,5752.57,1.8006 +95,insert,47.05,-1.0,-1.0,0.0,1.80781 +96,search,37810.4,0.96749,0.0636266,2509.31,1.80742 +97,insert,31.976,-1.0,-1.0,0.0,1.81148 +98,search,39507,0.96762,0.0634205,1425.94,1.81135 +99,insert,27.889,-1.0,-1.0,0.0,1.81418 +100,search,40875.2,0.96765,0.0633626,1271.16,1.81424 +101,insert,132.357,-1.0,-1.0,0.0,1.82705 +102,search,40646.6,0.96791,0.0630382,1493.15,1.82677 +103,insert,43.794,-1.0,-1.0,0.0,1.83254 +104,search,39604,0.96808,0.0628118,1488.1,1.83318 +105,insert,35.447,-1.0,-1.0,0.0,1.83698 +106,search,38631.5,0.96815,0.0628426,1296.73,1.83709 +107,insert,66.249,-1.0,-1.0,0.0,1.84299 +108,search,38677.8,0.96817,0.0628348,1322.95,1.84298 +109,insert,1287.6,-1.0,-1.0,0.0,2.0006 +110,search,41152.5,0.96984,0.0606519,12820,1.99993 +111,insert,91.233,-1.0,-1.0,0.0,2.01235 +112,search,42773,0.97048,0.0598906,4296.84,2.01228 +113,insert,55.928,-1.0,-1.0,0.0,2.01788 +114,search,42800.4,0.9704,0.0599167,1953.75,2.01798 +115,insert,128.33,-1.0,-1.0,0.0,2.03031 +116,search,44993.7,0.97085,0.0594764,1777.98,2.03038 +117,insert,45.136,-1.0,-1.0,0.0,2.0356 +118,search,44865.8,0.97094,0.0592616,1508.97,2.0352 +119,insert,17.356,-1.0,-1.0,0.0,2.0371 +120,search,44654.8,0.97098,0.0593001,1473.83,2.03718 +121,insert,69.592,-1.0,-1.0,0.0,2.04358 +122,search,41579.5,0.97104,0.0591428,1523.79,2.04354 +123,insert,1108.95,-1.0,-1.0,0.0,2.16608 +124,search,41835.3,0.97211,0.0581344,5953.15,2.16666 +125,insert,198.112,-1.0,-1.0,0.0,2.1864 +126,search,44581,0.97284,0.0573126,4490.63,2.18669 +127,insert,182.593,-1.0,-1.0,0.0,2.208 +128,search,45031.5,0.97353,0.0564313,3359.55,2.20838 +129,delete,14.156,-1.0,-1.0,0.0,2.20694 +130,search,47893.3,0.9736,0.0564543,1767.94,2.20686 +131,delete,4.495,-1.0,-1.0,0.0,2.20668 +132,search,47533.1,0.97366,0.0563439,1608.55,2.2067 +133,delete,13.714,-1.0,-1.0,0.0,2.20649 +134,search,42035.7,0.97365,0.0564712,102.593,2.20649 +135,delete,45.208,-1.0,-1.0,0.0,2.20436 +136,search,46171.2,0.97401,0.0559797,99.578,2.20436 +137,delete,11.148,-1.0,-1.0,0.0,2.20434 +138,search,46136.1,0.97397,0.0560673,95.865,2.20434 +139,delete,15.03,-1.0,-1.0,0.0,2.20232 +140,search,46758.5,0.97399,0.056044,1557.99,2.20239 +141,delete,20.302,-1.0,-1.0,0.0,2.19794 +142,search,46753.5,0.97405,0.0559093,1597.17,2.19779 +143,delete,16.636,-1.0,-1.0,0.0,2.19417 +144,search,44369.1,0.97399,0.056044,100.448,2.19417 +145,delete,5.793,-1.0,-1.0,0.0,2.19318 +146,search,48659.8,0.97388,0.0561804,99.627,2.19318 +147,delete,27.4,-1.0,-1.0,0.0,2.19246 +148,search,47121.5,0.97391,0.0561853,95.501,2.19246 +149,delete,230.619,-1.0,-1.0,0.0,2.14778 +150,search,46830.8,0.97451,0.0557837,94.038,2.14778 +151,delete,188.4,-1.0,-1.0,0.0,2.10792 +152,search,44544.9,0.97429,0.0560772,98.653,2.10792 +153,delete,51.397,-1.0,-1.0,0.0,2.09341 +154,search,45344.8,0.97403,0.0565428,100.541,2.09341 +155,delete,49.971,-1.0,-1.0,0.0,2.08959 +156,search,46860.4,0.97399,0.0564352,97.205,2.08959 +157,delete,72.512,-1.0,-1.0,0.0,2.07699 +158,search,42812.6,0.97384,0.0566412,92.849,2.07699 +159,delete,318.108,-1.0,-1.0,0.0,1.95404 +160,search,42129.9,0.97344,0.0567896,98.321,1.95404 +161,delete,82.235,-1.0,-1.0,0.0,1.9416 +162,search,47944.9,0.97343,0.0567033,100.236,1.9416 +163,delete,59.083,-1.0,-1.0,0.0,1.93227 +164,search,47539.9,0.97344,0.0567191,101.423,1.93227 +165,delete,69.325,-1.0,-1.0,0.0,1.92234 +166,search,46899,0.97338,0.0568155,92.307,1.92234 +167,delete,9.188,-1.0,-1.0,0.0,1.92008 +168,search,46893.3,0.97331,0.0569972,96.742,1.92008 +169,delete,34.925,-1.0,-1.0,0.0,1.9131 +170,search,43859.7,0.97323,0.0570165,100.664,1.9131 +171,delete,30.817,-1.0,-1.0,0.0,1.90997 +172,search,45038.7,0.97314,0.0570861,98.881,1.90997 +173,delete,80.717,-1.0,-1.0,0.0,1.89786 +174,search,45515.8,0.97287,0.0574233,93.91,1.89786 +175,delete,191.271,-1.0,-1.0,0.0,1.8273 +176,search,46979.7,0.97284,0.0574695,94.638,1.8273 +177,delete,32.047,-1.0,-1.0,0.0,1.82037 +178,search,47828.9,0.97282,0.0574753,99.528,1.82037 +179,delete,333.683,-1.0,-1.0,0.0,1.71742 +180,search,47552.2,0.97152,0.0592729,100.448,1.71742 +181,delete,66.003,-1.0,-1.0,0.0,1.70467 +182,search,39909.9,0.97141,0.0593485,95.321,1.70467 +183,delete,183.266,-1.0,-1.0,0.0,1.63303 +184,search,46210.6,0.969,0.0620927,93.357,1.63303 +185,delete,21.7,-1.0,-1.0,0.0,1.62927 +186,search,45334.4,0.96895,0.0622347,99.5,1.62927 +187,delete,249.353,-1.0,-1.0,0.0,1.54601 +188,search,45254.6,0.97058,0.060474,100,1.54601 +189,delete,29.596,-1.0,-1.0,0.0,1.54291 +190,search,45044.4,0.97052,0.0605272,95.938,1.54291 +191,delete,8.596,-1.0,-1.0,0.0,1.54152 +192,search,42978.5,0.97054,0.0604697,93.578,1.54152 +193,delete,96.44,-1.0,-1.0,0.0,1.51376 +194,search,45938.5,0.96992,0.0611991,100.14,1.51376 +195,delete,86.478,-1.0,-1.0,0.0,1.49775 +196,search,46168.6,0.96945,0.0614333,99.687,1.49775 +197,delete,81.924,-1.0,-1.0,0.0,1.48648 +198,search,46152.7,0.96933,0.0615037,97.671,1.48648 +199,delete,31.306,-1.0,-1.0,0.0,1.48214 +200,search,44959,0.9692,0.0616903,93.334,1.48214 +201,delete,10.808,-1.0,-1.0,0.0,1.47922 +202,search,42579.1,0.96918,0.0616643,96.173,1.47922 +203,delete,38.911,-1.0,-1.0,0.0,1.47295 +204,search,44968.5,0.96917,0.0618432,99.587,1.47295 +205,delete,63.185,-1.0,-1.0,0.0,1.46429 +206,search,44950.9,0.96918,0.0617454,98.93,1.46429 +207,delete,89.908,-1.0,-1.0,0.0,1.4455 +208,search,40992.5,0.9692,0.0615604,92.393,1.4455 +209,delete,27.98,-1.0,-1.0,0.0,1.43658 +210,search,46925.7,0.96915,0.0616568,98.977,1.43658 +211,delete,27.568,-1.0,-1.0,0.0,1.4326 +212,search,44245.7,0.96899,0.0618995,100.173,1.4326 +213,delete,49.308,-1.0,-1.0,0.0,1.42486 +214,search,45737,0.96883,0.0621111,98.873,1.42486 +215,delete,437.63,-1.0,-1.0,0.0,1.26778 +216,search,46182.6,0.96734,0.0638725,94.82,1.26778 +217,delete,282.346,-1.0,-1.0,0.0,1.16504 +218,search,46499.6,0.96587,0.0657298,94.542,1.16504 +219,delete,47.356,-1.0,-1.0,0.0,1.15448 +220,search,41070.8,0.96551,0.0662127,98.867,1.15448 +221,delete,304.342,-1.0,-1.0,0.0,1.05495 +222,search,44396.1,0.96588,0.0658488,99.76,1.05495 +223,delete,40.401,-1.0,-1.0,0.0,1.04851 +224,search,41418.6,0.96542,0.0664561,92.5,1.04851 +225,delete,10.4,-1.0,-1.0,0.0,1.04571 +226,search,48016.6,0.9653,0.0667129,95.004,1.04571 +227,delete,12.163,-1.0,-1.0,0.0,1.04379 +228,search,43833.9,0.96527,0.0667462,101.667,1.04379 +229,delete,66.79,-1.0,-1.0,0.0,1.03283 +230,search,46768.6,0.9647,0.0669362,100.895,1.03283 +231,delete,37.178,-1.0,-1.0,0.0,1.02685 +232,search,44791.5,0.96453,0.0671244,95.885,1.02685 +233,delete,13.162,-1.0,-1.0,0.0,1.02417 +234,search,42046.8,0.96435,0.0671891,93.687,1.02417 +235,delete,14.466,-1.0,-1.0,0.0,1.02058 +236,search,46180.7,0.96436,0.0671891,101.457,1.02058 +237,delete,352.686,-1.0,-1.0,0.0,0.910679 +238,search,45705.5,0.96379,0.0683987,100.526,0.910679 +239,delete,56.354,-1.0,-1.0,0.0,0.898169 +240,search,44704.5,0.96322,0.0688468,95.675,0.898169 +241,delete,18.879,-1.0,-1.0,0.0,0.894298 +242,search,42921.1,0.96317,0.0689725,93.777,0.894298 +243,delete,40.906,-1.0,-1.0,0.0,0.884516 +244,search,43429.9,0.96248,0.0698042,101.425,0.884516 +245,delete,40.37,-1.0,-1.0,0.0,0.879084 +246,search,45589.7,0.9623,0.0699525,100.17,0.879084 +247,delete,13.3,-1.0,-1.0,0.0,0.877764 +248,search,46097.8,0.9622,0.069999,95.793,0.877764 +249,delete,20.973,-1.0,-1.0,0.0,0.873799 +250,search,45648.7,0.96206,0.0702492,93.506,0.873799 +251,delete,316.283,-1.0,-1.0,0.0,0.758317 +252,search,43881.1,0.962,0.069978,100.371,0.758317 +253,delete,84.264,-1.0,-1.0,0.0,0.743387 +254,search,43982,0.96163,0.070281,99.905,0.743387 +255,delete,88.112,-1.0,-1.0,0.0,0.724221 +256,search,46118.5,0.96034,0.0716744,96.78,0.724221 +257,insert,28.775,-1.0,-1.0,0.0,0.725929 +258,search,45826.2,0.96033,0.0716393,93.585,0.725929 +259,insert,75.955,-1.0,-1.0,0.0,0.732452 +260,search,43702.3,0.96063,0.0715502,556.136,0.732482 +261,insert,9.727,-1.0,-1.0,0.0,0.732971 +262,search,45614.8,0.96076,0.0714364,101.135,0.732971 +263,insert,436.32,-1.0,-1.0,0.0,0.772987 +264,search,44422.3,0.9625,0.0698888,680.705,0.77345 +265,insert,161.7,-1.0,-1.0,0.0,0.792564 +266,search,41151.5,0.96411,0.0680986,612.149,0.792599 +267,insert,97.201,-1.0,-1.0,0.0,0.803289 +268,search,45527.3,0.96446,0.0675497,646.664,0.803533 +269,insert,997.968,-1.0,-1.0,0.0,0.898864 +270,search,46676.1,0.96575,0.0661569,1110.08,0.898462 +271,insert,13.314,-1.0,-1.0,0.0,0.899921 +272,search,45845.7,0.96555,0.0665912,907.718,0.899796 +273,insert,69.348,-1.0,-1.0,0.0,0.907798 +274,search,45874,0.96518,0.0668003,786.922,0.907806 +275,insert,1399.95,-1.0,-1.0,0.0,1.06385 +276,search,42379.1,0.9662,0.0656944,2410.53,1.06356 +277,insert,117.428,-1.0,-1.0,0.0,1.07516 +278,search,48260.9,0.96643,0.0655468,1257.04,1.07514 +279,insert,91.76,-1.0,-1.0,0.0,1.08375 +280,search,47385.9,0.96645,0.065664,895.679,1.08389 +281,insert,1014.7,-1.0,-1.0,0.0,1.20857 +282,search,48567,0.96762,0.0642821,1520.85,1.20871 +283,insert,1448.68,-1.0,-1.0,0.0,1.38951 +284,search,50101.5,0.96954,0.0613204,3415.98,1.38894 +285,insert,39.744,-1.0,-1.0,0.0,1.3944 +286,search,50470.5,0.96983,0.0612793,2166.39,1.39397 +287,insert,157.815,-1.0,-1.0,0.0,1.40931 +288,search,51165.7,0.97002,0.061118,1318.8,1.40939 +289,insert,1245.85,-1.0,-1.0,0.0,1.54123 +290,search,46749.8,0.97101,0.0602915,2214.29,1.54109 +291,insert,91.542,-1.0,-1.0,0.0,1.55107 +292,search,51079.1,0.97107,0.0603361,1655.28,1.55017 +293,insert,64.156,-1.0,-1.0,0.0,1.55836 +294,search,49763.3,0.97116,0.0603533,1349.02,1.55867 +295,insert,802.419,-1.0,-1.0,0.0,1.64895 +296,search,52163.4,0.9718,0.059658,1855.32,1.64769 +297,insert,16.701,-1.0,-1.0,0.0,1.64975 +298,search,51297.5,0.97152,0.0599441,1471.45,1.65015 +299,insert,243.725,-1.0,-1.0,0.0,1.67582 +300,search,52293.7,0.97301,0.0581291,1439.4,1.67535 +301,insert,1958.71,-1.0,-1.0,0.0,1.92926 +302,search,52722.5,0.97937,0.0501553,9517.4,1.92937 +303,insert,175.869,-1.0,-1.0,0.0,1.95048 +304,search,56325.8,0.97915,0.0506427,5587.41,1.95031 +305,insert,1226.01,-1.0,-1.0,0.0,2.11169 +306,search,55919.5,0.97917,0.0506267,5253.28,2.11234 +307,insert,142.412,-1.0,-1.0,0.0,2.12458 +308,search,56281.6,0.97936,0.0502403,2955.17,2.12447 +309,insert,36.869,-1.0,-1.0,0.0,2.12738 +310,search,52357.2,0.97958,0.050034,2019.22,2.12809 +311,insert,94.537,-1.0,-1.0,0.0,2.13575 +312,search,57777,0.97963,0.050025,1751.14,2.13554 +313,insert,226.521,-1.0,-1.0,0.0,2.15331 +314,search,56996.3,0.97973,0.0497817,1780.44,2.15346 +315,insert,24.795,-1.0,-1.0,0.0,2.15499 +316,search,57832.8,0.97967,0.0499607,1642.48,2.1549 +317,insert,223.474,-1.0,-1.0,0.0,2.1722 +318,search,58372.7,0.97985,0.0499936,1716.14,2.1721 +319,insert,2170.75,-1.0,-1.0,0.0,2.38896 +320,search,58311.1,0.98095,0.0482529,13772.1,2.38966 +321,insert,170.587,-1.0,-1.0,0.0,2.40691 +322,search,57174.5,0.98152,0.047651,6119.99,2.40697 +323,insert,415.353,-1.0,-1.0,0.0,2.45297 +324,search,61557.1,0.98174,0.0475498,4148.58,2.45253 +325,insert,3190.13,-1.0,-1.0,0.0,2.66782 +326,search,62837.9,0.98259,0.0467781,8161.84,2.66587 +327,insert,313.08,-1.0,-1.0,0.0,2.69634 +328,search,62670.4,0.98284,0.0465157,5978.04,2.69729 +329,insert,33.606,-1.0,-1.0,0.0,2.70057 +330,search,59183.9,0.98301,0.0460707,3229,2.7012 +331,insert,180.27,-1.0,-1.0,0.0,2.71929 +332,search,59201.7,0.98316,0.0458985,2539.1,2.71942 +333,insert,4.696,-1.0,-1.0,0.0,2.72008 +334,search,60260.8,0.9832,0.0458696,2014.68,2.71992 +335,insert,176.962,-1.0,-1.0,0.0,2.73682 +336,search,66724.5,0.98329,0.0458031,2465.07,2.73709 +337,insert,88.737,-1.0,-1.0,0.0,2.74519 +338,search,65475.8,0.98331,0.0457887,2120.8,2.74517 +339,insert,218.945,-1.0,-1.0,0.0,2.76356 +340,search,67689.1,0.98345,0.0455996,2305.57,2.76398 +341,insert,32.414,-1.0,-1.0,0.0,2.76749 +342,search,60456.6,0.98351,0.0454904,2073.42,2.76748 +343,insert,152.495,-1.0,-1.0,0.0,2.78261 +344,search,65260.8,0.98347,0.0457173,2217.48,2.78256 +345,insert,166.077,-1.0,-1.0,0.0,2.79996 +346,search,65432.6,0.98351,0.0456222,2305.09,2.79996 +347,insert,1696.33,-1.0,-1.0,0.0,3.00093 +348,search,68163.8,0.98394,0.0447218,19666.5,3.00085 +349,insert,184.923,-1.0,-1.0,0.0,3.02128 +350,search,67997.7,0.98399,0.0446416,6377.1,3.02092 +351,insert,1516.47,-1.0,-1.0,0.0,3.20385 +352,search,67522.3,0.98453,0.0439062,12689.3,3.201 +353,insert,238.252,-1.0,-1.0,0.0,3.21996 +354,search,69893.4,0.98481,0.0435027,5597.28,3.22193 +355,insert,1419.99,-1.0,-1.0,0.0,3.3814 +356,search,73342.8,0.98512,0.0429029,15073.5,3.38202 +357,insert,106.146,-1.0,-1.0,0.0,3.39019 +358,search,74980.6,0.98535,0.042762,6562.54,3.39055 +359,insert,69.659,-1.0,-1.0,0.0,3.39587 +360,search,68999.3,0.98545,0.0426787,3534.42,3.39619 +361,insert,378.159,-1.0,-1.0,0.0,3.42428 +362,search,75475.9,0.98567,0.0417345,3340.68,3.42379 +363,insert,88.462,-1.0,-1.0,0.0,3.42924 +364,search,66980.6,0.98575,0.0415224,2878.52,3.42973 +365,insert,351.991,-1.0,-1.0,0.0,3.45594 +366,search,75568.2,0.98586,0.0413081,3056.32,3.45568 +367,insert,161.485,-1.0,-1.0,0.0,3.46878 +368,search,74669.2,0.98589,0.0412574,3099.66,3.46873 +369,insert,396.492,-1.0,-1.0,0.0,3.49719 +370,search,71884.2,0.98599,0.041073,3786.27,3.49689 +371,insert,51.725,-1.0,-1.0,0.0,3.50075 +372,search,70564.8,0.9861,0.0408787,3079.46,3.50026 +373,insert,238.402,-1.0,-1.0,0.0,3.51779 +374,search,77344.9,0.98618,0.0407568,3084.27,3.51781 +375,insert,188.565,-1.0,-1.0,0.0,3.53015 +376,search,73126.3,0.98616,0.0407268,3109.33,3.53013 +377,insert,312.745,-1.0,-1.0,0.0,3.55791 +378,search,76789,0.98627,0.0405063,3879.22,3.55712 +379,insert,27.963,-1.0,-1.0,0.0,3.5593 +380,search,71905.1,0.98627,0.040531,3206.3,3.55976 +381,insert,105.372,-1.0,-1.0,0.0,3.56864 +382,search,72194.8,0.98629,0.040536,2971.52,3.56866 +383,insert,146.172,-1.0,-1.0,0.0,3.57877 +384,search,72722.3,0.9863,0.0404791,2957.77,3.57894 +385,delete,13.684,-1.0,-1.0,0.0,3.57838 +386,search,71487.8,0.98636,0.0404234,2839.78,3.5784 +387,delete,22.945,-1.0,-1.0,0.0,3.57579 +388,search,72022.2,0.98637,0.0403916,188.093,3.57579 +389,delete,51.231,-1.0,-1.0,0.0,3.57468 +390,search,72543.2,0.98635,0.040407,2771.9,3.5747 +391,delete,92.781,-1.0,-1.0,0.0,3.5539 +392,search,69420,0.98626,0.0405388,2748.19,3.5539 +393,delete,40.042,-1.0,-1.0,0.0,3.55111 +394,search,71680.3,0.98625,0.04057,2751.63,3.55114 +395,delete,20.835,-1.0,-1.0,0.0,3.5443 +396,search,71646.4,0.98618,0.0406339,189.189,3.5443 +397,delete,225.515,-1.0,-1.0,0.0,3.50938 +398,search,70229.8,0.98617,0.04067,186.103,3.50938 +399,delete,20.535,-1.0,-1.0,0.0,3.50836 +400,search,67042.2,0.98614,0.0406932,185.884,3.50836 +401,delete,43.768,-1.0,-1.0,0.0,3.50386 +402,search,67994.4,0.98621,0.0405815,183.904,3.50386 +403,delete,433.541,-1.0,-1.0,0.0,3.41821 +404,search,70511.3,0.98619,0.0406015,2568.13,3.41818 +405,delete,78.297,-1.0,-1.0,0.0,3.40782 +406,search,70541.9,0.98639,0.0404451,2556.65,3.4078 +407,delete,109.285,-1.0,-1.0,0.0,3.37944 +408,search,71604.5,0.98643,0.0403852,188.803,3.37944 +409,delete,348.507,-1.0,-1.0,0.0,3.2964 +410,search,70318.8,0.98638,0.0405075,187.179,3.2964 +411,delete,429.384,-1.0,-1.0,0.0,3.22488 +412,search,72133,0.98596,0.0412202,186.282,3.22488 +413,delete,61.846,-1.0,-1.0,0.0,3.21929 +414,search,67592.5,0.98593,0.0411993,186.746,3.21929 +415,delete,157.222,-1.0,-1.0,0.0,3.19775 +416,search,66615.7,0.9859,0.0413176,183.176,3.19775 +417,delete,356.312,-1.0,-1.0,0.0,3.13236 +418,search,70359.1,0.98615,0.0407588,2298.62,3.13234 +419,delete,38.154,-1.0,-1.0,0.0,3.12743 +420,search,70228.1,0.98609,0.0408626,186.187,3.12743 +421,delete,56.083,-1.0,-1.0,0.0,3.11795 +422,search,73165.4,0.98605,0.040994,187.701,3.11795 +423,delete,291.116,-1.0,-1.0,0.0,3.05307 +424,search,70839.4,0.98619,0.0408471,184.896,3.05307 +425,delete,66.929,-1.0,-1.0,0.0,3.04774 +426,search,67613.8,0.98619,0.0408716,185.496,3.04774 +427,delete,158.837,-1.0,-1.0,0.0,3.03348 +428,search,72295.7,0.98603,0.0410867,186.489,3.03348 +429,delete,670.898,-1.0,-1.0,0.0,2.8822 +430,search,72217.2,0.98434,0.0435774,188.16,2.8822 +431,delete,177.021,-1.0,-1.0,0.0,2.84579 +432,search,69119.7,0.9842,0.0438258,184.571,2.84579 +433,delete,362.485,-1.0,-1.0,0.0,2.76759 +434,search,69794.3,0.9842,0.0437573,188.563,2.76759 +435,delete,257.841,-1.0,-1.0,0.0,2.72024 +436,search,68062.6,0.98398,0.0441998,184.862,2.72024 +437,delete,41.78,-1.0,-1.0,0.0,2.71505 +438,search,71986.5,0.98397,0.0442512,187.976,2.71505 +439,delete,228.465,-1.0,-1.0,0.0,2.65955 +440,search,70031.7,0.98388,0.0443185,183.662,2.65955 +441,delete,112.115,-1.0,-1.0,0.0,2.64601 +442,search,70552.9,0.98389,0.0444699,188.682,2.64601 +443,delete,70.882,-1.0,-1.0,0.0,2.63225 +444,search,70215,0.98407,0.0441971,185.005,2.63225 +445,delete,122.116,-1.0,-1.0,0.0,2.61664 +446,search,70095.2,0.98389,0.0444924,188.262,2.61664 +447,delete,631.239,-1.0,-1.0,0.0,2.46555 +448,search,70265.4,0.98335,0.045254,187.21,2.46555 +449,delete,116.992,-1.0,-1.0,0.0,2.4492 +450,search,70560.3,0.98332,0.0452998,189.092,2.4492 +451,delete,229.277,-1.0,-1.0,0.0,2.40589 +452,search,69712.3,0.98302,0.0458232,186.742,2.40589 +453,delete,535.491,-1.0,-1.0,0.0,2.28542 +454,search,69868.4,0.98257,0.046383,187.857,2.28542 +455,delete,131.822,-1.0,-1.0,0.0,2.2673 +456,search,70824.1,0.98255,0.0462691,185.52,2.2673 +457,delete,27.085,-1.0,-1.0,0.0,2.26416 +458,search,70275.7,0.98253,0.0463896,189.185,2.26416 +459,delete,114.657,-1.0,-1.0,0.0,2.24573 +460,search,66448.5,0.98264,0.0462694,184.647,2.24573 +461,delete,23.932,-1.0,-1.0,0.0,2.24374 +462,search,70375.9,0.98267,0.0462248,188.002,2.24374 +463,delete,141.515,-1.0,-1.0,0.0,2.22115 +464,search,70002.9,0.98276,0.0459909,184.5,2.22115 +465,delete,69.314,-1.0,-1.0,0.0,2.20906 +466,search,71015.3,0.98268,0.0460462,188.338,2.20906 +467,delete,96.257,-1.0,-1.0,0.0,2.19706 +468,search,70798.3,0.9826,0.0461671,190.199,2.19706 +469,delete,58.408,-1.0,-1.0,0.0,2.18666 +470,search,76713.2,0.9826,0.0462321,187.945,2.18666 +471,delete,256.303,-1.0,-1.0,0.0,2.13065 +472,search,71970.2,0.98258,0.0464394,188.349,2.13065 +473,delete,287.138,-1.0,-1.0,0.0,2.07942 +474,search,70284.7,0.98246,0.0465461,188.443,2.07942 +475,delete,720.303,-1.0,-1.0,0.0,1.89012 +476,search,69603.7,0.98211,0.0466411,189.918,1.89012 +477,delete,156.425,-1.0,-1.0,0.0,1.86599 +478,search,68697.6,0.98214,0.0465508,190.283,1.86599 +479,delete,421.193,-1.0,-1.0,0.0,1.77478 +480,search,68674.1,0.98142,0.0477183,185.261,1.77478 +481,delete,164.322,-1.0,-1.0,0.0,1.75333 +482,search,68791.1,0.98128,0.0477472,188.763,1.75333 +483,delete,545.387,-1.0,-1.0,0.0,1.62266 +484,search,69585.5,0.98078,0.0486506,185.647,1.62266 +485,delete,91.262,-1.0,-1.0,0.0,1.61317 +486,search,68824.5,0.98068,0.0488985,188.741,1.61317 +487,delete,46.66,-1.0,-1.0,0.0,1.60908 +488,search,69750.1,0.98055,0.0490187,186.789,1.60908 +489,delete,117.796,-1.0,-1.0,0.0,1.59208 +490,search,70353.9,0.98038,0.0492895,188.826,1.59208 +491,delete,58.397,-1.0,-1.0,0.0,1.58447 +492,search,69299.3,0.98024,0.0494759,186.061,1.58447 +493,delete,322.295,-1.0,-1.0,0.0,1.52019 +494,search,66393.2,0.97998,0.0496927,188.297,1.52019 +495,delete,83.928,-1.0,-1.0,0.0,1.50876 +496,search,65869,0.97998,0.0497329,187.277,1.50876 +497,delete,184.799,-1.0,-1.0,0.0,1.47716 +498,search,69095.5,0.97986,0.0500477,190.242,1.47716 +499,delete,68.662,-1.0,-1.0,0.0,1.46991 +500,search,68385.9,0.97973,0.0504602,189.228,1.46991 +501,delete,97.848,-1.0,-1.0,0.0,1.45759 +502,search,68073.6,0.97972,0.0503304,190.629,1.45759 +503,delete,78.015,-1.0,-1.0,0.0,1.44884 +504,search,69894.2,0.97978,0.0501722,190.08,1.44884 +505,delete,165.876,-1.0,-1.0,0.0,1.41803 +506,search,68309.1,0.97954,0.0504519,187.404,1.41803 +507,delete,117.224,-1.0,-1.0,0.0,1.4004 +508,search,68822.9,0.97944,0.0504945,187.409,1.4004 +509,delete,72.16,-1.0,-1.0,0.0,1.39108 +510,search,69612.3,0.9795,0.0503976,187.538,1.39108 +511,delete,87.791,-1.0,-1.0,0.0,1.38042 +512,search,64422.2,0.97932,0.0506398,185.561,1.38042 +513,insert,1310.28,-1.0,-1.0,0.0,1.467 +514,search,76931,0.97965,0.0499694,1481.64,1.46684 +515,insert,20.949,-1.0,-1.0,0.0,1.46792 +516,search,68855.4,0.97955,0.0504287,1188.68,1.46796 +517,insert,74.318,-1.0,-1.0,0.0,1.47247 +518,search,69996.2,0.97959,0.0504034,186.66,1.47247 +519,insert,423.154,-1.0,-1.0,0.0,1.49598 +520,search,74168.9,0.97992,0.0500091,1248.19,1.49594 +521,insert,59.108,-1.0,-1.0,0.0,1.49944 +522,search,69746.6,0.97999,0.0498695,1197.79,1.49948 +523,insert,157.841,-1.0,-1.0,0.0,1.51059 +524,search,73477.6,0.98002,0.0498293,1277.04,1.51043 +525,insert,151.896,-1.0,-1.0,0.0,1.51911 +526,search,71637.1,0.98008,0.0496926,1253.26,1.51914 +527,insert,1950.54,-1.0,-1.0,0.0,1.67787 +528,search,75955.1,0.98118,0.0478962,2279.41,1.67708 +529,insert,1150.04,-1.0,-1.0,0.0,1.78285 +530,search,76470.9,0.98201,0.0470062,2560.08,1.78203 +531,insert,231.737,-1.0,-1.0,0.0,1.7957 +532,search,75011.8,0.98213,0.0471571,2119.79,1.79512 +533,insert,88.78,-1.0,-1.0,0.0,1.8008 +534,search,72527.3,0.98223,0.0471334,1967.09,1.80148 +535,insert,99.705,-1.0,-1.0,0.0,1.80765 +536,search,75569.4,0.98227,0.0471918,1666.74,1.80744 +537,insert,37.327,-1.0,-1.0,0.0,1.81071 +538,search,73864.6,0.9823,0.0471271,1525.4,1.81062 +539,insert,147.251,-1.0,-1.0,0.0,1.82055 +540,search,68805.5,0.98231,0.0470552,1519.61,1.82046 +541,insert,1607.66,-1.0,-1.0,0.0,1.98131 +542,search,77636,0.98273,0.0470409,3118.6,1.98117 +543,insert,190.72,-1.0,-1.0,0.0,1.99492 +544,search,76079.6,0.983,0.0465341,2138.79,1.99462 +545,insert,37.576,-1.0,-1.0,0.0,1.99684 +546,search,70381.9,0.983,0.0466415,1671.81,1.99687 +547,insert,659.949,-1.0,-1.0,0.0,2.05069 +548,search,77805.1,0.98364,0.0457879,1731.48,2.05065 +549,insert,1098.87,-1.0,-1.0,0.0,2.14702 +550,search,78396.4,0.98354,0.046035,2479.3,2.14757 +551,insert,106.644,-1.0,-1.0,0.0,2.15799 +552,search,76746.6,0.9836,0.046013,2010.51,2.15792 +553,insert,55.21,-1.0,-1.0,0.0,2.16255 +554,search,73952.1,0.98379,0.0457462,1835.13,2.16287 +555,insert,2021.3,-1.0,-1.0,0.0,2.32931 +556,search,80433.3,0.98486,0.0438956,3211.81,2.32876 +557,insert,130.505,-1.0,-1.0,0.0,2.33845 +558,search,74929.4,0.98488,0.043951,2257.26,2.33832 +559,insert,32.74,-1.0,-1.0,0.0,2.34121 +560,search,75915.6,0.98485,0.0440416,1885.27,2.34119 +561,insert,18.621,-1.0,-1.0,0.0,2.3423 +562,search,75104.8,0.98487,0.0440255,1854.39,2.34226 +563,insert,263.262,-1.0,-1.0,0.0,2.35925 +564,search,76485.5,0.98497,0.0436491,1940.12,2.35925 +565,insert,964.018,-1.0,-1.0,0.0,2.44338 +566,search,81838.3,0.98505,0.0434225,2582.59,2.44315 +567,insert,67.255,-1.0,-1.0,0.0,2.44792 +568,search,76567.6,0.98517,0.0430266,2221.61,2.44801 +569,insert,73.045,-1.0,-1.0,0.0,2.45406 +570,search,75552.1,0.98526,0.042837,2131.94,2.45419 +571,insert,51.971,-1.0,-1.0,0.0,2.4598 +572,search,77079.1,0.98523,0.0429545,1976.51,2.45973 +573,insert,334.412,-1.0,-1.0,0.0,2.48504 +574,search,79951.6,0.98529,0.043067,2105.71,2.48481 +575,insert,227.112,-1.0,-1.0,0.0,2.50314 +576,search,80740.4,0.98534,0.0430724,2073.74,2.50313 +577,insert,194.965,-1.0,-1.0,0.0,2.51783 +578,search,77300.2,0.98545,0.0429124,2244.92,2.51731 +579,insert,2409.76,-1.0,-1.0,0.0,2.77557 +580,search,82732.4,0.98593,0.0424901,11777.7,2.77497 +581,insert,128.566,-1.0,-1.0,0.0,2.78427 +582,search,80102.4,0.98577,0.0427149,5420.92,2.78444 +583,insert,119.563,-1.0,-1.0,0.0,2.79282 +584,search,79142.7,0.98578,0.0429415,2596.01,2.79283 +585,insert,1265.5,-1.0,-1.0,0.0,2.91259 +586,search,83826.7,0.98597,0.0425931,3104.47,2.91323 +587,insert,172.044,-1.0,-1.0,0.0,2.92644 +588,search,80296.5,0.98608,0.0423132,2559.2,2.92652 +589,insert,255.184,-1.0,-1.0,0.0,2.94595 +590,search,82172.9,0.98623,0.0419714,2479.16,2.9456 +591,insert,2159.83,-1.0,-1.0,0.0,3.15265 +592,search,84756,0.9868,0.0412064,12525.3,3.15265 +593,insert,801.433,-1.0,-1.0,0.0,3.23778 +594,search,84814.8,0.98704,0.0405477,7328.97,3.23867 +595,insert,35.625,-1.0,-1.0,0.0,3.24117 +596,search,85090.7,0.98724,0.0404405,3550,3.24066 +597,insert,1121.51,-1.0,-1.0,0.0,3.34148 +598,search,89129.2,0.98732,0.040069,4339.8,3.3424 +599,insert,636.315,-1.0,-1.0,0.0,3.39114 +600,search,87025.8,0.98737,0.0398441,4958.59,3.39152 +601,insert,324.21,-1.0,-1.0,0.0,3.41826 +602,search,85510.2,0.98752,0.0395008,3577,3.41839 +603,insert,31.397,-1.0,-1.0,0.0,3.42051 +604,search,81580.8,0.98758,0.039395,2954.43,3.42034 +605,insert,268.09,-1.0,-1.0,0.0,3.43925 +606,search,85833.4,0.98768,0.0391185,2988.5,3.43919 +607,insert,223.372,-1.0,-1.0,0.0,3.45248 +608,search,86531.1,0.98778,0.0388458,2909.33,3.45241 +609,insert,1112.32,-1.0,-1.0,0.0,3.54344 +610,search,88473.4,0.98802,0.0383722,5196.93,3.54342 +611,insert,121.153,-1.0,-1.0,0.0,3.55425 +612,search,86764,0.98809,0.0382017,3627.69,3.55389 +613,insert,959.187,-1.0,-1.0,0.0,3.63845 +614,search,91138.1,0.98811,0.0381785,5252.44,3.63902 +615,insert,1406.46,-1.0,-1.0,0.0,3.80029 +616,search,93779.4,0.98847,0.0374708,9396.05,3.79976 +617,insert,1360.03,-1.0,-1.0,0.0,3.94137 +618,search,93944.9,0.98866,0.037465,15036.8,3.94115 +619,insert,1166.09,-1.0,-1.0,0.0,4.04847 +620,search,98506.6,0.98886,0.036905,9206.83,4.04843 +621,insert,185.749,-1.0,-1.0,0.0,4.06371 +622,search,92795.1,0.98898,0.0367505,4941.42,4.0639 +623,insert,96.413,-1.0,-1.0,0.0,4.0726 +624,search,91437,0.98907,0.0366011,3767.77,4.07261 +625,insert,419.572,-1.0,-1.0,0.0,4.10768 +626,search,92587,0.98908,0.0366996,4369.76,4.10825 +627,insert,276.55,-1.0,-1.0,0.0,4.12771 +628,search,94438.6,0.98921,0.0365329,4410.1,4.12719 +629,insert,70.489,-1.0,-1.0,0.0,4.13297 +630,search,94828.7,0.98922,0.0366335,3656.07,4.13278 +631,insert,213.258,-1.0,-1.0,0.0,4.14796 +632,search,92315.3,0.98922,0.0366608,3712.73,4.1479 +633,insert,246.905,-1.0,-1.0,0.0,4.16476 +634,search,94940,0.9892,0.0367888,3731.65,4.16426 +635,insert,128.163,-1.0,-1.0,0.0,4.17222 +636,search,94274,0.98921,0.0367512,3598.87,4.17238 +637,insert,2078.03,-1.0,-1.0,0.0,4.35003 +638,search,101298,0.98933,0.036403,14441.2,4.34991 +639,insert,2005.93,-1.0,-1.0,0.0,4.52705 +640,search,101833,0.98969,0.0357867,26941.4,4.5273 +641,delete,210.72,-1.0,-1.0,0.0,4.48516 +642,search,98298.4,0.98957,0.0362258,8465.4,4.48366 +643,delete,14.216,-1.0,-1.0,0.0,4.48243 +644,search,97544.3,0.9897,0.0359986,4232.12,4.48144 +645,delete,20.985,-1.0,-1.0,0.0,4.48088 +646,search,99178.7,0.98972,0.0359243,3801.91,4.4809 +647,delete,91.117,-1.0,-1.0,0.0,4.4657 +648,search,100538,0.98971,0.0359615,3759.57,4.46577 +649,delete,48.467,-1.0,-1.0,0.0,4.46203 +650,search,100877,0.98967,0.0360068,3700.08,4.46205 +651,delete,27.655,-1.0,-1.0,0.0,4.45782 +652,search,99696.9,0.98963,0.036052,3700.82,4.45774 +653,delete,118.631,-1.0,-1.0,0.0,4.43031 +654,search,100787,0.98951,0.0362629,3656.98,4.43026 +655,delete,488.964,-1.0,-1.0,0.0,4.33045 +656,search,99432,0.98923,0.036705,348.82,4.33045 +657,delete,399.017,-1.0,-1.0,0.0,4.24665 +658,search,96923.5,0.98903,0.0368873,3429.1,4.24667 +659,delete,154.344,-1.0,-1.0,0.0,4.21019 +660,search,96425.7,0.9889,0.0370785,349.738,4.21019 +661,delete,142.862,-1.0,-1.0,0.0,4.20263 +662,search,98227.8,0.98886,0.0371481,3358.6,4.2026 +663,delete,97.21,-1.0,-1.0,0.0,4.18521 +664,search,98111.9,0.98875,0.0373179,348.966,4.18521 +665,delete,145.12,-1.0,-1.0,0.0,4.17005 +666,search,97331.1,0.98875,0.0372643,347.813,4.17005 +667,delete,403.62,-1.0,-1.0,0.0,4.10628 +668,search,96182.4,0.98857,0.0374234,346.966,4.10628 +669,delete,464.63,-1.0,-1.0,0.0,4.0369 +670,search,94555.7,0.98843,0.0378042,346.875,4.0369 +671,delete,133.09,-1.0,-1.0,0.0,4.02612 +672,search,98328.8,0.98841,0.0378536,347.179,4.02612 +673,delete,167.227,-1.0,-1.0,0.0,4.00489 +674,search,96978.2,0.98841,0.0379328,348.029,4.00489 +675,delete,318.15,-1.0,-1.0,0.0,3.97331 +676,search,95479.9,0.98815,0.038296,347.77,3.97331 +677,delete,398.752,-1.0,-1.0,0.0,3.89325 +678,search,95425.6,0.98813,0.0383184,347.415,3.89325 +679,delete,92.856,-1.0,-1.0,0.0,3.88261 +680,search,94372.2,0.98814,0.0383051,349.419,3.88261 +681,delete,42.148,-1.0,-1.0,0.0,3.88089 +682,search,95450,0.98816,0.0382619,346.062,3.88089 +683,delete,627.136,-1.0,-1.0,0.0,3.78738 +684,search,93578.8,0.9875,0.0394461,345.507,3.78738 +685,delete,533.723,-1.0,-1.0,0.0,3.69367 +686,search,97220.9,0.98662,0.0410027,347.373,3.69367 +687,delete,67.677,-1.0,-1.0,0.0,3.68726 +688,search,95868.9,0.98658,0.0410136,345.016,3.68726 +689,delete,259.569,-1.0,-1.0,0.0,3.63629 +690,search,94907.1,0.98654,0.0410977,344.129,3.63629 +691,delete,143.517,-1.0,-1.0,0.0,3.62063 +692,search,94658.7,0.98644,0.0412114,343.934,3.62063 +693,delete,383.003,-1.0,-1.0,0.0,3.55723 +694,search,92091.4,0.9864,0.0413192,341.722,3.55723 +695,delete,83.901,-1.0,-1.0,0.0,3.54635 +696,search,97660.8,0.9864,0.0413192,343.846,3.54635 +697,delete,104.081,-1.0,-1.0,0.0,3.53679 +698,search,94899.1,0.98636,0.0413533,341.337,3.53679 +699,delete,37.289,-1.0,-1.0,0.0,3.53007 +700,search,94160.6,0.98631,0.0414478,341.246,3.53007 +701,delete,194.485,-1.0,-1.0,0.0,3.50812 +702,search,94412.5,0.98626,0.0414898,341.146,3.50812 +703,delete,406.064,-1.0,-1.0,0.0,3.43215 +704,search,96946.3,0.98629,0.0415357,340.515,3.43215 +705,delete,123.625,-1.0,-1.0,0.0,3.41815 +706,search,96058.2,0.98619,0.0417672,342.955,3.41815 +707,delete,1052.49,-1.0,-1.0,0.0,3.168 +708,search,95390.5,0.9857,0.0423971,341.876,3.168 +709,delete,403.307,-1.0,-1.0,0.0,3.08665 +710,search,94746.3,0.98535,0.0431347,340.866,3.08665 +711,delete,164.186,-1.0,-1.0,0.0,3.06769 +712,search,93723.3,0.98521,0.0434094,341.148,3.06769 +713,delete,519.014,-1.0,-1.0,0.0,2.9621 +714,search,93518.1,0.98502,0.0436097,338.061,2.9621 +715,delete,115.766,-1.0,-1.0,0.0,2.94693 +716,search,93864.5,0.98496,0.0436804,338.552,2.94693 +717,delete,114.402,-1.0,-1.0,0.0,2.93417 +718,search,93823,0.98487,0.0437521,338.653,2.93417 +719,delete,730.153,-1.0,-1.0,0.0,2.77723 +720,search,93810.5,0.98412,0.0448757,339.081,2.77723 +721,delete,279.766,-1.0,-1.0,0.0,2.7311 +722,search,94652.6,0.98416,0.0448257,339.371,2.7311 +723,delete,95.27,-1.0,-1.0,0.0,2.72078 +724,search,93266.4,0.98408,0.0449323,337.66,2.72078 +725,delete,292.937,-1.0,-1.0,0.0,2.67201 +726,search,95959.1,0.98412,0.0447641,341.611,2.67201 +727,delete,285.645,-1.0,-1.0,0.0,2.6245 +728,search,96647.3,0.98416,0.0448034,341.533,2.6245 +729,delete,296.36,-1.0,-1.0,0.0,2.57339 +730,search,94037.3,0.98391,0.0453015,342.218,2.57339 +731,delete,225.758,-1.0,-1.0,0.0,2.54174 +732,search,93399.1,0.9837,0.0458317,343.323,2.54174 +733,delete,225.804,-1.0,-1.0,0.0,2.50917 +734,search,95187.2,0.98359,0.0458446,342.326,2.50917 +735,delete,389.501,-1.0,-1.0,0.0,2.43352 +736,search,95432.8,0.98354,0.0458172,343.852,2.43352 +737,delete,358.425,-1.0,-1.0,0.0,2.3771 +738,search,89540.5,0.98351,0.0458627,339.146,2.3771 +739,delete,208.669,-1.0,-1.0,0.0,2.3445 +740,search,93534.2,0.98353,0.0459533,336.937,2.3445 +741,delete,428.817,-1.0,-1.0,0.0,2.26812 +742,search,91509.7,0.98356,0.0461295,337.969,2.26812 +743,delete,471.542,-1.0,-1.0,0.0,2.179 +744,search,92041,0.98359,0.0461706,338.891,2.179 +745,delete,573.656,-1.0,-1.0,0.0,2.07225 +746,search,94048.5,0.98329,0.0465823,344.683,2.07225 +747,delete,487.92,-1.0,-1.0,0.0,1.97187 +748,search,92045.5,0.98312,0.0468745,342.032,1.97187 +749,delete,231.923,-1.0,-1.0,0.0,1.93528 +750,search,92564.4,0.98294,0.0471094,343.226,1.93528 +751,delete,92.83,-1.0,-1.0,0.0,1.92202 +752,search,90915.4,0.98291,0.0471493,340.69,1.92202 +753,delete,203.177,-1.0,-1.0,0.0,1.89213 +754,search,92852.8,0.98283,0.0472711,337.692,1.89213 +755,delete,125.672,-1.0,-1.0,0.0,1.87764 +756,search,90540.7,0.98272,0.0474526,338.001,1.87764 +757,delete,112.018,-1.0,-1.0,0.0,1.86378 +758,search,90731.1,0.98271,0.0475425,339.893,1.86378 +759,delete,106.928,-1.0,-1.0,0.0,1.85039 +760,search,91781.7,0.98266,0.047599,343.947,1.85039 +761,delete,155.563,-1.0,-1.0,0.0,1.83001 +762,search,92641.9,0.98264,0.0476747,341.106,1.83001 +763,delete,88.513,-1.0,-1.0,0.0,1.82066 +764,search,95932.7,0.98263,0.0476375,341.961,1.82066 +765,delete,766.473,-1.0,-1.0,0.0,1.6646 +766,search,92285.6,0.98293,0.046455,338.802,1.6646 +767,delete,869.219,-1.0,-1.0,0.0,1.47582 +768,search,90270.5,0.98213,0.0476213,336.202,1.47582 +769,insert,59.916,-1.0,-1.0,0.0,1.47671 +770,search,92587.3,0.98211,0.0476174,335.802,1.47671 +771,insert,136.609,-1.0,-1.0,0.0,1.48314 +772,search,87602.4,0.98213,0.0475582,341.082,1.48314 +773,insert,299.195,-1.0,-1.0,0.0,1.49496 +774,search,91755.3,0.98226,0.0473236,1380.52,1.49489 +775,insert,181.174,-1.0,-1.0,0.0,1.50415 +776,search,93257.7,0.98237,0.0471851,1380.51,1.50413 +777,insert,135.594,-1.0,-1.0,0.0,1.5107 +778,search,94846.7,0.98247,0.0469658,1407.76,1.51074 +779,insert,56.074,-1.0,-1.0,0.0,1.51359 +780,search,90014.9,0.98254,0.0468995,341.905,1.51359 +781,insert,43.443,-1.0,-1.0,0.0,1.51453 +782,search,90371.8,0.98257,0.0468122,337.058,1.51453 +783,insert,273.498,-1.0,-1.0,0.0,1.52779 +784,search,95321,0.98257,0.0467694,341.165,1.52779 +785,insert,189.789,-1.0,-1.0,0.0,1.54224 +786,search,92947.2,0.98276,0.046553,1464.54,1.54226 +787,insert,87.042,-1.0,-1.0,0.0,1.54605 +788,search,94276.1,0.98281,0.0464522,340.101,1.54605 +789,insert,48.264,-1.0,-1.0,0.0,1.54741 +790,search,93066.9,0.9828,0.0465642,340.558,1.54741 +791,insert,162.718,-1.0,-1.0,0.0,1.55412 +792,search,90189.5,0.98264,0.0467639,338.266,1.55412 +793,insert,20.188,-1.0,-1.0,0.0,1.55455 +794,search,91069.1,0.98264,0.0467639,341.546,1.55455 +795,insert,313.221,-1.0,-1.0,0.0,1.57094 +796,search,93476.9,0.98277,0.046588,344.468,1.57094 +797,insert,33.609,-1.0,-1.0,0.0,1.57161 +798,search,91504.5,0.98277,0.0466094,344.034,1.57161 +799,insert,39.369,-1.0,-1.0,0.0,1.57261 +800,search,94111,0.98272,0.0467089,342.252,1.57261 +801,insert,101.616,-1.0,-1.0,0.0,1.57648 +802,search,94588.5,0.98261,0.0469997,344.028,1.57648 +803,insert,4090.35,-1.0,-1.0,0.0,1.87471 +804,search,102635,0.98378,0.044824,4279.84,1.8742 +805,insert,86.542,-1.0,-1.0,0.0,1.87989 +806,search,95552.6,0.98392,0.0448968,3086.21,1.87984 +807,insert,91.689,-1.0,-1.0,0.0,1.88529 +808,search,97047.6,0.98399,0.0447533,1975.18,1.88553 +809,insert,169.122,-1.0,-1.0,0.0,1.89728 +810,search,96273.7,0.98411,0.0445501,1731.88,1.89734 +811,insert,190.522,-1.0,-1.0,0.0,1.90785 +812,search,93795.2,0.98432,0.0441186,1674.17,1.90791 +813,insert,316.803,-1.0,-1.0,0.0,1.92597 +814,search,96336.3,0.98473,0.0433793,280.298,1.92597 +815,insert,12.503,-1.0,-1.0,0.0,1.92653 +816,search,93614,0.98473,0.0433793,281.479,1.92653 +817,insert,551.852,-1.0,-1.0,0.0,1.95747 +818,search,97781.8,0.98471,0.0433984,1882.39,1.95751 +819,insert,114.34,-1.0,-1.0,0.0,1.96319 +820,search,96523.2,0.98466,0.0434377,1715.07,1.96317 +821,insert,78.669,-1.0,-1.0,0.0,1.96853 +822,search,93374.9,0.98464,0.0434766,1748.11,1.9684 +823,insert,186.521,-1.0,-1.0,0.0,1.98199 +824,search,92798.2,0.9847,0.0434281,1786.73,1.98207 +825,insert,428.319,-1.0,-1.0,0.0,2.01108 +826,search,96829.8,0.98484,0.0431073,1800.94,2.01107 +827,insert,113.301,-1.0,-1.0,0.0,2.01864 +828,search,94850,0.98474,0.0433038,285.116,2.01864 +829,insert,2474.08,-1.0,-1.0,0.0,2.18833 +830,search,100521,0.98479,0.0428478,2841.18,2.18838 +831,insert,183.049,-1.0,-1.0,0.0,2.19999 +832,search,96131.5,0.98489,0.042647,2079.76,2.19991 +833,insert,65.708,-1.0,-1.0,0.0,2.20414 +834,search,93400,0.98486,0.042671,1886.46,2.2041 +835,insert,368.174,-1.0,-1.0,0.0,2.22897 +836,search,97172.4,0.98482,0.0426841,285.776,2.22897 +837,insert,160.569,-1.0,-1.0,0.0,2.23894 +838,search,96328.7,0.98478,0.0427843,1914.51,2.23882 +839,insert,409.963,-1.0,-1.0,0.0,2.26669 +840,search,101012,0.98513,0.0423574,2019.56,2.26658 +841,insert,232.497,-1.0,-1.0,0.0,2.2835 +842,search,97464.6,0.98516,0.0423313,1970.32,2.28361 +843,insert,2101.78,-1.0,-1.0,0.0,2.44709 +844,search,101692,0.98521,0.0423597,3216.87,2.44756 +845,insert,1794.22,-1.0,-1.0,0.0,2.59743 +846,search,102260,0.98594,0.0412119,4589.35,2.59734 +847,insert,24.996,-1.0,-1.0,0.0,2.5986 +848,search,96964.9,0.98606,0.0411338,3017.55,2.59861 +849,insert,21.016,-1.0,-1.0,0.0,2.59997 +850,search,100360,0.98614,0.0410846,2361.15,2.60009 +851,insert,53.718,-1.0,-1.0,0.0,2.60409 +852,search,101523,0.98615,0.0410523,2219.78,2.60413 +853,insert,143.702,-1.0,-1.0,0.0,2.61232 +854,search,100974,0.98619,0.0409938,291.326,2.61232 +855,insert,71.631,-1.0,-1.0,0.0,2.61543 +856,search,97145.1,0.98622,0.0409663,2197.27,2.61541 +857,insert,127.665,-1.0,-1.0,0.0,2.62309 +858,search,100782,0.98622,0.0409175,2267.15,2.62311 +859,insert,204.325,-1.0,-1.0,0.0,2.63699 +860,search,97682.4,0.98614,0.0410603,2316.28,2.63696 +861,insert,38.223,-1.0,-1.0,0.0,2.63954 +862,search,102135,0.98614,0.0411819,2233.7,2.63958 +863,insert,361.824,-1.0,-1.0,0.0,2.66765 +864,search,97720.4,0.98626,0.0409804,2394.4,2.66776 +865,insert,67.092,-1.0,-1.0,0.0,2.67208 +866,search,102320,0.98621,0.0410228,2296.86,2.67218 +867,insert,270.559,-1.0,-1.0,0.0,2.69008 +868,search,98206.9,0.9862,0.0410346,2260.26,2.69007 +869,insert,37.459,-1.0,-1.0,0.0,2.69238 +870,search,98918.7,0.9862,0.0409858,293.047,2.69238 +871,insert,218.535,-1.0,-1.0,0.0,2.70626 +872,search,103705,0.9862,0.0409614,2306.88,2.70621 +873,insert,203.744,-1.0,-1.0,0.0,2.7214 +874,search,100417,0.98626,0.0408582,2372.76,2.72139 +875,insert,83.879,-1.0,-1.0,0.0,2.72834 +876,search,100696,0.98628,0.0407901,2335.71,2.72824 +877,insert,16.867,-1.0,-1.0,0.0,2.72929 +878,search,101350,0.9863,0.0408233,293.031,2.72929 +879,insert,1704.09,-1.0,-1.0,0.0,2.85755 +880,search,106014,0.98642,0.0404675,4347.64,2.85697 +881,insert,2471.8,-1.0,-1.0,0.0,3.08398 +882,search,107355,0.98649,0.0404045,8099.06,3.0844 +883,insert,2080.26,-1.0,-1.0,0.0,3.27966 +884,search,110060,0.98719,0.0392555,9194.07,3.27868 +885,insert,48.94,-1.0,-1.0,0.0,3.28265 +886,search,103310,0.98723,0.0393967,3914.77,3.28293 +887,insert,1815.52,-1.0,-1.0,0.0,3.43846 +888,search,110778,0.9877,0.0386653,5893.51,3.43839 +889,insert,1924,-1.0,-1.0,0.0,3.62355 +890,search,110667,0.98788,0.0384087,10851.5,3.62316 +891,insert,194.283,-1.0,-1.0,0.0,3.63609 +892,search,107850,0.98781,0.0386349,5175.58,3.63556 +893,insert,345.082,-1.0,-1.0,0.0,3.66096 +894,search,109862,0.98786,0.0386127,3802.27,3.66064 +895,insert,280.178,-1.0,-1.0,0.0,3.68238 +896,search,109811,0.98792,0.0384733,3272.46,3.68237 +897,delete,84.484,-1.0,-1.0,0.0,3.66156 +898,search,105680,0.98784,0.0384481,319.663,3.66156 +899,delete,50.253,-1.0,-1.0,0.0,3.66003 +900,search,99283.2,0.98783,0.0385091,320.97,3.66003 +901,delete,151.409,-1.0,-1.0,0.0,3.65245 +902,search,107899,0.98788,0.0384087,2987.17,3.65246 +903,delete,60.856,-1.0,-1.0,0.0,3.63464 +904,search,103494,0.98774,0.038626,325.136,3.63464 +905,delete,86.928,-1.0,-1.0,0.0,3.63188 +906,search,104794,0.98774,0.0386778,324.949,3.63188 +907,delete,72.978,-1.0,-1.0,0.0,3.62877 +908,search,105419,0.98771,0.0387038,325.104,3.62877 +909,delete,115.767,-1.0,-1.0,0.0,3.62456 +910,search,106996,0.9877,0.0387428,324.755,3.62456 +911,delete,198.084,-1.0,-1.0,0.0,3.6155 +912,search,106177,0.98744,0.0391948,2934.86,3.61546 +913,delete,42.619,-1.0,-1.0,0.0,3.60309 +914,search,105507,0.98746,0.0390511,326.289,3.60309 +915,delete,159.287,-1.0,-1.0,0.0,3.5893 +916,search,105462,0.98736,0.0393262,326.231,3.5893 +917,delete,58.175,-1.0,-1.0,0.0,3.58733 +918,search,100356,0.9874,0.0392328,326.644,3.58733 +919,delete,88.89,-1.0,-1.0,0.0,3.58482 +920,search,107938,0.98743,0.0391822,325.255,3.58482 +921,delete,67.785,-1.0,-1.0,0.0,3.57949 +922,search,102391,0.98743,0.0391822,324.141,3.57949 +923,delete,165.477,-1.0,-1.0,0.0,3.56757 +924,search,107149,0.98732,0.039262,322.868,3.56757 +925,delete,299.273,-1.0,-1.0,0.0,3.51723 +926,search,102841,0.98706,0.039508,326.058,3.51723 +927,delete,69.138,-1.0,-1.0,0.0,3.51332 +928,search,102472,0.98703,0.0395321,324.143,3.51332 +929,delete,106.223,-1.0,-1.0,0.0,3.5065 +930,search,104879,0.98703,0.0393801,325.764,3.5065 +931,delete,826.36,-1.0,-1.0,0.0,3.36239 +932,search,103650,0.98678,0.0397912,324.193,3.36239 +933,delete,92.451,-1.0,-1.0,0.0,3.34973 +934,search,100126,0.98679,0.0397574,323.887,3.34973 +935,delete,65.114,-1.0,-1.0,0.0,3.34118 +936,search,102171,0.98676,0.0397866,323.711,3.34118 +937,delete,86.939,-1.0,-1.0,0.0,3.33 +938,search,101929,0.98668,0.0399085,322.95,3.33 +939,delete,369.834,-1.0,-1.0,0.0,3.29307 +940,search,101348,0.9865,0.0401977,324.369,3.29307 +941,delete,149.574,-1.0,-1.0,0.0,3.281 +942,search,103019,0.98628,0.0406428,324.739,3.281 +943,delete,18.333,-1.0,-1.0,0.0,3.27961 +944,search,101668,0.98628,0.0406428,323.002,3.27961 +945,delete,261.485,-1.0,-1.0,0.0,3.23064 +946,search,102654,0.98635,0.04058,325.389,3.23064 +947,delete,96.1,-1.0,-1.0,0.0,3.22381 +948,search,100961,0.9863,0.0407006,320.601,3.22381 +949,delete,146.688,-1.0,-1.0,0.0,3.20365 +950,search,101557,0.98632,0.0406555,323.118,3.20365 +951,delete,87.553,-1.0,-1.0,0.0,3.18367 +952,search,104236,0.98617,0.0407926,323.958,3.18367 +953,delete,152.336,-1.0,-1.0,0.0,3.16935 +954,search,101602,0.98614,0.040767,323.892,3.16935 +955,delete,50.358,-1.0,-1.0,0.0,3.16118 +956,search,104842,0.98618,0.0405354,323.639,3.16118 +957,delete,642.385,-1.0,-1.0,0.0,3.03825 +958,search,104534,0.98581,0.0415428,322.806,3.03825 +959,delete,159.52,-1.0,-1.0,0.0,3.02038 +960,search,106027,0.98555,0.0419563,324.527,3.02038 +961,delete,106.669,-1.0,-1.0,0.0,3.01032 +962,search,98824,0.98542,0.0421142,322.689,3.01032 +963,delete,293.363,-1.0,-1.0,0.0,2.96376 +964,search,100623,0.9855,0.0419014,321.522,2.96376 +965,delete,171.265,-1.0,-1.0,0.0,2.935 +966,search,105663,0.98536,0.0422117,325.372,2.935 +967,delete,158.738,-1.0,-1.0,0.0,2.91399 +968,search,101275,0.98521,0.0425248,321.62,2.91399 +969,delete,170.293,-1.0,-1.0,0.0,2.88302 +970,search,99899.3,0.98514,0.0427265,322.25,2.88302 +971,delete,640.51,-1.0,-1.0,0.0,2.75931 +972,search,105230,0.98518,0.0423371,322.882,2.75931 +973,delete,592.997,-1.0,-1.0,0.0,2.63586 +974,search,104406,0.98437,0.0438496,321.861,2.63586 +975,delete,351.676,-1.0,-1.0,0.0,2.56975 +976,search,103478,0.98371,0.0450086,320.774,2.56975 +977,delete,189.065,-1.0,-1.0,0.0,2.53594 +978,search,104236,0.98372,0.0449584,320.827,2.53594 +979,delete,57.155,-1.0,-1.0,0.0,2.52975 +980,search,104619,0.98369,0.0449784,322.091,2.52975 +981,delete,289.254,-1.0,-1.0,0.0,2.47629 +982,search,99443.9,0.98371,0.0450973,320.004,2.47629 +983,delete,136.728,-1.0,-1.0,0.0,2.46256 +984,search,100287,0.98356,0.0454085,320.407,2.46256 +985,delete,145.89,-1.0,-1.0,0.0,2.44482 +986,search,100006,0.98342,0.0456195,318.526,2.44482 +987,delete,162.089,-1.0,-1.0,0.0,2.42591 +988,search,96661.5,0.98338,0.0456964,321.744,2.42591 +989,delete,66.568,-1.0,-1.0,0.0,2.41947 +990,search,100036,0.98336,0.045729,320.699,2.41947 +991,delete,196.352,-1.0,-1.0,0.0,2.38537 +992,search,99704.6,0.9834,0.0453708,319.959,2.38537 +993,delete,263.76,-1.0,-1.0,0.0,2.34778 +994,search,99951,0.9831,0.0460497,319.591,2.34778 +995,delete,224.793,-1.0,-1.0,0.0,2.3138 +996,search,100587,0.98289,0.0463498,320.413,2.3138 +997,delete,100.877,-1.0,-1.0,0.0,2.30187 +998,search,98549.4,0.98291,0.0462499,320.71,2.30187 +999,delete,315.261,-1.0,-1.0,0.0,2.24546 +1000,search,99193,0.98282,0.0463788,320.967,2.24546 +1001,delete,316.98,-1.0,-1.0,0.0,2.19567 +1002,search,98705.7,0.98284,0.0462785,320.794,2.19567 +1003,delete,157.726,-1.0,-1.0,0.0,2.17266 +1004,search,99651,0.98275,0.0465793,319.499,2.17266 +1005,delete,81.904,-1.0,-1.0,0.0,2.16271 +1006,search,98716.8,0.98274,0.0466273,321.168,2.16271 +1007,delete,456.997,-1.0,-1.0,0.0,2.07405 +1008,search,104141,0.98267,0.0466552,322.348,2.07405 +1009,delete,737.756,-1.0,-1.0,0.0,1.92546 +1010,search,101974,0.98252,0.0469944,322.317,1.92546 +1011,delete,926.326,-1.0,-1.0,0.0,1.7433 +1012,search,100754,0.98176,0.0482636,320.632,1.7433 +1013,delete,42.485,-1.0,-1.0,0.0,1.73768 +1014,search,97824.3,0.98168,0.0483392,324.757,1.73768 +1015,delete,670.086,-1.0,-1.0,0.0,1.60326 +1016,search,99679.1,0.98115,0.0489477,323.345,1.60326 +1017,delete,813.436,-1.0,-1.0,0.0,1.44867 +1018,search,98476.9,0.98139,0.0486934,319.774,1.44867 +1019,delete,91.058,-1.0,-1.0,0.0,1.43753 +1020,search,103717,0.98143,0.0484826,319.761,1.43753 +1021,delete,380.719,-1.0,-1.0,0.0,1.37765 +1022,search,101971,0.98152,0.0488941,319.405,1.37765 +1023,delete,285.695,-1.0,-1.0,0.0,1.33484 +1024,search,97854.2,0.98103,0.0493708,320.376,1.33484 +1025,insert,163.645,-1.0,-1.0,0.0,1.34256 +1026,search,101063,0.98113,0.0491657,318.173,1.34256 +1027,insert,1204.11,-1.0,-1.0,0.0,1.39969 +1028,search,106184,0.9817,0.0483271,1429.09,1.39978 +1029,insert,2208.24,-1.0,-1.0,0.0,1.54248 +1030,search,103621,0.98198,0.0476998,2066.48,1.54234 +1031,insert,3306.98,-1.0,-1.0,0.0,1.79153 +1032,search,105702,0.98292,0.0462448,3971.69,1.79144 +1033,insert,2153.13,-1.0,-1.0,0.0,1.95994 +1034,search,106115,0.98426,0.0440066,3553.68,1.95967 +1035,insert,1478,-1.0,-1.0,0.0,2.06538 +1036,search,105392,0.98423,0.0439831,3673.81,2.06548 +1037,insert,68.786,-1.0,-1.0,0.0,2.06934 +1038,search,102763,0.98419,0.0443301,2112.05,2.06915 +1039,insert,440.054,-1.0,-1.0,0.0,2.09794 +1040,search,104681,0.98425,0.0443514,1943.04,2.09793 +1041,insert,54.979,-1.0,-1.0,0.0,2.10152 +1042,search,102151,0.98428,0.044307,1887.57,2.10147 +1043,insert,114.67,-1.0,-1.0,0.0,2.10806 +1044,search,104855,0.98424,0.044313,1916.86,2.10802 +1045,insert,267.431,-1.0,-1.0,0.0,2.12305 +1046,search,104893,0.98423,0.0444579,1903.67,2.12304 +1047,insert,19.498,-1.0,-1.0,0.0,2.12384 +1048,search,107787,0.9842,0.0445051,334.641,2.12384 +1049,insert,104.487,-1.0,-1.0,0.0,2.12955 +1050,search,106221,0.98421,0.0445179,335.37,2.12955 +1051,insert,654.821,-1.0,-1.0,0.0,2.16696 +1052,search,108114,0.98424,0.044583,1979.59,2.16683 +1053,insert,297.941,-1.0,-1.0,0.0,2.18488 +1054,search,107648,0.98424,0.0444707,1973.09,2.18477 +1055,insert,224.855,-1.0,-1.0,0.0,2.19896 +1056,search,102549,0.98424,0.0445156,337.692,2.19896 +1057,insert,50.989,-1.0,-1.0,0.0,2.20109 +1058,search,102420,0.98424,0.0445381,336.545,2.20109 +1059,insert,164.92,-1.0,-1.0,0.0,2.20796 +1060,search,104464,0.9843,0.0444917,1977.99,2.20795 +1061,insert,53.747,-1.0,-1.0,0.0,2.21115 +1062,search,103756,0.9843,0.0444917,1995.1,2.21113 +1063,insert,61.827,-1.0,-1.0,0.0,2.21489 +1064,search,106666,0.98425,0.044666,2046.19,2.215 +1065,insert,1575.69,-1.0,-1.0,0.0,2.33248 +1066,search,117258,0.98434,0.0445311,2795.44,2.33229 +1067,insert,39.976,-1.0,-1.0,0.0,2.33472 +1068,search,107185,0.98438,0.0444334,2268.38,2.33455 +1069,insert,204.902,-1.0,-1.0,0.0,2.34725 +1070,search,109079,0.98456,0.0438843,2181.33,2.34732 +1071,insert,149.176,-1.0,-1.0,0.0,2.35791 +1072,search,105595,0.98457,0.043878,2111.42,2.35789 +1073,insert,158.499,-1.0,-1.0,0.0,2.36702 +1074,search,107371,0.98456,0.0438615,2108.49,2.36698 +1075,insert,65.888,-1.0,-1.0,0.0,2.37034 +1076,search,108723,0.98458,0.0438455,2109.16,2.37034 +1077,insert,160.146,-1.0,-1.0,0.0,2.38119 +1078,search,107784,0.98459,0.0438162,2122.76,2.38118 +1079,insert,133.188,-1.0,-1.0,0.0,2.38887 +1080,search,108520,0.98469,0.0436684,2150.19,2.38887 +1081,insert,1953.68,-1.0,-1.0,0.0,2.53009 +1082,search,115406,0.98494,0.0430987,2692.91,2.52983 +1083,insert,4.594,-1.0,-1.0,0.0,2.53028 +1084,search,100880,0.98485,0.0431934,2295.57,2.53028 +1085,insert,139.696,-1.0,-1.0,0.0,2.53866 +1086,search,109112,0.98487,0.0432232,2259.8,2.53867 +1087,insert,96.064,-1.0,-1.0,0.0,2.54399 +1088,search,106682,0.98489,0.0431834,2272.68,2.54403 +1089,insert,2174,-1.0,-1.0,0.0,2.7085 +1090,search,109583,0.98528,0.0427725,4053.15,2.70924 +1091,insert,298.384,-1.0,-1.0,0.0,2.7311 +1092,search,110597,0.98546,0.0423422,2872.69,2.73092 +1093,insert,110.185,-1.0,-1.0,0.0,2.73903 +1094,search,110168,0.98546,0.042295,2605.23,2.73898 +1095,insert,2114.09,-1.0,-1.0,0.0,2.90637 +1096,search,116747,0.98574,0.0419849,5192.44,2.90632 +1097,insert,116.723,-1.0,-1.0,0.0,2.91542 +1098,search,111137,0.9858,0.0419574,3378.8,2.91487 +1099,insert,80.532,-1.0,-1.0,0.0,2.92004 +1100,search,112620,0.98585,0.0419401,2737.12,2.91984 +1101,insert,240.155,-1.0,-1.0,0.0,2.93596 +1102,search,112533,0.98589,0.0420256,2622.63,2.93622 +1103,insert,509.749,-1.0,-1.0,0.0,2.97577 +1104,search,112736,0.98642,0.0410812,2655.38,2.97565 +1105,insert,16.196,-1.0,-1.0,0.0,2.97662 +1106,search,107445,0.9864,0.041052,2596.43,2.97658 +1107,insert,1209.8,-1.0,-1.0,0.0,3.07261 +1108,search,111024,0.98651,0.040636,3746.02,3.0724 +1109,insert,38.983,-1.0,-1.0,0.0,3.07573 +1110,search,106314,0.98657,0.0407523,3055.5,3.07595 +1111,insert,241.997,-1.0,-1.0,0.0,3.09192 +1112,search,108370,0.98659,0.0407367,2997.27,3.09212 +1113,insert,317.717,-1.0,-1.0,0.0,3.1147 +1114,search,109427,0.98682,0.0403531,2893.3,3.11508 +1115,insert,364.563,-1.0,-1.0,0.0,3.14201 +1116,search,108392,0.98682,0.0403283,2892.77,3.14153 +1117,insert,90.647,-1.0,-1.0,0.0,3.14829 +1118,search,109624,0.98687,0.0402355,2774.78,3.1485 +1119,insert,64.339,-1.0,-1.0,0.0,3.15217 +1120,search,113625,0.98689,0.0401892,2745.79,3.15217 +1121,insert,166.936,-1.0,-1.0,0.0,3.16335 +1122,search,109044,0.98686,0.0402427,2767.5,3.16312 +1123,insert,118.253,-1.0,-1.0,0.0,3.17088 +1124,search,111046,0.98683,0.0401969,2791.11,3.17108 +1125,insert,48.632,-1.0,-1.0,0.0,3.17415 +1126,search,110351,0.98683,0.0401969,2755.62,3.17425 +1127,insert,250.444,-1.0,-1.0,0.0,3.19346 +1128,search,112383,0.98687,0.0401609,2762.09,3.19344 +1129,insert,81.479,-1.0,-1.0,0.0,3.19872 +1130,search,105214,0.98687,0.0401111,2774.49,3.1987 +1131,insert,206.939,-1.0,-1.0,0.0,3.21214 +1132,search,107238,0.9869,0.0400321,2891.1,3.21206 +1133,insert,104.91,-1.0,-1.0,0.0,3.21896 +1134,search,107595,0.98686,0.0401182,2896.82,3.21892 +1135,insert,42.943,-1.0,-1.0,0.0,3.22199 +1136,search,108144,0.98684,0.040139,354.082,3.22199 +1137,insert,203.857,-1.0,-1.0,0.0,3.23102 +1138,search,113924,0.98685,0.0401265,2853.07,3.2311 +1139,insert,13.769,-1.0,-1.0,0.0,3.23204 +1140,search,110554,0.98684,0.0401639,2817.83,3.23201 +1141,insert,1161.84,-1.0,-1.0,0.0,3.32653 +1142,search,111908,0.9869,0.039907,3976.58,3.32697 +1143,insert,127.658,-1.0,-1.0,0.0,3.33653 +1144,search,109154,0.98701,0.039705,3422.18,3.33627 +1145,insert,56.241,-1.0,-1.0,0.0,3.34077 +1146,search,106838,0.987,0.0397372,3109.11,3.34135 +1147,insert,109.179,-1.0,-1.0,0.0,3.34924 +1148,search,109245,0.9871,0.039668,3165.63,3.34878 +1149,insert,31.206,-1.0,-1.0,0.0,3.35077 +1150,search,112014,0.98711,0.0396344,3028.11,3.35061 +1151,insert,34.893,-1.0,-1.0,0.0,3.35297 +1152,search,111449,0.98711,0.0396344,3049.95,3.35298 +1153,delete,35.676,-1.0,-1.0,0.0,3.34958 +1154,search,109545,0.98711,0.0396848,361.216,3.34958 +1155,delete,289.385,-1.0,-1.0,0.0,3.32125 +1156,search,110487,0.98697,0.0398666,361.781,3.32125 +1157,delete,531.549,-1.0,-1.0,0.0,3.24823 +1158,search,107475,0.98675,0.0402434,361.057,3.24823 +1159,delete,688.452,-1.0,-1.0,0.0,3.08659 +1160,search,105333,0.9866,0.0403799,361.292,3.08659 +1161,delete,519.456,-1.0,-1.0,0.0,3.00337 +1162,search,112884,0.98601,0.0415135,359.543,3.00337 +1163,delete,279.441,-1.0,-1.0,0.0,2.9513 +1164,search,106116,0.98598,0.0415156,361.924,2.9513 +1165,delete,106.776,-1.0,-1.0,0.0,2.94458 +1166,search,110746,0.98591,0.0416238,357.686,2.94458 +1167,delete,212.336,-1.0,-1.0,0.0,2.92576 +1168,search,108257,0.98583,0.0415754,356.6,2.92576 +1169,delete,59.116,-1.0,-1.0,0.0,2.91322 +1170,search,105954,0.98573,0.0416624,358.981,2.91322 +1171,delete,98.116,-1.0,-1.0,0.0,2.90279 +1172,search,108864,0.98569,0.0418617,361.711,2.90279 +1173,delete,131.748,-1.0,-1.0,0.0,2.89235 +1174,search,106908,0.98561,0.0418343,419.1,2.89235 +1175,delete,71.969,-1.0,-1.0,0.0,2.88827 +1176,search,105678,0.98561,0.0419061,358.421,2.88827 +1177,delete,45.818,-1.0,-1.0,0.0,2.88348 +1178,search,105577,0.9856,0.0419131,359.509,2.88348 +1179,delete,179.123,-1.0,-1.0,0.0,2.86394 +1180,search,108635,0.98545,0.0420412,356.096,2.86394 +1181,delete,143.105,-1.0,-1.0,0.0,2.84892 +1182,search,104496,0.98533,0.0421201,355.838,2.84892 +1183,delete,134.227,-1.0,-1.0,0.0,2.83236 +1184,search,106131,0.98516,0.0423075,355.687,2.83236 +1185,delete,86.232,-1.0,-1.0,0.0,2.82578 +1186,search,110657,0.98516,0.0424491,355.124,2.82578 +1187,delete,346.264,-1.0,-1.0,0.0,2.78044 +1188,search,105258,0.98511,0.042512,359.539,2.78044 +1189,delete,61.422,-1.0,-1.0,0.0,2.77514 +1190,search,112898,0.9851,0.04257,361.953,2.77514 +1191,delete,44.878,-1.0,-1.0,0.0,2.77245 +1192,search,111129,0.98507,0.0426186,361.087,2.77245 +1193,delete,461.977,-1.0,-1.0,0.0,2.68065 +1194,search,111509,0.98496,0.0426611,358.309,2.68065 +1195,delete,80.069,-1.0,-1.0,0.0,2.67558 +1196,search,110504,0.98494,0.042632,354.658,2.67558 +1197,delete,183.263,-1.0,-1.0,0.0,2.65672 +1198,search,110124,0.98457,0.0433738,354.752,2.65672 +1199,delete,45.926,-1.0,-1.0,0.0,2.65101 +1200,search,110149,0.98458,0.0433636,362.516,2.65101 +1201,delete,182.847,-1.0,-1.0,0.0,2.62336 +1202,search,112064,0.98448,0.0435822,361.292,2.62336 +1203,delete,104.149,-1.0,-1.0,0.0,2.61453 +1204,search,110531,0.98445,0.0436757,361.563,2.61453 +1205,delete,76.688,-1.0,-1.0,0.0,2.60225 +1206,search,110461,0.98447,0.0436803,360.464,2.60225 +1207,delete,75.647,-1.0,-1.0,0.0,2.5931 +1208,search,110510,0.98432,0.0438685,357.051,2.5931 +1209,delete,554.169,-1.0,-1.0,0.0,2.48229 +1210,search,110069,0.9842,0.0439625,354.636,2.48229 +1211,delete,30.223,-1.0,-1.0,0.0,2.4798 +1212,search,109640,0.98417,0.0440069,363.84,2.4798 +1213,delete,308.343,-1.0,-1.0,0.0,2.43384 +1214,search,112009,0.98394,0.0444752,360.374,2.43384 +1215,delete,69.571,-1.0,-1.0,0.0,2.42642 +1216,search,110220,0.98389,0.0445823,362.829,2.42642 +1217,delete,723.941,-1.0,-1.0,0.0,2.2743 +1218,search,110157,0.98341,0.0454752,358.16,2.2743 +1219,delete,265.313,-1.0,-1.0,0.0,2.22938 +1220,search,109583,0.98321,0.0462328,355.481,2.22938 +1221,delete,124.458,-1.0,-1.0,0.0,2.21359 +1222,search,108420,0.98314,0.0464533,351.626,2.21359 +1223,delete,528.966,-1.0,-1.0,0.0,2.10853 +1224,search,108413,0.98258,0.0471447,353.053,2.10853 +1225,delete,114.733,-1.0,-1.0,0.0,2.09138 +1226,search,109164,0.98241,0.0474301,349.306,2.09138 +1227,delete,226.715,-1.0,-1.0,0.0,2.05962 +1228,search,110346,0.98245,0.0472969,359.03,2.05962 +1229,delete,268.812,-1.0,-1.0,0.0,2.02093 +1230,search,109916,0.98215,0.048026,355.355,2.02093 +1231,delete,223.718,-1.0,-1.0,0.0,1.98225 +1232,search,109052,0.98136,0.0493019,359.646,1.98225 +1233,delete,52.538,-1.0,-1.0,0.0,1.97571 +1234,search,108890,0.98136,0.0492816,356.164,1.97571 +1235,delete,406.318,-1.0,-1.0,0.0,1.90439 +1236,search,108949,0.98117,0.0497674,355.943,1.90439 +1237,delete,63.316,-1.0,-1.0,0.0,1.89609 +1238,search,109007,0.98115,0.0497782,353.237,1.89609 +1239,delete,214.345,-1.0,-1.0,0.0,1.87096 +1240,search,109075,0.98106,0.0499544,351.791,1.87096 +1241,delete,160.158,-1.0,-1.0,0.0,1.84977 +1242,search,108969,0.98094,0.0502271,350.291,1.84977 +1243,delete,177.281,-1.0,-1.0,0.0,1.82578 +1244,search,109257,0.98074,0.0505476,355.685,1.82578 +1245,delete,63.886,-1.0,-1.0,0.0,1.81804 +1246,search,105704,0.98074,0.0505278,356.678,1.81804 +1247,delete,167.854,-1.0,-1.0,0.0,1.78373 +1248,search,110346,0.97958,0.0518213,360.958,1.78373 +1249,delete,141.561,-1.0,-1.0,0.0,1.76624 +1250,search,109231,0.97942,0.0520641,361.239,1.76624 +1251,delete,119.651,-1.0,-1.0,0.0,1.751 +1252,search,108558,0.97938,0.0520694,358.978,1.751 +1253,delete,62.73,-1.0,-1.0,0.0,1.74307 +1254,search,108510,0.97939,0.0521015,359.032,1.74307 +1255,delete,289.498,-1.0,-1.0,0.0,1.6858 +1256,search,108146,0.97926,0.0522155,354.65,1.6858 +1257,delete,118.067,-1.0,-1.0,0.0,1.6675 +1258,search,107686,0.97912,0.0524072,354.24,1.6675 +1259,delete,171.132,-1.0,-1.0,0.0,1.64354 +1260,search,107343,0.97905,0.0525184,355.317,1.64354 +1261,delete,83.405,-1.0,-1.0,0.0,1.63394 +1262,search,108352,0.97888,0.0527668,352.16,1.63394 +1263,delete,291.73,-1.0,-1.0,0.0,1.58435 +1264,search,107159,0.97886,0.05268,357.71,1.58435 +1265,delete,605.21,-1.0,-1.0,0.0,1.46851 +1266,search,108248,0.97891,0.0526718,357.202,1.46851 +1267,delete,261.086,-1.0,-1.0,0.0,1.43332 +1268,search,106245,0.97865,0.0530986,356.4,1.43332 +1269,delete,408.63,-1.0,-1.0,0.0,1.37062 +1270,search,108541,0.97888,0.0527857,358.147,1.37062 +1271,delete,268.904,-1.0,-1.0,0.0,1.33192 +1272,search,108613,0.97856,0.053034,356.555,1.33192 +1273,delete,341.932,-1.0,-1.0,0.0,1.27444 +1274,search,106645,0.97854,0.0530985,354.338,1.27444 +1275,delete,96.76,-1.0,-1.0,0.0,1.26343 +1276,search,106850,0.97849,0.0533184,355.204,1.26343 +1277,delete,130.783,-1.0,-1.0,0.0,1.24783 +1278,search,106375,0.9785,0.0535525,354.31,1.24783 +1279,delete,116.543,-1.0,-1.0,0.0,1.23556 +1280,search,106817,0.97846,0.0536125,354.188,1.23556 diff --git a/scripts/big_ann_perf_numbers/scan_using_batching_optimizations.csv b/scripts/big_ann_perf_numbers/scan_using_batching_optimizations.csv new file mode 100644 index 00000000..ff5bf830 --- /dev/null +++ b/scripts/big_ann_perf_numbers/scan_using_batching_optimizations.csv @@ -0,0 +1,251 @@ +step_num,step_type,latency_ms,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +2,search,2632.01,0.78814,0.157167,27.1243,17.7481,5.413,0.0184881,1024,38806 +3,insert,13.386,-1.0,-1.0,-1.0,-1.0,4.861,0.0226668,1024,49334 +4,search,1917.41,0.80378,0.157445,25.2878,17.2311,5.214,0.0226668,1024,49334 +5,insert,19.873,-1.0,-1.0,-1.0,-1.0,144.105,0.0334005,1024,73557 +6,search,1888.79,0.8809,0.134059,18.3656,16.172,94.741,0.033569,1028,73557 +7,insert,35.539,-1.0,-1.0,-1.0,-1.0,82.73,0.0429987,1029,95766 +8,search,1946.28,0.87389,0.135667,18.3448,15.5452,83.028,0.0429987,1029,95766 +9,insert,4.601,-1.0,-1.0,-1.0,-1.0,81.497,0.0447654,1029,100025 +10,search,1850.54,0.87441,0.134003,18.1401,15.2176,82.995,0.0447654,1029,100025 +11,insert,10.982,-1.0,-1.0,-1.0,-1.0,84.771,0.0495206,1029,111417 +12,search,1925.55,0.87669,0.133554,17.9087,15.0639,19.749,0.049652,1030,111417 +13,insert,34.869,-1.0,-1.0,-1.0,-1.0,5.36,0.0608124,1030,137139 +14,search,1943.05,0.87135,0.137981,18.0877,14.8735,13.398,0.0608222,1032,137139 +15,insert,18.482,-1.0,-1.0,-1.0,-1.0,5.164,0.0690103,1032,156710 +16,search,1884.59,0.8661,0.137958,18.2658,14.554,12.344,0.0690157,1035,156710 +17,insert,4.59,-1.0,-1.0,-1.0,-1.0,4.7,0.0713474,1035,161773 +18,search,1982.27,0.86496,0.138886,18.2326,14.5256,5.175,0.0713474,1035,161773 +19,insert,28.835,-1.0,-1.0,-1.0,-1.0,4.086,0.0781561,1035,177161 +20,search,1836.34,0.87166,0.134643,17.8515,14.4067,7.754,0.0781561,1035,177161 +21,insert,403.667,-1.0,-1.0,-1.0,-1.0,117.814,0.199758,1063,448898 +22,search,2081.83,0.86327,0.134857,19.2662,15.0447,27.848,0.199809,1069,448898 +23,insert,409.62,-1.0,-1.0,-1.0,-1.0,311.87,0.328989,1120,733493 +24,search,2541.04,0.85706,0.137099,20.1174,15.5544,46.644,0.329308,1131,733493 +25,insert,38.98,-1.0,-1.0,-1.0,-1.0,14.227,0.346145,1132,777443 +26,search,2296.53,0.85619,0.13842,20.2556,15.629,7.125,0.346145,1132,777443 +27,insert,29.156,-1.0,-1.0,-1.0,-1.0,10.562,0.357722,1133,805394 +28,search,2309.62,0.85729,0.137691,20.2172,15.6079,13.596,0.35797,1134,805394 +29,insert,67.381,-1.0,-1.0,-1.0,-1.0,35.009,0.385411,1141,866391 +30,search,2259.64,0.86042,0.137113,19.9102,15.5618,14.225,0.385411,1143,866391 +31,insert,449.841,-1.0,-1.0,-1.0,-1.0,344.588,0.55332,1199,1239816 +32,search,2566.69,0.85078,0.143067,21.0299,16.3049,57.874,0.553319,1203,1239816 +33,insert,49.195,-1.0,-1.0,-1.0,-1.0,21.03,0.573388,1207,1291211 +34,search,2637.32,0.85248,0.141198,21.0615,16.3669,40.36,0.573391,1210,1291211 +35,insert,48.962,-1.0,-1.0,-1.0,-1.0,28.407,0.585617,1215,1324978 +36,search,2679.79,0.85453,0.13992,20.9283,16.3451,7.076,0.585617,1215,1324978 +37,insert,67.274,-1.0,-1.0,-1.0,-1.0,28.986,0.607368,1219,1371885 +38,search,2691.33,0.85524,0.139471,21.0539,16.5981,11.789,0.607368,1220,1371885 +39,insert,8.003,-1.0,-1.0,-1.0,-1.0,6.592,0.610279,1220,1379335 +40,search,2699.52,0.85643,0.139086,21.0585,16.6344,7.21,0.610279,1220,1379335 +41,insert,36.694,-1.0,-1.0,-1.0,-1.0,26.993,0.623715,1226,1413312 +42,search,2733.34,0.85614,0.139715,21.0612,16.6814,7.142,0.623715,1226,1413312 +43,insert,10.595,-1.0,-1.0,-1.0,-1.0,6.634,0.627081,1226,1423411 +44,search,2717.31,0.85652,0.139367,21.0669,16.7085,13.307,0.62731,1227,1423411 +45,insert,196.158,-1.0,-1.0,-1.0,-1.0,11.277,0.640857,1229,1457559 +46,search,2733.39,0.85693,0.13898,20.9978,16.7575,7.014,0.640857,1229,1457559 +47,insert,322.675,-1.0,-1.0,-1.0,-1.0,232.876,0.746731,1259,1688593 +48,search,2906.63,0.86012,0.140045,20.7731,16.9772,77.789,0.746751,1265,1688593 +49,insert,45.189,-1.0,-1.0,-1.0,-1.0,19.325,0.76124,1268,1723505 +50,search,2911.56,0.86114,0.140008,20.7456,17.0214,23.492,0.761241,1270,1723505 +51,insert,347.994,-1.0,-1.0,-1.0,-1.0,199.574,0.900893,1303,2035040 +52,search,3104.82,0.86564,0.138716,20.5745,17.3909,17.913,0.901045,1307,2035040 +53,insert,22.179,-1.0,-1.0,-1.0,-1.0,17.241,0.919777,1311,2078341 +54,search,2444.74,0.86631,0.138402,20.5859,17.3743,8.543,0.919785,1312,2078341 +55,insert,192.021,-1.0,-1.0,-1.0,-1.0,267.73,1.06766,1355,2399905 +56,search,2621.24,0.86822,0.138735,20.3907,17.5395,64.348,1.06788,1369,2399905 +57,insert,19.433,-1.0,-1.0,-1.0,-1.0,8.015,1.07681,1370,2419836 +58,search,2632.25,0.86868,0.138522,20.4308,17.6446,26.228,1.07692,1375,2419836 +59,insert,126.721,-1.0,-1.0,-1.0,-1.0,80.962,1.17577,1386,2643083 +60,search,2689.86,0.86011,0.146646,21.878,19.1613,15.293,1.17595,1389,2643083 +61,insert,7.176,-1.0,-1.0,-1.0,-1.0,13.366,1.1789,1392,2653064 +62,search,2706.09,0.86032,0.146639,21.9275,19.2063,4.959,1.1789,1392,2653064 +63,insert,2.475,-1.0,-1.0,-1.0,-1.0,4.577,1.18047,1392,2656118 +64,search,3115.77,0.8604,0.146416,21.9225,19.2141,13.038,1.18058,1393,2656118 +65,insert,78.884,-1.0,-1.0,-1.0,-1.0,104.077,1.20899,1411,2723424 +66,search,3501.54,0.86183,0.144898,21.9506,19.2159,7.931,1.20899,1411,2723424 +67,insert,45.836,-1.0,-1.0,-1.0,-1.0,73.427,1.22966,1424,2769021 +68,search,3542.28,0.86232,0.144708,21.8205,19.1541,15.812,1.22966,1425,2769021 +69,insert,59.997,-1.0,-1.0,-1.0,-1.0,52.322,1.25219,1432,2821777 +70,search,3580.57,0.86494,0.142718,21.5631,19.0287,14.669,1.2522,1433,2821777 +71,insert,18.517,-1.0,-1.0,-1.0,-1.0,27.016,1.25833,1436,2834921 +72,search,3610.55,0.86539,0.14234,21.5078,19.0046,8.544,1.25833,1436,2834921 +73,insert,7.505,-1.0,-1.0,-1.0,-1.0,19.883,1.26069,1438,2842044 +74,search,3624.63,0.86524,0.142453,21.4984,18.9971,8.232,1.26069,1438,2842044 +75,insert,24.776,-1.0,-1.0,-1.0,-1.0,26.473,1.26741,1441,2858890 +76,search,3649.68,0.86629,0.141337,21.475,18.9623,21.085,1.26766,1443,2858890 +77,insert,32.532,-1.0,-1.0,-1.0,-1.0,25.674,1.27695,1446,2882818 +78,search,3625.03,0.86492,0.142189,21.579,19.0371,8.484,1.27695,1446,2882818 +79,insert,467.313,-1.0,-1.0,-1.0,-1.0,7.24,1.30434,1446,2947806 +80,search,3636.89,0.86495,0.14229,21.6919,19.1546,8.306,1.30434,1446,2947806 +81,insert,34.646,-1.0,-1.0,-1.0,-1.0,29.468,1.31699,1449,2976895 +82,search,3646.04,0.86584,0.141918,21.5183,19.0851,7.975,1.31699,1449,2976895 +83,insert,15.699,-1.0,-1.0,-1.0,-1.0,19.101,1.3229,1451,2990682 +84,search,3660.72,0.86702,0.140947,21.4726,19.0689,9.047,1.3229,1451,2990682 +85,insert,39.612,-1.0,-1.0,-1.0,-1.0,20.07,1.33627,1453,3025613 +86,search,3624.78,0.86791,0.140661,21.375,19.0761,8.325,1.33627,1453,3025613 +87,insert,671.505,-1.0,-1.0,-1.0,-1.0,560.225,1.5433,1524,3468632 +88,search,4018.18,0.87117,0.138193,20.9937,18.8929,88.589,1.54333,1535,3468632 +89,insert,418.166,-1.0,-1.0,-1.0,-1.0,445.405,1.70092,1595,3831692 +90,search,4258.33,0.87535,0.133437,20.6001,18.5074,44.56,1.7011,1600,3831692 +91,insert,40.406,-1.0,-1.0,-1.0,-1.0,34.17,1.71286,1604,3864067 +92,search,4291.22,0.87541,0.1332,20.6264,18.5244,15.297,1.71291,1605,3864067 +93,insert,270.232,-1.0,-1.0,-1.0,-1.0,187.571,1.81663,1628,4103827 +94,search,4401.52,0.87596,0.13334,20.4969,18.4313,28.677,1.81684,1630,4103827 +95,insert,18.795,-1.0,-1.0,-1.0,-1.0,21.703,1.82315,1632,4119898 +96,search,4338.53,0.8768,0.132725,20.449,18.4249,15.911,1.82329,1633,4119898 +97,insert,11.366,-1.0,-1.0,-1.0,-1.0,22.009,1.82724,1635,4129367 +98,search,4399.33,0.87635,0.132979,20.4711,18.4304,9.554,1.82724,1635,4129367 +99,insert,5.836,-1.0,-1.0,-1.0,-1.0,22.732,1.82884,1637,4134502 +100,search,4416.76,0.87634,0.133101,20.4432,18.4272,10.738,1.82884,1637,4134502 +101,insert,37.583,-1.0,-1.0,-1.0,-1.0,38.519,1.84193,1642,4164482 +102,search,4465.68,0.87692,0.132818,20.4162,18.4205,10.145,1.84193,1642,4164482 +103,insert,15.477,-1.0,-1.0,-1.0,-1.0,22.676,1.84756,1644,4178601 +104,search,4443.6,0.87701,0.13287,20.3856,18.3963,10.762,1.84756,1644,4178601 +105,insert,12.599,-1.0,-1.0,-1.0,-1.0,17.064,1.85088,1645,4187774 +106,search,4469.21,0.87704,0.132927,20.3724,18.3854,10.587,1.85088,1645,4187774 +107,insert,22.857,-1.0,-1.0,-1.0,-1.0,9.367,1.85653,1645,4200109 +108,search,4468.94,0.87714,0.1331,20.3782,18.3998,18.019,1.85681,1646,4200109 +109,insert,556.199,-1.0,-1.0,-1.0,-1.0,535.436,2.02015,1713,4557867 +110,search,4724.51,0.87922,0.13168,20.2081,18.4495,76.833,2.02124,1721,4557867 +111,insert,31.283,-1.0,-1.0,-1.0,-1.0,93.1,2.03272,1736,4587252 +112,search,4777.86,0.87917,0.131589,20.1872,18.4653,20.779,2.03301,1737,4587252 +113,insert,12.125,-1.0,-1.0,-1.0,-1.0,25.675,2.03628,1739,4600056 +114,search,4767.28,0.87921,0.131581,20.1737,18.466,12.165,2.03628,1739,4600056 +115,insert,39.108,-1.0,-1.0,-1.0,-1.0,17.433,2.04741,1740,4627422 +116,search,4799.69,0.88041,0.130799,20.0795,18.4134,18.172,2.04748,1741,4627422 +117,insert,11.424,-1.0,-1.0,-1.0,-1.0,10.782,2.05029,1741,4639292 +118,search,4790.3,0.88052,0.130588,20.0782,18.4176,12.466,2.05029,1741,4639292 +119,insert,4.439,-1.0,-1.0,-1.0,-1.0,10.977,2.0514,1741,4643423 +120,search,4490.36,0.88058,0.130556,20.075,18.4178,13.098,2.0514,1741,4643423 +121,insert,22.447,-1.0,-1.0,-1.0,-1.0,38.926,2.05832,1745,4657252 +122,search,4811.11,0.88046,0.130671,20.0593,18.4214,13.487,2.05832,1745,4657252 +123,insert,387.349,-1.0,-1.0,-1.0,-1.0,477.646,2.18625,1784,4938477 +124,search,4741.85,0.88126,0.131424,19.836,18.3256,149.472,2.18696,1797,4938477 +125,insert,63.723,-1.0,-1.0,-1.0,-1.0,68.576,2.20464,1805,4980492 +126,search,4945.4,0.88175,0.131552,19.7332,18.3052,40.516,2.20493,1807,4980492 +127,insert,71.663,-1.0,-1.0,-1.0,-1.0,77.772,2.22549,1817,5030515 +128,search,5042.96,0.88258,0.130504,19.6553,18.281,26.1,2.22549,1818,5030515 +129,delete,19.093,-1.0,-1.0,-1.0,-1.0,13.843,2.22511,1818,5009391 +130,search,4985.66,0.88254,0.130721,19.6659,18.3152,14.896,2.22511,1818,5009391 +131,delete,5.049,-1.0,-1.0,-1.0,-1.0,14.37,2.22511,1818,5004093 +132,search,4884.29,0.8826,0.130672,19.6524,18.3112,14.966,2.22511,1818,5004093 +133,delete,10.465,-1.0,-1.0,-1.0,-1.0,14.63,2.22511,1818,4991787 +134,search,5172.17,0.88266,0.130641,19.6579,18.3209,14.912,2.22511,1818,4991787 +135,delete,15.141,-1.0,-1.0,-1.0,-1.0,13.527,2.22431,1818,4974857 +136,search,5020.67,0.88305,0.13039,19.6213,18.3125,15.709,2.22431,1818,4974857 +137,delete,3.632,-1.0,-1.0,-1.0,-1.0,13.939,2.22431,1818,4971386 +138,search,5145.8,0.88306,0.130408,19.6283,18.3103,15.398,2.22431,1818,4971386 +139,delete,9.093,-1.0,-1.0,-1.0,-1.0,13.458,2.22431,1818,4963487 +140,search,5152.2,0.88293,0.130377,19.6583,18.3337,15.724,2.22431,1818,4963487 +141,delete,21.212,-1.0,-1.0,-1.0,-1.0,13.46,2.2238,1818,4941830 +142,search,5089.69,0.88303,0.130512,19.6694,18.3454,15.821,2.2238,1818,4941830 +143,delete,19.729,-1.0,-1.0,-1.0,-1.0,13.594,2.22143,1818,4925657 +144,search,4939.51,0.88286,0.130569,19.6885,18.3691,15.475,2.22143,1818,4925657 +145,delete,3.089,-1.0,-1.0,-1.0,-1.0,13.569,2.22143,1818,4922686 +146,search,5117.11,0.8829,0.130595,19.6756,18.3759,15.167,2.22143,1818,4922686 +147,delete,8.829,-1.0,-1.0,-1.0,-1.0,13.581,2.22143,1818,4913636 +148,search,4687.71,0.88296,0.130442,19.7007,18.4006,15.293,2.22143,1818,4913636 +149,delete,214.747,-1.0,-1.0,-1.0,-1.0,14.057,2.19857,1818,4717250 +150,search,4674.98,0.88245,0.130901,19.7853,18.5084,16.034,2.19857,1818,4717250 +151,delete,205.28,-1.0,-1.0,-1.0,-1.0,13.772,2.16451,1818,4560269 +152,search,4702.32,0.88134,0.131449,19.9457,18.5862,16.302,2.16451,1818,4560269 +153,delete,42.694,-1.0,-1.0,-1.0,-1.0,14.264,2.15391,1818,4521936 +154,search,4485.95,0.88054,0.132039,20.0548,18.6561,13.066,2.15391,1818,4521936 +155,delete,13.778,-1.0,-1.0,-1.0,-1.0,11.574,2.15176,1818,4502222 +156,search,4816.93,0.88057,0.131992,20.0546,18.6743,16.323,2.15176,1818,4502222 +157,delete,45.791,-1.0,-1.0,-1.0,-1.0,14.145,2.14629,1818,4456039 +158,search,4813.85,0.88001,0.132422,20.1212,18.7246,16.791,2.14629,1818,4456039 +159,delete,360.096,-1.0,-1.0,-1.0,-1.0,13.851,2.03063,1818,4143922 +160,search,4659.24,0.87823,0.133662,20.3417,18.9219,16.181,2.03063,1818,4143922 +161,delete,54.129,-1.0,-1.0,-1.0,-1.0,14.127,2.02303,1818,4101445 +162,search,4631.16,0.87828,0.133838,20.3345,18.9356,15.453,2.02303,1818,4101445 +163,delete,23.591,-1.0,-1.0,-1.0,-1.0,13.519,2.01367,1818,4080175 +164,search,4594.68,0.87784,0.13412,20.4039,18.9657,16.077,2.01367,1818,4080175 +165,delete,37.81,-1.0,-1.0,-1.0,-1.0,13.654,2.00452,1818,4047313 +166,search,4566.84,0.87786,0.134303,20.4205,18.9917,16.011,2.00452,1818,4047313 +167,delete,11.982,-1.0,-1.0,-1.0,-1.0,13.7,2.00213,1818,4040738 +168,search,4577.01,0.87769,0.134525,20.442,18.9951,16.602,2.00213,1818,4040738 +169,delete,23.242,-1.0,-1.0,-1.0,-1.0,13.448,1.9968,1818,4022674 +170,search,4557.45,0.87728,0.13473,20.4726,19.0108,16.509,1.9968,1818,4022674 +171,delete,13.345,-1.0,-1.0,-1.0,-1.0,13.768,1.99291,1818,4015835 +172,search,4779.47,0.87722,0.134757,20.4886,19.027,16.678,1.99291,1818,4015835 +173,delete,50.949,-1.0,-1.0,-1.0,-1.0,13.775,1.97858,1818,3986424 +174,search,4398.77,0.87638,0.135267,20.5634,19.0825,16.575,1.97858,1818,3986424 +175,delete,221.359,-1.0,-1.0,-1.0,-1.0,13.538,1.90948,1818,3804693 +176,search,4468.46,0.87432,0.135894,20.8358,19.1572,16.399,1.90948,1818,3804693 +177,delete,24.189,-1.0,-1.0,-1.0,-1.0,13.992,1.90402,1818,3786352 +178,search,4470.6,0.87397,0.135945,20.8741,19.165,16.117,1.90402,1818,3786352 +179,delete,252,-1.0,-1.0,-1.0,-1.0,13.345,1.80199,1818,3556994 +180,search,4240.15,0.86966,0.137334,21.4185,19.2499,16.171,1.80199,1818,3556994 +181,delete,44.096,-1.0,-1.0,-1.0,-1.0,13.839,1.78699,1818,3526824 +182,search,4305.69,0.86931,0.137605,21.447,19.2757,17.145,1.78699,1818,3526824 +183,delete,188.078,-1.0,-1.0,-1.0,-1.0,13.408,1.70964,1818,3350245 +184,search,4208.79,0.86244,0.142242,22.4081,19.7594,11.86,1.70964,1818,3350245 +185,delete,9.299,-1.0,-1.0,-1.0,-1.0,9.741,1.70627,1818,3340234 +186,search,4044.88,0.86248,0.14221,22.419,19.7658,13.894,1.70627,1818,3340234 +187,delete,166.412,-1.0,-1.0,-1.0,-1.0,12.763,1.6162,1818,3150857 +188,search,4040.95,0.8646,0.140539,21.9776,19.3985,16.938,1.6162,1818,3150857 +189,delete,11.059,-1.0,-1.0,-1.0,-1.0,14.157,1.61417,1818,3143609 +190,search,4165.7,0.86438,0.140673,21.9963,19.4198,10.843,1.61417,1818,3143609 +191,delete,4.444,-1.0,-1.0,-1.0,-1.0,11.889,1.61165,1818,3141038 +192,search,4094.82,0.86432,0.140676,21.9935,19.412,16.674,1.61165,1818,3141038 +193,delete,79.172,-1.0,-1.0,-1.0,-1.0,14.017,1.57978,1818,3081734 +194,search,3835.92,0.86281,0.141605,22.2438,19.5746,14.223,1.57978,1818,3081734 +195,delete,36.41,-1.0,-1.0,-1.0,-1.0,12.749,1.56014,1818,3043966 +196,search,3957.4,0.86208,0.142669,22.3273,19.6372,16.62,1.56014,1818,3043966 +197,delete,48.541,-1.0,-1.0,-1.0,-1.0,14.48,1.54298,1818,3008145 +198,search,3955.07,0.86155,0.142716,22.4142,19.6992,13.272,1.54298,1818,3008145 +199,delete,10.948,-1.0,-1.0,-1.0,-1.0,11.866,1.53834,1818,2999384 +200,search,3900.97,0.861,0.142993,22.4903,19.7293,11.601,1.53834,1818,2999384 +201,delete,5.192,-1.0,-1.0,-1.0,-1.0,9.332,1.53572,1818,2993528 +202,search,3449.55,0.86068,0.143014,22.5371,19.7501,17.535,1.53572,1818,2993528 +203,delete,21.045,-1.0,-1.0,-1.0,-1.0,14.451,1.53002,1818,2980973 +204,search,3959.78,0.8606,0.143098,22.5167,19.7202,17.482,1.53002,1818,2980973 +205,delete,33.381,-1.0,-1.0,-1.0,-1.0,14.656,1.52116,1818,2960291 +206,search,4035.31,0.86061,0.143017,22.5579,19.7135,10.88,1.52116,1818,2960291 +207,delete,33.21,-1.0,-1.0,-1.0,-1.0,9.695,1.50162,1818,2920620 +208,search,3114.5,0.86016,0.143377,22.5352,19.6886,10.775,1.50162,1818,2920620 +209,delete,16.775,-1.0,-1.0,-1.0,-1.0,9.678,1.49058,1818,2900501 +210,search,3118.7,0.85971,0.142991,22.6386,19.7055,10.7,1.49058,1818,2900501 +211,delete,7.223,-1.0,-1.0,-1.0,-1.0,9.46,1.48588,1818,2891660 +212,search,3853.94,0.85936,0.143372,22.6681,19.7394,13.961,1.48588,1818,2891660 +213,delete,15.712,-1.0,-1.0,-1.0,-1.0,12.248,1.47657,1818,2873257 +214,search,3834.44,0.85812,0.143949,22.8108,19.8141,17.018,1.47657,1818,2873257 +215,delete,372.361,-1.0,-1.0,-1.0,-1.0,13.979,1.3127,1818,2537571 +216,search,3722.23,0.85124,0.147583,23.6987,20.1773,17.155,1.3127,1818,2537571 +217,delete,246.559,-1.0,-1.0,-1.0,-1.0,14.116,1.19323,1818,2308194 +218,search,3642.65,0.8453,0.151171,24.312,20.5364,17.577,1.19323,1818,2308194 +219,delete,33.261,-1.0,-1.0,-1.0,-1.0,14.937,1.18109,1818,2285820 +220,search,3620.99,0.84415,0.152147,24.3499,20.5214,12.435,1.18109,1818,2285820 +221,delete,148.05,-1.0,-1.0,-1.0,-1.0,10.136,1.08192,1818,2082858 +222,search,3462.6,0.84261,0.151629,24.6078,20.5822,17.682,1.08192,1818,2082858 +223,delete,15.465,-1.0,-1.0,-1.0,-1.0,14.671,1.0757,1818,2071207 +224,search,3622.73,0.84146,0.152477,24.7149,20.5876,18.589,1.0757,1818,2071207 +225,delete,11.565,-1.0,-1.0,-1.0,-1.0,14.936,1.07328,1818,2065400 +226,search,3619.2,0.84121,0.152693,24.7684,20.6486,14.044,1.07328,1818,2065400 +227,delete,4.633,-1.0,-1.0,-1.0,-1.0,12.014,1.07066,1818,2062105 +228,search,3695.82,0.8409,0.152874,24.7888,20.6526,11.227,1.07066,1818,2062105 +229,delete,19.284,-1.0,-1.0,-1.0,-1.0,9.736,1.05706,1818,2039610 +230,search,3669.43,0.83892,0.153675,25.1294,20.8892,11.449,1.05706,1818,2039610 +231,delete,9.247,-1.0,-1.0,-1.0,-1.0,9.669,1.05025,1818,2027795 +232,search,3618.02,0.83784,0.154555,25.2542,20.9423,17.72,1.05025,1818,2027795 +233,delete,6.887,-1.0,-1.0,-1.0,-1.0,14.056,1.04807,1818,2022859 +234,search,3168.24,0.83751,0.154199,25.287,20.9366,11.084,1.04807,1818,2022859 +235,delete,5.077,-1.0,-1.0,-1.0,-1.0,9.661,1.04502,1818,2016264 +236,search,3103.44,0.83737,0.154328,25.3089,20.9416,11.13,1.04502,1818,2016264 +237,delete,173.802,-1.0,-1.0,-1.0,-1.0,10.223,0.922922,1818,1782866 +238,search,2950.14,0.83203,0.156784,26.1193,21.3925,10.968,0.922922,1818,1782866 +239,delete,15.404,-1.0,-1.0,-1.0,-1.0,9.793,0.910989,1818,1758931 +240,search,2737.08,0.82973,0.157742,26.3511,21.4413,10.913,0.910989,1818,1758931 +241,delete,5.298,-1.0,-1.0,-1.0,-1.0,9.709,0.907239,1818,1751275 +242,search,2744.69,0.82902,0.158101,26.4445,21.4555,10.906,0.907239,1818,1751275 +243,delete,12.776,-1.0,-1.0,-1.0,-1.0,9.744,0.899058,1818,1733264 +244,search,2843.13,0.82606,0.15926,27.4257,22.483,20.171,0.899058,1818,1733264 +245,delete,17.962,-1.0,-1.0,-1.0,-1.0,14.817,0.893956,1818,1722658 +246,search,3641.97,0.82565,0.159138,27.4898,22.497,18.578,0.893956,1818,1722658 +247,delete,6.054,-1.0,-1.0,-1.0,-1.0,15.18,0.892665,1818,1719601 +248,search,3453.26,0.825,0.159104,27.7058,22.7279,11.463,0.892665,1818,1719601 +249,delete,8.317,-1.0,-1.0,-1.0,-1.0,9.489,0.888585,1818,1711648 +250,search,3057.08,0.82427,0.159272,27.8052,22.7611,11.336,0.888585,1818,1711648 +251,delete,189.372,-1.0,-1.0,-1.0,-1.0,10.081,0.766745,1818,1470624 diff --git a/scripts/big_ann_perf_numbers/scan_vary_using_batching_250_no_aps.csv b/scripts/big_ann_perf_numbers/scan_vary_using_batching_250_no_aps.csv new file mode 100644 index 00000000..813fa8c7 --- /dev/null +++ b/scripts/big_ann_perf_numbers/scan_vary_using_batching_250_no_aps.csv @@ -0,0 +1,506 @@ +nprobe_percentage,step_num,step_type,latency_ms,recall_mean,recall_std_dev,mainteance_ms,index_mem_gb +0.95,2,search,9523.51,0.99971,0.00556076,9.033,0.0183461 +0.95,3,insert,18.725,-1.0,-1.0,0.0,0.0223849 +0.95,4,search,8441.92,0.9998,0.00468646,29.819,0.0224592 +0.95,5,insert,32.874,-1.0,-1.0,0.0,0.0330443 +0.95,6,search,8228.4,0.99993,0.0026449,105.336,0.0329754 +0.95,7,insert,45.215,-1.0,-1.0,0.0,0.0423855 +0.95,8,search,8388.71,0.99993,0.00264495,182.055,0.0422158 +0.95,9,insert,5.194,-1.0,-1.0,0.0,0.0442806 +0.95,10,search,8559.42,0.99992,0.00282753,132.976,0.0443737 +0.95,11,insert,11.98,-1.0,-1.0,0.0,0.0493843 +0.95,12,search,9087.21,0.99992,0.00282753,260.257,0.0494251 +0.95,13,insert,45.997,-1.0,-1.0,0.0,0.0606586 +0.95,14,search,9818.98,0.99994,0.0024489,337.415,0.0607059 +0.95,15,insert,26.07,-1.0,-1.0,0.0,0.0692592 +0.95,16,search,10597.9,0.99995,0.0022356,382.59,0.0695305 +0.95,17,insert,5.274,-1.0,-1.0,0.0,0.0716848 +0.95,18,search,10780.6,0.99996,0.00199968,215.298,0.0714449 +0.95,19,insert,44.155,-1.0,-1.0,0.0,0.0780512 +0.95,20,search,11964.3,0.99993,0.00264493,341.831,0.0780985 +0.95,21,insert,463.795,-1.0,-1.0,0.0,0.19728 +0.95,22,search,13010.3,0.99996,0.00199969,1886.63,0.196769 +0.95,23,insert,480.486,-1.0,-1.0,0.0,0.320353 +0.95,24,search,17137.2,0.99995,0.00223565,3961.6,0.322334 +0.95,25,insert,63.865,-1.0,-1.0,0.0,0.34112 +0.95,26,search,23845.3,0.99992,0.00282754,3079.21,0.341868 +0.95,27,insert,48.103,-1.0,-1.0,0.0,0.353831 +0.95,28,search,30776.5,0.99989,0.00331516,2836.04,0.354129 +0.95,29,insert,94.993,-1.0,-1.0,0.0,0.380489 +0.95,30,search,37498.2,0.9999,0.00316067,2164.36,0.381163 +0.95,31,insert,722.609,-1.0,-1.0,0.0,0.544157 +0.95,32,search,40686.7,0.99991,0.00299873,6087.03,0.544795 +0.95,33,insert,89.047,-1.0,-1.0,0.0,0.566606 +0.95,34,search,49355.1,0.99991,0.00299873,4477.65,0.567682 +0.95,35,insert,77.839,-1.0,-1.0,0.0,0.582318 +0.95,36,search,54964.6,0.99993,0.00264507,2566.38,0.582666 +0.95,37,insert,124.842,-1.0,-1.0,0.0,0.60306 +0.95,38,search,59086.5,0.99993,0.00264507,1764.02,0.603237 +0.95,39,insert,12.458,-1.0,-1.0,0.0,0.606432 +0.95,40,search,62049,0.99993,0.00264507,679.175,0.606314 +0.95,41,insert,83.216,-1.0,-1.0,0.0,0.621281 +0.95,42,search,62419.7,0.99991,0.0029987,855.505,0.621315 +0.95,43,insert,34.744,-1.0,-1.0,0.0,0.625901 +0.95,44,search,63523,0.99992,0.00282754,705.264,0.625923 +0.95,45,insert,391.399,-1.0,-1.0,0.0,0.640966 +0.95,46,search,64143.8,0.99993,0.00264507,1095.75,0.641074 +0.95,47,insert,609.552,-1.0,-1.0,0.0,0.741265 +0.95,48,search,64732.8,0.99996,0.00199959,4215.21,0.742498 +0.95,49,insert,76.004,-1.0,-1.0,0.0,0.75791 +0.95,50,search,69199.4,0.99997,0.00173174,2198.96,0.758022 +0.95,51,insert,697.786,-1.0,-1.0,0.0,0.893925 +0.95,52,search,74107.5,0.99995,0.00223571,11123,0.894839 +0.95,53,insert,122.635,-1.0,-1.0,0.0,0.913612 +0.95,54,search,83606.8,0.99994,0.0024489,5471.53,0.913871 +0.95,55,insert,795.383,-1.0,-1.0,0.0,1.05568 +0.95,56,search,90278.6,0.99997,0.00173174,10166.5,1.05468 +0.95,57,insert,75.956,-1.0,-1.0,0.0,1.06361 +0.95,58,search,94437.6,0.99997,0.00173174,3955.38,1.06383 +0.95,59,insert,594.061,-1.0,-1.0,0.0,1.16262 +0.95,60,search,100894,0.99997,0.00173174,7526.01,1.16071 +0.95,61,insert,42.304,-1.0,-1.0,0.0,1.16506 +0.95,62,search,104385,0.99996,0.00199968,3178.89,1.16621 +0.95,63,insert,10.664,-1.0,-1.0,0.0,1.16759 +0.95,64,search,104833,0.99998,0.00141404,2165.31,1.16709 +0.95,65,insert,316.078,-1.0,-1.0,0.0,1.19644 +0.95,66,search,110058,1,0,4346.5,1.19691 +0.95,67,insert,157.995,-1.0,-1.0,0.0,1.21721 +0.95,68,search,113969,0.99999,0.00099998,2253.5,1.21744 +0.95,69,insert,182.197,-1.0,-1.0,0.0,1.2402 +0.95,70,search,114961,0.99999,0.00099998,2267.82,1.24028 +0.95,71,insert,59.067,-1.0,-1.0,0.0,1.24644 +0.95,72,search,115971,0.99999,0.00099998,1543.38,1.2464 +0.95,73,insert,33.238,-1.0,-1.0,0.0,1.24954 +0.95,74,search,114229,0.99999,0.00099998,1369.61,1.24958 +0.95,75,insert,77.963,-1.0,-1.0,0.0,1.25679 +0.95,76,search,115734,0.99999,0.00099998,1425.66,1.25653 +0.95,77,insert,114.327,-1.0,-1.0,0.0,1.2672 +0.95,78,search,115305,0.99999,0.00099998,1521.6,1.2671 +0.95,79,insert,757.383,-1.0,-1.0,0.0,1.29592 +0.95,80,search,119677,0.99998,0.00141406,2552.79,1.29577 +0.95,81,insert,105.653,-1.0,-1.0,0.0,1.30792 +0.95,82,search,118010,0.99998,0.00141406,1794.7,1.30813 +0.95,83,insert,52.859,-1.0,-1.0,0.0,1.31436 +0.95,84,search,120107,0.99998,0.00141406,1491.52,1.31455 +0.95,85,insert,119.219,-1.0,-1.0,0.0,1.3294 +0.95,86,search,124109,0.99998,0.00141406,1885.07,1.32967 +0.95,87,insert,1438.99,-1.0,-1.0,0.0,1.52354 +0.95,88,search,125005,0.99998,0.00141406,22528.9,1.52442 +0.95,89,insert,1336.56,-1.0,-1.0,0.0,1.68435 +0.95,90,search,139715,0.99998,0.00141406,26890.2,1.68461 +0.95,91,insert,144.186,-1.0,-1.0,0.0,1.69942 +0.95,92,search,150429,0.99998,0.00141406,8889.88,1.69942 +0.95,93,insert,981.427,-1.0,-1.0,0.0,1.80371 +0.95,94,search,161753,0.99998,0.00141406,12834.3,1.8043 +0.95,95,insert,67.921,-1.0,-1.0,0.0,1.8114 +0.95,96,search,163073,0.99998,0.00141406,3668.88,1.81084 +0.95,97,insert,47.185,-1.0,-1.0,0.0,1.81493 +0.95,98,search,165485,0.99998,0.00141406,2184.61,1.81487 +0.95,99,insert,26.804,-1.0,-1.0,0.0,1.81702 +0.95,100,search,168676,0.99998,0.00141406,1852.2,1.81694 +0.95,101,insert,151.763,-1.0,-1.0,0.0,1.8304 +0.95,102,search,168870,0.99998,0.00141406,2254.32,1.83048 +0.75,2,search,5157.84,0.99611,0.0205396,4.12,0.0183461 +0.75,3,insert,10.416,-1.0,-1.0,0.0,0.0223849 +0.75,4,search,5089.6,0.99683,0.0182473,14.831,0.0224592 +0.75,5,insert,28.874,-1.0,-1.0,0.0,0.0330443 +0.75,6,search,6423.46,0.99815,0.0139859,80.202,0.0330488 +0.75,7,insert,38.547,-1.0,-1.0,0.0,0.0423284 +0.75,8,search,6743.25,0.99799,0.0152642,165.47,0.0423373 +0.75,9,insert,4.934,-1.0,-1.0,0.0,0.0440534 +0.75,10,search,6821.04,0.99836,0.0137604,176.435,0.0441281 +0.75,11,insert,14.41,-1.0,-1.0,0.0,0.0493398 +0.75,12,search,7128.61,0.99831,0.0137901,212.535,0.0492244 +0.75,13,insert,32.583,-1.0,-1.0,0.0,0.0603089 +0.75,14,search,7527.01,0.99826,0.0142469,305.35,0.0604427 +0.75,15,insert,26.629,-1.0,-1.0,0.0,0.0689651 +0.75,16,search,8143.18,0.99834,0.0138294,395.425,0.0691254 +0.75,17,insert,5.546,-1.0,-1.0,0.0,0.0712429 +0.75,18,search,8802.48,0.99803,0.0152036,325.553,0.0712246 +0.75,19,insert,49.576,-1.0,-1.0,0.0,0.0779957 +0.75,20,search,9656.65,0.99806,0.0150428,311.335,0.0781646 +0.75,21,insert,439.031,-1.0,-1.0,0.0,0.196456 +0.75,22,search,10409,0.99791,0.0147873,1713.58,0.197361 +0.75,23,insert,483.914,-1.0,-1.0,0.0,0.322766 +0.75,24,search,13379.4,0.99769,0.0158647,3672.3,0.322244 +0.75,25,insert,77.429,-1.0,-1.0,0.0,0.341349 +0.75,26,search,17662.1,0.99646,0.0195844,3312.01,0.341526 +0.75,27,insert,42.537,-1.0,-1.0,0.0,0.353945 +0.75,28,search,18012.2,0.99603,0.0206218,2834.92,0.354809 +0.75,29,insert,102.539,-1.0,-1.0,0.0,0.381047 +0.75,30,search,27281.3,0.9965,0.0191771,2427.6,0.380739 +0.75,31,insert,750.721,-1.0,-1.0,0.0,0.544619 +0.75,32,search,32840.1,0.99652,0.0199991,6297.19,0.544806 +0.75,33,insert,115.726,-1.0,-1.0,0.0,0.567317 +0.75,34,search,37795.2,0.99658,0.0196043,4852.08,0.56763 +0.75,35,insert,95.92,-1.0,-1.0,0.0,0.582627 +0.75,36,search,44984.2,0.99717,0.0173504,2718.8,0.582984 +0.75,37,insert,128.757,-1.0,-1.0,0.0,0.602918 +0.75,38,search,45879.6,0.99748,0.0161148,2016.51,0.60316 +0.75,39,insert,18.148,-1.0,-1.0,0.0,0.60627 +0.75,40,search,47197.9,0.99751,0.0160257,899.167,0.606519 +0.75,41,insert,120.724,-1.0,-1.0,0.0,0.621033 +0.75,42,search,48070.4,0.99759,0.0157864,970.479,0.621073 +0.75,43,insert,35.92,-1.0,-1.0,0.0,0.625271 +0.75,44,search,48729.8,0.99776,0.0149999,652.129,0.625482 +0.75,45,insert,405.013,-1.0,-1.0,0.0,0.64049 +0.75,46,search,48826.9,0.9978,0.0149397,1114.44,0.641175 +0.75,47,insert,665.631,-1.0,-1.0,0.0,0.741888 +0.75,48,search,50664.9,0.99803,0.0141125,3839.29,0.742245 +0.75,49,insert,87.116,-1.0,-1.0,0.0,0.757267 +0.75,50,search,53813.6,0.99807,0.0141165,1918.33,0.757701 +0.75,51,insert,838.734,-1.0,-1.0,0.0,0.894337 +0.75,52,search,56850.5,0.99826,0.0134527,10541.5,0.894381 +0.75,53,insert,132.188,-1.0,-1.0,0.0,0.914297 +0.75,54,search,63808.2,0.99824,0.0135249,5486.98,0.915372 +0.75,55,insert,857.849,-1.0,-1.0,0.0,1.05558 +0.75,56,search,68149.6,0.99845,0.0128298,8718.72,1.05475 +0.75,57,insert,81.533,-1.0,-1.0,0.0,1.06308 +0.75,58,search,73723.8,0.99832,0.0132365,3609.6,1.06424 +0.75,59,insert,607.923,-1.0,-1.0,0.0,1.16312 +0.75,60,search,74026.8,0.99842,0.0127877,7151.63,1.16314 +0.75,61,insert,43.485,-1.0,-1.0,0.0,1.16735 +0.75,62,search,72941.1,0.99835,0.0133531,2662.36,1.16609 +0.75,63,insert,10.599,-1.0,-1.0,0.0,1.16751 +0.75,64,search,76467.6,0.99841,0.013133,1607.62,1.1678 +0.75,65,insert,338.492,-1.0,-1.0,0.0,1.19699 +0.75,66,search,80706.2,0.99861,0.0118774,3614.01,1.19703 +0.75,67,insert,150.313,-1.0,-1.0,0.0,1.21641 +0.75,68,search,83828.1,0.99866,0.011671,2375.81,1.21615 +0.75,69,insert,202.397,-1.0,-1.0,0.0,1.23996 +0.75,70,search,84355.5,0.99871,0.0114609,2483.47,1.24047 +0.75,71,insert,57.209,-1.0,-1.0,0.0,1.24617 +0.75,72,search,83249.4,0.99871,0.0114609,1776.57,1.24603 +0.75,73,insert,32.473,-1.0,-1.0,0.0,1.24922 +0.75,74,search,88491.1,0.99873,0.0113757,1286.27,1.24898 +0.75,75,insert,80.764,-1.0,-1.0,0.0,1.25626 +0.75,76,search,84799.6,0.99874,0.0113325,1329.12,1.25636 +0.75,77,insert,124.679,-1.0,-1.0,0.0,1.26762 +0.75,78,search,84922.9,0.99874,0.0113325,1478.46,1.26782 +0.75,79,insert,761.751,-1.0,-1.0,0.0,1.29621 +0.75,80,search,86215.4,0.99878,0.011248,2322.34,1.29592 +0.75,81,insert,121.402,-1.0,-1.0,0.0,1.30874 +0.75,82,search,87678.7,0.99882,0.0110733,1664.39,1.30874 +0.75,83,insert,54.263,-1.0,-1.0,0.0,1.31517 +0.75,84,search,86665.1,0.99884,0.010985,1343.1,1.31479 +0.75,85,insert,126.908,-1.0,-1.0,0.0,1.33024 +0.75,86,search,87677.9,0.99883,0.011029,1618.81,1.33007 +0.75,87,insert,1442.07,-1.0,-1.0,0.0,1.52355 +0.75,88,search,91504.2,0.99907,0.00970343,20731.1,1.52548 +0.75,89,insert,1152.82,-1.0,-1.0,0.0,1.68253 +0.75,90,search,102276,0.99919,0.0089639,26299.4,1.68473 +0.75,91,insert,142.406,-1.0,-1.0,0.0,1.69899 +0.75,92,search,110683,0.99916,0.00912731,9548.98,1.69933 +0.75,93,insert,1085.72,-1.0,-1.0,0.0,1.80314 +0.75,94,search,118291,0.99909,0.00949663,11761.1,1.8034 +0.75,95,insert,71.56,-1.0,-1.0,0.0,1.81062 +0.75,96,search,120615,0.99908,0.00954754,3874.38,1.81054 +0.75,97,insert,52.145,-1.0,-1.0,0.0,1.81498 +0.75,98,search,121596,0.99912,0.00933995,2183.57,1.81515 +0.75,99,insert,28.321,-1.0,-1.0,0.0,1.8174 +0.75,100,search,122336,0.99914,0.00923371,1759.05,1.81738 +0.75,101,insert,148.033,-1.0,-1.0,0.0,1.83002 +0.75,102,search,123854,0.99918,0.00901842,2099.05,1.83005 +0.5,2,search,3743.63,0.97361,0.0540257,2.884,0.0183457 +0.5,3,insert,11.153,-1.0,-1.0,0.0,0.0223845 +0.5,4,search,3598.73,0.97715,0.0498717,3.635,0.0223845 +0.5,5,insert,30.994,-1.0,-1.0,0.0,0.032811 +0.5,6,search,4540.01,0.9874,0.0375665,89.192,0.032607 +0.5,7,insert,38.563,-1.0,-1.0,0.0,0.0422019 +0.5,8,search,4846.43,0.98484,0.0423822,159.183,0.0425038 +0.5,9,insert,5.569,-1.0,-1.0,0.0,0.0440766 +0.5,10,search,4957.5,0.98835,0.0364879,156.109,0.0444186 +0.5,11,insert,13.488,-1.0,-1.0,0.0,0.0491412 +0.5,12,search,5004.8,0.98773,0.037718,195.998,0.0493855 +0.5,13,insert,34.581,-1.0,-1.0,0.0,0.0603616 +0.5,14,search,5334.28,0.98638,0.0403838,252.709,0.0606627 +0.5,15,insert,27.724,-1.0,-1.0,0.0,0.0691303 +0.5,16,search,5421.35,0.98674,0.0394231,227.815,0.0688255 +0.5,17,insert,5.141,-1.0,-1.0,0.0,0.071198 +0.5,18,search,5687.47,0.98717,0.03814,223.956,0.0711552 +0.5,19,insert,48.413,-1.0,-1.0,0.0,0.0782699 +0.5,20,search,5800.35,0.98726,0.0383109,226.684,0.0782426 +0.5,21,insert,437.962,-1.0,-1.0,0.0,0.197909 +0.5,22,search,6458.81,0.98758,0.0366322,1111.19,0.196871 +0.5,23,insert,497.166,-1.0,-1.0,0.0,0.322367 +0.5,24,search,8118.26,0.98306,0.0436939,2786.47,0.321907 +0.5,25,insert,69.664,-1.0,-1.0,0.0,0.341771 +0.5,26,search,10072.1,0.97182,0.0582404,2577.11,0.341055 +0.5,27,insert,48.109,-1.0,-1.0,0.0,0.353585 +0.5,28,search,11947,0.96974,0.0605032,1338.78,0.35286 +0.5,29,insert,89.058,-1.0,-1.0,0.0,0.379365 +0.5,30,search,13399.3,0.97119,0.0587473,794.499,0.380149 +0.5,31,insert,632.677,-1.0,-1.0,0.0,0.54195 +0.5,32,search,13452.8,0.97269,0.057667,4650.08,0.543491 +0.5,33,insert,89.775,-1.0,-1.0,0.0,0.565608 +0.5,34,search,16581.5,0.97178,0.0584663,2672.46,0.566289 +0.5,35,insert,71.556,-1.0,-1.0,0.0,0.580414 +0.5,36,search,18470.8,0.97253,0.0581289,1532.85,0.580893 +0.5,37,insert,92.37,-1.0,-1.0,0.0,0.600819 +0.5,38,search,18330.6,0.97338,0.0567979,958.911,0.600816 +0.5,39,insert,21.539,-1.0,-1.0,0.0,0.604612 +0.5,40,search,19082.3,0.9732,0.0570819,694.963,0.604504 +0.5,41,insert,102.789,-1.0,-1.0,0.0,0.619391 +0.5,42,search,18711.9,0.97372,0.0567056,787.874,0.619435 +0.5,43,insert,30.477,-1.0,-1.0,0.0,0.623922 +0.5,44,search,19655.6,0.97383,0.0565013,830.736,0.623915 +0.5,45,insert,378.58,-1.0,-1.0,0.0,0.639142 +0.5,46,search,19384.2,0.97451,0.0559091,1157.1,0.639118 +0.5,47,insert,563.585,-1.0,-1.0,0.0,0.741071 +0.5,48,search,20200.9,0.97679,0.0534823,4321.88,0.739977 +0.5,49,insert,74.871,-1.0,-1.0,0.0,0.755689 +0.5,50,search,21395.2,0.97775,0.0525398,2115.88,0.754856 +0.5,51,insert,701.766,-1.0,-1.0,0.0,0.891892 +0.5,52,search,22905,0.98016,0.0498644,7573.03,0.893248 +0.5,53,insert,114.214,-1.0,-1.0,0.0,0.911387 +0.5,54,search,25683.9,0.97861,0.0517873,3388.47,0.911412 +0.5,55,insert,669.195,-1.0,-1.0,0.0,1.05338 +0.5,56,search,27611.4,0.98177,0.0481941,6749.72,1.05378 +0.5,57,insert,79.394,-1.0,-1.0,0.0,1.06247 +0.5,58,search,29610.8,0.98182,0.047809,2920.01,1.06225 +0.5,59,insert,629.259,-1.0,-1.0,0.0,1.16263 +0.5,60,search,30548.6,0.98243,0.0468256,5497.48,1.16091 +0.5,61,insert,32.408,-1.0,-1.0,0.0,1.16516 +0.5,62,search,29070.2,0.98031,0.0504931,1591.47,1.16459 +0.5,63,insert,5.033,-1.0,-1.0,0.0,1.16564 +0.5,64,search,30263.8,0.9807,0.0499765,1051.02,1.16574 +0.5,65,insert,249.18,-1.0,-1.0,0.0,1.1948 +0.5,66,search,30841.4,0.98149,0.0486293,2459.94,1.19433 +0.5,67,insert,120.312,-1.0,-1.0,0.0,1.2146 +0.5,68,search,31718.4,0.98176,0.0481391,1335.3,1.21446 +0.5,69,insert,152.82,-1.0,-1.0,0.0,1.2364 +0.5,70,search,32073.5,0.98193,0.0476919,1254.46,1.2368 +0.5,71,insert,40.187,-1.0,-1.0,0.0,1.24216 +0.5,72,search,32523.1,0.98202,0.0476519,1021.83,1.2423 +0.5,73,insert,22.541,-1.0,-1.0,0.0,1.24529 +0.5,74,search,31813.3,0.982,0.0476479,898.995,1.24531 +0.5,75,insert,73.629,-1.0,-1.0,0.0,1.25279 +0.5,76,search,34187.6,0.98213,0.0473263,991.224,1.25237 +0.5,77,insert,96.793,-1.0,-1.0,0.0,1.26381 +0.5,78,search,32661.1,0.98197,0.0474972,962.885,1.2637 +0.5,79,insert,717.384,-1.0,-1.0,0.0,1.29164 +0.5,80,search,32964.9,0.98178,0.0478975,1322.2,1.29165 +0.5,81,insert,89.447,-1.0,-1.0,0.0,1.30421 +0.5,82,search,33698.6,0.9821,0.0474537,1243.35,1.30482 +0.5,83,insert,36.083,-1.0,-1.0,0.0,1.3108 +0.5,84,search,34538.7,0.98218,0.0473759,1028.86,1.31099 +0.5,85,insert,102.746,-1.0,-1.0,0.0,1.32549 +0.5,86,search,33630.9,0.98235,0.0471124,1132.65,1.3256 +0.5,87,insert,1336.38,-1.0,-1.0,0.0,1.51868 +0.5,88,search,34413.8,0.98478,0.0425028,10220.9,1.52046 +0.5,89,insert,992.01,-1.0,-1.0,0.0,1.67934 +0.5,90,search,38139.1,0.98634,0.0395435,11659.5,1.67947 +0.5,91,insert,118.143,-1.0,-1.0,0.0,1.69359 +0.5,92,search,43373.5,0.98622,0.0400773,4030.16,1.69367 +0.5,93,insert,882.897,-1.0,-1.0,0.0,1.79861 +0.5,94,search,43180.6,0.98654,0.0392047,5516.66,1.7988 +0.5,95,insert,60.793,-1.0,-1.0,0.0,1.80626 +0.5,96,search,43812.8,0.98691,0.0386767,2241.62,1.80678 +0.5,97,insert,37.091,-1.0,-1.0,0.0,1.81065 +0.5,98,search,42798.9,0.98704,0.0386018,1381.24,1.81092 +0.5,99,insert,20.421,-1.0,-1.0,0.0,1.81303 +0.5,100,search,45119.1,0.9871,0.0385689,1295.79,1.81312 +0.5,101,insert,150.529,-1.0,-1.0,0.0,1.82562 +0.5,102,search,44183.1,0.98717,0.0383491,1474.14,1.8257 +0.25,2,search,2282.69,0.88485,0.117342,1.716,0.0183457 +0.25,3,insert,9.707,-1.0,-1.0,0.0,0.0223845 +0.25,4,search,2203.75,0.89452,0.112956,1.774,0.0223845 +0.25,5,insert,31.054,-1.0,-1.0,0.0,0.032811 +0.25,6,search,2604.86,0.93574,0.0952189,72.078,0.032607 +0.25,7,insert,38.421,-1.0,-1.0,0.0,0.0422019 +0.25,8,search,2715.59,0.93128,0.0983071,146.99,0.042614 +0.25,9,insert,5.194,-1.0,-1.0,0.0,0.0444508 +0.25,10,search,2752.27,0.94257,0.0871074,119.664,0.0441481 +0.25,11,insert,12.873,-1.0,-1.0,0.0,0.0491334 +0.25,12,search,2846.73,0.93983,0.0899551,151.276,0.0490987 +0.25,13,insert,30.466,-1.0,-1.0,0.0,0.0602396 +0.25,14,search,2918.6,0.93398,0.0949639,161.71,0.0602281 +0.25,15,insert,27.715,-1.0,-1.0,0.0,0.0689651 +0.25,16,search,2973.34,0.93191,0.0951186,179.394,0.069085 +0.25,17,insert,5.675,-1.0,-1.0,0.0,0.0712829 +0.25,18,search,3117.7,0.93227,0.0947425,150.274,0.0714004 +0.25,19,insert,47.577,-1.0,-1.0,0.0,0.0780039 +0.25,20,search,3189.27,0.93655,0.0904867,181.48,0.0780292 +0.25,21,insert,441.609,-1.0,-1.0,0.0,0.197719 +0.25,22,search,3571.69,0.93834,0.0877201,912.217,0.197477 +0.25,23,insert,450.585,-1.0,-1.0,0.0,0.321868 +0.25,24,search,4341.87,0.91593,0.105138,1822.31,0.321488 +0.25,25,insert,62.233,-1.0,-1.0,0.0,0.341099 +0.25,26,search,4786.43,0.89842,0.116361,1729.48,0.341241 +0.25,27,insert,39.278,-1.0,-1.0,0.0,0.353264 +0.25,28,search,5503.58,0.89316,0.118508,729.246,0.353976 +0.25,29,insert,82.9,-1.0,-1.0,0.0,0.380429 +0.25,30,search,5527.95,0.89845,0.115403,566.173,0.37977 +0.25,31,insert,587.56,-1.0,-1.0,0.0,0.543944 +0.25,32,search,6017.92,0.90654,0.111415,3449.11,0.542931 +0.25,33,insert,91.392,-1.0,-1.0,0.0,0.565799 +0.25,34,search,6862.79,0.90644,0.111933,1878.59,0.565218 +0.25,35,insert,56.485,-1.0,-1.0,0.0,0.579554 +0.25,36,search,7543.78,0.90745,0.111673,904.371,0.579638 +0.25,37,insert,82.46,-1.0,-1.0,0.0,0.601868 +0.25,38,search,7443.85,0.90846,0.110802,774.153,0.601668 +0.25,39,insert,13.019,-1.0,-1.0,0.0,0.60504 +0.25,40,search,7758.55,0.90858,0.110928,583.728,0.604879 +0.25,41,insert,69.935,-1.0,-1.0,0.0,0.6212 +0.25,42,search,7828.81,0.91014,0.109952,865.999,0.621318 +0.25,43,insert,19.907,-1.0,-1.0,0.0,0.625059 +0.25,44,search,7679.94,0.91007,0.110048,691.175,0.624947 +0.25,45,insert,346.416,-1.0,-1.0,0.0,0.640347 +0.25,46,search,7876.18,0.91282,0.108133,984.944,0.639864 +0.25,47,insert,488.511,-1.0,-1.0,0.0,0.73934 +0.25,48,search,7968.13,0.91793,0.104952,2848.47,0.740093 +0.25,49,insert,56.876,-1.0,-1.0,0.0,0.755575 +0.25,50,search,8574.73,0.91923,0.104955,1552.22,0.754557 +0.25,51,insert,614.492,-1.0,-1.0,0.0,0.890585 +0.25,52,search,8898.39,0.92771,0.0990787,4777.14,0.891454 +0.25,53,insert,95.807,-1.0,-1.0,0.0,0.911569 +0.25,54,search,9866.91,0.92524,0.10105,2207.39,0.910524 +0.25,55,insert,496.489,-1.0,-1.0,0.0,1.05029 +0.25,56,search,10756.1,0.9338,0.0947638,5256.67,1.05166 +0.25,57,insert,64.877,-1.0,-1.0,0.0,1.06022 +0.25,58,search,11183.9,0.93294,0.0955876,2247.02,1.06059 +0.25,59,insert,433.539,-1.0,-1.0,0.0,1.15772 +0.25,60,search,11644.4,0.934,0.0944534,3835.39,1.15751 +0.25,61,insert,21.641,-1.0,-1.0,0.0,1.16171 +0.25,62,search,12050.7,0.93065,0.0991768,2092,1.16264 +0.25,63,insert,7.967,-1.0,-1.0,0.0,1.16365 +0.25,64,search,11637.3,0.93061,0.099272,1336.6,1.16468 +0.25,65,insert,190.171,-1.0,-1.0,0.0,1.1951 +0.25,66,search,11656.2,0.93284,0.0971381,2451.94,1.19502 +0.25,67,insert,89.76,-1.0,-1.0,0.0,1.21518 +0.25,68,search,12556.2,0.93315,0.0969631,1630.31,1.21553 +0.25,69,insert,143.727,-1.0,-1.0,0.0,1.23926 +0.25,70,search,12137,0.93399,0.0965082,1742.14,1.23899 +0.25,71,insert,27.424,-1.0,-1.0,0.0,1.24378 +0.25,72,search,12357.8,0.93443,0.0961615,1421.86,1.24376 +0.25,73,insert,21.603,-1.0,-1.0,0.0,1.24711 +0.25,74,search,12355.8,0.93426,0.0962957,1400,1.24741 +0.25,75,insert,61.127,-1.0,-1.0,0.0,1.25443 +0.25,76,search,12115.5,0.93436,0.096282,1475.32,1.25452 +0.25,77,insert,70.904,-1.0,-1.0,0.0,1.26581 +0.25,78,search,12431.3,0.93413,0.0961939,1383.47,1.26591 +0.25,79,insert,808.369,-1.0,-1.0,0.0,1.295 +0.25,80,search,12497.5,0.93401,0.096665,1820.87,1.29529 +0.25,81,insert,80.251,-1.0,-1.0,0.0,1.30662 +0.25,82,search,12813,0.9348,0.0958508,1507.13,1.30637 +0.25,83,insert,26.16,-1.0,-1.0,0.0,1.31236 +0.25,84,search,12749,0.93515,0.0951409,1557.52,1.31294 +0.25,85,insert,104.126,-1.0,-1.0,0.0,1.3273 +0.25,86,search,12794.6,0.93577,0.0946486,1581.83,1.32728 +0.25,87,insert,943.232,-1.0,-1.0,0.0,1.51948 +0.25,88,search,13387.7,0.94254,0.0876102,10737.1,1.51868 +0.25,89,insert,940.714,-1.0,-1.0,0.0,1.6786 +0.25,90,search,14735.9,0.94648,0.0836913,12654,1.67838 +0.25,91,insert,107.711,-1.0,-1.0,0.0,1.69204 +0.25,92,search,16373,0.94667,0.0837738,3753.93,1.69365 +0.25,93,insert,727.292,-1.0,-1.0,0.0,1.79968 +0.25,94,search,16155.6,0.94789,0.0824523,5176.82,1.79895 +0.25,95,insert,49.626,-1.0,-1.0,0.0,1.80558 +0.25,96,search,17036.4,0.94816,0.0818819,2363.86,1.80609 +0.25,97,insert,27.707,-1.0,-1.0,0.0,1.80978 +0.25,98,search,17333.6,0.94819,0.0819383,2091.24,1.80984 +0.25,99,insert,18.379,-1.0,-1.0,0.0,1.81137 +0.25,100,search,17081.3,0.94821,0.0818611,38.394,1.81137 +0.25,101,insert,138.01,-1.0,-1.0,0.0,1.82553 +0.25,102,search,17142.3,0.94846,0.0816462,2220.78,1.82553 +0.05,2,search,873.849,0.57321,0.215169,0.753,0.0183461 +0.05,3,insert,13.361,-1.0,-1.0,0.0,0.0223849 +0.05,4,search,856.665,0.58482,0.214377,0.858,0.0223849 +0.05,5,insert,35.555,-1.0,-1.0,0.0,0.0328114 +0.05,6,search,881.401,0.65013,0.234846,65.997,0.0326074 +0.05,7,insert,34.026,-1.0,-1.0,0.0,0.0422023 +0.05,8,search,907.831,0.71023,0.206475,92.964,0.0426144 +0.05,9,insert,4.286,-1.0,-1.0,0.0,0.0444512 +0.05,10,search,918.404,0.71488,0.197403,88.731,0.0441252 +0.05,11,insert,11.808,-1.0,-1.0,0.0,0.0491742 +0.05,12,search,941.415,0.69284,0.200565,96.829,0.0489449 +0.05,13,insert,29.4,-1.0,-1.0,0.0,0.0601796 +0.05,14,search,955.218,0.67446,0.204164,115.475,0.060322 +0.05,15,insert,27.723,-1.0,-1.0,0.0,0.0691642 +0.05,16,search,968.137,0.65255,0.205064,110.948,0.0689296 +0.05,17,insert,5.081,-1.0,-1.0,0.0,0.0712339 +0.05,18,search,971.999,0.64673,0.209309,95.615,0.0708982 +0.05,19,insert,43.227,-1.0,-1.0,0.0,0.0777236 +0.05,20,search,980.94,0.66183,0.207236,107.451,0.0778476 +0.05,21,insert,436.254,-1.0,-1.0,0.0,0.19668 +0.05,22,search,1111.29,0.66877,0.204296,647.443,0.197373 +0.05,23,insert,465.031,-1.0,-1.0,0.0,0.322176 +0.05,24,search,1292.01,0.66837,0.211075,1741.07,0.321703 +0.05,25,insert,60.136,-1.0,-1.0,0.0,0.340587 +0.05,26,search,1254.09,0.65783,0.212576,1092.91,0.341108 +0.05,27,insert,37.104,-1.0,-1.0,0.0,0.352858 +0.05,28,search,1292.64,0.64663,0.217334,418.027,0.353109 +0.05,29,insert,74.381,-1.0,-1.0,0.0,0.380256 +0.05,30,search,1330.56,0.65813,0.218309,463.928,0.379752 +0.05,31,insert,509.231,-1.0,-1.0,0.0,0.543361 +0.05,32,search,1471.14,0.67277,0.212932,2205.56,0.541713 +0.05,33,insert,80.149,-1.0,-1.0,0.0,0.565231 +0.05,34,search,1506.85,0.67319,0.213557,1278.65,0.564945 +0.05,35,insert,56.656,-1.0,-1.0,0.0,0.579606 +0.05,36,search,1553.2,0.67518,0.212154,677.093,0.58035 +0.05,37,insert,71.806,-1.0,-1.0,0.0,0.600103 +0.05,38,search,1503.15,0.67436,0.212779,569.918,0.60058 +0.05,39,insert,17.578,-1.0,-1.0,0.0,0.604429 +0.05,40,search,1557.93,0.67903,0.211491,580.324,0.604298 +0.05,41,insert,62.367,-1.0,-1.0,0.0,0.618968 +0.05,42,search,1562.6,0.68094,0.211189,591.22,0.619109 +0.05,43,insert,14.838,-1.0,-1.0,0.0,0.623476 +0.05,44,search,1556.9,0.68053,0.21106,554.277,0.623353 +0.05,45,insert,329.092,-1.0,-1.0,0.0,0.638415 +0.05,46,search,1579.89,0.6852,0.208619,771.378,0.638332 +0.05,47,insert,390.783,-1.0,-1.0,0.0,0.738241 +0.05,48,search,1647.03,0.69248,0.210438,2014.49,0.73931 +0.05,49,insert,51.919,-1.0,-1.0,0.0,0.755075 +0.05,50,search,1675.36,0.69756,0.210277,1202.83,0.754351 +0.05,51,insert,439.798,-1.0,-1.0,0.0,0.89089 +0.05,52,search,1802.96,0.71888,0.202166,2914.9,0.891649 +0.05,53,insert,77.632,-1.0,-1.0,0.0,0.910222 +0.05,54,search,1833.91,0.71722,0.203346,1733.88,0.909768 +0.05,55,insert,514.027,-1.0,-1.0,0.0,1.05108 +0.05,56,search,2007.24,0.72905,0.198304,3672.65,1.05279 +0.05,57,insert,46.932,-1.0,-1.0,0.0,1.06139 +0.05,58,search,2029.71,0.727,0.201542,1590.45,1.06143 +0.05,59,insert,396.714,-1.0,-1.0,0.0,1.16002 +0.05,60,search,2092.94,0.72834,0.200396,2874.41,1.15954 +0.05,61,insert,16.747,-1.0,-1.0,0.0,1.16378 +0.05,62,search,2117.1,0.72832,0.202387,1294.25,1.1643 +0.05,63,insert,5.294,-1.0,-1.0,0.0,1.16583 +0.05,64,search,2083.26,0.72744,0.202948,1085.3,1.16577 +0.05,65,insert,121.655,-1.0,-1.0,0.0,1.19376 +0.05,66,search,2098.21,0.73114,0.200981,1733.55,1.19402 +0.05,67,insert,77.98,-1.0,-1.0,0.0,1.21405 +0.05,68,search,2133.03,0.7319,0.201766,1337.2,1.21443 +0.05,69,insert,104.974,-1.0,-1.0,0.0,1.23907 +0.05,70,search,2162.73,0.7349,0.19997,1478.22,1.23874 +0.05,71,insert,30.169,-1.0,-1.0,0.0,1.24509 +0.05,72,search,2176.96,0.73663,0.199247,1336.89,1.24488 +0.05,73,insert,11.745,-1.0,-1.0,0.0,1.24772 +0.05,74,search,2173.75,0.73605,0.199683,1256.81,1.24713 +0.05,75,insert,42.752,-1.0,-1.0,0.0,1.25569 +0.05,76,search,2166.39,0.73624,0.199625,1154.5,1.25562 +0.05,77,insert,65.676,-1.0,-1.0,0.0,1.26691 +0.05,78,search,2193.8,0.73787,0.199184,1334.75,1.26651 +0.05,79,insert,731.339,-1.0,-1.0,0.0,1.29381 +0.05,80,search,2226.37,0.73819,0.199011,1374.44,1.29427 +0.05,81,insert,68.476,-1.0,-1.0,0.0,1.30619 +0.05,82,search,2195.05,0.73885,0.198969,1359.59,1.30595 +0.05,83,insert,24.227,-1.0,-1.0,0.0,1.31218 +0.05,84,search,2232.82,0.74189,0.198012,1483.14,1.31255 +0.05,85,insert,81.791,-1.0,-1.0,0.0,1.32874 +0.05,86,search,2231.11,0.74257,0.198453,1423.25,1.32888 +0.05,87,insert,864.217,-1.0,-1.0,0.0,1.51901 +0.05,88,search,2377.17,0.75453,0.192191,6519.5,1.51873 +0.05,89,insert,742.049,-1.0,-1.0,0.0,1.67991 +0.05,90,search,2562.91,0.76709,0.186772,7774.15,1.68172 +0.05,91,insert,55.429,-1.0,-1.0,0.0,1.69436 +0.05,92,search,2637.16,0.76887,0.187009,2934.89,1.69398 +0.05,93,insert,616.954,-1.0,-1.0,0.0,1.80045 +0.05,94,search,2733.78,0.77007,0.187019,3484.94,1.79943 +0.05,95,insert,32.713,-1.0,-1.0,0.0,1.80629 +0.05,96,search,2617.49,0.77078,0.186384,2182.06,1.80663 +0.05,97,insert,18.348,-1.0,-1.0,0.0,1.81046 +0.05,98,search,2708.34,0.7717,0.185967,1766.49,1.81038 +0.05,99,insert,9.343,-1.0,-1.0,0.0,1.81222 +0.05,100,search,2689.76,0.77161,0.186039,1855.31,1.81215 +0.05,101,insert,71.056,-1.0,-1.0,0.0,1.82496 +0.05,102,search,2711.99,0.77238,0.185916,2003.62,1.82586 diff --git a/scripts/big_ann_perf_numbers/temp_perf_debug_scan_0.14_worker_batch_tuning.csv b/scripts/big_ann_perf_numbers/temp_perf_debug_scan_0.14_worker_batch_tuning.csv new file mode 100644 index 00000000..2e08ecf8 --- /dev/null +++ b/scripts/big_ann_perf_numbers/temp_perf_debug_scan_0.14_worker_batch_tuning.csv @@ -0,0 +1,46 @@ +step_num,step_type,latency_ms,worker_partition_size,worker_scan_time_ms,worker_scan_throughput,worker_result_time_ms,measured_ipc,cache_miss_rate,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +2,search,3070.27,37.3917,396.028,0.372447,499.333,0.83053,1.59165,0.83796,0.13696,-1.0,-1.0,7.297,0.0184881,1000,38806 +3,insert,24.883,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,11.592,0.0226489,997,49334 +4,search,2432.37,65.61,267.904,0.596273,173.074,1.39491,23.5485,0.85002,0.13685,-1.0,-1.0,17.203,0.0226571,995,49334 +5,insert,20.717,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,148.071,0.0331908,984,73557 +6,search,2305.81,193.134,226.938,0.869705,101.021,0.873411,18.4945,0.91587,0.110639,-1.0,-1.0,137.382,0.0331908,984,73557 +7,insert,24.865,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,136.613,0.0426695,984,95766 +8,search,2351.84,245.376,331.776,0.719487,106.128,1.37675,17.5143,0.91691,0.110489,-1.0,-1.0,87.988,0.0430701,988,95766 +9,insert,3.129,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,73.748,0.0447788,988,100025 +10,search,2372.69,250.163,320.96,0.775866,106.396,1.37115,19.4719,0.91771,0.107466,-1.0,-1.0,74.929,0.0447788,988,100025 +11,insert,8.53,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,77.981,0.0494549,989,111417 +12,search,2446.48,294.312,405.716,0.627239,116.446,1.48712,17.7425,0.91734,0.108494,-1.0,-1.0,23.414,0.0498645,990,111417 +13,insert,29.631,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,6.249,0.0612351,990,137139 +14,search,2421.19,333.836,331.021,0.756576,119.366,1.40499,12.7426,0.91308,0.111165,-1.0,-1.0,15.033,0.061251,992,137139 +15,insert,15.531,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,6.149,0.0699088,992,156710 +16,search,2450.41,367.914,461.266,0.650374,100.993,1.65992,16.2248,0.91007,0.112083,-1.0,-1.0,6.311,0.0699088,992,156710 +17,insert,4.465,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,9.042,0.0721524,993,161773 +18,search,2491.08,385.117,469.72,0.625897,114.158,1.62688,15.5473,0.91228,0.111388,-1.0,-1.0,6.296,0.0721524,993,161773 +19,insert,30.904,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,8.647,0.0788329,994,177161 +20,search,2463.67,427.16,434.459,0.68179,108.157,1.762,15.8342,0.91619,0.108129,-1.0,-1.0,6.174,0.0788329,994,177161 +21,insert,325.368,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,106.624,0.199226,1015,448898 +22,search,2572.78,924.323,535.212,0.889352,78.4564,1.9074,6.57268,0.90782,0.109883,-1.0,-1.0,15.309,0.199226,1017,448898 +23,insert,398.183,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,252.467,0.328008,1056,733493 +24,search,2882.84,1302.93,798.997,0.793248,90.673,2.12338,10.1353,0.90258,0.111878,-1.0,-1.0,64.024,0.328007,1065,733493 +25,insert,41.729,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.928,0.344779,1067,777443 +26,search,2844.52,1308.8,740.571,0.867858,85.9908,2.02675,8.83081,0.90327,0.111395,-1.0,-1.0,14.563,0.344787,1068,777443 +27,insert,30.127,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,8.481,0.355871,1068,805394 +28,search,2852.76,1337.72,772.889,0.860388,72.3551,1.99488,7.76554,0.9034,0.111453,-1.0,-1.0,8.841,0.355871,1068,805394 +29,insert,60.028,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,40.577,0.384014,1073,866391 +30,search,2866.05,1410.39,780.85,0.898717,76.9226,1.95992,10.2073,0.90458,0.112188,-1.0,-1.0,23.985,0.384013,1075,866391 +31,insert,436.755,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,364.699,0.553439,1125,1239816 +32,search,3141.84,1721.98,947.831,0.901958,91.0181,2.00413,9.49485,0.89642,0.118214,-1.0,-1.0,74.006,0.553553,1134,1239816 +33,insert,44.754,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,24.727,0.573565,1137,1291211 +34,search,3187.3,1721.41,962.491,0.931293,84.9232,3.14305,12.2368,0.89645,0.118294,-1.0,-1.0,52.214,0.573577,1141,1291211 +35,insert,28.286,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,36.02,0.585395,1147,1324978 +36,search,3206.84,1749.44,979.044,1.00084,83.5524,1.99927,7.53983,0.89755,0.11705,-1.0,-1.0,21.924,0.585403,1149,1324978 +37,insert,42.638,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,28.522,0.605791,1153,1371885 +38,search,3226.82,1777.43,979.4,0.938982,85.4242,2.0111,7.19635,0.89721,0.116469,-1.0,-1.0,18.322,0.605791,1154,1371885 +39,insert,13.507,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,15.482,0.60912,1155,1379335 +40,search,3263.26,1779.22,1006.7,0.891796,89.7042,2.02152,7.86378,0.89768,0.116823,-1.0,-1.0,9.444,0.60912,1155,1379335 +41,insert,61.145,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,18.594,0.624903,1157,1413312 +42,search,3345.96,1809.18,1059.58,0.941386,103.23,2.0098,6.21945,0.89914,0.116026,-1.0,-1.0,15.705,0.625015,1158,1413312 +43,insert,16.008,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,15.139,0.628672,1159,1423411 +44,search,3308.58,1815.56,1041.3,0.928153,96.6002,2.0169,7.3644,0.89885,0.116296,-1.0,-1.0,8.867,0.628672,1159,1423411 +45,insert,218.704,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,51.078,0.644769,1168,1457559 +46,search,3313.21,1816.28,1034.95,0.948786,93.9339,2.04583,10.1682,0.89879,0.116116,-1.0,-1.0,8.532,0.644769,1168,1457559 diff --git a/scripts/big_ann_perf_numbers/temp_perf_debug_scan_0.14_worker_batch_tuning_with_counters.csv b/scripts/big_ann_perf_numbers/temp_perf_debug_scan_0.14_worker_batch_tuning_with_counters.csv new file mode 100644 index 00000000..c36f9e3e --- /dev/null +++ b/scripts/big_ann_perf_numbers/temp_perf_debug_scan_0.14_worker_batch_tuning_with_counters.csv @@ -0,0 +1,76 @@ +step_num,step_type,latency_ms,worker_partition_size,worker_scan_time_ms,worker_scan_throughput,worker_result_time_ms,measured_ipc,cache_miss_rate,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +2,search,3035.6,37.3917,420.231,0.382277,504.338,0.867317,3.24812,0.83796,0.13696,-1.0,-1.0,6.95,0.0184881,1000,38806 +3,insert,25.975,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.301,0.022655,996,49334 +4,search,2370.06,65.5482,237.393,0.592827,151.278,1.13594,20.716,0.85049,0.13652,-1.0,-1.0,11.121,0.0226615,993,49334 +5,insert,25.255,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,154.544,0.0329603,983,73557 +6,search,2352.32,193.02,306.821,0.718086,108.047,1.30878,18.2649,0.91581,0.110963,-1.0,-1.0,129.304,0.0329986,984,73557 +7,insert,23.544,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,126.262,0.0424157,984,95766 +8,search,2362.35,243.663,341.842,0.677268,102.619,1.57255,23.9914,0.91496,0.111011,-1.0,-1.0,80.92,0.042911,988,95766 +9,insert,3.253,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,67.407,0.0446756,988,100025 +10,search,2424.36,248.155,387.108,0.597508,114.716,1.40239,25.3986,0.91674,0.108386,-1.0,-1.0,24.446,0.045102,991,100025 +11,insert,15.075,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,7.724,0.0497923,992,111417 +12,search,2456.76,286.378,340.763,0.620804,127.185,1.43018,18.6114,0.91484,0.110118,-1.0,-1.0,14.452,0.0499502,994,111417 +13,insert,18.65,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,6.06,0.0608532,994,137139 +14,search,2392.17,324.008,279.62,0.789245,99.7453,1.37047,15.1104,0.91101,0.112744,-1.0,-1.0,14.047,0.0608716,997,137139 +15,insert,15.206,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,6.198,0.069633,997,156710 +16,search,2385.43,356.422,287.099,0.770457,98.8011,1.46295,15.4498,0.90762,0.113728,-1.0,-1.0,6.247,0.069633,997,156710 +17,insert,4.057,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,6.283,0.0717643,997,161773 +18,search,2425.92,376.748,368.997,0.750144,98.8857,1.71388,18.4104,0.90924,0.113481,-1.0,-1.0,6.297,0.0717643,997,161773 +19,insert,31.156,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,8.606,0.0786085,998,177161 +20,search,2431.31,417.19,368.641,0.754435,97.1014,1.72491,21.242,0.91318,0.109991,-1.0,-1.0,6.338,0.0786085,998,177161 +21,insert,318.612,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,150.53,0.200787,1038,448898 +22,search,2621.51,843.081,509.473,0.839114,75.1851,1.89609,13.5775,0.90153,0.113162,-1.0,-1.0,46.414,0.200816,1049,448898 +23,insert,389.011,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,236.892,0.328393,1094,733493 +24,search,2917,1173.53,766.962,0.842252,78.3771,2.06638,10.4986,0.89616,0.115777,-1.0,-1.0,81.367,0.328673,1110,733493 +25,insert,38.602,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,26.869,0.344932,1114,777443 +26,search,2942.85,1161.84,778.321,0.855797,79.4583,2.18933,8.76152,0.89656,0.115824,-1.0,-1.0,19.327,0.344942,1116,777443 +27,insert,30.004,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.566,0.355953,1117,805394 +28,search,2879.78,1181.81,703.211,0.914815,67.1411,2.10186,9.3667,0.89704,0.115307,-1.0,-1.0,15.215,0.355974,1119,805394 +29,insert,54.017,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,49.861,0.383044,1128,866391 +30,search,2968.2,1235.9,785.407,0.854108,67.4165,2.12757,10.3829,0.89924,0.115321,-1.0,-1.0,23.059,0.383044,1130,866391 +31,insert,453.273,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,334.618,0.552862,1190,1239816 +32,search,3260.36,1498.72,958.818,0.870608,72.1074,2.05855,8.94397,0.88958,0.121369,-1.0,-1.0,68.148,0.552916,1196,1239816 +33,insert,44.691,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,34.798,0.572702,1203,1291211 +34,search,3252.97,1509.86,909.114,0.899267,71.5206,2.1166,6.89881,0.8888,0.121983,-1.0,-1.0,33.866,0.57271,1205,1291211 +35,insert,28.989,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,32.056,0.584599,1212,1324978 +36,search,3299.42,1533.91,928.471,0.938225,69.982,2.09337,8.251,0.89032,0.120622,-1.0,-1.0,16.006,0.584599,1213,1324978 +37,insert,44.573,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,40.031,0.605742,1219,1371885 +38,search,3590.33,1552.76,964.783,0.889823,84.6972,2.17256,11.2212,0.89006,0.121573,-1.0,-1.0,10.689,0.605742,1219,1371885 +39,insert,13.637,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,9.011,0.608441,1219,1379335 +40,search,3432.21,1560.85,943.132,0.864369,73.1322,2.26521,8.30382,0.89087,0.121418,-1.0,-1.0,9.351,0.608441,1219,1379335 +41,insert,54.656,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,31.722,0.622128,1224,1413312 +42,search,3410.96,1582.26,1028.72,0.83453,80.1023,2.18424,8.96297,0.892,0.120769,-1.0,-1.0,8.91,0.622128,1224,1413312 +43,insert,16.585,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,8.166,0.625911,1224,1423411 +44,search,3369.78,1596.76,990.591,0.882051,81.4331,2.19832,7.79683,0.89242,0.120319,-1.0,-1.0,8.899,0.625911,1224,1423411 +45,insert,197.6,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,26.795,0.642851,1231,1457559 +46,search,3377.11,1610.03,992.018,0.854689,71.6573,2.07907,8.84385,0.89297,0.118827,-1.0,-1.0,8.621,0.642851,1231,1457559 +47,insert,282.212,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,240.219,0.748077,1264,1688593 +48,search,3514.83,1755.28,1079.77,0.908995,76.4786,2.10633,7.74335,0.89387,0.119424,-1.0,-1.0,62.384,0.748077,1270,1688593 +49,insert,36.032,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,21.023,0.762801,1272,1723505 +50,search,3612.36,1760.31,1143.97,0.900675,98.3982,2.36903,7.57637,0.89462,0.119044,-1.0,-1.0,36.53,0.762807,1276,1723505 +51,insert,312.706,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,208.19,0.900711,1311,2035040 +52,search,3752.47,1954.7,1206.05,0.926171,86.0285,2.08198,7.43964,0.8975,0.118184,-1.0,-1.0,33.065,0.900711,1314,2035040 +53,insert,45.689,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,45.371,0.917223,1318,2078341 +54,search,3781.85,1979.61,1223.22,0.970751,88.3165,2.07803,6.85166,0.89761,0.118593,-1.0,-1.0,10.41,0.917223,1318,2078341 +55,insert,416.74,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,401.633,1.0665,1367,2399905 +56,search,4053.36,2166.51,1387.2,0.922167,112.087,2.16069,7.72146,0.90056,0.118392,-1.0,-1.0,99.117,1.06653,1380,2399905 +57,insert,30.987,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,33.25,1.07438,1384,2419836 +58,search,4054.25,2119.71,1351.65,0.930816,111.615,2.20247,8.51779,0.89909,0.119262,-1.0,-1.0,65.788,1.07442,1391,2419836 +59,insert,222.737,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,108.618,1.17291,1401,2643083 +60,search,4164.69,2178.58,1411.28,0.912069,112.475,2.11429,6.87599,0.8931,0.125411,-1.0,-1.0,61.905,1.17353,1408,2643083 +61,insert,11.629,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,18.731,1.17703,1410,2653064 +62,search,4244.38,2167.7,1475.38,0.921919,125.286,2.15535,7.6848,0.89305,0.125482,-1.0,-1.0,15.291,1.17704,1411,2653064 +63,insert,2.819,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,9.405,1.17793,1411,2656118 +64,search,4129.84,2167.31,1389.53,0.942525,109.384,2.14315,9.03602,0.89284,0.125525,-1.0,-1.0,10.916,1.17793,1411,2656118 +65,insert,77.318,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,103.552,1.20793,1432,2723424 +66,search,4221.1,2188.06,1421.74,0.949361,116.094,2.1466,9.45562,0.89358,0.125179,-1.0,-1.0,10.057,1.20793,1432,2723424 +67,insert,44.238,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,79.685,1.22887,1447,2769021 +68,search,4280,2202.74,1435.45,0.946927,124.751,2.18624,8.28047,0.8951,0.124238,-1.0,-1.0,19.65,1.22888,1449,2769021 +69,insert,49.515,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,55.921,1.25096,1457,2821777 +70,search,4314.18,2222.62,1454.55,0.897541,121.701,2.18296,7.10808,0.89674,0.122815,-1.0,-1.0,10.321,1.25096,1457,2821777 +71,insert,15.358,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,25.921,1.25685,1461,2834921 +72,search,4336.86,2226.55,1468.08,0.889896,122.891,2.17387,7.53162,0.89742,0.122313,-1.0,-1.0,13.824,1.25685,1461,2834921 +73,insert,7.146,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,10.889,1.25892,1461,2842044 +74,search,4336.7,2231.56,1474.8,0.950467,120.822,2.2214,7.55198,0.89751,0.12232,-1.0,-1.0,13.304,1.25892,1461,2842044 +75,insert,24.165,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.469,1.2636,1462,2858890 +76,search,4361.67,2241.33,1490.39,0.968308,134.077,2.31167,7.23226,0.89745,0.122324,-1.0,-1.0,19.894,1.2637,1463,2858890 diff --git a/scripts/big_ann_perf_numbers/test_metric_collection.csv b/scripts/big_ann_perf_numbers/test_metric_collection.csv new file mode 100644 index 00000000..2dd482ac --- /dev/null +++ b/scripts/big_ann_perf_numbers/test_metric_collection.csv @@ -0,0 +1,11 @@ +batch_size,step_num,step_type,search_latency_ms,worker_partition_size,worker_scan_time_ms,worker_scan_throughput,worker_result_time_ms,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +512,2,search,3482.2,37.5312,781.697,0.457078,388.613,0.8551,0.130106,-1.0,-1.0,10.871,0.0184881,1000,38806 +512,3,insert,23.284,-1.0,-1.0,-1.0,-1.0,19.612,0.022655,996,49334 +512,4,search,2553.16,63.3236,180.072,0.81906,144.894,0.86686,0.128427,-1.0,-1.0,19.651,0.0226469,994,49334 +512,5,insert,21.527,-1.0,-1.0,-1.0,-1.0,165.849,0.0330329,986,73557 +512,6,search,2558.93,174.009,285.811,0.804123,127.678,0.92469,0.104049,-1.0,-1.0,117.095,0.0331769,988,73557 +512,7,insert,24.61,-1.0,-1.0,-1.0,-1.0,116.018,0.0427286,989,95766 +512,8,search,2557.92,218.416,259.189,0.839563,125.21,0.92476,0.103613,-1.0,-1.0,20.489,0.0432125,992,95766 +512,9,insert,3.176,-1.0,-1.0,-1.0,-1.0,6.262,0.0448665,992,100025 +512,10,search,2584.78,223.689,220.772,0.805342,148.186,0.92573,0.101717,-1.0,-1.0,17.197,0.0449,995,100025 +512,11,insert,19.224,-1.0,-1.0,-1.0,-1.0,15.271,0.0497813,997,111417 diff --git a/scripts/big_ann_perf_numbers/test_perf_debug_scan_0.14_tuning.csv b/scripts/big_ann_perf_numbers/test_perf_debug_scan_0.14_tuning.csv new file mode 100644 index 00000000..ac48fae4 --- /dev/null +++ b/scripts/big_ann_perf_numbers/test_perf_debug_scan_0.14_tuning.csv @@ -0,0 +1,26 @@ +step_num,step_type,latency_ms,worker_partition_size,worker_scan_time_ms,worker_scan_throughput,worker_result_time_ms,measured_ipc,cache_miss_rate,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +2,search,3168.19,37.4251,328.899,0.550743,612.621,-nan,-nan,0.844,0.1346,-1.0,-1.0,6.735,0.0184881,1000,38806 +3,insert,27.469,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.719,0.022655,996,49334 +4,search,2508.68,65.1954,177.318,0.963355,191.554,-nan,-nan,0.8558,0.133903,-1.0,-1.0,17.764,0.0226615,993,49334 +5,insert,20.935,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,162.229,0.033017,984,73557 +6,search,2364.79,190.054,178.434,1.62821,98.8412,-nan,-nan,0.91846,0.108847,-1.0,-1.0,144.734,0.0330521,985,73557 +7,insert,23.907,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,144.808,0.0425589,986,95766 +8,search,2348.93,238.607,189.89,1.55421,95.834,-nan,-nan,0.91852,0.108405,-1.0,-1.0,87.19,0.0428008,990,95766 +9,insert,3.485,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,74.225,0.0446156,990,100025 +10,search,2394.72,245.023,194.572,1.41505,103.476,-nan,-nan,0.91978,0.10575,-1.0,-1.0,22.238,0.0450652,995,100025 +11,insert,8.361,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,9.159,0.0498095,997,111417 +12,search,2386.85,278.189,199.22,1.24952,111.249,-nan,-nan,0.91729,0.108302,-1.0,-1.0,22.702,0.0499412,999,111417 +13,insert,28.184,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,9.479,0.0612192,1001,137139 +14,search,2412.08,314.268,223.304,1.18219,106.811,-nan,-nan,0.9133,0.110833,-1.0,-1.0,16.574,0.0612314,1005,137139 +15,insert,15.287,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,8.984,0.069788,1006,156710 +16,search,2409.13,343.318,237.888,1.20787,101.79,-nan,-nan,0.90963,0.111169,-1.0,-1.0,8.479,0.0697908,1007,156710 +17,insert,3.765,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,8.428,0.0717758,1008,161773 +18,search,2420.02,356.533,237.722,1.17654,100.786,-nan,-nan,0.91096,0.110666,-1.0,-1.0,8.884,0.0718529,1009,161773 +19,insert,31.652,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,9.454,0.078631,1010,177161 +20,search,2434.27,395.28,257.442,1.20095,98.4046,-nan,-nan,0.91521,0.107631,-1.0,-1.0,6.351,0.078631,1010,177161 +21,insert,317.946,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,210.497,0.201512,1074,448898 +22,search,2673.03,753.477,413.894,1.25247,65.402,-nan,-nan,0.89884,0.114083,-1.0,-1.0,51.738,0.20151,1085,448898 +23,insert,428.467,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,269.614,0.327669,1144,733493 +24,search,3002.29,1034.83,619.84,1.08352,82.3551,-nan,-nan,0.8948,0.11623,-1.0,-1.0,80.543,0.328234,1166,733493 +25,insert,35.426,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.191,0.345577,1170,777443 +26,search,3078.55,1010.14,610.538,1.01519,83.5195,-nan,-nan,0.89313,0.117757,-1.0,-1.0,17.019,0.345672,1172,777443 diff --git a/scripts/big_ann_perf_numbers/test_perf_debug_scan_0.14_worker_batch_tuning.csv b/scripts/big_ann_perf_numbers/test_perf_debug_scan_0.14_worker_batch_tuning.csv new file mode 100644 index 00000000..1381c902 --- /dev/null +++ b/scripts/big_ann_perf_numbers/test_perf_debug_scan_0.14_worker_batch_tuning.csv @@ -0,0 +1,1280 @@ +step_num,step_type,latency_ms,worker_partition_size,worker_scan_time_ms,worker_scan_throughput,worker_result_time_ms,measured_ipc,cache_miss_rate,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +2,search,3247.47,37.4251,331.689,0.510184,648.614,-nan,-nan,0.844,0.1346,-1.0,-1.0,6.695,0.0184881,1000,38806 +3,insert,25.617,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.338,0.022655,996,49334 +4,search,2540.43,65.1954,195.461,0.99775,207.3,-nan,-nan,0.8558,0.133903,-1.0,-1.0,16.939,0.0226615,993,49334 +5,insert,19.949,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,164.352,0.032935,982,73557 +6,search,2350.58,189.735,175.935,1.65929,109.007,-nan,-nan,0.91916,0.108187,-1.0,-1.0,142.438,0.0329729,983,73557 +7,insert,24.085,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,145.763,0.0426744,984,95766 +8,search,2408.17,239.602,188.188,1.4864,107.986,-nan,-nan,0.91905,0.108333,-1.0,-1.0,83.786,0.0429485,987,95766 +9,insert,3.399,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,74.298,0.0447319,987,100025 +10,search,2401.18,247.607,192.967,1.41723,113.025,-nan,-nan,0.92091,0.10518,-1.0,-1.0,18.688,0.0451509,990,100025 +11,insert,8.32,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,9.81,0.049849,992,111417 +12,search,2404.25,283.16,203.377,1.28774,125.709,-nan,-nan,0.91837,0.107629,-1.0,-1.0,22.419,0.0499784,994,111417 +13,insert,28.707,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,6.171,0.0610747,994,137139 +14,search,2452.88,321.358,221.168,1.25571,121.735,-nan,-nan,0.91528,0.109521,-1.0,-1.0,12.182,0.0610862,996,137139 +15,insert,15.441,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,6.326,0.0696525,996,156710 +16,search,2446.12,356.024,248.257,1.20872,100.562,-nan,-nan,0.91308,0.109879,-1.0,-1.0,6.719,0.0696525,996,156710 +17,insert,3.853,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,8.758,0.0716342,997,161773 +18,search,2438.8,373.487,246.175,1.19235,108.491,-nan,-nan,0.91385,0.109958,-1.0,-1.0,6.346,0.0716342,997,161773 +19,insert,31.511,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,10.406,0.0785551,999,177161 +20,search,2417.02,411.658,261.014,1.26594,103.356,-nan,-nan,0.91716,0.107192,-1.0,-1.0,6.281,0.0785551,999,177161 +21,insert,322.721,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,154.488,0.200933,1036,448898 +22,search,2708.49,842.95,474.008,1.10849,90.2816,-nan,-nan,0.90531,0.110788,-1.0,-1.0,35.874,0.200931,1041,448898 +23,insert,399.981,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,323.52,0.328769,1091,733493 +24,search,2994.8,1174.21,669.034,1.03349,94.9481,-nan,-nan,0.9004,0.113599,-1.0,-1.0,66.913,0.328944,1102,733493 +25,insert,35.069,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,29.291,0.345738,1107,777443 +26,search,3016.23,1167.16,654.749,1.03724,84.4454,-nan,-nan,0.89929,0.114896,-1.0,-1.0,19.189,0.345741,1108,777443 +27,insert,26.067,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,17.498,0.356229,1109,805394 +28,search,3093.11,1196.28,687.579,1.03815,78.9058,-nan,-nan,0.90114,0.113727,-1.0,-1.0,17.461,0.356231,1110,805394 +29,insert,55.811,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,51.268,0.384265,1118,866391 +30,search,3067.15,1254.79,714.868,1.11675,81.1063,-nan,-nan,0.90334,0.112491,-1.0,-1.0,20.417,0.384265,1120,866391 +31,insert,434.69,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,348.394,0.55227,1174,1239816 +32,search,3302.38,1550.25,887.223,1.027,84.8034,-nan,-nan,0.8961,0.118117,-1.0,-1.0,63.66,0.552278,1178,1239816 +33,insert,46.096,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,26.776,0.573493,1183,1291211 +34,search,3347.85,1565.66,905.327,1.04494,83.7677,-nan,-nan,0.89578,0.118547,-1.0,-1.0,49.769,0.5735,1186,1291211 +35,insert,43.682,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,46.199,0.58576,1194,1324978 +36,search,3444.64,1584.95,935.756,0.99145,87.9751,-nan,-nan,0.89719,0.117346,-1.0,-1.0,44.552,0.58577,1198,1324978 +37,insert,61.434,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,41.089,0.606756,1204,1371885 +38,search,3437.94,1604.69,956.52,1.02288,88.8825,-nan,-nan,0.89618,0.118174,-1.0,-1.0,16.839,0.606756,1205,1371885 +39,insert,12.461,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,8.353,0.609532,1205,1379335 +40,search,3410.13,1609.6,973.105,0.988351,94.9484,-nan,-nan,0.89607,0.118548,-1.0,-1.0,9.248,0.609532,1205,1379335 +41,insert,44.087,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,36.041,0.625083,1211,1413312 +42,search,3454.85,1626.89,975.67,1.04153,80.2463,-nan,-nan,0.89742,0.117832,-1.0,-1.0,14.88,0.6253,1212,1413312 +43,insert,11.141,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,12.258,0.629047,1213,1423411 +44,search,3398.48,1636.44,969.078,1.04653,74.5874,-nan,-nan,0.89749,0.117805,-1.0,-1.0,8.882,0.629047,1213,1423411 +45,insert,203.117,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,43.051,0.644239,1221,1457559 +46,search,3388.06,1648.35,912.967,1.10212,75.6174,-nan,-nan,0.89793,0.116804,-1.0,-1.0,8.814,0.644239,1221,1457559 +47,insert,273.6,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,267.573,0.749406,1255,1688593 +48,search,3625.34,1789.11,1064.85,1.05902,88.5737,-nan,-nan,0.90016,0.116773,-1.0,-1.0,89.809,0.749877,1266,1688593 +49,insert,52.095,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,49.044,0.764106,1272,1723505 +50,search,3697.28,1775.03,1092.25,1.00747,93.0057,-nan,-nan,0.90113,0.115442,-1.0,-1.0,22.637,0.764106,1273,1723505 +51,insert,363.88,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,269.881,0.904015,1312,2035040 +52,search,3951.5,1969.26,1242.76,1.00906,108.238,-nan,-nan,0.90382,0.114674,-1.0,-1.0,34.094,0.904023,1316,2035040 +53,insert,45.887,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,51.689,0.92232,1321,2078341 +54,search,3972.63,1985.61,1245.76,0.987585,111.149,-nan,-nan,0.9038,0.114677,-1.0,-1.0,9.77,0.92232,1321,2078341 +55,insert,398.482,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,490.548,1.07033,1377,2399905 +56,search,4203.19,2132.33,1364.71,0.995361,120.229,-nan,-nan,0.90236,0.117637,-1.0,-1.0,148.974,1.07141,1394,2399905 +57,insert,23.348,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,9.984,1.07968,1394,2419836 +58,search,4234.97,2114.51,1370.67,1.03681,105.987,-nan,-nan,0.90361,0.115983,-1.0,-1.0,35.601,1.07972,1396,2419836 +59,insert,245.088,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,152.92,1.17676,1409,2643083 +60,search,4289.87,2168.03,1395.52,1.05625,117.672,-nan,-nan,0.89603,0.124549,-1.0,-1.0,51.073,1.17693,1414,2643083 +61,insert,10.324,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.841,1.18076,1415,2653064 +62,search,4231.39,2164.25,1359.35,1.06643,106.408,-nan,-nan,0.89595,0.124396,-1.0,-1.0,13.863,1.18076,1415,2653064 +63,insert,4.94,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,10.62,1.18206,1415,2656118 +64,search,4286.13,2167.84,1414.58,0.985006,120.159,-nan,-nan,0.89608,0.124257,-1.0,-1.0,12.667,1.18206,1415,2656118 +65,insert,96.44,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,127.683,1.20889,1438,2723424 +66,search,4427.55,2182.25,1444.93,1.00564,125.558,-nan,-nan,0.89726,0.12338,-1.0,-1.0,17.284,1.20891,1439,2723424 +67,insert,50.731,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,81.706,1.2296,1453,2769021 +68,search,4478.5,2194.51,1474.12,0.971752,130.866,-nan,-nan,0.89831,0.122862,-1.0,-1.0,15.807,1.2296,1454,2769021 +69,insert,58.868,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,67.143,1.25116,1462,2821777 +70,search,4524.09,2219.21,1498.16,0.956801,133.288,-nan,-nan,0.90033,0.121045,-1.0,-1.0,11.026,1.25116,1462,2821777 +71,insert,20.243,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,24.852,1.25617,1465,2834921 +72,search,4492.7,2227.61,1486.48,0.982621,128.681,-nan,-nan,0.90108,0.120799,-1.0,-1.0,10.905,1.25617,1465,2834921 +73,insert,11.74,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,10.319,1.25974,1465,2842044 +74,search,4472.35,2233.44,1432.02,1.08092,111.133,-nan,-nan,0.90122,0.120654,-1.0,-1.0,10.655,1.25974,1465,2842044 +75,insert,22.407,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.118,1.26643,1466,2858890 +76,search,4451.67,2244.69,1499.53,0.980039,126.196,-nan,-nan,0.90168,0.120285,-1.0,-1.0,10.943,1.26643,1466,2858890 +77,insert,31.107,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,10.223,1.27611,1466,2882818 +78,search,4478.69,2257.3,1506,0.998915,131.317,-nan,-nan,0.90142,0.12044,-1.0,-1.0,17.983,1.27632,1467,2882818 +79,insert,451.838,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,12.418,1.30428,1468,2947806 +80,search,4482,2290.68,1526.24,0.992914,127.819,-nan,-nan,0.90098,0.120964,-1.0,-1.0,10.728,1.30428,1468,2947806 +81,insert,31.632,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,31.168,1.31604,1472,2976895 +82,search,4548.47,2297.66,1532.82,0.97736,134.684,-nan,-nan,0.90237,0.120179,-1.0,-1.0,11.935,1.31604,1472,2976895 +83,insert,15.766,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,38.479,1.32143,1476,2990682 +84,search,4539.7,2295.85,1542.23,1.05909,119.832,-nan,-nan,0.9025,0.12003,-1.0,-1.0,12.587,1.32143,1476,2990682 +85,insert,46.906,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,37.972,1.33711,1479,3025613 +86,search,4617.63,2318.14,1563.25,1.01272,138.024,-nan,-nan,0.90394,0.119043,-1.0,-1.0,19.633,1.33732,1480,3025613 +87,insert,637.854,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,724.97,1.54453,1576,3468632 +88,search,4975.69,2442.84,1740.81,0.968766,153.493,-nan,-nan,0.90557,0.116489,-1.0,-1.0,78.526,1.54453,1583,3468632 +89,insert,403.651,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,441.781,1.70389,1651,3831692 +90,search,5205.97,2554.48,1806.34,1.07284,148.549,-nan,-nan,0.91036,0.110757,-1.0,-1.0,68.016,1.70424,1659,3831692 +91,insert,32.911,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,47.06,1.71631,1665,3864067 +92,search,5343.85,2547.49,1885.9,1.0381,166.411,-nan,-nan,0.91036,0.110702,-1.0,-1.0,17.647,1.71631,1666,3864067 +93,insert,262.614,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,230.646,1.82019,1698,4103827 +94,search,5483.83,2615.04,1971.46,1.0212,175.162,-nan,-nan,0.91068,0.110878,-1.0,-1.0,47.913,1.82044,1702,4103827 +95,insert,18.017,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,42.606,1.82655,1707,4119898 +96,search,5499.95,2604.41,1970.76,0.990128,172.939,-nan,-nan,0.91086,0.110906,-1.0,-1.0,14.889,1.82655,1707,4119898 +97,insert,10.122,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.915,1.82916,1707,4129367 +98,search,5484.74,2610.67,1974.87,1.02472,174.773,-nan,-nan,0.91098,0.110875,-1.0,-1.0,14.664,1.82916,1707,4129367 +99,insert,5.622,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,19.033,1.83055,1708,4134502 +100,search,5513.07,2613.02,1976.83,1.02165,167.954,-nan,-nan,0.91127,0.110706,-1.0,-1.0,14.173,1.83055,1708,4134502 +101,insert,33.103,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,42.466,1.84101,1712,4164482 +102,search,5515.33,2621.75,1983.15,1.01529,167.851,-nan,-nan,0.91148,0.111001,-1.0,-1.0,14.438,1.84101,1712,4164482 +103,insert,16.761,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,39.878,1.84731,1716,4178601 +104,search,5546.34,2623.31,1988.96,1.03176,173.108,-nan,-nan,0.91161,0.110939,-1.0,-1.0,14.579,1.84731,1716,4178601 +105,insert,7.691,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,27.215,1.84944,1718,4187774 +106,search,5509.85,2621.35,1963.75,1.07406,162.847,-nan,-nan,0.91143,0.111133,-1.0,-1.0,18.186,1.84944,1718,4187774 +107,insert,29.291,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,15.808,1.85475,1718,4200109 +108,search,5394,2626.41,1997.74,1.03681,169.298,-nan,-nan,0.91136,0.111178,-1.0,-1.0,15.845,1.85475,1718,4200109 +109,insert,531.995,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,448.355,2.01489,1788,4557867 +110,search,5176.37,2703.71,2103.93,1.08588,180.518,-nan,-nan,0.91342,0.109554,-1.0,-1.0,38.956,2.01571,1794,4557867 +111,insert,18.944,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,31.098,2.02934,1800,4587252 +112,search,5318.79,2705.27,2047.75,1.07626,165.316,-nan,-nan,0.91418,0.10914,-1.0,-1.0,19.958,2.02934,1800,4587252 +113,insert,16.39,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,32.827,2.03541,1802,4600056 +114,search,5654.72,2709.14,2158.82,0.987462,185.898,-nan,-nan,0.91422,0.109054,-1.0,-1.0,17.132,2.03541,1802,4600056 +115,insert,24.446,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,35.288,2.04504,1806,4627422 +116,search,5753.82,2717.72,2160.91,0.971458,182.168,-nan,-nan,0.91468,0.108513,-1.0,-1.0,19.945,2.04504,1806,4627422 +117,insert,14.656,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,19.187,2.05065,1806,4639292 +118,search,5869.07,2723.25,2163.05,0.986817,191.155,-nan,-nan,0.91473,0.108308,-1.0,-1.0,20.244,2.05065,1806,4639292 +119,insert,3.709,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,19.21,2.05155,1806,4643423 +120,search,5887.64,2725.34,2172.18,0.983043,189.816,-nan,-nan,0.91475,0.108249,-1.0,-1.0,20.132,2.05155,1806,4643423 +121,insert,19.371,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,24.611,2.05839,1807,4657252 +122,search,5929.2,2732.14,2173.14,1.03489,187.585,-nan,-nan,0.9149,0.10813,-1.0,-1.0,20.398,2.05839,1807,4657252 +123,insert,328.218,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,538.567,2.18565,1853,4938477 +124,search,6127.68,2791.56,2266.39,0.960952,197.559,-nan,-nan,0.91586,0.108387,-1.0,-1.0,176.556,2.18689,1868,4938477 +125,insert,57.06,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,53.619,2.20463,1873,4980492 +126,search,6184.17,2774.29,2266.34,1.02246,196.13,-nan,-nan,0.91641,0.107931,-1.0,-1.0,48.789,2.20465,1875,4980492 +127,insert,62.016,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,114.92,2.22747,1889,5030515 +128,search,6238.14,2776.54,2297.54,1.00095,193.508,-nan,-nan,0.91677,0.107671,-1.0,-1.0,49.803,2.22767,1892,5030515 +129,delete,18.336,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,53.23,2.22574,1857,5009391 +130,search,6072.57,2765.29,2233.47,1.01781,186.496,-nan,-nan,0.91494,0.109067,-1.0,-1.0,23.175,2.22574,1857,5009391 +131,delete,5.299,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.546,2.22574,1857,5004093 +132,search,6090.84,2762.62,2239.24,0.99419,194.216,-nan,-nan,0.91493,0.109213,-1.0,-1.0,22.841,2.22574,1857,5004093 +133,delete,11.109,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,21.864,2.22574,1857,4991787 +134,search,6072.1,2750.92,2226.39,0.978737,190.186,-nan,-nan,0.91479,0.109316,-1.0,-1.0,23.781,2.22574,1857,4991787 +135,delete,24.235,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,44.451,2.22323,1854,4974857 +136,search,6091.63,2743.87,2224.58,0.978153,193.477,-nan,-nan,0.91494,0.108938,-1.0,-1.0,23.862,2.22323,1854,4974857 +137,delete,5.354,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.574,2.22323,1854,4971386 +138,search,6072.16,2741.94,2225.1,0.97082,191.118,-nan,-nan,0.91489,0.109076,-1.0,-1.0,23.751,2.22323,1854,4971386 +139,delete,11.473,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.34,2.22323,1854,4963487 +140,search,6102.51,2736.16,2239.03,0.968781,202.361,-nan,-nan,0.9148,0.109122,-1.0,-1.0,23.712,2.22323,1854,4963487 +141,delete,28.103,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,76.215,2.21797,1848,4941830 +142,search,6033.17,2727.24,2220.73,1.01826,187.918,-nan,-nan,0.91458,0.109245,-1.0,-1.0,23.606,2.21797,1848,4941830 +143,delete,20.979,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,96.793,2.21227,1844,4925657 +144,search,5889.56,2725.51,2076.69,1.11362,170.181,-nan,-nan,0.91473,0.109164,-1.0,-1.0,24.545,2.21227,1844,4925657 +145,delete,3.32,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.343,2.21227,1844,4922686 +146,search,6050.31,2723.77,2219.04,1.00981,187.851,-nan,-nan,0.9147,0.109221,-1.0,-1.0,31.861,2.21231,1845,4922686 +147,delete,9.571,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.434,2.21231,1845,4913636 +148,search,6027.66,2714.93,2202.35,1.00352,181.783,-nan,-nan,0.91451,0.109372,-1.0,-1.0,22.964,2.21231,1845,4913636 +149,delete,208.839,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1268.02,2.1264,1749,4717250 +150,search,5736.04,2745.05,2120.02,1.01321,175.773,-nan,-nan,0.91336,0.110239,-1.0,-1.0,43.806,2.12689,1752,4717250 +151,delete,163.29,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1113.46,2.05587,1668,4560269 +152,search,5515.74,2774.9,2037.62,1.00963,176.203,-nan,-nan,0.91297,0.111296,-1.0,-1.0,130.037,2.05822,1680,4560269 +153,delete,27.404,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,162.594,2.04481,1663,4521936 +154,search,5393.05,2755.35,1953.87,1.02771,159.936,-nan,-nan,0.91192,0.111946,-1.0,-1.0,31.747,2.04498,1664,4521936 +155,delete,18.576,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,74.707,2.04061,1660,4502222 +156,search,5448.78,2745.72,2007.61,1.04,164.01,-nan,-nan,0.91198,0.111675,-1.0,-1.0,28.192,2.04084,1661,4502222 +157,delete,41.277,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,215.74,2.02523,1649,4456039 +158,search,5380.61,2738.92,1953.24,1.01867,158.316,-nan,-nan,0.91144,0.112519,-1.0,-1.0,30.528,2.02533,1650,4456039 +159,delete,284.078,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1757.01,1.87218,1491,4143922 +160,search,4936.35,2846.62,1828.84,1.06371,153.171,-nan,-nan,0.91003,0.11434,-1.0,-1.0,162.795,1.87532,1511,4143922 +161,delete,39.744,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,103.249,1.86806,1504,4101445 +162,search,4893.14,2766.67,1767.1,1.11177,143.763,-nan,-nan,0.91034,0.114005,-1.0,-1.0,52.833,1.86826,1508,4101445 +163,delete,18.011,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,42.722,1.86588,1506,4080175 +164,search,4912.77,2740.1,1769.34,1.03502,148.861,-nan,-nan,0.90974,0.11429,-1.0,-1.0,21.781,1.86588,1506,4080175 +165,delete,51.294,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,146.813,1.85609,1498,4047313 +166,search,4929.91,2731.21,1794.38,1.0211,148.083,-nan,-nan,0.91023,0.114008,-1.0,-1.0,37.188,1.85653,1500,4047313 +167,delete,6.561,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,19.717,1.85653,1500,4040738 +168,search,4948.08,2721.36,1804.24,1.0239,153.813,-nan,-nan,0.9105,0.113968,-1.0,-1.0,20.064,1.85653,1500,4040738 +169,delete,23.117,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,66.531,1.8506,1496,4022674 +170,search,4857.4,2715.88,1743.82,1.01978,141.626,-nan,-nan,0.91014,0.114269,-1.0,-1.0,20.138,1.8506,1496,4022674 +171,delete,8.109,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,19.565,1.8506,1496,4015835 +172,search,4932.5,2708.8,1799.37,0.994702,152.857,-nan,-nan,0.91009,0.114145,-1.0,-1.0,19.892,1.8506,1496,4015835 +173,delete,39.526,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,35.628,1.84738,1494,3986424 +174,search,4910.81,2681.13,1782.1,1.00745,152.973,-nan,-nan,0.90961,0.114648,-1.0,-1.0,27.665,1.84756,1495,3986424 +175,delete,197.197,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,793.33,1.75678,1406,3804693 +176,search,4581.61,2733.19,1641.87,1.01745,135.338,-nan,-nan,0.90609,0.116488,-1.0,-1.0,107.862,1.75855,1416,3804693 +177,delete,15.257,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,69.284,1.75324,1412,3786352 +178,search,4543.43,2701.28,1659.4,1.00961,141.104,-nan,-nan,0.906,0.116272,-1.0,-1.0,21.091,1.75324,1413,3786352 +179,delete,155.154,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,920.474,1.63049,1270,3556994 +180,search,4118.67,2806.52,1579.01,0.981462,140.917,-nan,-nan,0.89599,0.121748,-1.0,-1.0,102.605,1.63203,1280,3556994 +181,delete,26.962,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,68.828,1.62388,1276,3526824 +182,search,4057.46,2750.89,1573.36,0.980947,132.212,-nan,-nan,0.89574,0.122095,-1.0,-1.0,24.869,1.62388,1277,3526824 +183,delete,169.837,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,809.687,1.53551,1178,3350245 +184,search,3583.34,2808.65,1414.4,1.04713,118.451,-nan,-nan,0.87949,0.140091,-1.0,-1.0,34.637,1.53597,1184,3350245 +185,delete,5.727,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,12.815,1.53545,1180,3340234 +186,search,3775.45,2775.28,1386.52,1.07418,115.266,-nan,-nan,0.88493,0.131791,-1.0,-1.0,59.729,1.53653,1182,3340234 +187,delete,183.459,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,274.986,1.44471,1142,3150857 +188,search,3343.59,2789.51,1373.92,1.04862,115.242,-nan,-nan,0.8878,0.128698,-1.0,-1.0,36.227,1.44567,1147,3150857 +189,delete,4.459,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.926,1.44489,1146,3143609 +190,search,3678.88,2774.72,1356.67,1.0477,115.858,-nan,-nan,0.88821,0.12855,-1.0,-1.0,15.172,1.44489,1146,3143609 +191,delete,2.837,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.799,1.4448,1146,3141038 +192,search,3858.88,2773.23,1428,0.942163,117.559,-nan,-nan,0.888,0.128691,-1.0,-1.0,15.145,1.4448,1146,3141038 +193,delete,61.223,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,172.393,1.42531,1131,3081734 +194,search,3811.76,2743.25,1399.73,0.98777,123.447,-nan,-nan,0.88786,0.129639,-1.0,-1.0,15.094,1.42531,1131,3081734 +195,delete,39.091,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,133.867,1.40939,1119,3043966 +196,search,3745.81,2733.86,1380.28,0.989301,115.467,-nan,-nan,0.88696,0.12995,-1.0,-1.0,42.936,1.40999,1122,3043966 +197,delete,35.424,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,61.331,1.40061,1118,3008145 +198,search,3732.08,2708.44,1367.77,0.995324,115.846,-nan,-nan,0.88638,0.130237,-1.0,-1.0,14.71,1.40061,1118,3008145 +199,delete,12.137,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,21.509,1.39788,1117,2999384 +200,search,3695.41,2697.03,1336.02,1.02864,117.203,-nan,-nan,0.88604,0.130371,-1.0,-1.0,14.658,1.39788,1117,2999384 +201,delete,6.088,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,28.634,1.39584,1116,2993528 +202,search,3628.35,2692.83,1278.2,1.09542,107.519,-nan,-nan,0.88606,0.130361,-1.0,-1.0,14.607,1.39584,1116,2993528 +203,delete,16.886,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.624,1.3946,1116,2980973 +204,search,3709.07,2679.14,1337.17,0.987084,117.211,-nan,-nan,0.88599,0.130442,-1.0,-1.0,14.736,1.3946,1116,2980973 +205,delete,25.124,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,50.667,1.3884,1105,2960291 +206,search,3663.21,2666.94,1324.82,1.00665,118.693,-nan,-nan,0.88446,0.131253,-1.0,-1.0,18.178,1.3884,1105,2960291 +207,delete,49.955,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,170.689,1.36242,1055,2920620 +208,search,3528.85,2702.18,1281.08,0.939916,119.503,-nan,-nan,0.88069,0.133619,-1.0,-1.0,16.715,1.36242,1055,2920620 +209,delete,19.65,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,57.655,1.35549,1048,2900501 +210,search,3484.51,2691.69,1265.25,0.950598,111.161,-nan,-nan,0.8796,0.134079,-1.0,-1.0,16.637,1.35549,1048,2900501 +211,delete,10.091,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,27.022,1.35141,1047,2891660 +212,search,3484.63,2686.91,1270.74,0.97765,107.114,-nan,-nan,0.87962,0.134035,-1.0,-1.0,26.765,1.35148,1048,2891660 +213,delete,17.202,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,61.161,1.34627,1043,2873257 +214,search,3488.86,2677.57,1271.46,0.942013,106.435,-nan,-nan,0.87936,0.134836,-1.0,-1.0,19.928,1.34627,1043,2873257 +215,delete,369.806,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1479.68,1.14875,847,2537571 +216,search,2959.66,2950.98,1138.03,0.992466,98.0244,-nan,-nan,0.87201,0.141139,-1.0,-1.0,397.327,1.15709,887,2537571 +217,delete,216.625,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,956.183,1.03774,747,2308194 +218,search,2635.5,3033.76,1035.13,0.982548,85.9458,-nan,-nan,0.86662,0.144811,-1.0,-1.0,303.177,1.04421,778,2308194 +219,delete,15.796,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,36.79,1.0401,773,2285820 +220,search,2664.41,2815.48,1007.4,0.937145,84.3674,-nan,-nan,0.86553,0.145866,-1.0,-1.0,114.009,1.04053,782,2285820 +221,delete,191.188,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,702.282,0.931892,643,2082858 +222,search,2296.27,2957.97,888.05,0.970132,81.3842,-nan,-nan,0.8549,0.153183,-1.0,-1.0,121.082,0.934506,656,2082858 +223,delete,8.625,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.831,0.932846,653,2071207 +224,search,2253.15,2869.1,846.08,1.01828,77.2851,-nan,-nan,0.85226,0.154795,-1.0,-1.0,22.638,0.933088,654,2071207 +225,delete,6.719,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,18.903,0.931297,653,2065400 +226,search,2278.39,2859.76,869.168,0.923374,80.6006,-nan,-nan,0.85188,0.154997,-1.0,-1.0,10.064,0.931297,653,2065400 +227,delete,3.099,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,9.246,0.931297,653,2062105 +228,search,2259.02,2850.32,860.538,0.929616,76.6761,-nan,-nan,0.8516,0.15526,-1.0,-1.0,9.906,0.931297,653,2062105 +229,delete,20.146,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,25.382,0.925426,650,2039610 +230,search,2209.16,2824.57,799.868,1.04772,71.2309,-nan,-nan,0.85086,0.155547,-1.0,-1.0,10.199,0.925426,650,2039610 +231,delete,14.085,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,35.785,0.9204,645,2027795 +232,search,2229.65,2829.53,848.907,0.971051,70.876,-nan,-nan,0.84999,0.156205,-1.0,-1.0,27.882,0.92064,647,2027795 +233,delete,4.949,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.634,0.919074,646,2022859 +234,search,2256.11,2816.09,843.54,0.976747,78.8253,-nan,-nan,0.8495,0.156473,-1.0,-1.0,9.711,0.919074,646,2022859 +235,delete,6.068,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.721,0.918346,645,2016264 +236,search,2237.59,2808.5,841.331,0.983559,78.4392,-nan,-nan,0.84934,0.156535,-1.0,-1.0,10.018,0.918346,645,2016264 +237,delete,286.583,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,751.028,0.793305,517,1782866 +238,search,1903.72,3095.71,760.17,0.887256,69.231,-nan,-nan,0.83998,0.165413,-1.0,-1.0,200.908,0.79686,536,1782866 +239,delete,17.84,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,57.041,0.785481,527,1758931 +240,search,1898.4,2951.29,728.935,0.90852,74.76,-nan,-nan,0.83626,0.166359,-1.0,-1.0,47.148,0.785589,529,1758931 +241,delete,6.019,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,19.356,0.784131,528,1751275 +242,search,1895.25,2929.55,728.348,1.02523,67.0185,-nan,-nan,0.8357,0.16625,-1.0,-1.0,28.57,0.784224,530,1751275 +243,delete,18.536,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.478,0.781006,527,1733264 +244,search,1883.95,2900.72,724.987,0.980999,71.6968,-nan,-nan,0.83375,0.166934,-1.0,-1.0,9.812,0.781006,527,1733264 +245,delete,10.066,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,25.368,0.77889,526,1722658 +246,search,1870.38,2886.97,716.623,0.926433,66.7042,-nan,-nan,0.83306,0.167051,-1.0,-1.0,9.757,0.77889,526,1722658 +247,delete,2.385,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,9.415,0.77889,526,1719601 +248,search,1864.42,2880.35,714.634,0.9229,68.1556,-nan,-nan,0.8328,0.167259,-1.0,-1.0,9.656,0.77889,526,1719601 +249,delete,7.163,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.193,0.777426,524,1711648 +250,search,1893.66,2871.84,717.578,0.92695,70.6892,-nan,-nan,0.83294,0.167707,-1.0,-1.0,9.806,0.777426,524,1711648 +251,delete,281.255,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,332.799,0.658239,447,1470624 +252,search,1644.25,2988.37,643.236,0.960522,63.6029,-nan,-nan,0.82919,0.170523,-1.0,-1.0,65.749,0.659347,453,1470624 +253,delete,25.279,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,48.538,0.652117,447,1442070 +254,search,1638.66,2898.31,628.387,0.906523,62.5499,-nan,-nan,0.82636,0.171669,-1.0,-1.0,16.157,0.652123,448,1442070 +255,delete,39.605,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,123.359,0.632354,428,1405549 +256,search,1574.95,2955.47,614.627,0.957842,62.2004,-nan,-nan,0.82052,0.175222,-1.0,-1.0,42.976,0.632926,432,1405549 +257,insert,10.858,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,7.614,0.635618,432,1416288 +258,search,1581.91,2931.15,611.738,0.89751,60.0277,-nan,-nan,0.82148,0.174858,-1.0,-1.0,15.343,0.63568,433,1416288 +259,insert,37.579,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,34.39,0.646862,435,1443010 +260,search,1602.22,2960.01,620.766,0.914859,63.873,-nan,-nan,0.8208,0.176376,-1.0,-1.0,17.147,0.646862,436,1443010 +261,insert,6.734,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,20.263,0.648677,438,1447529 +262,search,1601.93,2946.01,621.983,0.869806,62.4922,-nan,-nan,0.82267,0.175033,-1.0,-1.0,7.9,0.648677,438,1447529 +263,insert,135.408,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,136.268,0.70138,443,1569110 +264,search,1678.61,3148.28,677.016,0.907297,65.9031,-nan,-nan,0.8246,0.175145,-1.0,-1.0,116.995,0.70138,448,1569110 +265,insert,86.922,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,162.318,0.731197,466,1636119 +266,search,1756.93,3138.28,700.504,0.86015,72.1634,-nan,-nan,0.82909,0.172376,-1.0,-1.0,112.359,0.731423,475,1636119 +267,insert,31.364,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,41.034,0.7436,478,1665152 +268,search,1769.01,3109.26,700.991,0.915684,71.061,-nan,-nan,0.83025,0.172058,-1.0,-1.0,83.72,0.743604,486,1665152 +269,insert,296.221,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,311.878,0.855934,513,1916952 +270,search,1945.72,3313.95,796.831,0.896126,74.983,-nan,-nan,0.83376,0.169836,-1.0,-1.0,92.175,0.85635,519,1916952 +271,insert,4.883,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,9.069,0.857303,519,1920898 +272,search,1912.6,3260.74,777.718,0.939992,72.1861,-nan,-nan,0.83444,0.168858,-1.0,-1.0,60.351,0.857304,521,1920898 +273,insert,21.209,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,34.317,0.864475,524,1942757 +274,search,1957.44,3265.22,807.787,0.960639,71.9841,-nan,-nan,0.83817,0.165899,-1.0,-1.0,48.809,0.864628,527,1942757 +275,insert,444.783,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,621.101,1.0443,594,2328372 +276,search,2241.75,3456.77,948.805,0.986834,86.1372,-nan,-nan,0.84527,0.16313,-1.0,-1.0,245.527,1.04593,619,2328372 +277,insert,36.67,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,76.231,1.05935,628,2363257 +278,search,2311,3329.98,961.356,0.908148,86.7903,-nan,-nan,0.84759,0.161182,-1.0,-1.0,114.935,1.06036,639,2363257 +279,insert,30.308,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,55.131,1.07157,645,2388933 +280,search,2371.95,3294.7,981.285,0.953042,85.6392,-nan,-nan,0.85003,0.159534,-1.0,-1.0,56.499,1.07228,651,2388933 +281,insert,291.072,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,377.28,1.20686,680,2684315 +282,search,2512.68,3429.78,1060.66,0.974092,91.9451,-nan,-nan,0.85315,0.158808,-1.0,-1.0,211.555,1.20867,697,2684315 +283,insert,464.574,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,707.8,1.40005,787,3109157 +284,search,2893.91,3485.52,1227.31,0.947671,107.377,-nan,-nan,0.86263,0.151379,-1.0,-1.0,292.422,1.40231,823,3109157 +285,insert,11.665,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,42.647,1.40723,828,3122751 +286,search,2949.41,3308.35,1218.58,0.950959,100.249,-nan,-nan,0.8623,0.151363,-1.0,-1.0,59.907,1.40768,834,3122751 +287,insert,39.619,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,80.018,1.42605,843,3163679 +288,search,3018,3288.09,1236.52,0.973086,113.833,-nan,-nan,0.86387,0.15031,-1.0,-1.0,43.721,1.42619,847,3163679 +289,insert,373.037,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,505.693,1.56313,903,3472031 +290,search,3231.67,3393.88,1342.28,1.03478,110.179,-nan,-nan,0.86775,0.147918,-1.0,-1.0,229.587,1.56537,922,3472031 +291,insert,23.679,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,48.936,1.57437,928,3495577 +292,search,3314.4,3331.06,1375.36,0.98187,112.035,-nan,-nan,0.86925,0.146365,-1.0,-1.0,144.314,1.57437,936,3495577 +293,insert,18.821,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,42.419,1.58281,939,3515193 +294,search,3363.03,3310.33,1379.33,1.03202,120.666,-nan,-nan,0.86995,0.145957,-1.0,-1.0,70.877,1.58309,944,3515193 +295,insert,254.202,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,365.033,1.67474,986,3723063 +296,search,3487.07,3361.04,1398.73,1.14297,116.852,-nan,-nan,0.87525,0.142732,-1.0,-1.0,176.858,1.67578,1004,3723063 +297,insert,4.343,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,20.057,1.67768,1005,3727399 +298,search,3534.97,3293.07,1443.31,0.96542,119.105,-nan,-nan,0.8754,0.14269,-1.0,-1.0,23.489,1.6777,1006,3727399 +299,insert,76.215,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,91.579,1.69952,1019,3788002 +300,search,3611.77,3306.8,1486.21,0.95501,127.677,-nan,-nan,0.87817,0.139905,-1.0,-1.0,19.687,1.69963,1020,3788002 +301,insert,696.228,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1160.91,1.97042,1156,4370866 +302,search,4180.71,3485.73,1768.79,0.969352,157.559,-nan,-nan,0.90213,0.121982,-1.0,-1.0,295.781,1.9708,1199,4370866 +303,insert,57.77,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,55.344,1.99031,1204,4420306 +304,search,4260.3,3290.38,1740.14,1.00478,147.249,-nan,-nan,0.90121,0.122298,-1.0,-1.0,63.879,1.99071,1211,4420306 +305,insert,388.84,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,470.51,2.15531,1254,4789669 +306,search,4484.52,3392.35,1860.36,0.95642,161.303,-nan,-nan,0.90362,0.120022,-1.0,-1.0,312.045,2.15725,1279,4789669 +307,insert,28.628,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,58.2,2.1661,1286,4815550 +308,search,4524.92,3334.42,1856.56,1.01501,154.683,-nan,-nan,0.90512,0.118899,-1.0,-1.0,148.016,2.16656,1296,4815550 +309,insert,7.911,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,29.693,2.16938,1299,4823345 +310,search,4522.76,3302.93,1800.4,1.09329,151.366,-nan,-nan,0.90518,0.118736,-1.0,-1.0,74.357,2.16938,1303,4823345 +311,insert,10.535,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,12.142,2.17346,1303,4843493 +312,search,4620.68,3301.07,1873.56,0.939633,163.139,-nan,-nan,0.90521,0.118762,-1.0,-1.0,24.779,2.17346,1304,4843493 +313,insert,41.166,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,137.331,2.18983,1319,4885489 +314,search,4685.96,3296.28,1893.68,0.968189,162.251,-nan,-nan,0.90576,0.118733,-1.0,-1.0,34.968,2.19018,1322,4885489 +315,insert,9.71,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,11.69,2.19332,1322,4892335 +316,search,4673.09,3290.58,1904.05,1.01368,165.117,-nan,-nan,0.90587,0.118811,-1.0,-1.0,12.43,2.19332,1322,4892335 +317,insert,49.852,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,110.429,2.21089,1335,4932996 +318,search,4601,3287.37,1829.57,1.08734,150.034,-nan,-nan,0.90616,0.118443,-1.0,-1.0,12.433,2.21089,1335,4932996 +319,insert,593.142,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,828.068,2.42319,1437,5430684 +320,search,4989.83,3406.28,2006.06,1.17582,163.318,-nan,-nan,0.91094,0.115162,-1.0,-1.0,287.957,2.42793,1471,5430684 +321,insert,43.606,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,87.349,2.44242,1481,5471239 +322,search,5217.89,3341.25,2155.88,1.00832,180.498,-nan,-nan,0.91137,0.114786,-1.0,-1.0,20.604,2.44242,1482,5471239 +323,insert,115.595,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,203.613,2.48753,1506,5575560 +324,search,5228.63,3353.92,2116.3,1.05867,175.497,-nan,-nan,0.91225,0.113563,-1.0,-1.0,39.69,2.48758,1510,5575560 +325,insert,1480.92,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,743.745,2.71036,1578,6069499 +326,search,5652.46,3480.56,2357.97,1.02024,202.967,-nan,-nan,0.91563,0.11156,-1.0,-1.0,366.034,2.7117,1606,6069499 +327,insert,67.688,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,86.121,2.7379,1616,6139647 +328,search,5759.23,3428.48,2376.59,0.996581,202.357,-nan,-nan,0.91702,0.110853,-1.0,-1.0,211.782,2.7397,1636,6139647 +329,insert,9.469,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,20.19,2.74252,1637,6146884 +330,search,5817.95,3385.96,2393.35,0.991392,204.802,-nan,-nan,0.91729,0.110487,-1.0,-1.0,88.173,2.74304,1643,6146884 +331,insert,53.955,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,103.752,2.76285,1654,6188816 +332,search,5778.19,3374.13,2334.97,1.01998,193.207,-nan,-nan,0.9172,0.110888,-1.0,-1.0,42.003,2.76299,1657,6188816 +333,insert,2.572,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.403,2.76328,1657,6190810 +334,search,5619.48,3368.53,2410.14,0.97144,206.669,-nan,-nan,0.91697,0.111125,-1.0,-1.0,15.691,2.76328,1657,6190810 +335,insert,49.828,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,101.06,2.77954,1669,6230108 +336,search,5660.87,3369.95,2299.56,1.07461,183.262,-nan,-nan,0.9174,0.11043,-1.0,-1.0,41.24,2.77981,1671,6230108 +337,insert,24.502,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,55.185,2.78834,1675,6249699 +338,search,5424.58,3369.5,2443.05,0.96791,212.547,-nan,-nan,0.91803,0.109772,-1.0,-1.0,10.119,2.78834,1675,6249699 +339,insert,33.1,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,62.42,2.80336,1687,6290226 +340,search,5741.51,3372.34,2341.27,1.02686,191.698,-nan,-nan,0.91898,0.108995,-1.0,-1.0,23.85,2.80353,1688,6290226 +341,insert,8.078,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,15.208,2.80588,1688,6297556 +342,search,6004.76,3371.89,2477.79,0.950462,208.155,-nan,-nan,0.91909,0.109042,-1.0,-1.0,25.651,2.80604,1689,6297556 +343,insert,39.281,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,90.939,2.81943,1699,6330843 +344,search,5916.25,3371.67,2389.48,1.00682,194.674,-nan,-nan,0.91925,0.108823,-1.0,-1.0,23.391,2.81971,1700,6330843 +345,insert,49.132,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,90.337,2.83753,1710,6370265 +346,search,5961.28,3374.56,2414.93,1.02316,199.591,-nan,-nan,0.91989,0.108362,-1.0,-1.0,15.872,2.83753,1710,6370265 +347,insert,585.072,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1025.58,3.0401,1836,6831086 +348,search,6432.08,3385.23,2601.4,1.01005,214.946,-nan,-nan,0.92269,0.105671,-1.0,-1.0,136.552,3.04157,1851,6831086 +349,insert,51.446,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,60.676,3.05854,1856,6876154 +350,search,6453.14,3373.56,2585.6,1.03137,207.192,-nan,-nan,0.92299,0.105466,-1.0,-1.0,43.467,3.05955,1858,6876154 +351,insert,486.223,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,667.573,3.24806,1923,7288266 +352,search,6872.14,3438.51,2843.76,0.968909,238.398,-nan,-nan,0.92333,0.105702,-1.0,-1.0,260.887,3.24991,1945,7288266 +353,insert,55.839,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,108.882,3.2695,1956,7333132 +354,search,6929.52,3402.63,2842.93,0.980906,240.042,-nan,-nan,0.9236,0.105772,-1.0,-1.0,127.2,3.2696,1967,7333132 +355,insert,430.123,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,747.302,3.43459,2059,7696838 +356,search,7148.56,3379.83,2886.97,1.0903,233.97,-nan,-nan,0.92549,0.103703,-1.0,-1.0,268.111,3.43787,2086,7696838 +357,insert,21.753,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,46.107,3.44417,2089,7714498 +358,search,7277.05,3339.99,2913.39,1.05335,246.119,-nan,-nan,0.92563,0.103592,-1.0,-1.0,37.388,3.44417,2090,7714498 +359,insert,12.429,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,38.695,3.44781,2092,7725755 +360,search,7317.71,3340.24,2956.63,1.00846,250.991,-nan,-nan,0.92563,0.103688,-1.0,-1.0,27.57,3.44781,2092,7725755 +361,insert,72.122,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,153.881,3.47426,2106,7789312 +362,search,7412.22,3343.23,3003,1.00827,258.018,-nan,-nan,0.92623,0.103469,-1.0,-1.0,42.122,3.47426,2107,7789312 +363,insert,26.285,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,34.66,3.47837,2108,7803163 +364,search,7383.54,3347.63,3030.94,1.01094,254.412,-nan,-nan,0.92648,0.103216,-1.0,-1.0,62.501,3.47875,2111,7803163 +365,insert,53.445,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,97.177,3.50686,2127,7863722 +366,search,6749.92,3350.76,2787.36,1.16549,214.683,-nan,-nan,0.9271,0.102796,-1.0,-1.0,28.118,3.50729,2129,7863722 +367,insert,24.784,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,53.797,3.52403,2137,7895271 +368,search,7165.88,3351.44,2983.11,1.05444,245.762,-nan,-nan,0.92767,0.102285,-1.0,-1.0,43.922,3.52445,2139,7895271 +369,insert,73.626,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,158.592,3.54825,2158,7961194 +370,search,7554.07,3339.06,3043.14,1.04121,250.702,-nan,-nan,0.92768,0.102291,-1.0,-1.0,78.69,3.54915,2163,7961194 +371,insert,13.175,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,42.572,3.55231,2165,7970239 +372,search,7320.52,3336.88,2832.92,1.17719,218.984,-nan,-nan,0.92773,0.102332,-1.0,-1.0,45.693,3.5526,2167,7970239 +373,insert,56.07,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,97.324,3.56904,2176,8010868 +374,search,7566.85,3340.48,3018.49,1.04616,249.573,-nan,-nan,0.92835,0.101855,-1.0,-1.0,27.026,3.56904,2176,8010868 +375,insert,45.038,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,86.28,3.58208,2184,8040698 +376,search,6950.24,3338.85,2985.79,1.08163,246.04,-nan,-nan,0.92855,0.101788,-1.0,-1.0,42.014,3.5823,2186,8040698 +377,insert,51.882,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,55.749,3.60813,2195,8104748 +378,search,7513.76,3347.67,3076.08,1.06537,260.384,-nan,-nan,0.92931,0.101258,-1.0,-1.0,63.825,3.60848,2199,8104748 +379,insert,5.772,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,26.469,3.60982,2199,8109755 +380,search,7647.37,3345.55,3085.86,1.05033,259.194,-nan,-nan,0.92929,0.101289,-1.0,-1.0,27.968,3.60982,2199,8109755 +381,insert,24.647,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,58.402,3.61798,2202,8130382 +382,search,7620.59,3348.23,3010.95,1.10353,242.677,-nan,-nan,0.92947,0.101211,-1.0,-1.0,55.905,3.61836,2204,8130382 +383,insert,42.875,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,78.319,3.62674,2209,8153290 +384,search,7668.02,3348.5,3051.13,1.09488,251.094,-nan,-nan,0.92956,0.101079,-1.0,-1.0,28.884,3.62674,2209,8153290 +385,delete,26.557,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,26.866,3.62674,2209,8138873 +386,search,7683.66,3343.6,3056.72,1.10707,250.553,-nan,-nan,0.92959,0.101001,-1.0,-1.0,29.267,3.62674,2209,8138873 +387,delete,34.375,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,170.871,3.61832,2203,8115069 +388,search,7670,3340.96,3081.7,1.03258,257.035,-nan,-nan,0.92969,0.100713,-1.0,-1.0,45.678,3.61869,2205,8115069 +389,delete,21.397,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,114.955,3.61303,2199,8101157 +390,search,7764.62,3342,3156.31,1.01771,270.006,-nan,-nan,0.92941,0.100948,-1.0,-1.0,50.764,3.61339,2201,8101157 +391,delete,117.445,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,416.004,3.57285,2170,8014644 +392,search,7681.97,3351.9,3129.75,0.97196,270.484,-nan,-nan,0.92885,0.100629,-1.0,-1.0,78.729,3.57367,2176,8014644 +393,delete,37.464,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,173.186,3.56598,2168,7978358 +394,search,7515.59,3334.29,2991.2,1.0753,244.624,-nan,-nan,0.92833,0.101446,-1.0,-1.0,40.967,3.56609,2169,7978358 +395,delete,22.665,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,257.149,3.55274,2158,7957094 +396,search,7521.83,3341.16,3004.9,1.0565,248.863,-nan,-nan,0.92801,0.101428,-1.0,-1.0,86.888,3.55363,2164,7957094 +397,delete,119.753,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,887.665,3.49478,2125,7823916 +398,search,7400.8,3346.68,2968.97,1.0543,254.641,-nan,-nan,0.92763,0.101616,-1.0,-1.0,131.63,3.49711,2137,7823916 +399,delete,4.775,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,27.105,3.49711,2137,7818430 +400,search,7418.57,3324.61,2958.99,1.08798,249.628,-nan,-nan,0.92792,0.101269,-1.0,-1.0,35.329,3.49723,2138,7818430 +401,delete,17.636,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,57.388,3.49321,2135,7800702 +402,search,7349.15,3317.74,2903.45,1.10967,239.598,-nan,-nan,0.92717,0.101939,-1.0,-1.0,40.242,3.49341,2136,7800702 +403,delete,329.934,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1905.38,3.35389,2014,7517858 +404,search,6919.22,3379.46,2751.79,1.07233,223.1,-nan,-nan,0.92549,0.103529,-1.0,-1.0,300.075,3.36127,2048,7517858 +405,delete,52.382,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,346.914,3.34233,2031,7451637 +406,search,6999.3,3322.13,2760.75,1.07002,224.239,-nan,-nan,0.9261,0.102909,-1.0,-1.0,80.801,3.34272,2035,7451637 +407,delete,114.218,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,723.831,3.2948,1994,7360417 +408,search,7060.27,3336.38,2860.48,0.978205,244.048,-nan,-nan,0.92505,0.103547,-1.0,-1.0,100.634,3.29567,2001,7360417 +409,delete,224.726,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,837.032,3.19099,1951,7131620 +410,search,6839.74,3337.05,2740.75,1.0613,233.546,-nan,-nan,0.92459,0.103301,-1.0,-1.0,143.068,3.19395,1962,7131620 +411,delete,262.392,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1739.98,3.07617,1850,6867617 +412,search,6623.28,3384.79,2712.8,0.970391,239.434,-nan,-nan,0.92372,0.104474,-1.0,-1.0,270.406,3.08042,1880,6867617 +413,delete,13.583,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,95.905,3.07706,1876,6850098 +414,search,6532.79,3322.53,2600.9,1.06053,216.379,-nan,-nan,0.92368,0.104534,-1.0,-1.0,74.961,3.07746,1882,6850098 +415,delete,75.412,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,492.002,3.04352,1859,6782921 +416,search,6487.53,3323.34,2586.31,1.07042,218.915,-nan,-nan,0.92344,0.104486,-1.0,-1.0,72.742,3.04495,1864,6782921 +417,delete,238.907,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1165.37,2.95114,1802,6562039 +418,search,6249.95,3315.79,2479.18,1.08095,207.181,-nan,-nan,0.92305,0.105265,-1.0,-1.0,140.724,2.95282,1814,6562039 +419,delete,23.928,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,77.329,2.94849,1810,6536285 +420,search,6396.4,3289.49,2583.19,0.975967,222.669,-nan,-nan,0.92325,0.105325,-1.0,-1.0,49.534,2.94873,1812,6536285 +421,delete,21.618,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,152.24,2.93687,1803,6510820 +422,search,6350.52,3288.5,2558.64,0.972112,218.993,-nan,-nan,0.92366,0.105078,-1.0,-1.0,32.264,2.937,1804,6510820 +423,delete,188.496,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,616.144,2.86399,1747,6334168 +424,search,6065.22,3299.56,2401.94,1.08905,200.763,-nan,-nan,0.92191,0.106386,-1.0,-1.0,89.426,2.86526,1755,6334168 +425,delete,18.13,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,73.386,2.86116,1752,6316443 +426,search,6199.85,3280.49,2493.87,0.978208,214.025,-nan,-nan,0.92209,0.106212,-1.0,-1.0,33.972,2.86122,1753,6316443 +427,delete,52.266,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,99.474,2.85217,1746,6266345 +428,search,6013.16,3258.07,2346.78,1.11085,196.799,-nan,-nan,0.92202,0.106483,-1.0,-1.0,20.487,2.85217,1746,6266345 +429,delete,496.006,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,2796.2,2.63182,1505,5883847 +430,search,5412.66,3617.3,2239.62,1.10402,178.508,-nan,-nan,0.91024,0.115128,-1.0,-1.0,626.866,2.64457,1580,5883847 +431,delete,70.643,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,407.219,2.60665,1554,5801380 +432,search,5437,3393.35,2154.01,1.05494,175.33,-nan,-nan,0.90892,0.115225,-1.0,-1.0,117.471,2.60826,1564,5801380 +433,delete,217.856,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1128.52,2.51483,1488,5607567 +434,search,5273.23,3431.17,2129,1.03503,177.952,-nan,-nan,0.90646,0.117174,-1.0,-1.0,146.318,2.51743,1500,5607567 +435,delete,103.938,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,371.715,2.48177,1470,5512176 +436,search,5317.04,3414.76,2189.13,0.972748,193.297,-nan,-nan,0.90537,0.119299,-1.0,-1.0,205.524,2.48612,1480,5512176 +437,delete,9.952,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,79.813,2.48103,1476,5501141 +438,search,5255.19,3390.65,2130.16,1.01803,183.314,-nan,-nan,0.90564,0.118834,-1.0,-1.0,135.576,2.48147,1483,5501141 +439,delete,108.257,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,321.629,2.42167,1467,5369822 +440,search,5261.21,3387.17,2151.58,0.968078,186.099,-nan,-nan,0.90818,0.116107,-1.0,-1.0,149.9,2.42271,1479,5369822 +441,delete,24.929,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,152.465,2.41266,1471,5338985 +442,search,5193.93,3356.95,2095.06,1.04999,177.903,-nan,-nan,0.90788,0.116243,-1.0,-1.0,26.861,2.41277,1472,5338985 +443,delete,30.28,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,86.567,2.39892,1466,5307279 +444,search,5135.41,3353.86,2025.45,1.17273,172.723,-nan,-nan,0.90864,0.115841,-1.0,-1.0,17.378,2.39892,1466,5307279 +445,delete,41.806,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,123.392,2.38775,1459,5268382 +446,search,5222.81,3345.32,2127.18,1.0067,181.798,-nan,-nan,0.90812,0.116251,-1.0,-1.0,39.124,2.38807,1461,5268382 +447,delete,455.945,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1537.78,2.21707,1309,4922787 +448,search,4611.61,3477.77,1836.58,1.11556,150.736,-nan,-nan,0.90203,0.12055,-1.0,-1.0,354.745,2.22398,1343,4922787 +449,delete,33.205,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,180.815,2.21276,1329,4887227 +450,search,4818.56,3388.34,1983.31,0.962429,176.776,-nan,-nan,0.90308,0.119907,-1.0,-1.0,143.892,2.21366,1337,4887227 +451,delete,91.237,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,394.013,2.16853,1299,4795082 +452,search,4639.3,3396.62,1884.27,1.04861,161.531,-nan,-nan,0.90179,0.120242,-1.0,-1.0,94.836,2.16914,1306,4795082 +453,delete,342.548,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1596.19,2.02039,1169,4500175 +454,search,4261.71,3511.26,1763.05,0.966918,155.413,-nan,-nan,0.89651,0.123812,-1.0,-1.0,410.667,2.02898,1205,4500175 +455,delete,30.706,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,117.701,2.01574,1197,4462648 +456,search,4375.34,3421.38,1812.61,0.93558,160.024,-nan,-nan,0.89628,0.123888,-1.0,-1.0,192.485,2.01761,1207,4462648 +457,delete,5.726,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,25.984,2.01571,1206,4456761 +458,search,4369.68,3393.41,1786.79,0.953508,162.524,-nan,-nan,0.89668,0.123411,-1.0,-1.0,87.153,2.0157,1211,4456761 +459,delete,33.906,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,187.816,1.99548,1196,4419992 +460,search,4231.56,3395.93,1688.31,1.01982,146.591,-nan,-nan,0.89653,0.123811,-1.0,-1.0,29.249,1.99548,1197,4419992 +461,delete,6.09,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.455,1.99548,1197,4415725 +462,search,4212.14,3389.66,1680.41,1.02545,139.037,-nan,-nan,0.89669,0.123569,-1.0,-1.0,14.028,1.99548,1197,4415725 +463,delete,52.676,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,267.322,1.97211,1172,4370609 +464,search,4268.98,3432.14,1746.99,0.978419,154.272,-nan,-nan,0.89581,0.124566,-1.0,-1.0,63.452,1.97282,1176,4370609 +465,delete,31.018,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,58.839,1.96092,1171,4345244 +466,search,4261.23,3407.7,1748.66,0.981658,154.883,-nan,-nan,0.89379,0.1255,-1.0,-1.0,25.879,1.96099,1172,4345244 +467,delete,37.606,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,62.642,1.95496,1169,4319734 +468,search,4246.92,3389.14,1744.41,0.934952,157.291,-nan,-nan,0.89327,0.125855,-1.0,-1.0,22.063,1.9551,1170,4319734 +469,delete,19.02,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,44.612,1.94564,1166,4298361 +470,search,4233.77,3380.06,1738.87,0.952064,154.547,-nan,-nan,0.89229,0.126401,-1.0,-1.0,14.922,1.94564,1166,4298361 +471,delete,149.412,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,421.573,1.89144,1116,4188315 +472,search,4107.49,3438.17,1703.49,0.978601,151.525,-nan,-nan,0.89108,0.127707,-1.0,-1.0,151.111,1.89429,1129,4188315 +473,delete,118.892,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,572.277,1.8342,1081,4074567 +474,search,3837.12,3442.32,1527.88,1.12393,127.968,-nan,-nan,0.8902,0.127283,-1.0,-1.0,175.324,1.83731,1097,4074567 +475,delete,441.401,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1693.51,1.64188,926,3691698 +476,search,3423.94,3659.77,1434.88,1.10616,120.814,-nan,-nan,0.88441,0.131971,-1.0,-1.0,494.535,1.65111,981,3691698 +477,delete,37.518,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,137.935,1.62875,968,3642619 +478,search,3417.72,3401.33,1356.73,1.09451,112.677,-nan,-nan,0.88278,0.132913,-1.0,-1.0,89.355,1.6294,975,3642619 +479,delete,240.813,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1221.91,1.52595,874,3421368 +480,search,3206.62,3754.17,1350.29,1.08946,110.302,-nan,-nan,0.89445,0.124311,-1.0,-1.0,390.057,1.53392,902,3421368 +481,delete,40.233,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,116.407,1.51797,889,3378034 +482,search,3152.39,3447.39,1281.98,1.10857,108.594,-nan,-nan,0.88677,0.131019,-1.0,-1.0,108.075,1.51863,898,3378034 +483,delete,284.832,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1019.19,1.39306,784,3115682 +484,search,2961.14,3597.73,1256.78,0.962054,110.315,-nan,-nan,0.87956,0.136816,-1.0,-1.0,337.789,1.39976,816,3115682 +485,delete,17.763,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,40.214,1.39521,813,3094629 +486,search,2995.11,3448.93,1262.51,0.95303,106.314,-nan,-nan,0.88083,0.136437,-1.0,-1.0,133.899,1.39574,823,3094629 +487,delete,8.003,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,21.814,1.39498,822,3086025 +488,search,3023.57,3396.71,1265.72,0.969439,114.052,-nan,-nan,0.88087,0.13626,-1.0,-1.0,27.44,1.39499,823,3086025 +489,delete,33.298,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,114.767,1.38129,815,3052105 +490,search,2986.82,3393.65,1241.05,1.01622,112.643,-nan,-nan,0.88056,0.136319,-1.0,-1.0,48.828,1.38216,818,3052105 +491,delete,14.97,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,29.384,1.3782,816,3038974 +492,search,2841.11,3371.91,1122.01,1.20808,93.1773,-nan,-nan,0.88026,0.136371,-1.0,-1.0,12.878,1.3782,816,3038974 +493,delete,148.971,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,429.615,1.30681,762,2911063 +494,search,2779.67,3458.87,1144.45,1.07008,98.178,-nan,-nan,0.87776,0.137785,-1.0,-1.0,121.55,1.30933,774,2911063 +495,delete,22.041,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,82.88,1.30107,765,2888785 +496,search,2836.88,3404.59,1185.91,0.956571,107.336,-nan,-nan,0.87832,0.137471,-1.0,-1.0,58.601,1.30203,770,2888785 +497,delete,56.86,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,150.667,1.28107,753,2829718 +498,search,2720.99,3374.53,1114.19,1.05149,96.3758,-nan,-nan,0.87639,0.138943,-1.0,-1.0,39.393,1.28151,756,2829718 +499,delete,15.464,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,26.272,1.27928,755,2816082 +500,search,2749.93,3345.96,1141.41,0.94681,98.724,-nan,-nan,0.87638,0.138929,-1.0,-1.0,11.628,1.27928,755,2816082 +501,delete,27.613,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,86.91,1.26708,748,2790880 +502,search,2643.03,3351.63,1052.33,1.05869,88.8017,-nan,-nan,0.87583,0.139061,-1.0,-1.0,20.811,1.26732,749,2790880 +503,delete,17.106,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,19.836,1.26593,748,2774459 +504,search,2752.49,3331.67,1134,0.975144,103.723,-nan,-nan,0.87556,0.139164,-1.0,-1.0,21.086,1.2661,749,2774459 +505,delete,61.057,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,172.949,1.23522,731,2714683 +506,search,2709.26,3331.88,1111.62,0.958128,101.529,-nan,-nan,0.87379,0.139823,-1.0,-1.0,37.111,1.23564,733,2714683 +507,delete,41.105,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,104.065,1.2236,722,2680986 +508,search,2538.02,3337.49,996.995,1.17072,83.4553,-nan,-nan,0.87343,0.140261,-1.0,-1.0,37.034,1.22388,724,2680986 +509,delete,19.32,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,87.013,1.21484,718,2662966 +510,search,2644.66,3332.5,1093.4,1.00441,97.8257,-nan,-nan,0.87269,0.140466,-1.0,-1.0,26.739,1.21507,719,2662966 +511,delete,24.279,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,29.404,1.21207,716,2642855 +512,search,2604.65,3310.35,1056.81,1.03112,95.653,-nan,-nan,0.87271,0.140844,-1.0,-1.0,21.934,1.21209,717,2642855 +513,insert,374.322,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,309.825,1.31449,741,2906838 +514,search,2775.36,3467.09,1162.22,0.974625,103.444,-nan,-nan,0.87457,0.139712,-1.0,-1.0,52.392,1.31478,745,2906838 +515,insert,5.921,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,10.434,1.31578,745,2913746 +516,search,2766.15,3461.07,1155.95,1.01444,96.4819,-nan,-nan,0.8753,0.139168,-1.0,-1.0,12.951,1.31578,745,2913746 +517,insert,31.044,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,50.522,1.32232,749,2936862 +518,search,2751.2,3471.08,1139,1.02213,99.3175,-nan,-nan,0.87552,0.138997,-1.0,-1.0,12.051,1.32232,749,2936862 +519,insert,128.684,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,155.996,1.35451,758,3009732 +520,search,2853.95,3519.02,1211.15,0.957387,103.653,-nan,-nan,0.87714,0.13883,-1.0,-1.0,127.899,1.3548,768,3009732 +521,insert,19.452,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,42.575,1.36012,771,3025906 +522,search,2834.22,3482.63,1196.79,0.96537,105.231,-nan,-nan,0.87724,0.138847,-1.0,-1.0,22.876,1.36012,772,3025906 +523,insert,46.738,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,87.702,1.37503,779,3061899 +524,search,2932.6,3487.38,1234.96,0.970915,108.791,-nan,-nan,0.87908,0.138187,-1.0,-1.0,51.017,1.37545,783,3061899 +525,insert,57.491,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,122.935,1.39225,795,3101209 +526,search,2938.43,3464.43,1234.49,0.934769,107.038,-nan,-nan,0.8796,0.137699,-1.0,-1.0,24.089,1.39265,796,3101209 +527,insert,610.658,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,813.572,1.57911,884,3522334 +528,search,3284.47,3581.62,1414.26,0.984524,125.218,-nan,-nan,0.88514,0.133021,-1.0,-1.0,316.516,1.58207,915,3522334 +529,insert,353.761,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,527.357,1.70009,971,3797294 +530,search,3566.82,3554.17,1492.76,1.04171,130.125,-nan,-nan,0.89141,0.13043,-1.0,-1.0,211.737,1.7012,987,3797294 +531,insert,101.397,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,140.612,1.72445,1001,3853781 +532,search,3596.81,3484.31,1461.58,1.1936,121.601,-nan,-nan,0.89208,0.129309,-1.0,-1.0,132.222,1.72495,1011,3853781 +533,insert,25.933,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,47.525,1.7327,1015,3873352 +534,search,3641.16,3450.13,1487.19,1.0733,125.192,-nan,-nan,0.89253,0.128807,-1.0,-1.0,95.518,1.73269,1021,3873352 +535,insert,33.163,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,41.195,1.7415,1024,3893308 +536,search,3631.82,3440.88,1458.72,1.08743,117.393,-nan,-nan,0.89296,0.128787,-1.0,-1.0,53.883,1.74167,1027,3893308 +537,insert,9.589,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.608,1.74556,1027,3901271 +538,search,3712.43,3435.99,1525.93,1.12763,131.816,-nan,-nan,0.89282,0.12889,-1.0,-1.0,14.752,1.74556,1027,3901271 +539,insert,34.024,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,68.932,1.75371,1033,3925164 +540,search,3713.16,3437.9,1522.81,1.04282,127.99,-nan,-nan,0.89352,0.128358,-1.0,-1.0,37.709,1.75432,1035,3925164 +541,insert,528.809,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,756.997,1.93603,1113,4320915 +542,search,3974.13,3539.51,1630.29,1.06531,132.729,-nan,-nan,0.89827,0.124958,-1.0,-1.0,324.92,1.93871,1143,4320915 +543,insert,52.669,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,94.112,1.95393,1154,4360814 +544,search,4177.95,3436.69,1743.69,0.983725,156.938,-nan,-nan,0.89916,0.124573,-1.0,-1.0,177.154,1.95506,1170,4360814 +545,insert,11.961,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,30.128,1.95879,1172,4370220 +546,search,4220.83,3385.95,1755.88,0.96058,149.853,-nan,-nan,0.89991,0.124139,-1.0,-1.0,90.293,1.95984,1180,4370220 +547,insert,188.321,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,343.467,2.02019,1227,4510675 +548,search,4214.14,3347.68,1680.12,1.13174,138.353,-nan,-nan,0.90169,0.122774,-1.0,-1.0,54.637,2.02063,1232,4510675 +549,insert,284.783,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,294.192,2.11909,1248,4744845 +550,search,4535.75,3401.42,1867.08,0.955623,162.386,-nan,-nan,0.89675,0.127609,-1.0,-1.0,112.71,2.11966,1256,4744845 +551,insert,24.47,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,55.785,2.13132,1259,4771433 +552,search,4546.66,3384.75,1874.44,0.968382,165.7,-nan,-nan,0.89763,0.126545,-1.0,-1.0,70.013,2.13182,1265,4771433 +553,insert,13.991,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,54.555,2.13627,1270,4782909 +554,search,4399.73,3365.39,1763.13,1.03325,144.918,-nan,-nan,0.89824,0.125762,-1.0,-1.0,13.89,2.13627,1270,4782909 +555,insert,530.892,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,864.925,2.3127,1392,5180322 +556,search,4885.71,3369.72,1978.3,1.0582,162.331,-nan,-nan,0.90396,0.12014,-1.0,-1.0,119.335,2.31394,1404,5180322 +557,insert,27.296,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,64.688,2.32177,1410,5203220 +558,search,4938.76,3340.47,1974.15,1.04392,163.959,-nan,-nan,0.90451,0.119584,-1.0,-1.0,16.087,2.32177,1410,5203220 +559,insert,7.586,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.597,2.32372,1410,5210154 +560,search,5033.15,3343.99,2065.66,1.00349,174.422,-nan,-nan,0.90471,0.119465,-1.0,-1.0,15.674,2.32372,1410,5210154 +561,insert,9.164,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.433,2.32645,1410,5215426 +562,search,5071.99,3347.03,2071.5,0.994145,183.904,-nan,-nan,0.90476,0.119458,-1.0,-1.0,16.064,2.32645,1410,5215426 +563,insert,63.48,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,69.304,2.33988,1417,5252726 +564,search,4966.6,3354.63,1987.47,1.0503,164.315,-nan,-nan,0.90526,0.119051,-1.0,-1.0,15.736,2.33988,1417,5252726 +565,insert,263.822,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,279.82,2.42579,1433,5447274 +566,search,5168.4,3425.63,2148.87,0.95942,189.255,-nan,-nan,0.90503,0.119292,-1.0,-1.0,207,2.42667,1442,5447274 +567,insert,18.169,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.735,2.43306,1442,5463135 +568,search,5046.75,3408.54,2031.04,1.06007,166.349,-nan,-nan,0.90449,0.119862,-1.0,-1.0,96.7,2.43326,1447,5463135 +569,insert,22.509,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,52.101,2.44028,1451,5478168 +570,search,5032.79,3403.17,2023.18,1.08877,164.916,-nan,-nan,0.9053,0.119142,-1.0,-1.0,86.248,2.44077,1458,5478168 +571,insert,18.182,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,33.493,2.44751,1459,5492309 +572,search,5021.92,3393.2,1984.26,1.14871,160.152,-nan,-nan,0.90522,0.119365,-1.0,-1.0,33.002,2.44774,1461,5492309 +573,insert,89.757,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,118.407,2.47207,1475,5554599 +574,search,5085.2,3387.13,2012.27,1.09612,159.133,-nan,-nan,0.9058,0.119203,-1.0,-1.0,23.438,2.47208,1476,5554599 +575,insert,66.247,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,124.503,2.4921,1488,5604500 +576,search,5328.42,3384.79,2199.45,0.976286,189.918,-nan,-nan,0.9059,0.119068,-1.0,-1.0,41.303,2.4924,1491,5604500 +577,insert,49.336,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,71.343,2.5056,1499,5638834 +578,search,5283.4,3379.09,2150.29,1.02095,174.755,-nan,-nan,0.90618,0.119181,-1.0,-1.0,16.132,2.5056,1499,5638834 +579,insert,900.846,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1310.81,2.78368,1666,6229778 +580,search,5952.23,3379.39,2460.87,0.971077,212.444,-nan,-nan,0.91028,0.114994,-1.0,-1.0,115.477,2.78475,1677,6229778 +581,insert,37.508,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,124.567,2.79862,1688,6261240 +582,search,5928.85,3360.16,2386.01,1.01233,197.431,-nan,-nan,0.91084,0.114296,-1.0,-1.0,34.41,2.79881,1690,6261240 +583,insert,22.512,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,70.918,2.80726,1697,6283315 +584,search,5830.85,3352.92,2296.07,1.08079,180.087,-nan,-nan,0.9109,0.114436,-1.0,-1.0,17.972,2.80726,1697,6283315 +585,insert,329.787,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,460.616,2.93446,1745,6556101 +586,search,5975.41,3390.03,2345.48,1.15426,186.188,-nan,-nan,0.91283,0.113298,-1.0,-1.0,194.012,2.93545,1760,6556101 +587,insert,43.596,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,84.259,2.94832,1767,6587187 +588,search,6189.66,3369.84,2481.64,1.11263,205.25,-nan,-nan,0.91392,0.112172,-1.0,-1.0,102.453,2.94895,1773,6587187 +589,insert,70.808,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,106.136,2.9642,1784,6631526 +590,search,6235.95,3374.71,2524.44,1.03605,207.71,-nan,-nan,0.91493,0.111587,-1.0,-1.0,39.976,2.96468,1786,6631526 +591,insert,619.54,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,825.27,3.169,1900,7108942 +592,search,6860.39,3432.2,2844.45,0.978448,256.884,-nan,-nan,0.91833,0.109222,-1.0,-1.0,164.665,3.17039,1916,7108942 +593,insert,228.255,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,390.544,3.25949,1963,7303976 +594,search,6944.78,3413.71,2829.1,0.99703,240.36,-nan,-nan,0.91972,0.10805,-1.0,-1.0,143.167,3.26063,1976,7303976 +595,insert,7.101,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,29.081,3.26233,1977,7309244 +596,search,7057.96,3391.68,2893.1,0.987915,250.881,-nan,-nan,0.92012,0.107618,-1.0,-1.0,38.715,3.26233,1978,7309244 +597,insert,304.404,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,416.297,3.36515,2027,7542477 +598,search,7112.32,3425.37,2876.5,1.06623,231.551,-nan,-nan,0.92199,0.106785,-1.0,-1.0,155.955,3.36654,2042,7542477 +599,insert,130.077,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,243.829,3.40933,2074,7654438 +600,search,7368.8,3400.67,3038.21,1.01773,251.933,-nan,-nan,0.9229,0.105691,-1.0,-1.0,88.494,3.41035,2082,7654438 +601,insert,72.207,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,135.976,3.43559,2095,7717936 +602,search,7484.03,3398.54,3082.38,1.02002,262.927,-nan,-nan,0.92345,0.105186,-1.0,-1.0,34.246,3.43574,2096,7717936 +603,insert,6.037,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,23.969,3.43695,2096,7723521 +604,search,7479.2,3398.94,3072.33,0.994627,267.403,-nan,-nan,0.92339,0.10521,-1.0,-1.0,25.177,3.43695,2096,7723521 +605,insert,57.693,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,116.951,3.45443,2107,7767404 +606,search,7394.06,3401.95,2996.95,1.03639,251.806,-nan,-nan,0.92333,0.105209,-1.0,-1.0,34.744,3.45458,2108,7767404 +607,insert,75.178,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,98.384,3.47741,2116,7826115 +608,search,7405.31,3396.42,2954.42,1.054,243.185,-nan,-nan,0.92321,0.105528,-1.0,-1.0,79.2,3.47769,2120,7826115 +609,insert,271.138,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,446.532,3.56683,2167,8036351 +610,search,7557.89,3406.32,3029.97,1.04163,247.868,-nan,-nan,0.92464,0.104993,-1.0,-1.0,93.147,3.56779,2174,8036351 +611,insert,29.179,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,83.326,3.57947,2181,8060364 +612,search,7629.76,3392.42,3075.56,1.02489,256.806,-nan,-nan,0.92489,0.104812,-1.0,-1.0,27.882,3.57947,2181,8060364 +613,insert,270.252,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,356.913,3.66311,2224,8256083 +614,search,7864.04,3396.81,3187.28,1.03013,278.148,-nan,-nan,0.92604,0.103572,-1.0,-1.0,57.193,3.66347,2227,8256083 +615,insert,437.186,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,747.545,3.83333,2293,8625707 +616,search,8185.18,3431.75,3370.12,0.949369,296.404,-nan,-nan,0.92716,0.103087,-1.0,-1.0,310.996,3.83597,2325,8625707 +617,insert,380.581,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,553.971,3.98193,2378,8949227 +618,search,8440.64,3433.68,3501.36,0.980651,297.404,-nan,-nan,0.92936,0.101058,-1.0,-1.0,277.79,3.9845,2402,8949227 +619,insert,288.027,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,343.682,4.08898,2442,9195551 +620,search,8422.47,3416.82,3401.68,1.05564,275.991,-nan,-nan,0.9308,0.0995509,-1.0,-1.0,212.503,4.09092,2463,9195551 +621,insert,48.835,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,63.312,4.10604,2469,9232372 +622,search,8635.16,3390.19,3510.21,1.03918,300.489,-nan,-nan,0.93137,0.0992954,-1.0,-1.0,45.854,4.10606,2471,9232372 +623,insert,25.883,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,71.2,4.11611,2478,9253561 +624,search,8379.65,3389.62,3274.55,1.15119,254.579,-nan,-nan,0.93156,0.0991336,-1.0,-1.0,28.101,4.11611,2479,9253561 +625,insert,93.518,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,150.526,4.14864,2494,9331230 +626,search,8680.24,3394.48,3511.51,1.03662,290.501,-nan,-nan,0.9322,0.0989088,-1.0,-1.0,73.342,4.14976,2500,9331230 +627,insert,53.835,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,111.593,4.16488,2512,9374063 +628,search,8422.11,3382.24,3258.68,1.16954,254.378,-nan,-nan,0.93231,0.0988375,-1.0,-1.0,23.056,4.16488,2512,9374063 +629,insert,32.255,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,21.268,4.17004,2512,9387598 +630,search,8355.27,3384.62,3194.67,1.19213,248.355,-nan,-nan,0.93234,0.0987269,-1.0,-1.0,33.404,4.17021,2513,9387598 +631,insert,70.921,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,75.504,4.18289,2518,9421724 +632,search,8767.78,3383.05,3557.98,1.03513,298.054,-nan,-nan,0.93234,0.098514,-1.0,-1.0,22.658,4.18289,2518,9421724 +633,insert,72.156,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,185.56,4.19932,2538,9461430 +634,search,8852.32,3368.18,3585.05,1.01169,302.96,-nan,-nan,0.93258,0.0981939,-1.0,-1.0,31.761,4.19956,2539,9461430 +635,insert,34.762,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,94.519,4.20633,2547,9479469 +636,search,8863.05,3366.2,3571.39,1.01465,299.804,-nan,-nan,0.93268,0.0981267,-1.0,-1.0,71.728,4.207,2552,9479469 +637,insert,605.325,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,840.918,4.39152,2648,9885997 +638,search,9251.6,3390.96,3756.86,1.02509,323.25,-nan,-nan,0.93473,0.0964742,-1.0,-1.0,236.327,4.39492,2671,9885997 +639,insert,545.018,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,720.892,4.57457,2763,10292043 +640,search,9643.52,3394.03,3931.56,1.00383,326.756,-nan,-nan,0.93719,0.0943849,-1.0,-1.0,168.365,4.57611,2779,10292043 +641,delete,217.226,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1740.63,4.49003,2718,10096584 +642,search,9377.67,3392.37,3762.58,1.07128,312.828,-nan,-nan,0.93683,0.0944116,-1.0,-1.0,226.354,4.49376,2736,10096584 +643,delete,12.154,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,54.925,4.49178,2735,10084840 +644,search,9401.01,3371.73,3767.73,1.03905,306.244,-nan,-nan,0.93666,0.0945367,-1.0,-1.0,44.383,4.49213,2736,10084840 +645,delete,33.205,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,53.037,4.49054,2734,10069802 +646,search,9489.92,3365.9,3823.84,1.05023,320.287,-nan,-nan,0.93665,0.0945439,-1.0,-1.0,31.497,4.49054,2734,10069802 +647,delete,125.673,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,771.14,4.44745,2697,9990953 +648,search,9417.47,3383.93,3816.01,1.0328,328.74,-nan,-nan,0.93615,0.0945666,-1.0,-1.0,155.409,4.44985,2709,9990953 +649,delete,46.864,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,173.907,4.44212,2703,9951625 +650,search,9397.92,3363.22,3792.73,1.01509,316.06,-nan,-nan,0.9362,0.0947268,-1.0,-1.0,69.379,4.44301,2707,9951625 +651,delete,32.152,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,179.941,4.4345,2700,9927065 +652,search,9498.17,3360.99,3870.14,0.980789,341.515,-nan,-nan,0.93625,0.0945808,-1.0,-1.0,46.234,4.43475,2702,9927065 +653,delete,118.44,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,695.537,4.38775,2667,9831098 +654,search,9304.99,3365.77,3769.85,1.0136,316.621,-nan,-nan,0.93543,0.094733,-1.0,-1.0,69.512,4.38836,2672,9831098 +655,delete,458.387,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,2558.28,4.22336,2523,9462172 +656,search,8839.01,3415.62,3591.75,1.00864,303.996,-nan,-nan,0.93307,0.0976823,-1.0,-1.0,353.088,4.23039,2561,9462172 +657,delete,225.258,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,677.84,4.14442,2471,9218902 +658,search,8593.07,3390.12,3464.31,1.01145,289.925,-nan,-nan,0.92907,0.100434,-1.0,-1.0,269.345,4.14816,2488,9218902 +659,delete,133.714,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,681.177,4.09054,2445,9106546 +660,search,8544.22,3378.65,3451.66,1.04905,280.053,-nan,-nan,0.92917,0.10023,-1.0,-1.0,95.461,4.09148,2451,9106546 +661,delete,68.513,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,296.972,4.07934,2444,9059776 +662,search,8620.21,3359.79,3510.96,0.965679,302.513,-nan,-nan,0.92888,0.100503,-1.0,-1.0,58.081,4.07956,2446,9059776 +663,delete,111.585,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,405.993,4.05122,2426,8990616 +664,search,8468.37,3359.41,3416.48,1.0302,285.986,-nan,-nan,0.92799,0.101306,-1.0,-1.0,58.898,4.05212,2429,8990616 +665,delete,65.014,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,303.738,4.03051,2416,8937437 +666,search,8400.73,3352.02,3375.13,1.02591,286.161,-nan,-nan,0.92798,0.101167,-1.0,-1.0,46.487,4.03082,2418,8937437 +667,delete,228.473,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1263.56,3.9438,2348,8766390 +668,search,8333.67,3375.78,3391.66,1.00725,292.279,-nan,-nan,0.92705,0.102075,-1.0,-1.0,171.055,3.94559,2360,8766390 +669,delete,275.38,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,2206.27,3.83523,2246,8532008 +670,search,7961.73,3435.05,3225.82,1.00984,273.054,-nan,-nan,0.92679,0.102386,-1.0,-1.0,380.893,3.84055,2281,8532008 +671,delete,44.608,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,185.425,3.82601,2272,8489178 +672,search,7937.34,3366.96,3186.29,1.05428,263.067,-nan,-nan,0.92652,0.102867,-1.0,-1.0,86.931,3.82634,2277,8489178 +673,delete,75.685,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,311.636,3.79704,2260,8421866 +674,search,7990.98,3357.43,3254.76,1.03803,278.263,-nan,-nan,0.9261,0.103015,-1.0,-1.0,60.65,3.79743,2262,8421866 +675,delete,192.067,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,662.948,3.75169,2226,8288319 +676,search,7522.12,3345.48,2889.76,1.16857,226.402,-nan,-nan,0.92577,0.10336,-1.0,-1.0,84.953,3.75243,2230,8288319 +677,delete,252.19,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,627.197,3.65635,2190,8072197 +678,search,7410.05,3327.53,2860.25,1.14915,227.501,-nan,-nan,0.9279,0.100827,-1.0,-1.0,71.629,3.65676,2193,8072197 +679,delete,39.528,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,359.218,3.63962,2181,8036947 +680,search,7510.31,3328.89,2959.25,1.06954,240.017,-nan,-nan,0.92787,0.10129,-1.0,-1.0,78.922,3.64033,2185,8036947 +681,delete,13.097,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,29.487,3.64033,2185,8026197 +682,search,7599.25,3319.61,3026.86,1.01762,255.01,-nan,-nan,0.92795,0.101076,-1.0,-1.0,31.792,3.64033,2185,8026197 +683,delete,370.667,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1764.57,3.51909,2077,7744229 +684,search,7321.34,3368.61,2956.8,1.01429,245.505,-nan,-nan,0.9268,0.102899,-1.0,-1.0,326.902,3.52354,2109,7744229 +685,delete,256.437,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1372.58,3.427,2014,7541066 +686,search,7173.83,3372.2,2941.73,0.978156,259.156,-nan,-nan,0.92398,0.105788,-1.0,-1.0,337.2,3.43405,2048,7541066 +687,delete,16.511,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,96.442,3.42806,2045,7522190 +688,search,7177.82,3304.04,2907.25,0.966255,246.539,-nan,-nan,0.92385,0.105495,-1.0,-1.0,54.573,3.42877,2047,7522190 +689,delete,146.113,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,550.021,3.36936,2015,7409400 +690,search,7097.22,3322.05,2875.33,0.977189,247.268,-nan,-nan,0.92286,0.106038,-1.0,-1.0,137.737,3.37085,2025,7409400 +691,delete,39.316,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,176.411,3.36071,2016,7375648 +692,search,7071.05,3299.56,2856.72,1.00735,238.646,-nan,-nan,0.92313,0.106055,-1.0,-1.0,29.557,3.36071,2016,7375648 +693,delete,252.394,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,570.051,3.29276,1984,7222068 +694,search,6892.57,3299.73,2736.12,1.05888,226.313,-nan,-nan,0.92327,0.105381,-1.0,-1.0,94.898,3.29391,1989,7222068 +695,delete,33.613,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,174.347,3.2818,1983,7196331 +696,search,6767.67,3295.3,2621.37,1.08934,213.826,-nan,-nan,0.92389,0.104669,-1.0,-1.0,65.21,3.28208,1986,7196331 +697,delete,41.729,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,159.176,3.27279,1980,7170716 +698,search,6897.05,3287.08,2740.17,1.02796,241.945,-nan,-nan,0.92427,0.104561,-1.0,-1.0,43.665,3.27296,1981,7170716 +699,delete,14.931,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,106.808,3.26309,1977,7155255 +700,search,6980.45,3288.01,2815.74,0.981928,251.196,-nan,-nan,0.92437,0.104175,-1.0,-1.0,28.678,3.26309,1977,7155255 +701,delete,73.129,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,120.246,3.25613,1971,7097733 +702,search,6900.75,3267.08,2779.14,0.967854,236.275,-nan,-nan,0.92396,0.104321,-1.0,-1.0,38.835,3.25628,1972,7097733 +703,delete,262.025,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,863.002,3.16736,1908,6924172 +704,search,6708.59,3293.71,2711.07,0.977221,231.803,-nan,-nan,0.92503,0.103516,-1.0,-1.0,128.838,3.16968,1916,6924172 +705,delete,31.046,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,126.337,3.16092,1909,6896276 +706,search,6597.22,3272.53,2607.84,1.04195,214.951,-nan,-nan,0.92468,0.103947,-1.0,-1.0,63.785,3.16142,1912,6896276 +707,delete,744.621,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,3503.36,2.87542,1634,6385507 +708,search,6001.17,3605.73,2553.05,0.966578,226.748,-nan,-nan,0.92238,0.107083,-1.0,-1.0,947.067,2.89213,1745,6385507 +709,delete,170.467,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,976.428,2.80059,1666,6207658 +710,search,5829.21,3356.24,2379.51,0.981776,200.246,-nan,-nan,0.91891,0.110359,-1.0,-1.0,306.113,2.80658,1700,6207658 +711,delete,44.865,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,295.012,2.78662,1686,6162720 +712,search,5897.94,3271.3,2397.77,0.970162,211.238,-nan,-nan,0.91787,0.111736,-1.0,-1.0,92.265,2.78781,1693,6162720 +713,delete,277.191,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1112.59,2.67537,1620,5927803 +714,search,5660.5,3290.83,2291.38,0.951273,195.629,-nan,-nan,0.91457,0.11458,-1.0,-1.0,158.242,2.67827,1633,5927803 +715,delete,30.077,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,133.673,2.6682,1625,5895666 +716,search,5667.22,3266.18,2249.26,1.02081,186.121,-nan,-nan,0.91497,0.114449,-1.0,-1.0,66.037,2.66854,1628,5895666 +717,delete,39.545,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,111.692,2.66148,1620,5868774 +718,search,5679.01,3258.26,2270.17,0.970395,196.108,-nan,-nan,0.91433,0.114956,-1.0,-1.0,58.179,2.66184,1623,5868774 +719,delete,494.825,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1800.9,2.49643,1455,5533540 +720,search,5054.81,3450.22,1998.89,1.10047,160.222,-nan,-nan,0.9086,0.117956,-1.0,-1.0,464.131,2.50526,1500,5533540 +721,delete,116.021,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,359.278,2.45861,1472,5418387 +722,search,5084.31,3302.46,1986.54,1.05529,163.748,-nan,-nan,0.9073,0.119204,-1.0,-1.0,207.064,2.46055,1486,5418387 +723,delete,23.788,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,81.586,2.4524,1481,5398291 +724,search,5098.18,3255.6,1997.12,1.09117,162.876,-nan,-nan,0.90671,0.119615,-1.0,-1.0,101.736,2.45248,1486,5398291 +725,delete,143.506,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,614.725,2.39444,1441,5273546 +726,search,4986.1,3257.5,2004.26,1.02883,169.734,-nan,-nan,0.90472,0.120844,-1.0,-1.0,201.575,2.39666,1456,5273546 +727,delete,105.531,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,628.509,2.35451,1408,5180937 +728,search,4876.57,3298.82,1939.57,1.01924,159.068,-nan,-nan,0.90558,0.11977,-1.0,-1.0,230.307,2.3578,1431,5180937 +729,delete,125.681,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,361.743,2.31195,1393,5079524 +730,search,4857.58,3237.91,1936.95,0.987534,166.544,-nan,-nan,0.90402,0.120692,-1.0,-1.0,85.552,2.31326,1400,5079524 +731,delete,70.586,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,220.263,2.29488,1383,5019265 +732,search,4834.02,3209.31,1920.48,0.999853,160.468,-nan,-nan,0.90345,0.120935,-1.0,-1.0,17.825,2.29488,1383,5019265 +733,delete,85.395,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,146.687,2.27474,1372,4955565 +734,search,4741.11,3182.31,1849.57,1.06009,154.399,-nan,-nan,0.90306,0.121451,-1.0,-1.0,38.685,2.27495,1374,4955565 +735,delete,217.234,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,556.281,2.19118,1331,4776948 +736,search,4680.31,3248.66,1898.49,0.974024,165.98,-nan,-nan,0.90777,0.116387,-1.0,-1.0,180.024,2.19424,1345,4776948 +737,delete,137.242,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,543.34,2.13766,1309,4654026 +738,search,4573.86,3191.35,1799.35,1.02143,154.393,-nan,-nan,0.90618,0.118516,-1.0,-1.0,73.695,2.13844,1315,4654026 +739,delete,76.221,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,353.704,2.10531,1291,4589888 +740,search,4427.61,3187.62,1745.75,1.01142,150.139,-nan,-nan,0.90471,0.119573,-1.0,-1.0,120.913,2.10662,1301,4589888 +741,delete,201.927,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,625.662,2.03192,1251,4430862 +742,search,4354.65,3178.63,1743.74,0.986245,155.012,-nan,-nan,0.90435,0.119953,-1.0,-1.0,130.574,2.03325,1262,4430862 +743,delete,237.226,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1147.81,1.92896,1182,4237049 +744,search,4075.9,3232.63,1614.86,1.00034,136.135,-nan,-nan,0.90152,0.12188,-1.0,-1.0,315.401,1.93614,1205,4237049 +745,delete,283.834,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1065.39,1.80794,1109,4000195 +746,search,3949.85,3295.59,1610.46,0.994881,145.458,-nan,-nan,0.89784,0.124382,-1.0,-1.0,236.872,1.81028,1129,4000195 +747,delete,196.746,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,905.321,1.71548,1064,3803954 +748,search,3791.67,3292.46,1542.51,0.957701,139.552,-nan,-nan,0.89485,0.126324,-1.0,-1.0,271.976,1.71989,1084,3803954 +749,delete,93.572,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,234.882,1.69194,1063,3733214 +750,search,3762.39,3234.82,1524.33,0.990288,133.326,-nan,-nan,0.89382,0.127438,-1.0,-1.0,20.038,1.69194,1063,3733214 +751,delete,35.552,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,118.328,1.68117,1053,3709324 +752,search,3744.52,3241.97,1518.89,1.00569,134.335,-nan,-nan,0.89291,0.128198,-1.0,-1.0,43.782,1.68157,1055,3709324 +753,delete,89.886,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,288.419,1.65218,1028,3649123 +754,search,3650.7,3257.98,1470.48,0.96927,128.833,-nan,-nan,0.89089,0.130356,-1.0,-1.0,71.324,1.65262,1030,3649123 +755,delete,36.104,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,61.275,1.64663,1026,3621475 +756,search,3650.64,3234.64,1475.6,0.947094,128.201,-nan,-nan,0.89059,0.130666,-1.0,-1.0,64.476,1.64685,1029,3621475 +757,delete,35.611,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,109.448,1.63548,1022,3594479 +758,search,3579.5,3229.44,1407.15,1.04619,118.884,-nan,-nan,0.89108,0.130296,-1.0,-1.0,47.088,1.63576,1024,3594479 +759,delete,30.82,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,122.488,1.62239,1016,3569055 +760,search,3653.78,3233.58,1477.48,0.952223,133.08,-nan,-nan,0.89086,0.130192,-1.0,-1.0,46.17,1.62267,1018,3569055 +761,delete,61.047,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,164.095,1.60692,1005,3527896 +762,search,3583.75,3225.76,1447.02,0.964125,128.226,-nan,-nan,0.88963,0.130938,-1.0,-1.0,17.64,1.60692,1005,3527896 +763,delete,26.763,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,83.98,1.60133,1000,3509970 +764,search,3480.78,3226,1351.92,1.04954,111.043,-nan,-nan,0.88992,0.130729,-1.0,-1.0,17.698,1.60133,1000,3509970 +765,delete,512.698,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1165.59,1.42944,863,3187549 +766,search,3143.45,3453.46,1288,1.01697,117.239,-nan,-nan,0.88742,0.130987,-1.0,-1.0,303.647,1.43375,893,3187549 +767,delete,476.465,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1250.19,1.25714,732,2822906 +768,search,2755.54,3551.63,1177.01,0.958107,106.413,-nan,-nan,0.87715,0.13834,-1.0,-1.0,452.244,1.26527,774,2822906 +769,insert,14.994,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,28.433,1.26839,776,2832899 +770,search,2762.04,3355.3,1113.59,1.03477,95.2523,-nan,-nan,0.88066,0.135018,-1.0,-1.0,25.479,1.26869,777,2832899 +771,insert,44.273,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,70.416,1.27982,782,2863523 +772,search,2862.77,3363.67,1192.91,0.982495,106.549,-nan,-nan,0.88142,0.134414,-1.0,-1.0,37.96,1.28012,784,2863523 +773,insert,102.861,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,116.862,1.30563,794,2925169 +774,search,2920.83,3399.47,1216.71,0.982827,110.738,-nan,-nan,0.88412,0.132438,-1.0,-1.0,51.51,1.30581,798,2925169 +775,insert,64.052,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,84.452,1.32143,803,2961356 +776,search,2951.23,3393.36,1239.86,0.97545,105.567,-nan,-nan,0.88367,0.133157,-1.0,-1.0,13.033,1.32143,803,2961356 +777,insert,65.171,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,119.047,1.3365,815,2998678 +778,search,3031.53,3392.55,1252.87,0.970532,111.003,-nan,-nan,0.88504,0.132724,-1.0,-1.0,22.019,1.33663,816,2998678 +779,insert,25.027,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,30.989,1.34094,818,3011024 +780,search,2914.07,3388.44,1183.1,1.13858,102.139,-nan,-nan,0.88462,0.132934,-1.0,-1.0,12.68,1.34094,818,3011024 +781,insert,11.495,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,34.187,1.34403,820,3019515 +782,search,2987.7,3388.45,1248.84,0.989951,111.058,-nan,-nan,0.88449,0.133066,-1.0,-1.0,12.657,1.34403,820,3019515 +783,insert,113.109,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,180.718,1.3715,838,3082298 +784,search,3087.18,3388.34,1278.74,0.953249,114.33,-nan,-nan,0.88572,0.132061,-1.0,-1.0,12.873,1.3715,838,3082298 +785,insert,62.965,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,99.773,1.38997,846,3122090 +786,search,3114.65,3395.49,1294.22,0.944388,111.683,-nan,-nan,0.88718,0.131237,-1.0,-1.0,30.988,1.39025,848,3122090 +787,insert,41.848,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,72.594,1.40013,855,3140294 +788,search,3108.65,3377.43,1296.19,0.97291,117.7,-nan,-nan,0.88724,0.131215,-1.0,-1.0,13.552,1.40013,855,3140294 +789,insert,11.564,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,23.869,1.40272,856,3147819 +790,search,3102.24,3379.9,1299.73,0.990994,111.301,-nan,-nan,0.88739,0.131289,-1.0,-1.0,13.562,1.40272,856,3147819 +791,insert,59.229,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,94.329,1.41513,865,3180668 +792,search,3076.55,3372.6,1247.68,1.07031,104.348,-nan,-nan,0.88781,0.130877,-1.0,-1.0,14.645,1.41513,865,3180668 +793,insert,7.752,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.448,1.41739,865,3183235 +794,search,3131.31,3374.42,1300.69,0.984249,112.914,-nan,-nan,0.88775,0.130874,-1.0,-1.0,15.03,1.41739,865,3183235 +795,insert,101.02,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,165.564,1.44216,879,3242089 +796,search,3238.92,3390,1345.46,0.941304,118.391,-nan,-nan,0.88832,0.130257,-1.0,-1.0,36.734,1.44265,880,3242089 +797,insert,7.629,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,12.958,1.4442,880,3247192 +798,search,3247.14,3388.46,1350.94,0.966991,121.667,-nan,-nan,0.88845,0.130133,-1.0,-1.0,14,1.4442,880,3247192 +799,insert,12.595,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,12.694,1.44687,880,3254626 +800,search,3224.2,3390.89,1348.78,0.962939,121.835,-nan,-nan,0.88857,0.129976,-1.0,-1.0,13.994,1.44687,880,3254626 +801,insert,33.907,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,64.225,1.45498,884,3274953 +802,search,3235.25,3402.87,1353.13,0.969955,121.187,-nan,-nan,0.88848,0.13011,-1.0,-1.0,13.812,1.45498,884,3274953 +803,insert,1301.39,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1497.01,1.81395,1024,4032688 +804,search,3851.97,3693.89,1673.95,0.94225,149.975,-nan,-nan,0.89663,0.124818,-1.0,-1.0,702.613,1.81702,1100,4032688 +805,insert,25.084,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,47.819,1.82367,1104,4050220 +806,search,3778.67,3409.83,1480.97,1.14869,119.469,-nan,-nan,0.89775,0.123841,-1.0,-1.0,220.979,1.82521,1125,4050220 +807,insert,26.397,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,48.832,1.83371,1128,4067940 +808,search,3865.95,3348.19,1536.44,1.14628,126.917,-nan,-nan,0.89774,0.123994,-1.0,-1.0,25.029,1.83382,1129,4067940 +809,insert,42.909,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,64.909,1.84309,1134,4099369 +810,search,3909.07,3354.33,1552.24,1.07921,129.112,-nan,-nan,0.89835,0.123446,-1.0,-1.0,28.231,1.84351,1135,4099369 +811,insert,53.494,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,75.892,1.85448,1142,4129509 +812,search,4089.42,3363.61,1702.56,0.997582,147.312,-nan,-nan,0.89884,0.122831,-1.0,-1.0,14.115,1.85448,1142,4129509 +813,insert,83.197,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,159.467,1.873,1159,4178669 +814,search,4080.57,3355.35,1657.88,1.03821,141.544,-nan,-nan,0.901,0.121435,-1.0,-1.0,24.523,1.87302,1160,4178669 +815,insert,2.771,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,35.51,1.87397,1162,4180960 +816,search,4099.57,3348.42,1630.85,1.08772,137.791,-nan,-nan,0.90095,0.121555,-1.0,-1.0,14.183,1.87397,1162,4180960 +817,insert,109.501,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,107.168,1.89742,1171,4255359 +818,search,4059.06,3370.19,1611.7,1.09472,133.549,-nan,-nan,0.90156,0.120824,-1.0,-1.0,53.771,1.8983,1175,4255359 +819,insert,27.665,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,65.399,1.9026,1181,4272706 +820,search,4214.72,3351.31,1744.75,0.956053,149.624,-nan,-nan,0.90216,0.120287,-1.0,-1.0,13.607,1.9026,1181,4272706 +821,insert,22.907,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,48.687,1.90888,1184,4287851 +822,search,4214.58,3353.24,1740.58,0.993616,151.39,-nan,-nan,0.9019,0.120437,-1.0,-1.0,24.556,1.90895,1185,4287851 +823,insert,50.887,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,79.122,1.92322,1191,4322788 +824,search,4248.01,3359.57,1762.8,0.949613,156.664,-nan,-nan,0.90179,0.121005,-1.0,-1.0,50.589,1.92382,1195,4322788 +825,insert,126.938,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,166.836,1.95539,1208,4396408 +826,search,4184.7,3359.16,1662.25,1.10836,137.15,-nan,-nan,0.9025,0.119897,-1.0,-1.0,87.671,1.95638,1216,4396408 +827,insert,30.888,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,31.673,1.96368,1218,4415721 +828,search,4167.71,3340.61,1644.54,1.16812,133.735,-nan,-nan,0.90193,0.120169,-1.0,-1.0,23.285,1.96383,1219,4415721 +829,insert,681.591,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,906.233,2.15372,1314,4832079 +830,search,4557.01,3412.8,1802.09,1.14986,148.798,-nan,-nan,0.90589,0.117338,-1.0,-1.0,236.691,2.15552,1337,4832079 +831,insert,44.897,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,101.157,2.16829,1345,4864525 +832,search,4739.6,3348.57,1897.5,1.03549,158.015,-nan,-nan,0.90691,0.116605,-1.0,-1.0,67.116,2.16906,1348,4864525 +833,insert,12.366,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.712,2.17115,1348,4874443 +834,search,4705.02,3350.54,1905.78,1.04607,161,-nan,-nan,0.90686,0.116542,-1.0,-1.0,16.024,2.17115,1348,4874443 +835,insert,107.815,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,142.237,2.19961,1363,4938267 +836,search,4890.78,3369.09,2008.7,0.98171,182.905,-nan,-nan,0.9076,0.11638,-1.0,-1.0,16.824,2.19961,1363,4938267 +837,insert,29.508,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,36.649,2.20659,1365,4961147 +838,search,4848.95,3379.04,1973.45,1.02603,169.769,-nan,-nan,0.90784,0.116248,-1.0,-1.0,31.362,2.20667,1366,4961147 +839,insert,105.339,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,146.531,2.23694,1378,5033740 +840,search,4832.94,3398.08,1947.85,1.0671,165.432,-nan,-nan,0.90887,0.11563,-1.0,-1.0,55.306,2.2374,1381,5033740 +841,insert,63.179,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,71.071,2.2533,1386,5078736 +842,search,5037.19,3407.83,2076.36,1.01233,192.809,-nan,-nan,0.91024,0.114571,-1.0,-1.0,40.696,2.25366,1388,5078736 +843,insert,614.405,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,853.089,2.43534,1489,5467376 +844,search,5361.72,3413.01,2220.49,1.02256,201.879,-nan,-nan,0.91164,0.113533,-1.0,-1.0,305.638,2.43821,1523,5467376 +845,insert,505.48,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,609.737,2.59055,1593,5815547 +846,search,5636.52,3402.83,2304.51,1.00666,198.181,-nan,-nan,0.91476,0.111799,-1.0,-1.0,263.321,2.593,1620,5815547 +847,insert,8.697,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.822,2.59525,1620,5821782 +848,search,5553.14,3350.75,2224.01,1.06381,187.057,-nan,-nan,0.91497,0.111636,-1.0,-1.0,49.629,2.59525,1623,5821782 +849,insert,3.6,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,38.913,2.59617,1625,5825594 +850,search,5790.86,3345.19,2366.53,0.987491,211.604,-nan,-nan,0.91522,0.111476,-1.0,-1.0,25.402,2.5963,1626,5825594 +851,insert,12.687,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,33.98,2.59909,1628,5834880 +852,search,5763.75,3342.62,2359.72,1.00828,204.171,-nan,-nan,0.91513,0.111691,-1.0,-1.0,17.632,2.59909,1628,5834880 +853,insert,47.29,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,49.027,2.60948,1631,5860274 +854,search,5795.25,3348.5,2377.06,0.978885,207.4,-nan,-nan,0.91548,0.111377,-1.0,-1.0,37.186,2.60952,1633,5860274 +855,insert,8.991,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.176,2.61112,1633,5866064 +856,search,5784.22,3348.34,2363.86,1.01217,202.234,-nan,-nan,0.91548,0.111422,-1.0,-1.0,17.484,2.61112,1633,5866064 +857,insert,22.782,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,45.143,2.61504,1636,5884456 +858,search,5632.75,3352.64,2285.37,1.06533,191.616,-nan,-nan,0.91584,0.11113,-1.0,-1.0,31.936,2.61532,1637,5884456 +859,insert,48.415,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,62.079,2.62761,1642,5916786 +860,search,5711.7,3360.52,2283.61,1.10561,188.713,-nan,-nan,0.91589,0.110928,-1.0,-1.0,20.317,2.62761,1642,5916786 +861,insert,15.436,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,36.216,2.629,1644,5923467 +862,search,5885.79,3358.79,2425.81,1.00398,216.466,-nan,-nan,0.91631,0.110563,-1.0,-1.0,31.596,2.62931,1645,5923467 +863,insert,107.17,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,123.235,2.66107,1653,5997844 +864,search,5760.58,3376.34,2315.75,1.04849,195.928,-nan,-nan,0.91512,0.111984,-1.0,-1.0,41.73,2.66122,1655,5997844 +865,insert,19.353,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,68.491,2.66646,1660,6009561 +866,search,5729.56,3369.5,2282.86,1.12699,190.896,-nan,-nan,0.91526,0.111884,-1.0,-1.0,18.672,2.66646,1660,6009561 +867,insert,70.115,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,77.952,2.68242,1666,6052876 +868,search,5770.7,3378.72,2336.38,1.04632,200.368,-nan,-nan,0.91556,0.112026,-1.0,-1.0,31.575,2.68255,1667,6052876 +869,insert,9.94,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.713,2.68506,1667,6059234 +870,search,5848.81,3378.83,2373.92,1.01026,204.667,-nan,-nan,0.91545,0.112149,-1.0,-1.0,18.653,2.68506,1667,6059234 +871,insert,64.829,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,89.489,2.70083,1673,6098225 +872,search,5977.5,3385.32,2460.77,0.986014,211.158,-nan,-nan,0.91558,0.11202,-1.0,-1.0,30.62,2.70116,1674,6098225 +873,insert,61.181,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,79.4,2.7171,1679,6137308 +874,search,5866.11,3390.33,2355.73,1.08059,205.227,-nan,-nan,0.91595,0.11173,-1.0,-1.0,38.395,2.71756,1681,6137308 +875,insert,33.684,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,42.453,2.72506,1683,6154089 +876,search,5960.84,3392.25,2482.83,0.950553,217.145,-nan,-nan,0.91565,0.111954,-1.0,-1.0,18.075,2.72506,1683,6154089 +877,insert,6.115,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.289,2.72606,1683,6156061 +878,search,5841.68,3393.57,2329.03,1.04639,197.031,-nan,-nan,0.91567,0.111948,-1.0,-1.0,17.967,2.72606,1683,6156061 +879,insert,496.619,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,514.082,2.85682,1732,6446004 +880,search,5999.13,3441.6,2444.75,1.08931,202.516,-nan,-nan,0.91792,0.11058,-1.0,-1.0,104.952,2.85787,1743,6446004 +881,insert,731.566,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1007.87,3.09555,1854,6969764 +882,search,6648.51,3484.7,2752.12,0.983634,243.433,-nan,-nan,0.9211,0.108119,-1.0,-1.0,372.6,3.09866,1890,6969764 +883,insert,612.612,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,993.69,3.30536,2022,7422501 +884,search,7244.54,3407.19,2994.15,0.96313,266.475,-nan,-nan,0.92511,0.104812,-1.0,-1.0,388.749,3.31087,2063,7422501 +885,insert,13.955,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,23.501,3.314,2063,7432053 +886,search,7079.91,3350.23,2786.97,1.11692,233.839,-nan,-nan,0.92544,0.10472,-1.0,-1.0,36.672,3.314,2064,7432053 +887,insert,484.294,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,608.347,3.46718,2135,7789886 +888,search,7289.14,3382.4,2868.33,1.154,225.454,-nan,-nan,0.92697,0.103943,-1.0,-1.0,147.622,3.46827,2148,7789886 +889,insert,574.447,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,706.879,3.65351,2229,8210883 +890,search,7864.17,3420.94,3198.08,1.01738,271.133,-nan,-nan,0.9293,0.101619,-1.0,-1.0,396.44,3.65927,2270,8210883 +891,insert,45.816,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,69.179,3.66876,2275,8240504 +892,search,7865.11,3361.56,3139.26,1.07211,260.478,-nan,-nan,0.92974,0.101403,-1.0,-1.0,73.332,3.66937,2281,8240504 +893,insert,68.778,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,142.723,3.691,2297,8299693 +894,search,7933.46,3347.5,3161.2,1.078,262.646,-nan,-nan,0.93005,0.101324,-1.0,-1.0,54.744,3.69149,2299,8299693 +895,insert,60.817,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,126.286,3.71035,2311,8349126 +896,search,7986.36,3351.61,3191.68,1.05947,268.406,-nan,-nan,0.93067,0.100872,-1.0,-1.0,44.684,3.71055,2312,8349126 +897,delete,104.642,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,517.191,3.67584,2290,8268842 +898,search,8095.53,3356.62,3310.94,1.0011,294.054,-nan,-nan,0.93048,0.100984,-1.0,-1.0,80.172,3.67654,2294,8268842 +899,delete,23.026,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,97.596,3.67143,2290,8250527 +900,search,8088.95,3348.46,3289.66,1.0033,294.895,-nan,-nan,0.93032,0.101108,-1.0,-1.0,32.822,3.67143,2290,8250527 +901,delete,88.713,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,180.785,3.65555,2277,8185565 +902,search,7926.17,3335.72,3178.11,1.018,273.346,-nan,-nan,0.92996,0.101202,-1.0,-1.0,46.152,3.65583,2278,8185565 +903,delete,72.058,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,188.194,3.62977,2261,8126915 +904,search,7712.9,3338.46,3022.87,1.09108,253.387,-nan,-nan,0.9288,0.101818,-1.0,-1.0,42.788,3.63001,2262,8126915 +905,delete,37.253,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,175.473,3.62157,2254,8098533 +906,search,7752.76,3333.68,3071.07,1.09429,254.746,-nan,-nan,0.92861,0.101869,-1.0,-1.0,42.105,3.62186,2255,8098533 +907,delete,32.896,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,206.434,3.61227,2248,8074833 +908,search,7765.41,3332.28,3080.55,1.07358,253.248,-nan,-nan,0.92835,0.102139,-1.0,-1.0,73.59,3.61299,2251,8074833 +909,delete,45.427,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,172.834,3.60443,2243,8035274 +910,search,7729.69,3322.04,3058.12,1.06137,252.908,-nan,-nan,0.92837,0.102038,-1.0,-1.0,57.098,3.60502,2246,8035274 +911,delete,89.781,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,282.559,3.58393,2231,7957223 +912,search,7650.27,3299.54,2997.2,1.07702,257.137,-nan,-nan,0.92742,0.103086,-1.0,-1.0,37.145,3.58401,2232,7957223 +913,delete,43.288,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,246.033,3.56557,2217,7917554 +914,search,7207.04,3300.17,2645.12,1.22085,205.708,-nan,-nan,0.92611,0.103897,-1.0,-1.0,82.445,3.56633,2219,7917554 +915,delete,90.482,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,308.365,3.54055,2199,7861503 +916,search,7708.56,3301.61,3105.03,0.999377,262.596,-nan,-nan,0.92528,0.105123,-1.0,-1.0,92.611,3.5415,2203,7861503 +917,delete,28.712,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,104.031,3.53645,2201,7844487 +918,search,7766.26,3291.52,3132.04,0.971795,273.223,-nan,-nan,0.92594,0.104644,-1.0,-1.0,41.669,3.5365,2202,7844487 +919,delete,44.641,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,54.683,3.53466,2201,7814993 +920,search,7740.23,3279.08,3117.05,0.988277,271.883,-nan,-nan,0.92581,0.104982,-1.0,-1.0,40.623,3.53478,2202,7814993 +921,delete,35.528,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,152.989,3.5274,2196,7793855 +922,search,7625.66,3276.71,3038.11,1.04452,258.819,-nan,-nan,0.9257,0.105088,-1.0,-1.0,43.151,3.52767,2197,7793855 +923,delete,77.066,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,254.907,3.50978,2184,7736054 +924,search,7468.39,3265.81,2920.17,1.0491,239.957,-nan,-nan,0.92539,0.105242,-1.0,-1.0,28.886,3.50978,2184,7736054 +925,delete,190.463,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,643.224,3.44041,2134,7587942 +926,search,7294.25,3271.24,2867.31,1.07001,237.844,-nan,-nan,0.92432,0.105719,-1.0,-1.0,70.598,3.44096,2138,7587942 +927,delete,28.837,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,26.325,3.44064,2138,7565670 +928,search,7412.21,3254.09,2953.33,0.989416,250.844,-nan,-nan,0.9244,0.10575,-1.0,-1.0,38.048,3.4409,2139,7565670 +929,delete,44.176,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,125.887,3.43227,2133,7529948 +930,search,7380.03,3244.16,2934.71,0.998844,248.037,-nan,-nan,0.92409,0.106138,-1.0,-1.0,27.288,3.43227,2133,7529948 +931,delete,634.248,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,3986.13,3.16993,1879,7016700 +932,search,6751.51,3418.99,2772.22,1.03015,240.057,-nan,-nan,0.9206,0.108363,-1.0,-1.0,738.719,3.18435,1954,7016700 +933,delete,23.358,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,138.755,3.17094,1946,6980979 +934,search,6834.73,3275.21,2754.7,1.01681,237.356,-nan,-nan,0.92102,0.108352,-1.0,-1.0,203.299,3.1729,1965,6980979 +935,delete,22.238,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,204.474,3.15922,1958,6954250 +936,search,6766.17,3244.51,2657.34,1.06059,227.349,-nan,-nan,0.92117,0.108004,-1.0,-1.0,43.777,3.15967,1959,6954250 +937,delete,39.954,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,123.18,3.15056,1953,6924596 +938,search,6700.77,3238.58,2620.25,1.06239,215.641,-nan,-nan,0.92068,0.108268,-1.0,-1.0,40.644,3.15093,1954,6924596 +939,delete,199.728,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,540.79,3.10958,1917,6784831 +940,search,6559.92,3214.75,2551.27,1.08448,221.45,-nan,-nan,0.92012,0.10926,-1.0,-1.0,86.588,3.11107,1923,6784831 +941,delete,46.643,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,37.35,3.10854,1922,6745819 +942,search,6684.95,3176.96,2650.55,0.996822,229.405,-nan,-nan,0.91965,0.110053,-1.0,-1.0,38.115,3.10882,1923,6745819 +943,delete,4.699,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,40.661,3.1074,1922,6740944 +944,search,6611.42,3175.25,2584.83,1.04811,221.732,-nan,-nan,0.91964,0.109868,-1.0,-1.0,24.323,3.1074,1922,6740944 +945,delete,147.936,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,978.343,3.03585,1862,6627202 +946,search,6144.55,3230.58,2291.76,1.23631,177.558,-nan,-nan,0.91788,0.110923,-1.0,-1.0,214.897,3.0389,1882,6627202 +947,delete,23.337,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,61.138,3.03331,1879,6607194 +948,search,6489.63,3180.61,2590.12,1.00727,226.946,-nan,-nan,0.91817,0.110392,-1.0,-1.0,83.475,3.03414,1885,6607194 +949,delete,59.612,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,202.91,3.01304,1874,6551065 +950,search,6471.01,3162.99,2560.31,0.989248,219.218,-nan,-nan,0.91782,0.11092,-1.0,-1.0,22.85,3.01304,1874,6551065 +951,delete,33.579,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,97.366,2.99414,1866,6506798 +952,search,6308.61,3158.91,2441.06,1.05654,198.817,-nan,-nan,0.91884,0.109499,-1.0,-1.0,54.162,2.99458,1868,6506798 +953,delete,62.696,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,214.154,2.98003,1858,6459301 +954,search,6265.85,3151.06,2433.75,1.06874,202.889,-nan,-nan,0.91869,0.109963,-1.0,-1.0,44.701,2.98054,1860,6459301 +955,delete,20.113,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,39.241,2.97218,1858,6440069 +956,search,6390.03,3145.61,2512.65,1.02672,209.887,-nan,-nan,0.9186,0.109901,-1.0,-1.0,27.455,2.97218,1858,6440069 +957,delete,471.5,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1722.47,2.80886,1732,6132470 +958,search,6058.73,3213.07,2428.84,0.987886,219.1,-nan,-nan,0.91577,0.111885,-1.0,-1.0,287.613,2.8138,1755,6132470 +959,delete,57.105,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,131.973,2.80031,1745,6086241 +960,search,6033.7,3162.71,2395.44,0.974807,208.845,-nan,-nan,0.91507,0.1122,-1.0,-1.0,40.211,2.80059,1747,6086241 +961,delete,31.017,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,71.303,2.79491,1742,6064734 +962,search,5953.07,3156.53,2316.76,1.03617,199.885,-nan,-nan,0.91483,0.112263,-1.0,-1.0,37.209,2.79493,1743,6064734 +963,delete,158.957,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,803.718,2.73135,1684,5967543 +964,search,5866.47,3227.48,2337.33,1.05612,199.252,-nan,-nan,0.91392,0.112172,-1.0,-1.0,156.417,2.73352,1698,5967543 +965,delete,71.227,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,284.876,2.70567,1675,5906381 +966,search,5726.36,3198.16,2238.62,1.02678,190.462,-nan,-nan,0.91365,0.112744,-1.0,-1.0,54.424,2.70647,1679,5906381 +967,delete,63.369,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,274.659,2.67995,1664,5851849 +968,search,5767.01,3184.75,2283.18,0.975996,198.299,-nan,-nan,0.91296,0.112752,-1.0,-1.0,33.229,2.68029,1665,5851849 +969,delete,72.565,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,254.658,2.64938,1648,5783023 +970,search,5639.75,3181.04,2199.45,0.993896,183.641,-nan,-nan,0.91173,0.113852,-1.0,-1.0,20.253,2.64938,1648,5783023 +971,delete,363.463,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1478.54,2.50841,1533,5496517 +972,search,5392.85,3245.65,2162.98,0.999485,185.256,-nan,-nan,0.90956,0.115782,-1.0,-1.0,314.529,2.51411,1563,5496517 +973,delete,281.782,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1412.68,2.38647,1449,5237981 +974,search,4988.4,3275.28,1955.26,1.06035,163.835,-nan,-nan,0.90808,0.117182,-1.0,-1.0,393.706,2.39355,1485,5237981 +975,delete,166.726,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,532.583,2.31706,1419,5099794 +976,search,5020.62,3256.58,2013.08,0.980703,173.531,-nan,-nan,0.90567,0.118244,-1.0,-1.0,154.945,2.31898,1435,5099794 +977,delete,60.957,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,251.464,2.28964,1417,5032210 +978,search,4820.34,3207.75,1890.41,1.04606,157.523,-nan,-nan,0.90445,0.119604,-1.0,-1.0,79.405,2.29075,1423,5032210 +979,delete,11.364,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,31.678,2.28823,1421,5020211 +980,search,4830.54,3193.93,1865.24,1.05948,155.354,-nan,-nan,0.90472,0.119337,-1.0,-1.0,17.147,2.28823,1421,5020211 +981,delete,143.889,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,442.455,2.2294,1384,4902291 +982,search,4859.13,3200.45,1936.65,0.947442,166.108,-nan,-nan,0.90189,0.121428,-1.0,-1.0,49.275,2.22977,1386,4902291 +983,delete,51.288,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,54.39,2.22636,1384,4872577 +984,search,4832.63,3172.09,1908.4,0.981904,166.354,-nan,-nan,0.90177,0.121487,-1.0,-1.0,18.703,2.22636,1384,4872577 +985,delete,52.584,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,117.509,2.21711,1377,4836730 +986,search,4761.18,3157.31,1901.78,0.979139,167.171,-nan,-nan,0.90144,0.121503,-1.0,-1.0,54.161,2.21749,1380,4836730 +987,delete,54.231,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,101.425,2.20708,1372,4797164 +988,search,4769.79,3130.89,1882.33,1.00173,163.966,-nan,-nan,0.90107,0.121988,-1.0,-1.0,17.809,2.20708,1372,4797164 +989,delete,20.718,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,15.263,2.20682,1372,4784789 +990,search,4805.71,3120.6,1892.45,0.979808,163.409,-nan,-nan,0.90102,0.121942,-1.0,-1.0,17.076,2.20682,1372,4784789 +991,delete,107.537,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,451.347,2.16706,1342,4705420 +992,search,4667.93,3181.65,1854.36,0.98716,163.136,-nan,-nan,0.90358,0.120105,-1.0,-1.0,153.76,2.17012,1349,4705420 +993,delete,108.191,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,352.608,2.13383,1326,4621807 +994,search,4457.72,3143.5,1679.52,1.17827,136.231,-nan,-nan,0.90243,0.120421,-1.0,-1.0,113.449,2.13447,1333,4621807 +995,delete,84.258,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,365.114,2.09958,1305,4555849 +996,search,4530.05,3144.65,1803.81,0.993125,164.764,-nan,-nan,0.90129,0.120252,-1.0,-1.0,100.505,2.10018,1313,4555849 +997,delete,34.619,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,174.022,2.0825,1304,4526975 +998,search,4548.43,3121.08,1786.7,0.969827,159.465,-nan,-nan,0.90129,0.120152,-1.0,-1.0,24.721,2.0825,1305,4526975 +999,delete,152.81,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,588.902,2.02119,1260,4408448 +1000,search,4298.02,3140.37,1670.45,1.08036,138.766,-nan,-nan,0.89986,0.121594,-1.0,-1.0,130.056,2.02288,1269,4408448 +1001,delete,147.266,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,574.625,1.96461,1223,4303257 +1002,search,4269.93,3157.01,1699.42,0.96846,148.896,-nan,-nan,0.89822,0.122703,-1.0,-1.0,113.813,1.96626,1230,4303257 +1003,delete,48.4,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,204.819,1.94372,1214,4259551 +1004,search,4215.54,3157.73,1687.02,0.99387,155.443,-nan,-nan,0.89755,0.123073,-1.0,-1.0,45.608,1.94432,1217,4259551 +1005,delete,21.618,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,49.799,1.93998,1213,4241434 +1006,search,4239.33,3142.33,1689.02,0.953466,147.4,-nan,-nan,0.89748,0.122865,-1.0,-1.0,28.943,1.94004,1214,4241434 +1007,delete,237.439,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,852.924,1.8518,1154,4052722 +1008,search,4030.56,3167.05,1606.96,0.951968,148.877,-nan,-nan,0.89389,0.125974,-1.0,-1.0,177.691,1.85428,1167,4052722 +1009,delete,400.833,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1160.72,1.70007,1044,3738432 +1010,search,3730.5,3263.9,1520.88,0.979574,138.27,-nan,-nan,0.89105,0.127954,-1.0,-1.0,299.035,1.70373,1064,3738432 +1011,delete,445.406,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1444.81,1.51,900,3372539 +1012,search,3327.79,3456.31,1394.33,0.994651,129.847,-nan,-nan,0.88827,0.12937,-1.0,-1.0,403.678,1.51753,940,3372539 +1013,delete,8.787,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,23.806,1.51393,937,3361432 +1014,search,3256.11,3274,1288.83,1.09529,109.427,-nan,-nan,0.88819,0.12985,-1.0,-1.0,36.394,1.51405,939,3361432 +1015,delete,322.261,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1038.41,1.38165,829,3091692 +1016,search,2993.93,3436.75,1226.88,0.991675,107.832,-nan,-nan,0.88306,0.133298,-1.0,-1.0,386.46,1.38851,867,3091692 +1017,delete,382.507,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1160.78,1.23177,743,2775418 +1018,search,2708.55,3463.58,1099.85,1.10425,93.5673,-nan,-nan,0.87961,0.136017,-1.0,-1.0,366.919,1.2384,777,2775418 +1019,delete,20.082,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,110.116,1.22983,770,2754073 +1020,search,2802.72,3308.1,1161.96,0.933669,107.287,-nan,-nan,0.87924,0.136131,-1.0,-1.0,88.014,1.23053,776,2754073 +1021,delete,146.755,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,481.99,1.17988,735,2638917 +1022,search,2700.03,3330.63,1121.88,0.977232,105.414,-nan,-nan,0.87781,0.13712,-1.0,-1.0,117.044,1.18209,743,2638917 +1023,delete,110.772,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,277.912,1.14767,706,2556494 +1024,search,2555.4,3358.96,1028.52,1.11012,87.8599,-nan,-nan,0.87566,0.139028,-1.0,-1.0,120.234,1.14931,716,2556494 +1025,insert,48.078,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,107.541,1.16172,725,2594934 +1026,search,2672.78,3334.78,1116.84,0.962735,103.239,-nan,-nan,0.878,0.136862,-1.0,-1.0,46.512,1.16218,727,2594934 +1027,insert,314.266,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,288.17,1.24839,748,2802105 +1028,search,2804.53,3456.45,1179.16,0.935239,110.537,-nan,-nan,0.87726,0.138132,-1.0,-1.0,118.89,1.24842,756,2802105 +1029,insert,644.677,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,855.592,1.43204,842,3203975 +1030,search,3119.26,3570.3,1335.83,0.909046,120.259,-nan,-nan,0.884,0.133913,-1.0,-1.0,256.849,1.43273,859,3203975 +1031,insert,919.918,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1084.81,1.72143,960,3830566 +1032,search,3635.12,3710.88,1585.81,0.953223,138.531,-nan,-nan,0.89287,0.129278,-1.0,-1.0,544.714,1.72385,1000,3830566 +1033,insert,623.51,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,977.758,1.91441,1107,4252669 +1034,search,4098.29,3557.7,1744.19,0.950928,154.621,-nan,-nan,0.89925,0.123747,-1.0,-1.0,567.396,1.91639,1152,4252669 +1035,insert,330.107,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,412.972,2.03014,1190,4512107 +1036,search,4334.61,3460.32,1808.37,0.976492,158.062,-nan,-nan,0.90242,0.121415,-1.0,-1.0,382.037,2.03363,1223,4512107 +1037,insert,14.723,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,54.301,2.03758,1227,4525815 +1038,search,4323.72,3379.88,1770.77,1.03449,153.531,-nan,-nan,0.90372,0.120209,-1.0,-1.0,141.452,2.03785,1237,4525815 +1039,insert,117.15,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,268.671,2.0697,1269,4599215 +1040,search,4467.29,3324.04,1832.81,1.02616,158.706,-nan,-nan,0.90466,0.119572,-1.0,-1.0,103.794,2.07041,1277,4599215 +1041,insert,10.635,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,44.047,2.07423,1280,4609851 +1042,search,4542.56,3306.86,1865.76,0.985717,164.639,-nan,-nan,0.9056,0.118971,-1.0,-1.0,41.524,2.07424,1283,4609851 +1043,insert,26.053,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.398,2.07973,1283,4627411 +1044,search,4521.03,3309.33,1859.76,0.998386,163.375,-nan,-nan,0.90545,0.118883,-1.0,-1.0,14.518,2.07973,1283,4627411 +1045,insert,76.058,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,113.83,2.09771,1294,4670607 +1046,search,4470.41,3322.86,1760.49,1.11386,149.885,-nan,-nan,0.90645,0.118526,-1.0,-1.0,23.632,2.09776,1295,4670607 +1047,insert,5.569,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,13.296,2.09877,1295,4675386 +1048,search,4532.04,3323.11,1842.06,1.03616,154.061,-nan,-nan,0.90645,0.118475,-1.0,-1.0,14.467,2.09877,1295,4675386 +1049,insert,25.409,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,33.061,2.10517,1297,4689998 +1050,search,4579.26,3325.71,1879.13,1.00104,160.24,-nan,-nan,0.90646,0.118473,-1.0,-1.0,35.231,2.10554,1298,4689998 +1051,insert,148.476,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,221.12,2.1459,1325,4783971 +1052,search,4692.87,3326.01,1926.63,1.00946,167.128,-nan,-nan,0.90701,0.117628,-1.0,-1.0,26.734,2.1459,1326,4783971 +1053,insert,52.123,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,116.684,2.16112,1338,4826219 +1054,search,4661.39,3324.66,1864.58,1.07285,160.395,-nan,-nan,0.90748,0.117385,-1.0,-1.0,54.978,2.16135,1341,4826219 +1055,insert,48.768,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,95.967,2.17394,1349,4862355 +1056,search,4618.08,3326.04,1783.22,1.07254,145.838,-nan,-nan,0.90785,0.117274,-1.0,-1.0,16,2.17394,1349,4862355 +1057,insert,7.426,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,52.033,2.17588,1353,4869564 +1058,search,4795.39,3317.6,1968.05,0.97857,175.275,-nan,-nan,0.90805,0.117261,-1.0,-1.0,29.015,2.176,1354,4869564 +1059,insert,46.363,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,57.568,2.18759,1359,4898570 +1060,search,4828.7,3324.9,1988.06,0.990374,175.473,-nan,-nan,0.90829,0.117018,-1.0,-1.0,23.836,2.1876,1360,4898570 +1061,insert,10.147,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,44.294,2.18975,1364,4907501 +1062,search,4773.58,3308.95,1913.87,1.05521,168.738,-nan,-nan,0.90783,0.117346,-1.0,-1.0,16.442,2.18975,1364,4907501 +1063,insert,12.151,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,27.657,2.19289,1365,4916386 +1064,search,4739.68,3311.56,1895.35,1.1427,159.251,-nan,-nan,0.90798,0.117489,-1.0,-1.0,15.971,2.19289,1365,4916386 +1065,insert,444.241,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,577.71,2.31464,1420,5194839 +1066,search,4944.97,3359.49,2001.48,1.05795,170.613,-nan,-nan,0.90932,0.116905,-1.0,-1.0,154.424,2.31579,1430,5194839 +1067,insert,8.921,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,41.023,2.31791,1433,5200182 +1068,search,4961.17,3331.59,1976.41,1.07842,165.293,-nan,-nan,0.90949,0.116802,-1.0,-1.0,86.149,2.31829,1438,5200182 +1069,insert,61.758,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,94.61,2.33325,1449,5230883 +1070,search,5099.12,3310.45,2093.4,1.0162,192.135,-nan,-nan,0.90989,0.116243,-1.0,-1.0,56.458,2.33363,1452,5230883 +1071,insert,39.564,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,36.282,2.3437,1454,5255659 +1072,search,5049.64,3312.63,2025.16,1.0514,175.539,-nan,-nan,0.91006,0.11625,-1.0,-1.0,16.289,2.3437,1454,5255659 +1073,insert,51.797,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,101.323,2.35512,1463,5281693 +1074,search,5006.06,3309.14,1963.72,1.04027,159.591,-nan,-nan,0.91036,0.116023,-1.0,-1.0,31.482,2.35527,1464,5281693 +1075,insert,13.166,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,48.938,2.35744,1468,5290081 +1076,search,5097.87,3304.06,2025.63,1.05547,176.79,-nan,-nan,0.91085,0.115649,-1.0,-1.0,23.845,2.35759,1469,5290081 +1077,insert,47.467,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,69.261,2.3691,1475,5316166 +1078,search,4906.83,3295.71,1882.89,1.21724,148.633,-nan,-nan,0.91078,0.115674,-1.0,-1.0,16.023,2.3691,1475,5316166 +1079,insert,39.567,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,63.614,2.37707,1481,5335531 +1080,search,4923.31,3295.04,1905.25,1.14123,152.212,-nan,-nan,0.91103,0.115809,-1.0,-1.0,40.06,2.37719,1483,5335531 +1081,insert,608.642,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,611.872,2.52933,1554,5678781 +1082,search,5516.94,3337.33,2250.01,0.997154,189.884,-nan,-nan,0.91258,0.114523,-1.0,-1.0,103.887,2.53052,1562,5678781 +1083,insert,0.769,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,15.664,2.53052,1562,5679848 +1084,search,5510.45,3326.41,2256.97,0.981054,202.607,-nan,-nan,0.9126,0.114631,-1.0,-1.0,16.511,2.53052,1562,5679848 +1085,insert,30.65,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,76.03,2.53931,1569,5702205 +1086,search,5361.33,3322.77,2125.22,1.07094,176.019,-nan,-nan,0.91299,0.114292,-1.0,-1.0,38.613,2.53976,1570,5702205 +1087,insert,24.131,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,68.953,2.54491,1575,5715514 +1088,search,5595.16,3319.28,2279.8,0.970465,206.337,-nan,-nan,0.91329,0.113853,-1.0,-1.0,17.817,2.54491,1575,5715514 +1089,insert,667.81,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,864.758,2.71515,1687,6103499 +1090,search,5814.67,3328.28,2327.59,1.07773,193.562,-nan,-nan,0.91638,0.111713,-1.0,-1.0,192.262,2.71749,1706,6103499 +1091,insert,80.521,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,116.452,2.73889,1720,6152505 +1092,search,5963.84,3296.27,2376.48,1.09394,200.905,-nan,-nan,0.91722,0.111277,-1.0,-1.0,19.521,2.73889,1720,6152505 +1093,insert,32.638,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,42.474,2.74849,1723,6171104 +1094,search,6024.88,3300.12,2421.68,1.04119,208.539,-nan,-nan,0.91762,0.110904,-1.0,-1.0,40.936,2.74895,1725,6171104 +1095,insert,572.161,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,692.198,2.92012,1804,6557850 +1096,search,6272.3,3346.91,2530.14,1.01769,213.645,-nan,-nan,0.91929,0.109913,-1.0,-1.0,221.078,2.92157,1822,6557850 +1097,insert,28.058,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,33.77,2.92859,1824,6579289 +1098,search,6299.03,3323.67,2509.57,1.06264,203.352,-nan,-nan,0.91982,0.109329,-1.0,-1.0,87.855,2.9292,1831,6579289 +1099,insert,19.301,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,58.169,2.93447,1836,6591442 +1100,search,6593.83,3304.5,2583.93,1.03641,220.575,-nan,-nan,0.92,0.109339,-1.0,-1.0,37.863,2.93477,1838,6591442 +1101,insert,62.733,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,132.143,2.95365,1852,6633739 +1102,search,6684.37,3302.49,2647.84,0.986209,225.982,-nan,-nan,0.92077,0.108636,-1.0,-1.0,46.225,2.95406,1855,6633739 +1103,insert,122.51,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,249.702,2.99537,1884,6724357 +1104,search,6709.13,3298.29,2591.52,1.09112,215.645,-nan,-nan,0.92167,0.10802,-1.0,-1.0,66.194,2.99557,1889,6724357 +1105,insert,2.923,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,20.83,2.99617,1889,6727059 +1106,search,6812.29,3288.67,2679.29,0.968912,225.843,-nan,-nan,0.92176,0.107995,-1.0,-1.0,21.956,2.99617,1889,6727059 +1107,insert,319.029,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,485.575,3.0967,1946,6950869 +1108,search,6878.34,3281.28,2646.22,1.09247,219.76,-nan,-nan,0.92238,0.107373,-1.0,-1.0,81.897,3.09697,1949,6950869 +1109,insert,9.217,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.885,3.09899,1949,6958173 +1110,search,6929.42,3281.37,2661.75,1.0485,223.111,-nan,-nan,0.92229,0.107424,-1.0,-1.0,25.024,3.09899,1949,6958173 +1111,insert,99.069,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,105.408,3.1151,1959,6995273 +1112,search,7120.23,3284.26,2800.23,0.976731,254.32,-nan,-nan,0.92241,0.107396,-1.0,-1.0,58.425,3.11591,1962,6995273 +1113,insert,75.696,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,76.863,3.13403,1969,7047862 +1114,search,7135.95,3295.47,2811.39,1.00545,250.609,-nan,-nan,0.92243,0.107274,-1.0,-1.0,24.235,3.13403,1969,7047862 +1115,insert,95.421,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,149.148,3.15923,1984,7110727 +1116,search,7156.6,3301.29,2824.64,1.0136,247.969,-nan,-nan,0.92281,0.106985,-1.0,-1.0,37.233,3.15941,1985,7110727 +1117,insert,21.503,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,30.346,3.16397,1986,7125591 +1118,search,7224.79,3307.18,2848.59,0.990331,259.919,-nan,-nan,0.92315,0.106694,-1.0,-1.0,48.299,3.16421,1988,7125591 +1119,insert,14.116,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,41.78,3.16724,1990,7134442 +1120,search,7089.19,3305.56,2749.74,1.0436,229.596,-nan,-nan,0.92307,0.106772,-1.0,-1.0,23.52,3.16724,1990,7134442 +1121,insert,37.822,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,59.999,3.17599,1993,7162109 +1122,search,7173.12,3311.51,2806.26,1.00045,239.63,-nan,-nan,0.92324,0.106748,-1.0,-1.0,72.569,3.17645,1998,7162109 +1123,insert,21.951,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,47.038,3.18172,2001,7179509 +1124,search,7185.18,3303.15,2809.41,1.03446,242.301,-nan,-nan,0.92329,0.106823,-1.0,-1.0,34.194,3.18194,2002,7179509 +1125,insert,11.138,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,44.157,3.1845,2003,7186372 +1126,search,7095.2,3303.67,2734.69,1.04877,226.589,-nan,-nan,0.92326,0.106876,-1.0,-1.0,23.988,3.1845,2003,7186372 +1127,insert,67.984,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,117.111,3.20323,2012,7231450 +1128,search,7211.26,3304.55,2810.83,1.01033,237.144,-nan,-nan,0.92328,0.106847,-1.0,-1.0,27.184,3.20323,2012,7231450 +1129,insert,26.685,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,32.604,3.20896,2013,7243215 +1130,search,7281.47,3307.47,2863.29,0.9685,250.935,-nan,-nan,0.92314,0.106861,-1.0,-1.0,27.978,3.20896,2013,7243215 +1131,insert,86.453,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,112.221,3.22169,2021,7276107 +1132,search,7330.66,3306.98,2895.27,0.939648,256.402,-nan,-nan,0.92317,0.106767,-1.0,-1.0,59.215,3.22227,2023,7276107 +1133,insert,42.902,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,42.434,3.23004,2025,7292577 +1134,search,7362.35,3308.85,2910.49,0.971741,264.361,-nan,-nan,0.9235,0.106331,-1.0,-1.0,36.105,3.23005,2026,7292577 +1135,insert,12.942,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,40.981,3.23282,2027,7299867 +1136,search,7174.89,3308.17,2794.28,1.04683,236.803,-nan,-nan,0.92344,0.106411,-1.0,-1.0,25.02,3.23282,2027,7299867 +1137,insert,48.469,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,62.128,3.24199,2031,7323342 +1138,search,7223.88,3312.61,2801.57,1.0075,235.056,-nan,-nan,0.92359,0.106196,-1.0,-1.0,26.051,3.24199,2031,7323342 +1139,insert,6.397,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,22.731,3.24339,2031,7325844 +1140,search,7304.36,3313.38,2845.72,0.990627,241.834,-nan,-nan,0.92357,0.106259,-1.0,-1.0,25.549,3.24339,2031,7325844 +1141,insert,405.015,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,305.944,3.33599,2059,7540761 +1142,search,7432.62,3348.57,2925.98,0.987705,248.693,-nan,-nan,0.92434,0.105681,-1.0,-1.0,106.179,3.33672,2069,7540761 +1143,insert,31.921,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,68.281,3.34432,2074,7561926 +1144,search,7509.61,3332.24,2971.85,0.997533,252.334,-nan,-nan,0.92437,0.105653,-1.0,-1.0,38.166,3.34448,2075,7561926 +1145,insert,13.176,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,55.372,3.34835,2079,7571861 +1146,search,7522.37,3333.67,2965.44,0.988849,253.988,-nan,-nan,0.92447,0.105514,-1.0,-1.0,41.019,3.34881,2080,7571861 +1147,insert,31.151,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,73.58,3.35643,2085,7590881 +1148,search,7483.77,3334.07,2929.86,1.00613,246.526,-nan,-nan,0.92428,0.105764,-1.0,-1.0,30.082,3.35643,2085,7590881 +1149,insert,10,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,34.604,3.35806,2086,7595507 +1150,search,7484.11,3333.97,2913.46,1.01552,247.452,-nan,-nan,0.92456,0.105642,-1.0,-1.0,44.738,3.35816,2087,7595507 +1151,insert,10.512,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,72.307,3.36167,2091,7601664 +1152,search,7464.79,3326.45,2892.66,1.02096,241.524,-nan,-nan,0.92432,0.105841,-1.0,-1.0,28.404,3.36167,2091,7601664 +1153,delete,55.568,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,139.354,3.35418,2086,7566707 +1154,search,7543.34,3322.7,2955.52,1.02292,254.88,-nan,-nan,0.92459,0.105484,-1.0,-1.0,27.77,3.35418,2086,7566707 +1155,delete,216.342,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,967.731,3.28169,2039,7396192 +1156,search,7443.03,3325.01,2936.72,0.938122,259.37,-nan,-nan,0.92456,0.104777,-1.0,-1.0,180.287,3.28379,2049,7396192 +1157,delete,421.191,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1989.07,3.14432,1902,7079041 +1158,search,7023.06,3398.55,2798.03,1.00183,251.059,-nan,-nan,0.92278,0.107307,-1.0,-1.0,366.012,3.15059,1935,7079041 +1159,delete,513.676,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1803.22,2.93743,1740,6597115 +1160,search,6307.21,3449.98,2520.94,1.0244,212.103,-nan,-nan,0.91661,0.11137,-1.0,-1.0,271.96,2.94242,1763,6597115 +1161,delete,293.061,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1728.43,2.81179,1640,6308902 +1162,search,5902.35,3488,2314.52,1.0846,193.108,-nan,-nan,0.91451,0.112873,-1.0,-1.0,328.689,2.81687,1670,6308902 +1163,delete,124.905,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,823.807,2.75451,1629,6164514 +1164,search,5849.07,3461.07,2274.79,1.10434,185.277,-nan,-nan,0.91516,0.112377,-1.0,-1.0,245.802,2.75895,1652,6164514 +1165,delete,37.036,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,142.558,2.74823,1643,6133412 +1166,search,5988.73,3415.07,2385.68,0.988888,199.961,-nan,-nan,0.91542,0.112265,-1.0,-1.0,37.035,2.74847,1644,6133412 +1167,delete,105.748,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,154.211,2.73422,1634,6057218 +1168,search,5854.24,3380.87,2283.02,1.12455,195.573,-nan,-nan,0.9147,0.112655,-1.0,-1.0,41.854,2.73431,1636,6057218 +1169,delete,29.121,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,156.51,2.71739,1623,6028053 +1170,search,5962.01,3382.2,2383.99,0.94943,210.724,-nan,-nan,0.9116,0.114816,-1.0,-1.0,29.377,2.71742,1624,6028053 +1171,delete,38.37,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,94.725,2.71087,1620,6001880 +1172,search,5780.52,3372,2235.28,1.09752,187.052,-nan,-nan,0.91103,0.115221,-1.0,-1.0,44.388,2.71135,1622,6001880 +1173,delete,60.836,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,152.472,2.69911,1615,5957180 +1174,search,5680.12,3352.07,2158.58,1.18141,177.291,-nan,-nan,0.91089,0.115137,-1.0,-1.0,49.412,2.69947,1617,5957180 +1175,delete,25.601,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,67.081,2.6976,1616,5939326 +1176,search,5891.83,3338.95,2350.7,0.975489,206.686,-nan,-nan,0.91075,0.115415,-1.0,-1.0,34.155,2.698,1617,5939326 +1177,delete,15.72,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,60.87,2.69395,1614,5924145 +1178,search,5889.81,3335.09,2343.97,0.975365,208.03,-nan,-nan,0.91051,0.11555,-1.0,-1.0,19.63,2.69395,1614,5924145 +1179,delete,87.103,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,329.514,2.66451,1594,5863334 +1180,search,5794.23,3336.17,2316.06,0.983663,199.886,-nan,-nan,0.90999,0.116168,-1.0,-1.0,82.516,2.66585,1600,5863334 +1181,delete,44.237,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,105.873,2.65789,1593,5822703 +1182,search,5757.27,3311.86,2271.17,1.00826,188.214,-nan,-nan,0.90998,0.116349,-1.0,-1.0,45.175,2.65857,1595,5822703 +1183,delete,54.532,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,164.76,2.64444,1585,5775807 +1184,search,5679.92,3296.93,2225.8,1.05659,189.712,-nan,-nan,0.90855,0.117145,-1.0,-1.0,18.887,2.64444,1585,5775807 +1185,delete,35.461,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,159.434,2.63346,1577,5750627 +1186,search,5643.03,3301.73,2228.47,0.997543,188.596,-nan,-nan,0.90846,0.117283,-1.0,-1.0,18.278,2.63346,1577,5750627 +1187,delete,189.742,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,974.26,2.55761,1508,5601207 +1188,search,5495.55,3346.41,2202.33,0.970026,188.976,-nan,-nan,0.90781,0.118192,-1.0,-1.0,149.702,2.56024,1520,5601207 +1189,delete,14.492,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,15.971,2.56024,1520,5586425 +1190,search,5433.16,3312.43,2102.03,1.09028,172.598,-nan,-nan,0.90771,0.117859,-1.0,-1.0,28.978,2.56053,1521,5586425 +1191,delete,12.315,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,55.706,2.55766,1519,5574023 +1192,search,5497.99,3311.53,2181.97,1.01434,184.665,-nan,-nan,0.90775,0.117789,-1.0,-1.0,17.224,2.55766,1519,5574023 +1193,delete,260.604,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1156.1,2.44979,1440,5356157 +1194,search,5145.82,3354.86,1990.72,1.11528,162.54,-nan,-nan,0.90507,0.119467,-1.0,-1.0,223.797,2.45338,1459,5356157 +1195,delete,17.15,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,15.555,2.45303,1459,5340404 +1196,search,5276.66,3294.72,2081.21,1.01048,174.121,-nan,-nan,0.90587,0.118693,-1.0,-1.0,64.412,2.45391,1463,5340404 +1197,delete,64.304,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,48.136,2.44567,1460,5293259 +1198,search,5260.62,3253.79,2063.73,1.01772,173.584,-nan,-nan,0.90591,0.118713,-1.0,-1.0,18.179,2.44567,1460,5293259 +1199,delete,19.131,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,75.804,2.43974,1456,5279787 +1200,search,5169.58,3252.39,1968.65,1.06356,163.007,-nan,-nan,0.90551,0.119172,-1.0,-1.0,17.462,2.43974,1456,5279787 +1201,delete,86.541,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,314.478,2.4125,1432,5216567 +1202,search,5239.66,3265,2052.78,0.992116,179.157,-nan,-nan,0.90466,0.119681,-1.0,-1.0,60.524,2.41307,1436,5216567 +1203,delete,27.173,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,16.017,2.41282,1436,5196947 +1204,search,5161.07,3234.12,1996.63,1.05338,165.877,-nan,-nan,0.90412,0.120407,-1.0,-1.0,27.286,2.41287,1437,5196947 +1205,delete,31.736,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,48.712,2.40374,1434,5168447 +1206,search,5055.24,3224.55,1908.59,1.08841,160.052,-nan,-nan,0.90372,0.12055,-1.0,-1.0,17.39,2.40374,1434,5168447 +1207,delete,32.333,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,103.052,2.39468,1426,5146927 +1208,search,5165.93,3226.44,2016.14,0.986529,173.473,-nan,-nan,0.90295,0.120914,-1.0,-1.0,16.626,2.39468,1426,5146927 +1209,delete,361.678,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,984.724,2.25497,1356,4887612 +1210,search,4768.37,3243.08,1807.76,1.16204,148.339,-nan,-nan,0.90146,0.122177,-1.0,-1.0,102.297,2.25621,1364,4887612 +1211,delete,7.281,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.761,2.25543,1364,4882301 +1212,search,4923.42,3223.36,1914.77,0.985325,165.262,-nan,-nan,0.90203,0.121672,-1.0,-1.0,28.408,2.25561,1365,4882301 +1213,delete,143.252,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,551.843,2.19956,1323,4780915 +1214,search,4815.28,3250.38,1892.83,1.07093,157.663,-nan,-nan,0.90026,0.122278,-1.0,-1.0,122.189,2.20147,1332,4780915 +1215,delete,16.27,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,14.75,2.20063,1332,4765751 +1216,search,4780.1,3218.27,1877.75,0.98943,160.969,-nan,-nan,0.90016,0.122775,-1.0,-1.0,15.256,2.20063,1332,4765751 +1217,delete,453.226,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1478.76,2.03809,1194,4452306 +1218,search,4417.17,3332.31,1755.87,0.993145,152.889,-nan,-nan,0.89603,0.127099,-1.0,-1.0,182.27,2.04044,1209,4452306 +1219,delete,110.441,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,438.763,1.98695,1162,4362045 +1220,search,4265.05,3362.47,1721.96,0.994977,146.241,-nan,-nan,0.8948,0.12708,-1.0,-1.0,210.83,1.9889,1180,4362045 +1221,delete,36.339,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,136.84,1.97403,1170,4326917 +1222,search,4271.98,3317.6,1704.32,1.00206,145.292,-nan,-nan,0.89512,0.126652,-1.0,-1.0,39.537,1.97428,1172,4326917 +1223,delete,242.413,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,784.705,1.87751,1100,4109781 +1224,search,4069.81,3351.54,1637.43,0.989783,136.116,-nan,-nan,0.8924,0.128785,-1.0,-1.0,233.098,1.8813,1120,4109781 +1225,delete,30.97,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,147.159,1.86741,1111,4075879 +1226,search,4065.94,3290.38,1613.99,0.99099,143.662,-nan,-nan,0.89235,0.128833,-1.0,-1.0,38.932,1.86771,1113,4075879 +1227,delete,85.22,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,450.104,1.82742,1079,4006503 +1228,search,3938.54,3326.96,1537.24,1.05298,127.797,-nan,-nan,0.89196,0.128835,-1.0,-1.0,187.96,1.83092,1091,4006503 +1229,delete,104.809,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,552.628,1.78283,1047,3922625 +1230,search,3809.52,3376.01,1483.64,1.03636,123.903,-nan,-nan,0.8911,0.129504,-1.0,-1.0,190.834,1.78542,1063,3922625 +1231,delete,93.065,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,350.858,1.74404,1021,3844860 +1232,search,3707.75,3394.91,1439.33,1.08488,118.389,-nan,-nan,0.88755,0.13071,-1.0,-1.0,85.758,1.74528,1027,3844860 +1233,delete,16.404,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,80.179,1.73967,1023,3831414 +1234,search,3753.76,3373.82,1467.42,1.01453,120.894,-nan,-nan,0.88814,0.130309,-1.0,-1.0,49.116,1.7399,1026,3831414 +1235,delete,183.006,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,546.858,1.6726,982,3684234 +1236,search,3649.04,3360.2,1469.96,0.961133,130.727,-nan,-nan,0.88465,0.133314,-1.0,-1.0,48.839,1.67306,985,3684234 +1237,delete,17.414,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,47.96,1.6698,983,3669074 +1238,search,3550.42,3351.03,1390.91,1.11508,116.535,-nan,-nan,0.88442,0.133329,-1.0,-1.0,16.484,1.6698,983,3669074 +1239,delete,65.993,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,139.728,1.65343,972,3620984 +1240,search,3523.24,3336.1,1375.8,1.07562,114.24,-nan,-nan,0.88439,0.133729,-1.0,-1.0,44.839,1.65366,974,3620984 +1241,delete,42.117,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,39.188,1.65003,972,3580113 +1242,search,3561.15,3287.69,1380.16,1.03778,117.579,-nan,-nan,0.88375,0.134318,-1.0,-1.0,16.264,1.65003,972,3580113 +1243,delete,63.968,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,202.022,1.62402,955,3533909 +1244,search,3414.45,3291.95,1283.86,1.13321,107.624,-nan,-nan,0.88211,0.135469,-1.0,-1.0,41.585,1.62416,957,3533909 +1245,delete,19.441,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,48.1,1.61985,954,3519590 +1246,search,3489.25,3278.98,1377.36,1.00551,122.183,-nan,-nan,0.8814,0.136149,-1.0,-1.0,26.701,1.61994,955,3519590 +1247,delete,78.46,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,104.602,1.58542,934,3452537 +1248,search,3434.4,3294.81,1337.17,1.01963,121.524,-nan,-nan,0.88329,0.133633,-1.0,-1.0,37.563,1.58571,936,3452537 +1249,delete,44.755,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,115.591,1.57145,928,3416711 +1250,search,3369.2,3282.89,1326.02,0.981666,117.11,-nan,-nan,0.88309,0.134278,-1.0,-1.0,54.987,1.57188,931,3416711 +1251,delete,33.386,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,70.685,1.56289,926,3387653 +1252,search,3370.56,3255.25,1324.68,1.00347,113.995,-nan,-nan,0.88292,0.134163,-1.0,-1.0,15.776,1.56289,926,3387653 +1253,delete,17.643,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,34.525,1.5572,924,3372157 +1254,search,3395.95,3252.81,1351.82,0.981625,117.847,-nan,-nan,0.88314,0.134194,-1.0,-1.0,15.688,1.5572,924,3372157 +1255,delete,159.625,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,190.399,1.50097,894,3258215 +1256,search,3303.88,3257.48,1312.19,1.00852,118.017,-nan,-nan,0.88056,0.135672,-1.0,-1.0,73.27,1.50197,899,3258215 +1257,delete,42.455,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,68.465,1.48795,892,3223657 +1258,search,3271.39,3233.26,1298.37,0.993107,114.707,-nan,-nan,0.87874,0.13664,-1.0,-1.0,29.477,1.48809,893,3223657 +1259,delete,59.483,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,248.99,1.46178,873,3174982 +1260,search,3249.97,3252.55,1280.49,0.962714,118.199,-nan,-nan,0.8778,0.137564,-1.0,-1.0,69.719,1.46258,877,3174982 +1261,delete,21.915,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,33.255,1.45887,875,3157038 +1262,search,3158.38,3225.6,1214.98,1.03043,105.064,-nan,-nan,0.87708,0.137953,-1.0,-1.0,26.904,1.45907,876,3157038 +1263,delete,131.984,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,426.831,1.40604,849,3058847 +1264,search,3062.54,3234.2,1187.49,1.04133,102.431,-nan,-nan,0.87528,0.13865,-1.0,-1.0,140.08,1.40805,858,3058847 +1265,delete,377.189,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,447.302,1.28369,769,2833531 +1266,search,2790.7,3293.27,1085.19,1.03725,88.457,-nan,-nan,0.86944,0.141716,-1.0,-1.0,123.728,1.28531,778,2833531 +1267,delete,85.054,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,208.316,1.25558,761,2763793 +1268,search,2826.78,3249.98,1131.6,0.937225,92.8669,-nan,-nan,0.86962,0.141183,-1.0,-1.0,66.865,1.25629,766,2763793 +1269,delete,194.337,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,317.011,1.19293,744,2627384 +1270,search,2792.27,3249.21,1106.81,1.01348,100.432,-nan,-nan,0.87145,0.139948,-1.0,-1.0,121.768,1.19454,754,2627384 +1271,delete,85.394,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,282.523,1.16142,732,2553476 +1272,search,2653.41,3218.66,1025.15,1.07635,87.7101,-nan,-nan,0.87065,0.140114,-1.0,-1.0,70.427,1.16203,737,2553476 +1273,delete,147.218,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,366.064,1.10689,701,2443067 +1274,search,2623.55,3244.78,1041.69,0.924011,87.3063,-nan,-nan,0.8693,0.141142,-1.0,-1.0,116.505,1.10899,709,2443067 +1275,delete,24.205,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,69.853,1.10579,704,2421654 +1276,search,2594.78,3194.67,1026.42,0.972842,88.2316,-nan,-nan,0.86811,0.142092,-1.0,-1.0,11.362,1.10579,704,2421654 +1277,delete,36.116,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,59.86,1.09782,699,2391396 +1278,search,2596.54,3172.71,1013.13,0.991487,90.3313,-nan,-nan,0.86699,0.142353,-1.0,-1.0,28.622,1.09796,700,2391396 +1279,delete,41.563,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,70.54,1.09206,695,2367854 +1280,search,2571.7,3151.31,1006.18,0.909026,91.2504,-nan,-nan,0.86739,0.141983,-1.0,-1.0,12.466,1.09206,695,2367854 diff --git a/scripts/big_ann_perf_numbers/test_perf_debug_scan_0.15_batch_versus_nonbatch.csv b/scripts/big_ann_perf_numbers/test_perf_debug_scan_0.15_batch_versus_nonbatch.csv new file mode 100644 index 00000000..449a240f --- /dev/null +++ b/scripts/big_ann_perf_numbers/test_perf_debug_scan_0.15_batch_versus_nonbatch.csv @@ -0,0 +1,26 @@ +num_search_workers,step_num,step_type,search_latency_ms,worker_partition_size,worker_scan_throughput,recall_mean,recall_std_dev,gt_scan_mean,gt_scan_dev,mainteance_ms,index_mem_gb,num_partitions,num_vectors +1,2,search,4777.65,37.312,5.22065,0.8551,0.130106,-1.0,-1.0,10.209,0.0184881,1000,38806 +1,3,insert,20.279,-1.0,-1.0,-1.0,-1.0,13.566,0.022655,996,49334 +1,4,search,5412.6,66.2949,6.35675,0.86686,0.128427,-1.0,-1.0,14.288,0.0226615,993,49334 +1,5,insert,18.384,-1.0,-1.0,-1.0,-1.0,160.439,0.033017,984,73557 +1,6,search,7588.72,195.098,7.56384,0.92515,0.103785,-1.0,-1.0,131.68,0.0331618,986,73557 +1,7,insert,32.757,-1.0,-1.0,-1.0,-1.0,124.282,0.0426658,987,95766 +1,8,search,8668.57,246.309,8.5135,0.92462,0.103689,-1.0,-1.0,30.552,0.0431782,992,95766 +1,9,insert,5.095,-1.0,-1.0,-1.0,-1.0,7.963,0.0449738,993,100025 +1,10,search,8844.58,249.764,8.77157,0.92358,0.103018,-1.0,-1.0,21.31,0.0450048,997,100025 +1,11,insert,11.355,-1.0,-1.0,-1.0,-1.0,7.957,0.049765,998,111417 +1,12,search,9715.83,289.247,9.18782,0.92349,0.103712,-1.0,-1.0,19.631,0.0500151,1002,111417 +1,13,insert,24.324,-1.0,-1.0,-1.0,-1.0,8.25,0.0610939,1003,137139 +1,14,search,10624.4,327.04,9.65616,0.92001,0.105792,-1.0,-1.0,11.911,0.0610947,1004,137139 +1,15,insert,21.929,-1.0,-1.0,-1.0,-1.0,9.06,0.0697341,1005,156710 +1,16,search,11085.7,363.254,10.1911,0.91823,0.106214,-1.0,-1.0,8.385,0.0697341,1005,156710 +1,17,insert,5.59,-1.0,-1.0,-1.0,-1.0,8.888,0.0715754,1006,161773 +1,18,search,8987.83,378.453,14.0274,0.91928,0.106082,-1.0,-1.0,12.499,0.0715754,1006,161773 +1,19,insert,48.525,-1.0,-1.0,-1.0,-1.0,10.652,0.0786999,1008,177161 +1,20,search,9641.55,418.638,14.3387,0.92342,0.102778,-1.0,-1.0,6.701,0.0786999,1008,177161 +1,21,insert,319.002,-1.0,-1.0,-1.0,-1.0,188.001,0.201592,1064,448898 +1,22,search,15838,823.636,16.2556,0.90938,0.10831,-1.0,-1.0,61.443,0.201591,1075,448898 +1,23,insert,400.325,-1.0,-1.0,-1.0,-1.0,276.861,0.32912,1141,733493 +1,24,search,20866.1,1101.08,16.8979,0.90518,0.110083,-1.0,-1.0,108.586,0.329715,1170,733493 +1,25,insert,40.431,-1.0,-1.0,-1.0,-1.0,24.171,0.346687,1175,777443 +1,26,search,21144.6,1048.89,16.971,0.90193,0.112609,-1.0,-1.0,31.049,0.346928,1181,777443 diff --git a/scripts/big_ann_perf_visualize.py b/scripts/big_ann_perf_visualize.py new file mode 100644 index 00000000..ef188fea --- /dev/null +++ b/scripts/big_ann_perf_visualize.py @@ -0,0 +1,282 @@ +import pandas as pd +import matplotlib.pyplot as plt +import os +import numpy as np +import matplotlib.cm as cm +import matplotlib.ticker as mticker +from matplotlib.ticker import ScalarFormatter, LogLocator, FormatStrFormatter + +SECONDS_TO_MS = 10.0 ** 3 +MIN_TO_SECONDS = 60 +MIN_TO_MS = MIN_TO_SECONDS * SECONDS_TO_MS + +SRC_DIR = "big_ann_perf_numbers" +DST_DIR = "bigann_perf_vis" + +NUM_OPERATIONS_TO_VISUALIZE = 1300 +def visualize_perf(src_dataset, config_details): + # Load CSV + df = pd.read_csv(os.path.join(SRC_DIR, src_dataset)) + df = df.head(NUM_OPERATIONS_TO_VISUALIZE) + df = df.fillna(0) + + # Filter rows for step_type == "search" + search_df = df[df['step_type'] == 'search'] + + # Extract data + x = search_df['step_num'].values + recall_mean = np.round(search_df['recall_mean'].values, 2) + latency_search = search_df['latency_ms'].values + + insert_df = df[df['step_type'] == 'insert'] + latency_insert = insert_df['latency_ms'].values + x_insert = insert_df['step_num'].values + + delete_df = df[df['step_type'] == 'delete'] + latency_delete = delete_df['latency_ms'].values + x_delete = delete_df['step_num'].values + + x_maintenance = df['step_num'].values + latency_maintenance = df['mainteance_ms'].values + + # Convert sums to minutes + total_search_min = latency_search.sum() / MIN_TO_MS + total_delete_min = latency_delete.sum() / MIN_TO_MS + total_insert_min = latency_insert.sum() / MIN_TO_MS + total_maintenance_min = latency_maintenance.sum() / MIN_TO_MS + total_all_min = total_search_min + total_delete_min + total_insert_min + total_maintenance_min + + # Create 3 rows x 2 columns subplots + fig, axs = plt.subplots(4, 2, figsize=(12, 12), sharex=True) + + # Row 0 + axs[0, 0].plot(x, recall_mean, color='green') + axs[0, 0].set_ylabel('Recall@10') + axs[0, 0].set_title('Recall Mean') + print("Average Recall for run", src_dataset, "is", np.mean(recall_mean)) + + axs[0, 1].plot(x, latency_search, color='purple') + axs[0, 1].set_ylabel('Latency (ms)') + axs[0, 1].set_title(f'Search Latency (Total: {total_search_min:.2f} min)') + + # Row 1 + axs[1, 0].plot(x_delete, latency_delete, color='red') + axs[1, 0].set_ylabel('Latency (ms)') + axs[1, 0].set_title(f'Delete Latency (Total: {total_delete_min:.2f} min)') + + axs[1, 1].plot(x_insert, latency_insert, color='orange') + axs[1, 1].set_ylabel('Latency (ms)') + axs[1, 1].set_title(f'Insert Latency (Total: {total_insert_min:.2f} min)') + + # Row 2 + axs[2, 0].plot(x_maintenance, latency_maintenance, color='blue') + axs[2, 0].set_xlabel('Step Num') + axs[2, 0].set_ylabel('Latency (ms)') + axs[2, 0].set_title(f'Maintenance Latency (Total: {total_maintenance_min:.2f} min)') + + axs[2, 0].plot(x_maintenance, latency_maintenance, color='blue') + + # Bottom right subplot: Vectors and Partitions over time + non_search_df = df[df['step_type'] != 'search'] + ax1 = axs[2, 1] + ax1.plot(non_search_df['step_num'].values, non_search_df['num_vectors'].values, color='olive', label='Num Vectors') + ax1.set_xlabel('Step Num') + ax1.set_ylabel('Num Vectors', color='olive') + ax1.tick_params(axis='y', labelcolor='olive') + + # Create second y-axis sharing the same x-axis + ax2 = ax1.twinx() + + # Plot num_partitions on right y-axis + ax2.plot(non_search_df['step_num'].values, non_search_df['num_partitions'].values, color='brown', label='Num Partitions') + ax2.set_ylabel('Num Partitions', color='brown') + ax2.tick_params(axis='y', labelcolor='brown') + + lines_1, labels_1 = ax1.get_legend_handles_labels() + lines_2, labels_2 = ax2.get_legend_handles_labels() + ax1.legend(lines_1 + lines_2, labels_1 + labels_2) + + axs[2, 1].set_title('Vector and Partition Count') + + # Plot the scan percentage needed to cover the ground truth vectors + axs[3, 0].plot(search_df['step_num'].values, search_df['gt_scan_mean'].values, color='green') + axs[3, 0].fill_between(search_df['step_num'].values, search_df['gt_scan_mean'].values - search_df['gt_scan_dev'].values, search_df['gt_scan_mean'].values + search_df['gt_scan_dev'].values, + color='green', alpha=0.3) + axs[3, 0].set_xlabel('Step Num') + axs[3, 0].set_ylabel('Partition Scan Percentage') + axs[3, 0].set_title('Rank of GT partitions as Search Candidates') + + # Plot Scan Throughput + axs[3, 1].plot(search_df['step_num'].values, search_df['worker_scan_throughput'].values, color='gray') + axs[3, 1].set_xlabel('Step Num') + axs[3, 1].set_ylabel('Scan Throughput (GB/s)') + axs[3, 1].set_title('Worker Scan Throughput') + + # Overall title including total latency sum in minutes + fig.suptitle(f'{config_details}\nTotal Latency: {total_all_min:.2f} minutes', fontsize=16) + + fig.tight_layout() + plt.savefig(os.path.join(DST_DIR, src_dataset.replace("csv", "png")), dpi=300) + +def visualize_percentage_variation(src_dataset): + # Load CSV + df = pd.read_csv(os.path.join(SRC_DIR, src_dataset)) + search_df = df[df['step_type'] == 'search'] + + # Get unique nprobe_percentage values + nprobe_values = sorted(search_df['nprobe_percentage'].unique()) + colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] + fig, axes = plt.subplots(2, 1, figsize=(10, 8), sharex=True) + + # Top subplot: latency_ms vs step_num + for i, nprobe in enumerate(nprobe_values): + sub_df = search_df[search_df['nprobe_percentage'] == nprobe] + axes[0].plot(sub_df['step_num'].values, sub_df['latency_ms'].values, label=f'Factor Scanned: {nprobe}', color=colors[i]) + total_time_minutes = sub_df['latency_ms'].values.sum() / MIN_TO_MS + axes[0].set_ylabel('Latency (ms)') + axes[0].set_yscale('log') + axes[0].set_title('Search Latency over Step Number') + axes[0].legend() + + # Bottom left subplot: recall_mean vs step_num + for i, nprobe in enumerate(nprobe_values): + sub_df = search_df[search_df['nprobe_percentage'] == nprobe] + axes[1].plot(sub_df['step_num'].values, sub_df['recall_mean'].values, label=f'Factor Scanned: {nprobe}', color=colors[i]) + axes[1].set_xlabel('Step Number') + axes[1].set_ylabel('Recall Mean') + axes[1].set_title('Recall Mean over Step Number') + + plt.tight_layout() + plt.savefig(os.path.join(DST_DIR, src_dataset.replace("csv", "png")), dpi=300) + +def visualize_vary_worker(src_dataset): + # Read CSV + df = pd.read_csv(os.path.join(SRC_DIR, src_dataset)) + search_df = df[df['step_type'] == 'search'] + + # List of metrics to plot + metrics = [ + ("search_latency_ms", "Batch Search Latency (seconds)"), + ("worker_partition_size", "Avg Scan Partition Size"), + ("worker_scan_throughput", "Partition Scan Throughput (GB/s)"), + ("recall_mean", "Query Recall") + ] + + # Get unique worker counts for consistent colors + worker_counts = sorted(search_df['num_search_workers'].unique()) + colors = plt.get_cmap('tab10').colors # or use any other color map + + fig, axs = plt.subplots(2, 2, sharex=True, figsize=(12, 10)) + axs = axs.flatten() + + for idx, (metric, metric_label) in enumerate(metrics): + scale_factor = 1.0 + if metric == "search_latency_ms": + scale_factor = 1000.0 + + ax = axs[idx] + for i, worker in enumerate(worker_counts): + data = search_df[search_df['num_search_workers'] == worker].sort_values('step_num') + ax.plot(data['step_num'].values, data[metric].values/scale_factor, label=f'Num Search Workers: {worker}', color=colors[i % len(colors)]) + + ax.set_xlabel('Step Num') + ax.set_ylabel(metric_label) + ax.set_title(metric_label) + ax.legend() + + if metric == "search_latency_ms": + ax.set_yscale('log') + minor_locator = mticker.LogLocator(subs=np.arange(2, 10)) + ax.yaxis.set_minor_locator(minor_locator) + minor_formatter = mticker.FormatStrFormatter("%.1f") + ax.yaxis.set_minor_formatter(minor_formatter) + + formatter = ScalarFormatter() + formatter.set_scientific(False) + ax.yaxis.set_major_formatter(formatter) + + fig.suptitle(f'Vary Search Workers Experiemnt (Scan Percentage = 15%, Batch Size = 500)', fontsize=16) + + plt.tight_layout() + plt.savefig(os.path.join(DST_DIR, src_dataset.replace("csv", "png")), dpi=300) + +def visualize_vary_batch_size(src_dataset): + # Read CSV + df = pd.read_csv(os.path.join(SRC_DIR, src_dataset)) + search_df = df[df['step_type'] == 'search'] + search_df = search_df[search_df["step_num"] > 5] + + metric_names = [ + ('search_latency_ms', 'Search Latency (ms)'), + ('worker_partition_size', 'Partition Size'), + ('worker_scan_throughput', 'Worker Scan Throughput'), + ('worker_scan_time_ms', 'Worker Scan Time (ms)'), + ('worker_result_time_ms', 'Worker Result Write Time (ms)') + ] + colors = plt.get_cmap('tab10').colors # or use any other color map + + batch_sizes = list(search_df['batch_size'].unique()) + fig, axes = plt.subplots(2, 3, figsize=(16, 12), sharex=True) + axes = axes.flatten() + + for i, (col, title) in enumerate(metric_names): + + ax = axes[i] + for j, batch in enumerate(batch_sizes): + batch_data = search_df[search_df['batch_size'] == batch] + ax.plot(batch_data['step_num'].values, batch_data[col].values, label=f'Batch Size {batch}', color=colors[j % len(colors)]) + ax.set_title(title) + + ax.set_xlabel('Step Num') + ax.legend() + + fig.tight_layout() + plt.savefig(os.path.join(DST_DIR, src_dataset.replace("csv", "png")), dpi=300) + +def visualize_hardware_metrics(src_dataset): + # Read CSV + df = pd.read_csv(os.path.join(SRC_DIR, src_dataset)) + search_df = df[df['step_type'] == 'search'] + fig, axs = plt.subplots(2, 2, figsize=(12, 8), sharex=True) + + # 1) worker_partition_size versus step_num + axs[0, 0].plot(search_df["step_num"].values, search_df["worker_partition_size"].values) + axs[0, 0].set_title("Partition Size vs Step") + axs[0, 0].set_ylabel("Worker Partition Size") + + # 2) worker_scan_throughput versus step_num + axs[0, 1].plot(search_df["step_num"].values, search_df["worker_scan_throughput"].values, color="orange") + axs[0, 1].set_title("Scan Throughput vs Step") + axs[0, 1].set_ylabel("Scan Throughput") + + # 3) measured_ipc versus step_num + axs[1, 0].plot(search_df["step_num"].values, search_df["measured_ipc"].values, color="green") + axs[1, 0].set_title("Measured IPC vs Step") + axs[1, 0].set_xlabel("Step Num") + axs[1, 0].set_ylabel("Measured IPC") + + # 4) cache_miss_rate versus step_num + axs[1, 1].plot(search_df["step_num"].values, search_df["cache_miss_rate"].values, color="red") + axs[1, 1].set_title("Cache Miss Rate vs Step") + axs[1, 1].set_xlabel("Step Num") + axs[1, 1].set_ylabel("Cache Miss Rate") + + fig.suptitle(f'Batch Query Search with Hardware Counters (# of Workers = 8, Batch Size = 256)', fontsize=16) + + fig.tight_layout() + plt.savefig(os.path.join(DST_DIR, src_dataset.replace("csv", "png")), dpi=300) + +if __name__ == "__main__": + ''' + # visualize_vary_worker("perf_debug_scan_0.15_vary_num_search_workers.csv") + # visualize_vary_batch_size("perf_debug_scan_0.15_vary_batch_size.csv") + visualize_hardware_metrics("perf_debug_scan_0.15_counters.csv") + ''' + + configs_to_visualize = [ + ("test_perf_debug_scan_0.14_worker_batch_tuning.csv", "Scan Percentage = 14%, Query Batch Size = 256, Partition Chunk Size = 256"), + ("perf_debug_scan_0.14_worker_batch_tuning_lower.csv", "Scan Percentage = 14%, Query Batch Size = 256, Partition Chunk Size = 128") + ] + + for dataset, config_details in configs_to_visualize: + visualize_perf(dataset, config_details) diff --git a/scripts/bigann_perf_vis/perf_debug_scan_0.14_tuning.png b/scripts/bigann_perf_vis/perf_debug_scan_0.14_tuning.png new file mode 100644 index 0000000000000000000000000000000000000000..eae31cea0db45c0759916a7550cd517aad3b2320 GIT binary patch literal 741337 zcmeEu`8${W+O^UkO%xRoiVzWzp$rL0$UGG)MCLgeD>Ru(h$2&_G9^PPL?M(}ri73= zLoyHV`rOZc-e>>tK7YZxJC1wb_p#&qy{^x74(nWNo!328mD5|P8L25KD7KzakX5Ik z*hWMCq1u4|hq)kA9RCt?lGAn4u)X4R?UI8jh4LjQJ1bi!tE-n;T}&MuuiDxiXVk&l=Z6DHn=06clGo5t@iA0|A$J;@DmyfV{y;HYCq+du@>E!G=%|Mx!u_fz9`vhM%i z|IEL-@!)^|_0LrQ`Ro73>HOzd{vU^O_wIj=SKUbsy?dX=!Qez3+~_ zR#sBl5*^O&?d@If;XeD@da&s(1x2Cz?5^d2g~i3a;=&DV&nQhVL|RLomL-4K%f8ob zqM@Z#`$fNZum9)I3ZKf$OWWHSj~zRf_3G8l+}zwajRXI{qpAmzo(sNj-iUrGD=TSe z*nyw0v$MMq78dr;Pwew^c+? za7R*7QdiAcYisLE7FEtdceij03)8Eqsof0-kk!{`boljU)5eV(e{EFwXv#zTvh4PugA|iJR3nfO!#vV$zyF?zvAqaY(ljfWk$ZGKjb{OPcMJ5@G-wpyj5HF+|vA?{9`;kJSSWyC^!^D z>)Kob�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 =C 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 z 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

    CBHFRG$J4|ot{nd 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

    R%UIsZl3QBq@5p>NU(V~O(L%NV@ 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 UaF&3SoT#aoRLT^q|a?z~oSPwZnJ)-b}5fJpI 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 VKkiw0Rl+;5(sGT(h4;67_HTIu)!P67 literal 0 HcmV?d00001 diff --git a/scripts/bigann_perf_vis/perf_debug_scan_0.14_worker_batch_tuning_lower.png b/scripts/bigann_perf_vis/perf_debug_scan_0.14_worker_batch_tuning_lower.png new file mode 100644 index 0000000000000000000000000000000000000000..efebbad411fa22ac5af5458240c4556e7ea78bec GIT binary patch literal 859116 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%0AFv@(U9Hic7fx(}ZQB5p8od#cw>WP1D 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�=q(yvjbGk5Lo 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

    $CTk2HKV-AiNO)|6nL9 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

    f}RRAB`jWgls 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

      KAF$1PMf%;j{@dHz?K1P2-x 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
      A1& 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 Q^ldZ`YadGe`r9A=56*c3mH+?% literal 0 HcmV?d00001 diff --git a/scripts/bigann_perf_vis/perf_debug_scan_0.15_vary_batch_size.png b/scripts/bigann_perf_vis/perf_debug_scan_0.15_vary_batch_size.png new file mode 100644 index 0000000000000000000000000000000000000000..ba0f4ac029dfa3f730f1ceea738e2491f4ec21df GIT binary patch literal 2514743 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

      t_Lcw~l@XuT z<>BS6_eAmEftiR7pkTzuJ9sd*kh4vtX-2{OvT};m9!Svbr0Q{qOFp!a*P`y02m{Nh ze@~LY+<lbeu` z;Lcp%KfxK*WhQvoE9XW6Ym$s@RZo#{OI1(Ue-7HfUC>kY-~|p;+2a^OBDvJn)qO9b z4|{%si4t$S>;$}BU-Hq=po*(wE*yv|x4fZ&nc1>nPly@nF-!E5Rw>W0KSooV=Dk8g z_fh}>v%>)T2QM;R`Ljr@Gva3=NK;pUB^_Db37EdBCx@1Sym)}J4KxR8Pdv4I!<>!g z^Q!xAU%YSw?&gjU$}8w*k(*&x{2WMZY%C8>D*W)w5xZd&y6ed#_cw3e@EZfc*GTN- zq1kRU3)Dyw%>hAoqK(mTs-oNl_XYi`l#C4J;;2_3AnsKgXh2@Oo?x~ipAmE);*z`f zBLcI81lnBSQuqnbSa`B4Q#Pe7b*KNVzGRwhbISQz{&MelcY>RYwiAhreSF zGs}j@`&!%jS(k9{wO_}kA0%aBG_W=D6P)$iV{%yl4lO)y3&OArh~Io{HpX%wV5fl8`VS-h z2m=b^2l{B@(}VW270a@(UK<4AE(=O+)>eIoEsX)nMG|yn~15K|laAz;JAp zl}UKDNr-65$rd|TEnk_5P^AR9bIs&&91nWfYm)xnV0gNlN`G;!x(W&jpR2Eh<7AR1 zGE&|QBw@8B<404iO0aR0e+D_{-#hD7aj(C6*NbEH%emf6JrgYfsBZTdwY#+jN`ZNcYJhM+bv}yR4K00=^3@!QMTALdT84#vxiE*aZ@(`I>{T3PO5-s4>NecS z_9rSP-3rAX=T4raMs=zSn~gN&lOlfsZ+0&RJ@fbT%Lk$R37rTdul^|sx%$~R zvOy(i2a1{&CInE8e7Du ztvu0?U;aapbcS!Rs?Y=VC#R^W6Qh)um!}EOTTdo|fipe~3V_=% zxdTjbr<}Ze%jopYJ9l1zX$58qxsv5u={|XPtuu0RA92NNlP%d05h2c4h3*UC5s863 z&D&IyZ=^GLsN=oR$bsc*aeXwUB~V4H zvA*A1Xx7%O)q5st*J`0)hgq@4?ZrTUN+&ZW)0@o|6gH5PK6wX7U`qm?do`DIg#ZV7 z%E`F!`-B8aZvo@Fk5Et7dlnWI(X6P~cz(pgo* z4SVQwXAG5pUH2UU$8EPOx|r>(ju5$4@lZcTYPjOOMBhb3SXFMHJ^=HO(RkB zYEsPTtfqIZWm=P^irjZW#{)GJbDpQJOf~3?R?E#4-Jg3FInd64R}gz40?htnSoN^< zoD<$BEc_G*{p=Z^GSgGL)?&{BCt&S4H=~BTfXc@sh31c#_O$_+lXbMQNp9N{@g-~x zk%3YO(qvGDg$pOaGGKUT`9?SqM&E10P@>JHKqy4+J>LxyCCjbFHWPj| zN>UV67%fX(cg0%M7*mL*wt-$HBEFHTe_MR{mn4{iO9e5~G$~x;|u`U$Rw3a(fV!O~jQCr7wn7)+7tg^~NQKb{T#O&Z!C0oU`3(e6+M{ zt7LkN52E#ZQw83(xOTgrN>S>B9x2@+u z`Q-H5=p@#Q#Fv1mJ?sV2>w4v;h3#)K9zbL%&BM^6h{PXvG>m7sQu()zXnru=cyPG# z$qmu-6B2>qx%xGNk@kYQeDq!V&+9Ja-u_O@;r%U3;2W*z`8YR&D$yg4_-?nH$T{ID zwIlof!K>T1w%Z>*y7-pY(bmnwAM14X`@ipY|DDNk@eUdLQ;o9HUf0;Ta769&>|TKn z(mpw~gV(lCoKdV0cxtHGSRXyIz9v2#?qp9s+-6upe`m>vEZuc2S}~?IqqFZD#5+b0 zcMF_J;vT9=UM^ZZAD0lvoH3))e4lTT*DR-J2J^PHvj)!hb8cq5`whaNUx{=-=WD-F z&O~skCjE&h;qis^YmE~4jW=%Gh{7%!s4ImkCj$YkK|cpR9VMud5Q~J1Q>qSq-z?xB z;dsg`V5C6@1YQV}h&u86#>`ZE&45BI8%(yXw$i@YJt3O^ZD~npP=WIJ`QbJL!=w8P zUslI#(_a!M%0BEz=Q4WtlkV1Ut24Qn3-2F%x#xafiqy9G`<|NxpIp)j(TY(@QTvTC zlC`$lv`c%cbba&W#QcQ~R5jbOH!MrIDJHQ!I|ci4hg`Tvtb9w?ZnZ^Gswv?@4;k{!8yRwg)auq&Do3a0beYLN5Aa?7M$^!xdY5v`oA8;xO_xrcYp zEw*u?HR*a0xp(L(yV|0lxi#(@tCr_%vJ>{5o#5RSRVr)$YGn@h&1mJt^kEyrjxl9P z{WypE`1ga^FElYblgn);P))>ilSo!?M1cfn zw~<0y?U7YI}M|QiDui#_x5W+g9y^BE~Z=FvfIJpGodTF zG_I>_A@|#So!Hh=+8_^M177*@(+7l^PFR|3i5p5 z7_S#+mp$5UHiY9iv>1;M2?AO!Dk_TB$(-*u^|*da46qaclT4xS9^ME(M7)%(1I`E> zS<}E28YI}u3!=#x(pv%siC;779w|as-t)4(~9(`W-n#DSN`+^MHfY^ ze{9Ug7F*uLDGoWKcg-F9xO5WyH;P#tXv_67fTWH(=P$PX{;MFZgDnhd5~aHCV`uLP z@U3!q?6~-&!KAv{YV)DS#OCSI=aZxjHD%v{>BjlZ8Uf2bO?0DW~H%}?!!w?eIt4Dw8Zf8mxmD%)1 z=GN^wt}Yus40=4-bdh7__4llA)tXpq)GY)ZZV|$XZOxJrGiQgUunsx^E9~6%az67R5_A@vtu~1A z`xiHW@z@;scaY6_aP&c`{iS(nQ6(FZvg2}68f!Uil=fbn;E#@ z_V=@|Hu7CwhbrOXWV*<&j)hd-+b@hK984${GWDLNhw zO)0s4NbdZJ$sWOm8Xc`Hxx64sbLD0eYEe-~mlXfWIjgH|Lk;zHQgLysH4L|JFy%e_ zUYl<^HPHng#X2bdM_LauDlEK@&NkwV^6t11&(W~fAwJCtC&q9s zQ?kAhbJONa24>gSZnC919EtyZNZ({T=r|?z;-PQRJ$`D7U6c!)dC!*aIpQ6@MYwwn zfn|R^^6u-jNe+EJ-Q26mbnDRzH~JT?mYM~{LuG2lx$nPb&Dd%+@Hs1l-jp&;LKRE8 zML$t{i;z-KW-Ul^`jCrc^WXXO0T2$jJUWkS8X#6l%e6eA5zSYC*@qRL0Kxl&(9-j8 zrH`G<+e88Y{e`A|i47lE7lx>8256klYT|ha8%$sl-w#gvp98S~2-0Sgdd-*+gmn?U zXZ}{7McnSBcA5VaC6u~wbeF(gx^8y9YM%OpH9`6G{99~S6(5YK&Y7vYt8_tORag8& zJF>9no)8_!X2~(gP!dkE1w}?_mbhCe^o5IUu`9^(@)3M0)Hp(` zcwqzgr?hv5H|$jwzc32ZxN%*S(UI?X&vF}ww&@g}tF@nYWpEljudFD39w8Ikva?Z6 znzB;Y_i{dWdE3<0CS}Lfr8f$F&9=MV+l+N)t zX9!+|8v0efrkSclMr=KPmG4w@5dK2g0j`sF0ji*L^6O_>MhFTBZHBO_A$+um*1@1L zB`d@eXx=I4W8mm`bh#00L>J=!)Y+K;LIM8@5@er zImB%MXfAL%;?>Q&r#TC~43Rf0r#o0j@7uM@9aQ@e=6?Uuphz_hPdm?9v~a};oo+~( z9l0kipx#+mwe&+2ou-oUl=hmTPdm;mlWWm?Y`UbX>fjay;S=kWM)Kdk(Rpdioyx!} zQY>#2)A#11>Rqj#)QA}Wr%#oDaiWQZo%1e6_s9PJVcdUR$kjrz=(?JoiEoN@+2f?) zD$TO4=KAc7(IsxOEgW_<+gi1H=w}o8gBbQ!^{+^|K(|x+#pTiL(q7LbW=316@?QFjc(}~`UGwhf18rGUT zz7)FExwKU7yojsJ%!9B+38nO+6DNzB*1Gcvt-ASmKV`VrLey!8B3;JgP0pLxEgmT+ znrwb0Ian`bgt=JHO?;vCqxR|Qn2TOh&W~HyOe=t0Se`jHs82$5PK}T24O!QUVPCh9 zW#SZ;AKepNtpqsc6{jpSBv@m;dhb#nYv=x2KiJJejR9nX%Fr+L9{n~VXeV(72)Lw6 zMn=I&Nxq*yb8ER~K{Jy@ltu5DI>6UtK{R;k^y%+ZZ@~}JY&vigm?S(8+`u$+2Vo^+ z2AGY9C$^&628Mj2L{1T0tjj~l^2?X^!gI~|YFd##FHzGds+u1QA!5BAcFCMS8}8uL zXUd~Au4)U4E}5gbo~A4;<%u6t9#>YqWGOZsnY}gQE49Bhk56xn@$HviRI}-%mzg|F zoE_byc|DWiWd$5NHVRwq#?Z)7Ny)XqG9d97O3rD?((P%%1?nAp7RkJC?7}aC=f3)I z`z<$$kR_*|E@D_n{?XelHN0kO@>6s7mXF`-T|HJ*PpZ+5r)pNm9&DD+=h>}NYc8gy zcjxMT2CBnRBO!+v1X_otX*-R>o15<3u1T`z4N+0BaJOH^=2yMO*kW8g&^f#^I;KJ5 zQPlkQ={kuAm7lkWUeELqWEa0W`dQav!S|F`;pwdIiCE3^J1zMi@w(!4hkehYyR2_) zl)!UXyw+RPQEC3yFy<`#wZ!yhZw(IlVb<{R&>b1u;K@Qj%S^u$JaIM(Za zX@yt&q?I*W=I`8flR1NCNv9}<#)4^X+i`UopLzB<8QO=YCK42e`MhTN5)Kz$-;~O< z_{mtdJ;xCPt#*J{l7YzxJFjg3L*gr9%ZbtS{l|{YnlM9`X?!(lf-n&FkYc7VuNwys z8VIXtB81lT*JA8zNPY-VAz>ry`t_fH_%yv9V*lRsSC8>6KGb5p>yOSs)iWXyr>Eqv zy}J?rBw=v7^n1M8kf~X(P>q-aXxqXS5^rQ(s>_EWOMnCBwiR z4G>yN)5Iq2nCrBksV7CZZhdin>-6s&gwN@3;#u}qc?=c?mS@IW9UoYi)G09(6qeN_ zLs3R$d+?}gGmHDTFLJa@64xUv7rQCmeVxub=r$6PJvEqh)AZW*H-#b9{K@vl%KN$Y z?R^=XpeJj%Eoxe(i?6A>X4ovven}ILYtF{b_3eJ_j)@E0PVOtX6hxJVv};EzZdWfC zoz$dF@ZZOO+3CJh8`HGVfySv&hV~>w{R->Po5=*R^Z;#r*$2Cxd7jx z{;~t)YuEEG1AJ zsKYVbz!|k<-uADC#Bo#O-GsyH2i~)V;m6E%}%tcJ}d9Q>2f6dsy1_>cxwe=YveplOE*;w+RuV)bZoT zqr(5fDYlirc%b*?8|7*b9f}QE&rP$}mwsRpxY}Y`Z#vZy;h(*liLrk3>B{KgB}$W= zeN)Ud8nSy$G|CS$PHsjHNz8Grdh~U)wfcrrbm%%Cfug8f789dvijXFrz(a4&efG6k zb;+XblV@&pYmTR_tkPqKmEuKq(XG5iv+>G97FjV`;#kl9y5RDXrCT3cg$6@tS9k#H|mZ zyA*uB#wEOerazfceQ-(HT(0e|AH#w9n&($2Dv5XT6fy++^*Fqr*k4#rZ4N|`T4?#- zDp;wgOBVLEXDg4YUcZ~x{&qmN{nCv@Q+HZcD^ZiW#-Rv}ob1CV-!!Zdr@)VcePU}Y zo4;`E=*$=Ff5!dVOCeXJcgYNbYiu+emO<^DIC5kOi?;_j6-Y+m3~TV=`ihUAK8@Qo z;!C8O7==Fh$-n6FVYGv~rDCPxazX}?4?xpIaZ92`Rh0sX-8{O>F(|9=c&0IO&akKbcr`RHE|4~(=DVQYbuH~_=;BGqa90K!j=oo4*w+FDntP~OB=1(2 z60O-jT-smsz+1(n?Fm|CTVNaDV{2Nkx`oy!c;JQ(Rz=DQAE$k zjN1Jm=1+dx%Y`g;g&$Jx(2l?E!rwm1WE5r<8=B25V-gqh1R}w!2y2|7#|h2OYnzl79B?YQ@Vtg4+{( z?=KYZIAHYQ>q7}H6Rx2*EeJ^ONv^O)=il%nO{lK7) zjZ5WKnk$-?+VFJe31xb`ljv(m%i+9I!*P+rxIVE@*>`3;_hcz8_|8T>et#Tt!U+DT zH<8bnp9y!K2OkzeQI8)!%mGhS+4Vn)&&jmZaW(NhbJwK}Gd_KPlD*ZLlJbs`N*(d1 zD}{X{$lBQES0H*6dw7ynVk#ANqM~+IJ@DE|op!cNQ@U@AnV*AZ!hkzz=MsALsv6tq z4;i#UrJkR@2XQs|JbHBI+_?|<^&cS0^%XSV28eAwHsQ}ydXxFcZ3Yk1(r$I`^O;Z0 z#NJosxVo;-XsV$3k-XSsj*;iM2Wy4gGNx}H)`N#z7}8lC)(27xJ>2TJt^L%?0}eYh z`mD;nkF?ee4V>vM-Zm8j3Xj8RT; zrI$+L4)?Bp6k{f>=baOMYL~CCPoCfQ3L(p*!q?8ds;BK(9PN9W=Cn77K8iBbbK8>B zUHE+jVnc(y_;$LT2`?>V<1V#izIDJXrh{FEFKS!0+zI!0?u_RRy)O@}cBJ{JcSKdc zIU}%!=4SEr8k*ap=4mnch0=y9?<{QxO6P30-{~*mcxEZHY|CN>1Ga(AxsPi;`zJi8 zil($oa=cdekT+RGap(Ns(^k1o{Am-HnI3_!{EkzrA|mX!9LE4zpni&AIqMt}og*P6%YDHQm^gu`0ot@<>U~oYU`Qh|lG0 z3Du@u_jh{V>n&*hTyUp;%yj?Yn}P<$a{ajYdyn4VNlHRM%HJX^90YykvRM@sm0Iwk zQo9vEdb*e0Vq$bsH=^aM=?UAPcpzpnYiUIR#56SM5sj_;QLp=vb6yn6<#!NJfq^XT~Rm9X}=S%CXnMER&&ANUWmk`<*lX zzPLK(Ty`sO$l$U)`J<{_jcsB1h2G}T+?>h8s+>Q#!jWgCI|Cj^4_^~|p|~>pyTd&> zr43ZNUe^LnI4+Lbb>y%*w^Sc}kWqX7w6vo^1m~u}&ADUmrkxyBH>^&Gbj{G>_m{eB zeQ#5*rjZQmI=fX{wUqX;h^sY?bBFIvy>Z?>*rGGfN{02xNejwlrTJ9KD%jBg;zBAVz1BT2m;})TiB9eZz>;*5=)H1?Dsj zkt>siR1|DlJlT6Ts%HeM7ULi0qNib&wn}<6Y5dQTD&i!`b?3y($ z@jemp?milhH=aZVsy^-ics5mNl})8mRr-za)n*+lx%<*0gG981(JRhw$In?yQjsZP7G&}EmWohc;i?%C|H<|=g%1=4>4;Fm; z{!U-VnUAU0M^ixZ-des#hs@hfSm@f!)V;dd{PNA(MKzbX^kv2@3W}_2=56}KMd*T- zc$AhIWGf*#Li{&`c8eQkjHI-2aBv6;|J#IU?v;YO&6k%q*#XIo1@&o8nve_f4cs|#Q1vuPal`* z@c6lCi|2Oi!u$Z8OZn<8;<2MzN*m2r2MF=p<&_M!{E*dda>Ld7Sa9QqkBe@dV!l_C zz9KDB%uR{vx(=V>k)w0ZG{eHh4kyF|(G^tZ~?$qxNi0(XnGru{Hwg zu3d{iPZ%&pKQAh{8Y{Ym-oL|YSLbK*v&Y5Qjty*yvKQ-AD+D&&eBEf7=H?Yd&hYyo zHu0_CTvoI0=!KH~TzYSluV=qe+u=Xam!+Q3RkqekFlj9t0ojUOv3yST&oGEe`wY`D63m*P;3zM)oo-gNd*So-DO z4QEvnmxu9rd3xT-FG#yxQ*(c-4n~ublat#!J1Ofyx?|)CJx`IoWpv}AfPUEfq-({(vPMDgLpQcbf4yOEcY+I$}F_SU-5B0kvzsuxak zX55^0SM#Fo*+(nq8+btJ=|%ozb3f53TC=Im*=8K6r83tgUP`(tbNbxD7-+O^{u&EQ zOFtwgKyM%Pd!6QgUmkpZ#Id5uB;jzC`Mip>tnVqa0i7>(6k!^)5^r4Cic&%hdUteE z4cG!-tzElSIQe|Y^gQJc5d+K8s)4ITQ_C|PomdoQOSbb>m6`UkP*b^UIVZdbh)>-l zbt~So;GW!Zy-%B!vo#bXo2_k@5Bl%-JH;%)?bk-N>wMXlf-vbj_V&XvHUjT$9A&&q zHP32^-JxDYeKVF`|77;v0RHmqcjl=ZR|UFHZ?VjK5%RYk*nQvlu}oE8XqS3#*j(1k zp(c(sfz;LMw0=5{{H2dnK2T|DWtAJW^m#b&|JBjnylGW9*E&6CkmH(XTHKlXnBjf5 zZF#|E=`xpnl-E2sKIq%VZ%p;6u0MDpA6|g^YnViyh8KlN$!0G1-^bZ!7gl+@vTmZc zQa|p7Z?LZRg9mOcTBYOf6UxtQUj8wZbB}&;L#>=opYEkfw(xL2NtdGCl%H56)5KoC z(r{n3+Wi`Duk6JiGec#X=I2bU&ly|_{#GZI{^>-z*cXLMoUh8tJ@a+gUhMQ+r`T0Z z2~p`ApeSTalI-BqPme-)>C^dp5(hwyj-0v3BBhNw*&AvzSamu1K48}HAaiHS6B65wqa(_pb@ zee)+me)A@COM!pEbg@rn_GP7{R4d^GZVhww%k}Q1?er`muT9x@z7DQ1Jis5RcfJkY z>ZHE_FS4Y|po1#Y0D90~3{_OY{E^VQ(E3<@WyXqm(pAw{&+)DySeOqJ(sJNlPo; zh;%94DGXghNGsjl-3-W!(1p^D=9M;UU_jB*PU-xxQ)zO=6e3i6)h(CBQ z*ts)a{_#A>TBkmk1B-2Pxcu{IFa`W&P&(yiXOxc`|7l3mL#+Ij>+ZWz+Pdi-c|&6L zcp5z4STiqq0uM+?-G(bW$q$h*`llci3R}^T)1yG}?;<$*S^{Agh*&F1=prNNvi_nl}{)xYP$!M{{` zH!hY=g&jVn%4pEahRb$XZ_nE$n_vC;a;5Sy@?1%eTTy5jko*fa*6S-#GtCyY!=WDLQz>gi0%@QElA8 z1V515nvUgFY1~d(vy#i_TXVFj+>#qwN#u}+ zRcxQ%0SHV(O?~|I_6NX3d>{pO;J7i_z-s{V-t6(|$R7V*IKS{fLu(<#AMDl4g6p4A z3rYJLy%A=^tn=scf)G9(+lb|g_`fRiEFs{BtFk(GgGMXVHY6>4KyCq zjWr$^%-joe58Cp?64;n2D2b`KbPmhjheTC64CZ4FlEyuda+hY)vng8cD**-W@YOiy zkh`|-!x$GY7w6iM1^$2L(P5hff{BW%+$4vZ{XMc}ep+V8MvREDn2KiB6K9RZ7;c1q zuTzwh#G=KK>$b7qHFiBM|GiDoz7mIWn;+Hu-n7kboBO?Pc34+rqnFiym&fD;F$wE= z{#NEOOAHH5)aozew{)t~)0x&PG#e6-bCLL6-S+5svC`6~c{U{^?3FfX7Nk#4*^1Sa zqkJeod_bS7*~773xMTVntIP!Ikgu^yo!0XggjN}4BJ`8JYxCEhLY(Tzw(7{7t|Hzo zMRU#+k(h?Bus3!?RtgqO%H5Ytd&l=ojcyGE$GI5kDt+53x?@NM@@JkI>hM%su&btY zz1?J9yR99XQbZI{ted<&=NuXv9qj-)7Z8y~gfkOB&L3<)Dk))u`l-na?Vsn2_MVjiE2S5qnYcWCV{I$=uP5!?&t`7v0_(&5yfWr`H)g&Z=DY z@KTJq`$k3FmeajvzvUo868KETnNQEQXt}6l%(J>Abb9@ZkFMMB;y3U7cb{JWyYl?F zo6i=A9M!fj;DTaqm1Szbt{5mKZid-IKPQdF|TNVuQWYGS8Ry%N);d9;Y!ef--uprA zU0KkuG0IEe7v9yNEvXRKz0g0_(VSIr$BKw&lnB@R#oPV#ZOVw8gY*4Mgs5(50|OdB zP-v?;Jv{|4C1^PYyX4|rx_=kdAo--%83u)Pn?CbY0*esh%&&`Au8VP2->t`*&zpXz zXK`Z977e5RQ1>XA)a(Nz5_+B{!43#CA4fq+u$m_moAG$SHHzAI!LHoERhk>q>L`*d zd9GP-BaL79689aO&VTA}5kdZm)-d8{dy!r?0T>tJLYhxZn2p2d@k0g3c)Ok}e7K+Z zGvGAe`2R8poL0h5xBF@I+2oQ`j_hn^R5J`ZU0&66d{xRj+I?T+6E*m_*54QD$uO z>-`_>*Q6M`9aVJHGq_QZYASoTg}Q7|X&kB^pV&c#P9LzcnN<~?3T$sr*Y)I5+PWg! zy1qyl+`@)}eWtP3$B$&GDj+4e>T_gj?_cR#^)r@QFvkqk$-usb95OvN2x+&hx%k9U z(QIB?B9c&~XjVmUKzWeej|fS7F!*5dR$Q;Fu`v~Nd;vy1IvfH3I-}cOfle6k8MI;; zR-GN0$^3nN!Z|^q3I29NV4vIhG^dt5kp~rB64lH^-{|~Q#f$7ybqmu*bxX)4jxzNu zmq0MZYtyO_70sjY-q4MBRg~qUOE9B$CukL2e$*md*e&j~<>3=#T6&Yfn)dzQXHG>k9js$ec-;m{xf` z4xj9Mcwl9e+A%R(MY%Rlb$+E3xY;UnNaZfaan+QiL`TkRk3_b)9&biAlf?Wpz4q*% zt8i6TZS3s}2P2-Nb2s#54DPcLEL3rob#{zE9S%0VmnzaK8Kq`|{W7pUVN6k%7OWrx z9E$6`Ni6b6aWC-hw<5mh(e*P?tDr*gjZw+MiTU^O56WM1(4fW?KLeKrkhRskOedQK z;?ww(E^Nz}%r?upDm13|XEAZ9T`3SzW*_=?K7RJHtJBz6TfxzhCdb6?t=hR-3zF8E ze-9E~h%N2oIVnVM!QV*y4+5z@IWZ&>kXvR@Y*B0JxIHqt8?q|gvMStH%CDEpJ@6f1 zk3$X_mJS&V1)pBj#ZPfNKHnoz%BPfe{u&G6TQ8q&N`4S=nO*z#)85lGB_^f3*v!nD zvIAguiGEYuGz4f?AgA1<_T}GAs8hTQViyja1y_D#{RbL*+`>0z6kZl9`zY(yk9_R9 zzI~==Tw^+Od_fzOK4572)_d{nK9(=&_wIRRQzcqTr)R!=tkRo*qh=JhmNn2}vj$gN zRb=ZFa<^R*2dU{psVC$4@&><2Z)@bcm*C~#1Mb1m!9kio7PuLRQXj*=?cyY!Y2 za=cZzt6b))_2fkOO7~Sn;>1nqmzWIxY>%hh6=i>w1n-;fB9AD#>$c*}#ft+-FUR45-OK z=3g<)ab8$wtgG7z4lBZLh@Yb9`4tmo#9Q5zo}cfDf>WR3hb);>Z~7o7r%Y8x90zKC zUlj_C>A@VAr3UYdjJRQhy{JET-FJr$HOfV*Wb>1sTVK-e4xswnGEH>Y%MUQXvJ|aJ zG3A;s2cQvR(V}NATLjB#anqIND~jBoWrUkEWbFP zh_aD`PP858e_vl&q4&jz%8syRa6g5_XN^j3Kpb&U51}Kd7e)-UL1oMhaetR?V0b>xBF`sh(2)y>k3uk_m(p^cAAnI@8JoF^} z#=H(^t74H{vg?Br>c<0v^)4Gim~NJBg6p>I8#iDwXOT60u1kwoquYpQw&{+WfQ8jC zea_)UlzaE6e_BraKZCU@(-S$0%Zmb$Zc=UT!$7yF#QF*)=qq_*D+O)uIIhC&*r*G7T#pK$ei!hbZllH$Y4n11=jf|*S5xuQQKbA6C zazd;nxWtF-jgysS^^3f`ey&0qW#QGkch7=Ok_Ob?st!I8Si=M*Yp+X-w8hrW&z}S? zMa_|u);+#{-Krxyj;=vH>(CSph4+R$@1^J4_xovUJZX6dW9|9Zok@&MYxyO|}x=D0Abo^~Cv)Z9>a($rml1mMooA-fMT73RXo2kdP!A_0wlF zzKPaqO?+nbYp}n|7ILA(@t-NVd6{8ph6DQ-$xKT%ML=j_3QYe!4C_5uLOb+EfAcPt zmC4@tPto`aqSFTg^Ii>I#LBJyThWONkR6Jb5;}THRWqn0;X-y;lFS~@C)aPjna|fc zvnmfRbm>XVd>*p%r$jBUo9$UY=0KQaXY5*|=gxT&!h$TP(5p<__2&yjm_sem4Zq)` z)<#bU59F_;hqmr+{{1^Y%8FI3CrQEL9tgHzMNL8dE+t-Iy&w=EIGWC#;5INcKK=#L z8{=pc2`&`a@)w`88ojyJ2G({hXFEB~HjQ50VuRJjT=K*^gg0LxVX5R2(|iCOMLXvc zK9AAb?tzPicMx5~%>xMUlY{HgF^-&{ zyUwhvrb`zP7q|2=vLI+oBs4t`JkEhHVgjM*ROYVP29P{M!5IYmI#!3L6C;zg5Aqxl zBL=bfh3rtL@2#^XYmHtPM6%?3`i(l7tQt~~C=13Y?KY~R<;I!uaf*I*?2jTNQp2Y~ zTCrTMX=Wxy3V0cpE&48d*0fr*a<+<$IRXJ-)Z&5qqJ;>b5i{>uNmcwbWpy#k6Ie-d zN$`&>jtEwXxLtm099JHfe>fX+|IcJLp^Kn4?w~)mjx2sQ`g!lCD@GT%=Z5!;-sKY0 z(gv}4g);s9%)jD-`YIpTwMe=@8YTV$SxF(qZjJ;od306Vttqir(XK61$Wn{~*~!~b z97`qyj8;n?$8J(-VH0y!*XEk9leg|&Ldz@A-3e%Ec`EM^!H$0eNoM(UX+t0SU}7{n5c?@dz?GpvcNFGk(god@$0l4Ki{IR zRtI-g5nbp^RT%e^nY6C*anHc&Rldd?-_PULK+-tjjfJ_MqSl^H&X2NMM*Fm$b62BC zARdp7YVUl20vtAXbgZo$)^vTC~=Vs8{>T$ki5p$_d2VyZr11eixFk_Zp_4w- zGRT0J-C&4^lrjH!DgT%!60^$zSu&#ebFKn)3U6rA%Jt_cElI{+V!}rqA9JE-lNC~# zO7%*6{Lxb192A?aoyQexmp^Xl!QsKpAXE0Xl~@T1XOiTj4r90x_$S;OEGzU^L`k&H zXGa))uhed>WR1b#8YTCo<6wUHU&Gy%f;_|j@9y7U6&8JYAZqWaH_cpYWAKE&=o8zw zvVb|O^BZl9!8skRBI7L{eBbwbPDhvVtO#AnkZMWpqFaRGrmhXf!#|WvCx@@d-Q14` zImecSz?Qstk^Hv%dKe`FI8eq4G*D!brR6w(A{y46-S#WYU@yhyx@OQXc`us3T;BOV z>+T;X+qvo?4&C;ioktoGtrNz3-lE8Z57ASR`6tPk!#Rx2`jxba)F(x>C5Xd%i7N7~ z@rr$gJt&~DfvQt)tQ8yRpv5$;6oj|oK5r$nTUP9c)3 zcXYmwj;$&M6L*k=l#GmNS+P}h7ufiDQPw|(7sl`vR_oBw9f46p8ki9up9!{;$sbCl zk=xhR!`$EFT+(jm_oc||%xm}Wn;Wt+;c7|5 zukYKCfM%!s|MZeXDtS})*R|Zlvh&Y$gcox+vTLzE$8o@$X)D7G zDtCu;VKCfHoCeH$Gkd{{n=MvJ0R^46c3&F&7#ch_91)5P4D_wAp<3u9HB7s#GqK}r zju%hE&|(KZ_t^BGkpA$AM$F!yr3QUCZ(>OIQWjP9i_L=g{0L~pPgMMjRy_Z6b6q6U2rMIE9*`fTB{%fXUIuX zpLf45{*ehDg`VKI71B_@XVTgjGx)ueRI1OB$G%!xD5N4fC82M!&8VlZk4{8{RMms)`M=L4+WXh~lfp_l*;;=sQUl;Z2)z&pRw~9q0DYad+**sAwt-*?X_pSZU1U z({wJ}EY4Z9_kDJS#>?r+=B^Y-bmZNmTgNoLjrzCFJWa!a_yo61DJ!WCKI=~AiJePT zba52qh$jj)4254KJ>#Qn)xtM|ymJ<-wIjbi=EdwOF$~4^JWv?Wvc z39vkr|7g5u_8GD2)>o?N7Bsk5$k#6M9SYTb@za1`CX0?Z^Yuhx&K$p&yN&$^5BNO$ zKY}|V&EbwJw>@%9OoYKi#ne|)iQOOi+%b^C(A>^2o>?kGB~d~vL&F3sNs1|Jhe>M( z9f={(&$Utl-9hs=6yPt-t^6o>cE(o!K4@Y3wb8mE86PpCzC-7dd4K0pKh}+PKlIPH zkb<;D5d?h3W%5knQUly>o_xg?KfeX+`A3qR4GHVA#Dj^ZmIGMtuD0{f$3`}7a>sVs zRw1}cA-l1X@)CJb?Pmc5rCdm@LkKq>y9UWrPd%d>5DQ9?iXhm)guyg+h zxGD3X<}=ZS6-JvvxU3g0lu3gJ4FB&kk?_I?0h3VBVOb6^)*!g~9AGa%XD#sZJq8_> zy1GX$fhm66yy4Du>q_f4b4TRbi4Pn~pn4f_k;WK( z$wOYhEd}!qRrcIoyQraa>mdddRsX>^_JF00paap@1QYyKjrl|f_}*QKuKv`M5eV$Q z-$+pJU2o~(r~V*!80Pw}3Y=wQmCWzQQ#dVX6^S^!;bq~8{EZ!p#<+kgn z!hjvaNNgq3B5MS@E9=z0Q{`Miw%fI&Z_i`1?yvA`2-n_3F|sw8B7}kEq2o6J5~8sL z1tR=-VN~#5qQo>N8p^^o^V)q$trueVquFo)g~Y{?J|^CrwwQ+`FoR4Fs~Y*s16f&i z1~x0lhMjPdJJH>9V}#^*c7q9J@6a-rp$%deQ5MPCh-^|mZgBMORvp9@#_%wV0g-|f z0bYSf%@5RS15}*%>lbU*+uKA&B$O>(Gb@h#zjrlWIri3jMR;RG=CV^ni1%bW<461HncSaC5`Cp8(uu4?0WuoVP~-B^w(V95n!r zs5^-5CGweJ>)Le-1#|;`GvF4&p;2%WAwVM*OBGWAix&sHJs+?+4FC|xO)TA|J2xi> zgaI+VPqV0F;^M}l-ovXN3L_#(WUPkvi-=~5N+u_t{aS_Kp@6I98ZQR<$SZ{63$^`g zXG(Kcy7AG+-ulYk5q{vX1msQD;9E`?D|U%LnkYKySDx7(Dy!Efr!X%xM;z~I zflqPZQvn;-&LIV)1sT#3@JX2vp@h_3zrwJ(p5*Cik;_nDe{JgMXw^eU0;0FaQ0gT+ zYs_k$V(Dn~t>zhN9AQ;K>E%P{=9L*2 zO}~V8MQ5#Hm|xkK0U~vZ$gWxaC-GT4#2%`QrqJ=MHHAdk)0eT68m$fl2;h+7lPVuW zq-AI^;XByQ;T4ub6KrF2<4ontz?(4Qfh0s8hK zaH6m_Kwf)kto?y|yi)%4=V+IQQ5kGOVE+15)`>H)T6E=g1kH3;e zPs0Aat;a|l^>(R~jB-CJ`Xj0rQB5j{B8Y9QzasVcmIw39gD*=LE4DVB zbJO7sbqt49ImoVk=@}&)wJ9lxl3K|Yw&vd}?a8Z6a!@lG5hY$BrTf1_K*9PD3dQqA zjC}NpNID2bV&_OCh51g!95!}0I|He5yu#|x`@~{#aYF%ah*6ee)05UA#wNPY)Yb{z znv@EQHdIwaQnt4*VV(m`HIYMqq^gW42UvE_1;`lL_l2!X7Ok%^!crB2}b9@V*&MN@jtKs#uq0rhfQv+br($+T)eGy9mHg(%8UB%TmQn zKQvfaSTxw{(f(=Fm5F@Yp#Eiuu$jy3BRDWX6D>;7Y_1C2^=D?>U<#Z)@fNl?gTW@+ zDGja->58>o+kO995MBJmcOnz4nwcXHwf^nH2;1{Hv_1*naqOV74D zfatWXT|xoboJ$Z(p4Vf5ufHhBCGP2Jx1kq`=?~YQ9Ask#h5_SZq@>_ImRAXk&iC|{Q>EdP<2(-#u1y?3RH3vxCyS!7?puFqCgiH+S zNzSxqB?O^uCX3N|f{gK3A7@E~z7g~ndaaQGzu#gYDhJ>ZQ&*RP`~UyF#oX02SO{UD z6WhB$rwpzEp$|@61Vg<&x zZ$o9}aeVMm0r@D(pt{QtcKhviSz=ae=CasO^6a4Ti{rlb@cyO9QG(7mmryxOhtt#9 zSz}}vdxqTf+^o7QI^COQYm0dKr24Ju336OqRYCC;W*H=HXzo+H@uK7CisPuXr)bMU zAX*WdcZ+YaadBzK?enUyh%}n0XqCK1*f*LdUEJ*{h`unNcm@4qEk9u7Aw zWLcS;!&}-ow9aqmKvqo-K$TGp_prKwc1WC7_n-X}T3Sk0U5e&8BIKk|P#l~>1ZE>T z07f}@atkL1JqcsA<5P6?G?2ZMIG?5H{I))bsB^_mE1EOO*H)B6|0K!0yF9h}jIqm}nstjht z4*B#qJ~ zg8Wpi5ua`g*RF_HLEG$eL=FNKQfpwH$j-@)p~_JDB=giFmw&iPFjMqVD}WrvccG9K zvEn?coxYgWRE=1eXtLr*P%y;|Lxvj8olKt0S|h{1e9%H&)g3Uk(zWVfbY9CHFqK~> z-n{AN$#XPm&4EcZJUGB3r8I~|&ye;=>TE=L1h$nrSf-+xw+TbvlCJ(;(`?ND*@x(w;p6>3eylm|a?=E6wIOQZq{3DR@qZc?+xbeoRb`C2j zPE~wArmbB%cdH)U(@L%qB$SCgN#zneg)b)~{QwW^Qf8DG_YXI&mDTVw=?eBlIi6+N zqfVY-VwiP7h+6N!8G%+IbIrRyp{Urr%IW}32xcS}E-oAkco+i3u(P8Bgn^zJ8`FcC zfo2FSE#T)pAO68?1k0AO=ss>1_gFTlaz8!J{IKt7!ysz)Txd4Eq2e=nhF)(=i%<@9 z$n+{@Vq>EKdFfy#xIC$DEBoe-18g)$QAqflga*qd!1L~aT3Q0-0pPr{BmpZTbsc9y zfY*EE>9-7!T&AG6{Ps=GX&k&G5D0rvqX5y(ZKnhx40_OK#F;=VAOMBO!9U>LgUA>} zhaLFJn;1Mz0FuPH2nXi@2HNumBhWwu14yP{aBdI0!UT^qBg*|#?F*&irF$W5SERe7aZYV~Z7=Nm* zWmR!tzKG;XgfDB9Vj`5np7Sn={JQS=4FK>C55EOcU+HNuYyV#f##|I|)n39+MEnOd zGaESz=$0|zzBS=(^Nwn*AhpILIlrA5xK2+QxJK66!}^Kt4<73cTd)@EJ2pBSg)sY8 z=J6v5ANBAy=*V<-edV#|E2A)>Xm002(F-%YlYz{c z(XyA|acOPpWYy6AQT=VFbxlmF6K{_k6SO?YzM;tesnDOzS>KU5ygWxbMMW(h%psbB zAv>!dBJSb?J=e|hW)7Wzb3}%I?r%t_@7zu8RBBF3vKgiSU6N94u}eOnE?sBc61{|w zfB3Z>s^Q)kuq}Y9@x_Zh&+{7Ul!0+Zf}PgZV!-nP#AaDQiJI!DXdw-3TYsVVR`X|C zY*~``ukC-raWUS*U|Zc*lsx)^u54&Xa@}U7%n`D9LT=E_&Q-XUOB{dPt{59qNlm4~ zPF>8IlU>7Ly-=-sEE|c|A`%|_D`x!=rUld-SN))C`Y+tz>DG0#Sh@Yu^WNUxU;X`J z{&8~3jljx4(+y@~pP(i6rCluO*L}eAUjwX?Rd9vxo{E6jCmb9HMiAb8dKxFhW~K}9 zuS9l=tF8*)fl(V{1c+Q3C!b)=lM2F1=kr>9mO=eTZyNJ$^m-l(-(5FB#tjUQ&MkY% z&*z+Y+u!-mjSfa01w8|W!u!~d?pG&!HZEolz#$O}B<*RmiYDspA@`|vaGzh`*BX3I zFKneo#D0&@{&R}uUeBH!TK4(;s3^8Vt{H9bQ*ZB){4(O>Jh^N6H-8aqOVTIl2&d#H zGiNsaF}Qy90w?=ix#&=I2IX|Jg10>Z`bZCZEcd0L*6S(DsffPSy`4(Yfi0)yzYymw zb4^&}^v2H&&wsG(>a(le5V73_=az^Np&1MTcP;o zB!j4B?b<@0+j(G*%q08m8=dPL?=MUnHW)KzRf)AG)2)A%zXzLFgG`FtuFyJYQU5a0(k5+#ha7WuC4>6WB_dk$7E3hpk=wu`R>&J zFcn(`A{USa*DJ0zsymc0+rBgk352319r;N6gVI^Tk7DDE;x|%S1liaJL7~`#wgM+r zRe{GN6Ka8b_ai<+C$kZ;(&XT%&eD>XmW17%S>LtiqN+*yNcN*}DkjCx;<*ZtxOnL~E9^PQ80vGH<$_qMprV2a z82o zauX3T+I)jv&DHYRsN)fQrh{Q{bv&l_IgG`THm!zuj=kfja#D|zU~QALp(aYN{Z*PvOoW>0@Vy(n8sf4>4~O8O)~ zP*hMF&!wBzGkuv6h%`3faiphxGSkgXiR|O^&yz|~^g&#LLd_9&aT!Vs@i81+J-@!1 zY*^S`7CI=+`7?GopxiwBVW5OB;pFr*M7TJJ6KQ7zYt6dAK5(yLx0a&vG3|97Sm8JS z&#L4*W@!TYGy#74K>oQ$i`b|pkT@0VwWI^{#v4sdIlzYlEPi?>CV(Iz0Y0xeu7=Of z@iTj-N6Vc+mZJiG1mI@jJ|z-vUjU=yGynaastizV+u8##rYek3K@Z@!Zv=p@+JnZF z>f1T&dM{mNrM{`S0TznjKYKCtDTog^7l0RFvfh~u0J3YfIp3fP>x0@23^Bc?UwKpn8=4(l3(^tpcgsVK@JOBw*oUW0okRGQVDTKjuaoi`l=Qc zrD^37^fN*zXhF^&q@!^QpdBw(Dq$NpHeh?ngRg%!f{>l9*x;@ATk~#za{V@=MGQy8 zt{}<1l;>g1zInNAYeTKAs@JAie=o?uc1VA6p}@P{Lj79Nn=VYyd@O_iCr5-Mk#tkp z?7L*zx{Tz^av`(RUT$+W9+VrjdbDMDgW8L8g~W{8X;NLIWJ$W$(CDQ~^gSJBOGc&M zY>t%rn{po`S zy+DKC^|s<*B_<6GqF$b*u$h#)l*Um#3hE9K-(d&W^yhq*SRTrk3!OWh4dMaW z*#uv|Dxue0-co(|5NdA2(YZFQXk|rOQp&4cV)C=zW#wbs(uu&CyjS|>N3lO^{H7?j zy}TZo!G)ws?*<-aTD~;2>un!>mKcYI@9>fUyhF7$5x@n$lsUee-L;xM`}S2_o!`2W z|KS;NS-1Srpkb&h5$eo&prMJ0DcBZ#VQR_=)lEv~tr z>D79kU5OTE=e_?%Tx9Px^`=|z8zJ!~FREpxI8w!g12DQx9J&tqGbugxDVcT2?p9aZ zaOdtXq=bHcf@Qc)9PjrI+orYXJ2FV#456pr?91$q-}wvyN>h3&M8G;@3JH=10?w;1 zWU!fnhSJPIGA<8WVI(44%&pK0>~6u=bwFcXDIE^UII#1{TMTxWU zfkj?g7f=dK|K!pr{|=pNg6oxlXu%JA16W1M;IvB^fCQV{+Sa9zx~yfp~w-2em4YPaMak6=oPyrb*Ol?S3ESM_zV`et*0;{z`^+E##D zCpsfz!BpF$rA)_U7qX+}@&Bua8=Cc$}b{poLnZ2^>1|`OFCUDb($O zCLjVXKRn{|yX2r>jS+-4E@Gr+mK!LsyCJu4R5mpG8TX%hFfU}(iCN!Mo7yc`A7tQO z-DmL>a34Pg70dyVQH@{A7jlYZRycZZnoECr&Yoa)_V4Hdcvcg1=V83kJ3%!wlH&;z zIhXxBf)rmK2a}}w8ohZqp8aS#LwvFIO|d~!k!H1ac!4#wv5QZN5uX7wXuY~ic<;z0oA{F9Bh z7T@40q40=00ys?CLxZ9t8BTq8D~j3iS&CT=6R!hC_lp7f+_QQpDC4OreswOR<+;Dn zSR%QFV8B%P8m>7P0UHNLM8~L%VXRSzY;Y@uRc@SGDiu@2{>x-BMgDp+dz}fj`yy|DHOEIDww<+2aF~-9ikc1)&D78&@xpdmX(MQD?SF$=y`qaZj{PS z)>G_wy{?=-wC}#DQU5=UpyS5i+JMjkJ#D6IOL0te^l#H9pjD+hy*M>L0)m&5-_kfs zF0MCg836GOr~+`LOr{yYc`-{4EPP<1xV69ZlQY&oxUbNI74ZeQvy2! z0EjB{;>D7^FqnOEOG_gI1D{&gn9|ZFpZjYIEKQz>84fuXRj>G_-eQrtG4b#~%~K^a zdRuO)=N$fw>Y=(X2&D1eVp;Lj|`U$3A#QqJY!ck;FO@1S@%76#=?0 zKQsi@m!FwVc7IMXri(YGBRZdPtRlpzW;Ej_DC!vv?OW{(K!x;#VQ>X*{YF}K7uS95 z8uzxoh=0;lfAObC0c1ketPHy2%qy`tJ4PiASw2PMpO7~6Fn`f7oGqWW(Hv2?3sP0w*g6+KrT$Iq@ zevMN1Pk8SK4=>n#Ds6=%J-i5&wFR)PBm?#T*T-Nhxi?vxp)C{10k6YFP~fVg(Xlb) zsH)0J0C9R3v{5^^FSw)*7#IN62lhqEr>sZE$19Dxu>r>3Uct*t9L|b^yYNm&pgwiQ zkhpK(?19{&(sr)?FN-A*O~P5b;0FOU=Vy(J-30`0IE9-;7Sg!{r>q6h(b3_Q^32T7 zz>*-ia!|KH1z=IYq?k5Hh+KFBW8s^n+EP54ECXW7a3>zizorj zUqwYc5!8-`o3*Mk#)Lc)Ar-vYHb31_*Uy`+Gn`?_`bi3m`yyr}3+|>4lXu-_cB|iL zSbp3q$B82IcD3%iw2w_2)jYccV^@silOR17=APsZBwC1YzK-z2&UA*^jM?ERf9)~y zubq1xJ9u6Azc*}GJ6rEqziPypJ?eCo{u%?HZf?}(8G`o$q1kC0vAB*8W4_=!U@Eny zlZO>#xbE6I2v*wOQK$`F`cGH3x@!0Pk}?TCTv9;M*C>Y3Wgd#s9*NK%y^=AInG9Ag zrf03BiWP~@G@AAZWH}r`D&G*l`7ObnqL`@2s9=h3T7?!i6+UL#W?HRZ{h|CriG~dk z=mAqJLJk`XA2Vz-tk$nctk6(MR4CCOHCRN2w%WPbH?W#J#|=-{lW*#pkNPdIFvTPY zA-WpSIRj9M1Dwr=-T(qeWhKi%!L?0^}?l30eUI z+HrjOVy5`i+*Bzebbbam?uHNC5J4k=(b=`^>}ZyRw~nM3ti-A<@%kRhEWwM z9rRt@=AkdMc)Da_6G^fd$?!e6CJB*LLS+xw%bOruw-P@6mF2sbGp;NxuDU{e7paaz zB2~ys@duZ7sLc-zKn?|NVMO}!473>60gFN%s8U11MD0gWBxZu)p zL{X@kTzH%mAou|2m-E zvLp01;U;PXc`{)Y?$NIBdejpTXh2~Y2`>-E>8-%TWLVlBoe!gkk2^kPZ&G~Zi##ya(18M`Qo?>-9 zFzy!WL%X7rl&Z*h$lQidI1)IxAf;XTCA*Dt`6P{bdnsx!<`NZ3KCes7N}I+Rs6uxy z^=s?LYLFzoG31qXUPnjtHKg19dsmO7JP!MM#lY55UF8QQrO1`sMyGZ9&P-IlcBuhd5@$0>9M^!G7NOt+Qo;D2StgcO-(xl*YW6n-HdU`-M5IA`&^Mm*fmD( zq{Qh^j~*~-Xvvq?#Q)m)^XhwHA`s{qv^{*x*@)ovcC|GpE2%A7>f4N`24PJ^3owv_wP~g)(vyu+8l5C!XutQj>)9Jj-={%BCGi-eV34C$djN}A= zbR#HPfgG?gll(T4QZ6RKeoxm+CV+Z^pRHS=S|n%}8iCR|^*C^1gult}`@Ga|GUdLE zHy<92?a+|ezxn#EyV;mHwz&J{qZHhKUy|;yiShV12iErrr}P5Hmo6!$2J4dY!tTbt zRbZ_-T+ZJgm@clIZ$V~P!nTs`TC;eFf<2>F#(H!5(_q$fcv0<{8kBDZws1C5ceC}L zzm85X$lXzg6eX=!nmF>s-WqPP5BnTt^*-te%Ek8N^GAR5=n>?Dv)*$f)KuQ3cOKD5 zpgO&pr%nL7dJMSc*ThF}nEeM#jet`MuGIlsGR5z2;q!8UP|PY2ty++A70*U#~{qoeO6ZVsh$6+%4mSAe3y9VqXT zfb|5fQvC5ISn5eD9CHeyZchb<=Iy~`2SIXt004)f1*#?{qF}T?4_0y%YCUGAsV}5b zs>{3Bh$db;aCji}&h~SvT$5yw?)mvu%?5Q>fy%@3kBroRXcS%hsRu*n^j;NTuP})U z+q^^hH23V@o6JX~*at7P#lk~sU4z8srCVP*QrfMn`Y;0QuKTd3O#e(W3xa{%ZWG$< zcXE#%Z*<^C0RP{^XB_y$X7Ny%BvZjtw78lLQ$hxr`RMm5QO?3ORn9Y%yVJL*yl;uW zraMU#k|CP^oE`jOVQ#)Ov0mvrH1pVatzw1_MSHL8#6x`U%JYgu5)B#qG5T)DTJ4)r zZ2EZ$V05S>4-<*1q`oIv*k_)g_uU0*oAzC?yE@ZX9ami2d!8zGX0>De5p@>Yi81~! z@*eY9&>}8)e!0582}*9cr5qTkJ4hfSm%m9e`wF1o8jMO(TZ`3rW5%>gsa0~q8`ho- z4E$i4R-)w53VEsj_BVPE=Ih@1TQ;R{3t z|CcbYT6QGM@{Tl8eZQ-P~hUBRb#`C zR9B&I_*TP?)1b|pETwZY73r}N<{Wy5<;UyGvzZikS84YK8;rMxu#?OXg% z{qA*zBG}S(1H@lPkFzbrf1h9xv%gE!6@@gHw0D`!&}LYrOK>OkAb#~Q(FU)&-7DS9 zFx*TdYm>tShgU%SMdSM^cy20xNj->{1QV!-8=xzlK;Q|M%`Y)q zrj_$Xj=(Ui20J=%F{C(5U(w(r;xu_J>T@2? z$GKH2nj9RpnqMRspZJhy#Yj}@*Yj~&3(Y@PS=xD}93QD5mPhUmiSkH>TxRjYjICx+ z<>sh<#SglnMb#lDiid_B!6t~*uzG@$Leo-%KqBB^FMtlyo1BNh~&2MYB8+w zvp9k%5mZtL+I}x}-mxFW@t=W-`>H}+u&G_@x;5AtImx4K+WS$&f}Wy9=K}Ne1(Nd& ze!{)ieJ*7D@%q=bFOufhe)nC zQO!@@L4`z9sl02l{82ByIV!raF7(MUK#iZQUG0R3t|%0GUu#k5dAq}u2#|Nsn4-a` z>qz^AUf4N26*V5p!xeQ(eV_P~`VMzPUGER$sp3hgl2ewX^ws|@AG;??M%D}nhve2Z5#}Ebyr@6FM17Wp zsAqkRW9*!gtM6oLSc%hWP3}7;;Y*+;k@YYr&~U0iC7F3*Vx?ok<0NFKsWjl<84Oo^ z2Rabf3DuScFvZ4u5pSf8E)sw8=0z<1a2Y_?+Vl<#aIL* z#;Z53^-lDB`2TBI)Rt7AWgIeHnBv~p~cTP?S(;c%LV^{ z1G`DYKk>uGrSNRyo3WZA{qq{H>vIR76op*P&w-<373eVVnRbCeJ6q`km#KgyJ9g9s zaMP!DQ+b3-oeUVjHNP#$`g_3oI54ycyzIZg?@e%>;KA=3!i56y{?Z||JYDT_k_Rd7 zn-NRgnag(5<8j4-TS8|8VxM|E$a`^$T^86QP%7hUerO=9D(v6NIgbpj<7|xBytk1c zZq1OK>8!)AAD7bUV#ob!jkt0`CmNs}eM*j6^G{wWRKIn&m+)1?X zZ>8scl#Xw?0tYE#-YMjU$8*zGi6nem6#+@<&ZD)2(VMfQ{8t~$h8Xv{AxAc`vC7-l zlvEY-)TZBCTA%=X565Hk(IOEwt$y!*%TaTASDq(tS!}Ew_*5e zaQ`?j;^m*MVDT+_L*=I-QXmn3&?vt`Znroy;$5z;e7H9!e+I=-J=x6aNb`Owm%!P< zYtrjbotU9yMk}&~1V9)FPjKyjPoCPyKZ&1fCJeSW*fRfa4l`ss>{Qbq`Y`pj*fmeT zhETt91K)_emHQguC#WKUwASu z>Z1`M;^+v+S9O^>*B;1S%87aG@t0m+SkB)4qR|-gYQo9VUEAk-b-HQ${Yzd+)C zc!c6N%rcsqq(I_xa3lg(a>KQ)VyC~Q z8xPwtKwCkzM}Itr7Thik$AyFQ38AM1+heL=8%P*XehZ#%zN~l=MpW&e`{Eex)tznu zI7;pd$GI=CTUmAHTpc$V?8>Y>j*J^WC8BaxGMz13 zf9g8y7aq)r9hH5obc3u= z`OXES1@$K`iP4n@<3Gh4s3LVwhvO4Sh6&sQcKj~2-e6MtNGNp_L{!syin4x%6sXQ70>H) zl{+8T$9n~Y(%upxKAuSL;uiJ_Hiu_#lDl@^V>RlIwT2_H39aSu-2WUQ;df*NSN9i> zy$`2Jn(%u?dwYBdw%#Bcgiu%){jq`L&^P6_Gm?gr`Z?#_R0 z?|tw3{xQHa#?f;eW3$$pbAI!SR>=>%k1jR=0S(*-5g&@eUbE>k=F(a}Il3h_Fi@5f zY2z5@aPjJ^sB@>Df`g6bCIMfB#;UzG3l9AkPhw5rilJee-bRR;m&&cRg zsE6gI_@g)zelInLwi(@v??qAcP(N;r_+WQSm)q1n8p1_hPhMtQ?3WoIA-+sWaW|SK z3+DdGBYjw--}P8i5H1@PcH!md6_(#Y2MPiC(`GDT|BP{fqCk1(?c6zI62OZQq;E4o zqt=7)-y$~am05z6Pe6rl2cXR4atX*70x5lrz`|G?7>VNG@;vs@K(Y22a{0XRrBGzb$gm03U#rbfb|8z6%L?sCfhY*kehG_4#|lY`>N zEpFCgquwamBr+ZWfu`3m#vljJAbuj}aoDNl!50i_GXOpWTF{{5`C zFygb1i;6Bz+DCI=6gvIYG3QYG@u{LbVShptezv1DQ@(`?F67;*WXvi~< z9W>29G@A?> z;@V|RcG=%NB&N1W^kBGu=r#*eF8U8VGV=OWalyjiWJoBZ>pgm9X-`it6*XMHSmBTq zWF#x-L*q)I+2t&0U^*s?Ar^CFD@vF_8YV?uk`@HghX?4v733x+FC9L_ZG@D@e&TU) zzL34Y^~-fUV_q5LOv>~@DFIaBIeujb)2oPNH}3829Jr-(#j)YyQZCG0W8UOZw`A=h zgH#~?Yx;jaYyX4m%~F~nR2Yr{!f_)_rAjKDI^oy&Jg!Z}B^nA>(|5~r zocfsD6}y`i`smW@+xZ|m)xEI;KiI`|(_GRHGM+zY*E`G@R;H;N={Gqk#=pqRInaA2 zXXU1VY-th+Ll4>(#IL^<5z&a+Q-!>gt1T#?=_FwPr`som0Oc*q=SZ(ZrwS7R;0z7r zgo3CDOy{VCz?reBsi~~h8TqeY1ID&Zrpdvk3s6WJ-r)%X`5L!+7x`e7%J1J7^9O~$ z>8A;S1{|n>qZN`k)}QO{%p4 zMu|!E!gAGmRG? z2@dD#S`0$eCRI<;!AKTW=o^7@W5&q0wSTVryswK+j!|#@(@w|qS-}%pMLem#Rd>3e z+3`Qz^}KaD(X^F=}PYslUGrplXOyDrSS#B$3Mcc#u-S+#!Pn~U#he?Aq^o{cM zdxyT1r}Bk95t|oMf-(O-+DZ*Ir&5UQsKLq{21_b9Y$tHY3cH^Tr$}XHs+~a9OWT>% zBqVA6v7_7Ev;IvgKif_cODH99dH8$&#(n6;v;vhpm7!ryL^O9wdwcG$yfme*U1JrR z_Z{>0%d@2SY4HG~KtC-&DAx7|wXOqOq1o=PRn@SE}T@s)UZHsILc34GFnEAy7cbm+pv<@?~T5 zQcem~$oY{vmL|~O#zRrXLlUi^8D@QLMWpG9=I-d|*GL8vKjgPRe_7mcOV&x@C81Is z?tMBaGAVwkPMZ5E+vXk1&})`cHJG^rER&0YtNK4zE^JpWwhpdr1Bb@P*G41df&xRe z#=?mBh2sO&pE>+csM_GgxkKNu_{Mq!3v4@$mgc18Ar)RCdI=dNv=!&&<^2M8va}Q{ zNm~5Vr$vE1s(*⁢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

    du*n|lxijE}>VWjz+?K-_&_6;^ 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