【问题标题】:How do the nodes in a CUDA graph connect?CUDA 图中的节点如何连接?
【发布时间】:2018-10-12 03:45:23
【问题描述】:

CUDA graphs 是一种从多个操作中综合复杂操作的新方法。使用“流捕获”,您似乎可以运行多种操作,包括 CuBlas 和类似的库操作,并将它们捕获为单个“元内核”。

我不清楚这些图表的数据流是如何工作的。在捕获阶段,我为输入分配内存 A,为临时值分配内存 B,为输出分配内存 C。但是当我在图表中捕获它时,我没有捕获内存分配。因此,当我随后实例化这些图的多个副本时,它们无法共享输入内存 A、临时工作空间 B 或输出内存 C。

那么这是如何工作的呢? IE。当我调用cudaGraphLaunch 时,我看不到提供输入参数的方法。我捕获的图表基本上以cudaMemcpyHostToDevice 开头,图表如何知道要复制哪个主机内存以及放在哪里?

背景:我发现 CUDA 在内核启动时存在严重瓶颈;移植到 CUDA 时,我的 AVX2 代码慢了 13 倍。内核本身看起来不错(根据 NSight),这只是调度数十万个内核启动的开销。

【问题讨论】:

    标签: c++ cuda


    【解决方案1】:

    内存分配通常在图形定义/实例化或“捕获”之外完成。

    但是,图表提供"memory copy" nodes,您通常会在其中执行cudaMemcpy 类型的操作。

    在图定义时,您为每个图节点传递一组参数(这将取决于节点类型,例如cudaMemcpy 操作的参数,如果它是内存复制节点,或者内核参数,如果它是一个内核节点)。这些参数决定了执行该图时将使用的实际内存分配。

    如果您想使用一组不同的分配,一种方法是为发生变化的节点实例化另一个具有不同参数的图。这可以通过重复整个过程来完成,或者从现有图开始,更改节点参数,然后使用这些更改实例化图。

    目前,在 cuda 图中,无法对特定图/节点执行节点参数的运行时绑定(即在图“启动”点)。当然,未来版本中可能会引入新功能。

    请注意,CUDA 10 中有一个名为 simpleCudaGraphs 的 CUDA 示例代码,它演示了内存复制节点和内核节点的使用,以及如何在节点之间创建依赖关系(有效地执行依赖关系)。

    【讨论】:

    • 有点令人失望 - 我不明白为什么你会为试图覆盖彼此结果的多个图表而烦恼。当其中一个节点是 cublas gemm 节点时,“对节点参数进行更改”看起来实际上并不可行;通用图形接口不知道特定内核的参数。
    • 如果很难捕获所有节点的参数 - 一种更简单的方法可能是允许基指针并从中捕获偏移量。这样,您可以分配多个竞技场并在每个竞技场上启动图表。
    • 在分析中,我现在看到我需要数十个 cudaGraph_t 对象(每个主机 CPU 内核一个)、数万个 cudaGraphExec_t(每个主机 CPU 线程一个)和一个复杂的缓存来避免丢弃图表。仅图形缓存争用就是性能瓶颈。也很糟糕:您需要捕获多个 cudaGraph_t 对象,每组内存缓冲区一个,但 cudaStreamBeginCapture 不是线程/流安全的。如果同时运行两个捕获,即使它们位于不同的线程和流上,也会出现奇怪的错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-11
    • 1970-01-01
    • 1970-01-01
    • 2012-04-24
    • 1970-01-01
    • 2020-03-25
    • 1970-01-01
    相关资源
    最近更新 更多