From aeb3b6a4d3661df79caa27710c605fdc7d4dce4f Mon Sep 17 00:00:00 2001 From: ybc Date: Thu, 22 Oct 2020 21:07:14 -0700 Subject: [PATCH 01/44] Add hierachical_neighbor_allreduce python interface --- bluefog/torch/mpi_ops.cc | 2 +- bluefog/torch/mpi_ops.h | 2 +- bluefog/torch/mpi_ops.py | 84 +++++++++++++++++++++++++++++++++++++-- examples/pytorch_mnist.py | 6 +++ 4 files changed, 89 insertions(+), 5 deletions(-) diff --git a/bluefog/torch/mpi_ops.cc b/bluefog/torch/mpi_ops.cc index fe62582e..b4f5f0ea 100644 --- a/bluefog/torch/mpi_ops.cc +++ b/bluefog/torch/mpi_ops.cc @@ -306,7 +306,7 @@ int DoNeighborAllgather(::torch::Tensor tensor, ::torch::Tensor output, int DoNeighborAllreduce(::torch::Tensor tensor, ::torch::Tensor output, double self_weight, const std::unordered_map& neighbor_weights, const std::vector& send_neighbors, bool enable_topo_check, - bool avg_computation, const std::string& name) { + bool avg_computation, bool is_hierarchical, const std::string& name) { ThrowIfError(common::CheckInitialized()); auto handle = handle_manager.AllocateHandle(); diff --git a/bluefog/torch/mpi_ops.h b/bluefog/torch/mpi_ops.h index df6d755e..ba495641 100644 --- a/bluefog/torch/mpi_ops.h +++ b/bluefog/torch/mpi_ops.h @@ -115,7 +115,7 @@ NEIGHBOR_ALLGATHER_H(torch_cuda_DoubleTensor, THCudaDoubleTensor) THTensor* tensor, THTensor* output, double self_weight, \ const std::unordered_map& neighbor_weights, \ const std::vector& send_neighbors, bool enable_topo_check, \ - bool avg_computation, char* name); + bool avg_computation, bool is_hierarchical, char* name); NEIGHBOR_ALLREDUCE_H(torch_HalfTensor, THHalfTensor) NEIGHBOR_ALLREDUCE_H(torch_FloatTensor, THFloatTensor) diff --git a/bluefog/torch/mpi_ops.py b/bluefog/torch/mpi_ops.py index b78671fe..f6550962 100644 --- a/bluefog/torch/mpi_ops.py +++ b/bluefog/torch/mpi_ops.py @@ -414,7 +414,8 @@ def _neighbor_allreduce_nonblocking(tensor, output, self_weight, neighbor_weight handle = getattr(mpi_lib, function)(tensor, output, self_weight, neighbor_weights, send_neighbors, enable_topo_check, avg_computation, - name.encode() if name is not None else "") + is_hierarchical=False, + name=name.encode() if name is not None else "") _handle_map[handle] = (tensor, output) return handle @@ -518,9 +519,86 @@ def neighbor_allreduce_nonblocking(tensor: torch.Tensor, else: first_dim = tensor.shape[0] * len(neighbor_weights) new_shape = torch.Size([first_dim] + list(tensor.shape[1:])) - output = tensor.new(new_shape) # Pre-allocate the memory for the output. + output = tensor.new(new_shape) # Pre-allocate the memory for the output. return _neighbor_allreduce_nonblocking(tensor, output, self_weight, neighbor_weights, - send_neighbors, enable_topo_check, name) + send_neighbors, enable_topo_check, name=name) + + +def hierachical_neighbor_allreduce(tensor: torch.Tensor, + self_weight: float, + neighbor_machine_weights: Dict[int, float], + send_neighbor_machines: List[int], + enable_topo_check: bool = True, + name: Optional[str] = None) -> torch.Tensor: + # TODO(ybc) add check for self_weight and neighbor_machine_weights. + if (self_weight is None and neighbor_machine_weights is not None) or \ + (self_weight is not None and send_neighbor_machines is None): + raise ValueError("Arguments self_weight and neighbor_machine_weights have to " + "be presented at the same time") + handle = hierachical_neighbor_allreduce_nonblocking( + tensor, self_weight, neighbor_machine_weights, send_neighbor_machines, + enable_topo_check, name) + return synchronize(handle) + + +def hierachical_neighbor_allreduce_nonblocking(tensor: torch.Tensor, + self_weight: float, + neighbor_machine_weights: Dict[int, float], + send_neighbor_machines: List[int], + enable_topo_check: bool = True, + name: Optional[str] = None) -> int: + if (self_weight is None or neighbor_machine_weights is None): + raise ValueError("Arguments self_weight and neighbor_weights cannot be empty or None.") + if (self_weight is None and neighbor_machine_weights is not None) or \ + (self_weight is not None and neighbor_machine_weights is None): + raise ValueError("Arguments self_weight and neighbor_weights have to be presented at " + "the same time") + + first_dim = tensor.shape[0] * len(neighbor_machine_weights) + new_shape = torch.Size([first_dim] + list(tensor.shape[1:])) + output = tensor.new(new_shape) # Pre-allocate the memory for the output. + + return _hierachical_neighbor_allreduce_nonblocking( + tensor, output, self_weight, neighbor_machine_weights, + send_neighbor_machines, enable_topo_check, name=name) + + +def _hierachical_neighbor_allreduce_nonblocking( + tensor, output, self_weight, neighbor_machine_weights, + send_neighbor_machines, enable_topo_check, name): + assert not is_homogeneous, \ + "hierachical_neighbor_allreduce should be used under homogeneous environment only" + function = _check_function(_neighbor_allreduce_function_factory, tensor) + if self_weight is not None and neighbor_machine_weights is not None: + if not isinstance(neighbor_machine_weights, dict): + raise ValueError("Argument neighbor_weights has to be a dictionary map from the " + "(in-)neighbor rank to the weights.") + if not isinstance(self_weight, float): + raise ValueError( + "Argument self_weight has to be a float for self rank.") + uniform_weights = 1.0/(len(neighbor_machine_weights)+1) + avg_computation = False + if abs(self_weight - uniform_weights) > 1e-6: + avg_computation = True + for n_weights in neighbor_machine_weights.values(): + if abs(n_weights - uniform_weights) > 1e-6: + avg_computation = True + break + else: + raise ValueError("Arguments self_weight and neighbor_weights cannot be empty or None.") + + # Translate machine id into rank id. + node_per_machine = local_size() + neighbor_weights = { + node_per_machine*m: weights for (m, weights) in neighbor_machine_weights.items()} + send_neighbors = [node_per_machine*m for m in send_neighbor_machines] + avg_computation = False + handle = getattr(mpi_lib, function)(tensor, output, self_weight, neighbor_weights, + send_neighbors, enable_topo_check, avg_computation, + is_hierarchical=True, + name=name.encode() if name is not None else "") + _handle_map[handle] = (tensor, output) + return handle def _pair_gossip_nonblocking_function_factory(tensor): diff --git a/examples/pytorch_mnist.py b/examples/pytorch_mnist.py index 67b6c9d9..460f9fe7 100644 --- a/examples/pytorch_mnist.py +++ b/examples/pytorch_mnist.py @@ -270,6 +270,9 @@ def train(epoch): if args.cuda: data, target = data.cuda(), target.cuda() + if args.dist_optimizer == 'neighbor_allreduce' and (batch_idx % 100 == 99): + optimizer.use_allreduce_in_communication() + optimizer.zero_grad() output = model(data) loss = F.nll_loss(output, target) @@ -289,6 +292,9 @@ def train(epoch): ) ) + if args.dist_optimizer == 'neighbor_allreduce' and (batch_idx % 100 == 99): + optimizer.use_neighbor_allreduce_in_communication() + def metric_average(val, name): tensor = torch.tensor(val) # pylint: disable=not-callable From 84e6975b964bbce0d8499ca66f46fc9aa9ca4f25 Mon Sep 17 00:00:00 2001 From: ybc Date: Thu, 22 Oct 2020 21:39:09 -0700 Subject: [PATCH 02/44] Pass down is_hierachical down to perform --- bluefog/common/common.h | 3 +++ bluefog/common/mpi_controller.cc | 10 ++++++++++ bluefog/common/operations.cc | 5 +++++ bluefog/common/operations.h | 1 + bluefog/torch/mpi_ops.cc | 29 ++++++++++++++++++----------- bluefog/torch/mpi_ops.py | 6 ++---- 6 files changed, 39 insertions(+), 15 deletions(-) diff --git a/bluefog/common/common.h b/bluefog/common/common.h index e11a156c..5dd3bcae 100644 --- a/bluefog/common/common.h +++ b/bluefog/common/common.h @@ -278,6 +278,9 @@ struct TensorTableEntry { // Boolean value for enabling topology check. bool enable_topo_check = false; + // Boolean value for hierarchical operation or not. + bool is_hierarchical = false; + // The ops requires the mutex. bool require_mutex = false; diff --git a/bluefog/common/mpi_controller.cc b/bluefog/common/mpi_controller.cc index ba878ed5..efc2a215 100644 --- a/bluefog/common/mpi_controller.cc +++ b/bluefog/common/mpi_controller.cc @@ -359,6 +359,11 @@ std::string GenerateNeighborAllreduceErrorMessage(const std::vector& void MPIController::NeighborAllreduce(TensorTableEntry& entry) { const void* sendbuf = entry.tensor->data(); int num_elements = entry.tensor->shape().num_elements(); + // TODO(ybc) support this + if (entry.is_hierarchical) { + throw std::runtime_error( + "Hierachical neighbor_allreduce is only supported under NCCL case."); + } Timeline* timeline_ptr; Status timeline_status = GetBluefogTimeline(timeline_ptr); @@ -484,6 +489,11 @@ void MPIController::Allreduce(std::vector& entries) { void MPIController::NeighborAllreduce(std::vector& entries) { auto& first_entry = entries[0]; with_device device_guard(first_entry.device); + // TODO(ybc) support this + if (first_entry.is_hierarchical) { + throw std::runtime_error( + "Hierachical neighbor_allreduce is only supported under NCCL case."); + } void* buffer_data; size_t buffer_len = 0; diff --git a/bluefog/common/operations.cc b/bluefog/common/operations.cc index bf1d5d56..ae4fb970 100644 --- a/bluefog/common/operations.cc +++ b/bluefog/common/operations.cc @@ -296,6 +296,8 @@ Response ConstructResponse(MessageTable* message_table, std::string name) { } } + // TODO(ybc) add check for is_hierarchical for neighbor_allreduce. + // If we are doing an (neighbor_)allreduce or broadcast, check that all tensor // shapes are identical. if (!error) { @@ -954,6 +956,7 @@ void NegotiateOfRequestOfMaster(BluefogGlobalState& state, if (response.response_type() == new_response.response_type() && response.devices() == new_response.devices() && entry.tensor->dtype() == new_entry.tensor->dtype() && + entry.is_hierarchical == new_entry.is_hierarchical && IsSameNeighborList(entry.send_neighbors, new_entry.send_neighbors) && IsSameNeighborList(entry.recv_neighbors, @@ -1484,6 +1487,7 @@ Status EnqueueTensorNeighborAllreduce(std::shared_ptr tensor, std::shared_ptr ready_event, std::shared_ptr> recv_neighbors, std::shared_ptr> send_neighbors, + bool is_hierarchical, bool enable_topo_check, const std::string& name, const int device, StatusCallback callback) { @@ -1505,6 +1509,7 @@ Status EnqueueTensorNeighborAllreduce(std::shared_ptr tensor, e.ready_event = ready_event; e.recv_neighbors = recv_neighbors; e.send_neighbors = send_neighbors; + e.is_hierarchical = is_hierarchical; e.enable_topo_check = enable_topo_check; e.device = device; e.callback = callback; diff --git a/bluefog/common/operations.h b/bluefog/common/operations.h index db20a1f0..66293cde 100644 --- a/bluefog/common/operations.h +++ b/bluefog/common/operations.h @@ -139,6 +139,7 @@ Status EnqueueTensorNeighborAllreduce(std::shared_ptr tensor, std::shared_ptr ready_event, std::shared_ptr> recv_neighbors, std::shared_ptr> send_neighbors, + bool is_hierarchical, bool enable_topo_check, const std::string& name, const int device, StatusCallback callback); diff --git a/bluefog/torch/mpi_ops.cc b/bluefog/torch/mpi_ops.cc index b4f5f0ea..07ea7266 100644 --- a/bluefog/torch/mpi_ops.cc +++ b/bluefog/torch/mpi_ops.cc @@ -338,11 +338,13 @@ int DoNeighborAllreduce(::torch::Tensor tensor, ::torch::Tensor output, auto bf_recv_neighbors = std::make_shared>(recv_neighbors); auto bf_send_neighbors = std::make_shared>(send_neighbors); auto ready_event = RecordReadyEvent(device); - auto enqueue_result = EnqueueTensorNeighborAllreduce( - bf_tensor, bf_output, bf_context, ready_event, bf_recv_neighbors, bf_send_neighbors, - enable_topo_check, op_name, CPU_DEVICE_ID, callback_wrapper([self_weight, neighbor_weights, - avg_computation, cpu_output, tensor, recv_neighbors, send_neighbors, output, device]() - mutable { + auto enqueue_result = EnqueueTensorNeighborAllreduce( + bf_tensor, bf_output, bf_context, ready_event, bf_recv_neighbors, + bf_send_neighbors, is_hierarchical, enable_topo_check, op_name, + CPU_DEVICE_ID, + callback_wrapper([self_weight, neighbor_weights, avg_computation, + cpu_output, tensor, recv_neighbors, send_neighbors, + output, device]() mutable { with_device device_guard(device); output.copy_(cpu_output); int recv_size = bluefog_neighbor_size(); @@ -381,8 +383,10 @@ int DoNeighborAllreduce(::torch::Tensor tensor, ::torch::Tensor output, for (int i = 0; i < indgree; i++) { double weight = 0.0; int recv_rank; - if(send_neighbors.empty()) recv_rank = *(sources_ptr+i); - else recv_rank = recv_neighbors[i]; + if(send_neighbors.empty()) + recv_rank = *(sources_ptr + i); + else + recv_rank = recv_neighbors[i]; auto it = neighbor_weights.find(recv_rank); if (it != neighbor_weights.end()) { weight = it->second; @@ -430,7 +434,7 @@ int DoNeighborAllreduce(::torch::Tensor tensor, ::torch::Tensor output, auto enqueue_result = EnqueueTensorNeighborAllreduce( bf_tensor, bf_output, bf_context, ready_event, bf_recv_neighbors, bf_send_neighbors, - enable_topo_check, op_name, device, callback_wrapper([self_weight, neighbor_weights, + is_hierarchical, enable_topo_check, op_name, device, callback_wrapper([self_weight, neighbor_weights, avg_computation, recv_neighbors, send_neighbors, tensor, output] () mutable { int recv_size = bluefog_neighbor_size(); if(!send_neighbors.empty()) recv_size = recv_neighbors.size(); @@ -450,10 +454,13 @@ int DoNeighborAllreduce(::torch::Tensor tensor, ::torch::Tensor output, int outdegree = 0; int* sources_ptr = nullptr; int* destinations_ptr = nullptr; - bluefog_load_topology(&indgree, sources_ptr, &outdegree, - destinations_ptr); auto output_reduced = output_buffer.slice(0, 0, first_dim); - if (!send_neighbors.empty()) indgree = recv_neighbors.size(); + if (send_neighbors.empty()) { + bluefog_load_topology(&indgree, sources_ptr, &outdegree, + destinations_ptr); + } else { + indgree = recv_neighbors.size(); + } for (int i = 0; i < indgree; i++) { double weight = 0.0; int recv_rank; diff --git a/bluefog/torch/mpi_ops.py b/bluefog/torch/mpi_ops.py index f6550962..a600f4c0 100644 --- a/bluefog/torch/mpi_ops.py +++ b/bluefog/torch/mpi_ops.py @@ -414,8 +414,7 @@ def _neighbor_allreduce_nonblocking(tensor, output, self_weight, neighbor_weight handle = getattr(mpi_lib, function)(tensor, output, self_weight, neighbor_weights, send_neighbors, enable_topo_check, avg_computation, - is_hierarchical=False, - name=name.encode() if name is not None else "") + False, name.encode() if name is not None else "") _handle_map[handle] = (tensor, output) return handle @@ -595,8 +594,7 @@ def _hierachical_neighbor_allreduce_nonblocking( avg_computation = False handle = getattr(mpi_lib, function)(tensor, output, self_weight, neighbor_weights, send_neighbors, enable_topo_check, avg_computation, - is_hierarchical=True, - name=name.encode() if name is not None else "") + True, name.encode() if name is not None else "") _handle_map[handle] = (tensor, output) return handle From cc4fb1d520bf33ae05c3c7bae02cb30b66aa42ea Mon Sep 17 00:00:00 2001 From: ybc Date: Thu, 22 Oct 2020 21:59:47 -0700 Subject: [PATCH 03/44] Build local nccl comm --- bluefog/common/nccl_controller.cc | 18 +++++++++++++++--- bluefog/common/nccl_controller.h | 7 ++++--- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/bluefog/common/nccl_controller.cc b/bluefog/common/nccl_controller.cc index a2249d80..074c88ee 100644 --- a/bluefog/common/nccl_controller.cc +++ b/bluefog/common/nccl_controller.cc @@ -69,7 +69,8 @@ ncclDataType_t GetNCCLDataType(const DataType bf_data_type) { } void NCCLContext::Initialize(const int rank, const int size, - const int local_rank) { + const int local_rank, const int local_size, + const MPI_Comm& world_comm, const MPI_Comm& local_comm) { if (is_initialized) { BFLOG(DEBUG) << "NCCL context has been initialized but NCCLContext::Initialize " @@ -84,7 +85,7 @@ void NCCLContext::Initialize(const int rank, const int size, ncclUniqueId nccl_id; if (rank == 0) ncclGetUniqueId(&nccl_id); MPICHECK( - MPI_Bcast((void*)&nccl_id, sizeof(nccl_id), MPI_BYTE, 0, MPI_COMM_WORLD)); + MPI_Bcast((void*)&nccl_id, sizeof(nccl_id), MPI_BYTE, 0, world_comm)); // Assume one device per process int nDevices = 0; @@ -96,6 +97,15 @@ void NCCLContext::Initialize(const int rank, const int size, greatest_priority)); // TODO(ybc) Handle the error case then np > number of GPU properly. NCCLCHECK(ncclCommInitRank(&nccl_comm, size, nccl_id, rank)); + MPI_Barrier(world_comm); + + // Build local nccl + ncclUniqueId local_nccl_id; + if (local_rank == 0) ncclGetUniqueId(&local_nccl_id); + MPICHECK(MPI_Bcast((void*)&local_nccl_id, sizeof(local_nccl_id), MPI_BYTE, 0, + local_comm)); + NCCLCHECK(ncclCommInitRank(&nccl_local_comm, local_size, local_nccl_id, + local_rank)); cuda_device = local_rank % nDevices; is_initialized = true; @@ -182,7 +192,9 @@ cudaError_t NCCLContext::ReleaseCudaEvent(cudaEvent_t event) { } void NCCLController::Initialize() { - nccl_ctx_.Initialize(mpi_ctx_.rank_, mpi_ctx_.size_, mpi_ctx_.local_rank_); + nccl_ctx_.Initialize(mpi_ctx_.rank_, mpi_ctx_.size_, mpi_ctx_.local_rank_, + mpi_ctx_.local_size_, mpi_ctx_.mpi_comm, + mpi_ctx_.local_comm); #if NCCL_MINOR < 7 InitPeerCommunicators(); #endif diff --git a/bluefog/common/nccl_controller.h b/bluefog/common/nccl_controller.h index 82ec3f09..7060ebc4 100644 --- a/bluefog/common/nccl_controller.h +++ b/bluefog/common/nccl_controller.h @@ -56,8 +56,9 @@ class NCCLContext { NCCLContext(const NCCLContext&) = delete; NCCLContext& operator=(NCCLContext other) = delete; - void Initialize(const int rank, const int size, - const int local_rank); // only initial nccl_comm etc. + void Initialize(const int rank, const int size, const int local_rank, + const int local_size, const MPI_Comm& world_comm, + const MPI_Comm& local_comm); // only initial nccl_comm etc. void Finalize(); // nccl_comm, peer, window will all be cleaned. #if NCCL_MINOR < 7 void CleanPeerCommunicators(); @@ -67,8 +68,8 @@ class NCCLContext { cudaError_t GetCudaEvent(cudaEvent_t* event); cudaError_t ReleaseCudaEvent(cudaEvent_t event); - // TODO(ybc) Create intra-comm to allow the ops lik in-node allreduce. ncclComm_t nccl_comm; // Store a global nccl comm. + ncclComm_t nccl_local_comm; // Store a local nccl comm. cudaStream_t stream; // We reuse CUDA events as it appears that their creation carries non-zero cost. From 2df368a28b8741af9dc73cc7fafb55f6963fd9a8 Mon Sep 17 00:00:00 2001 From: ybc Date: Thu, 22 Oct 2020 23:06:11 -0700 Subject: [PATCH 04/44] add ihierarchical neighbor allreduce impl in NCCL --- bluefog/common/nccl_controller.cc | 178 ++++++++++++++++++++++-------- bluefog/torch/mpi_ops.cc | 35 ++++-- 2 files changed, 157 insertions(+), 56 deletions(-) diff --git a/bluefog/common/nccl_controller.cc b/bluefog/common/nccl_controller.cc index 074c88ee..8180847d 100644 --- a/bluefog/common/nccl_controller.cc +++ b/bluefog/common/nccl_controller.cc @@ -670,33 +670,70 @@ void NCCLController::NeighborAllreduce(TensorTableEntry& entry) { } #if NCCL_MINOR > 6 - ncclGroupStart(); - if (entry.send_neighbors->empty()) { - for (int i = 0; i < mpi_ctx_.neighbor_indgree_; i++) { - int recv_rank = mpi_ctx_.neighbor_in_ranks_[i]; - void* recvbuf = (void*)(static_cast(entry.output->data()) + - num_elements * i * element_size); - NCCLCHECK(ncclRecv(recvbuf, num_elements, GetNCCLDataType(entry.tensor), - recv_rank, nccl_ctx_.nccl_comm, nccl_ctx_.stream)); - } - for (int send_rank : mpi_ctx_.neighbor_out_ranks_) { - NCCLCHECK(ncclSend(sendbuf, num_elements, GetNCCLDataType(entry.tensor), - send_rank, nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + if (!entry.is_hierarchical) { + ncclGroupStart(); + if (entry.send_neighbors->empty()) { + for (int i = 0; i < mpi_ctx_.neighbor_indgree_; i++) { + int recv_rank = mpi_ctx_.neighbor_in_ranks_[i]; + void* recvbuf = (void*)(static_cast(entry.output->data()) + + num_elements * i * element_size); + NCCLCHECK(ncclRecv(recvbuf, num_elements, GetNCCLDataType(entry.tensor), + recv_rank, nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + } + for (int send_rank : mpi_ctx_.neighbor_out_ranks_) { + NCCLCHECK(ncclSend(sendbuf, num_elements, GetNCCLDataType(entry.tensor), + send_rank, nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + } + } else { + for (size_t i = 0; i < entry.recv_neighbors->size(); ++i) { + int recv_rank = entry.recv_neighbors->at(i); + void* recvbuf = (void*)(static_cast(entry.output->data()) + + num_elements * i * element_size); + NCCLCHECK(ncclRecv(recvbuf, num_elements, GetNCCLDataType(entry.tensor), + recv_rank, nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + } + for (int send_rank : *entry.send_neighbors) { + NCCLCHECK(ncclSend(sendbuf, num_elements, GetNCCLDataType(entry.tensor), + send_rank, nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + } } + ncclGroupEnd(); } else { - for (size_t i = 0; i < entry.recv_neighbors->size(); ++i) { - int recv_rank = entry.recv_neighbors->at(i); - void* recvbuf = (void*)(static_cast(entry.output->data()) + - num_elements * i * element_size); - NCCLCHECK(ncclRecv(recvbuf, num_elements, GetNCCLDataType(entry.tensor), - recv_rank, nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + if (entry.send_neighbors->empty()) { + throw std::runtime_error( + "Under hierachical neighbor_allreduce, argument " + "send_machine_neighbors should " + "not be empty."); } - for (int send_rank : *entry.send_neighbors) { - NCCLCHECK(ncclSend(sendbuf, num_elements, GetNCCLDataType(entry.tensor), - send_rank, nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + // 1. In-place allreduce for all local ranks. Note it is sum, so we need to + // divided by local size at call back stage. + NCCLCHECK(ncclAllReduce(sendbuf, (void*)sendbuf, num_elements, + GetNCCLDataType(entry.tensor), ncclSum, + nccl_ctx_.nccl_local_comm, nccl_ctx_.stream)); + // 2. Local_rank = 0 do the neighbor all with other machines local_rank=0. + if (mpi_ctx_.local_rank_ == 0) { + ncclGroupStart(); + for (size_t i = 0; i < entry.recv_neighbors->size(); ++i) { + int recv_rank = entry.recv_neighbors->at(i); + void* recvbuf = (void*)(static_cast(entry.output->data()) + + num_elements * i * element_size); + NCCLCHECK(ncclRecv(recvbuf, num_elements, GetNCCLDataType(entry.tensor), + recv_rank, nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + } + for (int send_rank : *entry.send_neighbors) { + NCCLCHECK(ncclSend(sendbuf, num_elements, GetNCCLDataType(entry.tensor), + send_rank, nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + } + ncclGroupEnd(); + } else { + // No need to do anything } + // 3. Broadcast recv data from local rank = 0 to other local ranks. + int recv_num_elements = num_elements * entry.recv_neighbors->size(); + NCCLCHECK(ncclBroadcast(entry.output->data(), (void*)entry.output->data(), + recv_num_elements, GetNCCLDataType(entry.output), 0, + nccl_ctx_.nccl_local_comm, nccl_ctx_.stream)); } - ncclGroupEnd(); if (timeline_ptr_->Initialized()) { RecordEvent(event_queue, "COMM. (NCCL)"); @@ -721,7 +758,9 @@ void NCCLController::NeighborAllreduce(TensorTableEntry& entry) { "which doesn't support point-to-point communication. " "Hence, the performance may be largely degraded"; }); - + if (entry.is_hierarchical) { + throw std::runtime_error("Hierachical neighbor allreduce is not supported under NCCL < 2.7"); + } ncclGroupStart(); uint recv_rank_index = 0; uint send_rank_index = 0; @@ -890,37 +929,78 @@ void NCCLController::NeighborAllreduce(std::vector& entries) { // Hence, we need to offset the buffer data to location for neighbors. buffer_data = (uint8_t*)buffer_data + num_elements * element_size; - ncclGroupStart(); - if (first_entry.send_neighbors->empty()) { - for (int i = 0; i < mpi_ctx_.neighbor_indgree_; i++) { - int recv_rank = mpi_ctx_.neighbor_in_ranks_[i]; - void* recvbuf = - (void*)((uint8_t*)buffer_data + num_elements * i * element_size); - NCCLCHECK(ncclRecv(recvbuf, num_elements, - GetNCCLDataType(first_entry.tensor), recv_rank, - nccl_ctx_.nccl_comm, nccl_ctx_.stream)); - } - for (int send_rank : mpi_ctx_.neighbor_out_ranks_) { - NCCLCHECK(ncclSend(fused_input_data, num_elements, - GetNCCLDataType(first_entry.tensor), send_rank, - nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + if (!first_entry.is_hierarchical) { + ncclGroupStart(); + if (first_entry.send_neighbors->empty()) { + for (int i = 0; i < mpi_ctx_.neighbor_indgree_; i++) { + int recv_rank = mpi_ctx_.neighbor_in_ranks_[i]; + void* recvbuf = + (void*)((uint8_t*)buffer_data + num_elements * i * element_size); + NCCLCHECK(ncclRecv(recvbuf, num_elements, + GetNCCLDataType(first_entry.tensor), recv_rank, + nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + } + for (int send_rank : mpi_ctx_.neighbor_out_ranks_) { + NCCLCHECK(ncclSend(fused_input_data, num_elements, + GetNCCLDataType(first_entry.tensor), send_rank, + nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + } + } else { + for (size_t i = 0; i < first_entry.recv_neighbors->size(); ++i) { + int recv_rank = first_entry.recv_neighbors->at(i); + void* recvbuf = + (void*)((uint8_t*)buffer_data + num_elements * i * element_size); + NCCLCHECK(ncclRecv(recvbuf, num_elements, + GetNCCLDataType(first_entry.tensor), recv_rank, + nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + } + for (int send_rank : *first_entry.send_neighbors) { + NCCLCHECK(ncclSend(fused_input_data, num_elements, + GetNCCLDataType(first_entry.tensor), send_rank, + nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + } } + ncclGroupEnd(); } else { - for (size_t i = 0; i < first_entry.recv_neighbors->size(); ++i) { - int recv_rank = first_entry.recv_neighbors->at(i); - void* recvbuf = - (void*)((uint8_t*)buffer_data + num_elements * i * element_size); - NCCLCHECK(ncclRecv(recvbuf, num_elements, - GetNCCLDataType(first_entry.tensor), recv_rank, - nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + if (first_entry.send_neighbors->empty()) { + throw std::runtime_error( + "Under hierachical neighbor_allreduce, argument " + "send_machine_neighbors should not be empty."); } - for (int send_rank : *first_entry.send_neighbors) { - NCCLCHECK(ncclSend(fused_input_data, num_elements, - GetNCCLDataType(first_entry.tensor), send_rank, - nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + + // 1. In-place allreduce for all local ranks. Note it is sum, so we need to + // divided by local size at call back stage. + NCCLCHECK(ncclAllReduce(fused_input_data, (void*)fused_input_data, + num_elements, GetNCCLDataType(first_entry.tensor), + ncclSum, nccl_ctx_.nccl_local_comm, + nccl_ctx_.stream)); + // 2. Local_rank = 0 do the neighbor all with other machines local_rank=0. + if (mpi_ctx_.local_rank_ == 0) { + ncclGroupStart(); + for (size_t i = 0; i < first_entry.recv_neighbors->size(); ++i) { + int recv_rank = first_entry.recv_neighbors->at(i); + void* recvbuf = + (void*)((uint8_t*)buffer_data + num_elements * i * element_size); + NCCLCHECK(ncclRecv(recvbuf, num_elements, + GetNCCLDataType(first_entry.tensor), recv_rank, + nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + } + for (int send_rank : *first_entry.send_neighbors) { + NCCLCHECK(ncclSend(fused_input_data, num_elements, + GetNCCLDataType(first_entry.tensor), send_rank, + nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + } + ncclGroupEnd(); + } else { + // No need to do anything } + // 3. Broadcast recv data from local rank = 0 to other local ranks. + int recv_num_elements = num_elements * first_entry.recv_neighbors->size(); + NCCLCHECK(ncclBroadcast(buffer_data, (void*)buffer_data, recv_num_elements, + GetNCCLDataType(first_entry.output), 0, + nccl_ctx_.nccl_local_comm, nccl_ctx_.stream)); } - ncclGroupEnd(); + if (timeline_ptr_->Initialized()) { RecordEvent(event_queue, "COMM. (NCCL)"); } diff --git a/bluefog/torch/mpi_ops.cc b/bluefog/torch/mpi_ops.cc index 07ea7266..8c1d283b 100644 --- a/bluefog/torch/mpi_ops.cc +++ b/bluefog/torch/mpi_ops.cc @@ -36,6 +36,7 @@ using ::bluefog::common::bluefog_load_topology_weights; using ::bluefog::common::bluefog_neighbor_size; using ::bluefog::common::bluefog_rank; using ::bluefog::common::bluefog_size; +using ::bluefog::common::bluefog_local_size; using ::bluefog::common::with_device; using ::bluefog::common::GetBluefogTimeline; using ::bluefog::common::Status; @@ -344,7 +345,7 @@ int DoNeighborAllreduce(::torch::Tensor tensor, ::torch::Tensor output, CPU_DEVICE_ID, callback_wrapper([self_weight, neighbor_weights, avg_computation, cpu_output, tensor, recv_neighbors, send_neighbors, - output, device]() mutable { + is_hierarchical, output, device]() mutable { with_device device_guard(device); output.copy_(cpu_output); int recv_size = bluefog_neighbor_size(); @@ -402,6 +403,10 @@ int DoNeighborAllreduce(::torch::Tensor tensor, ::torch::Tensor output, } output_buffer.resize_(shape_vector); output_buffer.add_(tensor_buffer.mul(self_weight)); + if (is_hierarchical){ + // Because there is ncclAllreduce just take sum. + output_buffer.div_(bluefog_local_size()); + } } else { int neighbor_size = send_neighbors.empty() ? bluefog_neighbor_size() @@ -416,7 +421,12 @@ int DoNeighborAllreduce(::torch::Tensor tensor, ::torch::Tensor output, } // Include self data as well. output_buffer.add_(tensor_buffer); - output_buffer.div_(neighbor_size + 1); + if (is_hierarchical){ + // Because there is ncclAllreduce just take sum. + output_buffer.div_(bluefog_local_size() * (neighbor_size + 1)); + } else { + output_buffer.div_(neighbor_size + 1); + } } output.resize_(shape_vector); MaybeCopyBufferBack(output, output_buffer); @@ -433,11 +443,13 @@ int DoNeighborAllreduce(::torch::Tensor tensor, ::torch::Tensor output, auto ready_event = RecordReadyEvent(device); auto enqueue_result = EnqueueTensorNeighborAllreduce( - bf_tensor, bf_output, bf_context, ready_event, bf_recv_neighbors, bf_send_neighbors, - is_hierarchical, enable_topo_check, op_name, device, callback_wrapper([self_weight, neighbor_weights, - avg_computation, recv_neighbors, send_neighbors, tensor, output] () mutable { + bf_tensor, bf_output, bf_context, ready_event, bf_recv_neighbors, + bf_send_neighbors, is_hierarchical, enable_topo_check, op_name, device, + callback_wrapper([self_weight, neighbor_weights, avg_computation, + recv_neighbors, send_neighbors, is_hierarchical, + tensor, output]() mutable { int recv_size = bluefog_neighbor_size(); - if(!send_neighbors.empty()) recv_size = recv_neighbors.size(); + if (!send_neighbors.empty()) recv_size = recv_neighbors.size(); if (recv_size > 0) { ::torch::Tensor output_buffer = MaybeCopyToTensorBuffer(output); ::torch::Tensor tensor_buffer = MaybeCopyToTensorBuffer(tensor); @@ -481,6 +493,10 @@ int DoNeighborAllreduce(::torch::Tensor tensor, ::torch::Tensor output, } output_buffer.resize_(shape_vector); output_buffer.add_(tensor_buffer.mul(self_weight)); + if (is_hierarchical){ + // Because there is ncclAllreduce just take sum. + output_buffer.div_(bluefog_local_size()); + } } else { int neighbor_size = send_neighbors.empty() ? bluefog_neighbor_size() @@ -495,7 +511,12 @@ int DoNeighborAllreduce(::torch::Tensor tensor, ::torch::Tensor output, output_buffer.resize_(shape_vector); // Include self data as well. output_buffer.add_(tensor_buffer); - output_buffer.div_(neighbor_size + 1); + if (is_hierarchical){ + // Because there is ncclAllreduce just take sum. + output_buffer.div_(bluefog_local_size() * (neighbor_size + 1)); + } else { + output_buffer.div_(neighbor_size + 1); + } } output.resize_(shape_vector); MaybeCopyBufferBack(output, output_buffer); From 1e61f3c924a3de20c7c50c8ebc37f3174e05d87e Mon Sep 17 00:00:00 2001 From: ybc Date: Thu, 22 Oct 2020 23:30:14 -0700 Subject: [PATCH 05/44] export hierachical_neighbor_allreduce --- bluefog/torch/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bluefog/torch/__init__.py b/bluefog/torch/__init__.py index 2c813909..028396ab 100644 --- a/bluefog/torch/__init__.py +++ b/bluefog/torch/__init__.py @@ -47,6 +47,8 @@ from bluefog.torch.mpi_ops import broadcast_, broadcast_nonblocking_ from bluefog.torch.mpi_ops import neighbor_allgather, neighbor_allgather_nonblocking from bluefog.torch.mpi_ops import neighbor_allreduce, neighbor_allreduce_nonblocking +from bluefog.torch.mpi_ops import hierachical_neighbor_allreduce +from bluefog.torch.mpi_ops import hierachical_neighbor_allreduce_nonblocking from bluefog.torch.mpi_ops import pair_gossip, pair_gossip_nonblocking from bluefog.torch.mpi_ops import poll, synchronize, barrier From aafdf11521b74330d791ff80cad5147747c62697 Mon Sep 17 00:00:00 2001 From: ybc Date: Thu, 22 Oct 2020 23:41:25 -0700 Subject: [PATCH 06/44] Update mpi_ops.py --- bluefog/torch/mpi_ops.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bluefog/torch/mpi_ops.py b/bluefog/torch/mpi_ops.py index a600f4c0..56ab667a 100644 --- a/bluefog/torch/mpi_ops.py +++ b/bluefog/torch/mpi_ops.py @@ -527,8 +527,10 @@ def hierachical_neighbor_allreduce(tensor: torch.Tensor, self_weight: float, neighbor_machine_weights: Dict[int, float], send_neighbor_machines: List[int], - enable_topo_check: bool = True, + enable_topo_check: bool = False, name: Optional[str] = None) -> torch.Tensor: + # TODO(hhb) Implement the logics for topo check for hierachical_neighbor_allreduce. + # TODO(ybc) add check for self_weight and neighbor_machine_weights. if (self_weight is None and neighbor_machine_weights is not None) or \ (self_weight is not None and send_neighbor_machines is None): @@ -544,7 +546,7 @@ def hierachical_neighbor_allreduce_nonblocking(tensor: torch.Tensor, self_weight: float, neighbor_machine_weights: Dict[int, float], send_neighbor_machines: List[int], - enable_topo_check: bool = True, + enable_topo_check: bool = False, name: Optional[str] = None) -> int: if (self_weight is None or neighbor_machine_weights is None): raise ValueError("Arguments self_weight and neighbor_weights cannot be empty or None.") @@ -565,7 +567,7 @@ def hierachical_neighbor_allreduce_nonblocking(tensor: torch.Tensor, def _hierachical_neighbor_allreduce_nonblocking( tensor, output, self_weight, neighbor_machine_weights, send_neighbor_machines, enable_topo_check, name): - assert not is_homogeneous, \ + assert is_homogeneous, \ "hierachical_neighbor_allreduce should be used under homogeneous environment only" function = _check_function(_neighbor_allreduce_function_factory, tensor) if self_weight is not None and neighbor_machine_weights is not None: From d7f1d014865409cc93a24353179c886d3dfdc005 Mon Sep 17 00:00:00 2001 From: ybc Date: Thu, 22 Oct 2020 23:48:52 -0700 Subject: [PATCH 07/44] remove extra avg_computation in hierachical nar --- bluefog/torch/mpi_ops.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bluefog/torch/mpi_ops.py b/bluefog/torch/mpi_ops.py index 56ab667a..ba8294ff 100644 --- a/bluefog/torch/mpi_ops.py +++ b/bluefog/torch/mpi_ops.py @@ -411,10 +411,10 @@ def _neighbor_allreduce_nonblocking(tensor, output, self_weight, neighbor_weight else: raise ValueError("Arguments self_weight and neighbor_weights have to be presented at " "the same time") - + is_hierachical = False handle = getattr(mpi_lib, function)(tensor, output, self_weight, neighbor_weights, send_neighbors, enable_topo_check, avg_computation, - False, name.encode() if name is not None else "") + is_hierachical, name.encode() if name is not None else "") _handle_map[handle] = (tensor, output) return handle @@ -587,16 +587,15 @@ def _hierachical_neighbor_allreduce_nonblocking( break else: raise ValueError("Arguments self_weight and neighbor_weights cannot be empty or None.") - # Translate machine id into rank id. node_per_machine = local_size() neighbor_weights = { node_per_machine*m: weights for (m, weights) in neighbor_machine_weights.items()} send_neighbors = [node_per_machine*m for m in send_neighbor_machines] - avg_computation = False + is_hierachical = True handle = getattr(mpi_lib, function)(tensor, output, self_weight, neighbor_weights, send_neighbors, enable_topo_check, avg_computation, - True, name.encode() if name is not None else "") + is_hierachical, name.encode() if name is not None else "") _handle_map[handle] = (tensor, output) return handle From b4dd476d43ebc0103acc2ba39eb75160f75bbb45 Mon Sep 17 00:00:00 2001 From: ybc Date: Fri, 23 Oct 2020 00:02:03 -0700 Subject: [PATCH 08/44] fix the typo of hierarchical --- bluefog/common/mpi_controller.cc | 4 +-- bluefog/common/nccl_controller.cc | 6 ++--- bluefog/torch/__init__.py | 4 +-- bluefog/torch/mpi_ops.py | 42 +++++++++++++++---------------- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/bluefog/common/mpi_controller.cc b/bluefog/common/mpi_controller.cc index efc2a215..3757854d 100644 --- a/bluefog/common/mpi_controller.cc +++ b/bluefog/common/mpi_controller.cc @@ -362,7 +362,7 @@ void MPIController::NeighborAllreduce(TensorTableEntry& entry) { // TODO(ybc) support this if (entry.is_hierarchical) { throw std::runtime_error( - "Hierachical neighbor_allreduce is only supported under NCCL case."); + "hierarchical neighbor_allreduce is only supported under NCCL case."); } Timeline* timeline_ptr; @@ -492,7 +492,7 @@ void MPIController::NeighborAllreduce(std::vector& entries) { // TODO(ybc) support this if (first_entry.is_hierarchical) { throw std::runtime_error( - "Hierachical neighbor_allreduce is only supported under NCCL case."); + "hierarchical neighbor_allreduce is only supported under NCCL case."); } void* buffer_data; diff --git a/bluefog/common/nccl_controller.cc b/bluefog/common/nccl_controller.cc index 8180847d..5b3b5860 100644 --- a/bluefog/common/nccl_controller.cc +++ b/bluefog/common/nccl_controller.cc @@ -701,7 +701,7 @@ void NCCLController::NeighborAllreduce(TensorTableEntry& entry) { } else { if (entry.send_neighbors->empty()) { throw std::runtime_error( - "Under hierachical neighbor_allreduce, argument " + "Under hierarchical neighbor_allreduce, argument " "send_machine_neighbors should " "not be empty."); } @@ -759,7 +759,7 @@ void NCCLController::NeighborAllreduce(TensorTableEntry& entry) { "Hence, the performance may be largely degraded"; }); if (entry.is_hierarchical) { - throw std::runtime_error("Hierachical neighbor allreduce is not supported under NCCL < 2.7"); + throw std::runtime_error("hierarchical neighbor allreduce is not supported under NCCL < 2.7"); } ncclGroupStart(); uint recv_rank_index = 0; @@ -964,7 +964,7 @@ void NCCLController::NeighborAllreduce(std::vector& entries) { } else { if (first_entry.send_neighbors->empty()) { throw std::runtime_error( - "Under hierachical neighbor_allreduce, argument " + "Under hierarchical neighbor_allreduce, argument " "send_machine_neighbors should not be empty."); } diff --git a/bluefog/torch/__init__.py b/bluefog/torch/__init__.py index 028396ab..b7596b51 100644 --- a/bluefog/torch/__init__.py +++ b/bluefog/torch/__init__.py @@ -47,8 +47,8 @@ from bluefog.torch.mpi_ops import broadcast_, broadcast_nonblocking_ from bluefog.torch.mpi_ops import neighbor_allgather, neighbor_allgather_nonblocking from bluefog.torch.mpi_ops import neighbor_allreduce, neighbor_allreduce_nonblocking -from bluefog.torch.mpi_ops import hierachical_neighbor_allreduce -from bluefog.torch.mpi_ops import hierachical_neighbor_allreduce_nonblocking +from bluefog.torch.mpi_ops import hierarchical_neighbor_allreduce +from bluefog.torch.mpi_ops import hierarchical_neighbor_allreduce_nonblocking from bluefog.torch.mpi_ops import pair_gossip, pair_gossip_nonblocking from bluefog.torch.mpi_ops import poll, synchronize, barrier diff --git a/bluefog/torch/mpi_ops.py b/bluefog/torch/mpi_ops.py index ba8294ff..757e433b 100644 --- a/bluefog/torch/mpi_ops.py +++ b/bluefog/torch/mpi_ops.py @@ -411,10 +411,10 @@ def _neighbor_allreduce_nonblocking(tensor, output, self_weight, neighbor_weight else: raise ValueError("Arguments self_weight and neighbor_weights have to be presented at " "the same time") - is_hierachical = False + is_hierarchical = False handle = getattr(mpi_lib, function)(tensor, output, self_weight, neighbor_weights, send_neighbors, enable_topo_check, avg_computation, - is_hierachical, name.encode() if name is not None else "") + is_hierarchical, name.encode() if name is not None else "") _handle_map[handle] = (tensor, output) return handle @@ -523,31 +523,31 @@ def neighbor_allreduce_nonblocking(tensor: torch.Tensor, send_neighbors, enable_topo_check, name=name) -def hierachical_neighbor_allreduce(tensor: torch.Tensor, - self_weight: float, - neighbor_machine_weights: Dict[int, float], - send_neighbor_machines: List[int], - enable_topo_check: bool = False, - name: Optional[str] = None) -> torch.Tensor: - # TODO(hhb) Implement the logics for topo check for hierachical_neighbor_allreduce. +def hierarchical_neighbor_allreduce(tensor: torch.Tensor, + self_weight: float, + neighbor_machine_weights: Dict[int, float], + send_neighbor_machines: List[int], + enable_topo_check: bool = False, + name: Optional[str] = None) -> torch.Tensor: + # TODO(hhb) Implement the logics for topo check for hierarchical_neighbor_allreduce. # TODO(ybc) add check for self_weight and neighbor_machine_weights. if (self_weight is None and neighbor_machine_weights is not None) or \ (self_weight is not None and send_neighbor_machines is None): raise ValueError("Arguments self_weight and neighbor_machine_weights have to " "be presented at the same time") - handle = hierachical_neighbor_allreduce_nonblocking( + handle = hierarchical_neighbor_allreduce_nonblocking( tensor, self_weight, neighbor_machine_weights, send_neighbor_machines, enable_topo_check, name) return synchronize(handle) -def hierachical_neighbor_allreduce_nonblocking(tensor: torch.Tensor, - self_weight: float, - neighbor_machine_weights: Dict[int, float], - send_neighbor_machines: List[int], - enable_topo_check: bool = False, - name: Optional[str] = None) -> int: +def hierarchical_neighbor_allreduce_nonblocking(tensor: torch.Tensor, + self_weight: float, + neighbor_machine_weights: Dict[int, float], + send_neighbor_machines: List[int], + enable_topo_check: bool = False, + name: Optional[str] = None) -> int: if (self_weight is None or neighbor_machine_weights is None): raise ValueError("Arguments self_weight and neighbor_weights cannot be empty or None.") if (self_weight is None and neighbor_machine_weights is not None) or \ @@ -559,16 +559,16 @@ def hierachical_neighbor_allreduce_nonblocking(tensor: torch.Tensor, new_shape = torch.Size([first_dim] + list(tensor.shape[1:])) output = tensor.new(new_shape) # Pre-allocate the memory for the output. - return _hierachical_neighbor_allreduce_nonblocking( + return _hierarchical_neighbor_allreduce_nonblocking( tensor, output, self_weight, neighbor_machine_weights, send_neighbor_machines, enable_topo_check, name=name) -def _hierachical_neighbor_allreduce_nonblocking( +def _hierarchical_neighbor_allreduce_nonblocking( tensor, output, self_weight, neighbor_machine_weights, send_neighbor_machines, enable_topo_check, name): assert is_homogeneous, \ - "hierachical_neighbor_allreduce should be used under homogeneous environment only" + "hierarchical_neighbor_allreduce should be used under homogeneous environment only" function = _check_function(_neighbor_allreduce_function_factory, tensor) if self_weight is not None and neighbor_machine_weights is not None: if not isinstance(neighbor_machine_weights, dict): @@ -592,10 +592,10 @@ def _hierachical_neighbor_allreduce_nonblocking( neighbor_weights = { node_per_machine*m: weights for (m, weights) in neighbor_machine_weights.items()} send_neighbors = [node_per_machine*m for m in send_neighbor_machines] - is_hierachical = True + is_hierarchical = True handle = getattr(mpi_lib, function)(tensor, output, self_weight, neighbor_weights, send_neighbors, enable_topo_check, avg_computation, - is_hierachical, name.encode() if name is not None else "") + is_hierarchical, name.encode() if name is not None else "") _handle_map[handle] = (tensor, output) return handle From 85d9e971e1440a82e978b1eceb123d0f85a768a8 Mon Sep 17 00:00:00 2001 From: ybc Date: Fri, 23 Oct 2020 00:05:32 -0700 Subject: [PATCH 09/44] build DistributedHierarchicalNeighborAllreduceOptimizer --- bluefog/torch/__init__.py | 1 + bluefog/torch/optimizers.py | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/bluefog/torch/__init__.py b/bluefog/torch/__init__.py index b7596b51..f5f2e8e0 100644 --- a/bluefog/torch/__init__.py +++ b/bluefog/torch/__init__.py @@ -26,6 +26,7 @@ DistributedGradientAllreduceOptimizer, DistributedAllreduceOptimizer, DistributedNeighborAllreduceOptimizer, + DistributedHierarchicalNeighborAllreduceOptimizer, DistributedPushSumOptimizer, DistributedPullGetOptimizer, DistributedBluefogOptimizer) diff --git a/bluefog/torch/optimizers.py b/bluefog/torch/optimizers.py index 210262cc..66f12477 100644 --- a/bluefog/torch/optimizers.py +++ b/bluefog/torch/optimizers.py @@ -295,10 +295,14 @@ def __init__(self, params, model, reduce_type, num_steps_per_communication=1): super(self.__class__, self).__init__(params) named_parameters, models = _check_named_parameters(self, model) - self.neighbor_weights = None + # knobs for neighbor communication behavior self.self_weight = None + self.neighbor_weights = None self.send_neighbors = None + self.neighbor_machine_weights = None + self.send_neighbor_machines = None self.enable_topo_check = False + self._models = models self._parameter_names = {v: k for k, v in sorted(named_parameters)} self._handles = {} @@ -314,6 +318,8 @@ def __init__(self, params, model, reduce_type, num_steps_per_communication=1): self._reduce_method = 0 elif self._reduce_type_str == "neighbor.allreduce": self._reduce_method = 1 + elif self._reduce_type_str == "hierarchical.neighbor.allreduce": + self._reduce_method = 2 else: raise ValueError("Unknown reduce type for internal class _DistributedReduceOptimizer") @@ -352,6 +358,8 @@ def hook(module, *unused): handle = self._allreduce_data_async(p) elif self._reduce_method == 1: handle = self._neighbor_allreduce_data_async(p) + elif self._reduce_method == 2: + handle = self._hierarchical_neighbor_allreduce_data_async(p) else: raise ValueError( "Unknown reduce method. Do not change _reduce_method manually.") @@ -366,6 +374,15 @@ def _neighbor_allreduce_data_async(self, p): enable_topo_check=self.enable_topo_check) return handle + def _hierarchical_neighbor_allreduce_data_async(self, p): + name = self._parameter_names.get(p) + handle = bf.hierarchical_neighbor_allreduce_nonblocking( + p.data, name=name, self_weight=self.self_weight, + neighbor_machine_weights=self.neighbor_machine_weights, + send_neighbor_machines=self.send_neighbor_machines, + enable_topo_check=self.enable_topo_check) + return handle + def _allreduce_data_async(self, p): name = self._parameter_names.get(p) handle = bf.allreduce_nonblocking(p.data, average=True, name=name) @@ -389,6 +406,9 @@ def use_allreduce_in_communication(self): def use_neighbor_allreduce_in_communication(self): self._reduce_method = 1 + def use_hierarchical_neighbor_allreduce_in_communication(self): + self._reduce_method = 2 + def synchronize(self): with torch.no_grad(): for p, handle in self._handles.items(): @@ -791,6 +811,7 @@ def DistributedPushSumOptimizer(optimizer, model, ) return cls(optimizer.param_groups, model, num_steps_per_communication) + def DistributedPullGetOptimizer(optimizer, model, num_steps_per_communication=1): """ @@ -890,6 +911,7 @@ def DistributedBluefogOptimizer(optimizer, model, ) return cls(optimizer.param_groups, model, num_steps_per_communication, pull_style=False) + def DistributedAllreduceOptimizer(optimizer, model, num_steps_per_communication=1): """ @@ -984,6 +1006,17 @@ def DistributedNeighborAllreduceOptimizer(optimizer, model, return cls(optimizer.param_groups, model, "neighbor.allreduce", num_steps_per_communication) +def DistributedHierarchicalNeighborAllreduceOptimizer(optimizer, model, + num_steps_per_communication=1): + cls = type( + optimizer.__class__.__name__, + (optimizer.__class__,), + dict(_DistributedReduceOptimizer.__dict__), + ) + return cls(optimizer.param_groups, model, "hierarchical.neighbor.allreduce", + num_steps_per_communication) + + def DistributedGradientAllreduceOptimizer(optimizer, model, backward_passes_per_step=1): """ From f80cabf9bb0ae5d90690dcb63d9c2dd5e65801b5 Mon Sep 17 00:00:00 2001 From: ybc Date: Fri, 23 Oct 2020 17:40:13 -0700 Subject: [PATCH 10/44] Add GetExp2DynamicSendRecvMachineRanks --- bluefog/common/topology_util.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/bluefog/common/topology_util.py b/bluefog/common/topology_util.py index 08be77ba..4997afeb 100644 --- a/bluefog/common/topology_util.py +++ b/bluefog/common/topology_util.py @@ -430,6 +430,25 @@ def GetDynamicSendRecvRanks( index += 1 +def GetExp2DynamicSendRecvMachineRanks( + world_size: int, local_size: int, self_rank: int, local_rank: int + ) -> Iterator[Tuple[List[int], List[int]]]: + assert (self_rank % local_size) == local_rank, \ + "It should be used under homogeneous environment only." + assert (world_size % local_size) == 0, \ + "It should be used under homogeneous environment only." + machine_id = self_rank // local_size + machine_size = world_size // local_size + exp_2_size = int(np.log2(machine_size-1)) + index = 0 + while True: + machine_dist = 2**(index % (exp_2_size + 1)) + send_machine_rank = (machine_id + machine_dist) % machine_size + recv_machine_ranks = (machine_id - machine_dist) % machine_size + yield [send_machine_rank], [recv_machine_ranks] + index += 1 + + def GetInnerOuterRingDynamicSendRecvRanks( world_size: int, local_size: int, self_rank: int ) -> Iterator[Tuple[List[int], List[int]]]: From bb9fa0056946f1381bb06af831ec14de3d92c80b Mon Sep 17 00:00:00 2001 From: ybc Date: Fri, 23 Oct 2020 17:54:43 -0700 Subject: [PATCH 11/44] Add hierarchical_neighbor_allreduce --- examples/pytorch_cifar10_resnet.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/examples/pytorch_cifar10_resnet.py b/examples/pytorch_cifar10_resnet.py index 014b948b..adb18919 100644 --- a/examples/pytorch_cifar10_resnet.py +++ b/examples/pytorch_cifar10_resnet.py @@ -74,9 +74,9 @@ "--no-cuda", action="store_true", default=False, help="disables CUDA training" ) parser.add_argument("--seed", type=int, default=42, help="random seed") -parser.add_argument('--dist-optimizer', type=str, default='win_put', +parser.add_argument('--dist-optimizer', type=str, default='hierarchical_neighbor_allreduce', help='The type of distributed optimizer. Supporting options are ' + - '[win_put, neighbor_allreduce, allreduce, pull_get, push_sum, horovod]') + '[win_put, neighbor_allreduce, allreduce, pull_get, hierarchical_neighbor_allreduce, horovod]') parser.add_argument("--average-test-result", action="store_true", default=False, help=("Allreduce called to average test result. Warning this will " + @@ -226,6 +226,9 @@ elif args.dist_optimizer == 'gradient_allreduce': optimizer = optimizer = bf.DistributedGradientAllreduceOptimizer( optimizer, model=model) +elif args.dist_optimizer == 'hierarchical_neighbor_allreduce': + optimizer = optimizer = bf.DistributedHierarchicalNeighborAllreduceOptimizer( + optimizer, model=model) elif args.dist_optimizer == 'push_sum': optimizer = bf.DistributedPushSumOptimizer(optimizer, model=model) elif args.dist_optimizer == 'horovod': @@ -356,6 +359,14 @@ def adjust_learning_rate(epoch, batch_idx): bf.size(), local_size=bf.local_size() if args.local_size == -1 else args.local_size, self_rank=bf.rank()) + elif args.dist_optimizer == 'hierarchical_neighbor_allreduce': + # This optimizer can use only, + dynamic_machine_neighbor_allreduce_gen = topology_util.GetExp2DynamicSendRecvMachineRanks( + world_size=bf.size(), + local_size=bf.local_size(), + self_rank=bf.rank(), + local_rank=bf.local_rank() + ) else: dynamic_neighbor_allreduce_gen = topology_util.GetDynamicSendRecvRanks( bf.load_topology(), bf.rank()) @@ -386,6 +397,12 @@ def dynamic_topology_update(epoch, batch_idx): optimizer.neighbor_weights = {r: 1/(len(recv_neighbors) + 1) for r in recv_neighbors} optimizer.self_weight = 1 / (len(recv_neighbors) + 1) optimizer.enable_topo_check = False + elif args.dist_optimizer == 'hierarchical_neighbor_allreduce': + send_machines, recv_machines = next(dynamic_machine_neighbor_allreduce_gen) + optimizer.send_neighbor_machines = send_machines + optimizer.neighbor_machine_weights = {r: 1/(len(recv_neighbors) + 1) for r in recv_neighbors} + optimizer.self_weight = 1 / (len(recv_neighbors) + 1) + optimizer.enable_topo_check = False else: pass From aa53d06c9bae7289c5c30e13beb79cab4a8988ce Mon Sep 17 00:00:00 2001 From: ybc Date: Fri, 23 Oct 2020 18:02:43 -0700 Subject: [PATCH 12/44] Update pytorch_cifar10_resnet.py --- examples/pytorch_cifar10_resnet.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/pytorch_cifar10_resnet.py b/examples/pytorch_cifar10_resnet.py index adb18919..094bdae7 100644 --- a/examples/pytorch_cifar10_resnet.py +++ b/examples/pytorch_cifar10_resnet.py @@ -400,8 +400,8 @@ def dynamic_topology_update(epoch, batch_idx): elif args.dist_optimizer == 'hierarchical_neighbor_allreduce': send_machines, recv_machines = next(dynamic_machine_neighbor_allreduce_gen) optimizer.send_neighbor_machines = send_machines - optimizer.neighbor_machine_weights = {r: 1/(len(recv_neighbors) + 1) for r in recv_neighbors} - optimizer.self_weight = 1 / (len(recv_neighbors) + 1) + optimizer.neighbor_machine_weights = {r: 1/(len(recv_machines) + 1) for r in recv_machines} + optimizer.self_weight = 1 / (len(recv_machines) + 1) optimizer.enable_topo_check = False else: pass From 869f609273e37fb25406cb119310bda8914fb521 Mon Sep 17 00:00:00 2001 From: ybc Date: Fri, 23 Oct 2020 19:11:27 -0700 Subject: [PATCH 13/44] Copy input for hier nar due to in-place allreduce --- bluefog/torch/mpi_ops.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bluefog/torch/mpi_ops.py b/bluefog/torch/mpi_ops.py index 757e433b..8e165766 100644 --- a/bluefog/torch/mpi_ops.py +++ b/bluefog/torch/mpi_ops.py @@ -592,11 +592,12 @@ def _hierarchical_neighbor_allreduce_nonblocking( neighbor_weights = { node_per_machine*m: weights for (m, weights) in neighbor_machine_weights.items()} send_neighbors = [node_per_machine*m for m in send_neighbor_machines] + tensor_buffer = tensor.detach().clone() is_hierarchical = True - handle = getattr(mpi_lib, function)(tensor, output, self_weight, neighbor_weights, + handle = getattr(mpi_lib, function)(tensor_buffer, output, self_weight, neighbor_weights, send_neighbors, enable_topo_check, avg_computation, is_hierarchical, name.encode() if name is not None else "") - _handle_map[handle] = (tensor, output) + _handle_map[handle] = (tensor_buffer, output) return handle From 2e04cbfad4da555d005e11667990d878e536659f Mon Sep 17 00:00:00 2001 From: ybc Date: Sat, 24 Oct 2020 15:34:55 -0700 Subject: [PATCH 14/44] Update pytorch_cifar10_resnet.py --- examples/pytorch_cifar10_resnet.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/pytorch_cifar10_resnet.py b/examples/pytorch_cifar10_resnet.py index 094bdae7..1eb5a76b 100644 --- a/examples/pytorch_cifar10_resnet.py +++ b/examples/pytorch_cifar10_resnet.py @@ -112,11 +112,11 @@ elif args.virtual_topology == "InnerOuterRing": assert bf.is_homogeneous, "InnerOuterRing topo should be used only homogeneous environment" bf.set_topology(topology_util.InnerOuterRingGraph( - bf.size(), local_size=bf.local_size() if args.local_size == -1 else args.local_size)) + bf.size(), local_size=bf.local_size())) elif args.virtual_topology == "InnerOuterExp2": assert bf.is_homogeneous, "InnerOuterExp2 topo should be used under homogeneous environment" bf.set_topology(topology_util.InnerOuterExp2Graph( - bf.size(), local_size=bf.local_size() if args.local_size == -1 else args.local_size)) + bf.size(), local_size=bf.local_size())) else: raise ValueError("Unknown args.virtual_topology, supporting options are " + "[power2(Default), ring, mesh, star,InnerOuterRing, InnerOuterExp2].") @@ -352,12 +352,12 @@ def adjust_learning_rate(epoch, batch_idx): if args.virtual_topology == 'InnerOuterRing': dynamic_neighbor_allreduce_gen = topology_util.GetInnerOuterRingDynamicSendRecvRanks( bf.size(), - local_size=bf.local_size() if args.local_size == -1 else args.local_size, + local_size=bf.local_size(), self_rank=bf.rank()) elif args.virtual_topology == 'InnerOuterExp2': dynamic_neighbor_allreduce_gen = topology_util.GetInnerOuterExp2DynamicSendRecvRanks( bf.size(), - local_size=bf.local_size() if args.local_size == -1 else args.local_size, + local_size=bf.local_size(), self_rank=bf.rank()) elif args.dist_optimizer == 'hierarchical_neighbor_allreduce': # This optimizer can use only, From b88dde3e707d57a5ceb277169b49f0d3e01bb9a5 Mon Sep 17 00:00:00 2001 From: ybc Date: Sat, 24 Oct 2020 16:07:08 -0700 Subject: [PATCH 15/44] Copy fused input back to input for fused hier n_ar --- bluefog/common/nccl_controller.cc | 21 ++++++++++++++++++++- bluefog/common/nccl_controller.h | 3 +++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/bluefog/common/nccl_controller.cc b/bluefog/common/nccl_controller.cc index 5b3b5860..5561af50 100644 --- a/bluefog/common/nccl_controller.cc +++ b/bluefog/common/nccl_controller.cc @@ -991,8 +991,10 @@ void NCCLController::NeighborAllreduce(std::vector& entries) { nccl_ctx_.nccl_comm, nccl_ctx_.stream)); } ncclGroupEnd(); + MemcpyOutFusionBufferForInputs(fused_input_data, entries); } else { - // No need to do anything + // Because the in-place modification, we need to copy fused_input_data back to tensor as well + MemcpyOutFusionBufferForInputs(fused_input_data, entries); } // 3. Broadcast recv data from local rank = 0 to other local ranks. int recv_num_elements = num_elements * first_entry.recv_neighbors->size(); @@ -1004,6 +1006,7 @@ void NCCLController::NeighborAllreduce(std::vector& entries) { if (timeline_ptr_->Initialized()) { RecordEvent(event_queue, "COMM. (NCCL)"); } + // Remember buffer_data is already pointed at offset location (after self // tensor). int num_recv_neighbors = first_entry.send_neighbors->empty() @@ -1798,6 +1801,22 @@ void NCCLController::MemcpyOutFusionBufferForNeighbors( } } +void NCCLController::MemcpyOutFusionBufferForInputs( + const void* fused_input_data, std::vector& entries) { + // Copy the input data stored in the fusion buffer back to input, which is + // used in hierarchical neighbor allreduce since it has allreduce step to + // modified the input data. + int64_t offset = 0; + for (auto& e : entries) { + void* fused_input_data_at_offset = (uint8_t*)fused_input_data + offset; + void* dst_data = (void*)e.tensor->data(); + size_t count = (size_t)e.tensor->size(); + CUDACHECK(cudaMemcpyAsync(dst_data, fused_input_data_at_offset, count, + cudaMemcpyDeviceToDevice, nccl_ctx_.stream)); + offset += e.tensor->size(); + } +} + void NCCLController::MemcpyEntryInFusionBuffer(const TensorTableEntry& e, void* buffer_data_at_offset) { const void* src_data = e.tensor->data(); diff --git a/bluefog/common/nccl_controller.h b/bluefog/common/nccl_controller.h index 7060ebc4..3835a3d4 100644 --- a/bluefog/common/nccl_controller.h +++ b/bluefog/common/nccl_controller.h @@ -188,6 +188,9 @@ class NCCLController { const int num_recv_neighbors, const int64_t fused_data_size); + void MemcpyOutFusionBufferForInputs(const void* fused_input_data, + std::vector& entries); + void MemcpyEntryInFusionBuffer(const TensorTableEntry& e, void* buffer_data_at_offset); From 96214e5688c321be2c097b67bdee989780a66183 Mon Sep 17 00:00:00 2001 From: ybc Date: Sat, 24 Oct 2020 16:59:46 -0700 Subject: [PATCH 16/44] Use local rank 0 to recv and local rank 1 to send in h n_ar --- bluefog/common/nccl_controller.cc | 20 +++++++++++++++----- bluefog/torch/mpi_ops.py | 1 + 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/bluefog/common/nccl_controller.cc b/bluefog/common/nccl_controller.cc index 5561af50..72540998 100644 --- a/bluefog/common/nccl_controller.cc +++ b/bluefog/common/nccl_controller.cc @@ -967,6 +967,12 @@ void NCCLController::NeighborAllreduce(std::vector& entries) { "Under hierarchical neighbor_allreduce, argument " "send_machine_neighbors should not be empty."); } + if (mpi_ctx_.local_size_ < 2) { + throw std::runtime_error( + "Local size is smaller than 2, in this case, you should use " + "neighbor_allreduce instead of hierarchical_neighbor_allreduce." + ); + } // 1. In-place allreduce for all local ranks. Note it is sum, so we need to // divided by local size at call back stage. @@ -976,26 +982,30 @@ void NCCLController::NeighborAllreduce(std::vector& entries) { nccl_ctx_.stream)); // 2. Local_rank = 0 do the neighbor all with other machines local_rank=0. if (mpi_ctx_.local_rank_ == 0) { + // Use rank 0 for receiving ncclGroupStart(); - for (size_t i = 0; i < first_entry.recv_neighbors->size(); ++i) { + for (size_t i = 0; i < first_entry.recv_neighbors->size(); ++i) { int recv_rank = first_entry.recv_neighbors->at(i); void* recvbuf = (void*)((uint8_t*)buffer_data + num_elements * i * element_size); NCCLCHECK(ncclRecv(recvbuf, num_elements, - GetNCCLDataType(first_entry.tensor), recv_rank, + GetNCCLDataType(first_entry.tensor), recv_rank+1, nccl_ctx_.nccl_comm, nccl_ctx_.stream)); } + ncclGroupEnd(); + } else if (mpi_ctx_.local_rank_ == 1) { + ncclGroupStart(); for (int send_rank : *first_entry.send_neighbors) { NCCLCHECK(ncclSend(fused_input_data, num_elements, GetNCCLDataType(first_entry.tensor), send_rank, nccl_ctx_.nccl_comm, nccl_ctx_.stream)); } ncclGroupEnd(); - MemcpyOutFusionBufferForInputs(fused_input_data, entries); } else { - // Because the in-place modification, we need to copy fused_input_data back to tensor as well - MemcpyOutFusionBufferForInputs(fused_input_data, entries); + // Do nothing } + // Because the in-place modification, we need to copy fused_input_data back to tensor as well + MemcpyOutFusionBufferForInputs(fused_input_data, entries); // 3. Broadcast recv data from local rank = 0 to other local ranks. int recv_num_elements = num_elements * first_entry.recv_neighbors->size(); NCCLCHECK(ncclBroadcast(buffer_data, (void*)buffer_data, recv_num_elements, diff --git a/bluefog/torch/mpi_ops.py b/bluefog/torch/mpi_ops.py index 8e165766..81da35b3 100644 --- a/bluefog/torch/mpi_ops.py +++ b/bluefog/torch/mpi_ops.py @@ -569,6 +569,7 @@ def _hierarchical_neighbor_allreduce_nonblocking( send_neighbor_machines, enable_topo_check, name): assert is_homogeneous, \ "hierarchical_neighbor_allreduce should be used under homogeneous environment only" + assert local_size() > 1, "If local size is 1, you should use neighbor allreduce directorly." function = _check_function(_neighbor_allreduce_function_factory, tensor) if self_weight is not None and neighbor_machine_weights is not None: if not isinstance(neighbor_machine_weights, dict): From 95fd66cc2d69c9092f07a0f5cc85bec8e4406670 Mon Sep 17 00:00:00 2001 From: ybc Date: Sat, 24 Oct 2020 17:32:04 -0700 Subject: [PATCH 17/44] Add h n_ar to other examples and enable dynamic => disable args --- bluefog/common/nccl_controller.cc | 3 ++- examples/pytorch_benchmark.py | 28 +++++++++++++++++++++++----- examples/pytorch_cifar10_resnet.py | 12 ++++++------ examples/pytorch_mnist.py | 29 +++++++++++++++++++++++------ 4 files changed, 54 insertions(+), 18 deletions(-) diff --git a/bluefog/common/nccl_controller.cc b/bluefog/common/nccl_controller.cc index 72540998..f0e525fb 100644 --- a/bluefog/common/nccl_controller.cc +++ b/bluefog/common/nccl_controller.cc @@ -982,7 +982,7 @@ void NCCLController::NeighborAllreduce(std::vector& entries) { nccl_ctx_.stream)); // 2. Local_rank = 0 do the neighbor all with other machines local_rank=0. if (mpi_ctx_.local_rank_ == 0) { - // Use rank 0 for receiving + // Use local rank 0 for receiving ncclGroupStart(); for (size_t i = 0; i < first_entry.recv_neighbors->size(); ++i) { int recv_rank = first_entry.recv_neighbors->at(i); @@ -994,6 +994,7 @@ void NCCLController::NeighborAllreduce(std::vector& entries) { } ncclGroupEnd(); } else if (mpi_ctx_.local_rank_ == 1) { + // Use local rank 0 for sending ncclGroupStart(); for (int send_rank : *first_entry.send_neighbors) { NCCLCHECK(ncclSend(fused_input_data, num_elements, diff --git a/examples/pytorch_benchmark.py b/examples/pytorch_benchmark.py index 5a68c953..1681cf8b 100644 --- a/examples/pytorch_benchmark.py +++ b/examples/pytorch_benchmark.py @@ -55,9 +55,10 @@ help='partition size') parser.add_argument('--dist-optimizer', type=str, default='win_put', help='The type of distributed optimizer. Supporting options are ' + - '[win_put(default), neighbor_allreduce, allreduce, pull_get, push_sum, horovod]') -parser.add_argument('--enable-dynamic-topology', action='store_true', - default=False, help=('Enable each iteration to transmit one neighbor ' + + '[win_put(default), neighbor_allreduce, allreduce, ' + + 'hierarchical_neighbor_allreduce, pull_get, push_sum, horovod]') +parser.add_argument('--disable-dynamic-topology', action='store_true', + default=False, help=('Disable each iteration to transmit one neighbor ' + 'per iteration dynamically.')) parser.add_argument('--virtual-topology', type=str, default="power2", help='The underlying virtual topology. Supporting options are ' + @@ -142,6 +143,9 @@ def forward(self, x): optimizer, model=model) elif args.dist_optimizer == 'push_sum': optimizer = bf.DistributedPushSumOptimizer(optimizer, model=model) +elif args.dist_optimizer == 'hierarchical_neighbor_allreduce': + optimizer = optimizer = bf.DistributedHierarchicalNeighborAllreduceOptimizer( + optimizer, model=model) elif args.dist_optimizer == 'horovod': optimizer = optimizer = bf.DistributedOptimizer( optimizer, named_parameters=model.named_parameters() @@ -176,7 +180,7 @@ def forward(self, x): data_index = 0 -if args.enable_dynamic_topology and args.dist_optimizer != 'horovod': +if not args.disable_dynamic_topology and (args.dist_optimizer != 'horovod'): if args.virtual_topology == 'InnerOuterRing': dynamic_neighbor_allreduce_gen = topology_util.GetInnerOuterRingDynamicSendRecvRanks( bf.size(), @@ -187,6 +191,14 @@ def forward(self, x): bf.size(), local_size=bf.local_size() if args.local_size == -1 else args.local_size, self_rank=bf.rank()) + elif args.dist_optimizer == 'hierarchical_neighbor_allreduce': + # This optimizer can use following dynamic topo only so far. + dynamic_machine_neighbor_allreduce_gen = topology_util.GetExp2DynamicSendRecvMachineRanks( + world_size=bf.size(), + local_size=bf.local_size(), + self_rank=bf.rank(), + local_rank=bf.local_rank() + ) else: dynamic_neighbor_allreduce_gen = topology_util.GetDynamicSendRecvRanks( bf.load_topology(), bf.rank()) @@ -212,6 +224,12 @@ def dynamic_topology_update(batch_idx): optimizer.neighbor_weights = { r: 1/(len(recv_neighbors) + 1) for r in recv_neighbors} optimizer.self_weight = 1 / (len(recv_neighbors) + 1) + optimizer.enable_topo_check = False + elif args.dist_optimizer == 'hierarchical_neighbor_allreduce': + send_machines, recv_machines = next(dynamic_machine_neighbor_allreduce_gen) + optimizer.send_neighbor_machines = send_machines + optimizer.neighbor_machine_weights = {r: 1/(len(recv_machines) + 1) for r in recv_machines} + optimizer.self_weight = 1 / (len(recv_machines) + 1) optimizer.enable_topo_check = False else: pass @@ -220,7 +238,7 @@ def dynamic_topology_update(batch_idx): def benchmark_step(): global data_index - if args.enable_dynamic_topology: + if not args.disable_dynamic_topology: dynamic_topology_update(data_index) data = datasets[data_index % len(datasets)] data_index += 1 diff --git a/examples/pytorch_cifar10_resnet.py b/examples/pytorch_cifar10_resnet.py index 1eb5a76b..d2c7f62b 100644 --- a/examples/pytorch_cifar10_resnet.py +++ b/examples/pytorch_cifar10_resnet.py @@ -81,9 +81,9 @@ default=False, help=("Allreduce called to average test result. Warning this will " + "force the algorithm to sync every end of epoch.")) -parser.add_argument("--enable-dynamic-topology", action="store_true", - default=False, help=("Enable each iteration to transmit one neighbor " + - "per iteration dynamically.")) +parser.add_argument('--disable-dynamic-topology', action='store_true', + default=False, help=('Disable each iteration to transmit one neighbor ' + + 'per iteration dynamically.')) parser.add_argument('--virtual-topology', type=str, default="power2", help='The underlying virtual topology. Supporting options are ' + '[power2(Default), ring, mesh, star].') @@ -267,7 +267,7 @@ def train(epoch): disable=not verbose,) as t: for batch_idx, (data, target) in enumerate(train_loader): adjust_learning_rate(epoch, batch_idx) - if args.enable_dynamic_topology: + if not args.disable_dynamic_topology: dynamic_topology_update(epoch, batch_idx) if args.cuda: @@ -348,7 +348,7 @@ def adjust_learning_rate(epoch, batch_idx): args.base_lr * bf.size() * args.batches_per_allreduce * lr_adj ) -if args.enable_dynamic_topology and args.dist_optimizer != 'horovod': +if not args.disable_dynamic_topology and (args.dist_optimizer != 'horovod'): if args.virtual_topology == 'InnerOuterRing': dynamic_neighbor_allreduce_gen = topology_util.GetInnerOuterRingDynamicSendRecvRanks( bf.size(), @@ -360,7 +360,7 @@ def adjust_learning_rate(epoch, batch_idx): local_size=bf.local_size(), self_rank=bf.rank()) elif args.dist_optimizer == 'hierarchical_neighbor_allreduce': - # This optimizer can use only, + # This optimizer can use following dynamic topo only so far. dynamic_machine_neighbor_allreduce_gen = topology_util.GetExp2DynamicSendRecvMachineRanks( world_size=bf.size(), local_size=bf.local_size(), diff --git a/examples/pytorch_mnist.py b/examples/pytorch_mnist.py index 460f9fe7..84f7a2b1 100644 --- a/examples/pytorch_mnist.py +++ b/examples/pytorch_mnist.py @@ -62,9 +62,9 @@ default=False, help=("Allreduce called to average test result. Warning this will " + "force the algorithm to sync every end of epoch.")) -parser.add_argument("--enable-dynamic-topology", action="store_true", - default=False, help=("Enable each iteration to transmit one neighbor " + - "per iteration dynamically.")) +parser.add_argument('--disable-dynamic-topology', action='store_true', + default=False, help=('Disable each iteration to transmit one neighbor ' + + 'per iteration dynamically.')) parser.add_argument('--virtual-topology', type=str, default="power2", help='The underlying virtual topology. Supporting options are ' + '[power2(Default), ring, mesh, star, InnerOuterRing, InnerOuterExp2].') @@ -203,6 +203,9 @@ def forward(self, x): elif args.dist_optimizer == 'gradient_allreduce': optimizer = optimizer = bf.DistributedGradientAllreduceOptimizer( optimizer, model=model) +elif args.dist_optimizer == 'hierarchical_neighbor_allreduce': + optimizer = optimizer = bf.DistributedHierarchicalNeighborAllreduceOptimizer( + optimizer, model=model) elif args.dist_optimizer == 'push_sum': optimizer = bf.DistributedPushSumOptimizer(optimizer, model=model) elif args.dist_optimizer == 'horovod': @@ -217,7 +220,7 @@ def forward(self, x): '[neighbor_allreduce, gradient_allreduce, allreduce, ' + 'win_put, push_sum, horovod]') -if args.enable_dynamic_topology and args.dist_optimizer != 'horovod': +if not args.disable_dynamic_topology and (args.dist_optimizer != 'horovod'): if args.virtual_topology == 'InnerOuterRing': dynamic_neighbor_allreduce_gen = topology_util.GetInnerOuterRingDynamicSendRecvRanks( bf.size(), @@ -227,7 +230,15 @@ def forward(self, x): dynamic_neighbor_allreduce_gen = topology_util.GetInnerOuterExp2DynamicSendRecvRanks( bf.size(), local_size=bf.local_size() if args.local_size == -1 else args.local_size, - self_rank=bf.rank()) + self_rank=bf.rank()) + elif args.dist_optimizer == 'hierarchical_neighbor_allreduce': + # This optimizer can use following dynamic topo only so far. + dynamic_machine_neighbor_allreduce_gen = topology_util.GetExp2DynamicSendRecvMachineRanks( + world_size=bf.size(), + local_size=bf.local_size(), + self_rank=bf.rank(), + local_rank=bf.local_rank() + ) else: dynamic_neighbor_allreduce_gen = topology_util.GetDynamicSendRecvRanks( bf.load_topology(), bf.rank()) @@ -256,6 +267,12 @@ def dynamic_topology_update(epoch, batch_idx): optimizer.neighbor_weights = {r: 1/(len(recv_neighbors) + 1) for r in recv_neighbors} optimizer.self_weight = 1 / (len(recv_neighbors) + 1) optimizer.enable_topo_check = False + elif args.dist_optimizer == 'hierarchical_neighbor_allreduce': + send_machines, recv_machines = next(dynamic_machine_neighbor_allreduce_gen) + optimizer.send_neighbor_machines = send_machines + optimizer.neighbor_machine_weights = {r: 1/(len(recv_machines) + 1) for r in recv_machines} + optimizer.self_weight = 1 / (len(recv_machines) + 1) + optimizer.enable_topo_check = False else: pass @@ -265,7 +282,7 @@ def train(epoch): # Bluefog: set epoch to sampler for shuffling. train_sampler.set_epoch(epoch) for batch_idx, (data, target) in enumerate(train_loader): - if args.enable_dynamic_topology: + if not args.disable_dynamic_topology: dynamic_topology_update(epoch, batch_idx) if args.cuda: data, target = data.cuda(), target.cuda() From 2c65cefd34bea1bb74b7374125d67f6519a3bad6 Mon Sep 17 00:00:00 2001 From: ybc Date: Sat, 24 Oct 2020 21:52:46 -0700 Subject: [PATCH 18/44] fix the directly typo --- bluefog/torch/mpi_ops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bluefog/torch/mpi_ops.py b/bluefog/torch/mpi_ops.py index 81da35b3..04ab7784 100644 --- a/bluefog/torch/mpi_ops.py +++ b/bluefog/torch/mpi_ops.py @@ -569,7 +569,7 @@ def _hierarchical_neighbor_allreduce_nonblocking( send_neighbor_machines, enable_topo_check, name): assert is_homogeneous, \ "hierarchical_neighbor_allreduce should be used under homogeneous environment only" - assert local_size() > 1, "If local size is 1, you should use neighbor allreduce directorly." + assert local_size() > 1, "If local size is 1, you should use neighbor allreduce directly." function = _check_function(_neighbor_allreduce_function_factory, tensor) if self_weight is not None and neighbor_machine_weights is not None: if not isinstance(neighbor_machine_weights, dict): From 5c73e70fee8c5643ff5e022852c5d26bffae808e Mon Sep 17 00:00:00 2001 From: ybc Date: Sun, 25 Oct 2020 13:56:01 -0700 Subject: [PATCH 19/44] Fix the mesh topo usage --- examples/pytorch_ImageNet_Resnet50.py | 6 +++--- examples/pytorch_benchmark.py | 6 +++--- examples/pytorch_cifar10_resnet.py | 6 +++--- examples/pytorch_mnist.py | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/pytorch_ImageNet_Resnet50.py b/examples/pytorch_ImageNet_Resnet50.py index bf0618c1..3aabdb0c 100644 --- a/examples/pytorch_ImageNet_Resnet50.py +++ b/examples/pytorch_ImageNet_Resnet50.py @@ -91,10 +91,10 @@ if args.virtual_topology == "power2": pass elif args.virtual_topology == "ring": - bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=0)) + bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=1)) elif args.virtual_topology == "mesh": - bf.set_topology(topology_util.RingGraph( - bf.size(), connect_style=0), is_weighted=True) + bf.set_topology(topology_util.MeshGrid2DGraph( + bf.size()), is_weighted=True) elif args.virtual_topology == "star": bf.set_topology(topology_util.StarGraph(bf.size())) else: diff --git a/examples/pytorch_benchmark.py b/examples/pytorch_benchmark.py index 1681cf8b..15158271 100644 --- a/examples/pytorch_benchmark.py +++ b/examples/pytorch_benchmark.py @@ -77,10 +77,10 @@ if args.virtual_topology == "power2": pass elif args.virtual_topology == "ring": - bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=0)) + bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=1)) elif args.virtual_topology == "mesh": - bf.set_topology(topology_util.RingGraph( - bf.size(), connect_style=0), is_weighted=True) + bf.set_topology(topology_util.MeshGrid2DGraph( + bf.size()), is_weighted=True) elif args.virtual_topology == "star": bf.set_topology(topology_util.StarGraph(bf.size())) elif args.virtual_topology == "InnerOuterRing": diff --git a/examples/pytorch_cifar10_resnet.py b/examples/pytorch_cifar10_resnet.py index d2c7f62b..e801d30a 100644 --- a/examples/pytorch_cifar10_resnet.py +++ b/examples/pytorch_cifar10_resnet.py @@ -103,10 +103,10 @@ if args.virtual_topology == "power2": pass elif args.virtual_topology == "ring": - bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=0)) + bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=1)) elif args.virtual_topology == "mesh": - bf.set_topology(topology_util.RingGraph( - bf.size(), connect_style=0), is_weighted=True) + bf.set_topology(topology_util.MeshGrid2DGraph( + bf.size()), is_weighted=True) elif args.virtual_topology == "star": bf.set_topology(topology_util.StarGraph(bf.size())) elif args.virtual_topology == "InnerOuterRing": diff --git a/examples/pytorch_mnist.py b/examples/pytorch_mnist.py index 84f7a2b1..a80d97ed 100644 --- a/examples/pytorch_mnist.py +++ b/examples/pytorch_mnist.py @@ -93,10 +93,10 @@ if args.virtual_topology == "power2": pass elif args.virtual_topology == "ring": - bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=0)) + bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=1)) elif args.virtual_topology == "mesh": - bf.set_topology(topology_util.RingGraph( - bf.size(), connect_style=0), is_weighted=True) + bf.set_topology(topology_util.MeshGrid2DGraph( + bf.size()), is_weighted=True) elif args.virtual_topology == "star": bf.set_topology(topology_util.StarGraph(bf.size())) elif args.virtual_topology == "InnerOuterRing": From f6df8e14dc1a03e3148b2bb961fd93fbc1816485 Mon Sep 17 00:00:00 2001 From: ybc Date: Sun, 25 Oct 2020 17:59:24 -0700 Subject: [PATCH 20/44] Update the comments for hier n_ar --- bluefog/torch/mpi_ops.py | 80 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 4 deletions(-) diff --git a/bluefog/torch/mpi_ops.py b/bluefog/torch/mpi_ops.py index 04ab7784..e0f599ee 100644 --- a/bluefog/torch/mpi_ops.py +++ b/bluefog/torch/mpi_ops.py @@ -437,7 +437,7 @@ def neighbor_allreduce(tensor: torch.Tensor, are ready to send and receive the tensor. Arguments: - tensor: A tensor to weighted average. + tensor: A tensor to execute weighted average with neighbors. self_weight: The weight for self node, used with neighbor_weights. neighbor_weights: The weights for in-neighbor nodes, used with self weight. If neighbor_weights is presented, the return tensor will return the weighted average @@ -486,7 +486,7 @@ def neighbor_allreduce_nonblocking(tensor: torch.Tensor, are ready to send and receive the tensor. Arguments: - tensor: A tensor to neighbor_allreduce. + tensor: A tensor to execute weighted average with neighbors. self_weight: The weight for self node, used with neighbor_weights. neighbor_weights: The weights for in-neighbor nodes, used with self weight. If neighbor_weights is presented, the return tensor will return the weighted average @@ -529,6 +529,38 @@ def hierarchical_neighbor_allreduce(tensor: torch.Tensor, send_neighbor_machines: List[int], enable_topo_check: bool = False, name: Optional[str] = None) -> torch.Tensor: + """ + A function that performs weighted averaging of the input tensor over the negihbor machines and + itself in the Bluefog processes. It is similar to neighbor_allreduce except each machine, + containing multiple processes, runs allreduce internal to form a super node then executes the + neighbor allreduce. The default behavior is (uniformly) average. + + The input tensor is not modified. + + The reduction operation is keyed by the name. If name is not provided, an incremented + auto-generated name is used. The tensor type and shape must be the same on all + Bluefog processes for a given name. The reduction will not start until all processes + are ready to send and receive the tensor. + + Warning: This function should be called only under homogenerous environment, all machines have + same number of Bluefog processes -- bf.local_size(). + + Arguments: + tensor: A tensor to execute weighted average with neighbor machines. + self_weight: The weight for self node, used with neighbor_weights. + neighbor_machine_weights: The weights for in-neighbor nodes, used with self weight. + The data structure of weights should be {machine id : weight}. All processes under + same machine should specifiy the same weights dictionary. + send_neighbor_machines: The list of neighbor machines to be sent to. All processes under + same machine should specifiy the same machine id. + enable_topo_check: When send_neighbors is present, enabling this option checks if the + sending and recieving neighbors match with each other. Disabling this check can boost + the performance. + name: A name of the reduction operation. + + Returns: + A tensor of the same shape and type as `tensor`, across all processes. + """ # TODO(hhb) Implement the logics for topo check for hierarchical_neighbor_allreduce. # TODO(ybc) add check for self_weight and neighbor_machine_weights. @@ -548,6 +580,39 @@ def hierarchical_neighbor_allreduce_nonblocking(tensor: torch.Tensor, send_neighbor_machines: List[int], enable_topo_check: bool = False, name: Optional[str] = None) -> int: + """ + A function that nonblockingly performs weighted averaging of the input tensor over the negihbor + machines and itself in the Bluefog processes. It is similar to neighbor_allreduce except each + machine containing multiple processes, runs allreduce internal to form a super node then executes + the neighbor allreduce. The default behavior is (uniformly) average. + + The input tensor is not modified. + + The reduction operation is keyed by the name. If name is not provided, an incremented + auto-generated name is used. The tensor type and shape must be the same on all + Bluefog processes for a given name. The reduction will not start until all processes + are ready to send and receive the tensor. + + Warning: This function should be called only under homogenerous environment, all machines have + same number of Bluefog processes -- bf.local_size(). + + Arguments: + tensor: A tensor to execute weighted average with neighbor machines. + self_weight: The weight for self node, used with neighbor_weights. + neighbor_machine_weights: The weights for in-neighbor nodes, used with self weight. + The data structure of weights should be {machine id : weight}. All processes under + same machine should specifiy the same weights dictionary. + send_neighbor_machines: The list of neighbor machines to be sent to. All processes under + same machine should specifiy the same machine id. + enable_topo_check: When send_neighbors is present, enabling this option checks if the + sending and recieving neighbors match with each other. Disabling this check can boost + the performance. + name: A name of the reduction operation. + + Returns: + A handle to the hierarchical_neighbor_allreduce operation that can be used with `poll()` or + `synchronize()`. + """ if (self_weight is None or neighbor_machine_weights is None): raise ValueError("Arguments self_weight and neighbor_weights cannot be empty or None.") if (self_weight is None and neighbor_machine_weights is not None) or \ @@ -588,10 +653,17 @@ def _hierarchical_neighbor_allreduce_nonblocking( break else: raise ValueError("Arguments self_weight and neighbor_weights cannot be empty or None.") + + machine_size = size() // local_size() # Translate machine id into rank id. node_per_machine = local_size() - neighbor_weights = { - node_per_machine*m: weights for (m, weights) in neighbor_machine_weights.items()} + neighbor_weights = {} + for (m, weights) in neighbor_machine_weights.items(): + if m >= machine_size: + raise ValueError( + f"machine id is larger than number of machine we detected ({node_per_machine})." + "Note it is 0-based index.") + neighbor_weights[node_per_machine*m] = weights send_neighbors = [node_per_machine*m for m in send_neighbor_machines] tensor_buffer = tensor.detach().clone() is_hierarchical = True From f5d5f65698148fb75d4292b07e73f45a08ac7c99 Mon Sep 17 00:00:00 2001 From: ybc Date: Sun, 25 Oct 2020 18:23:54 -0700 Subject: [PATCH 21/44] Add is_hierarchical to request message --- bluefog/common/message.cc | 4 ++++ bluefog/common/message.h | 4 ++++ bluefog/common/operations.cc | 25 +++++++++++++++++++++++++ bluefog/common/wire/message.fbs | 3 +++ bluefog/common/wire/message_generated.h | 20 ++++++++++++++++---- 5 files changed, 52 insertions(+), 4 deletions(-) diff --git a/bluefog/common/message.cc b/bluefog/common/message.cc index 99bb22cc..82cfa6e0 100644 --- a/bluefog/common/message.cc +++ b/bluefog/common/message.cc @@ -96,6 +96,10 @@ int32_t Request::device() const { return device_; } void Request::set_device(int32_t value) { device_ = value; } +bool Request::is_hierarchical() const { return is_hierarchical_; } + +void Request::set_is_hierarchical(bool value) { is_hierarchical_ = value; } + const std::vector& Request::tensor_shape() const { return tensor_shape_; } diff --git a/bluefog/common/message.h b/bluefog/common/message.h index d60a5524..b24063df 100644 --- a/bluefog/common/message.h +++ b/bluefog/common/message.h @@ -70,6 +70,9 @@ class Request { int32_t device() const; void set_device(int32_t value); + bool is_hierarchical() const; + void set_is_hierarchical(bool value); + const std::vector& tensor_shape() const; void set_tensor_shape(const std::vector& value); void add_tensor_shape(int64_t value); @@ -84,6 +87,7 @@ class Request { DataType tensor_type_ = DataType::BLUEFOG_UINT8; int32_t root_rank_ = 0; int32_t device_ = 0; + bool is_hierarchical_ = false; std::string tensor_name_; std::vector tensor_shape_; }; diff --git a/bluefog/common/operations.cc b/bluefog/common/operations.cc index ae4fb970..93d85ca3 100644 --- a/bluefog/common/operations.cc +++ b/bluefog/common/operations.cc @@ -163,6 +163,25 @@ bool CheckRequestRootRank(const std::vector& requests, return error; } +bool CheckRequestIsHierarchical(const std::vector& requests, + std::ostringstream& error_message_stream) { + auto message_type = requests[0].request_type(); + bool error = false; + int first_is_hierarchical = requests[0].is_hierarchical(); + for (unsigned int i = 1; i < requests.size(); i++) { + int this_is_hierarchical = requests[i].is_hierarchical(); + if (first_is_hierarchical != this_is_hierarchical) { + error = true; + error_message_stream + << "Mismatched " << Request::RequestType_Name(message_type) + << " is_hierarchical. Some ranks specified for hierarchical ops " + << " but some ranks are not."; + break; + } + } + return error; +} + bool CheckRequestTensorShape(const std::vector& requests, std::ostringstream& error_message_stream) { bool error = false; @@ -297,6 +316,11 @@ Response ConstructResponse(MessageTable* message_table, std::string name) { } // TODO(ybc) add check for is_hierarchical for neighbor_allreduce. + if(!error) { + if(message_type == Request::NEIGHBOR_ALLREDUCE) { + error = CheckRequestIsHierarchical(requests, error_message_stream); + } + } // If we are doing an (neighbor_)allreduce or broadcast, check that all tensor // shapes are identical. @@ -1497,6 +1521,7 @@ Status EnqueueTensorNeighborAllreduce(std::shared_ptr tensor, message.set_tensor_type(tensor->dtype()); message.set_device(device); message.set_request_type(Request::NEIGHBOR_ALLREDUCE); + message.set_is_hierarchical(is_hierarchical); for (int i = 0; i < tensor->shape().dims(); i++) { message.add_tensor_shape((int64_t)tensor->shape().dim_size(i)); } diff --git a/bluefog/common/wire/message.fbs b/bluefog/common/wire/message.fbs index 8c8a64b0..abe876ad 100644 --- a/bluefog/common/wire/message.fbs +++ b/bluefog/common/wire/message.fbs @@ -67,6 +67,9 @@ table Request { // We use a repeated integer to represent the tensor shape. tensor_shape:[long]; + + // Indicates it is hierarchical operation or not. + is_hierarchical: bool; } table RequestList { requests:[Request]; diff --git a/bluefog/common/wire/message_generated.h b/bluefog/common/wire/message_generated.h index 57ec519c..4c54de00 100644 --- a/bluefog/common/wire/message_generated.h +++ b/bluefog/common/wire/message_generated.h @@ -199,7 +199,8 @@ struct Request FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_TENSOR_NAME = 10, VT_ROOT_RANK = 12, VT_DEVICE = 14, - VT_TENSOR_SHAPE = 16 + VT_TENSOR_SHAPE = 16, + VT_IS_HIERARCHICAL = 18 }; int32_t request_rank() const { return GetField(VT_REQUEST_RANK, 0); @@ -222,6 +223,9 @@ struct Request FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const flatbuffers::Vector *tensor_shape() const { return GetPointer *>(VT_TENSOR_SHAPE); } + bool is_hierarchical() const { + return GetField(VT_IS_HIERARCHICAL, 0) != 0; + } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyField(verifier, VT_REQUEST_RANK) && @@ -233,6 +237,7 @@ struct Request FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VerifyField(verifier, VT_DEVICE) && VerifyOffset(verifier, VT_TENSOR_SHAPE) && verifier.VerifyVector(tensor_shape()) && + VerifyField(verifier, VT_IS_HIERARCHICAL) && verifier.EndTable(); } }; @@ -262,6 +267,9 @@ struct RequestBuilder { void add_tensor_shape(flatbuffers::Offset> tensor_shape) { fbb_.AddOffset(Request::VT_TENSOR_SHAPE, tensor_shape); } + void add_is_hierarchical(bool is_hierarchical) { + fbb_.AddElement(Request::VT_IS_HIERARCHICAL, static_cast(is_hierarchical), 0); + } explicit RequestBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); @@ -282,13 +290,15 @@ inline flatbuffers::Offset CreateRequest( flatbuffers::Offset tensor_name = 0, int32_t root_rank = 0, int32_t device = 0, - flatbuffers::Offset> tensor_shape = 0) { + flatbuffers::Offset> tensor_shape = 0, + bool is_hierarchical = false) { RequestBuilder builder_(_fbb); builder_.add_tensor_shape(tensor_shape); builder_.add_device(device); builder_.add_root_rank(root_rank); builder_.add_tensor_name(tensor_name); builder_.add_request_rank(request_rank); + builder_.add_is_hierarchical(is_hierarchical); builder_.add_tensor_type(tensor_type); builder_.add_request_type(request_type); return builder_.Finish(); @@ -302,7 +312,8 @@ inline flatbuffers::Offset CreateRequestDirect( const char *tensor_name = nullptr, int32_t root_rank = 0, int32_t device = 0, - const std::vector *tensor_shape = nullptr) { + const std::vector *tensor_shape = nullptr, + bool is_hierarchical = false) { auto tensor_name__ = tensor_name ? _fbb.CreateString(tensor_name) : 0; auto tensor_shape__ = tensor_shape ? _fbb.CreateVector(*tensor_shape) : 0; return bluefog::common::wire::CreateRequest( @@ -313,7 +324,8 @@ inline flatbuffers::Offset CreateRequestDirect( tensor_name__, root_rank, device, - tensor_shape__); + tensor_shape__, + is_hierarchical); } struct RequestList FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { From 4489a9dd2f9be3b111130126c30390ab44c2df37 Mon Sep 17 00:00:00 2001 From: ybc Date: Sun, 25 Oct 2020 19:45:04 -0700 Subject: [PATCH 22/44] fix the is_hierarchical usage in request --- bluefog/common/message.cc | 2 ++ bluefog/common/operations.cc | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/bluefog/common/message.cc b/bluefog/common/message.cc index 82cfa6e0..b36cff16 100644 --- a/bluefog/common/message.cc +++ b/bluefog/common/message.cc @@ -122,6 +122,7 @@ void Request_ParseFromWire(Request& request, request.set_tensor_name(obj->tensor_name()->str()); request.set_root_rank(obj->root_rank()); request.set_device(obj->device()); + request.set_is_hierarchical(obj->is_hierarchical()); request.set_tensor_shape(std::vector(obj->tensor_shape()->begin(), obj->tensor_shape()->end())); } @@ -141,6 +142,7 @@ void Request_SerializeToWire(const Request& request, request_builder.add_tensor_name(tensor_name_wire); request_builder.add_root_rank(request.root_rank()); request_builder.add_device(request.device()); + request_builder.add_is_hierarchical(request.is_hierarchical()); request_builder.add_tensor_shape(tensor_shape_wire); obj = request_builder.Finish(); } diff --git a/bluefog/common/operations.cc b/bluefog/common/operations.cc index 93d85ca3..5273e2e5 100644 --- a/bluefog/common/operations.cc +++ b/bluefog/common/operations.cc @@ -167,14 +167,14 @@ bool CheckRequestIsHierarchical(const std::vector& requests, std::ostringstream& error_message_stream) { auto message_type = requests[0].request_type(); bool error = false; - int first_is_hierarchical = requests[0].is_hierarchical(); + bool first_is_hierarchical = requests[0].is_hierarchical(); for (unsigned int i = 1; i < requests.size(); i++) { - int this_is_hierarchical = requests[i].is_hierarchical(); + bool this_is_hierarchical = requests[i].is_hierarchical(); if (first_is_hierarchical != this_is_hierarchical) { error = true; error_message_stream << "Mismatched " << Request::RequestType_Name(message_type) - << " is_hierarchical. Some ranks specified for hierarchical ops " + << " is_hierarchical ops. Some ranks specified for hierarchical ops " << " but some ranks are not."; break; } From 4344a103fd1027ada0ba7fd00320da17216c0538 Mon Sep 17 00:00:00 2001 From: ybc Date: Sun, 25 Oct 2020 22:20:03 -0700 Subject: [PATCH 23/44] Update GetExp2DynamicSendRecvMachineRanks in 2 machines case --- bluefog/common/topology_util.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bluefog/common/topology_util.py b/bluefog/common/topology_util.py index 4997afeb..73cc30f9 100644 --- a/bluefog/common/topology_util.py +++ b/bluefog/common/topology_util.py @@ -437,9 +437,12 @@ def GetExp2DynamicSendRecvMachineRanks( "It should be used under homogeneous environment only." assert (world_size % local_size) == 0, \ "It should be used under homogeneous environment only." + assert world_size > local_size, \ + "It should be used under at least two machines case." + machine_id = self_rank // local_size machine_size = world_size // local_size - exp_2_size = int(np.log2(machine_size-1)) + exp_2_size = int(np.log2(machine_size-1)) if machine_size > 1 else 0 index = 0 while True: machine_dist = 2**(index % (exp_2_size + 1)) From 510210a361a66dd48366bcfc4c13306618e44a1c Mon Sep 17 00:00:00 2001 From: ybc Date: Sun, 25 Oct 2020 22:27:49 -0700 Subject: [PATCH 24/44] Update hier n_ar comments --- bluefog/torch/mpi_ops.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bluefog/torch/mpi_ops.py b/bluefog/torch/mpi_ops.py index e0f599ee..6c3b7609 100644 --- a/bluefog/torch/mpi_ops.py +++ b/bluefog/torch/mpi_ops.py @@ -531,9 +531,9 @@ def hierarchical_neighbor_allreduce(tensor: torch.Tensor, name: Optional[str] = None) -> torch.Tensor: """ A function that performs weighted averaging of the input tensor over the negihbor machines and - itself in the Bluefog processes. It is similar to neighbor_allreduce except each machine, - containing multiple processes, runs allreduce internal to form a super node then executes the - neighbor allreduce. The default behavior is (uniformly) average. + itself in the Bluefog processes. It is similar to neighbor_allreduce. But each machine runs + allreduce internal first to form a super node then executes the neighbor allreduce at machine + level. The default behavior is (uniformly) average. The input tensor is not modified. @@ -582,9 +582,9 @@ def hierarchical_neighbor_allreduce_nonblocking(tensor: torch.Tensor, name: Optional[str] = None) -> int: """ A function that nonblockingly performs weighted averaging of the input tensor over the negihbor - machines and itself in the Bluefog processes. It is similar to neighbor_allreduce except each - machine containing multiple processes, runs allreduce internal to form a super node then executes - the neighbor allreduce. The default behavior is (uniformly) average. + machines and itself in the Bluefog processes. It is similar to neighbor_allreduce. But + each machine runs allreduce internal first to form a super node then executes + the neighbor allreduce at machine level. The default behavior is (uniformly) average. The input tensor is not modified. From 726b06e547285f8930f4e529da10867c86b91612 Mon Sep 17 00:00:00 2001 From: ybc Date: Sun, 25 Oct 2020 23:28:26 -0700 Subject: [PATCH 25/44] Use local rank 0 to send/recv for h n_ar --- bluefog/common/nccl_controller.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/bluefog/common/nccl_controller.cc b/bluefog/common/nccl_controller.cc index f0e525fb..9e9926f2 100644 --- a/bluefog/common/nccl_controller.cc +++ b/bluefog/common/nccl_controller.cc @@ -989,13 +989,9 @@ void NCCLController::NeighborAllreduce(std::vector& entries) { void* recvbuf = (void*)((uint8_t*)buffer_data + num_elements * i * element_size); NCCLCHECK(ncclRecv(recvbuf, num_elements, - GetNCCLDataType(first_entry.tensor), recv_rank+1, + GetNCCLDataType(first_entry.tensor), recv_rank, nccl_ctx_.nccl_comm, nccl_ctx_.stream)); } - ncclGroupEnd(); - } else if (mpi_ctx_.local_rank_ == 1) { - // Use local rank 0 for sending - ncclGroupStart(); for (int send_rank : *first_entry.send_neighbors) { NCCLCHECK(ncclSend(fused_input_data, num_elements, GetNCCLDataType(first_entry.tensor), send_rank, From 8650da5e9407860511e4554284ab976cdee52ccc Mon Sep 17 00:00:00 2001 From: ybc Date: Tue, 27 Oct 2020 17:00:03 -0700 Subject: [PATCH 26/44] Add allreduce inplace API --- bluefog/torch/__init__.py | 1 + bluefog/torch/mpi_ops.py | 49 +++++++++++++++++++++++++++ bluefog/torch/utility.py | 2 +- test/torch_ops_test.py | 69 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 118 insertions(+), 3 deletions(-) diff --git a/bluefog/torch/__init__.py b/bluefog/torch/__init__.py index f5f2e8e0..e656b054 100644 --- a/bluefog/torch/__init__.py +++ b/bluefog/torch/__init__.py @@ -43,6 +43,7 @@ from bluefog.torch.mpi_ops import set_skip_negotiate_stage, get_skip_negotiate_stage from bluefog.torch.mpi_ops import allreduce, allreduce_nonblocking +from bluefog.torch.mpi_ops import allreduce_, allreduce_nonblocking_ from bluefog.torch.mpi_ops import allgather, allgather_nonblocking from bluefog.torch.mpi_ops import broadcast, broadcast_nonblocking from bluefog.torch.mpi_ops import broadcast_, broadcast_nonblocking_ diff --git a/bluefog/torch/mpi_ops.py b/bluefog/torch/mpi_ops.py index 6c3b7609..df285994 100644 --- a/bluefog/torch/mpi_ops.py +++ b/bluefog/torch/mpi_ops.py @@ -143,6 +143,55 @@ def allreduce_nonblocking(tensor: torch.Tensor, average: bool = True, return _allreduce_nonblocking(tensor, output, average, name) +def allreduce_(tensor: torch.Tensor, average: bool = True, + name: Optional[str] = None) -> torch.Tensor: + """ + A function that performs averaging or summation of the input tensor over all the + Bluefog processes. The operation is performed in-place. + + The reduction operation is keyed by the name. If name is not provided, an incremented + auto-generated name is used. The tensor type and shape must be the same on all + Bluefog processes for a given name. The reduction will not start until all processes + are ready to send and receive the tensor. + + Arguments: + tensor: A tensor to average and sum. + average: A flag indicating whether to compute average or summation, + defaults to average. + name: A name of the reduction operation. + + Returns: + A tensor of the same shape and type as `tensor`, averaged or summed across all + processes. + """ + handle = allreduce_nonblocking_(tensor, average, name) + return synchronize(handle) + + +def allreduce_nonblocking_(tensor: torch.Tensor, average: bool = True, + name: Optional[str] = None) -> int: + """ + A function that performs nonblocking averaging or summation of the input tensor + over all the Bluefog processes. The operation is performed in-place. + + The reduction operation is keyed by the name. If name is not provided, an incremented + auto-generated name is used. The tensor type and shape must be the same on all + Bluefog processes for a given name. The reduction will not start until all processes + are ready to send and receive the tensor. + + Arguments: + tensor: A tensor to average and sum. + average: A flag indicating whether to compute average or summation, + defaults to average. + name: A name of the reduction operation. + + Returns: + A handle to the allreduce operation that can be used with `poll()` or + `synchronize()`. + """ + return _allreduce_nonblocking(tensor, tensor, average, name) + + def _broadcast_function_factory(tensor): return 'bluefog_torch_broadcast_nonblocking_' + tensor.type().replace('.', '_') diff --git a/bluefog/torch/utility.py b/bluefog/torch/utility.py index 5de28b7a..ea94538d 100644 --- a/bluefog/torch/utility.py +++ b/bluefog/torch/utility.py @@ -74,7 +74,7 @@ def allreduce_parameters(params): # Run asynchronous broadcasts. handles = [] for name, p in params: - handle = bf.allreduce_nonblocking(p, average=True, name=name) + handle = bf.allreduce_nonblocking_(p, average=True, name=name) handles.append(handle) # Wait for completion. diff --git a/test/torch_ops_test.py b/test/torch_ops_test.py index 8a4e8fc6..7be827dd 100644 --- a/test/torch_ops_test.py +++ b/test/torch_ops_test.py @@ -131,7 +131,7 @@ def test_broadcast_inplace(self): ), "bf.broadcast_ produces incorrect broadcasted tensor" def test_allreduce_avg(self): - """Test that the allreduce correctly sums 1D, 2D, 3D tensors.""" + """Test that the allreduce correctly average 1D, 2D, 3D tensors.""" size = bf.size() if size <= 1: fname = inspect.currentframe().f_code.co_name @@ -168,7 +168,6 @@ def test_allreduce_sum(self): dims = [1, 2, 3] for dtype, dim in itertools.product(dtypes, dims): - torch.manual_seed(123456) tensor = torch.FloatTensor(*([23] * dim)).random_(-100, 100) tensor = self.cast_and_place(tensor, dtype) name = "allreduce_tensor_{}_{}".format(dim, dtype) @@ -179,6 +178,32 @@ def test_allreduce_sum(self): torch.allclose(output, tensor.mul(size)) ), "bf.allreduce(sum) produces incorrect tensor" + def test_allreduce_avg_inplace(self): + """Test that the allreduce correctly averages 1D, 2D, 3D tensors inplace.""" + size = bf.size() + rank = bf.rank() + if size <= 1: + fname = inspect.currentframe().f_code.co_name + warnings.warn("Skip {} due to size 1".format(fname)) + return + dtypes = [torch.FloatTensor, torch.DoubleTensor, torch.HalfTensor] + if TEST_ON_GPU: + dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] + + dims = [1, 2, 3] + for dtype, dim in itertools.product(dtypes, dims): + torch.manual_seed(123456) + tensor = torch.FloatTensor(*([23] * dim)).fill_(1).mul_(rank) + name = "allreduce_tensor_{}_{}".format(dim, dtype) + tensor = self.cast_and_place(tensor, dtype) + + bf.allreduce_(tensor, average=True, name=name) + tensor = self.convert_cpu_fp16_to_fp32(tensor)[0] + exp_tenosr = torch.ones_like(tensor).mul_((size-1)/2) + assert ( + torch.allclose(tensor, exp_tenosr) + ), "bf.allreduce_(avg) produces incorrect tensor" + def test_allreduce_fusion(self): """Test that the allreduce works under tensor fusion.""" size = bf.size() @@ -214,6 +239,46 @@ def test_allreduce_fusion(self): torch.allclose(tensor_2, output_2) ), "bf.allreduce(fusion) produces incorrect tensor 2" + def test_allreduce_fusion_inplace(self): + """Test that the allreduce works under tensor fusion.""" + size = bf.size() + rank = bf.rank() + if size <= 1: + fname = inspect.currentframe().f_code.co_name + warnings.warn("Skip {} due to size 1".format(fname)) + return + dtypes = [torch.FloatTensor, torch.DoubleTensor, torch.HalfTensor] + if TEST_ON_GPU: + dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] + + dims = [1, 2, 3] + for dtype, dim in itertools.product(dtypes, dims): + torch.manual_seed(123456) + tensor_1 = torch.FloatTensor(*([23] * dim)).fill_(1).mul_(rank) + tensor_2 = torch.FloatTensor(*([23] * dim)).fill_(1).mul_(rank+0.5) + name_1 = "allreduce_fusion_tensor_{}_{}_1".format(dim, dtype) + name_2 = "allreduce_fusion_tensor_{}_{}_2".format(dim, dtype) + tensor_1 = self.cast_and_place(tensor_1, dtype) + tensor_2 = self.cast_and_place(tensor_2, dtype) + + handle_1 = bf.allreduce_nonblocking_( + tensor_1, average=True, name=name_1) + handle_2 = bf.allreduce_nonblocking_( + tensor_2, average=True, name=name_2) + + bf.synchronize(handle_1) + bf.synchronize(handle_2) + tensor_1 = self.convert_cpu_fp16_to_fp32(tensor_1)[0] + tensor_2 = self.convert_cpu_fp16_to_fp32(tensor_2)[0] + exp_tenosr_1 = torch.ones_like(tensor_1).mul_((size-1)/2) + exp_tenosr_2 = torch.ones_like(tensor_2).mul_((size-1)/2 + 0.5) + assert ( + torch.allclose(tensor_1, exp_tenosr_1) + ), "bf.allreduce(fusion) produces incorrect tensor 1" + assert ( + torch.allclose(tensor_2, exp_tenosr_2) + ), "bf.allreduce(fusion) produces incorrect tensor 2" + def test_allgather(self): """Test that the allgather correctly gathers 1D, 2D, 3D tensors.""" size = bf.size() From cc05047907661923c1d803791f2de78ed6091396 Mon Sep 17 00:00:00 2001 From: ybc Date: Tue, 27 Oct 2020 20:29:50 -0700 Subject: [PATCH 27/44] Update pytorch_benchmark.py --- examples/pytorch_benchmark.py | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/pytorch_benchmark.py b/examples/pytorch_benchmark.py index 15158271..a242bb3f 100644 --- a/examples/pytorch_benchmark.py +++ b/examples/pytorch_benchmark.py @@ -69,7 +69,6 @@ args.cuda = not args.no_cuda and torch.cuda.is_available() if args.dist_optimizer == 'horovod': - print("importing horovod") import horovod.torch as bf bf.init() From 1a67e28a1ef73c468976f138e3a3bb51db0fd30e Mon Sep 17 00:00:00 2001 From: ybc Date: Wed, 28 Oct 2020 18:36:18 -0700 Subject: [PATCH 28/44] Add hierarchical local allreduce --- bluefog/common/mpi_controller.cc | 17 ++++++++++---- bluefog/common/nccl_controller.cc | 13 +++++++---- bluefog/common/operations.cc | 11 ++++++--- bluefog/common/operations.h | 1 + bluefog/torch/mpi_ops.cc | 39 ++++++++++++++++++------------- bluefog/torch/mpi_ops.h | 3 ++- bluefog/torch/mpi_ops.py | 28 ++++++++++++++-------- 7 files changed, 73 insertions(+), 39 deletions(-) diff --git a/bluefog/common/mpi_controller.cc b/bluefog/common/mpi_controller.cc index 3757854d..aa62efef 100644 --- a/bluefog/common/mpi_controller.cc +++ b/bluefog/common/mpi_controller.cc @@ -142,12 +142,16 @@ void MPIController::Allreduce(TensorTableEntry& entry) { void* buffer_data = (void*)entry.output->data(); int num_elements = entry.tensor->shape().num_elements(); + // Here is_hierarchical == true means local allreduce. + auto communicator_type = + entry.is_hierarchical ? Communicator::LOCAL : Communicator::GLOBAL; + // We need to explicitly set the device here. with_device device_guard(entry.device); - int ret_code = MPI_Allreduce( - sendbuf, buffer_data, num_elements, mpi_ctx_.GetMPIDataType(entry.tensor), - mpi_ctx_.GetMPISumOp(entry.tensor->dtype()), - mpi_ctx_.GetMPICommunicator(Communicator::GLOBAL)); + int ret_code = MPI_Allreduce(sendbuf, buffer_data, num_elements, + mpi_ctx_.GetMPIDataType(entry.tensor), + mpi_ctx_.GetMPISumOp(entry.tensor->dtype()), + mpi_ctx_.GetMPICommunicator(communicator_type)); if (ret_code != MPI_SUCCESS) { throw std::runtime_error( "MPI_AllReduce failed, see MPI output for details."); @@ -465,11 +469,14 @@ void MPIController::Allreduce(std::vector& entries) { timeline_ptr->ActivityEndAll(entries); timeline_ptr->ActivityStartAll(entries, "COMMUNICATE"); + // Here is_hierarchical == true means local allreduce. + auto communicator_type = + first_entry.is_hierarchical ? Communicator::LOCAL : Communicator::GLOBAL; int ret_code = MPI_Allreduce(MPI_IN_PLACE, buffer_data, num_elements, mpi_ctx_.GetMPIDataType(first_entry.tensor), mpi_ctx_.GetMPISumOp(first_entry.tensor->dtype()), - mpi_ctx_.GetMPICommunicator(Communicator::GLOBAL)); + mpi_ctx_.GetMPICommunicator(communicator_type)); if (ret_code != MPI_SUCCESS) { throw std::runtime_error( "MPI_AllReduce failed, see MPI output for details."); diff --git a/bluefog/common/nccl_controller.cc b/bluefog/common/nccl_controller.cc index 9e9926f2..73b68d75 100644 --- a/bluefog/common/nccl_controller.cc +++ b/bluefog/common/nccl_controller.cc @@ -443,13 +443,15 @@ void NCCLController::Allreduce(TensorTableEntry& entry) { int num_elements = entry.tensor->shape().num_elements(); std::queue> event_queue; + auto& nccl_comm = + entry.is_hierarchical ? nccl_ctx_.nccl_local_comm : nccl_ctx_.nccl_comm; with_device device_guard(entry.device); timeline_ptr_->ActivityStart(entry.tensor_name, "COMM. (NCCL)"); NCCLCHECK(ncclAllReduce(sendbuf, buffer_data, num_elements, - GetNCCLDataType(entry.tensor), ncclSum, - nccl_ctx_.nccl_comm, nccl_ctx_.stream)); + GetNCCLDataType(entry.tensor), ncclSum, nccl_comm, + nccl_ctx_.stream)); if (timeline_ptr_->Initialized()) { RecordEvent(event_queue, "COMM. (NCCL)"); @@ -846,10 +848,13 @@ void NCCLController::Allreduce(std::vector& entries) { } const void* fused_input_data = buffer_data; + auto& nccl_comm = first_entry.is_hierarchical ? nccl_ctx_.nccl_local_comm + : nccl_ctx_.nccl_comm; + ncclResult_t ret_code = ncclAllReduce(fused_input_data, buffer_data, num_elements, - GetNCCLDataType(first_entry.tensor), ncclSum, - nccl_ctx_.nccl_comm, nccl_ctx_.stream); + GetNCCLDataType(first_entry.tensor), ncclSum, nccl_comm, + nccl_ctx_.stream); if (ret_code != ncclSuccess) { std::string error_msg = "ncclAllReduce failed, see NCCL output (NCCL_DEBUG=INFO) " diff --git a/bluefog/common/operations.cc b/bluefog/common/operations.cc index 5273e2e5..e214cdf3 100644 --- a/bluefog/common/operations.cc +++ b/bluefog/common/operations.cc @@ -315,9 +315,10 @@ Response ConstructResponse(MessageTable* message_table, std::string name) { } } - // TODO(ybc) add check for is_hierarchical for neighbor_allreduce. - if(!error) { - if(message_type == Request::NEIGHBOR_ALLREDUCE) { + // If we are doing allreduce, make sure all are Hierarchical or are all not. + if (!error) { + if (message_type == Request::ALLREDUCE || + message_type == Request::NEIGHBOR_ALLREDUCE) { error = CheckRequestIsHierarchical(requests, error_message_stream); } } @@ -927,6 +928,7 @@ void NegotiateOfRequestOfMaster(BluefogGlobalState& state, if (response.response_type() == new_response.response_type() && response.devices() == new_response.devices() && entry.tensor->dtype() == new_entry.tensor->dtype() && + entry.is_hierarchical == new_entry.is_hierarchical && tensor_size + new_tensor_size <= state.tensor_fusion_threshold) { // These tensors will fuse together well. tensor_size += new_tensor_size; @@ -1382,6 +1384,7 @@ Status EnqueueTensorAllreduce(std::shared_ptr tensor, std::shared_ptr output, std::shared_ptr context, std::shared_ptr ready_event, + bool is_hierarchical_local, const std::string& name, const int device, StatusCallback callback) { Request message; @@ -1389,6 +1392,7 @@ Status EnqueueTensorAllreduce(std::shared_ptr tensor, message.set_tensor_name(name); message.set_tensor_type(tensor->dtype()); message.set_device(device); + message.set_is_hierarchical(is_hierarchical_local); message.set_request_type(Request::ALLREDUCE); for (int i = 0; i < tensor->shape().dims(); i++) { message.add_tensor_shape((int64_t)tensor->shape().dim_size(i)); @@ -1400,6 +1404,7 @@ Status EnqueueTensorAllreduce(std::shared_ptr tensor, e.output = output; e.device = device; e.ready_event = ready_event; + e.is_hierarchical = is_hierarchical_local; e.context = context; e.callback = callback; e.mpi_ops_type = MPIOpsType::ALLREDUCE; diff --git a/bluefog/common/operations.h b/bluefog/common/operations.h index 66293cde..7f922a52 100644 --- a/bluefog/common/operations.h +++ b/bluefog/common/operations.h @@ -112,6 +112,7 @@ Status EnqueueTensorAllreduce(std::shared_ptr tensor, std::shared_ptr output, std::shared_ptr context, std::shared_ptr ready_event, + bool is_hierarchical_local, const std::string& name, const int device, StatusCallback callback); diff --git a/bluefog/torch/mpi_ops.cc b/bluefog/torch/mpi_ops.cc index 8c1d283b..58661833 100644 --- a/bluefog/torch/mpi_ops.cc +++ b/bluefog/torch/mpi_ops.cc @@ -99,7 +99,7 @@ std::function(std::function)> } int DoAllreduce(::torch::Tensor tensor, ::torch::Tensor output, int average, - const std::string& name) { + bool is_hierarchical_local, const std::string& name) { ThrowIfError(common::CheckInitialized()); auto handle = handle_manager.AllocateHandle(); @@ -127,17 +127,21 @@ int DoAllreduce(::torch::Tensor tensor, ::torch::Tensor output, int average, auto ready_event = RecordReadyEvent(device); auto enqueue_result = EnqueueTensorAllreduce( - bf_tensor, bf_tensor, bf_context, ready_event, op_name, CPU_DEVICE_ID, - callback_wrapper([average, output, cpu_buffer, device]() mutable { - with_device device_guard(device); - output.copy_(cpu_buffer); + bf_tensor, bf_tensor, bf_context, ready_event, is_hierarchical_local, + op_name, CPU_DEVICE_ID, + callback_wrapper([average, output, is_hierarchical_local, cpu_buffer, + device]() mutable { + with_device device_guard(device); + output.copy_(cpu_buffer); - // Will execute in the `device` context. - ::torch::Tensor output_buffer = MaybeCopyToTensorBuffer(output); - if (average && bluefog_size() > 1) { - output_buffer.div_(bluefog_size()); - } - MaybeCopyBufferBack(output, output_buffer); + // Will execute in the `device` context. + ::torch::Tensor output_buffer = MaybeCopyToTensorBuffer(output); + int size = + is_hierarchical_local ? bluefog_local_size() : bluefog_size(); + if (average && size > 1) { + output_buffer.div_(bluefog_size()); + } + MaybeCopyBufferBack(output, output_buffer); })); ThrowIfError(enqueue_result); } else { @@ -147,15 +151,18 @@ int DoAllreduce(::torch::Tensor tensor, ::torch::Tensor output, int average, auto ready_event = RecordReadyEvent(device); auto enqueue_result = EnqueueTensorAllreduce( - bf_tensor, bf_output, bf_context, ready_event, op_name, device, - callback_wrapper([average, output]() mutable { + bf_tensor, bf_output, bf_context, ready_event, is_hierarchical_local, + op_name, device, + callback_wrapper([average, output, is_hierarchical_local]() mutable { // Will execute in the `device` context. ::torch::Tensor output_buffer = MaybeCopyToTensorBuffer(output); - if (average && bluefog_size() > 1) { - output_buffer.div_(bluefog_size()); + int size = + is_hierarchical_local ? bluefog_local_size() : bluefog_size(); + if (average && size > 1) { + output_buffer.div_(size); } MaybeCopyBufferBack(output, output_buffer); - })); + })); ThrowIfError(enqueue_result); } return handle; diff --git a/bluefog/torch/mpi_ops.h b/bluefog/torch/mpi_ops.h index ba495641..2808f780 100644 --- a/bluefog/torch/mpi_ops.h +++ b/bluefog/torch/mpi_ops.h @@ -31,7 +31,8 @@ namespace torch { #define ALLREDUCE_H(torch_Tensor, THTensor) \ extern "C" int bluefog_torch_allreduce_nonblocking_##torch_Tensor( \ - THTensor* tensor, THTensor* output, int average, char* name); + THTensor* tensor, THTensor* output, int average, \ + bool is_hierarchical_local, char* name); ALLREDUCE_H(torch_IntTensor, THIntTensor) ALLREDUCE_H(torch_LongTensor, THLongTensor) diff --git a/bluefog/torch/mpi_ops.py b/bluefog/torch/mpi_ops.py index df285994..dd8e61bc 100644 --- a/bluefog/torch/mpi_ops.py +++ b/bluefog/torch/mpi_ops.py @@ -79,7 +79,7 @@ def _allreduce_function_factory(tensor): return 'bluefog_torch_allreduce_nonblocking_' + tensor.type().replace('.', '_') -def _allreduce_nonblocking(tensor, output, average, name): +def _allreduce_nonblocking(tensor, output, average, is_hierarchical_local, name): function = _check_function(_allreduce_function_factory, tensor) if average: assert isinstance(tensor, (torch.HalfTensor, torch.FloatTensor, torch.DoubleTensor, @@ -87,14 +87,14 @@ def _allreduce_nonblocking(tensor, output, average, name): torch.cuda.HalfTensor)), \ "If average is set in allreduce, only float or double tensor is allowed." - handle = getattr(mpi_lib, function)(tensor, output, average, + handle = getattr(mpi_lib, function)(tensor, output, average, is_hierarchical_local, name.encode() if name is not None else "") _handle_map[handle] = (tensor, output) return handle def allreduce(tensor: torch.Tensor, average: bool = True, - name: Optional[str] = None) -> torch.Tensor: + is_hierarchical_local=False, name: Optional[str] = None) -> torch.Tensor: """ A function that performs averaging or summation of the input tensor over all the Bluefog processes. The input tensor is not modified. @@ -108,18 +108,20 @@ def allreduce(tensor: torch.Tensor, average: bool = True, tensor: A tensor to average and sum. average: A flag indicating whether to compute average or summation, defaults to average. + is_hierarchical_local: If set, allreduce is executed within one machine instead of + global allreduce. name: A name of the reduction operation. Returns: A tensor of the same shape and type as `tensor`, averaged or summed across all processes. """ - handle = allreduce_nonblocking(tensor, average, name) + handle = allreduce_nonblocking(tensor, average, is_hierarchical_local, name) return synchronize(handle) def allreduce_nonblocking(tensor: torch.Tensor, average: bool = True, - name: Optional[str] = None) -> int: + is_hierarchical_local=False, name: Optional[str] = None) -> int: """ A function that performs nonblocking averaging or summation of the input tensor over all the Bluefog processes. The input tensor is not modified. @@ -133,6 +135,8 @@ def allreduce_nonblocking(tensor: torch.Tensor, average: bool = True, tensor: A tensor to average and sum. average: A flag indicating whether to compute average or summation, defaults to average. + is_hierarchical_local: If set, allreduce is executed within one machine instead of + global allreduce. name: A name of the reduction operation. Returns: @@ -140,11 +144,11 @@ def allreduce_nonblocking(tensor: torch.Tensor, average: bool = True, `synchronize()`. """ output = tensor.new(tensor.shape) - return _allreduce_nonblocking(tensor, output, average, name) + return _allreduce_nonblocking(tensor, output, average, is_hierarchical_local, name) def allreduce_(tensor: torch.Tensor, average: bool = True, - name: Optional[str] = None) -> torch.Tensor: + is_hierarchical_local=False, name: Optional[str] = None) -> torch.Tensor: """ A function that performs averaging or summation of the input tensor over all the Bluefog processes. The operation is performed in-place. @@ -158,18 +162,20 @@ def allreduce_(tensor: torch.Tensor, average: bool = True, tensor: A tensor to average and sum. average: A flag indicating whether to compute average or summation, defaults to average. + is_hierarchical_local: If set, allreduce is executed within one machine instead of + global allreduce. name: A name of the reduction operation. Returns: A tensor of the same shape and type as `tensor`, averaged or summed across all processes. """ - handle = allreduce_nonblocking_(tensor, average, name) + handle = allreduce_nonblocking_(tensor, average, is_hierarchical_local, name) return synchronize(handle) def allreduce_nonblocking_(tensor: torch.Tensor, average: bool = True, - name: Optional[str] = None) -> int: + is_hierarchical_local=False, name: Optional[str] = None) -> int: """ A function that performs nonblocking averaging or summation of the input tensor over all the Bluefog processes. The operation is performed in-place. @@ -183,13 +189,15 @@ def allreduce_nonblocking_(tensor: torch.Tensor, average: bool = True, tensor: A tensor to average and sum. average: A flag indicating whether to compute average or summation, defaults to average. + is_hierarchical_local: If set, allreduce is executed within one machine instead of + global allreduce. name: A name of the reduction operation. Returns: A handle to the allreduce operation that can be used with `poll()` or `synchronize()`. """ - return _allreduce_nonblocking(tensor, tensor, average, name) + return _allreduce_nonblocking(tensor, tensor, average, is_hierarchical_local, name) def _broadcast_function_factory(tensor): From 5b9571971215844448a047468809891c0b57e25f Mon Sep 17 00:00:00 2001 From: ybc Date: Fri, 30 Oct 2020 22:19:23 -0700 Subject: [PATCH 29/44] Add use_empty_function_in_communication in dist optimizer --- bluefog/torch/optimizers.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/bluefog/torch/optimizers.py b/bluefog/torch/optimizers.py index 66f12477..5e63fd3b 100644 --- a/bluefog/torch/optimizers.py +++ b/bluefog/torch/optimizers.py @@ -360,6 +360,8 @@ def hook(module, *unused): handle = self._neighbor_allreduce_data_async(p) elif self._reduce_method == 2: handle = self._hierarchical_neighbor_allreduce_data_async(p) + elif self._reduce_method == -1: + handle = None else: raise ValueError( "Unknown reduce method. Do not change _reduce_method manually.") @@ -409,12 +411,16 @@ def use_neighbor_allreduce_in_communication(self): def use_hierarchical_neighbor_allreduce_in_communication(self): self._reduce_method = 2 + def use_empty_function_in_communication(self): + self._reduce_method = -1 + def synchronize(self): with torch.no_grad(): for p, handle in self._handles.items(): - output = bf.synchronize(handle) + if handle is not None: + output = bf.synchronize(handle) + p.set_(output) self._reduce_delay[p] = self._num_steps_per_communication - p.set_(output) self._handles.clear() self._synchronized = True From e869fc0d0bd52417f3fe2264aa54f81fe76db352 Mon Sep 17 00:00:00 2001 From: ybc Date: Sat, 31 Oct 2020 13:47:22 -0700 Subject: [PATCH 30/44] Add Hierarchical ops explanation in docs --- docs/_static/bf_hier_local_allreduce.png | Bin 0 -> 170899 bytes docs/_static/bf_hier_neighbor_allreduce.png | Bin 0 -> 168263 bytes docs/bluefog_ops.rst | 34 ++++++++++++++++++-- 3 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 docs/_static/bf_hier_local_allreduce.png create mode 100644 docs/_static/bf_hier_neighbor_allreduce.png diff --git a/docs/_static/bf_hier_local_allreduce.png b/docs/_static/bf_hier_local_allreduce.png new file mode 100644 index 0000000000000000000000000000000000000000..89f59d13d1f96eacf111a3b0f895e089175e9869 GIT binary patch literal 170899 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

1-*g!nCe+PI(T>&%I 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 Date: Sat, 31 Oct 2020 14:29:09 -0700 Subject: [PATCH 31/44] Update the document and remove som API --- bluefog/common/topology_util.py | 27 ++++++- bluefog/torch/__init__.py | 4 +- bluefog/torch/mpi_ops.py | 1 + bluefog/torch/optimizers.py | 106 +++++++++++++------------- bluefog/torch/utility.py | 2 +- docs/index.rst | 4 +- examples/pytorch_ImageNet_Resnet50.py | 2 +- examples/pytorch_benchmark.py | 23 ++---- examples/pytorch_cifar10_resnet.py | 21 +---- examples/pytorch_mnist.py | 21 +---- 10 files changed, 96 insertions(+), 115 deletions(-) diff --git a/bluefog/common/topology_util.py b/bluefog/common/topology_util.py index 73cc30f9..308e02c1 100644 --- a/bluefog/common/topology_util.py +++ b/bluefog/common/topology_util.py @@ -433,6 +433,23 @@ def GetDynamicSendRecvRanks( def GetExp2DynamicSendRecvMachineRanks( world_size: int, local_size: int, self_rank: int, local_rank: int ) -> Iterator[Tuple[List[int], List[int]]]: + """ + A utility function to generate 1-outgoing send machine id and corresponding recieving + machine id(s) for Exponentia-2 topology. + + Args: + world_size (int): the size of all nodes; world_size = num_machines * nodes_per_machine + local_size (int): number of nodes in each machine + self_rank (int): The self rank. + local_rank (int): The self local rank. + + Yields: + Iterator[Tuple[List[int], List[int]]]: send_machine_ids, recv_machine_ids. + + Warning: + This function should be used under homogeneous enviroment only, i.e. all machines have + the same number of local processes. + """ assert (self_rank % local_size) == local_rank, \ "It should be used under homogeneous environment only." assert (world_size % local_size) == 0, \ @@ -455,8 +472,9 @@ def GetExp2DynamicSendRecvMachineRanks( def GetInnerOuterRingDynamicSendRecvRanks( world_size: int, local_size: int, self_rank: int ) -> Iterator[Tuple[List[int], List[int]]]: - """A utility function to generate 1-outgoing send rank and corresponding recieving rank(s) - for Inner-Ring-Outer-Ring topology + """ + A utility function to generate 1-outgoing send rank and corresponding recieving rank(s) + for Inner-Ring-Outer-Ring topology. Args: world_size (int): the size of all nodes; world_size = num_machines * nodes_per_machine @@ -526,8 +544,9 @@ def GetInnerOuterRingDynamicSendRecvRanks( def GetInnerOuterExp2DynamicSendRecvRanks( world_size: int, local_size: int, self_rank: int ) -> Iterator[Tuple[List[int], List[int]]]: - """A utility function to generate 1-outgoing send rank and corresponding recieving rank(s) - for Inner-Exp2-Outer-Exp2 ring topology + """ + A utility function to generate 1-outgoing send rank and corresponding recieving rank(s) + for Inner-Exp2-Outer-Exp2 ring topology. Args: world_size (int): the size of all nodes; world_size = num_machines * nodes_per_machine diff --git a/bluefog/torch/__init__.py b/bluefog/torch/__init__.py index e656b054..706c592e 100644 --- a/bluefog/torch/__init__.py +++ b/bluefog/torch/__init__.py @@ -27,9 +27,7 @@ DistributedAllreduceOptimizer, DistributedNeighborAllreduceOptimizer, DistributedHierarchicalNeighborAllreduceOptimizer, - DistributedPushSumOptimizer, - DistributedPullGetOptimizer, - DistributedBluefogOptimizer) + DistributedWinPutOptimizer) check_extension('bluefog.torch', __file__, 'mpi_lib') diff --git a/bluefog/torch/mpi_ops.py b/bluefog/torch/mpi_ops.py index dd8e61bc..7d7765f2 100644 --- a/bluefog/torch/mpi_ops.py +++ b/bluefog/torch/mpi_ops.py @@ -917,6 +917,7 @@ def win_update_then_collect(name: str, require_mutex: bool = True) -> torch.Tens """ A utility function to sync the neighbor buffers then accumulate all neighbor buffers' tensors into self tensor and clear the buffer. It is equivalent to + >>> win_update(name, self_weight=1.0, neighbor_weights={neighbor: 1.0}, reset=True, require_mutex=require_mutex) diff --git a/bluefog/torch/optimizers.py b/bluefog/torch/optimizers.py index 5e63fd3b..3eae55b7 100644 --- a/bluefog/torch/optimizers.py +++ b/bluefog/torch/optimizers.py @@ -462,7 +462,7 @@ def step(self, closure=None): return super(self.__class__, self).step(closure) -class _DistributedBluefogOptimizer(torch.optim.Optimizer): +class _DistributedWinOptimizer(torch.optim.Optimizer): def __init__(self, params, model, num_steps_per_communication, pull_style): super(self.__class__, self).__init__(params) @@ -859,13 +859,13 @@ def DistributedPullGetOptimizer(optimizer, model, cls = type( optimizer.__class__.__name__, (optimizer.__class__,), - dict(_DistributedBluefogOptimizer.__dict__), + dict(_DistributedWinOptimizer.__dict__), ) return cls(optimizer.param_groups, model, num_steps_per_communication, pull_style=True) -def DistributedBluefogOptimizer(optimizer, model, - num_steps_per_communication=1): +def DistributedWinPutOptimizer(optimizer, model, + num_steps_per_communication=1): """An distributed optimizer that wraps another torch.optim.Optimizer with pull model average through bf.win_put ops. @@ -877,43 +877,17 @@ def DistributedBluefogOptimizer(optimizer, model, per num_steps_per_communication before reducing them over distributed computation resources. - Example for two scenarios to use num_steps_per_communication: - Scenario 1) Local accumulation of gradient without update model. - (Used in large batch size or large model cases) - >>> opt = bf.DistributedBluefogOptimizer(optimizer, model, num_steps_per_communication=J) - >>> opt.zero_grad() - >>> for j in range(J): - >>> output = model(data_batch_i) - >>> loss = ... - >>> loss.backward() - >>> opt.step() # Window operation happens here - Scenario 2) Local updating the model. (Used in case that decreasing the communication). - >>> opt = bf.DistributedBluefogOptimizer(optimizer, model, num_steps_per_communication=J) - >>> for j in range(J): - >>> output = model(data_batch_i) - >>> loss = ... - >>> opt.zero_grad() - >>> loss.backward() - >>> opt.step() # Window operation happens at the last iteration - Returned optimizer has two extra parameters `dst_weights` and `force_barrier`. Set dst_weights dictionary as {rank: scaling} differently per iteration to achieve win_put over dynamic graph behavior. If force_barrier is True, a barrier function will put at `step()` to synchronous processes. - - Example: - >>> import bluefog.torch as bf - >>> ... - >>> bf.init() - >>> optimizer = optim.SGD(model.parameters(), lr=lr * bf.size()) - >>> optimizer = bf.DistributedBluefogOptimizer(optimizer, model) """ # We dynamically create a new class that inherits from the optimizer that was passed in. # The goal is to override the `step()` method. cls = type( optimizer.__class__.__name__, (optimizer.__class__,), - dict(_DistributedBluefogOptimizer.__dict__), + dict(_DistributedWinOptimizer.__dict__), ) return cls(optimizer.param_groups, model, num_steps_per_communication, pull_style=False) @@ -932,9 +906,10 @@ def DistributedAllreduceOptimizer(optimizer, model, per num_steps_per_communication before reducing them over distributed computation resources. - Example for two scenarios to use num_steps_per_communication: + Example for two scenarios to use num_steps_per_communication. Scenario 1) Local accumulation of gradient without update model. (Used in large batch size or large model cases) + >>> opt = bf.DistributedAllreduceOptimizer(optimizer, model, num_steps_per_communication=J) >>> opt.zero_grad() @@ -943,7 +918,9 @@ def DistributedAllreduceOptimizer(optimizer, model, >>> loss = ... >>> loss.backward() >>> opt.step() # Allreducing happens here + Scenario 2) Local updating the model. (Used in case that decreasing the communication). + >>> opt = bf.DistributedAllreduceOptimizer(optimizer, model, num_steps_per_communication=J) >>> for j in range(J): @@ -969,9 +946,37 @@ def DistributedNeighborAllreduceOptimizer(optimizer, model, An distributed optimizer that wraps another torch.optim.Optimizer through neighbor_allreduce ops over parameters. - Returned optimizer has two extra parameters `self_weight` and `neighbor_weights`. - Set self_weight as some scalar and dst_weights dictionary as {rank: scaling} differently - per iteration to achieve win_put over dynamic graph behavior. + Returned optimizer has three extra parameters `self_weight`, `neighbor_weights` and + `send_neighbors` to control the behavior of neighbor allreduce. Changing the values + of these knobs to achieve dynamic topologies. + + Arguments: + optimizer: Optimizer to use for computing gradients and applying updates. + model: The model or a list of models you want to train with. + num_steps_per_communication: Number of expected model forward function calls before each + communication. This allows local model parameter updates + per num_steps_per_communication before reducing them over + distributed computation resources. + """ + # We dynamically create a new class that inherits from the optimizer that was passed in. + # The goal is to override the `step()` method with neighbor_allreduce implementation. + cls = type( + optimizer.__class__.__name__, + (optimizer.__class__,), + dict(_DistributedReduceOptimizer.__dict__), + ) + return cls(optimizer.param_groups, model, "neighbor.allreduce", num_steps_per_communication) + + +def DistributedHierarchicalNeighborAllreduceOptimizer(optimizer, model, + num_steps_per_communication=1): + """ + An distributed optimizer that wraps another torch.optim.Optimizer through + hierarchical_neighbor_allreduce ops over parameters. + + Returned optimizer has three extra parameters `self_weight`, `neighbor_machine_weights` and + `send_neighbor_machines` to control the behavior of hierarchical neighbor allreduce. Changing + the values of these knobs to achieve dynamic topologies. Arguments: optimizer: Optimizer to use for computing gradients and applying updates. @@ -981,20 +986,27 @@ def DistributedNeighborAllreduceOptimizer(optimizer, model, per num_steps_per_communication before reducing them over distributed computation resources. + Warning: + The processes within the same machine should provide the same `neighbor_machine_weights` and + `send_neighbor_machines` to avoid unexpected behavior. + Example for two scenarios to use num_steps_per_communication: Scenario 1) Local accumulation of gradient without update model. (Used in large batch size or large model cases) - >>> opt = bf.DistributedNeighborAllreduceOptimizer(optimizer, model, - num_steps_per_communication=J) + + >>> opt = bf.DistributedHierarchicalNeighborAllreduceOptimizer( + optimizer, model, num_steps_per_communication=J) >>> opt.zero_grad() >>> for j in range(J): >>> output = model(data_batch_i) >>> loss = ... >>> loss.backward() >>> opt.step() # Neighbor allreducing happens here + Scenario 2) Local updating the model. (Used in case that decreasing the communication). - >>> opt = bf.DistributedNeighborAllreduceOptimizer(optimizer, model, - num_steps_per_communication=J) + + >>> opt = bf.DistributedHierarchicalNeighborAllreduceOptimizer( + optimizer, model, num_steps_per_communication=J) >>> for j in range(J): >>> output = model(data_batch_i) >>> loss = ... @@ -1002,18 +1014,6 @@ def DistributedNeighborAllreduceOptimizer(optimizer, model, >>> loss.backward() >>> opt.step() # Neighbor allreducing happens at the last iteration """ - # We dynamically create a new class that inherits from the optimizer that was passed in. - # The goal is to override the `step()` method with neighbor_allreduce implementation. - cls = type( - optimizer.__class__.__name__, - (optimizer.__class__,), - dict(_DistributedReduceOptimizer.__dict__), - ) - return cls(optimizer.param_groups, model, "neighbor.allreduce", num_steps_per_communication) - - -def DistributedHierarchicalNeighborAllreduceOptimizer(optimizer, model, - num_steps_per_communication=1): cls = type( optimizer.__class__.__name__, (optimizer.__class__,), @@ -1039,8 +1039,10 @@ def DistributedGradientAllreduceOptimizer(optimizer, model, distributed computation resources. Example for two scenarios to use num_steps_per_communication: + Scenario 1) Local accumulation of gradient without update model. (Used in large batch size or large model cases) + >>> opt = bf.DistributedGradientAllreduceOptimizer(optimizer, model, >>> num_steps_per_communication=J) >>> opt.zero_grad() @@ -1049,7 +1051,9 @@ def DistributedGradientAllreduceOptimizer(optimizer, model, >>> loss = ... >>> loss.backward() >>> opt.step() # Allreducing happens here + Scenario 2) Local updating the model. (Used in case that decreasing the communication). + >>> opt = bf.DistributedGradientAllreduceOptimizer(optimizer, model, >>> num_steps_per_communication=J) >>> for j in range(J): diff --git a/bluefog/torch/utility.py b/bluefog/torch/utility.py index ea94538d..15a5f343 100644 --- a/bluefog/torch/utility.py +++ b/bluefog/torch/utility.py @@ -115,7 +115,7 @@ def broadcast_optimizer_state(optimizer, root_rank): super(optimizer.__class__, optimizer).step() elif optimizer.__module__ == bf.DistributedPullGetOptimizer.__module__: super(optimizer.__class__, optimizer).step() - elif optimizer.__module__ == bf.DistributedBluefogOptimizer.__module__: + elif optimizer.__module__ == bf.DistributedWinPutOptimizer.__module__: super(optimizer.__class__, optimizer).step() else: optimizer.step() diff --git a/docs/index.rst b/docs/index.rst index 38628fc3..a377419f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -44,7 +44,7 @@ the :ref:`install_bluefog` page if you need more information or other install op We provide high-level wrapper for torch optimizer. Probably, the only thing you need to modify the existing script to distributed implementation is wrapping the optimizer -with our ``DistributedBluefogOptimizer``, +with our ``DistributedNeighborAllreduceOptimizer``, then run it through ``bfrun``. That is it! .. code-block:: python @@ -57,7 +57,7 @@ then run it through ``bfrun``. That is it! ... bf.init() optimizer = optim.SGD(model.parameters(), lr=lr * bf.size()) - optimizer = bf.DistributedBluefogOptimizer( + optimizer = bf.DistributedNeighborAllreduceOptimizer( optimizer, model ) ... diff --git a/examples/pytorch_ImageNet_Resnet50.py b/examples/pytorch_ImageNet_Resnet50.py index 3aabdb0c..9bc2ed2d 100644 --- a/examples/pytorch_ImageNet_Resnet50.py +++ b/examples/pytorch_ImageNet_Resnet50.py @@ -182,7 +182,7 @@ # Bluefog: wrap optimizer with DistributedOptimizer. # TODO(hhb) Pass batches_per_allreduce to optimizer. if args.dist_optimizer == 'win_put': - optimizer = bf.DistributedBluefogOptimizer(optimizer, model=model) + optimizer = bf.DistributedWinPutOptimizer(optimizer, model=model) elif args.dist_optimizer == 'neighbor_allreduce': optimizer = optimizer = bf.DistributedNeighborAllreduceOptimizer( optimizer, model=model) diff --git a/examples/pytorch_benchmark.py b/examples/pytorch_benchmark.py index a242bb3f..03c22e1c 100644 --- a/examples/pytorch_benchmark.py +++ b/examples/pytorch_benchmark.py @@ -53,10 +53,10 @@ help='disables profiler') parser.add_argument('--partition', type=int, default=None, help='partition size') -parser.add_argument('--dist-optimizer', type=str, default='win_put', +parser.add_argument('--dist-optimizer', type=str, default='neighbor_allreduce', help='The type of distributed optimizer. Supporting options are ' + - '[win_put(default), neighbor_allreduce, allreduce, ' + - 'hierarchical_neighbor_allreduce, pull_get, push_sum, horovod]') + '[win_put, neighbor_allreduce, allreduce, ' + + 'hierarchical_neighbor_allreduce, horovod]') parser.add_argument('--disable-dynamic-topology', action='store_true', default=False, help=('Disable each iteration to transmit one neighbor ' + 'per iteration dynamically.')) @@ -130,7 +130,7 @@ def forward(self, x): # Bluefog: wrap optimizer with DistributedOptimizer. if args.dist_optimizer == 'win_put': - optimizer = bf.DistributedBluefogOptimizer(optimizer, model=model) + optimizer = bf.DistributedWinPutOptimizer(optimizer, model=model) elif args.dist_optimizer == 'neighbor_allreduce': optimizer = optimizer = bf.DistributedNeighborAllreduceOptimizer( optimizer, model=model) @@ -140,8 +140,6 @@ def forward(self, x): elif args.dist_optimizer == 'gradient_allreduce': optimizer = optimizer = bf.DistributedGradientAllreduceOptimizer( optimizer, model=model) -elif args.dist_optimizer == 'push_sum': - optimizer = bf.DistributedPushSumOptimizer(optimizer, model=model) elif args.dist_optimizer == 'hierarchical_neighbor_allreduce': optimizer = optimizer = bf.DistributedHierarchicalNeighborAllreduceOptimizer( optimizer, model=model) @@ -149,13 +147,11 @@ def forward(self, x): optimizer = optimizer = bf.DistributedOptimizer( optimizer, named_parameters=model.named_parameters() ) -elif args.dist_optimizer == 'pull_get': - optimizer = bf.DistributedPullGetOptimizer(optimizer, model=model) else: raise ValueError('Unknown args.dist-optimizer type -- ' + args.dist_optimizer + '\n' + 'Please set the argument to be one of ' + '[neighbor_allreduce, gradient_allreduce, allreduce, ' + - 'win_put, push_sum, horovod]') + 'win_put, horovod]') bf.broadcast_parameters(model.state_dict(), root_rank=0) bf.broadcast_optimizer_state(optimizer, root_rank=0) @@ -208,15 +204,6 @@ def dynamic_topology_update(batch_idx): num_out_neighbors = len(bf.out_neighbor_ranks()) sent_neighbor = bf.out_neighbor_ranks()[batch_idx % num_out_neighbors] optimizer.dst_weights = {sent_neighbor: 1.0} - elif args.dist_optimizer == 'pull_get': - num_in_neighbors = len(bf.in_neighbor_ranks()) - recv_neighbor = bf.in_neighbor_ranks()[batch_idx % num_in_neighbors] - optimizer.src_weights = {recv_neighbor: 1.0} - elif args.dist_optimizer == 'push_sum': - num_out_neighbors = len(bf.out_neighbor_ranks()) - sent_neighbor = bf.out_neighbor_ranks()[batch_idx % num_out_neighbors] - optimizer.dst_weights = {sent_neighbor: 0.5} - optimizer.self_weight = 0.5 elif args.dist_optimizer == 'neighbor_allreduce': send_neighbors, recv_neighbors = next(dynamic_neighbor_allreduce_gen) optimizer.send_neighbors = send_neighbors diff --git a/examples/pytorch_cifar10_resnet.py b/examples/pytorch_cifar10_resnet.py index e801d30a..32bdd1cc 100644 --- a/examples/pytorch_cifar10_resnet.py +++ b/examples/pytorch_cifar10_resnet.py @@ -74,7 +74,7 @@ "--no-cuda", action="store_true", default=False, help="disables CUDA training" ) parser.add_argument("--seed", type=int, default=42, help="random seed") -parser.add_argument('--dist-optimizer', type=str, default='hierarchical_neighbor_allreduce', +parser.add_argument('--dist-optimizer', type=str, default='neighbor_allreduce', help='The type of distributed optimizer. Supporting options are ' + '[win_put, neighbor_allreduce, allreduce, pull_get, hierarchical_neighbor_allreduce, horovod]') parser.add_argument("--average-test-result", action="store_true", @@ -216,7 +216,7 @@ # Bluefog: wrap optimizer with DistributedOptimizer. if args.dist_optimizer == 'win_put': - optimizer = bf.DistributedBluefogOptimizer(optimizer, model=model) + optimizer = bf.DistributedWinPutOptimizer(optimizer, model=model) elif args.dist_optimizer == 'neighbor_allreduce': optimizer = optimizer = bf.DistributedNeighborAllreduceOptimizer( optimizer, model=model) @@ -229,8 +229,6 @@ elif args.dist_optimizer == 'hierarchical_neighbor_allreduce': optimizer = optimizer = bf.DistributedHierarchicalNeighborAllreduceOptimizer( optimizer, model=model) -elif args.dist_optimizer == 'push_sum': - optimizer = bf.DistributedPushSumOptimizer(optimizer, model=model) elif args.dist_optimizer == 'horovod': optimizer = optimizer = bf.DistributedOptimizer( optimizer, named_parameters=model.named_parameters() @@ -241,7 +239,7 @@ raise ValueError('Unknown args.dist-optimizer type -- ' + args.dist_optimizer + '\n' + 'Please set the argument to be one of ' + '[neighbor_allreduce, gradient_allreduce, allreduce, ' + - 'win_put, push_sum, horovod]') + 'win_put, horovod]') print("resume_from_epoch: ", resume_from_epoch) # Restore from a previous checkpoint, if initial_epoch is specified. @@ -378,19 +376,6 @@ def dynamic_topology_update(epoch, batch_idx): num_out_neighbors = len(bf.out_neighbor_ranks()) sent_neighbor = bf.out_neighbor_ranks()[batch_idx % num_out_neighbors] optimizer.dst_weights = {sent_neighbor: 1.0} - elif args.dist_optimizer == 'pull_get': - if epoch < 3: - return - num_in_neighbors = len(bf.in_neighbor_ranks()) - recv_neighbor = bf.in_neighbor_ranks()[batch_idx % num_in_neighbors] - optimizer.src_weights = {recv_neighbor: 1.0} - elif args.dist_optimizer == 'push_sum': - if epoch < 3: - return - num_out_neighbors = len(bf.out_neighbor_ranks()) - sent_neighbor = bf.out_neighbor_ranks()[batch_idx % num_out_neighbors] - optimizer.dst_weights = {sent_neighbor: 0.5} - optimizer.self_weight = 0.5 elif args.dist_optimizer == 'neighbor_allreduce': send_neighbors, recv_neighbors = next(dynamic_neighbor_allreduce_gen) optimizer.send_neighbors = send_neighbors diff --git a/examples/pytorch_mnist.py b/examples/pytorch_mnist.py index a80d97ed..358b2111 100644 --- a/examples/pytorch_mnist.py +++ b/examples/pytorch_mnist.py @@ -55,9 +55,9 @@ parser.add_argument( "--no-cuda", action="store_true", default=False, help="disables CUDA training" ) -parser.add_argument('--dist-optimizer', type=str, default='win_put', +parser.add_argument('--dist-optimizer', type=str, default='neighbor_allreduce', help='The type of distributed optimizer. Supporting options are ' + - '[win_put, neighbor_allreduce, allreduce, pull_get, push_sum, horovod]') + '[win_put, neighbor_allreduce, allreduce, horovod]') parser.add_argument("--average-test-result", action="store_true", default=False, help=("Allreduce called to average test result. Warning this will " + @@ -193,7 +193,7 @@ def forward(self, x): # Bluefog: wrap optimizer with DistributedOptimizer. if args.dist_optimizer == 'win_put': - optimizer = bf.DistributedBluefogOptimizer(optimizer, model=model) + optimizer = bf.DistributedWinPutOptimizer(optimizer, model=model) elif args.dist_optimizer == 'neighbor_allreduce': optimizer = optimizer = bf.DistributedNeighborAllreduceOptimizer( optimizer, model=model) @@ -206,8 +206,6 @@ def forward(self, x): elif args.dist_optimizer == 'hierarchical_neighbor_allreduce': optimizer = optimizer = bf.DistributedHierarchicalNeighborAllreduceOptimizer( optimizer, model=model) -elif args.dist_optimizer == 'push_sum': - optimizer = bf.DistributedPushSumOptimizer(optimizer, model=model) elif args.dist_optimizer == 'horovod': optimizer = optimizer = bf.DistributedOptimizer( optimizer, named_parameters=model.named_parameters() @@ -218,7 +216,7 @@ def forward(self, x): raise ValueError('Unknown args.dist-optimizer type -- ' + args.dist_optimizer + '\n' + 'Please set the argument to be one of ' + '[neighbor_allreduce, gradient_allreduce, allreduce, ' + - 'win_put, push_sum, horovod]') + 'win_put, horovod]') if not args.disable_dynamic_topology and (args.dist_optimizer != 'horovod'): if args.virtual_topology == 'InnerOuterRing': @@ -250,17 +248,6 @@ def dynamic_topology_update(epoch, batch_idx): num_out_neighbors = len(bf.out_neighbor_ranks()) sent_neighbor = bf.out_neighbor_ranks()[batch_idx % num_out_neighbors] optimizer.dst_weights = {sent_neighbor: 1.0} - elif args.dist_optimizer == 'pull_get': - if epoch < 3: - return - num_in_neighbors = len(bf.in_neighbor_ranks()) - recv_neighbor = bf.in_neighbor_ranks()[batch_idx % num_in_neighbors] - optimizer.src_weights = {recv_neighbor: 1.0} - elif args.dist_optimizer == 'push_sum': - num_out_neighbors = len(bf.out_neighbor_ranks()) - sent_neighbor = bf.out_neighbor_ranks()[batch_idx % num_out_neighbors] - optimizer.dst_weights = {sent_neighbor: 0.5} - optimizer.self_weight = 0.5 elif args.dist_optimizer == 'neighbor_allreduce': send_neighbors, recv_neighbors = next(dynamic_neighbor_allreduce_gen) optimizer.send_neighbors = send_neighbors From 2fbab44179879f31d3420c6c35c6047ca6bf8aa9 Mon Sep 17 00:00:00 2001 From: ybc Date: Sat, 31 Oct 2020 14:54:59 -0700 Subject: [PATCH 32/44] Simplify the examples folder --- examples/pytorch_nonconvex_logitReg.py | 315 ------------------ examples/tensorflow2_mnist.py | 92 ----- .../pytorch_opt_linear_speedup_test.py | 0 3 files changed, 407 deletions(-) delete mode 100644 examples/pytorch_nonconvex_logitReg.py delete mode 100644 examples/tensorflow2_mnist.py rename {examples => scripts}/pytorch_opt_linear_speedup_test.py (100%) diff --git a/examples/pytorch_nonconvex_logitReg.py b/examples/pytorch_nonconvex_logitReg.py deleted file mode 100644 index 4b8f2c21..00000000 --- a/examples/pytorch_nonconvex_logitReg.py +++ /dev/null @@ -1,315 +0,0 @@ -# Copyright 2020 Bluefog Team. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -import torch -import matplotlib.pyplot as plt -import argparse - -import bluefog.torch as bf -from bluefog.common import topology_util - -# Parser -parser = argparse.ArgumentParser( - description="PyTorch ImageNet Example", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, -) -parser.add_argument( - "--save-plot-file", default='plot.png', help="Saving the plot in the file." -) -parser.add_argument( - "--plot-interactive", action='store_true', help="Use plt.show() to present the plot." -) -parser.add_argument( - "--max-iter", action='store', type=int, default=1000, help="Use plt.show() to present the plot." -) -parser.add_argument( - "--method", help="this example supports exact_diffusion, gradient_tracking, and push_diging", - default='exact_diffusion' -) -args = parser.parse_args() - - -def finalize_plot(): - plt.savefig(args.save_plot_file) - if args.plot_interactive: - plt.show() - plt.close() - - -def logistic_loss_step(x_, rho, beta, tensor_name): - """Calculate gradient of logistic loss via pytorch autograd.""" - with bf.timeline_context(tensor_name=tensor_name, - activity_name="gradient computation"): - loss_ = torch.mean(torch.log(1 + torch.exp(-y*X.mm(x_)))) \ - + torch.sum(rho*beta*x_*x_/(1+beta*x_*x_)) - loss_.backward() - return loss_ - -# # ================== Distributed gradient descent ================================ -# # Calculate the solution with distributed gradient descent: -# # x^{k+1} = x^k - alpha * allreduce(local_grad) -# # it will be used to verify the solution of various decentralized algorithms. -# # ================================================================================ -def distributed_grad_descent(rho, beta, maxite=5000, alpha=1e-1): - w_opt = torch.zeros(n, 1, dtype=torch.double, requires_grad=True) - - for i in range(maxite): - # calculate gradient via pytorch autograd - logistic_loss_step(w_opt, rho, beta, tensor_name='allreduce.gradient') - # global gradient - grad = bf.allreduce(w_opt.grad.data, name='gradient') - - # distributed gradient descent - w_opt.data = w_opt.data - alpha*grad - w_opt.grad.data.zero_() - - logistic_loss_step(w_opt, rho, beta, tensor_name='allreduce.gradient') - grad = bf.allreduce(w_opt.grad.data, name='gradient') # global gradient - - # evaluate the convergence of distributed logistic regression - # the norm of global gradient is expected to 0 (optimality condition) - global_grad_norm = torch.norm(grad, p=2) - print("[DG] Rank {}: global gradient norm: {}".format( - bf.rank(), global_grad_norm)) - - # the norm of local gradient is expected not be be close to 0 - # this is because each rank converges to global solution, not local solution - local_grad_norm = torch.norm(w_opt.grad.data, p=2) - print("[DG] Rank {}: local gradient norm: {}".format( - bf.rank(), local_grad_norm)) - - return w_opt - - -# ==================== Exact Diffusion =========================================== -# Calculate the true solution with exact diffusion recursion as follows: -# -# psi^{k+1} = w^k - alpha * grad(w^k) -# phi^{k+1} = psi^{k+1} + w^k - psi^{k} -# w^{k+1} = neighbor_allreduce(phi^{k+1}) -# -# Reference: -# -# [R1] K. Yuan, B. Ying, X. Zhao, and A. H. Sayed, ``Exact diffusion for distributed -# optimization and learning -- Part I: Algorithm development'', 2018. (Alg. 1) -# link: https://arxiv.org/abs/1702.05122 -# -# [R2] Z. Li, W. Shi and M. Yan, ``A Decentralized Proximal-gradient Method with -# Network Independent Step-sizes and Separated Convergence Rates'', 2019 -# ================================================================================ -def exact_diffusion(w_opt, rho, beta, maxite=2000, alpha_ed=1e-1, use_Abar=False): - w = torch.zeros(n, 1, dtype=torch.double, requires_grad=True) - phi, psi, psi_prev = w.clone(), w.clone(), w.clone() - mse = [] - - topology = bf.load_topology() - self_weight, neighbor_weights = topology_util.GetRecvWeights( - topology, bf.rank()) - - # construct A_bar - if use_Abar: - self_weight = (self_weight+1)/2 - for k, v in neighbor_weights.items(): - neighbor_weights[k] = v/2 - - # if bf.rank() == 0: - # for k, v in neighbor_weights.items(): - # print(neighbor_weights[k]) - - for i in range(maxite): - # calculate loccal gradient via pytorch autograd - logistic_loss_step( - w, rho, beta, tensor_name='neighbor.allreduce.local_variable') - - # exact diffusion - psi = w - alpha_ed * w.grad.data - phi = psi + w.data - psi_prev - w.data = bf.neighbor_allreduce( - phi, self_weight, neighbor_weights, name='local variable') - psi_prev = psi.clone() - w.grad.data.zero_() - - # record convergence - if bf.rank() == 0: - mse.append(torch.norm(w.data - w_opt.data, p=2)) - - return w, mse - -# ======================= gradient tracking ===================================== -# Calculate the true solution with gradient tracking (GT for short): -# -# w^{k+1} = neighbor_allreduce(w^k) - alpha*q^k -# q^{k+1} = neighbor_allreduce(q^k) + grad(w^{k+1}) - grad(w^k) -# where q^0 = grad(w^0) -# -# Reference: -# [R1] A. Nedic, A. Olshevsky, and W. Shi, ``Achieving geometric convergence -# for distributed optimization over time-varying graphs'', 2017. (Alg. 1) -# -# [R2] G. Qu and N. Li, ``Harnessing smoothness to accelerate distributed -# optimization'', 2018 -# -# [R3] J. Xu et.al., ``Augmented distributed gradient methods for multi-agent -# optimization under uncoordinated constant stepsizes'', 2015 -# -# [R4] P. Di Lorenzo and G. Scutari, ``Next: In-network nonconvex optimization'', -# 2016 -# ================================================================================ -def gradient_tracking(w_opt, rho, beta, maxite=2000, alpha_gt=1e-1): - w = torch.zeros(n, 1, dtype=torch.double, requires_grad=True) - logistic_loss_step( - w, rho, beta, tensor_name='neighbor.allreduce.Grad.Tracking.w') - q = w.grad.data # q^0 = grad(w^0) - w.grad.data.zero_() - - grad_prev = q.clone() - mse_gt = [] - for i in range(maxite): - - # Algorithm: - # w^{k+1} = neighbor_allreduce(w^k) - alpha*q^k - # q^{k+1} = neighbor_allreduce(q^k) + grad(w^{k+1}) - grad(w^k) - - # Notice the communication of neighbor_allreduce can overlap with gradient computation. - w_handle = bf.neighbor_allreduce_nonblocking(w.data, name='Grad.Tracking.w') - q_handle = bf.neighbor_allreduce_nonblocking(q, name='Grad.Tracking.q') - w.data = bf.synchronize(w_handle) - alpha_gt * q - # calculate local gradient - logistic_loss_step( - w, rho, beta, tensor_name='neighbor.allreduce.Grad.Tracking.w') - grad = w.grad.data.clone() - q = bf.synchronize(q_handle) + grad - grad_prev - grad_prev = grad - w.grad.data.zero_() - - # record convergence - if bf.rank() == 0: - mse_gt.append(torch.norm(w.data - w_opt.data, p=2)) - - return w, mse_gt - -# ======================= Push-DIGing for directed graph ======================= -# Calculate the true solution with Push-DIGing: -# -# Reference: -# -# [R1] A. Nedic, A. Olshevsky, and W. Shi, ``Achieving geometric convergence -# for distributed optimization over time-varying graphs'', 2017. (Alg. 2) -# ============================================================================ -def push_diging(w_opt, rho, beta, maxite=2000, alpha_pd=1e-1): - bf.set_topology(topology_util.PowerGraph(bf.size())) - outdegree = len(bf.out_neighbor_ranks()) - indegree = len(bf.in_neighbor_ranks()) - - # u, y, v = w[:n], w[n:2*n], w[2n] - w = torch.zeros(2*n+1, 1).to(torch.double) - x = torch.zeros(n, 1, dtype=torch.double, requires_grad=True) - - logistic_loss_step(x, rho, beta, tensor_name='w_buff') - grad = x.grad.data.clone() - w[n:2*n] = grad - x.grad.data.zero_() - - w[-1] = 1.0 - grad_prev = w[n:2*n].clone() - - bf.win_create(w, name="w_buff", zero_init=True) - - mse_pd = [] - for i in range(maxite): - w[:n] = w[:n] - alpha_pd*w[n:2*n] - bf.win_accumulate( - w, name="w_buff", - dst_weights={rank: 1.0 / (outdegree*2) - for rank in bf.out_neighbor_ranks()}, - require_mutex=True) - w.div_(2) - w = bf.win_update_then_collect(name="w_buff") - - x.data = w[:n]/w[-1] - logistic_loss_step(x, rho, beta, tensor_name='w_buff') - grad = x.grad.data.clone() - x.grad.data.zero_() - - w[n:2*n] += grad - grad_prev - grad_prev = grad - if i % 10 == 0: - bf.barrier() - if bf.rank() == 0: - mse_pd.append(torch.norm(x.data - w_opt, p=2)) - - bf.barrier() - w = bf.win_update_then_collect(name="w_buff") - x.data = w[:n]/w[-1] - - return x, mse_pd - - -# ======================= Code starts here ======================= -bf.init() - -# The logistic regression problem is -# min_w (1/n)*\sum_i ln(1 + exp(-y_i*X_i'*w)) + 0.5*rho*|w|^2 -# where each rank i holds a local dataset (X_i, y_i). -# In (X_i, y_i), X_i is data and y_i is lable. -# We expect each rank will converge to the global solution after the algorithm - -# Generate data for logistic regression (synthesized data) -torch.random.manual_seed(123417 * bf.rank()) -m, n = 20, 5 -X = torch.randn(m, n).to(torch.double) -w_0 = torch.randn(n, 1).to(torch.double) -y = torch.rand(m, 1).to(torch.double) < 1 / (1+torch.exp(X.mm(w_0))) -y = y.double() -y = 2*y - 1 -rho = 1e-3 -beta = 1 - -# calculate the global solution w_opt via distributed gradient descent -w_opt = distributed_grad_descent(rho, beta) - -# solve the logistic regression with indicated decentralized algorithms -if args.method == 'exact_diffusion': - w, mse = exact_diffusion(w_opt, rho, beta, maxite=args.max_iter) -elif args.method == 'gradient_tracking': - w, mse = gradient_tracking(w_opt, rho, beta, maxite=args.max_iter) -elif args.method == 'push_diging': - w, mse = push_diging(w_opt, rho, beta, maxite=args.max_iter) -else: - raise NotImplementedError( - 'Algorithm not support. This example only supports' + - ' exact_diffusion, gradient_tracking, and push_diging' - ) - -# plot and print result -if bf.rank() == 0: - plt.semilogy(mse) - finalize_plot() - -# calculate local and global gradient -logistic_loss_step(w, rho, beta, tensor_name="w_buff") -grad = bf.allreduce(w.grad.data, name='gradient') # global gradient - -# evaluate the convergence of gradient tracking for logistic regression -# the norm of global gradient is expected to be 0 (optimality condition) -global_grad_norm = torch.norm(grad, p=2) -print("[{}] Rank {}: global gradient norm: {}".format( - args.method, bf.rank(), global_grad_norm)) - -# the norm of local gradient is expected not to be close to 0 -# this is because each rank converges to global solution, not local solution -local_grad_norm = torch.norm(w.grad.data, p=2) -print("[{}] Rank {}: local gradient norm: {}".format( - args.method, bf.rank(), local_grad_norm)) diff --git a/examples/tensorflow2_mnist.py b/examples/tensorflow2_mnist.py deleted file mode 100644 index 258d8522..00000000 --- a/examples/tensorflow2_mnist.py +++ /dev/null @@ -1,92 +0,0 @@ -# Modifications copyright (C) 2020 Bluefog Team. All Rights Reserved. -# Copyright 2019 Uber Technologies, Inc. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -import tensorflow as tf -import bluefog.tensorflow as bf - -# Bluefog: initialize Bluefog. -bf.init() - -# Bluefog: pin GPU to be used to process local rank (one GPU per process) -gpus = tf.config.experimental.list_physical_devices('GPU') -for gpu in gpus: - tf.config.experimental.set_memory_growth(gpu, True) -if gpus: - tf.config.experimental.set_visible_devices(gpus[bf.local_rank()], 'GPU') - -(mnist_images, mnist_labels), _ = \ - tf.keras.datasets.mnist.load_data(path='mnist-%d.npz' % bf.rank()) - -dataset = tf.data.Dataset.from_tensor_slices( - (tf.cast(mnist_images[..., tf.newaxis] / 255.0, tf.float32), - tf.cast(mnist_labels, tf.int64)) -) -dataset = dataset.repeat().shuffle(10000).batch(128) - -mnist_model = tf.keras.Sequential([ - tf.keras.layers.Conv2D(32, [3, 3], activation='relu'), - tf.keras.layers.Conv2D(64, [3, 3], activation='relu'), - tf.keras.layers.MaxPooling2D(pool_size=(2, 2)), - tf.keras.layers.Dropout(0.25), - tf.keras.layers.Flatten(), - tf.keras.layers.Dense(128, activation='relu'), - tf.keras.layers.Dropout(0.5), - tf.keras.layers.Dense(10, activation='softmax') -]) -loss = tf.losses.SparseCategoricalCrossentropy() - -# Bluefog: adjust learning rate based on number of GPUs. -opt = tf.optimizers.SGD(0.01 * bf.size()) - - -@tf.function -def training_step(imgs, labels_, is_fisrt_batch): - with tf.GradientTape() as tape: - probs = mnist_model(imgs, training=True) - _loss_value = loss(labels_, probs) - tf.print("_loss_value: ", _loss_value) - - # Bluefog: add Bluefog Distributed GradientTape. - tape = bf.DistributedGradientTape(tape) - - grads = tape.gradient(_loss_value, mnist_model.trainable_variables) - opt.apply_gradients(zip(grads, mnist_model.trainable_variables)) - # Bluefog: broadcast initial variable states from rank 0 to all other processes. - # This is necessary to ensure consistent initialization of all workers when - # training is started with random weights or restored from a checkpoint. - # - # Note: broadcast should be done after the first gradient step to ensure optimizer - # initialization. - if is_fisrt_batch: - bf.broadcast_variables( - mnist_model.variables + opt.variables(), root_rank=0) - tf.print("broadcast is Done!") - - return _loss_value - - -tf.config.experimental_run_functions_eagerly(False) - -#TODO(ybc) Unfortunately, the tensorflow code won't work because the tensorflow is triggered -# through the graph flow engine so that the parallel ops can occur with any order. The mismatch -# of allreduce/broadcast order will cause the procedure crash or hang. -# One-sided ops can avoid this problem in theory. - -# Bluefog: adjust number of steps based on number of GPUs. -for batch, (images, labels) in enumerate(dataset.take(10000 // bf.size())): - loss_value = training_step(images, labels, batch == 0) - if batch % 2 == 0 and bf.local_rank() == 0: - print('Step #%d\tLoss: %.6f' % (batch, loss_value)) diff --git a/examples/pytorch_opt_linear_speedup_test.py b/scripts/pytorch_opt_linear_speedup_test.py similarity index 100% rename from examples/pytorch_opt_linear_speedup_test.py rename to scripts/pytorch_opt_linear_speedup_test.py From a6228c2c90268eaf59619627fcfbd68385e920be Mon Sep 17 00:00:00 2001 From: ybc Date: Sat, 31 Oct 2020 16:50:38 -0700 Subject: [PATCH 33/44] Add hier n_ar for mpi case --- bluefog/common/mpi_controller.cc | 111 ++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 38 deletions(-) diff --git a/bluefog/common/mpi_controller.cc b/bluefog/common/mpi_controller.cc index aa62efef..c3b6eac5 100644 --- a/bluefog/common/mpi_controller.cc +++ b/bluefog/common/mpi_controller.cc @@ -299,6 +299,12 @@ bool CheckNeighborSendRecvPattern(int size, const TensorTableEntry& entry, // enabled the check if enable_topo_check is true and partial // neighbor_allreduce is activated. if (entry.enable_topo_check && !entry.send_neighbors->empty()) { + if (entry.is_hierarchical) { + // TODO: support check. + BFLOG(INFO) << "Request to check topology for hierarchical neighbor " + << "allreduce ops but it is not supported yet."; + return res; + } timeline_ptr->ActivityStart(entry.tensor_name, "NEGOTIATION"); // Put all the send and recv neighbors in a single vector, and obtain a send // matrix and a recv matrix through MPI_Allgather. @@ -363,11 +369,6 @@ std::string GenerateNeighborAllreduceErrorMessage(const std::vector& void MPIController::NeighborAllreduce(TensorTableEntry& entry) { const void* sendbuf = entry.tensor->data(); int num_elements = entry.tensor->shape().num_elements(); - // TODO(ybc) support this - if (entry.is_hierarchical) { - throw std::runtime_error( - "hierarchical neighbor_allreduce is only supported under NCCL case."); - } Timeline* timeline_ptr; Status timeline_status = GetBluefogTimeline(timeline_ptr); @@ -401,44 +402,78 @@ void MPIController::NeighborAllreduce(TensorTableEntry& entry) { // is no need to transfer the local info again. However, for computation view, // including itself is more intuitive. std::string error_message = ""; - if (entry.send_neighbors->empty()) { - int ret_code = MPI_Neighbor_allgather( - sendbuf, num_elements, mpi_ctx_.GetMPIDataType(entry.tensor), buffer_data, - num_elements, mpi_ctx_.GetMPIDataType(entry.output), - mpi_ctx_.GetMPICommunicator(Communicator::GRAPH)); - if (ret_code != MPI_SUCCESS) { - throw std::runtime_error( - "MPI_Neighbor_allreduce (through neighbor_allgather) failed, see MPI " - "output for details."); - } - } else { - int nsend = entry.send_neighbors->size(); - int nrecv = entry.recv_neighbors->size(); - std::vector requests(nsend+nrecv); - std::vector statuses(nsend+nrecv); - int element_size = mpi_ctx_.GetMPITypeSize(entry.output->dtype()); - for (int i = 0; i < nrecv; ++i) { - void* recvbuf = (void*)(static_cast(entry.output->data()) - +num_elements*i*element_size); - int ret_code = MPI_Irecv(recvbuf, num_elements, mpi_ctx_.GetMPIDataType(entry.output), - entry.recv_neighbors->at(i), mpi_ctx_.rank_+entry.recv_neighbors->at(i), - mpi_ctx_.GetMPICommunicator(Communicator::GRAPH), &requests[i+nsend]); + + if (!entry.is_hierarchical) { + if (entry.send_neighbors->empty()) { + int ret_code = MPI_Neighbor_allgather( + sendbuf, num_elements, mpi_ctx_.GetMPIDataType(entry.tensor), + buffer_data, num_elements, mpi_ctx_.GetMPIDataType(entry.output), + mpi_ctx_.GetMPICommunicator(Communicator::GRAPH)); if (ret_code != MPI_SUCCESS) { throw std::runtime_error( - "MPI_Irecv (for dynamic neighbor_allreduce) failed, see MPI output for details."); + "MPI_Neighbor_allreduce (through neighbor_allgather) failed, see " + "MPI " + "output for details."); } - } - for (int i = 0; i < nsend; ++i) { - int ret_code = MPI_Isend(sendbuf, num_elements, mpi_ctx_.GetMPIDataType(entry.tensor), - entry.send_neighbors->at(i), mpi_ctx_.rank_+entry.send_neighbors->at(i), - mpi_ctx_.GetMPICommunicator(Communicator::GRAPH), &requests[i]); - if (ret_code != MPI_SUCCESS) { - throw std::runtime_error( - "MPI_Isend (for dynamic neighbor_allreduce) failed, see MPI output for details."); + } else { + int nsend = entry.send_neighbors->size(); + int nrecv = entry.recv_neighbors->size(); + std::vector requests(nsend + nrecv); + std::vector statuses(nsend + nrecv); + int element_size = mpi_ctx_.GetMPITypeSize(entry.output->dtype()); + for (int i = 0; i < nrecv; ++i) { + void* recvbuf = (void*)(static_cast(entry.output->data()) + + num_elements * i * element_size); + int ret_code = MPI_Irecv( + recvbuf, num_elements, mpi_ctx_.GetMPIDataType(entry.output), + entry.recv_neighbors->at(i), + mpi_ctx_.rank_ + entry.recv_neighbors->at(i), + mpi_ctx_.GetMPICommunicator(Communicator::GRAPH), + &requests[i + nsend]); + if (ret_code != MPI_SUCCESS) { + throw std::runtime_error( + "MPI_Irecv (for dynamic neighbor_allreduce) failed, see MPI " + "output for details."); + } } + for (int i = 0; i < nsend; ++i) { + int ret_code = MPI_Isend( + sendbuf, num_elements, mpi_ctx_.GetMPIDataType(entry.tensor), + entry.send_neighbors->at(i), + mpi_ctx_.rank_ + entry.send_neighbors->at(i), + mpi_ctx_.GetMPICommunicator(Communicator::GRAPH), &requests[i]); + if (ret_code != MPI_SUCCESS) { + throw std::runtime_error( + "MPI_Isend (for dynamic neighbor_allreduce) failed, see MPI " + "output for details."); + } + } + MPI_Waitall(nsend + nrecv, requests.data(), statuses.data()); + error_message = + GenerateNeighborAllreduceErrorMessage(statuses, nsend, nrecv); + } + } else { + if (entry.send_neighbors->empty()) { + throw std::runtime_error( + "Under hierarchical neighbor_allreduce, argument " + "send_machine_neighbors should not be empty."); + } + if (mpi_ctx_.local_size_ < 2) { + throw std::runtime_error( + "Local size is smaller than 2, in this case, you should use " + "neighbor_allreduce instead of hierarchical_neighbor_allreduce."); } - MPI_Waitall(nsend+nrecv, requests.data(), statuses.data()); - error_message = GenerateNeighborAllreduceErrorMessage(statuses, nsend, nrecv); + // 1. In-place allreduce + MPI_Allreduce(MPI_IN_PLACE, (void*)sendbuf, num_elements, + mpi_ctx_.GetMPIDataType(entry.tensor), MPI_SUM, + mpi_ctx_.GetMPICommunicator(Communicator::LOCAL)); + // 2. Local_rank = 0 do the neighbor all with other machines local_rank=0. + + // 3. Broadcast recv data from local rank = 0 to other local ranks. + int recv_num_elements = num_elements * entry.recv_neighbors->size(); + MPI_Bcast(buffer_data, recv_num_elements, + mpi_ctx_.GetMPIDataType(entry.output), 0, + mpi_ctx_.GetMPICommunicator(Communicator::LOCAL)); } timeline_ptr->ActivityEnd(entry.tensor_name); From c77cb0090f616f40700e1db835726ed115c84e6f Mon Sep 17 00:00:00 2001 From: ybc Date: Sat, 31 Oct 2020 16:58:38 -0700 Subject: [PATCH 34/44] Update mpi h_nar --- bluefog/common/mpi_controller.cc | 40 +++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/bluefog/common/mpi_controller.cc b/bluefog/common/mpi_controller.cc index c3b6eac5..9be5890a 100644 --- a/bluefog/common/mpi_controller.cc +++ b/bluefog/common/mpi_controller.cc @@ -468,7 +468,45 @@ void MPIController::NeighborAllreduce(TensorTableEntry& entry) { mpi_ctx_.GetMPIDataType(entry.tensor), MPI_SUM, mpi_ctx_.GetMPICommunicator(Communicator::LOCAL)); // 2. Local_rank = 0 do the neighbor all with other machines local_rank=0. - + if (mpi_ctx_.local_rank_ == 0) { + int nsend = entry.send_neighbors->size(); + int nrecv = entry.recv_neighbors->size(); + std::vector requests(nsend + nrecv); + std::vector statuses(nsend + nrecv); + int element_size = mpi_ctx_.GetMPITypeSize(entry.output->dtype()); + for (int i = 0; i < nrecv; ++i) { + void* recvbuf = (void*)(static_cast(entry.output->data()) + + num_elements * i * element_size); + int ret_code = MPI_Irecv( + recvbuf, num_elements, mpi_ctx_.GetMPIDataType(entry.output), + entry.recv_neighbors->at(i), + mpi_ctx_.rank_ + entry.recv_neighbors->at(i), + mpi_ctx_.GetMPICommunicator(Communicator::GRAPH), + &requests[i + nsend]); + if (ret_code != MPI_SUCCESS) { + throw std::runtime_error( + "MPI_Irecv (for dynamic neighbor_allreduce) failed, see MPI " + "output for details."); + } + } + for (int i = 0; i < nsend; ++i) { + int ret_code = MPI_Isend( + sendbuf, num_elements, mpi_ctx_.GetMPIDataType(entry.tensor), + entry.send_neighbors->at(i), + mpi_ctx_.rank_ + entry.send_neighbors->at(i), + mpi_ctx_.GetMPICommunicator(Communicator::GRAPH), &requests[i]); + if (ret_code != MPI_SUCCESS) { + throw std::runtime_error( + "MPI_Isend (for dynamic neighbor_allreduce) failed, see MPI " + "output for details."); + } + } + MPI_Waitall(nsend + nrecv, requests.data(), statuses.data()); + error_message = + GenerateNeighborAllreduceErrorMessage(statuses, nsend, nrecv); + } else { + // Do nothing here. + } // 3. Broadcast recv data from local rank = 0 to other local ranks. int recv_num_elements = num_elements * entry.recv_neighbors->size(); MPI_Bcast(buffer_data, recv_num_elements, From d85766c23307102e8dea8c3e25a3475068c4315a Mon Sep 17 00:00:00 2001 From: ybc Date: Sat, 31 Oct 2020 17:02:23 -0700 Subject: [PATCH 35/44] Remove the modula device count since we support only at most one device with process on in NCCL --- examples/pytorch_ImageNet_Resnet50.py | 2 +- examples/pytorch_benchmark.py | 2 +- examples/pytorch_cifar10_resnet.py | 2 +- examples/pytorch_mnist.py | 2 +- scripts/pytorch_opt_linear_speedup_test.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/pytorch_ImageNet_Resnet50.py b/examples/pytorch_ImageNet_Resnet50.py index 9bc2ed2d..2e50301e 100644 --- a/examples/pytorch_ImageNet_Resnet50.py +++ b/examples/pytorch_ImageNet_Resnet50.py @@ -103,7 +103,7 @@ if args.cuda: # Bluefog: pin GPU to local rank. - torch.cuda.set_device(bf.local_rank() % torch.cuda.device_count()) + torch.cuda.set_device(bf.local_rank()) torch.cuda.manual_seed(args.seed) cudnn.benchmark = True diff --git a/examples/pytorch_benchmark.py b/examples/pytorch_benchmark.py index 03c22e1c..6b4494b5 100644 --- a/examples/pytorch_benchmark.py +++ b/examples/pytorch_benchmark.py @@ -95,7 +95,7 @@ "[power2(Default), ring, mesh, star,InnerOuterRing, InnerOuterExp2].") if args.cuda: - torch.cuda.set_device(bf.local_rank() % torch.cuda.device_count()) + torch.cuda.set_device(bf.local_rank()) cudnn.benchmark = True # Set up standard model. diff --git a/examples/pytorch_cifar10_resnet.py b/examples/pytorch_cifar10_resnet.py index 32bdd1cc..35a36666 100644 --- a/examples/pytorch_cifar10_resnet.py +++ b/examples/pytorch_cifar10_resnet.py @@ -124,7 +124,7 @@ if args.cuda: print("using cuda.") # Bluefog: pin GPU to local rank. - torch.cuda.set_device(bf.local_rank() % torch.cuda.device_count()) + torch.cuda.set_device(bf.local_rank()) torch.cuda.manual_seed(args.seed) else: print("using cpu") diff --git a/examples/pytorch_mnist.py b/examples/pytorch_mnist.py index 358b2111..14d99017 100644 --- a/examples/pytorch_mnist.py +++ b/examples/pytorch_mnist.py @@ -113,7 +113,7 @@ if args.cuda: # Bluefog: pin GPU to local rank. - torch.cuda.set_device(bf.local_rank() % torch.cuda.device_count()) + torch.cuda.set_device(bf.local_rank()) torch.cuda.manual_seed(args.seed) diff --git a/scripts/pytorch_opt_linear_speedup_test.py b/scripts/pytorch_opt_linear_speedup_test.py index 0408b8e7..d53e4c95 100644 --- a/scripts/pytorch_opt_linear_speedup_test.py +++ b/scripts/pytorch_opt_linear_speedup_test.py @@ -75,7 +75,7 @@ bf.init() if args.cuda: - torch.cuda.set_device(bf.local_rank() % torch.cuda.device_count()) + torch.cuda.set_device(bf.local_rank()) cudnn.benchmark = True def logistic_loss_step(x_, rho, X, y, tensor_name, calculate_by_hand=True): From e266ca6196afa25874596d172c68a743b06ffa69 Mon Sep 17 00:00:00 2001 From: ybc Date: Sat, 31 Oct 2020 17:09:08 -0700 Subject: [PATCH 36/44] Add h_nar for fused case --- bluefog/common/mpi_controller.cc | 145 +++++++++++++++++++++---------- 1 file changed, 101 insertions(+), 44 deletions(-) diff --git a/bluefog/common/mpi_controller.cc b/bluefog/common/mpi_controller.cc index 9be5890a..7276a71a 100644 --- a/bluefog/common/mpi_controller.cc +++ b/bluefog/common/mpi_controller.cc @@ -569,11 +569,6 @@ void MPIController::Allreduce(std::vector& entries) { void MPIController::NeighborAllreduce(std::vector& entries) { auto& first_entry = entries[0]; with_device device_guard(first_entry.device); - // TODO(ybc) support this - if (first_entry.is_hierarchical) { - throw std::runtime_error( - "hierarchical neighbor_allreduce is only supported under NCCL case."); - } void* buffer_data; size_t buffer_len = 0; @@ -619,51 +614,113 @@ void MPIController::NeighborAllreduce(std::vector& entries) { // is no need to transfer the local info again. However, for computation view, // including itself is more intuitive. std::string error_message = ""; - if (first_entry.send_neighbors->empty()) { - int ret_code = MPI_Neighbor_allgather( - fused_input_data, num_elements, mpi_ctx_.GetMPIDataType(first_entry.tensor), - buffer_data, num_elements, mpi_ctx_.GetMPIDataType(first_entry.output), - mpi_ctx_.GetMPICommunicator(Communicator::GRAPH)); - if (ret_code != MPI_SUCCESS) { - throw std::runtime_error( - "MPI_Neighbor_allreduce (through neighbor_allgather) failed, see MPI " - "output for details."); - } - } else { - int nsend = first_entry.send_neighbors->size(); - int nrecv = first_entry.recv_neighbors->size(); - std::vector requests(nsend + nrecv); - std::vector statuses(nsend + nrecv); - for (int i = 0; i < nrecv; ++i) { - void* recvbuf = - (void*)((uint8_t*)buffer_data + num_elements * i * element_size); - int ret_code = MPI_Irecv(recvbuf, num_elements, - mpi_ctx_.GetMPIDataType(first_entry.output), - first_entry.recv_neighbors->at(i), - /*tag=*/mpi_ctx_.rank_ + first_entry.recv_neighbors->at(i), - mpi_ctx_.GetMPICommunicator(Communicator::GRAPH), - &requests[i + nsend]); + + if (!first_entry.is_hierarchical) { + if (first_entry.send_neighbors->empty()) { + int ret_code = MPI_Neighbor_allgather( + fused_input_data, num_elements, mpi_ctx_.GetMPIDataType(first_entry.tensor), + buffer_data, num_elements, mpi_ctx_.GetMPIDataType(first_entry.output), + mpi_ctx_.GetMPICommunicator(Communicator::GRAPH)); if (ret_code != MPI_SUCCESS) { throw std::runtime_error( - "MPI_Irecv (for dynamic neighbor_allreduce) failed, see MPI output " - "for details."); + "MPI_Neighbor_allreduce (through neighbor_allgather) failed, see MPI " + "output for details."); + } + } else { + int nsend = first_entry.send_neighbors->size(); + int nrecv = first_entry.recv_neighbors->size(); + std::vector requests(nsend + nrecv); + std::vector statuses(nsend + nrecv); + for (int i = 0; i < nrecv; ++i) { + void* recvbuf = + (void*)((uint8_t*)buffer_data + num_elements * i * element_size); + int ret_code = MPI_Irecv(recvbuf, num_elements, + mpi_ctx_.GetMPIDataType(first_entry.output), + first_entry.recv_neighbors->at(i), + /*tag=*/mpi_ctx_.rank_ + first_entry.recv_neighbors->at(i), + mpi_ctx_.GetMPICommunicator(Communicator::GRAPH), + &requests[i + nsend]); + if (ret_code != MPI_SUCCESS) { + throw std::runtime_error( + "MPI_Irecv (for dynamic neighbor_allreduce) failed, see MPI output " + "for details."); + } + } + for (int i = 0; i < nsend; ++i) { + int ret_code = MPI_Isend( + fused_input_data, num_elements, mpi_ctx_.GetMPIDataType(first_entry.tensor), + first_entry.send_neighbors->at(i), + /*tag=*/mpi_ctx_.rank_ + first_entry.send_neighbors->at(i), + mpi_ctx_.GetMPICommunicator(Communicator::GRAPH), &requests[i]); + if (ret_code != MPI_SUCCESS) { + throw std::runtime_error( + "MPI_Isend (for dynamic neighbor_allreduce) failed, see MPI output " + "for details."); + } } + MPI_Waitall(nsend + nrecv, requests.data(), statuses.data()); + error_message = + GenerateNeighborAllreduceErrorMessage(statuses, nsend, nrecv); } - for (int i = 0; i < nsend; ++i) { - int ret_code = MPI_Isend( - fused_input_data, num_elements, mpi_ctx_.GetMPIDataType(first_entry.tensor), - first_entry.send_neighbors->at(i), - /*tag=*/mpi_ctx_.rank_ + first_entry.send_neighbors->at(i), - mpi_ctx_.GetMPICommunicator(Communicator::GRAPH), &requests[i]); - if (ret_code != MPI_SUCCESS) { - throw std::runtime_error( - "MPI_Isend (for dynamic neighbor_allreduce) failed, see MPI output " - "for details."); + } else { + if (first_entry.send_neighbors->empty()) { + throw std::runtime_error( + "Under hierarchical neighbor_allreduce, argument " + "send_machine_neighbors should not be empty."); + } + if (mpi_ctx_.local_size_ < 2) { + throw std::runtime_error( + "Local size is smaller than 2, in this case, you should use " + "neighbor_allreduce instead of hierarchical_neighbor_allreduce."); + } + // 1. In-place allreduce + MPI_Allreduce(MPI_IN_PLACE, (void*)fused_input_data, num_elements, + mpi_ctx_.GetMPIDataType(first_entry.tensor), MPI_SUM, + mpi_ctx_.GetMPICommunicator(Communicator::LOCAL)); + // 2. Local_rank = 0 do the neighbor all with other machines local_rank=0. + if (mpi_ctx_.local_rank_ == 0) { + int nsend = first_entry.send_neighbors->size(); + int nrecv = first_entry.recv_neighbors->size(); + std::vector requests(nsend + nrecv); + std::vector statuses(nsend + nrecv); + for (int i = 0; i < nrecv; ++i) { + void* recvbuf = + (void*)((uint8_t*)buffer_data + num_elements * i * element_size); + int ret_code = MPI_Irecv(recvbuf, num_elements, + mpi_ctx_.GetMPIDataType(first_entry.output), + first_entry.recv_neighbors->at(i), + /*tag=*/mpi_ctx_.rank_ + first_entry.recv_neighbors->at(i), + mpi_ctx_.GetMPICommunicator(Communicator::GRAPH), + &requests[i + nsend]); + if (ret_code != MPI_SUCCESS) { + throw std::runtime_error( + "MPI_Irecv (for dynamic neighbor_allreduce) failed, see MPI output " + "for details."); + } + } + for (int i = 0; i < nsend; ++i) { + int ret_code = MPI_Isend( + fused_input_data, num_elements, mpi_ctx_.GetMPIDataType(first_entry.tensor), + first_entry.send_neighbors->at(i), + /*tag=*/mpi_ctx_.rank_ + first_entry.send_neighbors->at(i), + mpi_ctx_.GetMPICommunicator(Communicator::GRAPH), &requests[i]); + if (ret_code != MPI_SUCCESS) { + throw std::runtime_error( + "MPI_Isend (for dynamic neighbor_allreduce) failed, see MPI output " + "for details."); + } } + MPI_Waitall(nsend + nrecv, requests.data(), statuses.data()); + error_message = + GenerateNeighborAllreduceErrorMessage(statuses, nsend, nrecv); + } else { + // Do nothing here. } - MPI_Waitall(nsend + nrecv, requests.data(), statuses.data()); - error_message = - GenerateNeighborAllreduceErrorMessage(statuses, nsend, nrecv); + // 3. Broadcast recv data from local rank = 0 to other local ranks. + int recv_num_elements = num_elements * first_entry.recv_neighbors->size(); + MPI_Bcast(buffer_data, recv_num_elements, + mpi_ctx_.GetMPIDataType(first_entry.output), 0, + mpi_ctx_.GetMPICommunicator(Communicator::LOCAL)); } timeline_ptr->ActivityEndAll(entries); From 38db5b505653b8a87ee792090931e812c4355356 Mon Sep 17 00:00:00 2001 From: ybc Date: Sat, 31 Oct 2020 17:25:05 -0700 Subject: [PATCH 37/44] Add the missing MemcpyOutFusionBufferForInputs for h_nar --- bluefog/common/mpi_controller.cc | 26 ++++++++++++++++++++++++++ bluefog/common/mpi_controller.h | 3 +++ 2 files changed, 29 insertions(+) diff --git a/bluefog/common/mpi_controller.cc b/bluefog/common/mpi_controller.cc index 7276a71a..22e8baae 100644 --- a/bluefog/common/mpi_controller.cc +++ b/bluefog/common/mpi_controller.cc @@ -716,6 +716,8 @@ void MPIController::NeighborAllreduce(std::vector& entries) { } else { // Do nothing here. } + // Because the in-place modification, we need to copy fused_input_data back to tensor as well + MemcpyOutFusionBufferForInputs(fused_input_data, entries); // 3. Broadcast recv data from local rank = 0 to other local ranks. int recv_num_elements = num_elements * first_entry.recv_neighbors->size(); MPI_Bcast(buffer_data, recv_num_elements, @@ -1321,6 +1323,30 @@ void MPIController::MemcpyOutFusionBufferForNeighbors( } } +void MPIController::MemcpyOutFusionBufferForInputs( + const void* fused_input_data, std::vector& entries) { + // Copy the input data stored in the fusion buffer back to input, which is + // used in hierarchical neighbor allreduce since it has allreduce step to + // modified the input data. + int64_t offset = 0; + for (auto& e : entries) { + void* fused_input_data_at_offset = (uint8_t*)fused_input_data + offset; + void* dst_data = (void*)e.tensor->data(); + size_t count = (size_t)e.tensor->size(); +#if HAVE_CUDA + if (e.device != CPU_DEVICE_ID) { + CUDACHECK(cudaMemcpy(dst_data, fused_input_data_at_offset, count, + cudaMemcpyDeviceToDevice)); + } else { +#endif + std::memcpy(dst_data, fused_input_data, count); +#if HAVE_CUDA + } +#endif + offset += e.tensor->size(); + } +} + void MPIController::MemcpyEntryInFusionBuffer(const TensorTableEntry& e, void* buffer_data_at_offset) { const void* src_data = e.tensor->data(); diff --git a/bluefog/common/mpi_controller.h b/bluefog/common/mpi_controller.h index 64946159..75f4e245 100644 --- a/bluefog/common/mpi_controller.h +++ b/bluefog/common/mpi_controller.h @@ -116,6 +116,9 @@ class MPIController { const int num_recv_neighbors, const int64_t fused_data_size); + void MemcpyOutFusionBufferForInputs(const void* fused_input_data, + std::vector& entries); + void MemcpyEntryInFusionBuffer(const TensorTableEntry& e, void* buffer_data_at_offset); From cf481e127deccb9ee3e3665a22d2d135ff99d8ce Mon Sep 17 00:00:00 2001 From: ybc Date: Sat, 31 Oct 2020 22:29:29 -0700 Subject: [PATCH 38/44] Remove mesh/star topo in examples --- examples/pytorch_ImageNet_Resnet50.py | 6 ------ examples/pytorch_benchmark.py | 5 ----- examples/pytorch_cifar10_resnet.py | 7 ------- examples/pytorch_mnist.py | 4 +--- 4 files changed, 1 insertion(+), 21 deletions(-) diff --git a/examples/pytorch_ImageNet_Resnet50.py b/examples/pytorch_ImageNet_Resnet50.py index 2e50301e..fedb7b03 100644 --- a/examples/pytorch_ImageNet_Resnet50.py +++ b/examples/pytorch_ImageNet_Resnet50.py @@ -92,11 +92,6 @@ pass elif args.virtual_topology == "ring": bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=1)) - elif args.virtual_topology == "mesh": - bf.set_topology(topology_util.MeshGrid2DGraph( - bf.size()), is_weighted=True) - elif args.virtual_topology == "star": - bf.set_topology(topology_util.StarGraph(bf.size())) else: raise ValueError("Unknown args.virtual_topology, supporting options are " + "[power2(Default), ring, mesh, star].") @@ -180,7 +175,6 @@ momentum=args.momentum, weight_decay=args.wd) # Bluefog: wrap optimizer with DistributedOptimizer. -# TODO(hhb) Pass batches_per_allreduce to optimizer. if args.dist_optimizer == 'win_put': optimizer = bf.DistributedWinPutOptimizer(optimizer, model=model) elif args.dist_optimizer == 'neighbor_allreduce': diff --git a/examples/pytorch_benchmark.py b/examples/pytorch_benchmark.py index 6b4494b5..32678cf4 100644 --- a/examples/pytorch_benchmark.py +++ b/examples/pytorch_benchmark.py @@ -77,11 +77,6 @@ pass elif args.virtual_topology == "ring": bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=1)) - elif args.virtual_topology == "mesh": - bf.set_topology(topology_util.MeshGrid2DGraph( - bf.size()), is_weighted=True) - elif args.virtual_topology == "star": - bf.set_topology(topology_util.StarGraph(bf.size())) elif args.virtual_topology == "InnerOuterRing": assert bf.is_homogeneous, "InnerOuterRing topo should be used only homogeneous environment" bf.set_topology(topology_util.InnerOuterRingGraph( diff --git a/examples/pytorch_cifar10_resnet.py b/examples/pytorch_cifar10_resnet.py index 35a36666..ee72f7fc 100644 --- a/examples/pytorch_cifar10_resnet.py +++ b/examples/pytorch_cifar10_resnet.py @@ -104,11 +104,6 @@ pass elif args.virtual_topology == "ring": bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=1)) - elif args.virtual_topology == "mesh": - bf.set_topology(topology_util.MeshGrid2DGraph( - bf.size()), is_weighted=True) - elif args.virtual_topology == "star": - bf.set_topology(topology_util.StarGraph(bf.size())) elif args.virtual_topology == "InnerOuterRing": assert bf.is_homogeneous, "InnerOuterRing topo should be used only homogeneous environment" bf.set_topology(topology_util.InnerOuterRingGraph( @@ -233,8 +228,6 @@ optimizer = optimizer = bf.DistributedOptimizer( optimizer, named_parameters=model.named_parameters() ) -elif args.dist_optimizer == 'pull_get': - optimizer = bf.DistributedPullGetOptimizer(optimizer, model=model) else: raise ValueError('Unknown args.dist-optimizer type -- ' + args.dist_optimizer + '\n' + 'Please set the argument to be one of ' + diff --git a/examples/pytorch_mnist.py b/examples/pytorch_mnist.py index 14d99017..0faadfe5 100644 --- a/examples/pytorch_mnist.py +++ b/examples/pytorch_mnist.py @@ -210,8 +210,6 @@ def forward(self, x): optimizer = optimizer = bf.DistributedOptimizer( optimizer, named_parameters=model.named_parameters() ) -elif args.dist_optimizer == 'pull_get': - optimizer = bf.DistributedPullGetOptimizer(optimizer, model=model) else: raise ValueError('Unknown args.dist-optimizer type -- ' + args.dist_optimizer + '\n' + 'Please set the argument to be one of ' + @@ -228,7 +226,7 @@ def forward(self, x): dynamic_neighbor_allreduce_gen = topology_util.GetInnerOuterExp2DynamicSendRecvRanks( bf.size(), local_size=bf.local_size() if args.local_size == -1 else args.local_size, - self_rank=bf.rank()) + self_rank=bf.rank()) elif args.dist_optimizer == 'hierarchical_neighbor_allreduce': # This optimizer can use following dynamic topo only so far. dynamic_machine_neighbor_allreduce_gen = topology_util.GetExp2DynamicSendRecvMachineRanks( From 854e99b3c5080175c53a5e56641d0d194a97c726 Mon Sep 17 00:00:00 2001 From: ybc Date: Sun, 1 Nov 2020 13:07:45 -0800 Subject: [PATCH 39/44] Minor style update --- examples/pytorch_benchmark.py | 2 +- examples/pytorch_cifar10_resnet.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/pytorch_benchmark.py b/examples/pytorch_benchmark.py index 32678cf4..8332623c 100644 --- a/examples/pytorch_benchmark.py +++ b/examples/pytorch_benchmark.py @@ -205,7 +205,7 @@ def dynamic_topology_update(batch_idx): optimizer.neighbor_weights = { r: 1/(len(recv_neighbors) + 1) for r in recv_neighbors} optimizer.self_weight = 1 / (len(recv_neighbors) + 1) - optimizer.enable_topo_check = False + optimizer.enable_topo_check = False elif args.dist_optimizer == 'hierarchical_neighbor_allreduce': send_machines, recv_machines = next(dynamic_machine_neighbor_allreduce_gen) optimizer.send_neighbor_machines = send_machines diff --git a/examples/pytorch_cifar10_resnet.py b/examples/pytorch_cifar10_resnet.py index ee72f7fc..f9ccd533 100644 --- a/examples/pytorch_cifar10_resnet.py +++ b/examples/pytorch_cifar10_resnet.py @@ -75,8 +75,8 @@ ) parser.add_argument("--seed", type=int, default=42, help="random seed") parser.add_argument('--dist-optimizer', type=str, default='neighbor_allreduce', - help='The type of distributed optimizer. Supporting options are ' + - '[win_put, neighbor_allreduce, allreduce, pull_get, hierarchical_neighbor_allreduce, horovod]') + help='The type of distributed optimizer. Supporting options are [win_put, ' + + 'neighbor_allreduce, allreduce, hierarchical_neighbor_allreduce, horovod]') parser.add_argument("--average-test-result", action="store_true", default=False, help=("Allreduce called to average test result. Warning this will " + @@ -157,8 +157,8 @@ transform=transforms.Compose( [ transforms.ToTensor(), - transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[ - 0.229, 0.224, 0.225]), + transforms.Normalize(mean=[0.485, 0.456, 0.406], + std=[0.229, 0.224, 0.225]), ] ), ) @@ -178,8 +178,8 @@ transform=transforms.Compose( [ transforms.ToTensor(), - transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[ - 0.229, 0.224, 0.225]), + transforms.Normalize(mean=[0.485, 0.456, 0.406], + std=[0.229, 0.224, 0.225]), ] ), ) From aa4094a7629b45f9a883a4ec8e1736e39bb6eee1 Mon Sep 17 00:00:00 2001 From: ybc Date: Sun, 1 Nov 2020 17:40:15 -0800 Subject: [PATCH 40/44] PowerGraph => ExponentialGraph --- bluefog/common/basics.py | 10 ++--- bluefog/common/mpi_controller.cc | 2 +- bluefog/common/topology_util.py | 28 +++++++------- docs/timeline.rst | 2 +- examples/pytorch_ImageNet_Resnet50.py | 8 ++-- examples/pytorch_average_consensus.py | 16 ++++---- examples/pytorch_benchmark.py | 18 ++++----- examples/pytorch_cifar10_resnet.py | 44 +++++----------------- examples/pytorch_mnist.py | 18 ++++----- examples/pytorch_optimization.py | 8 ++-- scripts/pytorch_opt_linear_speedup_test.py | 10 ++--- scripts/single_ops_test.py | 16 ++++---- test/tensorflow_basics_test.py | 8 ++-- test/torch_basics_test.py | 10 ++--- test/torch_ops_test.py | 22 +++++------ test/torch_win_ops_test.py | 20 +++++----- 16 files changed, 108 insertions(+), 132 deletions(-) diff --git a/bluefog/common/basics.py b/bluefog/common/basics.py index 2e10f50a..e26b0bd2 100644 --- a/bluefog/common/basics.py +++ b/bluefog/common/basics.py @@ -51,7 +51,7 @@ def init(self, topology_fn: Optional[Callable[[int], networkx.DiGraph]] = None, Args: topology_fn: A callable function that takes size as input and return networkx.DiGraph object to decide the topology. If not provided - a default power graph (base 2) structure is called. + a default exponential graph (base 2) structure is called. is_weighted: If set to true, the neighbor ops like (win_update, neighbor_allreduce) will execute the weighted average instead, where the weight is the value used in topology matrix (including self). @@ -60,7 +60,7 @@ def init(self, topology_fn: Optional[Callable[[int], networkx.DiGraph]] = None, if topology_fn: topo = topology_fn(self.size()) else: - topo = topology_util.PowerGraph(self.size()) + topo = topology_util.ExponentialGraph(self.size()) self.set_topology(topo, is_weighted) atexit.register(self.shutdown) @@ -191,7 +191,7 @@ def set_topology(self, topology: Optional[networkx.DiGraph] = None, Args: Topo: A networkx.DiGraph object to decide the topology. If not provided - a default power graph (base 2) structure is used. + a default exponential graph (base 2) structure is used. is_weighted: If set to true, the win_update and neighbor_allreduce will execute the weighted average instead, where the weights are the value used in topology matrix (including self weight). Note win_get/win_put/win_accumulate do not use this weight @@ -207,10 +207,10 @@ def set_topology(self, topology: Optional[networkx.DiGraph] = None, >>> bf.set_topology(topology_util.RingGraph(bf.size())) """ if topology is None: - topology = topology_util.PowerGraph(size=self.size()) + topology = topology_util.ExponentialGraph(size=self.size()) if self.local_rank() == 0: logger.info( - "Topology is not specified. Default Power Two topology is used.") + "Topology is not specified. Default Exponential Two topology is used.") if not isinstance(topology, networkx.DiGraph): raise TypeError("topology must be a networkx.DiGraph obejct.") diff --git a/bluefog/common/mpi_controller.cc b/bluefog/common/mpi_controller.cc index 820c5e10..cba85dde 100644 --- a/bluefog/common/mpi_controller.cc +++ b/bluefog/common/mpi_controller.cc @@ -825,7 +825,7 @@ void MPIController::WinCreate(TensorTableEntry& entry) { win_manager->SetGlobalWin(global_mpi_win_ptr); // Build extra buffers for win_put. - // For example: size=4 power two ring topology + // For example: size=4 exponential two ring topology // r\s 0 1 2 3 // 0 g x x // 1 x g x diff --git a/bluefog/common/topology_util.py b/bluefog/common/topology_util.py index 308e02c1..6be78a38 100644 --- a/bluefog/common/topology_util.py +++ b/bluefog/common/topology_util.py @@ -63,18 +63,18 @@ def GetSendWeights(topo: nx.DiGraph, rank: int) -> Tuple[float, Dict[int, float] return self_weight, neighbor_weights -def PowerTwoRingGraph(size: int) -> nx.DiGraph: +def ExponentialTwoGraph(size: int) -> nx.DiGraph: """Generate graph topology such that each points only - connected to a point such that the index difference is power of 2. + connected to a point such that the index difference is the power of 2. - Example: A PowerTwoRingGraph with 12 nodes: + Example: A ExponentialTwoGraph with 12 nodes: .. plot:: :context: close-figs >>> import networkx as nx >>> from bluefog.common import topology_util - >>> G = topology_util.PowerTwoRingGraph(12) + >>> G = topology_util.ExponentialTwoGraph(12) >>> nx.draw_circular(G) """ assert size > 0 @@ -96,18 +96,18 @@ def isPowerOf(x, base): return False -def PowerGraph(size: int, base: int = 2) -> nx.DiGraph: +def ExponentialGraph(size: int, base: int = 2) -> nx.DiGraph: """Generate graph topology such that each points only connected to a point such that the index difference is power of base. (Default is 2) - Example: A PowerGraph with 12 nodes: + Example: A ExponentialGraph with 12 nodes: .. plot:: :context: close-figs >>> import networkx as nx >>> from bluefog.common import topology_util - >>> G = topology_util.PowerGraph(12) + >>> G = topology_util.ExponentialGraph(12) >>> nx.draw_circular(G) """ x = [1.0] @@ -125,20 +125,20 @@ def PowerGraph(size: int, base: int = 2) -> nx.DiGraph: return G -def SymmetricPowerGraph(size: int, base: int = 4) -> nx.DiGraph: +def SymmetricExponentialGraph(size: int, base: int = 4) -> nx.DiGraph: """ Generate symmeteric graph topology such that for the first half of nodes only connected to a point such that the index difference is power of base (Default is 4) and the connectivity for the second half of nodes just mirrored to the first half. - Example: A SymmetricPowerGraph with 12 nodes + Example: A SymmetricExponentialGraph with 12 nodes .. plot:: :context: close-figs >>> import networkx as nx >>> from bluefog.common import topology_util - >>> G = topology_util.SymmetricPowerGraph(12) + >>> G = topology_util.SymmetricExponentialGraph(12) >>> nx.draw_circular(G) """ x = [1.0] @@ -339,7 +339,7 @@ def InnerOuterRingGraph(world_size: int, local_size: int) -> nx.DiGraph: return G -def InnerOuterExp2Graph(world_size: int, local_size: int) -> nx.DiGraph: +def InnerOuterExpo2Graph(world_size: int, local_size: int) -> nx.DiGraph: """Generate Inner Ring and Outer Exponential-2 Graph. Within one machine all inner rank/processes is fully-connected and all @@ -349,7 +349,7 @@ def InnerOuterExp2Graph(world_size: int, local_size: int) -> nx.DiGraph: >>> import networkx as nx >>> from bluefog.common import topology_util - >>> G = topology_util.InnerOuterExp2Graph(12, 3) + >>> G = topology_util.InnerOuterExpo2Graph(12, 3) >>> nx.draw_circular(G) """ total_nodes = world_size @@ -541,7 +541,7 @@ def GetInnerOuterRingDynamicSendRecvRanks( index += 1 -def GetInnerOuterExp2DynamicSendRecvRanks( +def GetInnerOuterExpo2DynamicSendRecvRanks( world_size: int, local_size: int, self_rank: int ) -> Iterator[Tuple[List[int], List[int]]]: """ @@ -560,7 +560,7 @@ def GetInnerOuterExp2DynamicSendRecvRanks( >>> from bluefog.common import topology_util >>> world_size, local_size = bf.size(), bf.local_size() - >>> gen = topology_util.GetInnerOuterExp2DynamicSendRecvRanks(world_size, local_size, 0) + >>> gen = topology_util.GetInnerOuterExpo2DynamicSendRecvRanks(world_size, local_size, 0) >>> for _ in range(10): >>> print(next(gen)) """ diff --git a/docs/timeline.rst b/docs/timeline.rst index e8c578e9..170d7cd3 100644 --- a/docs/timeline.rst +++ b/docs/timeline.rst @@ -36,7 +36,7 @@ Example I: Logistic regression with neighbor_allreduce ------------------------------------------------------ In the first example, we show the timeline when running decentralized SGD for logistic regression, see the figure below. In this example, each rank is connected -via an undirected power-2 topology. We exploit the +via an undirected exponential-2 topology. We exploit the primitive ``neighbor_allreduce`` to perform the neighbor averaging. .. image:: ./_static/bf_timeline_example1a.png diff --git a/examples/pytorch_ImageNet_Resnet50.py b/examples/pytorch_ImageNet_Resnet50.py index fedb7b03..879e9613 100644 --- a/examples/pytorch_ImageNet_Resnet50.py +++ b/examples/pytorch_ImageNet_Resnet50.py @@ -72,9 +72,9 @@ parser.add_argument("--disable-dynamic-topology", action="store_true", default=False, help=("Disable each iteration to transmit one neighbor " + "per iteration dynamically.")) -parser.add_argument('--virtual-topology', type=str, default="power2", +parser.add_argument('--virtual-topology', type=str, default="expo2", help='The underlying virtual topology. Supporting options are ' + - '[power2(Default), ring, mesh, star].') + '[expo2(Default), ring, mesh, star].') args = parser.parse_args() args.cuda = not args.no_cuda and torch.cuda.is_available() @@ -88,13 +88,13 @@ torch.manual_seed(args.seed) if args.dist_optimizer != 'horovod': - if args.virtual_topology == "power2": + if args.virtual_topology == "expo2": pass elif args.virtual_topology == "ring": bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=1)) else: raise ValueError("Unknown args.virtual_topology, supporting options are " + - "[power2(Default), ring, mesh, star].") + "[expo2(Default), ring, mesh, star].") if args.cuda: # Bluefog: pin GPU to local rank. diff --git a/examples/pytorch_average_consensus.py b/examples/pytorch_average_consensus.py index 51d67349..f531b9e4 100644 --- a/examples/pytorch_average_consensus.py +++ b/examples/pytorch_average_consensus.py @@ -27,9 +27,9 @@ help='maximum iterations') parser.add_argument('--local-size', type=int, default=4, help='number of nodes per machine') -parser.add_argument('--virtual-topology', type=str, default="power2", +parser.add_argument('--virtual-topology', type=str, default="expo2", help='The underlying virtual topology. Supporting options are ' + - '[power2(Default), ring, mesh, star, InnerOuterRing].') + '[expo2(Default), ring, mesh, star, InnerOuterRing].') parser.add_argument('--asynchronous-mode', action='store_true', default=False, help='Use one-sided ops to run asynchronous push sum algorithm') parser.add_argument('--no-cuda', action='store_true', default=False, @@ -58,12 +58,12 @@ else: x = torch.randn(args.data_size, dtype=torch.double) -if args.virtual_topology == "power2": +if args.virtual_topology == "expo2": pass -elif args.virtual_topology == "power3": - bf.set_topology(topology_util.PowerGraph(bf.size(), base=3)) -elif args.virtual_topology == "power4": - bf.set_topology(topology_util.PowerGraph(bf.size(), base=4)) +elif args.virtual_topology == "expo3": + bf.set_topology(topology_util.ExponentialGraph(bf.size(), base=3)) +elif args.virtual_topology == "expo4": + bf.set_topology(topology_util.ExponentialGraph(bf.size(), base=4)) elif args.virtual_topology == "ring": bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=1)) elif args.virtual_topology == "mesh": @@ -77,7 +77,7 @@ bf.set_topology(topology_util.FullyConnectedGraph(bf.size())) else: raise ValueError("Unknown args.virtual_topology, supporting options are " + - "[power2(Default), ring, mesh, star].") + "[expo2(Default), ring, mesh, star].") x_bar = bf.allreduce(x, average=True) mse = [torch.norm(x-x_bar, p=2) / torch.norm(x_bar, p=2)] diff --git a/examples/pytorch_benchmark.py b/examples/pytorch_benchmark.py index 8332623c..5244fa91 100644 --- a/examples/pytorch_benchmark.py +++ b/examples/pytorch_benchmark.py @@ -60,9 +60,9 @@ parser.add_argument('--disable-dynamic-topology', action='store_true', default=False, help=('Disable each iteration to transmit one neighbor ' + 'per iteration dynamically.')) -parser.add_argument('--virtual-topology', type=str, default="power2", +parser.add_argument('--virtual-topology', type=str, default="expo2", help='The underlying virtual topology. Supporting options are ' + - '[power2(Default), ring, mesh, star, InnerOuterRing, InnerOuterExp2].') + '[expo2(Default), ring, mesh, star, InnerOuterRing, InnerOuterExpo2].') args = parser.parse_args() @@ -73,7 +73,7 @@ bf.init() if args.dist_optimizer != 'horovod': - if args.virtual_topology == "power2": + if args.virtual_topology == "expo2": pass elif args.virtual_topology == "ring": bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=1)) @@ -81,13 +81,13 @@ assert bf.is_homogeneous, "InnerOuterRing topo should be used only homogeneous environment" bf.set_topology(topology_util.InnerOuterRingGraph( bf.size(), local_size=bf.local_size() if args.local_size == -1 else args.local_size)) - elif args.virtual_topology == "InnerOuterExp2": - assert bf.is_homogeneous, "InnerOuterExp2 topo should be used under homogeneous environment" - bf.set_topology(topology_util.InnerOuterExp2Graph( + elif args.virtual_topology == "InnerOuterExpo2": + assert bf.is_homogeneous, "InnerOuterExpo2 topo should be used under homogeneous environment" + bf.set_topology(topology_util.InnerOuterExpo2Graph( bf.size(), local_size=bf.local_size() if args.local_size == -1 else args.local_size)) else: raise ValueError("Unknown args.virtual_topology, supporting options are " + - "[power2(Default), ring, mesh, star,InnerOuterRing, InnerOuterExp2].") + "[expo2(Default), ring, mesh, star,InnerOuterRing, InnerOuterExpo2].") if args.cuda: torch.cuda.set_device(bf.local_rank()) @@ -176,8 +176,8 @@ def forward(self, x): bf.size(), local_size=bf.local_size() if args.local_size == -1 else args.local_size, self_rank=bf.rank()) - elif args.virtual_topology == 'InnerOuterExp2': - dynamic_neighbor_allreduce_gen = topology_util.GetInnerOuterExp2DynamicSendRecvRanks( + elif args.virtual_topology == 'InnerOuterExpo2': + dynamic_neighbor_allreduce_gen = topology_util.GetInnerOuterExpo2DynamicSendRecvRanks( bf.size(), local_size=bf.local_size() if args.local_size == -1 else args.local_size, self_rank=bf.rank()) diff --git a/examples/pytorch_cifar10_resnet.py b/examples/pytorch_cifar10_resnet.py index f9ccd533..d02ca894 100644 --- a/examples/pytorch_cifar10_resnet.py +++ b/examples/pytorch_cifar10_resnet.py @@ -84,9 +84,9 @@ parser.add_argument('--disable-dynamic-topology', action='store_true', default=False, help=('Disable each iteration to transmit one neighbor ' + 'per iteration dynamically.')) -parser.add_argument('--virtual-topology', type=str, default="power2", +parser.add_argument('--virtual-topology', type=str, default="expo2", help='The underlying virtual topology. Supporting options are ' + - '[power2(Default), ring, mesh, star].') + '[expo2(Default), ring, mesh, star].') args = parser.parse_args() args.cuda = (not args.no_cuda) and (torch.cuda.is_available()) @@ -100,7 +100,7 @@ bf.init() torch.manual_seed(args.seed) if args.dist_optimizer != 'horovod': - if args.virtual_topology == "power2": + if args.virtual_topology == "expo2": pass elif args.virtual_topology == "ring": bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=1)) @@ -108,13 +108,13 @@ assert bf.is_homogeneous, "InnerOuterRing topo should be used only homogeneous environment" bf.set_topology(topology_util.InnerOuterRingGraph( bf.size(), local_size=bf.local_size())) - elif args.virtual_topology == "InnerOuterExp2": - assert bf.is_homogeneous, "InnerOuterExp2 topo should be used under homogeneous environment" - bf.set_topology(topology_util.InnerOuterExp2Graph( + elif args.virtual_topology == "InnerOuterExpo2": + assert bf.is_homogeneous, "InnerOuterExpo2 topo should be used under homogeneous environment" + bf.set_topology(topology_util.InnerOuterExpo2Graph( bf.size(), local_size=bf.local_size())) else: raise ValueError("Unknown args.virtual_topology, supporting options are " + - "[power2(Default), ring, mesh, star,InnerOuterRing, InnerOuterExp2].") + "[expo2(Default), ring, mesh, star,InnerOuterRing, InnerOuterExpo2].") if args.cuda: print("using cuda.") @@ -126,21 +126,6 @@ cudnn.benchmark = True -# If set > 0, will resume training from a given checkpoint. -resume_from_epoch = 0 -# for try_epoch in range(args.epochs, 0, -1): -# if os.path.exists(args.checkpoint_format.format(epoch=try_epoch)): -# resume_from_epoch = try_epoch -# break - -# Bluefog: broadcast resume_from_epoch from rank 0 (which will have -# checkpoints) to other ranks. -resume_from_epoch = bf.broadcast( - torch.tensor(resume_from_epoch), # pylint: disable=not-callable - root_rank=0, - name="resume_from_epoch", -).item() - # Bluefog: print logs on the first worker. verbose = 1 if bf.rank() == 0 else 0 @@ -234,15 +219,6 @@ '[neighbor_allreduce, gradient_allreduce, allreduce, ' + 'win_put, horovod]') -print("resume_from_epoch: ", resume_from_epoch) -# Restore from a previous checkpoint, if initial_epoch is specified. -# Bluefog: restore on the first worker which will broadcast weights to other workers. -# if resume_from_epoch > 0 and bf.rank() == 0: -# filepath = args.checkpoint_format.format(epoch=resume_from_epoch) -# checkpoint = torch.load(filepath) -# model.load_state_dict(checkpoint["model"]) -# optimizer.load_state_dict(checkpoint["optimizer"]) - # Bluefog: broadcast parameters & optimizer state. bf.broadcast_parameters(model.state_dict(), root_rank=0) bf.broadcast_optimizer_state(optimizer, root_rank=0) @@ -345,8 +321,8 @@ def adjust_learning_rate(epoch, batch_idx): bf.size(), local_size=bf.local_size(), self_rank=bf.rank()) - elif args.virtual_topology == 'InnerOuterExp2': - dynamic_neighbor_allreduce_gen = topology_util.GetInnerOuterExp2DynamicSendRecvRanks( + elif args.virtual_topology == 'InnerOuterExpo2': + dynamic_neighbor_allreduce_gen = topology_util.GetInnerOuterExpo2DynamicSendRecvRanks( bf.size(), local_size=bf.local_size(), self_rank=bf.rank()) @@ -421,7 +397,7 @@ def avg(self): return self.sum / self.n -for epoch in range(resume_from_epoch, args.epochs): +for epoch in range(args.epochs): train(epoch) validate(epoch) # save_checkpoint(epoch) diff --git a/examples/pytorch_mnist.py b/examples/pytorch_mnist.py index 0faadfe5..cd664c87 100644 --- a/examples/pytorch_mnist.py +++ b/examples/pytorch_mnist.py @@ -65,9 +65,9 @@ parser.add_argument('--disable-dynamic-topology', action='store_true', default=False, help=('Disable each iteration to transmit one neighbor ' + 'per iteration dynamically.')) -parser.add_argument('--virtual-topology', type=str, default="power2", +parser.add_argument('--virtual-topology', type=str, default="expo2", help='The underlying virtual topology. Supporting options are ' + - '[power2(Default), ring, mesh, star, InnerOuterRing, InnerOuterExp2].') + '[expo2(Default), ring, mesh, star, InnerOuterRing, InnerOuterExpo2].') parser.add_argument( "--seed", type=int, default=42, metavar="S", help="random seed (default: 42)" @@ -90,7 +90,7 @@ bf.init() if args.dist_optimizer != 'horovod': - if args.virtual_topology == "power2": + if args.virtual_topology == "expo2": pass elif args.virtual_topology == "ring": bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=1)) @@ -103,13 +103,13 @@ assert bf.is_homogeneous, "InnerOuterRing topo should be used only homogeneous environment" bf.set_topology(topology_util.InnerOuterRingGraph( bf.size(), local_size=bf.local_size() if args.local_size == -1 else args.local_size)) - elif args.virtual_topology == "InnerOuterExp2": - assert bf.is_homogeneous, "InnerOuterExp2 topo should be used under homogeneous environment" - bf.set_topology(topology_util.InnerOuterExp2Graph( + elif args.virtual_topology == "InnerOuterExpo2": + assert bf.is_homogeneous, "InnerOuterExpo2 topo should be used under homogeneous environment" + bf.set_topology(topology_util.InnerOuterExpo2Graph( bf.size(), local_size=bf.local_size() if args.local_size == -1 else args.local_size)) else: raise ValueError("Unknown args.virtual_topology, supporting options are " + - "[power2(Default), ring, mesh, star,InnerOuterRing, InnerOuterExp2].") + "[expo2(Default), ring, mesh, star,InnerOuterRing, InnerOuterExpo2].") if args.cuda: # Bluefog: pin GPU to local rank. @@ -222,8 +222,8 @@ def forward(self, x): bf.size(), local_size=bf.local_size() if args.local_size == -1 else args.local_size, self_rank=bf.rank()) - elif args.virtual_topology == 'InnerOuterExp2': - dynamic_neighbor_allreduce_gen = topology_util.GetInnerOuterExp2DynamicSendRecvRanks( + elif args.virtual_topology == 'InnerOuterExpo2': + dynamic_neighbor_allreduce_gen = topology_util.GetInnerOuterExpo2DynamicSendRecvRanks( bf.size(), local_size=bf.local_size() if args.local_size == -1 else args.local_size, self_rank=bf.rank()) diff --git a/examples/pytorch_optimization.py b/examples/pytorch_optimization.py index 79ae22ed..f1a224db 100644 --- a/examples/pytorch_optimization.py +++ b/examples/pytorch_optimization.py @@ -48,7 +48,7 @@ default='logistic_regression' ) parser.add_argument( - "--topology", help="this example supports mesh, star, ring, and power_two", + "--topology", help="this example supports mesh, star, ring, and expo2", default='ring' ) args = parser.parse_args() @@ -431,8 +431,8 @@ def push_diging(X, y, w_opt, loss, maxite=2000, alpha=1e-1, **kwargs): bf.init() if args.topology == 'mesh': bf.set_topology(topology_util.MeshGrid2DGraph(bf.size()), is_weighted=True) -elif args.topology == 'power_two': - bf.set_topology(topology_util.PowerGraph(bf.size())) +elif args.topology == 'expo2': + bf.set_topology(topology_util.ExponentialGraph(bf.size())) elif args.topology == 'star': bf.set_topology(topology_util.StarGraph(bf.size()), is_weighted=True) elif args.topology == 'ring': @@ -440,7 +440,7 @@ def push_diging(X, y, w_opt, loss, maxite=2000, alpha=1e-1, **kwargs): else: raise NotImplementedError( 'Topology not supported. This example only supports' + - ' mesh, star, ring and power_two' + ' mesh, star, ring and expo2' ) diff --git a/scripts/pytorch_opt_linear_speedup_test.py b/scripts/pytorch_opt_linear_speedup_test.py index d53e4c95..77acc631 100644 --- a/scripts/pytorch_opt_linear_speedup_test.py +++ b/scripts/pytorch_opt_linear_speedup_test.py @@ -36,9 +36,9 @@ default='exact_diffusion' ) parser.add_argument( - '--virtual-topology', type=str, default="power2", + '--virtual-topology', type=str, default="expo2", help='The underlying virtual topology. Supporting options are ' + - '[power2(Default), ring, mesh, star].') + '[expo2(Default), ring, mesh, star].') parser.add_argument( '--computation-mode', type=str, default="normal", @@ -101,7 +101,7 @@ def logistic_loss_step(x_, rho, X, y, tensor_name, calculate_by_hand=True): loss_.backward() return -if args.virtual_topology == "power2": +if args.virtual_topology == "expo2": pass elif args.virtual_topology == "ring": bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=0)) @@ -112,7 +112,7 @@ def logistic_loss_step(x_, rho, X, y, tensor_name, calculate_by_hand=True): bf.set_topology(topology_util.StarGraph(bf.size())) else: raise ValueError("Unknown args.virtual_topology, supporting options are " + - "[power2(Default), ring, mesh, star].") + "[expo2(Default), ring, mesh, star].") # Set up fake data # Generate data for logistic regression (synthesized data) @@ -208,4 +208,4 @@ def log(s, nl=True): print('[%d] Img/sec per %s: %.1f +-%.1f' % (bf.rank(), device, img_sec_mean, img_sec_conf)) log('Total img/sec on %d %s(s): %.1f +-%.1f' % - (bf.size(), device, img_sec_mean_all, img_sec_conf_all)) \ No newline at end of file + (bf.size(), device, img_sec_mean_all, img_sec_conf_all)) diff --git a/scripts/single_ops_test.py b/scripts/single_ops_test.py index a6e1b6ec..ef5caea8 100644 --- a/scripts/single_ops_test.py +++ b/scripts/single_ops_test.py @@ -19,9 +19,9 @@ help='number of benchmark iterations') parser.add_argument('--internal-num-iters', type=int, default=10, help='number of single ops in one benchmark step') -parser.add_argument('--virtual-topology', type=str, default="power2", +parser.add_argument('--virtual-topology', type=str, default="expo2", help='The underlying virtual topology. Supporting options are ' + - '[power2(Default), ring, mesh, star].') + '[expo2(Default), ring, mesh, star].') parser.add_argument('--seed', type=int, default=2020, help='Seed for randomness.') parser.add_argument('--profiler', action='store_true', default=False, help='disables profiler') @@ -32,12 +32,12 @@ data = torch.randn(args.data_size) bf.init() -if args.virtual_topology == "power2": +if args.virtual_topology == "expo2": pass -elif args.virtual_topology == "power3": - bf.set_topology(topology_util.PowerGraph(bf.size(), base=3)) -elif args.virtual_topology == "power4": - bf.set_topology(topology_util.PowerGraph(bf.size(), base=4)) +elif args.virtual_topology == "expo3": + bf.set_topology(topology_util.ExponentialGraph(bf.size(), base=3)) +elif args.virtual_topology == "expo4": + bf.set_topology(topology_util.ExponentialGraph(bf.size(), base=4)) elif args.virtual_topology == "ring": bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=0)) elif args.virtual_topology == "mesh": @@ -49,7 +49,7 @@ bf.set_topology(topology_util.FullyConnectedGraph(bf.size())) else: raise ValueError("Unknown args.virtual_topology, supporting options are " + - "[power2(Default), ring, mesh, star].") + "[expo2(Default), ring, mesh, star].") def benchmark_step(): global args, data diff --git a/test/tensorflow_basics_test.py b/test/tensorflow_basics_test.py index dccee249..d867cfd0 100644 --- a/test/tensorflow_basics_test.py +++ b/test/tensorflow_basics_test.py @@ -26,7 +26,7 @@ from common import mpi_env_rank_and_size import bluefog.tensorflow as bf -from bluefog.common.topology_util import PowerGraph, RingGraph +from bluefog.common.topology_util import ExponentialGraph, RingGraph warnings.filterwarnings("ignore", message="numpy.dtype size changed") warnings.filterwarnings("ignore", message="numpy.ufunc size changed") @@ -67,17 +67,17 @@ def test_set_and_load_topology(self): elif size == 1: expected_topology = nx.DiGraph(np.array([[1.0]])) else: - expected_topology = PowerGraph(size) + expected_topology = ExponentialGraph(size) bf.init() topology = bf.load_topology() assert isinstance(topology, nx.DiGraph) np.testing.assert_array_equal( nx.to_numpy_array(expected_topology), nx.to_numpy_array(topology)) - def test_in_out_neighbors_power2(self): + def test_in_out_neighbors_expo2(self): rank, size = mpi_env_rank_and_size() bf.init() - bf.set_topology(PowerGraph(size)) + bf.set_topology(ExponentialGraph(size)) in_neighobrs = bf.in_neighbor_ranks() out_neighbors = bf.out_neighbor_ranks() diff --git a/test/torch_basics_test.py b/test/torch_basics_test.py index 921051e8..4494f3d2 100644 --- a/test/torch_basics_test.py +++ b/test/torch_basics_test.py @@ -28,7 +28,7 @@ from common import mpi_env_rank_and_size import bluefog.torch as bf -from bluefog.common.topology_util import PowerGraph, RingGraph, RingGraph +from bluefog.common.topology_util import ExponentialGraph, RingGraph, RingGraph from bluefog.common.topology_util import IsTopologyEquivalent warnings.filterwarnings("ignore", message="numpy.dtype size changed") @@ -87,7 +87,7 @@ def test_set_topology_fail_with_win_create(self): topology = bf.load_topology() assert isinstance(topology, nx.DiGraph) - assert IsTopologyEquivalent(topology, PowerGraph(size)) + assert IsTopologyEquivalent(topology, ExponentialGraph(size)) is_freed = bf.win_free() assert is_freed, "bf.win_free do not free window object successfully." @@ -103,16 +103,16 @@ def test_set_and_load_topology(self): elif size == 1: expected_topology = nx.DiGraph(np.array([[1.0]])) else: - expected_topology = PowerGraph(size) + expected_topology = ExponentialGraph(size) topology = bf.load_topology() assert isinstance(topology, nx.DiGraph) assert IsTopologyEquivalent(expected_topology, topology) - def test_in_out_neighbors_power2(self): + def test_in_out_neighbors_expo2(self): bf.init() rank = bf.rank() size = bf.size() - assert bf.set_topology(PowerGraph(size)) + assert bf.set_topology(ExponentialGraph(size)) in_neighobrs = bf.in_neighbor_ranks() out_neighbors = bf.out_neighbor_ranks() diff --git a/test/torch_ops_test.py b/test/torch_ops_test.py index 7be827dd..49931cc8 100644 --- a/test/torch_ops_test.py +++ b/test/torch_ops_test.py @@ -371,7 +371,7 @@ def test_neighbor_allreduce_sum_precision(self): if TEST_ON_GPU: dtypes += [torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. num_indegree = int(np.ceil(np.log2(size))) neighbor_ranks = [(rank - 2**i) % size for i in range(num_indegree)] sum_value = np.sum(neighbor_ranks) + rank @@ -404,7 +404,7 @@ def test_neighbor_allreduce_avg_precision(self): if TEST_ON_GPU: dtypes += [torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. num_indegree = int(np.ceil(np.log2(size))) neighbor_ranks = [(rank - 2**i) % size for i in range(num_indegree)] sum_value = np.sum(neighbor_ranks) + rank @@ -435,7 +435,7 @@ def test_neighbor_allreduce_dynamic_topo_check(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. self_weight = 0.0 neighbor_weights = {(rank-1) % size : 1.0} send_ranks = [(rank + 2) % size] @@ -461,7 +461,7 @@ def test_neighbor_allreduce_dynamic_topo_move(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. self_weight = 0.0 neighbor_weights = {(rank-1) % size : 1.0} send_ranks = [(rank + 1) % size] @@ -495,7 +495,7 @@ def test_neighbor_allreduce_dynamic_topo_avg(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. num_indegree = int(np.ceil(np.log2(size))) neighbor_ranks = [(rank - 2**i) % size for i in range(num_indegree)] sum_value = np.sum(neighbor_ranks) + rank @@ -534,7 +534,7 @@ def test_neighbor_allreduce_avg(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. num_indegree = int(np.ceil(np.log2(size))) neighbor_ranks = [(rank - 2**i) % size for i in range(num_indegree)] sum_value = np.sum(neighbor_ranks) + rank @@ -727,7 +727,7 @@ def test_neighbor_allreduce_sum(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. num_indegree = int(np.ceil(np.log2(size))) neighbor_ranks = [(rank - 2**i) % size for i in range(num_indegree)] sum_value = np.sum(neighbor_ranks) + rank @@ -795,7 +795,7 @@ def test_neighbor_allreduce_fusion(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. num_indegree = int(np.ceil(np.log2(size))) neighbor_ranks = [(rank - 2**i) % size for i in range(num_indegree)] sum_value = np.sum(neighbor_ranks) + rank @@ -846,7 +846,7 @@ def test_neighbor_allreduce_fusion_alot(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. num_indegree = int(np.ceil(np.log2(size))) neighbor_ranks = [(rank - 2**i) % size for i in range(num_indegree)] sum_value = np.sum(neighbor_ranks) + rank @@ -892,7 +892,7 @@ def test_neighbor_allreduce_dynamic_topo_fusion(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. num_indegree = int(np.ceil(np.log2(size))) neighbor_ranks = [(rank - 2**i) % size for i in range(num_indegree)] sum_value = np.sum(neighbor_ranks) + rank @@ -953,7 +953,7 @@ def test_neighbor_allgather(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. num_indegree = int(np.ceil(np.log2(size))) neighbor_ranks = [(rank - 2**i) % size for i in range(num_indegree)] diff --git a/test/torch_win_ops_test.py b/test/torch_win_ops_test.py index d4871fe2..bee65e13 100644 --- a/test/torch_win_ops_test.py +++ b/test/torch_win_ops_test.py @@ -72,7 +72,7 @@ def test_win_create_and_sync_and_free(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. dims = [1, 2, 3] for dtype, dim in itertools.product(dtypes, dims): tensor = torch.FloatTensor(*([DIM_SIZE] * dim)).fill_(1).mul_(rank) @@ -233,7 +233,7 @@ def test_win_put(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. indegree = int(np.ceil(np.log2(size))) neighbor_ranks = [(rank - 2**i) % size for i in range(indegree)] # in-neighbor @@ -274,7 +274,7 @@ def test_get_win_version_with_win_put(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. indegree = int(np.ceil(np.log2(size))) neighbor_ranks = [(rank - 2**i) % size for i in range(indegree)] # in-neighbor @@ -328,7 +328,7 @@ def test_win_put_with_varied_tensor_elements(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. indegree = int(np.ceil(np.log2(size))) neighbor_ranks = [(rank - 2**i) % size for i in range(indegree)] # in-neighbor @@ -372,7 +372,7 @@ def test_win_put_with_given_destination(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. indegree = int(np.ceil(np.log2(size))) # We use given destination to form a (right-)ring. avg_value = (rank*indegree + 1.23*((rank-1) % @@ -413,7 +413,7 @@ def test_win_accumulate(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. outdegree = int(np.ceil(np.log2(size))) neighbor_ranks = [(rank - 2**i) % size for i in range(outdegree)] # in-neighbor @@ -449,7 +449,7 @@ def test_win_accumulate_with_varied_tensor_elements(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. outdegree = int(np.ceil(np.log2(size))) neighbor_ranks = [(rank - 2**i) % size for i in range(outdegree)] # in-neighbor @@ -526,7 +526,7 @@ def test_win_get(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. indegree = int(np.ceil(np.log2(size))) neighbor_ranks = [(rank - 2**i) % size for i in range(indegree)] # in-neighbor @@ -561,7 +561,7 @@ def test_get_win_version_with_win_get(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. indegree = int(np.ceil(np.log2(size))) neighbor_ranks = [(rank - 2**i) % size for i in range(indegree)] # in-neighbor @@ -615,7 +615,7 @@ def test_win_get_with_varied_tensor_elements(self): if TEST_ON_GPU: dtypes += [torch.cuda.FloatTensor, torch.cuda.DoubleTensor] - # By default, we use power two ring topology. + # By default, we use exponential two ring topology. indegree = int(np.ceil(np.log2(size))) neighbor_ranks = [(rank - 2**i) % size for i in range(indegree)] # in-neighbor From 42c3f95a4cbef645ca508e710b6e8ec6984eaafb Mon Sep 17 00:00:00 2001 From: ybc Date: Sun, 1 Nov 2020 22:21:57 -0800 Subject: [PATCH 41/44] Update install and ops documents --- docs/_static/bf_benchmark1.png | Bin 0 -> 46005 bytes docs/_static/bf_benchmark2.png | Bin 0 -> 39804 bytes docs/bluefog_ops.rst | 18 +++++++++++++++--- docs/env_variable.rst | 11 ++++++++++- docs/install.rst | 31 ++++++++++++++++++------------- 5 files changed, 43 insertions(+), 17 deletions(-) create mode 100644 docs/_static/bf_benchmark1.png create mode 100644 docs/_static/bf_benchmark2.png diff --git a/docs/_static/bf_benchmark1.png b/docs/_static/bf_benchmark1.png new file mode 100644 index 0000000000000000000000000000000000000000..5cd9527bab79e9c1d2de16c167f1e634622c25ad GIT binary patch literal 46005 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%0DEzUA#rrN~z> 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ψ>*@pj%5{)h~793yqt* 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

nE4Bm<@~w@kX3&S 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 sU)Hp+&fWX?w+- Bluefog Performance - Static and Dynamic Neighbor Averaging + Static and Dynamic Topology Neighbor Averaging Lauching Application Through bfrun Bluefog Docker Usage Bluefog Environment Variable diff --git a/docs/neighbor_average.rst b/docs/neighbor_average.rst index 003f4fd5..eb147b0a 100644 --- a/docs/neighbor_average.rst +++ b/docs/neighbor_average.rst @@ -1,3 +1,99 @@ -Static and Dynamic Neighbor Averaging -===================================== +Static and Dynamic Topology Neighbor Averaging +============================================== +The most distinguishable feature of Bluefog compared with other popular distributed training frameworks, such as +DistributedDataParallel provided by pytorch, Horovod, BytePS, etc., is that our core implementation rooted on the idea +that we introduce the virtual topology into the multiple processes and use the neighbor\_allreduce as +basic operation instead of allreduce. + +The core idea is very simple: all nodes/processes are connected through a virtual topology and they +fetch the information from their direct neighbors only, then do the average reduce operation. Although +the concept is simple, there are lots of deep research and theorems built upon it. Here we just touch +the most simple case to understand the basics. But let's run some code snippet to gain some insights first: + +BlueFog Code for Static and Dynamic Topology +-------------------------------------------- + +The BlueFog APIs are designed for easy use of the static and dynamic topology. +For simple static topology usage: + +.. code-block:: python + + import torch + import bluefog.torch as bf + from bluefog.common import topology_util + + bf.init() # Default topology is Exponential-2 graph + bf.set_topology(topology_util.RingGraph(bf.size())) # change to ring graph. + x = torch.Tensor([bf.rank()]) + for _ in range(100): + x = bf.neighbor_allreduce(x) # Use previous set ring graph. + print("rank {} has x={}".format(bf.rank(), x)) + +For dynamic topology case, especially dynamic Exponential 2 graph as we recommended +for most cases, you need a little bit more code: + +.. image:: _static/one-peer-exp2.png + :width: 600 + :align: center + +.. code-block:: python + + import torch + import bluefog.torch as bf + from bluefog.common import topology_util + + bf.init() + # Since Default topology is Exponential-2, the following utility function + # will generate one-peer dynamic Exponential-2 topology. + dynamic_neighbors = topology_util.GetDynamicSendRecvRanks( + bf.load_topology(), bf.rank()) + x = torch.Tensor([bf.rank()]) + for _ in range(maxite): + to_neighbors, from_neighbors = next(dynamic_neighbors) + avg_weight = 1/(len(from_neighbors) + 1) + x = bf.neighbor_allreduce(x, name='x', + self_weight=avg_weight, + neighbor_weights={r: avg_weight for r in from_neighbors}, + send_neighbors=to_neighbors) + +Notice here we use extra argument in the ``neighbor_allreduce`` function to change its behavior. +Although here we use the pre-defined utility function, you can implementation your own dynamic topology +function easily because all information it returns is just ranks (integers). + +Last note is ``hierarchical_neighbor_allreduce`` is defined over machine topology instead of previous +rank/processes topology. The usage is similar by just chaning rank integers into machine integers. + + + +Basic Theorem +------------- + +Formally, consider a digraph :math:`G=(V,E)`, where :math:`|V|=n`, +and weight matrix :math:`W` defined on :math:`G`, that is, :math:`w_{ij}\neq 0` +only for :math:`(j,i)\in E` and :math:`j=i`. +Neighbor average of vector :math:`x_1,\dots,x_n` defined over graph :math:`G` is equivalent to the +matrix multiplication: + +.. math:: + + W\mathbf{x} = W + \begin{bmatrix} + \text{---} & x_1^T & \text{---}\\ + & \cdots & \\ + \text{---} & x_n^T & \text{---} + \end{bmatrix}. + +**Theorem**: The sequence :math:`\mathbf{x}^{(k)} = W\mathbf{x}^{(k-1)}` converges to :math:`\mathbf{x}^\star=\frac{1}{n}\left(x_1+\dots+x_n\right)` +for all :math:`\mathbf{x}` if + +* :math:`W^{(k)}\mathbf{1} = \mathbf{1}`, +* :math:`\mathbf{1}^T W^{(k)}=\mathbf{1}^T`, +* :math:`W` has eigenvalues: :math:`\lambda_1=1 > |\lambda_2| \ge \dots \ge |\lambda_n| > -1`. + +Also, :math:`\|\mathbf{x}^{(k)}-\mathbf{x}^\star\|_2\le \underbrace{\max(|\lambda_2|,|\lambda_n|)}_{=:\rho}\|\mathbf{x}-\mathbf{x}^\star\|_2`. +Smaller :math:`\rho` means faster convergence. + +For dynamic topology, the combination matrix should change to :math:`W^{(k)}` and the +convergence condition becomes more complicated but similar. You can refer our papers to see more +theoratical guarantee.

1!&c{r-DYylV{w~iT_;v<}=S8h6 zm}IHDZ>$&rpnpR}y(J+Lg()xKtYF+2Q4~DcksL^fW($%$Qt3^|HXzO0ckYB&aNido z@d|)Q!qa-;!egkA^>|*w0EA-ZzYe{v9`0_0+ZBWt3k!?LcstP?JbRY#py6-x()nSU z0vNo9VYjL7La%^;e@^B9>MW{il&R8 zHa`Tpba+8MzwG`34==bs$tTFwg?1p(TZrut@7+$IX2LOlI_L3dc{3gCL_|mJDY?p4 zIubztp_(u+3|F8jKzHeqTxusUE|#Mo&JQ_!0D=N`lNf9Tks1V>bsofU&NDBsD76ej z=Ldc%Q>ZO?Fk(hzaOv{%x9^k_4RBq_V9w_tXaBW7p)A7>MVLvRqHpFmXjC2i1LKs$ zI5=WE7V9g1x)7xSSoa5vrXoP!qv(i2fcrb&AOqRcQ^#Xnsm&)NBcq;b45JkDs)Up8 z?AfgtYE{p%NMsae%xTz}h^~Qyc+o>Kh(j^Jw?s`8+Q~`r-Q#?yKb^Y3P&f9nki1 z((r}tzZSEZ#B?3y7Uom5X0X?Lx!_5va+wQ1tCL{u%V@!ppu%x zlminl407+`kU~4j=1=dnsIn7+u2*oNxKxXvLPSdgvR}GLw42eUZ_P4$n_hsf48cNx z)DBWo#;efs@oAWpG-Zu!g(!XC)TvjX(g-pxf&u42NMJ|jnFJcUh_iEEx&>eZ2@>^< z)Q!BB_4MZ zwkuoH)nv0nY=8KdVmngmvTydWA1=bl?3Y-ZoG;sdwiNG1v?=0`o?f zt_MsY;)zjdU-rJoAtSBCs19b2`QOuw3`Cn5ROI&*EI3-TBoMA^3JOsi00?1E(lu2! zh@<5=(??ncI!J~b43X9foY8ZY(#$(6JNt4w0~4`pGcq&sv@h9izI_JA{B9W;84SRr zCLxiM5G_)s>E2$F0osQbZ}AYghY=p)mpid&7T$`3r;1YRdP~=|7~`;z-FCuqKr0;@XItA~H`uU4OQz@v=0cAP zyqZ!4L9fV$ozmHKT~dJUA6i+aTNd3R1C##+OxS&Z@Lv@nR2-K$CtshnmESucAfUXr zs=4`?M5V`2ff%I9kI_eK3Ka9cpM|Ysg)|*MAwgyLLp$oN(%?mSrOPk)^-`azfj5h6MwXi&m^@kBj22L2%D4kH5tdXErivb-hH zrM$Uj)(aPQWT~6Wig1@Q7OzvGO$t1_0Ju&<$nBFj%B)7K|#S=`%7s> zQ02F8-}KEywbAc&k6ACCfS|i~(r%PiF*_@(+94wEYC~x$Dbo3c20iFhrdjPH+bhvn zziL4trMGrDy9&R>F$A#2do6xdUW`Yq>>RMa?q*Gc1VGEg^pbD~4-P&C$%YPQJJs3t zKKfRR@R7rZ^=7li^U{NYbRrf(}XuWW4Uc=?5L?U36|{!ur4hm0}h1wCzAHQvdu_iYa()-9%R#wIt#O+@_2iM_0h#wPCI?KL`R%NZMQR>7t9-0PE_WMgPaM^$@7z|GCYa;x)TE&uwcj7L3Uu@SYIS*NI=-Gftk zLyuKRsJL|Q$dMz8K`#9*gfYU~E}$$SG2d|}a)tXSS5uecxF0+tVD}91V;qXy`KP8% zpcf;5_3C}NAc$c*uYPU|>TaN^#M<$Jfsg1ri*fhxq~^^bV{2kh+u`Aa^`UAwZfYgI zVig&31Qh#N88*{ys*?vpK4_v^3~e|sO);0xa&4_&Xo>=*?3uUONvOdnl;Ce!z$!FA15v@p3rrV6$#AO7IwRkvaQ>;4UUZ^L`I%Pl1*su z2~;Tx87jrwYgn@|@`;vnM2e6?VmW^cfk@lqVNl)(zM|E`IaIjS<*h8sUde#qm)q=!ln(5OixSba8+#2ZW-AbCB({ zV-h9Wd8y0cf*88~O3J)?dU^!4#+GT43(UWE8om`(7l$lO6)}VL`Fxmj><^|X-unoy z-a)S+CgGgd-sZQ(XaBPQ?aTCk!PC_XbY!+v}pEROL`O`>@lFB{Qq)aRt)GORj|p1w-F%T(_0 z0OAql81I!ZADRJwA5G5bmcMr|4N#Fuxe_?<0`_FGyHEo&5lPle@K+LH3N4${@lS7v zyCJ7EspmD+NayLorAA<9=yE1lB6cco9ISdwS;$SggeF}ws5s&VL4)dw)q86jn=Gd} zL#@wN*D%1`NKB`(8l_01_5_%(n6=Mp`Vu2qm^EcU#m0C9NK%OXbayiH`xtJn9w0t} z%mZq1BRVh1pg$(H;R51PQcZ44U9rSM+HF+f^-6 z^=73kl*5Y}c-WMJFX=sjZN3TklkCJ5Ss*lV2?>s!L6|g9%=hcWbr8L$;m{#F&PKe{ zqT=UIS&X7PFHXdxLYw9s+k~9S1^7YfE%NxulLP>l3TVFC+Tp|lpsHXezechM2xws= za0KOmCYy@fTu$;>-+=w0MPR8j3ZfxB8{4n3X|+L5^X$9FXQp!wZ}mPZluB~{$z@Q< z$*z1AG&t1pqMO1F6DyUBMFz`?>B%k;&p$HDS2wf%eB<48YhIil6LIS3_9l;`!2*|d zvEbCGm^;PH^XQ2aNw{ZvN063@GZ~q#efd)Kf7Px>L#>6YCs{?#|e8SyV zO#tY`m^HF9hctFz7kV$7`2RM+9P%;N$;_Mj`XAw@Gf$!BceDz#2pDh6h$TkwLdKC8 zAxj(EoW!5p??|l^oZF87N8-Kv_io~!Nmm__P)JA^58yE1IP7^uNBr~C*8jaZK6gb91C97 zbLXz3rJ3{L9B!14=J)Qbgo{NV)B8oSCCQpo_!q9CA_%7=gU8QyNR00BhVg`bvI1oXWfJ;fiF{K`LWt`%=K zOuH}fp;w^;kfq@0__^D$-U9%I#J0;s_$tEjD&0R}`72_v{Nv+Ad-cteVk zDYDAZ!-u0#TC-rOfNka%)EO?k;AU=VC&JL;n&Z~HvbndvV`3{4!~^-y3?eI;b2TJA z;(B8pIjNASKqwjK(!kyoL2t9Q-4>MG7MfJ7trI#nKNe#glv%q#6~Z8K9#=V; zN9C)7I7BgbTLIPVl67)2wN>~g*b0WRGgMqXCQjuH7d&RuH`?L*-t|9>$6qI zDXYUketY)sSB9++zSRWyM@LdU))P-T_HJ>5I)Wo;{K<^s=us2Y6>A5F7L@wL?Q~)< zUcFMrwjlRK`}_Nw*2=YE)4id?&G27O`xNI)FD;peT4qi$-eAnSAOm@g z%o_Q~A@SqK8(8z9qY)l0s8^Gnxe6fA&I4~mnO?PIDmfwFUeMB!>d1GnOtumAriz9v zjxZd@t2_MXH!b}So;t+>_Tm)`r4M5jbF>i$utPQ2A&bboTP<}b2o7o%S>hUH{VtiSCt=hy!;AFP3!Sr^j*j(kD|`y5Gfujf1gRYBrINe=eWDR$&wh zagJ)jAP0Nlhq(~c1B7}k+V2`w@tRxkIzJAdth;UU@(XSfM3u!XlI$iK?yPlp@iEe| zpT?XFtgJG=15;D(4J!e+`+>-Et^@*Z5Q4xRS4`?y+uJLvs|Q13bo4r@QVSB=61y(~tzeAix6=jdQenfx!K=J=X1lBx${KE;pqiF#Vg@e+5+YFzyt*lp?ffeNh8$n9-7*G>XQ?afCUlG8595lateE zd~7(o&(e5{49r?6Ax#k*^K|PoJ|3Kw0q*cDGHZVRBwdL6=2S*vtf*^{un@RD(e*?N zr?9nP_N*A(w=KWFJ+(s%o#)CGW2DzSM5?88IFZDm!Q`UjfHyR;L8g+x3nUbQuJatG zQ($m6!%X@yJG^ut7(NR$7FNX}H34g9z@?zicAVHW#D82;k|aduBpXLqgjIm50KOv8 zNnaRk5Jinsw6I7)-XQ=4azJdw3K^*&@lq=z8|1S?5PCuu0LJ}gWAjq zOz`8!4<(J^iHRhD)KQFZv*VI)AVrUKLFeE8*o_!4Y@2N~$-$`W$9odNt7 z(E937Bn+jXrRpy|z#T&Wzn?YH6!%#Llo1f z{+%YOPFrP-;HJ(X$}}#Xhz=o=q6z@l{!{#MFJ9~+fEv7wix!7TNZxA$EHtV?0IT9# zAOOtg&#I7$$M6=WQ!W#i1m>zZ?jGBMqDuuZVK;;+7Pw8iy3KJXoyYk9gFlo{^WzgF z_mA$vD@;j9ba#AhNPSnXpYE{ti`0w_UU5pb7e66}S#Z!Nx=5`Q04S_&Z8IH+iu)*5 zClPrz;nSzrJ!4UI1aC#J7azm#evh^g9D{+Gxe0C9IEY>Gk&zEiKNk6>&mNDcBOViu zs#MgJj{FPwgYLO`GfZQBgakW^Z6eO-G4PHcx@~ql=BK-Vl4)}!BupnZEJxFqhiulcEzqTXc z=*}>J7%Ys`^~cy;$LYY%z_h^24XlA>ek}ES6fKO|`Fa1SsD7zoj5(J#G$`PmW6A&L z*B=Q-V@*+0GYQ$Z%htllDHrg15U+O}9wNTuecC5_e)tHk9X)y!a&|bHpc4(G`;7De1=r40$K(WMo#B>;-jr0Qol`rcTDjX zIoR=&(L5Q0`K=y$w-RolukX&_(2yxy|IU5S>E?k86F^LWGA!b{i38A^eJ|Z0JtQOq zI4lWnz{L0OuY&X8+<$s!#2z#-JRA%7R{rf7p zmxZ9Gs%?YEiYW2zdLmJBXvh=w8}r|15ac^{?j+D0)ulT(k_#>H;u-w9qP+Y~ov|Wb z1<2_f(U|uM$uT%cmNv_K>_L55CO3z7BGqm z2NXm^MJXagKm`=$w~xvF?z;1RGi%M7nYCuJZV7Pe`##U!`(O5csu#I?DIAYqtaxqoyG^zNKKkkiZ9dGyELGC7n-$@FXkp( zrPHJxA!`VQ05x`}l`wrurC zYXEW3!Gj0I*+scq=QVfkKD1Fy1=0PqfjyKYPKT%$FIM_u#%TDnv+Sz8_d|cn1)q2A z(=I~QVI*R-S1m_GV|3w)7yf&G=7Ca;_;*x>R|RPC;G=Q za9Ognk5k;@+dU3KZzw8h$v^YM?}5xxOoSEH>fhhMNdM38Gxe4RlJDnk_jq>4#J};{ zye_?a+bwznIu6zZc12&VOK~fipH6c<}}?o9S@D;u($sc#8Bo};7!18jB_J_eb|k`fst8wpuoiHgyaa*~!N9jYbw z>!`t+vH1t88T#DczU1bG-Raq$c6V*8iW?Fnj)c1Kc7E3>$Db9y*K-EUC=t?Z+0zq) z^x=s-m66{rxO{Jw=tX6vr6y%#BQ}kq!A0ADH3bE5P!F}_((k`(jT~u41#z3%s2)Y$ z>A>NtXtwR0jE=ne`R4$Wu04A?o6SbT2<-6Ls0nqe@OvWl3W$ko#QLZ=(Ph>6w9}`Z zkXn@skF}p#rfuZf%ho)pn?;i5TwANOl?z?$Jql!tIL;dtFi_CS*|l@2S4JObhCGz9 z2F?srI}jRggdvNU_{_3#M_l14Tb5tUh}4Odepm~7R%!3l`@Q)DucDC`Nd80b=Mq~M zk3LPuC)b)pb@;}0)e*pwVt4#l0MV{hZ!e{&(!3ku#9g%LdEh)|pqdjCRQZ-+;zAp} zvu(R}*$731PTEh*Q#>FgQ)B-Aq(?|0*$YPu`u5vn`PV-tKt~a|t~w5PLIh5|x6t=B z{UDn5{sYRV0pcw&#X|3fGxTv=I#h7%nKO0($>ig=zQ^IEqFFCw&mI@?}r2wp>DOZS6Q;OZmbLIZtZ4bn6z4E>b?J<* zwC>dnS&L3yKzm9Yqx$6HQ)yYyTi(~ZJfhu_Hzj>0uC*S&`k66bE<{axlJoMZU^VBu zX_uCl$B^V^N(?etRMa45ZxnZB{lyN$tnE&`7#l}ueoI07)O;;KC#o7QPrn@9Nwdz%j`n@6NXc! zC)OQ92{u$V2FL{4#Fh6f*%i7UeyYGju~$8cj(}*bh~Z zznKh__h?a<3^D$!=8C3~Q!$K~16UCe4igxOb8|@Fa0x<92><0gb?Xpv78rifw}8GZ z=cjyn$u)={^2K4h0A#|;AkP`*Ol(fLG{h%_o!0=Ol-MpolJ(c0r+HKtS};w;1b0!O z?~T3RPK}6&ut{4PMJqFva@QU`VkmfYw6(M6t71*pHdQ_z{3G>$(vj)V$_7OAm)NadWs^1f|2rkB`8+JA*izkdv!U zmc0Y_d4ip3S0X6vBiYn)j9?bB9X z(tn9yWvIjwKjcZTkJ~xCl#?VLBsrRSL6q&*OmxV!Q9|t3V|>5nI6Q`XVDZEOEdf;g zqM;%2h^3^~^L|SU z_)#qGg&en9fKlq@WqDo$#`bKBqz|g)2)i-3k zVd9n}Wb>`tx0}P*^Swj^a4k7&PcK2Bn7V||;X>`&ym_;bL%gvI%e>q88uhh5aHF#9 zYe7fVMOLs4s(vlCA0C+KYeT%f3EfZ+Q^c#!EYJfoYY^E8jgx_jR{5)ULw7o12?YohNHkqv!SwnS%Eb1lG^iF~a73tl}|n zLdteT1zdEI`0I}UAX|Ukc;)QULBodSyh*v>_)FHpxYhU1^bRGou z8E*+mE!4co+yxFkiT5X}gP5*v=&0>p=-M9CJedr>RJA)|2td0<``}@s&l22C%1Ah) z3IdZU_bzz^{sL_uF>-MyQZeZovW?ec-Z z;I7@eWjpEGOek^EWfR|g^COE(wE07aF7CdjUb4l+5Sr#KOikyjTs`ssA-BaI|Mq*T za46Prn)>hDA0)4LXBU_M>#wH(F}YA?ix)2rtdr%02a)|qqT73gF*yAdLL>GmQe)ZX zqf1gV1=Ufipgt5J9t&>3GzUI1Oh0SUNTZ4D5M)5n9#~kq1@!35QDR*S_kQyadEcA0 zT=o0+?=!P6A9qtQg92*KHqW7}C3eJ-7iFipqqpd?q4_(&Re zooNS_Z43j+FI^I=ic)Ka=&994CKJzG$rmSeo@DF|U*Kw7BRoQ!nY+9R)DQ$vze!0D z!H_cwB^83)fvXoTL}#?hBOdHnVCJbRczI?s55e6h)g7v#QOP5Dof{Bn%^=Cukgg}*BZx)ibh`c0Y3!?0MFrsk5?`^InO zohKh&m^;#l(a$$2&+AEi6`1#g!DVmtiW@BtanfZev7?omT+z1;$^I$^>}mP?x7y58 zy1;w~2d{FmS6{IMY$__J_%~?~lFXaGNp!2Pp@RSf@@$^Yha=IqEUnmnNcvqI>ct1fQmI8F3i&oc~FK~O4ybUl4d)gz3= zq-kF=S4P)bTwbc8k?Hx@qs9xoDA9IZa5U!LoTSB4 zd%>yUJw6^sV_BjH@9h}C+%HiI?z=wdHhb^z^&#Ku8tQF2LR;GmC8ML3e5<|{=SJ~6 zNHtr%cR#lK1a(;cdH%tF!8g__?Ie)TGWfH9NS{g0HKTfNyyklVm}&gYMOO0pKGFY_ zaGgGFY2WWoM%(ad_fDzT|9{UYtJl7D#4WcTYK;)ZO$y)T57sdQZ4lW@^hub9l>Gk@ zuXScGwmAj^S7AdHq(ea}BsW(o>(ZsD%jpaPl=@LFERb3pIE4002BcHJ$2E-f11K~x zLdnA1Toc(^yf;KKb8zsozf0e|9%0YVwYGStt-Ihzp}2Wz5`*FMIlW@Odog)Z=pymM zFt~;sYf8~U;E#g&f?y3V)JR#F^;v&S&8xR=nFvvmnwly_2r8e5hcNzoD9Q|qscB=` znkc7J5VfGU%_wLmHkE%PB`K7i@NWk8R4|wq2=#|>5yjE`I&S6TpG6FJy?fk%=~kvJ zhovoYf|y3nX@R9#3rDD~wXO6HV>NI+Vli}8<|l?yuP4>l*W0+juOvWrW)&1zi9~{@ za+sot;!=t>46rsjmI*iAb0%0t4aFxxQykQrnW?D~7swz*IyTub|CTiZuYhM5hipR9 zfBNY?A>PO^0)4=oniXtPZ-)D`NT+2o%Gl=g@*hIdG1Qc!fm?>j(EV%F8=BFqNw+ZQW7Jk$S_AcHHYMDqc_MK<2Sx9^fr2ahW18NOmC z60pTZvqi;$PvfNIE&XkC6@SVTf4}H6lfPL}@a&XTqn!m7CBYumzhb?bse~h2+IRel zhZ}L3$FVG9xr{0K#jl?Uy#z~UQFdC-W3)p_{y4eNFWn0^9+6XvlzC9VJ)hERke+?7 z*SREp%LCc&Ps+;X=3ySVmYaJbKfPD773{f?DtgJ!Ev)1soIhK6#)2C0EG+90dWS0^ z_)^?H{+0`#?r_F9$WD0DH1Cgt3?GL0N(K))qE_tQ{ zyzBgH?w+`EqgZ!)czC$Yy!9(b$Hl~)9^!wHXxP!OHZ<_e6s-<0Q`n#*T$jr;;?AkQ3EZ`b;!oe=(F>9)fk2I;ZF-Mv7 z;ZLn^OIlTAtn0R`OFjw7>4aWdFy;u~U2cHP0d-D@*SEAU#@c~wVOQ;L6ym{-NnY~@ z8A2?E3@#Aq78cglV}kl_3hfLPw1=q0oUZsYHRaP#0lhJG=rNk;?W2CJH!(|9McoRO zliV~bAj+h6Ts;SxSF_^Zc(5nMbuGorA{kPNkoQMMokdu|{`6ixnRD&S^wsb7qnQ`E zJXl~2vadG&gR*Y!j~+ehukgo!wk%>ol@O$$84HjhiD=;prq9^3R|LA=K8Is~DKdi< zs&<*U#C0GaX}s%}`qd|2jEKA}3xZMpQGl*RMb!(V#iVqvH0Z-j!ri5AE%yPdasd>2~W!?=@M;++|uwcRZ#sP=4b#!J@CNneT0C8oJ$IE1s`oH1hHsR%T_ zT($iZebd)GC*^((TNCzUJnMl%aqjkmP;&X{68@3-$tr^JF+k&~(|f0U%}p3*!AG*f zWh595BSOgT-P%lzW3NNKVN{u!;z7}9OxYlJiYP4KObB=gFbC!d_AI$_6B~7+eTF4T zEsqo-2H3{euf=4R4~)*k)lqovJJ|$oI-wWwf9w@b7|pUSaWR%d@oUK>Q=v`MX~Pc* z3OY<<=`;|x2nz>#R+XGPN99my-ixLWj6tDQ>;$_bwq;_s#Jha{NjhdFXqG}d39}Dg zLgWYb_;w0&99XxyJ7Kt|V!|@PEC$^Xynny5-0P8nI6uXG#H;Xv8=@b!tQs)-h845&E5O-dedx zPTQA$Vswf&o0SLVDb);HpkhP75kOiM4s=Q%mzbIIxbv=NRU?g%h*fOS`0ZkvrFPfL z-#cr71ZzHE5H6+MnLo<@4?hMkM93L5VM1oMH4)~L^=zn}_|`W$t*9&VdN*g}^$f$? zE1Y0O(^lr_=E`!1k5O3z4%F3nhk-%6sb_&Atm zR=Z=MJl?Y-av0^GE*;Nsp|b`A#bzHP=Rn=D!R)En_ucnz^~EWF>R(i5aemV^3NYV; z4WqAby@{AW2p3Atu3fs6V-Z$ylf|(OLXc_QzZ^O8;|5(dXi41$3d6L|ldVEWxt>HM zMA*7D|Av{-gsAQgUf;n|ipwH}+k~$o_I^+GGV(dPMg3~e^K2lP!v~sc&LagZsSIShl$DL*Hs5X)ywMgPl?%b>&|}!bf$|b4sRV|(&z)B zQ137!?9%WX*X0qD7yMx6MNEY>x-BXtWnIswVkIV1NOohbFH2L%g*=*S<5{!~@(jxL zB*#H1Zqo*E5+R6mS_LP16DMolIe&jl5wTF+;_DKBHOe@wB#i@dJyRd4QQqVYaeDfA z_pUL~^UaT#_HaGT8kSkFB#(%R+x7mLG{f0t+uS!`CoMSF65^@m6He=}C`vWnMRJTgPwYE&rz`%a40`Smsv!N z!pa9tQA(fzkolypw}p_GROXY~Mx$W|7t2W(4MX;#{89XFmY=n`7jkE~gj$V+?scJ%)5bkvxJBs zF|rQB-|0YxpM0YCH1~gG3CZ_&0?W# zmE9gO!L{20*dW|&N;-kX-zu68`I+K67uF*L+`~y_hYPD15@;qcl{kuQIe;OpxbNwJ zpDU02scnb2j>dxFn4C@xry}bDH*~O_vuScEY$X_B^eb)}{hr3n^58y`;?4{@mnxrZ zQtA6Xh!P#2By}`0n$Qp|m`-&MYlcwwL{xKNE8>l&g7ZJ}ILR(vxI{EODb!3;+08^v zL%v88t-R8wptw!^OW?F!UpzSC4hf^&)AoR#fYcEg1!hoMJ`}fM9vT?xE1weLS4C2B z`%_I|ho8NdQkrGMg%KmE<`VoGf<>WQ3SdF&Au$EPo&1LpBD+!(qsOJ*ziNsrg-Ke{ zjUYaly?gg+#~b~p?heklgwW8`}NZ38THZO;Kr!|nMF>Y7Qf&7ak=AB z%y{c;YvVf^Ap)4uz=5n4g;-_NyWgm#dj)!<`BhQ)66u4~Ndv)|x-uXC(cntJ!9e^5 zcy^{C?tIj~{Vq+U%0U2MWj#RMHV+vkhI1=ream@42GgeHKfTg+-Lz`wG~G3ew#euB zXMLw}x~pfkn~yj`q0SmO{8U6GR1FNsC--{3uKht_3b`9UVJBA?@zZ)yl4hTAt7a&H zE(6ojEn8bRg*-iT>^T)^I?BC>zvPU38>=ibS&*bp)plck0&_l^uFY#X#2lcy zJ9tnqFOjED>mzl+Z?#te!zp(bu&e^wTkJY2z@)D^9ENhHp39QwrDC*{d zxrws~(rSw^R13~I>CV}|>|6$|Oq#0n69+OfG9s&bjWa(UeFG2J91oR!jtvg0qiO9l zo(b*Q1v>!FYD`>*KfSxx<@}OD$Eea&Gc&OhmRV%fVDHq%C9HVyL9RnUFmO z-c^aI&vG5#=R<^wPqb!~h6ZHvVZ=dL#OIFcS1J23=H$tfm)ma1c)9P0|I>#L4=c4d%dY09S0+i!K7ZCvuT-I=PVTRuW%b*g@xbZ2i|0EJ|ZzVrH1Cx*kAvpON13u&~k&TMfc^;)qw5lK~TP(B-MBME$2gm1TW9 zeEe}R@EN9=nm*RK3a`yFlYhQe1){BT)!Vdi!+$eL?Eepw#OP%szOpYFl1vSVW3~WJ zVsIs_>|fn-K=dO0=X__JNHdijKe5cjv#EXw*Dw3--MP5*Jz5gvzE&34cMaplClCi> z4jrm2s$gDpGz-HTe(M)=53}~dy7!yppwwM(S)kAUo#MoU?@~rm30-*T9g<@#7zwg? z_|ER#x;bNXRz_lX7(2%N?I_9v#8^S~Pb>zY`kS)Yf^IqGp_Q;PUF%-SXPErk>G;(} zIAd~IzbYneg8mG^rB>90)Ds?@pMic}o>JhDyP?xW>nJy=>oAhRKeCSPVH#0X6rjx5H&|&@iAEL=CsG(>dvxI$P4AziJCP_yCA9ZM7%h9jf zj?L{$oHo#QF^IxQet8|OoLwci zpSn-*sPz0jJCS3VwkTQ2qLfZ1iJ z!e8TzTZXl9+}a}!3rRA&RSGO3>|Z3VxHGzUAK1P79`EL}@_|l!cv^T#XBH)3m3bBK zQC?o|Y_-*Gz=#pY^VeAfu?|9+E5t)@o-Ve?QP(7sr+)SSdu{UTvtlUud7wW)Bo^z+ zx!g6*PFN}-!$}waw%c5?KNA&P;@|%|0tjFR^RndR@abEasn>wKl5gR_h)T1v_ANJnk4E~}|?7<_mb<+;rE=?P59kj=PmeJQlpg~{i zUl@?9J-aw~(dsXv9&URTmv#NpGi~0|F=wxw5~88;f8%oeeIt5b9~yqV2wwsX7VPsQ z(p1a=k>uSxijT(+CZ7@oI=jQgpe;;)i6>UZV@IvzfJjP1+Mtu5M8tf7ar*-;9vS}Y zm-_n_Vr~_01^lb{0xDs(c4<-HEqdAvz<9(7q*VsY}o0k@!bc#kNf{RHEOea%bb(4>X6c~=!vtAeORO#Kx3O_y@}t?>yS2J1(Mh^R{(;bTAG%H!T~)?+ps+x&8a5%DG`xA9=jC>8D$(R^)sYuktR@`u3t(TN9oyDgl|O+qO&3)b5cCnCXEW zpi}k7>F%XjAK+XI(j-rJOPk}j)9i=VB>_y&mjmOr&XY>aIIFAPur?>E_nn8@RtE3g zYyEf}W#*8hL**K~cMh8+=d&v~`|fEl10Kr9QPg9?m9ZO@68(*JF9x;eRJ>tWJmw}^ zBD20aTSh~G)Qz$-kS9Wozv6-FJ1ZwND|BDMb*Y_rEJc(l2L<arO0A@dOWt;xWE3VSnX;zS1! zZ*GTSXTq6)3b$-R)ol!x`iD`-Rjw9}n?oXa;lhH0vLHLkVKEXhh!H}lRr{4A2fb~~ z@!zcp2`Wc@(!P|3PFGLkhVaSwuzE64Vc)V2ixN&3gurZ?@@>{ydXrSN1E7+{|0=~h zLwvDf{V}xtYDQVoTd_o*CWIZ}U!mkuOJ^KAOkztbO}?}FLd5so@cTlpi`a)55-jTV zU=;GAa8@!rg3ALvmwf(N9EUg4C*r(h&yJOvT3RzGwHQvS`sn0AETxz}Z&CT3#J(uj zaiz$E{48zkZN2xhR_fuYD}kEk7_tQ30Alu3_^cnh)yJM5MiZ7amtzo)2=Lo(gS)FY z`-B+}Vx*b1v>4LKAm?+OxVF9z^L|b-ELl?_#{dr*qoC>xf_bu6n8K7}O`aXwx$HOa zV_8j2GHb(vPU4dhuF^7rKc|AxxOq%@dhRpWfVRHI^R`)_f{L>sVto0zwC46#l=w9# zCi;TPIl8{ZcWT|>ZrcDz@l=x8&MD4-!zkM^*?|uotbi>Z93jPNN%MB>s88+^P`mM? zVa%uyu9#V&(Xd?m>_2(75oRu8QeTNS(EMMRZ`}GdIyRFvc4^8gy*J;n`-@})WTs82 zP@z%GgB}!X?mVT@^j=lAv=uP@SS0IvI(?%YS0>8~J(4PO5F=-T1%)q-&G3L=_yK~;z3)&W1WXlPu>KrdUkdY{%n zF%@$#vEueOzHNG7r&cgQ${{u{;6>D!0z5li#2E((dkd_eeR^f{RIe!kr#NBbEo6nw zNvB<)s|Bma9v#Vg71St3Ch6Q3ysKFO|03iH+MXWNYf${g%(28HO&XS_az^P*aP&um zJK-+Hb&ibc-(}qP4qb~_ksge}CV1k!5eW&_#hY0N4NUI%qHsF*y9Gn#)%nMI+;8_X zkq^0Uod#UB_LwoRcX^N2(b-fTaZw~E^66s^QeicyxLoRsfPDLv<>i*XB@MR2lg<1<4o) z@SPc;HlM(_=$N%c6KQ1_V72Y|OMKf}G+f~^2F~q)rHWz-#S;8joihEiSmbbrk}kxe z6Pn$-Ysn)!E0GncbqQ zFXwVr{Zu+x)e<`%`>ttzpa?M(3nwPbv5a%rx;>9u!I->l4B4gBD7I5%G3DpB`vTdD%y`?*zRm4I{7w_~p8!*kIMsi7j8&xbC8tmzVId zf6YgzUZdYAHw4jEp>*9e-P{eH#)2Ej`SP)>y`n6b)@#$D``ng z4(ytC4i}v^Zc#?VT9PqmCNCfV`vfBmKq_7abQX+w(_{Em9^p}FWvu`GbE9$y znx-26Rviw;!kqA@#uLMbEDs3}a_MMZj1^Z5YA7sq_1Y#H2;!kvicZ}MW}2Z-^d0Q`Ikl@ezN(?4-{Y z&onZ!TD7X)x4KhkzzTR{hW%!aa=RDvmoWl%{U)=v^w0K#e)zm9{o zBN+%8&-Rzr)WjhG9uQkWuVrUUzP@srN%SIs3&(b@@%l0jtQjvuzaXE2DS;-oyk0;{ zZ1?nPxOCN-HFeE?QWas9DW@x71H6T8`6=e%igcDjK;E4HTC3_kjlO@}dPcRc)lr0C zO~PDO{^~ccSEyTWw`I0UmxUxaK8C9+z((2^5drvT)#Iz3)%^f0>xNh7TJ5O-0-nRA z+mJAnnyj>$V5f0wUmq3H(8^(r0hXhc%O5n)(HPzf-oW@P3MH|evxrZfdNbMLUhPS0 ze`&21-&8Nr7O6y}omf+b{jnZzK~1HQmaFfcm`;y^!6vZ^R|a%SR+a(r)mYr`$ZqXd1srmR=Ra=eV-rix5 z5OZ2;&-iS9CWSZ!pEPc*53kdb+L2xYg_0(%c=2|0>NDpl9k1ulpPxQ)w;Ldvxy)(MgDN2gUETT4(Fma;xf1dG*x!4W#?c?)Y}OTrGCl{U z()HYts3?U}Jc+=O8R_GLhhlhTlpv`qb7@smb8|caWYZ3JZZhBii#h8bz!epFe@X;R zG)t2iq&8DmpV4E^Xp`*FUsjDyNJ~$b1~#G<<+U;TG`(6mpN$`&ac4Zt(D~;=4osqJ z*SDG)yMQ&^;UvOUSL;`lK$~`c-nsKv3Q&PL(4_APn@34@Y4d&T(Uw0eenrj^D?3(? zL6r5Bx4AFp%uj{> zzlHCD8B|&dy2yWDU}>kz87y1{8sgG^f7MZ=YgbwI5s!_!-Qu`;TU&-aBv`r}TYPt9 zCH?}2_Y@MTdiEXToEP);9#ZrymfVnCh0moejwC*t77LNO!N|mCGso3aG$wz?ou3?_ zEU8;nbK=*JLVasiJbpE%?A7G1i=|n+mgmq5bS}q`)Lb3wG24kmt4b(6`_U==#JOV!16=d$z zyuo|>_Nz5*VeM~;X`Sl2tBe0moz}4yoigUZ>=eBWBa--*tlW0#kPM2#z^i=T(#-r_ zD`FBe2yW6T4e_A-EUB-?vw{r=pM9t?c`WMPR7_}h{iF@RFnxSSPd};X`zt6)haPpa zv%B|AKRM%_e6~+>3GgW0{pp;n%ze{;nKb@Bv8eWZ1H%P=i07QO-JOb;v9v{lkXH2D zt(zvlr}11mC$zV}>D2scPB*4QA8Rh`yXVsUTPSt?iw|s^kFG~w!jPAK{VW)zsHvc< zhFV`|WhN2KFum7^ngcuZ+1gY`25x)&lg*eLtqAU*ra}p>9I#=F-w zVpZLf*+nlfZ^@LLQ;rRsQILJ1)ZhOF0Yk-fLMe(Fw{+@$EF>fhLD7ISTH8Ks^ZvRC z$JmQy`|Pn$TDBv~<%P3h?BKEQHw0;lkzKr4 zh@{b2l*)-lWAJm-HS c3*XYIsQUYJ9Xnq=A+?LbV9xhRQyhQ#Z--g)MF0Q* literal 0 HcmV?d00001 diff --git a/docs/bluefog_ops.rst b/docs/bluefog_ops.rst index 9523de37..04c92cf2 100644 --- a/docs/bluefog_ops.rst +++ b/docs/bluefog_ops.rst @@ -82,6 +82,8 @@ Hierarchical Collective Ops --------------------------- In practice, the communication speed and behavior is different between intra-machine and inter-machine communcation. Hence, we also provided two hierarchical collective ops. The basic unit in this case is each (physical) machine. +Hence, unlike previous neighbor collective ops, of which the topology is defined over the connection between ranks/processes, +the topology of hierarchical collective ops is defined over the connection between machines. hierarchical_local_allreduce ############################ @@ -89,17 +91,27 @@ hierarchical_local_allreduce :alt: BluefogHierarchicalLocalAllreduceExplanation :width: 700 +Because it is (machine) local operation, the topology definition will not impact this operation. Hence, the rank 0 and rank 1 +simply applied the local allreduce average to get (8+4)/2 = 6. Other ranks is like-wise. + hierarchical_neighbor_allreduce ############################### .. image:: _static/bf_hier_neighbor_allreduce.png :alt: BluefogHierarchicalNeighborAllreduceExplanation :width: 700 -The basic logics under hierarchical operations is, within the machine, each local rank performances the local allreduce -operation first so that in the view of external machines, all processes within same machine forms a super node. +Similar to the *hierarchical_local_allreduce* operation, it first applied the local allreduce average within the machine. +So that in the view of external machines, all processes within same machine forms a super node. Then, the super node exchange the +information with their neighbor machines like *neighbor_allreduce*. For example, machine 0, 2, and 3 first formed a local average value +6, 3, and 3 respectively. Then, a machine-wise neighbor allreduce produce (6+3+3)/3 = 4. + +In order to minimize the cross machines communcation, the real implementation is four steps actually: 1. Local Average. 2. All local rank +0 processes do the *neihbor_allreduce*. 3. local rank 0 processes broadcast the received tensors to other local ranks. 4. Compute the average of +received neighbor tensors within the process. + .. warning:: - hierarchical_neighbor_allreduce only should be used under the homogeneous environment only, i.e. each machine owns same number of + hierarchical_neighbor_allreduce should be used under the homogeneous environment only, i.e., each machine owns same number of the local processes. diff --git a/docs/env_variable.rst b/docs/env_variable.rst index 1c8f5930..e8b1f1c6 100644 --- a/docs/env_variable.rst +++ b/docs/env_variable.rst @@ -26,6 +26,15 @@ You can also hide the time in logs by setting: Performance ----------- +Our implementation is based upon the architecture of Horovod. Hence, we also have the tensor fusion functionality, which +batches small allreduce/neighbor_allreduce operations into one to improve the performance. Cycle time is anthor tuning parameter +to determine within the certain period of time, the ready tensor will be fused into one if it doesnot exceed the threshold of fusion. + +* BLUEFOG_FUSION_THRESHOLD +* BLUEFOG_CYCLE_TIME + +The fusion threshold is based on the Byte size and cycle time is based on the milliseconds. + **Timeline**: You can set `BLUEFOG_TIMELINE` with some filename to turn on the timeline. See our timeline document for more details. @@ -78,7 +87,7 @@ define this number as the maximum size of win_ops can send. When the NCCL implementation is used, the callback functions are executed through a thread pool. The size of thread pool can be controlled by following: -* BLUEFOG_NUM_FINALIZER_THREADS (Default: 50) +* BLUEFOG_NUM_FINALIZER_THREADS (Default: 1) Installation ------------ diff --git a/docs/install.rst b/docs/install.rst index 24abd187..3ca67c2e 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -33,13 +33,19 @@ After you think the environment is all set, just run following command to instal Installing Bluefog from Pip (GPU) --------------------------------- All steps for GPU case are the same as CPU case except for the OpenMPI installation. -In order to get full support of GPU, you have to install `CUDA>=10.0` -and install pytorch and/or tensorflow with the GPU support version. -To maximize the efficiency of GPU and MPI, our implementation assumes the -MPI installed is GPU-aware if GPU is available. It will avoid the extra cost -that copy and moving the data from the GPU and host memory, i.e. the address of -GPU location can be used directly. However, if MPI built is not GPU-aware, -there will be a segmentation fault. To do that, you can configure the open install setting +In order to get full support of GPU, you have to install `CUDA>=10.1` +and install pytorch with the GPU support version. +It is highly recommended to use NCCL instead of OpenMPI as GPU +communication implementation. We require the ``NCCL>=2.7`` since our implementation heavily +relied on the new `ncclSend` and `ncclRecv` API introduced after version 2.7. +To install Bluefog with NCCL implementation, you need to run + +.. code-block:: bash + + BLUEFOG_WITH_NCCL=1 pip install --no-cache-dir bluefog + +You can also install the GPU-aware OpenMPI as GPU communication implementation. +To do that, you can configure the open install setting after the download of OpenMPI: .. code-block:: bash @@ -48,16 +54,15 @@ after the download of OpenMPI: make -j $(nproc) all && \ make install -If you have NCCL installed in your system, it is also recommend to use NCCL instead of OpenMPI as -communication implementation. To install Bluefog with NCCL implementation, you need to run -.. code-block:: bash +Installing Bluefog from Github Directly +--------------------------------------- - BLUEFOG_WITH_NCCL=1 pip install --no-cache-dir bluefog +.. important:: + The lastest functionality may not be able avaiable through ``pip install bluefog``. + Installing from Github is better during our early development stage. -Installing Bluefog from Github Directly ---------------------------------------- First, please check your environment as mentioned in above subsections. Then, clone or download the bluefog repository from `Github`_. Last, just run the following command under the root folder of bluefog repository: From 618a2bee31a5d0fcd5bb9a5b97ca6fb77f78f42b Mon Sep 17 00:00:00 2001 From: ybc Date: Mon, 2 Nov 2020 21:28:43 -0800 Subject: [PATCH 42/44] Merge Imagenet and Cifar 10 example together and remove pair_gossip --- bluefog/torch/__init__.py | 1 - bluefog/torch/mpi_ops.py | 3 + bluefog/torch/utility.py | 6 +- examples/pytorch_ImageNet_Resnet50.py | 343 ------------------ examples/pytorch_benchmark.py | 4 +- ...ch_cifar10_resnet.py => pytorch_resnet.py} | 99 +++-- test/torch_ops_test.py | 8 +- 7 files changed, 73 insertions(+), 391 deletions(-) delete mode 100644 examples/pytorch_ImageNet_Resnet50.py rename examples/{pytorch_cifar10_resnet.py => pytorch_resnet.py} (83%) diff --git a/bluefog/torch/__init__.py b/bluefog/torch/__init__.py index 1f5c47b3..fdf66f9a 100644 --- a/bluefog/torch/__init__.py +++ b/bluefog/torch/__init__.py @@ -49,7 +49,6 @@ from bluefog.torch.mpi_ops import neighbor_allreduce, neighbor_allreduce_nonblocking from bluefog.torch.mpi_ops import hierarchical_neighbor_allreduce from bluefog.torch.mpi_ops import hierarchical_neighbor_allreduce_nonblocking -from bluefog.torch.mpi_ops import pair_gossip, pair_gossip_nonblocking from bluefog.torch.mpi_ops import poll, synchronize, barrier from bluefog.torch.mpi_ops import win_create, win_free diff --git a/bluefog/torch/mpi_ops.py b/bluefog/torch/mpi_ops.py index 24a4a1fc..234b8039 100644 --- a/bluefog/torch/mpi_ops.py +++ b/bluefog/torch/mpi_ops.py @@ -711,6 +711,9 @@ def _hierarchical_neighbor_allreduce_nonblocking( else: raise ValueError("Arguments self_weight and neighbor_weights cannot be empty or None.") + if not send_neighbor_machines: + raise ValueError("Argument send_neighbor_machines has to be presented and non-empty.") + machine_size = size() // local_size() # Translate machine id into rank id. node_per_machine = local_size() diff --git a/bluefog/torch/utility.py b/bluefog/torch/utility.py index 15a5f343..b4e05238 100644 --- a/bluefog/torch/utility.py +++ b/bluefog/torch/utility.py @@ -107,13 +107,13 @@ def broadcast_optimizer_state(optimizer, root_rank): # forces allreduce on all model parameters, which will result in deadlock # unless every rank calls step(). Therefore, to finish state initialization # only call optimizer.step() with a torch.optim.Optimizer. - if optimizer.__module__ == bf.DistributedAllreduceOptimizer.__module__: + if optimizer.__module__ == bf.DistributedHierarchicalNeighborAllreduceOptimizer.__module__: super(optimizer.__class__, optimizer).step() elif optimizer.__module__ == bf.DistributedNeighborAllreduceOptimizer.__module__: super(optimizer.__class__, optimizer).step() - elif optimizer.__module__ == bf.DistributedPushSumOptimizer.__module__: + elif optimizer.__module__ == bf.DistributedAllreduceOptimizer.__module__: super(optimizer.__class__, optimizer).step() - elif optimizer.__module__ == bf.DistributedPullGetOptimizer.__module__: + elif optimizer.__module__ == bf.DistributedGradientAllreduceOptimizer.__module__: super(optimizer.__class__, optimizer).step() elif optimizer.__module__ == bf.DistributedWinPutOptimizer.__module__: super(optimizer.__class__, optimizer).step() diff --git a/examples/pytorch_ImageNet_Resnet50.py b/examples/pytorch_ImageNet_Resnet50.py deleted file mode 100644 index 879e9613..00000000 --- a/examples/pytorch_ImageNet_Resnet50.py +++ /dev/null @@ -1,343 +0,0 @@ -# Modifications copyright (C) 2020 Bluefog Team. All Rights Reserved. -# Copyright 2019 Uber Technologies, Inc. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -import argparse -import os -import math - -import torch -import torch.backends.cudnn as cudnn -import torch.nn.functional as F -import torch.optim as optim -import torch.utils.data.distributed -from torchvision import datasets, transforms, models -import tensorboardX -from tqdm import tqdm - -from bluefog.common import topology_util -import bluefog.torch as bf - -# Training settings -parser = argparse.ArgumentParser(description='PyTorch ImageNet Example', - formatter_class=argparse.ArgumentDefaultsHelpFormatter) -parser.add_argument('--train-dir', default=os.path.expanduser('~/imagenet/train'), - help='path to training data') -parser.add_argument('--val-dir', default=os.path.expanduser('~/imagenet/validation'), - help='path to validation data') -parser.add_argument('--log-dir', default='./logs', - help='tensorboard log directory') -parser.add_argument('--checkpoint-format', default='./checkpoint-{epoch}.pth.tar', - help='checkpoint file format') -parser.add_argument('--batches-per-allreduce', type=int, default=1, - help='number of batches processed locally before ' - 'executing allreduce across workers; it multiplies ' - 'total batch size.') - -# Default settings from https://arxiv.org/abs/1706.02677. -parser.add_argument('--batch-size', type=int, default=32, - help='input batch size for training') -parser.add_argument('--val-batch-size', type=int, default=32, - help='input batch size for validation') -parser.add_argument('--epochs', type=int, default=90, - help='number of epochs to train') -parser.add_argument('--base-lr', type=float, default=0.0125, - help='learning rate for a single GPU') -parser.add_argument('--warmup-epochs', type=float, default=5, - help='number of warmup epochs') -parser.add_argument('--momentum', type=float, default=0.9, - help='SGD momentum') -parser.add_argument('--wd', type=float, default=0.00005, - help='weight decay') - -parser.add_argument('--no-cuda', action='store_true', default=False, - help='disables CUDA training') -parser.add_argument('--seed', type=int, default=42, - help='random seed') -parser.add_argument('--dist-optimizer', type=str, default='neighbor_allreduce', - help='The type of distributed optimizer. Supporting options are ' + - '[neighbor_allreduce, allreduce, win_put, horovod]') -parser.add_argument("--disable-dynamic-topology", action="store_true", - default=False, help=("Disable each iteration to transmit one neighbor " + - "per iteration dynamically.")) -parser.add_argument('--virtual-topology', type=str, default="expo2", - help='The underlying virtual topology. Supporting options are ' + - '[expo2(Default), ring, mesh, star].') - -args = parser.parse_args() -args.cuda = not args.no_cuda and torch.cuda.is_available() -allreduce_batch_size = args.batch_size * args.batches_per_allreduce - -if args.dist_optimizer == 'horovod': - print("importing horovod") - import horovod.torch as bf - -bf.init() -torch.manual_seed(args.seed) - -if args.dist_optimizer != 'horovod': - if args.virtual_topology == "expo2": - pass - elif args.virtual_topology == "ring": - bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=1)) - else: - raise ValueError("Unknown args.virtual_topology, supporting options are " + - "[expo2(Default), ring, mesh, star].") - -if args.cuda: - # Bluefog: pin GPU to local rank. - torch.cuda.set_device(bf.local_rank()) - torch.cuda.manual_seed(args.seed) - -cudnn.benchmark = True - -# If set > 0, will resume training from a given checkpoint. -resume_from_epoch = 0 -for try_epoch in range(args.epochs, 0, -1): - if os.path.exists(args.checkpoint_format.format(epoch=try_epoch)): - resume_from_epoch = try_epoch - break - -# Bluefog: broadcast resume_from_epoch from rank 0 (which will have -# checkpoints) to other ranks. -resume_from_epoch = bf.broadcast(torch.tensor(resume_from_epoch), root_rank=0, - name='resume_from_epoch').item() - -# Bluefog: print logs on the first worker. -verbose = 1 if bf.rank() == 0 else 0 - -# Bluefog: write TensorBoard logs on first worker. -log_writer = tensorboardX.SummaryWriter(args.log_dir) if bf.rank() == 0 else None - - -# Bluefog: limit # of CPU threads to be used per worker. -torch.set_num_threads(4) - -kwargs = {'num_workers': 4, 'pin_memory': True} if args.cuda else {} -train_dataset = \ - datasets.ImageFolder(args.train_dir, - transform=transforms.Compose([ - transforms.RandomResizedCrop(224), - transforms.RandomHorizontalFlip(), - transforms.ToTensor(), - transforms.Normalize(mean=[0.485, 0.456, 0.406], - std=[0.229, 0.224, 0.225]) - ])) -# Bluefog: use DistributedSampler to partition data among workers. Manually specify -# `num_replicas=bf.size()` and `rank=bf.rank()`. -train_sampler = torch.utils.data.distributed.DistributedSampler( - train_dataset, num_replicas=bf.size(), rank=bf.rank()) -train_loader = torch.utils.data.DataLoader( - train_dataset, batch_size=allreduce_batch_size, - sampler=train_sampler, **kwargs) - -val_dataset = \ - datasets.ImageFolder(args.val_dir, - transform=transforms.Compose([ - transforms.Resize(256), - transforms.CenterCrop(224), - transforms.ToTensor(), - transforms.Normalize(mean=[0.485, 0.456, 0.406], - std=[0.229, 0.224, 0.225]) - ])) -val_sampler = torch.utils.data.distributed.DistributedSampler( - val_dataset, num_replicas=bf.size(), rank=bf.rank()) -val_loader = torch.utils.data.DataLoader(val_dataset, batch_size=args.val_batch_size, - sampler=val_sampler, **kwargs) - - -# Set up standard ResNet-50 model.Ã¥ -model = models.resnet50() - -# For sum/average with gradient Accumulation: scale learning rate by batches_per_allreduce -lr_scaler = args.batches_per_allreduce * bf.size() if not args.use_adasum else 1 - -if args.cuda: - # Move model to GPU. - model.cuda() - -# Bluefog: scale learning rate by the number of GPUs. -optimizer = optim.SGD(model.parameters(), - lr=(args.base_lr * - lr_scaler), - momentum=args.momentum, weight_decay=args.wd) - -# Bluefog: wrap optimizer with DistributedOptimizer. -if args.dist_optimizer == 'win_put': - optimizer = bf.DistributedWinPutOptimizer(optimizer, model=model) -elif args.dist_optimizer == 'neighbor_allreduce': - optimizer = optimizer = bf.DistributedNeighborAllreduceOptimizer( - optimizer, model=model) -elif args.dist_optimizer == 'allreduce': - optimizer = optimizer = bf.DistributedAllreduceOptimizer( - optimizer, model=model) -elif args.dist_optimizer == 'horovod': - optimizer = optimizer = bf.DistributedOptimizer( - optimizer, named_parameters=model.named_parameters() - ) -else: - raise ValueError('Unknown args.dist-optimizer type -- ' + args.dist_optimizer + '\n' + - 'Please set the argument to be one of ' + - '[neighbor_allreduce, allreduce, win_put, horovod]') - -# Restore from a previous checkpoint, if initial_epoch is specified. -# Bluefog: restore on the first worker which will broadcast weights to other workers. -if resume_from_epoch > 0 and bf.rank() == 0: - filepath = args.checkpoint_format.format(epoch=resume_from_epoch) - checkpoint = torch.load(filepath) - model.load_state_dict(checkpoint['model']) - optimizer.load_state_dict(checkpoint['optimizer']) - -# Bluefog: broadcast parameters & optimizer state. -bf.broadcast_parameters(model.state_dict(), root_rank=0) -bf.broadcast_optimizer_state(optimizer, root_rank=0) - -def train(epoch): - model.train() - train_sampler.set_epoch(epoch) - train_loss = Metric('train_loss') - train_accuracy = Metric('train_accuracy') - - with tqdm(total=len(train_loader), - desc='Train Epoch #{}'.format(epoch + 1), - disable=not verbose) as t: - for batch_idx, (data, target) in enumerate(train_loader): - adjust_learning_rate(epoch, batch_idx) - - if args.cuda: - data, target = data.cuda(), target.cuda() - optimizer.zero_grad() - # Split data into sub-batches of size batch_size - for i in range(0, len(data), args.batch_size): - data_batch = data[i:i + args.batch_size] - target_batch = target[i:i + args.batch_size] - output = model(data_batch) - train_accuracy.update(accuracy(output, target_batch)) - loss = F.cross_entropy(output, target_batch) - train_loss.update(loss) - # Average gradients among sub-batches - loss.div_(math.ceil(float(len(data)) / args.batch_size)) - loss.backward() - # Gradient is applied across all ranks - optimizer.step() - t.set_postfix({'loss': train_loss.avg.item(), - 'accuracy': 100. * train_accuracy.avg.item()}) - t.update(1) - - if log_writer: - log_writer.add_scalar('train/loss', train_loss.avg, epoch) - log_writer.add_scalar('train/accuracy', train_accuracy.avg, epoch) - - -def validate(epoch): - model.eval() - val_loss = Metric('val_loss') - val_accuracy = Metric('val_accuracy') - - with tqdm(total=len(val_loader), - desc='Validate Epoch #{}'.format(epoch + 1), - disable=not verbose) as t: - with torch.no_grad(): - for data, target in val_loader: - if args.cuda: - data, target = data.cuda(), target.cuda() - output = model(data) - - val_loss.update(F.cross_entropy(output, target)) - val_accuracy.update(accuracy(output, target)) - t.set_postfix({'loss': val_loss.avg.item(), - 'accuracy': 100. * val_accuracy.avg.item()}) - t.update(1) - - if log_writer: - log_writer.add_scalar('val/loss', val_loss.avg, epoch) - log_writer.add_scalar('val/accuracy', val_accuracy.avg, epoch) - - -# Bluefog: using `lr = base_lr * bf.size()` from the very beginning leads to worse final -# accuracy. Scale the learning rate `lr = base_lr` ---> `lr = base_lr * bf.size()` during -# the first five epochs. See https://arxiv.org/abs/1706.02677 for details. -# After the warmup reduce learning rate by 10 on the 30th, 60th and 80th epochs. -def adjust_learning_rate(epoch, batch_idx): - if epoch < args.warmup_epochs: - epoch += float(batch_idx + 1) / len(train_loader) - lr_adj = 1. / bf.size() * (epoch * (bf.size() - 1) / args.warmup_epochs + 1) - elif epoch < 30: - lr_adj = 1. - elif epoch < 60: - lr_adj = 1e-1 - elif epoch < 80: - lr_adj = 1e-2 - else: - lr_adj = 1e-3 - for param_group in optimizer.param_groups: - param_group['lr'] = args.base_lr * bf.size() * args.batches_per_allreduce * lr_adj - -if not args.disable_dynamic_topology and args.dist_optimizer != 'horovod': - dynamic_neighbor_allreduce_gen = topology_util.GetDynamicSendRecvRanks( - bf.load_topology(), bf.rank()) - -def dynamic_topology_update(epoch, batch_idx): - if args.dist_optimizer == 'win_put': - if epoch < 3: - return - num_out_neighbors = len(bf.out_neighbor_ranks()) - sent_neighbor = bf.out_neighbor_ranks()[batch_idx % num_out_neighbors] - optimizer.dst_weights = {sent_neighbor: 1.0} - elif args.dist_optimizer == 'neighbor_allreduce': - send_neighbors, recv_neighbors = next(dynamic_neighbor_allreduce_gen) - optimizer.send_neighbors = send_neighbors - optimizer.neighbor_weights = {r: 1/(len(recv_neighbors) + 1) for r in recv_neighbors} - optimizer.self_weight = 1 / (len(recv_neighbors) + 1) - optimizer.enable_topo_check = False - else: - pass - -def accuracy(output, target): - # get the index of the max log-probability - pred = output.max(1, keepdim=True)[1] - return pred.eq(target.view_as(pred)).cpu().float().mean() - - -def save_checkpoint(epoch): - if bf.rank() == 0: - filepath = args.checkpoint_format.format(epoch=epoch + 1) - state = { - 'model': model.state_dict(), - 'optimizer': optimizer.state_dict(), - } - torch.save(state, filepath) - - -# Bluefog: average metrics from distributed training. -class Metric(object): - def __init__(self, name): - self.name = name - self.sum = torch.tensor(0.) - self.n = torch.tensor(0.) - - def update(self, val): - self.sum += bf.allreduce(val.detach().cpu(), name=self.name) - self.n += 1 - - @property - def avg(self): - return self.sum / self.n - - -for epoch in range(resume_from_epoch, args.epochs): - train(epoch) - validate(epoch) - save_checkpoint(epoch) diff --git a/examples/pytorch_benchmark.py b/examples/pytorch_benchmark.py index 5244fa91..81fe27e6 100644 --- a/examples/pytorch_benchmark.py +++ b/examples/pytorch_benchmark.py @@ -78,11 +78,11 @@ elif args.virtual_topology == "ring": bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=1)) elif args.virtual_topology == "InnerOuterRing": - assert bf.is_homogeneous, "InnerOuterRing topo should be used only homogeneous environment" + assert bf.is_homogeneous, "InnerOuterRing should be used only homogeneous environment" bf.set_topology(topology_util.InnerOuterRingGraph( bf.size(), local_size=bf.local_size() if args.local_size == -1 else args.local_size)) elif args.virtual_topology == "InnerOuterExpo2": - assert bf.is_homogeneous, "InnerOuterExpo2 topo should be used under homogeneous environment" + assert bf.is_homogeneous, "InnerOuterExpo2 should be used under homogeneous environment" bf.set_topology(topology_util.InnerOuterExpo2Graph( bf.size(), local_size=bf.local_size() if args.local_size == -1 else args.local_size)) else: diff --git a/examples/pytorch_cifar10_resnet.py b/examples/pytorch_resnet.py similarity index 83% rename from examples/pytorch_cifar10_resnet.py rename to examples/pytorch_resnet.py index d02ca894..654608ef 100644 --- a/examples/pytorch_cifar10_resnet.py +++ b/examples/pytorch_resnet.py @@ -53,6 +53,12 @@ 'total batch size.') parser.add_argument('--model', type=str, default='resnet18', help='model to benchmark') +parser.add_argument('--dataset', type=str, default='cifar10', + help='The dataset to train with.') +parser.add_argument('--train-dir', default=os.path.expanduser('~/imagenet/train'), + help='path to training data') +parser.add_argument('--val-dir', default=os.path.expanduser('~/imagenet/validation'), + help='path to validation data') # Default settings from https://arxiv.org/abs/1706.02677. parser.add_argument('--batch-size', type=int, default=32, @@ -77,10 +83,6 @@ parser.add_argument('--dist-optimizer', type=str, default='neighbor_allreduce', help='The type of distributed optimizer. Supporting options are [win_put, ' + 'neighbor_allreduce, allreduce, hierarchical_neighbor_allreduce, horovod]') -parser.add_argument("--average-test-result", action="store_true", - default=False, - help=("Allreduce called to average test result. Warning this will " + - "force the algorithm to sync every end of epoch.")) parser.add_argument('--disable-dynamic-topology', action='store_true', default=False, help=('Disable each iteration to transmit one neighbor ' + 'per iteration dynamically.')) @@ -135,18 +137,30 @@ kwargs = {"num_workers": 4, "pin_memory": True} if args.cuda else {} -train_dataset = datasets.CIFAR10( - os.path.join(cwd_folder_loc, "..", "data", "data-%d" % bf.rank()), - train=True, - download=True, - transform=transforms.Compose( - [ - transforms.ToTensor(), - transforms.Normalize(mean=[0.485, 0.456, 0.406], - std=[0.229, 0.224, 0.225]), - ] - ), -) +if args.dataset == "cifar10": + train_dataset = datasets.CIFAR10( + os.path.join(cwd_folder_loc, "..", "data", "data-%d" % bf.rank()), + train=True, + download=True, + transform=transforms.Compose( + [ + transforms.ToTensor(), + transforms.Normalize(mean=[0.485, 0.456, 0.406], + std=[0.229, 0.224, 0.225]), + ] + ), + ) +elif args.dataset == "imagenet": + train_dataset = datasets.ImageFolder(args.train_dir, + transform=transforms.Compose([ + transforms.RandomResizedCrop(224), + transforms.RandomHorizontalFlip(), + transforms.ToTensor(), + transforms.Normalize(mean=[0.485, 0.456, 0.406], + std=[0.229, 0.224, 0.225]) + ])) +else: + raise ValueError("Args dataset should be either cifar10 or imagenet") # Bluefog: use DistributedSampler to partition data among workers. Manually specify # `num_replicas=bf.size()` and `rank=bf.rank()`. @@ -157,29 +171,40 @@ train_dataset, batch_size=allreduce_batch_size, sampler=train_sampler, **kwargs ) -val_dataset = datasets.CIFAR10( - os.path.join(cwd_folder_loc, "..", "data", "data-%d" % bf.rank()), - train=False, - transform=transforms.Compose( - [ - transforms.ToTensor(), - transforms.Normalize(mean=[0.485, 0.456, 0.406], - std=[0.229, 0.224, 0.225]), - ] - ), -) -if args.average_test_result: - val_sampler = torch.utils.data.distributed.DistributedSampler( - val_dataset, num_replicas=bf.size(), rank=bf.rank() +if args.dataset == "cifar10": + val_dataset = datasets.CIFAR10( + os.path.join(cwd_folder_loc, "..", "data", "data-%d" % bf.rank()), + train=False, + transform=transforms.Compose( + [ + transforms.ToTensor(), + transforms.Normalize(mean=[0.485, 0.456, 0.406], + std=[0.229, 0.224, 0.225]), + ] + ), ) -else: - val_sampler = None +elif args.dataset == "imagenet": + val_dataset = datasets.ImageFolder(args.val_dir, + transform=transforms.Compose([ + transforms.Resize(256), + transforms.CenterCrop(224), + transforms.ToTensor(), + transforms.Normalize(mean=[0.485, 0.456, 0.406], + std=[0.229, 0.224, 0.225]) + ])) + +val_sampler = torch.utils.data.distributed.DistributedSampler( + val_dataset, num_replicas=bf.size(), rank=bf.rank() +) val_loader = torch.utils.data.DataLoader( val_dataset, batch_size=args.val_batch_size, sampler=val_sampler, **kwargs ) -model = getattr(models, args.model)(num_classes=10) +if args.dataset == "cifar10": + model = getattr(models, args.model)(num_classes=10) +elif args.dataset == "imagenet": + model = getattr(models, args.model)(num_classes=1000) if args.cuda: # Move model to GPU. @@ -373,8 +398,7 @@ def save_checkpoint(epoch): dirpath = os.path.dirname(filepath) if not os.path.exists(dirpath): os.makedirs(dirpath) - state = {"model": model.state_dict( - ), "optimizer": optimizer.state_dict()} + state = {"model": model.state_dict(), "optimizer": optimizer.state_dict()} torch.save(state, filepath) @@ -386,10 +410,7 @@ def __init__(self, name): self.n = torch.tensor(0.0) # pylint: disable=not-callable def update(self, val): - if args.average_test_result: - self.sum += bf.allreduce(val.detach().cpu(), name=self.name) - else: - self.sum += val.detach().cpu() + self.sum += bf.allreduce(val.detach().cpu(), name=self.name) self.n += 1 @property diff --git a/test/torch_ops_test.py b/test/torch_ops_test.py index 49931cc8..fd4c45d9 100644 --- a/test/torch_ops_test.py +++ b/test/torch_ops_test.py @@ -983,6 +983,7 @@ def test_neighbor_allgather(self): assert sorted(candidate_ranks) == gathered_ranks, \ "bf.neighbor_allgather produces incorrect gathered tensor" + @unittest.skip("Need re-design of API.") def test_pair_gossip(self): size = bf.size() rank = bf.rank() @@ -1002,7 +1003,7 @@ def test_pair_gossip(self): for dtype, dim in itertools.product(dtypes, dims): tensor = torch.FloatTensor(*([23] * dim)).fill_(1).mul_(rank) tensor = self.cast_and_place(tensor, dtype) - gossiped_tensor = bf.pair_gossip(tensor, target_rank) + # gossiped_tensor = bf.pair_gossip(tensor, target_rank) tensor, gossiped_tensor = self.convert_cpu_fp16_to_fp32(tensor, gossiped_tensor) assert ( @@ -1014,6 +1015,7 @@ def test_pair_gossip(self): bf.set_skip_negotiate_stage(False) + @unittest.skip("Need re-design of API.") def test_pair_gossip_weighted(self): size = bf.size() rank = bf.rank() @@ -1034,8 +1036,8 @@ def test_pair_gossip_weighted(self): for dtype, dim in itertools.product(dtypes, dims): tensor = torch.FloatTensor(*([23] * dim)).fill_(1).mul_(rank) tensor = self.cast_and_place(tensor, dtype) - gossiped_tensor = bf.pair_gossip( - tensor, target_rank, self_weight=0.25, pair_weight=0.75) + # gossiped_tensor = bf.pair_gossip( + # tensor, target_rank, self_weight=0.25, pair_weight=0.75) tensor, gossiped_tensor = self.convert_cpu_fp16_to_fp32(tensor, gossiped_tensor) assert ( list(gossiped_tensor.shape) == [23] * dim From d771ad0334dc8abd5abb54340faa012c3849cf5b Mon Sep 17 00:00:00 2001 From: ybc Date: Tue, 3 Nov 2020 22:41:13 -0800 Subject: [PATCH 43/44] Update performance and API documents --- bluefog/torch/__init__.py | 2 +- docs/_static/bf_full_benchmark1.png | Bin 0 -> 32930 bytes docs/_static/bf_full_benchmark2.png | Bin 0 -> 46082 bytes docs/conf.py | 3 +- docs/index.rst | 4 +- docs/neighbor_average.rst | 3 ++ docs/performance.rst | 73 +++++++++++++++++++++++++++- docs/rationale.rst | 4 -- docs/torch_api.rst | 35 ++++++++++++- examples/pytorch_resnet.py | 4 +- 10 files changed, 116 insertions(+), 12 deletions(-) create mode 100644 docs/_static/bf_full_benchmark1.png create mode 100644 docs/_static/bf_full_benchmark2.png create mode 100644 docs/neighbor_average.rst delete mode 100644 docs/rationale.rst diff --git a/bluefog/torch/__init__.py b/bluefog/torch/__init__.py index fdf66f9a..ded43234 100644 --- a/bluefog/torch/__init__.py +++ b/bluefog/torch/__init__.py @@ -38,7 +38,6 @@ from bluefog.torch.mpi_ops import mpi_threads_supported from bluefog.torch.mpi_ops import unified_mpi_window_model_supported from bluefog.torch.mpi_ops import nccl_built, is_homogeneous -from bluefog.torch.mpi_ops import set_skip_negotiate_stage, get_skip_negotiate_stage from bluefog.torch.mpi_ops import allreduce, allreduce_nonblocking from bluefog.torch.mpi_ops import allreduce_, allreduce_nonblocking_ @@ -63,6 +62,7 @@ from bluefog.torch.mpi_ops import win_associated_p from bluefog.torch.mpi_ops import turn_on_win_ops_with_associated_p from bluefog.torch.mpi_ops import turn_off_win_ops_with_associated_p +from bluefog.torch.mpi_ops import set_skip_negotiate_stage, get_skip_negotiate_stage from bluefog.torch.mpi_ops import timeline_start_activity, timeline_end_activity from bluefog.torch.mpi_ops import timeline_context diff --git a/docs/_static/bf_full_benchmark1.png b/docs/_static/bf_full_benchmark1.png new file mode 100644 index 0000000000000000000000000000000000000000..6ca1179b69d0d72039ced3b69bcaec62f4639107 GIT binary patch literal 32930 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 ASO5S3 literal 0 HcmV?d00001 diff --git a/docs/conf.py b/docs/conf.py index e944e6b7..e22a7df4 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -18,7 +18,7 @@ # -- Project information ----------------------------------------------------- project = 'Bluefog' -copyright = '2020, Bicheng Ying' +copyright = '2020, BlueFog Team' author = 'Bicheng Ying' master_doc = 'index' @@ -36,6 +36,7 @@ 'sphinx.ext.autodoc', 'sphinx.ext.napoleon', 'matplotlib.sphinxext.plot_directive', + 'autodocsumm', ] # Include the example source for plots in API docs diff --git a/docs/index.rst b/docs/index.rst index a377419f..066996f1 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -137,11 +137,11 @@ algorithm, please read our :ref:`Ops Explanation` page. :caption: More Information Bluefog Ops Explanation + Bluefog Performance + Static and Dynamic Neighbor Averaging Lauching Application Through bfrun Bluefog Docker Usage Bluefog Environment Variable - Bluefog Perform Comparison - Bluefog Rationale Bluefog Timeline Spectrum of Machine Learning Algorithm Codebase Structure diff --git a/docs/neighbor_average.rst b/docs/neighbor_average.rst new file mode 100644 index 00000000..003f4fd5 --- /dev/null +++ b/docs/neighbor_average.rst @@ -0,0 +1,3 @@ +Static and Dynamic Neighbor Averaging +===================================== + diff --git a/docs/performance.rst b/docs/performance.rst index fb51d0de..b2a56845 100644 --- a/docs/performance.rst +++ b/docs/performance.rst @@ -1,4 +1,75 @@ Performance =========== -To be added. \ No newline at end of file + +ThroughPut Benchmark +-------------------- + +All of our benchmarks were run on the AWS. We use p3.16xlarge as basic machine. +Each machine has 8 V100 GPUs (64GB memory) with NVLink-enabled and inter-connected communication speed is 25Gbps. +For more details of machine instance, you can find it `here`_. + +To reproduce the benchmarks, run following command [#]_: + +.. code-block:: bash + + $ bfrun -np 16 -H server1:4,server2:4,server3:4,server4:4 \ + python examples/pytorch_benchmark.py --batch-size 64 \ + --dist-optimizer=neighbor_allreduce --virtual-topology InnerOuterExp2 + +At the end of run, you will see the total number of images processed per second like: + +.. code-block:: bash + + Total img/sec on 16 GPU(s): 4310.6 +- 146.9 + +We also provide another distributed optimizer `DistributedHierarchicalNeighborAllreduce`, which is similar +as neighbor_allreduce one but within each machine execute local allreduce first to form a super node. This +optimizer may produce better scaling in terms of loss and accuracy. Read :ref:`Ops Explanation` page to checkout +the details of the underlying communication operation. + +.. code-block:: bash + + $ bfrun -np 16 -H server1:4,server2:4,server3:4,server4:4 \ + python examples/pytorch_benchmark.py --batch-size 64 \ + --dist-optimizer=hierarchical_neighbor_allreduce + +We also provided the option of set dist-optimizer as horovod for easy comparison. Above three dist-optimizers produce following +benchmarks: + +.. image:: _static/bf_full_benchmark1.png + :width: 600 + :align: center + +where N\_AR represents the neighbor allreduce optimizer and H\_N\_AR represents the hierarchical_neighbor_allreduce and the black +box represents the idea of linear scaling. We can see Bluefog can achieve over 95% scaling efficiency while Horovod is around 78% +sacling efficiency under a batch size of 64. + +For more communication intensive case with a batch size of 32, +the scaling efficiency between Bluefog and Horovod becomes even larger. + +.. image:: _static/bf_full_benchmark2.png + :width: 600 + :align: center + +Accuracy and Loss +----------------- + +TO BE ADDED + +Tricks of Boosting Accuracy +--------------------------- + +Just like the tricks decaying of lr over time used in the large batch size training for ImageNet, there are several small tricks of +using Bluefog as well, including + +* Smaller Warmup LR +* Periodical Global Average +* ATC (adapt-then-combine) VS DGD(distributed-gradient-descent) style (Do the neighbor allreduce after VS in parallel with gradient computation) +* Faster learning rate decaying like decaying every 25 epoches instead of 30 epoches for ImageNet + ResNet Training + +TO BE ADDED + + +.. _here: https://aws.amazon.com/ec2/instance-types/p3/ +.. [#] We recommended using aws-ParallelCluster as cluster manager combined with our docker images to run BlueFog on AWS. \ No newline at end of file diff --git a/docs/rationale.rst b/docs/rationale.rst deleted file mode 100644 index fda777f4..00000000 --- a/docs/rationale.rst +++ /dev/null @@ -1,4 +0,0 @@ -Bluefog Rationale -================= - -To be added. \ No newline at end of file diff --git a/docs/torch_api.rst b/docs/torch_api.rst index ac54240a..6468d64b 100644 --- a/docs/torch_api.rst +++ b/docs/torch_api.rst @@ -1,5 +1,38 @@ Torch Module (API Reference) ============================ +All APIs can be roughly categorized into 5 classes: + +* Bluefog Basic Operations: + * init, shutdown, + * size, local_size, rank, local_rank, is_homogeneous + * load_topology, set_topology, in_neighbor_ranks, out_neighbor_ranks +* High-level Optimizer Wrappers: + * DistributedGradientAllreduceOptimizer + * DistributedAllreduceOptimizer + * DistributedNeighborAllreduceOptimizer + * DistributedHierarchicalNeighborAllreduceOptimizer + * DistributedWinPutOptimizer +* Low-level Synchronous Communication Operations: + * allreduce, allreduce_nonblocking, allreduce\_, allreduce_nonblocking\_ + * allgather, allgather_nonblocking + * broadcast, broadcast_nonblocking, broadcast\_, broadcast_nonblocking\_ + * neighbor_allgather, neighbor_allgather_nonblocking + * neighbor_allreduce, neighbor_allreduce_nonblocking + * hierarchical_neighbor_allreduce, hierarchical_neighbor_allreduce_nonblocking + * poll, synchronize, barrier +* Low-level Asynchronous Communication Operations: + * win_create, win_free, win_update, win_update_then_collect + * win_put_nonblocking, win_put + * win_get_nonblocking, win_get + * win_accumulate_nonblocking, win_accumulate + * win_wait, win_poll, win_mutex +* Other miscellaneous and utility functions: + * broadcast_optimizer_state, broadcast_parameters, allreduce_parameters + * timeline_start_activity, timeline_end_activity + * nccl_built, mpi_threads_supported, unified_mpi_window_model_supported + .. automodule:: bluefog.torch - :members: \ No newline at end of file + :members: + :exclude-members: check_extension + :member-order: bysource \ No newline at end of file diff --git a/examples/pytorch_resnet.py b/examples/pytorch_resnet.py index 654608ef..5f998110 100644 --- a/examples/pytorch_resnet.py +++ b/examples/pytorch_resnet.py @@ -107,11 +107,11 @@ elif args.virtual_topology == "ring": bf.set_topology(topology_util.RingGraph(bf.size(), connect_style=1)) elif args.virtual_topology == "InnerOuterRing": - assert bf.is_homogeneous, "InnerOuterRing topo should be used only homogeneous environment" + assert bf.is_homogeneous, "InnerOuterRing should be used under homogeneous environment" bf.set_topology(topology_util.InnerOuterRingGraph( bf.size(), local_size=bf.local_size())) elif args.virtual_topology == "InnerOuterExpo2": - assert bf.is_homogeneous, "InnerOuterExpo2 topo should be used under homogeneous environment" + assert bf.is_homogeneous, "InnerOuterExpo2 should be used under homogeneous environment" bf.set_topology(topology_util.InnerOuterExpo2Graph( bf.size(), local_size=bf.local_size())) else: From fc4701e8e1f79cb48be37ed01ee5d5ed5ee7eb9f Mon Sep 17 00:00:00 2001 From: ybc Date: Tue, 3 Nov 2020 23:45:14 -0800 Subject: [PATCH 44/44] Add neighbor averaging doc --- docs/_static/one-peer-exp2.png | Bin 0 -> 164298 bytes docs/index.rst | 2 +- docs/neighbor_average.rst | 100 ++++++++++++++++++++++++++++++++- 3 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 docs/_static/one-peer-exp2.png diff --git a/docs/_static/one-peer-exp2.png b/docs/_static/one-peer-exp2.png new file mode 100644 index 0000000000000000000000000000000000000000..3009adc032b8170a42081ab5c8c3c9db23aeeaf1 GIT binary patch literal 164298 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