Skip to content

Commit 0eb2615

Browse files
committed
fix(ggml): preload bundled OpenMP runtime before loading ggml-base
- Preload the packaged libomp140.x86_64.dll on Windows before initializing ggml-base to ensure CPU backend DLLs can resolve their OpenMP runtime dependency. - This only applies to Windows builds with llama-cpp-python >= 0.3.39 and uses the bundled runtime from the package lib directory, avoiding the need for users to configure system PATH or install additional OpenMP runtimes. Signed-off-by: JamePeng <jame_peng@sina.com>
1 parent 79b8b5d commit 0eb2615

2 files changed

Lines changed: 45 additions & 2 deletions

File tree

llama_cpp/_ctypes_extensions.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import ctypes
66
import functools
77
import pathlib
8+
import importlib.metadata
89
from ctypes.util import find_library
910
from typing import (
1011
Any,
@@ -19,6 +20,15 @@
1920
)
2021
from typing_extensions import TypeAlias
2122

23+
def _version_at_least(version: str) -> bool:
24+
"""Check whether installed llama-cpp-python version meets requirement."""
25+
try:
26+
current = importlib.metadata.version("llama-cpp-python")
27+
from packaging.version import Version
28+
return Version(current) >= Version(version)
29+
except Exception:
30+
return False
31+
2232
def _format_library_dir_contents(base_paths: list[pathlib.Path]) -> str:
2333
"""Format directory contents for diagnostics after library loading fails."""
2434
sections = []

llama_cpp/_ggml.py

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@
66
import enum
77
import os
88
import pathlib
9-
109
from llama_cpp._ctypes_extensions import (
10+
_version_at_least,
1111
load_shared_library,
12-
byref,
1312
ctypes_function_for_shared_library,
1413
)
1514

@@ -21,12 +20,46 @@
2120
TYPE_CHECKING,
2221
)
2322

23+
def _preload_openmp_runtime():
24+
"""Preload bundled OpenMP runtime before loading ggml-base.
25+
26+
This is required on Windows when CPU backends depend on the packaged
27+
OpenMP runtime DLL.
28+
"""
29+
30+
# Only Windows DLL loading requires this workaround.
31+
if os.name != "nt":
32+
return
33+
34+
# Keep compatibility with older package versions.
35+
if not _version_at_least("0.3.39"):
36+
return
37+
38+
libomp_path = (pathlib.Path(__file__).parent / "lib" / "libomp140.x86_64.dll")
39+
40+
if not libomp_path.exists():
41+
print(f"[llama-cpp-python] WARNING: bundled OpenMP runtime not found: {libomp_path}")
42+
return
43+
44+
try:
45+
ctypes.CDLL(str(libomp_path), winmode=ctypes.RTLD_GLOBAL)
46+
print(f"[llama-cpp-python] loaded bundled OpenMP runtime: {libomp_path}")
47+
except Exception as e:
48+
print(
49+
"[llama-cpp-python] WARNING: failed to load bundled OpenMP runtime:\n"
50+
f" path: {libomp_path}\n"
51+
f" error: {e}"
52+
)
53+
2454
libggml_base_path = pathlib.Path(os.path.abspath(os.path.dirname(__file__)))
2555
libggml_base_paths = [
2656
libggml_base_path / "lib",
2757
libggml_base_path / "bin",
2858
]
2959

60+
# Load bundled OpenMP runtime before ggml-base on Windows.
61+
_preload_openmp_runtime()
62+
3063
libggml_base = load_shared_library("ggml-base", libggml_base_paths)
3164

3265
ggml_base_function = ctypes_function_for_shared_library(libggml_base)

0 commit comments

Comments
 (0)