4 minute read

tldr: 그냥 for loop 쓰는 게 빠르다.

array를 Eigen::Vector나 Eigen::Matrix로 매핑

Elegant 한 방법 → Eigen::Map()을 사용한다.

1
2
Vector3d xyzvel = Eigen::Map<const Eigen::Vector3d>(uservel, 3);
Matrix3d _CEN = Eigen::Map<const Eigen::Matrix3d>(&CEN[0][0], 3, 3).transpose();

그러나 신경 쓸게 한 둘이 아니다.

  1. uservel과 CEN이 const 로 받는 reference 이기 때문에 template 안에 const 키워드가 붙음
  2. Matrix mapping 은 끝에 transpose()를 붙여야 함.
    1. 이 경우 애초에 2d array 선언 시 신경 써서 transpose를 안 붙이면 그만이지만…
    1
    2
    3
    4
    5
    6
    
     // array
     arr[2][2] = { {1,2},{3,4} } 
     cout << a[1][1] << endl; // 2 출력
     // Eigen without .transpose()
     Matrix2d raw= = Eigen::Map<Eigen::Matrix2d>(arr, 2,2); 
     cout << raw[1][1] << endl; // 3출력 (Eigen은 {1,2}를 column vector로 인식)
    

더군다나 for loop을 사용해서 만들었을 때 보다 느리다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void Mapping(const int (&r)[3], const int (&z)[3][3])
{
    Vector3i v,a;
    auto s1 = std::chrono::steady_clock::now();
    v = Eigen::Map<const Vector3i>(r, 3);
    auto duration3 = (std::chrono::steady_clock::now() - s1).count();
    s1 = std::chrono::steady_clock::now();
    for (int i = 0; i < 3; i++)
    {
        a(i) = r[i];
    }
    auto duration4 = (std::chrono::steady_clock::now() - s1).count();

    Matrix3i m,k;
    s1 = std::chrono::steady_clock::now();
    m = Eigen::Map<const Matrix3i>(&z[0][0], 3,3).transpose();
    auto duration1 = (std::chrono::steady_clock::now() - s1).count();
    s1 = std::chrono::steady_clock::now();
    for (int i = 0; i < 3; i++)
    {
        for (int j =0; j< 3; j++)
        {
            k(i,j) = z[i][j];
        }
    }
    auto duration2 = (std::chrono::steady_clock::now() - s1).count();

    std::cout << "\nbuilding vector by Map takes " << duration3 << "ns" << std::endl;
    std::cout << "\nbuilding vector by for loop takes " << duration4 << "ns" << std::endl;

    std::cout << "\nbuilding m takes " << duration1 << "ns" << std::endl;
    std::cout << m << std::endl;
    std::cout << "\nbuilding k takes " << duration2 << "ns" << std::endl;
    std::cout << k << std::endl;
}

int main()
{
    int a[3] = {1,2,3};
    int b[3][3] = { {1,3,5},{2,4,6},{1,1,1}};
    Mapping(a,b);
    return 0;
}

결과는 놀랍게도

1
2
3
4
5
6
7
8
9
10
11
12
13
building vector by Map takes 32900ns

building vector by for loop takes 6000ns

building m takes 3300ns
1 3 5
2 4 6
1 1 1

building k takes 1300ns
1 3 5
2 4 6
1 1 1

따라서 부득이하게 array를 Eigen 형태로 바꿔야 한다면 for loop을 사용하고, 애초에 Eigen 형태만 사용하도록 짜는게 좋다.

Leave a comment