Skip to content

Commit 8066a38

Browse files
[UIL] Enable flagcxBackend to receive custom backend options (flagos-ai#309)
1 parent 42a9e1a commit 8066a38

4 files changed

Lines changed: 334 additions & 2 deletions

File tree

plugin/torch/example/example.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
FLAGCX_GROUP1 = None
2929
FLAGCX_GROUP2 = None
30+
FLAGCX_GROUP3 = None
3031
MY_RANK = None
3132
WORLD_SIZE = None
3233
PREV_RANK = None
@@ -50,7 +51,7 @@ def get_args():
5051
return parser.parse_args()
5152

5253
def init_pg():
53-
global FLAGCX_GROUP1, FLAGCX_GROUP2, MY_RANK, WORLD_SIZE, PREV_RANK, NEXT_RANK
54+
global FLAGCX_GROUP1, FLAGCX_GROUP2, FLAGCX_GROUP3, MY_RANK, WORLD_SIZE, PREV_RANK, NEXT_RANK
5455

5556
# Get rank and world_size from environment
5657
MY_RANK = int(os.environ["RANK"])
@@ -66,6 +67,13 @@ def init_pg():
6667
FLAGCX_GROUP2 = dist.new_group(ranks=ranks, backend=f"cpu:gloo,{dev_name}:flagcx")
6768
print(f"ranks_flagcx: {dist.get_process_group_ranks(FLAGCX_GROUP1)}")
6869

70+
# Create a group with options; this only works when flagcxBackend has Options defined
71+
# TODO: confirm with all vendors to see if their torch implementation support backend options
72+
if flagcx._C is not None and hasattr(flagcx._C, 'ProcessGroupFlagCX') and hasattr(flagcx._C.ProcessGroupFlagCX, 'Options'):
73+
flagcx_options = flagcx._C.ProcessGroupFlagCX.Options(enable_tuner=True)
74+
FLAGCX_GROUP3 = dist.new_group(ranks=ranks, backend=f"{dev_name}:flagcx", pg_options=flagcx_options)
75+
print(f"ranks_flagcx with options: {dist.get_process_group_ranks(FLAGCX_GROUP3)}")
76+
6977
# Get prev_rank and next_rank
7078
PREV_RANK = (MY_RANK - 1 + WORLD_SIZE) % WORLD_SIZE
7179
NEXT_RANK = (MY_RANK + 1) % WORLD_SIZE
@@ -77,6 +85,7 @@ def init_pg():
7785

7886
def destroy_pg():
7987
dist.destroy_process_group()
88+
8089

8190
def test_broadcast():
8291
if torch.cuda.is_available():
@@ -351,3 +360,4 @@ def test_all():
351360
dict_op_to_test.get(args.op, test_all)()
352361

353362
destroy_pg()
363+

plugin/torch/flagcx/include/backend_flagcx.hpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "event_flagcx.hpp"
2121
#include "stream_guard_flagcx.hpp"
22+
#include "utils_flagcx.hpp"
2223

2324
namespace c10d {
2425

@@ -74,8 +75,38 @@ class flagcxWork : public Work {
7475

7576
class flagcxBackend : public Backend {
7677
public:
78+
// TODO: check with all vendors to make sure their torch implementation support
79+
// backend options
80+
#if defined(USE_NVIDIA_ADAPTOR) || defined(USE_METAX_ADAPTOR)
81+
struct TuneObjectKey {
82+
std::string commOp;
83+
size_t nBytes;
84+
85+
bool operator<(const TuneObjectKey &other) const noexcept {
86+
if (other.commOp == commOp) {
87+
return nBytes < other.nBytes;
88+
}
89+
return commOp < other.commOp;
90+
}
91+
};
92+
93+
struct Options : Backend::Options {
94+
explicit Options(bool enableTuner = false);
95+
96+
static c10::intrusive_ptr<Options> create(bool enableTuner = false) {
97+
return c10::make_intrusive<Options>(enableTuner);
98+
}
99+
100+
bool enableTuner{false};
101+
};
102+
103+
explicit flagcxBackend(
104+
const c10::intrusive_ptr<::c10d::Store> &store, int rank = -1,
105+
int size = -1, c10::intrusive_ptr<Options> options = Options::create());
106+
#else
77107
explicit flagcxBackend(const c10::intrusive_ptr<::c10d::Store> &store,
78108
int rank = -1, int size = -1);
109+
#endif
79110

80111
~flagcxBackend() override;
81112

@@ -167,9 +198,18 @@ class flagcxBackend : public Backend {
167198
c10::intrusive_ptr<Work> recvAnysource(std::vector<at::Tensor> &tensors,
168199
int tag) override;
169200

201+
#if defined(USE_NVIDIA_ADAPTOR) || defined(USE_METAX_ADAPTOR)
202+
void checkRecordingEnded();
203+
void recordTuneObject(flagcxCommOp_t commOp, flagcxDataType_t dataType,
204+
size_t count);
205+
static c10::intrusive_ptr<Backend> createFlagcxBackend(
206+
c10d::DistributedBackendOptions backendOptions,
207+
c10::intrusive_ptr<Options> extraOptions = Options::create());
208+
#else
170209
static c10::intrusive_ptr<Backend>
171210
createFlagcxBackend(const c10::intrusive_ptr<::c10d::Store> &store, int rank,
172211
int size, const std::chrono::duration<float> &timeout);
212+
#endif
173213

174214
static void flagcxBackendConstructor() __attribute__((constructor)) {
175215
std::string devName = "cuda";
@@ -193,8 +233,14 @@ class flagcxBackend : public Backend {
193233
py::object module = py::module::import("torch.distributed");
194234
py::object registerBackend =
195235
module.attr("Backend").attr("register_backend");
236+
#if defined(USE_NVIDIA_ADAPTOR) || defined(USE_METAX_ADAPTOR)
237+
registerBackend("flagcx", py::cpp_function(createFlagcxBackend),
238+
py::arg("extended_api") = true,
239+
py::arg("devices") = py::make_tuple(devName));
240+
#else
196241
registerBackend("flagcx", py::cpp_function(createFlagcxBackend),
197242
py::arg("devices") = py::make_tuple(devName));
243+
#endif
198244
}
199245

200246
protected:
@@ -214,6 +260,15 @@ class flagcxBackend : public Backend {
214260
std::unordered_map<int, flagcxStream_t> flagcxStreams_;
215261
std::unordered_map<int, std::unique_ptr<flagcxEvent>> flagcxEvents_;
216262
flagcxHandlerGroup_t handler_ = nullptr;
263+
#if defined(USE_NVIDIA_ADAPTOR) || defined(USE_METAX_ADAPTOR)
264+
const c10::intrusive_ptr<Options> options_;
265+
std::set<TuneObjectKey> tuneObjectSet_;
266+
// whether we finished recording tuning objects
267+
// a tuning object is a (commOp, nBytes) pair
268+
// we record the tuning objects that will occur in this communicator so that
269+
// flagcxTuner knows which communicator it is tuning
270+
bool recordingEnded = false;
271+
#endif
217272
#ifdef USE_ASCEND_ADAPTOR
218273
aclrtStream acl_stream;
219274
#endif

0 commit comments

Comments
 (0)