自修改算法?

时间:2014-11-05 18:26:23

标签: c++ algorithm mathematical-optimization

我尝试实现通用的IIR过滤器。主要内容如下:

    // Loop over all SOS sections:
    value_type y = x;
    BOOST_FOREACH( Sos& n, m_sos )
    {
        y = update( n, y );
    }

使用:

...update( Sos& sos, const value_type& x ) const
{

    const value_type xs = sos.m_s * x;

    const value_type w0 =   xs
                          - sos.m_a( 1 ) * sos.m_w( 0 )
                          - sos.m_a( 2 ) * sos.m_w( 1 );

    const value_type y =   w0
                         + sos.m_b( 1 ) * sos.m_w( 0 )
                         + sos.m_b( 2 ) * sos.m_w( 1 );

    sos.m_w( 1 ) = sos.m_w( 0 );
    sos.m_w( 0 ) = w0;

    return y;
}

系数m_a,m_b是可变的,并且在运行时期间从文件中读取一次。 因此,在编译期间值是未知的。取决于设计 过滤它可能发生一些系数是1.0或0.0。因此相应 操作可以省略。这将节省很多性能。 当然,我现在可以优化代码以便快速使用一个专用过滤器,但如上所述 实施应非常通用。 我的第一个想法是某种自我修改算法...但也许有人有一个很酷的想法或提示...... :)

3 个答案:

答案 0 :(得分:3)

您可以制作过滤功能的模板版本。我不知道如何将其直接应用于您的代码,但请考虑以下内容:

// Z1 means "coefficient 1 is zero"
template <bool Z1, bool Z2, bool Z3, bool Z4, bool Z5>
...update( Sos& sos, const value_type& x ) const
{
    value_type coef1 = Z1 ? 0 : sos.m_a( 1 ); // or whatever else
    value_type coef2 = Z2 ? 0 : ...;
    value_type coef3 = Z3 ? 0 : ...;
    value_type coef4 = Z4 ? 0 : ...;
    value_type coef5 = Z5 ? 0 : ...;

    ... // the rest of your code
}

到目前为止,它定义了32个不同的函数,每个函数都经过最大程度的优化(编译器应检测乘以零常数并优化代码)。然后,您可以使用函数指针数组:

auto my_table[] = {
    &update<0, 0, 0, 0, 0>,
    &update<0, 0, 0, 0, 1>,
    ...
    &update<1, 1, 1, 1, 1>
};

然后检查性能不重要的系数(从文件读取系数的位置),从数组中获取函数指针,并将其存储在对象Sos中。

如果这听起来太模糊,我很抱歉;我不明白你的代码足以在可编译的代码中表达我的想法。

答案 1 :(得分:2)

只有5个系数,生成所有2 ^ 5个代码排列然后在运行时选择适当的排列是可行的(例如,如果第一个第二和第五个系数为0,则为“new Updater00110()”以及第三个和第四个系数是非零);这假设当系数为0或1时代码是相同的,如果它们不同,那么你会看到3 ^ 5个排列,这可能会使代码膨胀太多。

从表面上看,未使用的类/函数不应该使高速缓存或类似的东西混乱。

在过去,当我不得不生成这样的几个代码排列时,我使用了一个帮助程序(通常用像Python这样的解释语言编写)来自动生成所有2 ^ 5个排列的代码/文件。

答案 2 :(得分:1)

  

问:我必须使用哪种解决方案&#34;优化&#34;运行时的代码   取决于使用的系数?

所以基本上你想要一个&#34; 编译和优化自己的代码&#34;在运行时。 从技术上讲,这是可能的:例如 here 。主要是从代码中调用C / C ++编译器,创建代码页并使用函数指针跳转到它。

实践角度,我不推荐它。在运行时编译需要时间。当然,如果它只完成一次,它可能会还清。问题是你编译的二进制文件会产生很多要求,而且难以分发。

我的建议如下:

  • 使您的过滤器功能为内联 - 这将节省将参数传递给您的函数的时间。如果你只使用5个系数,这可能值得尝试。
  • 验证系数为1.0或0.0的情况的发生。可能这些情况非常罕见,因此您不必担心它们。
  • 检查您的设计是否可以使用预先计算的值集实现,在初始化时仅计算一次。