문제

내 경험상 .NET은 기본 코드보다 2 ~ 3 배 느립니다. (다변량 최적화를 위해 L-BFG를 구현했습니다).

StackoverFlow의 광고를 추적했습니다http://www.centerspace.net/products/

속도는 정말 놀랍고 속도는 기본 코드에 가깝습니다. 그들은 어떻게 그렇게 할 수 있습니까? 그들은 그렇게 말했습니다.

Q. nmath "Pure".net입니까?

A. 답은 "순수한 .NET"의 정의에 다소 의존합니다. NMATH는 C#과 작은 관리 C ++ 레이어로 작성되었습니다. 그러나 기본 선형 대수 작업의 성능을 향상시키기 위해 NMATH는 Native Intel Math 커널 라이브러리 (NMATH 포함)에 의존합니다. 그러나 COM 구성 요소, DLL (.NET 어셈블리)도 없습니다. 또한, 관리되는 C ++ 레이어에 할당 된 모든 메모리는 기본 코드에 의해 사용되는 모든 메모리가 관리 된 힙에서 할당됩니다.

누군가 나에게 더 설명 할 수 있습니까?

도움이 되었습니까?

해결책

C ++/CLI에 대한 요점이 정확합니다. 그림을 완성하려면 두 가지 흥미로운 점이 있습니다.

  • nmath가 여전히 그것에 의존하기 때문에 .NET 메모리 관리 (쓰레기 수집기)는 분명히 문제가되지 않습니다.

  • 성능 장점은 실제로 많은 CPU에 대해 매우 최적화 된 구현을 제공하는 Intel MKL에서 제공합니다. 내 관점에서 볼 때 이것은 중요한 점입니다. 직선을 사용하여 NAIV C/C ++ 코드는 반드시 C#/. NET보다 우수한 성능을 제공하지 않으며 때로는 더 나쁩니다. 그러나 C ++/CLI를 사용하면 모든 "더러운"최적화 옵션을 악용 할 수 있습니다.

다른 팁

그들은 어떻게 그렇게 할 수 있습니까?

.NET 용 숫자 라이브러리의 대부분과 마찬가지로 NMath는 .NET 어셈블리에 포함 된 Intel MKL 위의 래퍼에 지나지 않습니다. 아마도 C ++/CLI와 연결하여 혼합 조립. 실제로 .NET로 쓰여지지 않은 비트를 벤치마킹했을 것입니다.

f#.net 저널 기사 수치 라이브러리 : 특수 기능, 보간 및 랜덤 숫자 (2008 년 3 월 16 일) 및 수치 라이브러리 : 선형 대수 및 스펙트럼 방법 (2008 년 4 월 16 일)는 상당히 약간의 기능을 테스트했으며 NMATH는 실제로 모든 상용 라이브러리 중에서 가장 느 렸습니다. 그들의 PRNG는 다른 모든 것보다 느리고 무료 Math.net 라이브러리보다 50% 느 렸습니다. 일부 기본 기능이 누락되었습니다 (예 : 계산 능력 Gamma(-0.5)) 및 기타 기본 기능 (그들이 제공 한 감마 관련 기능)이 깨졌습니다. Eigensolver 벤치 마크에서 극도의 최적화와 Bluebit은 NMATH를 이겼습니다. Nmath는 당시 푸리에 변환조차 제공하지 않았습니다.

더 놀랍게도, 성능 불일치는 때때로 거대했습니다. 우리가 테스트 한 가장 비싼 상업용 수치 라이브러리 (IMSL)는 FFT 벤치 마크에서 무료 FFTW 라이브러리보다 500 × 더 느 렸습니다. 없음 라이브러리 중 일부는 여러 코어를 사용했습니다.

사실, 우리가 우리 자신의 상업화를 장려하는 것은이 라이브러리의 품질이 좋지 않았습니다. 숫자의 경우 F# 라이브러리 (100% 순수한 F# 코드).

저는 리드 개발자 중 하나입니다 ilnumerics. 그래서 나는 편견이 있습니다. 분명히;) 그러나 우리는 내부에 대해 더 공개되어 있습니다. 우리의 속도 '비밀'.

