torch-ddp 0.2.0 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c04c1f358a671d251826b7bf9db798bd5d9f11e279b639cff382f9f8f07d4b5f
4
- data.tar.gz: 14c9db6913aaf75f98242f06808db8a3b696f37e6d779e092c8ed59cd398a644
3
+ metadata.gz: 01c3dafea6b9ee6b691d59448137a325d54bd794c4004ac6cf519ac6d2961bc3
4
+ data.tar.gz: fbb84030108e52d0f54ce67ac43bb07ab1608d3878c8988bfcf91073e9e3f292
5
5
  SHA512:
6
- metadata.gz: 0c62affe04041abca2dc56d6e82cc511d0338c3a4460c076b2fde13f219b889903b376521c92a38a6df0f0447bbd058081075ec1fcd6d3fcfb914063a0338691
7
- data.tar.gz: 11634e1c29274033be29c37f51eae9bcc62bab902afedb469bdfde39e74f9d9230a93295a1c0b5fb2ee8e303af0df20e659335ee5e21c3c9e6b89608c9600dde
6
+ metadata.gz: f378128687e1c9db4deb53d01b5e10918d76456f586f1d9c35cca9ccdd3ac0f3effebf98724ad52d64c1ee38a4019e2996057791ddcc0cb6232e99a3263dc893
7
+ data.tar.gz: 2f028ae611ba90f2f664dbca9b37168f725d5bbe6743c2bd633e40e6d53e9083264e51407bb1365a699b17336a24454995866a492e01e16fb8a96cac0d89ce25
@@ -13,7 +13,7 @@ require "torchvision"
13
13
  DEFAULT_BACKEND = if Torch.const_defined?(:CUDA) && Torch::CUDA.respond_to?(:available?) && Torch::CUDA.available?
14
14
  "nccl"
15
15
  else
16
- Torch::Distributed.get_default_backend_for_device(Torch::Accelerator.current_accelerator) || "gloo"
16
+ Torch::Distributed.get_default_backend_for_device(nil) || "gloo"
17
17
  end
18
18
  SPAWN_BACKEND_ENV = "TORCH_RB_BENCH_BACKEND".freeze
19
19
  SPAWN_GROUP_ENV = "TORCH_RB_BENCH_GROUP_SIZE".freeze
@@ -181,8 +181,7 @@ def benchmark_worker(rank, world_size, port, options)
181
181
  raise ArgumentError, "Unsupported architecture #{arch.inspect}" unless config
182
182
 
183
183
  distributed = world_size > 1
184
- accelerator = Torch::Accelerator.current_accelerator
185
- selected_backend = options[:backend] || Torch::Distributed.get_default_backend_for_device(accelerator) || DEFAULT_BACKEND
184
+ selected_backend = options[:backend] || Torch::Distributed.get_default_backend_for_device(nil) || DEFAULT_BACKEND
186
185
  if distributed
187
186
  store = Torch::Distributed::TCPStore.new("127.0.0.1", port, world_size, rank.zero?)
188
187
  Torch::Distributed.init_process_group(selected_backend, store: store, rank: rank, world_size: world_size)
@@ -350,7 +349,7 @@ results = []
350
349
 
351
350
  backends.each do |backend|
352
351
  unless backend_supported?(backend)
353
- warn "Skipping backend=#{backend} because required accelerator support is unavailable."
352
+ warn "Skipping backend=#{backend} because required CUDA support is unavailable."
354
353
  next
355
354
  end
356
355
 
@@ -17,7 +17,7 @@ DEFAULT_CHECKPOINT_PATH = File.join(Dir.tmpdir, "mnist_ddp_checkpoint.pt")
17
17
  DEFAULT_BACKEND = if Torch.const_defined?(:CUDA) && Torch::CUDA.respond_to?(:available?) && Torch::CUDA.available?
18
18
  "nccl"
19
19
  else
20
- Torch::Distributed.get_default_backend_for_device(Torch::Accelerator.current_accelerator) || "gloo"
20
+ Torch::Distributed.get_default_backend_for_device(nil) || "gloo"
21
21
  end
