Skip to content

Commit dcf8468

Browse files
devrealclaude
andcommitted
device/gpu: address review feedback on proactive eviction
Three issues raised in code review: 1. MCA parameter scope mem_evict_upper and mem_evict_lower were registered once per GPU backend component, which means the second registration overwrites the first when both CUDA and Level Zero are enabled, and the params end up under backend-specific namespaces. Move the registrations to parsec_mca_device_init() in device.c under the "device" namespace (device_mem_evict_upper / device_mem_evict_lower), guarded by PARSEC_HAVE_CUDA || PARSEC_HAVE_HIP || PARSEC_HAVE_LEVEL_ZERO so the extern references are only present when transfer_gpu.c is compiled. 2. data_avail_epoch style Tier-1 used `data_avail_epoch = 1` while the rest of the function uses `data_avail_epoch++`. Changed to `++` for consistency. 3. Threshold step-down condition The previous placement fired on every PARSEC_HOOK_RETURN_NEXT from parsec_device_progress_stream, which tries one task per call — not all tasks. This could drive mem_evict_threshold to its minimum rapidly. The step-down is now integrated into the mem_evict_in_flight == 0 guard: we only lower the threshold when there are no active evictions AND parsec_gpu_create_w2r_task also returns NULL (no dirty pages available to queue). That is the true "stuck" condition. Signed-off-by: Joseph Schuchart <joseph.schuchart@stonybrook.edu> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent c9f7ba7 commit dcf8468

4 files changed

Lines changed: 27 additions & 21 deletions

File tree

parsec/mca/device/cuda/device_cuda_component.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,12 +161,6 @@ static int device_cuda_component_register(void)
161161
(void)parsec_mca_param_reg_int_name("device_cuda", "max_number_of_ejected_data",
162162
"Sets up the maximum number of blocks that can be ejected from GPU memory",
163163
false, false, MAX_PARAM_COUNT, &parsec_gpu_d2h_max_flows);
164-
(void)parsec_mca_param_reg_int_name("device_cuda", "mem_evict_upper",
165-
"Upper threshold (percentage of total GPU zone capacity) at which proactive clean-LRU eviction and D2H writeback begin. When a task stalls waiting for memory, the per-device threshold is stepped down by 5 points toward mem_evict_lower.",
166-
false, false, 95, &parsec_gpu_mem_evict_upper);
167-
(void)parsec_mca_param_reg_int_name("device_cuda", "mem_evict_lower",
168-
"Lower bound (percentage of total GPU zone capacity) to which the adaptive eviction threshold may be reduced after repeated stalls.",
169-
false, false, 80, &parsec_gpu_mem_evict_lower);
170164
(void)parsec_mca_param_reg_int_name("device_cuda", "max_streams",
171165
"Maximum number of Streams to use for the GPU engine; 2 streams are used for communication between host and device, so the minimum is 3",
172166
false, false, PARSEC_GPU_MAX_STREAMS, &parsec_cuda_max_streams);

