1 | /** |
2 | * Copyright (c) 2018-present, Facebook, Inc. |
3 | * All rights reserved. |
4 | * |
5 | * This source code is licensed under the BSD-style license found in the |
6 | * LICENSE file in the root directory of this source tree. |
7 | */ |
8 | |
9 | #include "gloo/barrier.h" |
10 | |
11 | namespace gloo { |
12 | |
13 | BarrierOptions::BarrierOptions(const std::shared_ptr<Context>& context) |
14 | : context(context), |
15 | buffer(context->createUnboundBuffer(nullptr, 0)), |
16 | timeout(context->getTimeout()) {} |
17 | |
18 | void barrier(BarrierOptions& opts) { |
19 | const auto& context = opts.context; |
20 | auto& buffer = opts.buffer; |
21 | const auto slot = Slot::build(kBarrierSlotPrefix, opts.tag); |
22 | |
23 | // Below implements a dissemination barrier, described in "Two algorithms |
24 | // for barrier synchronization (1988)" by Hensgen, Finkel and Manber. |
25 | // PDF: https://www.inf.ed.ac.uk/teaching/courses/ppls/BarrierPaper.pdf |
26 | // DOI: 10.1007/BF01379320 |
27 | |
28 | // Instead of iterating over i up to log2(context->size), we immediately |
29 | // compute 2^i and compare with context->size. |
30 | for (size_t d = 1; d < context->size; d <<= 1) { |
31 | buffer->recv((context->size + context->rank - d) % context->size, slot); |
32 | buffer->send((context->size + context->rank + d) % context->size, slot); |
33 | buffer->waitRecv(opts.timeout); |
34 | buffer->waitSend(opts.timeout); |
35 | } |
36 | } |
37 | |
38 | } // namespace gloo |
39 | |