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 +4 -4
- data/examples/benchmark/training.rb +3 -4
- data/examples/mnist/distributed.rb +11 -10
- data/ext/torch_ddp/cuda.cpp +2 -2
- data/ext/torch_ddp/distributed.cpp +4 -4
- data/ext/torch_ddp/extconf.rb +22 -6
- data/lib/torch/ddp/monkey_patch.rb +8 -1
- data/lib/torch/ddp/version.rb +1 -1
- data/lib/torch/ddp_ext.so +0 -0
- data/lib/torch/distributed.rb +15 -7
- metadata +9 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 01c3dafea6b9ee6b691d59448137a325d54bd794c4004ac6cf519ac6d2961bc3
|
|
4
|
+
data.tar.gz: fbb84030108e52d0f54ce67ac43bb07ab1608d3878c8988bfcf91073e9e3f292
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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(
|
|
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
|
-
|
|
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
|
|
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(
|
|
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
|
-
|
|
103
|
-
return nil unless
|
|
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?
|
|
108
|
-
count = Torch::
|
|
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
|
-
{ "#{
|
|
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
|
-
|
|
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
|
data/ext/torch_ddp/cuda.cpp
CHANGED
|
@@ -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::
|
|
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::
|
|
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 ==
|
|
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::
|
|
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::
|
|
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::
|
|
296
|
+
return Rice::Object(Qnil);
|
|
297
297
|
});
|
|
298
298
|
|
|
299
299
|
rb_mDistributed.define_singleton_function(
|
data/ext/torch_ddp/extconf.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require "mkmf-rice"
|
|
2
2
|
|
|
3
|
-
$CXXFLAGS += " -std=c++
|
|
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.
|
|
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 =
|
|
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 &&
|
|
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 &&
|
|
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)
|
data/lib/torch/ddp/version.rb
CHANGED
|
Binary file
|
data/lib/torch/distributed.rb
CHANGED
|
@@ -264,17 +264,17 @@ module Torch
|
|
|
264
264
|
when Torch::Device
|
|
265
265
|
device.type
|
|
266
266
|
when NilClass
|
|
267
|
-
|
|
267
|
+
device_type_fallback || "cpu"
|
|
268
268
|
when String
|
|
269
269
|
Torch.device(device).type
|
|
270
270
|
when Integer
|
|
271
|
-
return
|
|
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
|
|
274
|
+
return device_type_fallback || "cpu" if max <= 0 || device >= max
|
|
275
275
|
return Torch.device("cuda:#{device}").type
|
|
276
276
|
end
|
|
277
|
-
|
|
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
|
|
287
|
-
|
|
288
|
-
|
|
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.
|
|
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:
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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:
|
|
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: []
|