/home/caml-shaving

누가 퍼포먼스를 출렁이게 하는가?

세상에 믿을 놈 하나 없다

2019-10-01

태그: dev

유튜브 알고리즘이 이런 영상을 추천해줘서 무심코 보게 되었는데, 정말 재밌고 유익한 톡이었다. 세상에 믿을 놈 하나 없다더니 완벽하게 독립적인 성능 측정이 이렇게 어려운 일인지 처음 알았다.

뱀발로 해당 톡의 강연자를 찾아보니 역시나 엄청난 사람 이었다. 역시 세상은 넓고 괴수는 많다. 톡에서 제시한 해결책인 coz-profilerSTABILIZER 뿐만 아니라 몬가 다양한 메모리 관련 연구를 하고 계신 분인거 같다.

하지만 당장은 저렇게 정밀한 성능 측정을 할 일은 없을 것 같다. 그래서 그냥 재미로, 대체 성능에 영향을 주는게 그럼 뭔가 싶어서 해당 연구의 시발점이 된 논문을 찾아서 읽어봤다. “아무것도 잘못된 짓을 하지않고 잘못된 데이터 만들기!” 라니 제목도 참 유우머 있다.

측정 편향성

자연 과학 및 사회 과학에서, 실험 환경에 무해한 어떤 것이 성능 평가에 엄청난 편향을 초래하는 현상을 측정 편향성(measurement bias) 이라고 한다. 이 현상이 컴퓨터 시스템 평가에서도 두드러지게, 아주 흔하게 나타난다는 것이 이 논문의 핵심이다. 실험 결과를 부정확하게 만들 정도로 큰 영향을 주기 때문에 두드러지고, 다양한 하드웨어 (프로세서), 컴파일러 모두에서 아주 흔하게 나타난다.

성능에 영향을 주는 (그렇지만 프로그램을 직접 건드리지 않는) 행위는 뭐가 있을까? 여러가지가 있는데 이 논문에서는 두 가지를 소개한다. 하나는 프로그램의 링크 순서를 바꾸는 일이고, 다른 하나는 유닉스 시스템의 환경 변수 크기를 바꾸는 일이다. 세상에나 마상에나. 둘다 성능과는 아무런 의미가 없어보이는 행위인데 이게 성능에 미치는 영향은 어마무시하다. 논문에서는 -O3 최적화 옵션 대비 -O2 최적화 옵션이 얼마나 영향이 있는지를 계산하였는데, 앞의 의미없어 보이는 두 행위가 성능에 10%까지 영향을 미치는 것이 뚜렷하게 관찰되었다. 심지어 어떤 경우에는 -O3 최적화가 성능을 하락시키기까지 한다!

이런 무의미해보이는 행위가 성능에 영향을 미치는 이유 중 하나는 바로 이런 행위가 프로그램의 메모리 레이아웃을 바꿔서, 다양한 하드웨어 휴리스틱에 영향을 주기 때문이다. 링크 순서를 바꾸면, 프로그램의 코드 얼라인먼트에 영향을 주고, 이는 결국 (캐시와 같은) 하드웨어 버퍼와 (분기 예측과 같은) 하드웨어 휴리스틱에 충돌을 일으킨다. 그리고 유닉스 환경 변수의 크기를 바꾸면, 첫째로 C 프로그램 스택의 시작 주소가 달라지게 되고, 이는 결국 하드웨어 버퍼 위에 올라가는 스택 변수의 얼라인먼트에 영향을 준다. 둘째로, 특정 프로그램의 경우 시작과 동시에 유닉스 환경 변수를 힙에다 올리는데, 이 크기가 바뀌면 힙에 할당되는 데이터 구조의 얼라인먼트에 영향을 준다. 결국 이들 모두는 하드웨어 휴리스틱에 영향을 주고 이는 퍼포먼스를 출렁이게 한다.

더 심각한 것은 하드웨어의 동작이 매우 불투명하기 때문에, 이런 메모리 레이아웃을 바꾸는 행위가 모노톤하지 않다는 것이다. 예를 들어, 이 논문이 작성된 시기(2009년)의 메이저 프로세서 중 하나인 Core2 에는 적어도 LSD(Loop-stream Detector) 라고 불리는 장치(?)가 있는데, 이는 루프 인스트럭션 실행 동안 i-캐시 (인스트럭션 캐시?) 접근을 피하기 위한 최적화 장치이다. 그런데 인텔이 이 LSD가 어떻게 동작하는지를 공개해둔게 없어서, 당췌 어떻게 해야 LSD를 잘 활용해서 성능을 높일지 알 수가 없다. 또, 모던 프로세서들은 다들 빠른 속도를 위해 다양한 하드웨어 휴리스틱을 구사하고 있는데, 예를 들어 분기 예측만 해도 대체 어떻게 코드를 짜야 이를 십분 활용할 수 있을지 알 수가 없다. 논문이 공개된지 10년이 지난 지금, 성능을 높이기 위해 프로세서에 추가된 하드웨어 휴리스틱이 얼마나 많고 복잡할지, 상상만해도 아득하다.

결국 하드웨어 동작을 이해할 수가 없어서 뭔가 성능 측정이 제대로 안된다는 건 알겠는데, 대체 어떻게 하면 이 하드웨어 동작을 활용해서 성능을 높일 수 있는지 알 수가 없다. 너무 복잡하다. 모든 것은 컴파일러 님의 마음에 달린 줄 알았는데, 그 위에 하드웨어 님이 계실 줄은 꿈에도 몰랐다.

그래서 어떻게 해결하나?

논문에서는, 측정 편향이 있는 환경에서도 실험 결과 데이터에 대해 확신을 갖기 위한 분석 방법과, 실험 환경의 측정 편향 자체를 피하기 위한 방법, 두 가지를 소개하며 끝을 맺는다. 그리고 이를 버거 연구팀이 실제로 구현한 것이 바로 coz-profiler 와 STABILIZER 이다 (라고 이해했는데, 틀릴 수도 있다). 톡만 들어서 깊이 알지는 못하지만, coz-profiler는 정말로 성능에 영향을 미치는 원인을 찾는 프로파일러이고, STABILIZER는 실행 도중 메모리 레이아웃을 랜덤하게 바꿔서 레이아웃의 영향을 없애도록 하여 성능을 측정하는 도구인 것 같다.

컴파일러 최적화에 배신당한게 엊그제 같은데 이젠 하드웨어마저 날 배신한다. 정말 믿을 놈 하나 없는 세상이다. 하지만 어쩌겠나. 세상은 예측할 수 없을 만큼 복잡해졌고, 더 복잡해지고 있다. 여기에 적응해서 어떻게든 예측할 수 있는 방법을 찾을 수 밖에. 앞서 말했듯 당장은 이런 정밀한 성능 측정이 필요한 환경은 아니라, ‘이런 영향이 있다’ 정도로만 우선 알아두고 넘어가자. 혹시 모르지, 언젠가 말도 안되는 성능 측정 결과를 받고 망연자실하고 있을 때 불현듯 이 글이 생각나서 해결책을 찾을지도.