如何使用Vulkan时间戳查询



这是我试图测量GPU工作负载的简化伪代码:

for(N) vkCmdDrawIndexed();
vkCmdWriteTimestamp(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
vkCmdWriteTimestamp(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
submit();
vkDeviceWaitIdle();
vkGetQueryPoolResults();

需要注意的事项:

  • N在我的情况下是224
  • 我必须等待一个空闲的设备——如果没有它,我会继续收到一个验证错误,说我的数据还没有准备好,尽管我有多个查询池在运行
  • 放入第一个时间戳,我希望在所有先前的命令到达预处理步骤后立即写入查询值。我很确定所有224个命令几乎同时被预处理,但现实表明这不是真的
  • 放入第二个时间戳,我预计查询值将在之前的所有命令完成后写入。也就是说,这两个查询值之间的时间差应该给我GPU为一帧完成所有工作所需的时间
  • 我正在考虑VkPhysicalDeviceLimits::timestampPeriod(我的机器上为1(和VkQueueFamilyProperties::timestampValidBits(我的计算机上为64(

我创建了一个大数据集,在视觉上渲染一帧大约需要2秒(约2000毫秒(。但计算出的时间只有两(两(个不同的值——0.001024ms或0.002048ms,因此逐帧输出可能如下所示:

0.001024ms
0.001024ms
0.002048ms
0.001024ms
0.002048ms
0.002048ms
...

不知道你怎么样,但我觉得这些价值观非常可疑。我对此没有答案。也许当时,最后一个绘制命令到达命令处理器,所有的工作都已经完成了,但为什么是1024和2048呢??

我试图修改代码并移动上面的第一个时间戳,即:

vkCmdWriteTimestamp(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
for(N) vkCmdDrawIndexed();

vkCmdWriteTimestamp(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);

现在,当预处理器点击timestamp命令时,它会立即写入查询值,因为之前没有任何工作,也没有什么可等待的(记住空闲设备(。这一次我有了另一个更接近真相的价值观:

20.9336ms
20.9736ms
21.036ms
21.0196ms
20.9572ms
21.3586ms
...

这是更好的,但仍远远超出预期约2000米。

当我设置时间戳时,设备内部发生了什么,如何获得正确的值?

虽然Vulkan中的命令可能会被无序执行(在某些限制范围内(,但您不应该广泛地期望命令被无序执行。计时器查询尤其如此,如果它们被无序执行,就其含义而言,将是不可靠的。

考虑到这一点,您的代码是这样说的:;做一堆工作。然后查询管道开始准备执行新命令所需的时间,然后查询到达管道结束所需时间"好吧,管道的起点可能只有在大部分工作完成后才能执行新命令。

基本上,你认为正在发生的是:

top        work work work work work work | timer
stage1                                    work work work work work work 
stage2                                        work work work work work work 
bottom                                            work work work work work work | timer

但是没有任何东西需要GPU以这种方式执行。几乎可以肯定的是,实际发生的是:

time->
top        work work work work work work | timer
stage1         work work work work work work 
stage2             work work work work work work 
bottom                 work work work work work work | timer

所以你的两个计时器只得到了实际工作的一小部分。

想要的是:

top        timer | work work work work work work
stage1                 work work work work work work 
stage2                     work work work work work work 
bottom                         work work work work work work | timer

这将查询整个工作集从开始到结束的时间。

因此,将第一个查询放在要测量其时间的工作之前。

最新更新