Packages
snakepit
0.8.3
0.13.0
0.12.0
0.11.1
0.11.0
0.10.1
0.10.0
0.9.1
0.9.0
0.8.9
0.8.8
0.8.7
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.11
0.6.10
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.1
0.5.0
0.4.3
0.4.2
0.4.1
0.4.0
0.3.3
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.2
0.1.1
0.1.0
High-performance pooler and session manager for external language integrations. Supports Python, Node.js, Ruby, and more with gRPC streaming, session management, and production-ready process cleanup.
Current section
Files
Jump to
Current section
Files
lib/snakepit/hardware/cuda_detector.ex
defmodule Snakepit.Hardware.CUDADetector do
@moduledoc """
CUDA GPU hardware detection.
Detects NVIDIA CUDA-capable GPUs using nvidia-smi when available.
"""
@type cuda_device :: %{
id: non_neg_integer(),
name: String.t(),
memory_total_mb: non_neg_integer(),
memory_free_mb: non_neg_integer(),
compute_capability: String.t() | nil
}
@type cuda_info :: %{
version: String.t(),
driver_version: String.t(),
devices: [cuda_device()],
cudnn_version: String.t() | nil
}
@doc """
Detects CUDA GPU information.
Returns nil if CUDA is not available, or a map with:
- `:version` - CUDA runtime version (e.g., "12.1")
- `:driver_version` - NVIDIA driver version
- `:devices` - List of CUDA device maps
- `:cudnn_version` - cuDNN version if available, nil otherwise
"""
@spec detect() :: cuda_info() | nil
def detect do
with {:ok, driver_version} <- detect_driver_version(),
{:ok, cuda_version} <- detect_cuda_version(),
{:ok, devices} <- detect_devices() do
%{
version: cuda_version,
driver_version: driver_version,
devices: devices,
cudnn_version: detect_cudnn_version()
}
else
_ -> nil
end
end
@spec detect_driver_version() :: {:ok, String.t()} | :error
defp detect_driver_version do
case run_nvidia_smi(["--query-gpu=driver_version", "--format=csv,noheader,nounits"]) do
{:ok, output} ->
version =
output
|> String.split("\n")
|> List.first()
|> String.trim()
if version != "" do
{:ok, version}
else
:error
end
:error ->
:error
end
end
@spec detect_cuda_version() :: {:ok, String.t()} | :error
defp detect_cuda_version do
# Try nvidia-smi for CUDA version
case run_nvidia_smi(["--query-gpu=cuda_version", "--format=csv,noheader,nounits"]) do
{:ok, output} ->
version =
output
|> String.split("\n")
|> List.first()
|> String.trim()
if version != "" and version != "[N/A]" do
{:ok, version}
else
detect_cuda_version_fallback()
end
:error ->
detect_cuda_version_fallback()
end
end
defp detect_cuda_version_fallback do
# Try nvcc --version as fallback
case System.cmd("nvcc", ["--version"], stderr_to_stdout: true) do
{output, 0} ->
case Regex.run(~r/release (\d+\.\d+)/, output) do
[_, version] -> {:ok, version}
_ -> :error
end
_ ->
:error
end
rescue
_ -> :error
end
@spec detect_devices() :: {:ok, [cuda_device()]} | :error
defp detect_devices do
query = [
"--query-gpu=index,name,memory.total,memory.free,compute_cap",
"--format=csv,noheader,nounits"
]
case run_nvidia_smi(query) do
{:ok, output} ->
devices =
output
|> String.split("\n")
|> Enum.filter(&(&1 != ""))
|> Enum.map(&parse_device_line/1)
|> Enum.filter(&(&1 != nil))
{:ok, devices}
:error ->
:error
end
end
defp parse_device_line(line) do
case String.split(line, ", ") do
[id_str, name, mem_total_str, mem_free_str, compute_cap] ->
%{
id: safe_parse_integer(id_str, 0),
name: String.trim(name),
memory_total_mb: safe_parse_integer(mem_total_str, 0),
memory_free_mb: safe_parse_integer(mem_free_str, 0),
compute_capability: normalize_compute_cap(compute_cap)
}
[id_str, name, mem_total_str, mem_free_str] ->
%{
id: safe_parse_integer(id_str, 0),
name: String.trim(name),
memory_total_mb: safe_parse_integer(mem_total_str, 0),
memory_free_mb: safe_parse_integer(mem_free_str, 0),
compute_capability: nil
}
_ ->
nil
end
end
defp safe_parse_integer(str, default) do
str
|> String.trim()
|> Integer.parse()
|> case do
{n, _} -> n
:error -> default
end
end
defp normalize_compute_cap(cap) do
cap = String.trim(cap)
if cap in ["[N/A]", "N/A", ""] do
nil
else
cap
end
end
@spec detect_cudnn_version() :: String.t() | nil
defp detect_cudnn_version do
# cuDNN version is not easily detectable without Python
# Return nil for now, can be populated via Python probe
nil
end
@spec run_nvidia_smi([String.t()]) :: {:ok, String.t()} | :error
defp run_nvidia_smi(args) do
case System.cmd("nvidia-smi", args, stderr_to_stdout: true) do
{output, 0} -> {:ok, output}
_ -> :error
end
rescue
_ -> :error
end
end