我尝试实现通用的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。因此相应 操作可以省略。这将节省很多性能。 当然,我现在可以优化代码以便快速使用一个专用过滤器,但如上所述 实施应非常通用。 我的第一个想法是某种自我修改算法...但也许有人有一个很酷的想法或提示...... :)
答案 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 ++编译器,创建代码页并使用函数指针跳转到它。
从实践角度,我不推荐它。在运行时编译需要时间。当然,如果它只完成一次,它可能会还清。问题是你编译的二进制文件会产生很多要求,而且难以分发。
我的建议如下: