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:C7X 上的 uDMA 慢于 A72上的 memcpy

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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1187347/tda4vm-udma-on-c7x-is-slower-than-memcpy-on-a72

器件型号:TDA4VM

您好!

我 已经创建了一个 openvx 内核 ,它将一个 vx_tensor 复制到另一个。  每个内核都指定为内核的目标、唯一的区别是 A72使用 memcpy、C7X、C66、R5F 使用 uDMA。

下面是我复制一个大小为864*128*sizeof(float)=442368字节的 vx_tensor 得到的数字

内核 memcpy
appUdmaCopy1D
a72. 670 μ s 不适用
C66 4889 us 2237 us
C7X 内核上运行 1616 μ s 2003 US
R5F 18097 us 5794 us

我得到的数字非常令人失望、UDMA 似乎比做 A72 memcpy 慢。 在 C7x 上、执行 mempcy 时甚至会更慢。

这些数字是否正常? 我没有找到 uDMA 的任何规格。

以下是我的(简化的)内核代码:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bool TensorBlockCpyDma(const size_t nBytes,
const tivx_obj_desc_tensor_t* const srcDescriptor,
const tivx_obj_desc_tensor_t* const dstDescriptor)
{
bool ret = false;
if ( (0U == nBytes)
|| (NULL == srcDescriptor)
|| (NULL == dstDescriptor))
{
VX_PRINT(VX_ZONE_ERROR, "Invalid input pointer\n");
}
else
{
uint64_t srcPhys = tivxMemShared2PhysPtr(srcDescriptor->mem_ptr.shared_ptr, VX_MEMORY_TYPE_HOST);
uint64_t dstPhys = tivxMemShared2PhysPtr(dstDescriptor->mem_ptr.shared_ptr, VX_MEMORY_TYPE_HOST);
app_udma_copy_1d_prms_t prms;
appUdmaCopy1DPrms_Init(&prms);
prms.dest_addr = dstPhys;
prms.src_addr = srcPhys;
prms.length = nBytes;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

A72内核调用 memcpy()而不是 appUdmaCopy1D()。

谢谢!

弗雷德

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

    尊敬的 Fred:

    A72 memcpy 优于 udma 副本、因为副本的大小很小。 只是450KB、可能 完全存储在缓存中、并且可以提供比 UDMA 更好的性能。 您能否尝试复制2MB 以上的内存? 我认为在本例中、uDMA 的性能将优于 A72上的 memcpy。  

    在 C7x 上、能否尝试使用 DRU 通道而不是 uDMA 通道?  

    此致、

    Brijesh

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

    感谢您的回答、Brijesh。

    我尝试的 TensorCpy 是原始大小的5倍(2211840字节)、但 A72 memcpy 的性能仍然远远超过 DMA。

    内核 864 * 128 * 5 * sizeof (float)
    a72 memcpy 2033 us
    C66 DMA 9460us
    C7X DMA (DRU) 9074 us
    R5F DMA 搭配使用 13582 us

     

    我通过在 TensorBlockCpyDma()中添加这段代码,为 C7X 使用了 DRU :

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    app_udma_ch_handle_t handle = NULL;
    #ifdef C71
    handle = appUdmaCopyNDGetHandle(8U);
    #endif
    if (0 == appUdmaCopy1D(handle, &prms))
    {
    ret = true;
    }
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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

    您好、Brijesh、这有什么更新吗?

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

    您好、Brijesh、您能继续吗?

    在与 Kai 交谈后,她说 DRU 应该比 来自 C7X 的 memcpy 更快,所以我们需要找到 问题所在。 有任何迹象吗?

    谢谢。

    弗雷德

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

    尊敬的

    是的、DRU 性能应 优于 A72 memcpy 性能。 您确定测试实际使用的是 DRU 通道吗? 您能说明一下您是如何启用 DRU 通道进行此测试的吗? 如果可能、请共享该代码片段?  

    这是因为非 DRU 和 DRU DMA 副本的性能数据看起来非常相似(9.4ms 与9ms)、因此我怀疑是否真正使用了 DRU。  

    此外、在 A72侧、您如何执行 memcpy? 如何为 src 和 dst 缓冲区分配存储器? 如果可能、您能否也在此处分享该代码?

     

    此致、

    Brijesh

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

    尊敬的 Brijesh:

    要启用 DRU,我向 appUdmaCopyNDGetHandle()添加了呼叫,其中信道为8U。 下面是 我的 TensorCpyDma 函数:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    typedef struct
    {
    uint32_t elems;
    uint32_t srcOffset;
    uint32_t dstOffset;
    } TensorCpyCfg;
    bool TensorBlockCpyDma(const TensorCpyCfg* const cfg,
    const tivx_obj_desc_tensor_t* const srcDescriptor,
    const tivx_obj_desc_tensor_t* const dstDescriptor,
    const void* restrict const srcMapped,
    void* restrict const dstMapped)
    {
    bool ret = false;
    if ( (NULL == cfg)
    || (NULL == srcDescriptor)
    || (NULL == dstDescriptor)
    || (NULL == srcMapped)
    || (NULL == dstMapped))
    {
    VX_PRINT(VX_ZONE_ERROR, "Invalid input pointer\n");
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    DRU 的新逻辑位于包含"#ifdef C71"的模块中

    至于 A72 memcpy、则是在 TIOVX A72内核中完成的。 分配在 C++ Catch2测试中完成:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    TEST_CASE("TensorCpy - Performance comparison)
    {
    REQUIRE(0 == appInit());
    tivxRegisterMemoryTargetA72Kernels(); // Registers the A72 memcpy kernel
    std::string target = TIVX_TARGET_A72_0;
    std::string impl = "CPU";
    const size_t COLS = 864;
    const size_t ROWS = 128 * 5;
    std::vector<vx_size> dims{COLS, ROWS};
    TiovxUserKernelsTests::VxTensorWrapper src("TensorCpy src", dims);
    TiovxUserKernelsTests::VxTensorWrapper dst("TensorCpy dst", dims);
    TiovxUserKernelsTests::VxUserDataObjectWrapper<TensorCpyCfg> cfg("TensorCpyCfg");
    TensorCpyGraph graph(cfg, src, dst, target); // Calls vxCreateContext()
    src.Allocate(graph.ctx); // Calls vxCreateTensor()
    dst.Allocate(graph.ctx); // Calls vxCreateTensor()
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    C7X 内核的分配过程完全相同。

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

    尊敬的

    根据 以下链接上的数据表、当我们使用来自任何内核的 DRU 通道时、我们应获得大约10Gb/s 这意味着、对于上面大约0.5Mb 的数据、大约花费0.5ms。  

    https://software-dl.ti.com/jacinto7/esd/processor-sdk-rtos-jacinto7/latest/exports/docs/pdk_jacinto_08_05_00_36/docs/datasheet/jacinto/datasheet_j721e.html#udma

    这是它花费更多时间的原因、可能是由于未启用中断。 在 APIappUdmaCopyNDGetHandle 中、我看到通过将标志 udmaCreatePrms.enable_intr 设置为0来禁用中断、当设置为0时、任务通过执行 TaskP_yield 一直等待。 这可能无法提供良好的性能、因为可能还有其他相同或更高优先级的任务正在运行、不允许其展开。  

    我认为最好在启用中断的情况下检查性能、但 不确定这是否受 DRU 通道支持/验证。  

    此致、

    Brijesh

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

    在 appUdmaCreatePrms_Init ()(我使用)中,有以下注释:

    /* C7x 尚不支持中断模式-使用轮询*/
    我想这意味着 vision_apps API 尚未 准备好进行高效的 DRU 传输。
    是否有其他您可以让我参考的 API 来了解如何将 DRU 与 C7X 配合使用?  
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的

    确切地说、在没有中断模式的情况下、默认性能在默认代码中不是很好。  

    目前、只是为了测量性能、您能否 在 appUdmaTransfer 中注释掉对 TaskP_Yield API 的调用、然后检查性能?  

    此致、

    Brijesh

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

    尊敬的 Brijesh、我们使用 ND API 而不是1D/2D 找到了一种权变措施

    appUdmaCopyNDPrms_Init()
    appUdmaCopyNDInit()
    appUdmaCopyNDTrigg()
    appUdmaCopyNDWait()
    appUdmaCopyNDDeinit()
    我认为 vision_apps 附带的一些 app_udma 存在性能问题。
x 出现错误。请重试或与管理员联系。