关于C++函数调用和计算的问题

A question about function call and evaluation in C++

本文关键字:问题 计算 C++ 函数调用 关于      更新时间:2023-10-16

嘿,关于以下问题,我有一个可能直截了当的问题:

我有一个功能

double afunction(double *myarray)
{   
    double ret = 1.0;
    for(int i = 0; i < 4; i++)
        ret *= myarray[i]*myarray[i];
    return ret;
}

现在我想修改它,以便传递两个新参数:int index描述要更改的myarray索引,如下所示:myarray[ index ] = *add; .这将如下所示:

double afunction(double *myarray, int index, double *add)
{   
    myarray[ index ] += *add;
    double ret = 1.0;
    for(int i = 0; i < 4; i++)
        ret *= myarray[i]*myarray[i];
    return ret;
}

问题是:我不想修改数组myrray,也不想为此创建一个新数组,因为内存问题(这将稍后在 GPU 上计算,无论如何我无法在内核函数中分配一个全新的数组。简单的解决方案?谢谢!

编辑对不起,我打错了东西。我myarray[ index ] = *add;myarray[ index ] += *add;

编辑2一个更大的函数示例,以后可以很容易地扩展到大约 50 个不同的返回案例。因此,让 if 语句修改某个值myarray[index]在每个返回案例中添加*add是非常丑陋的:(

double afunction(double *myarray, int funcIndex, int indexAdd, double *add)
{   
    myarray[ indexAdd ] += *add;
    if(funcIndex >= 1 && funcIndex <= 4)
        return myarray[1]*myarray[1]*myarray[2];
    switch(funcIndex)
    {
        case 5:
            return sin(myarray[3]) * cos(myarray[1]);
        case 6:
            double ret = exp(myarray[1]);
            for(int i = 1; i < 5; i++)
                ret *= (myarray[ i ]-myarray[ 5-i ]);
            return ret;
        case 7:
            double ret = 0.0;
            for(int i = 1; i < 10; i++)
                ret += myarray[ i ];
            return ret;
    }
    return 0.0;
}
double ret = 1.0;
for(int i = 0; i < 4; i++)
    if (index == i)
        ret *= (*add) * (*add);
    else
        ret *= myarray[i]*myarray[i];

或:

double ret = (*add) * (*add);
for(int i = 0; i < 4; i++)
    ret *= myarray[i]*myarray[i];
ret /= myarray[index] * myarray[index];

这不是 100% 等效的,因为您使用的是浮点数。

编辑

好的,看到你编辑了原始问题。一种可以接受的替代方法是:

myarray[ indexAdd ] -= *add;
完成

其余计算后。同样,不能保证myarray[indexAdd]会完全恢复到原来的价值。

或者更好的是,将旧值保存在函数顶部,然后恢复它:

float old = myarray[ indexAdd ];
myarray[ indexAdd ] += *add;
//do work
myarray[ indexAdd ] = old;
double afunction(double *myarray, int index, double *add)
{   
    double ret = (*add) * (*add);
    for(int i = 0; i < 4; i++)
        if( i != index )
            ret *= myarray[i]*myarray[i];
    return ret;
}

有几种可能的解决方案:

显而易见的:

double
aFunction( double* array, int index, double add )
{
    double result = 1.0;
    for ( int i = 0; i != 4; ++ i ) {
        double tmp = array[i];
        if ( i == index ) {
            tmp += add;
        }
        result *= tmp * tmp;
    }
    return result;
}
可能

更快(如果在循环中没有),但可能不同结果:

double
aFunction( double* array, int index, double add )
{
    double result = 1.0;
    for ( int = 0; i != 4; ++ i ) {
        result *= array[i] * array[i];
    }
    //  Since we multiplied by array[i]^2, when we should
    //  have multipied by (array[i] + add)^2...
    result *= 2 * array[index] * add + add * add;
    return result;
}

我怀疑这个是否值得打扰四个元素的数组:四个if可能不比最后的附加计算。 但是,对于较长的数组,它可能是值得考虑。

最后,更多供参考,因为它真的很丑,并且只能在单线程环境:

double
aFunction( double* array, int index, double add )
{
    array[index] += add;
    double result = 1.0;
    for ( int i = 0; i != 4; ++ i ) {
        result *= array[i] * array[i];
    }
    array[index] -= add;
    return result;
}

根据实际的硬件和编译器优化,这可能会是最快的。 (但同样,对于四个元素来说,它远非一定。

关于代码的另外两个评论:如果你不打算修改 array,您可能应该将其作为double const*传递(这消除了上面的最后一种可能性),并且由于您所做的只是阅读单个值,将add作为指针传递确实没有意义;在上面的代码中,我按值传递了它。