Я пытаюсь оптимизировать критические операции в C ++, основанные на Eigen3.Для меня не ясно, какой тип операций доступа с коэффициентами приведет к снижению производительности во время выполнения или когда компилятор сделает хорошую работу.Чтобы попытаться определить источник моей путаницы, я публикую нижеприведенный пример, реализованный несколькими различными способами, вместе с некоторыми гипотезами для каждого.
Вот еще несколько подробностей:
- Матрица M будет оставаться постоянной в течение большей части программы
- критическая_функция действительно вызывается много раз, и поэтому она встроена
Может ли кто-нибудь уточнить, какой подход будет лучшим с точки зрения производительности?Я могу быть смущен влиянием стоимости ссылок, разыменования и т. Д.
Вариант 1: Прямой доступ к матричным коэффициентам
#include <Eigen/Dense>
class A{
A(){
// Assume M has the right numbers
}
// This function will be called many many times, inside loops
inline void critical_function()
{
// Do many operations using M(1, 1), for example:
double y = 1 / M(1, 1);
// ... some more code using M(1, 1)
}
private:
Eigen::Matrix3d M;
};
Гипотеза :
- M (1,1) приводит к постоянному разыменованию, что влечет за собой затраты, поскольку к вычислению смещения будут добавляться циклы (это не массив, но неясно, как компилятор управляет этим)
Вариант 2: Создание копии коэффициента, который нас интересует
#include <Eigen/Dense>
class A{
A(){
// Assume M has the right numbers
x = M(1, 1);
}
// This function will be called many many times, inside loops
inline void critical_function()
{
// Do many operations using x, for example:
double y = 1 / x;
// ... some more code using x
}
private:
double x;
Eigen::Matrix3d M;
};
Гипотеза :
- Доступ x генерирует меньше циклов, чем при обращении к M (1, 1) , поэтому предпочтительнее варианта 1.
- x действительно содержит то же значение, что и M(1,1) , но несет в себе важный риск того, что эти данные будут дублироваться, поэтому этого следует избегать при ведении кода.
Вариант 3: Использование ссылок
#include <Eigen/Dense>
class A{
A(){
// Assume M has the right numbers
}
// This function will be called many many times, inside loops
inline void critical_function()
{
auto & x = M(1, 1);
// Do many operations using x, for example:
double y = 1 / x;
// ... some more code using x
}
private:
Eigen::Matrix3d M;
};
Гипотеза :
- Имея одну ссылку x будет родовт. е. меньше циклов, чем постоянно, ссылаясь на M (1,1) внутри области действия функции.
- Эта потенциальная оптимизация оказывает влияние только внутри критической функции, но не будет перенесено во внешнюю область, такую как цикл, вызывающий функцию много раз.
Редактировать
Типы были исправлены, чтобы удвоиться (из int илиfloat), чтобы соответствовать Matrix3d.