63 file.read(
reinterpret_cast<char*
>(&
dest),
sizeof(
T));
65 throw std::runtime_error(
66 "GGUF Error: Failed to read data from file stream.");
87 throw std::runtime_error(
88 "GGUF Error: String length exceeds sanity limit: " +
91 std::vector<char>
buf(
static_cast<size_t>(len));
92 file.read(
buf.data(),
static_cast<std::streamsize
>(len));
94 throw std::runtime_error(
"GGUF Error: Failed to read string data.");
96 return std::string(
buf.data(),
static_cast<size_t>(len));
127 throw std::runtime_error(
"Failed to open file for metadata: " +
filename);
140 std::stringstream
ss;
141 ss <<
"Read Header:\n"
142 <<
" Magic: 0x" << std::hex <<
result.header.magic << std::dec <<
"\n"
143 <<
" Version: " <<
result.header.version <<
"\n"
144 <<
" Tensor Count: " <<
result.header.tensor_count <<
"\n"
145 <<
" Metadata KV Count: " <<
result.header.metadata_kv_count;
150 throw std::runtime_error(
"Not a valid GGUF file (magic number mismatch).");
154 std::to_string(
result.header.metadata_kv_count) +
" pairs)...");
208 result.metadata[key] = (
byte != 0);
245 if (key ==
"tokenizer.ggml.tokens" &&
247 Logger::info(
"Loading STRING array data ('" + key +
"') with " +
248 std::to_string(
count) +
" elements...");
249 result.tokenizer_tokens.reserve(
static_cast<size_t>(
count));
254 std::to_string(
result.tokenizer_tokens.size()));
255 }
else if (key ==
"tokenizer.ggml.scores" &&
257 Logger::info(
"Loading FLOAT32 array data ('" + key +
"') with " +
258 std::to_string(
count) +
" elements...");
259 result.tokenizer_scores.resize(
static_cast<size_t>(
count));
261 static_cast<std::streamsize
>(
count *
sizeof(
float)));
263 throw std::runtime_error(
264 "GGUF Error: Failed to read scores array data.");
267 std::to_string(
result.tokenizer_scores.size()));
268 }
else if (key ==
"tokenizer.ggml.token_type" &&
271 " array data ('" + key +
"') with " +
272 std::to_string(
count) +
" elements...");
273 result.tokenizer_token_types.resize(
static_cast<size_t>(
count));
276 reinterpret_cast<char*
>(
result.tokenizer_token_types.data()),
288 throw std::runtime_error(
289 "GGUF Error: Failed to read token_type array data.");
292 std::to_string(
result.tokenizer_token_types.size()));
293 }
else if (key ==
"tokenizer.ggml.merges" &&
295 Logger::info(
"Loading STRING array data ('" + key +
"') with " +
296 std::to_string(
count) +
" elements...");
297 result.tokenizer_merges.reserve(
static_cast<size_t>(
count));
302 std::to_string(
result.tokenizer_merges.size()));
306 "Skipping unhandled/non-tokenizer ARRAY data for key '" + key +
309 ", Count: " + std::to_string(
count) +
")");
315 }
catch (
const std::exception&
e) {
317 std::to_string(
arr_i) +
" for key '" + key +
325 throw std::runtime_error(
326 "Cannot skip array for key '" + key +
327 "' with unsupported or variable-sized element type: " +
333 throw std::overflow_error(
334 "Array size overflow calculating skip amount for key '" +
342 throw std::runtime_error(
343 "GGUF Error: Failed to seek past array data for key '" +
352 throw std::runtime_error(
353 "Unknown metadata type encountered: " +
358 }
catch (
const std::exception&
e) {
360 key.empty() ?
"(unknown key, error during key read)" : key;
362 "Error reading metadata for key: '" +
error_key +
370 result.tensor_infos.reserve(
static_cast<size_t>(
result.header.tensor_count));
372 std::to_string(
result.header.tensor_count) +
" tensors)...");
382 throw std::runtime_error(
"Tensor '" + info.
name +
383 "' has unsupported number of dimensions: " +
401 <<
"[GGUF_TENSOR_INFO] Tensor " <<
i <<
" ('" << info.
name
402 <<
"'):" <<
"\n Raw offset from file: " << info.
offset
404 <<
"\n Calculated accumulated_offset_debug (before this tensor): "
411 throw std::overflow_error(
412 "Tensor dimension overflow calculating num_elements for tensor "
423 throw std::runtime_error(
424 "Tensor '" + info.
name +
425 "' has unknown or unsupported type: " + std::to_string(info.
type));
430 throw std::runtime_error(
"Tensor '" + info.
name +
"' num_elements (" +
432 ") not divisible by block_size (" +
439 throw std::overflow_error(
440 "Tensor size overflow calculating size_in_bytes for tensor '" +
447 std::numeric_limits<uint64_t>::max() /
type_size) {
448 throw std::overflow_error(
449 "Tensor size overflow calculating size_in_bytes for tensor '" +
455 ss_offset_log <<
"\n Calculated size_in_bytes for this tensor: "
460 result.tensor_infos.push_back(info);
465 for (
size_t d = 0; d < info.
shape.size(); ++d)
467 << (d == info.
shape.size() - 1 ?
"" :
", ");
472 }
catch (
const std::exception&
e) {
474 info.
name.empty() ? (
"(unknown, index " + std::to_string(
i) +
")")
487 "'. Overwriting entry in map.");
491 Logger::info(
"Finished populating tensor_infos_map. Map size: " +
492 std::to_string(
result.tensor_infos_map.size()));
496 if (
result.metadata.count(
"general.alignment")) {
498 std::get<uint32_t>(
result.metadata[
"general.alignment"]);
506 "Metadata key 'general.alignment' not found. Using default "
510 }
catch (
const std::bad_variant_access&
e) {
512 "Could not read 'general.alignment' metadata as uint32. Using default "
515 }
catch (
const std::exception&
e) {
517 std::string(
e.what()) +
518 ". Using default alignment: " + std::to_string(
alignment));
523 Logger::info(
"[GGUF_LOAD] Current file position (metadata stream) before padding seek: " +
530 "[GGUF_LOAD] Calculated actual_data_start_offset_in_file (for mmap): " +
537 Logger::info(
"[GGUF_LOAD] mmap is disabled by configuration. Loading tensor data into memory using OPTIMIZED bulk I/O.");
549 throw std::runtime_error(
"Failed to open file for tensor data reading: " +
filename);
554 throw std::runtime_error(
"Failed to seek to tensor data start in file: " +
filename);
569 throw std::runtime_error(
"Failed to read tensor data chunk at offset " + std::to_string(
bytes_read_total) +
" from file: " +
filename);
585 ss_bytes <<
"[GGUF_LOAD] First 16 bytes of tensor data: ";
586 for (
int i = 0;
i < 16; ++
i) {
587 ss_bytes <<
"0x" << std::hex << static_cast<int>(
result.tensor_data[
i]) <<
" ";
592 Logger::info(
"[GGUF_LOAD] No tensor data to load (total size is 0).");
600 if (
result.file_descriptor == -1) {
601 throw std::runtime_error(
"GGUF Error: Failed to open file for mmap: " +
filename +
" - " +
strerror(
errno));
603 Logger::info(
"[GGUF_LOAD] File opened for mmap with fd: " + std::to_string(
result.file_descriptor));
608 result.file_descriptor = -1;
609 throw std::runtime_error(
"GGUF Error: Failed to fstat file for mmap: " +
filename +
" - " +
strerror(
errno));
640 result.file_descriptor = -1;
645 throw std::runtime_error(
651 Logger::info(
"[GGUF_LOAD] Calculated tensor_data_block_size_on_disk (for mmap length calculation): " +
659 result.file_descriptor = -1;
660 throw std::runtime_error(std::string(
"GGUF Error: Failed to get page size using sysconf - ") +
strerror(
errno));
671 throw std::runtime_error(
"GGUF Error: Failed to get valid system allocation granularity (page_size equivalent for mmap offset).");
674 Logger::info(
"[GGUF_LOAD] System page/allocation granularity for mmap offset: " + std::to_string(
page_size));
682 ", offset_diff_for_mmap=" + std::to_string(
result.offset_diff_for_mmap) +
717 result.mapped_tensor_data_size
730 result.mapped_tensor_data =
nullptr;
731 result.mapped_tensor_data_size = 0;
732 result.offset_diff_for_mmap = 0;
733 throw std::runtime_error(
"GGUF Error: mmap/MapViewOfFile failed. Aligned Offset: " + std::to_string(
mmap_offset) +
741 Logger::info(
"[GGUF_LOAD] Successfully mmapped tensor data block. Mapped Address: " +
742 std::to_string(
reinterpret_cast<uintptr_t>(
result.mapped_tensor_data)) +
743 ", Mapped Size: " + std::to_string(
result.mapped_tensor_data_size) +
744 " bytes from file offset " + std::to_string(
mmap_offset));
746 if (
result.mapped_tensor_data_size >= (
result.offset_diff_for_mmap + 16)) {
748 ss_bytes <<
"[GGUF_LOAD] First 16 bytes of *actual* tensor data (after offset_diff) in mmap: ";
750 for (
int i = 0;
i < 16; ++
i)
757 Logger::info(
"[GGUF_LOAD] Attempting to prefetch mmapped tensor data using posix_madvise(MADV_WILLNEED)...");
761 Logger::error(
"[GGUF_LOAD] Invalid page_size for madvise alignment: " + std::to_string(
page_size) +
". Skipping prefetch.");
780 ") with error code " + std::to_string(
errno) +
781 " (" +
strerror(
errno) +
"). Skipping prefetch for this tensor.");
785 "' calculated region for madvise is invalid or out of overall mmap bounds. Skipping prefetch. "
791 Logger::info(
"[GGUF_LOAD] Finished POSIX prefetching attempt with posix_madvise.");
794 Logger::info(
"[GGUF_LOAD] Tensor prefetching (posix_madvise) is currently implemented for POSIX systems. Skipping for Windows for now.");
798 Logger::info(
"[GGUF_LOAD] Tensor data block size (or mmap_length) is 0. Nothing to mmap.");
799 result.mapped_tensor_data =
nullptr;
800 result.mapped_tensor_data_size = 0;
801 result.offset_diff_for_mmap = 0;
804 Logger::info(
"GGUF metadata loaded and tensor data (if any) mmapped successfully.");
static void warning(const std::string &message)
static void info(const std::string &message)
static void error(const std::string &message)
GGMLType
Enumeration of GGML tensor data types.
GGUFValueType
Enumeration of value types used in GGUF metadata.
template void read_raw< int16_t >(std::ifstream &, int16_t &)
size_t gguf_value_type_size(GGUFValueType type)
template void read_raw< int8_t >(std::ifstream &, int8_t &)
template void read_raw< uint64_t >(std::ifstream &, uint64_t &)
template void read_raw< uint32_t >(std::ifstream &, uint32_t &)
template void read_raw< int64_t >(std::ifstream &, int64_t &)
template void read_raw< uint8_t >(std::ifstream &, uint8_t &)
template void read_raw< GGUFValueType >(std::ifstream &, GGUFValueType &)
void read_raw(std::ifstream &file, T &dest)
Reads raw binary data from a file stream.
template void read_raw< uint16_t >(std::ifstream &, uint16_t &)
template void read_raw< double >(std::ifstream &, double &)
template void read_raw< float >(std::ifstream &, float &)
template void read_raw< int32_t >(std::ifstream &, int32_t &)
GGUFData load_gguf_meta(const std::string &filename, bool use_mmap)
Loads GGUF metadata and optionally memory-maps tensor data.
std::string read_gguf_string(std::ifstream &file)
Reads a string from a GGUF format file.
Parser for GGUF (GPT-Generated Unified Format) files.
constexpr uint32_t GGUF_MAGIC
GGUF magic number that identifies the file format Spells "GGUF" in ASCII (0x47475546)
constexpr uint32_t GGUF_MAX_TENSOR_DIMS
constexpr uint64_t GGUF_STRING_MAX_LENGTH
constexpr uint64_t GGUF_DEFAULT_ALIGNMENT
Constants for GGUF file parsing and validation.
enum ember_ir::@44::Value::Type type
Logging utilities for the TinyLlama implementation.
size_t ggml_type_block_size(GGMLType type)
Gets the block size for a GGML type.
size_t ggml_type_size(GGMLType type)
Gets the size in bytes of a GGML type.
const char * ggml_type_name(GGMLType type)
Gets the string name of a GGML type.
Weight quantization structures and functions for model compression.
Represents an array in GGUF metadata.
Complete representation of a GGUF file's contents.
static const void * MMapFailure
Information about a tensor stored in a GGUF file.
std::vector< uint64_t > shape