目标CPU显着影响执行时间

时间:2010-08-13 16:31:22

标签: vb.net visual-studio

最近,我一直在用C ++和VB.NET运行一些测试来比较执行速度。在last thread I posted中,我谈到了我如何遇到C ++执行速度与VB一样快的事实,但是解决了这个问题。现在我正撞在另一面墙上:

我为VB.NET制作了一个DLL来测试这个理论,并在一个程序中比较相同的VB.NET和C ++代码的执行时间。但有趣的是什么? VB.NET的执行时间得到了改进,现在它与C ++的执行时间完全相同。花了一些时间解决这个问题,我发现Visual Studio 2008中高级编译选项中的“目标CPU”选项是罪魁祸首!

由于我正在运行64位Windows 7,因此我认为目标CPU x64会产生最佳执行时间。错误。以下是用于VB.NET的Windows窗体应用程序执行时间的结果,计算高达10,000,000的所有素数并得到它们的总和。

任何CPU:15.231秒

x86:10.858秒

x64:15.236秒

以下是我正在使用的代码,您可以自行测试:

Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim watch As New Stopwatch
    watch.Start()

    Dim maxVal As Long = 10000000
    Dim sumOfPrimes As Long = 0
    For i As Integer = 2 To maxVal
        If (isPrime(i) = True) Then
            sumOfPrimes += i
        End If
    Next
    watch.Stop()
    Console.WriteLine(watch.ElapsedMilliseconds)
    Console.WriteLine("The sum of all the prime numbers below " & maxVal & " is " & sumOfPrimes)
End Sub

Function isPrime(ByVal NumToCheck As Integer) As Boolean
    For i As Integer = 2 To (Math.Sqrt(CDbl(NumToCheck)))
        If (NumToCheck Mod i = 0) Then
            Return False
        End If
    Next
    Return True
End Function

End Class

为什么在运行64位时将目标CPU选为32位会导致性能提升?对此问题的任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:2)

32位和64位模式之间存在许多差异,这可能会以某种方式扭曲性能差异。

在64位模式下,CPU有更多的寄存器,每个寄存器都更大,这使得某些操作的执行速度更快(例如,更高的寄存器数可能会避免存储器访问)

但32位也至少有一个优势:

指针为32位宽,64位模式下为64位。对于严重依赖指针的程序,这可能导致64位模式下显着更高的内存使用率,这意味着程序数据的一小部分将适合CPU缓存,因此在64位模式下性能可能会降低,因此更高的缓存未命中数。

另一个因素是.NET框架在这两方面都不是同样出色。它们在32位和64位版本的CLR之间尚未具有功能奇偶校验,并且对于64位代码,JIT可能也不像32位情况那样进行调整。

答案 1 :(得分:0)

.NET 3.5 SP1(即Visual Studio 2008 SP1)带来了许多性能增强功能,让JIT:er内联更有效。不幸的是,这些增强功能仅针对x86:

How are value types implemented in the 32-bit CLR? What has been done to improve their performance?

然而,在.NET 4.0中,我发现x64和x86现在可以为x64提供相同或更好的性能。

答案 2 :(得分:0)

我在发布模式下运行以下代码。我使用 Ctrl + F5 来运行代码。

Public Class Form1

    Function isPrime(ByVal NumToCheck As Integer) As Boolean
        Dim limit As Integer = CInt(Math.Ceiling(Math.Sqrt(CDbl(NumToCheck))))
        For i As Integer = 2 To limit
            If (NumToCheck Mod i = 0) Then
                Return False
            End If
        Next
        Return True
    End Function

    Dim watch As New Stopwatch
    Private Sub Button1_Click(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) Handles Button1.Click
        watch.Reset()
        watch.Start()

        Dim maxVal As Integer = 2000000
        Dim sumOfPrimes As Long = 0
        For i As Integer = 2 To maxVal
            If isPrime(i) Then
                sumOfPrimes += i
            End If
        Next
        watch.Stop()
        Label1.Text = watch.ElapsedMilliseconds.ToString
        Label2.Text = "The sum of all the prime numbers below " & maxVal & " is " & sumOfPrimes
    End Sub
End Class

AnyCPU每次都比x86快。我使用的是.NET 4.0。