| 2203 | } |
| 2204 | |
| 2205 | void Subarray::precompute_tile_overlap( |
| 2206 | uint64_t start_range_idx, |
| 2207 | uint64_t end_range_idx, |
| 2208 | const Config* config, |
| 2209 | ThreadPool* compute_tp, |
| 2210 | bool override_memory_constraint) { |
| 2211 | auto timer_se = stats_->start_timer("read_compute_tile_overlap"); |
| 2212 | |
| 2213 | // If the `tile_overlap_` has already been precomputed and contains |
| 2214 | // the given range, re-use it with new range. |
| 2215 | const bool tile_overlap_computed = |
| 2216 | tile_overlap_.contains_range(start_range_idx, end_range_idx); |
| 2217 | if (tile_overlap_computed) { |
| 2218 | stats_->add_counter("precompute_tile_overlap.tile_overlap_cache_hit", 1); |
| 2219 | tile_overlap_.update_range(start_range_idx, end_range_idx); |
| 2220 | return; |
| 2221 | } |
| 2222 | |
| 2223 | stats_->add_counter( |
| 2224 | "precompute_tile_overlap.ranges_requested", |
| 2225 | end_range_idx - start_range_idx + 1); |
| 2226 | |
| 2227 | compute_range_offsets(); |
| 2228 | |
| 2229 | auto meta = array_->fragment_metadata(); |
| 2230 | auto fragment_num = meta.size(); |
| 2231 | |
| 2232 | // Lookup the target maximum tile overlap size. |
| 2233 | const uint64_t max_tile_overlap_size = |
| 2234 | config->get<uint64_t>("sm.max_tile_overlap_size", Config::must_find); |
| 2235 | |
| 2236 | uint64_t tile_overlap_start = start_range_idx; |
| 2237 | uint64_t tile_overlap_end = end_range_idx; |
| 2238 | |
| 2239 | // Currently, we allow the caller to override the memory constraint |
| 2240 | // imposed by `constants::max_tile_overlap_size`. This is temporary |
| 2241 | // until we refactor for all callers to become aware that `tile_overlap_` |
| 2242 | // may be truncated. |
| 2243 | uint64_t tmp_tile_overlap_end = tile_overlap_start; |
| 2244 | if (override_memory_constraint || fragment_num == 0) { |
| 2245 | tmp_tile_overlap_end = tile_overlap_end; |
| 2246 | } |
| 2247 | |
| 2248 | // Incrementally compute the tile overlap until either: |
| 2249 | // 1). Tile overlap has been computed for all of the requested ranges. |
| 2250 | // 2). The size of the current tile overlap has exceed our budget. |
| 2251 | // |
| 2252 | // Each loop is expensive, so we will double the range to compute for |
| 2253 | // each successive loop. The intent is to minimize the number of loops |
| 2254 | // at the risk of exceeding our target maximum memory usage for the |
| 2255 | // tile overlap data. |
| 2256 | RelevantFragmentGenerator relevant_fragment_generator(array_, *this, stats_); |
| 2257 | ComputeRelevantTileOverlapCtx tile_overlap_ctx; |
| 2258 | SubarrayTileOverlap tile_overlap( |
| 2259 | fragment_num, tile_overlap_start, tmp_tile_overlap_end); |
| 2260 | do { |
| 2261 | if (relevant_fragment_generator.update_range_coords(&tile_overlap)) { |
| 2262 | relevant_fragments_ = |
no test coverage detected