From d800adcfdddbc6283a830288babe78a59a3ae079 Mon Sep 17 00:00:00 2001 From: Bruno Donassolo Date: Tue, 13 Jul 2021 17:28:07 +0200 Subject: [PATCH] Host: non-linear constraints Allows the use of non-linear constraints for CPU resources. Add API in s4u::Host::set_sharing_policy - LINEAR(default, shared resources) or NONLINEAR Example: examples/cpp/exec-cpu-nonlinear --- MANIFEST.in | 2 + examples/cpp/CMakeLists.txt | 2 +- .../s4u-exec-cpu-nonlinear.cpp | 72 +++++++++++++++++++ .../s4u-exec-cpu-nonlinear.tesh | 5 ++ include/simgrid/s4u/Host.hpp | 10 +++ src/s4u/s4u_Host.cpp | 11 +++ src/surf/cpu_interface.cpp | 26 +++++++ src/surf/cpu_interface.hpp | 7 ++ 8 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 examples/cpp/exec-cpu-nonlinear/s4u-exec-cpu-nonlinear.cpp create mode 100644 examples/cpp/exec-cpu-nonlinear/s4u-exec-cpu-nonlinear.tesh diff --git a/MANIFEST.in b/MANIFEST.in index c7e3c41dff..9b183bfde7 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -234,6 +234,8 @@ include examples/cpp/exec-async/s4u-exec-async.cpp include examples/cpp/exec-async/s4u-exec-async.tesh include examples/cpp/exec-basic/s4u-exec-basic.cpp include examples/cpp/exec-basic/s4u-exec-basic.tesh +include examples/cpp/exec-cpu-nonlinear/s4u-exec-cpu-nonlinear.cpp +include examples/cpp/exec-cpu-nonlinear/s4u-exec-cpu-nonlinear.tesh include examples/cpp/exec-dependent/s4u-exec-dependent.cpp include examples/cpp/exec-dependent/s4u-exec-dependent.tesh include examples/cpp/exec-dvfs/s4u-exec-dvfs.cpp diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt index 94c2f8f636..ac25009336 100644 --- a/examples/cpp/CMakeLists.txt +++ b/examples/cpp/CMakeLists.txt @@ -70,7 +70,7 @@ foreach (example actor-create actor-daemon actor-exiting actor-join actor-kill energy-exec energy-boot energy-link energy-vm energy-exec-ptask energy-wifi engine-filtering exec-async exec-basic exec-dvfs exec-remote exec-waitany exec-waitfor exec-dependent exec-unassigned - exec-ptask-multicore + exec-ptask-multicore exec-cpu-nonlinear maestro-set mc-bugged1 mc-bugged2 mc-electric-fence mc-failing-assert network-wifi diff --git a/examples/cpp/exec-cpu-nonlinear/s4u-exec-cpu-nonlinear.cpp b/examples/cpp/exec-cpu-nonlinear/s4u-exec-cpu-nonlinear.cpp new file mode 100644 index 0000000000..9331ef981c --- /dev/null +++ b/examples/cpp/exec-cpu-nonlinear/s4u-exec-cpu-nonlinear.cpp @@ -0,0 +1,72 @@ +/* Copyright (c) 2010-2021. The SimGrid Team. All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +/* This example shows how to simulate a non-linear resource sharing for + * CPUs. + */ + +#include + +namespace sg4 = simgrid::s4u; + +XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_network_nonlinear, "Messages specific for this s4u example"); + +/*************************************************************************************************/ +static void runner() +{ + double computation_amount = sg4::this_actor::get_host()->get_speed(); + int n_task = 10; + std::vector tasks; + + XBT_INFO( + "Execute %d tasks of %g flops, should take %d second in a CPU without degradation. It will take the double here.", + n_task, computation_amount, n_task); + for (int i = 0; i < n_task; i++) { + tasks.emplace_back(sg4::this_actor::exec_async(computation_amount)); + } + XBT_INFO("Waiting for all tasks to be done!"); + for (auto& task : tasks) + task->wait(); + + XBT_INFO("Finished executing. Goodbye now!"); +} +/*************************************************************************************************/ +/** @brief Non-linear resource sharing for CPU */ +static double cpu_nonlinear(const sg4::Host* host, double capacity, int n) +{ + /* emulates a degradation in link according to the number of flows + * totally unrealistic but for learning purposes */ + capacity = n > 1 ? capacity / 2 : capacity; + XBT_INFO("Host %s, %d concurrent tasks, new capacity %lf", host->get_cname(), n, capacity); + return capacity; +} + +/** @brief Create a simple 1-host platform */ +static void load_platform() +{ + auto* zone = sg4::create_empty_zone("Zone1"); + auto* runner_host = zone->create_host("runner", 1e6); + runner_host->set_sharing_policy(sg4::Host::SharingPolicy::NONLINEAR, + std::bind(&cpu_nonlinear, runner_host, std::placeholders::_1, std::placeholders::_2)); + runner_host->seal(); + zone->seal(); + + /* create actor runner */ + sg4::Actor::create("runner", runner_host, runner); +} + +/*************************************************************************************************/ +int main(int argc, char* argv[]) +{ + sg4::Engine e(&argc, argv); + + /* create platform */ + load_platform(); + + /* runs the simulation */ + e.run(); + + return 0; +} diff --git a/examples/cpp/exec-cpu-nonlinear/s4u-exec-cpu-nonlinear.tesh b/examples/cpp/exec-cpu-nonlinear/s4u-exec-cpu-nonlinear.tesh new file mode 100644 index 0000000000..33f529e53b --- /dev/null +++ b/examples/cpp/exec-cpu-nonlinear/s4u-exec-cpu-nonlinear.tesh @@ -0,0 +1,5 @@ +$ ${bindir:=.}/s4u-exec-cpu-nonlinear "--log=root.fmt:[%10.6r]%e(%i:%a@%h)%e%m%n" +> [ 0.000000] (1:runner@runner) Execute 10 tasks of 1e+06 flops, should take 10 second in a CPU without degradation. It will take the double here. +> [ 0.000000] (1:runner@runner) Waiting for all tasks to be done! +> [ 0.000000] (0:maestro@) Host runner, 10 concurrent tasks, new capacity 500000.000000 +> [ 20.000000] (1:runner@runner) Finished executing. Goodbye now! diff --git a/include/simgrid/s4u/Host.hpp b/include/simgrid/s4u/Host.hpp index c39588fda3..42807933a0 100644 --- a/include/simgrid/s4u/Host.hpp +++ b/include/simgrid/s4u/Host.hpp @@ -157,6 +157,16 @@ public: int get_core_count() const; Host* set_core_count(int core_count); + enum class SharingPolicy { NONLINEAR = 1, LINEAR = 0 }; + /** + * @brief Describes how the CPU is shared between concurrent tasks + * + * @param policy Sharing policy + * @param cb Callback for NONLINEAR policies + */ + Host* set_sharing_policy(SharingPolicy policy, const s4u::NonLinearResourceCb& cb = {}); + SharingPolicy get_sharing_policy() const; + /** Returns the current computation load (in flops per second) * * The external load (coming from an availability trace) is not taken in account. diff --git a/src/s4u/s4u_Host.cpp b/src/s4u/s4u_Host.cpp index c06d170844..575dfad6ba 100644 --- a/src/s4u/s4u_Host.cpp +++ b/src/s4u/s4u_Host.cpp @@ -264,6 +264,17 @@ double Host::get_available_speed() const return this->pimpl_cpu_->get_speed_ratio(); } +Host* Host::set_sharing_policy(SharingPolicy policy, const s4u::NonLinearResourceCb& cb) +{ + kernel::actor::simcall([this, policy, &cb] { pimpl_cpu_->set_sharing_policy(policy, cb); }); + return this; +} + +Host::SharingPolicy Host::get_sharing_policy() const +{ + return this->pimpl_cpu_->get_sharing_policy(); +} + int Host::get_core_count() const { return this->pimpl_cpu_->get_core_count(); diff --git a/src/surf/cpu_interface.cpp b/src/surf/cpu_interface.cpp index ec58d4aac2..f6eeaa0f76 100644 --- a/src/surf/cpu_interface.cpp +++ b/src/surf/cpu_interface.cpp @@ -113,6 +113,31 @@ CpuImpl* CpuImpl::set_core_count(int core_count) return this; } +void CpuImpl::apply_sharing_policy_cfg() const +{ + if (!get_constraint()) + return; + + kernel::lmm::Constraint::SharingPolicy lmm_policy = kernel::lmm::Constraint::SharingPolicy::SHARED; + if (sharing_policy_ == s4u::Host::SharingPolicy::NONLINEAR) + lmm_policy = kernel::lmm::Constraint::SharingPolicy::NONLINEAR; + + get_constraint()->set_sharing_policy(lmm_policy, sharing_policy_cb_); +} + +void CpuImpl::set_sharing_policy(s4u::Host::SharingPolicy policy, const s4u::NonLinearResourceCb& cb) +{ + xbt_assert(dynamic_cast(get_model()) == nullptr, "Cannot change sharing policy with CPU:TI model"); + sharing_policy_ = policy; + sharing_policy_cb_ = cb; + apply_sharing_policy_cfg(); +} + +s4u::Host::SharingPolicy CpuImpl::get_sharing_policy() const +{ + return sharing_policy_; +} + int CpuImpl::get_core_count() { return core_count_; @@ -135,6 +160,7 @@ void CpuImpl::seal() lmm::System* lmm = get_model()->get_maxmin_system(); if (dynamic_cast(get_model()) == nullptr) this->set_constraint(lmm->constraint_new(this, core_count_ * speed_per_pstate_.front())); + apply_sharing_policy_cfg(); Resource::seal(); } diff --git a/src/surf/cpu_interface.hpp b/src/surf/cpu_interface.hpp index cb672bef21..3abfd85437 100644 --- a/src/surf/cpu_interface.hpp +++ b/src/surf/cpu_interface.hpp @@ -56,6 +56,10 @@ class XBT_PUBLIC CpuImpl : public Resource_T { int pstate_ = 0; /*< Current pstate (index in the speed_per_pstate_)*/ std::vector speed_per_pstate_; /*< List of supported CPU capacities (pstate related). Not 'const' because VCPU get modified on migration */ + s4u::Host::SharingPolicy sharing_policy_ = s4u::Host::SharingPolicy::LINEAR; + s4u::NonLinearResourceCb sharing_policy_cb_; + + void apply_sharing_policy_cfg() const; public: /** @@ -112,6 +116,9 @@ public: */ CpuImpl* set_pstate_speed(const std::vector& speed_per_state); + void set_sharing_policy(s4u::Host::SharingPolicy policy, const s4u::NonLinearResourceCb& cb); + s4u::Host::SharingPolicy get_sharing_policy() const; + /** * @brief Execute some quantity of computation * -- 2.20.1