/ / C + + матрична ефективність обчислення - c ++, алгоритм, продуктивність, матриця, власні властивості

Ефективність обчислення матриці C ++ - c ++, алгоритм, продуктивність, матриця, власні властивості

Ми намагаємося оптимізувати наш C ++ код, і у нас є наступні матричні обчислення (за допомогою бібліотеки Eigen)

#include<Eigen/Dense>

int main(){

MatrixXd P = MatrixXd::Random(30,30); // a  random double 30 x 30 matrix P
MatrixXd M = MatrixXd::Random(30,30); // a  random double 30 x 30 matrix M
Matrix<double, 30, 30> I;
I.setIdentity(); // I is an 30 x 30 identity matirx

P = (I-M)*P

return 0;

}

Де вони всі матриці nxn, а I - це тотожна матриця. Ми знайшли переписання вищезгаданого матричного обчислення

   P= (I- M)*P

як

   P = P-M*P

призводить до швидкості ~ 4-8x в ubuntu Linuxсистема, що використовує компілятор gcc 6.2. Я усвідомлюю той факт, що компілятор може нічого не знати про матрицю ідентичності та про те, що я * P = P, але все одно не може обернути голову навколо того, що робить ефективність настільки сильною. Хто-небудь знає можливі причини, які роблять такі істотні поліпшення?

Відповіді:

1 для відповіді № 1

Поперше, I.identity(); не існує. Те, чого ви хочете, теж є I.setIdentity(), або P = (MatrixXd::Identity(30,30)-M)*P. Якщо ви використовуєте перший варіант, Eigen, безумовно, повинен зробити повне віднімання 30x30 I і M (компілятору буде важко бачити еквівалентність другому виразу). Загалом, це призведе до двох тимчасових (один для різниці, один для продукту).

Якщо ви дійсно використовували I.Identity() ви викликаєте статичну функцію, як функцію-член, і ваш компілятор повинен принаймні попередити вас про це. Це фактично не буде змінено I і ви отримаєте неініціалізовані значення в I, який, ймовірно, включатиме деяке NaN або денормальне значення, обидва можуть бути поганими для продуктивності з плаваючою комою. І, звичайно, ваш результат буде неправильним.

Загалом, я думаю, що найпростіші способи написати свій рівняння є

P -= M*P;

або

MatrixXd Pnew = P - M*P;