Module: Ignis::CUDA::LibraryLoader

Defined in:
lib/nvruby/cuda/library_loader.rb

Overview

Handles dynamic loading of NVIDIA CUDA libraries. Cross-platform: Windows (DLLs via Kernel32) and Linux (.so via dlopen). Uses Ignis::Platform for path resolution when available.

Defined Under Namespace

Modules: Kernel32

Constant Summary collapse

WIN_LIB_PATTERNS =

Fallback patterns if Platform module not loaded

{
  cuda_runtime: 'cudart64_*.dll',
  cublas: 'cublas64_*.dll',
  cublaslt: 'cublasLt64_*.dll',
  cufft: 'cufft64_*.dll',
  curand: 'curand64_*.dll',
  cusparse: 'cusparse64_*.dll',
  cusolver: 'cusolver64_*.dll',
  cudnn: 'cudnn64_*.dll',
  nvrtc: 'nvrtc64_*.dll',
  cutensor: 'cutensor.dll',
  cudss: 'cudss64_*.dll',
  mathdx: 'mathdx64_0.dll',
  cuda_driver: 'nvcuda.dll'
}.freeze
LINUX_LIB_PATTERNS =
{
  cuda_runtime: 'libcudart.so*',
  cublas: 'libcublas.so*',
  cublaslt: 'libcublasLt.so*',
  cufft: 'libcufft.so*',
  curand: 'libcurand.so*',
  cusparse: 'libcusparse.so*',
  cusolver: 'libcusolver.so*',
  cudnn: 'libcudnn.so*',
  nvrtc: 'libnvrtc.so*',
  cutensor: 'libcutensor.so*',
  cudss: 'libcudss.so*',
  mathdx: 'libmathdx.so*',
  cuda_driver: 'libcuda.so*'
}.freeze

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.fiddle_handlesHash{Symbol => Fiddle::Handle} (readonly)

Returns:

  • (Hash{Symbol => Fiddle::Handle})


101
102
103
# File 'lib/nvruby/cuda/library_loader.rb', line 101

def fiddle_handles
  @fiddle_handles
end

.library_pathsHash{Symbol => String} (readonly)

Returns:

  • (Hash{Symbol => String})


98
99
100
# File 'lib/nvruby/cuda/library_loader.rb', line 98

def library_paths
  @library_paths
end

Class Method Details

.cuda_versionString

Returns e.g. “13.0”.

Returns:

  • (String)

    e.g. “13.0”

Raises:



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/nvruby/cuda/library_loader.rb', line 162

def cuda_version
  ensure_cuda_runtime!
  handle = @fiddle_handles[:cuda_runtime]

  fn = Fiddle::Function.new(
    handle['cudaRuntimeGetVersion'],
    [Fiddle::TYPE_VOIDP],
    Fiddle::TYPE_INT
  )

  version_ptr = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT)
  result = fn.call(version_ptr)
  raise CudaRuntimeError.new('Failed to get CUDA version', cuda_code: result) unless result.zero?

  version = version_ptr[0, Fiddle::SIZEOF_INT].unpack1('l')
  major = version / 1000
  minor = (version % 1000) / 10

  "#{major}.#{minor}"
end

.custom_pathsObject

Custom search paths for additional CUDA libraries



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/nvruby/cuda/library_loader.rb', line 74

def self.custom_paths
  if defined?(Ignis::Platform)
    Ignis::Platform.custom_lib_paths
  elsif windows?
    {
      cutensor: 'C:/Program Files/NVIDIA cuTENSOR/v2.4/bin/13',
      cudss: 'C:/Program Files/NVIDIA cuDSS/v0.7/bin/13'
    }
  else
    {
      cutensor: '/usr/local/cutensor/lib',
      cudss: '/usr/local/cudss/lib'
    }
  end
end

.ensure_cuda_runtime!Fiddle::Handle

Returns:

  • (Fiddle::Handle)


151
152
153
# File 'lib/nvruby/cuda/library_loader.rb', line 151

