Как правильно предварительно выделить память для возвращаемого значения функции, которое вызывается много раз в цикле? - PullRequest
5 голосов
/ 28 апреля 2019

Я пытаюсь улучшить свой код на 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);
    }
}

Но должно бытьлучший способ сделать это.Есть предложения?

Ответы [ 2 ]

3 голосов
/ 28 апреля 2019

Вы можете вернуться, передав неконстантную ссылку для предварительного выделения вне функции-члена.

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 голос
/ 28 апреля 2019

Первым шагом к ускорению этого процесса является устранение выделения памяти для каждого вызова f. Это требует наличия переменной valarray, которую можно использовать повторно. Это может быть либо член class C, либо переданный в качестве ссылочного параметра.

Однако, поскольку оператор умножения valarray всегда будет выделять новый valarray, для каждого вызова все равно будет выделяться память. Если производительность критична, вам нужно свернуть свой собственный цикл умножения, чтобы сохранить результат в массиве многократного использования (возможно, изменив его размер до правильного размера, что важно для первого вызова).

В дополнение к тому, что не выделяется новая память, это может обеспечить дополнительные преимущества от использования кэша, поскольку память используется повторно и, вероятно, уже будет в кэше данных ЦП.

...