diff --git a/Lab 1/Green Lab - Lab 1.pptx.pdf b/Lab 1/Green Lab - Lab 1.pptx.pdf new file mode 100644 index 0000000..aca87fb Binary files /dev/null and b/Lab 1/Green Lab - Lab 1.pptx.pdf differ diff --git a/Lab 1/README.md b/Lab 1/README.md new file mode 100644 index 0000000..b1fbb17 --- /dev/null +++ b/Lab 1/README.md @@ -0,0 +1,13 @@ +# GreenLab 2025: Lab 1 +This repository contains a set of exercises for the GreenLab Lab 1 of 2025. The exercises are designed to help students learn about ExperimentRunner and EnergieBridge using a series of hands-on tasks. + +## Setup and Installation +Firstly, you will set up your development environment by installing the Experiment Runner framework and the EnergiBridge tool; verify installations and run basic tests to ensure everything is working correctly. + +## Exercise 1 - EnergieBridge Demo** +This exercise introduces the basic functionalities and provides an overview of the EnergieBridge. + +**Ex 3 - Know about RuntableModel** +This exercise integrates the ExperimentRunner with the EnergieBridge, so you can use them together, running experiments and collect data. + + diff --git a/Lab 1/ex1/EnergiBridge.md b/Lab 1/ex1/EnergiBridge.md new file mode 100644 index 0000000..cf87889 --- /dev/null +++ b/Lab 1/ex1/EnergiBridge.md @@ -0,0 +1,79 @@ +# Getting familiar with [EnergiBridge](https://github.com/tdurieux/EnergiBridge) + +In this exercise, we will start with a simple experiment using **one factor** and **one level**. Later on, we will explore how to run more complex experiments. + +The goal here is to demonstrate how `EnergiBridge` can act as a **profiler** within the `experiment-runner` framework. For now, we just want to run a single command and observe the results. + +## Step 1: Run a Basic Command + +Execute the following command: + +```bash +energibridge --summary -o test.csv sleep 5 +``` + +This will: + +* Run the command `sleep 5` for 5 seconds +* Record resource usage data +* Save results in `test.csv` + +## Step 2: Observe Terminal Output + +You should see a message similar to: + +```bash +Energy consumption in joules: 253.86045820617682 for 5.1230927 sec of execution. +``` + +⚠️ Note: The energy consumption value is **system dependent** and will vary. + +## Step 3: Inspect the CSV Output + +Open the generated `test.csv` file to view detailed raw EnergiBridge data. Example header format: + +``` +Delta,Time,CPU_FREQUENCY_0,CPU_FREQUENCY_1,...,SYSTEM_POWER (Watts),TOTAL_MEMORY,TOTAL_SWAP,USED_MEMORY,USED_SWAP +``` + +Example first two rows: + +``` +0,1697704464320,0,0,0,0,0,0,0,0,0,0,46.529457092285156,44.31881332397461,43.83422088623047,47.03656005859375,44.67115783691406,43.856910705566406,41.333412170410156,41.268951416015625,44.348262786865234,43.08387756347656,46.37215805053711,45.429779052734375,15.021618843078613,8.819367408752441,5.0954484939575195,3.514699935913086,2.9715969562530518,1.5818228721618652,1.1069598197937012,0.9475208520889282,11.58033275604248,34359738368,0,10188488704,0 +104,1697704464321,0,0,0,0,0,0,0,0,0,0,46.529457092285156,44.31881332397461,43.83422088623047,47.03656005859375,44.67115783691406,43.856910705566406,41.333412170410156,41.268951416015625,44.348262786865234,43.08387756347656,46.37215042114258,45.429771423339844,15.021615982055664,8.819366455078125,5.095447063446045,3.514699697494507,2.9715967178344727,1.5818227529525757,1.1069598197937012,0.9475207924842834,11.58033275604248,34359738368,0,10189275136,0 +``` + +--- + +## 🔎 Optional Exploration + +You can run the following examples if you want to see the difference in consumption for tasks with different stress targets. + +* **CPU-bound workload**: + +```bash +energibridge --summary -o cpu_test.csv -m 5 sha1sum /dev/zero +``` + +* **Memory-bound workload**: + +```bash +energibridge --summary -o mem_test.csv -m 5 python -c "a = [0]*10**7" +``` + +* **Disk I/O workload**: + +```bash +energibridge --summary -o io_test.csv dd if=/dev/zero of=testfile bs=1M count=500 +``` + +### Discussion Points + +* Compare energy use across `sleep`, `cpu_test.csv`, `mem_test.csv`, and `io_test.csv`. +* Which workloads consume more CPU energy? Which stress memory or I/O? +* Do CPU frequency and temperature values rise under stress? + +### Visualization Task + +* Open the generated CSV files in Excel, Python (Pandas/Matplotlib), or use the official [chart.ipynb](https://github.com/tdurieux/EnergiBridge/blob/main/chart.ipynb). +* Plot CPU usage, memory usage, or power consumption over time. diff --git a/Lab 1/ex2/ExperimentRunner.md b/Lab 1/ex2/ExperimentRunner.md new file mode 100644 index 0000000..fa03543 --- /dev/null +++ b/Lab 1/ex2/ExperimentRunner.md @@ -0,0 +1,135 @@ +# Getting Familiar with [Experiment Runner](https://github.com/S2-group/experiment-runner/tree/master) + +## Overview + +In this exercise, you will learn how to configure and run experiments using **Experiment Runner**. The focus is on understanding: + +* The role of `RunnerConfig.py` +* The nine execution stages +* How to define an experiment using `RunTableModel` +* How measurement data is collected and aggregated + +By the end, you’ll be able to design your own small experiments and extend them with different factors, treatments, and measurement outputs. + +## RunnerConfig.py + +`RunnerConfig.py` defines how your experiment should be conducted, including the subjects (programs to run) and the output data to be collected. Based on this configuration, Experiment Runner will: + +* Create the experiment folder +* Generate the run table (`.csv`) inside the experiment folder +* Execute the experiment across all defined variations +* Follow **9 execution stages** during the lifecycle of each experiment + +## Execution Stages + +Execution stages are represented by methods inside the `RunnerConfig` class. They allow you to add setup, cleanup, or measurement actions before, during, and after runs. + +### The 9 Stages + +* **before\_experiment()**: Runs once before the entire experiment begins. Useful for cleanup, configuring CPU governors, or warming up the machine. + +For each run: + +* **before\_run()**: Invoked before a run starts. +* **start\_run()**: Marks the beginning of a run. +* **start\_measurement()**: Begins the measurement phase. +* **interact()**: Lets you interact with the target system during a run. +* **stop\_measurement()**: Stops measurements. +* **stop\_run()**: Called once a run finishes. +* **populate\_run\_data()**: Processes results and fills the data columns. + +Finally: + +* **after\_experiment()**: Runs once after all runs complete. Useful for cleanup and final reporting. + +⚠️ *Note: These stages are optional—you don’t need to implement them all for an experiment to run.* + + +## RunTableModel + +The `RunTableModel` specifies: + +* **Factors** and their **treatment levels** +* The number of **repetitions** +* Whether runs should be **shuffled** +* Any **excluded combinations** of treatments +* **Data columns** to store results + +The definition happens in the `create_run_table_model()` function. + +### Example 1: Defining the Run Table + +```python +def create_run_table_model(self) -> RunTableModel: + factor1 = FactorModel("fib_type", ['iter', 'mem', 'rec']) + factor2 = FactorModel("problem_size", [10, 35, 40, 5000, 10000]) + self.run_table_model = RunTableModel( + factors=[factor1, factor2], + exclude_combinations=[ + {factor2: [10]}, # exclude all runs with treatment "10" + {factor1: ['rec'], factor2: [5000, 10000]}, # exclude ('rec', 5000) and ('rec', 10000) + ], + shuffle=True, + repetitions=10, + data_columns=["energy", "runtime", "memory"] + ) + return self.run_table_model +``` + +This experiment repeats runs **10 times each**, producing **60 total results**. The results are stored in `run_table.csv`, for example: + +| \_\_run\_id | \_\_done | fib\_type | problem\_size | energy | runtime | memory | +| --------------------- | -------- | --------- | ------------- | ------ | ------- | ----------- | +| run\_0\_repetition\_0 | DONE | rec | 40 | 61.3 | 21.9402 | 10778673152 | + +--- + +### Example 2: Measurement Stages + +```python +def start_measurement(self, context: RunnerContext) -> None: + fib_type = context.execute_run["fib_type"] + problem_size = context.execute_run["problem_size"] + + self.profiler = EnergiBridge( + target_program=f"python examples/hello-world-fibonacci/fibonacci_{fib_type}.py {problem_size}", + out_file=context.run_dir / "energibridge.csv" + ) + + self.profiler.start() +``` + +```python +def populate_run_data(self, context: RunnerContext) -> Optional[Dict[str, Any]]: + eb_log, eb_summary = self.profiler.parse_log( + self.profiler.logfile, + self.profiler.summary_logfile + ) + + return { + "energy": list(eb_log["PACKAGE_ENERGY (J)"].values())[-1] - list(eb_log["PACKAGE_ENERGY (J)"].values())[0], + "runtime": eb_summary["runtime_seconds"], + "memory": max(eb_log["USED_MEMORY"].values()) + } +``` + +The final `run_table.csv` combines all repetitions and aggregates results from each `energibridge.csv`. The computation logic follows what’s defined in `populate_run_data()`. + +## Run it yourself + +* Change factor levels (e.g., add more Fibonacci sizes) and rerun. +* Increase or decrease repetitions to see how result stability changes. +* Add new data columns (e.g., `cpu_temp`) and extend `populate_run_data()`. +* Compare performance between Fibonacci implementations (`iter` vs `mem` vs `rec`). + +### Small experiments + +1. Predict which Fibonacci type (`iter`, `mem`, or `rec`) performs best at large problem sizes. Run the experiment and check if your prediction holds. +2. Try disabling shuffling—does the order of runs affect performance or stability? +3. Visualize your results (runtime vs. problem size) in a simple plot. + + +## Notes + +* Code snippets are taken from `examples/hello-world-fibonacci/RunnerConfig.py`. +* Explore additional examples in the [examples folder](https://github.com/S2-group/experiment-runner/tree/master/examples) for inspiration. diff --git a/Lab 1/setup/Setup.md b/Lab 1/setup/Setup.md new file mode 100644 index 0000000..e94d0cd --- /dev/null +++ b/Lab 1/setup/Setup.md @@ -0,0 +1,128 @@ +# Environment Setup Guide + +Follow these steps to prepare your environment for running experiments. + +## 1. Install [Experiment Runner](https://github.com/S2-group/experiment-runner/tree/master) + +Experiment Runner is a framework to automatically execute measurement-based experiments on any platform. Experiments are customizable and defined in Python. + +### Steps + +1. **Fork & Clone** + + * Fork the repository [here](https://github.com/S2-group/experiment-runner/tree/master). + * Clone your fork to your local machine. + +2. **Install** + + * Ensure you are using **Python ≥ 3.8**. + * Follow the installation instructions in the [README](https://github.com/S2-group/experiment-runner/tree/master). + * 💡 *Tip:* Use a virtual environment (`venv` or [Miniconda](https://docs.anaconda.com/miniconda/)) to avoid dependency issues. + * Run `python3 -m venv venv` in your project directory; + * Run `source ./venv/bin/activate` to activate the environment; + * Run `pip install -r ./experiment-runner/requirements.txt` + + * **Note**: Whenever you want to run experiment runner in this case, you must run it from the activated environment. + +3. **Run Example** + + * Test the setup by running the Hello World example: + + ```bash + python experiment-runner/examples/hello-world/RunnerConfig.py + ``` + * Results will be stored in: + + ``` + examples/hello-world/experiments/new_runner_experiment + ``` + * ✅ If it runs without errors, your installation is successful. + + +## 2. Install [EnergiBridge](https://github.com/tdurieux/EnergiBridge) + +EnergiBridge is a cross-platform tool to measure energy consumption and resource usage. It supports Linux, Windows, macOS, and multiple CPU architectures. + +### Steps + +1. **Install** + + * Follow the platform-specific installation instructions from the [EnergiBridge README](https://github.com/tdurieux/EnergiBridge?tab=readme-ov-file#install). + +2. **Verify Installation** + + * Run: + + ```bash + energibridge -h + ``` + * ✅ If the help message appears, EnergiBridge is installed correctly. + + +## 3. Troubleshooting + +### Rust / Cargo not found + +```bash +$ cargo build -r +cargo: command not found +``` + +➡️ Install Rust: [rust-lang.org/tools/install](https://www.rust-lang.org/tools/install). + +--- + +### Energibridge command not found (after installation) + +```bash +$ energibridge -h +energibridge: command not found +``` + +This happens because your OS does not know where to find energibridge (yet). To **fix this** you can use one of the following options: + + +#### Option 1: Add to PATH temporarily + +You can run the following command in a shell: +```bash +export PATH=$PATH:/target/release +``` + +Works **only for the current shell** session. + +#### Option 2: Add to PATH permanently +Append the line to your shell configuration file (e.g., `~/.bashrc`, `~/.zshrc`): + +```bash +echo 'export PATH=$PATH:~/EnergiBridge/target/release' >> ~/.bashrc +source ~/.bashrc +``` + +After this, energibridge will be available in all new terminal sessions. + +#### Option 3 (RECOMMENDED): Copy binary to a system-wide directory +```bash +sudo cp /target/release/energibridge /usr/local/bin/ +``` + +After this, you can run `energibridge` from anywhere without modifying configs. + +Run `energibridge -h` to check that it works. + +--- + +### Permission error + +```bash +$ energibridge sleep 3 +Permission denied +``` + +Run with `sudo`: + +```bash +sudo /path/to/energibridge sleep 3 +``` + +**Note:** When running with `sudo`, your user `$PATH` is not loaded. Use the **full path** or copy the binary to a system-wide directory. diff --git a/Lab 1/troubleshooting.md b/Lab 1/troubleshooting.md new file mode 100644 index 0000000..6c7d4e9 --- /dev/null +++ b/Lab 1/troubleshooting.md @@ -0,0 +1,67 @@ +## 3. Troubleshooting + +### Rust / Cargo not found + +```bash +$ cargo build -r +cargo: command not found +``` + +➡️ Install Rust: [rust-lang.org/tools/install](https://www.rust-lang.org/tools/install). + +--- + +### Energibridge command not found (after installation) + +```bash +$ energibridge -h +energibridge: command not found +``` + +This happens because your OS does not know where to find energibridge (yet). To **fix this** you can use one of the following options: + + +#### Option 1: Add to PATH temporarily + +You can run the following command in a shell: +```bash +export PATH=$PATH:/target/release +``` + +Works **only for the current shell** session. + +#### Option 2: Add to PATH permanently +Append the line to your shell configuration file (e.g., `~/.bashrc`, `~/.zshrc`): + +```bash +echo 'export PATH=$PATH:~/EnergiBridge/target/release' >> ~/.bashrc +source ~/.bashrc +``` + +After this, energibridge will be available in all new terminal sessions. + +#### Option 3 (RECOMMENDED): Copy binary to a system-wide directory +```bash +sudo cp /target/release/energibridge /usr/local/bin/ +``` + +After this, you can run `energibridge` from anywhere without modifying configs. + +Run `energibridge -h` to check that it works. + +--- + +### Permission error + +```bash +$ energibridge sleep 3 +Permission denied +``` + +Run with `sudo`: + +```bash +sudo /path/to/energibridge sleep 3 +``` + +**Note:** When running with `sudo`, your user `$PATH` is not loaded. Use the **full path** or copy the binary to a system-wide directory. diff --git a/README.md b/README.md deleted file mode 100644 index e48803d..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# green-lab -Online material for the Green Lab at VU Amsterdam diff --git a/lab2/README.md b/lab2/README.md new file mode 100644 index 0000000..5e695d8 --- /dev/null +++ b/lab2/README.md @@ -0,0 +1,78 @@ +# Instruction of Dependencies Installation for MacOS + + +## Set up environment and dependencies + +**Set up virtual environment** + +1. If you do not have, create a virtual environment: `python3 -m venv /path/`. This can be anywhere on your machine. + +2. Activate it with `source /path/bin/activate` + +**Install dependencies (MacOS)** + +1. Make sure you have [Homebrew](https://brew.sh/) installed, check: +``` +brew --version +``` + +2. Install OpenJDK8, sdk, and platform tools + +Option 1: (for Emulation) Install OpenJDK 8, Android Studio and Platform Tools: + ``` + brew install --cask temurin@8 android-studio android-platform-tools + ``` + Option 2: (for Android Phone) Install OpenJDK 8, CommandLineTools and Platform Tools: + ``` + brew install --cask temurin@8 android-commandlinetools android-platform-tools + ``` + *If you meet the notice of outdated formulae, can `brew update && brew upgrade && brew cleanup` to upgrade all installed packages, and clean outdated ones.* + + +3. Install libxml2: +``` +brew install libxml2 +``` + + +4. Check Java version: `java -version`, if you are running a different version than 1.8/8, `brew install jenv` +- Run `/usr/libexec/java_home -V` to see the location of your Java environments +- Copy the location of your AdoptOpenJDK8 environment: + ``` + Run jenv add + Run jenv global 1.8 + ``` +- Restart terminal and verify your Java version with java -version, it should output openjdk version "1.8.0_265" +- Install the requirements, under the android-runner: `pip install -r requirements.txt` + + + +# Troubleshooting +1. Emulator Not Found +``` +command not found: emulator +``` +This error is because `emulator` is not in the current system environment. + +**For Windows** + +Temporary addition (valid for current session only) +``` +set PATH=%PATH%;C:\Users\[username]\AppData\Local\Android\Sdk\emulator +``` + +Permanent addition: Right-click "This PC" → Properties → Advanced system settings → Environment Variables. Find Path in system variables, edit, and add emulator path + +**For MacOS/Linux** + +Temporary addition (valid for current session only) +``` +export PATH=$PATH:~/Library/Android/sdk/emulator +``` + +Permanently add to the terminal (`bashrc` or `zshrc`): + +``` +echo 'export PATH=$PATH:~/Library/Android/sdk/emulator' >> ~/.bashrc +source ~/.bashrc` +```