라벨이 Optimization인 게시물 표시

Optimized C++ 서평

https://www.amazon.com/Optimized-Proven-Techniques-Heightened-Performance/dp/1491922060 올 봄~여름쯤에 CppKorea에서 주최하는 스터디에 참가해서 읽었던 책이다. 'Optimized C++' 이라는 "자극적인" 책 제목에 이끌려서 읽게 됐는데, 결과적으로 말하자면 상당히 실망이다. 1. 내용이 깊지 않다. 책의 난이도를 의미하는 것이 아니다. 책의 난이도와 내용의 깊이는 엄밀히 말하면 별개이다. 아무튼, 책 내용의 깊이 측면에서 이 책은 매우 실망적이였다. Optimized C++ 이라는 책 이름에 걸맞는 내용들이 아니였다. 단순히, C++의 good practice들을 performance측면에서 서술한 것이 전부였다. 나는 뭔가 새롭고 고급스러운 스킬들이나 기술들을 원했는데, 내용은 단순히 겉핡기만 하고 있었다. custom memory allocator에 대한 부분으로 예를 들자면, 나는 그것을 활용한 실질적인 고급기술들이나 실제 응용들이 궁금한건데, 책은 단순히 custom memory allocator의 basic example만 가지고 그게 뭔지만 간단하게 설명하고 넘어간다. 2. 설명이 부실하다. 위에서 내용이 깊지 않다고 했는데, 사실 깊지 않은 내용이더라도 그것을 잘 전달하면 그것은 초심자 혹은 특정 level의 독자들을 위한 상당히 좋은 서적이 된다. 근데 이 책의 문제는 내용이 깊지도 않은데 설명도 부실하다. custom memory allocator로 예를 들자면, 책에서는 basic example만 가지고 간단하게 설명하고 넘어가는데, 문제는 저걸 이미 아는 사람은 읽을 필요가 없고, 저걸 모르는 사람은 책만 읽고서는 이해하기가 어렵다는 것이다. 즉, 뭔가 책의 target 독자층이 애매하다. 3. 영어가 뭔가 이상하다?? (지극히 주관적 생각임에 주의!) 이건 나의 문제일 수도 있는데.... 뭔가 영어가 너무 ...

cache friendly code의 중요성

요즘 학교 고급소프트웨어실습 (이하 고소실) 이라는 과목에서 cache friendly code를 작성하는 것을 해보고 있다. 평소에도 memory access pattern에 따라 성능 차이가 극심하게 날 수 있고 어쩌구~저쩌구~.... 개념적으로는 알고 있었지만 실제로 cache를 고려하면서 code를 작성하고, 간단한 코드를 memory access pattern을 다양하게 바꿔보면서 성능을 실험해본 것은 처음이다. 실제로 실험해보니 matrix multiplication 함수를 그냥 짰을 때랑 cache friendly하게 짰을 때 성능 차이가 극심하게 났다. (정확하게 얼마나 났는지는 기억이 안 나는데 아마 열 몇 배 빨랐던 것 같다. 기억이 틀릴 수 도 있다. ㅠㅜ 어쨌든 많이 빨라졌다..) 뭐, cache friendly code는 CPU뿐만 아니라 GPU에서도 상당히 중요하다. CUDA Programming에서, cache friendly 하지 않은 어떤 코드를 800ms정도 걸리는 걸 cache를 고려해서 수정을 하니까 200ms정도로 최적화를 시킬 수 있었다. 물론 GPU는 SIMD구조고, block, warp등 CPU와는 상당히 다른 아키텍처를 가지고 있기 때문에 CPU와는 cache friendly code를 짜는 법이 좀 차이가 났다. 어쨌든 이렇듯 cache friendly code를 작성하는 것은 상당히 중요하다. memory access pattern을 계속 고려하면서 최적화를 하는 작업은 상당히 노가다처럼 느껴지기도 하지만 참 재밌다.. 최적화쪽으로 공부를 한 번 해볼까하는 생각도 든다.. 또 한편으로 과연 그러나 이런 최적화기법들을 얼마나 실제에 적용할 수 있을 지에 대한 생각도 든다. 다른 모듈과 종속성이 별로 없는 특정 모듈이나 알고리즘들은 적용할 만하겠지만, 특정 자료구조가 예를 들어 다양한 곳에서 쓰이는 경우, 이 자료구조를 특정 memory access pattern을 가정해서 최적화하거나 하는게 ...

Data Alignment

CPU는 byte단위로 data를 읽는 것이 아니라 word단위로 data를 메모리에서 읽어들인다.  예를 들어 x86의 경우 32비트(4바이트)단위로 data를 읽어들이는데 이는 즉 0x0에서 0x3까지 4바이트를 읽어들이는 것은 한 번에 데이터를 읽어들일 수 있지만 0x1부터 0x4까지 4바이트를 읽어들이려면 0x0 ~ 0x3 , 0x4 ~ 0x7 이렇게 총 2 번 메모리를 읽어들여야 한다. 이러한 데이터를 비정렬 데이터라고 하는데 만약 비정렬 데이터를 들어들이려고 할 때 cpu의 동작은 cpu마다 다르다. 예를 들어, x86이나 x64같은 경우 cpu는 기본적으로 메모리 상에서 비정렬된 데이터에 대한 읽기 작업을 2개의 정렬된 위치에서의 읽기 작업으로 전환해서 수행한다. 즉 성능이 매우 안좋아지는 것이다. 하지만 예외가 발생하지는 않는다. 그러나 IA-64같은 경우는 비정렬 데이터에 접근하려고 하면 비정렬 예외가 발생하고 OS가 그 예외를 자동으로 처리해주거나 소프트웨어에 예외가 전달되게 된다. 그러면 x86기반에서 visual C++을 이용해 구조체를 사용하면 double같은 경우 8-byte로 alignment가 된다. 이는 왜 그런걸까? double(8-byte type)을 4-byte alignment하든 8-byte alignment하든 cpu는 2번 메모리에서 읽어들여야하는데 말이다. 그 이유는 바로 캐시라인 때문이다. 캐시라인의 크기는 cpu마다 다른데 Intel x86 cpu의 경우 cache line의 크기는 64byte이다. 만약에 double이 4-byte alignment된다고 가정하자. 그러면 double variable이 0x3C ~ 0x43에 위치하고, cache line 1이 0x0 ~ 0x3F , cache line 2가 0x40 ~ 0x7F 의 메모리 주소의 data를 가지고 있다고 생각해보자. 이 경우 double variable의 data를 읽으려면 cache line 1과 cache li...