Skip to content
95 changes: 95 additions & 0 deletions include/parallelzone/hardware/cpu/cpu.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright 2025 NWChemEx-Project
*
* 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.
*/

#pragma once
#include <chrono>
#include <parallelzone/task/task_wrapper.hpp>

namespace parallelzone::hardware {

/** @brief Aggregates known profiling information.
*
* The class is primarily intended to ensure that `profile_it` can maintain a
* consistent API as new profiling information is added, i.e.,
* `ProfileInformation` is intended to be an opaque type whose content can
* grow over time.
*/
struct ProfileInformation {
/// Type used to measure time durations
using duration = std::chrono::high_resolution_clock::duration;

/// Long the function ran for
duration wall_time;
};

/** @brief Class representing a central processing unit (CPU).
*
* This class is intended to be a runtime interface for interacting with the
* CPU. Right now it can be used to profile a task run on a CPU.
*/
class CPU {
private:
/// Type used internally for wrapping tasks
using task_type = task::TaskWrapper;

/// Type used internally for returning type-erased results
using result_type = typename task_type::type_erased_return_type;

public:
/// Type containing profiling information
using profile_information = ProfileInformation;

/** @brief Profiles a function.
*
* @tparam FxnType The type of the callable to profile.
* @tparam Args The types of the arguments to forward to the callable.
*
* @param[in] fxn The callable to run.
* @param[in] args The arguments to forward to the callable.
*
* @return A pair whose first element is the return of your callable and
* the second element is the profiling information obtained from
* running the callable. If your function does not have a return
* only the profiling info is returned.
*
* @throw ??? Throws if the callable throws. Same throw guarantee.
*/
template<typename FxnType, typename... Args>
auto profile_it(FxnType&& fxn, Args&&... args) const {
auto&& [t, unwrapper] = task::make_task(std::forward<FxnType>(fxn),
std::forward<Args>(args)...);
auto result = profile_it_(std::move(t));

using result_type = decltype(unwrapper(std::move(result.first)));

if constexpr(std::is_same_v<result_type, void>) {
return std::move(result.second);
} else {
auto unwrapped_result = unwrapper(std::move(result.first));
return std::make_pair(std::move(unwrapped_result),
std::move(result.second));
}
}

private:
/// How the type-erased profile_it_ method returns its results
using profile_return_type = std::pair<result_type, profile_information>;

/// Returns the result of the task and the profiling information obtained
profile_return_type profile_it_(task_type&& task) const;
};

} // namespace parallelzone::hardware
19 changes: 19 additions & 0 deletions include/parallelzone/hardware/hardware.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright 2025 NWChemEx-Project
*
* 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.
*/

#pragma once
#include <parallelzone/hardware/cpu/cpu.hpp>
#include <parallelzone/hardware/ram/ram.hpp>
19 changes: 19 additions & 0 deletions include/parallelzone/logging/logging.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright 2025 NWChemEx-Project
*
* 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.
*/

#pragma once
#include <parallelzone/logging/logger.hpp>
#include <parallelzone/logging/logger_factory.hpp>
5 changes: 4 additions & 1 deletion include/parallelzone/parallelzone.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
* library.
*/

#include "parallelzone/serialization.hpp"
#include <parallelzone/hardware/hardware.hpp>
#include <parallelzone/logging/logging.hpp>
#include <parallelzone/runtime/runtime.hpp>
#include <parallelzone/serialization.hpp>
#include <parallelzone/task/task.hpp>

namespace parallelzone {} // namespace parallelzone
69 changes: 69 additions & 0 deletions include/parallelzone/task/argument_traits.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright 2025 NWChemEx-Project
*
* 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.
*/

#pragma once
#include <type_traits>

