【问题标题】:A pragmatic loop unrolling technique [closed]实用的循环展开技术[关闭]
【发布时间】:2011-07-28 11:19:30
【问题描述】:

我正在寻找一个实用的循环展开技术示例。

我认为 Duff 的设备是一个不错的建议。
但是Duff's device's destination is never increased。它可能对将数据复制到串行设备的嵌入式程序员有用,而不是一般程序员。

你能给我一个很好的有用的例子吗?
如果你曾经在你的真实代码中使用过它,那就更好了。

【问题讨论】:

  • Duff 的使用没有增加目标地址这一事实并不限制您在需要增加它的情况下使用此代码。另一方面,您意识到下一个维护您的代码的人可能是一个知道您的地址应该的杀人凶手。
  • @dmckee: 如果我在这种情况下增加目标地址,它与 memcpy 相同。而且我认为 memcpy 在这种情况下更具可读性,甚至更快。
  • 它也不会阻止您减少目的地或做任何其他愚蠢的事情。因为 Duff 的设备不是关于移动数据,它是循环展开的一般表达式,您可以在任何想要手动展开循环的地方使用它。请参阅 Potatoswatter 的答案,但在使用它之前请阅读 John 的答案。

标签: c++ c optimization loops duffs-device


【解决方案1】:

最实用的技术是学习并喜欢编译器的优化选项,如果在分析中遇到热点,偶尔手动检查生成的程序集。

【讨论】:

    【解决方案2】:

    我不确定您所说的“目的地永远不会增加”是什么意思。

    手动循环展开是相当少见的。今天的嵌入式微处理器已经足够快了,这样的优化是不必要的(并且会浪费宝贵的程序内存)。

    我在线性求解器内核中使用了 Duff 设备的变体。每个fwd_step必须有一个back_step,并且以四个为一组进行。

    请注意,前向和后向循环由gotos 实现。当跳过fwd_step 中的if 时,执行跳转到后向循环的中间。所以它真的是一种双重达夫的装置。

    这不是任何一种“实用”技术,它只是我能找到的表达一些非常复杂的流控制的最佳方式。

    switch ( entry ) {
    
    #define fwd_step( index )                                                                                         \
                                                                                                         \
    case (index):                                                                                                    \
        if ( -- count ) {                                                                                               \
            ...
    
    startf:
        fwd_step( 0 )
        fwd_step( 1 )
        fwd_step( 2 )
        fwd_step( 3 )
    
            stream = stream_back;
            goto startf;
    
    
    #define back_step( index )                                                            \
            .... \
        }                                                                                    \
    
    startb:
        stream -= block_size;
    
        back_step( 3 )
        if ( ! -- countb ) break;
        back_step( 2 )
        if ( ! -- countb ) break;
        back_step( 1 )
        if ( ! -- countb ) break;
        back_step( 0 )
            if ( -- countb ) goto startb;
    } // end switch
    

    【讨论】:

    • “目标永远不会增加”意味着 Duff 使用他的代码将数据写入内存映射的 I/O 端口。他也是在测量到他的硬件上没有其他代码足够快之后才这样做的。
    【解决方案3】:

    (为了其他人的利益,可以找到Duff设备的背景herehere

    我在图像处理优化中遇到过这种情况,尤其是在处理要复制的像素少于完整图块或内核的边界条件(这可以避免在每个坐标处进行测试。)

    【讨论】:

      猜你喜欢
      • 2020-12-19
      • 2014-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-20
      相关资源
      最近更新 更多