![]() |
OpenCV 4.12.0
开源计算机视觉
|
上一个教程: 如何启用 Halide 后端以提高效率
下一个教程: OpenCV 与 OpenVINO 的用法
| 原始作者 | Dmitry Kurtaev |
| 兼容性 | OpenCV >= 3.3 |
Halide 代码对于我们使用的每个设备都是相同的。但是为了获得令人满意的效率,我们应该正确地调度计算。在本教程中,我们将介绍如何使用 OpenCV 深度学习模块中的 Halide 后端来调度你的网络。
为了更好地理解 Halide 调度,你可能需要阅读教程 @ http://halide-lang.org/tutorials。
如果这是你第一次在 OpenCV 中接触 Halide,我们建议从 如何启用 Halide 后端以提高效率 开始。
你可以通过编写文本配置文件来调度 Halide 管道的计算。这意味着你可以轻松地向量化、并行化和管理层计算的循环顺序。在第一次调用 cv::dnn::Net::forward 之前,将包含特定设备的调度指令的文件路径传递给 cv::dnn::Net::setHalideScheduler。
调度配置文件表示为 YAML 文件,其中每个节点都是一个调度的函数或调度指令。
考虑使用变量 n 表示批处理维度,c 表示通道,y 表示行,x 表示列。对于分割后的变量,使用带有相同前缀但带有 o 和 i 后缀的名称分别表示外部和内部变量。例如,对于范围为 [0, 10) 的变量 x,指令 split: { x: 2 } 会给出新的变量 xo(范围为 [0, 5))和 xi(范围为 [0, 2))。变量名 x 在同一调度节点中不再可用。
你可以在 opencv_extra/testdata/dnn 中找到调度示例,并使用它来调度你的网络。
由于层融合,我们只能调度融合集的最顶层。因为对于每个输出值,我们都使用融合的公式。例如,如果你有三个层:Convolution + Scale + ReLU 依次排列,
融合的函数类似于
所以只有名为 relu 的函数需要调度。
有时,网络使用阻塞结构构建,这意味着某些层是相同的或非常相似的。如果你想将相同的调度应用于不同的层,并精确到 tiling 或 vectorization 因子,请在调度文件开头的 patterns 部分中定义调度模式。此外,你的模式可以使用一些参数变量。
你可以让 DNN 自动调度层。只需跳过调用 cv::dnn::Net::setHalideScheduler。有时,它可能比手动调度更有效。但是,如果特定层需要手动调度,你可以混合使用手动和自动调度方式。编写调度文件并跳过你希望自动调度的层。