Cleanup: Improved main file readablilty and redundant code
This commit is contained in:
+154
-184
@@ -21,173 +21,10 @@ const uint16_t NUMBER_OF_VERSIONS = 4;
|
||||
|
||||
|
||||
void save_bmp(const char *filename, unsigned char *img, size_t width, ssize_t height,_Bool color);
|
||||
void benchmarking(size_t benchmarking_amount, int version_to_use, float complex complexA, size_t width, ssize_t height, float resolution, unsigned n, _Bool colored);
|
||||
unsigned tests(void);
|
||||
void checkInputs(_Bool n,_Bool r,_Bool o,_Bool d,_Bool s);
|
||||
|
||||
void benchmarking(size_t benchmarking_amount, int version_to_use, float complex complexA, size_t width, ssize_t height, float resolution, unsigned n, _Bool colored) {
|
||||
struct timespec start;
|
||||
struct timespec end;
|
||||
void (*tricorn_implementation)(float complex, size_t, ssize_t, float, unsigned, _Bool, unsigned char*);
|
||||
|
||||
unsigned int bytePerColor = colored ? 3 : 1;
|
||||
unsigned char *tempArr = malloc(width*height*bytePerColor);
|
||||
if(tempArr == NULL) {
|
||||
fprintf(stderr,"Could not allocate memory for buffer");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
switch (version_to_use)
|
||||
{
|
||||
case 0: // Uses highly optimized SIMD and threaded version / main implementation
|
||||
printf("Benchmarking V0 - highly optimized SIMD\n");
|
||||
tricorn_implementation = tricorn;
|
||||
break;
|
||||
case 1: // Uses unoptimised scalar comparison implementation
|
||||
printf("Benchmarking V1 - scalar comparison implementation\n");
|
||||
tricorn_implementation = tricorn_V1;
|
||||
break;
|
||||
case 2: // Uses optimized SISD implementation
|
||||
printf("Benchmarking V2 - unoptimized SIMD implementation\n");
|
||||
tricorn_implementation = tricorn_V2;
|
||||
break;
|
||||
case 3: // Uses unoptimized SIMD implementation
|
||||
printf("Benchmarking V3 - highly optimized SIMD + Threading implementation\n");
|
||||
tricorn_implementation = tricorn_V3;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"Invalid version to use: V%d. Available versions are : V0,V1,V2,V3,V4,V5\n",version_to_use);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
for (size_t i = 0; i < benchmarking_amount; i++)
|
||||
{
|
||||
tricorn_implementation(complexA,width,height,resolution,n,colored,tempArr);
|
||||
}
|
||||
clock_gettime(CLOCK_MONOTONIC, &end);
|
||||
|
||||
double time = end.tv_sec- start.tv_sec + 1e-9 * (end.tv_nsec- start.tv_nsec);
|
||||
printf("The total amount of time spent for %zu function calls: %lf seconds\n", benchmarking_amount,time);
|
||||
double average = time / benchmarking_amount;
|
||||
printf("Average time per function: %lf seconds\n", average);
|
||||
|
||||
free(tempArr);
|
||||
}
|
||||
|
||||
unsigned tests(void) {
|
||||
|
||||
printf("Doing testing\n\n");
|
||||
|
||||
printf("\n\n\nTest 1: Default image, coloured\n");
|
||||
float complex start = -2.0f - 0.5f*I;
|
||||
size_t width = 1920;
|
||||
size_t height = 1080;
|
||||
float resolution = 0.001f;
|
||||
int n = 200;
|
||||
_Bool colored = true;
|
||||
|
||||
printf("Start: %f%+fi\n", crealf(start), cimagf(start));
|
||||
printf("Width: %li\n",width);
|
||||
printf("Height: %li\n", height);
|
||||
printf("Resolution: %f\n", resolution);
|
||||
printf("Iterations: %i\n", n);
|
||||
printf("Colored: %s\n", colored ? "true" : "false");
|
||||
|
||||
|
||||
for(int i = 0; i < NUMBER_OF_VERSIONS;i++) {
|
||||
printf("\n\n");
|
||||
benchmarking(TESTING_AMOUNT,i,start, width, height, resolution, n, colored);
|
||||
}
|
||||
|
||||
printf("\n\n\nTest 2: Ultra high resolution low iterations\n");
|
||||
start = -2.0f - 0.5f*I;
|
||||
width = 7680;
|
||||
height = 4320;
|
||||
resolution = 0.001f;
|
||||
n = 5;
|
||||
|
||||
printf("Start: %f%+fi\n", crealf(start), cimagf(start));
|
||||
printf("Width: %li\n",width);
|
||||
printf("Height: %li\n", height);
|
||||
printf("Resolution: %f\n", resolution);
|
||||
printf("Iterations: %i\n", n);
|
||||
printf("Colored: %s\n", colored ? "true" : "false");
|
||||
|
||||
for(int i = 0; i < NUMBER_OF_VERSIONS; i++) {
|
||||
printf("\n\n");
|
||||
benchmarking(TESTING_AMOUNT,i,start, width, height, resolution, n, colored);
|
||||
}
|
||||
|
||||
printf("\n\n\nTest 3: Zoomed on fractal edge\n");
|
||||
start = -1.431f - 0.250f*I;
|
||||
width = 1024;
|
||||
height = 1024;
|
||||
resolution = 0.0005f;
|
||||
n = 3000;
|
||||
|
||||
printf("Start: %f%+fi\n", crealf(start), cimagf(start));
|
||||
printf("Width: %li\n",width);
|
||||
printf("Height: %li\n", height);
|
||||
printf("Resolution: %f\n", resolution);
|
||||
printf("Iterations: %i\n", n);
|
||||
printf("Colored: %s\n", colored ? "true" : "false");
|
||||
|
||||
|
||||
|
||||
for(int i = 0; i < NUMBER_OF_VERSIONS; i++) {
|
||||
printf("\n\n");
|
||||
benchmarking(TESTING_AMOUNT,i,start, width, height, resolution, n, colored);
|
||||
}
|
||||
|
||||
|
||||
|
||||
printf("\nTest 4: Pure Black\n");
|
||||
start = 0;
|
||||
width = 1920;
|
||||
height = 1080;
|
||||
resolution = 0.00001f;
|
||||
n = 1000;
|
||||
|
||||
printf("Start: %f%+fi\n", crealf(start), cimagf(start));
|
||||
printf("Width: %li\n",width);
|
||||
printf("Height: %li\n", height);
|
||||
printf("Resolution: %f\n", resolution);
|
||||
printf("Iterations: %i\n", n);
|
||||
printf("Colored: %s\n", colored ? "true" : "false");
|
||||
|
||||
|
||||
for(int i = 0; i < NUMBER_OF_VERSIONS; i++) {
|
||||
printf("\n\n");
|
||||
benchmarking(TESTING_AMOUNT,i,start, width, height, resolution, n, colored);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void checkInputs(_Bool n,_Bool r,_Bool o,_Bool d,_Bool s) {
|
||||
if (!n)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Input n not given.\n");
|
||||
}
|
||||
if (!r)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Input r not given.\n");
|
||||
}
|
||||
if (!o)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Input o not given.\n");
|
||||
}
|
||||
if (!d)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Input d not given.\n");
|
||||
}
|
||||
if (!s)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Input s not given.\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Example test command
|
||||
// ./project -s -2.0,-1.5 -d 1200,900 -r 0.003 -n 256 -o tricorn.bmp -C
|
||||
@@ -427,24 +264,23 @@ int main(int argc, char** argv)
|
||||
opt_long = getopt_long(argc,argv,optstring, long_options, NULL);
|
||||
}
|
||||
|
||||
float complex complexA = (starting_point_real + starting_point_imaginary*I);
|
||||
|
||||
// Run
|
||||
float complex start = (starting_point_real + starting_point_imaginary*I);
|
||||
int bytesPerColour = colored ? 3 : 1;
|
||||
|
||||
ssize_t absolute_height = height >= 0 ? height : height * - 1;
|
||||
unsigned char *tempArr = malloc(width*absolute_height*bytesPerColour);// allocate image array on the heap to support large images as the stack is usually only 8 MB big
|
||||
if(tempArr == NULL) {
|
||||
unsigned char *imageArr = malloc(width*absolute_height*bytesPerColour);// allocate image array on the heap to support large images as the stack is usually only 8 MB big
|
||||
|
||||
if(imageArr == NULL)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
if (will_test)
|
||||
{
|
||||
return tests() ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
if (!(nGiven && rGiven && oGiven && dGiven && sGiven))
|
||||
{
|
||||
checkInputs(nGiven,rGiven,oGiven,dGiven,sGiven);
|
||||
free(tempArr);
|
||||
free(imageArr);
|
||||
free(output_data);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -452,8 +288,8 @@ int main(int argc, char** argv)
|
||||
if (will_benchmark)
|
||||
{
|
||||
printf("\nDoing benchmarking. No images will be created\n");
|
||||
benchmarking(amount_function_called,version_to_use,complexA,width,height,resolution,n,colored);
|
||||
free(tempArr);
|
||||
benchmarking(amount_function_called,version_to_use,start,width,height,resolution,n,colored);
|
||||
free(imageArr);
|
||||
free(output_data);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -462,31 +298,165 @@ int main(int argc, char** argv)
|
||||
{
|
||||
case 0:
|
||||
// Uses highly optimized SIMD - main implementation
|
||||
tricorn(complexA,width,height,resolution,n,colored,tempArr);
|
||||
tricorn(start,width,height,resolution,n,colored,imageArr);
|
||||
break;
|
||||
case 1:
|
||||
// Uses scalar comparison implementation
|
||||
tricorn_V1(complexA,width,height,resolution,n,colored,tempArr);
|
||||
tricorn_V1(start,width,height,resolution,n,colored,imageArr);
|
||||
break;
|
||||
case 2:
|
||||
// Uses unoptimized SIMD implementation
|
||||
tricorn_V2(complexA,width,height,resolution,n,colored,tempArr);
|
||||
tricorn_V2(start,width,height,resolution,n,colored,imageArr);
|
||||
break;
|
||||
case 3:
|
||||
// Uses highly optimized SIMD + Threading implementation
|
||||
tricorn_V3(complexA,width,height,resolution,n,colored,tempArr);
|
||||
tricorn_V3(start,width,height,resolution,n,colored,imageArr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
save_bmp(output_data,tempArr,width,height,colored);
|
||||
save_bmp(output_data,imageArr,width,height,colored);
|
||||
|
||||
free(output_data);
|
||||
free(tempArr);
|
||||
free(imageArr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void benchmarking(size_t benchmarking_amount, int version_to_use, float complex complexA, size_t width, ssize_t height, float resolution, unsigned n, _Bool colored) {
|
||||
struct timespec start;
|
||||
struct timespec end;
|
||||
void (*tricorn_implementation)(float complex, size_t, ssize_t, float, unsigned, _Bool, unsigned char*);
|
||||
|
||||
unsigned int bytePerColor = colored ? 3 : 1;
|
||||
unsigned char *tempArr = malloc(width*height*bytePerColor);
|
||||
if(tempArr == NULL) {
|
||||
fprintf(stderr,"Could not allocate memory for buffer");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
switch (version_to_use)
|
||||
{
|
||||
case 0: // Uses highly optimized SIMD and threaded version / main implementation
|
||||
printf("Benchmarking V0 - highly optimized SIMD\n");
|
||||
tricorn_implementation = tricorn;
|
||||
break;
|
||||
case 1: // Uses unoptimised scalar comparison implementation
|
||||
printf("Benchmarking V1 - scalar comparison implementation\n");
|
||||
tricorn_implementation = tricorn_V1;
|
||||
break;
|
||||
case 2: // Uses optimized SISD implementation
|
||||
printf("Benchmarking V2 - unoptimized SIMD implementation\n");
|
||||
tricorn_implementation = tricorn_V2;
|
||||
break;
|
||||
case 3: // Uses unoptimized SIMD implementation
|
||||
printf("Benchmarking V3 - highly optimized SIMD + Threading implementation\n");
|
||||
tricorn_implementation = tricorn_V3;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"Invalid version to use: V%d. Available versions are : V0,V1,V2,V3,V4,V5\n",version_to_use);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
for (size_t i = 0; i < benchmarking_amount; i++)
|
||||
{
|
||||
tricorn_implementation(complexA,width,height,resolution,n,colored,tempArr);
|
||||
}
|
||||
clock_gettime(CLOCK_MONOTONIC, &end);
|
||||
|
||||
double time = end.tv_sec- start.tv_sec + 1e-9 * (end.tv_nsec- start.tv_nsec);
|
||||
printf("The total amount of time spent for %zu function calls: %lf seconds\n", benchmarking_amount,time);
|
||||
double average = time / benchmarking_amount;
|
||||
printf("Average time per function: %lf seconds\n", average);
|
||||
|
||||
free(tempArr);
|
||||
}
|
||||
|
||||
void run_benchmarks(float complex start,size_t width, size_t height,float res,int n, _Bool colored);
|
||||
unsigned tests(void) {
|
||||
|
||||
printf("Doing testing\n\n");
|
||||
|
||||
|
||||
printf("\n\n\nTest 1: Default image, coloured\n");
|
||||
float complex start = -2.0f - 0.5f*I;
|
||||
size_t width = 1920;
|
||||
size_t height = 1080;
|
||||
float res = 0.001f;
|
||||
int n = 200;
|
||||
_Bool colored = true;
|
||||
run_benchmarks(start,width,height,res,n,colored);
|
||||
|
||||
|
||||
printf("\n\n\nTest 2: Ultra high resolution low iterations\n");
|
||||
start = -2.0f - 0.5f*I;
|
||||
width = 7680;
|
||||
height = 4320;
|
||||
res = 0.001f;
|
||||
n = 5;
|
||||
run_benchmarks(start,width,height,res,n,colored);
|
||||
|
||||
|
||||
printf("\n\n\nTest 3: Zoomed on fractal edge\n");
|
||||
start = -1.431f - 0.250f*I;
|
||||
width = 1024;
|
||||
height = 1024;
|
||||
res = 0.0005f;
|
||||
n = 3000;
|
||||
run_benchmarks(start,width,height,res,n,colored);
|
||||
|
||||
|
||||
printf("\nTest 4: Pure Black\n");
|
||||
start = 0;
|
||||
width = 1920;
|
||||
height = 1080;
|
||||
res = 0.00001f;
|
||||
n = 1000;
|
||||
run_benchmarks(start,width,height,res,n,colored);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
void run_benchmarks(float complex start,size_t width, size_t height,float res,int n, _Bool colored){
|
||||
printf("Start: %f%+fi\n", crealf(start), cimagf(start));
|
||||
printf("Width: %li\n",width);
|
||||
printf("Height: %li\n", height);
|
||||
printf("Resolution: %f\n", res);
|
||||
printf("Iterations: %i\n", n);
|
||||
printf("Colored: %s\n", colored ? "true" : "false");
|
||||
for(int i = 0; i < NUMBER_OF_VERSIONS;i++) {
|
||||
printf("\n\n");
|
||||
benchmarking(TESTING_AMOUNT,i,start, width, height, res, n, colored);
|
||||
}
|
||||
}
|
||||
|
||||
void checkInputs(_Bool n,_Bool r,_Bool o,_Bool d,_Bool s) {
|
||||
if (!n)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Input n not given.\n");
|
||||
}
|
||||
if (!r)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Input r not given.\n");
|
||||
}
|
||||
if (!o)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Input o not given.\n");
|
||||
}
|
||||
if (!d)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Input d not given.\n");
|
||||
}
|
||||
if (!s)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Input s not given.\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void save_bmp(const char *filename, unsigned char *img, size_t width, ssize_t height,_Bool color) {
|
||||
// Open a file at the filepath given as a stream in the program
|
||||
|
||||
Reference in New Issue
Block a user