질문:
소프트웨어 산업의 합의는 깨끗하고 간단한 코드가 코드베이스와 코드를 소유 한 조직의 장기적인 생존력에 필수적이라는 것입니다. 이러한 특성으로 인해 유지 관리 비용이 절감되고 코드 기반이 계속 될 가능성이 높아집니다.
그러나 SIMD 코드는 일반적인 응용 프로그램 코드와 다르며 SIMD 코드에 특별히 적용되는 깨끗하고 간단한 코드와 비슷한 합의가 있는지 알고 싶습니다.
내 질문에 대한 배경.
다양한 이미지 처리 및 분석 작업을 위해 많은 SIMD (단일 명령, 다중 데이터) 코드를 작성합니다. 최근에는 한 아키텍처 (SSE2)에서 다른 아키텍처 (ARM NEON)로 소수의 기능을 이식해야했습니다.
이 코드는 축소 포장 소프트웨어 용으로 작성되었으므로 MATLAB과 같은 무제한 재배포 권한이없는 독점 언어에 의존 할 수 없습니다.
일반적인 코드 구조의 예 :
- 모든 메모리, 버퍼 및 수명 관리에 OpenCV 의 매트릭스 유형 (
Mat
) 사용 - 입력 인수의 크기 (차원)를 확인한 후 각 픽셀 행의 시작 주소에 대한 포인터가 사용됩니다.
- 각 입력 행렬에서 픽셀 수 및 각 픽셀 행의 시작 주소는 일부 저수준 C ++ 함수로 전달됩니다.
- 이러한 저수준 C ++ 함수는 SIMD 내장 함수 ( Intel Architecture 및 ARM NEON 용 )를 사용하여 원시 포인터 주소에서로드 및 저장합니다.
- 이러한 저수준 C ++ 함수의 특징 :
- 독점적으로 1 차원 (메모리에 연속)
- 메모리 할당을 처리하지 않습니다.
(임시를 포함한 모든 할당은 OpenCV 기능을 사용하는 외부 코드에 의해 처리됩니다.) - 기호 (내장, 변수 이름 등)의 이름 길이 범위는 대략 10-20 자이며 이는 상당히 과도합니다.
(테크노-바블처럼 읽습니다.) - 컴파일러가 "단일 할당"코딩 스타일로 작성 되지 않은 코드를 올바르게 구문 분석하는 데있어 버그가 많기 때문에 SIMD 변수를 재사용하지 않는 것이 좋습니다 .
(여러 컴파일러 버그 보고서를 제출했습니다.)
SIMD 프로그래밍의 어떤 측면으로 인해 토론이 일반적인 경우와 다릅니 까? 또는 SIMD가 다른 이유는 무엇입니까?
초기 개발 비용 측면에서
- 좋은 성능을 가진 C ++ SIMD 코드의 초기 개발 비용은 부담없이 작성된 C ++ 코드에 비해 약 10x-100x (넓은 마진) 입니다.
- 성능 대 읽기 가능 / 청소기 코드 선택 에 대한 답변에서 언급했듯이 ? 대부분의 코드 (일반적으로 작성된 코드 및 SIMD 코드 포함)는 처음 에는 깨끗하지도 않고 빠르지도 않습니다 .
- 스칼라 및 SIMD 코드 모두에서 코드 성능의 혁신적인 개선은 권장되지 않으며 ( 소프트웨어 재 작업 의 일종으로 간주되기 때문에 ) 비용과 이점은 추적되지 않습니다.
성향 측면에서
(예 : 파레토 원리, 일명 80-20 규칙 )
- 이미지 처리가 소프트웨어 시스템의 20 % 만 구성하더라도 (코드 크기 및 기능 모두), 이미지 처리는 시간이 80 % 이상 걸리는 (소비 된 CPU 시간의 백분율로 볼 때) 비교적 느립니다.
- 이는 데이터 크기 효과 때문입니다. 일반적인 이미지 크기는 메가 바이트로 측정되는 반면 이미지가 아닌 데이터의 일반적인 크기는 킬로바이트로 측정됩니다.
- 이미지 처리 코드 내에서 SIMD 프로그래머는 C ++ 코드에서 루프 구조를 식별하여 핫스팟을 포함하는 20 % 코드를 자동으로 인식하도록 훈련됩니다. 따라서 SIMD 프로그래머의 관점에서 볼 때 "중요한 코드"의 100 %가 성능 병목 현상입니다.
- 이미지 처리 시스템에서 종종 여러 핫스팟이 존재하며 비슷한 시간 비율을 차지합니다. 예를 들어, 총 시간의 각각을 차지하는 5 개의 핫스팟이있을 수 있습니다 (20 %, 18 %, 16 %, 14 %, 12 %). 고성능의 이득을 얻으려면 모든 핫스팟을 SIMD로 다시 작성해야합니다.
- 이것은 풍선 터지는 규칙 으로 요약됩니다. 풍선 은 두 번 터질 수 없습니다.
- 풍선이 5 개라고 가정합니다. 그들을 데 시리시키는 유일한 방법은 하나씩 하나씩 터지는 것입니다.
- 첫 번째 풍선이 터지면 나머지 4 개의 풍선이 총 실행 시간의 비율이 더 높아집니다.
- 더 많은 이익을 얻으려면 다른 풍선을 터뜨려 야합니다.
(이것은 80-20 최적화 규칙 에 위배됩니다 . 가장 낮은 과일의 20 %를 뽑은 후에 좋은 경제적 인 결과를 얻을 수 있습니다.)
가독성 및 유지 관리 측면에서
SIMD 코드는 읽기 어렵습니다.
- 이름 지정, 캡슐화, const-correctness (및 부작용을 명백하게 함), 함수 분해 등 모든 소프트웨어 엔지니어링 모범 사례를 따르는 경우에도 마찬가지입니다.
- 숙련 된 SIMD 프로그래머에게도 마찬가지입니다.
최적의 SIMD 코드는 동등한 C ++ 프로토 타입 코드와 비교하여 매우 왜곡됩니다 ( 비고 참조) .
- SIMD 코드를 왜곡하는 방법은 여러 가지가 있지만 10 회 중 1 회만 허용되는 빠른 결과를 얻을 수 있습니다.
- (즉, 높은 개발 비용을 정당화하기 위해 4x-10x의 성능 향상으로 조정됩니다. 실제로는 더 높은 이득이 관찰되었습니다.)
(참고)
이것은 논문제목을 그대로 인용하여 MIT Halide 프로젝트 의 주요 논문입니다.
"이미지 처리 파이프 라인을 쉽게 최적화하기 위해 일정에서 알고리즘을 분리"
앞으로 적용 가능성 측면에서
- SIMD 코드는 단일 아키텍처와 엄격하게 연결되어 있습니다. 각각의 새로운 아키텍처 (또는 광범위한 SIMD 레지스터)를 다시 작성해야합니다.
- 대부분의 소프트웨어 개발과 달리 각 SIMD 코드는 일반적으로 변경되지 않는 단일 목적으로 작성됩니다.
(다른 아키텍처로 이식하는 것을 제외하고) - 일부 아키텍처는 완벽한 역 호환성을 유지합니다 (Intel). 사소한 양 (ARM AArch64, 일부 대체하여 짧은 하강
vtbl
하여vtblq
) 충분하지만 몇 가지 코드 컴파일 실패한다.
기술과 훈련 측면에서
- SIMD 코드를 작성하고 유지 관리하기 위해 새로운 프로그래머를 올바르게 훈련시키기 위해 어떤 지식 전제 조건이 필요한지 명확하지 않습니다.
- 학교에서 SIMD 프로그래밍을 배운 대학 졸업생들은 그것을 비현실적인 경력 트랙으로 멸시하고 무시하는 것처럼 보입니다.
- 분해 판독 및 저수준 성능 프로파일 링은 고성능 SIMD 코드 작성을위한 두 가지 기본 기술로 인용됩니다. 그러나이 두 가지 기술로 프로그래머를 체계적으로 훈련시키는 방법은 불분명합니다.
- 교과서에서 가르치는 것과 크게 다른 최신 CPU 아키텍처는 교육을 더욱 어렵게 만듭니다.
정확성 및 결함 관련 비용 측면에서
- 단일 SIMD 처리 기능은 실제로 다음과 같은 방법으로 정확성을 확립 할 수있을 정도로 응집력이 높습니다.
- 공식적인 방법을 적용 (펜과 종이로)를 하고,
- 출력 정수 범위 확인 (시제품 코드를 사용하고 런타임 외부에서 수행) .
- 그러나 검증 프로세스는 비용이 많이 들며 (코드 검토에 100 % 시간, 프로토 타입 모델 검사에 100 % 시간을 소비) SIMD 코드의 기존 개발 비용이 3 배가됩니다.
- 버그가 어떻게 든이 검증 프로세스를 거치게되면, 결함이 의심되는 기능을 교체 (다시 쓰기)하는 것 외에는 "수리"(수정)하는 것이 거의 불가능합니다.
- SIMD 코드는 C ++ 컴파일러 (코드 생성기 최적화)의 결함으로 인해 어려움을 겪고 있습니다.
- C ++ 표현식 템플릿을 사용하여 생성 된 SIMD 코드 는 컴파일러의 결함으로 인해 크게 어려움을 겪습니다.
혁신적인 혁신의 관점에서
학계에서 많은 솔루션이 제안되었지만 상업적으로 널리 사용되는 솔루션은 거의 없습니다.
- MIT 할로겐
- 스탠포드 암실
- NT2 (Numerical Template Toolbox) 및 관련 Boost.SIMD
널리 사용되는 라이브러리는 SIMD를 많이 사용하지 않는 것 같습니다.
- 오픈 소스 라이브러리는 SIMD에 미지근한 것 같습니다.
- 최근 버전 2.4.9부터 많은 OpenCV API 함수를 프로파일 링 한 후 이것을 직접 관찰했습니다.
- 필자가 프로파일 링 한 다른 많은 이미지 처리 라이브러리도 SIMD를 많이 사용하지 않거나 실제 핫스팟을 그리워합니다.
- 상업용 라이브러리는 SIMD를 완전히 피하는 것 같습니다.
- 경우에 따라 이미지 처리 라이브러리가 이전 버전의 SIMD 최적화 코드를 이후 버전의 비 SIMD 코드로 되돌려 심각한 성능 저하를 초래하는 이미지 처리 라이브러리를 보았습니다.
공급 업체의 답변은 컴파일러 버그를 피해야한다는 것입니다.
- 경우에 따라 이미지 처리 라이브러리가 이전 버전의 SIMD 최적화 코드를 이후 버전의 비 SIMD 코드로 되돌려 심각한 성능 저하를 초래하는 이미지 처리 라이브러리를 보았습니다.
- 오픈 소스 라이브러리는 SIMD에 미지근한 것 같습니다.
이 프로그래머의 질문 : 지연 시간이 짧은 코드가 때때로 "못생긴"상태 여야합니까? 관련이 있으며 이전에 몇 년 전에 나의 견해를 설명하기 위해 그 질문에 대한 답변을 썼습니다.
그러나 그 대답은 "조기 최적화"관점, 즉 다음과 같은 관점에 대한 "유희"입니다.
- 모든 최적화는 정의에 따라 조기에 (또는 본질적으로 단기적으로 )
- 장기적인 이점이있는 유일한 최적화는 단순성입니다.
: 그 리드 나 모두 물어
SIMD 코드는 일반적인 애플리케이션 코드와 다른, 나는 SIMD 코드 깨끗하고 간단한 코드의 가치에 대한 유사한 업계의 합의가 있는지 알고 싶습니다.