parsec/mca/device/device.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,12 @@ no_valid_device: {
301301
PARSEC_OBJ_CLASS_INSTANCE(parsec_device_module_t, parsec_object_t,
302302
NULL, NULL);
303303

304+
#if defined(PARSEC_HAVE_CUDA) || defined(PARSEC_HAVE_HIP) || defined(PARSEC_HAVE_LEVEL_ZERO)
305+
/* Defined in transfer_gpu.c; registered here so they apply to all GPU backends. */
306+
extern int32_t parsec_gpu_mem_evict_upper;
307+
extern int32_t parsec_gpu_mem_evict_lower;
308+
#endif
309+
304310
int parsec_mca_device_init(void)
305311
{
306312
char** parsec_device_list = NULL;
@@ -313,6 +319,18 @@ int parsec_mca_device_init(void)
313319
PARSEC_OBJ_CONSTRUCT(&parsec_per_device_infos, parsec_info_t);
314320
PARSEC_OBJ_CONSTRUCT(&parsec_per_stream_infos, parsec_info_t);
315321

322+
#if defined(PARSEC_HAVE_CUDA) || defined(PARSEC_HAVE_HIP) || defined(PARSEC_HAVE_LEVEL_ZERO)
323+
(void)parsec_mca_param_reg_int_name("device", "mem_evict_upper",
324+
"Upper threshold (percentage of total GPU zone capacity) at which proactive "
325+
"clean-LRU eviction and D2H writeback begin. When the device is truly stalled "
326+
"(no in-flight evictions and no dirty pages left to queue), the per-device "
327+
"threshold is stepped down by 5 points toward device_mem_evict_lower.",
328+
false, false, 95, &parsec_gpu_mem_evict_upper);
329+
(void)parsec_mca_param_reg_int_name("device", "mem_evict_lower",
330+
"Lower bound (percentage of total GPU zone capacity) to which the adaptive "
331+
"eviction threshold may be reduced after repeated stalls.",
332+
false, false, 80, &parsec_gpu_mem_evict_lower);
333+
#endif /* PARSEC_HAVE_CUDA || PARSEC_HAVE_HIP || PARSEC_HAVE_LEVEL_ZERO */
316334
(void)parsec_mca_param_reg_int_name("device", "show_capabilities",
317335
"Show the detailed devices capabilities",
318336
false, false, parsec_debug_verbose >= 4 || (parsec_debug_verbose >= 3 && parsec_debug_rank == 0), NULL);

parsec/mca/device/device_gpu.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -957,7 +957,7 @@ parsec_device_data_reserve_space( parsec_device_gpu_module_t* gpu_device,
957957
(size_t)gpu_device->mem_evict_threshold * total_capacity ) {
958958
if( !parsec_device_try_evict_lru_one(gpu_device, &cycling) )
959959
break;
960-
data_avail_epoch = 1;
960+
data_avail_epoch++;
961961
}
962962
}
963963
#endif /* !defined(PARSEC_GPU_ALLOC_PER_TILE) */
@@ -2758,19 +2758,19 @@ parsec_device_kernel_scheduler( parsec_device_module_t *module,
27582758
}
27592759
assert(NULL == progress_task);
27602760

2761-
/* Every task in the pending queue failed to acquire GPU memory on this iteration:
2762-
* we are truly stalled. Step the eviction threshold down so tier-1 evicts more
2763-
* aggressively starting from the next scheduling iteration. */
2764-
if( PARSEC_HOOK_RETURN_NEXT == rc &&
2765-
gpu_device->mem_evict_threshold - 5 >= parsec_gpu_mem_evict_lower )
2766-
gpu_device->mem_evict_threshold -= 5;
2767-
27682761
/* TODO: check this */
27692762
/* If we can extract data go for it, otherwise try to drain the pending tasks.
2770-
* Skip if evictions are already in flight to avoid a storm of D2H tasks. */
2763+
* Skip if evictions are already in flight to avoid a storm of D2H tasks.
2764+
* If there are no in-flight evictions and nothing left to queue from the dirty
2765+
* LRU, we are truly stuck: step the eviction threshold down so tier-1 starts
2766+
* freeing pages earlier on the next attempt. */
27712767
if( 0 == gpu_device->mem_evict_in_flight ) {
27722768
size_t _sel = 0;
27732769
gpu_task = parsec_gpu_create_w2r_task(gpu_device, es, SIZE_MAX, &_sel);
2770+
if(gpu_device->mem_evict_threshold - 5 >= parsec_gpu_mem_evict_lower) {
2771+
/* We had to trigger a proactive D2H writeback so reduce the threshold */
2772+
gpu_device->mem_evict_threshold -= 5;
2773+
}
27742774
}
27752775
if( NULL != gpu_task )
27762776
goto get_data_out_of_device;

parsec/mca/device/level_zero/device_level_zero_component.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -271,12 +271,6 @@ static int device_level_zero_component_register(void)
271271
(void)parsec_mca_param_reg_int_name("device_level_zero", "max_number_of_ejected_data",
272272
"Sets up the maximum number of blocks that can be ejected from GPU memory",
273273
false, false, MAX_PARAM_COUNT, &parsec_gpu_d2h_max_flows);
274-
(void)parsec_mca_param_reg_int_name("device_level_zero", "mem_evict_upper",
275-
"Upper threshold (percentage of total GPU zone capacity) at which proactive clean-LRU eviction and D2H writeback begin. When a task stalls waiting for memory, the per-device threshold is stepped down by 5 points toward mem_evict_lower.",
276-
false, false, 95, &parsec_gpu_mem_evict_upper);
277-
(void)parsec_mca_param_reg_int_name("device_level_zero", "mem_evict_lower",
278-
"Lower bound (percentage of total GPU zone capacity) to which the adaptive eviction threshold may be reduced after repeated stalls.",
279-
false, false, 80, &parsec_gpu_mem_evict_lower);
280274
(void)parsec_mca_param_reg_int_name("device_level_zero", "max_streams",
281275
"Maximum number of Streams to use for the GPU engine; 2 streams are used for communication between host and device, so the minimum is 3",
282276
false, false, PARSEC_GPU_MAX_STREAMS, &parsec_level_zero_max_streams);

0 commit comments

Comments
 (0)