C++ Mandelbrot切片图像以提高速度
Mandelbrot集合当前通过从主菜单调用函数来显示一整组图像C++ Mandelbrot切片图像以提高速度,c++,C++,Mandelbrot集合当前通过从主菜单调用函数来显示一整组图像 // 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 WI
// 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;
}
使用std::chrono::duration\u cast;
使用std::chrono::毫秒;
使用std::complex;
使用std::cout;
使用std::endl;
使用std::of流;
//为我们将要使用的时钟类型定义别名“the_clock”。
typedef std::chrono::稳定时钟时钟时钟;
//要生成的图像的大小。
常数int宽度=100;
const int HEIGHT=100;
//在我们假设某个点不在
//曼德布罗特集。
const int MAX_迭代次数=500;
//图像数据。
//每个像素表示为0xRRGGBB。
uint32_t图像[高度][宽度];
//用给定的名称将图像写入TGA文件。
//格式规范:http://www.gamers.org/dEngine/quake3/TGA.txt
无效写入(常量字符*文件名)
{
ofstream outfile(文件名,ofstream::binary);
uint8_t头[18]={
0,//没有图像ID
0,//没有颜色映射
2,//未压缩的24位图像
0,0,0,0,0,//空颜色映射规范
0,0,//X原点
0,0,//Y原点
宽度&0xFF,(宽度>>8)&0xFF,//宽度
高度&0xFF,(高度>>8)&0xFF,//高度
24,//位/像素
0,//图像描述符
};
outfile.write((const char*)头,18);
对于(int y=0;y>8)&0xFF,//绿色通道
(图像[y][x]>>16)和0xFF,//红色通道
};
写入((常量字符*)像素,3);
}
}
outfile.close();
如果(!outfile)
{
//自从我们打开文件后,在某个点上发生了错误。
cout假设您希望使用N个并行线程进行渲染,那么每个线程将处理高度/N
行
为了简单起见,我选择了一个N,它将高度均匀地划分,比如5
。这意味着每个线程将处理20行(其中高度等于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
}
constexpr int THREADS=5;//我们的“N”平均地划分高度
无效计算mandelbrot_块(左双、右双、上双、下双、无符号y_-from、无符号y_-to)
{
for(无符号y=y_from;y
请花些时间阅读,特别是名为和的部分。还有请和。至于你的问题,你对线程了解多少?这似乎是一项工作,如果你愿意,你可以为图像的每一行设置一个async
,或者将其拆分为每个async
的X行。线程初学者如此了解edge在它们上非常基础。我如何使异步覆盖图像的每一行?我刚刚阅读了专门用于它的页面。30秒?!该程序在我的(2.7 GHz)上大约需要290毫秒机器,没有优化。你的设置一定有点奇怪。听起来你更想重新考虑你的算法。如果它需要30秒串行,你对四个内核的最好期望是7.5秒,我想这还是太慢了。(我对计算Mandelbrot集不太了解,但可以在互联网上查找关于该集的启发。)