멋진 소프트웨어 디자인으로 20 %의 성능 저하


17

객체 지향 프로그래밍을 최대한 활용하도록 가르치는 방법으로 희소 행렬 계산을위한 작은 라이브러리를 작성하고 있습니다. 나는 부품 (연결성 구조를 나타내는 희소 행렬과 그래프)이 매우 느슨하게 결합 된 멋진 객체 모델을 만들기 위해 열심히 노력했습니다. 내 생각에 코드는 훨씬 확장 가능하고 유지 관리가 가능합니다.

그러나 무딘 접근 방식을 사용하는 것보다 다소 느립니다. 이 객체 모델의 장단점을 테스트하기 위해 기본 그래프의 캡슐화를 중단하여 실행 속도가 얼마나 빨라지는 새로운 희소 행렬 유형을 작성했습니다.

처음에는 꽤 어둡게 보였습니다. 내가 자랑 스러웠던 코드는 우아한 소프트웨어 디자인이없는 버전보다 60 % 느리게 실행되었습니다. 그러나 API를 전혀 변경하지 않고도 함수를 인라인하고 루프를 약간 변경하여 몇 가지 저수준 최적화를 수행 할 수있었습니다. 이러한 변화로 인해 경쟁사보다 20 % 느립니다.

내 질문에 도달하게 된 것은 다음과 같습니다. 멋진 객체 모델이 있다는 것을 의미하는 경우 얼마나 많은 성능 손실을 수용해야합니까?


어떤 희소 행렬 연산을 측정하고 있습니까?
Bill Barth

행렬 벡터가 곱합니다. 행렬의 크기는 입니다. 나는 평균 정도 Erdos-Renyi 랜덤 그래프에 대해 Laplacians 그래프를 만들었습니다 . 또한 일부 기계에서는 20 %의 수치가 나빠 지므로 이제는 모든 것을 버리는 경향이 있습니다. 깊은 한숨개발 =는 로그 2 N을=1024,...,16384=로그2
Daniel Shapero

3
어떤 프로그래밍 언어를 사용하고 있습니까? 일반적으로 C ++과 같은 것은 저렴한 (또는 존재하지 않는) 비용으로 우아한 (ish) 디자인으로 벗어날 수 있습니다. 메타 프로그래밍이없는 다른 언어 (Java, Fortran 등)는 20 %의 비용이 합리적입니다.
LKlevin

코드를 보여줄 수 있습니까? 어떤 언어를 사용 했습니까? 어떤 컴파일러 및 컴파일 플래그? 성능 저하의 정확한 위치를 찾으셨습니까? 올바른 이유를 어떻게 찾았습니까? 어떤 프로파일 러를 사용했으며 어떻게 사용 했습니까? 멋진 개체 모델이 비효율적으로 구현되지 않았습니까? 20 %는 크기가 작기 때문에 구현이 열악하거나 다른 코딩 문제가 아니라 설계 때문이라고 말하기 전에 많은 데이터를 수집하고 자세한 분석을 수행해야 할 정도로 작습니다.
Kirill

짧은 참고 : 모든 사람들이 순수한 성능에 대해 좋은 디자인을 공개적으로 칭찬하는 것처럼 보입니다 (물론 유효한 이유가 있습니다). 그렇다면 왜 그렇게 많은 실제 코드가 실제로 유지가 불가능합니까? 모든 코드 슬롭이 죄책감을 느끼고 공개적으로 침묵합니까?
AlexE

답변:


9

과학적 소프트웨어 개발자는 훌륭한 디자인 원칙을 이해하는 사람이 거의 없으므로이 답변이 조금 오래 걸리면 사과드립니다. 소프트웨어 엔지니어링 관점에서 과학 소프트웨어 개발자의 목표는 종종 상충 되는 일련의 제약 조건을 만족시키는 솔루션을 설계하는 것입니다 .

희소 행렬 라이브러리의 설계에 적용될 수있는 이러한 제약 조건의 전형적인 예는 다음과 같습니다.

  • 한 달 안에 완료
  • 랩톱 및 여러 워크 스테이션에서 올바르게 실행
  • 효율적으로 실행

과학자들은 점차 소프트웨어 엔지니어링의 다른 일반적인 요구 사항에 더 많은 관심을 기울이고 있습니다.

  • 설명서 (사용 설명서, 자습서, 코드 주석)
  • 유지 보수성 (버전 제어, 테스트, 모듈 식 설계)
  • 재사용 성 (모듈 식 디자인, "유연성")

