5

我正在多 GPU 设置(Mac Pro 2013 年末)中开发 OS X 应用程序,该应用程序使用 OpenCL(在辅助 GPU 上)生成纹理,该纹理随后使用 OpenGL(在主 GPU 上)绘制到屏幕上. 由于调用 glBindTexture() 和 glBegin(),该应用程序受 CPU 限制,这两者基本上都将所有时间都花在:

_platform_memmove$VARIANT$Ivybridge

这是视频驱动程序的一部分:

AMDRadeonX4000GLDriver

设置:创建 OpenGL 纹理 ( glPixelBuffer ),然后创建对应的 OpenCL ( clPixelBuffer )。

cl_int clerror = 0;
GLuint glPixelBuffer = 0;
cl_mem clPixelBuffer = 0;

glGenTextures(1, &glPixelBuffer);
glBindTexture(GL_TEXTURE_2D, glPixelBuffer);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2048, 2048, 0, GL_RGBA, GL_FLOAT, NULL);
glBindTexture(GL_TEXTURE_2D, 0);

clPixelBuffer = clCreateFromGLTexture(_clShareGroupContext, CL_MEM_WRITE_ONLY, GL_TEXTURE_2D, 0, glPixelBuffer, &clerror);

绘制代码:将 OpenGL 纹理映射到视口上。整个 NSOpenGLView 就是这一个纹理。

glClear(GL_COLOR_BUFFER_BIT);

glBindTexture(GL_TEXTURE_2D, _glPixelBuffer);  // <- spends cpu time here,
glBegin(GL_QUADS);                             // <- and here
glTexCoord2f(0., 0.); glVertex3f(-1.f,  1.f, 0.f);
glTexCoord2f(0., hr); glVertex3f(-1.f, -1.f, 0.f);
glTexCoord2f(wr, hr); glVertex3f( 1.f, -1.f, 0.f);
glTexCoord2f(wr, 0.); glVertex3f( 1.f,  1.f, 0.f);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);

glFlush();

在获得纹理内存的控制权(通过clEnqueueAcquireGLObjects())后,OpenCL 内核将数据写入纹理,然后释放对纹理的控制权(通过clEnqueueReleaseGLObjects())。纹理数据不应该存在于主内存中(如果我理解正确的话)。

我的问题是:预计会在 memmove() 中花费这么多 CPU 时间吗?这是否表明我的代码存在问题?或者驱动程序中的错误,也许?我的(毫无根据的)怀疑是纹理数据正在通过:GPUx -> CPU/RAM -> GPUy 移动,我想避免这种情况。

4

1 回答 1

2

在我谈到内存转移之前,我的第一个观察是你正在使用 clBegin() 这不会是你最好的朋友,因为

1)这种直接绘图与驱动程序不兼容。请改用 VBO 等,以便这些数据可以存在于 GPU 上。

2) 在 OS X 上,这意味着您处于旧的兼容性环境中,而不是新的核心环境中。正如(我理解)新的上下文是完全重写的,这是未来优化将结束的地方,而您正在使用的上下文(可能)只是被维护。

那么对于内存传输....在GL方面,您是否将glCreateSyncFromCLeventARB()和glWaitSync()放在上面?我在您的代码中看到的 glFlush() 应该不需要。一旦您摆脱了立即模式绘图(如上所述)并在两个 API 之间使用同步对象,您的主机代码应该什么都不做(除了要求驱动程序告诉 GPU 做事)。这将为您提供获得快速缓冲区副本的最佳机会....

是的,副本:(因为您的 CL 纹理物理上与 GL 纹理位于不同的 GPU 内存上,所以必须通过 PCIe 总线进行复制,这会很慢(呃)。这就是您在分析中看到的.实际发生的是CPU正在将GPU内存A和GPU内存B映射到固定的主机内存中,然后使用DMA在它们之间进行复制(希望如此)。我怀疑数据实际上会触及系统内存,所以移动是GPUx-> GPUy。

试着把你的 CL 和 GL 上下文放在同一个 GPU 上,我想你会看到你的传输时间消失了。

最后的想法:如果您的 CL 计算与传输时间相比相形见绌,那么最好将上下文粘贴在同一个 CPU 上。您遇到了经典的 CPU/GPU 任务拆分问题。

于 2014-10-24T13:42:31.590 回答