This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TDA4VM:对自定义层挂钩的查询

Guru**** 536590 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1226560/tda4vm-queries-on-custom-layer-hooks

器件型号:TDA4VM

您好!

自定义层的最大池化示例不是很有用、因为它是一个简单的层、甚至不涉及使用权重或偏倚、所以我在尝试研究如何使用这些自定义层挂钩来处理更复杂的层时遇到了一些问题。

1)自定义层如何访问存储器的暂存区域以进行大型(每像素)工作计算(例如通过 TIDL_scratchBufAlloc)。  没有 sTIDL_AlgLayer_t 传递到定制层、它通常包含暂存偏移(在 Init/Alloc 期间没有用于设置暂存大小的挂钩)。

2)自定义图层如何同时具有权重和偏倚?  Max Pool 示例使用其在权重指针中的(少量)参数传递自定义结构、该结构看起来是唯一传输的数据。  我发现现在唯一的方法是在权重指针中同时传递权重和偏置。

3)如何处理权重和偏置的不同数据大小,例如,批标准层将使用8位权重,但在编译后 A16位偏置,以便在计算期间不会降低准确性。

4)量化和图形编译期间权重数据会发生什么情况(PerfSim -黑框),例如批量标准权重通常为8位,偏压为16位,但鉴于 Max Pool 的自定义结构不能应用通用缩放,否则会破坏未知数据格式。  这意味着权重是否始终未缩放(即保持为浮点)?  我假设编译器也会为临时存储器和偏置指针分配内存、而不为自定义层中的这两个存储器分配任何内存?

谢谢。

