#ifndef __SD_TENSOR_GGML_HPP__ #define __SD_TENSOR_GGML_HPP__ #include #include #include #include #include #include #include "ggml.h" #include "tensor.hpp" namespace sd { template struct GGMLTypeTraits; template <> struct GGMLTypeTraits { static constexpr ggml_type type = GGML_TYPE_F32; }; template <> struct GGMLTypeTraits { static constexpr ggml_type type = GGML_TYPE_F16; }; template <> struct GGMLTypeTraits { static constexpr ggml_type type = GGML_TYPE_I32; }; template <> struct GGMLTypeTraits { static constexpr ggml_type type = GGML_TYPE_I64; }; inline std::vector shape_from_ggml(const ggml_tensor* tensor) { std::vector shape; shape.reserve(static_cast(ggml_n_dims(tensor))); for (int i = 0; i < ggml_n_dims(tensor); ++i) { shape.push_back(tensor->ne[i]); } return shape; } template inline Tensor make_sd_tensor_from_ggml(const ggml_tensor* tensor) { if (tensor == nullptr) { return {}; } if (tensor->type != GGMLTypeTraits::type) { GGML_ABORT("ggml tensor type does not match sd::Tensor type"); } Tensor result(shape_from_ggml(tensor)); if (tensor->buffer != nullptr) { ggml_backend_tensor_get(tensor, result.data(), 0, ggml_nbytes(tensor)); } else { std::memcpy(result.data(), tensor->data, ggml_nbytes(tensor)); } return result; } template inline ggml_tensor* make_ggml_tensor(ggml_context* ctx, const Tensor& tensor, bool copy_data = true) { GGML_ASSERT(tensor.dim() > 0 && tensor.dim() <= 5); int n_dims = std::min(static_cast(tensor.dim()), GGML_MAX_DIMS); std::array ne = {1, 1, 1, 1}; for (int64_t i = 0; i < n_dims; ++i) { ne[static_cast(i)] = tensor.shape()[static_cast(i)]; } if (tensor.dim() == 5) { ne[3] *= tensor.shape()[4]; } ggml_tensor* result = ggml_new_tensor(ctx, GGMLTypeTraits::type, n_dims, ne.data()); if (copy_data && tensor.numel() > 0) { std::memcpy(result->data, tensor.data(), static_cast(ggml_nbytes(result))); } return result; } template inline Tensor load_tensor_from_file_as_tensor(const std::string& file_path) { std::ifstream file(file_path, std::ios::binary); if (!file.is_open()) { throw std::runtime_error("failed to open tensor file: " + file_path); } int32_t n_dims = 0; int32_t length = 0; int32_t ttype = 0; file.read(reinterpret_cast(&n_dims), sizeof(n_dims)); file.read(reinterpret_cast(&length), sizeof(length)); file.read(reinterpret_cast(&ttype), sizeof(ttype)); if (!file.good()) { throw std::runtime_error("incomplete tensor file header: " + file_path); } if (static_cast(ttype) != GGMLTypeTraits::type) { throw std::invalid_argument("tensor file type does not match requested sd::Tensor type"); } std::vector shape(n_dims, 1); for (int i = 0; i < n_dims; ++i) { int32_t dim = 1; file.read(reinterpret_cast(&dim), sizeof(dim)); shape[static_cast(i)] = dim; } std::string name(static_cast(length), '\0'); file.read(name.data(), length); shape.resize(static_cast(n_dims)); Tensor tensor(shape); file.read(reinterpret_cast(tensor.data()), static_cast(tensor.numel() * sizeof(T))); if (!file.good()) { throw std::runtime_error("incomplete tensor file data: " + file_path); } return tensor; } } // namespace sd #endif