#ifndef __SD_CORE_GGML_TENSOR_UTILS_H__ #define __SD_CORE_GGML_TENSOR_UTILS_H__ #include #include #include #include #include #include #include #include #include "core/tensor.hpp" #include "core/util.h" #include "ggml-backend.h" #include "ggml.h" #include "stable-diffusion.h" class RNG; __STATIC_INLINE__ int align_up_offset(int n, int multiple) { return (multiple - n % multiple) % multiple; } __STATIC_INLINE__ int align_up(int n, int multiple) { return n + align_up_offset(n, multiple); } void ggml_ext_im_set_randn_f32(ggml_tensor* tensor, std::shared_ptr rng); __STATIC_INLINE__ void ggml_ext_tensor_set_f32(ggml_tensor* tensor, float value, int64_t i0, int64_t i1 = 0, int64_t i2 = 0, int64_t i3 = 0) { GGML_ASSERT(tensor->nb[0] == sizeof(float)); *(float*)((char*)(tensor->data) + i3 * tensor->nb[3] + i2 * tensor->nb[2] + i1 * tensor->nb[1] + i0 * tensor->nb[0]) = value; } __STATIC_INLINE__ float ggml_ext_tensor_get_f32(const ggml_tensor* tensor, int64_t i0, int64_t i1 = 0, int64_t i2 = 0, int64_t i3 = 0) { if (tensor->buffer != nullptr) { float value; ggml_backend_tensor_get(tensor, &value, i3 * tensor->nb[3] + i2 * tensor->nb[2] + i1 * tensor->nb[1] + i0 * tensor->nb[0], sizeof(float)); return value; } GGML_ASSERT(tensor->nb[0] == sizeof(float)); return *(float*)((char*)(tensor->data) + i3 * tensor->nb[3] + i2 * tensor->nb[2] + i1 * tensor->nb[1] + i0 * tensor->nb[0]); } __STATIC_INLINE__ int ggml_ext_tensor_get_i32(const ggml_tensor* tensor, int64_t i0, int64_t i1 = 0, int64_t i2 = 0, int64_t i3 = 0) { if (tensor->buffer != nullptr) { int value; ggml_backend_tensor_get(tensor, &value, i3 * tensor->nb[3] + i2 * tensor->nb[2] + i1 * tensor->nb[1] + i0 * tensor->nb[0], sizeof(int)); return value; } GGML_ASSERT(tensor->nb[0] == sizeof(int)); return *(int*)((char*)(tensor->data) + i3 * tensor->nb[3] + i2 * tensor->nb[2] + i1 * tensor->nb[1] + i0 * tensor->nb[0]); } __STATIC_INLINE__ ggml_fp16_t ggml_ext_tensor_get_f16(const ggml_tensor* tensor, int64_t i0, int64_t i1 = 0, int64_t i2 = 0, int64_t i3 = 0) { GGML_ASSERT(tensor->nb[0] == sizeof(ggml_fp16_t)); return *(ggml_fp16_t*)((char*)(tensor->data) + i3 * tensor->nb[3] + i2 * tensor->nb[2] + i1 * tensor->nb[1] + i0 * tensor->nb[0]); } __STATIC_INLINE__ float sd_image_get_f32(sd_image_t image, int64_t iw, int64_t ih, int64_t ic, bool scale = true) { float value = *(image.data + ih * image.width * image.channel + iw * image.channel + ic); if (scale) { value /= 255.f; } return value; } void print_ggml_tensor(ggml_tensor* tensor, bool shape_only = false, const char* mark = ""); template __STATIC_INLINE__ void print_sd_tensor(const sd::Tensor& tensor, bool shape_only = false, const char* mark = "") { printf("%s: shape(", mark); for (size_t i = 0; i < static_cast(tensor.dim()); ++i) { printf("%s%lld", i == 0 ? "" : ", ", static_cast(tensor.shape()[i])); } printf(")\n"); fflush(stdout); if (shape_only) { return; } if (tensor.empty()) { return; } int range = 3; std::vector shape = tensor.shape(); while (shape.size() < 4) { shape.push_back(1); } for (int64_t i3 = 0; i3 < shape[3]; i3++) { if (i3 >= range && i3 + range < shape[3]) { continue; } for (int64_t i2 = 0; i2 < shape[2]; i2++) { if (i2 >= range && i2 + range < shape[2]) { continue; } for (int64_t i1 = 0; i1 < shape[1]; i1++) { if (i1 >= range && i1 + range < shape[1]) { continue; } for (int64_t i0 = 0; i0 < shape[0]; i0++) { if (i0 >= range && i0 + range < shape[0]) { continue; } size_t offset = static_cast(i0 + shape[0] * (i1 + shape[1] * (i2 + shape[2] * i3))); printf(" [%lld, %lld, %lld, %lld] = ", static_cast(i3), static_cast(i2), static_cast(i1), static_cast(i0)); if constexpr (std::is_same_v) { printf("%f\n", tensor[static_cast(offset)]); } else if constexpr (std::is_same_v) { printf("%f\n", ggml_fp16_to_fp32(tensor[static_cast(offset)])); } else if constexpr (std::is_same_v) { printf("%d\n", tensor[static_cast(offset)]); } else if constexpr (std::is_same_v) { printf("%lld\n", static_cast(tensor[static_cast(offset)])); } fflush(stdout); } } } } } void ggml_ext_tensor_iter( ggml_tensor* tensor, const std::function& fn); void ggml_ext_tensor_iter( ggml_tensor* tensor, const std::function& fn); void ggml_ext_tensor_diff( ggml_tensor* a, ggml_tensor* b, float gap = 0.1f); ggml_tensor* load_tensor_from_file(ggml_context* ctx, const std::string& file_path); __STATIC_INLINE__ float sigmoid(float x) { return 1 / (1.0f + expf(-x)); } // SPECIAL OPERATIONS WITH TENSORS uint8_t* ggml_tensor_to_sd_image(ggml_tensor* input, uint8_t* image_data = nullptr); uint8_t* ggml_tensor_to_sd_image(ggml_tensor* input, int idx, bool video = false); void sd_image_to_ggml_tensor(sd_image_t image, ggml_tensor* tensor, bool scale = true); void ggml_ext_tensor_apply_mask(ggml_tensor* image_data, ggml_tensor* mask, ggml_tensor* output, float masked_value = 0.5f); float ggml_ext_tensor_mean(ggml_tensor* src); // a = a+b void ggml_ext_tensor_add_inplace(ggml_tensor* a, ggml_tensor* b); void ggml_ext_tensor_scale_inplace(ggml_tensor* src, float scale); void ggml_ext_tensor_clamp_inplace(ggml_tensor* src, float min, float max); ggml_tensor* ggml_ext_tensor_concat(ggml_context* ctx, ggml_tensor* a, ggml_tensor* b, int dim); // convert values from [0, 1] to [-1, 1] void scale_to_minus1_1(ggml_tensor* src); // convert values from [-1, 1] to [0, 1] void scale_to_0_1(ggml_tensor* src); ggml_tensor* vector_to_ggml_tensor(ggml_context* ctx, const std::vector& vec); ggml_tensor* vector_to_ggml_tensor_i32(ggml_context* ctx, const std::vector& vec); std::vector arange(float start, float end, float step = 1.f); // Ref: https://github.com/CompVis/stable-diffusion/blob/main/ldm/modules/diffusionmodules/util.py#L151 std::vector timestep_embedding(std::vector timesteps, int dim, int max_period = 10000, bool flip_sin_to_cos = true, float scale = 1.f); void set_timestep_embedding(std::vector timesteps, ggml_tensor* embedding, int dim, int max_period = 10000); void set_timestep_embedding(std::vector timesteps, sd::Tensor* embedding, int dim, int max_period = 10000); ggml_tensor* new_timestep_embedding(ggml_context* ctx, std::vector timesteps, int dim, int max_period = 10000); size_t ggml_tensor_num(ggml_context* ctx); #endif // __SD_CORE_GGML_TENSOR_UTILS_H__