문제

동적 코드 생성으로 성능을 향상시킬 수있는 방법에 대한 아이디어가 있지만이 문제에 접근하는 가장 좋은 방법이 확실하지 않습니다.

수업이 있다고 가정 해 봅시다


class Calculator
{
  int Value1;
  int Value2;
  //.......... 
  int ValueN;

  void DoCalc()
  {
    if (Value1 > 0)
    {
      DoValue1RelatedStuff();    
    }
    if (Value2 > 0)
    {
      DoValue2RelatedStuff();    
    }
    //....
    //....
    //....
    if (ValueN > 0)
    {
      DoValueNRelatedStuff();    
    }
  }
}

DOCALC 방법은 가장 낮은 수준이며 계산 중에 여러 번 호출됩니다. 또 다른 중요한 측면은 Valuen이 처음에만 설정되어 계산 중에 변경되지 않는다는 것입니다. 많은 valuen이 0이므로 DOCALC 방법의 많은 IFS가 불필요합니다. 따라서 동적 코드 생성이 성능을 향상시키는 데 도움이되기를 바랐습니다.

예를 들어 메소드를 작성하는 경우


  void DoCalc_Specific()
  {
    const Value1 = 0;
    const Value2 = 0;
    const ValueN = 1;

    if (Value1 > 0)
    {
      DoValue1RelatedStuff();    
    }
    if (Value2 > 0)
    {
      DoValue2RelatedStuff();    
    }
    ....
    ....
    ....
    if (ValueN > 0)
    {
      DoValueNRelatedStuff();    
    }
  }

그리고 C# 컴파일러를 켜는 최적화로 컴파일하는 것은 필요한 것들만 유지하기에 충분히 똑똑합니다. 따라서 Valuen 값을 기반으로 실행 시간에 그러한 방법을 만들고 계산 중에 생성 된 방법을 사용하고 싶습니다.

나는 그것을 위해 표현 나무를 사용할 수 있다고 생각하지만, 표현 나무는 단순한 람다 기능으로 만 작동하므로 기능 본문 내부에서 IF 등을 사용할 수 없습니다. 따라서이 경우이 방법을 적절한 방식으로 변경해야합니다.

또 다른 가능성은 필요한 코드를 문자열로 만들고 동적으로 컴파일하는 것입니다. 그러나 기존 방법을 취하고 그에 따라 수정할 수 있다면 훨씬 나을 것입니다.

반사도 있습니다.

BTW. 나는 c#에만 국한되지 않습니다. 그래서 저는 이런 종류의 문제에 가장 적합한 프로그래밍 언어의 제안에 개방적입니다. 몇 가지 이유로 LISP를 제외하고.

하나의 중요한 설명. DoValue1RelatedStuff ()는 내 알고리즘에서 메소드 호출이 아닙니다. 그것은 단지 일부 공식 기반 계산 일 뿐이며 매우 빠릅니다. 나는 이렇게 썼어 야 했어


if (Value1 > 0)
{
  // Do Value1 Related Stuff
}

성능 테스트를 실행했으며 하나의 IF가 비활성화 된 경우 최적화 된 방법이 중복 IF보다 약 2 배 빠릅니다.

테스트에 사용한 코드는 다음과 같습니다.


    public class Program
    {
        static void Main(string[] args)
        {
            int x = 0, y = 2;

            var if_st = DateTime.Now.Ticks;
            for (var i = 0; i  < 10000000; i++)
            {
                WithIf(x, y);
            }
            var if_et = DateTime.Now.Ticks - if_st;
            Console.WriteLine(if_et.ToString());

            var noif_st = DateTime.Now.Ticks;
            for (var i = 0; i  < 10000000; i++)
            {
                Without(x, y);
            }
            var noif_et = DateTime.Now.Ticks - noif_st;
            Console.WriteLine(noif_et.ToString());

            Console.ReadLine();

        }

        static double WithIf(int x, int y)
        {
            var result = 0.0;
            for (var i = 0; i  < 100; i++)
            {
                if (x > 0)
                {
                    result += x * 0.01;
                }
                if (y > 0)
                {
                    result += y * 0.01;
                }
            }
            return result;
        }

        static double Without(int x, int y)
        {
            var result = 0.0;
            for (var i = 0; i < 100; i++)
            {
                result += y * 0.01;
            }
            return result;
        }
    }
도움이 되었습니까?

해결책

나는 보통 그러한 최적화에 대해 생각조차하지 않을 것입니다. 얼마나 많은 일이 있습니다 DoValueXRelatedStuff() 하다? 10 ~ 50 개 이상의 프로세서주기? 예? 즉, 10% 미만의 실행 시간을 절약하기 위해 상당히 복잡한 시스템을 구축한다는 것을 의미합니다 (그리고 이것은 나에게 상당히 낙관적 인 것 같습니다). 이것은 쉽게 1%이하로 내려갈 수 있습니다.

다른 최적화의 여지가 없습니까? 더 나은 알고리즘? 단일 프로세서주기 만 취하는 단일 분기를 제거해야합니까 (분기 예측이 올바른 경우)? 예? .NET을 사용하는 대신 코드를 어셈블러로 작성하거나 다른 기계에 구체적이라고 생각하지 않아야합니까?

당신은의 순서를 줄 수 있습니까? N, 일반적인 방법의 복잡성과 일반적으로 진실로 평가하는 표현의 비율?

다른 팁

평가의 오버 헤드가 만약에 진술은 코드를 동적으로 방출하려는 노력의 가치가 있습니다.

현대 CPU의 지원 지점 예측 그리고 분기 예측, 코드 접근법의 작은 세그먼트에서 분기의 오버 헤드가 0을 만듭니다.

코드의 두 개의 손으로 코드 된 두 버전을 벤치마킹하려고 시도 했습니까?

당신이 실제로 코드 최적화에 빠지면 - 당신이 무엇이든하기 전에 - 프로파일 러를 실행하십시오! 병목 현상이 어디에 있고 어떤 영역이 최적화 할 가치가 있는지 보여줍니다.

또한 - 언어 선택이 제한되지 않으면 (LISP를 제외하고) 성능 측면에서 어셈블러를 이길 수는 없습니다.)

어셈블러를 사용하여 내부 기능을 다시 작성하여 성능 마법을 달성 한 것을 기억합니다.

무엇이든하기 전에 실제로 문제가 있습니까??

즉, 당신을 괴롭힐 정도로 오래 걸리나요?

그렇다면 실제로 시간이 걸리는 것이 무엇인지 알아보십시오. 당신이 추측하는 것이 아닙니다. 이것 시간이 어디로 가는지 보는 데 사용하는 빠르고 더럽고 효과적인 방법입니다.

이제 해석 대 컴파일에 대해 이야기하고 있습니다. 해석 된 코드는 일반적으로 컴파일 된 코드보다 1 배의 순서가 느립니다. 그 이유는 통역사가 다음에 무엇을 해야하는지 지속적으로 알아 내기 때문입니다. 그리고 잊어 버렸습니다, 컴파일 된 코드 그냥 알고 있습니다.

당신 이이 상황에 있다면, 컴파일 된 코드의 속도를 얻기 위해 번역 가격을 지불하는 것이 합리적 일 수 있습니다.

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