그것은 모두 시스템 자원이 어떻게 활용되는지에 달려 있습니다! 순수한 속도에 관한 것이고 큰 배열을 처리 해야하는 경우 (중요성, 가장 중요한 순서, 가장 먼저)

  1. 메모리를 적절하게 관리하십시오! '순진한'메모리 관리는 GC를 심하게 강조하고 메모리 조각화를 유발하고 메모리 위치를 저하시키기 때문에 성능이 나빠질 것입니다 (따라서 캐시 성능). .NET와 같은 쓰레기 수집 환경에서는 자주 메모리 할당을 방지하기 위해 요약됩니다. Ilnumerics에서, 우리는이 목표를 아치기 위해 고성능 메모리 풀을 구현했습니다.

  2. 병렬 처리를 활용하십시오! 이것은 스레드 레벨 병렬 처리 및 데이터 레벨 병렬 처리를 모두 대상으로합니다. 계산의 집중 부분을 실행하여 여러 코어를 사용합니다. x86/x64에서 sse.xx 및 avx와 같은 Simd/Multimedia Extensions는 작지만 효과적인 벡터화를 허용합니다. 현재 .NET 언어로 직접 해결할 수 없습니다. 이것이 유일한 이유입니다. 왜 MKL May가 여전히 '순수한'.NET 코드보다 빠릅니다. (그러나 솔루션은 이미 상승하고 있습니다.)

  3. 아치형 고도로 최적화 된 언어의 속도 Fortran 및 C ++와 마찬가지로 동일한 최적화가 코드에 적용되는 것과 같은 코드에 적용되어야합니다. C#은 옵션을 제공합니다.

이러한 예방 조치는 순서대로 따라야합니다! 병목 현상이 메모리 대역이되고 프로세서가 새로운 데이터를 기다리는 데 대부분의 시간을 보내는 경우 SSE 확장 또는 바운드 체크 제거에주의를 기울이는 것은 의미가 없습니다. 또한 많은 간단한 작업의 경우 마지막 작은 규모를 최대 성능으로 아치기위한 큰 노력을 기울이지 않습니다! Lapack 함수 Daxpy의 일반적인 예를 고려하십시오. 벡터 X의 요소를 다른 벡터 Y의 해당 요소에 추가합니다. 처음으로 수행되면 X와 Y의 모든 메모리가 기본 메모리에서 가져와야합니다. 당신이 그것에 대해 할 수있는 일은 거의 없습니다. 그리고 메모리는 병목 현상입니다! 따라서 끝의 추가가 C#의 순진한 방식으로 완료되는지 여부에 관계없이

for (int i = 0; i < C.Length; i++) {
    C[i] = X[i] + Y[i]; 
}

또는 벡터화 전략을 사용하여 수행 - 메모리를 기다려야합니다!

나는이 대답이 어떻게 든 '답변'에 대한 질문을한다. 이러한 전략의 대부분은 현재 언급 된 제품 (아직?)에서 활용되지 않았기 때문이다. Thoses 포인트를 따르면 결국 '기본'언어의 모든 순진한 구현보다 훨씬 더 나은 성능을 얻게됩니다.

관심이 있으시면 L-BFG 구현을 공개 할 수 있습니까? 나는 그것을 Ilnumerics 및 사후 비교 결과로 전환하게되어 기쁩니다. 여기에 나열된 다른 라이브러리가 따르고 싶습니다. (?)

블로그를 게시했습니다 기사 이 질문을 해결합니다.

열쇠는 C ++/CLI. C ++ 코드를 관리 된 .NET 어셈블리로 컴파일 할 수 있습니다.

