Commit 6be05413 authored by Ramon Nou's avatar Ramon Nou
Browse files

Initial commit

parents
Loading
Loading
Loading
Loading

.gitignore

0 → 100644
+3 −0
Original line number Diff line number Diff line
.idea/
**/__pycache__/
 No newline at end of file

Dockerfile

0 → 100644
+29 −0
Original line number Diff line number Diff line
FROM ubuntu:22.04

ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get update
RUN apt-get install -y build-essential cmake libboost-dev libzmq3-dev python3 python3-zmq git

RUN mkdir /simulation

ADD https://framagit.org/simgrid/simgrid/-/archive/v3.31/simgrid-v3.31.tar.gz /simulation
WORKDIR /simulation
RUN tar -xvzf simgrid-v3.31.tar.gz
WORKDIR /simulation/simgrid-v3.31
RUN cmake -DCMAKE_INSTALL_PREFIX=/simulation/simgrid .
RUN make -j12
RUN make install

RUN git clone https://github.com/elastisim/elastisim.git /simulation/elastisim
WORKDIR /simulation/elastisim
RUN cmake -DCMAKE_INSTALL_PREFIX=/simulation/elastisim -DSIMGRID_SOURCE_DIR=/simulation/simgrid -DCMAKE_BUILD_TYPE="Release" .
RUN make -j12

WORKDIR /simulation/
RUN git clone https://github.com/elastisim/elastisim-python.git
ENV PYTHONPATH "${PYTHONPATH}:/simulation/elastisim-python"

WORKDIR /
ENTRYPOINT ["/simulation/elastisim/elastisim"]
 No newline at end of file

LICENSE

0 → 100644
+29 −0
Original line number Diff line number Diff line
BSD 3-Clause License

Copyright (c) 2022, Technical University of Darmstadt, Darmstadt, Germany
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
   contributors may be used to endorse or promote products derived from
   this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

0 → 100644
+41 −0
Original line number Diff line number Diff line
# ElastiSim Example Project

An example ElastiSim project utilizing an FCFS algorithm (without backfill) applied on 32 rigid jobs with alternating compute and I/O phases running on a crossbar topology with 128 compute nodes.

## Installation

To build the container required to run ElastiSim, install Docker and execute the following command:
```sh
docker build -t elastisim .
```

## Simulation

To run the simulation, execute the following commands in two different sessions:

### \*nix:
```sh
docker run -v $PWD/data:/data -v $PWD/algorithm:/algorithm -u `id -u $USER` --name elastisim -it --rm elastisim /data/input/configuration.json --log=root.thresh:warning
docker exec -u `id -u $USER` -it elastisim python3 /algorithm/algorithm.py
```

### Mac OS:
```sh
docker run -v $PWD/data:/data -v $PWD/algorithm:/algorithm --name elastisim -it --rm elastisim /data/input/configuration.json --log=root.thresh:warning
docker exec -it elastisim python3 /algorithm/algorithm.py
```

### Windows (PowerShell):
```sh
docker run -v ${PWD}\data:/data -v ${PWD}\algorithm:/algorithm --name elastisim -it --rm elastisim /data/input/configuration.json --log=root.thresh:warning
docker exec -it elastisim python3 /algorithm/algorithm.py
```

The first command runs the ElastiSim simulator process and accepts two inputs:
- the configuration file (JSON)
- the logging level

For a more detailed output change `--log=root.thresh:warning` to `--log=root.thresh:info` (caution: verbose).

The second command runs the scheduling algorithm.
 No newline at end of file

algorithm/algorithm.py

0 → 100644
+98 −0
Original line number Diff line number Diff line
# This file is part of the ElastiSim software.
#
# Copyright (c) 2022, Technical University of Darmstadt, Germany
#
# This software may be modified and distributed under the terms of the 3-Clause
# BSD License. See the LICENSE file in the base directory for details.
from typing import Any
from os import path
from elastisim_python import JobState, JobType, NodeState, pass_algorithm, Job, Node

filename = "data/output/breaks.txt"

def write_integer_to_file(filename, number):
    with open(filename, 'w') as file:
        file.write(str(number))

def read_integer_from_file(filename):
    if not path.isfile(filename):
        return 0
    with open(filename, 'r') as file:
        number = int(file.read())
        return number

def update_integer_in_file(filename, update_value):
    number = read_integer_from_file(filename)
    updated_number = number + update_value
    write_integer_to_file(filename, updated_number)

def schedule(jobs: list[Job], nodes: list[Node], system: dict[str, Any]) -> None:
    time = system['time']
    pending_jobs = [job for job in jobs if job.state == JobState.PENDING]
    running_jobs = [job for job in jobs if job.state == JobState.RUNNING]

    free_nodes = [node for node in nodes if node.state == NodeState.FREE]

    shrink = False
    expand = False
    schedule = False
    # Check if we can allocate more jobs (all jobs are malleable)
    high_bw = 0
    low_bw = 0
    #We should try to have 1 high bw job and 1 low job
    for job in pending_jobs:
        requestedBw = float(job.attributes["BW"])
        if not free_nodes:
            break
        is_minimum = True
        if (schedule):
            if (high_bw >= low_bw):
                # Check if there is a job with lower requirements
                for other_job in pending_jobs:
                    other_requestedBw = float(other_job.attributes["BW"])
                    if (requestedBw > other_requestedBw):
                        is_minimum = False
                        break
            if (is_minimum):
                #Run the job if possible
                if (high_bw >= low_bw):
                    low_bw = low_bw + 1
                else:
                    high_bw = high_bw + 1
                num_nodes_to_assign = min(len(free_nodes), 3 )#job.num_nodes_max)
                if num_nodes_to_assign >= job.num_nodes_min:
                    job.assign(free_nodes[:num_nodes_to_assign])
                    del free_nodes[:num_nodes_to_assign]
        else:
            num_nodes_to_assign = min(len(free_nodes), 3 ) #job.num_nodes_max)
            if num_nodes_to_assign >= job.num_nodes_min:
                job.assign(free_nodes[:num_nodes_to_assign])
                del free_nodes[:num_nodes_to_assign]

    for job in running_jobs:
        requestedBw = float(job.attributes["BW"])
        bytes_write = float(job.completed_phases)*float(job.arguments["bytes_write"])
        if (time-job.start_time > 10) :
            bw = (bytes_write/(1024*1024*1024))/(time-job.start_time)       
            if (bw > (requestedBw+requestedBw*0.1)):
                num_nodes_to_shrink = 1
                if (num_nodes_to_shrink < len(job.assigned_nodes)) :
                    if (shrink):
                       # print("BW Obtained : "+str(bw)+ " Requested "+str(requestedBw))
                       # print("Shrink : "+str(len(job.assigned_nodes))+"Job"+str(job.identifier))
                        node = job.assigned_nodes[len(job.assigned_nodes)-1]
                        job.remove(node)
            else:
                if (bw < (requestedBw-requestedBw*0.1)):
                    update_integer_in_file(filename, 1)
                    if (job.num_nodes_max > len(job.assigned_nodes)):
                        num_nodes_to_expand = min(len(free_nodes), 1)
                        if num_nodes_to_expand > 0:
                            if (expand):
                               # print("Expand: "+str(job.identifier) + " From " +str(len(job.assigned_nodes)))
                                job.assign(free_nodes[:num_nodes_to_expand])
                                del free_nodes[:num_nodes_to_expand]
       
if __name__ == '__main__':
    url = 'ipc:///tmp/elastisim.ipc'
    pass_algorithm(schedule, url)