Реализация фрактала Множество Мандельброта
В данном примере будет продемонстрировано построение множества Мандельброта на CUDA C с использованием OpenCV (Open Source Computer Vision Library), которая из себя представляет библиотеку алгоритмов компьютерного зрения. В программе будут применяться следующие модули:
opencv_core — основная функциональность. Включает в себя базовые структуры, вычисления (математические функции, генераторы случайных чисел) и линейную алгебру, DFT, DCT, ввод/вывод для XML и YAML и т. д.;
opencv_highgui — ввод/вывод изображений и видео.
Подробнее об opencv читайте тут.
Код построения множества Мандельброта:
#include "cuda_runtime.h" #include "device_launch_parameters.h" #include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> using namespace cv; using namespace std; #define HEIGHT 512 // must be multiple of block_size.y #define WIDTH 512 // must be multiple of block_size.x #define MAX_ITER 10000 void mandelbrotGPU(char*); __global__ void calc(char* image_buffer); #define cudaAssertSuccess(ans) { _cudaAssertSuccess((ans), __FILE__, __LINE__); } inline void _cudaAssertSuccess(cudaError_t code, char *file, int line) { if (code != cudaSuccess) { fprintf(stderr,"_cudaAssertSuccess: %s %s %d\n", cudaGetErrorString(code), file, line); exit(code); } } int main(int argc, char** argv) { IplImage* image_output = cvCreateImage(cvSize(WIDTH, HEIGHT), IPL_DEPTH_8U, 1); mandelbrotGPU(image_output->imageData); cvShowImage("GPU", image_output); waitKey(0); cvReleaseImage(&image_output); } void mandelbrotGPU(char* image_buffer) { char* d_image_buffer; cudaAssertSuccess(cudaMalloc(&d_image_buffer, WIDTH * HEIGHT)); dim3 block_size(16, 16); dim3 grid_size(WIDTH / block_size.x, HEIGHT / block_size.y); calc<<<grid_size, block_size>>>(d_image_buffer); cudaAssertSuccess(cudaPeekAtLastError()); cudaAssertSuccess(cudaDeviceSynchronize()); cudaAssertSuccess(cudaMemcpy(image_buffer, d_image_buffer, HEIGHT * WIDTH, cudaMemcpyDeviceToHost)); cudaAssertSuccess(cudaFree(d_image_buffer)); } __global__ void calc(char* image_buffer) { int row = blockIdx.y * blockDim.y + threadIdx.y; // WIDTH int col = blockIdx.x * blockDim.x + threadIdx.x; // HEIGHT int idx = row * WIDTH + col; if(col >= WIDTH || row >= HEIGHT) return; float x0 = ((float)col / WIDTH) * 3.5f - 2.5f; float y0 = ((float)row / HEIGHT) * 3.5f - 1.75f; float x = 0.0f; float y = 0.0f; int iter = 0; float xtemp; while((x * x + y * y <= 4.0f) && (iter < MAX_ITER)) { xtemp = x * x - y * y + x0; y = 2.0f * x * y + y0; x = xtemp; iter++; } int color = iter * 5; if (color >= 256) color = 0; image_buffer[idx] = color; }
Результат выполнения программы: