我们有一个图形密集型应用程序,它似乎在 AMD 64 位双核平台上遇到问题,而在 Intel 平台上并不明显。
运行应用程序会导致 CPU 以 100% 运行,尤其是在使用阴影和照明代码 (Open GL) 时。
有谁知道 AMD 处理器的具体问题可能导致此问题,或者知道在哪里追查问题,和/或优化代码库以避免这些问题的方法?
请注意,该应用程序通常在中档硬件上运行良好,我的开发机器有一个 nvidia gtx260 卡,所以电源不足应该不是问题
我们有一个图形密集型应用程序,它似乎在 AMD 64 位双核平台上遇到问题,而在 Intel 平台上并不明显。
运行应用程序会导致 CPU 以 100% 运行,尤其是在使用阴影和照明代码 (Open GL) 时。
有谁知道 AMD 处理器的具体问题可能导致此问题,或者知道在哪里追查问题,和/或优化代码库以避免这些问题的方法?
请注意,该应用程序通常在中档硬件上运行良好,我的开发机器有一个 nvidia gtx260 卡,所以电源不足应该不是问题
请注意,AMD64 是一种NUMA架构 - 如果您使用的是多处理器盒,您可能会在超传输总线上运行大量内存访问,这将比本地内存慢,并且可以解释这种行为。
单个插槽上的内核之间不会出现这种情况,因此如果您不使用多插槽机器,请随意忽略这一点。
Linux 是 NUMA 感知的(即它具有系统服务来通过本地银行分配内存并将进程绑定到特定的 CPU)。我相信 Win 2k3 服务器、2k8 和 Vista 支持 NUMA,但 XP 不支持。大多数专有的 unix 变体(例如 Solaris)也支持 NUMA。
这里迟到的答案。
不知道这是否相关,但在某些 win32 OpenGL 驱动程序中,SwapBuffers() 在等待 vsync 时不会产生 CPU,因此很容易获得 100% 的 CPU 利用率。
我使用的解决方案是测量自上次 SwapBuffers() 完成以来的时间,它告诉我下一个 vsync 有多远。所以在调用 SwapBuffers() 之前,我会使用很短的 Sleep(),直到我检测到 vsync 迫在眉睫。这种方式 SwapBuffers() 不必等待很长时间来等待 vsync,因此不会太严重地占用 CPU。
请注意,您可能必须使用 timeBeginPeriod() 来获得足够的 Sleep() 精度才能使其可靠地工作。
根据您如何完成阴影和其他图形代码,您可能“掉进了快速路径”并且图形驱动程序已经开始进行软件仿真。如果您有复杂的管道,或者在着色器代码中使用太多条件(或太多指令),则可能会发生这种情况。
我会确保这个特定的显卡支持您正在使用的所有功能。
此外,缓存不共享,这可能会导致在多个线程之间共享数据时性能不足。
我会投资分析软件来追踪问题的实际原因。
在 linux 上,Valgrind(包含 Cachegrind 和 Callgrind)+ KCacheGrind 可以确定所有繁重的函数调用在哪里进行。
此外,使用完整的调试符号进行编译,它甚至可以在慢速函数调用时显示汇编代码。
如果您使用的是英特尔专用编译器,这可能是您的问题的一部分(未定义),请尝试 GCC 系列。
此外,如果您还没有深入了解 OpenMP 和 Threads,您可能还想深入了解。
嗯 - 如果您使用阴影,GPU 应该处于负载状态,因此 GPU 渲染帧的速度不太可能比 CPU 发送图形数据的速度快。在这种情况下,100% 的负载是可以的,甚至可以预期。
它可能只是一个无聊的 OpenGL 驱动程序,它会在某个地方的自旋锁中消耗 CPU 周期。要了解到底发生了什么,我建议您运行分析工具,例如 AMD 的 Code Analyst(上次我使用它时免费)。
用几分钟分析你的程序,看看时间花在了哪里。如果您在 opengl 驱动程序中看到一个高峰,而不是在您的应用程序中看到一个新的驱动程序。否则,您至少会知道发生了什么。
顺便说一句 - 让我猜猜,你使用的是 ATI 卡,对吧?我不想冒犯任何 ATI 粉丝,但他们的 OpenGL 驱动器并不是很出色。如果您不走运,您甚至可能使用了该卡不支持或由于硅错误而被禁用的功能。在这种情况下,驱动程序将退回到软件光栅化模式。即使您的程序是单线程的,这也会大大减慢速度并为您提供 100% 的 CPU 负载。