병렬 과학 계산 소프트웨어 개발 언어?


18

처음부터 병렬 과학 계산 소프트웨어를 개발하고 싶습니다. 어떤 언어를 시작할지 생각하고 싶습니다. 이 프로그램에는 많은 LU 인수 분해 및 희소 선형 솔버 사용과 함께 데이터를 txt 파일로 읽고 쓰는 작업과 많은 계산을 동시에 수행하는 작업이 포함됩니다. 내가 생각한 후보 솔루션은 OpenMP 또는 공동 배열을 사용하는 Fortran 2003/2008, openmp cilk + 또는 TBB를 사용하는 C ++, Python입니다. 다른 문서화 된 제안은 환영합니다! 나는 C, Fortran 및 Java를 잘 알고 있습니다 (순서대로). 파이썬에서 스크립트를 작성했지만 기본 작업을 수행했습니다.

포트란은 매우 빠르지 만 유지 관리 및 병렬화가 어렵다는 것을 알고 있습니다. C ++은 내가 좋아하는 외부 라이브러리 등을 사용하지 않으면 속도가 느리다고 말하지만 풀 스케일, 산업 수준의 소프트웨어를 작성하는 것이 현실적입니까?

소프트웨어는 많은 양의 데이터를 처리하고 과학적인 계산에 효과적이어야합니다. 본질은 성능입니다.

배경으로, 나는 이미 포트란으로 작성된 작동 소프트웨어를 가지고 있습니다. 많은 사람들이 수년에 걸쳐 개발에 참여했으며 코드가 실제로 더럽습니다. 코드를 유지 관리하고 병렬 처리하는 것은 악몽이었고 대안을 생각하고 있습니다.

페트로스


5
C ++이 원하기 때문에 Fortran을 유지 관리하기가 어렵지 않습니다. 유지 관리 성은 언어 선택이 아닌 모범 사례와 관련이 있습니다. C ++의 속도 저하가 과매도되었습니다. 또한 데이터 크기 및 처리 시간 요구 사항을 설명하기 위해이 게시물을 보강하는 것이 좋습니다. "큰"은 내가 말하고있는 사람에 따라 9-10 배 정도 차이가 나는 것을 보았습니다.
Bill Barth 2016 년

@BillBarth 기존 Fortran 코드의 문제점은 세 사람이 서로 다른 관행을 사용하고 있다는 것입니다. 나는 C 배경, F77 배경의 한 사람과 Matlab의 다른 사람에서 왔습니다. 가장 큰 규모의 시스템에 대해서는 데이터를 할당 할 수없고 크기가 정해져 있지 않다 이 코드는 350 초 (경과 시간) 동안 240 초의 시간 범위에 걸쳐 72000 미분 및 74000 대수 방정식을 사용하여 시스템을 시뮬레이션 할 수있었습니다. OpenMP를 사용하여 병렬화하여 170으로 줄였습니다. 이제 보안 검사를 위해 여러 사례를 병렬로 실행해야합니다.
electrique 2016 년

4
@BillBarth는 C ++ 기술을 판매하는 데 너무 겸손하지만 "C ++의 느림이 과매도"되었다는 그의 주장에도 너무 관대합니다. scicomp.stackexchange.com에는이 질문에 대해 많은 C ++ 대 Fortran 스레드가 있었으며 일반적인 결론은 거의 모든 경우에 C ++이 Fortran보다 느리다는 것입니다. 저는 개인적으로 오늘날 그것이 도시 신화로 간주 될 수 있다고 생각합니다. 무엇 이다 매우 사실하면 코드의 계정 유지 보수성을 고려하면, 다음 포트란 오늘 아주 잘 지내지 않는다는 것입니다.
Wolfgang Bangerth 2016 년

2
@BillBarth와 다른 사람들이 Fortran, C ++ 및 기타 언어의 일반적인 장점에 대해 계속 논의 하고 싶다면 scicomp 대화방 및 @ 구체적으로 언급하고 싶은 사람에게 가져 가십시오 .
Aron Ahmadia

1
@AronAhmadia : 아, 내가 ;-) 제드에 말을 너무 많이 가지고 와서 (제드 :.. 다른 시간 우리의 경우, 적응 적 메쉬 데이터 구조에 어떤 스파 스 매트릭스에 대한 STL,하지만 많이)
볼프강 Bangerth