def ensure_cuda_runtime!
  load_library(:cuda_runtime)
end

.handle_for(library) ⇒ Fiddle::Handle?

Parameters:

  • library (Symbol)

Returns:

  • (Fiddle::Handle, nil)


157
158
159
# File 'lib/nvruby/cuda/library_loader.rb', line 157

def handle_for(library)
  @mutex.synchronize { @fiddle_handles[library] }
end

.lib_patternsHash{Symbol => String}

Library names and their patterns — resolved per platform.

Returns:

  • (Hash{Symbol => String})


26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/nvruby/cuda/library_loader.rb', line 26

def self.lib_patterns
  if defined?(Ignis::Platform)
    platform_patterns = {}
    (Ignis::Platform.windows? ? Ignis::Platform::WIN_LIB_PATTERNS : Ignis::Platform::LINUX_LIB_PATTERNS).each do |k, v|
      platform_patterns[k] = v
    end
    platform_patterns
  elsif RUBY_PLATFORM.match?(/mswin|mingw|cygwin/i)
    WIN_LIB_PATTERNS
  else
    LINUX_LIB_PATTERNS
  end
end

.load_all(libraries: %i[cuda_runtime cublas cufft curand])) ⇒ Hash{Symbol => Fiddle::Handle}

Load all required CUDA libraries.

Parameters:

  • libraries (Array<Symbol>) (defaults to: %i[cuda_runtime cublas cufft curand]))

Returns:

  • (Hash{Symbol => Fiddle::Handle})


142
143
144
145
146
147
148
# File 'lib/nvruby/cuda/library_loader.rb', line 142

def load_all(libraries: %i[cuda_runtime cublas cufft curand])
  libraries.each_with_object({}) do |lib, result|
    result[lib] = load_library(lib)
  rescue LibraryNotFoundError => e
    $stderr.puts "[LibraryLoader] Optional library not found: #{e.message}"
  end
end

.load_library(library) ⇒ Fiddle::Handle

Load a specific CUDA library via Fiddle::Handle.

Parameters:

  • library (Symbol)

Returns:

  • (Fiddle::Handle)


117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/nvruby/cuda/library_loader.rb', line 117

def load_library(library)
  @mutex.synchronize do
    return @fiddle_handles[library] if @fiddle_handles[library]

    ensure_dll_search_path! if windows?

    patterns = lib_patterns
    pattern = patterns[library]
    raise ArgumentError, "Unknown library: #{library}" unless pattern

    dll_path = find_library(library, pattern)
    raise LibraryNotFoundError, library.to_s unless dll_path

    handle = Fiddle::Handle.new(dll_path)
    @fiddle_handles[library] = handle
    @library_paths[library] = dll_path

    $stderr.puts "[LibraryLoader] Loaded #{library}: #{dll_path}"
    handle
  end
end

.loaded?(library) ⇒ Boolean

Parameters:

  • library (Symbol)

Returns:

  • (Boolean)


110
111
112
# File 'lib/nvruby/cuda/library_loader.rb', line 110

def loaded?(library)
  @mutex.synchronize { @fiddle_handles.key?(library) }
end

.loaded_librariesHash{Symbol => String}

Returns:

  • (Hash{Symbol => String})


104
105
106
# File 'lib/nvruby/cuda/library_loader.rb', line 104

def loaded_libraries
  @mutex.synchronize { @library_paths.dup }
end

.reset!void

This method returns an undefined value.



184
185
186
187
188
189
190
# File 'lib/nvruby/cuda/library_loader.rb', line 184

def reset!
  @mutex.synchronize do
    @fiddle_handles.clear
    @loaded_libraries.clear
    @library_paths.clear
  end
end

.windows?Boolean

Returns:

  • (Boolean)


193
194
195
196
197
198
199
# File 'lib/nvruby/cuda/library_loader.rb', line 193

def windows?
  if defined?(Ignis::Platform)
    Ignis::Platform.windows?
  else
    RUBY_PLATFORM.match?(/mswin|mingw|cygwin/i)
  end
end