DirectX11与OpenGL Compute Shader执行耗时差异原因咨询
问题分析与解决方案
1. 最核心错误:计时逻辑完全不符合GPU异步执行的特性
所有图形API的计算调度接口都是异步调用:DispatchCompute执行完成返回时,仅代表命令已经提交到驱动的命令队列,GPU甚至还没开始执行对应的计算任务。你用CPU端的std::chrono统计调用前后的时间差,实际测的是API命令提交开销、驱动内部处理开销,和Compute Shader在GPU上的真实执行时间没有任何关系。
你观测到的OpenGL比DirectX快10倍,本质是两个驱动的命令提交逻辑差异,和CS代码、缓冲区配置无关;而DirectX CS比CPU慢也是因为极小负载下,API提交的固定开销已经远大于32个向量加法的CPU执行耗时。
2. 测试负载过小,无参考价值
本次测试仅调度了32个线程做简单的向量加法,属于极小规模计算,GPU的并行优势完全无法发挥,所有开销基本都集中在API、驱动的固定流程上,这种场景下的性能对比没有实际工程参考意义。如果要验证CS的执行效率,建议把计算规模放大到至少百万级线程,让GPU的实际计算时间占总耗时的绝大多数,才能得到有效的对比结果。
3. 正确的GPU计时方式
要拿到准确的Compute Shader执行耗时,必须使用GPU端的时间戳查询接口:
- Direct3D 11 请使用
D3D11_QUERY_TIMESTAMP类型的查询对象,在Dispatch前后分别插入时间戳,等GPU执行完成后再读取两个时间戳的差值。 - OpenGL 请使用
GL_TIMESTAMP类型的查询对象,逻辑和DX基本一致。
其他可能的影响点
- 内存对齐校验:请确认C++端的
Data结构体、GLSL std430布局的结构体、HLSL结构体三者的内存布局完全对齐,虽然对齐错误不会直接拖慢执行速度,但如果触发驱动隐式的格式转换,也可能带来额外开销。 - DirectX输入缓冲区配置:你仅贴了UAV的创建代码,未提供输入StructuredBuffer的创建逻辑,请确认输入缓冲区的
Usage使用的是D3D11_USAGE_DEFAULT或者D3D11_USAGE_IMMUTABLE,不要使用D3D11_USAGE_STAGING或者开启不必要的CPU访问权限,否则会拖慢数据上传效率。 - 命令队列刷新逻辑:如果你的DirectX代码在Dispatch后没有主动flush命令队列,驱动可能会缓存命令延后提交,也会干扰你当前错误的CPU计时结果。
内容的提问来源于stack exchange,提问作者Boseong Jeong
相关产品推荐
相关产品推荐

