我刚写完一个 cuda 程序,它可以渲染 Mandelbrot 集的图像。我设置它的方式是,您将创建图像的函数传递给一个比例,该比例是每单位像素以及复平面中图像中心的 x 和 y 坐标。我想从许多帧创建一个深度缩放电影,我需要我的程序能够自动确定一个中心,在那里将发生“有趣”的事情(而不是放大一个区域,它只会是一种颜色)。我应该如何选择要放大的坐标。
如果有人感兴趣,这是我的代码。
#include <iostream>
#include <thrust/complex.h>
#include <cuda.h>
#include <cassert>
#include <cstdio>
#include <algorithm>
typedef double real;
inline void cuda_error(cudaError_t code, const char* lbl)
{
if(code != cudaSuccess)
{
std::cerr << lbl << " : " << cudaGetErrorString(code) << std::endl;
exit(1);
}
}
__global__ void mandelbrot_kernel(unsigned char* pix, real cx, real cy, real pix_scale, size_t w, size_t h, int iters)
{
cy = -cy;
real sx = cx - (w * pix_scale) / 2;
real sy = cy - (w * pix_scale) / 2;
size_t x = (size_t)blockIdx.x * blockDim.x + threadIdx.x;
size_t y = (size_t)blockIdx.y * blockDim.y + threadIdx.y;
if(x >= w || y >= h)
return;
thrust::complex<real> c(sx + pix_scale * x, sy + pix_scale * y);
thrust::complex<real> z(0, 0);
int i = 0;
for(; i < iters && thrust::abs(z) < 2; ++i)
z = z * z + c;
real scale = 255.0 / (real)iters;
size_t q = 3 * (w * y + x);
pix[q] = i * scale;
pix[q + 1] = 255 * sinf(z.imag());
pix[q + 2] = 255 * sinf(z.real());
}
void shade_mandelbrot(unsigned char* pix, real* devs, real cx, real cy, real pix_scale, int w, int h, int iters)
{
dim3 blockDim(16, 16);
dim3 gridDim((w + 15) / 16, (h + 15) / 16);
mandelbrot_kernel<<<gridDim, blockDim>>>(pix, cx, cy, pix_scale, w, h, iters);
}
void ppm_write(FILE* f, unsigned char* pix, int w, int h)
{
assert(fprintf(f, "P6 %d %d 255\n", w, h) > 0);
size_t sz = 3 * (size_t)w * (size_t)h;
assert(fwrite(pix, 1, sz, f) == sz);
}
int main()
{
int dim = 2000;
int w = dim;
int h = dim;
int imgs = 200;
int iters = 1024;
real cx = -0.7463, cy = 0.1102;
cuda_error(cudaSetDevice(0), "Set Device");
unsigned char* pix_buffers[2];
real* dev_buffers[2];
cuda_error(cudaHostAlloc(pix_buffers, 3 * sizeof(unsigned char) * w * h, 0), "Host Alloc 1");
cuda_error(cudaHostAlloc(pix_buffers + 1, 3 * sizeof(unsigned char) * w * h, 0), "Host Alloc 2");
real scale = 8.0 / w;
shade_mandelbrot(pix_buffers[0], dev_buffers[0], cx, cy, scale, w, h, iters);
for(int i = 0; i < imgs; i++)
{
cuda_error(cudaDeviceSynchronize(), "Sync");
std::cout << scale << std::endl;
if(i < (imgs - 1))
shade_mandelbrot(pix_buffers[(i + 1) % 2], dev_buffers[(i + 1) % 2], cx, cy, scale *= 0.97, w, h, 255);
char fn[100];
sprintf(fn, "/media/chase/3161D67803D8C5BE/Mandelbroght/image%06d.ppm", i);
puts(fn);
FILE* f = fopen(fn, "w");
assert(f);
ppm_write(f, pix_buffers[i % 2], w, h);
fclose(f);
}
cuda_error(cudaFreeHost(pix_buffers[0]), "Host Free 1");
cuda_error(cudaFreeHost(pix_buffers[1]), "Host Free 2");
return 0;
}
最佳答案
退出内循环时具有高迭代次数(但不等于iters
)的点将呈现有趣的行为,因为它们接近设定的边界。您可以随机选择点,通过算法运行它并使用计数最高的点作为中心。如果你随机选择几个点,你可能会更快地得到结果,取迭代次数最高的点,在它周围生成几个点,看看你是否得到更高的迭代次数,然后用这些点中最好的点重复。
关于c++ - 如何确定 Mandelbrot 集缩放的良好中心,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32027864/