FFmpeg 개발자들, 직접 작성한 어셈블리 코드 덕분에 100배 속도 향상 자랑
(tomshardware.com)- FFmpeg 개발진이 직접 작성한 어셈블리 코드를 통해 최대 100배의 성능 향상 발표
- 이번 패치는 전체 프로그램이 아닌 특정 함수에서만 속도 개선 효과 발생
- 최신 CPU의 AVX512 지원 시 100배, AVX2 지원에서는 64% 성능 향상 확인
- 해당 향상 기능은 주로 잘 알려지지 않은 필터에 적용됨
- 컴파일러의 자동 최적화가 여전히 직접 작성한 어셈블리 코드와의 성능 격차 드러남
FFmpeg의 성능 향상: 100배 속도 개선의 실제 의미
최신 패치와 주요 개선점
- FFmpeg 프로젝트 개발진이 손수 작성한 어셈블리 코드를 적용한 결과, 오픈소스 크로스플랫폼 미디어 트랜스코딩 도구에서 "100배 속도 향상"이라는 성과를 강조함
- 그러나 해당 주장에 대해 개발진은 전체 FFmpeg가 아닌 단일 함수에만 해당 속도 향상 적용임을 명확하게 설명함
- 'rangedetect8_avx512' 함수에서 이러한 특출난 최적화가 이루어졌으며, 최신 AVX512를 지원하는 프로세서에서 최대 100배, AVX2 경로에서는 약 64%의 성능 향상이 이루어짐
- 이 기능은 잘 알려져 있지 않은 필터에 적용된 것으로, 기존에는 개발 우선순위에 두지 않았으나 이번에 SIMD(단일 명령 다중 데이터) 방식으로 병렬 처리 최적화를 이룸
개발진 설명 및 기술적 배경
- FFmpeg 개발진은 트위터를 통해 "이 함수 하나가 100배 빨라졌으며 FFmpeg 전체는 아님"이라고 명확히 알림
- 추가 설명에서 해당 기능이 시스템에 따라 100%까지 속도 향상 가능성이 있다고 밝힘
- 이러한 성능 개선은 SIMD 기술을 바탕으로 최신 칩에서 병렬 처리 효율을 대폭 향상시킨 결과임
어셈블리 언어 직접 작성의 중요성
과거와 현재의 최적화 접근법
- 과거 1980~1990년대에는 제한된 하드웨어 환경에서 직접 작성한 어셈블리 코드가 게임 및 각종 소프트웨어 속도 개선의 핵심 도구였음
- 현재는 대부분의 최신 컴파일러가 고급 언어 코드를 어셈블리 코드로 변환하지만, 컴파일러의 레지스터 할당 등 최적화 한계로 인해 직접 작성한 어셈블리 코드가 여전히 더 높은 성능을 보임
- FFmpeg는 이러한 최적화 철학을 고수하는 몇 안 되는 프로젝트 중 하나로, 자체적으로 어셈블리 강좌도 운영
FFmpeg의 생태계 영향력
- FFmpeg의 라이브러리 및 툴은 Linux, Mac OS X, Microsoft Windows, BSD, Solaris 등 다양한 환경에서 작동
- VLC 등 인기 비디오 플레이어 프로그램에서도 FFmpeg의 libavcodec, libavformat 라이브러리를 활용
- 이처럼 폭넓은 오픈소스 미디어 인코딩/디코딩 생태계 내에서 FFmpeg가 차지하는 기술적 중요성 큼
마무리
- 이번 성능 향상은 핵심 기능 전체가 아닌 일부 함수에 한정되지만, 성능 한계 돌파를 보여주는 사례임
- 최신 하드웨어 특화 최적화와 오픈소스 정신이 맞물려 미디어 처리 분야에서 기술 모범을 계속 보임
이건 과거나 지금이나 유효하죠
비슷하게 코덱 라이브러리를 ARM으로 포팅하면서 SSE로 된 커널을 하나하나 푸는것 부터 진행했었고 다 풀고 스칼라만 남긴 상태에서 리얼월드 벤치마크를 돌렸을 때 성능 차이가 유의미하게 났습니다
Hacker News 의견
-
내가 10년 동안 HEVC 등의 SIMD 최적화를 하면서 assembly 버전과 일반 C 버전을 비교하는 게 거의 농담거리였음, 왜냐하면 100배 차이 같은 엄청난 숫자가 나오기 때문임 사실 이런 결과는 초기에 효율이 극도로 낮았음을 의미함 실제 사용에서는 마이크로벤치마크처럼 캐시가 꽉 찬 상태로 동일 함수를 수백만 번 계속 반복 호출하는 환경이 아님 그 대신 실제 상황에선 다른 여러 작업 속에 한 번만 호출될 수도 있음 캐시 효과를 줄이려면 아주 큰 테스트 메모리 영역을 만들어서 테스트해야 하는데, 실제로 그렇게 하는지는 의문임
-
FFmpeg 같이 영상 변환 소프트웨어도 "매크로 벤치마크"를 따로 진행하는지 궁금함 오랜 시간 동안 성능이나 품질, CPU 사용량 등을 다양한 영상과 변환 조합으로 측정할 것 같은데, 그러려면 전용의 일관된 하드웨어가 필요할 거라 생각함
-
잠시 방향이 다른 질문이긴 한데, SIMD에 경험이 많아 보여서 물어보고 싶음 ISPC 써봤는지, 그리고 어떻게 생각하는지 궁금함 요즘에도 여전히 직접 SIMD 코드를 작성해야 하고, 일반 컴파일러가 자동 벡터화에 약하다는 게 좀 황당하게 느껴짐 GPU 커널에선 예전부터 언제나 자동 벡터화가 됐던 것과는 대조적임
-
ffmpeg 자체도 마이크로벤치마크와 다르지 않다고 생각함 본질적으로는 while (read(buf)) write(transform(buf)) 같은 구조임
-
아쉽게도, 캐시 문제 외에도, 개발자들이 때로는 100% 속도 증가라고 말하지만 실제론 매우 한정적인 필터에 해당하는 경우가 많았음 그래도 정보를 투명하게 잘 전달하는 편임
-
"초기에 비효율적이었다"는 해석에 대해, 나는 어떤 수치가 나오는지, 결과 자체가 중요하다고 생각함
-
-
기사에서 어떤 부분은 100배, 또 어떤 부분은 100% 속도 향상이라고 해서 혼동이 됨 예를 들어 "‘rangedetect8_avx512’ 성능이 100.73% 증가"라고 쓰면서, 스크린샷은 100.73배를 보여줌 100배면 9900% 증가, 100% 속도 증가면 2배 빠른 것임 실제로는 어느 쪽이 맞는지 궁금함
-
스크린샷에 있는 것처럼 확실히 100배(혹은 100.73배)가 맞음, 그건 9973% 속도 증가를 의미함 기사 본문에서 % 표기가 잘못 사용된 듯함
-
단일 함수 기준으론 100배, 전체 필터 기준으론 100%(2배)임
-
ffmpeg 쪽 주장은 100배임 100%는 기사 오타 같음
-
함수명이 '8'과 관련 있고, 8비트 값으로 연산한다면, 이전 구현이 스칼라라면 AVX512로 128개 요소를 한 번에 처리 가능하기 때문에 100배 속도 증가도 가능하다고 생각함
-
-
ffmpeg 공식에서 어셈블리 작성 관련 가이드도 있으니 참고 자료로 남김 https://news.ycombinator.com/item?id=43140614
-
기사에서 "rangedetect8_avx512"가 실제로 어떤 상황에 쓰이고 전체 변환 과정에서 실제 실시간 성능 향상이 어느 정도인지 불분명하게 느껴짐 이것이 정말 눈에 띄는 실질적 의미가 있는지 궁금함
-
예전에 영상 신호가 아날로그 시절엔, 컨트롤 신호를 밴드 내에 부호화해 처리했음. DVD 이후에도 디지털 신호가 아날로그로 출력되다 보니, 색상 16 아래(0~255 중)를 "블랙보다 더 검은" 신호로 사용했고 BluRay, HDMI 도 마찬가지임 최근에는 전체 0~255 범위 모두 사용하려는 추세로 전환됨 하지만 여전히 신호 범위 구분이 제대로 안 돼 영상이 어둡게 망가지는 경우가 많음 이 함수는 픽셀값이 16~255인지, 0~255인지 판별하는 용도로 보임 만일 16~255임이 확실하면, 인코딩 시 정보를 절약할 수 있음 하지만 이 부분은 추측임 나도 직업상 영상 작업을 하지만, 블랙 레벨 처리를 항상 잘 못하는 것이 부끄러움
-
변환 과정에서 이 필터가 쓰이는 게 아니고, 컬러 범위나 알파가 premultiplied 여부 등 메타데이터용 정보를 판별하는 데 사용함 문제의 함수는 그중에서도 컬러 범위 파악에 해당함
-
-
흥미로운 경험을 언급하고 싶음 내가 유일하게 어셈블리 코드를 작성했던 이유도 SIMD 때문이었음 최근 그와 관련해 이야기를 나눴는데, 당시엔 어셈블리를 써야 했던 걸 깜빡 잊고 있었음 사실 컴파일러에 aliasing 문제로, 내가 원하는 대로 최적화가 안 됐던 것임 데이터가 다른 방식으로 접근될 일이 없다는 걸 명확히 알려주고, 비표준 키워드를 쓰니까 컴파일러가 자동으로 SIMD 명령을 활용했음 결국 직접 썼던 어셈블리는 뺐음
-
이번 최적화가 x86/x86-64(AVX2, AVX512)에만 적용된다는 점이 좀 아이러니함 한동안 모두가 x86을 썼기 때문에 SIMD 최적화가 널리 적용될 가능성이 있었지만, 새로운 확장 아키텍처들은 정말 별로였거나 호환성이 부족했음 그리고 이제야 좋아진 x86 SIMD가 나와도, x86이 더 이상 표준이 아니라서 의존하기 어렵게 변했음
- AVX512는 여러 확장 집합이 있어, 기초 명령만 사용하지 않으면 CPU마다 명령 지원 범위가 다를 수 있음 최신 인코더들은 멀티 스레딩 성능이 좋아졌지만 한계도 존재함 예전에 임베디드 프로젝트에서 SoC 쪽 비디오 인코더 호환성 문제로 고생하다가 ffmpeg를 돌려보고, CPU 코어 여러 개를 이용해서 더 나은 결과를 얻은 경험이 있음
-
사실 어셈블리가 최적화된 C보다 더 빠르다는 게 의외였음 요즘 컴파일러가 너무 좋아져서 직접 어셈블리 짠다고 성능이 아주 미미하게만 빨라질 줄 알았는데 명백히 내가 착각했다는 걸 깨달았음 언젠간 어셈블리도 확실히 배워야겠다고 결심함
-
관련 패치들을 보니까, 기존 baseline(ff_detect_range_c)은 매우 일반적인 스칼라 C 코드임, 그리고 속도 향상은 같은 연산의 AVX-512 버전(ff_detect_rangeb_avx512)에서 나온 것임 FFmpeg 개발자들은 벡터 폭에 상관없는 매크로로 어셈블리를 직접 쓰는 걸 선호하지만, 인텔의 intrinsics로도 거의 동일하게 표현 가능해 보임 (어차피 레지스터 할당 정도만 차이니 큰 실질 차이는 없음) 얼마나 벡터화를 잘 하느냐가 속도 차이의 본질임 현대 컴파일러로는 trivial하지 않은 반복문 벡터화는 거의 불가능하고, 그마저도 옵션(gcc -O3 등)을 줘야 시도함 그래서 이런 8비트처럼 단위가 작은 연산에서는 AVX/AVX2/AVX-512로 직접 벡터화하면 최소 몇십 배 성능 차이가 남 현대 CPU에서는 극한으로 최적화한 스칼라 코드도 컴파일러보다 더 빨리 짤 수 있는 경우가 있는데, 아주 드물고 매우 신경 써야 함(의존성 체인과 execution port 부담 등) 실제로 내가 40% 속도 향상 경험도 있음 관련 링크: baseline C, AVX512 버전
-
저수준 최적화에 더 가까이 다가가 보면, C 컴파일러가 갑자기 이상한 동작을 하는 사례를 한 시간 이내에 경험하게 됨 실제로 극도로 자주 호출되는 코드라면 최적화 이슈가 실제로 매우 중요하게 작동함 예시: https://stackoverflow.com/questions/71343461/…
-
SIMD intrinsics로 내려가기만 해도 컴파일러보다 훨씬 쉽게 성능을 끌어올릴 수 있음 직접 여러 파트로 나눠서 가이드를 쓴 적 있음 https://scallywag.software/vim/blog/simd-perlin-noise-i
-
거의 모든 C/C++ 라이브러리의 성능 결정적 구간은 수작업 어셈블리가 쓰이고 있음 (strlen 같은 단순 함수도 마찬가지) 컴파일러가 대부분 괜찮은 결과를 내지만, 이 정도로 투자할 가치가 있을 만큼 중요한 소프트웨어는 소수임
-
실제 성능 향상은 어셈블리 때문이 아니고 AVX512 덕분임 이 커널은 워낙 단순해서, AVX512 intrinsics로 짜면 C 코드와 어셈블리의 차이가 거의 없음 100배 속도 차이의 이유는 a) min/max가 SIMD에서는 단일 명령으로 처리되는 반면, 스칼라에서는 cmp+cmov 로 나뉨 b) 8비트 정밀도라 각 AVX512 명령이 64개를 동시에 처리함 결과적으로 L1, L2 캐시 대역폭까지 포화시킬 수 있음 (Zen 5 기준 128B, 64B/cycle) 다만, 한 프레임 전체를 처리한다면 메모리 크기 때문에 L3에 접근해야 할 경우엔 그 이득이 반감되고, L3에 들어가지 않을 경우 이득은 더 작아짐
-
-
Sound Open Firmware(SOF)가 생각남, 이도 gcc와 상업적 Cadence XCC 컴파일러(Xtensa HiFi SIMD intrinsics 지원) 중 선택해 빌드할 수 있음 https://thesofproject.github.io/latest/introduction/…
-
100x임, 100% x 아님