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

问题描述 投票:5回答:2

我正在尝试改进我的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);
    }
}

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

c++ optimization memory-management c++17
2个回答
3
投票

您可以通过将非const引用传递给成员函数之外的preallocate来返回。

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
}

这比您建议的解决方案的优势包括:

  • 对于成员函数的用户来说,返回引用更为明显
  • 成员函数的功能更加包含(它不需要两个方法来执行),这也避免了因使用不当而导致的错误
  • 班级本身不那么复杂

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


1
投票

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.