add multiple benchmark support, mandelbrot is still wip

This commit is contained in:
Mylloon 2024-04-24 01:32:17 +02:00
parent b5df88f878
commit d927f95d6a
Signed by: Anri
GPG key ID: A82D63DFF8D1317F
5 changed files with 226 additions and 39 deletions

6
includes/mandelbrot.h Normal file
View file

@ -0,0 +1,6 @@
#pragma once
/* Lance le benchmark avec mandelbrot (TP10)
*
* Renvoie le temps d'exécution */
double benchmark_mandelbrot(int, int);

View file

@ -1,3 +1,6 @@
#pragma once #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);

View file

@ -1,7 +1,62 @@
#include "../includes/mandelbrot.h"
#include "../includes/quicksort.h" #include "../includes/quicksort.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int int
main(int argc, char *argv[]) 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;
} }

157
src/mandelbrot.c Normal file
View file

@ -0,0 +1,157 @@
#include "../includes/mandelbrot.h"
#include "../includes/sched.h"
#include <assert.h>
#include <complex.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#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;
}

View file

@ -93,43 +93,14 @@ quicksort(void *closure, struct scheduler *s)
assert(rc >= 0); assert(rc >= 0);
} }
int double
benchmark(int argc, char **argv) benchmark_quicksort(int serial, int nthreads)
{ {
int *a; int *a;
struct timespec begin, end; struct timespec begin, end;
double delay; double delay;
int rc; int rc;
int n = 10 * 1024 * 1024; 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)); a = malloc(n * sizeof(int));
@ -152,16 +123,11 @@ benchmark(int argc, char **argv)
clock_gettime(CLOCK_MONOTONIC, &end); clock_gettime(CLOCK_MONOTONIC, &end);
delay = end.tv_sec + end.tv_nsec / 1000000000.0 - delay = end.tv_sec + end.tv_nsec / 1000000000.0 -
(begin.tv_sec + begin.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++) { for(int i = 0; i < n - 1; i++) {
assert(a[i] <= a[i + 1]); assert(a[i] <= a[i + 1]);
} }
free(a); free(a);
return 0; return delay;
usage:
printf("quicksort [-n size] [-t threads] [-s]\n");
return 1;
} }