오늘날 성능 최적화를 위해 두 플랫폼의 이점을 얻기 위해 혼합 .NET/기본 라이브러리를 만드는 것은 업계 표준입니다. .NET 인터페이스가있는 많은 상용 및 무료 라이브러리가 이와 같이 작동하는 NMATH뿐만 아니라. 예 : Math.net Numerics, dnanalytics, 극도의 최적화, Finmath 그리고 많은 다른 사람들. MKL과의 통합은 .NET 수치 라이브러리에 매우 인기가 있으며 대부분은 관리되는 C ++ 어셈블리를 중간 수준으로 사용합니다. 그러나이 솔루션에는 여러 가지 단점이 있습니다.

  1. Intel MKL은 독점 소프트웨어이며 약간 비쌉니다. 그러나 dnanalytics와 같은 일부 라이브러리는 MKL 기능을 순수한 .NET 코드로 무료로 대체합니다. 물론, 그것은 훨씬 느리지 만 무료이며 완벽하게 작동합니다.

  2. 32 비트 및 64 비트 모드 모두에 대해 무거운 관리 된 C ++ 커널 DLL이 필요한 호환성을 줄입니다.

  3. 기본 통화에 대한 관리는 마샬링을 수행해야하며, 이는 감마 또는 정상 CDF와 같은 빠른 자주 운영의 성능을 늦추었다.

RTMath Finmath 라이브러리에서 마지막 두 가지 문제가 해결되었습니다. 나는 그들이 어떻게 그것을했는지 잘 모르지만, 그들은 모든 CPU 플랫폼에 대해 컴파일 된 단일 순수한 .NET DLL을 제공하고 32 비트 및 64 비트를 지원합니다. 또한 NormalCDF 수십억 시간을 호출해야 할 때 MKL에 대한 성능 저하를 보지 못했습니다.

(기본) Intel MKL이 수학을하고 있기 때문에 실제로 관리 코드에서 수학을하지 않습니다. .NET의 메모리 관리자를 사용하므로 .NET 코드에서는 결과를 쉽게 사용할 수 있습니다.

나는 그의 대답에 대한 @darin dimitrov의 의견과 @darin의 의견에 대한 @trevor misfeldt의 의견을 배웠다. 따라서 미래의 독자들을위한 답변으로 게시합니다.

NMATH는 P/Invoke 또는 C ++/CLI를 사용하여 인텔 수학 커널 라이브러리 기본 기능을 호출하여 가장 집중적 인 계산이 수행되는 곳이므로 너무 빠릅니다.

그만큼 시간이 소비됩니다 안에 인텔 MKL 내부의 분해 방법. 데이터 복사가 필요하지 않습니다, 어느 하나. 그래서, CLI가 빠른지에 대한 문제가 아닙니다. 아니면 아니에요. 실행이 발생하는 곳입니다.

또한 @Paul의 블로그도 잘 읽었습니다. 요약은 다음과 같습니다.

C#은 빠르며 메모리 할당은 아닙니다. 변수를 Ref 또는 Out 매개 변수로 재사용하십시오, 메소드에서 새로운 변수를 반환하는 대신. 새로운 변수를 할당하면 메모리가 소비되고 실행 속도가 느려집니다. @Haymo Kutschbach는 이것을 잘 설명했습니다.

정밀도가 필요하지 않은 경우, 이중에서 단일 정밀도로 전환 할 때의 성능 게인은 상당합니다 (데이터 저장에 대한 메모리 절약은 말할 것도 없습니다).

많은 짧은 계산의 경우 C#에서 C ++/CLI 루틴을 호출하고 관리 된 공간에 할당 된 데이터에 모든 포인터를 고정 한 다음 Intel 라이브러리를 호출하는 것은 일반적으로 P/호출을 사용하여 C#에서 직접 호출하는 것보다 일반적으로 더 좋습니다. 데이터 마샬링 비용. @Haymo Kutschbach가 언급 한 바와 같이, C ++/CLI와 C#사이에는 차이가 없지만 댓글에 대해서는 언급했습니다. 마샬링 중에 복사하는 대신, 뻔뻔스러운 멤버 만 포함하는 뻔뻔스러운 유형과 클래스의 배열이 고정됩니다. 나타내다 https://msdn.microsoft.com/en-us/library/75dwhxf7(v=vs.110).aspx 뻔뻔스럽고 불가능한 유형의 목록.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top