0

我有兴趣了解几乎永远无法放入硬件加速器的工作负载百分比。虽然越来越多的任务适用于特定领域的加速器,但我想知道是否有可能拥有对加速器没有用的任务?简而言之,哪些任务不太可能与加速器兼容

希望有一个指向这个问题的资源的指针。

4

1 回答 1

1

因此,您在原始帖子中有以下问题:


问题

  • 我想知道是否有可能有对加速器没有用的任务?简而言之,哪些任务不太可能与加速器兼容?

答案

当然有可能。首先,需要在硬件加速器上加速的工作负载不应涉及以下内容:

  • 动态多态性和动态内存分配
  • 运行时类型信息 (RTTI)
  • 系统调用
  • ...... (更多取决于硬件加速器)

虽然解释上述每个点会使帖子太长,但我可以解释的很少。不支持动态内存分配,因为硬件加速器在硅片上有一组固定的资源,不支持动态创建和释放内存资源。同样,只有在编译时可以确定指针对象时才支持动态多态性。并且不应该有系统调用,因为这些是与在操作系统上执行某些任务相关的操作。因此不支持操作系统操作,例如文件读/写或操作系统查询,如时间和日期。

话虽如此,不太可能与加速器兼容的工作负载主要是 通信密集型内核。与 CPU 执行相比,这种通信密集型内核通常会导致严重的数据传输开销,这可能可以通过 CPU-FPGA 或 CPU-GPU 通信时间测量来检测。

为了更好地理解,让我们看下面的例子:

通信密集型广度优先搜索(BFS)

 1  procedure BFS(G, root) is
 2      let Q be a queue
 3      label root as explored
 4      Q.enqueue(root)
 5      while Q is not empty do
 6          v := Q.dequeue()
 7          if v is the goal then
 8              return v
 9          for all edges from v to w in G.adjacentEdges(v) do
10              if w is not labeled as explored then
11                  label w as explored
12                  Q.enqueue(w)

上面的伪代码是著名的面包优先搜索(BFS)。为什么它不适合加速?因为它遍历了图中的所有节点而不做任何重要的计算。因此,与计算密集型相比,它是通信密集型的。此外,对于像 BFS 这样的数据驱动算法,输入的形状和结构实际上可以决定运行时特性,如局部性分支行为,使其不太适合硬件加速。

  • 现在问题出现了,为什么我专注于计算密集型通信密集型

正如您在帖子中标记了 FPGA,我可以向您解释有关 FPGA 的这个概念。例如,在 CPU 和 FPGA 之间使用PCIe连接的给定系统中,我们将 PCIe 传输时间计算为数据通过基于 PCIe 的直接内存访问(DMA)从主机内存移动到设备内存的经过时间。

PCIe 传输时间是过滤掉通信受限工作负载的 FPGA 加速的重要因素。因此,上述 BFS 会显示出严重的 PCIe 传输开销,因此与加速不兼容

另一方面,考虑作为深度神经网络实现的一系列对象识别算法。如果您仔细研究这些算法,您会发现大量时间(可能超过 90%)花费在卷积函数上。输入数据相对较小。卷积令人尴尬地平行。这使其成为迁移到硬件加速器的理想工作负载。

让我们再举一个例子,展示一个完美的硬件加速工作负载:

计算密集型通用矩阵乘法(GEMM)

void gemm(TYPE m1[N], TYPE m2[N], TYPE prod[N]){
    int i, k, j, jj, kk;
    int i_row, k_row;
    TYPE temp_x, mul;

    loopjj:for (jj = 0; jj < row_size; jj += block_size){
        loopkk:for (kk = 0; kk < row_size; kk += block_size){
            loopi:for ( i = 0; i < row_size; ++i){
                loopk:for (k = 0; k < block_size; ++k){
                    i_row = i * row_size;
                    k_row = (k  + kk) * row_size;
                    temp_x = m1[i_row + k + kk];
                    loopj:for (j = 0; j < block_size; ++j){
                        mul = temp_x * m2[k_row + j + jj];
                        prod[i_row + j + jj] += mul;
                    }
                }
            }
        }
    }
}

上面的代码示例是通用矩阵乘法(GEMM)。它是线性代数、机器学习、统计学和许多其他领域的常用算法。此代码中的矩阵乘法更常见的是使用阻塞循环结构来计算。在移动到下一个块之前,在一个块中重用所有元素的算法可以显着提高内存局部性。因此,它是一个极其计算密集型和完美的加速候选者。

因此,仅举几例,我们可以得出以下结论是硬件加速的决定因素:

  • 您的工作负载
  • 您的工作负载访问的数据,
  • 您的工作负载有多并行
  • 可用于加速的底层硅
  • 通信通道的带宽和延迟。

不要忘记阿姆达尔定律

即使您找到了适合硬件加速的理想工作负载,斗争并没有就此结束。为什么?因为著名的阿姆达尔定律开始发挥作用。这意味着,您可能能够显着加快工作负载,但如果它只是应用程序运行时间的 2%,那么即使您无限加速它(将运行时间设为 0),您也只会加速整个应用程序在系统级别降低 2%。因此,理想的工作负载不仅应该是算法上的理想工作负载,事实上,它还应该对系统的整体运行时间做出重大贡献。

于 2022-03-05T12:27:28.660 回答