尽快评估多变量递归关系

时间:2019-04-02 03:25:38

标签: algorithm performance math recurrence

我有一些函数,这些函数被赋予了一些变量xyz等,并在这些点上使用一些常数系数来评估它们各自的多项式,返回价值。然后将我的变量设置为等于这些值,然后重复该过程。在伪代码中:

repeat N times:
    x_new = f1(x, y, z)
    y_new = f2(x, y, z)
    z_new = f3(x, y, z)
    x = x_new
    y = y_new
    z = z_new

和功能类似

f1(x, y, z)
    return c0 + c1*x + c2*y + c3*z + c4*x*x + c5*x*y + c6*x*z ...

每次我保存变量的中间值,然后绘制结果图形。为了有足够的点来制作足够质量的图,我需要大约一千万个数据点。我的代码可以对3个变量和3级的多项式做得相当快,但是我正在寻求扩展它以支持任意数量的任意次数的变量和多项式。这是事情进展缓慢的地方,我认为我需要一种不同的方法。

我原来的(硬编码)c评估器看起来像:

double evaluateStep(double x, double y, double z, double *coeffs) {
    double sum;
    sum =  coeffs[0];
    sum += coeffs[1] * x;
    sum += coeffs[2] * y;
    sum += coeffs[3] * z;
    sum += coeffs[4] * x * y;
    sum += coeffs[5] * x * z;
    sum += coeffs[6] * y * z;
    sum += coeffs[7] * x * x;
    sum += coeffs[8] * y * y;
    sum += coeffs[9] * z * z;

    sum += coeffs[10] * x * y * z;
    sum += coeffs[11] * x * x * y;
    sum += coeffs[12] * x * x * z;
    sum += coeffs[13] * y * y * x;
    sum += coeffs[14] * y * y * z;
    sum += coeffs[15] * z * z * x;
    sum += coeffs[16] * z * z * y;

    sum += coeffs[17] * x * x * x;
    sum += coeffs[18] * y * y * y;
    sum += coeffs[19] * z * z * z;
    return sum;
}

通用代码:

double recursiveEval(double factor, double *position, int ndim, double **coeffs, int order) {
    if (!order)
        return factor * *((*coeffs)++);

    double sum = 0;
    for (int i = 0; i < ndim; i++)
        sum += recursiveEval(factor * position[i], position + i, ndim - i, coeffs, order - 1);

    return sum;
}

double evaluateNDStep(double *position, double *coeffs) {
    double *coefficients = coeffs;
    return recursiveEval(1, position, NUM_DIMENSIONS + 1, &coefficients, ORDER);
}

当然,我敢肯定,这破坏了我的编译器(gcc)进行通用子表达式消除和其他类似优化的能力。我想知道是否有更好的方法可以采取。有一点我还无法利用的信息-所有系数都是在程序开始时从25个池中绘制的(重复)。如果有任何区别,则这些范围为[-1.2, 1.2](含)。

我已经考虑过计算多项式的一个项,然后通过简单的variableA/variableB乘法将其转换为其他项,但是引入的错误量可能有点太多。我还考虑了计算直至度数n的所有项,并使用这些项来构建n+12n度项。我不确定如何实现的另一种选择是利用许多项将共享相同系数(pidginhole原理)这一事实来考虑这些项,因此有可能将其简化为更少的所需乘法&附加项,而不是扩展表达式中的术语。不过,我不知道如何执行此操作,因为它必须在运行时发生,并且涉及到表达式的JIT编译之类的内容。

就目前而言,第3级的3个变量(共20个术语)需要近6秒,而第3级的4个变量(共35个术语)需要13秒多一点。这些将不能很好地扩展为更大的程度或更多的变量(不同项的数量的公式为nck(degree + variables, degree),其中nck为“ n select k”)。我正在寻找一种方法来提高广义代码的性能,最好是渐近地(我怀疑是通过部分分解)。我不太在乎语言。我正在用C语言编写此代码,但是如果您希望以其他某种语言来展示算法,那对我来说就不是问题。

0 个答案:

没有答案