Сокращение издержек на нестатические функции-члены - PullRequest
0 голосов
/ 04 мая 2019

У меня есть код вычислительной физики (конечная разность), который выполняет операции (производные) над большими массивами данных (полями решений и полями коэффициентов). Данные коэффициента хранятся в виде массива Model объектов с перегруженным оператором (). Следующий класс - пример того, что я пытаюсь сделать:

class Model
{
public: 
    inline double operator () (double field)
    {
        return alpha*field;
    }
private:
double alpha ;
}

Приложение будет использовать массив Models:

std::vector<Model> models; // array of models
std::vector<double> input;
std::vector<double> output;
...    
for (int i = 0; i < models.size(); i++)
{
    output[i] = models[i](input[i]);
} 

Проблема в том, что использование оператора () приводит к значительным издержкам.

Я профилировал код как есть, а затем снова удалил оператор () и написал код встроенным. (Я использую g ++ 7.3.0., Работает на Ubuntu 18.04). Я компилирую с -Winline и g ++ не жалуется, что не может встроить функцию.

Я также пытался использовать функцию static вместо оператора (), и это не привело к таким же издержкам. К сожалению, статическая функция не может получить доступ к переменным-членам. Другие сообщения указывают, что это не должно быть проблемой (например, C ++ Нестатические функции-члены, служебные данные ), но это, конечно, кажется, что здесь.

Итак, мой вопрос: откуда возникают издержки с этой нестатической функцией-членом?

1 Ответ

0 голосов
/ 04 мая 2019

Разница между статическим и нестатическим - указатель this. Код является общим для всех экземпляров, но у функции есть неявный аргумент для доступа к членам класса. Таким образом, нет лишних затрат памяти, таких как вопрос, который вы задаете, но есть небольшая стоимость во времени из-за передачи this и разыменования указателя для доступа к переменной-члену. Вы можете проверить созданный файл сборки, чтобы убедиться, что он встроен.

Предложения по ускорению исполнения:

  • Использовать оптимизацию компилятора
  • Использовать параллелизм: здесь легко использовать потоки C ++ или OpenMP
  • Измените свой дизайн, чтобы использовать вектор альфа, и удалите класс, тогда, возможно, вы могли бы использовать SIMD
...