|
1 | 1 | /* |
2 | | - * Copyright (C) 2022-2025 Intel Corporation |
| 2 | + * Copyright (C) 2022-2026 Intel Corporation |
3 | 3 | * |
4 | 4 | * Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. |
5 | 5 | * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
@@ -981,24 +981,22 @@ static bool bucket_can_pool(bucket_t *bucket) { |
981 | 981 | static size_t size_to_idx(disjoint_pool_t *pool, size_t size) { |
982 | 982 | assert(size <= CutOff && "Unexpected size"); |
983 | 983 | assert(size > 0 && "Unexpected size"); |
| 984 | + assert(pool->buckets_num > 0 && "Unexpected buckets count"); |
984 | 985 |
|
985 | | - size_t min_bucket_size = (size_t)1 << pool->min_bucket_size_exp; |
986 | | - if (size < min_bucket_size) { |
987 | | - return 0; |
988 | | - } |
| 986 | + size_t left = 0; |
| 987 | + size_t right = pool->buckets_num - 1; |
989 | 988 |
|
990 | | - // get the position of the leftmost set bit |
991 | | - size_t position = utils_msb64(size); |
| 989 | + while (left < right) { |
| 990 | + size_t mid = left + (right - left) / 2; |
992 | 991 |
|
993 | | - bool is_power_of_2 = IS_POWER_OF_2(size); |
994 | | - bool larger_than_halfway_between_powers_of_2 = |
995 | | - !is_power_of_2 && |
996 | | - (bool)((size - 1) & ((uint64_t)(1) << (position - 1))); |
997 | | - size_t index = (position - pool->min_bucket_size_exp) * 2 + |
998 | | - (int)(!is_power_of_2) + |
999 | | - (int)larger_than_halfway_between_powers_of_2; |
| 992 | + if (pool->buckets[mid]->size < size) { |
| 993 | + left = mid + 1; |
| 994 | + } else { |
| 995 | + right = mid; |
| 996 | + } |
| 997 | + } |
1000 | 998 |
|
1001 | | - return index; |
| 999 | + return left; |
1002 | 1000 | } |
1003 | 1001 |
|
1004 | 1002 | static umf_disjoint_pool_shared_limits_t * |
@@ -1120,6 +1118,7 @@ static const umf_disjoint_pool_params_t default_params = { |
1120 | 1118 | .max_poolable_size = 2 * 1024 * 1024, // 2MB default |
1121 | 1119 | .capacity = 4, // default |
1122 | 1120 | .min_bucket_size = 8, // default |
| 1121 | + .min_bucket_size_set = false, |
1123 | 1122 | .cur_pool_size = 0, |
1124 | 1123 | .pool_trace = 0, |
1125 | 1124 | .shared_limits = NULL, |
@@ -1161,6 +1160,10 @@ umf_result_t disjoint_pool_initialize(umf_memory_provider_handle_t provider, |
1161 | 1160 | umf_result_t disjoint_pool_post_initialize(void *ppPool) { |
1162 | 1161 | disjoint_pool_t *disjoint_pool = (disjoint_pool_t *)ppPool; |
1163 | 1162 |
|
| 1163 | + const size_t max_bucket_num = (size_t)utils_msb64(CutOff) * 2 + 1; |
| 1164 | + size_t bucket_sizes[max_bucket_num]; |
| 1165 | + size_t unique_bucket_sizes[max_bucket_num]; |
| 1166 | + |
1164 | 1167 | disjoint_pool->post_initialized = true; |
1165 | 1168 |
|
1166 | 1169 | if (disjoint_pool->params_overridden) { |
@@ -1191,53 +1194,67 @@ umf_result_t disjoint_pool_post_initialize(void *ppPool) { |
1191 | 1194 | goto err_free_disjoint_pool; |
1192 | 1195 | } |
1193 | 1196 |
|
| 1197 | + if (!disjoint_pool->params.min_bucket_size_set) { |
| 1198 | + size_t cache_line_size; |
| 1199 | + umf_result_t ret = umfMemoryProviderGetCacheLineSize( |
| 1200 | + disjoint_pool->provider, &cache_line_size); |
| 1201 | + if (ret == UMF_RESULT_SUCCESS) { |
| 1202 | + disjoint_pool->params.min_bucket_size = cache_line_size; |
| 1203 | + } |
| 1204 | + } |
| 1205 | + |
1194 | 1206 | // Generate buckets sized such as: 64, 96, 128, 192, ..., CutOff. |
1195 | 1207 | // Powers of 2 and the value halfway between the powers of 2. |
1196 | | - size_t Size1 = disjoint_pool->params.min_bucket_size; |
| 1208 | + size_t size1 = disjoint_pool->params.min_bucket_size; |
1197 | 1209 |
|
1198 | 1210 | // min_bucket_size cannot be larger than CutOff. |
1199 | | - Size1 = utils_min(Size1, CutOff); |
| 1211 | + size1 = utils_min(size1, CutOff); |
| 1212 | + |
| 1213 | + // Buckets sized smaller than the bucket default size - 8 aren't needed. |
| 1214 | + size1 = utils_max(size1, UMF_DISJOINT_POOL_MIN_BUCKET_DEFAULT_SIZE); |
1200 | 1215 |
|
1201 | | - // Buckets sized smaller than the bucket default size- 8 aren't needed. |
1202 | | - Size1 = utils_max(Size1, UMF_DISJOINT_POOL_MIN_BUCKET_DEFAULT_SIZE); |
| 1216 | + // Calculate the size of the "halfway" bucket |
| 1217 | + size_t size2 = size1 + size1 / 2; |
1203 | 1218 |
|
1204 | 1219 | // Calculate the exponent for min_bucket_size used for finding buckets. |
1205 | | - disjoint_pool->min_bucket_size_exp = (size_t)utils_msb64(Size1); |
| 1220 | + disjoint_pool->min_bucket_size_exp = (size_t)utils_msb64(size1); |
1206 | 1221 | if (umfDisjointPoolSharedLimitsCreate( |
1207 | 1222 | SIZE_MAX, &disjoint_pool->default_shared_limits) != |
1208 | 1223 | UMF_RESULT_SUCCESS) { |
1209 | 1224 | goto err_free_known_slabs; |
1210 | 1225 | } |
1211 | 1226 |
|
1212 | | - // count number of buckets, start from 1 |
1213 | | - disjoint_pool->buckets_num = 1; |
1214 | | - size_t Size2 = Size1 + Size1 / 2; |
1215 | | - size_t ts2 = Size2, ts1 = Size1; |
1216 | | - while (Size2 < CutOff) { |
1217 | | - disjoint_pool->buckets_num += 2; |
1218 | | - Size2 *= 2; |
| 1227 | + // Calclate sizes of buckets and store them in the array. |
| 1228 | + size_t i = 0; |
| 1229 | + for (; size2 < CutOff; size1 *= 2, size2 *= 2, i += 2) { |
| 1230 | + bucket_sizes[i] = |
| 1231 | + ALIGN_UP_SAFE(size1, disjoint_pool->params.min_bucket_size); |
| 1232 | + bucket_sizes[i + 1] = |
| 1233 | + ALIGN_UP_SAFE(size2, disjoint_pool->params.min_bucket_size); |
| 1234 | + } |
| 1235 | + bucket_sizes[i] = CutOff; |
| 1236 | + |
| 1237 | + // After rounding up some sizes may be equal, we need to remove duplicates |
| 1238 | + // and count the number of unique sizes. |
| 1239 | + size_t unique_count = 0; |
| 1240 | + for (size_t j = 0; j <= i; j++) { |
| 1241 | + if (j == 0 || bucket_sizes[j] != bucket_sizes[j - 1]) { |
| 1242 | + unique_bucket_sizes[unique_count++] = bucket_sizes[j]; |
| 1243 | + } |
1219 | 1244 | } |
| 1245 | + disjoint_pool->buckets_num = unique_count; |
1220 | 1246 |
|
1221 | 1247 | disjoint_pool->buckets = umf_ba_global_alloc( |
1222 | 1248 | sizeof(*disjoint_pool->buckets) * disjoint_pool->buckets_num); |
1223 | 1249 | if (disjoint_pool->buckets == NULL) { |
1224 | 1250 | goto err_free_shared_limits; |
1225 | 1251 | } |
1226 | 1252 |
|
1227 | | - size_t i = 0; |
1228 | | - Size1 = ts1; |
1229 | | - Size2 = ts2; |
1230 | | - for (; Size2 < CutOff; Size1 *= 2, Size2 *= 2, i += 2) { |
1231 | | - disjoint_pool->buckets[i] = create_bucket( |
1232 | | - Size1, disjoint_pool, disjoint_pool_get_limits(disjoint_pool)); |
1233 | | - disjoint_pool->buckets[i + 1] = create_bucket( |
1234 | | - Size2, disjoint_pool, disjoint_pool_get_limits(disjoint_pool)); |
1235 | | - } |
1236 | | - disjoint_pool->buckets[i] = create_bucket( |
1237 | | - CutOff, disjoint_pool, disjoint_pool_get_limits(disjoint_pool)); |
1238 | | - |
1239 | | - // check if all buckets were created successfully |
| 1253 | + // Create buckets for each unique size. |
1240 | 1254 | for (i = 0; i < disjoint_pool->buckets_num; i++) { |
| 1255 | + disjoint_pool->buckets[i] = |
| 1256 | + create_bucket(unique_bucket_sizes[i], disjoint_pool, |
| 1257 | + disjoint_pool_get_limits(disjoint_pool)); |
1241 | 1258 | if (disjoint_pool->buckets[i] == NULL) { |
1242 | 1259 | goto err_free_buckets; |
1243 | 1260 | } |
@@ -1733,6 +1750,7 @@ umfDisjointPoolParamsSetMinBucketSize(umf_disjoint_pool_params_handle_t hParams, |
1733 | 1750 | } |
1734 | 1751 |
|
1735 | 1752 | hParams->min_bucket_size = minBucketSize; |
| 1753 | + hParams->min_bucket_size_set = true; |
1736 | 1754 | return UMF_RESULT_SUCCESS; |
1737 | 1755 | } |
1738 | 1756 |
|
|
0 commit comments