gguf-split: Add option to delete split parts during merge (#26538)
* Add delete-files option to split parameters Added a new option to delete split files during execution to free up disk space. * Add test for delete files on merge option * Fix tests * Update tools/gguf-split/gguf-split.cpp Co-authored-by: Sigbjørn Skjæret <sigbjorn.skjaeret@huggingface.co> * Update tools/gguf-split/gguf-split.cpp Co-authored-by: Sigbjørn Skjæret <sigbjorn.skjaeret@huggingface.co> * Uncomment tests * Improvements to address PR comments * Fix formatting * Fix formatting * Rename --delete-files to --delete-splits * Comment tests * Move delete inside loop * style cleanup --------- Co-authored-by: Sigbjørn Skjæret <sigbjorn.skjaeret@huggingface.co>
This commit is contained in:
co-authored by
Sigbjørn Skjæret
parent
2f56fc3431
commit
76c956c137
@@ -47,6 +47,7 @@ struct split_params {
|
|||||||
std::string output;
|
std::string output;
|
||||||
bool no_tensor_first_split = false;
|
bool no_tensor_first_split = false;
|
||||||
bool dry_run = false;
|
bool dry_run = false;
|
||||||
|
bool delete_splits = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void split_print_usage(const char * executable) {
|
static void split_print_usage(const char * executable) {
|
||||||
@@ -65,6 +66,7 @@ static void split_print_usage(const char * executable) {
|
|||||||
printf(" --split-max-size N(M|G) max size per split\n");
|
printf(" --split-max-size N(M|G) max size per split\n");
|
||||||
printf(" --no-tensor-first-split do not add tensors to the first split (disabled by default)\n");
|
printf(" --no-tensor-first-split do not add tensors to the first split (disabled by default)\n");
|
||||||
printf(" --dry-run only print out a split plan and exit, without writing any new files\n");
|
printf(" --dry-run only print out a split plan and exit, without writing any new files\n");
|
||||||
|
printf(" --delete-splits delete the split files during merge to free up disk space WARNING: this option is unsafe and will leave you in an unrecoverable state if something fails during the merge\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,6 +149,9 @@ static void split_params_parse_ex(int argc, const char ** argv, split_params & p
|
|||||||
}
|
}
|
||||||
params.mode = MODE_SIZE;
|
params.mode = MODE_SIZE;
|
||||||
params.n_bytes_split = split_str_to_n_bytes(argv[arg_idx]);
|
params.n_bytes_split = split_str_to_n_bytes(argv[arg_idx]);
|
||||||
|
} else if (arg == "--delete-splits") {
|
||||||
|
arg_found = true;
|
||||||
|
params.delete_splits = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!arg_found) {
|
if (!arg_found) {
|
||||||
@@ -509,6 +514,7 @@ static void gguf_merge(const split_params & split_params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write tensors data
|
// Write tensors data
|
||||||
|
bool merge_error = false;
|
||||||
for (int i_split = 0; i_split < n_split; i_split++) {
|
for (int i_split = 0; i_split < n_split; i_split++) {
|
||||||
llama_split_path(split_path, sizeof(split_path), split_prefix, i_split, n_split);
|
llama_split_path(split_path, sizeof(split_path), split_prefix, i_split, n_split);
|
||||||
std::ifstream f_input(split_path, std::ios::binary);
|
std::ifstream f_input(split_path, std::ios::binary);
|
||||||
@@ -554,6 +560,16 @@ static void gguf_merge(const split_params & split_params) {
|
|||||||
ggml_free(ctx_meta);
|
ggml_free(ctx_meta);
|
||||||
f_input.close();
|
f_input.close();
|
||||||
fprintf(stderr, "\033[3Ddone\n");
|
fprintf(stderr, "\033[3Ddone\n");
|
||||||
|
|
||||||
|
if (!split_params.dry_run && split_params.delete_splits) {
|
||||||
|
int delete_result = std::remove(split_path);
|
||||||
|
if (delete_result != 0) {
|
||||||
|
merge_error = true;
|
||||||
|
fprintf(stderr, "error: failed to delete %s\n", split_path);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "%s: deleted file %s\n", __func__, split_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!split_params.dry_run) {
|
if (!split_params.dry_run) {
|
||||||
@@ -568,6 +584,10 @@ static void gguf_merge(const split_params & split_params) {
|
|||||||
|
|
||||||
fprintf(stderr, "%s: %s merged from %d split with %d tensors.\n",
|
fprintf(stderr, "%s: %s merged from %d split with %d tensors.\n",
|
||||||
__func__, split_params.output.c_str(), n_split, total_tensors);
|
__func__, split_params.output.c_str(), n_split, total_tensors);
|
||||||
|
|
||||||
|
if (merge_error) {
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char ** argv) {
|
int main(int argc, const char ** argv) {
|
||||||
|
|||||||
@@ -66,12 +66,12 @@ echo PASS
|
|||||||
echo
|
echo
|
||||||
|
|
||||||
# 5. Merge
|
# 5. Merge
|
||||||
#$SPLIT --merge $WORK_PATH/ggml-model-split-32-tensors-00001-of-00012.gguf $WORK_PATH/ggml-model-merge-2.gguf
|
#$SPLIT --merge $WORK_PATH/ggml-model-split-32-tensors-00001-of-00011.gguf $WORK_PATH/ggml-model-merge-2.gguf
|
||||||
#echo PASS
|
#echo PASS
|
||||||
#echo
|
#echo
|
||||||
|
|
||||||
# 5b. Test the merged model is loading properly
|
# 5b. Test the merged model is loading properly
|
||||||
#$MAIN -no-cnv --model $WORK_PATH/ggml-model-merge-2.gguf --n-predict 32
|
#$MAIN -no-cnv --model $WORK_PATH/ggml-model-merge-2.gguf -p "I believe the meaning of life is" --n-predict 32
|
||||||
#echo PASS
|
#echo PASS
|
||||||
#echo
|
#echo
|
||||||
|
|
||||||
@@ -85,5 +85,25 @@ $MAIN -no-cnv --model $WORK_PATH/ggml-model-split-500M-00001-of-00002.gguf -p "I
|
|||||||
echo PASS
|
echo PASS
|
||||||
echo
|
echo
|
||||||
|
|
||||||
|
# 7. Merge with delete splits
|
||||||
|
#for i in $(seq -w 1 11); do
|
||||||
|
# cp "$WORK_PATH/ggml-model-split-32-tensors-000${i}-of-00011.gguf" "$WORK_PATH/ggml-model-split-32-tensors-copy-000${i}-of-00011.gguf"
|
||||||
|
#done
|
||||||
|
#$SPLIT --merge --delete-splits $WORK_PATH/ggml-model-split-32-tensors-copy-00001-of-00011.gguf $WORK_PATH/ggml-model-merge-3.gguf
|
||||||
|
#echo PASS
|
||||||
|
#echo
|
||||||
|
|
||||||
|
# 7b. Test the merged model is loading properly
|
||||||
|
#$MAIN -no-cnv --model $WORK_PATH/ggml-model-merge-3.gguf -p "I believe the meaning of life is" --n-predict 32
|
||||||
|
#echo PASS
|
||||||
|
#echo
|
||||||
|
|
||||||
|
# 7c. Test the files were deleted
|
||||||
|
#for i in $(seq -w 1 11); do
|
||||||
|
# test ! -f "$WORK_PATH/ggml-model-split-32-tensors-copy-000${i}-of-00011.gguf"
|
||||||
|
#done
|
||||||
|
#echo PASS
|
||||||
|
#echo
|
||||||
|
|
||||||
# Clean up
|
# Clean up
|
||||||
rm -f $WORK_PATH/ggml-model-split*.gguf $WORK_PATH/ggml-model-merge*.gguf
|
rm -f $WORK_PATH/ggml-model-split*.gguf $WORK_PATH/ggml-model-merge*.gguf
|
||||||
|
|||||||
Reference in New Issue
Block a user