PLSSVM - Parallel Least Squares Support Vector Machine  2.0.0
A Least Squares Support Vector Machine implementation using different backends.
layout.hpp
Go to the documentation of this file.
1 
12 #ifndef PLSSVM_DETAIL_LAYOUT_HPP_
13 #define PLSSVM_DETAIL_LAYOUT_HPP_
14 #pragma once
15 
16 #include "plssvm/detail/assert.hpp" // PLSSVM_ASSERT, PLSSVM_ASSERT_ENABLED
17 #include "plssvm/detail/logger.hpp" // plssvm::detail::log, plssvm::verbosity_level
18 #include "plssvm/detail/performance_tracker.hpp" // plssvm::detail::tracking_entry
19 
20 #include "fmt/chrono.h" // format std::chrono types
21 #include "fmt/core.h" // fmt::format
22 #include "fmt/ostream.h" // format types with a user defined operator<<
23 
24 #include <algorithm> // std::all_of
25 #include <chrono> // std::chrono::{time_point, steady_clock, duration_cast}
26 #include <cstddef> // std::size_t
27 #include <iosfwd> // forward declare std::ostream and std::istream
28 #include <iostream> // std::cout, std::endl
29 #include <vector> // std::vector
30 
31 namespace plssvm::detail {
32 
36 enum class layout_type {
38  aos,
40  soa
41 };
42 
49 std::ostream &operator<<(std::ostream &out, layout_type layout);
50 
57 std::istream &operator>>(std::istream &in, layout_type &layout);
58 
69 template <typename real_type>
70 [[nodiscard]] inline std::vector<real_type> transform_to_aos_layout(const std::vector<std::vector<real_type>> &matrix, const std::size_t boundary_size, const std::size_t num_points, const std::size_t num_features) {
71  std::vector<real_type> vec(num_points * (num_features + boundary_size));
72 
73  #pragma omp parallel for collapse(2) default(none) shared(vec, matrix) firstprivate(num_features, num_points, boundary_size)
74  for (std::size_t row = 0; row < num_points; ++row) {
75  for (std::size_t col = 0; col < num_features; ++col) {
76  vec[row * (num_features + boundary_size) + col] = matrix[row][col];
77  }
78  }
79 
80  return vec;
81 }
82 
93 template <typename real_type>
94 [[nodiscard]] inline std::vector<real_type> transform_to_soa_layout(const std::vector<std::vector<real_type>> &matrix, const std::size_t boundary_size, const std::size_t num_points, const std::size_t num_features) {
95  std::vector<real_type> vec(num_features * (num_points + boundary_size));
96 
97  #pragma omp parallel for collapse(2) default(none) shared(vec, matrix) firstprivate(num_features, num_points, boundary_size)
98  for (std::size_t col = 0; col < num_features; ++col) {
99  for (std::size_t row = 0; row < num_points; ++row) {
100  vec[col * (num_points + boundary_size) + row] = matrix[row][col];
101  }
102  }
103 
104  return vec;
105 }
106 
117 template <typename real_type>
118 [[nodiscard]] inline std::vector<real_type> transform_to_layout(const layout_type layout, const std::vector<std::vector<real_type>> &matrix, const std::size_t boundary_size, const std::size_t num_points) {
119  // perform some sanity checks
120  PLSSVM_ASSERT(!matrix.empty(), "Matrix is empty!");
121  PLSSVM_ASSERT(num_points <= matrix.size(), "Number of data points to transform can not exceed matrix size!");
122  const typename std::vector<real_type>::size_type num_features = matrix.front().size();
123 #if defined(PLSSVM_ASSERT_ENABLED)
124  const bool has_same_num_features = std::all_of(matrix.begin(), matrix.end(), [=](const std::vector<real_type> &point) { return point.size() == num_features; });
125  PLSSVM_ASSERT(has_same_num_features, "Feature sizes mismatch! All features should have size {}.", num_features);
126  PLSSVM_ASSERT(num_features > 0, "All features are empty!");
127 #endif
128 
129  const std::chrono::time_point start_time = std::chrono::steady_clock::now();
130 
131  std::vector<real_type> ret;
132 
133  switch (layout) {
134  case layout_type::aos:
135  ret = transform_to_aos_layout(matrix, boundary_size, num_points, num_features);
136  break;
137  case layout_type::soa:
138  ret = transform_to_soa_layout(matrix, boundary_size, num_points, num_features);
139  break;
140  }
141 
142  const std::chrono::time_point end_time = std::chrono::steady_clock::now();
144  "Transformed {}x{} dataset from 2D to 1D {} in {}.\n",
145  detail::tracking_entry{ "transform", "num_data_points", num_points },
146  detail::tracking_entry{ "transform", "num_features", num_features },
147  detail::tracking_entry{ "transform", "layout", layout },
148  detail::tracking_entry{ "transform", "time", std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time) });
149 
150  return ret;
151 }
152 
153 } // namespace plssvm::detail
154 
155 #endif // PLSSVM_DETAIL_LAYOUT_HPP_
Implements a custom assert macro PLSSVM_ASSERT.
#define PLSSVM_ASSERT(cond, msg,...)
Defines the PLSSVM_ASSERT macro if PLSSVM_ASSERT_ENABLED is defined.
Definition: assert.hpp:74
Defines a simple logging function.
Namespace containing implementation details. Should not directly be used by users.
Definition: csvm.hpp:27
void log(const verbosity_level verb, const std::string_view msg, Args &&...args)
Definition: logger.hpp:109
std::vector< real_type > transform_to_soa_layout(const std::vector< std::vector< real_type >> &matrix, const std::size_t boundary_size, const std::size_t num_points, const std::size_t num_features)
Convert a 2D matrix into a 1D array in Struct-of-Arrays layout adding boundary_size values per featur...
Definition: layout.hpp:94
std::ostream & operator<<(std::ostream &out, const execution_range &range)
Output the execution range to the given output-stream out.
std::vector< real_type > transform_to_layout(const layout_type layout, const std::vector< std::vector< real_type >> &matrix, const std::size_t boundary_size, const std::size_t num_points)
Convert a 2D matrix into a 1D array in the layout adding boundary_size values per data point or featu...
Definition: layout.hpp:118
layout_type
Enum class for all available layout types.
Definition: layout.hpp:36
std::vector< real_type > transform_to_aos_layout(const std::vector< std::vector< real_type >> &matrix, const std::size_t boundary_size, const std::size_t num_points, const std::size_t num_features)
Convert a 2D matrix into a 1D array in Array-of-Structs layout adding boundary_size values per data p...
Definition: layout.hpp:70
std::istream & operator>>(std::istream &in, layout_type &layout)
Use the input-stream in to initialize the layout type.
Defines a performance tracker which can dump performance information in a YAML file.
A single tracking entry containing a specific category, a unique name, and the actual value to be tra...
Definition: performance_tracker.hpp:40