문제

기존 애플리케이션을 C#로 포팅하고 있으며 가능한 한 성능을 향상시키고 싶습니다. 기존의 많은 루프 카운터 및 배열 참조는 시스템으로 정의됩니다.

UINT32 vs int32를 사용하는 데 중요한 성능 차이가 있습니까?

도움이 되었습니까?

해결책

프로세서 수준에서 서명 된 산술과 서명되지 않은 산술 사이의 가능한 차이 외에는 성능 고려 사항이 있다고 생각하지 않지만 그 시점에서 차이점은 무의미하다고 생각합니다.

서명되지 않은 유형이 모든 언어가 지원하는 것은 아니기 때문에 CLS를 준수하지 않기 때문에 더 큰 차이는 CLS 규정 준수에 있습니다.

다른 팁

짧은 대답은 "아니요. 성능 영향은 무시할 수 있습니다"입니다.

정답은 "의존합니다"입니다.

더 좋은 질문은 "표시가 필요하지 않을 때 UINT를 사용해야합니까?"입니다.

성능과 관련하여 결정적인 "예"또는 "아니오"를 제공 할 수없는 이유는 대상 플랫폼이 궁극적으로 성능을 결정하기 때문입니다. 즉, 성능은 코드를 실행할 프로세서와 사용 가능한 지침에 의해 지시됩니다. .NET 코드가 컴파일됩니다 중간 언어 (IL 또는 바이트 코드). 그런 다음이 지침은 방금 (JIT) 컴파일러의 일부로 일반적인 언어 런타임 (clr). 모든 사용자에 대해 어떤 코드가 생성 될지 제어하거나 예측할 수 없습니다.

따라서 하드웨어가 성능의 최종 중재자라는 것을 알면, ".NET가 서명되지 않은 정수와 서명되지 않은 정수에 대해 .net이 생성하는 코드는 얼마나 다릅니 까?" "차이가 내 응용 프로그램과 대상 플랫폼에 영향을 미칩니 까?"

이러한 질문에 답하는 가장 좋은 방법은 테스트를 실행하는 것입니다.

class Program
{
  static void Main(string[] args)
  {
    const int iterations = 100;
    Console.WriteLine($"Signed:      {Iterate(TestSigned, iterations)}");
    Console.WriteLine($"Unsigned:    {Iterate(TestUnsigned, iterations)}");
    Console.Read();
  }

  private static void TestUnsigned()
  {
    uint accumulator = 0;
    var max = (uint)Int32.MaxValue;
    for (uint i = 0; i < max; i++) ++accumulator;
  }

  static void TestSigned()
  {
    int accumulator = 0;
    var max = Int32.MaxValue;
    for (int i = 0; i < max; i++) ++accumulator;
  }

  static TimeSpan Iterate(Action action, int count)
  {
    var elapsed = TimeSpan.Zero;
    for (int i = 0; i < count; i++)
      elapsed += Time(action);
    return new TimeSpan(elapsed.Ticks / count);
  }

  static TimeSpan Time(Action action)
  {
    var sw = new Stopwatch();
    sw.Start();
    action();
    sw.Stop();
    return sw.Elapsed;
  }
}

두 가지 테스트 방법, 테스트 디자인 그리고 testununsigned, 각각 서명 된 정수 및 서명되지 않은 정수에서 간단한 증분을 각각 ~ 2 백만 개의 반복을 수행합니다. 테스트 코드는 각 테스트의 100 회 반복을 실행하고 결과를 평균화합니다. 이것은 잠재적 인 불일치를 제거해야합니다. x64 용으로 컴파일 된 i7-5960X의 결과는 다음과 같습니다.

Signed:      00:00:00.5066966

Unsigned:    00:00:00.5052279

이러한 결과는 거의 동일하지만 결정적인 답변을 얻으려면 프로그램을 위해 생성 된 바이트 코드를 실제로 살펴 봐야합니다. 우리는 사용할 수 있습니다 ildasm .NET SDK의 일부로 컴파일러가 생성 한 어셈블리에서 코드를 검사합니다.

Bytecode

여기서, 우리는 C# 컴파일러가 서명 된 정수를 선호하고 실제로 대부분의 작업을 서명 된 정수로 기본적으로 수행하며 분기 (일명 점프 또는 IF)를 비교할 때 메모리 값을 서명하지 않은 것으로 취급합니다. 반복자와 축적기 모두에 서명되지 않은 정수를 사용하고 있다는 사실에도 불구하고 testununsigned, 코드는 거의 동일합니다 테스트 디자인 단일 명령을 제외한 방법 : IL_0016. the를 빠르게 볼 수 있습니다 ECMA 사양 차이점을 설명합니다.

