gpu_darwin.go 2.0 KB

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