Эйген конструктор копирования и оператор= производительность


На своей работе я использую математическую библиотеку Eigen. Я столкнулся с поведением, в котором использование конструктора копирования собственной матрицы в списке инициализаторов для моих собственных классов значительно медленнее, чем использование operator= в теле конструктора.

В этих примерах "Матрица" -это плотная матрица статического размера.
class Slow {
    public:
        Slow(const Matrix &m) : my_matrix{m} {}
    private:
        Matrix my_matrix;
}

class Fast {
    public:
        Fast(const Matrix &m) : my_matrix{} {
            my_matrix = m;
        }
    private:
        Matrix my_matrix;
}

Моя программа часто вызывает конструктор копирования моего класса, и разница в производительности между двумя указанными выше вариантами довольно заметна. Я проверил, что сгенерированная сборка на самом деле отличается.

Я понимаю, что конструктор копирования и оператор= не одно и то же, но мне трудно пробираться через исходный код Eigen, чтобы понять, почему один быстрее другого. Может ли кто - нибудь с некоторой собственной экспертизой взвесить то, что происходит под капотом, что заставляет operator= быть намного быстрее? Понимание и / или ссылки на рекомендуемое чтение также приветствуются.

1 2

1 ответ:

В" быстрой " версии копия обрабатывается вручную Eigen с помощью инлайнинга, явного развертывания цикла и явной векторизации. В "медленном" случае копи-ктор сводится к чему-то вроде:

template<typename T,int Size>
struct storage {
  T data[Size];
  storage(storage &other)
    : data(other.data)
  {}
};

, которые, как мы предполагали, были должным образом оптимизированы компилятором. К сожалению, если Size слишком велик, clang и gcc реализуют эту копию как вызов memcpy, теряющий информацию о времени компиляции Size. С другой стороны, разрешение компилятору обрабатывать эту копию позволяет более высокий уровень оптимизация уровня, как временное удаление в некоторых случаях.