dyng
DynamicGraphLayout
foresighted_parallel.h
1 /*
2  Copyright 2020 František Bráblík
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16 #pragma once
17 
18 #include "foresighted_layout.h"
19 #include "parallel.h"
20 
21 #include <memory>
22 
23 namespace dyng {
24 
37 template<typename StaticLayout>
38 class parallel_foresighted_layout : public foresighted_layout<StaticLayout> {
39 public:
41  unsigned threads
42  , float tolerance
43  , float canvas_width
44  , float canvas_height
45  , coords center = coords())
46  : foresighted_layout<StaticLayout>(tolerance, canvas_width, canvas_height, center)
47  , m_parallel(std::make_unique<detail::parallel>(threads)) {}
48 
50  parallel_foresighted_layout(unsigned threads, float tolerance)
51  : parallel_foresighted_layout(threads, tolerance, 1, 1) {}
52 
56 
58  void set_threads(unsigned count) {
59  m_parallel = std::make_unique<detail::parallel>(count);
60  }
61 
62 private:
63  // is a unique ptr because class parallel is neither copyable nor movable
64  std::unique_ptr<detail::parallel> m_parallel;
65 
66  void tolerance(
67  std::vector<graph_state>& states
68  , float width
69  , float height
70  , float tolerance_value) override {
71  float temp = this->m_cooling.start_temperature;
72  if (!this->m_relative_distance) {
73  tolerance_value *= this->m_static_layout.relative_unit(width, height)
74  * this->max_nodes(states);
75  }
76  detail::barrier bar(m_parallel->count());
77  std::vector<graph_state> copies = states;
78  std::vector<bool> apply(states.size());
79  auto get = [&](unsigned i) -> const graph_state& {
80  if (apply[i]) {
81  return copies[i];
82  }
83  return states[i];
84  };
85  // there is no benefit in iterating sequentially, so we can split the
86  // indices not in chunks but in an interleaved way;
87  // this makes it faster for incrementally growing dynamic graphs
88  // because the tasks are split more evenly
89  m_parallel->for_each_interleaved([&](unsigned begin, unsigned step){
90  for (unsigned r = 0; r < this->m_cooling.iterations; ++r) {
91  for (unsigned i = begin; i < states.size(); i += step) {
92  if (apply[i]) {
93  states[i] = copies[i];
94  } else {
95  copies[i] = states[i];
96  }
97  }
98  for (unsigned i = begin; i < states.size(); i += step) {
99  this->m_static_layout.iteration(copies[i], width, height, temp);
100  }
101  bar.wait();
102  if (begin == 0) {
103  // only the first thread will do this
104  // this has to be sequential
105  for (unsigned i = 0; i < states.size(); ++i) {
106  apply[i] = false;
107  if ((i == 0 || this->distance(copies[i], get(i - 1)) < tolerance_value)
108  && (i >= states.size() - 1
109  || this->distance(copies[i], states[i + 1]) < tolerance_value)) {
110  apply[i] = true;
111  }
112  }
113  temp = this->m_cooling.anneal(temp);
114  }
115  bar.wait();
116  }
117  });
118  }
119 };
120 
121 } // namespace dyng
dyng::foresighted_layout
Definition: foresighted_layout.h:48
dyng::coords
Class representing coordinates in 2D space.
Definition: coords.h:21
dyng::parallel_foresighted_layout::parallel_foresighted_layout
parallel_foresighted_layout(unsigned threads, float tolerance)
Initializes this with a given number of threads and given tolerance.
Definition: foresighted_parallel.h:50
dyng::parallel_foresighted_layout
Definition: foresighted_parallel.h:38
dyng::parallel_foresighted_layout::set_threads
void set_threads(unsigned count)
Sets the thread count.
Definition: foresighted_parallel.h:58
dyng::parallel_foresighted_layout::parallel_foresighted_layout
parallel_foresighted_layout()
Initializes this with the default thread count of 4 and tolerance = 0.
Definition: foresighted_parallel.h:54