OpenCL mandlebrot 图,在 GPU 上非常嘈杂
OpenCL mandlebrot plot, very noisy on GPU
为了尝试学习 OpenCL,我决定绘制 Mandlebrot 集的图。
它似乎在 CPU 上工作正常。下面的两张图片显示,第一个是在 CPU(Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz)上执行的内核,第二张图片显示的是在GPU(高清显卡 4000)。
这是内核:
typedef float2 Complex;
Complex complex_mul(Complex a, Complex b)
{
return (Complex)(a.s0*b.s0-a.s1*b.s1, a.s1*b.s0+a.s0*b.s1);
}
__kernel
void mandelbrot (__global float* p)
{
const int x = get_global_id (0);
const int y = get_global_id (1);
const int arrlen = PIXELS_WIDTH * PIXELS_HEIGHT;
float width = PIXELS_WIDTH;
float height = PIXELS_HEIGHT;
float whRatio = width / height;
float tx = x;
float ty = y;
float px = ((tx / float(PIXELS_WIDTH)) - 0.5) * 2.0;
float py = ((ty / float(PIXELS_HEIGHT)) - 0.5) * 2.0 / whRatio;
Complex z;
z.s0 = 0;
z.s1 = 0;
Complex c;
c.s0 = px;
c.s1 = py;
float color = 0.0;
int iterations = 500;
for (int i = 0; i < iterations; i++)
{
z = complex_mul(z,z) + c;
if ( length(z) > 2.0)
{
float u,o;
u = i;
o = iterations;
color = ( u / o );
break;
}
}
const int pId = y * PIXELS_WIDTH + x;
if ( pId < arrlen )
{
p[ pId ] = color;
}
}
和主机程序...至少有趣的一点(我希望):
size_t globalSizes[2] = { PIXEL_WIDTH, PIXEL_HEIGHT };
cl_mem image_buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY, sizeof(image_data), NULL, &error);
CheckError(error);
error = clSetKernelArg(kernel, 0, sizeof(cl_mem), &image_buffer);
CheckError(error);
error = clEnqueueNDRangeKernel(queue, kernel, 2, NULL, globalSizes, NULL, 0, NULL, &computeDone);
CheckError(error);
clWaitForEvents(1, &computeDone);
error = clEnqueueReadBuffer(queue, image_buffer, CL_TRUE, 0, sizeof(image_data), image_data, 0, NULL, NULL);
CheckError(error);
clReleaseMemObject(image_buffer);
我 运行 在配备 OS X 10.9.5 的 MacBook Pro 上使用此功能。每次执行时,集合周围的噪声部分会略有(随机)变化。
我希望我已经提供了足够的信息,如果有人对可能存在的问题提出建议,我将很高兴听到!
谢谢:)
编辑
我做了以下事情:
按照 huseyin tugrul buyukisik 在评论中的建议,将所有数字文字更改为浮点数。
然后将length(z) > 2.0
改为(z.s0 * z.s0) + (z.s1 * z.s1) > 4.0f
然后尝试使用迭代计数器。
看来噪声对迭代次数很敏感。
例如,1000 次迭代会产生很多噪声,但 1009 次迭代会产生非常平滑的图像。关于为什么会发生这种情况有什么建议吗?
干杯
有时驱动程序在驱动程序端的矢量实现上存在错误。如果 fp64 支持或主机端元素对齐检查不起作用,则尝试 "scalar" 版本可以简单地解决它。
例如,我的 fx-8150 cpu 在 float8 和 float16 方面有问题,但 gpus 在任何原生矢量上都没有问题,在遥远的过去 fx-8150 也没有问题。也许我们被迫(无意或有意)购买新技术。
您应该尝试不同版本的驱动程序,因为有时公司会故意或无意地调整设置并破坏支持列表。
也许我错了,你的集成 GPU 快没电了。
代码在 GPU 上的 Windows 8.1 上使用适用于您的处理器类型的最新驱动程序,稍作修改(例如 (float)(PIXEL_WIDTH) 和 0.5f 等)即可正常运行,所以这表明 Mac.
上存在图形驱动程序问题
为了尝试学习 OpenCL,我决定绘制 Mandlebrot 集的图。 它似乎在 CPU 上工作正常。下面的两张图片显示,第一个是在 CPU(Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz)上执行的内核,第二张图片显示的是在GPU(高清显卡 4000)。
这是内核:
typedef float2 Complex;
Complex complex_mul(Complex a, Complex b)
{
return (Complex)(a.s0*b.s0-a.s1*b.s1, a.s1*b.s0+a.s0*b.s1);
}
__kernel
void mandelbrot (__global float* p)
{
const int x = get_global_id (0);
const int y = get_global_id (1);
const int arrlen = PIXELS_WIDTH * PIXELS_HEIGHT;
float width = PIXELS_WIDTH;
float height = PIXELS_HEIGHT;
float whRatio = width / height;
float tx = x;
float ty = y;
float px = ((tx / float(PIXELS_WIDTH)) - 0.5) * 2.0;
float py = ((ty / float(PIXELS_HEIGHT)) - 0.5) * 2.0 / whRatio;
Complex z;
z.s0 = 0;
z.s1 = 0;
Complex c;
c.s0 = px;
c.s1 = py;
float color = 0.0;
int iterations = 500;
for (int i = 0; i < iterations; i++)
{
z = complex_mul(z,z) + c;
if ( length(z) > 2.0)
{
float u,o;
u = i;
o = iterations;
color = ( u / o );
break;
}
}
const int pId = y * PIXELS_WIDTH + x;
if ( pId < arrlen )
{
p[ pId ] = color;
}
}
和主机程序...至少有趣的一点(我希望):
size_t globalSizes[2] = { PIXEL_WIDTH, PIXEL_HEIGHT };
cl_mem image_buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY, sizeof(image_data), NULL, &error);
CheckError(error);
error = clSetKernelArg(kernel, 0, sizeof(cl_mem), &image_buffer);
CheckError(error);
error = clEnqueueNDRangeKernel(queue, kernel, 2, NULL, globalSizes, NULL, 0, NULL, &computeDone);
CheckError(error);
clWaitForEvents(1, &computeDone);
error = clEnqueueReadBuffer(queue, image_buffer, CL_TRUE, 0, sizeof(image_data), image_data, 0, NULL, NULL);
CheckError(error);
clReleaseMemObject(image_buffer);
我 运行 在配备 OS X 10.9.5 的 MacBook Pro 上使用此功能。每次执行时,集合周围的噪声部分会略有(随机)变化。
我希望我已经提供了足够的信息,如果有人对可能存在的问题提出建议,我将很高兴听到!
谢谢:)
编辑
我做了以下事情:
按照 huseyin tugrul buyukisik 在评论中的建议,将所有数字文字更改为浮点数。
然后将length(z) > 2.0
改为(z.s0 * z.s0) + (z.s1 * z.s1) > 4.0f
然后尝试使用迭代计数器。
看来噪声对迭代次数很敏感。
例如,1000 次迭代会产生很多噪声,但 1009 次迭代会产生非常平滑的图像。关于为什么会发生这种情况有什么建议吗?
干杯
有时驱动程序在驱动程序端的矢量实现上存在错误。如果 fp64 支持或主机端元素对齐检查不起作用,则尝试 "scalar" 版本可以简单地解决它。
例如,我的 fx-8150 cpu 在 float8 和 float16 方面有问题,但 gpus 在任何原生矢量上都没有问题,在遥远的过去 fx-8150 也没有问题。也许我们被迫(无意或有意)购买新技术。
您应该尝试不同版本的驱动程序,因为有时公司会故意或无意地调整设置并破坏支持列表。
也许我错了,你的集成 GPU 快没电了。
代码在 GPU 上的 Windows 8.1 上使用适用于您的处理器类型的最新驱动程序,稍作修改(例如 (float)(PIXEL_WIDTH) 和 0.5f 等)即可正常运行,所以这表明 Mac.
上存在图形驱动程序问题