罗斯

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Ross:

    自定义图层如何访问存储器的暂存区域以进行大量(每像素)工作计算(例如、普通图层通过 TIDL_scratchBufAlloc 执行哪些操作)。  没有 sTIDL_AlgLayer_t 传递到自定义层、该层通常包含暂存偏移(在 Init/Alloc 期间没有用于设置暂存大小的挂钩)。

      TIDL_scratchBufAlloc 仅用于 TIDL 的 PC/主机仿真流程。 如果在处理过程中需要 DDR 中的特定临时存储器、则 当前会为定制层分配固定大小的存储器、可以通过 sysMems 访问它、该 sysMems 作为参数传递给 TIDL_CustomLayerProcess

    2)自定义图层如何同时具有权重和偏倚?  Max Pool 示例使用其在权重指针中的(少量)参数传递自定义结构、该结构看起来是唯一传输的数据。  我发现现在唯一的方法是在权重指针中同时传递权重和偏置。

    是的、您需要存储参数的任何存储器都应通过对所有存储器求和作为权重指针的一部分进行请求。 您将在 TIDL_CustomLayerProcess 期间获得该 指针,在该期间可以解析单个权重和偏置指针。

    3)如何处理权重和偏置的不同数据大小,例如:批量标准层将使用8位权重,但编译后使用16位偏置,以免在计算过程中失去准确性。

    您需要请求以字节为单位的总存储器、以便它可以处理8位和16位数据。  

    量化和图形编译期间权重数据的情况(PerfSim -黑框)、例如批量标准权重通常为8位、偏置为16位、但鉴于 Max Pool 的自定义结构、不能应用通用缩放、否则它会损坏未知数据格式。  这意味着权重是否始终未缩放(即保持为浮点)?  我假设编译器也为暂存指针和偏置指针分配内存、而不为自定义层中的指针分配内存?

    权重和偏置首先存储为浮点、在量化步骤中、同样需要转换为定点。 转换为定点的方式完全是定制的特定层、最后、TIDL 需要对浮点数据应用相应的比例。 (请注意、此流程不是作为 挂钩函数提供的、因此为了使其正常工作、您可能需要修改公开提供的导入工具代码的某些部分)。 我们将在 SDK 9.1版本之前提供更加无缝的集成。 此外,香水不参与任何量化 相关的步骤。

    此致、

    安舒

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的

    感谢您提供以上答案。

    它可以通过 sysMems 访问,该 sysMems 作为参数传递

    当我在 PC 上运行导入时、这四个条目始终为空/大小为零-因此我的参考实现没有可用的暂存区?

    [报价 userid="122272" url="~/support/processors-group/processors/f/processors-forum/1226560/tda4vm-queries-on-custom-layer-hooks/4637294 #4637294"]权重和偏压首先存储为浮点,在量化步骤中同样需要转换为定点。 这转换为定点的方式完全是自定义的特定层

    因此、必须为定制层手动量化所有参数。  如果它单独处理权重/偏置/额外数据、而不是权重指针中的所有数据、则不必如此-它可以像标准层那样进行一般性量化。

    我有一个由我的成像团队生产的虚拟模型、其中自定义层产生小输出(在-2 /+2浮点的范围内)、如果不进行量化但量化完全破坏了它、这会在 TIDL 中产生正确的结果。  我怀疑是因为 TIDL_getCustomLayerOutputTensorScale 的指令未按比例调高小值(仅按比例缩小较大值)。  在这些输出范围较小的情况下、建议如何处理量化?

    谢谢。

    罗斯

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Ross:

    当我在 PC 上运行导入时,这四个条目始终为空/大小为零-因此没有可用于我的参考实施的暂存?

      我可以看出为什么这是从代码发生的(在 PC 仿真模式下、它应该为 L1、L2和 L3存储器执行此操作)、但它似乎为 DDR 执行此操作。 我可以建议使用代码中的小更新来解决该问题(您能说出所使用的确切 SDK 版本吗?)

    所有参数必须手动量化自定义层。  如果它单独处理权重/偏倚/额外数据,而不是所有在权重指针,这将不需要的情况-它可以被量化一般性地与标准层一样。[/引号]

      参数不能通用地量化到任何层、因为它取决于层本身 、因此这需要作为自定义层实现本身的一部分来完成。 目前、我们尚未 向定制层添加任何带有参数的层、这就是为什么定制层的这一部分现在可能没有正确的挂钩的原因。 您能分辨要将哪一层实现为自定义层吗?

    我怀疑是因为 TIDL_getCustomLayerOutputTensorScale 的指令导致不能按比例缩小小值(仅按比例缩小大值)。  在输出范围较小的情况下、建议如何处理量化?

    此处提到的功能用于激活量表(不用于参数),并期望自定义层实现者根据输入量表和范围(在您的情况下为-2至+2)提供输出量表。 您能否参考 文档的"添加函数以计算输出张量比例"部分、看看它是否有助于理解此函数?


    此致
    安舒

    [/quote]
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我可以建议一个小代码更新来解决此问题(您能说出所使用的 SDK 的确切版本吗?)

    是的、非常感谢。  目前、我们使用的是 RTOS SDK 8.5.0.11。

    此处提到的函数用于激活标度(不适用于参数),并期望自定义层实现者根据输入张量标度和范围提供输出张量度

    是的、抱歉、也许我不够清楚、我在谈论上述多个不同的事情。 :) 我理解这是输出张量缩放,这是我一直关注的文档。  但是、指令不会按比例增大小值、而只会按比例减小大值。

    例如、我的输入量程为1.0、权重量程为1.0 (因此累加器量程为1.0)、但我的最小/最大输出为-2/+2。

    文档/头文件中给出的计算导致0舍入位和1.0输出量程(因为-2/+2很容易适合8位有符号值)、因此在8位模式下、它只会将0、1或2全部四舍五入、稍后层中的所有内容都折叠为零。  即小数部分被丢弃。

    我希望在输出很小时使用最小值/最大值将固定 LSB 设置为小于1、但文档中从未涵盖这种情况(尽管在使用训练/量化中未看到的新数据时仍留下足够的余量、以避免饱和)。

    谢谢。

    罗斯

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我认为这可能与我刚刚发现的令人惊讶的东西有关。  有两个名称相同(但不同)的函数- TIDL_UpdateScaleFactors。

    从 TIDL_importQuantLayerParams 调用的对象始终具有 UpdateStats =0,因此从不使用其最小/最大输入参数。

    当 REF_STAT 被置位时、在基准实现期间调用的值始终具有 UpdateStats = 1、但不会以任何方式更新统计信息(实际上、除非输出为浮 点、否则不会执行任何操作、在这种情况下、它仅将缩放复位为1.0、并将舍入位重置为0)。

    这是令人费解的、因为 在设置 REF_STAT 时调用 TIDL_UpdateScaleFactors 是所有层的功能、也是文档提示需要针对自定义层进行的操作-但鉴于它没有效果、因为它看起来是错误的版本、 设置 REF_STAT 后、您实际上应该做什么?  如果未使用最小值/最大值、计算它们的意义何在?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Ross:

      很抱歉回复延迟(我休假了)。  UpdateStats 将在导 入期间设置为0 (这是因为最初就像您在推理期间所指出的那样,它被设置为1,但进行了一些更改,以将其移动到导入,而不需要将其设置为1)。 但是在这种情况下的代码没有被删除,这就是为什么它可能会给你造成一些困惑。  

      对于统计数据收集期间的自定义 层(REF_STAT)、您只应提供两个自定义层变体、一个是浮点型和另一个定点型(8位或16位、具体取决于您正在使用的量化)。 这些实现将用于收集自定义层的激活统计信息(范围)。


    此致、
    安舒

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的

    我可以建议一个小代码更新来解决此问题

    此补丁是否有任何更新?

    对于统计数据收集期间的自定义 层(REF_STAT)、您只应提供两个自定义层变体、一个是浮点型和另一个定点型(8位或16位、具体取决于您正在使用的量化)。 这些实现将用于收集自定义层的激活统计信息(范围)。

    [/报价]

    是的、我已经拥有了这个、它只是关于工作。  我有点疑惑、因为 TIDLE_EXEC_MODE_STATS_COLLECT 的 doxygen 说"定制层应该计算最小值和最大值、然后更新输出张量程"、但这似乎与它实际的工作原理相矛盾、即 TIDL 自动根据参考实现计算最小值/最大值、 而 TIDL_getCustomLayerOutputTensorScale 是更新比例的器件。

    我还感到困惑的是、实数层(例如批处理标准)跟踪最小值/最大值并调用  TIDL_UpdateScaleFactors (不是导入中使用的一个 、而是另一个)、这似乎同意关于 TIDLE_EXEC_MODE_STATS_collection 的注释、 但事实上这个函数不起任何作用、因此我不知道为什么所有层都跟踪自己的最小值/最大值?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Ross:

      很抱歉响应延迟。

    是的,我已经有了这个,它只是关于工作。  我有点疑惑、因为 TIDLE_EXEC_MODE_STATS_COLLECT 的 doxygen 说"定制层应该计算最小值和最大值、然后更新输出张量程"、但这似乎与它实际的工作原理相矛盾、即 TIDL 自动根据参考实现计算最小值/最大值、 然后、 TIDL_getCustomLayerOutputTensorScale 是更新比例的器件。

      如果您使用的是8.6版以后的最新文档,那么这一问题将得到纠正。  正确的行为是 TIDL 在内部计算每个张量的最小值和最大值(与层无关)、用户需要提供正确的定点和浮点函数来计算自定义层。

      此致、

    安舒