diff --git a/includes/mandelbrot.h b/includes/mandelbrot.h new file mode 100644 index 0000000..724dfbf --- /dev/null +++ b/includes/mandelbrot.h @@ -0,0 +1,6 @@ +#pragma once + +/* Lance le benchmark avec mandelbrot (TP10) + * + * Renvoie le temps d'exécution */ +double benchmark_mandelbrot(int, int); diff --git a/includes/quicksort.h b/includes/quicksort.h index f7f7881..84e7a93 100644 --- a/includes/quicksort.h +++ b/includes/quicksort.h @@ -1,3 +1,6 @@ #pragma once -int benchmark(int argc, char **argv); +/* Lance le benchmark avec quicksort (fournis) + * + * Renvoie le temps d'exécution */ +double benchmark_quicksort(int, int); diff --git a/src/main.c b/src/main.c index 2cbb073..dbcbd08 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,62 @@ +#include "../includes/mandelbrot.h" #include "../includes/quicksort.h" +#include +#include +#include +#include + int main(int argc, char *argv[]) { - return benchmark(argc, argv); + int serial = 0; + int nthreads = -1; + + int quicksort = 0; + int mandelbrot = 0; + double delay; + + int opt; + while((opt = getopt(argc, argv, "qmst:")) != -1) { + if(opt < 0) { + goto usage; + } + + switch(opt) { + case 'q': + quicksort = 1; + break; + case 'm': + mandelbrot = 1; + break; + case 's': + serial = 1; + break; + case 't': + nthreads = atoi(optarg); + break; + default: + goto usage; + } + } + if(nthreads < 0 && !serial) { + goto usage; + } + + if(quicksort) { + delay = benchmark_quicksort(serial, nthreads); + } else if(mandelbrot) { + delay = benchmark_mandelbrot(serial, nthreads); + } else { + goto usage; + } + + assert(delay >= 0.0); + printf("Done in %lf seconds.\n", delay); + + return 0; + +usage: + printf("Usage: %s -q|m [-t threads] [-s]\n", argv[0]); + return 1; } diff --git a/src/mandelbrot.c b/src/mandelbrot.c new file mode 100644 index 0000000..94b34bb --- /dev/null +++ b/src/mandelbrot.c @@ -0,0 +1,157 @@ +#include "../includes/mandelbrot.h" +#include "../includes/sched.h" + +#include +#include +#include +#include +#include + +#define ITERATIONS 1000 + +struct mandelbrot_args { + unsigned int *image; + double scale; + int dx, dy, width, height; +}; + +struct mandelbrot_args * +new_mandelbrot_args(unsigned int *image, double scale, int dx, int dy, + int width, int height) +{ + struct mandelbrot_args *args; + + if(!(args = malloc(sizeof(struct mandelbrot_args)))) { + perror("Mandelbrot parameters"); + return NULL; + } + + args->image = image; + args->scale = scale; + args->dx = dx; + args->dy = dy; + args->width = width; + args->height = height; + + return args; +} + +static int +mandel(double complex c) +{ + double complex z = 0.0; + int i = 0; + while(i < ITERATIONS && creal(z) * creal(z) + cimag(z) * cimag(z) <= 4.0) { + z = z * z + c; + i++; + } + return i; +} + +static double complex +toc(int x, int y, int dx, int dy, double scale) +{ + return ((x - dx) + I * (y - dy)) / scale; +} + +static unsigned int +torgb(int n) +{ + unsigned char r, g, b; + + if(n < 128) { + int v = 2 * n; + r = v; + g = 0; + b = 255 - v; + } else if(n < 256) { + int v = 2 * (n - 128); + r = 0; + g = v; + b = 255 - v; + } else if(n < 512) { + int v = n - 256; + r = 255 - v; + g = v; + b = 0; + } else if(n < 1024) { + int v = (n - 512) / 2; + g = 255; + r = b = v; + } else { + r = g = b = 255; + } + + return r << 16 | g << 8 | b; +} + +void +draw(void *closure, struct scheduler *s) +{ + struct mandelbrot_args *args = (struct mandelbrot_args *)closure; + unsigned int *image = args->image; + double scale = args->scale; + int dx = args->dx; + int dy = args->dy; + int width = args->width; + int height = args->height; + + free(closure); + + for(int y = 0; y < height; y++) { + for(int x = 0; x < width; x++) { + /* TODO: Utiliser s */ + unsigned rgb = torgb(mandel(toc(x, y, dx, dy, scale))); + image[y * width + x] = rgb; + } + } +} + +void +draw_serial(unsigned int *image, double scale, int dx, int dy, int width, + int height) +{ + for(int y = 0; y < height; y++) { + for(int x = 0; x < width; x++) { + unsigned rgb = torgb(mandel(toc(x, y, dx, dy, scale))); + image[y * width + x] = rgb; + } + } +} + +double +benchmark_mandelbrot(int serial, int nthreads) +{ + unsigned int *image; + struct timespec begin, end; + double delay; + int rc; + int width = 1920; + int height = 1080; + double scale = width / 4.0; + int dx = width / 2; + int dy = height / 2; + + if(!(image = malloc(width * height * sizeof(unsigned int)))) { + perror("Image allocation"); + return 1; + } + + clock_gettime(CLOCK_MONOTONIC, &begin); + + if(serial) { + draw_serial(image, scale, dx, dy, width, height); + } else { + rc = sched_init( + nthreads, width * height, draw, + new_mandelbrot_args(image, scale, dx, dy, width, height)); + 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); + + free(image); + return delay; +} diff --git a/src/quicksort.c b/src/quicksort.c index a0ac3af..9351cc8 100644 --- a/src/quicksort.c +++ b/src/quicksort.c @@ -93,43 +93,14 @@ quicksort(void *closure, struct scheduler *s) assert(rc >= 0); } -int -benchmark(int argc, char **argv) +double +benchmark_quicksort(int serial, int nthreads) { 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); - break; - case 't': - nthreads = atoi(optarg); - break; - default: - goto usage; - } - } - - if(n <= 0) { - goto usage; - } - if(nthreads < 0 && !serial) { - goto usage; - } a = malloc(n * sizeof(int)); @@ -152,16 +123,11 @@ benchmark(int argc, char **argv) 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; + return delay; }