108 lines
3.1 KiB
C++
108 lines
3.1 KiB
C++
#include <array>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <thread>
|
|
|
|
struct WorkerArgs
|
|
{
|
|
float x0, x1;
|
|
float y0, y1;
|
|
unsigned int width;
|
|
unsigned int height;
|
|
int maxIterations;
|
|
int *output;
|
|
int threadId;
|
|
int numThreads;
|
|
};
|
|
|
|
extern void mandelbrot_serial(float x0,
|
|
float y0,
|
|
float x1,
|
|
float y1,
|
|
int width,
|
|
int height,
|
|
int start_row,
|
|
int num_rows,
|
|
int max_iterations,
|
|
int *output);
|
|
|
|
//
|
|
// worker_thread_start --
|
|
//
|
|
// Thread entrypoint.
|
|
void worker_thread_start(WorkerArgs *const args)
|
|
{
|
|
|
|
// TODO FOR PP STUDENTS: Implement the body of the worker
|
|
// thread here. Each thread could make a call to mandelbrot_serial()
|
|
// to compute a part of the output image. For example, in a
|
|
// program that uses two threads, thread 0 could compute the top
|
|
// half of the image and thread 1 could compute the bottom half.
|
|
// Of course, you can copy mandelbrot_serial() to this file and
|
|
// modify it to pursue a better performance.
|
|
|
|
printf("Hello world from thread %d\n", args->threadId);
|
|
}
|
|
|
|
//
|
|
// mandelbrot_thread --
|
|
//
|
|
// Multi-threaded implementation of mandelbrot set image generation.
|
|
// Threads of execution are created by spawning std::threads.
|
|
void mandelbrot_thread(int num_threads,
|
|
float x0,
|
|
float y0,
|
|
float x1,
|
|
float y1,
|
|
int width,
|
|
int height,
|
|
int max_iterations,
|
|
int *output)
|
|
{
|
|
static constexpr int max_threads = 32;
|
|
|
|
if (num_threads > max_threads)
|
|
{
|
|
fprintf(stderr, "Error: Max allowed threads is %d\n", max_threads);
|
|
exit(1);
|
|
}
|
|
|
|
// Creates thread objects that do not yet represent a thread.
|
|
std::array<std::thread, max_threads> workers;
|
|
std::array<WorkerArgs, max_threads> args = {};
|
|
|
|
for (int i = 0; i < num_threads; i++)
|
|
{
|
|
// TODO FOR PP STUDENTS: You may or may not wish to modify
|
|
// the per-thread arguments here. The code below copies the
|
|
// same arguments for each thread
|
|
args[i].x0 = x0;
|
|
args[i].y0 = y0;
|
|
args[i].x1 = x1;
|
|
args[i].y1 = y1;
|
|
args[i].width = width;
|
|
args[i].height = height;
|
|
args[i].maxIterations = max_iterations;
|
|
args[i].numThreads = num_threads;
|
|
args[i].output = output;
|
|
|
|
args[i].threadId = i;
|
|
}
|
|
|
|
// Spawn the worker threads. Note that only numThreads-1 std::threads
|
|
// are created and the main application thread is used as a worker
|
|
// as well.
|
|
for (int i = 1; i < num_threads; i++)
|
|
{
|
|
workers[i] = std::thread(worker_thread_start, &args[i]);
|
|
}
|
|
|
|
worker_thread_start(&args[0]);
|
|
|
|
// join worker threads
|
|
for (int i = 1; i < num_threads; i++)
|
|
{
|
|
workers[i].join();
|
|
}
|
|
}
|