여기에 왜 함수형 프로그래밍에 대한 내 인수입니다 캔 , 그리고 해야 전산 과학에 활용 될 수있다. 이점은 엄청 나며 단점은 빨리 사라집니다. 내 마음에는 단 하나의 죄수가 있습니다.
단점 : C / C ++ / Fortran에서 언어 지원 부족
C ++ 14 / 17은 함수형 프로그래밍을 지원하는 강력한 기능을 추가했기 때문에 최소한 C ++에서는 이러한 단점이 사라지고 있습니다. 라이브러리 / 지원 코드를 직접 작성해야 할 수도 있지만 언어는 친구가 될 것입니다. C ++에서 불변 다차원 배열을 수행 라이브러리 : 예를 들어, 여기서 (경고 플러그)이다 https://github.com/jzrake/ndarray-v2를 .
또한 과학 응용 프로그램에 중점을 두지는 않지만 C ++의 함수형 프로그래밍에 대한 좋은 책 에 대한 링크가 있습니다.
내가 믿는 사람에 대한 나의 요약은 다음과 같습니다.
찬성 :
정확성 측면에서 , 기능성 프로그램은 명백하게 잘 구성 되어 있습니다. 물리적 변수의 최소 상태와 해당 상태를 시간 내에 앞으로 진행시키는 기능을 올바르게 정의하도록 강제합니다.
int main()
{
auto state = initial_condition();
while (should_continue(state))
{
state = advance(state);
side_effects(state);
}
return 0;
}
부분 미분 방정식 (또는 ODE)을 풀면 기능 프로그래밍에 적합합니다. advance
현재 솔루션에 순수한 함수 ( )를 적용 하여 다음 솔루션을 생성합니다.
내 경험상 물리 시뮬레이션 소프트웨어는 상태 관리 가 열악하여 부담이 큽니다 . 일반적으로 알고리즘의 각 단계는 공유 (효과적으로 전역적인) 상태의 일부에서 작동합니다. 이로 인해 올바른 순서로 작업을 수행하기가 어렵거나 불가능 해 지므로 소프트웨어가 세그먼트 오류로 나타날 수있는 버그 또는 코드를 충돌 시키지는 않지만 자동으로 과학의 무결성을 훼손하는 오류 조건에 취약 해집니다. 산출. 물리 시뮬레이션에서 공유 상태를 관리하려고 시도하면 멀티 스레딩도 막을 수 있습니다. 이는 수퍼 컴퓨터가 더 높은 코어 수로 이동하고 MPI를 통한 확장이 종종 ~ 100k 작업에서 최고가되기 때문에 미래의 문제입니다. 반대로, 함수형 프로그래밍은 불변성 때문에 공유 메모리 병렬 처리를 사소하게 만듭니다.
알고리즘의 지연 평가로 인해 함수형 프로그래밍에서도 성능 이 향상됩니다 (C ++에서는 컴파일 타임에 여러 유형을 생성 함-종종 함수의 각 애플리케이션마다 하나씩). 그러나 메모리 액세스 및 할당의 오버 헤드를 줄이고 가상 디스패치를 제거함으로써 컴파일러는이를 구성하는 모든 함수 객체를 한 번에보고 전체 알고리즘을 최적화 할 수 있습니다. 실제로, CPU 대 메모리 할당의 사용을 최적화하기 위해 서로 다른 평가 지점의 배열 (알고리즘 결과가 메모리 버퍼에 캐시 됨)을 실험합니다. 모듈 또는 클래스 기반 코드에서 일반적으로 볼 수있는 것과 비교할 때 알고리즘 단계의 로컬 성이 높기 때문에 (아래 예 참조) 다소 쉽습니다.
기능적 프로그램은 물리 상태를 사소한 한 이해 하기 쉽습니다 . 모든 동료가 구문을 쉽게 이해할 수있는 것은 아닙니다! 저자는 잘 알려진 함수를 사용하도록주의를 기울여야하며, 일반적으로 연구원은 절차 적으로가 아니라 기능적으로 표현 된 알고리즘을 보는 데 익숙해 져야합니다. 제어 구조가 없다는 것은 일부 사람들에게 큰 영향을 줄 수는 없지만 컴퓨터에서 더 나은 품질의 과학을 수행 할 수있는 미래를 막을 수는 없다고 생각합니다.
다음은 패키지를 advance
사용하여 유한 체적 코드에서 수정 된 샘플 함수 ndarray-v2
입니다. to_shared
연산자를 주목하십시오 -이것들은 내가 이전에 언급 한 평가 포인트입니다.
auto advance(const solution_state_t& state)
{
auto dt = determine_time_step_size(state);
auto du = state.u
| divide(state.vertices | volume_from_vertices)
| nd::map(recover_primitive)
| extrapolate_boundary_on_axis(0)
| nd::to_shared()
| compute_intercell_flux(0)
| nd::to_shared()
| nd::difference_on_axis(0)
| nd::multiply(-dt * mara::make_area(1.0));
return solution_state_t {
state.time + dt,
state.iteration + 1,
state.vertices,
state.u + du | nd::to_shared() };
}