이러한 요구 사항 중 하나 이상이 필요할 수 있습니다. 퍼포먼스로 Gordon Bell 상을 수상하려는 경우 몇 퍼센트도 관련이 있으며 코드의 품질을 평가할 판사 중 소수만이 심사 위원이 옳다고 확신 할 수 있습니다. 클러스터 또는 수퍼 컴퓨터와 같은 공유 리소스에서이 코드를 실행하는 것을 정당화하려는 경우 코드 성능에 대한 주장을 방어해야하는 경우가 많지만 그다지 엄격하지는 않습니다. 접근 방식의 성능 향상을 설명하는 논문을 저널에 게시하려는 경우 경쟁사보다 합법적으로 더 빨라야하며 20 % 성능은 유지 관리 성 및 재사용 성을 높이기 위해 기꺼이 절충해야합니다.

충분한 개발 시간이 주어진 "좋은 디자인"은 성능에 영향을 미치지 않아야합니다. 코드를 최대한 빨리 실행하는 것이 목표라면 이러한 제약 조건을 중심으로 코드를 설계해야합니다. 코드 생성, 인라인 어셈블리와 같은 기술을 사용하거나 튜닝 된 라이브러리를 활용하여 문제를 해결하는 데 도움이 될 수 있습니다.

그러나 개발 시간이 충분하지 않으면 어떻게해야합니까? 충분 해요? 글쎄, 그것은 달려 있고, 아무도 당신에게 더 많은 상황 없이이 질문에 대한 좋은 대답을 줄 수는 없습니다.

FWIW : 고성능 희소 행렬 커널 작성에 관심이있는 경우 최적화 된 PETSc 설치와 비교하고 구타하는 경우 팀과 협력해야합니다. 조정 된 커널을 라이브러리에 통합 할 수 있습니다.


코드 생성기에 대해 궁금합니다. 유용 할 것 같지만 유지 관리가 어려울 것 같습니다. Java 프로그래머가 많이 사용한다는 것을 알고 있지만 종종 특정 응용 프로그램에 대한 코드를 생성하도록 조정되어 있습니다. 그것들을 사용하는 과학적 코드를 알고 있습니까?
Daniel Shapero 2016 년

ATLAS, FFTW, Spiral, OSKI, Ignition, stencil_codegen 등이 있습니다. 공개적으로 광고되지는 않지만 MKL 및 ESSL의 중요한 커널 중 몇 개가 이런 식으로 생성 되어도 놀라지 않을 것입니다. 유지 관리 가능한 커널 생성 코드를 작성하는 것은 흥미로운 후속 질문입니다. 나는 이것에 경험이 있지만, 나는 자신을 권위라고 생각하지 않을 것입니다.
Aron Ahmadia 2016 년

12

시간을 보내는 것에 대한 질문입니다. 우리 대부분은 프로그래밍 시간의 3/4를, 결과를 기다리는 시간의 1/4을 소비합니다. (숫자는 다를 수 있지만 숫자가 장점이없는 것은 아니라고 생각합니다.) 따라서 두 배 빠르게 프로그래밍 할 수있는 디자인 (1.5 시간 단위 대신 3/4 시간 단위)을 사용하면 300 %의 성능 저하 (1/4 ~ 1 시간 단위)를 수행 할 수 있으며 문제 해결에 소요되는 실시간 측면에서 여전히 앞서 나옵니다.

반면에, 무거운 계산을 수행하는 경우 계산이 다르게 보일 수 있으며 코드를 최적화하는 데 더 많은 시간을 할애 할 수 있습니다.

나에게있어 20 %는 생산성이 높아지면 상당히 절충적인 것처럼 보입니다.


좋은 대답은 성능이 중요한 부분을 추가하는 것입니다. 주어진 과학 코드는 전적으로 행렬 곱셈을하지 않습니다. 런타임의 20 %가 행렬 곱셈이면 20 %의 성능 히트가 전체적으로 4 %의 차이 만 있으므로 사용하기 쉬운 라이브러리와 교환하여 기쁘게 생각합니다.
Aurelius

1
더 나은 라이브러리를 작성하면 버그가 줄어들 기 때문에 잘못된 결과를 기다리는 시간이 줄어 듭니다.
Davidmh 2016 년

4

IMHO 최대 50 %의 벌칙은 (이유가 무엇이든) 그렇게 나쁘지 않습니다.

실제로 컴파일러 유형에 따라 성능이 0-30 % 차이가 나는 것을 보았습니다. 이것은 하위 FE 이산화로 인해 발생하는 매트릭스에 대한 PETSc의 희소 MatMult 루틴을위한 것입니다.


1

소프트웨어 디자인은 시간이 지나도 자동으로 개선되지 않습니다. 성능은 것입니다. 다음 CPU로 20 %의 수익을 얻게됩니다. 또한 우수한 소프트웨어 디자인을 통해 향후 라이브러리를 쉽게 확장하거나 개선 할 수 있습니다.


나는 이것이 질문에 대답한다고 생각하지 않습니다.
nicoguaro

0

일반적인 원칙은 좋은 디자인을 먼저 수행 한 다음 필요한 경우에만 성능을 최적화하는 것 입니다. 실제로 20 %의 성능 향상이 필요한 유스 케이스는 거의 나타나지 않을 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.