@@ -809,17 +809,19 @@ struct ace_memory_requirements {
809809 size_t available_gpu_memory;
810810};
811811
812- // TODO: Adjust overhead factor if needed. Very conservative for now.
812+ // Amount of host memory that can be used for the build
813813constexpr double usable_cpu_memory_fraction = 0.8 ;
814- constexpr double usable_gpu_memory_fraction = 1.0 ;
815- constexpr double imbalance_factor = 3.0 ;
816- constexpr double vector_expansion_factor = 2.0 ;
817- constexpr size_t extra_cpu_workspace_size = 0 ;
818- constexpr size_t extra_gpu_workspace_size = 2e9 ;
814+
815+ // Factor to account for imbalances in the partitions (maximum allowed is 3x the average)
816+ constexpr double imbalance_factor = 3.0 ;
817+
818+ // Current partitioning adds each vector into 2 partitions (core and augmented)
819+ constexpr double vector_expansion_factor = 2.0 ;
819820
820821// Check if disk mode should be used for ACE based on memory constraints
821822template <typename T, typename IdxT>
822- bool ace_check_use_disk_mode (bool use_disk,
823+ bool ace_check_use_disk_mode (raft::resources const & res,
824+ bool use_disk,
823825 std::string& build_dir,
824826 size_t dataset_size,
825827 size_t dataset_dim,
@@ -851,7 +853,8 @@ bool ace_check_use_disk_mode(bool use_disk,
851853 mem.available_host_memory = cuvs::util::get_free_host_memory ();
852854 }
853855 size_t sub_partition_size =
854- static_cast <size_t >(imbalance_factor * vector_expansion_factor * (dataset_size / n_partitions));
856+ static_cast <size_t >(imbalance_factor * vector_expansion_factor *
857+ raft::div_rounding_up_safe (dataset_size, n_partitions));
855858 auto [opt_host_ws_total, opt_dev_ws_total, opt_host_ws_fixed, opt_dev_ws_fixed] =
856859 helpers::optimize_workspace_size (
857860 sub_partition_size, graph_degree, intermediate_degree, sizeof (IdxT), guarantee_connectivity);
@@ -872,8 +875,7 @@ bool ace_check_use_disk_mode(bool use_disk,
872875 mem.sub_graph_size = sub_partition_size * (intermediate_degree + graph_degree) * sizeof (IdxT);
873876 mem.cagra_graph_size = dataset_size * graph_degree * sizeof (IdxT);
874877 mem.total_size = mem.partition_labels_size + mem.id_mapping_size + mem.sub_dataset_size +
875- mem.sub_graph_size + mem.cagra_graph_size + opt_host_ws_total +
876- extra_cpu_workspace_size;
878+ mem.sub_graph_size + mem.cagra_graph_size + opt_host_ws_total;
877879
878880 RAFT_LOG_INFO (" ACE: Estimated host memory required: %.2f GiB, available: %.2f GiB" ,
879881 to_gib (mem.total_size ),
@@ -907,11 +909,11 @@ bool ace_check_use_disk_mode(bool use_disk,
907909 // * IVF-PQ on partition (sub_dataset_size, uncompressed upper bound)
908910 // * optimize workspace (opt_dev_ws_total)
909911 // + some extra workspace (IVF-PQ search, ...)
912+ size_t extra_gpu_workspace_size = raft::resource::get_workspace_total_bytes (res);
910913 size_t gpu_memory_required =
911914 std::max (mem.sub_dataset_size , opt_dev_ws_total) + extra_gpu_workspace_size;
912915
913- bool gpu_memory_limited = static_cast <size_t >(usable_gpu_memory_fraction *
914- mem.available_gpu_memory ) < gpu_memory_required;
916+ bool gpu_memory_limited = mem.available_gpu_memory < gpu_memory_required;
915917
916918 RAFT_LOG_INFO (" ACE: Estimated GPU memory required: %.2f GiB, available: %.2f GiB" ,
917919 to_gib (gpu_memory_required),
@@ -958,7 +960,8 @@ bool ace_check_use_disk_mode(bool use_disk,
958960
959961// Validate and adjust partitions for disk mode memory requirements
960962template <typename T, typename IdxT>
961- void ace_validate_disk_mode_partitions (size_t & n_partitions,
963+ void ace_validate_disk_mode_partitions (raft::resources const & res,
964+ size_t & n_partitions,
962965 size_t dataset_size,
963966 size_t dataset_dim,
964967 size_t intermediate_degree,
@@ -983,7 +986,8 @@ void ace_validate_disk_mode_partitions(size_t& n_partitions,
983986
984987 // Compute optimize workspace requirements
985988 size_t sub_partition_size =
986- static_cast <size_t >(imbalance_factor * vector_expansion_factor * (dataset_size / n_partitions));
989+ static_cast <size_t >(imbalance_factor * vector_expansion_factor *
990+ raft::div_rounding_up_safe (dataset_size, n_partitions));
987991 auto [host_workspace_size_total,
988992 gpu_workspace_size_total,
989993 host_workspace_size_fixed,
@@ -994,7 +998,7 @@ void ace_validate_disk_mode_partitions(size_t& n_partitions,
994998 // Check host memory requirements
995999 size_t disk_mode_host_required = mem.partition_labels_size + mem.id_mapping_size +
9961000 mem.sub_dataset_size + mem.sub_graph_size +
997- host_workspace_size_total + extra_cpu_workspace_size ;
1001+ host_workspace_size_total;
9981002
9991003 if (static_cast <size_t >(usable_cpu_memory_fraction * mem.available_host_memory ) <
10001004 disk_mode_host_required) {
@@ -1006,11 +1010,11 @@ void ace_validate_disk_mode_partitions(size_t& n_partitions,
10061010 to_gib (mem.available_host_memory ),
10071011 to_gib (mem.sub_dataset_size ),
10081012 to_gib (mem.sub_graph_size ),
1009- to_gib (host_workspace_size_total + extra_cpu_workspace_size ));
1013+ to_gib (host_workspace_size_total));
10101014
10111015 // Calculate suggested number of partitions for host memory
1012- size_t disk_mode_host_static = mem. partition_labels_size + mem. id_mapping_size +
1013- host_workspace_size_fixed + extra_cpu_workspace_size ;
1016+ size_t disk_mode_host_static =
1017+ mem. partition_labels_size + mem. id_mapping_size + host_workspace_size_fixed ;
10141018 size_t disk_mode_host_dynamic = disk_mode_host_required - disk_mode_host_static;
10151019 double available_for_scaling =
10161020 usable_cpu_memory_fraction * mem.available_host_memory - disk_mode_host_static;
@@ -1032,11 +1036,11 @@ void ace_validate_disk_mode_partitions(size_t& n_partitions,
10321036 // * IVF-PQ on partition (mem.sub_dataset_size) (compressed?)
10331037 // * optimize workspace (gpu_workspace_size_total)
10341038 // + some extra workspace (IVF-PQ search, ...)
1039+ size_t extra_gpu_workspace_size = raft::resource::get_workspace_total_bytes (res);
10351040 size_t disk_mode_gpu_required =
10361041 std::max (mem.sub_dataset_size , gpu_workspace_size_total) + extra_gpu_workspace_size;
10371042
1038- if (static_cast <size_t >(usable_gpu_memory_fraction * mem.available_gpu_memory ) <
1039- disk_mode_gpu_required) {
1043+ if (mem.available_gpu_memory < disk_mode_gpu_required) {
10401044 gpu_memory_insufficient = true ;
10411045 RAFT_LOG_WARN (
10421046 " ACE: GPU memory insufficient for per-partition processing. Required: %.2f GiB, "
@@ -1048,14 +1052,13 @@ void ace_validate_disk_mode_partitions(size_t& n_partitions,
10481052
10491053 size_t disk_mode_gpu_static = gpu_workspace_size_fixed + extra_gpu_workspace_size;
10501054 size_t disk_mode_gpu_dynamic = disk_mode_gpu_required - disk_mode_gpu_static;
1051- double available_for_scaling =
1052- usable_gpu_memory_fraction * mem.available_gpu_memory - disk_mode_gpu_static;
1055+ double available_for_scaling = mem.available_gpu_memory - disk_mode_gpu_static;
10531056
10541057 RAFT_EXPECTS (available_for_scaling > 0 ,
10551058 " ACE: GPU memory insufficient even for constant overhead. Required: %.2f GiB, "
10561059 " available: %.2f GiB" ,
10571060 to_gib (disk_mode_gpu_static),
1058- to_gib (usable_gpu_memory_fraction * mem.available_gpu_memory ));
1061+ to_gib (mem.available_gpu_memory ));
10591062
10601063 gpu_suggested_partitions =
10611064 static_cast <size_t >(std::ceil (disk_mode_gpu_dynamic * n_partitions / available_for_scaling));
@@ -1080,8 +1083,9 @@ void ace_validate_disk_mode_partitions(size_t& n_partitions,
10801083
10811084 n_partitions = new_n_partitions;
10821085
1083- size_t new_sub_partition_size = static_cast <size_t >(imbalance_factor * vector_expansion_factor *
1084- (dataset_size / n_partitions));
1086+ size_t new_sub_partition_size =
1087+ static_cast <size_t >(imbalance_factor * vector_expansion_factor *
1088+ raft::div_rounding_up_safe (dataset_size, n_partitions));
10851089 auto [new_opt_host_ws, new_opt_dev_ws, new_opt_host_ws_fixed, new_opt_dev_ws_fixed] =
10861090 helpers::optimize_workspace_size (new_sub_partition_size,
10871091 graph_degree,
@@ -1093,15 +1097,14 @@ void ace_validate_disk_mode_partitions(size_t& n_partitions,
10931097 mem.sub_graph_size =
10941098 new_sub_partition_size * (intermediate_degree + graph_degree) * sizeof (IdxT);
10951099 mem.total_size = mem.partition_labels_size + mem.id_mapping_size + mem.sub_dataset_size +
1096- mem.sub_graph_size + mem.cagra_graph_size + new_opt_host_ws +
1097- extra_cpu_workspace_size;
1100+ mem.sub_graph_size + mem.cagra_graph_size + new_opt_host_ws;
10981101
10991102 RAFT_LOG_INFO (
11001103 " ACE: Updated per-partition memory estimates: dataset %.2f GiB, graph %.2f GiB, "
11011104 " host workspace %.2f GiB, GPU workspace %.2f GiB" ,
11021105 to_gib (mem.sub_dataset_size ),
11031106 to_gib (mem.sub_graph_size ),
1104- to_gib (new_opt_host_ws + extra_cpu_workspace_size ),
1107+ to_gib (new_opt_host_ws),
11051108 to_gib (new_opt_dev_ws + extra_gpu_workspace_size));
11061109 }
11071110}
@@ -1184,7 +1187,8 @@ index<T, IdxT> build_ace(raft::resources const& res,
11841187
11851188 // Check if disk mode should be used based on memory constraints
11861189 ace_memory_requirements mem;
1187- bool use_disk_mode = ace_check_use_disk_mode<T, IdxT>(use_disk,
1190+ bool use_disk_mode = ace_check_use_disk_mode<T, IdxT>(res,
1191+ use_disk,
11881192 build_dir,
11891193 dataset_size,
11901194 dataset_dim,
@@ -1198,7 +1202,8 @@ index<T, IdxT> build_ace(raft::resources const& res,
11981202
11991203 // Validate and adjust partitions if disk mode is enabled
12001204 if (use_disk_mode) {
1201- ace_validate_disk_mode_partitions<T, IdxT>(n_partitions,
1205+ ace_validate_disk_mode_partitions<T, IdxT>(res,
1206+ n_partitions,
12021207 dataset_size,
12031208 dataset_dim,
12041209 intermediate_degree,
0 commit comments