답변:


19

요구 사항을 분석해 보겠습니다.

  • 유지 보수성
  • 텍스트 데이터 읽기 / 쓰기
  • LU 분해를위한 강력한 인터페이스 / 기능
  • 희소 선형 솔버
  • 대용량 데이터에 대한 성능 및 확장 성

이 목록에서 다음 언어를 고려할 것입니다.

C, C ++, 포트란, 파이썬, MATLAB, 자바

Julia는 유망한 새로운 언어이지만 커뮤니티는 여전히 그 주위를 형성하고 있으며 주요 코드로 배포되지 않았습니다.

텍스트 데이터 읽기 / 쓰기

이것은 모든 프로그래밍 언어로 쉽게 얻을 수 있습니다. I / O 액세스를 적절하게 버퍼링하고 통합해야하며 고려해야하는 모든 언어에서 우수한 성능을 얻을 수 있습니다. 성능이 좋은 사용법을 모르면 C ++에서 스트림 오브젝트를 피하십시오.

LU 분해를위한 강력한 인터페이스 / 기능

밀집된 LU 분해를 수행하는 경우 병렬 기능에 LAPACK 또는 ScaLAPACK / Elemental을 사용하려고합니다. LAPACK과 ScaLAPACK은 Fortran으로 작성되었으며 Elemental은 C ++로 작성되었습니다. 세 라이브러리는 모두 성능이 우수하고 잘 지원되며 문서화되어 있습니다. 고려해야 할 언어 중 하나에서 인터페이스로 인터페이스 할 수 있습니다.

희소 선형 솔버

무료로 제공되는 스파 스 선형 솔버는 거의 모두 C로 작성된 PETSc를 통해 사용할 수 있으며 잘 문서화되고 지원됩니다. 고려해야 할 모든 언어에서 PETSc에 인터페이스 할 수 있습니다.

대용량 데이터에 대한 성능 및 확장 성

언급 한 유일한 병렬 프로그래밍 패러다임은 공유 메모리 기반이므로 MPI 기반 (메시지 전달) 분산 메모리 컴퓨팅 방식을 고려하지 않습니다. 필자의 경험에 따르면 분산 메모리 솔루션을 사용하면 수십 개의 코어 이상으로 확장되는 코드를 작성하는 것이 훨씬 쉽습니다. 오늘날 거의 모든 대학 "클러스터"는 MPI 기반이며, 대형 공유 메모리 머신은 비싸고 그에 따라 드물다. 접근 방식에 MPI를 고려해야하지만 선택한 프로그래밍 패러다임에 관계없이 조언이 적용됩니다.

온 노드 성능과 관련하여 수치 루틴을 직접 작성하는 경우 Fortran에서 우수한 직렬 성능을 얻는 것이 가장 쉽습니다. C, C ++ 또는 Python에 대해 약간의 경험이 있다면 비교할만한 성능을 얻을 수 있습니다 (C와 C ++는 Fortran에서 치명적입니다. Python과 MATLAB은 많은 노력없이 약 25 %의 시간 오버 헤드 내에 있습니다). MATLAB은 JIT 컴파일러와 매우 우수한 선형 대수 표현성을 통해이를 수행합니다. Cython, numpy, numexpr을 사용하거나 숫자 커널을 포함하여 Python에서 성능을 주장해야 할 것입니다. 나는 언어를 잘 모르기 때문에 Java의 성능에 대해서는 언급 할 수 없지만 전문가가 작성한 경우 파이썬과 멀지 않은 것으로 생각됩니다.

인터페이스에 대한 참고 사항

나는 당신이 당신이 고려하고있는 어떤 프로그래밍 언어로든 원하는 모든 것을 할 수있을 것이라고 확신했으면한다. Java를 사용하는 경우 C 인터페이스는 약간 까다로울 수 있습니다. Python은 ctypes, Cython 및 f2py를 통해 탁월한 C 및 Fortran 인터페이스를 지원합니다. LAPACK은 이미 포장되어 있으며 scipy를 통해 제공됩니다. MATLAB은 기본 라이브러리에 필요한 모든 기능을 갖추고 있지만 클러스터에서 쉽게 확장 가능하거나 실행하기가 쉽지 않습니다. Java는 JNI 와 C 및 Fortran 인터페이스를 지원할 수 있지만 과학 컴퓨팅을위한 클러스터 및 병렬 소프트웨어에서는 일반적으로 발견되지 않습니다.

