2017-04-25 2 views
6

우리는 우리의 C++ 코드를 최적화하기 위해 노력하고있는 우리가 다음의 행렬 계산 (고유치 라이브러리를 사용하는) 그들은 모두 NXN 행렬이며, I는 단위 행렬이다C++ 행렬 계산 효율

#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; 

    } 

. 우리는 ~ 4-8x에

P = P-M*P 

결과로서 상기 매트릭스 연산

P= (I- M)*P 

재기록이 GCC 6.2 컴파일러를 사용하는 리눅스 우분투 시스템에 빠르게 찾아 냈다. 필자는 컴파일러가 항등 매트릭스와 사실 I * P = P에 대해 아무 것도 모를 수도 있지만 여전히 효율성이 훨씬 향상되는 것에 대해 내 머리를 감쌀 수는 없다는 것을 깨닫습니다. 누구나 그러한 실질적인 개선을 가져올 수있는 가능한 이유를 알고 있습니까?

+4

내가 전문가는 아니지만,하지만 P를 사용하여, M은 더 나은 캐시 행동처럼 들린다 I, M, P를 사용하는 것보다. 안타깝게도 이러한 종류의 최적화는 매우 복잡하고 (일부 대상 아키텍처에서) 매트릭스의 실제 크기 (및 내부 유형)가 여기에서도 중요하다고 가정합니다! – sascha

+3

두 번째 버전은 아마도 'dgemm' http://www.netlib.org/lapack/lapack-3.1.1/html/dgemm.f.html과 같이 일시적인 시간이없는 단일 함수 호출과 일치하며 첫 번째 버전은 그렇지 않습니다. 단일 함수와 일치하므로 임시 연산을 사용하여 계산합니다 (먼저 'I - M'을 계산 한 다음 'P'를 곱하고 'P'의 이전 값을 대체합니다.) – alfC

+3

[mcve]를 제공하십시오. . 플랫폼 및 게시 방법을 게시하십시오. 해체 게시 또한 도움이 될 것입니다. – xaxxon

답변

1

우선 I.identity();은 존재하지 않습니다. 원하는 것은 I.setIdentity() 또는 P = (MatrixXd::Identity(30,30)-M)*P입니다. 첫 번째 옵션을 사용하는 경우 Eigen은 IM의 전체 30x30 빼기를 반드시 수행해야합니다 (컴파일러가 두 번째 표현식과 동등한 것을 볼 때 매우 어려움). 전체적으로 이것은 두 개의 임시 테이블을 생성합니다 (하나는 차이점, 다른 하나는 제품에 대한 것임).

실제로 I.Identity()을 사용하는 경우 멤버 함수와 같은 정적 함수를 호출하므로 컴파일러에서 적어도 그에 대해 경고해야합니다. 이것은 실제로 I을 수정하지 않고 I에 초기화되지 않은 값으로 끝나게됩니다.이 값에는 일부 NaN 또는 비정규 값이 포함될 수 있으며 둘 다 부동 소수점 성능에 좋지 않을 수 있습니다. 그리고 물론 당신의 결과는 틀릴 것입니다.

전반적으로, 나는 당신의 방정식을 쓸 수있는 쉬운 방법을 생각할 것입니다

P -= M*P; 

또는

MatrixXd Pnew = P - M*P; 
+0

실수를 지적 해 주셔서 감사합니다 (예 : setIdentity(), 모바일 장치에서 게시물을 수정하려고 시도 했음). 내 게시물을 수정했습니다. – SunnyIsaLearner