Skip to content

Commit 78cf005

Browse files
committed
documentation
docu updates
1 parent 6848cb4 commit 78cf005

10 files changed

Lines changed: 163 additions & 170 deletions

File tree

apps/test_suite_runner/AbstractTestSuiteRunner.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ class AbstractTestSuiteRunner {
251251
log_stream << "Start Graph: " + filename_graph + "\n";
252252

253253
BspInstance<GraphType> bsp_instance;
254-
bsp_instance.setArchitecture(arch);
254+
bsp_instance.getArchitecture() = arch;
255255
bool graph_status = false;
256256
std::string ext;
257257
if (filename_graph.rfind('.') != std::string::npos)

apps/test_suite_runner/StringToScheduler/run_bsp_scheduler.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ limitations under the License.
5757
namespace osp {
5858

5959
const std::set<std::string> get_available_bsp_scheduler_names() {
60-
return {"Serial", "GreedyBsp", "GrowLocal", "BspLocking", "Cilk", "Etf", "GreedyRandom",
61-
"GreedyChildren", "Variance", "MultiHC", "LocalSearch", "Coarser", "FullILP", "MultiLevel"};
60+
return {"Serial", "GreedyBsp", "GrowLocal", "BspLocking", "Cilk", "Etf", "GreedyRandom",
61+
"GreedyChildren", "Variance", "MultiHC", "LocalSearch", "Coarser", "FullILP", "MultiLevel"};
6262
}
6363

6464
template<typename Graph_t>
@@ -247,7 +247,7 @@ RETURN_STATUS run_bsp_scheduler(const ConfigParser &parser, const boost::propert
247247
if (!status)
248248
return RETURN_STATUS::ERROR;
249249

250-
instance_coarse.setArchitecture(instance.getArchitecture());
250+
instance_coarse.getArchitecture() = instance.getArchitecture();
251251
instance_coarse.setNodeProcessorCompatibility(instance.getProcessorCompatibilityMatrix());
252252
BspSchedule<boost_graph_t> schedule_coarse(instance_coarse);
253253

include/osp/bsp/model/BspArchitecture.hpp

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,12 @@ inline std::ostream &operator<<(std::ostream &os, MEMORY_CONSTRAINT_TYPE type) {
9090
* bounds. It provides methods to set and retrieve these values.
9191
*
9292
* **Processors:**
93-
* The architecture consists of p processors, indexed from 0 to p-1.
93+
* The architecture consists of p processors, indexed from 0 to p-1. Note that processor indices are represented using `unsigned`.
9494
*
9595
* **Processor Types:**
9696
* Processors can have different types, which are represented by non-negative integers.
97-
* Processor types are assumed to be consecutive integers starting from 0.
97+
* Processor types are assumed to be consecutive integers starting from 0. Note that processor types are represented using `unsigned`.
98+
* Processor types are used to express compatabilities, which can be specified in the BspInstance, regarding node types.
9899
*
99100
* **Communication and Synchronization Costs:**
100101
* - Communication Cost (g): The cost of communicating a unit of data between processors, i.e., the bandwidth.
@@ -185,35 +186,16 @@ class BspArchitecture {
185186
}
186187

187188
public:
188-
/**
189-
* @brief Default constructor.
190-
* Initializes a BSP architecture with 2 processors, 1 processor type,
191-
* communication costs of 1, synchronisation costs of 2, memory bounds of 100,
192-
* and send costs of 1 between all processors.
193-
*/
194-
BspArchitecture()
195-
: numberOfProcessors_(2U), numberOfProcessorTypes_(1U), communicationCosts_(1U), synchronisationCosts_(2U),
196-
memoryBound_(numberOfProcessors_, 100U), isNuma_(false),
197-
processorTypes_(numberOfProcessors_, 0U), sendCosts_(numberOfProcessors_ * numberOfProcessors_, 1U) {
198-
SetSendCostDiagonalToZero();
199-
}
200-
201-
BspArchitecture(const BspArchitecture &other) = default;
202-
BspArchitecture(BspArchitecture &&other) noexcept = default;
203-
BspArchitecture &operator=(const BspArchitecture &other) = default;
204-
BspArchitecture &operator=(BspArchitecture &&other) noexcept = default;
205-
virtual ~BspArchitecture() = default;
206-
207189
/**
208190
* @brief Constructs a BspArchitecture object with the specified number of processors, communication cost, and
209191
* synchronization cost.
210192
*
211-
* @param NumberOfProcessors The number of processors in the architecture. Must be greater than 0.
212-
* @param CommunicationCost The communication cost between processors.
213-
* @param SynchronisationCost The synchronization cost between processors.
193+
* @param NumberOfProcessors The number of processors in the architecture. Must be greater than 0. Default: 2.
194+
* @param CommunicationCost The communication cost between processors. Default: 1.
195+
* @param SynchronisationCost The synchronization cost between processors. Default: 2.
214196
* @param MemoryBound The memory bound for each processor (default: 100).
215197
*/
216-
BspArchitecture(const unsigned NumberOfProcessors, const v_commw_t<Graph_t> CommunicationCost, const v_commw_t<Graph_t> SynchronisationCost,
198+
BspArchitecture(const unsigned NumberOfProcessors = 2U, const v_commw_t<Graph_t> CommunicationCost = 1U, const v_commw_t<Graph_t> SynchronisationCost = 2U,
217199
const v_memw_t<Graph_t> MemoryBound = 100U)
218200
: numberOfProcessors_(NumberOfProcessors), numberOfProcessorTypes_(1U), communicationCosts_(CommunicationCost),
219201
synchronisationCosts_(SynchronisationCost),
@@ -225,6 +207,12 @@ class BspArchitecture {
225207
SetSendCostDiagonalToZero();
226208
}
227209

210+
BspArchitecture(const BspArchitecture &other) = default;
211+
BspArchitecture(BspArchitecture &&other) noexcept = default;
212+
BspArchitecture &operator=(const BspArchitecture &other) = default;
213+
BspArchitecture &operator=(BspArchitecture &&other) noexcept = default;
214+
virtual ~BspArchitecture() = default;
215+
228216
/**
229217
* @brief Copy constructor from a BspArchitecture with a different graph type.
230218
*

include/osp/bsp/model/BspInstance.hpp

Lines changed: 92 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -29,40 +29,71 @@ namespace osp {
2929

3030
/**
3131
* @class BspInstance
32-
* @brief Represents an instance of the BSP (Bulk Synchronous Parallel) model.
32+
* @brief Represents a scheduling problem instance for the Bulk Synchronous Parallel (BSP) model.
3333
*
34-
* The BspInstance class encapsulates the computational DAG (Directed Acyclic Graph) and the BSP architecture
35-
* for a specific instance of the BSP model. It provides methods to access and modify the architecture and DAG,
36-
* as well as retrieve information about the instance such as the number of vertices and processors.
34+
* The BspInstance class serves as a container for all the necessary information to define a
35+
* BSP scheduling problem. It acts as the "ground" object that holds the actual implementation
36+
* of the graph and architecture.
3737
*
38-
* The instance specifies the compatibility between node types and processor types.
38+
* It aggregates three main components:
3939
*
40-
* @tparam Graph_t The type of the computational DAG.
40+
* 1. **Computational DAG**: The directed acyclic graph representing the program to be executed.
41+
* It defines the tasks (nodes), their dependencies (directed edges), and associated weights (work, memory, communication).
42+
*
43+
* 2. **BSP Architecture**: The hardware model description, including the number of processors,
44+
* their types, memory bounds, and communication/synchronization costs.
45+
* Note that processor indices are represented using `unsigned`.
46+
*
47+
* 3. **Node-Processor Compatibility**: A matrix defining which node types can be executed on which
48+
* processor types. This enables the modeling of heterogeneous systems (e.g., CPU + GPU) where
49+
* certain nodes are restricted to specific hardware accelerators.
50+
*
51+
* @warning Be careful when assigning an existing graph to a BspInstance. Depending on the
52+
* constructor or assignment operator used, this may result in a deep copy of the graph structure,
53+
* which can be expensive for large graphs.
54+
*
55+
* This class provides a unified interface to access and modify these components, facilitating
56+
* the development of scheduling algorithms that need to query problem constraints and properties.
57+
*
58+
* @tparam Graph_t The type of the computational DAG, which must satisfy the `is_computational_dag` concept.
4159
*/
4260
template<typename Graph_t>
4361
class BspInstance {
4462
static_assert(is_computational_dag_v<Graph_t>, "BspInstance can only be used with computational DAGs.");
4563

4664
private:
4765
/**
48-
* @brief The computational DAG of the instance. Holds the graph structure and the node types, work, memory, communication weights.
66+
* @brief The computational DAG representing the program structure.
67+
*
68+
* It contains the graph topology (nodes and directed edges) as well as attributes such as node types,
69+
* work weights, memory weights, and edge communication weights.
4970
*/
5071
Graph_t cdag;
5172
/**
52-
* @brief The BSP architecture of the instance. Holds the processor types and the memory bounds. Communication and synchronization cost. And the send cost between processors.
73+
* @brief The BSP architecture model.
74+
*
75+
* It defines the hardware characteristics including processor types, memory limits,
76+
* communication bandwidth/latency (send costs), and global synchronization costs.
5377
*/
5478
BspArchitecture<Graph_t> architecture;
5579

5680
/**
5781
* @brief Stores the compatibility between node types and processor types.
5882
*
59-
* The architecture defines a type for each processor, and the dag defines a type for each node.
83+
* The architecture defines a type for each processor, and the DAG defines a type for each node.
6084
* This matrix stores for each node type and processor type whether they are compatible, i.e.,
61-
* if a node of the can be assigned to a processor of the given type in a schedule.
85+
* if a node of that type can be assigned to a processor of the given type in a schedule.
6286
* @note The outer vector is indexed by node type, the inner vector is indexed by processor type.
6387
*/
6488
std::vector<std::vector<bool>> nodeProcessorCompatibility = std::vector<std::vector<bool>>({{true}});
6589

90+
/**
91+
* @brief The type of the vectex types in the computational DAG.
92+
* If the DAG does not support vertex types, this is `unsigned`.
93+
*/
94+
using vertex_type_t_or_default = std::conditional_t<is_computational_dag_typed_vertices_v<Graph_t>, v_type_t<Graph_t>, unsigned>;
95+
using processor_type_t = unsigned;
96+
6697
public:
6798
/**
6899
* @brief Default constructor for the BspInstance class.
@@ -107,19 +138,16 @@ class BspInstance {
107138

108139
/**
109140
* @brief Returns a reference to the BSP architecture of the instance.
141+
* Assigning the BSP architecture via the reference creates a copy of the architecture.
142+
* The move operator may be used to transfer ownership of the architecture.
110143
*/
111144
[[nodiscard]] const BspArchitecture<Graph_t> &getArchitecture() const { return architecture; }
112145
[[nodiscard]] BspArchitecture<Graph_t> &getArchitecture() { return architecture; }
113146

114-
/**
115-
* @brief Sets the BSP architecture for the instance.
116-
*
117-
* @param architecture_ The BSP architecture for the instance.
118-
*/
119-
void setArchitecture(const BspArchitecture<Graph_t> &architechture_) { architecture = architechture_; }
120-
121147
/**
122148
* @brief Returns a reference to the computational DAG of the instance.
149+
* Assigning the computational DAG via the reference creates a copy of the DAG.
150+
* The move operator may be used to transfer ownership of the DAG.
123151
*/
124152
[[nodiscard]] const Graph_t &getComputationalDag() const { return cdag; }
125153
[[nodiscard]] Graph_t &getComputationalDag() { return cdag; }
@@ -190,7 +218,6 @@ class BspInstance {
190218

191219
/**
192220
* @brief Returns the memory bound for a specific processor.
193-
*
194221
* @param proc The processor index.
195222
*/
196223
[[nodiscard]] v_memw_t<Graph_t> memoryBound(const unsigned proc) const { return architecture.memoryBound(proc); }
@@ -215,41 +242,11 @@ class BspInstance {
215242
*/
216243
void setNumberOfProcessors(const unsigned num) { architecture.setNumberOfProcessors(num); }
217244

218-
/**
219-
* @brief Returns false if there is a node whose weight does not fit on any of its compatible processors.
220-
* @return True if the memory constraints are feasible, false otherwise.
221-
*/
222-
[[nodiscard]] bool CheckMemoryConstraintsFeasibility() const {
223-
std::vector<v_memw_t<Graph_t>> max_memory_per_proc_type(architecture.getNumberOfProcessorTypes(), 0);
224-
for (unsigned proc = 0; proc < architecture.numberOfProcessors(); proc++) {
225-
max_memory_per_proc_type[architecture.processorType(proc)] =
226-
std::max(max_memory_per_proc_type[architecture.processorType(proc)], architecture.memoryBound(proc));
227-
}
228-
229-
for (unsigned vertType = 0; vertType < cdag.num_vertex_types(); vertType++) {
230-
v_memw_t<Graph_t> max_memory_of_type = max_memory_weight(vertType, cdag);
231-
bool fits = false;
232-
233-
for (unsigned proc_type = 0; proc_type < architecture.getNumberOfProcessorTypes(); proc_type++) {
234-
if (isCompatibleType(vertType, proc_type)) {
235-
fits = fits | (max_memory_of_type <= max_memory_per_proc_type[proc_type]);
236-
if (fits)
237-
break;
238-
}
239-
}
240-
241-
if (!fits)
242-
return false;
243-
}
244-
245-
return true;
246-
}
247-
248245
/**
249246
* @brief Returns the processor type for a given processor index. Does not perform bounds checking.
250247
* @param proc The processor index.
251248
*/
252-
[[nodiscard]] v_type_t<Graph_t> processorType(const unsigned proc) const { return architecture.processorType(proc); }
249+
[[nodiscard]] vertex_type_t_or_default processorType(const unsigned proc) const { return architecture.processorType(proc); }
253250

254251
/**
255252
* @brief Checks if a node is compatible with a processor. Does not perform bounds checking.
@@ -269,7 +266,7 @@ class BspInstance {
269266
* @param processorType The processor type.
270267
* @return True if the node type is compatible with the processor type, false otherwise.
271268
*/
272-
[[nodiscard]] bool isCompatibleType(const v_type_t<Graph_t> nodeType, const v_type_t<Graph_t> processorType) const {
269+
[[nodiscard]] bool isCompatibleType(const vertex_type_t_or_default nodeType, const processor_type_t processorType) const {
273270
return nodeProcessorCompatibility[nodeType][processorType];
274271
}
275272

@@ -285,6 +282,13 @@ class BspInstance {
285282
nodeProcessorCompatibility = compatibility_;
286283
}
287284

285+
/**
286+
* @brief Returns the node-processor compatibility matrix.
287+
*/
288+
[[nodiscard]] const std::vector<std::vector<bool>> &getNodeProcessorCompatibilityMatrix() const {
289+
return nodeProcessorCompatibility;
290+
}
291+
288292
/**
289293
* @brief Returns the node type - processor type compatibility matrix.
290294
*/
@@ -294,9 +298,9 @@ class BspInstance {
294298
* @brief Sets the compatibility matrix to be diagonal. This implies that node type `i` is only compatible with processor type `i`.
295299
* @param number_of_types The number of types.
296300
*/
297-
void setDiagonalCompatibilityMatrix(const unsigned number_of_types) {
301+
void setDiagonalCompatibilityMatrix(const vertex_type_t_or_default number_of_types) {
298302
nodeProcessorCompatibility.assign(number_of_types, std::vector<bool>(number_of_types, false));
299-
for (unsigned i = 0; i < number_of_types; ++i)
303+
for (vertex_type_t_or_default i = 0; i < number_of_types; ++i)
300304
nodeProcessorCompatibility[i][i] = true;
301305
}
302306

@@ -307,30 +311,52 @@ class BspInstance {
307311
nodeProcessorCompatibility.assign(cdag.num_vertex_types(), std::vector<bool>(architecture.getNumberOfProcessorTypes(), true));
308312
}
309313

314+
/**
315+
* @brief Returns false if there is a node whose weight does not fit on any of its compatible processors.
316+
* @return True if the memory constraints are feasible, false otherwise.
317+
*/
318+
[[nodiscard]] bool CheckMemoryConstraintsFeasibility() const {
319+
std::vector<v_memw_t<Graph_t>> max_memory_per_proc_type(architecture.getNumberOfProcessorTypes(), 0);
320+
for (unsigned proc = 0U; proc < architecture.numberOfProcessors(); proc++) {
321+
max_memory_per_proc_type[architecture.processorType(proc)] =
322+
std::max(max_memory_per_proc_type[architecture.processorType(proc)], architecture.memoryBound(proc));
323+
}
324+
325+
for (vertex_type_t_or_default vertType = 0U; vertType < cdag.num_vertex_types(); vertType++) {
326+
v_memw_t<Graph_t> max_memory_of_type = max_memory_weight(vertType, cdag);
327+
bool fits = false;
328+
329+
for (processor_type_t proc_type = 0U; proc_type < architecture.getNumberOfProcessorTypes(); proc_type++) {
330+
if (isCompatibleType(vertType, proc_type)) {
331+
fits = fits | (max_memory_of_type <= max_memory_per_proc_type[proc_type]);
332+
if (fits)
333+
break;
334+
}
335+
}
336+
337+
if (!fits)
338+
return false;
339+
}
340+
341+
return true;
342+
}
343+
310344
/**
311345
* @brief Returns a list of compatible processor types for each node type.
312-
*
313346
* @return A vector where the index is the node type and the value is a vector of compatible processor types.
314347
*/
315-
[[nodiscard]] std::vector<std::vector<unsigned>> getProcTypesCompatibleWithNodeType() const {
316-
unsigned numberOfNodeTypes = cdag.num_vertex_types();
317-
unsigned numberOfProcTypes = architecture.getNumberOfProcessorTypes();
318-
std::vector<std::vector<unsigned>> compatibleProcTypes(numberOfNodeTypes);
348+
[[nodiscard]] std::vector<std::vector<processor_type_t>> getProcTypesCompatibleWithNodeType() const {
349+
vertex_type_t_or_default numberOfNodeTypes = cdag.num_vertex_types();
350+
processor_type_t numberOfProcTypes = architecture.getNumberOfProcessorTypes();
351+
std::vector<std::vector<processor_type_t>> compatibleProcTypes(numberOfNodeTypes);
319352

320-
for (unsigned nodeType = 0; nodeType < numberOfNodeTypes; ++nodeType)
321-
for (unsigned processorType = 0; processorType < numberOfProcTypes; ++processorType)
353+
for (vertex_type_t_or_default nodeType = 0U; nodeType < numberOfNodeTypes; ++nodeType)
354+
for (processor_type_t processorType = 0U; processorType < numberOfProcTypes; ++processorType)
322355
if (isCompatibleType(nodeType, processorType))
323356
compatibleProcTypes[nodeType].push_back(processorType);
324357

325358
return compatibleProcTypes;
326359
}
327-
328-
/**
329-
* @brief Returns the node-processor compatibility matrix.
330-
*/
331-
[[nodiscard]] const std::vector<std::vector<bool>> &getNodeProcessorCompatibilityMatrix() const {
332-
return nodeProcessorCompatibility;
333-
}
334360
};
335361

336362
} // namespace osp

include/osp/bsp/scheduler/CoarseAndSchedule.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,17 @@ class CoarseAndSchedule : public Scheduler<Graph_t> {
4242
const auto &instance = schedule.getInstance();
4343

4444
BspInstance<Graph_t_coarse> instance_coarse;
45-
45+
4646
std::vector<vertex_idx_t<Graph_t_coarse>> reverse_vertex_map;
4747

4848
bool status = coarser.coarsenDag(instance.getComputationalDag(), instance_coarse.getComputationalDag(),
49-
reverse_vertex_map);
49+
reverse_vertex_map);
5050

5151
if (!status) {
5252
return RETURN_STATUS::ERROR;
53-
}
53+
}
5454

55-
instance_coarse.setArchitecture(instance.getArchitecture());
55+
instance_coarse.getArchitecture() = instance.getArchitecture();
5656
instance_coarse.setNodeProcessorCompatibility(instance.getProcessorCompatibilityMatrix());
5757

5858
BspSchedule<Graph_t_coarse> schedule_coarse(instance_coarse);

0 commit comments

Comments
 (0)