22
22
 
23
23
  class MyNet < Torch::NN::Module
@@ -99,16 +99,18 @@ def subset_for_rank(dataset, rank, world_size)
99
99
  end
100
100
 
101
101
  def checkpoint_map_location(device, rank)
102
- accelerator_device = Torch::Accelerator.current_accelerator
103
- return nil unless accelerator_device
104
-
105
- accelerator_type = accelerator_device.type
102
+ device_type = device&.type
103
+ return nil unless device_type && device_type != "cpu"
106
104
  target_index = device.index
107
- if target_index.nil? && Torch::Accelerator.respond_to?(:device_count)
108
- count = Torch::Accelerator.device_count
105
+ if target_index.nil?
106
+ count = if Torch.const_defined?(:CUDA) && Torch::CUDA.respond_to?(:device_count)
107
+ Torch::CUDA.device_count
108
+ else
109
+ 0
110
+ end
109
111
  target_index = count.positive? ? rank % count : 0
110
112
  end
111
- { "#{accelerator_type}:0" => "#{accelerator_type}:#{target_index}" }
113
+ { "#{device_type}:0" => "#{device_type}:#{target_index}" }
112
114
  end
113
115
 
114
116
  def load_checkpoint_if_present(ddp, device, rank, path)
@@ -173,8 +175,7 @@ end
173
175
 
174
176
  def run_worker(rank, world_size, port, options)
175
177
  store = Torch::Distributed::TCPStore.new("127.0.0.1", port, world_size, rank.zero?)
176
- accelerator = Torch::Accelerator.current_accelerator
177
- backend = options[:backend] || Torch::Distributed.get_default_backend_for_device(accelerator) || DEFAULT_BACKEND
178
+ backend = options[:backend] || Torch::Distributed.get_default_backend_for_device(nil) || DEFAULT_BACKEND
178
179
  Torch::Distributed.init_process_group(backend, store: store, rank: rank, world_size: world_size)
179
180
 
180
181
  device = if Torch::CUDA.available? && options[:gpus] > 0
@@ -44,7 +44,7 @@ void register_cuda_helpers(Rice::Module& m) {
44
44
  rb_eRuntimeError,
45
45
  "Torch::DDP._cuda_set_device requires CUDA support");
46
46
  #endif
47
- return Rice::Nil;
47
+ return Rice::Object(Qnil);
48
48
  });
49
49
 
50
50
  rb_mDDP.define_singleton_function(
@@ -57,7 +57,7 @@ void register_cuda_helpers(Rice::Module& m) {
57
57
  rb_eRuntimeError,
58
58
  "Torch::DDP._cuda_empty_cache requires CUDA support");
59
59
  #endif
60
- return Rice::Nil;
60
+ return Rice::Object(Qnil);
61
61
  });
62
62
  }
63
63
 
@@ -17,7 +17,7 @@
17
17
  #endif
18
18
 
19
19
  static_assert(
20
- TORCH_VERSION_MAJOR == 2 && TORCH_VERSION_MINOR == 9,
20
+ TORCH_VERSION_MAJOR == 2 && TORCH_VERSION_MINOR == 13,
21
21
  "Incompatible LibTorch version");
22
22
 
23
23
  #ifdef USE_C10D
@@ -254,7 +254,7 @@ void init_distributed(Rice::Module& m) {
254
254
  "_destroy_process_group",
255
255
  []() {
256
256
  shutdown_default_process_group();
257
- return Rice::Nil;
257
+ return Rice::Object(Qnil);
258
258
  });
259
259
 
260
260
  rb_mDistributed.define_singleton_function(
@@ -267,7 +267,7 @@ void init_distributed(Rice::Module& m) {
267
267
  "_default_process_group",
268
268
  [rb_cProcessGroup]() -> Rice::Object {
269
269
  if (!default_process_group) {
270
- return Rice::Nil;
270
+ return Rice::Object(Qnil);
271
271
  }
272
272
  return Rice::Data_Object<ProcessGroupWrapper>(new ProcessGroupWrapper(default_process_group), true, rb_cProcessGroup);
273
273
  });
@@ -293,7 +293,7 @@ void init_distributed(Rice::Module& m) {
293
293
  ::c10d::BarrierOptions opts;
294
294
  auto work = pg->barrier(opts);
295
295
  work->wait();
296
- return Rice::Nil;
296
+ return Rice::Object(Qnil);
297
297
  });
