]> git.djapps.eu Git - pkg/ggml/sources/whisper.cpp/commitdiff
metal : option to embed MSL source into compiled binary (#1842)
authorDidzis Gosko <redacted>
Sun, 11 Feb 2024 14:41:41 +0000 (16:41 +0200)
committerGitHub <redacted>
Sun, 11 Feb 2024 14:41:41 +0000 (16:41 +0200)
* ggml : embed Metal library source (ggml-metal.metal) into binary

enable by setting WHISPER_EMBED_METAL_LIBRARY

* rename the build option

* rename the preprocessor directive

* generate Metal library embedding assembly on-fly during build process

CMakeLists.txt
Makefile
ggml-metal.m

index 4c620f512063fff8d3d799ebb454544d8e342174..7b7c6a850388de57c89e4163dd70d7cd4ef02a7a 100644 (file)
@@ -68,6 +68,7 @@ if (APPLE)
     option(WHISPER_METAL_NDEBUG          "whisper: disable Metal debugging"      OFF)
     option(WHISPER_COREML                "whisper: enable Core ML framework"     OFF)
     option(WHISPER_COREML_ALLOW_FALLBACK "whisper: allow non-CoreML fallback"    OFF)
+    option(WHISPER_METAL_EMBED_LIBRARY   "whisper: embed Metal library"          OFF)
 else()
     option(WHISPER_BLAS                  "whisper: use BLAS libraries"  OFF)
     option(WHISPER_BLAS_VENDOR           "whisper: BLAS library vendor" Generic)
@@ -147,6 +148,30 @@ if (APPLE)
 
         # copy ggml-metal.metal to bin directory
         configure_file(ggml-metal.metal bin/ggml-metal.metal COPYONLY)
+
+        if (WHISPER_METAL_EMBED_LIBRARY)
+            enable_language(ASM)
+            set(WHISPER_EXTRA_FLAGS ${WHISPER_EXTRA_FLAGS} -DGGML_METAL_EMBED_LIBRARY)
+
+            set(METALLIB_SOURCE "${CMAKE_SOURCE_DIR}/ggml-metal.metal")
+
+            file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/autogenerated")
+            set(EMBED_METALLIB_ASSEMBLY "${CMAKE_BINARY_DIR}/autogenerated/ggml-embed-metallib.s")
+
+            add_custom_command(
+                OUTPUT ${EMBED_METALLIB_ASSEMBLY}
+                COMMAND echo ".section __DATA,__ggml_metallib" > ${EMBED_METALLIB_ASSEMBLY}
+                COMMAND echo ".globl _ggml_metallib_start" >> ${EMBED_METALLIB_ASSEMBLY}
+                COMMAND echo "_ggml_metallib_start:" >> ${EMBED_METALLIB_ASSEMBLY}
+                COMMAND echo ".incbin \\\"${METALLIB_SOURCE}\\\"" >> ${EMBED_METALLIB_ASSEMBLY}
+                COMMAND echo ".globl _ggml_metallib_end" >> ${EMBED_METALLIB_ASSEMBLY}
+                COMMAND echo "_ggml_metallib_end:" >> ${EMBED_METALLIB_ASSEMBLY}
+                DEPENDS ${METALLIB_SOURCE}
+                COMMENT "Generate assembly for embedded Metal library"
+            )
+
+            set(GGML_SOURCES_METAL ${GGML_SOURCES_METAL} ${EMBED_METALLIB_ASSEMBLY})
+        endif()
     endif()
 
     if (WHISPER_COREML)
index 4a676f1ff6b330dbb472bf95ce02bc7060b4f417..382568786c3b38fdc4c2959cff8e8d4f0ae46e07 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -345,6 +345,24 @@ ggml-metal.o: ggml-metal.m ggml-metal.h
        $(CC) $(CFLAGS) -c $< -o $@
 
 WHISPER_OBJ += ggml-metal.o
+
+ifdef WHISPER_METAL_EMBED_LIBRARY
+CFLAGS += -DGGML_METAL_EMBED_LIBRARY
+
+ggml-metal-embed.o: ggml-metal.metal
+       @echo "Embedding Metal library"
+       $(eval TEMP_ASSEMBLY=$(shell mktemp))
+       @echo ".section __DATA, __ggml_metallib" > $(TEMP_ASSEMBLY)
+       @echo ".globl _ggml_metallib_start" >> $(TEMP_ASSEMBLY)
+       @echo "_ggml_metallib_start:" >> $(TEMP_ASSEMBLY)
+       @echo ".incbin \"$<\"" >> $(TEMP_ASSEMBLY)
+       @echo ".globl _ggml_metallib_end" >> $(TEMP_ASSEMBLY)
+       @echo "_ggml_metallib_end:" >> $(TEMP_ASSEMBLY)
+       @$(AS) $(TEMP_ASSEMBLY) -o $@
+       @rm -f ${TEMP_ASSEMBLY}
+
+WHISPER_OBJ += ggml-metal-embed.o
+endif
 endif
 
 libwhisper.a: $(WHISPER_OBJ)
index 5260ed827702694d22c569274812c8377475cbf8..6027ca64734f431cfc40dc7e3a71bb5576a87c80 100644 (file)
@@ -272,6 +272,14 @@ static struct ggml_metal_context * ggml_metal_init(int n_cb) {
                 return NULL;
             }
         } else {
+#if GGML_METAL_EMBED_LIBRARY
+            GGML_METAL_LOG_INFO("%s: using embedded metal library\n", __func__);
+
+            extern const char ggml_metallib_start[];
+            extern const char ggml_metallib_end[];
+
+            NSString * src  = [[NSString alloc] initWithBytes:ggml_metallib_start length:(ggml_metallib_end-ggml_metallib_start) encoding:NSUTF8StringEncoding];
+#else
             GGML_METAL_LOG_INFO("%s: default.metallib not found, loading from source\n", __func__);
 
             NSString * sourcePath;
@@ -294,6 +302,7 @@ static struct ggml_metal_context * ggml_metal_init(int n_cb) {
                 GGML_METAL_LOG_ERROR("%s: error: %s\n", __func__, [[error description] UTF8String]);
                 return NULL;
             }
+#endif
 
             @autoreleasepool {
                 // dictionary of preprocessor macros