Files
pp2026-hw2/part2/mandelbrot_thread.cpp
2026-10-21 15:10:30 +08:00

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();
}
}