Removed libcap related code

libcap is not directly related to Vulkan and should be added by its own PR. It adds additional library dependencies for building and also requires users to run setcap or run ollama as root, which is not ideal for easy use
This commit is contained in:
Masato Nakasaka 2025-08-27 11:51:53 +09:00
parent 834a66689e
commit af5f5bdf60
5 changed files with 34 additions and 134 deletions

View File

@ -20,7 +20,7 @@ ENV PATH=/opt/rh/gcc-toolset-10/root/usr/bin:$PATH
ARG VULKANVERSION
RUN wget https://sdk.lunarg.com/sdk/download/${VULKANVERSION}/linux/vulkansdk-linux-x86_64-${VULKANVERSION}.tar.xz -O /tmp/vulkansdk-linux-x86_64-${VULKANVERSION}.tar.xz \
&& tar xvf /tmp/vulkansdk-linux-x86_64-${VULKANVERSION}.tar.xz \
&& dnf -y install ninja-build libcap-devel \
&& dnf -y install ninja-build \
&& ln -s /usr/bin/python3 /usr/bin/python \
&& /${VULKANVERSION}/vulkansdk -j 8 vulkan-headers \
&& /${VULKANVERSION}/vulkansdk -j 8 shaderc
@ -126,7 +126,7 @@ COPY --from=build /bin/ollama /bin/ollama
FROM ubuntu:24.04
RUN apt-get update \
&& apt-get install -y ca-certificates libcap2 libvulkan1 \
&& apt-get install -y ca-certificates libvulkan1 \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
COPY --from=archive /bin /usr/bin

View File