유지 보수성

이 중 많은 부분이 개인적인 취향에 달려 있지만 유지 관리에 대한 일반적인 합의는 소프트웨어의 코드 줄 수를 최소화하고, 잘 정의 된 인터페이스로 모듈 식 코드를 작성하고, 계산 소프트웨어를 제공하려는 것입니다. 구현의 정확성과 기능성을 검증하는 테스트

추천

나는 개인적으로 파이썬으로 많은 행운을 얻었 으며 많은 계산 프로젝트에 권장합니다. 나는 당신이 당신의 프로젝트를 위해 그것을 강력하게 고려해야한다고 생각합니다. 파이썬과 MATLAB은 아마도 과학 컴퓨팅에 사용할 수있는 가장 표현적인 언어 일 것입니다. Python을 다른 프로그래밍 언어에 쉽게 인터페이스 할 수 있습니다. f2py를 사용하여 현재 Fortran 구현을 래핑하고 Python에서 원하는 부분을 하나씩 다시 작성하여 기능을 유지하고 있는지 확인할 수 있습니다. 현재 공식 Python 2.7 구현scipy 조합을 권장합니다 . 무료로 제공되는 Enthought Python Distribution 에서이 스택을 쉽게 시작할 수 있습니다 .

C, C ++ 또는 Fortran에서 대부분의 작업을 수행 할 수도 있습니다. C 및 C ++는 많은 경험을 가진 전문 개발자에게는 매우 매력적인 언어이지만, 종종 새로운 개발자를 트립하고 이러한 의미에서보다 학문적 인 코드에 대한 좋은 아이디어는 아닙니다. Fortran과 MATLAB은 학술 계산에서 널리 사용되지만 고급 데이터 구조 및 Python이 제공하는 표현력에는 약합니다 (예 : Python dict 객체 생각).

관련 질문 :


1
매우 잘 문서화되고 포괄적 인 답변. Fortran에서 Lapack을 많이 사용합니다. 파이썬을 살펴보고 Fortran 코드를 감싸서 천천히 시작하여 천천히 파이썬으로 옮길 것입니다. 나를 두려워하는 유일한 것은 내가 가질 수있는 25 %의 시간 오버 헤드입니다. 그러나 좀 더 표현력있는 코드와 더 나은 병렬 컴퓨팅 처리의 이점이 있다면 나는 그것을 갈 것입니다. 소프트웨어가 현재 대화식 방식으로 실행되므로 (데이터를 변경하고 다시 실행) Windows 및 Linux에서 Uni에있는 연구원의 2,4,8,24,48 코어 공유 메모리 컴퓨터에서 공유 메모리만을 언급했습니다.
electrique 2016 년

3
파이썬으로 작성된 숫자 커널에 대해 25 % 오버 헤드를 청구하는 방법을 모르겠습니다. 순수 파이썬 숫자 커널은 보통 C보다 100 배 느립니다. Numpy와 numexpr은 특정 표현식으로 괜찮은 작업을 수행 할 수 있지만, 파이썬에서 새로운 숫자 커널을 작성하는 것은 어렵습니다. Cython은 몇 가지 사항을 빠르게 만들 수 있지만 일반적으로 C의 25 % 이내는 아닙니다. Python은 "접착제"언어이지만 Aron은이를 성능에 민감한 작업을위한 범용 솔루션으로 판매하고 있다고 생각합니다.
Jed Brown

Fortran은 I / O에 많은 구조가 필요하기 때문에 I / O는 Fortran의 약점입니다. Cython과 함께 일하는 실험실 동료들과 대화하면서 얻은 간접적 인 경험은 Jed가 Cython에 대해 말하는 것과 일치합니다. 그들 중 적어도 하나는 성능 집약적 인 작업을 위해 Cython을 대체하기 위해 수동으로 조정 된 C를 작성하고 결과 C 코드를 호출하는 Python의 성능이 Aron의 주장에 더 가깝다고 생각합니다. 또한 PETSc와 Python을 언급 할 경우 petsc4py도 언급 할 수 있습니다. 마지막으로 (몇 년 전) Java에 대한 좋은 MPI 인터페이스는 없었습니다. 변경 되었습니까?
Geoff Oxberry 2016 년

