0

*这是我已经问过的一个更具体、形式更好的问题。我删除了另一个。

所以我正在尝试从 CUDA 库中收集内核时序数据......

该库为其每种算法都有不同类型的基准,它们的工作方式如下:

有一个二维数组,它具有成对的数组大小和测试迭代。例子:

const int Tests[][2] = {
    { 10000, 10000 },
    { 50000, 5000 },
    { 100000, 5000 },
    { 200000, 2000 }
    // ...
};

然后在 main 中会有一个循环

// get context ptr
for(int test = 0; test < numTests; ++test)
    BenchmarkMyAlg(Tests[test][0], Tests[test][1], *context);

BenchmarkMyAlg 设置数据和所有内容,然后循环运行内核(Tests[test][1] 次)

我想要做的是获取每个测试参数对的“CUDA Launch Summary”数据,特别是“以微秒为单位执行设备功能的平均持续时间”。即对于main中该循环的每次迭代。

就像现在一样,我只能获得整个主循环的平均时间。换句话说,我只能在应用程序执行后获得 1 行 NSight 数据,并且我想要 numTests 行数据。

如果在 main 中测试了第二个不同的算法,NSight 将生成另一行数据。例如..

for(int test = 0; test < numTests; ++test)
    BenchmarkMyAlg(Tests[test][0], Tests[test][1], *context);

for(int test = 0; test < numTests; ++test)
    BenchmarkMyOtherAlg(Tests[test][0], Tests[test][1], *context);

但同样,新的数据行指的是整个循环,当我想要 2 * numTests 行数据时给我 2 行数据。

我已经尝试在 NSight 中挖掘设置,并且还对 nvprof 进行了一些修改,但我没有取得任何进展。

我在想有一种方法可以重新编码文件,以便 NSight 将每个测试迭代识别为新的/不同的内核,就像它在实际切换到不同的内核时所做的那样(就像在我的第二个示例中一样)。也许初始化 numTests 单独引用 BenchmarkMyAlg 函数,然后运行这些?我现在就去尝试一下,如果我有任何地方,我会回来评论。

4

1 回答 1

0

使用 nvprof,您应该能够获得组合结果(最小值、最大值、平均值)或每个单独调用的跟踪(使用 --print-gpu-trace)。你想要的是介于两者之间的东西,你想要对时间进行分组。该工具无法单独执行此操作,因为您的内核只有一个名称,因此它无法区分组(它需要为此检查参数,这将是一个很大的开销)。

获得所需内容的一种方法是对完整的 GPU 跟踪进行后处理以手动对各个调用进行分组 - 跟踪是按时间顺序排列的,因此应该很简单。

另一种方法是模板化您的内核,例如使用测试编号。即使您实际上并未在内核中使用模板参数,它也会强制每个测试具有不同的内核名称,这使得 nvprof(和 nsight)中的默认聚合可以满足您的需求。

于 2013-08-09T10:49:34.863 回答