298
298
 
299
299
  rb_mDistributed.define_singleton_function(
@@ -1,6 +1,6 @@
1
1
  require "mkmf-rice"
2
2
 
3
- $CXXFLAGS += " -std=c++17 $(optflags)"
3
+ $CXXFLAGS += " -std=c++20 $(optflags)"
4
4
 
5
5
  # change to 0 for Linux pre-cxx11 ABI version
6
6
  $CXXFLAGS += " -D_GLIBCXX_USE_CXX11_ABI=1"
@@ -38,7 +38,6 @@ cuda_inc ||= "/usr/include"
38
38
 
39
39
  cudnn_inc, cudnn_lib = dir_config("cudnn")
40
40
  cudnn_lib ||= "/usr/local/cuda/lib"
41
- abort "cuda.h not found" unless find_header("cuda.h")
42
41
 
43
42
  gloo_inc, _ = dir_config("gloo")
44
43
  gloo_inc ||= "./vendor/gloo"
@@ -56,13 +55,25 @@ if Dir["#{lib}/*torch_cuda*"].any?
56
55
  $LDFLAGS += " -L#{cudnn_lib}" if Dir.exist?(cudnn_lib) && cudnn_lib != cuda_lib
57
56
  with_cuda = have_library("cuda") && have_library("cudnn")
58
57
  end
58
+ abort "cuda.h not found" if with_cuda && !find_header("cuda.h")
59
59
  $defs << "-DWITH_CUDA" if with_cuda
60
60
 
61
61
  $INCFLAGS += " -I#{inc}"
62
62
  $INCFLAGS += " -I#{inc}/torch/csrc/api/include"
63
63
 
64
64
  CONFIG["CC"] = CONFIG["CXX"]
65
+ CONFIG["CXXFLAGS"] = $CXXFLAGS
66
+ RbConfig::CONFIG["CXXFLAGS"] = $CXXFLAGS
65
67
  $CFLAGS = $CXXFLAGS
68
+ $CFLAGS += " -std=c++20"
69
+
70
+ def try_link_with_cppflags(source, flags)
71
+ original_cppflags = $CPPFLAGS
72
+ $CPPFLAGS = [original_cppflags, flags].compact.join(" ")
73
+ try_link(source)
74
+ ensure
75
+ $CPPFLAGS = original_cppflags
76
+ end
66
77
 
67
78
  $LDFLAGS += " -Wl,-rpath,#{lib}"
68
79
  if RbConfig::CONFIG["host_os"] =~ /darwin/i && RbConfig::CONFIG["host_cpu"] =~ /arm|aarch64/i && Dir.exist?("/opt/homebrew/opt/libomp/lib")
@@ -70,7 +81,7 @@ if RbConfig::CONFIG["host_os"] =~ /darwin/i && RbConfig::CONFIG["host_cpu"] =~ /
70
81
  end
71
82
  $LDFLAGS += ":#{cuda_lib}/stubs:#{cuda_lib}" if with_cuda
72
83
 
73
- # https://github.com/pytorch/pytorch/blob/v2.9.0/torch/utils/cpp_extension.py#L1351-L1364
84
+ # https://github.com/pytorch/pytorch/blob/v2.13.0/torch/utils/cpp_extension.py#L1351-L1364
74
85
  $LDFLAGS += " -lc10 -ltorch_cpu -ltorch"
75
86
  if with_cuda
76
87
  $LDFLAGS += " -lcuda -lnvrtc"
@@ -80,7 +91,10 @@ if with_cuda
80
91
  $LDFLAGS += " -Wl,--no-as-needed,#{lib}/libtorch.so"
81
92
  end
82
93
 
83
- supports_c10d = try_link(<<~CPP, "-DUSE_C10D")
94
+ supports_c10d = try_link_with_cppflags(<<~CPP, "-DUSE_C10D")
95
+ // Ruby's headers define `_` as a compatibility macro, which collides with
96
+ // LibTorch 2.13's TensorAccessor headers.
97
+ #undef _
84
98
  #include <torch/torch.h>
85
99
  #include <torch/csrc/distributed/c10d/FileStore.hpp>
86
100
 
@@ -103,7 +117,8 @@ else
103
117
  puts "Building without distributed support"
104
118
  end
105
119
 
106
- supports_c10d_gloo = supports_c10d && try_link(<<~CPP, "-DUSE_C10D -DUSE_C10D_GLOO")
120
+ supports_c10d_gloo = supports_c10d && try_link_with_cppflags(<<~CPP, "-DUSE_C10D -DUSE_C10D_GLOO")
121
+ #undef _
107
122
  #include <torch/torch.h>
108
123
  #include <torch/csrc/distributed/c10d/ProcessGroupGloo.hpp>
109
124
  #include <torch/csrc/distributed/c10d/FileStore.hpp>
@@ -117,7 +132,8 @@ supports_c10d_gloo = supports_c10d && try_link(<<~CPP, "-DUSE_C10D -DUSE_C10D_GL
117
132
  }
118
133
  CPP
119
134
 
120
- supports_c10d_nccl = with_cuda && try_link(<<~CPP, "-DUSE_C10D -DUSE_C10D_NCCL")
135
+ supports_c10d_nccl = with_cuda && try_link_with_cppflags(<<~CPP, "-DUSE_C10D -DUSE_C10D_NCCL")
136
+ #undef _
121
137
  #include <torch/torch.h>
122
138
  #include <torch/csrc/distributed/c10d/ProcessGroupNCCL.hpp>
123
139
 
@@ -13,7 +13,7 @@ module Torch
13
13
  warn("#{WARNING_PREFIX} Applying torch compatibility patch for: #{missing.join(', ')}. Please upgrade the torch gem for native support.")
14
14
  patch_cuda_set_device if missing.include?(:cuda_set_device)
15
15
  patch_cuda_empty_cache if missing.include?(:cuda_empty_cache)
16
- patch_device_helpers
16
+ patch_device_helpers if missing.include?(:device_helpers)
17
17
  patch_load if missing.include?(:load_keywords)
18
18
  patch_tensor_item if missing.include?(:tensor_item_scalar)
19
19
  @applied = true
@@ -25,11 +25,18 @@ module Torch
25
25
  missing = []
26
26
  missing << :cuda_set_device unless Torch.const_defined?(:CUDA) && Torch::CUDA.respond_to?(:set_device)
27
27
  missing << :cuda_empty_cache unless Torch.const_defined?(:CUDA) && Torch::CUDA.respond_to?(:empty_cache)
28
+ missing << :device_helpers unless native_device_helpers?
28
29
  missing << :load_keywords unless load_supports_map_location_and_weights_only?
29
30
  missing << :tensor_item_scalar unless tensor_item_returns_scalar?
30
31
  missing
31
32
  end
32
33
 
34
+ def native_device_helpers?
35
+ Torch.tensor([0]).device.is_a?(Torch::Device)
36
+ rescue StandardError
37
+ false
38
+ end
39
+
33
40
  def load_supports_map_location_and_weights_only?
34
41
  params = Torch.method(:load).parameters
35
42
  keyword_names = params.select { |kind, _| [:key, :keyreq].include?(kind) }.map(&:last)
@@ -1,5 +1,5 @@
1
1
  module Torch
2
2
  module DDP
3
- VERSION = "0.2.0"
3
+ VERSION = "0.2.5"
4
4
  end
5
5
  end
Binary file
@@ -264,17 +264,17 @@ module Torch
264
264
  when Torch::Device
265
265
  device.type
266
266
  when NilClass
267
- accelerator_type || "cpu"
267
+ device_type_fallback || "cpu"
268
268
  when String
269
269
  Torch.device(device).type
270
270
  when Integer
271
- return accelerator_type || "cpu" if device.negative?
271
+ return device_type_fallback || "cpu" if device.negative?
272
272
  if Torch.const_defined?(:CUDA) && Torch::CUDA.respond_to?(:device_count)
273
273
  max = Torch::CUDA.device_count
274
- return accelerator_type || "cpu" if max <= 0 || device >= max
274
+ return device_type_fallback || "cpu" if max <= 0 || device >= max
275
275
  return Torch.device("cuda:#{device}").type
276
276
  end
277
- accelerator_type || "cpu"
277
+ device_type_fallback || "cpu"
278
278
  else
279
279
  return device.type if device.respond_to?(:type)
280
280
  Torch.device(device).type
@@ -283,9 +283,17 @@ module Torch
283
283
  raise ArgumentError, "Invalid device #{device.inspect}: #{e.message}"
284
284
  end
285
285
 
286
- def accelerator_type
287
- acc = Torch::Accelerator.current_accelerator
288
- acc.type if acc && acc.respond_to?(:type)
286
+ def device_type_fallback
287
+ if Torch.const_defined?(:CUDA) && Torch::CUDA.respond_to?(:available?) && Torch::CUDA.available?
288
+ return "cuda"
289
+ end
290
+
291
+ if Torch.const_defined?(:Backends) && Torch::Backends.const_defined?(:MPS) &&
292
+ Torch::Backends::MPS.respond_to?(:available?) && Torch::Backends::MPS.available?
293
+ return "mps"
294
+ end
295
+
296
+ "cpu"
289
297
  rescue
290
298
  nil
291
299
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: torch-ddp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Razuvaev
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2025-12-19 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: torch-rb
@@ -16,29 +15,28 @@ dependencies:
16
15
  requirements:
17
16
  - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: 0.22.2
18
+ version: 0.25.0
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - ">="
25
24
  - !ruby/object:Gem::Version
26
- version: 0.22.2
25
+ version: 0.25.0
27
26
  - !ruby/object:Gem::Dependency
28
27
  name: rice
29
28
  requirement: !ruby/object:Gem::Requirement
30
29
  requirements:
31
30
  - - ">="
32
31
  - !ruby/object:Gem::Version
33
- version: '4.7'
32
+ version: '4.8'
34
33
  type: :runtime
35
34
  prerelease: false
36
35
  version_requirements: !ruby/object:Gem::Requirement
37
36
  requirements:
38
37
  - - ">="
39
38
  - !ruby/object:Gem::Version
40
- version: '4.7'
41
- description:
39
+ version: '4.8'
42
40
  email: i@orlando-labs.com
43
41
  executables:
44
42
  - torchrun
@@ -58,6 +56,7 @@ files:
58
56
  - lib/torch-ddp.rb
59
57
  - lib/torch/ddp/monkey_patch.rb
60
58
  - lib/torch/ddp/version.rb
59
+ - lib/torch/ddp_ext.so
61
60
  - lib/torch/distributed.rb
62
61
  - lib/torch/nn/parallel/distributed_data_parallel.rb
63
62
  - lib/torch/torchrun.rb
@@ -71,7 +70,6 @@ homepage: https://github.com/ankane/torch.rb
71
70
  licenses:
72
71
  - BSD-3-Clause
73
72
  metadata: {}
74
- post_install_message:
75
73
  rdoc_options: []
76
74
  require_paths:
77
75
  - lib
@@ -79,15 +77,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
79
77
  requirements:
80
78
  - - ">="
81
79
  - !ruby/object:Gem::Version
82
- version: '3.2'
80
+ version: '3.3'
83
81
  required_rubygems_version: !ruby/object:Gem::Requirement
84
82
  requirements:
85
83
  - - ">="
86
84
  - !ruby/object:Gem::Version
87
85
  version: '0'
88
86
  requirements: []
89
- rubygems_version: 3.5.22
90
- signing_key:
87
+ rubygems_version: 4.0.1
91
88
  specification_version: 4
92
89
  summary: Distributed data parallel support for torch-rb
93
90
  test_files: []