@GeoffOxberry : Java MPI 바인딩이 존재하지만 거의 10 년 안에 업데이트되지 않았습니다. 나는 그들의 지위가 모호하다고 생각합니다. Fortran에는 매우 빠르게 진행할 수있는 수많은 I / O 옵션이 있습니다. Parallel HDF5 (및 일반적으로 HDF5)를 살펴 보는 것이 좋습니다. I / O가 실제로 우세한 경우 (런타임의 50 % 이상) 더 심각한 조치가 필요할 수 있지만, 그렇지 않으면 HDF와 같은 인터페이스의 품질과 이식성이 가치가있을 것입니다.
Bill Barth

@ BillBarth : 확인해야합니다. Fortran I / O에 대한 의견은 Fortran에서 입력 파일 파서를 작성하도록 권장하는 사람의 관점에서 비롯됩니다. 많은 구조를 적용하여 가능하지만 Fortran에서 정규 표현식 파서 또는 XML 파서 라이브러리를 쉽고 광범위하게 사용하지 못했습니다 (예제 제공). 우리는 더 이상 Fortran을 사용하는 유일한 사람들입니다. 아마도 우리는 다른 사용 사례를 생각하고 있습니다.
Geoff Oxberry 2016 년

2

Aron의 매우 포괄적 인 답변 외에도 scicomp.stackexchange의 다양한 스레드를 살펴보고 프로그래밍 속도와 프로그램 속도 및 얼마나 쉬운 지에 대한 질문을 다루었습니다. 이러한 언어로 소프트웨어를 작성하고 유지 관리하는 것입니다.

즉, 거기에 쓰여진 것 외에도 몇 가지 관찰을하겠습니다.

(i) 귀하는 목록에 co-array Fortran을 포함시킵니다. 내 지식으로는 실제로 그것을 지원하는 컴파일러의 수는 매우 적으며 실제로 0입니다. 가장 널리 사용되는 Fortran 컴파일러는 GNU gfortran이며 현재 개발 소스는 공동 배열의 하위 집합을 구문 분석하지만 실제로는 지원하지 않습니다 (즉, 구문을 허용하지만 의미는 구현하지 않습니다) . 이것은 물론 새로운 포트란 표준에 대한 일반적인 관찰입니다. 컴파일러가 실제로 새로운 표준을 지원하는 지연은 몇 년 안에 측정됩니다. 컴파일러는 지난 몇 년 동안 Fortran 2003을 완전히 구현했으며 Fortran 2008을 부분적으로 만 지원했습니다. 사용하는 것을 지원하는 컴파일러가있는 경우에도 사용을 중단해서는 안됩니다.

(ii) C ++ / Cilk +에서도 마찬가지입니다. 그렇습니다. 인텔은 GCC 지점에서이를 개발하고 있지만 GCC 릴리스에서는 사용할 수 없으며 당분간은 불가능할 것입니다. 일반적인 Linux 시스템에 GCC 버전이 설치된 Cilk +를 찾을 때까지 2-3 년이 더 걸릴 것으로 예상 할 수 있습니다.

(iii) C ++ / TBB는 다른 이야기입니다. TBB는 오랫동안 사용되어 왔으며 매우 안정적인 인터페이스를 가지고 있으며 지난 몇 년 동안 (Linux 및 Windows에서) 존재했던 대부분의 C ++ 컴파일러로 컴파일 할 수 있습니다. . 우리는 그것을 사용하고있다 deal.II 좋은 결과로 이미 몇 년 동안. 그것에 관한 좋은 책도 있습니다.

