Commit ef8a061a authored by Bruno Donassolo's avatar Bruno Donassolo
Browse files

Modeling hints: I/O operations

Adds an example showing how to model I/O operation in SimGrid.
It uses data from real experiments on Grid'5000 to model the impact of
concurrent operation on disks and the variability/noise in single I/O
operations.

Adds an entry in the doc presenting the results.
The code is available at: docs/source/tuto_disk.

The rst file was generated from the analysis.org file.
The folder includes a dockerfile to rerun the experiment if needed.
parent bd1d252d
Pipeline #436769 passed with stages
in 17 minutes and 26 seconds
......@@ -1868,6 +1868,18 @@ include docs/source/img/zoom_comm.drawio
include docs/source/img/zoom_comm.svg
include docs/source/index.rst
include docs/source/intl.rst
include docs/source/tuto_disk/CMakeLists.txt
include docs/source/tuto_disk/Dockerfile
include docs/source/tuto_disk/analysis.org
include docs/source/tuto_disk/analysis.rst
include docs/source/tuto_disk/fig/edel_read_dhist.png
include docs/source/tuto_disk/fig/edel_write_dhist.png
include docs/source/tuto_disk/fig/griffon_deg.png
include docs/source/tuto_disk/fig/griffon_read_dhist.png
include docs/source/tuto_disk/fig/griffon_write_dhist.png
include docs/source/tuto_disk/fig/simgrid_results.png
include docs/source/tuto_disk/init.el
include docs/source/tuto_disk/tuto_disk.cpp
include docs/source/tuto_s4u/deployment1.xml
include docs/source/tuto_s4u/deployment2.xml
include docs/source/tuto_s4u/deployment3.xml
......
......@@ -12,8 +12,8 @@
.. _platform_examples:
Platform Examples
=================
Network Topology Examples
=========================
Simple Example with 3 hosts
---------------------------
......
......@@ -288,3 +288,8 @@ So the final platform for our example becomes :
<link_ctn id="link2"/>
</route>
:ref:`Modeling I/O: the realistic way<howto_disk>`
*****************
Tutorial available at: :ref:`howto_disk`.
......@@ -75,7 +75,7 @@ of every page. Bugs in the code should be reported
   The XBT toolbox <The_XBT_toolbox.rst>
Describing the simulated platform <Platform.rst>
   Demystifying the routing <Platform_routing.rst>
   Examples <Platform_examples.rst>
   Network topology examples <Platform_examples.rst>
   Modeling hints <Platform_howtos.rst>
   XML reference <XML_reference.rst>
   C++ platforms <Platform_cpp.rst>
