aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--algorithms/burning-ship-lattice.c11
-rw-r--r--algorithms/burning-ship.c11
-rw-r--r--algorithms/mandelbrot.c11
-rw-r--r--algorithms/tricorn.c11
-rw-r--r--fractal-gen.c106
-rw-r--r--fractal-gen.h18
6 files changed, 98 insertions, 70 deletions
diff --git a/algorithms/burning-ship-lattice.c b/algorithms/burning-ship-lattice.c
index a219537..7c2d1e9 100644
--- a/algorithms/burning-ship-lattice.c
+++ b/algorithms/burning-ship-lattice.c
@@ -31,27 +31,26 @@ void *generate_burning_ship_lattice_section(void *section)
{
data_section *d = (data_section*)section;
unsigned int x,y,i;
- int idx = 0;
double a,b;
double complex z,c;
double size_units = 0.09f;
double top = -0.082f;
double left = -1.8f;
- for (y = d->core, b = (d->core*(size_units/d->size)+top); y < d->size; b+=((d->cores*size_units)/d->size), y+=d->cores)
+ for (y = d->core, b = (d->core*(size_units/size)+top); y < size; b+=((cores*size_units)/size), y+=cores)
{
- for (x = 0, a = left; x < d->size; a+=(size_units/d->size), x++)
+ for (x = 0, a = left; x < size; a+=(size_units/size), x++)
{
z = 0;
c = a+I*b;
- for (i = 0; i < d->iterat; i++)
+ for (i = 0; i < iterat; i++)
{
if (cabsf(z) >= 2)
break;
- z = cpow( cabsf(crealf(z)) + I*cabsf(cimagf(z)) , d->power) + c;
+ z = cpow( cabsf(crealf(z)) + I*cabsf(cimagf(z)) , power) + c;
}
- d->data[idx++] = (255*i)/d->iterat;
+ d->data[d->idx++] = (255*i)/iterat;
}
}
return NULL;
diff --git a/algorithms/burning-ship.c b/algorithms/burning-ship.c
index 35d1839..8a5d1a1 100644
--- a/algorithms/burning-ship.c
+++ b/algorithms/burning-ship.c
@@ -31,27 +31,26 @@ void *generate_burning_ship_section(void *section)
{
data_section *d = (data_section*)section;
unsigned int x,y,i;
- int idx = 0;
double a,b;
double complex z,c;
double size_units = 3.5f;
double top = -2.2f;
double left = -2.2f;
- for (y = d->core, b = (d->core*(size_units/d->size)+top); y < d->size; b+=((d->cores*size_units)/d->size), y+=d->cores)
+ for (y = d->core, b = (d->core*(size_units/size)+top); y < size; b+=((cores*size_units)/size), y+=cores)
{
- for (x = 0, a = left; x < d->size; a+=(size_units/d->size), x++)
+ for (x = 0, a = left; x < size; a+=(size_units/size), x++)
{
z = 0;
c = a+I*b;
- for (i = 0; i < d->iterat; i++)
+ for (i = 0; i < iterat; i++)
{
if (cabsf(z) >= 2)
break;
- z = cpow( cabsf(crealf(z)) + I*cabsf(cimagf(z)) , d->power) + c;
+ z = cpow( cabsf(crealf(z)) + I*cabsf(cimagf(z)) , power) + c;
}
- d->data[idx++] = (255*i)/d->iterat;
+ d->data[d->idx++] = (255*i)/iterat;
}
}
return NULL;
diff --git a/algorithms/mandelbrot.c b/algorithms/mandelbrot.c
index 1c3f5a2..28bb188 100644
--- a/algorithms/mandelbrot.c
+++ b/algorithms/mandelbrot.c
@@ -31,27 +31,26 @@ void *generate_mandelbrot_section(void *section)
{
data_section *d = (data_section*)section;
unsigned int x,y,i;
- int idx = 0;
double a,b;
double complex z,c;
double size_units = 3.5f;
double top = -1.75f;
double left = -2.5f;
- for (y = d->core, b = (d->core*(size_units/d->size)+top); y < d->size; b+=((d->cores*size_units)/d->size), y+=d->cores)
+ for (y = d->core, b = (d->core*(size_units/size)+top); y < size; b+=((cores*size_units)/size), y+=cores)
{
- for (x = d->clust_id, a = (d->clust_id*(size_units/d->size)+left); x < d->size; a+=((d->clust_total*size_units)/d->size), x+=d->clust_total)
+ for (x = clust_id, a = (clust_id*(size_units/size)+left); x < size; a+=((clust_total*size_units)/size), x+=clust_total)
{
z = 0;
c = a+I*b;
- for (i = 0; i < d->iterat; i++)
+ for (i = 0; i < iterat; i++)
{
if (cabsf(z) >= 2)
break;
- z = cpow(z , d->power) + c;
+ z = cpow(z , power) + c;
}
- d->data[idx++] = (255*i)/d->iterat;
+ d->data[d->idx++] = (255*i)/iterat;
}
}
return NULL;
diff --git a/algorithms/tricorn.c b/algorithms/tricorn.c
index 16c399e..c89420a 100644
--- a/algorithms/tricorn.c
+++ b/algorithms/tricorn.c
@@ -31,27 +31,26 @@ void *generate_tricorn_section(void *section)
{
data_section *d = (data_section*)section;
unsigned int x,y,i;
- int idx = 0;
double a,b;
double complex z,c;
double size_units = 4.f;
double top = -2.f;
double left = -2.3f;
- for (y = d->core, b = (d->core*(size_units/d->size)+top); y < d->size; b+=((d->cores*size_units)/d->size), y+=d->cores)
+ for (y = d->core, b = (d->core*(size_units/size)+top); y < size; b+=((cores*size_units)/size), y+=cores)
{
- for (x = 0, a = left; x < d->size; a+=(size_units/d->size), x++)
+ for (x = 0, a = left; x < size; a+=(size_units/size), x++)
{
z = 0;
c = a+I*b;
- for (i = 0; i < d->iterat; i++)
+ for (i = 0; i < iterat; i++)
{
if (cabsf(z) >= 2)
break;
- z = cpow(conj(z) , d->power) + c;
+ z = cpow(conj(z) , power) + c;
}
- d->data[idx++] = (255*i)/d->iterat;
+ d->data[d->idx++] = (255*i)/iterat;
}
}
return NULL;
diff --git a/fractal-gen.c b/fractal-gen.c
index dc30e8d..3268af2 100644
--- a/fractal-gen.c
+++ b/fractal-gen.c
@@ -35,9 +35,10 @@ struct section_generator
int main(int argc, char **argv)
{
- unsigned int size, iterat, cores, i, x, y;
- unsigned int clust_id, clust_total;
- double power;
+ unsigned long x, y, i;
+ double thread_mult;
+ double ram_nice = 0.f;
+ char* ram_unit = NULL;
char* bname;
data_section* sections;
void *(*generator)(void *);
@@ -47,9 +48,9 @@ int main(int argc, char **argv)
{ "burning-ship-gen" , &generate_burning_ship_section },
{ "burning-ship-lattice-gen" , &generate_burning_ship_lattice_section },
{ "tricorn-gen" , &generate_tricorn_section }
- };
+ };
- // Select correct generator for the fractal type
+ /* Select correct generator for the fractal type */
bname = basename(argv[0]);
generator = NULL;
for (i = 0; i < sizeof(generators)/sizeof(struct section_generator); i++)
@@ -62,10 +63,12 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}
- if (argc < 4 || argc > 6)
+ if (argc < 4 || argc > 7)
{
- fprintf(stderr, "%s size iterat power [threads]\n"
- "%s size iterat power cluster-id cluster-total\n", argv[0], argv[0]);
+ fprintf(stderr,
+ "%s size iterat power [threads]\n"
+ "%s size iterat power thread_multiplier cluster-id cluster-total\n",
+ argv[0], argv[0]);
return EXIT_FAILURE;
}
@@ -78,52 +81,73 @@ int main(int argc, char **argv)
* - our ID in cluster
* - total members in cluster
*/
- cores = (argc == 5)? atoi(argv[4]) : sysconf(_SC_NPROCESSORS_ONLN); // Screw maintainability ;)
- clust_id = argc == 6? atoi(argv[4]) : 0;
- clust_total = argc == 6? atoi(argv[5]) : 1;
+ cores = (argc == 5)? atoi(argv[4]) : sysconf(_SC_NPROCESSORS_ONLN);
+ thread_mult = argc == 7? atof(argv[4]) : 1.f;
+ clust_id = argc == 7? atoi(argv[5]) : 0;
+ clust_total = argc == 7? atoi(argv[6]) : 1;
- // Interlacing is column-based, can't have more workers than columns
+ /* Extend number of threads to multiplier value */
+ cores *= thread_mult;
+
+ /* Interlacing is column-based, can't have more workers than columns */
if (cores > size)
{
fprintf(stderr, "WARN: Capping number of threads to image width\n");
cores = size;
}
+ if (size % clust_total != 0)
+ {
+ fprintf(stderr, "ERROR: size must be an exact multiple of clust_total\n");
+ return EXIT_FAILURE;
+ }
+
assert(size > 0);
assert(iterat > 0);
assert(cores > 0);
- // Allocate memory for sections
+ /* Allocate memory for sections */
if ((sections = malloc(sizeof(data_section)*cores)) == NULL)
{
perror("malloc");
return EXIT_FAILURE;
}
- // Spawn all the threads! Something something interlacing
- fprintf(stderr, "Spawning %d threads:\n", cores);
+ ram_nice = (size*size)/clust_total;
+ if (ram_nice < 1024)
+ ram_unit = "B";
+ else if (ram_nice < 1024*1024)
+ ram_nice /= 1024, ram_unit = "KiB";
+ else if (ram_nice < 1024*1024*1024)
+ ram_nice /= (1024*1024), ram_unit = "MiB";
+ else
+ ram_nice /= (1024*1024*1024), ram_unit = "GiB";
+
+ fprintf(stderr,
+ "Forecast resource use:\n"
+ " Threads: %d\n"
+ " RAM : ~%.4f %s\n",
+ cores,
+ ram_nice,
+ ram_unit);
+ /* Spawn all the threads! Something something interlacing */
for (i = 0; i < cores; i++)
{
- // Has to be a better way
- sections[i].core = i;
- sections[i].cores = cores;
- sections[i].clust_id = clust_id;
- sections[i].clust_total = clust_total;
- sections[i].size = size;
- sections[i].power = power;
- sections[i].iterat = iterat;
-
- // A bit complex, icky, will document later
+ /* A bit complex, icky, will document later */
if (i < (size%cores))
- x = (size*((int)(size/cores)+1));
+ x = (size/cores)+1;
else
- x = (size*(int)(size/cores));
+ x = (size/cores);
+
+ x *= size;
+ x = ceilf((double)x/clust_total);
if ((sections[i].data = malloc(x)) == NULL)
{
- fprintf(stderr, "\n");
+ fprintf(stderr, "\nmalloc of %lu bytes failed\n", x);
perror("malloc");
- // Free already allocated chunks of memory
+
+ /* Free already allocated chunks of memory */
i--;
while(i-- + 1)
free(sections[i].data);
@@ -131,31 +155,35 @@ int main(int argc, char **argv)
free(sections);
return EXIT_FAILURE;
}
- fprintf(stderr, " -> Thread #%d (%d bytes data area)\r", i+1, x);
+ sections[i].core = i;
+ sections[i].datasize = x;
+ fprintf(stderr, " -> Thread %lu\r", i);
pthread_create(&sections[i].thread, NULL, generator, &(sections[i]));
}
- // Wait for each thread to complete
+ while((x = sections[0].idx) < sections[0].datasize)
+ {
+ fprintf(stderr, "Thread 0: %.4f%%\r", 100.f*(double)x/sections[0].datasize );
+ sleep(1);
+ }
+
+ /* Wait for each thread to complete */
for (i = 0; i < cores; i++)
pthread_join(sections[i].thread, NULL);
- // Output PGM Header
+ /* Output PGM Header */
printf("P5\n%d\n%d\n255\n",size/clust_total,size);
- // Vomit the data segments back onto the screen, deinterlacing
- // TO DO: look at fwrite performance benefits over putchar
+ /* Vomit the data segments back onto the screen, deinterlacing
+ * TO DO: look at fwrite performance benefits over putchar */
for (y = 0; y < size; y++)
- {
for (x = 0; x < size/clust_total; x++)
- {
putchar(sections[y%cores].data[(y/cores)*(size/clust_total) + x]);
- }
- }
fprintf(stderr, "\nDone\n");
- // Free the memory we allocated for point data
+ /* Free the memory we allocated for point data */
for (i = 0; i < cores; i++)
free(sections[i].data);
diff --git a/fractal-gen.h b/fractal-gen.h
index 656aeec..a4c0b76 100644
--- a/fractal-gen.h
+++ b/fractal-gen.h
@@ -40,17 +40,21 @@
typedef struct
{
- unsigned int core;
- unsigned int cores;
- unsigned int clust_id;
- unsigned int clust_total;
- unsigned int size;
- double power;
- unsigned int iterat;
+ volatile unsigned long idx;
+ unsigned long core;
+ unsigned long datasize;
char* data;
pthread_t thread;
} data_section;
+unsigned int cores;
+unsigned int clust_id;
+unsigned int clust_total;
+unsigned int size;
+unsigned int iterat;
+double power;
+
+
#include "algorithms.h"
#endif