this answer (성능에 대해 정수 곱하기/나누기보다 비트 시프트 연산자를 사용하는 것이 좋습니다)에 대한 의견에서이 코드가 실제로 더 빠를 지 여부를 묻습니다. 내 마음의 뒤쪽에 일부 수준에서 수준, 뭔가가 작동 할 정도로 영리하다는 생각은 그 >> 1
과 / 2
같은 작업입니다. 그러나, 나는 이것이 실제로 사실인지 궁금하다. 그렇다면 그것이 어떤 수준으로 발생하는지 궁금하다.주어진 C#/CIL에 대해 theJITter가 생성 한 원시 코드를 볼 수있는 방법이 있습니까?
IL_0000: ldarg.0
IL_0001: ldc.i4.2
IL_0002: div
IL_0003: ret
} // end of method Program::Divider
IL_0000: ldarg.0
IL_0001: ldc.i4.1
IL_0002: shr
IL_0003: ret
} // end of method Program::Shifter
대 그래서 C# 컴파일러는
div
방출된다
테스트 프로그램은 각각 분할하고 이들 인자를 전환하는 두 가지 방법에 대해 (ON optimize
)와 다음 비교 CIL을 생산 또는 shr
명령을 따르지 않아도됩니다. 이제는 JITter가 생성하는 실제 x86 어셈블러를보고 싶지만이 작업을 수행하는 방법을 모릅니다. 심지어 가능할까요? 그것은 그 디버거 옵션에 대한 주요 정보가 포함되어있어
편집는 nobugz에서 하나를 수락, 답변을
조사 결과
감사를 추가 할 수 있습니다. 무엇 결국 나를 위해 일한 것은 :
- 스위치는
- 같은 장소 (이 JIT 최적화 할 수 있도록 우리가 원하는 즉),
Tools | Options | Debugger
에서 구성 - 을 해제 스위치 오프 모듈로드에 JIT 최적화를 억제 '하는,
- 곳
- 어셈블리를 제작 해보세요
Debugger.Break()
문을 착용 할 것 (즉, 우리가 모든 코드를 디버깅 할) '내 코드 만 사용 스위치 오프 - 한 .exe를 실행하고 휴식 할 때, 디버그 인스턴스 VS 기존를 사용
- 이제 분해 윈도우가 당신에게
결과는 적어도 말을 계몽했다 실행될 것 실제 86를 보여줍니다 - 실제로 JITter가 산술 연산을 수행 할 수 있습니다. 디스 어셈블리 창에서 편집 된 샘플이 있습니다. 다양한 -Shifter
메서드는 >>
을 사용하여 2의 제곱으로 나눕니다. 다양한 -Divider
방법은 방법은 인라인되지 않은 두 정적으로 2 분주 /
Console.WriteLine(string.Format("
{0}
shift-divided by 2: {1}
divide-divided by 2: {2}",
60, TwoShifter(60), TwoDivider(60)));
00000026 mov dword ptr [edx+4],3Ch
...
0000003b mov dword ptr [edx+4],1Eh
...
00000057 mov dword ptr [esi+4],1Eh
를 사용하여 정수에 의해 분할하지만, 실제 계산은와
Console.WriteLine(string.Format("
{0}
divide-divided by 3: {1}",
60, ThreeDivider(60)));
00000085 mov dword ptr [esi+4],3Ch
...
000000a0 mov dword ptr [esi+4],14h
같은 지터에 의해 수행되었다 정적으로 3으로 나누기.
Console.WriteLine(string.Format("
{0}
shift-divided by 4: {1}
divide-divided by 4 {2}",
60, FourShifter(60), FourDivider(60)));
000000ce mov dword ptr [esi+4],3Ch
...
000000e3 mov dword ptr [edx+4],0Fh
...
000000ff mov dword ptr [esi+4],0Fh
및 4로 정적으로 나눕니다.
최고 : 그런 다음 인라인 및 것
Console.WriteLine(string.Format("
{0}
n-divided by 2: {1}
n-divided by 3: {2}
n-divided by 4: {3}",
60, Divider(60, 2), Divider(60, 3), Divider(60, 4)));
0000013e mov dword ptr [esi+4],3Ch
...
0000015b mov dword ptr [esi+4],1Eh
...
0000017b mov dword ptr [esi+4],14h
...
0000019b mov dword ptr [edi+4],0Fh
이 모든 정적 분열을 계산!
결과가 정적이 아닌 경우에는 어떻게해야합니까? 콘솔에서 정수를 읽는 코드를 추가했습니다. 이것은 그의 부문에 대한 생산하는 것입니다 :
Console.WriteLine(string.Format("
{0}
shift-divided by 2: {1}
divide-divided by 2: {2}",
i, TwoShifter(i), TwoDivider(i)));
00000211 sar eax,1
...
00000230 sar eax,1
는 그래서 CIL 다른 임에도 불구하고, 지터는 2로 나누어 것은 1.
Console.WriteLine(string.Format("
{0}
divide-divided by 3: {1}", i, ThreeDivider(i)));
00000283 IDIV EAX에 의해 오른쪽 이동 인 것을 알고, ECX
그리고 당신이 3
Console.WriteLine(string.Format("
{0}
shift-divided by 4: {1}
divide-divided by 4 {2}",
i, FourShifter(i), FourDivider(i)));
000002c5 sar eax,2
...
000002ec sar eax,2
에 의해 분할 분할해야 그리고 알것 알고 WS 4에 의한 분할은 마지막 2
에 의해 오른쪽 이동은 (최고 다시!)입니다 그것은 정적 또는에 따라 방법을 인라인과 일을 할 수있는 최선의 방법을 일했다
Console.WriteLine(string.Format("
{0}
n-divided by 2: {1}
n-divided by 3: {2}
n-divided by 4: {3}",
i, Divider(i, 2), Divider(i, 3), Divider(i, 4)));
00000345 sar eax,1
...
00000370 idiv eax,ecx
...
00000395 sar esi,2
사용 가능한 인수. 좋은.
는 그래서 그래, 어딘가 C# 및 86 사이의 스택, 뭔가 는 >> 1
및 / 2
이 동일한 지 운동 할만큼 영리입니다. C# 컴파일러, JITter 및 CLR을 함께 추가하면 이 훨씬 더 깨끗해집니다. 내 생각에 겸손한 프로그래머로 시도 할 수있는 작은 트릭보다 r이
당신은 우리 모두에게 좋은 결과를 게시 할 수 있습니까? 고마워 :) – flesh