namespace parallelzone::task {

/** @brief Structure that works out cv-qualifiers and reference-ness of @p T.
*
* @tparam The type being inspected.
*
* This structure is predominantly intended for use in template contexts where
* the properties of a type are not known. In those contexts, it can be
* useful to know if a type @p T is a reference, a const reference etc.
*/
template<typename T>
struct ArgumentTraits {
/// Type of @p T w/o reference and cv-qualifiers
using value_type = std::decay_t<T>;

/// Type of a mutable reference to an object of type @p value_type
using reference = value_type&;

/// Type of a read-only reference to an object of type @p value_type
using const_reference = const value_type&;

/// Type of an rvalue reference to an object of type @p value_type
using rvalue_reference = value_type&&;

/// Type of a pointer to an object of type @p value_type
using pointer = value_type*;

/// Type of a pointer to a read-only object of type @p value_type
using const_pointer = const value_type*;

/// Is @p T consistent with being passed by value?
static constexpr bool is_value_v = std::is_same_v<value_type, T>;

/// Is @p T consistent with being passed as a const value?
static constexpr bool is_const_value_v =
std::is_same_v<const value_type, T>;

/// Is @p T consistent with being passed by reference?
static constexpr bool is_reference_v = std::is_same_v<reference, T>;

/// Is @p T consistent with being passed by const reference?
static constexpr bool is_const_reference_v =
std::is_same_v<const_reference, T>;

/// Is @p T consistent with being passed by rvalue reference?
static constexpr bool is_rvalue_reference_v =
std::is_same_v<rvalue_reference, T>;
};

} // namespace parallelzone::task
127 changes: 127 additions & 0 deletions include/parallelzone/task/argument_wrapper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright 2025 NWChemEx-Project
*
* 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.
*/

#pragma once
#include <parallelzone/task/argument_traits.hpp>

namespace parallelzone::task {

/** @brief Class to help forward arguments for generic functions.
*
* @tparam The type of the object *this will wrap.
*
* Depending on how the user passes an argument to a function, the function
* will own the value or alias it. ParallelZone is designed to generically
* interact with functions and in turn will need to capture arguments. When
* PZ captures an argument it will need to prolong the lifetime if the user
* passed the argument by value or rvalue reference, and maintain the aliasing
* if the user passed the argument by reference.
*
* The ArgumentWrapper class handles the logic of potentially prolonging the
* lifetime of the argument, while providing a consistent API regardless of
* whether or not it is owning or aliasing the argument.
*/
template<typename T>
class ArgumentWrapper {
private:
/// Is @p U the same type as *this?
template<typename U>
static constexpr bool is_arg_wrapper_v =
std::is_same_v<ArgumentWrapper<T>, U>;

/// Disables a template function if @p U is the same type as *this
template<typename U>
using disable_if_arg_wrapper = std::enable_if_t<!is_arg_wrapper_v<U>>;

public:
/// Type traits of @p T needed for TMP
using traits_t = ArgumentTraits<T>;

/// Unqualified type of @p T
using value_type = typename traits_t::value_type;

/// Type of a mutable reference to an object of type @p value_type
using reference = typename traits_t::reference;

/// Type of a read-only reference to an object of type @p value_type
using const_reference = typename traits_t::const_reference;

/** @brief Creates a new object which wraps @p object.
*
* @tparam U The type of object must be implicitly convertible to @p T.
* @tparam <anonymous> Used to disable this ctor via SFINAE if @p U is
* an object of type ArgumentWrapper.
*
* The value ctor wraps the provided argument, automatically prolonging
* its lifetime if needed (needed when @p T is a value or rvalue
* reference). If an extended lifetime is not needed, @p object will be
* aliased and the user is responsible for ensuring @p object is alive
* for the duration of *this.
*
* @param object The value *this is wrapping.
*
* @throw None No throw guarantee.
*/
template<typename U, typename = disable_if_arg_wrapper<std::decay_t<U>>>
explicit ArgumentWrapper(U&& object) : m_value_(std::forward<U>(object)) {}

/** @brief Provides potentially mutable access to the value.
*
* This method is used to access the value. The result will be mutable if
* @p T is not const-qualified and read-only if @p T is const-qualified.
*
* @return A reference to the wrapped value.
*
* @throw None No throw guarantee.
*/
auto& value() { return m_value_; }

/** @brief Provides read-only access to the value.
*
* This method is identical to the non-const version except that the result
* is guarantee to be read-only.
*
* @return A read-only reference to the wrapped value.
*
* @throw None No throw guarantee.
*/
const auto& value() const { return m_value_; }

private:
/// Hold by value?
static constexpr bool hold_by_value =
traits_t::is_value_v || traits_t::is_rvalue_reference_v;

/// Hold by reference?
static constexpr bool hold_by_reference = traits_t::is_reference_v;

/// Hold by const reference?
static constexpr bool hold_by_const_reference =
traits_t::is_const_reference_v;

/// Type, if being held by reference
using reference_holder =
std::conditional_t<hold_by_reference, reference, const_reference>;

/// Works out the type of the holder
using holder_type =
std::conditional_t<hold_by_value, value_type, reference_holder>;

/// The actual value being held.
holder_type m_value_;
};

} // namespace parallelzone::task
Loading