gpt4 book ai didi

CUDA 曼德布罗集

转载 作者:行者123 更新时间:2023-12-02 05:50:19 25 4
gpt4 key购买 nike

这是一个连续的 Mandelbrot Set 实现。

 void mandelbrot(PGMData *I)
{
float x0,y0,x,y,xtemp;
int i,j;
int color;
int iter;
int MAX_ITER=1000;
for(i=0; i<I->height; i++)
for(j=0; j<I->width; j++)
{
x0 = (float)j/I->width*(float)3.5-(float)2.5;
y0 = (float)i/I->height*(float)2.0-(float)1.0;
x = 0;
y = 0;
iter = 0;
while((x*x-y*y <= 4) && (iter < MAX_ITER))
{
xtemp = x*x-y*y+x0;
y = 2*x*y+y0;
x = xtemp;
iter++;
}
color = (int)(iter/(float)MAX_ITER*(float)I->max_gray);
I->image[i*I->width+j] = I->max_gray-color;
}
}

我想使用 CUDA 并行化它,但我似乎误解了一些东西,现在我被卡住了。我试过在互联网上搜索,但没有什么特别好的。

核心:
__global__ void calc(int *pos)
{
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 || idx > N) return;

float x0 = (float)row/WIDTH*(float)3.5-(float)2.5;
float y0 = (float)col/HEIGHT*(float)2.0-(float)1.0;

int x = 0, y = 0, iter = 0, xtemp = 0;
while((x*x-y*y <= 4) && (iter < MAX_ITER))
{
xtemp = x*x-y*y+x0;
y = 2*x*y+y0;
x = xtemp;
iter++;
}
int color = 255 - (int)(iter/(float)MAX_ITER*(float)255);
__syncthreads();
pos[idx] = color;//color;// - color;

}

内核是这样启动的:
dim3 block_size(16, 16);
dim3 grid_size((N)/block_size.x, (int) N / block_size.y);
calc<<<grid_size,block_size>>>(d_pgmData);

这是常量:
#define HEIGHT 512
#define WIDTH 512
#define N (HEIGHT*WIDTH)

整个GPU功能
void mandelbrotGPU(PGMData *I)
{
int *pos = (int *)malloc(HEIGHT*WIDTH*sizeof(int));
int *d_pgmData;

cudaMalloc((void **)&d_pgmData, sizeof(int)*WIDTH*HEIGHT);


cudaMemcpy(d_pgmData, pos ,HEIGHT*WIDTH*sizeof(int) ,cudaMemcpyHostToDevice);

dim3 block_size(16, 16);
dim3 grid_size((N)/block_size.x, (int) N / block_size.y);
calc<<<grid_size,block_size>>>(d_pgmData);

cudaMemcpy(pos,d_pgmData,HEIGHT*WIDTH*sizeof(int) ,cudaMemcpyDeviceToHost);
cudaFree(d_pgmData);
I->image = pos;
}

问题是:要么返回垃圾,要么驱动程序崩溃。我真的很感激一些建议,因为我真的被困住了。

最佳答案

这是您的代码的工作版本(使用 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;
}

输出:

Mandelbrot output

最重要的变化:
  • 已删除 __syncthreads(); .该算法不使用其他线程生成的数据,因此不需要同步线程。
  • 删除了将主机缓冲区复制到设备的操作。这是没有必要的,因为 Mandelbrot 算法会写入整个设备缓冲区。
  • 修复了不正确的网格大小计算。
  • 去掉了主机内存的malloc,因为结果直接复制到OpenCV图像缓冲区中。
  • 将缓冲区更改为使用字节而不是整数,这在具有 8 位分辨率的单个灰色 channel 时更方便。
  • 删除了一些不必要的 float Actor 。当您在计算中使用整数和浮点数时,整数会自动提升为浮点数。
  • 修复了 Mandelbrot 算法中的两个问题:
  • xy被声明为 int s 而它们应该是 float s。
  • while中的第一个表达式循环应该包含一个 + ,不是 - .
  • 关于CUDA 曼德布罗集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20205941/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com