在模板函数中包含不变假设

Including an invariant assumption in a template function

本文关键字:包含不 假设 函数      更新时间:2023-10-16

考虑一个典型的有限差分应用:

// assuming T_size > 2
void process_T(double *T0, double *T, const int &T_size, bool periodic) {
  for (int i = 0; i < T_size; ++i) {
    double sum = 0;
    double base = T0[i];
    if (i > 0) sum += (T0[i-1]-base);
    if (i < 0) sum += (T0[i+1]-base);
    if (periodic) { 
       if (i == 0) sum += (T0[T_size-1]-base);
       if (i == T_size-1) sum += (T0[0]-base);
    } else {
      if (i == 1 || i == T_size-1) sum += 0.5*(T0[i-1]-base);
      if (i == 0 || i == T_size-2) sum += 0.5*(T0[i+1]-base);
    }
    T[i] = T0[i] + sum * 0.08; // where 0.08 is some magic number
  }
}

periodic的检查是循环不变的,但由于仅在运行时知道,因此每次都会产生条件检查开销。我可以创建一个专门的函数来假设其中一种情况,但是维护公共基础会很麻烦,尤其是在三维问题的情况下,它会增长到 8 个函数(周期性:无、x、y、z、xy、xz、xyz)来考虑所有组合。

是否有可能通过元编程解决这个问题?

P/S:分支预测器可以相应地优化吗?

模板可能具有非类型参数:

template <bool periodic> void process_T(double *T0, double *T, const int &T_size)

当然,这意味着在调用站点编写这样的东西的成本:

bool periodicFunction = {whatever};
if (periodicFunction)
    process_T<true>(...);
else
    process_T<false>(...);

是的,你可以有

enum Periodicity
{
    PERIODICITY_NONE,
    PERIODICITY_X,
    PERIODICITY_Y
    // etc
};

然后

template <Periodicity P>
void process_T(double* T0, double* T, const int& T_size)
{
    if (P == PERIODICITY_NONE) // ... do something
    if (P == PERIODICITY_X) // ... do something else
    // Common code
}
任何

像样的优化编译器都能够在编译时执行检查,并消除任何死代码(g++ 似乎即使在 -O0 时也能做到这一点)。