gpu_darwin.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. //go:build darwin
  2. package discover
  3. /*
  4. #cgo CFLAGS: -x objective-c
  5. #cgo LDFLAGS: -framework Foundation -framework CoreGraphics -framework Metal
  6. #include "gpu_info_darwin.h"
  7. */
  8. import "C"
  9. import (
  10. "log/slog"
  11. "runtime"
  12. "syscall"
  13. "github.com/ollama/ollama/format"
  14. "github.com/ollama/ollama/runners"
  15. )
  16. const (
  17. metalMinimumMemory = 512 * format.MebiByte
  18. )
  19. func GetGPUInfo() GpuInfoList {
  20. mem, _ := GetCPUMem()
  21. if runtime.GOARCH == "amd64" {
  22. return []GpuInfo{
  23. {
  24. Library: "cpu",
  25. Variant: runners.GetCPUCapability().String(),
  26. memInfo: mem,
  27. },
  28. }
  29. }
  30. info := GpuInfo{
  31. Library: "metal",
  32. ID: "0",
  33. }
  34. info.TotalMemory = uint64(C.getRecommendedMaxVRAM())
  35. // TODO is there a way to gather actual allocated video memory? (currentAllocatedSize doesn't work)
  36. info.FreeMemory = info.TotalMemory
  37. info.MinimumMemory = metalMinimumMemory
  38. return []GpuInfo{info}
  39. }
  40. func GetCPUInfo() GpuInfoList {
  41. mem, _ := GetCPUMem()
  42. return []GpuInfo{
  43. {
  44. Library: "cpu",
  45. Variant: runners.GetCPUCapability().String(),
  46. memInfo: mem,
  47. },
  48. }
  49. }
  50. func GetCPUMem() (memInfo, error) {
  51. return memInfo{
  52. TotalMemory: uint64(C.getPhysicalMemory()),
  53. FreeMemory: uint64(C.getFreeMemory()),
  54. // FreeSwap omitted as Darwin uses dynamic paging
  55. }, nil
  56. }
  57. func (l GpuInfoList) GetVisibleDevicesEnv() (string, string) {
  58. // No-op on darwin
  59. return "", ""
  60. }
  61. func GetSystemInfo() SystemInfo {
  62. mem, _ := GetCPUMem()
  63. query := "hw.perflevel0.physicalcpu"
  64. perfCores, err := syscall.SysctlUint32(query)
  65. if err != nil {
  66. slog.Warn("failed to discover physical CPU details", "query", query, "error", err)
  67. }
  68. query = "hw.perflevel1.physicalcpu"
  69. efficiencyCores, _ := syscall.SysctlUint32(query) // On x86 xeon this wont return data
  70. // Determine thread count
  71. query = "hw.logicalcpu"
  72. logicalCores, _ := syscall.SysctlUint32(query)
  73. return SystemInfo{
  74. System: CPUInfo{
  75. GpuInfo: GpuInfo{
  76. memInfo: mem,
  77. },
  78. CPUs: []CPU{
  79. {
  80. CoreCount: int(perfCores + efficiencyCores),
  81. EfficiencyCoreCount: int(efficiencyCores),
  82. ThreadCount: int(logicalCores),
  83. },
  84. },
  85. },
  86. GPUs: GetGPUInfo(),
  87. }
  88. }