2010-03-08 3 views
8

하나의 성능에 민감한 부분을 제외하고 기본적으로 산술을 검사하고 싶은 프로젝트가 있습니다. 불행히도 VB.Net에는 '확인되지 않은'블록이 없습니다.VB.Net에서 확인되지 않은 정수를 추가하는 가장 빠른 방법은 무엇입니까?

이상적으로 프레임 워크에는 명시 적으로 검사되지 않은 산술을 사용하는 일종의 정수 유형이 있지만 그와 같은 것을 찾지 못했습니다. 표현식 트리에 검사되지 않은 작업에 대한 이진 표현식이 있지만 대리자 오버 헤드가 확인되지 않은 이점을 취소 한 다음 일부가 취소되었습니다.

현재 산술 연산을하기 전에 입력을 UInt64/Int64로 변환하고 다시 변환합니다 (비트 단위로 그리고 범위 내에서). 이는 검사되지 않은 산술보다 약 50 % 더 느립니다 (프로파일 링에 따라).

산술에 민감한 부분을 체크되지 않은 산술로 움직이면 작동 할 수도 있지만, 어셈블리 자체에 모두 과장된 것처럼 보입니다.

+1

이 경우 추가 C# 어셈블리가 잔인 할 수도 있지만 C# 파일 (컴파일러의 일부 명령 줄 매개 변수)에서 모듈을 만든 다음 ILmerge를 사용하여 VB.NET 어셈블리와 병합 할 수도 있습니다. – OregonGhost

답변

2

개인적으로 나는이 어셈블리를 특히 작은 어셈블리가 될 것이므로 자체 어셈블리에 두는 것이 좋은 선택이라고 생각합니다. 이렇게하면 언제든지이 어셈블리를 쉽게 재생할 수 있으므로 유지 보수가 더 쉽습니다. 별도의 어셈블리를 체크하지 않고 플래그를 지정하고 실적에 민감한 코드를 여기에 입력하면됩니다.

+0

VB에서는 검사되지 않은 산술 연산을 수행 할 수 있습니다. 문제는 프로젝트 전체 옵션 (컴파일 탭의 고급 컴파일 옵션에서)입니다. –

+0

@Strilanc : 그럼에도 내 대답을 편집했습니다. 나는 너를위한 별도의 프로젝트를 만들 뿐이다. 중요한 코드를 작성한 다음 참조하십시오. –

+4

나는 약간 다른 점을 보았다 : 나는 체크되지 않은 산술을 사용하여 유형을 작성하고 체크되지 않은 어셈블리에 그것들을 넣었다. 이제 ModByte/ModInt16/ModInt32/ModInt64가 있고 체크되지 않은 어셈블리는 코드를 천천히 흡수하지 않습니다. –

3

나는 이것이 오래되었다는 것을 알고 있지만, 최근에는 선택되지 않은 C# 코드를 변환해야하고 어떻게했는지 공유 할 것이라고 생각했습니다. 순수한 VB 코드이며 범위가 필요할 수 있습니다 (프로젝트 전체 옵션이 아닌).

트릭은 Long 필드와 두 개의 정수 필드가 포함 된 구조를 만드는 것입니다. 그런 다음 StructLayout 및 FieldOffset 특성을 사용하여 긴 정수와 두 정수의 합집합을 만듭니다. 필드는 비공개가 될 수 있습니다. 확장 된 CType 연산자를 사용하여 Long에서 구조로, 구조에서 Integer로 변환합니다 (낮은 정수 값 사용). +, -, *, 등등에 대한 연산자 오버로드를 추가하고 presto! VB에서 검사되지 않은 산술!

정렬 ... 긴 값이 long의 범위를 벗어나면 Strilanc이 지적했듯이 여전히 오버플로됩니다. 그러나 검사되지 않은 많은 상황에서 잘 작동합니다.

다음은 예입니다 :

<StructLayout(LayoutKind.Explicit)> 
Public Structure UncheckedInteger 

    <FieldOffset(0)> 
    Private longValue As Long 
    <FieldOffset(0)> 
    Private intValueLo As Integer 
    <FieldOffset(4)> 
    Private intValueHi As Integer 

    Private Sub New(newLongValue As Long) 
     longValue = newLongValue 
    End Sub 

    Public Overloads Shared Widening Operator CType(value As Long) As UncheckedInteger 
     Return New UncheckedInteger(value) 
    End Operator 

    Public Overloads Shared Widening Operator CType(value As UncheckedInteger) As Long 
     Return value.longValue 
    End Operator 

    Public Overloads Shared Widening Operator CType(value As UncheckedInteger) As Integer 
     Return value.intValueLo 
    End Operator 

    Public Overloads Shared Operator *(x As UncheckedInteger, y As Integer) As UncheckedInteger 
     Return New UncheckedInteger(x.longValue * y) 
    End Operator 

    Public Overloads Shared Operator Xor(x As UncheckedInteger, y As Integer) As UncheckedInteger 
     Return New UncheckedInteger(x.longValue Xor y) 
    End Operator 

    ' Any other operator overload you need... 
End Structure 

이 같은 코드의 구조를 사용

Dim x As UncheckedInteger = 2147483647 
Dim result As Integer = x * 2 ' This would throw OverflowException using just Integers 

Console.WriteLine(result.ToString()) ' -2 

주의하여 계산하지 않는 오버 플로우를 UncheckedInteger에 결과를 할당하기 전에. 동일한 기술을 사용하여 UncheckedShort 및 UncheckedByte 구조체를 생성 할 수 있습니다.

+0

아직도 오버플로가되지 않습니까? long의 범위가 초과 될 때까지 2를 곱하면 어떻게됩니까? –

+0

긴 값이 범위를 벗어나면 게시 한 코드가 확실히 오버플로됩니다. 내 상황에서는 걱정할 필요가 없었습니다.긴 값을 오버플로하는 것이 걱정되면 범위 검사를 항상 추가 할 수 있습니다. –

관련 문제