From 329f2c9dfb7f476c6fc3861215e83add8af14836 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Tue, 10 Dec 2024 13:49:07 -0500 Subject: [PATCH 01/53] log the res allocation --- taskvine/src/manager/vine_schedule.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index 115c8898ef..d4ccde91b2 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -130,6 +130,24 @@ int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worke if ((tr->gpus > worker_net_resources->gpus.total) || (worker_net_resources->gpus.inuse + tr->gpus > overcommitted_resource_total(q, worker_net_resources->gpus.total))) { ok = 0; } + + + const char *filename = "resource_allocation.csv"; + FILE *file = fopen(filename, "a"); + + if (file == NULL) { + perror("failed to open file"); + return EXIT_FAILURE; + } + + fprintf(file, "%d,%f,%f,%f,%ld,%ld,%ld\n", t->task_id, tr->cores, tr->memory, tr->disk, + worker_net_resources->cores.total - worker_net_resources->cores.inuse, + worker_net_resources->memory.total - worker_net_resources->memory.inuse, + worker_net_resources->disk.total - worker_net_resources->disk.inuse); + + fclose(file); + + vine_resources_delete(worker_net_resources); return ok; } From 2ed9c0eac5d4013885590dbc4ecc117be6989650 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Tue, 10 Dec 2024 21:21:14 -0500 Subject: [PATCH 02/53] efficient resource allocation --- taskvine/src/manager/vine_manager.c | 24 +++++++++++++++++++++++- taskvine/src/manager/vine_schedule.c | 19 ++++++++++++------- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index 28ba5a33e4..e5dc312793 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2611,7 +2611,7 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, const struct rmsummary *max = vine_manager_task_resources_max(q, t); /* available disk for all sandboxes */ - int64_t available_disk = w->resources->disk.total - BYTES_TO_MEGABYTES(w->inuse_cache); + int64_t available_disk = w->resources->disk.total - w->resources->disk.inuse; /* do not count the size of input files as available. * TODO: efficiently discount the size of files already at worker. */ @@ -3382,11 +3382,33 @@ static int send_one_task(struct vine_manager *q) { int t_idx; struct vine_task *t; + uint64_t task_id; struct vine_worker_info *w = NULL; int iter_count = 0; int iter_depth = MIN(priority_queue_size(q->ready_tasks), q->attempt_schedule_depth); + /* first see if there are any available cores */ + int has_available_cores = 0; + char *key; + HASH_TABLE_ITERATE(q->worker_table, key, w) + { + if (w->resources->cores.total - w->resources->cores.inuse > 0) { + has_available_cores = 1; + break; + } + ITABLE_ITERATE(w->current_tasks, task_id, t) + { + if (t->type == VINE_TASK_TYPE_LIBRARY_INSTANCE && t->provides_library && t->function_slots_inuse < t->function_slots_total) { + has_available_cores = 1; + break; + } + } + } + if (!has_available_cores) { + return 0; + } + // Iterate over the ready tasks by priority. // The first time we arrive here, the task with the highest priority is considered. However, there may be various reasons // that this particular task is not eligible to run, such as: 1) the task requires more resources than the workers have; diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index d4ccde91b2..59b1e34f25 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -113,25 +113,30 @@ int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worke } int ok = 1; - if (worker_net_resources->disk.inuse + tr->disk > worker_net_resources->disk.total) { /* No overcommit disk */ + + int64_t available_disk = overcommitted_resource_total(q, worker_net_resources->disk.total) - worker_net_resources->disk.inuse; + if (t->input_files_size > 0) { + available_disk -= t->input_files_size; + } + if (tr->disk > available_disk) { ok = 0; } - if ((tr->cores > worker_net_resources->cores.total) || - (worker_net_resources->cores.inuse + tr->cores > overcommitted_resource_total(q, worker_net_resources->cores.total))) { + int64_t available_cores = overcommitted_resource_total(q, worker_net_resources->cores.total) - worker_net_resources->cores.inuse; + if (tr->cores > available_cores) { ok = 0; } - if ((tr->memory > worker_net_resources->memory.total) || - (worker_net_resources->memory.inuse + tr->memory > overcommitted_resource_total(q, worker_net_resources->memory.total))) { + int64_t available_memory = overcommitted_resource_total(q, worker_net_resources->memory.total) - worker_net_resources->memory.inuse; + if (tr->memory > available_memory) { ok = 0; } - if ((tr->gpus > worker_net_resources->gpus.total) || (worker_net_resources->gpus.inuse + tr->gpus > overcommitted_resource_total(q, worker_net_resources->gpus.total))) { + int64_t available_gpus = overcommitted_resource_total(q, worker_net_resources->gpus.total) - worker_net_resources->gpus.inuse; + if (tr->gpus > available_gpus) { ok = 0; } - const char *filename = "resource_allocation.csv"; FILE *file = fopen(filename, "a"); From 5620893829e087f965c503656d179115338104bb Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Tue, 10 Dec 2024 21:25:00 -0500 Subject: [PATCH 03/53] lint --- taskvine/src/manager/vine_schedule.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index 59b1e34f25..42a272be1c 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -137,21 +137,17 @@ int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worke ok = 0; } - const char *filename = "resource_allocation.csv"; - FILE *file = fopen(filename, "a"); + const char *filename = "resource_allocation.csv"; + FILE *file = fopen(filename, "a"); - if (file == NULL) { - perror("failed to open file"); - return EXIT_FAILURE; - } - - fprintf(file, "%d,%f,%f,%f,%ld,%ld,%ld\n", t->task_id, tr->cores, tr->memory, tr->disk, - worker_net_resources->cores.total - worker_net_resources->cores.inuse, - worker_net_resources->memory.total - worker_net_resources->memory.inuse, - worker_net_resources->disk.total - worker_net_resources->disk.inuse); + if (file == NULL) { + perror("failed to open file"); + return EXIT_FAILURE; + } - fclose(file); + fprintf(file, "%d,%f,%f,%f,%ld,%ld,%ld\n", t->task_id, tr->cores, tr->memory, tr->disk, worker_net_resources->cores.total - worker_net_resources->cores.inuse, worker_net_resources->memory.total - worker_net_resources->memory.inuse, worker_net_resources->disk.total - worker_net_resources->disk.inuse); + fclose(file); vine_resources_delete(worker_net_resources); return ok; From e4aeea0ab562c29f2c864a0f24364b2a965996eb Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Wed, 11 Dec 2024 09:55:12 -0500 Subject: [PATCH 04/53] test --- taskvine/src/manager/vine_manager.c | 1 + 1 file changed, 1 insertion(+) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index e5dc312793..e95a817b58 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -3386,6 +3386,7 @@ static int send_one_task(struct vine_manager *q) struct vine_worker_info *w = NULL; int iter_count = 0; + int test = 0; int iter_depth = MIN(priority_queue_size(q->ready_tasks), q->attempt_schedule_depth); /* first see if there are any available cores */ From aa857920d3d830a37b7299a9b5de68847bf45b7a Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Wed, 11 Dec 2024 09:57:23 -0500 Subject: [PATCH 05/53] test --- taskvine/src/manager/vine_manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index e95a817b58..d1ad3f5572 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -3386,7 +3386,7 @@ static int send_one_task(struct vine_manager *q) struct vine_worker_info *w = NULL; int iter_count = 0; - int test = 0; + int iter_depth = MIN(priority_queue_size(q->ready_tasks), q->attempt_schedule_depth); /* first see if there are any available cores */ From b6e17e062f66c0be694f0acb639da869ce50c455 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Wed, 11 Dec 2024 10:08:22 -0500 Subject: [PATCH 06/53] remove test comment --- taskvine/src/manager/vine_manager.c | 6 ++---- taskvine/src/manager/vine_schedule.c | 19 +++++++++++-------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index d1ad3f5572..ffc62fa9a9 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -371,7 +371,7 @@ static int handle_cache_update(struct vine_manager *q, struct vine_worker_info * vine_txn_log_write_cache_update(q, w, size, transfer_time, start_time, cachename); - w->resources->disk.inuse += size / 1e6; + w->resources->disk.inuse += BYTES_TO_MEGABYTES(size); /* If the replica corresponds to a declared file. */ @@ -2615,9 +2615,7 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, /* do not count the size of input files as available. * TODO: efficiently discount the size of files already at worker. */ - if (t->input_files_size > 0) { - available_disk -= t->input_files_size; - } + available_disk -= t->input_files_size; rmsummary_merge_override_basic(limits, max); diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index 42a272be1c..279e0d743e 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -137,17 +137,20 @@ int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worke ok = 0; } - const char *filename = "resource_allocation.csv"; - FILE *file = fopen(filename, "a"); + /* TEST - if (file == NULL) { - perror("failed to open file"); - return EXIT_FAILURE; - } + const char *filename = "resource_allocation.csv"; + FILE *file = fopen(filename, "a"); + + if (file == NULL) { + perror("failed to open file"); + return EXIT_FAILURE; + } - fprintf(file, "%d,%f,%f,%f,%ld,%ld,%ld\n", t->task_id, tr->cores, tr->memory, tr->disk, worker_net_resources->cores.total - worker_net_resources->cores.inuse, worker_net_resources->memory.total - worker_net_resources->memory.inuse, worker_net_resources->disk.total - worker_net_resources->disk.inuse); + fprintf(file, "%d,%f,%f,%f,%ld,%ld,%ld\n", t->task_id, tr->cores, tr->memory, tr->disk, worker_net_resources->cores.total - worker_net_resources->cores.inuse, worker_net_resources->memory.total - worker_net_resources->memory.inuse, worker_net_resources->disk.total - worker_net_resources->disk.inuse); - fclose(file); + fclose(file); + */ vine_resources_delete(worker_net_resources); return ok; From 7ac0d393138361e7c128b4a09223faaaee9be8ec Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Wed, 11 Dec 2024 10:35:31 -0500 Subject: [PATCH 07/53] BYTES_TO_MEGABYTES w->inuse_cache --- taskvine/src/manager/vine_manager.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index ffc62fa9a9..0ca25c2f0d 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2611,7 +2611,7 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, const struct rmsummary *max = vine_manager_task_resources_max(q, t); /* available disk for all sandboxes */ - int64_t available_disk = w->resources->disk.total - w->resources->disk.inuse; + int64_t available_disk = w->resources->disk.total - BYTES_TO_MEGABYTES(w->inuse_cache); /* do not count the size of input files as available. * TODO: efficiently discount the size of files already at worker. */ @@ -2834,8 +2834,9 @@ static void count_worker_resources(struct vine_manager *q, struct vine_worker_in static void update_max_worker(struct vine_manager *q, struct vine_worker_info *w) { - if (!w) + if (!w) { return; + } if (w->resources->workers.total < 1) { return; @@ -2849,8 +2850,8 @@ static void update_max_worker(struct vine_manager *q, struct vine_worker_info *w q->current_max_worker->memory = w->resources->memory.total; } - if (q->current_max_worker->disk < (w->resources->disk.total - w->inuse_cache)) { - q->current_max_worker->disk = w->resources->disk.total - w->inuse_cache; + if (q->current_max_worker->disk < (w->resources->disk.total - BYTES_TO_MEGABYTES(w->inuse_cache))) { + q->current_max_worker->disk = w->resources->disk.total - BYTES_TO_MEGABYTES(w->inuse_cache); } if (q->current_max_worker->gpus < w->resources->gpus.total) { From ac81d818bd8ac595f1fa9a807479e1ad3dd3b279 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Wed, 11 Dec 2024 10:36:16 -0500 Subject: [PATCH 08/53] remove comment --- taskvine/src/manager/vine_schedule.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index 279e0d743e..8f7c083b9b 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -114,10 +114,7 @@ int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worke int ok = 1; - int64_t available_disk = overcommitted_resource_total(q, worker_net_resources->disk.total) - worker_net_resources->disk.inuse; - if (t->input_files_size > 0) { - available_disk -= t->input_files_size; - } + int64_t available_disk = overcommitted_resource_total(q, worker_net_resources->disk.total) - worker_net_resources->disk.inuse - t->input_files_size; if (tr->disk > available_disk) { ok = 0; } @@ -137,7 +134,7 @@ int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worke ok = 0; } - /* TEST + /* TEST ^^^ const char *filename = "resource_allocation.csv"; FILE *file = fopen(filename, "a"); From 62c7856c59eac00e015ab83e294c97c88037d415 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Wed, 11 Dec 2024 16:19:10 -0500 Subject: [PATCH 09/53] change variable name --- taskvine/src/manager/vine_manager.c | 18 +++++++++--------- taskvine/src/manager/vine_schedule.c | 5 ++++- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index 0ca25c2f0d..fb16ee4431 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2611,11 +2611,11 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, const struct rmsummary *max = vine_manager_task_resources_max(q, t); /* available disk for all sandboxes */ - int64_t available_disk = w->resources->disk.total - BYTES_TO_MEGABYTES(w->inuse_cache); + int64_t disk_for_sandboxes = w->resources->disk.total - BYTES_TO_MEGABYTES(w->inuse_cache); /* do not count the size of input files as available. * TODO: efficiently discount the size of files already at worker. */ - available_disk -= t->input_files_size; + disk_for_sandboxes -= t->input_files_size; rmsummary_merge_override_basic(limits, max); @@ -2646,9 +2646,9 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, min_proportion = MAX(min_proportion, min->memory / w->resources->memory.total); } - if (available_disk > 0) { - max_proportion = MAX(max_proportion, limits->disk / available_disk); - min_proportion = MAX(min_proportion, min->disk / available_disk); + if (disk_for_sandboxes > 0) { + max_proportion = MAX(max_proportion, limits->disk / disk_for_sandboxes); + min_proportion = MAX(min_proportion, min->disk / disk_for_sandboxes); } if (w->resources->gpus.total > 0) { @@ -2696,7 +2696,7 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, /* worker's disk is shared evenly among tasks that are not running, * thus the proportion is modified by the current overcommit * multiplier */ - limits->disk = MAX(1, MAX(limits->disk, floor(available_disk * max_proportion / q->resource_submit_multiplier))); + limits->disk = MAX(1, MAX(limits->disk, floor(disk_for_sandboxes * max_proportion / q->resource_submit_multiplier))); } } @@ -2707,7 +2707,7 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, /* At least one specified resource would use the whole worker, thus * using whole worker for all unspecified resources. */ if ((limits->cores > 0 && limits->cores >= w->resources->cores.total) || (limits->gpus > 0 && limits->gpus >= w->resources->gpus.total) || - (limits->memory > 0 && limits->memory >= w->resources->memory.total) || (limits->disk > 0 && limits->disk >= available_disk)) { + (limits->memory > 0 && limits->memory >= w->resources->memory.total) || (limits->disk > 0 && limits->disk >= disk_for_sandboxes)) { use_whole_worker = 1; } @@ -2728,7 +2728,7 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, } if (limits->disk <= 0) { - limits->disk = available_disk; + limits->disk = disk_for_sandboxes; } } else if (vine_schedule_in_ramp_down(q)) { /* if in ramp down, use all the free space of that worker. note that we don't use @@ -2741,7 +2741,7 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, } limits->memory = w->resources->memory.total - w->resources->memory.inuse; - limits->disk = available_disk; + limits->disk = disk_for_sandboxes; } /* never go below specified min resources. */ diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index 8f7c083b9b..311e5d407f 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -144,7 +144,10 @@ int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worke return EXIT_FAILURE; } - fprintf(file, "%d,%f,%f,%f,%ld,%ld,%ld\n", t->task_id, tr->cores, tr->memory, tr->disk, worker_net_resources->cores.total - worker_net_resources->cores.inuse, worker_net_resources->memory.total - worker_net_resources->memory.inuse, worker_net_resources->disk.total - worker_net_resources->disk.inuse); + fprintf(file, "%d,%f,%f,%f,%ld,%ld,%ld,%d\n", t->task_id, + tr->cores, tr->memory, tr->disk, + available_cores, available_memory, available_disk, + ok); fclose(file); */ From fa663af83fc2fda2635ec6572acf8b4e5dc718b1 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Wed, 11 Dec 2024 18:39:30 -0500 Subject: [PATCH 10/53] limit available --- taskvine/src/manager/vine_manager.c | 34 +++++++++++++++++++--------- taskvine/src/manager/vine_schedule.c | 18 +++++++-------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index fb16ee4431..3c6a0750f2 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2611,11 +2611,17 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, const struct rmsummary *max = vine_manager_task_resources_max(q, t); /* available disk for all sandboxes */ - int64_t disk_for_sandboxes = w->resources->disk.total - BYTES_TO_MEGABYTES(w->inuse_cache); + int64_t disk_total = w->resources->disk.total - BYTES_TO_MEGABYTES(w->inuse_cache); /* do not count the size of input files as available. * TODO: efficiently discount the size of files already at worker. */ - disk_for_sandboxes -= t->input_files_size; + disk_total -= t->input_files_size; + + /* current available resources on this worker */ + int64_t disk_available = w->resources->disk.total - w->resources->disk.inuse - t->input_files_size; + int64_t cores_available = w->resources->cores.total - w->resources->cores.inuse; + int64_t memory_available = w->resources->memory.total - w->resources->memory.inuse; + int64_t gpus_available = w->resources->gpus.total - w->resources->gpus.inuse; rmsummary_merge_override_basic(limits, max); @@ -2646,9 +2652,9 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, min_proportion = MAX(min_proportion, min->memory / w->resources->memory.total); } - if (disk_for_sandboxes > 0) { - max_proportion = MAX(max_proportion, limits->disk / disk_for_sandboxes); - min_proportion = MAX(min_proportion, min->disk / disk_for_sandboxes); + if (disk_total > 0) { + max_proportion = MAX(max_proportion, limits->disk / disk_total); + min_proportion = MAX(min_proportion, min->disk / disk_total); } if (w->resources->gpus.total > 0) { @@ -2696,7 +2702,13 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, /* worker's disk is shared evenly among tasks that are not running, * thus the proportion is modified by the current overcommit * multiplier */ - limits->disk = MAX(1, MAX(limits->disk, floor(disk_for_sandboxes * max_proportion / q->resource_submit_multiplier))); + limits->disk = MAX(1, MAX(limits->disk, floor(disk_total * max_proportion / q->resource_submit_multiplier))); + + /* when the proportional resource allocation is larger than the available, use the available instead */ + limits->cores = MIN(limits->cores, cores_available); + limits->memory = MIN(limits->memory, memory_available); + limits->disk = MIN(limits->disk, disk_available); + limits->gpus = MIN(limits->gpus, gpus_available); } } @@ -2707,7 +2719,7 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, /* At least one specified resource would use the whole worker, thus * using whole worker for all unspecified resources. */ if ((limits->cores > 0 && limits->cores >= w->resources->cores.total) || (limits->gpus > 0 && limits->gpus >= w->resources->gpus.total) || - (limits->memory > 0 && limits->memory >= w->resources->memory.total) || (limits->disk > 0 && limits->disk >= disk_for_sandboxes)) { + (limits->memory > 0 && limits->memory >= w->resources->memory.total) || (limits->disk > 0 && limits->disk >= disk_total)) { use_whole_worker = 1; } @@ -2728,20 +2740,20 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, } if (limits->disk <= 0) { - limits->disk = disk_for_sandboxes; + limits->disk = disk_total; } } else if (vine_schedule_in_ramp_down(q)) { /* if in ramp down, use all the free space of that worker. note that we don't use * resource_submit_multiplier, as by definition in ramp down there are more workers than tasks. */ - limits->cores = limits->gpus > 0 ? 0 : (w->resources->cores.total - w->resources->cores.inuse); + limits->cores = limits->gpus > 0 ? 0 : cores_available; /* default gpus is 0 */ if (limits->gpus <= 0) { limits->gpus = 0; } - limits->memory = w->resources->memory.total - w->resources->memory.inuse; - limits->disk = disk_for_sandboxes; + limits->memory = memory_available; + limits->disk = disk_available; } /* never go below specified min resources. */ diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index 311e5d407f..930056de21 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -114,23 +114,23 @@ int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worke int ok = 1; - int64_t available_disk = overcommitted_resource_total(q, worker_net_resources->disk.total) - worker_net_resources->disk.inuse - t->input_files_size; - if (tr->disk > available_disk) { + int64_t disk_available = overcommitted_resource_total(q, worker_net_resources->disk.total) - worker_net_resources->disk.inuse - t->input_files_size; + if (tr->disk > disk_available) { ok = 0; } - int64_t available_cores = overcommitted_resource_total(q, worker_net_resources->cores.total) - worker_net_resources->cores.inuse; - if (tr->cores > available_cores) { + int64_t cores_available = overcommitted_resource_total(q, worker_net_resources->cores.total) - worker_net_resources->cores.inuse; + if (tr->cores > cores_available) { ok = 0; } - int64_t available_memory = overcommitted_resource_total(q, worker_net_resources->memory.total) - worker_net_resources->memory.inuse; - if (tr->memory > available_memory) { + int64_t memory_available = overcommitted_resource_total(q, worker_net_resources->memory.total) - worker_net_resources->memory.inuse; + if (tr->memory > memory_available) { ok = 0; } - int64_t available_gpus = overcommitted_resource_total(q, worker_net_resources->gpus.total) - worker_net_resources->gpus.inuse; - if (tr->gpus > available_gpus) { + int64_t gpus_available = overcommitted_resource_total(q, worker_net_resources->gpus.total) - worker_net_resources->gpus.inuse; + if (tr->gpus > gpus_available) { ok = 0; } @@ -146,7 +146,7 @@ int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worke fprintf(file, "%d,%f,%f,%f,%ld,%ld,%ld,%d\n", t->task_id, tr->cores, tr->memory, tr->disk, - available_cores, available_memory, available_disk, + cores_available, memory_available, disk_available, ok); fclose(file); From 18e09dd1d07748ed6ced55f2dff79845b179f476 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Wed, 11 Dec 2024 18:42:25 -0500 Subject: [PATCH 11/53] lint --- taskvine/src/manager/vine_manager.c | 10 +++++----- taskvine/src/manager/vine_schedule.c | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index 3c6a0750f2..8d0cb3f055 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2610,18 +2610,18 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, const struct rmsummary *min = vine_manager_task_resources_min(q, t); const struct rmsummary *max = vine_manager_task_resources_max(q, t); - /* available disk for all sandboxes */ + /* total disk for all sandboxes */ int64_t disk_total = w->resources->disk.total - BYTES_TO_MEGABYTES(w->inuse_cache); - /* do not count the size of input files as available. + /* do not count the size of input files as the total. * TODO: efficiently discount the size of files already at worker. */ disk_total -= t->input_files_size; /* current available resources on this worker */ int64_t disk_available = w->resources->disk.total - w->resources->disk.inuse - t->input_files_size; - int64_t cores_available = w->resources->cores.total - w->resources->cores.inuse; - int64_t memory_available = w->resources->memory.total - w->resources->memory.inuse; - int64_t gpus_available = w->resources->gpus.total - w->resources->gpus.inuse; + int64_t cores_available = w->resources->cores.total - w->resources->cores.inuse; + int64_t memory_available = w->resources->memory.total - w->resources->memory.inuse; + int64_t gpus_available = w->resources->gpus.total - w->resources->gpus.inuse; rmsummary_merge_override_basic(limits, max); diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index 930056de21..1cf4804543 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -144,8 +144,8 @@ int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worke return EXIT_FAILURE; } - fprintf(file, "%d,%f,%f,%f,%ld,%ld,%ld,%d\n", t->task_id, - tr->cores, tr->memory, tr->disk, + fprintf(file, "%d,%f,%f,%f,%ld,%ld,%ld,%d\n", t->task_id, + tr->cores, tr->memory, tr->disk, cores_available, memory_available, disk_available, ok); From 373325373026bf2d280830ecf036a65c8e774196 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Wed, 11 Dec 2024 19:43:16 -0500 Subject: [PATCH 12/53] count the global usable cores --- taskvine/src/manager/vine_manager.c | 33 +++++++++------------------- taskvine/src/manager/vine_manager.h | 1 + taskvine/src/manager/vine_schedule.c | 4 ++-- 3 files changed, 13 insertions(+), 25 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index 8d0cb3f055..876fcb0d05 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2409,6 +2409,7 @@ static vine_msg_code_t handle_resources(struct vine_manager *q, struct vine_work debug(D_VINE, "%s", line); if (sscanf(line, "cores %" PRId64, &total)) { + q->available_cores += (total - w->resources->cores.total); w->resources->cores.total = total; } else if (sscanf(line, "memory %" PRId64, &total)) { w->resources->memory.total = total; @@ -2816,6 +2817,8 @@ static vine_result_code_t start_one_task(struct vine_manager *q, struct vine_wor static void count_worker_resources(struct vine_manager *q, struct vine_worker_info *w) { + q->available_cores -= (w->resources->cores.total - w->resources->cores.inuse); + w->resources->cores.inuse = 0; w->resources->memory.inuse = 0; w->resources->disk.inuse = 0; @@ -2842,6 +2845,8 @@ static void count_worker_resources(struct vine_manager *q, struct vine_worker_in } w->resources->disk.inuse += ceil(BYTES_TO_MEGABYTES(w->inuse_cache)); + + q->available_cores += (w->resources->cores.total - w->resources->cores.inuse); } static void update_max_worker(struct vine_manager *q, struct vine_worker_info *w) @@ -3391,36 +3396,17 @@ the task to the worker. static int send_one_task(struct vine_manager *q) { + if (q->available_cores <= 0) { + return 0; + } + int t_idx; struct vine_task *t; - uint64_t task_id; struct vine_worker_info *w = NULL; int iter_count = 0; - int iter_depth = MIN(priority_queue_size(q->ready_tasks), q->attempt_schedule_depth); - /* first see if there are any available cores */ - int has_available_cores = 0; - char *key; - HASH_TABLE_ITERATE(q->worker_table, key, w) - { - if (w->resources->cores.total - w->resources->cores.inuse > 0) { - has_available_cores = 1; - break; - } - ITABLE_ITERATE(w->current_tasks, task_id, t) - { - if (t->type == VINE_TASK_TYPE_LIBRARY_INSTANCE && t->provides_library && t->function_slots_inuse < t->function_slots_total) { - has_available_cores = 1; - break; - } - } - } - if (!has_available_cores) { - return 0; - } - // Iterate over the ready tasks by priority. // The first time we arrive here, the task with the highest priority is considered. However, there may be various reasons // that this particular task is not eligible to run, such as: 1) the task requires more resources than the workers have; @@ -3916,6 +3902,7 @@ struct vine_manager *vine_ssl_create(int port, const char *key, const char *cert q->next_task_id = 1; q->fixed_location_in_queue = 0; + q->available_cores = 0; q->ready_tasks = priority_queue_create(0); q->running_table = itable_create(0); diff --git a/taskvine/src/manager/vine_manager.h b/taskvine/src/manager/vine_manager.h index b6951937f5..3870b8e281 100644 --- a/taskvine/src/manager/vine_manager.h +++ b/taskvine/src/manager/vine_manager.h @@ -138,6 +138,7 @@ struct vine_manager { int fixed_location_in_queue; /* Number of fixed location tasks currently being managed */ int num_tasks_left; /* Optional: Number of tasks remaining, if given by user. @ref vine_set_num_tasks */ int busy_waiting_flag; /* Set internally in main loop if no messages were processed -> wait longer. */ + int available_cores; /* Number of cores available among all workers. */ /* Accumulation of statistics for reporting to the caller. */ diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index 1cf4804543..8d35b0e296 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -134,7 +134,7 @@ int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worke ok = 0; } - /* TEST ^^^ +// /* TEST ^^^ const char *filename = "resource_allocation.csv"; FILE *file = fopen(filename, "a"); @@ -150,7 +150,7 @@ int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worke ok); fclose(file); - */ +// */ vine_resources_delete(worker_net_resources); return ok; From 0c2d22d289a0d3a701bf8d7e1fec0cd7e7c91155 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Wed, 11 Dec 2024 20:27:17 -0500 Subject: [PATCH 13/53] count slots and cores --- taskvine/src/manager/vine_manager.c | 16 +++++++++++++++- taskvine/src/manager/vine_manager.h | 1 + taskvine/src/manager/vine_schedule.c | 18 ------------------ 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index 876fcb0d05..d0edbd461e 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2790,6 +2790,7 @@ static vine_result_code_t start_one_task(struct vine_manager *q, struct vine_wor } else { t->function_slots_total = t->function_slots_requested; } + q->available_slots += t->function_slots_total; } char *command_line; @@ -2943,6 +2944,7 @@ static vine_result_code_t commit_task_to_worker(struct vine_manager *q, struct v } /* If start_one_task_fails, this will be decremented in handle_failure below. */ t->library_task->function_slots_inuse++; + q->available_slots--; } t->hostname = xxstrdup(w->hostname); @@ -3103,7 +3105,13 @@ static void reap_task_from_worker(struct vine_manager *q, struct vine_worker_inf */ if (t->needs_library) { + int previous_slots_inuse = t->library_task->function_slots_inuse; t->library_task->function_slots_inuse = MAX(0, t->library_task->function_slots_inuse - 1); + q->available_slots += (previous_slots_inuse - t->library_task->function_slots_inuse); + } + + if (t->provides_library) { + q->available_slots -= t->function_slots_total; } t->worker = 0; @@ -3346,27 +3354,32 @@ static struct vine_worker_info *consider_task(struct vine_manager *q, struct vin // Skip task if min requested start time not met. if (t->resources_requested->start > now_secs) { + printf("1\n"); return NULL; } // Skip if this task failed recently if (t->time_when_last_failure + q->transient_error_interval > now_usecs) { + printf("2\n"); return NULL; } // Skip if category already running maximum allowed tasks struct category *c = vine_category_lookup_or_create(q, t->category); if (c->max_concurrent > -1 && c->max_concurrent <= c->vine_stats->tasks_running) { + printf("3\n"); return NULL; } // Skip task if temp input files have not been materialized. if (!vine_manager_check_inputs_available(q, t)) { + printf("4\n"); return NULL; } // Skip function call task if no suitable library template was installed if (!vine_manager_check_library_for_function_call(q, t)) { + printf("5\n"); return NULL; } @@ -3396,7 +3409,7 @@ the task to the worker. static int send_one_task(struct vine_manager *q) { - if (q->available_cores <= 0) { + if (q->available_cores + q->available_slots <= 0 || priority_queue_size(q->ready_tasks) == 0) { return 0; } @@ -3903,6 +3916,7 @@ struct vine_manager *vine_ssl_create(int port, const char *key, const char *cert q->next_task_id = 1; q->fixed_location_in_queue = 0; q->available_cores = 0; + q->available_slots = 0; q->ready_tasks = priority_queue_create(0); q->running_table = itable_create(0); diff --git a/taskvine/src/manager/vine_manager.h b/taskvine/src/manager/vine_manager.h index 3870b8e281..57061cdc33 100644 --- a/taskvine/src/manager/vine_manager.h +++ b/taskvine/src/manager/vine_manager.h @@ -139,6 +139,7 @@ struct vine_manager { int num_tasks_left; /* Optional: Number of tasks remaining, if given by user. @ref vine_set_num_tasks */ int busy_waiting_flag; /* Set internally in main loop if no messages were processed -> wait longer. */ int available_cores; /* Number of cores available among all workers. */ + int available_slots; /* Number of function slots available among all workers. */ /* Accumulation of statistics for reporting to the caller. */ diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index 8d35b0e296..1a6791bbe6 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -134,24 +134,6 @@ int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worke ok = 0; } -// /* TEST ^^^ - - const char *filename = "resource_allocation.csv"; - FILE *file = fopen(filename, "a"); - - if (file == NULL) { - perror("failed to open file"); - return EXIT_FAILURE; - } - - fprintf(file, "%d,%f,%f,%f,%ld,%ld,%ld,%d\n", t->task_id, - tr->cores, tr->memory, tr->disk, - cores_available, memory_available, disk_available, - ok); - - fclose(file); -// */ - vine_resources_delete(worker_net_resources); return ok; } From 6e8649db0dd6734293f8e02f0523cb88de95f3a5 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Wed, 11 Dec 2024 20:28:38 -0500 Subject: [PATCH 14/53] rename --- taskvine/src/manager/vine_manager.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index d0edbd461e..eef91aa07c 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2409,7 +2409,7 @@ static vine_msg_code_t handle_resources(struct vine_manager *q, struct vine_work debug(D_VINE, "%s", line); if (sscanf(line, "cores %" PRId64, &total)) { - q->available_cores += (total - w->resources->cores.total); + q->total_available_cores += (total - w->resources->cores.total); w->resources->cores.total = total; } else if (sscanf(line, "memory %" PRId64, &total)) { w->resources->memory.total = total; @@ -2790,7 +2790,7 @@ static vine_result_code_t start_one_task(struct vine_manager *q, struct vine_wor } else { t->function_slots_total = t->function_slots_requested; } - q->available_slots += t->function_slots_total; + q->total_available_slots += t->function_slots_total; } char *command_line; @@ -2818,7 +2818,7 @@ static vine_result_code_t start_one_task(struct vine_manager *q, struct vine_wor static void count_worker_resources(struct vine_manager *q, struct vine_worker_info *w) { - q->available_cores -= (w->resources->cores.total - w->resources->cores.inuse); + q->total_available_cores -= (w->resources->cores.total - w->resources->cores.inuse); w->resources->cores.inuse = 0; w->resources->memory.inuse = 0; @@ -2847,7 +2847,7 @@ static void count_worker_resources(struct vine_manager *q, struct vine_worker_in w->resources->disk.inuse += ceil(BYTES_TO_MEGABYTES(w->inuse_cache)); - q->available_cores += (w->resources->cores.total - w->resources->cores.inuse); + q->total_available_cores += (w->resources->cores.total - w->resources->cores.inuse); } static void update_max_worker(struct vine_manager *q, struct vine_worker_info *w) @@ -2944,7 +2944,7 @@ static vine_result_code_t commit_task_to_worker(struct vine_manager *q, struct v } /* If start_one_task_fails, this will be decremented in handle_failure below. */ t->library_task->function_slots_inuse++; - q->available_slots--; + q->total_available_slots--; } t->hostname = xxstrdup(w->hostname); @@ -3107,11 +3107,11 @@ static void reap_task_from_worker(struct vine_manager *q, struct vine_worker_inf if (t->needs_library) { int previous_slots_inuse = t->library_task->function_slots_inuse; t->library_task->function_slots_inuse = MAX(0, t->library_task->function_slots_inuse - 1); - q->available_slots += (previous_slots_inuse - t->library_task->function_slots_inuse); + q->total_available_slots += (previous_slots_inuse - t->library_task->function_slots_inuse); } if (t->provides_library) { - q->available_slots -= t->function_slots_total; + q->total_available_slots -= t->function_slots_total; } t->worker = 0; @@ -3409,7 +3409,7 @@ the task to the worker. static int send_one_task(struct vine_manager *q) { - if (q->available_cores + q->available_slots <= 0 || priority_queue_size(q->ready_tasks) == 0) { + if (q->total_available_cores + q->total_available_slots <= 0 || priority_queue_size(q->ready_tasks) == 0) { return 0; } @@ -3915,8 +3915,8 @@ struct vine_manager *vine_ssl_create(int port, const char *key, const char *cert q->next_task_id = 1; q->fixed_location_in_queue = 0; - q->available_cores = 0; - q->available_slots = 0; + q->total_available_cores = 0; + q->total_available_slots = 0; q->ready_tasks = priority_queue_create(0); q->running_table = itable_create(0); From a3e286fde2f786e749bda41024011de7bd5f89a4 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Wed, 11 Dec 2024 20:32:45 -0500 Subject: [PATCH 15/53] remove comments --- taskvine/src/manager/vine_manager.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index eef91aa07c..a7e8c5e293 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -3354,32 +3354,27 @@ static struct vine_worker_info *consider_task(struct vine_manager *q, struct vin // Skip task if min requested start time not met. if (t->resources_requested->start > now_secs) { - printf("1\n"); return NULL; } // Skip if this task failed recently if (t->time_when_last_failure + q->transient_error_interval > now_usecs) { - printf("2\n"); return NULL; } // Skip if category already running maximum allowed tasks struct category *c = vine_category_lookup_or_create(q, t->category); if (c->max_concurrent > -1 && c->max_concurrent <= c->vine_stats->tasks_running) { - printf("3\n"); return NULL; } // Skip task if temp input files have not been materialized. if (!vine_manager_check_inputs_available(q, t)) { - printf("4\n"); return NULL; } // Skip function call task if no suitable library template was installed if (!vine_manager_check_library_for_function_call(q, t)) { - printf("5\n"); return NULL; } From e264f74f76ee12797dd68c40de805438aac2e4d6 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Wed, 11 Dec 2024 20:34:23 -0500 Subject: [PATCH 16/53] variable init --- taskvine/src/manager/vine_manager.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/taskvine/src/manager/vine_manager.h b/taskvine/src/manager/vine_manager.h index 57061cdc33..2331a4bada 100644 --- a/taskvine/src/manager/vine_manager.h +++ b/taskvine/src/manager/vine_manager.h @@ -138,8 +138,8 @@ struct vine_manager { int fixed_location_in_queue; /* Number of fixed location tasks currently being managed */ int num_tasks_left; /* Optional: Number of tasks remaining, if given by user. @ref vine_set_num_tasks */ int busy_waiting_flag; /* Set internally in main loop if no messages were processed -> wait longer. */ - int available_cores; /* Number of cores available among all workers. */ - int available_slots; /* Number of function slots available among all workers. */ + int total_available_cores; /* Number of cores available among all workers. */ + int total_available_slots; /* Number of function slots available among all workers. */ /* Accumulation of statistics for reporting to the caller. */ From e207615a3bff179f78a47ee78048cd1e4a2c19b9 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 12 Dec 2024 00:57:20 -0500 Subject: [PATCH 17/53] check worker cores --- taskvine/src/manager/vine_schedule.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index 1a6791bbe6..7731da5a8a 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -182,6 +182,11 @@ int check_worker_against_task(struct vine_manager *q, struct vine_worker_info *w return 0; } + /* worker is fully occupied */ + if (w->resources->cores.total == w->resources->cores.inuse) { + return 0; + } + /* Don't send tasks to this worker if it is in draining mode (no more tasks). */ if (w->draining) { return 0; From 1f3cb2dd8787b5ebfaf896e7508c2fa7de315be6 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 12 Dec 2024 01:00:59 -0500 Subject: [PATCH 18/53] log resource allocation failures --- taskvine/src/manager/vine_schedule.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index 7731da5a8a..b432b054ea 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -134,6 +134,12 @@ int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worke ok = 0; } + // it is concerning if the resource allocation fails + if (!ok) { + debug(D_VINE, "Resource allocation for task %d on worker %s fails: %.0f, %.2f, %.2f, %ld, %ld, %ld", + t->task_id, w->hostname, tr->cores, tr->memory, tr->disk, cores_available, memory_available, disk_available); + } + vine_resources_delete(worker_net_resources); return ok; } From 9c9caa484bbb636978d0a697334939460f8751fb Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 12 Dec 2024 01:02:39 -0500 Subject: [PATCH 19/53] lint --- taskvine/src/manager/vine_schedule.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index b432b054ea..baeee1e670 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -136,8 +136,7 @@ int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worke // it is concerning if the resource allocation fails if (!ok) { - debug(D_VINE, "Resource allocation for task %d on worker %s fails: %.0f, %.2f, %.2f, %ld, %ld, %ld", - t->task_id, w->hostname, tr->cores, tr->memory, tr->disk, cores_available, memory_available, disk_available); + debug(D_VINE, "Resource allocation for task %d on worker %s fails: %.0f, %.2f, %.2f, %ld, %ld, %ld", t->task_id, w->hostname, tr->cores, tr->memory, tr->disk, cores_available, memory_available, disk_available); } vine_resources_delete(worker_net_resources); From 47e27b0267b69fa8907965ec6a8ee812a552499e Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 12 Dec 2024 01:14:25 -0500 Subject: [PATCH 20/53] don't use %ld --- taskvine/src/manager/vine_schedule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index baeee1e670..56f2ab17ca 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -136,7 +136,7 @@ int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worke // it is concerning if the resource allocation fails if (!ok) { - debug(D_VINE, "Resource allocation for task %d on worker %s fails: %.0f, %.2f, %.2f, %ld, %ld, %ld", t->task_id, w->hostname, tr->cores, tr->memory, tr->disk, cores_available, memory_available, disk_available); + debug(D_VINE, "Resource allocation for task %d on worker %s fails: %.0f, %.2f, %.2f, %" PRId64 ", %" PRId64 ", %" PRId64 "", t->task_id, w->hostname, tr->cores, tr->memory, tr->disk, cores_available, memory_available, disk_available); } vine_resources_delete(worker_net_resources); From b95f32bbfb62e1e02fe8f57825a96281b6a9a7bc Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 12 Dec 2024 01:24:38 -0500 Subject: [PATCH 21/53] check mem and disk as well --- taskvine/src/manager/vine_schedule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index 56f2ab17ca..f2d4fe154a 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -188,7 +188,7 @@ int check_worker_against_task(struct vine_manager *q, struct vine_worker_info *w } /* worker is fully occupied */ - if (w->resources->cores.total == w->resources->cores.inuse) { + if ((w->resources->cores.total == w->resources->cores.inuse) || w->resources->memory.total == w->resources->memory.inuse || w->resources->disk.total == w->resources->disk.inuse) { return 0; } From 1b5a23b9e36221054191c57ad82426aceb909beb Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 12 Dec 2024 08:19:14 -0500 Subject: [PATCH 22/53] fix --- taskvine/src/manager/vine_schedule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index f2d4fe154a..d44f3ca4b8 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -188,7 +188,7 @@ int check_worker_against_task(struct vine_manager *q, struct vine_worker_info *w } /* worker is fully occupied */ - if ((w->resources->cores.total == w->resources->cores.inuse) || w->resources->memory.total == w->resources->memory.inuse || w->resources->disk.total == w->resources->disk.inuse) { + if ((w->resources->cores.total <= w->resources->cores.inuse) || w->resources->memory.total <= w->resources->memory.inuse || w->resources->disk.total <= w->resources->disk.inuse) { return 0; } From 1074d4576d13f79f22a8f6e07ea98d58c1e4336b Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Fri, 13 Dec 2024 14:15:49 -0500 Subject: [PATCH 23/53] shortcut on time --- taskvine/src/manager/vine_schedule.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index d44f3ca4b8..de0e53dac3 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -112,35 +112,29 @@ int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worke } } - int ok = 1; - int64_t disk_available = overcommitted_resource_total(q, worker_net_resources->disk.total) - worker_net_resources->disk.inuse - t->input_files_size; if (tr->disk > disk_available) { - ok = 0; + return 0; } int64_t cores_available = overcommitted_resource_total(q, worker_net_resources->cores.total) - worker_net_resources->cores.inuse; if (tr->cores > cores_available) { - ok = 0; + return 0; } int64_t memory_available = overcommitted_resource_total(q, worker_net_resources->memory.total) - worker_net_resources->memory.inuse; if (tr->memory > memory_available) { - ok = 0; + return 0; } int64_t gpus_available = overcommitted_resource_total(q, worker_net_resources->gpus.total) - worker_net_resources->gpus.inuse; if (tr->gpus > gpus_available) { - ok = 0; - } - - // it is concerning if the resource allocation fails - if (!ok) { - debug(D_VINE, "Resource allocation for task %d on worker %s fails: %.0f, %.2f, %.2f, %" PRId64 ", %" PRId64 ", %" PRId64 "", t->task_id, w->hostname, tr->cores, tr->memory, tr->disk, cores_available, memory_available, disk_available); + return 0; } vine_resources_delete(worker_net_resources); - return ok; + + return 1; } /* t->disk only specifies the size of output and ephemeral files. Here we check if the task would fit together with all its input files From b13309c72835f1bdaa024c4c45980d7d481dbca8 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Mon, 16 Dec 2024 13:40:20 -0500 Subject: [PATCH 24/53] two proportional allocations --- taskvine/src/manager/vine_manager.c | 211 +++++++++++----------------- 1 file changed, 82 insertions(+), 129 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index a7e8c5e293..14ed289345 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2594,7 +2594,6 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, /* Special case: A function-call task consumes no resources. */ /* Return early, otherwise these zeroes are expanded to use the whole worker. */ - if (t->needs_library) { limits->cores = 0; limits->memory = 0; @@ -2603,164 +2602,106 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, return limits; } + /* For disk, do not count the size of input files + * TODO: efficiently discount the size of files already at worker. */ if (t->input_files_size < 0) { vine_manager_compute_input_size(q, t); } - /* Compute the minimum and maximum resources for this task. */ - const struct rmsummary *min = vine_manager_task_resources_min(q, t); - const struct rmsummary *max = vine_manager_task_resources_max(q, t); + /* Shortcut if the task explicitly requests all resources */ + if (t->resources_requested->memory != -1 && t->resources_requested->disk != -1 && (t->resources_requested->cores + t->resources_requested->gpus != -1)) { + rmsummary_merge_override_basic(limits, t->resources_requested); + return limits; + } - /* total disk for all sandboxes */ - int64_t disk_total = w->resources->disk.total - BYTES_TO_MEGABYTES(w->inuse_cache); + /* The total resources we take into account for resource estimate */ + int64_t cores_total = w->resources->cores.total; + int64_t memory_total = w->resources->memory.total; + int64_t disk_total = w->resources->disk.total - BYTES_TO_MEGABYTES(w->inuse_cache) - t->input_files_size; + int64_t gpus_total = w->resources->gpus.total; - /* do not count the size of input files as the total. - * TODO: efficiently discount the size of files already at worker. */ - disk_total -= t->input_files_size; - - /* current available resources on this worker */ - int64_t disk_available = w->resources->disk.total - w->resources->disk.inuse - t->input_files_size; - int64_t cores_available = w->resources->cores.total - w->resources->cores.inuse; + /* The current available resources on this worker */ + int64_t cores_available = w->resources->cores.total - w->resources->cores.inuse; int64_t memory_available = w->resources->memory.total - w->resources->memory.inuse; + int64_t disk_available = w->resources->disk.total - w->resources->disk.inuse - t->input_files_size; int64_t gpus_available = w->resources->gpus.total - w->resources->gpus.inuse; - rmsummary_merge_override_basic(limits, max); + /* Shortcut if the ramp down mode is enabled. In this case, use all the free space of that worker if the user has not specified. + * Note that we don't use resource_submit_multiplier, as by definition in ramp down there are more workers than tasks. */ + if (vine_schedule_in_ramp_down(q)) { + limits->cores = cores_available; + limits->memory = memory_available; + limits->disk = disk_available; + limits->gpus = gpus_available; + rmsummary_merge_override_basic(limits, t->resources_requested); + return limits; + } - int use_whole_worker = 1; + /* When arrive here, we estimate some of the unspecified resources. Different strategies can be used. */ + /* Compute the minimum and maximum resources for this task. */ + const struct rmsummary *min = vine_manager_task_resources_min(q, t); + const struct rmsummary *max = vine_manager_task_resources_max(q, t); - int proportional_whole_tasks = q->proportional_whole_tasks; - if (t->resources_requested->memory > -1 || t->resources_requested->disk > -1) { - /* if mem or disk are specified explicitely, do not expand resources to fill an integer number of tasks. With this, - * the task is assigned exactly the memory and disk specified. We do not do this for cores and gpus, as the use case - * here is to specify the number of cores and allocated the rest of the resources evenly. */ - proportional_whole_tasks = 0; - } + /* Use the max as the limits */ + rmsummary_merge_override_basic(limits, max); + + /* Never go below min resources. */ + // rmsummary_merge_max(limits, min); - /* Proportionally assign the worker's resources to the task if configured. */ if (q->proportional_resources) { + int conservative_proportional_resources = 0; /* Compute the proportion of the worker the task shall have across resource types. */ double max_proportion = -1; - double min_proportion = -1; - if (w->resources->cores.total > 0) { - max_proportion = MAX(max_proportion, limits->cores / w->resources->cores.total); - min_proportion = MAX(min_proportion, min->cores / w->resources->cores.total); - } + int64_t cores_portion = conservative_proportional_resources ? cores_total : cores_available; + int64_t memory_portion = conservative_proportional_resources ? memory_total : memory_available; + int64_t disk_portion = conservative_proportional_resources ? disk_total : disk_available; + int64_t gpus_portion = conservative_proportional_resources ? gpus_total : gpus_available; - if (w->resources->memory.total > 0) { - max_proportion = MAX(max_proportion, limits->memory / w->resources->memory.total); - min_proportion = MAX(min_proportion, min->memory / w->resources->memory.total); + if (cores_portion > 0) { + max_proportion = MAX(max_proportion, (double)limits->cores / cores_portion); } - - if (disk_total > 0) { - max_proportion = MAX(max_proportion, limits->disk / disk_total); - min_proportion = MAX(min_proportion, min->disk / disk_total); + if (memory_portion > 0) { + max_proportion = MAX(max_proportion, (double)limits->memory / memory_portion); } - - if (w->resources->gpus.total > 0) { - max_proportion = MAX(max_proportion, limits->gpus / w->resources->gpus.total); - min_proportion = MAX(min_proportion, min->gpus / w->resources->gpus.total); + if (disk_portion > 0) { + max_proportion = MAX(max_proportion, (double)limits->disk / disk_portion); } - - /* If a max_proportion was defined, it cannot be less than a proportion using the minimum - * resources for the category. If it was defined, then the min_proportion is not relevant as the - * task will try to use the whole worker. */ - if (max_proportion != -1) { - max_proportion = MAX(max_proportion, min_proportion); + if (gpus_portion > 0) { + max_proportion = MAX(max_proportion, (double)limits->gpus / gpus_portion); } - /* If max_proportion or min_proportion > 1, then the task does not fit the worker for the - * specified resources. For the unspecified resources we use the whole - * worker as not to trigger a warning when checking for tasks that can't - * run on any available worker. */ - if (max_proportion > 1 || min_proportion > 1) { - use_whole_worker = 1; - } else if (max_proportion > 0) { - use_whole_worker = 0; - - // adjust max_proportion so that an integer number of tasks fit the worker. - if (proportional_whole_tasks) { - max_proportion = 1.0 / (floor(1.0 / max_proportion)); - } - - /* when cores are unspecified, they are set to 0 if gpus are specified. - * Otherwise they get a proportion according to specified - * resources. Tasks will get at least one core. */ - if (limits->cores < 0 && limits->gpus > 0) { - limits->cores = 0; - } else { - limits->cores = MAX(1, MAX(limits->cores, floor(w->resources->cores.total * max_proportion))); - } - - /* unspecified gpus are always 0 */ - if (limits->gpus < 0) { - limits->gpus = 0; - } - - limits->memory = MAX(1, MAX(limits->memory, floor(w->resources->memory.total * max_proportion))); - - /* worker's disk is shared evenly among tasks that are not running, - * thus the proportion is modified by the current overcommit - * multiplier */ - limits->disk = MAX(1, MAX(limits->disk, floor(disk_total * max_proportion / q->resource_submit_multiplier))); - - /* when the proportional resource allocation is larger than the available, use the available instead */ - limits->cores = MIN(limits->cores, cores_available); - limits->memory = MIN(limits->memory, memory_available); - limits->disk = MIN(limits->disk, disk_available); - limits->gpus = MIN(limits->gpus, gpus_available); - } - } - - /* If no resource was specified, use whole worker. */ - if (limits->cores < 1 && limits->gpus < 1 && limits->memory < 1 && limits->disk < 1) { - use_whole_worker = 1; - } - /* At least one specified resource would use the whole worker, thus - * using whole worker for all unspecified resources. */ - if ((limits->cores > 0 && limits->cores >= w->resources->cores.total) || (limits->gpus > 0 && limits->gpus >= w->resources->gpus.total) || - (limits->memory > 0 && limits->memory >= w->resources->memory.total) || (limits->disk > 0 && limits->disk >= disk_total)) { - - use_whole_worker = 1; - } - - if (use_whole_worker) { - /* default cores for tasks that define gpus is 0 */ - if (limits->cores <= 0) { - limits->cores = limits->gpus > 0 ? 0 : w->resources->cores.total; - } - - /* default gpus is 0 */ - if (limits->gpus <= 0) { - limits->gpus = 0; + /* Adjust max_proportion so that an integer number of tasks fit the worker. */ + /* If mem or disk are specified explicitely, do not expand resources to fill an integer number of tasks. With this, + * the task is assigned exactly the memory and disk specified. We do not do this for cores and gpus, as the use case + * here is to specify the number of cores and allocated the rest of the resources evenly. */ + if (q->proportional_whole_tasks && (t->resources_requested->memory == -1 && t->resources_requested->disk == -1)) { + max_proportion = 1.0 / floor(1.0 / max_proportion); } - if (limits->memory <= 0) { - limits->memory = w->resources->memory.total; + /* If the estimated portion is invalid, use the entire portion. */ + if (max_proportion <= 0 || max_proportion > 1) { + max_proportion = 1; } - if (limits->disk <= 0) { - limits->disk = disk_total; - } - } else if (vine_schedule_in_ramp_down(q)) { - /* if in ramp down, use all the free space of that worker. note that we don't use - * resource_submit_multiplier, as by definition in ramp down there are more workers than tasks. */ - limits->cores = limits->gpus > 0 ? 0 : cores_available; - - /* default gpus is 0 */ - if (limits->gpus <= 0) { - limits->gpus = 0; - } + limits->cores = MAX(1, MAX(limits->cores, floor(cores_portion * max_proportion))); + limits->memory = MAX(1, MAX(limits->memory, floor(memory_portion * max_proportion))); + limits->disk = MAX(1, MAX(limits->disk, floor(disk_portion * max_proportion / q->resource_submit_multiplier))); + limits->gpus = MAX(1, MAX(limits->gpus, floor(gpus_portion * max_proportion))); + } else { + /* If not proportional, choose the entire available resources. */ + limits->cores = cores_available; limits->memory = memory_available; limits->disk = disk_available; + limits->gpus = gpus_available; } - /* never go below specified min resources. */ + /* Never go below min resources. */ rmsummary_merge_max(limits, min); - /* assume the user knows what they are doing... */ + /* Overwrite those that have been requested. */ rmsummary_merge_override_basic(limits, t->resources_requested); return limits; @@ -3173,8 +3114,9 @@ static int vine_manager_transfer_capacity_available(struct vine_manager *q, stru /* Is the file already present on that worker? */ struct vine_file_replica *replica; - if ((replica = vine_file_replica_table_lookup(w, m->file->cached_name))) + if ((replica = vine_file_replica_table_lookup(w, m->file->cached_name))) { continue; + } struct vine_worker_info *peer; int found_match = 0; @@ -3198,8 +3140,9 @@ static int vine_manager_transfer_capacity_available(struct vine_manager *q, stru } /* If that resulted in a match, move on to the next file. */ - if (found_match) + if (found_match) { continue; + } /* If no match was found, the behavior depends on the original file type. @@ -3388,8 +3331,9 @@ static struct vine_worker_info *consider_task(struct vine_manager *q, struct vin // Check if there is transfer capacity available. if (q->peer_transfers_enabled) { - if (!vine_manager_transfer_capacity_available(q, w, t)) + if (!vine_manager_transfer_capacity_available(q, w, t)) { return NULL; + } } // All checks passed @@ -4655,8 +4599,16 @@ int vine_submit(struct vine_manager *q, struct vine_task *t) t->time_when_submitted = timestamp_get(); q->stats->tasks_submitted++; - if (q->monitor_mode != VINE_MON_DISABLED) + if (q->monitor_mode != VINE_MON_DISABLED) { vine_monitor_add_files(q, t); + } + + /* If the task requests gpus, it can't request cores */ + if (t->resources_requested->gpus > 0) { + t->resources_requested->cores = 0; + } else { + t->resources_requested->gpus = 0; + } rmsummary_merge_max(q->max_task_resources_requested, t->resources_requested); @@ -4920,6 +4872,7 @@ static int connect_new_workers(struct vine_manager *q, int stoptime, int max_new // If the manager link was awake, then accept at most max_new_workers. // Note we are using the information gathered in poll_active_workers, which // is a little ugly. + if (q->poll_table[0].revents) { do { add_worker(q); From 04f760d79e55f7924788c40f46b251642f5590bd Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Mon, 16 Dec 2024 15:12:57 -0500 Subject: [PATCH 25/53] update proportional --- taskvine/src/manager/vine_manager.c | 48 +++++++++++++++++++---------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index 14ed289345..33aaa478e5 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2621,13 +2621,13 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, int64_t gpus_total = w->resources->gpus.total; /* The current available resources on this worker */ - int64_t cores_available = w->resources->cores.total - w->resources->cores.inuse; + int64_t cores_available = w->resources->cores.total - w->resources->cores.inuse; int64_t memory_available = w->resources->memory.total - w->resources->memory.inuse; int64_t disk_available = w->resources->disk.total - w->resources->disk.inuse - t->input_files_size; int64_t gpus_available = w->resources->gpus.total - w->resources->gpus.inuse; /* Shortcut if the ramp down mode is enabled. In this case, use all the free space of that worker if the user has not specified. - * Note that we don't use resource_submit_multiplier, as by definition in ramp down there are more workers than tasks. */ + * Note that we don't use resource_submit_multiplier, as by definition in ramp down there are more workers than tasks. */ if (vine_schedule_in_ramp_down(q)) { limits->cores = cores_available; limits->memory = memory_available; @@ -2646,7 +2646,7 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, rmsummary_merge_override_basic(limits, max); /* Never go below min resources. */ - // rmsummary_merge_max(limits, min); + rmsummary_merge_max(limits, min); if (q->proportional_resources) { int conservative_proportional_resources = 0; @@ -2685,17 +2685,38 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, max_proportion = 1; } - limits->cores = MAX(1, MAX(limits->cores, floor(cores_portion * max_proportion))); - limits->memory = MAX(1, MAX(limits->memory, floor(memory_portion * max_proportion))); + /* When cores are unspecified, they are set to 0 if gpus are specified. + * Otherwise they get a proportion according to specified resources. + * Tasks will get at least one core */ + if (limits->cores == -1 && limits->gpus > 0) { + limits->cores = 0; + } else { + limits->cores = MAX(1, MAX(limits->cores, floor(cores_portion * max_proportion))); + } + + /* When gpus are unspecified, they are set to 0 if cores are specified. */ + if (limits->gpus == -1 && limits->cores > 0) { + limits->gpus = 0; + } else { + /* Do not allocate a proportion of gpus */ + } + limits->disk = MAX(1, MAX(limits->disk, floor(disk_portion * max_proportion / q->resource_submit_multiplier))); - limits->gpus = MAX(1, MAX(limits->gpus, floor(gpus_portion * max_proportion))); + limits->memory = MAX(1, MAX(limits->memory, floor(memory_portion * max_proportion))); + } - } else { - /* If not proportional, choose the entire available resources. */ - limits->cores = cores_available; + /* If one resource is not specified, use the available instead */ + if (limits->cores <= 0) { + limits->cores = limits->gpus <= 0 ? cores_available : 0; + } + if (limits->memory <= 0) { limits->memory = memory_available; + } + if (limits->disk <= 0) { limits->disk = disk_available; - limits->gpus = gpus_available; + } + if (limits->gpus <= 0) { + limits->gpus = limits->cores <= 0 ? gpus_available : 0; } /* Never go below min resources. */ @@ -4603,13 +4624,6 @@ int vine_submit(struct vine_manager *q, struct vine_task *t) vine_monitor_add_files(q, t); } - /* If the task requests gpus, it can't request cores */ - if (t->resources_requested->gpus > 0) { - t->resources_requested->cores = 0; - } else { - t->resources_requested->gpus = 0; - } - rmsummary_merge_max(q->max_task_resources_requested, t->resources_requested); return (t->task_id); From d1d1f2b21c3ec7c8a9c6ac5b4f57c96597cfca6c Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Mon, 16 Dec 2024 15:33:05 -0500 Subject: [PATCH 26/53] check input_files_size --- taskvine/src/manager/vine_manager.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index 33aaa478e5..3406c45e3f 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2602,12 +2602,6 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, return limits; } - /* For disk, do not count the size of input files - * TODO: efficiently discount the size of files already at worker. */ - if (t->input_files_size < 0) { - vine_manager_compute_input_size(q, t); - } - /* Shortcut if the task explicitly requests all resources */ if (t->resources_requested->memory != -1 && t->resources_requested->disk != -1 && (t->resources_requested->cores + t->resources_requested->gpus != -1)) { rmsummary_merge_override_basic(limits, t->resources_requested); @@ -2617,15 +2611,25 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, /* The total resources we take into account for resource estimate */ int64_t cores_total = w->resources->cores.total; int64_t memory_total = w->resources->memory.total; - int64_t disk_total = w->resources->disk.total - BYTES_TO_MEGABYTES(w->inuse_cache) - t->input_files_size; + int64_t disk_total = w->resources->disk.total - BYTES_TO_MEGABYTES(w->inuse_cache); int64_t gpus_total = w->resources->gpus.total; /* The current available resources on this worker */ int64_t cores_available = w->resources->cores.total - w->resources->cores.inuse; int64_t memory_available = w->resources->memory.total - w->resources->memory.inuse; - int64_t disk_available = w->resources->disk.total - w->resources->disk.inuse - t->input_files_size; + int64_t disk_available = w->resources->disk.total - w->resources->disk.inuse; int64_t gpus_available = w->resources->gpus.total - w->resources->gpus.inuse; + /* For disk, do not count the size of input files + * TODO: efficiently discount the size of files already at worker. */ + if (t->input_files_size < 0) { + vine_manager_compute_input_size(q, t); + } + if (t->input_files_size > 0) { + disk_total -= t->input_files_size; + disk_available -= t->input_files_size; + } + /* Shortcut if the ramp down mode is enabled. In this case, use all the free space of that worker if the user has not specified. * Note that we don't use resource_submit_multiplier, as by definition in ramp down there are more workers than tasks. */ if (vine_schedule_in_ramp_down(q)) { @@ -2705,7 +2709,7 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, limits->memory = MAX(1, MAX(limits->memory, floor(memory_portion * max_proportion))); } - /* If one resource is not specified, use the available instead */ + /* If one of the resources is not specified, use the available instead */ if (limits->cores <= 0) { limits->cores = limits->gpus <= 0 ? cores_available : 0; } From f81f3eb741d74440b416f81f89315b302ffee10c Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 19 Dec 2024 15:18:15 -0500 Subject: [PATCH 27/53] use total instead of available --- taskvine/src/manager/vine_manager.c | 34 ++++++++++++++--------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index 3406c45e3f..02bae346f8 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2653,27 +2653,20 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, rmsummary_merge_max(limits, min); if (q->proportional_resources) { - int conservative_proportional_resources = 0; - /* Compute the proportion of the worker the task shall have across resource types. */ double max_proportion = -1; - int64_t cores_portion = conservative_proportional_resources ? cores_total : cores_available; - int64_t memory_portion = conservative_proportional_resources ? memory_total : memory_available; - int64_t disk_portion = conservative_proportional_resources ? disk_total : disk_available; - int64_t gpus_portion = conservative_proportional_resources ? gpus_total : gpus_available; - - if (cores_portion > 0) { - max_proportion = MAX(max_proportion, (double)limits->cores / cores_portion); + if (cores_total > 0) { + max_proportion = MAX(max_proportion, (double)limits->cores / cores_total); } - if (memory_portion > 0) { - max_proportion = MAX(max_proportion, (double)limits->memory / memory_portion); + if (memory_total > 0) { + max_proportion = MAX(max_proportion, (double)limits->memory / memory_total); } - if (disk_portion > 0) { - max_proportion = MAX(max_proportion, (double)limits->disk / disk_portion); + if (disk_total > 0) { + max_proportion = MAX(max_proportion, (double)limits->disk / disk_total); } - if (gpus_portion > 0) { - max_proportion = MAX(max_proportion, (double)limits->gpus / gpus_portion); + if (gpus_total > 0) { + max_proportion = MAX(max_proportion, (double)limits->gpus / gpus_total); } /* Adjust max_proportion so that an integer number of tasks fit the worker. */ @@ -2695,7 +2688,7 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, if (limits->cores == -1 && limits->gpus > 0) { limits->cores = 0; } else { - limits->cores = MAX(1, MAX(limits->cores, floor(cores_portion * max_proportion))); + limits->cores = MAX(1, MAX(limits->cores, floor(cores_total * max_proportion))); } /* When gpus are unspecified, they are set to 0 if cores are specified. */ @@ -2705,8 +2698,13 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, /* Do not allocate a proportion of gpus */ } - limits->disk = MAX(1, MAX(limits->disk, floor(disk_portion * max_proportion / q->resource_submit_multiplier))); - limits->memory = MAX(1, MAX(limits->memory, floor(memory_portion * max_proportion))); + limits->disk = MAX(1, MAX(limits->disk, floor(disk_total * max_proportion / q->resource_submit_multiplier))); + limits->memory = MAX(1, MAX(limits->memory, floor(memory_total * max_proportion))); + + /* We divide the estimated disk by 2 for two reasons: + * 1. Inputs and outputs are moved around between the task sandbox and the cache, the task is using two "virtual" sandboxes; + * 2. We want to leave some space for the cache to grow. */ + limits->disk /= 2; } /* If one of the resources is not specified, use the available instead */ From 2ff15d43c689058e795603477c517578224ba493 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 19 Dec 2024 15:36:14 -0500 Subject: [PATCH 28/53] add an api --- taskvine/src/manager/vine_schedule.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index de0e53dac3..c8a5d5437b 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -162,6 +162,22 @@ int check_worker_have_enough_disk_with_inputs(struct vine_manager *q, struct vin return ok; } +/* Check if the worker is fully occupied by other tasks, or the disk is full. + * @param w The worker info structure. */ +static int worker_fully_occupied(struct vine_worker_info *w) +{ + if (w->resources->cores.total + w->resources->gpus.total >= w->resources->cores.inuse + w->resources->gpus.inuse) { + return 0; + } + if (w->resources->memory.total >= w->resources->memory.inuse) { + return 0; + } + if (w->resources->disk.total >= w->resources->disk.inuse) { + return 0; + } + return 1; +} + /* Check if this task is compatible with this given worker by considering * resources availability, features, blocklist, and all other relevant factors. * Used by all scheduling methods for basic compatibility. @@ -181,8 +197,8 @@ int check_worker_against_task(struct vine_manager *q, struct vine_worker_info *w return 0; } - /* worker is fully occupied */ - if ((w->resources->cores.total <= w->resources->cores.inuse) || w->resources->memory.total <= w->resources->memory.inuse || w->resources->disk.total <= w->resources->disk.inuse) { + /* if the worker has been fully occupied */ + if (worker_fully_occupied(w)) { return 0; } From b423522ccea356184b23ed02fb614524896477a7 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 19 Dec 2024 16:16:06 -0500 Subject: [PATCH 29/53] divide disk by 2 on proportional --- taskvine/test/vine_allocations.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/taskvine/test/vine_allocations.py b/taskvine/test/vine_allocations.py index b09e7a0cf3..febbf5c0f4 100755 --- a/taskvine/test/vine_allocations.py +++ b/taskvine/test/vine_allocations.py @@ -74,22 +74,24 @@ def check_task(category, category_mode, max, min, expected): check_task("all_zero", "fixed", max={"cores": 0, "memory": 0, "disk": 0, "gpus": 0}, min={}, expected={"cores": worker_cores, "memory": worker_memory, "disk": worker_disk, "gpus": 0}) + # note that the disk is divided by 2 if using proportional resource allocations q.tune("force-proportional-resources", 1) - check_task("only_memory", "fixed", max={"memory": worker_memory / 2}, min={}, expected={"cores": worker_cores / 2, "memory": worker_memory / 2, "disk": worker_disk / 2, "gpus": 0}) - check_task("only_memory_w_minimum", "fixed", max={"memory": worker_memory / 2}, min={"cores": 3, "gpus": 2}, expected={"cores": 4, "memory": worker_memory, "disk": worker_disk, "gpus": 2}) + check_task("only_memory", "fixed", max={"memory": worker_memory / 2}, min={}, expected={"cores": worker_cores / 2, "memory": worker_memory / 2, "disk": worker_disk / 2 / 2, "gpus": 0}) - check_task("only_cores", "fixed", max={"cores": worker_cores}, min={}, expected={"cores": worker_cores, "memory": worker_memory, "disk": worker_disk, "gpus": 0}) + check_task("only_memory_w_minimum", "fixed", max={"memory": worker_memory / 2}, min={"cores": 3, "gpus": 2}, expected={"cores": 4, "memory": worker_memory, "disk": worker_disk / 2, "gpus": 2}) - check_task("auto_whole_worker", "min_waste", max={}, min={}, expected={"cores": worker_cores, "memory": worker_memory, "disk": worker_disk, "gpus": 0}) + check_task("only_cores", "fixed", max={"cores": worker_cores}, min={}, expected={"cores": worker_cores, "memory": worker_memory, "disk": worker_disk / 2, "gpus": 0}) + + check_task("auto_whole_worker", "min_waste", max={}, min={}, expected={"cores": worker_cores, "memory": worker_memory, "disk": worker_disk / 2, "gpus": 0}) p = 1 / worker_cores r = {"cores": 1} - e = {"cores": 1, "memory": math.floor(worker_memory * p), "disk": math.floor(worker_disk * p), "gpus": 0} + e = {"cores": 1, "memory": math.floor(worker_memory * p), "disk": math.floor(worker_disk * p) / 2, "gpus": 0} check_task("only_cores_proportional", "fixed", max=r, min={}, expected=e) p = 2 / worker_cores - e = {"cores": 2, "memory": math.floor(worker_memory * p), "disk": math.floor(worker_disk * p), "gpus": 0} + e = {"cores": 2, "memory": math.floor(worker_memory * p), "disk": math.floor(worker_disk * p) , "gpus": 0} check_task("exhaustive_bucketing", "exhaustive_bucketing", max={}, min={}, expected=e) check_task("greedy_bucketing", "greedy_bucketing", max={}, min={}, expected=e) From 365de3c65b457874676a76490ff0c59834ee9151 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 19 Dec 2024 16:26:01 -0500 Subject: [PATCH 30/53] lint --- taskvine/src/manager/vine_manager.c | 2 +- taskvine/src/manager/vine_schedule.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index 02bae346f8..cae5b4460c 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2704,7 +2704,7 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, /* We divide the estimated disk by 2 for two reasons: * 1. Inputs and outputs are moved around between the task sandbox and the cache, the task is using two "virtual" sandboxes; * 2. We want to leave some space for the cache to grow. */ - limits->disk /= 2; + limits->disk /= 2; } /* If one of the resources is not specified, use the available instead */ diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index c8a5d5437b..cafa31f03a 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -162,7 +162,7 @@ int check_worker_have_enough_disk_with_inputs(struct vine_manager *q, struct vin return ok; } -/* Check if the worker is fully occupied by other tasks, or the disk is full. +/* Check if the worker is fully occupied by other tasks, or the disk is full. * @param w The worker info structure. */ static int worker_fully_occupied(struct vine_worker_info *w) { From 9ebb422642d8f4a3d7f5d26f015dbde3c093b2ff Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 19 Dec 2024 16:47:29 -0500 Subject: [PATCH 31/53] change func name --- taskvine/src/manager/vine_schedule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index cafa31f03a..ba3e090354 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -164,7 +164,7 @@ int check_worker_have_enough_disk_with_inputs(struct vine_manager *q, struct vin /* Check if the worker is fully occupied by other tasks, or the disk is full. * @param w The worker info structure. */ -static int worker_fully_occupied(struct vine_worker_info *w) +static int worker_has_available_resources(struct vine_worker_info *w) { if (w->resources->cores.total + w->resources->gpus.total >= w->resources->cores.inuse + w->resources->gpus.inuse) { return 0; @@ -198,7 +198,7 @@ int check_worker_against_task(struct vine_manager *q, struct vine_worker_info *w } /* if the worker has been fully occupied */ - if (worker_fully_occupied(w)) { + if (!worker_has_available_resources(w)) { return 0; } From 03ca4f6a9a1ee1f20fe6a48436a71fe63e5682db Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 19 Dec 2024 16:55:37 -0500 Subject: [PATCH 32/53] fix check_worker_have_enough_disk_with_inputs --- taskvine/src/manager/vine_schedule.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index ba3e090354..24fd8e0cce 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -144,6 +144,15 @@ int check_worker_have_enough_disk_with_inputs(struct vine_manager *q, struct vin int ok = 1; double available = w->resources->disk.total - MAX(0, t->resources_requested->disk) - w->resources->disk.inuse; + if (t->input_files_size < 0) { + vine_manager_compute_input_size(q, t); + } + + /* shortcut if the available disk is larger than the size of inputs, as traversing all the existing files is quite expensive. */ + if (available >= t->input_files_size) { + return 1; + } + struct vine_mount *m; LIST_ITERATE(t->input_mounts, m) { @@ -154,7 +163,7 @@ int check_worker_have_enough_disk_with_inputs(struct vine_manager *q, struct vin available -= m->file->size; if (available < 0) { - ok = 1; + ok = 0; break; } } From ccbca01d662af3f00055c243a54f5b51c5384a90 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 19 Dec 2024 17:00:39 -0500 Subject: [PATCH 33/53] expose input compute api --- taskvine/src/manager/vine_manager.c | 2 +- taskvine/src/manager/vine_manager.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index cae5b4460c..53ce3170b7 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2564,7 +2564,7 @@ static int build_poll_table(struct vine_manager *q) return n; } -static void vine_manager_compute_input_size(struct vine_manager *q, struct vine_task *t) +void vine_manager_compute_input_size(struct vine_manager *q, struct vine_task *t) { t->input_files_size = -1; diff --git a/taskvine/src/manager/vine_manager.h b/taskvine/src/manager/vine_manager.h index 2331a4bada..7b060837b7 100644 --- a/taskvine/src/manager/vine_manager.h +++ b/taskvine/src/manager/vine_manager.h @@ -272,6 +272,8 @@ struct rmsummary *vine_manager_choose_resources_for_task( struct vine_manager *q int64_t overcommitted_resource_total(struct vine_manager *q, int64_t total); +void vine_manager_compute_input_size(struct vine_manager *q, struct vine_task *t); + /* Internal: Shut down a specific worker. */ int vine_manager_shut_down_worker(struct vine_manager *q, struct vine_worker_info *w); From 53a125a9017e0176dd04c352c944865309caba4f Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 19 Dec 2024 18:26:48 -0500 Subject: [PATCH 34/53] more apis --- taskvine/src/manager/vine_schedule.c | 142 ++++++++++++++++----------- 1 file changed, 83 insertions(+), 59 deletions(-) diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index 24fd8e0cce..e9263ee3df 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -69,6 +69,50 @@ int vine_schedule_in_ramp_down(struct vine_manager *q) return 0; } +static struct vine_resources *count_worker_net_resources(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t) +{ + struct vine_resources *worker_net_resources = vine_resources_copy(w->resources); + + uint64_t task_id; + struct vine_task *ti; + ITABLE_ITERATE(w->current_tasks, task_id, ti) + { + if (ti->provides_library && ti->function_slots_inuse == 0 && (!t->needs_library || strcmp(t->needs_library, ti->provides_library))) { + worker_net_resources->disk.inuse -= ti->current_resource_box->disk; + worker_net_resources->cores.inuse -= ti->current_resource_box->cores; + worker_net_resources->memory.inuse -= ti->current_resource_box->memory; + worker_net_resources->gpus.inuse -= ti->current_resource_box->gpus; + } + } + + return worker_net_resources; +} + +static struct rmsummary *count_worker_available_resources(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t) +{ + struct rmsummary *worker_available_resources = rmsummary_create(-1); + + struct vine_resources *worker_net_resources; + if (t->needs_library) { + worker_net_resources = count_worker_net_resources(q, w, t); + } else { + worker_net_resources = vine_resources_copy(w->resources); + } + + if (t->input_files_size < 0) { + vine_manager_compute_input_size(q, t); + } + + worker_available_resources->cores = overcommitted_resource_total(q, worker_net_resources->cores.total) - worker_net_resources->cores.inuse; + worker_available_resources->disk = overcommitted_resource_total(q, worker_net_resources->disk.total) - worker_net_resources->disk.inuse - t->input_files_size; + worker_available_resources->memory = overcommitted_resource_total(q, worker_net_resources->memory.total) - worker_net_resources->memory.inuse; + worker_available_resources->gpus = overcommitted_resource_total(q, worker_net_resources->gpus.total) - worker_net_resources->gpus.inuse; + + vine_resources_delete(worker_net_resources); + + return worker_available_resources; +} + /* Check if worker resources are enough to run the task. * Note that empty libraries are not *real* tasks and can be * killed as needed to reclaim unused resources and @@ -94,62 +138,40 @@ int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worke return 1; } - struct vine_resources *worker_net_resources = vine_resources_copy(w->resources); - /* Subtract resources from libraries that have slots unused and don't match the current task. */ /* These will be killed anyway as needed in commit_task_to_worker. */ /* Matches assumption in vine_manager.c:commit_task_to_worker() */ - uint64_t task_id; - struct vine_task *ti; - ITABLE_ITERATE(w->current_tasks, task_id, ti) - { - if (ti->provides_library && ti->function_slots_inuse == 0 && (!t->needs_library || strcmp(t->needs_library, ti->provides_library))) { - worker_net_resources->disk.inuse -= ti->current_resource_box->disk; - worker_net_resources->cores.inuse -= ti->current_resource_box->cores; - worker_net_resources->memory.inuse -= ti->current_resource_box->memory; - worker_net_resources->gpus.inuse -= ti->current_resource_box->gpus; - } - } - - int64_t disk_available = overcommitted_resource_total(q, worker_net_resources->disk.total) - worker_net_resources->disk.inuse - t->input_files_size; - if (tr->disk > disk_available) { - return 0; - } + int ok = 1; - int64_t cores_available = overcommitted_resource_total(q, worker_net_resources->cores.total) - worker_net_resources->cores.inuse; - if (tr->cores > cores_available) { - return 0; - } + struct rmsummary *worker_available_resources = count_worker_available_resources(q, w, t); - int64_t memory_available = overcommitted_resource_total(q, worker_net_resources->memory.total) - worker_net_resources->memory.inuse; - if (tr->memory > memory_available) { - return 0; + if (tr->cores > worker_available_resources->cores || tr->gpus > worker_available_resources->gpus || + tr->memory > worker_available_resources->memory || tr->disk > worker_available_resources->disk) { + ok = 0; } - int64_t gpus_available = overcommitted_resource_total(q, worker_net_resources->gpus.total) - worker_net_resources->gpus.inuse; - if (tr->gpus > gpus_available) { - return 0; - } + rmsummary_delete(worker_available_resources); - vine_resources_delete(worker_net_resources); - - return 1; + return ok; } /* t->disk only specifies the size of output and ephemeral files. Here we check if the task would fit together with all its input files * taking into account that some files may be already at the worker. */ -int check_worker_have_enough_disk_with_inputs(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t) +int worker_has_available_disk_with_inputs(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t) { - int ok = 1; - double available = w->resources->disk.total - MAX(0, t->resources_requested->disk) - w->resources->disk.inuse; + double disk_available = w->resources->disk.total - MAX(0, t->resources_requested->disk) - w->resources->disk.inuse; if (t->input_files_size < 0) { vine_manager_compute_input_size(q, t); } - /* shortcut if the available disk is larger than the size of inputs, as traversing all the existing files is quite expensive. */ - if (available >= t->input_files_size) { + if (t->input_files_size <= 0) { + return 1; + } + + /* shortcut if the available disk is larger than the size of inputs, note that traversing all the existing files is quite expensive. */ + if (disk_available >= t->input_files_size) { return 1; } @@ -160,31 +182,36 @@ int check_worker_have_enough_disk_with_inputs(struct vine_manager *q, struct vin continue; } - available -= m->file->size; + disk_available -= m->file->size; - if (available < 0) { - ok = 0; - break; + if (disk_available < 0) { + return 0; } } - return ok; + return 1; } -/* Check if the worker is fully occupied by other tasks, or the disk is full. - * @param w The worker info structure. */ -static int worker_has_available_resources(struct vine_worker_info *w) +/* Check if the worker is fully occupied by other tasks, or the disk is full. */ +static int worker_has_available_resources(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t) { - if (w->resources->cores.total + w->resources->gpus.total >= w->resources->cores.inuse + w->resources->gpus.inuse) { - return 0; - } - if (w->resources->memory.total >= w->resources->memory.inuse) { + int ok = 1; + + /* If the worker doesn't have enough resources for the inputs. */ + if (!worker_has_available_disk_with_inputs(q, w, t)) { return 0; } - if (w->resources->disk.total >= w->resources->disk.inuse) { - return 0; + + struct rmsummary *worker_available_resources = count_worker_available_resources(q, w, t); + + if (((worker_available_resources->cores + worker_available_resources->gpus <= 0)) || + worker_available_resources->memory <= 0 || worker_available_resources->disk <= 0) { + ok = 0; } - return 1; + + rmsummary_delete(worker_available_resources); + + return ok; } /* Check if this task is compatible with this given worker by considering @@ -207,7 +234,7 @@ int check_worker_against_task(struct vine_manager *q, struct vine_worker_info *w } /* if the worker has been fully occupied */ - if (!worker_has_available_resources(w)) { + if (!worker_has_available_resources(q, w, t)) { return 0; } @@ -228,8 +255,9 @@ int check_worker_against_task(struct vine_manager *q, struct vine_worker_info *w /* Don't send tasks if the factory is used and has too many connected workers. */ if (w->factory_name) { struct vine_factory_info *f = vine_factory_info_lookup(q, w->factory_name); - if (f && f->connected_workers > f->max_workers) + if (f && f->connected_workers > f->max_workers) { return 0; + } } /* Check if worker is blocked from the manager. */ @@ -257,10 +285,6 @@ int check_worker_against_task(struct vine_manager *q, struct vine_worker_info *w } } - if (!check_worker_have_enough_disk_with_inputs(q, w, t)) { - return 0; - } - /* If the worker is not the one the task wants. */ if (t->has_fixed_locations && !check_fixed_location_worker(q, w, t)) { return 0; @@ -282,7 +306,6 @@ int check_worker_against_task(struct vine_manager *q, struct vine_worker_info *w } /* Finally check to see if a function task has the needed library task */ - if (t->needs_library) { struct vine_task *library = vine_schedule_find_library(q, w, t->needs_library); if (library) { @@ -302,6 +325,7 @@ int check_worker_against_task(struct vine_manager *q, struct vine_worker_info *w } } } + return 1; } From 079a4e2a851ca1083fe2db49eaeaf8e5f32f480d Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 19 Dec 2024 18:28:15 -0500 Subject: [PATCH 35/53] more apis --- taskvine/src/manager/vine_schedule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index e9263ee3df..f2c26a0332 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -233,7 +233,7 @@ int check_worker_against_task(struct vine_manager *q, struct vine_worker_info *w return 0; } - /* if the worker has been fully occupied */ + /* if the worker has available room for this task */ if (!worker_has_available_resources(q, w, t)) { return 0; } From 2d31bfa90107ee3d2f63f67c3fa0ff66795ad278 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 19 Dec 2024 21:25:05 -0500 Subject: [PATCH 36/53] update --- taskvine/src/manager/vine_manager.c | 2 +- taskvine/src/manager/vine_schedule.c | 75 ++++++++++++++-------------- 2 files changed, 39 insertions(+), 38 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index 53ce3170b7..c4ccc48a5e 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -3371,7 +3371,7 @@ the task to the worker. static int send_one_task(struct vine_manager *q) { - if (q->total_available_cores + q->total_available_slots <= 0 || priority_queue_size(q->ready_tasks) == 0) { + if ((q->total_available_cores + q->total_available_slots <= 0) || priority_queue_size(q->ready_tasks) == 0) { return 0; } diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index f2c26a0332..fc87badf89 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -69,45 +69,64 @@ int vine_schedule_in_ramp_down(struct vine_manager *q) return 0; } +/* Count the net resources of a worker after taking into account the resources used by the library task. + * If the task is not a function task, the net resources are the same as the worker's resources. + * If the task is a function task, the inuse resources are adjusted by the resources used by the library task. + * @param q The manager structure. + * @param w The worker info structure. + * @param t The task structure. + * */ static struct vine_resources *count_worker_net_resources(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t) { struct vine_resources *worker_net_resources = vine_resources_copy(w->resources); + if (!t->needs_library) { + return worker_net_resources; + } + uint64_t task_id; struct vine_task *ti; ITABLE_ITERATE(w->current_tasks, task_id, ti) { - if (ti->provides_library && ti->function_slots_inuse == 0 && (!t->needs_library || strcmp(t->needs_library, ti->provides_library))) { - worker_net_resources->disk.inuse -= ti->current_resource_box->disk; + /* If a library task that provides the library, substract the inuse resources */ + if (ti->provides_library && strcmp(t->needs_library, ti->provides_library) == 0) { worker_net_resources->cores.inuse -= ti->current_resource_box->cores; worker_net_resources->memory.inuse -= ti->current_resource_box->memory; + worker_net_resources->disk.inuse -= ti->current_resource_box->disk; worker_net_resources->gpus.inuse -= ti->current_resource_box->gpus; } + /* If a function task that uses the same library, add to the inuse resources */ + if (ti->needs_library && strcmp(t->needs_library, ti->needs_library) == 0) { + worker_net_resources->cores.inuse += ti->current_resource_box->cores; + worker_net_resources->memory.inuse += ti->current_resource_box->memory; + worker_net_resources->disk.inuse += ti->current_resource_box->disk; + worker_net_resources->gpus.inuse += ti->current_resource_box->gpus; + } } return worker_net_resources; } +/* Count the available resources of a worker for a task. + * For disk, if the available disk minus the task's input files size is negative, then the task cannot run. + * @param q The manager structure. + * @param w The worker info structure. + * @param t The task structure. + * @return The available resources of the worker for the task. + */ static struct rmsummary *count_worker_available_resources(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t) { struct rmsummary *worker_available_resources = rmsummary_create(-1); - struct vine_resources *worker_net_resources; - if (t->needs_library) { - worker_net_resources = count_worker_net_resources(q, w, t); - } else { - worker_net_resources = vine_resources_copy(w->resources); - } - if (t->input_files_size < 0) { vine_manager_compute_input_size(q, t); } - worker_available_resources->cores = overcommitted_resource_total(q, worker_net_resources->cores.total) - worker_net_resources->cores.inuse; - worker_available_resources->disk = overcommitted_resource_total(q, worker_net_resources->disk.total) - worker_net_resources->disk.inuse - t->input_files_size; - worker_available_resources->memory = overcommitted_resource_total(q, worker_net_resources->memory.total) - worker_net_resources->memory.inuse; - worker_available_resources->gpus = overcommitted_resource_total(q, worker_net_resources->gpus.total) - worker_net_resources->gpus.inuse; - + struct vine_resources *worker_net_resources = count_worker_net_resources(q, w, t); + worker_available_resources->cores = overcommitted_resource_total(q, worker_net_resources->cores.total) - (double)worker_net_resources->cores.inuse; + worker_available_resources->disk = overcommitted_resource_total(q, worker_net_resources->disk.total) - (double)worker_net_resources->disk.inuse - t->input_files_size; + worker_available_resources->memory = overcommitted_resource_total(q, worker_net_resources->memory.total) - (double)worker_net_resources->memory.inuse; + worker_available_resources->gpus = overcommitted_resource_total(q, worker_net_resources->gpus.total) - (double)worker_net_resources->gpus.inuse; vine_resources_delete(worker_net_resources); return worker_available_resources; @@ -122,26 +141,8 @@ static struct rmsummary *count_worker_available_resources(struct vine_manager *q * @param t Task info structure. * @param tr Chosen task resources. * @return 1 if yes, 0 otherwise. */ -int check_worker_have_enough_resources(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t, struct rmsummary *tr) +int check_worker_has_enough_resources(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t, struct rmsummary *tr) { - /* - This is a temporary hack in order to get Greg's application running. - The problem is in line with the problem pointed out in PR #3909 but a special case in the manager's end. - - The problem here is that the manager always allocates the whole disk the the library task, - so that libtask->current_resource_box->disk is always equal to worker_net_resources->disk.total. - For the first task, the ti->current_resource_box->disk == 0, it is able to run because the expr in line 114 doesn't satisfy. - However, if the first task causes any increase in the worker's disk, worker_net_resources->disk.inuse will go above the total, - which causes the consistent true of the expr in line 114. - */ - if (t->needs_library) { - return 1; - } - - /* Subtract resources from libraries that have slots unused and don't match the current task. */ - /* These will be killed anyway as needed in commit_task_to_worker. */ - /* Matches assumption in vine_manager.c:commit_task_to_worker() */ - int ok = 1; struct rmsummary *worker_available_resources = count_worker_available_resources(q, w, t); @@ -193,7 +194,7 @@ int worker_has_available_disk_with_inputs(struct vine_manager *q, struct vine_wo } /* Check if the worker is fully occupied by other tasks, or the disk is full. */ -static int worker_has_available_resources(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t) +static int check_worker_has_available_resources(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t) { int ok = 1; @@ -233,8 +234,8 @@ int check_worker_against_task(struct vine_manager *q, struct vine_worker_info *w return 0; } - /* if the worker has available room for this task */ - if (!worker_has_available_resources(q, w, t)) { + /* if the worker has room for this task */ + if (!check_worker_has_available_resources(q, w, t)) { return 0; } @@ -268,7 +269,7 @@ int check_worker_against_task(struct vine_manager *q, struct vine_worker_info *w /* Compute the resources to allocate to this task. */ struct rmsummary *l = vine_manager_choose_resources_for_task(q, w, t); - if (!check_worker_have_enough_resources(q, w, t, l)) { + if (!check_worker_has_enough_resources(q, w, t, l)) { rmsummary_delete(l); return 0; } From e1460e3487f6729c1aecd11a57acbdc7a50ea612 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 19 Dec 2024 21:43:50 -0500 Subject: [PATCH 37/53] combine the check inputs --- taskvine/src/manager/vine_schedule.c | 64 ++++++++++------------------ 1 file changed, 23 insertions(+), 41 deletions(-) diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index fc87badf89..ad7586d14b 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -157,59 +157,41 @@ int check_worker_has_enough_resources(struct vine_manager *q, struct vine_worker return ok; } -/* t->disk only specifies the size of output and ephemeral files. Here we check if the task would fit together with all its input files - * taking into account that some files may be already at the worker. */ -int worker_has_available_disk_with_inputs(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t) -{ - double disk_available = w->resources->disk.total - MAX(0, t->resources_requested->disk) - w->resources->disk.inuse; - - if (t->input_files_size < 0) { - vine_manager_compute_input_size(q, t); - } - - if (t->input_files_size <= 0) { - return 1; - } - - /* shortcut if the available disk is larger than the size of inputs, note that traversing all the existing files is quite expensive. */ - if (disk_available >= t->input_files_size) { - return 1; - } - - struct vine_mount *m; - LIST_ITERATE(t->input_mounts, m) - { - if (hash_table_lookup(w->current_files, m->file->cached_name)) { - continue; - } - - disk_available -= m->file->size; - - if (disk_available < 0) { - return 0; - } - } - - return 1; -} - /* Check if the worker is fully occupied by other tasks, or the disk is full. */ static int check_worker_has_available_resources(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t) { int ok = 1; - /* If the worker doesn't have enough resources for the inputs. */ - if (!worker_has_available_disk_with_inputs(q, w, t)) { - return 0; - } - struct rmsummary *worker_available_resources = count_worker_available_resources(q, w, t); + /* check if any of the resources is currently unavailable */ if (((worker_available_resources->cores + worker_available_resources->gpus <= 0)) || worker_available_resources->memory <= 0 || worker_available_resources->disk <= 0) { ok = 0; } + /* check if the worker has enough disk for the inputs, some of the inputs might have already been existing on the worker */ + if (t->input_files_size < 0) { + vine_manager_compute_input_size(q, t); + } + + double disk_needed_for_inputs = t->input_files_size; + if (t->input_files_size > worker_available_resources->disk) { + struct vine_mount *m; + LIST_ITERATE(t->input_mounts, m) + { + if (hash_table_lookup(w->current_files, m->file->cached_name)) { + continue; + } + + disk_needed_for_inputs -= m->file->size; + + if (disk_needed_for_inputs < 0) { + ok = 0; + } + } + } + rmsummary_delete(worker_available_resources); return ok; From e63a4265b3fd06190fc9dc5aff14559e1ddaafb2 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 19 Dec 2024 22:47:35 -0500 Subject: [PATCH 38/53] temp hack --- taskvine/src/manager/vine_schedule.c | 36 +++++++++++++++++++--------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index ad7586d14b..139a1c4814 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -80,7 +80,7 @@ static struct vine_resources *count_worker_net_resources(struct vine_manager *q, { struct vine_resources *worker_net_resources = vine_resources_copy(w->resources); - if (!t->needs_library) { + if (!t->needs_library && !t->provides_library) { return worker_net_resources; } @@ -88,20 +88,12 @@ static struct vine_resources *count_worker_net_resources(struct vine_manager *q, struct vine_task *ti; ITABLE_ITERATE(w->current_tasks, task_id, ti) { - /* If a library task that provides the library, substract the inuse resources */ - if (ti->provides_library && strcmp(t->needs_library, ti->provides_library) == 0) { + if (ti->provides_library && ti->function_slots_inuse == 0 && (!t->needs_library || strcmp(t->needs_library, ti->provides_library))) { + worker_net_resources->disk.inuse -= ti->current_resource_box->disk; worker_net_resources->cores.inuse -= ti->current_resource_box->cores; worker_net_resources->memory.inuse -= ti->current_resource_box->memory; - worker_net_resources->disk.inuse -= ti->current_resource_box->disk; worker_net_resources->gpus.inuse -= ti->current_resource_box->gpus; } - /* If a function task that uses the same library, add to the inuse resources */ - if (ti->needs_library && strcmp(t->needs_library, ti->needs_library) == 0) { - worker_net_resources->cores.inuse += ti->current_resource_box->cores; - worker_net_resources->memory.inuse += ti->current_resource_box->memory; - worker_net_resources->disk.inuse += ti->current_resource_box->disk; - worker_net_resources->gpus.inuse += ti->current_resource_box->gpus; - } } return worker_net_resources; @@ -123,10 +115,12 @@ static struct rmsummary *count_worker_available_resources(struct vine_manager *q } struct vine_resources *worker_net_resources = count_worker_net_resources(q, w, t); + worker_available_resources->cores = overcommitted_resource_total(q, worker_net_resources->cores.total) - (double)worker_net_resources->cores.inuse; worker_available_resources->disk = overcommitted_resource_total(q, worker_net_resources->disk.total) - (double)worker_net_resources->disk.inuse - t->input_files_size; worker_available_resources->memory = overcommitted_resource_total(q, worker_net_resources->memory.total) - (double)worker_net_resources->memory.inuse; worker_available_resources->gpus = overcommitted_resource_total(q, worker_net_resources->gpus.total) - (double)worker_net_resources->gpus.inuse; + vine_resources_delete(worker_net_resources); return worker_available_resources; @@ -143,6 +137,19 @@ static struct rmsummary *count_worker_available_resources(struct vine_manager *q * @return 1 if yes, 0 otherwise. */ int check_worker_has_enough_resources(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t, struct rmsummary *tr) { + /* + This is a temporary hack in order to get Greg's application running. + The problem is in line with the problem pointed out in PR #3909 but a special case in the manager's end. + + The problem here is that the manager always allocates the whole disk the the library task, + so that libtask->current_resource_box->disk is always equal to worker_net_resources->disk.total. + For the first task, the ti->current_resource_box->disk == 0, it is able to run because the expr in line 114 doesn't satisfy. + However, if the first task causes any increase in the worker's disk, worker_net_resources->disk.inuse will go above the total, + which causes the consistent true of the expr in line 114. + */ + if (t->needs_library) { + return 1; + } int ok = 1; struct rmsummary *worker_available_resources = count_worker_available_resources(q, w, t); @@ -160,6 +167,13 @@ int check_worker_has_enough_resources(struct vine_manager *q, struct vine_worker /* Check if the worker is fully occupied by other tasks, or the disk is full. */ static int check_worker_has_available_resources(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t) { + /* + This is the same hack as in check_worker_has_enough_resources. + Another PR is going on to fix the problem of library/function task allocation. + */ + if (t->needs_library) { + return 1; + } int ok = 1; struct rmsummary *worker_available_resources = count_worker_available_resources(q, w, t); From 232bbc247c098f3812bad26ec939a3662c12132a Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Fri, 20 Dec 2024 14:24:14 -0500 Subject: [PATCH 39/53] check inputs --- taskvine/src/manager/vine_manager.c | 5 +- taskvine/src/manager/vine_schedule.c | 110 +++++++++++++-------------- 2 files changed, 54 insertions(+), 61 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index c4ccc48a5e..f884424ad9 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2701,9 +2701,8 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, limits->disk = MAX(1, MAX(limits->disk, floor(disk_total * max_proportion / q->resource_submit_multiplier))); limits->memory = MAX(1, MAX(limits->memory, floor(memory_total * max_proportion))); - /* We divide the estimated disk by 2 for two reasons: - * 1. Inputs and outputs are moved around between the task sandbox and the cache, the task is using two "virtual" sandboxes; - * 2. We want to leave some space for the cache to grow. */ + /* We divide the estimated disk by 2 because inputs and outputs are moved around between the sandbox and + * the cache, we leave some space for that, and we want to leave some space for the cache to grow. */ limits->disk /= 2; } diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index 139a1c4814..19678243f8 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -69,38 +69,7 @@ int vine_schedule_in_ramp_down(struct vine_manager *q) return 0; } -/* Count the net resources of a worker after taking into account the resources used by the library task. - * If the task is not a function task, the net resources are the same as the worker's resources. - * If the task is a function task, the inuse resources are adjusted by the resources used by the library task. - * @param q The manager structure. - * @param w The worker info structure. - * @param t The task structure. - * */ -static struct vine_resources *count_worker_net_resources(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t) -{ - struct vine_resources *worker_net_resources = vine_resources_copy(w->resources); - - if (!t->needs_library && !t->provides_library) { - return worker_net_resources; - } - - uint64_t task_id; - struct vine_task *ti; - ITABLE_ITERATE(w->current_tasks, task_id, ti) - { - if (ti->provides_library && ti->function_slots_inuse == 0 && (!t->needs_library || strcmp(t->needs_library, ti->provides_library))) { - worker_net_resources->disk.inuse -= ti->current_resource_box->disk; - worker_net_resources->cores.inuse -= ti->current_resource_box->cores; - worker_net_resources->memory.inuse -= ti->current_resource_box->memory; - worker_net_resources->gpus.inuse -= ti->current_resource_box->gpus; - } - } - - return worker_net_resources; -} - /* Count the available resources of a worker for a task. - * For disk, if the available disk minus the task's input files size is negative, then the task cannot run. * @param q The manager structure. * @param w The worker info structure. * @param t The task structure. @@ -108,17 +77,32 @@ static struct vine_resources *count_worker_net_resources(struct vine_manager *q, */ static struct rmsummary *count_worker_available_resources(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t) { - struct rmsummary *worker_available_resources = rmsummary_create(-1); + /* Count the net resources of a worker after taking into account the resources used by the library task. + * If the task is not a function task, the net resources are the same as the worker's resources. + * If the task is a function task, the inuse resources are adjusted by the resources used by the library task. */ + struct vine_resources *worker_net_resources = vine_resources_copy(w->resources); - if (t->input_files_size < 0) { - vine_manager_compute_input_size(q, t); + /* Function resource allocation is going to be addressed in the next PR. */ + if (t->needs_library || t->provides_library) { + uint64_t task_id; + struct vine_task *ti; + ITABLE_ITERATE(w->current_tasks, task_id, ti) + { + if (ti->provides_library && ti->function_slots_inuse == 0 && (!t->needs_library || strcmp(t->needs_library, ti->provides_library))) { + worker_net_resources->cores.inuse -= ti->current_resource_box->cores; + worker_net_resources->memory.inuse -= ti->current_resource_box->memory; + worker_net_resources->disk.inuse -= ti->current_resource_box->disk; + worker_net_resources->gpus.inuse -= ti->current_resource_box->gpus; + } + } } - struct vine_resources *worker_net_resources = count_worker_net_resources(q, w, t); + /* The worker's available resources are the net resources minus the resources in use by the worker. */ + struct rmsummary *worker_available_resources = rmsummary_create(-1); worker_available_resources->cores = overcommitted_resource_total(q, worker_net_resources->cores.total) - (double)worker_net_resources->cores.inuse; - worker_available_resources->disk = overcommitted_resource_total(q, worker_net_resources->disk.total) - (double)worker_net_resources->disk.inuse - t->input_files_size; worker_available_resources->memory = overcommitted_resource_total(q, worker_net_resources->memory.total) - (double)worker_net_resources->memory.inuse; + worker_available_resources->disk = overcommitted_resource_total(q, worker_net_resources->disk.total) - (double)worker_net_resources->disk.inuse; worker_available_resources->gpus = overcommitted_resource_total(q, worker_net_resources->gpus.total) - (double)worker_net_resources->gpus.inuse; vine_resources_delete(worker_net_resources); @@ -159,6 +143,38 @@ int check_worker_has_enough_resources(struct vine_manager *q, struct vine_worker ok = 0; } + if (t->input_files_size < 0) { + vine_manager_compute_input_size(q, t); + } + + /* check if the sandbox can store the inputs */ + if (t->input_files_size > tr->disk) { + ok = 0; + } + + /* check if the cache can store the inputs, if the input is larger than the rest of the disk, check if some of the inputs have been existing in the cache */ + int64_t cache_available = worker_available_resources->disk - tr->disk; + if (t->input_files_size > cache_available) { + ok = 0; + + int64_t cache_needed_for_inputs = t->input_files_size; + + struct vine_mount *m; + LIST_ITERATE(t->input_mounts, m) + { + if (hash_table_lookup(w->current_files, m->file->cached_name)) { + continue; + } + + cache_needed_for_inputs -= m->file->size; + + if (cache_needed_for_inputs < cache_available) { + ok = 1; + break; + } + } + } + rmsummary_delete(worker_available_resources); return ok; @@ -184,28 +200,6 @@ static int check_worker_has_available_resources(struct vine_manager *q, struct v ok = 0; } - /* check if the worker has enough disk for the inputs, some of the inputs might have already been existing on the worker */ - if (t->input_files_size < 0) { - vine_manager_compute_input_size(q, t); - } - - double disk_needed_for_inputs = t->input_files_size; - if (t->input_files_size > worker_available_resources->disk) { - struct vine_mount *m; - LIST_ITERATE(t->input_mounts, m) - { - if (hash_table_lookup(w->current_files, m->file->cached_name)) { - continue; - } - - disk_needed_for_inputs -= m->file->size; - - if (disk_needed_for_inputs < 0) { - ok = 0; - } - } - } - rmsummary_delete(worker_available_resources); return ok; From 42981e155029a7ad0c798a68013a69cc305432bd Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Sat, 21 Dec 2024 01:26:01 -0500 Subject: [PATCH 40/53] do not count inputs when choose resource --- taskvine/src/manager/vine_manager.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index f884424ad9..408e6db627 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2620,16 +2620,6 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, int64_t disk_available = w->resources->disk.total - w->resources->disk.inuse; int64_t gpus_available = w->resources->gpus.total - w->resources->gpus.inuse; - /* For disk, do not count the size of input files - * TODO: efficiently discount the size of files already at worker. */ - if (t->input_files_size < 0) { - vine_manager_compute_input_size(q, t); - } - if (t->input_files_size > 0) { - disk_total -= t->input_files_size; - disk_available -= t->input_files_size; - } - /* Shortcut if the ramp down mode is enabled. In this case, use all the free space of that worker if the user has not specified. * Note that we don't use resource_submit_multiplier, as by definition in ramp down there are more workers than tasks. */ if (vine_schedule_in_ramp_down(q)) { From d2e35f7d92d72f47eab753466166678132a21e66 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Sat, 21 Dec 2024 01:27:59 -0500 Subject: [PATCH 41/53] remove comment --- taskvine/src/manager/vine_manager.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index 408e6db627..4099846e13 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2673,8 +2673,7 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, } /* When cores are unspecified, they are set to 0 if gpus are specified. - * Otherwise they get a proportion according to specified resources. - * Tasks will get at least one core */ + * Otherwise they get a proportion according to specified resources. */ if (limits->cores == -1 && limits->gpus > 0) { limits->cores = 0; } else { From f1f8b7d3faf7328e43c4dcae7f12fe796ec741df Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Sat, 21 Dec 2024 01:28:45 -0500 Subject: [PATCH 42/53] lint --- taskvine/src/manager/vine_manager.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index 4099846e13..ce7931f10b 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2699,15 +2699,15 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, if (limits->cores <= 0) { limits->cores = limits->gpus <= 0 ? cores_available : 0; } + if (limits->gpus <= 0) { + limits->gpus = limits->cores <= 0 ? gpus_available : 0; + } if (limits->memory <= 0) { limits->memory = memory_available; } if (limits->disk <= 0) { limits->disk = disk_available; } - if (limits->gpus <= 0) { - limits->gpus = limits->cores <= 0 ? gpus_available : 0; - } /* Never go below min resources. */ rmsummary_merge_max(limits, min); From 43e0e6f68d20bf7af0afdc348639afb32ae663ba Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Tue, 14 Jan 2025 12:22:32 -0500 Subject: [PATCH 43/53] check exec capacity --- taskvine/src/manager/vine_manager.c | 66 +++++++++++++++++++---------- taskvine/src/manager/vine_manager.h | 9 ++-- 2 files changed, 47 insertions(+), 28 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index f2bf7c1c28..3559ed9bbb 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -554,11 +554,13 @@ static vine_result_code_t get_completion_result(struct vine_manager *q, struct v original->library_failed_count++; original->time_when_last_failure = timestamp_get(); } + itable_remove(q->running_library_instances, t->task_id); printf("Library %s failed on worker %s (%s)", t->provides_library, w->hostname, w->addrport); - if (q->watch_library_logfiles) + if (q->watch_library_logfiles) { printf(", check the library log file %s\n", t->library_log_path); - else + } else { printf(", enable watch-library-logfiles for debug\n"); + } } else { /* Update task stats for this completion. */ observed_execution_time = timestamp_get() - t->time_when_commit_end; @@ -2409,7 +2411,6 @@ static vine_msg_code_t handle_resources(struct vine_manager *q, struct vine_work debug(D_VINE, "%s", line); if (sscanf(line, "cores %" PRId64, &total)) { - q->total_available_cores += (total - w->resources->cores.total); w->resources->cores.total = total; } else if (sscanf(line, "memory %" PRId64, &total)) { w->resources->memory.total = total; @@ -2742,7 +2743,6 @@ static vine_result_code_t start_one_task(struct vine_manager *q, struct vine_wor } else { t->function_slots_total = t->function_slots_requested; } - q->total_available_slots += t->function_slots_total; } char *command_line; @@ -2770,8 +2770,6 @@ static vine_result_code_t start_one_task(struct vine_manager *q, struct vine_wor static void count_worker_resources(struct vine_manager *q, struct vine_worker_info *w) { - q->total_available_cores -= (w->resources->cores.total - w->resources->cores.inuse); - w->resources->cores.inuse = 0; w->resources->memory.inuse = 0; w->resources->disk.inuse = 0; @@ -2798,8 +2796,6 @@ static void count_worker_resources(struct vine_manager *q, struct vine_worker_in } w->resources->disk.inuse += ceil(BYTES_TO_MEGABYTES(w->inuse_cache)); - - q->total_available_cores += (w->resources->cores.total - w->resources->cores.inuse); } static void update_max_worker(struct vine_manager *q, struct vine_worker_info *w) @@ -2896,7 +2892,6 @@ static vine_result_code_t commit_task_to_worker(struct vine_manager *q, struct v } /* If start_one_task_fails, this will be decremented in handle_failure below. */ t->library_task->function_slots_inuse++; - q->total_available_slots--; } t->hostname = xxstrdup(w->hostname); @@ -3060,13 +3055,7 @@ static void reap_task_from_worker(struct vine_manager *q, struct vine_worker_inf */ if (t->needs_library) { - int previous_slots_inuse = t->library_task->function_slots_inuse; t->library_task->function_slots_inuse = MAX(0, t->library_task->function_slots_inuse - 1); - q->total_available_slots += (previous_slots_inuse - t->library_task->function_slots_inuse); - } - - if (t->provides_library) { - q->total_available_slots -= t->function_slots_total; } t->worker = 0; @@ -3339,15 +3328,44 @@ int consider_task(struct vine_manager *q, struct vine_task *t) return 1; } +static int has_exec_capacity(struct vine_manager *q) +{ + /* First check if there is a free slot on a library instance */ + uint64_t task_id; + struct vine_task *t; + + ITABLE_ITERATE(q->running_library_instances, task_id, t) + { + /* A task must use at least one core */ + if (t->function_slots_inuse < t->function_slots_total) { + return 1; + } + } + + /* If no slots are available, or no library instances at all, check the worker cores */ + char *worker_key; + struct vine_worker_info *w; + + HASH_TABLE_ITERATE(q->worker_table, worker_key, w) + { + /* A task may use a gpu but not use cores */ + if (w->resources->cores.inuse + w->resources->gpus.inuse < w->resources->cores.total + w->resources->gpus.total) { + return 1; + } + } + + /* No available slots / cores / gpus */ + return 0; +} + /* Advance the state of the system by selecting one task available to run, finding the best worker for that task, and then committing the task to the worker. */ - static int send_one_task(struct vine_manager *q) { - if ((q->total_available_cores + q->total_available_slots <= 0) || priority_queue_size(q->ready_tasks) == 0) { + if (!has_exec_capacity(q)) { return 0; } @@ -3851,12 +3869,11 @@ struct vine_manager *vine_ssl_create(int port, const char *key, const char *cert cctools_uuid_t local_uuid; cctools_uuid_create(&local_uuid); q->uuid = strdup(local_uuid.str); - q->duplicated_libraries = 0; q->next_task_id = 1; + q->next_library_id = 1; + q->fixed_location_in_queue = 0; - q->total_available_cores = 0; - q->total_available_slots = 0; q->ready_tasks = priority_queue_create(0); q->running_table = itable_create(0); @@ -3865,6 +3882,7 @@ struct vine_manager *vine_ssl_create(int port, const char *key, const char *cert q->tasks = itable_create(0); q->library_templates = hash_table_create(0, 0); + q->running_library_instances = itable_create(0); q->worker_table = hash_table_create(0, 0); q->file_worker_table = hash_table_create(0, 0); @@ -4237,6 +4255,7 @@ void vine_delete(struct vine_manager *q) priority_queue_delete(q->ready_tasks); itable_delete(q->running_table); + itable_delete(q->running_library_instances); list_delete(q->waiting_retrieval_list); list_delete(q->retrieved_list); hash_table_delete(q->workers_with_watched_file_updates); @@ -4654,8 +4673,6 @@ struct vine_task *send_library_to_worker(struct vine_manager *q, struct vine_wor if (!check_worker_against_task(q, w, original)) { return 0; } - /* Track the number of duplicated libraries */ - q->duplicated_libraries += 1; /* Duplicate the original task */ struct vine_task *t = vine_task_copy(original); @@ -4667,7 +4684,7 @@ struct vine_task *send_library_to_worker(struct vine_manager *q, struct vine_wor /* If watch-library-logfiles is tuned, watch the output file of every duplicated library instance */ if (q->watch_library_logfiles) { char *remote_stdout_filename = string_format(".taskvine.stdout"); - char *local_library_log_filename = string_format("library-%d.debug.log", q->duplicated_libraries); + char *local_library_log_filename = string_format("library-%d.debug.log", q->next_library_id++); t->library_log_path = vine_get_path_library_log(q, local_library_log_filename); struct vine_file *library_local_stdout_file = vine_declare_file(q, t->library_log_path, VINE_CACHE_LEVEL_TASK, 0); @@ -4680,6 +4697,9 @@ struct vine_task *send_library_to_worker(struct vine_manager *q, struct vine_wor /* Add reference to task when adding it to primary table. */ itable_insert(q->tasks, t->task_id, vine_task_addref(t)); + /* Bookkeep the active library instances */ + itable_insert(q->running_library_instances, t->task_id, t); + /* Send the task to the worker in the usual way. */ /* Careful: If this failed, then the worker object or task object may no longer be valid! */ *result = commit_task_to_worker(q, w, t); diff --git a/taskvine/src/manager/vine_manager.h b/taskvine/src/manager/vine_manager.h index 81e47f209f..707dba2c61 100644 --- a/taskvine/src/manager/vine_manager.h +++ b/taskvine/src/manager/vine_manager.h @@ -108,7 +108,8 @@ struct vine_manager { struct list *retrieved_list; /* List of vine_task that have been retrieved. */ struct list *task_info_list; /* List of last N vine_task_infos for computing capacity. */ struct hash_table *categories; /* Maps category_name -> struct category */ - struct hash_table *library_templates; /* Maps library name -> vine_task of library with that name. */ + struct hash_table *library_templates; /* Maps library name -> vine_task of library with that name. */ + struct itable *running_library_instances; /* Maps task_id -> vine_task of library instance. */ /* Primary data structures for tracking worker state. */ @@ -133,13 +134,11 @@ struct vine_manager { /* Internal state modified by the manager */ - int next_task_id; /* Next integer task_id to be assigned to a created task. */ - int duplicated_libraries; /* The number of duplicated libraries */ + int next_task_id; /* Next integer task_id to be assigned to a created task. */ + int next_library_id; /* Next integer library_id to be assigned to a library instance. */ int fixed_location_in_queue; /* Number of fixed location tasks currently being managed */ int num_tasks_left; /* Optional: Number of tasks remaining, if given by user. @ref vine_set_num_tasks */ int busy_waiting_flag; /* Set internally in main loop if no messages were processed -> wait longer. */ - int total_available_cores; /* Number of cores available among all workers. */ - int total_available_slots; /* Number of function slots available among all workers. */ /* Accumulation of statistics for reporting to the caller. */ From 933f91998e903000824ead24edb5618404f34426 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Tue, 14 Jan 2025 14:53:19 -0500 Subject: [PATCH 44/53] fix comment --- taskvine/src/manager/vine_manager.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index 3559ed9bbb..90647431a3 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -3328,15 +3328,18 @@ int consider_task(struct vine_manager *q, struct vine_task *t) return 1; } +/* +Determine whether there is a worker available to run a task. +*/ static int has_exec_capacity(struct vine_manager *q) { - /* First check if there is a free slot on a library instance */ + /* First check if there is a free slot on any library instances */ uint64_t task_id; struct vine_task *t; ITABLE_ITERATE(q->running_library_instances, task_id, t) { - /* A task must use at least one core */ + /* A function task must use at least one slot */ if (t->function_slots_inuse < t->function_slots_total) { return 1; } @@ -3348,7 +3351,7 @@ static int has_exec_capacity(struct vine_manager *q) HASH_TABLE_ITERATE(q->worker_table, worker_key, w) { - /* A task may use a gpu but not use cores */ + /* A normal task may use a gpu but not use cores */ if (w->resources->cores.inuse + w->resources->gpus.inuse < w->resources->cores.total + w->resources->gpus.total) { return 1; } From 5d98a7ade20852c5f288f3770c9ead0f67e8b999 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Tue, 14 Jan 2025 15:30:46 -0500 Subject: [PATCH 45/53] skip function tasks --- taskvine/src/manager/vine_schedule.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index edc75621ea..61b7deff79 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -82,13 +82,13 @@ static struct rmsummary *count_worker_available_resources(struct vine_manager *q * If the task is a function task, the inuse resources are adjusted by the resources used by the library task. */ struct vine_resources *worker_net_resources = vine_resources_copy(w->resources); - /* Function resource allocation is going to be addressed in the next PR. */ - if (t->needs_library || t->provides_library) { + /* If the task is a library task, skip those idle libraries as if they are not using any resources */ + if (t->provides_library) { uint64_t task_id; struct vine_task *ti; ITABLE_ITERATE(w->current_tasks, task_id, ti) { - if (ti->provides_library && ti->function_slots_inuse == 0 && (!t->needs_library || strcmp(t->needs_library, ti->provides_library))) { + if (ti->provides_library && ti->function_slots_inuse == 0) { worker_net_resources->cores.inuse -= ti->current_resource_box->cores; worker_net_resources->memory.inuse -= ti->current_resource_box->memory; worker_net_resources->disk.inuse -= ti->current_resource_box->disk; @@ -121,16 +121,7 @@ static struct rmsummary *count_worker_available_resources(struct vine_manager *q * @return 1 if yes, 0 otherwise. */ int check_worker_has_enough_resources(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t, struct rmsummary *tr) { - /* - This is a temporary hack in order to get Greg's application running. - The problem is in line with the problem pointed out in PR #3909 but a special case in the manager's end. - - The problem here is that the manager always allocates the whole disk the the library task, - so that libtask->current_resource_box->disk is always equal to worker_net_resources->disk.total. - For the first task, the ti->current_resource_box->disk == 0, it is able to run because the expr in line 114 doesn't satisfy. - However, if the first task causes any increase in the worker's disk, worker_net_resources->disk.inuse will go above the total, - which causes the consistent true of the expr in line 114. - */ + /* Skip if it is a function task */ if (t->needs_library) { return 1; } @@ -183,10 +174,7 @@ int check_worker_has_enough_resources(struct vine_manager *q, struct vine_worker /* Check if the worker is fully occupied by other tasks, or the disk is full. */ static int check_worker_has_available_resources(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t) { - /* - This is the same hack as in check_worker_has_enough_resources. - Another PR is going on to fix the problem of library/function task allocation. - */ + /* Skip if it is a function task */ if (t->needs_library) { return 1; } From 89e225725850b112e65df8ac3313f354ba07c48f Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Tue, 14 Jan 2025 15:52:44 -0500 Subject: [PATCH 46/53] fix comments --- taskvine/src/manager/vine_manager.c | 17 +++++++++-------- taskvine/src/manager/vine_manager.h | 1 - 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index 90647431a3..dd9ca09f61 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -554,12 +554,11 @@ static vine_result_code_t get_completion_result(struct vine_manager *q, struct v original->library_failed_count++; original->time_when_last_failure = timestamp_get(); } - itable_remove(q->running_library_instances, t->task_id); - printf("Library %s failed on worker %s (%s)", t->provides_library, w->hostname, w->addrport); + debug(D_VINE | D_NOTICE, "Library %s failed on worker %s (%s)", t->provides_library, w->hostname, w->addrport); if (q->watch_library_logfiles) { - printf(", check the library log file %s\n", t->library_log_path); + debug(D_VINE | D_NOTICE, ", check the library log file %s\n", t->library_log_path); } else { - printf(", enable watch-library-logfiles for debug\n"); + debug(D_VINE | D_NOTICE, ", enable watch-library-logfiles for debug\n"); } } else { /* Update task stats for this completion. */ @@ -618,6 +617,7 @@ static vine_result_code_t get_completion_result(struct vine_manager *q, struct v /* Finally update data structures to reflect the completion. */ change_task_state(q, t, VINE_TASK_WAITING_RETRIEVAL); itable_remove(q->running_table, t->task_id); + itable_remove(q->running_library_instances, t->task_id); vine_task_set_result(t, task_status); return VINE_SUCCESS; @@ -3329,7 +3329,9 @@ int consider_task(struct vine_manager *q, struct vine_task *t) } /* -Determine whether there is a worker available to run a task. +This is a "conservative" estimate of the resources available. +If this returns false, then there is definitely no worker available to run any task. +If it returns true, then there may be a suitable worker, and we have to check them all in detail. */ static int has_exec_capacity(struct vine_manager *q) { @@ -3874,7 +3876,6 @@ struct vine_manager *vine_ssl_create(int port, const char *key, const char *cert q->uuid = strdup(local_uuid.str); q->next_task_id = 1; - q->next_library_id = 1; q->fixed_location_in_queue = 0; @@ -4655,7 +4656,7 @@ struct vine_task *send_library_to_worker(struct vine_manager *q, struct vine_wor if (original->library_failed_count > q->max_library_retries) { vine_manager_remove_library(q, name); debug(D_VINE, "library %s has reached the maximum failure count %d, it has been removed", name, q->max_library_retries); - printf("library %s has reached the maximum failure count %d, it has been removed\n", name, q->max_library_retries); + debug(D_VINE|D_NOTICE, "library %s has reached the maximum failure count %d, it has been removed\n", name, q->max_library_retries); return 0; } @@ -4687,7 +4688,7 @@ struct vine_task *send_library_to_worker(struct vine_manager *q, struct vine_wor /* If watch-library-logfiles is tuned, watch the output file of every duplicated library instance */ if (q->watch_library_logfiles) { char *remote_stdout_filename = string_format(".taskvine.stdout"); - char *local_library_log_filename = string_format("library-%d.debug.log", q->next_library_id++); + char *local_library_log_filename = string_format("library-task-%d.log", t->task_id); t->library_log_path = vine_get_path_library_log(q, local_library_log_filename); struct vine_file *library_local_stdout_file = vine_declare_file(q, t->library_log_path, VINE_CACHE_LEVEL_TASK, 0); diff --git a/taskvine/src/manager/vine_manager.h b/taskvine/src/manager/vine_manager.h index 707dba2c61..ea5e860186 100644 --- a/taskvine/src/manager/vine_manager.h +++ b/taskvine/src/manager/vine_manager.h @@ -135,7 +135,6 @@ struct vine_manager { /* Internal state modified by the manager */ int next_task_id; /* Next integer task_id to be assigned to a created task. */ - int next_library_id; /* Next integer library_id to be assigned to a library instance. */ int fixed_location_in_queue; /* Number of fixed location tasks currently being managed */ int num_tasks_left; /* Optional: Number of tasks remaining, if given by user. @ref vine_set_num_tasks */ int busy_waiting_flag; /* Set internally in main loop if no messages were processed -> wait longer. */ From 5063baaae41165edbecf59ddbb541c146601f151 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Tue, 14 Jan 2025 15:53:22 -0500 Subject: [PATCH 47/53] lint --- taskvine/src/manager/vine_manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index dd9ca09f61..2c774cfefe 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -4656,7 +4656,7 @@ struct vine_task *send_library_to_worker(struct vine_manager *q, struct vine_wor if (original->library_failed_count > q->max_library_retries) { vine_manager_remove_library(q, name); debug(D_VINE, "library %s has reached the maximum failure count %d, it has been removed", name, q->max_library_retries); - debug(D_VINE|D_NOTICE, "library %s has reached the maximum failure count %d, it has been removed\n", name, q->max_library_retries); + debug(D_VINE | D_NOTICE, "library %s has reached the maximum failure count %d, it has been removed\n", name, q->max_library_retries); return 0; } From 18cfaac34886de587546740b9276d2ff8459abcf Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Thu, 16 Jan 2025 11:59:15 -0500 Subject: [PATCH 48/53] add more comments --- taskvine/src/manager/vine_manager.c | 39 ---------------------------- taskvine/src/manager/vine_schedule.c | 8 ++++-- 2 files changed, 6 insertions(+), 41 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index 2c774cfefe..2199539512 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -3328,41 +3328,6 @@ int consider_task(struct vine_manager *q, struct vine_task *t) return 1; } -/* -This is a "conservative" estimate of the resources available. -If this returns false, then there is definitely no worker available to run any task. -If it returns true, then there may be a suitable worker, and we have to check them all in detail. -*/ -static int has_exec_capacity(struct vine_manager *q) -{ - /* First check if there is a free slot on any library instances */ - uint64_t task_id; - struct vine_task *t; - - ITABLE_ITERATE(q->running_library_instances, task_id, t) - { - /* A function task must use at least one slot */ - if (t->function_slots_inuse < t->function_slots_total) { - return 1; - } - } - - /* If no slots are available, or no library instances at all, check the worker cores */ - char *worker_key; - struct vine_worker_info *w; - - HASH_TABLE_ITERATE(q->worker_table, worker_key, w) - { - /* A normal task may use a gpu but not use cores */ - if (w->resources->cores.inuse + w->resources->gpus.inuse < w->resources->cores.total + w->resources->gpus.total) { - return 1; - } - } - - /* No available slots / cores / gpus */ - return 0; -} - /* Advance the state of the system by selecting one task available to run, finding the best worker for that task, and then committing @@ -3370,10 +3335,6 @@ the task to the worker. */ static int send_one_task(struct vine_manager *q) { - if (!has_exec_capacity(q)) { - return 0; - } - int t_idx; struct vine_task *t; diff --git a/taskvine/src/manager/vine_schedule.c b/taskvine/src/manager/vine_schedule.c index 61b7deff79..675b68cec5 100644 --- a/taskvine/src/manager/vine_schedule.c +++ b/taskvine/src/manager/vine_schedule.c @@ -121,10 +121,12 @@ static struct rmsummary *count_worker_available_resources(struct vine_manager *q * @return 1 if yes, 0 otherwise. */ int check_worker_has_enough_resources(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t, struct rmsummary *tr) { - /* Skip if it is a function task */ + /* Skip if it is a function task. Resource guarantees for function calls are handled at the end of @check_worker_against_task, which calls + * @vine_schedule_find_library to locate a suitable library for the function call, it directly returns false if no appropriate library is found */ if (t->needs_library) { return 1; } + int ok = 1; struct rmsummary *worker_available_resources = count_worker_available_resources(q, w, t); @@ -174,10 +176,12 @@ int check_worker_has_enough_resources(struct vine_manager *q, struct vine_worker /* Check if the worker is fully occupied by other tasks, or the disk is full. */ static int check_worker_has_available_resources(struct vine_manager *q, struct vine_worker_info *w, struct vine_task *t) { - /* Skip if it is a function task */ + /* Skip if it is a function task. Resource guarantees for function calls are handled at the end of @check_worker_against_task, which calls + * @vine_schedule_find_library to locate a suitable library for the function call, it directly returns false if no appropriate library is found */ if (t->needs_library) { return 1; } + int ok = 1; struct rmsummary *worker_available_resources = count_worker_available_resources(q, w, t); From 4e9b577c5d8ce89f8891f75a4815f25660114999 Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Fri, 17 Jan 2025 11:57:52 -0500 Subject: [PATCH 49/53] add disk_allocation_throttle_factor --- taskvine/src/manager/vine_manager.c | 18 +++++++++++------- taskvine/src/manager/vine_manager.h | 1 + 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index 2199539512..b501edb71e 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2673,6 +2673,10 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, max_proportion = 1; } + /* Perform the standard proportional memory and disk allocations */ + limits->memory = MAX(1, MAX(limits->memory, floor(memory_total * max_proportion))); + limits->disk = MAX(1, MAX(limits->disk, floor(disk_total * max_proportion / q->resource_submit_multiplier))); + /* When cores are unspecified, they are set to 0 if gpus are specified. * Otherwise they get a proportion according to specified resources. */ if (limits->cores == -1 && limits->gpus > 0) { @@ -2687,13 +2691,6 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, } else { /* Do not allocate a proportion of gpus */ } - - limits->disk = MAX(1, MAX(limits->disk, floor(disk_total * max_proportion / q->resource_submit_multiplier))); - limits->memory = MAX(1, MAX(limits->memory, floor(memory_total * max_proportion))); - - /* We divide the estimated disk by 2 because inputs and outputs are moved around between the sandbox and - * the cache, we leave some space for that, and we want to leave some space for the cache to grow. */ - limits->disk /= 2; } /* If one of the resources is not specified, use the available instead */ @@ -2710,6 +2707,10 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, limits->disk = disk_available; } + /* After the guess is done, scale the estimated disk allocation by a [0, 1] number (by default 0.75) to intentionally + * reserve some space for data movement between the sandbox and cache (output files) and allow room for cache growth. */ + limits->disk *= q->disk_allocation_throttle_factor; + /* Never go below min resources. */ rmsummary_merge_max(limits, min); @@ -5611,6 +5612,9 @@ int vine_tune(struct vine_manager *q, const char *name, double value) } else if (!strcmp(name, "sandbox-grow-factor")) { q->sandbox_grow_factor = MAX(1.1, value); + } else if (!strcmp(name, "disk-allocation-throttle-factor")) { + q->disk_allocation_throttle_factor = MAX(0.0, MIN(1.0, value)); /* has to be in [0, 1] */ + } else { debug(D_NOTICE | D_VINE, "Warning: tuning parameter \"%s\" not recognized\n", name); return -1; diff --git a/taskvine/src/manager/vine_manager.h b/taskvine/src/manager/vine_manager.h index ea5e860186..ade4c8bc99 100644 --- a/taskvine/src/manager/vine_manager.h +++ b/taskvine/src/manager/vine_manager.h @@ -225,6 +225,7 @@ struct vine_manager { int watch_library_logfiles; /* If true, watch the output files produced by each of the library processes running on the remote workers, take them back the current logging directory */ double sandbox_grow_factor; /* When task disk sandboxes are exhausted, increase the allocation using their measured valued times this factor */ + double disk_allocation_throttle_factor; /* intentionally reduces disk allocation for tasks to reserve some space for cache growth. */ /*todo: confirm datatype. int or int64*/ int max_task_stdout_storage; /* Maximum size of standard output from task. (If larger, send to a separate file.) */ From 098fc58a976c28e302aaf747517906c9e6b6222d Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Fri, 17 Jan 2025 12:21:47 -0500 Subject: [PATCH 50/53] initiate disk_allocation_throttle_factor --- taskvine/src/manager/vine_manager.c | 1 + 1 file changed, 1 insertion(+) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index 7aa213aa43..d5f5e911b7 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -4002,6 +4002,7 @@ struct vine_manager *vine_ssl_create(int port, const char *key, const char *cert q->large_task_check_interval = VINE_LARGE_TASK_CHECK_INTERVAL; q->hungry_check_interval = VINE_HUNGRY_CHECK_INTERVAL; q->option_blocklist_slow_workers_timeout = vine_option_blocklist_slow_workers_timeout; + q->disk_allocation_throttle_factor = 0.75; q->manager_preferred_connection = xxstrdup("by_ip"); From 8e83f5f7987d9ae4468d678f140b60dd51b4213e Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Fri, 17 Jan 2025 12:49:17 -0500 Subject: [PATCH 51/53] change name and test --- taskvine/src/manager/vine_manager.c | 14 +++++++------- taskvine/src/manager/vine_manager.h | 2 +- taskvine/test/vine_allocations.py | 11 ++++++----- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index d5f5e911b7..b13fc32aa9 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2696,9 +2696,13 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, max_proportion = 1; } - /* Perform the standard proportional memory and disk allocations */ + /* Perform the standard proportional memory allocation */ limits->memory = MAX(1, MAX(limits->memory, floor(memory_total * max_proportion))); + + /* For disk, scale the estimated disk allocation by a [0, 1] number (by default 0.75) to intentionally reserve + * some space for data movement between the sandbox and cache (output files) and allow room for cache growth. */ limits->disk = MAX(1, MAX(limits->disk, floor(disk_total * max_proportion / q->resource_submit_multiplier))); + limits->disk *= q->disk_proportion_available_to_task; /* When cores are unspecified, they are set to 0 if gpus are specified. * Otherwise they get a proportion according to specified resources. */ @@ -2730,10 +2734,6 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, limits->disk = disk_available; } - /* After the guess is done, scale the estimated disk allocation by a [0, 1] number (by default 0.75) to intentionally - * reserve some space for data movement between the sandbox and cache (output files) and allow room for cache growth. */ - limits->disk *= q->disk_allocation_throttle_factor; - /* Never go below min resources. */ rmsummary_merge_max(limits, min); @@ -4002,7 +4002,7 @@ struct vine_manager *vine_ssl_create(int port, const char *key, const char *cert q->large_task_check_interval = VINE_LARGE_TASK_CHECK_INTERVAL; q->hungry_check_interval = VINE_HUNGRY_CHECK_INTERVAL; q->option_blocklist_slow_workers_timeout = vine_option_blocklist_slow_workers_timeout; - q->disk_allocation_throttle_factor = 0.75; + q->disk_proportion_available_to_task = 0.75; q->manager_preferred_connection = xxstrdup("by_ip"); @@ -5668,7 +5668,7 @@ int vine_tune(struct vine_manager *q, const char *name, double value) q->sandbox_grow_factor = MAX(1.1, value); } else if (!strcmp(name, "disk-allocation-throttle-factor")) { - q->disk_allocation_throttle_factor = MAX(0.0, MIN(1.0, value)); /* has to be in [0, 1] */ + q->disk_proportion_available_to_task = MAX(0.0, MIN(1.0, value)); /* has to be in [0, 1] */ } else if (!strcmp(name, "max-library-retries")) { q->max_library_retries = MIN(1, value); diff --git a/taskvine/src/manager/vine_manager.h b/taskvine/src/manager/vine_manager.h index ade4c8bc99..ea8f3f7109 100644 --- a/taskvine/src/manager/vine_manager.h +++ b/taskvine/src/manager/vine_manager.h @@ -225,7 +225,7 @@ struct vine_manager { int watch_library_logfiles; /* If true, watch the output files produced by each of the library processes running on the remote workers, take them back the current logging directory */ double sandbox_grow_factor; /* When task disk sandboxes are exhausted, increase the allocation using their measured valued times this factor */ - double disk_allocation_throttle_factor; /* intentionally reduces disk allocation for tasks to reserve some space for cache growth. */ + double disk_proportion_available_to_task; /* intentionally reduces disk allocation for tasks to reserve some space for cache growth. */ /*todo: confirm datatype. int or int64*/ int max_task_stdout_storage; /* Maximum size of standard output from task. (If larger, send to a separate file.) */ diff --git a/taskvine/test/vine_allocations.py b/taskvine/test/vine_allocations.py index febbf5c0f4..df42efce41 100755 --- a/taskvine/test/vine_allocations.py +++ b/taskvine/test/vine_allocations.py @@ -76,18 +76,19 @@ def check_task(category, category_mode, max, min, expected): # note that the disk is divided by 2 if using proportional resource allocations q.tune("force-proportional-resources", 1) + disk_proportion_available_to_task = 0.75 - check_task("only_memory", "fixed", max={"memory": worker_memory / 2}, min={}, expected={"cores": worker_cores / 2, "memory": worker_memory / 2, "disk": worker_disk / 2 / 2, "gpus": 0}) + check_task("only_memory", "fixed", max={"memory": worker_memory / 2}, min={}, expected={"cores": worker_cores / 2, "memory": worker_memory / 2, "disk": worker_disk / 2 * disk_proportion_available_to_task, "gpus": 0}) - check_task("only_memory_w_minimum", "fixed", max={"memory": worker_memory / 2}, min={"cores": 3, "gpus": 2}, expected={"cores": 4, "memory": worker_memory, "disk": worker_disk / 2, "gpus": 2}) + check_task("only_memory_w_minimum", "fixed", max={"memory": worker_memory / 2}, min={"cores": 3, "gpus": 2}, expected={"cores": 4, "memory": worker_memory, "disk": worker_disk * disk_proportion_available_to_task, "gpus": 2}) - check_task("only_cores", "fixed", max={"cores": worker_cores}, min={}, expected={"cores": worker_cores, "memory": worker_memory, "disk": worker_disk / 2, "gpus": 0}) + check_task("only_cores", "fixed", max={"cores": worker_cores}, min={}, expected={"cores": worker_cores, "memory": worker_memory, "disk": worker_disk * disk_proportion_available_to_task, "gpus": 0}) - check_task("auto_whole_worker", "min_waste", max={}, min={}, expected={"cores": worker_cores, "memory": worker_memory, "disk": worker_disk / 2, "gpus": 0}) + check_task("auto_whole_worker", "min_waste", max={}, min={}, expected={"cores": worker_cores, "memory": worker_memory, "disk": worker_disk * disk_proportion_available_to_task, "gpus": 0}) p = 1 / worker_cores r = {"cores": 1} - e = {"cores": 1, "memory": math.floor(worker_memory * p), "disk": math.floor(worker_disk * p) / 2, "gpus": 0} + e = {"cores": 1, "memory": math.floor(worker_memory * p), "disk": math.floor(worker_disk * p) * disk_proportion_available_to_task, "gpus": 0} check_task("only_cores_proportional", "fixed", max=r, min={}, expected=e) p = 2 / worker_cores From e9d4f8b29f4e0849b4956d3fcb9145d8f3da7fef Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Fri, 17 Jan 2025 12:55:49 -0500 Subject: [PATCH 52/53] lint --- taskvine/src/manager/vine_manager.c | 2 +- taskvine/test/vine_allocations.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index b13fc32aa9..15cc0cd2dc 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -2700,7 +2700,7 @@ struct rmsummary *vine_manager_choose_resources_for_task(struct vine_manager *q, limits->memory = MAX(1, MAX(limits->memory, floor(memory_total * max_proportion))); /* For disk, scale the estimated disk allocation by a [0, 1] number (by default 0.75) to intentionally reserve - * some space for data movement between the sandbox and cache (output files) and allow room for cache growth. */ + * some space for data movement between the sandbox and cache (output files) and allow room for cache growth. */ limits->disk = MAX(1, MAX(limits->disk, floor(disk_total * max_proportion / q->resource_submit_multiplier))); limits->disk *= q->disk_proportion_available_to_task; diff --git a/taskvine/test/vine_allocations.py b/taskvine/test/vine_allocations.py index df42efce41..b32a61ec25 100755 --- a/taskvine/test/vine_allocations.py +++ b/taskvine/test/vine_allocations.py @@ -76,7 +76,7 @@ def check_task(category, category_mode, max, min, expected): # note that the disk is divided by 2 if using proportional resource allocations q.tune("force-proportional-resources", 1) - disk_proportion_available_to_task = 0.75 + disk_proportion_available_to_task = 0.75 # the default factor check_task("only_memory", "fixed", max={"memory": worker_memory / 2}, min={}, expected={"cores": worker_cores / 2, "memory": worker_memory / 2, "disk": worker_disk / 2 * disk_proportion_available_to_task, "gpus": 0}) From 46aec0376e82e884eafcca02d5a5a25c9386634e Mon Sep 17 00:00:00 2001 From: JinZhou5042 Date: Fri, 17 Jan 2025 14:30:34 -0500 Subject: [PATCH 53/53] name fix --- taskvine/src/manager/vine_manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taskvine/src/manager/vine_manager.c b/taskvine/src/manager/vine_manager.c index 15cc0cd2dc..c1688729ac 100644 --- a/taskvine/src/manager/vine_manager.c +++ b/taskvine/src/manager/vine_manager.c @@ -5667,7 +5667,7 @@ int vine_tune(struct vine_manager *q, const char *name, double value) } else if (!strcmp(name, "sandbox-grow-factor")) { q->sandbox_grow_factor = MAX(1.1, value); - } else if (!strcmp(name, "disk-allocation-throttle-factor")) { + } else if (!strcmp(name, "disk-proportion-available-to-task")) { q->disk_proportion_available_to_task = MAX(0.0, MIN(1.0, value)); /* has to be in [0, 1] */ } else if (!strcmp(name, "max-library-retries")) {