为循环中多次调用的函数返回值预分配内存的正确方法是什么



我正在尝试改进我的c ++代码并尝试改进我的编码风格。我想实现这个在循环中多次调用的函数。

Class C {
    double alpha = 0.1;
    std::valarray<double> f(std::valarray<double> const & arr) //called many times in a loop
    {
        return arr * alpha;
    }
}

传入的数组非常大,每次 f 返回时,它都会为返回值分配一个全新的数组,这确实减慢了我的代码速度。我试图通过在执行期间知道数组大小后立即在它所属的类中为其预分配返回值来实现修复;

Class C {
    double alpha = 0.1;
    std::valarray<double> f_retval;
    void f(std::valarray<double> const & arr) //called many times in a loop
    {
        f_retval = arr * alpha;
    }
    void allocateMembers(int Nx) //known size of the arrays used in the class 
    {
        f_retval = std::valarray<double>(Nx);
    }
}

但必须有更好的方法来做到这一点。有什么建议吗?

您可以通过传递

非常量引用来返回成员函数外部的预分配。

Class C {
    double alpha = 0.1;
    void f(std::valarray<double> const & arr, std::valarray<double>& result) //called many times in a loop
    {
        result = arr * alpha;
    }
}

然后,调用方需要创建自己的预分配结果变量,但随后他们可以在重复调用 f 期间重用该变量。

std::valarray<double> f_retval = std::valarray<double>(Nx);
while (/*some condition*/) {
    myC.f(toModify, f_retval);
    // do something with f_retval
}

与建议的解决方案相比,它的优势包括:

  • 按引用返回对成员函数的用户更明显
  • 成员函数的功能更加包含(它不需要两种方法来执行(,这也避免了因使用不当而导致的 bug
  • 类本身不太复杂

我可以看到引用返回的唯一潜在缺点是调用此方法需要额外的变量声明。

加快速度的第一步是消除每次调用f的内存分配。 这需要一个可以重用的valarray变量。 这可以是class C的成员,也可以作为引用参数传入。

但是,由于valarray乘法运算符将始终分配一个新的valarray,因此每次调用仍然会有一个内存分配。 如果性能至关重要,则需要滚动自己的乘法循环以将结果存储到可重用数组中(可能将其大小调整为正确的大小,这对于第一次调用至关重要(。

除了不分配新内存之外,这还可能从缓存使用中提供额外的好处,因为内存是重复使用的,并且可能已经在 CPU 数据缓存中。

最新更新