Эйген конструктор копирования и оператор= производительность
На своей работе я использую математическую библиотеку 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 ответ:
В" быстрой " версии копия обрабатывается вручную Eigen с помощью инлайнинга, явного развертывания цикла и явной векторизации. В "медленном" случае копи-ктор сводится к чему-то вроде:
template<typename T,int Size> struct storage { T data[Size]; storage(storage &other) : data(other.data) {} };
, которые, как мы предполагали, были должным образом оптимизированы компилятором. К сожалению, если
Size
слишком велик, clang и gcc реализуют эту копию как вызовmemcpy
, теряющий информацию о времени компиляцииSize
. С другой стороны, разрешение компилятору обрабатывать эту копию позволяет более высокий уровень оптимизация уровня, как временное удаление в некоторых случаях.