@ -57,7 +57,6 @@ var (
cudartLibPath string
oneapiLibPath string
vulkanLibPath string
libcapLibPath string
nvmlLibPath string
rocmGPUs []RocmGPUInfo
oneapiGPUs []OneapiGPUInfo
@ -187,19 +186,18 @@ func initVulkanHandles() *vulkanHandles {
vHandles := &vulkanHandles{}
// Short Circuit if we already know which library to use
if vulkanLibPath != "" && libcapLibPath != "" {
vHandles.deviceCount, vHandles.vulkan, _, _ = LoadVulkanMgmt([]string{vulkanLibPath}, []string{libcapLibPath})
if vulkanLibPath != "" {
vHandles.deviceCount, vHandles.vulkan, _ = LoadVulkanMgmt([]string{vulkanLibPath})
return vHandles
}
vulkanPaths := FindGPULibs(VulkanMgmtName, VulkanGlobs)
libcapPaths := FindLibCapLibs()
if len(vulkanPaths) > 0 && len(libcapPaths) > 0 {
slog.Info("vulkan: load libvulkan and libcap ok")
vHandles.deviceCount, vHandles.vulkan, vulkanLibPath, libcapLibPath = LoadVulkanMgmt(vulkanPaths, libcapPaths)
if len(vulkanPaths) > 0 {
slog.Info("vulkan: load libvulkan ok")
vHandles.deviceCount, vHandles.vulkan, vulkanLibPath = LoadVulkanMgmt(vulkanPaths)
} else {
slog.Info("vulkan: failed to load libvulkan or libcap")
slog.Info("vulkan: failed to load libvulkan")
}
return vHandles
@ -760,32 +758,27 @@ func loadOneapiMgmt(oneapiLibPaths []string) (int, *C.oneapi_handle_t, string, e
return 0, nil, "", err
}
func LoadVulkanMgmt(vulkanLibPaths []string, capLibPaths []string) (int, *C.vk_handle_t, string, string) {
func LoadVulkanMgmt(vulkanLibPaths []string) (int, *C.vk_handle_t, string) {
var resp C.vk_init_resp_t
resp.ch.verbose = getVerboseState()
for _, vkLibPath := range vulkanLibPaths {
for _, capLibPath := range capLibPaths {
vkLib := C.CString(vkLibPath)
capLib := C.CString(capLibPath)
defer C.free(unsafe.Pointer(vkLib))
defer C.free(unsafe.Pointer(capLib))
vkLib := C.CString(vkLibPath)
defer C.free(unsafe.Pointer(vkLib))
C.vk_init(vkLib, capLib, &resp)
if resp.err != nil {
slog.Error(
"Unable to load vulkan",
"vulkan_library", vkLibPath,
"cap_library", capLibPath,
"error", C.GoString(resp.err),
)
C.free(unsafe.Pointer(resp.err))
} else {
return int(resp.num_devices), &resp.ch, vkLibPath, capLibPath
}
C.vk_init(vkLib, &resp)
if resp.err != nil {
slog.Error(
"Unable to load vulkan",
"vulkan_library", vkLibPath,
"error", C.GoString(resp.err),
)
C.free(unsafe.Pointer(resp.err))
} else {
return int(resp.num_devices), &resp.ch, vkLibPath
}
}
return 0, nil, "", ""
return 0, nil, ""
}
func getVerboseState() C.uint16_t {

View File

@ -2,28 +2,6 @@
#include <string.h>
int check_perfmon(vk_handle_t* rh) {
#ifdef __linux__
cap_t caps;
const cap_value_t cap_list[1] = {CAP_PERFMON};
caps = (*rh->cap_get_proc)();
if (caps == NULL)
return -1;
if ((*rh->cap_set_flag)(caps, CAP_EFFECTIVE, 1, cap_list, CAP_SET) == -1)
return -1;
if ((*rh->cap_set_proc)(caps) == -1)
return -1;
if ((*rh->cap_free)(caps) == -1)
return -1;
#endif
return 0;
}
int is_extension_supported(vk_handle_t* rh, VkPhysicalDevice device, char* extension) {
VkPhysicalDeviceProperties properties;
(*rh->vkGetPhysicalDeviceProperties)(device, &properties);
@ -53,30 +31,22 @@ int is_extension_supported(vk_handle_t* rh, VkPhysicalDevice device, char* exten
return 0;
}
void vk_init(char* vk_lib_path, char* cap_lib_path, vk_init_resp_t *resp) {
void vk_init(char* vk_lib_path, vk_init_resp_t *resp) {
const int buflen = 256;
char buf[buflen + 1];
int i;
struct lookup {
int is_cap;
char *s;
void **p;
} l[] = {
#ifdef __linux__
{1, "cap_get_proc", (void *)&resp->ch.cap_get_proc},
{1, "cap_get_bound", (void *)&resp->ch.cap_get_bound},
{1, "cap_set_flag", (void *)&resp->ch.cap_set_flag},
{1, "cap_set_proc", (void *)&resp->ch.cap_set_proc},
{1, "cap_free", (void *)&resp->ch.cap_free},
#endif
{0, "vkGetPhysicalDeviceProperties", (void *)&resp->ch.vkGetPhysicalDeviceProperties},
{0, "vkEnumerateDeviceExtensionProperties", (void *)&resp->ch.vkEnumerateDeviceExtensionProperties},
{0, "vkCreateInstance", (void *)&resp->ch.vkCreateInstance},
{0, "vkEnumeratePhysicalDevices", (void *)&resp->ch.vkEnumeratePhysicalDevices},
{0, "vkGetPhysicalDeviceMemoryProperties2", (void *)&resp->ch.vkGetPhysicalDeviceMemoryProperties2},
{0, "vkDestroyInstance", (void *)&resp->ch.vkDestroyInstance},
{0, NULL, NULL},
{"vkGetPhysicalDeviceProperties", (void *)&resp->ch.vkGetPhysicalDeviceProperties},
{"vkEnumerateDeviceExtensionProperties", (void *)&resp->ch.vkEnumerateDeviceExtensionProperties},
{"vkCreateInstance", (void *)&resp->ch.vkCreateInstance},
{"vkEnumeratePhysicalDevices", (void *)&resp->ch.vkEnumeratePhysicalDevices},
{"vkGetPhysicalDeviceMemoryProperties2", (void *)&resp->ch.vkGetPhysicalDeviceMemoryProperties2},
{"vkDestroyInstance", (void *)&resp->ch.vkDestroyInstance},
{NULL, NULL},
};
resp->ch.vk_handle = LOAD_LIBRARY(vk_lib_path, RTLD_LAZY);
@ -91,39 +61,13 @@ void vk_init(char* vk_lib_path, char* cap_lib_path, vk_init_resp_t *resp) {
return;
}
#ifdef __linux__
resp->ch.cap_handle = LOAD_LIBRARY(cap_lib_path, RTLD_LAZY);
if (!resp->ch.cap_handle) {
char *msg = LOAD_ERR();
LOG(resp->ch.verbose, "library %s load err: %s\n", cap_lib_path, msg);
snprintf(buf, buflen,
"Unable to load %s library to query for Vulkan GPUs: %s",
cap_lib_path, msg);
free(msg);
resp->err = strdup(buf);
return;
}
#endif
for (i = 0; l[i].s != NULL; i++) {
if (l[i].is_cap)
#ifdef __linux__
*l[i].p = LOAD_SYMBOL(resp->ch.cap_handle, l[i].s);
#else
continue;
#endif
else
*l[i].p = LOAD_SYMBOL(resp->ch.vk_handle, l[i].s);
*l[i].p = LOAD_SYMBOL(resp->ch.vk_handle, l[i].s);
if (!*l[i].p) {
char *msg = LOAD_ERR();
LOG(resp->ch.verbose, "dlerr: %s\n", msg);
if (l[i].is_cap) {
UNLOAD_LIBRARY(resp->ch.cap_handle);
resp->ch.cap_handle = NULL;
} else {
UNLOAD_LIBRARY(resp->ch.vk_handle);
resp->ch.vk_handle = NULL;
}
UNLOAD_LIBRARY(resp->ch.vk_handle);
resp->ch.vk_handle = NULL;
snprintf(buf, buflen, "symbol lookup for %s failed: %s", l[i].s,
msg);
free(msg);
@ -132,12 +76,6 @@ void vk_init(char* vk_lib_path, char* cap_lib_path, vk_init_resp_t *resp) {
}
}
if (check_perfmon(&resp->ch) != 0) {
resp->err = strdup("performance monitoring is not allowed. Please enable CAP_PERFMON or run as root to use Vulkan.");
LOG(resp->ch.verbose, "vulkan: %s", resp->err);
return;
}
VkInstance instance;
VkApplicationInfo appInfo = {};
@ -277,10 +215,4 @@ void vk_release(vk_handle_t rh) {
(*rh.vkDestroyInstance)(rh.vk, NULL);
UNLOAD_LIBRARY(rh.vk_handle);
rh.vk_handle = NULL;
#ifdef __linux__
LOG(rh.verbose, "releasing libcap library\n");
UNLOAD_LIBRARY(rh.cap_handle);
rh.cap_handle = NULL;
#endif
}

View File

@ -4,29 +4,15 @@
#include "gpu_info.h"
#ifdef __linux__
#include <sys/capability.h>
#endif
#include <vulkan/vulkan.h>
typedef struct {
void* vk_handle;
void* cap_handle;
uint16_t verbose;
VkInstance vk;
int num_devices;
#ifdef __linux__
cap_t (*cap_get_proc)(void);
int (*cap_get_bound)(cap_value_t);
int (*cap_set_flag)(cap_t, cap_flag_t, int, const cap_value_t *, cap_flag_value_t);
int (*cap_set_proc)(cap_t);
int (*cap_free)(cap_t);
#endif
void (*vkGetPhysicalDeviceProperties)(
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceProperties* pProperties);
@ -58,7 +44,7 @@ typedef struct vk_init_resp
vk_handle_t ch;
} vk_init_resp_t;
void vk_init(char* vk_lib_path, char* cap_lib_path, vk_init_resp_t *resp);
void vk_init(char* vk_lib_path, vk_init_resp_t *resp);
void vk_check_vram(vk_handle_t rh, int i, mem_info_t *resp);
int vk_check_flash_attention(vk_handle_t rh, int i);
void vk_release(vk_handle_t rh);

View File

@ -53,7 +53,6 @@ var (
NvmlMgmtName = "" // not currently wired on linux
OneapiMgmtName = "libze_intel_gpu.so*"
VulkanMgmtName = "libvulkan.so*"
libcapMgmtName = "libcap.so*"
)
var VulkanGlobs = []string{
@ -62,16 +61,6 @@ var VulkanGlobs = []string{
"/usr/lib*/libvulkan.so*",
}
var capLinuxGlobs = []string{
"/usr/lib/x86_64-linux-gnu/libcap.so*",
"/usr/lib/aarch64-linux-gnu/libvulkan.so*",
"/usr/lib*/libcap.so*",
}
func FindLibCapLibs() []string {
return FindGPULibs(libcapMgmtName, capLinuxGlobs)
}
func GetCPUMem() (memInfo, error) {
var mem memInfo
var total, available, free, buffers, cached, freeSwap uint64