15
15
#include " ggml/ggml-backend.h"
16
16
#include " ggml/ggml.h"
17
17
18
+ #include " stable-diffusion.h"
19
+
18
20
#ifdef SD_USE_METAL
19
21
#include " ggml-metal.h"
20
22
#endif
@@ -609,7 +611,7 @@ bool is_safetensors_file(const std::string& file_path) {
609
611
}
610
612
611
613
size_t header_size_ = read_u64 (header_size_buf);
612
- if (header_size_ >= file_size_) {
614
+ if (header_size_ >= file_size_ || header_size_ <= 2 ) {
613
615
return false ;
614
616
}
615
617
@@ -1434,7 +1436,61 @@ bool ModelLoader::load_tensors(std::map<std::string, struct ggml_tensor*>& tenso
1434
1436
return true ;
1435
1437
}
1436
1438
1437
- int64_t ModelLoader::cal_mem_size (ggml_backend_t backend) {
1439
+ bool ModelLoader::save_to_gguf_file (const std::string& file_path, ggml_type type) {
1440
+ auto backend = ggml_backend_cpu_init ();
1441
+ size_t mem_size = 1 * 1024 * 1024 ; // for padding
1442
+ mem_size += tensor_storages.size () * ggml_tensor_overhead ();
1443
+ mem_size += cal_mem_size (backend, type);
1444
+ LOG_INFO (" model tensors mem size: %.2fMB" , mem_size / 1024 .f / 1024 .f );
1445
+ ggml_context* ggml_ctx = ggml_init ({mem_size, NULL , false });
1446
+
1447
+ gguf_context* gguf_ctx = gguf_init_empty ();
1448
+
1449
+ auto on_new_tensor_cb = [&](const TensorStorage& tensor_storage, ggml_tensor** dst_tensor) -> bool {
1450
+ const std::string& name = tensor_storage.name ;
1451
+
1452
+ ggml_type tensor_type = tensor_storage.type ;
1453
+ if (type != GGML_TYPE_COUNT) {
1454
+ if (ggml_is_quantized (type) && tensor_storage.ne [0 ] % 32 != 0 ) {
1455
+ tensor_type = GGML_TYPE_F16;
1456
+ } else {
1457
+ tensor_type = type;
1458
+ }
1459
+ }
1460
+
1461
+ ggml_tensor* tensor = ggml_new_tensor (ggml_ctx, tensor_type, tensor_storage.n_dims , tensor_storage.ne );
1462
+ if (tensor == NULL ) {
1463
+ LOG_ERROR (" ggml_new_tensor failed" );
1464
+ return false ;
1465
+ }
1466
+ ggml_set_name (tensor, name.c_str ());
1467
+
1468
+ // LOG_DEBUG("%s %d %s %d[%d %d %d %d] %d[%d %d %d %d]", name.c_str(),
1469
+ // ggml_nbytes(tensor), ggml_type_name(tensor_type),
1470
+ // tensor_storage.n_dims,
1471
+ // tensor_storage.ne[0], tensor_storage.ne[1], tensor_storage.ne[2], tensor_storage.ne[3],
1472
+ // tensor->n_dims, tensor->ne[0], tensor->ne[1], tensor->ne[2], tensor->ne[3]);
1473
+
1474
+ *dst_tensor = tensor;
1475
+
1476
+ gguf_add_tensor (gguf_ctx, tensor);
1477
+
1478
+ return true ;
1479
+ };
1480
+
1481
+ bool success = load_tensors (on_new_tensor_cb, backend);
1482
+ ggml_backend_free (backend);
1483
+ LOG_INFO (" load tensors done" );
1484
+ LOG_INFO (" trying to save tensors to %s" , file_path.c_str ());
1485
+ if (success) {
1486
+ gguf_write_to_file (gguf_ctx, file_path.c_str (), false );
1487
+ }
1488
+ ggml_free (ggml_ctx);
1489
+ gguf_free (gguf_ctx);
1490
+ return success;
1491
+ }
1492
+
1493
+ int64_t ModelLoader::cal_mem_size (ggml_backend_t backend, ggml_type type) {
1438
1494
size_t alignment = 128 ;
1439
1495
if (backend != NULL ) {
1440
1496
alignment = ggml_backend_get_alignment (backend);
@@ -1449,8 +1505,28 @@ int64_t ModelLoader::cal_mem_size(ggml_backend_t backend) {
1449
1505
}
1450
1506
1451
1507
for (auto & tensor_storage : processed_tensor_storages) {
1508
+ ggml_type tensor_type = tensor_storage.type ;
1509
+ if (type != GGML_TYPE_COUNT) {
1510
+ if (ggml_is_quantized (type) && tensor_storage.ne [0 ] % 32 != 0 ) {
1511
+ tensor_type = GGML_TYPE_F16;
1512
+ } else {
1513
+ tensor_type = type;
1514
+ }
1515
+ }
1516
+ tensor_storage.type = tensor_type;
1452
1517
mem_size += tensor_storage.nbytes () + alignment;
1453
1518
}
1454
1519
1455
1520
return mem_size;
1456
1521
}
1522
+
1523
+ bool convert (const char * input_path, const char * output_path, sd_type_t output_type) {
1524
+ ModelLoader model_loader;
1525
+
1526
+ if (!model_loader.init_from_file (input_path)) {
1527
+ LOG_ERROR (" init model loader from file failed: '%s'" , input_path);
1528
+ return false ;
1529
+ }
1530
+ bool success = model_loader.save_to_gguf_file (output_path, (ggml_type)output_type);
1531
+ return success;
1532
+ }
0 commit comments