blt.un.s : (서명되지 않거나 정렬되지 않은), 짧은 형태보다 적은 경우 대상 지점.

BLT.S : 짧은 형태보다 적은 경우 대상 지점.

이러한 일반적인 지시이기 때문에 대부분의 최신 고전력 프로세서는 두 작업에 대한 하드웨어 지침을 가지고 있으며 동일한 수의 주기로 실행 가능성이 높다고 가정하는 것이 안전합니다. 이것은 보장되지 않습니다. 저전력 프로세서에는 지침이 적고 서명되지 않은 int에 대한 분기가 없을 수 있습니다. 이 경우 JIT 컴파일러는 여러 하드웨어 지침 (먼저 변환, 지점)을 방출하여 blt.un.s IL 교육. 이 경우에도 이러한 추가 지침은 기본적이며 성능에 크게 영향을 미치지 않을 것입니다.

따라서 성능 측면에서 긴 대답은 "서명 된 정수를 사용하거나 서명되지 않은 정수 사이에 성능 차이가있을 가능성은 낮습니다. 차이가 있으면 무시할 수 있습니다."

그렇다면 성능이 동일하다면 다음 논리적 질문은 "내가 확신 할 때 서명되지 않은 값을 사용해야한다면 필요 표시?"

여기에는 고려해야 할 두 가지가 있습니다. 첫째, 부호없는 정수는 아닙니다. CLS 준수, 다른 프로그램이 소비 할 API의 일부로 서명되지 않은 정수를 노출시키는 경우 (예 : 재사용 가능한 라이브러리를 배포하는 경우) 문제가 발생할 수 있음을 의미합니다. 둘째, BCL에 의해 노출 된 메소드 서명 (위의 이유)을 포함하여 .NET에서 대부분의 작업은 서명 된 정수를 사용합니다. 따라서 실제로 서명되지 않은 정수를 사용할 계획이라면 자신이 꽤 많이 캐스팅 할 수 있습니다. 이것은 매우 작은 성능에 맞을 것이며 코드를 조금 더 지저분하게 만들 것입니다. 결국, 그것은 아마 그만한 가치가 없을 것입니다.

tldr; 내 C ++ 일로 돌아와서, 나는 "가장 적합한 것을 사용하고 컴파일러가 나머지를 분류하게하십시오"라고 말하고 싶습니다. C#은 컷 앤 건조하지 않기 때문에 .NET에 대해 이것을 말할 것입니다. x86/x64의 서명 된 정수와 서명되지 않은 정수 사이에는 성능 차이가 없지만 대부분의 작업에는 서명 된 정수가 필요하므로 실제로 필요하지 않으면 실제로 필요하지 않습니다. 값을 양수로 제한하거나 부호 비트가 먹는 여분의 범위가 필요하고 서명 된 정수를 고수하십시오. 결국 코드는 더 깨끗합니다.

.NET의 문제에 대한 연구를하지 않았지만 Win32/C ++의 옛날에는 "서명 된 int"를 "서명 된 긴"에 캐스팅하려면 CPU가 연장을 위해 OP를 실행해야했습니다. 그 신호. "서명되지 않은 int"를 "부호없는 긴"에 시전하려면 상단 바이트에 0이 있습니다. 저축은 몇 번의 클럭주기 순서에있었습니다 (즉, 인식 할 수있는 차이를 갖기 위해서는 수십억 번해야합니다).

차이가없고 성능은 현명합니다. 간단한 정수 계산은 잘 알려져 있으며 최신 CPU는 신속하게 수행하도록 최적화되어 있습니다.

이러한 유형의 최적화는 노력의 가치가 거의 없습니다. 작업에 가장 적합한 데이터 유형을 사용하여 그대로 두십시오. 데이터베이스를 터치하는 것만 큼 DB 디자인, 쿼리 구문 또는 인덱싱 전략에서 C#의 코드 최적화를 수백 크기로 상쇄 할 수있는 수십 개의 조정을 찾을 수 있습니다.

그것은 동일한 양의 메모리를 어느 쪽이든 할당하려고합니다 (부호를 위해 공간을 절약하지 않기 때문에 더 큰 값을 저장할 수 있지만). 따라서 하나의 옵션이나 다른 옵션이 폭발 할 수있는 큰 값 / 음수 값을 사용하지 않는 한 '성능'차이를 보게 될 것입니다.

이것은 실제로 루프 카운터의 성능 요구 사항과 관련이 없습니다.

prehaps 완료해야 할 반복이 많이있었습니다

        Console.WriteLine(Int32.MaxValue);      // Max interation 2147483647
        Console.WriteLine(UInt32.MaxValue);     // Max interation 4294967295

서명되지 않은 int는 이유가있을 수 있습니다.

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