Mac*_*ack 6 c# c++ benchmarking
当你处理繁重的计算时,当你需要使用原始CPU功率时,我担心C#的速度.
在计算方面,我一直认为C++比C#快得多.所以我做了一些快速测试.第一个测试计算素数<整数n,第二个测试计算一些pandigital数字.第二次测试的想法来自于:Pandigital Numbers
C#素数计算:
using System;
using System.Diagnostics;
class Program
{
    static int primes(int n)
    {
        uint i, j;
        int countprimes = 0;
        for (i = 1; i <= n; i++)
        {
            bool isprime = true;
            for (j = 2; j <= Math.Sqrt(i); j++)
                if ((i % j) == 0)
                {
                    isprime = false;
                    break;
                }
            if (isprime) countprimes++;
        }
        return countprimes;
    }
    static void Main(string[] args)
    {
        int n = int.Parse(Console.ReadLine());
        Stopwatch sw = new Stopwatch();
        sw.Start();
        int res = primes(n);
        sw.Stop();
        Console.WriteLine("I found {0} prime numbers between 0 and {1} in {2} msecs.", res, n, sw.ElapsedMilliseconds);
        Console.ReadKey();
    }
}
C++变体:
#include <iostream>
#include <ctime>
#include <cmath>
int primes(unsigned long n) {
unsigned long i, j;
int countprimes = 0;
  for(i = 1; i <= n; i++) {
      int isprime = 1;
      for(j = 2; j < sqrt((float)i); j++) 
          if(!(i%j)) {
        isprime = 0;
        break;
   }
    countprimes+= isprime;
  }
  return countprimes;
}
int main() {
 int n, res;
 cin>>n;
 unsigned int start = clock();
 res = primes(n);
 int tprime = clock() - start;
 cout<<"\nI found "<<res<<" prime numbers between 1 and "<<n<<" in "<<tprime<<" msecs.";
 return 0;
}
当我试图找到小于100,000的素数时,C#变体在0.409秒内完成,C++变体在0.614秒内完成.当我运行它们为1,000,000 C#时完成6.039秒而C++运行时间约为12.987秒.
C#中的Pandigital测试:
using System;
using System.Diagnostics;
class Program
{
    static bool IsPandigital(int n)
    {
        int digits = 0; int count = 0; int tmp;
        for (; n > 0; n /= 10, ++count)
        {
            if ((tmp = digits) == (digits |= 1 << (n - ((n / 10) * 10) - 1)))
                return false;
        }
        return digits == (1 << count) - 1;
    }
    static void Main()
    {
        int pans = 0;
        Stopwatch sw = new Stopwatch();
        sw.Start();
        for (int i = 1; i <= 123456789; i++)
        {
            if (IsPandigital(i))
            {
                pans++;
            }
        }
        sw.Stop();
        Console.WriteLine("{0}pcs, {1}ms", pans, sw.ElapsedMilliseconds);
        Console.ReadKey();
    }
}
C++中的Pandigital测试:
#include <iostream>
#include <ctime>
using namespace std;
int IsPandigital(int n)
    {
        int digits = 0; int count = 0; int tmp;
        for (; n > 0; n /= 10, ++count)
        {
            if ((tmp = digits) == (digits |= 1 << (n - ((n / 10) * 10) - 1)))
                return 0;
        }
        return digits == (1 << count) - 1;
    }
int main() {
   int pans = 0;
   unsigned int start = clock();
   for (int i = 1; i <= 123456789; i++)
   {
      if (IsPandigital(i))
      {
        pans++;
      }
   }
   int ptime = clock() - start;
   cout<<"\nPans:"<<pans<<" time:"<<ptime;  
   return 0;
}
C#variant在29.906秒内运行,C++在大约36.298秒内运行.
我没有触及任何编译器开关,并且C#和C++程序都是使用调试选项编译的.在我尝试运行测试之前,我担心C#会远远落后于C++,但现在似乎C#的优势速度差异很大.
任何人都能解释一下吗?C#是jitted而C++是原生编译的,因此C++比C#变体更快是正常的.
谢谢你的回答!
我已经重新配置了Release配置的所有测试.
第一次测试(素数)
C#(数字<100,0000):0.189秒C++(数字<100,0000):0.036秒
C#(数字<1,000,000):5.300秒C++(数字<1,000,000):1.166秒
第二次测试(pandigital数字):
C#:21.224秒C++:4.104秒
所以,每一件事都发生了变化,现在C++的速度要快得多.我的错误是我已经运行了Debug配置测试.如果我通过ngen运行C#可执行文件,我能看到一些速度提升吗?
我试图比较C#和C++的原因是因为我知道两者的一些基础知识,我想学习一个处理GUI的API.我认为WPF很好,所以考虑到我的目标是桌面,我想看看C#在使用纯粹的CPU能力来计算各种计算(文件存档,加密,编解码器等)时是否可以提供足够的速度和性能.但遗憾的是,C#在速度方面无法与C++保持同步.
所以,我假设我将永远坚持这个问题关于WPF,Win32,MFC的艰难问题,我会更新找到合适的API.
sis*_*sis 11
C++中的素数生成器不正确
i ^(1/2)== i xor 0
^是按位xor运算符,/是整数除法.
第一次编辑,它是正确但无效的:因为我xor = = i,筛子不会停在sqrt(i)但是在i.
第二次编辑:
筛分可以更有效地完成.(您只需要计算sqrt(n)).这就是我为自己使用实现Eratosthenes筛选的方法(虽然这是在C99中):
void sieve(const int n, unsigned char* primes)
{
        memset(primes, 1, (n+1) * sizeof(unsigned char));
        // sieve of eratosthenes
        primes[0] = primes[1] = 0;
        int m = floor(sqrt(n));
        for (int i = 2; i <= m; i++)
                if (primes[i]) // no need to remove multiples of i if it is not prime
                        for (int j = i; j <= (n/i); j++)
                                primes[i*j] = 0;
}
为什么你会认为jitted代码比本机代码慢?唯一的速度惩罚是实际的点击,只发生一次(一般来说).鉴于一个运行时间为30秒的程序,我们讨论的是总成本的一小部分.
我认为你可能会将jitted代码与解释代码混淆,后者是逐行编译的.这两者之间存在非常显着的差异.
正如其他人指出的那样,你还需要在发布模式下运行它; 调试模式会关闭大多数优化,因此两个版本都会比它们应该更慢(但是数量不同).
编辑 - 我应该指出另一件事,就是这一行:
for (j = 2; j <= Math.Sqrt(i); j++)
效率极低,可能会干扰基准测试.你应该在内循环Math.Sqrt(i) 之外进行计算.这可能会使两个版本的速度减慢相等,但我不确定,不同的编译器会执行不同的优化.
它花了这么长时间,因为算法是错误的.
for(j = 2; j < (i^(1/2)); j++) 
是相同的
for(j = 2; j < (i^0); j++) 
是相同的
for(j = 2; j < i; j++) 
我比sqrt(i)大很多.看一下运行时间,它应该比C++实现中的要大一个数量级.
此外,像其他人一样,我认为在调试模式下进行性能测试是不合理的.