Mandelbrot切片图像提高速度

时间:2018-05-04 12:57:40

标签: c++

Mandelbrot集当前通过从main中调用函数将图像显示在一整套中。

// This shows the whole set.
    compute_mandelbrot(-2.0, 1.0, 1.125, -1.125);

我的计划是将图像分成16个水平切片,然后显示它以提高速度,然后将其并行编程。 我不确定如何创建这些切片,有人可以解释,重定向我或显示一些示例代码

图片详情:

// The size of the image to generate.
const int WIDTH = 100;
const int HEIGHT = 100;

// The number of times to iterate before we assume that a point isn't in the
// Mandelbrot set.

const int MAX_ITERATIONS = 500;

出于测试目的,生病发送完整代码,没有错误 - 由于整个过程需要超过30秒才能输出,因此无法有效编码,这对于Mandelbrot集来说太长了,因此紧迫性切片和并行编程。

如果有人有任何其他指示,那么他们将非常感激

e.g。在哪里实现并行编程

    using std::chrono::duration_cast;
using std::chrono::milliseconds;
using std::complex;
using std::cout;
using std::endl;
using std::ofstream;

// Define the alias "the_clock" for the clock type we're going to use.
typedef std::chrono::steady_clock the_clock;


// The size of the image to generate.
const int WIDTH = 100;
const int HEIGHT = 100;

// The number of times to iterate before we assume that a point isn't in the
// Mandelbrot set.

const int MAX_ITERATIONS = 500;

// The image data.
// Each pixel is represented as 0xRRGGBB.
uint32_t image[HEIGHT][WIDTH];


// Write the image to a TGA file with the given name.
// Format specification: http://www.gamers.org/dEngine/quake3/TGA.txt
void write_tga(const char *filename)
{
    ofstream outfile(filename, ofstream::binary);

    uint8_t header[18] = {
        0, // no image ID
        0, // no colour map
        2, // uncompressed 24-bit image
        0, 0, 0, 0, 0, // empty colour map specification
        0, 0, // X origin
        0, 0, // Y origin
        WIDTH & 0xFF, (WIDTH >> 8) & 0xFF, // width
        HEIGHT & 0xFF, (HEIGHT >> 8) & 0xFF, // height
        24, // bits per pixel
        0, // image descriptor
    };
    outfile.write((const char *)header, 18);

    for (int y = 0; y < HEIGHT; ++y)
    {
        for (int x = 0; x < WIDTH; ++x)
        {
            uint8_t pixel[3] = {
                image[y][x] & 0xFF, // blue channel
                (image[y][x] >> 8) & 0xFF, // green channel
                (image[y][x] >> 16) & 0xFF, // red channel
            };
            outfile.write((const char *)pixel, 3);
        }
    }

    outfile.close();
    if (!outfile)
    {
        // An error has occurred at some point since we opened the file.
        cout << "Error writing to " << filename << endl;
        exit(1);
    }
}


// Render the Mandelbrot set into the image array.
// The parameters specify the region on the complex plane to plot.
void compute_mandelbrot(double left, double right, double top, double bottom)
{
    for (int y = 0; y < HEIGHT; ++y)
    {
        for (int x = 0; x < WIDTH; ++x)
        {
            // Work out the point in the complex plane that
            // corresponds to this pixel in the output image.
            complex<double> c(left + (x * (right - left) / WIDTH),
                top + (y * (bottom - top) / HEIGHT));

            // Start off z at (0, 0).
            complex<double> z(0.0, 0.0);

            // Iterate z = z^2 + c until z moves more than 2 units
            // away from (0, 0), or we've iterated too many times.
            int iterations = 0;
            while (abs(z) < 2.0 && iterations < MAX_ITERATIONS)
            {
                z = (z * z) + c;

                ++iterations;
            }

            /*if (iterations == MAX_ITERATIONS)
            {
                // z didn't escape from the circle.
                // This point is in the Mandelbrot set.
                image[y][x] = 0x58DC77; // green
            }*/
            if (iterations <= 10)
            {
                // z didn't escape from the circle.
                // This point is in the Mandelbrot set.
                image[y][x] = 0xA9C3F6; // light blue
            }
            else if (iterations <=100)
            {

                // This point is in the Mandelbrot set.
                image[y][x] = 0x36924B; // darkest green
            }
            else if (iterations <= 200)
            {

                // This point is in the Mandelbrot set.
                image[y][x] = 0x5FB072; // lighter green
            }
            else if (iterations <= 300)
            {
                // z didn't escape from the circle.
                // This point is in the Mandelbrot set.
                image[y][x] = 0x7CD891; // mint green
            }
            else if (iterations <= 450)
            {
                // z didn't escape from the circle.
                // This point is in the Mandelbrot set.
                image[y][x] = 0x57F97D; // green
            }
            else
            {
                // z escaped within less than MAX_ITERATIONS
                // iterations. This point isn't in the set.
                image[y][x] = 0x58DC77; // light green
            }
        }
    }
}


int main(int argc, char *argv[])
{
    cout << "Processing" << endl;

    // Start timing
    the_clock::time_point start = the_clock::now();

    // This shows the whole set.
    compute_mandelbrot(-2.0, 1.0, 1.125, -1.125);

    // This zooms in on an interesting bit of detail.
    //compute_mandelbrot(-0.751085, -0.734975, 0.118378, 0.134488);

    // Stop timing
    the_clock::time_point end = the_clock::now();

    // Compute the difference between the two times in milliseconds
    auto time_taken = duration_cast<milliseconds>(end - start).count();
    cout << "Computing the Mandelbrot set took " << time_taken << " ms." << endl;


    write_tga("output.tga");

    return 0;
}

1 个答案:

答案 0 :(得分:0)

假设你想使用N个并行线程进行渲染,那么每个线程都将处理HEIGHT / N行。

为了简单起见,我选择一个N,将HEIGHT均分,如5。这意味着每个线程每个将处理20行(HEIGHT等于100)。

你可以这样实现:

constexpr int THREADS = 5;  // Our "N", divides HEIGHT evenly

void compute_mandelbrot_piece(double left, double right, double top, double bottom, unsigned y_from, unsigned y_to)
{
    for (unsigned y = y_from; y < y_to; ++y)
    {
        for (unsigned x = 0; y < WIDTH; ++x)
        {
            // Existing code to calculate value for y,x
            // ...
        }
    }
}

void compute_mandelbrot(double left, double right, double top, double bottom)
{
    std::vector<std::thread> render_threads;
    render_threads.reserve(THREADS);  // Allocate memory for all threads, keep the size zero

    // Create threads, each handling part of the image
    for (unsigned y = 0; y < HEIGHT; y += HEIGHT / THREADS)
    {
        render_threads.emplace_back(&compute_mandelbrot_piece, left, right, top, bottom, y, y + HEIGHT / THREADS);
    }

    // Wait for the threads to finish, and join them
    for (auto& thread : render_threads)
    {
        thread.join();
    }

    // Now all threads are done, and the image should be fully rendered and ready to save
}
相关问题