├── 10 ├── README.md └── heat_stencil_2D.c ├── 11 ├── real.tar.gz └── README.md ├── 12 └── README.md ├── 13 ├── particle.plt └── README.md ├── example_makefile ├── .gitignore ├── common.h ├── common.c ├── program1.c ├── program2.c ├── Makefile └── README.md ├── docs ├── img │ ├── slurm.png │ ├── slurm2.png │ ├── sandbox.png │ ├── supercomputer2.png │ └── supercomputer3.png ├── dist │ ├── theme │ │ ├── fonts │ │ │ ├── league-gothic │ │ │ │ ├── LICENSE │ │ │ │ ├── league-gothic.eot │ │ │ │ ├── league-gothic.ttf │ │ │ │ ├── league-gothic.woff │ │ │ │ └── league-gothic.css │ │ │ └── source-sans-pro │ │ │ │ ├── source-sans-pro-italic.eot │ │ │ │ ├── source-sans-pro-italic.ttf │ │ │ │ ├── source-sans-pro-italic.woff │ │ │ │ ├── source-sans-pro-regular.eot │ │ │ │ ├── source-sans-pro-regular.ttf │ │ │ │ ├── source-sans-pro-regular.woff │ │ │ │ ├── source-sans-pro-semibold.eot │ │ │ │ ├── source-sans-pro-semibold.ttf │ │ │ │ ├── source-sans-pro-semibold.woff │ │ │ │ ├── source-sans-pro-semibolditalic.eot │ │ │ │ ├── source-sans-pro-semibolditalic.ttf │ │ │ │ ├── source-sans-pro-semibolditalic.woff │ │ │ │ ├── source-sans-pro.css │ │ │ │ └── LICENSE │ │ ├── solarized.css │ │ ├── white.css │ │ ├── black.css │ │ ├── night.css │ │ └── serif.css │ └── reset.css ├── plugin │ ├── menu │ │ ├── font-awesome │ │ │ ├── webfonts │ │ │ │ ├── fa-brands-400.eot │ │ │ │ ├── fa-brands-400.ttf │ │ │ │ ├── fa-brands-400.woff │ │ │ │ ├── fa-regular-400.eot │ │ │ │ ├── fa-regular-400.ttf │ │ │ │ ├── fa-solid-900.eot │ │ │ │ ├── fa-solid-900.ttf │ │ │ │ ├── fa-solid-900.woff │ │ │ │ ├── fa-solid-900.woff2 │ │ │ │ ├── fa-brands-400.woff2 │ │ │ │ ├── fa-regular-400.woff │ │ │ │ └── fa-regular-400.woff2 │ │ │ ├── css │ │ │ │ ├── brands.css │ │ │ │ ├── solid.css │ │ │ │ ├── regular.css │ │ │ │ └── svg-with-js.css │ │ │ └── LICENSE.txt │ │ ├── bower.json │ │ ├── CONTRIBUTING.md │ │ ├── LICENSE │ │ ├── package.json │ │ └── gulpfile.js │ ├── math │ │ ├── plugin.js │ │ ├── mathjax2.js │ │ ├── mathjax3.js │ │ ├── katex.js │ │ ├── math.esm.js │ │ └── math.js │ ├── highlight │ │ ├── monokai.css │ │ └── zenburn.css │ ├── search │ │ ├── search.esm.js │ │ ├── search.js │ │ └── plugin.js │ ├── zoom │ │ ├── zoom.esm.js │ │ ├── zoom.js │ │ └── plugin.js │ └── notes │ │ └── plugin.js └── index.html ├── resources ├── example_figure.png └── example_figure_std.png ├── 05 ├── ex1 │ ├── Makefile │ └── ex1.c ├── ex2 │ ├── Makefile │ └── ex2.c └── README.md ├── 03 ├── mandelbrot │ ├── Makefile │ └── mandelbrot.c └── README.md ├── 04 ├── monte_carlo_pi │ ├── Makefile │ └── mc_pi_pthreads.c └── README.md ├── .clang-format ├── 01 ├── medium.c ├── slow.c ├── fast.c └── readme.md ├── job.sh ├── 07 ├── analysis.c └── README.md ├── 08 └── README.md ├── 06 └── README.md ├── 02 └── readme.md ├── readme.md ├── lcc3_tutorial.md ├── 09 └── README.md └── submission_tutorial.md /example_makefile/.gitignore: -------------------------------------------------------------------------------- 1 | common.o 2 | program1 3 | program2 4 | -------------------------------------------------------------------------------- /example_makefile/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void common_function(); 4 | -------------------------------------------------------------------------------- /11/real.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/11/real.tar.gz -------------------------------------------------------------------------------- /docs/img/slurm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/img/slurm.png -------------------------------------------------------------------------------- /docs/img/slurm2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/img/slurm2.png -------------------------------------------------------------------------------- /docs/img/sandbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/img/sandbox.png -------------------------------------------------------------------------------- /docs/img/supercomputer2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/img/supercomputer2.png -------------------------------------------------------------------------------- /docs/img/supercomputer3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/img/supercomputer3.png -------------------------------------------------------------------------------- /resources/example_figure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/resources/example_figure.png -------------------------------------------------------------------------------- /resources/example_figure_std.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/resources/example_figure_std.png -------------------------------------------------------------------------------- /docs/dist/theme/fonts/league-gothic/LICENSE: -------------------------------------------------------------------------------- 1 | SIL Open Font License (OFL) 2 | http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL 3 | -------------------------------------------------------------------------------- /example_makefile/common.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | #include 4 | 5 | void common_function(int foo) { 6 | printf("using common %d\n", foo); 7 | } 8 | -------------------------------------------------------------------------------- /docs/dist/theme/fonts/league-gothic/league-gothic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/dist/theme/fonts/league-gothic/league-gothic.eot -------------------------------------------------------------------------------- /docs/dist/theme/fonts/league-gothic/league-gothic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/dist/theme/fonts/league-gothic/league-gothic.ttf -------------------------------------------------------------------------------- /docs/dist/theme/fonts/league-gothic/league-gothic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/dist/theme/fonts/league-gothic/league-gothic.woff -------------------------------------------------------------------------------- /docs/plugin/menu/font-awesome/webfonts/fa-brands-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/plugin/menu/font-awesome/webfonts/fa-brands-400.eot -------------------------------------------------------------------------------- /docs/plugin/menu/font-awesome/webfonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/plugin/menu/font-awesome/webfonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /docs/plugin/menu/font-awesome/webfonts/fa-brands-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/plugin/menu/font-awesome/webfonts/fa-brands-400.woff -------------------------------------------------------------------------------- /docs/plugin/menu/font-awesome/webfonts/fa-regular-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/plugin/menu/font-awesome/webfonts/fa-regular-400.eot -------------------------------------------------------------------------------- /docs/plugin/menu/font-awesome/webfonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/plugin/menu/font-awesome/webfonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /docs/plugin/menu/font-awesome/webfonts/fa-solid-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/plugin/menu/font-awesome/webfonts/fa-solid-900.eot -------------------------------------------------------------------------------- /docs/plugin/menu/font-awesome/webfonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/plugin/menu/font-awesome/webfonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /docs/plugin/menu/font-awesome/webfonts/fa-solid-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/plugin/menu/font-awesome/webfonts/fa-solid-900.woff -------------------------------------------------------------------------------- /docs/plugin/menu/font-awesome/webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/plugin/menu/font-awesome/webfonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /docs/plugin/menu/font-awesome/webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/plugin/menu/font-awesome/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /docs/plugin/menu/font-awesome/webfonts/fa-regular-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/plugin/menu/font-awesome/webfonts/fa-regular-400.woff -------------------------------------------------------------------------------- /docs/plugin/menu/font-awesome/webfonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/plugin/menu/font-awesome/webfonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /05/ex1/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -std=gnu11 -Wall -Wextra -lm -fopenmp 2 | 3 | .PHONY: all 4 | all: ex1 5 | 6 | .PHONY: clean 7 | clean: 8 | $(RM) ex1 9 | 10 | ex1: ex1.c 11 | -------------------------------------------------------------------------------- /05/ex2/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -std=gnu11 -Wall -Wextra -lm -fopenmp 2 | 3 | .PHONY: all 4 | all: ex2 5 | 6 | .PHONY: clean 7 | clean: 8 | $(RM) ex2 9 | 10 | ex2: ex2.c 11 | -------------------------------------------------------------------------------- /docs/dist/theme/fonts/source-sans-pro/source-sans-pro-italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/dist/theme/fonts/source-sans-pro/source-sans-pro-italic.eot -------------------------------------------------------------------------------- /docs/dist/theme/fonts/source-sans-pro/source-sans-pro-italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/dist/theme/fonts/source-sans-pro/source-sans-pro-italic.ttf -------------------------------------------------------------------------------- /docs/dist/theme/fonts/source-sans-pro/source-sans-pro-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/dist/theme/fonts/source-sans-pro/source-sans-pro-italic.woff -------------------------------------------------------------------------------- /docs/dist/theme/fonts/source-sans-pro/source-sans-pro-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/dist/theme/fonts/source-sans-pro/source-sans-pro-regular.eot -------------------------------------------------------------------------------- /docs/dist/theme/fonts/source-sans-pro/source-sans-pro-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/dist/theme/fonts/source-sans-pro/source-sans-pro-regular.ttf -------------------------------------------------------------------------------- /docs/dist/theme/fonts/source-sans-pro/source-sans-pro-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/dist/theme/fonts/source-sans-pro/source-sans-pro-regular.woff -------------------------------------------------------------------------------- /docs/dist/theme/fonts/source-sans-pro/source-sans-pro-semibold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/dist/theme/fonts/source-sans-pro/source-sans-pro-semibold.eot -------------------------------------------------------------------------------- /docs/dist/theme/fonts/source-sans-pro/source-sans-pro-semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/dist/theme/fonts/source-sans-pro/source-sans-pro-semibold.ttf -------------------------------------------------------------------------------- /docs/dist/theme/fonts/source-sans-pro/source-sans-pro-semibold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/dist/theme/fonts/source-sans-pro/source-sans-pro-semibold.woff -------------------------------------------------------------------------------- /docs/dist/theme/fonts/source-sans-pro/source-sans-pro-semibolditalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/dist/theme/fonts/source-sans-pro/source-sans-pro-semibolditalic.eot -------------------------------------------------------------------------------- /docs/dist/theme/fonts/source-sans-pro/source-sans-pro-semibolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/dist/theme/fonts/source-sans-pro/source-sans-pro-semibolditalic.ttf -------------------------------------------------------------------------------- /docs/dist/theme/fonts/source-sans-pro/source-sans-pro-semibolditalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uibk-dps-teaching/ps_parprog_2024/HEAD/docs/dist/theme/fonts/source-sans-pro/source-sans-pro-semibolditalic.woff -------------------------------------------------------------------------------- /03/mandelbrot/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -std=gnu11 -Wall -Wextra -lm 2 | 3 | .PHONY: all 4 | all: mandelbrot 5 | 6 | .PHONY: clean 7 | clean: 8 | $(RM) mandelbrot mandelbrot.png 9 | 10 | mandelbrot: mandelbrot.c 11 | -------------------------------------------------------------------------------- /example_makefile/program1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "common.h" 5 | 6 | int main(void) { 7 | puts("This is Program 1"); 8 | 9 | common_function(2); 10 | 11 | return EXIT_SUCCESS; 12 | } 13 | -------------------------------------------------------------------------------- /example_makefile/program2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "common.h" 5 | 6 | int main(void) { 7 | puts("This is Program 2"); 8 | 9 | common_function(3); 10 | 11 | return EXIT_SUCCESS; 12 | } 13 | -------------------------------------------------------------------------------- /example_makefile/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -std=gnu11 -Wall -Werror -Wextra 2 | 3 | .PHONY: all 4 | all: program1 program2 5 | 6 | .PHONY: clean 7 | clean: 8 | $(RM) common.o program1 program2 9 | 10 | common.o: common.c common.h 11 | 12 | program1: program1.c common.o 13 | 14 | program2: program2.c common.o 15 | -------------------------------------------------------------------------------- /04/monte_carlo_pi/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-Wall -Wextra -Wpedantic -Werror -std=c17 -O3 -march=native -g 3 | LDFLAGS=-lpthread 4 | 5 | TARGETS=mc_pi_pthreads 6 | 7 | .PHONY: all clean 8 | 9 | all: $(TARGETS) 10 | 11 | clean: 12 | $(RM) $(TARGETS) 13 | 14 | %: %.c 15 | $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) 16 | -------------------------------------------------------------------------------- /docs/dist/theme/fonts/league-gothic/league-gothic.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'League Gothic'; 3 | src: url('./league-gothic.eot'); 4 | src: url('./league-gothic.eot?#iefix') format('embedded-opentype'), 5 | url('./league-gothic.woff') format('woff'), 6 | url('./league-gothic.ttf') format('truetype'); 7 | 8 | font-weight: normal; 9 | font-style: normal; 10 | } 11 | -------------------------------------------------------------------------------- /docs/plugin/math/plugin.js: -------------------------------------------------------------------------------- 1 | import {KaTeX} from "./katex"; 2 | import {MathJax2} from "./mathjax2"; 3 | import {MathJax3} from "./mathjax3"; 4 | 5 | const defaultTypesetter = MathJax2; 6 | 7 | /*! 8 | * This plugin is a wrapper for the MathJax2, 9 | * MathJax3 and KaTeX typesetter plugins. 10 | */ 11 | export default Plugin = Object.assign( defaultTypesetter(), { 12 | KaTeX, 13 | MathJax2, 14 | MathJax3 15 | } ); -------------------------------------------------------------------------------- /example_makefile/README.md: -------------------------------------------------------------------------------- 1 | # Template Makefile 2 | 3 | This Makefile demonstrates how you can compile multiple executables 4 | (`program1` and `program2`) which use a shared translation unit (`common`). 5 | 6 | Note that this Makefile uses GNU Make's [implicit rules](https://www.gnu.org/software/make/manual/html_node/Implicit-Rules.html). 7 | 8 | For more information, please [consult the manual](https://www.gnu.org/software/make/manual/). 9 | -------------------------------------------------------------------------------- /docs/plugin/menu/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reveal.js-menu", 3 | "version": "2.1.0", 4 | "homepage": "https://denehyg.github.io/reveal.js-menu", 5 | "authors": ["Greg Denehy"], 6 | "description": "A slideout menu for navigating reveal.js presentations", 7 | "keywords": ["reveal", "menu"], 8 | "license": "MIT, Copyright (C) 2020 Greg Denehy", 9 | "ignore": ["**/.*", "node_modules", "bower_components", "test", "tests"] 10 | } 11 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | 3 | AlignEscapedNewlines: DontAlign 4 | AllowShortCaseLabelsOnASingleLine: true 5 | AllowShortFunctionsOnASingleLine: Inline 6 | AllowShortIfStatementsOnASingleLine: true 7 | BreakBeforeBraces: Attach 8 | ColumnLimit: 100 9 | Cpp11BracedListStyle: false 10 | IndentCaseLabels: true 11 | IndentWidth: 4 12 | PointerAlignment: Left 13 | SpaceBeforeParens: Never 14 | TabWidth: 4 15 | UseTab: ForIndentation 16 | 17 | -------------------------------------------------------------------------------- /01/medium.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define N 1024*1024*64 5 | 6 | int main() { 7 | 8 | int sum = 0; 9 | 10 | double startTime = omp_get_wtime(); 11 | 12 | #pragma omp parallel for 13 | for(int i = 0; i < N; ++i) { 14 | #pragma omp atomic 15 | sum++; 16 | } 17 | 18 | double endTime = omp_get_wtime(); 19 | 20 | printf("sum: %d, time: %2.4f seconds\n", sum, endTime-startTime); 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /01/slow.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define N 1024*1024*64 5 | 6 | int main() { 7 | 8 | int sum = 0; 9 | 10 | double startTime = omp_get_wtime(); 11 | 12 | #pragma omp parallel for 13 | for(int i = 0; i < N; ++i) { 14 | #pragma omp critical 15 | sum++; 16 | } 17 | 18 | double endTime = omp_get_wtime(); 19 | 20 | printf("sum: %d, time: %2.4f seconds\n", sum, endTime-startTime); 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /docs/plugin/menu/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | ### Bug Reports 4 | When reporting a bug make sure to include information about which browser and operating system you are on as well as the necessary steps to reproduce the issue. If possible please include a link to a sample presentation where the bug can be tested. 5 | 6 | ### Pull Requests 7 | - Should follow the coding style of the file you work in 8 | - Should be made towards the **dev branch** 9 | - Should be submitted from a feature/topic branch (not your master) 10 | -------------------------------------------------------------------------------- /01/fast.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define N 1024*1024*64 5 | 6 | int main() { 7 | 8 | int sum = 0; 9 | 10 | double startTime = omp_get_wtime(); 11 | 12 | #pragma omp parallel 13 | { 14 | int localSum = 0; 15 | 16 | #pragma omp for 17 | for(int i = 0; i < N; ++i) { 18 | localSum++; 19 | } 20 | 21 | #pragma omp critical 22 | sum += localSum; 23 | } 24 | 25 | double endTime = omp_get_wtime(); 26 | 27 | printf("sum: %d, time: %2.4f seconds\n", sum, endTime-startTime); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /job.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Execute job in the partition "lva" unless you have special requirements. 4 | #SBATCH --partition=lva 5 | # Name your job to be able to identify it later 6 | #SBATCH --job-name test 7 | # Redirect output stream to this file 8 | #SBATCH --output=output.log 9 | # Maximum number of tasks (=processes) to start in total 10 | #SBATCH --ntasks=1 11 | # Maximum number of tasks (=processes) to start per node 12 | #SBATCH --ntasks-per-node=1 13 | # Enforce exclusive node allocation, do not share with other jobs 14 | #SBATCH --exclusive 15 | 16 | /bin/hostname 17 | -------------------------------------------------------------------------------- /docs/plugin/menu/font-awesome/css/brands.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.1.0 by @fontawesome - https://fontawesome.com 3 | * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | @font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:normal;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands"} -------------------------------------------------------------------------------- /docs/plugin/menu/font-awesome/css/solid.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.1.0 by @fontawesome - https://fontawesome.com 3 | * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | @font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.fas{font-family:"Font Awesome 5 Free";font-weight:900} -------------------------------------------------------------------------------- /docs/plugin/menu/font-awesome/css/regular.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.1.0 by @fontawesome - https://fontawesome.com 3 | * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | @font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.far{font-family:"Font Awesome 5 Free";font-weight:400} -------------------------------------------------------------------------------- /13/particle.plt: -------------------------------------------------------------------------------- 1 | set terminal gif animate delay 30 # set gif to animate in a frame delay of 30 ms 2 | set output 'output.gif' # write to the file output.gif 3 | 4 | set style line 2 lc rgb 'black' pt 7 # set line to be a filled circle of color black 5 | stats 'data.dat' nooutput # read data from data.dat file 6 | set xrange [-0.5:100.5] # print data values for x axis from range [-0.5:100.5] 7 | set yrange [-0.5:100.5] # print data values for y axis from range [-0.5:100.5] 8 | set zrange [-0.5:100.5] # print data values for z axis from range [-0.5:100.5] 9 | 10 | do for [i=1:int(STATS_blocks)] { 11 | splot 'data.dat' index (i-1) with points ls 2 ps 0.4 # for each datapoint plot the point 12 | } -------------------------------------------------------------------------------- /05/ex2/ex2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | 6 | int data; 7 | int flag = 0; 8 | 9 | #pragma omp parallel num_threads(2) 10 | { 11 | if (omp_get_thread_num() == 0) { 12 | 13 | data = 42; 14 | 15 | flag = 1; 16 | 17 | } else if(omp_get_thread_num() == 1) { 18 | 19 | int flag_val = 0; 20 | 21 | while (flag_val < 1) { 22 | 23 | flag_val = flag; 24 | 25 | } 26 | 27 | printf("flag=%d data=%d\n", flag, data); 28 | 29 | printf("flag=%d data=%d\n", flag, data); 30 | 31 | } 32 | } 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /03/mandelbrot/mandelbrot.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // Include that allows to print result as an image 7 | #define STB_IMAGE_WRITE_IMPLEMENTATION 8 | #include "stb_image_write.h" 9 | 10 | // Default size of image 11 | #define X 1280 12 | #define Y 720 13 | #define MAX_ITER 10000 14 | 15 | void calc_mandelbrot(uint8_t image[Y][X]) { 16 | // TODO: Write your code here! 17 | } 18 | 19 | int main() { 20 | uint8_t image[Y][X]; 21 | 22 | calc_mandelbrot(image); 23 | 24 | const int channel_nr = 1, stride_bytes = 0; 25 | stbi_write_png("mandelbrot.png", X, Y, channel_nr, image, stride_bytes); 26 | return EXIT_SUCCESS; 27 | } -------------------------------------------------------------------------------- /07/analysis.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define SIZE 1024 4 | 5 | int main(int argc, char** argv) { 6 | 7 | int a[SIZE]; 8 | int b[SIZE]; 9 | 10 | for(int i = 0; i < SIZE; ++i) { 11 | a[i] = argc; 12 | } 13 | 14 | for(int i = 0; i < SIZE; ++i) { 15 | b[i] = a[i]; 16 | } 17 | 18 | for(int i = 4; i < SIZE; ++i) { 19 | a[i-4] = a[i]; 20 | } 21 | 22 | for(int i = 1; i < SIZE-1; ++i) { 23 | a[i] = a[i%argc]; 24 | } 25 | 26 | // output data to prevent compiler from removing any code 27 | for(int i = 0; i < SIZE; ++i) { 28 | printf("%d ", a[i]); 29 | printf("%d ", b[i]); 30 | } 31 | printf("\n"); 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /docs/dist/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v4.0 | 20180602 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | main, menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | font-size: 100%; 23 | font: inherit; 24 | vertical-align: baseline; 25 | } 26 | /* HTML5 display-role reset for older browsers */ 27 | article, aside, details, figcaption, figure, 28 | footer, header, hgroup, main, menu, nav, section { 29 | display: block; 30 | } -------------------------------------------------------------------------------- /docs/plugin/menu/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2020 Greg Denehy 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /docs/plugin/menu/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reveal.js-menu", 3 | "version": "2.1.0", 4 | "description": "A slideout menu for navigating reveal.js presentations", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1", 7 | "build": "gulp" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/denehyg/reveal.js-menu.git" 12 | }, 13 | "keywords": [ 14 | "reveal", 15 | "menu" 16 | ], 17 | "author": "Greg Denehy", 18 | "license": "MIT, Copyright (C) 2020 Greg Denehy", 19 | "bugs": { 20 | "url": "https://github.com/denehyg/reveal.js-menu/issues" 21 | }, 22 | "homepage": "https://github.com/denehyg/reveal.js-menu#readme", 23 | "devDependencies": { 24 | "@babel/core": "^7.10.4", 25 | "@babel/preset-env": "^7.10.4", 26 | "@rollup/plugin-babel": "^5.0.4", 27 | "@rollup/plugin-commonjs": "^13.0.0", 28 | "@rollup/plugin-node-resolve": "^8.1.0", 29 | "babel-plugin-transform-html-import-to-string": "0.0.1", 30 | "core-js": "^3.6.5", 31 | "gulp": "^4.0.2", 32 | "rollup": "^2.21.0", 33 | "rollup-plugin-terser": "^6.1.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /docs/plugin/highlight/monokai.css: -------------------------------------------------------------------------------- 1 | /* 2 | Monokai style - ported by Luigi Maselli - http://grigio.org 3 | */ 4 | 5 | .hljs { 6 | display: block; 7 | overflow-x: auto; 8 | padding: 0.5em; 9 | background: #272822; 10 | color: #ddd; 11 | } 12 | 13 | .hljs-tag, 14 | .hljs-keyword, 15 | .hljs-selector-tag, 16 | .hljs-literal, 17 | .hljs-strong, 18 | .hljs-name { 19 | color: #f92672; 20 | } 21 | 22 | .hljs-code { 23 | color: #66d9ef; 24 | } 25 | 26 | .hljs-class .hljs-title { 27 | color: white; 28 | } 29 | 30 | .hljs-attribute, 31 | .hljs-symbol, 32 | .hljs-regexp, 33 | .hljs-link { 34 | color: #bf79db; 35 | } 36 | 37 | .hljs-string, 38 | .hljs-bullet, 39 | .hljs-subst, 40 | .hljs-title, 41 | .hljs-section, 42 | .hljs-emphasis, 43 | .hljs-type, 44 | .hljs-built_in, 45 | .hljs-builtin-name, 46 | .hljs-selector-attr, 47 | .hljs-selector-pseudo, 48 | .hljs-addition, 49 | .hljs-variable, 50 | .hljs-template-tag, 51 | .hljs-template-variable { 52 | color: #a6e22e; 53 | } 54 | 55 | .hljs-comment, 56 | .hljs-quote, 57 | .hljs-deletion, 58 | .hljs-meta { 59 | color: #75715e; 60 | } 61 | 62 | .hljs-keyword, 63 | .hljs-selector-tag, 64 | .hljs-literal, 65 | .hljs-doctag, 66 | .hljs-title, 67 | .hljs-section, 68 | .hljs-type, 69 | .hljs-selector-id { 70 | font-weight: bold; 71 | } 72 | -------------------------------------------------------------------------------- /docs/plugin/highlight/zenburn.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Zenburn style from voldmar.ru (c) Vladimir Epifanov 4 | based on dark.css by Ivan Sagalaev 5 | 6 | */ 7 | 8 | .hljs { 9 | display: block; 10 | overflow-x: auto; 11 | padding: 0.5em; 12 | background: #3f3f3f; 13 | color: #dcdcdc; 14 | } 15 | 16 | .hljs-keyword, 17 | .hljs-selector-tag, 18 | .hljs-tag { 19 | color: #e3ceab; 20 | } 21 | 22 | .hljs-template-tag { 23 | color: #dcdcdc; 24 | } 25 | 26 | .hljs-number { 27 | color: #8cd0d3; 28 | } 29 | 30 | .hljs-variable, 31 | .hljs-template-variable, 32 | .hljs-attribute { 33 | color: #efdcbc; 34 | } 35 | 36 | .hljs-literal { 37 | color: #efefaf; 38 | } 39 | 40 | .hljs-subst { 41 | color: #8f8f8f; 42 | } 43 | 44 | .hljs-title, 45 | .hljs-name, 46 | .hljs-selector-id, 47 | .hljs-selector-class, 48 | .hljs-section, 49 | .hljs-type { 50 | color: #efef8f; 51 | } 52 | 53 | .hljs-symbol, 54 | .hljs-bullet, 55 | .hljs-link { 56 | color: #dca3a3; 57 | } 58 | 59 | .hljs-deletion, 60 | .hljs-string, 61 | .hljs-built_in, 62 | .hljs-builtin-name { 63 | color: #cc9393; 64 | } 65 | 66 | .hljs-addition, 67 | .hljs-comment, 68 | .hljs-quote, 69 | .hljs-meta { 70 | color: #7f9f7f; 71 | } 72 | 73 | 74 | .hljs-emphasis { 75 | font-style: italic; 76 | } 77 | 78 | .hljs-strong { 79 | font-weight: bold; 80 | } 81 | -------------------------------------------------------------------------------- /docs/dist/theme/fonts/source-sans-pro/source-sans-pro.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Source Sans Pro'; 3 | src: url('./source-sans-pro-regular.eot'); 4 | src: url('./source-sans-pro-regular.eot?#iefix') format('embedded-opentype'), 5 | url('./source-sans-pro-regular.woff') format('woff'), 6 | url('./source-sans-pro-regular.ttf') format('truetype'); 7 | font-weight: normal; 8 | font-style: normal; 9 | } 10 | 11 | @font-face { 12 | font-family: 'Source Sans Pro'; 13 | src: url('./source-sans-pro-italic.eot'); 14 | src: url('./source-sans-pro-italic.eot?#iefix') format('embedded-opentype'), 15 | url('./source-sans-pro-italic.woff') format('woff'), 16 | url('./source-sans-pro-italic.ttf') format('truetype'); 17 | font-weight: normal; 18 | font-style: italic; 19 | } 20 | 21 | @font-face { 22 | font-family: 'Source Sans Pro'; 23 | src: url('./source-sans-pro-semibold.eot'); 24 | src: url('./source-sans-pro-semibold.eot?#iefix') format('embedded-opentype'), 25 | url('./source-sans-pro-semibold.woff') format('woff'), 26 | url('./source-sans-pro-semibold.ttf') format('truetype'); 27 | font-weight: 600; 28 | font-style: normal; 29 | } 30 | 31 | @font-face { 32 | font-family: 'Source Sans Pro'; 33 | src: url('./source-sans-pro-semibolditalic.eot'); 34 | src: url('./source-sans-pro-semibolditalic.eot?#iefix') format('embedded-opentype'), 35 | url('./source-sans-pro-semibolditalic.woff') format('woff'), 36 | url('./source-sans-pro-semibolditalic.ttf') format('truetype'); 37 | font-weight: 600; 38 | font-style: italic; 39 | } 40 | -------------------------------------------------------------------------------- /docs/plugin/menu/font-awesome/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Font Awesome Free License 2 | ------------------------- 3 | 4 | Font Awesome Free is free, open source, and GPL friendly. You can use it for 5 | commercial projects, open source projects, or really almost whatever you want. 6 | Full Font Awesome Free license: https://fontawesome.com/license. 7 | 8 | # Icons: CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/) 9 | In the Font Awesome Free download, the CC BY 4.0 license applies to all icons 10 | packaged as SVG and JS file types. 11 | 12 | # Fonts: SIL OFL 1.1 License (https://scripts.sil.org/OFL) 13 | In the Font Awesome Free download, the SIL OLF license applies to all icons 14 | packaged as web and desktop font files. 15 | 16 | # Code: MIT License (https://opensource.org/licenses/MIT) 17 | In the Font Awesome Free download, the MIT license applies to all non-font and 18 | non-icon files. 19 | 20 | # Attribution 21 | Attribution is required by MIT, SIL OLF, and CC BY licenses. Downloaded Font 22 | Awesome Free files already contain embedded comments with sufficient 23 | attribution, so you shouldn't need to do anything additional when using these 24 | files normally. 25 | 26 | We've kept attribution comments terse, so we ask that you do not actively work 27 | to remove them from files, especially code. They're a great way for folks to 28 | learn about Font Awesome. 29 | 30 | # Brand Icons 31 | All brand icons are trademarks of their respective owners. The use of these 32 | trademarks does not indicate endorsement of the trademark holder by Font 33 | Awesome, nor vice versa. **Please do not use brand logos for any purpose except 34 | to represent the company, product, or service to which they refer.** 35 | -------------------------------------------------------------------------------- /05/README.md: -------------------------------------------------------------------------------- 1 | # Assignment 5 2 | 3 | The goal of this assignment is to expand your knowledge on and familiarity with OpenMP. 4 | 5 | ## Exercise 1 (1.5 Points) 6 | 7 | ### Description 8 | 9 | This exercise deals with performance analysis and improvement of a given code [ex1/ex1.c](ex1/ex1.c). The program reads a matrix size n from the command-line. Then two square matrices a and b of size n\*n are filled with random numbers. Finally, the program should print the sum of all elements of matrix c and the wall clock time after the matrix multiplication c=a\*b was conducted. 10 | 11 | ### Tasks 12 | 13 | 1) Are there any (performance) issues in the given code? Document your findings. 14 | 2) Improve the performance of the given source code. 15 | 3) Benchmark your modification of the code and the original implementation with 1, 2, 4, 6, and 12 threads on LCC3 using n=1,500. Has your effort paid off? 16 | 4) Enter your shortest wall clock time for 12 threads and n=1,500 on LCC3 to the comparison spreadsheet linked on Discord. 17 | 18 | ## Exercise 2 (1.5 Points) 19 | 20 | ### Description 21 | 22 | This exercise deals with the OpenMP flush directive and why it can be necessary. 23 | 24 | ### Tasks 25 | 26 | 1) Examine [ex2/ex2.c](ex2/ex2.c) and explain what the code does from an abstract, high-level perspective. What should happen here? 27 | 2) Compile this code with optimization level `-O3`. Run it in an interactive job (e.g. using `salloc --exclusive --tasks-per-node=1 --cpus-per-task=1 srun --pty bash`) in a loop many times (e.g. write a loop in bash that executes it 1000 times). Run this loop repeatedly. What can you observe? **Note: Please quit your interactive job once you are done!** 28 | 3) Does this code require any `#pragma omp flush` and/or `#pragma omp atomic` directives? If it does, where are they necessary? If it does not, why not? 29 | 30 | ## General Notes 31 | 32 | All the material required by the tasks above (e.g., code, figures, text, etc...) must be part of the solution that is handed in. Your experiments should be reproducible and comparable to your measurements using the solution materials that you hand in. 33 | 34 | **Every** member of your group must be able to explain the given problem, your solution, and possible findings. You may also need to answer detailed questions about any of these aspects. 35 | -------------------------------------------------------------------------------- /docs/plugin/math/mathjax2.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A plugin which enables rendering of math equations inside 3 | * of reveal.js slides. Essentially a thin wrapper for MathJax. 4 | * 5 | * @author Hakim El Hattab 6 | */ 7 | export const MathJax2 = () => { 8 | 9 | // The reveal.js instance this plugin is attached to 10 | let deck; 11 | 12 | let defaultOptions = { 13 | messageStyle: 'none', 14 | tex2jax: { 15 | inlineMath: [ [ '$', '$' ], [ '\\(', '\\)' ] ], 16 | skipTags: [ 'script', 'noscript', 'style', 'textarea', 'pre' ] 17 | }, 18 | skipStartupTypeset: true 19 | }; 20 | 21 | function loadScript( url, callback ) { 22 | 23 | let head = document.querySelector( 'head' ); 24 | let script = document.createElement( 'script' ); 25 | script.type = 'text/javascript'; 26 | script.src = url; 27 | 28 | // Wrapper for callback to make sure it only fires once 29 | let finish = () => { 30 | if( typeof callback === 'function' ) { 31 | callback.call(); 32 | callback = null; 33 | } 34 | } 35 | 36 | script.onload = finish; 37 | 38 | // IE 39 | script.onreadystatechange = () => { 40 | if ( this.readyState === 'loaded' ) { 41 | finish(); 42 | } 43 | } 44 | 45 | // Normal browsers 46 | head.appendChild( script ); 47 | 48 | } 49 | 50 | return { 51 | id: 'mathjax2', 52 | 53 | init: function( reveal ) { 54 | 55 | deck = reveal; 56 | 57 | let revealOptions = deck.getConfig().mathjax2 || deck.getConfig().math || {}; 58 | 59 | let options = { ...defaultOptions, ...revealOptions }; 60 | let mathjax = options.mathjax || 'https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js'; 61 | let config = options.config || 'TeX-AMS_HTML-full'; 62 | let url = mathjax + '?config=' + config; 63 | 64 | options.tex2jax = { ...defaultOptions.tex2jax, ...revealOptions.tex2jax }; 65 | 66 | options.mathjax = options.config = null; 67 | 68 | loadScript( url, function() { 69 | 70 | MathJax.Hub.Config( options ); 71 | 72 | // Typeset followed by an immediate reveal.js layout since 73 | // the typesetting process could affect slide height 74 | MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, deck.getRevealElement() ] ); 75 | MathJax.Hub.Queue( deck.layout ); 76 | 77 | // Reprocess equations in slides when they turn visible 78 | deck.on( 'slidechanged', function( event ) { 79 | 80 | MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, event.currentSlide ] ); 81 | 82 | } ); 83 | 84 | } ); 85 | 86 | } 87 | } 88 | 89 | }; 90 | -------------------------------------------------------------------------------- /11/README.md: -------------------------------------------------------------------------------- 1 | # Assignment 11 2 | The goal of this assignment is to parallelize an unknown application using profiling and OpenMP. 3 | 4 | ## Exercise 1 (1 Point) 5 | 6 | ### Description 7 | 8 | The file [real.tar.gz](real.tar.gz) contains a realistic implementation of a (simple) numerical algorithm. Imagine you are tasked with making this implementation faster by parallelizing it with OpenMP, without any further information. To that end, this exercise consists in analysing the performance of this application with a sample-based profiler, in order to figure out where to start with the parallelization. For simplicity, we recommend using `gprof`, but you can also use another profile of your choice, if you prefer. 9 | 10 | As an example, using `gprof` requires three steps: First, the application needs to be compiled with `gcc` and the flag `-pg`. This causes the compiler to put instrumentation code in the executable. Then, run the application normally, which will produce a new file `gmon.out`. Finally, run `gprof gmon.out > analysis.txt` in order to obtain the analysis results. Add the `--line` flag to `gprof` if you need more fine-grained information. 11 | 12 | ### Tasks 13 | 14 | - Obtain a performance profile of the given application by following the steps outlined above. 15 | - Discuss the performance profile. What information does it hold and how/why is this useful? 16 | 17 | ## Exercise 2 (2 Points) 18 | 19 | ### Description 20 | 21 | Now that we have a performance profile, we actually need to parallelize the application with OpenMP. 22 | 23 | ### Tasks 24 | 25 | - Investigate any loops that carry larger workloads and determine if and how they can be parallelized. Parallelize them with OpenMP. Ensure that any code modification does not violate program correctness with respect to its output. 26 | - Benchmark the original, sequential program and your parallelized version for 1, 2, 6 and 12 threads on LCC3, discuss the results and enter the data in the comparison spreadsheet linked on Discord. 27 | 28 | ## General Notes 29 | 30 | All the material required by the tasks above (e.g., code, figures, text, etc...) must be part of the solution that is handed in. Your experiments should be reproducible and comparable to your measurements using the solution materials that you hand in. 31 | 32 | **Every** member of your group must be able to explain the given problem, your solution, and possible findings. You may also need to answer detailed questions about any of these aspects. 33 | -------------------------------------------------------------------------------- /docs/plugin/math/mathjax3.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A plugin which enables rendering of math equations inside 3 | * of reveal.js slides. Essentially a thin wrapper for MathJax 3 4 | * 5 | * @author Hakim El Hattab 6 | * @author Gerhard Burger 7 | */ 8 | export const MathJax3 = () => { 9 | 10 | // The reveal.js instance this plugin is attached to 11 | let deck; 12 | 13 | let defaultOptions = { 14 | tex: { 15 | inlineMath: [ [ '$', '$' ], [ '\\(', '\\)' ] ] 16 | }, 17 | options: { 18 | skipHtmlTags: [ 'script', 'noscript', 'style', 'textarea', 'pre' ] 19 | }, 20 | startup: { 21 | ready: () => { 22 | MathJax.startup.defaultReady(); 23 | MathJax.startup.promise.then(() => { 24 | Reveal.layout(); 25 | }); 26 | } 27 | } 28 | }; 29 | 30 | function loadScript( url, callback ) { 31 | 32 | let script = document.createElement( 'script' ); 33 | script.type = "text/javascript" 34 | script.id = "MathJax-script" 35 | script.src = url; 36 | script.async = true 37 | 38 | // Wrapper for callback to make sure it only fires once 39 | script.onload = () => { 40 | if (typeof callback === 'function') { 41 | callback.call(); 42 | callback = null; 43 | } 44 | }; 45 | 46 | document.head.appendChild( script ); 47 | 48 | } 49 | 50 | return { 51 | id: 'mathjax3', 52 | init: function(reveal) { 53 | 54 | deck = reveal; 55 | 56 | let revealOptions = deck.getConfig().mathjax3 || {}; 57 | let options = {...defaultOptions, ...revealOptions}; 58 | options.tex = {...defaultOptions.tex, ...revealOptions.tex} 59 | options.options = {...defaultOptions.options, ...revealOptions.options} 60 | options.startup = {...defaultOptions.startup, ...revealOptions.startup} 61 | 62 | let url = options.mathjax || 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js'; 63 | options.mathjax = null; 64 | 65 | window.MathJax = options; 66 | 67 | loadScript( url, function() { 68 | // Reprocess equations in slides when they turn visible 69 | Reveal.addEventListener( 'slidechanged', function( event ) { 70 | MathJax.typeset(); 71 | } ); 72 | } ); 73 | 74 | } 75 | } 76 | 77 | }; 78 | -------------------------------------------------------------------------------- /08/README.md: -------------------------------------------------------------------------------- 1 | # Assignment 8 2 | 3 | The goal of this assignment is to gain more experience in parallelizing programs with OpenMP. 4 | 5 | ## Exercise 1 (1.5 Points) 6 | 7 | ### Description 8 | 9 | This exercise consists of exploring the effects of OpenMP thread affinity. 10 | 11 | ### Tasks 12 | 13 | 1) Write an OpenMP program that atomically increments an `int` using `#pragma omp atomic` in a parallel for loop for a large number of iterations, i.e. such that the program takes at least 2 seconds to execute. Have the program print the time required to process the entire loop. Compile your program with gcc 12.2.0 and optimization level `-O3`. Do not perform any manual optimizations such as reducing the number of atomic operations. 14 | 2) Run your program with 6 threads. Explore the affinity features of OpenMP 4.0 to change the way threads are mapped to cores, e.g. using a single CPU only or using both CPUs. Explain the affinity settings that you chose. 15 | 3) Benchmark your program with these affinity settings. What can you observe? 16 | 4) Enter the time for N=500.000.000 into the comparison spreadsheet linked on Discord. 17 | 18 | ## Exercise 2 (1.5 Points) 19 | 20 | ### Description 21 | 22 | This exercise consists of extending the Hadamard product implementation of the previous assignment. 23 | 24 | ### Tasks 25 | 26 | 1) Implement a parallel version of the Hadamard product using OpenMP. Use the snippet below as sequential implementation. 27 | 28 | ```c 29 | for (size_t i = 0; i < n; ++i) { 30 | for (size_t j = 0; j < n; ++j) { 31 | c[i][j] = a[i][j] * b[i][j]; 32 | } 33 | } 34 | ``` 35 | 36 | 2) Benchmark your serial implementations and your parallel implementations with 1, 2, 4, 6 and 12 threads on LCC3 using N=10.000², 20.000² and 30.000². Use OpenMP's time measurement function to measure only the computational loop. 37 | 3) Use the 3 loop scheduling methods discussed in the lecture, `static`, `dynamic` and `guided`. Explain their differences and compare their performance for the two code snippets. What can you observe? 38 | 4) In addition, try the loop scheduling methods `auto` and `runtime`. What do they do, what can you observe? 39 | 5) Enter the time for N=65.536² into the comparison spreadsheet linked on Discord. 40 | 41 | ## General Notes 42 | 43 | All the material required by the tasks above (e.g., code, figures, text, etc...) must be part of the solution that is handed in. Your experiments should be reproducible and comparable to your measurements using the solution materials that you hand in. 44 | 45 | **Every** member of your group must be able to explain the given problem, your solution, and possible findings. You may also need to answer detailed questions about any of these aspects. 46 | -------------------------------------------------------------------------------- /06/README.md: -------------------------------------------------------------------------------- 1 | # Assignment 6 2 | 3 | ## Exercise 1 (1 Point) 4 | 5 | ### Description 6 | 7 | Consider the following individual code snippets, and analyze them regarding dependencies. 8 | 9 | ```c 10 | for (int i=0; i < n-1; i++) { 11 | x[i] = (y[i] + x[i+1]) / 7; 12 | } 13 | ``` 14 | 15 | ```c 16 | for (int i=0; i < n; i++) { 17 | a = (x[i] + y[i]) / (i+1); 18 | z[i] = a; 19 | } 20 | 21 | f = sqrt(a + k); 22 | ``` 23 | 24 | ```c 25 | for (int i=0; i < n; i++) { 26 | x[i] = y[i] * 2 + b * i; 27 | } 28 | 29 | 30 | for (int i=0; i < n; i++) { 31 | y[i] = x[i] + a / (i+1); 32 | } 33 | ``` 34 | 35 | ### Tasks 36 | 37 | Regarding each snippet 38 | 39 | 1) What are the data dependencies? 40 | 2) Parallelize and optimize the code 41 | 42 | ## Exercise 2 (1 Point) 43 | 44 | ### Description 45 | 46 | In this exercise we try to parallelize loops which have data dependencies. 47 | Look at the following individual code snippets. 48 | a) 49 | 50 | ```c 51 | double factor = 1; 52 | 53 | for (int i=0; i < n; i++) { 54 | x[i] = factor * y[i]; 55 | factor = factor / 2; 56 | } 57 | ``` 58 | 59 | b) 60 | 61 | ```c 62 | for (int i = 1; i { 61 | return Promise.all( 62 | [ 63 | { 64 | name: 'RevealMenu', 65 | input: './plugin.js', 66 | output: './menu' 67 | } 68 | ].map(plugin => { 69 | return rollup({ 70 | cache: cache[plugin.input], 71 | input: plugin.input, 72 | plugins: [ 73 | resolve(), 74 | commonjs(), 75 | babel({ 76 | ...babelConfig, 77 | ignore: [/node_modules\/.*/] 78 | }), 79 | terser() 80 | ] 81 | }).then(bundle => { 82 | cache[plugin.input] = bundle.cache; 83 | bundle.write({ 84 | file: plugin.output + '.esm.js', 85 | name: plugin.name, 86 | format: 'es' 87 | }); 88 | 89 | bundle.write({ 90 | file: plugin.output + '.js', 91 | name: plugin.name, 92 | format: 'umd' 93 | }); 94 | }); 95 | }) 96 | ); 97 | }); 98 | 99 | gulp.task('default', gulp.series('build')); 100 | -------------------------------------------------------------------------------- /docs/plugin/search/search.esm.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Handles finding a text string anywhere in the slides and showing the next occurrence to the user 3 | * by navigatating to that slide and highlighting it. 4 | * 5 | * @author Jon Snyder , February 2013 6 | */ 7 | export default()=>{let e,t,n,l,i,o,r;function s(){t=document.createElement("div"),t.classList.add("searchbox"),t.style.position="absolute",t.style.top="10px",t.style.right="10px",t.style.zIndex=10,t.innerHTML='\n\t\t',n=t.querySelector(".searchinput"),n.style.width="240px",n.style.fontSize="14px",n.style.padding="4px 6px",n.style.color="#000",n.style.background="#fff",n.style.borderRadius="2px",n.style.border="0",n.style.outline="0",n.style.boxShadow="0 2px 18px rgba(0, 0, 0, 0.2)",n.style["-webkit-appearance"]="none",e.getRevealElement().appendChild(t),n.addEventListener("keyup",(function(t){if(13===t.keyCode)t.preventDefault(),function(){if(o){var t=n.value;""===t?(r&&r.remove(),l=null):(r=new c("slidecontent"),l=r.apply(t),i=0)}l&&(l.length&&l.length<=i&&(i=0),l.length>i&&(e.slide(l[i].h,l[i].v),i++))}(),o=!1;else o=!0}),!1),d()}function a(){t||s(),t.style.display="inline",n.focus(),n.select()}function d(){t||s(),t.style.display="none",r&&r.remove()}function c(t,n){var l=document.getElementById(t)||document.body,i=n||"EM",o=new RegExp("^(?:"+i+"|SCRIPT|FORM)$"),r=["#ff6","#a0ffff","#9f9","#f99","#f6f"],s=[],a=0,d="",c=[];this.setRegex=function(e){e=e.replace(/^[^\w]+|[^\w]+$/g,"").replace(/[^\w'-]+/g,"|"),d=new RegExp("("+e+")","i")},this.getRegex=function(){return d.toString().replace(/^\/\\b\(|\)\\b\/i$/g,"").replace(/\|/g," ")},this.hiliteWords=function(t){if(null!=t&&t&&d&&!o.test(t.nodeName)){if(t.hasChildNodes())for(var n=0;n{e=n,e.registerKeyboardShortcut("CTRL + Shift + F","Search"),document.addEventListener("keydown",(function(e){"F"==e.key&&(e.ctrlKey||e.metaKey)&&(e.preventDefault(),t||s(),"inline"!==t.style.display?a():d())}),!1)},open:a}}; 8 | -------------------------------------------------------------------------------- /docs/plugin/zoom/zoom.esm.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * reveal.js Zoom plugin 3 | */ 4 | const e={id:"zoom",init:function(e){e.getRevealElement().addEventListener("mousedown",(function(o){var n=/Linux/.test(window.navigator.platform)?"ctrl":"alt",i=(e.getConfig().zoomKey?e.getConfig().zoomKey:n)+"Key",d=e.getConfig().zoomLevel?e.getConfig().zoomLevel:2;o[i]&&!e.isOverview()&&(o.preventDefault(),t.to({x:o.clientX,y:o.clientY,scale:d,pan:!1}))}))},destroy:()=>{t.reset()}};var t=function(){var e=1,o=0,n=0,i=-1,d=-1,l="transform"in document.body.style;function s(t,o){var n=r();if(t.width=t.width||1,t.height=t.height||1,t.x-=(window.innerWidth-t.width*o)/2,t.y-=(window.innerHeight-t.height*o)/2,l)if(1===o)document.body.style.transform="";else{var i=n.x+"px "+n.y+"px",d="translate("+-t.x+"px,"+-t.y+"px) scale("+o+")";document.body.style.transformOrigin=i,document.body.style.transform=d}else 1===o?(document.body.style.position="",document.body.style.left="",document.body.style.top="",document.body.style.width="",document.body.style.height="",document.body.style.zoom=""):(document.body.style.position="relative",document.body.style.left=-(n.x+t.x)/o+"px",document.body.style.top=-(n.y+t.y)/o+"px",document.body.style.width=100*o+"%",document.body.style.height=100*o+"%",document.body.style.zoom=o);e=o,document.documentElement.classList&&(1!==e?document.documentElement.classList.add("zoomed"):document.documentElement.classList.remove("zoomed"))}function c(){var t=.12*window.innerWidth,i=.12*window.innerHeight,d=r();nwindow.innerHeight-i&&window.scroll(d.x,d.y+(1-(window.innerHeight-n)/i)*(14/e)),owindow.innerWidth-t&&window.scroll(d.x+(1-(window.innerWidth-o)/t)*(14/e),d.y)}function r(){return{x:void 0!==window.scrollX?window.scrollX:window.pageXOffset,y:void 0!==window.scrollY?window.scrollY:window.pageYOffset}}return l&&(document.body.style.transition="transform 0.8s ease"),document.addEventListener("keyup",(function(o){1!==e&&27===o.keyCode&&t.out()})),document.addEventListener("mousemove",(function(t){1!==e&&(o=t.clientX,n=t.clientY)})),{to:function(o){if(1!==e)t.out();else{if(o.x=o.x||0,o.y=o.y||0,o.element){var n=o.element.getBoundingClientRect();o.x=n.left-20,o.y=n.top-20,o.width=n.width+40,o.height=n.height+40}void 0!==o.width&&void 0!==o.height&&(o.scale=Math.max(Math.min(window.innerWidth/o.width,window.innerHeight/o.height),1)),o.scale>1&&(o.x*=o.scale,o.y*=o.scale,s(o,o.scale),!1!==o.pan&&(i=setTimeout((function(){d=setInterval(c,1e3/60)}),800)))}},out:function(){clearTimeout(i),clearInterval(d),s({x:0,y:0},1),e=1},magnify:function(e){this.to(e)},reset:function(){this.out()},zoomLevel:function(){return e}}}(); 5 | /*! 6 | * zoom.js 0.3 (modified for use with reveal.js) 7 | * http://lab.hakim.se/zoom-js 8 | * MIT licensed 9 | * 10 | * Copyright (C) 2011-2014 Hakim El Hattab, http://hakim.se 11 | */export default()=>e; 12 | -------------------------------------------------------------------------------- /docs/plugin/math/katex.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A plugin which enables rendering of math equations inside 3 | * of reveal.js slides. Essentially a thin wrapper for KaTeX. 4 | * 5 | * @author Hakim El Hattab 6 | * @author Gerhard Burger 7 | */ 8 | export const KaTeX = () => { 9 | let deck; 10 | 11 | let defaultOptions = { 12 | version: 'latest', 13 | delimiters: [ 14 | {left: '$$', right: '$$', display: true}, // Note: $$ has to come before $ 15 | {left: '$', right: '$', display: false}, 16 | {left: '\\(', right: '\\)', display: false}, 17 | {left: '\\[', right: '\\]', display: true} 18 | ], 19 | ignoredTags: ['script', 'noscript', 'style', 'textarea', 'pre'] 20 | } 21 | 22 | const loadCss = src => { 23 | let link = document.createElement('link'); 24 | link.rel = 'stylesheet'; 25 | link.href = src; 26 | document.head.appendChild(link); 27 | }; 28 | 29 | /** 30 | * Loads a JavaScript file and returns a Promise for when it is loaded 31 | * Credits: https://aaronsmith.online/easily-load-an-external-script-using-javascript/ 32 | */ 33 | const loadScript = src => { 34 | return new Promise((resolve, reject) => { 35 | const script = document.createElement('script') 36 | script.type = 'text/javascript' 37 | script.onload = resolve 38 | script.onerror = reject 39 | script.src = src 40 | document.head.append(script) 41 | }) 42 | }; 43 | 44 | async function loadScripts(urls) { 45 | for(const url of urls) { 46 | await loadScript(url); 47 | } 48 | } 49 | 50 | return { 51 | id: 'katex', 52 | 53 | init: function (reveal) { 54 | 55 | deck = reveal; 56 | 57 | let revealOptions = deck.getConfig().katex || {}; 58 | 59 | let options = {...defaultOptions, ...revealOptions}; 60 | const {local, version, extensions, ...katexOptions} = options; 61 | 62 | let baseUrl = options.local || 'https://cdn.jsdelivr.net/npm/katex'; 63 | let versionString = options.local ? '' : '@' + options.version; 64 | 65 | let cssUrl = baseUrl + versionString + '/dist/katex.min.css'; 66 | let katexUrl = baseUrl + versionString + '/dist/katex.min.js'; 67 | let mhchemUrl = baseUrl + versionString + '/dist/contrib/mhchem.min.js' 68 | let karUrl = baseUrl + versionString + '/dist/contrib/auto-render.min.js'; 69 | 70 | let katexScripts = [katexUrl]; 71 | if(options.extensions && options.extensions.includes("mhchem")) { 72 | katexScripts.push(mhchemUrl); 73 | } 74 | katexScripts.push(karUrl); 75 | 76 | const renderMath = () => { 77 | renderMathInElement(reveal.getSlidesElement(), katexOptions); 78 | deck.layout(); 79 | } 80 | 81 | loadCss(cssUrl); 82 | 83 | // For some reason dynamically loading with defer attribute doesn't result in the expected behavior, the below code does 84 | loadScripts(katexScripts).then(() => { 85 | if( deck.isReady() ) { 86 | renderMath(); 87 | } 88 | else { 89 | deck.on( 'ready', renderMath.bind( this ) ); 90 | } 91 | }); 92 | 93 | } 94 | } 95 | 96 | }; 97 | -------------------------------------------------------------------------------- /docs/plugin/math/math.esm.js: -------------------------------------------------------------------------------- 1 | const t=()=>{let t,e={messageStyle:"none",tex2jax:{inlineMath:[["$","$"],["\\(","\\)"]],skipTags:["script","noscript","style","textarea","pre"]},skipStartupTypeset:!0};return{id:"mathjax2",init:function(a){t=a;let n=t.getConfig().mathjax2||t.getConfig().math||{},i={...e,...n},s=(i.mathjax||"https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js")+"?config="+(i.config||"TeX-AMS_HTML-full");i.tex2jax={...e.tex2jax,...n.tex2jax},i.mathjax=i.config=null,function(t,e){let a=document.querySelector("head"),n=document.createElement("script");n.type="text/javascript",n.src=t;let i=()=>{"function"==typeof e&&(e.call(),e=null)};n.onload=i,n.onreadystatechange=()=>{"loaded"===this.readyState&&i()},a.appendChild(n)}(s,(function(){MathJax.Hub.Config(i),MathJax.Hub.Queue(["Typeset",MathJax.Hub,t.getRevealElement()]),MathJax.Hub.Queue(t.layout),t.on("slidechanged",(function(t){MathJax.Hub.Queue(["Typeset",MathJax.Hub,t.currentSlide])}))}))}}},e=t; 2 | /*! 3 | * This plugin is a wrapper for the MathJax2, 4 | * MathJax3 and KaTeX typesetter plugins. 5 | */ 6 | var a=Plugin=Object.assign(e(),{KaTeX:()=>{let t,e={version:"latest",delimiters:[{left:"$$",right:"$$",display:!0},{left:"$",right:"$",display:!1},{left:"\\(",right:"\\)",display:!1},{left:"\\[",right:"\\]",display:!0}],ignoredTags:["script","noscript","style","textarea","pre"]};const a=t=>new Promise(((e,a)=>{const n=document.createElement("script");n.type="text/javascript",n.onload=e,n.onerror=a,n.src=t,document.head.append(n)}));return{id:"katex",init:function(n){t=n;let i=t.getConfig().katex||{},s={...e,...i};const{local:l,version:o,extensions:r,...c}=s;let d=s.local||"https://cdn.jsdelivr.net/npm/katex",p=s.local?"":"@"+s.version,u=d+p+"/dist/katex.min.css",h=d+p+"/dist/contrib/mhchem.min.js",x=d+p+"/dist/contrib/auto-render.min.js",m=[d+p+"/dist/katex.min.js"];s.extensions&&s.extensions.includes("mhchem")&&m.push(h),m.push(x);const f=()=>{renderMathInElement(n.getSlidesElement(),c),t.layout()};(t=>{let e=document.createElement("link");e.rel="stylesheet",e.href=t,document.head.appendChild(e)})(u),async function(t){for(const e of t)await a(e)}(m).then((()=>{t.isReady()?f():t.on("ready",f.bind(this))}))}}},MathJax2:t,MathJax3:()=>{let t,e={tex:{inlineMath:[["$","$"],["\\(","\\)"]]},options:{skipHtmlTags:["script","noscript","style","textarea","pre"]},startup:{ready:()=>{MathJax.startup.defaultReady(),MathJax.startup.promise.then((()=>{Reveal.layout()}))}}};return{id:"mathjax3",init:function(a){t=a;let n=t.getConfig().mathjax3||{},i={...e,...n};i.tex={...e.tex,...n.tex},i.options={...e.options,...n.options},i.startup={...e.startup,...n.startup};let s=i.mathjax||"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js";i.mathjax=null,window.MathJax=i,function(t,e){let a=document.createElement("script");a.type="text/javascript",a.id="MathJax-script",a.src=t,a.async=!0,a.onload=()=>{"function"==typeof e&&(e.call(),e=null)},document.head.appendChild(a)}(s,(function(){Reveal.addEventListener("slidechanged",(function(t){MathJax.typeset()}))}))}}}});export default a; 7 | -------------------------------------------------------------------------------- /docs/plugin/search/search.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).RevealSearch=t()}(this,(function(){"use strict"; 2 | /*! 3 | * Handles finding a text string anywhere in the slides and showing the next occurrence to the user 4 | * by navigatating to that slide and highlighting it. 5 | * 6 | * @author Jon Snyder , February 2013 7 | */return()=>{let e,t,n,l,o,i,r;function s(){t=document.createElement("div"),t.classList.add("searchbox"),t.style.position="absolute",t.style.top="10px",t.style.right="10px",t.style.zIndex=10,t.innerHTML='\n\t\t',n=t.querySelector(".searchinput"),n.style.width="240px",n.style.fontSize="14px",n.style.padding="4px 6px",n.style.color="#000",n.style.background="#fff",n.style.borderRadius="2px",n.style.border="0",n.style.outline="0",n.style.boxShadow="0 2px 18px rgba(0, 0, 0, 0.2)",n.style["-webkit-appearance"]="none",e.getRevealElement().appendChild(t),n.addEventListener("keyup",(function(t){if(13===t.keyCode)t.preventDefault(),function(){if(i){var t=n.value;""===t?(r&&r.remove(),l=null):(r=new c("slidecontent"),l=r.apply(t),o=0)}l&&(l.length&&l.length<=o&&(o=0),l.length>o&&(e.slide(l[o].h,l[o].v),o++))}(),i=!1;else i=!0}),!1),d()}function a(){t||s(),t.style.display="inline",n.focus(),n.select()}function d(){t||s(),t.style.display="none",r&&r.remove()}function c(t,n){var l=document.getElementById(t)||document.body,o=n||"EM",i=new RegExp("^(?:"+o+"|SCRIPT|FORM)$"),r=["#ff6","#a0ffff","#9f9","#f99","#f6f"],s=[],a=0,d="",c=[];this.setRegex=function(e){e=e.replace(/^[^\w]+|[^\w]+$/g,"").replace(/[^\w'-]+/g,"|"),d=new RegExp("("+e+")","i")},this.getRegex=function(){return d.toString().replace(/^\/\\b\(|\)\\b\/i$/g,"").replace(/\|/g," ")},this.hiliteWords=function(t){if(null!=t&&t&&d&&!i.test(t.nodeName)){if(t.hasChildNodes())for(var n=0;n{e=n,e.registerKeyboardShortcut("CTRL + Shift + F","Search"),document.addEventListener("keydown",(function(e){"F"==e.key&&(e.ctrlKey||e.metaKey)&&(e.preventDefault(),t||s(),"inline"!==t.style.display?a():d())}),!1)},open:a}}})); 8 | -------------------------------------------------------------------------------- /docs/plugin/zoom/zoom.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).RevealZoom=t()}(this,(function(){"use strict"; 2 | /*! 3 | * reveal.js Zoom plugin 4 | */const e={id:"zoom",init:function(e){e.getRevealElement().addEventListener("mousedown",(function(o){var n=/Linux/.test(window.navigator.platform)?"ctrl":"alt",i=(e.getConfig().zoomKey?e.getConfig().zoomKey:n)+"Key",d=e.getConfig().zoomLevel?e.getConfig().zoomLevel:2;o[i]&&!e.isOverview()&&(o.preventDefault(),t.to({x:o.clientX,y:o.clientY,scale:d,pan:!1}))}))},destroy:()=>{t.reset()}};var t=function(){var e=1,o=0,n=0,i=-1,d=-1,l="transform"in document.body.style;function s(t,o){var n=r();if(t.width=t.width||1,t.height=t.height||1,t.x-=(window.innerWidth-t.width*o)/2,t.y-=(window.innerHeight-t.height*o)/2,l)if(1===o)document.body.style.transform="";else{var i=n.x+"px "+n.y+"px",d="translate("+-t.x+"px,"+-t.y+"px) scale("+o+")";document.body.style.transformOrigin=i,document.body.style.transform=d}else 1===o?(document.body.style.position="",document.body.style.left="",document.body.style.top="",document.body.style.width="",document.body.style.height="",document.body.style.zoom=""):(document.body.style.position="relative",document.body.style.left=-(n.x+t.x)/o+"px",document.body.style.top=-(n.y+t.y)/o+"px",document.body.style.width=100*o+"%",document.body.style.height=100*o+"%",document.body.style.zoom=o);e=o,document.documentElement.classList&&(1!==e?document.documentElement.classList.add("zoomed"):document.documentElement.classList.remove("zoomed"))}function c(){var t=.12*window.innerWidth,i=.12*window.innerHeight,d=r();nwindow.innerHeight-i&&window.scroll(d.x,d.y+(1-(window.innerHeight-n)/i)*(14/e)),owindow.innerWidth-t&&window.scroll(d.x+(1-(window.innerWidth-o)/t)*(14/e),d.y)}function r(){return{x:void 0!==window.scrollX?window.scrollX:window.pageXOffset,y:void 0!==window.scrollY?window.scrollY:window.pageYOffset}}return l&&(document.body.style.transition="transform 0.8s ease"),document.addEventListener("keyup",(function(o){1!==e&&27===o.keyCode&&t.out()})),document.addEventListener("mousemove",(function(t){1!==e&&(o=t.clientX,n=t.clientY)})),{to:function(o){if(1!==e)t.out();else{if(o.x=o.x||0,o.y=o.y||0,o.element){var n=o.element.getBoundingClientRect();o.x=n.left-20,o.y=n.top-20,o.width=n.width+40,o.height=n.height+40}void 0!==o.width&&void 0!==o.height&&(o.scale=Math.max(Math.min(window.innerWidth/o.width,window.innerHeight/o.height),1)),o.scale>1&&(o.x*=o.scale,o.y*=o.scale,s(o,o.scale),!1!==o.pan&&(i=setTimeout((function(){d=setInterval(c,1e3/60)}),800)))}},out:function(){clearTimeout(i),clearInterval(d),s({x:0,y:0},1),e=1},magnify:function(e){this.to(e)},reset:function(){this.out()},zoomLevel:function(){return e}}}(); 5 | /*! 6 | * zoom.js 0.3 (modified for use with reveal.js) 7 | * http://lab.hakim.se/zoom-js 8 | * MIT licensed 9 | * 10 | * Copyright (C) 2011-2014 Hakim El Hattab, http://hakim.se 11 | */return()=>e})); 12 | -------------------------------------------------------------------------------- /docs/plugin/math/math.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).RevealMath=e()}(this,(function(){"use strict";const t=()=>{let t,e={messageStyle:"none",tex2jax:{inlineMath:[["$","$"],["\\(","\\)"]],skipTags:["script","noscript","style","textarea","pre"]},skipStartupTypeset:!0};return{id:"mathjax2",init:function(n){t=n;let a=t.getConfig().mathjax2||t.getConfig().math||{},i={...e,...a},s=(i.mathjax||"https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js")+"?config="+(i.config||"TeX-AMS_HTML-full");i.tex2jax={...e.tex2jax,...a.tex2jax},i.mathjax=i.config=null,function(t,e){let n=document.querySelector("head"),a=document.createElement("script");a.type="text/javascript",a.src=t;let i=()=>{"function"==typeof e&&(e.call(),e=null)};a.onload=i,a.onreadystatechange=()=>{"loaded"===this.readyState&&i()},n.appendChild(a)}(s,(function(){MathJax.Hub.Config(i),MathJax.Hub.Queue(["Typeset",MathJax.Hub,t.getRevealElement()]),MathJax.Hub.Queue(t.layout),t.on("slidechanged",(function(t){MathJax.Hub.Queue(["Typeset",MathJax.Hub,t.currentSlide])}))}))}}},e=t;return Plugin=Object.assign(e(),{KaTeX:()=>{let t,e={version:"latest",delimiters:[{left:"$$",right:"$$",display:!0},{left:"$",right:"$",display:!1},{left:"\\(",right:"\\)",display:!1},{left:"\\[",right:"\\]",display:!0}],ignoredTags:["script","noscript","style","textarea","pre"]};const n=t=>new Promise(((e,n)=>{const a=document.createElement("script");a.type="text/javascript",a.onload=e,a.onerror=n,a.src=t,document.head.append(a)}));return{id:"katex",init:function(a){t=a;let i=t.getConfig().katex||{},s={...e,...i};const{local:o,version:l,extensions:r,...c}=s;let d=s.local||"https://cdn.jsdelivr.net/npm/katex",u=s.local?"":"@"+s.version,p=d+u+"/dist/katex.min.css",h=d+u+"/dist/contrib/mhchem.min.js",x=d+u+"/dist/contrib/auto-render.min.js",m=[d+u+"/dist/katex.min.js"];s.extensions&&s.extensions.includes("mhchem")&&m.push(h),m.push(x);const f=()=>{renderMathInElement(a.getSlidesElement(),c),t.layout()};(t=>{let e=document.createElement("link");e.rel="stylesheet",e.href=t,document.head.appendChild(e)})(p),async function(t){for(const e of t)await n(e)}(m).then((()=>{t.isReady()?f():t.on("ready",f.bind(this))}))}}},MathJax2:t,MathJax3:()=>{let t,e={tex:{inlineMath:[["$","$"],["\\(","\\)"]]},options:{skipHtmlTags:["script","noscript","style","textarea","pre"]},startup:{ready:()=>{MathJax.startup.defaultReady(),MathJax.startup.promise.then((()=>{Reveal.layout()}))}}};return{id:"mathjax3",init:function(n){t=n;let a=t.getConfig().mathjax3||{},i={...e,...a};i.tex={...e.tex,...a.tex},i.options={...e.options,...a.options},i.startup={...e.startup,...a.startup};let s=i.mathjax||"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js";i.mathjax=null,window.MathJax=i,function(t,e){let n=document.createElement("script");n.type="text/javascript",n.id="MathJax-script",n.src=t,n.async=!0,n.onload=()=>{"function"==typeof e&&(e.call(),e=null)},document.head.appendChild(n)}(s,(function(){Reveal.addEventListener("slidechanged",(function(t){MathJax.typeset()}))}))}}}})})); 2 | -------------------------------------------------------------------------------- /05/ex1/ex1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define PERROR fprintf(stderr, "%s:%d: error: %s\n", __FILE__, __LINE__, strerror(errno)) 8 | #define PERROR_GOTO(label) \ 9 | do { \ 10 | PERROR; \ 11 | goto label; \ 12 | } while (0) 13 | 14 | #define INIT_ARRAY(arr, label) \ 15 | do { \ 16 | if (!(arr)) PERROR_GOTO(label); \ 17 | for (long i = 0; i < n; ++i) { \ 18 | (arr)[i] = malloc(sizeof(**(arr)) * n); \ 19 | if (!(arr)[i]) PERROR_GOTO(label); \ 20 | } \ 21 | } while (0) 22 | 23 | void free_2d_array(int **arr, long len) { 24 | if (!arr) { 25 | return; 26 | } 27 | for (long i = 0; i < len; ++i) { 28 | if (!arr[i]) { 29 | break; 30 | } 31 | free(arr[i]); 32 | } 33 | free(arr); 34 | } 35 | 36 | int main(int argc, char **argv) { 37 | // handle input 38 | if (argc != 2) { 39 | fprintf(stderr, "Error: usage: %s \n", argv[0]); 40 | return EXIT_FAILURE; 41 | } 42 | errno = 0; 43 | char *str = argv[1]; 44 | char *endptr; 45 | long n = strtol(str, &endptr, 0); 46 | if (errno != 0) { 47 | perror("strtol"); 48 | return EXIT_FAILURE; 49 | } 50 | if (endptr == str) { 51 | fprintf(stderr, "Error: no digits were found!\n"); 52 | return EXIT_FAILURE; 53 | } 54 | if (n < 0) { 55 | fprintf(stderr, "Error: matrix size must not be negative!\n"); 56 | return EXIT_FAILURE; 57 | } 58 | 59 | // allocate memory 60 | int status = EXIT_FAILURE; 61 | int **a = malloc(sizeof(*a) * n); 62 | INIT_ARRAY(a, error_a); 63 | int **b = malloc(sizeof(*b) * n); 64 | INIT_ARRAY(b, error_b); 65 | int **c = malloc(sizeof(*c) * n); 66 | INIT_ARRAY(c, error_c); 67 | unsigned *local_res = malloc(omp_get_max_threads() * sizeof(*local_res)); 68 | if (!local_res) PERROR_GOTO(error_c); 69 | status = EXIT_SUCCESS; 70 | 71 | // fill matrix 72 | srand(7); 73 | for (long i = 0; i < n; ++i) { 74 | for (long j = 0; j < n; ++j) { 75 | a[i][j] = rand(); 76 | b[i][j] = rand(); 77 | } 78 | } 79 | 80 | double start_time = omp_get_wtime(); 81 | #pragma omp parallel default(none) shared(n, a, b, c, local_res) 82 | { 83 | // matrix multiplication 84 | #pragma omp parallel for default(none) shared(n, a, b, c) 85 | for (long i = 0; i < n; ++i) { 86 | for (long j = 0; j < n; ++j) { 87 | for (long k = 0; k < n; ++k) { 88 | c[i][j] += a[i][k] * b[k][j]; 89 | } 90 | } 91 | } 92 | 93 | // sum of matrix c 94 | #pragma omp parallel for default(none) shared(n, a, b, c, local_res) 95 | for (long i = 0; i < n; ++i) { 96 | for (long j = 0; j < n; ++j) { 97 | local_res[omp_get_thread_num()] += c[i][j]; 98 | } 99 | } 100 | } 101 | unsigned long res = 0; 102 | for (int l = 0; l < omp_get_num_threads(); ++l) { 103 | res += local_res[l]; 104 | } 105 | double end_time = omp_get_wtime(); 106 | printf("res: %lu, time: %2.2f seconds\n", res, end_time - start_time); 107 | 108 | // cleanup 109 | free(local_res); 110 | error_c: 111 | free_2d_array(c, n); 112 | error_b: 113 | free_2d_array(b, n); 114 | error_a: 115 | free_2d_array(a, n); 116 | return status; 117 | } -------------------------------------------------------------------------------- /01/readme.md: -------------------------------------------------------------------------------- 1 | # Assignment 1 2 | 3 | The goal of this assignment is to get you acquainted with working on an HPC cluster as well as obtaining, illustrating, and interpreting measurement data. 4 | 5 | ## Exercise 1 (1.5 Points) 6 | 7 | ### Description 8 | 9 | This exercise consists in familiarizing yourself with SLURM job submission. 10 | 11 | You received user credentials for the LCC3 cluster. If you did not change the default password, do so **immediately**. You are responsible for this account during this semester. 12 | 13 | You can find information about LCC3 at https://www.uibk.ac.at/zid/systeme/hpc-systeme/leo3/ and information about SLURM job submission at https://www.uibk.ac.at/zid/systeme/hpc-systeme/common/tutorials/slurm-tutorial.html. 14 | 15 | **Please run any benchmarks or heavy CPU loads only on the compute nodes, not on the login node.** 16 | If you want to do some interactive experimentation, use an *interactive job* as outlined in the tutorial. Make sure to stop any interactive jobs once you are done. 17 | 18 | ### Tasks 19 | 20 | - Study how to submit jobs in SLURM, how to check their state and how to cancel them. 21 | - Prepare a submission script that starts an arbitrary executable, e.g. `/bin/hostname` 22 | - In your opionion, what are the 5 most important parameters available when submitting a job and why? What are possible settings of these parameters, and what effect do they have? 23 | - How do you run your program in parallel? What environment setup is required? 24 | 25 | ## Exercise 2 (1.5 Points) 26 | 27 | This exercise consists in running and comparing two parallel implementations of the same algorithm. 28 | 29 | ### Description 30 | 31 | There are usually multiple implementations to choose from putting an algorithm into source code. In this exercise, we will compare the behavior of three different parallel implementations that all do the same thing: They simply sum up numbers, measure the time required to do so, and finally both print the calculated sum and the time. 32 | 33 | ### Tasks 34 | 35 | - Compile the three given source codes `slow.c`, `medium.c`, and `fast.c` with the compiler flag `-fopenmp` to enable OpenMP parallelism. 36 | - Vary the number of cores by setting the environment variable `OMP_NUM_THREADS` before running the program, e.g. `OMP_NUM_THREADS=1 ./slow`. Measure the execution times of all three programs for all numbers of cores your personal computing system (e.g. PC or laptop) offers. 37 | - See if you can reduce the execution times even further by trying out different compiler flags (optimization flags). 38 | - Create a table and figures that illustrate the measured data and study them. What effects can you observe? 39 | - How stable are the measurements when running the experiments multiple times? 40 | - Enter the shortest execution times for 1 and 12 threads measured on the LCC3 cluster for each code to the performance comparison sheet linked on Discord. 41 | 42 | ## General Notes 43 | 44 | All the material required by the tasks above (e.g. code, figures, text, etc...) must be part of the solution that is handed in. Your experiments should be reproducible and comparable to your own measurements using the solution materials that you hand in. 45 | 46 | **Every** member of your group must be able to explain the given problem, your solution, and possible findings. You may also need to answer detailed questions about any of these aspects. 47 | -------------------------------------------------------------------------------- /04/README.md: -------------------------------------------------------------------------------- 1 | # Assignment 4 2 | 3 | The goal of this assignment is to get to know the basic functionality of OpenMP. 4 | 5 | ## Exercise 1 (1.5 Points) 6 | 7 | ### Description 8 | 9 | This exercise consists of implementing a Monte Carlo Pi approximation in OpenMP. 10 | 11 | ### Tasks 12 | 13 | 1) Review the pthreads-based implementation provided in [monte_carlo_pi/mc_pi_pthreads.c](monte_carlo_pi/mc_pi_pthreads.c). Benchmark it with 1, 2, 4, 6, and 12 threads on LCC3. What can you observe? 14 | 2) Implement parallel versions of this approximation using OpenMP. In total, three different versions using the following OpenMP constructs should be provided: 15 | 1) `critical` section 16 | 2) `atomic` statement 17 | 3) `reduction` clause 18 | 3) To increase the performance difference among these versions, make sure you increment the samples counter directly, without aggregating to private variables first. 19 | 4) Benchmark your OpenMP implementations with the same number of threads using OpenMP's time measurement function. What can you observe? How do those results compare to your earlier measurements? 20 | 5) The tool `/usr/bin/time` can be used to get useful information on the properties of a program's execution, e.g. its execution time or the maximum amount of main memory used. Measure the execution time of your OpenMP implementation using `/usr/bin/time -v `. Take a look at the output, specifically "user time" and "elapsed (wall clock) time". How do they differ? Does either of them match the time measurement function of OpenMP? 21 | 6) Add the wall clock time measurements for 12 threads on LCC3 to the comparison spreadsheet linked on Discord. 22 | 23 | ## Exercise 2 (1.5 Points) 24 | 25 | ### Description 26 | 27 | In this exercise, you are asked to investigate the effect of false sharing in multi-threaded programs. 28 | 29 | ### Tasks 30 | 31 | 1) Implement (or copy from Exercise 1) a parallel Monte Carlo PI version that uses a local sum approach, i.e. that first aggregates to a per-thread private variable before using `atomic` to aggregate the entire sum of samples. 32 | 2) Create a second version that does not rely on private variables but a single array where each thread gets one element for local sum storage. In memory, the data layout should then look like `[thread_0][thread_1][_thread_2][...]`. 33 | 3) Create a third version that continues to use a single array but add padding to it, ensuring that the individual local sum storage locations are separated by unused data, e.g. `[thread_0][N_unused_bytes][thread_1][N_unused_bytes][thread_2][...]`. How you achieve this padding is up to you (there are several implementation possibilities). How large should the padding distance ideally be? 34 | 4) Benchmark all three versions (private variable, array, array with padding) and document your results. Also check the L1 cache misses using `perf stat`. Feel free to also check for this effect on your local machines and report the data (including the CPU type!). 35 | 5) Enter the wall clock time of each version for 12 threads on LCC3 to the comparison spreadsheet linked on Discord. 36 | 37 | ## General Notes 38 | 39 | All the material required by the tasks above (e.g., code, figures, text, etc...) must be part of the solution that is handed in. Your experiments should be reproducible and comparable to your measurements using the solution materials that you hand in. 40 | 41 | **Every** member of your group must be able to explain the given problem, your solution, and possible findings. You may also need to answer detailed questions about any of these aspects. 42 | -------------------------------------------------------------------------------- /02/readme.md: -------------------------------------------------------------------------------- 1 | # Assignment 2 2 | 3 | The goal of this assignment is to get you acquainted with the architecture of the LCC3 HPC cluster. Moreover, you will obtain a first grasp on the theoretical scaling characteristics of parallel programs. 4 | 5 | ## Exercise 1 (1.5 Points) 6 | 7 | ### Description 8 | 9 | This exercise consists in familiarizing yourself with the hardware of LCC3, that you're running your applications on. 10 | 11 | Understanding the architecture of the utilized hardware is paramount for optimizing (parallel) programs. It enables precise resource allocation, memory optimization, and strategic parallelization decisions. In this exercise, we are interested in gathering information about the hardware of the LCC3 compute nodes utilizing the [Portable Hardware Locality (hwloc)](https://www.open-mpi.org/projects/hwloc/) software package. 12 | 13 | ### Tasks 14 | 15 | - Connect to the LCC3 compute cluster using your login credentials. Once connected, load the `hwloc` module via `module load hwloc/2.8.0-intel-2021.7.1-co55pj6`. 16 | - Find out more about the hardware that you're running on by executing `lstopo --of txt`. 17 | - Interpret the output and describe what information you can gather. Please also elaborate on these questions: 18 | - Can you retrieve the number of CPUs and cores from the output? 19 | - Investigate the memory hierarchy information provided by lstopo. 20 | - How much memory (RAM) does the compute node offer? 21 | - What does the term `NUMANode` tell you about the memory? Why are there two `NUMANodes`? 22 | - What interesting information can you retrieve about the caches of the system? 23 | - Is there anything else you can find out from the output? 24 | - Based on your observations, how many threads could you utilize at maximum when parallelizing a program with OpenMP on this system? 25 | - Compare your observations to the [LCC3 documentation](https://www.uibk.ac.at/zid/systeme/hpc-systeme/leo3/hardware/) and [CPU documentation](https://www.intel.com/content/www/us/en/products/sku/47922/intel-xeon-processor-x5650-12m-cache-2-66-ghz-6-40-gts-intel-qpi/specifications.html). Do your observations match the documentation? 26 | 27 | ## Exercise 2 (1.5 Points) 28 | 29 | ### Description 30 | 31 | Amdahl's law is one of the most important properties of parallel programs. 32 | 33 | ### Tasks 34 | 35 | - How is the speedup of a parallel program defined? 36 | - What is the formal definition of Amdahl's law and what relationship does it describe for parallel programs (explain in your own words)? Why/How is this significant? 37 | - Compute the theoretical speedup of a program that spends 10% of its time in unparallelizable, sequential regions for 6 cores and for a hypothetically unlimited number of cores. 38 | - Compute the theoretical speedup of a program that spends 20% of its time in unparallelizable, sequential regions for 6 cores and for a hypothetically unlimited number of cores. 39 | - Given an algorithm of time complexity O(n^3). How large (in %) can the unparallelizable, sequential region be at most, such that a speedup of 10 can be achieved using 64 cores? 40 | 41 | ## General Notes 42 | 43 | All the material required by the tasks above (e.g. code, figures, text, etc...) must be part of the solution that is handed in. Your experiments should be reproducible and comparable to your own measurements using the solution materials that you hand in. 44 | 45 | **Every** member of your group must be able to explain the given problem, your solution, and possible findings. You may also need to answer detailed questions about any of these aspects. -------------------------------------------------------------------------------- /10/README.md: -------------------------------------------------------------------------------- 1 | # Assignment 10 2 | 3 | The goal of this task is to practice using OpenMP tasks and take a first look at the heat stencil application. 4 | 5 | ## Exercise 1 (1 Point) 6 | 7 | ### Description 8 | 9 | This exercise consists of implementing a program that calculates Delannoy numbers with OpenMP tasks. 10 | 11 | A Delannoy number specifies the number of paths from the south-west corner of a 2D grid to the north-east corner, using only the per-step directions north, north-east, and east. See https://en.wikipedia.org/wiki/Delannoy_number for more information and a visualization. 12 | 13 | ### Tasks 14 | 15 | - Implement a sequential program that computes the Delannoy number for a square 2D grid of size NxN where N is an input parameter for your program. If in doubt, base your implementation on the formula given in the Wikipedia article under "basic recurrence relation". Make sure your program is semantically correct by comparing the result against the Delannoy numbers given in the article. 16 | - Parallelize your program using OpenMP tasks and benchmark both the sequential and parallel implementation for several N between 3 and ~15. What can you observe? 17 | - What is the main bottleneck of your parallel implementation and how can it be improved without changing the underlying algorithm? 18 | - Enter the wall clock time of the sequential version and the parallel version for 1 and 12 threads for N=12 on LCC3 to the comparison spreadsheet linked on Discord. 19 | 20 | ## Exercise 2 (2 Points) 21 | 22 | ### Description 23 | 24 | This exercise consists of implementing a 2-dimensional heat stencil application. 25 | 26 | A large class of scientific applications are so-called stencil or structured grid applications. These simulate time-dependent physical processes such as the propagation of heat or pressure in a given medium. The core of the simulation operates on a grid and updates each cell with information from its neighbor cells. 27 | 28 | heat_stencil 29 | 30 | ### Tasks 31 | 32 | - Given the code in [heat_stencil_2D.c](heat_stencil_2D.c), finish the implementation: 33 | - implement the heat propagation by updating each cell with information from its neighbors. If in doubt, you can start with the formula given in https://en.wikipedia.org/wiki/Finite_difference_method#Example:_The_Laplace_operator 34 | - make sure the heat source stays the same through all iterations 35 | - if computing the value at the boundary, use temperature at the center position as the next value (e.g if you want to calculate A[0,1], use A[0,1] as the left neighbor cell instead of the non-existent A[-1,1]) 36 | - The simple verification at the end should pass 37 | - Parallelize the implementation using OpenMP. Investigate the use of the `collapse` clause and explain its purpose and effects. 38 | - Measure the time, speedup and efficiency of the stencil codes for varying problem sizes and numbers of threads. 39 | - Enter the wall clock time of the sequential version and the parallel version for 1 and 12 threads for 500x500 on LCC3 to the comparison spreadsheet linked on Discord. 40 | 41 | ## General Notes 42 | 43 | All the material required by the tasks above (e.g., code, figures, text, etc...) must be part of the solution that is handed in. Your experiments should be reproducible and comparable to your measurements using the solution materials that you hand in. 44 | 45 | **Every** member of your group must be able to explain the given problem, your solution, and possible findings. You may also need to answer detailed questions about any of these aspects. 46 | -------------------------------------------------------------------------------- /07/README.md: -------------------------------------------------------------------------------- 1 | # Assignment 7 2 | 3 | The goal of this assignment is to work with data and control dependencies. 4 | 5 | ## Exercise 1 (1 Point) 6 | 7 | ### Description 8 | 9 | Consider the following, individual code examples in the context of dependence analysis, race conditions, and parallelization: 10 | 11 | ```C 12 | a[0] = 0; 13 | #pragma omp parallel for 14 | for (i=1; in+1=zn2+c*, where *z* is a complex number and *c* is a constant. 12 | > Short reminder: a complex number *z* is the sum of a real part *x* and an imaginary part *y* that includes the imaginary unit *i* with the property (*i2=-1*) → *z=x+yi*. 13 | 14 | 15 | Since the exact math behind this is not that important to us, we will provide you with a pseudocode: 16 | 17 | ``` 18 | function calc_mandelbrot(image): 19 | for each (X,Y) do: 20 | x = 0.0 21 | y = 0.0 22 | cx = mapped x_pixel_idx to Mandelbrot x-axis [-2.5, 1] 23 | cy = mapped y_pixel_idx to Mandelbrot y-axis [-1, 1] 24 | iteration = 0 25 | while (x*x + y*y <= 2*2 AND iteration < MAX_ITER) do: 26 | x_tmp = x*x - y*y + cx 27 | y = 2*x*y + cy 28 | x = x_tmp 29 | iteration = iteration + 1 30 | 31 | norm_iteration = mapped iteration to pixel range [0, 255] 32 | image[y_pixel][x_pixel] = norm_iteration 33 | ``` 34 | 35 | ### Tasks 36 | 37 | 1) Open the `mandelbrot.c` file and implement the sequential `calc_mandelbrot` function with the help of the provided pseudocode. 38 | 2) Check out the generated image `mandelbrot.png` to see if you implemented the algorithm correctly. 39 | 3) Benchmark your program on the LCC3 cluster, document your results and add them to the comparison spreadsheet linked on Discord. How would you improve program performance? 40 | 4) Can you think of a way to parallelize this algorithm? 41 | 42 | ## Exercise 2 (1.5 Points) 43 | 44 | ### Description 45 | 46 | The Hadamard product is defined as the element-wise product of two matrices with the same dimensions. The following two snippets give an implementation of the Hadamard product for n x n square matrices. 47 | 48 | ```C 49 | for (size_t j = 0; j < n; ++j) { 50 | for (size_t i = 0; i < n; ++i) { 51 | c[i][j] = a[i][j] * b[i][j]; 52 | } 53 | } 54 | ``` 55 | 56 | ```C 57 | for (size_t i = 0; i < n; ++i) { 58 | for (size_t j = 0; j < n; ++j) { 59 | c[i][j] = a[i][j] * b[i][j]; 60 | } 61 | } 62 | ``` 63 | 64 | ### Tasks 65 | 66 | 1) For both implementations, give a function f to calculate the number of data cache read misses for the matrix size n and the cache line size s in an 8-way set-associative cache. Assume that all variables are initialized appropriately (the matrix elements are of type `int32_t`) and that the matrices are stored in contiguous memory in row-major order. Additionally, the matrices are too large to store them entirely in the cache (n >> s). 67 | 2) Use the two snippets to implement two versions of the Hadamard product. 68 | 3) Log into the LCC3 cluster and analyze the cache behavior of the implementations using `cachegrind` (e.g. `valgrind --tool=cachegrind `) and `perf` (e.g. `perf stat -e LLC-load-misses -e LLC-store-misses `) Can you validate your theoretical findings? Compare the results of both tools. 69 | 70 | ## General Notes 71 | 72 | All the material required by the tasks above (e.g., code, figures, text, etc...) must be part of the solution that is handed in. Your experiments should be reproducible and comparable to your measurements using the solution materials that you hand in. 73 | 74 | **Every** member of your group must be able to explain the given problem, your solution, and possible findings. You may also need to answer detailed questions about any of these aspects. 75 | -------------------------------------------------------------------------------- /04/monte_carlo_pi/mc_pi_pthreads.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 199506L 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define START_SEED 0 11 | 12 | typedef uint64_t timepoint_t; 13 | typedef uint32_t count_t; 14 | 15 | struct MonteCarloPiInput { 16 | count_t iterations; 17 | uint32_t id; 18 | }; 19 | 20 | static void* monte_carlo_pi(void* arg); 21 | static timepoint_t time_ns(); 22 | static double elapsed_seconds(timepoint_t start, timepoint_t end); 23 | 24 | int main(int argc, char** argv) { 25 | // read input arguments 26 | if (argc > 2) { 27 | fprintf(stderr, "Usage: %s []\n", argv[0]); 28 | return EXIT_FAILURE; 29 | } 30 | 31 | const int32_t requested_threads = (argc <= 1) ? 1 : atoi(argv[1]); 32 | const uint32_t num_threads = (requested_threads < 1) ? 1 : (uint32_t) requested_threads; 33 | 34 | const count_t total_iterations = ((count_t) 700) * 1000 * 1000; 35 | const count_t per_thread_iterations = total_iterations / num_threads; 36 | 37 | bool simulation_success = true; 38 | 39 | // start time measurement 40 | timepoint_t start = time_ns(); 41 | 42 | // create and start threads 43 | pthread_t threads[num_threads]; 44 | struct MonteCarloPiInput inputs[num_threads]; 45 | int creation_statuses[num_threads]; 46 | 47 | for (uint32_t i = 0; i < num_threads; ++i) { 48 | inputs[i] = (struct MonteCarloPiInput) { 49 | .id = i, 50 | .iterations = per_thread_iterations + ((i == 0) ? (total_iterations % num_threads) : 0) 51 | }; 52 | 53 | creation_statuses[i] = pthread_create(&threads[i], NULL, monte_carlo_pi, (void*) &inputs[i]); 54 | 55 | if (creation_statuses[i] != 0) { 56 | fprintf(stderr, "Failed to create thread %u with error %d\n", i, creation_statuses[i]); 57 | simulation_success = false; 58 | } 59 | } 60 | 61 | // join threads and calculate result 62 | count_t points_in_circle = 0; 63 | for (uint32_t i = 0; i < num_threads; ++i) { 64 | if (creation_statuses[i] == 0) { 65 | count_t* result = NULL; 66 | int status = pthread_join(threads[i], (void**) &result); 67 | 68 | if (status != 0) { 69 | fprintf(stderr, "Joining thread %u failed with error %d\n", i, status); 70 | simulation_success = false; 71 | } else if (result != NULL) { 72 | points_in_circle += *result; 73 | free(result); 74 | } 75 | } 76 | } 77 | 78 | double pi_approximation = 4.0 * (points_in_circle / (double) total_iterations); 79 | 80 | // print result and elapsed time 81 | timepoint_t end = time_ns(); 82 | double elapsed_time = elapsed_seconds(start, end); 83 | 84 | if (simulation_success) { 85 | printf("Approximation of PI took %.3f seconds with %u threads - value: %.10f\n", 86 | elapsed_time, num_threads, pi_approximation); 87 | } else { 88 | printf("Simulation failed!\n"); 89 | } 90 | 91 | return (simulation_success) ? EXIT_SUCCESS : EXIT_FAILURE; 92 | } 93 | 94 | static void* monte_carlo_pi(void* arg) { 95 | struct MonteCarloPiInput* input = (struct MonteCarloPiInput*) arg; 96 | unsigned int seed = START_SEED + input->id; 97 | 98 | count_t* points_in_cricle = calloc(1, sizeof(count_t)); 99 | 100 | for (count_t i = 0; i < input->iterations; ++i) { 101 | float x = (rand_r(&seed) / (float) RAND_MAX); 102 | float y = (rand_r(&seed) / (float) RAND_MAX); 103 | 104 | if (x * x + y * y <= 1.0f) { 105 | ++(*points_in_cricle); 106 | } 107 | } 108 | 109 | // implicit call to pthread_exit() 110 | return (void*) points_in_cricle; 111 | } 112 | 113 | static timepoint_t time_ns() { 114 | // Note: We assume that all time information fits into an uint64_t 115 | struct timespec now; 116 | clock_gettime(CLOCK_MONOTONIC, &now); 117 | return ((timepoint_t) now.tv_sec) * ((timepoint_t) 1E9) + now.tv_nsec; 118 | } 119 | 120 | static double elapsed_seconds(timepoint_t start, timepoint_t end) { 121 | return ((start > end) ? start - end : end - start) / 1E9; 122 | } 123 | -------------------------------------------------------------------------------- /docs/dist/theme/fonts/source-sans-pro/LICENSE: -------------------------------------------------------------------------------- 1 | SIL Open Font License 2 | 3 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name ‘Source’. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. 4 | 5 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 6 | This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL 7 | 8 | —————————————————————————————- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | —————————————————————————————- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. 14 | 15 | The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. 16 | 17 | DEFINITIONS 18 | “Font Software” refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. 19 | 20 | “Reserved Font Name” refers to any names specified as such after the copyright statement(s). 21 | 22 | “Original Version” refers to the collection of Font Software components as distributed by the Copyright Holder(s). 23 | 24 | “Modified Version” refers to any derivative made by adding to, deleting, or substituting—in part or in whole—any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. 25 | 26 | “Author” refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. 27 | 28 | PERMISSION & CONDITIONS 29 | Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 30 | 31 | 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 32 | 33 | 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 34 | 35 | 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 36 | 37 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 38 | 39 | 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. 40 | 41 | TERMINATION 42 | This license becomes null and void if any of the above conditions are not met. 43 | 44 | DISCLAIMER 45 | THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. -------------------------------------------------------------------------------- /13/README.md: -------------------------------------------------------------------------------- 1 | # Assignment 13 2 | 3 | The goal of this assignment is to implement a 3D n-body simulation. 4 | 5 | ## Exercise 1 (3 Points) 6 | 7 | ### Description 8 | 9 | N-body simulations form a large class of scientific applications, as they are used in research ranging from astrophysics to molecular dynamics. At their core, they model and simulate the interaction of moving particles in physical space. For this assignment, the specific n-body setting relates to astrophysics, where the mutual gravitational effect of stars is investigated. Each particle has several properties which include at least 10 | 11 | - position, 12 | - velocity, and 13 | - mass. 14 | 15 | For each timestep (you can assume `dt = 1`), particles must be moved by first computing the force exerted on them according to the [Newtonian equation for gravity](https://en.wikipedia.org/wiki/Newton%27s_law_of_universal_gravitation), `force = G * (mass_1 * mass_2) / radius^2` where `G` is the gravitational constant (and can be assumed as `G = 1` for simplicity). Second, using the computed force on a particle, its position and velocity can be updated via `velocity = velocity + force / mass` and `position = position + velocity`. 16 | 17 | ### Tasks 18 | 19 | 1. Provide a sequential implementation of the n-body simulation in 3D. Hints on how to proceed (not mandatory to follow): 20 | 1. generate particles randomly, e.g. uniformly distributed 21 | 2. provide a function for computing forces and moving particles 22 | 3. move particles in a time loop for a given number of steps 23 | 2. Measure the execution time for various particle numbers and timesteps. What can you observe? 24 | 3. Implement a parallel version the n-body simulation. Optimize your code as much as possible, consider all the optimizations that we discussed in this course. Which optimizations are suitable for this kind of problem? Benchmark your optimized version for multiple numbers of threads and discuss the results. 25 | 4. Write your data to a file (e.g. `data.dat` ) and use any visualization tool to visualize the movement of the data. 26 | Here is an example using `gnuplot`: 27 | 28 | 1. 29 | ```` 30 | set terminal gif animate delay 100 # set gif to animate in a frame delay of 100 ms 31 | set output 'output.gif' # write to the file output.gif 32 | 33 | set style line 2 lc rgb 'black' pt 7 # set line to be a filled circle of color black 34 | stats 'data.dat' nooutput # read data from data.dat file 35 | set xrange [-0.5:100.5] # print data values for x axis from range [-0.5:100.5] 36 | set yrange [-0.5:100.5] # print data values for y axis from range [-0.5:100.5] 37 | set zrange [-0.5:100.5] # print data values for z axis from range [-0.5:100.5] 38 | 39 | do for [i=1:int(STATS_blocks)] { 40 | splot 'data.dat' index (i-1) with points ls 2 ps 0.4 #for each datapoint plot the point 41 | } 42 | ```` 43 | 2. use this [gnuplot](particle.plt) snippet to create a gif, adapt this file according to your particle range implementation 44 | 3. the data for the previous example has to be in following format: 45 | ```` 46 | x1_timestep1 y1_timestep1 z1_timestep1 47 | x2_timestep1 y2_timestep1 z2_timestep1 48 | x3_timestep1 y3_timestep1 z3_timestep1 49 | 50 | 51 | x1_timestep2 y1_timestep2 z1_timestep2 52 | x2_timestep2 y2_timestep2 z2_timestep2 53 | x3_timestep2 y3_timestep2 z3_timestep2 54 | 55 | 56 | x1_timestep3 y1_timestep3 z1_timestep3 57 | x2_timestep3 y2_timestep3 z2_timestep3 58 | x3_timestep3 y3_timestep3 z3_timestep3 59 | ```` 60 | So in one line there is an x, y, and z value for a point, multiple points are in different lines. 61 | Having 2 blank lines means the points for this timestep are finished. Note that all values can be floating point numbers 62 | 5) For measuring performance either disable writing to a datafile or consider not dumping each timestep 63 | 6) Benchmark the sequential program and the parallelized version using 5000 particles and 100 time steps for 12 threads on LCC3 and enter the results in the comparison spreadsheet linked on Discord. 64 | 65 | ## General Notes 66 | 67 | All the material required by the tasks above (e.g., code, figures, text, etc...) must be part of the solution that is handed in. Your experiments should be reproducible and comparable to your measurements using the solution materials that you hand in. 68 | 69 | **Every** member of your group must be able to explain the given problem, your solution, and possible findings. You may also need to answer detailed questions about any of these aspects. 70 | -------------------------------------------------------------------------------- /docs/plugin/menu/font-awesome/css/svg-with-js.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.1.0 by @fontawesome - https://fontawesome.com 3 | * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | .svg-inline--fa,svg:not(:root).svg-inline--fa{overflow:visible}.svg-inline--fa{display:inline-block;font-size:inherit;height:1em;vertical-align:-.125em}.svg-inline--fa.fa-lg{vertical-align:-.225em}.svg-inline--fa.fa-w-1{width:.0625em}.svg-inline--fa.fa-w-2{width:.125em}.svg-inline--fa.fa-w-3{width:.1875em}.svg-inline--fa.fa-w-4{width:.25em}.svg-inline--fa.fa-w-5{width:.3125em}.svg-inline--fa.fa-w-6{width:.375em}.svg-inline--fa.fa-w-7{width:.4375em}.svg-inline--fa.fa-w-8{width:.5em}.svg-inline--fa.fa-w-9{width:.5625em}.svg-inline--fa.fa-w-10{width:.625em}.svg-inline--fa.fa-w-11{width:.6875em}.svg-inline--fa.fa-w-12{width:.75em}.svg-inline--fa.fa-w-13{width:.8125em}.svg-inline--fa.fa-w-14{width:.875em}.svg-inline--fa.fa-w-15{width:.9375em}.svg-inline--fa.fa-w-16{width:1em}.svg-inline--fa.fa-w-17{width:1.0625em}.svg-inline--fa.fa-w-18{width:1.125em}.svg-inline--fa.fa-w-19{width:1.1875em}.svg-inline--fa.fa-w-20{width:1.25em}.svg-inline--fa.fa-pull-left{margin-right:.3em;width:auto}.svg-inline--fa.fa-pull-right{margin-left:.3em;width:auto}.svg-inline--fa.fa-border{height:1.5em}.svg-inline--fa.fa-li{width:2em}.svg-inline--fa.fa-fw{width:1.25em}.fa-layers svg.svg-inline--fa{bottom:0;left:0;margin:auto;position:absolute;right:0;top:0}.fa-layers{display:inline-block;height:1em;position:relative;text-align:center;vertical-align:-.125em;width:1em}.fa-layers svg.svg-inline--fa{transform-origin:center center}.fa-layers-counter,.fa-layers-text{display:inline-block;position:absolute;text-align:center}.fa-layers-text{left:50%;top:50%;transform:translate(-50%,-50%);transform-origin:center center}.fa-layers-counter{background-color:#ff253a;border-radius:1em;box-sizing:border-box;color:#fff;height:1.5em;line-height:1;max-width:5em;min-width:1.5em;overflow:hidden;padding:.25em;right:0;text-overflow:ellipsis;top:0;transform:scale(.25);transform-origin:top right}.fa-layers-bottom-right{bottom:0;right:0;top:auto;transform:scale(.25);transform-origin:bottom right}.fa-layers-bottom-left{bottom:0;left:0;right:auto;top:auto;transform:scale(.25);transform-origin:bottom left}.fa-layers-top-right{right:0;top:0;transform:scale(.25);transform-origin:top right}.fa-layers-top-left{left:0;right:auto;top:0;transform:scale(.25);transform-origin:top left}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{animation:a 2s infinite linear}.fa-pulse{animation:a 1s infinite steps(8)}@keyframes a{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";transform:scaleX(-1)}.fa-flip-vertical{transform:scaleY(-1)}.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-horizontal.fa-flip-vertical{transform:scale(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;position:relative;width:2em}.fa-stack-1x,.fa-stack-2x{bottom:0;left:0;margin:auto;position:absolute;right:0;top:0}.svg-inline--fa.fa-stack-1x{height:1em;width:1em}.svg-inline--fa.fa-stack-2x{height:2em;width:2em}.fa-inverse{color:#fff}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto} -------------------------------------------------------------------------------- /10/heat_stencil_2D.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define RESOLUTION_WIDTH 50 8 | #define RESOLUTION_HEIGHT 50 9 | 10 | #define PERROR fprintf(stderr, "%s:%d: error: %s\n", __FILE__, __LINE__, strerror(errno)) 11 | #define PERROR_GOTO(label) \ 12 | do { \ 13 | PERROR; \ 14 | goto label; \ 15 | } while (0) 16 | 17 | 18 | // -- vector utilities -- 19 | 20 | #define IND(y, x) ((y) * (N) + (x)) 21 | 22 | void printTemperature(double *m, int N, int M); 23 | 24 | // -- simulation code --- 25 | 26 | int main(int argc, char **argv) { 27 | // 'parsing' optional input parameter = problem size 28 | int N = 200; 29 | if (argc > 1) { 30 | N = atoi(argv[1]); 31 | } 32 | int T = N * 10; 33 | printf("Computing heat-distribution for room size %dX%d for T=%d timesteps\n", N, N, T); 34 | 35 | // ---------- setup ---------- 36 | 37 | // create a buffer for storing temperature fields 38 | double *A = malloc(sizeof(double) * N * N); 39 | 40 | if(!A) PERROR_GOTO(error_a); 41 | 42 | // set up initial conditions in A 43 | for (int i = 0; i < N; i++) { 44 | for (int j = 0; j < N; j++) { 45 | A[IND(i,j)] = 273; // temperature is 0° C everywhere (273 K) 46 | } 47 | } 48 | 49 | // and there is a heat source 50 | int source_x = N / 4; 51 | int source_y = N / 4; 52 | A[IND(source_x,source_y)] = 273 + 60; 53 | 54 | printf("Initial:"); 55 | printTemperature(A, N, N); 56 | printf("\n"); 57 | 58 | // ---------- compute ---------- 59 | 60 | // create a second buffer for the computation 61 | double *B = malloc(sizeof(double) * N * N); 62 | if(!B) PERROR_GOTO(error_b); 63 | // for each time step .. 64 | for (int t = 0; t < T; t++) { 65 | // todo implement heat propagation 66 | // todo make sure the heat source stays the same 67 | 68 | // every 1000 steps show intermediate step 69 | if (!(t % 1000)) { 70 | printf("Step t=%d\n", t); 71 | printTemperature(A, N, N); 72 | printf("\n"); 73 | } 74 | } 75 | 76 | 77 | // ---------- check ---------- 78 | 79 | printf("Final:"); 80 | printTemperature(A, N, N); 81 | printf("\n"); 82 | 83 | // simple verification if nowhere the heat is more then the heat source 84 | int success = 1; 85 | for (long long i = 0; i < N; i++) { 86 | for (long long j = 0; j < N; j++) { 87 | double temp = A[IND(i,j)]; 88 | if (273 <= temp && temp <= 273 + 60) 89 | continue; 90 | success = 0; 91 | break; 92 | } 93 | } 94 | 95 | printf("Verification: %s\n", (success) ? "OK" : "FAILED"); 96 | 97 | // todo ---------- cleanup ---------- 98 | error_b: 99 | free(B); 100 | error_a: 101 | free(A); 102 | return (success) ? EXIT_SUCCESS : EXIT_FAILURE; 103 | } 104 | 105 | void printTemperature(double *m, int N, int M) { 106 | const char *colors = " .-:=+*^X#%@"; 107 | const int numColors = 12; 108 | 109 | // boundaries for temperature (for simplicity hard-coded) 110 | const double max = 273 + 30; 111 | const double min = 273 + 0; 112 | 113 | // set the 'render' resolution 114 | int W = RESOLUTION_WIDTH; 115 | int H = RESOLUTION_HEIGHT; 116 | 117 | // step size in each dimension 118 | int sW = N / W; 119 | int sH = M / H; 120 | 121 | // upper wall 122 | printf("\t"); 123 | for (int u = 0; u < W + 2; u++) { 124 | printf("X"); 125 | } 126 | printf("\n"); 127 | // room 128 | for (int i = 0; i < H; i++) { 129 | // left wall 130 | printf("\tX"); 131 | // actual room 132 | for (int j = 0; j < W; j++) { 133 | // get max temperature in this tile 134 | double max_t = 0; 135 | for (int x = sH * i; x < sH * i + sH; x++) { 136 | for (int y = sW * j; y < sW * j + sW; y++) { 137 | max_t = (max_t < m[IND(x,y)]) ? m[IND(x,y)] : max_t; 138 | } 139 | } 140 | double temp = max_t; 141 | 142 | // pick the 'color' 143 | int c = ((temp - min) / (max - min)) * numColors; 144 | c = (c >= numColors) ? numColors - 1 : ((c < 0) ? 0 : c); 145 | 146 | // print the average temperature 147 | printf("%c", colors[c]); 148 | } 149 | // right wall 150 | printf("X\n"); 151 | } 152 | // lower wall 153 | printf("\t"); 154 | for (int l = 0; l < W + 2; l++) { 155 | printf("X"); 156 | } 157 | printf("\n"); 158 | } 159 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # UIBK PS Parallel Systems (703078, 2024) 2 | 3 | This repository contains material required to complete exercises for the 4 | Parallel Programming lab in the 2024 summer semester, including assignment 5 | sheets and any associated materials. Note that some of this material is based 6 | on previous years. 7 | 8 | **Make sure to read this document carefully, as it contains vital information 9 | regarding the grading of exercises.** 10 | 11 | ## Topics 12 | 13 | Generally, topics discussed here include 14 | 15 | - parallel programming concepts 16 | - shared memory parallelization using OpenMP 17 | - performance-oriented programming 18 | - proper experiment orchestration and benchmarking 19 | - parallel programming tools 20 | 21 | ## Schedule 22 | 23 | This schedule gives you an overview of the topics we will discuss on each date. 24 | It will be updated continuously throughout the semester. Note that exercises 25 | associated with a given date are to be discussed on that day, i.e., solutions 26 | for that assignment have to be handed in via OLAT by 17:00 on the previous day 27 | (Monday). 28 | 29 | | Date | Assignment | Topics | 30 | | ---------- | ---------- | ----------------------------------------------------------- | 31 | | 2024-03-05 | - | Administrative matters, introduction to LCC3 | 32 | | 2024-03-12 | [1](01) | Working on LCC3, initial measurements | 33 | | 2024-03-19 | [2](02) | LCC3 hardware, Amdahl's law | 34 | | 2024-04-09 | [3](03) | Sequential performance, cache effects | 35 | | 2024-04-16 | [4](04) | OpenMP parallelism, performance analysis, false sharing | 36 | | 2024-04-23 | [5](05) | OpenMP performance analysis and flush | 37 | | 2024-04-30 | [6](06) | Dependence Analysis | 38 | | 2024-05-07 | [7](07) | OpenMP correctness, auto-vectorization, dependence analysis | 39 | | 2024-05-14 | [8](08) | OpenMP affinity and loop scheduling | 40 | | 2024-05-21 | [9](09) | Vectorization | 41 | | 2024-05-28 | [10](10) | OpenMP task parallelism, heat stencil | 42 | | 2024-06-04 | [11](11) | Profiling and parallelization of a mystery application | 43 | | 2024-06-11 | [12](12) | Scalar architectures and optimizations | 44 | | 2024-06-18 | [13](13) | N-Body simulation | 45 | 46 | ## General Information 47 | 48 | All programming exercise solutions you hand in **must** compile and run on the 49 | LCC3 cluster as described in the [LCC3 tutorial](lcc3_tutorial.md). One way 50 | way of ensuring this is by developing on LCC3 directly, either through a 51 | terminal or using an editor/IDE with support for remote development via SSH 52 | (such as [Visual Studio Code](https://code.visualstudio.com/docs/remote/ssh)). 53 | 54 | Note that the default version of the GCC compiler present on LCC3 is very 55 | outdated. You may load a never version by calling `module load gcc/12.2.0-gcc-8.5.0-p4pe45v`. 56 | 57 | **As the tutorial states, use job scripts to run your applications on LCC3 58 | compute nodes, do NOT run applications directly on the LCC3 login node.** 59 | 60 | ### Connecting to LCC3 via SSH 61 | 62 | **NOTE**: You have to be inside the University network to be able to connect via 63 | SSH. See [here](https://www.uibk.ac.at/zid/netz-komm/vpn/) for more information. 64 | 65 | The hostname of LCC3 is `login.lcc3.uibk.ac.at`. 66 | 67 | ### Coding Guidelines 68 | 69 | All programming exercises are conducted in C or C++. 70 | 71 | Your code should always compile without warnings, when passing the flags `-Wall 72 | -Wextra -Werror -std=gnu11`. Error handling is your discretion, but wherever you 73 | do or do not include error handling you need to be able to justify it. 74 | 75 | Make sure your code is properly formatted using either your IDE/Text editor of 76 | choice, or by using a tool such as `clang-format`. You can find an example 77 | [.clang-format](.clang-format) file in this repository. **Failure to 78 | consistently format code may result in lower scores.** 79 | 80 | Try to write _self-documenting code_ by choosing descriptive variable and 81 | function names. While you may want to add comments to certain sections of your 82 | code, try to avoid trivial comments such as `fopen(...); // open file`. The best 83 | source code comments are the ones you do NOT need to write. **All names and 84 | comments should be written in English**. 85 | 86 | Finally, all submitted code must be accompanied by a GNU Makefile. That is, your 87 | solution must be able to be compiled with a single call to `make`. You can find 88 | an example Makefile and more information [here](example_makefile). 89 | -------------------------------------------------------------------------------- /lcc3_tutorial.md: -------------------------------------------------------------------------------- 1 | # LCC3 Cluster Tutorial 2 | 3 | This short tutorial should help you with logging in to and working on the LCC3 cluster at the University of Innsbruck. Please refer to the various links for more information or ask your course instructor in case of problems. 4 | 5 | ## General Makeup and Usage of Clusters and Supercomputers 6 | 7 | Larger clusters and supercomputers work differently than personal computers or laptops. They represent multiple individual computers (called *nodes*) that are connected via a fast network interconnect. 8 | 9 | There are two types of nodes, one or a couple of *login node(s)* and a larger number of *compute nodes*. They all usually consist of the same hardware and software stack, but differ in their usage. The login nodes are used for logging in via ssh, compiling, editing scripts or configuration files, etc. Multiple people are working simultaneously on the same login nodes and they are not used for actual computation of your applications. For this purpose, the cluster has compute nodes, which are usually reserved exclusively for running applications. 10 | 11 | The process of getting access to a compute node and running your application is handled by a so-called *submission system* which manages all node allocations, scheduling, cleanup, etc. Submission systems are required to allow a large number of scientists to share the same cluster without interference. The user interacts with these submission systems by writing *job scripts*, which tell the submission system what to do for a proper application execution. Hence, the usual working order on a cluster is 12 | 13 | 1. ssh to the login node of your cluster 14 | 2. compile the application and ensure it can be executed properly 15 | 3. write a job script 16 | 4. submit the job using the job script - the job will be placed in a queue and the submission system decides when it will be executed 17 | 5. wait for the job to start, run, and finish and inspect the output 18 | 6. depending on the output: either fix any bugs or enjoy the rest of the day 19 | 20 | ## LCC3 @ UIBK 21 | 22 | LCC3 is a cluster of the University of Innsbruck reserved exclusively for teaching purposes. The hardware is a bit dated (it used to be a fast, top-of-the-line scientific cluster in ~2011) but this is irrelevant for our purpose. The basic principles of supercomputers and high performance computing still apply, and the cluster is idle most of the time, ensuring short queuing times. 23 | 24 | ### General 25 | 26 | LCC3 is located on-campus and provides a single login node (`login.lcc3.uibk.ac.at`) and multiple compute nodes (`n000`-`n0XX`). The submission system used by LCC3 is SLURM. Each node consists of two Intel Xeon X5650 six-core processors and 48 GB of main memory. **The system is reachable only from within the UIBK network (requires VPN when working from home).** 27 | 28 | More documentation can be found on the ZID website https://www.uibk.ac.at/zid/systeme/hpc-systeme/leo3/. 29 | 30 | ### Storage 31 | 32 | LCC3 has two main storage mount points, `/home/cb76/` (`$HOME`) and `/scratch/` (`$SCRATCH`) , both of which are network-mounted on all login and compute nodes. The former is limited to 1 GB, hence if you run out of storage or start to get weird-looking I/O errors, consider moving your stuff to `/scratch/`, which has a limit of 100 GB. 33 | 34 | ### Submission System 35 | 36 | While you should consult the SLURM documentation (e.g. https://www.uibk.ac.at/zid/systeme/hpc-systeme/common/tutorials/slurm-tutorial.html) for further information, the most important commands are briefly described below: 37 | 38 | * `sbatch ` - submit a job 39 | * `scancel ` - delete a job before or during execution 40 | * `squ` - show queued jobs of the cluster 41 | * `srun --pty bash` - login interactively on a compute node (for short debugging sessions only, don't leave this open/idle) 42 | 43 | ### SLURM Example Job Script for OpenMP applications 44 | 45 | While all commands can also be given to `sbatch` on the command line, users usually write job scripts for proper documentation and for keeping the command line invocation as short as possible. The commands in the job script are special comments, marked with `#SBATCH`, which are read and processed by `sbatch`. See [job.sh](job.sh) for an example script. 46 | 47 | ### Module System 48 | 49 | Clusters usually have a lot of software packages installed, often in multiple versions, which might conflict with each other. For this purpose, they use the module system for managing which packages are visible to the user. The most important commands are: 50 | 51 | * `module avail` - show available modules that can be loaded 52 | * `module list` - show modules currently loaded 53 | * `module load ` - load a module 54 | * `module unload ` - unload a module 55 | 56 | ### Useful Links 57 | 58 | * Current workload of LCC3 (only works within the UIBK network): https://login.lcc3.uibk.ac.at/cgi-bin/state.pl 59 | * Hardware details: https://www.uibk.ac.at/zid/systeme/hpc-systeme/leo3/hardware/ 60 | -------------------------------------------------------------------------------- /12/README.md: -------------------------------------------------------------------------------- 1 | # Assignment 12 2 | 3 | The goal of this assignment is to study program optimizations of scalar architectures. 4 | 5 | ## Exercise 1 (1.5 Points) 6 | 7 | ### Description 8 | 9 | Assume that during testing of your program on a scalar architecture, you found that the execution time is too high, and you have to optimize it. You suppose that the following extracts significantly impact the execution time of your program. 10 | 11 | **a)** `c1` is of type `unsigned`: 12 | 13 | ```C 14 | unsigned c2 = 32 * c1; 15 | ``` 16 | 17 | **b)** `c1` is of type `unsigned`: 18 | 19 | ```C 20 | unsigned c2 = 15 * c1; 21 | ``` 22 | 23 | **c)** `c1` is of type `unsigned`: 24 | 25 | ```C 26 | unsigned c2 = 96 * c1; 27 | ``` 28 | 29 | _Hint_: use shift(s) and addition(s) to replace the multiplication 30 | 31 | **d)** `c1` is of type `unsigned`: 32 | 33 | ```C 34 | unsigned c2 = 0.125 * c1; 35 | ``` 36 | 37 | **e)** `a` is of type `unsigned *`: 38 | 39 | ```C 40 | unsigned sum_fifth = 0; 41 | 42 | for (int i = 0; i < N / 5; ++i) { 43 | sum_fifth += a[5 * i]; 44 | } 45 | ``` 46 | 47 | **f)** `a` is of type `double *`: 48 | 49 | ```C 50 | for (int i = 0; i < N; ++i) { 51 | a[i] += i / 5.3; 52 | } 53 | ``` 54 | 55 | **g)** `c1` is of type `float`: 56 | 57 | ```C 58 | float c2 = -1 * c1; 59 | ``` 60 | 61 | _Hint_: Inquire how IEEE 754 single-precision floating-point numbers are represented in memory. 62 | 63 | ### Tasks 64 | 65 | 1) Apply strength reduction. 66 | 2) State under which circumstances the transformation should be applied (e.g. if the cost of performing two additions is less than one multiplication). 67 | 3) After you have applied strength reduction, compare the assembly code of the original snippets with your transformation. Investigate how the compiler (`gcc`) optimizes the snippets when using `-O3` and whether the compiler uses your transformation or applies another optimization on top of it. You can use [Compiler Explorer](https://godbolt.org/) to carry out this task. The given examples are already available at . Note that you can easily navigate to the assembler code for a given input source line by right-clicking, but be aware that the source for one line might be distributed among interleaved instructions. 68 | 69 | ## Exercise 2 (1.5 Points) 70 | 71 | ### Description 72 | 73 | For each loop iteration instructions such as compare and add operations have to be performed. If the number of executions is sufficiently large this can have an impact on the performance of the program. Investigate the following given code examples along with their task and, for each example, study why the transformation may or may not be beneficial. \ 74 | Furthermore, for each example, you are asked to compare the performance counters of the original and the transformed code. Therefore, you should create a small test program for each configuration, compile it with `gcc` using `-O3`, and profile it with `perf` on LCC3. 75 | Note that if not stated otherwise, variables and array elements are of type `int`. 76 | 77 | ### Tasks 78 | 79 | 1) Apply loop unrolling. Note that you can assume that `N` is odd. 80 | 81 | ```C 82 | for (int i = 0; i < N - 1; ++i) { 83 | a[i] = b[i] + b[i + 1]; 84 | } 85 | ``` 86 | 87 | 2) Apply loop-invariant code motion (`a` is of type `double *`): 88 | 89 | ```C 90 | for (int i = 0; i < N; ++i) { 91 | a[i] *= hypot(0.3, 0.4); 92 | } 93 | ``` 94 | 95 | 3) Apply loop unswitching: 96 | 97 | ```C 98 | for (int i = 0; i < N; ++i) { 99 | if (N % 2) { 100 | a[i] = b[i] + 5; 101 | } else { 102 | a[i] = c[i] + 5; 103 | } 104 | } 105 | ``` 106 | 107 | 4) Apply loop fission/distribution. Does this transformation impact the number of cache misses? 108 | 109 | ```C 110 | for (int i = 0; i < N; ++i) { 111 | sum_a += a[i]; 112 | sum_b += b[i]; 113 | sum_c += c[i]; 114 | } 115 | ``` 116 | 117 | 5) Apply loop peeling and loop fusion/combination. Note that `N` is larger than `0`. 118 | 119 | ```C 120 | int min = a[0]; 121 | for (int i = 1; i < N; ++i) { 122 | min = (a[i] < min) ? a[i] : min; 123 | } 124 | for (int i = 0; i < N; ++i) { 125 | sum += a[i]; 126 | } 127 | ``` 128 | 129 | 6) Apply loop splitting: 130 | 131 | ```C 132 | for (int i = 0; i < N; ++i) { 133 | if (i % 2) { 134 | a[i] = b[i] + 4; 135 | } else { 136 | a[i] = c[i] + 5; 137 | } 138 | } 139 | ``` 140 | 141 | 7) Apply loop tiling (`a`, `b`, and `c` are of type `double`). You can assume that a macro `BLOCK_SIZE`, which is defined in some boilerplate code, defines a suitable block size for tiling (e.g., `#define BLOCK_SIZE 64 / sizeof(double)`). \ 142 | 143 | ```C 144 | for (int i = 0; i < N; ++i) { 145 | for (int j = 0; j < N; ++j) { 146 | for (int k = 0; k < N; ++k) { 147 | c[i][j] = a[i][k] * b[k][j]; 148 | } 149 | } 150 | } 151 | ``` 152 | 153 | ## General Notes 154 | 155 | All the material required by the tasks above (e.g., code, figures, text, etc...) must be part of the solution that is handed in. Your experiments should be reproducible and comparable to your measurements using the solution materials that you hand in. 156 | 157 | **Every** member of your group must be able to explain the given problem, your solution, and possible findings. You may also need to answer detailed questions about any of these aspects. 158 | -------------------------------------------------------------------------------- /09/README.md: -------------------------------------------------------------------------------- 1 | # Assignment 9 2 | 3 | The goal of this assignment is to study several means of vectorizing a simple program. 4 | 5 | ## Exercise 1 (1 Point) 6 | 7 | ### Description 8 | 9 | In this exercise, we will employ auto-vectorization of the compiler to increase the performance of a small program that computes a multiply-add operation on three vectors. 10 | 11 | ### Tasks 12 | 13 | - Write a sequential program that computes `a[i] += b[i] * c[i]` for three `float` vectors `a`, `b`, and `c`. Enclose this computation in a loop such that it is repeated `1e6` times. I.e. your code should look like this: 14 | 15 | ``` 16 | for(int run = 0; run < repetitions; ++run) { 17 | for(int i = 0; i < size; ++i) { 18 | a[i] += b[i] * c[i]; 19 | } 20 | } 21 | ``` 22 | 23 | - Initialize the vectors with constant values and add some output that allows you to verify correct computation of the program for subsequent optimization steps (try to avoid overflows). Compile this program on LCC3 with `gcc 12.2.0` using `-O1` and measure the execution time **of the computation only** for several problem sizes (=vector lengths). This sequential program is our baseline reference. 24 | - Try to use auto-vectorization in the compiler to vectorize the computation. Investigate which flag(s) to use for that, and try to limit your compiler change to only enable vectorization but not any other optimizations. Measure the execution time for the same problem sizes as before and compute the respective speedups. What can you observe in terms of performance? Is the result still correct? Does varying the problem size affect the performance gain or loss? 25 | - Use `perf` to further investigate the origin of any performance difference you might observe. `perf stat -e rYYXX` (mind the order of X and Y!) allows you to measure custom events supported by the CPU, where - on Intel systems - XX is the so-called _event code_ and YY is the so-called _unit mask_ (also called _umask_). A few event codes and unit masks for measuring vectorized instructions are given below. Check which ones are suitable for your investigation: 26 | 27 | | Name | Event Code | Unit Mask | 28 | |--------------------------------------|:----------:|:---------:| 29 | | FP_COMP_OPS_EXE.X87 | 10 | 01 | 30 | | FP_COMP_OPS_EXE.MMX | 10 | 02 | 31 | | FP_COMP_OPS_EXE.SSE_FP | 10 | 04 | 32 | | FP_COMP_OPS_EXE.SSE2_INTEGER | 10 | 08 | 33 | | FP_COMP_OPS_EXE.SSE_FP_PACKED | 10 | 10 | 34 | | FP_COMP_OPS_EXE.SSE_FP_SCALAR | 10 | 20 | 35 | | FP_COMP_OPS_EXE.SSE_SINGLE_PRECISION | 10 | 40 | 36 | | FP_COMP_OPS_EXE.SSE_DOUBLE_PRECISION | 10 | 80 | 37 | 38 | In case you are interested: For further events relevant to the CPU type on LCC3 and short event descriptions, see [Intel's perfmon web interface](https://perfmon-events.intel.com/) (pay attention to choosing a suitable micro-architecture) or alternatively [Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3B: System Programming Guide, Part 2](https://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-3b-part-2-manual.html). It lists all events that can be counted with `perf` on our hardware. 39 | 40 | - Enter the wall clock time of the sequential program and the auto-vectorized version with size 2048 and 1e6 repetitions to the spreadsheet linked on Discord. 41 | 42 | ## Exercise 2 (1 Point) 43 | 44 | ### Description 45 | 46 | Instead of relying on the compiler to vectorize the code for us, we will do so manually in this exercise, using OpenMP. 47 | 48 | ### Tasks 49 | 50 | - Vectorize your sequential program using OpenMP. Do not use any OpenMP thread-based parallelism. 51 | - Compile your OpenMP-vectorized code with `-O1` but without any compiler flags for auto-vectorization and compare its performance for the problem size 2048 to both the sequential version and the compiler-vectorized version. What can you observe? Is the result still correct? 52 | - Verify any findings using `perf` as described in Exercise 1. 53 | - Repeat the sequential and OpenMP executions when changing the data type from `float` to `double`. What can you observe? 54 | - How does the solution for this Exercise compare to Exercise 1? Are there any advantages or disadvantages? 55 | - Enter the wall clock time of the OpenMP-vectorized version with size 2048, 1e6 repetitions and data type `float` to the spreadsheet linked on Discord. 56 | 57 | ## Exercise 3 (1 Point) 58 | 59 | ### Description 60 | 61 | Instead of relying on OpenMP for vectorization, we will do so using compiler-specific intrinsics in this exercise. 62 | 63 | ### Tasks 64 | 65 | - Vectorize your code for `float` types using the gcc-specific intrinsic functions `_mm_load_ps`, `_mm_add_ps`, `_mm_mul_ps`, and `_mm_store_ps`. Do not forget to include the respective header `xmmintrin.h`. 66 | - Compile your manually vectorized code with `-O1` but without any compiler flags for auto-vectorization and compare its performance for your set of problem sizes to your previous code versions. What can you observe? Is the result still correct? 67 | - Verify any findings using `perf` as described in Exercise 1. 68 | - How does the solution for this Exercise compare to Exercise 2 and Exercise 1? Are there any advantages or disadvantages? 69 | - Enter the wall clock time of the compiler-specific intrinsics version with size 2048 and 1e6 repetitions to the spreadsheet linked on Discord. 70 | 71 | ## General Notes 72 | 73 | All the material required by the tasks above (e.g., code, figures, text, etc...) must be part of the solution that is handed in. Your experiments should be reproducible and comparable to your measurements using the solution materials that you hand in. 74 | 75 | **Every** member of your group must be able to explain the given problem, your solution, and possible findings. You may also need to answer detailed questions about any of these aspects. 76 | -------------------------------------------------------------------------------- /docs/plugin/search/plugin.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Handles finding a text string anywhere in the slides and showing the next occurrence to the user 3 | * by navigatating to that slide and highlighting it. 4 | * 5 | * @author Jon Snyder , February 2013 6 | */ 7 | 8 | const Plugin = () => { 9 | 10 | // The reveal.js instance this plugin is attached to 11 | let deck; 12 | 13 | let searchElement; 14 | let searchButton; 15 | let searchInput; 16 | 17 | let matchedSlides; 18 | let currentMatchedIndex; 19 | let searchboxDirty; 20 | let hilitor; 21 | 22 | function render() { 23 | 24 | searchElement = document.createElement( 'div' ); 25 | searchElement.classList.add( 'searchbox' ); 26 | searchElement.style.position = 'absolute'; 27 | searchElement.style.top = '10px'; 28 | searchElement.style.right = '10px'; 29 | searchElement.style.zIndex = 10; 30 | 31 | //embedded base64 search icon Designed by Sketchdock - http://www.sketchdock.com/: 32 | searchElement.innerHTML = ` 33 | `; 34 | 35 | searchInput = searchElement.querySelector( '.searchinput' ); 36 | searchInput.style.width = '240px'; 37 | searchInput.style.fontSize = '14px'; 38 | searchInput.style.padding = '4px 6px'; 39 | searchInput.style.color = '#000'; 40 | searchInput.style.background = '#fff'; 41 | searchInput.style.borderRadius = '2px'; 42 | searchInput.style.border = '0'; 43 | searchInput.style.outline = '0'; 44 | searchInput.style.boxShadow = '0 2px 18px rgba(0, 0, 0, 0.2)'; 45 | searchInput.style['-webkit-appearance'] = 'none'; 46 | 47 | deck.getRevealElement().appendChild( searchElement ); 48 | 49 | // searchButton.addEventListener( 'click', function(event) { 50 | // doSearch(); 51 | // }, false ); 52 | 53 | searchInput.addEventListener( 'keyup', function( event ) { 54 | switch (event.keyCode) { 55 | case 13: 56 | event.preventDefault(); 57 | doSearch(); 58 | searchboxDirty = false; 59 | break; 60 | default: 61 | searchboxDirty = true; 62 | } 63 | }, false ); 64 | 65 | closeSearch(); 66 | 67 | } 68 | 69 | function openSearch() { 70 | if( !searchElement ) render(); 71 | 72 | searchElement.style.display = 'inline'; 73 | searchInput.focus(); 74 | searchInput.select(); 75 | } 76 | 77 | function closeSearch() { 78 | if( !searchElement ) render(); 79 | 80 | searchElement.style.display = 'none'; 81 | if(hilitor) hilitor.remove(); 82 | } 83 | 84 | function toggleSearch() { 85 | if( !searchElement ) render(); 86 | 87 | if (searchElement.style.display !== 'inline') { 88 | openSearch(); 89 | } 90 | else { 91 | closeSearch(); 92 | } 93 | } 94 | 95 | function doSearch() { 96 | //if there's been a change in the search term, perform a new search: 97 | if (searchboxDirty) { 98 | var searchstring = searchInput.value; 99 | 100 | if (searchstring === '') { 101 | if(hilitor) hilitor.remove(); 102 | matchedSlides = null; 103 | } 104 | else { 105 | //find the keyword amongst the slides 106 | hilitor = new Hilitor("slidecontent"); 107 | matchedSlides = hilitor.apply(searchstring); 108 | currentMatchedIndex = 0; 109 | } 110 | } 111 | 112 | if (matchedSlides) { 113 | //navigate to the next slide that has the keyword, wrapping to the first if necessary 114 | if (matchedSlides.length && (matchedSlides.length <= currentMatchedIndex)) { 115 | currentMatchedIndex = 0; 116 | } 117 | if (matchedSlides.length > currentMatchedIndex) { 118 | deck.slide(matchedSlides[currentMatchedIndex].h, matchedSlides[currentMatchedIndex].v); 119 | currentMatchedIndex++; 120 | } 121 | } 122 | } 123 | 124 | // Original JavaScript code by Chirp Internet: www.chirp.com.au 125 | // Please acknowledge use of this code by including this header. 126 | // 2/2013 jon: modified regex to display any match, not restricted to word boundaries. 127 | function Hilitor(id, tag) { 128 | 129 | var targetNode = document.getElementById(id) || document.body; 130 | var hiliteTag = tag || "EM"; 131 | var skipTags = new RegExp("^(?:" + hiliteTag + "|SCRIPT|FORM)$"); 132 | var colors = ["#ff6", "#a0ffff", "#9f9", "#f99", "#f6f"]; 133 | var wordColor = []; 134 | var colorIdx = 0; 135 | var matchRegex = ""; 136 | var matchingSlides = []; 137 | 138 | this.setRegex = function(input) 139 | { 140 | input = input.replace(/^[^\w]+|[^\w]+$/g, "").replace(/[^\w'-]+/g, "|"); 141 | matchRegex = new RegExp("(" + input + ")","i"); 142 | } 143 | 144 | this.getRegex = function() 145 | { 146 | return matchRegex.toString().replace(/^\/\\b\(|\)\\b\/i$/g, "").replace(/\|/g, " "); 147 | } 148 | 149 | // recursively apply word highlighting 150 | this.hiliteWords = function(node) 151 | { 152 | if(node == undefined || !node) return; 153 | if(!matchRegex) return; 154 | if(skipTags.test(node.nodeName)) return; 155 | 156 | if(node.hasChildNodes()) { 157 | for(var i=0; i < node.childNodes.length; i++) 158 | this.hiliteWords(node.childNodes[i]); 159 | } 160 | if(node.nodeType == 3) { // NODE_TEXT 161 | var nv, regs; 162 | if((nv = node.nodeValue) && (regs = matchRegex.exec(nv))) { 163 | //find the slide's section element and save it in our list of matching slides 164 | var secnode = node; 165 | while (secnode != null && secnode.nodeName != 'SECTION') { 166 | secnode = secnode.parentNode; 167 | } 168 | 169 | var slideIndex = deck.getIndices(secnode); 170 | var slidelen = matchingSlides.length; 171 | var alreadyAdded = false; 172 | for (var i=0; i < slidelen; i++) { 173 | if ( (matchingSlides[i].h === slideIndex.h) && (matchingSlides[i].v === slideIndex.v) ) { 174 | alreadyAdded = true; 175 | } 176 | } 177 | if (! alreadyAdded) { 178 | matchingSlides.push(slideIndex); 179 | } 180 | 181 | if(!wordColor[regs[0].toLowerCase()]) { 182 | wordColor[regs[0].toLowerCase()] = colors[colorIdx++ % colors.length]; 183 | } 184 | 185 | var match = document.createElement(hiliteTag); 186 | match.appendChild(document.createTextNode(regs[0])); 187 | match.style.backgroundColor = wordColor[regs[0].toLowerCase()]; 188 | match.style.fontStyle = "inherit"; 189 | match.style.color = "#000"; 190 | 191 | var after = node.splitText(regs.index); 192 | after.nodeValue = after.nodeValue.substring(regs[0].length); 193 | node.parentNode.insertBefore(match, after); 194 | } 195 | } 196 | }; 197 | 198 | // remove highlighting 199 | this.remove = function() 200 | { 201 | var arr = document.getElementsByTagName(hiliteTag); 202 | var el; 203 | while(arr.length && (el = arr[0])) { 204 | el.parentNode.replaceChild(el.firstChild, el); 205 | } 206 | }; 207 | 208 | // start highlighting at target node 209 | this.apply = function(input) 210 | { 211 | if(input == undefined || !input) return; 212 | this.remove(); 213 | this.setRegex(input); 214 | this.hiliteWords(targetNode); 215 | return matchingSlides; 216 | }; 217 | 218 | } 219 | 220 | return { 221 | 222 | id: 'search', 223 | 224 | init: reveal => { 225 | 226 | deck = reveal; 227 | deck.registerKeyboardShortcut( 'CTRL + Shift + F', 'Search' ); 228 | 229 | document.addEventListener( 'keydown', function( event ) { 230 | if( event.key == "F" && (event.ctrlKey || event.metaKey) ) { //Control+Shift+f 231 | event.preventDefault(); 232 | toggleSearch(); 233 | } 234 | }, false ); 235 | 236 | }, 237 | 238 | open: openSearch 239 | 240 | } 241 | }; 242 | 243 | export default Plugin; -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 16 | 17 | 18 | reveal.js 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 |
30 |
35 | 234 |
235 |
236 |
237 | 238 | 239 | 240 | 241 | 242 | 243 | 263 | 264 | 265 | -------------------------------------------------------------------------------- /docs/plugin/notes/plugin.js: -------------------------------------------------------------------------------- 1 | import speakerViewHTML from './speaker-view.html' 2 | 3 | import { marked } from 'marked'; 4 | 5 | /** 6 | * Handles opening of and synchronization with the reveal.js 7 | * notes window. 8 | * 9 | * Handshake process: 10 | * 1. This window posts 'connect' to notes window 11 | * - Includes URL of presentation to show 12 | * 2. Notes window responds with 'connected' when it is available 13 | * 3. This window proceeds to send the current presentation state 14 | * to the notes window 15 | */ 16 | const Plugin = () => { 17 | 18 | let connectInterval; 19 | let speakerWindow = null; 20 | let deck; 21 | 22 | /** 23 | * Opens a new speaker view window. 24 | */ 25 | function openSpeakerWindow() { 26 | 27 | // If a window is already open, focus it 28 | if( speakerWindow && !speakerWindow.closed ) { 29 | speakerWindow.focus(); 30 | } 31 | else { 32 | speakerWindow = window.open( 'about:blank', 'reveal.js - Notes', 'width=1100,height=700' ); 33 | speakerWindow.marked = marked; 34 | speakerWindow.document.write( speakerViewHTML ); 35 | 36 | if( !speakerWindow ) { 37 | alert( 'Speaker view popup failed to open. Please make sure popups are allowed and reopen the speaker view.' ); 38 | return; 39 | } 40 | 41 | connect(); 42 | } 43 | 44 | } 45 | 46 | /** 47 | * Reconnect with an existing speaker view window. 48 | */ 49 | function reconnectSpeakerWindow( reconnectWindow ) { 50 | 51 | if( speakerWindow && !speakerWindow.closed ) { 52 | speakerWindow.focus(); 53 | } 54 | else { 55 | speakerWindow = reconnectWindow; 56 | window.addEventListener( 'message', onPostMessage ); 57 | onConnected(); 58 | } 59 | 60 | } 61 | 62 | /** 63 | * Connect to the notes window through a postmessage handshake. 64 | * Using postmessage enables us to work in situations where the 65 | * origins differ, such as a presentation being opened from the 66 | * file system. 67 | */ 68 | function connect() { 69 | 70 | const presentationURL = deck.getConfig().url; 71 | 72 | const url = typeof presentationURL === 'string' ? presentationURL : 73 | window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search; 74 | 75 | // Keep trying to connect until we get a 'connected' message back 76 | connectInterval = setInterval( function() { 77 | speakerWindow.postMessage( JSON.stringify( { 78 | namespace: 'reveal-notes', 79 | type: 'connect', 80 | state: deck.getState(), 81 | url 82 | } ), '*' ); 83 | }, 500 ); 84 | 85 | window.addEventListener( 'message', onPostMessage ); 86 | 87 | } 88 | 89 | /** 90 | * Calls the specified Reveal.js method with the provided argument 91 | * and then pushes the result to the notes frame. 92 | */ 93 | function callRevealApi( methodName, methodArguments, callId ) { 94 | 95 | let result = deck[methodName].apply( deck, methodArguments ); 96 | speakerWindow.postMessage( JSON.stringify( { 97 | namespace: 'reveal-notes', 98 | type: 'return', 99 | result, 100 | callId 101 | } ), '*' ); 102 | 103 | } 104 | 105 | /** 106 | * Posts the current slide data to the notes window. 107 | */ 108 | function post( event ) { 109 | 110 | let slideElement = deck.getCurrentSlide(), 111 | notesElements = slideElement.querySelectorAll( 'aside.notes' ), 112 | fragmentElement = slideElement.querySelector( '.current-fragment' ); 113 | 114 | let messageData = { 115 | namespace: 'reveal-notes', 116 | type: 'state', 117 | notes: '', 118 | markdown: false, 119 | whitespace: 'normal', 120 | state: deck.getState() 121 | }; 122 | 123 | // Look for notes defined in a slide attribute 124 | if( slideElement.hasAttribute( 'data-notes' ) ) { 125 | messageData.notes = slideElement.getAttribute( 'data-notes' ); 126 | messageData.whitespace = 'pre-wrap'; 127 | } 128 | 129 | // Look for notes defined in a fragment 130 | if( fragmentElement ) { 131 | let fragmentNotes = fragmentElement.querySelector( 'aside.notes' ); 132 | if( fragmentNotes ) { 133 | messageData.notes = fragmentNotes.innerHTML; 134 | messageData.markdown = typeof fragmentNotes.getAttribute( 'data-markdown' ) === 'string'; 135 | 136 | // Ignore other slide notes 137 | notesElements = null; 138 | } 139 | else if( fragmentElement.hasAttribute( 'data-notes' ) ) { 140 | messageData.notes = fragmentElement.getAttribute( 'data-notes' ); 141 | messageData.whitespace = 'pre-wrap'; 142 | 143 | // In case there are slide notes 144 | notesElements = null; 145 | } 146 | } 147 | 148 | // Look for notes defined in an aside element 149 | if( notesElements ) { 150 | messageData.notes = Array.from(notesElements).map( notesElement => notesElement.innerHTML ).join( '\n' ); 151 | messageData.markdown = notesElements[0] && typeof notesElements[0].getAttribute( 'data-markdown' ) === 'string'; 152 | } 153 | 154 | speakerWindow.postMessage( JSON.stringify( messageData ), '*' ); 155 | 156 | } 157 | 158 | /** 159 | * Check if the given event is from the same origin as the 160 | * current window. 161 | */ 162 | function isSameOriginEvent( event ) { 163 | 164 | try { 165 | return window.location.origin === event.source.location.origin; 166 | } 167 | catch ( error ) { 168 | return false; 169 | } 170 | 171 | } 172 | 173 | function onPostMessage( event ) { 174 | 175 | // Only allow same-origin messages 176 | // (added 12/5/22 as a XSS safeguard) 177 | if( isSameOriginEvent( event ) ) { 178 | 179 | let data = JSON.parse( event.data ); 180 | if( data && data.namespace === 'reveal-notes' && data.type === 'connected' ) { 181 | clearInterval( connectInterval ); 182 | onConnected(); 183 | } 184 | else if( data && data.namespace === 'reveal-notes' && data.type === 'call' ) { 185 | callRevealApi( data.methodName, data.arguments, data.callId ); 186 | } 187 | 188 | } 189 | 190 | } 191 | 192 | /** 193 | * Called once we have established a connection to the notes 194 | * window. 195 | */ 196 | function onConnected() { 197 | 198 | // Monitor events that trigger a change in state 199 | deck.on( 'slidechanged', post ); 200 | deck.on( 'fragmentshown', post ); 201 | deck.on( 'fragmenthidden', post ); 202 | deck.on( 'overviewhidden', post ); 203 | deck.on( 'overviewshown', post ); 204 | deck.on( 'paused', post ); 205 | deck.on( 'resumed', post ); 206 | 207 | // Post the initial state 208 | post(); 209 | 210 | } 211 | 212 | return { 213 | id: 'notes', 214 | 215 | init: function( reveal ) { 216 | 217 | deck = reveal; 218 | 219 | if( !/receiver/i.test( window.location.search ) ) { 220 | 221 | // If the there's a 'notes' query set, open directly 222 | if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) { 223 | openSpeakerWindow(); 224 | } 225 | else { 226 | // Keep listening for speaker view hearbeats. If we receive a 227 | // heartbeat from an orphaned window, reconnect it. This ensures 228 | // that we remain connected to the notes even if the presentation 229 | // is reloaded. 230 | window.addEventListener( 'message', event => { 231 | 232 | if( !speakerWindow && typeof event.data === 'string' ) { 233 | let data; 234 | 235 | try { 236 | data = JSON.parse( event.data ); 237 | } 238 | catch( error ) {} 239 | 240 | if( data && data.namespace === 'reveal-notes' && data.type === 'heartbeat' ) { 241 | reconnectSpeakerWindow( event.source ); 242 | } 243 | } 244 | }); 245 | } 246 | 247 | // Open the notes when the 's' key is hit 248 | deck.addKeyBinding({keyCode: 83, key: 'S', description: 'Speaker notes view'}, function() { 249 | openSpeakerWindow(); 250 | } ); 251 | 252 | } 253 | 254 | }, 255 | 256 | open: openSpeakerWindow 257 | }; 258 | 259 | }; 260 | 261 | export default Plugin; 262 | -------------------------------------------------------------------------------- /docs/plugin/zoom/plugin.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * reveal.js Zoom plugin 3 | */ 4 | const Plugin = { 5 | 6 | id: 'zoom', 7 | 8 | init: function( reveal ) { 9 | 10 | reveal.getRevealElement().addEventListener( 'mousedown', function( event ) { 11 | var defaultModifier = /Linux/.test( window.navigator.platform ) ? 'ctrl' : 'alt'; 12 | 13 | var modifier = ( reveal.getConfig().zoomKey ? reveal.getConfig().zoomKey : defaultModifier ) + 'Key'; 14 | var zoomLevel = ( reveal.getConfig().zoomLevel ? reveal.getConfig().zoomLevel : 2 ); 15 | 16 | if( event[ modifier ] && !reveal.isOverview() ) { 17 | event.preventDefault(); 18 | 19 | zoom.to({ 20 | x: event.clientX, 21 | y: event.clientY, 22 | scale: zoomLevel, 23 | pan: false 24 | }); 25 | } 26 | } ); 27 | 28 | }, 29 | 30 | destroy: () => { 31 | 32 | zoom.reset(); 33 | 34 | } 35 | 36 | }; 37 | 38 | export default () => Plugin; 39 | 40 | /*! 41 | * zoom.js 0.3 (modified for use with reveal.js) 42 | * http://lab.hakim.se/zoom-js 43 | * MIT licensed 44 | * 45 | * Copyright (C) 2011-2014 Hakim El Hattab, http://hakim.se 46 | */ 47 | var zoom = (function(){ 48 | 49 | // The current zoom level (scale) 50 | var level = 1; 51 | 52 | // The current mouse position, used for panning 53 | var mouseX = 0, 54 | mouseY = 0; 55 | 56 | // Timeout before pan is activated 57 | var panEngageTimeout = -1, 58 | panUpdateInterval = -1; 59 | 60 | // Check for transform support so that we can fallback otherwise 61 | var supportsTransforms = 'transform' in document.body.style; 62 | 63 | if( supportsTransforms ) { 64 | // The easing that will be applied when we zoom in/out 65 | document.body.style.transition = 'transform 0.8s ease'; 66 | } 67 | 68 | // Zoom out if the user hits escape 69 | document.addEventListener( 'keyup', function( event ) { 70 | if( level !== 1 && event.keyCode === 27 ) { 71 | zoom.out(); 72 | } 73 | } ); 74 | 75 | // Monitor mouse movement for panning 76 | document.addEventListener( 'mousemove', function( event ) { 77 | if( level !== 1 ) { 78 | mouseX = event.clientX; 79 | mouseY = event.clientY; 80 | } 81 | } ); 82 | 83 | /** 84 | * Applies the CSS required to zoom in, prefers the use of CSS3 85 | * transforms but falls back on zoom for IE. 86 | * 87 | * @param {Object} rect 88 | * @param {Number} scale 89 | */ 90 | function magnify( rect, scale ) { 91 | 92 | var scrollOffset = getScrollOffset(); 93 | 94 | // Ensure a width/height is set 95 | rect.width = rect.width || 1; 96 | rect.height = rect.height || 1; 97 | 98 | // Center the rect within the zoomed viewport 99 | rect.x -= ( window.innerWidth - ( rect.width * scale ) ) / 2; 100 | rect.y -= ( window.innerHeight - ( rect.height * scale ) ) / 2; 101 | 102 | if( supportsTransforms ) { 103 | // Reset 104 | if( scale === 1 ) { 105 | document.body.style.transform = ''; 106 | } 107 | // Scale 108 | else { 109 | var origin = scrollOffset.x +'px '+ scrollOffset.y +'px', 110 | transform = 'translate('+ -rect.x +'px,'+ -rect.y +'px) scale('+ scale +')'; 111 | 112 | document.body.style.transformOrigin = origin; 113 | document.body.style.transform = transform; 114 | } 115 | } 116 | else { 117 | // Reset 118 | if( scale === 1 ) { 119 | document.body.style.position = ''; 120 | document.body.style.left = ''; 121 | document.body.style.top = ''; 122 | document.body.style.width = ''; 123 | document.body.style.height = ''; 124 | document.body.style.zoom = ''; 125 | } 126 | // Scale 127 | else { 128 | document.body.style.position = 'relative'; 129 | document.body.style.left = ( - ( scrollOffset.x + rect.x ) / scale ) + 'px'; 130 | document.body.style.top = ( - ( scrollOffset.y + rect.y ) / scale ) + 'px'; 131 | document.body.style.width = ( scale * 100 ) + '%'; 132 | document.body.style.height = ( scale * 100 ) + '%'; 133 | document.body.style.zoom = scale; 134 | } 135 | } 136 | 137 | level = scale; 138 | 139 | if( document.documentElement.classList ) { 140 | if( level !== 1 ) { 141 | document.documentElement.classList.add( 'zoomed' ); 142 | } 143 | else { 144 | document.documentElement.classList.remove( 'zoomed' ); 145 | } 146 | } 147 | } 148 | 149 | /** 150 | * Pan the document when the mosue cursor approaches the edges 151 | * of the window. 152 | */ 153 | function pan() { 154 | var range = 0.12, 155 | rangeX = window.innerWidth * range, 156 | rangeY = window.innerHeight * range, 157 | scrollOffset = getScrollOffset(); 158 | 159 | // Up 160 | if( mouseY < rangeY ) { 161 | window.scroll( scrollOffset.x, scrollOffset.y - ( 1 - ( mouseY / rangeY ) ) * ( 14 / level ) ); 162 | } 163 | // Down 164 | else if( mouseY > window.innerHeight - rangeY ) { 165 | window.scroll( scrollOffset.x, scrollOffset.y + ( 1 - ( window.innerHeight - mouseY ) / rangeY ) * ( 14 / level ) ); 166 | } 167 | 168 | // Left 169 | if( mouseX < rangeX ) { 170 | window.scroll( scrollOffset.x - ( 1 - ( mouseX / rangeX ) ) * ( 14 / level ), scrollOffset.y ); 171 | } 172 | // Right 173 | else if( mouseX > window.innerWidth - rangeX ) { 174 | window.scroll( scrollOffset.x + ( 1 - ( window.innerWidth - mouseX ) / rangeX ) * ( 14 / level ), scrollOffset.y ); 175 | } 176 | } 177 | 178 | function getScrollOffset() { 179 | return { 180 | x: window.scrollX !== undefined ? window.scrollX : window.pageXOffset, 181 | y: window.scrollY !== undefined ? window.scrollY : window.pageYOffset 182 | } 183 | } 184 | 185 | return { 186 | /** 187 | * Zooms in on either a rectangle or HTML element. 188 | * 189 | * @param {Object} options 190 | * - element: HTML element to zoom in on 191 | * OR 192 | * - x/y: coordinates in non-transformed space to zoom in on 193 | * - width/height: the portion of the screen to zoom in on 194 | * - scale: can be used instead of width/height to explicitly set scale 195 | */ 196 | to: function( options ) { 197 | 198 | // Due to an implementation limitation we can't zoom in 199 | // to another element without zooming out first 200 | if( level !== 1 ) { 201 | zoom.out(); 202 | } 203 | else { 204 | options.x = options.x || 0; 205 | options.y = options.y || 0; 206 | 207 | // If an element is set, that takes precedence 208 | if( !!options.element ) { 209 | // Space around the zoomed in element to leave on screen 210 | var padding = 20; 211 | var bounds = options.element.getBoundingClientRect(); 212 | 213 | options.x = bounds.left - padding; 214 | options.y = bounds.top - padding; 215 | options.width = bounds.width + ( padding * 2 ); 216 | options.height = bounds.height + ( padding * 2 ); 217 | } 218 | 219 | // If width/height values are set, calculate scale from those values 220 | if( options.width !== undefined && options.height !== undefined ) { 221 | options.scale = Math.max( Math.min( window.innerWidth / options.width, window.innerHeight / options.height ), 1 ); 222 | } 223 | 224 | if( options.scale > 1 ) { 225 | options.x *= options.scale; 226 | options.y *= options.scale; 227 | 228 | magnify( options, options.scale ); 229 | 230 | if( options.pan !== false ) { 231 | 232 | // Wait with engaging panning as it may conflict with the 233 | // zoom transition 234 | panEngageTimeout = setTimeout( function() { 235 | panUpdateInterval = setInterval( pan, 1000 / 60 ); 236 | }, 800 ); 237 | 238 | } 239 | } 240 | } 241 | }, 242 | 243 | /** 244 | * Resets the document zoom state to its default. 245 | */ 246 | out: function() { 247 | clearTimeout( panEngageTimeout ); 248 | clearInterval( panUpdateInterval ); 249 | 250 | magnify( { x: 0, y: 0 }, 1 ); 251 | 252 | level = 1; 253 | }, 254 | 255 | // Alias 256 | magnify: function( options ) { this.to( options ) }, 257 | reset: function() { this.out() }, 258 | 259 | zoomLevel: function() { 260 | return level; 261 | } 262 | } 263 | 264 | })(); 265 | -------------------------------------------------------------------------------- /submission_tutorial.md: -------------------------------------------------------------------------------- 1 | # Submission tutorial 2 | 3 | This tutorial is designed to give you the knowledge on how to achieve high-quality submissions in the course PS Parallel Programming. 4 | The focus of this tutorial is on exercises dealing with parallelizing, optimizing and/or measuring the performance of an application, but many concepts can be transferred to theoretical exercises as well. 5 | 6 | The tutorial is split into three parts [Measurement](#measurement), [Reporting](#reporting) and [Submission](#submission) providing theoretical background where necessary in addition to practical guidelines and examples. 7 | 8 | Remember, this tutorial serves as resource to assist you in creating high-quality submissions. Should you have any questions or require clarification, don't hesitate to discuss them with your instructor. 9 | 10 | ## Table of contents 11 | 12 | - [Measurement](#measurement) 13 | - [Measurement: Introduction](#measurement-introduction) 14 | - [Measurement: Guidelines](#measurement-guidelines) 15 | - [Reporting](#reporting) 16 | - [Reporting: Introduction](#reporting-introduction) 17 | - [Reporting: Guidelines](#reporting-guidelines) 18 | - [Submission](#submission) 19 | - [Acknowledgements](#acknowledgements) 20 | 21 | ## Measurement 22 | 23 | ### Measurement: Introduction 24 | 25 | The first step into analyzing an application is to conduct measurements. 26 | In parallel programming we are mostly interested in metrics of performance like 27 | 28 | - Execution time 29 | - Hardware counters (L3 cache misses, branch prediction misses, etc.) 30 | - Latency 31 | - Scalability 32 | - ... 33 | 34 | In order to measure a metric properly it is important to roughly distinguish between 35 | 36 | 1. deterministic metrics - e.g. the result is constant no matter how often you measure 37 | 2. non-deterministic metrics - e.g. measuring more than once may lead to different results 38 | 39 | Depending on the measured metric the methodology has to be adjusted. 40 | For deterministic metrics it is sufficient to measure once, whereas for non-deterministic metrics you have to measure multiple times and use statistical methods for analysis. 41 | 42 | ### Measurement: Guidelines 43 | 44 | Most metrics relevant for parallel programming are non-deterministic metrics like execution time, hardware counters, etc.. 45 | Therefore, here are some common guidelines on how to measure non-deterministic metrics: 46 | 47 | - Repeat your measurement 48 | - Rationale: Due to the non-deterministic nature of the metric statistical methods have to be used therefore, multiple data points are required. 49 | - For this course it is sufficient to repeat measurements at least 3 times, preferably 5 or more times 50 | - Minimize external influences 51 | - Rationale: External influences can skew your results. 52 | - For this course this means: 53 | - Allocate the node exclusively - e.g. use `--exclusive` in `sbatch` 54 | - Do not run measurements on the login node since you do not have control over the load on the login node 55 | - Do not cause unnecessary load on the node - e.g. do not start unnecessary background processes 56 | 57 | For example a `SLURM` job script measuring the `sleep` application and adhering to the guidelines could look like this: 58 | 59 | ```sh 60 | #!/bin/bash 61 | 62 | #SBATCH --partition=lva 63 | #SBATCH --job-name benchmark_echo 64 | #SBATCH --output=output.log 65 | #SBATCH --ntasks=1 66 | #SBATCH --ntasks-per-node=1 67 | 68 | # Guideline: minimize external influences 69 | #SBATCH --exclusive 70 | 71 | # Guideline: repeat measurements 72 | for i in {1..10} 73 | do 74 | /usr/bin/time -f '%e' sleep 5 75 | done 76 | ``` 77 | 78 | ## Reporting 79 | 80 | ### Reporting: Introduction 81 | 82 | Once the desired metrics have been measured the next step is to process and analyze the data in order to draw conclusions from it. 83 | In general the way of reporting a metric is dependent on what you want to show with the metric. 84 | 85 | This section primarily focuses on reporting non-deterministic metrics, with execution time being a primary example. 86 | As mentioned in the [Measurement](#measurement) section a non-deterministic metric requires statistical methods for analysis. 87 | For this course it is sufficient if you reduce your multiple data points into 88 | 89 | 1. A representative value - e.g. average, median, etc. 90 | 2. A metric of variation - e.g. standard deviation, interquartile range, etc. 91 | 92 | ### Reporting: Guidelines 93 | 94 | Here are some guidelines for reporting results: 95 | 96 | - Describe your measurement methodology/platform 97 | - Rationale: The reader should be able to reproduce the results based on your report 98 | - If this guideline is relevant for the task it is sufficient to describe the following points 99 | - the measurement platform - e.g. LCC3, local PC, etc. 100 | - the compilation process - e.g. compilation flags like `-O3` 101 | - the measurement process - e.g. time measurement via `/usr/bin/time`, cache miss measurement via `perf`, etc. 102 | - Link to relevant material like the `Makefile`, the `SLURM` job script, etc. 103 | - Visualize the data 104 | - Rationale: A graphical representation is easier to understand in many cases 105 | - Discuss the results 106 | - Rationale: Enhance the results by providing an analysis 107 | - Report every relevant result in your submission 108 | - Rationale: Results not part of your submission are inconvenient for the reader 109 | - For this course this means that all results should be included in your report if possible - e.g. do not reference external resources for your results like the performance comparison spreadsheet 110 | - In case you have results that do not fit well into the report, but you still want to include them consider creating an Appendix and putting them there 111 | 112 | When plotting data make sure that 113 | 114 | - The axes are labelled 115 | - The axis label includes the unit of measurement or "[unit]" if the dimension is unitless 116 | - The graph is labelled 117 | - Either add a title to the graph or label it in the report 118 | - The measured data points are clearly marked in the graph 119 | - Rationale: In case your choice of visualization includes interpolation between data points it is important to know which points have been measured and which have been interpolated 120 | - The starting points of the axes are appropriate 121 | - Rationale: Inappropriate axis starting points might lead to faulty conclusions based on the graph 122 | - Example: Consider an execution time plot with the execution time on the Y-axis and the number of threads on the X-axis. The Y-axis should start at 0. 123 | - If multiple traces are present in the graph ensure 124 | - That they can be distinguished easily 125 | - That the traces are labelled either in a legend or in the report 126 | - Example: A line plot for the execution time of 3 programs should clearly mark which line corresponds to which program and assign names to the lines in the legend. 127 | 128 | The figure below shows an example of an execution time plot adhering to the guidelines: 129 | 130 | ![Execution time plot](resources/example_figure.png) 131 | 132 | Depending on the task you may be asked how stable the measurements are. 133 | In this case you can either include the metric of variation - e.g. standard deviation, interquartile range, etc. - into the plot for the representative values, or you can create a separate plot for the metric of variation. 134 | 135 | Example plot with standard deviation: 136 | 137 | ![Execution time plot + std](resources/example_figure_std.png) 138 | 139 | ## Submission 140 | 141 | The final part of this tutorial deals with submitting the results. 142 | When handing in your results submit 143 | 144 | - A report 145 | - The source code 146 | - The build script(s) - e.g. `Makefile`, `CMakeLists.txt`, etc. 147 | - The job script(s) for LCC3 148 | - Any other relevant script used during benchmarking or analysis 149 | - The unprocessed and processed data - Example: csv files for raw data and an excel file for the processed data 150 | - Any figures (if they are available separate from the report) 151 | - The team composition (if not already mentioned in the report) 152 | 153 | Depending on the task some points might not be applicable. 154 | 155 | Do not submit 156 | 157 | - Binaries 158 | - Unrelated files 159 | - Example: Configuration files from your IDE like ".vscode/settings.json", etc. 160 | 161 | ## Acknowledgements 162 | 163 | Special thanks to 164 | 165 | - The PS Parallel Programming instructors, for their contributions to the tutorial 166 | - ChatGPT, for enhancing the writing quality 167 | -------------------------------------------------------------------------------- /docs/dist/theme/solarized.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Solarized Light theme for reveal.js. 3 | * Author: Achim Staebler 4 | */ 5 | @import url(./fonts/league-gothic/league-gothic.css); 6 | @import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); 7 | /** 8 | * Solarized colors by Ethan Schoonover 9 | */ 10 | html * { 11 | color-profile: sRGB; 12 | rendering-intent: auto; 13 | } 14 | 15 | /********************************************* 16 | * GLOBAL STYLES 17 | *********************************************/ 18 | :root { 19 | --r-background-color: #fdf6e3; 20 | --r-main-font: Lato, sans-serif; 21 | --r-main-font-size: 40px; 22 | --r-main-color: #657b83; 23 | --r-block-margin: 20px; 24 | --r-heading-margin: 0 0 20px 0; 25 | --r-heading-font: League Gothic, Impact, sans-serif; 26 | --r-heading-color: #586e75; 27 | --r-heading-line-height: 1.2; 28 | --r-heading-letter-spacing: normal; 29 | --r-heading-text-transform: uppercase; 30 | --r-heading-text-shadow: none; 31 | --r-heading-font-weight: normal; 32 | --r-heading1-text-shadow: none; 33 | --r-heading1-size: 3.77em; 34 | --r-heading2-size: 2.11em; 35 | --r-heading3-size: 1.55em; 36 | --r-heading4-size: 1em; 37 | --r-code-font: monospace; 38 | --r-link-color: #268bd2; 39 | --r-link-color-dark: #1a6091; 40 | --r-link-color-hover: #78b9e6; 41 | --r-selection-background-color: #d33682; 42 | --r-selection-color: #fff; 43 | } 44 | 45 | .reveal-viewport { 46 | background: #fdf6e3; 47 | background-color: var(--r-background-color); 48 | } 49 | 50 | .reveal { 51 | font-family: var(--r-main-font); 52 | font-size: var(--r-main-font-size); 53 | font-weight: normal; 54 | color: var(--r-main-color); 55 | } 56 | 57 | .reveal ::selection { 58 | color: var(--r-selection-color); 59 | background: var(--r-selection-background-color); 60 | text-shadow: none; 61 | } 62 | 63 | .reveal ::-moz-selection { 64 | color: var(--r-selection-color); 65 | background: var(--r-selection-background-color); 66 | text-shadow: none; 67 | } 68 | 69 | .reveal .slides section, 70 | .reveal .slides section > section { 71 | line-height: 1.3; 72 | font-weight: inherit; 73 | } 74 | 75 | /********************************************* 76 | * HEADERS 77 | *********************************************/ 78 | .reveal h1, 79 | .reveal h2, 80 | .reveal h3, 81 | .reveal h4, 82 | .reveal h5, 83 | .reveal h6 { 84 | margin: var(--r-heading-margin); 85 | color: var(--r-heading-color); 86 | font-family: var(--r-heading-font); 87 | font-weight: var(--r-heading-font-weight); 88 | line-height: var(--r-heading-line-height); 89 | letter-spacing: var(--r-heading-letter-spacing); 90 | text-transform: var(--r-heading-text-transform); 91 | text-shadow: var(--r-heading-text-shadow); 92 | word-wrap: break-word; 93 | } 94 | 95 | .reveal h1 { 96 | font-size: var(--r-heading1-size); 97 | } 98 | 99 | .reveal h2 { 100 | font-size: var(--r-heading2-size); 101 | } 102 | 103 | .reveal h3 { 104 | font-size: var(--r-heading3-size); 105 | } 106 | 107 | .reveal h4 { 108 | font-size: var(--r-heading4-size); 109 | } 110 | 111 | .reveal h1 { 112 | text-shadow: var(--r-heading1-text-shadow); 113 | } 114 | 115 | /********************************************* 116 | * OTHER 117 | *********************************************/ 118 | .reveal p { 119 | margin: var(--r-block-margin) 0; 120 | line-height: 1.3; 121 | } 122 | 123 | /* Remove trailing margins after titles */ 124 | .reveal h1:last-child, 125 | .reveal h2:last-child, 126 | .reveal h3:last-child, 127 | .reveal h4:last-child, 128 | .reveal h5:last-child, 129 | .reveal h6:last-child { 130 | margin-bottom: 0; 131 | } 132 | 133 | /* Ensure certain elements are never larger than the slide itself */ 134 | .reveal img, 135 | .reveal video, 136 | .reveal iframe { 137 | max-width: 95%; 138 | max-height: 95%; 139 | } 140 | 141 | .reveal strong, 142 | .reveal b { 143 | font-weight: bold; 144 | } 145 | 146 | .reveal em { 147 | font-style: italic; 148 | } 149 | 150 | .reveal ol, 151 | .reveal dl, 152 | .reveal ul { 153 | display: inline-block; 154 | text-align: left; 155 | margin: 0 0 0 1em; 156 | } 157 | 158 | .reveal ol { 159 | list-style-type: decimal; 160 | } 161 | 162 | .reveal ul { 163 | list-style-type: disc; 164 | } 165 | 166 | .reveal ul ul { 167 | list-style-type: square; 168 | } 169 | 170 | .reveal ul ul ul { 171 | list-style-type: circle; 172 | } 173 | 174 | .reveal ul ul, 175 | .reveal ul ol, 176 | .reveal ol ol, 177 | .reveal ol ul { 178 | display: block; 179 | margin-left: 40px; 180 | } 181 | 182 | .reveal dt { 183 | font-weight: bold; 184 | } 185 | 186 | .reveal dd { 187 | margin-left: 40px; 188 | } 189 | 190 | .reveal blockquote { 191 | display: block; 192 | position: relative; 193 | width: 70%; 194 | margin: var(--r-block-margin) auto; 195 | padding: 5px; 196 | font-style: italic; 197 | background: rgba(255, 255, 255, 0.05); 198 | box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); 199 | } 200 | 201 | .reveal blockquote p:first-child, 202 | .reveal blockquote p:last-child { 203 | display: inline-block; 204 | } 205 | 206 | .reveal q { 207 | font-style: italic; 208 | } 209 | 210 | .reveal pre { 211 | display: block; 212 | position: relative; 213 | width: 90%; 214 | margin: var(--r-block-margin) auto; 215 | text-align: left; 216 | font-size: 0.55em; 217 | font-family: var(--r-code-font); 218 | line-height: 1.2em; 219 | word-wrap: break-word; 220 | box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); 221 | } 222 | 223 | .reveal code { 224 | font-family: var(--r-code-font); 225 | text-transform: none; 226 | tab-size: 2; 227 | } 228 | 229 | .reveal pre code { 230 | display: block; 231 | padding: 5px; 232 | overflow: auto; 233 | max-height: 400px; 234 | word-wrap: normal; 235 | } 236 | 237 | .reveal .code-wrapper { 238 | white-space: normal; 239 | } 240 | 241 | .reveal .code-wrapper code { 242 | white-space: pre; 243 | } 244 | 245 | .reveal table { 246 | margin: auto; 247 | border-collapse: collapse; 248 | border-spacing: 0; 249 | } 250 | 251 | .reveal table th { 252 | font-weight: bold; 253 | } 254 | 255 | .reveal table th, 256 | .reveal table td { 257 | text-align: left; 258 | padding: 0.2em 0.5em 0.2em 0.5em; 259 | border-bottom: 1px solid; 260 | } 261 | 262 | .reveal table th[align=center], 263 | .reveal table td[align=center] { 264 | text-align: center; 265 | } 266 | 267 | .reveal table th[align=right], 268 | .reveal table td[align=right] { 269 | text-align: right; 270 | } 271 | 272 | .reveal table tbody tr:last-child th, 273 | .reveal table tbody tr:last-child td { 274 | border-bottom: none; 275 | } 276 | 277 | .reveal sup { 278 | vertical-align: super; 279 | font-size: smaller; 280 | } 281 | 282 | .reveal sub { 283 | vertical-align: sub; 284 | font-size: smaller; 285 | } 286 | 287 | .reveal small { 288 | display: inline-block; 289 | font-size: 0.6em; 290 | line-height: 1.2em; 291 | vertical-align: top; 292 | } 293 | 294 | .reveal small * { 295 | vertical-align: top; 296 | } 297 | 298 | .reveal img { 299 | margin: var(--r-block-margin) 0; 300 | } 301 | 302 | /********************************************* 303 | * LINKS 304 | *********************************************/ 305 | .reveal a { 306 | color: var(--r-link-color); 307 | text-decoration: none; 308 | transition: color 0.15s ease; 309 | } 310 | 311 | .reveal a:hover { 312 | color: var(--r-link-color-hover); 313 | text-shadow: none; 314 | border: none; 315 | } 316 | 317 | .reveal .roll span:after { 318 | color: #fff; 319 | background: var(--r-link-color-dark); 320 | } 321 | 322 | /********************************************* 323 | * Frame helper 324 | *********************************************/ 325 | .reveal .r-frame { 326 | border: 4px solid var(--r-main-color); 327 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); 328 | } 329 | 330 | .reveal a .r-frame { 331 | transition: all 0.15s linear; 332 | } 333 | 334 | .reveal a:hover .r-frame { 335 | border-color: var(--r-link-color); 336 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); 337 | } 338 | 339 | /********************************************* 340 | * NAVIGATION CONTROLS 341 | *********************************************/ 342 | .reveal .controls { 343 | color: var(--r-link-color); 344 | } 345 | 346 | /********************************************* 347 | * PROGRESS BAR 348 | *********************************************/ 349 | .reveal .progress { 350 | background: rgba(0, 0, 0, 0.2); 351 | color: var(--r-link-color); 352 | } 353 | 354 | /********************************************* 355 | * PRINT BACKGROUND 356 | *********************************************/ 357 | @media print { 358 | .backgrounds { 359 | background-color: var(--r-background-color); 360 | } 361 | } -------------------------------------------------------------------------------- /docs/dist/theme/white.css: -------------------------------------------------------------------------------- 1 | /** 2 | * White theme for reveal.js. This is the opposite of the 'black' theme. 3 | * 4 | * By Hakim El Hattab, http://hakim.se 5 | */ 6 | @import url(./fonts/source-sans-pro/source-sans-pro.css); 7 | section.has-dark-background, section.has-dark-background h1, section.has-dark-background h2, section.has-dark-background h3, section.has-dark-background h4, section.has-dark-background h5, section.has-dark-background h6 { 8 | color: #fff; 9 | } 10 | 11 | /********************************************* 12 | * GLOBAL STYLES 13 | *********************************************/ 14 | :root { 15 | --r-background-color: #fff; 16 | --r-main-font: Source Sans Pro, Helvetica, sans-serif; 17 | --r-main-font-size: 42px; 18 | --r-main-color: #222; 19 | --r-block-margin: 20px; 20 | --r-heading-margin: 0 0 20px 0; 21 | --r-heading-font: Source Sans Pro, Helvetica, sans-serif; 22 | --r-heading-color: #222; 23 | --r-heading-line-height: 1.2; 24 | --r-heading-letter-spacing: normal; 25 | --r-heading-text-transform: uppercase; 26 | --r-heading-text-shadow: none; 27 | --r-heading-font-weight: 600; 28 | --r-heading1-text-shadow: none; 29 | --r-heading1-size: 2.5em; 30 | --r-heading2-size: 1.6em; 31 | --r-heading3-size: 1.3em; 32 | --r-heading4-size: 1em; 33 | --r-code-font: monospace; 34 | --r-link-color: #2a76dd; 35 | --r-link-color-dark: #1a53a1; 36 | --r-link-color-hover: #6ca0e8; 37 | --r-selection-background-color: #98bdef; 38 | --r-selection-color: #fff; 39 | } 40 | 41 | .reveal-viewport { 42 | background: #fff; 43 | background-color: var(--r-background-color); 44 | } 45 | 46 | .reveal { 47 | font-family: var(--r-main-font); 48 | font-size: var(--r-main-font-size); 49 | font-weight: normal; 50 | color: var(--r-main-color); 51 | } 52 | 53 | .reveal ::selection { 54 | color: var(--r-selection-color); 55 | background: var(--r-selection-background-color); 56 | text-shadow: none; 57 | } 58 | 59 | .reveal ::-moz-selection { 60 | color: var(--r-selection-color); 61 | background: var(--r-selection-background-color); 62 | text-shadow: none; 63 | } 64 | 65 | .reveal .slides section, 66 | .reveal .slides section > section { 67 | line-height: 1.3; 68 | font-weight: inherit; 69 | } 70 | 71 | /********************************************* 72 | * HEADERS 73 | *********************************************/ 74 | .reveal h1, 75 | .reveal h2, 76 | .reveal h3, 77 | .reveal h4, 78 | .reveal h5, 79 | .reveal h6 { 80 | margin: var(--r-heading-margin); 81 | color: var(--r-heading-color); 82 | font-family: var(--r-heading-font); 83 | font-weight: var(--r-heading-font-weight); 84 | line-height: var(--r-heading-line-height); 85 | letter-spacing: var(--r-heading-letter-spacing); 86 | text-transform: var(--r-heading-text-transform); 87 | text-shadow: var(--r-heading-text-shadow); 88 | word-wrap: break-word; 89 | } 90 | 91 | .reveal h1 { 92 | font-size: var(--r-heading1-size); 93 | } 94 | 95 | .reveal h2 { 96 | font-size: var(--r-heading2-size); 97 | } 98 | 99 | .reveal h3 { 100 | font-size: var(--r-heading3-size); 101 | } 102 | 103 | .reveal h4 { 104 | font-size: var(--r-heading4-size); 105 | } 106 | 107 | .reveal h1 { 108 | text-shadow: var(--r-heading1-text-shadow); 109 | } 110 | 111 | /********************************************* 112 | * OTHER 113 | *********************************************/ 114 | .reveal p { 115 | margin: var(--r-block-margin) 0; 116 | line-height: 1.3; 117 | } 118 | 119 | /* Remove trailing margins after titles */ 120 | .reveal h1:last-child, 121 | .reveal h2:last-child, 122 | .reveal h3:last-child, 123 | .reveal h4:last-child, 124 | .reveal h5:last-child, 125 | .reveal h6:last-child { 126 | margin-bottom: 0; 127 | } 128 | 129 | /* Ensure certain elements are never larger than the slide itself */ 130 | .reveal img, 131 | .reveal video, 132 | .reveal iframe { 133 | max-width: 95%; 134 | max-height: 95%; 135 | } 136 | 137 | .reveal strong, 138 | .reveal b { 139 | font-weight: bold; 140 | } 141 | 142 | .reveal em { 143 | font-style: italic; 144 | } 145 | 146 | .reveal ol, 147 | .reveal dl, 148 | .reveal ul { 149 | display: inline-block; 150 | text-align: left; 151 | margin: 0 0 0 1em; 152 | } 153 | 154 | .reveal ol { 155 | list-style-type: decimal; 156 | } 157 | 158 | .reveal ul { 159 | list-style-type: disc; 160 | } 161 | 162 | .reveal ul ul { 163 | list-style-type: square; 164 | } 165 | 166 | .reveal ul ul ul { 167 | list-style-type: circle; 168 | } 169 | 170 | .reveal ul ul, 171 | .reveal ul ol, 172 | .reveal ol ol, 173 | .reveal ol ul { 174 | display: block; 175 | margin-left: 40px; 176 | } 177 | 178 | .reveal dt { 179 | font-weight: bold; 180 | } 181 | 182 | .reveal dd { 183 | margin-left: 40px; 184 | } 185 | 186 | .reveal blockquote { 187 | display: block; 188 | position: relative; 189 | width: 70%; 190 | margin: var(--r-block-margin) auto; 191 | padding: 5px; 192 | font-style: italic; 193 | background: rgba(255, 255, 255, 0.05); 194 | box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); 195 | } 196 | 197 | .reveal blockquote p:first-child, 198 | .reveal blockquote p:last-child { 199 | display: inline-block; 200 | } 201 | 202 | .reveal q { 203 | font-style: italic; 204 | } 205 | 206 | .reveal pre { 207 | display: block; 208 | position: relative; 209 | width: 90%; 210 | margin: var(--r-block-margin) auto; 211 | text-align: left; 212 | font-size: 0.55em; 213 | font-family: var(--r-code-font); 214 | line-height: 1.2em; 215 | word-wrap: break-word; 216 | box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); 217 | } 218 | 219 | .reveal code { 220 | font-family: var(--r-code-font); 221 | text-transform: none; 222 | tab-size: 2; 223 | } 224 | 225 | .reveal pre code { 226 | display: block; 227 | padding: 5px; 228 | overflow: auto; 229 | max-height: 400px; 230 | word-wrap: normal; 231 | } 232 | 233 | .reveal .code-wrapper { 234 | white-space: normal; 235 | } 236 | 237 | .reveal .code-wrapper code { 238 | white-space: pre; 239 | } 240 | 241 | .reveal table { 242 | margin: auto; 243 | border-collapse: collapse; 244 | border-spacing: 0; 245 | } 246 | 247 | .reveal table th { 248 | font-weight: bold; 249 | } 250 | 251 | .reveal table th, 252 | .reveal table td { 253 | text-align: left; 254 | padding: 0.2em 0.5em 0.2em 0.5em; 255 | border-bottom: 1px solid; 256 | } 257 | 258 | .reveal table th[align=center], 259 | .reveal table td[align=center] { 260 | text-align: center; 261 | } 262 | 263 | .reveal table th[align=right], 264 | .reveal table td[align=right] { 265 | text-align: right; 266 | } 267 | 268 | .reveal table tbody tr:last-child th, 269 | .reveal table tbody tr:last-child td { 270 | border-bottom: none; 271 | } 272 | 273 | .reveal sup { 274 | vertical-align: super; 275 | font-size: smaller; 276 | } 277 | 278 | .reveal sub { 279 | vertical-align: sub; 280 | font-size: smaller; 281 | } 282 | 283 | .reveal small { 284 | display: inline-block; 285 | font-size: 0.6em; 286 | line-height: 1.2em; 287 | vertical-align: top; 288 | } 289 | 290 | .reveal small * { 291 | vertical-align: top; 292 | } 293 | 294 | .reveal img { 295 | margin: var(--r-block-margin) 0; 296 | } 297 | 298 | /********************************************* 299 | * LINKS 300 | *********************************************/ 301 | .reveal a { 302 | color: var(--r-link-color); 303 | text-decoration: none; 304 | transition: color 0.15s ease; 305 | } 306 | 307 | .reveal a:hover { 308 | color: var(--r-link-color-hover); 309 | text-shadow: none; 310 | border: none; 311 | } 312 | 313 | .reveal .roll span:after { 314 | color: #fff; 315 | background: var(--r-link-color-dark); 316 | } 317 | 318 | /********************************************* 319 | * Frame helper 320 | *********************************************/ 321 | .reveal .r-frame { 322 | border: 4px solid var(--r-main-color); 323 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); 324 | } 325 | 326 | .reveal a .r-frame { 327 | transition: all 0.15s linear; 328 | } 329 | 330 | .reveal a:hover .r-frame { 331 | border-color: var(--r-link-color); 332 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); 333 | } 334 | 335 | /********************************************* 336 | * NAVIGATION CONTROLS 337 | *********************************************/ 338 | .reveal .controls { 339 | color: var(--r-link-color); 340 | } 341 | 342 | /********************************************* 343 | * PROGRESS BAR 344 | *********************************************/ 345 | .reveal .progress { 346 | background: rgba(0, 0, 0, 0.2); 347 | color: var(--r-link-color); 348 | } 349 | 350 | /********************************************* 351 | * PRINT BACKGROUND 352 | *********************************************/ 353 | @media print { 354 | .backgrounds { 355 | background-color: var(--r-background-color); 356 | } 357 | } -------------------------------------------------------------------------------- /docs/dist/theme/black.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Black theme for reveal.js. This is the opposite of the 'white' theme. 3 | * 4 | * By Hakim El Hattab, http://hakim.se 5 | */ 6 | @import url(./fonts/source-sans-pro/source-sans-pro.css); 7 | section.has-light-background, section.has-light-background h1, section.has-light-background h2, section.has-light-background h3, section.has-light-background h4, section.has-light-background h5, section.has-light-background h6 { 8 | color: #222; 9 | } 10 | 11 | /********************************************* 12 | * GLOBAL STYLES 13 | *********************************************/ 14 | :root { 15 | --r-background-color: #191919; 16 | --r-main-font: Source Sans Pro, Helvetica, sans-serif; 17 | --r-main-font-size: 42px; 18 | --r-main-color: #fff; 19 | --r-block-margin: 20px; 20 | --r-heading-margin: 0 0 20px 0; 21 | --r-heading-font: Source Sans Pro, Helvetica, sans-serif; 22 | --r-heading-color: #fff; 23 | --r-heading-line-height: 1.2; 24 | --r-heading-letter-spacing: normal; 25 | --r-heading-text-transform: uppercase; 26 | --r-heading-text-shadow: none; 27 | --r-heading-font-weight: 600; 28 | --r-heading1-text-shadow: none; 29 | --r-heading1-size: 2.5em; 30 | --r-heading2-size: 1.6em; 31 | --r-heading3-size: 1.3em; 32 | --r-heading4-size: 1em; 33 | --r-code-font: monospace; 34 | --r-link-color: #42affa; 35 | --r-link-color-dark: #068de9; 36 | --r-link-color-hover: #8dcffc; 37 | --r-selection-background-color: rgba(66, 175, 250, 0.75); 38 | --r-selection-color: #fff; 39 | } 40 | 41 | .reveal-viewport { 42 | background: #191919; 43 | background-color: var(--r-background-color); 44 | } 45 | 46 | .reveal { 47 | font-family: var(--r-main-font); 48 | font-size: var(--r-main-font-size); 49 | font-weight: normal; 50 | color: var(--r-main-color); 51 | } 52 | 53 | .reveal ::selection { 54 | color: var(--r-selection-color); 55 | background: var(--r-selection-background-color); 56 | text-shadow: none; 57 | } 58 | 59 | .reveal ::-moz-selection { 60 | color: var(--r-selection-color); 61 | background: var(--r-selection-background-color); 62 | text-shadow: none; 63 | } 64 | 65 | .reveal .slides section, 66 | .reveal .slides section > section { 67 | line-height: 1.3; 68 | font-weight: inherit; 69 | } 70 | 71 | /********************************************* 72 | * HEADERS 73 | *********************************************/ 74 | .reveal h1, 75 | .reveal h2, 76 | .reveal h3, 77 | .reveal h4, 78 | .reveal h5, 79 | .reveal h6 { 80 | margin: var(--r-heading-margin); 81 | color: var(--r-heading-color); 82 | font-family: var(--r-heading-font); 83 | font-weight: var(--r-heading-font-weight); 84 | line-height: var(--r-heading-line-height); 85 | letter-spacing: var(--r-heading-letter-spacing); 86 | text-transform: var(--r-heading-text-transform); 87 | text-shadow: var(--r-heading-text-shadow); 88 | word-wrap: break-word; 89 | } 90 | 91 | .reveal h1 { 92 | font-size: var(--r-heading1-size); 93 | } 94 | 95 | .reveal h2 { 96 | font-size: var(--r-heading2-size); 97 | } 98 | 99 | .reveal h3 { 100 | font-size: var(--r-heading3-size); 101 | } 102 | 103 | .reveal h4 { 104 | font-size: var(--r-heading4-size); 105 | } 106 | 107 | .reveal h1 { 108 | text-shadow: var(--r-heading1-text-shadow); 109 | } 110 | 111 | /********************************************* 112 | * OTHER 113 | *********************************************/ 114 | .reveal p { 115 | margin: var(--r-block-margin) 0; 116 | line-height: 1.3; 117 | } 118 | 119 | /* Remove trailing margins after titles */ 120 | .reveal h1:last-child, 121 | .reveal h2:last-child, 122 | .reveal h3:last-child, 123 | .reveal h4:last-child, 124 | .reveal h5:last-child, 125 | .reveal h6:last-child { 126 | margin-bottom: 0; 127 | } 128 | 129 | /* Ensure certain elements are never larger than the slide itself */ 130 | .reveal img, 131 | .reveal video, 132 | .reveal iframe { 133 | max-width: 95%; 134 | max-height: 95%; 135 | } 136 | 137 | .reveal strong, 138 | .reveal b { 139 | font-weight: bold; 140 | } 141 | 142 | .reveal em { 143 | font-style: italic; 144 | } 145 | 146 | .reveal ol, 147 | .reveal dl, 148 | .reveal ul { 149 | display: inline-block; 150 | text-align: left; 151 | margin: 0 0 0 1em; 152 | } 153 | 154 | .reveal ol { 155 | list-style-type: decimal; 156 | } 157 | 158 | .reveal ul { 159 | list-style-type: disc; 160 | } 161 | 162 | .reveal ul ul { 163 | list-style-type: square; 164 | } 165 | 166 | .reveal ul ul ul { 167 | list-style-type: circle; 168 | } 169 | 170 | .reveal ul ul, 171 | .reveal ul ol, 172 | .reveal ol ol, 173 | .reveal ol ul { 174 | display: block; 175 | margin-left: 40px; 176 | } 177 | 178 | .reveal dt { 179 | font-weight: bold; 180 | } 181 | 182 | .reveal dd { 183 | margin-left: 40px; 184 | } 185 | 186 | .reveal blockquote { 187 | display: block; 188 | position: relative; 189 | width: 70%; 190 | margin: var(--r-block-margin) auto; 191 | padding: 5px; 192 | font-style: italic; 193 | background: rgba(255, 255, 255, 0.05); 194 | box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); 195 | } 196 | 197 | .reveal blockquote p:first-child, 198 | .reveal blockquote p:last-child { 199 | display: inline-block; 200 | } 201 | 202 | .reveal q { 203 | font-style: italic; 204 | } 205 | 206 | .reveal pre { 207 | display: block; 208 | position: relative; 209 | width: 90%; 210 | margin: var(--r-block-margin) auto; 211 | text-align: left; 212 | font-size: 0.55em; 213 | font-family: var(--r-code-font); 214 | line-height: 1.2em; 215 | word-wrap: break-word; 216 | box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); 217 | } 218 | 219 | .reveal code { 220 | font-family: var(--r-code-font); 221 | text-transform: none; 222 | tab-size: 2; 223 | } 224 | 225 | .reveal pre code { 226 | display: block; 227 | padding: 5px; 228 | overflow: auto; 229 | max-height: 400px; 230 | word-wrap: normal; 231 | } 232 | 233 | .reveal .code-wrapper { 234 | white-space: normal; 235 | } 236 | 237 | .reveal .code-wrapper code { 238 | white-space: pre; 239 | } 240 | 241 | .reveal table { 242 | margin: auto; 243 | border-collapse: collapse; 244 | border-spacing: 0; 245 | } 246 | 247 | .reveal table th { 248 | font-weight: bold; 249 | } 250 | 251 | .reveal table th, 252 | .reveal table td { 253 | text-align: left; 254 | padding: 0.2em 0.5em 0.2em 0.5em; 255 | border-bottom: 1px solid; 256 | } 257 | 258 | .reveal table th[align=center], 259 | .reveal table td[align=center] { 260 | text-align: center; 261 | } 262 | 263 | .reveal table th[align=right], 264 | .reveal table td[align=right] { 265 | text-align: right; 266 | } 267 | 268 | .reveal table tbody tr:last-child th, 269 | .reveal table tbody tr:last-child td { 270 | border-bottom: none; 271 | } 272 | 273 | .reveal sup { 274 | vertical-align: super; 275 | font-size: smaller; 276 | } 277 | 278 | .reveal sub { 279 | vertical-align: sub; 280 | font-size: smaller; 281 | } 282 | 283 | .reveal small { 284 | display: inline-block; 285 | font-size: 0.6em; 286 | line-height: 1.2em; 287 | vertical-align: top; 288 | } 289 | 290 | .reveal small * { 291 | vertical-align: top; 292 | } 293 | 294 | .reveal img { 295 | margin: var(--r-block-margin) 0; 296 | } 297 | 298 | /********************************************* 299 | * LINKS 300 | *********************************************/ 301 | .reveal a { 302 | color: var(--r-link-color); 303 | text-decoration: none; 304 | transition: color 0.15s ease; 305 | } 306 | 307 | .reveal a:hover { 308 | color: var(--r-link-color-hover); 309 | text-shadow: none; 310 | border: none; 311 | } 312 | 313 | .reveal .roll span:after { 314 | color: #fff; 315 | background: var(--r-link-color-dark); 316 | } 317 | 318 | /********************************************* 319 | * Frame helper 320 | *********************************************/ 321 | .reveal .r-frame { 322 | border: 4px solid var(--r-main-color); 323 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); 324 | } 325 | 326 | .reveal a .r-frame { 327 | transition: all 0.15s linear; 328 | } 329 | 330 | .reveal a:hover .r-frame { 331 | border-color: var(--r-link-color); 332 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); 333 | } 334 | 335 | /********************************************* 336 | * NAVIGATION CONTROLS 337 | *********************************************/ 338 | .reveal .controls { 339 | color: var(--r-link-color); 340 | } 341 | 342 | /********************************************* 343 | * PROGRESS BAR 344 | *********************************************/ 345 | .reveal .progress { 346 | background: rgba(0, 0, 0, 0.2); 347 | color: var(--r-link-color); 348 | } 349 | 350 | /********************************************* 351 | * PRINT BACKGROUND 352 | *********************************************/ 353 | @media print { 354 | .backgrounds { 355 | background-color: var(--r-background-color); 356 | } 357 | } -------------------------------------------------------------------------------- /docs/dist/theme/night.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Black theme for reveal.js. 3 | * 4 | * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se 5 | */ 6 | @import url(https://fonts.googleapis.com/css?family=Montserrat:700); 7 | @import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic,700italic); 8 | section.has-light-background, section.has-light-background h1, section.has-light-background h2, section.has-light-background h3, section.has-light-background h4, section.has-light-background h5, section.has-light-background h6 { 9 | color: #222; 10 | } 11 | 12 | /********************************************* 13 | * GLOBAL STYLES 14 | *********************************************/ 15 | :root { 16 | --r-background-color: #111; 17 | --r-main-font: Open Sans, sans-serif; 18 | --r-main-font-size: 40px; 19 | --r-main-color: #eee; 20 | --r-block-margin: 20px; 21 | --r-heading-margin: 0 0 20px 0; 22 | --r-heading-font: Montserrat, Impact, sans-serif; 23 | --r-heading-color: #eee; 24 | --r-heading-line-height: 1.2; 25 | --r-heading-letter-spacing: -0.03em; 26 | --r-heading-text-transform: none; 27 | --r-heading-text-shadow: none; 28 | --r-heading-font-weight: normal; 29 | --r-heading1-text-shadow: none; 30 | --r-heading1-size: 3.77em; 31 | --r-heading2-size: 2.11em; 32 | --r-heading3-size: 1.55em; 33 | --r-heading4-size: 1em; 34 | --r-code-font: monospace; 35 | --r-link-color: #e7ad52; 36 | --r-link-color-dark: #d08a1d; 37 | --r-link-color-hover: #f3d7ac; 38 | --r-selection-background-color: #e7ad52; 39 | --r-selection-color: #fff; 40 | } 41 | 42 | .reveal-viewport { 43 | background: #111; 44 | background-color: var(--r-background-color); 45 | } 46 | 47 | .reveal { 48 | font-family: var(--r-main-font); 49 | font-size: var(--r-main-font-size); 50 | font-weight: normal; 51 | color: var(--r-main-color); 52 | } 53 | 54 | .reveal ::selection { 55 | color: var(--r-selection-color); 56 | background: var(--r-selection-background-color); 57 | text-shadow: none; 58 | } 59 | 60 | .reveal ::-moz-selection { 61 | color: var(--r-selection-color); 62 | background: var(--r-selection-background-color); 63 | text-shadow: none; 64 | } 65 | 66 | .reveal .slides section, 67 | .reveal .slides section > section { 68 | line-height: 1.3; 69 | font-weight: inherit; 70 | } 71 | 72 | /********************************************* 73 | * HEADERS 74 | *********************************************/ 75 | .reveal h1, 76 | .reveal h2, 77 | .reveal h3, 78 | .reveal h4, 79 | .reveal h5, 80 | .reveal h6 { 81 | margin: var(--r-heading-margin); 82 | color: var(--r-heading-color); 83 | font-family: var(--r-heading-font); 84 | font-weight: var(--r-heading-font-weight); 85 | line-height: var(--r-heading-line-height); 86 | letter-spacing: var(--r-heading-letter-spacing); 87 | text-transform: var(--r-heading-text-transform); 88 | text-shadow: var(--r-heading-text-shadow); 89 | word-wrap: break-word; 90 | } 91 | 92 | .reveal h1 { 93 | font-size: var(--r-heading1-size); 94 | } 95 | 96 | .reveal h2 { 97 | font-size: var(--r-heading2-size); 98 | } 99 | 100 | .reveal h3 { 101 | font-size: var(--r-heading3-size); 102 | } 103 | 104 | .reveal h4 { 105 | font-size: var(--r-heading4-size); 106 | } 107 | 108 | .reveal h1 { 109 | text-shadow: var(--r-heading1-text-shadow); 110 | } 111 | 112 | /********************************************* 113 | * OTHER 114 | *********************************************/ 115 | .reveal p { 116 | margin: var(--r-block-margin) 0; 117 | line-height: 1.3; 118 | } 119 | 120 | /* Remove trailing margins after titles */ 121 | .reveal h1:last-child, 122 | .reveal h2:last-child, 123 | .reveal h3:last-child, 124 | .reveal h4:last-child, 125 | .reveal h5:last-child, 126 | .reveal h6:last-child { 127 | margin-bottom: 0; 128 | } 129 | 130 | /* Ensure certain elements are never larger than the slide itself */ 131 | .reveal img, 132 | .reveal video, 133 | .reveal iframe { 134 | max-width: 95%; 135 | max-height: 95%; 136 | } 137 | 138 | .reveal strong, 139 | .reveal b { 140 | font-weight: bold; 141 | } 142 | 143 | .reveal em { 144 | font-style: italic; 145 | } 146 | 147 | .reveal ol, 148 | .reveal dl, 149 | .reveal ul { 150 | display: inline-block; 151 | text-align: left; 152 | margin: 0 0 0 1em; 153 | } 154 | 155 | .reveal ol { 156 | list-style-type: decimal; 157 | } 158 | 159 | .reveal ul { 160 | list-style-type: disc; 161 | } 162 | 163 | .reveal ul ul { 164 | list-style-type: square; 165 | } 166 | 167 | .reveal ul ul ul { 168 | list-style-type: circle; 169 | } 170 | 171 | .reveal ul ul, 172 | .reveal ul ol, 173 | .reveal ol ol, 174 | .reveal ol ul { 175 | display: block; 176 | margin-left: 40px; 177 | } 178 | 179 | .reveal dt { 180 | font-weight: bold; 181 | } 182 | 183 | .reveal dd { 184 | margin-left: 40px; 185 | } 186 | 187 | .reveal blockquote { 188 | display: block; 189 | position: relative; 190 | width: 70%; 191 | margin: var(--r-block-margin) auto; 192 | padding: 5px; 193 | font-style: italic; 194 | background: rgba(255, 255, 255, 0.05); 195 | box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); 196 | } 197 | 198 | .reveal blockquote p:first-child, 199 | .reveal blockquote p:last-child { 200 | display: inline-block; 201 | } 202 | 203 | .reveal q { 204 | font-style: italic; 205 | } 206 | 207 | .reveal pre { 208 | display: block; 209 | position: relative; 210 | width: 90%; 211 | margin: var(--r-block-margin) auto; 212 | text-align: left; 213 | font-size: 0.55em; 214 | font-family: var(--r-code-font); 215 | line-height: 1.2em; 216 | word-wrap: break-word; 217 | box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); 218 | } 219 | 220 | .reveal code { 221 | font-family: var(--r-code-font); 222 | text-transform: none; 223 | tab-size: 2; 224 | } 225 | 226 | .reveal pre code { 227 | display: block; 228 | padding: 5px; 229 | overflow: auto; 230 | max-height: 400px; 231 | word-wrap: normal; 232 | } 233 | 234 | .reveal .code-wrapper { 235 | white-space: normal; 236 | } 237 | 238 | .reveal .code-wrapper code { 239 | white-space: pre; 240 | } 241 | 242 | .reveal table { 243 | margin: auto; 244 | border-collapse: collapse; 245 | border-spacing: 0; 246 | } 247 | 248 | .reveal table th { 249 | font-weight: bold; 250 | } 251 | 252 | .reveal table th, 253 | .reveal table td { 254 | text-align: left; 255 | padding: 0.2em 0.5em 0.2em 0.5em; 256 | border-bottom: 1px solid; 257 | } 258 | 259 | .reveal table th[align=center], 260 | .reveal table td[align=center] { 261 | text-align: center; 262 | } 263 | 264 | .reveal table th[align=right], 265 | .reveal table td[align=right] { 266 | text-align: right; 267 | } 268 | 269 | .reveal table tbody tr:last-child th, 270 | .reveal table tbody tr:last-child td { 271 | border-bottom: none; 272 | } 273 | 274 | .reveal sup { 275 | vertical-align: super; 276 | font-size: smaller; 277 | } 278 | 279 | .reveal sub { 280 | vertical-align: sub; 281 | font-size: smaller; 282 | } 283 | 284 | .reveal small { 285 | display: inline-block; 286 | font-size: 0.6em; 287 | line-height: 1.2em; 288 | vertical-align: top; 289 | } 290 | 291 | .reveal small * { 292 | vertical-align: top; 293 | } 294 | 295 | .reveal img { 296 | margin: var(--r-block-margin) 0; 297 | } 298 | 299 | /********************************************* 300 | * LINKS 301 | *********************************************/ 302 | .reveal a { 303 | color: var(--r-link-color); 304 | text-decoration: none; 305 | transition: color 0.15s ease; 306 | } 307 | 308 | .reveal a:hover { 309 | color: var(--r-link-color-hover); 310 | text-shadow: none; 311 | border: none; 312 | } 313 | 314 | .reveal .roll span:after { 315 | color: #fff; 316 | background: var(--r-link-color-dark); 317 | } 318 | 319 | /********************************************* 320 | * Frame helper 321 | *********************************************/ 322 | .reveal .r-frame { 323 | border: 4px solid var(--r-main-color); 324 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); 325 | } 326 | 327 | .reveal a .r-frame { 328 | transition: all 0.15s linear; 329 | } 330 | 331 | .reveal a:hover .r-frame { 332 | border-color: var(--r-link-color); 333 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); 334 | } 335 | 336 | /********************************************* 337 | * NAVIGATION CONTROLS 338 | *********************************************/ 339 | .reveal .controls { 340 | color: var(--r-link-color); 341 | } 342 | 343 | /********************************************* 344 | * PROGRESS BAR 345 | *********************************************/ 346 | .reveal .progress { 347 | background: rgba(0, 0, 0, 0.2); 348 | color: var(--r-link-color); 349 | } 350 | 351 | /********************************************* 352 | * PRINT BACKGROUND 353 | *********************************************/ 354 | @media print { 355 | .backgrounds { 356 | background-color: var(--r-background-color); 357 | } 358 | } -------------------------------------------------------------------------------- /docs/dist/theme/serif.css: -------------------------------------------------------------------------------- 1 | /** 2 | * A simple theme for reveal.js presentations, similar 3 | * to the default theme. The accent color is brown. 4 | * 5 | * This theme is Copyright (C) 2012-2013 Owen Versteeg, http://owenversteeg.com - it is MIT licensed. 6 | */ 7 | .reveal a { 8 | line-height: 1.3em; 9 | } 10 | 11 | section.has-dark-background, section.has-dark-background h1, section.has-dark-background h2, section.has-dark-background h3, section.has-dark-background h4, section.has-dark-background h5, section.has-dark-background h6 { 12 | color: #fff; 13 | } 14 | 15 | /********************************************* 16 | * GLOBAL STYLES 17 | *********************************************/ 18 | :root { 19 | --r-background-color: #F0F1EB; 20 | --r-main-font: Palatino Linotype, Book Antiqua, Palatino, FreeSerif, serif; 21 | --r-main-font-size: 40px; 22 | --r-main-color: #000; 23 | --r-block-margin: 20px; 24 | --r-heading-margin: 0 0 20px 0; 25 | --r-heading-font: Palatino Linotype, Book Antiqua, Palatino, FreeSerif, serif; 26 | --r-heading-color: #383D3D; 27 | --r-heading-line-height: 1.2; 28 | --r-heading-letter-spacing: normal; 29 | --r-heading-text-transform: none; 30 | --r-heading-text-shadow: none; 31 | --r-heading-font-weight: normal; 32 | --r-heading1-text-shadow: none; 33 | --r-heading1-size: 3.77em; 34 | --r-heading2-size: 2.11em; 35 | --r-heading3-size: 1.55em; 36 | --r-heading4-size: 1em; 37 | --r-code-font: monospace; 38 | --r-link-color: #51483D; 39 | --r-link-color-dark: #25211c; 40 | --r-link-color-hover: #8b7c69; 41 | --r-selection-background-color: #26351C; 42 | --r-selection-color: #fff; 43 | } 44 | 45 | .reveal-viewport { 46 | background: #F0F1EB; 47 | background-color: var(--r-background-color); 48 | } 49 | 50 | .reveal { 51 | font-family: var(--r-main-font); 52 | font-size: var(--r-main-font-size); 53 | font-weight: normal; 54 | color: var(--r-main-color); 55 | } 56 | 57 | .reveal ::selection { 58 | color: var(--r-selection-color); 59 | background: var(--r-selection-background-color); 60 | text-shadow: none; 61 | } 62 | 63 | .reveal ::-moz-selection { 64 | color: var(--r-selection-color); 65 | background: var(--r-selection-background-color); 66 | text-shadow: none; 67 | } 68 | 69 | .reveal .slides section, 70 | .reveal .slides section > section { 71 | line-height: 1.3; 72 | font-weight: inherit; 73 | } 74 | 75 | /********************************************* 76 | * HEADERS 77 | *********************************************/ 78 | .reveal h1, 79 | .reveal h2, 80 | .reveal h3, 81 | .reveal h4, 82 | .reveal h5, 83 | .reveal h6 { 84 | margin: var(--r-heading-margin); 85 | color: var(--r-heading-color); 86 | font-family: var(--r-heading-font); 87 | font-weight: var(--r-heading-font-weight); 88 | line-height: var(--r-heading-line-height); 89 | letter-spacing: var(--r-heading-letter-spacing); 90 | text-transform: var(--r-heading-text-transform); 91 | text-shadow: var(--r-heading-text-shadow); 92 | word-wrap: break-word; 93 | } 94 | 95 | .reveal h1 { 96 | font-size: var(--r-heading1-size); 97 | } 98 | 99 | .reveal h2 { 100 | font-size: var(--r-heading2-size); 101 | } 102 | 103 | .reveal h3 { 104 | font-size: var(--r-heading3-size); 105 | } 106 | 107 | .reveal h4 { 108 | font-size: var(--r-heading4-size); 109 | } 110 | 111 | .reveal h1 { 112 | text-shadow: var(--r-heading1-text-shadow); 113 | } 114 | 115 | /********************************************* 116 | * OTHER 117 | *********************************************/ 118 | .reveal p { 119 | margin: var(--r-block-margin) 0; 120 | line-height: 1.3; 121 | } 122 | 123 | /* Remove trailing margins after titles */ 124 | .reveal h1:last-child, 125 | .reveal h2:last-child, 126 | .reveal h3:last-child, 127 | .reveal h4:last-child, 128 | .reveal h5:last-child, 129 | .reveal h6:last-child { 130 | margin-bottom: 0; 131 | } 132 | 133 | /* Ensure certain elements are never larger than the slide itself */ 134 | .reveal img, 135 | .reveal video, 136 | .reveal iframe { 137 | max-width: 95%; 138 | max-height: 95%; 139 | } 140 | 141 | .reveal strong, 142 | .reveal b { 143 | font-weight: bold; 144 | } 145 | 146 | .reveal em { 147 | font-style: italic; 148 | } 149 | 150 | .reveal ol, 151 | .reveal dl, 152 | .reveal ul { 153 | display: inline-block; 154 | text-align: left; 155 | margin: 0 0 0 1em; 156 | } 157 | 158 | .reveal ol { 159 | list-style-type: decimal; 160 | } 161 | 162 | .reveal ul { 163 | list-style-type: disc; 164 | } 165 | 166 | .reveal ul ul { 167 | list-style-type: square; 168 | } 169 | 170 | .reveal ul ul ul { 171 | list-style-type: circle; 172 | } 173 | 174 | .reveal ul ul, 175 | .reveal ul ol, 176 | .reveal ol ol, 177 | .reveal ol ul { 178 | display: block; 179 | margin-left: 40px; 180 | } 181 | 182 | .reveal dt { 183 | font-weight: bold; 184 | } 185 | 186 | .reveal dd { 187 | margin-left: 40px; 188 | } 189 | 190 | .reveal blockquote { 191 | display: block; 192 | position: relative; 193 | width: 70%; 194 | margin: var(--r-block-margin) auto; 195 | padding: 5px; 196 | font-style: italic; 197 | background: rgba(255, 255, 255, 0.05); 198 | box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); 199 | } 200 | 201 | .reveal blockquote p:first-child, 202 | .reveal blockquote p:last-child { 203 | display: inline-block; 204 | } 205 | 206 | .reveal q { 207 | font-style: italic; 208 | } 209 | 210 | .reveal pre { 211 | display: block; 212 | position: relative; 213 | width: 90%; 214 | margin: var(--r-block-margin) auto; 215 | text-align: left; 216 | font-size: 0.55em; 217 | font-family: var(--r-code-font); 218 | line-height: 1.2em; 219 | word-wrap: break-word; 220 | box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); 221 | } 222 | 223 | .reveal code { 224 | font-family: var(--r-code-font); 225 | text-transform: none; 226 | tab-size: 2; 227 | } 228 | 229 | .reveal pre code { 230 | display: block; 231 | padding: 5px; 232 | overflow: auto; 233 | max-height: 400px; 234 | word-wrap: normal; 235 | } 236 | 237 | .reveal .code-wrapper { 238 | white-space: normal; 239 | } 240 | 241 | .reveal .code-wrapper code { 242 | white-space: pre; 243 | } 244 | 245 | .reveal table { 246 | margin: auto; 247 | border-collapse: collapse; 248 | border-spacing: 0; 249 | } 250 | 251 | .reveal table th { 252 | font-weight: bold; 253 | } 254 | 255 | .reveal table th, 256 | .reveal table td { 257 | text-align: left; 258 | padding: 0.2em 0.5em 0.2em 0.5em; 259 | border-bottom: 1px solid; 260 | } 261 | 262 | .reveal table th[align=center], 263 | .reveal table td[align=center] { 264 | text-align: center; 265 | } 266 | 267 | .reveal table th[align=right], 268 | .reveal table td[align=right] { 269 | text-align: right; 270 | } 271 | 272 | .reveal table tbody tr:last-child th, 273 | .reveal table tbody tr:last-child td { 274 | border-bottom: none; 275 | } 276 | 277 | .reveal sup { 278 | vertical-align: super; 279 | font-size: smaller; 280 | } 281 | 282 | .reveal sub { 283 | vertical-align: sub; 284 | font-size: smaller; 285 | } 286 | 287 | .reveal small { 288 | display: inline-block; 289 | font-size: 0.6em; 290 | line-height: 1.2em; 291 | vertical-align: top; 292 | } 293 | 294 | .reveal small * { 295 | vertical-align: top; 296 | } 297 | 298 | .reveal img { 299 | margin: var(--r-block-margin) 0; 300 | } 301 | 302 | /********************************************* 303 | * LINKS 304 | *********************************************/ 305 | .reveal a { 306 | color: var(--r-link-color); 307 | text-decoration: none; 308 | transition: color 0.15s ease; 309 | } 310 | 311 | .reveal a:hover { 312 | color: var(--r-link-color-hover); 313 | text-shadow: none; 314 | border: none; 315 | } 316 | 317 | .reveal .roll span:after { 318 | color: #fff; 319 | background: var(--r-link-color-dark); 320 | } 321 | 322 | /********************************************* 323 | * Frame helper 324 | *********************************************/ 325 | .reveal .r-frame { 326 | border: 4px solid var(--r-main-color); 327 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); 328 | } 329 | 330 | .reveal a .r-frame { 331 | transition: all 0.15s linear; 332 | } 333 | 334 | .reveal a:hover .r-frame { 335 | border-color: var(--r-link-color); 336 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); 337 | } 338 | 339 | /********************************************* 340 | * NAVIGATION CONTROLS 341 | *********************************************/ 342 | .reveal .controls { 343 | color: var(--r-link-color); 344 | } 345 | 346 | /********************************************* 347 | * PROGRESS BAR 348 | *********************************************/ 349 | .reveal .progress { 350 | background: rgba(0, 0, 0, 0.2); 351 | color: var(--r-link-color); 352 | } 353 | 354 | /********************************************* 355 | * PRINT BACKGROUND 356 | *********************************************/ 357 | @media print { 358 | .backgrounds { 359 | background-color: var(--r-background-color); 360 | } 361 | } --------------------------------------------------------------------------------