Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 18 additions & 19 deletions apps/test_suite_runner/AbstractTestSuiteRunner.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,16 @@ limitations under the License.
#include <string>
#include <vector>

#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include "ConfigParser.hpp"
#include "StatsModules/IStatsModule.hpp"
#include "osp/bsp/model/BspInstance.hpp"
#include "osp/auxiliary/io/arch_file_reader.hpp"
#include "osp/auxiliary/io/general_file_reader.hpp"
#include "osp/auxiliary/return_status.hpp"
#include "osp/bsp/model/BspInstance.hpp"
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>

//#define EIGEN_FOUND 1
// #define EIGEN_FOUND 1

#ifdef EIGEN_FOUND
#include <Eigen/Sparse>
Expand Down Expand Up @@ -83,7 +84,7 @@ class AbstractTestSuiteRunner {

if (write_target_object_to_file) {
output_target_object_dir_path = parser.global_params.get_child("scheduleDirectory")
.get_value<std::string>();
.get_value<std::string>();
if (output_target_object_dir_path.substr(0, 1) != "/")
output_target_object_dir_path = executable_dir + output_target_object_dir_path;
if (!output_target_object_dir_path.empty() && !std::filesystem::exists(output_target_object_dir_path)) {
Expand Down Expand Up @@ -167,13 +168,13 @@ class AbstractTestSuiteRunner {
}
}

virtual RETURN_STATUS compute_target_object_impl(const BspInstance<GraphType> &instance, std::unique_ptr<TargetObjectType>& target_object,
const pt::ptree &algo_config,
long long &computation_time_ms) = 0;
virtual RETURN_STATUS compute_target_object_impl(const BspInstance<GraphType> &instance, std::unique_ptr<TargetObjectType> &target_object,
const pt::ptree &algo_config,
long long &computation_time_ms) = 0;

virtual void create_and_register_statistic_modules(const std::string &module_name) = 0;

virtual void write_target_object_hook(const TargetObjectType&, const std::string &, const std::string &,
virtual void write_target_object_hook(const TargetObjectType &, const std::string &, const std::string &,
const std::string &) {
} // default in case TargetObjectType cannot be written to file

Expand Down Expand Up @@ -250,7 +251,7 @@ class AbstractTestSuiteRunner {
log_stream << "Start Graph: " + filename_graph + "\n";

BspInstance<GraphType> bsp_instance;
bsp_instance.setArchitecture(arch);
bsp_instance.getArchitecture() = arch;
bool graph_status = false;
std::string ext;
if (filename_graph.rfind('.') != std::string::npos)
Expand All @@ -268,12 +269,12 @@ class AbstractTestSuiteRunner {
SM_csc_int64 L_csc_int64{};

if constexpr (std::is_same_v<GraphType, sparse_matrix_graph_int32_t> || std::is_same_v<GraphType, sparse_matrix_graph_int64_t>) {
if (ext != "mtx"){
if (ext != "mtx") {
log_stream << "Error: Only .mtx file is accepted for SpTRSV" << std::endl;
return 0;
}
if constexpr (std::is_same_v<GraphType, sparse_matrix_graph_int32_t>){

if constexpr (std::is_same_v<GraphType, sparse_matrix_graph_int32_t>) {
graph_status = Eigen::loadMarket(L_csr_int32, filename_graph);
if (!graph_status) {
std::cerr << "Failed to read matrix from " << filename_graph << std::endl;
Expand All @@ -297,7 +298,7 @@ class AbstractTestSuiteRunner {
}
} else {
#endif
graph_status = file_reader::readGraph(filename_graph, bsp_instance.getComputationalDag());
graph_status = file_reader::readGraph(filename_graph, bsp_instance.getComputationalDag());

#ifdef EIGEN_FOUND
}
Expand All @@ -309,22 +310,20 @@ class AbstractTestSuiteRunner {

for (auto &algorithm_config_pair : parser.scheduler) {
const pt::ptree &algo_config = algorithm_config_pair.second;



std::string current_algo_name = algo_config.get_child("name").get_value<std::string>();
log_stream << "Start Algorithm " + current_algo_name + "\n";

long long computation_time_ms;
std::unique_ptr<TargetObjectType> target_object;
std::unique_ptr<TargetObjectType> target_object;

RETURN_STATUS exec_status = compute_target_object_impl(bsp_instance, target_object, algo_config, computation_time_ms);

if (exec_status != RETURN_STATUS::OSP_SUCCESS && exec_status != RETURN_STATUS::BEST_FOUND) {
if (exec_status == RETURN_STATUS::ERROR)
log_stream << "Error computing with " << current_algo_name << "." << std::endl;
else if (exec_status == RETURN_STATUS::TIMEOUT)
log_stream << "Scheduler " << current_algo_name << " timed out." << std::endl;
log_stream << "Scheduler " << current_algo_name << " timed out." << std::endl;
continue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ limitations under the License.
namespace osp {

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

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

instance_coarse.setArchitecture(instance.getArchitecture());
instance_coarse.getArchitecture() = instance.getArchitecture();
instance_coarse.setNodeProcessorCompatibility(instance.getProcessorCompatibilityMatrix());
BspSchedule<boost_graph_t> schedule_coarse(instance_coarse);

Expand Down
56 changes: 56 additions & 0 deletions include/osp/auxiliary/return_status.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
Copyright 2024 Huawei Technologies Co., Ltd.

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.

@author Toni Boehnlein, Benjamin Lozes, Pal Andras Papp, Raphael S. Steiner
*/

#pragma once

#include <iostream>

namespace osp {

enum class RETURN_STATUS { OSP_SUCCESS,
BEST_FOUND,
TIMEOUT,
ERROR };

/**
* @brief Converts the enum to a string literal.
* Returns const char* to avoid std::string allocation overhead.
*/
inline const char *to_string(const RETURN_STATUS status) {
switch (status) {
case RETURN_STATUS::OSP_SUCCESS:
return "SUCCESS";
case RETURN_STATUS::BEST_FOUND:
return "BEST FOUND";
case RETURN_STATUS::TIMEOUT:
return "TIMEOUT";
case RETURN_STATUS::ERROR:
return "ERROR";
default:
return "UNKNOWN";
}
}

/**
* @brief Stream operator overload using the helper function.
*/
inline std::ostream &operator<<(std::ostream &os, RETURN_STATUS status) {
return os << to_string(status);
}

} // namespace osp
122 changes: 38 additions & 84 deletions include/osp/bsp/model/BspArchitecture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,12 @@ inline std::ostream &operator<<(std::ostream &os, MEMORY_CONSTRAINT_TYPE type) {
* bounds. It provides methods to set and retrieve these values.
*
* **Processors:**
* The architecture consists of p processors, indexed from 0 to p-1.
* The architecture consists of p processors, indexed from 0 to p-1. Note that processor indices are represented using `unsigned`.
*
* **Processor Types:**
* Processors can have different types, which are represented by non-negative integers.
* Processor types are assumed to be consecutive integers starting from 0.
* Processor types are assumed to be consecutive integers starting from 0. Note that processor types are represented using `unsigned`.
* Processor types are used to express compatabilities, which can be specified in the BspInstance, regarding node types.
*
* **Communication and Synchronization Costs:**
* - Communication Cost (g): The cost of communicating a unit of data between processors, i.e., the bandwidth.
Expand Down Expand Up @@ -185,46 +186,53 @@ class BspArchitecture {
}

public:
/**
* @brief Default constructor.
* Initializes a BSP architecture with 2 processors, 1 processor type,
* communication costs of 1, synchronisation costs of 2, memory bounds of 100,
* and send costs of 1 between all processors.
*/
BspArchitecture()
: numberOfProcessors_(2U), numberOfProcessorTypes_(1U), communicationCosts_(1U), synchronisationCosts_(2U),
memoryBound_(numberOfProcessors_, 100U), isNuma_(false),
processorTypes_(numberOfProcessors_, 0U), sendCosts_(numberOfProcessors_ * numberOfProcessors_, 1U) {
SetSendCostDiagonalToZero();
}

BspArchitecture(const BspArchitecture &other) = default;
BspArchitecture(BspArchitecture &&other) noexcept = default;
BspArchitecture &operator=(const BspArchitecture &other) = default;
BspArchitecture &operator=(BspArchitecture &&other) noexcept = default;
virtual ~BspArchitecture() = default;

/**
* @brief Constructs a BspArchitecture object with the specified number of processors, communication cost, and
* synchronization cost.
*
* @param NumberOfProcessors The number of processors in the architecture. Must be greater than 0.
* @param CommunicationCost The communication cost between processors.
* @param SynchronisationCost The synchronization cost between processors.
* @param NumberOfProcessors The number of processors in the architecture. Must be greater than 0. Default: 2.
* @param CommunicationCost The communication cost between processors. Default: 1.
* @param SynchronisationCost The synchronization cost between processors. Default: 2.
* @param MemoryBound The memory bound for each processor (default: 100).
* @param SendCosts The matrix of send costs between processors. Needs to be a processors x processors matrix. Diagonal entries are forced to zero. Default: empty (uniform costs).
*/
BspArchitecture(const unsigned NumberOfProcessors, const v_commw_t<Graph_t> CommunicationCost, const v_commw_t<Graph_t> SynchronisationCost,
const v_memw_t<Graph_t> MemoryBound = 100U)
BspArchitecture(const unsigned NumberOfProcessors = 2U, const v_commw_t<Graph_t> CommunicationCost = 1U, const v_commw_t<Graph_t> SynchronisationCost = 2U,
const v_memw_t<Graph_t> MemoryBound = 100U, const std::vector<std::vector<v_commw_t<Graph_t>>> &SendCosts = {})
: numberOfProcessors_(NumberOfProcessors), numberOfProcessorTypes_(1U), communicationCosts_(CommunicationCost),
synchronisationCosts_(SynchronisationCost),
memoryBound_(NumberOfProcessors, MemoryBound), isNuma_(false),
processorTypes_(NumberOfProcessors, 0U), sendCosts_(NumberOfProcessors * NumberOfProcessors, 1U) {
processorTypes_(NumberOfProcessors, 0U) {
if (NumberOfProcessors == 0U) {
throw std::runtime_error("BspArchitecture: Number of processors must be greater than 0.");
}
SetSendCostDiagonalToZero();

if (SendCosts.empty()) {
InitializeUniformSendCosts();
} else {
if (NumberOfProcessors != SendCosts.size()) {
throw std::invalid_argument("sendCosts_ needs to be a processors x processors matrix.\n");
}
if (std::any_of(SendCosts.begin(), SendCosts.end(),
[NumberOfProcessors](const auto &thing) { return thing.size() != NumberOfProcessors; })) {
throw std::invalid_argument("sendCosts_ needs to be a processors x processors matrix.\n");
}

sendCosts_.reserve(NumberOfProcessors * NumberOfProcessors);
for (const auto &row : SendCosts) {
sendCosts_.insert(sendCosts_.end(), row.begin(), row.end());
}

SetSendCostDiagonalToZero();
isNuma_ = AreSendCostsNuma();
}
}

BspArchitecture(const BspArchitecture &other) = default;
BspArchitecture(BspArchitecture &&other) noexcept = default;
BspArchitecture &operator=(const BspArchitecture &other) = default;
BspArchitecture &operator=(BspArchitecture &&other) noexcept = default;
virtual ~BspArchitecture() = default;

/**
* @brief Copy constructor from a BspArchitecture with a different graph type.
*
Expand Down Expand Up @@ -258,62 +266,7 @@ class BspArchitecture {
*/
BspArchitecture(const unsigned NumberOfProcessors, const v_commw_t<Graph_t> CommunicationCost, const v_commw_t<Graph_t> SynchronisationCost,
const std::vector<std::vector<v_commw_t<Graph_t>>> &SendCosts)
: numberOfProcessors_(NumberOfProcessors), numberOfProcessorTypes_(1U), communicationCosts_(CommunicationCost),
synchronisationCosts_(SynchronisationCost), memoryBound_(NumberOfProcessors, 100U),
processorTypes_(NumberOfProcessors, 0U) {
if (NumberOfProcessors == 0U) {
throw std::runtime_error("BspArchitecture: Number of processors must be greater than 0.");
}
if (NumberOfProcessors != SendCosts.size()) {
throw std::invalid_argument("sendCosts_ needs to be a processors x processors matrix.\n");
}
if (std::any_of(SendCosts.begin(), SendCosts.end(),
[NumberOfProcessors](const auto &thing) { return thing.size() != NumberOfProcessors; })) {
throw std::invalid_argument("sendCosts_ needs to be a processors x processors matrix.\n");
}

sendCosts_.reserve(NumberOfProcessors * NumberOfProcessors);
for (const auto &row : SendCosts) {
sendCosts_.insert(sendCosts_.end(), row.begin(), row.end());
}

SetSendCostDiagonalToZero();
isNuma_ = AreSendCostsNuma();
}

/**
* @brief Constructs a BspArchitecture object with custom send costs and memory bound.
*
* @param NumberOfProcessors The number of processors. Must be greater than 0.
* @param CommunicationCost The communication cost.
* @param SynchronisationCost The synchronization cost.
* @param MemoryBound The memory bound for each processor.
* @param SendCosts The matrix of send costs between processors. Needs to be a processors x processors matrix. Diagonal entries are forced to zero.
*/
BspArchitecture(const unsigned NumberOfProcessors, const v_commw_t<Graph_t> CommunicationCost, const v_commw_t<Graph_t> SynchronisationCost,
const v_memw_t<Graph_t> MemoryBound, const std::vector<std::vector<v_commw_t<Graph_t>>> &SendCosts)
: numberOfProcessors_(NumberOfProcessors), numberOfProcessorTypes_(1U), communicationCosts_(CommunicationCost),
synchronisationCosts_(SynchronisationCost), memoryBound_(NumberOfProcessors, MemoryBound),
processorTypes_(NumberOfProcessors, 0U) {
if (NumberOfProcessors == 0U) {
throw std::runtime_error("BspArchitecture: Number of processors must be greater than 0.");
}
if (NumberOfProcessors != SendCosts.size()) {
throw std::invalid_argument("sendCosts_ needs to be a processors x processors matrix.\n");
}
if (std::any_of(SendCosts.begin(), SendCosts.end(),
[NumberOfProcessors](const auto &thing) { return thing.size() != NumberOfProcessors; })) {
throw std::invalid_argument("sendCosts_ needs to be a processors x processors matrix.\n");
}

sendCosts_.reserve(NumberOfProcessors * NumberOfProcessors);
for (const auto &row : SendCosts) {
sendCosts_.insert(sendCosts_.end(), row.begin(), row.end());
}

SetSendCostDiagonalToZero();
isNuma_ = AreSendCostsNuma();
}
: BspArchitecture(NumberOfProcessors, CommunicationCost, SynchronisationCost, 100U, SendCosts) {}

/**
* @brief Sets the uniform send cost for each pair of processors.
Expand Down Expand Up @@ -636,6 +589,7 @@ class BspArchitecture {

/**
* @brief Returns the send costs between two processors. Does not perform bounds checking.
* Does not the communication costs into account.
*
* @param p1 The index of the first processor.
* @param p2 The index of the second processor.
Expand Down
Loading