(iv) OpenMP에 대한 저 자신의 의견, 즉 그것이 문제를 찾는 해결책이라고 생각합니다. 매우 규칙적인 데이터 구조가있는 경우 관심있는 내부 루프를 병렬화하는 데 효과적입니다. 그러나 무언가를 병렬화 해야하는 경우 거의 원하지 않는 일입니다. 실제로 원하는 것은 외부 루프 를 병렬화하는 것 입니다. 그리고 TBB와 같은 솔루션은 프로그래밍 언어의 메커니즘을 사용하기 때문에 언어 밖에서 발생하는 문제를 설명하기보다는 (#pragma를 통해) 스레드 핸들에 액세스 할 수없는 방식으로 훨씬 나은 솔루션입니다. , 프로그램 내에서 결과 상태 표시기 등.

(v) 실험적이라면 병렬 프로그래밍, 특히 설명하는 것과 같은 작업을 위해 설계된 새로운 프로그래밍 언어를 살펴볼 수도 있습니다. 본질적으로 살펴볼 두 가지가 있습니다 : X10Chapel . Chapel에 대한 훌륭한 자습서를 보았으며 오늘날에는 물론 해결책도 있지만 잘 설계된 것처럼 보입니다.


기록을 위해 인텔은 현재 컴파일러에 병렬 (분산 메모리) 코어 레이 포트란이 내장되어 있다고 주장합니다. TACC를 조사하고 있지만 아직보고 할 내용이 없습니다. Cray는 또한 컴파일러에서 구현되지만 전 세계의 소수의 컴퓨터에서만 사용할 수 있습니다. 나는 공동 배열과 관련하여 Fortran 2008 표준을 완벽하게 구현한다고 생각하지는 않지만 소수의 컴파일러에서 초기 지원 이상이 있습니다. 물론 Cilk +는 인텔 컴파일러에서도 사용할 수 있지만, 신뢰하는 것은 아직 현명하지 않습니다.
Bill Barth 2016 년

Fortran 2008 표준은 2010 년 말까지 승인되지 않았으므로 CAF가 널리 사용되기까지 몇 년이 걸릴 것입니다. G95는 실제로 (무료) 구현이 있었지만 더 이상 개발되지 않았습니다 (개발자가 PathScale에 합류했습니다).
stali 2016 년

g95의 대부분은 궁극적으로 gfortran으로 끝나지만 CAF가 그 일부가 아닐 수도 있습니다.
Wolfgang Bangerth 2016 년

나는 Intel 컴파일러가 co-array를 잘 지원한다고 생각합니다. 그들은 mpiexec를 사용하여 그것을 만들었습니다. 내 첫 번째 선택이 아닙니다. 좋은 점은 동일한 구현이 공유 및 분산 메모리에서 실행될 수 있다는 것입니다 (몇 가지 테스트를 실행했습니다). opteron 공유 메모리 프로세서가 정말 합리적인 가격으로 60 코어에 도달하면 공유 메모리 옵션을 먼저보고 싶습니다.
electrique

2

일반적으로이 소프트웨어 프로젝트에 대해 진지하게 생각한다면 가장 편한 언어로 완전히 다시 쓰도록 제안합니다. 혼자서 작업하는 것처럼 들리므로 집에서 가장 느끼는 언어로 최상의 결과를 얻을 수 있습니다.

더 구체적으로, 병렬 처리와 관련하여 상자 밖에서 조금 생각하는 것이 좋습니다. OpenMP는 장점이 있지만 순차적 코드를 사용하여 여기저기서 병렬 처리를한다는 생각에 갇혀 있습니다. 본질적으로 인텔 TBB도 마찬가지입니다.

Cilk 는 올바른 방향으로 나아가는 단계입니다. 즉, 본질적으로 병렬 설정에서 문제 / 해결책을 다시 생각하게합니다. 그래도 마음에 들지 않는 점은 또 다른 언어 라는 점입니다 . 또한 병렬 작업 간의 관계를 대략적으로 유추 할 수 있기 때문에 스케줄러는 상당히 보수적 일 수 있으며 특정 문제에 대해 확장 성이 떨어질 수 있습니다.

그러나 좋은 소식은 구현에 대해 진지한 경우 Cilk가 수행하는 작업을 수행 할 수 있다는 것입니다. 예를 들어 문제를 일련의 상호 의존적 작업으로 다시 작성하고 여러 프로세서 / pthreads 를 사용 하거나 OpenMP를 잘못 사용하여 프로세스를 생성합니다. 이를 수행 할 수있는 좋은 예 는 PLASMA 라이브러리 에서 사용되는 QUARK 스케줄러 입니다. 성능과 Cilk의 비교는 여기에 있습니다 .


제안 된 링크를 살펴 보겠습니다. 비교 용지는 매우 좋습니다! 감사! 나는 pthreads에 대해 생각하고 있었지만 프로그램이 크로스 플랫폼이되기를 원합니다. 내가 아는 것에서 pthreads는 Windows에서 문제가 있습니다 (잘못된?).
electrique

@ p3tris : pthreads의 "p"는 POSIX 용이므로 가능한 한 이식성이 뛰어납니다. 프로젝트 와 같이 pthreads-win32또는 cygwin프로젝트 내에 호환되는 Windows 구현이 있습니다 .
Pedro

을 바탕으로 stackoverflow.com/q/2797690/801468 나는 그것을 사용하는 분류에 필요한 물건을 많이가 있습니다 참조하십시오. 프로그래머가 아니기 때문에 더 테스트 된 것을 선호합니다.
electrique

2

위의 의견에서 거친 포란에 대한 논의는 거의 없었습니다. 현재, 그리고 제한된 지식으로 컴파일러에서 대략적인 지원은 다음과 같습니다.

  • Cray에는 최소한 기본적인 대소 기능을 지원하는 컴파일러가 있습니다. "교육용"코드를 작성하는 데 사용했지만 실제 코드를 거친 포트란으로 작성할 수 있다고 말하고 싶습니다. 구문과 개념은 대부분 MPI보다 훨씬 간단하지만 항상 그렇듯이 많은 트랩이 있으며 트랩은 MPI와 다릅니다.
  • 인텔 포트란은 MPI 라이브러리 위에 구축 된 거친 지원을 제공합니다. 아마도 이것은 이론적 인 최고 성능을 제한하지만 메트릭을 보지 못했습니다.
  • Gfortran은 거친 이미지를 지원하지만 단일 이미지 (또는 MPI에서 단일 순위)에 대해서만 지원합니다. 따라서 gfortran 4.8 또는 4.9가 나올 때까지 실제 병렬 처리를 사용할 수 없습니다.

일반적으로 Coarray 기반 코드를 시작하는 경우주의해야합니다. 이 구문은 MPI를 사용하는 Fortran / C / C ++보다 간단하고 훨씬 편리하지만 완전한 기능을 갖춘 것은 아닙니다. 예를 들어, MPI가 지원하는 많은 당신을 위해 매우 편리 할 수 감소 작업 등을. 그것은 많은 의사 소통에 대한 필요성에 달려 있습니다. 예를 원한다면 알려 주시면 파일을 파낼 수 있다면 몇 가지를 알려 드리겠습니다.


그렇습니다. 이러한 종류의 문제에 대한 대충 Fortran의 준비에 대한 자세한 정보는 확실히 도움이 될 것입니다. Scicomp에 오신 것을 환영합니다!
Aron Ahmadia

1

한 번 봐 가지고 스파크 는 함수형 프로그래밍을 활용 메모리 계산을위한 분산 프레임 워크의를. Spark의 프로그램 구조는 MPI와 비교할 때 매우 다릅니다. 기본적으로 단일 컴퓨터와 같은 코드를 작성하면 자동으로 메모리에있는 데이터에 함수로 배포됩니다. Scala, Java 및 Python을 지원합니다.

로지스틱 회귀 (스칼라) :

//load data to distributed memory
val points = spark.textFile(...).map(parsePoint).cache()
var w = Vector.random(D) // current separating plane
for (i <- 1 to ITERATIONS) {
  val gradient = points.map(p =>
    (1 / (1 + exp(-p.y*(w dot p.x))) - 1) * p.y * p.x
  ).reduce(_ + _)
  w -= gradient
}
println("Final separating plane: " + w)

일부 저수준 계산에 Fortran 라이브러리를 사용하는 MLib (Machine Learning 라이브러리) 라는 확장이 있습니다 (Python의 경우 numpy가 사용됩니다). 따라서 아이디어는 간단하고 알고리즘에 집중하고 최적화 수준을 낮은 수준 (처리 순서, 데이터 배포 등)으로 유지합니다.

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