x=x+1 대x + = 1
저는 이 두 명령이 같은 결과, 즉 X를 1씩 증가시키지만 후자가 아마도 더 효율적일 것이라고 생각합니다.
만약 이것이 정확하지 않다면, diff를 설명해주세요.
만약 그것이 맞다면, 왜 후자가 더 효율적이어야 합니까?둘 다 같은 IL로 컴파일해야 하지 않나요?
감사해요.
MSDN 라이브러리에서 +=:
이 연산자를 사용하는 것은 결과가 한 번만 평가된다는 점을 제외하고는 결과 = 결과 + 식을 지정하는 것과 거의 같습니다.
따라서 이들은 동일하지 않으므로 x += 1이 더 효율적입니다.
업데이트: 제 MSDN 라이브러리 링크가 동일한 인용문이 포함되지 않은 VB 페이지가 아닌 JScript 페이지에 있다는 것을 방금 알게 되었습니다.
따라서 추가적인 연구와 테스트를 통해 이 답변은 VB.NET에는 적용되지 않습니다.잘못했습니다.다음은 샘플 콘솔 앱입니다.
Module Module1
Sub Main()
Dim x = 0
Console.WriteLine(PlusEqual1(x))
Console.WriteLine(Add1(x))
Console.WriteLine(PlusEqual2(x))
Console.WriteLine(Add2(x))
Console.ReadLine()
End Sub
Public Function PlusEqual1(ByVal x As Integer) As Integer
x += 1
Return x
End Function
Public Function Add1(ByVal x As Integer) As Integer
x = x + 1
Return x
End Function
Public Function PlusEqual2(ByVal x As Integer) As Integer
x += 2
Return x
End Function
Public Function Add2(ByVal x As Integer) As Integer
x = x + 2
Return x
End Function
End Module
PlusEqual1과 Add1의 IL은 실제로 동일합니다.
.method public static int32 Add1(int32 x) cil managed
{
.maxstack 2
.locals init (
[0] int32 Add1)
L_0000: nop
L_0001: ldarg.0
L_0002: ldc.i4.1
L_0003: add.ovf
L_0004: starg.s x
L_0006: ldarg.0
L_0007: stloc.0
L_0008: br.s L_000a
L_000a: ldloc.0
L_000b: ret
}
PlusEqual2 및 Add2의 IL은 다음과 거의 같습니다.
.method public static int32 Add2(int32 x) cil managed
{
.maxstack 2
.locals init (
[0] int32 Add2)
L_0000: nop
L_0001: ldarg.0
L_0002: ldc.i4.2
L_0003: add.ovf
L_0004: starg.s x
L_0006: ldarg.0
L_0007: stloc.0
L_0008: br.s L_000a
L_000a: ldloc.0
L_000b: ret
}
간단한 콘솔 앱을 작성했습니다.
static void Main(string[] args)
{
int i = 0;
i += 1;
i = i + 1;
Console.WriteLine(i);
}
저는 Reflector를 사용하여 분해했고 다음과 같은 결과를 얻었습니다.
private static void Main(string[] args)
{
int i = 0;
i++;
i++;
Console.WriteLine(i);
}
그들은 같습니다.
그들은 동일하게 컴파일하고, 두 번째는 타이핑하기가 더 쉽습니다.
중요:
한 답은 정확합니다.+=
도, 일반적인 언어로.에서는 VB를 하만지라고 합니다.NET에서는, 제가 봤을 때는.X
OP에 지정된 것은 변수 또는 속성입니다.
그들은 아마 같은 IL로 컴파일될 것입니다.
업데이트(아마도 발생할 수 있는 논란 해결):
언어의 입니다.VB.NET은 프로그래밍 언어입니다.사양에 정의된 내용을 준수하는 컴파일러는 VB.NET 구현이 될 수 있습니다.하여 MS VB에 대한 를 생성하는 .NET 컴파일러의 소스 코드를 편집하여 다음에 대한 크래피 코드를 생성하는 경우X += 1
예를 들어, VB.NET 사양을 여전히 준수할 것입니다(VB.NET 사양에는 작동 방식에 대한 설명이 없었기 때문입니다).그것은 단지 효과가 정확히 같을 것이라고 말하고, 이것은 실제로 동일한 코드를 생성하는 것을 논리적으로 만듭니다.)
컴파일러가 두 가지 모두에 대해 동일한 코드를 생성할 가능성이 매우 높지만(나는 실제로 그렇게 생각합니다) 꽤 복잡한 소프트웨어입니다.이런, 당신은 컴파일러가 같은 코드를 두 번 컴파일할 때 정확히 같은 코드를 생성한다는 보장조차 할 수 없습니다!
컴파일러의 소스 코드를 자세히 알지 못하는 한 100% 안전하다고 느낄 수 있는 것은 훌륭한 컴파일러가 성능 면에서 동일한 코드를 생성해야 한다는 것입니다. 이는 정확히 동일한 코드일 수도 있고 아닐 수도 있습니다.
정말 많은 추측들!심지어 Reflector와 관련된 결론도 분해하는 동안 최적화를 수행할 수 있기 때문에 반드시 사실은 아닙니다.
그럼 왜 아무도 IL 코드를 조사하지 않는 겁니까?다음 C# 프로그램을 살펴보십시오.
static void Main(string[] args)
{
int x = 2;
int y = 3;
x += 1;
y = y + 1;
Console.WriteLine(x);
Console.WriteLine(y);
}
이 코드 조각은 다음 항목을 컴파일합니다.
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 25 (0x19)
.maxstack 2
.locals init ([0] int32 x,
[1] int32 y)
// some commands omitted here
IL_0004: ldloc.0
IL_0005: ldc.i4.1
IL_0006: add
IL_0007: stloc.0
IL_0008: ldloc.1
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stloc.1
// some commands omitted here
}
보시다시피, 사실은 완전히 똑같습니다.왜 그럴까요?IL의 목적은 어떻게 해야 하는지가 아니라 무엇을 해야 하는지를 알려주는 것이기 때문입니다.최적화는 JIT 컴파일러의 작업이 될 것입니다.근데 VB에서도 마찬가지야.그물
x86에서 x가 레지스터 eax에 있으면 둘 다 다음과 같은 결과를 초래합니다.
그래서 당신 말이 맞아요, 편집 단계가 끝나면 IL도 똑같을 거예요.
이와 같은 질문에는 "최적화 도구를 신뢰하라"는 질문이 있습니다.
유명한 신화는
x++;
보다 효율성이 떨어집니다.
++x;
임시 값을 저장해야 하기 때문입니다.임시 값을 사용하지 않으면 최적화 도구가 해당 저장소를 제거합니다.
- 네, 그들은 똑같이 행동합니다.
- 아니요, 그들은 아마도 똑같이 효율적일 것입니다.옵티마이저는 그런 것에 능합니다.더블 체크를 원하시면 최적화된 코드를 작성하여 리플렉터에서 확인하시기 바랍니다.
x가 int 또는 float와 같은 단순한 유형인 경우 최적화 도구는 동일한 결과를 생성할 수 있습니다.
만약 당신이 다른 언어(여기서 제한된 VB 지식, +=?)를 사용한다면, 여기서 x는 하나의 큰 경적 객체일 수 있고, 전자는 수백 메그가 될 수 있는 여분의 복사본을 만들 수 있습니다.후자는 그렇지 않습니다.
똑같습니다.
x=x+1
수학적인 것은 모순으로 보이는 반면에.
x+=1
그렇지도 않고 가볍게 입력할 수 있습니다.
VB에서는 동일할 수 있지만 C(측정 시스템의 출처)에서는 동일할 필요가 없습니다.
C++에서는 데이터 유형이 x이고 연산자가 어떻게 정의되는지에 따라 달라집니다.x가 일부 클래스의 인스턴스인 경우 완전히 다른 결과를 얻을 수 있습니다.
아니면 문제를 수정하고 x가 정수인지 지정해야 합니다.
나는 그 차이가 메모리 참조에 사용되는 추가 클럭 주기 때문이라고 생각했지만, 내가 틀린 것으로 드러났습니다! 나는 이것을 이해할 수 없습니다.
instruction type example cycles
===================================================================
ADD reg,reg add ax,bx 1
ADD mem,reg add total, cx 3
ADD reg,mem add cx,incr 2
ADD reg,immed add bx,6 1
ADD mem,immed add pointers[bx][si],6 3
ADD accum,immed add ax,10 1
INC reg inc bx 1
INC mem inc vpage 3
MOV reg,reg mov bp,sp 1
MOV mem,reg mov array[di],bx 1
MOV reg,mem mov bx,pointer 1
MOV mem,immed mov [bx],15 1
MOV reg,immed mov cx,256 1
MOV mem,accum mov total,ax 1
MOV accum,mem mov al,string 1
MOV segreg,reg16 mov ds,ax 2, 3
MOV segreg,mem16 mov es,psp 2, 3
MOV reg16,segreg mov ax,ds 1
MOV mem16,segreg mov stack_save,ss 1
MOV reg32,controlreg mov eax,cr0 22
mov eax,cr2 12
mov eax,cr3 21, 46
mov eax,cr4 14
MOV controlreg,reg32 mov cr0,eax 4
MOV reg32,debugreg mov edx,dr0 DR0-DR3,DR6,DR7=11;
DR4,DR5=12
MOV debugreg,reg32 mov dr0,ecx DR0-DR3,DR6,DR7=11;
DR4,DR5=12
출처:http://sshot_sshot.tripod.com/trdos/pentium.txt
지침은 다음과 같이 번역할 수 있습니다.
;for i = i+1 ; cycles
mov ax, [i] ; 1
add ax, 1 ; 1
mov [i], ax ; 1
;for i += 1
; dunno the syntax of instruction. it should be the pointers one :S
;for i++
inc i ; 3
;or
mov ax, [i] ; 1
inc ax ; 1
mov [i], ax ; 1
;for ++i
mov ax, [i] ; 1
;do stuff ; matters not
inc ax ; 1
mov [i], ax ; 1
모두 동일한 것으로 나타났습니다. 도움이 될 수 있는 몇 가지 데이터만 있습니다.댓글 달아주세요!
주의할 점은 +=, -=, *= 등이 암시적 캐스트를 한다는 것입니다.
int i = 0;
i = i + 5.5; // doesn't compile.
i += 5.5; // compiles.
실행 시간(최소한 PERL 사용 시)에는 차이가 없습니다.x+=1은 x=x+1보다 입력 속도가 약 0.5초 빠릅니다.
프로그래밍 효율성에는 차이가 없고 타이핑 효율성만 있습니다.
1980년대 초, Lattice C 컴파일러의 정말 멋진 최적화 중 하나는 "x = x + 1;", "x + = 1;", "x + + +;" 모두 정확히 동일한 기계 코드를 생성했다는 것입니다.만약 그들이 그것을 할 수 있다면, 이 밀레니엄으로 작성된 컴파일러는 분명히 그것을 할 수 있을 것입니다.
x가 단순 정수 스칼라 변수인 경우에는 동일해야 합니다.
만약 x가 큰 표현식이라면, 부작용이 있을 수 있습니다.+=1
그리고.++
두 배 더 빨라야 합니다.
많은 사람들이 이런 종류의 낮은 수준의 최적화에 집중합니다. 마치 그것이 최적화의 전부인 것처럼 말입니다.훨씬 더 큰 주제라는 것을 알고 계실 겁니다.
언급URL : https://stackoverflow.com/questions/808062/x-x1-vs-x-1
'source' 카테고리의 다른 글
Node.js가 종료되기 직전 정리 작업 수행 (0) | 2023.05.21 |
---|---|
기존 Git 저장소를 SVN으로 푸시 (0) | 2023.05.21 |
Node.js를 백그라운드 프로세스로 실행하고 절대 죽지 않는 방법은 무엇입니까? (0) | 2023.05.21 |
Microsoft를 사용하여 Excel에서 데이터 세트로 가져오는 방법사무실. 인터럽트.엑셀? (0) | 2023.05.21 |
Angular routerLink가 해당 구성 요소로 이동하지 않습니다. (0) | 2023.05.21 |