......
cmake_minimum_required(VERSION 2.8.8)
project(tuto_disk)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/" "../../../")
find_package(SimGrid REQUIRED)
include_directories(${SimGrid_INCLUDE_DIR})
set(SIMULATOR_SOURCES tuto_disk.cpp)
add_executable(tuto_disk ${SIMULATOR_SOURCES})
target_link_libraries(tuto_disk ${SimGrid_LIBRARY})
FROM debian:10.10-slim
RUN echo " \
deb [check-valid-until=no, trusted=yes] http://snapshot.debian.org/archive/debian/20210707T150931Z/ buster main contrib non-free \n\
deb-src [check-valid-until=no, trusted=yes] http://snapshot.debian.org/archive/debian/20210707T150931Z/ buster main contrib non-free \n\
deb [check-valid-until=no, trusted=yes] http://snapshot.debian.org/archive/debian-security/20210707T150931Z/ buster/updates main contrib non-free \n\
deb-src [check-valid-until=no, trusted=yes] http://snapshot.debian.org/archive/debian-security/20210707T150931Z/ buster/updates main contrib non-free" > /etc/apt/sources.list
RUN apt-get -o Acquire::Check-Valid-Until=false update;
# emacs
RUN apt-get install -y \
emacs \
ess \
elpa-htmlize
# R
RUN apt-get install -y \
r-base-core \
r-cran-ggplot2 \
r-cran-dplyr \
r-cran-plyr \
r-cran-jsonlite \
r-cran-gridextra
# simgrid dependencies
RUN apt install -y \
g++ \
gcc \
git \
valgrind \
gfortran \
libboost-dev \
libboost-all-dev \
cmake \
dpkg-dev
RUN apt-get install -y \
curl
RUN apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# install ox-rst to convert org to rst
RUN mkdir /source && cd /source && \
git clone https://github.com/msnoigrs/ox-rst.git ox-rst.git
# compile install simgrid
RUN cd /source && git clone --depth=1 https://framagit.org/simgrid/simgrid.git simgrid.git && \
cd simgrid.git && \
cmake -DCMAKE_INSTALL_PREFIX=/usr/ -Denable_documentation=OFF -Denable_smpi=ON -Denable_compile_optimizations=ON . && \
make -j4 install
## compile
RUN cd /source/simgrid.git/docs/source/tuto_disk && \
cmake . &&\
make
# Generate HTML
RUN cd /source/simgrid.git/docs/source/tuto_disk && \
emacs -l init.el -batch \
--eval "(require 'package)" \
--eval "(package-initialize)" \
--eval "(setq enable-local-eval t)" \
--eval "(setq enable-local-variables t)" \
--eval "(setq ess-ask-for-ess-directory nil)" \
--eval "(setq org-babel-execute-src-block t)" \
--eval "(setq org-export-babel-evaluate t)" \
analysis.org --funcall org-rst-export-to-rst
WORKDIR /source/simgrid.git/
ENTRYPOINT [ "/bin/bash"]
This diff is collapsed.
This diff is collapsed.
(package-initialize)
(add-to-list 'package-archives
'("gnu" . "https://elpa.gnu.org/packages/"))
(add-to-list 'package-archives
'("melpa-stable" . "https://stable.melpa.org/packages/"))
(add-to-list 'package-archives
'("melpa" . "https://melpa.org/packages/"))
(add-to-list 'load-path "/source/ox-rst.git/")
(setq package-archive-priorities '(("melpa-stable" . 100)
("melpa" . 50)
("gnu" . 10)))
(require 'org)
(require 'ox-rst)
(defun auto-fill-mode-on () (TeX-PDF-mode 1))
(add-hook 'tex-mode-hook 'TeX-PDF-mode-on)
(add-hook 'latex-mode-hook 'TeX-PDF-mode-on)
(setq TeX-PDF-mode t)
(defun auto-fill-mode-on () (auto-fill-mode 1))
(add-hook 'text-mode-hook 'auto-fill-mode-on)
(add-hook 'emacs-lisp-mode 'auto-fill-mode-on)
(add-hook 'tex-mode-hook 'auto-fill-mode-on)
(add-hook 'latex-mode-hook 'auto-fill-mode-on)
(global-set-key (kbd "C-c l") 'org-store-link)
;; In org-mode 9 you need to have #+PROPERTY: header-args :eval never-export
;; in the beginning or your document to tell org-mode not to evaluate every
;; code block every time you export.
(setq org-confirm-babel-evaluate nil) ;; Do not ask for confirmation all the time!!
(org-babel-do-load-languages
'org-babel-load-languages
'(
(emacs-lisp . t)
(shell . t)
(python . t)
(R . t)
(ruby . t)
(ocaml . t)
(ditaa . t)
(dot . t)
(octave . t)
(sqlite . t)
(perl . t)
(screen . t)
(plantuml . t)
(lilypond . t)
(org . t)
(makefile . t)
))
(setq org-src-preserve-indentation t)
(add-hook 'org-babel-after-execute-hook 'org-display-inline-images)
(add-hook 'org-mode-hook 'org-display-inline-images)
(add-hook 'org-mode-hook 'org-babel-result-hide-all)
(global-set-key (kbd "C-c S-t") 'org-babel-execute-subtree)
/* Copyright (c) 2017-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 tutorial presents how to faithful emulate disk operation in SimGrid
*/
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <random>
#include <simgrid/s4u.hpp>
namespace sg4 = simgrid::s4u;
XBT_LOG_NEW_DEFAULT_CATEGORY(disk_test, "Messages specific for this simulation");
/** @brief Calculates the bandwidth for disk doing async operations */
static void estimate_bw(const sg4::Disk* disk, int n, int n_flows, bool read)
{
unsigned long long size = 100000;
double cur_time = sg4::Engine::get_clock();
std::vector<sg4::IoPtr> activities;
for (int i = 0; i < n_flows; i++) {
sg4::IoPtr act;
if (read)
act = disk->read_async(size);
else
act = disk->write_async(size);
activities.push_back(act);
}
for (const auto& act : activities)
act->wait();
double elapsed_time = sg4::Engine::get_clock() - cur_time;
printf("%s,%s,%d,%d,%d,%lf\n", disk->get_cname(), read ? "read" : "write", n, n_flows, size, elapsed_time);
}
static void host()
{
/* - Estimating bw for each disk and considering concurrent flows */
for (int i = 0; i < 20; i++) {
for (int flows = 1; flows <= 15; flows++) {
for (auto* disk : sg4::Host::current()->get_disks()) {
estimate_bw(disk, i, flows, true);
estimate_bw(disk, i, flows, false);
}
}
}
}
/*************************************************************************************************/
/** @brief Auxiliary class to generate noise in disk operations */
class DiskNoise {
double bw_;
std::vector<double> breaks_;
std::vector<double> heights_;
std::mt19937& gen_;
public:
DiskNoise(double capacity, std::mt19937& gen, const std::vector<double>& b, const std::vector<double> h)
: bw_(capacity), breaks_(b), heights_(h), gen_(gen)
{
}
double operator()(sg_size_t /*size*/) const
{
std::piecewise_constant_distribution<double> d(breaks_.begin(), breaks_.end(), heights_.begin());
auto value = d(gen_);
return value / bw_;
}
};
/** @brief Auxiliary method to get list of values from json in a vector */
static std::vector<double> get_list_from_json(const boost::property_tree::ptree& pt, const std::string& path)
{
std::vector<double> v;
for (const auto& it : pt.get_child(path)) {
double value = it.second.get_value<double>();
v.push_back(value * 1e6);
}
return v;
}
/*************************************************************************************************/
/**
* @brief Non-linear resource callback for disks
*
* @param degradation Vector with effective read/write bandwidth
* @param capacity Resource current capacity in SimGrid
* @param n Number of activities sharing this resource
*/
static double disk_dynamic_sharing(const std::vector<double>& degradation, double capacity, int n)
{
n--;
if (n >= degradation.size())
return capacity;
return degradation[n];
}
/**
* @brief Noise for I/O operations
*
* @param data Map with noise information
* @param size I/O size in bytes
* @param op I/O operation: read/write
*/
static double disk_variability(const std::unordered_map<sg4::Io::OpType, DiskNoise>& data, sg_size_t size,
sg4::Io::OpType op)
{
auto it = data.find(op);
if (it == data.end())
return 1.0;
double value = it->second(size);
return value;
}
/** @brief Creates a disk */
static void create_disk(sg4::Host* host, std::mt19937& gen, const std::string& disk_name,
const boost::property_tree::ptree& pt)
{
double read_bw = pt.get_child("read_bw").begin()->second.get_value<double>() * 1e6;
double write_bw = pt.get_child("write_bw").begin()->second.get_value<double>() * 1e6;
auto* disk = host->create_disk(disk_name, read_bw, write_bw);
std::vector<double> read_deg = get_list_from_json(pt, "degradation.read");
std::vector<double> write_deg = get_list_from_json(pt, "degradation.write");
/* get maximum possible disk speed for read/write disk constraint */
double max_bw = std::max(*std::max_element(read_deg.begin(), read_deg.end()),
*std::max_element(write_deg.begin(), write_deg.end()));
disk->set_readwrite_bandwidth(max_bw);
disk->set_sharing_policy(sg4::Disk::Operation::READ, sg4::Disk::SharingPolicy::NONLINEAR,
std::bind(&disk_dynamic_sharing, read_deg, std::placeholders::_1, std::placeholders::_2));
disk->set_sharing_policy(sg4::Disk::Operation::WRITE, sg4::Disk::SharingPolicy::NONLINEAR,
std::bind(&disk_dynamic_sharing, write_deg, std::placeholders::_1, std::placeholders::_2));
/* this is the default behavior, expliciting only to make it clearer */
disk->set_sharing_policy(sg4::Disk::Operation::READWRITE, sg4::Disk::SharingPolicy::LINEAR);
/* configuring variability */
DiskNoise read_noise(read_bw, gen, get_list_from_json(pt, "noise.read.breaks"),
get_list_from_json(pt, "noise.read.heights"));
DiskNoise write_noise(write_bw, gen, get_list_from_json(pt, "noise.write.breaks"),
get_list_from_json(pt, "noise.write.heights"));
std::unordered_map<sg4::Io::OpType, DiskNoise> noise{{sg4::Io::OpType::READ, read_noise},
{sg4::Io::OpType::WRITE, write_noise}};
disk->set_factor_cb(std::bind(&disk_variability, noise, std::placeholders::_1, std::placeholders::_2));
disk->seal();
}
/*************************************************************************************************/
int main(int argc, char** argv)
{
sg4::Engine e(&argc, argv);
std::mt19937 gen(42);
/* simple platform containing 1 host and 2 disk */
auto* zone = sg4::create_full_zone("bob_zone");
auto* bob = zone->create_host("bob", 1e6);
std::ifstream jsonFile("IO_noise.json");
boost::property_tree::ptree pt;
boost::property_tree::read_json(jsonFile, pt);
for (const auto& it : pt.get_child("")) {
create_disk(bob, gen, it.first, it.second);
}
zone->seal();
sg4::Actor::create("", bob, host);
printf("disk,op,n,flows,size,elapsed\n");
e.run();
return 0;
}
......@@ -966,6 +966,19 @@ set(DOC_SOURCES
docs/source/tuto_smpi/gemm_mpi.cpp
docs/source/tuto_smpi/roundtrip.c
docs/source/tuto_disk/analysis.org
docs/source/tuto_disk/analysis.rst
docs/source/tuto_disk/CMakeLists.txt
docs/source/tuto_disk/Dockerfile
docs/source/tuto_disk/fig/edel_read_dhist.png
docs/source/tuto_disk/fig/edel_write_dhist.png
docs/source/tuto_disk/fig/griffon_deg.png
docs/source/tuto_disk/fig/griffon_read_dhist.png
docs/source/tuto_disk/fig/griffon_write_dhist.png
docs/source/tuto_disk/fig/simgrid_results.png
docs/source/tuto_disk/init.el
docs/source/tuto_disk/tuto_disk.cpp
docs/source/Tutorial_Model-checking.rst
CITATION.bib
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment