2011-03-04 6 views
7

OpenCV, HALCON 등을 확장하는 n 개의 이미지 처리 라이브러리에서 작업하고 있습니다. 라이브러리는 .NET Framework 3.5와 함께 있어야하며 .NET에 대한 경험이 제한되어 있으므로 성능과 관련하여 몇 가지 질문을하고 싶습니다.Math.Pow의 모범 사례

필자는 자신에게 올바르게 설명 할 수없는 몇 가지 특정 사항에 직면했으며, 왜 그런지와 b) 사례를 다루는 가장 좋은 방법은 무엇인지 물어보기를 바랍니다.

첫 번째 질문은 Math.pow에 관한 것입니다. StackOverflow에서 이미 (a) 꽤 잘 설명하고 있지만 (b)에 대해서는 어떻게하지 않는지에 대한 해답을 이미 찾았습니다. 이

Stopwatch watch = new Stopwatch(); // from the Diagnostics class 
watch.Start(); 
for (int i = 0; i < 1000000; i++) 
    double result = Math.Pow(4,7) // the function call 
watch.Stop() 

결과는 (~ 내 컴퓨터에이 300ms) 아주 좋은하지 않았다 (10 번이나 실행 한 검사 및 평균 값을 calcuated)처럼 내 벤치 마크 프로그램 보인다.

첫 번째 아이디어는 정적 함수이기 때문에 이것이 무엇인지 확인하는 것이 었습니다. 그래서를 통해 직접 내 자신의 클래스

class MyMath 
{ 
    public static double Pow (double x, double y) //Using some expensive functions to calculate the power 
    { 
     return Math.Exp(Math.Log(x) * y); 
    } 

    public static double PowLoop (double x, int y) // Using Loop 
    { 
     double res = x; 
     for(int i = 1; i < y; i++) 
      res *= x; 
     return res; 
    } 

    public static double Pow7 (double x)   // Using inline calls 
    { 
     return x * x * x * x * x * x * x; 
    } 
} 

나는 Math.Pow (4,7)를 대체 할 경우 내가 확인 세 번째 일이었다 구현 4 * 4 * 4 * 4 * 4 * 4 * 4. 탕 위해 수학을 사용하지 마십시오

결과는

300 ms Math.Pow(4,7) 
356 ms MyMath.Pow(4,7) //gives wrong rounded results 
264 ms MyMath.PowLoop(4,7) 
92 ms MyMath.Pow7(4) 
16 ms 4*4*4*4*4*4*4 

지금 내 상황은 지금과 같이 기본적으로 (10 테스트 중 평균 실행)이다. 내 유일한 문제는 바로 ... 지금 내 수학 수업을 실제로 구현해야합니까? 그것은 어떻게 든 힘 기능을 위해서만 자신의 클래스를 구현하는 것은 비효율적 인 것 같습니다. (Btw. PowLoop 및 Pow7은 Release 빌드에서 Math.Pow가 아닌 ​​동안 ~ 25 % 더 빠릅니다).

그래서 내 마지막 질문

이가) 나는 모든 (하지만 내가 어떻게 든 슬픈 어쩌면 분수) (용)에서 Math.Pow를 사용하지 않는다면 내가 잘못.

b) 최적화 할 코드가 있다면 직접 모든 수학 연산을 직접 작성 하시겠습니까?

C) 수학 연산

D) 내 질문의 소스에 대한 빠른 (오픈 소스 ^^) 라이브러리 어쩌면 이미 거기는 기본적으로 : I는 .NET Framework 자체가 이미 매우 최적화 된 제공한다고 가정 한 Math-Class 나 배열을 처리하는 것과 같은 기본적인 작업을위한 코드/컴파일 결과를 얻었고 나 자신의 코드를 작성하여 얼마나 많은 이익을 얻을지 조금 놀랐습니다. C#에서 직접 볼 수있는 다른 "일반적인"필드 또는 다른 것이 C#을 직접 신뢰할 수 없습니다.

+6

나는 4 * 4 * 4 * 4 * 4 * 4가 컴파일 시간에 평가 될 것이라고 생각한다. 따라서 그것은 매우 빠르다. – Nick

+0

대부분의 사람들은 100ms 정도는 큰 문제가 아니라고 생각합니다. C#은 대부분의 사람들이 사용하는 응용 프로그램의 첫 번째 선택이 아닙니다. – Ian

+1

큰 숫자로 테스트 했습니까? 나는 Math.Pow가 더 큰 지수에 최적화되어 있다고 생각할 것입니다. x^7 == x^{3 + 3 + 1} == {x^3 + x^3 x}, 이것은 실행 중일 것입니다. 순서는 거칠다 O (log (n)), 솔루션은 O (n)이고, 큰 지수의 경우 훨씬 느릴 것이다. – markijbema

답변

0

코드 라인을 100 만회 반복하면 거의 모든 세부 사항이 달라집니다.

Math.Pow()는 수동 4 * 4 ... * 4 예제보다 상당히 느린 함수 호출입니다.

표준 수학 수업보다 더 최적화 된 것을 쓸 수 있을지 의심 스럽기 때문에 자신의 수업을 작성하지 마십시오.

1

첫째, 정수 연산은 부동 소수점보다 더 빠르게 입니다. 부동 소수점 값이 필요하지 않으면 부동 소수점 데이터 유형을 사용하지 마십시오. 이것은 모든 프로그래밍 언어에 대해 사실입니다.

두 번째로, 자신이 말했듯이 Math.Pow이 실제 처리 할 수 ​​있습니다. 간단한 루프보다 훨씬 복잡한 알고리즘을 사용합니다. 단순히 루핑하는 것보다 느리다는 것은 당연합니다. 루프를 없애고 곱셈을 n 번 수행하면 루프를 설정하는 오버 헤드가 줄어들어 더욱 빨라집니다. 그러나 루프를 사용하지 않는 경우 사전에 지수의 값인 을 알아야합니다. 런타임에 제공 할 수 없습니다.

나는 왜 Math.ExpMath.Log이 더 빠를 지 모르겠습니다. 그러나 Math.Log을 사용하면 음수의 값을 찾을 수 없습니다.

기본적으로 int은 빠르며 회피 루프는 여분의 오버 헤드를 방지합니다. 그러나 당신이 그 사람들을 위해 갈 때 유연성을 잃어 버리고 있습니다. 그러나 필요한 모든 것이 정수인 경우 실수를 피하는 것이 좋습니다. 그러나이 경우에는 이미 존재하는 사용자 정의 함수를 코딩하는 것이 너무 많은 것 같습니다.

당신이 스스로에게 물어야 할 질문은 이것이 그만한 가치가 있는지의 여부입니다. Math.Pow 실제로 프로그램 속도가 느려 집니까? 그리고 어쨌든 귀하의 언어로 이미 번들 된 Math.Pow은 종종 가장 빠르거나 아주 가깝습니다. 정말로 일반적인 용도 (정수, 양수 값 등에 국한되지 않음) 인 대체 구현을 실제로 만들고 싶다면 어쨌든 기본 구현에 사용 된 동일한 알고리즘을 사용하게 될 것입니다. 마음에 부담

+1

대답에 대한 일반적인 견해에 동의하지만, 한 가지 말하고 싶습니다. 물론 라이브러리 함수 함수는 최적화되어 있지만 모든 경우에 대해 항상 최적화 할 수있는 것은 아닙니다. 알고리즘에 대한 유효한 옵션이 많이있는 인스턴스 정렬을 고려해보십시오. 실제로는 어떤 특정 데이터가 가장 적합한 지에 따라 달라집니다. – markijbema

+0

@markijbema : 그렇기 때문에 제 대답에 "일반적인 목적"이라는 단어를 사용했습니다. 데이터에 대한 추가 가정을 할 수 있다면 (예 : 항상 정수 또는 지정된 범위 내에 있음) 물론이를 사용하여 최적화 할 수 있습니다 (예 : quicksort 대신 계산 방식). 그게 내 대답의 요점이다. 범용 기능의 경우 라이브러리와 일치시키기가 어렵다. – MAK

4

두 가지 :

  1. 코드의 당신은 아마 don't need to optimise이 비트. 함수 호출에 1 초도 안 걸렸습니다. 이것이 프로그램에서 큰 문제를 일으킬 것입니까?

  2. Math.Pow 어쨌든 매우 적절할 것입니다. 추측 해 보면, 더 낮은 수준의 언어로 작성된 적절한 숫자 라이브러리를 호출하게 될 것입니다. 즉, 주문 증가를 기대해서는 안됩니다.

  3. 숫자 프로그래밍은 생각보다 어렵습니다. 계산 방법을 알고 있다고 생각하는 알고리즘조차도 그렇게 계산되지 않습니다. 예를 들어 평균을 계산할 때 숫자를 더하고 숫자의 개수로 나눠서는 안됩니다. (현대 수치 라이브러리는 점 오류를 떠 보정하기 위해 두 개의 패스 루틴을 사용합니다.) 당신이 확실히 최적화해야 할 것을 결정하는 경우, 다음 소수점 값을 정수를 사용하기보다는 부동 고려했다

, 또는 아웃소싱 이것을 다른 숫자 라이브러리로 옮긴다.