commit 1ba60ab73d510a996b93a2acc1b91a69c7ef01eb Author: Mylloon Date: Sat Mar 9 18:22:32 2024 +0100 add sched.h and quicksort.h, alongs with template for report, makefiles and basic readme diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fe5cc77 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.o +*.out + +*.pdf + +*.tar diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7dd4e21 --- /dev/null +++ b/Makefile @@ -0,0 +1,54 @@ +CC = gcc +RM = rm -r +TAR = tar -cf +CP = cp -r +MKDIR = mkdir -p + +SRC_DIR = src +INC_DIR = includes +SOURCES = $(wildcard $(SRC_DIR)/*.c) +OBJETS = $(patsubst %.c,%.o,$(notdir $(SOURCES))) + +CFLAGS = -std=gnu11 -pedantic +LDFLAGS = + +EXE = projet +EXE_EXT = out + +ARCHIVE = kennel +PDF_DIR = report + +%.o: src/%.c + $(CC) -c $< -o $@ $(CFLAGS) + +compilation: $(OBJETS) + $(CC) -o $(EXE).$(EXE_EXT) $(OBJETS) $(LDFLAGS) + +main: CFLAGS += -O3 +main: compilation + +dev: CFLAGS += -Wall -Wextra -Wshadow -Wcast-align -Wstrict-prototypes +dev: CFLAGS += -fanalyzer -fsanitize=undefined -g -Og +dev: LDFLAGS += -fsanitize=undefined +dev: compilation + +all: + main + +pdf-make: + cd report && \ + $(MAKE) + +pdf-clean: + cd report && \ + $(MAKE) clean + +clean: pdf-clean + -$(RM) $(OBJETS) "$(EXE).$(EXE_EXT)" "$(ARCHIVE).tar" + +archive: pdf-make + $(MKDIR) "$(ARCHIVE)" + $(CP) "$(SRC_DIR)" "$(INC_DIR)" Makefile README \ + "$(wildcard $(PDF_DIR)/*.pdf)" "$(ARCHIVE)" + $(TAR) "$(ARCHIVE).tar" "$(ARCHIVE)" + $(RM) "$(ARCHIVE)" diff --git a/README b/README new file mode 100644 index 0000000..3a4922f --- /dev/null +++ b/README @@ -0,0 +1,19 @@ +Projet de programmation système avancée +======================================= + +Compilation +----------- + + make + +Ce qui créer l'exécutable `projet.out`. + +Lancement +--------- + + ./projet.out + +Info +---- + +Anri Kennel 22302653 diff --git a/includes/quicksort.h b/includes/quicksort.h new file mode 100644 index 0000000..4fe17bc --- /dev/null +++ b/includes/quicksort.h @@ -0,0 +1,11 @@ +#pragma once + +#include "sched.h" + +#include +#include +#include +#include +#include + +int benchmark(int argc, char **argv); diff --git a/includes/sched.h b/includes/sched.h new file mode 100644 index 0000000..70056ba --- /dev/null +++ b/includes/sched.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +struct scheduler; + +typedef void (*taskfunc)(void *, struct scheduler *); + +static inline int sched_default_threads() { + return sysconf(_SC_NPROCESSORS_ONLN); +} + +/* Lance l'ordonnanceur + * - nthreads : nombre de threads créer par l'ordonnanceur + * Si 0, le nombre de threads sera égal au nombre de coeurs de votre machine + * + * - qlen : nombre minimum de tâches simultanées que l’ordonnanceur devra + * supporter + * Retourne une erreur si l'utilisateur dépasse qlen + * + * - f, closure : tâche initiale + * + * Renvoie 1 quand elle a terminé, -1 en cas d'échec d'initialisation + */ +int sched_init(int nthreads, int qlen, taskfunc f, void *closure); + +/* Enfile une nouvelle tâche (f, closure) à l'ordonanceur (s) */ +int sched_spawn(taskfunc f, void *closure, struct scheduler *s); diff --git a/report/.gitignore b/report/.gitignore new file mode 100644 index 0000000..b162c46 --- /dev/null +++ b/report/.gitignore @@ -0,0 +1,5 @@ +* + +!.gitignore +!Makefile +!*.tex diff --git a/report/Makefile b/report/Makefile new file mode 100644 index 0000000..bbed92c --- /dev/null +++ b/report/Makefile @@ -0,0 +1,16 @@ +NAME = document + +TEX = $(NAME).tex +SRC = $(TEX) +PDF = $(TEX:.tex=.pdf) + +TEXMK = latexmk -shell-escape -lualatex + +all: $(PDF) + +$(PDF): %.pdf: %.tex + $(TEXMK) $< + +EXTS = aux fdb_latexmk fls log nav out snm synctex.gz toc +clean: + rm -rf $(PDF) _minted-$(NAME)/ $(foreach ext,$(EXTS),$(NAME).$(ext)) diff --git a/report/document.tex b/report/document.tex new file mode 100644 index 0000000..6732ef7 --- /dev/null +++ b/report/document.tex @@ -0,0 +1,37 @@ +\documentclass{article} + +\usepackage[T1]{fontenc} % encoding +\renewcommand{\familydefault}{\sfdefault} % sans-serif font + +\usepackage[french]{babel} % langages +\frenchsetup{SmallCapsFigTabCaptions=false} + +\newcommand{\anri}{Anri Kennel} + +\newcommand{\settitle}{Projet} + +\usepackage[ + pdfauthor={\anri}, % author metadata + pdftitle={\settitle}, % title metadata + hidelinks, % clickable links in table of contents +]{hyperref} + +\title{\settitle} + +\title{Projet} +\author{\anri\thanks{\anri : 22302653} \\ +Programmation système avancée $\cdot$ Université Paris Cité} +\date{Année universitaire 2023-2024} + +\begin{document} +\maketitle +\tableofcontents +\clearpage + +\section{Description} +\dots + +\section{Statistiques} +\dots + +\end{document} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..40baf29 --- /dev/null +++ b/src/main.c @@ -0,0 +1,5 @@ +#include "../includes/quicksort.h" + +int main(int argc, char *argv[]) { + return benchmark(argc, argv); +} diff --git a/src/quicksort.c b/src/quicksort.c new file mode 100644 index 0000000..03c0899 --- /dev/null +++ b/src/quicksort.c @@ -0,0 +1,150 @@ +#include "../includes/quicksort.h" + +int partition(int *a, int lo, int hi) { + int pivot = a[lo]; + int i = lo - 1; + int j = hi + 1; + int t; + while (1) { + do { + i++; + } while (a[i] < pivot); + + do { + j--; + } while (a[j] > pivot); + + if (i >= j) { + return j; + } + + t = a[i]; + a[i] = a[j]; + a[j] = t; + } +} + +struct quicksort_args { + int *a; + int lo, hi; +}; + +struct quicksort_args *new_args(int *a, int lo, int hi) { + struct quicksort_args *args = malloc(sizeof(struct quicksort_args)); + if (args == NULL) { + return NULL; + } + + args->a = a; + args->lo = lo; + args->hi = hi; + return args; +} + +void quicksort_serial(int *a, int lo, int hi) { + int p; + + if (lo >= hi) { + return; + } + + p = partition(a, lo, hi); + quicksort_serial(a, lo, p); + quicksort_serial(a, p + 1, hi); +} + +void quicksort(void *closure, struct scheduler *s) { + struct quicksort_args *args = (struct quicksort_args *)closure; + int *a = args->a; + int lo = args->lo; + int hi = args->hi; + int p; + int rc; + + free(closure); + + if (lo >= hi) { + return; + } + + if (hi - lo <= 128) { + quicksort_serial(a, lo, hi); + return; + } + + p = partition(a, lo, hi); + rc = sched_spawn(quicksort, new_args(a, lo, p), s); + assert(rc >= 0); + rc = sched_spawn(quicksort, new_args(a, p + 1, hi), s); + assert(rc >= 0); +} + +int benchmark(int argc, char **argv) { + int *a; + struct timespec begin, end; + double delay; + int rc; + int n = 10 * 1024 * 1024; + int nthreads = -1; + int serial = 0; + + while (1) { + int opt = getopt(argc, argv, "sn:t:"); + if (opt < 0) { + break; + } + switch (opt) { + case 's': + serial = 1; + break; + case 'n': + n = atoi(optarg); + if (n <= 0) { + goto usage; + } + break; + case 't': + nthreads = atoi(optarg); + if (nthreads <= 0) { + goto usage; + } + break; + default: + goto usage; + } + } + + a = malloc(n * sizeof(int)); + + unsigned long long s = 0; + for (int i = 0; i < n; i++) { + s = s * 6364136223846793005ULL + 1442695040888963407; + a[i] = (int)((s >> 33) & 0x7FFFFFFF); + } + + clock_gettime(CLOCK_MONOTONIC, &begin); + + if (serial) { + quicksort_serial(a, 0, n - 1); + } else { + rc = + sched_init(nthreads, (n + 127) / 128, quicksort, new_args(a, 0, n - 1)); + assert(rc >= 0); + } + + clock_gettime(CLOCK_MONOTONIC, &end); + delay = end.tv_sec + end.tv_nsec / 1000000000.0 - + (begin.tv_sec + begin.tv_nsec / 1000000000.0); + printf("Done in %lf seconds.\n", delay); + + for (int i = 0; i < n - 1; i++) { + assert(a[i] <= a[i + 1]); + } + + free(a); + return 0; + +usage: + printf("quicksort [-n size] [-t threads] [-s]\n"); + return 1; +} diff --git a/src/sched.c b/src/sched.c new file mode 100644 index 0000000..2dc1215 --- /dev/null +++ b/src/sched.c @@ -0,0 +1 @@ +#include "../includes/sched.h"