Add barrier to JACCL (#3459)

This commit is contained in:
Irakli Salia
2026-04-28 09:39:56 -07:00
committed by GitHub
parent d7d0992d75
commit e8ebdebeeb
8 changed files with 63 additions and 0 deletions
+5
View File
@@ -29,6 +29,8 @@ in macOS 26.2.
- **Point-to-Point Operations**:
- `send`: Send data to a specific node
- `recv`: Receive data from a specific node
- **Synchronization**:
- `barrier`: Block until all nodes in the group reach this point
- **Type Support**: Bool, Int8-64, UInt8-64, Float16, BFloat16, Float32,
Float64, Complex64
@@ -286,6 +288,9 @@ class Group {
// Simple send/recv primitives.
virtual void send(const void* input, size_t n_bytes, int dst) = 0;
virtual void recv(void* output, size_t n_bytes, int src) = 0;
// Block until every rank reaches this point.
virtual void barrier() = 0;
};
```
@@ -35,6 +35,7 @@ endfunction()
# Examples
build_example(minimal_env.cpp)
build_example(minimal_cfg.cpp)
build_example(minimal_barrier.cpp)
# Benchmarks
build_example(allreduce_bench.cpp)
@@ -0,0 +1,42 @@
// Copyright © 2026 Apple Inc.
//
// Exercises Group::barrier(). Ranks arrive at the barrier at staggered times;
// after the barrier returns we do a small all_sum to confirm the group is
// healthy and that barrier() carried the correct fence semantics.
#include <chrono>
#include <iostream>
#include <thread>
#include <jaccl/jaccl.h>
int main() {
auto group = jaccl::init();
if (!group) {
std::cerr << "Failed to initialize JACCL" << std::endl;
return 1;
}
int rank = group->rank();
int size = group->size();
std::this_thread::sleep_for(std::chrono::milliseconds(100 * rank));
std::cout << "rank " << rank << " entering barrier" << std::endl;
group->barrier();
std::cout << "rank " << rank << " exited barrier" << std::endl;
int in = rank + 1;
int out = 0;
group->all_sum(&in, &out, sizeof(in), jaccl::Int32);
int expected = size * (size + 1) / 2;
if (out != expected) {
std::cerr << "rank " << rank << ": post-barrier all_sum mismatch (got "
<< out << ", expected " << expected << ")" << std::endl;
return 1;
}
std::cout << "rank " << rank << ": post-barrier all_sum OK (" << out << ")"
<< std::endl;
return 0;
}
+1
View File
@@ -30,6 +30,7 @@ class Group {
virtual void send(const void* input, size_t n_bytes, int dst) = 0;
virtual void recv(void* output, size_t n_bytes, int src) = 0;
virtual void barrier() = 0;
};
/**
+5
View File
@@ -184,6 +184,11 @@ void MeshGroup::recv(void* output, size_t n_bytes, int src) {
mesh_.recv(static_cast<char*>(output), n_bytes, src);
}
void MeshGroup::barrier() {
uint8_t b = 0;
all_sum(&b, &b, sizeof(b), Dtype::UInt8);
}
template <typename T, typename ReduceOp>
void MeshGroup::all_reduce(
const void* input,
+2
View File
@@ -47,6 +47,8 @@ class MeshGroup : public Group {
void send(const void* input, size_t n_bytes, int dst) override;
void recv(void* output, size_t n_bytes, int src) override;
void barrier() override;
private:
template <typename T, typename ReduceOp>
void all_reduce(
+5
View File
@@ -190,6 +190,11 @@ void RingGroup::recv(void* output, size_t n_bytes, int src) {
ring_.recv(static_cast<char*>(output), n_bytes, src, n_conns_);
}
void RingGroup::barrier() {
uint8_t b = 0;
all_sum(&b, &b, sizeof(b), Dtype::UInt8);
}
template <typename T, typename ReduceOp>
void RingGroup::all_reduce(
const void* input,
+2
View File
@@ -48,6 +48,8 @@ class RingGroup : public Group {
void send(const void* input, size_t n_bytes, int dst) override;
void recv(void* output, size_t n_bytes, int src) override;
void barrier() override;
private:
template <typename T, typename ReduceOp>
void all_reduce(